function BulletWeapon.simulateFire(k,F,x)BaseWeapon.simulateFire(k,x)if k.lastFireSound then k.lastFireSound:Stop()end k.lastFireSound=k:tryPlaySound("\070\105\114\101\100",k:getConfigValue("\070\105\114\101\100\080\108\097\121\098\097\099\107\083\112\101\101\100\082\097\110\103\101",.1))local A=k:getConfigValue("\078\117\109\080\114\111\106\101\099\116\105\108\101\115",1)local R=Random.new(k:getRandomSeedForId(x.id))for A=1,A,1 do k:simulateProjectile(F,x,A,R)end local v=k:getConfigValue("\065\099\116\105\111\110\079\112\101\110\084\105\109\101",.025)if k.boltMotor then(coroutine.wrap(function()k:animateBoltAction(true)wait(v)k:animateBoltAction(false)end))()end if not NO_BULLET_CASINGS and(k.casingTemplate and k.casingEjectPoint)then local F=k.casingTemplate:Clone()F.Anchored=false F.Archivable=false F.CFrame=k.casingEjectPoint.WorldCFrame F.Velocity=k.casingEjectPoint.Parent.Velocity+k.casingEjectPoint.WorldAxis*localRandom:NextNumber(k:getConfigValue("\067\097\115\105\110\103\069\106\101\099\116\083\112\101\101\100\077\105\110",15),k:getConfigValue("\067\097\115\105\110\103\069\106\101\099\116\083\112\101\101\100\077\097\120",18))F.Parent=workspace.CurrentCamera CollectionService:AddTag(F,"\087\101\097\112\111\110\115\083\121\115\116\101\109\073\103\110\111\114\101")local x=F:FindFirstChild("\067\097\115\105\110\103\072\105\116\083\111\117\110\100")if x then local A=nil A=F.Touched:Connect(function(F)if not F:IsDescendantOf(k.instance)then x:Play()A:Disconnect()A=nil end end)end Debris:AddItem(F,2)end if k.player==Players.LocalPlayer then(coroutine.wrap(function()local F=tick()local x=k:getConfigValue("\082\101\099\111\105\108\068\101\108\097\121\084\105\109\101",.07)while tick()<F+x do RunService.RenderStepped:Wait()end RunService.RenderStepped:Wait()local A,v=k:getConfigValue("\082\101\099\111\105\108\077\105\110",.05),k:getConfigValue("\082\101\099\111\105\108\077\097\120",.5)local m=R:NextNumber(A,v)local M=(math.sin(tick()*2)*m)*math.rad(.05)local q=m*.025 k.weaponsSystem.camera:addRecoil(Vector2.new(M,q))if not(k.weaponsSystem.camera:isZoomed()and k:getConfigValue("\072\097\115\083\099\111\112\101",false))then k.recoilIntensity=math.clamp(k.recoilIntensity*1+m/10,.005,1)end local B=k.weaponsSystem.gui if B then B:setCrosshairScale(1+m)end end))()end end function BulletWeapon.getIgnoreList(x,F)local k=tick()local A=x.ignoreList if not A or k-x.ignoreListRefreshTime>IGNORE_LIST_LIFETIME then A={x.instanceIsTool and x.instance.Parent or x.instance;workspace.CurrentCamera}if not RunService:IsServer()then if F and(Players.LocalPlayer and Players.LocalPlayer.Character)then table.insert(A,Players.LocalPlayer.Character)end end x.ignoreList=A end return A end

function BulletWeapon:simulateFire(firingPlayer, fireInfo)
	BaseWeapon.simulateFire(self, fireInfo)

	-- Play "Fired" sound
	if self.lastFireSound then
		self.lastFireSound:Stop()
	end
	self.lastFireSound = self:tryPlaySound("Fired", self:getConfigValue("FiredPlaybackSpeedRange", 0.1))

	-- Simulate each projectile/bullet fired from current weapon
	local numProjectiles = self:getConfigValue("NumProjectiles", 1)
	local randomGenerator = Random.new(self:getRandomSeedForId(fireInfo.id))
	for i = 1, numProjectiles do
		self:simulateProjectile(firingPlayer, fireInfo, i, randomGenerator)
	end

	-- Animate the bolt if the current gun has one
	local actionOpenTime = self:getConfigValue("ActionOpenTime", 0.025)
	if self.boltMotor then
		coroutine.wrap(function()
			self:animateBoltAction(true)
			wait(actionOpenTime)
			self:animateBoltAction(false)
		end)()
	end

	-- Eject bullet casings and play "CasingHitSound" (child of casing) sound if applicable for current weapon
	if not NO_BULLET_CASINGS and self.casingTemplate and self.casingEjectPoint then
		local casing = self.casingTemplate:Clone()
		casing.Anchored = false
		casing.Archivable = false
		casing.CFrame = self.casingEjectPoint.WorldCFrame
		casing.Velocity = self.casingEjectPoint.Parent.Velocity + (self.casingEjectPoint.WorldAxis * localRandom:NextNumber(self:getConfigValue("CasingEjectSpeedMin", 15), self:getConfigValue("CasingEjectSpeedMax", 18)))
		casing.Parent = workspace.CurrentCamera
		CollectionService:AddTag(casing, "WeaponsSystemIgnore")

		local casingHitSound = casing:FindFirstChild("CasingHitSound")
		if casingHitSound then
			local touchedConn = nil
			touchedConn = casing.Touched:Connect(function(hitPart)
				if not hitPart:IsDescendantOf(self.instance) then
					casingHitSound:Play()
					touchedConn:Disconnect()
					touchedConn = nil
				end
			end)
		end

		Debris:AddItem(casing, 2)
	end

	if self.player == Players.LocalPlayer then
		coroutine.wrap(function()
			-- Wait for "RecoilDelayTime" before adding recoil
			local startTime = tick()
			local recoilDelayTime = self:getConfigValue("RecoilDelayTime", 0.07)
			while tick() < startTime + recoilDelayTime do
				RunService.RenderStepped:Wait()
			end
			RunService.RenderStepped:Wait()

			-- Add recoil to camera
			local recoilMin, recoilMax = self:getConfigValue("RecoilMin", 0.05), self:getConfigValue("RecoilMax", 0.5)
			local intensityToAdd = randomGenerator:NextNumber(recoilMin, recoilMax)
			local xIntensity = math.sin(tick() * 2) * intensityToAdd * math.rad(0.05)
			local yIntensity = intensityToAdd * 0.025
			self.weaponsSystem.camera:addRecoil(Vector2.new(xIntensity, yIntensity))

			if not (self.weaponsSystem.camera:isZoomed() and self:getConfigValue("HasScope", false)) then
				self.recoilIntensity = math.clamp(self.recoilIntensity * 1 + (intensityToAdd / 10), 0.005, 1)
			end

			-- Make crosshair reflect recoil/spread amount
			local weaponsGui = self.weaponsSystem.gui
			if weaponsGui then
				weaponsGui:setCrosshairScale(1 + intensityToAdd)
			end
		end)()
	end
end

function BulletWeapon:getIgnoreList(includeLocalPlayer)
	local now = tick()
	local ignoreList = self.ignoreList
	if not ignoreList or now - self.ignoreListRefreshTime > IGNORE_LIST_LIFETIME then
		ignoreList = {
			self.instanceIsTool and self.instance.Parent or self.instance,
			workspace.CurrentCamera
		}
		if not RunService:IsServer() then
			if includeLocalPlayer and Players.LocalPlayer and Players.LocalPlayer.Character then
				table.insert(ignoreList, Players.LocalPlayer.Character)
			end
		end
		self.ignoreList = ignoreList
	end
	return ignoreList
end
