diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index e3cd263c4..973090bb7 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -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 diff --git a/Moose Development/Moose/Wrapper/Scenery.lua b/Moose Development/Moose/Wrapper/Scenery.lua index 24dc45fd6..3c697579c 100644 --- a/Moose Development/Moose/Wrapper/Scenery.lua +++ b/Moose Development/Moose/Wrapper/Scenery.lua @@ -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