Help with Object Oriented Programming

Ohhhhhhh. Thanks for helping me out.

But now I get a new error:

I just tried :WaitForChild, which doesn’t work either.

How are the leaderstats added to the player

Like this: (not the entire script. Just the leaderstats part which works fine)

local function OnPlayerAdded(player)
	-- Setup leaderboard stats
	local leaderstats = Instance.new('Folder')
	leaderstats.Parent = player
	leaderstats.Name = 'leaderstats'

	local Captures = Instance.new('IntValue')
	Captures.Parent = leaderstats
	Captures.Name = 'Captures'
	Captures.Value = 0

	local Cash = Instance.new('NumberValue')
	Cash.Parent = leaderstats
	Cash.Name = 'Cash'
	Cash.Value = 0
	
	local Kills = Instance.new('IntValue')
	Kills.Parent = leaderstats
	Kills.Name = "Kills"
	Kills.Value = 0
	
	local Deaths = Instance.new('IntValue')
	Deaths.Parent = leaderstats
	Deaths.Name = "Deaths"
	Deaths.Value = 0
end

Players.PlayerAdded:Connect(OnPlayerAdded)

I’m not sure why indexing and WaitForChild don’t seem to work, is there any both scripts can be combined, or do they have to be separate?

Also, for WaitForChild, does it throw the Infinite Yield Possible warning, or does it not seem to do anything?

When I try :WaitForChild, nothing appears in the output, but the code still doesn’t work.

They have to be separate since the leaderstats script is in a Server Script.

Ok, I think I understand what’s happening, If you’re expecting the value of StatFunction.Cash to appear in the leaderboard after changing it, it won’t happen because of the way variables work.

You would have to try something like this:

local StatFunctions = {}

StatFunctions.__index = StatFunctions

function StatFunctions.new(player)
	local self = {}
	setmetatable(self, StatFunctions)

    local leaderstats = player:WaitForChild("leaderstats")
	
	self.Player = player
	self.Cash = leaderstats.Cash -- Save a reference to the objects
	self.Captures = leaderstats.Captures
	self.Kills = leaderstats.Kills
	self.Deaths = leaderstats.Deaths
	
	
	
	
	return self
end

function StatFunctions:AddCash(player, amount)
	self.Cash.Value += tonumber(amount) -- Add to the 'Value' property of the object
end


return StatFunctions

Now you should see changes appear on the leaderboard

1 Like

It still doesn’t work unfortunately. No errors in the output, either.

You should use a OOP module if you can’t do this type of OOP.

I use Classic when it comes to OOP:

The thing about being a Programmer is that I like to make things on my own. I wouldn’t learn anything by using a Module.

Did you load the OnPlayerAdded function?

Look at the bottom of the leaderstats script. I already put it there. I would’ve gotten an error if I hadn’t

I think its because self is not called.

Use this:

local StatFunctions = {}

StatFunctions.__index = StatFunctions
StatFunctions.self = nil

function StatFunctions.new(player)
	local self = {}
	setmetatable(self, StatFunctions)

    local leaderstats = player:WaitForChild("leaderstats")
	
	self.Player = player
	self.Cash = leaderstats.Cash -- Save a reference to the objects
	self.Captures = leaderstats.Captures
	self.Kills = leaderstats.Kills
	self.Deaths = leaderstats.Deaths
	
	
	
	
	StatFunctions.self = self
end

function StatFunctions:AddCash(player, amount)
	StatFunctions.self.Cash.Value += tonumber(amount) -- Add to the 'Value' property of the object
end


return StatFunctions

If you look at my code properly, self is in fact a table:

I am saying that you are not making self to the whole module. Only to the new function.

This is definitely not the way to implement object oriented programming. Each call to the constructor will override the StatFunctions.self attribute and you don’t even get an object from the constructor.

1 Like

That’s exactly what I thought. Do you know what I’m doing wrong?

1 Like

I think some more investigation needs doing into why this doesn’t seem to be working - Help with Object Oriented Programming - #9 by HugeCoolboy2007

1 Like

When I construct an OOP Class, I would return the one set with the metatable like so:

local StatFunctions = {}

StatFunctions.__index = StatFunctions

function StatFunctions.new(player)
	local self = {}
	
	self.Player = player
	self.Cash = player.leaderstats.Cash.Value
	self.Captures = player.leaderstats.Captures.Value
	self.Kills = player.leaderstats.Kills.Value
	self.Deaths = player.leaderstats.Deaths.Value
	
	
	
	
	return setmetatable(self, StatFunctions)
end

function StatFunctions:AddCash(player, amount)
	
	self.Cash += tonumber(amount)
end


return StatFunctions

Seconding @HugeCoolboy2007 .

Using WaitForChild on the leaderstats and saving the ValueBase instance rather than their values should work.

I am not sure I understand why you parameter the player when you have the self argument (which is your new instance object).

Would suggest this instead: (in addition, I personally prefer stating the type of the parameter, then not needing to convert it, but that is up to you)

function StatFunctions:AddCash(amount : number)
	self.Cash.Value += amount
end
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local StatFunctions = require(ServerStorage.StatFunctions)

Players.PlayerAdded:Connect(function(player)
    local playerStat = StatFunctions.new(player)
    playerStat:AddCash(10)
end)

it doesn’t find the leaderstats because it fires before the folder (what I’m assuming) spawns in so you should make a slight delay like around 2 seconds