Cleaning this script with many elseifs

I’m using a script that is a state-like system where a part gets destroyed and a new gets cloned, it works but it’s very messy and it’s tedious to detect if it upgraded (like went from crude to unpolished) or degraded (perfect to crude), any ideas? I was thinking of using tables…
Is there also a way to make it so the event ONLY fires when the state gets changed?

-- THIS IS A .CHANGED CONNECTION FOR INTVALUE WITH VALUE BEING PASSED AS THE CHANGE INTVALUE.
if Value < 80 and Value > 60 and Moai.Moai.StateType.Value == "Perfect" or Moai.Moai.StateType.Value == "Crude" then -- unpolished state
				Moai.Moai.DontAlert.Value =  true
				if Moai.Moai.StateType.Value == "Crude" then
					Moai.Moai.StateType.Value = "Unpolished"
					AlertEvent:FireClient(Players:FindFirstChild(Moai.Moai:FindFirstChild("Owner").Value), "YOUR MOAI HAS BEEN UPGRADED!") -- in this case it gets upgraded
				else
					Moai.Moai.StateType.Value = "Unpolished"
					AlertEvent:FireClient(Players:FindFirstChild(Moai.Moai:FindFirstChild("Owner").Value), "YOUR MOAI HAS BEEN DEGRADED!") -- but in here it went from perfected to unpolished.
				end
				if Moai:FindFirstChild("Meshes/Clean") then
					Moai["Meshes/Clean"]:Destroy()
				else
					Moai.Crude:Destroy()
				end
				local UnpolishedMoai: Part? = UnpolishedMesh:Clone()
				UnpolishedMoai.CFrame = Moai.PrimaryPart.CFrame
				UnpolishedMoai.Parent = Moai
			elseif Value > 85 and Moai.Moai.StateType.Value ~= "Perfect" and Moai.Moai.DontAlert.Value == true then -- perfect state
				Moai.Moai.DontAlert.Value = false
				Moai.Moai.StateType.Value = "Perfect"
				AlertEvent:FireClient(Players:FindFirstChild(Moai.Moai:FindFirstChild("Owner").Value), "YOUR MOAI HAS BEEN UPGRADED!")
				Moai["Meshes/Unpolished"]:Destroy()
				local PerfectMoai: Part? = PerfectMesh:Clone()
				PerfectMoai.CFrame = Moai.PrimaryPart.CFrame
				PerfectMoai.Parent = Moai
			elseif Value < 60 and Value > 40 and Moai.Moai.StateType.Value ~= "Unpolished" or Moai.Moai.StateType.Value ~= "Stage 3" and Moai.Moai.StateType.Value ~= "Perfect" then
				Moai.Moai.DontAlert.Value = true
				if Moai.Moai.StateType.Value == "Unpolished" then
					Moai.Moai.StateType.Value = "Crude"
					AlertEvent:FireClient(Players:FindFirstChild(Moai.Moai:FindFirstChild("Owner").Value), "YOUR MOAI HAS BEEN DEGRADED!")
				else
					Moai.Moai.StateType.Value = "Crude"
					AlertEvent:FireClient(Players:FindFirstChild(Moai.Moai:FindFirstChild("Owner").Value), "YOUR MOAI HAS BEEN UPGRADED!")
				end
				if Moai:FindFirstChild("Meshes/Unpolished") then
					Moai:FindFirstChild("Meshes/Unpolished"):Destroy()
				else
					print(". . . ")
				end
				local PerfectMoai: Model? = Core.MoaiMeshes.Crude:Clone()
				PerfectMoai:SetPrimaryPartCFrame(Moai.PrimaryPart.CFrame)
				PerfectMoai.Parent = Moai
			end
1 Like

Offtopic question but does .Changed call on same value change? (for example: if a stringvalue default value is “Hello” and I somewhat changed it to “Hello” even though it is the same) Will .Changed call on the example? if not then it would sorta help

Edit: I cleaned it on my own! I knew tables would play a role! I would convert to modulescripts but i don’t know…

local Stage = {
	["Perfect"] = function()
		--
	end,
	["Unpolished"] = function()
		--
	end,
	["Crude"] = function()
		print("debug")
	end,
	["Stage 3"] = function()
		print("test")
	end,
	["Stage 2"] = function()
		print("t")
	end,
	["Rock"] = function()
		print("d")
	end,
}
Moai.Moai.StateType.Changed:Connect(function(Value)
	Stage[Value]()
end)
1 Like

When it comes to reducing if statements, you could use Logical Operators

For example

if Moai.Moai.StateType.Value == "Crude" then
	Moai.Moai.StateType.Value = "Unpolished"
	AlertEvent:FireClient(Players:FindFirstChild(Moai.Moai:FindFirstChild("Owner").Value), "YOUR MOAI HAS BEEN UPGRADED!") -- in this case it gets upgraded
else
	Moai.Moai.StateType.Value = "Unpolished"
	AlertEvent:FireClient(Players:FindFirstChild(Moai.Moai:FindFirstChild("Owner").Value), "YOUR MOAI HAS BEEN DEGRADED!") -- but in here it went from perfected to unpolished.
end

-- can be converted to 2 lines
AlertEvent:FireClient(Players:FindFirstChild(Moai.Moai:FindFirstChild("Owner").Value), 
	"YOUR MOAI HAS BEEN " .. (Moai.Moai.StateType.Value == "Crude" and "UPGRADED!" or "DEGRADED!"))
Moai.Moai.StateType.Value = "Unpolished"

Though it does still feel pretty long

In order to shorten things down even more (and make things more readable) you should be using variables to store values. Also there’s no reason to use FindFirstChild if you’re not using it in an if statement (Since when not in an if statement, FFC will return nil and you will get the "attempt to index nil with object" error)

-- More readable code
local owner: Player = Players[Moai.Moai.Owner.Value]
local stateType: StringValue = Moai.Moai.StateType

AlertEvent:FireClient(owner,  "YOUR MOAI HAS BEEN " .. (stateType.Value == "Crude" and "UPGRADED!" or "DEGRADED!"))
stateType.Value = "Unpolished"

Some More things that you can do with logical operators

if Moai:FindFirstChild("Meshes/Clean") then
	Moai["Meshes/Clean"]:Destroy()
else
	Moai.Crude:Destroy()
end

-- can be converted to a single line 
(Moai:FindFirstChild("Meshes/Clean") or Moai.Crude):Destroy()

If you go a bit further, that should mean in theory you can remove most if statements (assuming that there isn’t radically different behavior between each of the conditions)

1 Like

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