Introduction

Welcome to the Gremlin Scripts Collection documentation!

Gremlin Scripts Collection Logo

You can learn how to use all of the Gremlin Scripts by using the table of contents to the left.

Gremlin (Core)

Welcome to the Gremlin documentation! We're still building most of this out, so there will be some rough edges, but hopefully you'll be up and running in no time with whichever Gremlin Scripts you end up using in your own missions!

Gremlin is a framework for building these scripts around, so it doesn't do much on its own. Still, in case it proves useful for your own scripts, we've documented it anyway. Enjoy!

Setup

First, you need to add MiST to your mission. Follow its instructions to do this.

Next, copy the contents of Gremlin Scripts' src/ directory to your missions folder. Include gremlin.lua as a DoScriptFile action, immediately followed by the specific Gremlin Scripts you wish to use in your mission.

Finally, run a single line of code to set everything up. Note that the Gremlin Scripts will set up Gremlin automatically, so unless you're building your own scripts on this framework, you don't need to do this step in your own missions.

Gremlin:setup()

Yep. That's it. One line of code to ensure everything is working.

Of course, there are a couple of things that you can configure:

Gremlin:setup({
    trace = false,
    debug = true,
    optionalFeatures = {
      logEvents = false,
    },
})
  • trace: boolean Turn on trace level logs if true

  • debug: boolean Turn on debug level logs if true

  • optionalFeatures: table Enable or disable optional features

If you aren't building your own script, you can still configure these by passing them to any Gremlin Script's :setup() method, instead.

That's it for now. Check out the rest of these docs for more info!

Usage

Gremlin is an abstraction framework that makes working with DCS in scripts much simpler. It doesn't do much on its own, yet, but we're working on adding more! Here's how to use some of what's already working:

Gremlin:setup()

Gremlin.log.info('My Cool DCS Script', 'Starting up!')

Gremlin.comms.displayMessageTo('test', 'Hullabaloo!', timer.getTime() + 1)

local myArgs = Gremlin.utils.parseFuncArgs({ '{unit}:test', '{group}:test', timer.getTime() }, {
    unit = {
        test: Unit:getByName('test'),
    },
    group = {
        test: Group:getByName('test'),
    },
})

local mergedList = Gremlin.utils.mergeTables(list1, list2, list3)

Clearly, the above script doesn't actually do anything, besides show some of how the framework can be used. The function documentation will be more helpful when building scripts that actually do things.

Functions

Gremlin:setup(config)

Sets up Gremlin. Docs for this are in the setup section.

Comms

Gremlin.comms.displayMessageTo(_name, _text, _time)

Displays a message to a named Unit, Group, Country, or Coalition, or to everyone with the special name all


Gremlin.comms.playClipTo(_name, _path)

Plays a clip to a named Unit, Group, Country, or Coalition, or to everyone with the special name all

Events

Gremlin.events.on(_eventId, _fn)

Calls _fn(_event) when an event's ID (that is, its type) matches _eventId; returns an _index value that will let you unregister the event handler using Gremlin.events.off() when you no longer need it.

This is an improved interface that avoids calling functions that don't handle certain event types anyway; said another way, it's more efficient than what DCS or MiST currently support with their event handler systems.

Gremlin.events.off(_eventId, _index)

Stops calling the _eventId handler whose _index is given; the only safe way to stop listening for events.

Gremlin.events.fire(_event)

Another improvement on the DCS event system, this lets you fire off your own events. In fact, the official Gremlin scripts use this to provide support for events in their own code.

Note: you can only receive these custom-fired events if you register an event handler using Gremlin.events.on()!

Log

Gremlin.log.error(toolId, message)

Logs an error message, the highest level DCS supports

Gremlin.log.warn(toolId, message)

Logs a warning message

Gremlin.log.info(toolId, message)

Logs an info message

Gremlin.log.debug(toolId, message)

Logs a debug message, if they're enabled

Gremlin.log.trace(toolId, message)

Logs a trace message, if they're enabled

Only one function in here for the moment! But it's pretty powerful, so the configuration can be a bit complex.

Gremlin.menu.updateF10({ toolId, commands, getForUnits })

WARNING - DO NOT CALL THIS FUNCTION MORE THAN ONCE PER SCRIPT! This is a great way to confuse the poor thing and break your missions.

Registers a set of menu commands to be updated automatically (every 10 seconds) by Gremlin itself. These commands will be grouped under a parent menu named after the tool itself - Gremlin Evac for evac.lua, Gremlin Waves for waves.lua, etc. Here's an example:

Gremlin.menu.updateF10({ MyScript.Id, {
    {
        text = 'My Cool Unit Command',
        func = MyScript.commands.myCoolUnitFunc,
        args = { '{unit}:name' },
        when = true,
    },
    {
        text = 'My Cool Group Command',
        func = MyScript.commands.myCoolGroupFunc,
        args = { '{group}:name' },
        when = {
            func = MyScript.unit.inTheZone,
            args = { '{unit}:name' },
            comp = 'equal',
            value = true,
        },
    },
}, function()
    return MyScript._state.pilotedUnits
end })
  • toolId - should be a string identifying your script by name for the menu. Should be the same value used for Gremlin's logging methods.

  • commands - an array of commands to register

    • text - a string or a function that returns a string; used for the menu text
    • func - the function to call when this menu command is selected
    • args - any arguments to pass to func (and text, if it's a function)
      • {unit}:name - placeholder value for the name of the unit whose menu is being updated
      • {group}:name - placeholder value for the name of the group whose menu is being updated
    • when - indicates when a command should be visible in the menu; can either be a boolean or a table
      • func - the function to call when deciding whether to add a command to the menu
      • args - the arguments to pass to func; uses the same placeholders as args a level up
      • comp - one of equal or inequal (at the moment); denotes what kind of comparison to make between func's return value and value
      • value - the value to compare against func's result
  • getForUnits - a function that returns a table of units to add menus to; this is a function so that your list can change over time

Utils

Gremlin.utils.checkTrigger(_trigger, _type, _extra)

Checks a trigger definition against a type and optional extra data - returns true when any conditions are met


Gremlin.utils.countTableEntries(_tbl)

Counts the number of entries in a table, regardless of type


Gremlin.utils.getUnitZones(_unit)

Looks up a list of all the zones a unit is currently in


Gremlin.utils.innerSquash(_tbl, _idx)

Flatten a table by one level, by removing the second level:

Gremlin.utils.innerSquash({
    walnut = { 'redWalnut', 'blueWalnut', [0] = 'noWalnut' },
    pecan = { 'redPecan', 'bluePecan', [0] = 'noPecan' },
    almond = { 'redAlmond', 'blueAlmond', [0] = 'noAlmond' },
}, coalition.side.BLUE)

would become

{
    walnut = 'blueWalnut',
    pecan = 'bluePecan',
    almond = 'blueAlmond',
}

Gremlin.utils.inspect(_value, _depth)

Converts a Lua value to a string for display or logging. It tries to make the string valid Lua, but there are a few types we can't reconstruct. Leave the second argument off if calling this directly!


Gremlin.utils.isInTable(_tbl, _needle)

Checks whether _needle is in the haystack _tbl


Gremlin.utils.parseFuncArgs(_args, _objs)

Preps arguments for things like scheduled functions, with some limited autocompletion of Units and Groups. Use a string placeholder for these autocompletions that meets one of the following criteria:

  • '{unit}:name' will be replaced by the corresponding Unit
  • '{group}:name' will be replaced by the corresponding Group

For _objs, simply pass a table with the appropriate structure:

{
    unit = Unit.getByName(unitName),
    group = Group.getByName(groupName),
}

Gremlin.utils.mergeTables(...)

Combines two or more tables into a single one, for easier indexing and iteration across multiple tables.

Gremlin Evac

The Gremlin Evac script sets up your missions to include evacuation scenarios. Simply call Evac:setup() to get sane defualts, or customize everything by filling out the available options you wish to override.

Features

  • Automatic spawn of evacuees
  • Loading and unloading via in-game menus
  • Manual overrides via config and function calls
  • Automatic loss for any side that loses too many evacuees
  • Automatic win for any side that rescues enough evacuees
  • More coming soon!

Setup

Configuration

Evac:setup({
    adminPilotNames = { 'Walter White' },
    beaconBatteryLife = 30,
    beaconSound = 'beacon.ogg',
    carryLimits = {
        ['C-130'] = 90,
        ['CH-43E'] = 55,
        ['CH-47D'] = 44,
        ['Hercules'] = 90,
        ['Mi-8MT'] = 24,
        ['Mi-24P'] = 5,
        ['Mi-24V'] = 5,
        ['Mi-26'] = 70,
        ['SH-60B'] = 5,
        ['SH60B'] = 5,
        ['UH-1H'] = 8,
        ['UH-60L'] = 11,
    },
    idStart = 50000,
    loadUnloadPerIndividual = 30,
    lossFlags = { 'GremlinEvacRedLoss', 'GremlinEvacBlueLoss' },
    lossThresholds = { 25, 25 },
    maxExtractable = {
        _global = {
            Generic = { 0, 0, [0] = 0 },
            Infantry = { 0, 0, [0] = 0 },
            M249 = { 0, 0, [0] = 0 },
            RPG = { 0, 0, [0] = 0 },
            StingerIgla = { 0, 0, [0] = 0 },
            ['2B11'] = { 0, 0, [0] = 0 },
            JTAC = { 0, 0, [0] = 0 },
        },
    },
    spawnRates = {
        _global = {
            {
                side = coalition.side.NEUTRAL,
                units = 0,
                startTrigger = { type = 'time', value = 0 },
                spawnTrigger = { type = 'time', value = 0 },
                endTrigger = { type = 'limits', value = 100 },
            },
            {
                side = coalition.side.RED,
                units = 0,
                startTrigger = { type = 'time', value = 0 },
                spawnTrigger = { type = 'time', value = 0 },
                endTrigger = { type = 'limits', value = 100 },
            },
            {
                side = coalition.side.BLUE,
                units = 0,
                startTrigger = { type = 'time', value = 0 },
                spawnTrigger = { type = 'time', value = 0 },
                endTrigger = { type = 'limits', value = 100 },
            },
        },
    },
    spawnWeight = 100,
    startingUnits = { 'helicargo1', 'helicargo2', 'MedEvac1', 'MedEvac2', 'MedEvac3' },
    startingZones = {
        { mode = Evac.modes.EVAC,  name = "Test 1", smoke = trigger.smokeColor.Green,  side = coalition.side.BLUE, active = true },
        { mode = Evac.modes.RELAY, name = "Test 2", smoke = trigger.smokeColor.Orange, side = coalition.side.BLUE, active = true },
        { mode = Evac.modes.SAFE,  name = "Test 3", smoke = trigger.smokeColor.White,  side = coalition.side.BLUE },
    },
    winFlags = { 'GremlinEvacRedWin', 'GremlinEvacBlueWin' },
    winThresholds = { 75, 75 },
})
  • adminPilotNames: Pilots to consider admins, with bonus menu items available.

    • Default: {}
  • beaconBatteryLife: How long beacons should broadcast once spawned, in minutes

    • Default: 30
  • beaconSound: The audio file name to play for radio beacons

    • Default: beacon.ogg
  • carryLimits: Specifies the maximum capacity loadout per aircraft designator

    • Default: { ["C-130"] = 90, ["CH-47D"] = 44, ["CH-43E"] = 55, ["Mi-8MT"] = 24, ["Mi-24P"] = 5, ["Mi-24V"] = 5, ["Mi-26"] = 70, ["SH60B"] = 5, ["UH-1H"] = 8, ["UH-60L"] = 11 }
  • idStart: The lowest ID number that Gremlin Evac will use to create units and groups

    • Default: 50000
  • loadUnloadPerIndividual: The amount of time it takes to load/unload a single evacuee onto/from an aircraft, in seconds

    • Default: 30
  • lossFlags: Flags to tell the Mission Editor that one side or the other (or both!) has lost

    • Default: { 'GremlinEvacRedLoss', 'GremlinEvacBlueLoss' }
  • lossThresholds: The maximum percentage of evacuees that can be lost from any side

    • Default: { 25, 25 }
  • maxExtractable: Provides a cap for automatically generated evacuees, by zone/type/side; the script won't create more than allowed here

    • Default: 0 for everything
  • spawnRates: Describes how and when to spawn evacuee units/groups

    • Default: { _global = { units = 0, per = 0, period = Gremlin.Periods.Second } } (everything at mission start)
    • Spec
      • key: Zone name
      • value: table
        • key: index
        • value: table
          • side: The side ID for spawning
          • units: Number or composition of units to spawn
          • startTrigger: Trigger to start spawning
          • spawnTrigger: Trigger to actually spawn units
          • endTrigger: Trigger to stop spawning
    • Notes:
      • Triggers:
        • { type = 'time', value = 900 }: seconds since mission start
        • { type = 'time', value = { after = 15, period = Gremlin.Periods.Minute } }: another way to say time since mission start
        • { type = 'repeat', value = { per = 5, period = Gremlin.Periods.Minute } }: every per periods
        • { type = 'flag', value = 7 }: flag goes truthy
        • { type = 'event', value = { id = 'Evac:Spawn', filter = function(event) return true end } }: event triggered
        • { type = 'menu', value = 'Spawn Bonus Evacuees' }: menu item selected
        • { type = 'limits', value = 50 }: value% of allowed evacuees spawned
  • spawnWeight: The average weight of an evacuee - the exact weight used will vary between 90% and 120% of this value

    • Default: 100
  • startingUnits: Registers units for evacuation purposes during setup

    • Default: {}
  • startingZones: Registers zones for evacuation purposes during setup

    • Default: {}
    • Spec
      • key: ignored
      • value: table
        • mode: One of the Evac.modes constants, indicating what evacuation mode the zone should be registered using
        • name: Zone name - MUST MATCH THE MISSION EDITOR'S NAME FOR THE ZONE EXACTLY!
        • smoke: Smoke color, taken from trigger.smokeColor
        • side: Coalition, taken from coalition.side
  • winFlags: Flags to tell the Mission Editor that one side or the other (or both!) has won

    • Default: { 'GremlinEvacRedWin', 'GremlinEvacBlueWin' }
  • winThresholds: The minimum percentage of evacuees that must be saved to win, per side

    • Default: { 75, 75 }

Usage

For many use cases, you simply configure Gremlin Evac, and the script does the rest. When you want more power, you can use the various available functions to control the map. Below are some simple examples that might help you in this endeavor.

Basic Setup

Evac:setup({
    startingZones = {
        { mode = Evac.modes.EVAC, name = "Blue Evac", smoke = trigger.smokeColor.Green, side = coalition.side.BLUE },
        { mode = Evac.modes.RELAY, name = "Blue Relay", smoke = trigger.smokeColor.Orange, side = coalition.side.BLUE, active = true },
        { mode = Evac.modes.SAFE, name = "Blue Safe", smoke = trigger.smokeColor.White, side = coalition.side.BLUE, active = true },
        { mode = Evac.modes.EVAC, name = "Red Evac", smoke = trigger.smokeColor.Green, side = coalition.side.RED },
        { mode = Evac.modes.RELAY, name = "Red Relay", smoke = trigger.smokeColor.Orange, side = coalition.side.RED, active = true },
        { mode = Evac.modes.SAFE, name = "Red Safe", smoke = trigger.smokeColor.White, side = coalition.side.RED, active = true },
    },
})

Initializes Gremlin Evac with 6 zones, 4 of which are active at start. Three are RedFor, the other three are BlueFor. Two each are evacuation zones, two each are relay/staging zones, and the last two each are safe zones. All other settings are kept at the defaults.

Full Setup

This example is also available on the Setup page.

Evac:setup({
    beaconBatteryLife = 2,
    beaconSound = "test.ogg",
    carryLimits = {
        ["SH60B"] = 15,
    },
    idStart = 5,
    loadUnloadPerIndividual = 2,
    lossFlags = { 1, 2 },
    lossThresholds = { 0, 25 },
    maxExtractable = {
        _global = {
            {
                Generic = { 12, 12, [0] = 0 },
                Infantry = { 12, 12, [0] = 0 },
                M249 = { 12, 12, [0] = 0 },
                RPG = { 12, 12, [0] = 0 },
                StingerIgla = { 12, 12, [0] = 0 },
                ["2B11"] = { 12, 12, [0] = 0 },
                JTAC = { 3, 3, [0] = 0 },
            },
        },
    },
    spawnWeight = 50,
    spawnRates = {
        ["Test 1"] = {
            {
                side = coalition.side.BLUE,
                units = 12,
                startTrigger = { type = 'time', value = 0 },
                spawnTrigger = { type = 'repeat', value = { per = 5, period = Gremlin.Periods.Minute } },
                endTrigger = { type = 'limits', value = 100 },
            },
        },
    },
    startingUnits = { 'helicargo1', 'helicargo2', 'MedEvac1', 'MedEvac2', 'MedEvac3' },
    startingZones = {
        { mode = Evac.modes.EVAC, name = "Test 1", smoke = trigger.smokeColor.Green, side = coalition.side.BLUE, active = true },
        { mode = Evac.modes.RELAY, name = "Test 2", smoke = trigger.smokeColor.Orange, side = coalition.side.BLUE, active = true },
        { mode = Evac.modes.SAFE, name = "Test 3", smoke = trigger.smokeColor.White, side = coalition.side.BLUE },
    },
    winFlags = { 3, 4 },
    winThresholds = { 0, 75 },
})

Initializes Gremlin Evac, overriding all the defaults:

  • any beacons are killed after 2 minutes (default is 30)
  • the beacon sound file is changed to something mission specific
  • the list of craft that can perform evac ops is reset to just the SH60B Unit type at a max loadout of 15 evacuees
  • the starting ID is dropped from 50000 to 5
  • the time it takes to load or unload evacuees is set to 2 seconds per evacuee (down from 30 seconds)
  • the flags used to indicate evacuation mission failure are set to 1 and 2, respectively (default is GremlinEvacRedLoss and GremlinEvacBlueLoss)
  • the percentage of evacuees that can be lost is set to 0 for red, and 25 for blue (default is 25 for both)
  • the maximums for generated evacuees are set to 12 on both sides, for all roles except JTAC, which is set to 3 (default is 0)
  • the average spawn weight is dropped from 100kg to 50kg
  • the spawn rates are configured to spawn 12 Blue generic evacuees every 5 minutes in the Test 1 Zone (default is spawn all across all Zones at mission start)
  • the starting Zones are set to three Blue Zones, two of which (evacuation and relay/staging) are active from mission start (default is no registered Zones)
  • the flags used to indicate evacuation mission success are set to 3 and 4, respectively (default is GremlinEvacRedWin and GremlinEvacBlueWin)
  • the percentage of evacuees that need to be evacuated to win is set to 0 for red, and 75 for blue (default is 75 for both)

Manual Setup

Sometimes the built-in logic isn't enough for your mission. This example pulls in several functions to integrate with other parts of the game.

Evac:setup()

Evac.zones.evac.register('Blue Evac 1', trigger.smokeColor.Blue, coalition.side.BLUE)
Evac.zones.evac.register('Blue Evac 2', trigger.smokeColor.Blue, coalition.side.BLUE)
Evac.zones.relay.register('Blue Relay 1', trigger.smokeColor.Orange, coalition.side.BLUE)
Evac.zones.relay.register('Blue Relay 2', trigger.smokeColor.Orange, coalition.side.BLUE)
Evac.zones.safe.register('Blue Safe', trigger.smokeColor.Green, coalition.side.BLUE)

Evac.zones.evac.register('Red Evac 1', trigger.smokeColor.Red, coalition.side.RED)
Evac.zones.evac.register('Red Evac 2', trigger.smokeColor.Red, coalition.side.RED)
Evac.zones.relay.register('Red Relay 1', trigger.smokeColor.Orange, coalition.side.RED)
Evac.zones.relay.register('Red Relay 2', trigger.smokeColor.Orange, coalition.side.RED)
Evac.zones.safe.register('Red Safe', trigger.smokeColor.Green, coalition.side.RED)

Evac.zones.evac.activate('Blue Evac 1')
Evac.zones.evac.activate('Blue Evac 2')
Evac.zones.relay.activate('Blue Relay 1')
Evac.zones.relay.activate('Blue Relay 2')

Evac.zones.evac.activate('Red Evac 1')
Evac.zones.evac.activate('Red Evac 2')
Evac.zones.relay.activate('Red Relay 1')
Evac.zones.relay.activate('Red Relay 2')

Evac.zones.evac.setRemaining('Blue Evac 1', coalition.side.BLUE, country.USA, {
    { type = 'Infantry' },
    { type = 'Infantry' },
    { type = 'Infantry' },
    { type = 'Infantry' },
    { type = 'Infantry' },
    { type = 'RPG' },
    { type = '2B11' },
})
Evac.zones.evac.setRemaining('Blue Evac 2', coalition.side.BLUE, country.USA, {
    { type = 'Infantry' },
    { type = 'Infantry' },
    { type = 'Infantry' },
    { type = 'Infantry' },
    { type = 'Infantry' },
    { type = 'RPG' },
    { type = 'M249' },
    { type = 'StingerIgla' },
    { type = '2B11' },
    { type = 'JTAC' },
})

Evac.zones.evac.setRemaining('Red Evac 1', coalition.side.RED, country.RUSSIA, 4)
Evac.zones.evac.setRemaining('Red Evac 2', coalition.side.RED, country.RUSSIA, 3)

Evac.units.loadEvacuees('MEDEVAC_BLUE_1')
Evac.units.loadEvacuees('MEDEVAC_BLUE_2')

Evac.units.loadEvacuees('MEDEVAC_RED_1')
Evac.units.loadEvacuees('MEDEVAC_RED_2')

This setup does a few things, in order:

  1. sets up Gremlin Evac using all the defaults
  2. registers 5 zones for blue evacuations, and 5 for red
  3. activates the evac and relay Zones
  4. manually spawns 17 blue evacuees, using composition tables
  5. manually spawns 7 red evacuees, using numbers (makes all evacuees into generic ones)
  6. manually loads up evacuees onto various standby Units

Everything from there is either automatic from Gremlin Evac, or manual via additional triggers in the mission.

Events

  • Evac:BeaconDead

    • details - the beacon details table used internally
    • Fired when a beacon dies and gets removed from the map
  • Evac:BeaconSpawn

    • details - the beacon details table used internally
    • zone - The zone the beacon was spawned into
    • Fired when a beacon spawns and gets added to the map
  • Evac:Loss

    • side - The numeric ID of the coalition that lost
    • Fired when any side loses too many evacuees
  • Evac:Spawned

    • units - The number of evacuees spawned
    • zone - The zone in which evacuees were spawned
    • Fired when evacuees spawn into the map
  • Evac:UnitLoaded

    • number - The number of evacuees loaded
    • unit - The unit that did the loading
    • zone - The zone the evacuees were picked up from
    • Fired when evacuees are finished loading onto an evacuation unit
  • Evac:UnitUnloaded

    • number - The number of evacuees unloaded
    • unit - The unit that did the unloading
    • zone - The zone the evacuees were dropped off
    • Fired when evacuees are finished unloading from an evacuation unit
  • Evac:Win

    • side - The numeric ID of the coalition that won
    • Fired when any side rescues enough evacuees
  • Evac:ZoneActive

    • mode - The Evac.modes integer dictating how evacuees should be handled in the zone
    • zone - The affected zone
    • Fired when a zone goes active
  • Evac:ZoneAdd

    • mode - The Evac.modes integer dictating how evacuees should be handled in the zone
    • zone - The affected zone
    • Fired when a zone is added to Evac
  • Evac:ZoneInactive

    • mode - The Evac.modes integer dictating how evacuees should be handled in the zone
    • zone - The affected zone
    • Fired when a zone goes inactive
  • Evac:ZoneRemove

    • mode - The Evac.modes integer dictating how evacuees should be handled in the zone
    • zone - The affected zone
    • Fired when a zone is removed from Evac

Functions

Gremlin Evac has its functions nested into various tables, rather than living directly under Evac (or worse, the global namespace). These tables include zones, units, and groups. Keep reading to learn more!

Functions » Groups

Evac.groups.spawn(_side, _numberOrComposition, _country, _zone, _scatterRadius)

Spawns evacuees manually. _side is the Group's coalition.side, _numberOrComposition follows the same rules as Evac.zones.evac.setRemaining(), _country is the country for the Group, _zone is the Zone name to spawn the evacuees into, and _scatterRadius is the distance between spawned Units on the map.

Evac.groups.list(_zone)

Returns a list of all Groups in a Zone. _zone is the name of the Zone to search.

Evac.groups.count(_zone)

Returns a count of all Groups in a Zone. _zone is the name of the Zone to search.

Functions » Units

Evac.units.register(_unit)

Registers a Unit, either by name or object, as capable of picking up evacuees. Note that the Unit MUST be one of your supported craft in your carryLimits config, or loading and unloading will not be available.

Evac.units.findEvacuees(_unit)

Lists the currently-active beacons broadcasting for the Unit's side. _unit is the name of the Unit doing the search.

Evac.units.loadEvacuees(_unit)

Starts the evacuee loading process for a Unit. _unit is the name of the Unit to load evacuees onto.

Evac.units.unloadEvacuees(_unit)

Starts the evacuee unloading process for a Unit. _unit is the name of the Unit to unload evacuees from.

Evac.units.countEvacuees(_unit)

Count the number of evacuees aboard a given Unit. _unit is the name of the Unit to count evacuees aboard.

Evac.units.count(_zone)

Count the number of Units in a given Zone. _zone is the name of the Zone to check.

Evac.units.unregister(_unit)

Removes a Unit from Gremlin Evac's internal state, making it no longer eligible for evacuation ops.

Functions » Zones

Evac.zones.evac.register(_zone, _smoke, _side)

Registers an evacuation zone with Gremlin Evac so that it can spawn and track evacuees there.

Evac.zones.relay.register(_zone, _smoke, _side)

Registers a relay/staging zone with Gremlin Evac so that it can track evacuees there.

Evac.zones.safe.register(_zone, _smoke, _side)

Registers a safe zone with Gremlin Evac so that it can track evacuees there.

For all three of the above, _zone is the name of the zone to register, _smoke is the smoke color from trigger.smokeColor, and _side is taken from coalition.side.


Evac.zones.evac.activate(_zone)

Turns on evacuation automations for a given zone.

Evac.zones.relay.activate(_zone)

Turns on relay/staging automations for a given zone.

Evac.zones.safe.activate(_zone)

Turns on safe zone automations for a given zone.

For all three of the above, _zone is the zone name to activate.


Evac.zones.evac.setRemaining(_zone, _side, _country, _numberOrComposition)

Sets the number of waiting evacuees in the zone.

Evac.zones.relay.setRemaining(_zone, _side, _country, _numberOrComposition)

Sets the number of waiting evacuees in the zone.

For both of the above, _zone is the zone name to activate, _side is taken from coalition.side, _country is taken from the country table, and _numberOrComposition is (as its name suggests) either a number of evacuees to generate (these will all be of type "Generic"), or a table listing off the composition of the units to spawn (as its name also suggests).

Sample Composition
Evac.zones.evac.setRemaining('test', coalition.side.BLUE, country.USA, {
    { type = 'Carrier Seaman', unitName = 'Karl Marx', unitId = 42, weight = 75 },
    { type = 'Infantry' },
    { type = 'JTAC' },
    {},
})

This will add a generic evacuee named Karl Marx, with associated ID and weight values, an infantry unit, a JTAC unit, and a second generic evacuee whose name is automatically generated. Note how none of the parameters are required if you just want a generic evacuee, though a unit composed entirely of generics is simpler to build with a number instead of a composition table.


Evac.zones.evac.count(_zone)

Gets an evacuee count for a given evacuation zone.

Evac.zones.relay.count(_zone)

Gets an evacuee count for a given relay/staging zone.

Evac.zones.safe.count(_zone)

Gets an evacuee count for a given safe zone.

For all three of the above, _zone is the zone name to count evacuees within.


Evac.zones.evac.isIn(_unit)

Gets a value indicating whether an evacuee is in a given evacuation zone.

Evac.zones.relay.isIn(_unit)

Gets a value indicating whether an evacuee is in a given relay/staging zone.

Evac.zones.safe.isIn(_unit)

Gets a value indicating whether an evacuee is in a given safe zone.

For all three of the above, _unit is the unit name to search for.


Evac.zones.evac.deactivate(_zone)

Turns off evacuation automations for a given zone.

Evac.zones.relay.deactivate(_zone)

Turns off relay/staging automations for a given zone.

Evac.zones.safe.deactivate(_zone)

Turns off safe zone automations for a given zone.

For all three of the above, _zone is the zone name to deactivate.


Evac.zones.evac.unregister(_zone)

Removes an evacuation zone from Evac's control.

Evac.zones.relay.unregister(_zone)

Removes a relay/staging zone from Evac's control.

Evac.zones.safe.unregister(_zone)

Removes a safe zone from Evac's control.

For all three of the above, _zone is the zone name to remove.

About

Gremlin Urgency is a great way to add ... well, urgency to your missions. Timed events made easy - whether that be mission duration or anything else.

Setup

Configuration

Urgency:setup({
    adminPilotNames = {
        'Steve Jobs',
        'Linus Torvalds',
        'Bill Gates',
    },
    countdowns = {
        missionDuration = {
            reuse = false,
            startTrigger = {
                type = 'time',
                value = 0, -- mission start (or, well, as close as we can manage)
            },
            startFlag = 'MissionRunning',
            endTrigger = {
                type = 'time',
                value = 25200, -- 7 hours
            },
            endFlag = 'MissionTimeout',
            messages = {
                [0] = { to = 'blue', text = 'Mission is a go! We only get seven hours to complete our objectives!', duration = 15 },
                [-1800] = { to = 'blue', text = '30 minutes left in mission! Are we gonna make it?', duration = 15 },
                [-900] = { to = 'blue', text = '15 minutes left in mission! Are we gonna make it?', duration = 15 },
                [-600] = { to = 'blue', text = '10 minutes left in mission! Are we gonna make it?', duration = 15 },
                [-300] = { to = 'blue', text = '5 minutes left in mission! Are we gonna make it?', duration = 15 },
                [-60] = { to = 'blue', text = '1 minute left in mission! Are we gonna make it?', duration = 15 },
                [-30] = { to = 'blue', text = '30 seconds left in mission...', duration = 5 },
                [-15] = { to = 'blue', text = '15 seconds left in mission...', duration = 5 },
                [-10] = { to = 'blue', text = '10 seconds left in mission...', duration = 1 },
                [-9] = { to = 'blue', text = '9 seconds left in mission...', duration = 1 },
                [-8] = { to = 'blue', text = '8 seconds left in mission...', duration = 1 },
                [-7] = { to = 'blue', text = '7 seconds left in mission...', duration = 1 },
                [-6] = { to = 'blue', text = '6 seconds left in mission...', duration = 1 },
                [-5] = { to = 'blue', text = '5 seconds left in mission...', duration = 1 },
                [-4] = { to = 'blue', text = '4 seconds left in mission...', duration = 1 },
                [-3] = { to = 'blue', text = '3 seconds left in mission...', duration = 1 },
                [-2] = { to = 'blue', text = '2 seconds left in mission...', duration = 1 },
                [-1] = { to = 'blue', text = '1 seconds left in mission...', duration = 1 },
                [25200] = { to = 'all', text = "Time's up! Ending mission...", duration = 15 },
            },
        },
        easterEgg1 = {
            reuse = true,
            startTrigger = {
                type = 'flag',
                value = 'Egg1Triggered',
            },
            startFlag = 'Egg1Found',
            endTrigger = {
                type = 'time',
                value = 3600, -- 1 hour
            },
            endFlag = 'Egg1Expired',
            messages = {
                [0] = { to = 'all', text = 'An Easter Egg Was Discovered!', duration = 15 },
                [3600] = { to = 'all', text = 'An Easter Egg Has Vanished!', duration = 15 },
            },
            clips = {
                [0] = { to = 'all', path = 'exclaim.ogg' },
                [3600] = { to = 'all', path = 'snake.ogg' },
            },
        },
    },
})
  • adminPilotNames table

    • A list of pilots who should get the admin menu
  • countdowns table

    • A list of countdowns to register at mission start
    • countdown
      • reuse whether to put this countdown back in the queue to be triggered again
      • startTrigger table
        • type one of time, flag, event, or menu
        • value the time, event id and handler, or menu text to trigger on
      • startFlag the flag to set true when the countdown starts
      • endTrigger table
        • type one of time, flag, event, or menu
        • value the time, event id and handler, or menu text to trigger on
      • endFlag the flag to set true when the countdown ends
      • messages a list of messages to display, keyed by the countdown's seconds since start (or seconds until end, if negative)
        • to the units that should receive the message (unit, group, country, coalition), or the special value all for everyone
        • text the message to display
        • duration how long the message should be visible (in seconds)
      • clips a list of clips to play, keyed by the countdown's seconds since start (or seconds until end, if negative)
        • to the units that should receive the message (unit, group, country, coalition), or the special value all for everyone
        • path the path to the clip to play

Usage

Gremlin Urgency is really simple to use. Configure it once (see the Setup page), and it handles the rest!

Events

  • Urgency:CountdownEnd

    • name - The name of the countdown that just ended
    • Fired when a countdown ends
  • Urgency:CountdownStart

    • name - The name of the countdown that just started
    • Fired when a countdown begins
  • Urgency:CountdownsReset

    • Fired when an admin pilot resets all active countdowns to pending
  • Urgency:CountdownsRestored

    • Fired when an admin pilot restores all countdowns so they will start over

About

Gremlin Waves is a reinforcements script for your missions. Running low on RedFor, but not ready for the fun to end? Call in reinforcements with Gremlin Waves!

Setup

Configuration

Waves:setup({
    adminPilotNames = {
        'Steve Jobs',
        'Linus Torvalds',
        'Bill Gates',
    },
    waves = {
        ['Wave 2'] = {
            trigger = {
                type = 'time',
                value = 12600, -- 3.5 hours
            },
            groups = {
                ['F-14B'] = {
                    category = Group.Category.AIRPLANE,
                    country = country.USA,
                    zone = 'Reinforcement Staging',
                    scatter = 15,
                    orders = {},
                    units = {
                        ['F-14B'] = 3,
                    },
                },
                ['Ground A'] = {
                    category = Group.Category.GROUND,
                    country = country.USA,
                    zone = 'Reinforcement Staging',
                    scatter = 5,
                    orders = {},
                    units = {
                        ['Infantry'] = 4,
                    }
                },
                ['Ground B'] = {
                    category = Group.Category.GROUND,
                    country = country.USA,
                    zone = 'Reinforcement Staging',
                    scatter = 5,
                    orders = {},
                    units = {
                        ['RPG'] = 1,
                        ['Infantry'] = 3,
                        ['JTAC'] = 1,
                    }
                },
            },
        },
    },
})
  • adminPilotNames table
    • list of pilots who should see the menu
  • waves table
    • collection of reinforcement waves for this mission
    • wave
      • trigger table
        • type one of time, flag, event, or menu
        • value a time, flag name / number, event id / filter, or menu item text
      • groups table
        • list of groups to spawn
        • group
          • category a member of Groups.Category indicating the group's category
          • country a country id
          • zone where to spawn the group
          • scatter how far apart, in meters, to scatter units at spawn
          • orders table
          • units table
            • key: the unit type to spawn
            • value: how many to spawn in the group

Usage

Gremlin Waves is really simple to use. Configure it once (see the Setup page), and it handles the rest!

Events

  • Waves:GroupSpawn

    • wave - The name of the wave that is spawning groups
    • group - The name of the group that spawned in this wave
    • Fired when a group is spawned as part of a wave
  • Waves:Paused

    • Fired when an admin pilot pauses all pending waves
  • Waves:Resumed

    • Fired when an admin pilot resumes all pending waves
  • Waves:WaveSpawn

    • wave - The name of the wave that spawned
    • Fired when a wave is fully spawned

Contributors

Gremlin Aviation

Modules

  • Gremlin

Module Gremlin

Gremlin.

DO NOT EDIT THIS SCRIPT DIRECTLY! Things WILL break that way.

Instead, pass a table to Gremlin:setup() with any options you wish to configure.

Enums

NameSummary
PeriodsTime period "constants", in seconds.
SideToTextCoalition name from ID.

Comms

NameSummary
Gremlin.comms.displayMessageTo(_name, _text, _time)Display message to target.
Gremlin.comms.playClipTo(_name, _path)Play sound file for target.

Events

NameSummary
Gremlin.events.fire(_event)Fire an event.
Gremlin.events.idToNameEvent name lookup.
Gremlin.events.off(_eventId, _index)Unregister an event handler.
Gremlin.events.on(_eventId, _fn)Register an event handler.

Logging

NameSummary
Gremlin.log.debug(toolId, message)Log a message at the debug level.
Gremlin.log.error(toolId, message)Log a message at the error level.
Gremlin.log.info(toolId, message)Log a message at the info level.
Gremlin.log.trace(toolId, message)Log a message at the trace level.
Gremlin.log.warn(toolId, message)Log a message at the warn level.

Utils

NameSummary
Gremlin.utils.countTableEntries(_tbl)Count items in a table, numeric or otherwise.
Gremlin.utils.getUnitZones(_unit)Get a list of zones a unit is in.
Gremlin.utils.inspect(_value, _depth)Get a mostly-Lua representation of a value.
Gremlin.utils.isInTable(_tbl, _needle)Searches a table for a value.
Gremlin.utils.mergeTables(...)Combine two tables together.
Gremlin.utils.parseFuncArgs(_args, _objs)Parse arguments for things like menus.
checkTrigger(_trigger, _type, _extra)Check whether a trigger condition has been met.
innerSquash(_tbl, _idx)Flattens a table by removing the second level, rather than the first

Top Level methods

NameSummary
setup(config)Setup Gremlin.

Enums

Periods

Time period "constants", in seconds.

Fields:

  • Second 1 second
  • Minute 1 minute
  • Hour 1 hour
  • Day 1 day

SideToText

Coalition name from ID.

Fields:

  • [0] Neutral
  • [1] Red
  • [2] Blue

Comms

Methods for handling communications with players.

Gremlin.comms.displayMessageTo(_name, _text, _time)

Display message to target. Finds a target by name, and then sends a text message.

Parameters:

  • _name string, Unit or Group The name of the target to send a message to
  • _text string The text to send
  • _time number How long before the message should be dismissed

Gremlin.comms.playClipTo(_name, _path)

Play sound file for target. Finds a target by name, then plays a sound file.

Parameters:

  • _name string, Unit or Group The name of the target to play sound to
  • _path string The filename of the audio clip to play

Events

Methods for handling and firing events.

Gremlin.events.fire(_event)

Fire an event. NOTE: Only works between scripts that register handlers. It cannot send events back to DCS proper.

Parameters:

  • _event table The event object to send to all relevant Gremlin handlers

Gremlin.events.idToName

Event name lookup. Not populated until setup is complete!

Gremlin.events.off(_eventId, _index)

Unregister an event handler.

Parameters:

  • _eventId integer The DCS event ID to stop listening for
  • _index integer The handler index to remove

Gremlin.events.on(_eventId, _fn)

Register an event handler.

Parameters:

  • _eventId integer The DCS event ID to listen for
  • _fn function The event handler to register

Returns:

  • integer The handler index for later removal

Logging

Methods for logging things.

Gremlin.log.debug(toolId, message)

Log a message at the debug level.

Parameters:

  • toolId string The string identifying the source of the message
  • message string The message to log

Gremlin.log.error(toolId, message)

Log a message at the error level.

Parameters:

  • toolId string The string identifying the source of the message
  • message string The message to log

Gremlin.log.info(toolId, message)

Log a message at the info level.

Parameters:

  • toolId string The string identifying the source of the message
  • message string The message to log

Gremlin.log.trace(toolId, message)

Log a message at the trace level.

Parameters:

  • toolId string The string identifying the source of the message
  • message string The message to log

Gremlin.log.warn(toolId, message)

Log a message at the warn level.

Parameters:

  • toolId string The string identifying the source of the message
  • message string The message to log

Methods for setting up menus and keeping them up to date.

Gremlin.menu.updateF10(toolId, commands, forUnits)

Update the F10 menu.

Parameters:

  • toolId string A string indicating the top level menu to create
  • commands table A table of menu items to sync
  • forUnits table A list of units who should be given menu access

Utils

Methods for miscellaneous script activities.

Gremlin.utils.countTableEntries(_tbl)

Count items in a table, numeric or otherwise.

Parameters:

  • _tbl table The table to count entries within

Returns:

  • integer The number of items in the table

Gremlin.utils.getUnitZones(_unit)

Get a list of zones a unit is in.

Parameters:

  • _unit string The unit whose zones should be retrieved

Returns:

  • table The list of unit zones

Gremlin.utils.inspect(_value, _depth)

Get a mostly-Lua representation of a value.

Parameters:

  • _value any The value to inspect
  • _depth integer How deep we've already inspected; should be 0 or nil

Returns:

  • string A string representation of the value

Gremlin.utils.isInTable(_tbl, _needle)

Searches a table for a value.

Parameters:

  • _tbl table The table to search
  • _needle any The value to find

Returns:

  • boolean Whether the needle was in the haystack

Gremlin.utils.mergeTables(...)

Combine two tables together. Doesn't care about integer versus string keys.

Parameters:

  • ... table One or more tables to combine together

Returns:

  • table The final combined result

Gremlin.utils.parseFuncArgs(_args, _objs)

Parse arguments for things like menus.

Parameters:

  • _args table The arguments to parse
  • _objs table Values for substitution

Returns:

  • table The final (usable) arguments

checkTrigger(_trigger, _type, _extra)

Check whether a trigger condition has been met.

Parameters:

  • _trigger table The trigger definition table to check against
  • _type string The trigger type to check for
  • _extra any Any extra data needed to perform the check, or nil

Returns:

  • boolean Whether the trigger condition has been met

innerSquash(_tbl, _idx)

Flattens a table by removing the second level, rather than the first

Parameters:

  • _tbl table The table to flatten
  • _idx string or number The inner index to extract

Returns:

  • table The flattened table

Top Level methods

setup(config)

Setup Gremlin.

Parameters:

  • config table The settings table to configure Gremlin using

Last updated 2024-04-28 12:12:18

Evac

Modules

  • Urgency

Module Urgency

Gremlin Urgency

DO NOT EDIT THIS SCRIPT DIRECTLY! Things WILL break that way.

Instead!

When calling Urgency:setup(), you can pass in a configuration table instead of nil. Make your changes in the table you pass - defaults are already in place if you want to leave those out.

An example, providing all the defaults, is available in the docs, or near the end of this script.

Top level methods

NameSummary
setup(config)Setup Gremlin Urgency

The argument should contain a configuration table as shown below. |

Top level methods

Methods for interacting with Urgency itself.

setup(config)

Setup Gremlin Urgency

The argument should contain a configuration table as shown below.

Example providing all the defaults:

Urgency:setup({
    adminPilotNames = {},
    countdowns = {},
})

Parameters:

Last updated 2024-04-28 12:12:18

Modules

  • Waves

Module Waves

Gremlin Waves

DO NOT EDIT THIS SCRIPT DIRECTLY! Things WILL break that way.

Instead!

When calling Waves:setup(), you can pass in a configuration table instead of nil. Make your changes in the table you pass - defaults are already in place if you want to leave those out.

An example, providing all the defaults, is available in the docs, or near the end of this script.

Top level methods

NameSummary
setup(config)Setup Gremlin Waves

The argument should contain a configuration table as shown below. |

Top level methods

Methods for interacting with Waves itself.

setup(config)

Setup Gremlin Waves

The argument should contain a configuration table as shown below.

Example providing all the defaults:

Waves:setup({
    adminPilotNames = {},
    waves = {},
})

Parameters:

Last updated 2024-04-28 12:12:18