Merge branch 'FF/Ops' into FF/OpsDev

This commit is contained in:
Frank
2024-01-01 21:55:52 +01:00
57 changed files with 3538 additions and 1657 deletions

View File

@@ -449,10 +449,10 @@ do -- Zones and Pathlines
-- Loop over layers.
for layerID, layerData in pairs(env.mission.drawings.layers or {}) do
-- Loop over objects in layers.
for objectID, objectData in pairs(layerData.objects or {}) do
-- Check for polygon which has at least 4 points (we would need 3 but the origin seems to be there twice)
if objectData.polygonMode and (objectData.polygonMode=="free") and objectData.points and #objectData.points>=4 then
@@ -488,10 +488,32 @@ do -- Zones and Pathlines
-- Create new polygon zone.
local Zone=ZONE_POLYGON:NewFromPointsArray(ZoneName, points)
--Zone.DrawID = objectID
-- Set color.
Zone:SetColor({1, 0, 0}, 0.15)
Zone:SetFillColor({1, 0, 0}, 0.15)
if objectData.colorString then
-- eg colorString = 0xff0000ff
local color = string.gsub(objectData.colorString,"^0x","")
local r = tonumber(string.sub(color,1,2),16)/255
local g = tonumber(string.sub(color,3,4),16)/255
local b = tonumber(string.sub(color,5,6),16)/255
local a = tonumber(string.sub(color,7,8),16)/255
Zone:SetColor({r, g, b}, a)
end
if objectData.fillColorString then
-- eg fillColorString = 0xff00004b
local color = string.gsub(objectData.colorString,"^0x","")
local r = tonumber(string.sub(color,1,2),16)/255
local g = tonumber(string.sub(color,3,4),16)/255
local b = tonumber(string.sub(color,5,6),16)/255
local a = tonumber(string.sub(color,7,8),16)/255
Zone:SetFillColor({r, g, b}, a)
end
-- Store in DB.
self.ZONENAMES[ZoneName] = ZoneName
@@ -532,7 +554,26 @@ do -- Zones and Pathlines
-- Set color.
Zone:SetColor({1, 0, 0}, 0.15)
if objectData.colorString then
-- eg colorString = 0xff0000ff
local color = string.gsub(objectData.colorString,"^0x","")
local r = tonumber(string.sub(color,1,2),16)/255
local g = tonumber(string.sub(color,3,4),16)/255
local b = tonumber(string.sub(color,5,6),16)/255
local a = tonumber(string.sub(color,7,8),16)/255
Zone:SetColor({r, g, b}, a)
end
if objectData.fillColorString then
-- eg fillColorString = 0xff00004b
local color = string.gsub(objectData.colorString,"^0x","")
local r = tonumber(string.sub(color,1,2),16)/255
local g = tonumber(string.sub(color,3,4),16)/255
local b = tonumber(string.sub(color,5,6),16)/255
local a = tonumber(string.sub(color,7,8),16)/255
Zone:SetFillColor({r, g, b}, a)
end
-- Store in DB.
self.ZONENAMES[ZoneName] = ZoneName
@@ -756,7 +797,7 @@ end -- cargo
--- Finds a CLIENT based on the ClientName.
-- @param #DATABASE self
-- @param #string ClientName
-- @param #string ClientName - Note this is the UNIT name of the client!
-- @return Wrapper.Client#CLIENT The found CLIENT.
function DATABASE:FindClient( ClientName )

View File

@@ -368,7 +368,7 @@ function MESSAGE:ToCoalition( CoalitionSide, Settings )
if CoalitionSide then
if self.MessageDuration ~= 0 then
self:T( self.MessageCategory .. self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ) .. " / " .. self.MessageDuration )
trigger.action.outTextForCoalition( CoalitionSide, self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ), self.MessageDuration, self.ClearScreen )
trigger.action.outTextForCoalition( CoalitionSide, self.MessageCategory .. self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ), self.MessageDuration, self.ClearScreen )
end
end
@@ -498,7 +498,6 @@ function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,G
_MESSAGESRS.Gender = Gender or "female"
_MESSAGESRS.MSRS:SetGoogle(PathToCredentials)
_MESSAGESRS.google = PathToCredentials
_MESSAGESRS.MSRS:SetLabel(Label or "MESSAGE")
_MESSAGESRS.label = Label or "MESSAGE"
@@ -512,8 +511,6 @@ function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,G
if Voice then _MESSAGESRS.MSRS:SetVoice(Voice) end
_MESSAGESRS.voice = Voice --or MSRS.Voices.Microsoft.Hedda
--if _MESSAGESRS.google and not Voice then _MESSAGESRS.Voice = MSRS.Voices.Google.Standard.en_GB_Standard_A end
--_MESSAGESRS.MSRS:SetVoice(Voice or _MESSAGESRS.voice)
_MESSAGESRS.SRSQ = MSRSQUEUE:New(Label or "MESSAGE")
end

View File

@@ -24,8 +24,9 @@
do -- COORDINATE
--- @type COORDINATE
---
-- @type COORDINATE
-- @field #string ClassName Name of the class
-- @field #number x Component of the 3D vector.
-- @field #number y Component of the 3D vector.
@@ -2472,15 +2473,18 @@ do -- COORDINATE
-- Write command as string and execute that. Idea by Grimes https://forum.dcs.world/topic/324201-mark-to-all-function/#comment-5273793
local s=string.format("trigger.action.markupToAll(7, %d, %d,", Coalition, MarkID)
for _,vec in pairs(vecs) do
s=s..string.format("%s,", UTILS._OneLineSerialize(vec))
--s=s..string.format("%s,", UTILS._OneLineSerialize(vec))
s=s..string.format("{x=%.1f, y=%.1f, z=%.1f},", vec.x, vec.y, vec.z)
end
s=s..string.format("%s, %s, %s, %s", UTILS._OneLineSerialize(Color), UTILS._OneLineSerialize(FillColor), tostring(LineType), tostring(ReadOnly))
if Text and Text~="" then
s=s..string.format(", \"%s\"", Text)
s=s..string.format("{%.3f, %.3f, %.3f, %.3f},", Color[1], Color[2], Color[3], Color[4])
s=s..string.format("{%.3f, %.3f, %.3f, %.3f},", FillColor[1], FillColor[2], FillColor[3], FillColor[4])
s=s..string.format("%d,", LineType or 1)
s=s..string.format("%s", tostring(ReadOnly))
if Text and type(Text)=="string" and string.len(Text)>0 then
s=s..string.format(", \"%s\"", tostring(Text))
end
s=s..")"
-- Execute string command
local success=UTILS.DoString(s)
@@ -2568,7 +2572,7 @@ do -- COORDINATE
Offset=Offset or 2
-- Measurement of visibility should not be from the ground, so Adding a hypotethical 2 meters to each Coordinate.
-- Measurement of visibility should not be from the ground, so Adding a hypothetical 2 meters to each Coordinate.
local FromVec3 = self:GetVec3()
FromVec3.y = FromVec3.y + Offset
@@ -2969,10 +2973,10 @@ do -- COORDINATE
end
-- corrected Track to be direction of travel of bogey (self in this case)
local track = "Maneuver"
if self.Heading then
track = UTILS.BearingToCardinal(self.Heading) or "North"
local track = "Maneuver"
if self.Heading then
track = UTILS.BearingToCardinal(self.Heading) or "North"
end
if rangeNM > 3 then
@@ -3117,6 +3121,49 @@ do -- COORDINATE
local MGRS = coord.LLtoMGRS( lat, lon )
return "MGRS " .. UTILS.tostringMGRS( MGRS, MGRS_Accuracy )
end
--- Provides a COORDINATE from an MGRS String
-- @param #COORDINATE self
-- @param #string MGRSString MGRS String, e.g. "MGRS 37T DK 12345 12345"
-- @return #COORDINATE self
function COORDINATE:NewFromMGRSString( MGRSString )
local myparts = UTILS.Split(MGRSString," ")
local northing = tostring(myparts[5]) or ""
local easting = tostring(myparts[4]) or ""
if string.len(easting) < 5 then easting = easting..string.rep("0",5-string.len(easting)) end
if string.len(northing) < 5 then northing = northing..string.rep("0",5-string.len(northing)) end
local MGRS = {
UTMZone = myparts[2],
MGRSDigraph = myparts[3],
Easting = easting,
Northing = northing,
}
local lat, lon = coord.MGRStoLL(MGRS)
local point = coord.LLtoLO(lat, lon, 0)
local coord = COORDINATE:NewFromVec2({x=point.x,y=point.z})
return coord
end
--- Provides a COORDINATE from an MGRS Coordinate
-- @param #COORDINATE self
-- @param #string UTMZone UTM Zone, e.g. "37T"
-- @param #string MGRSDigraph Digraph, e.g. "DK"
-- @param #string Easting Meters easting - string in order to allow for leading zeros, e.g. "01234". Should be 5 digits.
-- @param #string Northing Meters northing - string in order to allow for leading zeros, e.g. "12340". Should be 5 digits.
-- @return #COORDINATE self
function COORDINATE:NewFromMGRS( UTMZone, MGRSDigraph, Easting, Northing )
if string.len(Easting) < 5 then Easting = Easting..string.rep("0",5-string.len(Easting) )end
if string.len(Northing) < 5 then Northing = Northing..string.rep("0",5-string.len(Northing) )end
local MGRS = {
UTMZone = UTMZone,
MGRSDigraph = MGRSDigraph,
Easting = Easting,
Northing = Northing,
}
local lat, lon = coord.MGRStoLL(MGRS)
local point = coord.LLtoLO(lat, lon, 0)
local coord = COORDINATE:NewFromVec2({x=point.x,y=point.z})
end
--- Provides a coordinate string of the point, based on a coordinate format system:
-- * Uses default settings in COORDINATE.
@@ -3630,7 +3677,7 @@ end
do -- POINT_VEC2
--- @type POINT_VEC2
-- @type POINT_VEC2
-- @field DCS#Distance x The x coordinate in meters.
-- @field DCS#Distance y the y coordinate in meters.
-- @extends Core.Point#COORDINATE

View File

@@ -146,7 +146,45 @@ do -- SET_BASE
return self
end
--- [Internal] Add a functional filter
-- @param #SET_BASE self
-- @param #function ConditionFunction If this function returns `true`, the object is added to the SET. The function needs to take a CONTROLLABLE object as first argument.
-- @param ... Condition function arguments, if any.
-- @return #boolean If true, at least one condition is true
function SET_BASE:FilterFunction(ConditionFunction, ...)
local condition={}
condition.func=ConditionFunction
condition.arg={}
if arg then
condition.arg=arg
end
if not self.Filter.Functions then self.Filter.Functions = {} end
table.insert(self.Filter.Functions, condition)
return self
end
--- [Internal] Check if the condition functions returns true.
-- @param #SET_BASE self
-- @param Wrapper.Controllable#CONTROLLABLE Object The object to filter for
-- @return #boolean If true, if **all** conditions are true
function SET_BASE:_EvalFilterFunctions(Object)
-- All conditions must be true.
for _,_condition in pairs(self.Filter.Functions or {}) do
local condition=_condition
-- Call function.
if condition.func(Object,unpack(condition.arg)) == false then
return false
end
end
-- No condition was true.
return true
end
--- Clear the Objects in the Set.
-- @param #SET_BASE self
-- @param #boolean TriggerEvent If `true`, an event remove is triggered for each group that is removed from the set.
@@ -419,7 +457,11 @@ do -- SET_BASE
-- @param #SET_BASE self
-- @return Core.Base#BASE
function SET_BASE:GetRandom()
local tablemax = table.maxn(self.Index)
local tablemax = 0
for _,_ind in pairs(self.Index) do
tablemax = tablemax + 1
end
--local tablemax = table.maxn(self.Index)
local RandomItem = self.Set[self.Index[math.random(1,tablemax)]]
self:T3( { RandomItem } )
return RandomItem
@@ -561,10 +603,12 @@ do -- SET_BASE
return self
end
--- Iterate the SET_BASE while identifying the nearest object from a @{Core.Point#POINT_VEC2}.
--- Iterate the SET_BASE while identifying the nearest object in the set from a @{Core.Point#POINT_VEC2}.
-- @param #SET_BASE self
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#POINT_VEC2} object from where to evaluate the closest object in the set.
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#COORDINATE} or @{Core.Point#POINT_VEC2} object (but **not** a simple DCS#Vec2!) from where to evaluate the closest object in the set.
-- @return Core.Base#BASE The closest object.
-- @usage
-- myset:FindNearestObjectFromPointVec2( ZONE:New("Test Zone"):GetCoordinate() )
function SET_BASE:FindNearestObjectFromPointVec2( PointVec2 )
self:F2( PointVec2 )
@@ -961,6 +1005,7 @@ do
-- * @{#SET_GROUP.FilterCategoryShip}: Builds the SET_GROUP from ships.
-- * @{#SET_GROUP.FilterCategoryStructure}: Builds the SET_GROUP from structures.
-- * @{#SET_GROUP.FilterZones}: Builds the SET_GROUP with the groups within a @{Core.Zone#ZONE}.
-- * @{#SET_GROUP.FilterFunction}: Builds the SET_GROUP with a custom condition.
--
-- Once the filter criteria have been set for the SET_GROUP, you can start filtering using:
--
@@ -1034,6 +1079,7 @@ do
Countries = nil,
GroupPrefixes = nil,
Zones = nil,
Functions = nil,
},
FilterMeta = {
Coalitions = {
@@ -1247,7 +1293,26 @@ do
return self
end
--- [User] Add a custom condition function.
-- @function [parent=#SET_GROUP] FilterFunction
-- @param #SET_GROUP self
-- @param #function ConditionFunction If this function returns `true`, the object is added to the SET. The function needs to take a GROUP object as first argument.
-- @param ... Condition function arguments if any.
-- @return #SET_GROUP self
-- @usage
-- -- Image you want to exclude a specific GROUP from a SET:
-- local groundset = SET_GROUP:New():FilterCoalitions("blue"):FilterCategoryGround():FilterFunction(
-- -- The function needs to take a GROUP object as first - and in this case, only - argument.
-- function(grp)
-- local isinclude = true
-- if grp:GetName() == "Exclude Me" then isinclude = false end
-- return isinclude
-- end
-- ):FilterOnce()
-- BASE:I(groundset:Flush())
--- Builds a set of groups of coalitions.
-- Possible current coalitions are red, blue and neutral.
-- @param #SET_GROUP self
@@ -1921,7 +1986,7 @@ do
MGroupInclude = MGroupInclude and MGroupActive
end
if self.Filter.Coalitions then
if self.Filter.Coalitions and MGroupInclude then
local MGroupCoalition = false
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
self:T3( { "Coalition:", MGroup:GetCoalition(), self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
@@ -1932,7 +1997,7 @@ do
MGroupInclude = MGroupInclude and MGroupCoalition
end
if self.Filter.Categories then
if self.Filter.Categories and MGroupInclude then
local MGroupCategory = false
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
self:T3( { "Category:", MGroup:GetCategory(), self.FilterMeta.Categories[CategoryName], CategoryName } )
@@ -1943,7 +2008,7 @@ do
MGroupInclude = MGroupInclude and MGroupCategory
end
if self.Filter.Countries then
if self.Filter.Countries and MGroupInclude then
local MGroupCountry = false
for CountryID, CountryName in pairs( self.Filter.Countries ) do
self:T3( { "Country:", MGroup:GetCountry(), CountryName } )
@@ -1954,7 +2019,7 @@ do
MGroupInclude = MGroupInclude and MGroupCountry
end
if self.Filter.GroupPrefixes then
if self.Filter.GroupPrefixes and MGroupInclude then
local MGroupPrefix = false
for GroupPrefixId, GroupPrefix in pairs( self.Filter.GroupPrefixes ) do
self:T3( { "Prefix:", string.find( MGroup:GetName(), GroupPrefix, 1 ), GroupPrefix } )
@@ -1965,7 +2030,7 @@ do
MGroupInclude = MGroupInclude and MGroupPrefix
end
if self.Filter.Zones then
if self.Filter.Zones and MGroupInclude then
local MGroupZone = false
for ZoneName, Zone in pairs( self.Filter.Zones ) do
--self:T( "Zone:", ZoneName )
@@ -1975,6 +2040,12 @@ do
end
MGroupInclude = MGroupInclude and MGroupZone
end
if self.Filter.Functions and MGroupInclude then
local MGroupFunc = false
MGroupFunc = self:_EvalFilterFunctions(MGroup)
MGroupInclude = MGroupInclude and MGroupFunc
end
self:T2( MGroupInclude )
return MGroupInclude
@@ -2074,6 +2145,7 @@ do -- SET_UNIT
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
-- * @{#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}.
-- * @{#SET_UNIT.FilterFunction}: Builds the SET_UNIT with a custom condition.
--
-- Once the filter criteria have been set for the SET_UNIT, you can start filtering using:
--
@@ -2152,6 +2224,7 @@ do -- SET_UNIT
Countries = nil,
UnitPrefixes = nil,
Zones = nil,
Functions = nil,
},
FilterMeta = {
Coalitions = {
@@ -2523,6 +2596,25 @@ do -- SET_UNIT
return self
end
--- [User] Add a custom condition function.
-- @function [parent=#SET_UNIT] FilterFunction
-- @param #SET_UNIT self
-- @param #function ConditionFunction If this function returns `true`, the object is added to the SET. The function needs to take a UNIT object as first argument.
-- @param ... Condition function arguments if any.
-- @return #SET_UNIT self
-- @usage
-- -- Image you want to exclude a specific UNIT from a SET:
-- local groundset = SET_UNIT:New():FilterCoalitions("blue"):FilterCategories("ground"):FilterFunction(
-- -- The function needs to take a UNIT object as first - and in this case, only - argument.
-- function(unit)
-- local isinclude = true
-- if unit:GetName() == "Exclude Me" then isinclude = false end
-- return isinclude
-- end
-- ):FilterOnce()
-- BASE:I(groundset:Flush())
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
-- @param #SET_UNIT self
@@ -2848,59 +2940,50 @@ do -- SET_UNIT
-- @return Core.Point#COORDINATE The center coordinate of all the units in the set, including heading in degrees and speed in mps in case of moving units.
function SET_UNIT:GetCoordinate()
local Coordinate = nil
local unit = self:GetRandom()
if self:Count() == 1 and unit then
return unit:GetCoordinate()
end
if unit then
local Coordinate = unit:GetCoordinate()
--self:F({Coordinate:GetVec3()})
local x1 = Coordinate.x
local x2 = Coordinate.x
local y1 = Coordinate.y
local y2 = Coordinate.y
local z1 = Coordinate.z
local z2 = Coordinate.z
local MaxVelocity = 0
local AvgHeading = nil
local MovingCount = 0
for UnitName, UnitData in pairs( self:GetAliveSet() ) do
local Unit = UnitData -- Wrapper.Unit#UNIT
local Coordinate = Unit:GetCoordinate()
x1 = (Coordinate.x < x1) and Coordinate.x or x1
x2 = (Coordinate.x > x2) and Coordinate.x or x2
y1 = (Coordinate.y < y1) and Coordinate.y or y1
y2 = (Coordinate.y > y2) and Coordinate.y or y2
z1 = (Coordinate.y < z1) and Coordinate.z or z1
z2 = (Coordinate.y > z2) and Coordinate.z or z2
local Velocity = Coordinate:GetVelocity()
if Velocity ~= 0 then
MaxVelocity = (MaxVelocity < Velocity) and Velocity or MaxVelocity
local Heading = Coordinate:GetHeading()
AvgHeading = AvgHeading and (AvgHeading + Heading) or Heading
MovingCount = MovingCount + 1
local function GetSetVec3(units)
-- Init.
local x=0
local y=0
local z=0
local n=0
-- Loop over all units.
for _,unit in pairs(units) do
local vec3=nil --DCS#Vec3
if unit and unit:IsAlive() then
vec3 = unit:GetVec3()
end
if vec3 then
-- Sum up posits.
x=x+vec3.x
y=y+vec3.y
z=z+vec3.z
-- Increase counter.
n=n+1
end
end
AvgHeading = AvgHeading and (AvgHeading / MovingCount)
Coordinate.x = (x2 - x1) / 2 + x1
Coordinate.y = (y2 - y1) / 2 + y1
Coordinate.z = (z2 - z1) / 2 + z1
Coordinate:SetHeading( AvgHeading )
Coordinate:SetVelocity( MaxVelocity )
self:F( { Coordinate = Coordinate } )
if n>0 then
-- Average.
local Vec3={x=x/n, y=y/n, z=z/n} --DCS#Vec3
return Vec3
end
return nil
end
local Coordinate = nil
local Vec3 = GetSetVec3(self.Set)
if Vec3 then
Coordinate = COORDINATE:NewFromVec3(Vec3)
end
return Coordinate
if Coordinate then
local heading = self:GetHeading() or 0
local velocity = self:GetVelocity() or 0
Coordinate:SetHeading( heading )
Coordinate:SetVelocity( velocity )
self:I(UTILS.PrintTableToLog(Coordinate))
end
return Coordinate
end
--- Get the maximum velocity of the SET_UNIT.
@@ -3109,7 +3192,7 @@ do -- SET_UNIT
MUnitInclude = MUnitInclude and MUnitActive
end
if self.Filter.Coalitions then
if self.Filter.Coalitions and MUnitInclude then
local MUnitCoalition = false
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
self:F( { "Coalition:", MUnit:GetCoalition(), self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
@@ -3120,7 +3203,7 @@ do -- SET_UNIT
MUnitInclude = MUnitInclude and MUnitCoalition
end
if self.Filter.Categories then
if self.Filter.Categories and MUnitInclude then
local MUnitCategory = false
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
self:T3( { "Category:", MUnit:GetDesc().category, self.FilterMeta.Categories[CategoryName], CategoryName } )
@@ -3131,7 +3214,7 @@ do -- SET_UNIT
MUnitInclude = MUnitInclude and MUnitCategory
end
if self.Filter.Types then
if self.Filter.Types and MUnitInclude then
local MUnitType = false
for TypeID, TypeName in pairs( self.Filter.Types ) do
self:T3( { "Type:", MUnit:GetTypeName(), TypeName } )
@@ -3142,7 +3225,7 @@ do -- SET_UNIT
MUnitInclude = MUnitInclude and MUnitType
end
if self.Filter.Countries then
if self.Filter.Countries and MUnitInclude then
local MUnitCountry = false
for CountryID, CountryName in pairs( self.Filter.Countries ) do
self:T3( { "Country:", MUnit:GetCountry(), CountryName } )
@@ -3153,7 +3236,7 @@ do -- SET_UNIT
MUnitInclude = MUnitInclude and MUnitCountry
end
if self.Filter.UnitPrefixes then
if self.Filter.UnitPrefixes and MUnitInclude then
local MUnitPrefix = false
for UnitPrefixId, UnitPrefix in pairs( self.Filter.UnitPrefixes ) do
self:T3( { "Prefix:", string.find( MUnit:GetName(), UnitPrefix, 1 ), UnitPrefix } )
@@ -3164,7 +3247,7 @@ do -- SET_UNIT
MUnitInclude = MUnitInclude and MUnitPrefix
end
if self.Filter.RadarTypes then
if self.Filter.RadarTypes and MUnitInclude then
local MUnitRadar = false
for RadarTypeID, RadarType in pairs( self.Filter.RadarTypes ) do
self:T3( { "Radar:", RadarType } )
@@ -3178,7 +3261,7 @@ do -- SET_UNIT
MUnitInclude = MUnitInclude and MUnitRadar
end
if self.Filter.SEAD then
if self.Filter.SEAD and MUnitInclude then
local MUnitSEAD = false
if MUnit:HasSEAD() == true then
self:T3( "SEAD Found" )
@@ -3188,7 +3271,7 @@ do -- SET_UNIT
end
end
if self.Filter.Zones then
if self.Filter.Zones and MUnitInclude then
local MGroupZone = false
for ZoneName, Zone in pairs( self.Filter.Zones ) do
self:T3( "Zone:", ZoneName )
@@ -3199,6 +3282,11 @@ do -- SET_UNIT
MUnitInclude = MUnitInclude and MGroupZone
end
if self.Filter.Functions and MUnitInclude then
local MUnitFunc = self:_EvalFilterFunctions(MUnit)
MUnitInclude = MUnitInclude and MUnitFunc
end
self:T2( MUnitInclude )
return MUnitInclude
end
@@ -3280,6 +3368,7 @@ do -- SET_STATIC
-- * @{#SET_STATIC.FilterPrefixes}: Builds the SET_STATIC with the units containing the same string(s) in their name. **Attention!** LUA regular expression apply here, so special characters in names like minus, dot, hash (#) etc might lead to unexpected results.
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
-- * @{#SET_STATIC.FilterZones}: Builds the SET_STATIC with the units within a @{Core.Zone#ZONE}.
-- * @{#SET_STATIC.FilterFunction}: Builds the SET_STATIC with a custom condition.
--
-- Once the filter criteria have been set for the SET_STATIC, you can start filtering using:
--
@@ -3482,7 +3571,25 @@ do -- SET_STATIC
end
return self
end
--- [User] Add a custom condition function.
-- @function [parent=#SET_STATIC] FilterFunction
-- @param #SET_STATIC self
-- @param #function ConditionFunction If this function returns `true`, the object is added to the SET. The function needs to take a STATIC object as first argument.
-- @param ... Condition function arguments if any.
-- @return #SET_STATIC self
-- @usage
-- -- Image you want to exclude a specific CLIENT from a SET:
-- local groundset = SET_STATIC:New():FilterCoalitions("blue"):FilterActive(true):FilterFunction(
-- -- The function needs to take a STATIC object as first - and in this case, only - argument.
-- function(static)
-- local isinclude = true
-- if static:GetName() == "Exclude Me" then isinclude = false end
-- return isinclude
-- end
-- ):FilterOnce()
-- BASE:I(groundset:Flush())
--- Builds a set of units of defined countries.
-- Possible current countries are those known within DCS world.
-- @param #SET_STATIC self
@@ -4039,6 +4146,7 @@ do -- SET_CLIENT
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
-- * @{#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}.
-- * @{#SET_CLIENT.FilterFunction}: Builds the SET_CLIENT with a custom condition.
--
-- Once the filter criteria have been set for the SET_CLIENT, you can start filtering using:
--
@@ -4541,6 +4649,25 @@ do -- SET_CLIENT
return AliveSet.Set or {}
end
--- [User] Add a custom condition function.
-- @function [parent=#SET_CLIENT] FilterFunction
-- @param #SET_CLIENT self
-- @param #function ConditionFunction If this function returns `true`, the object is added to the SET. The function needs to take a CLIENT object as first argument.
-- @param ... Condition function arguments if any.
-- @return #SET_CLIENT self
-- @usage
-- -- Image you want to exclude a specific CLIENT from a SET:
-- local groundset = SET_CLIENT:New():FilterCoalitions("blue"):FilterActive(true):FilterFunction(
-- -- The function needs to take a UNIT object as first - and in this case, only - argument.
-- function(client)
-- local isinclude = true
-- if client:GetPlayerName() == "Exclude Me" then isinclude = false end
-- return isinclude
-- end
-- ):FilterOnce()
-- BASE:I(groundset:Flush())
---
-- @param #SET_CLIENT self
-- @param Wrapper.Client#CLIENT MClient
@@ -4562,7 +4689,7 @@ do -- SET_CLIENT
MClientInclude = MClientInclude and MClientActive
end
if self.Filter.Coalitions then
if self.Filter.Coalitions and MClientInclude then
local MClientCoalition = false
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
local ClientCoalitionID = _DATABASE:GetCoalitionFromClientTemplate( MClientName )
@@ -4575,7 +4702,7 @@ do -- SET_CLIENT
MClientInclude = MClientInclude and MClientCoalition
end
if self.Filter.Categories then
if self.Filter.Categories and MClientInclude then
local MClientCategory = false
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
local ClientCategoryID = _DATABASE:GetCategoryFromClientTemplate( MClientName )
@@ -4588,7 +4715,7 @@ do -- SET_CLIENT
MClientInclude = MClientInclude and MClientCategory
end
if self.Filter.Types then
if self.Filter.Types and MClientInclude then
local MClientType = false
for TypeID, TypeName in pairs( self.Filter.Types ) do
self:T3( { "Type:", MClient:GetTypeName(), TypeName } )
@@ -4600,7 +4727,7 @@ do -- SET_CLIENT
MClientInclude = MClientInclude and MClientType
end
if self.Filter.Countries then
if self.Filter.Countries and MClientInclude then
local MClientCountry = false
for CountryID, CountryName in pairs( self.Filter.Countries ) do
local ClientCountryID = _DATABASE:GetCountryFromClientTemplate( MClientName )
@@ -4613,7 +4740,7 @@ do -- SET_CLIENT
MClientInclude = MClientInclude and MClientCountry
end
if self.Filter.ClientPrefixes then
if self.Filter.ClientPrefixes and MClientInclude then
local MClientPrefix = false
for ClientPrefixId, ClientPrefix in pairs( self.Filter.ClientPrefixes ) do
self:T3( { "Prefix:", string.find( MClient.UnitName, ClientPrefix, 1 ), ClientPrefix } )
@@ -4625,7 +4752,7 @@ do -- SET_CLIENT
MClientInclude = MClientInclude and MClientPrefix
end
if self.Filter.Zones then
if self.Filter.Zones and MClientInclude then
local MClientZone = false
for ZoneName, Zone in pairs( self.Filter.Zones ) do
self:T3( "Zone:", ZoneName )
@@ -4637,7 +4764,7 @@ do -- SET_CLIENT
MClientInclude = MClientInclude and MClientZone
end
if self.Filter.Playernames then
if self.Filter.Playernames and MClientInclude then
local MClientPlayername = false
local playername = MClient:GetPlayerName() or "Unknown"
--self:T(playername)
@@ -4650,7 +4777,7 @@ do -- SET_CLIENT
MClientInclude = MClientInclude and MClientPlayername
end
if self.Filter.Callsigns then
if self.Filter.Callsigns and MClientInclude then
local MClientCallsigns = false
local callsign = MClient:GetCallsign()
--self:I(callsign)
@@ -4663,6 +4790,11 @@ do -- SET_CLIENT
MClientInclude = MClientInclude and MClientCallsigns
end
if self.Filter.Functions and MClientInclude then
local MClientFunc = self:_EvalFilterFunctions(MClient)
MClientInclude = MClientInclude and MClientFunc
end
end
self:T2( MClientInclude )
return MClientInclude
@@ -5256,7 +5388,7 @@ do -- SET_AIRBASE
function SET_AIRBASE:GetRandomAirbase()
local RandomAirbase = self:GetRandom()
self:F( { RandomAirbase = RandomAirbase:GetName() } )
--self:F( { RandomAirbase = RandomAirbase:GetName() } )
return RandomAirbase
end
@@ -5422,7 +5554,7 @@ do -- SET_AIRBASE
MAirbaseInclude = MAirbaseInclude and MAirbaseCoalition
end
if self.Filter.Categories then
if self.Filter.Categories and MAirbaseInclude then
local MAirbaseCategory = false
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
local AirbaseCategoryID = _DATABASE:GetCategoryFromAirbase( MAirbaseName )
@@ -7768,7 +7900,7 @@ do -- SET_OPSGROUP
end
-- Filter coalitions.
if self.Filter.Coalitions then
if self.Filter.Coalitions and MGroupInclude then
local MGroupCoalition = false
@@ -7782,7 +7914,7 @@ do -- SET_OPSGROUP
end
-- Filter categories.
if self.Filter.Categories then
if self.Filter.Categories and MGroupInclude then
local MGroupCategory = false
@@ -7796,7 +7928,7 @@ do -- SET_OPSGROUP
end
-- Filter countries.
if self.Filter.Countries then
if self.Filter.Countries and MGroupInclude then
local MGroupCountry = false
for CountryID, CountryName in pairs( self.Filter.Countries ) do
if country.id[CountryName] == MGroup:GetCountry() then
@@ -7807,12 +7939,12 @@ do -- SET_OPSGROUP
end
-- Filter "prefixes".
if self.Filter.GroupPrefixes then
if self.Filter.GroupPrefixes and MGroupInclude then
local MGroupPrefix = false
for GroupPrefixId, GroupPrefix in pairs( self.Filter.GroupPrefixes ) do
if string.find( MGroup:GetName(), GroupPrefix:gsub ("-", "%%-"), 1 ) then --Not sure why "-" is replaced by "%-" ?!
if string.find( MGroup:GetName(), GroupPrefix:gsub ("-", "%%-"), 1 ) then --Not sure why "-" is replaced by "%-" ?! - So we can still match group names with a dash in them
MGroupPrefix = true
end
end

View File

@@ -1108,6 +1108,22 @@ function SPAWN:InitRandomizeCallsign()
return self
end
--- [BLUE AIR only!] This method sets a specific callsign for a spawned group. Use for a group with one unit only!
-- @param #SPAWN self
-- @param #number ID ID of the callsign enumerator, e.g. CALLSIGN.Tanker.Texaco - - resulting in e.g. Texaco-2-1
-- @param #string Name Name of this callsign as it cannot be determined from the ID because of the dependency on the task type of the plane, and the plane type. E.g. "Texaco"
-- @param #number Minor Minor number, i.e. the unit number within the group, e.g 2 - resulting in e.g. Texaco-2-1
-- @param #number Major Major number, i.e. the group number of this name, e.g. 1 - resulting in e.g. Texaco-2-1
-- @return #SPAWN self
function SPAWN:InitCallSign(ID,Name,Minor,Major)
self.SpawnInitCallSign = true
self.SpawnInitCallSignID = ID or 1
self.SpawnInitCallSignMinor = Minor or 1
self.SpawnInitCallSignMajor = Major or 1
self.SpawnInitCallSignName = string.lower(Name) or "enfield"
return self
end
--- This method sets a spawn position for the group that is different from the location of the template.
-- @param #SPAWN self
-- @param Core.Point#COORDINATE Coordinate The position to spawn from
@@ -3331,10 +3347,23 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) -- R2.2
end
end
if self.SpawnInitCallSign then
for UnitID = 1, #SpawnTemplate.units do
local Callsign = SpawnTemplate.units[UnitID].callsign
if Callsign and type( Callsign ) ~= "number" then
SpawnTemplate.units[UnitID].callsign[1] = self.SpawnInitCallSignID
SpawnTemplate.units[UnitID].callsign[2] = self.SpawnInitCallSignMinor
SpawnTemplate.units[UnitID].callsign[3] = self.SpawnInitCallSignMajor
SpawnTemplate.units[UnitID].callsign["name"] = string.format("%s%d%d",self.SpawnInitCallSignName,self.SpawnInitCallSignMinor,self.SpawnInitCallSignMajor)
--UTILS.PrintTableToLog(SpawnTemplate.units[UnitID].callsign,1)
end
end
end
for UnitID = 1, #SpawnTemplate.units do
local Callsign = SpawnTemplate.units[UnitID].callsign
if Callsign then
if type( Callsign ) ~= "number" then -- blue callsign
if type( Callsign ) ~= "number" and not self.SpawnInitCallSign then -- blue callsign
-- UTILS.PrintTableToLog(Callsign,1)
Callsign[2] = ((SpawnIndex - 1) % 10) + 1
local CallsignName = SpawnTemplate.units[UnitID].callsign["name"] -- #string
@@ -3342,7 +3371,7 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) -- R2.2
local CallsignLen = CallsignName:len()
SpawnTemplate.units[UnitID].callsign[2] = UnitID
SpawnTemplate.units[UnitID].callsign["name"] = CallsignName:sub( 1, CallsignLen ) .. SpawnTemplate.units[UnitID].callsign[2] .. SpawnTemplate.units[UnitID].callsign[3]
else
elseif type( Callsign ) == "number" then
SpawnTemplate.units[UnitID].callsign = Callsign + SpawnIndex
end
end
@@ -3377,11 +3406,11 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) -- R2.2
end
end
-- VoiceCallsignNumber
if SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignNumber then
if SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignNumber and type( Callsign ) ~= "number" then
SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignNumber = SpawnTemplate.units[UnitID].callsign[2] .. SpawnTemplate.units[UnitID].callsign[3]
end
-- VoiceCallsignLabel
if SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignLabel then
if SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignLabel and type( Callsign ) ~= "number" then
local CallsignName = SpawnTemplate.units[UnitID].callsign["name"] -- #string
CallsignName = string.match(CallsignName,"^(%a+)") -- 2.8 - only the part w/o numbers
local label = "NY" -- Navy One exception

File diff suppressed because it is too large Load Diff