Merge branch 'develop' into FF/Ops

This commit is contained in:
Frank
2024-01-16 17:11:16 +01:00
23 changed files with 696 additions and 387 deletions

View File

@@ -3062,7 +3062,7 @@ function AIRBOSS:EnableSRS(PathToSRS,Port,Culture,Gender,Voice,GoogleCreds,Volum
-- SRS
local Frequency = self.AirbossRadio.frequency
local Modulation = self.AirbossRadio.modulation
self.SRS = MSRS:New(PathToSRS,Frequency,Modulation,Volume,AltBackend)
self.SRS = MSRS:New(PathToSRS,Frequency,Modulation,AltBackend)
self.SRS:SetCoalition(self:GetCoalition())
self.SRS:SetCoordinate(self:GetCoordinate())
self.SRS:SetCulture(Culture or "en-US")
@@ -3072,10 +3072,11 @@ function AIRBOSS:EnableSRS(PathToSRS,Port,Culture,Gender,Voice,GoogleCreds,Volum
self.SRS:SetPort(Port or 5002)
self.SRS:SetLabel(self.AirbossRadio.alias or "AIRBOSS")
self.SRS:SetCoordinate(self.carrier:GetCoordinate())
self.SRS:SetVolume(Volume)
self.SRS:SetVolume(Volume or 1)
--self.SRS:SetModulations(Modulations)
if GoogleCreds then
self.SRS:SetGoogle(GoogleCreds)
self.SRS:SetProviderOptionsGoogle(GoogleCreds,GoogleCreds)
self.SRS:SetProvider(MSRS.Provider.GOOGLE)
end
if Voice then
self.SRS:SetVoice(Voice)

View File

@@ -434,6 +434,7 @@ _AUFTRAGSNR=0
-- @field #string ARMORATTACK Armor attack.
-- @field #string CASENHANCED Enhanced CAS.
-- @field #string HOVER Hover.
-- @field #string LANDATCOORDINATE Land at coordinate.
-- @field #string GROUNDATTACK Ground attack.
-- @field #string CARGOTRANSPORT Cargo transport.
-- @field #string RELOCATECOHORT Relocate a cohort from one legion to another.
@@ -480,6 +481,7 @@ AUFTRAG.Type={
ARMORATTACK="Armor Attack",
CASENHANCED="CAS Enhanced",
HOVER="Hover",
LANDATCOORDINATE="Land at Coordinate",
GROUNDATTACK="Ground Attack",
CARGOTRANSPORT="Cargo Transport",
RELOCATECOHORT="Relocate Cohort",
@@ -1052,6 +1054,42 @@ function AUFTRAG:NewHOVER(Coordinate, Altitude, Time, Speed, MissionAlt)
return mission
end
--- **[AIR ROTARY]** Create an LANDATCOORDINATE mission.
-- @param #AUFTRAG self
-- @param Core.Point#COORDINATE Coordinate Where to land.
-- @param #number OuterRadius (Optional) Vary the coordinate by this many feet, e.g. get a new random coordinate between OuterRadius and (optionally) avoiding InnerRadius of the coordinate.
-- @param #number InnerRadius (Optional) Vary the coordinate by this many feet, e.g. get a new random coordinate between OuterRadius and (optionally) avoiding InnerRadius of the coordinate.
-- @param #number Time Time in seconds to stay. Default 300 seconds.
-- @param #number Speed Speed in knots to fly to the target coordinate. Default 150kn.
-- @param #number MissionAlt Altitude to fly towards the mission in feet AGL. Default 1000ft.
-- @return #AUFTRAG self
function AUFTRAG:NewLANDATCOORDINATE(Coordinate, OuterRadius, InnerRadius, Time, Speed, MissionAlt)
local mission=AUFTRAG:New(AUFTRAG.Type.LANDATCOORDINATE)
mission:_TargetFromObject(Coordinate)
mission.stayTime = Time or 300
mission.stayAt = Coordinate
self:SetMissionSpeed(Speed or 150)
self:SetMissionAltitude(MissionAlt or 1000)
if OuterRadius then
mission.stayAt = Coordinate:GetRandomCoordinateInRadius(UTILS.FeetToMeters(OuterRadius),UTILS.FeetToMeters(InnerRadius or 0))
end
-- Mission options:
mission.missionFraction=0.9
mission.optionROE=ENUMS.ROE.ReturnFire
mission.optionROT=ENUMS.ROT.PassiveDefense
mission.categories={AUFTRAG.Category.HELICOPTER}
mission.DCStask=mission:GetDCSMissionTask()
return mission
end
--- **[AIR]** Create an enhanced orbit race track mission. Planes will keep closer to the track.
-- @param #AUFTRAG self
-- @param Core.Point#COORDINATE Coordinate Where to start the race track.
@@ -6443,7 +6481,19 @@ function AUFTRAG:GetDCSMissionTask()
param.missionAltitude = self.missionAltitude
DCStask.params=param
table.insert(DCStasks, DCStask)
elseif self.type==AUFTRAG.Type.LANDATCOORDINATE then
---------------------
-- LANDATCOORDINATE Mission
---------------------
local DCStask={}
local Vec2 = self.stayAt:GetVec2()
local DCStask = CONTROLLABLE.TaskLandAtVec2(nil,Vec2,self.stayTime)
table.insert(DCStasks, DCStask)
elseif self.type==AUFTRAG.Type.ONGUARD or self.type==AUFTRAG.Type.ARMOREDGUARD then

View File

@@ -3001,6 +3001,9 @@ function AWACS:_Picture(Group,IsGeneral)
if clustersAO == 0 and clustersEWR == 0 then
-- clean
local picclean = self.gettext:GetEntry("PICCLEAN",self.locale)
text = string.format(picclean,gcallsign,self.callsigntxt)
textScreen = text
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
else

View File

@@ -293,7 +293,7 @@ CSAR.AircraftType["Bronco-OV-10A"] = 2
--- CSAR class version.
-- @field #string version
CSAR.version="1.0.18"
CSAR.version="1.0.19"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list
@@ -536,6 +536,7 @@ function CSAR:New(Coalition, Template, Alias)
-- @param #number Frequency Beacon frequency in kHz.
-- @param #string Leadername Name of the #UNIT of the downed pilot.
-- @param #string CoordinatesText String of the position of the pilot. Format determined by self.coordtype.
-- @param #string Playername Player name if any given. Might be nil!
--- On After "Aproach" event. Heli close to downed Pilot.
-- @function [parent=#CSAR] OnAfterApproach
@@ -842,7 +843,7 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
self:_CreateDownedPilotTrack(_spawnedGroup,_GroupName,_coalition,_unitName,_text,_typeName,_freq,_playerName,wetfeet)
self:_InitSARForPilot(_spawnedGroup, _unitName, _freq, noMessage) --shagrat use unitName to have the aircraft callsign / descriptive "name" etc.
self:_InitSARForPilot(_spawnedGroup, _unitName, _freq, noMessage, _playerName) --shagrat use unitName to have the aircraft callsign / descriptive "name" etc.
return self
end
@@ -1224,7 +1225,8 @@ end
-- @param #string _GroupName Name of the Group
-- @param #number _freq Beacon frequency.
-- @param #boolean _nomessage Send message true or false.
function CSAR:_InitSARForPilot(_downedGroup, _GroupName, _freq, _nomessage)
-- @param #string _playername Name of the downed pilot if any
function CSAR:_InitSARForPilot(_downedGroup, _GroupName, _freq, _nomessage, _playername)
self:T(self.lid .. " _InitSARForPilot")
local _leader = _downedGroup:GetUnit(1)
local _groupName = _GroupName
@@ -1247,7 +1249,7 @@ function CSAR:_InitSARForPilot(_downedGroup, _GroupName, _freq, _nomessage)
end
-- trigger FSM event
self:__PilotDown(2,_downedGroup, _freqk, _groupName, _coordinatesText)
self:__PilotDown(2,_downedGroup, _freqk, _groupName, _coordinatesText, _playername)
return self
end
@@ -1923,7 +1925,7 @@ function CSAR:_DisplayToAllSAR(_message, _side, _messagetime)
local messagetime = _messagetime or self.messageTime
if self.msrs then
local voice = self.CSARVoice or MSRS.Voices.Google.Standard.en_GB_Standard_F
if self.msrs.google == nil then
if self.msrs:GetProvider() == MSRS.Provider.WINDOWS then
voice = self.CSARVoiceMS or MSRS.Voices.Microsoft.Hedda
end
self:I("Voice = "..voice)
@@ -2310,7 +2312,8 @@ function CSAR:onafterStart(From, Event, To)
self.msrs:SetVoice(self.SRSVoice)
self.msrs:SetGender(self.SRSGender)
if self.SRSGPathToCredentials then
self.msrs:SetGoogle(self.SRSGPathToCredentials)
self.msrs:SetProviderOptionsGoogle(self.SRSGPathToCredentials,self.SRSGPathToCredentials)
self.msrs:SetProvider(MSRS.Provider.GOOGLE)
end
self.msrs:SetVolume(self.SRSVolume)
self.msrs:SetLabel("CSAR")
@@ -2542,8 +2545,9 @@ end
-- @param #number Frequency Beacon frequency in kHz.
-- @param #string Leadername Name of the #UNIT of the downed pilot.
-- @param #string CoordinatesText String of the position of the pilot. Format determined by self.coordtype.
function CSAR:onbeforePilotDown(From, Event, To, Group, Frequency, Leadername, CoordinatesText)
self:T({From, Event, To, Group, Frequency, Leadername, CoordinatesText})
-- @param #string Playername Player name if any given. Might be nil!
function CSAR:onbeforePilotDown(From, Event, To, Group, Frequency, Leadername, CoordinatesText, Playername)
self:T({From, Event, To, Group, Frequency, Leadername, CoordinatesText, tostring(Playername)})
return self
end

View File

@@ -1744,7 +1744,7 @@ end
function CTLD:_GenerateUHFrequencies()
self:T(self.lid .. " _GenerateUHFrequencies")
self.FreeUHFFrequencies = {}
self.FreeUHFFrequencies = UTILS.GenerateUHFrequencies()
self.FreeUHFFrequencies = UTILS.GenerateUHFrequencies(243,320)
return self
end

View File

@@ -47,7 +47,6 @@
-- @field #number capalt
-- @field #number capdir
-- @field #number capleg
-- @field #number capgrouping
-- @field #number maxinterceptsize
-- @field #number missionrange
-- @field #number noaltert5
@@ -65,6 +64,7 @@
-- @field #boolean Monitor
-- @field #boolean TankerInvisible
-- @field #number CapFormation
-- @field #table ReadyFlightGroups
-- @extends Core.Fsm#FSM
--- *“Airspeed, altitude, and brains. Two are always needed to successfully complete the flight.”* -- Unknown.
@@ -190,7 +190,6 @@ EASYGCICAP = {
capalt = 25000,
capdir = 45,
capleg = 15,
capgrouping = 2,
maxinterceptsize = 2,
missionrange = 100,
noaltert5 = 4,
@@ -209,6 +208,7 @@ EASYGCICAP = {
Monitor = false,
TankerInvisible = true,
CapFormation = nil,
ReadyFlightGroups = {},
}
--- Internal Squadron data type
@@ -244,7 +244,7 @@ EASYGCICAP = {
--- EASYGCICAP class version.
-- @field #string version
EASYGCICAP.version="0.0.9"
EASYGCICAP.version="0.1.10"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@@ -258,10 +258,10 @@ EASYGCICAP.version="0.0.9"
--- Create a new GCICAP Manager
-- @param #EASYGCICAP self
-- @param #string Alias
-- @param #string AirbaseName
-- @param #string Coalition
-- @param #string EWRName
-- @param #string Alias A Name for this GCICAP
-- @param #string AirbaseName Name of the Home Airbase
-- @param #string Coalition Coalition, e.g. "blue" or "red"
-- @param #string EWRName (Partial) group name of the EWR system of the coalition, e.g. "Red EWR"
-- @return #EASYGCICAP self
function EASYGCICAP:New(Alias, AirbaseName, Coalition, EWRName)
-- Inherit everything from FSM class.
@@ -321,6 +321,7 @@ end
-- @param #number Formation Formation to fly, defaults to ENUMS.Formation.FixedWing.FingerFour.Group
-- @return #EASYGCICAP self
function EASYGCICAP:SetCAPFormation(Formation)
self:T(self.lid.."SetCAPFormation")
self.CapFormation = Formation
return self
end
@@ -428,7 +429,7 @@ end
--- Set default number of airframes standing by for intercept tasks (visible on the airfield)
-- @param #EASYGCICAP self
-- @param #number Airframes defaults to 2
-- @return #EASYGCICAP selfAirframes
-- @return #EASYGCICAP self
function EASYGCICAP:SetDefaultNumberAlter5Standby(Airframes)
self:T(self.lid.."SetDefaultNumberAlter5Standby")
self.noaltert5 = math.abs(Airframes) or 2
@@ -438,13 +439,25 @@ end
--- Set default engage range for intruders detected by CAP flights in NM.
-- @param #EASYGCICAP self
-- @param #number Range defaults to 50NM
-- @return #EASYGCICAP selfAirframes
-- @return #EASYGCICAP self
function EASYGCICAP:SetDefaultEngageRange(Range)
self:T(self.lid.."SetDefaultNumberAlter5Standby")
self.engagerange = Range or 50
return self
end
--- Set default overhead for intercept calculations
-- @param #EASYGCICAP self
-- @param #number Overhead The overhead to use.
-- @return #EASYGCICAP self
-- @usage Either a CAP Plane or a newly spawned GCI plane will take care of intruders. Standard overhead is 0.75, i.e. a group of 3 intrudes will
-- be managed by 2 planes from the assigned AirWing. There is an maximum missions limitation per AirWing, so we do not spam the skies.
function EASYGCICAP:SetDefaultOverhead(Overhead)
self:T(self.lid.."SetDefaultOverhead")
self.overhead = Overhead or 0.75
return self
end
--- Add an AirWing to the manager
-- @param #EASYGCICAP self
-- @param #string Airbasename
@@ -491,7 +504,7 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias)
-- Create Airwing
local CAP_Wing = AIRWING:New(Airbasename,Alias)
CAP_Wing:SetVerbosityLevel(3)
CAP_Wing:SetVerbosityLevel(0)
CAP_Wing:SetReportOff()
CAP_Wing:SetMarker(false)
CAP_Wing:SetAirbase(AIRBASE:FindByName(Airbasename))
@@ -528,6 +541,7 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias)
flightgroup:SetDespawnAfterHolding()
flightgroup:SetDestinationbase(AIRBASE:FindByName(Airbasename))
flightgroup:GetGroup():CommandEPLRS(true,5)
flightgroup:GetGroup():SetOptionRadarUsingForContinousSearch()
if Mission.type ~= AUFTRAG.Type.TANKER and Mission.type ~= AUFTRAG.Type.AWACS and Mission.type ~= AUFTRAG.Type.RECON then
flightgroup:SetDetection(true)
flightgroup:SetEngageDetectedOn(self.engagerange,{"Air"},self.GoZoneSet,self.NoGoZoneSet)
@@ -548,7 +562,7 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias)
flightgroup:SetFuelLowRTB(true)
Intel:AddAgent(flightgroup)
function flightgroup:OnAfterHolding(From,Event,To)
self:ClearToLand(5)
self:Despawn(1,true)
end
end
@@ -1045,6 +1059,172 @@ function EASYGCICAP:AddRejectZone(Zone)
return self
end
--- (Internal) Try to assign the intercept to a FlightGroup already in air and ready.
-- @param #EASYGCICAP self
-- @param #table ReadyFlightGroups ReadyFlightGroups
-- @param Ops.Auftrag#AUFTRAG InterceptAuftrag The Auftrag
-- @param Wrapper.Group#GROUP Group The Target
-- @param #number WingSize Calculated number of Flights
-- @return #boolean assigned
-- @return #number leftover
function EASYGCICAP:_TryAssignIntercept(ReadyFlightGroups,InterceptAuftrag,Group,WingSize)
self:I("_TryAssignIntercept for size "..WingSize or 1)
local assigned = false
local wingsize = WingSize or 1
local mindist = 0
local disttable = {}
if Group and Group:IsAlive() then
local gcoord = Group:GetCoordinate() or COORDINATE:New(0,0,0)
self:I(self.lid..string.format("Assignment for %s",Group:GetName()))
for _name,_FG in pairs(ReadyFlightGroups or {}) do
local FG = _FG -- Ops.FlightGroup#FLIGHTGROUP
local fcoord = FG:GetCoordinate()
local dist = math.floor(UTILS.Round(fcoord:Get2DDistance(gcoord)/1000,1))
self:I(self.lid..string.format("FG %s Distance %dkm",_name,dist))
disttable[#disttable+1] = { FG=FG, dist=dist}
if dist>mindist then mindist=dist end
end
local function sortDistance(a, b)
return a.dist < b.dist
end
table.sort(disttable, sortDistance)
for _,_entry in ipairs(disttable) do
local FG = _entry.FG -- Ops.FlightGroup#FLIGHTGROUP
FG:AddMission(InterceptAuftrag)
local cm = FG:GetMissionCurrent()
if cm then cm:Cancel() end
wingsize = wingsize - 1
self:I(self.lid..string.format("Assigned to FG %s Distance %dkm",FG:GetName(),_entry.dist))
if wingsize == 0 then
assigned = true
break
end
end
end
return assigned, wingsize
end
--- Add a zone to the rejected zones set.
-- @param #EASYGCICAP self
-- @param Ops.Intelligence#INTEL.Cluster Cluster
-- @return #EASYGCICAP self
function EASYGCICAP:_AssignIntercept(Cluster)
-- Here, we'll decide if we need to launch an intercepting flight, and from where
local overhead = self.overhead
local capspeed = self.capspeed + 100
local capalt = self.capalt
local maxsize = self.maxinterceptsize
local repeatsonfailure = self.repeatsonfailure
local wings = self.wings
local ctlpts = self.ManagedCP
local MaxAliveMissions = self.MaxAliveMissions * self.capgrouping
local nogozoneset = self.NoGoZoneSet
local ReadyFlightGroups = self.ReadyFlightGroups
-- Aircraft?
if Cluster.ctype ~= INTEL.Ctype.AIRCRAFT then return end
-- Threatlevel 0..10
local contact = self.Intel:GetHighestThreatContact(Cluster)
local name = contact.groupname --#string
local threat = contact.threatlevel --#number
local position = self.Intel:CalcClusterFuturePosition(Cluster,300)
-- calculate closest zone
local bestdistance = 2000*1000 -- 2000km
local targetairwing = nil -- Ops.AirWing#AIRWING
local targetawname = "" -- #string
local clustersize = self.Intel:ClusterCountUnits(Cluster) or 1
local wingsize = math.abs(overhead * (clustersize+1))
if wingsize > maxsize then wingsize = maxsize end
-- existing mission, and if so - done?
local retrymission = true
if Cluster.mission and (not Cluster.mission:IsOver()) then
retrymission = false
end
if (retrymission) and (wingsize >= 1) then
MESSAGE:New(string.format("**** %s Interceptors need wingsize %d", UTILS.GetCoalitionName(self.coalition), wingsize),15,"CAPGCI"):ToAllIf(self.debug):ToLog()
for _,_data in pairs (wings) do
local airwing = _data[1] -- Ops.AirWing#AIRWING
local zone = _data[2] -- Core.Zone#ZONE
local zonecoord = zone:GetCoordinate()
local name = _data[3] -- #string
local distance = position:DistanceFromPointVec2(zonecoord)
local airframes = airwing:CountAssets(true)
if distance < bestdistance and airframes >= wingsize then
bestdistance = distance
targetairwing = airwing
targetawname = name
end
end
for _,_data in pairs (ctlpts) do
--local airwing = _data[1] -- Ops.AirWing#AIRWING
--local zone = _data[2] -- Core.Zone#ZONE
--local zonecoord = zone:GetCoordinate()
--local name = _data[3] -- #string
local data = _data -- #EASYGCICAP.CapPoint
local name = data.AirbaseName
local zonecoord = data.Coordinate
local airwing = wings[name][1]
local distance = position:DistanceFromPointVec2(zonecoord)
local airframes = airwing:CountAssets(true)
if distance < bestdistance and airframes >= wingsize then
bestdistance = distance
targetairwing = airwing -- Ops.AirWing#AIRWING
targetawname = name
end
end
local text = string.format("Closest Airwing is %s", targetawname)
local m = MESSAGE:New(text,10,"CAPGCI"):ToAllIf(self.debug):ToLog()
-- Do we have a matching airwing?
if targetairwing then
local AssetCount = targetairwing:CountAssetsOnMission(MissionTypes,Cohort)
-- Enough airframes on mission already?
self:T(self.lid.." Assets on Mission "..AssetCount)
if AssetCount <= MaxAliveMissions then
local repeats = repeatsonfailure
local InterceptAuftrag = AUFTRAG:NewINTERCEPT(contact.group)
:SetMissionRange(150)
:SetPriority(1,true,1)
--:SetRequiredAssets(wingsize)
:SetRepeatOnFailure(repeats)
:SetMissionSpeed(UTILS.KnotsToAltKIAS(capspeed,capalt))
:SetMissionAltitude(capalt)
if nogozoneset:Count() > 0 then
InterceptAuftrag:AddConditionSuccess(
function(group,zoneset)
local success = false
if group and group:IsAlive() then
local coord = group:GetCoordinate()
if coord and zoneset:IsCoordinateInZone(coord) then
success = true
end
end
return success
end,
contact.group,
nogozoneset
)
end
local assigned, rest = self:_TryAssignIntercept(ReadyFlightGroups,InterceptAuftrag,contact.group,wingsize)
if not assigned then
InterceptAuftrag:SetRequiredAssets(rest)
targetairwing:AddMission(InterceptAuftrag)
end
Cluster.mission = InterceptAuftrag
end
else
MESSAGE:New("**** Not enough airframes available or max mission limit reached!",15,"CAPGCI"):ToAllIf(self.debug):ToLog()
end
end
end
--- (Internal) Start detection.
-- @param #EASYGCICAP self
-- @return #EASYGCICAP self
@@ -1068,131 +1248,16 @@ function EASYGCICAP:_StartIntel()
BlueIntel.debug = true
end
-- Here, we'll decide if we need to launch an intercepting flight, and from where
local overhead = self.overhead
local capspeed = self.capspeed + 100
local capalt = self.capalt
local maxsize = self.maxinterceptsize
local repeatsonfailure = self.repeatsonfailure
local wings = self.wings
local ctlpts = self.ManagedCP
local MaxAliveMissions = self.MaxAliveMissions * self.capgrouping
local nogozoneset = self.NoGoZoneSet
local function AssignCluster(Cluster)
self:_AssignIntercept(Cluster)
end
function BlueIntel:OnAfterNewCluster(From,Event,To,Cluster)
-- Aircraft?
if Cluster.ctype ~= INTEL.Ctype.AIRCRAFT then return end
-- Threatlevel 0..10
local contact = self:GetHighestThreatContact(Cluster)
local name = contact.groupname --#string
local threat = contact.threatlevel --#number
local position = self:CalcClusterFuturePosition(Cluster,300)
-- calculate closest zone
local bestdistance = 2000*1000 -- 2000km
local targetairwing = nil -- Ops.AirWing#AIRWING
local targetawname = "" -- #string
local clustersize = self:ClusterCountUnits(Cluster) or 1
local wingsize = math.abs(overhead * (clustersize+1))
if wingsize > maxsize then wingsize = maxsize end
-- existing mission, and if so - done?
local retrymission = true
if Cluster.mission and (not Cluster.mission:IsOver()) then
retrymission = false
end
if (retrymission) and (wingsize >= 1) then
MESSAGE:New(string.format("**** %s Interceptors need wingsize %d", UTILS.GetCoalitionName(self.coalition), wingsize),15,"CAPGCI"):ToAllIf(self.debug):ToLog()
for _,_data in pairs (wings) do
local airwing = _data[1] -- Ops.AirWing#AIRWING
local zone = _data[2] -- Core.Zone#ZONE
local zonecoord = zone:GetCoordinate()
local name = _data[3] -- #string
local distance = position:DistanceFromPointVec2(zonecoord)
local airframes = airwing:CountAssets(true)
if distance < bestdistance and airframes >= wingsize then
bestdistance = distance
targetairwing = airwing
targetawname = name
end
end
for _,_data in pairs (ctlpts) do
--local airwing = _data[1] -- Ops.AirWing#AIRWING
--local zone = _data[2] -- Core.Zone#ZONE
--local zonecoord = zone:GetCoordinate()
--local name = _data[3] -- #string
local data = _data -- #EASYGCICAP.CapPoint
local name = data.AirbaseName
local zonecoord = data.Coordinate
local airwing = wings[name][1]
local distance = position:DistanceFromPointVec2(zonecoord)
local airframes = airwing:CountAssets(true)
if distance < bestdistance and airframes >= wingsize then
bestdistance = distance
targetairwing = airwing -- Ops.AirWing#AIRWING
targetawname = name
end
end
local text = string.format("Closest Airwing is %s", targetawname)
local m = MESSAGE:New(text,10,"CAPGCI"):ToAllIf(self.debug):ToLog()
-- Do we have a matching airwing?
if targetairwing then
local AssetCount = targetairwing:CountAssetsOnMission(MissionTypes,Cohort)
--[[
local Assets = targetairwing:GetAssetsOnMission(AUFTRAG.Type.GCICAP)
for _,_asset in pairs(Assets) do
local asset = _asset -- Functional.Warehouse#WAREHOUSE.Assetitem
local fg = asset.flightgroup
local name = asset.spawngroupname
local mission = fg:GetMissionCurrent()
local mtype = mission.type
local distance = position:Get3DDistance(fg:GetCoordinate()) or 1000*1000
distance = distance / 1000
local text = string.format("FlightGroup %s on mission %s with distance %d km",name,mtype,distance)
local m = MESSAGE:New(text,15,"GCICAP"):ToAllIf(self.debug):ToLog()
end
--]]
-- Enough airframes on mission already?
self:T(self.lid.." Assets on Mission "..AssetCount)
if AssetCount <= MaxAliveMissions then
local repeats = repeatsonfailure
local InterceptAuftrag = AUFTRAG:NewINTERCEPT(contact.group)
:SetMissionRange(150)
:SetPriority(1,true,1)
:SetRequiredAssets(wingsize)
:SetRepeatOnFailure(repeats)
:SetMissionSpeed(UTILS.KnotsToAltKIAS(capspeed,capalt))
:SetMissionAltitude(capalt)
if nogozoneset:Count() > 0 then
InterceptAuftrag:AddConditionSuccess(
function(group,zoneset)
local success = false
if group and group:IsAlive() then
local coord = group:GetCoordinate()
if coord and zoneset:IsCoordinateInZone(coord) then
success = true
end
end
return success
end,
contact.group,
nogozoneset
)
end
targetairwing:AddMission(InterceptAuftrag)
Cluster.mission = InterceptAuftrag
end
else
MESSAGE:New("**** Not enough airframes available or max mission limit reached!",15,"CAPGCI"):ToAllIf(self.debug):ToLog()
end
end
AssignCluster(Cluster)
end
self.Intel = BlueIntel
return self
self.Intel = BlueIntel
return self
end
-------------------------------------------------------------------------
@@ -1266,6 +1331,24 @@ function EASYGCICAP:onafterStatus(From,Event,To)
tankermission = tankermission + _wing[1]:CountMissionsInQueue({AUFTRAG.Type.TANKER})
assets = assets + count
instock = instock + count2
local assetsonmission = _wing[1]:GetAssetsOnMission({AUFTRAG.Type.GCICAP,AUFTRAG.Type.PATROLRACETRACK})
-- update ready groups
self.ReadyFlightGroups = nil
self.ReadyFlightGroups = {}
for _,_asset in pairs(assetsonmission or {}) do
local asset = _asset -- Functional.Warehouse#WAREHOUSE.Assetitem
local FG = asset.flightgroup -- Ops.FlightGroup#FLIGHTGROUP
if FG then
local name = FG:GetName()
local engage = FG:IsEngaging()
local hasmissiles = FG:IsOutOfMissiles() == nil and true or false
local ready = hasmissiles and FG:IsFuelGood() and FG:IsAirborne()
--self:I(string.format("Flightgroup %s Engaging = %s Ready = %s",tostring(name),tostring(engage),tostring(ready)))
if ready then
self.ReadyFlightGroups[name] = FG
end
end
end
end
if self.Monitor then
local threatcount = #self.Intel.Clusters or 0

View File

@@ -7180,7 +7180,7 @@ function OPSGROUP:SetLaserTarget(Target)
-- Scenery as target. Treat it like a coordinate. Set offset to 1 meter above ground.
self.spot.TargetType=0
self.spot.offsetTarget={x=0, y=1, z=0}
self.spot.offsetTarget={x=0, y=3, z=0}
elseif Target:IsInstanceOf("POSITIONABLE") then

View File

@@ -1495,13 +1495,13 @@ end
-- @return #PLAYERRECCE self
function PLAYERRECCE:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey)
self:T(self.lid.."SetSRS")
self.PathToSRS = PathToSRS or "C:\\Program Files\\DCS-SimpleRadio-Standalone" --
self.Gender = Gender or "male" --
self.Culture = Culture or "en-US" --
self.Port = Port or 5002 --
self.Voice = Voice --
self.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone" --
self.Gender = Gender or MSRS.gender or "male" --
self.Culture = Culture or MSRS.culture or "en-US" --
self.Port = Port or MSRS.port or 5002 --
self.Voice = Voice or MSRS.voice --
self.PathToGoogleKey = PathToGoogleKey --
self.Volume = Volume or 1.0 --
self.Volume = Volume or 1.0 --
self.UseSRS = true
self.Frequency = Frequency or {127,251} --
self.BCFrequency = self.Frequency
@@ -1514,17 +1514,17 @@ function PLAYERRECCE:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,V
self.SRS:SetGender(self.Gender)
self.SRS:SetCulture(self.Culture)
self.SRS:SetPort(self.Port)
self.SRS:SetVoice(self.Voice)
self.SRS:SetVolume(self.Volume)
if self.PathToGoogleKey then
self.SRS:SetProviderOptionsGoogle(self.PathToGoogleKey,self.PathToGoogleKey)
self.SRS:SetProvider(MSRS.Provider.GOOGLE)
end
-- Pre-configured Google?
if (not PathToGoogleKey) and self.AwacsSRS:GetProvider() == MSRS.Provider.GOOGLE then
if (not PathToGoogleKey) and self.SRS:GetProvider() == MSRS.Provider.GOOGLE then
self.PathToGoogleKey = MSRS.poptions.gcloud.credentials
self.Voice = Voice or MSRS.poptions.gcloud.voice
end
self.SRS:SetVoice(self.Voice)
self.SRSQueue = MSRSQUEUE:New(self.MenuName or self.Name)
self.SRSQueue:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers)
return self

View File

@@ -98,7 +98,7 @@ PLAYERTASK = {
--- PLAYERTASK class version.
-- @field #string version
PLAYERTASK.version="0.1.22"
PLAYERTASK.version="0.1.23"
--- Generic task condition.
-- @type PLAYERTASK.Condition
@@ -1965,6 +1965,7 @@ end
-- @param Ops.FlightGroup#FLIGHTGROUP FlightGroup The FlightGroup (e.g. drone) to be used for lasing (one unit in one group only).
-- Can optionally be handed as Ops.ArmyGroup#ARMYGROUP - **Note** might not find an LOS spot or get lost on the way. Cannot island-hop.
-- @param #number LaserCode The lasercode to be used. Defaults to 1688.
-- @param Core.Point#COORDINATE HoldingPoint (Optional) Point where the drone should initially circle. If not set, defaults to BullsEye of the coalition.
-- @return #PLAYERTASKCONTROLLER self
-- @usage
-- -- Set up precision bombing, FlightGroup as lasing unit
@@ -1979,7 +1980,7 @@ end
-- ArmyGroup:Activate()
-- taskmanager:EnablePrecisionBombing(ArmyGroup,1688)
--
function PLAYERTASKCONTROLLER:EnablePrecisionBombing(FlightGroup,LaserCode)
function PLAYERTASKCONTROLLER:EnablePrecisionBombing(FlightGroup,LaserCode,HoldingPoint)
self:T(self.lid.."EnablePrecisionBombing")
if FlightGroup then
if FlightGroup.ClassName and (FlightGroup.ClassName == "FLIGHTGROUP" or FlightGroup.ClassName == "ARMYGROUP")then
@@ -1995,6 +1996,7 @@ function PLAYERTASKCONTROLLER:EnablePrecisionBombing(FlightGroup,LaserCode)
-- let it orbit the BullsEye if FG
if self.LasingDrone:IsFlightgroup() then
local BullsCoordinate = COORDINATE:NewFromVec3( coalition.getMainRefPoint( self.Coalition ))
if HoldingPoint then BullsCoordinate = HoldingPoint end
local Orbit = AUFTRAG:NewORBIT_CIRCLE(BullsCoordinate,10000,120)
self.LasingDrone:AddMission(Orbit)
end
@@ -2553,10 +2555,11 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
self.LasingDrone.playertask.reachmessage = false
-- move the drone to target
if self.LasingDrone:IsFlightgroup() then
self.LasingDrone:CancelAllMissions()
local auftrag = AUFTRAG:NewORBIT_CIRCLE(task.Target:GetCoordinate(),10000,120)
local currmission = self.LasingDrone:GetMissionCurrent()
--local currmission = self.LasingDrone:GetMissionCurrent()
self.LasingDrone:AddMission(auftrag)
currmission:__Cancel(-2)
--currmission:__Cancel(-2)
elseif self.LasingDrone:IsArmygroup() then
local tgtcoord = task.Target:GetCoordinate()
local tgtzone = ZONE_RADIUS:New("ArmyGroup-"..math.random(1,10000),tgtcoord:GetVec2(),3000)
@@ -2606,6 +2609,7 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
-- not done yet
local dcoord = self.LasingDrone:GetCoordinate()
local tcoord = task.Target:GetCoordinate()
tcoord.y = tcoord.y + 2
local dist = dcoord:Get2DDistance(tcoord)
-- close enough?
if dist < 3000 and not self.LasingDrone:IsLasing() then
@@ -3189,7 +3193,7 @@ function PLAYERTASKCONTROLLER:_ActiveTaskInfo(Task, Group, Client)
local islasing = self.LasingDrone:IsLasing() == true and yes or no
local prectext = self.gettext:GetEntry("POINTERTARGETREPORT",self.locale)
prectext = string.format(prectext,inreach,islasing)
text = text .. prectext
text = text .. prectext.."("..self.LaserCode..")"
end
end
-- Buddylasing