Merge branch 'develop' into FF/Ops

This commit is contained in:
Frank 2023-08-13 18:20:23 +02:00
commit 76a36cb9f9
12 changed files with 985 additions and 204 deletions

View File

@ -2389,7 +2389,6 @@ do -- COORDINATE
end end
--- Creates a free form shape on the F10 map. The first point is the current COORDINATE. The remaining points need to be specified. --- Creates a free form shape on the F10 map. The first point is the current COORDINATE. The remaining points need to be specified.
-- **NOTE**: A free form polygon must have **at least three points** in total and currently only **up to 15 points** in total are supported.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #table Coordinates Table of coordinates of the remaining points of the shape. -- @param #table Coordinates Table of coordinates of the remaining points of the shape.
-- @param #number Coalition Coalition: All=-1, Neutral=0, Red=1, Blue=2. Default -1=All. -- @param #number Coalition Coalition: All=-1, Neutral=0, Red=1, Blue=2. Default -1=All.
@ -2463,9 +2462,30 @@ do -- COORDINATE
vecs[11], vecs[12], vecs[13], vecs[14], vecs[15], vecs[11], vecs[12], vecs[13], vecs[14], vecs[15],
Color, FillColor, LineType, ReadOnly, Text or "") Color, FillColor, LineType, ReadOnly, Text or "")
else else
self:E("ERROR: Currently a free form polygon can only have 15 points in total!")
-- Unfortunately, unpack(vecs) does not work! So no idea how to generalize this :( -- Unfortunately, unpack(vecs) does not work! So no idea how to generalize this :(
trigger.action.markupToAll(7, Coalition, MarkID, unpack(vecs), Color, FillColor, LineType, ReadOnly, Text or "") --trigger.action.markupToAll(7, Coalition, MarkID, unpack(vecs), Color, FillColor, LineType, ReadOnly, Text or "")
-- 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))
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)
end
s=s..")"
-- Execute string command
local success=UTILS.DoString(s)
if not success then
self:E("ERROR: Could not draw polygon")
env.info(s)
end
end end
return MarkID return MarkID

View File

@ -46,8 +46,9 @@
-- @image Core_Sets.JPG -- @image Core_Sets.JPG
do -- SET_BASE 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 indices. -- @field #table Index Table of indices.
@ -242,7 +243,7 @@ do -- SET_BASE
function SET_BASE:Add( ObjectName, Object ) function SET_BASE:Add( ObjectName, Object )
-- Debug info. -- Debug info.
self:T( { ObjectName = ObjectName, Object = Object } ) self:T2( { ObjectName = ObjectName, Object = Object } )
-- Ensure that the existing element is removed from the Set before a new one is inserted to the Set -- Ensure that the existing element is removed from the Set before a new one is inserted to the Set
if self.Set[ObjectName] then if self.Set[ObjectName] then
@ -257,6 +258,8 @@ do -- SET_BASE
-- Trigger Added event. -- Trigger Added event.
self:Added( ObjectName, Object ) self:Added( ObjectName, Object )
return self
end end
--- Adds a @{Core.Base#BASE} object in the @{Core.Set#SET_BASE}, using the Object Name as the index. --- Adds a @{Core.Base#BASE} object in the @{Core.Set#SET_BASE}, using the Object Name as the index.
@ -578,8 +581,8 @@ do -- SET_BASE
end end
----- Private method that registers all alive players in the mission. ----- Private method that registers all alive players in the mission.
---- @param #SET_BASE self -- @param #SET_BASE self
---- @return #SET_BASE self -- @return #SET_BASE self
-- function SET_BASE:_RegisterPlayers() -- function SET_BASE:_RegisterPlayers()
-- --
-- local CoalitionsData = { AlivePlayersRed = coalition.getPlayers( coalition.side.RED ), AlivePlayersBlue = coalition.getPlayers( coalition.side.BLUE ) } -- local CoalitionsData = { AlivePlayersRed = coalition.getPlayers( coalition.side.RED ), AlivePlayersBlue = coalition.getPlayers( coalition.side.BLUE ) }
@ -796,8 +799,8 @@ do -- SET_BASE
----- Iterate the SET_BASE and call an iterator 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
-- function SET_BASE:ForEachDCSUnitAlive( IteratorFunction, ... ) -- function SET_BASE:ForEachDCSUnitAlive( IteratorFunction, ... )
-- self:F3( arg ) -- self:F3( arg )
@ -808,8 +811,8 @@ do -- SET_BASE
-- end -- end
-- --
----- Iterate the SET_BASE and call an iterator 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
-- function SET_BASE:ForEachPlayer( IteratorFunction, ... ) -- function SET_BASE:ForEachPlayer( IteratorFunction, ... )
-- self:F3( arg ) -- self:F3( arg )
@ -821,8 +824,8 @@ do -- SET_BASE
-- --
-- --
----- Iterate the SET_BASE and call an iterator 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
-- function SET_BASE:ForEachClient( IteratorFunction, ... ) -- function SET_BASE:ForEachClient( IteratorFunction, ... )
-- self:F3( arg ) -- self:F3( arg )
@ -901,9 +904,12 @@ do -- SET_BASE
end end
do -- SET_GROUP do
--- @type SET_GROUP #SET_GROUP -- SET_GROUP
---
-- @type SET_GROUP #SET_GROUP
-- @field Core.Timer#TIMER ZoneTimer -- @field Core.Timer#TIMER ZoneTimer
-- @field #number ZoneTimerInterval -- @field #number ZoneTimerInterval
-- @extends Core.Set#SET_BASE -- @extends Core.Set#SET_BASE
@ -1568,7 +1574,7 @@ do -- SET_GROUP
self:F2( arg ) self:F2( arg )
self:ForEach( IteratorFunction, arg, self:GetSet(), self:ForEach( IteratorFunction, arg, self:GetSet(),
--- @param Core.Zone#ZONE_BASE ZoneObject -- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Group#GROUP GroupObject -- @param Wrapper.Group#GROUP GroupObject
function( ZoneObject, GroupObject ) function( ZoneObject, GroupObject )
if GroupObject:IsCompletelyInZone( ZoneObject ) then if GroupObject:IsCompletelyInZone( ZoneObject ) then
@ -1590,7 +1596,7 @@ do -- SET_GROUP
self:F2( arg ) self:F2( arg )
self:ForEach( IteratorFunction, arg, self:GetSet(), self:ForEach( IteratorFunction, arg, self:GetSet(),
--- @param Core.Zone#ZONE_BASE ZoneObject -- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Group#GROUP GroupObject -- @param Wrapper.Group#GROUP GroupObject
function( ZoneObject, GroupObject ) function( ZoneObject, GroupObject )
if GroupObject:IsPartlyInZone( ZoneObject ) then if GroupObject:IsPartlyInZone( ZoneObject ) then
@ -1612,7 +1618,7 @@ do -- SET_GROUP
self:F2( arg ) self:F2( arg )
self:ForEach( IteratorFunction, arg, self:GetSet(), self:ForEach( IteratorFunction, arg, self:GetSet(),
--- @param Core.Zone#ZONE_BASE ZoneObject -- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Group#GROUP GroupObject -- @param Wrapper.Group#GROUP GroupObject
function( ZoneObject, GroupObject ) function( ZoneObject, GroupObject )
if GroupObject:IsNotInZone( ZoneObject ) then if GroupObject:IsNotInZone( ZoneObject ) then
@ -1659,7 +1665,7 @@ do -- SET_GROUP
self:F2( arg ) self:F2( arg )
self:ForEach( IteratorFunction, arg, self:GetSet(), self:ForEach( IteratorFunction, arg, self:GetSet(),
--- @param Core.Zone#ZONE_BASE ZoneObject -- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Group#GROUP GroupObject -- @param Wrapper.Group#GROUP GroupObject
function( ZoneObject, GroupObject ) function( ZoneObject, GroupObject )
if GroupObject:IsAnyInZone( ZoneObject ) then if GroupObject:IsAnyInZone( ZoneObject ) then
@ -1857,8 +1863,8 @@ do -- SET_GROUP
end end
----- Iterate the SET_GROUP and call an iterator 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
-- function SET_GROUP:ForEachPlayer( IteratorFunction, ... ) -- function SET_GROUP:ForEachPlayer( IteratorFunction, ... )
-- self:F2( arg ) -- self:F2( arg )
@ -1870,8 +1876,8 @@ do -- SET_GROUP
-- --
-- --
----- Iterate the SET_GROUP and call an iterator 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
-- function SET_GROUP:ForEachClient( IteratorFunction, ... ) -- function SET_GROUP:ForEachClient( IteratorFunction, ... )
-- self:F2( arg ) -- self:F2( arg )
@ -1945,7 +1951,7 @@ do -- SET_GROUP
if self.Filter.Zones then if self.Filter.Zones then
local MGroupZone = false local MGroupZone = false
for ZoneName, Zone in pairs( self.Filter.Zones ) do for ZoneName, Zone in pairs( self.Filter.Zones ) do
--self:I( "Zone:", ZoneName ) --self:T( "Zone:", ZoneName )
if MGroup:IsInZone(Zone) then if MGroup:IsInZone(Zone) then
MGroupZone = true MGroupZone = true
end end
@ -2011,8 +2017,9 @@ do -- SET_GROUP
end end
do -- SET_UNIT do -- SET_UNIT
--- @type SET_UNIT ---
-- @type SET_UNIT
-- @field Core.Timer#TIMER ZoneTimer -- @field Core.Timer#TIMER ZoneTimer
-- @field #number ZoneTimerInterval -- @field #number ZoneTimerInterval
-- @extends Core.Set#SET_BASE -- @extends Core.Set#SET_BASE
@ -2672,7 +2679,7 @@ do -- SET_UNIT
self:F2( arg ) self:F2( arg )
self:ForEach( IteratorFunction, arg, self:GetSet(), self:ForEach( IteratorFunction, arg, self:GetSet(),
--- @param Core.Zone#ZONE_BASE ZoneObject -- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Unit#UNIT UnitObject -- @param Wrapper.Unit#UNIT UnitObject
function( ZoneObject, UnitObject ) function( ZoneObject, UnitObject )
if UnitObject:IsInZone( ZoneObject ) then if UnitObject:IsInZone( ZoneObject ) then
@ -2694,7 +2701,7 @@ do -- SET_UNIT
self:F2( arg ) self:F2( arg )
self:ForEach( IteratorFunction, arg, self:GetSet(), self:ForEach( IteratorFunction, arg, self:GetSet(),
--- @param Core.Zone#ZONE_BASE ZoneObject -- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Unit#UNIT UnitObject -- @param Wrapper.Unit#UNIT UnitObject
function( ZoneObject, UnitObject ) function( ZoneObject, UnitObject )
if UnitObject:IsNotInZone( ZoneObject ) then if UnitObject:IsNotInZone( ZoneObject ) then
@ -3011,8 +3018,8 @@ do -- SET_UNIT
----- Iterate the SET_UNIT and call an iterator 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
-- function SET_UNIT:ForEachPlayer( IteratorFunction, ... ) -- function SET_UNIT:ForEachPlayer( IteratorFunction, ... )
-- self:F2( arg ) -- self:F2( arg )
@ -3024,8 +3031,8 @@ do -- SET_UNIT
-- --
-- --
----- Iterate the SET_UNIT and call an iterator 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
-- function SET_UNIT:ForEachClient( IteratorFunction, ... ) -- function SET_UNIT:ForEachClient( IteratorFunction, ... )
-- self:F2( arg ) -- self:F2( arg )
@ -3040,7 +3047,7 @@ do -- SET_UNIT
-- @param Wrapper.Unit#UNIT MUnit -- @param Wrapper.Unit#UNIT MUnit
-- @return #SET_UNIT self -- @return #SET_UNIT self
function SET_UNIT:IsIncludeObject( MUnit ) function SET_UNIT:IsIncludeObject( MUnit )
self:F2( MUnit ) self:F2( {MUnit} )
local MUnitInclude = false local MUnitInclude = false
@ -3191,8 +3198,9 @@ do -- SET_UNIT
end end
do -- SET_STATIC do -- SET_STATIC
--- @type SET_STATIC ---
-- @type SET_STATIC
-- @extends Core.Set#SET_BASE -- @extends Core.Set#SET_BASE
--- Mission designers can use the SET_STATIC class to build sets of Statics belonging to certain: --- Mission designers can use the SET_STATIC class to build sets of Statics belonging to certain:
@ -3612,7 +3620,7 @@ do -- SET_STATIC
self:F2( arg ) self:F2( arg )
self:ForEach( IteratorFunction, arg, self:GetSet(), self:ForEach( IteratorFunction, arg, self:GetSet(),
--- @param Core.Zone#ZONE_BASE ZoneObject -- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Static#STATIC StaticObject -- @param Wrapper.Static#STATIC StaticObject
function( ZoneObject, StaticObject ) function( ZoneObject, StaticObject )
if StaticObject:IsInZone( ZoneObject ) then if StaticObject:IsInZone( ZoneObject ) then
@ -3634,7 +3642,7 @@ do -- SET_STATIC
self:F2( arg ) self:F2( arg )
self:ForEach( IteratorFunction, arg, self:GetSet(), self:ForEach( IteratorFunction, arg, self:GetSet(),
--- @param Core.Zone#ZONE_BASE ZoneObject -- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Static#STATIC StaticObject -- @param Wrapper.Static#STATIC StaticObject
function( ZoneObject, StaticObject ) function( ZoneObject, StaticObject )
if StaticObject:IsNotInZone( ZoneObject ) then if StaticObject:IsNotInZone( ZoneObject ) then
@ -3945,8 +3953,9 @@ do -- SET_STATIC
end end
do -- SET_CLIENT do -- SET_CLIENT
--- @type SET_CLIENT ---
-- @type SET_CLIENT
-- @field Core.Timer#TIMER ZoneTimer -- @field Core.Timer#TIMER ZoneTimer
-- @field #number ZoneTimerInterval -- @field #number ZoneTimerInterval
-- @extends Core.Set#SET_BASE -- @extends Core.Set#SET_BASE
@ -4008,8 +4017,8 @@ do -- SET_CLIENT
Countries = nil, Countries = nil,
ClientPrefixes = nil, ClientPrefixes = nil,
Zones = nil, Zones = nil,
Playernames = nil, Playernames = nil,
Callsigns = nil, Callsigns = nil,
}, },
FilterMeta = { FilterMeta = {
Coalitions = { Coalitions = {
@ -4059,7 +4068,7 @@ do -- SET_CLIENT
--- Remove CLIENT(s) from SET_CLIENT. --- Remove CLIENT(s) from SET_CLIENT.
-- @param Core.Set#SET_CLIENT self -- @param Core.Set#SET_CLIENT self
-- @param Wrapper.Client#CLIENT RemoveClientNames A single name or an array of CLIENT names. -- @param Wrapper.Client#CLIENT RemoveClientNames A single object or an array of CLIENT objects.
-- @return self -- @return self
function SET_CLIENT:RemoveClientsByName( RemoveClientNames ) function SET_CLIENT:RemoveClientsByName( RemoveClientNames )
@ -4369,7 +4378,7 @@ do -- SET_CLIENT
self:F2( arg ) self:F2( arg )
self:ForEach( IteratorFunction, arg, self:GetSet(), self:ForEach( IteratorFunction, arg, self:GetSet(),
--- @param Core.Zone#ZONE_BASE ZoneObject -- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Client#CLIENT ClientObject -- @param Wrapper.Client#CLIENT ClientObject
function( ZoneObject, ClientObject ) function( ZoneObject, ClientObject )
if ClientObject:IsInZone( ZoneObject ) then if ClientObject:IsInZone( ZoneObject ) then
@ -4391,7 +4400,7 @@ do -- SET_CLIENT
self:F2( arg ) self:F2( arg )
self:ForEach( IteratorFunction, arg, self:GetSet(), self:ForEach( IteratorFunction, arg, self:GetSet(),
--- @param Core.Zone#ZONE_BASE ZoneObject -- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Client#CLIENT ClientObject -- @param Wrapper.Client#CLIENT ClientObject
function( ZoneObject, ClientObject ) function( ZoneObject, ClientObject )
if ClientObject:IsNotInZone( ZoneObject ) then if ClientObject:IsNotInZone( ZoneObject ) then
@ -4459,7 +4468,7 @@ do -- SET_CLIENT
if self.Filter.Active == false or (self.Filter.Active == true and MClient:IsActive() == true and MClient:IsAlive() == true) then if self.Filter.Active == false or (self.Filter.Active == true and MClient:IsActive() == true and MClient:IsAlive() == true) then
MClientActive = true MClientActive = true
end end
--self:I( { "Evaluated Active", MClientActive } ) --self:T( { "Evaluated Active", MClientActive } )
MClientInclude = MClientInclude and MClientActive MClientInclude = MClientInclude and MClientActive
end end
@ -4526,45 +4535,45 @@ do -- SET_CLIENT
MClientInclude = MClientInclude and MClientPrefix MClientInclude = MClientInclude and MClientPrefix
end end
if self.Filter.Zones then if self.Filter.Zones then
local MClientZone = false local MClientZone = false
for ZoneName, Zone in pairs( self.Filter.Zones ) do for ZoneName, Zone in pairs( self.Filter.Zones ) do
self:T3( "Zone:", ZoneName ) self:T3( "Zone:", ZoneName )
local unit = MClient:GetClientGroupUnit() local unit = MClient:GetClientGroupUnit()
if unit and unit:IsInZone(Zone) then if unit and unit:IsInZone(Zone) then
MClientZone = true MClientZone = true
end end
end end
MClientInclude = MClientInclude and MClientZone MClientInclude = MClientInclude and MClientZone
end end
if self.Filter.Playernames then if self.Filter.Playernames then
local MClientPlayername = false local MClientPlayername = false
local playername = MClient:GetPlayerName() or "Unknown" local playername = MClient:GetPlayerName() or "Unknown"
--self:I(playername) --self:T(playername)
for _,_Playername in pairs(self.Filter.Playernames) do for _,_Playername in pairs(self.Filter.Playernames) do
if playername and string.find(playername,_Playername) then if playername and string.find(playername,_Playername) then
MClientPlayername = true MClientPlayername = true
end end
end end
self:T( { "Evaluated Playername", MClientPlayername } ) self:T( { "Evaluated Playername", MClientPlayername } )
MClientInclude = MClientInclude and MClientPlayername MClientInclude = MClientInclude and MClientPlayername
end end
if self.Filter.Callsigns then if self.Filter.Callsigns then
local MClientCallsigns = false local MClientCallsigns = false
local callsign = MClient:GetCallsign() local callsign = MClient:GetCallsign()
--self:I(callsign) --self:T(callsign)
for _,_Callsign in pairs(self.Filter.Callsigns) do for _,_Callsign in pairs(self.Filter.Callsigns) do
if callsign and string.find(callsign,_Callsign) then if callsign and string.find(callsign,_Callsign) then
MClientCallsigns = true MClientCallsigns = true
end end
end end
self:T( { "Evaluated Callsign", MClientCallsigns } ) self:T( { "Evaluated Callsign", MClientCallsigns } )
MClientInclude = MClientInclude and MClientCallsigns MClientInclude = MClientInclude and MClientCallsigns
end end
end end
self:T2( MClientInclude ) self:T2( MClientInclude )
return MClientInclude return MClientInclude
end end
@ -4573,7 +4582,8 @@ end
do -- SET_PLAYER do -- SET_PLAYER
--- @type SET_PLAYER ---
-- @type SET_PLAYER
-- @extends Core.Set#SET_BASE -- @extends Core.Set#SET_BASE
--- Mission designers can use the @{Core.Set#SET_PLAYER} class to build sets of units belonging to alive players: --- Mission designers can use the @{Core.Set#SET_PLAYER} class to build sets of units belonging to alive players:
@ -4868,7 +4878,7 @@ do -- SET_PLAYER
self:F2( arg ) self:F2( arg )
self:ForEach( IteratorFunction, arg, self:GetSet(), self:ForEach( IteratorFunction, arg, self:GetSet(),
--- @param Core.Zone#ZONE_BASE ZoneObject -- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Client#CLIENT ClientObject -- @param Wrapper.Client#CLIENT ClientObject
function( ZoneObject, ClientObject ) function( ZoneObject, ClientObject )
if ClientObject:IsInZone( ZoneObject ) then if ClientObject:IsInZone( ZoneObject ) then
@ -4890,7 +4900,7 @@ do -- SET_PLAYER
self:F2( arg ) self:F2( arg )
self:ForEach( IteratorFunction, arg, self:GetSet(), self:ForEach( IteratorFunction, arg, self:GetSet(),
--- @param Core.Zone#ZONE_BASE ZoneObject -- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Client#CLIENT ClientObject -- @param Wrapper.Client#CLIENT ClientObject
function( ZoneObject, ClientObject ) function( ZoneObject, ClientObject )
if ClientObject:IsNotInZone( ZoneObject ) then if ClientObject:IsNotInZone( ZoneObject ) then
@ -4998,8 +5008,9 @@ do -- SET_PLAYER
end end
do -- SET_AIRBASE do -- SET_AIRBASE
--- @type SET_AIRBASE ---
-- @type SET_AIRBASE
-- @extends Core.Set#SET_BASE -- @extends Core.Set#SET_BASE
--- Mission designers can use the @{Core.Set#SET_AIRBASE} class to build sets of airbases optionally belonging to certain: --- Mission designers can use the @{Core.Set#SET_AIRBASE} class to build sets of airbases optionally belonging to certain:
@ -5341,8 +5352,9 @@ do -- SET_AIRBASE
end end
do -- SET_CARGO do -- SET_CARGO
--- @type SET_CARGO ---
-- @type SET_CARGO
-- @extends Core.Set#SET_BASE -- @extends Core.Set#SET_BASE
--- Mission designers can use the @{Core.Set#SET_CARGO} class to build sets of cargos optionally belonging to certain: --- Mission designers can use the @{Core.Set#SET_CARGO} class to build sets of cargos optionally belonging to certain:
@ -5767,8 +5779,9 @@ do -- SET_CARGO
end end
do -- SET_ZONE do -- SET_ZONE
--- @type SET_ZONE ---
-- @type SET_ZONE
-- @extends Core.Set#SET_BASE -- @extends Core.Set#SET_BASE
--- Mission designers can use the @{Core.Set#SET_ZONE} class to build sets of zones of various types. --- Mission designers can use the @{Core.Set#SET_ZONE} class to build sets of zones of various types.
@ -6135,8 +6148,9 @@ do -- SET_ZONE
end end
do -- SET_ZONE_GOAL do -- SET_ZONE_GOAL
--- @type SET_ZONE_GOAL ---
-- @type SET_ZONE_GOAL
-- @extends Core.Set#SET_BASE -- @extends Core.Set#SET_BASE
--- Mission designers can use the @{Core.Set#SET_ZONE_GOAL} class to build sets of zones of various types. --- Mission designers can use the @{Core.Set#SET_ZONE_GOAL} class to build sets of zones of various types.
@ -6446,8 +6460,9 @@ do -- SET_ZONE_GOAL
end end
do -- SET_OPSZONE do -- SET_OPSZONE
--- @type SET_OPSZONE ---
-- @type SET_OPSZONE
-- @extends Core.Set#SET_BASE -- @extends Core.Set#SET_BASE
--- Mission designers can use the @{Core.Set#SET_OPSZONE} class to build sets of zones of various types. --- Mission designers can use the @{Core.Set#SET_OPSZONE} class to build sets of zones of various types.
@ -6903,8 +6918,9 @@ end
do -- SET_OPSGROUP do -- SET_OPSGROUP
--- @type SET_OPSGROUP ---
-- @type SET_OPSGROUP
-- @extends Core.Set#SET_BASE -- @extends Core.Set#SET_BASE
--- Mission designers can use the @{Core.Set#SET_OPSGROUP} class to build sets of OPS groups belonging to certain: --- Mission designers can use the @{Core.Set#SET_OPSGROUP} class to build sets of OPS groups belonging to certain:
@ -7571,6 +7587,7 @@ do -- SET_SCENERY
Scenerys = {}, Scenerys = {},
Filter = { Filter = {
SceneryPrefixes = nil, SceneryPrefixes = nil,
SceneryRoles = nil,
Zones = nil, Zones = nil,
}, },
} }
@ -7593,7 +7610,7 @@ do -- SET_SCENERY
if ZoneSet then if ZoneSet then
for _,_zone in pairs(ZoneSet.Set) do for _,_zone in pairs(ZoneSet.Set) do
self:T("Zone type handed: "..tostring(_zone.ClassName)) self:T("Zone type handed: "..tostring(_zone.ClassName))
table.insert(zonenames,_zone:GetName()) table.insert(zonenames,_zone:GetName())
end end
self:AddSceneryByName(zonenames) self:AddSceneryByName(zonenames)
@ -7617,7 +7634,7 @@ do -- SET_SCENERY
--- Add SCENERY(s) to SET_SCENERY. --- Add SCENERY(s) to SET_SCENERY.
-- @param #SET_SCENERY self -- @param #SET_SCENERY self
-- @param #string AddScenery A single SCENERY. -- @param Wrapper.Scenery#SCENERY AddScenery A single SCENERY object.
-- @return #SET_SCENERY self -- @return #SET_SCENERY self
function SET_SCENERY:AddScenery( AddScenery ) function SET_SCENERY:AddScenery( AddScenery )
self:F2( AddScenery:GetName() ) self:F2( AddScenery:GetName() )
@ -7687,6 +7704,7 @@ do -- SET_SCENERY
end end
for _,Zone in pairs( zones ) do for _,Zone in pairs( zones ) do
local zonename = Zone:GetName() local zonename = Zone:GetName()
self:T(zonename)
self.Filter.Zones[zonename] = Zone self.Filter.Zones[zonename] = Zone
end end
return self return self
@ -7705,11 +7723,30 @@ do -- SET_SCENERY
Prefixes = { Prefixes } Prefixes = { Prefixes }
end end
for PrefixID, Prefix in pairs( Prefixes ) do for PrefixID, Prefix in pairs( Prefixes ) do
--self:T(Prefix)
self.Filter.SceneryPrefixes[Prefix] = Prefix self.Filter.SceneryPrefixes[Prefix] = Prefix
end end
return self return self
end end
--- Builds a set of SCENERYs that **contain** an exact match of the "ROLE" property.
-- @param #SET_SCENERY self
-- @param #string Role The string pattern(s) that needs to exactly match the scenery "ROLE" property from the ME quad-zone properties. Can also be passed as a `#table` of strings.
-- @return #SET_SCENERY self
function SET_SCENERY:FilterRoles( Role )
if not self.Filter.SceneryRoles then
self.Filter.SceneryRoles = {}
end
if type( Role ) ~= "table" then
Role = { Role }
end
for PrefixID, Prefix in pairs( Role ) do
--self:T(Prefix)
self.Filter.SceneryRoles[Prefix] = Prefix
end
return self
end
--- Iterate the SET_SCENERY and count how many SCENERYSs are alive. --- Iterate the SET_SCENERY and count how many SCENERYSs are alive.
-- @param #SET_SCENERY self -- @param #SET_SCENERY self
-- @return #number The number of SCENERYSs alive. -- @return #number The number of SCENERYSs alive.
@ -7802,10 +7839,76 @@ do -- SET_SCENERY
-- @param Wrapper.Scenery#SCENERY MScenery -- @param Wrapper.Scenery#SCENERY MScenery
-- @return #SET_SCENERY self -- @return #SET_SCENERY self
function SET_SCENERY:IsIncludeObject( MScenery ) function SET_SCENERY:IsIncludeObject( MScenery )
self:F2( MScenery ) self:T( MScenery.SceneryName )
return true
local MSceneryInclude = true
if MScenery then
local MSceneryName = MScenery:GetName()
-- Filter Prefixes
if self.Filter.Prefixes then
local MSceneryPrefix = false
for ZonePrefixId, ZonePrefix in pairs( self.Filter.Prefixes ) do
self:T( { "Prefix:", string.find( MSceneryName, ZonePrefix, 1 ), ZonePrefix } )
if string.find( MSceneryName, ZonePrefix, 1 ) then
MSceneryPrefix = true
end
end
self:T( { "Evaluated Prefix", MSceneryPrefix } )
MSceneryInclude = MSceneryInclude and MSceneryPrefix
end
if self.Filter.Zones then
local MSceneryZone = false
for ZoneName, Zone in pairs( self.Filter.Zones ) do
--self:T( "Zone:", ZoneName )
local coord = MScenery:GetCoordinate()
if coord and Zone:IsCoordinateInZone(coord) then
MSceneryZone = true
end
self:T( { "Evaluated Zone", MSceneryZone } )
end
MSceneryInclude = MSceneryInclude and MSceneryZone
end
-- Filter Roles
if self.Filter.SceneryRoles then
local MSceneryRole = false
local Role = MScenery:GetProperty("ROLE") or "none"
for ZoneRoleId, ZoneRole in pairs( self.Filter.SceneryRoles ) do
self:T( { "Role:", ZoneRole, Role } )
if ZoneRole == Role then
MSceneryRole = true
end
end
self:T( { "Evaluated Role ", MSceneryRole } )
MSceneryInclude = MSceneryInclude and MSceneryRole
end
end
self:T2( MSceneryInclude )
return MSceneryInclude
end end
--- Filters for the defined collection.
-- @param #SET_SCENERY self
-- @return #SET_SCENERY self
function SET_SCENERY:FilterOnce()
for ObjectName, Object in pairs( self:GetSet() ) do
self:T(ObjectName)
if self:IsIncludeObject( Object ) then
self:Add( ObjectName, Object )
else
self:Remove(ObjectName, true)
end
end
return self --FilteredSet
end
--- Count overall initial (Life0) lifepoints of the SET objects. --- Count overall initial (Life0) lifepoints of the SET objects.
-- @param #SET_SCENERY self -- @param #SET_SCENERY self
-- @return #number LIfe0Points -- @return #number LIfe0Points
@ -7843,7 +7946,7 @@ do -- SET_SCENERY
function SET_SCENERY:GetRelativeLife() function SET_SCENERY:GetRelativeLife()
local life = self:GetLife() local life = self:GetLife()
local life0 = self:GetLife0() local life0 = self:GetLife0()
self:T3(string.format("Set Lifepoints: %d life0 | %d life",life0,life)) self:T2(string.format("Set Lifepoints: %d life0 | %d life",life0,life))
local rlife = math.floor((life / life0) * 100) local rlife = math.floor((life / life0) * 100)
return rlife return rlife
end end

View File

@ -1420,7 +1420,7 @@ function SCORING:ReportDetailedPlayerHits( PlayerName )
Penalty = Penalty + UnitData.Penalty Penalty = Penalty + UnitData.Penalty
PenaltyHit = UnitData.PenaltyHit PenaltyHit = UnitData.PenaltyHit
end end
local ScoreMessageHit = string.format( "%s:%d ", CategoryName, Score - Penalty ) local ScoreMessageHit = string.format( "%s: %d ", CategoryName, Score - Penalty )
self:T( ScoreMessageHit ) self:T( ScoreMessageHit )
ScoreMessageHits = ScoreMessageHits .. ScoreMessageHit ScoreMessageHits = ScoreMessageHits .. ScoreMessageHit
PlayerScore = PlayerScore + Score PlayerScore = PlayerScore + Score
@ -1476,7 +1476,7 @@ function SCORING:ReportDetailedPlayerDestroys( PlayerName )
end end
end end
local ScoreMessageDestroy = string.format( " %s:%d ", CategoryName, Score - Penalty ) local ScoreMessageDestroy = string.format( " %s: %d ", CategoryName, Score - Penalty )
self:T( ScoreMessageDestroy ) self:T( ScoreMessageDestroy )
ScoreMessageDestroys = ScoreMessageDestroys .. ScoreMessageDestroy ScoreMessageDestroys = ScoreMessageDestroys .. ScoreMessageDestroy

View File

@ -1735,10 +1735,10 @@ AIRBOSS.Difficulty = {
-- @field #table trapsheet Groove data table recorded every 0.5 seconds. -- @field #table trapsheet Groove data table recorded every 0.5 seconds.
-- @field #boolean trapon If true, save trap sheets. -- @field #boolean trapon If true, save trap sheets.
-- @field #string debriefschedulerID Debrief scheduler ID. -- @field #string debriefschedulerID Debrief scheduler ID.
-- --
-- @field Sound.SRS#MSRS SRS -- @field Sound.SRS#MSRS SRS
-- @field Sound.SRS#MSRSQUEUE SRSQ -- @field Sound.SRS#MSRSQUEUE SRSQ
-- --
-- @extends #AIRBOSS.FlightGroup -- @extends #AIRBOSS.FlightGroup
--- Main group level radio menu: F10 Other/Airboss. --- Main group level radio menu: F10 Other/Airboss.
@ -3058,7 +3058,7 @@ end
-- @param #number Port Port of the SRS server, defaults to 5002. -- @param #number Port Port of the SRS server, defaults to 5002.
-- @param #string Culture (Optional, Airboss Culture) Culture, defaults to "en-US". -- @param #string Culture (Optional, Airboss Culture) Culture, defaults to "en-US".
-- @param #string Gender (Optional, Airboss Gender) Gender, e.g. "male" or "female". Defaults to "male". -- @param #string Gender (Optional, Airboss Gender) Gender, e.g. "male" or "female". Defaults to "male".
-- @param #string Voice (Optional, Airboss Voice) Set to use a specific voice. Will **override gender and culture** settings. -- @param #string Voice (Optional, Airboss Voice) Set to use a specific voice. Will **override gender and culture** settings.
-- @param #string GoogleCreds (Optional) Path to Google credentials, e.g. "C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourgooglekey.json". -- @param #string GoogleCreds (Optional) Path to Google credentials, e.g. "C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourgooglekey.json".
-- @param #number Volume (Optional) E.g. 0.75. Defaults to 1.0 (loudest). -- @param #number Volume (Optional) E.g. 0.75. Defaults to 1.0 (loudest).
-- @param #table AltBackend (Optional) See MSRS for details. -- @param #table AltBackend (Optional) See MSRS for details.
@ -3087,10 +3087,10 @@ function AIRBOSS:EnableSRS(PathToSRS,Port,Culture,Gender,Voice,GoogleCreds,Volum
-- SRSQUEUE -- SRSQUEUE
self.SRSQ = MSRSQUEUE:New("AIRBOSS") self.SRSQ = MSRSQUEUE:New("AIRBOSS")
self.SRSQ:SetTransmitOnlyWithPlayers(true) self.SRSQ:SetTransmitOnlyWithPlayers(true)
if not self.PilotRadio then if not self.PilotRadio then
self:SetSRSPilotVoice() self:SetSRSPilotVoice()
end end
return self return self
end end
--- Set LSO radio frequency and modulation. Default frequency is 264 MHz AM. --- Set LSO radio frequency and modulation. Default frequency is 264 MHz AM.
@ -5924,9 +5924,11 @@ function AIRBOSS:_ScanCarrierZone()
-- Get aircraft type name. -- Get aircraft type name.
local actype = group:GetTypeName() local actype = group:GetTypeName()
-- Create a new flight group
if knownflight then if knownflight then
-- Debug output.
self:T2(self.lid..string.format("Known flight group %s of type %s in CCA.", groupname, actype))
-- Check if flight is AI and if we want to handle it at all. -- Check if flight is AI and if we want to handle it at all.
if knownflight.ai and knownflight.flag == -100 and self.handleai then if knownflight.ai and knownflight.flag == -100 and self.handleai then
@ -5943,9 +5945,10 @@ function AIRBOSS:_ScanCarrierZone()
flight.airboss = self flight.airboss = self
end end
-- Send AI flight to marshal stack. -- Send AI flight to marshal stack if group closes in more than 5 and has initial flag value.
if putintomarshal then if putintomarshal then
-- Get the next free stack for current recovery case. -- Get the next free stack for current recovery case.
local stack = self:_GetFreeStack( knownflight.ai ) local stack = self:_GetFreeStack( knownflight.ai )
@ -11553,7 +11556,7 @@ function AIRBOSS:GetHeadingIntoWind( magnetic, coord )
local function adjustDegreesForWindSpeed(windSpeed) local function adjustDegreesForWindSpeed(windSpeed)
local degreesAdjustment = 0 local degreesAdjustment = 0
-- the windspeeds are in m/s -- the windspeeds are in m/s
-- +0 degrees at 15m/s = 37kts -- +0 degrees at 15m/s = 37kts
-- +0 degrees at 14m/s = 35kts -- +0 degrees at 14m/s = 35kts
-- +0 degrees at 13m/s = 33kts -- +0 degrees at 13m/s = 33kts
@ -11568,7 +11571,7 @@ function AIRBOSS:GetHeadingIntoWind( magnetic, coord )
-- +20 degrees at 4m/s = 26kts -- +20 degrees at 4m/s = 26kts
-- +20 degrees at 3m/s = 26kts -- +20 degrees at 3m/s = 26kts
-- +30 degrees at 2m/s = 26kts 1s -- +30 degrees at 2m/s = 26kts 1s
if windSpeed > 0 and windSpeed < 3 then if windSpeed > 0 and windSpeed < 3 then
degreesAdjustment = 30 degreesAdjustment = 30
elseif windSpeed >= 3 and windSpeed < 5 then elseif windSpeed >= 3 and windSpeed < 5 then
@ -11580,17 +11583,17 @@ function AIRBOSS:GetHeadingIntoWind( magnetic, coord )
elseif windSpeed >= 13 then elseif windSpeed >= 13 then
degreesAdjustment = 0 degreesAdjustment = 0
end end
return degreesAdjustment return degreesAdjustment
end end
-- Get direction the wind is blowing from. This is where we want to go. -- Get direction the wind is blowing from. This is where we want to go.
local windfrom, vwind = self:GetWind( nil, nil, coord ) local windfrom, vwind = self:GetWind( nil, nil, coord )
--self:I("windfrom="..windfrom.." vwind="..vwind) --self:I("windfrom="..windfrom.." vwind="..vwind)
vwind = vwind + adjustDegreesForWindSpeed(vwind) vwind = vwind + adjustDegreesForWindSpeed(vwind)
--self:I("windfrom="..windfrom.." (c)vwind="..vwind) --self:I("windfrom="..windfrom.." (c)vwind="..vwind)
-- Actually, we want the runway in the wind. -- Actually, we want the runway in the wind.
@ -14730,12 +14733,12 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
if radio == nil or call == nil then if radio == nil or call == nil then
return return
end end
if not self.SRS then if not self.SRS then
-- Create a new radio transmission item. -- Create a new radio transmission item.
local transmission = {} -- #AIRBOSS.Radioitem local transmission = {} -- #AIRBOSS.Radioitem
transmission.radio = radio transmission.radio = radio
transmission.call = call transmission.call = call
transmission.Tplay = timer.getAbsTime() + (delay or 0) transmission.Tplay = timer.getAbsTime() + (delay or 0)
@ -14743,58 +14746,58 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
transmission.isplaying = false transmission.isplaying = false
transmission.Tstarted = nil transmission.Tstarted = nil
transmission.loud = loud and call.loud transmission.loud = loud and call.loud
-- Player onboard number if sender has one. -- Player onboard number if sender has one.
if self:_IsOnboard( call.modexsender ) then if self:_IsOnboard( call.modexsender ) then
self:_Number2Radio( radio, call.modexsender, delay, 0.3, pilotcall ) self:_Number2Radio( radio, call.modexsender, delay, 0.3, pilotcall )
end end
-- Play onboard number if receiver has one. -- Play onboard number if receiver has one.
if self:_IsOnboard( call.modexreceiver ) then if self:_IsOnboard( call.modexreceiver ) then
self:_Number2Radio( radio, call.modexreceiver, delay, 0.3, pilotcall ) self:_Number2Radio( radio, call.modexreceiver, delay, 0.3, pilotcall )
end end
-- Add transmission to the right queue. -- Add transmission to the right queue.
local caller = "" local caller = ""
if radio.alias == "LSO" then if radio.alias == "LSO" then
table.insert( self.RQLSO, transmission ) table.insert( self.RQLSO, transmission )
caller = "LSOCall" caller = "LSOCall"
-- Schedule radio queue checks. -- Schedule radio queue checks.
if not self.RQLid then if not self.RQLid then
self:T( self.lid .. string.format( "Starting LSO radio queue." ) ) self:T( self.lid .. string.format( "Starting LSO radio queue." ) )
self.RQLid = self.radiotimer:Schedule( nil, AIRBOSS._CheckRadioQueue, { self, self.RQLSO, "LSO" }, 0.02, 0.05 ) self.RQLid = self.radiotimer:Schedule( nil, AIRBOSS._CheckRadioQueue, { self, self.RQLSO, "LSO" }, 0.02, 0.05 )
end end
elseif radio.alias == "MARSHAL" then elseif radio.alias == "MARSHAL" then
table.insert( self.RQMarshal, transmission ) table.insert( self.RQMarshal, transmission )
caller = "MarshalCall" caller = "MarshalCall"
if not self.RQMid then if not self.RQMid then
self:T( self.lid .. string.format( "Starting Marhal radio queue." ) ) self:T( self.lid .. string.format( "Starting Marhal radio queue." ) )
self.RQMid = self.radiotimer:Schedule( nil, AIRBOSS._CheckRadioQueue, { self, self.RQMarshal, "MARSHAL" }, 0.02, 0.05 ) self.RQMid = self.radiotimer:Schedule( nil, AIRBOSS._CheckRadioQueue, { self, self.RQMarshal, "MARSHAL" }, 0.02, 0.05 )
end end
end end
-- Append radio click sound at the end of the transmission. -- Append radio click sound at the end of the transmission.
if click then if click then
self:RadioTransmission( radio, self[caller].CLICK, false, delay ) self:RadioTransmission( radio, self[caller].CLICK, false, delay )
end end
else else
-- SRS transmission -- SRS transmission
local frequency = self.MarshalRadio.frequency local frequency = self.MarshalRadio.frequency
local modulation = self.MarshalRadio.modulation local modulation = self.MarshalRadio.modulation
local voice = nil local voice = nil
local gender = nil local gender = nil
local culture = nil local culture = nil
if radio.alias == "AIRBOSS" then if radio.alias == "AIRBOSS" then
frequency = self.AirbossRadio.frequency frequency = self.AirbossRadio.frequency
modulation = self.AirbossRadio.modulation modulation = self.AirbossRadio.modulation
@ -14802,13 +14805,13 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
gender = self.AirbossRadio.gender gender = self.AirbossRadio.gender
culture = self.AirbossRadio.culture culture = self.AirbossRadio.culture
end end
if radio.alias == "MARSHAL" then if radio.alias == "MARSHAL" then
voice = self.MarshalRadio.voice voice = self.MarshalRadio.voice
gender = self.MarshalRadio.gender gender = self.MarshalRadio.gender
culture = self.MarshalRadio.culture culture = self.MarshalRadio.culture
end end
if radio.alias == "LSO" then if radio.alias == "LSO" then
frequency = self.LSORadio.frequency frequency = self.LSORadio.frequency
modulation = self.LSORadio.modulation modulation = self.LSORadio.modulation
@ -14816,7 +14819,7 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
gender = self.LSORadio.gender gender = self.LSORadio.gender
culture = self.LSORadio.culture culture = self.LSORadio.culture
end end
if pilotcall then if pilotcall then
voice = self.PilotRadio.voice voice = self.PilotRadio.voice
gender = self.PilotRadio.gender gender = self.PilotRadio.gender
@ -14830,16 +14833,16 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
modulation = self.AirbossRadio.modulation modulation = self.AirbossRadio.modulation
radio.alias = "AIRBOSS" radio.alias = "AIRBOSS"
end end
local volume = nil local volume = nil
if loud then if loud then
volume = 1.0 volume = 1.0
end end
--local text = tostring(call.modexreceiver).."; "..radio.alias.."; "..call.subtitle --local text = tostring(call.modexreceiver).."; "..radio.alias.."; "..call.subtitle
local text = call.subtitle local text = call.subtitle
self:I(self.lid..text) self:I(self.lid..text)
local srstext = self:_GetNiceSRSText(text) local srstext = self:_GetNiceSRSText(text)
self.SRSQ:NewTransmission(srstext, call.duration, self.SRS, tstart, 0.1, subgroups, call.subtitle, call.subduration, frequency, modulation, gender, culture, voice, volume, radio.alias) self.SRSQ:NewTransmission(srstext, call.duration, self.SRS, tstart, 0.1, subgroups, call.subtitle, call.subduration, frequency, modulation, gender, culture, voice, volume, radio.alias)
end end
@ -14858,11 +14861,11 @@ function AIRBOSS:SetSRSPilotVoice( Voice, Gender, Culture )
self.PilotRadio.voice = Voice or MSRS.Voices.Microsoft.David self.PilotRadio.voice = Voice or MSRS.Voices.Microsoft.David
self.PilotRadio.gender = Gender or "male" self.PilotRadio.gender = Gender or "male"
self.PilotRadio.culture = Culture or "en-US" self.PilotRadio.culture = Culture or "en-US"
if (not Voice) and self.SRS and self.SRS.google then if (not Voice) and self.SRS and self.SRS.google then
self.PilotRadio.voice = MSRS.Voices.Google.Standard.en_US_Standard_J self.PilotRadio.voice = MSRS.Voices.Google.Standard.en_US_Standard_J
end end
return self return self
end end
@ -15176,44 +15179,44 @@ function AIRBOSS:MessageToPlayer( playerData, message, sender, receiver, duratio
-- SCHEDULER:New(nil, self.MessageToPlayer, {self, playerData, message, sender, receiver, duration, clear}, delay) -- SCHEDULER:New(nil, self.MessageToPlayer, {self, playerData, message, sender, receiver, duration, clear}, delay)
self:ScheduleOnce( delay, self.MessageToPlayer, self, playerData, message, sender, receiver, duration, clear ) self:ScheduleOnce( delay, self.MessageToPlayer, self, playerData, message, sender, receiver, duration, clear )
else else
if not self.SRS then if not self.SRS then
-- Wait until previous sound finished. -- Wait until previous sound finished.
local wait = 0 local wait = 0
-- Onboard number to get the attention. -- Onboard number to get the attention.
if receiver == playerData.onboard then if receiver == playerData.onboard then
-- Which voice over number to use. -- Which voice over number to use.
if sender and (sender == "LSO" or sender == "MARSHAL" or sender == "AIRBOSS") then if sender and (sender == "LSO" or sender == "MARSHAL" or sender == "AIRBOSS") then
-- User sound of board number. -- User sound of board number.
wait = wait + self:_Number2Sound( playerData, sender, receiver ) wait = wait + self:_Number2Sound( playerData, sender, receiver )
end end
end end
-- Negative. -- Negative.
if string.find( text:lower(), "negative" ) then if string.find( text:lower(), "negative" ) then
local filename = self:_RadioFilename( self.MarshalCall.NEGATIVE, false, "MARSHAL" ) local filename = self:_RadioFilename( self.MarshalCall.NEGATIVE, false, "MARSHAL" )
USERSOUND:New( filename ):ToGroup( playerData.group, wait ) USERSOUND:New( filename ):ToGroup( playerData.group, wait )
wait = wait + self.MarshalCall.NEGATIVE.duration wait = wait + self.MarshalCall.NEGATIVE.duration
end end
-- Affirm. -- Affirm.
if string.find( text:lower(), "affirm" ) then if string.find( text:lower(), "affirm" ) then
local filename = self:_RadioFilename( self.MarshalCall.AFFIRMATIVE, false, "MARSHAL" ) local filename = self:_RadioFilename( self.MarshalCall.AFFIRMATIVE, false, "MARSHAL" )
USERSOUND:New( filename ):ToGroup( playerData.group, wait ) USERSOUND:New( filename ):ToGroup( playerData.group, wait )
wait = wait + self.MarshalCall.AFFIRMATIVE.duration wait = wait + self.MarshalCall.AFFIRMATIVE.duration
end end
-- Roger. -- Roger.
if string.find( text:lower(), "roger" ) then if string.find( text:lower(), "roger" ) then
local filename = self:_RadioFilename( self.MarshalCall.ROGER, false, "MARSHAL" ) local filename = self:_RadioFilename( self.MarshalCall.ROGER, false, "MARSHAL" )
USERSOUND:New( filename ):ToGroup( playerData.group, wait ) USERSOUND:New( filename ):ToGroup( playerData.group, wait )
wait = wait + self.MarshalCall.ROGER.duration wait = wait + self.MarshalCall.ROGER.duration
end end
-- Play click sound to end message. -- Play click sound to end message.
if wait > 0 then if wait > 0 then
local filename = self:_RadioFilename( self.MarshalCall.CLICK ) local filename = self:_RadioFilename( self.MarshalCall.CLICK )
@ -15226,7 +15229,7 @@ function AIRBOSS:MessageToPlayer( playerData, message, sender, receiver, duratio
local voice = self.MarshalRadio.voice local voice = self.MarshalRadio.voice
local gender = self.MarshalRadio.gender local gender = self.MarshalRadio.gender
local culture = self.MarshalRadio.culture local culture = self.MarshalRadio.culture
if not sender then sender = "AIRBOSS" end if not sender then sender = "AIRBOSS" end
if string.find(sender,"AIRBOSS" ) then if string.find(sender,"AIRBOSS" ) then

View File

@ -1517,6 +1517,23 @@ function AWACS:_SubScribeTactRadio(Group,Frequency)
return self return self
end end
--- [Internal] _CheckSubscribers
-- @param #AWACS self
-- @return #AWACS self
function AWACS:_CheckSubscribers()
self:T(self.lid.."_InitLocalization")
for _name,_freq in pairs(self.TacticalSubscribers or {}) do
local grp = GROUP:FindByName(_name)
if (not grp) or (not grp:IsAlive()) then
self.TacticalFrequencies[_freq] = _freq
self.TacticalSubscribers[_name] = nil
end
end
return self
end
--- [Internal] Init localization --- [Internal] Init localization
-- @param #AWACS self -- @param #AWACS self
-- @return #AWACS self -- @return #AWACS self
@ -1596,7 +1613,7 @@ function AWACS:_NewRadioEntry(TextTTS, TextScreen,GID,IsGroup,ToScreen,IsNew,Fro
local RadioEntry = {} -- #AWACS.RadioEntry local RadioEntry = {} -- #AWACS.RadioEntry
RadioEntry.IsNew = IsNew RadioEntry.IsNew = IsNew
RadioEntry.TextTTS = TextTTS RadioEntry.TextTTS = TextTTS
RadioEntry.TextScreen = TextScreen RadioEntry.TextScreen = TextScreen or TextTTS
RadioEntry.GroupID = GID RadioEntry.GroupID = GID
RadioEntry.ToScreen = ToScreen RadioEntry.ToScreen = ToScreen
RadioEntry.Duration = STTS.getSpeechTime(TextTTS,0.95,false) or 8 RadioEntry.Duration = STTS.getSpeechTime(TextTTS,0.95,false) or 8
@ -6180,6 +6197,8 @@ function AWACS:onafterStatus(From, Event, To)
self:_CheckMerges() self:_CheckMerges()
self:_CheckSubscribers()
local outcome, targets = self:_TargetSelectionProcess(true) local outcome, targets = self:_TargetSelectionProcess(true)
self:_CheckTaskQueue() self:_CheckTaskQueue()

View File

@ -1485,6 +1485,17 @@ function CHIEF:AddGciCapZone(Zone, Altitude, Speed, Heading, Leg)
return zone return zone
end end
--- Remove a GCI CAP
-- @param #CHIEF self
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
function CHIEF:RemoveGciCapZone(Zone)
-- Hand over to commander.
local zone=self.commander:RemoveGciCapZone(Zone)
return zone
end
--- Add an AWACS zone. --- Add an AWACS zone.
-- @param #CHIEF self -- @param #CHIEF self
-- @param Core.Zone#ZONE Zone Zone. -- @param Core.Zone#ZONE Zone Zone.
@ -1501,6 +1512,17 @@ function CHIEF:AddAwacsZone(Zone, Altitude, Speed, Heading, Leg)
return zone return zone
end end
--- Remove a AWACS zone.
-- @param #CHIEF self
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
function CHIEF:RemoveAwacsZone(Zone)
-- Hand over to commander.
local zone=self.commander:RemoveAwacsZone(Zone)
return zone
end
--- Add a refuelling tanker zone. --- Add a refuelling tanker zone.
-- @param #CHIEF self -- @param #CHIEF self
-- @param Core.Zone#ZONE Zone Zone. -- @param Core.Zone#ZONE Zone Zone.
@ -1518,6 +1540,16 @@ function CHIEF:AddTankerZone(Zone, Altitude, Speed, Heading, Leg, RefuelSystem)
return zone return zone
end end
--- Remove a refuelling tanker zone.
-- @param #CHIEF self
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
function CHIEF:RemoveTankerZone(Zone)
-- Hand over to commander.
local zone=self.commander:RemoveTankerZone(Zone)
return zone
end
--- Set border zone set, defining your territory. --- Set border zone set, defining your territory.
-- --

View File

@ -710,6 +710,26 @@ function COMMANDER:AddGciCapZone(Zone, Altitude, Speed, Heading, Leg)
return patrolzone return patrolzone
end end
--- Remove a GCI CAP.
-- @param #COMMANDER self
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
function COMMANDER:RemoveGciCapZone(Zone)
local patrolzone={} --Ops.AirWing#AIRWING.PatrolZone
patrolzone.zone=Zone
for i,_patrolzone in pairs(self.gcicapZones) do
if _patrolzone.zone == patrolzone.zone then
if _patrolzone.mission and _patrolzone.mission:IsNotOver() then
_patrolzone.mission:Cancel()
end
table.remove(self.gcicapZones, i)
break
end
end
return patrolzone
end
--- Add an AWACS zone. --- Add an AWACS zone.
-- @param #COMMANDER self -- @param #COMMANDER self
-- @param Core.Zone#ZONE Zone Zone. -- @param Core.Zone#ZONE Zone Zone.
@ -735,6 +755,26 @@ function COMMANDER:AddAwacsZone(Zone, Altitude, Speed, Heading, Leg)
return awacszone return awacszone
end end
--- Remove a AWACS zone.
-- @param #COMMANDER self
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
function COMMANDER:RemoveAwacsZone(Zone)
local awacszone={} --Ops.AirWing#AIRWING.PatrolZone
awacszone.zone=Zone
for i,_awacszone in pairs(self.awacsZones) do
if _awacszone.zone == awacszone.zone then
if _awacszone.mission and _awacszone.mission:IsNotOver() then
_awacszone.mission:Cancel()
end
table.remove(self.awacsZones, i)
break
end
end
return awacszone
end
--- Add a refuelling tanker zone. --- Add a refuelling tanker zone.
-- @param #COMMANDER self -- @param #COMMANDER self
-- @param Core.Zone#ZONE Zone Zone. -- @param Core.Zone#ZONE Zone Zone.
@ -762,6 +802,26 @@ function COMMANDER:AddTankerZone(Zone, Altitude, Speed, Heading, Leg, RefuelSyst
return tankerzone return tankerzone
end end
--- Remove a refuelling tanker zone.
-- @param #COMMANDER self
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
function COMMANDER:RemoveTankerZone(Zone)
local tankerzone={} --Ops.AirWing#AIRWING.PatrolZone
tankerzone.zone=Zone
for i,_tankerzone in pairs(self.tankerZones) do
if _tankerzone.zone == tankerzone.zone then
if _tankerzone.mission and _tankerzone.mission:IsNotOver() then
_tankerzone.mission:Cancel()
end
table.remove(self.tankerZones, i)
break
end
end
return tankerzone
end
--- Check if this mission is already in the queue. --- Check if this mission is already in the queue.
-- @param #COMMANDER self -- @param #COMMANDER self
-- @param Ops.Auftrag#AUFTRAG Mission The mission. -- @param Ops.Auftrag#AUFTRAG Mission The mission.

View File

@ -325,7 +325,322 @@ function FLIGHTGROUP:New(group)
-- @param #FLIGHTGROUP self -- @param #FLIGHTGROUP self
-- @param #number delay Delay in seconds. -- @param #number delay Delay in seconds.
-- TODO: Add pseudo functions. --- FSM Function OnAfterElementSpawned.
-- @function [parent=#FLIGHTGROUP] OnAfterElementSpawned
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
--- FSM Function OnAfterElementParking.
-- @function [parent=#FLIGHTGROUP] OnAfterElementParking
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
-- @param Wrapper.Airbase#AIRBASE.ParkingSpot Spot Parking Spot.
--- FSM Function OnAfterElementEngineOn.
-- @function [parent=#FLIGHTGROUP] OnAfterElementEngineOn
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
--- FSM Function OnAfterElementTaxiing.
-- @function [parent=#FLIGHTGROUP] OnAfterElementTaxiing
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
--- FSM Function OnAfterElementTakeoff.
-- @function [parent=#FLIGHTGROUP] OnAfterElementTakeoff
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
-- @param Wrapper.Airbase#AIRBASE airbase The airbase if applicable or nil.
--- FSM Function OnAfterElementAirborne.
-- @function [parent=#FLIGHTGROUP] OnAfterElementAirborne
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
--- FSM Function OnAfterElementLanded.
-- @function [parent=#FLIGHTGROUP] OnAfterElementLanded
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
-- @param Wrapper.Airbase#AIRBASE airbase The airbase if applicable or nil.
--- FSM Function OnAfterElementArrived.
-- @function [parent=#FLIGHTGROUP] OnAfterElementArrived
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
-- @param Wrapper.Airbase#AIRBASE airbase The airbase, where the element arrived.
-- @param Wrapper.Airbase#AIRBASE.ParkingSpot Parking The Parking spot the element has.
--- FSM Function OnAfterElementDestroyed.
-- @function [parent=#FLIGHTGROUP] OnAfterElementDestroyed
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
--- FSM Function OnAfterElementDead.
-- @function [parent=#FLIGHTGROUP] OnAfterElementDead
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
--- FSM Function OnAfterSpawned.
-- @function [parent=#FLIGHTGROUP] OnAfterSpawned
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- FSM Function OnAfterParking.
-- @function [parent=#FLIGHTGROUP] OnAfterParking
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- FSM Function OnAfterTaxiing.
-- @function [parent=#FLIGHTGROUP] OnAfterTaxiing
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- FSM Function OnAfterTakeoff.
-- @function [parent=#FLIGHTGROUP] OnAfterTakeoff
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- FSM Function OnAfterAirborne.
-- @function [parent=#FLIGHTGROUP] OnAfterAirborne
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- FSM Function OnAfterCruise.
-- @function [parent=#FLIGHTGROUP] OnAfterCruise
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- FSM Function OnAfterLanding.
-- @function [parent=#FLIGHTGROUP] OnAfterLanding
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- FSM Function OnAfterLanded.
-- @function [parent=#FLIGHTGROUP] OnAfterLanded
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Wrapper.Airbase#AIRBASE airbase The airbase the flight landed.
--- FSM Function OnAfterLandedAt.
-- @function [parent=#FLIGHTGROUP] OnAfterLandedAt
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- FSM Function OnAfterArrived.
-- @function [parent=#FLIGHTGROUP] OnAfterArrived
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- FSM Function OnAfterDead.
-- @function [parent=#FLIGHTGROUP] OnAfterDead
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- FSM Function OnAfterUpdateRoute.
-- @function [parent=#FLIGHTGROUP] OnAfterUpdateRoute
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #number n Next waypoint index. Default is the one coming after that one that has been passed last.
-- @param #number N Waypoint Max waypoint index to be included in the route. Default is the final waypoint.
--- FSM Function OnAfterOutOfMissilesAA.
-- @function [parent=#FLIGHTGROUP] OnAfterOutOfMissilesAA
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- FSM Function OnAfterOutOfMissilesAG.
-- @function [parent=#FLIGHTGROUP] OnAfterOutOfMissilesAG
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- FSM Function OnAfterRTB.
-- @function [parent=#FLIGHTGROUP] OnAfterRTB
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Wrapper.Airbase#AIRBASE airbase The airbase to hold at.
-- @param #number SpeedTo Speed used for traveling from current position to holding point in knots. Default 75% of max speed.
-- @param #number SpeedHold Holding speed in knots. Default 250 kts.
-- @param #number SpeedLand Landing speed in knots. Default 170 kts.
--- FSM Function OnAfterLandAtAirbase.
-- @function [parent=#FLIGHTGROUP] OnAfterLandAtAirbase
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Wrapper.Airbase#AIRBASE airbase The airbase to hold at.
--- FSM Function OnAfterWait.
-- @function [parent=#FLIGHTGROUP] OnAfterWait
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #number Duration Duration how long the group will be waiting in seconds. Default `nil` (=forever).
-- @param #number Altitude Altitude in feet. Default 10,000 ft for airplanes and 1,000 feet for helos.
-- @param #number Speed Speed in knots. Default 250 kts for airplanes and 20 kts for helos.
--- FSM Function OnAfterRefuel.
-- @function [parent=#FLIGHTGROUP] OnAfterRefuel
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Core.Point#COORDINATE Coordinate The coordinate.
--- FSM Function OnAfterRefueled.
-- @function [parent=#FLIGHTGROUP] OnAfterRefueled
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- FSM Function OnAfterDisengage.
-- @function [parent=#FLIGHTGROUP] OnAfterDisengage
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Core.Set#SET_UNIT TargetUnitSet
--- FSM Function OnAfterEngageTarget.
-- @function [parent=#FLIGHTGROUP] OnAfterEngageTarget
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #table Target Target object. Can be a UNIT, STATIC, GROUP, SET_UNIT or SET_GROUP object.
--- FSM Function OnAfterLandAt.
-- @function [parent=#FLIGHTGROUP] OnAfterLandAt
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Core.Set#SET_UNIT TargetUnitSet
--- FSM Function OnAfterFuelLow.
-- @function [parent=#FLIGHTGROUP] OnAfterFuelLow
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- FSM Function OnAfterFuelCritical.
-- @function [parent=#FLIGHTGROUP] OnAfterFuelCritical
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- FSM Function OnBeforeUpdateRoute.
-- @function [parent=#FLIGHTGROUP] OnBeforeUpdateRoute
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #number n Next waypoint index. Default is the one coming after that one that has been passed last.
-- @param #number N Waypoint Max waypoint index to be included in the route. Default is the final waypoint.
-- @return #boolean Transision allowed?
--- FSM Function OnBeforeRTB.
-- @function [parent=#FLIGHTGROUP] OnBeforeRTB
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Wrapper.Airbase#AIRBASE airbase The airbase to hold at.
-- @param #number SpeedTo Speed used for travelling from current position to holding point in knots.
-- @param #number SpeedHold Holding speed in knots.
--- FSM Function OnBeforeLandAtAirbase.
-- @function [parent=#FLIGHTGROUP] OnBeforeLandAtAirbase
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Wrapper.Airbase#AIRBASE airbase The airbase to hold at.
--- FSM Function OnBeforeWait.
-- @function [parent=#FLIGHTGROUP] OnBeforeWait
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #number Duration Duration how long the group will be waiting in seconds. Default `nil` (=forever).
-- @param #number Altitude Altitude in feet. Default 10,000 ft for airplanes and 1,000 feet for helos.
-- @param #number Speed Speed in knots. Default 250 kts for airplanes and 20 kts for helos.
--- FSM Function OnBeforeLandAt.
-- @function [parent=#FLIGHTGROUP] OnBeforeLandAt
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Core.Point#COORDINATE Coordinate The coordinate where to land. Default is current position.
-- @param #number Duration The duration in seconds to remain on ground. Default 600 sec (10 min).
-- TODO: Add pseudo functions ? Normally done, but should be double check
-- Handle events: -- Handle events:
self:HandleEvent(EVENTS.Birth, self.OnEventBirth) self:HandleEvent(EVENTS.Birth, self.OnEventBirth)

View File

@ -21,7 +21,7 @@
-- === -- ===
-- @module Ops.PlayerTask -- @module Ops.PlayerTask
-- @image OPS_PlayerTask.jpg -- @image OPS_PlayerTask.jpg
-- @date Last Update June 2023 -- @date Last Update July 2023
do do
@ -98,7 +98,7 @@ PLAYERTASK = {
--- PLAYERTASK class version. --- PLAYERTASK class version.
-- @field #string version -- @field #string version
PLAYERTASK.version="0.1.18" PLAYERTASK.version="0.1.19"
--- Generic task condition. --- Generic task condition.
-- @type PLAYERTASK.Condition -- @type PLAYERTASK.Condition
@ -1656,13 +1656,6 @@ function PLAYERTASKCONTROLLER:New(Name, Coalition, Type, ClientFilter)
local starttime = math.random(5,10) local starttime = math.random(5,10)
self:__Status(starttime) self:__Status(starttime)
-- Player leaves
self:HandleEvent(EVENTS.PlayerLeaveUnit, self._EventHandler)
self:HandleEvent(EVENTS.Ejection, self._EventHandler)
self:HandleEvent(EVENTS.Crash, self._EventHandler)
self:HandleEvent(EVENTS.PilotDead, self._EventHandler)
self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler)
self:I(self.lid..self.version.." Started.") self:I(self.lid..self.version.." Started.")
return self return self
@ -2177,7 +2170,7 @@ end
-- @return #PLAYERTASKCONTROLLER self -- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:_EventHandler(EventData) function PLAYERTASKCONTROLLER:_EventHandler(EventData)
self:T(self.lid.."_EventHandler: "..EventData.id) self:T(self.lid.."_EventHandler: "..EventData.id)
self:T(self.lid.."_EventHandler: "..EventData.IniPlayerName) --self:T(self.lid.."_EventHandler: "..EventData.IniPlayerName)
if EventData.id == EVENTS.PlayerLeaveUnit or EventData.id == EVENTS.Ejection or EventData.id == EVENTS.Crash or EventData.id == EVENTS.PilotDead then if EventData.id == EVENTS.PlayerLeaveUnit or EventData.id == EVENTS.Ejection or EventData.id == EVENTS.Crash or EventData.id == EVENTS.PilotDead then
if EventData.IniPlayerName then if EventData.IniPlayerName then
self:T(self.lid.."Event for player: "..EventData.IniPlayerName) self:T(self.lid.."Event for player: "..EventData.IniPlayerName)
@ -2483,6 +2476,15 @@ function PLAYERTASKCONTROLLER:_CheckTaskQueue()
self:T("*****Removing player " .. _id) self:T("*****Removing player " .. _id)
self.TasksPerPlayer:PullByID(_id) self.TasksPerPlayer:PullByID(_id)
end end
local clients=task:GetClientObjects()
for _,client in pairs(clients) do
self:_RemoveMenuEntriesForTask(task,client)
--self:_SwitchMenuForClient(client,"Info")
end
for _,client in pairs(clients) do
-- self:_RemoveMenuEntriesForTask(Task,client)
self:_SwitchMenuForClient(client,"Info",5)
end
-- Follow-up tasks? -- Follow-up tasks?
local nexttasks = {} local nexttasks = {}
if task.FinalState == "Success" then if task.FinalState == "Success" then
@ -3594,28 +3596,28 @@ function PLAYERTASKCONTROLLER:_RemoveMenuEntriesForTask(Task,Client)
if Task then if Task then
if Task.UUIDS and self.JoinTaskMenuTemplate then if Task.UUIDS and self.JoinTaskMenuTemplate then
--self:I("***** JoinTaskMenuTemplate") --self:I("***** JoinTaskMenuTemplate")
UTILS.PrintTableToLog(Task.UUIDS) --UTILS.PrintTableToLog(Task.UUIDS)
local controller = self.JoinTaskMenuTemplate local controller = self.JoinTaskMenuTemplate
for _,_uuid in pairs(Task.UUIDS) do for _,_uuid in pairs(Task.UUIDS) do
local Entry = controller:FindEntryByUUID(_uuid) local Entry = controller:FindEntryByUUID(_uuid)
if Entry then if Entry then
controller:DeleteF10Entry(Entry,Client) controller:DeleteF10Entry(Entry,Client)
controller:DeleteGenericEntry(Entry) controller:DeleteGenericEntry(Entry)
UTILS.PrintTableToLog(controller.menutree) --UTILS.PrintTableToLog(controller.menutree)
end end
end end
end end
if Task.AUUIDS and self.ActiveTaskMenuTemplate then if Task.AUUIDS and self.ActiveTaskMenuTemplate then
--self:I("***** ActiveTaskMenuTemplate") --self:I("***** ActiveTaskMenuTemplate")
UTILS.PrintTableToLog(Task.AUUIDS) --UTILS.PrintTableToLog(Task.AUUIDS)
for _,_uuid in pairs(Task.AUUIDS) do for _,_uuid in pairs(Task.AUUIDS) do
local controller = self.ActiveTaskMenuTemplate local controller = self.ActiveTaskMenuTemplate
local Entry = controller:FindEntryByUUID(_uuid) local Entry = controller:FindEntryByUUID(_uuid)
if Entry then if Entry then
controller:DeleteF10Entry(Entry,Client) controller:DeleteF10Entry(Entry,Client)
controller:DeleteGenericEntry(Entry) controller:DeleteGenericEntry(Entry)
UTILS.PrintTableToLog(controller.menutree) --UTILS.PrintTableToLog(controller.menutree)
end end
end end
end end
@ -4063,6 +4065,12 @@ function PLAYERTASKCONTROLLER:onafterStart(From, Event, To)
self:T(self.lid.."onafterStart") self:T(self.lid.."onafterStart")
self:_CreateJoinMenuTemplate() self:_CreateJoinMenuTemplate()
self:_CreateActiveTaskMenuTemplate() self:_CreateActiveTaskMenuTemplate()
-- Player Events
self:HandleEvent(EVENTS.PlayerLeaveUnit, self._EventHandler)
self:HandleEvent(EVENTS.Ejection, self._EventHandler)
self:HandleEvent(EVENTS.Crash, self._EventHandler)
self:HandleEvent(EVENTS.PilotDead, self._EventHandler)
self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler)
return self return self
end end
@ -4210,6 +4218,15 @@ function PLAYERTASKCONTROLLER:onafterTaskFailed(From, Event, To, Task)
taskname = string.format(failtxttts, self.MenuName or self.Name, Task.PlayerTaskNr, tostring(Task.TTSType)) taskname = string.format(failtxttts, self.MenuName or self.Name, Task.PlayerTaskNr, tostring(Task.TTSType))
self.SRSQueue:NewTransmission(taskname,nil,self.SRS,nil,2) self.SRSQueue:NewTransmission(taskname,nil,self.SRS,nil,2)
end end
local clients=Task:GetClientObjects()
for _,client in pairs(clients) do
self:_RemoveMenuEntriesForTask(Task,client)
--self:_SwitchMenuForClient(client,"Info")
end
for _,client in pairs(clients) do
-- self:_RemoveMenuEntriesForTask(Task,client)
self:_SwitchMenuForClient(client,"Info",5)
end
return self return self
end end

View File

@ -295,8 +295,9 @@ UTILS.DeepCopy = function(object)
end end
--- Porting in Slmod's serialize_slmod2. --- Serialize a given table.
-- @param #table tbl Input table. -- @param #table tbl Input table.
-- @return #string Table as a string.
UTILS.OneLineSerialize = function( tbl ) -- serialization of a table all on a single line, no comments, made to replace old get_table_string function UTILS.OneLineSerialize = function( tbl ) -- serialization of a table all on a single line, no comments, made to replace old get_table_string function
local lookup_table = {} local lookup_table = {}
@ -373,7 +374,54 @@ local lookup_table = {}
return objectreturn return objectreturn
end end
--porting in Slmod's "safestring" basic serialize --- Serialize a table to a single line string.
-- @param #table tbl table to serialize.
-- @return #string string containing serialized table.
function UTILS._OneLineSerialize(tbl)
if type(tbl) == 'table' then --function only works for tables!
local tbl_str = {}
tbl_str[#tbl_str + 1] = '{ '
for ind,val in pairs(tbl) do -- serialize its fields
if type(ind) == "number" then
tbl_str[#tbl_str + 1] = '['
tbl_str[#tbl_str + 1] = tostring(ind)
tbl_str[#tbl_str + 1] = '] = '
else --must be a string
tbl_str[#tbl_str + 1] = '['
tbl_str[#tbl_str + 1] = UTILS.BasicSerialize(ind)
tbl_str[#tbl_str + 1] = '] = '
end
if ((type(val) == 'number') or (type(val) == 'boolean')) then
tbl_str[#tbl_str + 1] = tostring(val)
tbl_str[#tbl_str + 1] = ', '
elseif type(val) == 'string' then
tbl_str[#tbl_str + 1] = UTILS.BasicSerialize(val)
tbl_str[#tbl_str + 1] = ', '
elseif type(val) == 'nil' then -- won't ever happen, right?
tbl_str[#tbl_str + 1] = 'nil, '
elseif type(val) == 'table' then
tbl_str[#tbl_str + 1] = UTILS._OneLineSerialize(val)
tbl_str[#tbl_str + 1] = ', ' --I think this is right, I just added it
else
--log:warn('Unable to serialize value type $1 at index $2', mist.utils.basicSerialize(type(val)), tostring(ind))
end
end
tbl_str[#tbl_str + 1] = '}'
return table.concat(tbl_str)
else
return UTILS.BasicSerialize(tbl)
end
end
--- Basic serialize (porting in Slmod's "safestring" basic serialize).
-- @param #string s Table to serialize.
UTILS.BasicSerialize = function(s) UTILS.BasicSerialize = function(s)
if s == nil then if s == nil then
return "\"\"" return "\"\""
@ -404,6 +452,114 @@ function UTILS.PrintTableToLog(table, indent)
end end
end end
--- Returns table in a easy readable string representation.
-- @param tbl table to show
-- @param loc
-- @param indent
-- @param tableshow_tbls
-- @return Human readable string representation of given table.
function UTILS.TableShow(tbl, loc, indent, tableshow_tbls)
tableshow_tbls = tableshow_tbls or {} --create table of tables
loc = loc or ""
indent = indent or ""
if type(tbl) == 'table' then --function only works for tables!
tableshow_tbls[tbl] = loc
local tbl_str = {}
tbl_str[#tbl_str + 1] = indent .. '{\n'
for ind,val in pairs(tbl) do -- serialize its fields
if type(ind) == "number" then
tbl_str[#tbl_str + 1] = indent
tbl_str[#tbl_str + 1] = loc .. '['
tbl_str[#tbl_str + 1] = tostring(ind)
tbl_str[#tbl_str + 1] = '] = '
else
tbl_str[#tbl_str + 1] = indent
tbl_str[#tbl_str + 1] = loc .. '['
tbl_str[#tbl_str + 1] = UTILS.BasicSerialize(ind)
tbl_str[#tbl_str + 1] = '] = '
end
if ((type(val) == 'number') or (type(val) == 'boolean')) then
tbl_str[#tbl_str + 1] = tostring(val)
tbl_str[#tbl_str + 1] = ',\n'
elseif type(val) == 'string' then
tbl_str[#tbl_str + 1] = UTILS.BasicSerialize(val)
tbl_str[#tbl_str + 1] = ',\n'
elseif type(val) == 'nil' then -- won't ever happen, right?
tbl_str[#tbl_str + 1] = 'nil,\n'
elseif type(val) == 'table' then
if tableshow_tbls[val] then
tbl_str[#tbl_str + 1] = tostring(val) .. ' already defined: ' .. tableshow_tbls[val] .. ',\n'
else
tableshow_tbls[val] = loc .. '[' .. UTILS.BasicSerialize(ind) .. ']'
tbl_str[#tbl_str + 1] = tostring(val) .. ' '
tbl_str[#tbl_str + 1] = UTILS.TableShow(val, loc .. '[' .. UTILS.BasicSerialize(ind).. ']', indent .. ' ', tableshow_tbls)
tbl_str[#tbl_str + 1] = ',\n'
end
elseif type(val) == 'function' then
if debug and debug.getinfo then
local fcnname = tostring(val)
local info = debug.getinfo(val, "S")
if info.what == "C" then
tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', C function') .. ',\n'
else
if (string.sub(info.source, 1, 2) == [[./]]) then
tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', defined in (' .. info.linedefined .. '-' .. info.lastlinedefined .. ')' .. info.source) ..',\n'
else
tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', defined in (' .. info.linedefined .. '-' .. info.lastlinedefined .. ')') ..',\n'
end
end
else
tbl_str[#tbl_str + 1] = 'a function,\n'
end
else
tbl_str[#tbl_str + 1] = 'unable to serialize value type ' .. UTILS.BasicSerialize(type(val)) .. ' at index ' .. tostring(ind)
end
end
tbl_str[#tbl_str + 1] = indent .. '}'
return table.concat(tbl_str)
end
end
--- Dumps the global table _G.
-- This dumps the global table _G to a file in the DCS\Logs directory.
-- This function requires you to disable script sanitization in $DCS_ROOT\Scripts\MissionScripting.lua to access lfs and io libraries.
-- @param #string fname File name.
function UTILS.Gdump(fname)
if lfs and io then
local fdir = lfs.writedir() .. [[Logs\]] .. fname
local f = io.open(fdir, 'w')
f:write(UTILS.TableShow(_G))
f:close()
env.info(string.format('Wrote debug data to $1', fdir))
else
env.error("WARNING: lfs and/or io not de-sanitized - cannot dump _G!")
end
end
--- Executes the given string.
-- borrowed from Slmod
-- @param #string s string containing LUA code.
-- @return #boolean `true` if successfully executed, `false` otherwise.
function UTILS.DoString(s)
local f, err = loadstring(s)
if f then
return true, f()
else
return false, err
end
end
UTILS.ToDegree = function(angle) UTILS.ToDegree = function(angle)
return angle*180/math.pi return angle*180/math.pi

View File

@ -1734,6 +1734,27 @@ function CONTROLLABLE:EnRouteTaskSEAD(TargetTypes, Priority)
return DCSTask return DCSTask
end end
--- (AIR) Enroute CAP task.
-- @param #CONTROLLABLE self
-- @param DCS#AttributeNameArray TargetTypes Array of target categories allowed to engage. Default `{"Air"}`.
-- @param #number Priority (Optional) All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. Default 0.
-- @return DCS#Task The DCS task structure.
function CONTROLLABLE:EnRouteTaskCAP(TargetTypes, Priority)
local DCSTask = {
id = 'EngageTargets',
key = "CAP",
--auto = true,
enabled = true,
params = {
targetTypes = TargetTypes or {"Air"},
priority = Priority or 0
}
}
return DCSTask
end
--- (AIR) Engaging a controllable. The task does not assign the target controllable to the unit/controllable to attack now; --- (AIR) Engaging a controllable. The task does not assign the target controllable to the unit/controllable to attack now;
-- it just allows the unit/controllable to engage the target controllable as well as other assigned targets. -- it just allows the unit/controllable to engage the target controllable as well as other assigned targets.
-- See [hoggit](https://wiki.hoggitworld.com/view/DCS_task_engageGroup). -- See [hoggit](https://wiki.hoggitworld.com/view/DCS_task_engageGroup).

View File

@ -18,6 +18,7 @@
-- @field #string SceneryName Name of the scenery object. -- @field #string SceneryName Name of the scenery object.
-- @field DCS#Object SceneryObject DCS scenery object. -- @field DCS#Object SceneryObject DCS scenery object.
-- @field #number Life0 Initial life points. -- @field #number Life0 Initial life points.
-- @field #table Properties
-- @extends Wrapper.Positionable#POSITIONABLE -- @extends Wrapper.Positionable#POSITIONABLE
@ -43,7 +44,7 @@ function SCENERY:Register( SceneryName, SceneryObject )
local self = BASE:Inherit( self, POSITIONABLE:New( SceneryName ) ) local self = BASE:Inherit( self, POSITIONABLE:New( SceneryName ) )
self.SceneryName = SceneryName self.SceneryName = tostring(SceneryName)
self.SceneryObject = SceneryObject self.SceneryObject = SceneryObject
@ -52,9 +53,43 @@ function SCENERY:Register( SceneryName, SceneryObject )
else else
self.Life0 = 0 self.Life0 = 0
end end
self.Properties = {}
return self return self
end end
--- Returns the Value of the zone with the given PropertyName, or nil if no matching property exists.
-- @param #SCENERY self
-- @param #string PropertyName The name of a the QuadZone Property from the scenery assignment to be retrieved.
-- @return #string The Value of the QuadZone Property from the scenery assignment with the given PropertyName, or nil if absent.
function SCENERY:GetProperty(PropertyName)
return self.Properties[PropertyName]
end
--- Returns the scenery Properties table.
-- @param #SCENERY self
-- @return #table The Key:Value table of QuadZone properties of the zone from the scenery assignment .
function SCENERY:GetAllProperties()
return self.Properties
end
--- Set a scenery property
-- @param #SCENERY self
-- @param #string PropertyName
-- @param #string PropertyValue
-- @return #SCENERY self
function SCENERY:SetProperty(PropertyName, PropertyValue)
self.Properties[PropertyName] = PropertyValue
return self
end
--- Obtain object name.
--@param #SCENERY self
--@return #string Name
function SCENERY:GetName()
return self.SceneryName
end
--- Obtain DCS Object from the SCENERY Object. --- Obtain DCS Object from the SCENERY Object.
--@param #SCENERY self --@param #SCENERY self
--@return DCS#Object DCS scenery object. --@return DCS#Object DCS scenery object.
@ -115,26 +150,28 @@ end
--@param Core.Point#COORDINATE Coordinate Where to find the scenery object --@param Core.Point#COORDINATE Coordinate Where to find the scenery object
--@param #number Radius (optional) Search radius around coordinate, defaults to 100 --@param #number Radius (optional) Search radius around coordinate, defaults to 100
--@return #SCENERY Scenery Object or `nil` if it cannot be found --@return #SCENERY Scenery Object or `nil` if it cannot be found
function SCENERY:FindByName(Name, Coordinate, Radius) function SCENERY:FindByName(Name, Coordinate, Radius, Role)
local radius = Radius or 100 local radius = Radius or 100
local name = Name or "unknown" local name = Name or "unknown"
local scenery = nil local scenery = nil
BASE:T({name, radius, Coordinate:GetVec2()})
--- ---
-- @param Core.Point#COORDINATE coordinate -- @param Core.Point#COORDINATE coordinate
-- @param #number radius -- @param #number radius
-- @param #string name -- @param #string name
local function SceneryScan(coordinate, radius, name) local function SceneryScan(scoordinate, sradius, sname)
if coordinate ~= nil then if scoordinate ~= nil then
local scenerylist = coordinate:ScanScenery(radius) local Vec2 = scoordinate:GetVec2()
local rscenery = nil local scanzone = ZONE_RADIUS:New("Zone-"..sname,Vec2,sradius,true)
for _,_scenery in pairs(scenerylist) do scanzone:Scan({Object.Category.SCENERY})
local scanned = scanzone:GetScannedSceneryObjects()
local rscenery = nil -- Wrapper.Scenery#SCENERY
for _,_scenery in pairs(scanned) do
local scenery = _scenery -- Wrapper.Scenery#SCENERY local scenery = _scenery -- Wrapper.Scenery#SCENERY
if tostring(scenery.SceneryName) == tostring(name) then if tostring(scenery.SceneryName) == tostring(sname) then
rscenery = scenery rscenery = scenery
if Role then rscenery:SetProperty("ROLE",Role) end
break break
end end
end end
@ -144,6 +181,7 @@ function SCENERY:FindByName(Name, Coordinate, Radius)
end end
if Coordinate then if Coordinate then
--BASE:I("Coordinate Scenery Scan")
scenery = SceneryScan(Coordinate, radius, name) scenery = SceneryScan(Coordinate, radius, name)
end end
@ -154,7 +192,7 @@ end
-- to find the correct object. -- to find the correct object.
--@param #SCENERY self --@param #SCENERY self
--@param #string Name The name or id of the scenery object as taken from the ME. Ex. '595785449' --@param #string Name The name or id of the scenery object as taken from the ME. Ex. '595785449'
--@param Core.Zone#ZONE Zone Where to find the scenery object. Can be handed as zone name. --@param Core.Zone#ZONE_BASE Zone Where to find the scenery object. Can be handed as zone name.
--@param #number Radius (optional) Search radius around coordinate, defaults to 100 --@param #number Radius (optional) Search radius around coordinate, defaults to 100
--@return #SCENERY Scenery Object or `nil` if it cannot be found --@return #SCENERY Scenery Object or `nil` if it cannot be found
function SCENERY:FindByNameInZone(Name, Zone, Radius) function SCENERY:FindByNameInZone(Name, Zone, Radius)
@ -164,7 +202,7 @@ function SCENERY:FindByNameInZone(Name, Zone, Radius)
Zone = ZONE:FindByName(Zone) Zone = ZONE:FindByName(Zone)
end end
local coordinate = Zone:GetCoordinate() local coordinate = Zone:GetCoordinate()
return self:FindByName(Name,coordinate,Radius) return self:FindByName(Name,coordinate,Radius,Zone:GetProperty("ROLE"))
end end
--- Find a SCENERY object from its zone name. Since SCENERY isn't registered in the Moose database (just too many objects per map), we need to do a scan first --- Find a SCENERY object from its zone name. Since SCENERY isn't registered in the Moose database (just too many objects per map), we need to do a scan first
@ -173,38 +211,34 @@ end
--@param #string ZoneName The name of the scenery zone as created with a right-click on the map in the mission editor and select "assigned to...". Can be handed over as ZONE object. --@param #string ZoneName The name of the scenery zone as created with a right-click on the map in the mission editor and select "assigned to...". Can be handed over as ZONE object.
--@return #SCENERY First found Scenery Object or `nil` if it cannot be found --@return #SCENERY First found Scenery Object or `nil` if it cannot be found
function SCENERY:FindByZoneName( ZoneName ) function SCENERY:FindByZoneName( ZoneName )
local zone = ZoneName -- Core.Zone#ZONE local zone = ZoneName -- Core.Zone#ZONE_BASE
if type(ZoneName) == "string" then if type(ZoneName) == "string" then
zone = ZONE:FindByName(ZoneName) zone = ZONE:FindByName(ZoneName) -- Core.Zone#ZONE_POLYGON
end end
local _id = zone:GetProperty('OBJECT ID') local _id = zone:GetProperty('OBJECT ID')
BASE:T("Object ID ".._id) --local properties = zone:GetAllProperties() or {}
--BASE:I(string.format("Object ID is: %s",_id or "none"))
--BASE:T("Object ID ".._id)
if not _id then if not _id then
-- this zone has no object ID -- this zone has no object ID
BASE:E("**** Zone without object ID: "..ZoneName.." | Type: "..tostring(zone.ClassName)) BASE:E("**** Zone without object ID: "..ZoneName.." | Type: "..tostring(zone.ClassName))
if string.find(zone.ClassName,"POLYGON") then if string.find(zone.ClassName,"POLYGON") then
zone:Scan({Object.Category.SCENERY}) zone:Scan({Object.Category.SCENERY})
local scanned = zone:GetScannedScenery() local scanned = zone:GetScannedSceneryObjects()
for _,_scenery in (scanned) do for _,_scenery in (scanned) do
local scenery = _scenery -- Wrapper.Scenery#SCENERY local scenery = _scenery -- Wrapper.Scenery#SCENERY
if scenery:IsAlive() then if scenery:IsAlive() then
local role = zone:GetProperty("ROLE")
if role then scenery:SetProperty("ROLE",role) end
return scenery return scenery
end end
end end
return nil return nil
else else
local coordinate = zone:GetCoordinate() return self:FindByName(_id, zone:GetCoordinate(),nil,zone:GetProperty("ROLE"))
local scanned = coordinate:ScanScenery()
for _,_scenery in (scanned) do
local scenery = _scenery -- Wrapper.Scenery#SCENERY
if scenery:IsAlive() then
return scenery
end
end
return nil
end end
else else
return self:FindByName(_id, zone:GetCoordinate()) return self:FindByName(_id, zone:GetCoordinate(),nil,zone:GetProperty("ROLE"))
end end
end end
@ -219,6 +253,7 @@ function SCENERY:FindAllByZoneName( ZoneName )
zone = ZONE:FindByName(ZoneName) zone = ZONE:FindByName(ZoneName)
end end
local _id = zone:GetProperty('OBJECT ID') local _id = zone:GetProperty('OBJECT ID')
--local properties = zone:GetAllProperties() or {}
if not _id then if not _id then
-- this zone has no object ID -- this zone has no object ID
--BASE:E("**** Zone without object ID: "..ZoneName.." | Type: "..tostring(zone.ClassName)) --BASE:E("**** Zone without object ID: "..ZoneName.." | Type: "..tostring(zone.ClassName))
@ -230,7 +265,7 @@ function SCENERY:FindAllByZoneName( ZoneName )
return nil return nil
end end
else else
local obj = self:FindByName(_id, zone:GetCoordinate()) local obj = self:FindByName(_id, zone:GetCoordinate(),nil,zone:GetProperty("ROLE"))
if obj then if obj then
return {obj} return {obj}
else else