mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Merge branch 'develop' into FF/Ops
This commit is contained in:
commit
0933eef4c3
@ -1140,8 +1140,8 @@ end
|
||||
-- @param DCS#Vec3 CV2 Vec3
|
||||
function AI_FORMATION:FollowMe(FollowGroup, ClientUnit, CT1, CV1, CT2, CV2)
|
||||
|
||||
if FollowGroup:GetState( FollowGroup, "Mode" ) == self.__Enum.Mode.Formation then
|
||||
|
||||
if FollowGroup:GetState( FollowGroup, "Mode" ) == self.__Enum.Mode.Formation and not self:Is("Stopped") then
|
||||
|
||||
self:T({Mode=FollowGroup:GetState( FollowGroup, "Mode" )})
|
||||
|
||||
FollowGroup:OptionROTEvadeFire()
|
||||
|
||||
@ -122,7 +122,7 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
|
||||
self.Schedule[Scheduler][CallID].Function = ScheduleFunction
|
||||
self.Schedule[Scheduler][CallID].Arguments = ScheduleArguments
|
||||
self.Schedule[Scheduler][CallID].StartTime = timer.getTime() + ( Start or 0 )
|
||||
self.Schedule[Scheduler][CallID].Start = Start + 0.1
|
||||
self.Schedule[Scheduler][CallID].Start = Start + 0.001
|
||||
self.Schedule[Scheduler][CallID].Repeat = Repeat or 0
|
||||
self.Schedule[Scheduler][CallID].Randomize = Randomize or 0
|
||||
self.Schedule[Scheduler][CallID].Stop = Stop
|
||||
|
||||
@ -5411,10 +5411,12 @@ do -- SET_ZONE
|
||||
|
||||
--- Get a random zone from the set.
|
||||
-- @param #SET_ZONE self
|
||||
-- @param #number margin Number of tries to find a zone
|
||||
-- @return Core.Zone#ZONE_BASE The random Zone.
|
||||
-- @return #nil if no zone in the collection.
|
||||
function SET_ZONE:GetRandomZone()
|
||||
|
||||
function SET_ZONE:GetRandomZone(margin)
|
||||
|
||||
local margin = margin or 100
|
||||
if self:Count() ~= 0 then
|
||||
|
||||
local Index = self.Index
|
||||
@ -5423,9 +5425,11 @@ do -- SET_ZONE
|
||||
-- Loop until a zone has been found.
|
||||
-- The :GetZoneMaybe() call will evaluate the probability for the zone to be selected.
|
||||
-- If the zone is not selected, then nil is returned by :GetZoneMaybe() and the loop continues!
|
||||
while not ZoneFound do
|
||||
local counter = 0
|
||||
while (not ZoneFound) or (counter < margin) do
|
||||
local ZoneRandom = math.random( 1, #Index )
|
||||
ZoneFound = self.Set[Index[ZoneRandom]]:GetZoneMaybe()
|
||||
counter = counter + 1
|
||||
end
|
||||
|
||||
return ZoneFound
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
--- **Functional** -- Modular, Automatic and Network capable Targeting and Interception System for Air Defenses
|
||||
--- **Functional** -- Modular, Automatic and Network capable Targeting and Interception System for Air Defenses
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@ -37,7 +37,7 @@
|
||||
-- @field #table SAM_Table Table of SAM sites
|
||||
-- @field #string lid Prefix for logging
|
||||
-- @field @{#Functional.Detection#DETECTION_AREAS} Detection The #DETECTION_AREAS object for EWR
|
||||
-- @field @{Functional.Detection#DETECTION_AREAS} AWACS_Detection The #DETECTION_AREAS object for AWACS
|
||||
-- @field @{#Functional.Detection#DETECTION_AREAS} AWACS_Detection The #DETECTION_AREAS object for AWACS
|
||||
-- @field #boolean debug Switch on extra messages
|
||||
-- @field #boolean verbose Switch on extra logging
|
||||
-- @field #number checkradius Radius of the SAM sites
|
||||
@ -96,7 +96,7 @@
|
||||
--
|
||||
-- # 2. Start up your MANTIS with a basic setting
|
||||
--
|
||||
-- `myredmantis = MANTIS:New("myredmantis","Red SAM","Red EWR",nil,"red",false)`
|
||||
-- `myredmantis = MANTIS:New("myredmantis","Red SAM","Red EWR",nil,"red",false)`
|
||||
-- `myredmantis:Start()`
|
||||
--
|
||||
-- [optional] Use
|
||||
@ -111,7 +111,7 @@
|
||||
--
|
||||
-- If you want to use a separate AWACS unit (default detection range: 250km) to support your EWR system, use e.g. the following setup:
|
||||
--
|
||||
-- `mybluemantis = MANTIS:New("bluemantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs")`
|
||||
-- `mybluemantis = MANTIS:New("bluemantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs")`
|
||||
-- `mybluemantis:Start()`
|
||||
--
|
||||
-- # 3. Default settings
|
||||
@ -181,6 +181,26 @@ do
|
||||
--@param #boolean dynamic Use constant (true) filtering or just filter once (false, default) (optional)
|
||||
--@param #string awacs Group name of your Awacs (optional)
|
||||
--@return #MANTIS self
|
||||
--@usage Start up your MANTIS with a basic setting
|
||||
--
|
||||
-- `myredmantis = MANTIS:New("myredmantis","Red SAM","Red EWR",nil,"red",false)`
|
||||
-- `myredmantis:Start()`
|
||||
--
|
||||
-- [optional] Use
|
||||
--
|
||||
-- * `MANTIS:SetEWRGrouping(radius)`
|
||||
-- * `MANTIS:SetEWRRange(radius)`
|
||||
-- * `MANTIS:SetSAMRadius(radius)`
|
||||
-- * `MANTIS:SetDetectInterval(interval)`
|
||||
-- * `MANTIS:SetAutoRelocate(hq, ewr)`
|
||||
--
|
||||
-- before starting #MANTIS to fine-tune your setup.
|
||||
--
|
||||
-- If you want to use a separate AWACS unit (default detection range: 250km) to support your EWR system, use e.g. the following setup:
|
||||
--
|
||||
-- `mybluemantis = MANTIS:New("bluemantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs")`
|
||||
-- `mybluemantis:Start()`
|
||||
--
|
||||
function MANTIS:New(name,samprefix,ewrprefix,hq,coaltion,dynamic,awacs)
|
||||
|
||||
-- DONE: Create some user functions for these
|
||||
@ -307,7 +327,7 @@ do
|
||||
self.engagerange = range
|
||||
end
|
||||
|
||||
--- Function to set a new SAM firing engage range, use this method to adjust range while running MANTIS, e.g. for different setups day and night
|
||||
--- Function to set a new SAM firing engage range, use this method to adjust range while running MANTIS, e.g. for different setups day and night
|
||||
-- @param #MANTIS self
|
||||
-- @param #number range Percent of the max fire range
|
||||
function MANTIS:SetNewSAMRangeWhileRunning(range)
|
||||
@ -535,7 +555,7 @@ do
|
||||
end
|
||||
end
|
||||
|
||||
--- Function to check if any object is in the given SAM zone
|
||||
--- (Internal) Function to check if any object is in the given SAM zone
|
||||
-- @param #MANTIS self
|
||||
-- @param #table dectset Table of coordinates of detected items
|
||||
-- @param samcoordinate Core.Point#COORDINATE Coordinate object.
|
||||
@ -562,7 +582,7 @@ do
|
||||
return false
|
||||
end
|
||||
|
||||
--- Function to start the detection via EWR groups
|
||||
--- (Internal) Function to start the detection via EWR groups
|
||||
-- @param #MANTIS self
|
||||
-- @return Functional.Detection #DETECTION_AREAS The running detection set
|
||||
function MANTIS:StartDetection()
|
||||
@ -593,7 +613,7 @@ do
|
||||
return _MANTISdetection
|
||||
end
|
||||
|
||||
--- Function to start the detection via AWACS if defined as separate
|
||||
--- (Internal) Function to start the detection via AWACS if defined as separate
|
||||
-- @param #MANTIS self
|
||||
-- @return Functional.Detection #DETECTION_AREAS The running detection set
|
||||
function MANTIS:StartAwacsDetection()
|
||||
@ -625,7 +645,7 @@ do
|
||||
return _MANTISAwacs
|
||||
end
|
||||
|
||||
--- Function to set the SAM start state
|
||||
--- (Internal) Function to set the SAM start state
|
||||
-- @param #MANTIS self
|
||||
-- @return #MANTIS self
|
||||
function MANTIS:SetSAMStartState()
|
||||
|
||||
@ -1318,6 +1318,10 @@ function ATIS:onafterBroadcast(From, Event, To)
|
||||
time=time-UTILS.GMTToLocalTimeDifference()*60*60
|
||||
end
|
||||
|
||||
if time < 0 then
|
||||
time = 24*60*60 + time --avoid negative time around midnight
|
||||
end
|
||||
|
||||
local clock=UTILS.SecondsToClock(time)
|
||||
local zulu=UTILS.Split(clock, ":")
|
||||
local ZULU=string.format("%s%s", zulu[1], zulu[2])
|
||||
|
||||
@ -17,13 +17,13 @@
|
||||
-- ===
|
||||
--
|
||||
-- ## Example Missions:
|
||||
--
|
||||
--
|
||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Flightgroup).
|
||||
--
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
--
|
||||
-- ===
|
||||
-- @module Ops.FlightGroup
|
||||
-- @image OPS_FlightGroup.png
|
||||
@ -234,7 +234,7 @@ function FLIGHTGROUP:New(group)
|
||||
self.lid=string.format("FLIGHTGROUP %s | ", self.groupname)
|
||||
|
||||
-- Defaults
|
||||
self.isFlightgroup=true
|
||||
self.isFlightgroup=true
|
||||
self:SetFuelLowThreshold()
|
||||
self:SetFuelLowRTB()
|
||||
self:SetFuelCriticalThreshold()
|
||||
@ -325,10 +325,10 @@ function FLIGHTGROUP:New(group)
|
||||
|
||||
-- Start the status monitoring.
|
||||
self:__Status(-1)
|
||||
|
||||
|
||||
-- Start queue update timer.
|
||||
self.timerQueueUpdate=TIMER:New(self._QueueUpdate, self):Start(2, 5)
|
||||
|
||||
|
||||
-- Start check zone timer.
|
||||
self.timerCheckZone=TIMER:New(self._CheckInZones, self):Start(3, 10)
|
||||
|
||||
@ -491,7 +491,7 @@ function FLIGHTGROUP:SetFuelCriticalRTB(switch)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Enable to automatically engage detected targets.
|
||||
--- Enable to automatically engage detected targets.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #number RangeMax Max range in NM. Only detected targets within this radius from the group will be engaged. Default is 25 NM.
|
||||
-- @param #table TargetTypes Types of target attributes that will be engaged. See [DCS enum attributes](https://wiki.hoggitworld.com/view/DCS_enum_attributes). Default "All".
|
||||
@ -508,7 +508,7 @@ function FLIGHTGROUP:SetEngageDetectedOn(RangeMax, TargetTypes, EngageZoneSet, N
|
||||
else
|
||||
TargetTypes={"All"}
|
||||
end
|
||||
|
||||
|
||||
-- Ensure SET_ZONE if ZONE is provided.
|
||||
if EngageZoneSet and EngageZoneSet:IsInstanceOf("ZONE_BASE") then
|
||||
local zoneset=SET_ZONE:New():AddZone(EngageZoneSet)
|
||||
@ -532,7 +532,7 @@ function FLIGHTGROUP:SetEngageDetectedOn(RangeMax, TargetTypes, EngageZoneSet, N
|
||||
return self
|
||||
end
|
||||
|
||||
--- Disable to automatically engage detected targets.
|
||||
--- Disable to automatically engage detected targets.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @return #FLIGHTGROUP self
|
||||
function FLIGHTGROUP:SetEngageDetectedOff()
|
||||
@ -762,45 +762,45 @@ function FLIGHTGROUP:onbeforeStatus(From, Event, To)
|
||||
-- First we check if elements are still alive. Could be that they were despawned without notice, e.g. when landing on a too small airbase.
|
||||
for i,_element in pairs(self.elements) do
|
||||
local element=_element --#FLIGHTGROUP.Element
|
||||
|
||||
|
||||
-- Check that element is not already dead or not yet alive.
|
||||
if element.status~=OPSGROUP.ElementStatus.DEAD and element.status~=OPSGROUP.ElementStatus.INUTERO then
|
||||
|
||||
|
||||
-- Unit shortcut.
|
||||
local unit=element.unit
|
||||
|
||||
local isdead=false
|
||||
|
||||
local isdead=false
|
||||
if unit and unit:IsAlive() then
|
||||
|
||||
|
||||
-- Get life points.
|
||||
local life=unit:GetLife() or 0
|
||||
|
||||
|
||||
-- Units with life <=1 are dead.
|
||||
if life<=1 then
|
||||
--env.info(string.format("FF unit %s: live<=1 in status at T=%.3f", unit:GetName(), timer.getTime()))
|
||||
isdead=true
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
-- Not alive any more.
|
||||
--env.info(string.format("FF unit %s: NOT alive in status at T=%.3f", unit:GetName(), timer.getTime()))
|
||||
isdead=true
|
||||
end
|
||||
|
||||
|
||||
-- This one is dead.
|
||||
if isdead then
|
||||
local text=string.format("Element %s is dead at t=%.3f! Maybe despawned without notice or landed at a too small airbase. Calling ElementDead in 60 sec to give other events a chance",
|
||||
local text=string.format("Element %s is dead at t=%.3f! Maybe despawned without notice or landed at a too small airbase. Calling ElementDead in 60 sec to give other events a chance",
|
||||
tostring(element.name), timer.getTime())
|
||||
self:E(self.lid..text)
|
||||
self:__ElementDead(60, element)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
if self:IsDead() then
|
||||
if self:IsDead() then
|
||||
self:T(self.lid..string.format("Onbefore Status DEAD ==> false"))
|
||||
return false
|
||||
return false
|
||||
elseif self:IsStopped() then
|
||||
self:T(self.lid..string.format("Onbefore Status STOPPED ==> false"))
|
||||
return false
|
||||
@ -818,7 +818,7 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
|
||||
|
||||
-- FSM state.
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
|
||||
-- Update position.
|
||||
self:_UpdatePosition()
|
||||
|
||||
@ -865,22 +865,22 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
|
||||
|
||||
-- Short info.
|
||||
if self.verbose>=1 then
|
||||
|
||||
|
||||
local nTaskTot, nTaskSched, nTaskWP=self:CountRemainingTasks()
|
||||
local nMissions=self:CountRemainingMissison()
|
||||
|
||||
|
||||
|
||||
|
||||
local text=string.format("Status %s [%d/%d]: Tasks=%d (%d,%d) Curr=%d, Missions=%s, Waypoint=%d/%d, Detected=%d, Home=%s, Destination=%s",
|
||||
fsmstate, #self.elements, #self.elements, nTaskTot, nTaskSched, nTaskWP, self.taskcurrent, nMissions, self.currentwp or 0, self.waypoints and #self.waypoints or 0,
|
||||
self.detectedunits:Count(), self.homebase and self.homebase:GetName() or "unknown", self.destbase and self.destbase:GetName() or "unknown")
|
||||
self:I(self.lid..text)
|
||||
|
||||
|
||||
end
|
||||
|
||||
---
|
||||
-- Elements
|
||||
---
|
||||
|
||||
|
||||
if self.verbose>=2 then
|
||||
local text="Elements:"
|
||||
for i,_element in pairs(self.elements) do
|
||||
@ -958,7 +958,7 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
|
||||
|
||||
-- Log outut.
|
||||
self:I(self.lid..string.format("Travelled ds=%.1f km dt=%.1f s ==> v=%.1f knots. Fuel left for %.1f min", self.traveldist/1000, dt, UTILS.MpsToKnots(v), TmaxFuel/60))
|
||||
|
||||
|
||||
end
|
||||
|
||||
---
|
||||
@ -1008,34 +1008,34 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
|
||||
|
||||
---
|
||||
-- Engage Detected Targets
|
||||
---
|
||||
---
|
||||
if self:IsAirborne() and self.detectionOn and self.engagedetectedOn and not (self.fuellow or self.fuelcritical) then
|
||||
env.info("FF 100")
|
||||
|
||||
|
||||
-- Target.
|
||||
local targetgroup=nil --Wrapper.Group#GROUP
|
||||
local targetdist=math.huge
|
||||
|
||||
|
||||
-- Loop over detected groups.
|
||||
for _,_group in pairs(self.detectedgroups:GetSet()) do
|
||||
local group=_group --Wrapper.Group#GROUP
|
||||
|
||||
|
||||
env.info("FF 200")
|
||||
|
||||
|
||||
if group and group:IsAlive() then
|
||||
|
||||
|
||||
env.info("FF 300")
|
||||
|
||||
|
||||
-- Get 3D vector of target.
|
||||
local targetVec3=group:GetVec3()
|
||||
|
||||
-- Distance to target.
|
||||
-- Distance to target.
|
||||
local distance=UTILS.VecDist3D(self.position, targetVec3)
|
||||
|
||||
|
||||
if distance<=self.engagedetectedRmax and distance<targetdist then
|
||||
|
||||
|
||||
env.info("FF 400")
|
||||
|
||||
|
||||
-- Check type attribute.
|
||||
local righttype=false
|
||||
for _,attribute in pairs(self.engagedetectedTypes) do
|
||||
@ -1046,13 +1046,13 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- We got the right type.
|
||||
if righttype then
|
||||
|
||||
|
||||
local insideEngage=true
|
||||
local insideNoEngage=false
|
||||
|
||||
|
||||
-- Check engage zones.
|
||||
if self.engagedetectedEngageZones then
|
||||
insideEngage=false
|
||||
@ -1062,10 +1062,10 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
|
||||
if inzone then
|
||||
insideEngage=true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Check no engage zones.
|
||||
if self.engagedetectedNoEngageZones then
|
||||
for _,_zone in pairs(self.engagedetectedNoEngageZones.Set) do
|
||||
@ -1077,25 +1077,25 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- If inside engage but not inside no engage zones.
|
||||
if insideEngage and not insideNoEngage then
|
||||
targetdist=distance
|
||||
targetgroup=group
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- If we found a group, we engage it.
|
||||
if targetgroup then
|
||||
self:I(self.lid..string.format("Engaging target group %s at distance %d meters", targetgroup:GetName(), targetdist))
|
||||
self:EngageTarget(targetgroup)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
@ -1255,7 +1255,7 @@ function FLIGHTGROUP:OnEventCrash(EventData)
|
||||
local element=self:GetElementByName(unitname)
|
||||
|
||||
if element and element.status~=OPSGROUP.ElementStatus.DEAD then
|
||||
self:T(self.lid..string.format("EVENT: Element %s crashed ==> destroyed", element.name))
|
||||
self:T(self.lid..string.format("EVENT: Element %s crashed ==> destroyed", element.name))
|
||||
self:ElementDestroyed(element)
|
||||
end
|
||||
|
||||
@ -1271,7 +1271,7 @@ function FLIGHTGROUP:OnEventUnitLost(EventData)
|
||||
-- Check that this is the right group.
|
||||
if EventData and EventData.IniGroup and EventData.IniUnit and EventData.IniGroupName and EventData.IniGroupName==self.groupname then
|
||||
self:T2(self.lid..string.format("EVENT: Unit %s lost at t=%.3f", EventData.IniUnitName, timer.getTime()))
|
||||
|
||||
|
||||
local unit=EventData.IniUnit
|
||||
local group=EventData.IniGroup
|
||||
local unitname=EventData.IniUnitName
|
||||
@ -1283,7 +1283,7 @@ function FLIGHTGROUP:OnEventUnitLost(EventData)
|
||||
self:T(self.lid..string.format("EVENT: Element %s unit lost ==> destroyed t=%.3f", element.name, timer.getTime()))
|
||||
self:ElementDestroyed(element)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@ -1306,7 +1306,7 @@ function FLIGHTGROUP:onafterElementSpawned(From, Event, To, Element)
|
||||
-- Set element status.
|
||||
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.SPAWNED)
|
||||
|
||||
if Element.unit:InAir() then
|
||||
if Element.unit:InAir(true) then
|
||||
-- Trigger ElementAirborne event. Add a little delay because spawn is also delayed!
|
||||
self:__ElementAirborne(0.11, Element)
|
||||
else
|
||||
@ -1433,26 +1433,26 @@ end
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase if applicable or nil.
|
||||
function FLIGHTGROUP:onafterElementLanded(From, Event, To, Element, airbase)
|
||||
self:T2(self.lid..string.format("Element landed %s at %s airbase", Element.name, airbase and airbase:GetName() or "unknown"))
|
||||
|
||||
|
||||
if self.despawnAfterLanding then
|
||||
|
||||
|
||||
-- Despawn the element.
|
||||
self:DespawnElement(Element)
|
||||
|
||||
|
||||
else
|
||||
|
||||
-- Helos with skids land directly on parking spots.
|
||||
if self.ishelo then
|
||||
|
||||
|
||||
local Spot=self:GetParkingSpot(Element, 10, airbase)
|
||||
|
||||
|
||||
self:_SetElementParkingAt(Element, Spot)
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- Set element status.
|
||||
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.LANDED, airbase)
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@ -1483,7 +1483,7 @@ function FLIGHTGROUP:onafterElementDestroyed(From, Event, To, Element)
|
||||
|
||||
-- Call OPSGROUP function.
|
||||
self:GetParent(self).onafterElementDestroyed(self, From, Event, To, Element)
|
||||
|
||||
|
||||
end
|
||||
|
||||
--- On after "ElementDead" event.
|
||||
@ -1503,7 +1503,7 @@ function FLIGHTGROUP:onafterElementDead(From, Event, To, Element)
|
||||
|
||||
-- Not parking any more.
|
||||
Element.parking=nil
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
@ -1515,7 +1515,7 @@ end
|
||||
function FLIGHTGROUP:onafterSpawned(From, Event, To)
|
||||
self:T(self.lid..string.format("Flight spawned"))
|
||||
|
||||
-- Update position.
|
||||
-- Update position.
|
||||
self:_UpdatePosition()
|
||||
|
||||
if self.isAI then
|
||||
@ -1525,32 +1525,32 @@ function FLIGHTGROUP:onafterSpawned(From, Event, To)
|
||||
|
||||
-- Set ROT.
|
||||
self:SwitchROT(self.option.ROT)
|
||||
|
||||
|
||||
-- Set Formation
|
||||
self:SwitchFormation(self.option.Formation)
|
||||
|
||||
|
||||
-- Set TACAN beacon.
|
||||
self:_SwitchTACAN()
|
||||
|
||||
|
||||
-- Set radio freq and modu.
|
||||
if self.radioDefault then
|
||||
self:SwitchRadio()
|
||||
else
|
||||
self:SetDefaultRadio(self.radio.Freq, self.radio.Modu, self.radio.On)
|
||||
end
|
||||
|
||||
|
||||
-- Set callsign.
|
||||
if self.callsignDefault then
|
||||
self:SwitchCallsign(self.callsignDefault.NumberSquad, self.callsignDefault.NumberGroup)
|
||||
else
|
||||
self:SetDefaultCallsign(self.callsign.NumberSquad, self.callsign.NumberGroup)
|
||||
end
|
||||
|
||||
|
||||
-- TODO: make this input.
|
||||
self:GetGroup():SetOption(AI.Option.Air.id.PROHIBIT_JETT, true)
|
||||
self:GetGroup():SetOption(AI.Option.Air.id.PROHIBIT_AB, true) -- Does not seem to work. AI still used the after burner.
|
||||
self:GetGroup():SetOption(AI.Option.Air.id.RTB_ON_BINGO, false)
|
||||
--self.group:SetOption(AI.Option.Air.id.RADAR_USING, AI.Option.Air.val.RADAR_USING.FOR_CONTINUOUS_SEARCH)
|
||||
--self.group:SetOption(AI.Option.Air.id.RADAR_USING, AI.Option.Air.val.RADAR_USING.FOR_CONTINUOUS_SEARCH)
|
||||
|
||||
-- Update route.
|
||||
self:__UpdateRoute(-0.5)
|
||||
@ -1690,7 +1690,7 @@ function FLIGHTGROUP:onafterLanded(From, Event, To, airbase)
|
||||
-- Add flight to taxiinb queue.
|
||||
self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.TAXIINB)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
--- On after "LandedAt" event.
|
||||
@ -1699,7 +1699,7 @@ end
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function FLIGHTGROUP:onafterLandedAt(From, Event, To)
|
||||
self:T(self.lid..string.format("Flight landed at"))
|
||||
self:T(self.lid..string.format("Flight landed at"))
|
||||
end
|
||||
|
||||
|
||||
@ -1735,22 +1735,22 @@ function FLIGHTGROUP:onafterDead(From, Event, To)
|
||||
self.flightcontrol:_RemoveFlight(self)
|
||||
self.flightcontrol=nil
|
||||
end
|
||||
|
||||
|
||||
if self.Ndestroyed==#self.elements then
|
||||
if self.squadron then
|
||||
-- All elements were destroyed ==> Asset group is gone.
|
||||
self.squadron:DelGroup(self.groupname)
|
||||
end
|
||||
end
|
||||
else
|
||||
if self.airwing then
|
||||
-- Not all assets were destroyed (despawn) ==> Add asset back to airwing.
|
||||
self.airwing:AddAsset(self.group, 1)
|
||||
self.airwing:AddAsset(self.group, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Call OPSGROUP function.
|
||||
self:GetParent(self).onafterDead(self, From, Event, To)
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
@ -1799,10 +1799,10 @@ function FLIGHTGROUP:onbeforeUpdateRoute(From, Event, To, n)
|
||||
end
|
||||
|
||||
if self.taskcurrent>0 then
|
||||
|
||||
|
||||
--local task=self:GetTaskCurrent()
|
||||
local task=self:GetTaskByID(self.taskcurrent)
|
||||
|
||||
|
||||
if task then
|
||||
if task.dcstask.id=="PatrolZone" then
|
||||
-- For patrol zone, we need to allow the update.
|
||||
@ -1861,7 +1861,7 @@ function FLIGHTGROUP:onafterUpdateRoute(From, Event, To, n)
|
||||
-- Set current waypoint or we get problem that the _PassingWaypoint function is triggered too early, i.e. right now and not when passing the next WP.
|
||||
local current=self.group:GetCoordinate():WaypointAir(COORDINATE.WaypointAltType.BARO, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, speed, true, nil, {}, "Current")
|
||||
table.insert(wp, current)
|
||||
|
||||
|
||||
local Nwp=self.waypoints and #self.waypoints or 0
|
||||
|
||||
-- Add remaining waypoints to route.
|
||||
@ -1885,7 +1885,7 @@ function FLIGHTGROUP:onafterUpdateRoute(From, Event, To, n)
|
||||
---
|
||||
-- No waypoints left
|
||||
---
|
||||
|
||||
|
||||
if self:IsAirborne() then
|
||||
self:T(self.lid.."No waypoints left ==> CheckGroupDone")
|
||||
self:_CheckGroupDone()
|
||||
@ -1919,7 +1919,7 @@ function FLIGHTGROUP:_CheckGroupDone(delay)
|
||||
self:UnpauseMission()
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
-- Group is currently engaging.
|
||||
if self:IsEngaging() then
|
||||
return
|
||||
@ -1939,7 +1939,7 @@ function FLIGHTGROUP:_CheckGroupDone(delay)
|
||||
|
||||
-- Number of remaining tasks/missions?
|
||||
if nTasks==0 and nMissions==0 then
|
||||
|
||||
|
||||
local destbase=self.destbase or self.homebase
|
||||
local destzone=self.destzone or self.homezone
|
||||
|
||||
@ -2062,19 +2062,19 @@ function FLIGHTGROUP:onafterRTB(From, Event, To, airbase, SpeedTo, SpeedHold, Sp
|
||||
|
||||
-- Clear holding time in any case.
|
||||
self.Tholding=nil
|
||||
|
||||
|
||||
-- Cancel all missions.
|
||||
for _,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
local mystatus=mission:GetGroupStatus(self)
|
||||
|
||||
|
||||
-- Check if mission is already over!
|
||||
if not (mystatus==AUFTRAG.GroupStatus.DONE or mystatus==AUFTRAG.GroupStatus.CANCELLED) then
|
||||
local text=string.format("Canceling mission %s in state=%s", mission.name, mission.status)
|
||||
self:T(self.lid..text)
|
||||
self:MissionCancel(mission)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
-- Defaults:
|
||||
@ -2176,7 +2176,7 @@ function FLIGHTGROUP:onafterRTB(From, Event, To, airbase, SpeedTo, SpeedHold, Sp
|
||||
-- Clear all tasks.
|
||||
-- Warning, looks like this can make DCS CRASH! Had this after calling RTB once passed the final waypoint.
|
||||
--self:ClearTasks()
|
||||
|
||||
|
||||
-- Just route the group. Respawn might happen when going from holding to final.
|
||||
self:Route(wp, 1)
|
||||
|
||||
@ -2374,39 +2374,39 @@ function FLIGHTGROUP:onafterEngageTarget(From, Event, To, Target)
|
||||
|
||||
-- Check target object.
|
||||
if Target:IsInstanceOf("UNIT") or Target:IsInstanceOf("STATIC") then
|
||||
|
||||
|
||||
DCStask=self:GetGroup():TaskAttackUnit(Target, true)
|
||||
|
||||
|
||||
elseif Target:IsInstanceOf("GROUP") then
|
||||
|
||||
DCStask=self:GetGroup():TaskAttackGroup(Target, nil, nil, nil, nil, nil, nil, true)
|
||||
|
||||
|
||||
elseif Target:IsInstanceOf("SET_UNIT") then
|
||||
|
||||
local DCSTasks={}
|
||||
|
||||
|
||||
for _,_unit in pairs(Target:GetSet()) do --detected by =HRP= Zero
|
||||
local unit=_unit --Wrapper.Unit#UNIT
|
||||
local task=self:GetGroup():TaskAttackUnit(unit, true)
|
||||
table.insert(DCSTasks)
|
||||
end
|
||||
|
||||
|
||||
-- Task combo.
|
||||
DCStask=self:GetGroup():TaskCombo(DCSTasks)
|
||||
|
||||
elseif Target:IsInstanceOf("SET_GROUP") then
|
||||
|
||||
local DCSTasks={}
|
||||
|
||||
|
||||
for _,_unit in pairs(Target:GetSet()) do --detected by =HRP= Zero
|
||||
local unit=_unit --Wrapper.Unit#UNIT
|
||||
local task=self:GetGroup():TaskAttackGroup(Target, nil, nil, nil, nil, nil, nil, true)
|
||||
table.insert(DCSTasks)
|
||||
end
|
||||
|
||||
|
||||
-- Task combo.
|
||||
DCStask=self:GetGroup():TaskCombo(DCSTasks)
|
||||
|
||||
|
||||
else
|
||||
self:E("ERROR: unknown Target in EngageTarget! Needs to be a UNIT, STATIC, GROUP, SET_UNIT or SET_GROUP")
|
||||
return
|
||||
@ -2414,10 +2414,10 @@ function FLIGHTGROUP:onafterEngageTarget(From, Event, To, Target)
|
||||
|
||||
-- Create new task.The description "Engage_Target" is checked so do not change that lightly.
|
||||
local Task=self:NewTaskScheduled(DCStask, 1, "Engage_Target", 0)
|
||||
|
||||
|
||||
-- Backup ROE setting.
|
||||
Task.backupROE=self:GetROE()
|
||||
|
||||
|
||||
-- Switch ROE to open fire
|
||||
self:SwitchROE(ENUMS.ROE.OpenFire)
|
||||
|
||||
@ -2428,7 +2428,7 @@ function FLIGHTGROUP:onafterEngageTarget(From, Event, To, Target)
|
||||
end
|
||||
|
||||
-- Execute task.
|
||||
self:TaskExecute(Task)
|
||||
self:TaskExecute(Task)
|
||||
|
||||
end
|
||||
|
||||
@ -2501,9 +2501,9 @@ function FLIGHTGROUP:onafterFuelLow(From, Event, To)
|
||||
local tanker=self.airwing:GetTankerForFlight(self)
|
||||
|
||||
if tanker then
|
||||
|
||||
|
||||
self:I(self.lid..string.format("Send to refuel at tanker %s", tanker.flightgroup:GetName()))
|
||||
|
||||
|
||||
-- Get a coordinate towards the tanker.
|
||||
local coordinate=self:GetCoordinate():GetIntermediateCoordinate(tanker.flightgroup:GetCoordinate(), 0.75)
|
||||
|
||||
@ -2600,12 +2600,12 @@ function FLIGHTGROUP:onafterStop(From, Event, To)
|
||||
self:UnHandleEvent(EVENTS.Ejection)
|
||||
self:UnHandleEvent(EVENTS.Crash)
|
||||
self:UnHandleEvent(EVENTS.RemoveUnit)
|
||||
|
||||
|
||||
-- Call OPSGROUP function.
|
||||
self:GetParent(self).onafterStop(self, From, Event, To)
|
||||
|
||||
|
||||
-- Remove flight from data base.
|
||||
_DATABASE.FLIGHTGROUPS[self.groupname]=nil
|
||||
_DATABASE.FLIGHTGROUPS[self.groupname]=nil
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -2668,7 +2668,7 @@ function FLIGHTGROUP:_InitGroup()
|
||||
self:E(self.lid.."WARNING: Group was already initialized!")
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
-- Group object.
|
||||
local group=self.group --Wrapper.Group#GROUP
|
||||
|
||||
@ -2705,7 +2705,7 @@ function FLIGHTGROUP:_InitGroup()
|
||||
self.radio.Freq=tonumber(self.template.frequency)
|
||||
self.radio.Modu=tonumber(self.template.modulation)
|
||||
self.radio.On=self.template.communication
|
||||
|
||||
|
||||
-- Set callsign. Default is set on spawn if not modified by user.
|
||||
local callsign=self.template.units[1].callsign
|
||||
if type(callsign)=="number" then -- Sometimes callsign is just "101".
|
||||
@ -2726,7 +2726,7 @@ function FLIGHTGROUP:_InitGroup()
|
||||
else
|
||||
self.optionDefault.Formation=ENUMS.Formation.FixedWing.EchelonLeft.Group
|
||||
end
|
||||
|
||||
|
||||
-- Default TACAN off.
|
||||
self:SetDefaultTACAN(nil, nil, nil, nil, true)
|
||||
self.tacan=UTILS.DeepCopy(self.tacanDefault)
|
||||
@ -2870,7 +2870,7 @@ function FLIGHTGROUP:GetHomebaseFromWaypoints()
|
||||
|
||||
-- Get airbase ID depending on airbase category.
|
||||
local airbaseID=nil
|
||||
|
||||
|
||||
if wp.airdromeId then
|
||||
airbaseID=wp.airdromeId
|
||||
else
|
||||
@ -2878,7 +2878,7 @@ function FLIGHTGROUP:GetHomebaseFromWaypoints()
|
||||
end
|
||||
|
||||
local airbase=AIRBASE:FindByID(airbaseID)
|
||||
|
||||
|
||||
return airbase
|
||||
end
|
||||
|
||||
@ -3126,14 +3126,14 @@ function FLIGHTGROUP:InitWaypoints()
|
||||
-- Template waypoints.
|
||||
self.waypoints0=self.group:GetTemplateRoutePoints()
|
||||
|
||||
-- Waypoints
|
||||
-- Waypoints
|
||||
self.waypoints={}
|
||||
|
||||
|
||||
for index,wp in pairs(self.waypoints0) do
|
||||
|
||||
local waypoint=self:_CreateWaypoint(wp)
|
||||
|
||||
local waypoint=self:_CreateWaypoint(wp)
|
||||
self:_AddWaypoint(waypoint)
|
||||
|
||||
|
||||
end
|
||||
|
||||
-- Get home and destination airbases from waypoints.
|
||||
@ -3188,7 +3188,7 @@ function FLIGHTGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Altitud
|
||||
|
||||
-- Create waypoint data table.
|
||||
local waypoint=self:_CreateWaypoint(wp)
|
||||
|
||||
|
||||
-- Set altitude.
|
||||
if Altitude then
|
||||
waypoint.alt=UTILS.FeetToMeters(Altitude)
|
||||
@ -3426,12 +3426,12 @@ end
|
||||
function FLIGHTGROUP:GetClosestAirbase()
|
||||
|
||||
local group=self.group --Wrapper.Group#GROUP
|
||||
|
||||
|
||||
local coord=group:GetCoordinate()
|
||||
local coalition=self:GetCoalition()
|
||||
|
||||
|
||||
local airbase=coord:GetClosestAirbase() --(nil, coalition)
|
||||
|
||||
|
||||
return airbase
|
||||
end
|
||||
|
||||
|
||||
@ -2646,7 +2646,7 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
|
||||
local TaskFinal=self.group:TaskCombo({TaskControlled, TaskDone})
|
||||
|
||||
-- Set task for group.
|
||||
self:SetTask(TaskFinal, 1)
|
||||
self:SetTask(TaskFinal)
|
||||
|
||||
end
|
||||
|
||||
|
||||
@ -1500,4 +1500,24 @@ function UTILS.GetOSTime()
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
--- Shuffle a table accoring to Fisher Yeates algorithm
|
||||
--@param #table table to be shuffled
|
||||
--@return #table
|
||||
function UTILS.ShuffleTable(t)
|
||||
if t == nil or type(t) ~= "table" then
|
||||
BASE:I("Error in ShuffleTable: Missing or wrong tyåe of Argument")
|
||||
return
|
||||
end
|
||||
math.random()
|
||||
math.random()
|
||||
math.random()
|
||||
local TempTable = {}
|
||||
for i = 1, #t do
|
||||
local r = math.random(1,#t)
|
||||
TempTable[i] = t[r]
|
||||
table.remove(t,r)
|
||||
end
|
||||
return TempTable
|
||||
end
|
||||
|
||||
@ -1894,7 +1894,7 @@ do -- Patrol methods
|
||||
local ToCoord = COORDINATE:NewFromVec2( { x = Waypoint.x, y = Waypoint.y } )
|
||||
-- Create a "ground route point", which is a "point" structure that can be given as a parameter to a Task
|
||||
local Route = {}
|
||||
Route[#Route+1] = FromCoord:WaypointGround( 0 )
|
||||
Route[#Route+1] = FromCoord:WaypointGround( Speed, Formation )
|
||||
Route[#Route+1] = ToCoord:WaypointGround( Speed, Formation )
|
||||
|
||||
|
||||
@ -1947,7 +1947,7 @@ do -- Patrol methods
|
||||
|
||||
-- Create a "ground route point", which is a "point" structure that can be given as a parameter to a Task
|
||||
local Route = {}
|
||||
Route[#Route+1] = FromCoord:WaypointGround( 20 )
|
||||
Route[#Route+1] = FromCoord:WaypointGround( Speed, Formation )
|
||||
Route[#Route+1] = ToCoord:WaypointGround( Speed, Formation )
|
||||
|
||||
|
||||
|
||||
@ -1174,8 +1174,9 @@ end
|
||||
|
||||
--- Returns true if the UNIT is in the air.
|
||||
-- @param #UNIT self
|
||||
-- @param #boolean NoHeloCheck If true, no additonal checks for helos are performed.
|
||||
-- @return #boolean Return true if in the air or #nil if the UNIT is not existing or alive.
|
||||
function UNIT:InAir()
|
||||
function UNIT:InAir(NoHeloCheck)
|
||||
self:F2( self.UnitName )
|
||||
|
||||
-- Get DCS unit object.
|
||||
@ -1185,14 +1186,14 @@ function UNIT:InAir()
|
||||
|
||||
-- Get DCS result of whether unit is in air or not.
|
||||
local UnitInAir = DCSUnit:inAir()
|
||||
|
||||
|
||||
-- Get unit category.
|
||||
local UnitCategory = DCSUnit:getDesc().category
|
||||
|
||||
-- If DCS says that it is in air, check if this is really the case, since we might have landed on a building where inAir()=true but actually is not.
|
||||
-- This is a workaround since DCS currently does not acknoledge that helos land on buildings.
|
||||
-- Note however, that the velocity check will fail if the ground is moving, e.g. on an aircraft carrier!
|
||||
if UnitInAir==true and UnitCategory == Unit.Category.HELICOPTER then
|
||||
if UnitInAir==true and UnitCategory == Unit.Category.HELICOPTER and (not NoHeloCheck) then
|
||||
local VelocityVec3 = DCSUnit:getVelocity()
|
||||
local Velocity = UTILS.VecNorm(VelocityVec3)
|
||||
local Coordinate = DCSUnit:getPoint()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user