Skip to content

Add Custom Consul scripts ​

This guide is the simplest flow to add one custom Consul script.

Before You Start ​

If you don't have make installed, follow the setup steps in Build from source.

Step 1) Add the Consul UI entry ​

Run this once per game; if your script supports both games, run it two times (GAME=Attila and GAME=Rome2). This make target will generate the required UI files

bash
make GAME=Attila insert-consul-entry \
  ARG1='consul_my_feature' \
  ARG2='Your tooltip description.' \
  ARG3='Your Latin Name'

Step 2) Edit src/consul/consul.lua ​

In this example, you create a create_two_faction_script and wire it to UI. Edit these exact anchors:
consul.ui = {}
consul.consul_scripts_v2.initialize()
consul.consul_scripts.OnComponentLClickUp() - click_map.

lua
-- 1) consul.ui = { ... }
consul.ui = {
    -- ...existing keys...
    consul_my_feature_entry = "consul_my_feature_entry",
    consul_my_feature_script = "consul_my_feature_script",
}

-- 2) consul.consul_scripts_v2.initialize() for a two-faction action
scripts.instances["my_feature"] = scripts.create_two_faction_script(
    "my_feature",
    function(faction1, faction2)
        consul._game():force_make_peace(faction1, faction2)
    end,
    "Forcing peace between"
)

-- 3) consul.consul_scripts.OnComponentLClickUp -> click_map (same for both)
local click_map = {
    -- ...existing entries...
    [ui.consul_my_feature_entry] = {
      script = scripts2.instances.my_feature,
      component = ui.consul_my_feature_script,
      log_msg = "Clicked on consul_my_feature"
  }
}

Step 2.1) If you need advanced custom logic ​

create_two_faction_script(...) returns a script object with setup(), start(), and stop(); use helpers for common patterns, and write a custom object when you need multi-step or special behavior.

lua
-- A) custom script object in consul.consul_scripts
consul.consul_scripts.my_feature = {
    
    -- 1. Setup is executed only once, when the mod loads for the first  time.
    setup = function()
        local scripts = consul.consul_scripts
        
        -- Ensure the event handler tables exist 
        -- before trying to assign keys inside them
        scripts.event_handlers['SomeGameEvent'] =
            scripts.event_handlers['SomeGameEvent'] or {}
            
        scripts.event_handlers['SettlementSelected'] = 
            scripts.event_handlers['SettlementSelected'] or {}
        
        -- Clear any existing handlers for this feature to ensure a clean state
        scripts.event_handlers['SomeGameEvent']['my_feature'] = nil
        scripts.event_handlers['SettlementSelected']['my_feature'] = nil
    end,
    
    -- 2. Triggered when the Consul menu entry is selected (highlighted green).
    start = function()
        local scripts = consul.consul_scripts
        
        scripts.event_handlers['SomeGameEvent']['my_feature'] = 
        function(context)
            if not context:character():faction():is_human() then return end
        end

        scripts.event_handlers['SettlementSelected']['my_feature'] = 
        function(context)
            -- your action here
        end
    end,
    
    -- 3. Triggered when the entry is deselected (no longer green). 
    stop = function()
        local scripts = consul.consul_scripts
        
        -- We set these to nil to stop listening to the events.
        scripts.event_handlers['SomeGameEvent']['my_feature'] = nil
        scripts.event_handlers['SettlementSelected']['my_feature'] = nil
    end
}

-- B) wire it in consul.consul_scripts.OnComponentLClickUp() -> click_map
local click_map = {
    -- ...existing entries...
    [ui.consul_my_feature_entry] = {
        script = scripts.my_feature,
        component = ui.consul_my_feature_script,
        log_msg = "Clicked on consul_my_feature"
    }
}

Step 3) Regenerate docs ​

Run this after adding or renaming a script entry.

bash
py ./scripts/generate_consul_scripts_docs.py

Step 4) Optional: Submit Changes ​

If you want to share your script in the main repo, open a pull request on GitHub:

Released under the GPL-3.0 license.