Files
DCS-CTLD/.github/AS-IS-ANALYSIS.md

9.6 KiB
Raw Permalink Blame History

DCS-CTLD — As-Is Analysis

This document captures the current state of the CTLD codebase prior to the v2 modernization effort. It serves as a reference and justification for the changes outlined in MODERNIZATION-PLAN.md.


1. Overview

Metric Value
Primary script CTLD.lua
Lines of code ~8 700
i18n script CTLD-i18n.lua
Bundled dependency mist.lua (MIST 4.5 build 128-DYNSLOTS-02)
Lua version 5.1 (DCS sandbox)
Public functions (ctld.*) 100+
Local / private functions 0 (everything is public on the ctld table)
OOP / metatables usage None — fully procedural
Unit tests None

2. File structure

.
├── CTLD.lua                  -- Main script (monolith)
├── CTLD-i18n.lua             -- Translation tables (FR, ES, KO)
├── mist.lua                  -- MIST library (stock, not customized)
├── beacon.ogg                -- Radio beacon sound
├── beaconsilent.ogg          -- Silent beacon sound (FC3)
├── README.md                 -- User / mission-maker guide
├── demo-mission.miz
├── test-mission.miz
├── test-dev-dynamic.miz
├── test-dev-static.miz
├── test_witchcraft_#131.miz
└── test_witchcraft_#137 et #149.miz

No src/, no test/, no docs/, no CI configuration.


3. CTLD.lua section breakdown

Section Lines Content
Header + contributors 135 Credits, links
i18n table setup 36360 English reference keys (all = ""), i18n_translate()
USER CONFIGURATION 403600 50+ tunable parameters
Crate configuration 6011 200 ctld.spawnableCrates, AA system templates
Public API functions 1 2001 950 Functions usable from DO SCRIPT triggers
Core gameplay logic 1 9504 600 Troops, vehicles, crates, FOBs, beacons
JTAC subsystem 4 6007 000 Targeting, lasing, IR points, F10 menus
AI processing + menus 7 0008 200 AI auto-load/unload, F10 menu building
ctld.initialize() 8 1908 400 State tables init, zone parsing
Event handler + tools 8 4008 705 DCS event handler, ctld.tools utilities

4. State management

34 global tables inside the ctld namespace track runtime state. Most are duplicated per coalition.

4.1 — Coalition-duplicated tables (RED / BLUE pairs)

Table pair Content
ctld.spawnedCratesRED / BLUE Spawned crate statics
ctld.droppedTroopsRED / BLUE Deployed infantry groups
ctld.droppedVehiclesRED / BLUE Deployed vehicles
ctld.droppedFOBCratesRED / BLUE FOB crates on ground

This duplication creates 50+ if coalition == 1 then … RED … else … BLUE branches.

4.2 — Shared tables

Table Content
ctld.inTransitTroops Cargo currently onboard (keyed by unit name)
ctld.inTransitSlingLoadCrates Simulated sling-load crates
ctld.builtFOBS Completed FOB positions
ctld.completeAASystems Assembled AA system groups
ctld.deployedRadioBeacons Active beacons
ctld.fobBeacons FOB beacon cache (refreshed every 60 s)
ctld.extractZones Extract zone definitions
ctld.hoverStatus Hover-over-crate tracking
ctld.crateLookupTable Crate weight → type lookup
ctld.callbacks Registered callback functions
ctld.jtacUnits JTAC unit references
ctld.jtacCurrentTargets JTAC active targets
ctld.jtacSelectedTarget Player-selected JTAC targets
ctld.jtacGeneratedLaserCodes Allocated laser codes
ctld.usedUHFFrequencies / VHF / FM Radio frequency pools

5. Code duplication patterns

5.1 — RED/BLUE branching (most pervasive)

-- This pattern appears 50+ times
if _heli:getCoalition() == 1 then
    _list = ctld.droppedTroopsRED
else
    _list = ctld.droppedTroopsBLUE
end

5.2 — Troop / Vehicle symmetry

Many functions have near-identical troop and vehicle variants differentiated only by a boolean parameter (true = troops, false = vehicles).

5.3 — Sling load vs simulated load

Two code paths for crate pickup depending on ctld.slingLoad:

  • Real sling load (DCS native, crashy)
  • Simulated hover load (custom implementation)

5.4 — Zone handling

Pickup zones, dropoff zones, and waypoint zones share similar parsing (smoke color, coalition check, active flag) but are implemented separately.


6. MIST dependency

91 calls to mist.* functions across the codebase.

Category Functions Call count
Utility deepCopy, round, makeVec2/3 ~28
Distance / vectors get2DDist, vec.mag, vec.dp, vec.sub ~15
Heading / bearing getHeading ~8
Coordinate format tostringLL, tostringMGRS ~4
Spawning dynAdd, dynAddStatic ~8
Route / waypoints buildWP, getGroupRoute ~4
LOS / search getUnitsLOS, getAvgPos, makeUnitTable ~4
Database mist.DBs.unitsByName iterated
Scheduling mist.scheduleFunction ~1
Other misc ~19

No functions provide a fallback if MIST is absent — CTLD hard-crashes on assert(mist ~= nil) during initialization.


7. Scheduling and timers

20+ timer.scheduleFunction calls drive recurring behavior. All timers reschedule themselves recursively; there are no continuous polling loops.

Timer Interval Purpose
checkTransportStatus 3 s Monitor transport helicopters
checkHoverStatus 1 s Track hover-over-crate countdown
refreshRadioBeacons 60 s Update beacon battery status
refreshSmoke 300 s Refresh smoke markers
checkAIStatus 2 s AI troop behavior check
timerJTACAutoLase variable JTAC targeting loop
timerLaseUnit variable Single-unit lasing
autoUpdateRepackMenu 1 s Refresh vehicle repacking F10 menu
reconRefreshTargetsInLosOnF10Map variable RECON map markers

8. Error handling

  • pcall usage: 12 instances, mainly around crate spawning and hover math.
  • Nil checks: Extensive if X == nil then return end before DCS API calls.
  • No structured error propagation: errors are logged via env.error() / ctld.logError() and silently swallowed.
  • No stack traces or exception chaining.

9. Internationalization (i18n)

Language Code translation_version Completeness
English en 1.6 Reference (keys only, values = "")
French fr 1.6 Partial — many crate/equipment names empty
Spanish es 1.6 Similar to French
Korean ko 1.1 Severely outdated, many missing keys

Issues:

  • No tooling to detect missing keys or version drift.
  • Empty string ("") is a valid Lua value, so missing translations silently fall back to the English key (which is also "" for reference entries).
  • All translations live in a single CTLD-i18n.lua file — no per-language separation.

10. Documentation

Audience Coverage Location
Mission maker Partial README.md (setup, config, API examples)
Player Minimal README.md (gameplay mechanics mentioned briefly)
Developer None No architecture doc, no contributing guide

README strengths:

  • Good coverage of pickup/dropoff zone configuration.
  • Code examples for DO SCRIPT functions.
  • Dynamic loading workflow documented.

README gaps:

  • JTAC advanced features poorly explained.
  • No API reference table (signatures, parameters, return values).
  • No architecture or data flow diagrams.
  • Some examples use different defaults than the current code.

11. Testing

  • No automated tests of any kind.
  • Manual smoke testing via .miz missions in the repository:
    • test-mission.miz — full feature demonstration
    • test-dev-dynamic.miz — dynamic script loading for fast iteration
    • test-dev-static.miz — static loading variant
    • test_witchcraft_#131.miz, test_witchcraft_#137 et #149.miz — bug repro missions
  • No test framework, no mocks, no CI.

12. Dead code and technical debt

Item Location Detail
Commented-out blocks 18+ blocks across file Old implementations, debug markers, disabled alternatives
Unused function ctld.tools.getRelativeBearing Defined but never called
Unused function ctld.tools.isValueInIpairTable Called once, could be inlined
Commented event handler ctld.initialize() Old ctld.eventHandler pattern, replaced but not removed
Disabled vehicle types Crate config tables Many entries commented out (-- BUK, -- Strela, etc.)
Debug markers Various --ctld.logTrace("FG_ XXXX...") left in code
Alternate coordinate ctld.listFOBS() MGRS conversion commented out

13. Summary of pain points

  1. Monolithic file: 8 700 lines, impossible to navigate or review efficiently.
  2. No encapsulation: 100+ public functions, 0 local functions, all state is global.
  3. RED/BLUE duplication: 50+ coalition branches + paired tables.
  4. MIST hard dependency: 91 calls, no fallback, no abstraction layer.
  5. No tests: zero automated tests, zero mocks, zero CI.
  6. No OOP: purely procedural, no classes, no metatables.
  7. Dead code: 18+ commented blocks, unused functions.
  8. i18n drift: Korean 3 versions behind, many empty translations.
  9. No developer documentation: new contributors must read 8 700 lines to understand the architecture.
  10. No build system: the source file IS the deliverable.