Attempting to make a stat system, but I'm getting an 'attempt to index nil with' error no matter what I change, how can I fix it?

  1. What do you want to achieve? Keep it simple and clear!

I am trying to set rules for base stats i.e what they do for each character, and then manage the values for said stats within a character-specific module script in the event of stat buffs and whatnot that doesn’t exist yet because I have yet to get past this part.

Every character has the base stats within them as attributes, I’m unsure if there’s a better way, but regardless, I am using damageMult as an example.

  1. What is the issue? Include screenshots / videos if possible!
    I get the error:
    ServerStorage.Classes.ClassHandler:10: attempt to index nil with 'GetAttribute'

  2. What solutions have you tried so far? Did you look for solutions on the Creator Hub?

I have tried running Class.new(newChar) all across the module script in hopes that (newChar) wouldn’t be nil, printing newChar(the local variable) at every opportunity which prints the Model name as it should except for when it hasn’t been declared yet ofc but I don’t see a way around (newChar) being nil. I have looked for solutions both on the Creator Hub and on three scripting help discords to no avail.

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

Module Script in ServerStorage:

local Class = {}
Class.__index = Class
	
function Class.new(newChar)
	local self = setmetatable({}, Class)
	
	self.Stats = {
		damageMult = newChar:GetAttribute("damageMult", 1) -- Error line
	}
	
	self.Result = nil
	self.IsChanging = false
	
	self.Oil = {
		[1] = "Red",
		[2] = "Blue",
		[3] = "Green",
	}
	return self
end

function Class:random(player)
	self.Result = Class.new().Oil[math.random(1, #Class.new().Oil)]
	print(self.Result)
	return self.Result
end

function Class:Replace(player)
	if not self.Result then return end
	for i,v in pairs(script.Parent.Oil:GetChildren()) do
		i = self.Result
		if v.Name == self.Result then
			
			local oldChar = player.Character or player.CharacterAdded:Wait()
			local newChar = v:FindFirstChildWhichIsA("Model"):Clone()
			local oldCFrame = oldChar.PrimaryPart.CFrame
			
			player.Character = newChar
			newChar.PrimaryPart.CFrame = oldCFrame
			newChar.Parent = game:GetService("Workspace")
			--This is where I would try to run Class.new(newChar) which shouldn't return nil as the character absolutely does exist at this time, but regardless of whether I do or don't, the error at line 10 persists.
			
			self.Result = nil
			return newChar
		end
	end
end

ClassLoader (Script in ServerScriptService:)

CupEvent.OnServerEvent:Connect(function(player, camPos)
	print("Server")
	
	local pos = player.Character.PrimaryPart.CFrame

	ClassMod:random()
	
	player:LoadCharacter()
	
	ClassMod:Replace(player)
	
	
	player.Character.PrimaryPart.CFrame = pos
end)

You call Class.new() with no parameters (in Class:random), so newChar is nil and so newChar.GetAttributenil.GetAttribute

edit: Just call Classmod:random() with the player argument and give Class.new() player.Character in the code of Class:random

Function

function Class:random(player)
	local char = player.Character or player.CharacterAdded:Wait()
	local classInst = Class.new(char)
	self.Result = classInst.Oil[math.random(1, #classInst.Oil)]
	return self.Result
end

Call it like:

ClassMod:random(player)

I am still getting the error. It did fix the randomization also not working because of said error and I thank both you and hazame4 but newChar is still nil somehow

at the start of Class.new, add:
print(debug.traceback(),newChar)
This will print the exact location of where the Class.new function was called from, so that you can see where exactly a value wasn’t provided which resulted in newChar being nil