---
title: Creating Plugins
description: "Plugins are tools and assist scripts that are designed to add features to gw2cc and do not take full control of the client, in contrast to bots. Plugins **must**be located in the `plugins/` folder. The name of the plugin is…"
url: "https://gw2cc.eu/docs/plugins/"
updated: "2025-07-29"
category: Developer Guide
---

# Creating Plugins

Plugins are tools and assist scripts that are designed to add features to gw2cc and do not take full control of the client, in contrast to bots.

Plugins **must**be located in the `plugins/` folder. The name of the plugin is defined by the name set in the `MetaInfo.tres` file. To get started, simply use the built in Mod Wizard, which will set up all needed Files for you.

![](https://i0.wp.com/gw2cc.eu/wp-content/uploads/image-24.png?resize=687%2C374&ssl=1)

### Loading Plugins

Plugins can either be **enabled**or **disabled**as indicated by the checkbox in the plugin menu. If enabled, the PluginManager will try to auto-load the plugin on every scene change.

For this, the PluginManager checks the MetaInfo.tres if a `[SceneName].tscn` file exists, where `[SceneName]` is a placeholder for the name of the current scene (e.g. `Ingame.tscn` for the main ingame scene). If found, the manager will instantiate the packed scene and append the plugin node to the SceneTree. At the end of a scene, plugin nodes are automatically unloaded again. This, in particular, also happens if you switch maps!

As a consequence of these designs, the correct place to perform initialization is`_ready()`, while `_exit_tree()` is the proper place to perform cleanup. Furthermore, plugins need to make sure to save and restore state respectively in these methods if they want it to persist across scene changes.

### Voluntary Unloading

A plugin can decide at any point to unload itself, for instance because a critical error occurred, or because certain preconditions are missing (e.g. because a character has an incompatible class). Usually this will happen during startup, i.e. during `_ready()`. To unload oneself, simply call the `PluginManager.unload_plugin(PLUGIN_NAME)` function. If you do so, you should always make sure to add a reason via the `warning()` or`error()`method of `ScopedLogger` beforehand so that the users can understand why a plugin has been unloaded.

```
const PLUGIN_NAME = preload("../MetaInfo.tres").product_name
var _logger = ScopedLogger.create(PLUGIN_NAME)

func _ready():
	Manager.agent.controlled_character_spawned.connect(_on_controlled_character_spawned, CONNECT_ONE_SHOT)

func _on_controlled_character_spawned(cc: AgentChar):
	if not cc.has_component(ProfessionElementalist):
		_logger.error("This plugin is only available for Elementalist characters")
		PluginManager.unload_plugin(PLUGIN_NAME)
		return
```

You should also make use of this option, if your plugin only works in either standalone or attached mode but not in both.

### Dependencies

Plugins can depend on other plugins for functionality, either optionally or necessarily. To do so, developers should use the PluginManager directly to manually load a dependency if needed. In total 3 steps need to be performed for this:

1. Check if the required plugin actually exists, i.e. is in the plugins folder.
2. If it does, check if it's already loaded.
3. If not, try to load it. If this step fails; a plugin can decide on its own if it wants to stay loaded or if it wants to unload itself with an error.

All together, this could for instance look like this:

```
func _ready():
	var DPSMeter_available = PluginManager.available_plugins.get("DPSMeter")

	if not DPSMeter_available: # Step 1
		_logger.critical("This plugin requires the DPSMeter plugin to work. Please visit the gw2cc store to obtain a copy.")
		return
	var DPSMeter_loaded = PluginManager.loaded_plugins.get("DPSMeter")
	if not DPSMeter_loaded and not PluginManager.load_plugin("DPSMeter"): # Step 2 and 3
		_logger.critical("Failed to load the DPSMeter plugin.")  # use warning() here instead, if it's only an optional dependency
		PluginManager.unload_plugin(PLUGIN_NAME) # unload self, since we cant run without DPSMeter

	_logger.info("Dependency: DPSMeter loaded")
	# We can access the loaded dependency via the PluginManager
	var DPSMeter = PluginManager.loaded_plugins.get("DPSMeter")
	DPSMeter.show_damage()
```
