add initial As-Is Analysis and Modernization Plan documents

This commit is contained in:
David Pierron
2026-04-01 18:10:25 +02:00
parent e59bc50e6c
commit 9302203f09
3 changed files with 704 additions and 0 deletions
+265
View File
@@ -0,0 +1,265 @@
# 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
```text
.
├── 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)
```lua
-- 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.