Compare commits

...

178 Commits

Author SHA1 Message Date
David Pierron 9302203f09 add initial As-Is Analysis and Modernization Plan documents 2026-04-01 18:10:25 +02:00
David Pierron e59bc50e6c version pushed to 1.6.0-alpha (for testing) 2025-11-22 11:53:11 +01:00
FullGas1 c12c0b242d Work by Fullgas on multiple issues and new features
* Indicate obligation to use MIST delivered with CTLD

* update ctld.dynamicCargoUnits table

* Indicate obligation to use MIST delivered with CTLD

* MIST madatory in red

* MIST mandatory in red

* fix mist.utils.getHeadingPoints calls

* commit

* fix #164 Issue-wrong12oclock msg

* commit ctld.tools.getRelativeBearing()

* commit
2025-11-22 11:50:10 +01:00
David Pierron 659268d3f5 Merge branch 'master' into develop 2025-09-27 18:53:23 +02:00
David Pierron 041a9ab6af small corrections to PR153 2025-07-22 15:24:20 +02:00
David Pierron 8d73c966db PR153 - multiple changes from FullGas1
Issue #137: Repack vehicles in crates
Issue #139: MQ9 autolase follow a moving target
Issue #151: Patriot Crate spawning into Chinook rear rotor
Issue #131: Limit Number of Troops in the game
2025-07-22 15:18:30 +02:00
FullGas1 af3e4fab17 commit 2025-05-20 17:46:02 +02:00
FullGas1 97e7c72144 fix "es" dictionary 2025-05-16 14:34:11 +02:00
FullGas1 65336fdab8 Final commit 2025-05-10 15:30:25 +02:00
FullGas1 61db3e9f93 Commit 2025-05-10 12:04:46 +02:00
FullGas1 a1da0ea1c4 Last fix commit !? 2025-05-10 12:04:18 +02:00
FullGas1 782940265d commit 2025-05-10 01:33:15 +02:00
FullGas1 b5cd8929f3 commit 2025-05-09 15:25:34 +02:00
FullGas1 1826d28a86 commit 2025-05-09 14:33:54 +02:00
FullGas1 359bf1418d commit 2025-05-09 11:54:54 +02:00
FullGas1 e3424c6af5 commit 2025-05-09 11:01:38 +02:00
FullGas1 1ac3b3f8a9 Merge branch 'Issues-#137-Repack-Vehicles-In-Crates' of https://github.com/FullGas1/DCS-CTLD_FG into Issues-#137-Repack-Vehicles-In-Crates 2025-05-09 10:15:41 +02:00
FullGas1 e13e630830 commit 2025-05-09 10:07:00 +02:00
FullGas1 7bfed7ef55 bommit fix 2025-05-08 19:30:19 +02:00
FullGas1 8bfaba399f bugs fix 2025-05-04 23:46:00 +02:00
FullGas1 4dada3d24d Merge branch 'Issues-#137-Repack-Vehicles-In-Crates' of https://github.com/FullGas1/DCS-CTLD_FG into Issues-#137-Repack-Vehicles-In-Crates 2025-05-03 16:10:34 +02:00
FullGas1 74b40fe3cb fix bug 2025-05-03 16:10:22 +02:00
FullGas1 aa8bc78b27 #131 test.miz 2025-04-26 13:50:01 +02:00
FullGas1 7286a6a010 Issue #131-Limit-Number-of-Troops 2025-04-26 13:45:31 +02:00
FullGas1 c8bb41648c Issue #131-Limit-Number-of-Troops 2025-04-26 13:44:25 +02:00
FullGas1 08635622b0 load temporary test .miz 2025-04-21 22:49:33 +02:00
FullGas1 42e8549649 commit 2025-04-21 22:48:32 +02:00
FullGas1 5c48a9d756 commit 2025-04-21 21:27:07 +02:00
FullGas1 f3983c6a90 Merge branch 'Issues-#137-Repack-Vehicles-In-Crates' of https://github.com/FullGas1/DCS-CTLD_FG into Issues-#137-Repack-Vehicles-In-Crates 2025-04-21 21:04:19 +02:00
FullGas1 1c66408127 Readme update 2025-04-21 21:04:17 +02:00
FullGas1 3ac2b3b22c commit 2025-04-21 16:49:55 +02:00
FullGas1 c576268d87 commit 2025-04-21 14:10:41 +02:00
FullGas1 35f52d543a commit 2025-04-21 14:09:18 +02:00
FullGas1 c608d00d15 commit #137 2025-04-21 13:29:31 +02:00
FullGas1 d2789f554a debug #137 2025-04-21 02:51:14 +02:00
FullGas1 fcef6a66d1 debug #137 2025-04-21 01:44:55 +02:00
FullGas1 dd71451194 debug #137 Repack 2025-04-20 22:55:49 +02:00
FullGas1 807e81e389 debug #137 2025-04-20 14:51:25 +02:00
FullGas1 33d8810ebb commit #149 drone follow target 2025-04-20 14:13:32 +02:00
FullGas1 87e8a31f31 debug 2025-04-20 14:06:58 +02:00
FullGas1 e4a0fff931 debug 2025-04-20 12:38:18 +02:00
FullGas1 ca5bf76c78 debug 2025-04-20 00:55:26 +02:00
FullGas1 f8659c5de6 debug 2025-04-19 01:49:10 +02:00
FullGas1 9a0cc8eeee debug 2025-04-17 23:48:58 +02:00
FullGas1 a706890cb6 debug 2025-04-17 23:48:37 +02:00
FullGas1 815684dd77 commit 2025-04-17 00:04:22 +02:00
FullGas1 0ccb2ba7bb debug 2025-04-13 23:14:21 +02:00
FullGas1 1e471df264 debug #159 jtac autoorbiting 2025-04-13 22:07:53 +02:00
FullGas1 cc8b916870 debug 2025-04-09 00:54:01 +02:00
FullGas1 cd62d0c60a Merge branch 'Issues-#137-Repack-Vehicles-In-Crates' of https://github.com/FullGas1/DCS-CTLD_FG into Issues-#137-Repack-Vehicles-In-Crates 2025-04-07 23:46:41 +02:00
FullGas1 a35e023752 #149 Flying JTAC orbit on target 2025-04-07 23:46:37 +02:00
FullGas1 f71e7f3213 commit 2025-04-06 22:31:37 +02:00
FullGas1 a468faefec commit 2025-04-06 21:53:15 +02:00
FullGas1 99f2c7aec0 commit 2025-04-06 19:26:06 +02:00
FullGas1 7db8e2d772 commit 2025-04-06 19:19:57 +02:00
FullGas1 026099bd12 commit 2025-04-06 19:19:45 +02:00
FullGas1 82a330e61a commit 2025-04-06 19:04:35 +02:00
FullGas1 b3470250e4 commit 2025-04-06 17:28:54 +02:00
FullGas1 bbde4ae62b comiit 2025-04-06 17:16:28 +02:00
FullGas1 540a316754 commit 2025-04-06 17:12:44 +02:00
FullGas1 574217d931 commit 2025-04-06 17:02:08 +02:00
FullGas1 1fce52088d commit 2025-04-06 11:15:16 +02:00
FullGas1 4d704a489e commit 2025-04-06 11:13:50 +02:00
FullGas1 da80f9ea06 commit 2025-04-06 11:09:38 +02:00
FullGas1 93260908c4 debug 2025-04-05 19:39:42 +02:00
FullGas1 3c261e8dc2 debug 2025-04-04 21:52:40 +02:00
FullGas1 7b7eb62bf0 debug 2025-04-03 23:48:00 +02:00
FullGas1 951ee37903 debbug 2025-04-03 21:45:46 +02:00
FullGas1 3a7ab50834 debug 2025-04-03 20:36:50 +02:00
FullGas1 9a69d4b52c debug 2025-04-03 16:32:55 +02:00
FullGas1 0345d16150 debug 2025-04-03 02:02:41 +02:00
FullGas1 d071fba20f debug 2025-04-03 01:10:03 +02:00
FullGas1 1a32ce6b57 debug 2025-04-03 00:50:30 +02:00
FullGas1 85275ad84b debug 2025-04-03 00:50:19 +02:00
FullGas1 819ba2de53 debug 2025-04-02 22:54:17 +02:00
FullGas1 8f34ad3902 debug 2025-04-02 22:19:34 +02:00
FullGas1 16f366d039 debug 2025-04-01 19:43:24 +02:00
FullGas1 2524320096 debug 2025-04-01 17:49:52 +02:00
FullGas1 e6b8c9ba14 ebug 2025-04-01 17:34:00 +02:00
FullGas1 a5b47503be Merge branch 'Issues-#137-Repack-Vehicles-In-Crates' of https://github.com/FullGas1/DCS-CTLD_FG into Issues-#137-Repack-Vehicles-In-Crates 2025-04-01 16:37:11 +02:00
FullGas1 aaa25dcd41 commit 2025-04-01 16:28:50 +02:00
FullGas1 e834dd1395 debug 2025-04-01 03:04:26 +02:00
FullGas1 774e499759 commit 2025-04-01 02:48:10 +02:00
FullGas1 0a1f4de471 commit 2025-04-01 02:22:35 +02:00
FullGas1 f9cd8b8b51 commit 2025-03-31 18:05:13 +02:00
FullGas1 3eef8d9a5d ctld.getNearbyUnits : sort by distance 2025-03-31 12:22:39 +02:00
FullGas1 e1b9e1d7d8 commit 2025-03-31 12:19:41 +02:00
FullGas1 ca976f4387 commit 2025-03-30 23:42:53 +02:00
FullGas1 91f74b73ed commit 2025-03-30 16:25:31 +02:00
FullGas1 f8df243043 commit 2025-03-30 15:42:07 +02:00
FullGas1 29b19d5262 commit 2025-03-30 15:24:20 +02:00
FullGas1 48aca9d488 commit 2025-03-30 15:07:49 +02:00
FullGas1 12741d0532 commit 2025-03-30 12:55:22 +02:00
FullGas1 6df583b9f1 commit 2025-03-30 12:23:40 +02:00
FullGas1 ca99c58f98 commit 2025-03-30 12:21:43 +02:00
FullGas1 879272a2e8 debug 2025-03-30 00:31:35 +01:00
FullGas1 267156e04e debug 2025-03-30 00:00:34 +01:00
FullGas1 6fa12ca46f debug 2025-03-29 23:49:50 +01:00
FullGas1 eb22f5dc67 debug 2025-03-29 23:20:10 +01:00
FullGas1 601805abb0 debug 2025-03-29 23:06:27 +01:00
FullGas1 e0e4279f20 debug 2025-03-29 23:00:17 +01:00
FullGas1 9023c571ba debug 2025-03-29 22:54:18 +01:00
FullGas1 72aab26e43 debug 2025-03-29 22:39:04 +01:00
FullGas1 aef146a6d8 debug 2025-03-29 22:16:48 +01:00
FullGas1 d8db662dc5 debug 2025-03-29 22:07:45 +01:00
FullGas1 e4f13f98b1 commit 2025-03-29 19:36:58 +01:00
FullGas1 c1aba95b6f for debug 2025-03-29 16:24:36 +01:00
FullGas1 d50bcfccd9 commit 2025-03-29 16:18:08 +01:00
FullGas1 f0f095e274 commit 2025-03-29 11:07:52 +01:00
FullGas1 69f04dfd57 commit 2025-03-29 10:53:37 +01:00
FullGas1 546f3feaae commit 2025-03-29 10:53:04 +01:00
FullGas1 23e83bf53a commit 2025-03-29 10:32:31 +01:00
FullGas1 ee07423588 Merge branch 'Issues-#137-Repack-Vehicles-In-Crates' of https://github.com/FullGas1/DCS-CTLD_FG into Issues-#137-Repack-Vehicles-In-Crates 2025-03-29 10:19:30 +01:00
FullGas1 96d801c342 commit 2025-03-29 10:19:27 +01:00
FullGas1 b1818d9fb3 update en dict version number 2025-03-29 09:57:57 +01:00
FullGas1 2bc6e76516 update fr & es dict version number 2025-03-29 09:57:33 +01:00
FullGas1 61a1fd42ee update dict versionnumber 2025-03-29 09:54:52 +01:00
FullGas1 954a6b0fad update dictionary 2025-03-29 09:48:35 +01:00
FullGas1 159915a6ac commit 2025-03-26 18:51:16 +01:00
FullGas1 d029e2479b commit 2025-03-26 18:43:54 +01:00
FullGas1 251467fee4 update dictionary 2025-03-26 18:39:35 +01:00
FullGas1 f3a9b44388 commit 2025-03-26 18:22:20 +01:00
FullGas1 f0adb72c49 comiit 2025-03-26 17:36:56 +01:00
FullGas1 ecc47bb247 fixes 2025-03-26 10:32:35 +01:00
FullGas1 0c74729837 fixes ctld.getSecureDistanceFromUnit 2025-03-26 10:32:10 +01:00
FullGas1 ef1d3d57e5 add ctld.getSecureDistanceFromUnit 2025-03-26 01:49:45 +01:00
FullGas1 b69f20eb6b add ctld.getSecureDistanceFromUnit fct 2025-03-26 01:31:53 +01:00
FullGas1 d80a70c0ee readme update 2025-03-26 01:18:09 +01:00
FullGas1 80fe5d59b0 readme update for repack 2025-03-26 01:00:37 +01:00
FullGas1 3eaa08b74e fixes 2025-03-26 00:01:15 +01:00
FullGas1 f83365ec63 fixes 2025-03-25 23:59:26 +01:00
FullGas1 0b3b1ea1f8 fixes 2025-03-25 23:59:06 +01:00
FullGas1 888d949234 fixes 2025-03-25 23:39:25 +01:00
FullGas1 75c9d0bf68 fixes 2025-03-25 18:10:39 +01:00
FullGas1 7517eaf188 fixes 2025-03-25 17:39:58 +01:00
FullGas1 1181fcfff7 fixes 2025-03-25 17:22:18 +01:00
FullGas1 9def2f1a3a fixes 2025-03-25 17:00:17 +01:00
FullGas1 9c25240c43 fixes 2025-03-25 16:33:09 +01:00
FullGas1 8a17ff52aa fixes 2025-03-25 15:24:12 +01:00
FullGas1 d125cdbe80 fixes 2025-03-25 15:14:03 +01:00
FullGas1 8dcaa3e0bb fixes 2025-03-25 15:05:28 +01:00
FullGas1 baf1231141 fixes 2025-03-25 14:57:32 +01:00
FullGas1 d1d9b55769 fixes 2025-03-25 14:55:10 +01:00
FullGas1 ff06dcecf7 fixes 2025-03-25 12:50:41 +01:00
FullGas1 dcdf6438a1 fixes 2025-03-25 12:29:25 +01:00
FullGas1 4d0062dee3 fixes 2025-03-25 11:37:16 +01:00
FullGas1 c618f4b282 fixes 2025-03-25 11:33:15 +01:00
FullGas1 b390d5dabf fixes 2025-03-25 11:22:57 +01:00
FullGas1 f4b81fd101 fixes 2025-03-25 11:20:40 +01:00
FullGas1 78aa8a010e fixes 2025-03-25 11:10:13 +01:00
FullGas1 6996769cec fixes 2025-03-25 11:04:00 +01:00
FullGas1 0d9c01283c fixes 2025-03-25 11:02:40 +01:00
FullGas1 fa1553a83e fixes 2025-03-24 16:09:58 +01:00
FullGas1 4db3c71728 fixes 2025-03-24 00:49:58 +01:00
FullGas1 0180cf33d2 fixes 2025-03-24 00:37:19 +01:00
FullGas1 c51a3d80ca fixes 2025-03-23 22:26:51 +01:00
FullGas1 9eb4fc66b5 fixes 2025-03-23 22:25:28 +01:00
FullGas1 8f2a335609 fixes 2025-03-23 22:12:19 +01:00
FullGas1 c5bae34ed1 fixes 2025-03-23 19:31:30 +01:00
FullGas1 6fc9f146ae fixes 2025-03-23 17:38:24 +01:00
FullGas1 b6232d3c15 fixes 2025-03-23 17:09:35 +01:00
FullGas1 111fd73b94 fixes 2025-03-23 17:03:37 +01:00
FullGas1 61d9e206b2 fixes 2025-03-23 16:58:32 +01:00
FullGas1 08ebd7e82d fixes 2025-03-23 16:54:27 +01:00
FullGas1 f152f58a97 fixes 2025-03-23 16:49:29 +01:00
FullGas1 38e86bead3 fixes 2025-03-23 16:37:30 +01:00
FullGas1 b0d8f8b5c7 fixes 2025-03-23 16:36:31 +01:00
FullGas1 a58efad985 fixes 2025-03-23 00:09:30 +01:00
FullGas1 0793d3bda5 fixes 2025-03-22 23:47:06 +01:00
FullGas1 c397bad107 fixes 2025-03-22 23:30:53 +01:00
FullGas1 791ee4e63e fixes 2025-03-22 23:02:57 +01:00
FullGas1 5aa37c52a4 fixes 2025-03-22 21:42:46 +01:00
FullGas1 fb26645996 add ctld.updateDynamicLogisticUnitsZones 2025-02-26 21:27:21 +01:00
FullGas1 3a3bcaf568 wip 2025-02-26 15:13:25 +01:00
FullGas1 fb804b4a22 1rst ok version 2025-02-26 15:05:22 +01:00
FullGas1 665bdddbdd wip 2025-02-26 03:34:05 +01:00
FullGas1 6beaedb79a ctld.getUnitsInRepackRadius(_PlayerTransportUnitName, _radius) added 2025-02-22 04:35:25 +01:00
FullGas1 9c2f982d03 ctld.getNearbyUnits 2025-02-21 23:48:02 +01:00
9 changed files with 787 additions and 13 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.
+364
View File
@@ -0,0 +1,364 @@
# DCS-CTLD Modernization Plan
> Status: **Draft**
> Branch: `next` (git flow, `main` stays stable)
> Target: CTLD v2.0
---
## Vision
Rewrite CTLD as a modern, modular, and testable Lua project while
temporarily preserving backward compatibility with existing missions.
The deliverable remains a single `.lua` file produced by an automated build.
---
## Architectural decisions
Key decisions made during the planning phase, for reference.
| # | Topic | Decision |
| - | ----- | -------- |
| 1 | Module split | Separate source files in `src/`, concatenated into a single `dist/CTLD.lua` by a build script (CI) |
| 2 | OOP level | Full OOP Lua 5.1 with metatables and classes — ready to break backward compat when needed |
| 3 | MIST dependency | Middleware layer (`src/mist_compat/`): CTLD never calls `mist.*` directly. Long-term goal: eliminate MIST entirely |
| 4 | API breaking changes | Short/medium term: legacy wrappers with deprecation warnings. Long term (v3): legacy API removed |
| 5 | Lua environment | Lua 5.1 DCS sandbox, desanitized server assumed (`io`, `os`, `lfs` accessible) |
| 6 | Testing | Both: busted + DCS/MIST mocks in CI, and in-game test missions for integration |
| 7 | Documentation | 3 audiences (player, mission maker, developer). Markdown in `docs/`, auto-published to GitHub Pages via MkDocs |
| 8 | i18n | Included in plan: audit missing keys, CI lint for version drift, cleanup empty translations |
| 9 | Priorities | 1-Cleanup, 2-OOP, 3-MIST middleware, 4-Legacy compat, 5-Tests, 6-CI, 7-i18n, 8-Docs |
| 10 | Branching | `next` branch for v2, git flow. `main` stays stable. Feature branches: `feature/<phase>-<description>` |
---
## Guiding principles
- **OOP Lua 5.1**: metatables, classes, state encapsulation.
- **Separate modules** in development, single file in delivery.
- **Zero direct MIST dependency**: all MIST usage goes through a middleware layer.
- **Automated testing**: pure logic tested outside DCS, integration tested in-game.
- **Auto-generated documentation**: from the repo to GitHub Pages.
- **Transitional legacy compatibility**: deprecated wrappers with warnings, removed in v3.
---
## Phases
### Phase 1 — Dead code cleanup
**Goal**: Start from a clean, noise-free baseline.
| Task | Detail |
| ---- | ------ |
| 1.1 | Remove the 18+ identified commented-out code blocks |
| 1.2 | Remove unused functions (`ctld.tools.getRelativeBearing`, etc.) |
| 1.3 | Remove state variables that are never read |
| 1.4 | Clean up obsolete `--TODO`/`--FIXME` markers |
| 1.5 | Validate with existing test missions that nothing breaks |
**Deliverable**: A lighter CTLD.lua, functionally identical.
---
### Phase 2 — Module split + OOP
**Goal**: Transform the procedural monolith into a modular, object-oriented architecture.
#### 2.1 — Lua 5.1 class system
Define a micro class framework based on metatables:
```lua
-- src/lib/class.lua
local function class(base)
local cls = {}
cls.__index = cls
if base then setmetatable(cls, { __index = base }) end
function cls:new(...)
local instance = setmetatable({}, cls)
if instance.init then instance:init(...) end
return instance
end
return cls
end
```
#### 2.2 — Module layout
Target structure for the `src/` directory:
```text
src/
├── lib/
│ ├── class.lua -- OOP micro-framework
│ ├── utils.lua -- Utilities (deepCopy, formatText, logging)
│ └── vec.lua -- Vector math (2D/3D distance, bearing)
├── core/
│ ├── config.lua -- User configuration (USER CONFIGURATION)
│ ├── state.lua -- State manager (replaces 34 global tables)
│ ├── coalition.lua -- Coalition class (eliminates RED/BLUE duplication)
│ ├── i18n.lua -- i18n system
│ └── events.lua -- Event handler + callback system
├── transport/
│ ├── transport.lua -- Transport class (heli/plane)
│ ├── troops.lua -- Troop management (load/unload/extract)
│ └── vehicles.lua -- Vehicle management
├── logistics/
│ ├── crate.lua -- Crate class
│ ├── crate_manager.lua -- Spawning, hover, sling load, unpack
│ ├── fob.lua -- FOB construction and management
│ └── beacon.lua -- Radio beacons
├── jtac/
│ ├── jtac_controller.lua -- JTACController class
│ ├── targeting.lua -- Target acquisition, LOS, priorities
│ ├── lasing.lua -- Laser/IR point, spot corrections
│ └── menu.lua -- F10 JTAC menus
├── ui/
│ ├── f10_menu.lua -- F10 menu construction
│ ├── messages.lua -- Player messages (displayMessageToGroup)
│ └── smoke.lua -- Smoke markers
├── recon/
│ └── recon.lua -- Target recognition on F10 map
├── ai/
│ └── ai_transport.lua -- AI auto-load/unload logic
├── compat/
│ └── legacy_api.lua -- Deprecated ctld.* wrappers
├── mist_compat/
│ └── mist_middleware.lua -- MIST middleware (see Phase 3)
└── ctld.lua -- Entry point, initialization, orchestration
```
#### 2.3 — Core classes
| Class | Responsibility | Replaces |
| ----- | -------------- | -------- |
| `Coalition` | Encapsulates side (1/2) and per-coalition state | `ctld.spawnedCratesRED/BLUE`, `ctld.droppedTroopsRED/BLUE`, etc. (34 tables → 2 instances) |
| `Transport` | State of a transport helicopter/plane | `ctld.inTransitTroops[name]`, `ctld.hoverStatus[name]` |
| `Crate` | Represents a logistics crate | Entries from `ctld.spawnableCrates`, `ctld.crateLookupTable` |
| `CrateManager` | Spawn, pickup, drop, unpack crates | `ctld.spawnCrate`, `ctld.unpackCrates`, `ctld.checkHoverStatus` |
| `FOB` | A built Forward Operating Base | `ctld.builtFOBS[name]` |
| `JTACController` | An active JTAC with its lasing state | `ctld.jtacUnits`, `ctld.jtacCurrentTargets`, `ctld.jtacSelectedTarget` |
| `Beacon` | A deployed radio beacon | `ctld.deployedRadioBeacons[name]` |
| `StateManager` | Central registry of all active objects | Replaces 34 global tables |
| `Config` | Typed user configuration | Current USER CONFIGURATION section |
#### 2.4 — Eliminating RED/BLUE duplication
Before (50+ branches):
```lua
if _heli:getCoalition() == 1 then
_extract = ctld.findNearestGroup(_heli, ctld.droppedTroopsRED)
else
_extract = ctld.findNearestGroup(_heli, ctld.droppedTroopsBLUE)
end
```
After:
```lua
local side = stateManager:getCoalition(heli:getCoalition())
local extract = side:findNearestDroppedTroop(heli)
```
---
### Phase 3 — MIST middleware
**Goal**: Isolate MIST behind a facade. CTLD never references `mist.*` directly.
| Task | Detail |
| ---- | ------ |
| 3.1 | Inventory the 91 MIST calls and categorize them (trivial / medium / complex) |
| 3.2 | Create `src/mist_compat/mist_middleware.lua` exposing a clean API |
| 3.3 | Rewrite trivial functions: `deepCopy`, `get2DDist`, `round`, `makeVec2/3` |
| 3.4 | Wrap medium functions: `getHeading`, `vec.*`, `tostringLL/MGRS` |
| 3.5 | Delegate complex functions to MIST: `dynAdd`, `dynAddStatic`, `getUnitsLOS` |
| 3.6 | Replace all `mist.*` calls in modules with middleware calls |
| 3.7 | (Long term) Rewrite complex functions to eliminate MIST entirely |
**Deliverable**: CTLD works with or without MIST (graceful degradation when MIST is absent, eventually).
---
### Phase 4 — Legacy API compatibility layer
**Goal**: Existing missions continue to work without modification.
| Task | Detail |
| ---- | ------ |
| 4.1 | List all public `ctld.*` functions documented in the README |
| 4.2 | Create `src/compat/legacy_api.lua` with wrappers that call the new API |
| 4.3 | Each wrapper logs a deprecated warning with the new API name |
| 4.4 | Document old → new migration in `docs/migration-v2.md` |
| 4.5 | Announce the policy: legacy maintained in v2, removed in v3 |
Example:
```lua
-- legacy_api.lua
function ctld.spawnCrateAtZone(_side, _weight, _zone)
ctld.logWarning("DEPRECATED: ctld.spawnCrateAtZone() -> use CrateManager:spawnAtZone()")
local side = (_side == "red") and 1 or 2
return ctld.crateManager:spawnAtZone(side, _weight, _zone)
end
```
---
### Phase 5 — Unit tests
**Goal**: Coverage of pure logic outside DCS + in-game smoke tests.
#### 5.1 — Framework and mocks
| Task | Detail |
| ---- | ------ |
| 5.1.1 | Set up busted (Lua 5.1) + luarocks in the repo |
| 5.1.2 | Create `test/mocks/dcs_env.lua`: stubs for `trigger`, `Unit`, `Group`, `coalition`, `land`, `timer`, `missionCommands`, `coord`, `world`, `env` |
| 5.1.3 | Create `test/mocks/mist_env.lua`: stubs for MIST functions used |
| 5.1.4 | Configure busted to load mocks before tests |
#### 5.2 — Unit tests (outside DCS)
| Module | Priority tests |
| ------ | -------------- |
| `lib/class.lua` | Inheritance, instantiation, override |
| `lib/vec.lua` | 2D/3D distance, bearing, clock direction |
| `lib/utils.lua` | deepCopy, formatText |
| `core/coalition.lua` | Per-coalition state management, lookup |
| `core/i18n.lua` | Translation, fallback, parameters |
| `core/config.lua` | Default values, override |
| `logistics/crate.lua` | Weight uniqueness, lookup |
| `compat/legacy_api.lua` | Wrappers call the correct new API |
#### 5.3 — In-game tests
| Task | Detail |
| ---- | ------ |
| 5.3.1 | Create an automated test mission (DO SCRIPT running a test suite) |
| 5.3.2 | Write results to a file via `io.open` (desanitized server) |
| 5.3.3 | Validate: troop load/unload, crate spawn/unpack, JTAC lasing, FOB build, beacons |
---
### Phase 6 — CI infrastructure
**Goal**: Automate build, tests, and release.
| Task | Detail |
| ---- | ------ |
| 6.1 | **Build script**: Lua (or Python/Bash) script that concatenates `src/**/*.lua``dist/CTLD.lua` in the correct order |
| 6.2 | **GitHub Actions — Tests**: install Lua 5.1 + luarocks + busted, run `busted test/` |
| 6.3 | **GitHub Actions — Build**: generate `dist/CTLD.lua` and `dist/CTLD-i18n.lua` |
| 6.4 | **GitHub Actions — Release**: on tag, publish the `.lua` artifact as a GitHub release |
| 6.5 | **GitHub Actions — Docs**: MkDocs build + deploy to GitHub Pages |
| 6.6 | **i18n lint**: CI script comparing keys across languages and checking `translation_version` |
---
### Phase 7 — i18n cleanup + tooling
**Goal**: Reliable i18n with automatic drift detection.
| Task | Detail |
| ---- | ------ |
| 7.1 | Full audit: list EN vs FR vs ES vs KO keys, identify missing ones |
| 7.2 | Fill empty FR keys (crate/equipment names) |
| 7.3 | Update KO (1.1 → 1.6+) or mark it as `incomplete` |
| 7.4 | CI lint script for i18n (see 6.6) |
| 7.5 | Document the process of adding a language in `docs/contributing/i18n.md` |
| 7.6 | Consider extracting i18n into per-language files (`i18n/fr.lua`, `i18n/ko.lua`) |
---
### Phase 8 — Documentation
**Goal**: 3 guides for 3 audiences, auto-published.
#### 8.1 — `docs/` structure
```text
docs/
├── index.md -- Landing page
├── user-guide/
│ ├── getting-started.md -- For the player: F10 menus, in-game workflow
│ ├── troops.md -- Troop loading/unloading
│ ├── crates.md -- Crate system
│ ├── jtac.md -- Using JTACs
│ ├── fob.md -- FOB construction
│ └── beacons.md -- Radio beacons
├── mission-maker/
│ ├── setup.md -- Mission installation
│ ├── configuration.md -- All configurable options
│ ├── api-reference.md -- Public API (DO SCRIPT)
│ ├── zones.md -- Pickup/dropoff/waypoint zones
│ ├── jtac-setup.md -- Advanced JTAC configuration
│ └── examples.md -- Mission examples
├── developer/
│ ├── architecture.md -- Module, class, and flow diagrams
│ ├── contributing.md -- How to contribute
│ ├── building.md -- Build script, CI
│ ├── testing.md -- Running tests
│ ├── i18n.md -- Adding/maintaining a translation
│ └── migration-v2.md -- v1 → v2 migration guide
└── mkdocs.yml -- MkDocs configuration
```
#### 8.2 — Publishing
- MkDocs Material theme
- GitHub Actions: build + deploy to `gh-pages` on every push to `next`
- Slimmed-down README.md: links to the full documentation site
---
## Indicative timeline
| Phase | Dependencies | Complexity |
| ----- | ------------ | ---------- |
| 1 — Dead code cleanup | None | Low |
| 2 — Modules + OOP | Phase 1 | **High** |
| 3 — MIST middleware | Phase 2 | Medium |
| 4 — Legacy compat | Phase 2 | Medium |
| 5 — Tests | Phases 2-3 | Medium |
| 6 — CI | Phases 2, 5 | Medium |
| 7 — i18n | Phase 2 | Low |
| 8 — Documentation | Phases 2-4 | Medium |
> Phases 3 and 4 can be worked on in parallel.
> Phase 6 can start as early as Phase 2 (build script) and grow incrementally.
---
## Branching strategy
```text
main (stable, v1.x)
└── next (v2 development)
├── feature/phase1-cleanup
├── feature/phase2-oop-core
├── feature/phase2-oop-jtac
├── feature/phase3-mist-middleware
├── feature/phase4-legacy-compat
├── feature/phase5-tests
└── ...
```
- `main`: stable v1.x releases, urgent hotfixes only.
- `next`: v2 integration, git flow (feature → next → release).
- Tags: `v2.0-alpha.1`, `v2.0-beta.1`, `v2.0-rc.1`, `v2.0`.
---
## Risks and mitigations
| Risk | Impact | Mitigation |
| ---- | ------ | ---------- |
| Gameplay regressions after OOP refactoring | High | Unit tests + systematic test missions |
| DCS mock divergence from real API | Medium | In-game tests as complement, versioned mocks |
| Incomplete MIST middleware | Medium | Progressive approach, MIST remains as fallback |
| Mission maker resistance to API changes | Medium | Legacy layer + communication + migration guide |
| Build script complexity (module ordering) | Low | Explicit dependencies, build tested in CI |
+75
View File
@@ -0,0 +1,75 @@
# Copilot Instructions for DCS-CTLD
## Working mode / Mode de travail
- **Communication language**: French (français) for all conversations and commit messages.
- **Documentation language**: English for all technical documentation (code comments, docs/, README). French summaries in docs are acceptable but English is the primary language.
- **Development methodology**: TDD (Test-Driven Development) — write tests before implementation when possible.
- **Programming paradigm**: OOP Lua 5.1 with metatables and classes. No procedural spaghetti.
- **Branching strategy**: Git flow on the `next` branch. Feature branches named `feature/<phase>-<description>`. Never commit directly to `main` or `next`.
- **Commit style**: Conventional Commits (`feat:`, `fix:`, `refactor:`, `test:`, `docs:`, `chore:`).
- **Build target**: Individual source modules in `src/` are concatenated into a single `dist/CTLD.lua` deliverable by a build script. Never edit the built file directly.
- **MIST dependency**: CTLD code must never call `mist.*` directly. All MIST usage goes through the middleware layer (`src/mist_compat/`).
- **Legacy API**: When refactoring a public `ctld.*` function, always create a deprecated wrapper in `src/compat/legacy_api.lua` that logs a warning and delegates to the new API.
- **Refer to the modernization plan**: See `.github/MODERNIZATION-PLAN.md` for the full roadmap and architectural decisions.
## Project context
- This repository contains Lua mission scripts for DCS World.
- The primary script is CTLD.lua.
- Internationalization tables are split between CTLD.lua (English reference keys) and CTLD-i18n.lua (translated values).
- Runtime is DCS mission scripting environment (Lua 5.1, metatables available, no LuaJIT, no goto).
- Assumes desanitized server (io, os, lfs accessible).
- MIST is being progressively replaced by an internal middleware layer.
## Architecture (v2 target)
- Source modules live in `src/` organized by domain: `lib/`, `core/`, `transport/`, `logistics/`, `jtac/`, `ui/`, `recon/`, `ai/`, `compat/`, `mist_compat/`.
- OOP via a micro class system using metatables (`src/lib/class.lua`).
- State is managed by a `StateManager` singleton and per-coalition `Coalition` instances — no more `ctld.xxxRED`/`ctld.xxxBLUE` table pairs.
- Tests live in `test/` and use busted with DCS/MIST mocks.
## Compatibility (v1 legacy)
- Preserve existing public ctld.* APIs used by Mission Editor DO SCRIPT triggers.
- Do not rename exported ctld functions or change their parameter semantics unless explicitly requested.
- Keep behavior compatible with existing .miz missions in this repository.
- Keep script load order assumptions intact: MIST first, CTLD-i18n.lua before CTLD.lua.
## CTLD.lua editing rules
- Keep user-tunable options in the USER CONFIGURATION section with clear comments and safe defaults.
- Keep coalition conventions consistent:
- 1 = red
- 2 = blue
- 0 = both (where applicable)
- Keep pickup/dropoff/waypoint zone tuple formats compatible with current parser logic.
- Keep crate weight values unique in ctld.spawnableCrates.
- Preserve callback behavior and action names used by ctld.processCallback.
- Use defensive nil checks before calling methods on DCS objects (Unit/Group/zone lookups).
- Prefer existing logging patterns (ctld.logInfo, env.info, env.error) over ad-hoc prints.
- Avoid adding heavy polling loops; prefer bounded searches and scheduled checks.
## I18N rules
- For every new player-visible string, add an English reference key and use ctld.i18n_translate at call sites.
- Do not hardcode new menu or gameplay text without i18n_translate.
- When adding keys, keep translation_version alignment in mind and add placeholders in CTLD-i18n.lua tables.
- Do not remove or rename existing i18n keys unless all language tables are updated.
## Testing expectations
- Prefer the dynamic loading workflow documented in README for fast iteration.
- After gameplay logic changes, validate at least:
- troop load/unload flows
- crate spawn/load/unpack flows
- JTAC-related flows (if touched)
- Use repository missions for smoke tests when relevant:
- test-dev-dynamic.miz
- test-dev-static.miz
- test-mission.miz
- If user-facing behavior or configuration changes, update README examples in the same change.
## Code style conventions
- Follow existing file style and indentation.
- OOP Lua 5.1: use the project class system (`src/lib/class.lua`) for new classes.
- For internal helpers, follow existing naming patterns (local variables often prefixed with _).
- Keep mission-designer guidance comments concise and practical.
- No direct `mist.*` calls — use the middleware.
- Every new public function should have at least one unit test.
+5
View File
@@ -0,0 +1,5 @@
{
"Lua.diagnostics.globals": [
"ctld"
]
}
+74 -9
View File
@@ -1,4 +1,5 @@
--[[
--[[ ! IMPORTANT : You must must use the version of MIST supplied in the CTLD pack to correctly manage dynamic spwans
Combat Troop and Logistics Drop
Allows Huey, Mi-8 and C130 to transport troops internally and Helicopters to transport Logistic / Vehicle units to the field via sling-loads
@@ -40,7 +41,7 @@ end
ctld.Id = "CTLD - "
--- Version.
ctld.Version = "1.5.2"
ctld.Version = "1.6.0-alpha"
-- To add debugging messages to dcs.log, change the following log levels to `true`; `Debug` is less detailed than `Trace`
ctld.Debug = false
@@ -817,7 +818,9 @@ ctld.vehicleTransportEnabled = {
-- We will also use this to make modifications to the menu and other checks and messages
ctld.dynamicCargoUnits = {
"CH-47Fbl1",
--"UH-1H",
"UH-1H",
"Mi-8MT",
"Mi-24P",
}
-- ************** Maximum Units SETUP for UNITS ******************
@@ -888,6 +891,7 @@ ctld.internalCargoLimits = {
-- Remove the -- below to turn on options
["Mi-8MT"] = 2,
["CH-47Fbl1"] = 8,
["UH-1H"] = 3, -- to remove after debug
}
@@ -2617,10 +2621,19 @@ function ctld.spawnCrate(_arguments, bypassCrateWaitTime)
-- add to move table
ctld.crateMove[_name] = _name
local refPoint = _heli:getPoint()
local refLat, refLon = coord.LOtoLL(refPoint)
local unitPos = _heli:getPosition()
local refHeading = math.deg(math.atan2(unitPos.x.z, unitPos.x.x))
local destLat, destLon, destAlt = coord.LOtoLL(_point)
local relativePos, forma = ctld.tools.getRelativeBearing(refLat, refLon, refHeading, destLat, destLon, 'clock')
ctld.displayMessageToGroup(_heli,
ctld.i18n_translate("A %1 crate weighing %2 kg has been brought out and is at your %3 o'clock ",
_crateType.desc, _crateType.weight, _position), 20)
_crateType.desc, _crateType.weight, relativePos), 20)
else
env.info("Couldn't find crate item to spawn")
end
@@ -4223,8 +4236,7 @@ function ctld.dropSlingCrate(_args)
_position = "6"
end
ctld.displayMessageToGroup(_heli,
ctld.i18n_translate("%1 crate has been safely unhooked and is at your %2 o'clock", _crate.desc,
_position), 10)
ctld.i18n_translate("%1 crate has been safely unhooked and is at your %2 o'clock", _crate.desc, _position), 10)
elseif _heightDiff > 7.5 and _heightDiff <= 40.0 then
ctld.displayMessageToGroup(_heli,
ctld.i18n_translate("%1 crate has been safely dropped below you", _crate.desc), 10)
@@ -5746,7 +5758,7 @@ function ctld.unitDynamicCargoCapable(_unit)
--ctld.logDebug("ctld.unitDynamicCargoCapable(_type=[%s])", ctld.p(_type))
for _, _name in ipairs(ctld.dynamicCargoUnits) do
local _nameLower = string.lower(_name)
if string.find(_type, _nameLower, 1, true) then --string.match does not work with patterns containing '-' as it is a magic character
if string.find(_type, _nameLower, 1, true) then --string.match does not work with patterns containing '-' as it is a magic character
result = true
break
end
@@ -8540,7 +8552,7 @@ function ctld.eventHandler:onEvent(event)
for _, aircraftType in pairs(ctld.aircraftTypeTable) do
if aircraftType == playerTypeName then
ctld.logTrace("adding by aircraft type, unitName = %s", ctld.p(unitName))
if ctld.isValueInIpairTable(ctld.transportPilotNames, unitName) == false then
if ctld.tools.isValueInIpairTable(ctld.transportPilotNames, unitName) == false then
table.insert(ctld.transportPilotNames, unitName) -- add transport unit to the list
end
if ctld.addedTo[tostring(_groupId)] == nil then -- only if menu not already set up
@@ -8618,7 +8630,8 @@ function ctld.RandomReal(mini, maxi)
end
-- Tools
function ctld.isValueInIpairTable(tab, value)
ctld.tools = {}
function ctld.tools.isValueInIpairTable(tab, value)
for i, v in ipairs(tab) do
if v == value then
return true -- La valeur existe
@@ -8626,6 +8639,58 @@ function ctld.isValueInIpairTable(tab, value)
end
return false -- La valeur n'existe pas
end
------------------------------------------------------------------------------------
--- Calculates the orientation of an end point relative to a reference point.
--- The calculation takes into account the current orientation of the reference point.
---
--- @param refLat number Latitude of the reference point in degrees.
--- @param refLon number Longitude of the reference point in degrees.
--- @param refHeading number Current orientation of the reference point in degrees (0 = North, 90 = East).
--- @param destLat number Latitude of the arrival point in degrees.
--- @param destLon number Longitude of the arrival point in degrees.
--- @param resultFormat string The desired output format: "radian", "degree" or "clock".
--- @return number The relative orientation in the specified resultFormat.
function ctld.tools.getRelativeBearing(refLat, refLon, refHeading, destLat, destLon, resultFormat)
-- Converting degrees to radians for geometric calculations
local radrefLat = math.rad(refLat)
local raddestLat = math.rad(destLat)
local radrefLon = math.rad(refLon)
local raddestLon = math.rad(destLon)
local radrefHeading = math.rad(refHeading)
-- Calculating the longitude difference between the two points
local deltaLon = raddestLon - radrefLon
-- Using the great circle formula for azimuth (bearing)
-- This formula is based on spherical trigonometry and uses atan2
-- to correctly handle all quadrants.
local y = math.sin(deltaLon) * math.cos(raddestLat)
local x = math.cos(radrefLat) * math.sin(raddestLat) - math.sin(radrefLat) * math.cos(raddestLat) * math.cos(deltaLon)
local absoluteBearingRad = math.atan2(y, x)
-- Calculate relative orientation by subtracting the reference refHeading
local relativeBearingRad = absoluteBearingRad - radrefHeading
-- Normalizes the angle to be in the range [-pi, pi]
-- This ensures a consistent angle, whether positive or negative.
local normalizedRad = (relativeBearingRad + math.pi) % (2 * math.pi) - math.pi
-- Returns the value in the requested resultFormat
if resultFormat == "radian" then
return normalizedRad, resultFormat
elseif resultFormat == "clock" then
-- Convert to clock position (12h = front, 3h = right, 6h = back, etc..)
local bearingDeg = math.deg(normalizedRad)
local clockPosition = ((bearingDeg + 360) % 360) / 30
clockPosition = clockPosition >= 0 and math.floor(clockPosition + 0.5) or math.ceil(clockPosition - 0.5), resultFormat -- rounded clockPosition
if clockPosition == 0 then clockPosition = 12 end
return clockPosition, resultFormat
else -- By default, the resultFormat is "degree"
resultFormat = "degree"
local bearingDeg = math.deg(normalizedRad)
return (bearingDeg + 360) % 360, resultFormat
end
end
--- Enable/Disable error boxes displayed on screen.
env.setErrorMessageBoxEnabled(false)
+1 -1
View File
@@ -132,7 +132,7 @@ Optionaly, you can disable the STTS (text to speech over SRS) feature (4).
![dynamic_loading]
### Script Setup
**This script requires MIST version 4.0.57 or above: https://github.com/mrSkortch/MissionScriptingTools**
🔴IMPORTANT: This script requires MIST supplied in the CTLD zipped pack to correctly manage dynamic spwans.
First make sure MIST is loaded, either as an Initialization Script for the mission or the first DO SCRIPT with a "TIME MORE" of 1. "TIME MORE" means run the actions after X seconds into the mission.
+3 -3
View File
@@ -35,7 +35,7 @@ mist = {}
-- don't change these
mist.majorVersion = 4
mist.minorVersion = 5
mist.build = "128-DYNSLOTS-01"
mist.build = "128-DYNSLOTS-02"
-- forward declaration of log shorthand
local log
@@ -826,11 +826,11 @@ do -- the main scope
if zone.verticies then
local offset = {}
for i = 1, #zone.verticies do
table.insert(offset, {dist = mist.utils.get2DDist(uRef.point, zone.verticies[i]), heading = mist.getHeadingPoints(uRef.point, zone.verticies[i]) + uRef.heading})
table.insert(offset, {dist = mist.utils.get2DDist(uRef.point, zone.verticies[i]), heading = mist.utils.getHeadingPoints(uRef.point, zone.verticies[i]) + uRef.heading})
end
zone.offset = offset
else
zone.offset = {dist = mist.utils.get2DDist(uRef.point, zone.point), heading = mist.getHeadingPoints(uRef.point, zone.point) + uRef.heading}
zone.offset = {dist = mist.utils.get2DDist(uRef.point, zone.point), heading = mist.utils.getHeadingPoints(uRef.point, zone.point) + uRef.heading}
end
end
end
Binary file not shown.
Binary file not shown.