I need to make a roblox ability system
Basically, there are a bunch of abilities in game.ReplicatedStorage.Abilities
They are modules and all of them have a function called:
Activate
Deactivate
Cancel
Passive

Deactivate and Cancel might not always be used, but Activate is always used.

The ability is used from the client and detects when the player presses F, Deactivate happens when the player lets go of F, Cancel is usually called from a different script, the client doesn't have control over it.

The client sends a signal to the server (server script) that checks the players equipped ability, and then activates the ability or deactivates it based off of the button that was pressed or let go.

The client should detect a keybind, that keybind can be changed by game settings, so after this is done, also create a small system that can change keybinds and detect changes from the client, the client is the one who changes and detects.

Every single available ability is in game.ReplicatedStorage.Abilities, and they are modules and they all have the name "AbilityModule".

Every module has a few attributes inside of them:
Name -- String, the name of the ability
Description -- String, the description of the ability
Power -- Number, The power rating of the ability, basically how powerful/OP it is
Price -- Number, The price of it, this is in a leaderstat called "Bricks" by default, if UseCinderblocks is true then it uses a leaderstat called "Cinderblocks"
Rarity -- Number, The rarity number of t
Level --  Number, The level of the ability, this is always set to 1 if Upgradable is false
Upgradable -- Bool, if the ability is upgrdable
UseCinderblocks -- If the ability costs Cinderblocks
Passive -- Bool, if the ability is always active and passive

The way a player equips an ability is by cloning one of the AbilityModules from a folder called "OwnedAbilities", the Owned abilities folder is inside of the player instance and parenting it into the player instance in game.Players, it is cloned from the server.
Only one remote event is used for equipping, it is "EquipAbility" and the parameters are:
EquipAbility:FireServer(abilityname)

The server checks if the player owns the ability by looking for the module the player is requesting inside of OwnedAbilities, if no ability is found, they don't own it.

When a player does equip a module and they own it, then anytime the player presses the ability keybind from the client, the server calls the Activate function from the equipped ability.

If the player lets go of the keybind then Deactivate is called, there might not be anything inside of the function though.

However, some abilities are passive and always happen, for this, when the ability is equipped (and cloned and stuff) then another function called "Passive" is called, but only if a attribute inside of the module named "Passive" is true.

If another module is already equipped and another one is equipped, then the game deletes the previously equipped one.

Key features:

Use minimal remote events
Compact writing
Be efficient
Highly, highly, HIGHLY modular and versatile
To add a new ability just clone a module and edit it and change the attributes

Use a special datastore method to find already owned modules, when a player joins, find their owned modules by name, and any modules they own, the server finds it in the Abilities folder by the attribute name, if it exists then the module is cloned into the OwnedAbilities folder inside of the player instance, then the server needs to also find the last ability they had equipped, and then find the ability in the owned abilities, if it's found, clone it and put it in the player instance itself.
With that datastore, it saves the owned abilities and the ability last equipped when the player leaves, and when the player joins it loads the owned abilities and the last ability the player equipped.

This is a highly advanced system, I need you to use 100% of your brain power on it.