Error With Nightstick SWEP

So I’ve been trying to make a nightstick SWEP for some one I’m developing a DarkRP server for, and they requested a; left click = arrest/right click = unarrest. Seems simple, however I seem to be getting these errors.

Left click to arrest results in this error:


[ERROR] lua/weapons/weapon_nightstick/shared.lua:548: attempt to compare number with nil
  1. unknown - lua/weapons/weapon_nightstick/shared.lua:548



Right click to unarrest results in this error:



[ERROR] lua/weapons/weapon_nightstick/shared.lua:598: attempt to compare number with nil
  1. unknown - lua/weapons/weapon_nightstick/shared.lua:598



Here’s the actual SWEP code:


AddCSLuaFile("shared.lua")


	SWEP.PrintName = "Nightstick"
	SWEP.Slot = 1
	SWEP.SlotPos = 3
	SWEP.DrawAmmo = false
	SWEP.DrawCrosshair = false
	SWEP.Author			= "Oneleg"

	SWEP.HoldType = "melee"
	SWEP.ViewModelFOV = 70
	SWEP.ViewModelFlip = false
	SWEP.ViewModel = "models/weapons/c_stunstick.mdl"
	SWEP.WorldModel = "models/weapons/w_stunbaton.mdl"
	SWEP.ShowViewModel = false
	SWEP.ShowWorldModel = false
	SWEP.ViewModelBoneMods = {}





	SWEP.Spawnable			= false
	SWEP.AdminSpawnable		= true


	SWEP.Primary.ClipSize		= -1
	SWEP.Primary.DefaultClip	= -1
	SWEP.Primary.Automatic		= true
	SWEP.Primary.Ammo			= "none"
	SWEP.Primary.Delay = 1

	SWEP.Secondary.ClipSize		= -1
	SWEP.Secondary.DefaultClip	= -1
	SWEP.Secondary.Automatic	= false
	SWEP.Secondary.Ammo			= "none"

	SWEP.Weight				= 5
	SWEP.AutoSwitchTo		= false
	SWEP.AutoSwitchFrom		= false

	SWEP.Base = "weapon_cs_base2"


SWEP.VElements = {
	["stick2"] = { type = "Model", model = "models/props_c17/canister02a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "stick", pos = Vector(0, 0, 0.239), angle = Angle(180, 0, 0), size = Vector(0.146, 0.146, 0.061), color = Color(10, 9, 9, 255), surpresslightning = false, material = "phoenix_storms/fender_chrome", skin = 0, bodygroup = {} },
	["stick3"] = { type = "Model", model = "models/props_vehicles/tire001a_tractor.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "stick1", pos = Vector(0, 0, 4.356), angle = Angle(90, 0, 0), size = Vector(0.453, 0.02, 0.02), color = Color(10, 9, 9, 255), surpresslightning = false, material = "phoenix_storms/iron_rails", skin = 0, bodygroup = {} },
	["stick1"] = { type = "Model", model = "models/hunter/tubes/tube1x1x4.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "stick", pos = Vector(0.081, -0.08, 18.1), angle = Angle(92.955, 111.037, 0), size = Vector(0.029, 0.029, 0.039), color = Color(10, 9, 9, 255), surpresslightning = false, material = "phoenix_storms/fender_chrome", skin = 0, bodygroup = {} },
	["stick"] = { type = "Model", model = "models/props_c17/oildrum001.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(5.022, 1.485, -21.591), angle = Angle(5.763, 0, 0), size = Vector(0.05, 0.05, 0.533), color = Color(10, 9, 9, 255), surpresslightning = false, material = "phoenix_storms/fender_chrome", skin = 0, bodygroup = {} }
}



SWEP.WElements = {
	["stick2"] = { type = "Model", model = "models/props_c17/canister02a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "stick", pos = Vector(0, 0, 0.578), angle = Angle(180, 0, 0), size = Vector(0.137, 0.137, 0.057), color = Color(10, 9, 9, 255), surpresslightning = false, material = "phoenix_storms/fender_chrome", skin = 0, bodygroup = {} },
	["stick1"] = { type = "Model", model = "models/hunter/tubes/tube1x1x4.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "stick", pos = Vector(0.081, -0.08, 18.1), angle = Angle(92.955, 111.037, 0), size = Vector(0.029, 0.029, 0.039), color = Color(10, 9, 9, 255), surpresslightning = false, material = "phoenix_storms/fender_chrome", skin = 0, bodygroup = {} },
	["stick3"] = { type = "Model", model = "models/props_vehicles/tire001a_tractor.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "stick1", pos = Vector(0, 0, 4.356), angle = Angle(90, 0, 0), size = Vector(0.453, 0.02, 0.02), color = Color(10, 9, 9, 255), surpresslightning = false, material = "phoenix_storms/iron_rails", skin = 0, bodygroup = {} },
	["stick"] = { type = "Model", model = "models/props_c17/oildrum001.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(6.651, 1.228, -20.611), angle = Angle(12.236, 0, 0), size = Vector(0.05, 0.05, 0.533), color = Color(10, 9, 9, 255), surpresslightning = false, material = "phoenix_storms/fender_chrome", skin = 0, bodygroup = {} }
}



function SWEP:Initialize()


// other initialize code goes here

		if CLIENT then

		// Create a new table for every weapon instance
		self.VElements = table.FullCopy( self.VElements )
		self.WElements = table.FullCopy( self.WElements )
		self.ViewModelBoneMods = table.FullCopy( self.ViewModelBoneMods )

		self:CreateModels(self.VElements) // create viewmodels
		self:CreateModels(self.WElements) // create worldmodels

// init view model bone build function
				if IsValid(self.Owner) then
				local vm = self.Owner:GetViewModel()
				if IsValid(vm) then
				self:ResetBonePositions(vm)

				// Init viewmodel visibility
				if (self.ShowViewModel == nil or self.ShowViewModel) then
				vm:SetColor(Color(255,255,255,255))
				else
				// we set the alpha to 1 instead of 0 because else ViewModelDrawn stops being called
				vm:SetColor(Color(255,255,255,1))
				// ^ stopped working in GMod 13 because you have to do Entity:SetRenderMode(1) for translucency to kick in
				// however for some reason the view model resets to render mode 0 every frame so we just apply a debug material to prevent it from drawing
				vm:SetMaterial("Debug/hsv")	
				end
			end
		end

	end

end

function SWEP:Holster()

if CLIENT and IsValid(self.Owner) then
local vm = self.Owner:GetViewModel()
if IsValid(vm) then
self:ResetBonePositions(vm)
end
end

return true
end

	function SWEP:OnRemove()
		self:Holster()
		end

		if CLIENT then

		SWEP.vRenderOrder = nil
		function SWEP:ViewModelDrawn()

		local vm = self.Owner:GetViewModel()
		if !IsValid(vm) then return end

		if (!self.VElements) then return end

		self:UpdateBonePositions(vm)

		if (!self.vRenderOrder) then

// we build a render order because sprites need to be drawn after models
self.vRenderOrder = {}

		for k, v in pairs( self.VElements ) do
		if (v.type == "Model") then
		table.insert(self.vRenderOrder, 1, k)
		elseif (v.type == "Sprite" or v.type == "Quad") then
		table.insert(self.vRenderOrder, k)
		end
		end

		end

		for k, name in ipairs( self.vRenderOrder ) do

		local v = self.VElements[name]
		if (!v) then self.vRenderOrder = nil break end
		if (v.hide) then continue end

		local model = v.modelEnt
		local sprite = v.spriteMaterial

		if (!v.bone) then continue end

		local pos, ang = self:GetBoneOrientation( self.VElements, v, vm )

		if (!pos) then continue end

		if (v.type == "Model" and IsValid(model)) then

		model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
		ang:RotateAroundAxis(ang:Up(), v.angle.y)
		ang:RotateAroundAxis(ang:Right(), v.angle.p)
		ang:RotateAroundAxis(ang:Forward(), v.angle.r)

model:SetAngles(ang)
//model:SetModelScale(v.size)
local matrix = Matrix()
matrix:Scale(v.size)
model:EnableMatrix( "RenderMultiply", matrix )

if (v.material == "") then
model:SetMaterial("")
elseif (model:GetMaterial() != v.material) then
model:SetMaterial( v.material )
end

if (v.skin and v.skin != model:GetSkin()) then
model:SetSkin(v.skin)
end

if (v.bodygroup) then
for k, v in pairs( v.bodygroup ) do
if (model:GetBodygroup(k) != v) then
model:SetBodygroup(k, v)
end
end
end

if (v.surpresslightning) then
render.SuppressEngineLighting(true)
end

render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
render.SetBlend(v.color.a/255)
model:DrawModel()
render.SetBlend(1)
render.SetColorModulation(1, 1, 1)

if (v.surpresslightning) then
render.SuppressEngineLighting(false)
end

elseif (v.type == "Sprite" and sprite) then

local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
render.SetMaterial(sprite)
render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)

elseif (v.type == "Quad" and v.draw_func) then

local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
ang:RotateAroundAxis(ang:Up(), v.angle.y)
ang:RotateAroundAxis(ang:Right(), v.angle.p)
ang:RotateAroundAxis(ang:Forward(), v.angle.r)

cam.Start3D2D(drawpos, ang, v.size)
v.draw_func( self )
cam.End3D2D()

end

end

end

SWEP.wRenderOrder = nil
function SWEP:DrawWorldModel()

if (self.ShowWorldModel == nil or self.ShowWorldModel) then
self:DrawModel()
end

if (!self.WElements) then return end

if (!self.wRenderOrder) then

self.wRenderOrder = {}

for k, v in pairs( self.WElements ) do
if (v.type == "Model") then
table.insert(self.wRenderOrder, 1, k)
elseif (v.type == "Sprite" or v.type == "Quad") then
table.insert(self.wRenderOrder, k)
end
end

end

if (IsValid(self.Owner)) then
bone_ent = self.Owner
else
// when the weapon is dropped
bone_ent = self
end

for k, name in pairs( self.wRenderOrder ) do

local v = self.WElements[name]
if (!v) then self.wRenderOrder = nil break end
if (v.hide) then continue end

local pos, ang

if (v.bone) then
pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent )
else
pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent, "ValveBiped.Bip01_R_Hand" )
end

if (!pos) then continue end

local model = v.modelEnt
local sprite = v.spriteMaterial

if (v.type == "Model" and IsValid(model)) then

model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
ang:RotateAroundAxis(ang:Up(), v.angle.y)
ang:RotateAroundAxis(ang:Right(), v.angle.p)
ang:RotateAroundAxis(ang:Forward(), v.angle.r)

model:SetAngles(ang)
//model:SetModelScale(v.size)
local matrix = Matrix()
matrix:Scale(v.size)
model:EnableMatrix( "RenderMultiply", matrix )

if (v.material == "") then
model:SetMaterial("")
elseif (model:GetMaterial() != v.material) then
model:SetMaterial( v.material )
end

if (v.skin and v.skin != model:GetSkin()) then
model:SetSkin(v.skin)
end

if (v.bodygroup) then
for k, v in pairs( v.bodygroup ) do
if (model:GetBodygroup(k) != v) then
model:SetBodygroup(k, v)
end
end
end

if (v.surpresslightning) then
render.SuppressEngineLighting(true)
end

render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
render.SetBlend(v.color.a/255)
model:DrawModel()
render.SetBlend(1)
render.SetColorModulation(1, 1, 1)

if (v.surpresslightning) then
render.SuppressEngineLighting(false)
end

elseif (v.type == "Sprite" and sprite) then

local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
render.SetMaterial(sprite)
render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)

elseif (v.type == "Quad" and v.draw_func) then

local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
ang:RotateAroundAxis(ang:Up(), v.angle.y)
ang:RotateAroundAxis(ang:Right(), v.angle.p)
ang:RotateAroundAxis(ang:Forward(), v.angle.r)

cam.Start3D2D(drawpos, ang, v.size)
v.draw_func( self )
cam.End3D2D()

end

end

end

function SWEP:GetBoneOrientation( basetab, tab, ent, bone_override )

local bone, pos, ang
if (tab.rel and tab.rel != "") then

local v = basetab[tab.rel]

if (!v) then return end

// Technically, if there exists an element with the same name as a bone
// you can get in an infinite loop. Let's just hope nobody's that stupid.
pos, ang = self:GetBoneOrientation( basetab, v, ent )

if (!pos) then return end

pos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
ang:RotateAroundAxis(ang:Up(), v.angle.y)
ang:RotateAroundAxis(ang:Right(), v.angle.p)
ang:RotateAroundAxis(ang:Forward(), v.angle.r)

else

bone = ent:LookupBone(bone_override or tab.bone)

if (!bone) then return end

pos, ang = Vector(0,0,0), Angle(0,0,0)
local m = ent:GetBoneMatrix(bone)
if (m) then
pos, ang = m:GetTranslation(), m:GetAngles()
end

if (IsValid(self.Owner) and self.Owner:IsPlayer() and
ent == self.Owner:GetViewModel() and self.ViewModelFlip) then
ang.r = -ang.r // Fixes mirrored models
end

end

return pos, ang
end

function SWEP:CreateModels( tab )

if (!tab) then return end

// Create the clientside models here because Garry says we can't do it in the render hook
for k, v in pairs( tab ) do
if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and
string.find(v.model, ".mdl") and file.Exists (v.model, "GAME") ) then

v.modelEnt = ClientsideModel(v.model, RENDER_GROUP_VIEW_MODEL_OPAQUE)
if (IsValid(v.modelEnt)) then
v.modelEnt:SetPos(self:GetPos())
v.modelEnt:SetAngles(self:GetAngles())
v.modelEnt:SetParent(self)
v.modelEnt:SetNoDraw(true)
v.createdModel = v.model
else
v.modelEnt = nil
end

elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite)
and file.Exists ("materials/"..v.sprite..".vmt", "GAME")) then

local name = v.sprite.."-"
local params = { ["$basetexture"] = v.sprite }
// make sure we create a unique name based on the selected options
			local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" }
			for i, j in pairs( tocheck ) do
			if (v[j]) then
			params["$"..j] = 1
			name = name.."1"
			else
			name = name.."0"
			end
			end

			v.createdSprite = v.sprite
			v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params)

			end
			end

			end

			local allbones
			local hasGarryFixedBoneScalingYet = false

			function SWEP:UpdateBonePositions(vm)

			if self.ViewModelBoneMods then

			if (!vm:GetBoneCount()) then return end

// !! WORKAROUND !! //
// We need to check all model names :/
	local loopthrough = self.ViewModelBoneMods
	if (!hasGarryFixedBoneScalingYet) then
	allbones = {}
	for i=0, vm:GetBoneCount() do
	local bonename = vm:GetBoneName(i)
	if (self.ViewModelBoneMods[bonename]) then
	allbones[bonename] = self.ViewModelBoneMods[bonename]
	else
	allbones[bonename] = {
	scale = Vector(1,1,1),
	pos = Vector(0,0,0),
	angle = Angle(0,0,0)
	}
	end
	end

loopthrough = allbones
end
// !! ----------- !! //

for k, v in pairs( loopthrough ) do
local bone = vm:LookupBone(k)
if (!bone) then continue end

// !! WORKAROUND !! //
local s = Vector(v.scale.x,v.scale.y,v.scale.z)
local p = Vector(v.pos.x,v.pos.y,v.pos.z)
local ms = Vector(1,1,1)
if (!hasGarryFixedBoneScalingYet) then
local cur = vm:GetBoneParent(bone)
while(cur >= 0) do
local pscale = loopthrough[vm:GetBoneName(cur)].scale
ms = ms * pscale
cur = vm:GetBoneParent(cur)
end
end

s = s * ms
// !! ----------- !! //

		if vm:GetManipulateBoneScale(bone) != s then
		vm:ManipulateBoneScale( bone, s )
		end
		if vm:GetManipulateBoneAngles(bone) != v.angle then
		vm:ManipulateBoneAngles( bone, v.angle )
		end
		if vm:GetManipulateBonePosition(bone) != p then
		vm:ManipulateBonePosition( bone, p )
		end
		end
		else
		self:ResetBonePositions(vm)
		end

		end

		function SWEP:ResetBonePositions(vm)

			if (!vm:GetBoneCount()) then return end
			for i=0, vm:GetBoneCount() do
			vm:ManipulateBoneScale( i, Vector(1, 1, 1) )
			vm:ManipulateBoneAngles( i, Angle(0, 0, 0) )
			vm:ManipulateBonePosition( i, Vector(0, 0, 0) )
			end

end

/**************************
Global utility code
**************************/

// Fully copies the table, meaning all tables inside this table are copied too and so on (normal table.Copy copies only their reference).
// Does not copy entities of course, only copies their reference.
// WARNING: do not use on tables that contain themselves somewhere down the line or you'll get an infinite loop
function table.FullCopy( tab )

if (!tab) then return nil end

		local res = {}
		for k, v in pairs( tab ) do
		if (type(v) == "table") then
		res[k] = table.FullCopy(v) // recursion ho!
				elseif (type(v) == "Vector") then
		res[k] = Vector(v.x, v.y, v.z)
		elseif (type(v) == "Angle") then
		res[k] = Angle(v.p, v.y, v.r)
		else
		res[k] = v
		end
		end

return res

end

end



/*--------------------------------------------------------*/

-----------------ACTUAL ATTACK CODE------------------------

/*--------------------------------------------------------*/

function SWEP:PrimaryAttack()
	if CurTime() < self.NextStrike then return end
	
	if SERVER then
		self:SetWeaponHoldType("melee")
		timer.Simple(0.3, function(wep) if wep:IsValid() then wep:SetWeaponHoldType("normal") end end, self)
	end
	self.Owner:SetAnimation(PLAYER_ATTACK1)
	self.Weapon:EmitSound(self.Sound)
	self.Weapon:SendWeaponAnim(ACT_VM_HITCENTER)

	self.NextStrike = CurTime() + .4
	if CLIENT then return end
	local trace = self.Owner:GetEyeTrace()
	if trace.Entity:GetClass() == "prop_ragdoll" then
		for k,v in pairs(player.GetAll()) do
			if trace.Entity.OwnerINT and trace.Entity.OwnerINT == v:EntIndex() then
				KnockoutToggle(v, true)
				return
			end
		end
	end
		
	if not ValidEntity(trace.Entity) or (self.Owner:EyePos():Distance(trace.Entity:GetPos()) > 115) or (not trace.Entity:IsPlayer() and not trace.Entity:IsNPC()) then
		return
	end

	if CfgVars["needwantedforarrest"] == 1 and not trace.Entity:IsNPC() and not trace.Entity:GetNWBool("wanted") then
		Notify(self.Owner, 1, 5, "The player must be wanted in order to be able to arrest them.")
		return
	end
	local jpc = DB.CountJailPos()

	if not jpc or jpc == 0 then
		Notify(self.Owner, 1, 4, "You cannot arrest people since there are no jail positions set!")
	else
		-- Send NPCs to Jail
		if trace.Entity:IsNPC() then
			trace.Entity:SetPos(DB.RetrieveJailPos())
		else
			if not trace.Entity.Babygod then
				trace.Entity:Arrest()
				Notify(trace.Entity, 1, 4, "You've been arrested by " .. self.Owner:Nick())
			else
				Notify(self.Owner, 1, 4, "You can't arrest players who are spawning.")
			end
		end
	end
end

function SWEP:SecondaryAttack()
	if CurTime() < self.NextStrike then return end

	if SERVER then
		self:SetWeaponHoldType("melee")
		timer.Simple(0.3, function(wep) if wep:IsValid() then wep:SetWeaponHoldType("normal") end end, self)
	end
	self.Owner:SetAnimation(PLAYER_ATTACK1)
	self.Weapon:EmitSound(self.Sound)
	self.Weapon:SendWeaponAnim(ACT_VM_HITCENTER)

	self.NextStrike = CurTime() + .4
	
	if CLIENT then return end

	local trace = self.Owner:GetEyeTrace()

	if not ValidEntity(trace.Entity) or not trace.Entity:IsPlayer() or (self.Owner:EyePos():Distance(trace.Entity:GetPos()) > 115) or not trace.Entity:GetNWBool("Arrested") then
		return
	end

	trace.Entity:Unarrest()
	Notify(trace.Entity, 1, 4, "You were unarrested by " .. self.Owner:Nick())
end


And yes I do use the SWEP Construction Kit.

self.NextStrike isn’t initialized anywhere before 548 and 598. It is initialized later, however, on lines 558 and 608 respectively, but it does no use to do it after the initial CurTime() check.