How do I make this card class code less messy?

Recently i’ve had a lot of trouble getting help with my code, becuase people say it’s very messy, but I don’t know what i am doing wrong, how do I fix this?

This piece of code in particular:

local Card = {}

Card.__index = Card

function Card.new(Properties , player)
	self = setmetatable({} , Card)
	self.Name = "Bonk648"
	
	self.Color = 6865280869
	self.Image = 6873565000
	self.Power = 500
	self.Health = 500
	
	do --Read only properties
		self.WhiteCost = 10
		self.RedCost = 10
		self.BlueCost = 10
		self.GreenCost = 10
		self.YellowCost = 10
		
		self.Counters = 0
		self.Slot = "Deck"
	end
	
	self.Owner = player
	self.Events = {}
	
	do -- Events
		self.Events.DamageTaken = {}
		self.Events.Destroyed = {}
		self.Events.Targeted = {}
		self.Events.PowerChanged = {}
		self.Events.CountersChanged = {}
		self.Events.TurnEnd = {}
		self.Events.TurnStart = {}
		self.Events.CardDrawn = {}
		self.Events.CardDestroyed = {}
		self.Events.OnSelfCast = {}
		self.Events.OnAllyCast = {}
		self.Events.OnEnemyCast = {}
		self.Events.EnemyDestroyed = {}
		self.Events.AllyDestroyed = {}
		self.Events.Transformed = {}
	end
		
	for i , v in pairs(Properties) do
		if self[i] then
			self[i] = v
		end
	end
	
	self.Model = game.InsertService:LoadAsset(Properties.Model or 6892715376):FindFirstChildWhichIsA("Model")
	self.CardObject = self:RenewGui()
	
	local proxy = setmetatable({keys = {"Name", "Color", "Image", "Power", "Health", "WhiteCost", "RedCost", "GreenCost", "BlueCost", "YellowCost", "Counters", "Slot"}} , {
		__index = function(Tab , key) 
			if self[key] then
				return self[key]
			end
		end,
		__newindex = function(Tab , key , val)
			if self[key] then
				
				if table.find({"Power", "Health", "WhiteCost", "RedCost", "GreenCost", "BlueCost", "YellowCost", "Counters"} , key) then
					local EventTable = nil
					local Args = nil
					
					if key == "Power" then
						EventTable = self.Events.PowerChanged
						Args = {self , val - self[key]}
					end
					
					if key == "Health" then
						if self[key] < val then
							EventTable = self.Events.DamageTaken
							Args = {self , val - self[key]}
						elseif val <= 0 then
							EventTable = self.Events.Destroyed
							Args = {self}
						end
					end
					
					if key == "Counters" then
						EventTable = self.Events.AttackChanged
						Args = {self , val - self[key]}
					end
					
					self[key] = math.clamp(val , 0 , math.huge)
					
					if EventTable then
						
						for i , Effect in pairs(EventTable) do
						Effect(Args)
						end
					end
					
				elseif table.find({"Name", "Color", "Image"} , key) then
					self[key] = val
				else
				warn("Attempt to set read only property")
				end
				
			end
		end
	})
	
	return proxy
end

function Card:SpawnModel(slotGui)
	local effect = game.ReplicatedStorage.CastEffect:Clone() --Spawn effect
	effect:SetPrimaryPartCFrame(slotGui.Parent.CFrame - Vector3.new(0,6,0)) --Make it appear in the correct slot
	effect.Parent = workspace

	local tween = game:GetService("TweenService"):Create(effect.PrimaryPart,TweenInfo.new(0.35),{CFrame = CFrame.new((effect.PrimaryPart.Position + Vector3.new(0,8,0))) * CFrame.Angles(0,math.rad(120),0)}) --Tween 
	tween:Play()
	tween.Completed:Wait()

	local model = self.Model
	model:SetPrimaryPartCFrame(self.Parent.Parent.CFrame)
	model:SetPrimaryPartCFrame(CFrame.new(model.PrimaryPart.Position + Vector3.new(0,6,0)))
	model.Parent = self.CardObject
	model.Humanoid.Animator:LoadAnimation(model.IdleAnimation):Play()

	local tween = game:GetService("TweenService"):Create(effect.PrimaryPart,TweenInfo.new(0.2),{CFrame =(effect.PrimaryPart.CFrame * CFrame.Angles(0,math.rad(240),0))}) --Tween 
	tween:Play()
	tween.Completed:Wait()	

	local tween = game:GetService("TweenService"):Create(effect.PrimaryPart,TweenInfo.new(0.2),{CFrame = (effect.PrimaryPart.CFrame * CFrame.Angles(0,math.rad(360),0))}) --Tween 
	tween:Play()
	tween.Completed:Wait()	
	effect:Destroy()
end

function Card:RenewGui()
	
	local InsertService = game:GetService("InsertService")
	local BorderDec =  InsertService:LoadAsset(tonumber(self.Color))
	local DisplayDec =  InsertService:LoadAsset(self.Image)
	local card =  game.ReplicatedStorage.EmptyCard:Clone()
	card.Name = self.Name
	card.NameLabel.Text = self.Name
	card.Border.Image = BorderDec.Decal.Texture
	card.Display.Image = DisplayDec.Decal.Texture 
	BorderDec:Destroy()
	DisplayDec:Destroy()
	card.Power.Text = self.Power
	card.Health.Text = self.Health
	card.ModelVal.Value = self.Model
	local distance = 0.13

	local colors = {"White","Yellow","Green","Blue","Red",}

	for i , color in pairs(colors) do
		print(self[color .. "Cost"])
		card.Costs[color].CostLabel.Text = self[color .. "Cost"]

		if tonumber(card.Costs[color].CostLabel.Text) <= 0 then 
			card.Costs[color].Visible = false
		else
			card.Costs[color].Position = UDim2.new(distance,0,0.91, 0)
			distance += 0.075
		end
	end
	print("Card Gui Created")
	return card
end

Card.DefaultCards = {
	Card.new({
		["Name"] = "Bonk9098",
		["Color"] = 6865280869,
		["Image"] = 6873565000,
		["Power"] = 400,
		["Health"] = 5000,
		["WhiteCost"] = 10,
		["RedCost"] = 3,
		["BlueCost"] = 3,
		["GreenCost"] = 3,
		["YellowCost"] = 3,
		["Model"] = 6971743255
	}),

	Card.new({
		["Name"] = "Nil",
		["Color"] = 6865283271,
		["Image"] = 6865303020,
		["Power"] = 50,
		["Health"] = 50,
		["WhiteCost"] = 1,
		["RedCost"] = 1,
		["BlueCost"] = 1,
		["GreenCost"] = 0,
		["YellowCost"] = 0,
		["Model"] = 6892715376
	}),
	Card.new({
		["Name"] = "Nil",
		["Color"] = 6865283271,
		["Image"] = 6865303020,
		["Power"] = 50,
		["Health"] = 50,
		["WhiteCost"] = 1,
		["RedCost"] = 1,
		["BlueCost"] = 1,
		["GreenCost"] = 0,
		["YellowCost"] = 0,
		["Model"] = 6892715376
	}),
	Card.new({
		["Name"] = "Nil",
		["Color"] = 6865281448,
		["Image"] = 6865303020,
		["Power"] = 50,
		["Health"] = 50,
		["WhiteCost"] = 1,
		["RedCost"] = 1,
		["BlueCost"] = 1,
		["GreenCost"] = 0,
		["YellowCost"] = 0,
		["Model"] = 6892715376
	}),
	Card.new({
		["Name"] = "Nil",
		["Color"] = 6865282008,
		["Image"] = 6865303020,
		["Power"] = 50,
		["Health"] = 50,
		["WhiteCost"] = 1,
		["RedCost"] = 1,
		["BlueCost"] = 1,
		["GreenCost"] = 0,
		["YellowCost"] = 0,
		["Model"] = 6892715376
	}),
	Card.new({
		["Name"] = "Nil",
		["Color"] = 6865280869,
		["Image"] = 6865303020,
		["Power"] = 50,
		["Health"] = 50,
		["WhiteCost"] = 1,
		["RedCost"] = 1,
		["BlueCost"] = 1,
		["GreenCost"] = 0,
		["YellowCost"] = 0,
		["Model"] = 6892715376
	}),
	Card.new({
		["Name"] = "Nil",
		["Color"] = 6865282709,
		["Image"] = 6865303020,
		["Power"] = 50,
		["Health"] = 50,
		["WhiteCost"] = 1,
		["RedCost"] = 1,
		["BlueCost"] = 1,
		["GreenCost"] = 0,
		["YellowCost"] = 0,
		["Model"] = 6892715376
	}),
}
return Card

For making code more clean, switch this topic to #help-and-feedback:code-review.

1 Like

ok, will do that now… 3 0 c h a r s