-- Creates "bullet". No projectile motion is actually used. Pistol raytraces to target and creates
-- a tracer trail to the target. Fading trail gives illusion of motion.

local function createBullet(target)
	-- Get actual handle position. Want to offset from the center of the handle as the bullet comes
	-- from the barrel of the gun
	local handlePos = tool.Handle.CFrame + tool.Handle.CFrame:vectorToWorldSpace(Vector3.new(0,0,.3))
	local toTarget = handlePos:vectorToWorldSpace(Vector3.new(0,1,0)) * 200
	local torsoLook = (tool.Parent:FindFirstChild("Torso").CFrame.lookVector * Vector3.new(1,0,1)).unit
	local toTargetAngle = (toTarget * Vector3.new(1,0,1)).unit
	local angle = math.acos(torsoLook:Dot(toTargetAngle))

	-- Checks angle from where the character is facing to the orientation of the pistol. If the angle
	-- is less than 90 degress then we shoot to where the mouse is pointing (helps accuracy). Otherwise
	-- the gun is assumed at the edge of its rotation and just shoots straight.
	if math.deg(angle) < 90 then
		toTarget = target - tool.Handle.Position
		if toTarget.magnitude > range then
			toTarget = toTarget.unit * range
		end
		toTarget = toTarget * 1.1
	end
	
	-- Shoot ray and check if humanoid was hit. If so, it should take damage
	local ray = Ray.new(handlePos.p, toTarget)
	local part, position = game.Workspace:FindPartOnRay(ray, tool.Parent)
	if part and part.Parent and part.Parent:FindFirstChild("Humanoid") then
		part.Parent:FindFirstChild("Humanoid"):TakeDamage(damage)
	end	

	if position then
		toTarget = position - handlePos.p
	end
	
	-- Create tracer trail. Trail is made of thin parts 2 studs long. Fades each segment
	-- starting with closest tracer to the tool.
	local bulletTrail = Instance.new("Model", game.Workspace)
	local trailTable = {}
	-- Fetch decal from server storage
	local decal = game.ServerStorage.ROBLOX_PistolTracerDecal
	for i = 0, toTarget.magnitude/2, 1 do
		local trailSegment = Instance.new("Part", bulletTrail)
		trailSegment.CanCollide = false
		trailSegment.Anchored = true
		trailSegment.FormFactor = Enum.FormFactor.Custom
		trailSegment.Size = Vector3.new(.1,.1,2)
		trailSegment.BrickColor = BrickColor.White()
		trailSegment.CFrame = CFrame.new(handlePos.p + (toTarget.unit * 2 * (i + .5)), handlePos.p)
		trailSegment.Transparency = 1
		
		-- Add point light to tracer for a little illumination
		local light = Instance.new("PointLight", trailSegment)	
		light.Range = 3
		
		-- Add decal to faces of the part
		local function addDecal(face)
			local decalClone = decal:Clone()
			decalClone.Parent = trailSegment
			decalClone.Face = face
		end		
		
		addDecal(Enum.NormalId.Top)
		addDecal(Enum.NormalId.Bottom)
		addDecal(Enum.NormalId.Left)
		addDecal(Enum.NormalId.Right)
		
		-- Add segment to all of the tracers
		table.insert(trailTable, trailSegment)
	end
	
	-- Coroutine thread to fade each trail segment. Put in coroutine so it does not
	-- block the rest of the pistol's script
	local fadeThread = coroutine.create(function()
		local count = 1
		local ended = false
		-- Keep looping until end condition is met
		while not ended do
			-- Assume end condition is met. Easier to switch it off later if we need to
			-- keep looping
			ended = true
			-- Loop through every part in the trail
			for index, part in pairs(trailTable) do
				if index <= count then
					local shouldDestroy = false
					for _, face in pairs(part:GetChildren()) do
						
						if face:IsA("Decal") then
							-- Increase decal transparencies and use this to determine if
							-- segment has completely faded
							face.Transparency = face.Transparency + .05
							if face.Transparency < 1 then
								ended = false
							else
								shouldDestroy = true
							end
						else
							-- Dim the point light
							face.Brightness = face.Brightness - .1
						end
					end			
					-- If segment is completely faded then clean it up
					if shouldDestroy then
						table.remove(trailTable, index)
						part:Destroy()
					end		
				end
			end
			count = count + 1
			wait()
		end
		bulletTrail:Destroy()
	end)	
	coroutine.resume(fadeThread)	
end
