CAPTURE ZONE

This commit is contained in:
Frank
2019-12-26 23:20:55 +01:00
parent 389931fbf0
commit 8337058306
4 changed files with 248 additions and 188 deletions

View File

@@ -685,30 +685,44 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories )
local function EvaluateZone( ZoneObject )
--if ZoneObject:isExist() then --FF: isExist always returns false for SCENERY objects since DCS 2.2 and still in DCS 2.5
if ZoneObject then
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
if ( ObjectCategory == Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive() ) or (ObjectCategory == Object.Category.STATIC and ZoneObject:isExist()) then
local CoalitionDCSUnit = ZoneObject:getCoalition()
local Include = false
if not UnitCategories then
-- Anythink found is included.
Include = true
else
-- Check if found object is in specified categories.
local CategoryDCSUnit = ZoneObject:getDesc().category
for UnitCategoryID, UnitCategory in pairs( UnitCategories ) do
if UnitCategory == CategoryDCSUnit then
Include = true
break
end
end
end
if Include then
local CoalitionDCSUnit = ZoneObject:getCoalition()
-- This coalition is inside the zone.
self.ScanData.Coalitions[CoalitionDCSUnit] = true
self.ScanData.Units[ZoneObject] = ZoneObject
self:F2( { Name = ZoneObject:getName(), Coalition = CoalitionDCSUnit } )
end
end
if ObjectCategory == Object.Category.SCENERY then
local SceneryType = ZoneObject:getTypeName()
local SceneryName = ZoneObject:getName()
@@ -716,21 +730,29 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories )
self.ScanData.Scenery[SceneryType][SceneryName] = SCENERY:Register( SceneryName, ZoneObject )
self:F2( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } )
end
end
return true
end
-- Search objects.
world.searchObjects( ObjectCategories, SphereSearch, EvaluateZone )
end
--- Count the number of different coalitions inside the zone.
-- @param #ZONE_RADIUS self
-- @return #table Table of DCS units and DCS statics inside the zone.
function ZONE_RADIUS:GetScannedUnits()
return self.ScanData.Units
end
--- Count the number of different coalitions inside the zone.
-- @param #ZONE_RADIUS self
-- @return Core.Set#SET_UNIT Set of units and statics inside the zone.
function ZONE_RADIUS:GetScannedSetUnit()
local SetUnit = SET_UNIT:New()
@@ -756,6 +778,9 @@ function ZONE_RADIUS:GetScannedSetUnit()
end
--- Count the number of different coalitions inside the zone.
-- @param #ZONE_RADIUS self
-- @return #number Counted coalitions.
function ZONE_RADIUS:CountScannedCoalitions()
local Count = 0
@@ -763,14 +788,25 @@ function ZONE_RADIUS:CountScannedCoalitions()
for CoalitionID, Coalition in pairs( self.ScanData.Coalitions ) do
Count = Count + 1
end
return Count
end
--- Check if a certain coalition is inside a scanned zone.
-- @param #ZONE_RADIUS self
-- @param #number Coalition The coalition id, e.g. coalition.side.BLUE.
-- @return #boolean If true, the coalition is inside the zone.
function ZONE_RADIUS:CheckScannedCoalition( Coalition )
if Coalition then
return self.ScanData.Coalitions[Coalition]
end
return nil
end
--- Get Coalitions of the units in the Zone, or Check if there are units of the given Coalition in the Zone.
-- Returns nil if there are none ot two Coalitions in the zone!
-- Returns nil if there are none to two Coalitions in the zone!
-- Returns one Coalition if there are only Units of one Coalition in the Zone.
-- Returns the Coalition for the given Coalition if there are units of the Coalition in the Zone
-- Returns the Coalition for the given Coalition if there are units of the Coalition in the Zone.
-- @param #ZONE_RADIUS self
-- @return #table
function ZONE_RADIUS:GetScannedCoalition( Coalition )
@@ -795,20 +831,27 @@ function ZONE_RADIUS:GetScannedCoalition( Coalition )
end
--- Get scanned scenery type
-- @param #ZONE_RADIUS self
-- @return #table Table of DCS scenery type objects.
function ZONE_RADIUS:GetScannedSceneryType( SceneryType )
return self.ScanData.Scenery[SceneryType]
end
--- Get scanned scenery table
-- @param #ZONE_RADIUS self
-- @return #table Table of DCS scenery objects.
function ZONE_RADIUS:GetScannedScenery()
return self.ScanData.Scenery
end
--- Is All in Zone of Coalition?
-- Check if only the specifed coalition is inside the zone and noone else.
-- @param #ZONE_RADIUS self
-- @param Coalition
-- @return #boolean
-- @param #number Coalition Coalition ID of the coalition which is checked to be the only one in the zone.
-- @return #boolean True, if **only** that coalition is inside the zone and no one else.
-- @usage
-- self.Zone:Scan()
-- local IsGuarded = self.Zone:IsAllInZoneOfCoalition( self.Coalition )
@@ -820,11 +863,12 @@ end
--- Is All in Zone of Other Coalition?
-- Check if only one coalition is inside the zone and the specified coalition is not the one.
-- You first need to use the @{#ZONE_RADIUS.Scan} method to scan the zone before it can be evaluated!
-- Note that once a zone has been scanned, multiple evaluations can be done on the scan result set.
-- @param #ZONE_RADIUS self
-- @param Coalition
-- @return #boolean
-- @param #number Coalition Coalition ID of the coalition which is not supposed to be in the zone.
-- @return #boolean True, if and only if only one coalition is inside the zone and the specified coalition is not it.
-- @usage
-- self.Zone:Scan()
-- local IsCaptured = self.Zone:IsAllInZoneOfOtherCoalition( self.Coalition )
@@ -836,11 +880,12 @@ end
--- Is Some in Zone of Coalition?
-- Check if more than one coaltion is inside the zone and the specifed coalition is one of them.
-- You first need to use the @{#ZONE_RADIUS.Scan} method to scan the zone before it can be evaluated!
-- Note that once a zone has been scanned, multiple evaluations can be done on the scan result set.
-- @param #ZONE_RADIUS self
-- @param Coalition
-- @return #boolean
-- @param #number Coalition ID of the coaliton which is checked to be inside the zone.
-- @return #boolean True if more than one coalition is inside the zone and the specified coalition is one of them.
-- @usage
-- self.Zone:Scan()
-- local IsAttacked = self.Zone:IsSomeInZoneOfCoalition( self.Coalition )

View File

@@ -197,8 +197,7 @@ do -- ZONE_CAPTURE_COALITION
--
-- ### IMPORTANT
--
-- **Each capture zone object must have the monitoring process started specifically.
-- The monitoring process is NOT started by default!!!**
-- **Each capture zone object must have the monitoring process started specifically. The monitoring process is NOT started by default!**
--
--
-- # Full Example
@@ -554,175 +553,7 @@ do -- ZONE_CAPTURE_COALITION
return self
end
--- @param #ZONE_CAPTURE_COALITION self
function ZONE_CAPTURE_COALITION:onenterCaptured()
self:F({"hello"})
self:GetParent( self, ZONE_CAPTURE_COALITION ).onenterCaptured( self )
self.Goal:Achieved()
end
function ZONE_CAPTURE_COALITION:IsGuarded()
local IsGuarded = self:IsAllInZoneOfCoalition( self.Coalition )
self:F( { IsGuarded = IsGuarded } )
return IsGuarded
end
function ZONE_CAPTURE_COALITION:IsEmpty()
local IsEmpty = self:IsNoneInZone()
self:F( { IsEmpty = IsEmpty } )
return IsEmpty
end
function ZONE_CAPTURE_COALITION:IsCaptured()
local IsCaptured = self:IsAllInZoneOfOtherCoalition( self.Coalition )
self:F( { IsCaptured = IsCaptured } )
return IsCaptured
end
function ZONE_CAPTURE_COALITION:IsAttacked()
local IsAttacked = self:IsSomeInZoneOfCoalition( self.Coalition )
self:F( { IsAttacked = IsAttacked } )
return IsAttacked
end
--- Mark.
-- @param #ZONE_CAPTURE_COALITION self
function ZONE_CAPTURE_COALITION:Mark()
local Coord = self:GetCoordinate()
local ZoneName = self:GetZoneName()
local State = self:GetState()
if self.MarkRed and self.MarkBlue then
self:F( { MarkRed = self.MarkRed, MarkBlue = self.MarkBlue } )
Coord:RemoveMark( self.MarkRed )
Coord:RemoveMark( self.MarkBlue )
end
if self.Coalition == coalition.side.BLUE then
self.MarkBlue = Coord:MarkToCoalitionBlue( "Coalition: Blue\nGuard Zone: " .. ZoneName .. "\nStatus: " .. State )
self.MarkRed = Coord:MarkToCoalitionRed( "Coalition: Blue\nCapture Zone: " .. ZoneName .. "\nStatus: " .. State )
else
self.MarkRed = Coord:MarkToCoalitionRed( "Coalition: Red\nGuard Zone: " .. ZoneName .. "\nStatus: " .. State )
self.MarkBlue = Coord:MarkToCoalitionBlue( "Coalition: Red\nCapture Zone: " .. ZoneName .. "\nStatus: " .. State )
end
end
--- Bound.
-- @param #ZONE_CAPTURE_COALITION self
function ZONE_CAPTURE_COALITION:onenterGuarded()
--self:GetParent( self ):onenterGuarded()
if self.Coalition == coalition.side.BLUE then
--elf.ProtectZone:BoundZone( 12, country.id.USA )
else
--self.ProtectZone:BoundZone( 12, country.id.RUSSIA )
end
self:Mark()
end
function ZONE_CAPTURE_COALITION:onenterCaptured()
--self:GetParent( self ):onenterCaptured()
local NewCoalition = self:GetScannedCoalition()
self:F( { NewCoalition = NewCoalition } )
self:SetCoalition( NewCoalition )
self:Mark()
self.Goal:Achieved()
end
function ZONE_CAPTURE_COALITION:onenterEmpty()
--self:GetParent( self ):onenterEmpty()
self:Mark()
end
function ZONE_CAPTURE_COALITION:onenterAttacked()
--self:GetParent( self ):onenterAttacked()
self:Mark()
end
--- When started, check the Coalition status.
-- @param #ZONE_CAPTURE_COALITION self
function ZONE_CAPTURE_COALITION:onafterGuard()
--self:F({BASE:GetParent( self )})
--BASE:GetParent( self ).onafterGuard( self )
if not self.SmokeScheduler then
self.SmokeScheduler = self:ScheduleRepeat( self.StartInterval, self.RepeatInterval, 0.1, nil, self.StatusSmoke, self )
end
end
function ZONE_CAPTURE_COALITION:IsCaptured()
local IsCaptured = self:IsAllInZoneOfOtherCoalition( self.Coalition )
self:F( { IsCaptured = IsCaptured } )
return IsCaptured
end
function ZONE_CAPTURE_COALITION:IsAttacked()
local IsAttacked = self:IsSomeInZoneOfCoalition( self.Coalition )
self:F( { IsAttacked = IsAttacked } )
return IsAttacked
end
--- Check status Coalition ownership.
-- @param #ZONE_CAPTURE_COALITION self
function ZONE_CAPTURE_COALITION:StatusZone()
local State = self:GetState()
self:F( { State = self:GetState() } )
self:GetParent( self, ZONE_CAPTURE_COALITION ).StatusZone( self )
if State ~= "Guarded" and self:IsGuarded() then
self:Guard()
end
if State ~= "Empty" and self:IsEmpty() then
self:Empty()
end
if State ~= "Attacked" and self:IsAttacked() then
self:Attack()
end
if State ~= "Captured" and self:IsCaptured() then
self:Capture()
end
end
--- Starts the zone capturing monitoring process.
-- This process can be CPU intensive, ensure that you specify reasonable time intervals for the monitoring process.
@@ -753,6 +584,7 @@ do -- ZONE_CAPTURE_COALITION
if self.ScheduleStatusZone then
self:ScheduleStop( self.ScheduleStatusZone )
end
self.ScheduleStatusZone = self:ScheduleRepeat( self.StartInterval, self.RepeatInterval, 1.5, nil, self.StatusZone, self )
end
@@ -812,7 +644,184 @@ do -- ZONE_CAPTURE_COALITION
end
end
end
--- On after "Guard" event.
-- @param #ZONE_CAPTURE_COALITION self
function ZONE_CAPTURE_COALITION:onafterGuard()
if not self.SmokeScheduler then
self.SmokeScheduler = self:ScheduleRepeat( self.StartInterval, self.RepeatInterval, 0.1, nil, self.StatusSmoke, self )
end
end
--- On enter "Guarded" state.
-- @param #ZONE_CAPTURE_COALITION self
function ZONE_CAPTURE_COALITION:onenterGuarded()
self:Mark()
end
--- On enter "Captured" state.
-- @param #ZONE_CAPTURE_COALITION self
function ZONE_CAPTURE_COALITION:onenterCaptured()
-- Get new coalition.
local NewCoalition = self:GetScannedCoalition()
self:F( { NewCoalition = NewCoalition } )
-- Set new owner of zone.
self:SetCoalition( NewCoalition )
-- Update mark.
self:Mark()
-- Goal achieved.
self.Goal:Achieved()
end
--- On enter "Empty" state.
-- @param #ZONE_CAPTURE_COALITION self
function ZONE_CAPTURE_COALITION:onenterEmpty()
self:Mark()
end
--- On enter "Attacked" state.
-- @param #ZONE_CAPTURE_COALITION self
function ZONE_CAPTURE_COALITION:onenterAttacked()
self:Mark()
end
--- Check if zone is "Guarded"
-- @param #ZONE_CAPTURE_COALITION self
-- @return #boolean self:IsAllInZoneOfCoalition( self.Coalition )
function ZONE_CAPTURE_COALITION:IsGuarded()
local IsGuarded = self:IsAllInZoneOfCoalition( self.Coalition )
self:F( { IsGuarded = IsGuarded } )
return IsGuarded
end
--- Check if zone is "Empty"
-- @param #ZONE_CAPTURE_COALITION self
-- @return #boolean self:IsNoneInZone()
function ZONE_CAPTURE_COALITION:IsEmpty()
local IsEmpty = self:IsNoneInZone()
self:F( { IsEmpty = IsEmpty } )
return IsEmpty
end
--- Check if zone is "Captured"
-- @param #ZONE_CAPTURE_COALITION self
-- @return #boolean self:IsAllInZoneOfOtherCoalition( self.Coalition )
function ZONE_CAPTURE_COALITION:IsCaptured()
local IsCaptured = self:IsAllInZoneOfOtherCoalition( self.Coalition )
self:F( { IsCaptured = IsCaptured } )
return IsCaptured
end
--- Check if zone is "Attacked"
-- @param #ZONE_CAPTURE_COALITION self
-- @return #boolean self:IsSomeInZoneOfCoalition( self.Coalition )
function ZONE_CAPTURE_COALITION:IsAttacked()
local IsAttacked = self:IsSomeInZoneOfCoalition( self.Coalition )
self:F( { IsAttacked = IsAttacked } )
return IsAttacked
end
--- Check if zone is captured.
-- @param #ZONE_CAPTURE_COALITION self
-- @return #boolean self:IsAllInZoneOfOtherCoalition( self.Coalition )
function ZONE_CAPTURE_COALITION:IsCaptured()
local IsCaptured = self:IsAllInZoneOfOtherCoalition( self.Coalition )
self:F( { IsCaptured = IsCaptured } )
return IsCaptured
end
--- Check if zone is attacked.
-- @param #ZONE_CAPTURE_COALITION self
-- @return #boolean self:IsSomeInZoneOfCoalition( self.Coalition )
function ZONE_CAPTURE_COALITION:IsAttacked()
local IsAttacked = self:IsSomeInZoneOfCoalition( self.Coalition )
self:F( { IsAttacked = IsAttacked } )
return IsAttacked
end
--- Check status Coalition ownership.
-- @param #ZONE_CAPTURE_COALITION self
function ZONE_CAPTURE_COALITION:StatusZone()
-- Get FSM state.
local State = self:GetState()
-- Scan zone in parent class ZONE_GOAL_COALITION
self:GetParent( self, ZONE_CAPTURE_COALITION ).StatusZone( self )
-- Check if zone is guarded.
if State ~= "Guarded" and self:IsGuarded() then
self:Guard()
end
-- Check if zone is empty.
if State ~= "Empty" and self:IsEmpty() then
self:Empty()
end
-- Check if zone is attacked.
if State ~= "Attacked" and self:IsAttacked() then
self:Attack()
end
-- Check if zone is captured.
if State ~= "Captured" and self:IsCaptured() then
self:Capture()
end
--
local text=string.format("CAPTURE ZONE %s: Status %s", self:GetZoneName(), State)
local NewState = self:GetState()
if NewState~=State then
text=text..string.format(" --> %s", NewState)
end
self:I(text)
end
--- Update Mark on F10 map.
-- @param #ZONE_CAPTURE_COALITION self
function ZONE_CAPTURE_COALITION:Mark()
local Coord = self:GetCoordinate()
local ZoneName = self:GetZoneName()
local State = self:GetState()
if self.MarkRed and self.MarkBlue then
self:F( { MarkRed = self.MarkRed, MarkBlue = self.MarkBlue } )
Coord:RemoveMark( self.MarkRed )
Coord:RemoveMark( self.MarkBlue )
end
if self.Coalition == coalition.side.BLUE then
self.MarkBlue = Coord:MarkToCoalitionBlue( "Coalition: Blue\nGuard Zone: " .. ZoneName .. "\nStatus: " .. State )
self.MarkRed = Coord:MarkToCoalitionRed( "Coalition: Blue\nCapture Zone: " .. ZoneName .. "\nStatus: " .. State )
elseif self.Coalition == coalition.side.RED then
self.MarkRed = Coord:MarkToCoalitionRed( "Coalition: Red\nGuard Zone: " .. ZoneName .. "\nStatus: " .. State )
self.MarkBlue = Coord:MarkToCoalitionBlue( "Coalition: Red\nCapture Zone: " .. ZoneName .. "\nStatus: " .. State )
else
self.MarkRed = Coord:MarkToCoalitionRed( "Coalition: Neutral\nCapture Zone: " .. ZoneName .. "\nStatus: " .. State )
self.MarkBlue = Coord:MarkToCoalitionBlue( "Coalition: Neutral\nCapture Zone: " .. ZoneName .. "\nStatus: " .. State )
end
end
end

View File

@@ -17,10 +17,10 @@
do -- Zone
--- @type ZONE_GOAL
-- @extends Core.Fsm#FSM
-- @extends Core.Zone#ZONE_RADIUS
-- Models processes that have a Goal with a defined achievement involving a Zone.
--- Models processes that have a Goal with a defined achievement involving a Zone.
-- Derived classes implement the ways how the achievements can be realized.
--
-- ## 1. ZONE_GOAL constructor
@@ -39,7 +39,10 @@ do -- Zone
--
-- @field #ZONE_GOAL
ZONE_GOAL = {
ClassName = "ZONE_GOAL",
ClassName = "ZONE_GOAL",
Goal = nil,
SmokeTime = nil,
SmokeScheduler = nil,
}
--- ZONE_GOAL Constructor.

View File

@@ -38,6 +38,8 @@ do -- ZoneGoal
-- @field #ZONE_GOAL_COALITION
ZONE_GOAL_COALITION = {
ClassName = "ZONE_GOAL_COALITION",
Coalition = nil,
}
--- @field #table ZONE_GOAL_COALITION.States
@@ -104,6 +106,7 @@ do -- ZoneGoal
local State = self:GetState()
self:F( { State = self:GetState() } )
env.info("scanning")
self:Scan( { Object.Category.UNIT, Object.Category.STATIC } )
end