# Create Add-ons

## How it works

Any add-on uses this format: ![](https://3676259257-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVUU2n77rqU9V23f4W1Tt%2Fuploads%2FcXBnomGtucQ6Xe8570nG%2FAddonFormat.png?alt=media\&token=7a0dfe3e-3c07-49e7-8406-37b1a546f764)\
`CoolAddon` is the module that will only run in the plugin.\
`game` module will be synced to game-module's add-ons folder\
\
![](https://3676259257-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVUU2n77rqU9V23f4W1Tt%2Fuploads%2FSszb4fj0gNScz1Ckd8ng%2Fimage.png?alt=media\&token=28f93cfa-a8db-4bbb-be83-efaf1d456ab8)\
\
`CoolAddon` will use the ui-library to make ui and should return a table like this:

```luau
return {
	api = gameapi, -- require(script.game)
	name = "Screen effects",
	icon = 97990680261359,
	description = [[
		- ImpactFrames (CCE)
		- CameraShake (with presets)
		- Camera weld (VFX on screen)
		ImpactFrames emit others enable
	]],
	uninstall = function()
		-- optional
	end
}
```

Which will show this in **Manage Add-ons**:

<div align="left"><figure><img src="https://3676259257-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVUU2n77rqU9V23f4W1Tt%2Fuploads%2FIGvjhoPrRtb9CDcl6zNP%2Fimage.png?alt=media&#x26;token=c2a8033c-f0c8-4947-b864-7d2a6560f91c" alt=""><figcaption></figcaption></figure></div>

`game` module can return anything, and whatever it returns will be put in the API\
ex: `return { customFunc = function() }` will be `shared.fx.CoolAddon.customFunc()`\
also it will be renamed to `CoolAddon` when put under `ReplicatedStorage.vfx.addons`:\
![](https://3676259257-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVUU2n77rqU9V23f4W1Tt%2Fuploads%2F1kOEy7xINqYouCZBQBZN%2Fimage.png?alt=media\&token=8d498d53-377f-4bf6-91c5-e580e2d091b0)

The main function `game` module should use most is THIS:

```luau
shared.fx.api.add {
    emit = function(vfx, attributes, ..),
    enable = function(vfx, attributes, ..),
    disable = function(vfx, attributes, ..),

    retime = function(vfx, timeScale, origins),
    rescale = function(vfx, sizeScale, origins),
    recolor = function(vfx, hue, sat, lightness, origins)
    
    selector = ".Tag,[$Attribute]" -- :QueryDescendants(selector)
} -- everything here is optional
```

`emit` happens with `.emit(vfx)` and with Emit button in plugin (same for `enable` and `disable`)\
`retime`, `rescale`, and `recolor` happen with module's functions too (AND plugin sliders!!!!!1)\
so everything here is used in-game (with funcs like `.recolor()`) and in plugin with Sliders!!

## Installation

Add-ons can be installed by clicking the ![](https://3676259257-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVUU2n77rqU9V23f4W1Tt%2Fuploads%2F5xJv5gG2cD7MWDnOTNjp%2Fimage.png?alt=media\&token=6aacd800-59ec-4439-bfc1-33f9bb825b27) button in **Manage Add-ons**\
Or with a shortcut for quick reinstalling when debugging/developing an add-on

<div align="left"><figure><img src="https://3676259257-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVUU2n77rqU9V23f4W1Tt%2Fuploads%2FkU0Qyqt8pXw9jtnQbQd1%2Fimage.png?alt=media&#x26;token=4b2b4fbb-4fce-4ca5-b9f4-1ebb704eae28" alt=""><figcaption></figcaption></figure></div>

## Debugging

To easily make, edit, and debug add-ons, they will be placed in `ServerStorage.vfx_addons`\
That folder is made and reserved by the plugin to store add-ons in the place (for debugging & more)\
Errors, warnings, and prints will point to the script in `vfx_addons` even if the add-on is published\
\
Add-ons are automatically uninstalled when they error or take too long to return.\
When an add-on is uninstalled, all connections and objects it created are cleaned up-\
except things made independently, which should be cleaned up by the custom `uninstall` function

## Limitations

1. Add-ons must return in max 2 seconds\
   (*this is to make sure the game-module loads fast in-game)*
2. Add-ons can only have classes `ModuleScript` and `Folder`\
   \&#xNAN;*(it will support all types of instances soon since roblox released* [*ReflectionService*](https://create.roblox.com/docs/reference/engine/classes/ReflectionService)*)*
3. Add-ons in-game can't be uninstalled like in plugin<br>

{% hint style="info" %}
You can use task.spawn to not yield the main thread if you need more time than 2s
{% endhint %}

## Publishing

Add-ons can be published so anyone with the plugin can install and use them

You can choose to make your add-on open-source where anyone can get the source and edit-\
by clicking this ![](https://3676259257-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVUU2n77rqU9V23f4W1Tt%2Fuploads%2Fr3WJ0lZGkyYbkpUNNDtX%2Fimage.png?alt=media\&token=df70a052-37d5-4a44-bcfb-0804870318be) or choose not to. but the `game` module will be exposed to be used in games.

You can also make a license/terms that user must agree upon to install your add-on, like this:

```luau
local agreed = shared.fx.ui.okPopup("title", "terms here", "i agree to the terms")
-- this can be even used in the command bar
```

This is done using the `canInstall` callback, which will only allow installing if it returns `true`\
It can also be used to make add-ons **paid** by checking if user owns a gamepass or through http

## How to start

Start by reading an open-source add-on as a template, then add your own functionality, or-\
by reading the ui-library document and learn how to make UI like a properties UI for your add-on
