local GUN = GUN_Troops
--#=================================================#
--Thinker for most of the GUN effect objects, since this is much easier than making five billion states and custom objects.
--#=================================================#

--GFX object when you need capechase, autoframing, gradual fading, offsets, etc.
addHook("MobjThinker", function(s)
	if not s.valid return end
	--Apply autoframe behaviour? Basically an adjustable FF_ANIMATE that can loop within the same sprite.
	if s.sttspeed
		if s.sttspeed == 1 or (leveltime % (s.sttspeed) == 0) --Animation speed. If sttspeed is 2, we'd advance frames every 2 tics.
			if (s.frame & FF_FRAMEMASK) == s.sttfinalframe --Never go past this frame!
				if s.sttfirstframe != nil --Unless we want it to loop?
					s.frame = ($ & ~FF_FRAMEMASK)|s.sttfirstframe
				end
			else		
				--If you don't specify a frameloop, make sure you don't exceed the amount of available frames!
				if s.sttlastframe != nil and ((s.frame & FF_FRAMEMASK) >= s.sttlastframe) 
					s.frame = ($ & ~FF_FRAMEMASK)|(s.sttfirstframe or 0)
				else
					s.frame = $+1
				end
			end
		end
	end
	
	--Fade if sttfade exists.
	if s.sttfade
		local FADE = (s.sttfade == true) and 10 or s.sttfade
		if (s.fuse > FADE)
			FADE = nil
		elseif (FADE != 10) and (leveltime % 2)
			FADE = nil --Fade slower if it's not 10...
		end
		if FADE --Fade confirmed. Go!
			local trans = (s.frame & FF_TRANSMASK)
			s.frame = ($ & ~FF_TRANSMASK)|min(FF_TRANS90, (trans+FRACUNIT))
			if s.sttroll --Slow rollspeed too.
				s.sttroll = FixedDiv(FixedMul(s.sttroll, 20),21)
			end
		end
		--Automatically roll at any given speed?
		if s.sttroll
			if (s.renderflags & RF_FLOORSPRITE)
				s.angle =  $+s.sttroll
			else
				s.sttrollangle = s.sttrollangle and $+s.sttroll or s.sttroll
				s.rollangle = s.sttrollangle
			end
		end	
	end
	
	--Scroll graphic?
	if s.sttXspeed
		s.spritexoffset = $+s.sttXspeed	
	end
	if s.sttYspeed
		if s.floorspriteslope --Raise the tilt of slopesprites instead!
			local EX,EY,EZ = s.floorspriteslope.o.x, s.floorspriteslope.o.y, s.floorspriteslope.o.z
			s.floorspriteslope.o = {x = EX, y = EY, z = EZ+s.sttYspeed}
		else
			s.spriteyoffset = $+s.sttYspeed
		end
	end

	if not (s.tracer and s.tracer.valid) return end --Will need a tracer from here on!	
	local t = s.tracer
	
	--Apply capechase and potentially also offsets if given a tracer!
	if (s.renderflags & RF_FLOORSPRITE) 
		P_SetOrigin(s, t.x, t.y, t.z) --No capechase for floorsprites! I don't want the object's angle to change!
	else
		local PREVANGLE = s.angle
		A_CapeChase(s, 1, 0) 
		if not s.valid return end --Capechase removes the object sometimes, so always check s.valid afterwards!

		if s.ditchtracer --Ditch the capechase after any couple of frames?
			s.ditchtracer = $-1 --This is a number value, NOT true or false!
			if s.ditchtracer == 0
				if s.GSoffsetangFACE != nil --Face target one last time! 
					local EXT = (tonumber(s.GSoffsetangFACE)) or s.angle
					P_MoveOrigin(s, s.x+FixedMul(s.GSoffsetX, cos(s.GSoffsetang+EXT)), s.y+FixedMul(s.GSoffsetY, sin(s.GSoffsetang+EXT)), s.z)
					s.angle = R_PointToAngle2(s.x, s.y, t.x, t.y) + ((s.renderflags & RF_PAPERSPRITE) and ANGLE_90 or 0)
				else
					s.angle = PREVANGLE --Undo capechase's angle copying.
				end 
				s.tracer = nil return --Done!
			end
		end
	end	
	
	--If you set one offset, then set them all, even if they're just 0.
	if s.GSoffsetX != nil
		local ANGLE = (s.GSoffsetang != nil) and s.GSoffsetang or t.angle --Force a specific angle, or use the tracer's angle?
		
		s.GSoffsetwait = (s.GSoffsetwait) and 1 or 2
		
		P_MoveOrigin(s,
		s.x+ FixedMul(s.GSoffsetX/s.GSoffsetwait, cos(ANGLE)),
		s.y+ FixedMul(s.GSoffsetY/s.GSoffsetwait, sin(ANGLE)),
		s.z+ (s.GSoffsetZ or 0)*P_MobjFlip(t) )
		
		--Adjust offsets overtime? 110 would INCREASE distance by 10% each frame, 80 would DECREASE distance by 20%.
		if s.GSshiftoffsetXY and (s.GSoffsetX or s.GSoffsetY)
			s.GSoffsetX = FixedDiv(FixedMul($, s.GSshiftoffsetXY), 100)
			s.GSoffsetY = FixedDiv(FixedMul($, s.GSshiftoffsetXY), 100)
		end
		if s.GSshiftoffsetZ and s.GSoffsetZ
			s.GSoffsetZ = FixedDiv(FixedMul($, s.GSshiftoffsetZ), 100)
		end
		
		--Face tracer all the time? If set to "false" or "0", the obejct will face it's tracer without adjusting offsets!
		if s.GSoffsetangFACE != nil 
			s.angle = t.angle + ((s.renderflags & RF_PAPERSPRITE) and ANGLE_90 or 0)
			if s.GSoffsetangFACE --Rotate around tracer at this speed?
				s.GSoffsetang = $+s.GSoffsetangFACE
			end return --Don't need to do further papersprite checks.
		end
	end
	--Properly angle papersprites with tracers.
	if (s.renderflags & RF_PAPERSPRITE)
		local EXTRA = (s.GSpaperang) or 0
		s.angle = t.angle+ANGLE_90+EXTRA
	end	
end, MT_GUNAUTOFRAME)

--An over/underlay object that can copy the tracer's frame, then disappears.
GUN.OverLayThink = function(s)
	if not s.valid return end
	if not (s.tracer and s.tracer.valid) s.state = S_NULL return end --
	local t = s.tracer

	A_CapeChase(s,1,0) if not s.valid return end if t.player s.angle = t.player.drawangle end --Use drawangle for players!	
		
		if (t.flags2 & MF2_DONTDRAW)
			s.flags2 = $|MF2_DONTDRAW return --No need to continue if we're not rendered anyway.
		else
			s.flags2 = $ & ~MF2_DONTDRAW
		end	
		s.spriteyscale = t.spriteyscale
		s.spritexscale = t.spritexscale
		s.spriteyoffset = t.spriteyoffset
		s.spritexoffset = t.spritexoffset
		s.rollangle = t.rollangle	
		
		--Copy target's frame?
		if s.copyframe
			s.sprite = t.sprite
			if t.player
				s.skin = t.skin
				s.sprite2 = t.sprite2
			end
			s.frame = ($ & ~FF_FRAMEMASK)|(t.frame & FF_FRAMEMASK)
			
			--Mimmick flip flags too!
			if (t.frame & FF_HORIZONTALFLIP)
				s.frame = $|FF_HORIZONTALFLIP
			else
				s.frame = $ & ~FF_HORIZONTALFLIP
			end
			if (t.frame & FF_VERTICALFLIP)
				s.frame = $|FF_VERTICALFLIP
			else
				s.frame = $ & ~FF_VERTICALFLIP
			end
		end
		if s.fusefade and (s.fuse <= s.fusefade) --Assumes you have a fuse to fade!
			local TRANS = (FF_TRANS90 - s.fuse*FF_TRANS10)
			if ((s.frame & FF_TRANSMASK) < TRANS)
				s.frame = ($ & ~FF_TRANSMASK)| min(FF_TRANS90, TRANS)
			end
		end
end
addHook("MobjThinker", function(s)
	GUN.OverLayThink(s)
end, MT_GUNOVERLAY)
