mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-08-11 11:48:38 +00:00
Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7026a94301 | |||
| 92bc0389d3 | |||
| 7a5f6ad3c6 | |||
| 2a73d8d34a | |||
| dfe4db25ae | |||
| f66c77b027 | |||
| 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 | |||
| 36c0297344 | |||
| 8c60a8c678 | |||
| 6829d75464 | |||
| 867f919d5f | |||
| f769a0deb5 | |||
| 4efd71e36a | |||
| 7e9dd9deff | |||
| e8f5214e0b | |||
| fed9174bcb | |||
| b6ea6606fc | |||
| e4c7e809cb | |||
| aab16dd966 | |||
| 8b356f0913 | |||
| 9963c737a3 | |||
| 5005203206 | |||
| a3455855b8 | |||
| 73d3ed119c | |||
| d1e4dd3fe9 | |||
| c3086b0265 | |||
| 599a2ba6fb |
@@ -736,6 +736,12 @@ do -- Event Handling
|
||||
-- @param #BASE self
|
||||
-- @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.
|
||||
-- *** NOTE *** this is a workarounf for DCS not creating these events as of Aug 2024.
|
||||
-- @function [parent=#BASE] OnEventNewDynamicCargo
|
||||
@@ -881,6 +887,22 @@ end
|
||||
world.onEvent(Event)
|
||||
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.
|
||||
-- @param #BASE self
|
||||
-- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object
|
||||
|
||||
@@ -92,6 +92,8 @@ DATABASE = {
|
||||
ZONES_GOAL = {},
|
||||
WAREHOUSES = {},
|
||||
FLIGHTGROUPS = {},
|
||||
COHORTS={},
|
||||
LEGIONS={},
|
||||
FLIGHTCONTROLS = {},
|
||||
OPSZONES = {},
|
||||
PATHLINES = {},
|
||||
@@ -2087,6 +2089,40 @@ function DATABASE:FindOpsGroupFromUnit(unitname)
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
|
||||
--- Add an OPS COHORT (SQUADRON, PLATOON, FLOTILLA) to the data base.
|
||||
-- @param #DATABASE self
|
||||
-- @param Ops.Cohort#COHORT cohort The cohort added to the DB.
|
||||
function DATABASE:AddCohort(cohort)
|
||||
self.COHORTS[cohort.name]=cohort
|
||||
end
|
||||
|
||||
--- Find an OPS COHORT (SQUADRON, PLATOON, FLOTILLA) in the data base.
|
||||
-- @param #DATABASE self
|
||||
-- @param #string cohortname Name of the cohort.
|
||||
-- @return Ops.Cohort#COHORT Cohort object.
|
||||
function DATABASE:FindCohort(cohortname)
|
||||
return self.COHORTS[cohortname]
|
||||
end
|
||||
|
||||
--- Add an OPS LEGION (AIRWING, BRIGADE, FLEET) to the data base.
|
||||
-- @param #DATABASE self
|
||||
-- @param Ops.Legion#LEGION legion The legion added to the DB.
|
||||
function DATABASE:AddLegion(legion)
|
||||
self.LEGIONS[legion.alias]=legion
|
||||
end
|
||||
|
||||
--- Find an OPS LEGION (AIRWING, BRIGADE, FLEET) in the data base.
|
||||
-- @param #DATABASE self
|
||||
-- @param #string legionname Name of the legion.
|
||||
-- @return Ops.Legion#LEGION Legion object.
|
||||
function DATABASE:FindLegion(legionname)
|
||||
return self.LEGIONS[legionname]
|
||||
end
|
||||
|
||||
--
|
||||
|
||||
--- Add a flight control to the data base.
|
||||
-- @param #DATABASE self
|
||||
-- @param OPS.FlightControl#FLIGHTCONTROL flightcontrol
|
||||
|
||||
@@ -278,6 +278,7 @@ EVENTS = {
|
||||
SimulationUnfreeze = world.event.S_EVENT_SIMULATION_UNFREEZE or -1,
|
||||
HumanAircraftRepairStart = world.event.S_EVENT_HUMAN_AIRCRAFT_REPAIR_START 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
|
||||
NewDynamicCargo = world.event.S_EVENT_NEW_DYNAMIC_CARGO 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.)STATIC : A STATIC object type is involved in the Event.
|
||||
-- * A GROUP : A DCS Group object is involved in the Event.
|
||||
--
|
||||
-- @type EVENTDATA
|
||||
-- @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#Unit IniDCSUnit (UNIT/STATIC) The initiating @{DCS#Unit} or @{DCS#StaticObject}.
|
||||
-- @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 #string IniUnitName (UNIT/STATIC) The initiating UNIT name (same as IniDCSUnitName).
|
||||
-- @field DCS#Group IniDCSGroup (UNIT) The initiating {DCSGroup#Group}.
|
||||
-- @field #string IniDCSGroupName (UNIT) The initiating Group name.
|
||||
-- @field Wrapper.Group#GROUP IniGroup (UNIT) The initiating MOOSE wrapper @{Wrapper.Group#GROUP} of the initiator Group object.
|
||||
-- @field #string IniGroupName UNIT) The initiating GROUP name (same as IniDCSGroupName).
|
||||
-- @field DCS#Group IniDCSGroup (UNIT/GROUP) The initiating @{DCS#Group}.
|
||||
-- @field #string IniDCSGroupName (UNIT/GROUP) The initiating Group name.
|
||||
-- @field Wrapper.Group#GROUP IniGroup (UNIT/GROUP) The initiating MOOSE wrapper @{Wrapper.Group#GROUP} of the initiator Group object.
|
||||
-- @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 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 #string IniTypeName (UNIT) The type name of the initiator.
|
||||
--
|
||||
@@ -734,6 +737,12 @@ local _EVENTMETA = {
|
||||
Side = "I",
|
||||
Event = "OnEventHumanAircraftRepairFinish",
|
||||
Text = "S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH"
|
||||
},
|
||||
[EVENTS.GroupChangeOption] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventGroupChangeOption",
|
||||
Text = "S_EVENT_GROUP_CHANGE_OPTION"
|
||||
},
|
||||
-- dynamic cargo
|
||||
[EVENTS.NewDynamicCargo] = {
|
||||
@@ -1234,7 +1243,16 @@ function EVENT:onEvent( Event )
|
||||
|
||||
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
|
||||
---
|
||||
@@ -1453,7 +1471,11 @@ function EVENT:onEvent( Event )
|
||||
-- Weapon.
|
||||
if Event.weapon and type(Event.weapon) == "table" and Event.weapon.isExist and Event.weapon:isExist() then
|
||||
Event.Weapon = Event.weapon
|
||||
Event.WeaponName = Event.weapon:isExist() and Event.weapon.getTypeName and Event.weapon:getTypeName() or "Unknown Weapon"
|
||||
if Event.weapon_name == "ZELL Booster" then
|
||||
Event.WeaponName = "ZELL Booster"
|
||||
else
|
||||
Event.WeaponName = Event.weapon:isExist() and Event.weapon.getTypeName and Event.weapon:getTypeName() or "Unknown Weapon"
|
||||
end
|
||||
if Event.weapon_name == "ZELL Booster" then Event.WeaponName = "ZELL Booster" end
|
||||
Event.WeaponUNIT = CLIENT:Find( Event.Weapon, '', true ) -- Sometimes, the weapon is a player unit!
|
||||
Event.WeaponPlayerName = Event.WeaponUNIT and Event.Weapon.getPlayerName and Event.Weapon:getPlayerName()
|
||||
|
||||
@@ -375,3 +375,13 @@ function SCHEDULEDISPATCHER:NoTrace( Scheduler )
|
||||
Scheduler.ShowTrace = false
|
||||
end
|
||||
|
||||
--- Helper for memory cleanup for self stopping schedulers
|
||||
-- @param #SCHEDULEDISPATCHER self
|
||||
-- @param Core.Scheduler#SCHEDULER Scheduler Scheduler object.
|
||||
-- @param #string CallID (Optional) Scheduler Call ID.
|
||||
function SCHEDULEDISPATCHER:_Reclaim( Scheduler, CallID )
|
||||
self:Stop( Scheduler, CallID ) -- remove DCS timer, nil ScheduleID
|
||||
if self.Schedule[Scheduler] then self.Schedule[Scheduler][CallID] = nil end
|
||||
self.ObjectSchedulers[CallID] = nil
|
||||
self.PersistentSchedulers[CallID] = nil
|
||||
end
|
||||
|
||||
@@ -87,7 +87,8 @@ do -- world
|
||||
-- @field S_EVENT_SIMULATION_UNFREEZE = 58
|
||||
-- @field S_EVENT_HUMAN_AIRCRAFT_REPAIR_START = 59
|
||||
-- @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.
|
||||
-- @type world.BirthPlace
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,292 @@
|
||||
--- **Ops** - Passive strategic territory.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Associate a static MOOSE zone with a coalition
|
||||
-- * Keep strategic territory geometry separate from OPSZONE scanning
|
||||
-- * Register territories in the MOOSE database
|
||||
-- * Delegate coordinate checks and F10 drawing to the underlying zone
|
||||
--
|
||||
-- A TERRITORY is deliberately passive. It does not scan DCS objects, evaluate
|
||||
-- ownership, run a scheduler, or make tactical or strategic decisions.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Ops.Territory
|
||||
|
||||
|
||||
--- TERRITORY class.
|
||||
-- @type TERRITORY
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #string version Class version.
|
||||
-- @field #number verbose Verbosity level.
|
||||
-- @field #string lid Log ID string.
|
||||
-- @field #string name Unique territory name.
|
||||
-- @field #string zoneName Name of the underlying MOOSE zone.
|
||||
-- @field Core.Zone#ZONE_BASE zone Underlying MOOSE zone.
|
||||
-- @field #number coalition Coalition associated with the territory.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- A passive strategic area defined by an existing MOOSE zone.
|
||||
--
|
||||
-- TERRITORY contains geometry and declarative ownership only. Unlike
|
||||
-- @{Ops.OpsZone#OPSZONE}, it performs no periodic object scans and has no FSM.
|
||||
--
|
||||
-- @field #TERRITORY
|
||||
TERRITORY = {
|
||||
ClassName = "TERRITORY",
|
||||
verbose = 0,
|
||||
}
|
||||
|
||||
--- TERRITORY class version.
|
||||
-- @field #string version
|
||||
TERRITORY.version = "0.1.0"
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- DATABASE extension
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Finds a TERRITORY based on its name.
|
||||
-- @param Core.Database#DATABASE self
|
||||
-- @param #string TerritoryName Name of the territory.
|
||||
-- @return #TERRITORY The found territory or `nil`.
|
||||
function DATABASE:FindTerritory(TerritoryName)
|
||||
local territories = self.TERRITORIES or {}
|
||||
return territories[TerritoryName]
|
||||
end
|
||||
|
||||
--- Adds a TERRITORY to the database.
|
||||
-- @param Core.Database#DATABASE self
|
||||
-- @param #TERRITORY Territory Territory to add.
|
||||
-- @return #TERRITORY The registered territory or `nil`.
|
||||
function DATABASE:AddTerritory(Territory)
|
||||
if not Territory then
|
||||
return nil
|
||||
end
|
||||
|
||||
self.TERRITORIES = self.TERRITORIES or {}
|
||||
|
||||
local territoryName = Territory:GetName()
|
||||
if not self.TERRITORIES[territoryName] then
|
||||
self.TERRITORIES[territoryName] = Territory
|
||||
end
|
||||
|
||||
return self.TERRITORIES[territoryName]
|
||||
end
|
||||
|
||||
--- Deletes a TERRITORY from the database.
|
||||
-- @param Core.Database#DATABASE self
|
||||
-- @param #string TerritoryName Name of the territory.
|
||||
-- @return Core.Database#DATABASE self
|
||||
function DATABASE:DeleteTerritory(TerritoryName)
|
||||
if self.TERRITORIES then
|
||||
self.TERRITORIES[TerritoryName] = nil
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new TERRITORY class object.
|
||||
-- @param #TERRITORY self
|
||||
-- @param Core.Zone#ZONE_BASE Zone The underlying MOOSE zone or its Mission Editor name.
|
||||
-- @param #number Coalition (Optional) Associated coalition. Default `coalition.side.NEUTRAL`.
|
||||
-- @param #string Name (Optional) Unique territory name. Default is the zone name.
|
||||
-- @return #TERRITORY self
|
||||
-- @usage
|
||||
-- local north = TERRITORY:New("Territory North", coalition.side.BLUE)
|
||||
-- local southZone = ZONE:FindByName("Territory South")
|
||||
-- local south = TERRITORY:New(southZone, coalition.side.RED, "Southern Territory")
|
||||
function TERRITORY:New(Zone, Coalition, Name)
|
||||
|
||||
-- Inherit everything from BASE class.
|
||||
local self = BASE:Inherit(self, BASE:New()) -- #TERRITORY
|
||||
|
||||
-- Resolve a Mission Editor zone name.
|
||||
if type(Zone) == "string" then
|
||||
local zoneName = Zone
|
||||
Zone = ZONE:FindByName(zoneName)
|
||||
if not Zone then
|
||||
self:E(string.format("ERROR: No ZONE found for name: %s", tostring(zoneName)))
|
||||
return nil
|
||||
end
|
||||
elseif not Zone then
|
||||
self:E("ERROR: First parameter Zone is nil in TERRITORY:New(Zone) call!")
|
||||
return nil
|
||||
end
|
||||
|
||||
-- A territory relies only on the common ZONE_BASE interface.
|
||||
if type(Zone.GetName) ~= "function"
|
||||
or type(Zone.GetCoordinate) ~= "function"
|
||||
or type(Zone.IsCoordinateInZone) ~= "function" then
|
||||
self:E("ERROR: TERRITORY requires a ZONE_BASE derived object!")
|
||||
return nil
|
||||
end
|
||||
|
||||
local zoneName = Zone:GetName()
|
||||
local territoryName = Name or zoneName
|
||||
if type(territoryName) ~= "string" or territoryName == "" then
|
||||
self:E("ERROR: TERRITORY requires a non-empty name!")
|
||||
return nil
|
||||
end
|
||||
|
||||
self.zone = Zone
|
||||
self.zoneName = zoneName
|
||||
self.name = territoryName
|
||||
self.lid = string.format("TERRITORY %s | ", territoryName)
|
||||
|
||||
if not self:SetCoalition(Coalition or coalition.side.NEUTRAL) then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Register in the MOOSE database.
|
||||
_DATABASE:AddTerritory(self)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Set functions
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Set the coalition associated with this territory.
|
||||
-- This method only changes declarative ownership. It does not evaluate DCS
|
||||
-- units or trigger any capture logic.
|
||||
-- @param #TERRITORY self
|
||||
-- @param #number Coalition Coalition side number.
|
||||
-- @return #TERRITORY self or `nil` if the coalition is invalid.
|
||||
function TERRITORY:SetCoalition(Coalition)
|
||||
if Coalition ~= coalition.side.NEUTRAL
|
||||
and Coalition ~= coalition.side.RED
|
||||
and Coalition ~= coalition.side.BLUE then
|
||||
self:E(self.lid .. string.format("ERROR: Invalid coalition: %s", tostring(Coalition)))
|
||||
return nil
|
||||
end
|
||||
|
||||
self.coalition = Coalition
|
||||
return self
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Get functions
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Find a TERRITORY by name.
|
||||
-- @param #TERRITORY self
|
||||
-- @param #string Name Name of the territory.
|
||||
-- @return #TERRITORY The found territory or `nil`.
|
||||
function TERRITORY:FindByName(Name)
|
||||
return _DATABASE:FindTerritory(Name)
|
||||
end
|
||||
|
||||
--- Get the territory name.
|
||||
-- @param #TERRITORY self
|
||||
-- @return #string Territory name.
|
||||
function TERRITORY:GetName()
|
||||
return self.name
|
||||
end
|
||||
|
||||
--- Get the underlying zone name.
|
||||
-- @param #TERRITORY self
|
||||
-- @return #string Zone name.
|
||||
function TERRITORY:GetZoneName()
|
||||
return self.zoneName
|
||||
end
|
||||
|
||||
--- Get the underlying MOOSE zone.
|
||||
-- @param #TERRITORY self
|
||||
-- @return Core.Zone#ZONE_BASE The underlying zone.
|
||||
function TERRITORY:GetZone()
|
||||
return self.zone
|
||||
end
|
||||
|
||||
--- Get the territory center coordinate.
|
||||
-- @param #TERRITORY self
|
||||
-- @return Core.Point#COORDINATE Territory center coordinate.
|
||||
function TERRITORY:GetCoordinate()
|
||||
return self.zone:GetCoordinate()
|
||||
end
|
||||
|
||||
--- Get the coalition associated with the territory.
|
||||
-- @param #TERRITORY self
|
||||
-- @return #number Coalition side number.
|
||||
function TERRITORY:GetCoalition()
|
||||
return self.coalition
|
||||
end
|
||||
|
||||
--- Get the name of the coalition associated with the territory.
|
||||
-- @param #TERRITORY self
|
||||
-- @return #string Coalition name.
|
||||
function TERRITORY:GetCoalitionName()
|
||||
return UTILS.GetCoalitionName(self.coalition)
|
||||
end
|
||||
|
||||
--- Get the owner of the territory.
|
||||
-- This is an alias for @{#TERRITORY.GetCoalition}.
|
||||
-- @param #TERRITORY self
|
||||
-- @return #number Coalition side number.
|
||||
function TERRITORY:GetOwner()
|
||||
return self:GetCoalition()
|
||||
end
|
||||
|
||||
--- Get the owner coalition name.
|
||||
-- This is an alias for @{#TERRITORY.GetCoalitionName}.
|
||||
-- @param #TERRITORY self
|
||||
-- @return #string Coalition name.
|
||||
function TERRITORY:GetOwnerName()
|
||||
return self:GetCoalitionName()
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Zone functions
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Test whether a coordinate lies inside the territory.
|
||||
-- @param #TERRITORY self
|
||||
-- @param Core.Point#COORDINATE Coordinate Coordinate to test.
|
||||
-- @return #boolean `true` if the coordinate lies inside the territory.
|
||||
function TERRITORY:ContainsCoordinate(Coordinate)
|
||||
return self.zone:IsCoordinateInZone(Coordinate)
|
||||
end
|
||||
|
||||
--- Test whether a Vec2 lies inside the territory.
|
||||
-- @param #TERRITORY self
|
||||
-- @param DCS#Vec2 Vec2 Vec2 to test.
|
||||
-- @return #boolean `true` if the Vec2 lies inside the territory.
|
||||
function TERRITORY:ContainsVec2(Vec2)
|
||||
return self.zone:IsVec2InZone(Vec2)
|
||||
end
|
||||
|
||||
--- Draw the territory on the F10 map.
|
||||
-- Drawing is delegated to the underlying MOOSE zone.
|
||||
-- @param #TERRITORY self
|
||||
-- @param #number Coalition (Optional) Coalition visibility. Default `-1` for all.
|
||||
-- @param #table Color (Optional) RGB line color.
|
||||
-- @param #number Alpha (Optional) Line alpha.
|
||||
-- @param #table FillColor (Optional) RGB fill color.
|
||||
-- @param #number FillAlpha (Optional) Fill alpha.
|
||||
-- @param #number LineType (Optional) DCS line type.
|
||||
-- @return #TERRITORY self
|
||||
function TERRITORY:Draw(Coalition, Color, Alpha, FillColor, FillAlpha, LineType)
|
||||
self.zone:DrawZone(Coalition, Color, Alpha, FillColor, FillAlpha, LineType)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove the territory drawing from the F10 map.
|
||||
-- @param #TERRITORY self
|
||||
-- @return #TERRITORY self
|
||||
function TERRITORY:Undraw()
|
||||
self.zone:UndrawZone()
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove the territory from the MOOSE database.
|
||||
-- The underlying zone is not deleted.
|
||||
-- @param #TERRITORY self
|
||||
-- @return #TERRITORY self
|
||||
function TERRITORY:Remove()
|
||||
_DATABASE:DeleteTerritory(self.name)
|
||||
return self
|
||||
end
|
||||
@@ -79,6 +79,7 @@ __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Tiresias.lua' )
|
||||
__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/Formation.lua')
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Territory.lua')
|
||||
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Airboss.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/RecoveryTanker.lua' )
|
||||
|
||||
@@ -290,6 +290,9 @@ function AIRWING:New(warehousename, airwingname)
|
||||
-- @param Ops.FlightGroup#FLIGHTGROUP FlightGroup The FLIGHTGROUP on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
|
||||
-- Add legion to DB
|
||||
_DATABASE:AddLegion(self)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -541,6 +544,47 @@ function AIRWING:AddPayloadCapability(Payload, MissionTypes, Performance)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Filter available payloads for a given aircraft type and mission type.
|
||||
-- @param #AIRWING self
|
||||
-- @param #string UnitType The type of the unit.
|
||||
-- @param #string MissionType The mission type.
|
||||
-- @param #table Payloads Specific payloads only to be considered.
|
||||
-- @return #AIRWING.Payload Payload table or *nil*.
|
||||
function AIRWING:_FilterPlayloads(UnitType, MissionType, Payloads)
|
||||
|
||||
local function _checkPayloads(payload)
|
||||
if Payloads then
|
||||
for _,Payload in pairs(Payloads) do
|
||||
if Payload.uid==payload.uid then
|
||||
return true
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Payload was not specified.
|
||||
return nil
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Pre-selection: filter out only those payloads that are valid for the airframe and mission type and are available.
|
||||
local payloads={}
|
||||
|
||||
for _,_payload in pairs(self.payloads) do
|
||||
local payload=_payload --#AIRWING.Payload
|
||||
|
||||
local specialpayload=_checkPayloads(payload)
|
||||
local compatible=AUFTRAG.CheckMissionCapability(MissionType, payload.capabilities)
|
||||
|
||||
local goforit = specialpayload or (specialpayload==nil and compatible)
|
||||
|
||||
if payload.aircrafttype==UnitType and payload.navail>0 and goforit then
|
||||
table.insert(payloads, payload)
|
||||
end
|
||||
end
|
||||
|
||||
return payloads
|
||||
end
|
||||
|
||||
--- Fetch a payload from the airwing resources for a given unit and mission type.
|
||||
-- The payload with the highest priority is preferred.
|
||||
-- @param #AIRWING self
|
||||
@@ -589,34 +633,7 @@ function AIRWING:FetchPayloadFromStock(UnitType, MissionType, Payloads)
|
||||
end
|
||||
end
|
||||
|
||||
local function _checkPayloads(payload)
|
||||
if Payloads then
|
||||
for _,Payload in pairs(Payloads) do
|
||||
if Payload.uid==payload.uid then
|
||||
return true
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Payload was not specified.
|
||||
return nil
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Pre-selection: filter out only those payloads that are valid for the airframe and mission type and are available.
|
||||
local payloads={}
|
||||
for _,_payload in pairs(self.payloads) do
|
||||
local payload=_payload --#AIRWING.Payload
|
||||
|
||||
local specialpayload=_checkPayloads(payload)
|
||||
local compatible=AUFTRAG.CheckMissionCapability(MissionType, payload.capabilities)
|
||||
|
||||
local goforit = specialpayload or (specialpayload==nil and compatible)
|
||||
|
||||
if payload.aircrafttype==UnitType and payload.navail>0 and goforit then
|
||||
table.insert(payloads, payload)
|
||||
end
|
||||
end
|
||||
local payloads=self:_FilterPlayloads(UnitType, MissionType, Payloads)
|
||||
|
||||
-- Debug.
|
||||
if self.verbose>=4 then
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
-- **Supported Aircraft:**
|
||||
--
|
||||
-- * [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)
|
||||
-- * [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)
|
||||
@@ -1276,6 +1276,7 @@ AIRBOSS = {
|
||||
-- @field #string A4EC A-4E Community mod.
|
||||
-- @field #string HORNET F/A-18C Lot 20 Hornet by Eagle Dynamics.
|
||||
-- @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 F14B F-14B by Heatblur.
|
||||
-- @field #string F14A_AI F-14A Tomcat (AI).
|
||||
@@ -1297,6 +1298,7 @@ AIRBOSS.AircraftCarrier={
|
||||
F14A="F-14A-135-GR",
|
||||
F14A_Early="F-14A-135-GR-Early",
|
||||
F14B="F-14B",
|
||||
F14BU="F-14BU",
|
||||
F14A_AI="F-14A",
|
||||
FA18C="F/A-18C",
|
||||
T45C="T-45",
|
||||
@@ -4201,13 +4203,16 @@ function AIRBOSS:_CheckRecoveryTimes()
|
||||
-- Time into the wind 1 day or if longer recovery time + the 5 min early.
|
||||
local t = math.max( nextwindow.STOP - nextwindow.START + self.dTturn, 60 * 60 * 24 )
|
||||
|
||||
-- Recovery wind on deck in knots.
|
||||
-- Recovery wind on deck in knots.
|
||||
-- NOTE: Do NOT clamp the desired wind-over-deck (WOD) to the carrier's max hull
|
||||
-- speed here. WOD = carrier speed + headwind, so a WOD target above the hull's
|
||||
-- top speed is achievable whenever there is wind. CarrierTurnIntoWind ->
|
||||
-- GetHeadingIntoWind already converts the WOD target into the required hull
|
||||
-- speed and caps THAT at the carrier's max speed (Vmax) internally. Clamping the
|
||||
-- WOD target itself capped achievable WOD at ~30 kts (the supercarrier's max
|
||||
-- hull speed) even in strong wind, which made high-WOD recovery windows fall
|
||||
-- short of their requested value.
|
||||
local v = UTILS.KnotsToMps( nextwindow.SPEED )
|
||||
|
||||
-- Check that we do not go above max possible speed.
|
||||
local vmax = self.carrier:GetSpeedMax() / 3.6 -- convert to m/s
|
||||
v = math.min( v, vmax )
|
||||
|
||||
-- Route carrier into the wind. Sets self.turnintowind=true
|
||||
self:CarrierTurnIntoWind( t, v, uturn )
|
||||
|
||||
@@ -5505,7 +5510,7 @@ function AIRBOSS:_GetAircraftAoA( playerData )
|
||||
local goshawk = playerData.actype == AIRBOSS.AircraftCarrier.T45C
|
||||
local skyhawk = playerData.actype == AIRBOSS.AircraftCarrier.A4EC
|
||||
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
|
||||
|
||||
-- Table with AoA values.
|
||||
@@ -5568,6 +5573,18 @@ function AIRBOSS:_GetAircraftAoA( playerData )
|
||||
aoa.OnSpeedMin = 9.5
|
||||
aoa.Fast = 8.0
|
||||
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
|
||||
|
||||
return aoa
|
||||
@@ -5584,7 +5601,7 @@ function AIRBOSS:_AoAUnit2Deg( playerData, aoaunits )
|
||||
local degrees = aoaunits
|
||||
|
||||
-- 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 --
|
||||
@@ -5627,7 +5644,7 @@ function AIRBOSS:_AoADeg2Units( playerData, degrees )
|
||||
local aoaunits = degrees
|
||||
|
||||
-- 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 --
|
||||
@@ -5677,7 +5694,7 @@ function AIRBOSS:_GetAircraftParameters( playerData, step )
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOF
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.GROWLER
|
||||
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 goshawk = playerData.actype == AIRBOSS.AircraftCarrier.T45C
|
||||
local corsair = playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR or playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR_CW
|
||||
@@ -6610,9 +6627,7 @@ function AIRBOSS:_RefuelAI( flight )
|
||||
local refuelac=false
|
||||
local actype=flight.group:GetTypeName()
|
||||
if actype==AIRBOSS.AircraftCarrier.AV8B or
|
||||
actype==AIRBOSS.AircraftCarrier.F14A or
|
||||
actype==AIRBOSS.AircraftCarrier.F14B or
|
||||
actype==AIRBOSS.AircraftCarrier.F14A_AI or
|
||||
self:_IsTomcat( actype, true ) or
|
||||
actype==AIRBOSS.AircraftCarrier.HORNET or
|
||||
actype==AIRBOSS.AircraftCarrier.RHINOE or
|
||||
actype==AIRBOSS.AircraftCarrier.RHINOF or
|
||||
@@ -6722,7 +6737,7 @@ function AIRBOSS:_LandAI( flight )
|
||||
Speed = UTILS.KnotsToKmph( 200 )
|
||||
elseif flight.actype == AIRBOSS.AircraftCarrier.E2D or flight.actype == AIRBOSS.AircraftCarrier.C2A then
|
||||
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 )
|
||||
elseif flight.actype == AIRBOSS.AircraftCarrier.S3B or flight.actype == AIRBOSS.AircraftCarrier.S3BTANKER then
|
||||
Speed = UTILS.KnotsToKmph( 140 )
|
||||
@@ -8197,7 +8212,7 @@ function AIRBOSS:_CheckPlayerStatus()
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOE
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOF
|
||||
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
|
||||
if playerData.step==AIRBOSS.PatternStep.WAKE and hornet then-- VNAO Edit - Added
|
||||
@@ -9452,7 +9467,7 @@ function AIRBOSS:_Initial( playerData )
|
||||
|
||||
-- Hook down for students.
|
||||
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°!"
|
||||
else
|
||||
hint = hint .. " - Hook down!"
|
||||
@@ -9617,8 +9632,7 @@ function AIRBOSS:_DirtyUp( playerData )
|
||||
|
||||
-- Radio call "Say/Fly needles". Delayed by 10/15 seconds.
|
||||
if playerData.actype == AIRBOSS.AircraftCarrier.HORNET
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.F14A
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.F14B
|
||||
or self:_IsTomcat( playerData.actype )
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOE
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOF
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.GROWLER
|
||||
@@ -10812,7 +10826,7 @@ function AIRBOSS:_Trapped( playerData )
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOF
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.GROWLER then
|
||||
dcorr = 100
|
||||
elseif playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B then
|
||||
elseif self:_IsTomcat( playerData.actype ) then
|
||||
-- TODO: Check Tomcat.
|
||||
dcorr = 100
|
||||
elseif playerData.actype == AIRBOSS.AircraftCarrier.A4EC then
|
||||
@@ -11625,7 +11639,7 @@ function AIRBOSS:_AttitudeMonitor( playerData )
|
||||
|
||||
local unitClient = Unit.getByName(unit:GetName()) -- 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
|
||||
local nozzlePosL = 0 -- VNAO Edit - Added
|
||||
@@ -11858,7 +11872,7 @@ function AIRBOSS:_NozzleArgumentLeft( unit ) -- VNAO Edit - Added
|
||||
else -- VNAO Edit - Added
|
||||
nozzlePosL = 0 -- 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
|
||||
end -- VNAO Edit - Added
|
||||
|
||||
@@ -11883,7 +11897,7 @@ function AIRBOSS:_NozzleArgumentRight( unit ) -- VNAO Edit - Added
|
||||
else -- VNAO Edit - Added
|
||||
nozzlePosR = 0 -- 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
|
||||
end -- VNAO Edit - Added
|
||||
return nozzlePosR -- VNAO Edit - Added
|
||||
@@ -13146,7 +13160,7 @@ function AIRBOSS:_Flightdata2Text( playerData, groovestep )
|
||||
|
||||
|
||||
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 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?
|
||||
@@ -13662,7 +13676,7 @@ function AIRBOSS:_StepHint( playerData, step )
|
||||
|
||||
-- Late break.
|
||||
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."
|
||||
end
|
||||
end
|
||||
@@ -13671,7 +13685,7 @@ function AIRBOSS:_StepHint( playerData, step )
|
||||
if step == AIRBOSS.PatternStep.ABEAM then
|
||||
if playerData.actype == AIRBOSS.AircraftCarrier.AV8B then
|
||||
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."
|
||||
else
|
||||
hint = hint .. "\nDirty up! Gear DOWN, flaps DOWN. Check hook down."
|
||||
@@ -15106,7 +15120,7 @@ function AIRBOSS:_GetACNickname( actype )
|
||||
nickname = "Hawkeye"
|
||||
elseif actype == AIRBOSS.AircraftCarrier.C2A then
|
||||
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"
|
||||
elseif actype == AIRBOSS.AircraftCarrier.FA18C or actype == AIRBOSS.AircraftCarrier.HORNET then
|
||||
nickname = "Hornet"
|
||||
@@ -15243,6 +15257,29 @@ function AIRBOSS:_GetGoodBadScore( playerData )
|
||||
return lowscore, badscore
|
||||
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.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param Wrapper.Unit#UNIT unit Aircraft unit. (Will also work with groups as given parameter.)
|
||||
|
||||
@@ -192,6 +192,8 @@
|
||||
-- @field #boolean optionInvisible Invisible is on/off.
|
||||
-- @field #boolean optionImmortal Immortal is on/off.
|
||||
--
|
||||
-- @field #AUFTRAG.Summary summary Auftrag summary.
|
||||
--
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- *A warrior's mission is to foster the success of others.* -- Morihei Ueshiba
|
||||
@@ -656,6 +658,19 @@ AUFTRAG.Category={
|
||||
-- @field #string DAMAGED Target was damaged.
|
||||
-- @field #string DESTROYED Target was destroyed.
|
||||
|
||||
--- Mission summary.
|
||||
-- @type AUFTRAG.Summary
|
||||
-- @field #boolean success If true, mission was successful.
|
||||
-- @field #number Ntargets0 Number of initial targets.
|
||||
-- @field #number Ntargets Number of final targets after mission is done.
|
||||
-- @field #number damage Target damage in per cent.
|
||||
-- @field #number Ndestroyed Number of destroyed targets.
|
||||
-- @field #number Nkills Number of kills from assigned groups.
|
||||
-- @field #number Nelements Number of elements assigned to mission.
|
||||
-- @field #number targetLife Target life points after mission is over.
|
||||
-- @field #number category Target category.
|
||||
-- @field #number Ncasualties Number of own casualties.
|
||||
|
||||
--- Generic mission condition.
|
||||
-- @type AUFTRAG.Condition
|
||||
-- @field #function func Callback function to check for a condition. Should return a #boolean.
|
||||
@@ -676,7 +691,7 @@ AUFTRAG.Category={
|
||||
|
||||
--- AUFTRAG class version.
|
||||
-- @field #string version
|
||||
AUFTRAG.version="1.4.2"
|
||||
AUFTRAG.version="1.5.0"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -776,6 +791,7 @@ function AUFTRAG:New(Type)
|
||||
|
||||
self:AddTransition("*", "Cancel", AUFTRAG.Status.CANCELLED) -- Command to cancel the mission.
|
||||
|
||||
self:AddTransition("*", "Evaluated", "*")
|
||||
self:AddTransition("*", "Success", AUFTRAG.Status.SUCCESS)
|
||||
self:AddTransition("*", "Failed", AUFTRAG.Status.FAILED)
|
||||
|
||||
@@ -946,6 +962,24 @@ function AUFTRAG:New(Type)
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
|
||||
--- Triggers the FSM event "Evaluated".
|
||||
-- @function [parent=#AUFTRAG] Evaluated
|
||||
-- @param #AUFTRAG self
|
||||
-- @param #AUFTRAG.Summary
|
||||
|
||||
--- Triggers the FSM event "Evaluated" after a delay.
|
||||
-- @function [parent=#AUFTRAG] __Evaluated
|
||||
-- @param #AUFTRAG self
|
||||
-- @param #number delay Delay in seconds.
|
||||
-- @param #AUFTRAG.Summary Summary Mission summary.
|
||||
|
||||
--- On after "Evaluated" event.
|
||||
-- @function [parent=#AUFTRAG] OnAfterEvaluated
|
||||
-- @param #AUFTRAG self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #AUFTRAG.Summary Summary Mission summary.
|
||||
|
||||
--- Triggers the FSM event "Success".
|
||||
-- @function [parent=#AUFTRAG] Success
|
||||
@@ -1751,6 +1785,9 @@ function AUFTRAG:NewBAI(Target, Altitude)
|
||||
mission.optionROE=ENUMS.ROE.OpenFire
|
||||
mission.optionROT=ENUMS.ROT.PassiveDefense
|
||||
|
||||
-- Evaluate result after 5 min. We might need time until the bombs have dropped and targets have been detroyed.
|
||||
mission.dTevaluate=5*60
|
||||
|
||||
mission.categories={AUFTRAG.Category.AIRCRAFT}
|
||||
|
||||
mission.DCStask=mission:GetDCSMissionTask()
|
||||
@@ -2304,6 +2341,9 @@ function AUFTRAG:NewARTY(Target, Nshots, Radius, Altitude)
|
||||
|
||||
local mission=AUFTRAG:New(AUFTRAG.Type.ARTY)
|
||||
|
||||
printf("FF nshots=%s", tostring(Nshots))
|
||||
printf("FF radius=%s", tostring(Radius))
|
||||
|
||||
mission:_TargetFromObject(Target)
|
||||
|
||||
mission.artyShots=Nshots or nil
|
||||
@@ -2407,7 +2447,7 @@ end
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Ops.OpsZone#OPSZONE OpsZone The OPS zone to capture.
|
||||
-- @param #number Coalition The coalition which should capture the zone for the mission to be successful.
|
||||
-- @param #number Speed Speed in knots.
|
||||
-- @param #number Speed (Optional) Speed in knots.
|
||||
-- @param #number Altitude (Optional) Altitude in feet. Only for airborne units. Default 2000 feet ASL.
|
||||
-- @param #string Formation (Optional) Formation used by ground units during patrol. Default "Off Road".
|
||||
-- @param #number StayInZoneTime Stay this many seconds in the zone when done, only then drive back.
|
||||
@@ -4690,6 +4730,18 @@ function AUFTRAG:Evaluate()
|
||||
failed=false
|
||||
end
|
||||
|
||||
self.summary={} --#AUFTRAG.Summary
|
||||
self.summary.success=not failed
|
||||
self.summary.damage=targetdamage
|
||||
self.summary.Ntargets=Ntargets
|
||||
self.summary.Ntargets0=Ntargets0
|
||||
self.summary.Ncasualties=self.Ncasualties
|
||||
self.summary.Ndestroyed=self.engageTarget.Ndestroyed
|
||||
self.summary.Nelements=self.Nelements
|
||||
self.summary.Nkills=self.Nkills
|
||||
self.summary.category=self.engageTarget:GetCategory()
|
||||
self.summary.targetLife=Life
|
||||
|
||||
-- Debug text.
|
||||
if self.verbose > 0 then
|
||||
local text=string.format("Evaluating mission:\n")
|
||||
@@ -4709,6 +4761,9 @@ function AUFTRAG:Evaluate()
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
-- Trigger evaluated result and pass summary.
|
||||
self:Evaluated(self.summary)
|
||||
|
||||
-- Trigger events.
|
||||
if failed then
|
||||
self:I(self.lid..string.format("Mission %d [%s] failed!", self.auftragsnummer, self.type))
|
||||
@@ -5018,7 +5073,7 @@ function AUFTRAG:CheckGroupsDone()
|
||||
-- Check status of all OPS groups.
|
||||
for groupname,data in pairs(self.groupdata) do
|
||||
local groupdata=data --#AUFTRAG.GroupData
|
||||
if groupdata then
|
||||
if groupdata and not groupdata.opsgroup:IsDestroyed() then
|
||||
if not (groupdata.status==AUFTRAG.GroupStatus.DONE or groupdata.status==AUFTRAG.GroupStatus.CANCELLED) then
|
||||
-- At least this group is not DONE or CANCELLED.
|
||||
self:T2(self.lid..string.format("CheckGroupsDone: OPSGROUP %s is not DONE or CANCELLED but in state %s. Mission NOT DONE!", groupdata.opsgroup.groupname, groupdata.status:upper()))
|
||||
@@ -5120,7 +5175,6 @@ end
|
||||
-- FSM Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
--- On after "Planned" event.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param #string From From state.
|
||||
@@ -5430,7 +5484,7 @@ function AUFTRAG:onafterSuccess(From, Event, To)
|
||||
|
||||
-- Stop mission.
|
||||
self:T(self.lid..string.format("Mission SUCCESS! Number of max repeats %d reached ==> Stopping mission!", self.repeated+1))
|
||||
self:Stop()
|
||||
self:__Stop(-120)
|
||||
|
||||
end
|
||||
|
||||
@@ -5472,7 +5526,7 @@ function AUFTRAG:onafterFailed(From, Event, To)
|
||||
|
||||
-- Stop mission.
|
||||
self:T(self.lid..string.format("Mission FAILED! Number of max repeats %d reached ==> Stopping mission!", self.repeated+1))
|
||||
self:Stop()
|
||||
self:__Stop(-120)
|
||||
|
||||
end
|
||||
|
||||
@@ -5585,6 +5639,7 @@ function AUFTRAG:onafterRepeat(From, Event, To)
|
||||
self.Ngroups=0
|
||||
self.Nassigned=nil
|
||||
self.Ndead=0
|
||||
self.summary=nil
|
||||
|
||||
-- Update DCS mission task. Could be that the initial task (e.g. for bombing) was destroyed. Then we need to update the coordinate.
|
||||
self.DCStask=self:GetDCSMissionTask()
|
||||
@@ -5636,6 +5691,8 @@ function AUFTRAG:onafterStop(From, Event, To)
|
||||
-- No group data.
|
||||
self.groupdata={}
|
||||
|
||||
self.summary=nil
|
||||
|
||||
-- Clear pending scheduler calls.
|
||||
self.CallScheduler:Clear()
|
||||
|
||||
@@ -5980,6 +6037,7 @@ function AUFTRAG:CountOpsGroups()
|
||||
local groupdata=_groupdata --#AUFTRAG.GroupData
|
||||
if groupdata and groupdata.opsgroup and groupdata.opsgroup:IsAlive() and not groupdata.opsgroup:IsDead() then
|
||||
N=N+1
|
||||
printf("FF Count Group N=%d %s", N, tostring(groupdata.opsgroup.groupname))
|
||||
end
|
||||
end
|
||||
return N
|
||||
@@ -6466,7 +6524,13 @@ function AUFTRAG:GetDCSMissionTask(MissionGroup)
|
||||
-- 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)
|
||||
|
||||
|
||||
@@ -150,6 +150,9 @@ function BRIGADE:New(WarehouseName, BrigadeName)
|
||||
-- @param Ops.ArmyGroup#ARMYGROUP ArmyGroup The ARMYGROUP on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
|
||||
-- Add legion to DB
|
||||
_DATABASE:AddLegion(self)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
@@ -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.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.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.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.
|
||||
@@ -2037,7 +2038,7 @@ function CTLD:_C130DcAutoRegisterEntry(SetId, Cargo)
|
||||
|
||||
local pos = Cargo:GetPositionable()
|
||||
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 entry = {
|
||||
id = entryId,
|
||||
@@ -2748,14 +2749,12 @@ function CTLD:_EventHandler(EventData)
|
||||
loaded = self.Loaded_Cargo[unitname] -- #CTLD.LoadedCargo
|
||||
loaded.Cratesloaded = loaded.Cratesloaded - 1
|
||||
if loaded.Cratesloaded < 0 then loaded.Cratesloaded = 0 end
|
||||
-- TODO zap cargo from list
|
||||
local Loaded = {}
|
||||
for _,_item in pairs (loaded.Cargo or {}) do
|
||||
self:T(self.lid.."UNLOAD checking: ".._item:GetName())
|
||||
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
|
||||
table.insert(Loaded,_item)
|
||||
else
|
||||
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)
|
||||
end
|
||||
end
|
||||
@@ -3125,14 +3124,14 @@ end
|
||||
function CTLD:_FindRepairNearby(Group, Unit, Repairtype)
|
||||
self:T(self.lid .. " _FindRepairNearby")
|
||||
--self:T({Group:GetName(),Unit:GetName(),Repairtype})
|
||||
local unitcoord = Unit:GetCoordinate()
|
||||
local unitcoord = Unit:GetCoord()
|
||||
|
||||
-- find nearest group of deployed groups
|
||||
local nearestGroup = nil
|
||||
local nearestGroupIndex = -1
|
||||
local nearestDistance = 10000
|
||||
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 desc = unit:GetDesc() or nil
|
||||
if distance < nearestDistance and distance ~= -1 and not desc.attributes.Infantry then
|
||||
@@ -3277,7 +3276,7 @@ end
|
||||
local capabilities = self:_GetUnitCapabilities(Unit)
|
||||
local cantroops = capabilities.troops -- #boolean
|
||||
local trooplimit = capabilities.trooplimit -- #number
|
||||
local unitcoord = unit:GetCoordinate()
|
||||
local unitcoord = unit:GetCoord()
|
||||
|
||||
-- find nearest group of deployed troops
|
||||
local nearestGroup = nil
|
||||
@@ -3288,7 +3287,7 @@ end
|
||||
local distancekeys = {}
|
||||
local extractdistance = self.CrateDistance * self.ExtractFactor
|
||||
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 vtime = v.ExtractTime or TNow-310
|
||||
if distance <= extractdistance and distance ~= -1 and (TNow - vtime > 300) then
|
||||
@@ -3376,7 +3375,7 @@ end
|
||||
self:_UpdateUnitCargoMass(Unit)
|
||||
local groupname = nearestGroup:GetName()
|
||||
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
|
||||
if coord then
|
||||
local heading = unit:GetHeading() or 0
|
||||
@@ -3747,16 +3746,16 @@ function CTLD:_C130GetUnits(Group, Unit, Name)
|
||||
return self
|
||||
end
|
||||
|
||||
local coord = Unit:GetCoordinate() or Group:GetCoordinate()
|
||||
local coord = Unit:GetCoord() or Group:GetCoord()
|
||||
local capabilities = self:_GetUnitCapabilities(Unit)
|
||||
local innerDist = (capabilities.length and capabilities.length/2) or 15
|
||||
local maxUnitsNearby = self.maxUnitsNearby or 3
|
||||
local searchRadius = self.UnitDistance or 90
|
||||
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
|
||||
for _,gr in pairs(nearGroups.Set) do
|
||||
local gc = gr:GetCoordinate()
|
||||
local gc = gr:GetCoord()
|
||||
if gc then
|
||||
local dist = coord:Get2DDistance(gc)
|
||||
if dist > innerDist then
|
||||
@@ -3806,6 +3805,7 @@ function CTLD:_C130GetUnits(Group, Unit, Name)
|
||||
if canmove then
|
||||
SPAWN:NewWithAlias(_template,alias)
|
||||
:InitRandomizeUnits(true,10,2)
|
||||
:InitCoalition(self.coalition)
|
||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits, 70)
|
||||
:InitDelayOff()
|
||||
:OnSpawnGroup(function(grp,TimeStamp)
|
||||
@@ -3819,6 +3819,7 @@ function CTLD:_C130GetUnits(Group, Unit, Name)
|
||||
SPAWN:NewWithAlias(_template,alias)
|
||||
:InitRandomizeUnits(true,10,2)
|
||||
:InitDelayOff()
|
||||
:InitCoalition(self.coalition)
|
||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits, 70)
|
||||
:OnSpawnGroup(function(grp,TimeStamp)
|
||||
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
|
||||
local location = Cargo:GetLocation()
|
||||
if location then
|
||||
local unitcoord = Unit:GetCoordinate() or Group:GetCoordinate()
|
||||
local unitcoord = Unit:GetCoord() or Group:GetCoord()
|
||||
if unitcoord then
|
||||
if not location:IsCoordinateInZone(unitcoord) then
|
||||
-- no we're not at the right spot
|
||||
@@ -3972,7 +3973,7 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack, quiet, suppress
|
||||
end
|
||||
|
||||
-- get position and heading of heli
|
||||
local position = Unit:GetCoordinate()
|
||||
local position = Unit:GetCoord()
|
||||
local heading = Unit:GetHeading() + 1
|
||||
local height = Unit:GetHeight()
|
||||
local droppedcargo = {}
|
||||
@@ -4136,8 +4137,8 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack, quiet, suppress
|
||||
if type(ship) == "string" then
|
||||
self:T("Spawning on ship "..ship)
|
||||
local Ship = UNIT:FindByName(ship)
|
||||
local shipcoord = Ship:GetCoordinate()
|
||||
local unitcoord = Unit:GetCoordinate()
|
||||
local shipcoord = Ship:GetCoord()
|
||||
local unitcoord = Unit:GetCoord()
|
||||
local dist = shipcoord:Get2DDistance(unitcoord)
|
||||
dist = dist - (20 + math.random(1, 10))
|
||||
local halfwidth = (width or 20) / 2
|
||||
@@ -4389,17 +4390,17 @@ end
|
||||
function CTLD:_C130RemoveUnitsNearby(_group,_unit)
|
||||
self:T(self.lid .. " _C130RemoveUnitsNearby")
|
||||
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
|
||||
local capabilities = self:_GetUnitCapabilities(_unit)
|
||||
local innerDist = (capabilities.length and capabilities.length/2) or 15
|
||||
local finddist = self.PackDistance or (self.CrateDistance or 35)
|
||||
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 removedTable = {}
|
||||
for _, gr in pairs(nearestGroups.Set) do
|
||||
local gc = gr:GetCoordinate()
|
||||
local gc = gr:GetCoord()
|
||||
if gc then
|
||||
local dist = location:Get2DDistance(gc)
|
||||
if dist > innerDist then
|
||||
@@ -4533,7 +4534,7 @@ end
|
||||
function CTLD:_FindCratesNearby( _group, _unit, _dist, _ignoreweight, ignoretype, ignoreHercInner)
|
||||
self:T(self.lid .. " _FindCratesNearby")
|
||||
local finddist = _dist
|
||||
local location = _group:GetCoordinate()
|
||||
local location = _group:GetCoord()
|
||||
local existingcrates = self.Spawned_Cargo -- #table
|
||||
-- cycle
|
||||
local index = 0
|
||||
@@ -5159,7 +5160,6 @@ function CTLD:_UnloadTroops(Group, Unit)
|
||||
-- unload troops
|
||||
local name = cargo:GetName() or "none"
|
||||
local temptable = cargo:GetTemplates() or {}
|
||||
local position = Group:GetCoordinate()
|
||||
local zoneradius = self.troopdropzoneradius or 100 -- drop zone radius
|
||||
local factor = 1
|
||||
if IsHerc then
|
||||
@@ -5196,6 +5196,7 @@ function CTLD:_UnloadTroops(Group, Unit)
|
||||
local Positions = self:_GetUnitPositions(randomcoord,rad,heading,_template)
|
||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
||||
:InitDelayOff()
|
||||
:InitCoalition(self.coalition)
|
||||
:InitSetUnitAbsolutePositions(Positions)
|
||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
||||
: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 template = Crate:GetTemplates()
|
||||
local ctype = Crate:GetType()
|
||||
local ccoord = Crate:GetPositionable():GetCoordinate() -- Core.Point#COORDINATE
|
||||
local distToUnit=Unit and ccoord:Get2DDistance(Unit:GetCoordinate())or 0
|
||||
local ccoord = Crate:GetPositionable():GetCoord() -- Core.Point#COORDINATE
|
||||
local distToUnit=Unit and ccoord:Get2DDistance(Unit:GetCoord())or 0
|
||||
local isHercDrop=Crate:WasDropped(true)
|
||||
if not isHercDrop and distToUnit>baseDist 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.Template = template
|
||||
object.CanBuild = false
|
||||
object.Heading = Unit:GetHeading()
|
||||
object.Type = ctype -- #CTLD_CARGO.Enum
|
||||
object.Coord = ccoord:GetVec2()
|
||||
buildables[name] = object
|
||||
@@ -5611,7 +5613,7 @@ function CTLD:_BuildCrates(Group, Unit,Engineering,MultiDrop,NotifyGroup)
|
||||
local sep = self.buildPairSeparation or 25
|
||||
local hdg = (Unit:GetHeading()+180)%360
|
||||
local lat = (hdg+90)%360
|
||||
local base = Unit:GetCoordinate():Translate(20,hdg)
|
||||
local base = Unit:GetCoord():Translate(20,hdg)
|
||||
|
||||
if full == 1 then
|
||||
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)
|
||||
local off = start + (n-1)*sep
|
||||
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
|
||||
local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,b,false,Group:GetCoordinate(),MultiDrop)
|
||||
buildtimer:Start(self.buildtime)
|
||||
@@ -5683,18 +5685,18 @@ end
|
||||
-- @return #number Number
|
||||
function CTLD:_FindPackableGroupsNearby(Group, Unit)
|
||||
self:T(self.lid .. " _FindPackableGroupsNearby")
|
||||
local location = Group:GetCoordinate()
|
||||
local location = Group:GetCoord()
|
||||
if not location then return {}, 0 end
|
||||
local capabilities = self:_GetUnitCapabilities(Unit)
|
||||
local innerDist = (capabilities.length and capabilities.length/2) or 15
|
||||
local finddist = self.PackDistance or (self.CrateDistance or 35)
|
||||
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 = {}
|
||||
|
||||
for _, gr in pairs(nearestGroups.Set) do
|
||||
if gr and gr:GetName() ~= Group:GetName() then
|
||||
local gc = gr:GetCoordinate()
|
||||
local gc = gr:GetCoord()
|
||||
if gc then
|
||||
local dist = location:Get2DDistance(gc)
|
||||
if dist > innerDist and dist <= finddist then
|
||||
@@ -5827,12 +5829,12 @@ function CTLD:_LoadPackedCratesByIds(Group, Unit, crateIds, cargoName)
|
||||
|
||||
local matchingCrates = {}
|
||||
local finddist = self.CrateDistance or 35
|
||||
local location = Group:GetCoordinate()
|
||||
local location = Group:GetCoord()
|
||||
for _, crateObj in pairs(self.Spawned_Cargo or {}) do
|
||||
if crateObj and idLookup[crateObj:GetID()] then
|
||||
local pos = crateObj:GetPositionable()
|
||||
if pos and pos:IsAlive() then
|
||||
local dist = location:Get2DDistance(pos:GetCoordinate())
|
||||
local dist = location:Get2DDistance(pos:GetCoord())
|
||||
if dist <= finddist then
|
||||
matchingCrates[#matchingCrates + 1] = crateObj
|
||||
end
|
||||
@@ -5942,12 +5944,12 @@ function CTLD:_RemovePackedCratesByIds(Group, Unit, crateIds)
|
||||
|
||||
local crates = {}
|
||||
local finddist = self.CrateDistance or 35
|
||||
local location = Group:GetCoordinate()
|
||||
local location = Group:GetCoord()
|
||||
for _, entry in pairs(self.Spawned_Cargo or {}) do
|
||||
if entry and idLookup[entry:GetID()] then
|
||||
local pos = entry:GetPositionable()
|
||||
if pos and pos:IsAlive() then
|
||||
local dist = location:Get2DDistance(pos:GetCoordinate())
|
||||
local dist = location:Get2DDistance(pos:GetCoord())
|
||||
if dist <= finddist then
|
||||
crates[#crates + 1] = entry
|
||||
end
|
||||
@@ -6197,28 +6199,31 @@ function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation,Mult
|
||||
for _,_template in pairs(temptable) do
|
||||
self.TroopCounter = self.TroopCounter + 1
|
||||
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
|
||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
||||
--: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)
|
||||
--spawn:InitRandomizeUnits(true,20,2)
|
||||
end
|
||||
if Build.Heading and self.useaircraftheadingforbuilds then
|
||||
spawn:InitGroupHeading(Build.Heading)
|
||||
end
|
||||
local spawnedGroup = spawn:SpawnFromVec2(randomcoord)
|
||||
self.DroppedTroops[self.TroopCounter] = spawnedGroup
|
||||
|
||||
if Repair then
|
||||
self:__CratesRepaired(1,Group,Unit,self.DroppedTroops[self.TroopCounter])
|
||||
self:__CratesRepaired(1,Group,Unit,spawnedGroup)
|
||||
else
|
||||
self:__CratesBuild(1,Group,Unit,self.DroppedTroops[self.TroopCounter])
|
||||
self:__CratesBuild(1,Group,Unit,spawnedGroup)
|
||||
end
|
||||
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
|
||||
self:T(self.lid.."Group KIA while building!")
|
||||
end
|
||||
@@ -6241,14 +6246,11 @@ end
|
||||
-- @param Wrapper.Group#GROUP Group The Group to move.
|
||||
function CTLD:_MoveGroupToZone(Group)
|
||||
self:T(self.lid .. " _MoveGroupToZone")
|
||||
local groupname = Group:GetName() or "none"
|
||||
local groupcoord = Group:GetCoordinate()
|
||||
-- Get closest zone of type
|
||||
local outcome, name, zone, distance = self:IsUnitInZone(Group,CTLD.CargoZoneType.MOVE)
|
||||
self:T({canmove=outcome, name=name, zone=zone, dist=distance,max=self.movetroopsdistance})
|
||||
if (distance <= self.movetroopsdistance) and outcome == true and zone~= nil then
|
||||
-- yes, we can ;)
|
||||
local groupname = Group:GetName()
|
||||
local zonecoord = zone:GetRandomCoordinate(20,125) -- Core.Point#COORDINATE
|
||||
local formation = self:_GetVehicleFormation()
|
||||
--local coordinate = zonecoord:GetVec2()
|
||||
@@ -7931,6 +7933,7 @@ function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID, qty)
|
||||
local Positions = self:_GetUnitPositions(randomcoord, rad, heading, _template)
|
||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template, alias)
|
||||
:InitDelayOff()
|
||||
:InitCoalition(self.coalition)
|
||||
:InitSetUnitAbsolutePositions(Positions)
|
||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
||||
:OnSpawnGroup(function(grp) grp.spawntime = timer.getTime() end)
|
||||
@@ -9008,7 +9011,7 @@ function CTLD:IsUnitInZone(Unit,Zonetype)
|
||||
local zoneret = nil
|
||||
local zonewret = nil
|
||||
local zonenameret = nil
|
||||
local unitcoord = Unit:GetCoordinate()
|
||||
local unitcoord = Unit:GetCoord()
|
||||
if not unitcoord then
|
||||
if Zonetype == CTLD.CargoZoneType.SHIP then
|
||||
return false, nil, nil, 1000000, nil
|
||||
@@ -9029,7 +9032,7 @@ function CTLD:IsUnitInZone(Unit,Zonetype)
|
||||
self:T("Checking Type Ship: "..zonename)
|
||||
local ZoneUNIT = UNIT:FindByName(zonename)
|
||||
if not ZoneUNIT then return false end
|
||||
zonecoord = ZoneUNIT:GetCoordinate()
|
||||
zonecoord = ZoneUNIT:GetCoord()
|
||||
zoneradius = czone.shiplength
|
||||
zonewidth = czone.shipwidth
|
||||
zone = ZONE_UNIT:New( ZoneUNIT:GetName(), ZoneUNIT, zoneradius/2)
|
||||
@@ -9078,7 +9081,7 @@ function CTLD:SmokePositionNow(Unit, Flare, SmokeColor)
|
||||
end
|
||||
local FlareColor = self.FlareColor or FLARECOLOR.Red
|
||||
-- table of #CTLD.CargoZone table
|
||||
local unitcoord = Unit:GetCoordinate() -- Core.Point#COORDINATE
|
||||
local unitcoord = Unit:GetCoord() -- Core.Point#COORDINATE
|
||||
local Group = Unit:GetGroup()
|
||||
if Flare then
|
||||
unitcoord:Flare(FlareColor, 90)
|
||||
@@ -9097,7 +9100,7 @@ end
|
||||
function CTLD:SmokeZoneNearBy(Unit, Flare)
|
||||
self:T(self.lid .. " SmokeZoneNearBy")
|
||||
-- table of #CTLD.CargoZone table
|
||||
local unitcoord = Unit:GetCoordinate()
|
||||
local unitcoord = Unit:GetCoord()
|
||||
local Group = Unit:GetGroup()
|
||||
local smokedistance = self.smokedistance
|
||||
local smoked = false
|
||||
@@ -9234,7 +9237,7 @@ end
|
||||
-- get speed and height
|
||||
local uspeed = Unit:GetVelocityMPS()
|
||||
local uheight = Unit:GetHeight()
|
||||
local ucoord = Unit:GetCoordinate()
|
||||
local ucoord = Unit:GetCoord()
|
||||
if not ucoord then
|
||||
return false
|
||||
end
|
||||
@@ -9263,7 +9266,7 @@ end
|
||||
-- get speed and height
|
||||
local uspeed = Unit:GetVelocityMPS()
|
||||
local uheight = Unit:GetHeight()
|
||||
local ucoord = Unit:GetCoordinate()
|
||||
local ucoord = Unit:GetCoord()
|
||||
if not ucoord then
|
||||
return false
|
||||
end
|
||||
@@ -9355,7 +9358,7 @@ end
|
||||
minheight = 5.1 -- herc is 5m AGL on the ground
|
||||
end
|
||||
local uheight = Unit:GetHeight()
|
||||
local ucoord = Unit:GetCoordinate()
|
||||
local ucoord = Unit:GetCoord()
|
||||
if not ucoord then
|
||||
return false
|
||||
end
|
||||
@@ -10141,6 +10144,7 @@ end
|
||||
local alias = string.format("%s-%d", _template, math.random(1,100000))
|
||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
||||
:InitRandomizeUnits(randompositions,20,2)
|
||||
:InitCoalition(self.coalition)
|
||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
||||
:InitDelayOff()
|
||||
:OnSpawnGroup(function(grp,TimeStamp) grp.spawntime = TimeStamp or timer.getTime() end,TimeStamp)
|
||||
@@ -10295,6 +10299,7 @@ end
|
||||
if canmove then
|
||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
||||
:InitRandomizeUnits(true,20,2)
|
||||
:InitCoalition(self.coalition)
|
||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
||||
:InitDelayOff()
|
||||
: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
|
||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
||||
:InitDelayOff()
|
||||
:InitCoalition(self.coalition)
|
||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
||||
:OnSpawnGroup(function(grp,TimeStamp) grp.spawntime = TimeStamp or timer.getTime() end,TimeStamp)
|
||||
:SpawnFromVec2(randomcoord)
|
||||
@@ -10583,7 +10589,7 @@ end
|
||||
self:T({From, Event, To})
|
||||
if Unit and Unit:IsPlayer() and self.PlayerTaskQueue then
|
||||
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()
|
||||
self.PlayerTaskQueue:ForEach(
|
||||
function (Task)
|
||||
@@ -10640,7 +10646,7 @@ end
|
||||
for _,_cargo in pairs(Cargotable) do
|
||||
local Vehicle = _cargo.Positionable
|
||||
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()
|
||||
self.PlayerTaskQueue:ForEach(
|
||||
function (Task)
|
||||
@@ -10705,7 +10711,7 @@ end
|
||||
self:T({From, Event, To})
|
||||
if Unit and Unit:IsPlayer() and self.PlayerTaskQueue then
|
||||
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()
|
||||
self.PlayerTaskQueue:ForEach(
|
||||
function (Task)
|
||||
|
||||
@@ -1102,6 +1102,31 @@ function COHORT:CountAssets(InStock, MissionTypes, Attributes)
|
||||
return N
|
||||
end
|
||||
|
||||
--- Count available assets in legion warehouse stock. Spawned, requested and reserved assets are not counted.
|
||||
-- @param #COHORT self
|
||||
-- @param #table MissionTypes (Optional) Count only assest that can perform certain mission type(s). Default is all types.
|
||||
-- @param #table Attributes (Optional) Count only assest that have a certain attribute(s), e.g. `WAREHOUSE.Attribute.AIR_BOMBER`.
|
||||
-- @return #number Number of assets.
|
||||
function COHORT:CountAvailableAssets(MissionTypes, Attributes)
|
||||
|
||||
local N=0
|
||||
for _,_asset in pairs(self.assets) do
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
if not (asset.spawned or asset.requested or asset.isReserved) then
|
||||
|
||||
if MissionTypes==nil or AUFTRAG.CheckMissionCapability(MissionTypes, self.missiontypes) then
|
||||
if Attributes==nil or self:CheckAttribute(Attributes) then
|
||||
N=N+1 --This is in stock.
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return N
|
||||
end
|
||||
|
||||
|
||||
--- Get OPSGROUPs.
|
||||
-- @param #COHORT self
|
||||
-- @param #table MissionTypes (Optional) Count only assest that can perform certain mission type(s). Default is all types.
|
||||
|
||||
@@ -1883,6 +1883,8 @@ function COMMANDER:RecruitAssetsForMission(Mission)
|
||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, Mission.type, Mission.alert5MissionType, NreqMin, NreqMax, TargetVec2, Payloads,
|
||||
Mission.engageRange, Mission.refuelSystem, nil, nil, MaxWeight, nil, Mission.attributes, Mission.properties, {Mission.engageWeaponType})
|
||||
|
||||
self:T(self.lid..string.format("Recruited=%s Nassets=%d", tostring(recruited), #assets))
|
||||
|
||||
return recruited, assets, legions
|
||||
end
|
||||
|
||||
@@ -2112,6 +2114,22 @@ function COMMANDER:CountAssets(InStock, MissionTypes, Attributes)
|
||||
return N
|
||||
end
|
||||
|
||||
--- Count available assets of all assigned legions, which are in stock. Spawned and reserved assets are not counted.
|
||||
-- @param #COMMANDER self
|
||||
-- @param #table MissionTypes (Optional) Count only assest that can perform certain mission type(s). Default is all types.
|
||||
-- @param #table Attributes (Optional) Count only assest that have a certain attribute(s), e.g. `WAREHOUSE.Attribute.AIR_BOMBER`.
|
||||
-- @return #number Amount of asset groups.
|
||||
function COMMANDER:CountAvailableAssets(MissionTypes, Attributes)
|
||||
|
||||
local N=0
|
||||
for _,_legion in pairs(self.legions) do
|
||||
local legion=_legion --Ops.Legion#LEGION
|
||||
N=N+legion:CountAvailableAssets(MissionTypes, Attributes)
|
||||
end
|
||||
|
||||
return N
|
||||
end
|
||||
|
||||
--- Count assets of all assigned legions.
|
||||
-- @param #COMMANDER self
|
||||
-- @param #table MissionTypes (Optional) Count only missions of these types. Default is all types.
|
||||
|
||||
@@ -135,6 +135,7 @@
|
||||
-- local mywing = EASYGCICAP:New("Blue CAP Operations",AIRBASE.Caucasus.Kutaisi,"blue","Blue EWR")
|
||||
--
|
||||
-- -- Add a CAP patrol point belonging to our airbase, we'll be at 30k ft doing 400 kn, initial direction 90 degrees (East), leg 20NM
|
||||
-- -- NOTE - Skip this function and do not create CAP Points if you want GCI behaviour only.
|
||||
-- mywing:AddPatrolPointCAP(AIRBASE.Caucasus.Kutaisi,ZONE:FindByName("Blue Zone 1"):GetCoordinate(),30000,400,90,20)
|
||||
--
|
||||
-- -- Add a Squadron with template "Blue Sq1 M2000c", 20 airframes, skill good, Modex starting with 102 and skin "Vendee Jeanne"
|
||||
@@ -190,9 +191,10 @@
|
||||
-- * @{#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.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.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.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.
|
||||
@@ -286,7 +288,7 @@ EASYGCICAP = {
|
||||
|
||||
--- EASYGCICAP class version.
|
||||
-- @field #string version
|
||||
EASYGCICAP.version="0.1.36"
|
||||
EASYGCICAP.version="0.1.38"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
--
|
||||
@@ -587,6 +589,17 @@ function EASYGCICAP:SetDefaultCAPAlt(Altitude)
|
||||
return self
|
||||
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
|
||||
-- @param #EASYGCICAP self
|
||||
-- @param #number Direction (Optional) Direction defaults to 90 (East)
|
||||
@@ -754,6 +767,15 @@ end
|
||||
function EASYGCICAP:_AddAirwing(Airbasename, Alias)
|
||||
self:T(self.lid.."_AddAirwing "..Airbasename)
|
||||
|
||||
-- Gather Some Stats
|
||||
local function counttable(tbl)
|
||||
local count = 0
|
||||
for _,_data in pairs(tbl) do
|
||||
count = count + 1
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
local CapFormation = self.CapFormation
|
||||
local DespawnAfterLanding = self.DespawnAfterLanding
|
||||
local DespawnAfterHolding = self.DespawnAfterHolding
|
||||
@@ -772,7 +794,11 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias)
|
||||
CAP_Wing:SetMarker(false)
|
||||
CAP_Wing:SetAirbase(AIRBASE:FindByName(Airbasename))
|
||||
CAP_Wing:SetRespawnAfterDestroyed()
|
||||
CAP_Wing:SetNumberCAP(self.capgrouping)
|
||||
|
||||
--- #DONE avoid wings with no CAP points starting CAP anyhow; AirWing uses this to start CAP and creates points when there are none.
|
||||
if counttable(self.ManagedCP) >0 then
|
||||
CAP_Wing:SetNumberCAP(self.capgrouping)
|
||||
end
|
||||
CAP_Wing:SetCapCloseRaceTrack(true)
|
||||
|
||||
if self.showpatrolpointmarks then
|
||||
@@ -1039,7 +1065,7 @@ function EASYGCICAP:_SetCAPPatrolPoints()
|
||||
MESSAGE:New(self.lid.."You are trying to create a CAP point for which there is no wing! "..tostring(data.AirbaseName),30,"CHECK"):ToAllIf(self.debug):ToLog()
|
||||
return
|
||||
end
|
||||
local Wing = self.wings[data.AirbaseName][1] -- Ops.Airwing#AIRWING
|
||||
local Wing = self.wings[data.AirbaseName][1] -- Ops.AirWing#AIRWING
|
||||
local Coordinate = data.Coordinate
|
||||
local Altitude = data.Altitude
|
||||
local Speed = data.Speed
|
||||
@@ -1505,6 +1531,7 @@ function EASYGCICAP:_AssignIntercept(Cluster)
|
||||
local overhead = self.overhead
|
||||
local capspeed = self.capspeed + 100
|
||||
local capalt = self.capalt
|
||||
local interalt = self.interceptalt or self.capalt
|
||||
local maxsize = self.maxinterceptsize
|
||||
local repeatsonfailure = self.repeatsonfailure
|
||||
|
||||
@@ -1592,6 +1619,7 @@ function EASYGCICAP:_AssignIntercept(Cluster)
|
||||
:SetRepeatOnFailure(repeats)
|
||||
:SetMissionSpeed(UTILS.KnotsToAltKIAS(capspeed,capalt))
|
||||
:SetMissionAltitude(capalt)
|
||||
:SetEngageAltitude(interalt)
|
||||
|
||||
if nogozoneset:Count() > 0 then
|
||||
InterceptAuftrag:AddConditionSuccess(
|
||||
|
||||
@@ -167,6 +167,9 @@ function FLEET:New(WarehouseName, FleetName)
|
||||
-- @param Ops.NavyGroup#NAVYGROUP NavyGroup The NAVYGROUP on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
|
||||
-- Add legion to DB
|
||||
_DATABASE:AddLegion(self)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
@@ -73,6 +73,9 @@ function FLOTILLA:New(TemplateGroupName, Ngroups, FlotillaName)
|
||||
-- Get initial ammo.
|
||||
self.ammo=self:_CheckAmmo()
|
||||
|
||||
-- Add cohort to DB
|
||||
_DATABASE:AddCohort(self)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
@@ -350,6 +350,18 @@ INTEL.RCS_NoseOnFraction = 0.15
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
--- Create a new INTEL object and start the FSM.
|
||||
-- @param #INTEL self
|
||||
-- @return #INTEL self
|
||||
function INTEL:_UpdateAgents()
|
||||
|
||||
-- Filter coalition.
|
||||
if self.coalition then
|
||||
local coalitionname=UTILS.GetCoalitionName(self.coalition):lower()
|
||||
self.detectionset:FilterCoalitions(coalitionname):FilterAlive():FilterOnce()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Create a new INTEL object and start the FSM.
|
||||
-- @param #INTEL self
|
||||
@@ -837,6 +849,18 @@ function INTEL:AddAgent(AgentGroup)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set whether the detection set, aka agents, are updated periodically. With this all alive groups of the INTEL coalition are included.
|
||||
-- @param #INTEL self
|
||||
-- @param #boolean switch If `true` or nil, all groups of the coalition will be added automatically to the Agent set.
|
||||
-- @return #INTEL self
|
||||
function INTEL:SetAgentAuto(switch)
|
||||
if switch==nil then
|
||||
switch=true
|
||||
end
|
||||
self.update_detectionset=switch
|
||||
return self
|
||||
end
|
||||
|
||||
--- Enable or disable cluster analysis of detected targets.
|
||||
-- Targets will be grouped in coupled clusters.
|
||||
-- @param #INTEL self
|
||||
@@ -1026,6 +1050,10 @@ function INTEL:onafterStatus(From, Event, To)
|
||||
-- FSM state.
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
if self.update_detectionset then
|
||||
self:_UpdateAgents()
|
||||
end
|
||||
|
||||
-- Fresh arrays.
|
||||
self.ContactsLost={}
|
||||
self.ContactsUnknown={}
|
||||
|
||||
@@ -306,7 +306,6 @@ function LEGION:New(WarehouseName, LegionName)
|
||||
-- @param Ops.Cohort#COHORT Cohort The cohort the asset belongs to.
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset that returned.
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -2099,6 +2098,23 @@ function LEGION:CountAssets(InStock, MissionTypes, Attributes)
|
||||
return N
|
||||
end
|
||||
|
||||
--- Count total number of available assets in the legion stock.
|
||||
-- @param #LEGION self
|
||||
-- @param #table MissionTypes (Optional) Count only assest that can perform certain mission type(s). Default is all types.
|
||||
-- @param #table Attributes (Optional) Count only assest that have a certain attribute(s), e.g. `GROUP.Attribute.AIR_BOMBER`.
|
||||
-- @return #number Amount of asset groups in stock.
|
||||
function LEGION:CountAvailableAssets(MissionTypes, Attributes)
|
||||
|
||||
local N=0
|
||||
|
||||
for _,_cohort in pairs(self.cohorts) do
|
||||
local cohort=_cohort --Ops.Cohort#COHORT
|
||||
N=N+cohort:CountAvailableAssets(MissionTypes,Attributes)
|
||||
end
|
||||
|
||||
return N
|
||||
end
|
||||
|
||||
--- Get OPSGROUPs that are spawned and alive.
|
||||
-- @param #LEGION self
|
||||
-- @param #table MissionTypes (Optional) Get only assest that can perform certain mission type(s). Default is all types.
|
||||
|
||||
@@ -4691,7 +4691,7 @@ function OPSGROUP:_UpdateTask(Task, Mission)
|
||||
self:T(self.lid..string.format("Zone %s captured ==> Task DONE!", zoneCurr:GetName()))
|
||||
|
||||
-- Task done.
|
||||
if Task.StayInZoneTime then
|
||||
if Task.StayInZoneTime and Task.StayInZoneTime>0 then
|
||||
local stay = Task.StayInZoneTime
|
||||
self:__TaskDone(stay,Task)
|
||||
else
|
||||
|
||||
@@ -72,6 +72,9 @@ function PLATOON:New(TemplateGroupName, Ngroups, PlatoonName)
|
||||
-- Get ammo.
|
||||
self.ammo=self:_CheckAmmo()
|
||||
|
||||
-- Add cohort to DB
|
||||
_DATABASE:AddCohort(self)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
@@ -116,6 +116,9 @@ function SQUADRON:New(TemplateGroupName, Ngroups, SquadronName)
|
||||
|
||||
-- See COHORT class
|
||||
|
||||
-- Add cohort to DB
|
||||
_DATABASE:AddCohort(self)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ _TARGETID=0
|
||||
|
||||
--- TARGET class version.
|
||||
-- @field #string version
|
||||
TARGET.version="0.7.1"
|
||||
TARGET.version="0.8.0"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -206,6 +206,9 @@ function TARGET:New(TargetObject)
|
||||
self:AddTransition("*", "Status", "*") -- Status update.
|
||||
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
|
||||
|
||||
self:AddTransition("*", "ElementDestroyed", "*") -- A target element was destroyed.
|
||||
self:AddTransition("*", "ElementDead", "*") -- A target element is dead (destroyed or despawned).
|
||||
|
||||
self:AddTransition("*", "ObjectDamaged", "*") -- A target object was damaged.
|
||||
self:AddTransition("*", "ObjectDestroyed", "*") -- A target object was destroyed.
|
||||
self:AddTransition("*", "ObjectDead", "*") -- A target object is dead (destroyed or despawned).
|
||||
@@ -245,6 +248,19 @@ function TARGET:New(TargetObject)
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
|
||||
--- Triggers the FSM event "ElementDestroyed".
|
||||
-- @function [parent=#TARGET] ElementDestroyed
|
||||
-- @param #TARGET self
|
||||
-- @param #string ElementName Name of the element.
|
||||
-- @param #TARGET.Object Target Target object.
|
||||
|
||||
--- Triggers the FSM event "ElementDead".
|
||||
-- @function [parent=#TARGET] ElementDead
|
||||
-- @param #TARGET self
|
||||
-- @param #string ElementName Name of the element.
|
||||
-- @param #TARGET.Object Target Target object.
|
||||
|
||||
|
||||
--- Triggers the FSM event "ObjectDamaged".
|
||||
-- @function [parent=#TARGET] ObjectDamaged
|
||||
-- @param #TARGET self
|
||||
@@ -643,6 +659,19 @@ function TARGET:onafterStatus(From, Event, To)
|
||||
-- FSM state.
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
-- First we check any target has been destroyed and the dead/unitlost event was not fired
|
||||
for i,_target in pairs(self.targets) do
|
||||
local target=_target --#TARGET.Object
|
||||
local life=self:GetTargetLife(target)
|
||||
if life<1 and target.Status~=TARGET.ObjectStatus.DEAD then
|
||||
self:E(self.lid..string.format("FF life is zero but no object dead event fired ==> waiting for target object %s events!", tostring(target.Name)))
|
||||
-- We wait 60 seconds for the events to occur
|
||||
self:__Status(-60)
|
||||
return self
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Update damage.
|
||||
local damaged=false
|
||||
for i,_target in pairs(self.targets) do
|
||||
@@ -736,6 +765,61 @@ end
|
||||
-- FSM Events
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- On after "ElementDestroyed" event.
|
||||
-- @param #TARGET self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #string Name Name of the element.
|
||||
-- @param #TARGET.Object Target Target object.
|
||||
function TARGET:onafterElementDestroyed(From, Event, To, Name, Target)
|
||||
-- Debug message.
|
||||
self:T(self.lid..string.format("Element %s of target object %s destroyed", Name, Target.Name))
|
||||
|
||||
-- Increase destroyed counter.
|
||||
Target.Ndestroyed=Target.Ndestroyed+1
|
||||
|
||||
-- Increase dead counter.
|
||||
self.Ndestroyed=self.Ndestroyed+1
|
||||
|
||||
self:ElementDead(Name, Target)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- On after "ElementDead" event.
|
||||
-- @param #TARGET self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #string Name Name of the element.
|
||||
-- @param #TARGET.Object Target Target object.
|
||||
function TARGET:onafterElementDead(From, Event, To, Name, Target)
|
||||
-- Debug message.
|
||||
self:T(self.lid..string.format("Element %s of target object %s dead", Name, Target.Name))
|
||||
|
||||
-- Increase dead counter.
|
||||
Target.Ndead=Target.Ndead+1
|
||||
|
||||
-- Increase dead counter.
|
||||
self.Ndead=self.Ndead+1
|
||||
|
||||
-- All dead ==> Trigger event.
|
||||
if Target.Ndestroyed==Target.N0 then
|
||||
|
||||
self:ObjectDestroyed(Target)
|
||||
|
||||
elseif Target.Ndead==Target.N0 then
|
||||
|
||||
self:ObjectDead(Target)
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- On after "ObjectDamaged" event.
|
||||
-- @param #TARGET self
|
||||
-- @param #string From From state.
|
||||
@@ -761,11 +845,6 @@ function TARGET:onafterObjectDestroyed(From, Event, To, Target)
|
||||
-- Debug message.
|
||||
self:T(self.lid..string.format("Object %s destroyed", Target.Name))
|
||||
|
||||
-- Increase destroyed counter.
|
||||
self.Ndestroyed=self.Ndestroyed+1
|
||||
|
||||
Target.Ndestroyed=Target.Ndestroyed+1
|
||||
|
||||
Target.Life=0
|
||||
|
||||
-- Call object dead event.
|
||||
@@ -788,15 +867,9 @@ function TARGET:onafterObjectDead(From, Event, To, Target)
|
||||
-- Set target status.
|
||||
Target.Status=TARGET.ObjectStatus.DEAD
|
||||
|
||||
-- Increase dead object counter
|
||||
Target.Ndead=Target.Ndead+1
|
||||
|
||||
-- Set target object life to 0.
|
||||
Target.Life=0
|
||||
|
||||
-- Increase dead counter.
|
||||
self.Ndead=self.Ndead+1
|
||||
|
||||
-- Check if anyone is alive?
|
||||
local dead=true
|
||||
for _,_target in pairs(self.targets) do
|
||||
@@ -889,54 +962,21 @@ function TARGET:OnEventUnitDeadOrLost(EventData)
|
||||
-- Add to the list of casualties.
|
||||
table.insert(self.casualties, Name)
|
||||
|
||||
-- Try to get target Group.
|
||||
local target=self:GetTargetByName(EventData.IniGroupName)
|
||||
|
||||
-- Try unit target.
|
||||
if not target then
|
||||
target=self:GetTargetByName(EventData.IniUnitName)
|
||||
end
|
||||
-- Get target from Group or Unit.
|
||||
local target=self:GetTargetByName(EventData.IniGroupName) or self:GetTargetByName(EventData.IniUnitName)
|
||||
|
||||
-- Check if we could find a target object.
|
||||
if target then
|
||||
|
||||
local Ndead=target.Ndead
|
||||
local Ndestroyed=target.Ndestroyed
|
||||
-- Increase dead/destroyed counter
|
||||
if EventData.id==EVENTS.RemoveUnit then
|
||||
Ndead=Ndead+1
|
||||
self:ElementDead(Name, target)
|
||||
else
|
||||
Ndestroyed=Ndestroyed+1
|
||||
Ndead=Ndead+1
|
||||
end
|
||||
|
||||
|
||||
-- Check if ALL objects are dead
|
||||
if Ndead==target.N0 then
|
||||
|
||||
if Ndestroyed>=target.N0 then
|
||||
|
||||
-- Debug message.
|
||||
self:T2(self.lid..string.format("EVENT ID=%d: target %s dead/lost ==> destroyed", EventData.id, tostring(target.Name)))
|
||||
|
||||
target.Life = 0
|
||||
|
||||
-- Trigger object destroyed event. This sets the Life to zero and increases Ndestroyed
|
||||
self:ObjectDestroyed(target)
|
||||
|
||||
else
|
||||
|
||||
-- Debug message.
|
||||
self:T2(self.lid..string.format("EVENT ID=%d: target %s removed ==> dead", EventData.id, tostring(target.Name)))
|
||||
|
||||
target.Life = 0
|
||||
|
||||
-- Trigger object dead event. This sets the Life to zero and increases Ndead counter
|
||||
self:ObjectDead(target)
|
||||
|
||||
end
|
||||
|
||||
self:ElementDestroyed(Name, target)
|
||||
end
|
||||
|
||||
else
|
||||
self:E(self.lid..string.format("ERROR: Could not get target from IniGroup or IniUnit name when event Dead or UnitLost occured! Stats are not correctly updated :("))
|
||||
end -- Event belongs to this TARGET
|
||||
|
||||
end
|
||||
|
||||
@@ -2108,7 +2108,7 @@ function MSRS:_HoundTextToSpeech(Message,Frequencies,Modulations,Volume,Label,Co
|
||||
|
||||
local ffs = {}
|
||||
for _,_f in pairs(Frequencies) do
|
||||
table.insert(ffs,string.format("%.1f",_f))
|
||||
table.insert(ffs,string.format("%.3f",_f))
|
||||
end
|
||||
|
||||
local freqs = table.concat(ffs, ",")
|
||||
@@ -2214,7 +2214,7 @@ function MSRS:_HoundTestTone(Frequencies, Modulations, Coalition)
|
||||
|
||||
local ffs = {}
|
||||
for _,_f in pairs(Frequencies or self.frequencies) do
|
||||
table.insert(ffs,string.format("%.1f",_f))
|
||||
table.insert(ffs,string.format("%.3f",_f))
|
||||
end
|
||||
|
||||
local freqs = table.concat(ffs, ",")
|
||||
@@ -2291,7 +2291,7 @@ function MSRS:RadioJammerOn(Frequencies, Modulations, Coalition, Noisetype, Volu
|
||||
|
||||
local ffs = {}
|
||||
for _,_f in pairs(Frequencies or self.frequencies) do
|
||||
table.insert(ffs,string.format("%.1f",_f))
|
||||
table.insert(ffs,string.format("%.3f",_f))
|
||||
end
|
||||
|
||||
local freqs = table.concat(ffs, ",")
|
||||
|
||||
@@ -523,7 +523,7 @@ ENUMS.ReportingName =
|
||||
Tornado = "Tornado",
|
||||
-- Transport / Bomber / Others
|
||||
Atlas = "A400",
|
||||
Lancer = "B1-B",
|
||||
Lancer = "B-1B",
|
||||
Stratofortress = "B-52H",
|
||||
Herc = "C-130",
|
||||
Hercules = "C-130J-30",
|
||||
@@ -568,7 +568,7 @@ ENUMS.ReportingName =
|
||||
Apache = "AH-64",
|
||||
Chinook = "CH-47",
|
||||
Sea_Stallion = "CH-53",
|
||||
Kiowa = "OH-58",
|
||||
Kiowa = "OH58D",
|
||||
Seahawk = "SH-60",
|
||||
Blackhawk = "UH-60",
|
||||
Sea_King = "S-61",
|
||||
@@ -2126,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.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
|
||||
-- @field #string FARP
|
||||
|
||||
@@ -2379,6 +2379,11 @@ function UTILS.IsLoadingDoorOpen( unit_name )
|
||||
return true
|
||||
end
|
||||
|
||||
if type_name == "Ka-50_3" and unit:getDrawArgumentValue(38) == 1 then
|
||||
BASE:T(unit_name .. " cockpit door is open")
|
||||
return true
|
||||
end
|
||||
|
||||
if type_name=="C-130J-30" and (unit:getDrawArgumentValue(86)==1)then
|
||||
BASE:T(unit_name.." rear doors are open")
|
||||
return true
|
||||
|
||||
@@ -1964,6 +1964,25 @@ function AIRBASE:Register(AirbaseName)
|
||||
-- Category.
|
||||
self.category=self.descriptors and self.descriptors.category or Airbase.Category.AIRDROME
|
||||
|
||||
-- Get DCS object.
|
||||
local airbase=self:GetDCSObject()
|
||||
|
||||
if airbase then
|
||||
self.objectcategory=Object.getCategory(airbase)
|
||||
else
|
||||
self.objectcategory=Object.Category.BASE
|
||||
end
|
||||
|
||||
if self.objectcategory==Object.Category.BASE then
|
||||
self.objectcategoryName="BASE"
|
||||
elseif self.objectcategory==Object.Category.STATIC then
|
||||
self.objectcategoryName="STATIC"
|
||||
elseif self.objectcategory==Object.Category.UNIT then
|
||||
self.objectcategoryName="UNIT"
|
||||
else
|
||||
self.objectcategoryName="OTHER"
|
||||
end
|
||||
|
||||
-- H2 is bugged
|
||||
--if self.AirbaseName == "H4" and self.descriptors == nil then
|
||||
--self:E("***** H4 on Syria map is currently bugged!")
|
||||
@@ -1971,24 +1990,24 @@ function AIRBASE:Register(AirbaseName)
|
||||
--end
|
||||
|
||||
-- Set category.
|
||||
if self.category==Airbase.Category.AIRDROME then
|
||||
self.isAirdrome=true
|
||||
elseif self.category==Airbase.Category.HELIPAD or self.descriptors.typeName=="FARP_SINGLE_01" then
|
||||
self.isHelipad=true
|
||||
self.category=Airbase.Category.HELIPAD
|
||||
elseif self.category==Airbase.Category.SHIP then
|
||||
self.isShip=true
|
||||
-- DCS bug: Oil rigs and gas platforms have category=2 (ship). Also they cannot be retrieved by coalition.getStaticObjects()
|
||||
if self.descriptors.typeName=="Oil rig" or self.descriptors.typeName=="Ga" then
|
||||
if self.category==Airbase.Category.AIRDROME then
|
||||
self.isAirdrome=true
|
||||
elseif self.category==Airbase.Category.HELIPAD or self.descriptors.typeName=="FARP_SINGLE_01" then
|
||||
self.isHelipad=true
|
||||
self.isShip=false
|
||||
self.category=Airbase.Category.HELIPAD
|
||||
_DATABASE:AddStatic(AirbaseName)
|
||||
elseif self.category==Airbase.Category.SHIP then
|
||||
self.isShip=true
|
||||
-- DCS bug: Oil rigs and gas platforms have category=2 (ship). Also they cannot be retrieved by coalition.getStaticObjects()
|
||||
if self.descriptors.typeName=="Oil rig" or self.descriptors.typeName=="Ga" then
|
||||
self.isHelipad=true
|
||||
self.isShip=false
|
||||
self.category=Airbase.Category.HELIPAD
|
||||
_DATABASE:AddStatic(AirbaseName)
|
||||
end
|
||||
if self:GetTypeName() == "Zell" then self.isZell = true end
|
||||
else
|
||||
self:E("ERROR: Unknown airbase category!")
|
||||
end
|
||||
if self:GetTypeName() == "Zell" then self.isZell = true end
|
||||
else
|
||||
self:E("ERROR: Unknown airbase category!")
|
||||
end
|
||||
|
||||
-- Init Runways.
|
||||
self:_InitRunways()
|
||||
@@ -2614,7 +2633,7 @@ function AIRBASE:GetMinimumBoundingCircleFromParkingSpots(mark)
|
||||
local spots = self:GetParkingSpotsVec2s()
|
||||
if #spots == 0 then return self.AirbaseZone end
|
||||
local center, radius = UTILS.GetMinimumBoundingCircle(spots)
|
||||
self.parkingCircle = ZONE_RADIUS:New(self.AirbaseName.." ParkingCircle",center,radius+50)
|
||||
self.parkingCircle = ZONE_RADIUS:New(self.AirbaseName.." ParkingCircle", center, radius+50, true)
|
||||
if mark == true then
|
||||
self.parkingCircle:DrawZone(-1,{1,0,0},1,{0,1,0},0.2,3)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user