Get weapon stats serverside

So i’ve been working on some nextbots an came across a thread wich showed how to give them a weapon entity. I used self.Weapon:GetMaxClip1() to get the weapons clip and make them reload, however there is no function to obtain other stats such as the Primary.Sound/Numshots/Damage/etc. I took a look at the weapon info system on the workshop wich displays the stats of any weapon, however this was done client side.

It used something similar to this



ent = weapon -- ent wich is the weapon the player is looking at
weaponinfo.dmg = weapon.Primary.Damage
weaponinfo.dly = weapon.Primary.Delay	


and so on. However this doesn’t seem to work on server (I guess), as I tried to do



weaponinfo.dmg = wep.Primary.Damage -- wep is the weapon entity given to the bot
--or
weaponinfo.dmg = (self.Weapon).Primary.Damage -- Same thing


and only got


attempt to index field 'Primary' (a nil value)

So does anybody have any idea of how to get the stats of a wepon serverside???
Here is the snip of code…



function ENT:GiveWeapon(wep)
if SERVER then
local wep = ents.Create(wep)
local pos = self:GetAttachment(self:LookupAttachment("anim_attachment_RH")).Pos
wep:SetOwner(self)
	wep:SetPos(pos)

	wep:Spawn()
	wep:SetSolid(SOLID_NONE)
		
	wep:SetParent(self)

	wep:Fire("setparentattachment", "anim_attachment_RH")
	wep:AddEffects(EF_BONEMERGE)
	

self.Weapon = wep
self.magmaxammo = self.Weapon:GetMaxClip1() --where I got the clip size
print(self.Weapon)  -- prints Weapon [185][weapon_smg1] it prints any weapon I give it tho
print(wep)          -- prints Weapon [185][weapon_smg1] it prints any weapon I give it tho
end
end

I could get away with copying the stats on the shoot/firebullet function, but the point is that the bot can shoot any weapon I exchange with them…

Damage is implemented differently on every weapon base. For engine weapons, you would have to read their script file in /scripts/weapon_name.txt, or use a static table you write yourself. Also, doing self.Weapon is useless: just use self.

Thanks for replying :slight_smile:
I know its implemented diferently, but most weapon bases still use floats such as SWEP.Primary.Damage/Cone/etc. and stuff like that. And why use self? isn’t that the nextbot and not the weapon??? self.Weapon is just the way the wep is being refered to, I could have name it self.NBWeapon or anything else…

The SWEP class has a structure (Collection of different variables) of variables that you can edit, same with entities. They also have their table of functions which is the entities metatable. When you over-ride a hook or function from a given entity’s metatable then you call back to it’s class with self, which holds the entity you are working on in context as a variable. So on the wiki if you searched up Entity you would find the entity class. It holds variables such as the string PrintName and the boolean AdminSpawnable. Not only can you reference variables with self, you may also call class functions with it. I am not the biggest pro but I believe that’s how it goes.

Edit: tl;dr It keeps you in context reference with the current entity.

Only TTT and M9K use it that way iirc.

Thanks for replying¡¡¡

Indeed, as if in my SWEP structure I have SWEP.Primary.Damage = 10. I can reference it anywhere else in the swep’s code by self.Primary.Damage, getting an outpu of 10.

However im triying to get those variables from the swep’s code in my nextbot’s code. In the code I posted, self would refer to the nextbot and not the weapon that is spawned within the nextbot’s code (as the weapon is not the current entity, in my code is referenced as “wep” and/or “self.Weapon”).

Do self:GetWeapon() to get the weapon entity whenever “self” refers to a player, bot, or NPC.

Didn’t worked :frowning:



function ENT:GiveWeapon(wep)
if SERVER then
local wep = ents.Create(wep)
local pos = self:GetAttachment(self:LookupAttachment("anim_attachment_RH")).Pos
wep:SetOwner(self)
	wep:SetPos(pos)

	wep:Spawn()
	wep:SetSolid(SOLID_NONE)
		
	wep:SetParent(self)

	wep:Fire("setparentattachment", "anim_attachment_RH")
	wep:AddEffects(EF_BONEMERGE)
	

self.Weapon = wep
self.magmaxammo = self.Weapon:GetMaxClip1()
weaponinfo = self.Weapon:GetClass()
print(self:GetWeapon())
print(wep)
end
end

-----------------------------------

[ERROR] addons/nb/lua/entities/shoot.lua:150: attempt to call method 'GetWeapon' (a nil value)


I thought get weapon was only for players…

Oh, I see what you’re doing now; I don’t see what the problem is with getting the damage.

Me neither I have gotten variables and strings from a players and entities before by just using “ent.WhateverIWantToKnow” severside. However for some reason it doesn’t seem to work with the weapon here. Even the addon I looked at got the SWEPS structure like that.

As I said both attempts failed


weaponinfo.dmg = wep.Primary.Damage -- wep is the weapon entity given to the bot
--or
weaponinfo.dmg = (self.Weapon).Primary.Damage -- Same thing

Oh, the weapon table isn’t implemented until a frame after creation. Also, you aren’t checking if self.Primary exists on the weapon before accessing the sub-key.

Ok I got it, the weapons I was giving them did not indeed had a proper table. However for the ones that had one on it worked properly, ended up copying some stats from the hl2 weapons as those didn’t had one and added replacers for any varaibles that didn’t exist on the given weapon.

ALERTCrappy/MessyCode***



function ENT:GiveWeapon(wep)
if SERVER then
local wep = ents.Create(wep)
local pos = self:GetAttachment(self:LookupAttachment("anim_attachment_RH")).Pos
wep:SetOwner(self)
	wep:SetPos(pos)

	wep:Spawn()
	wep:SetSolid(SOLID_NONE)
		
	wep:SetParent(self)

	wep:Fire("setparentattachment", "anim_attachment_RH")
	wep:AddEffects(EF_BONEMERGE)
	


self.Weapon = wep
self.magmaxammo = self.Weapon:GetMaxClip1()
local weaponinfo = self.Weapon:GetClass()
print(self.Weapon)
print(wep)
if self.Weapon:IsWeapon() and self.Weapon:IsScripted() then
self.weaponinfosnd = (self.Weapon).Primary.Sound
self.weaponinfodmg = (self.Weapon).Primary.Damage
self.weaponinfodly = (self.Weapon).Primary.Delay	
self.weaponinfonst = (self.Weapon).Primary.NumShots
self.weaponinfocon = (self.Weapon).Primary.Cone
self.weaponinfotrc = (self.Weapon).Primary.TracerName	
self.weaponinfoaut = (self.Weapon).Primary.Automatic
self.weaponinforsnd = (self.Weapon).ReloadSound

elseif self.Weapon:GetClass() == "weapon_smg1" then
self.weaponinfosnd =	"Weapon_SMG1.Single"
self.weaponinfodmg =	4
self.weaponinfodly =	0.08	
self.weaponinfonst =	1
self.weaponinfocon =  	2
self.weaponinfotrc =	"Tracer"
self.weaponinfoaut = 	true
self.weaponinforsnd =	"Weapon_SMG1.Reload"
elseif self.Weapon:GetClass() == "weapon_357" then
self.weaponinfosnd =	"Weapon_357.Single"
self.weaponinfodmg =	40
self.weaponinfodly =	0.7
self.weaponinfonst =	1
self.weaponinfocon =  	0.01
self.weaponinfotrc =	"Tracer"	
self.weaponinfoaut = 	false
self.weaponinforsnd =	"Weapon_357.Reload"
elseif self.Weapon:GetClass() == "weapon_ar2" then
self.weaponinfosnd =	"Weapon_AR2.Single"
self.weaponinfodmg =	8
self.weaponinfodly =	0.12
self.weaponinfonst =	1
self.weaponinfocon =  	1.3
self.weaponinfotrc =	"AR2Tracer"	
self.weaponinfoaut = 	true
self.weaponinforsnd =	"Weapon_AR2.Reload"
elseif self.Weapon:GetClass() == "weapon_pistol" then
self.weaponinfosnd =	"weapon_pistol.Single"
self.weaponinfodmg =	5
self.weaponinfodly =	0.15
self.weaponinfonst =	1
self.weaponinfocon =  	0.2
self.weaponinfotrc =	"Tracer"	
self.weaponinfoaut = 	false
self.weaponinforsnd =	"Weapon_Pistol.Reload"
elseif self.Weapon:GetClass() == "weapon_shotgun" then
self.weaponinfosnd =	"weapon_shotgun.Single"
self.weaponinfodmg =	8
self.weaponinfodly =	0.8
self.weaponinfonst =	7
self.weaponinfocon =  	4
self.weaponinfotrc =	"Tracer"	
self.weaponinfoaut = 	false
self.weaponinforsnd =	"Weapon_Shotgun.Reload"
elseif self.Weapon:GetClass() == "weapon_crossbow" then
self.weaponinfosnd =	"Weapon_Crossbow.Single"
self.weaponinfodmg =	100
self.weaponinfodly =	1
self.weaponinfonst =	1
self.weaponinfocon =  	0
self.weaponinfotrc =	"Tracer"	
self.weaponinfoaut = 	false
self.weaponinforsnd =	"Weapon_Crossbow.Reload"
else
self.weaponinfosnd =	"Weapon_Crossbow.BoltHitWorld"
self.weaponinfodmg =	5
self.weaponinfodly =	0.15
self.weaponinfonst =	1
self.weaponinfocon =  	0.2
self.weaponinfotrc =	"Tracer"	
self.weaponinfoaut = 	false
self.weaponinforsnd =	"Weapon_Pistol.Reload"
end
print(self.weaponinfosnd )
print(self.weaponinfodmg )
print(self.weaponinfodly )
print(self.weaponinfonst )
print(self.weaponinfocon )
print(self.weaponinfotrc )
print(self.weaponinfoaut )
end
end

--also added on the think function a replacer for SWEPS that doesnt have the vars I want or are tables...

function ENT:Think()

if SERVER then

if self.weaponinfosnd == nil then
self.weaponinfosnd = "Weapon_SMG1.Single"
end
if istable(self.weaponinfosnd) then
self.weaponinfosnd = "Weapon_SMG1.Single"
end
if self.weaponinfodmg == nil then
self.weaponinfodmg = 5
end
if self.weaponinfodly == nil then
self.weaponinfodly = 0.12
end
if self.weaponinfonst == nil then
self.weaponinfonst = 1
end
if self.weaponinfocon == nil then
self.weaponinfocon = 1.8
end
if self.weaponinfotrc == nil then
self.weaponinfotrc = "Tracer"	
end
if self.weaponinfoaut == nil then
self.weaponinfoaut = false
end
if self.weaponinforsnd == nil then
self.weaponinforsnd = "Weapon_Pistol.Reload"
end
if istable(self.weaponinforsnd) then
self.weaponinforsnd = "Weapon_Pistol.Reload"
end

if weaponinfoaut == false then
self.autdelay = 2
else
self.autdelay = 1
end
end
end



Now I can give them any weapon on the go :smiley:

THANKS¡¡¡¡¡¡

Why not just use a hash table to get the stats instead of a bunch of if-statements?