Need help with custom StarterCharacters guns not working

so im using a gun kit that i forget the name of The guns work on my normal character and the other StarterCharacter you see in the back ground but this one does not aim or shoot none of the other guns in the kit work either i currently need to get the gun in the hand and for it to shoot

here is the other StarterCharacter that works

show us the output and the gun code

1 Like

for sure

alright so the output just spams this error when the gun is selected

i think it might be from deleting the camera script and i cant find the model so i cant replace it

there is a script in replicatedStorage called base weapon

this is is

local RunService = game:GetService("RunService")
local Players = game:GetService("Players")

local IsServer = RunService:IsServer()

local WeaponsSystemFolder = script.Parent.Parent
local AnimationsFolder = WeaponsSystemFolder:WaitForChild("Assets"):WaitForChild("Animations")

local localRandom = Random.new()

local BaseWeapon = {}
BaseWeapon.__index = BaseWeapon

BaseWeapon.CanAimDownSights = false
BaseWeapon.CanBeReloaded = false
BaseWeapon.CanBeFired = false
BaseWeapon.CanHit = false

function BaseWeapon.new(weaponsSystem, instance)
	assert(instance, "BaseWeapon.new() requires a valid Instance to be attached to.")

	local self = setmetatable({}, BaseWeapon)
	self.connections = {}
	self.descendants = {}
	self.descendantsRegistered = false
	self.optionalDescendantNames = {}
	self.weaponsSystem = weaponsSystem
	self.instance = instance
	self.animController = nil
	self.player = nil
	self.enabled = false
	self.equipped = false
	self.activated = false
	self.nextShotId = 1
	self.activeRenderStepName = nil
	self.curReloadSound = nil

	self.animTracks = {}
	self.sounds = {}
	self.configValues = {}
	self.trackedConfigurations = {}

	self.ammoInWeaponValue = nil

	self.reloading = false
	self.canReload = true

	self:registerDescendants()
	self.connections.descendantAdded = self.instance.DescendantAdded:Connect(function(descendant)
		self:onDescendantAdded(descendant)
	end)

	return self
end

function BaseWeapon:doInitialSetup()
	local selfClass = getmetatable(self)
	self.instanceIsTool = self.instance:IsA("Tool")

	-- Set up child added/removed
	self.connections.childAdded = self.instance.ChildAdded:Connect(function(child)
		self:onChildAdded(child)
	end)
	self.connections.childRemoved = self.instance.ChildRemoved:Connect(function(child)
		self:onChildRemoved(child)
	end)
	for _, child in pairs(self.instance:GetChildren()) do
		self:onChildAdded(child)
	end

	-- Initialize self.ammoInWeaponValue
	if selfClass.CanBeReloaded then
		if IsServer then
			self.ammoInWeaponValue = self.instance:FindFirstChild("CurrentAmmo")
			if not self.ammoInWeaponValue then
				self.ammoInWeaponValue = Instance.new("IntValue")
				self.ammoInWeaponValue.Name = "CurrentAmmo"
				self.ammoInWeaponValue.Value = 0
				self.ammoInWeaponValue.Parent = self.instance
			end
			self.ammoInWeaponValue.Value = self:getConfigValue("AmmoCapacity", 30)
		else
			self.ammoInWeaponValue = self.instance:WaitForChild("CurrentAmmo")
		end
	end

	self.connections.ancestryChanged = self.instance.AncestryChanged:Connect(function() self:onAncestryChanged() end)
	self:onAncestryChanged()

	-- Set up equipped/unequipped and activated/deactivated
	if self.instanceIsTool then
		self.connections.equipped = self.instance.Equipped:Connect(function()
			if IsServer or (Players.LocalPlayer and (self.instance:IsDescendantOf(Players.LocalPlayer.Backpack) or self.instance:IsDescendantOf(Players.LocalPlayer.Character))) then
				self:setEquipped(true)
				if self:getAmmoInWeapon() <= 0 then
					-- Have to wait a frame, otherwise the reload animation will not play
					coroutine.wrap(function()
						task.wait()
						self:reload()
					end)()
				end
			end
		end)
		self.connections.unequipped = self.instance.Unequipped:Connect(function()
			if IsServer or (Players.LocalPlayer and (self.instance:IsDescendantOf(Players.LocalPlayer.Backpack) or self.instance:IsDescendantOf(Players.LocalPlayer.Character))) then
				self:setEquipped(false)
				if self.reloading then
					self:cancelReload()
				end
			end
		end)
		if self.instance:IsDescendantOf(workspace) and self.player then
			self:setEquipped(true)
		end

		self.connections.activated = self.instance.Activated:Connect(function()
			self:setActivated(true)
		end)
		self.connections.deactivated = self.instance.Deactivated:Connect(function()
			self:setActivated(false)
		end)

		-- Weld handle to weapon primary part
		if IsServer then
			self.handle = self.instance:FindFirstChild("Handle")

			local model = self.instance:FindFirstChildOfClass("Model")
			local handleAttachment = model:FindFirstChild("HandleAttachment", true)

			if self.handle and handleAttachment then
				local handleOffset = model.PrimaryPart.CFrame:toObjectSpace(handleAttachment.WorldCFrame)

				local weld = Instance.new("Weld")
				weld.Name = "HandleWeld"
				weld.Part0 = self.handle
				weld.Part1 = model.PrimaryPart
				weld.C0 = CFrame.new()
				weld.C1 = handleOffset
				weld.Parent = self.handle

				self.handle.Anchored = false
				model.PrimaryPart.Anchored = false
			end
		end
	end
end

function BaseWeapon:registerDescendants()
	if not self.instance then
		error("No instance set yet!")
	end

	if self.descendantsRegistered then
		warn("Descendants already registered!")
		return
	end

	for _, descendant in ipairs(self.instance:GetDescendants()) do
		if self.descendants[descendant.Name] == nil then
			self.descendants[descendant.Name] = descendant
		else
			self.descendants[descendant.Name] = "Multiple"
		end
	end
	self.descendantsRegistered = true
end

function BaseWeapon:addOptionalDescendant(key, descendantName)
	if self.instance == nil then
		error("No instance set yet!")
	end

	if not self.descendantsRegistered then
		error("Descendants not registered!")
	end

	if self.descendants[descendantName] == "Multiple" then
		error("Weapon \""..self.instance.Name.."\" has multiple descendants named \""..descendantName.."\", so you cannot addOptionalDescendant with that descendant name.")
	end

	local found = self.descendants[descendantName]
	if found then
		self[key] = found
		return
	else
		self.optionalDescendantNames[descendantName] = key
	end
end

function BaseWeapon:onDescendantAdded(descendant)
	if self.descendants[descendant.Name] == nil then
		self.descendants[descendant.Name] = descendant
	else
		self.descendants[descendant.Name] = "Multiple"
	end

	local desiredKey = self.optionalDescendantNames[descendant.Name]
	if desiredKey then
		if self.descendants[descendant.Name] == "Multiple" then
			error("Weapon \""..self.instance.Name.."\" has multiple descendants named \""..descendant.Name.."\", so you cannot addOptionalDependency with that descendant name.")
		end
		self[desiredKey] = descendant
		self.optionalDescendantNames[descendant.Name] = nil
	end
end

function BaseWeapon:cleanupConnection(...)
	local args = { ... }
	for _, name in pairs(args) do
		if typeof(name) == "string" and self.connections[name] then
			self.connections[name]:Disconnect()
			self.connections[name] = nil
		end
	end
end

function BaseWeapon:onAncestryChanged()
	if self.instanceIsTool then
		local player = nil
		if self.instance:IsDescendantOf(Players) then
			local parentPlayer = self.instance.Parent.Parent
			if parentPlayer and parentPlayer:IsA("Player") then
				player = parentPlayer
			end
		elseif self.instance:IsDescendantOf(workspace) then
			local parentPlayer = Players:GetPlayerFromCharacter(self.instance.Parent)
			if parentPlayer and parentPlayer:IsA("Player") then
				player = parentPlayer
			end
		end

		self:setPlayer(player)
	end
end

function BaseWeapon:setPlayer(player)
	if self.player == player then
		return
	end

	self.player = player
end

function BaseWeapon:setEquipped(equipped)
	if self.equipped == equipped then
		return
	end

	self.equipped = equipped
	self:onEquippedChanged()

	if not self.equipped then
		self:stopAnimations()
	end
end

function BaseWeapon:onEquippedChanged()
	if self.activeRenderStepName then
		RunService:UnbindFromRenderStep(self.activeRenderStepName)
		self.activeRenderStepName = nil
	end
	self:cleanupConnection("localStepped")

	if not IsServer and self.weaponsSystem then
		self.weaponsSystem.setWeaponEquipped(self, self.equipped)
		if self.equipped then
			if self.player == Players.LocalPlayer then
				RunService:BindToRenderStep(self.instance:GetFullName(), Enum.RenderPriority.Input.Value, function(dt)
					self:onRenderStepped(dt)
				end)
				self.activeRenderStepName = self.instance:GetFullName()
			end
			self.connections.localStepped = RunService.Heartbeat:Connect(function(dt)
				self:onStepped(dt)
			end)
		end
	end

	if self.instanceIsTool then
		for _, part in pairs(self.instance:GetDescendants()) do
			if part:IsA("BasePart") then
				part.CanCollide = part ~= self.handle and not self.equipped
			end
		end
	end

	self:setActivated(false)
end

function BaseWeapon:setActivated(activated, fromNetwork)
	if not IsServer and fromNetwork and self.player == Players.LocalPlayer then
		return
	end

	if self.activated == activated then
		return
	end

	self.activated = activated
	if IsServer and not fromNetwork then
		self.weaponsSystem.getRemoteEvent("WeaponActivated"):FireAllClients(self.player, self.instance, self.activated)
	end

	self:onActivatedChanged()
end

function BaseWeapon:onActivatedChanged()

end

function BaseWeapon:renderFire(fireInfo)

end

function BaseWeapon:simulateFire(fireInfo)

end

function BaseWeapon:isOwnerAlive()
	if self.instance:IsA("Tool") then
		local humanoid = self.instance.Parent:FindFirstChildOfClass("Humanoid")
		if humanoid then
			return humanoid:GetState() ~= Enum.HumanoidStateType.Dead
		end
	end

	return true
end

function BaseWeapon:fire(origin, dir, charge)
	if not self:isOwnerAlive() or self.reloading then
		return
	end

	if self:useAmmo(1) <= 0 then
		self:reload()
		return
	end

	local fireInfo = {}
	fireInfo.origin = origin
	fireInfo.dir = dir
	fireInfo.charge = math.clamp(charge or 1, 0, 1)
	fireInfo.id = self.nextShotId
	self.nextShotId = self.nextShotId + 1

	if not IsServer then
		self:onFired(self.player, fireInfo, false)
		self.weaponsSystem.getRemoteEvent("WeaponFired"):FireServer(self.instance, fireInfo)
	else
		self:onFired(self.player, fireInfo, false)
	end
end

function BaseWeapon:onFired(firingPlayer, fireInfo, fromNetwork)
	if not IsServer then
		if firingPlayer == Players.LocalPlayer and fromNetwork then
			return
		end

		self:simulateFire(firingPlayer, fireInfo)
	else
		if self:useAmmo(1) <= 0 then
			return
		end

		self.weaponsSystem.getRemoteEvent("WeaponFired"):FireAllClients(firingPlayer, self.instance, fireInfo)
	end
end

function BaseWeapon:getConfigValue(valueName, defaultValue)
	if self.configValues[valueName] ~= nil then
		return self.configValues[valueName]
	else
		return defaultValue
	end
end

function BaseWeapon:tryPlaySound(soundName, playbackSpeedRange)
	playbackSpeedRange = playbackSpeedRange or 0

	local soundTemplate = self.sounds[soundName]
	if not soundTemplate then
		soundTemplate = self.instance:FindFirstChild(soundName, true)
		self.sounds[soundName] = soundTemplate
	end

	if not soundTemplate then
		return
	end

	local sound = soundTemplate:Clone()
	sound.PlaybackSpeed = sound.PlaybackSpeed + localRandom:NextNumber(-playbackSpeedRange * 0.5, playbackSpeedRange * 0.5)
	sound.Parent = soundTemplate.Parent
	sound:Play()
	coroutine.wrap(function()
		task.wait(sound.TimeLength / sound.PlaybackSpeed)
		sound:Destroy()
	end)()

	return sound
end

function BaseWeapon:getSound(soundName)
	local soundTemplate = self.sounds[soundName]
	if not soundTemplate then
		soundTemplate = self.instance:FindFirstChild(soundName, true)
		self.sounds[soundName] = soundTemplate
	end

	return soundTemplate
end

function BaseWeapon:onDestroyed()

end

function BaseWeapon:onConfigValueAdded(valueObj)
	local valueName = valueObj.Name
	local newValue = valueObj.Value
	self.configValues[valueName] = newValue
	self:onConfigValueChanged(valueName, newValue, nil)

	self.connections["valueChanged:" .. valueName] = valueObj.Changed:Connect(function(changedValue)
		local oldValue = self.configValues[valueName]
		self.configValues[valueName] = changedValue

		self:onConfigValueChanged(valueName, changedValue, oldValue)
	end)
	self.connections["valueRenamed:" .. valueName] = valueObj:GetPropertyChangedSignal("Name"):Connect(function()
		self.configValues[valueName] = nil
		self:cleanupConnection("valueChanged:" .. valueName)
		self:cleanupConnection("valueRenamed:" .. valueName)
		self:onConfigValueAdded(valueObj)
	end)
end

function BaseWeapon:onConfigValueRemoved(valueObj)
	local valueName = valueObj.Name
	self.configValues[valueName] = nil

	self:cleanupConnection("valueChanged:" .. valueName)
	self:cleanupConnection("valueRenamed:" .. valueName)
end

-- This function is used to set configuration values from outside configuration objects/folders
function BaseWeapon:importConfiguration(config)
	if not config or not config:IsA("Configuration") then
		for _, child in pairs(config:GetChildren()) do
			if child:IsA("ValueBase") then
				local valueName = child.Name
				local newValue = child.Value
				local oldValue = self.configValues[valueName]
				self.configValues[valueName] = newValue
				self:onConfigValueChanged(valueName, newValue, oldValue)
			end
		end
	end
end

function BaseWeapon:setConfiguration(config)
	self:cleanupConnection("configChildAdded", "configChildRemoved")
	if not config or not config:IsA("Configuration") then
		return
	end

	for _, child in pairs(config:GetChildren()) do
		if child:IsA("ValueBase") then
			self:onConfigValueAdded(child)
		end
	end
	self.connections.configChildAdded = config.ChildAdded:Connect(function(child)
		if child:IsA("ValueBase") then
			self:onConfigValueAdded(child)
		end
	end)
	self.connections.configChildRemoved = config.ChildRemoved:Connect(function(child)
		if child:IsA("ValueBase") then
			self:onConfigValueRemoved(child)
		end
	end)
end

function BaseWeapon:onChildAdded(child)
	if child:IsA("Configuration") then
		self:setConfiguration(child)
	end
end

function BaseWeapon:onChildRemoved(child)
	if child:IsA("Configuration") then
		self:setConfiguration(nil)
	end
end

function BaseWeapon:onConfigValueChanged(valueName, newValue, oldValue)

end

function BaseWeapon:onRenderStepped(dt)

end

function BaseWeapon:onStepped(dt)

end

function BaseWeapon:getAnimationController()
	if self.animController then
		if not self.instanceIsTool or (self.animController.Parent and self.animController.Parent:IsAncestorOf(self.instance)) then
			return self.animController
		end
	end

	self:setAnimationController(nil)

	if self.instanceIsTool then
		local humanoid = IsServer and self.instance.Parent:FindFirstChildOfClass("Humanoid") or self.instance.Parent:WaitForChild("Humanoid", math.huge)
		local animController = nil
		if not humanoid then
			animController = self.instance.Parent:FindFirstChildOfClass("AnimationController")
		end

		self:setAnimationController(humanoid or animController)
		return self.animController
	end
end

function BaseWeapon:setAnimationController(animController)
	if animController == self.animController then
		return
	end
	self:stopAnimations()
	self.animController = animController
end

function BaseWeapon:stopAnimations()
	for _, track in pairs(self.animTracks) do
		if track.IsPlaying then
			track:Stop()
		end
	end
	self.animTracks = {}
end

function BaseWeapon:getAnimTrack(key)
	local track = self.animTracks[key]
	if not track then
		local animController = self:getAnimationController()
		if not animController then
			warn("No animation controller when trying to play ", key)
			return nil
		end

		local animation = AnimationsFolder:FindFirstChild(key)
		if not animation then
			error(string.format("No such animation \"%s\" ", tostring(key)))
		end

		track = animController:LoadAnimation(animation)
		self.animTracks[key] = track
	end

	return track
end

function BaseWeapon:reload(player, fromNetwork)
	if
		not self.equipped or
		self.reloading or
		not self.canReload or
		self:getAmmoInWeapon() == self:getConfigValue("AmmoCapacity", 30)
	then
		return false
	end

	if not IsServer then
		if self.player ~= nil and self.player ~= Players.LocalPlayer then
			return
		end
		self.weaponsSystem.getRemoteEvent("WeaponReloadRequest"):FireServer(self.instance)
		self:onReloaded(self.player)
	else
		self:onReloaded(player, fromNetwork)
		self.weaponsSystem.getRemoteEvent("WeaponReloaded"):FireAllClients(player, self.instance)
	end
end

function BaseWeapon:onReloaded(player, fromNetwork)
	if fromNetwork and player == Players.LocalPlayer then -- make sure localplayer doesn't reload twice
		return
	end

	self.reloading = true
	self.canReload = false

	-- Play reload animation and sound
	if not IsServer then
		local reloadTrackKey = self:getConfigValue("ReloadAnimation", "RifleReload")
		if reloadTrackKey then
			self.reloadTrack = self:getAnimTrack(reloadTrackKey)
			if self.reloadTrack then
				self.reloadTrack:Play()
			end
		end

		self.curReloadSound = self:tryPlaySound("Reload", nil)
		if self.curReloadSound then
			self.curReloadSound.Ended:Connect(function()
				self.curReloadSound = nil
			end)
		end
	end

	local reloadTime = self:getConfigValue("ReloadTime", 2)
	local startTime = tick()

	if self.connections.reload ~= nil then -- this prevents an endless ammo bug
		return
	end
	self.connections.reload = RunService.Heartbeat:Connect(function()
		-- Stop trying to reload if the player unequipped this weapon or reloading was canceled some other way
		if not self.reloading then
			if self.connections.reload then
				self.connections.reload:Disconnect()
				self.connections.reload = nil
			end
		end

		-- Wait until gun finishes reloading
		if tick() < startTime + reloadTime then
			return
		end

		-- Add ammo to weapon
		if self.ammoInWeaponValue then
			self.ammoInWeaponValue.Value = self:getConfigValue("AmmoCapacity", 30)
		end

		if self.connections.reload then
			self.connections.reload:Disconnect()
			self.connections.reload = nil
		end

		self.reloading = false
		self.canReload = false
	end)
end

function BaseWeapon:cancelReload(player, fromNetwork)
	if not self.reloading then
		return
	end
	if fromNetwork and player == Players.LocalPlayer then
		return
	end

	if not IsServer and not fromNetwork and player == Players.LocalPlayer then
		self.weaponsSystem.getRemoteEvent("WeaponReloadCanceled"):FireServer(self.instance)
	elseif IsServer and fromNetwork then
		self.weaponsSystem.getRemoteEvent("WeaponReloadCanceled"):FireAllClients(player, self.instance)
	end

	self.reloading = false
	self.canReload = true

	if not IsServer and self.reloadTrack and self.reloadTrack.IsPlaying then
		warn("Stopping reloadTrack")
		self.reloadTrack:Stop()
	end
	if self.curReloadSound then
		self.curReloadSound:Stop()
		self.curReloadSound:Destroy()
		self.curReloadSound = nil
	end
end

function BaseWeapon:getAmmoInWeapon()
	if self.ammoInWeaponValue then
		return self.ammoInWeaponValue.Value
	end
	return 0
end

function BaseWeapon:useAmmo(amount)
	if self.ammoInWeaponValue then
		local ammoUsed = math.min(amount, self.ammoInWeaponValue.Value)
		self.ammoInWeaponValue.Value = self.ammoInWeaponValue.Value - ammoUsed
		self.canReload = true
		return ammoUsed
	else
		return 0
	end
end

function BaseWeapon:renderCharge()

end

return BaseWeapon

this is the explorer

sorry if i missed anything ill screenshot or send the code if you need more and thanks for the reply.

also a bit late but heres a copy of it with all the scripts and files

developer forum help.rbxl (219.3 KB)