#SCENERY, SET_SCENERY

* Reworked COORDINATE scan as this doesn't seem to work
* Added SET_SCENERY Filters, and FilterOnce() to apply them
This commit is contained in:
Applevangelist 2023-08-01 16:18:23 +02:00
parent 7c4dd8160d
commit 2771e7f856
2 changed files with 161 additions and 37 deletions

View File

@ -243,7 +243,7 @@ do -- SET_BASE
function SET_BASE:Add( ObjectName, Object )
-- 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
if self.Set[ObjectName] then
@ -258,6 +258,8 @@ do -- SET_BASE
-- Trigger Added event.
self:Added( ObjectName, Object )
return self
end
--- Adds a @{Core.Base#BASE} object in the @{Core.Set#SET_BASE}, using the Object Name as the index.
@ -1949,7 +1951,7 @@ do
if self.Filter.Zones then
local MGroupZone = false
for ZoneName, Zone in pairs( self.Filter.Zones ) do
--self:I( "Zone:", ZoneName )
--self:T( "Zone:", ZoneName )
if MGroup:IsInZone(Zone) then
MGroupZone = true
end
@ -4466,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
MClientActive = true
end
--self:I( { "Evaluated Active", MClientActive } )
--self:T( { "Evaluated Active", MClientActive } )
MClientInclude = MClientInclude and MClientActive
end
@ -4548,7 +4550,7 @@ do -- SET_CLIENT
if self.Filter.Playernames then
local MClientPlayername = false
local playername = MClient:GetPlayerName() or "Unknown"
--self:I(playername)
--self:T(playername)
for _,_Playername in pairs(self.Filter.Playernames) do
if playername and string.find(playername,_Playername) then
MClientPlayername = true
@ -4561,7 +4563,7 @@ do -- SET_CLIENT
if self.Filter.Callsigns then
local MClientCallsigns = false
local callsign = MClient:GetCallsign()
--self:I(callsign)
--self:T(callsign)
for _,_Callsign in pairs(self.Filter.Callsigns) do
if callsign and string.find(callsign,_Callsign) then
MClientCallsigns = true
@ -7585,6 +7587,7 @@ do -- SET_SCENERY
Scenerys = {},
Filter = {
SceneryPrefixes = nil,
SceneryRoles = nil,
Zones = nil,
},
}
@ -7607,7 +7610,7 @@ do -- SET_SCENERY
if ZoneSet then
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())
end
self:AddSceneryByName(zonenames)
@ -7701,6 +7704,7 @@ do -- SET_SCENERY
end
for _,Zone in pairs( zones ) do
local zonename = Zone:GetName()
self:T(zonename)
self.Filter.Zones[zonename] = Zone
end
return self
@ -7719,11 +7723,30 @@ do -- SET_SCENERY
Prefixes = { Prefixes }
end
for PrefixID, Prefix in pairs( Prefixes ) do
--self:T(Prefix)
self.Filter.SceneryPrefixes[Prefix] = Prefix
end
return self
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.
-- @param #SET_SCENERY self
-- @return #number The number of SCENERYSs alive.
@ -7816,10 +7839,76 @@ do -- SET_SCENERY
-- @param Wrapper.Scenery#SCENERY MScenery
-- @return #SET_SCENERY self
function SET_SCENERY:IsIncludeObject( MScenery )
self:F2( MScenery )
return true
self:T( MScenery.SceneryName )
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
--- 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.
-- @param #SET_SCENERY self
-- @return #number LIfe0Points

View File

@ -9,7 +9,7 @@
-- ===
--
-- @module Wrapper.Scenery
-- @image Wrapper_Scenery.JPG
-- @image Wrapper_Scenery.JPG+
--- SCENERY Class
@ -18,6 +18,7 @@
-- @field #string SceneryName Name of the scenery object.
-- @field DCS#Object SceneryObject DCS scenery object.
-- @field #number Life0 Initial life points.
-- @field #table Properties
-- @extends Wrapper.Positionable#POSITIONABLE
@ -43,7 +44,7 @@ function SCENERY:Register( SceneryName, SceneryObject )
local self = BASE:Inherit( self, POSITIONABLE:New( SceneryName ) )
self.SceneryName = SceneryName
self.SceneryName = tostring(SceneryName)
self.SceneryObject = SceneryObject
@ -52,9 +53,43 @@ function SCENERY:Register( SceneryName, SceneryObject )
else
self.Life0 = 0
end
self.Properties = {}
return self
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.
--@param #SCENERY self
--@return DCS#Object DCS scenery object.
@ -115,26 +150,28 @@ end
--@param Core.Point#COORDINATE Coordinate Where to find the scenery object
--@param #number Radius (optional) Search radius around coordinate, defaults to 100
--@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 name = Name or "unknown"
local scenery = nil
BASE:T({name, radius, Coordinate:GetVec2()})
---
-- @param Core.Point#COORDINATE coordinate
-- @param #number radius
-- @param #string name
local function SceneryScan(coordinate, radius, name)
if coordinate ~= nil then
local scenerylist = coordinate:ScanScenery(radius)
local rscenery = nil
for _,_scenery in pairs(scenerylist) do
local function SceneryScan(scoordinate, sradius, sname)
if scoordinate ~= nil then
local Vec2 = scoordinate:GetVec2()
local scanzone = ZONE_RADIUS:New("Zone-"..sname,Vec2,sradius,true)
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
if tostring(scenery.SceneryName) == tostring(name) then
if tostring(scenery.SceneryName) == tostring(sname) then
rscenery = scenery
if Role then rscenery:SetProperty("ROLE",Role) end
break
end
end
@ -144,6 +181,7 @@ function SCENERY:FindByName(Name, Coordinate, Radius)
end
if Coordinate then
--BASE:I("Coordinate Scenery Scan")
scenery = SceneryScan(Coordinate, radius, name)
end
@ -154,7 +192,7 @@ end
-- to find the correct object.
--@param #SCENERY self
--@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
--@return #SCENERY Scenery Object or `nil` if it cannot be found
function SCENERY:FindByNameInZone(Name, Zone, Radius)
@ -164,7 +202,7 @@ function SCENERY:FindByNameInZone(Name, Zone, Radius)
Zone = ZONE:FindByName(Zone)
end
local coordinate = Zone:GetCoordinate()
return self:FindByName(Name,coordinate,Radius)
return self:FindByName(Name,coordinate,Radius,Zone:GetProperty("ROLE"))
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
@ -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.
--@return #SCENERY First found Scenery Object or `nil` if it cannot be found
function SCENERY:FindByZoneName( ZoneName )
local zone = ZoneName -- Core.Zone#ZONE
local zone = ZoneName -- Core.Zone#ZONE_BASE
if type(ZoneName) == "string" then
zone = ZONE:FindByName(ZoneName)
zone = ZONE:FindByName(ZoneName) -- Core.Zone#ZONE_POLYGON
end
local _id = zone:GetProperty('OBJECT 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
-- this zone has no object ID
BASE:E("**** Zone without object ID: "..ZoneName.." | Type: "..tostring(zone.ClassName))
if string.find(zone.ClassName,"POLYGON") then
zone:Scan({Object.Category.SCENERY})
local scanned = zone:GetScannedScenery()
local scanned = zone:GetScannedSceneryObjects()
for _,_scenery in (scanned) do
local scenery = _scenery -- Wrapper.Scenery#SCENERY
if scenery:IsAlive() then
local role = zone:GetProperty("ROLE")
if role then scenery:SetProperty("ROLE",role) end
return scenery
end
end
return nil
else
local coordinate = zone:GetCoordinate()
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
return self:FindByName(_id, zone:GetCoordinate(),nil,zone:GetProperty("ROLE"))
end
else
return self:FindByName(_id, zone:GetCoordinate())
return self:FindByName(_id, zone:GetCoordinate(),nil,zone:GetProperty("ROLE"))
end
end
@ -219,6 +253,7 @@ function SCENERY:FindAllByZoneName( ZoneName )
zone = ZONE:FindByName(ZoneName)
end
local _id = zone:GetProperty('OBJECT ID')
--local properties = zone:GetAllProperties() or {}
if not _id then
-- this zone has no object ID
--BASE:E("**** Zone without object ID: "..ZoneName.." | Type: "..tostring(zone.ClassName))
@ -230,7 +265,7 @@ function SCENERY:FindAllByZoneName( ZoneName )
return nil
end
else
local obj = self:FindByName(_id, zone:GetCoordinate())
local obj = self:FindByName(_id, zone:GetCoordinate(),nil,zone:GetProperty("ROLE"))
if obj then
return {obj}
else