Part's CFrame remains the same as when loop started, but should've changed

I’m currently trying to create the firing portion of an FPS system, e.g. muzzle flash/projectiles. What I want is the muzzle flash VFX and tracer to originate from a part called Flame (which is welded to the gun) for every shot. Everything works when the gun is on semi-automatic mode, however when switching to fully automatic (which uses a while loop) the muzzle flash VFX and tracer’s origin remain the same as when the loop began. I’ve tried using task.spawn to start the loop in a new thread to no avail (but I’ll remain using task.spawn as without it it delays the next shot because of the lag to create a new projectile). I’ve also tried extracting the origin’s CFrame to a function which didn’t work. I’ve tried to search for this issue on Dev Forums but couldn’t find anything on it because it’s kind of hard to explain.
Here is my intended result.
Here is what I’m getting.

Here’s my code (it’s compiled from TypeScript, that’s why variable naming is odd):

CreateFireFX = function(self, suppressed)
	if suppressed == nil then
		suppressed = false
	end
	if not controllers.VM.On then
		return nil
	end
	if not currentGun or not data then
		return nil
	end
	if self.Ammo.Mag == 0 then
		return nil
	end
	task.spawn(function()
		return self:CreateTracer()
	end)
	if not suppressed then
		self:CreateFlashVFX()
		currentGun.Trigger.Fire:Play()
	end
	self:CalculateRecoil()
	self.Ammo.Mag -= 1
	self:UpdateUI()
end,
FullAuto = function(self, suppressed)
	if suppressed == nil then
		suppressed = false
	end
	if not currentGun or not data then
		return nil
	end
	if self.Ammo.Mag == 0 then
		return nil
	end
	while state.M1Down do
		self:CreateFireFX(suppressed)
		task.wait(60 / data.firerate)
	end
	state.Firing = false
end,
Fire = function(self, suppressed)
	if suppressed == nil then
		suppressed = false
	end
	if not controllers.VM.On then
		return nil
	end
	if not currentGun or not data then
		return nil
	end
	if self.Ammo.Mag == 0 then
		return nil
	end
	if state.Firing then
		return nil
	end
	state.Firing = true
	local _exp = self:GetFiremode()
	repeat
		if _exp == "auto" then
			task.spawn(function()
				return self:FullAuto()
			end)
			break
		end
		if _exp == "burst" then
			task.spawn(function()
				return self:Burst()
			end)
			break
		end
		if _exp == "semi" then
			self:CreateFireFX(suppressed)
			task.wait(60 / data.firerate)
			state.Firing = false
			break
		end
		error(Exception.new("Unhandled fire mode: " .. self:GetFiremode()))
	until true
end,

I’m sure this is quite the simple issue to fix and I’m just overthinking it but I’d like to save the headache because I’ve been working on this specific issue for like an hour lol

We need your script to be able to help…

very sorry, not even thinking. edited.

i also didn’t know if typescript source was acceptable, let me know if that’s preferred.

still having this issue and still need help :frowning: