Need help with OOP

I’m trying to get 2 properties from my object table but when I access it using self they return as nil, surprisingly one of the values from the object table isn’t nil.

Here is how my code works, I setup my classes and constructor inside my module script, then I make the object inside a serverscript. Using this new object I send the object table over to a local script.

This removes the metatable so I set it up again, now on the client I run one of the functions in my class, which errors due to self returning as nil.

Here is my module script, This is the part that errors

local fireball = {}
fireball.__index = fireball 

--Services 
local rs = game:GetService("ReplicatedStorage")
local runService = game:GetService("RunService")

--Tool 
local tool = rs:WaitForChild("Tool")

--Fire Particles 
local fireParticles = rs:WaitForChild("FireParticles ")

--Remotes 

function fireball.new(player)
	local newFireball = {}
	
	local clone = tool:Clone()
	clone.Parent = player.Backpack 
	clone.RequiresHandle = false 
	clone.Name = "Fireball"
	
	newFireball.Clone = clone 
	
	local fireParticles1 = fireParticles:Clone()
	local fireParticles2 = fireParticles:Clone()
	
	fireParticles1.Parent = player.Character.RightHand
	fireParticles2.Parent = player.Character.LeftHand
	
	newFireball.Fire1 = fireParticles1
	newFireball.Fire2 = fireParticles2
	
	return newFireball
end

function fireball:OnEquipped(Player)
	print(Player)
	print(self.Clone)
	print(self.Fire1)
	print(self.Fire2)
	local Char = Player.Character or Player.CharacterAdded:Wait()
	local RightHand = Char:WaitForChild("RightHand")
	local LeftHand = Char:WaitForChild("LeftHand")
	
	local fire1 = self.FireParticles1 
	local fire2 = self.FireParticles2

	
	self.Clone.Equipped:Connect(function() -- self.Clone works for some random reason 
		runService.RenderStepped:Connect(function()
			fire1.CFrame = RightHand.CFrame 
			fire2.CFrame = LeftHand.CFrame -- Fire1 and fire2 returns as nil, I can't use these 
			
			
		end)
	end)
	
	self.Clone.Unequipped:Connect(function()
		print("not equipped")
	end)
end

return fireball 

Here is the server script

--Services 
local rs = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

--Modules 
local fireball = require(rs:WaitForChild("fireball"))

--Remotes 
local rEvent = rs:WaitForChild("RemoteEvent")


Players.PlayerAdded:Connect(function(Player)
	Player.CharacterAdded:Connect(function()
		local Fireball = fireball.new(Player)
		rEvent:FireAllClients(Fireball, Player)
	end)
end)

Here is the local script

--Services 
local rs = game:GetService("ReplicatedStorage")

--Modules 
local Fireball = require(rs:WaitForChild("fireball"))

--Remotes 
local rEvent = rs:WaitForChild("RemoteEvent")

--Events 
rEvent.OnClientEvent:Connect(function(object, Player)
	setmetatable(object, Fireball)
	
	object:OnEquipped(Player)
	
end)

Your constructor is incorrect, when your creating a instance of an object you need to call setmetatable to the class so it can basically allow the instance to access the methods. So you need to do this:

function fireball.new(player)
	local newFireball = setmetatable({}, fireball)
	
	local clone = tool:Clone()
	clone.Parent = player.Backpack 
	clone.RequiresHandle = false 
	clone.Name = "Fireball"
	
	newFireball.Clone = clone 
	
	local fireParticles1 = fireParticles:Clone()
	local fireParticles2 = fireParticles:Clone()
	
	fireParticles1.Parent = player.Character.RightHand
	fireParticles2.Parent = player.Character.LeftHand
	
	newFireball.Fire1 = fireParticles1
	newFireball.Fire2 = fireParticles2
	
	return newFireball
end

Also, be mindful of the fact that you need to remove references from the FireballObject to instances that are destroyed or you will end up leaking memory.

2 Likes

thanks I added setmetatable but self still returns as nil

also to prevent leaking memory do I for example just set newFireball.Fire1 = nil?

Yes and does the method get called?

1 Like

yes the method gets called 30 chars

When the method gets called this is what I get in the output
image

any idea on this?

Sorry for the late reply I was doing work, sending instances over remotes does not work the way you think it does. When you send a instance over a remote it passes a reference to the instance and not the instance itself, thus the Fire1 and Fire2 properties are nil, to send it over you need to parent them to a container that the client can’t see (from inside of the constructor), for example Replicated Storage. Furthermore, the self param is not nil since you can see it printing the self.Clone.

1 Like

thanks alot this really helped, everyday I feel dumber and dumber