Compare commits

..

42 Commits

Author SHA1 Message Date
Frank
8bf56b8b1a Update Airboss.lua
- Fixed AI handling (got lost in some merge with develop branch and was using FLIGHTGROUPS)
2023-07-26 16:36:44 +02:00
Applevangelist
f31741f934 #AI_ESCORT
* Improve documentation
2023-07-25 12:01:18 +02:00
Applevangelist
46258492bd #AIRBASE, #ATIS
* Additions
2023-07-23 12:37:57 +02:00
Applevangelist
6481f66e27 #MANTIS
* Added IDs for Current Hill Assets, keyword "CHM" for group names
2023-07-16 11:27:34 +02:00
Thomas
5954b8692f Update Spot.lua
Fix
2023-07-15 09:36:24 +02:00
Applevangelist
f6fdecf892 Merge remote-tracking branch 'origin/master' 2023-07-13 16:15:11 +02:00
Applevangelist
53fb77b50d #SPAWN 2023-07-13 16:15:06 +02:00
Applevangelist
04a9dc3a8c #SPAWN
* Added method to init spawn position
2023-07-13 16:13:00 +02:00
Applevangelist
10b9a32f29 #SPOT
* Fix for switching laser off and on again not follwing unit any more
2023-07-12 17:54:17 +02:00
Applevangelist
40fa929eb0 * Added omissed DetectedItem.Name found by @Nocke 2023-07-07 15:14:33 +02:00
Applevangelist
8c8ef19f01 #CONTROLLABLE
* Added TaskGroundEscort
2023-07-03 16:44:46 +02:00
Applevangelist
1eaa3d309d #SCORING
* typo
2023-07-01 13:15:59 +02:00
Applevangelist
a52cd5612a Merge remote-tracking branch 'origin/master' 2023-07-01 13:12:29 +02:00
Applevangelist
e82ed762be Merge remote-tracking branch 'origin/master' 2023-07-01 13:11:46 +02:00
Applevangelist
0bb16ec827 #AIRBASE
* Fix for nil error in finding parking for a group

#MANTIS
* Added SAM type "SHORAD" as designator

#SCORING
* fix for non local problem

#UTILS
* fix for OneLineSerialize
2023-07-01 13:11:21 +02:00
Thomas
a978420a67 Point - BRAANATO (#1969)
corrected Track to be direction of travel of bogey (self in this case)
2023-06-26 13:25:23 +02:00
Applevangelist
f59326bf10 #ATIS
* Fix for airbases which have no runways, e.g. Naqoura Syria
2023-06-24 14:03:43 +02:00
Thomas
d937ab2679 CTLD (#1967)
* Added option for troops subcategories in menu
2023-06-22 13:46:11 +02:00
Applevangelist
7164e211f2 #AIRBASE
- Nicosia unused atm
2023-06-21 10:42:35 +02:00
Applevangelist
dae78d7ac1 #Positionable, Unit - remove pcall 2023-06-16 11:06:46 +02:00
Applevangelist
254468c723 #NET
* Improvements
2023-06-15 14:51:36 +02:00
Applevangelist
71be4d99d6 #POSITIONABLE:GetRelativeCoordinate( x, y, z ) 2023-06-14 17:40:33 +02:00
Frank
f86fc845e7 Update Timer.lua
- Timer stop is using protected call now because it can crash the whole script.
2023-06-13 21:53:19 +02:00
Frank
cc907b9c14 Update Unit.lua
- UNIT:IsAlive() fixed so it is consistent with GROUP:IsAlive()
2023-06-13 19:02:55 +02:00
Applevangelist
241b2beee1 * Makes calls for GetAmmo() and GetVec3() safer with pcall()
* Small docu fix Ben-Gurion
2023-06-13 08:39:56 +02:00
Frank
12f260e857 Update Unit.lua
- Added `UNIT:IsExist` function.
2023-06-12 23:01:19 +02:00
Thomas
096d145cf9 Update Airbase.lua (#1957)
Deleted raj al … airbases #1955
2023-06-12 06:22:51 +02:00
Thomas
b3883301a2 Update Airbase.lua
Corrected enumerator for Ben-Gurion (Ben_Gurion)
2023-06-11 12:33:01 +02:00
Applevangelist
3a7521c492 #UTILS
* Sinai TIme
2023-06-10 19:08:46 +02:00
Applevangelist
caa5a96235 fix 2023-06-10 19:06:22 +02:00
Applevangelist
cee1c592ba #UTILS
* Sinai TIme
2023-06-10 19:04:40 +02:00
Frank
f1fc9f0b27 Update Utils.lua
- Added parameters time zone and magvar for Sinai map
2023-06-10 10:08:22 +02:00
Applevangelist
e9adcb0dd5 #AIRBASE
* Sinai airfield enumerator
2023-06-09 15:13:45 +02:00
Applevangelist
afe2b675e5 #RAT
* Fixes from dev
2023-06-08 13:59:59 +02:00
Applevangelist
2c14ee74b0 #SCORING
* Can leave text empty on some instances
2023-06-08 13:58:26 +02:00
Frank
f351d2a37e Merge pull request #1951 from FlightControl-Master/FF/MasterDevel
Update RAT.lua
2023-06-08 09:45:49 +02:00
Frank
4cb0e70184 Update RAT.lua
- Fixed RATMANAGER spamming due to not accounting for planned/scheduled groups
2023-06-08 09:43:11 +02:00
Applevangelist
41bb2551d3 #CTLD
* Ensure new menus can be build if player changes helos
2023-06-03 12:34:18 +02:00
Applevangelist
55ed394782 #UNIT #CTLD
* Stabilize that sometimes a unit coordinate cannot be found
2023-06-02 08:44:14 +02:00
Applevangelist
dd7a883a33 Fixes 2023-06-01 10:02:51 +02:00
Applevangelist
f7acbc3928 #CSAR
* Corrected flare distance to kms
2023-05-30 07:38:19 +02:00
Applevangelist
2318578126 #SPAWN
* Logic fix for the last parameter of `NewFromTemplate()`
2023-05-28 15:27:34 +02:00
20 changed files with 825 additions and 247 deletions

View File

@@ -147,8 +147,8 @@
-- @image Escorting.JPG -- @image Escorting.JPG
---
--- @type AI_ESCORT -- @type AI_ESCORT
-- @extends AI.AI_Formation#AI_FORMATION -- @extends AI.AI_Formation#AI_FORMATION
@@ -168,10 +168,13 @@
-- --
-- -- First find the GROUP object and the CLIENT object. -- -- First find the GROUP object and the CLIENT object.
-- local EscortUnit = CLIENT:FindByName( "Unit Name" ) -- The Unit Name is the name of the unit flagged with the skill Client in the mission editor. -- local EscortUnit = CLIENT:FindByName( "Unit Name" ) -- The Unit Name is the name of the unit flagged with the skill Client in the mission editor.
-- local EscortGroup = GROUP:FindByName( "Group Name" ) -- The Group Name is the name of the group that will escort the Escort Client. -- local EscortGroup = SET_GROUP:New():FilterPrefixes("Escort"):FilterOnce() -- The the group name of the escorts contains "Escort".
-- --
-- -- Now use these 2 objects to construct the new EscortPlanes object. -- -- Now use these 2 objects to construct the new EscortPlanes object.
-- EscortPlanes = AI_ESCORT:New( EscortUnit, EscortGroup, "Desert", "Welcome to the mission. You are escorted by a plane with code name 'Desert', which can be instructed through the F10 radio menu." ) -- EscortPlanes = AI_ESCORT:New( EscortUnit, EscortGroup, "Desert", "Welcome to the mission. You are escorted by a plane with code name 'Desert', which can be instructed through the F10 radio menu." )
-- EscortPlanes:MenusAirplanes() -- create menus for airplanes
-- EscortPlanes:__Start(2)
--
-- --
-- @field #AI_ESCORT -- @field #AI_ESCORT
AI_ESCORT = { AI_ESCORT = {
@@ -189,7 +192,7 @@ AI_ESCORT = {
TaskPoints = {} TaskPoints = {}
} }
--- @field Functional.Detection#DETECTION_AREAS -- @field Functional.Detection#DETECTION_AREAS
AI_ESCORT.Detection = nil AI_ESCORT.Detection = nil
--- MENUPARAM type --- MENUPARAM type
@@ -211,10 +214,14 @@ AI_ESCORT.Detection = nil
-- --
-- -- First find the GROUP object and the CLIENT object. -- -- First find the GROUP object and the CLIENT object.
-- local EscortUnit = CLIENT:FindByName( "Unit Name" ) -- The Unit Name is the name of the unit flagged with the skill Client in the mission editor. -- local EscortUnit = CLIENT:FindByName( "Unit Name" ) -- The Unit Name is the name of the unit flagged with the skill Client in the mission editor.
-- local EscortGroup = GROUP:FindByName( "Group Name" ) -- The Group Name is the name of the group that will escort the Escort Client. -- local EscortGroup = SET_GROUP:New():FilterPrefixes("Escort"):FilterOnce() -- The the group name of the escorts contains "Escort".
-- --
-- -- Now use these 2 objects to construct the new EscortPlanes object. -- -- Now use these 2 objects to construct the new EscortPlanes object.
-- EscortPlanes = AI_ESCORT:New( EscortUnit, EscortGroup, "Desert", "Welcome to the mission. You are escorted by a plane with code name 'Desert', which can be instructed through the F10 radio menu." ) -- EscortPlanes = AI_ESCORT:New( EscortUnit, EscortGroup, "Desert", "Welcome to the mission. You are escorted by a plane with code name 'Desert', which can be instructed through the F10 radio menu." )
-- EscortPlanes:MenusAirplanes() -- create menus for airplanes
-- EscortPlanes:__Start(2)
--
--
function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing ) function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing )
local self = BASE:Inherit( self, AI_FORMATION:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing ) ) -- #AI_ESCORT local self = BASE:Inherit( self, AI_FORMATION:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing ) ) -- #AI_ESCORT
@@ -231,6 +238,13 @@ function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing )
self.EscortBriefing = EscortBriefing self.EscortBriefing = EscortBriefing
self.Menu = {} self.Menu = {}
self.Menu.HoldAtEscortPosition = self.Menu.HoldAtEscortPosition or {}
self.Menu.HoldAtLeaderPosition = self.Menu.HoldAtLeaderPosition or {}
self.Menu.Flare = self.Menu.Flare or {}
self.Menu.Smoke = self.Menu.Smoke or {}
self.Menu.Targets = self.Menu.Targets or {}
self.Menu.ROE = self.Menu.ROE or {}
self.Menu.ROT = self.Menu.ROT or {}
-- if not EscortBriefing then -- if not EscortBriefing then
-- EscortGroup:MessageToClient( EscortGroup:GetCategoryName() .. " '" .. EscortName .. "' (" .. EscortGroup:GetCallsign() .. ") reporting! " .. -- EscortGroup:MessageToClient( EscortGroup:GetCategoryName() .. " '" .. EscortName .. "' (" .. EscortGroup:GetCallsign() .. ") reporting! " ..
@@ -250,7 +264,7 @@ function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing )
EscortGroupSet:ForEachGroup( EscortGroupSet:ForEachGroup(
--- @param Core.Group#GROUP EscortGroup -- @param Core.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
-- Set EscortGroup known at EscortUnit. -- Set EscortGroup known at EscortUnit.
if not self.PlayerUnit._EscortGroups then if not self.PlayerUnit._EscortGroups then
@@ -325,14 +339,14 @@ function AI_ESCORT:_InitEscortRoute( EscortGroup )
end end
--- @param #AI_ESCORT self -- @param #AI_ESCORT self
-- @param Core.Set#SET_GROUP EscortGroupSet -- @param Core.Set#SET_GROUP EscortGroupSet
function AI_ESCORT:onafterStart( EscortGroupSet ) function AI_ESCORT:onafterStart( EscortGroupSet )
self:F() self:F()
EscortGroupSet:ForEachGroup( EscortGroupSet:ForEachGroup(
--- @param Core.Group#GROUP EscortGroup -- @param Core.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
EscortGroup:WayPointInitialize() EscortGroup:WayPointInitialize()
@@ -370,7 +384,7 @@ function AI_ESCORT:onafterStart( EscortGroupSet )
self:_InitFlightMenus() self:_InitFlightMenus()
self.EscortGroupSet:ForSomeGroupAlive( self.EscortGroupSet:ForSomeGroupAlive(
--- @param Core.Group#GROUP EscortGroup -- @param Core.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
self:_InitEscortMenus( EscortGroup ) self:_InitEscortMenus( EscortGroup )
@@ -378,7 +392,7 @@ function AI_ESCORT:onafterStart( EscortGroupSet )
self:SetFlightModeFormation( EscortGroup ) self:SetFlightModeFormation( EscortGroup )
--- @param #AI_ESCORT self -- @param #AI_ESCORT self
-- @param Core.Event#EVENTDATA EventData -- @param Core.Event#EVENTDATA EventData
function EscortGroup:OnEventDeadOrCrash( EventData ) function EscortGroup:OnEventDeadOrCrash( EventData )
self:F( { "EventDead", EventData } ) self:F( { "EventDead", EventData } )
@@ -394,14 +408,14 @@ function AI_ESCORT:onafterStart( EscortGroupSet )
end end
--- @param #AI_ESCORT self -- @param #AI_ESCORT self
-- @param Core.Set#SET_GROUP EscortGroupSet -- @param Core.Set#SET_GROUP EscortGroupSet
function AI_ESCORT:onafterStop( EscortGroupSet ) function AI_ESCORT:onafterStop( EscortGroupSet )
self:F() self:F()
EscortGroupSet:ForEachGroup( EscortGroupSet:ForEachGroup(
--- @param Core.Group#GROUP EscortGroup -- @param Core.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
EscortGroup:WayPointInitialize() EscortGroup:WayPointInitialize()
@@ -550,7 +564,7 @@ function AI_ESCORT:SetFlightMenuFormation( Formation )
local MenuFlightFormationID = MENU_GROUP_COMMAND:New( self.PlayerGroup, Formation, FlightMenuFormation, local MenuFlightFormationID = MENU_GROUP_COMMAND:New( self.PlayerGroup, Formation, FlightMenuFormation,
function ( self, Formation, ... ) function ( self, Formation, ... )
self.EscortGroupSet:ForSomeGroupAlive( self.EscortGroupSet:ForSomeGroupAlive(
--- @param Core.Group#GROUP EscortGroup -- @param Core.Group#GROUP EscortGroup
function( EscortGroup, self, Formation, Arguments ) function( EscortGroup, self, Formation, Arguments )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
self:E({FormationID=FormationID}) self:E({FormationID=FormationID})
@@ -764,7 +778,7 @@ end
function AI_ESCORT:SetFlightMenuHoldAtEscortPosition() function AI_ESCORT:SetFlightMenuHoldAtEscortPosition()
for _, MenuHoldAtEscortPosition in pairs( self.Menu.HoldAtEscortPosition ) do for _, MenuHoldAtEscortPosition in pairs( self.Menu.HoldAtEscortPosition or {} ) do
local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu ) local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu )
local FlightMenuHoldPosition = MENU_GROUP_COMMAND local FlightMenuHoldPosition = MENU_GROUP_COMMAND
@@ -785,7 +799,7 @@ end
function AI_ESCORT:SetEscortMenuHoldAtEscortPosition( EscortGroup ) function AI_ESCORT:SetEscortMenuHoldAtEscortPosition( EscortGroup )
for _, HoldAtEscortPosition in pairs( self.Menu.HoldAtEscortPosition ) do for _, HoldAtEscortPosition in pairs( self.Menu.HoldAtEscortPosition or {}) do
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
local EscortGroupName = EscortGroup:GetName() local EscortGroupName = EscortGroup:GetName()
local EscortMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", EscortGroup.EscortMenu ) local EscortMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", EscortGroup.EscortMenu )
@@ -853,7 +867,7 @@ end
function AI_ESCORT:SetFlightMenuHoldAtLeaderPosition() function AI_ESCORT:SetFlightMenuHoldAtLeaderPosition()
for _, MenuHoldAtLeaderPosition in pairs( self.Menu.HoldAtLeaderPosition ) do for _, MenuHoldAtLeaderPosition in pairs( self.Menu.HoldAtLeaderPosition or {}) do
local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu ) local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu )
local FlightMenuHoldAtLeaderPosition = MENU_GROUP_COMMAND local FlightMenuHoldAtLeaderPosition = MENU_GROUP_COMMAND
@@ -874,7 +888,7 @@ end
function AI_ESCORT:SetEscortMenuHoldAtLeaderPosition( EscortGroup ) function AI_ESCORT:SetEscortMenuHoldAtLeaderPosition( EscortGroup )
for _, HoldAtLeaderPosition in pairs( self.Menu.HoldAtLeaderPosition ) do for _, HoldAtLeaderPosition in pairs( self.Menu.HoldAtLeaderPosition or {}) do
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
local EscortGroupName = EscortGroup:GetName() local EscortGroupName = EscortGroup:GetName()
@@ -999,7 +1013,7 @@ end
function AI_ESCORT:SetFlightMenuFlare() function AI_ESCORT:SetFlightMenuFlare()
for _, MenuFlare in pairs( self.Menu.Flare) do for _, MenuFlare in pairs( self.Menu.Flare or {}) do
local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu ) local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu )
local FlightMenuFlare = MENU_GROUP:New( self.PlayerGroup, MenuFlare.MenuText, FlightMenuReportNavigation ) local FlightMenuFlare = MENU_GROUP:New( self.PlayerGroup, MenuFlare.MenuText, FlightMenuReportNavigation )
@@ -1014,7 +1028,7 @@ end
function AI_ESCORT:SetEscortMenuFlare( EscortGroup ) function AI_ESCORT:SetEscortMenuFlare( EscortGroup )
for _, MenuFlare in pairs( self.Menu.Flare) do for _, MenuFlare in pairs( self.Menu.Flare or {}) do
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
local EscortGroupName = EscortGroup:GetName() local EscortGroupName = EscortGroup:GetName()
@@ -1059,7 +1073,7 @@ end
function AI_ESCORT:SetFlightMenuSmoke() function AI_ESCORT:SetFlightMenuSmoke()
for _, MenuSmoke in pairs( self.Menu.Smoke) do for _, MenuSmoke in pairs( self.Menu.Smoke or {}) do
local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu ) local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu )
local FlightMenuSmoke = MENU_GROUP:New( self.PlayerGroup, MenuSmoke.MenuText, FlightMenuReportNavigation ) local FlightMenuSmoke = MENU_GROUP:New( self.PlayerGroup, MenuSmoke.MenuText, FlightMenuReportNavigation )
@@ -1076,7 +1090,7 @@ end
function AI_ESCORT:SetEscortMenuSmoke( EscortGroup ) function AI_ESCORT:SetEscortMenuSmoke( EscortGroup )
for _, MenuSmoke in pairs( self.Menu.Smoke) do for _, MenuSmoke in pairs( self.Menu.Smoke or {}) do
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
local EscortGroupName = EscortGroup:GetName() local EscortGroupName = EscortGroup:GetName()
@@ -1169,7 +1183,7 @@ function AI_ESCORT:SetFlightMenuTargets()
local FlightMenuAttackNearbyAir = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Attack nearest airborne targets", self.FlightMenuAttack, AI_ESCORT._FlightAttackNearestTarget, self, self.__Enum.ReportType.Air ):SetTag( "Attack" ) local FlightMenuAttackNearbyAir = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Attack nearest airborne targets", self.FlightMenuAttack, AI_ESCORT._FlightAttackNearestTarget, self, self.__Enum.ReportType.Air ):SetTag( "Attack" )
local FlightMenuAttackNearbyGround = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Attack nearest ground targets", self.FlightMenuAttack, AI_ESCORT._FlightAttackNearestTarget, self, self.__Enum.ReportType.Ground ):SetTag( "Attack" ) local FlightMenuAttackNearbyGround = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Attack nearest ground targets", self.FlightMenuAttack, AI_ESCORT._FlightAttackNearestTarget, self, self.__Enum.ReportType.Ground ):SetTag( "Attack" )
for _, MenuTargets in pairs( self.Menu.Targets) do for _, MenuTargets in pairs( self.Menu.Targets or {}) do
MenuTargets.FlightReportTargetsScheduler = SCHEDULER:New( self, self._FlightReportTargetsScheduler, {}, MenuTargets.Interval, MenuTargets.Interval ) MenuTargets.FlightReportTargetsScheduler = SCHEDULER:New( self, self._FlightReportTargetsScheduler, {}, MenuTargets.Interval, MenuTargets.Interval )
end end
@@ -1179,7 +1193,7 @@ end
function AI_ESCORT:SetEscortMenuTargets( EscortGroup ) function AI_ESCORT:SetEscortMenuTargets( EscortGroup )
for _, MenuTargets in pairs( self.Menu.Targets) do for _, MenuTargets in pairs( self.Menu.Targets or {} or {}) do
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
local EscortGroupName = EscortGroup:GetName() local EscortGroupName = EscortGroup:GetName()
--local EscortMenuReportTargets = MENU_GROUP:New( self.PlayerGroup, "Report targets", EscortGroup.EscortMenu ) --local EscortMenuReportTargets = MENU_GROUP:New( self.PlayerGroup, "Report targets", EscortGroup.EscortMenu )
@@ -1231,7 +1245,7 @@ function AI_ESCORT:MenuAssistedAttack()
self:F() self:F()
self.EscortGroupSet:ForSomeGroupAlive( self.EscortGroupSet:ForSomeGroupAlive(
--- @param Core.Group#GROUP EscortGroup -- @param Core.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
if not EscortGroup:IsAir() then if not EscortGroup:IsAir() then
-- Request assistance from other escorts. -- Request assistance from other escorts.
@@ -1246,7 +1260,7 @@ end
function AI_ESCORT:SetFlightMenuROE() function AI_ESCORT:SetFlightMenuROE()
for _, MenuROE in pairs( self.Menu.ROE) do for _, MenuROE in pairs( self.Menu.ROE or {}) do
local FlightMenuROE = MENU_GROUP:New( self.PlayerGroup, "Rule Of Engagement", self.FlightMenu ) local FlightMenuROE = MENU_GROUP:New( self.PlayerGroup, "Rule Of Engagement", self.FlightMenu )
local FlightMenuROEHoldFire = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Hold fire", FlightMenuROE, AI_ESCORT._FlightROEHoldFire, self, "Holding weapons!" ) local FlightMenuROEHoldFire = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Hold fire", FlightMenuROE, AI_ESCORT._FlightROEHoldFire, self, "Holding weapons!" )
@@ -1261,7 +1275,7 @@ end
function AI_ESCORT:SetEscortMenuROE( EscortGroup ) function AI_ESCORT:SetEscortMenuROE( EscortGroup )
for _, MenuROE in pairs( self.Menu.ROE) do for _, MenuROE in pairs( self.Menu.ROE or {}) do
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
local EscortGroupName = EscortGroup:GetName() local EscortGroupName = EscortGroup:GetName()
@@ -1302,7 +1316,7 @@ end
function AI_ESCORT:SetFlightMenuROT() function AI_ESCORT:SetFlightMenuROT()
for _, MenuROT in pairs( self.Menu.ROT) do for _, MenuROT in pairs( self.Menu.ROT or {}) do
local FlightMenuROT = MENU_GROUP:New( self.PlayerGroup, "Reaction On Threat", self.FlightMenu ) local FlightMenuROT = MENU_GROUP:New( self.PlayerGroup, "Reaction On Threat", self.FlightMenu )
local FlightMenuROTNoReaction = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Fight until death", FlightMenuROT, AI_ESCORT._FlightROTNoReaction, self, "Fighting until death!" ) local FlightMenuROTNoReaction = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Fight until death", FlightMenuROT, AI_ESCORT._FlightROTNoReaction, self, "Fighting until death!" )
@@ -1317,7 +1331,7 @@ end
function AI_ESCORT:SetEscortMenuROT( EscortGroup ) function AI_ESCORT:SetEscortMenuROT( EscortGroup )
for _, MenuROT in pairs( self.Menu.ROT) do for _, MenuROT in pairs( self.Menu.ROT or {}) do
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
local EscortGroupName = EscortGroup:GetName() local EscortGroupName = EscortGroup:GetName()
@@ -1375,7 +1389,7 @@ function AI_ESCORT:SetEscortMenuResumeMission( EscortGroup )
end end
--- @param #AI_ESCORT self -- @param #AI_ESCORT self
-- @param Wrapper.Group#GROUP OrbitGroup -- @param Wrapper.Group#GROUP OrbitGroup
-- @param Wrapper.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
-- @param #number OrbitHeight -- @param #number OrbitHeight
@@ -1419,7 +1433,7 @@ function AI_ESCORT:_HoldPosition( OrbitGroup, EscortGroup, OrbitHeight, OrbitSec
end end
--- @param #AI_ESCORT self -- @param #AI_ESCORT self
-- @param Wrapper.Group#GROUP OrbitGroup -- @param Wrapper.Group#GROUP OrbitGroup
-- @param #number OrbitHeight -- @param #number OrbitHeight
-- @param #number OrbitSeconds -- @param #number OrbitSeconds
@@ -1428,7 +1442,7 @@ function AI_ESCORT:_FlightHoldPosition( OrbitGroup, OrbitHeight, OrbitSeconds )
local EscortUnit = self.PlayerUnit local EscortUnit = self.PlayerUnit
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
--- @param Core.Group#GROUP EscortGroup -- @param Core.Group#GROUP EscortGroup
function( EscortGroup, OrbitGroup ) function( EscortGroup, OrbitGroup )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
if OrbitGroup == nil then if OrbitGroup == nil then
@@ -1456,7 +1470,7 @@ end
function AI_ESCORT:_FlightJoinUp() function AI_ESCORT:_FlightJoinUp()
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
--- @param Core.Group#GROUP EscortGroup -- @param Core.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
self:_JoinUp( EscortGroup ) self:_JoinUp( EscortGroup )
@@ -1483,7 +1497,7 @@ end
function AI_ESCORT:_FlightFormationTrail( XStart, XSpace, YStart ) function AI_ESCORT:_FlightFormationTrail( XStart, XSpace, YStart )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
--- @param Core.Group#GROUP EscortGroup -- @param Core.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
self:_EscortFormationTrail( EscortGroup, XStart, XSpace, YStart ) self:_EscortFormationTrail( EscortGroup, XStart, XSpace, YStart )
@@ -1510,7 +1524,7 @@ end
function AI_ESCORT:_FlightFormationStack( XStart, XSpace, YStart, YSpace ) function AI_ESCORT:_FlightFormationStack( XStart, XSpace, YStart, YSpace )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
--- @param Core.Group#GROUP EscortGroup -- @param Core.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
self:_EscortFormationStack( EscortGroup, XStart, XSpace, YStart, YSpace ) self:_EscortFormationStack( EscortGroup, XStart, XSpace, YStart, YSpace )
@@ -1533,7 +1547,7 @@ end
function AI_ESCORT:_FlightFlare( Color, Message ) function AI_ESCORT:_FlightFlare( Color, Message )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
--- @param Core.Group#GROUP EscortGroup -- @param Core.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
self:_Flare( EscortGroup, Color, Message ) self:_Flare( EscortGroup, Color, Message )
@@ -1556,7 +1570,7 @@ end
function AI_ESCORT:_FlightSmoke( Color, Message ) function AI_ESCORT:_FlightSmoke( Color, Message )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
--- @param Core.Group#GROUP EscortGroup -- @param Core.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
self:_Smoke( EscortGroup, Color, Message ) self:_Smoke( EscortGroup, Color, Message )
@@ -1587,7 +1601,7 @@ end
function AI_ESCORT:_FlightSwitchReportNearbyTargets( ReportTargets ) function AI_ESCORT:_FlightSwitchReportNearbyTargets( ReportTargets )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
--- @param Core.Group#GROUP EscortGroup -- @param Core.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
self:_EscortSwitchReportNearbyTargets( EscortGroup, ReportTargets ) self:_EscortSwitchReportNearbyTargets( EscortGroup, ReportTargets )
@@ -1679,7 +1693,7 @@ function AI_ESCORT:_ScanTargets( ScanDuration )
end end
--- @param Wrapper.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
-- @param #AI_ESCORT self -- @param #AI_ESCORT self
function AI_ESCORT.___Resume( EscortGroup, self ) function AI_ESCORT.___Resume( EscortGroup, self )
@@ -1701,7 +1715,7 @@ function AI_ESCORT.___Resume( EscortGroup, self )
end end
--- @param #AI_ESCORT self -- @param #AI_ESCORT self
-- @param Wrapper.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
-- @param #number WayPoint -- @param #number WayPoint
function AI_ESCORT:_ResumeMission( EscortGroup, WayPoint ) function AI_ESCORT:_ResumeMission( EscortGroup, WayPoint )
@@ -1723,7 +1737,7 @@ function AI_ESCORT:_ResumeMission( EscortGroup, WayPoint )
end end
--- @param #AI_ESCORT self -- @param #AI_ESCORT self
-- @param Wrapper.Group#GROUP EscortGroup The escort group that will attack the detected item. -- @param Wrapper.Group#GROUP EscortGroup The escort group that will attack the detected item.
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem -- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
function AI_ESCORT:_AttackTarget( EscortGroup, DetectedItem ) function AI_ESCORT:_AttackTarget( EscortGroup, DetectedItem )
@@ -1743,7 +1757,7 @@ function AI_ESCORT:_AttackTarget( EscortGroup, DetectedItem )
local AttackUnitTasks = {} local AttackUnitTasks = {}
DetectedSet:ForEachUnit( DetectedSet:ForEachUnit(
--- @param Wrapper.Unit#UNIT DetectedUnit -- @param Wrapper.Unit#UNIT DetectedUnit
function( DetectedUnit, Tasks ) function( DetectedUnit, Tasks )
if DetectedUnit:IsAlive() then if DetectedUnit:IsAlive() then
AttackUnitTasks[#AttackUnitTasks+1] = EscortGroup:TaskAttackUnit( DetectedUnit ) AttackUnitTasks[#AttackUnitTasks+1] = EscortGroup:TaskAttackUnit( DetectedUnit )
@@ -1767,7 +1781,7 @@ function AI_ESCORT:_AttackTarget( EscortGroup, DetectedItem )
local Tasks = {} local Tasks = {}
DetectedSet:ForEachUnit( DetectedSet:ForEachUnit(
--- @param Wrapper.Unit#UNIT DetectedUnit -- @param Wrapper.Unit#UNIT DetectedUnit
function( DetectedUnit, Tasks ) function( DetectedUnit, Tasks )
if DetectedUnit:IsAlive() then if DetectedUnit:IsAlive() then
Tasks[#Tasks+1] = EscortGroup:TaskFireAtPoint( DetectedUnit:GetVec2(), 50 ) Tasks[#Tasks+1] = EscortGroup:TaskFireAtPoint( DetectedUnit:GetVec2(), 50 )
@@ -1795,7 +1809,7 @@ end
function AI_ESCORT:_FlightAttackTarget( DetectedItem ) function AI_ESCORT:_FlightAttackTarget( DetectedItem )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
--- @param Core.Group#GROUP EscortGroup -- @param Core.Group#GROUP EscortGroup
function( EscortGroup, DetectedItem ) function( EscortGroup, DetectedItem )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
self:_AttackTarget( EscortGroup, DetectedItem ) self:_AttackTarget( EscortGroup, DetectedItem )
@@ -1842,7 +1856,7 @@ end
--- ---
--- @param #AI_ESCORT self -- @param #AI_ESCORT self
-- @param Wrapper.Group#GROUP EscortGroup The escort group that will attack the detected item. -- @param Wrapper.Group#GROUP EscortGroup The escort group that will attack the detected item.
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem -- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
function AI_ESCORT:_AssistTarget( EscortGroup, DetectedItem ) function AI_ESCORT:_AssistTarget( EscortGroup, DetectedItem )
@@ -1854,7 +1868,7 @@ function AI_ESCORT:_AssistTarget( EscortGroup, DetectedItem )
local Tasks = {} local Tasks = {}
DetectedSet:ForEachUnit( DetectedSet:ForEachUnit(
--- @param Wrapper.Unit#UNIT DetectedUnit -- @param Wrapper.Unit#UNIT DetectedUnit
function( DetectedUnit, Tasks ) function( DetectedUnit, Tasks )
if DetectedUnit:IsAlive() then if DetectedUnit:IsAlive() then
Tasks[#Tasks+1] = EscortGroup:TaskFireAtPoint( DetectedUnit:GetVec2(), 50 ) Tasks[#Tasks+1] = EscortGroup:TaskFireAtPoint( DetectedUnit:GetVec2(), 50 )
@@ -1881,7 +1895,7 @@ end
function AI_ESCORT:_FlightROEHoldFire( EscortROEMessage ) function AI_ESCORT:_FlightROEHoldFire( EscortROEMessage )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
--- @param Wrapper.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
self:_ROE( EscortGroup, EscortGroup.OptionROEHoldFire, EscortROEMessage ) self:_ROE( EscortGroup, EscortGroup.OptionROEHoldFire, EscortROEMessage )
end end
@@ -1890,7 +1904,7 @@ end
function AI_ESCORT:_FlightROEOpenFire( EscortROEMessage ) function AI_ESCORT:_FlightROEOpenFire( EscortROEMessage )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
--- @param Wrapper.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
self:_ROE( EscortGroup, EscortGroup.OptionROEOpenFire, EscortROEMessage ) self:_ROE( EscortGroup, EscortGroup.OptionROEOpenFire, EscortROEMessage )
end end
@@ -1899,7 +1913,7 @@ end
function AI_ESCORT:_FlightROEReturnFire( EscortROEMessage ) function AI_ESCORT:_FlightROEReturnFire( EscortROEMessage )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
--- @param Wrapper.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
self:_ROE( EscortGroup, EscortGroup.OptionROEReturnFire, EscortROEMessage ) self:_ROE( EscortGroup, EscortGroup.OptionROEReturnFire, EscortROEMessage )
end end
@@ -1908,7 +1922,7 @@ end
function AI_ESCORT:_FlightROEWeaponFree( EscortROEMessage ) function AI_ESCORT:_FlightROEWeaponFree( EscortROEMessage )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
--- @param Wrapper.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
self:_ROE( EscortGroup, EscortGroup.OptionROEWeaponFree, EscortROEMessage ) self:_ROE( EscortGroup, EscortGroup.OptionROEWeaponFree, EscortROEMessage )
end end
@@ -1924,7 +1938,7 @@ end
function AI_ESCORT:_FlightROTNoReaction( EscortROTMessage ) function AI_ESCORT:_FlightROTNoReaction( EscortROTMessage )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
--- @param Wrapper.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
self:_ROT( EscortGroup, EscortGroup.OptionROTNoReaction, EscortROTMessage ) self:_ROT( EscortGroup, EscortGroup.OptionROTNoReaction, EscortROTMessage )
end end
@@ -1933,7 +1947,7 @@ end
function AI_ESCORT:_FlightROTPassiveDefense( EscortROTMessage ) function AI_ESCORT:_FlightROTPassiveDefense( EscortROTMessage )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
--- @param Wrapper.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
self:_ROT( EscortGroup, EscortGroup.OptionROTPassiveDefense, EscortROTMessage ) self:_ROT( EscortGroup, EscortGroup.OptionROTPassiveDefense, EscortROTMessage )
end end
@@ -1942,7 +1956,7 @@ end
function AI_ESCORT:_FlightROTEvadeFire( EscortROTMessage ) function AI_ESCORT:_FlightROTEvadeFire( EscortROTMessage )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
--- @param Wrapper.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
self:_ROT( EscortGroup, EscortGroup.OptionROTEvadeFire, EscortROTMessage ) self:_ROT( EscortGroup, EscortGroup.OptionROTEvadeFire, EscortROTMessage )
end end
@@ -1951,7 +1965,7 @@ end
function AI_ESCORT:_FlightROTVertical( EscortROTMessage ) function AI_ESCORT:_FlightROTVertical( EscortROTMessage )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
--- @param Wrapper.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
self:_ROT( EscortGroup, EscortGroup.OptionROTVertical, EscortROTMessage ) self:_ROT( EscortGroup, EscortGroup.OptionROTVertical, EscortROTMessage )
end end
@@ -2178,5 +2192,3 @@ function AI_ESCORT:_FlightReportTargetsScheduler()
return false return false
end end

View File

@@ -1124,7 +1124,7 @@ end
-- @param #string AirbaseName Name of the airbase. -- @param #string AirbaseName Name of the airbase.
-- @return #number Category. -- @return #number Category.
function DATABASE:GetCategoryFromAirbase( AirbaseName ) function DATABASE:GetCategoryFromAirbase( AirbaseName )
return self.AIRBASES[AirbaseName]:GetCategory() return self.AIRBASES[AirbaseName]:GetAirbaseCategory()
end end

View File

@@ -2945,7 +2945,12 @@ do -- COORDINATE
alttext = "very low" alttext = "very low"
end end
local track = UTILS.BearingToCardinal(bearing) or "North" -- corrected Track to be direction of travel of bogey (self in this case)
local track = "Maneuver"
if self.Heading then
track = UTILS.BearingToCardinal(self.Heading) or "North"
end
if rangeNM > 3 then if rangeNM > 3 then
if SSML then -- google says "oh" instead of zero, be aware if SSML then -- google says "oh" instead of zero, be aware

View File

@@ -163,6 +163,16 @@
-- --
-- * @{#SPAWN.InitArray}(): Make groups visible before they are actually activated, and order these groups like a battalion in an array. -- * @{#SPAWN.InitArray}(): Make groups visible before they are actually activated, and order these groups like a battalion in an array.
-- --
-- ### Group initial position - if wanted different from template position, for use with e.g. @{#SPAWN.SpawnScheduled}().
--
-- * @{#SPAWN.InitPositionCoordinate}(): Set initial position of group via a COORDINATE.
-- * @{#SPAWN.InitPositionVec2}(): Set initial position of group via a VEC2.
--
-- ### Set the positions of a group's units to absolute positions, or relative positions to unit No. 1
--
-- * @{#SPAWN.InitSetUnitRelativePositions}(): Spawn the UNITs of this group with individual relative positions to unit #1 and individual headings.
-- * @{#SPAWN.InitSetUnitAbsolutePositions}(): Spawn the UNITs of this group with individual absolute positions and individual headings.
--
-- ### Position randomization -- ### Position randomization
-- --
-- * @{#SPAWN.InitRandomizePosition}(): Randomizes the position of @{Wrapper.Group}s that are spawned within a **radius band**, given an Outer and Inner radius, from the point that the spawn happens. -- * @{#SPAWN.InitRandomizePosition}(): Randomizes the position of @{Wrapper.Group}s that are spawned within a **radius band**, given an Outer and Inner radius, from the point that the spawn happens.
@@ -268,7 +278,7 @@ SPAWN = {
-- @type SPAWN.Takeoff -- @type SPAWN.Takeoff
-- @extends Wrapper.Group#GROUP.Takeoff -- @extends Wrapper.Group#GROUP.Takeoff
--- @field #SPAWN.Takeoff Takeoff -- @field #SPAWN.Takeoff Takeoff
SPAWN.Takeoff = { SPAWN.Takeoff = {
Air = 1, Air = 1,
Runway = 2, Runway = 2,
@@ -276,7 +286,7 @@ SPAWN.Takeoff = {
Cold = 4, Cold = 4,
} }
--- @type SPAWN.SpawnZoneTable -- @type SPAWN.SpawnZoneTable
-- @list <Core.Zone#ZONE_BASE> SpawnZone -- @list <Core.Zone#ZONE_BASE> SpawnZone
--- Creates the main object to spawn a @{Wrapper.Group} defined in the DCS ME. --- Creates the main object to spawn a @{Wrapper.Group} defined in the DCS ME.
@@ -388,9 +398,9 @@ end
--- Creates a new SPAWN instance to create new groups based on the provided template. This will also register the template for future use. --- Creates a new SPAWN instance to create new groups based on the provided template. This will also register the template for future use.
-- @param #SPAWN self -- @param #SPAWN self
-- @param #table SpawnTemplate is the Template of the Group. This must be a valid Group Template structure - see [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_func_addGroup)! -- @param #table SpawnTemplate is the Template of the Group. This must be a valid Group Template structure - see [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_func_addGroup)!
-- @param #string SpawnTemplatePrefix [Mandatory] is the name of the template and the prefix of the GROUP on spawn. -- @param #string SpawnTemplatePrefix [Mandatory] is the name of the template and the prefix of the GROUP on spawn. The name in the template **will** be overwritten!
-- @param #string SpawnAliasPrefix [Optional] is the prefix that will be given to the GROUP on spawn. -- @param #string SpawnAliasPrefix [Optional] is the prefix that will be given to the GROUP on spawn.
-- @param #boolean MooseNaming [Optional] If false, skip the Moose naming additions (like groupname#001-01) - you need to ensure yourself no duplicate group names exist! -- @param #boolean NoMooseNamingPostfix [Optional] If true, skip the Moose naming additions (like groupname#001-01) - **but** you need to ensure yourself no duplicate group names exist!
-- @return #SPAWN self -- @return #SPAWN self
-- @usage -- @usage
-- -- Spawn a P51 Mustang from scratch -- -- Spawn a P51 Mustang from scratch
@@ -491,7 +501,7 @@ end
-- ) -- )
-- mustang:Spawn() -- mustang:Spawn()
-- --
function SPAWN:NewFromTemplate( SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPrefix, MooseNaming ) function SPAWN:NewFromTemplate( SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPrefix, NoMooseNamingPostfix )
local self = BASE:Inherit( self, BASE:New() ) local self = BASE:Inherit( self, BASE:New() )
self:F( { SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPrefix } ) self:F( { SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPrefix } )
--if SpawnAliasPrefix == nil or SpawnAliasPrefix == "" then --if SpawnAliasPrefix == nil or SpawnAliasPrefix == "" then
@@ -532,7 +542,10 @@ function SPAWN:NewFromTemplate( SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPr
self.SpawnInitModex = nil self.SpawnInitModex = nil
self.SpawnInitAirbase = nil self.SpawnInitAirbase = nil
self.TweakedTemplate = true -- Check if the user is using self made template. self.TweakedTemplate = true -- Check if the user is using self made template.
self.MooseNameing = MooseNaming or true self.MooseNameing = true
if NoMooseNamingPostfix == true then
self.MooseNameing = false
end
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned. self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
else else
@@ -1044,7 +1057,7 @@ end
--- This method provides the functionality to randomize the spawning of the Groups at a given list of zones of different types. --- This method provides the functionality to randomize the spawning of the Groups at a given list of zones of different types.
-- @param #SPAWN self -- @param #SPAWN self
-- @param #table SpawnZoneTable A table with @{Core.Zone} objects. If this table is given, then each spawn will be executed within the given list of @{Core.Zone}s objects. -- @param #table SpawnZoneTable A table with @{Core.Zone} objects. If this table is given, then each spawn will be executed within the given list of @{Core.Zone}s objects.
-- @return #SPAWN -- @return #SPAWN self
-- @usage -- @usage
-- --
-- -- Create a zone table of the 2 zones. -- -- Create a zone table of the 2 zones.
@@ -1074,6 +1087,31 @@ function SPAWN:InitRandomizeZones( SpawnZoneTable )
return self return self
end end
--- This method sets a spawn position for the group that is different from the location of the template.
-- @param #SPAWN self
-- @param Core.Point#COORDINATE Coordinate The position to spawn from
-- @return #SPAWN self
function SPAWN:InitPositionCoordinate(Coordinate)
self:T( { self.SpawnTemplatePrefix, Coordinate:GetVec2()} )
self:InitPositionVec2(Coordinate:GetVec2())
return self
end
--- This method sets a spawn position for the group that is different from the location of the template.
-- @param #SPAWN self
-- @param DCS#Vec2 Vec2 The position to spawn from
-- @return #SPAWN self
function SPAWN:InitPositionVec2(Vec2)
self:T( { self.SpawnTemplatePrefix, Vec2} )
self.SpawnInitPosition = Vec2
self.SpawnFromNewPosition = true
self:I("MaxGroups:"..self.SpawnMaxGroups)
for SpawnGroupID = 1, self.SpawnMaxGroups do
self:_SetInitialPosition( SpawnGroupID )
end
return self
end
--- For planes and helicopters, when these groups go home and land on their home airbases and FARPs, they normally would taxi to the parking spot, shut-down their engines and wait forever until the Group is removed by the runtime environment. --- For planes and helicopters, when these groups go home and land on their home airbases and FARPs, they normally would taxi to the parking spot, shut-down their engines and wait forever until the Group is removed by the runtime environment.
-- This method is used to re-spawn automatically (so no extra call is needed anymore) the same group after it has landed. -- This method is used to re-spawn automatically (so no extra call is needed anymore) the same group after it has landed.
-- This will enable a spawned group to be re-spawned after it lands, until it is destroyed... -- This will enable a spawned group to be re-spawned after it lands, until it is destroyed...
@@ -1374,6 +1412,11 @@ function SPAWN:SpawnWithIndex( SpawnIndex, NoBirth )
if self:_GetSpawnIndex( SpawnIndex ) then if self:_GetSpawnIndex( SpawnIndex ) then
if self.SpawnFromNewPosition then
self:_SetInitialPosition( SpawnIndex )
end
if self.SpawnGroups[self.SpawnIndex].Visible then if self.SpawnGroups[self.SpawnIndex].Visible then
self.SpawnGroups[self.SpawnIndex].Group:Activate() self.SpawnGroups[self.SpawnIndex].Group:Activate()
else else
@@ -1611,7 +1654,7 @@ end
-- @param #number SpawnTime The time interval defined in seconds between each new spawn of new groups. -- @param #number SpawnTime The time interval defined in seconds between each new spawn of new groups.
-- @param #number SpawnTimeVariation The variation to be applied on the defined time interval between each new spawn. -- @param #number SpawnTimeVariation The variation to be applied on the defined time interval between each new spawn.
-- The variation is a number between 0 and 1, representing the % of variation to be applied on the time interval. -- The variation is a number between 0 and 1, representing the % of variation to be applied on the time interval.
-- @param #boolen WithDelay Do not spawn the **first** group immediately, but delay the spawn as per the calculation below. -- @param #boolean WithDelay Do not spawn the **first** group immediately, but delay the spawn as per the calculation below.
-- Effectively the same as @{InitDelayOn}(). -- Effectively the same as @{InitDelayOn}().
-- @return #SPAWN self -- @return #SPAWN self
-- @usage -- @usage
@@ -3125,6 +3168,10 @@ function SPAWN:_GetTemplate( SpawnTemplatePrefix )
local SpawnTemplate = nil local SpawnTemplate = nil
if _DATABASE.Templates.Groups[SpawnTemplatePrefix] == nil then
error( 'No Template exists for SpawnTemplatePrefix = ' .. SpawnTemplatePrefix )
end
local Template = _DATABASE.Templates.Groups[SpawnTemplatePrefix].Template local Template = _DATABASE.Templates.Groups[SpawnTemplatePrefix].Template
self:F( { Template = Template } ) self:F( { Template = Template } )
@@ -3158,8 +3205,10 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) -- R2.2
if self.TweakedTemplate ~= nil and self.TweakedTemplate == true then if self.TweakedTemplate ~= nil and self.TweakedTemplate == true then
BASE:I( "WARNING: You are using a tweaked template." ) BASE:I( "WARNING: You are using a tweaked template." )
SpawnTemplate = self.SpawnTemplate SpawnTemplate = self.SpawnTemplate
if self.MooseNameing then if self.MooseNameing == true then
SpawnTemplate.name = self:SpawnGroupName( SpawnIndex ) SpawnTemplate.name = self:SpawnGroupName( SpawnIndex )
else
SpawnTemplate.name = self:SpawnGroupName()
end end
else else
SpawnTemplate = self:_GetTemplate( SpawnTemplatePrefix ) SpawnTemplate = self:_GetTemplate( SpawnTemplatePrefix )
@@ -3291,6 +3340,57 @@ function SPAWN:_RandomizeTemplate( SpawnIndex )
return self return self
end end
--- Private method that sets the DCS#Vec2 where the Group will be spawned.
-- @param #SPAWN self
-- @param #number SpawnIndex
-- @return #SPAWN self
function SPAWN:_SetInitialPosition( SpawnIndex )
self:T( { self.SpawnTemplatePrefix, SpawnIndex, self.SpawnRandomizeZones } )
if self.SpawnFromNewPosition then
self:T( "Preparing Spawn at Vec2 ", self.SpawnInitPosition )
local SpawnVec2 = self.SpawnInitPosition
self:T( { SpawnVec2 = SpawnVec2 } )
local SpawnTemplate = self.SpawnGroups[SpawnIndex].SpawnTemplate
SpawnTemplate.route = SpawnTemplate.route or {}
SpawnTemplate.route.points = SpawnTemplate.route.points or {}
SpawnTemplate.route.points[1] = SpawnTemplate.route.points[1] or {}
SpawnTemplate.route.points[1].x = SpawnTemplate.route.points[1].x or 0
SpawnTemplate.route.points[1].y = SpawnTemplate.route.points[1].y or 0
self:T( { Route = SpawnTemplate.route } )
for UnitID = 1, #SpawnTemplate.units do
local UnitTemplate = SpawnTemplate.units[UnitID]
self:T( 'Before Translation SpawnTemplate.units[' .. UnitID .. '].x = ' .. UnitTemplate.x .. ', SpawnTemplate.units[' .. UnitID .. '].y = ' .. UnitTemplate.y )
local SX = UnitTemplate.x
local SY = UnitTemplate.y
local BX = SpawnTemplate.route.points[1].x
local BY = SpawnTemplate.route.points[1].y
local TX = SpawnVec2.x + (SX - BX)
local TY = SpawnVec2.y + (SY - BY)
UnitTemplate.x = TX
UnitTemplate.y = TY
-- TODO: Manage altitude based on landheight...
-- SpawnTemplate.units[UnitID].alt = SpawnVec2:
self:T( 'After Translation SpawnTemplate.units[' .. UnitID .. '].x = ' .. UnitTemplate.x .. ', SpawnTemplate.units[' .. UnitID .. '].y = ' .. UnitTemplate.y )
end
SpawnTemplate.route.points[1].x = SpawnVec2.x
SpawnTemplate.route.points[1].y = SpawnVec2.y
SpawnTemplate.x = SpawnVec2.x
SpawnTemplate.y = SpawnVec2.y
end
return self
end
--- Private method that randomizes the @{Core.Zone}s where the Group will be spawned. --- Private method that randomizes the @{Core.Zone}s where the Group will be spawned.
-- @param #SPAWN self -- @param #SPAWN self
-- @param #number SpawnIndex -- @param #number SpawnIndex
@@ -3410,7 +3510,7 @@ end
-- TODO Need to delete this... _DATABASE does this now ... -- TODO Need to delete this... _DATABASE does this now ...
--- @param #SPAWN self -- @param #SPAWN self
-- @param Core.Event#EVENTDATA EventData -- @param Core.Event#EVENTDATA EventData
function SPAWN:_OnBirth( EventData ) function SPAWN:_OnBirth( EventData )
self:F( self.SpawnTemplatePrefix ) self:F( self.SpawnTemplatePrefix )
@@ -3430,7 +3530,7 @@ function SPAWN:_OnBirth( EventData )
end end
--- @param #SPAWN self -- @param #SPAWN self
-- @param Core.Event#EVENTDATA EventData -- @param Core.Event#EVENTDATA EventData
function SPAWN:_OnDeadOrCrash( EventData ) function SPAWN:_OnDeadOrCrash( EventData )
self:F( self.SpawnTemplatePrefix ) self:F( self.SpawnTemplatePrefix )

View File

@@ -33,7 +33,8 @@
do do
--- @type SPOT ---
-- @type SPOT
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
@@ -228,7 +229,8 @@ do
-- @param #number LaserCode Laser code. -- @param #number LaserCode Laser code.
-- @param #number Duration Duration of lasing in seconds. -- @param #number Duration Duration of lasing in seconds.
function SPOT:onafterLaseOn( From, Event, To, Target, LaserCode, Duration ) function SPOT:onafterLaseOn( From, Event, To, Target, LaserCode, Duration )
self:F( { "LaseOn", Target, LaserCode, Duration } ) self:T({From, Event, To})
self:T2( { "LaseOn", Target, LaserCode, Duration } )
local function StopLase( self ) local function StopLase( self )
self:LaseOff() self:LaseOff()
@@ -256,6 +258,8 @@ do
self:HandleEvent( EVENTS.Dead ) self:HandleEvent( EVENTS.Dead )
self:__Lasing( -1 ) self:__Lasing( -1 )
return self
end end
@@ -268,7 +272,7 @@ do
-- @param #number LaserCode Laser code. -- @param #number LaserCode Laser code.
-- @param #number Duration Duration of lasing in seconds. -- @param #number Duration Duration of lasing in seconds.
function SPOT:onafterLaseOnCoordinate(From, Event, To, Coordinate, LaserCode, Duration) function SPOT:onafterLaseOnCoordinate(From, Event, To, Coordinate, LaserCode, Duration)
self:F( { "LaseOnCoordinate", Coordinate, LaserCode, Duration } ) self:T2( { "LaseOnCoordinate", Coordinate, LaserCode, Duration } )
local function StopLase( self ) local function StopLase( self )
self:LaseOff() self:LaseOff()
@@ -290,12 +294,14 @@ do
end end
self:__Lasing(-1) self:__Lasing(-1)
return self
end end
--- @param #SPOT self ---
-- @param #SPOT self
-- @param Core.Event#EVENTDATA EventData -- @param Core.Event#EVENTDATA EventData
function SPOT:OnEventDead(EventData) function SPOT:OnEventDead(EventData)
self:F( { Dead = EventData.IniDCSUnitName, Target = self.Target } ) self:T2( { Dead = EventData.IniDCSUnitName, Target = self.Target } )
if self.Target then if self.Target then
if EventData.IniDCSUnitName == self.TargetName then if EventData.IniDCSUnitName == self.TargetName then
self:F( {"Target dead ", self.TargetName } ) self:F( {"Target dead ", self.TargetName } )
@@ -309,42 +315,51 @@ do
self:LaseOff() self:LaseOff()
end end
end end
return self
end end
--- @param #SPOT self ---
-- @param #SPOT self
-- @param From -- @param From
-- @param Event -- @param Event
-- @param To -- @param To
function SPOT:onafterLasing( From, Event, To ) function SPOT:onafterLasing( From, Event, To )
self:T({From, Event, To})
if self.Target and self.Target:IsAlive() then if self.Lasing then
self.SpotIR:setPoint( self.Target:GetPointVec3():AddY(1):AddY(math.random(-100,100)/100):AddX(math.random(-100,100)/100):GetVec3() ) if self.Target and self.Target:IsAlive() then
self.SpotLaser:setPoint( self.Target:GetPointVec3():AddY(1):GetVec3() )
self:__Lasing( -0.2 )
elseif self.TargetCoord then
-- Wiggle the IR spot a bit. self.SpotIR:setPoint( self.Target:GetPointVec3():AddY(1):AddY(math.random(-100,100)/100):AddX(math.random(-100,100)/100):GetVec3() )
local irvec3={x=self.TargetCoord.x+math.random(-100,100)/100, y=self.TargetCoord.y+math.random(-100,100)/100, z=self.TargetCoord.z} --#DCS.Vec3 self.SpotLaser:setPoint( self.Target:GetPointVec3():AddY(1):GetVec3() )
local lsvec3={x=self.TargetCoord.x, y=self.TargetCoord.y, z=self.TargetCoord.z} --#DCS.Vec3
self.SpotIR:setPoint(irvec3) self:__Lasing(0.2)
self.SpotLaser:setPoint(lsvec3) elseif self.TargetCoord then
self:__Lasing(-0.25) -- Wiggle the IR spot a bit.
else local irvec3={x=self.TargetCoord.x+math.random(-100,100)/100, y=self.TargetCoord.y+math.random(-100,100)/100, z=self.TargetCoord.z} --#DCS.Vec3
self:F( { "Target is not alive", self.Target:IsAlive() } ) local lsvec3={x=self.TargetCoord.x, y=self.TargetCoord.y, z=self.TargetCoord.z} --#DCS.Vec3
self.SpotIR:setPoint(irvec3)
self.SpotLaser:setPoint(lsvec3)
self:__Lasing(0.2)
else
self:F( { "Target is not alive", self.Target:IsAlive() } )
end
end end
return self
end end
--- @param #SPOT self ---
-- @param #SPOT self
-- @param From -- @param From
-- @param Event -- @param Event
-- @param To -- @param To
-- @return #SPOT -- @return #SPOT
function SPOT:onafterLaseOff( From, Event, To ) function SPOT:onafterLaseOff( From, Event, To )
self:T({From, Event, To})
self:F( {"Stopped lasing for ", self.Target and self.Target:GetName() or "coord", SpotIR = self.SportIR, SpotLaser = self.SpotLaser } ) self:T2( {"Stopped lasing for ", self.Target and self.Target:GetName() or "coord", SpotIR = self.SportIR, SpotLaser = self.SpotLaser } )
self.Lasing = false self.Lasing = false

View File

@@ -107,7 +107,7 @@ _TIMERID=0
--- TIMER class version. --- TIMER class version.
-- @field #string version -- @field #string version
TIMER.version="0.1.2" TIMER.version="0.2.0"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
@@ -222,7 +222,20 @@ function TIMER:Stop(Delay)
-- Remove timer function. -- Remove timer function.
self:T(self.lid..string.format("Stopping timer by removing timer function after %d calls!", self.ncalls)) self:T(self.lid..string.format("Stopping timer by removing timer function after %d calls!", self.ncalls))
timer.removeFunction(self.tid)
-- We use a pcall here because if the DCS timer does not exist any more, it crashes the whole script!
local status=pcall(
function ()
timer.removeFunction(self.tid)
end
)
-- Debug messages.
if status then
self:T2(self.lid..string.format("Stopped timer!"))
else
self:E(self.lid..string.format("WARNING: Could not remove timer function! isrunning=%s", tostring(self.isrunning)))
end
-- Not running any more. -- Not running any more.
self.isrunning=false self.isrunning=false

View File

@@ -2354,6 +2354,7 @@ do -- DETECTION_TYPES
if not DetectedItem then if not DetectedItem then
DetectedItem = self:AddDetectedItem( "TYPE", DetectedTypeName ) DetectedItem = self:AddDetectedItem( "TYPE", DetectedTypeName )
DetectedItem.TypeName = DetectedTypeName DetectedItem.TypeName = DetectedTypeName
DetectedItem.Name = DetectedUnitName -- fix by @Nocke
end end
DetectedItem.Set:AddUnit( DetectedUnit ) DetectedItem.Set:AddUnit( DetectedUnit )

View File

@@ -22,7 +22,7 @@
-- @module Functional.Mantis -- @module Functional.Mantis
-- @image Functional.Mantis.jpg -- @image Functional.Mantis.jpg
-- --
-- Last Update: Oct 2022 -- Last Update: July 2023
------------------------------------------------------------------------- -------------------------------------------------------------------------
--- **MANTIS** class, extends Core.Base#BASE --- **MANTIS** class, extends Core.Base#BASE
@@ -104,9 +104,13 @@
-- * Silkworm (though strictly speaking this is a surface to ship missile) -- * Silkworm (though strictly speaking this is a surface to ship missile)
-- * SA-2, SA-3, SA-5, SA-6, SA-7, SA-8, SA-9, SA-10, SA-11, SA-13, SA-15, SA-19 -- * SA-2, SA-3, SA-5, SA-6, SA-7, SA-8, SA-9, SA-10, SA-11, SA-13, SA-15, SA-19
-- * From HDS (see note on HDS below): SA-2, SA-3, SA-10B, SA-10C, SA-12, SA-17, SA-20A, SA-20B, SA-23, HQ-2 -- * From HDS (see note on HDS below): SA-2, SA-3, SA-10B, SA-10C, SA-12, SA-17, SA-20A, SA-20B, SA-23, HQ-2
--
-- * From SMA: RBS98M, RBS70, RBS90, RBS90M, RBS103A, RBS103B, RBS103AM, RBS103BM, Lvkv9040M -- * From SMA: RBS98M, RBS70, RBS90, RBS90M, RBS103A, RBS103B, RBS103AM, RBS103BM, Lvkv9040M
-- **NOTE** If you are using the Swedish Military Assets (SMA), please note that the **group name** for RBS-SAM types also needs to contain the keyword "SMA" -- **NOTE** If you are using the Swedish Military Assets (SMA), please note that the **group name** for RBS-SAM types also needs to contain the keyword "SMA"
-- --
-- * From CH: 2S38, PantsirS1, PantsirS2, PGL-625, HQ-17A, M903PAC2, M903PAC3, TorM2, TorM2K, TorM2M, NASAMS3-AMRAAMER, NASAMS3-AIM9X2, C-RAM, PGZ-09, S350-9M100, S350-9M96D
-- **NOTE** If you are using the Military Assets by Currenthill (CH), please note that the **group name** for CH-SAM types also needs to contain the keyword "CHM"
--
-- Following the example started above, an SA-6 site group name should start with "Red SAM SA-6" then, or a blue Patriot installation with e.g. "Blue SAM Patriot". -- Following the example started above, an SA-6 site group name should start with "Red SAM SA-6" then, or a blue Patriot installation with e.g. "Blue SAM Patriot".
-- **NOTE** If you are using the High-Digit-Sam Mod, please note that the **group name** for the following SAM types also needs to contain the keyword "HDS": -- **NOTE** If you are using the High-Digit-Sam Mod, please note that the **group name** for the following SAM types also needs to contain the keyword "HDS":
-- --
@@ -369,6 +373,7 @@ MANTIS.SamData = {
["SA-20A"] = { Range=150, Blindspot=5, Height=27, Type="Long" , Radar="S-300PMU1"}, ["SA-20A"] = { Range=150, Blindspot=5, Height=27, Type="Long" , Radar="S-300PMU1"},
["SA-20B"] = { Range=200, Blindspot=4, Height=27, Type="Long" , Radar="S-300PMU2"}, ["SA-20B"] = { Range=200, Blindspot=4, Height=27, Type="Long" , Radar="S-300PMU2"},
["HQ-2"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" }, ["HQ-2"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" },
["SHORAD"] = { Range=3, Blindspot=0, Height=3, Type="Short", Radar="Igla" }
} }
--- SAM data HDS --- SAM data HDS
@@ -415,6 +420,35 @@ MANTIS.SamDataSMA = {
["Lvkv9040M SMA"] = { Range=4, Blindspot=0, Height=2.5, Type="Short", Radar="LvKv9040" }, ["Lvkv9040M SMA"] = { Range=4, Blindspot=0, Height=2.5, Type="Short", Radar="LvKv9040" },
} }
--- SAM data CH
-- @type MANTIS.SamDataCH
-- @field #number Range Max firing range in km
-- @field #number Blindspot no-firing range (green circle)
-- @field #number Height Max firing height in km
-- @field #string Type #MANTIS.SamType of SAM, i.e. SHORT, MEDIUM or LONG (range)
-- @field #string Radar Radar typename on unit level (used as key)
MANTIS.SamDataCH = {
-- units from CH (Military Assets by Currenthill)
-- https://www.currenthill.com/
-- group name MUST contain CHM to ID launcher type correctly!
["2S38 CH"] = { Range=8, Blindspot=0.5, Height=6, Type="Short", Radar="2S38" },
["PantsirS1 CH"] = { Range=20, Blindspot=1.2, Height=15, Type="Short", Radar="PantsirS1" },
["PantsirS2 CH"] = { Range=30, Blindspot=1.2, Height=18, Type="Medium", Radar="PantsirS2" },
["PGL-625 CH"] = { Range=10, Blindspot=0.5, Height=5, Type="Short", Radar="PGL_625" },
["HQ-17A CH"] = { Range=20, Blindspot=1.5, Height=10, Type="Short", Radar="HQ17A" },
["M903PAC2 CH"] = { Range=160, Blindspot=3, Height=24.5, Type="Long", Radar="MIM104_M903_PAC2" },
["M903PAC3 CH"] = { Range=120, Blindspot=1, Height=40, Type="Long", Radar="MIM104_M903_PAC3" },
["TorM2 CH"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2" },
["TorM2K CH"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2K" },
["TorM2M CH"] = { Range=16, Blindspot=1, Height=10, Type="Short", Radar="TorM2M" },
["NASAMS3-AMRAAMER CH"] = { Range=50, Blindspot=2, Height=35.7, Type="Medium", Radar="CH_NASAMS3_LN_AMRAAM_ER" },
["NASAMS3-AIM9X2 CH"] = { Range=20, Blindspot=0.2, Height=18, Type="Short", Radar="CH_NASAMS3_LN_AIM9X2" },
["C-RAM CH"] = { Range=2, Blindspot=0, Height=2, Type="Short", Radar="CH_Centurion_C_RAM" },
["PGZ-09 CH"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="CH_PGZ09" },
["S350-9M100 CH"] = { Range=15, Blindspot=1.5, Height=8, Type="Short", Radar="CH_S350_50P6_9M100" },
["S350-9M96D CH"] = { Range=150, Blindspot=2.5, Height=30, Type="Long", Radar="CH_S350_50P6_9M96D" },
}
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- MANTIS System -- MANTIS System
----------------------------------------------------------------------- -----------------------------------------------------------------------
@@ -578,7 +612,7 @@ do
-- TODO Version -- TODO Version
-- @field #string version -- @field #string version
self.version="0.8.9" self.version="0.8.11"
self:I(string.format("***** Starting MANTIS Version %s *****", self.version)) self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
--- FSM Functions --- --- FSM Functions ---
@@ -1299,11 +1333,12 @@ do
-- @param #string grpname Name of the group -- @param #string grpname Name of the group
-- @param #boolean mod HDS mod flag -- @param #boolean mod HDS mod flag
-- @param #boolean sma SMA mod flag -- @param #boolean sma SMA mod flag
-- @param #boolean chm CH mod flag
-- @return #number range Max firing range -- @return #number range Max firing range
-- @return #number height Max firing height -- @return #number height Max firing height
-- @return #string type Long, medium or short range -- @return #string type Long, medium or short range
-- @return #number blind "blind" spot -- @return #number blind "blind" spot
function MANTIS:_GetSAMDataFromUnits(grpname,mod,sma) function MANTIS:_GetSAMDataFromUnits(grpname,mod,sma,chm)
self:T(self.lid.."_GetSAMRangeFromUnits") self:T(self.lid.."_GetSAMRangeFromUnits")
local found = false local found = false
local range = self.checkradius local range = self.checkradius
@@ -1318,8 +1353,10 @@ do
SAMData = self.SamDataHDS SAMData = self.SamDataHDS
elseif sma then elseif sma then
SAMData = self.SamDataSMA SAMData = self.SamDataSMA
elseif chm then
SAMData = self.SamDataCH
end end
--self:I("Looking to auto-match for "..grpname) --self:T("Looking to auto-match for "..grpname)
for _,_unit in pairs(units) do for _,_unit in pairs(units) do
local unit = _unit -- Wrapper.Unit#UNIT local unit = _unit -- Wrapper.Unit#UNIT
local type = string.lower(unit:GetTypeName()) local type = string.lower(unit:GetTypeName())
@@ -1364,10 +1401,13 @@ do
local found = false local found = false
local HDSmod = false local HDSmod = false
local SMAMod = false local SMAMod = false
local CHMod = false
if string.find(grpname,"HDS",1,true) then if string.find(grpname,"HDS",1,true) then
HDSmod = true HDSmod = true
elseif string.find(grpname,"SMA",1,true) then elseif string.find(grpname,"SMA",1,true) then
SMAMod = true SMAMod = true
elseif string.find(grpname,"CHM",1,true) then
CHMod = true
end end
if self.automode then if self.automode then
for idx,entry in pairs(self.SamData) do for idx,entry in pairs(self.SamData) do
@@ -1386,8 +1426,8 @@ do
end end
end end
-- secondary filter if not found -- secondary filter if not found
if (not found and self.automode) or HDSmod or SMAMod then if (not found and self.automode) or HDSmod or SMAMod or CHMod then
range, height, type = self:_GetSAMDataFromUnits(grpname,HDSmod,SMAMod) range, height, type = self:_GetSAMDataFromUnits(grpname,HDSmod,SMAMod,CHMod)
elseif not found then elseif not found then
self:E(self.lid .. string.format("*****Could not match radar data for %s! Will default to midrange values!",grpname)) self:E(self.lid .. string.format("*****Could not match radar data for %s! Will default to midrange values!",grpname))
end end

View File

@@ -5490,7 +5490,7 @@ function RAT:_ATCInit(airports_map)
if not RAT.ATC.init then if not RAT.ATC.init then
local text local text
text="Starting RAT ATC.\nSimultanious = "..RAT.ATC.Nclearance.."\n".."Delay = "..RAT.ATC.delay text="Starting RAT ATC.\nSimultanious = "..RAT.ATC.Nclearance.."\n".."Delay = "..RAT.ATC.delay
BASE:T(RAT.id..text) BASE:T(RAT.id..text)
RAT.ATC.init=true RAT.ATC.init=true
for _,ap in pairs(airports_map) do for _,ap in pairs(airports_map) do
local name=ap:GetName() local name=ap:GetName()
@@ -5671,9 +5671,9 @@ function RAT:_ATCClearForLanding(airport, flight)
-- Debug message. -- Debug message.
local text1=string.format("ATC %s: Flight %s cleared for landing (flag=%d).", airport, flight, flagvalue) local text1=string.format("ATC %s: Flight %s cleared for landing (flag=%d).", airport, flight, flagvalue)
if string.find(flight,"#") then if string.find(flight,"#") then
flight = string.match(flight,"^(.+)#") flight = string.match(flight,"^(.+)#")
end end
local text2=string.format("ATC %s: Flight %s you are cleared for landing.", airport, flight) local text2=string.format("ATC %s: Flight %s you are cleared for landing.", airport, flight)
BASE:T( RAT.id..text1) BASE:T( RAT.id..text1)
MESSAGE:New(text2, 10):ToAllIf(RAT.ATC.messages) MESSAGE:New(text2, 10):ToAllIf(RAT.ATC.messages)
@@ -5716,9 +5716,9 @@ function RAT:_ATCFlightLanded(name)
local text1=string.format("ATC %s: Flight %s landed. Tholding = %i:%02d, Tfinal = %i:%02d.", dest, name, Thold/60, Thold%60, Tfinal/60, Tfinal%60) local text1=string.format("ATC %s: Flight %s landed. Tholding = %i:%02d, Tfinal = %i:%02d.", dest, name, Thold/60, Thold%60, Tfinal/60, Tfinal%60)
local text2=string.format("ATC %s: Number of flights still on final %d.", dest, RAT.ATC.airport[dest].Nonfinal) local text2=string.format("ATC %s: Number of flights still on final %d.", dest, RAT.ATC.airport[dest].Nonfinal)
local text3=string.format("ATC %s: Traffic report: Number of planes landed in total %d. Flights/hour = %3.2f.", dest, RAT.ATC.airport[dest].traffic, TrafficPerHour) local text3=string.format("ATC %s: Traffic report: Number of planes landed in total %d. Flights/hour = %3.2f.", dest, RAT.ATC.airport[dest].traffic, TrafficPerHour)
if string.find(name,"#") then if string.find(name,"#") then
name = string.match(name,"^(.+)#") name = string.match(name,"^(.+)#")
end end
local text4=string.format("ATC %s: Flight %s landed. Welcome to %s.", dest, name, dest) local text4=string.format("ATC %s: Flight %s landed. Welcome to %s.", dest, name, dest)
BASE:T(RAT.id..text1) BASE:T(RAT.id..text1)
BASE:T(RAT.id..text2) BASE:T(RAT.id..text2)
@@ -5832,6 +5832,7 @@ RATMANAGER={
rat={}, rat={},
name={}, name={},
alive={}, alive={},
planned={},
min={}, min={},
nrat=0, nrat=0,
ntot=nil, ntot=nil,
@@ -5880,6 +5881,7 @@ function RATMANAGER:Add(ratobject,min)
self.rat[self.nrat]=ratobject self.rat[self.nrat]=ratobject
self.alive[self.nrat]=0 self.alive[self.nrat]=0
self.planned[self.nrat]=0
self.name[self.nrat]=ratobject.alias self.name[self.nrat]=ratobject.alias
self.min[self.nrat]=min or 1 self.min[self.nrat]=min or 1
@@ -6020,11 +6022,25 @@ function RATMANAGER:_Manage()
for i=1,self.nrat do for i=1,self.nrat do
for j=1,N[i] do for j=1,N[i] do
time=time+self.dTspawn time=time+self.dTspawn
SCHEDULER:New(nil, RAT._SpawnWithRoute, {self.rat[i]}, time) self.planned[i]=self.planned[i]+1
SCHEDULER:New(nil, RATMANAGER._Spawn, {self, i}, time)
end end
end end
end end
--- Instantly starts the RAT manager and spawns the initial random number RAT groups for each RAT object.
-- @param #RATMANAGER self
-- @param #RATMANAGER RATMANAGER self object.
-- @param #number i Index.
function RATMANAGER:_Spawn(i)
local rat=self.rat[i] --#RAT
rat:_SpawnWithRoute()
self.planned[i]=self.planned[i]-1
end
--- Counts the number of alive RAT objects. --- Counts the number of alive RAT objects.
-- @param #RATMANAGER self -- @param #RATMANAGER self
function RATMANAGER:_Count() function RATMANAGER:_Count()
@@ -6053,7 +6069,7 @@ function RATMANAGER:_Count()
ntotal=ntotal+n ntotal=ntotal+n
-- Debug output. -- Debug output.
local text=string.format("Number of alive groups of %s = %d", self.name[i], n) local text=string.format("Number of alive groups of %s = %d, planned=%d", self.name[i], n, self.planned[i])
self:T(RATMANAGER.id..text) self:T(RATMANAGER.id..text)
end end
@@ -6083,9 +6099,10 @@ function RATMANAGER:_RollDice(nrat,ntot,min,alive)
local M={} local M={}
local P={} local P={}
for i=1,nrat do for i=1,nrat do
local a=alive[i]+self.planned[i]
N[#N+1]=0 N[#N+1]=0
M[#M+1]=math.max(alive[i], min[i]) M[#M+1]=math.max(a, min[i])
P[#P+1]=math.max(min[i]-alive[i],0) P[#P+1]=math.max(min[i]-a,0)
end end
-- Min/max group arrays. -- Min/max group arrays.
@@ -6102,7 +6119,7 @@ function RATMANAGER:_RollDice(nrat,ntot,min,alive)
-- Number of new groups to be added. -- Number of new groups to be added.
local nnew=ntot local nnew=ntot
for i=1,nrat do for i=1,nrat do
nnew=nnew-alive[i] nnew=nnew-alive[i]-self.planned[i]
end end
for i=1,nrat-1 do for i=1,nrat-1 do
@@ -6134,7 +6151,7 @@ function RATMANAGER:_RollDice(nrat,ntot,min,alive)
end end
-- Debug info -- Debug info
self:T3(string.format("RATMANAGER: i=%d, alive=%d, min=%d, mini=%d, maxi=%d, add=%d, sumN=%d, sumP=%d", j, alive[j], min[j], mini[j], maxi[j], N[j],sN, sP)) self:T3(string.format("RATMANAGER: i=%d, alive=%d, planned=%d, min=%d, mini=%d, maxi=%d, add=%d, sumN=%d, sumP=%d", j, alive[j], self.planned[i], min[j], mini[j], maxi[j], N[j],sN, sP))
end end
@@ -6149,7 +6166,7 @@ function RATMANAGER:_RollDice(nrat,ntot,min,alive)
-- Debug info -- Debug info
local text=RATMANAGER.id.."\n" local text=RATMANAGER.id.."\n"
for i=1,nrat do for i=1,nrat do
text=text..string.format("%s: i=%d, alive=%d, min=%d, mini=%d, maxi=%d, add=%d\n", self.name[i], i, alive[i], min[i], mini[i], maxi[i], N[i]) text=text..string.format("%s: i=%d, alive=%d, planned=%d, min=%d, mini=%d, maxi=%d, add=%d\n", self.name[i], i, alive[i], self.planned[i], min[i], mini[i], maxi[i], N[i])
end end
text=text..string.format("Total # of groups to add = %d", sum(N, done)) text=text..string.format("Total # of groups to add = %d", sum(N, done))
self:T(text) self:T(text)

View File

@@ -715,11 +715,11 @@ function SCORING:AddGoalScorePlayer( PlayerName, GoalTag, Text, Score )
PlayerData.Goals[GoalTag] = PlayerData.Goals[GoalTag] or { Score = 0 } PlayerData.Goals[GoalTag] = PlayerData.Goals[GoalTag] or { Score = 0 }
PlayerData.Goals[GoalTag].Score = PlayerData.Goals[GoalTag].Score + Score PlayerData.Goals[GoalTag].Score = PlayerData.Goals[GoalTag].Score + Score
PlayerData.Score = PlayerData.Score + Score PlayerData.Score = PlayerData.Score + Score
if Text then
MESSAGE:NewType( self.DisplayMessagePrefix .. Text, MESSAGE:NewType( self.DisplayMessagePrefix .. Text,
MESSAGE.Type.Information ) MESSAGE.Type.Information )
:ToAll() :ToAll()
end
self:ScoreCSV( PlayerName, "", "GOAL_" .. string.upper( GoalTag ), 1, Score, nil ) self:ScoreCSV( PlayerName, "", "GOAL_" .. string.upper( GoalTag ), 1, Score, nil )
end end
end end
@@ -738,7 +738,7 @@ function SCORING:AddGoalScore( PlayerUnit, GoalTag, Text, Score )
local PlayerName = PlayerUnit:GetPlayerName() local PlayerName = PlayerUnit:GetPlayerName()
self:F( { PlayerUnit.UnitName, PlayerName, GoalTag, Text, Score } ) self:T2( { PlayerUnit.UnitName, PlayerName, GoalTag, Text, Score } )
-- PlayerName can be nil, if the Unit with the player crashed or due to another reason. -- PlayerName can be nil, if the Unit with the player crashed or due to another reason.
if PlayerName then if PlayerName then
@@ -748,10 +748,11 @@ function SCORING:AddGoalScore( PlayerUnit, GoalTag, Text, Score )
PlayerData.Goals[GoalTag].Score = PlayerData.Goals[GoalTag].Score + Score PlayerData.Goals[GoalTag].Score = PlayerData.Goals[GoalTag].Score + Score
PlayerData.Score = PlayerData.Score + Score PlayerData.Score = PlayerData.Score + Score
MESSAGE:NewType( self.DisplayMessagePrefix .. Text, if Text then
MESSAGE:NewType( self.DisplayMessagePrefix .. Text,
MESSAGE.Type.Information ) MESSAGE.Type.Information )
:ToAll() :ToAll()
end
self:ScoreCSV( PlayerName, "", "GOAL_" .. string.upper( GoalTag ), 1, Score, PlayerUnit:GetName() ) self:ScoreCSV( PlayerName, "", "GOAL_" .. string.upper( GoalTag ), 1, Score, PlayerUnit:GetName() )
end end
end end
@@ -785,10 +786,11 @@ function SCORING:_AddMissionTaskScore( Mission, PlayerUnit, Text, Score )
PlayerData.Score = self.Players[PlayerName].Score + Score PlayerData.Score = self.Players[PlayerName].Score + Score
PlayerData.Mission[MissionName].ScoreTask = self.Players[PlayerName].Mission[MissionName].ScoreTask + Score PlayerData.Mission[MissionName].ScoreTask = self.Players[PlayerName].Mission[MissionName].ScoreTask + Score
MESSAGE:NewType( self.DisplayMessagePrefix .. Mission:GetText() .. " : " .. Text .. " Score: " .. Score, if Text then
MESSAGE.Type.Information ) MESSAGE:NewType( self.DisplayMessagePrefix .. Mission:GetText() .. " : " .. Text .. " Score: " .. Score,
:ToAll() MESSAGE.Type.Information )
:ToAll()
end
self:ScoreCSV( PlayerName, "", "TASK_" .. MissionName:gsub( ' ', '_' ), 1, Score, PlayerUnit:GetName() ) self:ScoreCSV( PlayerName, "", "TASK_" .. MissionName:gsub( ' ', '_' ), 1, Score, PlayerUnit:GetName() )
end end
end end
@@ -821,7 +823,9 @@ function SCORING:_AddMissionGoalScore( Mission, PlayerName, Text, Score )
PlayerData.Score = self.Players[PlayerName].Score + Score PlayerData.Score = self.Players[PlayerName].Score + Score
PlayerData.Mission[MissionName].ScoreTask = self.Players[PlayerName].Mission[MissionName].ScoreTask + Score PlayerData.Mission[MissionName].ScoreTask = self.Players[PlayerName].Mission[MissionName].ScoreTask + Score
MESSAGE:NewType( string.format( "%s%s: %s! Player %s receives %d score!", self.DisplayMessagePrefix, Mission:GetText(), Text, PlayerName, Score ), MESSAGE.Type.Information ):ToAll() if Text then
MESSAGE:NewType( string.format( "%s%s: %s! Player %s receives %d score!", self.DisplayMessagePrefix, Mission:GetText(), Text, PlayerName, Score ), MESSAGE.Type.Information ):ToAll()
end
self:ScoreCSV( PlayerName, "", "TASK_" .. MissionName:gsub( ' ', '_' ), 1, Score ) self:ScoreCSV( PlayerName, "", "TASK_" .. MissionName:gsub( ' ', '_' ), 1, Score )
end end
@@ -848,10 +852,11 @@ function SCORING:_AddMissionScore( Mission, Text, Score )
PlayerData.Score = PlayerData.Score + Score PlayerData.Score = PlayerData.Score + Score
PlayerData.Mission[MissionName].ScoreMission = PlayerData.Mission[MissionName].ScoreMission + Score PlayerData.Mission[MissionName].ScoreMission = PlayerData.Mission[MissionName].ScoreMission + Score
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' has " .. Text .. " in " .. Mission:GetText() .. ". " .. Score .. " mission score!", if Text then
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' has " .. Text .. " in " .. Mission:GetText() .. ". " .. Score .. " mission score!",
MESSAGE.Type.Information ) MESSAGE.Type.Information )
:ToAll() :ToAll()
end
self:ScoreCSV( PlayerName, "", "MISSION_" .. MissionName:gsub( ' ', '_' ), 1, Score ) self:ScoreCSV( PlayerName, "", "MISSION_" .. MissionName:gsub( ' ', '_' ), 1, Score )
end end
end end
@@ -1762,9 +1767,9 @@ function SCORING:SecondsToClock( sSeconds )
-- return nil; -- return nil;
return "00:00:00"; return "00:00:00";
else else
nHours = string.format( "%02.f", math.floor( nSeconds / 3600 ) ); local nHours = string.format( "%02.f", math.floor( nSeconds / 3600 ) );
nMins = string.format( "%02.f", math.floor( nSeconds / 60 - (nHours * 60) ) ); local nMins = string.format( "%02.f", math.floor( nSeconds / 60 - (nHours * 60) ) );
nSecs = string.format( "%02.f", math.floor( nSeconds - nHours * 3600 - nMins * 60 ) ); local nSecs = string.format( "%02.f", math.floor( nSeconds - nHours * 3600 - nMins * 60 ) );
return nHours .. ":" .. nMins .. ":" .. nSecs return nHours .. ":" .. nMins .. ":" .. nSecs
end end
end end

View File

@@ -1,3 +1,4 @@
---@diagnostic disable: cast-local-type
--- **Ops** - Automatic Terminal Information Service (ATIS). --- **Ops** - Automatic Terminal Information Service (ATIS).
-- --
-- === -- ===
@@ -418,6 +419,8 @@ ATIS.RunwayM2T = {
TheChannel = -10, TheChannel = -10,
Syria = 5, Syria = 5,
MarianaIslands = 2, MarianaIslands = 2,
Falklands = 12,
Sinai = 5,
} }
--- Whether ICAO phraseology is used for ATIS broadcasts. --- Whether ICAO phraseology is used for ATIS broadcasts.
@@ -429,6 +432,8 @@ ATIS.RunwayM2T = {
-- @field #boolean TheChannel true. -- @field #boolean TheChannel true.
-- @field #boolean Syria true. -- @field #boolean Syria true.
-- @field #boolean MarianaIslands true. -- @field #boolean MarianaIslands true.
-- @field #boolean Falklands true.
-- @field #boolean Sinai true.
ATIS.ICAOPhraseology = { ATIS.ICAOPhraseology = {
Caucasus = true, Caucasus = true,
Nevada = false, Nevada = false,
@@ -436,7 +441,9 @@ ATIS.ICAOPhraseology = {
PersianGulf = true, PersianGulf = true,
TheChannel = true, TheChannel = true,
Syria = true, Syria = true,
MarianaIslands = true MarianaIslands = true,
Falklands = true,
Sinai = true,
} }
--- Nav point data. --- Nav point data.
@@ -608,15 +615,16 @@ _ATIS = {}
--- ATIS class version. --- ATIS class version.
-- @field #string version -- @field #string version
ATIS.version = "0.9.14" ATIS.version = "0.9.15"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Add new Normandy airfields.
-- TODO: Zulu time --> Zulu in output.
-- TODO: Correct fog for elevation. -- TODO: Correct fog for elevation.
-- DONE: Zulu time --> Zulu in output.
-- DONE: Fix for AB not having a runway - Helopost like Naqoura
-- DONE: Add new Normandy airfields.
-- DONE: Use new AIRBASE system to set start/landing runway -- DONE: Use new AIRBASE system to set start/landing runway
-- DONE: SetILS doesn't work -- DONE: SetILS doesn't work
-- DONE: Visibility reported twice over SRS -- DONE: Visibility reported twice over SRS
@@ -1270,6 +1278,7 @@ end
-- @param #string Event Event. -- @param #string Event Event.
-- @param #string To To state. -- @param #string To To state.
function ATIS:onafterStart( From, Event, To ) function ATIS:onafterStart( From, Event, To )
self:I("Airbase category is "..self.airbase:GetAirbaseCategory())
-- Check that this is an airdrome. -- Check that this is an airdrome.
if self.airbase:GetAirbaseCategory() == Airbase.Category.SHIP then if self.airbase:GetAirbaseCategory() == Airbase.Category.SHIP then
@@ -1821,7 +1830,10 @@ function ATIS:onafterBroadcast( From, Event, To )
-- Airbase name -- Airbase name
subtitle = string.format( "%s", self.airbasename ) subtitle = string.format( "%s", self.airbasename )
if (not self.ATISforFARPs) and self.airbasename:find( "AFB" ) == nil and self.airbasename:find( "Airport" ) == nil and self.airbasename:find( "Airstrip" ) == nil and self.airbasename:find( "airfield" ) == nil and self.airbasename:find( "AB" ) == nil then if (not self.ATISforFARPs) and self.airbasename:find( "AFB" ) == nil and self.airbasename:find( "Airport" ) == nil
and self.airbasename:find( "Airstrip" ) == nil and self.airbasename:find( "airfield" ) == nil and self.airbasename:find( "AB" ) == nil
and self.airbasename:find( "Field" ) == nil
then
subtitle = subtitle .. " Airport" subtitle = subtitle .. " Airport"
end end
if not self.useSRS then if not self.useSRS then
@@ -2140,15 +2152,19 @@ function ATIS:onafterBroadcast( From, Event, To )
end end
alltext = alltext .. ";\n" .. subtitle alltext = alltext .. ";\n" .. subtitle
local _RUNACT
if not self.ATISforFARPs then if not self.ATISforFARPs then
-- Active runway. -- Active runway.
local subtitle=string.format("Active runway %s", runwayLanding) if runwayLanding then
if rwyLandingLeft==true then local subtitle=string.format("Active runway %s", runwayLanding)
subtitle=subtitle.." Left" if rwyLandingLeft==true then
elseif rwyLandingLeft==false then subtitle=subtitle.." Left"
subtitle=subtitle.." Right" elseif rwyLandingLeft==false then
subtitle=subtitle.." Right"
end
end end
local _RUNACT = subtitle _RUNACT = subtitle
if not self.useSRS then if not self.useSRS then
self:Transmission(ATIS.Sound.ActiveRunway, 1.0, subtitle) self:Transmission(ATIS.Sound.ActiveRunway, 1.0, subtitle)
self.radioqueue:Number2Transmission(runwayLanding) self.radioqueue:Number2Transmission(runwayLanding)
@@ -2509,8 +2525,11 @@ function ATIS:GetActiveRunway(Takeoff)
else else
runway=self.airbase:GetActiveRunwayLanding() runway=self.airbase:GetActiveRunwayLanding()
end end
if runway then -- some ABs have NO runways, e.g. Syria Naqoura
return runway.name, runway.isLeft return runway.name, runway.isLeft
else
return nil, nil
end
end end
--- Get runway from user supplied magnetic heading. --- Get runway from user supplied magnetic heading.

View File

@@ -5822,27 +5822,64 @@ function AIRBOSS:_ScanCarrierZone()
-- Get aircraft type name. -- Get aircraft type name.
local actype = group:GetTypeName() local actype = group:GetTypeName()
-- Create a new flight group
if knownflight then if knownflight then
-- Debug output.
self:T2(self.lid..string.format("Known flight group %s of type %s in CCA.", groupname, actype))
-- Check if flight is AI and if we want to handle it at all. -- Check if flight is AI and if we want to handle it at all.
if knownflight.ai and knownflight.flag == -100 and self.handleai and false then --Disabled AI handling because of incorrect OPSGROUP reference! if knownflight.ai and self.handleai then
local putintomarshal = false -- Defines if AI group should be handled by the airboss.
local iscarriersquad=true
-- Get flight group. -- Check if AI group is part of the group set if a set was defined.
local flight = _DATABASE:GetOpsGroup( groupname ) if self.squadsetAI then
local group=self.squadsetAI:FindGroup(groupname)
if flight and flight:IsInbound() and flight.destbase:GetName() == self.carrier:GetName() then if group then
if flight.ishelo then iscarriersquad=true
else else
putintomarshal = true iscarriersquad=false
end end
flight.airboss = self
end end
-- Send AI flight to marshal stack. -- Check if group was explicitly excluded.
if putintomarshal then if self.excludesetAI then
local group=self.excludesetAI:FindGroup(groupname)
if group then
iscarriersquad=false
end
end
-- Get distance to carrier.
local dist=knownflight.group:GetCoordinate():Get2DDistance(self:GetCoordinate())
-- Close in distance. Is >0 if AC comes closer wrt to first detected distance d0.
local closein=knownflight.dist0-dist
-- Debug info.
self:T3(self.lid..string.format("Known AI flight group %s closed in by %.1f NM", knownflight.groupname, UTILS.MetersToNM(closein)))
-- Is this group the tanker?
local istanker=self.tanker and self.tanker.tanker:GetName()==groupname
-- Is this group the AWACS?
local isawacs=self.awacs and self.awacs.tanker:GetName()==groupname
-- Send tanker to marshal stack?
local tanker2marshal = istanker and self.tanker:IsReturning() and self.tanker.airbase:GetName()==self.airbase:GetName() and knownflight.flag==-100 and self.tanker.recovery==true
-- Send AWACS to marhsal stack?
local awacs2marshal = isawacs and self.awacs:IsReturning() and self.awacs.airbase:GetName()==self.airbase:GetName() and knownflight.flag==-100 and self.awacs.recovery==true
-- Put flight into Marshal.
local putintomarshal=closein>UTILS.NMToMeters(5) and knownflight.flag==-100 and iscarriersquad and istanker==false and isawacs==false
-- Send AI flight to marshal stack if group closes in more than 5 and has initial flag value.
if putintomarshal or tanker2marshal or awacs2marshal then
-- Get the next free stack for current recovery case. -- Get the next free stack for current recovery case.
local stack = self:_GetFreeStack( knownflight.ai ) local stack = self:_GetFreeStack( knownflight.ai )

View File

@@ -30,7 +30,7 @@
-- @module Ops.CSAR -- @module Ops.CSAR
-- @image OPS_CSAR.jpg -- @image OPS_CSAR.jpg
-- Date: January 2023 -- Date: May 2023
------------------------------------------------------------------------- -------------------------------------------------------------------------
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM --- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
@@ -292,7 +292,7 @@ CSAR.AircraftType["Bronco-OV-10A"] = 2
--- CSAR class version. --- CSAR class version.
-- @field #string version -- @field #string version
CSAR.version="1.0.17" CSAR.version="1.0.18"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list -- ToDo list
@@ -316,7 +316,7 @@ function CSAR:New(Coalition, Template, Alias)
-- Inherit everything from FSM class. -- Inherit everything from FSM class.
local self=BASE:Inherit(self, FSM:New()) -- #CSAR local self=BASE:Inherit(self, FSM:New()) -- #CSAR
BASE:T({Coalition, Prefixes, Alias}) BASE:T({Coalition, Template, Alias})
--set Coalition --set Coalition
if Coalition and type(Coalition)=="string" then if Coalition and type(Coalition)=="string" then
@@ -1880,7 +1880,7 @@ function CSAR:_SignalFlare(_unitName)
if _SETTINGS:IsImperial() then if _SETTINGS:IsImperial() then
_distance = string.format("%.1fnm",UTILS.MetersToNM(_closest.distance)) _distance = string.format("%.1fnm",UTILS.MetersToNM(_closest.distance))
else else
_distance = string.format("%.1fkm",_closest.distance) _distance = string.format("%.1fkm",_closest.distance/1000)
end end
local _msg = string.format("%s - Popping signal flare at your %s o\'clock. Distance %s", self:_GetCustomCallSign(_unitName), _clockDir, _distance) local _msg = string.format("%s - Popping signal flare at your %s o\'clock. Distance %s", self:_GetCustomCallSign(_unitName), _clockDir, _distance)
self:_DisplayMessageToSAR(_heli, _msg, self.messageTime, false, true, true) self:_DisplayMessageToSAR(_heli, _msg, self.messageTime, false, true, true)
@@ -2175,6 +2175,7 @@ function CSAR:_AddBeaconToGroup(_group, _freq)
if _group:IsAlive() then if _group:IsAlive() then
local _radioUnit = _group:GetUnit(1) local _radioUnit = _group:GetUnit(1)
if _radioUnit then if _radioUnit then
local name = _radioUnit:GetName()
local Frequency = _freq -- Freq in Hertz local Frequency = _freq -- Freq in Hertz
local name = _radioUnit:GetName() local name = _radioUnit:GetName()
local Sound = "l10n/DEFAULT/"..self.radioSound local Sound = "l10n/DEFAULT/"..self.radioSound

View File

@@ -22,7 +22,7 @@
-- @module Ops.CTLD -- @module Ops.CTLD
-- @image OPS_CTLD.jpg -- @image OPS_CTLD.jpg
-- Last Update Apr 2023 -- Last Update June 2023
do do
@@ -204,7 +204,7 @@ CTLD_CARGO = {
-- @param #CTLD_CARGO self -- @param #CTLD_CARGO self
-- @param #boolean loaded -- @param #boolean loaded
function CTLD_CARGO:Isloaded() function CTLD_CARGO:Isloaded()
if self.HasBeenMoved and not self.WasDropped() then if self.HasBeenMoved and not self:WasDropped() then
return true return true
else else
return false return false
@@ -1221,7 +1221,7 @@ CTLD.UnitTypes = {
--- CTLD class version. --- CTLD class version.
-- @field #string version -- @field #string version
CTLD.version="1.0.37" CTLD.version="1.0.40"
--- Instantiate a new CTLD. --- Instantiate a new CTLD.
-- @param #CTLD self -- @param #CTLD self
@@ -1390,6 +1390,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
-- sub categories -- sub categories
self.usesubcats = false self.usesubcats = false
self.subcats = {} self.subcats = {}
self.subcatsTroop = {}
-- disallow building in loadzones -- disallow building in loadzones
self.nobuildinloadzones = true self.nobuildinloadzones = true
@@ -1750,6 +1751,8 @@ function CTLD:_EventHandler(EventData)
if _coalition ~= self.coalition then if _coalition ~= self.coalition then
return --ignore! return --ignore!
end end
local unitname = event.IniUnitName or "none"
self.MenusDone[unitname] = nil
-- check is Helicopter -- check is Helicopter
local _unit = event.IniUnit local _unit = event.IniUnit
local _group = event.IniGroup local _group = event.IniGroup
@@ -1770,6 +1773,7 @@ function CTLD:_EventHandler(EventData)
local unitname = event.IniUnitName or "none" local unitname = event.IniUnitName or "none"
self.CtldUnits[unitname] = nil self.CtldUnits[unitname] = nil
self.Loaded_Cargo[unitname] = nil self.Loaded_Cargo[unitname] = nil
self.MenusDone[unitname] = nil
end end
return self return self
end end
@@ -2276,6 +2280,7 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop)
if not drop then if not drop then
inzone = self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD) inzone = self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD)
if not inzone then if not inzone then
---@diagnostic disable-next-line: cast-local-type
inzone, ship, zone, distance, width = self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP) inzone, ship, zone, distance, width = self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP)
end end
else else
@@ -3442,6 +3447,9 @@ function CTLD:_RefreshF10Menus()
if _unit:IsHelicopter() or (self:IsHercules(_unit) and self.enableHercules) then --ensure no stupid unit entries here if _unit:IsHelicopter() or (self:IsHercules(_unit) and self.enableHercules) then --ensure no stupid unit entries here
local unitName = _unit:GetName() local unitName = _unit:GetName()
_UnitList[unitName] = unitName _UnitList[unitName] = unitName
else
local unitName = _unit:GetName()
_UnitList[unitName] = nil
end end
end -- end isAlive end -- end isAlive
end -- end if _unit end -- end if _unit
@@ -3462,6 +3470,12 @@ function CTLD:_RefreshF10Menus()
self.subcats[entry.Subcategory] = entry.Subcategory self.subcats[entry.Subcategory] = entry.Subcategory
end end
end end
for _id,_cargo in pairs(self.Cargo_Troops) do
local entry = _cargo -- #CTLD_CARGO
if not self.subcatsTroop[entry.Subcategory] then
self.subcatsTroop[entry.Subcategory] = entry.Subcategory
end
end
end end
-- build unit menus -- build unit menus
@@ -3500,13 +3514,26 @@ function CTLD:_RefreshF10Menus()
-- sub menu troops management -- sub menu troops management
if cantroops then if cantroops then
local troopsmenu = MENU_GROUP:New(_group,"Load troops",toptroops) local troopsmenu = MENU_GROUP:New(_group,"Load troops",toptroops)
for _,_entry in pairs(self.Cargo_Troops) do if self.usesubcats then
local entry = _entry -- #CTLD_CARGO local subcatmenus = {}
menucount = menucount + 1 for _name,_entry in pairs(self.subcatsTroop) do
menus[menucount] = MENU_GROUP_COMMAND:New(_group,entry.Name,troopsmenu,self._LoadTroops, self, _group, _unit, entry) subcatmenus[_name] = MENU_GROUP:New(_group,_name,troopsmenu)
end
for _,_entry in pairs(self.Cargo_Troops) do
local entry = _entry -- #CTLD_CARGO
local subcat = entry.Subcategory
menucount = menucount + 1
menus[menucount] = MENU_GROUP_COMMAND:New(_group,entry.Name,subcatmenus[subcat],self._LoadTroops, self, _group, _unit, entry)
end
else
for _,_entry in pairs(self.Cargo_Troops) do
local entry = _entry -- #CTLD_CARGO
menucount = menucount + 1
menus[menucount] = MENU_GROUP_COMMAND:New(_group,entry.Name,troopsmenu,self._LoadTroops, self, _group, _unit, entry)
end
end end
local unloadmenu1 = MENU_GROUP_COMMAND:New(_group,"Drop troops",toptroops, self._UnloadTroops, self, _group, _unit):Refresh() local unloadmenu1 = MENU_GROUP_COMMAND:New(_group,"Drop troops",toptroops, self._UnloadTroops, self, _group, _unit):Refresh()
local extractMenu1 = MENU_GROUP_COMMAND:New(_group, "Extract troops", toptroops, self._ExtractTroops, self, _group, _unit):Refresh() local extractMenu1 = MENU_GROUP_COMMAND:New(_group, "Extract troops", toptroops, self._ExtractTroops, self, _group, _unit):Refresh()
end end
-- sub menu crates management -- sub menu crates management
if cancrates then if cancrates then
@@ -3597,7 +3624,8 @@ end
-- @param #number NoTroops Size of the group in number of Units across combined templates (for loading). -- @param #number NoTroops Size of the group in number of Units across combined templates (for loading).
-- @param #number PerTroopMass Mass in kg of each soldier -- @param #number PerTroopMass Mass in kg of each soldier
-- @param #number Stock Number of groups in stock. Nil for unlimited. -- @param #number Stock Number of groups in stock. Nil for unlimited.
function CTLD:AddTroopsCargo(Name,Templates,Type,NoTroops,PerTroopMass,Stock) -- @param #string SubCategory Name of sub-category (optional).
function CTLD:AddTroopsCargo(Name,Templates,Type,NoTroops,PerTroopMass,Stock,SubCategory)
self:T(self.lid .. " AddTroopsCargo") self:T(self.lid .. " AddTroopsCargo")
self:T({Name,Templates,Type,NoTroops,PerTroopMass,Stock}) self:T({Name,Templates,Type,NoTroops,PerTroopMass,Stock})
if not self:_CheckTemplates(Templates) then if not self:_CheckTemplates(Templates) then
@@ -3606,7 +3634,7 @@ function CTLD:AddTroopsCargo(Name,Templates,Type,NoTroops,PerTroopMass,Stock)
end end
self.CargoCounter = self.CargoCounter + 1 self.CargoCounter = self.CargoCounter + 1
-- Troops are directly loadable -- Troops are directly loadable
local cargo = CTLD_CARGO:New(self.CargoCounter,Name,Templates,Type,false,true,NoTroops,nil,nil,PerTroopMass,Stock) local cargo = CTLD_CARGO:New(self.CargoCounter,Name,Templates,Type,false,true,NoTroops,nil,nil,PerTroopMass,Stock, SubCategory)
table.insert(self.Cargo_Troops,cargo) table.insert(self.Cargo_Troops,cargo)
return self return self
end end
@@ -4308,6 +4336,9 @@ end
local uspeed = Unit:GetVelocityMPS() local uspeed = Unit:GetVelocityMPS()
local uheight = Unit:GetHeight() local uheight = Unit:GetHeight()
local ucoord = Unit:GetCoordinate() local ucoord = Unit:GetCoordinate()
if not ucoord then
return false
end
local gheight = ucoord:GetLandHeight() local gheight = ucoord:GetLandHeight()
local aheight = uheight - gheight -- height above ground local aheight = uheight - gheight -- height above ground
local maxh = self.maximumHoverHeight -- 15 local maxh = self.maximumHoverHeight -- 15
@@ -4334,6 +4365,9 @@ end
local uspeed = Unit:GetVelocityMPS() local uspeed = Unit:GetVelocityMPS()
local uheight = Unit:GetHeight() local uheight = Unit:GetHeight()
local ucoord = Unit:GetCoordinate() local ucoord = Unit:GetCoordinate()
if not ucoord then
return false
end
local gheight = ucoord:GetLandHeight() local gheight = ucoord:GetLandHeight()
local aheight = uheight - gheight -- height above ground local aheight = uheight - gheight -- height above ground
local minh = self.HercMinAngels-- 1500m local minh = self.HercMinAngels-- 1500m
@@ -4419,6 +4453,9 @@ end
end end
local uheight = Unit:GetHeight() local uheight = Unit:GetHeight()
local ucoord = Unit:GetCoordinate() local ucoord = Unit:GetCoordinate()
if not ucoord then
return false
end
local gheight = ucoord:GetLandHeight() local gheight = ucoord:GetLandHeight()
local aheight = uheight - gheight -- height above ground local aheight = uheight - gheight -- height above ground
if aheight >= minheight then if aheight >= minheight then

View File

@@ -43,7 +43,7 @@ BIGSMOKEPRESET = {
HugeSmoke=8, HugeSmoke=8,
} }
--- DCS map as returned by env.mission.theatre. --- DCS map as returned by `env.mission.theatre`.
-- @type DCSMAP -- @type DCSMAP
-- @field #string Caucasus Caucasus map. -- @field #string Caucasus Caucasus map.
-- @field #string Normandy Normandy map. -- @field #string Normandy Normandy map.
@@ -53,6 +53,7 @@ BIGSMOKEPRESET = {
-- @field #string Syria Syria map. -- @field #string Syria Syria map.
-- @field #string MarianaIslands Mariana Islands map. -- @field #string MarianaIslands Mariana Islands map.
-- @field #string Falklands South Atlantic map. -- @field #string Falklands South Atlantic map.
-- @field #string Sinai Sinai map.
DCSMAP = { DCSMAP = {
Caucasus="Caucasus", Caucasus="Caucasus",
NTTR="Nevada", NTTR="Nevada",
@@ -62,6 +63,7 @@ DCSMAP = {
Syria="Syria", Syria="Syria",
MarianaIslands="MarianaIslands", MarianaIslands="MarianaIslands",
Falklands="Falklands", Falklands="Falklands",
Sinai="SinaiMap"
} }
@@ -297,14 +299,14 @@ end
-- @param #table tbl Input table. -- @param #table tbl Input table.
UTILS.OneLineSerialize = function( tbl ) -- serialization of a table all on a single line, no comments, made to replace old get_table_string function UTILS.OneLineSerialize = function( tbl ) -- serialization of a table all on a single line, no comments, made to replace old get_table_string function
lookup_table = {} local lookup_table = {}
local function _Serialize( tbl ) local function _Serialize( tbl )
if type(tbl) == 'table' then --function only works for tables! if type(tbl) == 'table' then --function only works for tables!
if lookup_table[tbl] then if lookup_table[tbl] then
return lookup_table[object] return lookup_table[tbl]
end end
local tbl_str = {} local tbl_str = {}
@@ -1390,7 +1392,7 @@ function UTILS.TACANToFrequency(TACANChannel, TACANMode)
end end
--- Returns the DCS map/theatre as optained by env.mission.theatre --- Returns the DCS map/theatre as optained by `env.mission.theatre`.
-- @return #string DCS map name. -- @return #string DCS map name.
function UTILS.GetDCSMap() function UTILS.GetDCSMap()
return env.mission.theatre return env.mission.theatre
@@ -1446,6 +1448,7 @@ end
-- * Syria +5 (East) -- * Syria +5 (East)
-- * Mariana Islands +2 (East) -- * Mariana Islands +2 (East)
-- * Falklands +12 (East) - note there's a LOT of deviation across the map, as we're closer to the South Pole -- * Falklands +12 (East) - note there's a LOT of deviation across the map, as we're closer to the South Pole
-- * Sinai +4.8 (East)
-- @param #string map (Optional) Map for which the declination is returned. Default is from env.mission.theatre -- @param #string map (Optional) Map for which the declination is returned. Default is from env.mission.theatre
-- @return #number Declination in degrees. -- @return #number Declination in degrees.
function UTILS.GetMagneticDeclination(map) function UTILS.GetMagneticDeclination(map)
@@ -1470,6 +1473,8 @@ function UTILS.GetMagneticDeclination(map)
declination=2 declination=2
elseif map==DCSMAP.Falklands then elseif map==DCSMAP.Falklands then
declination=12 declination=12
elseif map==DCSMAP.Sinai then
declination=4.8
else else
declination=0 declination=0
end end
@@ -1685,6 +1690,8 @@ function UTILS.GMTToLocalTimeDifference()
return 10 -- Guam is UTC+10 hours. return 10 -- Guam is UTC+10 hours.
elseif theatre==DCSMAP.Falklands then elseif theatre==DCSMAP.Falklands then
return -3 -- Fireland is UTC-3 hours. return -3 -- Fireland is UTC-3 hours.
elseif theatre==DCSMAP.Sinai then
return 2 -- Currently map is +2 but should be +3 (DCS bug?)
else else
BASE:E(string.format("ERROR: Unknown Map %s in UTILS.GMTToLocal function. Returning 0", tostring(theatre))) BASE:E(string.format("ERROR: Unknown Map %s in UTILS.GMTToLocal function. Returning 0", tostring(theatre)))
return 0 return 0

View File

@@ -11,8 +11,8 @@
-- @module Wrapper.Airbase -- @module Wrapper.Airbase
-- @image Wrapper_Airbase.JPG -- @image Wrapper_Airbase.JPG
---
--- @type AIRBASE -- @type AIRBASE
-- @field #string ClassName Name of the class, i.e. "AIRBASE". -- @field #string ClassName Name of the class, i.e. "AIRBASE".
-- @field #table CategoryName Names of airbase categories. -- @field #table CategoryName Names of airbase categories.
-- @field #string AirbaseName Name of the airbase. -- @field #string AirbaseName Name of the airbase.
@@ -426,7 +426,7 @@ AIRBASE.TheChannel = {
-- * AIRBASE.Syria.Al_Dumayr -- * AIRBASE.Syria.Al_Dumayr
-- * AIRBASE.Syria.Gazipasa -- * AIRBASE.Syria.Gazipasa
-- * AIRBASE.Syria.Hatay -- * AIRBASE.Syria.Hatay
-- * AIRBASE.Syria.Nicosia -- * AIRBASE.Syria.Nicosia [Deactivated by ED as of June/2023]
-- * AIRBASE.Syria.Pinarbashi -- * AIRBASE.Syria.Pinarbashi
-- * AIRBASE.Syria.Paphos -- * AIRBASE.Syria.Paphos
-- * AIRBASE.Syria.Kingsfield -- * AIRBASE.Syria.Kingsfield
@@ -467,8 +467,8 @@ AIRBASE.TheChannel = {
-- * AIRBASE.Syria.H3_Northwest -- * AIRBASE.Syria.H3_Northwest
-- * AIRBASE.Syria.H3_Southwest -- * AIRBASE.Syria.H3_Southwest
-- * AIRBASE.Syria.Kharab_Ishk -- * AIRBASE.Syria.Kharab_Ishk
-- * AIRBASE.Syria.Raj_al_Issa_East -- * AIRBASE.Syria.Raj_al_Issa_East (deleted by ED)
-- * AIRBASE.Syria.Raj_al_Issa_West -- * AIRBASE.Syria.Raj_al_Issa_West (deleted by ED)
-- * AIRBASE.Syria.Ruwayshid -- * AIRBASE.Syria.Ruwayshid
-- * AIRBASE.Syria.Sanliurfa -- * AIRBASE.Syria.Sanliurfa
-- * AIRBASE.Syria.Tal_Siman -- * AIRBASE.Syria.Tal_Siman
@@ -490,9 +490,8 @@ AIRBASE.Syria={
["Wujah_Al_Hajar"]="Wujah Al Hajar", ["Wujah_Al_Hajar"]="Wujah Al Hajar",
["Al_Dumayr"]="Al-Dumayr", ["Al_Dumayr"]="Al-Dumayr",
["Gazipasa"]="Gazipasa", ["Gazipasa"]="Gazipasa",
--["Ru_Convoy_4"]="Ru Convoy-4",
["Hatay"]="Hatay", ["Hatay"]="Hatay",
["Nicosia"]="Nicosia", --["Nicosia"]="Nicosia",
["Pinarbashi"]="Pinarbashi", ["Pinarbashi"]="Pinarbashi",
["Paphos"]="Paphos", ["Paphos"]="Paphos",
["Kingsfield"]="Kingsfield", ["Kingsfield"]="Kingsfield",
@@ -533,8 +532,8 @@ AIRBASE.Syria={
["H3_Northwest"]="H3 Northwest", ["H3_Northwest"]="H3 Northwest",
["H3_Southwest"]="H3 Southwest", ["H3_Southwest"]="H3 Southwest",
["Kharab_Ishk"]="Kharab Ishk", ["Kharab_Ishk"]="Kharab Ishk",
["Raj_al_Issa_East"]="Raj al Issa East", -- ["Raj_al_Issa_East"]="Raj al Issa East",
["Raj_al_Issa_West"]="Raj al Issa West", -- ["Raj_al_Issa_West"]="Raj al Issa West",
["Ruwayshid"]="Ruwayshid", ["Ruwayshid"]="Ruwayshid",
["Sanliurfa"]="Sanliurfa", ["Sanliurfa"]="Sanliurfa",
["Tal_Siman"]="Tal Siman", ["Tal_Siman"]="Tal Siman",
@@ -549,6 +548,8 @@ AIRBASE.Syria={
-- * AIRBASE.MarianaIslands.Saipan_Intl -- * AIRBASE.MarianaIslands.Saipan_Intl
-- * AIRBASE.MarianaIslands.Tinian_Intl -- * AIRBASE.MarianaIslands.Tinian_Intl
-- * AIRBASE.MarianaIslands.Olf_Orote -- * AIRBASE.MarianaIslands.Olf_Orote
-- * AIRBASE.MarianaIslands.Pagan_Airstrip
-- * AIRBASE.MarianaIslands.North_West_Field
-- --
-- @field MarianaIslands -- @field MarianaIslands
AIRBASE.MarianaIslands = { AIRBASE.MarianaIslands = {
@@ -558,6 +559,8 @@ AIRBASE.MarianaIslands = {
["Saipan_Intl"] = "Saipan Intl", ["Saipan_Intl"] = "Saipan Intl",
["Tinian_Intl"] = "Tinian Intl", ["Tinian_Intl"] = "Tinian Intl",
["Olf_Orote"] = "Olf Orote", ["Olf_Orote"] = "Olf Orote",
["Pagan_Airstrip"] = "Pagan Airstrip",
["North_West_Field"] = "North West Field",
} }
--- Airbases of the South Atlantic map: --- Airbases of the South Atlantic map:
@@ -619,6 +622,72 @@ AIRBASE.SouthAtlantic={
["Gull_Point"] = "Gull Point", ["Gull_Point"] = "Gull Point",
} }
--- Airbases of the Sinai map:
--
-- * AIRBASE.Sinai.Abu_Suwayr
-- * AIRBASE.Sinai.Sde_Dov
-- * AIRBASE.Sinai.AzZaqaziq
-- * AIRBASE.Sinai.Hatzor
-- * AIRBASE.Sinai.Kedem
-- * AIRBASE.Sinai.Nevatim
-- * AIRBASE.Sinai.Cairo_International_Airport
-- * AIRBASE.Sinai.Al_Ismailiyah
-- * AIRBASE.Sinai.As_Salihiyah
-- * AIRBASE.Sinai.Fayed
-- * AIRBASE.Sinai.Bilbeis_Air_Base
-- * AIRBASE.Sinai.Ramon_Airbase
-- * AIRBASE.Sinai.Kibrit_Air_Base
-- * AIRBASE.Sinai.El_Arish
-- * AIRBASE.Sinai.Ovda
-- * AIRBASE.Sinai.Melez
-- * AIRBASE.Sinai.Al_Mansurah
-- * AIRBASE.Sinai.Palmahim
-- * AIRBASE.Sinai.Baluza
-- * AIRBASE.Sinai.El_Gora
-- * AIRBASE.Sinai.Difarsuwar_Airfield
-- * AIRBASE.Sinai.Wadi_al_Jandali
-- * AIRBASE.Sinai.St_Catherine
-- * AIRBASE.Sinai.Tel_Nof
-- * AIRBASE.Sinai.Abu_Rudeis
-- * AIRBASE.Sinai.Inshas_Airbase
-- * AIRBASE.Sinai.Ben_Gurion
-- * AIRBASE.Sinai.Bir_Hasanah
-- * AIRBASE.Sinai.Cairo_West
--
-- @field Sinai
AIRBASE.Sinai = {
["Hatzerim"] = "Hatzerim",
["Abu_Suwayr"] = "Abu Suwayr",
["Sde_Dov"] = "Sde Dov",
["AzZaqaziq"] = "AzZaqaziq",
["Hatzor"] = "Hatzor",
["Kedem"] = "Kedem",
["Nevatim"] = "Nevatim",
["Cairo_International_Airport"] = "Cairo International Airport",
["Al_Ismailiyah"] = "Al Ismailiyah",
["As_Salihiyah"] = "As Salihiyah",
["Fayed"] = "Fayed",
["Bilbeis_Air_Base"] = "Bilbeis Air Base",
["Ramon_Airbase"] = "Ramon Airbase",
["Kibrit_Air_Base"] = "Kibrit Air Base",
["El_Arish"] = "El Arish",
["Ovda"] = "Ovda",
["Melez"] = "Melez",
["Al_Mansurah"] = "Al Mansurah",
["Palmahim"] = "Palmahim",
["Baluza"] = "Baluza",
["El_Gora"] = "El Gora",
["Difarsuwar_Airfield"] = "Difarsuwar Airfield",
["Wadi_al_Jandali"] = "Wadi al Jandali",
["St_Catherine"] = "St Catherine",
["Tel_Nof"] = "Tel Nof",
["Abu_Rudeis"] = "Abu Rudeis",
["Inshas_Airbase"] = "Inshas Airbase",
["Ben_Gurion"] = "Ben-Gurion",
["Bir_Hasanah"] = "Bir Hasanah",
["Cairo_West"] = "Cairo West",
}
--- AIRBASE.ParkingSpot ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy". --- AIRBASE.ParkingSpot ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy".
-- @type AIRBASE.ParkingSpot -- @type AIRBASE.ParkingSpot
-- @field Core.Point#COORDINATE Coordinate Coordinate of the parking spot. -- @field Core.Point#COORDINATE Coordinate Coordinate of the parking spot.
@@ -723,6 +792,12 @@ function AIRBASE:Register(AirbaseName)
-- Category. -- Category.
self.category=self.descriptors and self.descriptors.category or Airbase.Category.AIRDROME self.category=self.descriptors and self.descriptors.category or Airbase.Category.AIRDROME
-- H2 is bugged
--if self.AirbaseName == "H4" and self.descriptors == nil then
--self:E("***** H4 on Syria map is currently bugged!")
--return nil
--end
-- Set category. -- Set category.
if self.category==Airbase.Category.AIRDROME then if self.category==Airbase.Category.AIRDROME then
self.isAirdrome=true self.isAirdrome=true
@@ -1436,16 +1511,16 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
-- Get the aircraft size, i.e. it's longest side of x,z. -- Get the aircraft size, i.e. it's longest side of x,z.
local aircraft = nil -- fix local problem below local aircraft = nil -- fix local problem below
local _aircraftsize, ax,ay,az -- SU27 dimensions as default
local _aircraftsize = 23
local ax = 23 -- l
local ay = 7 -- h
local az = 17 -- w
if group and group.ClassName == "GROUP" then if group and group.ClassName == "GROUP" then
aircraft=group:GetUnit(1) aircraft=group:GetUnit(1)
_aircraftsize, ax,ay,az=aircraft:GetObjectSize() if aircraft then
else _aircraftsize, ax,ay,az=aircraft:GetObjectSize()
-- SU27 dimensions end
_aircraftsize = 23
ax = 23 -- length
ay = 7 -- height
az = 17 -- width
end end
@@ -2295,3 +2370,17 @@ function AIRBASE:CheckOnRunWay(group, radius, despawn)
return false return false
end end
--- Get category of airbase.
-- @param #AIRBASE self
-- @return #number Category of airbase from GetDesc().category.
function AIRBASE:GetCategory()
return self.category
end
--- Get category name of airbase.
-- @param #AIRBASE self
-- @return #string Category of airbase, i.e. Airdrome, Ship, or Helipad
function AIRBASE:GetCategoryName()
return AIRBASE.CategoryName[self.category]
end

View File

@@ -52,6 +52,7 @@
-- * @{#CONTROLLABLE.TaskEmbarking}: (AIR) Move the controllable to a Vec2 Point, wait for a defined duration and embark a controllable. -- * @{#CONTROLLABLE.TaskEmbarking}: (AIR) Move the controllable to a Vec2 Point, wait for a defined duration and embark a controllable.
-- * @{#CONTROLLABLE.TaskEmbarkToTransport}: (GROUND) Embark to a Transport landed at a location. -- * @{#CONTROLLABLE.TaskEmbarkToTransport}: (GROUND) Embark to a Transport landed at a location.
-- * @{#CONTROLLABLE.TaskEscort}: (AIR) Escort another airborne controllable. -- * @{#CONTROLLABLE.TaskEscort}: (AIR) Escort another airborne controllable.
-- * @{#CONTROLLABLE.TaskGroundEscort}: (AIR/HELO) Escort a ground controllable.
-- * @{#CONTROLLABLE.TaskFAC_AttackGroup}: (AIR + GROUND) The task makes the controllable/unit a FAC and orders the FAC to control the target (enemy ground controllable) destruction. -- * @{#CONTROLLABLE.TaskFAC_AttackGroup}: (AIR + GROUND) The task makes the controllable/unit a FAC and orders the FAC to control the target (enemy ground controllable) destruction.
-- * @{#CONTROLLABLE.TaskFireAtPoint}: (GROUND) Fire some or all ammunition at a VEC2 point. -- * @{#CONTROLLABLE.TaskFireAtPoint}: (GROUND) Fire some or all ammunition at a VEC2 point.
-- * @{#CONTROLLABLE.TaskFollow}: (AIR) Following another airborne controllable. -- * @{#CONTROLLABLE.TaskFollow}: (AIR) Following another airborne controllable.
@@ -1270,7 +1271,7 @@ end
--- (AIR) Orbit at a position with at a given altitude and speed. Optionally, a race track pattern can be specified. --- (AIR) Orbit at a position with at a given altitude and speed. Optionally, a race track pattern can be specified.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @param Core.Point#COORDINATE Coord Coordinate at which the CONTROLLABLE orbits. -- @param Core.Point#COORDINATE Coord Coordinate at which the CONTROLLABLE orbits. Can also be given as a `DCS#Vec3` or `DCS#Vec2` object.
-- @param #number Altitude Altitude in meters of the orbit pattern. Default y component of Coord. -- @param #number Altitude Altitude in meters of the orbit pattern. Default y component of Coord.
-- @param #number Speed Speed [m/s] flying the orbit pattern. Default 128 m/s = 250 knots. -- @param #number Speed Speed [m/s] flying the orbit pattern. Default 128 m/s = 250 knots.
-- @param Core.Point#COORDINATE CoordRaceTrack (Optional) If this coordinate is specified, the CONTROLLABLE will fly a race-track pattern using this and the initial coordinate. -- @param Core.Point#COORDINATE CoordRaceTrack (Optional) If this coordinate is specified, the CONTROLLABLE will fly a race-track pattern using this and the initial coordinate.
@@ -1279,11 +1280,11 @@ function CONTROLLABLE:TaskOrbit( Coord, Altitude, Speed, CoordRaceTrack )
local Pattern = AI.Task.OrbitPattern.CIRCLE local Pattern = AI.Task.OrbitPattern.CIRCLE
local P1 = Coord:GetVec2() local P1 = {x=Coord.x, y=Coord.z or Coord.y}
local P2 = nil local P2 = nil
if CoordRaceTrack then if CoordRaceTrack then
Pattern = AI.Task.OrbitPattern.RACE_TRACK Pattern = AI.Task.OrbitPattern.RACE_TRACK
P2 = CoordRaceTrack:GetVec2() P2 = {x=CoordRaceTrack.x, y=CoordRaceTrack.z or CoordRaceTrack.y}
end end
local Task = { local Task = {
@@ -1480,15 +1481,53 @@ function CONTROLLABLE:TaskFollow( FollowControllable, Vec3, LastWaypointIndex )
return DCSTask return DCSTask
end end
--- (AIR/HELO) Escort a ground controllable.
-- The unit / controllable will follow lead unit of the other controllable, additional units of both controllables will continue following their leaders.
-- The unit / controllable will also protect that controllable from threats of specified types.
-- @param #CONTROLLABLE self
-- @param #CONTROLLABLE FollowControllable The controllable to be escorted.
-- @param #number LastWaypointIndex (optional) Detach waypoint of another controllable. Once reached the unit / controllable Escort task is finished.
-- @param #number OrbitDistance (optional) Maximum distance helo will orbit around the ground unit in meters. Defaults to 2000 meters.
-- @param DCS#AttributeNameArray TargetTypes (optional) Array of AttributeName that is contains threat categories allowed to engage. Default {"Ground vehicles"}. See [https://wiki.hoggit.us/view/DCS_enum_attributes](https://wiki.hoggit.us/view/DCS_enum_attributes)
-- @return DCS#Task The DCS task structure.
function CONTROLLABLE:TaskGroundEscort( FollowControllable, LastWaypointIndex, OrbitDistance, TargetTypes )
-- Escort = {
-- id = 'GroundEscort',
-- params = {
-- groupId = Group.ID, -- must
-- engagementDistMax = Distance, -- Must. With his task it does not appear to actually define the range AI are allowed to attack at, rather it defines the size length of the orbit. The helicopters will fly up to this set distance before returning to the escorted group.
-- lastWptIndexFlag = boolean, -- optional
-- lastWptIndex = number, -- optional
-- targetTypes = array of AttributeName, -- must
-- lastWptIndexFlagChangedManually = boolean, -- must be true
-- }
-- }
local DCSTask = {
id = 'GroundEscort',
params = {
groupId = FollowControllable and FollowControllable:GetID() or nil,
engagementDistMax = OrbitDistance or 2000,
lastWptIndexFlag = LastWaypointIndex and true or false,
lastWptIndex = LastWaypointIndex,
targetTypes = TargetTypes or {"Ground vehicles"},
lastWptIndexFlagChangedManually = true,
},
}
return DCSTask
end
--- (AIR) Escort another airborne controllable. --- (AIR) Escort another airborne controllable.
-- The unit / controllable will follow lead unit of another controllable, wingmens of both controllables will continue following their leaders. -- The unit / controllable will follow lead unit of another controllable, wingmens of both controllables will continue following their leaders.
-- The unit / controllable will also protect that controllable from threats of specified types. -- The unit / controllable will also protect that controllable from threats of specified types.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @param #CONTROLLABLE FollowControllable The controllable to be escorted. -- @param #CONTROLLABLE FollowControllable The controllable to be escorted.
-- @param DCS#Vec3 Vec3 Position of the unit / lead unit of the controllable relative lead unit of another controllable in frame reference oriented by course of lead unit of another controllable. If another controllable is on land the unit / controllable will orbit around. -- @param DCS#Vec3 Vec3 Position of the unit / lead unit of the controllable relative lead unit of another controllable in frame reference oriented by course of lead unit of another controllable. If another controllable is on land the unit / controllable will orbit around.
-- @param #number LastWaypointIndex Detach waypoint of another controllable. Once reached the unit / controllable Follow task is finished. -- @param #number LastWaypointIndex Detach waypoint of another controllable. Once reached the unit / controllable Escort task is finished.
-- @param #number EngagementDistance Maximal distance from escorted controllable to threat. If the threat is already engaged by escort escort will disengage if the distance becomes greater than 1.5 * engagementDistMax. -- @param #number EngagementDistance Maximal distance from escorted controllable to threat in meters. If the threat is already engaged by escort escort will disengage if the distance becomes greater than 1.5 * engagementDistMax.
-- @param DCS#AttributeNameArray TargetTypes Array of AttributeName that is contains threat categories allowed to engage. Default {"Air"}. -- @param DCS#AttributeNameArray TargetTypes Array of AttributeName that is contains threat categories allowed to engage. Default {"Air"}. See https://wiki.hoggit.us/view/DCS_enum_attributes
-- @return DCS#Task The DCS task structure. -- @return DCS#Task The DCS task structure.
function CONTROLLABLE:TaskEscort( FollowControllable, Vec3, LastWaypointIndex, EngagementDistance, TargetTypes ) function CONTROLLABLE:TaskEscort( FollowControllable, Vec3, LastWaypointIndex, EngagementDistance, TargetTypes )
@@ -1504,8 +1543,7 @@ function CONTROLLABLE:TaskEscort( FollowControllable, Vec3, LastWaypointIndex, E
-- } -- }
-- } -- }
local DCSTask local DCSTask = {
DCSTask = {
id = 'Escort', id = 'Escort',
params = { params = {
groupId = FollowControllable and FollowControllable:GetID() or nil, groupId = FollowControllable and FollowControllable:GetID() or nil,

View File

@@ -5,7 +5,7 @@
-- === -- ===
-- --
-- ### Author: **Applevangelist** -- ### Author: **Applevangelist**
-- # Last Update Apr 2023 -- # Last Update June 2023
-- --
-- === -- ===
-- --
@@ -42,7 +42,7 @@ do
-- @field #NET -- @field #NET
NET = { NET = {
ClassName = "NET", ClassName = "NET",
Version = "0.1.1", Version = "0.1.2",
BlockTime = 600, BlockTime = 600,
BlockedPilots = {}, BlockedPilots = {},
BlockedUCIDs = {}, BlockedUCIDs = {},
@@ -90,7 +90,7 @@ function NET:New()
-- @param #string From State. -- @param #string From State.
-- @param #string Event Trigger. -- @param #string Event Trigger.
-- @param #string To State. -- @param #string To State.
-- @param Wrapper.Unit#UNIT Client Unit Object. -- @param Wrapper.Client#CLIENT Client Object.
-- @param #string Name Name of joining Pilot. -- @param #string Name Name of joining Pilot.
-- @return #NET self -- @return #NET self
@@ -220,7 +220,8 @@ function NET:_EventHandler(EventData)
side = PlayerSide, side = PlayerSide,
slot = PlayerSlot, slot = PlayerSlot,
} }
self:__PlayerJoined(1,data.IniUnit,name) local client = CLIENT:FindByPlayerName(name) or data.IniUnit
self:__PlayerJoined(1,client,name)
return self return self
end end
end end
@@ -771,7 +772,7 @@ end
-- @param #string To -- @param #string To
-- @return #NET self -- @return #NET self
function NET:onafterStatus(From,Event,To) function NET:onafterStatus(From,Event,To)
self:I({From,Event,To}) self:T({From,Event,To})
local function HouseHold(tavolo) local function HouseHold(tavolo)
local TNow = timer.getTime() local TNow = timer.getTime()
@@ -799,7 +800,7 @@ end
-- @param #string To -- @param #string To
-- @return #NET self -- @return #NET self
function NET:onafterRun(From,Event,To) function NET:onafterRun(From,Event,To)
self:I({From,Event,To}) self:T({From,Event,To})
self:HandleEvent(EVENTS.PlayerEnterUnit,self._EventHandler) self:HandleEvent(EVENTS.PlayerEnterUnit,self._EventHandler)
self:HandleEvent(EVENTS.PlayerEnterAircraft,self._EventHandler) self:HandleEvent(EVENTS.PlayerEnterAircraft,self._EventHandler)
self:HandleEvent(EVENTS.PlayerLeaveUnit,self._EventHandler) self:HandleEvent(EVENTS.PlayerLeaveUnit,self._EventHandler)
@@ -807,7 +808,7 @@ function NET:onafterRun(From,Event,To)
self:HandleEvent(EVENTS.Ejection,self._EventHandler) self:HandleEvent(EVENTS.Ejection,self._EventHandler)
self:HandleEvent(EVENTS.Crash,self._EventHandler) self:HandleEvent(EVENTS.Crash,self._EventHandler)
self:HandleEvent(EVENTS.SelfKillPilot,self._EventHandler) self:HandleEvent(EVENTS.SelfKillPilot,self._EventHandler)
self:__Status(-30) self:__Status(-10)
end end
--- Stop the event functions --- Stop the event functions

View File

@@ -237,22 +237,23 @@ end
-- @return DCS#Vec3 The 3D point vector of the POSITIONABLE. -- @return DCS#Vec3 The 3D point vector of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive. -- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetVec3() function POSITIONABLE:GetVec3()
local DCSPositionable = self:GetDCSObject() local DCSPositionable = self:GetDCSObject()
if DCSPositionable then if DCSPositionable then
--local status, vec3 = pcall(
-- function()
-- local vec3 = DCSPositionable:getPoint()
-- return vec3
--end
--)
local vec3 = DCSPositionable:getPoint() local vec3 = DCSPositionable:getPoint()
--if status then
if vec3 then
return vec3 return vec3
else --else
self:E( "ERROR: Cannot get vec3!" ) --self:E( { "Cannot get Vec3 from DCS Object", Positionable = self, Alive = self:IsAlive() } )
end --end
end end
-- ERROR! -- ERROR!
self:E( { "Cannot GetVec3", Positionable = self, Alive = self:IsAlive() } ) self:E( { "Cannot get the Positionable DCS Object for GetVec3", Positionable = self, Alive = self:IsAlive() } )
return nil return nil
end end
@@ -464,6 +465,115 @@ function POSITIONABLE:GetOffsetCoordinate( x, y, z )
return coord return coord
end end
--- Returns a COORDINATE object, which is transformed to be relative to the POSITIONABLE. Inverse of @{#POSITIONABLE.GetOffsetCoordinate}.
-- @param #POSITIONABLE self
-- @param #number x Offset along the world x-axis in meters. Default 0 m.
-- @param #number y Offset along the world y-axis in meters. Default 0 m.
-- @param #number z Offset along the world z-axis in meters. Default 0 m.
-- @return Core.Point#COORDINATE The relative COORDINATE with respect to the orientation of the POSITIONABLE.
function POSITIONABLE:GetRelativeCoordinate( x, y, z )
-- Default if nil.
x = x or 0
y = y or 0
z = z or 0
-- Vector from the origin of the map to self.
local selfPos = self:GetVec3()
-- Vectors making up self's local coordinate system.
local X = self:GetOrientationX()
local Y = self:GetOrientationY()
local Z = self:GetOrientationZ()
-- Offset from self to self's position (still in the world coordinate system).
local off = {
x = x - selfPos.x,
y = y - selfPos.y,
z = z - selfPos.z
}
-- The end result
local res = { x = 0, y = 0, z = 0 }
-- Matrix equation to solve:
-- | X.x, Y.x, Z.x | | res.x | | off.x |
-- | X.y, Y.y, Z.y | . | res.y | = | off.y |
-- | X.z, Y.z, Z.z | | res.z | | off.z |
-- Use gaussian elimination to solve the system of equations.
-- https://en.wikipedia.org/wiki/Gaussian_elimination
local mat = {
{ X.x, Y.x, Z.x, off.x },
{ X.y, Y.y, Z.y, off.y },
{ X.z, Y.z, Z.z, off.z }
}
-- Matrix dimensions
local m = 3
local n = 4
-- Pivot indices
local h = 1
local k = 1
while h <= m and k <= n do
local v_max = math.abs( mat[h][k] )
local i_max = h
for i = h,m,1 do
local value = math.abs( mat[i][k] )
if value > v_max then
i_max = i
v_max = value
end
end
if mat[i_max][k] == 0 then
-- Already all 0s, nothing to do.
k = k + 1
else
-- Swap rows h and i_max
local tmp = mat[h]
mat[h] = mat[i_max]
mat[i_max] = tmp
for i = h + 1,m,1 do
-- The scaling factor to use to reduce all values in this column
local f = mat[i][k] / mat[h][k]
mat[i][k] = 0
for j = k+1,n,1 do
mat[i][j] = mat[i][j] - f*mat[h][j]
end
end
h = h + 1
k = k + 1
end
end
-- mat is now in row echelon form:
-- | #, #, #, # |
-- | 0, #, #, # |
-- | 0, 0, #, # |
--
-- and the linear equation is now effectively:
-- | #, #, # | | res.x | | # |
-- | 0, #, # | . | res.y | = | # |
-- | 0, 0, # | | res.z | | # |
-- this resulting system of equations can be easily solved via substitution.
res.z = mat[3][4] / mat[3][3]
res.y = (mat[2][4] - res.z * mat[2][3]) / mat[2][2]
res.x = (mat[1][4] - res.y * mat[1][2] - res.z * mat[1][3]) / mat[1][1]
local coord = COORDINATE:NewFromVec3( res )
-- Return the relative coordinate.
return coord
end
--- Returns a random @{DCS#Vec3} vector within a range, indicating the point in 3D of the POSITIONABLE within the mission. --- Returns a random @{DCS#Vec3} vector within a range, indicating the point in 3D of the POSITIONABLE within the mission.
-- @param #POSITIONABLE self -- @param #POSITIONABLE self
-- @param #number Radius -- @param #number Radius

View File

@@ -25,6 +25,7 @@
-- @field #string ClassName Name of the class. -- @field #string ClassName Name of the class.
-- @field #string UnitName Name of the unit. -- @field #string UnitName Name of the unit.
-- @field #string GroupName Name of the group the unit belongs to. -- @field #string GroupName Name of the group the unit belongs to.
-- @field #table DCSUnit The DCS Unit object from the API.
-- @extends Wrapper.Controllable#CONTROLLABLE -- @extends Wrapper.Controllable#CONTROLLABLE
--- For each DCS Unit object alive within a running mission, a UNIT wrapper object (instance) will be created within the global _DATABASE object (an instance of @{Core.Database#DATABASE}). --- For each DCS Unit object alive within a running mission, a UNIT wrapper object (instance) will be created within the global _DATABASE object (an instance of @{Core.Database#DATABASE}).
@@ -92,6 +93,7 @@ UNIT = {
ClassName="UNIT", ClassName="UNIT",
UnitName=nil, UnitName=nil,
GroupName=nil, GroupName=nil,
DCSUnit = nil,
} }
@@ -124,6 +126,7 @@ function UNIT:Register( UnitName )
if group then if group then
self.GroupName=group:getName() self.GroupName=group:getName()
end end
self.DCSUnit = unit
end end
-- Set event prio. -- Set event prio.
@@ -176,6 +179,10 @@ function UNIT:GetDCSObject()
return DCSUnit return DCSUnit
end end
if self.DCSUnit then
return self.DCSUnit
end
return nil return nil
end end
@@ -313,19 +320,36 @@ function UNIT:IsActive()
return nil return nil
end end
--- Returns if the Unit is alive. --- Returns if the unit is exists in the mission.
-- If the Unit is not alive, nil is returned. -- If not even the DCS unit object does exist, `nil` is returned.
-- If the Unit is alive and active, true is returned. -- If the unit object exists, the value of the DCS API function [isExist](https://wiki.hoggitworld.com/view/DCS_func_isExist) is returned.
-- If the Unit is alive but not active, false is returned.
-- @param #UNIT self -- @param #UNIT self
-- @return #boolean `true` if Unit is alive and active. `false` if Unit is alive but not active. `nil` if the Unit is not existing or is not alive. -- @return #boolean Returns `true` if unit exists in the mission.
function UNIT:IsExist()
local DCSUnit = self:GetDCSObject() -- DCS#Unit
if DCSUnit then
local exists = DCSUnit:isExist()
return exists
end
return nil
end
--- Returns if the Unit is alive.
-- If the Unit is not alive/existent, `nil` is returned.
-- If the Unit is alive and active, `true` is returned.
-- If the Unit is alive but not active, `false`` is returned.
-- @param #UNIT self
-- @return #boolean Returns `true` if Unit is alive and active, `false` if it exists but is not active and `nil` if the object does not exist or DCS `isExist` function returns false.
function UNIT:IsAlive() function UNIT:IsAlive()
self:F3( self.UnitName ) self:F3( self.UnitName )
local DCSUnit = self:GetDCSObject() -- DCS#Unit local DCSUnit = self:GetDCSObject() -- DCS#Unit
if DCSUnit then if DCSUnit and DCSUnit:isExist() then
local UnitIsAlive = DCSUnit:isExist() and DCSUnit:isActive() -- and DCSUnit:getLife() > 1 local UnitIsAlive = DCSUnit:isActive()
return UnitIsAlive return UnitIsAlive
end end
@@ -677,17 +701,24 @@ end
-- @return DCS#Unit.Ammo Table with ammuntion of the unit (or nil). This can be a complex table! -- @return DCS#Unit.Ammo Table with ammuntion of the unit (or nil). This can be a complex table!
function UNIT:GetAmmo() function UNIT:GetAmmo()
self:F2( self.UnitName ) self:F2( self.UnitName )
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
if DCSUnit then if DCSUnit then
--local status, unitammo = pcall(
-- function()
-- local UnitAmmo = DCSUnit:getAmmo()
-- return UnitAmmo
--end
--)
--if status then
--return unitammo
--end
local UnitAmmo = DCSUnit:getAmmo() local UnitAmmo = DCSUnit:getAmmo()
return UnitAmmo return UnitAmmo
end end
return nil return nil
end end
--- Sets the Unit's Internal Cargo Mass, in kg --- Sets the Unit's Internal Cargo Mass, in kg
-- @param #UNIT self -- @param #UNIT self
-- @param #number mass to set cargo to -- @param #number mass to set cargo to