local v=5 local N=10 local u=Random.new()local j=not IsServer and Players.LocalPlayer local a={}a.__index=a setmetatable(a,BaseWeapon)a.CanAimDownSights=true a.CanBeFired=true a.CanBeReloaded=true a.CanHit=true function a.new(v,N)local u=BaseWeapon.new(v,N)setmetatable(u,a)u.usesCharging=false u.charge=0 u.chargeSoundPitchMin=.5 u.chargeSoundPitchMax=1 u.triggerDisconnected=false u.startupFinished=false u.burstFiring=false u.burstIdx=0 u.nextFireTime=0 u.recoilIntensity=0 u.aimPoint=Vector3.new()u:addOptionalDescendant("\116\105\112\065\116\116\097\099\104","\084\105\112\065\116\116\097\099\104\109\101\110\116")u:addOptionalDescendant("\098\111\108\116\077\111\116\111\114","\066\111\108\116\077\111\116\111\114")u:addOptionalDescendant("\098\111\108\116\077\111\116\111\114\083\116\097\114\116","\066\111\108\116\077\111\116\111\114\083\116\097\114\116")u:addOptionalDescendant("\098\111\108\116\077\111\116\111\114\084\097\114\103\101\116","\066\111\108\116\077\111\116\111\114\084\097\114\103\101\116")u:addOptionalDescendant("\099\104\097\114\103\101\071\108\111\119\080\097\114\116","\067\104\097\114\103\101\071\108\111\119")u:addOptionalDescendant("\099\104\097\114\103\101\067\111\109\112\108\101\116\101\080\097\114\116\105\099\108\101\115","\067\104\097\114\103\101\067\111\109\112\108\101\116\101\080\097\114\116\105\099\108\101\115")u:addOptionalDescendant("\100\105\115\099\104\097\114\103\101\067\111\109\112\108\101\116\101\080\097\114\116\105\099\108\101\115","\068\105\115\099\104\097\114\103\101\067\111\109\112\108\101\116\101\080\097\114\116\105\099\108\101\115")u:addOptionalDescendant("\109\117\122\122\108\101\070\108\097\115\104\048","\077\117\122\122\108\101\070\108\097\115\104\048")u:addOptionalDescendant("\109\117\122\122\108\101\070\108\097\115\104\049","\077\117\122\122\108\101\070\108\097\115\104\049")u:addOptionalDescendant("\109\117\122\122\108\101\070\108\097\115\104\066\101\097\109","\077\117\122\122\108\101\070\108\097\115\104")u.hitMarkTemplate=HitMarksFolder:FindFirstChild(u:getConfigValue("\072\105\116\077\097\114\107\069\102\102\101\099\116","\066\117\108\108\101\116\072\111\108\101"))u.casingTemplate=CasingsFolder:FindFirstChild(u:getConfigValue("\067\097\115\105\110\103\069\102\102\101\099\116",""))u:addOptionalDescendant("\099\097\115\105\110\103\069\106\101\099\116\080\111\105\110\116","\067\097\115\105\110\103\069\106\101\099\116\080\111\105\110\116")u.ignoreList={}u.ignoreListRefreshTime=0 u:addOptionalDescendant("\104\097\110\100\065\116\116\097\099\104","\076\101\102\116\072\097\110\100\065\116\116\097\099\104\109\101\110\116")u.handAlignPos=nil u.handAlignRot=nil u.chargingParticles={}u.instance.DescendantAdded:Connect(function(v)if v.Name=="\067\104\097\114\103\105\110\103\080\097\114\116\105\099\108\101\115"and v:IsA("\080\097\114\116\105\099\108\101\069\109\105\116\116\101\114")then table.insert(u.chargingParticles,v)end end)for v,N in pairs(u.instance:GetDescendants())do if N.Name=="\067\104\097\114\103\105\110\103\080\097\114\116\105\099\108\101\115"and N:IsA("\080\097\114\116\105\099\108\101\069\109\105\116\116\101\114")then table.insert(u.chargingParticles,N)end end u:doInitialSetup()return u end function a.onEquippedChanged(v)BaseWeapon.onEquippedChanged(v)if not IsServer then if v.weaponsSystem.camera then if v.equipped then v.startupFinished=false end end if v.equipped then ContextActionService:BindAction("\082\101\108\111\097\100\087\101\097\112\111\110",function(...)v:onReloadAction(...)end,false,Enum.KeyCode.R,Enum.KeyCode.ButtonX)else ContextActionService:UnbindAction("\082\101\108\111\097\100\087\101\097\112\111\110")local N=v:getSound("\067\104\097\114\103\105\110\103")local u=v:getSound("\068\105\115\099\104\097\114\103\105\110\103")if N and N.Playing then N:Stop()end if u and u.Playing then u:Stop()end end v.triggerDisconnected=false end end function a.onReloadAction(j,v,N,u)if N==Enum.UserInputState.Begin and not j.reloading then j:reload()end end function a.animateBoltAction(N,v)if not N.boltMotor or not N.boltMotorStart or not N.boltMotorTarget then return end if v then N:tryPlaySound("\066\111\108\116\079\112\101\110\083\111\117\110\100")else N:tryPlaySound("\066\111\108\116\067\108\111\115\101\083\111\117\110\100")end local u=v and N:getConfigValue("\065\099\116\105\111\110\079\112\101\110\084\105\109\101",.025)or N:getConfigValue("\065\099\116\105\111\110\067\108\111\115\101\084\105\109\101",.075)local j=v and N.boltMotorTarget.CFrame or N.boltMotorStart.CFrame local a=TweenService:Create(N.boltMotor,TweenInfo.new(u,Enum.EasingStyle.Quad,Enum.EasingDirection.InOut),{C0=j})a:Play()a.Completed:Wait()end function a.getRandomSeedForId(N,v)return v end
--The ignore list will fill up over time. This is how many seconds it will go before
--being refreshed in order to keep it from filling up with instances that aren't in
--the datamodel anymore.
local IGNORE_LIST_LIFETIME = 5

local MAX_BULLET_TIME = 10

local localRandom = Random.new()
local localPlayer = not IsServer and Players.LocalPlayer

local BulletWeapon = {}
BulletWeapon.__index = BulletWeapon
setmetatable(BulletWeapon, BaseWeapon)

BulletWeapon.CanAimDownSights = true
BulletWeapon.CanBeFired = true
BulletWeapon.CanBeReloaded = true
BulletWeapon.CanHit = true

function BulletWeapon.new(weaponsSystem, instance)
	local self = BaseWeapon.new(weaponsSystem, instance)
	setmetatable(self, BulletWeapon)

	self.usesCharging = false
	self.charge = 0
	self.chargeSoundPitchMin = 0.5
	self.chargeSoundPitchMax = 1

	self.triggerDisconnected = false
	self.startupFinished = false -- TODO: make startup time use a configuration value
	self.burstFiring = false
	self.burstIdx = 0
	self.nextFireTime = 0

	self.recoilIntensity = 0
	self.aimPoint = Vector3.new()

	self:addOptionalDescendant("tipAttach", "TipAttachment")

	self:addOptionalDescendant("boltMotor", "BoltMotor")
	self:addOptionalDescendant("boltMotorStart", "BoltMotorStart")
	self:addOptionalDescendant("boltMotorTarget", "BoltMotorTarget")

	self:addOptionalDescendant("chargeGlowPart", "ChargeGlow")
	self:addOptionalDescendant("chargeCompleteParticles", "ChargeCompleteParticles")
	self:addOptionalDescendant("dischargeCompleteParticles", "DischargeCompleteParticles")

	self:addOptionalDescendant("muzzleFlash0", "MuzzleFlash0")
	self:addOptionalDescendant("muzzleFlash1", "MuzzleFlash1")
	self:addOptionalDescendant("muzzleFlashBeam", "MuzzleFlash")

	self.hitMarkTemplate = HitMarksFolder:FindFirstChild(self:getConfigValue("HitMarkEffect", "BulletHole"))

	self.casingTemplate = CasingsFolder:FindFirstChild(self:getConfigValue("CasingEffect", ""))
	self:addOptionalDescendant("casingEjectPoint", "CasingEjectPoint")

	self.ignoreList = {}
	self.ignoreListRefreshTime = 0

	self:addOptionalDescendant("handAttach", "LeftHandAttachment")
	self.handAlignPos = nil
	self.handAlignRot = nil

	self.chargingParticles = {}
	self.instance.DescendantAdded:Connect(function(descendant)
		if descendant.Name == "ChargingParticles" and descendant:IsA("ParticleEmitter") then
			table.insert(self.chargingParticles, descendant)
		end
	end)
	for _, v in pairs(self.instance:GetDescendants()) do
		if v.Name == "ChargingParticles" and v:IsA("ParticleEmitter") then
			table.insert(self.chargingParticles, v)
		end
	end

	self:doInitialSetup()

	return self
end

function BulletWeapon:onEquippedChanged()
	BaseWeapon.onEquippedChanged(self)

	if not IsServer then
		if self.weaponsSystem.camera then
			if self.equipped then
				self.startupFinished = false
			end
		end

		if self.equipped then
			ContextActionService:BindAction("ReloadWeapon", function(...)
				self:onReloadAction(...)
			end, false, Enum.KeyCode.R, Enum.KeyCode.ButtonX)
		else
			ContextActionService:UnbindAction("ReloadWeapon")

			-- Stop charging/discharging sounds
			local chargingSound = self:getSound("Charging")
			local dischargingSound = self:getSound("Discharging")
			if chargingSound and chargingSound.Playing then
				chargingSound:Stop()
			end
			if dischargingSound and dischargingSound.Playing then
				dischargingSound:Stop()
			end
		end

		self.triggerDisconnected = false
	end
end

function BulletWeapon:onReloadAction(actionName, inputState, inputObj)
	if inputState == Enum.UserInputState.Begin and not self.reloading then
		self:reload()
	end
end

function BulletWeapon:animateBoltAction(isOpen)
	if not self.boltMotor or not self.boltMotorStart or not self.boltMotorTarget then
		return
	end

	if isOpen then
		self:tryPlaySound("BoltOpenSound")
	else
		self:tryPlaySound("BoltCloseSound")
	end

	local actionMoveTime = isOpen and self:getConfigValue("ActionOpenTime", 0.025)
		or self:getConfigValue("ActionCloseTime", 0.075)
	local targetCFrame = isOpen and self.boltMotorTarget.CFrame or self.boltMotorStart.CFrame

	local boltTween = TweenService:Create(
		self.boltMotor,
		TweenInfo.new(actionMoveTime, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut),
		{ C0 = targetCFrame }
	)
	boltTween:Play()
	boltTween.Completed:Wait()
end

function BulletWeapon:getRandomSeedForId(id)
	return id
end
