diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index e80f36558..5cf5bf666 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -309,7 +309,7 @@ do -- Zones self:I(string.format("Register ZONE: %s (Polygon, Quad)", ZoneName)) - Zone=ZONE_POLYGON_BASE:New(ZoneName, ZoneData.verticies) + Zone=ZONE_POLYGON:NewFromPointsArray(ZoneName, ZoneData.verticies) --for i,vec2 in pairs(ZoneData.verticies) do -- local coord=COORDINATE:NewFromVec2(vec2) diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index 5112de2c0..5df1d0413 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -6792,20 +6792,36 @@ do -- SET_SCENERY -- mysceneryset = SET_SCENERY:New(ZoneSet) function SET_SCENERY:New(ZoneSet) - local zoneset = {} - -- Inherits from BASE - local self = BASE:Inherit( self, SET_BASE:New( zoneset ) ) -- Core.Set#SET_SCENERY - - local zonenames = {} - for _,_zone in pairs(ZoneSet.Set) do - table.insert(zonenames,_zone:GetName()) + local zoneset = {} + -- Inherits from BASE + local self = BASE:Inherit( self, SET_BASE:New( zoneset ) ) -- Core.Set#SET_SCENERY + + local zonenames = {} + + if ZoneSet then + for _,_zone in pairs(ZoneSet.Set) do + --self:I("Zone type handed: "..tostring(_zone.ClassName)) + table.insert(zonenames,_zone:GetName()) + end + self:AddSceneryByName(zonenames) + end + + return self end - self:AddSceneryByName(zonenames) - - return self + --- Creates a new SET_SCENERY object. Scenery is **not** auto-registered in the Moose database, there are too many objects on each map. Hence we need to find them first. For this we scan the zone. + -- @param #SET_SCENERY self + -- @param Core.Zone#ZONE Zone The zone to be scanned. Can be a ZONE_RADIUS (round) or a ZONE_POLYGON (e.g. Quad-Point) + -- @return #SET_SCENERY + function SET_SCENERY:NewFromZone(Zone) + local zone = Zone -- Core.Zone#ZONE_POLYGON + if type(Zone) == "string" then + zone = ZONE:FindByName(Zone) + end + zone:Scan({Object.Category.SCENERY}) + return zone:GetScannedSetScenery() end - + --- Add SCENERY(s) to SET_SCENERY. -- @param #SET_SCENERY self -- @param #string AddScenery A single SCENERY. diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua index d19725683..651bc1941 100644 --- a/Moose Development/Moose/Core/Zone.lua +++ b/Moose Development/Moose/Core/Zone.lua @@ -934,6 +934,7 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories ) self.ScanData = {} self.ScanData.Coalitions = {} self.ScanData.Scenery = {} + self.ScanData.SceneryTable = {} self.ScanData.Units = {} local ZoneCoord = self:GetCoordinate() @@ -996,8 +997,10 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories ) if ObjectCategory == Object.Category.SCENERY then local SceneryType = ZoneObject:getTypeName() local SceneryName = ZoneObject:getName() + --BASE:I("SceneryType "..SceneryType.."SceneryName"..SceneryName) self.ScanData.Scenery[SceneryType] = self.ScanData.Scenery[SceneryType] or {} self.ScanData.Scenery[SceneryType][SceneryName] = SCENERY:Register( SceneryName, ZoneObject ) + table.insert(self.ScanData.SceneryTable,self.ScanData.Scenery[SceneryType][SceneryName] ) self:T( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } ) end @@ -1137,11 +1140,29 @@ end --- Get scanned scenery table -- @param #ZONE_RADIUS self --- @return #table Table of DCS scenery objects. +-- @return #table Structured object table: [type].[name].SCENERY function ZONE_RADIUS:GetScannedScenery() return self.ScanData.Scenery end +--- Get table of scanned scenery objects +-- @param #ZONE_RADIUS self +-- @return #table Table of SCENERY objects. +function ZONE_RADIUS:GetScannedSceneryObjects() + return self.ScanData.SceneryTable +end + +--- Get set of scanned scenery objects +-- @param #ZONE_RADIUS self +-- @return #table Table of Wrapper.Scenery#SCENERY scenery objects. +function ZONE_RADIUS:GetScannedSetScenery() + local scenery = SET_SCENERY:New() + local objects = self:GetScannedSceneryObjects() + for _,_obj in pairs (objects) do + scenery:AddScenery(_obj) + end + return scenery +end --- Is All in Zone of Coalition? -- Check if only the specifed coalition is inside the zone and noone else. @@ -2326,7 +2347,7 @@ function ZONE_POLYGON_BASE:Boundary(Coalition, Color, Radius, Alpha, Segments, C for Segment = 0, Segments do local PointX = self._.Polygon[i].x + ( Segment * DeltaX / Segments ) local PointY = self._.Polygon[i].y + ( Segment * DeltaY / Segments ) - ZONE_RADIUS:New( "Zone", {x = PointX, y = PointY}, Radius, true ):DrawZone(Coalition, Color, 1, Color, Alpha, nil, false) + --ZONE_RADIUS:New( "Zone", {x = PointX, y = PointY}, Radius ):DrawZone(Coalition, Color, 1, Color, Alpha, nil, true) end end j = i @@ -2452,14 +2473,28 @@ function ZONE_POLYGON:Scan( ObjectCategories, UnitCategories ) self.ScanData = {} self.ScanData.Coalitions = {} self.ScanData.Scenery = {} + self.ScanData.SceneryTable = {} self.ScanData.Units = {} - + + local vectors = self:GetBoundingSquare() + + local minVec3 = {x=vectors.x1, y=0, z=vectors.y1} + local maxVec3 = {x=vectors.x2, y=0, z=vectors.y2} + + local VolumeBox = { + id = world.VolumeType.BOX, + params = { + min = minVec3, + max = maxVec3 + } + } + local function EvaluateZone( ZoneObject ) if ZoneObject then local ObjectCategory = ZoneObject:getCategory() - + if ( ObjectCategory == Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive() ) or (ObjectCategory == Object.Category.STATIC and ZoneObject:isExist()) then local CoalitionDCSUnit = ZoneObject:getCoalition() @@ -2494,16 +2529,16 @@ function ZONE_POLYGON:Scan( ObjectCategories, UnitCategories ) end end - --[[ - -- no scenery possible at the moment + -- trying with box search if ObjectCategory == Object.Category.SCENERY then local SceneryType = ZoneObject:getTypeName() local SceneryName = ZoneObject:getName() self.ScanData.Scenery[SceneryType] = self.ScanData.Scenery[SceneryType] or {} self.ScanData.Scenery[SceneryType][SceneryName] = SCENERY:Register( SceneryName, ZoneObject ) + table.insert(self.ScanData.SceneryTable,self.ScanData.Scenery[SceneryType][SceneryName]) self:T( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } ) end - --]] + end return true @@ -2529,6 +2564,18 @@ function ZONE_POLYGON:Scan( ObjectCategories, UnitCategories ) end ) + local searchscenery = false + for _,_type in pairs(ObjectCategories) do + if _type == Object.Category.SCENERY then + searchscenery = true + end + end + + if searchscenery then + -- Search objects. + world.searchObjects({Object.Category.SCENERY}, VolumeBox, EvaluateZone ) + end + end --- Count the number of different coalitions inside the zone. @@ -2643,20 +2690,39 @@ function ZONE_POLYGON:GetScannedCoalition( Coalition ) end end ---- Get scanned scenery type (currently not implemented in ZONE_POLYGON) +--- Get scanned scenery types -- @param #ZONE_POLYGON self -- @return #table Table of DCS scenery type objects. function ZONE_POLYGON:GetScannedSceneryType( SceneryType ) return self.ScanData.Scenery[SceneryType] end ---- Get scanned scenery table (currently not implemented in ZONE_POLYGON) +--- Get scanned scenery table -- @param #ZONE_POLYGON self --- @return #table Table of DCS scenery objects. +-- @return #table Table of Wrapper.Scenery#SCENERY scenery objects. +function ZONE_POLYGON:GetScannedSceneryObjects() + return self.ScanData.SceneryTable +end + +--- Get scanned scenery table +-- @param #ZONE_POLYGON self +-- @return #table Structured table of [type].[name].Wrapper.Scenery#SCENERY scenery objects. function ZONE_POLYGON:GetScannedScenery() return self.ScanData.Scenery end +--- Get scanned set of scenery objects +-- @param #ZONE_POLYGON self +-- @return #table Table of Wrapper.Scenery#SCENERY scenery objects. +function ZONE_POLYGON:GetScannedSetScenery() + local scenery = SET_SCENERY:New() + local objects = self:GetScannedSceneryObjects() + for _,_obj in pairs (objects) do + scenery:AddScenery(_obj) + end + return scenery +end + --- Is All in Zone of Coalition? -- Check if only the specifed coalition is inside the zone and noone else. -- @param #ZONE_POLYGON self diff --git a/Moose Development/Moose/Wrapper/Scenery.lua b/Moose Development/Moose/Wrapper/Scenery.lua index 9b0871960..4cd321063 100644 --- a/Moose Development/Moose/Wrapper/Scenery.lua +++ b/Moose Development/Moose/Wrapper/Scenery.lua @@ -159,12 +159,69 @@ end -- to find the correct object. --@param #SCENERY self --@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 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 ) - local zone = ZoneName + local zone = ZoneName -- Core.Zone#ZONE if type(ZoneName) == "string" then - zone = ZONE:FindByName(ZoneName) + zone = ZONE:FindByName(ZoneName) end local _id = zone:GetProperty('OBJECT ID') - return self:FindByName(_id, zone:GetCoordinate()) + 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() + for _,_scenery in (scanned) do + local scenery = _scenery -- Wrapper.Scenery#SCENERY + if scenery:IsAlive() then + 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 + end + else + return self:FindByName(_id, zone:GetCoordinate()) + end +end + +--- Scan and find all SCENERY objects from a zone by zone-name. Since SCENERY isn't registered in the Moose database (just too many objects per map), we need to do a scan first +-- to find the correct object. +--@param #SCENERY self +--@param #string ZoneName The name of the zone, can be handed as ZONE_RADIUS or ZONE_POLYGON object +--@return #table of SCENERY Objects, or `nil` if nothing found +function SCENERY:FindAllByZoneName( ZoneName ) + local zone = ZoneName -- Core.Zone#ZONE_RADIUS + if type(ZoneName) == "string" then + zone = ZONE:FindByName(ZoneName) + end + local _id = zone:GetProperty('OBJECT ID') + if not _id then + -- this zone has no object ID + --BASE:E("**** Zone without object ID: "..ZoneName.." | Type: "..tostring(zone.ClassName)) + zone:Scan({Object.Category.SCENERY}) + local scanned = zone:GetScannedSceneryObjects() + if #scanned > 0 then + return scanned + else + return nil + end + else + local obj = self:FindByName(_id, zone:GetCoordinate()) + if obj then + return {obj} + else + return nil + end + end end