bad key to string index (number expected, got string) What the hell, why is it expecting a Number?

I have no idea why it’s expecting a number, am I doing tables right, or perhaps I’m having a brain walrus?

ERROR:


ERROR] addons/test/lua/entities/crate_uncommon/init.lua:14: bad key to string index (number expected, got string)
  1. error - [C]:-1
   2. __index - lua/includes/extensions/string.lua:274
    3. SpawnFunction - addons/test/lua/entities/crate_uncommon/init.lua:14
     4. Unbox - addons/test/lua/entities/crate_uncommon/init.lua:66
      5. unknown - addons/test/lua/entities/crate_uncommon/init.lua:49



The offending function:


function ENT:SpawnFunction(item) 
testpos = self:GetPos()
local wom = math.random(0,100)
		local item
		item = table.Random(self.Loot1)
	local thespawnedwep = ents.Create("spawned_weapon")
				thespawnedwep:SetWeaponClass(item) // line
				thespawnedwep:SetModel(item:GetModel()) // line 14
				thespawnedwep:SetPos(testpos)
				thespawnedwep:Spawn()
       
end

The Item table:



UncommonA = {
"cw_g4p_glock17",
"cw_m3super90",
}

local crate_uncommon = ents.Create('crate_uncommon')
	crate_uncommon:SetPos(table.Random(DropSpawns_Uncommon))	
	crate_uncommon:Spawn()
	crate_uncommon.LifeTime = CrateTimeU
	crate_uncommon.Loot1  = UncommonA



Called with: self:SpawnFunction(Item)
Thanks!

it’s because item is a string, and you’re trying to call :GetModel() on it
it says it’s expecting a number because you can use (“string”)[#] to get one character out of a string

What would you recommend as a solution?
Everything I can think of is super messy. :expressionless:

You have a list of strings and are trying to call methods that I can assume you’re trying to get from a different SWEP. I’d recommend just inserting the model yourself in the table but you can also do something like:



thespawnedwep:SetModel( weapons.Get( item ).WorldModel )


Thanks, that works. I have no idea how to do the first method you described, but I’d be up for learning.
Couple of new problems, the lifetime error is being caused when picking up too many crates in a short amount of time. The other error is hit or miss random after pressing “e” on a crate.
Pretty sure I screwed up how I’m getting the weapon name with the print.


A Bug Out Bag has spawned, go make sure it works!

[ERROR] addons/test/lua/entities/crate_uncommon/init.lua:68: attempt to concatenate local 'item' (a nil value)
  1. Open- addons/test/lua/entities/crate_uncommon/init.lua:68
   2. unknown - addons/test/lua/entities/crate_uncommon/init.lua:50

Player Found a Bug-out Bag!

[ERROR] addons/test/lua/entities/crate_uncommon/init.lua:39: attempt to perform arithmetic on field 'LifeTime' (a nil value)
  1. unknown - addons/test/lua/entities/crate_uncommon/init.lua:39

Timer Failed! [Simple][@addons/testlua/entities/crate_uncommon/init.lua (line 38)]


It’s because you use local item; with nothing being set… You also use Item which isn’t item because of case-sensitivity…

Show us the full code.

Fixed the issue. made the SpawnFunction return the item for use in the print concat.
I’ve got another issue though; Sometimes (Mostly when holding E, can be random) 1-2 items pop out, which means SOMEHOW THIS LINE is calling the SpawnFunction in addition to getting it’s return.


DarkRP.notify(ply, 3, 10, "You've found a Bug-out Bag1, a(n)"..self:SpawnFunction().." was found inside.")

New Spawn Function


function ENT:SpawnFunction(item)
testpos = self:GetPos()
		local item
		item = table.Random(self.Loot1)
	local thespawnedwep = ents.Create("spawned_weapon")
				thespawnedwep:SetWeaponClass(item)
				thespawnedwep:SetModel( weapons.Get( item ).WorldModel )
				thespawnedwep:SetPos(testpos)
				thespawnedwep:Spawn()
		return item
			
       
end

SetUseType to SIMPLE_USE so that 1 press of the use-key fires ENT:AcceptInput or ENT:Use once instead of continuously…

It’s already set under ENT:Initialize self:SetUseType(SIMPLE_USE).
I’m pretty sure even though its supposed to concat the SpawnFunction its concatting it AND calling it. Removing the notify seems to fix the problem; am I concatting it right?

Yes, it is calling the function and you’re concatenating the return…

A few things I noticed with the code…

You call self:Remove before self:Open… Call self:Open first, then change all self:Remove to SafeRemoveEntity( self );

Next, if you do print( “blah” … self:SpawnFunction( ) … " blah" ); and call self:SpawnFunction( ) right before the print, then YES it will execute twice as you mentioned. You could simply do local _item = self:SpawnFunction( ); print( "You received " … _item ); then it’ll be called once and you can use the reference from the returned item where-ever you want…

Here is an example for enemy spawner - different examples; shows how to use table, call or create helper functions, etc…: https://dl.dropboxusercontent.com/u/26074909/tutoring/entities/enemy_spawner.lua.html

NPC that gives a weapon on use: https://dl.dropboxusercontent.com/u/26074909/tutoring/entities/npc_weapon_giver.lua.html

Just wanted to expand on this a little:
EVERY time you have the code: MyFunction(), NO MATTER WHERE IT IS, the function will run IN ITS ENTIRETY and, where applicable, return its return value.

As Acecool said, the most common (only?) way to use a function’s return value more than once is using:
local a = MyFunction()

print(a)

There’s no way to get a function’s return value without having it run.

Thank you, guys!
I’ll study these.
On a smaller note, is it possible to retrieve the “Nice” (Printname?) name of a swep for what I’m doing? I tried a variety of different methods and I cant seem to get it to work.

You just grab the wep / wep table and grap the PrintName field. If you have a weapon entity, just do
myvariable = WeaponEntity.PrintName
if you have a classname, do
myvariable = weapons.GetStored(classname).PrintName

What’s the difference between weapons.GetStored and weapons.get? its complaining that it’s null, also. This could be do to the way CW2.0 handles PrintNames.

If I’m not mistaken:
[lua]local wep = weapons.Get( “weapon_name” )
– is essentially equal to:
local wep = table.Copy( weapons.GetStored( “weapon_name” ) )[/lua]

Basically, if all you want to do is read values, GetStored is more efficient. If you want to get the table so that you can make changes to it, WITHOUT modifying the actual table, you should use Get. If, for some unholy reason, you want to change a SWEP’s ACTUAL table, you have to use GetStored.

The trick is that tables are pointers, they don’t work like other variables. If you don’t understand, Google “Lua tables” and I’m sure you’ll find great learning resources :slight_smile:

Thanks!
I’ll mark as solved when I get back, I feel as though I’m taking up the front page of Developer Discussion with this thread.

You should generally use GetStored so you can skip a call to table.Copy, which can become relatively expensive on some weapons depending on what they have on their table.

Wrong.

weapons.Get literally calls table.Copy

Thank you - my post was meant to agree with Neat-Nit and I turn around and type the wrong thing.