Bit new to metatables, need help

Alright so im remaking the datastores and adding a class using metatables (followed a tutorial)
but i needed to add a folder (similar to leaderstats) to the player and i think i need to add it through the constructor

local playerclass = {};
playerclass.__index = playerclass;

function playerclass.new(plr, self)
	repeat task.wait() until plr.Character ~= nil
	if self then return setmetatable(self, playerclass) end
	local self = setmetatable({},playerclass)
	self.name = plr.Name
	self.displayname = plr.DisplayName
	self.character = plr.Character
	self.cash = 0
	self.level = 1
	self.items = Instance.new("Folder")
	self.items.Parent = plr
	self.items.Name = "Items"
	self.slot1 = Instance.new("StringValue")
	self.slot1.Parent = self.items
	self.slot1.Name = "Primary"
	self.slot1.Value = "Winchester Model 70"
	self.slot2 = Instance.new("StringValue")
	self.slot2.Parent = self.items
	self.slot2.Name = "Seconday"
	self.slot2.Value = "M1911"
	self.slot3 = Instance.new("StringValue")
	self.slot3.Parent = self.items
	self.slot3.Name = "Melee"
	self.slot3.Value = "Combat Knife"
	return self
end

return playerclass

issue is it wont work

2 Likes

Don’t use long-polling like this:
repeat task.wait() until plr.Character ~= nil

Instead do this:
local char = plr.Character or plr.CharacterAdded:Wait()

I’m unsure why your constructor has the 2nd argument as “self”, if you do:
local playerClass = playerclass:new()
It will automatically populate the self variable for you. Though in your case you should be fine with just doing:
local self = setmetatable({},playerclass)

I would also move your leaderstats creation into its own method in the class and then have the constructor call it.

What specifically about your script doesn’t work?

2 Likes

Sorry for the late response and also sorry that im pretty bad at scripting ngl because i dont know what you mean :{
Also apparently it works for my friend who joined my game?? makes no sense.

What i meant by “it doesnt work” is that the folder “Items” would not create

1 Like

Okay i think what you meant is do all of that items stuff in a seperate function so i did and it did not work
new code:

local playerclass = {};
playerclass.__index = playerclass;

function playerclass:SetItems(plr)
	local items = Instance.new("Folder")
	items.Parent = plr
	items.Name = "Items"
	local slot1, slot2, slot3 = Instance.new("StringValue")
	slot1.Parent = items
	slot2.Parent = items
	slot3.Parent = items
	slot1.Name = "Primary"
	slot2.Name = "Secondary"
	slot3.Name = "Melee"
	slot1.Value = "Winchester Model 70"
	slot2.Value = "M1911"
	slot3.Value = "Combat Knife"
end

function playerclass.new(plr)
	local char = plr.Character or plr.CharacterAdded:Wait()
	if self then return setmetatable(self, playerclass) end
	local self = setmetatable({},playerclass)
	self.name = plr.Name
	self.displayname = plr.DisplayName
	self.character = plr.Character
	self.cash = 0
	self.level = 1
	playerclass.SetItems(plr)
	return self
end

return playerclass

(if you are wondering, yes i am actually using those methods in a seperate script.)

1 Like

It’s because the SetItems function requires a self argument meanwhile you’re only calling it with plr.

1 Like

Didnt Work
(char limit) aaaaaaa

1 Like

Did you do playerclass:SetItem(plr)?

1 Like

i did it in the constructor, not sure if thats why it wont work

1 Like

Were you getting any errors previously?

1 Like

No. Whats weird is also that other people had the gun at one point??

1 Like

Are you 100% sure you executed @CE0_OfTrolling 's solution successfully? You mentioned you only did it in the constructor.

Here’s an explanation (more in-depth) of how it works:

The dot operator will not pass the item itself as a parameter, however the colon operator does.
So:

PlayerClass.SetItem(PlayerClass, player)
--is the same as
PlayerClass:SetItem(player)

When using colon notation, the first parameter passed is always stored in self. If you call with colon notation, the item itself is also passed as a parameter. Here’s some more information about that.

Since you only pass the player as a parameter, it is stored in the self parameter and the plr parameter is left as nil. Since it’s left as nil, when you assign the parent to what you think is the player, you’re actually assigning it to nothing.

You should change all instances of PlayerClass.SetItems(plr) to PlayerClass:SetItems(plr) throughout your code.

1 Like

Might’ve misunderstood what you said but this is what I did and now its saying “Attempted to index nil with Parent”

local playerclass = {};
playerclass.__index = playerclass;

function playerclass:SetItems(plrclass,plr)
	local items = Instance.new("Folder")
	items.Parent = plr
	items.Name = "Items"
	local slot1, slot2, slot3 = Instance.new("StringValue")
	slot1.Parent = items
	slot2.Parent = items
	slot3.Parent = items
	slot1.Name = "Primary"
	slot2.Name = "Secondary"
	slot3.Name = "Melee"
	slot1.Value = "Winchester Model 70"
	slot2.Value = "M1911"
	slot3.Value = "Combat Knife"
end

function playerclass.new(plr, self)
	local char = plr.Character or plr.CharacterAdded:Wait()
	playerclass.SetItems(plr,self)
	if self then return setmetatable(self, playerclass) end
	local self = setmetatable({},playerclass)
	self.name = plr.Name
	self.displayname = plr.DisplayName
	self.character = plr.Character
	self.cash = 0
	self.level = 1
	playerclass:SetItems(plr)
	return self
end

return playerclass

Remove plrclass from the list of arguments.

it should be function playerclass:SetItems(plr).

I’m going to re-write the constructor for you, since its very confusing at the moment.

function playerclass.new(plr)
	local self = setmetatable({}, playerclass)
	self.name = plr.Name
	self.displayname = plr.DisplayName
	self.character = plr.Character
	self.cash = 0
	self.level = 1
	self:SetItems(plr)
	return self
end

Sorry for late late reply but this didnt work either
ServerScriptService.Main.Server.PlayerClass:10: attempt to index nil with ‘Parent’ is the error
and this is my code

local playerclass = {};
playerclass.__index = playerclass;

function playerclass:SetItems(plrclass,plr)
	local items = Instance.new("Folder")
	items.Parent = plr
	items.Name = "Items"
	local slot1, slot2, slot3 = Instance.new("StringValue")
	slot1.Parent = items
	slot2.Parent = items
	slot3.Parent = items
	slot1.Name = "Primary"
	slot2.Name = "Secondary"
	slot3.Name = "Melee"
	slot1.Value = "Winchester Model 70"
	slot2.Value = "M1911"
	slot3.Value = "Combat Knife"
end

function playerclass.new(plr)
	local self = setmetatable({}, playerclass)
	self.name = plr.Name
	self.displayname = plr.DisplayName
	self.character = plr.Character
	self.cash = 0
	self.level = 1
	self:SetItems(plr)
	return self
end
return playerclass

In this line, only slot1’s value is being set. slot2 and slot3 are nil.
Full code:

local playerclass = {};
playerclass.__index = playerclass;

function playerclass:SetItems(plr)
	local items = Instance.new("Folder")
	items.Parent = plr
	items.Name = "Items"
	local slot1, slot2, slot3 = Instance.new("StringValue"), Instance.new("StringValue"), Instance.new("StringValue")
	slot1.Parent = items
	slot2.Parent = items
	slot3.Parent = items
	slot1.Name = "Primary"
	slot2.Name = "Secondary"
	slot3.Name = "Melee"
	slot1.Value = "Winchester Model 70"
	slot2.Value = "M1911"
	slot3.Value = "Combat Knife"
end

function playerclass.new(plr)
	local self = setmetatable({}, playerclass)
	self.name = plr.Name
	self.displayname = plr.DisplayName
	self.character = plr.Character
	self.cash = 0
	self.level = 1
	self:SetItems(plr)
	return self
end
return playerclass

I completely forgot about that rule of lua.
THANK YOU IT WORKED!
Also thanks to everyone else who helped me!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.