mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
OPS Zone
This commit is contained in:
parent
77fc2c5cf1
commit
3050fdb3c3
@ -514,6 +514,10 @@ do -- Object
|
|||||||
--- @function [parent=#Object] isExist
|
--- @function [parent=#Object] isExist
|
||||||
-- @param #Object self
|
-- @param #Object self
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
|
|
||||||
|
--- @function [parent=#Object] isActive
|
||||||
|
-- @param #Object self
|
||||||
|
-- @return #boolean
|
||||||
|
|
||||||
--- @function [parent=#Object] destroy
|
--- @function [parent=#Object] destroy
|
||||||
-- @param #Object self
|
-- @param #Object self
|
||||||
|
|||||||
@ -94,6 +94,7 @@ __Moose.Include( 'Scripts/Moose/Ops/FlightControl.lua' )
|
|||||||
__Moose.Include( 'Scripts/Moose/Ops/OpsTransport.lua' )
|
__Moose.Include( 'Scripts/Moose/Ops/OpsTransport.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/CSAR.lua' )
|
__Moose.Include( 'Scripts/Moose/Ops/CSAR.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/CTLD.lua' )
|
__Moose.Include( 'Scripts/Moose/Ops/CTLD.lua' )
|
||||||
|
__Moose.Include( 'Scripts/Moose/Ops/OpsZone.lua' )
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Balancer.lua' )
|
__Moose.Include( 'Scripts/Moose/AI/AI_Balancer.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Air.lua' )
|
__Moose.Include( 'Scripts/Moose/AI/AI_Air.lua' )
|
||||||
|
|||||||
@ -309,6 +309,9 @@ end
|
|||||||
-- @return #CHIEF self
|
-- @return #CHIEF self
|
||||||
function CHIEF:AddTarget(Target)
|
function CHIEF:AddTarget(Target)
|
||||||
|
|
||||||
|
Target:SetPriority()
|
||||||
|
Target:SetImportance()
|
||||||
|
|
||||||
table.insert(self.targetqueue, Target)
|
table.insert(self.targetqueue, Target)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@ -424,7 +427,7 @@ function CHIEF:onafterStatus(From, Event, To)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Create missions for all new contacts.
|
-- Create TARGETs for all new contacts.
|
||||||
local Nred=0 ; local Nyellow=0 ; local Nengage=0
|
local Nred=0 ; local Nyellow=0 ; local Nengage=0
|
||||||
for _,_contact in pairs(self.Contacts) do
|
for _,_contact in pairs(self.Contacts) do
|
||||||
local contact=_contact --Ops.Intelligence#INTEL.Contact
|
local contact=_contact --Ops.Intelligence#INTEL.Contact
|
||||||
@ -448,7 +451,13 @@ function CHIEF:onafterStatus(From, Event, To)
|
|||||||
redalert=inred
|
redalert=inred
|
||||||
end
|
end
|
||||||
|
|
||||||
if redalert and threat and not contact.mission then
|
if redalert and threat and not contact.target then
|
||||||
|
|
||||||
|
local Target=TARGET:New(contact.group)
|
||||||
|
|
||||||
|
self:AddTarget(Target)
|
||||||
|
|
||||||
|
--[[
|
||||||
|
|
||||||
-- Create a mission based on group category.
|
-- Create a mission based on group category.
|
||||||
local mission=AUFTRAG:NewAUTO(group)
|
local mission=AUFTRAG:NewAUTO(group)
|
||||||
@ -469,6 +478,8 @@ function CHIEF:onafterStatus(From, Event, To)
|
|||||||
self:AddMission(mission)
|
self:AddMission(mission)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -485,25 +496,35 @@ function CHIEF:onafterStatus(From, Event, To)
|
|||||||
else
|
else
|
||||||
self:SetDefcon(CHIEF.DEFCON.GREEN)
|
self:SetDefcon(CHIEF.DEFCON.GREEN)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Check Target Queue
|
||||||
|
---
|
||||||
|
|
||||||
|
-- Check target queue and assign missions to new targets.
|
||||||
|
self:CheckTargetQueue()
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Mission Queue
|
-- Check Mission Queue
|
||||||
---
|
---
|
||||||
|
|
||||||
-- Check mission queue and assign one PLANNED mission.
|
-- Check mission queue and assign one PLANNED mission.
|
||||||
self:CheckMissionQueue()
|
self:CheckMissionQueue()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Mission Queue
|
-- Info General
|
||||||
---
|
---
|
||||||
|
|
||||||
local Nassets=self.wingcommander:CountAssets()
|
local Nassets=self.wingcommander:CountAssets()
|
||||||
|
|
||||||
local text=string.format("Defcon=%s Assets=%d, Missions=%d, Contacts: Total=%d Yellow=%d Red=%d", self.Defcon, Nassets, #self.missionqueue, #self.Contacts, Nyellow, Nred)
|
local text=string.format("Defcon=%s Assets=%d, Contacts: Total=%d Yellow=%d Red=%d, Targets=%d, Missions=%d", self.Defcon, Nassets, #self.Contacts, Nyellow, Nred, #self.targetqueue, #self.missionqueue)
|
||||||
self:I(self.lid..text)
|
self:I(self.lid..text)
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Assets
|
-- Info Assets
|
||||||
---
|
---
|
||||||
|
|
||||||
local text="Assets:"
|
local text="Assets:"
|
||||||
@ -524,31 +545,7 @@ function CHIEF:onafterStatus(From, Event, To)
|
|||||||
self:I(self.lid..text)
|
self:I(self.lid..text)
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Target Queue
|
-- Info Contacts
|
||||||
---
|
|
||||||
|
|
||||||
if #self.targetqueue>0 then
|
|
||||||
local text="Targets:"
|
|
||||||
for i,_target in pairs(self.targetqueue) do
|
|
||||||
local target=_target --Ops.Target#TARGET
|
|
||||||
|
|
||||||
text=text..string.format("\n[%d] %s: Category=%s, alive=%s [%.1f/%.1f]", i, target:GetName(), target.category, tostring(target:IsAlive()), target:GetLife(), target:GetLife0())
|
|
||||||
|
|
||||||
|
|
||||||
if target:IsAlive() then
|
|
||||||
|
|
||||||
if self:CheckTargetInZones(target, self.borderzoneset) then
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
self:I(self.lid..text)
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- Contacts
|
|
||||||
---
|
---
|
||||||
|
|
||||||
-- Info about contacts.
|
-- Info about contacts.
|
||||||
@ -564,6 +561,26 @@ function CHIEF:onafterStatus(From, Event, To)
|
|||||||
end
|
end
|
||||||
self:I(self.lid..text)
|
self:I(self.lid..text)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Info Targets
|
||||||
|
---
|
||||||
|
|
||||||
|
if #self.targetqueue>0 then
|
||||||
|
local text="Targets:"
|
||||||
|
for i,_target in pairs(self.targetqueue) do
|
||||||
|
local target=_target --Ops.Target#TARGET
|
||||||
|
|
||||||
|
text=text..string.format("\n[%d] %s: Category=%s, prio=%d, importance=%d, alive=%s [%.1f/%.1f]",
|
||||||
|
i, target:GetName(), target.category, target.prio, target.importance or -1, tostring(target:IsAlive()), target:GetLife(), target:GetLife0())
|
||||||
|
|
||||||
|
end
|
||||||
|
self:I(self.lid..text)
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Info Missions
|
||||||
|
---
|
||||||
|
|
||||||
-- Mission queue.
|
-- Mission queue.
|
||||||
if #self.missionqueue>0 then
|
if #self.missionqueue>0 then
|
||||||
@ -688,6 +705,73 @@ function CHIEF:onafterDeclareWar(From, Event, To, Chief)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Target Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Check mission queue and assign ONE planned mission.
|
||||||
|
-- @param #CHIEF self
|
||||||
|
function CHIEF:CheckTargetQueue()
|
||||||
|
|
||||||
|
-- TODO: Sort mission queue. wrt what? Threat level?
|
||||||
|
|
||||||
|
for _,_target in pairs(self.targetqueue) do
|
||||||
|
local target=_target --Ops.Target#TARGET
|
||||||
|
|
||||||
|
if target:IsAlive() and not target.mission then
|
||||||
|
|
||||||
|
-- TODO: stategry
|
||||||
|
self.strategy=CHIEF.Strategy.TOTALWAR
|
||||||
|
|
||||||
|
local valid=false
|
||||||
|
if self.strategy==CHIEF.Strategy.DEFENSIVE then
|
||||||
|
|
||||||
|
if self:CheckTargetInZones(target, self.borderzoneset) then
|
||||||
|
valid=true
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif self.strategy==CHIEF.Strategy.OFFENSIVE then
|
||||||
|
|
||||||
|
if self:CheckTargetInZones(target, self.borderzoneset) or self:CheckTargetInZones(target, self.yellowzoneset) then
|
||||||
|
valid=true
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif self.strategy==CHIEF.Strategy.AGGRESSIVE then
|
||||||
|
|
||||||
|
if self:CheckTargetInZones(target, self.borderzoneset) or self:CheckTargetInZones(target, self.yellowzoneset) or self:CheckTargetInZones(target, self.engagezoneset) then
|
||||||
|
valid=true
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif self.strategy==CHIEF.Strategy.TOTALWAR then
|
||||||
|
valid=true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Valid target?
|
||||||
|
if valid then
|
||||||
|
|
||||||
|
-- Create mission
|
||||||
|
local mission=AUFTRAG:NewTargetAir(target)
|
||||||
|
|
||||||
|
if mission then
|
||||||
|
|
||||||
|
-- Set target mission entry.
|
||||||
|
target.mission=mission
|
||||||
|
|
||||||
|
-- Mission parameters.
|
||||||
|
mission.prio=target.prio
|
||||||
|
mission.importance=target.importance
|
||||||
|
|
||||||
|
-- Add mission to queue.
|
||||||
|
self:AddMission(mission)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- Resources
|
-- Resources
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@ -117,8 +117,9 @@ INTEL = {
|
|||||||
-- @field #boolean isship
|
-- @field #boolean isship
|
||||||
-- @field #boolean ishelo
|
-- @field #boolean ishelo
|
||||||
-- @field #boolean isground
|
-- @field #boolean isground
|
||||||
-- @field Ops.Auftrag#AUFTRAG mission The current Auftrag attached to this contact
|
-- @field Ops.Auftrag#AUFTRAG mission The current Auftrag attached to this contact.
|
||||||
-- @field #string recce The name of the recce unit that detected this contact
|
-- @field Ops.Target#TARGET target The Target attached to this contact.
|
||||||
|
-- @field #string recce The name of the recce unit that detected this contact.
|
||||||
|
|
||||||
--- Cluster info.
|
--- Cluster info.
|
||||||
-- @type INTEL.Cluster
|
-- @type INTEL.Cluster
|
||||||
|
|||||||
592
Moose Development/Moose/Ops/OpsZone.lua
Normal file
592
Moose Development/Moose/Ops/OpsZone.lua
Normal file
@ -0,0 +1,592 @@
|
|||||||
|
--- **Ops** - Strategic Zone.
|
||||||
|
--
|
||||||
|
-- **Main Features:**
|
||||||
|
--
|
||||||
|
-- * Monitor if zone is captured.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ### Author: **funkyfranky**
|
||||||
|
--
|
||||||
|
-- @module Ops.OpsZone
|
||||||
|
-- @image OPS_OpsZone.png
|
||||||
|
|
||||||
|
|
||||||
|
--- OPSZONE class.
|
||||||
|
-- @type OPSZONE
|
||||||
|
-- @field #string ClassName Name of the class.
|
||||||
|
-- @field #number verbose Verbosity of output.
|
||||||
|
-- @field Core.Zone#ZONE zone The zone.
|
||||||
|
-- @field #string zoneName Name of the zone.
|
||||||
|
-- @field #number ownerCurrent Coalition of the current owner of the zone.
|
||||||
|
-- @field #number ownerPrevious Coalition of the previous owner of the zone.
|
||||||
|
-- @field Core.Timer#TIMER timerStatus Timer for calling the status update.
|
||||||
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
|
--- Be surprised!
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- # The OPSZONE Concept
|
||||||
|
--
|
||||||
|
-- An OPSZONE is a strategically important area.
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- @field #OPSZONE
|
||||||
|
OPSZONE = {
|
||||||
|
ClassName = "OPSZONE",
|
||||||
|
verbose = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
--- OPSZONE class version.
|
||||||
|
-- @field #string version
|
||||||
|
OPSZONE.version="0.0.1"
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- ToDo list
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- TODO: Can neutrals capture?
|
||||||
|
-- TODO: Can statics capture or hold a zone?
|
||||||
|
-- TODO: Differentiate between ground attack and boming by air or arty.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Constructor
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Create a new OPSZONE class object.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @param Core.Zone#ZONE Zone The zone.
|
||||||
|
-- @param #number CoalitionOwner Initial owner of the coaliton. Default `coalition.side.NEUTRAL`.
|
||||||
|
-- @return #OPSZONE self
|
||||||
|
function OPSZONE:New(Zone, CoalitionOwner)
|
||||||
|
|
||||||
|
-- Inherit everything from LEGION class.
|
||||||
|
local self=BASE:Inherit(self, FSM:New()) -- #OPSZONE
|
||||||
|
|
||||||
|
-- Check if zone name instead of ZONE object was passed.
|
||||||
|
if type(Zone)=="string" then
|
||||||
|
Zone=ZONE:New(Zone)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Basic checks.
|
||||||
|
if not Zone then
|
||||||
|
self:E("ERROR: OPSZONE not found!")
|
||||||
|
return nil
|
||||||
|
elseif not Zone:IsInstanceOf("ZONE_RADIUS") then
|
||||||
|
self:E("ERROR: OPSZONE must be a SPHERICAL zone due to DCS restrictions!")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
self.zone=Zone
|
||||||
|
self.zoneName=Zone:GetName()
|
||||||
|
self.zoneRadius=Zone:GetRadius()
|
||||||
|
|
||||||
|
self.ownerCurrent=CoalitionOwner or coalition.side.NEUTRAL
|
||||||
|
self.ownerPrevious=CoalitionOwner or coalition.side.NEUTRAL
|
||||||
|
|
||||||
|
-- Set some string id for output to DCS.log file.
|
||||||
|
self.lid=string.format("OPSZONE %s | ", Zone:GetName())
|
||||||
|
|
||||||
|
-- FMS start state is PLANNED.
|
||||||
|
self:SetStartState("Empty")
|
||||||
|
|
||||||
|
|
||||||
|
-- Add FSM transitions.
|
||||||
|
-- From State --> Event --> To State
|
||||||
|
self:AddTransition("*", "Start", "*") -- Start FSM.
|
||||||
|
self:AddTransition("*", "Stop", "*") -- Start FSM.
|
||||||
|
|
||||||
|
self:AddTransition("*", "Captured", "Guarded") -- Start FSM.
|
||||||
|
self:AddTransition("*", "Empty", "Empty") -- Start FSM.
|
||||||
|
|
||||||
|
self:AddTransition("*", "Attacked", "Attacked") -- A guarded zone is under attack.
|
||||||
|
self:AddTransition("*", "Defeated", "Guarded") -- The owning coalition defeated an attack.
|
||||||
|
|
||||||
|
|
||||||
|
self.timerStatus=TIMER:New(OPSZONE.Status, self)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- User Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Get current owner of the zone.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @return #number Owner coalition.
|
||||||
|
function OPSZONE:GetOwner()
|
||||||
|
return self.ownerCurrent
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get previous owner of the zone.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @return #number Previous owner coalition.
|
||||||
|
function OPSZONE:GetPreviousOwner()
|
||||||
|
return self.ownerPrevious
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Check if the red coalition is currently owning the zone.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @return #boolean If `true`, zone is red.
|
||||||
|
function OPSZONE:IsRed()
|
||||||
|
local is=self.ownerCurrent==coalition.side.RED
|
||||||
|
return is
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if the blue coalition is currently owning the zone.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @return #boolean If `true`, zone is blue.
|
||||||
|
function OPSZONE:IsBlue()
|
||||||
|
local is=self.ownerCurrent==coalition.side.BLUE
|
||||||
|
return is
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if the neutral coalition is currently owning the zone.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @return #boolean If `true`, zone is neutral.
|
||||||
|
function OPSZONE:IsNeutral()
|
||||||
|
local is=self.ownerCurrent==coalition.side.NEUTRAL
|
||||||
|
return is
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if zone is guarded.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @return #boolean If `true`, zone is guarded.
|
||||||
|
function OPSZONE:IsEmpty()
|
||||||
|
local is=self:is("Guarded")
|
||||||
|
return is
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if zone is empty.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @return #boolean If `true`, zone is empty.
|
||||||
|
function OPSZONE:IsEmpty()
|
||||||
|
local is=self:is("Empty")
|
||||||
|
return is
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if zone is being attacked by the opposite coalition.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @return #boolean If `true`, zone is being attacked.
|
||||||
|
function OPSZONE:IsAttacked()
|
||||||
|
local is=self:is("Attacked")
|
||||||
|
return is
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if zone is contested. Contested here means red *and* blue units are present in the zone.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @return #boolean If `true`, zone is contested.
|
||||||
|
function OPSZONE:IsContested()
|
||||||
|
return self.isContested
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- FSM Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Start OPSZONE FSM.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
function OPSZONE:onafterStart(From, Event, To)
|
||||||
|
|
||||||
|
-- Info.
|
||||||
|
self:I(self.lid..string.format("Starting OPSZONE v%s", OPSZONE.version))
|
||||||
|
|
||||||
|
-- Status update.
|
||||||
|
self.timerStatus:Start(1, 60)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Update status.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
function OPSZONE:Status()
|
||||||
|
|
||||||
|
-- Current FSM state.
|
||||||
|
local fsmstate=self:GetState()
|
||||||
|
|
||||||
|
-- Info message.
|
||||||
|
local text=string.format("State %s: Owner %d (previous %d), contested=%s, Nunits: red=%d, blue=%d, neutral=%d", fsmstate, self.ownerCurrent, self.ownerPrevious, tostring(self:IsContested()), 0, 0, 0)
|
||||||
|
self:I(self.lid..text)
|
||||||
|
|
||||||
|
-- Scanning zone.
|
||||||
|
self:Scan()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- FSM Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- On after "Captured" event.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param #number NewOwnerCoalition Coalition of the new owner.
|
||||||
|
function OPSZONE:onafterCaptured(From, Event, To, NewOwnerCoalition)
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:I(self.lid..string.format("Zone captured by %d coalition", NewOwnerCoalition))
|
||||||
|
|
||||||
|
self.ownerPrevious=self.ownerCurrent
|
||||||
|
self.ownerCurrent=NewOwnerCoalition
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On after "Empty" event.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
function OPSZONE:onafterEmpty(From, Event, To)
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:I(self.lid..string.format("Zone is empty now"))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On after "Attacked" event.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param #number AttackerCoalition Coalition of the attacking ground troops.
|
||||||
|
function OPSZONE:onafterAttacked(From, Event, To, AttackerCoalition)
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:I(self.lid..string.format("Zone is being attacked by coalition %s!", tostring(AttackerCoalition)))
|
||||||
|
|
||||||
|
-- Time stam when the attack started.
|
||||||
|
self.Tattacked=timer.getAbsTime()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- On after "Empty" event.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
function OPSZONE:onafterEmpty(From, Event, To)
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:I(self.lid..string.format("Zone is empty now"))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On after "Defeated" event.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
function OPSZONE:onafterDefeated(From, Event, To)
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:I(self.lid..string.format("Attack on zone has been defeated"))
|
||||||
|
|
||||||
|
-- Not attacked any more.
|
||||||
|
self.Tattacked=nil
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On enter "Guarded" state.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
function OPSZONE:onenterGuarded(From, Event, To)
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:I(self.lid..string.format("Zone is guarded"))
|
||||||
|
|
||||||
|
self.Tattacked=nil
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On enter "Guarded" state.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
function OPSZONE:onenterAttacked(From, Event, To)
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:I(self.lid..string.format("Zone is Attacked"))
|
||||||
|
|
||||||
|
self.Tattacked=nil
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Scan Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Add a platoon to the brigade.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @return #OPSZONE self
|
||||||
|
function OPSZONE:Scan()
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
local text=string.format("Scanning zone %s R=%.1f m", self.zone:GetName(), self.zone:GetRadius())
|
||||||
|
self:I(self.lid..text)
|
||||||
|
|
||||||
|
-- Search.
|
||||||
|
local SphereSearch={id=world.VolumeType.SPHERE, params={point=self.zone:GetVec3(), radius=self.zone:GetRadius(),}}
|
||||||
|
|
||||||
|
local ObjectCategories={Object.Category.UNIT, Object.Category.STATIC}
|
||||||
|
|
||||||
|
local Nred=0
|
||||||
|
local Nblu=0
|
||||||
|
local Nnut=0
|
||||||
|
|
||||||
|
--- Function to evaluate the world search
|
||||||
|
local function EvaluateZone(_ZoneObject)
|
||||||
|
|
||||||
|
local ZoneObject=_ZoneObject --DCS#Object
|
||||||
|
|
||||||
|
if ZoneObject then
|
||||||
|
|
||||||
|
-- Object category.
|
||||||
|
local ObjectCategory=ZoneObject:getCategory()
|
||||||
|
|
||||||
|
if ObjectCategory==Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive() then
|
||||||
|
|
||||||
|
---
|
||||||
|
-- UNIT
|
||||||
|
---
|
||||||
|
|
||||||
|
local DCSUnit=ZoneObject --DCS#Unit
|
||||||
|
|
||||||
|
--TODO: only ground units!
|
||||||
|
|
||||||
|
local Coalition=DCSUnit:getCoalition()
|
||||||
|
|
||||||
|
if Coalition==coalition.side.RED then
|
||||||
|
Nred=Nred+1
|
||||||
|
elseif Coalition==coalition.side.BLUE then
|
||||||
|
Nblu=Nblu+1
|
||||||
|
elseif Coalition==coalition.side.NEUTRAL then
|
||||||
|
Nnut=Nnut+1
|
||||||
|
end
|
||||||
|
|
||||||
|
local unit=UNIT:Find(DCSUnit)
|
||||||
|
|
||||||
|
env.info(string.format("FF found unit %s", unit:GetName()))
|
||||||
|
|
||||||
|
|
||||||
|
elseif ObjectCategory==Object.Category.STATIC and ZoneObject:isExist() then
|
||||||
|
|
||||||
|
---
|
||||||
|
-- STATIC
|
||||||
|
---
|
||||||
|
|
||||||
|
local DCSStatic=ZoneObject --DCS#Static
|
||||||
|
|
||||||
|
-- CAREFUL! Downed pilots break routine here without any error thrown.
|
||||||
|
local unit=STATIC:Find(DCSStatic)
|
||||||
|
|
||||||
|
--env.info(string.format("FF found static %s", unit:GetName()))
|
||||||
|
|
||||||
|
elseif ObjectCategory==Object.Category.SCENERY then
|
||||||
|
|
||||||
|
---
|
||||||
|
-- SCENERY
|
||||||
|
---
|
||||||
|
|
||||||
|
local SceneryType = ZoneObject:getTypeName()
|
||||||
|
local SceneryName = ZoneObject:getName()
|
||||||
|
|
||||||
|
local Scenery=SCENERY:Register(SceneryName, ZoneObject)
|
||||||
|
|
||||||
|
env.info(string.format("FF found scenery type=%s, name=%s", SceneryType, SceneryName))
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Search objects.
|
||||||
|
world.searchObjects(ObjectCategories, SphereSearch, EvaluateZone)
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
local text=string.format("Scan result Nred=%d, Nblue=%d, Nneutrl=%d", Nred, Nblu, Nnut)
|
||||||
|
self:I(self.lid..text)
|
||||||
|
|
||||||
|
if self:IsRed() then
|
||||||
|
|
||||||
|
---
|
||||||
|
-- RED zone
|
||||||
|
---
|
||||||
|
|
||||||
|
if Nred==0 then
|
||||||
|
|
||||||
|
-- No red units in red zone any more.
|
||||||
|
|
||||||
|
if Nblu>0 then
|
||||||
|
-- Blue captured red zone.
|
||||||
|
self:Captured(coalition.side.BLUE)
|
||||||
|
elseif Nnut>0 and self.neutralCanCapture then
|
||||||
|
-- Neutral captured red zone.
|
||||||
|
self:Captured(coalition.side.NEUTRAL)
|
||||||
|
else
|
||||||
|
-- Red zone is now empty (but will remain red).
|
||||||
|
self:Empty()
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Still red units in red zone.
|
||||||
|
|
||||||
|
if Nblu>0 then
|
||||||
|
|
||||||
|
if not self:IsAttacked() then
|
||||||
|
self:Attacked(coalition.side.BLUE)
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif Nblu==0 then
|
||||||
|
|
||||||
|
if self:IsAttacked() and self:IsContested() then
|
||||||
|
self:Defeated(coalition.side.BLUE)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Contested by blue?
|
||||||
|
if Nblu==0 then
|
||||||
|
self.isContested=false
|
||||||
|
else
|
||||||
|
self.isContested=true
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif self:IsBlue() then
|
||||||
|
|
||||||
|
---
|
||||||
|
-- BLUE zone
|
||||||
|
---
|
||||||
|
|
||||||
|
if Nblu==0 then
|
||||||
|
|
||||||
|
-- No blue units in blue zone any more.
|
||||||
|
|
||||||
|
if Nred>0 then
|
||||||
|
-- Red captured blue zone.
|
||||||
|
self:Captured(coalition.side.RED)
|
||||||
|
elseif Nnut>0 and self.neutralCanCapture then
|
||||||
|
-- Neutral captured blue zone.
|
||||||
|
self:Captured(coalition.side.NEUTRAL)
|
||||||
|
else
|
||||||
|
-- Blue zone is empty now.
|
||||||
|
self:Empty()
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Still blue units in blue zone.
|
||||||
|
|
||||||
|
if Nred>0 then
|
||||||
|
|
||||||
|
if not self:IsAttacked() then
|
||||||
|
-- Red is attacking blue zone.
|
||||||
|
self:Attacked(coalition.side.RED)
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif Nred==0 then
|
||||||
|
|
||||||
|
if self:IsAttacked() and self:IsContested() then
|
||||||
|
-- Blue defeated read attack.
|
||||||
|
self:Defeated(coalition.side.RED)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Contested by red?
|
||||||
|
if Nred==0 then
|
||||||
|
self.isContested=false
|
||||||
|
else
|
||||||
|
self.isContested=true
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif self:IsNeutral() then
|
||||||
|
|
||||||
|
---
|
||||||
|
-- NEUTRAL zone
|
||||||
|
---
|
||||||
|
|
||||||
|
-- Not checked as neutrals cant capture (for now).
|
||||||
|
--if Nnut==0 then
|
||||||
|
|
||||||
|
-- No neutral units in neutral zone any more.
|
||||||
|
|
||||||
|
if Nred>0 and Nblu>0 then
|
||||||
|
env.info("FF neutrals left neutral zone and red and blue are present! What to do?")
|
||||||
|
-- TODO Contested!
|
||||||
|
self:Attacked()
|
||||||
|
self.isContested=true
|
||||||
|
elseif Nred>0 then
|
||||||
|
-- Red captured neutral zone.
|
||||||
|
self:Captured(coalition.side.RED)
|
||||||
|
elseif Nblu>0 then
|
||||||
|
-- Blue captured neutral zone.
|
||||||
|
self:Captured(coalition.side.BLUE)
|
||||||
|
else
|
||||||
|
-- Neutral zone is empty now.
|
||||||
|
if not self:IsEmpty() then
|
||||||
|
self:Emtpy()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--end
|
||||||
|
|
||||||
|
else
|
||||||
|
env.info("FF error")
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- DCS Event Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Monitor hit events.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData The event data.
|
||||||
|
function OPSZONE:OnEventHit(EventData)
|
||||||
|
|
||||||
|
if self.HitsOn then
|
||||||
|
|
||||||
|
local UnitHit = EventData.TgtUnit
|
||||||
|
|
||||||
|
-- Check if unit is inside the capture zone and that it is of the defending coalition.
|
||||||
|
if UnitHit and UnitHit:IsInZone(self) and UnitHit:GetCoalition()==self.ownerCurrent then
|
||||||
|
|
||||||
|
-- Update last hit time.
|
||||||
|
self.HitTimeLast=timer.getTime()
|
||||||
|
|
||||||
|
-- Only trigger attacked event if not already in state "Attacked".
|
||||||
|
if not self:IsAttacked() then
|
||||||
|
self:T3(self.lid.."Hit ==> Attack")
|
||||||
|
self:Attacked()
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -30,6 +30,8 @@
|
|||||||
-- @field #number Ndead Number of target elements/units that are dead (destroyed or despawned).
|
-- @field #number Ndead Number of target elements/units that are dead (destroyed or despawned).
|
||||||
-- @field #table elements Table of target elements/units.
|
-- @field #table elements Table of target elements/units.
|
||||||
-- @field #table casualties Table of dead element names.
|
-- @field #table casualties Table of dead element names.
|
||||||
|
-- @field #number prio Priority.
|
||||||
|
-- @field #number importance Importance
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- **It is far more important to be able to hit the target than it is to haggle over who makes a weapon or who pulls a trigger** -- Dwight D. Eisenhower
|
--- **It is far more important to be able to hit the target than it is to haggle over who makes a weapon or who pulls a trigger** -- Dwight D. Eisenhower
|
||||||
@ -287,6 +289,24 @@ function TARGET:AddObject(Object)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set priority of the target.
|
||||||
|
-- @param #TARGET self
|
||||||
|
-- @param #number Priority Priority of the target. Default 50.
|
||||||
|
-- @return #TARGET self
|
||||||
|
function TARGET:SetPriority(Priority)
|
||||||
|
self.prio=Priority or 50
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set importance of the target.
|
||||||
|
-- @param #TARGET self
|
||||||
|
-- @param #number Priority Priority of the target. Default `nil`.
|
||||||
|
-- @return #TARGET self
|
||||||
|
function TARGET:SetImportance(Importance)
|
||||||
|
self.importance=Importance
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Check if TARGET is alive.
|
--- Check if TARGET is alive.
|
||||||
-- @param #TARGET self
|
-- @param #TARGET self
|
||||||
-- @return #boolean If true, target is alive.
|
-- @return #boolean If true, target is alive.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user