diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua
index 0454f1274..dfbbb6a90 100644
--- a/Moose Development/Moose/Core/Point.lua
+++ b/Moose Development/Moose/Core/Point.lua
@@ -874,6 +874,11 @@ do -- COORDINATE
-- Get the vector from A to B
local vec=UTILS.VecSubstract(ToCoordinate, self)
+
+ if f>1 then
+ local norm=UTILS.VecNorm(vec)
+ f=Fraction/norm
+ end
-- Scale the vector.
vec.x=f*vec.x
@@ -883,7 +888,9 @@ do -- COORDINATE
-- Move the vector to start at the end of A.
vec=UTILS.VecAdd(self, vec)
+ -- Create a new coordiante object.
local coord=COORDINATE:New(vec.x,vec.y,vec.z)
+
return coord
end
@@ -2769,8 +2776,9 @@ do -- COORDINATE
-- @param #COORDINATE FromCoordinate The coordinate to measure the distance and the bearing from.
-- @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
-- @return #string The BRAA text.
- function COORDINATE:ToStringBRAANATO(FromCoordinate,Bogey,Spades)
+ function COORDINATE:ToStringBRAANATO(FromCoordinate,Bogey,Spades,SSML)
-- Thanks to @Pikey
local BRAANATO = "Merged."
@@ -2791,22 +2799,39 @@ do -- COORDINATE
local track = UTILS.BearingToCardinal(bearing) or "North"
if rangeNM > 3 then
- if aspect == "" then
- BRAANATO = string.format("BRA, %03d, %d miles, Angels %d, Track %s",bearing, rangeNM, alt, track)
+ if SSML then
+ if aspect == "" then
+ BRAANATO = string.format("brah %03d, %d miles, Angels %d, Track %s",bearing, rangeNM, alt, track)
+ else
+ BRAANATO = string.format("brah %03d, %d miles, Angels %d, %s, Track %s",bearing, rangeNM, alt, aspect, track)
+ end
+ if Bogey and Spades then
+ BRAANATO = BRAANATO..", Bogey, Spades."
+ elseif Bogey then
+ BRAANATO = BRAANATO..", Bogey."
+ elseif Spades then
+ BRAANATO = BRAANATO..", Spades."
+ else
+ BRAANATO = BRAANATO.."."
+ end
else
- BRAANATO = string.format("BRAA, %03d, %d miles, Angels %d, %s, Track %s",bearing, rangeNM, alt, aspect, track)
- end
- if Bogey and Spades then
- BRAANATO = BRAANATO..", Bogey, Spades."
- elseif Bogey then
- BRAANATO = BRAANATO..", Bogey."
- elseif Spades then
- BRAANATO = BRAANATO..", Spades."
- else
- BRAANATO = BRAANATO.."."
+ if aspect == "" then
+ BRAANATO = string.format("BRA %03d, %d miles, Angels %d, Track %s",bearing, rangeNM, alt, track)
+ else
+ BRAANATO = string.format("BRAA %03d, %d miles, Angels %d, %s, Track %s",bearing, rangeNM, alt, aspect, track)
+ end
+ if Bogey and Spades then
+ BRAANATO = BRAANATO..", Bogey, Spades."
+ elseif Bogey then
+ BRAANATO = BRAANATO..", Bogey."
+ elseif Spades then
+ BRAANATO = BRAANATO..", Spades."
+ else
+ BRAANATO = BRAANATO.."."
+ end
end
end
-
+
return BRAANATO
end
diff --git a/Moose Development/Moose/Ops/ArmyGroup.lua b/Moose Development/Moose/Ops/ArmyGroup.lua
index 98d2992a2..35ba2606f 100644
--- a/Moose Development/Moose/Ops/ArmyGroup.lua
+++ b/Moose Development/Moose/Ops/ArmyGroup.lua
@@ -1005,32 +1005,65 @@ end
-- @param #number Formation Formation of the group.
function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation)
- -- Debug info.
- local text=string.format("Update route state=%s: n=%s, N=%s, Speed=%s, Formation=%s", self:GetState(), tostring(n), tostring(N), tostring(Speed), tostring(Formation))
- self:T(self.lid..text)
-
-- Update route from this waypoint number onwards.
n=n or self:GetWaypointIndexNext(self.adinfinitum)
-- Max index.
- N=N or #self.waypoints
+ N=N or #self.waypoints
N=math.min(N, #self.waypoints)
+
+ -- Debug info.
+ local text=string.format("Update route state=%s: n=%s, N=%s, Speed=%s, Formation=%s", self:GetState(), tostring(n), tostring(N), tostring(Speed), tostring(Formation))
+ self:T(self.lid..text)
- -- Waypoints.
+ -- Waypoints including addtional wp onroad.
local waypoints={}
- local formationlast=nil
- for i=n, #self.waypoints do
+ -- Next waypoint.
+ local wp=self.waypoints[n] --Ops.OpsGroup#OPSGROUP.Waypoint
+
+ -- Formation at the current position.
+ local formation0=wp.action
+ if formation0==ENUMS.Formation.Vehicle.OnRoad then
+ if wp.roadcoord then
+ if wp.roaddist>10 then
+ formation0=ENUMS.Formation.Vehicle.OffRoad
+ end
+ else
+ formation0=ENUMS.Formation.Vehicle.OffRoad
+ end
+ end
+
+ -- Current point.
+ local current=self:GetCoordinate():WaypointGround(UTILS.MpsToKmph(self.speedWp), formation0) --ENUMS.Formation.Vehicle.OffRoad)
+ table.insert(waypoints, 1, current)
+
+ -- Loop over waypoints.
+ for j=n, N do
+
+ -- Index of previous waypoint.
+ local i=j-1
+
+ -- If we go to the first waypoint j=1 ==> i=0, so we take the last waypoint passed. E.g. when adinfinitum and passed final waypoint.
+ if i==0 then
+ i=self.currentwp
+ end
-- Next waypoint.
- local wp=UTILS.DeepCopy(self.waypoints[i]) --Ops.OpsGroup#OPSGROUP.Waypoint
+ local wp=UTILS.DeepCopy(self.waypoints[j]) --Ops.OpsGroup#OPSGROUP.Waypoint
+
+ -- Previous waypoint. Index is i and not i-1 because we added the current position.
+ local wp0=self.waypoints[i] --Ops.OpsGroup#OPSGROUP.Waypoint
+
+ --local text=string.format("FF Update: i=%d, wp[i]=%s, wp[i-1]=%s", i, wp.action, wp0.action)
+ --env.info(text)
-- Speed.
if Speed then
wp.speed=UTILS.KnotsToMps(tonumber(Speed))
else
- -- Take default waypoint speed. But make sure speed>0 if patrol ad infinitum.
- if wp.speed<0.1 then --self.adinfinitum and
+ -- Take default waypoint speed. But make sure speed>0 if patrol ad infinitum.
+ if wp.speed<0.1 then
wp.speed=UTILS.KmphToMps(self.speedCruise)
end
end
@@ -1041,9 +1074,23 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation)
elseif Formation then
wp.action=Formation
end
-
+
-- Add waypoint in between because this waypoint is "On Road" but lies "Off Road".
- if wp.action==ENUMS.Formation.Vehicle.OnRoad and wp.roaddist>10 then
+ if wp.action==ENUMS.Formation.Vehicle.OnRoad and wp0.roaddist>=0 then
+
+ --env.info("FF adding waypoint0 on road #"..i)
+
+ -- Add "On Road" waypoint in between.
+ local wproad=wp0.roadcoord:WaypointGround(UTILS.MpsToKmph(wp.speed), ENUMS.Formation.Vehicle.OnRoad) --Ops.OpsGroup#OPSGROUP.Waypoint
+
+ -- Insert road waypoint.
+ table.insert(waypoints, wproad)
+ end
+
+ -- Add waypoint in between because this waypoint is "On Road" but lies "Off Road".
+ if wp.action==ENUMS.Formation.Vehicle.OnRoad and wp.roaddist>=0 then
+
+ --env.info("FF adding waypoint on road #"..i)
-- The real waypoint is actually off road.
wp.action=ENUMS.Formation.Vehicle.OffRoad
@@ -1053,13 +1100,11 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation)
-- Insert road waypoint.
table.insert(waypoints, wproad)
- end
+ end
+
-- Add waypoint.
- table.insert(waypoints, wp)
-
- -- Last formation.
- formationlast=wp.action
+ table.insert(waypoints, wp)
end
-- First (next wp).
@@ -1069,29 +1114,18 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation)
self.option.Formation=wp.action
-- Current set speed in m/s.
- self.speedWp=wp.speed
-
- local formation0=wp.action==ENUMS.Formation.Vehicle.OnRoad and ENUMS.Formation.Vehicle.OnRoad or wp.action
-
- -- Current point.
- local current=self:GetCoordinate():WaypointGround(UTILS.MpsToKmph(self.speedWp), formation0)
- table.insert(waypoints, 1, current)
-
- -- Insert a point on road.
- if wp.action==ENUMS.Formation.Vehicle.OnRoad and (wp.coordinate or wp.roadcoord) then
-
- current=self:GetClosestRoad():WaypointGround(UTILS.MpsToKmph(self.speedWp), ENUMS.Formation.Vehicle.OnRoad)
- table.insert(waypoints, 2, current)
- end
+ self.speedWp=wp.speed
-- Debug output.
if self.verbose>=10 then
- --if true then
for i,_wp in pairs(waypoints) do
local wp=_wp --Ops.OpsGroup#OPSGROUP.Waypoint
- local text=string.format("WP #%d UID=%d type=%s: Speed=%d m/s, alt=%d m, Action=%s", i, wp.uid and wp.uid or -1, wp.type, wp.speed, wp.alt, wp.action)
+
+ local text=string.format("WP #%d UID=%d Formation=%s: Speed=%d m/s, Alt=%d m, Type=%s", i, wp.uid and wp.uid or -1, wp.action, wp.speed, wp.alt, wp.type)
+
local coord=COORDINATE:NewFromWaypoint(wp):MarkToAll(text)
self:I(text)
+
end
end
@@ -1722,7 +1756,10 @@ end
-- @param #boolean Updateroute If true or nil, call UpdateRoute. If false, no call.
-- @return Ops.OpsGroup#OPSGROUP.Waypoint Waypoint table.
function ARMYGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Formation, Updateroute)
+
+ -- Debug info.
self:T(self.lid..string.format("AddWaypoint Formation = %s",tostring(Formation) or "none"))
+
-- Create coordinate.
local coordinate=self:_CoordinateFromObject(Coordinate)
diff --git a/Moose Development/Moose/Ops/Auftrag.lua b/Moose Development/Moose/Ops/Auftrag.lua
index c956636a9..a1e46b10b 100644
--- a/Moose Development/Moose/Ops/Auftrag.lua
+++ b/Moose Development/Moose/Ops/Auftrag.lua
@@ -2112,6 +2112,10 @@ function AUFTRAG:_NewRELOCATECOHORT(Legion, Cohort)
mission.DCStask=mission:GetDCSMissionTask()
+ if Cohort.isGround then
+ mission.optionFormation=ENUMS.Formation.Vehicle.OnRoad
+ end
+
mission.DCStask.params.legion=Legion
mission.DCStask.params.cohort=Cohort
diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua
index 4d41e9d71..05e019653 100644
--- a/Moose Development/Moose/Ops/Awacs.lua
+++ b/Moose Development/Moose/Ops/Awacs.lua
@@ -16,7 +16,7 @@
-- ===
--
-- ### Author: **applevangelist**
--- @date Last Update April 2022
+-- @date Last Update May 2022
--
-- ==
-- @module Ops.AWACS
@@ -81,6 +81,7 @@ do
-- @field #number Countactcounter
-- @field Utilities.FiFo#FIFO ContactsAO
-- @field Utilities.FiFo#FIFO RadioQueue
+-- @field Utilities.FiFo#FIFO PrioRadioQueue
-- @field Utilities.FiFo#FIFO CAPAirwings
-- @field #number AwacsTimeOnStation
-- @field #number AwacsTimeStamp
@@ -131,7 +132,7 @@ do
-- @field #AWACS
AWACS = {
ClassName = "AWACS", -- #string
- version = "alpha 0.0.17", -- #string
+ version = "alpha 0.0.19", -- #string
lid = "", -- #string
coalition = coalition.side.BLUE, -- #number
coalitiontxt = "blue", -- #string
@@ -163,6 +164,7 @@ AWACS = {
Countactcounter = 0,
ContactsAO = {}, -- Utilities.FiFo#FIFO
RadioQueue = {}, -- Utilities.FiFo#FIFO
+ PrioRadioQueue = {}, -- Utilities.FiFo#FIFO
AwacsTimeOnStation = 1,
AwacsTimeStamp = 0,
EscortsTimeOnStation = 0.5,
@@ -308,6 +310,20 @@ AWACS.THREATLEVEL = {
RED = 10,
}
+---
+--@field CapVoices -- Random CAP voices
+AWACS.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",
+}
---
-- @type AWACS.MonitoringData
-- @field #string AwacsStateMission
@@ -441,17 +457,21 @@ AWACS.TaskStatus = {
--@field #boolean FromAI
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- TODO-List 0.0.17
+-- TODO-List 0.0.19
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--
--- TODO - System for Players to VID contacts? And put data into contacst fifo
---
--- TODO - WIP - Player tasking
+-- TODO - System for Players to VID contacts?
+-- TODO - Task reassignment - if a player reject a task, don't choose him again for x minutes
+-- DEBUG - WIP - Player tasking
+-- TODO - Maybe check in AI only when airborne
+-- DONE - remove SSML tag when not on google (currently sometimes spoken)
-- TODO - Localization
-- TODO - (LOW) LotATC / IFF
---
-- TODO - SW Optimizer
+-- TODO - Assign specific number of AI CAP to a station
--
+-- DONE - added SSML tags to make google readouts nicer
+-- DONE - 2nd audio queue for priority messages
-- DONE - (WIP) Missile launch callout
-- DONE - Event detection, Player joining, eject, crash, dead, leaving; AI shot -> DEFEND
-- DONE - AI Tasking
@@ -559,7 +579,6 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station
self.CallSign = CALLSIGN.AWACS.Darkstar -- #number
self.CallSignNo = 1 -- #number
self.NoHelos = true
- self.MaxAIonCAP = 4
self.AIRequested = 0
self.AIonCAP = 0
self.AICAPMissions = FIFO:New() -- Utilities.FiFo#FIFO
@@ -575,7 +594,7 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station
local speed = 250
self.SpeedBase = speed
self.Speed = UTILS.KnotsToAltKIAS(speed,self.AwacsAngels*1000)
- self.CapSpeedBase = 270
+
self.Heading = 0 -- north
self.Leg = 50 -- nm
self.invisible = false
@@ -590,8 +609,16 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station
self.ShiftChangeTime = 0.25 -- 15mins
self.ShiftChangeAwacsFlag = false
self.ShiftChangeEscortsFlag = false
- self.CAPTimeOnStation = 4
+ self.CapSpeedBase = 270
+ self.CAPTimeOnStation = 4
+ self.MaxAIonCAP = 4
+ self.AICAPCAllName = CALLSIGN.Aircraft.Colt
+ self.AICAPCAllNumber = 0
+ self.CAPGender = "male"
+ self.CAPCulture = "en-US"
+ self.CAPVoice = nil
+
self.DeclareRadius = 5 -- NM
self.AwacsMission = nil
@@ -615,12 +642,9 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station
self.Port = 5002
self.Volume = 1.0
self.RadioQueue = FIFO:New() -- Utilities.FiFo#FIFO
+ self.PrioRadioQueue = FIFO:New() -- Utilities.FiFo#FIFO
self.maxspeakentries = 3
- self.CAPGender = "male"
- self.CAPCulture = "en-US"
- self.CAPVoice = nil
-
self.SuppressScreenOutput = false
-- Client SET
@@ -633,9 +657,6 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station
self.ManagedGrps = {} -- #table of #AWACS.ManagedGroup entries
self.ManagedGrpID = 0
- self.AICAPCAllName = CALLSIGN.Aircraft.Colt
- self.AICAPCAllNumber = 0
-
-- Anchor stacks init
self.AnchorStacks = FIFO:New() -- Utilities.FiFo#FIFO
self.AnchorBaseAngels = 22
@@ -757,12 +778,13 @@ end
-- @param #string TextTTS Text to speak
-- @param #string TextScreen Text for screen
-- @param #number GID Group ID #AWACS.ManagedGroup GID
--- @param #boolean IsGroup
--- @param #boolean ToScreen
--- @param #boolean IsNew
--- @param #boolean FromAI
+-- @param #boolean IsGroup Has a group
+-- @param #boolean ToScreen Show on screen
+-- @param #boolean IsNew New
+-- @param #boolean FromAI From AI
+-- @param #boolean IsPrio Priority entry
-- @return #AWACS self
-function AWACS:_NewRadioEntry(TextTTS, TextScreen,GID,IsGroup,ToScreen,IsNew,FromAI)
+function AWACS:_NewRadioEntry(TextTTS, TextScreen,GID,IsGroup,ToScreen,IsNew,FromAI,IsPrio)
self:T(self.lid.."_NewRadioEntry")
local RadioEntry = {} -- #AWACS.RadioEntry
RadioEntry.IsNew = IsNew
@@ -773,7 +795,11 @@ function AWACS:_NewRadioEntry(TextTTS, TextScreen,GID,IsGroup,ToScreen,IsNew,Fro
RadioEntry.Duration = STTS.getSpeechTime(TextTTS,0.95,false) or 8
RadioEntry.FromAI = FromAI
RadioEntry.IsGroup = IsGroup
- self.RadioQueue:Push(RadioEntry)
+ if IsPrio then
+ self.PrioRadioQueue:Push(RadioEntry)
+ else
+ self.RadioQueue:Push(RadioEntry)
+ end
return self
end
@@ -834,14 +860,14 @@ end
-- @param Core.Event#EVENTDATA EventData
-- @return #AWACS self
function AWACS:_EventHandler(EventData)
- self:I(self.lid.."_EventHandler")
+ self:T(self.lid.."_EventHandler")
self:T({Event = EventData.id})
local Event = EventData -- Core.Event#EVENTDATA
if Event.id == EVENTS.PlayerEnterAircraft or Event.id == EVENTS.PlayerEnterUnit then --player entered unit
- --self:I("Player enter unit: " .. Event.IniPlayerName)
- --self:I("Coalition = " .. UTILS.GetCoalitionName(Event.IniCoalition))
+ --self:T("Player enter unit: " .. Event.IniPlayerName)
+ --self:T("Coalition = " .. UTILS.GetCoalitionName(Event.IniCoalition))
if Event.IniCoalition == self.coalition then
self:_SetClientMenus()
end
@@ -849,9 +875,9 @@ function AWACS:_EventHandler(EventData)
if Event.id == EVENTS.PlayerLeaveUnit then --player left unit
-- check known player?
- --self:I("Player group left unit: " .. Event.IniGroupName)
- --self:I("Player name left: " .. Event.IniPlayerName)
- --self:I("Coalition = " .. UTILS.GetCoalitionName(Event.IniCoalition))
+ --self:T("Player group left unit: " .. Event.IniGroupName)
+ --self:T("Player name left: " .. Event.IniPlayerName)
+ --self:T("Coalition = " .. UTILS.GetCoalitionName(Event.IniCoalition))
if Event.IniCoalition == self.coalition then
local Outcome, GID, CallSign = self:_GetGIDFromGroupOrName(Event.IniGroupName)
if Outcome and GID > 0 then
@@ -863,8 +889,8 @@ function AWACS:_EventHandler(EventData)
if Event.id == EVENTS.Ejection or Event.id == EVENTS.Crash or Event.id == EVENTS.Dead or Event.id == EVENTS.PilotDead then --unit or player dead
-- check known group?
if Event.IniCoalition == self.coalition then
- --self:I("Ejection/Crash/Dead/PilotDead Group: " .. Event.IniGroupName)
- --self:I("Coalition = " .. UTILS.GetCoalitionName(Event.IniCoalition))
+ --self:T("Ejection/Crash/Dead/PilotDead Group: " .. Event.IniGroupName)
+ --self:T("Coalition = " .. UTILS.GetCoalitionName(Event.IniCoalition))
local Outcome, GID, CallSign = self:_GetGIDFromGroupOrName(Event.IniGroupName)
if Outcome and GID > 0 then
self:_CheckOut(nil,GID,true)
@@ -874,18 +900,18 @@ function AWACS:_EventHandler(EventData)
if Event.id == EVENTS.Shot and self.PlayerGuidance then
if Event.IniCoalition ~= self.coalition then
- self:I("Shot from: " .. Event.IniGroupName)
- --self:I(UTILS.OneLineSerialize(Event))
+ self:T("Shot from: " .. Event.IniGroupName)
+ --self:T(UTILS.OneLineSerialize(Event))
local position = Event.IniGroup:GetCoordinate()
if not position then return self end
- --self:I("Coalition = " .. UTILS.GetCoalitionName(Event.IniCoalition))
+ --self:T("Coalition = " .. UTILS.GetCoalitionName(Event.IniCoalition))
-- Check missile type
local Category = Event.WeaponCategory
local WeaponDesc = EventData.Weapon:getDesc() -- https://wiki.hoggitworld.com/view/DCS_enum_weapon
- self:I({WeaponDesc})
- --self:I("Weapon = " .. tostring(WeaponDesc.displayName))
+ self:T({WeaponDesc})
+ --self:T("Weapon = " .. tostring(WeaponDesc.displayName))
if WeaponDesc.category == 1 and (WeaponDesc.missileCategory == 1 or WeaponDesc.missileCategory == 2) then
- self:I("AAM or SAM Missile fired")
+ self:T("AAM or SAM Missile fired")
-- Missile fired
-- WIP Missile Callouts
local warndist = 25
@@ -920,8 +946,8 @@ end
-- @param #number Warndist Distance in NM to find friendly planes
-- @return #AWACS self
function AWACS:_MissileWarning(Coordinate,Type,Warndist)
- self:I(self.lid.."_MissileWarning Type="..Type.." WarnDist="..Warndist)
- self:I(UTILS.OneLineSerialize(Coordinate))
+ self:T(self.lid.."_MissileWarning Type="..Type.." WarnDist="..Warndist)
+ 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()
@@ -935,7 +961,7 @@ function AWACS:_MissileWarning(Coordinate,Type,Warndist)
if isPlayer then
local callsign = self:_GetCallSign(_grp)
local text = string.format("%s, %s! %s! %s! Defend!",callsign,Type,Type,Type)
- self:_NewRadioEntry(text, text,0,false,self.debug,true,false)
+ self:_NewRadioEntry(text, text,0,false,self.debug,true,false,true)
end
end
end
@@ -1051,6 +1077,22 @@ function AWACS:SetSRSVoiceCAP(Gender, Culture, Voice)
return self
end
+--- [User] Set AI CAP Plane Details
+-- @param #AWACS self
+-- @param #number Callsign Callsign name of AI CAP, e.g. CALLSIGN.Aircraft.Dodge. Defaults to CALLSIGN.Aircraft.Colt. Note that not all available callsigns work for all plane types.
+-- @param #number MaxAICap Maximum number of AI CAP planes on station that AWACS will set up automatically. Default to 4.
+-- @param #number TOS Time on station, in hours. AI planes might go back to base earlier if they run out of fuel or missiles.
+-- @param #number Speed Airspeed to be used in knots. Will be adjusted to flight height automatically. Defaults to 270.
+-- @return #AWACS self
+function AWACS:SetAICAPDetails(Callsign,MaxAICap,TOS,Speed)
+ self:T(self.lid.."SetAICAPDetails")
+ self.CapSpeedBase = Speed or 270
+ self.CAPTimeOnStation = TOS or 4
+ self.MaxAIonCAP = MaxAICap or 4
+ self.AICAPCAllName = Callsign or CALLSIGN.Aircraft.Colt
+ return self
+end
+
--- [User] Set AWACS Escorts Template
-- @param #AWACS self
-- @param #number EscortNumber Number of fighther planes to accompany this AWACS. 0 or nil means no escorts.
@@ -1060,6 +1102,9 @@ function AWACS:SetEscort(EscortNumber)
if EscortNumber and EscortNumber > 0 then
self.HasEscorts = true
self.EscortNumber = EscortNumber
+ else
+ self.HasEscorts = false
+ self.EscortNumber = 0
end
return self
end
@@ -1072,7 +1117,7 @@ end
-- @param #number Angels (Optional) Add Angels
-- @return #AWACS self
function AWACS:_MessageVector(GID,Tag,Coordinate,Angels)
- self:I(self.lid.."_MessageVector")
+ self:T(self.lid.."_MessageVector")
local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup
local Tag = Tag or ""
@@ -1237,8 +1282,10 @@ end
--- [Internal] Return Bullseye BR for Alpha Check etc, returns e.g. "Rock 021, 16" ("Rock" being the set BE name)
-- @param #AWACS self
-- @param Core.Point#COORDINATE Coordinate
+-- @param #boolean ssml Add SSML tag
+-- @param #boolean TTS For non-Alpha checks, hand back in format "Rock 0 2 1, 16"
-- @return #string BullseyeBR
-function AWACS:ToStringBULLS( Coordinate )
+function AWACS:ToStringBULLS( Coordinate, ssml, TTS )
-- local BullsCoordinate = COORDINATE:NewFromVec3( coalition.getMainRefPoint( self.coalition ) )
local bullseyename = self.AOName or "Rock"
--local BullsCoordinate = self.OpsZone:GetCoordinate()
@@ -1249,7 +1296,14 @@ function AWACS:ToStringBULLS( Coordinate )
local AngleDegrees = UTILS.Round( UTILS.ToDegree( AngleRadians ), 0 )
local Bearing = string.format( '%03d', AngleDegrees )
local Distance = UTILS.Round( UTILS.MetersToNM( Distance ), 0 )
- return string.format("%s %03d, %d",bullseyename,Bearing,Distance)
+ if ssml then
+ 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)
+ else
+ return string.format("%s %s, %d",bullseyename,Bearing,Distance)
+ end
end
--- [Internal] Change Bullseye string to be TTS friendly, "Bullseye 021, 16" returns e.g. "Bulls eye 0 2 1. 1 6"
@@ -1334,7 +1388,7 @@ end
-- @param #number CID Contact ID
-- @return #AWACS self
function AWACS:_UpdateContactFromCluster(CID)
- self:I(self.lid.."_UpdateContactFromCluster CID="..CID)
+ self:T(self.lid.."_UpdateContactFromCluster CID="..CID)
local existingcontact = self.Contacts:PullByID(CID) -- #AWACS.ManagedContact
local ContactTable = existingcontact.Cluster.Contacts or {}
@@ -1363,7 +1417,7 @@ end
-- @param #AWACS self
-- @return #AWACS self
function AWACS:_CleanUpContacts()
- self:I(self.lid.."_CleanUpContacts")
+ self:T(self.lid.."_CleanUpContacts")
if self.Contacts:Count() > 0 then
local deadcontacts = FIFO:New()
@@ -1372,7 +1426,7 @@ function AWACS:_CleanUpContacts()
local contact = Contact -- #AWACS.ManagedContact
if not contact.Contact.group:IsAlive() or contact.Target:IsDead() then
deadcontacts:Push(contact,contact.CID)
- self:I("DEAD contact CID="..contact.CID)
+ self:T("DEAD contact CID="..contact.CID)
end
end
)
@@ -1381,7 +1435,7 @@ function AWACS:_CleanUpContacts()
-- announce VANISHED
if deadcontacts:Count() > 0 then
- self:I("DEAD count="..deadcontacts:Count())
+ self:T("DEAD count="..deadcontacts:Count())
-- check cluster alive or announce lost
deadcontacts:ForEach(
@@ -1395,7 +1449,7 @@ function AWACS:_CleanUpContacts()
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)
+ self:_NewRadioEntry(text,textScreen,0,false,self.debug,true,false,true)
-- pull from Contacts
self.Contacts:PullByID(contact.CID)
@@ -1465,7 +1519,7 @@ end
-- @return #boolean HaveTargets True if targets could be found, else false
-- @return Utilities.FiFo#FIFO Targetselection
function AWACS:_TargetSelectionProcess(Untargeted)
- self:I(self.lid.."_TargetSelectionProcess")
+ self:T(self.lid.."_TargetSelectionProcess")
local maxtargets = 3 -- handleable number of callouts
local contactstable = self.Contacts:GetDataTable()
@@ -1474,7 +1528,7 @@ function AWACS:_TargetSelectionProcess(Untargeted)
local prefiltered = FIFO:New()
local HaveTargets = false
- self:I(self.lid.."Initial count: "..self.Contacts:Count())
+ self:T(self.lid.."Initial count: "..self.Contacts:Count())
-- Bucket sort
@@ -1489,7 +1543,7 @@ function AWACS:_TargetSelectionProcess(Untargeted)
end
)
contactstable = prefiltered:GetDataTable()
- self:I(self.lid.."Untargeted: "..prefiltered:Count())
+ self:T(self.lid.."Untargeted: "..prefiltered:Count())
end
-- Loop through
@@ -1498,18 +1552,18 @@ function AWACS:_TargetSelectionProcess(Untargeted)
local checked = false
local contactname = contact.TargetGroupNaming or "ZETA"
local typename = contact.ReportingName or "Unknown"
- self:I(self.lid..string.format("Looking at group %s type %s",contactname,typename))
+ self:T(self.lid..string.format("Looking at group %s type %s",contactname,typename))
local contactcoord = contact.Cluster.coordinate or contact.Contact.position or contact.Contact.group:GetCoordinate()
local contactvec2 = contactcoord:GetVec2()
- -- self:I({contactcoord:ToStringMGRS()})
- -- self:I({contactvec2})
+ -- self:T({contactcoord:ToStringMGRS()})
+ -- self:T({contactvec2})
-- Bucket 0 - NOT in Rejection Zone :)
if self.RejectZone then
local isinrejzone = self.RejectZone:IsVec2InZone(contactvec2)
--local distance = self.OpsZone:Get2DDistance(contactcoord)
if isinrejzone then
- self:I(self.lid.."Across Border = YES - ignore")
+ self:T(self.lid.."Across Border = YES - ignore")
--targettable:Push(contact,distance)
checked = true
end
@@ -1520,9 +1574,9 @@ function AWACS:_TargetSelectionProcess(Untargeted)
if contactcoord then
distance = HVTCoordinate:Get2DDistance(contactcoord)
end
- self:I(self.lid.."HVT Distance = "..UTILS.Round(UTILS.MetersToNM(distance),0))
+ self:T(self.lid.."HVT Distance = "..UTILS.Round(UTILS.MetersToNM(distance),0))
if UTILS.MetersToNM(distance) <= 45 and not checked then
- self:I(self.lid.."In HVT Distance = YES")
+ self:T(self.lid.."In HVT Distance = YES")
targettable:Push(contact,distance)
checked = true
end
@@ -1531,7 +1585,7 @@ function AWACS:_TargetSelectionProcess(Untargeted)
local isinopszone = self.OpsZone:IsVec2InZone(contactvec2)
local distance = self.OpsZone:Get2DDistance(contactcoord)
if isinopszone and not checked then
- self:I(self.lid.."In FEZ = YES")
+ self:T(self.lid.."In FEZ = YES")
targettable:Push(contact,distance)
checked = true
end
@@ -1539,7 +1593,7 @@ function AWACS:_TargetSelectionProcess(Untargeted)
-- Bucket 3 - in Radar(Control)Zone, < 100nm to AO, Aspect HOT on AO
local isinopszone = self.ControlZone:IsVec2InZone(contactvec2)
if isinopszone and not checked then
- self:I(self.lid.."In Radar Zone = YES")
+ self:T(self.lid.."In Radar Zone = YES")
-- Close to Bulls Eye?
local distance = self.AOCoordinate:Get2DDistance(contactcoord) -- m
local AOdist = UTILS.Round(UTILS.MetersToNM(distance),0) -- NM
@@ -1552,10 +1606,10 @@ function AWACS:_TargetSelectionProcess(Untargeted)
sizing = math.fmod((sizing * 0.1),1)
local AOdist2 = (AOdist / 2) * sizing
AOdist2 = UTILS.Round((AOdist/2)+((AOdist/2)-AOdist2), 0)
- self:I(self.lid.."Aspect = "..aspect.." | Size = "..sizing )
+ self:T(self.lid.."Aspect = "..aspect.." | Size = "..sizing )
if (AOdist2 < 75) or (aspect == "Hot") then
local text = string.format("In AO(Adj) dist = %d(%d) NM",AOdist,AOdist2)
- self:I(self.lid..text)
+ self:T(self.lid..text)
--if sizing > 2 then distance = math.floor(distance / sizing)+1 end
targettable:Push(contact,distance)
checked = true
@@ -1566,14 +1620,14 @@ function AWACS:_TargetSelectionProcess(Untargeted)
if self.BorderZone then
local isinborderzone = self.BorderZone:IsVec2InZone(contactvec2)
if isinborderzone and not checked then
- self:I(self.lid.."In BorderZone = YES")
+ self:T(self.lid.."In BorderZone = YES")
targettable:Push(contact,distance)
checked = true
end
end
end
- self:I(self.lid.."Post filter count: "..targettable:Count())
+ self:T(self.lid.."Post filter count: "..targettable:Count())
if targettable:Count() > maxtargets then
local targets = targettable:GetSortedDataTable()
@@ -1602,7 +1656,7 @@ end
-- @param #boolean IsGeneral Is a general picture, address all stations
-- @return #AWACS self
function AWACS:_CreatePicture(AO,Callsign,GID,MaxEntries,IsGeneral)
- self:I(self.lid.."_CreatePicture AO="..tostring(AO).." for "..Callsign.." GID "..GID)
+ self:T(self.lid.."_CreatePicture AO="..tostring(AO).." for "..Callsign.." GID "..GID)
local managedgroup = nil
local group = nil
@@ -1635,14 +1689,14 @@ function AWACS:_CreatePicture(AO,Callsign,GID,MaxEntries,IsGeneral)
local text = ""
local textScreen = ""
- -- " group, , BRA, for at angels , "
+ -- " group, BRA for at angels , , "
while counter < maxentries do
counter = counter + 1
local contact = fifo:Pull() -- #AWACS.ManagedContact
- self:I({contact})
+ self:T({contact})
if contact and contact.Contact.group and contact.Contact.group:IsAlive() then
--local coordinate = contact.Contact.group:GetCoordinate()
- local coordinate = contact.Cluster.coordinate or contact.Contact.position or contact.Contact.group:GetCoordinate()
+ local coordinate = contact.Cluster.coordinate or contact.Contact.position or contact.Contact.group:GetCoordinate() -- Core.Point#COORDINATE
if not coordinate then
self:E(self.lid.."NO Coordinate for this cluster! CID="..contact.CID)
self:E({contact})
@@ -1652,25 +1706,40 @@ function AWACS:_CreatePicture(AO,Callsign,GID,MaxEntries,IsGeneral)
coordinate.Heading = contact.Contact.heading or contact.Contact.group:GetHeading()
end
local refBRAA = ""
+ local refBRAATTS = ""
text = contact.TargetGroupNaming.." group." -- Alpha Group.
textScreen = contact.TargetGroupNaming.." group,"
if IsGeneral then
-- AO/BE Reference
refBRAA=self:ToStringBULLS(coordinate)
+ if self.PathToGoogleKey then
+ refBRAATTS = self:ToStringBULLS(coordinate, true)
+ else
+ --refBRAATTS = self:ToStringBullsTTS(refBRAA)
+ refBRAATTS = self:ToStringBULLS(refBRAA,false,true)
+ end
local alt = contact.Contact.group:GetAltitude() or 8000
alt = UTILS.Round(UTILS.MetersToFeet(alt)/1000,0)
- text = text .. " "..self:ToStringBullsTTS(refBRAA).." miles, "..alt.." thousand." -- Alpha Group. Bulls eye 0 2 1, 16 miles, 25 thousand.
+ -- 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) -- Charlie group, BRAA, 045, 105 miles, Angels 41, Flanking, Track North-East, Bogey, Spades.
- text = text .. " "..refBRAA
+ refBRAA = coordinate:ToStringBRAANATO(groupcoord,true,true)
+ refBRAATTS = string.gsub(refBRAA,"BRAA","brah")
+ 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)
+ end
+ 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.
@@ -1680,14 +1749,16 @@ function AWACS:_CreatePicture(AO,Callsign,GID,MaxEntries,IsGeneral)
-- sizing
local size = contact.Contact.group:CountAliveUnits()
local threatsize, threatsizetext = self:_GetBlurredSize(size)
-
- text = text.." "..threatsizetext.."." -- Alpha Group. Heavy.
- textScreen = textScreen.." "..threatsizetext..","
-
+
+ if threatsize > 1 then
+ text = text.." "..threatsizetext.."." -- Alpha Group. Heavy.
+ textScreen = textScreen.." "..threatsizetext.."."
+ end
+
-- 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.
- textScreen = textScreen .. " "..contact.EngagementTag -- Alpha Group, Bullseye 021, 16, Flanking. Singleton, Targeted by Jazz 1 1.
+ textScreen = textScreen .. " "..contact.EngagementTag -- Alpha Group, Bullseye 021, 16, Flanking. Targeted by Jazz 1 1.
end
-- Transmit Radio
@@ -1734,7 +1805,7 @@ function AWACS:_CreateBogeyDope(Callsign,GID)
while counter < maxentries do
counter = counter + 1
local contact = fifo:PullByID(sortedIDs[counter]) -- #AWACS.ManagedContact
- self:I({contact})
+ self:T({contact})
local position = contact.Cluster.coordinate or contact.Contact.position
if contact and position then
local tag = contact.TargetGroupNaming
@@ -1759,14 +1830,15 @@ function AWACS:_Picture(Group,IsGeneral)
self:T(self.lid.."_Picture")
local text = ""
local textScreen = text
+ local general = IsGeneral
local GID, Outcome, gcallsign = self:_GetManagedGrpID(Group)
--local gcallsign = ""
- if Outcome then
- IsGeneral = false
+ if Group and Outcome then
+ general = false
end
- if IsGeneral then
+ if general then
gcallsign = "All Stations"
--else
--gcallsign = self:_GetCallSign(Group,GID) or "Ghost 1"
@@ -1782,7 +1854,7 @@ function AWACS:_Picture(Group,IsGeneral)
return self
end
- if Outcome or IsGeneral then
+ if Outcome or general then
-- Pilot is checked in
-- get clusters from Intel
-- DONE Use contacts table!
@@ -1853,7 +1925,7 @@ function AWACS:_Picture(Group,IsGeneral)
end
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
- self:_CreatePicture(true,gcallsign,GID,3,IsGeneral)
+ self:_CreatePicture(true,gcallsign,GID,3,general)
self.PictureAO:Clear()
self.PictureEWR:Clear()
@@ -1982,7 +2054,7 @@ end
-- @param Wrapper.Group#GROUP Group Group to use
-- @return #AWACS self
function AWACS:_Declare(Group)
- self:I(self.lid.."_Declare")
+ self:T(self.lid.."_Declare")
local GID, Outcome, Callsign = self:_GetManagedGrpID(Group)
local text = "Declare Not yet implemented"
@@ -2049,7 +2121,7 @@ function AWACS:_Declare(Group)
text = string.format("%s. %s. %s.",Callsign,self.callsigntxt,"Clean")
TextTTS = text
end
- self:_NewRadioEntry(TextTTS,text,GID,Outcome,true,true,false)
+ self:_NewRadioEntry(TextTTS,text,GID,Outcome,true,true,false,true)
--
elseif self.AwacsFG then
-- no, unknown
@@ -2064,7 +2136,7 @@ end
-- @param Wrapper.Group#GROUP Group Group to use
-- @return #AWACS self
function AWACS:_Commit(Group)
- self:I(self.lid.."_Commit")
+ self:T(self.lid.."_Commit")
local GID, Outcome = self:_GetManagedGrpID(Group)
local text = ""
if Outcome then
@@ -2072,7 +2144,7 @@ function AWACS:_Commit(Group)
-- Get current task from the group
local currtaskid = Pilot.CurrentTask
local managedtask = self.ManagedTasks:ReadByID(currtaskid) -- #AWACS.ManagedTask
- self:I(string.format("TID %d(%d) | ToDo %s | Status %s",currtaskid,managedtask.TID,managedtask.ToDo,managedtask.Status))
+ self:T(string.format("TID %d(%d) | ToDo %s | Status %s",currtaskid,managedtask.TID,managedtask.ToDo,managedtask.Status))
if managedtask then
-- got a task, status?
if managedtask.Status == AWACS.TaskStatus.REQUESTED then
@@ -2080,7 +2152,7 @@ function AWACS:_Commit(Group)
managedtask = self.ManagedTasks:PullByID(currtaskid)
managedtask.Status = AWACS.TaskStatus.ASSIGNED
self.ManagedTasks:Push(managedtask,currtaskid)
- self:I(string.format("COMMITTED - TID %d(%d) for GID %d | ToDo %s | Status %s",currtaskid,GID,managedtask.TID,managedtask.ToDo,managedtask.Status))
+ self:T(string.format("COMMITTED - TID %d(%d) for GID %d | ToDo %s | Status %s",currtaskid,GID,managedtask.TID,managedtask.ToDo,managedtask.Status))
-- link to Pilot
Pilot.HasAssignedTask = true
Pilot.CurrentTask = currtaskid
@@ -2088,7 +2160,7 @@ function AWACS:_Commit(Group)
text = string.format("%s. %s. Copy.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
local EngagementTag = string.format("Targeted by %s.",Pilot.CallSign)
self:_UpdateContactEngagementTag(Pilot.ContactCID,EngagementTag,false,false,AWACS.TaskStatus.ASSIGNED)
- self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
+ self:_NewRadioEntry(text,text,GID,Outcome,true,true,false,true)
else
self:E(self.lid.."Cannot find REQUESTED managed task with TID="..currtaskid.." for GID="..GID)
end
@@ -2108,7 +2180,7 @@ end
-- @param Wrapper.Group#GROUP Group Group to use
-- @return #AWACS self
function AWACS:_Judy(Group)
- self:I(self.lid.."_Judy")
+ self:T(self.lid.."_Judy")
local GID, Outcome = self:_GetManagedGrpID(Group)
local text = ""
if Outcome then
@@ -2126,7 +2198,7 @@ function AWACS:_Judy(Group)
text = string.format("%s. %s. Copy.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
local EngagementTag = string.format("Targeted by %s.",Pilot.CallSign)
self:_UpdateContactEngagementTag(Pilot.ContactCID,EngagementTag,false,false,AWACS.TaskStatus.ASSIGNED)
- self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
+ self:_NewRadioEntry(text,text,GID,Outcome,true,true,false,true)
else
self:E(self.lid.."Cannot find REQUESTED or UNASSIGNED managed task with TID="..currtaskid.." for GID="..GID)
end
@@ -2146,7 +2218,7 @@ end
-- @param Wrapper.Group#GROUP Group Group to use
-- @return #AWACS self
function AWACS:_Unable(Group)
- self:I(self.lid.."_Unable")
+ self:T(self.lid.."_Unable")
local GID, Outcome = self:_GetManagedGrpID(Group)
local text = ""
if Outcome then
@@ -2154,7 +2226,7 @@ function AWACS:_Unable(Group)
-- Get current task from the group
local currtaskid = Pilot.CurrentTask
local managedtask = self.ManagedTasks:ReadByID(currtaskid) -- #AWACS.ManagedTask
- self:I(string.format("UNABLE for TID %d(%d) | ToDo %s | Status %s",currtaskid,managedtask.TID,managedtask.ToDo,managedtask.Status))
+ self:T(string.format("UNABLE for TID %d(%d) | ToDo %s | Status %s",currtaskid,managedtask.TID,managedtask.ToDo,managedtask.Status))
if managedtask then
-- got a task, status?
if managedtask.Status == AWACS.TaskStatus.REQUESTED then
@@ -2164,7 +2236,7 @@ function AWACS:_Unable(Group)
managedtask.IsUnassigned = true
managedtask.Status = AWACS.TaskStatus.UNASSIGNED
self.ManagedTasks:Push(managedtask,currtaskid)
- self:I(string.format("REJECTED - TID %d(%d) for GID %d | ToDo %s | Status %s",currtaskid,GID,managedtask.TID,managedtask.ToDo,managedtask.Status))
+ self:T(string.format("REJECTED - TID %d(%d) for GID %d | ToDo %s | Status %s",currtaskid,GID,managedtask.TID,managedtask.ToDo,managedtask.Status))
-- unlink group from task
Pilot.HasAssignedTask = false
Pilot.CurrentTask = 0
@@ -2172,7 +2244,7 @@ function AWACS:_Unable(Group)
text = string.format("%s. %s. Copy.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
local EngagementTag = ""
self:_UpdateContactEngagementTag(Pilot.ContactCID,EngagementTag,false,false,AWACS.TaskStatus.UNASSIGNED)
- self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
+ self:_NewRadioEntry(text,text,GID,Outcome,true,true,false,true)
else
self:E(self.lid.."Cannot find REQUESTED managed task with TID="..currtaskid.." for GID="..GID)
end
@@ -2192,7 +2264,7 @@ end
-- @param Wrapper.Group#GROUP Group Group to use
-- @return #AWACS self
function AWACS:_TaskAbort(Group)
- self:I(self.lid.."_TaskAbort")
+ self:T(self.lid.."_TaskAbort")
local GID, Outcome = self:_GetManagedGrpID(Group)
local text = ""
if Outcome then
@@ -2202,7 +2274,7 @@ function AWACS:_TaskAbort(Group)
local managedtask = self.ManagedTasks:ReadByID(currtaskid) -- #AWACS.ManagedTask
if managedtask then
-- got a task, status?
- self:I(string.format("ABORT for TID %d(%d) | ToDo %s | Status %s",currtaskid,managedtask.TID,managedtask.ToDo,managedtask.Status))
+ self:T(string.format("ABORT for TID %d(%d) | ToDo %s | Status %s",currtaskid,managedtask.TID,managedtask.ToDo,managedtask.Status))
if managedtask.Status == AWACS.TaskStatus.ASSIGNED then
-- ok let's commit this one
managedtask = self.ManagedTasks:PullByID(currtaskid)
@@ -2211,7 +2283,7 @@ function AWACS:_TaskAbort(Group)
managedtask.IsUnassigned = true
self.ManagedTasks:Push(managedtask,currtaskid)
-- unlink group
- self:I(string.format("ABORTED - TID %d(%d) for GID %d | ToDo %s | Status %s",currtaskid,GID,managedtask.TID,managedtask.ToDo,managedtask.Status))
+ self:T(string.format("ABORTED - TID %d(%d) for GID %d | ToDo %s | Status %s",currtaskid,GID,managedtask.TID,managedtask.ToDo,managedtask.Status))
-- unlink group from task
Pilot.HasAssignedTask = false
Pilot.CurrentTask = 0
@@ -2219,7 +2291,7 @@ function AWACS:_TaskAbort(Group)
text = string.format("%s. %s. Copy.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
local EngagementTag = ""
self:_UpdateContactEngagementTag(Pilot.ContactCID,EngagementTag,false,false,AWACS.TaskStatus.UNASSIGNED)
- self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
+ self:_NewRadioEntry(text,text,GID,Outcome,true,true,false,true)
else
self:E(self.lid.."Cannot find ASSIGNED managed task with TID="..currtaskid.." for GID="..GID)
end
@@ -2243,7 +2315,7 @@ function AWACS:_Showtask(Group)
self:T(self.lid.."_Showtask")
local GID, Outcome, Callsign = self:_GetManagedGrpID(Group)
- local text = "Showtask WIP"
+ local text = ""
if Outcome then
-- known group
@@ -2275,6 +2347,20 @@ function AWACS:_Showtask(Group)
self:I(taskreport:Text())
end
+ local pposition = managedgroup.Group:GetCoordinate() or managedgroup.LastKnownPosition
+ if currenttask.ToDo == AWACS.TaskDescription.INTERCEPT then
+ local targetpos = currenttask.Target:GetCoordinate()
+ if pposition and targetpos then
+ local alti = currenttask.Cluster.altitude or currenttask.Contact.altitude or currenttask.Contact.group:GetAltitude()
+ local direction = self:_ToStringBRA(pposition,targetpos,alti)
+ description = description .. "\nBRA "..direction
+ end
+ elseif currenttask.ToDo == AWACS.TaskDescription.ANCHOR or currenttask.ToDo == AWACS.TaskDescription.REANCHOR then
+ local targetpos = currenttask.Target:GetCoordinate()
+ local direction = self:_ToStringBR(pposition,targetpos)
+ description = description .. "\nBR "..direction
+ end
+
MESSAGE:New(string.format("%s\nStatus %s",description,status),30,"AWACS",true):ToGroup(Group)
end
@@ -2376,7 +2462,13 @@ function AWACS:_CheckInAI(FlightGroup,Group,AuftragsNr)
FlightGroup:SetDefaultRadio(self.Frequency,self.Modulation,false)
FlightGroup:SwitchRadio(self.Frequency,self.Modulation)
- FlightGroup:SetSRS(self.PathToSRS,self.CAPGender,self.CAPCulture,self.CAPVoice,self.Port,self.PathToGoogleKey,"FLIGHT")
+ local CAPVoice = self.CAPVoice
+
+ if self.PathToGoogleKey then
+ CAPVoice = AWACS.CapVoices[math.floor(math.random(1,10))]
+ end
+
+ FlightGroup:SetSRS(self.PathToSRS,self.CAPGender,self.CAPCulture,CAPVoice,self.Port,self.PathToGoogleKey,"FLIGHT")
text = string.format("%s. %s. Checking in as fragged. Expected playtime %d hours. Request Alpha Check %s.",self.callsigntxt, managedgroup.CallSign, self.CAPTimeOnStation, self.AOName)
@@ -2748,11 +2840,11 @@ function AWACS:_StartIntel(awacs)
local intel = INTEL:New(self.DetectionSet,self.coalition,self.callsigntxt)
--intel:SetVerbosity(2)
--intel:SetClusterRadius(UTILS.NMToMeters(5))
- intel:SetClusterAnalysis(true,false)
+ intel:SetClusterAnalysis(true,true,true)
local acceptzoneset = SET_ZONE:New()
acceptzoneset:AddZone(self.ControlZone)
- --acceptzoneset:AddZone(self.OpsZone)
+ acceptzoneset:AddZone(self.OpsZone)
self.OrbitZone:SetRadius(UTILS.NMToMeters(55))
acceptzoneset:AddZone(self.OrbitZone)
@@ -2868,18 +2960,27 @@ function AWACS:_ToStringBR(FromCoordinate,ToCoordinate)
local AngleDegrees = UTILS.Round( UTILS.ToDegree( AngleRadians ), 0 ) -- degrees
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
AngleDegText = string.gsub(AngleDegText,"%d","%1 ") -- "0 5 1 "
AngleDegText = string.gsub(AngleDegText," $","") -- "0 5 1"
- --local AngleTextHundred = math.abs(UTILS.Round(AngleDegrees/100,0)) -- 100s (3,0)
- --local AngleTextTens = math.abs(UTILS.Round((AngleDegrees-(AngleTextHundred*100))/10,0)) -- 10s
- --local AngleTextOnes = math.abs(AngleDegrees-(AngleTextHundred*100)-(AngleTextTens*10)) -- 1s
local Distance = ToCoordinate:Get2DDistance( FromCoordinate ) --meters
local distancenm = UTILS.Round(UTILS.MetersToNM(Distance),0)
BRText = string.format("%03d, %d miles",AngleDegrees,distancenm)
BRTextTTS = string.format("%s, %d miles",AngleDegText,distancenm)
- self:I(BRText,BRTextTTS)
+
+ if self.PathToGoogleKey then
+ BRTextTTS = string.format("%s, %d miles",AngleDegTextTTS,distancenm)
+ end
+
+ self:T(BRText,BRTextTTS)
return BRText,BRTextTTS
end
@@ -2891,7 +2992,7 @@ end
-- @return #string BRText Desired Output (BRA) "214, 35 miles, 20 thousand"
-- @return #string BRTextTTS Desired Output (BRA) "2 1 4, 35 miles, 20 thousand"
function AWACS:_ToStringBRA(FromCoordinate,ToCoordinate,Altitude)
- self:T(self.lid.."_ToStringBR")
+ self:T(self.lid.."_ToStringBRA")
local BRText = ""
local BRTextTTS = ""
local altitude = UTILS.Round(UTILS.MetersToFeet(Altitude)/1000,0)
@@ -2900,17 +3001,17 @@ 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)
AngleDegText = string.gsub(AngleDegText,"%d","%1 ") -- "0 5 1 "
AngleDegText = string.gsub(AngleDegText," $","") -- "0 5 1"
-
- --local AngleTextHundred = math.abs(UTILS.Round(AngleDegrees/100,0)) -- 100s (3,0)
- --local AngleTextTens = math.abs(UTILS.Round((AngleDegrees-(AngleTextHundred*100))/10,0)) -- 10s
- --local AngleTextOnes = math.abs(AngleDegrees-(AngleTextHundred*100)-(AngleTextTens*10)) -- 1s
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)
- self:I(BRText,BRTextTTS)
+ if self.PathToGoogleKey then
+ BRTextTTS = string.format("%s, %d miles, %d thousand",AngleDegTextTTS,distancenm,altitude)
+ end
+ self:T(BRText,BRTextTTS)
return BRText,BRTextTTS
end
@@ -3108,7 +3209,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
@@ -3240,9 +3341,47 @@ function AWACS:_CheckTaskQueue()
elseif targetstatus == "Alive" and auftrag:IsOver() then
entry.Status = AWACS.TaskStatus.FAILED
end
- else
+ elseif entry.IsPlayerTask then
-- Player task
-- TODO
+ if entry.Target:IsDead() or entry.Target:IsDestroyed() then
+ -- success!
+ entry.Status = AWACS.TaskStatus.SUCCESS
+ elseif entry.Target:IsAlive() then
+ -- still alive
+ -- out of zones?
+ local targetpos = entry.Target:GetCoordinate()
+ -- success == out of our controlled zones
+ local outofzones = false
+ self.RejectZoneSet:ForEachZone(
+ function(Zone,Position)
+ local zone = Zone -- Core.Zone#ZONE
+ local pos = Position -- Core.Point#VEC2
+ if pos and zone:IsVec2InZone(pos) then
+ -- crossed the border
+ outofzones = true
+ end
+ end,
+ targetpos:GetVec2()
+ )
+ if not outofzones then
+ outofzones = true
+ self.ZoneSet:ForEachZone(
+ function(Zone,Position)
+ local zone = Zone -- Core.Zone#ZONE
+ local pos = Position -- Core.Point#VEC2
+ if pos and zone:IsVec2InZone(pos) then
+ -- in any zone
+ outofzones = false
+ end
+ end,
+ targetpos:GetVec2()
+ )
+ end
+ if outofzones then
+ entry.Status = AWACS.TaskStatus.SUCCESS
+ end
+ end
end
if entry.Status == AWACS.TaskStatus.SUCCESS then
@@ -3359,8 +3498,8 @@ end
-- @param #string ReportingName The NATO code reporting name for the contact, e.g. "Foxbat". "Bogey" if unknown.
-- @return #AWACS self
function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,ReportingName)
- self:I(self.lid.."_AnnounceContact")
- --self:I({Contact})
+ self:T(self.lid.."_AnnounceContact")
+ --self:T({Contact})
-- do we have a group to talk to?
local tag = ""
local Tag = Tag
@@ -3369,15 +3508,15 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo
-- injected data available?
CID = Contact.CID or 0
Tag = Contact.TargetGroupNaming or ""
- --self:I({CID,Tag})
+ --self:T({CID,Tag})
end
local isGroup = false
local GID = 0
local grpcallsign = "Ghost 1"
if Group and Group:IsAlive() then
- GID, isGroup = self:_GetManagedGrpID(Group)
+ GID, isGroup,grpcallsign = self:_GetManagedGrpID(Group)
self:T("GID="..GID.." CheckedIn = "..tostring(isGroup))
- grpcallsign = self:_GetCallSign(Group,GID) or "Ghost 1"
+ --grpcallsign = self:_GetCallSign(Group,GID) or "Ghost 1"
end
local cluster = Contact.Cluster
@@ -3393,16 +3532,24 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo
clustercoordinate:SetHeading(Contact.Contact.group:GetHeading())
local BRAfromBulls, BRAfromBullsTTS = self:_GetBRAfromBullsOrAO(clustercoordinate)
+
+
self:T(BRAfromBulls)
self:T(BRAfromBullsTTS)
BRAfromBulls=BRAfromBulls.."."
BRAfromBullsTTS=BRAfromBullsTTS.."."
+
if isGroup then
BRAfromBulls = clustercoordinate:ToStringBRAANATO(Group:GetCoordinate(),true,true)
+ BRAfromBullsTTS = string.gsub(BRAfromBulls,"BRAA","brah")
+ BRAfromBullsTTS = string.gsub(BRAfromBullsTTS,"BRA","brah")
+ if self.PathToGoogleKey then
+ BRAfromBullsTTS = clustercoordinate:ToStringBRAANATO(Group:GetCoordinate(),true,true,true)
+ end
end
-
+
-- "Uzi 1-1, Magic, BRA, 183 for 10 at 2000, hot"
- -- ", , /, , BRA, for at angels , , "
+ -- ", , /, , BRA for at angels , , "
local BRAText = ""
local TextScreen = ""
@@ -3436,10 +3583,17 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo
end
end
- --BRAText = BRAText .. " "..threatsizetext..". "..BRAfromBullsTTS
- BRAText = BRAText .. " "..BRAfromBullsTTS.." "..threatsizetext.."."
- --TextScreen = TextScreen .. " "..threatsizetext..". "..BRAfromBulls
- TextScreen = TextScreen .. " "..BRAfromBulls.." "..threatsizetext.."."
+ if threatsize > 1 then
+ --BRAText = BRAText .. " "..threatsizetext..". "..BRAfromBullsTTS
+ BRAText = BRAText .. " "..BRAfromBullsTTS.." "..threatsizetext.."."
+ --TextScreen = TextScreen .. " "..threatsizetext..". "..BRAfromBulls
+ TextScreen = TextScreen .. " "..BRAfromBulls.." "..threatsizetext.."."
+ else
+ --BRAText = BRAText .. " "..threatsizetext..". "..BRAfromBullsTTS
+ BRAText = BRAText .. " "..BRAfromBullsTTS
+ --TextScreen = TextScreen .. " "..threatsizetext..". "..BRAfromBulls
+ TextScreen = TextScreen .. " "..BRAfromBulls
+ end
if self.ModernEra then
-- Platform
@@ -3466,9 +3620,12 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo
end
end
+ string.gsub(BRAText,"BRAA","brah")
+ string.gsub(BRAText,"BRA","brah")
+
--self:T(BRAText)
- self:_NewRadioEntry(BRAText,TextScreen,GID,isGroup,true,IsNew,false)
+ self:_NewRadioEntry(BRAText,TextScreen,GID,isGroup,true,IsNew,false,IsNew)
return self
end
@@ -3707,7 +3864,7 @@ function AWACS:_CheckAICAPOnStation()
report:Add("===============")
end
if self.debug then
- --self:I(report:Text())
+ --self:T(report:Text())
end
end
end
@@ -3738,8 +3895,20 @@ function AWACS:_SetAIROE(FlightGroup,Group)
-- FG level
FlightGroup:SetDefaultAlarmstate(AI.Option.Ground.val.ALARM_STATE.GREEN)
FlightGroup:SetDefaultCallsign(callname,math.fmod(self.AICAPCAllNumber,9))
- FlightGroup:SetDefaultROE(ENUMS.ROE.WeaponHold)
- FlightGroup:SetDefaultROT(ENUMS.ROT.EvadeFire)
+ if ROE == AWACS.ROE.POLICE or ROE == AWACS.ROE.VID then
+ FlightGroup:SetDefaultROE(ENUMS.ROE.WeaponHold)
+ elseif ROE == AWACS.ROE.IFF then
+ FlightGroup:SetDefaultROE(ENUMS.ROE.ReturnFire)
+ elseif ROE == AWACS.ROE.BVR then
+ FlightGroup:SetDefaultROE(ENUMS.ROE.OpenFire)
+ end
+ if ROT == AWACS.ROT.PASSIVE or ROT == AWACS.ROT.RETURNFIRE then
+ FlightGroup:SetDefaultROT(ENUMS.ROT.BypassAndEscape)
+ elseif ROT == AWACS.ROT.ACTIVE or ROT == AWACS.ROT.OPENFIRE then
+ FlightGroup:SetDefaultROT(ENUMS.ROT.EvadeFire)
+ elseif ROT == AWACS.ROT.LOCK then
+ FlightGroup:SetDefaultROT(ENUMS.ROT.PassiveDefense)
+ end
FlightGroup:SetFuelLowRTB(true)
FlightGroup:SetFuelLowThreshold(0.2)
FlightGroup:SetEngageDetectedOff()
@@ -3765,7 +3934,7 @@ function AWACS:_TACRangeCall(GID,Contact)
local distance = position:Get2DDistance(managedgroup.Group:GetCoordinate())
distance = UTILS.Round(UTILS.MetersToNM(distance)) -- 30nm - hopefully
local text = string.format("%s. %s. %s group, %d miles.",self.callsigntxt,pilotcallsign,contacttag,distance)
- self:_NewRadioEntry(text,text,GID,true,self.debug,true,false)
+ self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
self:_UpdateContactEngagementTag(Contact.CID,Contact.EngagementTag,true,false,AWACS.TaskStatus.EXECUTING)
end
end
@@ -3787,10 +3956,15 @@ function AWACS:_MeldRangeCall(GID,Contact)
local contacttag = Contact.TargetGroupNaming
if contact and not Contact.MeldCallDone then
local position = contact.position -- Core.Point#COORDINATE
- if position then
- local BRATExt = position:ToStringBRAANATO(flightpos,false,false)
+ if position then
+ local BRATExt = ""
+ if self.PathToGoogleKey then
+ BRATExt = position:ToStringBRAANATO(flightpos,false,false,true)
+ else
+ BRATExt = position:ToStringBRAANATO(flightpos,false,false)
+ end
local text = string.format("%s. %s. %s group, %s",self.callsigntxt,pilotcallsign,contacttag,BRATExt)
- self:_NewRadioEntry(text,text,GID,true,self.debug,true,false)
+ self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
self:_UpdateContactEngagementTag(Contact.CID,Contact.EngagementTag,true,true,AWACS.TaskStatus.EXECUTING)
end
end
@@ -3811,9 +3985,14 @@ function AWACS:_ThreatRangeCall(GID,Contact)
if contact then
local position = contact.position or contact.group:GetCoordinate() -- Core.Point#COORDINATE
if position then
- local BRATExt = position:ToStringBRAANATO(flightpos,false,false)
+ local BRATExt = ""
+ if self.PathToGoogleKey then
+ BRATExt = position:ToStringBRAANATO(flightpos,false,false,true)
+ else
+ BRATExt = position:ToStringBRAANATO(flightpos,false,false)
+ end
local text = string.format("%s. %s. %s group, Threat. %s",self.callsigntxt,pilotcallsign,contacttag,BRATExt)
- self:_NewRadioEntry(text,text,GID,true,self.debug,true,false)
+ self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
end
end
return self
@@ -3856,7 +4035,7 @@ function AWACS:_AssignPilotToTarget(Pilots,Targets)
end
end
- -- TODO Check Human assignment working
+ -- DONE Check Human assignment working
if inreach and Pilot and Pilot.IsPlayer then
local callsign = Pilot.CallSign
-- update pilot TaskSheet
@@ -3867,7 +4046,7 @@ function AWACS:_AssignPilotToTarget(Pilots,Targets)
local PlayerPositon = Pilot.LastKnownPosition
local TargetAlt = Target.Contact.altitude or Target.Cluster.altitude or Target.Contact.group:GetAltitude()
local TargetDirections, TargetDirectionsTTS = self:_ToStringBRA(PlayerPositon,TargetPosition,TargetAlt)
- local ScreenText = string.format("Intercept %s group.\n%s",Target.TargetGroupNaming,TargetDirections)
+ local ScreenText = string.format("Intercept %s group.",Target.TargetGroupNaming)
Pilot.CurrentTask = self:_CreateTaskForGroup(Pilot.GID,AWACS.TaskDescription.INTERCEPT,ScreenText,Target.Target,AWACS.TaskStatus.REQUESTED,nil,Target.Cluster,Target.Contact)
Pilot.ContactCID = Target.CID
@@ -3887,11 +4066,11 @@ function AWACS:_AssignPilotToTarget(Pilots,Targets)
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)
- self:_NewRadioEntry(text,textScreen,Pilot.GID,true,self.debug,true,false)
+ self:_NewRadioEntry(text,textScreen,Pilot.GID,true,self.debug,true,false,true)
local text = string.format("%s. Commit.",Pilot.CallSign)
- self:_NewRadioEntry(text,text,Pilot.GID,true,self.debug,true,true)
+ self:_NewRadioEntry(text,text,Pilot.GID,true,self.debug,true,true,true)
--self:__Intercept(2)
@@ -3910,18 +4089,8 @@ function AWACS:_AssignPilotToTarget(Pilots,Targets)
self:I("Current Mission: " .. currmission:GetType())
end
-- create one intercept Auftrag and one to return to CAP post this one
- local ZoneSet = SET_ZONE:New()
- ZoneSet:AddZone(self.ControlZone)
- ZoneSet:AddZone(self.OrbitZone)
-
- if self.BorderZone then
- ZoneSet:AddZone(self.BorderZone)
- end
-
- local RejectZoneSet = SET_ZONE:New()
- if self.RejectZone then
- RejectZoneSet:AddZone(self.RejectZone)
- end
+ local ZoneSet = self.ZoneSet
+ local RejectZoneSet = self.RejectZoneSet
local intercept = AUFTRAG:NewINTERCEPT(Target.Target)
intercept:SetWeaponExpend(AI.Task.WeaponExpend.ALL)
@@ -3936,25 +4105,31 @@ function AWACS:_AssignPilotToTarget(Pilots,Targets)
local success = true
local target = target -- Ops.Target#TARGET
if target:IsDestroyed() then return true end
- local tgtcoord = target:GetCoordinate():GetVec2()
+ local tgtcoord = target:GetCoordinate()
+ local tgtvec2 = nil
+ if tgtcoord then
+ tgtvec2 = tgtcoord:GetVec2()
+ end
local zones = zoneset -- Core.Set#SET_ZONE
local rzones = rzoneset -- Core.Set#SET_ZONE
- zones:ForEachZone(
- function(zone)
- -- BASE:I("AUFTRAG Condition Succes ZONE Eval Running")
- if zone:IsVec2InZone(tgtcoord) then
- success = false
+ if tgtvec2 then
+ zones:ForEachZone(
+ function(zone)
+ -- BASE:I("AUFTRAG Condition Succes ZONE Eval Running")
+ if zone:IsVec2InZone(tgtvec2) then
+ success = false
+ end
end
- end
- )
- rzones:ForEachZone(
- function(zone)
- -- BASE:I("AUFTRAG Condition Succes REJECT ZONE Eval Running")
- if zone:IsVec2InZone(tgtcoord) then
- success = true
+ )
+ rzones:ForEachZone(
+ function(zone)
+ -- BASE:I("AUFTRAG Condition Succes REJECT ZONE Eval Running")
+ if zone:IsVec2InZone(tgtvec2) then
+ success = true
+ end
end
- end
- )
+ )
+ end
return success
end,
Target.Target,
@@ -4015,11 +4190,11 @@ function AWACS:_AssignPilotToTarget(Pilots,Targets)
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)
- self:_NewRadioEntry(text,textScreen,Pilot.GID,true,self.debug,true,false)
+ self:_NewRadioEntry(text,textScreen,Pilot.GID,true,self.debug,true,false,true)
local text = string.format("%s. Commit.",Pilot.CallSign)
- self:_NewRadioEntry(text,text,Pilot.GID,true,self.debug,true,true)
+ self:_NewRadioEntry(text,text,Pilot.GID,true,self.debug,true,true,true)
self:__Intercept(2)
@@ -4067,6 +4242,22 @@ function AWACS:onafterStart(From, Event, To)
self.AwacsInZone = false -- not yet arrived or gone again
self.AwacsReady = false
+ local ZoneSet = SET_ZONE:New()
+ ZoneSet:AddZone(self.ControlZone)
+ ZoneSet:AddZone(self.OrbitZone)
+
+ if self.BorderZone then
+ ZoneSet:AddZone(self.BorderZone)
+ end
+
+ local RejectZoneSet = SET_ZONE:New()
+ if self.RejectZone then
+ RejectZoneSet:AddZone(self.RejectZone)
+ end
+
+ self.ZoneSet = ZoneSet
+ self.RejectZoneSet = RejectZoneSet
+
self:__Status(-30)
return self
end
@@ -4090,7 +4281,7 @@ function AWACS:_CheckAwacsStatus()
self:T(self.lid.."Arrived in Orbit Zone: " .. orbitzone:GetName())
local text = string.format("%s on station for %s control.",self.callsigntxt,self.AOName or "Rock")
local textScreen = string.format("%s on station for %s control.",self.callsigntxt,self.AOName or "Rock")
- self:_NewRadioEntry(text,textScreen,0,false,true,true,false)
+ self:_NewRadioEntry(text,textScreen,0,false,true,true,false,true)
end
end
@@ -4112,7 +4303,8 @@ function AWACS:_CheckAwacsStatus()
local alt = UTILS.Round(UTILS.MetersToFeet(awacs:GetAltitude())/1000,0)
if alt >= 10 then
local text = string.format("%s. All stations, SUNRISE SUNRISE SUNRISE, %s.",self.callsigntxt,self.callsigntxt)
- self.AwacsFG:RadioTransmission(text,1,false)
+ self:_NewRadioEntry(text,text,0,false,false,false,false,true)
+ --self.AwacsFG:RadioTransmission(text,1,false)
self:T(self.lid..text)
self.sunrisedone = true
end
@@ -4312,7 +4504,7 @@ end
-- @param #string To
-- @return #AWACS self
function AWACS:onafterStatus(From, Event, To)
- self:I({From, Event, To})
+ self:T({From, Event, To})
self:_SetClientMenus()
@@ -4471,7 +4663,7 @@ function AWACS:onafterAssignedAnchor(From, Event, To, GID, Anchor, AnchorStackNo
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 TextTasking = 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)
@@ -4507,7 +4699,7 @@ end
-- @param Ops.Intelligence#INTEL.Cluster Cluster
-- @return #AWACS self
function AWACS:onafterNewCluster(From,Event,To,Cluster)
- self:I({From, Event, To, Cluster.index})
+ self:T({From, Event, To, Cluster.index})
self.CID = self.CID + 1
self.Countactcounter = self.Countactcounter + 1
@@ -4573,7 +4765,7 @@ function AWACS:onafterNewCluster(From,Event,To,Cluster)
inborderzone = self.BorderZone:IsVec2InZone(ContactCoordinate)
end
- if incontrolzone or inborderzone or (distance <= UTILS.NMToMeters(55)) then
+ if incontrolzone or inborderzone or (distance <= UTILS.NMToMeters(55)) or IsPopup then
self:_AnnounceContact(managedcontact,true,nil,false,managedcontact.TargetGroupNaming,IsPopup,managedcontact.ReportingName)
end
@@ -4647,21 +4839,39 @@ function AWACS:onafterCheckRadioQueue(From,Event,To)
-- do we have messages queued?
local nextcall = 10
- if self.RadioQueue:IsNotEmpty() then
- local RadioEntry = self.RadioQueue:Pull() -- #AWACS.RadioEntry
+ if self.RadioQueue:IsNotEmpty() or self.PrioRadioQueue:IsNotEmpty() then
+ local RadioEntry = nil
+
+ if self.PrioRadioQueue:IsNotEmpty() then
+ RadioEntry = self.PrioRadioQueue:Pull() -- #AWACS.RadioEntry
+ else
+ RadioEntry = self.RadioQueue:Pull() -- #AWACS.RadioEntry
+ end
self:T({RadioEntry})
if not RadioEntry.FromAI then
-- AI AWACS Speaking
- self.AwacsFG:RadioTransmission(RadioEntry.TextTTS,1,false)
+ if self.PathToGoogleKey then
+ local gtext = RadioEntry.TextTTS
+ gtext = string.format("%s",gtext)
+ self.AwacsFG:RadioTransmission(gtext,1,false)
+ else
+ self.AwacsFG:RadioTransmission(RadioEntry.TextTTS,1,false)
+ end
self:T(RadioEntry.TextTTS)
else
-- CAP AI speaking
if RadioEntry.GroupID and RadioEntry.GroupID ~= 0 then
local managedgroup = self.ManagedGrps[RadioEntry.GroupID] -- #AWACS.ManagedGroup
if managedgroup and managedgroup.FlightGroup and managedgroup.FlightGroup:IsAlive() then
- managedgroup.FlightGroup:RadioTransmission(RadioEntry.TextTTS,1,false)
+ if self.PathToGoogleKey then
+ local gtext = RadioEntry.TextTTS
+ gtext = string.format("%s",gtext)
+ managedgroup.FlightGroup:RadioTransmission(gtext,1,false)
+ else
+ managedgroup.FlightGroup:RadioTransmission(RadioEntry.TextTTS,1,false)
+ end
self:T(RadioEntry.TextTTS)
end
end
@@ -4831,23 +5041,73 @@ function AWACS:onafterReAnchor(From, Event, To, GID)
[4] = "Lost contact with",
}
- -- TODO - need to save last known coordinate
+ -- DONE - need to save last known coordinate
local faded = textoptions[math.random(1,4)]
local text = string.format("All stations. %s. %s %s.",self.callsigntxt, faded, savedcallsign)
local textScreen = string.format("All stations, %s. %s %s.", self.callsigntxt, faded, savedcallsign)
local brtext = self:ToStringBULLS(managedgroup.LastKnownPosition)
- local brtexttts = self:ToStringBullsTTS(brtext)
-
+ local brtexttts = self:ToStringBULLS(brtext,false,true)
+ if self.PathToGoogleKey then
+ brtexttts = self:ToStringBULLS(managedgroup.LastKnownPosition,true)
+ end
text = text .. " "..brtexttts.." miles."
textScreen = textScreen .. " "..brtext.." miles."
- self:_NewRadioEntry(text,textScreen,0,false,self.debug,true,false)
+ self:_NewRadioEntry(text,textScreen,0,false,self.debug,true,false,true)
self.ManagedGrps[GID] = nil
end
elseif managedgroup.IsPlayer then
-- TODO
+ local PLFG = managedgroup.Group -- Wrapper.Group#GROUP
+ if PLFG and PLFG:IsAlive() then
+ -- re-establish anchor task
+ -- get anchor zone data
+ local Anchor = self.AnchorStacks:ReadByPointer(managedgroup.AnchorStackNo) -- #AWACS.AnchorData
+ local AnchorName = Anchor.StationName or "unknown"
+ local AnchorCoordTxt = Anchor.StationZoneCoordinateText or "unknown"
+ local Angels = managedgroup.AnchorStackAngels or 25
+ local AnchorSpeed = self.CapSpeedBase or 270
+ local StationZone = Anchor.StationZone -- Core.Zone#ZONE
+ local ROEROT = self.AwacsROE.." "..self.AwacsROT
+ local TextTasking = string.format("Station at %s\nAngels %d\nSpeed %d knots\nCoord %s\nROE %s",AnchorName,Angels,AnchorSpeed,AnchorCoordTxt,ROEROT)
+ managedgroup.CurrentTask = self:_CreateTaskForGroup(GID,AWACS.TaskDescription.ANCHOR,TextTasking,StationZone)
+ managedgroup.HasAssignedTask = true
+ managedgroup.ContactCID = 0
+ self.ManagedGrps[GID] = managedgroup
+ self:_MessageVector(GID," to Station",Anchor.StationZoneCoordinate,managedgroup.AnchorStackAngels)
+ else
+ -- lost group, remove from known groups, declare vanished
+ -- ALL remove from managedgrps
+ -- message loss
+ local savedcallsign = managedgroup.CallSign
+ --vanished/friendly flight faded/lost contact with C/S/CSAR Scramble
+ -- Magic, RIGHTGUARD, RIGHTGUARD, Dodge 41, Bullseye X/Y
+ local textoptions = {
+ [1] = "Lost friendly flight",
+ [2] = "Vanished friendly flight",
+ [3] = "Faded friendly contact",
+ [4] = "Lost contact with",
+ }
+
+ -- DONE - need to save last known coordinate
+ local faded = textoptions[math.random(1,4)]
+ local text = string.format("All stations. %s. %s %s.",self.callsigntxt, faded, savedcallsign)
+ local textScreen = string.format("All stations, %s. %s %s.", self.callsigntxt, faded, savedcallsign)
+
+ local brtext = self:ToStringBULLS(managedgroup.LastKnownPosition)
+ local brtexttts = self:ToStringBULLS(brtext,false,true)
+ if self.PathToGoogleKey then
+ brtexttts = self:ToStringBULLS(managedgroup.LastKnownPosition,true)
+ end
+ text = text .. " "..brtexttts.." miles."
+ textScreen = textScreen .. " "..brtext.." miles."
+
+ self:_NewRadioEntry(text,textScreen,0,false,self.debug,true,false,true)
+
+ self.ManagedGrps[GID] = nil
+ end
end
end
return self
diff --git a/Moose Development/Moose/Ops/Commander.lua b/Moose Development/Moose/Ops/Commander.lua
index 171365087..5049e05e9 100644
--- a/Moose Development/Moose/Ops/Commander.lua
+++ b/Moose Development/Moose/Ops/Commander.lua
@@ -732,9 +732,12 @@ function COMMANDER:RelocateCohort(Cohort, Legion, Delay, NcarriersMin, Ncarriers
else
for _,legion in pairs(self.legions) do
mission:AssignTransportLegion(legion)
- end
+ end
end
+ -- Set mission range very large. Mission designer should know...
+ mission:SetMissionRange(10000)
+
-- Add mission.
self:AddMission(mission)
diff --git a/Moose Development/Moose/Ops/Flotilla.lua b/Moose Development/Moose/Ops/Flotilla.lua
index 179925658..55e44e9b6 100644
--- a/Moose Development/Moose/Ops/Flotilla.lua
+++ b/Moose Development/Moose/Ops/Flotilla.lua
@@ -65,7 +65,10 @@ function FLOTILLA:New(TemplateGroupName, Ngroups, FlotillaName)
local self=BASE:Inherit(self, COHORT:New(TemplateGroupName, Ngroups, FlotillaName)) -- #FLOTILLA
-- All flotillas get mission type Nothing.
- self:AddMissionCapability(AUFTRAG.Type.NOTHING, 50)
+ self:AddMissionCapability(AUFTRAG.Type.NOTHING, 50)
+
+ -- Is naval.
+ self.isNaval=true
-- Get initial ammo.
self.ammo=self:_CheckAmmo()
diff --git a/Moose Development/Moose/Ops/Legion.lua b/Moose Development/Moose/Ops/Legion.lua
index e1339535c..66888cb66 100644
--- a/Moose Development/Moose/Ops/Legion.lua
+++ b/Moose Development/Moose/Ops/Legion.lua
@@ -499,6 +499,9 @@ function LEGION:RelocateCohort(Cohort, Legion, Delay, NcarriersMin, NcarriersMax
end
end
+ -- Set mission range very large. Mission designer should know...
+ mission:SetMissionRange(10000)
+
-- Add mission.
self:AddMission(mission)
end
diff --git a/Moose Development/Moose/Ops/NavyGroup.lua b/Moose Development/Moose/Ops/NavyGroup.lua
index 5c1cd9781..f0d5268e0 100644
--- a/Moose Development/Moose/Ops/NavyGroup.lua
+++ b/Moose Development/Moose/Ops/NavyGroup.lua
@@ -541,6 +541,10 @@ function NAVYGROUP:_CreateTurnIntoWind(starttime, stoptime, speed, uturn, offset
-- Set start time.
local Tstart=UTILS.ClockToSeconds(starttime)
+
+ if uturn==nil then
+ uturn=true
+ end
-- Set stop time.
local Tstop=Tstart+90*60
@@ -1241,8 +1245,8 @@ function NAVYGROUP:onafterTurnIntoWind(From, Event, To, IntoWind)
IntoWind.Open=true
- IntoWind.Coordinate=self:GetCoordinate()
-
+ IntoWind.Coordinate=self:GetCoordinate(true)
+
self.intowind=IntoWind
-- Wind speed in m/s.
diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua
index f8562f732..ea09416c0 100644
--- a/Moose Development/Moose/Ops/OpsGroup.lua
+++ b/Moose Development/Moose/Ops/OpsGroup.lua
@@ -2823,7 +2823,7 @@ end
--- Get next waypoint index.
-- @param #OPSGROUP self
--- @param #boolean cyclic If true, return first waypoint if last waypoint was reached. Default is patrol ad infinitum value set.
+-- @param #boolean cyclic If `true`, return first waypoint if last waypoint was reached. Default is patrol ad infinitum value set.
-- @param #number i Waypoint index from which the next index is returned. Default is the last waypoint passed.
-- @return #number Next waypoint index.
function OPSGROUP:GetWaypointIndexNext(cyclic, i)
@@ -4095,11 +4095,14 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
local wp=nil --#OPSGROUP.Waypoint
if self.isArmygroup then
self:T2(self.lid.."Routing group to spawn zone of new legion")
- wp=ARMYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Formation)
+ wp=ARMYGROUP.AddWaypoint(self, Coordinate, UTILS.KmphToKnots(self.speedCruise), currUID, Mission.optionFormation)
elseif self.isFlightgroup then
self:T2(self.lid.."Routing group to intermediate point near new legion")
Coordinate=self:GetCoordinate():GetIntermediateCoordinate(Coordinate, 0.8)
wp=FLIGHTGROUP.AddWaypoint(self, Coordinate, UTILS.KmphToKnots(self.speedCruise), currUID, UTILS.MetersToFeet(self.altitudeCruise))
+ elseif self.isNavygroup then
+ self:T2(self.lid.."Routing group to spawn zone of new legion")
+ wp=NAVYGROUP.AddWaypoint(self, Coordinate, UTILS.KmphToKnots(self.speedCruise), currUID)
else
end
@@ -5016,9 +5019,9 @@ function OPSGROUP:onafterMissionDone(From, Event, To, Mission)
-- Emission to default.
if Mission.optionEmission then
self:SwitchEmission()
- end
+ end
-- Formation to default.
- if Mission.optionFormation then
+ if Mission.optionFormation and self:IsFlightgroup() then
self:SwitchFormation()
end
-- Radio freq and modu to default.
@@ -5130,6 +5133,17 @@ function OPSGROUP:RouteToMission(mission, delay)
-- Ingress waypoint coordinate where the mission is executed.
local waypointcoord=nil --Core.Point#COORDINATE
+ -- Current coordinate of the group.
+ local currentcoord=self:GetCoordinate()
+
+ -- Road connection.
+ local roadcoord=currentcoord:GetClosestPointToRoad()
+
+ local roaddist=nil
+ if roadcoord then
+ roaddist=currentcoord:Get2DDistance(roadcoord)
+ end
+
-- Target zone.
local targetzone=nil --Core.Zone#ZONE
@@ -5215,14 +5229,23 @@ function OPSGROUP:RouteToMission(mission, delay)
---
-- Roughly go to the new legion.
- local ToCoordinate=mission.DCStask.params.legion:GetCoordinate()
+ local ToCoordinate=mission.DCStask.params.legion:GetCoordinate()
if self.isFlightgroup then
- waypointcoord=self:GetCoordinate():GetIntermediateCoordinate(ToCoordinate, 0.2):SetAltitude(self.altitudeCruise)
+ -- Get mission waypoint coord in direction of the
+ waypointcoord=currentcoord:GetIntermediateCoordinate(ToCoordinate, 0.2):SetAltitude(self.altitudeCruise)
+ elseif self.isArmygroup then
+ -- Army group: check for road connection.
+ if roadcoord then
+ waypointcoord=roadcoord
+ else
+ waypointcoord=currentcoord:GetIntermediateCoordinate(ToCoordinate, 100)
+ end
else
- waypointcoord=self:GetCoordinate():GetIntermediateCoordinate(ToCoordinate, 0.05)
+ -- Navy group: Route into direction of the target.
+ waypointcoord=currentcoord:GetIntermediateCoordinate(ToCoordinate, 0.05)
end
-
+
elseif mission.type==AUFTRAG.Type.RECOVERYTANKER then
---
-- Recoverytanker
@@ -5356,12 +5379,16 @@ function OPSGROUP:RouteToMission(mission, delay)
end
- -- Add waypoint.
+ -- Add mission execution (ingress) waypoint.
local waypoint=nil --#OPSGROUP.Waypoint
if self:IsFlightgroup() then
waypoint=FLIGHTGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, UTILS.MetersToFeet(mission.missionAltitude or self.altitudeCruise), false)
elseif self:IsArmygroup() then
- waypoint=ARMYGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, mission.optionFormation, false)
+ local formation=mission.optionFormation
+ if mission.type==AUFTRAG.Type.RELOCATECOHORT then
+ formation=ENUMS.Formation.Vehicle.OffRoad
+ end
+ waypoint=ARMYGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, formation, false)
elseif self:IsNavygroup() then
waypoint=NAVYGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, UTILS.MetersToFeet(mission.missionAltitude or self.altitudeCruise), false)
end
@@ -5380,8 +5407,6 @@ function OPSGROUP:RouteToMission(mission, delay)
-- Add egress waypoint.
local egresscoord=mission:GetMissionEgressCoord()
if egresscoord then
- --egresscoord:MarkToAll(string.format("Egress Mission %s alt=%d m", mission:GetName(), waypointcoord.y))
- -- Add waypoint.
local Ewaypoint=nil --#OPSGROUP.Waypoint
if self:IsFlightgroup() then
Ewaypoint=FLIGHTGROUP.AddWaypoint(self, egresscoord, SpeedToMission, waypoint.uid, UTILS.MetersToFeet(mission.missionAltitude or self.altitudeCruise), false)
@@ -5394,12 +5419,9 @@ function OPSGROUP:RouteToMission(mission, delay)
mission:SetGroupEgressWaypointUID(self, Ewaypoint.uid)
end
-
- -- Get current pos.
- local coord=self:GetCoordinate()
-- Distance to waypoint coordinate.
- local d=coord:Get2DDistance(waypointcoord)
+ local d=currentcoord:Get2DDistance(waypointcoord)
-- Debug info.
self:T(self.lid..string.format("FF distance to ingress waypoint=%.1f m", d))
@@ -5787,6 +5809,8 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint)
self:_PassedFinalWaypoint(true, "PassingWaypoint: adinfinitum but only ONE WAYPOINT left")
else
+ --[[ Solved now!
+
-- Looks like the passing waypoint function is triggered over and over again if the group is near the final waypoint.
-- So the only good solution is to guide the group away from that waypoint and then update the route.
@@ -5795,9 +5819,19 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint)
-- Get a waypoint
local Coordinate=Waypoint.coordinate:GetIntermediateCoordinate(wp1.coordinate, 0.1)
-
- -- Detour to the temp waypoint. When reached, the normal route is resumed.
- self:Detour(Coordinate, self.speedCruise, nil, true)
+
+ local formation=nil
+ if self.isArmygroup then
+ formation=ENUMS.Formation.Vehicle.OffRoad
+ end
+
+ self:Detour(Coordinate, self.speedCruise, formation, true)
+
+ ]]
+
+
+ -- Send
+ self:__UpdateRoute(-0.01, 1, 1)
end
end
@@ -5809,6 +5843,27 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint)
-- Final waypoint reached.
self:_PassedFinalWaypoint(true, "PassingWaypoint: wpindex=#self.waypoints (or wpindex=nil)")
end
+
+ elseif wpindex==1 then
+
+ -- Ad infinitum and not mission waypoint?
+ if self.adinfinitum then
+ ---
+ -- Ad Infinitum
+ ---
+
+ if #self.waypoints<=1 then
+ -- Only one waypoint. Ad infinitum does not really make sense. However, another waypoint could be added later...
+ self:_PassedFinalWaypoint(true, "PassingWaypoint: adinfinitum but only ONE WAYPOINT left")
+
+ else
+
+ if not Waypoint.missionUID then
+ -- Redo the route until the end.
+ self:__UpdateRoute(-0.01, 2)
+ end
+ end
+ end
end
@@ -9709,6 +9764,11 @@ function OPSGROUP:_CheckStuck()
-- Debug warning.
self:T(self.lid..string.format("WARNING: Group came to an unexpected standstill. Speed=%.1f<%.1f m/s expected for %d sec", speed, ExpectedSpeed, holdtime))
+
+ if self.legion then
+ self:T(self.lid..string.format("Asset is returned to its legion after being stuck!"))
+ self:ReturnToLegion()
+ end
end
diff --git a/Moose Development/Moose/Ops/Platoon.lua b/Moose Development/Moose/Ops/Platoon.lua
index 405cb2268..c262ff4a5 100644
--- a/Moose Development/Moose/Ops/Platoon.lua
+++ b/Moose Development/Moose/Ops/Platoon.lua
@@ -65,6 +65,9 @@ function PLATOON:New(TemplateGroupName, Ngroups, PlatoonName)
-- All platoons get mission type Nothing.
self:AddMissionCapability(AUFTRAG.Type.NOTHING, 50)
+
+ -- Is ground.
+ self.isGround=true
-- Get ammo.
self.ammo=self:_CheckAmmo()
diff --git a/Moose Development/Moose/Ops/Squadron.lua b/Moose Development/Moose/Ops/Squadron.lua
index 43d3c7a22..e720de2cc 100644
--- a/Moose Development/Moose/Ops/Squadron.lua
+++ b/Moose Development/Moose/Ops/Squadron.lua
@@ -102,6 +102,9 @@ function SQUADRON:New(TemplateGroupName, Ngroups, SquadronName)
-- Everyone can ORBIT.
self:AddMissionCapability(AUFTRAG.Type.ORBIT)
+
+ -- Is air.
+ self.isAir=true
-- Refueling system.
self.refuelSystem=select(2, self.templategroup:GetUnit(1):IsRefuelable())
diff --git a/Moose Development/Moose/Sound/SRS.lua b/Moose Development/Moose/Sound/SRS.lua
index eabaad197..cafb49c7c 100644
--- a/Moose Development/Moose/Sound/SRS.lua
+++ b/Moose Development/Moose/Sound/SRS.lua
@@ -96,6 +96,14 @@
-- For more information on setting up a cloud account, visit: https://cloud.google.com/text-to-speech
-- Google's supported SSML reference: https://cloud.google.com/text-to-speech/docs/ssml
--
+-- **NOTE on using GOOGLE TTS with SRS:** You need to have the C# library installed in your SRS folder for Google to work.
+-- You can obtain it e.g. here: [NuGet](https://www.nuget.org/packages/Grpc.Core)
+--
+-- **Pro-Tipp** - use the command line with power shell to call DCS-SR-ExternalAudio.exe - it will tell you what is missing.
+-- and also the Google Console error, in case you have missed a step in setting up your Google TTS.
+-- E.g. `.\DCS-SR-ExternalAudio.exe -t "Text Message" -f 255 -m AM -c 2 -s 2 -z -G "Path_To_You_Google.Json"`
+-- Plays a message on 255AM for the blue coalition in-game.
+--
-- ## Set Voice
--
-- Use a specifc voice with the @{#MSRS.SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
diff --git a/Moose Development/Moose/Wrapper/Positionable.lua b/Moose Development/Moose/Wrapper/Positionable.lua
index 66df70473..203c8042f 100644
--- a/Moose Development/Moose/Wrapper/Positionable.lua
+++ b/Moose Development/Moose/Wrapper/Positionable.lua
@@ -1625,6 +1625,10 @@ do -- Cargo
["Ural-4320T"] = 14,
["ZBD04A"] = 7, -- new by kappa
["VAB_Mephisto"] = 8, -- new by Apple
+ ["tt_KORD"] = 6, -- 2.7.1 HL/TT
+ ["tt_DSHK"] = 6,
+ ["HL_KORD"] = 6,
+ ["HL_DSHK"] = 6,
}
-- Assuming that each passenger weighs 95 kg on average.