* Added `ZONE_RADIUS:GetRandomCoordinateWithoutBuildings(...)`

#MARKEROPS
* Some documentation improvement

#PLAYTASKCONTROLLER
* Added `PLAYERTASKCONTROLLER:EnableMarkerOps(Tag)`

#OPSGROUP
* Changed offset to 2m for lasing ground units

*AUFTRAG
* Documentation correction `NewARMOREDGUARD`
This commit is contained in:
Applevangelist 2022-08-30 14:26:52 +02:00
parent 23815429e2
commit b4e2d3edfe
5 changed files with 124 additions and 13 deletions

View File

@ -123,7 +123,7 @@ function MARKEROPS_BASE:New(Tagname,Keywords)
end
--- (internal) Handle events.
-- @param #MARKEROPS self
-- @param #MARKEROPS_BASE self
-- @param Core.Event#EVENTDATA Event
function MARKEROPS_BASE:OnEventMark(Event)
self:T({Event})
@ -173,7 +173,7 @@ function MARKEROPS_BASE:OnEventMark(Event)
end
--- (internal) Match tag.
-- @param #MARKEROPS self
-- @param #MARKEROPS_BASE self
-- @param #string Eventtext Text added to the marker.
-- @return #boolean
function MARKEROPS_BASE:_MatchTag(Eventtext)
@ -186,7 +186,7 @@ function MARKEROPS_BASE:_MatchTag(Eventtext)
end
--- (internal) Match keywords table.
-- @param #MARKEROPS self
-- @param #MARKEROPS_BASE self
-- @param #string Eventtext Text added to the marker.
-- @return #table
function MARKEROPS_BASE:_MatchKeywords(Eventtext)

View File

@ -970,7 +970,7 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories )
local SceneryName = ZoneObject:getName()
self.ScanData.Scenery[SceneryType] = self.ScanData.Scenery[SceneryType] or {}
self.ScanData.Scenery[SceneryType][SceneryName] = SCENERY:Register( SceneryName, ZoneObject )
self:F2( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } )
self:T( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } )
end
end
@ -1373,7 +1373,86 @@ function ZONE_RADIUS:GetRandomCoordinate(inner, outer, surfacetypes)
return Coordinate
end
--- Returns a @{Core.Point#COORDINATE} object reflecting a random location within the zone where there are no **map objects** of type "Building".
-- Does not find statics you might have placed there. **Note** This might be quite CPU intensive, use with care.
-- @param #ZONE_RADIUS self
-- @param #number inner (Optional) Minimal distance from the center of the zone in meters. Default is 0m.
-- @param #number outer (Optional) Maximal distance from the outer edge of the zone in meters. Default is the radius of the zone.
-- @param #number distance (Optional) Minumum distance from any building coordinate. Defaults to 100m.
-- @param #boolean markbuildings (Optional) Place markers on found buildings (if any).
-- @param #boolean markfinal (Optional) Place marker on the final coordinate (if any).
-- @return Core.Point#COORDINATE The random coordinate or `nil` if cannot be found in 1000 iterations.
function ZONE_RADIUS:GetRandomCoordinateWithoutBuildings(inner,outer,distance,markbuildings,markfinal)
local dist = distance or 100
local objects = {}
if self.ScanData and self.ScanData.Scenery then
objects = self:GetScannedScenery()
else
self:Scan({Object.Category.SCENERY})
objects = self:GetScannedScenery()
end
local T0 = timer.getTime()
local T1 = timer.getTime()
local buildings = {}
if self.ScanData and self.ScanData.BuildingCoordinates then
buildings = self.ScanData.BuildingCoordinates
else
-- build table of buildings coordinates
for _,_object in pairs (objects) do
for _,_scen in pairs (_object) do
local scenery = _scen -- Wrapper.Scenery#SCENERY
local description=scenery:GetDesc()
if description and description.attributes and description.attributes.Buildings then
if markbuildings then
MARKER:New(scenery:GetCoordinate(),"Building"):ToAll()
end
buildings[#buildings+1] = scenery:GetCoordinate()
end
end
end
self.ScanData.BuildingCoordinates = buildings
end
-- max 1000 tries
local rcoord = nil
local found = false
local iterations = 0
for i=1,1000 do
iterations = iterations + 1
rcoord = self:GetRandomCoordinate(inner,outer)
found = false
for _,_coord in pairs (buildings) do
local coord = _coord -- Core.Point#COORDINATE
-- keep >50m dist from buildings
if coord:Get2DDistance(rcoord) > dist then
found = true
else
found = false
end
end
if found then
-- we have a winner!
if markfinal then
MARKER:New(rcoord,"FREE"):ToAll()
end
break
end
end
T1=timer.getTime()
self:T(string.format("Found a coordinate: %s | Iterations: %d | Time: %d",tostring(found),iterations,T1-T0))
if found then return rcoord else return nil end
end
--- @type ZONE
-- @extends #ZONE_RADIUS

View File

@ -2185,7 +2185,7 @@ end
--- **[GROUND]** Create an ARMORED ON GUARD mission.
-- @param #AUFTRAG self
-- @param Core.Point#COORDINATE Coordinate Coordinate, where to stand guard.
-- @param #string Formation Formation to take, e.g. "on Road", "Vee" etc.
-- @param #string Formation Formation to take, e.g. "On Road", "Vee" etc.
-- @return #AUFTRAG self
function AUFTRAG:NewARMOREDGUARD(Coordinate,Formation)

View File

@ -6421,7 +6421,7 @@ function OPSGROUP:onbeforeLaserOn(From, Event, To, Target)
self.spot.element=element
-- Height offset. No offset for aircraft. We take the height for ground or naval.
local offsetY=0
local offsetY=2 --2m for ARMYGROUP, else there might be no LOS
if self.isFlightgroup or self.isNavygroup then
offsetY=element.height
end

View File

@ -703,6 +703,7 @@ do
-- @field #string locale
-- @field #boolean precisionbombing
-- @field Ops.FlightGroup#FLIGHTGROUP LasingDrone
-- @field Core.MarkerOps_BASE#MARKEROPS_BASE MarkerOps
-- @extends Core.Fsm#FSM
---
@ -1324,6 +1325,37 @@ function PLAYERTASKCONTROLLER:EnablePrecisionBombing(FlightGroup,LaserCode)
return self
end
--- [User] Allow addition of targets with user F10 map markers.
-- @param #PLAYERTASKCONTROLLER self
-- @param #string Tag (Optional) The tagname to use to identify commands, defaults to "TASK"
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:EnableMarkerOps(Tag)
self:T(self.lid.."EnableMarkerOps")
local tag = Tag or "TASK"
local MarkerOps = MARKEROPS_BASE:New(tag)
local function Handler(Keywords,Coord,Text)
if self.verbose then
local m = MESSAGE:New(string.format("Target added from marker at: %s", Coord:ToStringLLDMS()),15,"INFO"):ToAll()
end
self:AddTarget(Coord)
end
-- Event functions
function MarkerOps:OnAfterMarkAdded(From,Event,To,Text,Keywords,Coord)
Handler(Keywords,Coord,Text)
end
function MarkerOps:OnAfterMarkChanged(From,Event,To,Text,Keywords,Coord)
Handler(Keywords,Coord,Text)
end
self.MarkerOps = MarkerOps
return self
end
--- [Internal] Get player name
-- @param #PLAYERTASKCONTROLLER self
-- @param Wrapper.Client#CLIENT Client
@ -1595,7 +1627,7 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
if self.LasingDrone and self.LasingDrone:IsAlive() then
if self.LasingDrone.playertask and (not self.LasingDrone.playertask.busy) then
-- not busy, get a task
self:I(self.lid.."Sending lasing unit to target")
self:T(self.lid.."Sending lasing unit to target")
local task = self.PrecisionTasks:Pull() -- Ops.PlayerTask#PLAYERTASK
self.LasingDrone.playertask.id = task.PlayerTaskNr
self.LasingDrone.playertask.busy = true
@ -1612,7 +1644,7 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
local tgtzone = ZONE_RADIUS:New("ArmyGroup-"..math.random(1,10000),tgtcoord:GetVec2(),3000)
local finalpos=nil -- Core.Point#COORDINATE
for i=1,50 do
finalpos = tgtzone:GetRandomCoordinate(2000,0,{land.SurfaceType.LAND,land.SurfaceType.ROAD,land.SurfaceType.SHALLOW_WATER})
finalpos = tgtzone:GetRandomCoordinate(2500,0,{land.SurfaceType.LAND,land.SurfaceType.ROAD,land.SurfaceType.SHALLOW_WATER})
if finalpos then
if finalpos:IsLOS(tgtcoord,0) then
break
@ -1621,7 +1653,7 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
end
if finalpos then
-- yeah we got one
local auftrag = AUFTRAG:NewARMOREDGUARD(finalpos)
local auftrag = AUFTRAG:NewARMOREDGUARD(finalpos,"Off road")
local currmission = self.LasingDrone:GetMissionCurrent()
self.LasingDrone:AddMission(auftrag)
if currmission then currmission:__Cancel(-2) end
@ -1638,7 +1670,7 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
elseif self.LasingDrone.playertask and self.LasingDrone.playertask.busy then
-- drone is busy, set up laser when over target
local task = self.PrecisionTasks:ReadByID(self.LasingDrone.playertask.id) -- Ops.PlayerTask#PLAYERTASK
self:I("Looking at Task: "..task.PlayerTaskNr.." Type: "..task.Type.." State: "..task:GetState())
self:T("Looking at Task: "..task.PlayerTaskNr.." Type: "..task.Type.." State: "..task:GetState())
if (not task) or task:GetState() == "Done" or task:GetState() == "Stopped" then
-- we're done here
local task = self.PrecisionTasks:PullByID(self.LasingDrone.playertask.id) -- Ops.PlayerTask#PLAYERTASK
@ -1651,7 +1683,7 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
self.LasingDrone.playertask.inreach = false
self.LasingDrone.playertask.id = 0
self.LasingDrone.playertask.reachmessage = false
self:I(self.lid.."Laser Off")
self:T(self.lid.."Laser Off")
else
-- not done yet
local dcoord = self.LasingDrone:GetCoordinate()
@ -1659,7 +1691,7 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
local dist = dcoord:Get2DDistance(tcoord)
-- close enough?
if dist < 3000 and not self.LasingDrone:IsLasing() then
self:I(self.lid.."Laser On")
self:T(self.lid.."Laser On")
self.LasingDrone:__LaserOn(-1,tcoord)
self.LasingDrone.playertask.inreach = true
if not self.LasingDrone.playertask.reachmessage then