Fixed tanks spawning with troops (again)

This commit is contained in:
iTracerFacer 2025-11-09 19:50:39 -06:00
parent 24ffbaf378
commit 4be360880a
11 changed files with 3472 additions and 409 deletions

72
.github/copilot-instructions.md vendored Normal file
View File

@ -0,0 +1,72 @@
# Copilot instructions for DCS_MissionDev
These notes teach AI coding agents how to be productive in this DCS World mission-scripting workspace. Keep responses concrete, reference the files below, and prefer making small targeted edits over broad rewrites.
## Big picture
- This repo is a DCS mission lab focused on Lua scripting for the MOOSE, MIST, CTLD, and CSAR ecosystems.
- Structure:
- Root hosts shared framework scripts and utilities: `Moose_.lua`, `Moose.lua`, `mist.lua`, multiple pinned `mist_*` versions, `CTLD.lua`, `CSAR.lua`, plus helper and mission glue scripts (e.g., `NukeBlockerScriptv1_2_1.lua`, `OnBirthMessage.lua`).
- Mission families live under `DCS_<Theater>/...` with individual `.miz` files and scenario folders.
- Purpose-built modules live under `Moose_*/*` with a main Lua, demo `.miz`, and a README describing setup.
- Loading order matters in DCS: framework(s) first, then modules, then mission glue. Typical trigger order: `Moose_.lua` → framework/middleware → module script(s) → custom mission logic.
## Core modules and patterns (examples in repo)
- Zone Capture (dual coalition): `Moose_DualCoalitionZoneCapture/Moose_DualCoalitionZoneCapture.lua`
- Edit-only config tables: `ZONE_CONFIG` (BLUE/RED/NEUTRAL lists) and `ZONE_SETTINGS` (scan/capture/guard).
- Uses MOOSE classes like `ZONE`, `ZONE_CAPTURE_COALITION`, `COMMANDCENTER`, `MISSION`; logs via `env.info` with `[CAPTURE Module]` prefix.
- Visuals driven by `ZONE_COLORS`; contested/attacked overrides ownership color.
- Dynamic Ground Battle: `Moose_DynamicGroundBattle/Moose_DynamicGroundBattle.lua`
- User-edit section defines red/blue `ZONE:New(...)`, warehouse `STATIC:FindByName(...)`, and template arrays. After the “DO NOT EDIT BELOW THIS LINE” banner core logic runs.
- Spawn rates scale with warehouse survival; periodic tasking (`ASSIGN_TASKS_SCHED`) retasks idle groups; optional infantry movement via `MOVING_INFANTRY_PATROLS`.
- CTLD: `CTLD.lua`
- Large, configurable logistics/troop script; user config at top: smoke, hover pickup, crate rules, pickup/drop/wp zones, vehicle weights, JTAC settings, and transport pilot names.
- Important distances: `ctld.maximumDistanceLogistic`, `ctld.minimumDeployDistance`, etc. Keep names matching ME zones strictly.
- CSAR: `CSAR.lua`
- Note: the current file contains an HTML GitHub page artifact. When updating, replace with the raw Lua from ciribob/DCS-CSAR (use the Raw file, not the HTML page).
## Developer workflows (what to run and how)
- Script load in missions (Mission Editor → Triggers):
1) DO SCRIPT FILE `Moose_.lua`
2) DO SCRIPT FILE your module(s) (e.g., DualCoalitionZoneCapture or DynamicGroundBattle)
3) DO SCRIPT FILE mission glue (CTLD/CSAR/others), respecting their config requirements
- Fast mission patching without opening the editor: `Patch-MooseMissions/`
- Use `Patch-MooseMissions.ps1` to inject or replace a Lua inside a `.miz` and auto-bump version numbers.
- See `Patch-MooseMissions/README.md` for examples (pipeline-friendly; default script location inside miz: `l10n/DEFAULT/*.lua`).
- Versioning conventions for missions: filenames embed the version (`F99th-Operation Ronin 1.4.miz` → next `1.5`); the patcher respects X, X.Y, X.Y.Z.
- Debugging:
- Prefer `env.info("[Tag] message")`; check `Saved Games\DCS\Logs\DCS.log`. Modules log with distinct prefixes (e.g., `[CAPTURE Module]`).
- Common issues: wrong zone/group/static names; framework not loaded first; CTLD/CSAR configs mismatched with ME. Fix by aligning names and load order.
## Conventions and gotchas (repo-specific)
- Name matching is strict across modules. Examples to copy:
- Zones: `"Capture Zone-1"`, `"FrontLine7"`, etc.
- HQ groups: `BLUEHQ`, `REDHQ` for MOOSE `COMMANDCENTER`/`MISSION` creation.
- Warehouses: use Static object Unit Name: `RedWarehouse1-1`, `BlueWarehouse3-1`.
- Module layout: top “user config” section, followed by `-- DO NOT EDIT BELOW THIS LINE` guard. Keep PRs to config when possible; avoid editing engine logic unless necessary.
- Framework pinning: multiple `mist_*` versions live alongside `mist.lua`. Mission scripts may expect a specific version; dont silently swap them—load the version matching the mission.
- CTLD settings commonly used here: `ctld.enableCrates`, `ctld.slingLoad`, `ctld.pickupZones`, `ctld.dropOffZones`, `ctld.wpZones`, `ctld.transportPilotNames`. Follow the existing style when extending.
- CSAR file hygiene: replace HTML artifacts with raw Lua. Verify by ensuring the file starts with Lua, not `<!DOCTYPE html>`.
## Integration points
- MOOSE: all advanced orchestration depends on `Moose_.lua`/`Moose.lua` APIs (`ZONE`, `GROUP`, `STATIC`, `ZONE_CAPTURE_COALITION`, `COMMANDCENTER`, `MISSION`, `SCORING`). Load it first.
- CTLD/CSAR interop: DynamicGroundBattle notes CTLD troops integrate automatically; ensure CTLD is active if you expect troop drops to influence zones.
- VoiceAttack: profiles under `Moose_CTLD_Pure/Voice Attack/` are player tooling, not runtime dependencies. Dont reference them from mission scripts.
## Making changes safely
- When adding new zones/templates/warehouses, update the corresponding arrays in the modules user config and mirror the names in the Mission Editor.
- When changing visuals or scan cadence, update `ZONE_COLORS` and `ZONE_SETTINGS` in Zone Capture, or scheduler values in Dynamic Ground Battle.
- For patching `.miz` with new `Moose_.lua`/scripts, prefer the PowerShell patcher; it preserves originals and bumps the version.
## Pointers to examples in this repo
- Dual coalition capture: `Moose_DualCoalitionZoneCapture/README.md` and example `.miz` in same folder.
- Dynamic ground battle: `Moose_DynamicGroundBattle/README.md`.
- Mission patching: `Patch-MooseMissions/README.md`.
If anything above is ambiguous (e.g., CSAR expected version, CTLD defaults for a specific mission family), ask for the target mission and well codify the exact load order and script set.

View File

@ -186,6 +186,7 @@ CTLD.Messages = {
CTLD.Config = {
CoalitionSide = coalition.side.BLUE, -- default coalition this instance serves (menus created for this side)
CountryId = nil, -- optional explicit country id for spawned groups; falls back per coalition
AllowedAircraft = { -- transport-capable unit type names (case-sensitive as in DCS DB)
'UH-1H','Mi-8MTV2','Mi-24P','SA342M','SA342L','SA342Minigun','Ka-50','Ka-50_3','AH-64D_BLK_II','UH-60L','CH-47Fbl1','CH-47F','Mi-17','GazelleAI'
},
@ -196,7 +197,7 @@ CTLD.Config = {
-- 2 = INFO - Important state changes, initialization, cleanup (default for production)
-- 3 = VERBOSE - Detailed operational info (zone validation, menus, builds, MEDEVAC events)
-- 4 = DEBUG - Everything including hover checks, crate pickups, detailed troop spawns
LogLevel = 1,
LogLevel = 4,
-- Per-aircraft capacity limits (realistic cargo/troop capacities)
-- Set maxCrates = 0 and maxTroops = 0 for attack helicopters with no cargo capability
@ -254,9 +255,9 @@ CTLD.Config = {
-- Air-spawn settings for CTLD-built drones (AIRPLANE category entries in the catalog like MQ-9 / WingLoong)
DroneAirSpawn = {
Enabled = true, -- when true, AIRPLANE catalog items that opt-in can spawn in the air at a set altitude
AltitudeMeters = 3048, -- default spawn altitude ASL (meters) - 10,000 feet
SpeedMps = 120 -- default initial speed in m/s
Enabled = true, -- when true, AIRPLANE catalog items that opt-in can spawn in the air at a set altitude
AltitudeMeters = 3048, -- default spawn altitude ASL (meters) - 10,000 feet
SpeedMps = 120 -- default initial speed in m/s
},
DropCrateForwardOffset = 35, -- meters: drop loaded crates this far in front of the aircraft (instead of directly under)
RestrictFOBToZones = false, -- if true, recipes marked isFOB only build inside configured FOBZones
@ -1198,28 +1199,29 @@ local LOG_INFO = 2
local LOG_VERBOSE = 3
local LOG_DEBUG = 4
local _logLevelLabels = {
[LOG_ERROR] = 'ERROR',
[LOG_INFO] = 'INFO',
[LOG_VERBOSE] = 'VERBOSE',
[LOG_DEBUG] = 'DEBUG',
}
local function _log(level, msg)
local logLevel = CTLD.Config and CTLD.Config.LogLevel or LOG_INFO
if level <= logLevel then
_logVerbose('' .. msg)
if level > logLevel or level == LOG_NONE then return end
local label = _logLevelLabels[level] or tostring(level)
local text = string.format('[Moose_CTLD][%s] %s', label, tostring(msg))
if env and env.info then
env.info(text)
else
print(text)
end
end
local function _logError(msg)
_log(LOG_ERROR, msg)
end
local function _logInfo(msg)
_log(LOG_INFO, msg)
end
local function _logVerbose(msg)
_log(LOG_VERBOSE, msg)
end
local function _logDebug(msg)
_log(LOG_DEBUG, msg)
end
local function _logError(msg) _log(LOG_ERROR, msg) end
local function _logInfo(msg) _log(LOG_INFO, msg) end
local function _logVerbose(msg) _log(LOG_VERBOSE, msg) end
local function _logDebug(msg) _log(LOG_DEBUG, msg) end
-- =========================
-- Zone and Unit Utilities
@ -1402,9 +1404,29 @@ function CTLD:_nearestActivePickupZone(unit)
return _nearestZonePoint(unit, self:_collectActivePickupDefs())
end
local function _defaultCountryForSide(side)
if not (country and country.id) then return nil end
if side == coalition.side.BLUE then
return country.id.USA or country.id.CJTF_BLUE
elseif side == coalition.side.RED then
return country.id.RUSSIA or country.id.CJTF_RED
elseif side == coalition.side.NEUTRAL then
return country.id.UN or country.id.CJTF_NEUTRAL or country.id.USA
end
return nil
end
local function _coalitionAddGroup(side, category, groupData, ctldConfig)
-- Enforce side/category in groupData just to be safe
groupData.category = category
local countryId = ctldConfig and ctldConfig.CountryId
if not countryId then
countryId = _defaultCountryForSide(side)
if ctldConfig then ctldConfig.CountryId = countryId end
end
if countryId then
groupData.country = countryId
end
-- Apply air-spawn altitude adjustment for AIRPLANE category if DroneAirSpawn is enabled
if category == Group.Category.AIRPLANE and ctldConfig and ctldConfig.DroneAirSpawn and ctldConfig.DroneAirSpawn.Enabled then
@ -1424,7 +1446,8 @@ local function _coalitionAddGroup(side, category, groupData, ctldConfig)
end
end
return coalition.addGroup(side, category, groupData)
local addCountry = countryId or side
return coalition.addGroup(addCountry, category, groupData)
end
local function _spawnStaticCargo(side, point, cargoType, name)
@ -2264,6 +2287,8 @@ function CTLD:New(cfg)
end
o.Side = o.Config.CoalitionSide
o.CountryId = o.Config.CountryId or _defaultCountryForSide(o.Side)
o.Config.CountryId = o.CountryId
o.MenuRoots = {}
o.MenusByGroup = {}
@ -7736,6 +7761,28 @@ function CTLD:_CreateMobileMASH(group, position, catalogDef)
if not cfg or not cfg.Enabled then return end
if not cfg.MobileMASH or not cfg.MobileMASH.Enabled then return end
-- Ensure we have a MOOSE GROUP instance (coalition.addGroup returns a raw DCS group)
local mashGroup = group
if mashGroup and not (mashGroup.IsAlive and mashGroup.GetCoordinate) then
local rawName = (mashGroup.GetName and mashGroup:GetName()) or (mashGroup.getName and mashGroup:getName())
if rawName and GROUP and GROUP.FindByName then
local found = GROUP:FindByName(rawName)
if found then
mashGroup = found
else
_logError(string.format('[MobileMASH] Could not resolve MOOSE group for %s; aborting Mobile MASH setup', rawName))
return
end
else
_logError('[MobileMASH] Missing group reference for Mobile MASH deployment; aborting')
return
end
end
if not mashGroup then
_logError('[MobileMASH] Mobile MASH group resolution failed; aborting')
return
end
local side = catalogDef.side or self.Side
if not CTLD._mobileMASHCounter then CTLD._mobileMASHCounter = {} end
if not CTLD._mobileMASHCounter[side] then CTLD._mobileMASHCounter[side] = 0 end
@ -7750,7 +7797,7 @@ function CTLD:_CreateMobileMASH(group, position, catalogDef)
position = {x = position.x, z = position.z},
radius = radius,
side = side,
group = group,
group = mashGroup,
isMobile = true,
catalogKey = catalogDef.description or 'Mobile MASH'
}
@ -7760,8 +7807,8 @@ function CTLD:_CreateMobileMASH(group, position, catalogDef)
CTLD._mashZones[mashId] = mashData
-- Draw on F10 map
local circleId = mashId .. '_circle'
local textId = mashId .. '_text'
local circleId = _nextMarkupId()
local textId = _nextMarkupId()
local p = {x = position.x, y = 0, z = position.z}
local borderColor = cfg.MASHZoneColors.border or {1, 1, 0, 0.85}
@ -7791,15 +7838,16 @@ function CTLD:_CreateMobileMASH(group, position, catalogDef)
local ctldInstance = self
local scheduler = SCHEDULER:New(nil, function()
-- Check if group still exists
if not group or not group:IsAlive() then
if not mashGroup or not mashGroup:IsAlive() then
ctldInstance:_RemoveMobileMASH(mashId)
return
end
-- Send periodic announcement
local currentPos = group:GetCoordinate()
if currentPos then
local currentGrid = ctldInstance:_GetMGRSString({x = currentPos.x, z = currentPos.z})
local coord = mashGroup:GetCoordinate()
if coord then
local vec3 = coord:GetVec3()
local currentGrid = ctldInstance:_GetMGRSString({x = vec3.x, z = vec3.z})
local announceMsg = _fmtTemplate(CTLD.Messages.medevac_mash_announcement, {
mash_id = CTLD._mobileMASHCounter[side],
grid = currentGrid,
@ -7814,7 +7862,7 @@ function CTLD:_CreateMobileMASH(group, position, catalogDef)
-- Set up death event handler for this specific MASH
local ctldInstance = self
local mashGroupName = group:GetName()
local mashGroupName = mashGroup:GetName()
local eventHandler = EVENTHANDLER:New()
eventHandler:HandleEvent(EVENTS.Dead)

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-16"?>
<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>DCS CTLD Menu Navigation</Name>
<Id>a8f7c9d2-4e6b-4c1a-9f3e-2a8d7c6b5e4f</Id>
<Commands>
<Command>
<Id>3a7f2b1e-8c4d-4f9a-b2e1-5d6c7a8b9c0d</Id>
<CommandString>load troops</CommandString>
<ActionSequence>
<PressKey>
<KeyCodes>{RALT}\{F2}{F1}{F1}</KeyCodes>
</PressKey>
</ActionSequence>
</Command>
<Command>
<Id>4b8c9d0e-1f2a-3b4c-5d6e-7f8a9b0c1d2e</Id>
<CommandString>show status;ctld status;check status</CommandString>
<ActionSequence>
<PressKey>
<KeyCodes>{RALT}\{F5}{F2}</KeyCodes>
</PressKey>
</ActionSequence>
</Command>
</Commands>
</Profile>

File diff suppressed because it is too large Load Diff

View File

@ -1,378 +0,0 @@
<?xml version="1.0" encoding="utf-16"?>
<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Name="DCS CTLD Menu Navigation" Id="a8f7c9d2-4e6b-4c1a-9f3e-2a8d7c6b5e4f" EnableMouseClicks="true" Dock="1" v="2.8.10" TrimExecuteCommandLines="true">
<Commands>
<!-- F10 MENU KEY: RAlt+\ (works on ground and in air) -->
<!-- On ground: \ alone works, but RAlt+\ is compatible -->
<!-- In air: RAlt+\ required (\ alone is disabled) -->
<!-- OPERATIONS: TROOP TRANSPORT -->
<Command Id="cmd_load_troops">
<CommandString>load troops</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F1}{F1}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_deploy_hold">
<CommandString>deploy troops;deploy hold;deploy defend</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F1}{F3}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_deploy_attack">
<CommandString>deploy attack;troops attack</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F1}{F4}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<!-- OPERATIONS: BUILD -->
<Command Id="cmd_build_here">
<CommandString>build here;build at position</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F2}{F1}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_refresh_buildable">
<CommandString>refresh buildable list;refresh build list</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F2}{F4}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<!-- OPERATIONS: MEDEVAC -->
<Command Id="cmd_medevac_list">
<CommandString>list medevac;active medevac requests</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F3}{F1}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_medevac_nearest">
<CommandString>nearest medevac location;medevac location</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F3}{F2}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_salvage_points">
<CommandString>salvage points;check salvage</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F3}{F3}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_vectors_medevac">
<CommandString>vectors to medevac;medevac vectors</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F3}{F4}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_mash_locations">
<CommandString>mash locations;show mash</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F3}{F5}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_smoke_crews">
<CommandString>smoke crew locations;mark crews</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F3}{F6}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_smoke_mash">
<CommandString>smoke mash zones;mark mash</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F3}{F7}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<!-- LOGISTICS: CRATE MANAGEMENT -->
<Command Id="cmd_drop_one_crate">
<CommandString>drop one crate;drop crate</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F3}{F1}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_drop_all_crates">
<CommandString>drop all crates;drop cargo</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F3}{F2}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_remark_crate">
<CommandString>mark nearest crate;smoke crate;remark crate</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F3}{F3}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_show_inventory">
<CommandString>show inventory;check inventory;zone inventory</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F4}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<!-- FIELD TOOLS -->
<Command Id="cmd_create_dropzone">
<CommandString>create drop zone;mark drop zone</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F3}{F1}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_smoke_green">
<CommandString>smoke green;green smoke</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F3}{F2}{F1}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_smoke_red">
<CommandString>smoke red;red smoke</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F3}{F2}{F2}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_smoke_white">
<CommandString>smoke white;white smoke</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F3}{F2}{F3}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_smoke_orange">
<CommandString>smoke orange;orange smoke</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F3}{F2}{F4}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_smoke_blue">
<CommandString>smoke blue;blue smoke</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F3}{F2}{F5}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<!-- NAVIGATION -->
<Command Id="cmd_vectors_crate">
<CommandString>vectors to crate;find crate;nearest crate</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F4}{F1}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_vectors_pickup">
<CommandString>vectors to pickup;find pickup zone;nearest pickup</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F4}{F2}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_smoke_nearest_zone">
<CommandString>smoke nearest zone;mark nearest zone</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F4}{F3}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_smoke_all_zones">
<CommandString>smoke all zones;mark all zones;smoke nearby zones</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F4}{F4}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_vectors_mash">
<CommandString>vectors to mash;find mash;nearest mash</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F4}{F6}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_hover_coach_enable">
<CommandString>enable hover coach;hover coach on</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F4}{F7}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_hover_coach_disable">
<CommandString>disable hover coach;hover coach off</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F4}{F8}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<!-- STATUS & ADMIN -->
<Command Id="cmd_show_status">
<CommandString>show status;ctld status;check status</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F5}{F2}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_draw_zones">
<CommandString>draw zones on map;show zones;mark zones on map</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F5}{F3}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_clear_map">
<CommandString>clear map drawings;clear map marks;remove zone marks</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F5}{F4}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_medevac_stats">
<CommandString>medevac statistics;medevac stats;show medevac stats</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F5}{F5}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<!-- QUICK ACCESS COMBOS -->
<Command Id="cmd_quick_pickup">
<CommandString>quick pickup;pickup mode</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F1}{F1}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_quick_deploy">
<CommandString>quick deploy;fast deploy</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F1}{F3}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
<Command Id="cmd_quick_build">
<CommandString>quick build;fast build</CommandString>
<ActionSequence>
<CommandAction>
<Context>Send keys to active window</Context>
<KeyCodes>{RALT}\\{F2}{F2}{F1}</KeyCodes>
</CommandAction>
</ActionSequence>
</Command>
</Commands>
</Profile>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,587 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>CTLD VoiceAttack Profile &mdash; Command Reference</title>
<style>
:root {
color-scheme: light dark;
--bg: #0f141a;
--bg-alt: #162029;
--fg: #f0f3f6;
--fg-muted: #c8d2dd;
--accent: #2f8dda;
--accent-soft: rgba(47, 141, 218, 0.14);
--border: rgba(240, 243, 246, 0.14);
--border-strong: rgba(240, 243, 246, 0.28);
}
body {
margin: 0;
font-family: "Segoe UI", "Roboto", sans-serif;
font-size: 15px;
line-height: 1.6;
background: var(--bg);
color: var(--fg);
}
main {
margin: 0 auto;
padding: 48px 32px 64px;
max-width: 1180px;
}
header {
position: sticky;
top: 0;
margin: -48px -32px 36px;
padding: 36px 32px 24px;
background: linear-gradient(160deg, rgba(47, 141, 218, 0.35), rgba(15, 20, 26, 0.0));
border-bottom: 1px solid var(--border);
backdrop-filter: blur(10px);
}
h1 {
margin: 0 0 4px;
font-size: 30px;
letter-spacing: 0.02em;
}
h2 {
margin-top: 44px;
margin-bottom: 12px;
font-size: 22px;
color: var(--accent);
}
p.lead {
margin: 8px 0 16px;
color: var(--fg-muted);
max-width: 880px;
}
.callout {
background: var(--bg-alt);
border: 1px solid var(--border);
border-radius: 12px;
padding: 18px 22px;
margin-bottom: 28px;
box-shadow: 0 16px 32px rgba(0, 0, 0, 0.22);
}
.callout strong {
color: var(--accent);
}
table {
width: 100%;
border-collapse: collapse;
background: var(--bg-alt);
border: 1px solid var(--border);
border-radius: 12px;
overflow: hidden;
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.18);
}
thead {
background: rgba(47, 141, 218, 0.18);
color: var(--fg);
text-transform: uppercase;
letter-spacing: 0.05em;
font-size: 12px;
}
th, td {
padding: 14px 18px;
vertical-align: top;
border-bottom: 1px solid var(--border);
}
tbody tr:last-child td {
border-bottom: none;
}
tbody tr:nth-child(odd) {
background: rgba(255, 255, 255, 0.02);
}
code {
font-family: "Cascadia Code", "Fira Code", monospace;
font-size: 13px;
background: rgba(255, 255, 255, 0.04);
padding: 2px 6px;
border-radius: 6px;
border: 1px solid var(--border);
}
ul {
padding-left: 22px;
margin: 0;
}
.phrases span {
display: inline-block;
background: var(--accent-soft);
color: var(--accent);
border: 1px solid rgba(47, 141, 218, 0.35);
border-radius: 999px;
padding: 4px 12px;
margin: 2px 6px 2px 0;
font-size: 13px;
}
footer {
margin-top: 64px;
font-size: 13px;
color: var(--fg-muted);
border-top: 1px solid var(--border);
padding-top: 18px;
}
@media (max-width: 900px) {
main {
padding: 36px 18px 48px;
}
header {
margin: -36px -18px 24px;
padding: 28px 18px 18px;
}
table, thead, tbody, th, td, tr {
display: block;
}
thead {
display: none;
}
tbody tr {
margin-bottom: 18px;
border: 1px solid var(--border);
border-radius: 10px;
overflow: hidden;
}
td {
border: none;
border-bottom: 1px solid var(--border);
}
td::before {
content: attr(data-label);
display: block;
font-weight: 600;
margin-bottom: 6px;
color: var(--accent);
text-transform: uppercase;
letter-spacing: 0.05em;
font-size: 11px;
}
tbody tr:last-child td {
border-bottom: none;
}
}
</style>
</head>
<body>
<main>
<header>
<h1>CTLD VoiceAttack Command Reference</h1>
<p class="lead">All phrases below assume the VoiceAttack profile sends <code>Right&nbsp;Alt&nbsp;+&nbsp;Backslash</code> to open the radio menu, then <code>F10 &gt; F2</code> to enter the CTLD root. Speak any phrase shown to run the navigation sequence automatically.</p>
</header>
<section class="callout">
<strong>Pro Tip:</strong> Fine-tune the pause durations inside VoiceAttack if your DCS instance needs more/less time for menus to populate. You can also add your own synonyms by editing the command string list for any entry.
</section>
<h2>Operations &mdash; Troop Transport</h2>
<table>
<thead>
<tr>
<th scope="col">Phrases</th>
<th scope="col">Action</th>
<th scope="col">Menu Path</th>
</tr>
</thead>
<tbody>
<tr>
<td class="phrases" data-label="Phrases">
<span>load troops</span>
<span>load infantry</span>
</td>
<td data-label="Action">Load default troop package.</td>
<td data-label="Menu Path">Operations → Troop Transport → Load Troops</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>load assault squad</span>
<span>load assault team</span>
</td>
<td data-label="Action">Load Assault Squad preset (AS).</td>
<td data-label="Menu Path">Operations → Troop Transport → Load Troops (Type) → Assault Squad</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>load manpads team</span>
<span>load aa squad</span>
</td>
<td data-label="Action">Load MANPADS Team preset (AA).</td>
<td data-label="Menu Path">Operations → Troop Transport → Load Troops (Type) → MANPADS Team</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>load anti tank team</span>
<span>load at squad</span>
</td>
<td data-label="Action">Load Anti-Tank Team preset (AT).</td>
<td data-label="Menu Path">Operations → Troop Transport → Load Troops (Type) → AT Team</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>load mortar team</span>
<span>load mortar squad</span>
</td>
<td data-label="Action">Load Mortar Team preset (AR).</td>
<td data-label="Menu Path">Operations → Troop Transport → Load Troops (Type) → Mortar Team</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>deploy troops hold</span>
<span>deploy hold</span>
</td>
<td data-label="Action">Unload troops with Hold/Defend behavior.</td>
<td data-label="Menu Path">Operations → Troop Transport → Deploy [Hold Position]</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>deploy troops attack</span>
<span>deploy attack</span>
</td>
<td data-label="Action">Unload troops with Attack/Advance behavior.</td>
<td data-label="Menu Path">Operations → Troop Transport → Deploy [Attack]</td>
</tr>
</tbody>
</table>
<h2>Operations &mdash; Build</h2>
<table>
<thead>
<tr>
<th scope="col">Phrases</th>
<th scope="col">Action</th>
<th scope="col">Menu Path</th>
</tr>
</thead>
<tbody>
<tr>
<td class="phrases" data-label="Phrases">
<span>build here</span>
<span>build at position</span>
</td>
<td data-label="Action">Build using nearby crates (with confirm/cooldown rules).</td>
<td data-label="Menu Path">Operations → Build → Build Here</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>open build advanced</span>
<span>build advanced menu</span>
</td>
<td data-label="Action">Open the dynamic build menu.</td>
<td data-label="Menu Path">Operations → Build → Build (Advanced)</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>open buildable near you</span>
<span>show buildable list</span>
</td>
<td data-label="Action">Focus the “Buildable Near You” submenu.</td>
<td data-label="Menu Path">Operations → Build → Build (Advanced) → Buildable Near You</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>refresh build list</span>
<span>refresh buildable list</span>
</td>
<td data-label="Action">Rescan crate availability for builds.</td>
<td data-label="Menu Path">Operations → Build → Refresh Buildable List</td>
</tr>
</tbody>
</table>
<h2>Operations &mdash; MEDEVAC</h2>
<table>
<thead>
<tr>
<th scope="col">Phrases</th>
<th scope="col">Action</th>
<th scope="col">Menu Path</th>
</tr>
</thead>
<tbody>
<tr>
<td class="phrases" data-label="Phrases">
<span>list medevac requests</span>
<span>active medevac</span>
</td>
<td data-label="Action">Show all active MEDEVAC crews.</td>
<td data-label="Menu Path">Operations → MEDEVAC → List Active MEDEVAC Requests</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>nearest medevac location</span>
<span>medevac location</span>
</td>
<td data-label="Action">Display nearest crew position.</td>
<td data-label="Menu Path">Operations → MEDEVAC → Nearest MEDEVAC Location</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>check salvage points</span>
<span>show salvage</span>
</td>
<td data-label="Action">Report coalition salvage totals.</td>
<td data-label="Menu Path">Operations → MEDEVAC → Coalition Salvage Points</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>vectors to medevac</span>
<span>medevac vectors</span>
</td>
<td data-label="Action">Provide bearing/range to nearest crew.</td>
<td data-label="Menu Path">Operations → MEDEVAC → Vectors to Nearest MEDEVAC</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>show mash locations</span>
<span>list mash</span>
</td>
<td data-label="Action">List all MASH delivery zones.</td>
<td data-label="Menu Path">Operations → MEDEVAC → MASH Locations</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>smoke crew locations</span>
<span>mark crews</span>
</td>
<td data-label="Action">Drop smoke on every active crew.</td>
<td data-label="Menu Path">Operations → MEDEVAC → Pop Smoke at Crew Locations</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>smoke mash zones</span>
<span>mark mash</span>
</td>
<td data-label="Action">Drop smoke on all MASH zones.</td>
<td data-label="Menu Path">Operations → MEDEVAC → Pop Smoke at MASH Zones</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>medevac guide</span>
<span>salvage guide</span>
</td>
<td data-label="Action">Show in-game MEDEVAC/salvage quick reference.</td>
<td data-label="Menu Path">Operations → MEDEVAC → MASH &amp; Salvage System Guide</td>
</tr>
</tbody>
</table>
<h2>Logistics</h2>
<table>
<thead>
<tr>
<th scope="col">Phrases</th>
<th scope="col">Action</th>
<th scope="col">Menu Path</th>
</tr>
</thead>
<tbody>
<tr>
<td class="phrases" data-label="Phrases">
<span>open request crate</span>
<span>request crate menu</span>
</td>
<td data-label="Action">Open the crate request submenu (choose item manually).</td>
<td data-label="Menu Path">Logistics → Request Crate</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>open recipe info</span>
<span>recipe info menu</span>
</td>
<td data-label="Action">Open recipe info submenu.</td>
<td data-label="Menu Path">Logistics → Recipe Info</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>drop one crate</span>
<span>drop crate</span>
</td>
<td data-label="Action">Drop a single loaded crate.</td>
<td data-label="Menu Path">Logistics → Crate Management → Drop One Loaded Crate</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>drop all crates</span>
<span>drop cargo</span>
</td>
<td data-label="Action">Drop every loaded crate.</td>
<td data-label="Menu Path">Logistics → Crate Management → Drop All Loaded Crates</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>remark nearest crate</span>
<span>smoke crate</span>
</td>
<td data-label="Action">Smoke the nearest friendly crate.</td>
<td data-label="Menu Path">Logistics → Crate Management → Re-mark Nearest Crate (Smoke)</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>show zone inventory</span>
<span>check inventory</span>
</td>
<td data-label="Action">Show stock at nearest supply/FOB zone.</td>
<td data-label="Menu Path">Logistics → Show Inventory at Nearest Zone</td>
</tr>
</tbody>
</table>
<h2>Field Tools</h2>
<table>
<thead>
<tr>
<th scope="col">Phrases</th>
<th scope="col">Action</th>
<th scope="col">Menu Path</th>
</tr>
</thead>
<tbody>
<tr>
<td class="phrases" data-label="Phrases">
<span>create drop zone</span>
<span>mark drop zone</span>
</td>
<td data-label="Action">Create a player drop zone (AO).</td>
<td data-label="Menu Path">Field Tools → Create Drop Zone (AO)</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>smoke green</span>
<span>green smoke</span>
</td>
<td data-label="Action">Drop green smoke at your position.</td>
<td data-label="Menu Path">Field Tools → Smoke My Location → Green</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>smoke red</span>
<span>red smoke</span>
</td>
<td data-label="Action">Drop red smoke at your position.</td>
<td data-label="Menu Path">Field Tools → Smoke My Location → Red</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>smoke white</span>
<span>white smoke</span>
</td>
<td data-label="Action">Drop white smoke at your position.</td>
<td data-label="Menu Path">Field Tools → Smoke My Location → White</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>smoke orange</span>
<span>orange smoke</span>
</td>
<td data-label="Action">Drop orange smoke at your position.</td>
<td data-label="Menu Path">Field Tools → Smoke My Location → Orange</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>smoke blue</span>
<span>blue smoke</span>
</td>
<td data-label="Action">Drop blue smoke at your position.</td>
<td data-label="Menu Path">Field Tools → Smoke My Location → Blue</td>
</tr>
</tbody>
</table>
<h2>Navigation &amp; Hover Coach</h2>
<table>
<thead>
<tr>
<th scope="col">Phrases</th>
<th scope="col">Action</th>
<th scope="col">Menu Path</th>
</tr>
</thead>
<tbody>
<tr>
<td class="phrases" data-label="Phrases">
<span>vectors to crate</span>
<span>find crate</span>
</td>
<td data-label="Action">Show bearing/range to nearest friendly crate.</td>
<td data-label="Menu Path">Navigation → Request Vectors to Nearest Crate</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>vectors to pickup zone</span>
<span>find pickup zone</span>
</td>
<td data-label="Action">Show bearing/range to nearest supply zone.</td>
<td data-label="Menu Path">Navigation → Vectors to Nearest Pickup Zone</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>smoke nearest zone</span>
<span>mark nearest zone</span>
</td>
<td data-label="Action">Smoke the closest zone (pickup/drop/FOB/MASH).</td>
<td data-label="Menu Path">Navigation → Smoke Nearest Zone (Pickup/Drop/FOB/MASH)</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>smoke all zones</span>
<span>mark all zones</span>
</td>
<td data-label="Action">Smoke every zone within 5&nbsp;km.</td>
<td data-label="Menu Path">Navigation → Smoke All Nearby Zones (5km)</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>vectors to medevac crew</span>
<span>find medevac crew</span>
</td>
<td data-label="Action">Show bearing/range to the nearest crew (shortcut).</td>
<td data-label="Menu Path">Navigation → Vectors to Nearest MEDEVAC Crew</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>vectors to mash</span>
<span>find mash</span>
</td>
<td data-label="Action">Show bearing/range to nearest MASH.</td>
<td data-label="Menu Path">Navigation → Vectors to Nearest MASH</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>enable hover coach</span>
<span>hover coach on</span>
</td>
<td data-label="Action">Enable hover coach prompts for this group.</td>
<td data-label="Menu Path">Navigation → Hover Coach: Enable</td>
</tr>
<tr>
<td class="phrases" data-label="Phrases">
<span>disable hover coach</span>
<span>hover coach off</span>
</td>
<td data-label="Action">Disable hover coach prompts for this group.</td>
<td data-label="Menu Path">Navigation → Hover Coach: Disable</td>
</tr>
</tbody>
</table>
<footer>
Generated for <code>CTLD_VoiceAttack_Profile_F10.vap</code> (Right Alt + Backslash → F10 → F2). Tweak phrases or delays directly inside VoiceAttack to match your mission&apos;s pace.
</footer>
</main>
</body>
</html>

View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-16"?>
<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>DCS CTLD Menu Navigation</Name>
<Id>a8f7c9d2-4e6b-4c1a-9f3e-2a8d7c6b5e4f</Id>
<Commands>
<!-- OPERATIONS: TROOP TRANSPORT -->
<Command>
<CommandString>load troops</CommandString>
<ActionSequence>
<CommandAction>
<Id>3a7f2b1e-8c4d-4f9a-b2e1-5d6c7a8b9c0d</Id>
<ActionType>PressKey</ActionType>
<Delay>0</Delay>
<KeyCodes>
<unsignedShort>165</unsignedShort>
</KeyCodes>
</CommandAction>
<CommandAction>
<Id>3a7f2b1e-8c4d-4f9a-b2e1-5d6c7a8b9c0e</Id>
<ActionType>Pause</ActionType>
<Delay>200</Delay>
</CommandAction>
<CommandAction>
<Id>3a7f2b1e-8c4d-4f9a-b2e1-5d6c7a8b9c0f</Id>
<ActionType>PressKey</ActionType>
<Delay>0</Delay>
<KeyCodes>
<unsignedShort>220</unsignedShort>
</KeyCodes>
</CommandAction>
<CommandAction>
<Id>3a7f2b1e-8c4d-4f9a-b2e1-5d6c7a8b9c10</Id>
<ActionType>Pause</ActionType>
<Delay>300</Delay>
</CommandAction>
<CommandAction>
<Id>3a7f2b1e-8c4d-4f9a-b2e1-5d6c7a8b9c11</Id>
<ActionType>PressKey</ActionType>
<Delay>0</Delay>
<KeyCodes>
<unsignedShort>113</unsignedShort>
</KeyCodes>
</CommandAction>
<CommandAction>
<Id>3a7f2b1e-8c4d-4f9a-b2e1-5d6c7a8b9c12</Id>
<ActionType>Pause</ActionType>
<Delay>300</Delay>
</CommandAction>
<CommandAction>
<Id>3a7f2b1e-8c4d-4f9a-b2e1-5d6c7a8b9c13</Id>
<ActionType>PressKey</ActionType>
<Delay>0</Delay>
<KeyCodes>
<unsignedShort>112</unsignedShort>
</KeyCodes>
</CommandAction>
<CommandAction>
<Id>3a7f2b1e-8c4d-4f9a-b2e1-5d6c7a8b9c14</Id>
<ActionType>Pause</ActionType>
<Delay>300</Delay>
</CommandAction>
<CommandAction>
<Id>3a7f2b1e-8c4d-4f9a-b2e1-5d6c7a8b9c15</Id>
<ActionType>PressKey</ActionType>
<Delay>0</Delay>
<KeyCodes>
<unsignedShort>112</unsignedShort>
</KeyCodes>
</CommandAction>
</ActionSequence>
<Id>3a7f2b1e-8c4d-4f9a-b2e1-5d6c7a8b9c0d</Id>
</Command>
</Commands>
</Profile>

View File

@ -263,7 +263,7 @@ local troops = {}
troops['AS'] = {
label = 'Assault Squad',
size = 8,
unitsBlue = { 'Soldier M4', 'Infantry M249' },
unitsBlue = { 'Soldier M4', 'Soldier M249' },
unitsRed = { 'Infantry AK', 'Infantry AK' },
units = { 'Infantry AK' },
}