Question regarding OOP

  1. What do you want to achieve?

I’m trying to make a Tycoon from B Ricey’s tutorial series.

B Ricey’s Tutorial Series Episode 3

  1. What is the issue?

The problem is that I don’t understand a majority of the code but this a certain part of his code that’s confusing me.

Unlockables
local Unlockable = {}
Unlockable.__index = Unlockable

function Unlockable.new(tycoon, instance)
	local self = setmetatable({},Unlockable)
	self.Tycoon = tycoon
	self.Instance = instance
	return self
end

function Unlockable:Init()
	self.Subscription = self.Tycoon:SubscribeTopic("Button", function(...)
		self:OnButtonPressed(...)
	end)
end

function Unlockable:OnButtonPressed(id)
	if id == self.Instance:GetAttribute("UnlockId") then
		self.Tycoon:Unlock(self.Instance,id)
		self.Subscription:Disconnect()
	end
end

return Unlockable

Main Tycoon Module
local CS = game:GetService("CollectionService")

local template = game:GetService("ServerStorage").Template
local components = script.Parent.Components
local tycoonStorage = game:GetService("ServerStorage").TycoonStorage


local function newmodel(model, vector)
	local newModel = model:Clone()
	newModel.Parent = workspace
	newModel:MoveTo(vector)
	return newModel
end


local Tycoon = {}
Tycoon.__index = Tycoon

function Tycoon.new(player)
	local self = setmetatable({},Tycoon)
	self.Owner = player
	
	self._topicEvent = Instance.new("BindableEvent")
	return self
end

function Tycoon:Init()
	self.Model = newmodel(template, Vector3.new(0,1,0))
	
	self:LockAll()
end

function Tycoon:Lock(instance)
	instance.Parent = tycoonStorage
	self:CreateComponent(instance,components.Unlockable)
end

function Tycoon:Unlock(instance, id)
	CS:RemoveTag(instance, "Unlockable")
	self:AddComponents(instance)
	instance.Parent = self.Model
end

function Tycoon:LockAll()
	for _,instance in ipairs(self.Model:GetDescendants()) do
		if CS:HasTag(instance, "Unlockable") then
			self:Lock(instance)
		else
			self:AddComponents(instance)
		end
	end
end

function Tycoon:AddComponents(instance)
	for _,v in ipairs(CS:GetTags(instance)) do
		local component = components:FindFirstChild(v)
		if component then
			self:CreateComponent(instance, component)
		end
	end
end

function Tycoon:CreateComponent(instance,componentscript)
	local compmodule = require(componentscript)
	local newcomp = compmodule.new(self, instance)
	newcomp:Init()
end

function Tycoon:PublishTopic(topicName,...)
	self._topicEvent:Fire(topicName,...)
end

function Tycoon:SubscribeTopic(topicName, callback)
	local connection = self._topicEvent.Event:Connect(function(name,...)
		if name == topicName then
			callback(...)
		end
	end)
	return connection
end

function Tycoon:Destroy()
	self.Model:Destroy()
	self._topicEvent:Destroy()
end

return Tycoon

To dim down the confusion I’ll show my “specific problem” below:

Main issues
function Tycoon:SubscribeTopic(topicName, callback)
	local connection = self._topicEvent.Event:Connect(function(name,...)
		if name == topicName then
			callback(...)
		end
	end)
	return connection
end
function Unlockable:Init()
	self.Subscription = self.Tycoon:SubscribeTopic("Button", function(...)
		self:OnButtonPressed(...)
	end)
end

How do these subscribetopic functions relate to each other? Are they in some way related? If so what is connecting them?

  1. What solutions have you tried so far?

I don’t know what solutions to try because this code is extremely specific.

If I’m following the code right it seems to connect the topicevent when a tycoon is unlockable (which I assume means when the game first opens or when a player leaves or wants to do a different tycoon).

function Unlockable:Init()
	self.Subscription = self.Tycoon:SubscribeTopic("Button", function(...) -- "Button is the name of the event (aka. topic)
		self:OnButtonPressed(...)
	end)
end

Init stands for “Initilization” which is usually the start of the module script and its code running. The code above basically is connecting the function below (“OnButtonpressed”) to a button

function Unlockable:OnButtonPressed(id)
	if id == self.Instance:GetAttribute("UnlockId") then
		self.Tycoon:Unlock(self.Instance,id)
		self.Subscription:Disconnect()
	end
end

This is just how they label the topics (btw topics are events from my understanding) so it seems this is connecting custom events and if you are wondering what callback think of it as the function thats being called on these events and the three dots means there can be a bunch of different variables.

function Tycoon:SubscribeTopic(topicName, callback)
	local connection = self._topicEvent.Event:Connect(function(name,...)
		if name == topicName then
			callback(...)
		end
	end)
	return connection
end

Now this may be wrong, I’d have to see more code since I work with OOP but I haven’t done stuff like this with events (or topics is what they’re calling it)

1 Like

I think this is happening because of the component organization system he made on his 2nd episode where he’s basically interconnecting or associating tables with the Tycoon table. That’s why in the .new() he’s using the parameters tycoon and instance which comes from addcomponents which then goes to createcomponent which sends the parameters self and instance. Exactly what every .new has.

I don’t know why he’s using ellipses though, what the callback parameter is, and how the bindable event works.

Yeah I’d have to see the componet module but if you get confused basically all the topics are doing is connecting functions to bindable events but only using one bindable event so he doesn’t have to make a ton.

function Tycoon.new(player)
	local self = setmetatable({},Tycoon)
	self.Owner = player
	
	self._topicEvent = Instance.new("BindableEvent") -- Here's the bindable event he's using called topicevent
	return self
end
1 Like

What would be the difference if he went about not using a bindable event?

Well, instead of using bindable events you could technically have a CollectionService tag the buttons you want and loop through those tags and connect the button event to them. For example,

This is one of my property/tycoon mock ups - pretty messy since this was code was from one of my first time using something like OOP. but the code shows how I connected anything with the access tag to have a .touched event, I guess you could do the same thing with the buttons instead of doing bindables.

function PropertyManager.Setup()
	for _, inst: BasePart in (CollectionService:GetTagged("Access")) do
		inst.Touched:Connect(function(hit: BasePart)
			if hit and hit.Parent then
				local char: Instance = hit.Parent
				if char:FindFirstChild("Humanoid") then
					local player = Players:GetPlayerFromCharacter(char)
					if not PropertyManager.PropertiesMade[player] then
						local prop: Instance? = inst.Parent
						PropertyManager.PropertiesMade[player] = PropertyModule.new(prop, inst)
						PropertyManager.PropertiesMade[player]:GiveOwnership(player)
			
						PropertyManager.SetupUpgrades(player)
						Disappear(inst, false, 1, false)
					
					end
				end
			end
		end)
	end
end
1 Like

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