Merge branch 'develop' into FF/Ops

This commit is contained in:
Frank 2021-12-17 13:27:13 +01:00
commit 7e1552eeb4
11 changed files with 625 additions and 301 deletions

View File

@ -585,7 +585,7 @@ function AI_AIR:onafterRTB( AIGroup, From, Event, To )
if AIGroup and AIGroup:IsAlive() then if AIGroup and AIGroup:IsAlive() then
self:I( "Group " .. AIGroup:GetName() .. " ... RTB! ( " .. self:GetState() .. " )" ) self:T( "Group " .. AIGroup:GetName() .. " ... RTB! ( " .. self:GetState() .. " )" )
self:ClearTargetDistance() self:ClearTargetDistance()
--AIGroup:ClearTasks() --AIGroup:ClearTasks()

View File

@ -20,9 +20,9 @@
-- Various types of SET_ classes are available: -- Various types of SET_ classes are available:
-- --
-- * @{#SET_GROUP}: Defines a collection of @{Wrapper.Group}s filtered by filter criteria. -- * @{#SET_GROUP}: Defines a collection of @{Wrapper.Group}s filtered by filter criteria.
-- * @{#SET_UNIT}: Defines a colleciton of @{Wrapper.Unit}s filtered by filter criteria. -- * @{#SET_UNIT}: Defines a collection of @{Wrapper.Unit}s filtered by filter criteria.
-- * @{#SET_STATIC}: Defines a collection of @{Wrapper.Static}s filtered by filter criteria. -- * @{#SET_STATIC}: Defines a collection of @{Wrapper.Static}s filtered by filter criteria.
-- * @{#SET_CLIENT}: Defines a collection of @{Client}s filterd by filter criteria. -- * @{#SET_CLIENT}: Defines a collection of @{Client}s filtered by filter criteria.
-- * @{#SET_AIRBASE}: Defines a collection of @{Wrapper.Airbase}s filtered by filter criteria. -- * @{#SET_AIRBASE}: Defines a collection of @{Wrapper.Airbase}s filtered by filter criteria.
-- * @{#SET_CARGO}: Defines a collection of @{Cargo.Cargo}s filtered by filter criteria. -- * @{#SET_CARGO}: Defines a collection of @{Cargo.Cargo}s filtered by filter criteria.
-- * @{#SET_ZONE}: Defines a collection of @{Core.Zone}s filtered by filter criteria. -- * @{#SET_ZONE}: Defines a collection of @{Core.Zone}s filtered by filter criteria.
@ -50,14 +50,14 @@ do -- SET_BASE
--- @type SET_BASE --- @type SET_BASE
-- @field #table Filter Table of filters. -- @field #table Filter Table of filters.
-- @field #table Set Table of objects. -- @field #table Set Table of objects.
-- @field #table Index Table of indicies. -- @field #table Index Table of indices.
-- @field #table List Unused table. -- @field #table List Unused table.
-- @field Core.Scheduler#SCHEDULER CallScheduler -- @field Core.Scheduler#SCHEDULER CallScheduler
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- The @{Core.Set#SET_BASE} class defines the core functions that define a collection of objects. --- The @{Core.Set#SET_BASE} class defines the core functions that define a collection of objects.
-- A SET provides iterators to iterate the SET, but will **temporarily** yield the ForEach interator loop at defined **"intervals"** to the mail simulator loop. -- A SET provides iterators to iterate the SET, but will **temporarily** yield the ForEach iterator loop at defined **"intervals"** to the mail simulator loop.
-- In this way, large loops can be done while not blocking the simulator main processing loop. -- In this way, large loops can be done while not blocking the simulator main processing loop.
-- The default **"yield interval"** is after 10 objects processed. -- The default **"yield interval"** is after 10 objects processed.
-- The default **"time interval"** is after 0.001 seconds. -- The default **"time interval"** is after 0.001 seconds.
@ -68,7 +68,7 @@ do -- SET_BASE
-- --
-- ## Define the SET iterator **"yield interval"** and the **"time interval"** -- ## Define the SET iterator **"yield interval"** and the **"time interval"**
-- --
-- Modify the iterator intervals with the @{Core.Set#SET_BASE.SetInteratorIntervals} method. -- Modify the iterator intervals with the @{Core.Set#SET_BASE.SetIteratorIntervals} method.
-- You can set the **"yield interval"**, and the **"time interval"**. (See above). -- You can set the **"yield interval"**, and the **"time interval"**. (See above).
-- --
-- @field #SET_BASE SET_BASE -- @field #SET_BASE SET_BASE
@ -787,7 +787,7 @@ do -- SET_BASE
end end
----- Iterate the SET_BASE and call an interator function for each **alive** unit, providing the Unit and optional parameters. ----- Iterate the SET_BASE and call an iterator function for each **alive** unit, providing the Unit and optional parameters.
---- @param #SET_BASE self ---- @param #SET_BASE self
---- @param #function IteratorFunction The function that will be called when there is an alive unit in the SET_BASE. The function needs to accept a UNIT parameter. ---- @param #function IteratorFunction The function that will be called when there is an alive unit in the SET_BASE. The function needs to accept a UNIT parameter.
---- @return #SET_BASE self ---- @return #SET_BASE self
@ -799,7 +799,7 @@ do -- SET_BASE
-- return self -- return self
--end --end
-- --
----- Iterate the SET_BASE and call an interator function for each **alive** player, providing the Unit of the player and optional parameters. ----- Iterate the SET_BASE and call an iterator function for each **alive** player, providing the Unit of the player and optional parameters.
---- @param #SET_BASE self ---- @param #SET_BASE self
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_BASE. The function needs to accept a UNIT parameter. ---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_BASE. The function needs to accept a UNIT parameter.
---- @return #SET_BASE self ---- @return #SET_BASE self
@ -812,7 +812,7 @@ do -- SET_BASE
--end --end
-- --
-- --
----- Iterate the SET_BASE and call an interator function for each client, providing the Client to the function and optional parameters. ----- Iterate the SET_BASE and call an iterator function for each client, providing the Client to the function and optional parameters.
---- @param #SET_BASE self ---- @param #SET_BASE self
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_BASE. The function needs to accept a CLIENT parameter. ---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_BASE. The function needs to accept a CLIENT parameter.
---- @return #SET_BASE self ---- @return #SET_BASE self
@ -919,17 +919,13 @@ do -- SET_GROUP
-- * @{#SET_GROUP.FilterCategoryGround}: Builds the SET_GROUP from ground vehicles or infantry. -- * @{#SET_GROUP.FilterCategoryGround}: Builds the SET_GROUP from ground vehicles or infantry.
-- * @{#SET_GROUP.FilterCategoryShip}: Builds the SET_GROUP from ships. -- * @{#SET_GROUP.FilterCategoryShip}: Builds the SET_GROUP from ships.
-- * @{#SET_GROUP.FilterCategoryStructure}: Builds the SET_GROUP from structures. -- * @{#SET_GROUP.FilterCategoryStructure}: Builds the SET_GROUP from structures.
-- -- * @{#SET_GROUP.FilterZones}: Builds the SET_GROUP with the groups within a @{Core.Zone#ZONE}.
-- --
-- Once the filter criteria have been set for the SET_GROUP, you can start filtering using: -- Once the filter criteria have been set for the SET_GROUP, you can start filtering using:
-- --
-- * @{#SET_GROUP.FilterStart}: Starts the filtering of the groups within the SET_GROUP and add or remove GROUP objects **dynamically**. -- * @{#SET_GROUP.FilterStart}: Starts the filtering of the groups within the SET_GROUP and add or remove GROUP objects **dynamically**.
-- * @{#SET_GROUP.FilterOnce}: Filters of the groups **once**. -- * @{#SET_GROUP.FilterOnce}: Filters of the groups **once**.
-- --
-- Planned filter criteria within development are (so these are not yet available):
--
-- * @{#SET_GROUP.FilterZones}: Builds the SET_GROUP with the groups within a @{Core.Zone#ZONE}.
--
-- ## SET_GROUP iterators -- ## SET_GROUP iterators
-- --
-- Once the filters have been defined and the SET_GROUP has been built, you can iterate the SET_GROUP with the available iterator methods. -- Once the filters have been defined and the SET_GROUP has been built, you can iterate the SET_GROUP with the available iterator methods.
@ -949,7 +945,7 @@ do -- SET_GROUP
-- ### When a GROUP object crashes or is dead, the SET_GROUP will trigger a **Dead** event. -- ### When a GROUP object crashes or is dead, the SET_GROUP will trigger a **Dead** event.
-- --
-- You can handle the event using the OnBefore and OnAfter event handlers. -- You can handle the event using the OnBefore and OnAfter event handlers.
-- The event handlers need to have the paramters From, Event, To, GroupObject. -- The event handlers need to have the parameters From, Event, To, GroupObject.
-- The GroupObject is the GROUP object that is dead and within the SET_GROUP, and is passed as a parameter to the event handler. -- The GroupObject is the GROUP object that is dead and within the SET_GROUP, and is passed as a parameter to the event handler.
-- See the following example: -- See the following example:
-- --
@ -964,7 +960,7 @@ do -- SET_GROUP
-- end -- end
-- --
-- While this is a good example, there is a catch. -- While this is a good example, there is a catch.
-- Imageine you want to execute the code above, the the self would need to be from the object declared outside (above) the OnAfterDead method. -- Imagine you want to execute the code above, the the self would need to be from the object declared outside (above) the OnAfterDead method.
-- So, the self would need to contain another object. Fortunately, this can be done, but you must use then the **`.`** notation for the method. -- So, the self would need to contain another object. Fortunately, this can be done, but you must use then the **`.`** notation for the method.
-- See the modified example: -- See the modified example:
-- --
@ -996,6 +992,7 @@ do -- SET_GROUP
Categories = nil, Categories = nil,
Countries = nil, Countries = nil,
GroupPrefixes = nil, GroupPrefixes = nil,
Zones = nil,
}, },
FilterMeta = { FilterMeta = {
Coalitions = { Coalitions = {
@ -1171,6 +1168,30 @@ do -- SET_GROUP
end end
--- Builds a set of groups in zones.
-- @param #SET_GROUP self
-- @param #table Zones Table of Core.Zone#ZONE Zone objects, or a Core.Set#SET_ZONE
-- @return #SET_GROUP self
function SET_GROUP:FilterZones( Zones )
if not self.Filter.Zones then
self.Filter.Zones = {}
end
local zones = {}
if Zones.ClassName and Zones.ClassName == "SET_ZONE" then
zones = Zones.Set
elseif type( Zones ) ~= "table" or (type( Zones ) == "table" and Zones.ClassName ) then
self:E("***** FilterZones needs either a table of ZONE Objects or a SET_ZONE as parameter!")
return self
else
zones = Zones
end
for _,Zone in pairs( zones ) do
local zonename = Zone:GetName()
self.Filter.Zones[zonename] = Zone
end
return self
end
--- Builds a set of groups of coalitions. --- Builds a set of groups of coalitions.
-- Possible current coalitions are red, blue and neutral. -- Possible current coalitions are red, blue and neutral.
-- @param #SET_GROUP self -- @param #SET_GROUP self
@ -1513,7 +1534,7 @@ do -- SET_GROUP
--- Iterate the SET_GROUP and return true if all the @{Wrapper.Group#GROUP} are completely in the @{Core.Zone#ZONE} --- Iterate the SET_GROUP and return true if all the @{Wrapper.Group#GROUP} are completely in the @{Core.Zone#ZONE}
-- @param #SET_GROUP self -- @param #SET_GROUP self
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for. -- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @return #boolean true if all the @{Wrapper.Group#GROUP} are completly in the @{Core.Zone#ZONE}, false otherwise -- @return #boolean true if all the @{Wrapper.Group#GROUP} are completely in the @{Core.Zone#ZONE}, false otherwise
-- @usage -- @usage
-- local MyZone = ZONE:New("Zone1") -- local MyZone = ZONE:New("Zone1")
-- local MySetGroup = SET_GROUP:New() -- local MySetGroup = SET_GROUP:New()
@ -1561,7 +1582,7 @@ do -- SET_GROUP
--- Iterate the SET_GROUP and return true if at least one of the @{Wrapper.Group#GROUP} is completely inside the @{Core.Zone#ZONE} --- Iterate the SET_GROUP and return true if at least one of the @{Wrapper.Group#GROUP} is completely inside the @{Core.Zone#ZONE}
-- @param #SET_GROUP self -- @param #SET_GROUP self
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for. -- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @return #boolean true if at least one of the @{Wrapper.Group#GROUP} is completly inside the @{Core.Zone#ZONE}, false otherwise. -- @return #boolean true if at least one of the @{Wrapper.Group#GROUP} is completely inside the @{Core.Zone#ZONE}, false otherwise.
-- @usage -- @usage
-- local MyZone = ZONE:New("Zone1") -- local MyZone = ZONE:New("Zone1")
-- local MySetGroup = SET_GROUP:New() -- local MySetGroup = SET_GROUP:New()
@ -1586,7 +1607,7 @@ do -- SET_GROUP
--- Iterate the SET_GROUP and return true if at least one @{#UNIT} of one @{GROUP} of the @{SET_GROUP} is in @{ZONE} --- Iterate the SET_GROUP and return true if at least one @{#UNIT} of one @{GROUP} of the @{SET_GROUP} is in @{ZONE}
-- @param #SET_GROUP self -- @param #SET_GROUP self
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for. -- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @return #boolean true if at least one of the @{Wrapper.Group#GROUP} is partly or completly inside the @{Core.Zone#ZONE}, false otherwise. -- @return #boolean true if at least one of the @{Wrapper.Group#GROUP} is partly or completely inside the @{Core.Zone#ZONE}, false otherwise.
-- @usage -- @usage
-- local MyZone = ZONE:New("Zone1") -- local MyZone = ZONE:New("Zone1")
-- local MySetGroup = SET_GROUP:New() -- local MySetGroup = SET_GROUP:New()
@ -1612,7 +1633,7 @@ do -- SET_GROUP
-- Will return false if a @{GROUP} is fully in the @{ZONE} -- Will return false if a @{GROUP} is fully in the @{ZONE}
-- @param #SET_GROUP self -- @param #SET_GROUP self
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for. -- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @return #boolean true if at least one of the @{Wrapper.Group#GROUP} is partly or completly inside the @{Core.Zone#ZONE}, false otherwise. -- @return #boolean true if at least one of the @{Wrapper.Group#GROUP} is partly or completely inside the @{Core.Zone#ZONE}, false otherwise.
-- @usage -- @usage
-- local MyZone = ZONE:New("Zone1") -- local MyZone = ZONE:New("Zone1")
-- local MySetGroup = SET_GROUP:New() -- local MySetGroup = SET_GROUP:New()
@ -1742,7 +1763,7 @@ do -- SET_GROUP
return CountG,CountU return CountG,CountU
end end
----- Iterate the SET_GROUP and call an interator function for each **alive** player, providing the Group of the player and optional parameters. ----- Iterate the SET_GROUP and call an iterator function for each **alive** player, providing the Group of the player and optional parameters.
---- @param #SET_GROUP self ---- @param #SET_GROUP self
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_GROUP. The function needs to accept a GROUP parameter. ---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_GROUP. The function needs to accept a GROUP parameter.
---- @return #SET_GROUP self ---- @return #SET_GROUP self
@ -1755,7 +1776,7 @@ do -- SET_GROUP
--end --end
-- --
-- --
----- Iterate the SET_GROUP and call an interator function for each client, providing the Client to the function and optional parameters. ----- Iterate the SET_GROUP and call an iterator function for each client, providing the Client to the function and optional parameters.
---- @param #SET_GROUP self ---- @param #SET_GROUP self
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_GROUP. The function needs to accept a CLIENT parameter. ---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_GROUP. The function needs to accept a CLIENT parameter.
---- @return #SET_GROUP self ---- @return #SET_GROUP self
@ -1828,7 +1849,18 @@ do -- SET_GROUP
end end
MGroupInclude = MGroupInclude and MGroupPrefix MGroupInclude = MGroupInclude and MGroupPrefix
end end
if self.Filter.Zones then
local MGroupZone = false
for ZoneName, Zone in pairs( self.Filter.Zones ) do
self:T3( "Zone:", ZoneName )
if MGroup:IsInZone(Zone) then
MGroupZone = true
end
end
MGroupInclude = MGroupInclude and MGroupZone
end
self:T2( MGroupInclude ) self:T2( MGroupInclude )
return MGroupInclude return MGroupInclude
end end
@ -1889,16 +1921,13 @@ do -- SET_UNIT
-- * @{#SET_UNIT.FilterCountries}: Builds the SET_UNIT with the units belonging to the country(ies). -- * @{#SET_UNIT.FilterCountries}: Builds the SET_UNIT with the units belonging to the country(ies).
-- * @{#SET_UNIT.FilterPrefixes}: Builds the SET_UNIT with the units sharing the same string(s) in their name. **ATTENTION!** Bad naming convention as this *does not* only filter *prefixes*. -- * @{#SET_UNIT.FilterPrefixes}: Builds the SET_UNIT with the units sharing the same string(s) in their name. **ATTENTION!** Bad naming convention as this *does not* only filter *prefixes*.
-- * @{#SET_UNIT.FilterActive}: Builds the SET_UNIT with the units that are only active. Units that are inactive (late activation) won't be included in the set! -- * @{#SET_UNIT.FilterActive}: Builds the SET_UNIT with the units that are only active. Units that are inactive (late activation) won't be included in the set!
-- -- * @{#SET_UNIT.FilterZones}: Builds the SET_UNIT with the units within a @{Core.Zone#ZONE}.
--
-- Once the filter criteria have been set for the SET_UNIT, you can start filtering using: -- Once the filter criteria have been set for the SET_UNIT, you can start filtering using:
-- --
-- * @{#SET_UNIT.FilterStart}: Starts the filtering of the units **dynamically**. -- * @{#SET_UNIT.FilterStart}: Starts the filtering of the units **dynamically**.
-- * @{#SET_UNIT.FilterOnce}: Filters of the units **once**. -- * @{#SET_UNIT.FilterOnce}: Filters of the units **once**.
-- --
-- Planned filter criteria within development are (so these are not yet available):
--
-- * @{#SET_UNIT.FilterZones}: Builds the SET_UNIT with the units within a @{Core.Zone#ZONE}.
--
-- ## 4) SET_UNIT iterators -- ## 4) SET_UNIT iterators
-- --
-- Once the filters have been defined and the SET_UNIT has been built, you can iterate the SET_UNIT with the available iterator methods. -- Once the filters have been defined and the SET_UNIT has been built, you can iterate the SET_UNIT with the available iterator methods.
@ -1928,7 +1957,7 @@ do -- SET_UNIT
-- ### 6.1) When a UNIT object crashes or is dead, the SET_UNIT will trigger a **Dead** event. -- ### 6.1) When a UNIT object crashes or is dead, the SET_UNIT will trigger a **Dead** event.
-- --
-- You can handle the event using the OnBefore and OnAfter event handlers. -- You can handle the event using the OnBefore and OnAfter event handlers.
-- The event handlers need to have the paramters From, Event, To, GroupObject. -- The event handlers need to have the parameters From, Event, To, GroupObject.
-- The GroupObject is the UNIT object that is dead and within the SET_UNIT, and is passed as a parameter to the event handler. -- The GroupObject is the UNIT object that is dead and within the SET_UNIT, and is passed as a parameter to the event handler.
-- See the following example: -- See the following example:
-- --
@ -1943,7 +1972,7 @@ do -- SET_UNIT
-- end -- end
-- --
-- While this is a good example, there is a catch. -- While this is a good example, there is a catch.
-- Imageine you want to execute the code above, the the self would need to be from the object declared outside (above) the OnAfterDead method. -- Imagine you want to execute the code above, the the self would need to be from the object declared outside (above) the OnAfterDead method.
-- So, the self would need to contain another object. Fortunately, this can be done, but you must use then the **`.`** notation for the method. -- So, the self would need to contain another object. Fortunately, this can be done, but you must use then the **`.`** notation for the method.
-- See the modified example: -- See the modified example:
-- --
@ -1975,6 +2004,7 @@ do -- SET_UNIT
Types = nil, Types = nil,
Countries = nil, Countries = nil,
UnitPrefixes = nil, UnitPrefixes = nil,
Zones = nil,
}, },
FilterMeta = { FilterMeta = {
Coalitions = { Coalitions = {
@ -2166,7 +2196,31 @@ do -- SET_UNIT
end end
return self return self
end end
--- Builds a set of units in zones.
-- @param #SET_UNIT self
-- @param #table Zones Table of Core.Zone#ZONE Zone objects, or a Core.Set#SET_ZONE
-- @return #SET_UNIT self
function SET_UNIT:FilterZones( Zones )
if not self.Filter.Zones then
self.Filter.Zones = {}
end
local zones = {}
if Zones.ClassName and Zones.ClassName == "SET_ZONE" then
zones = Zones.Set
elseif type( Zones ) ~= "table" or (type( Zones ) == "table" and Zones.ClassName ) then
self:E("***** FilterZones needs either a table of ZONE Objects or a SET_ZONE as parameter!")
return self
else
zones = Zones
end
for _,Zone in pairs( zones ) do
local zonename = Zone:GetName()
self.Filter.Zones[zonename] = Zone
end
return self
end
--- Builds a set of units that are only active. --- Builds a set of units that are only active.
-- Only the units that are active will be included within the set. -- Only the units that are active will be included within the set.
-- @param #SET_UNIT self -- @param #SET_UNIT self
@ -2344,7 +2398,7 @@ do -- SET_UNIT
end end
--- Iterate the SET_UNIT and call an interator function for each **alive** UNIT, providing the UNIT and optional parameters. --- Iterate the SET_UNIT and call an iterator function for each **alive** UNIT, providing the UNIT and optional parameters.
-- @param #SET_UNIT self -- @param #SET_UNIT self
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the SET_UNIT. The function needs to accept a UNIT parameter. -- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the SET_UNIT. The function needs to accept a UNIT parameter.
-- @return #SET_UNIT self -- @return #SET_UNIT self
@ -2404,7 +2458,7 @@ do -- SET_UNIT
end end
--- Iterate the SET_UNIT **sorted *per Threat Level** and call an interator function for each **alive** UNIT, providing the UNIT and optional parameters. --- Iterate the SET_UNIT **sorted *per Threat Level** and call an iterator function for each **alive** UNIT, providing the UNIT and optional parameters.
-- --
-- @param #SET_UNIT self -- @param #SET_UNIT self
-- @param #number FromThreatLevel The TreatLevel to start the evaluation **From** (this must be a value between 0 and 10). -- @param #number FromThreatLevel The TreatLevel to start the evaluation **From** (this must be a value between 0 and 10).
@ -2800,7 +2854,7 @@ do -- SET_UNIT
----- Iterate the SET_UNIT and call an interator function for each **alive** player, providing the Unit of the player and optional parameters. ----- Iterate the SET_UNIT and call an iterator function for each **alive** player, providing the Unit of the player and optional parameters.
---- @param #SET_UNIT self ---- @param #SET_UNIT self
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_UNIT. The function needs to accept a UNIT parameter. ---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_UNIT. The function needs to accept a UNIT parameter.
---- @return #SET_UNIT self ---- @return #SET_UNIT self
@ -2813,7 +2867,7 @@ do -- SET_UNIT
--end --end
-- --
-- --
----- Iterate the SET_UNIT and call an interator function for each client, providing the Client to the function and optional parameters. ----- Iterate the SET_UNIT and call an iterator function for each client, providing the Client to the function and optional parameters.
---- @param #SET_UNIT self ---- @param #SET_UNIT self
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_UNIT. The function needs to accept a CLIENT parameter. ---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_UNIT. The function needs to accept a CLIENT parameter.
---- @return #SET_UNIT self ---- @return #SET_UNIT self
@ -2925,7 +2979,18 @@ do -- SET_UNIT
MUnitInclude = MUnitInclude and MUnitSEAD MUnitInclude = MUnitInclude and MUnitSEAD
end end
end end
if self.Filter.Zones then
local MGroupZone = false
for ZoneName, Zone in pairs( self.Filter.Zones ) do
self:T3( "Zone:", ZoneName )
if MUnit:IsInZone(Zone) then
MGroupZone = true
end
end
MUnitInclude = MUnitInclude and MGroupZone
end
self:T2( MUnitInclude ) self:T2( MUnitInclude )
return MUnitInclude return MUnitInclude
end end
@ -3008,15 +3073,12 @@ do -- SET_STATIC
-- * @{#SET_STATIC.FilterTypes}: Builds the SET_STATIC with the units belonging to the unit type(s). -- * @{#SET_STATIC.FilterTypes}: Builds the SET_STATIC with the units belonging to the unit type(s).
-- * @{#SET_STATIC.FilterCountries}: Builds the SET_STATIC with the units belonging to the country(ies). -- * @{#SET_STATIC.FilterCountries}: Builds the SET_STATIC with the units belonging to the country(ies).
-- * @{#SET_STATIC.FilterPrefixes}: Builds the SET_STATIC with the units containing the same string(s) in their name. **ATTENTION** bad naming convention as this *does not** only filter *prefixes*. -- * @{#SET_STATIC.FilterPrefixes}: Builds the SET_STATIC with the units containing the same string(s) in their name. **ATTENTION** bad naming convention as this *does not** only filter *prefixes*.
-- -- * @{#SET_STATIC.FilterZones}: Builds the SET_STATIC with the units within a @{Core.Zone#ZONE}.
--
-- Once the filter criteria have been set for the SET_STATIC, you can start filtering using: -- Once the filter criteria have been set for the SET_STATIC, you can start filtering using:
-- --
-- * @{#SET_STATIC.FilterStart}: Starts the filtering of the units within the SET_STATIC. -- * @{#SET_STATIC.FilterStart}: Starts the filtering of the units within the SET_STATIC.
-- --
-- Planned filter criteria within development are (so these are not yet available):
--
-- * @{#SET_STATIC.FilterZones}: Builds the SET_STATIC with the units within a @{Core.Zone#ZONE}.
--
-- ## SET_STATIC iterators -- ## SET_STATIC iterators
-- --
-- Once the filters have been defined and the SET_STATIC has been built, you can iterate the SET_STATIC with the available iterator methods. -- Once the filters have been defined and the SET_STATIC has been built, you can iterate the SET_STATIC with the available iterator methods.
@ -3024,14 +3086,9 @@ do -- SET_STATIC
-- The following iterator methods are currently available within the SET_STATIC: -- The following iterator methods are currently available within the SET_STATIC:
-- --
-- * @{#SET_STATIC.ForEachStatic}: Calls a function for each alive unit it finds within the SET_STATIC. -- * @{#SET_STATIC.ForEachStatic}: Calls a function for each alive unit it finds within the SET_STATIC.
-- * @{#SET_GROUP.ForEachGroupCompletelyInZone}: Iterate the SET_GROUP and call an iterator function for each **alive** GROUP presence completely in a @{Zone}, providing the GROUP and optional parameters to the called function. -- * @{#SET_STATIC.ForEachStaticCompletelyInZone}: Iterate the SET_STATIC and call an iterator function for each **alive** STATIC presence completely in a @{Zone}, providing the STATIC and optional parameters to the called function.
-- * @{#SET_GROUP.ForEachGroupNotInZone}: Iterate the SET_GROUP and call an iterator function for each **alive** GROUP presence not in a @{Zone}, providing the GROUP and optional parameters to the called function. -- * @{#SET_STATIC.ForEachStaticInZone}: Iterate the SET_STATIC and call an iterator function for each **alive** STATIC presence completely in a @{Zone}, providing the STATIC and optional parameters to the called function.
-- -- * @{#SET_STATIC.ForEachStaticNotInZone}: Iterate the SET_STATIC and call an iterator function for each **alive** STATIC presence not in a @{Zone}, providing the STATIC and optional parameters to the called function.
-- Planned iterators methods in development are (so these are not yet available):
--
-- * @{#SET_STATIC.ForEachStaticInZone}: Calls a function for each unit contained within the SET_STATIC.
-- * @{#SET_STATIC.ForEachStaticCompletelyInZone}: Iterate and call an iterator function for each **alive** STATIC presence completely in a @{Zone}, providing the STATIC and optional parameters to the called function.
-- * @{#SET_STATIC.ForEachStaticNotInZone}: Iterate and call an iterator function for each **alive** STATIC presence not in a @{Zone}, providing the STATIC and optional parameters to the called function.
-- --
-- ## SET_STATIC atomic methods -- ## SET_STATIC atomic methods
-- --
@ -3050,6 +3107,7 @@ do -- SET_STATIC
Types = nil, Types = nil,
Countries = nil, Countries = nil,
StaticPrefixes = nil, StaticPrefixes = nil,
Zones = nil,
}, },
FilterMeta = { FilterMeta = {
Coalitions = { Coalitions = {
@ -3161,7 +3219,31 @@ do -- SET_STATIC
end end
return self return self
end end
--- Builds a set of statics in zones.
-- @param #SET_STATIC self
-- @param #table Zones Table of Core.Zone#ZONE Zone objects, or a Core.Set#SET_ZONE
-- @return #SET_STATIC self
function SET_STATIC:FilterZones( Zones )
if not self.Filter.Zones then
self.Filter.Zones = {}
end
local zones = {}
if Zones.ClassName and Zones.ClassName == "SET_ZONE" then
zones = Zones.Set
elseif type( Zones ) ~= "table" or (type( Zones ) == "table" and Zones.ClassName ) then
self:E("***** FilterZones needs either a table of ZONE Objects or a SET_ZONE as parameter!")
return self
else
zones = Zones
end
for _,Zone in pairs( zones ) do
local zonename = Zone:GetName()
self.Filter.Zones[zonename] = Zone
end
return self
end
--- Builds a set of units out of categories. --- Builds a set of units out of categories.
-- Possible current categories are plane, helicopter, ground, ship. -- Possible current categories are plane, helicopter, ground, ship.
@ -3371,7 +3453,7 @@ do -- SET_STATIC
end end
--- Iterate the SET_STATIC and call an interator function for each **alive** STATIC, providing the STATIC and optional parameters. --- Iterate the SET_STATIC and call an iterator function for each **alive** STATIC, providing the STATIC and optional parameters.
-- @param #SET_STATIC self -- @param #SET_STATIC self
-- @param #function IteratorFunction The function that will be called when there is an alive STATIC in the SET_STATIC. The function needs to accept a STATIC parameter. -- @param #function IteratorFunction The function that will be called when there is an alive STATIC in the SET_STATIC. The function needs to accept a STATIC parameter.
-- @return #SET_STATIC self -- @return #SET_STATIC self
@ -3650,7 +3732,18 @@ do -- SET_STATIC
end end
MStaticInclude = MStaticInclude and MStaticPrefix MStaticInclude = MStaticInclude and MStaticPrefix
end end
if self.Filter.Zones then
local MStaticZone = false
for ZoneName, Zone in pairs( self.Filter.Zones ) do
self:T3( "Zone:", ZoneName )
if MStatic and MStatic:IsInZone(Zone) then
MStaticZone = true
end
end
MStaticInclude = MStaticInclude and MStaticZone
end
self:T2( MStaticInclude ) self:T2( MStaticInclude )
return MStaticInclude return MStaticInclude
end end
@ -3721,16 +3814,13 @@ do -- SET_CLIENT
-- * @{#SET_CLIENT.FilterCountries}: Builds the SET_CLIENT with the clients belonging to the country(ies). -- * @{#SET_CLIENT.FilterCountries}: Builds the SET_CLIENT with the clients belonging to the country(ies).
-- * @{#SET_CLIENT.FilterPrefixes}: Builds the SET_CLIENT with the clients containing the same string(s) in their unit/pilot name. **ATTENTION!** Bad naming convention as this *does not* only filter *prefixes*. -- * @{#SET_CLIENT.FilterPrefixes}: Builds the SET_CLIENT with the clients containing the same string(s) in their unit/pilot name. **ATTENTION!** Bad naming convention as this *does not* only filter *prefixes*.
-- * @{#SET_CLIENT.FilterActive}: Builds the SET_CLIENT with the units that are only active. Units that are inactive (late activation) won't be included in the set! -- * @{#SET_CLIENT.FilterActive}: Builds the SET_CLIENT with the units that are only active. Units that are inactive (late activation) won't be included in the set!
-- -- * @{#SET_CLIENT.FilterZones}: Builds the SET_CLIENT with the clients within a @{Core.Zone#ZONE}.
--
-- Once the filter criteria have been set for the SET_CLIENT, you can start filtering using: -- Once the filter criteria have been set for the SET_CLIENT, you can start filtering using:
-- --
-- * @{#SET_CLIENT.FilterStart}: Starts the filtering of the clients **dynamically**. -- * @{#SET_CLIENT.FilterStart}: Starts the filtering of the clients **dynamically**.
-- * @{#SET_CLIENT.FilterOnce}: Filters the clients **once**. -- * @{#SET_CLIENT.FilterOnce}: Filters the clients **once**.
-- --
-- Planned filter criteria within development are (so these are not yet available):
--
-- * @{#SET_CLIENT.FilterZones}: Builds the SET_CLIENT with the clients within a @{Core.Zone#ZONE}.
--
-- ## 4) SET_CLIENT iterators -- ## 4) SET_CLIENT iterators
-- --
-- Once the filters have been defined and the SET_CLIENT has been built, you can iterate the SET_CLIENT with the available iterator methods. -- Once the filters have been defined and the SET_CLIENT has been built, you can iterate the SET_CLIENT with the available iterator methods.
@ -3750,6 +3840,7 @@ do -- SET_CLIENT
Types = nil, Types = nil,
Countries = nil, Countries = nil,
ClientPrefixes = nil, ClientPrefixes = nil,
Zones = nil,
}, },
FilterMeta = { FilterMeta = {
Coalitions = { Coalitions = {
@ -3946,7 +4037,29 @@ do -- SET_CLIENT
return self return self
end end
--- Builds a set of clients in zones.
-- @param #SET_CLIENT self
-- @param #table Zones Table of Core.Zone#ZONE Zone objects, or a Core.Set#SET_ZONE
-- @return #SET_TABLE self
function SET_CLIENT:FilterZones( Zones )
if not self.Filter.Zones then
self.Filter.Zones = {}
end
local zones = {}
if Zones.ClassName and Zones.ClassName == "SET_ZONE" then
zones = Zones.Set
elseif type( Zones ) ~= "table" or (type( Zones ) == "table" and Zones.ClassName ) then
self:E("***** FilterZones needs either a table of ZONE Objects or a SET_ZONE as parameter!")
return self
else
zones = Zones
end
for _,Zone in pairs( zones ) do
local zonename = Zone:GetName()
self.Filter.Zones[zonename] = Zone
end
return self
end
--- Starts the filtering. --- Starts the filtering.
-- @param #SET_CLIENT self -- @param #SET_CLIENT self
@ -3987,7 +4100,7 @@ do -- SET_CLIENT
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName] return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
end end
--- Iterate the SET_CLIENT and call an interator function for each **alive** CLIENT, providing the CLIENT and optional parameters. --- Iterate the SET_CLIENT and call an iterator function for each **alive** CLIENT, providing the CLIENT and optional parameters.
-- @param #SET_CLIENT self -- @param #SET_CLIENT self
-- @param #function IteratorFunction The function that will be called when there is an alive CLIENT in the SET_CLIENT. The function needs to accept a CLIENT parameter. -- @param #function IteratorFunction The function that will be called when there is an alive CLIENT in the SET_CLIENT. The function needs to accept a CLIENT parameter.
-- @return #SET_CLIENT self -- @return #SET_CLIENT self
@ -4145,6 +4258,18 @@ do -- SET_CLIENT
end end
end end
if self.Filter.Zones then
local MClientZone = false
for ZoneName, Zone in pairs( self.Filter.Zones ) do
self:T3( "Zone:", ZoneName )
local unit = MClient:GetClientGroupUnit()
if unit and unit:IsInZone(Zone) then
MClientZone = true
end
end
MClientInclude = MClientInclude and MClientZone
end
self:T2( MClientInclude ) self:T2( MClientInclude )
return MClientInclude return MClientInclude
end end
@ -4205,6 +4330,7 @@ do -- SET_PLAYER
Types = nil, Types = nil,
Countries = nil, Countries = nil,
ClientPrefixes = nil, ClientPrefixes = nil,
Zones = nil,
}, },
FilterMeta = { FilterMeta = {
Coalitions = { Coalitions = {
@ -4296,7 +4422,31 @@ do -- SET_PLAYER
end end
return self return self
end end
--- Builds a set of players in zones.
-- @param #SET_PLAYER self
-- @param #table Zones Table of Core.Zone#ZONE Zone objects, or a Core.Set#SET_ZONE
-- @return #SET_PLAYER self
function SET_PLAYER:FilterZones( Zones )
if not self.Filter.Zones then
self.Filter.Zones = {}
end
local zones = {}
if Zones.ClassName and Zones.ClassName == "SET_ZONE" then
zones = Zones.Set
elseif type( Zones ) ~= "table" or (type( Zones ) == "table" and Zones.ClassName ) then
self:E("***** FilterZones needs either a table of ZONE Objects or a SET_ZONE as parameter!")
return self
else
zones = Zones
end
for _,Zone in pairs( zones ) do
local zonename = Zone:GetName()
self.Filter.Zones[zonename] = Zone
end
return self
end
--- Builds a set of clients out of categories joined by players. --- Builds a set of clients out of categories joined by players.
-- Possible current categories are plane, helicopter, ground, ship. -- Possible current categories are plane, helicopter, ground, ship.
@ -4415,7 +4565,7 @@ do -- SET_PLAYER
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName] return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
end end
--- Iterate the SET_PLAYER and call an interator function for each **alive** CLIENT, providing the CLIENT and optional parameters. --- Iterate the SET_PLAYER and call an iterator function for each **alive** CLIENT, providing the CLIENT and optional parameters.
-- @param #SET_PLAYER self -- @param #SET_PLAYER self
-- @param #function IteratorFunction The function that will be called when there is an alive CLIENT in the SET_PLAYER. The function needs to accept a CLIENT parameter. -- @param #function IteratorFunction The function that will be called when there is an alive CLIENT in the SET_PLAYER. The function needs to accept a CLIENT parameter.
-- @return #SET_PLAYER self -- @return #SET_PLAYER self
@ -4546,7 +4696,19 @@ do -- SET_PLAYER
MClientInclude = MClientInclude and MClientPrefix MClientInclude = MClientInclude and MClientPrefix
end end
end end
if self.Filter.Zones then
local MClientZone = false
for ZoneName, Zone in pairs( self.Filter.Zones ) do
self:T3( "Zone:", ZoneName )
local unit = MClient:GetClientGroupUnit()
if unit and unit:IsInZone(Zone) then
MClientZone = true
end
end
MClientInclude = MClientInclude and MClientZone
end
self:T2( MClientInclude ) self:T2( MClientInclude )
return MClientInclude return MClientInclude
end end
@ -4837,7 +4999,7 @@ do -- SET_AIRBASE
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName] return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
end end
--- Iterate the SET_AIRBASE and call an interator function for each AIRBASE, providing the AIRBASE and optional parameters. --- Iterate the SET_AIRBASE and call an iterator function for each AIRBASE, providing the AIRBASE and optional parameters.
-- @param #SET_AIRBASE self -- @param #SET_AIRBASE self
-- @param #function IteratorFunction The function that will be called when there is an alive AIRBASE in the SET_AIRBASE. The function needs to accept a AIRBASE parameter. -- @param #function IteratorFunction The function that will be called when there is an alive AIRBASE in the SET_AIRBASE. The function needs to accept a AIRBASE parameter.
-- @return #SET_AIRBASE self -- @return #SET_AIRBASE self
@ -5168,7 +5330,7 @@ do -- SET_CARGO
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName] return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
end end
--- (R2.1) Iterate the SET_CARGO and call an interator function for each CARGO, providing the CARGO and optional parameters. --- (R2.1) Iterate the SET_CARGO and call an iterator function for each CARGO, providing the CARGO and optional parameters.
-- @param #SET_CARGO self -- @param #SET_CARGO self
-- @param #function IteratorFunction The function that will be called when there is an alive CARGO in the SET_CARGO. The function needs to accept a CARGO parameter. -- @param #function IteratorFunction The function that will be called when there is an alive CARGO in the SET_CARGO. The function needs to accept a CARGO parameter.
-- @return #SET_CARGO self -- @return #SET_CARGO self
@ -5589,7 +5751,7 @@ do -- SET_ZONE
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName] return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
end end
--- Iterate the SET_ZONE and call an interator function for each ZONE, providing the ZONE and optional parameters. --- Iterate the SET_ZONE and call an iterator function for each ZONE, providing the ZONE and optional parameters.
-- @param #SET_ZONE self -- @param #SET_ZONE self
-- @param #function IteratorFunction The function that will be called when there is an alive ZONE in the SET_ZONE. The function needs to accept a AIRBASE parameter. -- @param #function IteratorFunction The function that will be called when there is an alive ZONE in the SET_ZONE. The function needs to accept a AIRBASE parameter.
-- @return #SET_ZONE self -- @return #SET_ZONE self
@ -5907,7 +6069,7 @@ do -- SET_ZONE_GOAL
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName] return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
end end
--- Iterate the SET_ZONE_GOAL and call an interator function for each ZONE, providing the ZONE and optional parameters. --- Iterate the SET_ZONE_GOAL and call an iterator function for each ZONE, providing the ZONE and optional parameters.
-- @param #SET_ZONE_GOAL self -- @param #SET_ZONE_GOAL self
-- @param #function IteratorFunction The function that will be called when there is an alive ZONE in the SET_ZONE_GOAL. The function needs to accept a AIRBASE parameter. -- @param #function IteratorFunction The function that will be called when there is an alive ZONE in the SET_ZONE_GOAL. The function needs to accept a AIRBASE parameter.
-- @return #SET_ZONE_GOAL self -- @return #SET_ZONE_GOAL self
@ -6077,7 +6239,7 @@ do -- SET_OPSGROUP
-- ### When a GROUP object crashes or is dead, the SET_OPSGROUP will trigger a **Dead** event. -- ### When a GROUP object crashes or is dead, the SET_OPSGROUP will trigger a **Dead** event.
-- --
-- You can handle the event using the OnBefore and OnAfter event handlers. -- You can handle the event using the OnBefore and OnAfter event handlers.
-- The event handlers need to have the paramters From, Event, To, GroupObject. -- The event handlers need to have the parameters From, Event, To, GroupObject.
-- The GroupObject is the GROUP object that is dead and within the SET_OPSGROUP, and is passed as a parameter to the event handler. -- The GroupObject is the GROUP object that is dead and within the SET_OPSGROUP, and is passed as a parameter to the event handler.
-- See the following example: -- See the following example:
-- --

View File

@ -878,16 +878,16 @@ end
-- @param #number Formation Formation of the group. -- @param #number Formation Formation of the group.
function ARMYGROUP:onbeforeUpdateRoute(From, Event, To, n, N, Speed, Formation) function ARMYGROUP:onbeforeUpdateRoute(From, Event, To, n, N, Speed, Formation)
if self:IsWaiting() then if self:IsWaiting() then
self:E(self.lid.."Update route denied. Group is WAIRING!") self:T(self.lid.."Update route denied. Group is WAIRING!")
return false return false
elseif self:IsInUtero() then elseif self:IsInUtero() then
self:E(self.lid.."Update route denied. Group is INUTERO!") self:T(self.lid.."Update route denied. Group is INUTERO!")
return false return false
elseif self:IsDead() then elseif self:IsDead() then
self:E(self.lid.."Update route denied. Group is DEAD!") self:T(self.lid.."Update route denied. Group is DEAD!")
return false return false
elseif self:IsStopped() then elseif self:IsStopped() then
self:E(self.lid.."Update route denied. Group is STOPPED!") self:T(self.lid.."Update route denied. Group is STOPPED!")
return false return false
elseif self:IsHolding() then elseif self:IsHolding() then
self:T(self.lid.."Update route denied. Group is holding position!") self:T(self.lid.."Update route denied. Group is holding position!")
@ -908,7 +908,7 @@ end
function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation) function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation)
-- Debug info. -- 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)) local text=string.format("Update route state=%s: n=%s, N=%s, Speed=%d, Formation=%s", self:GetState(), tostring(n), tostring(N), tonumber(Speed), tostring(Formation))
self:T(self.lid..text) self:T(self.lid..text)
-- Update route from this waypoint number onwards. -- Update route from this waypoint number onwards.
@ -929,7 +929,7 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation)
self:T({wp}) self:T({wp})
-- Speed. -- Speed.
if Speed then if Speed then
wp.speed=UTILS.KnotsToMps(Speed) wp.speed=UTILS.KnotsToMps(tonumber(Speed))
else else
-- Take default waypoint speed. But make sure speed>0 if patrol ad infinitum. -- Take default waypoint speed. But make sure speed>0 if patrol ad infinitum.
if wp.speed<0.1 then --self.adinfinitum and if wp.speed<0.1 then --self.adinfinitum and
@ -1031,7 +1031,7 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation)
-- Passed final WP ==> Full Stop -- Passed final WP ==> Full Stop
--- ---
self:E(self.lid..string.format("WARNING: Passed final WP when UpdateRoute() ==> Full Stop!")) self:T(self.lid..string.format("WARNING: Passed final WP when UpdateRoute() ==> Full Stop!"))
self:FullStop() self:FullStop()
end end
@ -1250,7 +1250,7 @@ function ARMYGROUP:onafterRTZ(From, Event, To, Zone, Formation)
end end
else else
self:E(self.lid.."ERROR: No RTZ zone given!") self:T(self.lid.."ERROR: No RTZ zone given!")
end end
end end
@ -1386,7 +1386,7 @@ function ARMYGROUP:onbeforeEngageTarget(From, Event, To, Target)
local ammo=self:GetAmmoTot() local ammo=self:GetAmmoTot()
if ammo.Total==0 then if ammo.Total==0 then
self:E(self.lid.."WARNING: Cannot engage TARGET because no ammo left!") self:T(self.lid.."WARNING: Cannot engage TARGET because no ammo left!")
return false return false
end end
@ -1684,7 +1684,7 @@ function ARMYGROUP:_InitGroup(Template)
-- Quick check. -- Quick check.
if #units~=size0 then if #units~=size0 then
self:E(self.lid..string.format("ERROR: Got #units=%d but group consists of %d units!", #units, size0)) self:T(self.lid..string.format("ERROR: Got #units=%d but group consists of %d units!", #units, size0))
end end
-- Add elemets. -- Add elemets.
@ -1714,7 +1714,7 @@ function ARMYGROUP:SwitchFormation(Formation, Permanently, NoRouteUpdate)
if self:IsAlive() or self:IsInUtero() then if self:IsAlive() or self:IsInUtero() then
Formation=Formation or self.optionDefault.Formation Formation=Formation or (self.optionDefault.Formation or "Off road")
Permanently = Permanently or false Permanently = Permanently or false
if Permanently then if Permanently then
@ -1724,7 +1724,7 @@ function ARMYGROUP:SwitchFormation(Formation, Permanently, NoRouteUpdate)
end end
-- Set current formation. -- Set current formation.
self.option.Formation=Formation self.option.Formation=Formation or "Off road"
if self:IsInUtero() then if self:IsInUtero() then
self:T(self.lid..string.format("Will switch formation to %s (permanently=%s) when group is spawned", tostring(self.option.Formation), tostring(Permanently))) self:T(self.lid..string.format("Will switch formation to %s (permanently=%s) when group is spawned", tostring(self.option.Formation), tostring(Permanently)))

View File

@ -1977,7 +1977,7 @@ function AUFTRAG:_DetermineAuftragType(Target)
auftrag=AUFTRAG.Type.ANTISHIP auftrag=AUFTRAG.Type.ANTISHIP
else else
self:E(self.lid.."ERROR: Unknown Group category!") self:T(self.lid.."ERROR: Unknown Group category!")
end end
elseif airbase then elseif airbase then
@ -3237,7 +3237,7 @@ function AUFTRAG:onafterStatus(From, Event, To)
-- Check for error. -- Check for error.
if fsmstate~=self.status then if fsmstate~=self.status then
self:E(self.lid..string.format("ERROR: FSM state %s != %s mission status!", fsmstate, self.status)) self:T(self.lid..string.format("ERROR: FSM state %s != %s mission status!", fsmstate, self.status))
end end
-- General info. -- General info.
@ -3254,7 +3254,7 @@ function AUFTRAG:onafterStatus(From, Event, To)
local chief=self.chief and self.statusChief or "N/A" local chief=self.chief and self.statusChief or "N/A"
-- Info message. -- Info message.
self:I(self.lid..string.format("Status %s: Target=%s, T=%s-%s, assets=%d, groups=%d, targets=%d, legions=%d, commander=%s, chief=%s", self:T(self.lid..string.format("Status %s: Target=%s, T=%s-%s, assets=%d, groups=%d, targets=%d, legions=%d, commander=%s, chief=%s",
self.status, targetname, Cstart, Cstop, #self.assets, Ngroups, Ntargets, Nlegions, commander, chief)) self.status, targetname, Cstart, Cstop, #self.assets, Ngroups, Ntargets, Nlegions, commander, chief))
end end
@ -3366,22 +3366,23 @@ function AUFTRAG:Evaluate()
end end
-- Debug text. -- Debug text.
local text=string.format("Evaluating mission:\n") if self.verbose > 0 then
text=text..string.format("Own casualties = %d/%d\n", self.Ncasualties, self.Nelements) local text=string.format("Evaluating mission:\n")
text=text..string.format("Own losses = %.1f %%\n", owndamage) text=text..string.format("Own casualties = %d/%d\n", self.Ncasualties, self.Nelements)
text=text..string.format("Killed units = %d\n", self.Nkills) text=text..string.format("Own losses = %.1f %%\n", owndamage)
text=text..string.format("--------------------------\n") text=text..string.format("Killed units = %d\n", self.Nkills)
text=text..string.format("Targets left = %d/%d\n", Ntargets, Ntargets0) text=text..string.format("--------------------------\n")
text=text..string.format("Targets life = %.1f/%.1f\n", Life, Life0) text=text..string.format("Targets left = %d/%d\n", Ntargets, Ntargets0)
text=text..string.format("Enemy losses = %.1f %%\n", targetdamage) text=text..string.format("Targets life = %.1f/%.1f\n", Life, Life0)
text=text..string.format("--------------------------\n") text=text..string.format("Enemy losses = %.1f %%\n", targetdamage)
text=text..string.format("Success Cond = %s\n", tostring(successCondition)) text=text..string.format("--------------------------\n")
text=text..string.format("Failure Cond = %s\n", tostring(failureCondition)) text=text..string.format("Success Cond = %s\n", tostring(successCondition))
text=text..string.format("--------------------------\n") text=text..string.format("Failure Cond = %s\n", tostring(failureCondition))
text=text..string.format("Final Success = %s\n", tostring(not failed)) text=text..string.format("--------------------------\n")
text=text..string.format("=========================") text=text..string.format("Final Success = %s\n", tostring(not failed))
self:I(self.lid..text) text=text..string.format("=========================")
self:I(self.lid..text)
end
if failed then if failed then
self:Failed() self:Failed()
else else
@ -3446,7 +3447,7 @@ function AUFTRAG:SetGroupStatus(opsgroup, status)
if groupdata then if groupdata then
groupdata.status=status groupdata.status=status
else else
self:E(self.lid.."WARNING: Could not SET flight data for flight group. Setting status to DONE") self:T(self.lid.."WARNING: Could not SET flight data for flight group. Setting status to DONE")
end end
end end
@ -3483,7 +3484,7 @@ function AUFTRAG:GetGroupStatus(opsgroup)
return groupdata.status return groupdata.status
else else
self:E(self.lid..string.format("WARNING: Could not GET groupdata for opsgroup %s. Returning status DONE.", opsgroup and opsgroup.groupname or "nil")) self:T(self.lid..string.format("WARNING: Could not GET groupdata for opsgroup %s. Returning status DONE.", opsgroup and opsgroup.groupname or "nil"))
return AUFTRAG.GroupStatus.DONE return AUFTRAG.GroupStatus.DONE
end end
@ -3521,7 +3522,7 @@ function AUFTRAG:RemoveLegion(Legion)
end end
end end
self:E(self.lid..string.format("ERROR: Legion %s not found and could not be removed!", Legion.alias)) self:T(self.lid..string.format("ERROR: Legion %s not found and could not be removed!", Legion.alias))
return self return self
end end
@ -3735,7 +3736,7 @@ function AUFTRAG:OnEventUnitLost(EventData)
for _,_groupdata in pairs(self.groupdata) do for _,_groupdata in pairs(self.groupdata) do
local groupdata=_groupdata --#AUFTRAG.GroupData local groupdata=_groupdata --#AUFTRAG.GroupData
if groupdata and groupdata.opsgroup and groupdata.opsgroup.groupname==EventData.IniGroupName then if groupdata and groupdata.opsgroup and groupdata.opsgroup.groupname==EventData.IniGroupName then
self:I(self.lid..string.format("UNIT LOST event for opsgroup %s unit %s", groupdata.opsgroup.groupname, EventData.IniUnitName)) self:T(self.lid..string.format("UNIT LOST event for opsgroup %s unit %s", groupdata.opsgroup.groupname, EventData.IniUnitName))
end end
end end
@ -3858,7 +3859,7 @@ function AUFTRAG:onafterAssetDead(From, Event, To, Asset)
-- Number of groups alive. -- Number of groups alive.
local N=self:CountOpsGroups() local N=self:CountOpsGroups()
self:I(self.lid..string.format("Asset %s dead! Number of ops groups remaining %d", tostring(Asset.spawngroupname), N)) self:T(self.lid..string.format("Asset %s dead! Number of ops groups remaining %d", tostring(Asset.spawngroupname), N))
-- All assets dead? -- All assets dead?
if N==0 then if N==0 then
@ -3892,7 +3893,7 @@ function AUFTRAG:onafterCancel(From, Event, To)
local Ngroups = self:CountOpsGroups() local Ngroups = self:CountOpsGroups()
-- Debug info. -- Debug info.
self:I(self.lid..string.format("CANCELLING mission in status %s. Will wait for %d groups to report mission DONE before evaluation", self.status, Ngroups)) self:T(self.lid..string.format("CANCELLING mission in status %s. Will wait for %d groups to report mission DONE before evaluation", self.status, Ngroups))
-- Time stamp. -- Time stamp.
self.Tover=timer.getAbsTime() self.Tover=timer.getAbsTime()
@ -4010,13 +4011,13 @@ function AUFTRAG:onafterSuccess(From, Event, To)
local N=math.max(self.NrepeatSuccess, self.Nrepeat) local N=math.max(self.NrepeatSuccess, self.Nrepeat)
-- Repeat mission. -- Repeat mission.
self:I(self.lid..string.format("Mission SUCCESS! Repeating mission for the %d time (max %d times) ==> Repeat mission!", self.repeated+1, N)) self:T(self.lid..string.format("Mission SUCCESS! Repeating mission for the %d time (max %d times) ==> Repeat mission!", self.repeated+1, N))
self:Repeat() self:Repeat()
else else
-- Stop mission. -- Stop mission.
self:I(self.lid..string.format("Mission SUCCESS! Number of max repeats %d reached ==> Stopping mission!", self.repeated+1)) self:T(self.lid..string.format("Mission SUCCESS! Number of max repeats %d reached ==> Stopping mission!", self.repeated+1))
self:Stop() self:Stop()
end end
@ -4052,13 +4053,13 @@ function AUFTRAG:onafterFailed(From, Event, To)
local N=math.max(self.NrepeatFailure, self.Nrepeat) local N=math.max(self.NrepeatFailure, self.Nrepeat)
-- Repeat mission. -- Repeat mission.
self:I(self.lid..string.format("Mission FAILED! Repeating mission for the %d time (max %d times) ==> Repeat mission!", self.repeated+1, N)) self:T(self.lid..string.format("Mission FAILED! Repeating mission for the %d time (max %d times) ==> Repeat mission!", self.repeated+1, N))
self:Repeat() self:Repeat()
else else
-- Stop mission. -- Stop mission.
self:I(self.lid..string.format("Mission FAILED! Number of max repeats %d reached ==> Stopping mission!", self.repeated+1)) self:T(self.lid..string.format("Mission FAILED! Number of max repeats %d reached ==> Stopping mission!", self.repeated+1))
self:Stop() self:Stop()
end end
@ -4185,7 +4186,7 @@ end
function AUFTRAG:onafterStop(From, Event, To) function AUFTRAG:onafterStop(From, Event, To)
-- Debug info. -- Debug info.
self:I(self.lid..string.format("STOPPED mission in status=%s. Removing missions from queues. Stopping CallScheduler!", self.status)) self:T(self.lid..string.format("STOPPED mission in status=%s. Removing missions from queues. Stopping CallScheduler!", self.status))
-- TODO: Mission should be OVER! we dont want to remove running missions from any queues. -- TODO: Mission should be OVER! we dont want to remove running missions from any queues.
@ -4378,7 +4379,7 @@ function AUFTRAG:GetTargetCoordinate()
return nil return nil
else else
self:E(self.lid.."ERROR: Cannot get target coordinate!") self:T(self.lid.."ERROR: Cannot get target coordinate!")
end end
return nil return nil
@ -4409,7 +4410,7 @@ function AUFTRAG:GetTargetDistance(FromCoord)
if TargetCoord and FromCoord then if TargetCoord and FromCoord then
return TargetCoord:Get2DDistance(FromCoord) return TargetCoord:Get2DDistance(FromCoord)
else else
self:E(self.lid.."ERROR: TargetCoord or FromCoord does not exist in AUFTRAG:GetTargetDistance() function! Returning 0") self:T(self.lid.."ERROR: TargetCoord or FromCoord does not exist in AUFTRAG:GetTargetDistance() function! Returning 0")
end end
return 0 return 0
@ -5021,7 +5022,7 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable)
table.insert(DCStasks, DCStask) table.insert(DCStasks, DCStask)
else else
self:E(self.lid..string.format("ERROR: Unknown mission task!")) self:T(self.lid..string.format("ERROR: Unknown mission task!"))
return nil return nil
end end

View File

@ -49,7 +49,7 @@ BRIGADE = {
--- BRIGADE class version. --- BRIGADE class version.
-- @field #string version -- @field #string version
BRIGADE.version="0.1.0" BRIGADE.version="0.1.1"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list -- ToDo list
@ -288,6 +288,126 @@ function BRIGADE:RemoveAssetFromPlatoon(Asset)
end end
end end
--- [ GROUND ] Function to load back an asset in the field that has been filed before.
-- @param #BRIGADE self
-- @param #string Templatename e.g."1 PzDv LogRg I\_AID-976" - that's the alias (name) of an platoon spawned as `"platoon - alias"_AID-"asset-ID"`
-- @param Core.Point#COORDINATE Position where to spawn the platoon
-- @return #BRIGADE self
-- @usage
-- Prerequisites:
-- Save the assets spawned by BRIGADE/CHIEF regularly (~every 5 mins) into a file, e.g. like this:
--
-- local Path = FilePath or "C:\\Users\\<yourname>\\Saved Games\\DCS\\Missions\\" -- example path
-- local BlueOpsFilename = BlueFileName or "ExamplePlatoonSave.csv" -- example filename
-- local BlueSaveOps = SET_GROUP:New():FilterCoalitions("blue"):FilterPrefixes("AID"):FilterCategoryGround():FilterOnce()
-- UTILS.SaveSetOfGroups(BlueSaveOps,Path,BlueOpsFilename)
--
-- where Path and Filename are strings, as chosen by you.
-- You can then load back the assets at the start of your next mission run. Be aware that it takes a couple of seconds for the
-- platoon data to arrive in brigade, so make this an action after ~20 seconds, e.g. like so:
--
-- function LoadBackAssets()
-- local Path = FilePath or "C:\\Users\\<yourname>\\Saved Games\\DCS\\Missions\\" -- example path
-- local BlueOpsFilename = BlueFileName or "ExamplePlatoonSave.csv" -- example filename
-- if UTILS.CheckFileExists(Path,BlueOpsFilename) then
-- local loadback = UTILS.LoadSetOfGroups(Path,BlueOpsFilename,false)
-- for _,_platoondata in pairs (loadback) do
-- local groupname = _platoondata.groupname -- #string
-- local coordinate = _platoondata.coordinate -- Core.Point#COORDINATE
-- Your_Brigade:LoadBackAssetInPosition(groupname,coordinate)
-- end
-- end
-- end
--
-- local AssetLoader = TIMER:New(LoadBackAssets)
-- AssetLoader:Start(20)
--
-- The assets loaded back into the mission will be considered for AUFTRAG type missions from CHIEF and BRIGADE.
function BRIGADE:LoadBackAssetInPosition(Templatename,Position)
self:T(self.lid .. "LoadBackAssetInPosition: " .. tostring(Templatename))
-- get Platoon alias from Templatename
local nametbl = UTILS.Split(Templatename,"_")
local name = nametbl[1]
self:T(string.format("*** Target Platoon = %s ***",name))
-- find a matching asset table from BRIGADE
local cohorts = self.cohorts or {}
local thisasset = nil --Functional.Warehouse#WAREHOUSE.Assetitem
local found = false
for _,_cohort in pairs(cohorts) do
local asset = _cohort:GetName()
self:T(string.format("*** Looking at Platoon = %s ***",asset))
if asset == name then
self:T("**** Found Platoon ****")
local cohassets = _cohort.assets or {}
for _,_zug in pairs (cohassets) do
local zug = _zug -- Functional.Warehouse#WAREHOUSE.Assetitem
if zug.assignment == name and zug.requested == false then
self:T("**** Found Asset ****")
found = true
thisasset = zug --Functional.Warehouse#WAREHOUSE.Assetitem
break
end
end
end
end
if found then
-- prep asset
thisasset.rid = thisasset.uid
thisasset.requested = false
thisasset.score=100
thisasset.missionTask="CAS"
thisasset.spawned = true
local template = thisasset.templatename
local alias = thisasset.spawngroupname
-- Spawn group
local spawnasset = SPAWN:NewWithAlias(template,alias)
:InitDelayOff()
:SpawnFromCoordinate(Position)
-- build a new self request
local request = {} --Functional.Warehouse#WAREHOUSE.Pendingitem
request.assignment = name
request.warehouse = self
request.assets = {thisasset}
request.ntransporthome = 0
request.ndelivered = 0
request.ntransport = 0
request.cargoattribute = thisasset.attribute
request.category = thisasset.category
request.cargoassets = {thisasset}
request.assetdesc = WAREHOUSE.Descriptor.ASSETLIST
request.cargocategory = thisasset.category
request.toself = true
request.transporttype = WAREHOUSE.TransportType.SELFPROPELLED
request.assetproblem = {}
request.born = true
request.prio = 50
request.uid = thisasset.uid
request.airbase = nil
request.timestamp = timer.getAbsTime()
request.assetdescval = {thisasset}
request.nasset = 1
request.cargogroupset = SET_GROUP:New()
request.cargogroupset:AddGroup(spawnasset)
request.iscargo = true
-- Call Brigade self
self:__AssetSpawned(2, spawnasset, thisasset, request)
end
return self
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- FSM Functions -- FSM Functions
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -45,7 +45,7 @@
-- * Object oriented refactoring of Ciribob\'s fantastic CSAR script. -- * Object oriented refactoring of Ciribob\'s fantastic CSAR script.
-- * No need for extra MIST loading. -- * No need for extra MIST loading.
-- * Additional events to tailor your mission. -- * Additional events to tailor your mission.
-- * Optional SpawnCASEVAC to create casualties without beacon (e.g. handling dead ground vehicles and create CASVAC requests). -- * Optional SpawnCASEVAC to create casualties without beacon (e.g. handling dead ground vehicles and create CASVAC requests).
-- --
-- ## 0. Prerequisites -- ## 0. Prerequisites
-- --
@ -117,7 +117,7 @@
-- self.SRSchannel = 300 -- radio channel -- self.SRSchannel = 300 -- radio channel
-- self.SRSModulation = radio.modulation.AM -- modulation -- self.SRSModulation = radio.modulation.AM -- modulation
-- -- -- --
-- self.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection --shagrat -- self.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection --shagrat
-- --
-- ## 3. Results -- ## 3. Results
-- --
@ -178,8 +178,8 @@
-- -- Create downed "Pilot Wagner" in #ZONE "CSAR_Start_1" at a random point for the blue coalition -- -- Create downed "Pilot Wagner" in #ZONE "CSAR_Start_1" at a random point for the blue coalition
-- my_csar:SpawnCSARAtZone( "CSAR_Start_1", coalition.side.BLUE, "Pilot Wagner", true ) -- my_csar:SpawnCSARAtZone( "CSAR_Start_1", coalition.side.BLUE, "Pilot Wagner", true )
-- --
-- --Create a casualty and CASEVAC request from a "Point" (VEC2) for the blue coalition --shagrat -- --Create a casualty and CASEVAC request from a "Point" (VEC2) for the blue coalition --shagrat
-- my_csar:SpawnCASEVAC(Point, coalition.side.BLUE) -- my_csar:SpawnCASEVAC(Point, coalition.side.BLUE)
-- --
-- @field #CSAR -- @field #CSAR
CSAR = { CSAR = {
@ -243,11 +243,11 @@ CSAR.AircraftType["Mi-8MTV2"] = 12
CSAR.AircraftType["Mi-8MT"] = 12 CSAR.AircraftType["Mi-8MT"] = 12
CSAR.AircraftType["Mi-24P"] = 8 CSAR.AircraftType["Mi-24P"] = 8
CSAR.AircraftType["Mi-24V"] = 8 CSAR.AircraftType["Mi-24V"] = 8
CSAR.AircraftType["Bell-47"] = 2 CSAR.AircraftType["Bell-47"] = 2
--- CSAR class version. --- CSAR class version.
-- @field #string version -- @field #string version
CSAR.version="0.1.12r5" CSAR.version="1.0.1r1"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list -- ToDo list
@ -356,6 +356,7 @@ function CSAR:New(Coalition, Template, Alias)
self.extractDistance = 500 -- Distance the Downed pilot will run to the rescue helicopter self.extractDistance = 500 -- Distance the Downed pilot will run to the rescue helicopter
self.loadtimemax = 135 -- seconds self.loadtimemax = 135 -- seconds
self.radioSound = "beacon.ogg" -- the name of the sound file to use for the Pilot radio beacons. If this isnt added to the mission BEACONS WONT WORK! self.radioSound = "beacon.ogg" -- the name of the sound file to use for the Pilot radio beacons. If this isnt added to the mission BEACONS WONT WORK!
self.beaconRefresher = 29 -- seconds
self.allowFARPRescue = true --allows pilot to be rescued by landing at a FARP or Airbase self.allowFARPRescue = true --allows pilot to be rescued by landing at a FARP or Airbase
self.FARPRescueDistance = 1000 -- you need to be this close to a FARP or Airport for the pilot to be rescued. self.FARPRescueDistance = 1000 -- you need to be this close to a FARP or Airport for the pilot to be rescued.
self.max_units = 6 --max number of pilots that can be carried self.max_units = 6 --max number of pilots that can be carried
@ -654,10 +655,10 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
if not noMessage then if not noMessage then
if _freq ~= 0 then --shagrat different CASEVAC msg if _freq ~= 0 then --shagrat different CASEVAC msg
self:_DisplayToAllSAR("MAYDAY MAYDAY! " .. _typeName .. " is down. ", self.coalition, self.messageTime) self:_DisplayToAllSAR("MAYDAY MAYDAY! " .. _typeName .. " is down. ", self.coalition, self.messageTime)
else else
self:_DisplayToAllSAR("Troops In Contact. " .. _typeName .. " requests CASEVAC. ", self.coalition, self.messageTime) self:_DisplayToAllSAR("Troops In Contact. " .. _typeName .. " requests CASEVAC. ", self.coalition, self.messageTime)
end end
end end
if (_freq and _freq ~= 0) then --shagrat only add beacon if _freq is NOT 0 if (_freq and _freq ~= 0) then --shagrat only add beacon if _freq is NOT 0
@ -669,18 +670,18 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
local _text = _description local _text = _description
if not forcedesc then if not forcedesc then
if _playerName ~= nil then if _playerName ~= nil then
if _freq ~= 0 then --shagrat if _freq ~= 0 then --shagrat
_text = "Pilot " .. _playerName _text = "Pilot " .. _playerName
else else
_text = "TIC - " .. _playerName _text = "TIC - " .. _playerName
end end
elseif _unitName ~= nil then elseif _unitName ~= nil then
if _freq ~= 0 then --shagrat if _freq ~= 0 then --shagrat
_text = "AI Pilot of " .. _unitName _text = "AI Pilot of " .. _unitName
else else
_text = "TIC - " .. _unitName _text = "TIC - " .. _unitName
end end
end end
end end
self:T({_spawnedGroup, _alias}) self:T({_spawnedGroup, _alias})
@ -901,12 +902,12 @@ function CSAR:_EventHandler(EventData)
local _unit = _event.IniUnit local _unit = _event.IniUnit
local _unitname = _event.IniUnitName local _unitname = _event.IniUnitName
local _group = _event.IniGroup local _group = _event.IniGroup
if _unit == nil then if _unit == nil then
return -- error! return -- error!
end end
local _coalition = _unit:GetCoalition() local _coalition = _unit:GetCoalition()
if _coalition ~= self.coalition then if _coalition ~= self.coalition then
return --ignore! return --ignore!
end end
@ -926,28 +927,28 @@ function CSAR:_EventHandler(EventData)
end end
-- all checks passed, get going. -- all checks passed, get going.
if self.csarUsePara == false then --shagrat check parameter LandingAfterEjection, if true don't spawn a Pilot from EJECTION event, wait for the Chute to land if self.csarUsePara == false then --shagrat check parameter LandingAfterEjection, if true don't spawn a Pilot from EJECTION event, wait for the Chute to land
local _freq = self:_GenerateADFFrequency() local _freq = self:_GenerateADFFrequency()
self:_AddCsar(_coalition, _unit:GetCountry(), _unit:GetCoordinate() , _unit:GetTypeName(), _unit:GetName(), _event.IniPlayerName, _freq, false, "none") self:_AddCsar(_coalition, _unit:GetCountry(), _unit:GetCoordinate() , _unit:GetTypeName(), _unit:GetName(), _event.IniPlayerName, _freq, false, "none")
return true return true
end end
---- shagrat on event LANDING_AFTER_EJECTION spawn pilot at parachute location ---- shagrat on event LANDING_AFTER_EJECTION spawn pilot at parachute location
elseif (_event.id == EVENTS.LandingAfterEjection and self.csarUsePara == true) then elseif (_event.id == EVENTS.LandingAfterEjection and self.csarUsePara == true) then
self:I({EVENT=_event}) self:I({EVENT=_event})
local _LandingPos = COORDINATE:NewFromVec3(_event.initiator:getPosition().p) local _LandingPos = COORDINATE:NewFromVec3(_event.initiator:getPosition().p)
local _unitname = "Aircraft" --_event.initiator:getName() or "Aircraft" --shagrat Optional use of Object name which is unfortunately 'f15_Pilot_Parachute' local _unitname = "Aircraft" --_event.initiator:getName() or "Aircraft" --shagrat Optional use of Object name which is unfortunately 'f15_Pilot_Parachute'
local _typename = "Ejected Pilot" --_event.Initiator.getTypeName() or "Ejected Pilot" local _typename = "Ejected Pilot" --_event.Initiator.getTypeName() or "Ejected Pilot"
local _country = _event.initiator:getCountry() local _country = _event.initiator:getCountry()
local _coalition = coalition.getCountryCoalition( _country ) local _coalition = coalition.getCountryCoalition( _country )
if _coalition == self.coalition then if _coalition == self.coalition then
local _freq = self:_GenerateADFFrequency() local _freq = self:_GenerateADFFrequency()
self:I({coalition=_coalition,country= _country, coord=_LandingPos, name=_unitname, player=_event.IniPlayerName, freq=_freq}) self:I({coalition=_coalition,country= _country, coord=_LandingPos, name=_unitname, player=_event.IniPlayerName, freq=_freq})
self:_AddCsar(_coalition, _country, _LandingPos, nil, _unitname, _event.IniPlayerName, _freq, false, "none")--shagrat add CSAR at Parachute location. self:_AddCsar(_coalition, _country, _LandingPos, nil, _unitname, _event.IniPlayerName, _freq, false, "none")--shagrat add CSAR at Parachute location.
Unit.destroy(_event.initiator) -- shagrat remove static Pilot model Unit.destroy(_event.initiator) -- shagrat remove static Pilot model
end end
return true return true
elseif _event.id == EVENTS.Land then elseif _event.id == EVENTS.Land then
self:T(self.lid .. " Landing") self:T(self.lid .. " Landing")
@ -1012,13 +1013,13 @@ function CSAR:_InitSARForPilot(_downedGroup, _GroupName, _freq, _nomessage)
local _leadername = _leader:GetName() local _leadername = _leader:GetName()
if not _nomessage then if not _nomessage then
if _freq ~= 0 then --shagrat if _freq ~= 0 then --shagrat
local _text = string.format("%s requests SAR at %s, beacon at %.2f KHz", _groupName, _coordinatesText, _freqk)--shagrat _groupName to prevent 'f15_Pilot_Parachute' local _text = string.format("%s requests SAR at %s, beacon at %.2f KHz", _groupName, _coordinatesText, _freqk)--shagrat _groupName to prevent 'f15_Pilot_Parachute'
self:_DisplayToAllSAR(_text,self.coalition,self.messageTime) self:_DisplayToAllSAR(_text,self.coalition,self.messageTime)
else --shagrat CASEVAC msg else --shagrat CASEVAC msg
local _text = string.format("Pickup Zone at %s.", _coordinatesText ) local _text = string.format("Pickup Zone at %s.", _coordinatesText )
self:_DisplayToAllSAR(_text,self.coalition,self.messageTime) self:_DisplayToAllSAR(_text,self.coalition,self.messageTime)
end end
end end
for _,_heliName in pairs(self.csarUnits) do for _,_heliName in pairs(self.csarUnits) do
@ -1456,12 +1457,13 @@ end
-- @param #number _time Message show duration. -- @param #number _time Message show duration.
-- @param #boolean _clear (optional) Clear screen. -- @param #boolean _clear (optional) Clear screen.
-- @param #boolean _speak (optional) Speak message via SRS. -- @param #boolean _speak (optional) Speak message via SRS.
function CSAR:_DisplayMessageToSAR(_unit, _text, _time, _clear, _speak) -- @param #boolean _override (optional) Override message suppression
function CSAR:_DisplayMessageToSAR(_unit, _text, _time, _clear, _speak, _override)
self:T(self.lid .. " _DisplayMessageToSAR") self:T(self.lid .. " _DisplayMessageToSAR")
local group = _unit:GetGroup() local group = _unit:GetGroup()
local _clear = _clear or nil local _clear = _clear or nil
local _time = _time or self.messageTime local _time = _time or self.messageTime
if not self.suppressmessages then if _override or not self.suppressmessages then
local m = MESSAGE:New(_text,_time,"Info",_clear):ToGroup(group) local m = MESSAGE:New(_text,_time,"Info",_clear):ToGroup(group)
end end
-- integrate SRS -- integrate SRS
@ -1531,11 +1533,11 @@ function CSAR:_DisplayActiveSAR(_unitName)
else else
distancetext = string.format("%.1fkm", _distance/1000.0) distancetext = string.format("%.1fkm", _distance/1000.0)
end end
if _value.frequency == 0 then--shagrat insert CASEVAC without Frequency if _value.frequency == 0 then--shagrat insert CASEVAC without Frequency
table.insert(_csarList, { dist = _distance, msg = string.format("%s at %s - %s ", _value.desc, _coordinatesText, distancetext) }) table.insert(_csarList, { dist = _distance, msg = string.format("%s at %s - %s ", _value.desc, _coordinatesText, distancetext) })
else else
table.insert(_csarList, { dist = _distance, msg = string.format("%s at %s - %.2f KHz ADF - %s ", _value.desc, _coordinatesText, _value.frequency / 1000, distancetext) }) table.insert(_csarList, { dist = _distance, msg = string.format("%s at %s - %.2f KHz ADF - %s ", _value.desc, _coordinatesText, _value.frequency / 1000, distancetext) })
end end
end end
end end
@ -1549,7 +1551,7 @@ function CSAR:_DisplayActiveSAR(_unitName)
_msg = _msg .. "\n" .. _line.msg _msg = _msg .. "\n" .. _line.msg
end end
self:_DisplayMessageToSAR(_heli, _msg, self.messageTime*2) self:_DisplayMessageToSAR(_heli, _msg, self.messageTime*2, false, false, true)
return self return self
end end
@ -1617,7 +1619,7 @@ function CSAR:_SignalFlare(_unitName)
_distance = string.format("%.1fkm",_closest.distance) _distance = string.format("%.1fkm",_closest.distance)
end end
local _msg = string.format("%s - Popping signal flare at your %s o\'clock. Distance %s", _unitName, _clockDir, _distance) local _msg = string.format("%s - Popping signal flare at your %s o\'clock. Distance %s", _unitName, _clockDir, _distance)
self:_DisplayMessageToSAR(_heli, _msg, self.messageTime, false, true) self:_DisplayMessageToSAR(_heli, _msg, self.messageTime, false, true, true)
local _coord = _closest.pilot:GetCoordinate() local _coord = _closest.pilot:GetCoordinate()
_coord:FlareRed(_clockDir) _coord:FlareRed(_clockDir)
@ -1628,7 +1630,7 @@ function CSAR:_SignalFlare(_unitName)
else else
_distance = string.format("%.1fkm",smokedist/1000) _distance = string.format("%.1fkm",smokedist/1000)
end end
self:_DisplayMessageToSAR(_heli, string.format("No Pilots within %s",_distance), self.messageTime) self:_DisplayMessageToSAR(_heli, string.format("No Pilots within %s",_distance), self.messageTime, false, false, true)
end end
return self return self
end end
@ -1671,7 +1673,7 @@ function CSAR:_Reqsmoke( _unitName )
_distance = string.format("%.1fkm",_closest.distance/1000) _distance = string.format("%.1fkm",_closest.distance/1000)
end end
local _msg = string.format("%s - Popping smoke at your %s o\'clock. Distance %s", _unitName, _clockDir, _distance) local _msg = string.format("%s - Popping smoke at your %s o\'clock. Distance %s", _unitName, _clockDir, _distance)
self:_DisplayMessageToSAR(_heli, _msg, self.messageTime, false, true) self:_DisplayMessageToSAR(_heli, _msg, self.messageTime, false, true, true)
local _coord = _closest.pilot:GetCoordinate() local _coord = _closest.pilot:GetCoordinate()
local color = self.smokecolor local color = self.smokecolor
_coord:Smoke(color) _coord:Smoke(color)
@ -1682,7 +1684,7 @@ function CSAR:_Reqsmoke( _unitName )
else else
_distance = string.format("%.1fkm",smokedist/1000) _distance = string.format("%.1fkm",smokedist/1000)
end end
self:_DisplayMessageToSAR(_heli, string.format("No Pilots within %s",_distance), self.messageTime) self:_DisplayMessageToSAR(_heli, string.format("No Pilots within %s",_distance), self.messageTime, false, false, true)
end end
return self return self
end end
@ -1754,13 +1756,13 @@ function CSAR:_CheckOnboard(_unitName)
--list onboard pilots --list onboard pilots
local _inTransit = self.inTransitGroups[_unitName] local _inTransit = self.inTransitGroups[_unitName]
if _inTransit == nil then if _inTransit == nil then
self:_DisplayMessageToSAR(_unit, "No Rescued Pilots onboard", self.messageTime) self:_DisplayMessageToSAR(_unit, "No Rescued Pilots onboard", self.messageTime, false, false, true)
else else
local _text = "Onboard - RTB to FARP/Airfield or MASH: " local _text = "Onboard - RTB to FARP/Airfield or MASH: "
for _, _onboard in pairs(self.inTransitGroups[_unitName]) do for _, _onboard in pairs(self.inTransitGroups[_unitName]) do
_text = _text .. "\n" .. _onboard.desc _text = _text .. "\n" .. _onboard.desc
end end
self:_DisplayMessageToSAR(_unit, _text, self.messageTime*2) self:_DisplayMessageToSAR(_unit, _text, self.messageTime*2, false, false, true)
end end
return self return self
end end
@ -2020,7 +2022,12 @@ function CSAR:onbeforeStatus(From, Event, To)
self:T({From, Event, To}) self:T({From, Event, To})
-- housekeeping -- housekeeping
self:_AddMedevacMenuItem() self:_AddMedevacMenuItem()
self:_RefreshRadioBeacons()
if not self.BeaconTimer or (self.BeaconTimer and not self.BeaconTimer:IsRunning()) then
self.BeaconTimer = TIMER:New(self._RefreshRadioBeacons,self)
self.BeaconTimer:Start(2,self.beaconRefresher)
end
self:_CheckDownedPilotTable() self:_CheckDownedPilotTable()
for _,_sar in pairs (self.csarUnits) do for _,_sar in pairs (self.csarUnits) do
local PilotTable = self.downedPilots local PilotTable = self.downedPilots

View File

@ -22,7 +22,7 @@
-- @module Ops.CTLD -- @module Ops.CTLD
-- @image OPS_CTLD.jpg -- @image OPS_CTLD.jpg
-- Date: Oct 2021 -- Date: Dec 2021
do do
------------------------------------------------------ ------------------------------------------------------
@ -669,7 +669,9 @@ do
-- my_ctld.cratecountry = country.id.GERMANY -- ID of crates. Will default to country.id.RUSSIA for RED coalition setups. -- my_ctld.cratecountry = country.id.GERMANY -- ID of crates. Will default to country.id.RUSSIA for RED coalition setups.
-- my_ctld.allowcratepickupagain = true -- allow re-pickup crates that were dropped. -- my_ctld.allowcratepickupagain = true -- allow re-pickup crates that were dropped.
-- my_ctld.enableslingload = false -- allow cargos to be slingloaded - might not work for all cargo types -- my_ctld.enableslingload = false -- allow cargos to be slingloaded - might not work for all cargo types
-- my_ctld.pilotmustopendoors = false -- -- force opening of doors -- my_ctld.pilotmustopendoors = false -- force opening of doors
-- my_ctld.SmokeColor = SMOKECOLOR.Red -- color to use when dropping smoke from heli
-- my_ctld.FlareColor = FLARECOLOR.Red -- color to use when flaring from heli
-- --
-- ## 2.1 User functions -- ## 2.1 User functions
-- --
@ -812,7 +814,7 @@ do
-- --
-- ## 4.1 Manage Crates -- ## 4.1 Manage Crates
-- --
-- Use this entry to get, load, list nearby, drop, build and repair crates. Also @see options. -- Use this entry to get, load, list nearby, drop, build and repair crates. Also see options.
-- --
-- ## 4.2 Manage Troops -- ## 4.2 Manage Troops
-- --
@ -823,7 +825,7 @@ do
-- --
-- Lists what you have loaded. Shows load capabilities for number of crates and number of seats for troops. -- Lists what you have loaded. Shows load capabilities for number of crates and number of seats for troops.
-- --
-- ## 4.4 Smoke & Flare zones nearby -- ## 4.4 Smoke & Flare zones nearby or drop smoke or flare from Heli
-- --
-- Does what it says. -- Does what it says.
-- --
@ -920,7 +922,7 @@ CTLD = {
-- DONE: Added support for Hercules -- DONE: Added support for Hercules
-- TODO: Possibly - either/or loading crates and troops -- TODO: Possibly - either/or loading crates and troops
-- DONE: Make inject respect existing cargo types -- DONE: Make inject respect existing cargo types
-- TODO: Drop beacons or flares/smoke -- DONE: Drop beacons or flares/smoke
-- DONE: Add statics as cargo -- DONE: Add statics as cargo
-- DONE: List cargo in stock -- DONE: List cargo in stock
-- DONE: Limit of troops, crates buildable? -- DONE: Limit of troops, crates buildable?
@ -988,7 +990,7 @@ CTLD.UnitTypes = {
--- CTLD class version. --- CTLD class version.
-- @field #string version -- @field #string version
CTLD.version="0.2.4" CTLD.version="1.0.1"
--- Instantiate a new CTLD. --- Instantiate a new CTLD.
-- @param #CTLD self -- @param #CTLD self
@ -1154,6 +1156,10 @@ function CTLD:New(Coalition, Prefixes, Alias)
-- slingload -- slingload
self.enableslingload = false self.enableslingload = false
-- Smokes and Flares
self.SmokeColor = SMOKECOLOR.Red
self.FlareColor = FLARECOLOR.Red
for i=1,100 do for i=1,100 do
math.random() math.random()
end end
@ -2911,8 +2917,11 @@ function CTLD:_RefreshF10Menus()
local listmenu = MENU_GROUP_COMMAND:New(_group,"List boarded cargo",topmenu, self._ListCargo, self, _group, _unit) local listmenu = MENU_GROUP_COMMAND:New(_group,"List boarded cargo",topmenu, self._ListCargo, self, _group, _unit)
local invtry = MENU_GROUP_COMMAND:New(_group,"Inventory",topmenu, self._ListInventory, self, _group, _unit) local invtry = MENU_GROUP_COMMAND:New(_group,"Inventory",topmenu, self._ListInventory, self, _group, _unit)
local rbcns = MENU_GROUP_COMMAND:New(_group,"List active zone beacons",topmenu, self._ListRadioBeacons, self, _group, _unit) local rbcns = MENU_GROUP_COMMAND:New(_group,"List active zone beacons",topmenu, self._ListRadioBeacons, self, _group, _unit)
local smokemenu = MENU_GROUP_COMMAND:New(_group,"Smoke zones nearby",topmenu, self.SmokeZoneNearBy, self, _unit, false) local smoketopmenu = MENU_GROUP:New(_group,"Smokes & Flares",topmenu)
local smokemenu = MENU_GROUP_COMMAND:New(_group,"Flare zones nearby",topmenu, self.SmokeZoneNearBy, self, _unit, true):Refresh() local smokemenu = MENU_GROUP_COMMAND:New(_group,"Smoke zones nearby",smoketopmenu, self.SmokeZoneNearBy, self, _unit, false)
local smokeself = MENU_GROUP_COMMAND:New(_group,"Drop smoke now",smoketopmenu, self.SmokePositionNow, self, _unit, false)
local flaremenu = MENU_GROUP_COMMAND:New(_group,"Flare zones nearby",smoketopmenu, self.SmokeZoneNearBy, self, _unit, true)
local flareself = MENU_GROUP_COMMAND:New(_group,"Fire flare now",smoketopmenu, self.SmokePositionNow, self, _unit, true):Refresh()
-- sub menus -- sub menus
-- sub menu troops management -- sub menu troops management
if cantroops then if cantroops then
@ -3373,7 +3382,28 @@ function CTLD:IsUnitInZone(Unit,Zonetype)
end end
end end
--- User function - Start smoke in a zone close to the Unit. --- User function - Drop a smoke or flare at current location.
-- @param #CTLD self
-- @param Wrapper.Unit#UNIT Unit The Unit.
-- @param #boolean Flare If true, flare instead.
function CTLD:SmokePositionNow(Unit, Flare)
self:T(self.lid .. " SmokePositionNow")
local SmokeColor = self.SmokeColor or SMOKECOLOR.Red
local FlareColor = self.FlareColor or FLARECOLOR.Red
-- table of #CTLD.CargoZone table
local unitcoord = Unit:GetCoordinate() -- Core.Point#COORDINATE
local Group = Unit:GetGroup()
if Flare then
unitcoord:Flare(FlareColor, 90)
else
local height = unitcoord:GetLandHeight() + 2
unitcoord.y = height
unitcoord:Smoke(SmokeColor)
end
return self
end
--- User function - Start smoke/flare in a zone close to the Unit.
-- @param #CTLD self -- @param #CTLD self
-- @param Wrapper.Unit#UNIT Unit The Unit. -- @param Wrapper.Unit#UNIT Unit The Unit.
-- @param #boolean Flare If true, flare instead. -- @param #boolean Flare If true, flare instead.
@ -4188,7 +4218,7 @@ end
local statics = nil local statics = nil
local statics = {} local statics = {}
self:I(self.lid.."Bulding Statics Table for Saving") self:T(self.lid.."Bulding Statics Table for Saving")
for _,_cargo in pairs (stcstable) do for _,_cargo in pairs (stcstable) do
local cargo = _cargo -- #CTLD_CARGO local cargo = _cargo -- #CTLD_CARGO
local object = cargo:GetPositionable() -- Wrapper.Static#STATIC local object = cargo:GetPositionable() -- Wrapper.Static#STATIC

View File

@ -668,7 +668,7 @@ function FLIGHTGROUP:StartUncontrolled(delay)
self.group:StartUncontrolled(_delay) self.group:StartUncontrolled(_delay)
self.isUncontrolled=false self.isUncontrolled=false
else else
self:E(self.lid.."ERROR: Could not start uncontrolled group as it is NOT alive!") self:T(self.lid.."ERROR: Could not start uncontrolled group as it is NOT alive!")
end end
end end
@ -766,7 +766,7 @@ function FLIGHTGROUP:onbeforeStatus(From, Event, To)
if isdead then if isdead then
local text=string.format("Element %s is dead at t=%.3f but has status %s! 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 but has status %s! 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(), tostring(element.status)) tostring(element.name), timer.getTime(), tostring(element.status))
self:E(self.lid..text) self:T(self.lid..text)
self:__ElementDead(60, element) self:__ElementDead(60, element)
end end
@ -841,7 +841,7 @@ function FLIGHTGROUP:Status()
end end
else else
--self:E(self.lid..string.format("Element %s is in PARKING queue but has no parking spot assigned!", element.name)) --self:T(self.lid..string.format("Element %s is in PARKING queue but has no parking spot assigned!", element.name))
end end
end end
end end
@ -957,7 +957,7 @@ function FLIGHTGROUP:Status()
end end
-- Log outut. -- 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)) self:T(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 end
@ -1897,10 +1897,10 @@ function FLIGHTGROUP:onbeforeUpdateRoute(From, Event, To, n, N)
self:T3(self.lid.."Update route possible. Group is ALIVE") self:T3(self.lid.."Update route possible. Group is ALIVE")
elseif self:IsDead() then elseif self:IsDead() then
-- Group is dead! No more updates. -- Group is dead! No more updates.
self:E(self.lid.."Update route denied. Group is DEAD!") self:T(self.lid.."Update route denied. Group is DEAD!")
allowed=false allowed=false
elseif self:IsInUtero() then elseif self:IsInUtero() then
self:E(self.lid.."Update route denied. Group is INUTERO!") self:T(self.lid.."Update route denied. Group is INUTERO!")
allowed=false allowed=false
else else
-- Not airborne yet. Try again in 5 sec. -- Not airborne yet. Try again in 5 sec.
@ -1923,19 +1923,19 @@ function FLIGHTGROUP:onbeforeUpdateRoute(From, Event, To, n, N)
-- Requested waypoint index <1. Something is seriously wrong here! -- Requested waypoint index <1. Something is seriously wrong here!
if n and n<1 then if n and n<1 then
self:E(self.lid.."Update route denied because waypoint n<1!") self:T(self.lid.."Update route denied because waypoint n<1!")
allowed=false allowed=false
end end
-- No current waypoint. Something is serously wrong! -- No current waypoint. Something is serously wrong!
if not self.currentwp then if not self.currentwp then
self:E(self.lid.."Update route denied because self.currentwp=nil!") self:T(self.lid.."Update route denied because self.currentwp=nil!")
allowed=false allowed=false
end end
local Nn=n or self.currentwp+1 local Nn=n or self.currentwp+1
if not Nn or Nn<1 then if not Nn or Nn<1 then
self:E(self.lid.."Update route denied because N=nil or N<1") self:T(self.lid.."Update route denied because N=nil or N<1")
trepeat=-5 trepeat=-5
allowed=false allowed=false
end end
@ -1958,7 +1958,7 @@ function FLIGHTGROUP:onbeforeUpdateRoute(From, Event, To, n, N)
self:T2(self.lid.."Allowing update route for Task: Task_Land_At") self:T2(self.lid.."Allowing update route for Task: Task_Land_At")
else else
local taskname=task and task.description or "No description" local taskname=task and task.description or "No description"
self:E(self.lid..string.format("WARNING: Update route denied because taskcurrent=%d>0! Task description = %s", self.taskcurrent, tostring(taskname))) self:T(self.lid..string.format("WARNING: Update route denied because taskcurrent=%d>0! Task description = %s", self.taskcurrent, tostring(taskname)))
allowed=false allowed=false
end end
else else
@ -2229,24 +2229,24 @@ function FLIGHTGROUP:onbeforeRTB(From, Event, To, airbase, SpeedTo, SpeedHold)
local Tsuspend=nil local Tsuspend=nil
if airbase==nil then if airbase==nil then
self:E(self.lid.."ERROR: Airbase is nil in RTB() call!") self:T(self.lid.."ERROR: Airbase is nil in RTB() call!")
allowed=false allowed=false
end end
-- Check that coaliton is okay. We allow same (blue=blue, red=red) or landing on neutral bases. -- Check that coaliton is okay. We allow same (blue=blue, red=red) or landing on neutral bases.
if airbase and airbase:GetCoalition()~=self.group:GetCoalition() and airbase:GetCoalition()>0 then if airbase and airbase:GetCoalition()~=self.group:GetCoalition() and airbase:GetCoalition()>0 then
self:E(self.lid..string.format("ERROR: Wrong airbase coalition %d in RTB() call! We allow only same as group %d or neutral airbases 0", airbase:GetCoalition(), self.group:GetCoalition())) self:T(self.lid..string.format("ERROR: Wrong airbase coalition %d in RTB() call! We allow only same as group %d or neutral airbases 0", airbase:GetCoalition(), self.group:GetCoalition()))
return false return false
end end
if self.currbase and self.currbase:GetName()==airbase:GetName() then if self.currbase and self.currbase:GetName()==airbase:GetName() then
self:E(self.lid.."WARNING: Currbase is already same as RTB airbase. RTB canceled!") self:T(self.lid.."WARNING: Currbase is already same as RTB airbase. RTB canceled!")
return false return false
end end
-- Check if the group has landed at an airbase. If so, we lost control and RTBing is not possible (only after a respawn). -- Check if the group has landed at an airbase. If so, we lost control and RTBing is not possible (only after a respawn).
if self:IsLanded() then if self:IsLanded() then
self:E(self.lid.."WARNING: Flight has already landed. RTB canceled!") self:T(self.lid.."WARNING: Flight has already landed. RTB canceled!")
return false return false
end end
@ -2260,7 +2260,7 @@ function FLIGHTGROUP:onbeforeRTB(From, Event, To, airbase, SpeedTo, SpeedHold)
self.RTBRecallCount = self.RTBRecallCount+1 self.RTBRecallCount = self.RTBRecallCount+1
end end
if self.RTBRecallCount>6 then if self.RTBRecallCount>6 then
self:I(self.lid..string.format("WARNING: Group [%s] is not moving and was called RTB %d times. Assuming a problem and despawning!", self:GetState(), self.RTBRecallCount)) self:T(self.lid..string.format("WARNING: Group [%s] is not moving and was called RTB %d times. Assuming a problem and despawning!", self:GetState(), self.RTBRecallCount))
self.RTBRecallCount=0 self.RTBRecallCount=0
self:Despawn(5) self:Despawn(5)
return return
@ -2274,25 +2274,25 @@ function FLIGHTGROUP:onbeforeRTB(From, Event, To, airbase, SpeedTo, SpeedHold)
local Ntot,Nsched, Nwp=self:CountRemainingTasks() local Ntot,Nsched, Nwp=self:CountRemainingTasks()
if self.taskcurrent>0 then if self.taskcurrent>0 then
self:I(self.lid..string.format("WARNING: Got current task ==> RTB event is suspended for 10 sec")) self:T(self.lid..string.format("WARNING: Got current task ==> RTB event is suspended for 10 sec"))
Tsuspend=-10 Tsuspend=-10
allowed=false allowed=false
end end
if Nsched>0 then if Nsched>0 then
self:I(self.lid..string.format("WARNING: Still got %d SCHEDULED tasks in the queue ==> RTB event is suspended for 10 sec", Nsched)) self:T(self.lid..string.format("WARNING: Still got %d SCHEDULED tasks in the queue ==> RTB event is suspended for 10 sec", Nsched))
Tsuspend=-10 Tsuspend=-10
allowed=false allowed=false
end end
if Nwp>0 then if Nwp>0 then
self:I(self.lid..string.format("WARNING: Still got %d WAYPOINT tasks in the queue ==> RTB event is suspended for 10 sec", Nwp)) self:T(self.lid..string.format("WARNING: Still got %d WAYPOINT tasks in the queue ==> RTB event is suspended for 10 sec", Nwp))
Tsuspend=-10 Tsuspend=-10
allowed=false allowed=false
end end
if self.Twaiting and self.dTwait then if self.Twaiting and self.dTwait then
self:I(self.lid..string.format("WARNING: Group is Waiting for a specific duration ==> RTB event is canceled", Nwp)) self:T(self.lid..string.format("WARNING: Group is Waiting for a specific duration ==> RTB event is canceled", Nwp))
allowed=false allowed=false
end end
@ -2305,7 +2305,7 @@ function FLIGHTGROUP:onbeforeRTB(From, Event, To, airbase, SpeedTo, SpeedHold)
return allowed return allowed
else else
self:E(self.lid.."WARNING: Group is not alive! RTB call not allowed.") self:T(self.lid.."WARNING: Group is not alive! RTB call not allowed.")
return false return false
end end
@ -2361,35 +2361,35 @@ function FLIGHTGROUP:onbeforeLandAtAirbase(From, Event, To, airbase)
local Tsuspend=nil local Tsuspend=nil
if airbase==nil then if airbase==nil then
self:E(self.lid.."ERROR: Airbase is nil in LandAtAirase() call!") self:T(self.lid.."ERROR: Airbase is nil in LandAtAirase() call!")
allowed=false allowed=false
end end
-- Check that coaliton is okay. We allow same (blue=blue, red=red) or landing on neutral bases. -- Check that coaliton is okay. We allow same (blue=blue, red=red) or landing on neutral bases.
if airbase and airbase:GetCoalition()~=self.group:GetCoalition() and airbase:GetCoalition()>0 then if airbase and airbase:GetCoalition()~=self.group:GetCoalition() and airbase:GetCoalition()>0 then
self:E(self.lid..string.format("ERROR: Wrong airbase coalition %d in LandAtAirbase() call! We allow only same as group %d or neutral airbases 0", airbase:GetCoalition(), self.group:GetCoalition())) self:T(self.lid..string.format("ERROR: Wrong airbase coalition %d in LandAtAirbase() call! We allow only same as group %d or neutral airbases 0", airbase:GetCoalition(), self.group:GetCoalition()))
return false return false
end end
if self.currbase and self.currbase:GetName()==airbase:GetName() then if self.currbase and self.currbase:GetName()==airbase:GetName() then
self:E(self.lid.."WARNING: Currbase is already same as LandAtAirbase airbase. LandAtAirbase canceled!") self:T(self.lid.."WARNING: Currbase is already same as LandAtAirbase airbase. LandAtAirbase canceled!")
return false return false
end end
-- Check if the group has landed at an airbase. If so, we lost control and RTBing is not possible (only after a respawn). -- Check if the group has landed at an airbase. If so, we lost control and RTBing is not possible (only after a respawn).
if self:IsLanded() then if self:IsLanded() then
self:E(self.lid.."WARNING: Flight has already landed. LandAtAirbase canceled!") self:T(self.lid.."WARNING: Flight has already landed. LandAtAirbase canceled!")
return false return false
end end
if self:IsParking() then if self:IsParking() then
allowed=false allowed=false
Tsuspend=-30 Tsuspend=-30
self:E(self.lid.."WARNING: Flight is parking. LandAtAirbase call delayed by 30 sec") self:T(self.lid.."WARNING: Flight is parking. LandAtAirbase call delayed by 30 sec")
elseif self:IsTaxiing() then elseif self:IsTaxiing() then
allowed=false allowed=false
Tsuspend=-1 Tsuspend=-1
self:E(self.lid.."WARNING: Flight is parking. LandAtAirbase call delayed by 1 sec") self:T(self.lid.."WARNING: Flight is parking. LandAtAirbase call delayed by 1 sec")
end end
if Tsuspend and not allowed then if Tsuspend and not allowed then
@ -2398,7 +2398,7 @@ function FLIGHTGROUP:onbeforeLandAtAirbase(From, Event, To, airbase)
return allowed return allowed
else else
self:E(self.lid.."WARNING: Group is not alive! LandAtAirbase call not allowed") self:T(self.lid.."WARNING: Group is not alive! LandAtAirbase call not allowed")
return false return false
end end
@ -2573,14 +2573,14 @@ function FLIGHTGROUP:onbeforeWait(From, Event, To, Duration, Altitude, Speed)
-- Check for a current task. -- Check for a current task.
if self.taskcurrent>0 and not self:IsLandedAt() then if self.taskcurrent>0 and not self:IsLandedAt() then
self:I(self.lid..string.format("WARNING: Got current task ==> WAIT event is suspended for 30 sec!")) self:T(self.lid..string.format("WARNING: Got current task ==> WAIT event is suspended for 30 sec!"))
Tsuspend=-30 Tsuspend=-30
allowed=false allowed=false
end end
-- Check for a current transport assignment. -- Check for a current transport assignment.
if self.cargoTransport and not self:IsLandedAt() then if self.cargoTransport and not self:IsLandedAt() then
--self:I(self.lid..string.format("WARNING: Got current TRANSPORT assignment ==> WAIT event is suspended for 30 sec!")) --self:T(self.lid..string.format("WARNING: Got current TRANSPORT assignment ==> WAIT event is suspended for 30 sec!"))
--Tsuspend=-30 --Tsuspend=-30
--allowed=false --allowed=false
end end
@ -2803,7 +2803,7 @@ function FLIGHTGROUP:onafterEngageTarget(From, Event, To, Target)
DCStask=self:GetGroup():TaskCombo(DCSTasks) DCStask=self:GetGroup():TaskCombo(DCSTasks)
else else
self:E("ERROR: unknown Target in EngageTarget! Needs to be a UNIT, STATIC, GROUP, SET_UNIT or SET_GROUP") self:T("ERROR: unknown Target in EngageTarget! Needs to be a UNIT, STATIC, GROUP, SET_UNIT or SET_GROUP")
return return
end end
@ -3094,7 +3094,7 @@ function FLIGHTGROUP:_InitGroup(Template)
-- Quick check. -- Quick check.
if #units~=size0 then if #units~=size0 then
self:E(self.lid..string.format("ERROR: Got #units=%d but group consists of %d units!", #units, size0)) self:T(self.lid..string.format("ERROR: Got #units=%d but group consists of %d units!", #units, size0))
end end
-- Add elemets. -- Add elemets.
@ -3893,7 +3893,7 @@ function FLIGHTGROUP:GetParking(airbase)
-- No parking spot for at least one asset :( -- No parking spot for at least one asset :(
if not gotit then if not gotit then
self:E(self.lid..string.format("WARNING: No free parking spot for element %s", element.name)) self:T(self.lid..string.format("WARNING: No free parking spot for element %s", element.name))
return nil return nil
end end

View File

@ -512,7 +512,7 @@ function OPSGROUP:New(group)
-- Check if group exists. -- Check if group exists.
if self.group then if self.group then
if not self:IsExist() then if not self:IsExist() then
self:E(self.lid.."ERROR: GROUP does not exist! Returning nil") self:T(self.lid.."ERROR: GROUP does not exist! Returning nil")
return nil return nil
end end
end end
@ -1382,7 +1382,7 @@ function OPSGROUP:GetCoordinate(NewObject)
return self.coordinate return self.coordinate
end end
else else
self:E(self.lid.."WARNING: Cannot get coordinate!") self:T(self.lid.."WARNING: Cannot get coordinate!")
end end
return nil return nil
@ -1413,11 +1413,11 @@ function OPSGROUP:GetVelocity(UnitName)
return vel return vel
else else
self:E(self.lid.."WARNING: Unit does not exist. Cannot get velocity!") self:T(self.lid.."WARNING: Unit does not exist. Cannot get velocity!")
end end
else else
self:E(self.lid.."WARNING: Group does not exist. Cannot get velocity!") self:T(self.lid.."WARNING: Group does not exist. Cannot get velocity!")
end end
return nil return nil
@ -1454,7 +1454,7 @@ function OPSGROUP:GetHeading(UnitName)
end end
else else
self:E(self.lid.."WARNING: Group does not exist. Cannot get heading!") self:T(self.lid.."WARNING: Group does not exist. Cannot get heading!")
end end
return nil return nil
@ -1486,7 +1486,7 @@ function OPSGROUP:GetOrientation(UnitName)
end end
else else
self:E(self.lid.."WARNING: Group does not exist. Cannot get orientation!") self:T(self.lid.."WARNING: Group does not exist. Cannot get orientation!")
end end
return nil return nil
@ -1724,9 +1724,9 @@ function OPSGROUP:Activate(delay)
self.isLateActivated=false self.isLateActivated=false
elseif self:IsAlive()==true then elseif self:IsAlive()==true then
self:E(self.lid.."WARNING: Activating group that is already activated") self:T(self.lid.."WARNING: Activating group that is already activated")
else else
self:E(self.lid.."ERROR: Activating group that is does not exist!") self:T(self.lid.."ERROR: Activating group that is does not exist!")
end end
end end
@ -2790,13 +2790,13 @@ function OPSGROUP:RemoveWaypoint(wpindex)
-- Always keep at least one waypoint. -- Always keep at least one waypoint.
if N==1 then if N==1 then
self:E(self.lid..string.format("ERROR: Cannot remove waypoint with index=%d! It is the only waypoint and a group needs at least ONE waypoint", wpindex)) self:T(self.lid..string.format("ERROR: Cannot remove waypoint with index=%d! It is the only waypoint and a group needs at least ONE waypoint", wpindex))
return self return self
end end
-- Check that wpindex is not larger than the number of waypoints in the table. -- Check that wpindex is not larger than the number of waypoints in the table.
if wpindex>N then if wpindex>N then
self:E(self.lid..string.format("ERROR: Cannot remove waypoint with index=%d as there are only N=%d waypoints!", wpindex, N)) self:T(self.lid..string.format("ERROR: Cannot remove waypoint with index=%d as there are only N=%d waypoints!", wpindex, N))
return self return self
end end
@ -3101,7 +3101,7 @@ end
function OPSGROUP:ClearTasks() function OPSGROUP:ClearTasks()
local hastask=self:HasTaskController() local hastask=self:HasTaskController()
if self:IsAlive() and self.controller and self:HasTaskController() then if self:IsAlive() and self.controller and self:HasTaskController() then
self:I(self.lid..string.format("CLEARING Tasks")) self:T(self.lid..string.format("CLEARING Tasks"))
self.controller:resetTask() self.controller:resetTask()
end end
return self return self
@ -3639,7 +3639,7 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
--- ---
-- Just stay put and wait until something happens. -- Just stay put and wait until something happens.
elseif Task.dcstask.id==AUFTRAG.SpecialTask.ALERT5 then elseif Task.dcstask.id==AUFTRAG.SpecialTask.ALERT5 then
--- ---
@ -3723,7 +3723,7 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
elseif Task.type==OPSGROUP.TaskType.WAYPOINT then elseif Task.type==OPSGROUP.TaskType.WAYPOINT then
-- Waypoint tasks are executed elsewhere! -- Waypoint tasks are executed elsewhere!
else else
self:E(self.lid.."ERROR: Unknown task type: ") self:T(self.lid.."ERROR: Unknown task type: ")
end end
end end
@ -3803,7 +3803,7 @@ function OPSGROUP:onafterTaskCancel(From, Event, To, Task)
else else
local text=string.format("WARNING: No (current) task to cancel!") local text=string.format("WARNING: No (current) task to cancel!")
self:E(self.lid..text) self:T(self.lid..text)
end end
@ -3925,9 +3925,9 @@ function OPSGROUP:AddMission(Mission)
table.insert(self.missionqueue, Mission) table.insert(self.missionqueue, Mission)
-- ad infinitum? -- ad infinitum?
self.adinfinitum = Mission.DCStask.params.adinfinitum and Mission.DCStask.params.adinfinitum or false self.adinfinitum = Mission.DCStask.params.adinfinitum and Mission.DCStask.params.adinfinitum or false
-- Info text. -- Info text.
local text=string.format("Added %s mission %s starting at %s, stopping at %s", local text=string.format("Added %s mission %s starting at %s, stopping at %s",
tostring(Mission.type), tostring(Mission.name), UTILS.SecondsToClock(Mission.Tstart, true), Mission.Tstop and UTILS.SecondsToClock(Mission.Tstop, true) or "INF") tostring(Mission.type), tostring(Mission.name), UTILS.SecondsToClock(Mission.Tstart, true), Mission.Tstop and UTILS.SecondsToClock(Mission.Tstop, true) or "INF")
@ -3953,7 +3953,7 @@ function OPSGROUP:RemoveMission(Mission)
if Task then if Task then
self:RemoveTask(Task) self:RemoveTask(Task)
end end
-- Take care of a paused mission. -- Take care of a paused mission.
if self.missionpaused and self.missionpaused.auftragsnummer==Mission.auftragsnummer then if self.missionpaused and self.missionpaused.auftragsnummer==Mission.auftragsnummer then
self.missionpaused=nil self.missionpaused=nil
@ -4222,14 +4222,14 @@ function OPSGROUP:onafterMissionStart(From, Event, To, Mission)
-- Route group to mission zone. -- Route group to mission zone.
if self.speedMax>3.6 then if self.speedMax>3.6 then
self:RouteToMission(Mission, 3) self:RouteToMission(Mission, 3)
else else
--- ---
-- IMMOBILE Group -- IMMOBILE Group
--- ---
env.info("FF Immobile GROUP") env.info("FF Immobile GROUP")
-- Add waypoint task. UpdateRoute is called inside. -- Add waypoint task. UpdateRoute is called inside.
@ -4240,7 +4240,7 @@ function OPSGROUP:onafterMissionStart(From, Event, To, Mission)
-- Set waypoint task. -- Set waypoint task.
Mission:SetGroupWaypointTask(self, Task) Mission:SetGroupWaypointTask(self, Task)
-- Execute task. This calls mission execute. -- Execute task. This calls mission execute.
self:__TaskExecute(3, Task) self:__TaskExecute(3, Task)
end end
@ -4320,7 +4320,7 @@ function OPSGROUP:onafterUnpauseMission(From, Event, To)
self.missionpaused=nil self.missionpaused=nil
else else
self:E(self.lid.."ERROR: No mission to unpause!") self:T(self.lid.."ERROR: No mission to unpause!")
end end
end end
@ -4543,7 +4543,7 @@ function OPSGROUP:RouteToMission(mission, delay)
end end
-- Get ingress waypoint. -- Get ingress waypoint.
if mission.type==AUFTRAG.Type.PATROLZONE or mission.type==AUFTRAG.Type.BARRAGE or mission.type==AUFTRAG.Type.AMMOSUPPLY if mission.type==AUFTRAG.Type.PATROLZONE or mission.type==AUFTRAG.Type.BARRAGE or mission.type==AUFTRAG.Type.AMMOSUPPLY
or mission.type.FUELSUPPLY then or mission.type.FUELSUPPLY then
local zone=mission.engageTarget:GetObject() --Core.Zone#ZONE local zone=mission.engageTarget:GetObject() --Core.Zone#ZONE
waypointcoord=zone:GetRandomCoordinate(nil , nil, surfacetypes) waypointcoord=zone:GetRandomCoordinate(nil , nil, surfacetypes)
@ -4552,7 +4552,7 @@ function OPSGROUP:RouteToMission(mission, delay)
else else
waypointcoord=mission:GetMissionWaypointCoord(self.group, randomradius, surfacetypes) waypointcoord=mission:GetMissionWaypointCoord(self.group, randomradius, surfacetypes)
end end
local armorwaypointcoord = nil local armorwaypointcoord = nil
if mission.type==AUFTRAG.Type.ARMORATTACK then if mission.type==AUFTRAG.Type.ARMORATTACK then
local target=mission.engageTarget:GetObject() -- Wrapper.Positionable#POSITIONABLE local target=mission.engageTarget:GetObject() -- Wrapper.Positionable#POSITIONABLE
@ -4562,7 +4562,7 @@ function OPSGROUP:RouteToMission(mission, delay)
-- Ingress - add formation to this one -- Ingress - add formation to this one
armorwaypointcoord = zone:GetRandomCoordinate(1000, 500, surfacetypes) -- Core.Point#COORDINATE armorwaypointcoord = zone:GetRandomCoordinate(1000, 500, surfacetypes) -- Core.Point#COORDINATE
end end
-- Add enroute tasks. -- Add enroute tasks.
for _,task in pairs(mission.enrouteTasks) do for _,task in pairs(mission.enrouteTasks) do
self:AddTaskEnroute(task) self:AddTaskEnroute(task)
@ -5301,7 +5301,7 @@ function OPSGROUP:onbeforeLaserOn(From, Event, To, Target)
else else
-- No target specified. -- No target specified.
self:E(self.lid.."ERROR: No target provided for LASER!") self:T(self.lid.."ERROR: No target provided for LASER!")
return false return false
end end
@ -5328,7 +5328,7 @@ function OPSGROUP:onbeforeLaserOn(From, Event, To, Target)
-- Check LOS. -- Check LOS.
local los=self:HasLoS(self.spot.Coordinate, self.spot.element, self.spot.offset) local los=self:HasLoS(self.spot.Coordinate, self.spot.element, self.spot.offset)
--self:I({los=los, coord=self.spot.Coordinate, offset=self.spot.offset}) --self:T({los=los, coord=self.spot.Coordinate, offset=self.spot.offset})
if los then if los then
self:LaserGotLOS() self:LaserGotLOS()
@ -5342,7 +5342,7 @@ function OPSGROUP:onbeforeLaserOn(From, Event, To, Target)
end end
else else
self:E(self.lid.."ERROR: No element alive for lasing") self:T(self.lid.."ERROR: No element alive for lasing")
return false return false
end end
@ -5609,7 +5609,7 @@ function OPSGROUP:SetLaserTarget(Target)
end end
else else
self:E("WARNING: LASER target is not alive!") self:T("WARNING: LASER target is not alive!")
return return
end end
@ -5620,7 +5620,7 @@ function OPSGROUP:SetLaserTarget(Target)
self.spot.offsetTarget={x=0, y=0, z=0} self.spot.offsetTarget={x=0, y=0, z=0}
else else
self:E(self.lid.."ERROR: LASER target should be a POSITIONABLE (GROUP, UNIT or STATIC) or a COORDINATE object!") self:T(self.lid.."ERROR: LASER target should be a POSITIONABLE (GROUP, UNIT or STATIC) or a COORDINATE object!")
return return
end end
@ -5713,7 +5713,7 @@ function OPSGROUP:_UpdateLaser()
if los then if los then
-- Got LOS -- Got LOS
if self.spot.lostLOS then if self.spot.lostLOS then
--self:I({los=self.spot.LOS, coord=self.spot.Coordinate, offset=self.spot.offset}) --self:T({los=self.spot.LOS, coord=self.spot.Coordinate, offset=self.spot.offset})
self:LaserGotLOS() self:LaserGotLOS()
end end
@ -5878,7 +5878,7 @@ end
function OPSGROUP:onafterRespawn(From, Event, To, Template) function OPSGROUP:onafterRespawn(From, Event, To, Template)
-- Debug info. -- Debug info.
self:I(self.lid.."Respawning group!") self:T(self.lid.."Respawning group!")
-- Copy template. -- Copy template.
local template=UTILS.DeepCopy(Template or self.template) local template=UTILS.DeepCopy(Template or self.template)
@ -6148,7 +6148,7 @@ function OPSGROUP:onbeforeStop(From, Event, To)
-- We check if -- We check if
if self:IsAlive() then if self:IsAlive() then
self:E(self.lid..string.format("WARNING: Group is still alive! Will not stop the FSM. Use :Despawn() instead")) self:T(self.lid..string.format("WARNING: Group is still alive! Will not stop the FSM. Use :Despawn() instead"))
return false return false
end end
@ -6205,7 +6205,7 @@ function OPSGROUP:onafterStop(From, Event, To)
local life, life0=self:GetLifePoints() local life, life0=self:GetLifePoints()
local state=self:GetState() local state=self:GetState()
local text=string.format("WARNING: Group is still alive! Current state=%s. Life points=%d/%d. Use OPSGROUP:Destroy() or OPSGROUP:Despawn() for a clean stop", state, life, life0) local text=string.format("WARNING: Group is still alive! Current state=%s. Life points=%d/%d. Use OPSGROUP:Destroy() or OPSGROUP:Despawn() for a clean stop", state, life, life0)
self:E(self.lid..text) self:T(self.lid..text)
end end
-- Remove flight from data base. -- Remove flight from data base.
@ -6249,7 +6249,7 @@ function OPSGROUP:_CheckCargoTransport()
if text=="" then if text=="" then
text=" empty" text=" empty"
end end
self:I(self.lid.."Cargo bay:"..text) self:T(self.lid.."Cargo bay:"..text)
end end
-- Cargo queue debug info. -- Cargo queue debug info.
@ -6274,7 +6274,7 @@ function OPSGROUP:_CheckCargoTransport()
end end
end end
if text~="" then if text~="" then
self:I(self.lid.."Cargo queue:"..text) self:T(self.lid.."Cargo queue:"..text)
end end
end end
@ -6589,7 +6589,7 @@ function OPSGROUP:_DelCargobay(CargoGroup)
return true return true
end end
self:E(self.lid.."ERROR: Group is not in cargo bay. Cannot remove it!") self:T(self.lid.."ERROR: Group is not in cargo bay. Cannot remove it!")
return false return false
end end
@ -6928,7 +6928,7 @@ function OPSGROUP:GetWeightCargo(UnitName, IncludeReserved)
-- Quick check. -- Quick check.
if IncludeReserved==false and gewicht~=weight then if IncludeReserved==false and gewicht~=weight then
self:E(self.lid..string.format("ERROR: FF weight!=gewicht: weight=%.1f, gewicht=%.1f", weight, gewicht)) self:T(self.lid..string.format("ERROR: FF weight!=gewicht: weight=%.1f, gewicht=%.1f", weight, gewicht))
end end
return gewicht return gewicht
@ -7262,7 +7262,7 @@ function OPSGROUP:onafterPickup(From, Event, To)
local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate, nil, uid, UTILS.MetersToFeet(self.altitudeCruise), false) ; waypoint.detour=1 local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate, nil, uid, UTILS.MetersToFeet(self.altitudeCruise), false) ; waypoint.detour=1
else else
self:E(self.lid.."ERROR: Transportcarrier aircraft cannot land in Pickup zone! Specify a ZONE_AIRBASE as pickup zone") self:T(self.lid.."ERROR: Transportcarrier aircraft cannot land in Pickup zone! Specify a ZONE_AIRBASE as pickup zone")
end end
-- Cancel landedAt task. This should trigger Cruise once airborne. -- Cancel landedAt task. This should trigger Cruise once airborne.
@ -7271,7 +7271,7 @@ function OPSGROUP:onafterPickup(From, Event, To)
if Task then if Task then
self:TaskCancel(Task) self:TaskCancel(Task)
else else
self:E(self.lid.."ERROR: No current task but landed at?!") self:T(self.lid.."ERROR: No current task but landed at?!")
end end
end end
@ -7502,7 +7502,7 @@ function OPSGROUP:onafterLoad(From, Event, To, CargoGroup, Carrier)
end end
else else
self:E(self.lid.."ERROR: Cargo has no carrier on Load event!") self:T(self.lid.."ERROR: Cargo has no carrier on Load event!")
end end
end end
@ -7656,7 +7656,7 @@ function OPSGROUP:onafterTransport(From, Event, To)
local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate, nil, self:GetWaypointCurrent().uid, UTILS.MetersToFeet(self.altitudeCruise), false) ; waypoint.detour=1 local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate, nil, self:GetWaypointCurrent().uid, UTILS.MetersToFeet(self.altitudeCruise), false) ; waypoint.detour=1
else else
self:E(self.lid.."ERROR: Aircraft (cargo carrier) cannot land in Deploy zone! Specify a ZONE_AIRBASE as deploy zone") self:T(self.lid.."ERROR: Aircraft (cargo carrier) cannot land in Deploy zone! Specify a ZONE_AIRBASE as deploy zone")
end end
-- Cancel landedAt task. This should trigger Cruise once airborne. -- Cancel landedAt task. This should trigger Cruise once airborne.
@ -7665,7 +7665,7 @@ function OPSGROUP:onafterTransport(From, Event, To)
if Task then if Task then
self:TaskCancel(Task) self:TaskCancel(Task)
else else
self:E(self.lid.."ERROR: No current task but landed at?!") self:T(self.lid.."ERROR: No current task but landed at?!")
end end
end end
@ -7793,7 +7793,7 @@ function OPSGROUP:onafterUnloading(From, Event, To)
--- ---
-- Issue warning. -- Issue warning.
self:E(self.lid.."ERROR: Deploy/disembark zone is a ZONE_AIRBASE of a ship! Where to put the cargo? Dumping into the sea, sorry!") self:T(self.lid.."ERROR: Deploy/disembark zone is a ZONE_AIRBASE of a ship! Where to put the cargo? Dumping into the sea, sorry!")
-- Unload but keep "in utero" (no coordinate provided). -- Unload but keep "in utero" (no coordinate provided).
self:Unload(cargo.opsgroup) self:Unload(cargo.opsgroup)
@ -7992,7 +7992,7 @@ end
-- @param #string To To state. -- @param #string To To state.
-- @param #OPSGROUP OpsGroupCargo Cargo OPSGROUP that was unloaded from a carrier. -- @param #OPSGROUP OpsGroupCargo Cargo OPSGROUP that was unloaded from a carrier.
function OPSGROUP:onafterUnloaded(From, Event, To, OpsGroupCargo) function OPSGROUP:onafterUnloaded(From, Event, To, OpsGroupCargo)
self:I(self.lid..string.format("Unloaded OPSGROUP %s", OpsGroupCargo:GetName())) self:T(self.lid..string.format("Unloaded OPSGROUP %s", OpsGroupCargo:GetName()))
end end
@ -8023,13 +8023,13 @@ function OPSGROUP:onafterUnloadingDone(From, Event, To)
if self.cargoTZC then if self.cargoTZC then
-- Pickup the next batch. -- Pickup the next batch.
self:I(self.lid.."Unloaded: Still cargo left ==> Pickup") self:T(self.lid.."Unloaded: Still cargo left ==> Pickup")
self:Pickup() self:Pickup()
else else
-- Debug info. -- Debug info.
self:I(self.lid..string.format("WARNING: Not all cargo was delivered but could not get a transport zone combo ==> setting carrier state to NOT CARRIER")) self:T(self.lid..string.format("WARNING: Not all cargo was delivered but could not get a transport zone combo ==> setting carrier state to NOT CARRIER"))
-- This is not a carrier anymore. -- This is not a carrier anymore.
self:_NewCarrierStatus(OPSGROUP.CarrierStatus.NOTCARRIER) self:_NewCarrierStatus(OPSGROUP.CarrierStatus.NOTCARRIER)
@ -8039,7 +8039,7 @@ function OPSGROUP:onafterUnloadingDone(From, Event, To)
else else
-- Everything delivered. -- Everything delivered.
self:I(self.lid.."Unloaded: ALL cargo unloaded ==> Delivered (current)") self:T(self.lid.."Unloaded: ALL cargo unloaded ==> Delivered (current)")
self:Delivered(self.cargoTransport) self:Delivered(self.cargoTransport)
end end
@ -8239,14 +8239,14 @@ end
function OPSGROUP:onbeforeBoard(From, Event, To, CarrierGroup, Carrier) function OPSGROUP:onbeforeBoard(From, Event, To, CarrierGroup, Carrier)
if self:IsDead() then if self:IsDead() then
self:I(self.lid.."Group DEAD ==> Deny Board transition!") self:T(self.lid.."Group DEAD ==> Deny Board transition!")
return false return false
elseif CarrierGroup:IsDead() then elseif CarrierGroup:IsDead() then
self:I(self.lid.."Carrier Group DEAD ==> Deny Board transition!") self:T(self.lid.."Carrier Group DEAD ==> Deny Board transition!")
self:_NewCargoStatus(OPSGROUP.CargoStatus.NOTCARGO) self:_NewCargoStatus(OPSGROUP.CargoStatus.NOTCARGO)
return false return false
elseif Carrier.status==OPSGROUP.ElementStatus.DEAD then elseif Carrier.status==OPSGROUP.ElementStatus.DEAD then
self:I(self.lid.."Carrier Element DEAD ==> Deny Board transition!") self:T(self.lid.."Carrier Element DEAD ==> Deny Board transition!")
self:_NewCargoStatus(OPSGROUP.CargoStatus.NOTCARGO) self:_NewCargoStatus(OPSGROUP.CargoStatus.NOTCARGO)
return false return false
end end
@ -8592,7 +8592,7 @@ function OPSGROUP:_CheckGroupDone(delay)
self:T(self.lid..string.format("Adinfinitum=TRUE ==> Goto WP index=%d at speed=%d knots", i, speed)) self:T(self.lid..string.format("Adinfinitum=TRUE ==> Goto WP index=%d at speed=%d knots", i, speed))
else else
self:E(self.lid..string.format("WARNING: No waypoints left! Commanding a Full Stop")) self:T(self.lid..string.format("WARNING: No waypoints left! Commanding a Full Stop"))
self:__FullStop(-1) self:__FullStop(-1)
end end
@ -8632,7 +8632,7 @@ function OPSGROUP:_CheckGroupDone(delay)
self:T(self.lid..string.format("NOT Passed final WP, #WP>0 ==> Update Route")) self:T(self.lid..string.format("NOT Passed final WP, #WP>0 ==> Update Route"))
self:Cruise() self:Cruise()
else else
self:E(self.lid..string.format("WARNING: No waypoints left! Commanding a Full Stop")) self:T(self.lid..string.format("WARNING: No waypoints left! Commanding a Full Stop"))
self:__FullStop(-1) self:__FullStop(-1)
end end
@ -8686,7 +8686,7 @@ function OPSGROUP:_CheckStuck()
if holdtime>=5*60 and holdtime<10*60 then if holdtime>=5*60 and holdtime<10*60 then
-- Debug warning. -- Debug warning.
self:E(self.lid..string.format("WARNING: Group came to an unexpected standstill. Speed=%.1f<%.1f m/s expected for %d sec", speed, ExpectedSpeed, holdtime)) 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))
-- Give cruise command again. -- Give cruise command again.
if self:IsReturning() then if self:IsReturning() then
@ -8698,14 +8698,14 @@ function OPSGROUP:_CheckStuck()
elseif holdtime>=10*60 and holdtime<30*60 then elseif holdtime>=10*60 and holdtime<30*60 then
-- Debug warning. -- Debug warning.
self:E(self.lid..string.format("WARNING: Group came to an unexpected standstill. Speed=%.1f<%.1f m/s expected for %d sec", speed, ExpectedSpeed, holdtime)) 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))
--TODO: Stuck event! --TODO: Stuck event!
-- Look for a current mission and cancel it as we do not seem to be able to perform it. -- Look for a current mission and cancel it as we do not seem to be able to perform it.
local mission=self:GetMissionCurrent() local mission=self:GetMissionCurrent()
if mission then if mission then
self:E(self.lid..string.format("WARNING: Cancelling mission %s [%s] due to being stuck", mission:GetName(), mission:GetType())) self:T(self.lid..string.format("WARNING: Cancelling mission %s [%s] due to being stuck", mission:GetName(), mission:GetType()))
self:MissionCancel(mission) self:MissionCancel(mission)
else else
-- Give cruise command again. -- Give cruise command again.
@ -8719,7 +8719,7 @@ function OPSGROUP:_CheckStuck()
elseif holdtime>=30*60 then elseif holdtime>=30*60 then
-- Debug warning. -- Debug warning.
self:E(self.lid..string.format("WARNING: Group came to an unexpected standstill. Speed=%.1f<%.1f m/s expected for %d sec", speed, ExpectedSpeed, holdtime)) 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))
end end
@ -9137,7 +9137,7 @@ function OPSGROUP:_InitWaypoints(WpIndexMin, WpIndexMax)
end end
else else
self:E(self.lid.."WARNING: No waypoints initialized. Number of waypoints is 0!") self:T(self.lid.."WARNING: No waypoints initialized. Number of waypoints is 0!")
end end
return self return self
@ -9172,7 +9172,7 @@ function OPSGROUP:Route(waypoints, delay)
self:SetTask(DCSTask) self:SetTask(DCSTask)
else else
self:E(self.lid.."ERROR: Group is not alive! Cannot route group.") self:T(self.lid.."ERROR: Group is not alive! Cannot route group.")
end end
end end
@ -9289,7 +9289,7 @@ function OPSGROUP._PassingWaypoint(opsgroup, uid)
if (opsgroup:IsNavygroup() or opsgroup:IsArmygroup()) and opsgroup.currentwp==#opsgroup.waypoints then if (opsgroup:IsNavygroup() or opsgroup:IsArmygroup()) and opsgroup.currentwp==#opsgroup.waypoints then
--TODO: not sure if this works with FLIGHTGROUPS --TODO: not sure if this works with FLIGHTGROUPS
-- Removing this for now. -- Removing this for now.
opsgroup:Cruise() opsgroup:Cruise()
end end
@ -9502,7 +9502,7 @@ function OPSGROUP:SwitchROE(roe)
if self:IsInUtero() then if self:IsInUtero() then
self:T2(self.lid..string.format("Setting current ROE=%d when GROUP is SPAWNED", self.option.ROE)) self:T2(self.lid..string.format("Setting current ROE=%d when GROUP is SPAWNED", self.option.ROE))
else else
self.group:OptionROE(self.option.ROE) self.group:OptionROE(self.option.ROE)
self:T(self.lid..string.format("Setting current ROE=%d (%s)", self.option.ROE, self:_GetROEName(self.option.ROE))) self:T(self.lid..string.format("Setting current ROE=%d (%s)", self.option.ROE, self:_GetROEName(self.option.ROE)))
@ -9510,7 +9510,7 @@ function OPSGROUP:SwitchROE(roe)
else else
self:E(self.lid.."WARNING: Cannot switch ROE! Group is not alive") self:T(self.lid.."WARNING: Cannot switch ROE! Group is not alive")
end end
return self return self
@ -9575,7 +9575,7 @@ function OPSGROUP:SwitchROT(rot)
else else
self:E(self.lid.."WARNING: Cannot switch ROT! Group is not alive") self:T(self.lid.."WARNING: Cannot switch ROT! Group is not alive")
end end
end end
@ -9628,7 +9628,7 @@ function OPSGROUP:SwitchAlarmstate(alarmstate)
elseif self.option.Alarm==2 then elseif self.option.Alarm==2 then
self.group:OptionAlarmStateRed() self.group:OptionAlarmStateRed()
else else
self:E("ERROR: Unknown Alarm State! Setting to AUTO") self:T("ERROR: Unknown Alarm State! Setting to AUTO")
self.group:OptionAlarmStateAuto() self.group:OptionAlarmStateAuto()
self.option.Alarm=0 self.option.Alarm=0
end end
@ -9639,7 +9639,7 @@ function OPSGROUP:SwitchAlarmstate(alarmstate)
end end
else else
self:E(self.lid.."WARNING: Cannot switch Alarm State! Group is not alive.") self:T(self.lid.."WARNING: Cannot switch Alarm State! Group is not alive.")
end end
return self return self
@ -9888,11 +9888,11 @@ function OPSGROUP:SwitchTACAN(Channel, Morse, UnitName, Band)
self:T(self.lid..string.format("Switching TACAN to Channel %d%s Morse %s on unit %s", self.tacan.Channel, self.tacan.Band, tostring(self.tacan.Morse), self.tacan.BeaconName)) self:T(self.lid..string.format("Switching TACAN to Channel %d%s Morse %s on unit %s", self.tacan.Channel, self.tacan.Band, tostring(self.tacan.Morse), self.tacan.BeaconName))
else else
self:E(self.lid.."ERROR: Cound not set TACAN! Unit is not alive") self:T(self.lid.."ERROR: Cound not set TACAN! Unit is not alive")
end end
else else
self:E(self.lid.."ERROR: Cound not set TACAN! Group is not alive and not in utero any more") self:T(self.lid.."ERROR: Cound not set TACAN! Group is not alive and not in utero any more")
end end
return self return self
@ -10030,7 +10030,7 @@ function OPSGROUP:SwitchICLS(Channel, Morse, UnitName)
self:T(self.lid..string.format("Switching ICLS to Channel %d Morse %s on unit %s", self.icls.Channel, tostring(self.icls.Morse), self.icls.BeaconName)) self:T(self.lid..string.format("Switching ICLS to Channel %d Morse %s on unit %s", self.icls.Channel, tostring(self.icls.Morse), self.icls.BeaconName))
else else
self:E(self.lid.."ERROR: Cound not set ICLS! Unit is not alive.") self:T(self.lid.."ERROR: Cound not set ICLS! Unit is not alive.")
end end
end end
@ -10119,7 +10119,7 @@ function OPSGROUP:SwitchRadio(Frequency, Modulation)
self:T(self.lid..string.format("Switching radio to frequency %.3f MHz %s", self.radio.Freq, UTILS.GetModulationName(self.radio.Modu))) self:T(self.lid..string.format("Switching radio to frequency %.3f MHz %s", self.radio.Freq, UTILS.GetModulationName(self.radio.Modu)))
else else
self:E(self.lid.."ERROR: Cound not set Radio! Group is not alive or not in utero any more") self:T(self.lid.."ERROR: Cound not set Radio! Group is not alive or not in utero any more")
end end
return self return self
@ -10142,7 +10142,7 @@ function OPSGROUP:TurnOffRadio()
self:T(self.lid..string.format("Switching radio OFF")) self:T(self.lid..string.format("Switching radio OFF"))
else else
self:E(self.lid.."ERROR: Radio can only be turned off for aircraft!") self:T(self.lid.."ERROR: Radio can only be turned off for aircraft!")
end end
end end
@ -10182,7 +10182,7 @@ function OPSGROUP:SwitchFormation(Formation)
-- Polymorphic and overwritten in ARMYGROUP. -- Polymorphic and overwritten in ARMYGROUP.
else else
self:E(self.lid.."ERROR: Formation can only be set for aircraft or ground units!") self:T(self.lid.."ERROR: Formation can only be set for aircraft or ground units!")
return self return self
end end
@ -10255,7 +10255,7 @@ function OPSGROUP:SwitchCallsign(CallsignName, CallsignNumber)
end end
else else
self:E(self.lid.."ERROR: Group is not alive and not in utero! Cannot switch callsign") self:T(self.lid.."ERROR: Group is not alive and not in utero! Cannot switch callsign")
end end
return self return self
@ -11101,11 +11101,11 @@ function OPSGROUP:_CoordinateFromObject(Object)
local coord=Object:GetCoordinate() local coord=Object:GetCoordinate()
return coord return coord
else else
self:E(self.lid.."ERROR: Coordinate is neither a COORDINATE nor any POSITIONABLE or ZONE!") self:T(self.lid.."ERROR: Coordinate is neither a COORDINATE nor any POSITIONABLE or ZONE!")
end end
end end
else else
self:E(self.lid.."ERROR: Object passed is nil!") self:T(self.lid.."ERROR: Object passed is nil!")
end end
return nil return nil
@ -11213,8 +11213,8 @@ function OPSGROUP:_AddElementByName(unitname)
element.category=unit:GetUnitCategory() element.category=unit:GetUnitCategory()
element.categoryname=unit:GetCategoryName() element.categoryname=unit:GetCategoryName()
element.typename=unit:GetTypeName() element.typename=unit:GetTypeName()
--self:I({desc=element.descriptors}) --self:I({desc=element.descriptors})
-- Ammo. -- Ammo.
@ -11327,7 +11327,7 @@ function OPSGROUP:_GetTemplate(Copy)
end end
else else
self:E(self.lid..string.format("ERROR: No template was set yet!")) self:T(self.lid..string.format("ERROR: No template was set yet!"))
end end
return nil return nil

View File

@ -802,7 +802,7 @@ function RESCUEHELO:_OnEventCrashOrEject(EventData)
-- Debug. -- Debug.
local text=string.format("Unit %s crashed or ejected.", unitname) local text=string.format("Unit %s crashed or ejected.", unitname)
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug) MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
self:I(self.lid..text) self:T(self.lid..text)
-- Get coordinate of unit. -- Get coordinate of unit.
local coord=unit:GetCoordinate() local coord=unit:GetCoordinate()

View File

@ -409,7 +409,11 @@ end
-- @param #number knots Speed in knots. -- @param #number knots Speed in knots.
-- @return #number Speed in m/s. -- @return #number Speed in m/s.
UTILS.KnotsToMps = function( knots ) UTILS.KnotsToMps = function( knots )
return knots / 1.94384 --* 1852 / 3600 if type(knots) == "number" then
return knots / 1.94384 --* 1852 / 3600
else
return 0
end
end end
--- Convert temperature from Celsius to Farenheit. --- Convert temperature from Celsius to Farenheit.