From 591cf29edf4b94d58ed2aeef29ee2bc612950ee9 Mon Sep 17 00:00:00 2001 From: Applevangelist <72444570+Applevangelist@users.noreply.github.com> Date: Sun, 22 May 2022 11:17:20 +0200 Subject: [PATCH 01/30] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5a1979522..69ab8403a 100644 --- a/README.md +++ b/README.md @@ -61,9 +61,10 @@ Documentation on the MOOSE class hierarchy, usage guides and background informat -## [MOOSE Youtube Channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg) +## [MOOSE Youtube Tutorials](https://youtube.com/playlist?list=PLLkY2GByvtC2ME0Q9wrKRDE6qnXJYV3iT) -MOOSE has a [broadcast and training channel on YouTube](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg) with various channels that you can watch. +Pene has kindly created a [tutorial series for MOOSE](https://youtube.com/playlist?list=PLLkY2GByvtC2ME0Q9wrKRDE6qnXJYV3iT) + with various videos that you can watch. From ce33e1d2428108257e23600d036eef33fe91cbdd Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sun, 22 May 2022 13:03:34 +0200 Subject: [PATCH 02/30] AWACS - Options to Draw Zones --- Moose Development/Moose/Ops/Awacs.lua | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index 1aa3fd14f..e52acfc99 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -1245,13 +1245,16 @@ end --- [User] Set additional defensive zone, e.g. the zone behind the FEZ to also be defended -- @param #AWACS self -- @param Core.Zone#ZONE Zone +-- @param #boolean Draw Draw lines around this zone if true -- @return #AWACS self -function AWACS:SetAdditionalZone(Zone) +function AWACS:SetAdditionalZone(Zone, Draw) self:T(self.lid.."SetAdditionalZone") self.BorderZone = Zone if self.debug then Zone:DrawZone(-1,{1,0.64,0},1,{1,0.64,0},0.2,1,true) MARKER:New(Zone:GetCoordinate(),"Defensive Zone"):ToAll() + elseif Draw then + Zone:DrawZone(-1,{1,0.64,0},1,{1,0.64,0},0.2,1,true) end return self end @@ -1259,17 +1262,29 @@ end --- [User] Set rejection zone, e.g. a border of a foreign country. Detected bogeys in here won't be engaged. -- @param #AWACS self -- @param Core.Zone#ZONE Zone +-- @param #boolean Draw Draw lines around this zone if true -- @return #AWACS self -function AWACS:SetRejectionZone(Zone) +function AWACS:SetRejectionZone(Zone,Draw) self:T(self.lid.."SetRejectionZone") self.RejectZone = Zone - if self.debug then + if Draw then + Zone:DrawZone(-1,{1,0.64,0},1,{1,0.64,0},0.2,1,true) + --MARKER:New(Zone:GetCoordinate(),"Rejection Zone"):ToAll() + elseif self.debug then Zone:DrawZone(-1,{1,0.64,0},1,{1,0.64,0},0.2,1,true) MARKER:New(Zone:GetCoordinate(),"Rejection Zone"):ToAll() end return self end +--- [User] Draw a line around the FEZ on the F10 map. +-- @param #AWACS self +-- @return #AWACS self +function AWACS:DrawFEZ() + self.OpsZone:DrawZone(-1,{1,0,0},1,{1,0,0},0.2,5,true) + return self +end + --- [User] Set AWACS flight details -- @param #AWACS self -- @param #number CallSign Defaults to CALLSIGN.AWACS.Magic From 77aba386255807bc1cfc09c1c528c20315247ae4 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sun, 22 May 2022 17:14:14 +0200 Subject: [PATCH 03/30] AWACS - added docu --- Moose Development/Moose/Ops/Awacs.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index e52acfc99..134f7caba 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -283,8 +283,13 @@ do -- Meld Distance = 35 -- Threat Distance = 25 -- Merge Distance = 3 +-- +-- ## 8 Bespoke Player CallSigns +-- +-- Append the GROUP name of your client slots with "#CallSign" to use bespoke callsigns in AWACS callouts. E.g. "Player F14#Ghostrider" will be refered to +-- as "Ghostrider" plus group number, e.g. "Ghostrider 9". -- --- ## 8 Discussion +-- ## 9 Discussion -- -- If you have questions or suggestions, please visit the [MOOSE Discord](https://discord.gg/AeYAkHP) #ops-awacs channel. -- From 4afedcf126036e1d58df7534e5c48a554df09acd Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 24 May 2022 14:04:52 +0200 Subject: [PATCH 04/30] AWACS - added documentation, added option to suppress group tags --- Moose Development/Moose/Ops/Awacs.lua | 144 ++++++++++++++++---------- 1 file changed, 90 insertions(+), 54 deletions(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index 134f7caba..ba5825492 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -16,6 +16,10 @@ -- ## Example Missions: -- -- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/). +-- +-- ## Videos: +-- +-- Demo videos can be found on [Youtube](https://www.youtube.com/watch?v=ocdy8QzTNN4&list=PLFxp425SeXnq-oS0DSjam1HtddywH8i_k) -- -- === -- @@ -26,22 +30,6 @@ -- @module Ops.AWACS -- @image OPS_AWACS.jpg - ---- --- === --- --- **AWACS** - MOOSE based AI AWACS Fighter Engagement Zone Operations for Players and AI --- --- === --- --- ## Example Missions: --- --- ### Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/). --- --- === --- - - do --- Ops AWACS Class -- @type AWACS @@ -109,17 +97,19 @@ do -- @field #number PictureInterval Interval in seconds for general picture -- @field #number PictureTimeStamp Interval timestamp -- @field #number maxassigndistance Only assing AI/Pilots to targets max this far away --- @field #boolean PlayerGuidance -- if true additional callouts to guide/warn players --- @field #boolean ModernEra -- if true we get more intel on targets, and EPLR on the AIC --- @field #boolean callsignshort -- if true use short (group) callsigns, e.g. "Ghost 1", else "Ghost 1 1" --- @field #number MeldDistance -- 25nm - distance for "Meld" Call , usually shortly before the actual engagement --- @field #number TacDistance -- 30nm - distance for "TAC" Call --- @field #number ThreatDistance -- 15nm - distance to declare untargeted (new) threats --- @field #string AOName -- name of the FEZ, e.g. Rock --- @field Core.Point#COORDINATE AOCoordinate -- Coordinate of bulls eye +-- @field #boolean PlayerGuidance if true additional callouts to guide/warn players +-- @field #boolean ModernEra if true we get more intel on targets, and EPLR on the AIC +-- @field #boolean callsignshort if true use short (group) callsigns, e.g. "Ghost 1", else "Ghost 1 1" +-- @field #number MeldDistance 25nm - distance for "Meld" Call , usually shortly before the actual engagement +-- @field #number TacDistance 30nm - distance for "TAC" Call +-- @field #number ThreatDistance 15nm - distance to declare untargeted (new) threats +-- @field #string AOName name of the FEZ, e.g. Rock +-- @field Core.Point#COORDINATE AOCoordinate Coordinate of bulls eye -- @field Utilities.FiFo#FIFO clientmenus --- @field #number RadarBlur -- Radar blur in % --- @field #number ReassignmentPause -- Wait this many seconds before re-assignment of a player +-- @field #number RadarBlur Radar blur in % +-- @field #number ReassignmentPause Wait this many seconds before re-assignment of a player +-- @field #boolean NoGroupTags Set to true if you don't want group tags. +-- @field #boolean SuppressScreenOutput Set to true to suppress all screen output. -- @extends Core.Fsm#FSM @@ -139,6 +129,8 @@ do -- ** References from ARN33396 ATP 3-52.4 (Sep 2021) (Combined Forces) -- ** References from CNATRA P-877 (Rev 12-20) (NAVY) -- * FSM events that the mission designer can hook into +-- +-- === -- -- ## 1 Prerequisites -- @@ -288,15 +280,51 @@ do -- -- Append the GROUP name of your client slots with "#CallSign" to use bespoke callsigns in AWACS callouts. E.g. "Player F14#Ghostrider" will be refered to -- as "Ghostrider" plus group number, e.g. "Ghostrider 9". +-- +-- ## 9 Options +-- +-- There's a number of functions available, to set various options for the setup. +-- +-- * @{#AWACS.SetBullsEyeAlias}() : Set the alias name of the Bulls Eye. +-- * @{#AWACS.SetTOS}() : Set time on station for AWACS and CAP. +-- * @{#AWACS.SetReassignmentPause}() : Pause this number of seconds before re-assigning a Player to a task. +-- * @{#AWACS.SuppressScreenMessages}() : Suppress message output on screen. +-- * @{#AWACS.SetRadarBlur}() : Set the radar blur faktor in percent. +-- * @{#AWACS.SetColdWar}() : Set to cold war - no fill-ins, no EPLRS, VID as standard. +-- * @{#AWACS.SetModernEraDefensive}() : Set to modern, EPLRS, BVR/IFF engagement, fill-ins. +-- * @{#AWACS.SetModernEraAgressive}() : Set to modern, EPLRS, BVR/IFF engagement, fill-ins. +-- * @{#AWACS.SetPolicingModern}() : Set to modern, EPLRS, VID engagement, fill-ins. +-- * @{#AWACS.SetPolicingColdWar}() : Set to cold war, no EPLRS, VID engagement, no fill-ins. +-- * @{#AWACS.SetInterceptTimeline}() : Set distances for TAC, Meld and Threat range calls. +-- * @{#AWACS.SetAdditionalZone}() : Add one additional defense zone, e.g. own border. +-- * @{#AWACS.SetRejectionZone}() : Add one foreign border. Targets beyond will be ignored for tasking. +-- * @{#AWACS.DrawFEZ}() : Show the FEZ on the F10 map. +-- * @{#AWACS.SetAWACSDetails}() : Set AWACS details. +-- * @{#AWACS.AddGroupToDetection}() : Add a group object to INTEL detection, e.g. EWR. +-- * @{#AWACS.SetSRS}() : Set SRS details. +-- * @{#AWACS.SetSRSVoiceCAP}() : Set voice details for AI CAP planes, using Windows dektop TTS. +-- * @{#AWACS.SetAICAPDetails}() : Set AI CAP details. +-- * @{#AWACS.SetEscort}() : Set number of escorting planes for AWACS. +-- * @{#AWACS.AddCAPAirWing}() : Add an additional @{Ops.AirWing#AIRWING} for CAP flights. +-- +-- Further options (set before starting your AWACS instance, but after `:New()`) +-- +-- self.PlayerGuidance = true -- allow missile warning call-outs. +-- self.NoGroupTags = false -- use group tags like Alpha, Bravo .. etc in call outs. +-- self.callsignshort = true -- use short callsigns, e.g. "Moose 1", not "Moose 1-1". +-- self.DeclareRadius = 5 -- you need to be this close to the lead unit for declare/VID to work, in NM. +-- self.MenuStrict = true -- Players need to check-in to see the menu; check-in still require to use the menu. +-- self.maxassigndistance = 100 -- Don't assign targets further out than this, in NM. +-- self.debug = false -- set to true to produce more log output. -- --- ## 9 Discussion +-- ## 10 Discussion -- -- If you have questions or suggestions, please visit the [MOOSE Discord](https://discord.gg/AeYAkHP) #ops-awacs channel. -- -- @field #AWACS AWACS = { ClassName = "AWACS", -- #string - version = "beta 0.1.22", -- #string + version = "beta 0.1.23", -- #string lid = "", -- #string coalition = coalition.side.BLUE, -- #number coalitiontxt = "blue", -- #string @@ -370,6 +398,8 @@ AWACS = { clientmenus = nil, RadarBlur = 15, ReassignmentPause = 180, + NoGroupTags = false, + SuppressScreenOutput = false, } --- @@ -629,12 +659,12 @@ AWACS.TaskStatus = { --@field #boolean FromAI ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- TODO-List 0.1.22 +-- TODO-List 0.1.23 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- -- DEBUG - WIP - Player tasking, VID --- TODO - Localization --- TODO - (LOW) LotATC / IFF +-- TODO - Localization (sensible?) +-- TODO - (LOW) LotATC -- TODO - SW Optimization -- WONTDO - Maybe check in AI only when airborne -- DONE - remove SSML tag when not on google (currently sometimes spoken) @@ -773,7 +803,6 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station self.invisible = false self.immortal = false self.callsigntxt = "AWACS" - self.maxassigndistance = 100 --nm self.AwacsTimeOnStation = 4 self.AwacsTimeStamp = 0 @@ -792,10 +821,6 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station self.CAPCulture = "en-US" self.CAPVoice = nil - self.ReassignmentPause = 180 - - self.DeclareRadius = 5 -- NM - self.AwacsMission = nil self.AwacsInZone = false -- not yet arrived or gone again self.AwacsReady = false @@ -803,8 +828,6 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station self.AwacsROE = AWACS.ROE.IFF self.AwacsROT = AWACS.ROT.BYPASSESCAPE - self.MenuStrict = true - -- Escorts self.HasEscorts = false self.EscortTemplate = "" @@ -820,14 +843,20 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station self.PrioRadioQueue = FIFO:New() -- Utilities.FiFo#FIFO self.maxspeakentries = 3 - self.SuppressScreenOutput = false - -- Client SET self.clientset = SET_CLIENT:New():FilterActive(true):FilterCoalitions(self.coalitiontxt):FilterCategories("plane"):FilterStart() - + + -- Player options self.PlayerGuidance = true self.ModernEra = true - + self.NoGroupTags = false + self.SuppressScreenOutput = false + self.ReassignmentPause = 180 + self.callsignshort = true + self.DeclareRadius = 5 -- NM + self.MenuStrict = true + self.maxassigndistance = 100 --nm + -- managed groups self.ManagedGrps = {} -- #table of #AWACS.ManagedGroup entries self.ManagedGrpID = 0 @@ -2004,9 +2033,13 @@ function AWACS:_CreatePicture(AO,Callsign,GID,MaxEntries,IsGeneral) end local refBRAA = "" local refBRAATTS = "" - text = contact.TargetGroupNaming.." group." -- Alpha Group. - textScreen = contact.TargetGroupNaming.." group," - + if self.NoGroupTags then + text = "Group." -- Alpha Group. + textScreen = "Group," + else + text = contact.TargetGroupNaming.." group." -- Alpha Group. + textScreen = contact.TargetGroupNaming.." group," + end if IsGeneral then -- AO/BE Reference refBRAA=self:_ToStringBULLS(coordinate) @@ -2135,15 +2168,15 @@ function AWACS:_Picture(Group,IsGeneral) local GID, Outcome, gcallsign = self:_GetManagedGrpID(Group) --local gcallsign = "" - if Group and Outcome then - general = false - end - if general then gcallsign = "All Stations" --else --gcallsign = self:_GetCallSign(Group,GID) or "Ghost 1" end + + if Group and Outcome then + general = false + end if not self.intel then -- no intel yet! @@ -2210,13 +2243,13 @@ function AWACS:_Picture(Group,IsGeneral) else if clustersAO > 0 then - if general then - text = string.format("%s, %s. ",gcallsign, self.callsigntxt) - textScreen = string.format("%s, %s. ",gcallsign, self.callsigntxt) - else + --if general then + --text = string.format("%s, %s. ",gcallsign, self.callsigntxt) + --textScreen = string.format("%s, %s. ",gcallsign, self.callsigntxt) + --else text = string.format("%s, %s. Picture. ",gcallsign, self.callsigntxt) textScreen = string.format("%s, %s. Picture. ",gcallsign, self.callsigntxt) - end + --end if clustersAO == 1 then text = text .. "One group. " textScreen = textScreen .. "One group.\n" @@ -4148,6 +4181,9 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo Tag = Contact.TargetGroupNaming or "" --self:T({CID,Tag}) end + if self.NoGroupTags then + Tag = nil + end local isGroup = false local GID = 0 local grpcallsign = "Ghost 1" From 88d132931eb3f9e6d22c430361fc0674a0ad74d7 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 24 May 2022 14:44:23 +0200 Subject: [PATCH 05/30] AWACS - Nicefy docs --- Moose Development/Moose/Ops/Awacs.lua | 28 +++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index ba5825492..eeeb9a90f 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -6,16 +6,16 @@ -- * AWACS replacement for the in-game AWACS -- * Will control a fighter engagement zone and assign tasks to AI and human CAP flights -- * Concentrates on threat-based call outs --- * Callouts referenced from: --- ** References from ARN33396 ATP 3-52.4 (Sep 2021) (Combined Forces) --- ** References from CNATRA P-877 (Rev 12-20) (NAVY) +-- * Callouts referenced from: +-- ** References from ARN33396 ATP 3-52.4 (Sep 2021) (Combined Forces) +-- ** References from CNATRA P-877 (Rev 12-20) (NAVY) -- * Many additional events that the mission designer can hook into -- -- === -- -- ## Example Missions: -- --- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/). +-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Awacs/). -- -- ## Videos: -- @@ -114,7 +114,6 @@ do --- --- === -- -- *Of all men\'s miseries the bitterest is this: to know so much and to have control over nothing.* (Herodotus) -- @@ -131,7 +130,9 @@ do -- * FSM events that the mission designer can hook into -- -- === --- +-- + +--- -- ## 1 Prerequisites -- -- The radio callouts in this class are ***exclusively*** created with Text-To-Speech (TTS), based on the Moose @{Sound.SRS} Class, and output is via [Ciribob's SRS system](https://github.com/ciribob/DCS-SimpleRadioStandalone/releases) @@ -309,13 +310,13 @@ do -- -- Further options (set before starting your AWACS instance, but after `:New()`) -- --- self.PlayerGuidance = true -- allow missile warning call-outs. --- self.NoGroupTags = false -- use group tags like Alpha, Bravo .. etc in call outs. --- self.callsignshort = true -- use short callsigns, e.g. "Moose 1", not "Moose 1-1". --- self.DeclareRadius = 5 -- you need to be this close to the lead unit for declare/VID to work, in NM. --- self.MenuStrict = true -- Players need to check-in to see the menu; check-in still require to use the menu. --- self.maxassigndistance = 100 -- Don't assign targets further out than this, in NM. --- self.debug = false -- set to true to produce more log output. +-- testawacs.PlayerGuidance = true -- allow missile warning call-outs. +-- testawacs.NoGroupTags = false -- use group tags like Alpha, Bravo .. etc in call outs. +-- testawacs.callsignshort = true -- use short callsigns, e.g. "Moose 1", not "Moose 1-1". +-- testawacs.DeclareRadius = 5 -- you need to be this close to the lead unit for declare/VID to work, in NM. +-- testawacs.MenuStrict = true -- Players need to check-in to see the menu; check-in still require to use the menu. +-- testawacs.maxassigndistance = 100 -- Don't assign targets further out than this, in NM. +-- testawacs.debug = false -- set to true to produce more log output. -- -- ## 10 Discussion -- @@ -936,7 +937,6 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station self:AddTransition("*", "Intercept", "*") self:AddTransition("*", "InterceptSuccess", "*") self:AddTransition("*", "InterceptFailure", "*") - -- self:AddTransition("*", "Stop", "Stopped") -- Stop FSM. -- self:__Start(math.random(2,5)) From 91686e252c967ffee744dd0ee91ff93d7f8291bd Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 24 May 2022 16:05:04 +0200 Subject: [PATCH 06/30] AWACS FSM Functions Docu --- Moose Development/Moose/Ops/Awacs.lua | 136 ++++++++++++++++++++++++-- 1 file changed, 130 insertions(+), 6 deletions(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index eeeb9a90f..39fa31530 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -130,9 +130,7 @@ do -- * FSM events that the mission designer can hook into -- -- === --- - ---- +-- -- ## 1 Prerequisites -- -- The radio callouts in this class are ***exclusively*** created with Text-To-Speech (TTS), based on the Moose @{Sound.SRS} Class, and output is via [Ciribob's SRS system](https://github.com/ciribob/DCS-SimpleRadioStandalone/releases) @@ -306,7 +304,7 @@ do -- * @{#AWACS.SetSRSVoiceCAP}() : Set voice details for AI CAP planes, using Windows dektop TTS. -- * @{#AWACS.SetAICAPDetails}() : Set AI CAP details. -- * @{#AWACS.SetEscort}() : Set number of escorting planes for AWACS. --- * @{#AWACS.AddCAPAirWing}() : Add an additional @{Ops.AirWing#AIRWING} for CAP flights. +-- * @{#AWACS.AddCAPAirWing}() : Add an additional @{Ops.Airwing#AIRWING} for CAP flights. -- -- Further options (set before starting your AWACS instance, but after `:New()`) -- @@ -939,7 +937,6 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station self:AddTransition("*", "InterceptFailure", "*") self:AddTransition("*", "Stop", "Stopped") -- Stop FSM. - -- self:__Start(math.random(2,5)) local text = string.format("%sAWACS Version %s Initiated",self.lid,self.version) @@ -960,6 +957,119 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station -- Missile warning self:HandleEvent(EVENTS.Shot, self._EventHandler) + + ------------------------ + --- Pseudo Functions --- + ------------------------ + + --- Triggers the FSM event "Start". Starts the AWACS. Initializes parameters and starts event handlers. + -- @function [parent=#AWACS] Start + -- @param #AWACS self + + --- Triggers the FSM event "Start" after a delay. Starts the AWACS. Initializes parameters and starts event handlers. + -- @function [parent=#AWACS] __Start + -- @param #AWACS self + -- @param #number delay Delay in seconds. + + --- Triggers the FSM event "Stop". Stops the AWACS and all its event handlers. + -- @param #AWACS self + + --- Triggers the FSM event "Stop" after a delay. Stops the AWACS and all its event handlers. + -- @function [parent=#AWACS] __Stop + -- @param #AWACS self + -- @param #number delay Delay in seconds. + + --- On After "CheckedIn" event. AI or Player checked in. + -- @function [parent=#AWACS] OnAfterCheckedIn + -- @param #AWACS self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + --- On After "CheckedOut" event. AI or Player checked out. + -- @function [parent=#AWACS] OnAfterCheckedOut + -- @param #AWACS self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + --- On After "AssignedAnchor" event. AI or Player has been assigned a CAP station. + -- @function [parent=#AWACS] OnAfterAssignedAnchor + -- @param #AWACS self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + --- On After "ReAnchor" event. AI or Player has been send back to station. + -- @function [parent=#AWACS] OnAfterReAnchor + -- @param #AWACS self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + --- On After "NewCluster" event. AWACS detected a cluster. + -- @function [parent=#AWACS] OnAfterNewCluster + -- @param #AWACS self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + --- On After "NewContact" event. AWACS detected a contact. + -- @function [parent=#AWACS] OnAfterNewContact + -- @param #AWACS self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + --- On After "LostCluster" event. AWACS lost a radar cluster. + -- @function [parent=#AWACS] OnAfterLostCluster + -- @param #AWACS self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + --- On After "LostContact" event. AWACS lost a radar contact. + -- @function [parent=#AWACS] OnAfterLostContact + -- @param #AWACS self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + --- On After "EscortShiftChange" event. AWACS escorts shift change. + -- @function [parent=#AWACS] OnAfterEscortShiftChange + -- @param #AWACS self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + --- On After "AwacsShiftChange" event. AWACS shift change. + -- @function [parent=#AWACS] OnAfterAwacsShiftChange + -- @param #AWACS self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + --- On After "Intercept" event. CAP send on intercept. + -- @function [parent=#AWACS] OnAfterIntercept + -- @param #AWACS self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + --- On After "InterceptSuccess" event. Intercept successful. + -- @function [parent=#AWACS] OnAfterIntercept + -- @param #AWACS self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + --- On After "InterceptFailure" event. Intercept failure. + -- @function [parent=#AWACS] OnAfterIntercept + -- @param #AWACS self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + return self end @@ -5284,6 +5394,20 @@ function AWACS:onafterStop(From, Event, To) SubAW:RemoveUsingOpsAwacs() end end + -- Events + -- Player joins + self:UnHandleEvent(EVENTS.PlayerEnterAircraft) + self:UnHandleEvent(EVENTS.PlayerEnterUnit) + -- Player leaves + self:UnHandleEvent(EVENTS.PlayerLeaveUnit) + self:UnHandleEvent(EVENTS.Ejection) + self:UnHandleEvent(EVENTS.Crash) + self:UnHandleEvent(EVENTS.Dead) + self:UnHandleEvent(EVENTS.UnitLost) + self:UnHandleEvent(EVENTS.BDA) + self:UnHandleEvent(EVENTS.PilotDead) + -- Missile warning + self:UnHandleEvent(EVENTS.Shot) return self end @@ -5797,7 +5921,7 @@ function AWACS:onafterReAnchor(From, Event, To, GID) end text = text .. " "..brtexttts.." miles." textScreen = textScreen .. " "..brtext.." miles." - + self:_NewRadioEntry(text,textScreen,0,false,self.debug,true,false,true) end self.ManagedGrps[GID] = nil From e731fe9b98bdad3356a19e7e3236efd11f02734a Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 31 May 2022 14:02:14 +0200 Subject: [PATCH 07/30] AWACS 0.1.24 - Added merge call, google now says "zero" not "oh", aligned some callouts to more realistic versions, bulls related calls without aspect now. --- Moose Development/Moose/Core/Point.lua | 34 +++- Moose Development/Moose/Core/Set.lua | 20 +++ Moose Development/Moose/Ops/Awacs.lua | 230 +++++++++++++++---------- 3 files changed, 183 insertions(+), 101 deletions(-) diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index dfbbb6a90..010905098 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -2777,8 +2777,10 @@ do -- COORDINATE -- @param #boolean Bogey Add "Bogey" at the end if true (not yet declared hostile or friendly) -- @param #boolean Spades Add "Spades" at the end if true (no IFF/VID ID yet known) -- @param #boolean SSML Add SSML tags speaking aspect as 0 1 2 and "brah" instead of BRAA + -- @param #boolean Angels If true, altitude is e.g. "Angels 25" (i.e., a friendly plane), else "25 thousand" + -- @param #boolean Zeros If using SSML, be aware that Google TTS will say "oh" and not "zero" for "0"; if Zeros is set to true, "0" will be replaced with "zero" -- @return #string The BRAA text. - function COORDINATE:ToStringBRAANATO(FromCoordinate,Bogey,Spades,SSML) + function COORDINATE:ToStringBRAANATO(FromCoordinate,Bogey,Spades,SSML,Angels,Zeros) -- Thanks to @Pikey local BRAANATO = "Merged." @@ -2796,14 +2798,32 @@ do -- COORDINATE local alt = UTILS.Round(UTILS.MetersToFeet(self.y)/1000,0)--*1000 + local alttext = string.format("%d thousand",alt) + + if Angels then + alttext = string.format("Angels %d",alt) + end + local track = UTILS.BearingToCardinal(bearing) or "North" if rangeNM > 3 then - if SSML then - if aspect == "" then - BRAANATO = string.format("brah %03d, %d miles, Angels %d, Track %s",bearing, rangeNM, alt, track) + if SSML then -- google says "oh" instead of zero, be aware + if Zeros then + bearing = string.format("%03d",bearing) + local AngleDegText = string.gsub(bearing,"%d","%1 ") -- "0 5 1 " + AngleDegText = string.gsub(AngleDegText," $","") -- "0 5 1" + AngleDegText = string.gsub(AngleDegText,"0","zero") + if aspect == "" then + BRAANATO = string.format("brah %s, %d miles, %s, Track %s", AngleDegText, rangeNM, alttext, track) + else + BRAANATO = string.format("brah %s, %d miles, %s, %s, Track %s", AngleDegText, rangeNM, alttext, aspect, track) + end else - BRAANATO = string.format("brah %03d, %d miles, Angels %d, %s, Track %s",bearing, rangeNM, alt, aspect, track) + if aspect == "" then + BRAANATO = string.format("brah %03d, %d miles, %s, Track %s", bearing, rangeNM, alttext, track) + else + BRAANATO = string.format("brah %03d, %d miles, %s, %s, Track %s", bearing, rangeNM, alttext, aspect, track) + end end if Bogey and Spades then BRAANATO = BRAANATO..", Bogey, Spades." @@ -2816,9 +2836,9 @@ do -- COORDINATE end else if aspect == "" then - BRAANATO = string.format("BRA %03d, %d miles, Angels %d, Track %s",bearing, rangeNM, alt, track) + BRAANATO = string.format("BRA %03d, %d miles, %s, Track %s",bearing, rangeNM, alttext, track) else - BRAANATO = string.format("BRAA %03d, %d miles, Angels %d, %s, Track %s",bearing, rangeNM, alt, aspect, track) + BRAANATO = string.format("BRAA %03d, %d miles, %s, %s, Track %s",bearing, rangeNM, alttext, aspect, track) end if Bogey and Spades then BRAANATO = BRAANATO..", Bogey, Spades." diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index 518d8ff62..655e4eca2 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -4180,6 +4180,26 @@ do -- SET_CLIENT return CountU end + + --- Gets the alive set. + -- @param #SET_CLIENT self + -- @return #table Table of SET objects + function SET_CLIENT:GetAliveSet() + + local AliveSet = SET_CLIENT:New() + + -- Clean the Set before returning with only the alive Groups. + for GroupName, GroupObject in pairs(self.Set) do + local GroupObject=GroupObject --Wrapper.Client#CLIENT + + if GroupObject and GroupObject:IsAlive() then + AliveSet:Add(GroupName, GroupObject) + end + end + + return AliveSet.Set or {} + end + --- -- @param #SET_CLIENT self -- @param Wrapper.Client#CLIENT MClient diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index 39fa31530..17870073b 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -323,7 +323,7 @@ do -- @field #AWACS AWACS = { ClassName = "AWACS", -- #string - version = "beta 0.1.23", -- #string + version = "beta 0.1.24", -- #string lid = "", -- #string coalition = coalition.side.BLUE, -- #number coalitiontxt = "blue", -- #string @@ -658,7 +658,7 @@ AWACS.TaskStatus = { --@field #boolean FromAI ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- TODO-List 0.1.23 +-- TODO-List 0.1.24 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- -- DEBUG - WIP - Player tasking, VID @@ -1725,7 +1725,8 @@ function AWACS:_ToStringBULLS( Coordinate, ssml, TTS ) return string.format("%s %03d, %d",bullseyename,Bearing,Distance) elseif TTS then Bearing = self:_ToStringBullsTTS(Bearing) - return string.format("%s %s, %d",bullseyename,Bearing,Distance) + local BearingTTS = string.gsub(Bearing,"0","zero") + return string.format("%s %s, %d",bullseyename,BearingTTS,Distance) else return string.format("%s %s, %d",bullseyename,Bearing,Distance) end @@ -1838,6 +1839,33 @@ function AWACS:_UpdateContactFromCluster(CID) return self end +--- [Internal] Check merges for Players +-- @param #AWACS self +-- @return #AWACS self +function AWACS:_CheckMerges() + self:T(self.lid.."_CheckMerges") + for _id,_pilot in pairs (self.ManagedGrps) do + local pilot = _pilot -- #AWACS.ManagedGroup + if pilot.Group and pilot.Group:IsAlive() then + local ppos = pilot.Group:GetCoordinate() + if ppos then + self.Contacts:ForEach( + function (Contact) + local contact = Contact -- #AWACS.ManagedContact + 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 and distnm <= 3 then + self:_MergedCall(_id) + end + end + ) + end + end + end + return self +end + --- [Internal] Clean up contacts list -- @param #AWACS self -- @return #AWACS self @@ -1861,22 +1889,12 @@ function AWACS:_CleanUpContacts() if deadcontacts:Count() > 0 then self:T("DEAD count="..deadcontacts:Count()) - -- check cluster alive or announce lost - deadcontacts:ForEach( function (Contact) local contact = Contact -- #AWACS.ManagedContact - -- see if the complete cluster is dead - -- if contact.Cluster and self.intel:ClusterCountUnits(contact.Cluster) > 0 then - -- not complete cluster dead, update contact data later - -- aliveclusters:Push(contact) - --else local text = string.format("%s, %s Group. Vanished.",self.callsigntxt, contact.TargetGroupNaming) local textScreen = string.format("%s, %s group vanished.", self.callsigntxt, contact.TargetGroupNaming) - self:_NewRadioEntry(text,textScreen,0,false,self.debug,true,false,true) - - -- pull from Contacts self.Contacts:PullByID(contact.CID) -- end end @@ -2153,12 +2171,12 @@ function AWACS:_CreatePicture(AO,Callsign,GID,MaxEntries,IsGeneral) if IsGeneral then -- AO/BE Reference refBRAA=self:_ToStringBULLS(coordinate) - if self.PathToGoogleKey then - refBRAATTS = self:_ToStringBULLS(coordinate, true) - else + -- if self.PathToGoogleKey then + refBRAATTS = self:_ToStringBULLS(coordinate, false, true) + --else --refBRAATTS = self:__ToStringBullsTTS(refBRAA) - refBRAATTS = self:_ToStringBULLS(coordinate,false,true) - end + --refBRAATTS = self:_ToStringBULLS(coordinate,false,true) + --end local alt = contact.Contact.group:GetAltitude() or 8000 alt = UTILS.Round(UTILS.MetersToFeet(alt)/1000,0) -- Alpha Group. Bulls eye 0 2 1, 16 miles, 25 thousand. @@ -2171,7 +2189,7 @@ function AWACS:_CreatePicture(AO,Callsign,GID,MaxEntries,IsGeneral) refBRAATTS = string.gsub(refBRAATTS,"BRA","brah") -- Charlie group, BRAA 045, 105 miles, Angels 41, Flanking, Track North-East, Bogey, Spades. if self.PathToGoogleKey then - refBRAATTS = coordinate:ToStringBRAANATO(groupcoord,true,true,true) + refBRAATTS = coordinate:ToStringBRAANATO(groupcoord,true,true,true,false,true) end if contact.IFF ~= AWACS.IFF.BOGEY then refBRAA = string.gsub(refBRAA,"Bogey", contact.IFF) @@ -2184,11 +2202,11 @@ function AWACS:_CreatePicture(AO,Callsign,GID,MaxEntries,IsGeneral) -- Aspect local aspect = "" - if IsGeneral then - aspect = coordinate:ToStringAspect(self.OpsZone:GetCoordinate()) - text = text .. " "..aspect.."." -- Alpha Group. Bulls eye 0 2 1, 1 6. Flanking. - textScreen = textScreen .. " "..aspect.."." -- Alpha Group, Bullseye 021, 16, Flanking. - end + -- if IsGeneral then + -- aspect = coordinate:ToStringAspect(self.OpsZone:GetCoordinate()) + -- text = text .. " "..aspect.."." -- Alpha Group. Bulls eye 0 2 1, 1 6. Flanking. + -- textScreen = textScreen .. " "..aspect.."." -- Alpha Group, Bullseye 021, 16, Flanking. + --end -- sizing local size = contact.Contact.group:CountAliveUnits() @@ -2201,7 +2219,7 @@ function AWACS:_CreatePicture(AO,Callsign,GID,MaxEntries,IsGeneral) -- engagement tag? if contact.EngagementTag then - text = text .. " "..contact.EngagementTag -- Alpha Group. Bulls eye 0 2 1, 16. Flanking. Heavy. Targeted by Jazz 1 1. + text = text .. " "..contact.EngagementTag -- Alpha Group. Bulls eye 0 2 1, 16. Heavy. Targeted by Jazz 1 1. textScreen = textScreen .. " "..contact.EngagementTag -- Alpha Group, Bullseye 021, 16, Flanking. Targeted by Jazz 1 1. end @@ -2499,7 +2517,7 @@ end -- @param #string Declaration Text declaration the player used -- @return #AWACS self function AWACS:_VID(Group,Declaration) - self:I(self.lid.."_VID") + self:T(self.lid.."_VID") local GID, Outcome, Callsign = self:_GetManagedGrpID(Group) local text = "" @@ -2533,7 +2551,7 @@ function AWACS:_VID(Group,Declaration) distance = UTILS.Round(distance,0) + 1 if distance <= radius or self.debug then -- we can VID - self:I("Contact VID as "..Declaration) + self:T("Contact VID as "..Declaration) -- update cluster.IFF = Declaration task.Status = AWACS.TaskStatus.SUCCESS @@ -2542,12 +2560,12 @@ function AWACS:_VID(Group,Declaration) self.Contacts:PullByID(CID) self.Contacts:Push(cluster,CID) text = string.format("%s. %s. Copy, target identified as %s.",Callsign,self.callsigntxt, Declaration) - self:I(text) + self:T(text) else -- too far away - self:I("Contact VID not close enough") + self:T("Contact VID not close enough") text = string.format("%s. %s. Negative, get closer to target.",Callsign,self.callsigntxt) - self:I(text) + self:T(text) end self:_NewRadioEntry(text,text,GID,Outcome,true,true,false,true) end @@ -2921,7 +2939,8 @@ function AWACS:_CheckIn(Group) self.ManagedGrps[self.ManagedGrpID]=managedgroup local alphacheckbulls = self:_ToStringBULLS(Group:GetCoordinate()) - local alphacheckbullstts = self:_ToStringBullsTTS(alphacheckbulls)-- make tts friendly + --local alphacheckbullstts = self:_ToStringBullsTTS(alphacheckbulls)-- make tts friendly + local alphacheckbullstts = self:_ToStringBULLS(Group:GetCoordinate(),false,true) self.ManagedGrps[self.ManagedGrpID]=managedgroup text = string.format("%s. %s. Alpha Check. %s",managedgroup.CallSign,self.callsigntxt,alphacheckbulls) @@ -2989,8 +3008,8 @@ function AWACS:_CheckInAI(FlightGroup,Group,AuftragsNr) self:_NewRadioEntry(text,text,managedgroup.GID,Outcome,false,true,true) - local alphacheckbulls = self:_ToStringBULLS(Group:GetCoordinate()) - alphacheckbulls = self:_ToStringBullsTTS(alphacheckbulls)-- make tts friendly + local alphacheckbulls = self:_ToStringBULLS(Group:GetCoordinate(),false,true) + --alphacheckbulls = self:_ToStringBullsTTS(alphacheckbulls)-- make tts friendly text = string.format("%s. %s. Alpha Check. %s",managedgroup.CallSign,self.callsigntxt,alphacheckbulls) self:__CheckedIn(1,managedgroup.GID) @@ -3073,8 +3092,11 @@ function AWACS:_SetClientMenus() -- go through set and build the menu local grp = _group -- Wrapper.Client#CLIENT local cgrp = grp:GetGroup() - local cgrpname = cgrp:GetName() - self:T(cgrpname) + local cgrpname = nil + if cgrp and cgrp:IsAlive() then + cgrpname = cgrp:GetName() + self:T(cgrpname) + end --cgrpname = string.match(cgrpname,"([%a%s]+)#") if self.MenuStrict then -- check if pilot has checked in @@ -3519,14 +3541,16 @@ function AWACS:_ToStringBR(FromCoordinate,ToCoordinate) local AngleDegText = string.format("%03d",AngleDegrees) -- 051 local AngleDegTextTTS = "" - if self.PathToGoogleKey then - AngleDegTextTTS = string.format("%s",AngleDegText) - else - AngleDegTextTTS = string.format("%s",AngleDegText) - end + --if self.PathToGoogleKey then + --AngleDegTextTTS = string.format("%s",AngleDegText) + --else + --AngleDegTextTTS = string.format("%s",AngleDegText) + --end AngleDegText = string.gsub(AngleDegText,"%d","%1 ") -- "0 5 1 " AngleDegText = string.gsub(AngleDegText," $","") -- "0 5 1" + AngleDegTextTTS = string.gsub(AngleDegText,"0","zero") + local Distance = ToCoordinate:Get2DDistance( FromCoordinate ) --meters local distancenm = UTILS.Round(UTILS.MetersToNM(Distance),0) @@ -3558,9 +3582,11 @@ function AWACS:_ToStringBRA(FromCoordinate,ToCoordinate,Altitude) local AngleDegrees = UTILS.Round( UTILS.ToDegree( AngleRadians ), 0 ) -- degrees local AngleDegText = string.format("%03d",AngleDegrees) -- 051 - local AngleDegTextTTS = string.format("%s",AngleDegText) + --local AngleDegTextTTS = string.format("%s",AngleDegText) + AngleDegText = string.gsub(AngleDegText,"%d","%1 ") -- "0 5 1 " AngleDegText = string.gsub(AngleDegText," $","") -- "0 5 1" + local AngleDegTextTTS = string.gsub(AngleDegText,"0","zero") local Distance = ToCoordinate:Get2DDistance( FromCoordinate ) --meters local distancenm = UTILS.Round(UTILS.MetersToNM(Distance),0) BRText = string.format("%03d, %d miles, %d thousand",AngleDegrees,distancenm,altitude) @@ -3766,7 +3792,7 @@ end -- @param #AWACS self -- @return #AWACS self function AWACS:_CheckTaskQueue() - self:I(self.lid.."_CheckTaskQueue") + self:T(self.lid.."_CheckTaskQueue") local opentasks = 0 local assignedtasks = 0 @@ -3789,7 +3815,7 @@ function AWACS:_CheckTaskQueue() if self.ManagedTasks:IsNotEmpty() then opentasks = self.ManagedTasks:GetSize() - self:I("Assigned Tasks: " .. opentasks) + self:T("Assigned Tasks: " .. opentasks) local taskstack = self.ManagedTasks:GetPointerStack() for _id,_entry in pairs(taskstack) do local data = _entry -- Utilities.FiFo#FIFO.IDEntry @@ -3797,7 +3823,7 @@ function AWACS:_CheckTaskQueue() local target = entry.Target -- Ops.Target#TARGET local description = entry.ToDo if description == AWACS.TaskDescription.ANCHOR or description == AWACS.TaskDescription.REANCHOR then - self:I("Open Task ANCHOR/REANCHOR") + self:T("Open Task ANCHOR/REANCHOR") -- see if we have reached the anchor zone local managedgroup = self.ManagedGrps[entry.AssignedGroupID] -- #AWACS.ManagedGroup if managedgroup then @@ -3807,7 +3833,7 @@ function AWACS:_CheckTaskQueue() local zone = target:GetObject() -- Core.Zone#ZONE self:T({zone}) if group:IsInZone(zone) then - self:I("Open Task ANCHOR/REANCHOR success for GroupID "..entry.AssignedGroupID) + self:T("Open Task ANCHOR/REANCHOR success for GroupID "..entry.AssignedGroupID) -- made it target:Stop() -- add group to idle stack @@ -3824,7 +3850,7 @@ function AWACS:_CheckTaskQueue() self.ManagedTasks:PullByID(entry.TID) else --inzone -- not there yet - self:I("Open Task ANCHOR/REANCHOR executing for GroupID "..entry.AssignedGroupID) + self:T("Open Task ANCHOR/REANCHOR executing for GroupID "..entry.AssignedGroupID) end else -- group dead, pull task @@ -3838,7 +3864,7 @@ function AWACS:_CheckTaskQueue() elseif description == AWACS.TaskDescription.INTERCEPT then -- DONE - self:I("Open Tasks INTERCEPT") + self:T("Open Tasks INTERCEPT") local taskstatus = entry.Status local targetstatus = entry.Target:GetState() @@ -3864,15 +3890,15 @@ function AWACS:_CheckTaskQueue() distance = grouposition:Get2DDistance(position) distance = UTILS.Round(UTILS.MetersToNM(distance),0) end - self:I("TAC/MELD distance check: "..distance.."NM!") + self:T("TAC/MELD distance check: "..distance.."NM!") if distance <= self.TacDistance and distance >= self.MeldDistance then -- TAC distance - self:I("TAC distance: "..distance.."NM!") + self:T("TAC distance: "..distance.."NM!") local Contact = self.Contacts:ReadByID(entry.Contact.CID) self:_TACRangeCall(entry.AssignedGroupID,Contact) elseif distance <= self.MeldDistance and distance >= self.ThreatDistance then -- MELD distance - self:I("MELD distance: "..distance.."NM!") + self:T("MELD distance: "..distance.."NM!") local Contact = self.Contacts:ReadByID(entry.Contact.CID) self:_MeldRangeCall(entry.AssignedGroupID,Contact) end @@ -3885,7 +3911,7 @@ function AWACS:_CheckTaskQueue() auftragstatus = auftrag:GetState() end local text = string.format("ID=%d | Status=%s | TargetState=%s | AuftragState=%s",entry.TID,taskstatus,targetstatus,auftragstatus) - self:I(text) + self:T(text) if auftrag then if auftrag:IsExecuting() then entry.Status = AWACS.TaskStatus.EXECUTING @@ -3943,7 +3969,7 @@ function AWACS:_CheckTaskQueue() end if entry.Status == AWACS.TaskStatus.SUCCESS then - self:I("Open Tasks INTERCEPT success for GroupID "..entry.AssignedGroupID) + self:T("Open Tasks INTERCEPT success for GroupID "..entry.AssignedGroupID) if managedgroup then self:_UpdateContactEngagementTag(managedgroup.ContactCID,"",true,true,AWACS.TaskStatus.SUCCESS) @@ -3966,7 +3992,7 @@ function AWACS:_CheckTaskQueue() end elseif entry.Status == AWACS.TaskStatus.FAILED then - self:I("Open Tasks INTERCEPT failed for GroupID "..entry.AssignedGroupID) + self:T("Open Tasks INTERCEPT failed for GroupID "..entry.AssignedGroupID) if managedgroup then managedgroup.HasAssignedTask = false self:_UpdateContactEngagementTag(managedgroup.ContactCID,"",false,false,AWACS.TaskStatus.UNASSIGNED) @@ -3991,7 +4017,7 @@ function AWACS:_CheckTaskQueue() elseif entry.Status == AWACS.TaskStatus.REQUESTED then -- requested - player tasks only! - self:I("Open Tasks INTERCEPT REQUESTED for GroupID "..entry.AssignedGroupID) + self:T("Open Tasks INTERCEPT REQUESTED for GroupID "..entry.AssignedGroupID) local created = entry.RequestedTimestamp or timer.getTime() - 120 local Tnow = timer.getTime() local Trunning = (Tnow-created) / 60 -- mins @@ -4001,7 +4027,7 @@ function AWACS:_CheckTaskQueue() entry.Status = AWACS.TaskStatus.UNASSIGNED self.ManagedTasks:PullByID(entry.TID) end - self:I(text) + self:T(text) end ---------------------------------------- @@ -4026,7 +4052,7 @@ function AWACS:_CheckTaskQueue() elseif entry.Target:IsAlive() then -- still alive -- out of zones? - self:I("Checking VID target out of bounds") + self:T("Checking VID target out of bounds") local targetpos = entry.Target:GetCoordinate() -- success == out of our controlled zones local outofzones = false @@ -4057,13 +4083,13 @@ function AWACS:_CheckTaskQueue() end if outofzones then entry.Status = AWACS.TaskStatus.SUCCESS - self:I("Out of bounds - SUCCESS") + self:T("Out of bounds - SUCCESS") end end if entry.Status == AWACS.TaskStatus.REQUESTED then -- requested - player tasks only! - self:I("Open Tasks VID REQUESTED for GroupID "..entry.AssignedGroupID) + self:T("Open Tasks VID REQUESTED for GroupID "..entry.AssignedGroupID) local created = entry.RequestedTimestamp or timer.getTime() - 120 local Tnow = timer.getTime() local Trunning = (Tnow-created) / 60 -- mins @@ -4073,9 +4099,9 @@ function AWACS:_CheckTaskQueue() entry.Status = AWACS.TaskStatus.UNASSIGNED self.ManagedTasks:PullByID(entry.TID) end - self:I(text) + self:T(text) elseif entry.Status == AWACS.TaskStatus.ASSIGNED then - self:I("Open Tasks VID ASSIGNED for GroupID "..entry.AssignedGroupID) + 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 @@ -4088,29 +4114,29 @@ function AWACS:_CheckTaskQueue() distance = grouposition:Get2DDistance(position) distance = UTILS.Round(UTILS.MetersToNM(distance),0) end - self:I("TAC/MELD distance check: "..distance.."NM!") + self:T("TAC/MELD distance check: "..distance.."NM!") if distance <= self.TacDistance and distance >= self.MeldDistance then -- TAC distance - self:I("TAC distance: "..distance.."NM!") + self:T("TAC distance: "..distance.."NM!") local Contact = self.Contacts:ReadByID(entry.Contact.CID) self:_TACRangeCall(entry.AssignedGroupID,Contact) elseif distance <= self.MeldDistance and distance >= self.ThreatDistance then -- MELD distance - self:I("MELD distance: "..distance.."NM!") + self:T("MELD distance: "..distance.."NM!") local Contact = self.Contacts:ReadByID(entry.Contact.CID) self:_MeldRangeCall(entry.AssignedGroupID,Contact) end end end elseif entry.Status == AWACS.TaskStatus.SUCCESS then - self:I("Open Tasks VID success for GroupID "..entry.AssignedGroupID) + self:T("Open Tasks VID success for GroupID "..entry.AssignedGroupID) -- outcomes - player ID'd -- target dead or left zones handled above -- target ID'd --> if hostile, assign INTERCEPT TASK self.ManagedTasks:PullByID(entry.TID) local Contact = self.Contacts:ReadByID(entry.Contact.CID) -- #AWACS.ManagedContact if Contact and (Contact.IFF == AWACS.IFF.FRIENDLY or Contact.IFF == AWACS.IFF.NEUTRAL) then - self:I("IFF outcome friendly/neutral for GroupID "..entry.AssignedGroupID) + self:T("IFF outcome friendly/neutral for GroupID "..entry.AssignedGroupID) -- nothing todo, re-anchor if managedgroup then managedgroup.HasAssignedTask = false @@ -4130,7 +4156,7 @@ function AWACS:_CheckTaskQueue() self:__ReAnchor(5,managedgroup.GID) end elseif Contact and Contact.IFF == AWACS.IFF.ENEMY then - self:I("IFF outcome hostile for GroupID "..entry.AssignedGroupID) + self:T("IFF outcome hostile for GroupID "..entry.AssignedGroupID) -- change to intercept --self.ManagedTasks:PullByID(entry.TID) entry.ToDo = AWACS.TaskDescription.INTERCEPT @@ -4141,7 +4167,7 @@ function AWACS:_CheckTaskQueue() local TextTTS = string.format("%s, %s. Engage hostile target!",managedgroup.CallSign,self.callsigntxt) self:_NewRadioEntry(TextTTS,TextTTS,managedgroup.GID,true,self.debug,true,false,true) elseif not Contact then - self:I("IFF outcome target DEAD for GroupID "..entry.AssignedGroupID) + self:T("IFF outcome target DEAD for GroupID "..entry.AssignedGroupID) -- nothing todo, re-anchor if managedgroup then managedgroup.HasAssignedTask = false @@ -4167,7 +4193,7 @@ function AWACS:_CheckTaskQueue() -- outcomes - player unable/abort -- Player dead managed above -- Remove task - self:I("Open Tasks VID failed for GroupID "..entry.AssignedGroupID) + self:T("Open Tasks VID failed for GroupID "..entry.AssignedGroupID) if managedgroup then managedgroup.HasAssignedTask = false self:_UpdateContactEngagementTag(managedgroup.ContactCID,"",false,false,AWACS.TaskStatus.UNASSIGNED) @@ -4328,7 +4354,7 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo BRAfromBullsTTS = string.gsub(BRAfromBulls,"BRAA","brah") BRAfromBullsTTS = string.gsub(BRAfromBullsTTS,"BRA","brah") if self.PathToGoogleKey then - BRAfromBullsTTS = clustercoordinate:ToStringBRAANATO(Group:GetCoordinate(),true,true,true) + BRAfromBullsTTS = clustercoordinate:ToStringBRAANATO(Group:GetCoordinate(),true,true,true,false,true) end end @@ -4707,7 +4733,7 @@ end -- @param #AWACS.ManagedContact Contact -- @return #AWACS self function AWACS:_TACRangeCall(GID,Contact) - self:I(self.lid.."_TACRangeCall") + self:T(self.lid.."_TACRangeCall") -- AIC: “Enforcer 11, single group, 30 miles.” local pilotcallsign = self:_GetCallSign(nil,GID) local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup @@ -4732,7 +4758,7 @@ end -- @param #AWACS.ManagedContact Contact -- @return #AWACS self function AWACS:_MeldRangeCall(GID,Contact) - self:I(self.lid.."_MeldRangeCall") + self:T(self.lid.."_MeldRangeCall") -- AIC: “Heat 11, single group, BRAA 089/28, 32 thousand, hot, hostile, crow.” local pilotcallsign = self:_GetCallSign(nil,GID) local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup @@ -4744,7 +4770,7 @@ function AWACS:_MeldRangeCall(GID,Contact) if position then local BRATExt = "" if self.PathToGoogleKey then - BRATExt = position:ToStringBRAANATO(flightpos,false,false,true) + BRATExt = position:ToStringBRAANATO(flightpos,false,false,true,false,true) else BRATExt = position:ToStringBRAANATO(flightpos,false,false) end @@ -4760,7 +4786,7 @@ end -- @param #AWACS self -- @return #AWACS self function AWACS:_ThreatRangeCall(GID,Contact) - self:I(self.lid.."_ThreatRangeCall") + self:T(self.lid.."_ThreatRangeCall") -- AIC: “Enforcer 11 12, east group, THREAT, BRAA 260/15, 29 thousand, hot, hostile, robin.” local pilotcallsign = self:_GetCallSign(nil,GID) local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup @@ -4772,7 +4798,7 @@ function AWACS:_ThreatRangeCall(GID,Contact) if position then local BRATExt = "" if self.PathToGoogleKey then - BRATExt = position:ToStringBRAANATO(flightpos,false,false,true) + BRATExt = position:ToStringBRAANATO(flightpos,false,false,true,false,true) else BRATExt = position:ToStringBRAANATO(flightpos,false,false) end @@ -4783,13 +4809,27 @@ function AWACS:_ThreatRangeCall(GID,Contact) return self end +--- [Internal] Merged Call to Pilot +-- @param #AWACS self +-- @param #number GID +-- @return #AWACS self +function AWACS:_MergedCall(GID) + self:T(self.lid.."_MergedCall") + -- AIC: “Enforcer, mergedb” + local pilotcallsign = self:_GetCallSign(nil,GID) + --local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup + local text = string.format("%s. %s. Merged.",self.callsigntxt,pilotcallsign) + self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true) + return self +end + --- [Internal] Assign a Pilot to a target -- @param #AWACS self -- @param #table Pilots Table of #AWACS.ManagedGroup Pilot -- @param Utilities.FiFo#FIFO Targets FiFo of #AWACS.ManagedContact Targets -- @return #AWACS self function AWACS:_AssignPilotToTarget(Pilots,Targets) - self:I(self.lid.."_AssignPilotToTarget") + self:T(self.lid.."_AssignPilotToTarget") local inreach = false local Pilot = nil -- #AWACS.ManagedGroup @@ -4807,7 +4847,7 @@ function AWACS:_AssignPilotToTarget(Pilots,Targets) local pilotcoord = _Pilot.Group:GetCoordinate() local targetdist = targetgroupcoord:Get2DDistance(pilotcoord) if UTILS.MetersToNM(targetdist) < self.maxassigndistance and targetdist < closest then - self:I(string.format("%sTarget distance %d! Assignment %s!",self.lid,UTILS.Round(UTILS.MetersToNM(targetdist),0),_Pilot.CallSign)) + self:T(string.format("%sTarget distance %d! Assignment %s!",self.lid,UTILS.Round(UTILS.MetersToNM(targetdist),0),_Pilot.CallSign)) inreach = true closest = targetdist Pilot = _Pilot @@ -4815,7 +4855,7 @@ function AWACS:_AssignPilotToTarget(Pilots,Targets) Targets:PullByID(_target.CID) break else - self:I(self.lid .. "Target distance > "..self.maxassigndistance.."NM! No Assignment!") + self:T(self.lid .. "Target distance > "..self.maxassigndistance.."NM! No Assignment!") end end end @@ -4855,8 +4895,8 @@ function AWACS:_AssignPilotToTarget(Pilots,Targets) self.Contacts:PullByID(Target.CID) self.Contacts:Push(Target,Target.CID) - local text = string.format("%s. %s. Request commit %s group. %s.", self.callsigntxt,Pilot.CallSign,Target.TargetGroupNaming,TargetDirectionsTTS) - local textScreen = string.format("%s, %s. Request commit %s group. %s.", self.callsigntxt,Pilot.CallSign,Target.TargetGroupNaming,TargetDirections) + local text = string.format("%s. %s group. %s. %s, request commit.", self.callsigntxt,Target.TargetGroupNaming,TargetDirectionsTTS,Pilot.CallSign) + local textScreen = string.format("%s. %s group. %s. %s, request commit.", self.callsigntxt,Target.TargetGroupNaming,TargetDirections,Pilot.CallSign) self:_NewRadioEntry(text,textScreen,Pilot.GID,true,self.debug,true,false,true) @@ -4864,15 +4904,15 @@ function AWACS:_AssignPilotToTarget(Pilots,Targets) -- Target information local callsign = Pilot.CallSign local FGStatus = Pilot.FlightGroup:GetState() - self:I("Pilot AI Callsign: " .. callsign) - self:I("Pilot FG State: " .. FGStatus) + self:T("Pilot AI Callsign: " .. callsign) + self:T("Pilot FG State: " .. FGStatus) local targetstatus = Target.Target:GetState() - self:I("Target State: " .. targetstatus) + self:T("Target State: " .. targetstatus) -- local currmission = Pilot.FlightGroup:GetMissionCurrent() if currmission then - self:I("Current Mission: " .. currmission:GetType()) + self:T("Current Mission: " .. currmission:GetType()) end -- create one intercept Auftrag and one to return to CAP post this one local ZoneSet = self.ZoneSet @@ -4973,8 +5013,8 @@ function AWACS:_AssignPilotToTarget(Pilots,Targets) end local bratext, bratexttts = self:_ToStringBRA(Pilot.Group:GetCoordinate(),position,altitude or 8000) - local text = string.format("%s. %s. Commit %s group. %s.", self.callsigntxt,Pilot.CallSign,Target.TargetGroupNaming,bratexttts) - local textScreen = string.format("%s, %s. Commit %s group. %s.", self.callsigntxt,Pilot.CallSign,Target.TargetGroupNaming,bratext) + local text = string.format("%s. %s group. %s. %s, commit.", self.callsigntxt,Target.TargetGroupNaming,bratexttts,Pilot.CallSign) + local textScreen = string.format("%s. %s group. %s. %s, request commit.", self.callsigntxt,Target.TargetGroupNaming,bratext,Pilot.CallSign) self:_NewRadioEntry(text,textScreen,Pilot.GID,true,self.debug,true,false,true) @@ -5323,6 +5363,8 @@ function AWACS:onafterStatus(From, Event, To) self:_CleanUpContacts() + self:_CheckMerges() + if self.debug then --local outcome, targets = self:_TargetSelectionProcess() -- TODO for debug ATM end @@ -5474,9 +5516,9 @@ function AWACS:onafterAssignedAnchor(From, Event, To, GID, Anchor, AnchorStackNo local AnchorSpeed = self.CapSpeedBase or 270 local AuftragsNr = managedgroup.CurrentAuftrag - local textTTS = string.format("%s. %s. Station at %s at angels %d doing %d knots. Wait for task assignment.",CallSign,self.callsigntxt,AnchorName,Angels,AnchorSpeed) - local ROEROT = self.AwacsROE.." "..self.AwacsROT - local textScreen = string.format("%s. %s.\nStation at %s\nAngels %d\nSpeed %d knots\nCoord %s\nROE %s\nWait for task assignment.",CallSign,self.callsigntxt,AnchorName,Angels,AnchorSpeed,AnchorCoordTxt,ROEROT) + local textTTS = string.format("%s. %s. Station at %s at angels %d doing %d knots.",CallSign,self.callsigntxt,AnchorName,Angels,AnchorSpeed) + local ROEROT = self.AwacsROE..", "..self.AwacsROT + local textScreen = string.format("%s. %s.\nStation at %s\nAngels %d\nSpeed %d knots\nCoord %s\nROE %s.",CallSign,self.callsigntxt,AnchorName,Angels,AnchorSpeed,AnchorCoordTxt,ROEROT) local TextTasking = string.format("Station at %s\nAngels %d\nSpeed %d knots\nCoord %s\nROE %s",AnchorName,Angels,AnchorSpeed,AnchorCoordTxt,ROEROT) self:_NewRadioEntry(textTTS,textScreen,GID,isPlayer,isPlayer,true,false) @@ -5865,9 +5907,9 @@ function AWACS:onafterReAnchor(From, Event, To, GID) local brtext = self:_ToStringBULLS(lastknown) local brtexttts = self:_ToStringBULLS(brtext,false,true) - if self.PathToGoogleKey then - brtexttts = self:_ToStringBULLS(lastknown,true) - end + --if self.PathToGoogleKey then + --brtexttts = self:_ToStringBULLS(lastknown,true) + --end text = text .. " "..brtexttts.." miles." textScreen = textScreen .. " "..brtext.." miles." @@ -5916,9 +5958,9 @@ function AWACS:onafterReAnchor(From, Event, To, GID) local lastknown = UTILS.DeepCopy(managedgroup.LastKnownPosition) local brtext = self:_ToStringBULLS(lastknown) local brtexttts = self:_ToStringBULLS(brtext,false,true) - if self.PathToGoogleKey then - brtexttts = self:_ToStringBULLS(lastknown,true) - end + --if self.PathToGoogleKey then + --brtexttts = self:_ToStringBULLS(lastknown,true) + --end text = text .. " "..brtexttts.." miles." textScreen = textScreen .. " "..brtext.." miles." From 6c33c5701f0cb2f6a93c9b6d895440566164ac23 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 31 May 2022 16:21:19 +0200 Subject: [PATCH 08/30] Awacs --- Moose Development/Moose/Ops/Awacs.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index 17870073b..1ce2ba6c5 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -4372,7 +4372,7 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo TextScreen = string.format("%s.",self.callsigntxt) end - if IsNew then + if IsNew and self.PlayerGuidance then BRAText = BRAText .. " New group." TextScreen = TextScreen .. " New group." elseif IsPopup then From 3f918bd309a38be694fe787d9f8145c98cd3fad5 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 2 Jun 2022 15:31:03 +0200 Subject: [PATCH 09/30] AWACS 0.1.25 * Added Function ZipLip * Changed merge distance to 5nm for account for delay in speech generation * Altered RadioQueue to not save all calls until a player connects * Some bugfixes --- Moose Development/Moose/Ops/Awacs.lua | 51 +++++++++++++++++++++------ 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index 1ce2ba6c5..217e2bc3b 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -323,7 +323,7 @@ do -- @field #AWACS AWACS = { ClassName = "AWACS", -- #string - version = "beta 0.1.24", -- #string + version = "beta 0.1.25", -- #string lid = "", -- #string coalition = coalition.side.BLUE, -- #number coalitiontxt = "blue", -- #string @@ -658,7 +658,7 @@ AWACS.TaskStatus = { --@field #boolean FromAI ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- TODO-List 0.1.24 +-- TODO-List 0.1.25 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- -- DEBUG - WIP - Player tasking, VID @@ -1142,13 +1142,24 @@ end --- [User] Do not show messages on screen -- @param #AWACS self -- @param #boolean Switch If true, no messages will be shown on screen. --- @return #AWACS sel +-- @return #AWACS self function AWACS:SuppressScreenMessages(Switch) self:T(self.lid.."_SetBullsEyeAlias") self.SuppressScreenOutput = Switch or false return self end +--- [User] Do not show messages on screen, no extra calls for player guidance, use short callsigns. +-- @param #AWACS self +-- @return #AWACS self +function AWACS:ZipLip() + self:T(self.lid.."ZipLip") + self:SuppressScreenMessages(true) + self.PlayerGuidance = false + self.callsignshort = true + return self +end + --- [Internal] Event handler -- @param #AWACS self -- @param Wrapper.Group#GROUP Group Group, can also be passed as #string group name @@ -1320,6 +1331,17 @@ function AWACS:SetColdWar() return self end +--- [User] Set AWACS to Modern Era standards - ROE to BVR, ROT to defensive (evade fire). Radar blur 15%. +-- @param #AWACS self +-- @return #AWACS self +function AWACS:SetModernEra() + self.ModernEra = true + self.AwacsROT = AWACS.ROT.EVADE + self.AwacsROE = AWACS.ROE.BVR + self.RadarBlur = 15 + return self +end + --- [User] Set AWACS to Modern Era standards - ROE to IFF, ROT to defensive (evade fire). Radar blur 15%. -- @param #AWACS self -- @return #AWACS self @@ -1754,7 +1776,7 @@ end -- @return #string CallSign function AWACS:_GetManagedGrpID(Group) if not Group or not Group:IsAlive() then - self:E(self.lid.."_GetManagedGrpID - Requested Group is not alive!") + self:T(self.lid.."_GetManagedGrpID - Requested Group is not alive!") return 0,false,"" end self:T(self.lid.."_GetManagedGrpID for "..Group:GetName()) @@ -1855,7 +1877,8 @@ 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 and distnm <= 3 then + if (pilot.IsPlayer or self.debug) and distnm <= 5 then + self:I(self.lid.."Merged") self:_MergedCall(_id) end end @@ -5573,6 +5596,9 @@ function AWACS:onafterNewCluster(From,Event,To,Cluster) end local Contact = GetFirstAliveContact(ContactTable) -- Ops.Intelligence#INTEL.Contact + + if not Contact then return self end + local targetset = SET_GROUP:New() -- SET for TARGET for _,_grp in pairs(ContactTable) do @@ -5695,7 +5721,7 @@ function AWACS:onafterCheckRadioQueue(From,Event,To) -- do we have messages queued? local nextcall = 10 - if (self.RadioQueue:IsNotEmpty() or self.PrioRadioQueue:IsNotEmpty()) and self.clientset:CountAlive() > 0 then + if (self.RadioQueue:IsNotEmpty() or self.PrioRadioQueue:IsNotEmpty()) then local RadioEntry = nil @@ -5706,6 +5732,12 @@ function AWACS:onafterCheckRadioQueue(From,Event,To) end self:T({RadioEntry}) + if self.clientset:CountAlive() == 0 then + self:I(self.lid.."No player connected.") + self:__CheckRadioQueue(5) + return self + end + if not RadioEntry.FromAI then -- AI AWACS Speaking if self.PathToGoogleKey then @@ -5750,7 +5782,7 @@ function AWACS:onafterCheckRadioQueue(From,Event,To) if self:Is("Running") then -- exit if stopped - self:__CheckRadioQueue(nextcall+2) + self:__CheckRadioQueue(nextcall+1) end return self end @@ -5906,7 +5938,7 @@ function AWACS:onafterReAnchor(From, Event, To, GID) local textScreen = string.format("All stations, %s. %s %s.", self.callsigntxt, faded, savedcallsign) local brtext = self:_ToStringBULLS(lastknown) - local brtexttts = self:_ToStringBULLS(brtext,false,true) + local brtexttts = self:_ToStringBULLS(lastknown,false,true) --if self.PathToGoogleKey then --brtexttts = self:_ToStringBULLS(lastknown,true) --end @@ -5957,7 +5989,7 @@ function AWACS:onafterReAnchor(From, Event, To, GID) if managedgroup.LastKnownPosition then local lastknown = UTILS.DeepCopy(managedgroup.LastKnownPosition) local brtext = self:_ToStringBULLS(lastknown) - local brtexttts = self:_ToStringBULLS(brtext,false,true) + local brtexttts = self:_ToStringBULLS(lastknown,false,true) --if self.PathToGoogleKey then --brtexttts = self:_ToStringBULLS(lastknown,true) --end @@ -5970,7 +6002,6 @@ function AWACS:onafterReAnchor(From, Event, To, GID) end end end - return self end end -- end do From bd3364a3cf2eda953e4a1930df7cb59b900baabf Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 2 Jun 2022 17:39:39 +0200 Subject: [PATCH 10/30] AWACS - limit merge calls --- Moose Development/Moose/Ops/Awacs.lua | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index 217e2bc3b..1596bf727 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -588,6 +588,7 @@ AWACS.CapVoices = { -- @field #string EngagementTag -- @field #boolean TACCallDone -- @field #boolean MeldCallDone +-- @field #boolean MergeCallDone --- -- @type AWACS.TaskDescription @@ -1870,6 +1871,8 @@ function AWACS:_CheckMerges() local pilot = _pilot -- #AWACS.ManagedGroup if pilot.Group and pilot.Group:IsAlive() then local ppos = pilot.Group:GetCoordinate() + local pcallsign = pilot.CallSign + self:I(self.lid.."Checking for "..pcallsign) if ppos then self.Contacts:ForEach( function (Contact) @@ -1877,9 +1880,13 @@ 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 then - self:I(self.lid.."Merged") - self:_MergedCall(_id) + 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 + self:I(self.lid.."Merged") + self:_MergedCall(_id) + contact.MergeCallDone = true + end end end ) From 613b7eda8a31b103cfe17304fec61445d880cb75 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 3 Jun 2022 09:27:01 +0200 Subject: [PATCH 11/30] AWACS 0.1.26 - corrected player picture call to use B/E references, bogey dope to announce only one group. ZipLip will also remove group tags. --- Moose Development/Moose/Ops/Awacs.lua | 36 +++++++++++---------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index 1596bf727..de6fb39b3 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -246,12 +246,12 @@ do -- -- ### 6.3 Picture -- --- Get a picture from the AWACS. It will call out the three most important groups. References are BRAA to the Player position. --- **Note** that AWACS will do a regular picture call to all stations every five minutes. Here, references are to the (named) BullsEye position. +-- Get a picture from the AWACS. It will call out the three most important groups. References are **always** to the (named) BullsEye position. +-- **Note** that AWACS will anyway do a regular picture call to all stations every five minutes. -- -- ### 6.4 Bogey Dope -- --- Get bogey dope from the AWACS. It will call out the three most important groups. References are BRAA to the Player position. +-- Get bogey dope from the AWACS. It will call out the closest bogey group, if any. Reference is BRAA to the Player position. -- -- ### 6.5 Declare -- @@ -323,7 +323,7 @@ do -- @field #AWACS AWACS = { ClassName = "AWACS", -- #string - version = "beta 0.1.25", -- #string + version = "beta 0.1.26", -- #string lid = "", -- #string coalition = coalition.side.BLUE, -- #number coalitiontxt = "blue", -- #string @@ -659,7 +659,7 @@ AWACS.TaskStatus = { --@field #boolean FromAI ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- TODO-List 0.1.25 +-- TODO-List 0.1.26 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- -- DEBUG - WIP - Player tasking, VID @@ -1150,7 +1150,7 @@ function AWACS:SuppressScreenMessages(Switch) return self end ---- [User] Do not show messages on screen, no extra calls for player guidance, use short callsigns. +--- [User] Do not show messages on screen, no extra calls for player guidance, use short callsigns, no group tags. -- @param #AWACS self -- @return #AWACS self function AWACS:ZipLip() @@ -1158,6 +1158,7 @@ function AWACS:ZipLip() self:SuppressScreenMessages(true) self.PlayerGuidance = false self.callsignshort = true + self.NoGroupTags = true return self end @@ -2191,6 +2192,7 @@ function AWACS:_CreatePicture(AO,Callsign,GID,MaxEntries,IsGeneral) end local refBRAA = "" local refBRAATTS = "" + if self.NoGroupTags then text = "Group." -- Alpha Group. textScreen = "Group," @@ -2198,20 +2200,16 @@ function AWACS:_CreatePicture(AO,Callsign,GID,MaxEntries,IsGeneral) text = contact.TargetGroupNaming.." group." -- Alpha Group. textScreen = contact.TargetGroupNaming.." group," end - if IsGeneral then - -- AO/BE Reference + + --if IsGeneral then refBRAA=self:_ToStringBULLS(coordinate) - -- if self.PathToGoogleKey then - refBRAATTS = self:_ToStringBULLS(coordinate, false, true) - --else - --refBRAATTS = self:__ToStringBullsTTS(refBRAA) - --refBRAATTS = self:_ToStringBULLS(coordinate,false,true) - --end + refBRAATTS = self:_ToStringBULLS(coordinate, false, true) local alt = contact.Contact.group:GetAltitude() or 8000 alt = UTILS.Round(UTILS.MetersToFeet(alt)/1000,0) -- Alpha Group. Bulls eye 0 2 1, 16 miles, 25 thousand. text = text .. " "..refBRAATTS.." miles, "..alt.." thousand." -- Alpha Group. Bulls eye 0 2 1, 16 miles, 25 thousand. textScreen = textScreen .. " "..refBRAA.." miles, "..alt.." thousand." -- Alpha Group, Bullseye 021, 16 miles, 25 thousand, + --[[ else -- pilot reference refBRAA = coordinate:ToStringBRAANATO(groupcoord,true,true) @@ -2228,16 +2226,11 @@ function AWACS:_CreatePicture(AO,Callsign,GID,MaxEntries,IsGeneral) text = text .. " "..refBRAATTS textScreen = textScreen .." "..refBRAA end + --]] -- Aspect local aspect = "" - -- if IsGeneral then - -- aspect = coordinate:ToStringAspect(self.OpsZone:GetCoordinate()) - -- text = text .. " "..aspect.."." -- Alpha Group. Bulls eye 0 2 1, 1 6. Flanking. - -- textScreen = textScreen .. " "..aspect.."." -- Alpha Group, Bullseye 021, 16, Flanking. - --end - -- sizing local size = contact.Contact.group:CountAliveUnits() local threatsize, threatsizetext = self:_GetBlurredSize(size) @@ -2285,7 +2278,8 @@ function AWACS:_CreateBogeyDope(Callsign,GID) local groupcoord = group:GetCoordinate() local fifo = self.ContactsAO -- Utilities.FiFo#FIFO - local maxentries = self.maxspeakentries + --local maxentries = self.maxspeakentries + local maxentries = 1 local counter = 0 local entries = fifo:GetSize() From feddda2948fdd5254df52b32366150d81b790ef9 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 3 Jun 2022 14:42:08 +0200 Subject: [PATCH 12/30] AWACS - added docu for speech queue padding options --- Moose Development/Moose/Ops/Awacs.lua | 53 +++++++++++++++++++++------ 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index de6fb39b3..97bc4680d 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -24,9 +24,7 @@ -- === -- -- ### Author: **applevangelist** --- @date Last Update May 2022 --- --- == +-- @date Last Update June 2022 -- @module Ops.AWACS -- @image OPS_AWACS.jpg @@ -110,6 +108,8 @@ do -- @field #number ReassignmentPause Wait this many seconds before re-assignment of a player -- @field #boolean NoGroupTags Set to true if you don't want group tags. -- @field #boolean SuppressScreenOutput Set to true to suppress all screen output. +-- @field #number GoogleTTSPadding +-- @field #number WindowsTTSPadding -- @extends Core.Fsm#FSM @@ -128,8 +128,6 @@ do -- ** References from ARN33396 ATP 3-52.4 (Sep 2021) (Combined Forces) -- ** References from CNATRA P-877 (Rev 12-20) (NAVY) -- * FSM events that the mission designer can hook into --- --- === -- -- ## 1 Prerequisites -- @@ -315,11 +313,19 @@ do -- testawacs.MenuStrict = true -- Players need to check-in to see the menu; check-in still require to use the menu. -- testawacs.maxassigndistance = 100 -- Don't assign targets further out than this, in NM. -- testawacs.debug = false -- set to true to produce more log output. +-- -- By default, the radio queue is checked every 10 secs. This is altered by the calculated length of the sentence to speak +-- -- over the radio. Google and Windows speech speed is different. Use the below to fine-tune the setup in case of overlapping +-- -- messages or too long pauses +-- testawacs.GoogleTTSPadding = 1 +-- testawacs.WindowsTTSPadding = 2.5 -- -- ## 10 Discussion -- -- If you have questions or suggestions, please visit the [MOOSE Discord](https://discord.gg/AeYAkHP) #ops-awacs channel. -- +-- +-- +-- -- @field #AWACS AWACS = { ClassName = "AWACS", -- #string @@ -399,6 +405,8 @@ AWACS = { ReassignmentPause = 180, NoGroupTags = false, SuppressScreenOutput = false, + GoogleTTSPadding = 1, + WindowsTTSPadding = 2.5, } --- @@ -842,6 +850,8 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station self.RadioQueue = FIFO:New() -- Utilities.FiFo#FIFO self.PrioRadioQueue = FIFO:New() -- Utilities.FiFo#FIFO self.maxspeakentries = 3 + self.GoogleTTSPadding = 1 + self.WindowsTTSPadding = 2.5 -- Client SET self.clientset = SET_CLIENT:New():FilterActive(true):FilterCoalitions(self.coalitiontxt):FilterCategories("plane"):FilterStart() @@ -1286,7 +1296,7 @@ end -- @return #AWACS self function AWACS:_MissileWarning(Coordinate,Type,Warndist) self:T(self.lid.."_MissileWarning Type="..Type.." WarnDist="..Warndist) - self:T(UTILS.OneLineSerialize(Coordinate)) + --self:T(UTILS.OneLineSerialize(Coordinate)) if not Coordinate then return self end local shotzone = ZONE_RADIUS:New("WarningZone",Coordinate:GetVec2(),UTILS.NMToMeters(Warndist)) local targetgrpset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryAirplane():FilterActive():FilterZones({shotzone}):FilterOnce() @@ -1295,7 +1305,7 @@ function AWACS:_MissileWarning(Coordinate,Type,Warndist) for _,_grp in pairs (targets) do -- TODO -- player callouts only if _grp and _grp:IsAlive() then - local isPlayer = _grp:GetUnit(1):IsPlayer() + local isPlayer = _grp:IsPlayer() --if self.debug or isPlayer then if isPlayer then local callsign = self:_GetCallSign(_grp) @@ -1390,6 +1400,19 @@ function AWACS:SetPolicingColdWar() return self end +--- [User] Set AWACS Player Guidance - influences missile callout and the "New" label in group callouts. +-- @param #AWACS self +-- @param #boolean Switch If true (default) it is on, if false, it is off. +-- @return #AWACS self +function AWACS:SetPlayerGuidance(Switch) + if (Switch == nil) or (Switch == true) then + self.PlayerGuidance = true + else + self.PlayerGuidance = false + end + return self +end + --- [User] Get AWACS Name -- @param #AWACS self -- @return #string Name of this instance @@ -1873,7 +1896,7 @@ function AWACS:_CheckMerges() if pilot.Group and pilot.Group:IsAlive() then local ppos = pilot.Group:GetCoordinate() local pcallsign = pilot.CallSign - self:I(self.lid.."Checking for "..pcallsign) + self:T(self.lid.."Checking for "..pcallsign) if ppos then self.Contacts:ForEach( function (Contact) @@ -1884,7 +1907,7 @@ function AWACS:_CheckMerges() 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 - self:I(self.lid.."Merged") + self:T(self.lid.."Merged") self:_MergedCall(_id) contact.MergeCallDone = true end @@ -4759,6 +4782,7 @@ end function AWACS:_TACRangeCall(GID,Contact) self:T(self.lid.."_TACRangeCall") -- AIC: “Enforcer 11, single group, 30 miles.” + 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 @@ -4783,6 +4807,7 @@ end -- @return #AWACS self function AWACS:_MeldRangeCall(GID,Contact) self:T(self.lid.."_MeldRangeCall") + if not Contact then return self end -- AIC: “Heat 11, single group, BRAA 089/28, 32 thousand, hot, hostile, crow.” local pilotcallsign = self:_GetCallSign(nil,GID) local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup @@ -4811,6 +4836,7 @@ end -- @return #AWACS self function AWACS:_ThreatRangeCall(GID,Contact) self:T(self.lid.."_ThreatRangeCall") + if not Contact then return self end -- AIC: “Enforcer 11 12, east group, THREAT, BRAA 260/15, 29 thousand, hot, hostile, robin.” local pilotcallsign = self:_GetCallSign(nil,GID) local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup @@ -5735,7 +5761,7 @@ function AWACS:onafterCheckRadioQueue(From,Event,To) if self.clientset:CountAlive() == 0 then self:I(self.lid.."No player connected.") - self:__CheckRadioQueue(5) + self:__CheckRadioQueue(-5) return self end @@ -5783,7 +5809,12 @@ function AWACS:onafterCheckRadioQueue(From,Event,To) if self:Is("Running") then -- exit if stopped - self:__CheckRadioQueue(nextcall+1) + if self.PathToGoogleKey then + nextcall = nextcall + self.GoogleTTSPadding + else + nextcall = nextcall + self.WindowsTTSPadding + end + self:__CheckRadioQueue(-nextcall) end return self end From 9f287d0d7f8e2ff8777480ff30a71692fbd817b8 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sat, 4 Jun 2022 13:56:57 +0200 Subject: [PATCH 13/30] AWACS 0.1.27 * Added options for NoMissileCals and PlayerCapAssignment * Added documentation on options --- Moose Development/Moose/Ops/Awacs.lua | 51 ++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index 97bc4680d..42772b29c 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -108,6 +108,8 @@ do -- @field #number ReassignmentPause Wait this many seconds before re-assignment of a player -- @field #boolean NoGroupTags Set to true if you don't want group tags. -- @field #boolean SuppressScreenOutput Set to true to suppress all screen output. +-- @field #boolean NoMissileCalls Suppress missile callouts +-- @field #boolean PlayerCapAssigment Assign players to CAP tasks when they are logged on -- @field #number GoogleTTSPadding -- @field #number WindowsTTSPadding -- @extends Core.Fsm#FSM @@ -271,7 +273,7 @@ do -- Tac Distance = 45 -- Meld Distance = 35 -- Threat Distance = 25 --- Merge Distance = 3 +-- Merge Distance = 5 -- -- ## 8 Bespoke Player CallSigns -- @@ -303,8 +305,11 @@ do -- * @{#AWACS.SetAICAPDetails}() : Set AI CAP details. -- * @{#AWACS.SetEscort}() : Set number of escorting planes for AWACS. -- * @{#AWACS.AddCAPAirWing}() : Add an additional @{Ops.Airwing#AIRWING} for CAP flights. +-- * @{#AWACS.ZipLip}() : Do not show messages on screen, no extra calls for player guidance, use short callsigns, no group tags. -- --- Further options (set before starting your AWACS instance, but after `:New()`) +-- ## 9.1 Single Options +-- +-- Further single options (set before starting your AWACS instance, but after `:New()`) -- -- testawacs.PlayerGuidance = true -- allow missile warning call-outs. -- testawacs.NoGroupTags = false -- use group tags like Alpha, Bravo .. etc in call outs. @@ -313,11 +318,34 @@ do -- testawacs.MenuStrict = true -- Players need to check-in to see the menu; check-in still require to use the menu. -- testawacs.maxassigndistance = 100 -- Don't assign targets further out than this, in NM. -- testawacs.debug = false -- set to true to produce more log output. +-- testawacs.NoMissileCalls = true -- suppress missile callouts +-- testawacs.PlayerCapAssigment = true -- no task assignment for players +-- testawacs.invisible = false -- set AWACS to be invisible to hostiles +-- testawacs.immortal = false -- set AWACS to be immortal -- -- By default, the radio queue is checked every 10 secs. This is altered by the calculated length of the sentence to speak -- -- over the radio. Google and Windows speech speed is different. Use the below to fine-tune the setup in case of overlapping -- -- messages or too long pauses --- testawacs.GoogleTTSPadding = 1 --- testawacs.WindowsTTSPadding = 2.5 +-- testawacs.GoogleTTSPadding = 1 -- seconds +-- testawacs.WindowsTTSPadding = 2.5 -- seconds +-- +-- ## 9.2 Bespoke random voices for AI CAP (Google TTS only) +-- +-- Currently there are 10 voices defined which are randomly assigned to the AI CAP flights: +-- +-- Defaults are: +-- +-- testawacs.CapVoices = { +-- [1] = "de-DE-Wavenet-A", +-- [2] = "de-DE-Wavenet-B", +-- [3] = "fr-FR-Wavenet-A", +-- [4] = "fr-FR-Wavenet-B", +-- [5] = "en-GB-Wavenet-A", +-- [6] = "en-GB-Wavenet-B", +-- [7] = "en-GB-Wavenet-D", +-- [8] = "en-AU-Wavenet-B", +-- [9] = "en-US-Wavenet-J", +-- [10] = "en-US-Wavenet-H", +-- } -- -- ## 10 Discussion -- @@ -329,7 +357,7 @@ do -- @field #AWACS AWACS = { ClassName = "AWACS", -- #string - version = "beta 0.1.26", -- #string + version = "beta 0.1.27", -- #string lid = "", -- #string coalition = coalition.side.BLUE, -- #number coalitiontxt = "blue", -- #string @@ -405,8 +433,10 @@ AWACS = { ReassignmentPause = 180, NoGroupTags = false, SuppressScreenOutput = false, + NoMissileCalls = true, GoogleTTSPadding = 1, WindowsTTSPadding = 2.5, + PlayerCapAssigment = true, } --- @@ -667,10 +697,10 @@ AWACS.TaskStatus = { --@field #boolean FromAI ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- TODO-List 0.1.26 +-- TODO-List 0.1.27 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- --- DEBUG - WIP - Player tasking, VID +-- DONE - WIP - Player tasking, VID -- TODO - Localization (sensible?) -- TODO - (LOW) LotATC -- TODO - SW Optimization @@ -866,6 +896,8 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station self.DeclareRadius = 5 -- NM self.MenuStrict = true self.maxassigndistance = 100 --nm + self.NoMissileCalls = true + self.PlayerCapAssigment = true -- managed groups self.ManagedGrps = {} -- #table of #AWACS.ManagedGroup entries @@ -1169,6 +1201,7 @@ function AWACS:ZipLip() self.PlayerGuidance = false self.callsignshort = true self.NoGroupTags = true + self.NoMissileCalls = true return self end @@ -1247,7 +1280,7 @@ function AWACS:_EventHandler(EventData) end end - if Event.id == EVENTS.Shot and self.PlayerGuidance then + if Event.id == EVENTS.Shot and self.PlayerGuidance and not self.NoMissileCalls then if Event.IniCoalition ~= self.coalition then self:T("Shot from: " .. Event.IniGroupName) --self:T(UTILS.OneLineSerialize(Event)) @@ -5425,7 +5458,7 @@ function AWACS:onafterStatus(From, Event, To) local AI, Humans = self:_GetIdlePilots() -- assign Pilot if there are targets and available Pilots, prefer Humans to AI -- TODO - Implemented AI First, Humans laters - need to work out how to loop the targets to assign a pilot - if outcome and #Humans > 0 then + if outcome and #Humans > 0 and self.PlayerCapAssigment then -- add a task for AI self:_AssignPilotToTarget(Humans,targets) end From 0cb7415a4c1d2bc258f9d5be06bcb52fb70ba371 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sun, 5 Jun 2022 18:03:39 +0200 Subject: [PATCH 14/30] AWACS -- enforce EPLRS --- Moose Development/Moose/Ops/Awacs.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index 42772b29c..5fa27f67e 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -1710,6 +1710,7 @@ function AWACS:_StartSettings(FlightGroup,Mission) group:SetCommandInvisible(self.invisible) group:SetCommandImmortal(self.immortal) group:CommandSetCallsign(self.CallSign,self.CallSignNo,2) + group:CommandEPLRS(self.ModernEra,5) -- Non AWACS does not seem take AWACS CS in DCS Group self.AwacsFG = AwacsFG From d4999de214929fb8a1a715d0a8cff1efe353c646 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 7 Jun 2022 08:12:57 +0200 Subject: [PATCH 15/30] CSAR - added options to use Google TTS --- Moose Development/Moose/Ops/Awacs.lua | 3 +- Moose Development/Moose/Ops/CSAR.lua | 102 +++++++++++++++----------- 2 files changed, 61 insertions(+), 44 deletions(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index 5fa27f67e..cc9f70181 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -1200,7 +1200,7 @@ function AWACS:ZipLip() self:SuppressScreenMessages(true) self.PlayerGuidance = false self.callsignshort = true - self.NoGroupTags = true + --self.NoGroupTags = true self.NoMissileCalls = true return self end @@ -1532,6 +1532,7 @@ function AWACS:SetAwacsDetails(CallSign,CallSignNo,Angels,Speed,Heading,Leg) end --- [User] Add a radar GROUP object to the INTEL detection SET_GROUP +-- @param #AWACS self -- @param Wrapper.Group#GROUP Group The GROUP to be added. Can be passed as SET_GROUP. -- @return #AWACS self function AWACS:AddGroupToDetection(Group) diff --git a/Moose Development/Moose/Ops/CSAR.lua b/Moose Development/Moose/Ops/CSAR.lua index a213f5632..08bde94fc 100644 --- a/Moose Development/Moose/Ops/CSAR.lua +++ b/Moose Development/Moose/Ops/CSAR.lua @@ -30,7 +30,7 @@ -- @module Ops.CSAR -- @image OPS_CSAR.jpg --- Date: Feb 2022 +-- Date: June 2022 ------------------------------------------------------------------------- --- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM @@ -76,65 +76,69 @@ -- -- The following options are available (with their defaults). Only set the ones you want changed: -- --- self.allowDownedPilotCAcontrol = false -- Set to false if you don\'t want to allow control by Combined Arms. --- self.allowFARPRescue = true -- allows pilots to be rescued by landing at a FARP or Airbase. Else MASH only! --- self.FARPRescueDistance = 1000 -- you need to be this close to a FARP or Airport for the pilot to be rescued. --- self.autosmoke = false -- automatically smoke a downed pilot\'s location when a heli is near. --- self.autosmokedistance = 1000 -- distance for autosmoke --- self.coordtype = 1 -- Use Lat/Long DDM (0), Lat/Long DMS (1), MGRS (2), Bullseye imperial (3) or Bullseye metric (4) for coordinates. --- self.csarOncrash = false -- (WIP) If set to true, will generate a downed pilot when a plane crashes as well. --- self.enableForAI = false -- set to false to disable AI pilots from being rescued. --- self.pilotRuntoExtractPoint = true -- Downed pilot will run to the rescue helicopter up to self.extractDistance in meters. --- self.extractDistance = 500 -- Distance the downed pilot will start to run to the rescue helicopter. --- self.immortalcrew = true -- Set to true to make wounded crew immortal. --- self.invisiblecrew = false -- Set to true to make wounded crew insvisible. --- self.loadDistance = 75 -- configure distance for pilots to get into helicopter in meters. --- self.mashprefix = {"MASH"} -- prefixes of #GROUP objects used as MASHes. --- self.max_units = 6 -- max number of pilots that can be carried if #CSAR.AircraftType is undefined. --- self.messageTime = 15 -- Time to show messages for in seconds. Doubled for long messages. --- self.radioSound = "beacon.ogg" -- the name of the sound file to use for the pilots\' radio beacons. --- self.smokecolor = 4 -- Color of smokemarker, 0 is green, 1 is red, 2 is white, 3 is orange and 4 is blue. --- self.useprefix = true -- Requires CSAR helicopter #GROUP names to have the prefix(es) defined below. --- self.csarPrefix = { "helicargo", "MEDEVAC"} -- #GROUP name prefixes used for useprefix=true - DO NOT use # in helicopter names in the Mission Editor! --- self.verbose = 0 -- set to > 1 for stats output for debugging. +-- mycsar.allowDownedPilotCAcontrol = false -- Set to false if you don\'t want to allow control by Combined Arms. +-- mycsar.allowFARPRescue = true -- allows pilots to be rescued by landing at a FARP or Airbase. Else MASH only! +-- mycsar.FARPRescueDistance = 1000 -- you need to be this close to a FARP or Airport for the pilot to be rescued. +-- mycsar.autosmoke = false -- automatically smoke a downed pilot\'s location when a heli is near. +-- mycsar.autosmokedistance = 1000 -- distance for autosmoke +-- mycsar.coordtype = 1 -- Use Lat/Long DDM (0), Lat/Long DMS (1), MGRS (2), Bullseye imperial (3) or Bullseye metric (4) for coordinates. +-- mycsar.csarOncrash = false -- (WIP) If set to true, will generate a downed pilot when a plane crashes as well. +-- mycsar.enableForAI = false -- set to false to disable AI pilots from being rescued. +-- mycsar.pilotRuntoExtractPoint = true -- Downed pilot will run to the rescue helicopter up to mycsar.extractDistance in meters. +-- mycsar.extractDistance = 500 -- Distance the downed pilot will start to run to the rescue helicopter. +-- mycsar.immortalcrew = true -- Set to true to make wounded crew immortal. +-- mycsar.invisiblecrew = false -- Set to true to make wounded crew insvisible. +-- mycsar.loadDistance = 75 -- configure distance for pilots to get into helicopter in meters. +-- mycsar.mashprefix = {"MASH"} -- prefixes of #GROUP objects used as MASHes. +-- mycsar.max_units = 6 -- max number of pilots that can be carried if #CSAR.AircraftType is undefined. +-- mycsar.messageTime = 15 -- Time to show messages for in seconds. Doubled for long messages. +-- mycsar.radioSound = "beacon.ogg" -- the name of the sound file to use for the pilots\' radio beacons. +-- mycsar.smokecolor = 4 -- Color of smokemarker, 0 is green, 1 is red, 2 is white, 3 is orange and 4 is blue. +-- mycsar.useprefix = true -- Requires CSAR helicopter #GROUP names to have the prefix(es) defined below. +-- mycsar.csarPrefix = { "helicargo", "MEDEVAC"} -- #GROUP name prefixes used for useprefix=true - DO NOT use # in helicopter names in the Mission Editor! +-- mycsar.verbose = 0 -- set to > 1 for stats output for debugging. -- -- (added 0.1.4) limit amount of downed pilots spawned by **ejection** events --- self.limitmaxdownedpilots = true --- self.maxdownedpilots = 10 +-- mycsar.limitmaxdownedpilots = true +-- mycsar.maxdownedpilots = 10 -- -- (added 0.1.8) - allow to set far/near distance for approach and optionally pilot must open doors --- self.approachdist_far = 5000 -- switch do 10 sec interval approach mode, meters --- self.approachdist_near = 3000 -- switch to 5 sec interval approach mode, meters --- self.pilotmustopendoors = false -- switch to true to enable check of open doors +-- mycsar.approachdist_far = 5000 -- switch do 10 sec interval approach mode, meters +-- mycsar.approachdist_near = 3000 -- switch to 5 sec interval approach mode, meters +-- mycsar.pilotmustopendoors = false -- switch to true to enable check of open doors -- -- (added 0.1.9) --- self.suppressmessages = false -- switch off all messaging if you want to do your own +-- mycsar.suppressmessages = false -- switch off all messaging if you want to do your own -- -- (added 0.1.11) --- self.rescuehoverheight = 20 -- max height for a hovering rescue in meters --- self.rescuehoverdistance = 10 -- max distance for a hovering rescue in meters +-- mycsar.rescuehoverheight = 20 -- max height for a hovering rescue in meters +-- mycsar.rescuehoverdistance = 10 -- max distance for a hovering rescue in meters -- -- (added 0.1.12) -- -- Country codes for spawned pilots --- self.countryblue= country.id.USA --- self.countryred = country.id.RUSSIA --- self.countryneutral = country.id.UN_PEACEKEEPERS +-- mycsar.countryblue= country.id.USA +-- mycsar.countryred = country.id.RUSSIA +-- mycsar.countryneutral = country.id.UN_PEACEKEEPERS -- -- ## 2.1 Experimental Features -- -- WARNING - Here\'ll be dragons! -- DANGER - For this to work you need to de-sanitize your mission environment (all three entries) in \Scripts\MissionScripting.lua -- Needs SRS => 1.9.6 to work (works on the **server** side of SRS) --- self.useSRS = false -- Set true to use FF\'s SRS integration --- self.SRSPath = "E:\\Progra~1\\DCS-SimpleRadio-Standalone\\" -- adjust your own path in your SRS installation -- server(!) --- self.SRSchannel = 300 -- radio channel --- self.SRSModulation = radio.modulation.AM -- modulation --- self.SRSport = 5002 -- and SRS port +-- mycsar.useSRS = false -- Set true to use FF\'s SRS integration +-- mycsar.SRSPath = "C:\\Progra~1\\DCS-SimpleRadio-Standalone\\" -- adjust your own path in your SRS installation -- server(!) +-- mycsar.SRSchannel = 300 -- radio channel +-- mycsar.SRSModulation = radio.modulation.AM -- modulation +-- mycsar.SRSport = 5002 -- and SRS Server port +-- mycsar.SRSCulture = "en-GB" -- SRS voice culture +-- mycsar.SRSVoice = nil -- SRS voice, relevant for Google TTS +-- mycsar.SRSGPathToCredentials = nil -- Path to your Google credentials json file, set this if you want to use Google TTS +-- mycsar.SRSVolume = 1 -- Volume, between 0 and 1 -- -- --- self.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection --shagrat --- self.wetfeettemplate = "man in floating thingy" -- if you use a mod to have a pilot in a rescue float, put the template name in here for wet feet spawns. Note: in conjunction with csarUsePara this might create dual ejected pilots in edge cases. +-- mycsar.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection --shagrat +-- mycsar.wetfeettemplate = "man in floating thingy" -- if you use a mod to have a pilot in a rescue float, put the template name in here for wet feet spawns. Note: in conjunction with csarUsePara this might create dual ejected pilots in edge cases. -- -- ## 3. Results -- -- Number of successful landings with save pilots and aggregated number of saved pilots is stored in these variables in the object: -- --- self.rescues -- number of successful landings *with* saved pilots --- self.rescuedpilots -- aggregated number of pilots rescued from the field (of *all* players) +-- mycsar.rescues -- number of successful landings *with* saved pilots +-- mycsar.rescuedpilots -- aggregated number of pilots rescued from the field (of *all* players) -- -- ## 4. Events -- @@ -260,7 +264,7 @@ CSAR.AircraftType["AH-64D_BLK_II"] = 2 --- CSAR class version. -- @field #string version -CSAR.version="1.0.4e" +CSAR.version="1.0.5" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- ToDo list @@ -415,6 +419,10 @@ function CSAR:New(Coalition, Template, Alias) self.SRSchannel = 300 -- radio channel self.SRSModulation = radio.modulation.AM -- modulation self.SRSport = 5002 -- port + self.SRSCulture = "en-GB" + self.SRSVoice = nil + self.SRSGPathToCredentials = nil + self.SRSVolume = 1 ------------------------ --- Pseudo Functions --- @@ -1526,6 +1534,14 @@ function CSAR:_DisplayMessageToSAR(_unit, _text, _time, _clear, _speak, _overrid local channel = self.SRSchannel local msrs = MSRS:New(path,channel,modulation) msrs:SetPort(self.SRSport) + msrs:SetLabel("CSAR") + msrs:SetCulture(self.SRSCulture) + msrs:SetCoalition(self.coalition) + msrs:SetVoice(self.SRSVoice) + if self.SRSGPathToCredentials then + msrs:SetGoogle(self.SRSGPathToCredentials) + end + msrs:SetVolume(self.SRSVolume) msrs:PlaySoundText(srstext, 2) end return self From 30dc3386368dd6df257d22172d1e9191d323dc4c Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 7 Jun 2022 08:56:25 +0200 Subject: [PATCH 16/30] CSAR - added a couple of more lines to go out via TTS --- Moose Development/Moose/Ops/CSAR.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Moose Development/Moose/Ops/CSAR.lua b/Moose Development/Moose/Ops/CSAR.lua index 08bde94fc..e1c719363 100644 --- a/Moose Development/Moose/Ops/CSAR.lua +++ b/Moose Development/Moose/Ops/CSAR.lua @@ -1248,7 +1248,7 @@ function CSAR:_PickupUnit(_heliUnit, _pilotName, _woundedGroup, _woundedGroupNam _maxUnits = self.max_units end if _unitsInHelicopter + 1 > _maxUnits then - self:_DisplayMessageToSAR(_heliUnit, string.format("%s, %s. We\'re already crammed with %d guys! Sorry!", _pilotName, _heliName, _unitsInHelicopter, _unitsInHelicopter), self.messageTime) + self:_DisplayMessageToSAR(_heliUnit, string.format("%s, %s. We\'re already crammed with %d guys! Sorry!", _pilotName, _heliName, _unitsInHelicopter, _unitsInHelicopter), self.messageTime,false,false,true) return true end @@ -1346,7 +1346,7 @@ function CSAR:_CheckCloseWoundedGroup(_distance, _heliUnit, _heliName, _woundedG --if _time <= 0 or _distance < self.loadDistance then if _distance < self.loadDistance + 5 or _distance <= 13 then if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(_heliName) then - self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me in!", self.messageTime, true) + self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me in!", self.messageTime, true, true) return true else self.landedStatus[_lookupKeyHeli] = nil @@ -1358,7 +1358,7 @@ function CSAR:_CheckCloseWoundedGroup(_distance, _heliUnit, _heliName, _woundedG else if (_distance < self.loadDistance) then if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(_heliName) then - self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me in!", self.messageTime, true) + self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me in!", self.messageTime, true, true) return true else self:_PickupUnit(_heliUnit, _pilotName, _woundedGroup, _woundedGroupName) @@ -1400,7 +1400,7 @@ function CSAR:_CheckCloseWoundedGroup(_distance, _heliUnit, _heliName, _woundedG self:_DisplayMessageToSAR(_heliUnit, "Hovering above " .. _pilotName .. ". \n\nHold hover for " .. _time .. " seconds to winch them up. \n\nIf the countdown stops you\'re too far away!", self.messageTime, true) else if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(_heliName) then - self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me in!", self.messageTime, true) + self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me in!", self.messageTime, true, true) return true else self.hoverStatus[_lookupKeyHeli] = nil @@ -1459,7 +1459,7 @@ function CSAR:_ScheduledSARFlight(heliname,groupname, isairport) if ( _dist < self.FARPRescueDistance or isairport ) and _heliUnit:InAir() == false then if self.pilotmustopendoors and self:_IsLoadingDoorOpen(heliname) == false then - self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me out!", self.messageTime, true) + self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me out!", self.messageTime, true, true) else self:_RescuePilots(_heliUnit) return From 01e9e8364114ee82dc0f5560832be14ddcb513a5 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 7 Jun 2022 11:30:20 +0200 Subject: [PATCH 17/30] AWACS - PlayerGuidance makes picture calls refer to asking player BRA, delete contact engagement label on checking out --- Moose Development/Moose/Ops/Awacs.lua | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index cc9f70181..bd36ca4c4 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -357,7 +357,7 @@ do -- @field #AWACS AWACS = { ClassName = "AWACS", -- #string - version = "beta 0.1.27", -- #string + version = "beta 0.1.28", -- #string lid = "", -- #string coalition = coalition.side.BLUE, -- #number coalitiontxt = "blue", -- #string @@ -697,7 +697,7 @@ AWACS.TaskStatus = { --@field #boolean FromAI ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- TODO-List 0.1.27 +-- TODO-List 0.1.28 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- -- DONE - WIP - Player tasking, VID @@ -2259,15 +2259,14 @@ function AWACS:_CreatePicture(AO,Callsign,GID,MaxEntries,IsGeneral) textScreen = contact.TargetGroupNaming.." group," end - --if IsGeneral then + if IsGeneral or not self.PlayerGuidance then refBRAA=self:_ToStringBULLS(coordinate) refBRAATTS = self:_ToStringBULLS(coordinate, false, true) local alt = contact.Contact.group:GetAltitude() or 8000 alt = UTILS.Round(UTILS.MetersToFeet(alt)/1000,0) -- Alpha Group. Bulls eye 0 2 1, 16 miles, 25 thousand. text = text .. " "..refBRAATTS.." miles, "..alt.." thousand." -- Alpha Group. Bulls eye 0 2 1, 16 miles, 25 thousand. - textScreen = textScreen .. " "..refBRAA.." miles, "..alt.." thousand." -- Alpha Group, Bullseye 021, 16 miles, 25 thousand, - --[[ + textScreen = textScreen .. " "..refBRAA.." miles, "..alt.." thousand." -- Alpha Group, Bullseye 021, 16 miles, 25 thousand, else -- pilot reference refBRAA = coordinate:ToStringBRAANATO(groupcoord,true,true) @@ -2284,7 +2283,6 @@ function AWACS:_CreatePicture(AO,Callsign,GID,MaxEntries,IsGeneral) text = text .. " "..refBRAATTS textScreen = textScreen .." "..refBRAA end - --]] -- Aspect local aspect = "" @@ -3143,6 +3141,7 @@ function AWACS:_CheckOut(Group,GID,dead) -- delete open tasks if managedgroup.CurrentTask and managedgroup.CurrentTask > 0 then self.ManagedTasks:PullByID(managedgroup.CurrentTask ) + self:_UpdateContactEngagementTag(managedgroup.ContactCID,"",false,false) end self.ManagedGrps[GID] = nil self:__CheckedOut(1,GID,Stack,Angels) From 6636e89a0bdd2d33a0e19076cc713f7705b90a37 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Wed, 8 Jun 2022 20:24:31 +0200 Subject: [PATCH 18/30] AIRBASE added South Atlantic --- Moose Development/Moose/Wrapper/Airbase.lua | 22 +++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua index 04b474db9..edde1fdc2 100644 --- a/Moose Development/Moose/Wrapper/Airbase.lua +++ b/Moose Development/Moose/Wrapper/Airbase.lua @@ -487,6 +487,28 @@ AIRBASE.MarianaIslands={ ["Olf_Orote"]="Olf Orote", } +--- Airbases of the South Atlantic map: +-- +-- * AIRBASE.SouthAtlantic.Port_Stanley +-- * AIRBASE.SouthAtlantic.Mount_Pleasant +-- * AIRBASE.SouthAtlantic.San_Carlos_FOB +-- * AIRBASE.SouthAtlantic.Rio_Grande +-- * AIRBASE.SouthAtlantic.Rio_Gallegos +-- * AIRBASE.SouthAtlantic.Ushuaia +-- * AIRBASE.SouthAtlantic.Ushuaia_Helo_Port +-- * AIRBASE.SouthAtlantic.Punta_Arenas +-- +--@field MarianaIslands +AIRBASE.SouthAtlantic={ + ["Port_Stanley"]="Port Stanley", + ["Mount_Pleasant"]="Mount Pleasant", + ["San_Carlos_FOB"]="San Carlos FOB", + ["Rio_Grande"]="Rio Grande", + ["Rio_Gallegos"]="Rio Gallegos", + ["Ushuaia"]="Ushuaia", + ["Ushuaia_Helo_Port"]="Ushuaia Helo Port", + ["Punta_Arenas"]="Punta Arenas", +} --- AIRBASE.ParkingSpot ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy". -- @type AIRBASE.ParkingSpot From 96c6c372fdf09a4b9bfb830166a178759377b1a2 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 9 Jun 2022 10:56:33 +0200 Subject: [PATCH 19/30] Added documentation for CTLD_HERCULES --- Moose Development/Moose/Ops/CTLD.lua | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index 4a7a5e66c..5176f24bc 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -4792,10 +4792,11 @@ end end -- end do do ---- Hercules Cargo Drop Events by Anubis Yinepu +--- **Hercules Cargo AIR Drop Events** by Anubis Yinepu -- Moose CTLD OO refactoring by Applevangelist -- --- This script will only work for the Herculus mod by Anubis +-- This script will only work for the Herculus mod by Anubis, and only for **Air Dropping** cargo from the Hercules. +-- Use the standard Moose CTLD if you want to unload on the ground. -- Payloads carried by pylons 11, 12 and 13 need to be declared in the Herculus_Loadout.lua file -- Except for Ammo pallets, this script will spawn whatever payload gets launched from pylons 11, 12 and 13 -- Pylons 11, 12 and 13 are moveable within the Herculus cargobay area @@ -4883,7 +4884,7 @@ CTLD_HERCULES.Types = { ["ART GVOZDIKA [34720lb]"] = {['name'] = "SAU Gvozdika", ['container'] = false}, ["APC MTLB Air [26400lb]"] = {['name'] = "MTLB", ['container'] = true}, ["APC MTLB Skid [26290lb]"] = {['name'] = "MTLB", ['container'] = false}, - ["Generic Crate [20000lb]"] = {['name'] = "Hercules_Container_Parachute", ['container'] = true} --nothing generic in Moose CTLD + --["Generic Crate [20000lb]"] = {['name'] = "Hercules_Container_Parachute", ['container'] = true} --nothing generic in Moose CTLD } --- Cargo Object @@ -4922,6 +4923,14 @@ CTLD_HERCULES.Types = { -- ...Checking template for Transport Tigr Air [15900lb] (Tigr_233036) ... OK) -- -- Expected template names are the ones in the rounded brackets. +-- +-- HINTS +-- +-- The script works on the EVENTS.Shot trigger, which is used by the mod when you **drop cargo from the Hercules while flying**. Unloading on the ground does +-- not achieve anything here. If you just want to unload on the ground, use the normal Moose CTLD. +-- There are two ways of airdropping: +-- 1) Very low and very slow (>5m and <10m AGL) - here you can drop stuff which has "Skid" at the end of the cargo name (loaded via F8 Ground Crew menu) +-- 2) Higher up and slow (>100m AGL) - here you can drop paratroopers and cargo which has "Air" at the end of the cargo name (loaded via F8 Ground Crew menu) function CTLD_HERCULES:New(Coalition, Alias, CtldObject) -- Inherit everything from FSM class. local self=BASE:Inherit(self, FSM:New()) -- #CTLD_HERCULES From 913d5a532da16125ed0e52068abbbcafe862564f Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 9 Jun 2022 11:46:17 +0200 Subject: [PATCH 20/30] CTLD - further documentation --- Moose Development/Moose/Ops/CTLD.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index 5176f24bc..32f7ed106 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -4909,7 +4909,8 @@ CTLD_HERCULES.Types = { -- @return #CTLD_HERCULES self -- @usage -- Integrate to your CTLD instance like so, where `my_ctld` is a previously created CTLD instance: --- +-- +-- my_ctld.enableHercules = false -- avoid dual loading via CTLD F10 and F8 ground crew -- local herccargo = CTLD_HERCULES:New("blue", "Hercules Test", my_ctld) -- -- You also need: From a2b3190b1dd41d8c285ccad2d0ecf631563f1d5c Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 9 Jun 2022 12:12:45 +0200 Subject: [PATCH 21/30] More docu --- Moose Development/Moose/Ops/Awacs.lua | 15 +++------ Moose Development/Moose/Ops/CTLD.lua | 48 +++++++++++++++++---------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index bd36ca4c4..890196d00 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -1,16 +1,9 @@ --- **Ops** - AWACS -- --- ## Main Features: --- --- * WIP (beta) --- * AWACS replacement for the in-game AWACS --- * Will control a fighter engagement zone and assign tasks to AI and human CAP flights --- * Concentrates on threat-based call outs --- * Callouts referenced from: --- ** References from ARN33396 ATP 3-52.4 (Sep 2021) (Combined Forces) --- ** References from CNATRA P-877 (Rev 12-20) (NAVY) --- * Many additional events that the mission designer can hook into --- +-- === +-- +-- **AWACS** - MOOSE AI AWACS Operations using text-to-speech. +-- -- === -- -- ## Example Missions: diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index 32f7ed106..522dd1efe 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -722,7 +722,8 @@ do -- ["Mi-24P"] = {type="Mi-24P", crates=true, troops=true, cratelimit = 2, trooplimit = 8, length = 18, cargoweightlimit = 700}, -- ["Mi-24V"] = {type="Mi-24V", crates=true, troops=true, cratelimit = 2, trooplimit = 8, length = 18, cargoweightlimit = 700}, -- ["Hercules"] = {type="Hercules", crates=true, troops=true, cratelimit = 7, trooplimit = 64, length = 25, cargoweightlimit = 19000}, --- ["UH-60L"] = {type="UH-60L", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16, cargoweightlimit = 3500}, +-- ["UH-60L"] = {type="UH-60L", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16, cargoweightlimit = 3500}, +-- ["AH-64D_BLK_II"] = {type="AH-64D_BLK_II", crates=false, troops=true, cratelimit = 0, trooplimit = 2, length = 17, cargoweightlimit = 200}, -- -- ### 2.1.2 Activate and deactivate zones -- @@ -870,12 +871,13 @@ do -- -- ## 5. Support for Hercules mod by Anubis -- --- Basic support for the Hercules mod By Anubis has been build into CTLD - that is you can load/drop/build the same objects as the helicopters. --- To also cover objects and troops which can be loaded from the groud crew Rearm/Refuel menu, you need to use @{#CTLD_HERCULES.New}() and link --- this object to your CTLD setup. In this case, do **not** use the `Hercules_Cargo.lua` or `Hercules_Cargo_CTLD.lua` which are part of the mod +-- Basic support for the Hercules mod By Anubis has been build into CTLD - that is you can load/drop/build the same way and for the same objects as +-- the helicopters (main method). +-- To cover objects and troops which can be loaded from the groud crew Rearm/Refuel menu (F8), you need to use @{#CTLD_HERCULES.New}() and link +-- this object to your CTLD setup (alternative method). In this case, do **not** use the `Hercules_Cargo.lua` or `Hercules_Cargo_CTLD.lua` which are part of the mod -- in your mission! -- --- ### 5.1 Create an own CTLD instance and allow the usage of the Hercules mod: +-- ### 5.1 Create an own CTLD instance and allow the usage of the Hercules mod (main method) -- -- local my_ctld = CTLD:New(coalition.side.BLUE,{"Helicargo", "Hercules"},"Lufttransportbrigade I") -- @@ -893,26 +895,38 @@ do -- -- my_ctld.useprefix = true -- this is true by default and MUST BE ON. -- --- ### 5.2 Integrate Hercules ground crew loadable objects --- --- Add ground crew loadable objects to your CTLD instance like so, where `my_ctld` is the previously created CTLD instance: +-- ### 5.2 Integrate Hercules ground crew (F8 Menu) loadable objects (alternative method) -- +-- Integrate to your CTLD instance like so, where `my_ctld` is a previously created CTLD instance: +-- +-- my_ctld.enableHercules = false -- avoid dual loading via CTLD F10 and F8 ground crew -- local herccargo = CTLD_HERCULES:New("blue", "Hercules Test", my_ctld) -- --- You also need: --- --- * A template called "Infantry" for 10 Paratroopers (as set via herccargo.infantrytemplate). --- * Depending on what you are loading with the help of the ground crew, there are 42 more templates for the various vehicles that are loadable. +-- You also need: +-- +-- * A template called "Infantry" for 10 Paratroopers (as set via herccargo.infantrytemplate). +-- * Depending on what you are loading with the help of the ground crew, there are 42 more templates for the various vehicles that are loadable. -- -- There's a **quick check output in the `dcs.log`** which tells you what's there and what not. --- E.g.: --- ...Checking template for APC BTR-82A Air [24998lb] (BTR-82A) ... MISSING) --- ...Checking template for ART 2S9 NONA Skid [19030lb] (SAU 2-C9) ... MISSING) --- ...Checking template for EWR SBORKA Air [21624lb] (Dog Ear radar) ... MISSING) --- ...Checking template for Transport Tigr Air [15900lb] (Tigr_233036) ... OK) +-- E.g.: +-- +-- ...Checking template for APC BTR-82A Air [24998lb] (BTR-82A) ... MISSING) +-- ...Checking template for ART 2S9 NONA Skid [19030lb] (SAU 2-C9) ... MISSING) +-- ...Checking template for EWR SBORKA Air [21624lb] (Dog Ear radar) ... MISSING) +-- ...Checking template for Transport Tigr Air [15900lb] (Tigr_233036) ... OK) -- -- Expected template names are the ones in the rounded brackets. -- +-- ### 5.2.1 Hints +-- +-- The script works on the EVENTS.Shot trigger, which is used by the mod when you **drop cargo from the Hercules while flying**. Unloading on the ground does +-- not achieve anything here. If you just want to unload on the ground, use the normal Moose CTLD (see 5.1). +-- +-- There are two ways of airdropping: +-- +-- 1) Very low and very slow (>5m and <10m AGL) - here you can drop stuff which has "Skid" at the end of the cargo name (loaded via F8 Ground Crew menu) +-- 2) Higher up and slow (>100m AGL) - here you can drop paratroopers and cargo which has "Air" at the end of the cargo name (loaded via F8 Ground Crew menu) +-- -- Standard transport capabilities as per the real Hercules are: -- -- ["Hercules"] = {type="Hercules", crates=true, troops=true, cratelimit = 7, trooplimit = 64}, -- 19t cargo, 64 paratroopers From f48c71f30cc2f0e394cb9c85b34566e8cd5028ae Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 10 Jun 2022 11:56:19 +0200 Subject: [PATCH 22/30] AWACS - Added option to use marker to create, move and delete a player station --- Moose Development/Moose/Ops/Awacs.lua | 177 ++++++++++++++++++++++++-- 1 file changed, 169 insertions(+), 8 deletions(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index 890196d00..a9cf20fd2 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -105,6 +105,8 @@ do -- @field #boolean PlayerCapAssigment Assign players to CAP tasks when they are logged on -- @field #number GoogleTTSPadding -- @field #number WindowsTTSPadding +-- @field #boolean AllowMarkers +-- @field #string PlayerStationName -- @extends Core.Fsm#FSM @@ -339,8 +341,20 @@ do -- [9] = "en-US-Wavenet-J", -- [10] = "en-US-Wavenet-H", -- } +-- +-- ## 10 Using F10 map markers to create new player station points +-- +-- You can use F10 map markers to create new station points for human CAP flights. The latest created station will take priority for (new) station assignments for humans. +-- Enable this option with +-- +-- testawacs.AllowMarkers = true -- --- ## 10 Discussion +-- Set a marker on the map and add the following text to create a station: "AWACS Station London" - "AWACS Station" are the necessary keywords, "London" +-- in this example will be the name of the new station point. The user marker can then be deleted, an info marker point at the same place will remain. +-- You can delete a player station point the same way: "AWACS Delete London"; note this will only work if currently there are no assigned flights on this station. +-- Lastly, you can move the station around with keyword "Move": "AWACS Move London". +-- +-- ## 11 Discussion -- -- If you have questions or suggestions, please visit the [MOOSE Discord](https://discord.gg/AeYAkHP) #ops-awacs channel. -- @@ -350,7 +364,7 @@ do -- @field #AWACS AWACS = { ClassName = "AWACS", -- #string - version = "beta 0.1.28", -- #string + version = "beta 0.1.29", -- #string lid = "", -- #string coalition = coalition.side.BLUE, -- #number coalitiontxt = "blue", -- #string @@ -430,6 +444,8 @@ AWACS = { GoogleTTSPadding = 1, WindowsTTSPadding = 2.5, PlayerCapAssigment = true, + AllowMarkers = false, + PlayerStationName = nil, } --- @@ -690,7 +706,7 @@ AWACS.TaskStatus = { --@field #boolean FromAI ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- TODO-List 0.1.28 +-- TODO-List 0.1.29 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- -- DONE - WIP - Player tasking, VID @@ -3020,7 +3036,12 @@ function AWACS:_CheckIn(Group) textTTS = string.format("%s. %s. Alpha Check. %s",managedgroup.CallSign,self.callsigntxt,alphacheckbullstts) self:__CheckedIn(1,managedgroup.GID) - self:__AssignAnchor(5,managedgroup.GID) + + if self.PlayerStationName then + self:__AssignAnchor(5,managedgroup.GID,true,self.PlayerStationName) + else + self:__AssignAnchor(5,managedgroup.GID) + end elseif self.AwacsFG then text = string.format("%s. %s. Negative. You are already checked in.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt) @@ -3308,10 +3329,101 @@ function AWACS:_SetClientMenus() return self end +--- [Internal] AWACS Delete a new Anchor Stack from a Marker - only works if no assignments are on the station +-- @param #AWACS self +-- @return #AWACS self +function AWACS:_DeleteAnchorStackFromMarker(Name,Coord) + self:I(self.lid.."_DeleteAnchorStackFromMarker") + if self.AnchorStacks:HasUniqueID(Name) and self.PlayerStationName == Name then + local stack = self.AnchorStacks:ReadByID(Name) -- #AWACS.AnchorData + local marker = stack.AnchorMarker + if stack.AnchorAssignedID:Count() == 0 then + marker:Remove() + if self.debug then + stack.StationZone:UndrawZone() + end + self.AnchorStacks:PullByID(Name) + self.PlayerStationName = nil + else + if self.debug then + self:I(self.lid.."**** Cannot delete station, there are CAPs assigned!") + local text = marker:GetText() + marker:TextUpdate(text.."\nMarked for deletion") + end + end + end + return self +end + +--- [Internal] AWACS Move a new Anchor Stack from a Marker +-- @param #AWACS self +-- @return #AWACS self +function AWACS:_MoveAnchorStackFromMarker(Name,Coord) + self:I(self.lid.."_MoveAnchorStackFromMarker") + if self.AnchorStacks:HasUniqueID(Name) and self.PlayerStationName == Name then + local station = self.AnchorStacks:PullByID(Name) -- #AWACS.AnchorData + local stationtag = string.format("Station: %s\nCoordinate: %s",Name,Coord:ToStringLLDDM()) + local marker = station.AnchorMarker + local zone = station.StationZone + if self.debug then + zone:UndrawZone() + end + local radius = self.StationZone:GetRadius() + if radius < 10000 then radius = 10000 end + station.StationZone = ZONE_RADIUS:New(Name, Coord:GetVec2(), radius) + marker:UpdateCoordinate(Coord) + marker:UpdateText(stationtag) + station.AnchorMarker = marker + if self.debug then + station.StationZone:DrawZone(-1,{0,0,1},1,{0,0,1},0.2,5,true) + end + self.AnchorStacks:Push(station,Name) + end + return self +end + +--- [Internal] AWACS Create a new Anchor Stack from a Marker - this then is the preferred station for players +-- @param #AWACS self +-- @return #AWACS self +function AWACS:_CreateAnchorStackFromMarker(Name,Coord) + self:I(self.lid.."_CreateAnchorStackFromMarker") + local AnchorStackOne = {} -- #AWACS.AnchorData + AnchorStackOne.AnchorBaseAngels = self.AnchorBaseAngels + AnchorStackOne.Anchors = FIFO:New() -- Utilities.FiFo#FIFO + AnchorStackOne.AnchorAssignedID = FIFO:New() -- Utilities.FiFo#FIFO + + local newname = Name + + for i=1,self.AnchorMaxStacks do + AnchorStackOne.Anchors:Push((i-1)*self.AnchorStackDistance+self.AnchorBaseAngels) + end + local radius = self.StationZone:GetRadius() + if radius < 10000 then radius = 10000 end + AnchorStackOne.StationZone = ZONE_RADIUS:New(newname, Coord:GetVec2(), radius) + AnchorStackOne.StationZoneCoordinate = Coord + AnchorStackOne.StationZoneCoordinateText = Coord:ToStringLLDDM() + AnchorStackOne.StationName = newname + + --push to AnchorStacks + if self.debug then + AnchorStackOne.StationZone:DrawZone(-1,{0,0,1},1,{0,0,1},0.2,5,true) + local stationtag = string.format("Station: %s\nCoordinate: %s",newname,self.StationZone:GetCoordinate():ToStringLLDDM()) + AnchorStackOne.AnchorMarker=MARKER:New(AnchorStackOne.StationZone:GetCoordinate(),stationtag):ToAll() + else + local stationtag = string.format("Station: %s\nCoordinate: %s",newname,self.StationZone:GetCoordinate():ToStringLLDDM()) + AnchorStackOne.AnchorMarker=MARKER:New(AnchorStackOne.StationZone:GetCoordinate(),stationtag):ToAll() + end + + self.AnchorStacks:Push(AnchorStackOne,newname) + self.PlayerStationName = newname + + return self +end + --- [Internal] AWACS Create a new Anchor Stack -- @param #AWACS self -- @return #boolean success --- @return #nunber AnchorStackNo +-- @return #number AnchorStackNo function AWACS:_CreateAnchorStack() self:T(self.lid.."_CreateAnchorStack") local stackscreated = self.AnchorStacks:GetSize() @@ -3354,14 +3466,14 @@ function AWACS:_CreateAnchorStack() local anchorbasecoord = self.OpsZone:GetCoordinate() -- Core.Point#COORDINATE -- OpsZone can be Polygon, so use distance to StationZone as radius local anchorradius = anchorbasecoord:Get2DDistance(self.StationZone:GetCoordinate()) - --local anchorradius = self.OpsZone:GetRadius() -- #number - --anchorradius = anchorradius + self.StationZone:GetRadius() local angel = self.StationZone:GetCoordinate():GetAngleDegrees(self.OpsZone:GetVec3()) self:T("Angel Radians= " .. angel) local turn = math.fmod(self.AnchorTurn*stackscreated,360) -- #number if self.AnchorTurn < 0 then turn = -turn end local newanchorbasecoord = anchorbasecoord:Translate(anchorradius,turn+angel) -- Core.Point#COORDINATE - AnchorStackOne.StationZone = ZONE_RADIUS:New(newname, newanchorbasecoord:GetVec2(), self.StationZone:GetRadius()) + local radius = self.StationZone:GetRadius() + if radius < 10000 then radius = 10000 end + AnchorStackOne.StationZone = ZONE_RADIUS:New(newname, newanchorbasecoord:GetVec2(), radius) AnchorStackOne.StationZoneCoordinate = newanchorbasecoord AnchorStackOne.StationZoneCoordinateText = newanchorbasecoord:ToStringLLDDM() AnchorStackOne.StationName = newname @@ -5173,6 +5285,55 @@ function AWACS:onafterStart(From, Event, To) self.ZoneSet = ZoneSet self.RejectZoneSet = RejectZoneSet + if self.AllowMarkers then + -- Add MarkerOps + + local MarkerOps = MARKEROPS_BASE:New("AWACS",{"Station","Delete","Move"}) + + local function Handler(Keywords,Coord,Text) + self:I(Text) + for _,_word in pairs (Keywords) do + if string.lower(_word) == "station" then + -- get the station name from the text field + local Name = string.match(Text," ([%a]+)$") + self:_CreateAnchorStackFromMarker(Name,Coord) + break + elseif string.lower(_word) == "delete" then + -- get the station name from the text field + local Name = string.match(Text," ([%a]+)$") + self:_DeleteAnchorStackFromMarker(Name,Coord) + break + elseif string.lower(_word) == "move" then + -- get the station name from the text field + local Name = string.match(Text," ([%a]+)$") + self:_MoveAnchorStackFromMarker(Name,Coord) + break + end + end + end + + -- Event functions + function MarkerOps:OnAfterMarkAdded(From,Event,To,Text,Keywords,Coord) + --local m = MESSAGE:New(string.format("AWACS %s Mark Added.", self.Tag),10,"Info",true):ToAllIf(self.debug) + BASE:I(string.format("%s Mark Added.", self.Tag)) + Handler(Keywords,Coord,Text) + end + + function MarkerOps:OnAfterMarkChanged(From,Event,To,Text,Keywords,Coord) + BASE:I(string.format("%s Mark Changed.", self.Tag)) + --local m = MESSAGE:New(string.format("AWACS %s Mark Changed.", self.Tag),10,"Info",true):ToAllIf(self.debug) + Handler(Keywords,Coord,Text) + end + + function MarkerOps:OnAfterMarkDeleted(From,Event,To) + BASE:I(string.format("%s Mark Deleted.", self.Tag)) + --local m = MESSAGE:New(string.format("AWACS %s Mark Deleted.", self.Tag),10,"Info",true):ToAllIf(self.debug) + end + + self.MarkerOps = MarkerOps + + end + self:__Status(-30) return self end From d01360ca19253a74718bca7d3756a61f93606545 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sun, 12 Jun 2022 12:47:10 +0200 Subject: [PATCH 23/30] CSAR - Put wounded group back into status green, so they run to the chopper --- Moose Development/Moose/Ops/CSAR.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Moose Development/Moose/Ops/CSAR.lua b/Moose Development/Moose/Ops/CSAR.lua index e1c719363..e33248b31 100644 --- a/Moose Development/Moose/Ops/CSAR.lua +++ b/Moose Development/Moose/Ops/CSAR.lua @@ -1336,7 +1336,8 @@ function CSAR:_CheckCloseWoundedGroup(_distance, _heliUnit, _heliName, _woundedG local _time = self.landedStatus[_lookupKeyHeli] if _time == nil then self.landedStatus[_lookupKeyHeli] = math.floor( (_distance - self.loadDistance) / 3.6 ) - _time = self.landedStatus[_lookupKeyHeli] + _time = self.landedStatus[_lookupKeyHeli] + _woundedGroup:OptionAlarmStateGreen() self:_OrderGroupToMoveToPoint(_woundedGroup, _heliUnit:GetCoordinate()) self:_DisplayMessageToSAR(_heliUnit, "Wait till " .. _pilotName .. " gets in. \nETA " .. _time .. " more seconds.", self.messageTime, false) else From 8bff9efc5c85fa7e57dbc059fce096438063b0aa Mon Sep 17 00:00:00 2001 From: Applevangelist <72444570+Applevangelist@users.noreply.github.com> Date: Mon, 13 Jun 2022 15:21:50 +0200 Subject: [PATCH 24/30] Beacon - update docs (#1733) Updated docs to point to ActivateTacan as better option to AAATACAN --- Moose Development/Moose/Core/Beacon.lua | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Moose Development/Moose/Core/Beacon.lua b/Moose Development/Moose/Core/Beacon.lua index cdd311372..5a0775ec2 100644 --- a/Moose Development/Moose/Core/Beacon.lua +++ b/Moose Development/Moose/Core/Beacon.lua @@ -16,14 +16,14 @@ --- *In order for the light to shine so brightly, the darkness must be present.* -- Francis Bacon -- -- After attaching a @{#BEACON} to your @{Wrapper.Positionable#POSITIONABLE}, you need to select the right function to activate the kind of beacon you want. --- There are two types of BEACONs available : the AA TACAN Beacon and the general purpose Radio Beacon. +-- There are two types of BEACONs available : the (aircraft) TACAN Beacon and the general purpose Radio Beacon. -- Note that in both case, you can set an optional parameter : the `BeaconDuration`. This can be very usefull to simulate the battery time if your BEACON is -- attach to a cargo crate, for exemple. -- --- ## AA TACAN Beacon usage +-- ## Aircraft TACAN Beacon usage -- --- This beacon only works with airborne @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}. Use @{#BEACON:AATACAN}() to set the beacon parameters and start the beacon. --- Use @#BEACON:StopAATACAN}() to stop it. +-- This beacon only works with airborne @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}. Use @{#BEACON:ActivateTACAN}() to set the beacon parameters and start the beacon. +-- Use @#BEACON:StopRadioBeacon}() to stop it. -- -- ## General Purpose Radio Beacon usage -- @@ -245,7 +245,8 @@ function BEACON:ActivateICLS(Channel, Callsign, Duration) return self end ---- Activates a TACAN BEACON on an Aircraft. +--- DEPRECATED: Please use @{BEACON:ActivateTACAN}() instead. +-- Activates a TACAN BEACON on an Aircraft. -- @param #BEACON self -- @param #number TACANChannel (the "10" part in "10Y"). Note that AA TACAN are only available on Y Channels -- @param #string Message The Message that is going to be coded in Morse and broadcasted by the beacon @@ -325,7 +326,7 @@ function BEACON:StopAATACAN() end ---- Activates a general pupose Radio Beacon +--- Activates a general purpose Radio Beacon -- This uses the very generic singleton function "trigger.action.radioTransmission()" provided by DCS to broadcast a sound file on a specific frequency. -- Although any frequency could be used, only 2 DCS Modules can home on radio beacons at the time of writing : the Huey and the Mi-8. -- They can home in on these specific frequencies : @@ -402,7 +403,7 @@ function BEACON:RadioBeacon(FileName, Frequency, Modulation, Power, BeaconDurati end end ---- Stops the AA TACAN BEACON +--- Stops the Radio Beacon -- @param #BEACON self -- @return #BEACON self function BEACON:StopRadioBeacon() @@ -448,4 +449,4 @@ function BEACON:_TACANToFrequency(TACANChannel, TACANMode) end return (A + TACANChannel - B) * 1000000 -end \ No newline at end of file +end From 5cb2bd1332adf0d3766684ada01c1add6fdc000d Mon Sep 17 00:00:00 2001 From: Applevangelist <72444570+Applevangelist@users.noreply.github.com> Date: Mon, 13 Jun 2022 15:41:19 +0200 Subject: [PATCH 25/30] Update Beacon.lua --- Moose Development/Moose/Core/Beacon.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Moose Development/Moose/Core/Beacon.lua b/Moose Development/Moose/Core/Beacon.lua index 5a0775ec2..3f255e0e0 100644 --- a/Moose Development/Moose/Core/Beacon.lua +++ b/Moose Development/Moose/Core/Beacon.lua @@ -22,14 +22,14 @@ -- -- ## Aircraft TACAN Beacon usage -- --- This beacon only works with airborne @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}. Use @{#BEACON:ActivateTACAN}() to set the beacon parameters and start the beacon. --- Use @#BEACON:StopRadioBeacon}() to stop it. +-- This beacon only works with airborne @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}. Use @{#BEACON.ActivateTACAN}() to set the beacon parameters and start the beacon. +-- Use @{#BEACON.StopRadioBeacon}() to stop it. -- -- ## General Purpose Radio Beacon usage -- -- This beacon will work with any @{Wrapper.Positionable#POSITIONABLE}, but **it won't follow the @{Wrapper.Positionable#POSITIONABLE}** ! This means that you should only use it with --- @{Wrapper.Positionable#POSITIONABLE} that don't move, or move very slowly. Use @{#BEACON:RadioBeacon}() to set the beacon parameters and start the beacon. --- Use @{#BEACON:StopRadioBeacon}() to stop it. +-- @{Wrapper.Positionable#POSITIONABLE} that don't move, or move very slowly. Use @{#BEACON.RadioBeacon}() to set the beacon parameters and start the beacon. +-- Use @{#BEACON.StopRadioBeacon}() to stop it. -- -- @type BEACON -- @field #string ClassName Name of the class "BEACON". From ab31aecdac7269b32ad0edaf1d9aef0aee0d0327 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 14 Jun 2022 12:37:56 +0200 Subject: [PATCH 26/30] CSAR - some fixes for latest open beta --- Moose Development/Moose/Ops/CSAR.lua | 122 +++++++++++++++++---------- 1 file changed, 77 insertions(+), 45 deletions(-) diff --git a/Moose Development/Moose/Ops/CSAR.lua b/Moose Development/Moose/Ops/CSAR.lua index e33248b31..10f36e91a 100644 --- a/Moose Development/Moose/Ops/CSAR.lua +++ b/Moose Development/Moose/Ops/CSAR.lua @@ -130,7 +130,7 @@ -- mycsar.SRSGPathToCredentials = nil -- Path to your Google credentials json file, set this if you want to use Google TTS -- mycsar.SRSVolume = 1 -- Volume, between 0 and 1 -- -- --- mycsar.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection --shagrat +-- mycsar.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection. Requires mycsar.enableForAI to be set to true. --shagrat -- mycsar.wetfeettemplate = "man in floating thingy" -- if you use a mod to have a pilot in a rescue float, put the template name in here for wet feet spawns. Note: in conjunction with csarUsePara this might create dual ejected pilots in edge cases. -- -- ## 3. Results @@ -869,12 +869,12 @@ function CSAR:_EventHandler(EventData) -- no Player if self.enableForAI == false and _event.IniPlayerName == nil then - return + return self end -- no event if _event == nil or _event.initiator == nil then - return false + return self -- take off elseif _event.id == EVENTS.Takeoff then -- taken off @@ -882,35 +882,43 @@ function CSAR:_EventHandler(EventData) local _coalition = _event.IniCoalition if _coalition ~= self.coalition then - return --ignore! + return self --ignore! end if _event.IniGroupName then self.takenOff[_event.IniUnitName] = true end - return true + return self -- player enter unit elseif _event.id == EVENTS.PlayerEnterAircraft or _event.id == EVENTS.PlayerEnterUnit then --player entered unit self:T(self.lid .. " Event unit - Player Enter") local _coalition = _event.IniCoalition + self:T("Coalition = "..UTILS.GetCoalitionName(_coalition)) if _coalition ~= self.coalition then - return --ignore! + return self --ignore! end if _event.IniPlayerName then self.takenOff[_event.IniPlayerName] = nil end + -- jumped into flying plane? + self:T("Taken Off: "..tostring(_event.IniUnit:InAir(true))) + + if _event.IniUnit:InAir(true) then + self.takenOff[_event.IniPlayerName] = true + end + local _unit = _event.IniUnit local _group = _event.IniGroup if _unit:IsHelicopter() or _group:IsHelicopter() then self:_AddMedevacMenuItem() end - return true + return self elseif (_event.id == EVENTS.PilotDead and self.csarOncrash == false) then -- Pilot dead @@ -922,57 +930,68 @@ function CSAR:_EventHandler(EventData) local _group = _event.IniGroup if _unit == nil then - return -- error! + return self -- error! end local _coalition = _event.IniCoalition if _coalition ~= self.coalition then - return --ignore! + return self --ignore! end -- Catch multiple events here? if self.takenOff[_event.IniUnitName] == true or _group:IsAirborne() then if self:_DoubleEjection(_unitname) then - return + return self end else self:T(self.lid .. " Pilot has not taken off, ignore") end - return + return self elseif _event.id == EVENTS.PilotDead or _event.id == EVENTS.Ejection then if _event.id == EVENTS.PilotDead and self.csarOncrash == false then - return + return self end self:T(self.lid .. " Event unit - Pilot Ejected") local _unit = _event.IniUnit local _unitname = _event.IniUnitName local _group = _event.IniGroup + + self:T({_unit.UnitName, _unitname, _group.GroupName}) if _unit == nil then - return -- error! + self:T("Unit NIL!") + return self -- error! end - local _coalition = _unit:GetCoalition() + --local _coalition = _unit:GetCoalition() -- nil now for some reason + local _coalition = _group:GetCoalition() if _coalition ~= self.coalition then - return --ignore! + self:T("Wrong coalition! Coalition = "..UTILS.GetCoalitionName(_coalition)) + return self --ignore! end - + + + self:T("Airborne: "..tostring(_group:IsAirborne())) + self:T("Taken Off: "..tostring(self.takenOff[_event.IniUnitName])) + if not self.takenOff[_event.IniUnitName] and not _group:IsAirborne() then self:T(self.lid .. " Pilot has not taken off, ignore") - return -- give up, pilot hasnt taken off + -- return self -- give up, pilot hasnt taken off end if self:_DoubleEjection(_unitname) then - return + self:T("Double Ejection!") + return self end -- limit no of pilots in the field. if self.limitmaxdownedpilots and self:_ReachedPilotLimit() then - return + self:T("Maxed Downed Pilot!") + return self end @@ -981,33 +1000,27 @@ function CSAR:_EventHandler(EventData) local wetfeet = false - local surface = _unit:GetCoordinate():GetSurfaceType() + local initdcscoord = nil + local initcoord = nil + --if _event.id == EVENTS.Ejection then + initdcscoord = _event.TgtDCSUnit:getPoint() + initcoord = COORDINATE:NewFromVec3(initdcscoord) + self:T({initdcscoord}) + --end + + --local surface = _unit:GetCoordinate():GetSurfaceType() + local surface = initcoord:GetSurfaceType() + if surface == land.SurfaceType.WATER then + self:T("Wet feet!") wetfeet = true end -- all checks passed, get going. if self.csarUsePara == false or (self.csarUsePara and wetfeet ) then --shagrat check parameter LandingAfterEjection, if true don't spawn a Pilot from EJECTION event, wait for the Chute to land - local _freq = self:_GenerateADFFrequency() - self:_AddCsar(_coalition, _unit:GetCountry(), _unit:GetCoordinate() , _unit:GetTypeName(), _unit:GetName(), _event.IniPlayerName, _freq, false, "none") - return true - end - - ---- shagrat on event LANDING_AFTER_EJECTION spawn pilot at parachute location - elseif (_event.id == EVENTS.LandingAfterEjection and self.csarUsePara == true) then - self:I({EVENT=_event}) - local _LandingPos = COORDINATE:NewFromVec3(_event.initiator:getPosition().p) - local _unitname = "Aircraft" --_event.initiator:getName() or "Aircraft" --shagrat Optional use of Object name which is unfortunately 'f15_Pilot_Parachute' - local _typename = "Ejected Pilot" --_event.Initiator.getTypeName() or "Ejected Pilot" - local _country = _event.initiator:getCountry() - local _coalition = coalition.getCountryCoalition( _country ) - if _coalition == self.coalition then local _freq = self:_GenerateADFFrequency() - self:I({coalition=_coalition,country= _country, coord=_LandingPos, name=_unitname, player=_event.IniPlayerName, freq=_freq}) - self:_AddCsar(_coalition, _country, _LandingPos, nil, _unitname, _event.IniPlayerName, _freq, false, "none")--shagrat add CSAR at Parachute location. - - Unit.destroy(_event.initiator) -- shagrat remove static Pilot model - end - return true + self:_AddCsar(_coalition, _unit:GetCountry(), initcoord , _unit:GetTypeName(), _unit:GetName(), _event.IniPlayerName, _freq, false, "none") + return self + end elseif _event.id == EVENTS.Land then self:T(self.lid .. " Landing") @@ -1022,12 +1035,12 @@ function CSAR:_EventHandler(EventData) if _unit == nil then self:T(self.lid .. " Unit nil on landing") - return -- error! + return self -- error! end local _coalition = _event.IniCoalition if _coalition ~= self.coalition then - return --ignore! + return self --ignore! end self.takenOff[_event.IniUnitName] = nil @@ -1036,13 +1049,13 @@ function CSAR:_EventHandler(EventData) if _place == nil then self:T(self.lid .. " Landing Place Nil") - return -- error! + return self -- error! end -- anyone on board? if self.inTransitGroups[_event.IniUnitName] == nil then -- ignore - return + return self end if _place:GetCoalition() == self.coalition or _place:GetCoalition() == coalition.side.NEUTRAL then @@ -1052,8 +1065,27 @@ function CSAR:_EventHandler(EventData) end end - return true + return self end + + ---- shagrat on event LANDING_AFTER_EJECTION spawn pilot at parachute location + if (_event.id == EVENTS.LandingAfterEjection and self.csarUsePara == true) then + self:T("LANDING_AFTER_EJECTION") + local _LandingPos = COORDINATE:NewFromVec3(_event.initiator:getPosition().p) + local _unitname = "Aircraft" --_event.initiator:getName() or "Aircraft" --shagrat Optional use of Object name which is unfortunately 'f15_Pilot_Parachute' + local _typename = "Ejected Pilot" --_event.Initiator.getTypeName() or "Ejected Pilot" + local _country = _event.initiator:getCountry() + local _coalition = coalition.getCountryCoalition( _country ) + self:T("Country = ".._country.." Coalition = ".._coalition) + if _coalition == self.coalition then + local _freq = self:_GenerateADFFrequency() + self:I({coalition=_coalition,country= _country, coord=_LandingPos, name=_unitname, player=_event.IniPlayerName, freq=_freq}) + self:_AddCsar(_coalition, _country, _LandingPos, nil, _unitname, _event.IniPlayerName, _freq, false, "none")--shagrat add CSAR at Parachute location. + + Unit.destroy(_event.initiator) -- shagrat remove static Pilot model + end + end + return self end From 3eb9bfe9ee1676318320ac84f61924e7637596d0 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 14 Jun 2022 13:07:07 +0200 Subject: [PATCH 27/30] COORDINATE - additions to BRAANATO AWACS - make bogey dope use the priority queue to avoid collisions. Say "very low" and not "zero thousand", drop "vanished" if not tags is requested --- Moose Development/Moose/Core/Point.lua | 4 +++ Moose Development/Moose/Ops/Awacs.lua | 36 ++++++++++++++++---------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index 010905098..e459e702e 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -2804,6 +2804,10 @@ do -- COORDINATE alttext = string.format("Angels %d",alt) end + if alt < 1 then + alttext = "very low" + end + local track = UTILS.BearingToCardinal(bearing) or "North" if rangeNM > 3 then diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index a9cf20fd2..7dee1b2a2 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -314,7 +314,7 @@ do -- testawacs.maxassigndistance = 100 -- Don't assign targets further out than this, in NM. -- testawacs.debug = false -- set to true to produce more log output. -- testawacs.NoMissileCalls = true -- suppress missile callouts --- testawacs.PlayerCapAssigment = true -- no task assignment for players +-- testawacs.PlayerCapAssigment = true -- no intercept task assignments for players -- testawacs.invisible = false -- set AWACS to be invisible to hostiles -- testawacs.immortal = false -- set AWACS to be immortal -- -- By default, the radio queue is checked every 10 secs. This is altered by the calculated length of the sentence to speak @@ -364,7 +364,7 @@ do -- @field #AWACS AWACS = { ClassName = "AWACS", -- #string - version = "beta 0.1.29", -- #string + version = "beta 0.1.30", -- #string lid = "", -- #string coalition = coalition.side.BLUE, -- #number coalitiontxt = "blue", -- #string @@ -706,7 +706,7 @@ AWACS.TaskStatus = { --@field #boolean FromAI ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- TODO-List 0.1.29 +-- TODO-List 0.1.30 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- -- DONE - WIP - Player tasking, VID @@ -1201,7 +1201,7 @@ function AWACS:SuppressScreenMessages(Switch) return self end ---- [User] Do not show messages on screen, no extra calls for player guidance, use short callsigns, no group tags. +--- [User] Do not show messages on screen, no extra calls for player guidance, use short callsigns etc. -- @param #AWACS self -- @return #AWACS self function AWACS:ZipLip() @@ -1984,7 +1984,7 @@ function AWACS:_CleanUpContacts() --local aliveclusters = FIFO:New() -- announce VANISHED - if deadcontacts:Count() > 0 then + if deadcontacts:Count() > 0 and (not self.NoGroupTags) then self:T("DEAD count="..deadcontacts:Count()) deadcontacts:ForEach( @@ -2505,7 +2505,7 @@ function AWACS:_BogeyDope(Group) if not self.intel then -- no intel yet! text = string.format("%s. %s. Clean.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt) - self:_NewRadioEntry(text,text,0,false,true,true,false) + self:_NewRadioEntry(text,text,0,false,true,true,false,true) return self end @@ -2547,7 +2547,7 @@ function AWACS:_BogeyDope(Group) text = string.format("%s. %s. Clean.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt) - self:_NewRadioEntry(text,textScreen,GID,Outcome,Outcome,true,false) + self:_NewRadioEntry(text,textScreen,GID,Outcome,Outcome,true,false,true) else @@ -2561,7 +2561,7 @@ function AWACS:_BogeyDope(Group) textScreen = textScreen .. contactsAO .. " groups.\n" end - self:_NewRadioEntry(text,textScreen,GID,Outcome,true,true,false) + self:_NewRadioEntry(text,textScreen,GID,Outcome,true,true,false,true) self:_CreateBogeyDope(self:_GetCallSign(Group,GID) or "Ghost 1",GID) end @@ -3775,10 +3775,18 @@ function AWACS:_ToStringBRA(FromCoordinate,ToCoordinate,Altitude) local AngleDegTextTTS = string.gsub(AngleDegText,"0","zero") local Distance = ToCoordinate:Get2DDistance( FromCoordinate ) --meters local distancenm = UTILS.Round(UTILS.MetersToNM(Distance),0) - BRText = string.format("%03d, %d miles, %d thousand",AngleDegrees,distancenm,altitude) - BRTextTTS = string.format("%s, %d miles, %d thousand",AngleDegText,distancenm,altitude) - if self.PathToGoogleKey then - BRTextTTS = string.format("%s, %d miles, %d thousand",AngleDegTextTTS,distancenm,altitude) + if altitude >= 1 then + BRText = string.format("%03d, %d miles, %d thousand",AngleDegrees,distancenm,altitude) + BRTextTTS = string.format("%s, %d miles, %d thousand",AngleDegText,distancenm,altitude) + if self.PathToGoogleKey then + BRTextTTS = string.format("%s, %d miles, %d thousand",AngleDegTextTTS,distancenm,altitude) + end + else + BRText = string.format("%03d, %d miles, very low",AngleDegrees,distancenm) + BRTextTTS = string.format("%s, %d miles, very low",AngleDegText,distancenm) + if self.PathToGoogleKey then + BRTextTTS = string.format("%s, %d miles, very low",AngleDegTextTTS,distancenm) + end end self:T(BRText,BRTextTTS) return BRText,BRTextTTS @@ -4620,8 +4628,8 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo string.gsub(BRAText,"BRA","brah") --self:T(BRAText) - - self:_NewRadioEntry(BRAText,TextScreen,GID,isGroup,true,IsNew,false,IsNew) + local prio = IsNew or IsBogeyDope + self:_NewRadioEntry(BRAText,TextScreen,GID,isGroup,true,IsNew,false,prio) return self end From 4784a315134515c0ac1d86375cecf676ccc0d416 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 14 Jun 2022 17:20:12 +0200 Subject: [PATCH 28/30] UTILS - Falklands additions --- Moose Development/Moose/Utilities/Utils.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua index 8f7c4f7ec..77f4d536e 100644 --- a/Moose Development/Moose/Utilities/Utils.lua +++ b/Moose Development/Moose/Utilities/Utils.lua @@ -52,6 +52,7 @@ BIGSMOKEPRESET = { -- @field #string TheChannel The Channel map. -- @field #string Syria Syria map. -- @field #string MarianaIslands Mariana Islands map. +-- @field #string Falklands South Atlantic map. DCSMAP = { Caucasus="Caucasus", NTTR="Nevada", @@ -59,7 +60,8 @@ DCSMAP = { PersianGulf="PersianGulf", TheChannel="TheChannel", Syria="Syria", - MarianaIslands="MarianaIslands" + MarianaIslands="MarianaIslands", + Falklands="Falklands", } @@ -1347,6 +1349,7 @@ end -- * The Cannel Map -10 (West) -- * Syria +5 (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 -- @param #string map (Optional) Map for which the declination is returned. Default is from env.mission.theatre -- @return #number Declination in degrees. function UTILS.GetMagneticDeclination(map) @@ -1369,6 +1372,8 @@ function UTILS.GetMagneticDeclination(map) declination=5 elseif map==DCSMAP.MarianaIslands then declination=2 + elseif map==DCSMAP.Falklands then + declination=12 else declination=0 end From b78467139798271221be6bd7d5ae26caea016348 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 16 Jun 2022 13:40:35 +0200 Subject: [PATCH 29/30] CSAR - added event for "Landed" at a friendly/neutral AFB. Fixed Airbase rescue. --- Moose Development/Moose/Ops/CSAR.lua | 60 ++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/Moose Development/Moose/Ops/CSAR.lua b/Moose Development/Moose/Ops/CSAR.lua index 10f36e91a..cfc9d1342 100644 --- a/Moose Development/Moose/Ops/CSAR.lua +++ b/Moose Development/Moose/Ops/CSAR.lua @@ -264,7 +264,7 @@ CSAR.AircraftType["AH-64D_BLK_II"] = 2 --- CSAR class version. -- @field #string version -CSAR.version="1.0.5" +CSAR.version="1.0.6" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- ToDo list @@ -333,6 +333,7 @@ function CSAR:New(Coalition, Template, Alias) self:AddTransition("*", "Status", "*") -- CSAR status update. self:AddTransition("*", "PilotDown", "*") -- Downed Pilot added self:AddTransition("*", "Approach", "*") -- CSAR heli closing in. + self:AddTransition("*", "Landed", "*") -- CSAR heli landed self:AddTransition("*", "Boarded", "*") -- Pilot boarded. self:AddTransition("*", "Returning", "*") -- CSAR able to return to base. self:AddTransition("*", "Rescued", "*") -- Pilot at MASH. @@ -474,7 +475,16 @@ function CSAR:New(Coalition, Template, Alias) -- @param #string Heliname Name of the helicopter group. -- @param #string Woundedgroupname Name of the downed pilot\'s group. - --- On After "Boarded" event. Downed pilot boarded heli. + --- On After "Landed" event. Heli landed at an airbase. + -- @function [parent=#CSAR] OnAfterLanded + -- @param #CSAR self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + -- @param #string HeliName Name of the #UNIT which has landed. + -- @param Wrapper.Airbase#AIRBASE Airbase Airbase where the heli landed. + + --- On After "Boarded" event. Downed pilot boarded heli. -- @function [parent=#CSAR] OnAfterBoarded -- @param #CSAR self -- @param #string From From state. @@ -1038,15 +1048,17 @@ function CSAR:_EventHandler(EventData) return self -- error! end - local _coalition = _event.IniCoalition + --local _coalition = _event.IniCoalition + local _coalition = _event.IniGroup:GetCoalition() if _coalition ~= self.coalition then + self:T(self.lid .. " Wrong coalition") return self --ignore! end self.takenOff[_event.IniUnitName] = nil local _place = _event.Place -- Wrapper.Airbase#AIRBASE - + if _place == nil then self:T(self.lid .. " Landing Place Nil") return self -- error! @@ -1059,6 +1071,7 @@ function CSAR:_EventHandler(EventData) end if _place:GetCoalition() == self.coalition or _place:GetCoalition() == coalition.side.NEUTRAL then + self:__Landed(2,_event.IniUnitName, _place) self:_ScheduledSARFlight(_event.IniUnitName,_event.IniGroupName,true) else self:T(string.format("Airfield %d, Unit %d", _place:GetCoalition(), _unit:GetCoalition())) @@ -1185,7 +1198,7 @@ function CSAR:_CheckWoundedGroupStatus(heliname,woundedgroupname) self.heliVisibleMessage[_lookupKeyHeli] = nil self.heliCloseMessage[_lookupKeyHeli] = nil self.landedStatus[_lookupKeyHeli] = nil - self:T("...helinunit nil!") + self:T("...heliunit nil!") return end @@ -1281,7 +1294,7 @@ function CSAR:_PickupUnit(_heliUnit, _pilotName, _woundedGroup, _woundedGroupNam end if _unitsInHelicopter + 1 > _maxUnits then self:_DisplayMessageToSAR(_heliUnit, string.format("%s, %s. We\'re already crammed with %d guys! Sorry!", _pilotName, _heliName, _unitsInHelicopter, _unitsInHelicopter), self.messageTime,false,false,true) - return true + return self end local found,downedgrouptable = self:_CheckNameInDownedPilots(_woundedGroupName) @@ -1302,7 +1315,7 @@ function CSAR:_PickupUnit(_heliUnit, _pilotName, _woundedGroup, _woundedGroupNam self:__Boarded(5,_heliName,_woundedGroupName) - return true + return self end --- (Internal) Move group to destination. @@ -1378,24 +1391,24 @@ function CSAR:_CheckCloseWoundedGroup(_distance, _heliUnit, _heliName, _woundedG end --if _time <= 0 or _distance < self.loadDistance then if _distance < self.loadDistance + 5 or _distance <= 13 then - if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(_heliName) then + if self.pilotmustopendoors and (self:_IsLoadingDoorOpen(_heliName) == false) then self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me in!", self.messageTime, true, true) - return true + return false else self.landedStatus[_lookupKeyHeli] = nil self:_PickupUnit(_heliUnit, _pilotName, _woundedGroup, _woundedGroupName) - return false + return true end end end else if (_distance < self.loadDistance) then - if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(_heliName) then + if self.pilotmustopendoors and (self:_IsLoadingDoorOpen(_heliName) == false) then self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me in!", self.messageTime, true, true) - return true + return false else self:_PickupUnit(_heliUnit, _pilotName, _woundedGroup, _woundedGroupName) - return false + return true end end end @@ -1432,18 +1445,19 @@ function CSAR:_CheckCloseWoundedGroup(_distance, _heliUnit, _heliName, _woundedG if _time > 0 then self:_DisplayMessageToSAR(_heliUnit, "Hovering above " .. _pilotName .. ". \n\nHold hover for " .. _time .. " seconds to winch them up. \n\nIf the countdown stops you\'re too far away!", self.messageTime, true) else - if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(_heliName) then + if self.pilotmustopendoors and (self:_IsLoadingDoorOpen(_heliName) == false) then self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me in!", self.messageTime, true, true) - return true + return false else self.hoverStatus[_lookupKeyHeli] = nil self:_PickupUnit(_heliUnit, _pilotName, _woundedGroup, _woundedGroupName) - return false + return true end end _reset = false else self:_DisplayMessageToSAR(_heliUnit, "Too high to winch " .. _pilotName .. " \nReduce height and hover for 10 seconds!", self.messageTime, true,true) + return false end end @@ -2075,7 +2089,7 @@ end -- @param #string To To state. function CSAR:onafterStart(From, Event, To) self:T({From, Event, To}) - self:I(self.lid .. "Started.") + self:I(self.lid .. "Started ("..self.version..")") -- event handler self:HandleEvent(EVENTS.Takeoff, self._EventHandler) self:HandleEvent(EVENTS.Land, self._EventHandler) @@ -2275,6 +2289,18 @@ function CSAR:onbeforePilotDown(From, Event, To, Group, Frequency, Leadername, C self:T({From, Event, To, Group, Frequency, Leadername, CoordinatesText}) return self end + +--- (Internal) Function called before Landed() event. +-- @param #CSAR self. +-- @param #string From From state. +-- @param #string Event Event triggered. +-- @param #string To To state. +-- @param #string HeliName Name of the #UNIT which has landed. +-- @param Wrapper.Airbase#AIRBASE Airbase Airbase where the heli landed. +function CSAR:onbeforeLanded(From, Event, To, HeliName, Airbase) + self:T({From, Event, To, HeliName, Airbase}) + return self +end -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- End Ops.CSAR -------------------------------------------------------------------------------------------------------------------------------------------------------------------- From b805d7fe19e6ffbde09f3641159c8d09df5a09f6 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 16 Jun 2022 15:42:13 +0200 Subject: [PATCH 30/30] CSAR - fix for oncrash --- Moose Development/Moose/Ops/CSAR.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/Ops/CSAR.lua b/Moose Development/Moose/Ops/CSAR.lua index cfc9d1342..76281a3f1 100644 --- a/Moose Development/Moose/Ops/CSAR.lua +++ b/Moose Development/Moose/Ops/CSAR.lua @@ -1012,11 +1012,15 @@ function CSAR:_EventHandler(EventData) local initdcscoord = nil local initcoord = nil - --if _event.id == EVENTS.Ejection then + if _event.id == EVENTS.Ejection then initdcscoord = _event.TgtDCSUnit:getPoint() initcoord = COORDINATE:NewFromVec3(initdcscoord) self:T({initdcscoord}) - --end + else + initdcscoord = _event.IniDCSUnit:getPoint() + initcoord = COORDINATE:NewFromVec3(initdcscoord) + self:T({initdcscoord}) + end --local surface = _unit:GetCoordinate():GetSurfaceType() local surface = initcoord:GetSurfaceType()