Merge branch 'FF/Ops' into FF/OpsRat

This commit is contained in:
Frank
2024-03-24 17:59:27 +01:00
53 changed files with 3631 additions and 2476 deletions

View File

@@ -9755,7 +9755,7 @@ function AIRBOSS:_Groove( playerData )
local glideslopeError = groovedata.GSE
local AoA = groovedata.AoA
if rho <= RXX and playerData.step == AIRBOSS.PatternStep.GROOVE_XX and (math.abs( groovedata.Roll ) <= 4.0 or playerData.unit:IsInZone( self:_GetZoneLineup() )) then
if rho <= RXX and playerData.step == AIRBOSS.PatternStep.GROOVE_XX and (math.abs( groovedata.Roll ) <= 4.0 and playerData.unit:IsInZone( self:_GetZoneLineup() )) then
-- Start time in groove
playerData.TIG0 = timer.getTime()
@@ -12123,16 +12123,18 @@ function AIRBOSS:_LSOgrade( playerData )
local GIC, nIC = self:_Flightdata2Text( playerData, AIRBOSS.GroovePos.IC )
local GAR, nAR = self:_Flightdata2Text( playerData, AIRBOSS.GroovePos.AR )
-- VTOL approach, which is graded differently (currently only Harrier).
local vtol=playerData.actype==AIRBOSS.AircraftCarrier.AV8B
-- Put everything together.
local G = GXX .. " " .. GIM .. " " .. " " .. GIC .. " " .. GAR
-- Count number of minor, normal and major deviations.
-- Count number of minor/small nS, normal nN and major/large deviations nL.
local N=nXX+nIM+nIC+nAR
local Nv=nXX+nIM
local nL=count(G, '_')/2
local nS=count(G, '%(')
local nN=N-nS-nL
local nNv=Nv-nS-nL
-- Groove time 15-18.99 sec for a unicorn. Or 60-65 for V/STOL unicorn.
local Tgroove=playerData.Tgroove
@@ -12148,34 +12150,64 @@ function AIRBOSS:_LSOgrade( playerData )
G = "Unicorn"
else
-- Add AV-8B Harrier devation allowances due to lower groundspeed and 3x conventional groove time, this allows to maintain LSO tolerances while respecting the deviations are not unsafe.--Pene testing
-- Large devaitions still result in a No Grade, A Unicorn still requires a clean pass with no deviation.
if nL > 1 and playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
-- Larger deviations ==> "No grade" 2.0 points.
grade="--"
points=2.0
elseif nNv >= 1 and playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
-- Only average deviations ==> "Fair Pass" Pass with average deviations and corrections.
grade="(OK)"
points=3.0
elseif nNv < 1 and playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
-- Only minor average deviations ==> "OK" Pass with minor deviations and corrections. (test nNv<=1 and)
grade="OK"
points=4.0
elseif nL > 0 then
-- Larger deviations ==> "No grade" 2.0 points.
grade="--"
points=2.0
elseif nN> 0 then
-- No larger but average deviations ==> "Fair Pass" Pass with average deviations and corrections.
grade="(OK)"
points=3.0
else
-- Only minor corrections
grade="OK"
points=4.0
end
if vtol then
-- Add AV-8B Harrier devation allowances due to lower groundspeed and 3x conventional groove time, this allows to maintain LSO tolerances while respecting the deviations are not unsafe.--Pene testing
-- Large devaitions still result in a No Grade, A Unicorn still requires a clean pass with no deviation.
-- Normal laning part at the beginning
local Gb = GXX .. " " .. GIM
-- Number of deviations that occurred at the the beginning of the landing (XX or IM). These are graded like in non-VTOL landings, i.e. on deviations is
local N=nXX+nIM
local nL=count(Gb, '_')/2
local nS=count(Gb, '%(')
local nN=N-nS-nL
-- VTOL part of the landing
local Gv = GIC .. " " .. GAR
-- Number of deviations that occurred at the the end (VTOL part) of the landing (IC or AR).
local Nv=nIC+nAR
local nLv=count(Gv, '_')/2
local nSv=count(Gv, '%(')
local nNv=Nv-nSv-nLv
if nL>0 or nLv>1 then
-- Larger deviations at XX or IM or at least one larger deviation IC or AR==> "No grade" 2.0 points.
-- In other words, we allow one larger deviation at IC+AR
grade="--"
points=2.0
elseif nN>0 or nNv>1 or nLv==1 then
-- Average deviations at XX+IM or more than one normal deviation IC or AR ==> "Fair Pass" Pass with average deviations and corrections.
grade="(OK)"
points=3.0
else
-- Only minor corrections
grade="OK"
points=4.0
end
else
-- This is a normal (non-VTOL) landing.
if nL > 0 then
-- Larger deviations ==> "No grade" 2.0 points.
grade="--"
points=2.0
elseif nN> 0 then
-- No larger but average/normal deviations ==> "Fair Pass" Pass with average deviations and corrections.
grade="(OK)"
points=3.0
else
-- Only minor corrections ==> "Okay pass" 4.0 points.
grade="OK"
points=4.0
end
end
end
-- Replace" )"( and "__"

File diff suppressed because it is too large Load Diff

View File

@@ -145,7 +145,7 @@
-- @field #table NassetsLegMax Number of required warehouse assets for each assigned legion.
-- @field #table requestID The ID of the queued warehouse request. Necessary to cancel the request if the mission was cancelled before the request is processed.
-- @field #table payloads User specified airwing payloads for this mission. Only these will be considered for the job!
-- @field Ops.AirWing#AIRWING.PatrolData patroldata Patrol data.
-- @field Ops.Airwing#AIRWING.PatrolData patroldata Patrol data.
--
-- @field #table specialLegions User specified legions assigned for this mission. Only these will be considered for the job!
-- @field #table specialCohorts User specified cohorts assigned for this mission. Only these will be considered for the job!
@@ -338,7 +338,7 @@
--
-- ## Legion Level
--
-- Adding an AUFTRAG to an airwing is done via the @{Ops.AirWing#AIRWING.AddMission} function. See AIRWING docs for further details.
-- Adding an AUFTRAG to an airwing is done via the @{Ops.Airwing#AIRWING.AddMission} function. See AIRWING docs for further details.
-- Similarly, an AUFTRAG can be added to a brigade via the @{Ops.Brigade#BRIGADE.AddMission} function.
--
-- ## Commander Level
@@ -3734,7 +3734,7 @@ end
--- Add a required payload for this mission. Only these payloads will be used for this mission. If they are not available, the mission cannot start. Only available for use with an AIRWING.
-- @param #AUFTRAG self
-- @param Ops.AirWing#AIRWING.Payload Payload Required payload.
-- @param Ops.Airwing#AIRWING.Payload Payload Required payload.
-- @return #AUFTRAG self
function AUFTRAG:AddRequiredPayload(Payload)

View File

@@ -36,7 +36,7 @@ do
-- @field #number Frequency
-- @field #number Modulation
-- @field Wrapper.Airbase#AIRBASE Airbase
-- @field Ops.AirWing#AIRWING AirWing
-- @field Ops.Airwing#AIRWING AirWing
-- @field #number AwacsAngels
-- @field Core.Zone#ZONE OrbitZone
-- @field #number CallSign
@@ -159,10 +159,10 @@ do
--
-- ## 3 Airwing(s)
--
-- The AWACS plane, the optional escort planes, and the AI CAP planes work based on the @{Ops.AirWing} class. Read and understand the manual for this class in
-- The AWACS plane, the optional escort planes, and the AI CAP planes work based on the @{Ops.Airwing} class. Read and understand the manual for this class in
-- order to set everything up correctly. You will at least need one Squadron containing the AWACS plane itself.
--
-- Set up the AirWing
-- Set up the Airwing
--
-- local AwacsAW = AIRWING:New("AirForce WH-1","AirForce One")
-- AwacsAW:SetMarker(false)
@@ -226,7 +226,7 @@ do
--
-- ## 5 Set up AWACS
--
-- -- Set up AWACS called "AWACS North". It will use the AwacsAW AirWing set up above and be of the "blue" coalition. Homebase is Kutaisi.
-- -- Set up AWACS called "AWACS North". It will use the AwacsAW Airwing set up above and be of the "blue" coalition. Homebase is Kutaisi.
-- -- The AWACS Orbit Zone is a round zone set in the mission editor named "Awacs Orbit", the FEZ is a Polygon-Zone called "Rock" we have also
-- -- set up in the mission editor with a late activated helo named "Rock#ZONE_POLYGON". Note this also sets the BullsEye to be referenced as "Rock".
-- -- The CAP station zone is called "Fremont". We will be on 255 AM.
@@ -248,7 +248,7 @@ do
--
-- ### 5.1 Alternative - Set up as GCI (no AWACS plane needed) Theater Air Control System (TACS)
--
-- -- Set up as TACS called "GCI Senaki". It will use the AwacsAW AirWing set up above and be of the "blue" coalition. Homebase is Senaki.
-- -- Set up as TACS called "GCI Senaki". It will use the AwacsAW Airwing set up above and be of the "blue" coalition. Homebase is Senaki.
-- -- No need to set the AWACS Orbit Zone; the FEZ is still a Polygon-Zone called "Rock" we have also
-- -- set up in the mission editor with a late activated helo named "Rock#ZONE_POLYGON". Note this also sets the BullsEye to be referenced as "Rock".
-- -- The CAP station zone is called "Fremont". We will be on 255 AM. Note the Orbit Zone is given as *nil* in the `New()`-Statement
@@ -508,7 +508,7 @@ do
-- @field #AWACS
AWACS = {
ClassName = "AWACS", -- #string
version = "0.2.61", -- #string
version = "0.2.64", -- #string
lid = "", -- #string
coalition = coalition.side.BLUE, -- #number
coalitiontxt = "blue", -- #string
@@ -852,8 +852,8 @@ AWACS.Messages = {
--- Contact Data
-- @type AWACS.ManagedContact
-- @field #number CID
-- @field Ops.Intelligence#INTEL.Contact Contact
-- @field Ops.Intelligence#INTEL.Cluster Cluster
-- @field Ops.Intel#INTEL.Contact Contact
-- @field Ops.Intel#INTEL.Cluster Cluster
-- @field #string IFF -- ID'ed or not (yet)
-- @field Ops.Target#TARGET Target
-- @field #number LinkedTask --> TID
@@ -902,8 +902,8 @@ AWACS.TaskStatus = {
-- @field #AWACS.TaskStatus Status
-- @field #AWACS.TaskDescription ToDo
-- @field #string ScreenText Long descrition
-- @field Ops.Intelligence#INTEL.Contact Contact
-- @field Ops.Intelligence#INTEL.Cluster Cluster
-- @field Ops.Intel#INTEL.Contact Contact
-- @field Ops.Intel#INTEL.Cluster Cluster
-- @field #number CurrentAuftrag
-- @field #number RequestedTimestamp
@@ -956,7 +956,7 @@ AWACS.TaskStatus = {
-- DONE - Shift Change, Change on asset RTB or dead or mission done (done for AWACS and Escorts)
-- DONE - TripWire - WIP - Threat (35nm), Meld (45nm, on mission), Merged (<3nm)
--
-- DONE - Escorts via AirWing not staying on
-- DONE - Escorts via Airwing not staying on
-- DONE - Borders for INTEL. Optional, i.e. land based defense within borders
-- DONE - Use AO as Anchor of Bulls, AO as default
-- DONE - SRS TTS output
@@ -984,7 +984,7 @@ AWACS.TaskStatus = {
--- Set up a new AI AWACS.
-- @param #AWACS self
-- @param #string Name Name of this AWACS for the radio menu.
-- @param #string AirWing The core Ops.AirWing#AIRWING managing the AWACS, Escort and (optionally) AI CAP planes for us.
-- @param #string AirWing The core Ops.Airwing#AIRWING managing the AWACS, Escort and (optionally) AI CAP planes for us.
-- @param #number Coalition Coalition, e.g. coalition.side.BLUE. Can also be passed as "blue", "red" or "neutral".
-- @param #string AirbaseName Name of the home airbase.
-- @param #string AwacsOrbit Name of the round, mission editor created zone where this AWACS orbits.
@@ -1024,7 +1024,7 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station
-- base setup
self.Name = Name -- #string
self.AirWing = AirWing -- Ops.AirWing#AIRWING object
self.AirWing = AirWing -- Ops.Airwing#AIRWING object
AirWing:SetUsingOpsAwacs(self)
@@ -1032,7 +1032,7 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station
self.CAPAirwings:Push(AirWing,1)
self.AwacsFG = nil
--self.AwacsPayload = PayLoad -- Ops.AirWing#AIRWING.Payload
--self.AwacsPayload = PayLoad -- Ops.Airwing#AIRWING.Payload
--self.ModernEra = true -- use of EPLRS
self.RadarBlur = 15 -- +/-15% detection precision i.e. 85-115 reported group size
if type(OpsZone) == "string" then
@@ -1384,7 +1384,7 @@ end
-- Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- [User] Set the tactical information option, create 10 radio channels groups can subscribe and get Bogey Dope on a specific frequency automatically.
--- [User] Set the tactical information option, create 10 radio channels groups can subscribe and get Bogey Dope on a specific frequency automatically. You **need** to set up SRS first before using this!
-- @param #AWACS self
-- @param #number BaseFreq Base Frequency to use, defaults to 130.
-- @param #number Increase Increase to use, defaults to 0.5, thus channels created are 130, 130.5, 131 .. etc.
@@ -1394,6 +1394,10 @@ end
-- @return #AWACS self
function AWACS:SetTacticalRadios(BaseFreq,Increase,Modulation,Interval,Number)
self:T(self.lid.."SetTacticalRadios")
if not self.AwacsSRS then
MESSAGE:New("AWACS: Setup SRS in your code BEFORE trying to add tac radios please!",30,"ERROR",true):ToLog():ToAll()
return self
end
self.TacticalMenu = true
self.TacticalBaseFreq = BaseFreq or 130
self.TacticalIncrFreq = Increase or 0.5
@@ -1407,7 +1411,7 @@ function AWACS:SetTacticalRadios(BaseFreq,Increase,Modulation,Interval,Number)
self.TacticalFrequencies[freq] = freq
end
if self.AwacsSRS then
self.TacticalSRS = MSRS:New(self.PathToSRS,self.TacticalBaseFreq,self.TacticalModulation)
self.TacticalSRS = MSRS:New(self.PathToSRS,self.TacticalBaseFreq,self.TacticalModulation,self.Backend)
self.TacticalSRS:SetCoalition(self.coalition)
self.TacticalSRS:SetGender(self.Gender)
self.TacticalSRS:SetCulture(self.Culture)
@@ -2085,8 +2089,9 @@ end
-- @param #number Volume Volume - between 0.0 (silent) and 1.0 (loudest)
-- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS; if you use a config file for MSRS, hand in nil here.
-- @param #string AccessKey (Optional) Your Google API access key. This is necessary if DCS-gRPC is used as backend; if you use a config file for MSRS, hand in nil here.
-- @param #string Backend (Optional) Your MSRS Backend if different from your config file settings, e.g. MSRS.Backend.SRSEXE or MSRS.Backend.GRPC
-- @return #AWACS self
function AWACS:SetSRS(PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,AccessKey)
function AWACS:SetSRS(PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,AccessKey,Backend)
self:T(self.lid.."SetSRS")
self.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
self.Gender = Gender or MSRS.gender or "male"
@@ -2096,8 +2101,9 @@ function AWACS:SetSRS(PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey
self.PathToGoogleKey = PathToGoogleKey
self.AccessKey = AccessKey
self.Volume = Volume or 1.0
self.AwacsSRS = MSRS:New(self.PathToSRS,self.MultiFrequency,self.MultiModulation)
self.Backend = Backend or MSRS.backend
BASE:I({backend = self.Backend})
self.AwacsSRS = MSRS:New(self.PathToSRS,self.MultiFrequency,self.MultiModulation,self.Backend)
self.AwacsSRS:SetCoalition(self.coalition)
self.AwacsSRS:SetGender(self.Gender)
self.AwacsSRS:SetCulture(self.Culture)
@@ -2463,7 +2469,7 @@ function AWACS:_UpdateContactFromCluster(CID)
local function GetFirstAliveContact(table)
for _,_contact in pairs (table) do
local contact = _contact -- Ops.Intelligence#INTEL.Contact
local contact = _contact -- Ops.Intel#INTEL.Contact
if contact and contact.group and contact.group:IsAlive() then
return contact
end
@@ -2499,13 +2505,22 @@ function AWACS:_CheckMerges()
local cpos = contact.Cluster.coordinate or contact.Contact.position or contact.Contact.group:GetCoordinate()
local dist = ppos:Get2DDistance(cpos)
local distnm = UTILS.Round(UTILS.MetersToNM(dist),0)
if (pilot.IsPlayer or self.debug) and distnm <= 5 and not contact.MergeCallDone then
local label = contact.EngagementTag or ""
if not contact.MergeCallDone or not string.find(label,pcallsign) then
if (pilot.IsPlayer or self.debug) and distnm <= 5 then --and ((not contact.MergeCallDone) or (timer.getTime() - contact.MergeCallDone > 30)) then
--local label = contact.EngagementTag or ""
--if not contact.MergeCallDone or not string.find(label,pcallsign) then
self:T(self.lid.."Merged")
self:_MergedCall(_id)
contact.MergeCallDone = true
end
--contact.MergeCallDone = true
--end
end
if (pilot.IsPlayer or self.debug) and distnm >5 and distnm <= self.ThreatDistance then
self:_ThreatRangeCall(_id,Contact)
end
if (pilot.IsPlayer or self.debug) and distnm > self.ThreatDistance and distnm <= self.MeldDistance then
self:_MeldRangeCall(_id,Contact)
end
if (pilot.IsPlayer or self.debug) and distnm > self.MeldDistance and distnm <= self.TacDistance then
self:_TACRangeCall(_id,Contact)
end
end
)
@@ -3099,7 +3114,7 @@ function AWACS:_BogeyDope(Group,Tactical)
local clean = self.gettext:GetEntry("CLEAN",self.locale)
text = string.format(clean,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
self:_NewRadioEntry(text,textScreen,GID,Outcome,Outcome,true,false,true,Tactical)
self:_NewRadioEntry(text,text,GID,Outcome,Outcome,true,false,true,Tactical)
else
@@ -3141,9 +3156,13 @@ end
function AWACS:_ShowAwacsInfo(Group)
self:T(self.lid.."_ShowAwacsInfo")
local report = REPORT:New("Info")
local STN = self.STN
report:Add("====================")
report:Add(string.format("AWACS %s",self.callsigntxt))
report:Add(string.format("Radio: %.3f %s",self.Frequency,UTILS.GetModulationName(self.Modulation)))
if STN then
report:Add(string.format("Link-16 STN: %s",STN))
end
report:Add(string.format("Bulls Alias: %s",self.AOName))
report:Add(string.format("Coordinate: %s",self.AOCoordinate:ToStringLLDDM()))
report:Add("====================")
@@ -4260,7 +4279,7 @@ function AWACS:_StartIntel(awacs)
intel:__Start(5)
self.intel = intel -- Ops.Intelligence#INTEL
self.intel = intel -- Ops.Intel#INTEL
return self
end
@@ -4420,8 +4439,8 @@ end
-- @param #table Object Object for Ops.Target#TARGET assignment
-- @param #AWACS.TaskStatus TaskStatus Status of this task
-- @param Ops.Auftrag#AUFTRAG Auftrag The Auftrag for this task if any
-- @param Ops.Intelligence#INTEL.Cluster Cluster Intel Cluster for this task
-- @param Ops.Intelligence#INTEL.Contact Contact Intel Contact for this task
-- @param Ops.Intel#INTEL.Cluster Cluster Intel Cluster for this task
-- @param Ops.Intel#INTEL.Contact Contact Intel Contact for this task
-- @return #number TID Task ID created
function AWACS:_CreateTaskForGroup(GroupID,Description,ScreenText,Object,TaskStatus,Auftrag,Cluster,Contact)
self:T(self.lid.."_CreateTaskForGroup "..GroupID .." Description: "..Description)
@@ -4620,7 +4639,7 @@ function AWACS:_CheckTaskQueue()
-- Check ranges for TAC and MELD
-- postions relative to CAP position
--[[
local targetgrp = entry.Contact.group
local position = entry.Contact.position or entry.Cluster.coordinate
if targetgrp and targetgrp:IsAlive() and managedgroup then
@@ -4645,6 +4664,7 @@ function AWACS:_CheckTaskQueue()
end
end
end
--]]
local auftrag = entry.Auftrag -- Ops.Auftrag#AUFTRAG
local auftragstatus = "Not Known"
@@ -4843,6 +4863,7 @@ function AWACS:_CheckTaskQueue()
elseif entry.Status == AWACS.TaskStatus.ASSIGNED then
self:T("Open Tasks VID ASSIGNED for GroupID "..entry.AssignedGroupID)
-- check TAC/MELD ranges
--[[
local targetgrp = entry.Contact.group
local position = entry.Contact.position or entry.Cluster.coordinate
if targetgrp and targetgrp:IsAlive() and managedgroup then
@@ -4867,6 +4888,7 @@ function AWACS:_CheckTaskQueue()
end
end
end
--]]
elseif entry.Status == AWACS.TaskStatus.SUCCESS then
self:T("Open Tasks VID success for GroupID "..entry.AssignedGroupID)
-- outcomes - player ID'd
@@ -4978,7 +5000,7 @@ end
--- [User] Add another AirWing for AI CAP Flights under management
-- @param #AWACS self
-- @param Ops.AirWing#AIRWING AirWing The AirWing to (also) obtain CAP flights from
-- @param Ops.Airwing#AIRWING AirWing The AirWing to (also) obtain CAP flights from
-- @param Core.Zone#ZONE_RADIUS Zone (optional) This AirWing has it's own station zone, AI CAP will be send there
-- @return #AWACS self
function AWACS:AddCAPAirWing(AirWing,Zone)
@@ -5063,7 +5085,7 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo
end
local cluster = Contact.Cluster
local intel = self.intel -- Ops.Intelligence#INTEL
local intel = self.intel -- Ops.Intel#INTEL
local size = self.intel:ClusterCountUnits(cluster)
local threatsize, threatsizetext = self:_GetBlurredSize(size)
@@ -5465,9 +5487,10 @@ function AWACS:_TACRangeCall(GID,Contact)
if not Contact then return self end
local pilotcallsign = self:_GetCallSign(nil,GID)
local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup
local contact = Contact.Contact -- Ops.Intelligence#INTEL.Contact
local contact = Contact.Contact -- Ops.Intel#INTEL.Contact
local contacttag = Contact.TargetGroupNaming
if contact and not Contact.TACCallDone then
local name = managedgroup.GroupName
if contact then --and not Contact.TACCallDone then
local position = contact.position -- Core.Point#COORDINATE
if position then
local distance = position:Get2DDistance(managedgroup.Group:GetCoordinate())
@@ -5475,8 +5498,18 @@ function AWACS:_TACRangeCall(GID,Contact)
local grptxt = self.gettext:GetEntry("GROUP",self.locale)
local miles = self.gettext:GetEntry("MILES",self.locale)
local text = string.format("%s. %s. %s %s, %d %s.",self.callsigntxt,pilotcallsign,contacttag,grptxt,distance,miles)
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
if not self.TacticalSubscribers[name] then
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
end
self:_UpdateContactEngagementTag(Contact.CID,Contact.EngagementTag,true,false,AWACS.TaskStatus.EXECUTING)
if GID and GID ~= 0 then
--local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup
if managedgroup and managedgroup.Group and managedgroup.Group:IsAlive() then
if self.TacticalSubscribers[name] then
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true,true)
end
end
end
end
end
return self
@@ -5494,9 +5527,10 @@ function AWACS:_MeldRangeCall(GID,Contact)
local pilotcallsign = self:_GetCallSign(nil,GID)
local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup
local flightpos = managedgroup.Group:GetCoordinate()
local contact = Contact.Contact -- Ops.Intelligence#INTEL.Contact
local contacttag = Contact.TargetGroupNaming
if contact and not Contact.MeldCallDone then
local contact = Contact.Contact -- Ops.Intel#INTEL.Contact
local contacttag = Contact.TargetGroupNaming or "Bogey"
local name = managedgroup.GroupName
if contact then --and not Contact.MeldCallDone then
local position = contact.position -- Core.Point#COORDINATE
if position then
local BRATExt = ""
@@ -5507,8 +5541,19 @@ function AWACS:_MeldRangeCall(GID,Contact)
end
local grptxt = self.gettext:GetEntry("GROUP",self.locale)
local text = string.format("%s. %s. %s %s, %s",self.callsigntxt,pilotcallsign,contacttag,grptxt,BRATExt)
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
if not self.TacticalSubscribers[name] then
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
end
self:_UpdateContactEngagementTag(Contact.CID,Contact.EngagementTag,true,true,AWACS.TaskStatus.EXECUTING)
if GID and GID ~= 0 then
--local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup
if managedgroup and managedgroup.Group and managedgroup.Group:IsAlive() then
local name = managedgroup.GroupName
if self.TacticalSubscribers[name] then
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true,true)
end
end
end
end
end
return self
@@ -5524,8 +5569,10 @@ function AWACS:_ThreatRangeCall(GID,Contact)
local pilotcallsign = self:_GetCallSign(nil,GID)
local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup
local flightpos = managedgroup.Group:GetCoordinate() or managedgroup.LastKnownPosition
local contact = Contact.Contact -- Ops.Intelligence#INTEL.Contact
local contacttag = Contact.TargetGroupNaming
local contact = Contact.Contact -- Ops.Intel#INTEL.Contact
local contacttag = Contact.TargetGroupNaming or "Bogey"
local name = managedgroup.GroupName
local IsSub = self.TacticalSubscribers[name] and true or false
if contact then
local position = contact.position or contact.group:GetCoordinate() -- Core.Point#COORDINATE
if position then
@@ -5538,7 +5585,18 @@ function AWACS:_ThreatRangeCall(GID,Contact)
local grptxt = self.gettext:GetEntry("GROUP",self.locale)
local thrt = self.gettext:GetEntry("THREAT",self.locale)
local text = string.format("%s. %s. %s %s, %s. %s",self.callsigntxt,pilotcallsign,contacttag,grptxt, thrt, BRATExt)
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
if IsSub == false then
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
end
if GID and GID ~= 0 then
--local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup
if managedgroup and managedgroup.Group and managedgroup.Group:IsAlive() then
local name = managedgroup.GroupName
if self.TacticalSubscribers[name] then
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true,true)
end
end
end
end
end
return self
@@ -5554,11 +5612,17 @@ function AWACS:_MergedCall(GID)
local pilotcallsign = self:_GetCallSign(nil,GID)
local merge = self.gettext:GetEntry("MERGED",self.locale)
local text = string.format("%s. %s. %s.",self.callsigntxt,pilotcallsign,merge)
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup
local name
if managedgroup then
name = managedgroup.GroupName or "none"
end
if not self.TacticalSubscribers[name] then
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
end
if GID and GID ~= 0 then
local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup
if managedgroup and managedgroup.Group and managedgroup.Group:IsAlive() then
local name = managedgroup.GroupName
if managedgroup and managedgroup.Group and managedgroup.Group:IsAlive() then
if self.TacticalSubscribers[name] then
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true,true)
end
@@ -5832,7 +5896,7 @@ function AWACS:onafterStart(From, Event, To)
if not self.GCI then
-- set up the AWACS and let it orbit
local AwacsAW = self.AirWing -- Ops.AirWing#AIRWING
local AwacsAW = self.AirWing -- Ops.Airwing#AIRWING
local mission = AUFTRAG:NewORBIT_RACETRACK(self.OrbitZone:GetCoordinate(),self.AwacsAngels*1000,self.Speed,self.Heading,self.Leg)
local timeonstation = (self.AwacsTimeOnStation + self.ShiftChangeTime) * 3600
mission:SetTime(nil,timeonstation)
@@ -5953,6 +6017,10 @@ function AWACS:_CheckAwacsStatus()
local awacs = nil -- Wrapper.Group#GROUP
if self.AwacsFG then
awacs = self.AwacsFG:GetGroup() -- Wrapper.Group#GROUP
local unit = awacs:GetUnit(1)
if unit then
self.STN = tostring(unit:GetSTN())
end
end
local monitoringdata = self.MonitoringData -- #AWACS.MonitoringData
@@ -6426,7 +6494,7 @@ end
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Ops.Intelligence#INTEL.Cluster Cluster
-- @param Ops.Intel#INTEL.Cluster Cluster
-- @return #AWACS self
function AWACS:onafterNewCluster(From,Event,To,Cluster)
self:T({From, Event, To, Cluster.index})
@@ -6438,7 +6506,7 @@ function AWACS:onafterNewCluster(From,Event,To,Cluster)
local function GetFirstAliveContact(table)
for _,_contact in pairs (table) do
local contact = _contact -- Ops.Intelligence#INTEL.Contact
local contact = _contact -- Ops.Intel#INTEL.Contact
if contact and contact.group and contact.group:IsAlive() then
return contact, contact.group
end
@@ -6446,7 +6514,7 @@ function AWACS:onafterNewCluster(From,Event,To,Cluster)
return nil
end
local Contact, Group = GetFirstAliveContact(ContactTable) -- Ops.Intelligence#INTEL.Contact
local Contact, Group = GetFirstAliveContact(ContactTable) -- Ops.Intel#INTEL.Contact
if not Contact then return self end
@@ -6457,7 +6525,7 @@ function AWACS:onafterNewCluster(From,Event,To,Cluster)
local targetset = SET_GROUP:New()
-- SET for TARGET
for _,_grp in pairs(ContactTable) do
local grp = _grp -- Ops.Intelligence#INTEL.Contact
local grp = _grp -- Ops.Intel#INTEL.Contact
targetset:AddGroup(grp.group, true)
end
local managedcontact = {} -- #AWACS.ManagedContact
@@ -6519,7 +6587,7 @@ end
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Ops.Intelligence#INTEL.Contact Contact
-- @param Ops.Intel#INTEL.Contact Contact
-- @return #AWACS self
function AWACS:onafterNewContact(From,Event,To,Contact)
self:T({From, Event, To, Contact})
@@ -6548,7 +6616,7 @@ end
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Ops.Intelligence#INTEL.Contact Contact
-- @param Ops.Intel#INTEL.Contact Contact
-- @return #AWACS self
function AWACS:onafterLostContact(From,Event,To,Contact)
self:T({From, Event, To, Contact})
@@ -6560,7 +6628,7 @@ end
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Ops.Intelligence#INTEL.Cluster Cluster
-- @param Ops.Intel#INTEL.Cluster Cluster
-- @param Ops.Auftrag#AUFTRAG Mission
-- @return #AWACS self
function AWACS:onafterLostCluster(From,Event,To,Cluster,Mission)
@@ -6632,7 +6700,7 @@ function AWACS:onafterCheckTacticalQueue(From,Event,To)
end -- end while
if self:Is("Running") then
if not self:Is("Stopped") then
self:__CheckTacticalQueue(-self.TacticalInterval)
end
return self
@@ -6761,7 +6829,7 @@ function AWACS:onafterAwacsShiftChange(From,Event,To)
self.AwacsTimeStamp = timer.getTime()
-- set up the AWACS and let it orbit
local AwacsAW = self.AirWing -- Ops.AirWing#AIRWING
local AwacsAW = self.AirWing -- Ops.Airwing#AIRWING
local mission = AUFTRAG:NewORBIT_RACETRACK(self.OrbitZone:GetCoordinate(),self.AwacsAngels*1000,self.Speed,self.Heading,self.Leg)
self.CatchAllMissions[#self.CatchAllMissions+1] = mission
local timeonstation = (self.AwacsTimeOnStation + self.ShiftChangeTime) * 3600

View File

@@ -313,8 +313,8 @@ end
--
-- local Path = FilePath or "C:\\Users\\<yourname>\\Saved Games\\DCS\\Missions\\" -- example path
-- local BlueOpsFilename = BlueFileName or "ExamplePlatoonSave.csv" -- example filename
-- local BlueSaveOps = SET_GROUP:New():FilterCoalitions("blue"):FilterPrefixes("AID"):FilterCategoryGround():FilterOnce()
-- UTILS.SaveSetOfGroups(BlueSaveOps,Path,BlueOpsFilename)
-- local BlueSaveOps = SET_OPSGROUP:New():FilterCoalitions("blue"):FilterCategoryGround():FilterOnce()
-- UTILS.SaveSetOfOpsGroups(BlueSaveOps,Path,BlueOpsFilename)
--
-- where Path and Filename are strings, as chosen by you.
-- You can then load back the assets at the start of your next mission run. Be aware that it takes a couple of seconds for the
@@ -324,7 +324,7 @@ end
-- local Path = FilePath or "C:\\Users\\<yourname>\\Saved Games\\DCS\\Missions\\" -- example path
-- local BlueOpsFilename = BlueFileName or "ExamplePlatoonSave.csv" -- example filename
-- if UTILS.CheckFileExists(Path,BlueOpsFilename) then
-- local loadback = UTILS.LoadSetOfGroups(Path,BlueOpsFilename,false)
-- local loadback = UTILS.LoadSetOfOpsGroups(Path,BlueOpsFilename,false)
-- for _,_platoondata in pairs (loadback) do
-- local groupname = _platoondata.groupname -- #string
-- local coordinate = _platoondata.coordinate -- Core.Point#COORDINATE

View File

@@ -290,10 +290,11 @@ CSAR.AircraftType["Bell-47"] = 2
CSAR.AircraftType["UH-60L"] = 10
CSAR.AircraftType["AH-64D_BLK_II"] = 2
CSAR.AircraftType["Bronco-OV-10A"] = 2
CSAR.AircraftType["MH-60R"] = 10
--- CSAR class version.
-- @field #string version
CSAR.version="1.0.19"
CSAR.version="1.0.20"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list

View File

@@ -24,7 +24,7 @@
-- @module Ops.CTLD
-- @image OPS_CTLD.jpg
-- Last Update December 2023
-- Last Update February 2024
do
@@ -44,6 +44,7 @@ do
-- @field #number PerCrateMass Mass in kg.
-- @field #number Stock Number of builds available, -1 for unlimited.
-- @field #string Subcategory Sub-category name.
-- @field #boolean DontShowInMenu Show this item in menu or not.
-- @extends Core.Base#BASE
---
@@ -62,6 +63,7 @@ CTLD_CARGO = {
PerCrateMass = 0,
Stock = nil,
Mark = nil,
DontShowInMenu = false,
}
--- Define cargo types.
@@ -97,8 +99,9 @@ CTLD_CARGO = {
-- @param #number PerCrateMass Mass in kg
-- @param #number Stock Number of builds available, nil for unlimited
-- @param #string Subcategory Name of subcategory, handy if using > 10 types to load.
-- @param #boolean DontShowInMenu Show this item in menu or not (default: false == show it).
-- @return #CTLD_CARGO self
function CTLD_CARGO:New(ID, Name, Templates, Sorte, HasBeenMoved, LoadDirectly, CratesNeeded, Positionable, Dropped, PerCrateMass, Stock, Subcategory)
function CTLD_CARGO:New(ID, Name, Templates, Sorte, HasBeenMoved, LoadDirectly, CratesNeeded, Positionable, Dropped, PerCrateMass, Stock, Subcategory,DontShowInMenu)
-- Inherit everything from BASE class.
local self=BASE:Inherit(self, BASE:New()) -- #CTLD_CARGO
self:T({ID, Name, Templates, Sorte, HasBeenMoved, LoadDirectly, CratesNeeded, Positionable, Dropped})
@@ -115,6 +118,7 @@ CTLD_CARGO = {
self.Stock = Stock or nil --#number
self.Mark = nil
self.Subcategory = Subcategory or "Other"
self.DontShowInMenu = DontShowInMenu or false
return self
end
@@ -1222,13 +1226,14 @@ CTLD.UnitTypeCapabilities = {
["Hercules"] = {type="Hercules", crates=true, troops=true, cratelimit = 7, trooplimit = 64, length = 25, cargoweightlimit = 19000}, -- 19t cargo, 64 paratroopers.
--Actually it's longer, but the center coord is off-center of the model.
["UH-60L"] = {type="UH-60L", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16, cargoweightlimit = 3500}, -- 4t cargo, 20 (unsec) seats
["MH-60R"] = {type="MH-60R", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16, cargoweightlimit = 3500}, -- 4t cargo, 20 (unsec) seats
["AH-64D_BLK_II"] = {type="AH-64D_BLK_II", crates=false, troops=true, cratelimit = 0, trooplimit = 2, length = 17, cargoweightlimit = 200}, -- 2 ppl **outside** the helo
["Bronco-OV-10A"] = {type="Bronco-OV-10A", crates= false, troops=true, cratelimit = 0, trooplimit = 5, length = 13, cargoweightlimit = 1450},
}
--- CTLD class version.
-- @field #string version
CTLD.version="1.0.45"
CTLD.version="1.0.48"
--- Instantiate a new CTLD.
-- @param #CTLD self
@@ -1433,7 +1438,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
--- Pseudo Functions ---
------------------------
--- Triggers the FSM event "Start". Starts the CTLD. Initializes parameters and starts event handlers.
--- Triggers the FSM event "Start". Starts the CTLD. Initializes parameters and starts event handlers.
-- @function [parent=#CTLD] Start
-- @param #CTLD self
@@ -3024,9 +3029,10 @@ end
function CTLD:_GetUnitPositions(Coordinate,Radius,Heading,Template)
local Positions = {}
local template = _DATABASE:GetGroupTemplate(Template)
UTILS.PrintTableToLog(template)
--UTILS.PrintTableToLog(template)
local numbertroops = #template.units
local newcenter = Coordinate:Translate(Radius,((Heading+270)%360))
local slightshift = math.abs(math.random(0,200)/100)
local newcenter = Coordinate:Translate(Radius+slightshift,((Heading+270)%360))
for i=1,360,math.floor(360/numbertroops) do
local phead = ((Heading+270+i)%360)
local post = newcenter:Translate(Radius,phead)
@@ -3038,7 +3044,7 @@ function CTLD:_GetUnitPositions(Coordinate,Radius,Heading,Template)
}
table.insert(Positions,p1t)
end
UTILS.PrintTableToLog(Positions)
--UTILS.PrintTableToLog(Positions)
return Positions
end
@@ -3700,14 +3706,20 @@ function CTLD:_RefreshF10Menus()
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)
local noshow = entry.DontShowInMenu
if not noshow then
menucount = menucount + 1
menus[menucount] = MENU_GROUP_COMMAND:New(_group,entry.Name,subcatmenus[subcat],self._LoadTroops, self, _group, _unit, entry)
end
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)
local noshow = entry.DontShowInMenu
if not noshow then
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()
@@ -3728,33 +3740,45 @@ function CTLD:_RefreshF10Menus()
for _,_entry in pairs(self.Cargo_Crates) do
local entry = _entry -- #CTLD_CARGO
local subcat = entry.Subcategory
menucount = menucount + 1
local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0)
menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,subcatmenus[subcat],self._GetCrates, self, _group, _unit, entry)
local noshow = entry.DontShowInMenu
if not noshow then
menucount = menucount + 1
local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0)
menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,subcatmenus[subcat],self._GetCrates, self, _group, _unit, entry)
end
end
for _,_entry in pairs(self.Cargo_Statics) do
local entry = _entry -- #CTLD_CARGO
local subcat = entry.Subcategory
menucount = menucount + 1
local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0)
menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,subcatmenus[subcat],self._GetCrates, self, _group, _unit, entry)
local noshow = entry.DontShowInMenu
if not noshow then
menucount = menucount + 1
local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0)
menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,subcatmenus[subcat],self._GetCrates, self, _group, _unit, entry)
end
end
else
for _,_entry in pairs(self.Cargo_Crates) do
local entry = _entry -- #CTLD_CARGO
menucount = menucount + 1
local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0)
menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,cratesmenu,self._GetCrates, self, _group, _unit, entry)
local noshow = entry.DontShowInMenu
if not noshow then
menucount = menucount + 1
local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0)
menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,cratesmenu,self._GetCrates, self, _group, _unit, entry)
end
end
for _,_entry in pairs(self.Cargo_Statics) do
local entry = _entry -- #CTLD_CARGO
menucount = menucount + 1
local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0)
menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,cratesmenu,self._GetCrates, self, _group, _unit, entry)
local noshow = entry.DontShowInMenu
if not noshow then
menucount = menucount + 1
local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0)
menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,cratesmenu,self._GetCrates, self, _group, _unit, entry)
end
end
end
listmenu = MENU_GROUP_COMMAND:New(_group,"List crates nearby",topcrates, self._ListCratesNearby, self, _group, _unit)
removecrates = MENU_GROUP_COMMAND:New(_group,"Remove crates nearby",removecratesmenu, self._RemoveCratesNearby, self, _group, _unit)
local removecrates = MENU_GROUP_COMMAND:New(_group,"Remove crates nearby",removecratesmenu, self._RemoveCratesNearby, self, _group, _unit)
local unloadmenu = MENU_GROUP_COMMAND:New(_group,"Drop crates",topcrates, self._UnloadCrates, self, _group, _unit)
if not self.nobuildmenu then
local buildmenu = MENU_GROUP_COMMAND:New(_group,"Build crates",topcrates, self._BuildCrates, self, _group, _unit)

View File

@@ -140,7 +140,7 @@ COMMANDER = {
--- COMMANDER class version.
-- @field #string version
COMMANDER.version="0.1.3"
COMMANDER.version="0.1.4"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@@ -675,7 +675,8 @@ function COMMANDER:AddCapZone(Zone, Altitude, Speed, Heading, Leg)
patrolzone.zone=Zone
patrolzone.altitude=Altitude or 12000
patrolzone.heading=Heading or 270
patrolzone.speed=UTILS.KnotsToAltKIAS(Speed or 350, patrolzone.altitude)
--patrolzone.speed=UTILS.KnotsToAltKIAS(Speed or 350, patrolzone.altitude)
patrolzone.speed=Speed or 350
patrolzone.leg=Leg or 30
patrolzone.mission=nil
--patrolzone.marker=MARKER:New(patrolzone.zone:GetCoordinate(), "CAP Zone"):ToCoalition(self:GetCoalition())
@@ -700,7 +701,8 @@ function COMMANDER:AddGciCapZone(Zone, Altitude, Speed, Heading, Leg)
patrolzone.zone=Zone
patrolzone.altitude=Altitude or 12000
patrolzone.heading=Heading or 270
patrolzone.speed=UTILS.KnotsToAltKIAS(Speed or 350, patrolzone.altitude)
--patrolzone.speed=UTILS.KnotsToAltKIAS(Speed or 350, patrolzone.altitude)
patrolzone.speed=Speed or 350
patrolzone.leg=Leg or 30
patrolzone.mission=nil
--patrolzone.marker=MARKER:New(patrolzone.zone:GetCoordinate(), "GCICAP Zone"):ToCoalition(self:GetCoalition())
@@ -745,7 +747,9 @@ function COMMANDER:AddAwacsZone(Zone, Altitude, Speed, Heading, Leg)
awacszone.zone=Zone
awacszone.altitude=Altitude or 12000
awacszone.heading=Heading or 270
awacszone.speed=UTILS.KnotsToAltKIAS(Speed or 350, awacszone.altitude)
--awacszone.speed=UTILS.KnotsToAltKIAS(Speed or 350, awacszone.altitude)
awacszone.speed=Speed or 350
awacszone.speed=Speed or 350
awacszone.leg=Leg or 30
awacszone.mission=nil
--awacszone.marker=MARKER:New(awacszone.zone:GetCoordinate(), "AWACS Zone"):ToCoalition(self:GetCoalition())
@@ -791,7 +795,8 @@ function COMMANDER:AddTankerZone(Zone, Altitude, Speed, Heading, Leg, RefuelSyst
tankerzone.zone=Zone
tankerzone.altitude=Altitude or 12000
tankerzone.heading=Heading or 270
tankerzone.speed=UTILS.KnotsToAltKIAS(Speed or 350, tankerzone.altitude)
--tankerzone.speed=UTILS.KnotsToAltKIAS(Speed or 350, tankerzone.altitude) -- speed translation to alt will be done by AUFTRAG anyhow
tankerzone.speed = Speed or 350
tankerzone.leg=Leg or 30
tankerzone.refuelsystem=RefuelSystem
tankerzone.mission=nil

View File

@@ -702,7 +702,7 @@ function EASYGCICAP:_SetTankerPatrolPoints()
self:T(self.lid.."_SetTankerPatrolPoints")
for _,_data in pairs(self.ManagedTK) do
local data = _data --#EASYGCICAP.CapPoint
local Wing = self.wings[data.AirbaseName][1] -- Ops.AirWing#AIRWING
local Wing = self.wings[data.AirbaseName][1] -- Ops.Airwing#AIRWING
local Coordinate = data.Coordinate
local Altitude = data.Altitude
local Speed = data.Speed
@@ -721,7 +721,7 @@ function EASYGCICAP:_SetAwacsPatrolPoints()
self:T(self.lid.."_SetAwacsPatrolPoints")
for _,_data in pairs(self.ManagedEWR) do
local data = _data --#EASYGCICAP.CapPoint
local Wing = self.wings[data.AirbaseName][1] -- Ops.AirWing#AIRWING
local Wing = self.wings[data.AirbaseName][1] -- Ops.Airwing#AIRWING
local Coordinate = data.Coordinate
local Altitude = data.Altitude
local Speed = data.Speed
@@ -740,7 +740,7 @@ function EASYGCICAP:_SetCAPPatrolPoints()
self:T(self.lid.."_SetCAPPatrolPoints")
for _,_data in pairs(self.ManagedCP) do
local data = _data --#EASYGCICAP.CapPoint
local Wing = self.wings[data.AirbaseName][1] -- Ops.AirWing#AIRWING
local Wing = self.wings[data.AirbaseName][1] -- Ops.Airwing#AIRWING
local Coordinate = data.Coordinate
local Altitude = data.Altitude
local Speed = data.Speed
@@ -759,7 +759,7 @@ function EASYGCICAP:_SetReconPatrolPoints()
self:T(self.lid.."_SetReconPatrolPoints")
for _,_data in pairs(self.ManagedREC) do
local data = _data --#EASYGCICAP.CapPoint
local Wing = self.wings[data.AirbaseName][1] -- Ops.AirWing#AIRWING
local Wing = self.wings[data.AirbaseName][1] -- Ops.Airwing#AIRWING
local Coordinate = data.Coordinate
local Altitude = data.Altitude
local Speed = data.Speed
@@ -947,7 +947,7 @@ function EASYGCICAP:_AddSquadron(TemplateName, SquadName, AirbaseName, AirFrames
Squadron_One:SetSkill(Skill or AI.Skill.AVERAGE)
Squadron_One:SetMissionRange(self.missionrange)
local wing = self.wings[AirbaseName][1] -- Ops.AirWing#AIRWING
local wing = self.wings[AirbaseName][1] -- Ops.Airwing#AIRWING
wing:AddSquadron(Squadron_One)
wing:NewPayload(TemplateName,-1,{AUFTRAG.Type.CAP, AUFTRAG.Type.GCICAP, AUFTRAG.Type.INTERCEPT, AUFTRAG.Type.PATROLRACETRACK, AUFTRAG.Type.ALERT5},75)
@@ -978,7 +978,7 @@ function EASYGCICAP:_AddReconSquadron(TemplateName, SquadName, AirbaseName, AirF
Squadron_One:SetSkill(Skill or AI.Skill.AVERAGE)
Squadron_One:SetMissionRange(self.missionrange)
local wing = self.wings[AirbaseName][1] -- Ops.AirWing#AIRWING
local wing = self.wings[AirbaseName][1] -- Ops.Airwing#AIRWING
wing:AddSquadron(Squadron_One)
wing:NewPayload(TemplateName,-1,{AUFTRAG.Type.RECON},75)
@@ -1014,7 +1014,7 @@ function EASYGCICAP:_AddTankerSquadron(TemplateName, SquadName, AirbaseName, Air
Squadron_One:SetRadio(Frequency,Modulation)
Squadron_One:AddTacanChannel(TACAN,TACAN)
local wing = self.wings[AirbaseName][1] -- Ops.AirWing#AIRWING
local wing = self.wings[AirbaseName][1] -- Ops.Airwing#AIRWING
wing:AddSquadron(Squadron_One)
wing:NewPayload(TemplateName,-1,{AUFTRAG.Type.TANKER},75)
@@ -1047,7 +1047,7 @@ function EASYGCICAP:_AddAWACSSquadron(TemplateName, SquadName, AirbaseName, AirF
Squadron_One:SetSkill(Skill or AI.Skill.AVERAGE)
Squadron_One:SetMissionRange(self.missionrange)
Squadron_One:SetRadio(Frequency,Modulation)
local wing = self.wings[AirbaseName][1] -- Ops.AirWing#AIRWING
local wing = self.wings[AirbaseName][1] -- Ops.Airwing#AIRWING
wing:AddSquadron(Squadron_One)
wing:NewPayload(TemplateName,-1,{AUFTRAG.Type.AWACS},75)
@@ -1126,7 +1126,7 @@ end
--- Add a zone to the rejected zones set.
-- @param #EASYGCICAP self
-- @param Ops.Intelligence#INTEL.Cluster Cluster
-- @param Ops.Intel#INTEL.Cluster Cluster
-- @return #EASYGCICAP self
function EASYGCICAP:_AssignIntercept(Cluster)
-- Here, we'll decide if we need to launch an intercepting flight, and from where
@@ -1151,7 +1151,7 @@ function EASYGCICAP:_AssignIntercept(Cluster)
local position = self.Intel:CalcClusterFuturePosition(Cluster,300)
-- calculate closest zone
local bestdistance = 2000*1000 -- 2000km
local targetairwing = nil -- Ops.AirWing#AIRWING
local targetairwing = nil -- Ops.Airwing#AIRWING
local targetawname = "" -- #string
local clustersize = self.Intel:ClusterCountUnits(Cluster) or 1
local wingsize = math.abs(overhead * (clustersize+1))
@@ -1164,7 +1164,7 @@ function EASYGCICAP:_AssignIntercept(Cluster)
if (retrymission) and (wingsize >= 1) then
MESSAGE:New(string.format("**** %s Interceptors need wingsize %d", UTILS.GetCoalitionName(self.coalition), wingsize),15,"CAPGCI"):ToAllIf(self.debug):ToLog()
for _,_data in pairs (wings) do
local airwing = _data[1] -- Ops.AirWing#AIRWING
local airwing = _data[1] -- Ops.Airwing#AIRWING
local zone = _data[2] -- Core.Zone#ZONE
local zonecoord = zone:GetCoordinate()
local name = _data[3] -- #string
@@ -1177,7 +1177,7 @@ function EASYGCICAP:_AssignIntercept(Cluster)
end
end
for _,_data in pairs (ctlpts) do
--local airwing = _data[1] -- Ops.AirWing#AIRWING
--local airwing = _data[1] -- Ops.Airwing#AIRWING
--local zone = _data[2] -- Core.Zone#ZONE
--local zonecoord = zone:GetCoordinate()
--local name = _data[3] -- #string
@@ -1191,7 +1191,7 @@ function EASYGCICAP:_AssignIntercept(Cluster)
local airframes = airwing:CountAssets(true)
if distance < bestdistance and airframes >= wingsize then
bestdistance = distance
targetairwing = airwing -- Ops.AirWing#AIRWING
targetairwing = airwing -- Ops.Airwing#AIRWING
targetawname = name
end
end

View File

@@ -44,7 +44,7 @@
-- @field #boolean fuelcritical Fuel critical switch.
-- @field #number fuelcriticalthresh Critical fuel threshold in percent.
-- @field #boolean fuelcriticalrtb RTB on critical fuel switch.
-- @field Ops.FlightControl#FLIGHTCONTROL flightcontrol The flightcontrol handling this group.
-- @field OPS.FlightControl#FLIGHTCONTROL flightcontrol The flightcontrol handling this group.
-- @field Ops.Airboss#AIRBOSS airboss The airboss handling this group.
-- @field Core.UserFlag#USERFLAG flaghold Flag for holding.
-- @field #number Tholding Abs. mission time stamp when the group reached the holding point.
@@ -54,7 +54,7 @@
-- @field #boolean despawnAfterLanding If `true`, group is despawned after landed at an airbase.
-- @field #boolean despawnAfterHolding If `true`, group is despawned after reaching the holding point.
-- @field #number RTBRecallCount Number that counts RTB calls.
-- @field Ops.FlightControl#FLIGHTCONTROL.HoldingStack stack Holding stack.
-- @field OPS.FlightControl#FLIGHTCONTROL.HoldingStack stack Holding stack.
-- @field #boolean isReadyTO Flight is ready for takeoff. This is for FLIGHTCONTROL.
-- @field #boolean prohibitAB Disallow (true) or allow (false) AI to use the afterburner.
-- @field #boolean jettisonEmptyTanks Allow (true) or disallow (false) AI to jettison empty fuel tanks.
@@ -695,7 +695,7 @@ end
--- Get airwing the flight group belongs to.
-- @param #FLIGHTGROUP self
-- @return Ops.AirWing#AIRWING The AIRWING object (if any).
-- @return Ops.Airwing#AIRWING The AIRWING object (if any).
function FLIGHTGROUP:GetAirwing()
return self.legion
end
@@ -793,7 +793,7 @@ end
--- Set the FLIGHTCONTROL controlling this flight group.
-- @param #FLIGHTGROUP self
-- @param Ops.FlightControl#FLIGHTCONTROL flightcontrol The FLIGHTCONTROL object.
-- @param OPS.FlightControl#FLIGHTCONTROL flightcontrol The FLIGHTCONTROL object.
-- @return #FLIGHTGROUP self
function FLIGHTGROUP:SetFlightControl(flightcontrol)
@@ -822,7 +822,7 @@ end
--- Get the FLIGHTCONTROL controlling this flight group.
-- @param #FLIGHTGROUP self
-- @return Ops.FlightControl#FLIGHTCONTROL The FLIGHTCONTROL object.
-- @return OPS.FlightControl#FLIGHTCONTROL The FLIGHTCONTROL object.
function FLIGHTGROUP:GetFlightControl()
return self.flightcontrol
end
@@ -3799,10 +3799,11 @@ function FLIGHTGROUP:_InitGroup(Template)
self.speedMax=group:GetSpeedMax()
-- Is group mobile?
if self.speedMax>3.6 then
if self.speedMax and self.speedMax>3.6 then
self.isMobile=true
else
self.isMobile=false
self.speedMax = 0
end
-- Cruise speed limit 380 kts for fixed and 110 knots for rotary wings.
@@ -4871,7 +4872,7 @@ function FLIGHTGROUP:_UpdateMenu(delay)
-- Get all FLIGHTCONTROLS
local fc={}
for airbasename,_flightcontrol in pairs(_DATABASE.FLIGHTCONTROLS) do
local flightcontrol=_flightcontrol --Ops.FlightControl#FLIGHTCONTROL
local flightcontrol=_flightcontrol --OPS.FlightControl#FLIGHTCONTROL
-- Get coord of airbase.
local coord=flightcontrol:GetCoordinate()

View File

@@ -2272,7 +2272,7 @@ function INTEL:GetHighestThreatContact(Cluster)
for _,_contact in pairs(Cluster.Contacts) do
local contact=_contact --Ops.Intelligence#INTEL.Contact
local contact=_contact --Ops.Intel#INTEL.Contact
if contact.threatlevel>threatlevel then
threatlevel=contact.threatlevel
@@ -2312,8 +2312,8 @@ end
-- @field #string alias Alias name for logging.
-- @field #number cachetime Number of seconds to keep an object.
-- @field #number interval Number of seconds between collection runs.
-- @field #table contacts Table of Ops.Intelligence#INTEL.Contact contacts.
-- @field #table clusters Table of Ops.Intelligence#INTEL.Cluster clusters.
-- @field #table contacts Table of Ops.Intel#INTEL.Contact contacts.
-- @field #table clusters Table of Ops.Intel#INTEL.Cluster clusters.
-- @field #table contactcoords Table of contacts' Core.Point#COORDINATE objects.
-- @extends Core.Fsm#FSM
@@ -2337,7 +2337,7 @@ INTEL_DLINK.version = "0.0.1"
--- Function to instantiate a new object
-- @param #INTEL_DLINK self
-- @param #table Intels Table of Ops.Intelligence#INTEL objects.
-- @param #table Intels Table of Ops.Intel#INTEL objects.
-- @param #string Alias (optional) Name of this instance. Default "SPECTRE"
-- @param #number Interval (optional) When to query #INTEL objects for detected items (default 20 seconds).
-- @param #number Cachetime (optional) How long to cache detected items (default 300 seconds).
@@ -2449,7 +2449,7 @@ end
--- Function to add an #INTEL object to the aggregator
-- @param #INTEL_DLINK self
-- @param Ops.Intelligence#INTEL Intel the #INTEL object to add
-- @param Ops.Intel#INTEL Intel the #INTEL object to add
-- @return #INTEL_DLINK self
function INTEL_DLINK:AddIntel(Intel)
self:T(self.lid .. "AddIntel")

View File

@@ -3190,14 +3190,14 @@ function LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, Inclu
elseif (currmission.type==AUFTRAG.Type.ONGUARD or currmission.type==AUFTRAG.Type.PATROLZONE) and (MissionType==AUFTRAG.Type.ARTY or MissionType==AUFTRAG.Type.GROUNDATTACK) then
score=score+25
elseif currmission.type==AUFTRAG.Type.NOTHING then
score=score+25
score=score+30
end
end
if MissionType==AUFTRAG.Type.OPSTRANSPORT or MissionType==AUFTRAG.Type.AMMOSUPPLY or MissionType==AUFTRAG.Type.AWACS or MissionType==AUFTRAG.Type.FUELSUPPLY or MissionType==AUFTRAG.Type.TANKER then
-- TODO: need to check for missions that do not require ammo like transport, recon, awacs, tanker etc.
-- We better take a fresh asset. Sometimes spawned assets to something else, which is difficult to check.
-- We better take a fresh asset. Sometimes spawned assets do something else, which is difficult to check.
score=score-10
else
-- Combat mission.

View File

@@ -1800,10 +1800,11 @@ function NAVYGROUP:_InitGroup(Template)
self.speedMax=self.group:GetSpeedMax()
-- Is group mobile?
if self.speedMax>3.6 then
if self.speedMax and self.speedMax>3.6 then
self.isMobile=true
else
self.isMobile=false
self.speedMax = 0
end
-- Cruise speed: 70% of max speed.

View File

@@ -508,7 +508,7 @@ OPSGROUP.CargoStatus={
--- OpsGroup version.
-- @field #string version
OPSGROUP.version="1.0.0"
OPSGROUP.version="1.0.1"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@@ -535,7 +535,7 @@ OPSGROUP.version="1.0.0"
-- @param Wrapper.Group#GROUP group The GROUP object. Can also be given by its group name as `#string`.
-- @return #OPSGROUP self
function OPSGROUP:New(group)
-- Inherit everything from FSM class.
local self=BASE:Inherit(self, FSM:New()) -- #OPSGROUP
@@ -554,10 +554,15 @@ function OPSGROUP:New(group)
-- Check if group exists.
if self.group then
if not self:IsExist() then
self:T(self.lid.."ERROR: GROUP does not exist! Returning nil")
self:E(self.lid.."ERROR: GROUP does not exist! Returning nil")
return nil
end
end
if UTILS.IsInstanceOf(group,"OPSGROUP") then
self:E(self.lid.."ERROR: GROUP is already an OPSGROUP: "..tostring(self.groupname).."!")
return group
end
-- Set the template.
self:_SetTemplate()
@@ -591,33 +596,34 @@ function OPSGROUP:New(group)
if units then
local masterunit=units[1] --Wrapper.Unit#UNIT
-- Get Descriptors.
self.descriptors=masterunit:GetDesc()
-- Set type name.
self.actype=masterunit:GetTypeName()
-- Is this a submarine.
self.isSubmarine=masterunit:HasAttribute("Submarines")
-- Has this a datalink?
self.isEPLRS=masterunit:HasAttribute("Datalink")
if self:IsFlightgroup() then
self.rangemax=self.descriptors.range and self.descriptors.range*1000 or 500*1000
self.ceiling=self.descriptors.Hmax
self.tankertype=select(2, masterunit:IsTanker())
self.refueltype=select(2, masterunit:IsRefuelable())
--env.info("DCS Unit BOOM_AND_RECEPTACLE="..tostring(Unit.RefuelingSystem.BOOM_AND_RECEPTACLE))
--env.info("DCS Unit PROBE_AND_DROGUE="..tostring(Unit.RefuelingSystem.PROBE_AND_DROGUE))
if unit then
-- Get Descriptors.
self.descriptors=masterunit:GetDesc()
-- Set type name.
self.actype=masterunit:GetTypeName()
-- Is this a submarine.
self.isSubmarine=masterunit:HasAttribute("Submarines")
-- Has this a datalink?
self.isEPLRS=masterunit:HasAttribute("Datalink")
if self:IsFlightgroup() then
self.rangemax=self.descriptors.range and self.descriptors.range*1000 or 500*1000
self.ceiling=self.descriptors.Hmax
self.tankertype=select(2, masterunit:IsTanker())
self.refueltype=select(2, masterunit:IsRefuelable())
--env.info("DCS Unit BOOM_AND_RECEPTACLE="..tostring(Unit.RefuelingSystem.BOOM_AND_RECEPTACLE))
--env.info("DCS Unit PROBE_AND_DROGUE="..tostring(Unit.RefuelingSystem.PROBE_AND_DROGUE))
end
end
end
-- Init set of detected units.

View File

@@ -21,7 +21,7 @@
-- ===
-- @module Ops.PlayerTask
-- @image OPS_PlayerTask.jpg
-- @date Last Update Jan 2024
-- @date Last Update Feb 2024
do
@@ -411,6 +411,15 @@ function PLAYERTASK:IsDone()
return IsDone
end
--- [User] Check if PLAYERTASK has clients assigned to it.
-- @param #PLAYERTASK self
-- @return #boolean hasclients
function PLAYERTASK:HasClients()
self:T(self.lid.."HasClients?")
local hasclients = self:CountClients() > 0 and true or false
return hasclients
end
--- [User] Get client names assigned as table of #strings
-- @param #PLAYERTASK self
-- @return #table clients
@@ -1552,7 +1561,7 @@ PLAYERTASKCONTROLLER.Messages = {
--- PLAYERTASK class version.
-- @field #string version
PLAYERTASKCONTROLLER.version="0.1.64"
PLAYERTASKCONTROLLER.version="0.1.65"
--- Create and run a new TASKCONTROLLER instance.
-- @param #PLAYERTASKCONTROLLER self
@@ -3173,7 +3182,7 @@ function PLAYERTASKCONTROLLER:_ActiveTaskInfo(Task, Group, Client)
local ttsname = self.gettext:GetEntry("TASKNAMETTS",self.locale)
local taskname = string.format(tname,task.Type,task.PlayerTaskNr)
local ttstaskname = string.format(ttsname,task.TTSType,task.PlayerTaskNr)
local Coordinate = task.Target:GetCoordinate()
local Coordinate = task.Target:GetCoordinate() or COORDINATE:New(0,0,0)
local CoordText = ""
local CoordTextLLDM = nil
if self.Type ~= PLAYERTASKCONTROLLER.Type.A2A then
@@ -3946,7 +3955,7 @@ function PLAYERTASKCONTROLLER:SetupIntel(RecceName)
local function NewCluster(Cluster)
if not self.usecluster then return self end
local cluster = Cluster -- Ops.Intelligence#INTEL.Cluster
local cluster = Cluster -- Ops.Intel#INTEL.Cluster
local type = cluster.ctype
self:T({type,self.Type})
if (type == INTEL.Ctype.AIRCRAFT and self.Type == PLAYERTASKCONTROLLER.Type.A2A) or (type == INTEL.Ctype.NAVAL and (self.Type == PLAYERTASKCONTROLLER.Type.A2S or self.Type == PLAYERTASKCONTROLLER.Type.A2GS)) then
@@ -3954,7 +3963,7 @@ function PLAYERTASKCONTROLLER:SetupIntel(RecceName)
local contacts = cluster.Contacts -- #table of GROUP
local targetset = SET_GROUP:New()
for _,_object in pairs(contacts) do
local contact = _object -- Ops.Intelligence#INTEL.Contact
local contact = _object -- Ops.Intel#INTEL.Contact
self:T("Adding group: "..contact.groupname)
targetset:AddGroup(contact.group,true)
end
@@ -3966,14 +3975,14 @@ function PLAYERTASKCONTROLLER:SetupIntel(RecceName)
if type == INTEL.Ctype.GROUND then
targetset = SET_GROUP:New()
for _,_object in pairs(contacts) do
local contact = _object -- Ops.Intelligence#INTEL.Contact
local contact = _object -- Ops.Intel#INTEL.Contact
self:T("Adding group: "..contact.groupname)
targetset:AddGroup(contact.group,true)
end
elseif type == INTEL.Ctype.STRUCTURE then
targetset = SET_STATIC:New()
for _,_object in pairs(contacts) do
local contact = _object -- Ops.Intelligence#INTEL.Contact
local contact = _object -- Ops.Intel#INTEL.Contact
self:T("Adding static: "..contact.groupname)
targetset:AddStatic(contact.group)
end
@@ -3986,7 +3995,7 @@ function PLAYERTASKCONTROLLER:SetupIntel(RecceName)
local function NewContact(Contact)
if self.usecluster then return self end
local contact = Contact -- Ops.Intelligence#INTEL.Contact
local contact = Contact -- Ops.Intel#INTEL.Contact
local type = contact.ctype
self:T({type,self.Type})
if (type == INTEL.Ctype.AIRCRAFT and self.Type == PLAYERTASKCONTROLLER.Type.A2A) or (type == INTEL.Ctype.NAVAL and (self.Type == PLAYERTASKCONTROLLER.Type.A2S or self.Type == PLAYERTASKCONTROLLER.Type.A2GS)) then

View File

@@ -243,7 +243,7 @@ end
--- Set airwing.
-- @param #SQUADRON self
-- @param Ops.AirWing#AIRWING Airwing The airwing.
-- @param Ops.Airwing#AIRWING Airwing The airwing.
-- @return #SQUADRON self
function SQUADRON:SetAirwing(Airwing)
self.legion=Airwing
@@ -252,7 +252,7 @@ end
--- Get airwing.
-- @param #SQUADRON self
-- @return Ops.AirWing#AIRWING The airwing.
-- @return Ops.Airwing#AIRWING The airwing.
function SQUADRON:GetAirwing(Airwing)
return self.legion
end

View File

@@ -36,7 +36,7 @@
-- @field #number prio Priority.
-- @field #number importance Importance.
-- @field Ops.Auftrag#AUFTRAG mission Mission attached to this target.
-- @field Ops.Intelligence#INTEL.Contact contact Contact attached to this target.
-- @field Ops.Intel#INTEL.Contact contact Contact attached to this target.
-- @field #boolean isDestroyed If true, target objects were destroyed.
-- @field #table resources Resource list.
-- @field #table conditionStart Start condition functions.