Object Oriented Abilities, how?

Hi, how would one go about making an ability based system with OOP? For example, lets say you got the “Default” ability as a module script that is made of multiple sub modules ( components ), you want that ability to be triggered user input based, how would you guys go about it while also making it safe and efficient to make other abilities?

updated summary:Object Oriented Abilities, how? - #19 by Teryjaki20

1 Like

The main issue I’m having is handling remote traffic relative to that module script, considering that the ability is gained with requiring the ability on the client.

For several weapon systems, I put a settings module in each weapon, and didn’t but should’ve added a function in a “settings” module for each weapon that will find a setting. If the setting does not exist, it will take it from a settings module with all the settings.

Then, I have a weapon system that clones the script to each weapon.

So, that is not object oriented. If I were to make it again, I would add something like this into my code:

local construct = {}
function construct.new(...)
return {...}
end
function construct:SetValues(self, i, v)
for _, obj in pairs(self) do
self[i] = v
end
end
function construct:ValueExists(self, i)
--Return the value if it exists
for index, value in pairs(self) do
if index == i then
return value
end
end
end

This is something I just wrote right here, a utility for editing tables.

What I’m really interested in is this:

Consider the components:

  • push

With the components I would make an ability named “Default”

local Default = {}

local components = {
	["Push"] = nil -- this is just an example
}
Default.__index = Default

Default.New = function(Power)
	local Def = table.pack()
	setmetatable(Def, Default)
	
	Def.Power = Power
	Def.Push = components.Push
	
	return Def
end

Default.Initpush = function(self)
	-- lets say i want to have a remote here, to handle the push, how would i get the client input, make things work?
end
return Default

What I’ve considered is making the input in the components themselves, but I don’t think it’s the right approach, I want everything to be exploiter free, or at least the important stuff like Power that determines the push distance.

Well, I was forced to make some modules client and server compatible. To do this, I would have to use RunService to detect if the script is on the client or server.

Then, you would have to implement this into the initpush function. I would look for an event and connect it to the initpush function.

So, I tried sending the whole module, which did not work, because you cannot send the whole module to the client while doing so, as functions do not send through remotes (probably for security reasons) so you will have to have the module on both the client and server.

I’m sure that this is possible but I’m not too experienced in OOP so I can’t really help with coding it, but I can always make suggestions and ideas.

And I agree with that.

Could you please give me an example of this, doesn’t need to be OOP just a sample, so I can have an understanding, thank you.

So, RunService has many different functions you can use to find out what you’re running.

RunService:IsClient() will return a Boolean determining if the current script is executing from a client.

RunService:IsServer() will return the opposite value.

There’s also RunService:IsStudio()

But implementing these functions in completely object-oriented code will be easy to impossible depending on what you want to do with them.

But I do not really understand how a client required script can be also a server, I don’t understand the way of making it on the server too.

And even if its possible, how would i link everything up?

I know for sure that there’s no rule saying you cannot require a module from the client and server, because I have done that about 3 times before I assume.

I think it is possible, but you would have to add many or and and statements to filter out the OOP with the IsClient boolean value you got, and what to fire. However, this is very hard to do without the help of loadstring, but I would not recommend using that. You can require another module that is specific to the server/client from the module you are currently using, which has the functions you desire for that specific platform. Then, you can add a “Default” module consisting of functions that run on the client and server.

I personally would do it with a main Abilities module that creates a “controller” object for a player on the server, then maybe functions for loading and unloading certain abilities, and each ability has it own object with an Activate function.

idk really how to explain it better tho.

1 Like

Can you give some code example?

But I kinda understand what you mean, but wouldn’t this require me to link everything to a superclass so i could access the values?

1 Like

Sounds kinda like ECS, not exactly OOP but that debate is for software engineers and architects.

As long as it’s componentalized so that you can modularize it and drag and drop it wherever server or client or even shared between, that’s what matters for code organization.

But yeah this is how I organize my code now:

1 Like

The issue summary is basically how would i go about making a client have an ability “equipped” so input results will be relative to that, thats my actual question.

For this just have one input handler system on the client.

And a way to store dictionary to key to event

{[Enum.KeyCode.W] = "Default" }

Or the other way around

{Default = {W, A, S, D}}

Manipulate this dictionary data based on your equip system.

Detect using UIS or CAS fire event.

In the server loop through the Server components or shared components that belong to default.

Another dictionary

{"Default" = {PushComponent, Damage component, HitboxComponent} }

Then do stuff based on the components given that you want for only the server to do like knockback or damage, clients will only get visual effects components or UI components.

ECS system is there to help detect the components and automatically execute code based on that. (Separate the Data from the actual functions.)

Imagine this:
default is a module script in replicated storage
the player owns the default module (bought it)
he equips it (if he clicks, he will push with it, with the respective power of the hand that he was equipped) - How would i do this?

@dthecoolest @SubtotalAnt8185 @PostVivic

Well, you can have some scripts in the equipped tool that will require the default module and look for custom settings in other modules.