This commit is contained in:
Frank
2020-04-19 23:49:08 +02:00
parent 54e799d3f6
commit 31697030ed
5 changed files with 280 additions and 47 deletions
@@ -5176,7 +5176,7 @@ function WAREHOUSE:onafterAssetSpawned(From, Event, To, group, asset, request)
local assetitem=_asset --#WAREHOUSE.Assetitem
-- Debug info.
self:T2(self.lid..string.format("Asset %s spawned %s as %s", assetitem.templatename, tostring(assetitem.spawned), tostring(assetitem.spawngroupname)))
self:I(self.lid..string.format("Asset %s spawned=%s as %s", assetitem.templatename, tostring(assetitem.spawned), tostring(assetitem.spawngroupname)))
if assetitem.spawned then
n=n+1
@@ -5680,7 +5680,9 @@ function WAREHOUSE:_SpawnAssetAircraft(alias, asset, request, parking, uncontrol
local AirbaseCategory = self:GetAirbaseCategory()
-- Check enough parking spots.
if AirbaseCategory==Airbase.Category.HELIPAD or AirbaseCategory==Airbase.Category.SHIP then
if AirbaseCategory==Airbase.Category.HELIPAD then
elseif AirbaseCategory==Airbase.Category.SHIP then
--TODO Figure out what's necessary in this case.
@@ -7547,17 +7549,29 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets)
for i,unit in pairs(units) do
local coord=COORDINATE:New(unit.x, unit.alt, unit.y)
coords[unit.name]=coord
--[[
local airbase=coord:GetClosestAirbase()
local _,TermID, dist, spot=coord:GetClosestParkingSpot(airbase)
if dist<=10 then
env.info(string.format("Found client %s on parking spot %d at airbase %s", unit.name, TermID, airbase:GetName()))
end
]]
end
end
return coords
end
if airbase:GetAirbaseCategory()==Airbase.Category.SHIP then
-- Scan a radius of 100 meters around the spot.
local _,_,_,units=airbase:GetCoordinate():ScanObjects(200, true, false, false)
local N=0
for _,_unit in pairs(units) do
local unit=_unit --Wrapper.Unit#UNIT
if not unit:InAir() then
N=N+1
end
end
env.info(string.format("FF number of units on deck=%d", N))
if #assets>=6 and N==0 then
-- More than 6 is difficult. We need an empty deck.
elseif N+#assets>6 then
-- wait until max 6 ac are on deck.
return {}
end
end
-- Get parking spot data table. This contains all free and "non-free" spots.
local parkingdata=airbase:GetParkingSpotsTable()
+23 -2
View File
@@ -720,7 +720,7 @@ function AIRWING:onafterStatus(From, Event, To)
local skill=squadron.skill and tostring(squadron.skill) or "N/A"
-- Squadron text
text=text..string.format("\n* %s %s: %s*%d, Callsign=%s, Modex=%d, Skill=%s", squadron.name, squadron:GetState(), squadron.aircrafttype, #squadron.assets, callsign, modex, skill)
text=text..string.format("\n* %s %s: %s*%d (avail %d), Callsign=%s, Modex=%d, Skill=%s", squadron.name, squadron:GetState(), squadron.aircrafttype, #squadron.assets, squadron:CountAssetsInStock(), callsign, modex, skill)
-- Loop over all assets.
if self.verbose>0 then
@@ -773,7 +773,10 @@ function AIRWING:onafterStatus(From, Event, To)
--------------
-- Mission ---
--------------
-- Check if any missions should be cancelled.
self:_CheckMissions()
-- Get next mission.
local mission=self:_GetNextMission()
@@ -975,6 +978,24 @@ function AIRWING:GetTankerForFlight(flightgroup)
end
--- Get next mission.
-- @param #AIRWING self
function AIRWING:_CheckMissions()
-- Loop over missions in queue.
for _,_mission in pairs(self.missionqueue) do
local mission=_mission --Ops.Auftrag#AUFTRAG
if mission:IsNotOver() then
if mission:IsReadyToCancel() then
mission:Cancel()
end
end
end
end
--- Get next mission.
-- @param #AIRWING self
-- @return Ops.Auftrag#AUFTRAG Next mission or *nil*.
+212 -33
View File
@@ -37,7 +37,9 @@
-- @field #number Ntargets Number of mission targets.
-- @field #number dTevaluate Time interval in seconds before the mission result is evaluated after mission is over.
-- @field #number Tover Mission abs. time stamp, when mission was over.
-- @field #table startconditions Conditions that have to be true, before the mission is started.
-- @field #table conditionStart Condition(s) that have to be true, before the mission will be started.
-- @field #table conditionSuccess If all stop conditions are true, the mission is cancelled.
-- @field #table conditionFailure If all stop conditions are true, the mission is cancelled.
--
-- @field #number orbitSpeed Orbit speed in m/s.
-- @field #number orbitAltitude Orbit altitude in meters.
@@ -164,7 +166,9 @@ AUFTRAG = {
missionFraction = 0.5,
enrouteTasks = {},
marker = nil,
startconditions = {},
conditionStart = {},
conditionSuccess = {},
conditionFailure = {},
}
--- Global mission counter.
@@ -299,10 +303,10 @@ AUFTRAG.TargetType={
-- @field #string DAMAGED Target was damaged.
-- @field #string DESTROYED Target was destroyed.
--- Mission start condition.
-- @type AUFTRAG.ConditionStart
-- @field #function funcReady Callback function to check whether the mission can be started. Should return a #boolean.
-- @field #table argReady Arguments passed to the callback function.
--- Generic mission condition.
-- @type AUFTRAG.Condition
-- @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.
--- Flight specific data. Each flight subscribed to this mission has different data for this.
-- @type AUFTRAG.FlightData
@@ -316,7 +320,7 @@ AUFTRAG.TargetType={
--- AUFTRAG class version.
-- @field #string version
AUFTRAG.version="0.1.7"
AUFTRAG.version="0.2.0"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@@ -1235,17 +1239,57 @@ end
-- @param #function ConditionFunction Function that needs to be true before the mission can be started. Must return a #boolean.
-- @param ... Condition function arguments if any.
-- @return #AUFTRAG self
function AUFTRAG:AddStartCondition(ConditionFunction, ...)
function AUFTRAG:AddConditionStart(ConditionFunction, ...)
local condition={} --#AUFTRAG.ConditionStart
local condition={} --#AUFTRAG.Condition
condition.funcReady=ConditionFunction
condition.argReady={}
condition.func=ConditionFunction
condition.arg={}
if arg then
condition.argReady=arg
condition.arg=arg
end
table.insert(self.startconditions, condition)
table.insert(self.conditionStart, condition)
return self
end
--- Add success condition.
-- @param #AUFTRAG self
-- @param #function ConditionFunction If this function returns `true`, the mission is cancelled.
-- @param ... Condition function arguments if any.
-- @return #AUFTRAG self
function AUFTRAG:AddConditionSuccess(ConditionFunction, ...)
local condition={} --#AUFTRAG.Condition
condition.func=ConditionFunction
condition.arg={}
if arg then
condition.arg=arg
end
table.insert(self.conditionSuccess, condition)
return self
end
--- Add failure condition.
-- @param #AUFTRAG self
-- @param #function ConditionFunction If this function returns `true`, the mission is cancelled.
-- @param ... Condition function arguments if any.
-- @return #AUFTRAG self
function AUFTRAG:AddConditionFailure(ConditionFunction, ...)
local condition={} --#AUFTRAG.Condition
condition.func=ConditionFunction
condition.arg={}
if arg then
condition.arg=arg
end
table.insert(self.conditionFailure, condition)
return self
end
@@ -1328,6 +1372,13 @@ function AUFTRAG:IsScheduled()
return self.status==AUFTRAG.Status.SCHEDULED
end
--- Check if mission is STARTED, i.e. flight is on its way to the mission execution waypoint.
-- @param #AUFTRAG self
-- @return #boolean If true, mission is started.
function AUFTRAG:IsStarted()
return self.status==AUFTRAG.Status.STARTED
end
--- Check if mission is executing.
-- @param #AUFTRAG self
-- @return #boolean If true, mission is currently executing.
@@ -1374,7 +1425,7 @@ end
--- Check if mission is ready to be started.
-- * Mission start time passed.
-- * Mission stop time did not pass already.
-- * Any start conditions are true.
-- * All start conditions are true.
-- @param #AUFTRAG self
-- @return #boolean If true, mission can be started.
function AUFTRAG:IsReadyToGo()
@@ -1391,23 +1442,100 @@ function AUFTRAG:IsReadyToGo()
return false
end
-- All start conditions must be true.
for _,_condition in pairs(self.startconditions or {}) do
local condition=_condition --#AUFTRAG.ConditionStart
-- All start conditions true?
local startme=self:EvalConditionsAll(self.conditionStart)
if not startme then
return false
end
-- We're good to go!
return true
end
--- Check if mission is ready to be started.
-- * Mission stop already passed.
-- * Any stop condition is true.
-- @param #AUFTRAG self
-- @return #boolean If true, mission should be cancelled.
function AUFTRAG:IsReadyToCancel()
local Tnow=timer.getAbsTime()
-- Stop time already passed.
if self.Tstop and Tnow>self.Tstop then
return true
end
local failure=self:EvalConditionsAny(self.conditionFailure)
if failure then
self.failurecondition=true
return true
end
local success=self:EvalConditionsAny(self.conditionSuccess)
if success then
self.successcondition=true
return true
end
-- No criterion matched.
return false
end
--- Check if all given condition are true.
-- @param #AUFTRAG self
-- @param #table Conditions Table of conditions.
-- @return #boolean If true, all conditions were true. Returns false if at least one condition returned false.
function AUFTRAG:EvalConditionsAll(Conditions)
-- Any stop condition must be true.
for _,_condition in pairs(Conditions or {}) do
local condition=_condition --#AUFTRAG.Condition
-- Call function.
local ready=condition.funcReady(unpack(condition.argReady))
local istrue=condition.func(unpack(condition.arg))
if not ready then
-- Any false will return false.
if not istrue then
return false
end
end
-- We're good to go!
-- All conditions were true.
return true
end
--- Check if any of the given conditions is true.
-- @param #AUFTRAG self
-- @param #table Conditions Table of conditions.
-- @return #boolean If true, at least one condition is true.
function AUFTRAG:EvalConditionsAny(Conditions)
-- Any stop condition must be true.
for _,_condition in pairs(Conditions or {}) do
local condition=_condition --#AUFTRAG.Condition
-- 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.
return false
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Mission Status
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -1500,6 +1628,15 @@ function AUFTRAG:Evaluate()
-- Assume success and check if any failed condition applies.
local failed=false
-- Any success condition true?
local successCondition=self:EvalConditionsAny(self.conditionSuccess)
-- Any failure condition true?
local failureCondition=self:EvalConditionsAny(self.conditionFailure)
-- Target damage in %.
local targetdamage=self:GetTargetDamage()
-- Current number of mission targets.
local Ntargets=self:CountMissionTargets()
@@ -1511,7 +1648,21 @@ function AUFTRAG:Evaluate()
--TODO: all assets dead? Is this a FAILED criterion even if all targets have been destroyed? What if there are no initial targets (e.g. when ORBIT, PATROL, RECON missions).
self:I(self.lid..string.format("Evaluating mission: Initial Targets=%d, current targets=%d ==> success=%s", self.Ntargets, Ntargets, tostring(not failed)))
--self:I(self.lid..string.format("Evaluating mission: Initial Targets=%d, current targets=%d ==> success=%s", self.Ntargets, Ntargets, tostring(not failed)))
if failureCondition then
failed=true
elseif successCondition then
failed=false
end
local text=string.format("Evaluating mission:\n")
text=text..string.format("Targets = %d/%d\n", self.Ntargets, Ntargets)
text=text..string.format("Damage = %.1f %%\n", targetdamage)
text=text..string.format("Success Cond = %s\n", tostring(successCondition))
text=text..string.format("Failure Cond = %s", tostring(failureCondition))
self:I(self.lid..text)
if failed then
self:Failed()
@@ -1652,6 +1803,10 @@ function AUFTRAG:CheckFlightsDone()
return false
end
-- It could be that all flights were destroyed on the way to the mission execution waypoint.
if self:IsStarted() and self:CountFlightGroups()==0 then
return true
end
-- Check status of all flight groups.
for groupname,data in pairs(self.flightdata) do
@@ -2157,24 +2312,45 @@ end
--- Get target damage.
-- @param #AUFTRAG self
-- @return #number Percent.
-- @return #number Damage in percent.
function AUFTRAG:GetTargetDamage()
local target=self:GetTargetData()
local life=self:GetTargetLife()/self:GetTargetData().Lifepoints
local life=self:GetTargetLife()/self:GetTargetInitialLife()
local damage=1-life
return damage*100
end
--- Get target life points.
-- @param #AUFTRAG self
-- @return #number Life points of target.
function AUFTRAG:GetTargetLife()
return self:_GetTargetLife(nil, false)
end
--- Get target life points.
-- @param #AUFTRAG self
-- @param #AUFTRAG.TargetData Target (Optional) The target object.
-- @param #boolean Healthy Get the life points of the healthy target.
-- @return #number Life points of target.
function AUFTRAG:GetTargetLife(Target)
function AUFTRAG:_GetTargetLife(Target, Healthy)
local N=0
Target=Target or self:GetTargetData()
local function _GetLife(unit)
local unit=unit --Wrapper.Unit#UNIT
if Healthy then
local life=unit:GetLife()
local life0=unit:GetLife0()
return math.max(life, life0)
else
return unit:GetLife()
end
end
if Target then
if Target.Type==AUFTRAG.TargetType.GROUP then
@@ -2188,7 +2364,7 @@ function AUFTRAG:GetTargetLife(Target)
-- We check that unit is "alive".
if unit and unit:IsAlive() then
N=N+unit:GetLife()
N=N+_GetLife(unit)
end
end
@@ -2197,15 +2373,18 @@ function AUFTRAG:GetTargetLife(Target)
local target=Target.Target --Wrapper.Unit#UNIT
if target and target:IsAlive() then
N=N+target:GetLife()
N=N+_GetLife(target)
end
elseif Target.Type==AUFTRAG.TargetType.STATIC then
local target=Target.Target --Wrapper.Static#STATIC
-- Statics are alive or not.
if target and target:IsAlive() then
N=N+1 --target:GetLife()
N=N+1 --_GetLife(target)
else
N=N+0
end
elseif Target.Type==AUFTRAG.TargetType.AIRBASE then
@@ -2230,7 +2409,7 @@ function AUFTRAG:GetTargetLife(Target)
-- We check that unit is "alive".
if unit and unit:IsAlive() then
N=N+unit:GetLife()
N=N+_GetLife(unit)
end
end
@@ -2243,13 +2422,13 @@ function AUFTRAG:GetTargetLife(Target)
-- We check that unit is "alive".
if unit and unit:IsAlive() then
N=N+unit:GetLife()
N=N+_GetLife(unit)
end
end
else
self:E("ERROR unknown target type")
self:E(self.lid.."ERROR unknown target type")
end
end
@@ -2788,7 +2967,7 @@ function AUFTRAG:_TargetFromObject(Object)
local Ninitial=self:CountMissionTargets(target)
-- Initial total life point.
local Lifepoints=self:GetTargetLife(target)
local Lifepoints=self:_GetTargetLife(target, true)
-- Set engage Target.
self.engageTarget=target
@@ -2798,8 +2977,8 @@ function AUFTRAG:_TargetFromObject(Object)
-- TODO: get rid of this.
self.Ntargets=Ninitial
env.info("FF check")
self:I(self.lid..string.format("Mission Target Type=%s, Ntargets=%d", target.Type, self.Ntargets))
-- Debug info.
self:I(self.lid..string.format("Mission Target %s Type=%s, Ntargets=%d, Lifepoints=%d", target.Name, target.Type, Ninitial, Lifepoints))
return target
end
+4 -3
View File
@@ -2416,8 +2416,9 @@ end
function FLIGHTGROUP:onafterFlightArrived(From, Event, To)
self:T(self.lid..string.format("Flight arrived"))
-- Remove flight from landing queue.
-- Flight Control
if self.flightcontrol then
-- Remove flight from landing queue.
self.flightcontrol:_RemoveFlightFromQueue(self.flightcontrol.Qtaxiinb, self, "TAXI_INB")
-- Add flight to arrived queue.
self.flightcontrol:_AddFlightToArrivedQueue(self)
@@ -2829,7 +2830,7 @@ function FLIGHTGROUP:onafterRTB(From, Event, To, airbase, SpeedTo, SpeedHold, Sp
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
self:T(self.lid..text)
local althold=self.ishelo and 1000 or 6000
local althold=self.ishelo and 1000+math.random(10)*100 or math.random(4,10)*1000
-- Holding points.
local c0=self.group:GetCoordinate()
@@ -2874,7 +2875,7 @@ function FLIGHTGROUP:onafterRTB(From, Event, To, airbase, SpeedTo, SpeedHold, Sp
self.flaghold:Set(0)
-- Task fuction when reached holding point.
local TaskArrived=self.group:TaskFunction("FLIGHTGROUP._ReachedHolding", self)
local TaskArrived=self.group:TaskFunction("FLIGHTGROUP.", self)
-- Orbit until flaghold=1 (true) but max 5 min if no FC is giving the landing clearance.
local TaskOrbit=self.group:TaskOrbit(p0, nil, UTILS.KnotsToMps(SpeedHold), p1)
+18
View File
@@ -614,6 +614,24 @@ function SQUADRON:CanMission(Mission)
return true
end
--- Get assets for a mission.
-- @param #SQUADRON self
-- @return #number Assets not spawned.
function SQUADRON:CountAssetsInStock()
local N=0
for _,_asset in pairs(self.assets) do
local asset=_asset --Ops.AirWing#AIRWING.SquadronAsset
if asset.spawned then
else
N=N+1
end
end
return N
end
--- Get assets for a mission.
-- @param #SQUADRON self
-- @param Ops.Auftrag#AUFTRAG Mission The mission.