OOP / Self in Tables?

Why not use two different modules for Camera and Background and put them under the framework module? I think that would solve it.

2 Likes

solution ^

Sorry!

So I have one initial Module script: Util that requires others and allows them to communicate with each other - They’re stored within the same ‘self’ so it’s simple to call another function.

Heirarchy as:

Util

Camera
Background
Teleport
Transition

The Util requires the modules below and creates a table for them within a self.
So say like self.Camera = {} then within the Camera module is self.Camera:Enable()

There shouldn’t be any conflicts unless the functions were all stored in the same table

They are two different modules :confused: That’s the issue.
They both have the same function name as :Indoor() - However one is:
self.Camera:Indoor() and the other is self.Background:Indoor() however they both seem to overwrite eachother despite being two different tables.

This is a pretty good tutorial that explains inheritance (what you’re trying to do)

They’re not doing inheritance though, they’re all separate

Because you’re indexing both tables into self, and they become the same table

Hold on just booted my PC.

So this is the main util:

	local Core = { ... }
	local Server, Script = game, script
	
	self = {}
	self.__index = self
	
	self.Player = Server:GetService('Players').LocalPlayer
	self.Character = self.Player.Character or self.Player.CharacterAdded:Wait(2)
	self.Player.CharacterAdded:Connect(function(Character, ...)
		self.Character = Character
	end)
	
	for __,Module in (Script:GetChildren(...)) do
		if Module:IsA('ModuleScript') then
			self[Module.Name] = setmetatable(self, {})
			require(Module):init(self, ...)
		end
	end
	
	self.Camera:Enable(...)
	self.Chunk:Load("Ol' Oak Village", ...)
	
	return Core

and for an example this is the Camera (Doesn’t include the indoor function on this version.)

	local Core = { ... }
	local Server, Script = game, script
	
	function Core:init(__index, ...)
		self = __index
		
		local Camera = Server:GetService('Workspace'):WaitForChild('Camera')
		
		local Connection = nil
		local Offset = Vector3.new(0, 20, -15)
		local Shake = Vector2.new(0, 0)
		
		function self.Camera:Enable(...)
			Camera.CameraType = Enum.CameraType.Scriptable
			Connection = Server:GetService('RunService').PreRender:Connect(function(...)
				local HumanoidRootPart = self.Character:FindFirstChild('HumanoidRootPart')
				if HumanoidRootPart then
					Camera.CFrame = CFrame.lookAt((HumanoidRootPart.Position + Offset) + Vector3.new(Shake.X, Shake.Y, 0), HumanoidRootPart.Position + Vector3.new(Shake.X, Shake.Y, 0))
				end
			end)
		end
		
		function self.Camera:Disable(...)
			pcall(function(...)
				Connection:Disconnect(...)
				Camera.CameraType = Enum.CameraType.Custom
				Offset = Vector3.new(0, 20, -15)
				Shake = Vector2.new(0, 0)
			end)
		end
		
		function self.Camera:Shake(int, Time, ...)
			for i = 1, Time do
				task.wait(...)
				Shake = Vector2.new(math.random(-int, int)/10, math.random(-int, int)/10)
			end
			Shake = Vector2.new(0, 0, 0)
		end
		
		self.Player.Chatted:Connect(function(Msg, ...)
			if Msg == '/shake' then
				self.Camera:Shake(10, 100, ...)
			end
		end)
	end
	
	return Core

They are though, it’s what they’re trying to achieve with the structure they explained

The issue is that the : symbol means that the argument self is passed in(the one you define at the top), and both functions have that so they use the same copy of self, this is definitely one of the reasons this override occurs. Basically self.Camera:Indoor() and self.Background:Indoor() don’t use self.Camera and self.Background respectively, they use self.

2 Likes

Why are you setting the metatable to the util module?

2 Likes

That was the only way I could make the ‘self’ work with the others - Without the metatable it returned nil.

Shouldn’t this just be a simple loop or are you like creating a new object from the util module

1 Like

I mean different actual modules(not tables within a module), with different self and different self.__index each. Basically different objects that have a relationship with the framework(they get required by it).

1 Like

Are you trying to do something like this? Where for example, toolHandler is the “main” module and then crossbow is a tool you can use. And you can make more tools while using the same :activated() function for example set in the crossbow module?

–Main module

local ToolHandler = {}
ToolHandler.__index = ToolHandler

local Players = game:GetService("Players")
local localPlayer = Players.LocalPlayer

local dependencyModules = {
	Crossbow = script.Crossbow,
	Sword = script.Sword,
}

ToolHandler.new = function(tool : string)
    local self = setmetatable({}, ToolHandler)

	self.name = tool
    self.particleEmitters = {}
    self.character = localPlayer.Character
    self.humanoid = localPlayer.Character.Humanoid

	self:start()
	return self
end

function ToolHandler:start()
	print("load stuff like activated, unequip and equip connections")
end

function ToolHandler:usedTool(amount : number)
	print("tool used")
end

ToolHandler.init = function()
	for _, instance in dependencyModules do
		if instance:IsA("ModuleScript") then
			dependencyModules[instance.Name] = require(instance)
			dependencyModules[instance.Name].init()
		end
	end
end

return ToolHandler

Tool example using crossbow

local Crossbow = {}
Crossbow.__index = Crossbow

local ToolHandler = require(script.Parent)

Crossbow.new = function(tool)
	local self = ToolHandler.new(tool)
	setmetatable(self, Crossbow)
	self.timeout = 3

	return self
end

function Crossbow:activated()
	print("activated")
end

function Crossbow:equip()
	print("equip")
end

function Crossbow:unequip()
	print("unequip")
end

function Crossbow.init()
	setmetatable(Crossbow, ToolHandler)
end

return Crossbow
1 Like

I think I’ve fixed it by adjusting the Function from self.Camera:Indoor() to self.Camera.Indoor = function()?

The only change that made is that it doesn’t use the self on the top of your first code example. So that plays a role here. Basically what you did made the function equivalent to self.Camera.Indoor() instead of self.Camera:Indoor() that uses self. Using self means that self.Camera:Indoor() is equal to self.Camera.Indoor(self, ...) meaning that self is passed in as the first function argument.

1 Like

They’re showing as within their respective folders now and not seeming to overwrite eachother? Still accessing the initial ‘self’?

Before that the self of the function was overriding the self on the top of your code due to the self argument being a local variable within the function instead of a global one, so it has priority.

If you change your main self name to something like framework you should be able to access both of them within the function.