How do I use a modules functions inside of my module?

So I am working on a module where it uses OOP to create a .new another one of my functions would need to use .new to to create a new object. My code is below

local OQUO = {}
OQUO.__index = OQUO

function OQUO:GetColor(color)
	local colorstring = tostring(string.lower(color))
	if colorstring == "red" then
		return Color3.fromRGB(255,0,0)
	elseif colorstring == "green" then
		return Color3.fromRGB(0,255,0)
	elseif colorstring == "blue" then
		return Color3.fromRGB(0,0,255)
	elseif colorstring == "black" then
		return Color3.fromRGB(163, 162, 165)
	elseif colorstring == "orange" then
		return Color3.fromRGB(255, 170, 0)
	elseif colorstring == "pink" then
		return Color3.fromRGB(255, 0, 255)
	elseif colorstring == "purple" then
		return Color3.fromRGB(170, 0, 255)
	elseif colorstring == "teal" then
		return Color3.fromRGB(0, 255, 255)
	elseif colorstring == "white" then
		return Color3.fromRGB(255, 255, 255)
	elseif colorstring == "yellow" then
		return Color3.fromRGB(255, 255, 0)
	end
end

function errors(msg)
	warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~\nOQUO Extention Error:\n" .. msg .. "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~")
end

function check(light)
	if string.sub(string.lower(light.Name), 1, 6) == "parcan" then
		return true
	else
		return false
	end
end

local alllighting = {}
for i,v in ipairs(workspace:GetChildren()) do
	if check(v) then
		table.insert(alllighting, v)
	end
end

function OQUO.new(tble)
	local info = tble
	setmetatable(info, OQUO)
	return info
end 

function OQUO:On()
	for _,light in ipairs(self) do
		if check(light) then
			local Head = light:WaitForChild("Head")
			Head:WaitForChild("Filter"):WaitForChild("SurfaceLight").Enabled = true
			Head:WaitForChild("B"):WaitForChild("Beam").Enabled = true	
			Head:WaitForChild("Light").Material = Enum.Material.Neon	
		else
			errors(light.Name .. " is not a valid OQUO lighting kit")
		end
	end
end

function OQUO:Off()
	for _,light in ipairs(self) do
		if check(light) then
			local Head = light:WaitForChild("Head")
			Head:WaitForChild("Filter"):WaitForChild("SurfaceLight").Enabled = false
			Head:WaitForChild("B"):WaitForChild("Beam").Enabled = false	
			Head:WaitForChild("Light").Material = Enum.Material.Metal	
		else
			errors(light.Name .. " is not a valid OQUO lighting kit")
		end
	end
end

function OQUO:Color(color)
	for _,light in ipairs(self) do
		if check(light) then
			local Head = light:WaitForChild("Head")
			Head:WaitForChild("Filter"):WaitForChild("SurfaceLight").Color = color
			Head:WaitForChild("B"):WaitForChild("Beam").Color = ColorSequence.new(color)	
		else
			errors(light.Name .. " is not a valid OQUO lighting kit")
		end
	end	
end

function OQUO.RandomLight()
	local chosenlight = alllighting[math.random(1, #alllighting)]
	local info = {chosenlight}
	setmetatable(info, OQUO)
	return info
end

function OQUO:Brightness(value)
	for _,light in ipairs(self) do
		if check(light) then
			local Head = light:WaitForChild("Head")
			Head:WaitForChild("B"):WaitForChild("Beam").Transparency = NumberSequence.new(value, value)	
		else
			errors(light.Name .. " is not a valid OQUO lighting kit")
		end
	end	
end

return OQUO

the lines I am focusing on are the .new and randomlight. As you see I currentyl just copy and pasted what was in .new however I would rather just use the function within the module. How would I accomplish this?

Basically it’s like what you say here - you can just use the function and it’ll work the same. So tihs would be your randomlight function:

	local chosenlight = alllighting[math.random(1, #alllighting)]
	return OQUO.new({chosenlight})

And because the new does the same things as you had pasted in the function, you’ll get the same result.

1 Like

I know I get the same result I just feel it is more efficient to do the function inside of the module so if I were to make changed to the .new function itself I don’t need to change both.

oh nvm I see

Yeah, but basically you can do that - there’s no difference between the .new here vs. any other function. So all you’d need to do is call the .new() from inside your other function & it’ll work how you want it to.

Using a module’s function inside of the module is as simple as this.

local f = {}

function f:MPLY(x1, x2)
	return x1 * x2
end

function f:PR()
	local i = f:MPLY(5, 9)
	print(i)
end

return f

All you need to do is specify what function you want to use from the table. The same way you’d use functions stored in a table from a normal script.

2 Likes

Oh dear, that is a painful amount of nested if statements. Sorry to turn this into a code review, but there’s a lot that’s bugging me about your code. Mostly just stupid optimisations and overwriting bad practice in your code, but please have a look anyway.

-- In regards to your colour strings
local colorstrings = {
    ["red"] = Color3.fromRGB(255, 0, 0),
}

-- In regards to the GetColor function
function OQUO:GetColor(color)
    local colorstring = tostring(color:lower())
    return colorstrings[colorstring] or Color3.fromRGB(255, 255, 255)
end

-- In regards to function check
local function check(light)
    return light:lower():sub(1, 6) == "parcan"
end

-- In regards to class instantiator (which is actually just a table wrapper)
function OQUO.new(infotable)
    return setmetatable(infotable, OQUO)
end

-- In regards to On/Off
local function SetLightsEnabled(bool)
    for _, light in pairs(self) do
        -- sorry, was too lazy to copy/paste/rewrite in here
        -- uses bool to determine state of properties
        -- i.e. material = (bool == true and "Neon" or "SmoothPlastic")
        -- ^ use their enums
    end
end

function OQUO:On()
    SetLightsEnabled(true)
end

function OQUO:Off()
    SetLightsEnabled(false)
end

Aside from my ramblings, using functions from a ModuleScript is simple, as the people above said. So long as you return your main table that represents your class, you’re fine.

local Class = {}
Class.__index = Class

-- whatever

return Class

-- elsewhere:
Class:Method()
Class.Method()

Just be wary of how you use dot and colon syntax, because that matters. Colon syntax automatically passes the variable the method was ran from as the first argument, self. Dot syntax doesn’t pass any arguments automatically and is more tuned for indexing.

Fun fact: this also applies to service methods.

local Players = game:GetService("Players")

-- GetPlayerFromCharacter, Colon/standard syntax
Players:GetPlayerFromCharacter(someArg) --> passes Players (self), someArg

-- GetPlayerFromCharacter, Dot syntax
Players.GetPlayerFromCharacter(Players, someArg) --> passes Players, someArg
10 Likes

I love the critisism! I thank you so much as this will help me greatly on becoming an even better developer!

5 Likes