mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-07-26 11:57:16 +00:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| de3dc95c92 | |||
| d9a6f5daaf | |||
| 27fa920a8f | |||
| cf65cbf8fc | |||
| 2f229c1d8c | |||
| 7e07f2b4ea | |||
| d214d115c6 | |||
| fc1059c5d6 | |||
| 6e09ea7089 | |||
| 7587119843 | |||
| a5880b89c1 | |||
| 1be2c92a5c | |||
| 4c8a17fe57 | |||
| 64dea17982 | |||
| b1f86c702d | |||
| 1a9540d0d4 | |||
| cdfaac527c | |||
| 4e3bf9969b | |||
| 74c16bd4f0 | |||
| 55e048b322 | |||
| b31fb7ece3 | |||
| 149e3421d9 | |||
| 338ec34604 | |||
| 3d79a16d3a | |||
| efa08c1280 | |||
| 589e65963f | |||
| af4f20af67 | |||
| b1b8630d21 | |||
| 98ed7d50c1 | |||
| 4ba81cb8bc | |||
| 626b12f486 |
@@ -735,6 +735,12 @@ do -- Event Handling
|
|||||||
-- @function [parent=#BASE] OnEventPlayerEnterAircraft
|
-- @function [parent=#BASE] OnEventPlayerEnterAircraft
|
||||||
-- @param #BASE self
|
-- @param #BASE self
|
||||||
-- @param Core.Event#EVENTDATA EventData The EventData structure.
|
-- @param Core.Event#EVENTDATA EventData The EventData structure.
|
||||||
|
|
||||||
|
--- Occurs when an option is changed for an AI group.
|
||||||
|
-- The event identifies the initiating group, but does not provide the option ID or value.
|
||||||
|
-- @function [parent=#BASE] OnEventGroupChangeOption
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData The EventData structure.
|
||||||
|
|
||||||
--- Occurs when a player creates a dynamic cargo object from the F8 ground crew menu.
|
--- Occurs when a player creates a dynamic cargo object from the F8 ground crew menu.
|
||||||
-- *** NOTE *** this is a workarounf for DCS not creating these events as of Aug 2024.
|
-- *** NOTE *** this is a workarounf for DCS not creating these events as of Aug 2024.
|
||||||
@@ -880,6 +886,22 @@ end
|
|||||||
|
|
||||||
world.onEvent(Event)
|
world.onEvent(Event)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Creation of a `S_EVENT_GROUP_CHANGE_OPTION` event.
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param DCS#Time EventTime The time stamp of the event.
|
||||||
|
-- @param DCS#Group Initiator The initiating group of the event.
|
||||||
|
function BASE:CreateEventGroupChangeOption( EventTime, Initiator )
|
||||||
|
self:F( { EventTime, Initiator } )
|
||||||
|
|
||||||
|
local Event = {
|
||||||
|
id = EVENTS.GroupChangeOption,
|
||||||
|
time = EventTime,
|
||||||
|
initiator = Initiator,
|
||||||
|
}
|
||||||
|
|
||||||
|
world.onEvent( Event )
|
||||||
|
end
|
||||||
|
|
||||||
--- Creation of a S_EVENT_NEW_DYNAMIC_CARGO event.
|
--- Creation of a S_EVENT_NEW_DYNAMIC_CARGO event.
|
||||||
-- @param #BASE self
|
-- @param #BASE self
|
||||||
|
|||||||
@@ -278,6 +278,7 @@ EVENTS = {
|
|||||||
SimulationUnfreeze = world.event.S_EVENT_SIMULATION_UNFREEZE or -1,
|
SimulationUnfreeze = world.event.S_EVENT_SIMULATION_UNFREEZE or -1,
|
||||||
HumanAircraftRepairStart = world.event.S_EVENT_HUMAN_AIRCRAFT_REPAIR_START or -1,
|
HumanAircraftRepairStart = world.event.S_EVENT_HUMAN_AIRCRAFT_REPAIR_START or -1,
|
||||||
HumanAircraftRepairFinish = world.event.S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH or -1,
|
HumanAircraftRepairFinish = world.event.S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH or -1,
|
||||||
|
GroupChangeOption = world.event.S_EVENT_GROUP_CHANGE_OPTION or -1,
|
||||||
-- dynamic cargo
|
-- dynamic cargo
|
||||||
NewDynamicCargo = world.event.S_EVENT_NEW_DYNAMIC_CARGO or -1,
|
NewDynamicCargo = world.event.S_EVENT_NEW_DYNAMIC_CARGO or -1,
|
||||||
DynamicCargoLoaded = world.event.S_EVENT_DYNAMIC_CARGO_LOADED or -1,
|
DynamicCargoLoaded = world.event.S_EVENT_DYNAMIC_CARGO_LOADED or -1,
|
||||||
@@ -291,23 +292,25 @@ EVENTS = {
|
|||||||
--
|
--
|
||||||
-- * A (Object.Category.)UNIT : A UNIT object type is involved in the Event.
|
-- * A (Object.Category.)UNIT : A UNIT object type is involved in the Event.
|
||||||
-- * A (Object.Category.)STATIC : A STATIC object type is involved in the Event.
|
-- * A (Object.Category.)STATIC : A STATIC object type is involved in the Event.
|
||||||
|
-- * A GROUP : A DCS Group object is involved in the Event.
|
||||||
--
|
--
|
||||||
-- @type EVENTDATA
|
-- @type EVENTDATA
|
||||||
-- @field #number id The identifier of the event.
|
-- @field #number id The identifier of the event.
|
||||||
--
|
--
|
||||||
-- @field DCS#Unit initiator (UNIT/STATIC/SCENERY) The initiating @{DCS#Unit} or @{DCS#StaticObject}.
|
-- @field DCS#Unit initiator (UNIT/STATIC/SCENERY/GROUP) The initiating @{DCS#Unit} or @{DCS#StaticObject}. For `S_EVENT_GROUP_CHANGE_OPTION`, this is a DCS Group.
|
||||||
-- @field DCS#Object.Category IniObjectCategory (UNIT/STATIC/SCENERY) The initiator object category ( Object.Category.UNIT or Object.Category.STATIC ).
|
-- @field DCS#Object.Category IniObjectCategory (UNIT/STATIC/SCENERY) The initiator object category ( Object.Category.UNIT or Object.Category.STATIC ).
|
||||||
-- @field DCS#Unit IniDCSUnit (UNIT/STATIC) The initiating @{DCS#Unit} or @{DCS#StaticObject}.
|
-- @field DCS#Unit IniDCSUnit (UNIT/STATIC) The initiating @{DCS#Unit} or @{DCS#StaticObject}.
|
||||||
-- @field #string IniDCSUnitName (UNIT/STATIC) The initiating Unit name.
|
-- @field #string IniDCSUnitName (UNIT/STATIC) The initiating Unit name.
|
||||||
-- @field Wrapper.Unit#UNIT IniUnit (UNIT/STATIC) The initiating MOOSE wrapper @{Wrapper.Unit#UNIT} of the initiator Unit object.
|
-- @field Wrapper.Unit#UNIT IniUnit (UNIT/STATIC) The initiating MOOSE wrapper @{Wrapper.Unit#UNIT} of the initiator Unit object.
|
||||||
-- @field #string IniUnitName (UNIT/STATIC) The initiating UNIT name (same as IniDCSUnitName).
|
-- @field #string IniUnitName (UNIT/STATIC) The initiating UNIT name (same as IniDCSUnitName).
|
||||||
-- @field DCS#Group IniDCSGroup (UNIT) The initiating {DCSGroup#Group}.
|
-- @field DCS#Group IniDCSGroup (UNIT/GROUP) The initiating @{DCS#Group}.
|
||||||
-- @field #string IniDCSGroupName (UNIT) The initiating Group name.
|
-- @field #string IniDCSGroupName (UNIT/GROUP) The initiating Group name.
|
||||||
-- @field Wrapper.Group#GROUP IniGroup (UNIT) The initiating MOOSE wrapper @{Wrapper.Group#GROUP} of the initiator Group object.
|
-- @field Wrapper.Group#GROUP IniGroup (UNIT/GROUP) The initiating MOOSE wrapper @{Wrapper.Group#GROUP} of the initiator Group object.
|
||||||
-- @field #string IniGroupName UNIT) The initiating GROUP name (same as IniDCSGroupName).
|
-- @field #string IniGroupName (UNIT/GROUP) The initiating GROUP name (same as IniDCSGroupName).
|
||||||
|
-- @field DCS#Group.Category IniGroupCategory (GROUP) The category of the initiating group.
|
||||||
-- @field #string IniPlayerName (UNIT) The name of the initiating player in case the Unit is a client or player slot.
|
-- @field #string IniPlayerName (UNIT) The name of the initiating player in case the Unit is a client or player slot.
|
||||||
-- @field #string IniPlayerUCID (UNIT) The UCID of the initiating player in case the Unit is a client or player slot and on a multi-player server.
|
-- @field #string IniPlayerUCID (UNIT) The UCID of the initiating player in case the Unit is a client or player slot and on a multi-player server.
|
||||||
-- @field DCS#coalition.side IniCoalition (UNIT) The coalition of the initiator.
|
-- @field DCS#coalition.side IniCoalition (UNIT/GROUP) The coalition of the initiator.
|
||||||
-- @field DCS#Unit.Category IniCategory (UNIT) The category of the initiator.
|
-- @field DCS#Unit.Category IniCategory (UNIT) The category of the initiator.
|
||||||
-- @field #string IniTypeName (UNIT) The type name of the initiator.
|
-- @field #string IniTypeName (UNIT) The type name of the initiator.
|
||||||
--
|
--
|
||||||
@@ -734,6 +737,12 @@ local _EVENTMETA = {
|
|||||||
Side = "I",
|
Side = "I",
|
||||||
Event = "OnEventHumanAircraftRepairFinish",
|
Event = "OnEventHumanAircraftRepairFinish",
|
||||||
Text = "S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH"
|
Text = "S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH"
|
||||||
|
},
|
||||||
|
[EVENTS.GroupChangeOption] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventGroupChangeOption",
|
||||||
|
Text = "S_EVENT_GROUP_CHANGE_OPTION"
|
||||||
},
|
},
|
||||||
-- dynamic cargo
|
-- dynamic cargo
|
||||||
[EVENTS.NewDynamicCargo] = {
|
[EVENTS.NewDynamicCargo] = {
|
||||||
@@ -1234,7 +1243,16 @@ function EVENT:onEvent( Event )
|
|||||||
|
|
||||||
if Event.initiator then
|
if Event.initiator then
|
||||||
|
|
||||||
Event.IniObjectCategory = Object.getCategory(Event.initiator)
|
if Event.id == EVENTS.GroupChangeOption then
|
||||||
|
Event.IniDCSGroup = Event.initiator
|
||||||
|
Event.IniDCSGroupName = Group.getName(Event.initiator)
|
||||||
|
Event.IniGroupName = Event.IniDCSGroupName
|
||||||
|
Event.IniGroup = GROUP:FindByName(Event.IniDCSGroupName)
|
||||||
|
Event.IniCoalition = Group.getCoalition(Event.initiator)
|
||||||
|
Event.IniGroupCategory = Group.getCategory(Event.initiator)
|
||||||
|
else
|
||||||
|
Event.IniObjectCategory = Object.getCategory(Event.initiator)
|
||||||
|
end
|
||||||
|
|
||||||
if Event.IniObjectCategory == Object.Category.STATIC then
|
if Event.IniObjectCategory == Object.Category.STATIC then
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ do -- world
|
|||||||
-- @field S_EVENT_SIMULATION_UNFREEZE = 58
|
-- @field S_EVENT_SIMULATION_UNFREEZE = 58
|
||||||
-- @field S_EVENT_HUMAN_AIRCRAFT_REPAIR_START = 59
|
-- @field S_EVENT_HUMAN_AIRCRAFT_REPAIR_START = 59
|
||||||
-- @field S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH = 60
|
-- @field S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH = 60
|
||||||
-- @field S_EVENT_MAX = 61
|
-- @field S_EVENT_GROUP_CHANGE_OPTION = 61
|
||||||
|
-- @field S_EVENT_MAX = 62
|
||||||
|
|
||||||
--- The birthplace enumerator is used to define where an aircraft or helicopter has spawned in association with birth events.
|
--- The birthplace enumerator is used to define where an aircraft or helicopter has spawned in association with birth events.
|
||||||
-- @type world.BirthPlace
|
-- @type world.BirthPlace
|
||||||
@@ -614,7 +615,6 @@ do -- Object
|
|||||||
-- @field SCENERY
|
-- @field SCENERY
|
||||||
-- @field CARGO
|
-- @field CARGO
|
||||||
|
|
||||||
---
|
|
||||||
-- @type Object.Desc
|
-- @type Object.Desc
|
||||||
-- @extends #Desc
|
-- @extends #Desc
|
||||||
-- @field #number life initial life level
|
-- @field #number life initial life level
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,760 +0,0 @@
|
|||||||
--- **Functional** - Enhanced Warsaw Pact GCI Controller.
|
|
||||||
--
|
|
||||||
-- ## Main Features:
|
|
||||||
--
|
|
||||||
-- * Guide AI and human pilots in Warsaw Pact Style. GCI Kernel Functions.
|
|
||||||
-- * Advanced Tactics for Groups.
|
|
||||||
-- * Many additional events that the mission designer can hook into.
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ### Author: **Applevangelist**
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
-- @module Functional.REDGCI_KERNEL
|
|
||||||
-- @image Func_RedGCI.png
|
|
||||||
-- @version 1.0.0
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
--- REDGCI_KERNEL class
|
|
||||||
-- @type REDGCI_KERNEL
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
-- # RedGCI — Soviet GCI Doctrine & Player Guide
|
|
||||||
--
|
|
||||||
-- ## Philosophy: Централизованное управление (Centralized Control)
|
|
||||||
--
|
|
||||||
-- The fundamental difference between Soviet and NATO GCI is **who makes the tactical decision**.
|
|
||||||
--
|
|
||||||
-- In NATO doctrine, the GCI controller provides situational awareness — bearing, range, altitude, aspect — and the pilot decides how to prosecute the intercept. The pilot is an autonomous tactician. GCI is an advisor.
|
|
||||||
--
|
|
||||||
-- In Soviet doctrine, the GCI controller **directs**. The pilot executes. The controller selects the intercept geometry, assigns the heading, manages the radar, calls weapons free, and coordinates multi-ship tactics. The pilot's job is to fly the numbers and shoot when told. This is not a flaw — it is the system working as designed. Soviet fighter pilots were trained to be precise executors of GCI instructions, not independent tacticians. The ground radar network (PVO) was the brain; the aircraft was the weapon.
|
|
||||||
--
|
|
||||||
-- RedGCI models this philosophy faithfully.
|
|
||||||
--
|
|
||||||
-- ---
|
|
||||||
--
|
|
||||||
-- ## What to Expect as a Player
|
|
||||||
--
|
|
||||||
-- ### You will not be asked what you want to do.
|
|
||||||
--
|
|
||||||
-- There are no "recommend a vector" calls, no "at your discretion" callouts. The controller tells you your heading, your altitude, and your task. Your acknowledgement is assumed.
|
|
||||||
--
|
|
||||||
-- ### The controller manages your radar.
|
|
||||||
--
|
|
||||||
-- You do not decide when to turn your radar on. The GCI will tell you when to switch on (`локатор` / `Radar on`). Before that call, you fly cold and silent. This preserves your emissions discipline and prevents the target from getting an early RWR spike.
|
|
||||||
--
|
|
||||||
-- ### Weapons free is a controlled event.
|
|
||||||
--
|
|
||||||
-- You do not engage until the controller clears you (`цель разрешена` / `WEAPONS FREE`). The controller determines when geometry, range, and aspect are favorable. Shooting early breaks the coordinated intercept and may compromise your wingman's attack.
|
|
||||||
--
|
|
||||||
-- ### Radio calls are short and military.
|
|
||||||
--
|
|
||||||
-- Soviet GCI brevity is terse by design. Expect calls like:
|
|
||||||
--
|
|
||||||
-- - `"Сокол, курс 170, высота 4500."` — vector, altitude
|
|
||||||
-- - `"Сокол, цель, пара, истребитель. Локатор."` — picture call on commit: count, type, radar on
|
|
||||||
-- - `"Сокол, захват. Дальность 20. Цель разрешена."` — lock confirmed, range, weapons free
|
|
||||||
-- - `"Сокол, молодец. Домой."` — good kill, RTB
|
|
||||||
--
|
|
||||||
-- There are no "BOGEY DOPE" requests, no "BRAA" calls, no "DECLARE" queries. The controller has already done that work. You fly the vector.
|
|
||||||
--
|
|
||||||
-- ---
|
|
||||||
--
|
|
||||||
-- ## State Flow — What the GCI is Doing Behind the Scenes
|
|
||||||
--
|
|
||||||
-- RedGCI manages a state machine that progresses through six phases. Understanding these phases helps you anticipate what call is coming next.
|
|
||||||
--
|
|
||||||
-- ```
|
|
||||||
-- VECTOR → COMMIT → RADAR_CONTACT → VISUAL → MERGE → (SPLASH / ABORT / RTB)
|
|
||||||
-- ```
|
|
||||||
--
|
|
||||||
-- ### VECTOR
|
|
||||||
-- The controller has a track. You are being vectored onto an intercept geometry. Your radar is off. The controller is solving a collision course and updating your heading every tick. Altitude calls reflect the intercept geometry — you may be sent below the target (classic Soviet shoot-up doctrine for radar-limited types) or level/above (MiG-29/Su-27 lookdown geometry). Expect heading updates every 10–15 seconds.
|
|
||||||
--
|
|
||||||
-- **What you should do:** Fly the heading. Don't deviate. Don't turn your radar on yet. Speed is expected at 900kph TAS (depending on airframe)
|
|
||||||
--
|
|
||||||
-- ### COMMIT
|
|
||||||
-- Range has closed to approximately 30km. The controller calls the picture: count and type. Your radar comes on. You are now committed to the intercept — turning away is no longer the default option. The controller is building your radar geometry toward a lock.
|
|
||||||
--
|
|
||||||
-- **What you should do:** Activate your radar. Acquire the target. Do not fire yet.
|
|
||||||
--
|
|
||||||
-- ### RADAR_CONTACT
|
|
||||||
-- You have radar lock (or the AI has achieved it). The controller confirms lock and calls range. If geometry and range are favorable, weapons free follows immediately. If not — for example if aspect angle is unfavorable for a stern conversion — the controller holds fire and waits for better geometry.
|
|
||||||
--
|
|
||||||
-- **What you should do:** Maintain lock. Track the target. Wait for the weapons free call.
|
|
||||||
--
|
|
||||||
-- ### VISUAL
|
|
||||||
-- Range has closed to approximately 5km — visual conditions. Weapons free is automatic at this point. You are now in the merge envelope.
|
|
||||||
--
|
|
||||||
-- **What you should do:** Engage.
|
|
||||||
--
|
|
||||||
-- ### MERGE
|
|
||||||
-- Inside 2km. The GCI transitions to merge control: bearing to target, overshoot calls, separation instructions, reattack vectors. At this range the controller cannot see fine-grained geometry — merge calls are based on relative bearing and closure.
|
|
||||||
--
|
|
||||||
-- **What you should do:** Fight. Listen for overshoot, separation, and reattack calls.
|
|
||||||
--
|
|
||||||
-- ### SPLASH / ABORT / RTB
|
|
||||||
-- - `SPLASH` — kill confirmed, RTB
|
|
||||||
-- - `ABORT (THREAT)` — your RWR is spiked or a threat geometry has developed; break off immediately on the given heading
|
|
||||||
-- - `ABORT (BINGO)` — fuel state critical; break off and return
|
|
||||||
--
|
|
||||||
-- ---
|
|
||||||
--
|
|
||||||
-- ## Multi-Ship (2v2) Tactics (REDGCI2v2)
|
|
||||||
--
|
|
||||||
-- When two fighters are dispatched against a threat, the GCI selects a tactic automatically based on the tactical situation. The tactic is applied at COMMIT — until then, both fighters are vectored together toward the intercept midpoint.
|
|
||||||
--
|
|
||||||
-- | Tactic | Description |
|
|
||||||
-- |--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
||||||
-- | **PINCER** | Classic bracket. F1 and F2 split left and right, attacking from opposite angles simultaneously. Forces the target to choose which threat to react to. |
|
|
||||||
-- | **HIGH-LOW** | Vertical split. One fighter attacks from below (radar up, clean sky background), one from above. Degrades the target's ability to acquire both simultaneously. |
|
|
||||||
-- | **STAGGER** | BVR timing offset. F1 fires first at long range, F2 follows 8–13km behind to engage a maneuvering or defending target. |
|
|
||||||
-- | **TRAIL** | Close trail. F1 is the shooter, F2 is support — ready to engage if F1 overshoots or is defeated. |
|
|
||||||
-- | **GIRAFFE** | *(Historical — Iraq/Iran War, Mirage F1 vs F-14A)* F1 attacks at normal altitude, binding the AWG-9 radar. F2 flies nap-of-earth |
|
|
||||||
-- | | (300–600m AGL) using ground clutter to degrade radar detection, then pulls up and fires from close range. |
|
|
||||||
--
|
|
||||||
-- During a tactic split, you may receive a heading that seems unusual — a large lateral offset or an unexpected altitude change. **Trust the vector.** The controller is positioning you for the tactic geometry. The merge point will bring you back onto the target.
|
|
||||||
--
|
|
||||||
-- ---
|
|
||||||
--
|
|
||||||
-- ## Dispatcher & CAP Flow (REDGCI_DISPATCHER)
|
|
||||||
--
|
|
||||||
-- When using the dispatcher layer, the full operational flow is:
|
|
||||||
--
|
|
||||||
-- ```
|
|
||||||
-- Spawn at homeplate
|
|
||||||
-- → Taxi and takeoff (template-controlled)
|
|
||||||
-- → Transit to CAP zone
|
|
||||||
-- → Orbit in assigned zone (radar cold, weapons safe)
|
|
||||||
-- ↓ INTEL detects threat cluster
|
|
||||||
-- → "Attention, radar contact. Pair, fighter, 45 kilometers." (all CAP fighters)
|
|
||||||
-- ↓ Dispatcher assigns pair
|
|
||||||
-- → "101 102, intercept. Pair, fighter." (dispatched pair)
|
|
||||||
-- → VECTOR → COMMIT → RADAR_CONTACT → VISUAL → MERGE → SPLASH
|
|
||||||
-- ↓ Engagement complete
|
|
||||||
-- → AI: RTB waypoint → land → despawn → respawn after delay
|
|
||||||
-- → Human: "101, mission complete. RTB, refuel and rearm."
|
|
||||||
-- ↓ After RespawnDelay
|
|
||||||
-- → New AI pair spawns into same CAP zone
|
|
||||||
-- ```
|
|
||||||
--
|
|
||||||
-- Human players are dispatched first when available. If a human and AI are both in the CAP pool, the human is always assigned to the next intercept. AI fills gaps. The dispatcher does not send a single fighter if a pair is available — pairing is always preferred.
|
|
||||||
--
|
|
||||||
-- ---
|
|
||||||
--
|
|
||||||
-- ## Key Differences from NATO GCI at a Glance
|
|
||||||
--
|
|
||||||
-- | | Soviet (RedGCI) | NATO |
|
|
||||||
-- |--------------------|--------------------------------------|------------------------------------|
|
|
||||||
-- | Tactical decision | Controller | Pilot |
|
|
||||||
-- | Radar management | Controller-commanded | Pilot-initiated |
|
|
||||||
-- | Weapons free | Controller-called | Pilot-discretion (after WF) |
|
|
||||||
-- | Heading calls | Prescriptive | Advisory |
|
|
||||||
-- | Brevity style | Terse, military, positional | Standardized (BRAA, DECLARE, etc.) |
|
|
||||||
-- | Multi-ship tactics | Centrally planned, applied at COMMIT | Mutually briefed, pilot-executed |
|
|
||||||
-- | Pilot autonomy | Low (by design) | High |
|
|
||||||
--
|
|
||||||
-- **The Soviet system is not inferior** — it is optimized for a different kind of pilot and a different operational context. Mass interception of large NATO strike packages over defended Soviet airspace demanded centralized, efficient, high-throughput GCI control. RedGCI brings that experience to DCS.
|
|
||||||
--
|
|
||||||
-- @field #REDGCI_KERNEL
|
|
||||||
REDGCI_KERNEL = {}
|
|
||||||
REDGCI_KERNEL.version = "1.0.0"
|
|
||||||
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
-- Konstanten (aus gci_types.h)
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
REDGCI_KERNEL.C = {
|
|
||||||
RANGE_VECTOR_START = 60000.0,
|
|
||||||
RANGE_COMMIT = 30000.0,
|
|
||||||
RANGE_RADAR_FLOOR = 20000.0,
|
|
||||||
RANGE_VISUAL = 5000.0,
|
|
||||||
RANGE_MERGE = 2000.0,
|
|
||||||
WF_RANGE_MAX = 25000.0,
|
|
||||||
ALT_OFFSET_LOOKDOWN = 0.0,
|
|
||||||
ASPECT_NOTCH_MIN = 80.0,
|
|
||||||
ASPECT_NOTCH_MAX = 100.0,
|
|
||||||
ASPECT_REAR_ATTACK = 120.0,
|
|
||||||
MAX_TTI = 600.0,
|
|
||||||
TICK_INTERVAL = 15.0,
|
|
||||||
FUEL_BINGO = 0.25,
|
|
||||||
DELAY_MIN = 3.0,
|
|
||||||
DELAY_MAX = 8.0,
|
|
||||||
DELAY_MERGE_MIN = 2.0,
|
|
||||||
DELAY_MERGE_MAX = 4.0,
|
|
||||||
TACTIC_PINCER = 0,
|
|
||||||
TACTIC_HIGH_LOW = 1,
|
|
||||||
TACTIC_STAGGER = 2,
|
|
||||||
TACTIC_TRAIL = 3,
|
|
||||||
TACTIC_GIRAFFE = 4, -- Irak/Iran-Doktrin: F1=Decoy normal, F2=Nap-of-Earth im Groundclutter
|
|
||||||
PURSUIT_COLLISION = 0,
|
|
||||||
PURSUIT_LEAD = 1,
|
|
||||||
PURSUIT_PURE = 2,
|
|
||||||
PURSUIT_NO_SOLUTION = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
-- Hilfsfunktionen
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function REDGCI_KERNEL.clamp(v, lo, hi)
|
|
||||||
if v < lo then return lo end
|
|
||||||
if v > hi then return hi end
|
|
||||||
return v
|
|
||||||
end
|
|
||||||
|
|
||||||
function REDGCI_KERNEL.vec2len(x, z)
|
|
||||||
return math.sqrt(x*x + z*z)
|
|
||||||
end
|
|
||||||
|
|
||||||
function REDGCI_KERNEL.bearing(dx, dz)
|
|
||||||
local b = math.deg(math.atan2(dx, dz))
|
|
||||||
return b < 0.0 and b + 360.0 or b
|
|
||||||
end
|
|
||||||
|
|
||||||
function REDGCI_KERNEL.randDelay(lo, hi)
|
|
||||||
return lo + UTILS.LCGRandom() * (hi - lo)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
-- Aspect Angle (0=Nose-on, 90=Beam, 180=Tail)
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function REDGCI_KERNEL.aspectAngle(target, observer)
|
|
||||||
local dx = observer.x - target.x
|
|
||||||
local dz = observer.z - target.z
|
|
||||||
local range = REDGCI_KERNEL.vec2len(dx, dz)
|
|
||||||
if range < 1.0 then return 0.0 end
|
|
||||||
local nx = dx / range
|
|
||||||
local nz = dz / range
|
|
||||||
local spd = (target.speed or 1.0) + 1e-6
|
|
||||||
local tvx = (target.vx or 0.0) / spd
|
|
||||||
local tvz = (target.vz or 0.0) / spd
|
|
||||||
local dot = REDGCI_KERNEL.clamp(tvx*nx + tvz*nz, -1.0, 1.0)
|
|
||||||
return math.deg(math.acos(dot))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
-- Closure Rate (positiv = Annäherung)
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function REDGCI_KERNEL.closureRate(f, t)
|
|
||||||
local dx = t.x - f.x
|
|
||||||
local dz = t.z - f.z
|
|
||||||
local range = REDGCI_KERNEL.vec2len(dx, dz)
|
|
||||||
if range < 1.0 then return 0.0 end
|
|
||||||
local nx = dx / range
|
|
||||||
local nz = dz / range
|
|
||||||
local dvx = (t.vx or 0.0) - (f.vx or 0.0)
|
|
||||||
local dvz = (t.vz or 0.0) - (f.vz or 0.0)
|
|
||||||
return -(dvx*nx + dvz*nz)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
-- _solveCollision (intern, GCI-Koordinaten)
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function REDGCI_KERNEL._solveCollision(f, t)
|
|
||||||
local C = REDGCI_KERNEL.C
|
|
||||||
local dx = t.x - f.x
|
|
||||||
local dz = t.z - f.z
|
|
||||||
local vtx = t.vx or 0.0
|
|
||||||
local vtz = t.vz or 0.0
|
|
||||||
local vf = f.speed or 1.0
|
|
||||||
local a = vtx*vtx + vtz*vtz - vf*vf
|
|
||||||
local b = 2.0 * (dx*vtx + dz*vtz)
|
|
||||||
local c = dx*dx + dz*dz
|
|
||||||
local sol_t = -1.0
|
|
||||||
if math.abs(a) < 1.0 then
|
|
||||||
if math.abs(b) > 0.01 then
|
|
||||||
sol_t = -c / b
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local disc = b*b - 4.0*a*c
|
|
||||||
if disc < 0.0 then return false end
|
|
||||||
local sq = math.sqrt(disc)
|
|
||||||
local t1 = (-b - sq) / (2.0 * a)
|
|
||||||
local t2 = (-b + sq) / (2.0 * a)
|
|
||||||
if t1 > 0.0 and t2 > 0.0 then sol_t = math.min(t1, t2)
|
|
||||||
elseif t1 > 0.0 then sol_t = t1
|
|
||||||
elseif t2 > 0.0 then sol_t = t2
|
|
||||||
else return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if sol_t < 0.0 or sol_t > C.MAX_TTI then return false end
|
|
||||||
local ip = {
|
|
||||||
x = t.x + vtx * sol_t,
|
|
||||||
z = t.z + vtz * sol_t,
|
|
||||||
y = math.max(t.y + C.ALT_OFFSET_LOOKDOWN, 300.0),
|
|
||||||
}
|
|
||||||
local hdg = REDGCI_KERNEL.bearing(ip.x - f.x, ip.z - f.z)
|
|
||||||
return true, hdg, sol_t, ip
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
-- _solveLead (intern, GCI-Koordinaten)
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function REDGCI_KERNEL._solveLead(f, t)
|
|
||||||
local C = REDGCI_KERNEL.C
|
|
||||||
local dx = t.x - f.x
|
|
||||||
local dz = t.z - f.z
|
|
||||||
local range = REDGCI_KERNEL.vec2len(dx, dz)
|
|
||||||
if range < 1.0 then return 0.0, 0.0 end
|
|
||||||
local base_bearing = REDGCI_KERNEL.bearing(dx, dz)
|
|
||||||
local aspect_rad = math.rad(REDGCI_KERNEL.aspectAngle(t, f))
|
|
||||||
local speed_ratio = (t.speed or 1.0) / ((f.speed or 1.0) + 1e-6)
|
|
||||||
local sin_lead = REDGCI_KERNEL.clamp(speed_ratio * math.sin(aspect_rad), -1.0, 1.0)
|
|
||||||
local lead_deg = math.deg(math.asin(sin_lead))
|
|
||||||
local hdg
|
|
||||||
if math.abs(lead_deg) < 45.0 then
|
|
||||||
hdg = (base_bearing + lead_deg + 360.0) % 360.0
|
|
||||||
else
|
|
||||||
hdg = base_bearing
|
|
||||||
end
|
|
||||||
local closing = REDGCI_KERNEL.closureRate(f, t)
|
|
||||||
if closing < 50.0 then closing = 50.0 end
|
|
||||||
local tti = math.min(range / closing, C.MAX_TTI)
|
|
||||||
return hdg, tti
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
-- computeIntercept (GCI-Koordinaten intern)
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function REDGCI_KERNEL.computeIntercept(fighter, target)
|
|
||||||
local C = REDGCI_KERNEL.C
|
|
||||||
local dx = target.x - fighter.x
|
|
||||||
local dz = target.z - fighter.z
|
|
||||||
local sol = {
|
|
||||||
heading_deg = 0.0,
|
|
||||||
time_to_intercept = C.MAX_TTI,
|
|
||||||
intercept_point = { x=target.x, z=target.z, y=target.y },
|
|
||||||
target_alt = target.y,
|
|
||||||
solution_found = false,
|
|
||||||
aspect_angle = REDGCI_KERNEL.aspectAngle(target, fighter),
|
|
||||||
range = REDGCI_KERNEL.vec2len(dx, dz),
|
|
||||||
mode = C.PURSUIT_NO_SOLUTION,
|
|
||||||
weapons_free = false,
|
|
||||||
}
|
|
||||||
local closure = REDGCI_KERNEL.closureRate(fighter, target)
|
|
||||||
local projected_range = sol.range - closure * C.TICK_INTERVAL
|
|
||||||
sol.weapons_free = (sol.range < C.WF_RANGE_MAX) or
|
|
||||||
(closure > 0.0 and projected_range < C.WF_RANGE_MAX)
|
|
||||||
local ok, hdg, tti, ip = REDGCI_KERNEL._solveCollision(fighter, target)
|
|
||||||
if ok then
|
|
||||||
sol.heading_deg = hdg
|
|
||||||
sol.time_to_intercept = tti
|
|
||||||
sol.intercept_point = ip
|
|
||||||
sol.solution_found = true
|
|
||||||
sol.mode = C.PURSUIT_COLLISION
|
|
||||||
return sol
|
|
||||||
end
|
|
||||||
local lhdg, ltti = REDGCI_KERNEL._solveLead(fighter, target)
|
|
||||||
sol.heading_deg = lhdg
|
|
||||||
sol.time_to_intercept = ltti
|
|
||||||
sol.solution_found = true
|
|
||||||
sol.mode = C.PURSUIT_LEAD
|
|
||||||
sol.intercept_point = {
|
|
||||||
x = target.x + (target.vx or 0.0) * ltti,
|
|
||||||
z = target.z + (target.vz or 0.0) * ltti,
|
|
||||||
y = math.max(target.y + C.ALT_OFFSET_LOOKDOWN, 300.0),
|
|
||||||
}
|
|
||||||
return sol
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
-- computeInterceptDCS (DCS-Koordinaten Ein/Aus)
|
|
||||||
-- Flat-Rückgabe kompatibel mit alter C-API
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function REDGCI_KERNEL.computeInterceptDCS(f, t)
|
|
||||||
local f_gci = { x=f.z, z=f.x, y=f.y, vx=f.vz, vz=f.vx, vy=f.vy, speed=f.spd }
|
|
||||||
local t_gci = { x=t.z, z=t.x, y=t.y, vx=t.vz, vz=t.vx, vy=t.vy, speed=t.spd }
|
|
||||||
local sol = REDGCI_KERNEL.computeIntercept(f_gci, t_gci)
|
|
||||||
-- GCI→DCS: ip.z(Nord)→DCS.x, ip.x(Ost)→DCS.z
|
|
||||||
return sol.heading_deg,
|
|
||||||
sol.time_to_intercept,
|
|
||||||
sol.mode,
|
|
||||||
sol.weapons_free,
|
|
||||||
sol.range,
|
|
||||||
sol.aspect_angle,
|
|
||||||
sol.intercept_point.z,
|
|
||||||
sol.intercept_point.x,
|
|
||||||
sol.intercept_point.y,
|
|
||||||
sol.target_alt
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
-- computeSplit (GCI-Koordinaten intern)
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function REDGCI_KERNEL.computeSplit(f1, f2, tgt, tactic, variation)
|
|
||||||
local C = REDGCI_KERNEL.C
|
|
||||||
variation = REDGCI_KERNEL.clamp(variation or 0.5, 0.0, 1.0)
|
|
||||||
tactic = tactic or C.TACTIC_PINCER
|
|
||||||
local mid_x = (f1.x + f2.x) * 0.5
|
|
||||||
local mid_z = (f1.z + f2.z) * 0.5
|
|
||||||
local dx = tgt.x - mid_x
|
|
||||||
local dz = tgt.z - mid_z
|
|
||||||
local rng = REDGCI_KERNEL.vec2len(dx, dz)
|
|
||||||
if rng < 1.0 then rng = 1.0 end
|
|
||||||
local ax = dx / rng
|
|
||||||
local az = dz / rng
|
|
||||||
local px = -az
|
|
||||||
local pz = ax
|
|
||||||
|
|
||||||
local plan = {
|
|
||||||
tactic = tactic,
|
|
||||||
wp_f1 = { x=0, z=0, y=0 },
|
|
||||||
wp_f2 = { x=0, z=0, y=0 },
|
|
||||||
merge_f1 = { x=0, z=0, y=0 },
|
|
||||||
merge_f2 = { x=0, z=0, y=0 },
|
|
||||||
}
|
|
||||||
|
|
||||||
local function clamp_alt(pt)
|
|
||||||
if pt.y < 300.0 then pt.y = 300.0 end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function clamp_alt_noe(pt)
|
|
||||||
if pt.y < 150.0 then pt.y = 150.0 end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- GIRAFFE F2 fliegt NOE — separater clamp mit niedrigerer Mindesthöhe
|
|
||||||
local function clamp_alt_noe(pt)
|
|
||||||
if pt.y < 150.0 then pt.y = 150.0 end
|
|
||||||
end
|
|
||||||
|
|
||||||
if tactic == C.TACTIC_PINCER then
|
|
||||||
local spread = 12000.0 + variation * 5000.0
|
|
||||||
local approach = rng * 0.45
|
|
||||||
local merge_off = spread * 0.30
|
|
||||||
plan.wp_f1 = { x=mid_x+ax*approach+px*spread, z=mid_z+az*approach+pz*spread, y=tgt.y }
|
|
||||||
plan.wp_f2 = { x=mid_x+ax*approach-px*spread, z=mid_z+az*approach-pz*spread, y=tgt.y }
|
|
||||||
plan.merge_f1 = { x=tgt.x-ax*3000+px*merge_off, z=tgt.z-az*3000+pz*merge_off, y=tgt.y }
|
|
||||||
plan.merge_f2 = { x=tgt.x-ax*3000-px*merge_off, z=tgt.z-az*3000-pz*merge_off, y=tgt.y }
|
|
||||||
|
|
||||||
elseif tactic == C.TACTIC_HIGH_LOW then
|
|
||||||
local vert = 3000.0 + variation * 1500.0
|
|
||||||
local approach = rng * 0.50
|
|
||||||
local side_off = 2000.0
|
|
||||||
plan.wp_f1 = { x=mid_x+ax*approach+px*side_off, z=mid_z+az*approach+pz*side_off, y=tgt.y-500.0 }
|
|
||||||
plan.wp_f2 = { x=mid_x+ax*approach-px*side_off, z=mid_z+az*approach-pz*side_off, y=tgt.y+vert }
|
|
||||||
plan.merge_f1 = { x=tgt.x-ax*3000+px*side_off, z=tgt.z-az*3000+pz*side_off, y=plan.wp_f1.y }
|
|
||||||
plan.merge_f2 = { x=tgt.x-ax*3000-px*side_off, z=tgt.z-az*3000-pz*side_off, y=plan.wp_f2.y }
|
|
||||||
|
|
||||||
elseif tactic == C.TACTIC_STAGGER then
|
|
||||||
local lag = 8000.0 + variation * 3000.0
|
|
||||||
local lead_dist = rng * 0.85
|
|
||||||
plan.wp_f1 = { x=mid_x+ax*lead_dist, z=mid_z+az*lead_dist, y=tgt.y }
|
|
||||||
plan.wp_f2 = { x=mid_x+ax*(lead_dist-lag), z=mid_z+az*(lead_dist-lag), y=tgt.y }
|
|
||||||
plan.merge_f1 = { x=plan.wp_f1.x, z=plan.wp_f1.z, y=plan.wp_f1.y }
|
|
||||||
plan.merge_f2 = { x=plan.wp_f2.x, z=plan.wp_f2.z, y=plan.wp_f2.y }
|
|
||||||
|
|
||||||
elseif tactic == C.TACTIC_TRAIL then
|
|
||||||
local lag = 3000.0 + variation * 2000.0
|
|
||||||
local lead_dist = rng * 0.85
|
|
||||||
local side_off = 500.0
|
|
||||||
plan.wp_f1 = { x=mid_x+ax*lead_dist, z=mid_z+az*lead_dist, y=tgt.y }
|
|
||||||
plan.wp_f2 = { x=mid_x+ax*(lead_dist-lag)+px*side_off, z=mid_z+az*(lead_dist-lag)+pz*side_off, y=tgt.y }
|
|
||||||
plan.merge_f1 = { x=plan.wp_f1.x, z=plan.wp_f1.z, y=plan.wp_f1.y }
|
|
||||||
plan.merge_f2 = { x=plan.wp_f2.x, z=plan.wp_f2.z, y=plan.wp_f2.y }
|
|
||||||
|
|
||||||
elseif tactic == C.TACTIC_GIRAFFE then
|
|
||||||
-- ── GIRAFFE: Irak/Iran-Doktrin (Mirage F1 vs F-14A) ──────────────
|
|
||||||
--
|
|
||||||
-- F1 = Decoy: normale Höhe, direkter Anflug, bindet AWG-9 Radar.
|
|
||||||
-- Zieht Phoenixe auf sich — gibt F2 Zeit für Pull-up.
|
|
||||||
--
|
|
||||||
-- F2 = Killer: Nap-of-Earth (~300-600m AGL/MSL) weit seitlich versetzt.
|
|
||||||
-- Nutzt Groundclutter um AWG-9 Look-Down zu degradieren.
|
|
||||||
-- Nähert sich bis 10km vor Ziel, dann Pull-up und Schuss.
|
|
||||||
-- Seitlicher Versatz ~8-12km damit F2 nicht im Radarsektor
|
|
||||||
-- des AWG-9 liegt während F1 den Lock hält.
|
|
||||||
--
|
|
||||||
-- Historisch: Iran-Irak Krieg 1982-88. Irakische Mirage F1EQ nutzten
|
|
||||||
-- dieses Profil gegen F-14A/AIM-54 Phoenix — der AWG-9 hatte trotz
|
|
||||||
-- Look-Down-Fähigkeit bei sehr tiefen Zielen über unebenen Terrain
|
|
||||||
-- (Zagros-Berge, Khuzestan-Ebene) erhöhte Clutter-Probleme.
|
|
||||||
--
|
|
||||||
-- Höhen: neutral (0.0) — Lua addiert AltOffset + terrain-awareness.
|
|
||||||
-- Mindesthöhe 300m MSL wird am Ende geclampt.
|
|
||||||
|
|
||||||
local noe_alt = 300.0 + variation * 300.0 -- 300-600m MSL (Nap-of-Earth)
|
|
||||||
local side_off = 8000.0 + variation * 4000.0 -- 8-12km seitlich (aus AWG-9 Sektor)
|
|
||||||
local approach = rng * 0.60 -- F1 direkter Anflug, 60% des Weges
|
|
||||||
local noe_dist = rng * 0.75 -- F2 nähert sich weiter ran vor Pull-up
|
|
||||||
|
|
||||||
plan.wp_f1 = { x=mid_x+ax*approach+px*2000, z=mid_z+az*approach+pz*2000, y=tgt.y }
|
|
||||||
plan.merge_f1 = { x=tgt.x-ax*5000+px*2000, z=tgt.z-az*5000+pz*2000, y=tgt.y }
|
|
||||||
plan.wp_f2 = { x=mid_x+ax*noe_dist-px*side_off, z=mid_z+az*noe_dist-pz*side_off, y=noe_alt, absolute_alt=true }
|
|
||||||
plan.merge_f2 = { x=tgt.x-ax*10000-px*side_off*0.3, z=tgt.z-az*10000-pz*side_off*0.3, y=tgt.y }
|
|
||||||
|
|
||||||
else
|
|
||||||
plan.wp_f1 = { x=tgt.x, z=tgt.z, y=tgt.y }
|
|
||||||
plan.wp_f2 = { x=tgt.x, z=tgt.z, y=tgt.y }
|
|
||||||
plan.merge_f1 = { x=tgt.x, z=tgt.z, y=tgt.y }
|
|
||||||
plan.merge_f2 = { x=tgt.x, z=tgt.z, y=tgt.y }
|
|
||||||
end
|
|
||||||
|
|
||||||
clamp_alt(plan.wp_f1)
|
|
||||||
if tactic == C.TACTIC_GIRAFFE then
|
|
||||||
clamp_alt_noe(plan.wp_f2)
|
|
||||||
else
|
|
||||||
clamp_alt(plan.wp_f2)
|
|
||||||
end
|
|
||||||
clamp_alt(plan.merge_f1)
|
|
||||||
clamp_alt(plan.merge_f2)
|
|
||||||
return plan
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
-- computeSplitDCS (DCS-Koordinaten Ein/Aus)
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function REDGCI_KERNEL.computeSplitDCS(f1, f2, tgt, tactic, variation)
|
|
||||||
local function dcs2gci(u)
|
|
||||||
return { x=u.z, z=u.x, y=u.y, vx=u.vz or 0, vz=u.vx or 0, speed=u.spd or 0 }
|
|
||||||
end
|
|
||||||
local function gci2dcs(pt)
|
|
||||||
return { x=pt.z, z=pt.x, y=pt.y, absolute_alt=pt.absolute_alt }
|
|
||||||
end
|
|
||||||
local tgt_gci = { x=tgt.z, z=tgt.x, y=tgt.y }
|
|
||||||
local plan = REDGCI_KERNEL.computeSplit(
|
|
||||||
dcs2gci(f1), dcs2gci(f2), tgt_gci, tactic, variation)
|
|
||||||
plan.wp_f1 = gci2dcs(plan.wp_f1)
|
|
||||||
plan.wp_f2 = gci2dcs(plan.wp_f2)
|
|
||||||
plan.merge_f1 = gci2dcs(plan.merge_f1)
|
|
||||||
plan.merge_f2 = gci2dcs(plan.merge_f2)
|
|
||||||
return plan
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
-- buildTransmission (Port von gci_build_transmission)
|
|
||||||
--
|
|
||||||
-- ctx/prev Felder: state, prev_state, ticks_in_state, range,
|
|
||||||
-- aspect_angle, closure_rate, altitude_delta, fuel_fraction
|
|
||||||
-- sol Felder: heading_deg, time_to_intercept, target_alt,
|
|
||||||
-- range, aspect_angle, weapons_free
|
|
||||||
-- Rückgabe: { token_str, delay_sec, weapons_free, silence }
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function REDGCI_KERNEL.buildTransmission(ctx, prev, sol)
|
|
||||||
local C = REDGCI_KERNEL.C
|
|
||||||
local tx = {
|
|
||||||
token_str = "",
|
|
||||||
delay_sec = REDGCI_KERNEL.clamp(
|
|
||||||
REDGCI_KERNEL.randDelay(C.DELAY_MIN, C.DELAY_MAX), 3.0, 8.0),
|
|
||||||
weapons_free = sol.weapons_free,
|
|
||||||
silence = false,
|
|
||||||
priority = 50,
|
|
||||||
}
|
|
||||||
|
|
||||||
local hdg_i = math.floor((sol.heading_deg or 0) + 0.5)
|
|
||||||
local alt_i = math.floor((sol.target_alt or 0) / 100.0 + 0.5) * 100
|
|
||||||
local rng_km = math.floor((ctx.range or 0) / 1000.0 + 0.5)
|
|
||||||
local aspect_i = math.floor((ctx.aspect_angle or 0) + 0.5)
|
|
||||||
local delay = tx.delay_sec
|
|
||||||
local state = ctx.state or "VECTOR"
|
|
||||||
local prev_state = prev.state or "VECTOR"
|
|
||||||
local ticks = ctx.ticks_in_state or 0
|
|
||||||
|
|
||||||
local function emit(fmt, ...)
|
|
||||||
tx.token_str = string.format(fmt, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
if state == "VECTOR" then
|
|
||||||
if prev_state ~= "VECTOR" then
|
|
||||||
local tti_m = math.floor((sol.time_to_intercept or 0) / 60.0)
|
|
||||||
local tti_s = math.floor(sol.time_to_intercept or 0) % 60
|
|
||||||
if tti_m > 0 then
|
|
||||||
emit("VECTOR_WITH_TTI|hdg=%d|alt=%d|rng=%d|tti_m=%d|tti_s=%d|delay=%.1f",
|
|
||||||
hdg_i, alt_i, rng_km, tti_m, tti_s, delay)
|
|
||||||
else
|
|
||||||
emit("VECTOR|hdg=%d|alt=%d|rng=%d|delay=%.1f",
|
|
||||||
hdg_i, alt_i, rng_km, delay)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local hdg_delta = math.abs((sol.heading_deg or 0) - (ctx.aspect_angle or 0))
|
|
||||||
if hdg_delta < 5.0 and ticks > 3 then
|
|
||||||
tx.silence = true
|
|
||||||
else
|
|
||||||
emit("VECTOR|hdg=%d|alt=%d|rng=%d|delay=%.1f",
|
|
||||||
hdg_i, alt_i, rng_km, delay)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif state == "COMMIT" then
|
|
||||||
if prev_state ~= "COMMIT" then
|
|
||||||
tx.priority = 100
|
|
||||||
emit("COMMIT_FIRST|hdg=%d|alt=%d|rng=%d|aspect=%d|delay=%.1f",
|
|
||||||
hdg_i, alt_i, rng_km, aspect_i, delay)
|
|
||||||
elseif ticks == 6 then
|
|
||||||
emit("COMMIT_NO_LOCK|hdg=%d|rng=%d|aspect=%d|delay=%.1f",
|
|
||||||
hdg_i, rng_km, aspect_i, delay)
|
|
||||||
elseif ticks > 8 then
|
|
||||||
emit("COMMIT_NUDGE|hdg=%d|aspect=%d|delay=%.1f",
|
|
||||||
hdg_i, aspect_i, delay)
|
|
||||||
else
|
|
||||||
tx.silence = true
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif state == "RADAR_CONTACT" then
|
|
||||||
if prev_state ~= "RADAR_CONTACT" then
|
|
||||||
if sol.weapons_free then
|
|
||||||
tx.priority = 100
|
|
||||||
emit("RADAR_LOCK_WF|rng=%d|delay=%.1f", rng_km, delay)
|
|
||||||
tx.weapons_free = true
|
|
||||||
else
|
|
||||||
emit("RADAR_LOCK_HOLD|rng=%d|delay=%.1f", rng_km, delay)
|
|
||||||
end
|
|
||||||
elseif not sol.weapons_free
|
|
||||||
and (ctx.range or 0) < C.WF_RANGE_MAX
|
|
||||||
and (ctx.aspect_angle or 0) > C.ASPECT_REAR_ATTACK
|
|
||||||
and prev_state == "RADAR_CONTACT" then
|
|
||||||
emit("RADAR_WF_NOW|rng=%d|delay=%.1f", rng_km, delay)
|
|
||||||
tx.priority = 100
|
|
||||||
tx.weapons_free = true
|
|
||||||
else
|
|
||||||
tx.silence = true
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif state == "VISUAL" then
|
|
||||||
if prev_state ~= "VISUAL" then
|
|
||||||
emit("VISUAL_CONFIRM|rng=%d|delay=%.1f", rng_km, delay)
|
|
||||||
tx.weapons_free = true
|
|
||||||
else
|
|
||||||
tx.silence = true
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif state == "NOTCH" then
|
|
||||||
if prev_state ~= "NOTCH" then
|
|
||||||
emit("NOTCH_ENTRY|delay=1.5")
|
|
||||||
elseif ticks % 8 == 0 then
|
|
||||||
emit("NOTCH_UPDATE|rng=%d|aspect=%d|delay=%.1f",
|
|
||||||
rng_km, aspect_i, delay)
|
|
||||||
else
|
|
||||||
tx.silence = true
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif state == "ABORT" then
|
|
||||||
tx.delay_sec = 1.5
|
|
||||||
if (ctx.fuel_fraction or 1.0) < C.FUEL_BINGO then
|
|
||||||
emit("ABORT_BINGO|hdg=%d|delay=1.5", hdg_i)
|
|
||||||
else
|
|
||||||
emit("ABORT_THREAT|hdg=%d|delay=1.5", hdg_i)
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
tx.silence = true
|
|
||||||
end
|
|
||||||
|
|
||||||
return tx
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
-- mergeTransition (Port von gci_merge_transition)
|
|
||||||
--
|
|
||||||
-- ctx Felder: phase, ticks_in_phase, range, bearing_to_target,
|
|
||||||
-- closure_rate, altitude_delta, pass_count, radar_lost
|
|
||||||
-- Rückgabe: phase string
|
|
||||||
-- "ENTRY"|"OVERSHOOT"|"SEPARATION"|"REATTACK"|"LOST"|"SPLASH"
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function REDGCI_KERNEL.mergeTransition(ctx, prev)
|
|
||||||
if ctx.radar_lost then return "LOST" end
|
|
||||||
if (ctx.closure_rate or 0) < -30.0 and (ctx.range or 0) > 3000.0 then
|
|
||||||
return "SEPARATION"
|
|
||||||
end
|
|
||||||
local brg = ctx.bearing_to_target or 0
|
|
||||||
if brg > 100.0 and brg < 260.0 and (ctx.range or 0) < 5000.0 then
|
|
||||||
return "OVERSHOOT"
|
|
||||||
end
|
|
||||||
if ctx.phase == "SEPARATION" and (ctx.pass_count or 0) < 3 then
|
|
||||||
return "REATTACK"
|
|
||||||
end
|
|
||||||
return ctx.phase
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
-- buildMergeTransmission (Port von gci_build_merge_transmission)
|
|
||||||
-- ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function REDGCI_KERNEL.buildMergeTransmission(ctx, prev)
|
|
||||||
local C = REDGCI_KERNEL.C
|
|
||||||
local tx = {
|
|
||||||
token_str = "",
|
|
||||||
delay_sec = REDGCI_KERNEL.clamp(
|
|
||||||
REDGCI_KERNEL.randDelay(C.DELAY_MERGE_MIN, C.DELAY_MERGE_MAX), 2.0, 5.0),
|
|
||||||
weapons_free = false,
|
|
||||||
silence = false,
|
|
||||||
priority = 50,
|
|
||||||
}
|
|
||||||
|
|
||||||
local brg = math.floor((ctx.bearing_to_target or 0) + 0.5)
|
|
||||||
local rng_km = math.floor((ctx.range or 0) / 1000.0 + 0.5)
|
|
||||||
local delay = tx.delay_sec
|
|
||||||
local phase = ctx.phase or "ENTRY"
|
|
||||||
local prev_phase = prev.phase or "ENTRY"
|
|
||||||
local ticks = ctx.ticks_in_phase or 0
|
|
||||||
|
|
||||||
local dir_rl = ((ctx.bearing_to_target or 0) < 180.0) and "right" or "left"
|
|
||||||
local alt_d = ctx.altitude_delta or 0
|
|
||||||
local alt_rel = ""
|
|
||||||
if alt_d > 400.0 then alt_rel = "low"
|
|
||||||
elseif alt_d < -400.0 then alt_rel = "high"
|
|
||||||
end
|
|
||||||
|
|
||||||
local function emit(fmt, ...)
|
|
||||||
tx.token_str = string.format(fmt, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
if phase == "ENTRY" then
|
|
||||||
tx.priority = 100
|
|
||||||
emit("MERGE_ENTRY|brg=%d|dir_rl=%s|delay=%.1f", brg, dir_rl, delay)
|
|
||||||
|
|
||||||
elseif phase == "OVERSHOOT" then
|
|
||||||
emit("MERGE_OVERSHOOT|brg=%d|dir_rl=%s|alt_rel=%s|delay=%.1f",
|
|
||||||
brg, dir_rl, alt_rel, delay)
|
|
||||||
|
|
||||||
elseif phase == "SEPARATION" then
|
|
||||||
if (ctx.pass_count or 0) < 3 then
|
|
||||||
emit("MERGE_REATTACK|brg=%d|rng=%d|delay=%.1f", brg, rng_km, delay)
|
|
||||||
else
|
|
||||||
emit("ABORT_THREAT|hdg=%d|delay=%.1f", brg, delay)
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif phase == "REATTACK" then
|
|
||||||
if prev_phase ~= "REATTACK" or ticks % 3 == 0 then
|
|
||||||
emit("MERGE_REATTACK|brg=%d|rng=%d|delay=%.1f", brg, rng_km, delay)
|
|
||||||
else
|
|
||||||
tx.silence = true
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif phase == "LOST" then
|
|
||||||
if prev_phase ~= "LOST" or ticks == 4 then
|
|
||||||
emit("MERGE_LOST|brg=%d|rng=%d|delay=%.1f", brg, rng_km, delay)
|
|
||||||
else
|
|
||||||
tx.silence = true
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif phase == "SPLASH" then
|
|
||||||
tx.delay_sec = 1.5
|
|
||||||
tx.priority = 100
|
|
||||||
emit("MERGE_SPLASH|delay=1.5")
|
|
||||||
|
|
||||||
else
|
|
||||||
tx.silence = true
|
|
||||||
end
|
|
||||||
|
|
||||||
return tx
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- END of Class
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
@@ -80,11 +80,6 @@ __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Stratego.lua' )
|
|||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ClientWatch.lua')
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ClientWatch.lua')
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Formation.lua')
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Formation.lua')
|
||||||
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/RedGCIKernel.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/RedGCI.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/RedGCI2v2.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/RedGCIDispatcher.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Airboss.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Airboss.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/RecoveryTanker.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/RecoveryTanker.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/RescueHelo.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/RescueHelo.lua' )
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
-- **Supported Aircraft:**
|
-- **Supported Aircraft:**
|
||||||
--
|
--
|
||||||
-- * [F/A-18C Hornet Lot 20](https://forums.eagle.ru/forumdisplay.php?f=557) (Player & AI)
|
-- * [F/A-18C Hornet Lot 20](https://forums.eagle.ru/forumdisplay.php?f=557) (Player & AI)
|
||||||
-- * [F-14A/B/A Early Tomcat](https://forums.eagle.ru/forumdisplay.php?f=395) (Player & AI)
|
-- * [F-14A/B/B(U)/A Early Tomcat](https://forums.eagle.ru/forumdisplay.php?f=395) (Player & AI)
|
||||||
-- * [A-4E Skyhawk Community Mod](https://forums.eagle.ru/showthread.php?t=224989) (Player & AI)
|
-- * [A-4E Skyhawk Community Mod](https://forums.eagle.ru/showthread.php?t=224989) (Player & AI)
|
||||||
-- * [AV-8B N/A Harrier](https://forums.eagle.ru/forumdisplay.php?f=555) (Player & AI)
|
-- * [AV-8B N/A Harrier](https://forums.eagle.ru/forumdisplay.php?f=555) (Player & AI)
|
||||||
-- * [T-45C Goshawk](https://forum.dcs.world/topic/203816-vnao-t-45-goshawk/) (VNAO mod) (Player & AI)
|
-- * [T-45C Goshawk](https://forum.dcs.world/topic/203816-vnao-t-45-goshawk/) (VNAO mod) (Player & AI)
|
||||||
@@ -1276,6 +1276,7 @@ AIRBOSS = {
|
|||||||
-- @field #string A4EC A-4E Community mod.
|
-- @field #string A4EC A-4E Community mod.
|
||||||
-- @field #string HORNET F/A-18C Lot 20 Hornet by Eagle Dynamics.
|
-- @field #string HORNET F/A-18C Lot 20 Hornet by Eagle Dynamics.
|
||||||
-- @field #string F14A F-14A by Heatblur.
|
-- @field #string F14A F-14A by Heatblur.
|
||||||
|
-- @field #string F14BU F-14BU by Heatblur.
|
||||||
-- @field #string F14A_Early F-14A-135-GR-Early by Heatblur.
|
-- @field #string F14A_Early F-14A-135-GR-Early by Heatblur.
|
||||||
-- @field #string F14B F-14B by Heatblur.
|
-- @field #string F14B F-14B by Heatblur.
|
||||||
-- @field #string F14A_AI F-14A Tomcat (AI).
|
-- @field #string F14A_AI F-14A Tomcat (AI).
|
||||||
@@ -1297,6 +1298,7 @@ AIRBOSS.AircraftCarrier={
|
|||||||
F14A="F-14A-135-GR",
|
F14A="F-14A-135-GR",
|
||||||
F14A_Early="F-14A-135-GR-Early",
|
F14A_Early="F-14A-135-GR-Early",
|
||||||
F14B="F-14B",
|
F14B="F-14B",
|
||||||
|
F14BU="F-14BU",
|
||||||
F14A_AI="F-14A",
|
F14A_AI="F-14A",
|
||||||
FA18C="F/A-18C",
|
FA18C="F/A-18C",
|
||||||
T45C="T-45",
|
T45C="T-45",
|
||||||
@@ -5508,7 +5510,7 @@ function AIRBOSS:_GetAircraftAoA( playerData )
|
|||||||
local goshawk = playerData.actype == AIRBOSS.AircraftCarrier.T45C
|
local goshawk = playerData.actype == AIRBOSS.AircraftCarrier.T45C
|
||||||
local skyhawk = playerData.actype == AIRBOSS.AircraftCarrier.A4EC
|
local skyhawk = playerData.actype == AIRBOSS.AircraftCarrier.A4EC
|
||||||
local harrier = playerData.actype == AIRBOSS.AircraftCarrier.AV8B
|
local harrier = playerData.actype == AIRBOSS.AircraftCarrier.AV8B
|
||||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B or playerData.actype == AIRBOSS.AircraftCarrier.F14A_Early
|
local tomcat = self:_IsTomcat( playerData.actype )
|
||||||
local corsair = playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR or playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR_CW
|
local corsair = playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR or playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR_CW
|
||||||
|
|
||||||
-- Table with AoA values.
|
-- Table with AoA values.
|
||||||
@@ -5571,6 +5573,18 @@ function AIRBOSS:_GetAircraftAoA( playerData )
|
|||||||
aoa.OnSpeedMin = 9.5
|
aoa.OnSpeedMin = 9.5
|
||||||
aoa.Fast = 8.0
|
aoa.Fast = 8.0
|
||||||
aoa.FAST = 7.5
|
aoa.FAST = 7.5
|
||||||
|
else
|
||||||
|
-- Unknown carrier-capable type: _IsCarrierAircraft() is enum-driven, so a type can
|
||||||
|
-- reach here with no AoA branch. Returning an empty table nil-propagates into
|
||||||
|
-- _GetAircraftParameters() and the AoA waveoff check. Fall back to Hornet values.
|
||||||
|
self:E( self.lid .. string.format( "ERROR: No AoA parameters defined for aircraft type %s! Falling back to F/A-18C values.", tostring( playerData.actype ) ) )
|
||||||
|
aoa.SLOW = 9.8
|
||||||
|
aoa.Slow = 9.3
|
||||||
|
aoa.OnSpeedMax = 8.8
|
||||||
|
aoa.OnSpeed = 8.1
|
||||||
|
aoa.OnSpeedMin = 7.4
|
||||||
|
aoa.Fast = 6.9
|
||||||
|
aoa.FAST = 6.3
|
||||||
end
|
end
|
||||||
|
|
||||||
return aoa
|
return aoa
|
||||||
@@ -5587,7 +5601,7 @@ function AIRBOSS:_AoAUnit2Deg( playerData, aoaunits )
|
|||||||
local degrees = aoaunits
|
local degrees = aoaunits
|
||||||
|
|
||||||
-- Check aircraft type of player.
|
-- Check aircraft type of player.
|
||||||
if playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B or playerData.actype == AIRBOSS.AircraftCarrier.F14A_Early then
|
if self:_IsTomcat( playerData.actype ) then
|
||||||
|
|
||||||
-------------
|
-------------
|
||||||
-- F-14A/B --
|
-- F-14A/B --
|
||||||
@@ -5630,7 +5644,7 @@ function AIRBOSS:_AoADeg2Units( playerData, degrees )
|
|||||||
local aoaunits = degrees
|
local aoaunits = degrees
|
||||||
|
|
||||||
-- Check aircraft type of player.
|
-- Check aircraft type of player.
|
||||||
if playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B or playerData.actype == AIRBOSS.AircraftCarrier.F14A_Early then
|
if self:_IsTomcat( playerData.actype ) then
|
||||||
|
|
||||||
-------------
|
-------------
|
||||||
-- F-14A/B --
|
-- F-14A/B --
|
||||||
@@ -5680,7 +5694,7 @@ function AIRBOSS:_GetAircraftParameters( playerData, step )
|
|||||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOF
|
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOF
|
||||||
or playerData.actype == AIRBOSS.AircraftCarrier.GROWLER
|
or playerData.actype == AIRBOSS.AircraftCarrier.GROWLER
|
||||||
local skyhawk = playerData.actype == AIRBOSS.AircraftCarrier.A4EC
|
local skyhawk = playerData.actype == AIRBOSS.AircraftCarrier.A4EC
|
||||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B
|
local tomcat = self:_IsTomcat( playerData.actype )
|
||||||
local harrier = playerData.actype == AIRBOSS.AircraftCarrier.AV8B
|
local harrier = playerData.actype == AIRBOSS.AircraftCarrier.AV8B
|
||||||
local goshawk = playerData.actype == AIRBOSS.AircraftCarrier.T45C
|
local goshawk = playerData.actype == AIRBOSS.AircraftCarrier.T45C
|
||||||
local corsair = playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR or playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR_CW
|
local corsair = playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR or playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR_CW
|
||||||
@@ -6613,9 +6627,7 @@ function AIRBOSS:_RefuelAI( flight )
|
|||||||
local refuelac=false
|
local refuelac=false
|
||||||
local actype=flight.group:GetTypeName()
|
local actype=flight.group:GetTypeName()
|
||||||
if actype==AIRBOSS.AircraftCarrier.AV8B or
|
if actype==AIRBOSS.AircraftCarrier.AV8B or
|
||||||
actype==AIRBOSS.AircraftCarrier.F14A or
|
self:_IsTomcat( actype, true ) or
|
||||||
actype==AIRBOSS.AircraftCarrier.F14B or
|
|
||||||
actype==AIRBOSS.AircraftCarrier.F14A_AI or
|
|
||||||
actype==AIRBOSS.AircraftCarrier.HORNET or
|
actype==AIRBOSS.AircraftCarrier.HORNET or
|
||||||
actype==AIRBOSS.AircraftCarrier.RHINOE or
|
actype==AIRBOSS.AircraftCarrier.RHINOE or
|
||||||
actype==AIRBOSS.AircraftCarrier.RHINOF or
|
actype==AIRBOSS.AircraftCarrier.RHINOF or
|
||||||
@@ -6725,7 +6737,7 @@ function AIRBOSS:_LandAI( flight )
|
|||||||
Speed = UTILS.KnotsToKmph( 200 )
|
Speed = UTILS.KnotsToKmph( 200 )
|
||||||
elseif flight.actype == AIRBOSS.AircraftCarrier.E2D or flight.actype == AIRBOSS.AircraftCarrier.C2A then
|
elseif flight.actype == AIRBOSS.AircraftCarrier.E2D or flight.actype == AIRBOSS.AircraftCarrier.C2A then
|
||||||
Speed = UTILS.KnotsToKmph( 150 )
|
Speed = UTILS.KnotsToKmph( 150 )
|
||||||
elseif flight.actype == AIRBOSS.AircraftCarrier.F14A_AI or flight.actype == AIRBOSS.AircraftCarrier.F14A or flight.actype == AIRBOSS.AircraftCarrier.F14B then
|
elseif self:_IsTomcat( flight.actype, true ) then
|
||||||
Speed = UTILS.KnotsToKmph( 175 )
|
Speed = UTILS.KnotsToKmph( 175 )
|
||||||
elseif flight.actype == AIRBOSS.AircraftCarrier.S3B or flight.actype == AIRBOSS.AircraftCarrier.S3BTANKER then
|
elseif flight.actype == AIRBOSS.AircraftCarrier.S3B or flight.actype == AIRBOSS.AircraftCarrier.S3BTANKER then
|
||||||
Speed = UTILS.KnotsToKmph( 140 )
|
Speed = UTILS.KnotsToKmph( 140 )
|
||||||
@@ -8200,7 +8212,7 @@ function AIRBOSS:_CheckPlayerStatus()
|
|||||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOE
|
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOE
|
||||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOF
|
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOF
|
||||||
or playerData.actype == AIRBOSS.AircraftCarrier.GROWLER
|
or playerData.actype == AIRBOSS.AircraftCarrier.GROWLER
|
||||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B
|
local tomcat = self:_IsTomcat( playerData.actype )
|
||||||
|
|
||||||
-- VNAO Edit - Added wrapped up call to LSO grading Hornet
|
-- VNAO Edit - Added wrapped up call to LSO grading Hornet
|
||||||
if playerData.step==AIRBOSS.PatternStep.WAKE and hornet then-- VNAO Edit - Added
|
if playerData.step==AIRBOSS.PatternStep.WAKE and hornet then-- VNAO Edit - Added
|
||||||
@@ -9455,7 +9467,7 @@ function AIRBOSS:_Initial( playerData )
|
|||||||
|
|
||||||
-- Hook down for students.
|
-- Hook down for students.
|
||||||
if playerData.difficulty == AIRBOSS.Difficulty.EASY and playerData.actype ~= AIRBOSS.AircraftCarrier.AV8B then
|
if playerData.difficulty == AIRBOSS.Difficulty.EASY and playerData.actype ~= AIRBOSS.AircraftCarrier.AV8B then
|
||||||
if playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B then
|
if self:_IsTomcat( playerData.actype ) then
|
||||||
hint = hint .. " - Hook down, SAS on, Wing Sweep 68°!"
|
hint = hint .. " - Hook down, SAS on, Wing Sweep 68°!"
|
||||||
else
|
else
|
||||||
hint = hint .. " - Hook down!"
|
hint = hint .. " - Hook down!"
|
||||||
@@ -9620,8 +9632,7 @@ function AIRBOSS:_DirtyUp( playerData )
|
|||||||
|
|
||||||
-- Radio call "Say/Fly needles". Delayed by 10/15 seconds.
|
-- Radio call "Say/Fly needles". Delayed by 10/15 seconds.
|
||||||
if playerData.actype == AIRBOSS.AircraftCarrier.HORNET
|
if playerData.actype == AIRBOSS.AircraftCarrier.HORNET
|
||||||
or playerData.actype == AIRBOSS.AircraftCarrier.F14A
|
or self:_IsTomcat( playerData.actype )
|
||||||
or playerData.actype == AIRBOSS.AircraftCarrier.F14B
|
|
||||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOE
|
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOE
|
||||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOF
|
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOF
|
||||||
or playerData.actype == AIRBOSS.AircraftCarrier.GROWLER
|
or playerData.actype == AIRBOSS.AircraftCarrier.GROWLER
|
||||||
@@ -10815,7 +10826,7 @@ function AIRBOSS:_Trapped( playerData )
|
|||||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOF
|
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOF
|
||||||
or playerData.actype == AIRBOSS.AircraftCarrier.GROWLER then
|
or playerData.actype == AIRBOSS.AircraftCarrier.GROWLER then
|
||||||
dcorr = 100
|
dcorr = 100
|
||||||
elseif playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B then
|
elseif self:_IsTomcat( playerData.actype ) then
|
||||||
-- TODO: Check Tomcat.
|
-- TODO: Check Tomcat.
|
||||||
dcorr = 100
|
dcorr = 100
|
||||||
elseif playerData.actype == AIRBOSS.AircraftCarrier.A4EC then
|
elseif playerData.actype == AIRBOSS.AircraftCarrier.A4EC then
|
||||||
@@ -11628,7 +11639,7 @@ function AIRBOSS:_AttitudeMonitor( playerData )
|
|||||||
|
|
||||||
local unitClient = Unit.getByName(unit:GetName()) -- VNAO Edit - Added
|
local unitClient = Unit.getByName(unit:GetName()) -- VNAO Edit - Added
|
||||||
local hornet = playerData.actype == AIRBOSS.AircraftCarrier.HORNET -- VNAO Edit - Added
|
local hornet = playerData.actype == AIRBOSS.AircraftCarrier.HORNET -- VNAO Edit - Added
|
||||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B or playerData.actype == AIRBOSS.AircraftCarrier.F14A_Early -- VNAO Edit - Added
|
local tomcat = self:_IsTomcat( playerData.actype ) -- VNAO Edit - Added
|
||||||
|
|
||||||
if hornet then -- VNAO Edit - Added
|
if hornet then -- VNAO Edit - Added
|
||||||
local nozzlePosL = 0 -- VNAO Edit - Added
|
local nozzlePosL = 0 -- VNAO Edit - Added
|
||||||
@@ -11861,7 +11872,7 @@ function AIRBOSS:_NozzleArgumentLeft( unit ) -- VNAO Edit - Added
|
|||||||
else -- VNAO Edit - Added
|
else -- VNAO Edit - Added
|
||||||
nozzlePosL = 0 -- VNAO Edit - Added
|
nozzlePosL = 0 -- VNAO Edit - Added
|
||||||
end -- VNAO Edit - Added
|
end -- VNAO Edit - Added
|
||||||
elseif typeName == "F-14A-135-GR" or typeName == "F-14B" or typeName == "F-14A-135-GR-Early" then -- VNAO Edit - Added
|
elseif self:_IsTomcat( typeName ) then -- VNAO Edit - Added
|
||||||
nozzlePosL = unitClient:getDrawArgumentValue(434) -- VNAO Edit - Added
|
nozzlePosL = unitClient:getDrawArgumentValue(434) -- VNAO Edit - Added
|
||||||
end -- VNAO Edit - Added
|
end -- VNAO Edit - Added
|
||||||
|
|
||||||
@@ -11886,7 +11897,7 @@ function AIRBOSS:_NozzleArgumentRight( unit ) -- VNAO Edit - Added
|
|||||||
else -- VNAO Edit - Added
|
else -- VNAO Edit - Added
|
||||||
nozzlePosR = 0 -- VNAO Edit - Added
|
nozzlePosR = 0 -- VNAO Edit - Added
|
||||||
end -- VNAO Edit - Added
|
end -- VNAO Edit - Added
|
||||||
elseif typeName == "F-14A-135-GR" or typeName == "F-14B" or typeName == "F-14A-135-GR-Early" then -- VNAO Edit - Added
|
elseif self:_IsTomcat( typeName ) then -- VNAO Edit - Added
|
||||||
nozzlePosR = unitClient:getDrawArgumentValue(433) -- VNAO Edit - Added
|
nozzlePosR = unitClient:getDrawArgumentValue(433) -- VNAO Edit - Added
|
||||||
end -- VNAO Edit - Added
|
end -- VNAO Edit - Added
|
||||||
return nozzlePosR -- VNAO Edit - Added
|
return nozzlePosR -- VNAO Edit - Added
|
||||||
@@ -13149,7 +13160,7 @@ function AIRBOSS:_Flightdata2Text( playerData, groovestep )
|
|||||||
|
|
||||||
|
|
||||||
local hornet = playerData.actype == AIRBOSS.AircraftCarrier.HORNET-- VNAO Edit - Added
|
local hornet = playerData.actype == AIRBOSS.AircraftCarrier.HORNET-- VNAO Edit - Added
|
||||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B-- VNAO Edit - Added
|
local tomcat = self:_IsTomcat( playerData.actype )-- VNAO Edit - Added
|
||||||
|
|
||||||
if hornet then-- VNAO Edit - Added
|
if hornet then-- VNAO Edit - Added
|
||||||
if Lnoz > 0.6 and Rnoz > 0.6 then -- VNAO Edit - Added check them both, it's possilbe there could be a single engine landing and one is in idle perhaps?
|
if Lnoz > 0.6 and Rnoz > 0.6 then -- VNAO Edit - Added check them both, it's possilbe there could be a single engine landing and one is in idle perhaps?
|
||||||
@@ -13665,7 +13676,7 @@ function AIRBOSS:_StepHint( playerData, step )
|
|||||||
|
|
||||||
-- Late break.
|
-- Late break.
|
||||||
if step == AIRBOSS.PatternStep.LATEBREAK then
|
if step == AIRBOSS.PatternStep.LATEBREAK then
|
||||||
if playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B then
|
if self:_IsTomcat( playerData.actype ) then
|
||||||
hint = hint .. "\nWing Sweep 20°, Gear DOWN < 280 KIAS."
|
hint = hint .. "\nWing Sweep 20°, Gear DOWN < 280 KIAS."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -13674,7 +13685,7 @@ function AIRBOSS:_StepHint( playerData, step )
|
|||||||
if step == AIRBOSS.PatternStep.ABEAM then
|
if step == AIRBOSS.PatternStep.ABEAM then
|
||||||
if playerData.actype == AIRBOSS.AircraftCarrier.AV8B then
|
if playerData.actype == AIRBOSS.AircraftCarrier.AV8B then
|
||||||
hint = hint .. "\nNozzles 50°-60°. Antiskid OFF. Lights OFF."
|
hint = hint .. "\nNozzles 50°-60°. Antiskid OFF. Lights OFF."
|
||||||
elseif playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B then
|
elseif self:_IsTomcat( playerData.actype ) then
|
||||||
hint = hint .. "\nSlats/Flaps EXTENDED < 225 KIAS. DLC SELECTED. Auto Throttle IF DESIRED."
|
hint = hint .. "\nSlats/Flaps EXTENDED < 225 KIAS. DLC SELECTED. Auto Throttle IF DESIRED."
|
||||||
else
|
else
|
||||||
hint = hint .. "\nDirty up! Gear DOWN, flaps DOWN. Check hook down."
|
hint = hint .. "\nDirty up! Gear DOWN, flaps DOWN. Check hook down."
|
||||||
@@ -15109,7 +15120,7 @@ function AIRBOSS:_GetACNickname( actype )
|
|||||||
nickname = "Hawkeye"
|
nickname = "Hawkeye"
|
||||||
elseif actype == AIRBOSS.AircraftCarrier.C2A then
|
elseif actype == AIRBOSS.AircraftCarrier.C2A then
|
||||||
nickname = "Greyhound"
|
nickname = "Greyhound"
|
||||||
elseif actype == AIRBOSS.AircraftCarrier.F14A_AI or actype == AIRBOSS.AircraftCarrier.F14A or actype == AIRBOSS.AircraftCarrier.F14B or actype == AIRBOSS.AircraftCarrier.F14A_Early then
|
elseif self:_IsTomcat( actype, true ) then
|
||||||
nickname = "Tomcat"
|
nickname = "Tomcat"
|
||||||
elseif actype == AIRBOSS.AircraftCarrier.FA18C or actype == AIRBOSS.AircraftCarrier.HORNET then
|
elseif actype == AIRBOSS.AircraftCarrier.FA18C or actype == AIRBOSS.AircraftCarrier.HORNET then
|
||||||
nickname = "Hornet"
|
nickname = "Hornet"
|
||||||
@@ -15246,6 +15257,29 @@ function AIRBOSS:_GetGoodBadScore( playerData )
|
|||||||
return lowscore, badscore
|
return lowscore, badscore
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check whether an aircraft type name is any F-14 Tomcat variant.
|
||||||
|
-- Central predicate so that adding a new Tomcat variant only requires editing
|
||||||
|
-- this function and the AIRBOSS.AircraftCarrier enum.
|
||||||
|
-- @param #AIRBOSS self
|
||||||
|
-- @param #string actype Aircraft type name, e.g. from `unit:GetTypeName()` or `playerData.actype`.
|
||||||
|
-- @param #boolean IncludeAI If true, also match the AI-only F-14A (AIRBOSS.AircraftCarrier.F14A_AI).
|
||||||
|
-- @return #boolean If true, actype is an F-14 variant.
|
||||||
|
function AIRBOSS:_IsTomcat( actype, IncludeAI )
|
||||||
|
|
||||||
|
if actype == AIRBOSS.AircraftCarrier.F14A
|
||||||
|
or actype == AIRBOSS.AircraftCarrier.F14B
|
||||||
|
or actype == AIRBOSS.AircraftCarrier.F14BU
|
||||||
|
or actype == AIRBOSS.AircraftCarrier.F14A_Early then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if IncludeAI and actype == AIRBOSS.AircraftCarrier.F14A_AI then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
--- Check if aircraft is capable of landing on this aircraft carrier.
|
--- Check if aircraft is capable of landing on this aircraft carrier.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param Wrapper.Unit#UNIT unit Aircraft unit. (Will also work with groups as given parameter.)
|
-- @param Wrapper.Unit#UNIT unit Aircraft unit. (Will also work with groups as given parameter.)
|
||||||
@@ -19394,4 +19428,4 @@ function AIRBOSS:onafterLSOGrade(From, Event, To, playerData, grade)
|
|||||||
self.funkmanSocket:SendTable(result)
|
self.funkmanSocket:SendTable(result)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6466,7 +6466,13 @@ function AUFTRAG:GetDCSMissionTask(MissionGroup)
|
|||||||
-- ESCORT Mission --
|
-- ESCORT Mission --
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
local DCStask=CONTROLLABLE.TaskEscort(nil, self.engageTarget:GetObject(), self.escortVec3, nil, self.engageMaxDistance, self.engageTargetTypes)
|
local FollowGroup=self.engageTarget:GetObject()
|
||||||
|
local DCStask=nil
|
||||||
|
if next(self.engageTargetTypes)==nil then
|
||||||
|
DCStask=FollowGroup:TaskFollow(FollowGroup, self.escortVec3)
|
||||||
|
else
|
||||||
|
DCStask=CONTROLLABLE.TaskEscort(nil, FollowGroup, self.escortVec3, nil, self.engageMaxDistance, self.engageTargetTypes)
|
||||||
|
end
|
||||||
|
|
||||||
table.insert(DCStasks, DCStask)
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ do
|
|||||||
-- my_ctld.placeCratesAhead = false -- place crates straight ahead of the helicopter, in a random way. If true, crates are more neatly sorted.
|
-- my_ctld.placeCratesAhead = false -- place crates straight ahead of the helicopter, in a random way. If true, crates are more neatly sorted.
|
||||||
-- my_ctld.nobuildinloadzones = true -- forbid players to build stuff in LOAD zones if set to `true`
|
-- my_ctld.nobuildinloadzones = true -- forbid players to build stuff in LOAD zones if set to `true`
|
||||||
-- my_ctld.movecratesbeforebuild = true -- crates must be moved once before they can be build. Set to false for direct builds.
|
-- my_ctld.movecratesbeforebuild = true -- crates must be moved once before they can be build. Set to false for direct builds.
|
||||||
|
-- my_ctld.useaircraftheadingforbuilds = false -- Matches the heading of the spawned groups from a crate build to the aircraft heading when starting the build. Default is false for template heading.
|
||||||
-- my_ctld.surfacetypes = {land.SurfaceType.LAND,land.SurfaceType.ROAD,land.SurfaceType.RUNWAY,land.SurfaceType.SHALLOW_WATER} -- surfaces for loading back objects.
|
-- my_ctld.surfacetypes = {land.SurfaceType.LAND,land.SurfaceType.ROAD,land.SurfaceType.RUNWAY,land.SurfaceType.SHALLOW_WATER} -- surfaces for loading back objects.
|
||||||
-- my_ctld.nobuildmenu = false -- if set to true effectively enforces to have engineers build/repair stuff for you.
|
-- my_ctld.nobuildmenu = false -- if set to true effectively enforces to have engineers build/repair stuff for you.
|
||||||
-- my_ctld.RadioSound = "beacon.ogg" -- -- this sound will be hearable if you tune in the beacon frequency. Add the sound file to your miz.
|
-- my_ctld.RadioSound = "beacon.ogg" -- -- this sound will be hearable if you tune in the beacon frequency. Add the sound file to your miz.
|
||||||
@@ -2037,7 +2038,7 @@ function CTLD:_C130DcAutoRegisterEntry(SetId, Cargo)
|
|||||||
|
|
||||||
local pos = Cargo:GetPositionable()
|
local pos = Cargo:GetPositionable()
|
||||||
local pname = pos and pos.GetName and pos:GetName() or nil
|
local pname = pos and pos.GetName and pos:GetName() or nil
|
||||||
local pcoord = pos and pos.GetCoordinate and pos:GetCoordinate() or nil
|
local pcoord = pos and pos.GetCoord and pos:GetCoord() or nil
|
||||||
local entryId = string.format("%s#%d", SetId, #setData.entries + 1)
|
local entryId = string.format("%s#%d", SetId, #setData.entries + 1)
|
||||||
local entry = {
|
local entry = {
|
||||||
id = entryId,
|
id = entryId,
|
||||||
@@ -2748,16 +2749,14 @@ function CTLD:_EventHandler(EventData)
|
|||||||
loaded = self.Loaded_Cargo[unitname] -- #CTLD.LoadedCargo
|
loaded = self.Loaded_Cargo[unitname] -- #CTLD.LoadedCargo
|
||||||
loaded.Cratesloaded = loaded.Cratesloaded - 1
|
loaded.Cratesloaded = loaded.Cratesloaded - 1
|
||||||
if loaded.Cratesloaded < 0 then loaded.Cratesloaded = 0 end
|
if loaded.Cratesloaded < 0 then loaded.Cratesloaded = 0 end
|
||||||
-- TODO zap cargo from list
|
|
||||||
local Loaded = {}
|
local Loaded = {}
|
||||||
for _,_item in pairs (loaded.Cargo or {}) do
|
for _,_item in pairs (loaded.Cargo or {}) do
|
||||||
self:T(self.lid.."UNLOAD checking: ".._item:GetName())
|
self:T(self.lid.."UNLOAD checking: ".._item:GetName())
|
||||||
self:T(self.lid.."UNLOAD state: ".. tostring(_item:WasDropped()))
|
self:T(self.lid.."UNLOAD state: ".. tostring(_item:WasDropped()))
|
||||||
if _item and _item:GetType() == CTLD_CARGO.Enum.GCLOADABLE and event.IniDynamicCargoName and event.IniDynamicCargoName ~= _item:GetName() and not _item:WasDropped() then
|
local unloadedItem = _item and _item:GetType() == CTLD_CARGO.Enum.GCLOADABLE and event.IniDynamicCargoName and event.IniDynamicCargoName == _item:GetName()
|
||||||
|
if not unloadedItem then
|
||||||
table.insert(Loaded,_item)
|
table.insert(Loaded,_item)
|
||||||
else
|
end
|
||||||
table.insert(Loaded,_item)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
loaded.Cargo = nil
|
loaded.Cargo = nil
|
||||||
loaded.Cargo = Loaded
|
loaded.Cargo = Loaded
|
||||||
@@ -3125,14 +3124,14 @@ end
|
|||||||
function CTLD:_FindRepairNearby(Group, Unit, Repairtype)
|
function CTLD:_FindRepairNearby(Group, Unit, Repairtype)
|
||||||
self:T(self.lid .. " _FindRepairNearby")
|
self:T(self.lid .. " _FindRepairNearby")
|
||||||
--self:T({Group:GetName(),Unit:GetName(),Repairtype})
|
--self:T({Group:GetName(),Unit:GetName(),Repairtype})
|
||||||
local unitcoord = Unit:GetCoordinate()
|
local unitcoord = Unit:GetCoord()
|
||||||
|
|
||||||
-- find nearest group of deployed groups
|
-- find nearest group of deployed groups
|
||||||
local nearestGroup = nil
|
local nearestGroup = nil
|
||||||
local nearestGroupIndex = -1
|
local nearestGroupIndex = -1
|
||||||
local nearestDistance = 10000
|
local nearestDistance = 10000
|
||||||
for k,v in pairs(self.DroppedTroops) do
|
for k,v in pairs(self.DroppedTroops) do
|
||||||
local distance = self:_GetDistance(v:GetCoordinate(),unitcoord)
|
local distance = self:_GetDistance(v:GetCoord(),unitcoord)
|
||||||
local unit = v:GetUnit(1) -- Wrapper.Unit#UNIT
|
local unit = v:GetUnit(1) -- Wrapper.Unit#UNIT
|
||||||
local desc = unit:GetDesc() or nil
|
local desc = unit:GetDesc() or nil
|
||||||
if distance < nearestDistance and distance ~= -1 and not desc.attributes.Infantry then
|
if distance < nearestDistance and distance ~= -1 and not desc.attributes.Infantry then
|
||||||
@@ -3277,7 +3276,7 @@ end
|
|||||||
local capabilities = self:_GetUnitCapabilities(Unit)
|
local capabilities = self:_GetUnitCapabilities(Unit)
|
||||||
local cantroops = capabilities.troops -- #boolean
|
local cantroops = capabilities.troops -- #boolean
|
||||||
local trooplimit = capabilities.trooplimit -- #number
|
local trooplimit = capabilities.trooplimit -- #number
|
||||||
local unitcoord = unit:GetCoordinate()
|
local unitcoord = unit:GetCoord()
|
||||||
|
|
||||||
-- find nearest group of deployed troops
|
-- find nearest group of deployed troops
|
||||||
local nearestGroup = nil
|
local nearestGroup = nil
|
||||||
@@ -3288,7 +3287,7 @@ end
|
|||||||
local distancekeys = {}
|
local distancekeys = {}
|
||||||
local extractdistance = self.CrateDistance * self.ExtractFactor
|
local extractdistance = self.CrateDistance * self.ExtractFactor
|
||||||
for k,v in pairs(self.DroppedTroops) do
|
for k,v in pairs(self.DroppedTroops) do
|
||||||
local distance = self:_GetDistance(v:GetCoordinate(),unitcoord)
|
local distance = self:_GetDistance(v:GetCoord(),unitcoord)
|
||||||
local TNow = timer.getTime()
|
local TNow = timer.getTime()
|
||||||
local vtime = v.ExtractTime or TNow-310
|
local vtime = v.ExtractTime or TNow-310
|
||||||
if distance <= extractdistance and distance ~= -1 and (TNow - vtime > 300) then
|
if distance <= extractdistance and distance ~= -1 and (TNow - vtime > 300) then
|
||||||
@@ -3376,7 +3375,7 @@ end
|
|||||||
self:_UpdateUnitCargoMass(Unit)
|
self:_UpdateUnitCargoMass(Unit)
|
||||||
local groupname = nearestGroup:GetName()
|
local groupname = nearestGroup:GetName()
|
||||||
self:__TroopsExtracted(running,Group, Unit, nearestGroup, groupname)
|
self:__TroopsExtracted(running,Group, Unit, nearestGroup, groupname)
|
||||||
local coord = Unit:GetCoordinate() or Group:GetCoordinate() -- Core.Point#COORDINATE
|
local coord = Unit:GetCoord() or Group:GetCoord() -- Core.Point#COORDINATE
|
||||||
local Point
|
local Point
|
||||||
if coord then
|
if coord then
|
||||||
local heading = unit:GetHeading() or 0
|
local heading = unit:GetHeading() or 0
|
||||||
@@ -3747,16 +3746,16 @@ function CTLD:_C130GetUnits(Group, Unit, Name)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
local coord = Unit:GetCoordinate() or Group:GetCoordinate()
|
local coord = Unit:GetCoord() or Group:GetCoord()
|
||||||
local capabilities = self:_GetUnitCapabilities(Unit)
|
local capabilities = self:_GetUnitCapabilities(Unit)
|
||||||
local innerDist = (capabilities.length and capabilities.length/2) or 15
|
local innerDist = (capabilities.length and capabilities.length/2) or 15
|
||||||
local maxUnitsNearby = self.maxUnitsNearby or 3
|
local maxUnitsNearby = self.maxUnitsNearby or 3
|
||||||
local searchRadius = self.UnitDistance or 90
|
local searchRadius = self.UnitDistance or 90
|
||||||
local checkZone = ZONE_RADIUS:New("CTLD_C130UnitsZone",coord:GetVec2(),searchRadius,false)
|
local checkZone = ZONE_RADIUS:New("CTLD_C130UnitsZone",coord:GetVec2(),searchRadius,false)
|
||||||
local nearGroups = SET_GROUP:New():FilterCoalitions("blue"):FilterZones({checkZone}):FilterOnce()
|
local nearGroups = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterZones({checkZone}):FilterOnce()
|
||||||
local nearbyCount = 0
|
local nearbyCount = 0
|
||||||
for _,gr in pairs(nearGroups.Set) do
|
for _,gr in pairs(nearGroups.Set) do
|
||||||
local gc = gr:GetCoordinate()
|
local gc = gr:GetCoord()
|
||||||
if gc then
|
if gc then
|
||||||
local dist = coord:Get2DDistance(gc)
|
local dist = coord:Get2DDistance(gc)
|
||||||
if dist > innerDist then
|
if dist > innerDist then
|
||||||
@@ -3806,6 +3805,7 @@ function CTLD:_C130GetUnits(Group, Unit, Name)
|
|||||||
if canmove then
|
if canmove then
|
||||||
SPAWN:NewWithAlias(_template,alias)
|
SPAWN:NewWithAlias(_template,alias)
|
||||||
:InitRandomizeUnits(true,10,2)
|
:InitRandomizeUnits(true,10,2)
|
||||||
|
:InitCoalition(self.coalition)
|
||||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits, 70)
|
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits, 70)
|
||||||
:InitDelayOff()
|
:InitDelayOff()
|
||||||
:OnSpawnGroup(function(grp,TimeStamp)
|
:OnSpawnGroup(function(grp,TimeStamp)
|
||||||
@@ -3819,6 +3819,7 @@ function CTLD:_C130GetUnits(Group, Unit, Name)
|
|||||||
SPAWN:NewWithAlias(_template,alias)
|
SPAWN:NewWithAlias(_template,alias)
|
||||||
:InitRandomizeUnits(true,10,2)
|
:InitRandomizeUnits(true,10,2)
|
||||||
:InitDelayOff()
|
:InitDelayOff()
|
||||||
|
:InitCoalition(self.coalition)
|
||||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits, 70)
|
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits, 70)
|
||||||
:OnSpawnGroup(function(grp,TimeStamp)
|
:OnSpawnGroup(function(grp,TimeStamp)
|
||||||
grp.spawntime = TimeStamp or timer.getTime()
|
grp.spawntime = TimeStamp or timer.getTime()
|
||||||
@@ -3925,7 +3926,7 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack, quiet, suppress
|
|||||||
-- Check cargo location if available
|
-- Check cargo location if available
|
||||||
local location = Cargo:GetLocation()
|
local location = Cargo:GetLocation()
|
||||||
if location then
|
if location then
|
||||||
local unitcoord = Unit:GetCoordinate() or Group:GetCoordinate()
|
local unitcoord = Unit:GetCoord() or Group:GetCoord()
|
||||||
if unitcoord then
|
if unitcoord then
|
||||||
if not location:IsCoordinateInZone(unitcoord) then
|
if not location:IsCoordinateInZone(unitcoord) then
|
||||||
-- no we're not at the right spot
|
-- no we're not at the right spot
|
||||||
@@ -3972,7 +3973,7 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack, quiet, suppress
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- get position and heading of heli
|
-- get position and heading of heli
|
||||||
local position = Unit:GetCoordinate()
|
local position = Unit:GetCoord()
|
||||||
local heading = Unit:GetHeading() + 1
|
local heading = Unit:GetHeading() + 1
|
||||||
local height = Unit:GetHeight()
|
local height = Unit:GetHeight()
|
||||||
local droppedcargo = {}
|
local droppedcargo = {}
|
||||||
@@ -4136,8 +4137,8 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack, quiet, suppress
|
|||||||
if type(ship) == "string" then
|
if type(ship) == "string" then
|
||||||
self:T("Spawning on ship "..ship)
|
self:T("Spawning on ship "..ship)
|
||||||
local Ship = UNIT:FindByName(ship)
|
local Ship = UNIT:FindByName(ship)
|
||||||
local shipcoord = Ship:GetCoordinate()
|
local shipcoord = Ship:GetCoord()
|
||||||
local unitcoord = Unit:GetCoordinate()
|
local unitcoord = Unit:GetCoord()
|
||||||
local dist = shipcoord:Get2DDistance(unitcoord)
|
local dist = shipcoord:Get2DDistance(unitcoord)
|
||||||
dist = dist - (20 + math.random(1, 10))
|
dist = dist - (20 + math.random(1, 10))
|
||||||
local halfwidth = (width or 20) / 2
|
local halfwidth = (width or 20) / 2
|
||||||
@@ -4389,17 +4390,17 @@ end
|
|||||||
function CTLD:_C130RemoveUnitsNearby(_group,_unit)
|
function CTLD:_C130RemoveUnitsNearby(_group,_unit)
|
||||||
self:T(self.lid .. " _C130RemoveUnitsNearby")
|
self:T(self.lid .. " _C130RemoveUnitsNearby")
|
||||||
if not _group or not _unit then return self end
|
if not _group or not _unit then return self end
|
||||||
local location = _group:GetCoordinate()
|
local location = _group:GetCoord()
|
||||||
if not location then return self end
|
if not location then return self end
|
||||||
local capabilities = self:_GetUnitCapabilities(_unit)
|
local capabilities = self:_GetUnitCapabilities(_unit)
|
||||||
local innerDist = (capabilities.length and capabilities.length/2) or 15
|
local innerDist = (capabilities.length and capabilities.length/2) or 15
|
||||||
local finddist = self.PackDistance or (self.CrateDistance or 35)
|
local finddist = self.PackDistance or (self.CrateDistance or 35)
|
||||||
local zone = ZONE_RADIUS:New("CTLD_C130RemoveZone",location:GetVec2(),finddist,false)
|
local zone = ZONE_RADIUS:New("CTLD_C130RemoveZone",location:GetVec2(),finddist,false)
|
||||||
local nearestGroups = SET_GROUP:New():FilterCoalitions("blue"):FilterZones({zone}):FilterOnce()
|
local nearestGroups = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterZones({zone}):FilterOnce()
|
||||||
local removedAny = false
|
local removedAny = false
|
||||||
local removedTable = {}
|
local removedTable = {}
|
||||||
for _, gr in pairs(nearestGroups.Set) do
|
for _, gr in pairs(nearestGroups.Set) do
|
||||||
local gc = gr:GetCoordinate()
|
local gc = gr:GetCoord()
|
||||||
if gc then
|
if gc then
|
||||||
local dist = location:Get2DDistance(gc)
|
local dist = location:Get2DDistance(gc)
|
||||||
if dist > innerDist then
|
if dist > innerDist then
|
||||||
@@ -4533,7 +4534,7 @@ end
|
|||||||
function CTLD:_FindCratesNearby( _group, _unit, _dist, _ignoreweight, ignoretype, ignoreHercInner)
|
function CTLD:_FindCratesNearby( _group, _unit, _dist, _ignoreweight, ignoretype, ignoreHercInner)
|
||||||
self:T(self.lid .. " _FindCratesNearby")
|
self:T(self.lid .. " _FindCratesNearby")
|
||||||
local finddist = _dist
|
local finddist = _dist
|
||||||
local location = _group:GetCoordinate()
|
local location = _group:GetCoord()
|
||||||
local existingcrates = self.Spawned_Cargo -- #table
|
local existingcrates = self.Spawned_Cargo -- #table
|
||||||
-- cycle
|
-- cycle
|
||||||
local index = 0
|
local index = 0
|
||||||
@@ -5159,7 +5160,6 @@ function CTLD:_UnloadTroops(Group, Unit)
|
|||||||
-- unload troops
|
-- unload troops
|
||||||
local name = cargo:GetName() or "none"
|
local name = cargo:GetName() or "none"
|
||||||
local temptable = cargo:GetTemplates() or {}
|
local temptable = cargo:GetTemplates() or {}
|
||||||
local position = Group:GetCoordinate()
|
|
||||||
local zoneradius = self.troopdropzoneradius or 100 -- drop zone radius
|
local zoneradius = self.troopdropzoneradius or 100 -- drop zone radius
|
||||||
local factor = 1
|
local factor = 1
|
||||||
if IsHerc then
|
if IsHerc then
|
||||||
@@ -5196,6 +5196,7 @@ function CTLD:_UnloadTroops(Group, Unit)
|
|||||||
local Positions = self:_GetUnitPositions(randomcoord,rad,heading,_template)
|
local Positions = self:_GetUnitPositions(randomcoord,rad,heading,_template)
|
||||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
||||||
:InitDelayOff()
|
:InitDelayOff()
|
||||||
|
:InitCoalition(self.coalition)
|
||||||
:InitSetUnitAbsolutePositions(Positions)
|
:InitSetUnitAbsolutePositions(Positions)
|
||||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
||||||
:OnSpawnGroup(function(grp) grp.spawntime = timer.getTime() end)
|
:OnSpawnGroup(function(grp) grp.spawntime = timer.getTime() end)
|
||||||
@@ -5506,8 +5507,8 @@ function CTLD:_BuildCrates(Group, Unit,Engineering,MultiDrop,NotifyGroup)
|
|||||||
local required = Crate:GetCratesNeeded()
|
local required = Crate:GetCratesNeeded()
|
||||||
local template = Crate:GetTemplates()
|
local template = Crate:GetTemplates()
|
||||||
local ctype = Crate:GetType()
|
local ctype = Crate:GetType()
|
||||||
local ccoord = Crate:GetPositionable():GetCoordinate() -- Core.Point#COORDINATE
|
local ccoord = Crate:GetPositionable():GetCoord() -- Core.Point#COORDINATE
|
||||||
local distToUnit=Unit and ccoord:Get2DDistance(Unit:GetCoordinate())or 0
|
local distToUnit=Unit and ccoord:Get2DDistance(Unit:GetCoord())or 0
|
||||||
local isHercDrop=Crate:WasDropped(true)
|
local isHercDrop=Crate:WasDropped(true)
|
||||||
if not isHercDrop and distToUnit>baseDist then
|
if not isHercDrop and distToUnit>baseDist then
|
||||||
elseif self:IsC130J(Unit) and distToUnit<15 then
|
elseif self:IsC130J(Unit) and distToUnit<15 then
|
||||||
@@ -5526,6 +5527,7 @@ function CTLD:_BuildCrates(Group, Unit,Engineering,MultiDrop,NotifyGroup)
|
|||||||
object.Found = 1
|
object.Found = 1
|
||||||
object.Template = template
|
object.Template = template
|
||||||
object.CanBuild = false
|
object.CanBuild = false
|
||||||
|
object.Heading = Unit:GetHeading()
|
||||||
object.Type = ctype -- #CTLD_CARGO.Enum
|
object.Type = ctype -- #CTLD_CARGO.Enum
|
||||||
object.Coord = ccoord:GetVec2()
|
object.Coord = ccoord:GetVec2()
|
||||||
buildables[name] = object
|
buildables[name] = object
|
||||||
@@ -5611,7 +5613,7 @@ function CTLD:_BuildCrates(Group, Unit,Engineering,MultiDrop,NotifyGroup)
|
|||||||
local sep = self.buildPairSeparation or 25
|
local sep = self.buildPairSeparation or 25
|
||||||
local hdg = (Unit:GetHeading()+180)%360
|
local hdg = (Unit:GetHeading()+180)%360
|
||||||
local lat = (hdg+90)%360
|
local lat = (hdg+90)%360
|
||||||
local base = Unit:GetCoordinate():Translate(20,hdg)
|
local base = Unit:GetCoord():Translate(20,hdg)
|
||||||
|
|
||||||
if full == 1 then
|
if full == 1 then
|
||||||
local cratesNow, numberNow = self:_FindCratesNearby(Group,Unit, finddist,true,true, not Engineering)
|
local cratesNow, numberNow = self:_FindCratesNearby(Group,Unit, finddist,true,true, not Engineering)
|
||||||
@@ -5645,7 +5647,7 @@ function CTLD:_BuildCrates(Group, Unit,Engineering,MultiDrop,NotifyGroup)
|
|||||||
self:_RefreshPackMenus(Group,Unit)
|
self:_RefreshPackMenus(Group,Unit)
|
||||||
local off = start + (n-1)*sep
|
local off = start + (n-1)*sep
|
||||||
local coord = base:Translate(off,lat):GetVec2()
|
local coord = base:Translate(off,lat):GetVec2()
|
||||||
local b = { Name=build.Name, Required=build.Required, Template=build.Template, CanBuild=true, Type=build.Type, Coord=coord }
|
local b = { Name=build.Name, Required=build.Required, Template=build.Template, CanBuild=true, Type=build.Type, Coord=coord, Heading=build.Heading }
|
||||||
if self.buildtime and self.buildtime > 0 then
|
if self.buildtime and self.buildtime > 0 then
|
||||||
local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,b,false,Group:GetCoordinate(),MultiDrop)
|
local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,b,false,Group:GetCoordinate(),MultiDrop)
|
||||||
buildtimer:Start(self.buildtime)
|
buildtimer:Start(self.buildtime)
|
||||||
@@ -5683,18 +5685,18 @@ end
|
|||||||
-- @return #number Number
|
-- @return #number Number
|
||||||
function CTLD:_FindPackableGroupsNearby(Group, Unit)
|
function CTLD:_FindPackableGroupsNearby(Group, Unit)
|
||||||
self:T(self.lid .. " _FindPackableGroupsNearby")
|
self:T(self.lid .. " _FindPackableGroupsNearby")
|
||||||
local location = Group:GetCoordinate()
|
local location = Group:GetCoord()
|
||||||
if not location then return {}, 0 end
|
if not location then return {}, 0 end
|
||||||
local capabilities = self:_GetUnitCapabilities(Unit)
|
local capabilities = self:_GetUnitCapabilities(Unit)
|
||||||
local innerDist = (capabilities.length and capabilities.length/2) or 15
|
local innerDist = (capabilities.length and capabilities.length/2) or 15
|
||||||
local finddist = self.PackDistance or (self.CrateDistance or 35)
|
local finddist = self.PackDistance or (self.CrateDistance or 35)
|
||||||
local zone = ZONE_RADIUS:New("CTLD_PackableZone", location:GetVec2(), finddist, false)
|
local zone = ZONE_RADIUS:New("CTLD_PackableZone", location:GetVec2(), finddist, false)
|
||||||
local nearestGroups = SET_GROUP:New():FilterCoalitions("blue"):FilterZones({zone}):FilterOnce()
|
local nearestGroups = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterZones({zone}):FilterOnce()
|
||||||
local packable = {}
|
local packable = {}
|
||||||
|
|
||||||
for _, gr in pairs(nearestGroups.Set) do
|
for _, gr in pairs(nearestGroups.Set) do
|
||||||
if gr and gr:GetName() ~= Group:GetName() then
|
if gr and gr:GetName() ~= Group:GetName() then
|
||||||
local gc = gr:GetCoordinate()
|
local gc = gr:GetCoord()
|
||||||
if gc then
|
if gc then
|
||||||
local dist = location:Get2DDistance(gc)
|
local dist = location:Get2DDistance(gc)
|
||||||
if dist > innerDist and dist <= finddist then
|
if dist > innerDist and dist <= finddist then
|
||||||
@@ -5827,12 +5829,12 @@ function CTLD:_LoadPackedCratesByIds(Group, Unit, crateIds, cargoName)
|
|||||||
|
|
||||||
local matchingCrates = {}
|
local matchingCrates = {}
|
||||||
local finddist = self.CrateDistance or 35
|
local finddist = self.CrateDistance or 35
|
||||||
local location = Group:GetCoordinate()
|
local location = Group:GetCoord()
|
||||||
for _, crateObj in pairs(self.Spawned_Cargo or {}) do
|
for _, crateObj in pairs(self.Spawned_Cargo or {}) do
|
||||||
if crateObj and idLookup[crateObj:GetID()] then
|
if crateObj and idLookup[crateObj:GetID()] then
|
||||||
local pos = crateObj:GetPositionable()
|
local pos = crateObj:GetPositionable()
|
||||||
if pos and pos:IsAlive() then
|
if pos and pos:IsAlive() then
|
||||||
local dist = location:Get2DDistance(pos:GetCoordinate())
|
local dist = location:Get2DDistance(pos:GetCoord())
|
||||||
if dist <= finddist then
|
if dist <= finddist then
|
||||||
matchingCrates[#matchingCrates + 1] = crateObj
|
matchingCrates[#matchingCrates + 1] = crateObj
|
||||||
end
|
end
|
||||||
@@ -5942,12 +5944,12 @@ function CTLD:_RemovePackedCratesByIds(Group, Unit, crateIds)
|
|||||||
|
|
||||||
local crates = {}
|
local crates = {}
|
||||||
local finddist = self.CrateDistance or 35
|
local finddist = self.CrateDistance or 35
|
||||||
local location = Group:GetCoordinate()
|
local location = Group:GetCoord()
|
||||||
for _, entry in pairs(self.Spawned_Cargo or {}) do
|
for _, entry in pairs(self.Spawned_Cargo or {}) do
|
||||||
if entry and idLookup[entry:GetID()] then
|
if entry and idLookup[entry:GetID()] then
|
||||||
local pos = entry:GetPositionable()
|
local pos = entry:GetPositionable()
|
||||||
if pos and pos:IsAlive() then
|
if pos and pos:IsAlive() then
|
||||||
local dist = location:Get2DDistance(pos:GetCoordinate())
|
local dist = location:Get2DDistance(pos:GetCoord())
|
||||||
if dist <= finddist then
|
if dist <= finddist then
|
||||||
crates[#crates + 1] = entry
|
crates[#crates + 1] = entry
|
||||||
end
|
end
|
||||||
@@ -6171,11 +6173,11 @@ function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation,Mult
|
|||||||
local ctype = Build.Type -- #CTLD_CARGO.Enum
|
local ctype = Build.Type -- #CTLD_CARGO.Enum
|
||||||
local canmove = false
|
local canmove = false
|
||||||
if ctype == CTLD_CARGO.Enum.VEHICLE then canmove = true end
|
if ctype == CTLD_CARGO.Enum.VEHICLE then canmove = true end
|
||||||
if ctype == CTLD_CARGO.Enum.STATIC then
|
if ctype == CTLD_CARGO.Enum.STATIC then
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
local temptable = Build.Template or {}
|
local temptable = Build.Template or {}
|
||||||
if type(temptable) == "string" then
|
if type(temptable) == "string" then
|
||||||
temptable = {temptable}
|
temptable = {temptable}
|
||||||
end
|
end
|
||||||
local zone = nil -- Core.Zone#ZONE_RADIUS
|
local zone = nil -- Core.Zone#ZONE_RADIUS
|
||||||
@@ -6197,28 +6199,31 @@ function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation,Mult
|
|||||||
for _,_template in pairs(temptable) do
|
for _,_template in pairs(temptable) do
|
||||||
self.TroopCounter = self.TroopCounter + 1
|
self.TroopCounter = self.TroopCounter + 1
|
||||||
local alias = string.format("%s-%d", _template, math.random(1,100000))
|
local alias = string.format("%s-%d", _template, math.random(1,100000))
|
||||||
|
local spawn = SPAWN:NewWithAlias(_template,alias)
|
||||||
|
:InitDelayOff()
|
||||||
|
:InitCoalition(self.coalition)
|
||||||
|
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
||||||
|
:OnSpawnGroup(function(grp) grp.spawntime = timer.getTime() end)
|
||||||
if canmove then
|
if canmove then
|
||||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
--spawn:InitRandomizeUnits(true,20,2)
|
||||||
--:InitRandomizeUnits(true,20,2)
|
|
||||||
:InitDelayOff()
|
|
||||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
|
||||||
:OnSpawnGroup(function(grp) grp.spawntime = timer.getTime() end)
|
|
||||||
:SpawnFromVec2(randomcoord)
|
|
||||||
else -- don't random position of e.g. SAM units build as FOB
|
|
||||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
|
||||||
:InitDelayOff()
|
|
||||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
|
||||||
:OnSpawnGroup(function(grp) grp.spawntime = timer.getTime() end)
|
|
||||||
:SpawnFromVec2(randomcoord)
|
|
||||||
end
|
end
|
||||||
|
if Build.Heading and self.buildcrateswithaircraftheading then
|
||||||
|
spawn:InitGroupHeading(Build.Heading)
|
||||||
|
end
|
||||||
|
local spawnedGroup = spawn:SpawnFromVec2(randomcoord)
|
||||||
|
self.DroppedTroops[self.TroopCounter] = spawnedGroup
|
||||||
|
|
||||||
if Repair then
|
if Repair then
|
||||||
self:__CratesRepaired(1,Group,Unit,self.DroppedTroops[self.TroopCounter])
|
self:__CratesRepaired(1,Group,Unit,spawnedGroup)
|
||||||
else
|
else
|
||||||
self:__CratesBuild(1,Group,Unit,self.DroppedTroops[self.TroopCounter])
|
self:__CratesBuild(1,Group,Unit,spawnedGroup)
|
||||||
end
|
end
|
||||||
end -- template loop
|
end -- template loop
|
||||||
self:_RefreshLoadCratesMenu(Group, Unit)
|
|
||||||
self:_RefreshPackMenus(Group, Unit)
|
if Group and Group:IsAlive() and Group:GetID() then
|
||||||
|
self:_RefreshLoadCratesMenu(Group, Unit)
|
||||||
|
self:_RefreshPackMenus(Group, Unit)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
self:T(self.lid.."Group KIA while building!")
|
self:T(self.lid.."Group KIA while building!")
|
||||||
end
|
end
|
||||||
@@ -6241,14 +6246,11 @@ end
|
|||||||
-- @param Wrapper.Group#GROUP Group The Group to move.
|
-- @param Wrapper.Group#GROUP Group The Group to move.
|
||||||
function CTLD:_MoveGroupToZone(Group)
|
function CTLD:_MoveGroupToZone(Group)
|
||||||
self:T(self.lid .. " _MoveGroupToZone")
|
self:T(self.lid .. " _MoveGroupToZone")
|
||||||
local groupname = Group:GetName() or "none"
|
|
||||||
local groupcoord = Group:GetCoordinate()
|
|
||||||
-- Get closest zone of type
|
-- Get closest zone of type
|
||||||
local outcome, name, zone, distance = self:IsUnitInZone(Group,CTLD.CargoZoneType.MOVE)
|
local outcome, name, zone, distance = self:IsUnitInZone(Group,CTLD.CargoZoneType.MOVE)
|
||||||
self:T({canmove=outcome, name=name, zone=zone, dist=distance,max=self.movetroopsdistance})
|
self:T({canmove=outcome, name=name, zone=zone, dist=distance,max=self.movetroopsdistance})
|
||||||
if (distance <= self.movetroopsdistance) and outcome == true and zone~= nil then
|
if (distance <= self.movetroopsdistance) and outcome == true and zone~= nil then
|
||||||
-- yes, we can ;)
|
-- yes, we can ;)
|
||||||
local groupname = Group:GetName()
|
|
||||||
local zonecoord = zone:GetRandomCoordinate(20,125) -- Core.Point#COORDINATE
|
local zonecoord = zone:GetRandomCoordinate(20,125) -- Core.Point#COORDINATE
|
||||||
local formation = self:_GetVehicleFormation()
|
local formation = self:_GetVehicleFormation()
|
||||||
--local coordinate = zonecoord:GetVec2()
|
--local coordinate = zonecoord:GetVec2()
|
||||||
@@ -7931,6 +7933,7 @@ function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID, qty)
|
|||||||
local Positions = self:_GetUnitPositions(randomcoord, rad, heading, _template)
|
local Positions = self:_GetUnitPositions(randomcoord, rad, heading, _template)
|
||||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template, alias)
|
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template, alias)
|
||||||
:InitDelayOff()
|
:InitDelayOff()
|
||||||
|
:InitCoalition(self.coalition)
|
||||||
:InitSetUnitAbsolutePositions(Positions)
|
:InitSetUnitAbsolutePositions(Positions)
|
||||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
||||||
:OnSpawnGroup(function(grp) grp.spawntime = timer.getTime() end)
|
:OnSpawnGroup(function(grp) grp.spawntime = timer.getTime() end)
|
||||||
@@ -9008,7 +9011,7 @@ function CTLD:IsUnitInZone(Unit,Zonetype)
|
|||||||
local zoneret = nil
|
local zoneret = nil
|
||||||
local zonewret = nil
|
local zonewret = nil
|
||||||
local zonenameret = nil
|
local zonenameret = nil
|
||||||
local unitcoord = Unit:GetCoordinate()
|
local unitcoord = Unit:GetCoord()
|
||||||
if not unitcoord then
|
if not unitcoord then
|
||||||
if Zonetype == CTLD.CargoZoneType.SHIP then
|
if Zonetype == CTLD.CargoZoneType.SHIP then
|
||||||
return false, nil, nil, 1000000, nil
|
return false, nil, nil, 1000000, nil
|
||||||
@@ -9029,7 +9032,7 @@ function CTLD:IsUnitInZone(Unit,Zonetype)
|
|||||||
self:T("Checking Type Ship: "..zonename)
|
self:T("Checking Type Ship: "..zonename)
|
||||||
local ZoneUNIT = UNIT:FindByName(zonename)
|
local ZoneUNIT = UNIT:FindByName(zonename)
|
||||||
if not ZoneUNIT then return false end
|
if not ZoneUNIT then return false end
|
||||||
zonecoord = ZoneUNIT:GetCoordinate()
|
zonecoord = ZoneUNIT:GetCoord()
|
||||||
zoneradius = czone.shiplength
|
zoneradius = czone.shiplength
|
||||||
zonewidth = czone.shipwidth
|
zonewidth = czone.shipwidth
|
||||||
zone = ZONE_UNIT:New( ZoneUNIT:GetName(), ZoneUNIT, zoneradius/2)
|
zone = ZONE_UNIT:New( ZoneUNIT:GetName(), ZoneUNIT, zoneradius/2)
|
||||||
@@ -9078,7 +9081,7 @@ function CTLD:SmokePositionNow(Unit, Flare, SmokeColor)
|
|||||||
end
|
end
|
||||||
local FlareColor = self.FlareColor or FLARECOLOR.Red
|
local FlareColor = self.FlareColor or FLARECOLOR.Red
|
||||||
-- table of #CTLD.CargoZone table
|
-- table of #CTLD.CargoZone table
|
||||||
local unitcoord = Unit:GetCoordinate() -- Core.Point#COORDINATE
|
local unitcoord = Unit:GetCoord() -- Core.Point#COORDINATE
|
||||||
local Group = Unit:GetGroup()
|
local Group = Unit:GetGroup()
|
||||||
if Flare then
|
if Flare then
|
||||||
unitcoord:Flare(FlareColor, 90)
|
unitcoord:Flare(FlareColor, 90)
|
||||||
@@ -9097,7 +9100,7 @@ end
|
|||||||
function CTLD:SmokeZoneNearBy(Unit, Flare)
|
function CTLD:SmokeZoneNearBy(Unit, Flare)
|
||||||
self:T(self.lid .. " SmokeZoneNearBy")
|
self:T(self.lid .. " SmokeZoneNearBy")
|
||||||
-- table of #CTLD.CargoZone table
|
-- table of #CTLD.CargoZone table
|
||||||
local unitcoord = Unit:GetCoordinate()
|
local unitcoord = Unit:GetCoord()
|
||||||
local Group = Unit:GetGroup()
|
local Group = Unit:GetGroup()
|
||||||
local smokedistance = self.smokedistance
|
local smokedistance = self.smokedistance
|
||||||
local smoked = false
|
local smoked = false
|
||||||
@@ -9234,7 +9237,7 @@ end
|
|||||||
-- get speed and height
|
-- get speed and height
|
||||||
local uspeed = Unit:GetVelocityMPS()
|
local uspeed = Unit:GetVelocityMPS()
|
||||||
local uheight = Unit:GetHeight()
|
local uheight = Unit:GetHeight()
|
||||||
local ucoord = Unit:GetCoordinate()
|
local ucoord = Unit:GetCoord()
|
||||||
if not ucoord then
|
if not ucoord then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@@ -9263,7 +9266,7 @@ end
|
|||||||
-- get speed and height
|
-- get speed and height
|
||||||
local uspeed = Unit:GetVelocityMPS()
|
local uspeed = Unit:GetVelocityMPS()
|
||||||
local uheight = Unit:GetHeight()
|
local uheight = Unit:GetHeight()
|
||||||
local ucoord = Unit:GetCoordinate()
|
local ucoord = Unit:GetCoord()
|
||||||
if not ucoord then
|
if not ucoord then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@@ -9355,7 +9358,7 @@ end
|
|||||||
minheight = 5.1 -- herc is 5m AGL on the ground
|
minheight = 5.1 -- herc is 5m AGL on the ground
|
||||||
end
|
end
|
||||||
local uheight = Unit:GetHeight()
|
local uheight = Unit:GetHeight()
|
||||||
local ucoord = Unit:GetCoordinate()
|
local ucoord = Unit:GetCoord()
|
||||||
if not ucoord then
|
if not ucoord then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@@ -10141,6 +10144,7 @@ end
|
|||||||
local alias = string.format("%s-%d", _template, math.random(1,100000))
|
local alias = string.format("%s-%d", _template, math.random(1,100000))
|
||||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
||||||
:InitRandomizeUnits(randompositions,20,2)
|
:InitRandomizeUnits(randompositions,20,2)
|
||||||
|
:InitCoalition(self.coalition)
|
||||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
||||||
:InitDelayOff()
|
:InitDelayOff()
|
||||||
:OnSpawnGroup(function(grp,TimeStamp) grp.spawntime = TimeStamp or timer.getTime() end,TimeStamp)
|
:OnSpawnGroup(function(grp,TimeStamp) grp.spawntime = TimeStamp or timer.getTime() end,TimeStamp)
|
||||||
@@ -10295,6 +10299,7 @@ end
|
|||||||
if canmove then
|
if canmove then
|
||||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
||||||
:InitRandomizeUnits(true,20,2)
|
:InitRandomizeUnits(true,20,2)
|
||||||
|
:InitCoalition(self.coalition)
|
||||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
||||||
:InitDelayOff()
|
:InitDelayOff()
|
||||||
:OnSpawnGroup(function(grp,TimeStamp) grp.spawntime = TimeStamp or timer.getTime() end,TimeStamp)
|
:OnSpawnGroup(function(grp,TimeStamp) grp.spawntime = TimeStamp or timer.getTime() end,TimeStamp)
|
||||||
@@ -10302,6 +10307,7 @@ end
|
|||||||
else -- don't random position of e.g. SAM units build as FOB
|
else -- don't random position of e.g. SAM units build as FOB
|
||||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
||||||
:InitDelayOff()
|
:InitDelayOff()
|
||||||
|
:InitCoalition(self.coalition)
|
||||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
||||||
:OnSpawnGroup(function(grp,TimeStamp) grp.spawntime = TimeStamp or timer.getTime() end,TimeStamp)
|
:OnSpawnGroup(function(grp,TimeStamp) grp.spawntime = TimeStamp or timer.getTime() end,TimeStamp)
|
||||||
:SpawnFromVec2(randomcoord)
|
:SpawnFromVec2(randomcoord)
|
||||||
@@ -10583,7 +10589,7 @@ end
|
|||||||
self:T({From, Event, To})
|
self:T({From, Event, To})
|
||||||
if Unit and Unit:IsPlayer() and self.PlayerTaskQueue then
|
if Unit and Unit:IsPlayer() and self.PlayerTaskQueue then
|
||||||
local playername = Unit:GetPlayerName()
|
local playername = Unit:GetPlayerName()
|
||||||
local dropcoord = Troops:GetCoordinate() or COORDINATE:New(0,0,0)
|
local dropcoord = Troops:GetCoord() or COORDINATE:New(0,0,0)
|
||||||
local dropvec2 = dropcoord:GetVec2()
|
local dropvec2 = dropcoord:GetVec2()
|
||||||
self.PlayerTaskQueue:ForEach(
|
self.PlayerTaskQueue:ForEach(
|
||||||
function (Task)
|
function (Task)
|
||||||
@@ -10640,7 +10646,7 @@ end
|
|||||||
for _,_cargo in pairs(Cargotable) do
|
for _,_cargo in pairs(Cargotable) do
|
||||||
local Vehicle = _cargo.Positionable
|
local Vehicle = _cargo.Positionable
|
||||||
if Vehicle then
|
if Vehicle then
|
||||||
local dropcoord = Vehicle:GetCoordinate() or COORDINATE:New(0,0,0)
|
local dropcoord = Vehicle:GetCoord() or COORDINATE:New(0,0,0)
|
||||||
local dropvec2 = dropcoord:GetVec2()
|
local dropvec2 = dropcoord:GetVec2()
|
||||||
self.PlayerTaskQueue:ForEach(
|
self.PlayerTaskQueue:ForEach(
|
||||||
function (Task)
|
function (Task)
|
||||||
@@ -10705,7 +10711,7 @@ end
|
|||||||
self:T({From, Event, To})
|
self:T({From, Event, To})
|
||||||
if Unit and Unit:IsPlayer() and self.PlayerTaskQueue then
|
if Unit and Unit:IsPlayer() and self.PlayerTaskQueue then
|
||||||
local playername = Unit:GetPlayerName()
|
local playername = Unit:GetPlayerName()
|
||||||
local dropcoord = Vehicle:GetCoordinate() or COORDINATE:New(0,0,0)
|
local dropcoord = Vehicle:GetCoord() or COORDINATE:New(0,0,0)
|
||||||
local dropvec2 = dropcoord:GetVec2()
|
local dropvec2 = dropcoord:GetVec2()
|
||||||
self.PlayerTaskQueue:ForEach(
|
self.PlayerTaskQueue:ForEach(
|
||||||
function (Task)
|
function (Task)
|
||||||
|
|||||||
@@ -191,9 +191,10 @@
|
|||||||
-- * @{#EASYGCICAP.SetDefaultResurrection}: Set how many seconds the AirWing stays inoperable after the AirWing STATIC HQ ist destroyed, default 900 secs.
|
-- * @{#EASYGCICAP.SetDefaultResurrection}: Set how many seconds the AirWing stays inoperable after the AirWing STATIC HQ ist destroyed, default 900 secs.
|
||||||
-- * @{#EASYGCICAP.SetDefaultCAPSpeed}: Set how many knots the CAP flights should do (will be altitude corrected), default 300 kn.
|
-- * @{#EASYGCICAP.SetDefaultCAPSpeed}: Set how many knots the CAP flights should do (will be altitude corrected), default 300 kn.
|
||||||
-- * @{#EASYGCICAP.SetDefaultCAPAlt}: Set at which altitude (ASL) the CAP planes will fly, default 25,000 ft.
|
-- * @{#EASYGCICAP.SetDefaultCAPAlt}: Set at which altitude (ASL) the CAP planes will fly, default 25,000 ft.
|
||||||
|
-- * @{#EASYGCICAP.SetDefaultINTERCEPTAlt}: Set at which altitude (ASL) the Intercept planes will fly, default 25,000 ft.
|
||||||
-- * @{#EASYGCICAP.SetDefaultCAPDirection}: Set the initial direction from the CAP point the planes will fly in degrees, default is 90°.
|
-- * @{#EASYGCICAP.SetDefaultCAPDirection}: Set the initial direction from the CAP point the planes will fly in degrees, default is 90°.
|
||||||
-- * @{#EASYGCICAP.SetDefaultCAPLeg}: Set the length of the CAP leg, default is 15 NM.
|
-- * @{#EASYGCICAP.SetDefaultCAPLeg}: Set the length of the CAP leg, default is 15 NM.
|
||||||
-- * @{#EASYGCICAP.SetDefaultCAPGrouping}: Set how many planes will be spawned per mission (CVAP/GCI), defaults to 2.
|
-- * @{#EASYGCICAP.SetDefaultCAPGrouping}: Set how many planes will be spawned per mission (CAP/GCI), defaults to 2.
|
||||||
-- * @{#EASYGCICAP.SetDefaultMissionRange}: Set how many NM the planes can go from the home base, defaults to 100.
|
-- * @{#EASYGCICAP.SetDefaultMissionRange}: Set how many NM the planes can go from the home base, defaults to 100.
|
||||||
-- * @{#EASYGCICAP.SetDefaultNumberAlert5Standby}: Set how many planes will be spawned on cold standby (Alert5), default 2.
|
-- * @{#EASYGCICAP.SetDefaultNumberAlert5Standby}: Set how many planes will be spawned on cold standby (Alert5), default 2.
|
||||||
-- * @{#EASYGCICAP.SetDefaultEngageRange}: Set max engage range for CAP flights if they detect intruders, defaults to 50.
|
-- * @{#EASYGCICAP.SetDefaultEngageRange}: Set max engage range for CAP flights if they detect intruders, defaults to 50.
|
||||||
@@ -287,7 +288,7 @@ EASYGCICAP = {
|
|||||||
|
|
||||||
--- EASYGCICAP class version.
|
--- EASYGCICAP class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
EASYGCICAP.version="0.1.37"
|
EASYGCICAP.version="0.1.38"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
--
|
--
|
||||||
@@ -588,6 +589,17 @@ function EASYGCICAP:SetDefaultCAPAlt(Altitude)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set default INTERCEPT Altitude in feet
|
||||||
|
-- @param #EASYGCICAP self
|
||||||
|
-- @param #number Altitude (Optional) Altitude defaults to 25000
|
||||||
|
-- @return #EASYGCICAP self
|
||||||
|
function EASYGCICAP:SetDefaultINTERCEPTAlt(Altitude)
|
||||||
|
self:T(self.lid.."SetDefaultINTERCEPTAlt")
|
||||||
|
self.interceptalt = Altitude or 25000
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
--
|
||||||
|
|
||||||
--- Set default CAP lieg initial direction in degrees
|
--- Set default CAP lieg initial direction in degrees
|
||||||
-- @param #EASYGCICAP self
|
-- @param #EASYGCICAP self
|
||||||
-- @param #number Direction (Optional) Direction defaults to 90 (East)
|
-- @param #number Direction (Optional) Direction defaults to 90 (East)
|
||||||
@@ -1519,6 +1531,7 @@ function EASYGCICAP:_AssignIntercept(Cluster)
|
|||||||
local overhead = self.overhead
|
local overhead = self.overhead
|
||||||
local capspeed = self.capspeed + 100
|
local capspeed = self.capspeed + 100
|
||||||
local capalt = self.capalt
|
local capalt = self.capalt
|
||||||
|
local interalt = self.interceptalt or self.capalt
|
||||||
local maxsize = self.maxinterceptsize
|
local maxsize = self.maxinterceptsize
|
||||||
local repeatsonfailure = self.repeatsonfailure
|
local repeatsonfailure = self.repeatsonfailure
|
||||||
|
|
||||||
@@ -1606,6 +1619,7 @@ function EASYGCICAP:_AssignIntercept(Cluster)
|
|||||||
:SetRepeatOnFailure(repeats)
|
:SetRepeatOnFailure(repeats)
|
||||||
:SetMissionSpeed(UTILS.KnotsToAltKIAS(capspeed,capalt))
|
:SetMissionSpeed(UTILS.KnotsToAltKIAS(capspeed,capalt))
|
||||||
:SetMissionAltitude(capalt)
|
:SetMissionAltitude(capalt)
|
||||||
|
:SetEngageAltitude(interalt)
|
||||||
|
|
||||||
if nogozoneset:Count() > 0 then
|
if nogozoneset:Count() > 0 then
|
||||||
InterceptAuftrag:AddConditionSuccess(
|
InterceptAuftrag:AddConditionSuccess(
|
||||||
|
|||||||
@@ -2661,7 +2661,7 @@ function LEGION._CohortCan(Cohort, MissionType, Categories, Attributes, Properti
|
|||||||
local RangeMax = RangeMax or 0
|
local RangeMax = RangeMax or 0
|
||||||
local InRange=(RangeMax and math.max(RangeMax, Rmax) or Rmax) >= TargetDistance and TargetDistance > RangeMin
|
local InRange=(RangeMax and math.max(RangeMax, Rmax) or Rmax) >= TargetDistance and TargetDistance > RangeMin
|
||||||
|
|
||||||
--env.info(string.format("Range TargetDist=%.1f Rmax=%.1f RangeMax=%.1f InRange=%s RangeMin=%s", TargetDistance, Rmax, RangeMax, tostring(InRange),tostring(RangeMin)))
|
--env.info(string.format("Range TargetDist=%.1f Rmax=%.1f RangeMax=%.1f InRange=%s", TargetDistance, Rmax, RangeMax, tostring(InRange)))
|
||||||
|
|
||||||
return InRange
|
return InRange
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -131,14 +131,24 @@ ENUMS.WeaponFlag={
|
|||||||
Cannons = 805306368, -- GUN_POD + BuiltInCannon
|
Cannons = 805306368, -- GUN_POD + BuiltInCannon
|
||||||
--- Torpedo
|
--- Torpedo
|
||||||
Torpedo = 4294967296,
|
Torpedo = 4294967296,
|
||||||
|
--- Decoy
|
||||||
|
Decoys = 8589934592,
|
||||||
|
--- Shell
|
||||||
|
SmokeShell = 17179869184,
|
||||||
|
IlluminationShell = 34359738368,
|
||||||
|
MarkerShell = 51539607552,
|
||||||
|
MarkerWeapon = 51539620864,
|
||||||
|
SubmunitionDispenserShell = 68719476736,
|
||||||
|
ConventionalShell = 206963736576,
|
||||||
---
|
---
|
||||||
-- Even More Genral
|
-- Even More Genral
|
||||||
Auto = 3221225470, -- Any Weapon (AnyBomb + AnyRocket + AnyMissile + Cannons)
|
Auto = 265214230526, -- Any Weapon (AnyBomb + AnyRocket + AnyMissile + Cannons + Torpedos)
|
||||||
AutoDCS = 1073741822, -- Something if often see
|
AutoDCS = 1073741822, -- Something if often see
|
||||||
AnyAG = 2956984318, -- Any Air-To-Ground Weapon
|
AnyAG = 2956984318, -- Any Air-To-Ground Weapon
|
||||||
AnyAA = 264241152, -- Any Air-To-Air Weapon
|
AnyAA = 264241152, -- Any Air-To-Air Weapon
|
||||||
AnyUnguided = 2952822768, -- Any Unguided Weapon
|
AnyUnguided = 2952822768, -- Any Unguided Weapon
|
||||||
AnyGuided = 268402702, -- Any Guided Weapon
|
AnyGuided = 268402702, -- Any Guided Weapon
|
||||||
|
AnyShell = 258503344128, -- Any Shell
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Weapon types by category. See the [Weapon Flag](https://wiki.hoggitworld.com/view/DCS_enum_weapon_flag) enumerator on hoggit wiki.
|
--- Weapon types by category. See the [Weapon Flag](https://wiki.hoggitworld.com/view/DCS_enum_weapon_flag) enumerator on hoggit wiki.
|
||||||
@@ -220,11 +230,11 @@ ENUMS.WeaponType.Torpedo={
|
|||||||
}
|
}
|
||||||
ENUMS.WeaponType.Any={
|
ENUMS.WeaponType.Any={
|
||||||
-- General combinations
|
-- General combinations
|
||||||
Weapon = 3221225470, -- Any Weapon (AnyBomb + AnyRocket + AnyMissile + Cannons)
|
Weapon = 265214230526, -- Any Weapon (AnyBomb + AnyRocket + AnyMissile + Cannons + Torpedos)
|
||||||
AG = 2956984318, -- Any Air-To-Ground Weapon
|
AG = 2956984318, -- Any Air-To-Ground Weapon
|
||||||
AA = 264241152, -- Any Air-To-Air Weapon
|
AA = 264241152, -- Any Air-To-Air Weapon
|
||||||
Unguided = 2952822768, -- Any Unguided Weapon
|
Unguided = 2952822768, -- Any Unguided Weapon
|
||||||
Guided = 268402702, -- Any Guided Weapon
|
Guided = 268402702, -- Any Guided Weapon
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -513,7 +523,7 @@ ENUMS.ReportingName =
|
|||||||
Tornado = "Tornado",
|
Tornado = "Tornado",
|
||||||
-- Transport / Bomber / Others
|
-- Transport / Bomber / Others
|
||||||
Atlas = "A400",
|
Atlas = "A400",
|
||||||
Lancer = "B1-B",
|
Lancer = "B-1B",
|
||||||
Stratofortress = "B-52H",
|
Stratofortress = "B-52H",
|
||||||
Herc = "C-130",
|
Herc = "C-130",
|
||||||
Hercules = "C-130J-30",
|
Hercules = "C-130J-30",
|
||||||
@@ -558,7 +568,7 @@ ENUMS.ReportingName =
|
|||||||
Apache = "AH-64",
|
Apache = "AH-64",
|
||||||
Chinook = "CH-47",
|
Chinook = "CH-47",
|
||||||
Sea_Stallion = "CH-53",
|
Sea_Stallion = "CH-53",
|
||||||
Kiowa = "OH-58",
|
Kiowa = "OH58D",
|
||||||
Seahawk = "SH-60",
|
Seahawk = "SH-60",
|
||||||
Blackhawk = "UH-60",
|
Blackhawk = "UH-60",
|
||||||
Sea_King = "S-61",
|
Sea_King = "S-61",
|
||||||
@@ -1798,13 +1808,21 @@ ENUMS.Storage.weapons.missiles.Igla_S = 'weapons.missiles.Igla_S'
|
|||||||
ENUMS.Storage.weapons.gunmounts.AKAN_NO_TRC = 'weapons.gunmounts.{AKAN_NO_TRC}'
|
ENUMS.Storage.weapons.gunmounts.AKAN_NO_TRC = 'weapons.gunmounts.{AKAN_NO_TRC}'
|
||||||
ENUMS.Storage.weapons.gunmounts.AKAN = 'weapons.gunmounts.{AKAN}'
|
ENUMS.Storage.weapons.gunmounts.AKAN = 'weapons.gunmounts.{AKAN}'
|
||||||
ENUMS.Storage.weapons.shells.M882_9x19 = 'weapons.shells.9x19_m882'
|
ENUMS.Storage.weapons.shells.M882_9x19 = 'weapons.shells.9x19_m882'
|
||||||
|
ENUMS.Storage.weapons.droptanks.fuel_tank_370gal = "weapons.droptanks.fuel_tank_370gal"
|
||||||
|
ENUMS.Storage.weapons.droptanks.fuel_tank_300gal = "weapons.droptanks.fuel_tank_300gal"
|
||||||
|
|
||||||
|
-- NEW
|
||||||
ENUMS.Storage.weapons.adapters.HB_F_4E_ORD_LAU_77 = 'weapons.adapters.HB_F-4E_ORD_LAU_77'
|
ENUMS.Storage.weapons.adapters.HB_F_4E_ORD_LAU_77 = 'weapons.adapters.HB_F-4E_ORD_LAU_77'
|
||||||
ENUMS.Storage.weapons.adapters.hb_a_6e_lau7_adu299 = 'weapons.adapters.hb_a-6e_lau7_adu299'
|
ENUMS.Storage.weapons.adapters.hb_a_6e_lau7_adu299 = 'weapons.adapters.hb_a-6e_lau7_adu299'
|
||||||
|
ENUMS.Storage.weapons.adapters.CHAP_AIM92LN = 'weapons.adapters.CHAP_AIM92LN'
|
||||||
|
ENUMS.Storage.weapons.adapters.CHAP_HOT3LN = 'weapons.adapters.CHAP_HOT3LN'
|
||||||
|
ENUMS.Storage.weapons.adapters.CHAP_FZ225 = 'weapons.adapters.CHAP_FZ225'
|
||||||
|
|
||||||
ENUMS.Storage.weapons.bombs.AH6_SMOKE_BLUE = 'weapons.bombs.AH6_SMOKE_BLUE'
|
ENUMS.Storage.weapons.bombs.AH6_SMOKE_BLUE = 'weapons.bombs.AH6_SMOKE_BLUE'
|
||||||
ENUMS.Storage.weapons.bombs.AH6_SMOKE_GREEN = 'weapons.bombs.AH6_SMOKE_GREEN'
|
ENUMS.Storage.weapons.bombs.AH6_SMOKE_GREEN = 'weapons.bombs.AH6_SMOKE_GREEN'
|
||||||
ENUMS.Storage.weapons.bombs.AH6_SMOKE_RED = 'weapons.bombs.AH6_SMOKE_RED'
|
ENUMS.Storage.weapons.bombs.AH6_SMOKE_RED = 'weapons.bombs.AH6_SMOKE_RED'
|
||||||
ENUMS.Storage.weapons.bombs.AH6_SMOKE_YELLOW = 'weapons.bombs.AH6_SMOKE_YELLOW'
|
ENUMS.Storage.weapons.bombs.AH6_SMOKE_YELLOW = 'weapons.bombs.AH6_SMOKE_YELLOW'
|
||||||
|
ENUMS.Storage.weapons.bombs.AO_25SL = 'weapons.bombs.AO_25SL'
|
||||||
|
|
||||||
ENUMS.Storage.weapons.missiles.HB_AGM_78 = 'weapons.missiles.HB_AGM_78'
|
ENUMS.Storage.weapons.missiles.HB_AGM_78 = 'weapons.missiles.HB_AGM_78'
|
||||||
ENUMS.Storage.weapons.missiles.V_1 = 'weapons.missiles.V-1'
|
ENUMS.Storage.weapons.missiles.V_1 = 'weapons.missiles.V-1'
|
||||||
@@ -1851,6 +1869,10 @@ ENUMS.Storage.weapons.shells.M42A1_HE = 'weapons.shells.M42A1_HE'
|
|||||||
ENUMS.Storage.weapons.shells.HE_20x138B = 'weapons.shells.20x138B_HE'
|
ENUMS.Storage.weapons.shells.HE_20x138B = 'weapons.shells.20x138B_HE'
|
||||||
ENUMS.Storage.weapons.shells.HE_37x263 = 'weapons.shells.37x263_HE'
|
ENUMS.Storage.weapons.shells.HE_37x263 = 'weapons.shells.37x263_HE'
|
||||||
ENUMS.Storage.weapons.shells.HE_2A20_115mm = 'weapons.shells.2A20_115mm_HE'
|
ENUMS.Storage.weapons.shells.HE_2A20_115mm = 'weapons.shells.2A20_115mm_HE'
|
||||||
|
ENUMS.Storage.weapons.shells.AP_20x99R = 'weapons.shells.20x99R_AP'
|
||||||
|
ENUMS.Storage.weapons.shells.IranFAC_DShK_API_T = 'weapons.shells.IranFAC_DShK_API_T'
|
||||||
|
ENUMS.Storage.weapons.shells.IranFAC_DShK_API = 'weapons.shells.IranFAC_DShK_API'
|
||||||
|
ENUMS.Storage.weapons.shells.HE_T_20x99R = 'weapons.shells.20x99R_HE_T'
|
||||||
|
|
||||||
ENUMS.Storage.weapons.gunmounts.B17_TailTurret_M2_L = 'weapons.gunmounts.B17_TailTurret_M2_L'
|
ENUMS.Storage.weapons.gunmounts.B17_TailTurret_M2_L = 'weapons.gunmounts.B17_TailTurret_M2_L'
|
||||||
ENUMS.Storage.weapons.gunmounts.AH6_M134L = 'weapons.gunmounts.{AH6_M134L}'
|
ENUMS.Storage.weapons.gunmounts.AH6_M134L = 'weapons.gunmounts.{AH6_M134L}'
|
||||||
@@ -1881,6 +1903,11 @@ ENUMS.Storage.weapons.gunmounts.AH_6_FN_HMP400 = 'weapons.gunmounts.{AH-6_FN_HMP
|
|||||||
ENUMS.Storage.weapons.gunmounts.AH_6_M134L = 'weapons.gunmounts.AH-6_M134L'
|
ENUMS.Storage.weapons.gunmounts.AH_6_M134L = 'weapons.gunmounts.AH-6_M134L'
|
||||||
ENUMS.Storage.weapons.gunmounts.AH_6_M134R = 'weapons.gunmounts.AH-6_M134R'
|
ENUMS.Storage.weapons.gunmounts.AH_6_M134R = 'weapons.gunmounts.AH-6_M134R'
|
||||||
ENUMS.Storage.weapons.gunmounts.AH_6_HMP400 = 'weapons.gunmounts.AH-6_HMP400'
|
ENUMS.Storage.weapons.gunmounts.AH_6_HMP400 = 'weapons.gunmounts.AH-6_HMP400'
|
||||||
|
ENUMS.Storage.weapons.gunmounts.AKAN_NO_TRC = 'weapons.gunmounts.{AKAN_NO_TRC}'
|
||||||
|
ENUMS.Storage.weapons.gunmounts.AKAN = 'weapons.gunmounts.{AKAN}'
|
||||||
|
ENUMS.Storage.weapons.gunmounts.CHAP_HMP400LC = 'weapons.gunmounts.{CHAP_HMP400LC}'
|
||||||
|
ENUMS.Storage.weapons.gunmounts.HMP400LC = 'weapons.gunmounts.HMP400LC'
|
||||||
|
ENUMS.Storage.weapons.gunmounts.SHVAK_GUN = 'weapons.gunmounts.SHVAK_GUN'
|
||||||
|
|
||||||
ENUMS.Storage.weapons.droptanks.PTB_800 = 'weapons.droptanks.PTB-800'
|
ENUMS.Storage.weapons.droptanks.PTB_800 = 'weapons.droptanks.PTB-800'
|
||||||
ENUMS.Storage.weapons.droptanks.PTB_275 = 'weapons.droptanks.PTB-275'
|
ENUMS.Storage.weapons.droptanks.PTB_275 = 'weapons.droptanks.PTB-275'
|
||||||
@@ -1931,6 +1958,7 @@ ENUMS.Storage.weapons.droptanks.S_3_PTB = 'weapons.droptanks.S-3-PTB'
|
|||||||
ENUMS.Storage.weapons.droptanks.fuel_tank_370gal = 'weapons.droptanks.fuel_tank_370gal'
|
ENUMS.Storage.weapons.droptanks.fuel_tank_370gal = 'weapons.droptanks.fuel_tank_370gal'
|
||||||
ENUMS.Storage.weapons.droptanks.MIG_23_PTB = 'weapons.droptanks.MIG-23-PTB'
|
ENUMS.Storage.weapons.droptanks.MIG_23_PTB = 'weapons.droptanks.MIG-23-PTB'
|
||||||
ENUMS.Storage.weapons.droptanks.f_18c_ptb = 'weapons.droptanks.f-18c-ptb'
|
ENUMS.Storage.weapons.droptanks.f_18c_ptb = 'weapons.droptanks.f-18c-ptb'
|
||||||
|
ENUMS.Storage.weapons.droptanks.CHAP_TigerUHT_fueltank = 'weapons.droptanks.CHAP_TigerUHT_fueltank'
|
||||||
|
|
||||||
ENUMS.Storage.weapons.containers.FN_HMP400_100 = 'weapons.containers.{FN_HMP400_100}'
|
ENUMS.Storage.weapons.containers.FN_HMP400_100 = 'weapons.containers.{FN_HMP400_100}'
|
||||||
ENUMS.Storage.weapons.containers.AN_M3 = 'weapons.containers.{AN-M3}'
|
ENUMS.Storage.weapons.containers.AN_M3 = 'weapons.containers.{AN-M3}'
|
||||||
@@ -2062,6 +2090,13 @@ ENUMS.Storage.weapons.containers.GIAT_M621_AP = 'weapons.containers.{GIAT_M621_A
|
|||||||
ENUMS.Storage.weapons.containers.M134_R = 'weapons.containers.M134_R'
|
ENUMS.Storage.weapons.containers.M134_R = 'weapons.containers.M134_R'
|
||||||
ENUMS.Storage.weapons.containers.OH58D_M3P_L300 = 'weapons.containers.OH58D_M3P_L300'
|
ENUMS.Storage.weapons.containers.OH58D_M3P_L300 = 'weapons.containers.OH58D_M3P_L300'
|
||||||
ENUMS.Storage.weapons.containers.AH6_M134R = 'weapons.containers.{AH6_M134R}'
|
ENUMS.Storage.weapons.containers.AH6_M134R = 'weapons.containers.{AH6_M134R}'
|
||||||
|
ENUMS.Storage.weapons.containers.CHAP_HMP400LC = 'weapons.containers.{CHAP_HMP400LC}'
|
||||||
|
|
||||||
|
ENUMS.Storage.weapons.missiles.C701_AShM = 'weapons.missiles.C701 AShM'
|
||||||
|
ENUMS.Storage.weapons.missiles.IGLA_9M39 = 'weapons.missiles.9M39_IGLA'
|
||||||
|
ENUMS.Storage.weapons.missiles.CHAP_AIM92 = 'weapons.missiles.CHAP_AIM92'
|
||||||
|
ENUMS.Storage.weapons.missiles.AM39 = 'weapons.missiles.AM39'
|
||||||
|
ENUMS.Storage.weapons.missiles.Shahed136_LM = 'weapons.missiles.Shahed136_LM'
|
||||||
|
|
||||||
ENUMS.Storage.weapons.torpedoes.G7A_T1 = 'weapons.torpedoes.G7A_T1'
|
ENUMS.Storage.weapons.torpedoes.G7A_T1 = 'weapons.torpedoes.G7A_T1'
|
||||||
|
|
||||||
@@ -2091,6 +2126,56 @@ ENUMS.Storage.weapons.containers.UH60_GAU19_RIGHT = 'weapons.containers.{UH60_GA
|
|||||||
ENUMS.Storage.weapons.containers.UH60_M230_RIGHT = 'weapons.containers.{UH60_M230_RIGHT}'
|
ENUMS.Storage.weapons.containers.UH60_M230_RIGHT = 'weapons.containers.{UH60_M230_RIGHT}'
|
||||||
ENUMS.Storage.weapons.containers.UH60L_M2_GUNNER = 'weapons.containers.{UH60L_M2_GUNNER}'
|
ENUMS.Storage.weapons.containers.UH60L_M2_GUNNER = 'weapons.containers.{UH60L_M2_GUNNER}'
|
||||||
|
|
||||||
|
|
||||||
|
ENUMS.Storage.weapons.adapters.GD_F100_SUU_13 = 'weapons.adapters.GD_F100_SUU-13'
|
||||||
|
ENUMS.Storage.weapons.containers.GPU_5_POD = 'weapons.containers.{GPU_5_POD}'
|
||||||
|
ENUMS.Storage.weapons.bombs.BOLT_117 = 'weapons.bombs.BOLT-117'
|
||||||
|
ENUMS.Storage.weapons.shells.F100_M39_20_TP_T = 'weapons.shells.F100_M39_20_TP_T'
|
||||||
|
ENUMS.Storage.weapons.gunmounts.M_39_F_100 = 'weapons.gunmounts.M-39 F-100'
|
||||||
|
ENUMS.Storage.weapons.droptanks.GD_F100_TANK_275_L = 'weapons.droptanks.GD_F100_TANK_275_L'
|
||||||
|
ENUMS.Storage.weapons.bombs.BLU_4B_R_GROUP_R = 'weapons.bombs.BLU-4B_R_GROUP_R'
|
||||||
|
ENUMS.Storage.weapons.containers.F100_CAMERA_P2 = 'weapons.containers.F100_CAMERA_P2'
|
||||||
|
ENUMS.Storage.weapons.containers.HB_ORD_SUU_7 = 'weapons.containers.HB_ORD_SUU_7'
|
||||||
|
ENUMS.Storage.weapons.adapters.SidewinderPylon = 'weapons.adapters.SidewinderPylon'
|
||||||
|
ENUMS.Storage.weapons.adapters.apu_470 = 'weapons.adapters.apu_470'
|
||||||
|
ENUMS.Storage.weapons.droptanks.GD_F100_TANK_335_R = 'weapons.droptanks.GD_F100_TANK_335_R'
|
||||||
|
ENUMS.Storage.weapons.bombs.BLU_3B_R_GROUP_R = 'weapons.bombs.BLU-3B_R_GROUP_R'
|
||||||
|
ENUMS.Storage.weapons.droptanks.GD_F100_TANK_335_L = 'weapons.droptanks.GD_F100_TANK_335_L'
|
||||||
|
ENUMS.Storage.weapons.adapters.mbdz_u2t = 'weapons.adapters.mbdz_u2t'
|
||||||
|
ENUMS.Storage.weapons.containers.ZellRocket = 'weapons.containers.ZellRocket'
|
||||||
|
ENUMS.Storage.weapons.containers.apu_73 = 'weapons.containers.apu-73'
|
||||||
|
ENUMS.Storage.weapons.gunmounts.GAU_13 = 'weapons.gunmounts.GAU-13'
|
||||||
|
ENUMS.Storage.weapons.shells.F100_M39_20_TP = 'weapons.shells.F100_M39_20_TP'
|
||||||
|
ENUMS.Storage.weapons.shells.F100_M39_20_API = 'weapons.shells.F100_M39_20_API'
|
||||||
|
ENUMS.Storage.weapons.adapters.bdz_umk2b = 'weapons.adapters.bdz_umk2b'
|
||||||
|
ENUMS.Storage.weapons.droptanks.GD_F100_TANK_450 = 'weapons.droptanks.GD_F100_TANK_450'
|
||||||
|
ENUMS.Storage.weapons.droptanks.GD_F100_TANK_275_R = 'weapons.droptanks.GD_F100_TANK_275_R'
|
||||||
|
ENUMS.Storage.weapons.bombs.BLU_18_B_GROUP = 'weapons.bombs.BLU-18/B_GROUP'
|
||||||
|
ENUMS.Storage.weapons.containers.ZELL_Booster = 'weapons.containers.ZELL Booster'
|
||||||
|
ENUMS.Storage.weapons.adapters.apu_60 = 'weapons.adapters.apu_60'
|
||||||
|
ENUMS.Storage.weapons.gunmounts.GPU_5_POD = 'weapons.gunmounts.{GPU_5_POD}'
|
||||||
|
ENUMS.Storage.weapons.containers.F100_CAMERA_KA71A = 'weapons.containers.F100_CAMERA_KA71A'
|
||||||
|
ENUMS.Storage.weapons.bombs.BLU_3_R_GROUP_R = 'weapons.bombs.BLU-3_R_GROUP_R'
|
||||||
|
ENUMS.Storage.weapons.shells.F100_M39_20_HEI = 'weapons.shells.F100_M39_20_HEI'
|
||||||
|
ENUMS.Storage.weapons.droptanks.GD_F100_TANK_200 = 'weapons.droptanks.GD_F100_TANK_200'
|
||||||
|
ENUMS.Storage.weapons.adapters.apu_73 = 'weapons.adapters.apu-73'
|
||||||
|
ENUMS.Storage.weapons.gunmounts.AKAN_NO_TRC = 'weapons.gunmounts.AKAN_NO_TRC'
|
||||||
|
ENUMS.Storage.weapons.gunmounts.AKAN = 'weapons.gunmounts.AKAN'
|
||||||
|
ENUMS.Storage.weapons.shells.F100_M39_20_HEI_T = 'weapons.shells.F100_M39_20_HEI_T'
|
||||||
|
ENUMS.Storage.weapons.shells.F100_M39_20_API_T = 'weapons.shells.F100_M39_20_API_T'
|
||||||
|
ENUMS.Storage.weapons.containers.GD_F100_STRIKE_CAMERA = 'weapons.containers.GD_F100_STRIKE_CAMERA'
|
||||||
|
ENUMS.Storage.weapons.bombs.BLU_49_B = 'weapons.bombs.BLU-49/B'
|
||||||
|
|
||||||
|
ENUMS.Storage.weapons.bombs.GBU_24E = 'weapons.bombs.GBU_24E'
|
||||||
|
ENUMS.Storage.weapons.containers.GD_F100_SUU_13 = 'weapons.containers.GD_F100_SUU-13'
|
||||||
|
ENUMS.Storage.weapons.gunmounts.AKAN = 'weapons.gunmounts.{AKAN}'
|
||||||
|
ENUMS.Storage.weapons.gunmounts.AKAN_NO_TRC = 'weapons.gunmounts.{AKAN_NO_TRC}'
|
||||||
|
ENUMS.Storage.weapons.gunmounts.SUU_23_POD_Wing = 'weapons.gunmounts.{SUU_23_POD_Wing}'
|
||||||
|
ENUMS.Storage.weapons.containers.SUU_23_POD_Wing = 'weapons.containers.{SUU_23_POD_Wing}'
|
||||||
|
ENUMS.Storage.weapons.containers.SUU_23_POD_Centerline = 'weapons.containers.{SUU_23_POD_Centerline}'
|
||||||
|
ENUMS.Storage.weapons.gunmounts.SUU_23_POD_Centerline = 'weapons.gunmounts.{SUU_23_POD_Centerline}'
|
||||||
|
ENUMS.Storage.weapons.containers.HB_F_4E_BRU_42 = 'weapons.containers.HB_F-4E_BRU-42'
|
||||||
|
|
||||||
---
|
---
|
||||||
-- @type ENUMS.FARPType
|
-- @type ENUMS.FARPType
|
||||||
-- @field #string FARP
|
-- @field #string FARP
|
||||||
|
|||||||
@@ -753,8 +753,8 @@ UTILS.KnotsToKmph = function(knots)
|
|||||||
return knots * 1.852
|
return knots * 1.852
|
||||||
end
|
end
|
||||||
|
|
||||||
UTILS.KmphToKnots = function(kmph)
|
UTILS.KmphToKnots = function(knots)
|
||||||
return kmph / 1.852
|
return knots / 1.852
|
||||||
end
|
end
|
||||||
|
|
||||||
UTILS.KmphToMps = function( kmph )
|
UTILS.KmphToMps = function( kmph )
|
||||||
|
|||||||
@@ -76,10 +76,6 @@ Functional/Tiresias.lua
|
|||||||
Functional/Stratego.lua
|
Functional/Stratego.lua
|
||||||
Functional/ClientWatch.lua
|
Functional/ClientWatch.lua
|
||||||
Functional/Formation.lua
|
Functional/Formation.lua
|
||||||
Functional/RedGCIKernel.lua
|
|
||||||
Functional/RedGCI.lua
|
|
||||||
Functional/RedGCI2v2.lua
|
|
||||||
Functional/RedGCIDispatcher.lua
|
|
||||||
|
|
||||||
Ops/Airboss.lua
|
Ops/Airboss.lua
|
||||||
Ops/RecoveryTanker.lua
|
Ops/RecoveryTanker.lua
|
||||||
|
|||||||
Reference in New Issue
Block a user