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.

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:
- Check if the required plugin actually exists, i.e. is in the plugins folder.
- If it does, check if it’s already loaded.
- 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()