mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
OPS
- Added new **CONDITION** class - Added new **OPERATION** class
This commit is contained in:
parent
ae54cd8fde
commit
edbfa9117d
279
Moose Development/Moose/Core/Condition.lua
Normal file
279
Moose Development/Moose/Core/Condition.lua
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
--- **Core** - Define any or all conditions to be evaluated.
|
||||||
|
--
|
||||||
|
-- **Main Features:**
|
||||||
|
--
|
||||||
|
-- * Add arbitrary numbers of conditon functions
|
||||||
|
-- * Evaluate *any* or *all* conditions
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ### Author: **funkyfranky**
|
||||||
|
-- @module Core.Condition
|
||||||
|
-- @image Core_Condition.png
|
||||||
|
|
||||||
|
|
||||||
|
--- CONDITON class.
|
||||||
|
-- @type CONDITION
|
||||||
|
-- @field #string ClassName Name of the class.
|
||||||
|
-- @field #string lid Class id string for output to DCS log file.
|
||||||
|
-- @field #boolean isAny General functions are evaluated as any condition.
|
||||||
|
-- @field #boolean negateResult Negeate result of evaluation.
|
||||||
|
-- @field #table functionsGen General condition functions.
|
||||||
|
-- @field #table functionsAny Any condition functions.
|
||||||
|
-- @field #table functionsAll All condition functions.
|
||||||
|
--
|
||||||
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
|
--- *Better three hours too soon than a minute too late.* - William Shakespeare
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- # The CONDITION Concept
|
||||||
|
--
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- @field #CONDITION
|
||||||
|
CONDITION = {
|
||||||
|
ClassName = "CONDITION",
|
||||||
|
lid = nil,
|
||||||
|
functionsGen = {},
|
||||||
|
functionsAny = {},
|
||||||
|
functionsAll = {},
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Condition function.
|
||||||
|
-- @type CONDITION.Function
|
||||||
|
-- @field #function func Callback function to check for a condition. Should return a `#boolean`.
|
||||||
|
-- @field #table arg (Optional) Arguments passed to the condition callback function if any.
|
||||||
|
|
||||||
|
--- CONDITION class version.
|
||||||
|
-- @field #string version
|
||||||
|
CONDITION.version="0.0.1"
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- TODO list
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- TODO: Make FSM.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Constructor
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Create a new CONDITION object.
|
||||||
|
-- @param #CONDITION self
|
||||||
|
-- @param #string Name (Optional) Name used in the logs.
|
||||||
|
-- @return #CONDITION self
|
||||||
|
function CONDITION:New(Name)
|
||||||
|
|
||||||
|
-- Inherit BASE.
|
||||||
|
local self=BASE:Inherit(self, BASE:New()) --#CONDITION
|
||||||
|
|
||||||
|
self.name=Name or "Condition X"
|
||||||
|
|
||||||
|
self.lid=string.format("%s | ", self.name)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set that general condition functions return `true` if `any` function returns `true`. Default is that *all* functions must return `true`.
|
||||||
|
-- @param #CONDITION self
|
||||||
|
-- @param #boolean Any If `true`, *any* condition can be true. Else *all* conditions must result `true`.
|
||||||
|
-- @return #CONDITION self
|
||||||
|
function CONDITION:SetAny(Any)
|
||||||
|
self.isAny=Any
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Negate result.
|
||||||
|
-- @param #CONDITION self
|
||||||
|
-- @param #boolean Negate If `true`, result is negated else not.
|
||||||
|
-- @return #CONDITION self
|
||||||
|
function CONDITION:SetNegateResult(Negate)
|
||||||
|
self.negateResult=Negate
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add a function that is evaluated. It must return a `#boolean` value, *i.e.* either `true` or `false` (or `nil`).
|
||||||
|
-- @param #CONDITION self
|
||||||
|
-- @param #function Function The function to call.
|
||||||
|
-- @param ... (Optional) Parameters passed to the function (if any).
|
||||||
|
--
|
||||||
|
-- @usage
|
||||||
|
-- local function isAequalB(a, b)
|
||||||
|
-- return a==b
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- myCondition:AddFunction(isAequalB, a, b)
|
||||||
|
--
|
||||||
|
-- @return #CONDITION self
|
||||||
|
function CONDITION:AddFunction(Function, ...)
|
||||||
|
|
||||||
|
-- Condition function.
|
||||||
|
local condition=self:_CreateCondition(Function, ...)
|
||||||
|
|
||||||
|
-- Add to table.
|
||||||
|
table.insert(self.functionsGen, condition)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add a function that is evaluated. It must return a `#boolean` value, *i.e.* either `true` or `false` (or `nil`).
|
||||||
|
-- @param #CONDITION self
|
||||||
|
-- @param #function Function The function to call.
|
||||||
|
-- @param ... (Optional) Parameters passed to the function (if any).
|
||||||
|
-- @return #CONDITION self
|
||||||
|
function CONDITION:AddFunctionAny(Function, ...)
|
||||||
|
|
||||||
|
-- Condition function.
|
||||||
|
local condition=self:_CreateCondition(Function, ...)
|
||||||
|
|
||||||
|
-- Add to table.
|
||||||
|
table.insert(self.functionsAny, condition)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add a function that is evaluated. It must return a `#boolean` value, *i.e.* either `true` or `false` (or `nil`).
|
||||||
|
-- @param #CONDITION self
|
||||||
|
-- @param #function Function The function to call.
|
||||||
|
-- @param ... (Optional) Parameters passed to the function (if any).
|
||||||
|
-- @return #CONDITION self
|
||||||
|
function CONDITION:AddFunctionAll(Function, ...)
|
||||||
|
|
||||||
|
-- Condition function.
|
||||||
|
local condition=self:_CreateCondition(Function, ...)
|
||||||
|
|
||||||
|
-- Add to table.
|
||||||
|
table.insert(self.functionsAll, condition)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Evaluate conditon functions.
|
||||||
|
-- @param #CONDITION self
|
||||||
|
-- @param #boolean AnyTrue If `true`, evaluation return `true` if *any* condition function returns `true`. By default, *all* condition functions must return true.
|
||||||
|
-- @return #boolean Result of condition functions.
|
||||||
|
function CONDITION:Evaluate(AnyTrue)
|
||||||
|
|
||||||
|
-- Any condition for gen.
|
||||||
|
local evalAny=self.isAny
|
||||||
|
if AnyTrue~=nil then
|
||||||
|
evalAny=AnyTrue
|
||||||
|
end
|
||||||
|
|
||||||
|
local isGen=nil
|
||||||
|
if evalAny then
|
||||||
|
isGen=self:_EvalConditionsAny(self.functionsGen)
|
||||||
|
else
|
||||||
|
isGen=self:_EvalConditionsAll(self.functionsGen)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Is any?
|
||||||
|
local isAny=self:_EvalConditionsAny(self.functionsAny)
|
||||||
|
|
||||||
|
-- Is all?
|
||||||
|
local isAll=self:_EvalConditionsAll(self.functionsAll)
|
||||||
|
|
||||||
|
-- Result.
|
||||||
|
local result=isGen and isAny and isAll
|
||||||
|
|
||||||
|
-- Negate result.
|
||||||
|
if self.negateResult then
|
||||||
|
result=not result
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
|
self:I(self.lid..string.format("Evaluate: isGen=%s, isAny=%s, isAll=%s (negate=%s) ==> result=%s", tostring(isGen), tostring(isAny), tostring(isAll), tostring(self.negateResult), tostring(result)))
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if all given condition are true.
|
||||||
|
-- @param #CONDITION self
|
||||||
|
-- @param #table functions Functions to evaluate.
|
||||||
|
-- @return #boolean If true, all conditions were true (or functions was empty/nil). Returns false if at least one condition returned false.
|
||||||
|
function CONDITION:_EvalConditionsAll(functions)
|
||||||
|
|
||||||
|
-- At least one condition?
|
||||||
|
local gotone=false
|
||||||
|
|
||||||
|
|
||||||
|
-- Any stop condition must be true.
|
||||||
|
for _,_condition in pairs(functions or {}) do
|
||||||
|
local condition=_condition --#CONDITION.Function
|
||||||
|
|
||||||
|
-- At least one condition was defined.
|
||||||
|
gotone=true
|
||||||
|
|
||||||
|
-- Call function.
|
||||||
|
local istrue=condition.func(unpack(condition.arg))
|
||||||
|
|
||||||
|
-- Any false will return false.
|
||||||
|
if not istrue then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- All conditions were true.
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Check if any of the given conditions is true.
|
||||||
|
-- @param #CONDITION self
|
||||||
|
-- @param #table functions Functions to evaluate.
|
||||||
|
-- @return #boolean If true, at least one condition is true (or functions was emtpy/nil).
|
||||||
|
function CONDITION:_EvalConditionsAny(functions)
|
||||||
|
|
||||||
|
-- At least one condition?
|
||||||
|
local gotone=false
|
||||||
|
|
||||||
|
-- Any stop condition must be true.
|
||||||
|
for _,_condition in pairs(functions or {}) do
|
||||||
|
local condition=_condition --#CONDITION.Function
|
||||||
|
|
||||||
|
-- At least one condition was defined.
|
||||||
|
gotone=true
|
||||||
|
|
||||||
|
-- Call function.
|
||||||
|
local istrue=condition.func(unpack(condition.arg))
|
||||||
|
|
||||||
|
-- Any true will return true.
|
||||||
|
if istrue then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- No condition was true.
|
||||||
|
if gotone then
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
-- No functions passed.
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create conditon fucntion object.
|
||||||
|
-- @param #CONDITION self
|
||||||
|
-- @param #function Function The function to call.
|
||||||
|
-- @param ... (Optional) Parameters passed to the function (if any).
|
||||||
|
-- @return #CONDITION.Function Condition function.
|
||||||
|
function CONDITION:_CreateCondition(Function, ...)
|
||||||
|
|
||||||
|
local condition={} --#CONDITION.Function
|
||||||
|
|
||||||
|
condition.func=Function
|
||||||
|
condition.arg={}
|
||||||
|
if arg then
|
||||||
|
condition.arg=arg
|
||||||
|
end
|
||||||
|
|
||||||
|
return condition
|
||||||
|
end
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -31,6 +31,7 @@ __Moose.Include( 'Scripts/Moose/Core/Spot.lua' )
|
|||||||
__Moose.Include( 'Scripts/Moose/Core/Astar.lua' )
|
__Moose.Include( 'Scripts/Moose/Core/Astar.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/MarkerOps_Base.lua' )
|
__Moose.Include( 'Scripts/Moose/Core/MarkerOps_Base.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/TextAndSound.lua' )
|
__Moose.Include( 'Scripts/Moose/Core/TextAndSound.lua' )
|
||||||
|
__Moose.Include( 'Scripts/Moose/Core/Condition.lua' )
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/Wrapper/Object.lua' )
|
__Moose.Include( 'Scripts/Moose/Wrapper/Object.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Wrapper/Identifiable.lua' )
|
__Moose.Include( 'Scripts/Moose/Wrapper/Identifiable.lua' )
|
||||||
@ -101,6 +102,7 @@ __Moose.Include( 'Scripts/Moose/Ops/Chief.lua' )
|
|||||||
__Moose.Include( 'Scripts/Moose/Ops/Flotilla.lua' )
|
__Moose.Include( 'Scripts/Moose/Ops/Flotilla.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Fleet.lua' )
|
__Moose.Include( 'Scripts/Moose/Ops/Fleet.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Awacs.lua' )
|
__Moose.Include( 'Scripts/Moose/Ops/Awacs.lua' )
|
||||||
|
__Moose.Include( 'Scripts/Moose/Ops/Operation.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/FlightControl.lua' )
|
__Moose.Include( 'Scripts/Moose/Ops/FlightControl.lua' )
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Balancer.lua' )
|
__Moose.Include( 'Scripts/Moose/AI/AI_Balancer.lua' )
|
||||||
|
|||||||
@ -4143,7 +4143,7 @@ function AUFTRAG:CheckGroupsDone()
|
|||||||
if groupdata then
|
if groupdata then
|
||||||
if not (groupdata.status==AUFTRAG.GroupStatus.DONE or groupdata.status==AUFTRAG.GroupStatus.CANCELLED) then
|
if not (groupdata.status==AUFTRAG.GroupStatus.DONE or groupdata.status==AUFTRAG.GroupStatus.CANCELLED) then
|
||||||
-- At least this flight is not DONE or CANCELLED.
|
-- At least this flight is not DONE or CANCELLED.
|
||||||
self:T(self.lid..string.format("CheckGroupsDone: OPSGROUP %s is not DONE or CANCELLED but in state %s. Mission NOT DONE!", groupdata.opsgroup.groupname, groupdata.status))
|
self:T2(self.lid..string.format("CheckGroupsDone: OPSGROUP %s is not DONE or CANCELLED but in state %s. Mission NOT DONE!", groupdata.opsgroup.groupname, groupdata.status:upper()))
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -4155,7 +4155,7 @@ function AUFTRAG:CheckGroupsDone()
|
|||||||
local status=self:GetLegionStatus(legion)
|
local status=self:GetLegionStatus(legion)
|
||||||
if not status==AUFTRAG.Status.CANCELLED then
|
if not status==AUFTRAG.Status.CANCELLED then
|
||||||
-- At least one LEGION has not CANCELLED.
|
-- At least one LEGION has not CANCELLED.
|
||||||
self:T(self.lid..string.format("CheckGroupsDone: LEGION %s is not CANCELLED but in state %s. Mission NOT DONE!", legion.alias, status))
|
self:T2(self.lid..string.format("CheckGroupsDone: LEGION %s is not CANCELLED but in state %s. Mission NOT DONE!", legion.alias, status))
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -4163,7 +4163,7 @@ function AUFTRAG:CheckGroupsDone()
|
|||||||
-- Check commander status.
|
-- Check commander status.
|
||||||
if self.commander then
|
if self.commander then
|
||||||
if not self.statusCommander==AUFTRAG.Status.CANCELLED then
|
if not self.statusCommander==AUFTRAG.Status.CANCELLED then
|
||||||
self:T(self.lid..string.format("CheckGroupsDone: COMMANDER is not CANCELLED but in state %s. Mission NOT DONE!", self.statusCommander))
|
self:T2(self.lid..string.format("CheckGroupsDone: COMMANDER is not CANCELLED but in state %s. Mission NOT DONE!", self.statusCommander))
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -4171,14 +4171,14 @@ function AUFTRAG:CheckGroupsDone()
|
|||||||
-- Check chief status.
|
-- Check chief status.
|
||||||
if self.chief then
|
if self.chief then
|
||||||
if not self.statusChief==AUFTRAG.Status.CANCELLED then
|
if not self.statusChief==AUFTRAG.Status.CANCELLED then
|
||||||
self:T(self.lid..string.format("CheckGroupsDone: CHIEF is not CANCELLED but in state %s. Mission NOT DONE!", self.statusChief))
|
self:T2(self.lid..string.format("CheckGroupsDone: CHIEF is not CANCELLED but in state %s. Mission NOT DONE!", self.statusChief))
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- These are early stages, where we might not even have a opsgroup defined to be checked. If there were any groups, we checked above.
|
-- These are early stages, where we might not even have a opsgroup defined to be checked. If there were any groups, we checked above.
|
||||||
if self:IsPlanned() or self:IsQueued() or self:IsRequested() then
|
if self:IsPlanned() or self:IsQueued() or self:IsRequested() then
|
||||||
self:T(self.lid..string.format("CheckGroupsDone: Mission is still in state %s [FSM=%s] (PLANNED or QUEUED or REQUESTED). Mission NOT DONE!", self.status, self:GetState()))
|
self:T2(self.lid..string.format("CheckGroupsDone: Mission is still in state %s [FSM=%s] (PLANNED or QUEUED or REQUESTED). Mission NOT DONE!", self.status, self:GetState()))
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -48,6 +48,7 @@
|
|||||||
-- @field #table tacanChannel List of TACAN channels available to the cohort.
|
-- @field #table tacanChannel List of TACAN channels available to the cohort.
|
||||||
-- @field #number weightAsset Weight of one assets group in kg.
|
-- @field #number weightAsset Weight of one assets group in kg.
|
||||||
-- @field #number cargobayLimit Cargo bay capacity in kg.
|
-- @field #number cargobayLimit Cargo bay capacity in kg.
|
||||||
|
-- @field #table operations Operations this cohort is part of.
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- *I came, I saw, I conquered.* -- Julius Caesar
|
--- *I came, I saw, I conquered.* -- Julius Caesar
|
||||||
@ -82,6 +83,7 @@ COHORT = {
|
|||||||
cargobayLimit = 0,
|
cargobayLimit = 0,
|
||||||
descriptors = {},
|
descriptors = {},
|
||||||
properties = {},
|
properties = {},
|
||||||
|
operations = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
--- COHORT class version.
|
--- COHORT class version.
|
||||||
@ -1544,7 +1546,17 @@ function COHORT:_MissileCategoryName(categorynumber)
|
|||||||
cat="other"
|
cat="other"
|
||||||
end
|
end
|
||||||
return cat
|
return cat
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Add an OPERATION.
|
||||||
|
-- @param #COHORT self
|
||||||
|
-- @param Ops.Operation#OPERATION Operation The operation this cohort is part of.
|
||||||
|
-- @return #COHORT self
|
||||||
|
function COHORT:_AddOperation(Operation)
|
||||||
|
|
||||||
|
self.operations[Operation.name]=Operation
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
-- @field #table missionqueue Mission queue.
|
-- @field #table missionqueue Mission queue.
|
||||||
-- @field #table transportqueue Transport queue.
|
-- @field #table transportqueue Transport queue.
|
||||||
-- @field #table targetqueue Target queue.
|
-- @field #table targetqueue Target queue.
|
||||||
|
-- @field #table opsqueue Operations queue.
|
||||||
-- @field #table rearmingZones Rearming zones. Each element is of type `#BRIGADE.SupplyZone`.
|
-- @field #table rearmingZones Rearming zones. Each element is of type `#BRIGADE.SupplyZone`.
|
||||||
-- @field #table refuellingZones Refuelling zones. Each element is of type `#BRIGADE.SupplyZone`.
|
-- @field #table refuellingZones Refuelling zones. Each element is of type `#BRIGADE.SupplyZone`.
|
||||||
-- @field #table capZones CAP zones. Each element is of type `#AIRWING.PatrolZone`.
|
-- @field #table capZones CAP zones. Each element is of type `#AIRWING.PatrolZone`.
|
||||||
@ -127,6 +128,7 @@ COMMANDER = {
|
|||||||
missionqueue = {},
|
missionqueue = {},
|
||||||
transportqueue = {},
|
transportqueue = {},
|
||||||
targetqueue = {},
|
targetqueue = {},
|
||||||
|
opsqueue = {},
|
||||||
rearmingZones = {},
|
rearmingZones = {},
|
||||||
refuellingZones = {},
|
refuellingZones = {},
|
||||||
capZones = {},
|
capZones = {},
|
||||||
@ -841,6 +843,9 @@ function COMMANDER:onafterStatus(From, Event, To)
|
|||||||
self:T(self.lid..text)
|
self:T(self.lid..text)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Check Operations queue.
|
||||||
|
self:CheckOpsQueue()
|
||||||
|
|
||||||
-- Check target queue and add missions.
|
-- Check target queue and add missions.
|
||||||
self:CheckTargetQueue()
|
self:CheckTargetQueue()
|
||||||
|
|
||||||
@ -1217,6 +1222,28 @@ end
|
|||||||
-- Mission Functions
|
-- Mission Functions
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Check OPERATIONs queue.
|
||||||
|
-- @param #COMMANDER self
|
||||||
|
function COMMANDER:CheckOpsQueue()
|
||||||
|
|
||||||
|
-- Number of missions.
|
||||||
|
local Nops=#self.opsqueue
|
||||||
|
|
||||||
|
-- Treat special cases.
|
||||||
|
if Nops==0 then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Loop over operations.
|
||||||
|
for _,_ops in pairs(self.opsqueue) do
|
||||||
|
local operation=_ops --Ops.Operation#OPRATION
|
||||||
|
|
||||||
|
--TODO: What?
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- Check target queue and assign ONE valid target by adding it to the mission queue of the COMMANDER.
|
--- Check target queue and assign ONE valid target by adding it to the mission queue of the COMMANDER.
|
||||||
-- @param #COMMANDER self
|
-- @param #COMMANDER self
|
||||||
function COMMANDER:CheckTargetQueue()
|
function COMMANDER:CheckTargetQueue()
|
||||||
@ -1281,7 +1308,7 @@ function COMMANDER:CheckTargetQueue()
|
|||||||
local isReadyStart=target:EvalConditionsAll(target.conditionStart)
|
local isReadyStart=target:EvalConditionsAll(target.conditionStart)
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
local text=string.format("Target %s: Alive=%s, Threat=%s, Important=%s", target:GetName(), tostring(isAlive), tostring(isThreat), tostring(isImportant))
|
local text=string.format("Target %s: Alive=%s, Important=%s", target:GetName(), tostring(isAlive), tostring(isImportant))
|
||||||
self:T2(self.lid..text)
|
self:T2(self.lid..text)
|
||||||
|
|
||||||
-- Check that target is alive and not already a mission has been assigned.
|
-- Check that target is alive and not already a mission has been assigned.
|
||||||
|
|||||||
@ -149,13 +149,13 @@ FLIGHTCONTROL = {
|
|||||||
FLIGHTCONTROL.FlightStatus={
|
FLIGHTCONTROL.FlightStatus={
|
||||||
PARKING="Parking",
|
PARKING="Parking",
|
||||||
READYTX="Ready To Taxi",
|
READYTX="Ready To Taxi",
|
||||||
TAXIOUT="Taxi to runway",
|
TAXIOUT="Taxi To Runway",
|
||||||
READYTO="Ready For Takeoff",
|
READYTO="Ready For Takeoff",
|
||||||
TAKEOFF="Takeoff",
|
TAKEOFF="Takeoff",
|
||||||
INBOUND="Inbound",
|
INBOUND="Inbound",
|
||||||
HOLDING="Holding",
|
HOLDING="Holding",
|
||||||
LANDING="Landing",
|
LANDING="Landing",
|
||||||
TAXIINB="Taxi Inbound",
|
TAXIINB="Taxi To Parking",
|
||||||
ARRIVED="Arrived",
|
ARRIVED="Arrived",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,21 +172,20 @@ FLIGHTCONTROL.version="0.5.2"
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
--
|
|
||||||
|
|
||||||
|
-- TODO: Runway destroyed.
|
||||||
-- TODO: Support airwings. Dont give clearance for Alert5 or if mission has not started.
|
-- TODO: Support airwings. Dont give clearance for Alert5 or if mission has not started.
|
||||||
-- TODO: Switch to enable/disable AI messages.
|
-- TODO: Switch to enable/disable AI messages.
|
||||||
-- TODO: Improve ATC TTS messages.
|
-- TODO: Improve ATC TTS messages.
|
||||||
-- TODO: Add helos.
|
|
||||||
-- TODO: Talk me down option.
|
-- TODO: Talk me down option.
|
||||||
-- TODO: ATIS option.
|
-- TODO: ATIS option.
|
||||||
-- TODO: Check runways and clean up.
|
-- TODO: Check runways and clean up.
|
||||||
-- TODO: Accept and forbit parking spots.
|
-- TODO: Accept and forbit parking spots.
|
||||||
-- TODO: Define holding zone.
|
-- TODO: Add FARPS?
|
||||||
|
-- DONE: Define holding zone.
|
||||||
-- DONE: Basic ATC voice overs.
|
-- DONE: Basic ATC voice overs.
|
||||||
-- DONE: Add SRS TTS.
|
-- DONE: Add SRS TTS.
|
||||||
-- DONE: Add parking guard.
|
-- DONE: Add parking guard.
|
||||||
-- NOGO: Add FARPS?
|
|
||||||
-- DONE: Interface with FLIGHTGROUP.
|
-- DONE: Interface with FLIGHTGROUP.
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -793,7 +792,7 @@ function FLIGHTCONTROL:_CheckQueues()
|
|||||||
else
|
else
|
||||||
-- TODO: Humans have to confirm via F10 menu.
|
-- TODO: Humans have to confirm via F10 menu.
|
||||||
self:SetFlightStatus(flight, FLIGHTCONTROL.FlightStatus.LANDING)
|
self:SetFlightStatus(flight, FLIGHTCONTROL.FlightStatus.LANDING)
|
||||||
flight:_UpdateMenu()
|
flight:_UpdateMenu(0.5)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set time last flight got landing clearance.
|
-- Set time last flight got landing clearance.
|
||||||
@ -1299,7 +1298,7 @@ function FLIGHTCONTROL:_RemoveFlightFromQueue(queue, flight, queuename)
|
|||||||
table.remove(queue, i)
|
table.remove(queue, i)
|
||||||
|
|
||||||
if not flight.isAI then
|
if not flight.isAI then
|
||||||
flight:_UpdateMenu()
|
flight:_UpdateMenu(0.5)
|
||||||
end
|
end
|
||||||
|
|
||||||
return true, i
|
return true, i
|
||||||
@ -1797,6 +1796,9 @@ function FLIGHTCONTROL:_CreatePlayerMenu(flight, mainmenu)
|
|||||||
MENU_GROUP_COMMAND:New(group, "Radio Check", helpmenu, self._PlayerRadioCheck, self, groupname)
|
MENU_GROUP_COMMAND:New(group, "Radio Check", helpmenu, self._PlayerRadioCheck, self, groupname)
|
||||||
MENU_GROUP_COMMAND:New(group, "Confirm Status", helpmenu, self._PlayerConfirmStatus, self, groupname)
|
MENU_GROUP_COMMAND:New(group, "Confirm Status", helpmenu, self._PlayerConfirmStatus, self, groupname)
|
||||||
MENU_GROUP_COMMAND:New(group, "Mark Holding", helpmenu, self._PlayerNotImplemented, self, groupname)
|
MENU_GROUP_COMMAND:New(group, "Mark Holding", helpmenu, self._PlayerNotImplemented, self, groupname)
|
||||||
|
if gotcontrol and flight:IsInbound() and flight.stack then
|
||||||
|
MENU_GROUP_COMMAND:New(group, "Vector Holding", helpmenu, self._PlayerVectorInbound, self, groupname)
|
||||||
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Info Menu
|
-- Info Menu
|
||||||
@ -1832,22 +1834,24 @@ function FLIGHTCONTROL:_CreatePlayerMenu(flight, mainmenu)
|
|||||||
---
|
---
|
||||||
-- Taxiing
|
-- Taxiing
|
||||||
---
|
---
|
||||||
|
|
||||||
if status==FLIGHTCONTROL.FlightStatus.READYTO then
|
if status==FLIGHTCONTROL.FlightStatus.READYTX or status==FLIGHTCONTROL.FlightStatus.TAXIOUT then
|
||||||
|
-- Flight is "ready to taxi" (awaiting clearance) or "taxiing to runway".
|
||||||
|
MENU_GROUP_COMMAND:New(group, "Request Takeoff", rootmenu, self._PlayerRequestTakeoff, self, groupname)
|
||||||
|
MENU_GROUP_COMMAND:New(group, "Abort Taxi", rootmenu, self._PlayerAbortTaxi, self, groupname)
|
||||||
|
elseif status==FLIGHTCONTROL.FlightStatus.READYTO then
|
||||||
|
-- Flight is ready for take off.
|
||||||
MENU_GROUP_COMMAND:New(group, "Abort Takeoff", rootmenu, self._PlayerAbortTakeoff, self, groupname)
|
MENU_GROUP_COMMAND:New(group, "Abort Takeoff", rootmenu, self._PlayerAbortTakeoff, self, groupname)
|
||||||
elseif status==FLIGHTCONTROL.FlightStatus.TAKEOFF then
|
elseif status==FLIGHTCONTROL.FlightStatus.TAKEOFF then
|
||||||
|
-- Flight is taking off.
|
||||||
MENU_GROUP_COMMAND:New(group, "Abort Takeoff", rootmenu, self._PlayerAbortTakeoff, self, groupname)
|
MENU_GROUP_COMMAND:New(group, "Abort Takeoff", rootmenu, self._PlayerAbortTakeoff, self, groupname)
|
||||||
elseif status==FLIGHTCONTROL.FlightStatus.READYTX or status==FLIGHTCONTROL.FlightStatus.TAXIOUT then
|
|
||||||
MENU_GROUP_COMMAND:New(group, "Abort Taxi", rootmenu, self._PlayerAbortTaxi, self, groupname)
|
|
||||||
MENU_GROUP_COMMAND:New(group, "Request Takeoff", rootmenu, self._PlayerRequestTakeoff, self, groupname)
|
|
||||||
elseif status==FLIGHTCONTROL.FlightStatus.TAXIINB then
|
elseif status==FLIGHTCONTROL.FlightStatus.TAXIINB then
|
||||||
-- Could be after "abort taxi" call and we changed our mind (again)
|
-- Could be after "abort taxi" call and we changed our mind (again)
|
||||||
MENU_GROUP_COMMAND:New(group, "Request Parking", rootmenu, self._PlayerRequestParking, self, groupname)
|
MENU_GROUP_COMMAND:New(group, "Request Taxi", rootmenu, self._PlayerRequestTaxi, self, groupname)
|
||||||
MENU_GROUP_COMMAND:New(group, "Request Taxi", rootmenu, self._PlayerRequestTaxi, self, groupname)
|
MENU_GROUP_COMMAND:New(group, "Request Parking", rootmenu, self._PlayerRequestParking, self, groupname)
|
||||||
|
MENU_GROUP_COMMAND:New(group, "Arrived at Parking", rootmenu, self._PlayerArrived, self, groupname)
|
||||||
end
|
end
|
||||||
|
|
||||||
MENU_GROUP_COMMAND:New(group, "Arrived and Parking", rootmenu, self._PlayerArrived, self, groupname)
|
|
||||||
|
|
||||||
elseif flight:IsAirborne() then
|
elseif flight:IsAirborne() then
|
||||||
---
|
---
|
||||||
-- Airborne
|
-- Airborne
|
||||||
@ -1858,16 +1862,19 @@ function FLIGHTCONTROL:_CreatePlayerMenu(flight, mainmenu)
|
|||||||
-- Inbound
|
-- Inbound
|
||||||
---
|
---
|
||||||
|
|
||||||
MENU_GROUP_COMMAND:New(group, "Abort Inbound", rootmenu, self._PlayerAbortInbound, self, groupname)
|
|
||||||
MENU_GROUP_COMMAND:New(group, "Holding", rootmenu, self._PlayerHolding, self, groupname)
|
MENU_GROUP_COMMAND:New(group, "Holding", rootmenu, self._PlayerHolding, self, groupname)
|
||||||
|
MENU_GROUP_COMMAND:New(group, "Abort Inbound", rootmenu, self._PlayerAbortInbound, self, groupname)
|
||||||
|
MENU_GROUP_COMMAND:New(group, "Request Parking", rootmenu, self._PlayerRequestParking, self, groupname)
|
||||||
|
|
||||||
|
|
||||||
elseif flight:IsHolding() then
|
elseif flight:IsHolding() then
|
||||||
---
|
---
|
||||||
-- Holding
|
-- Holding
|
||||||
---
|
---
|
||||||
|
|
||||||
MENU_GROUP_COMMAND:New(group, "Abort Holding", rootmenu, self._PlayerAbortHolding, self, groupname)
|
|
||||||
MENU_GROUP_COMMAND:New(group, "Landing", rootmenu, self._PlayerConfirmLanding, self, groupname)
|
MENU_GROUP_COMMAND:New(group, "Landing", rootmenu, self._PlayerConfirmLanding, self, groupname)
|
||||||
|
MENU_GROUP_COMMAND:New(group, "Abort Holding", rootmenu, self._PlayerAbortHolding, self, groupname)
|
||||||
|
MENU_GROUP_COMMAND:New(group, "Request Parking", rootmenu, self._PlayerRequestParking, self, groupname)
|
||||||
|
|
||||||
elseif flight:IsLanding() then
|
elseif flight:IsLanding() then
|
||||||
---
|
---
|
||||||
@ -1875,11 +1882,16 @@ function FLIGHTCONTROL:_CreatePlayerMenu(flight, mainmenu)
|
|||||||
---
|
---
|
||||||
|
|
||||||
MENU_GROUP_COMMAND:New(group, "Abort Landing", rootmenu, self._PlayerAbortLanding, self, groupname)
|
MENU_GROUP_COMMAND:New(group, "Abort Landing", rootmenu, self._PlayerAbortLanding, self, groupname)
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
if flight:IsInbound() or flight:IsHolding() or flight:IsLanding() or flight:IsLanded() then
|
|
||||||
MENU_GROUP_COMMAND:New(group, "Request Parking", rootmenu, self._PlayerRequestParking, self, groupname)
|
MENU_GROUP_COMMAND:New(group, "Request Parking", rootmenu, self._PlayerRequestParking, self, groupname)
|
||||||
|
|
||||||
|
elseif flight:IsLanded() then
|
||||||
|
---
|
||||||
|
-- Landed
|
||||||
|
---
|
||||||
|
|
||||||
|
MENU_GROUP_COMMAND:New(group, "Arrived at Parking", rootmenu, self._PlayerArrived, self, groupname)
|
||||||
|
MENU_GROUP_COMMAND:New(group, "Request Parking", rootmenu, self._PlayerRequestParking, self, groupname)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
@ -2158,6 +2170,9 @@ function FLIGHTCONTROL:_PlayerRequestInbound(groupname)
|
|||||||
|
|
||||||
-- Call sign.
|
-- Call sign.
|
||||||
local callsign=flight:GetCallsignName()
|
local callsign=flight:GetCallsignName()
|
||||||
|
|
||||||
|
-- Get player element.
|
||||||
|
local player=flight:GetPlayerElement()
|
||||||
|
|
||||||
-- Pilot calls inbound for landing.
|
-- Pilot calls inbound for landing.
|
||||||
local text=string.format("%s, %s, inbound for landing", self.alias, callsign)
|
local text=string.format("%s, %s, inbound for landing", self.alias, callsign)
|
||||||
@ -2165,20 +2180,17 @@ function FLIGHTCONTROL:_PlayerRequestInbound(groupname)
|
|||||||
-- Radio message.
|
-- Radio message.
|
||||||
self:TransmissionPilot(text, flight)
|
self:TransmissionPilot(text, flight)
|
||||||
|
|
||||||
|
-- Current player coord.
|
||||||
|
local flightcoord=flight:GetCoordinate(nil, player.name)
|
||||||
|
|
||||||
-- Distance from player to airbase.
|
-- Distance from player to airbase.
|
||||||
local dist=flight:GetCoordinate():Get2DDistance(self:GetCoordinate())
|
local dist=flightcoord:Get2DDistance(self:GetCoordinate())
|
||||||
|
|
||||||
if dist<UTILS.NMToMeters(50) then
|
if dist<UTILS.NMToMeters(50) then
|
||||||
|
|
||||||
-- Call RTB event.
|
-- Call RTB event. This also sets the flight control and flight status to INBOUND and updates the menu.
|
||||||
flight:RTB(self.airbase)
|
flight:RTB(self.airbase)
|
||||||
|
|
||||||
-- Set flightcontrol for this flight.
|
|
||||||
flight:SetFlightControl(self)
|
|
||||||
|
|
||||||
-- Add flight to inbound queue.
|
|
||||||
self:SetFlightStatus(flight, FLIGHTCONTROL.FlightStatus.INBOUND)
|
|
||||||
|
|
||||||
-- Get holding point.
|
-- Get holding point.
|
||||||
local stack=self:_GetHoldingStack(flight)
|
local stack=self:_GetHoldingStack(flight)
|
||||||
|
|
||||||
@ -2190,14 +2202,11 @@ function FLIGHTCONTROL:_PlayerRequestInbound(groupname)
|
|||||||
-- Stack.
|
-- Stack.
|
||||||
flight.stack=stack
|
flight.stack=stack
|
||||||
|
|
||||||
-- Current postion.
|
|
||||||
local coord=flight:GetCoordinate()
|
|
||||||
|
|
||||||
-- Heading to holding point.
|
-- Heading to holding point.
|
||||||
local heading=coord:HeadingTo(stack.pos0)
|
local heading=flightcoord:HeadingTo(stack.pos0)
|
||||||
|
|
||||||
-- Distance to holding point.
|
-- Distance to holding point.
|
||||||
local distance=coord:Get2DDistance(stack.pos0)
|
local distance=flightcoord:Get2DDistance(stack.pos0)
|
||||||
|
|
||||||
local dist=UTILS.MetersToNM(distance)
|
local dist=UTILS.MetersToNM(distance)
|
||||||
|
|
||||||
@ -2209,7 +2218,7 @@ function FLIGHTCONTROL:_PlayerRequestInbound(groupname)
|
|||||||
self:TransmissionTower(text, flight, 15)
|
self:TransmissionTower(text, flight, 15)
|
||||||
|
|
||||||
-- Create player menu.
|
-- Create player menu.
|
||||||
flight:_UpdateMenu()
|
--flight:_UpdateMenu()
|
||||||
|
|
||||||
else
|
else
|
||||||
self:E(self.lid..string.format("WARNING: Could not get holding stack for flight %s", flight:GetName()))
|
self:E(self.lid..string.format("WARNING: Could not get holding stack for flight %s", flight:GetName()))
|
||||||
@ -2225,7 +2234,7 @@ function FLIGHTCONTROL:_PlayerRequestInbound(groupname)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
-- Error you are not airborne!
|
-- Error you are not airborne!
|
||||||
local text=string.format("Negative, you must be AIRBORNE to call INBOUND!")
|
local text=string.format("Negative, you must be AIRBORNE to call INBOUND!")
|
||||||
|
|
||||||
@ -2239,6 +2248,56 @@ function FLIGHTCONTROL:_PlayerRequestInbound(groupname)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Player vector to inbound
|
||||||
|
-- @param #FLIGHTCONTROL self
|
||||||
|
-- @param #string groupname Name of the flight group.
|
||||||
|
function FLIGHTCONTROL:_PlayerVectorInbound(groupname)
|
||||||
|
|
||||||
|
-- Get flight group.
|
||||||
|
local flight=_DATABASE:GetOpsGroup(groupname) --Ops.FlightGroup#FLIGHTGROUP
|
||||||
|
|
||||||
|
if flight then
|
||||||
|
|
||||||
|
if flight:IsInbound() and self:IsControlling(flight) and flight.stack then
|
||||||
|
|
||||||
|
-- Call sign.
|
||||||
|
local callsign=flight:GetCallsignName()
|
||||||
|
|
||||||
|
-- Get player element.
|
||||||
|
local player=flight:GetPlayerElement()
|
||||||
|
|
||||||
|
-- Current player coord.
|
||||||
|
local flightcoord=flight:GetCoordinate(nil, player.name)
|
||||||
|
|
||||||
|
-- Distance from player to airbase.
|
||||||
|
local dist=flightcoord:Get2DDistance(self:GetCoordinate())
|
||||||
|
|
||||||
|
-- Call sign.
|
||||||
|
local callsign=flight:GetCallsignName()
|
||||||
|
|
||||||
|
-- Heading to holding point.
|
||||||
|
local heading=flightcoord:HeadingTo(flight.stack.pos0)
|
||||||
|
|
||||||
|
-- Distance to holding point.
|
||||||
|
local distance=flightcoord:Get2DDistance(flight.stack.pos0)
|
||||||
|
|
||||||
|
local dist=UTILS.MetersToNM(distance)
|
||||||
|
|
||||||
|
-- Message text.
|
||||||
|
local text=string.format("%s, fly heading %03d for %d nautical miles, hold at angels %d.",
|
||||||
|
callsign, self.alias, heading, dist, flight.stack.angels)
|
||||||
|
|
||||||
|
-- Send message.
|
||||||
|
self:TextMessageToFlight(text, flight)
|
||||||
|
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:E(self.lid..string.format("Cannot find flight group %s.", tostring(groupname)))
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- Player aborts inbound.
|
--- Player aborts inbound.
|
||||||
-- @param #FLIGHTCONTROL self
|
-- @param #FLIGHTCONTROL self
|
||||||
-- @param #string groupname Name of the flight group.
|
-- @param #string groupname Name of the flight group.
|
||||||
@ -2274,11 +2333,14 @@ function FLIGHTCONTROL:_PlayerAbortInbound(groupname)
|
|||||||
self:E(self.lid.."ERROR: No stack!")
|
self:E(self.lid.."ERROR: No stack!")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Remove flight. This also updates the menu.
|
||||||
|
self:_RemoveFlight(flight)
|
||||||
|
|
||||||
-- Set flight to cruise.
|
-- Set flight to cruise.
|
||||||
flight:Cruise()
|
flight:Cruise()
|
||||||
|
|
||||||
-- Remove flight. This also updates the menu.
|
-- Create player menu.
|
||||||
self:_RemoveFlight(flight)
|
--flight:_UpdateMenu()
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
@ -2313,19 +2375,27 @@ function FLIGHTCONTROL:_PlayerHolding(groupname)
|
|||||||
|
|
||||||
if self:IsControlling(flight) then
|
if self:IsControlling(flight) then
|
||||||
|
|
||||||
|
-- Callsign.
|
||||||
|
local callsign=flight:GetCallsignName()
|
||||||
|
|
||||||
|
-- Player element.
|
||||||
|
local player=flight:GetPlayerElement()
|
||||||
|
|
||||||
-- Holding stack.
|
-- Holding stack.
|
||||||
local stack=flight.stack
|
local stack=flight.stack
|
||||||
|
|
||||||
if stack then
|
if stack then
|
||||||
|
|
||||||
local Coordinate=flight:GetCoordinate()
|
-- Current coordinate.
|
||||||
|
local Coordinate=flight:GetCoordinate(nil, player.name)
|
||||||
|
|
||||||
|
-- Distance.
|
||||||
local dist=stack.pos0:Get2DDistance(Coordinate)
|
local dist=stack.pos0:Get2DDistance(Coordinate)
|
||||||
|
|
||||||
if dist<5000 then
|
if dist<5000 then
|
||||||
|
|
||||||
-- Message to flight
|
-- Message to flight
|
||||||
local text=string.format("Roger, you are added to the holding queue!")
|
local text=string.format("%s, roger, you are added to the holding queue!", callsign)
|
||||||
self:TextMessageToFlight(text, flight, 10, true)
|
self:TextMessageToFlight(text, flight, 10, true)
|
||||||
|
|
||||||
-- Call holding event.
|
-- Call holding event.
|
||||||
@ -2396,7 +2466,7 @@ function FLIGHTCONTROL:_PlayerAbortHolding(groupname)
|
|||||||
-- Not holding any more.
|
-- Not holding any more.
|
||||||
flight.Tholding=nil
|
flight.Tholding=nil
|
||||||
|
|
||||||
-- Set flight to cruise.
|
-- Set flight to cruise. This also updates the menu.
|
||||||
flight:Cruise()
|
flight:Cruise()
|
||||||
|
|
||||||
-- Set flight.
|
-- Set flight.
|
||||||
@ -2471,8 +2541,7 @@ function FLIGHTCONTROL:_PlayerConfirmLanding(groupname)
|
|||||||
self:TransmissionTower(text, flight, 10)
|
self:TransmissionTower(text, flight, 10)
|
||||||
|
|
||||||
-- Create player menu.
|
-- Create player menu.
|
||||||
flight:_UpdateMenu()
|
flight:_UpdateMenu(0.5)
|
||||||
--self:_CreatePlayerMenu(flight, flight.menu.atc)
|
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
@ -2577,7 +2646,7 @@ function FLIGHTCONTROL:_PlayerRequestTaxi(groupname)
|
|||||||
self:SetFlightStatus(flight, FLIGHTCONTROL.FlightStatus.READYTX)
|
self:SetFlightStatus(flight, FLIGHTCONTROL.FlightStatus.READYTX)
|
||||||
|
|
||||||
-- Update menu.
|
-- Update menu.
|
||||||
flight:_UpdateMenu()
|
flight:_UpdateMenu(0.5)
|
||||||
|
|
||||||
else
|
else
|
||||||
self:TextMessageToFlight(string.format("Negative, you must be PARKING to request TAXI!"), flight)
|
self:TextMessageToFlight(string.format("Negative, you must be PARKING to request TAXI!"), flight)
|
||||||
@ -2616,7 +2685,7 @@ function FLIGHTCONTROL:_PlayerAbortTaxi(groupname)
|
|||||||
self:SetFlightStatus(flight, FLIGHTCONTROL.FlightStatus.PARKING)
|
self:SetFlightStatus(flight, FLIGHTCONTROL.FlightStatus.PARKING)
|
||||||
|
|
||||||
-- Update menu.
|
-- Update menu.
|
||||||
flight:_UpdateMenu()
|
flight:_UpdateMenu(0.5)
|
||||||
|
|
||||||
elseif flight:IsTaxiing() then
|
elseif flight:IsTaxiing() then
|
||||||
|
|
||||||
@ -2628,7 +2697,7 @@ function FLIGHTCONTROL:_PlayerAbortTaxi(groupname)
|
|||||||
self:SetFlightStatus(flight, FLIGHTCONTROL.FlightStatus.TAXIINB)
|
self:SetFlightStatus(flight, FLIGHTCONTROL.FlightStatus.TAXIINB)
|
||||||
|
|
||||||
-- Update menu.
|
-- Update menu.
|
||||||
flight:_UpdateMenu()
|
flight:_UpdateMenu(0.5)
|
||||||
|
|
||||||
else
|
else
|
||||||
self:TextMessageToFlight(string.format("Negative, you must be PARKING or TAXIING to abort TAXI!"), flight)
|
self:TextMessageToFlight(string.format("Negative, you must be PARKING or TAXIING to abort TAXI!"), flight)
|
||||||
@ -2690,15 +2759,15 @@ function FLIGHTCONTROL:_PlayerRequestTakeoff(groupname)
|
|||||||
]]
|
]]
|
||||||
|
|
||||||
-- We only check for landing flights.
|
-- We only check for landing flights.
|
||||||
local text=""
|
local text=string.format("%s, %s, ", callsign, self.alias)
|
||||||
if Nlanding==0 then
|
if Nlanding==0 then
|
||||||
text="No current traffic. You are cleared for takeoff."
|
text=text.."no current traffic. You are cleared for takeoff."
|
||||||
self:SetFlightStatus(flight, FLIGHTCONTROL.FlightStatus.TAKEOFF)
|
self:SetFlightStatus(flight, FLIGHTCONTROL.FlightStatus.TAKEOFF)
|
||||||
elseif Nlanding>0 then
|
elseif Nlanding>0 then
|
||||||
if Nlanding==1 then
|
if Nlanding==1 then
|
||||||
text=string.format("Negative, we got %d flight inbound before it's your turn. Hold position until futher notice.", Nlanding)
|
text=text..string.format("negative, we got %d flight inbound before it's your turn. Hold position until futher notice.", Nlanding)
|
||||||
else
|
else
|
||||||
text=string.format("Negative, we got %d flights inbound. Hold positon until futher notice.", Nlanding)
|
text=text..string.format("negative, we got %d flights inbound. Hold positon until futher notice.", Nlanding)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2706,7 +2775,7 @@ function FLIGHTCONTROL:_PlayerRequestTakeoff(groupname)
|
|||||||
self:TransmissionTower(text, flight, 10)
|
self:TransmissionTower(text, flight, 10)
|
||||||
|
|
||||||
-- Update menu.
|
-- Update menu.
|
||||||
flight:_UpdateMenu()
|
flight:_UpdateMenu(0.5)
|
||||||
|
|
||||||
else
|
else
|
||||||
self:TextMessageToFlight(string.format("Negative, you must request TAXI before you can request TAKEOFF!"), flight)
|
self:TextMessageToFlight(string.format("Negative, you must request TAXI before you can request TAKEOFF!"), flight)
|
||||||
@ -2755,7 +2824,7 @@ function FLIGHTCONTROL:_PlayerAbortTakeoff(groupname)
|
|||||||
self:TransmissionTower(text, flight, 10)
|
self:TransmissionTower(text, flight, 10)
|
||||||
|
|
||||||
-- Update menu.
|
-- Update menu.
|
||||||
flight:_UpdateMenu()
|
flight:_UpdateMenu(0.5)
|
||||||
|
|
||||||
else
|
else
|
||||||
self:TextMessageToFlight("Negative, You are NOT in the takeoff queue", flight)
|
self:TextMessageToFlight("Negative, You are NOT in the takeoff queue", flight)
|
||||||
@ -2857,7 +2926,7 @@ function FLIGHTCONTROL:_PlayerArrived(groupname)
|
|||||||
local player=flight:GetPlayerElement()
|
local player=flight:GetPlayerElement()
|
||||||
|
|
||||||
-- Get current coordinate.
|
-- Get current coordinate.
|
||||||
local coord=flight:GetCoordinate(player.name)
|
local coord=flight:GetCoordinate(nil, player.name)
|
||||||
|
|
||||||
--Closest parking spot.
|
--Closest parking spot.
|
||||||
local spot=self:GetClosestParkingSpot(coord)
|
local spot=self:GetClosestParkingSpot(coord)
|
||||||
@ -2882,7 +2951,7 @@ function FLIGHTCONTROL:_PlayerArrived(groupname)
|
|||||||
self:SetFlightStatus(flight, FLIGHTCONTROL.FlightStatus.PARKING)
|
self:SetFlightStatus(flight, FLIGHTCONTROL.FlightStatus.PARKING)
|
||||||
|
|
||||||
-- Create player menu.
|
-- Create player menu.
|
||||||
flight:_UpdateMenu()
|
flight:_UpdateMenu(0.5)
|
||||||
|
|
||||||
-- Create mark on F10 map.
|
-- Create mark on F10 map.
|
||||||
--[[
|
--[[
|
||||||
|
|||||||
@ -385,7 +385,7 @@ function FLIGHTGROUP:SetReadyForTakeoff(ReadyTO, Delay)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set the FLIGHTCONTROL controlling this flight group.
|
--- Set the FLIGHTCONTROL controlling this flight group. Also updates the player menu after 0.5 sec.
|
||||||
-- @param #FLIGHTGROUP self
|
-- @param #FLIGHTGROUP self
|
||||||
-- @param Ops.FlightControl#FLIGHTCONTROL flightcontrol The FLIGHTCONTROL object.
|
-- @param Ops.FlightControl#FLIGHTCONTROL flightcontrol The FLIGHTCONTROL object.
|
||||||
-- @return #FLIGHTGROUP self
|
-- @return #FLIGHTGROUP self
|
||||||
@ -569,7 +569,7 @@ function FLIGHTGROUP:IsParking()
|
|||||||
return self:Is("Parking")
|
return self:Is("Parking")
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Check if flight is parking.
|
--- Check if is taxiing to the runway.
|
||||||
-- @param #FLIGHTGROUP self
|
-- @param #FLIGHTGROUP self
|
||||||
-- @return #boolean If true, flight is taxiing after engine start up.
|
-- @return #boolean If true, flight is taxiing after engine start up.
|
||||||
function FLIGHTGROUP:IsTaxiing()
|
function FLIGHTGROUP:IsTaxiing()
|
||||||
@ -1638,10 +1638,10 @@ function FLIGHTGROUP:onafterSpawned(From, Event, To)
|
|||||||
self:SetFlightControl(flightcontrol)
|
self:SetFlightControl(flightcontrol)
|
||||||
else
|
else
|
||||||
-- F10 other menu.
|
-- F10 other menu.
|
||||||
self:_UpdateMenu()
|
self:_UpdateMenu(0.5)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:_UpdateMenu()
|
self:_UpdateMenu(0.5)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -1679,7 +1679,7 @@ function FLIGHTGROUP:onafterParking(From, Event, To)
|
|||||||
|
|
||||||
if flightcontrol then
|
if flightcontrol then
|
||||||
|
|
||||||
-- Set FC for this flight
|
-- Set FC for this flight. This also updates the menu.
|
||||||
self:SetFlightControl(flightcontrol)
|
self:SetFlightControl(flightcontrol)
|
||||||
|
|
||||||
if self.flightcontrol then
|
if self.flightcontrol then
|
||||||
@ -1779,20 +1779,7 @@ function FLIGHTGROUP:onafterCruise(From, Event, To)
|
|||||||
-- AI
|
-- AI
|
||||||
---
|
---
|
||||||
|
|
||||||
--[[
|
-- Check group Done.
|
||||||
if self:IsTransporting() then
|
|
||||||
if self.cargoTransport and self.cargoTZC and self.cargoTZC.DeployAirbase then
|
|
||||||
self:LandAtAirbase(self.cargoTZC.DeployAirbase)
|
|
||||||
end
|
|
||||||
elseif self:IsPickingup() then
|
|
||||||
if self.cargoTransport and self.cargoTZC and self.cargoTZC.PickupAirbase then
|
|
||||||
self:LandAtAirbase(self.cargoTZC.PickupAirbase)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
self:_CheckGroupDone(nil, 120)
|
|
||||||
end
|
|
||||||
]]
|
|
||||||
|
|
||||||
self:_CheckGroupDone(nil, 120)
|
self:_CheckGroupDone(nil, 120)
|
||||||
|
|
||||||
else
|
else
|
||||||
@ -1801,7 +1788,7 @@ function FLIGHTGROUP:onafterCruise(From, Event, To)
|
|||||||
-- CLIENT
|
-- CLIENT
|
||||||
---
|
---
|
||||||
|
|
||||||
self:_UpdateMenu(0.1)
|
--self:_UpdateMenu(0.1)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -3202,7 +3189,7 @@ function FLIGHTGROUP:_InitGroup(Template)
|
|||||||
|
|
||||||
-- Set callsign. Default is set on spawn if not modified by user.
|
-- Set callsign. Default is set on spawn if not modified by user.
|
||||||
local callsign=template.units[1].callsign
|
local callsign=template.units[1].callsign
|
||||||
self:I({callsign=callsign})
|
--self:I({callsign=callsign})
|
||||||
if type(callsign)=="number" then -- Sometimes callsign is just "101".
|
if type(callsign)=="number" then -- Sometimes callsign is just "101".
|
||||||
local cs=tostring(callsign)
|
local cs=tostring(callsign)
|
||||||
callsign={}
|
callsign={}
|
||||||
@ -4183,9 +4170,16 @@ function FLIGHTGROUP:_UpdateMenu(delay)
|
|||||||
-- Delayed call.
|
-- Delayed call.
|
||||||
self:ScheduleOnce(delay, FLIGHTGROUP._UpdateMenu, self)
|
self:ScheduleOnce(delay, FLIGHTGROUP._UpdateMenu, self)
|
||||||
else
|
else
|
||||||
|
|
||||||
|
-- Message to group.
|
||||||
|
MESSAGE:New("Updating MENU state="..self:GetState(), 5):ToGroup(self.group)
|
||||||
|
env.info(self.lid.."updating menu state=")
|
||||||
|
|
||||||
|
-- Player element.
|
||||||
|
local player=self:GetPlayerElement()
|
||||||
|
|
||||||
-- Get current position of group.
|
-- Get current position of player.
|
||||||
local position=self:GetCoordinate()
|
local position=self:GetCoordinate(nil, player.name)
|
||||||
|
|
||||||
-- Get all FLIGHTCONTROLS
|
-- Get all FLIGHTCONTROLS
|
||||||
local fc={}
|
local fc={}
|
||||||
@ -4211,6 +4205,7 @@ function FLIGHTGROUP:_UpdateMenu(delay)
|
|||||||
-- Remove all submenus.
|
-- Remove all submenus.
|
||||||
self.menu.atc.root:RemoveSubMenus()
|
self.menu.atc.root:RemoveSubMenus()
|
||||||
|
|
||||||
|
-- Create help menu.
|
||||||
self:_CreateMenuAtcHelp(self.menu.atc.root)
|
self:_CreateMenuAtcHelp(self.menu.atc.root)
|
||||||
|
|
||||||
-- Max menu entries.
|
-- Max menu entries.
|
||||||
@ -4260,6 +4255,7 @@ function FLIGHTGROUP:_CreateMenuAtcHelp(rootmenu)
|
|||||||
---
|
---
|
||||||
MENU_GROUP_COMMAND:New(self.group, "Subtitles On/Off", helpmenu, self._MenuNotImplemented, self, groupname)
|
MENU_GROUP_COMMAND:New(self.group, "Subtitles On/Off", helpmenu, self._MenuNotImplemented, self, groupname)
|
||||||
MENU_GROUP_COMMAND:New(self.group, "My Voice On/Off", helpmenu, self._MenuNotImplemented, self, groupname)
|
MENU_GROUP_COMMAND:New(self.group, "My Voice On/Off", helpmenu, self._MenuNotImplemented, self, groupname)
|
||||||
|
MENU_GROUP_COMMAND:New(self.group, "Update Menu", helpmenu, self._UpdateMenu, self, 0)
|
||||||
MENU_GROUP_COMMAND:New(self.group, "My Status", helpmenu, self._PlayerMyStatus, self, groupname)
|
MENU_GROUP_COMMAND:New(self.group, "My Status", helpmenu, self._PlayerMyStatus, self, groupname)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
434
Moose Development/Moose/Ops/Operation.lua
Normal file
434
Moose Development/Moose/Ops/Operation.lua
Normal file
@ -0,0 +1,434 @@
|
|||||||
|
--- **Ops** - Operation with multiple phases.
|
||||||
|
--
|
||||||
|
-- ## Main Features:
|
||||||
|
--
|
||||||
|
-- * Define operation phases
|
||||||
|
-- * Dedicate resources to operations
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ## Example Missions:
|
||||||
|
--
|
||||||
|
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Operation).
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ### Author: **funkyfranky**
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
-- @module Ops.Operation
|
||||||
|
-- @image OPS_Operation.png
|
||||||
|
|
||||||
|
|
||||||
|
--- OPERATION class.
|
||||||
|
-- @type OPERATION
|
||||||
|
-- @field #string ClassName Name of the class.
|
||||||
|
-- @field #number verbose Verbosity level.
|
||||||
|
-- @field #string lid Class id string for output to DCS log file.
|
||||||
|
-- @field #string name Name of the operation.
|
||||||
|
-- @field #table cohorts Dedicated cohorts.
|
||||||
|
-- @field #table legions Dedicated legions.
|
||||||
|
-- @field #table phases Phases.
|
||||||
|
-- @field #number counterPhase Running number counting the phases.
|
||||||
|
-- @field #OPERATION.Phase phase Currently active phase (if any).
|
||||||
|
--
|
||||||
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
|
--- *A warrior's mission is to foster the success of others.* -- Morihei Ueshiba
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- # The OPERATION Concept
|
||||||
|
--
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- @field #OPERATION
|
||||||
|
OPERATION = {
|
||||||
|
ClassName = "OPERATION",
|
||||||
|
verbose = 0,
|
||||||
|
lid = nil,
|
||||||
|
cohorts = {},
|
||||||
|
legions = {},
|
||||||
|
phases = {},
|
||||||
|
counterPhase = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Global mission counter.
|
||||||
|
_OPERATIONID=0
|
||||||
|
|
||||||
|
--- Operation phase.
|
||||||
|
-- @type OPERATION.Phase
|
||||||
|
-- @field #number uid Unique ID of the phase.
|
||||||
|
-- @field #string name Name of the phase.
|
||||||
|
-- @field Core.Condition#CONDITION conditionOver Conditions when the phase is over.
|
||||||
|
-- @field #boolean isOver If `true`, phase is over.
|
||||||
|
|
||||||
|
--- OPERATION class version.
|
||||||
|
-- @field #string version
|
||||||
|
OPERATION.version="0.0.1"
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- TODO list
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- TODO: A lot
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Constructor
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Create a new generic OPERATION object.
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param #string Name Name of the operation. Be creative! Default "Operation-01" where the last number is a running number.
|
||||||
|
-- @return #OPERATION self
|
||||||
|
function OPERATION:New(Name)
|
||||||
|
|
||||||
|
-- Inherit everything from FSM class.
|
||||||
|
local self=BASE:Inherit(self, FSM:New()) -- #OPERATION
|
||||||
|
|
||||||
|
-- Increase global counter.
|
||||||
|
_OPERATIONID=_OPERATIONID+1
|
||||||
|
|
||||||
|
-- Set Name.
|
||||||
|
self.name=Name or string.format("Operation-%02d", _OPERATIONID)
|
||||||
|
|
||||||
|
-- Set log ID.
|
||||||
|
self.lid=string.format("%s | ",self.name)
|
||||||
|
|
||||||
|
|
||||||
|
-- FMS start state is PLANNED.
|
||||||
|
self:SetStartState("Planned")
|
||||||
|
|
||||||
|
-- Add FSM transitions.
|
||||||
|
-- From State --> Event --> To State
|
||||||
|
self:AddTransition("*", "Start", "Running")
|
||||||
|
|
||||||
|
self:AddTransition("*", "StatusUpdate", "*")
|
||||||
|
|
||||||
|
self:AddTransition("Running", "Pause", "Paused")
|
||||||
|
self:AddTransition("Paused", "Unpause", "Running")
|
||||||
|
|
||||||
|
self:AddTransition("*", "ChangePhase", "*")
|
||||||
|
self:AddTransition("*", "PhaseChange", "*")
|
||||||
|
|
||||||
|
self:AddTransition("*", "Over", "Over")
|
||||||
|
|
||||||
|
self:AddTransition("*", "Stop", "Stopped")
|
||||||
|
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
--- Pseudo Functions ---
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
--- Triggers the FSM event "StatusUpdate".
|
||||||
|
-- @function [parent=#OPERATION] StatusUpdate
|
||||||
|
-- @param #OPERATION self
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Status" after a delay.
|
||||||
|
-- @function [parent=#OPERATION] __StatusUpdate
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Stop".
|
||||||
|
-- @function [parent=#OPERATION] Stop
|
||||||
|
-- @param #OPERATION self
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Stop" after a delay.
|
||||||
|
-- @function [parent=#OPERATION] __Stop
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
|
||||||
|
--- Triggers the FSM event "PhaseChange".
|
||||||
|
-- @function [parent=#OPERATION] PhaseChange
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param #OPERATION.Phase Phase The new phase.
|
||||||
|
|
||||||
|
--- Triggers the FSM event "PhaseChange" after a delay.
|
||||||
|
-- @function [parent=#OPERATION] __PhaseChange
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
-- @param #OPERATION.Phase Phase The new phase.
|
||||||
|
|
||||||
|
--- On after "PhaseChange" event.
|
||||||
|
-- @function [parent=#OPERATION] OnAfterPhaseChange
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param #OPERATION.Phase Phase The new phase.
|
||||||
|
|
||||||
|
-- Init status update.
|
||||||
|
self:__StatusUpdate(-1)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- User API Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Create a new generic OPERATION object.
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param #string Name Name of the phase. Default "Phase-01" where the last number is a running number.
|
||||||
|
-- @param Core.Condition#CONDITION ConditionOver Condition when the phase is over.
|
||||||
|
-- @return #OPERATION.Phase Phase table object.
|
||||||
|
function OPERATION:AddPhase(Name, ConditionOver)
|
||||||
|
|
||||||
|
-- Increase phase counter.
|
||||||
|
self.counterPhase=self.counterPhase+1
|
||||||
|
|
||||||
|
local phase={} --#OPERATION.Phase
|
||||||
|
phase.uid=self.counterPhase
|
||||||
|
phase.name=Name or string.format("Phase-%02d", self.counterPhase)
|
||||||
|
phase.conditionOver=ConditionOver or CONDITION:New(Name)
|
||||||
|
phase.isOver=false
|
||||||
|
|
||||||
|
-- Add phase.
|
||||||
|
table.insert(self.phases, phase)
|
||||||
|
|
||||||
|
return phase
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get a phase by its name.
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param #string Name Name of the phase. Default "Phase-01" where the last number is a running number.
|
||||||
|
-- @return #OPERATION.Phase Phase table object or nil if phase could not be found.
|
||||||
|
function OPERATION:GetPhaseByName(Name)
|
||||||
|
|
||||||
|
for _,_phase in pairs(self.phases or {}) do
|
||||||
|
local phase=_phase --#OPERATION.Phase
|
||||||
|
if phase.name==Name then
|
||||||
|
return phase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Assign cohort to operation.
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param Ops.Cohort#COHORT Cohort The cohort
|
||||||
|
-- @return #OPERATION self
|
||||||
|
function OPERATION:AssignCohort(Cohort)
|
||||||
|
|
||||||
|
self.cohorts[Cohort.name]=Cohort
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Assign legion to operation. All cohorts of this legion will be assigned and are only available
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param Ops.Legion#LEGION Legion The legion to be assigned.
|
||||||
|
-- @return #OPERATION self
|
||||||
|
function OPERATION:AssignLegion(Legion)
|
||||||
|
|
||||||
|
self.legions[Legion.alias]=Legion
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Set start and stop time of the operation.
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param #string ClockStart Time the mission is started, e.g. "05:00" for 5 am. If specified as a #number, it will be relative (in seconds) to the current mission time. Default is 5 seconds after mission was added.
|
||||||
|
-- @param #string ClockStop (Optional) Time the mission is stopped, e.g. "13:00" for 1 pm. If mission could not be started at that time, it will be removed from the queue. If specified as a #number it will be relative (in seconds) to the current mission time.
|
||||||
|
-- @return #OPERATION self
|
||||||
|
function OPERATION:SetTime(ClockStart, ClockStop)
|
||||||
|
|
||||||
|
-- Current mission time.
|
||||||
|
local Tnow=timer.getAbsTime()
|
||||||
|
|
||||||
|
-- Set start time. Default in 5 sec.
|
||||||
|
local Tstart=Tnow+5
|
||||||
|
if ClockStart and type(ClockStart)=="number" then
|
||||||
|
Tstart=Tnow+ClockStart
|
||||||
|
elseif ClockStart and type(ClockStart)=="string" then
|
||||||
|
Tstart=UTILS.ClockToSeconds(ClockStart)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set stop time. Default nil.
|
||||||
|
local Tstop=nil
|
||||||
|
if ClockStop and type(ClockStop)=="number" then
|
||||||
|
Tstop=Tnow+ClockStop
|
||||||
|
elseif ClockStop and type(ClockStop)=="string" then
|
||||||
|
Tstop=UTILS.ClockToSeconds(ClockStop)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.Tstart=Tstart
|
||||||
|
self.Tstop=Tstop
|
||||||
|
|
||||||
|
if Tstop then
|
||||||
|
self.duration=self.Tstop-self.Tstart
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get currrently active phase.
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @return #OPERATION.Phase Current phase or `nil` if no current phase is active.
|
||||||
|
function OPERATION:GetPhaseActive()
|
||||||
|
return self.phase
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get next phase.
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @return #OPERATION.Phase Next phase or `nil` if no next phase exists.
|
||||||
|
function OPERATION:GetPhaseNext()
|
||||||
|
|
||||||
|
for _,_phase in pairs(self.phases or {}) do
|
||||||
|
local phase=_phase --#OPERATION.Phase
|
||||||
|
|
||||||
|
if not phase.isOver then
|
||||||
|
-- Return first phase that is not over.
|
||||||
|
return phase
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Count phases.
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @return #number Number of phases
|
||||||
|
function OPERATION:CountPhases()
|
||||||
|
|
||||||
|
local N=0
|
||||||
|
for phasename, phase in pairs(self.phases) do
|
||||||
|
N=N+1
|
||||||
|
end
|
||||||
|
|
||||||
|
return N
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Status Update
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- On after "Start" event.
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
function OPERATION:onafterStart(From, Event, To)
|
||||||
|
|
||||||
|
-- Get
|
||||||
|
local Phase=self:GetPhaseNext()
|
||||||
|
|
||||||
|
if Phase then
|
||||||
|
self:PhaseChange(Phase)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- On after "StatusUpdate" event.
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
function OPERATION:onafterStatusUpdate(From, Event, To)
|
||||||
|
|
||||||
|
-- Current abs. mission time.
|
||||||
|
local Tnow=timer.getAbsTime()
|
||||||
|
|
||||||
|
-- Current FSM state.
|
||||||
|
local fsmstate=self:GetState()
|
||||||
|
|
||||||
|
-- Current phase.
|
||||||
|
local currphase=self:GetPhaseActive()
|
||||||
|
local phasename=currphase and currphase.name or "None"
|
||||||
|
local Nphase=self:CountPhases()
|
||||||
|
|
||||||
|
-- General info.
|
||||||
|
local text=string.format("State=%s: Phase=%s, Phases=%d", fsmstate, phasename, Nphase)
|
||||||
|
self:I(self.lid..text)
|
||||||
|
|
||||||
|
-- Info on phases.
|
||||||
|
local text="Phases:"
|
||||||
|
for i,_phase in pairs(self.phases) do
|
||||||
|
local phase=_phase --#OPERATION.Phase
|
||||||
|
text=text..string.format("\n[%d] %s", i, phase.name)
|
||||||
|
end
|
||||||
|
if text=="Phases:" then text=text.." None" end
|
||||||
|
|
||||||
|
-- Next status update.
|
||||||
|
self:__StatusUpdate(-30)
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- FSM Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- On after "ChangePhase" event.
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param #OPERATION.Phase Phase The new phase.
|
||||||
|
function OPERATION:onafterChangePhase(From, Event, To, Phase)
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
|
self:T(self.lid..string.format("Changed to phase: %s", Phase.name))
|
||||||
|
|
||||||
|
-- Set currently active phase.
|
||||||
|
self.phase=Phase
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On after "Over" event.
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param #OPERATION.Phase Phase The new phase.
|
||||||
|
function OPERATION:onafterOver(From, Event, To)
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
|
self:T(self.lid..string.format("Operation is over!"))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Misc Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Check phases.
|
||||||
|
-- @param #OPERATION self
|
||||||
|
function OPERATION:_CheckPhases()
|
||||||
|
|
||||||
|
-- Currently active phase.
|
||||||
|
local phase=self:GetPhaseActive()
|
||||||
|
|
||||||
|
-- Check if active phase is over.
|
||||||
|
if phase then
|
||||||
|
phase.isOver=phase.conditionOver:Evaluate()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If no current phase or current phase is over, get next phase.
|
||||||
|
if phase==nil or (phase and phase.isOver) then
|
||||||
|
|
||||||
|
-- Get next phase.
|
||||||
|
local Phase=self:GetPhaseNext()
|
||||||
|
|
||||||
|
if Phase then
|
||||||
|
|
||||||
|
-- Change phase to next one.
|
||||||
|
self:PhaseChange(Phase)
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- No further phases defined ==> Operation is over.
|
||||||
|
self:Over()
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -11607,7 +11607,7 @@ function OPSGROUP:SetDefaultCallsign(CallsignName, CallsignNumber)
|
|||||||
self.callsignDefault.NumberGroup=CallsignNumber or 1
|
self.callsignDefault.NumberGroup=CallsignNumber or 1
|
||||||
self.callsignDefault.NameSquad=UTILS.GetCallsignName(self.callsign.NumberSquad)
|
self.callsignDefault.NameSquad=UTILS.GetCallsignName(self.callsign.NumberSquad)
|
||||||
|
|
||||||
self:I(self.lid..string.format("Default callsign=%s", self.callsignDefault.NameSquad))
|
--self:I(self.lid..string.format("Default callsign=%s", self.callsignDefault.NameSquad))
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|||||||
@ -30,6 +30,7 @@ Core/Timer.lua
|
|||||||
Core/Goal.lua
|
Core/Goal.lua
|
||||||
Core/Spot.lua
|
Core/Spot.lua
|
||||||
Core/TextAndSound.lua
|
Core/TextAndSound.lua
|
||||||
|
Core/Condition.lua
|
||||||
|
|
||||||
Wrapper/Object.lua
|
Wrapper/Object.lua
|
||||||
Wrapper/Identifiable.lua
|
Wrapper/Identifiable.lua
|
||||||
@ -96,6 +97,7 @@ Ops/Chief.lua
|
|||||||
Ops/CSAR.lua
|
Ops/CSAR.lua
|
||||||
Ops/CTLD.lua
|
Ops/CTLD.lua
|
||||||
Ops/Awacs.lua
|
Ops/Awacs.lua
|
||||||
|
Ops/Operation.lua
|
||||||
Ops/FlightControl.lua
|
Ops/FlightControl.lua
|
||||||
|
|
||||||
AI/AI_Balancer.lua
|
AI/AI_Balancer.lua
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user