mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
OPS Commander
This commit is contained in:
parent
418d6c882c
commit
1b0ad13529
@ -1622,13 +1622,17 @@ WAREHOUSE = {
|
|||||||
-- @field #boolean spawned If true, asset was spawned into the cruel world. If false, it is still in stock.
|
-- @field #boolean spawned If true, asset was spawned into the cruel world. If false, it is still in stock.
|
||||||
-- @field #string spawngroupname Name of the spawned group.
|
-- @field #string spawngroupname Name of the spawned group.
|
||||||
-- @field #boolean iscargo If true, asset is cargo. If false asset is transport. Nil if in stock.
|
-- @field #boolean iscargo If true, asset is cargo. If false asset is transport. Nil if in stock.
|
||||||
-- @field #number rid The request ID of this asset.
|
|
||||||
-- @field #boolean arrived If true, asset arrived at its destination.
|
-- @field #boolean arrived If true, asset arrived at its destination.
|
||||||
|
--
|
||||||
-- @field #number damage Damage of asset group in percent.
|
-- @field #number damage Damage of asset group in percent.
|
||||||
-- @field Ops.AirWing#AIRWING.Payload payload The payload of the asset.
|
-- @field Ops.AirWing#AIRWING.Payload payload The payload of the asset.
|
||||||
-- @field Ops.FlightGroup#FLIGHTGROUP flightgroup The flightgroup object.
|
-- @field Ops.OpsGroup#OPSGROUP flightgroup The flightgroup object.
|
||||||
|
-- @field Ops.Cohort#COHORT cohort The cohort this asset belongs to.
|
||||||
|
-- @field Ops.Legion#LEGION legion The legion this asset belonts to.
|
||||||
-- @field #string squadname Name of the squadron this asset belongs to.
|
-- @field #string squadname Name of the squadron this asset belongs to.
|
||||||
-- @field #number Treturned Time stamp when asset returned to the airwing.
|
-- @field #number Treturned Time stamp when asset returned to its legion (airwing, brigade).
|
||||||
|
-- @field #boolean requested If `true`, asset was requested and cannot be selected by another request.
|
||||||
|
-- @field #boolean isReserved If `true`, asset was reserved and cannot be selected by another request.
|
||||||
|
|
||||||
--- Item of the warehouse queue table.
|
--- Item of the warehouse queue table.
|
||||||
-- @type WAREHOUSE.Queueitem
|
-- @type WAREHOUSE.Queueitem
|
||||||
@ -3118,14 +3122,16 @@ end
|
|||||||
-- @param #WAREHOUSE self
|
-- @param #WAREHOUSE self
|
||||||
-- @return DCS#Vec3 The 3D vector of the warehouse.
|
-- @return DCS#Vec3 The 3D vector of the warehouse.
|
||||||
function WAREHOUSE:GetVec3()
|
function WAREHOUSE:GetVec3()
|
||||||
return self.warehouse:GetVec3()
|
local vec3=self.warehouse:GetVec3()
|
||||||
|
return vec3
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get 2D vector of warehouse static.
|
--- Get 2D vector of warehouse static.
|
||||||
-- @param #WAREHOUSE self
|
-- @param #WAREHOUSE self
|
||||||
-- @return DCS#Vec2 The 2D vector of the warehouse.
|
-- @return DCS#Vec2 The 2D vector of the warehouse.
|
||||||
function WAREHOUSE:GetVec2()
|
function WAREHOUSE:GetVec2()
|
||||||
return self.warehouse:GetVec2()
|
local vec2=self.warehouse:GetVec2()
|
||||||
|
return vec2
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -3194,18 +3200,6 @@ function WAREHOUSE:GetAssignment(request)
|
|||||||
return tostring(request.assignment)
|
return tostring(request.assignment)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
|
||||||
--- Get warehouse unique ID from static warehouse object. This is the ID under which you find the @{#WAREHOUSE} object in the global data base.
|
|
||||||
-- @param #WAREHOUSE self
|
|
||||||
-- @param #string staticname Name of the warehouse static object.
|
|
||||||
-- @return #number Warehouse unique ID.
|
|
||||||
function WAREHOUSE:GetWarehouseID(staticname)
|
|
||||||
local warehouse=STATIC:FindByName(staticname, true)
|
|
||||||
local uid=tonumber(warehouse:GetID())
|
|
||||||
return uid
|
|
||||||
end
|
|
||||||
]]
|
|
||||||
|
|
||||||
--- Find a warehouse in the global warehouse data base.
|
--- Find a warehouse in the global warehouse data base.
|
||||||
-- @param #WAREHOUSE self
|
-- @param #WAREHOUSE self
|
||||||
-- @param #number uid The unique ID of the warehouse.
|
-- @param #number uid The unique ID of the warehouse.
|
||||||
@ -3951,6 +3945,8 @@ function WAREHOUSE:onafterAddAsset(From, Event, To, group, ngroups, forceattribu
|
|||||||
|
|
||||||
-- Asset is not spawned.
|
-- Asset is not spawned.
|
||||||
asset.spawned=false
|
asset.spawned=false
|
||||||
|
asset.requested=false
|
||||||
|
asset.isReserved=false
|
||||||
asset.iscargo=nil
|
asset.iscargo=nil
|
||||||
asset.arrived=nil
|
asset.arrived=nil
|
||||||
|
|
||||||
@ -4141,6 +4137,8 @@ function WAREHOUSE:_RegisterAsset(group, ngroups, forceattribute, forcecargobay,
|
|||||||
asset.skill=skill
|
asset.skill=skill
|
||||||
asset.assignment=assignment
|
asset.assignment=assignment
|
||||||
asset.spawned=false
|
asset.spawned=false
|
||||||
|
asset.requested=false
|
||||||
|
asset.isReserved=false
|
||||||
asset.life0=group:GetLife0()
|
asset.life0=group:GetLife0()
|
||||||
asset.damage=0
|
asset.damage=0
|
||||||
asset.spawngroupname=string.format("%s_AID-%d", templategroupname, asset.uid)
|
asset.spawngroupname=string.format("%s_AID-%d", templategroupname, asset.uid)
|
||||||
|
|||||||
@ -372,6 +372,8 @@ end
|
|||||||
function COHORT:AddAsset(Asset)
|
function COHORT:AddAsset(Asset)
|
||||||
self:T(self.lid..string.format("Adding asset %s of type %s", Asset.spawngroupname, Asset.unittype))
|
self:T(self.lid..string.format("Adding asset %s of type %s", Asset.spawngroupname, Asset.unittype))
|
||||||
Asset.squadname=self.name
|
Asset.squadname=self.name
|
||||||
|
Asset.legion=self.legion
|
||||||
|
Asset.cohort=self
|
||||||
table.insert(self.assets, Asset)
|
table.insert(self.assets, Asset)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -700,7 +702,7 @@ end
|
|||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
--- Check if there is a cohort that can execute a given mission.
|
--- Check if there is a cohort that can execute a given mission.
|
||||||
-- We check the mission type, the refuelling system, engagement range
|
-- We check the mission type, the refuelling system, mission range.
|
||||||
-- @param #COHORT self
|
-- @param #COHORT self
|
||||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||||
-- @return #boolean If true, Cohort can do that type of mission.
|
-- @return #boolean If true, Cohort can do that type of mission.
|
||||||
|
|||||||
@ -28,15 +28,13 @@
|
|||||||
--
|
--
|
||||||
-- # The COMMANDER Concept
|
-- # The COMMANDER Concept
|
||||||
--
|
--
|
||||||
-- A commander is the head of legions. He will find the best LEGIONs to perform an assigned AUFTRAG (mission).
|
-- A commander is the head of legions. He/she will find the best LEGIONs to perform an assigned AUFTRAG (mission).
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- @field #COMMANDER
|
-- @field #COMMANDER
|
||||||
COMMANDER = {
|
COMMANDER = {
|
||||||
ClassName = "COMMANDER",
|
ClassName = "COMMANDER",
|
||||||
Debug = nil,
|
legions = {},
|
||||||
lid = nil,
|
|
||||||
legions = {},
|
|
||||||
missionqueue = {},
|
missionqueue = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,6 +48,8 @@ COMMANDER.version="0.1.0"
|
|||||||
|
|
||||||
-- TODO: Improve legion selection. Mostly done!
|
-- TODO: Improve legion selection. Mostly done!
|
||||||
-- TODO: Allow multiple Legions for one mission.
|
-- TODO: Allow multiple Legions for one mission.
|
||||||
|
-- TODO: Add ops transports.
|
||||||
|
-- TODO: Find solution for missions, which require a transport. This is not as easy as it sounds since the selected mission assets restrict the possible transport assets.
|
||||||
-- NOGO: Maybe it's possible to preselect the assets for the mission.
|
-- NOGO: Maybe it's possible to preselect the assets for the mission.
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -247,15 +247,19 @@ function COMMANDER:onafterStatus(From, Event, To)
|
|||||||
-- FSM state.
|
-- FSM state.
|
||||||
local fsmstate=self:GetState()
|
local fsmstate=self:GetState()
|
||||||
|
|
||||||
-- Check mission queue and assign one PLANNED mission.
|
|
||||||
self:CheckMissionQueue()
|
|
||||||
|
|
||||||
-- Status.
|
-- Status.
|
||||||
local text=string.format("Status %s: Legions=%d, Missions=%d", fsmstate, #self.legions, #self.missionqueue)
|
local text=string.format("Status %s: Legions=%d, Missions=%d", fsmstate, #self.legions, #self.missionqueue)
|
||||||
self:I(self.lid..text)
|
self:I(self.lid..text)
|
||||||
|
|
||||||
-- Legion info.
|
-- Check mission queue and assign one PLANNED mission.
|
||||||
|
self:CheckMissionQueue()
|
||||||
|
|
||||||
|
---
|
||||||
|
-- LEGIONS
|
||||||
|
---
|
||||||
|
|
||||||
if #self.legions>0 then
|
if #self.legions>0 then
|
||||||
|
|
||||||
local text="Legions:"
|
local text="Legions:"
|
||||||
for _,_legion in pairs(self.legions) do
|
for _,_legion in pairs(self.legions) do
|
||||||
local legion=_legion --Ops.Legion#LEGION
|
local legion=_legion --Ops.Legion#LEGION
|
||||||
@ -272,8 +276,70 @@ function COMMANDER:onafterStatus(From, Event, To)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
self:I(self.lid..text)
|
self:I(self.lid..text)
|
||||||
|
|
||||||
|
|
||||||
|
local assets={}
|
||||||
|
|
||||||
|
local Ntotal=0
|
||||||
|
local Nspawned=0
|
||||||
|
local Nrequested=0
|
||||||
|
local Nreserved=0
|
||||||
|
local Nstock=0
|
||||||
|
|
||||||
|
local text="===========================================\n"
|
||||||
|
text=text.."Assets:"
|
||||||
|
for _,_legion in pairs(self.legions) do
|
||||||
|
local legion=_legion --Ops.Legion#LEGION
|
||||||
|
|
||||||
|
for _,_cohort in pairs(legion.cohorts) do
|
||||||
|
local cohort=_cohort --Ops.Cohort#COHORT
|
||||||
|
|
||||||
|
for _,_asset in pairs(cohort.assets) do
|
||||||
|
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||||
|
|
||||||
|
table.insert(assets, asset)
|
||||||
|
|
||||||
|
text=text..string.format("\n- %s [UID=%d] Legion=%s, Cohort=%s: Spawned=%s, Requested=%s [RID=%s], Reserved=%s",
|
||||||
|
asset.spawngroupname, asset.uid, legion.alias, cohort.name, tostring(asset.spawned), tostring(asset.requested), tostring(asset.rid), tostring(asset.isReserved))
|
||||||
|
|
||||||
|
if asset.spawned then
|
||||||
|
Nspawned=Nspawned+1
|
||||||
|
end
|
||||||
|
|
||||||
|
if asset.requested then
|
||||||
|
Nrequested=Nrequested+1
|
||||||
|
end
|
||||||
|
|
||||||
|
if asset.isReserved then
|
||||||
|
Nreserved=Nreserved+1
|
||||||
|
end
|
||||||
|
|
||||||
|
if not (asset.spawned or asset.requested or asset.isReserved) then
|
||||||
|
Nstock=Nstock+1
|
||||||
|
end
|
||||||
|
|
||||||
|
Ntotal=Ntotal+1
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
text=text.."\n-------------------------------------------"
|
||||||
|
text=text..string.format("\nNstock = %d", Nstock)
|
||||||
|
text=text..string.format("\nNreserved = %d", Nreserved)
|
||||||
|
text=text..string.format("\nNrequested = %d", Nrequested)
|
||||||
|
text=text..string.format("\nNspawned = %d", Nspawned)
|
||||||
|
text=text..string.format("\nNtotal = %d (=%d)", Ntotal, Nstock+Nspawned+Nrequested+Nreserved)
|
||||||
|
text=text.."\n==========================================="
|
||||||
|
self:I(self.lid..text)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- MISSIONS
|
||||||
|
---
|
||||||
|
|
||||||
-- Mission queue.
|
-- Mission queue.
|
||||||
if #self.missionqueue>0 then
|
if #self.missionqueue>0 then
|
||||||
|
|
||||||
@ -314,6 +380,9 @@ function COMMANDER:onafterMissionAssign(From, Event, To, Legion, Mission)
|
|||||||
-- Add mission to legion.
|
-- Add mission to legion.
|
||||||
Legion:AddMission(Mission)
|
Legion:AddMission(Mission)
|
||||||
|
|
||||||
|
-- Directly request the mission as the assets have already been selected.
|
||||||
|
Legion:MissionRequest(Mission)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- On after "MissionCancel" event.
|
--- On after "MissionCancel" event.
|
||||||
@ -362,25 +431,127 @@ end
|
|||||||
function COMMANDER:CheckMissionQueue()
|
function COMMANDER:CheckMissionQueue()
|
||||||
|
|
||||||
-- TODO: Sort mission queue. wrt what? Threat level?
|
-- TODO: Sort mission queue. wrt what? Threat level?
|
||||||
|
-- Currently, we sort wrt to priority. So that should reflect the threat level of the mission target.
|
||||||
|
|
||||||
|
-- Number of missions.
|
||||||
|
local Nmissions=#self.missionqueue
|
||||||
|
|
||||||
|
-- Treat special cases.
|
||||||
|
if Nmissions==0 then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Sort results table wrt prio and start time.
|
||||||
|
local function _sort(a, b)
|
||||||
|
local taskA=a --Ops.Auftrag#AUFTRAG
|
||||||
|
local taskB=b --Ops.Auftrag#AUFTRAG
|
||||||
|
return (taskA.prio<taskB.prio) or (taskA.prio==taskB.prio and taskA.Tstart<taskB.Tstart)
|
||||||
|
end
|
||||||
|
table.sort(self.missionqueue, _sort)
|
||||||
|
|
||||||
|
-- Get the lowest importance value (lower means more important).
|
||||||
|
-- If a mission with importance 1 exists, mission with importance 2 will not be assigned. Missions with no importance (nil) can still be selected.
|
||||||
|
local vip=math.huge
|
||||||
|
for _,_mission in pairs(self.missionqueue) do
|
||||||
|
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||||
|
if mission.importance and mission.importance<vip then
|
||||||
|
vip=mission.importance
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Loop over missions in queue.
|
||||||
for _,_mission in pairs(self.missionqueue) do
|
for _,_mission in pairs(self.missionqueue) do
|
||||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||||
|
|
||||||
-- We look for PLANNED missions.
|
-- We look for PLANNED missions.
|
||||||
if mission:IsPlanned() then
|
if mission:IsPlanned() and mission:IsReadyToGo() and (mission.importance==nil or mission.importance<=vip) then
|
||||||
|
|
||||||
---
|
---
|
||||||
-- PLANNNED Mission
|
-- PLANNNED Mission
|
||||||
---
|
---
|
||||||
|
|
||||||
|
---
|
||||||
|
-- 1. Select best assets from legions
|
||||||
|
---
|
||||||
|
|
||||||
-- Get legions for mission.
|
-- Get legions for mission.
|
||||||
local legions=self:GetLegionsForMission(mission)
|
local legions=self:GetLegionsForMission(mission)
|
||||||
|
|
||||||
|
-- Get ALL assets from pre-selected legions.
|
||||||
|
local assets=self:GetAssets(InStock, legions, MissionTypes, Attributes)
|
||||||
|
|
||||||
|
-- Now we select the best assets from all legions.
|
||||||
|
legions={}
|
||||||
|
if #assets>=mission.nassets then
|
||||||
|
|
||||||
|
for _,_asset in pairs(assets) do
|
||||||
|
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||||
|
asset.payload=asset.legion:FetchPayloadFromStock(asset.unittype, mission.type, mission.payloads)
|
||||||
|
asset.score=asset.legion:CalculateAssetMissionScore(asset, mission, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Sort assets wrt to their mission score. Higher is better.
|
||||||
|
local function optimize(assetA, assetB)
|
||||||
|
return (assetA.score>assetB.score)
|
||||||
|
end
|
||||||
|
table.sort(assets, optimize)
|
||||||
|
|
||||||
|
-- Remove distance parameter.
|
||||||
|
local text=string.format("Optimized assets for %s mission:", mission.type)
|
||||||
|
for i,Asset in pairs(assets) do
|
||||||
|
local asset=Asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||||
|
|
||||||
|
-- Score text.
|
||||||
|
text=text..string.format("\n%s %s: score=%d", asset.squadname, asset.spawngroupname, asset.score)
|
||||||
|
|
||||||
|
-- Nillify score.
|
||||||
|
asset.score=nil
|
||||||
|
|
||||||
|
-- Add assets to mission.
|
||||||
|
if i<=mission.nassets then
|
||||||
|
|
||||||
|
-- Add asset to mission.
|
||||||
|
mission:AddAsset(Asset)
|
||||||
|
|
||||||
|
-- Put into table.
|
||||||
|
legions[asset.legion.alias]=asset.legion
|
||||||
|
|
||||||
|
-- Number of assets requested from this legion.
|
||||||
|
-- TODO: Check if this is really necessary as we do not go through the selection process.
|
||||||
|
mission.Nassets=mission.Nassets or {}
|
||||||
|
if mission.Nassets[asset.legion.alias] then
|
||||||
|
mission.Nassets[asset.legion.alias]=mission.Nassets[asset.legion.alias]+1
|
||||||
|
else
|
||||||
|
mission.Nassets[asset.legion.alias]=1
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Return payload of asset (if any).
|
||||||
|
if asset.payload then
|
||||||
|
asset.legion:ReturnPayloadFromAsset(asset)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:T2(self.lid..text)
|
||||||
|
|
||||||
|
else
|
||||||
|
self:T2(self.lid..string.format("Not enough assets available for mission"))
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Assign Mission to Legions
|
||||||
|
---
|
||||||
|
|
||||||
if legions then
|
if legions then
|
||||||
|
|
||||||
for _,_legion in pairs(legions) do
|
for _,_legion in pairs(legions) do
|
||||||
local legion=_legion --Ops.Legion#LEGION
|
local legion=_legion --Ops.Legion#LEGION
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
|
self:I(self.lid..string.format("Assigning mission %s [%s] to legion %s", mission:GetName(), mission:GetType(), legion.alias))
|
||||||
|
|
||||||
-- Add mission to legion.
|
-- Add mission to legion.
|
||||||
self:MissionAssign(legion, mission)
|
self:MissionAssign(legion, mission)
|
||||||
|
|
||||||
@ -424,7 +595,7 @@ function COMMANDER:GetLegionsForMission(Mission)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Has it assets that can?
|
-- Has it assets that can?
|
||||||
if Nassets>0 then
|
if Nassets>0 and false then
|
||||||
|
|
||||||
-- Get coordinate of the target.
|
-- Get coordinate of the target.
|
||||||
local coord=Mission:GetTargetCoordinate()
|
local coord=Mission:GetTargetCoordinate()
|
||||||
@ -447,61 +618,14 @@ function COMMANDER:GetLegionsForMission(Mission)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Add legion if it can provide at least 1 asset.
|
||||||
|
if Nassets>0 then
|
||||||
|
table.insert(legions, legion)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Can anyone?
|
return legions
|
||||||
if #legions>0 then
|
|
||||||
|
|
||||||
--- Something like:
|
|
||||||
-- * Closest legion that can should be first prio.
|
|
||||||
-- * However, there should be a certain "quantization". if wing is 50 or 60 NM way should not really matter. In that case, the legion with more resources should get the job.
|
|
||||||
local function score(a)
|
|
||||||
local d=math.round(a.dist/10)
|
|
||||||
end
|
|
||||||
|
|
||||||
env.info(self.lid.."FF #legions="..#legions)
|
|
||||||
|
|
||||||
-- Sort table wrt distance and number of assets.
|
|
||||||
-- Distances within 10 NM are equal and the legion with more assets is preferred.
|
|
||||||
local function sortdist(a,b)
|
|
||||||
local ad=a.dist
|
|
||||||
local bd=b.dist
|
|
||||||
return ad<bd or (ad==bd and a.nassets>b.nassets)
|
|
||||||
end
|
|
||||||
table.sort(legions, sortdist)
|
|
||||||
|
|
||||||
|
|
||||||
-- Loops over all legions and stop if enough assets are summed up.
|
|
||||||
local selection={} ; local N=0
|
|
||||||
for _,leg in ipairs(legions) do
|
|
||||||
local legion=leg.airwing --Ops.Legion#LEGION
|
|
||||||
|
|
||||||
Mission.Nassets=Mission.Nassets or {}
|
|
||||||
Mission.Nassets[legion.alias]=leg.nassets
|
|
||||||
|
|
||||||
table.insert(selection, legion)
|
|
||||||
|
|
||||||
N=N+leg.nassets
|
|
||||||
|
|
||||||
if N>=Mission.nassets then
|
|
||||||
self:I(self.lid..string.format("Found enough assets!"))
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if N>=Mission.nassets then
|
|
||||||
self:I(self.lid..string.format("Found %d legions that can do mission %s (%s) requiring %d assets", #selection, Mission:GetName(), Mission:GetType(), Mission.nassets))
|
|
||||||
return selection
|
|
||||||
else
|
|
||||||
self:T(self.lid..string.format("Not enough LEGIONs found that could do the job :/ Number of assets avail %d < %d required for the mission", N, Mission.nassets))
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
self:T(self.lid..string.format("No LEGION found that could do the job :/"))
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Count assets of all assigned legions.
|
--- Count assets of all assigned legions.
|
||||||
@ -521,6 +645,42 @@ function COMMANDER:CountAssets(InStock, MissionTypes, Attributes)
|
|||||||
return N
|
return N
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Count assets of all assigned legions.
|
||||||
|
-- @param #COMMANDER self
|
||||||
|
-- @param #boolean InStock If true, only assets that are in the warehouse stock/inventory are counted.
|
||||||
|
-- @param #table Legions (Optional) Table of legions. Default is all legions.
|
||||||
|
-- @param #table MissionTypes (Optional) Count only assest that can perform certain mission type(s). Default is all types.
|
||||||
|
-- @param #table Attributes (Optional) Count only assest that have a certain attribute(s), e.g. `WAREHOUSE.Attribute.AIR_BOMBER`.
|
||||||
|
-- @return #number Amount of asset groups.
|
||||||
|
function COMMANDER:GetAssets(InStock, Legions, MissionTypes, Attributes)
|
||||||
|
|
||||||
|
-- Selected assets.
|
||||||
|
local assets={}
|
||||||
|
|
||||||
|
for _,_legion in pairs(Legions or self.legions) do
|
||||||
|
local legion=_legion --Ops.Legion#LEGION
|
||||||
|
|
||||||
|
--TODO Check if legion is running and maybe if runway is operational if air assets are requested.
|
||||||
|
|
||||||
|
for _,_cohort in pairs(legion.cohorts) do
|
||||||
|
local cohort=_cohort --Ops.Cohort#COHORT
|
||||||
|
|
||||||
|
for _,_asset in pairs(cohort.assets) do
|
||||||
|
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||||
|
|
||||||
|
-- TODO: Check if repaired.
|
||||||
|
-- TODO: currently we take only unspawned assets.
|
||||||
|
if not (asset.spawned or asset.isReserved or asset.requested) then
|
||||||
|
table.insert(assets, asset)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return assets
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -118,6 +118,12 @@ function LEGION:New(WarehouseName, LegionName)
|
|||||||
-- @param #LEGION self
|
-- @param #LEGION self
|
||||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||||
|
|
||||||
|
--- Triggers the FSM event "MissionCancel" after a delay.
|
||||||
|
-- @function [parent=#LEGION] __MissionCancel
|
||||||
|
-- @param #LEGION self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||||
|
|
||||||
--- On after "MissionCancel" event.
|
--- On after "MissionCancel" event.
|
||||||
-- @function [parent=#LEGION] OnAfterMissionCancel
|
-- @function [parent=#LEGION] OnAfterMissionCancel
|
||||||
-- @param #LEGION self
|
-- @param #LEGION self
|
||||||
@ -446,12 +452,14 @@ function LEGION:_GetNextTransport()
|
|||||||
local function getAssets(n)
|
local function getAssets(n)
|
||||||
local assets={}
|
local assets={}
|
||||||
|
|
||||||
-- Loop over assets.
|
-- Loop over cohorts.
|
||||||
for _,_cohort in pairs(self.cohorts) do
|
for _,_cohort in pairs(self.cohorts) do
|
||||||
local cohort=_cohort --Ops.Cohort#COHORT
|
local cohort=_cohort --Ops.Cohort#COHORT
|
||||||
|
|
||||||
|
-- Check if chort can do a transport.
|
||||||
if cohort:CheckMissionCapability({AUFTRAG.Type.OPSTRANSPORT}, cohort.missiontypes) then
|
if cohort:CheckMissionCapability({AUFTRAG.Type.OPSTRANSPORT}, cohort.missiontypes) then
|
||||||
|
|
||||||
|
-- Loop over cohort assets.
|
||||||
for _,_asset in pairs(cohort.assets) do
|
for _,_asset in pairs(cohort.assets) do
|
||||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||||
|
|
||||||
@ -534,6 +542,23 @@ function LEGION:CalculateAssetMissionScore(asset, Mission, includePayload)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Get coordinate of the target.
|
||||||
|
local coord=Mission:GetTargetCoordinate()
|
||||||
|
local dist=0
|
||||||
|
if coord then
|
||||||
|
|
||||||
|
-- Distance from legion to target.
|
||||||
|
local distance=UTILS.MetersToNM(coord:Get2DDistance(self:GetCoordinate()))
|
||||||
|
|
||||||
|
-- Round: 55 NM ==> 5.5 ==> 6, 63 NM ==> 6.3 ==> 6
|
||||||
|
dist=UTILS.Round(distance/10, 0)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Reduce score for legions that are futher away.
|
||||||
|
score=score-dist
|
||||||
|
|
||||||
|
|
||||||
-- TODO: This could be vastly improved. Need to gather ideas during testing.
|
-- TODO: This could be vastly improved. Need to gather ideas during testing.
|
||||||
-- Calculate ETA? Assets on orbit missions should arrive faster even if they are further away.
|
-- Calculate ETA? Assets on orbit missions should arrive faster even if they are further away.
|
||||||
-- Max speed of assets.
|
-- Max speed of assets.
|
||||||
@ -669,6 +694,7 @@ function LEGION:onafterMissionRequest(From, Event, To, Mission)
|
|||||||
|
|
||||||
-- Set asset to requested! Important so that new requests do not use this asset!
|
-- Set asset to requested! Important so that new requests do not use this asset!
|
||||||
asset.requested=true
|
asset.requested=true
|
||||||
|
asset.isReserved=false
|
||||||
|
|
||||||
if Mission.missionTask then
|
if Mission.missionTask then
|
||||||
asset.missionTask=Mission.missionTask
|
asset.missionTask=Mission.missionTask
|
||||||
@ -728,6 +754,7 @@ function LEGION:onafterTransportRequest(From, Event, To, OpsTransport)
|
|||||||
-- The queueid has been increased in the onafterAddRequest function. So we can simply use it here.
|
-- The queueid has been increased in the onafterAddRequest function. So we can simply use it here.
|
||||||
OpsTransport.requestID=OpsTransport.requestID or {}
|
OpsTransport.requestID=OpsTransport.requestID or {}
|
||||||
OpsTransport.requestID[self.alias]=self.queueid
|
OpsTransport.requestID[self.alias]=self.queueid
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -1174,7 +1201,6 @@ function LEGION:_CreateFlightGroup(asset)
|
|||||||
|
|
||||||
opsgroup=FLIGHTGROUP:New(asset.spawngroupname)
|
opsgroup=FLIGHTGROUP:New(asset.spawngroupname)
|
||||||
|
|
||||||
|
|
||||||
elseif self:IsBrigade() then
|
elseif self:IsBrigade() then
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -1183,8 +1209,6 @@ function LEGION:_CreateFlightGroup(asset)
|
|||||||
|
|
||||||
opsgroup=ARMYGROUP:New(asset.spawngroupname)
|
opsgroup=ARMYGROUP:New(asset.spawngroupname)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
else
|
else
|
||||||
self:E(self.lid.."ERROR: not airwing or brigade!")
|
self:E(self.lid.."ERROR: not airwing or brigade!")
|
||||||
end
|
end
|
||||||
@ -1198,6 +1222,8 @@ function LEGION:_CreateFlightGroup(asset)
|
|||||||
-- Set home base.
|
-- Set home base.
|
||||||
opsgroup.homebase=self.airbase
|
opsgroup.homebase=self.airbase
|
||||||
|
|
||||||
|
-- Set home zone.
|
||||||
|
opsgroup.homezone=self.spawnzone
|
||||||
|
|
||||||
-- Set weapon data.
|
-- Set weapon data.
|
||||||
if opsgroup.cohort.weaponData then
|
if opsgroup.cohort.weaponData then
|
||||||
@ -1594,10 +1620,11 @@ function LEGION:CanMission(Mission)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Loop over cohorts and recruit assets.
|
||||||
for cohortname,_cohort in pairs(cohorts) do
|
for cohortname,_cohort in pairs(cohorts) do
|
||||||
local cohort=_cohort --Ops.Cohort#COHORT
|
local cohort=_cohort --Ops.Cohort#COHORT
|
||||||
|
|
||||||
-- Check if this squadron can.
|
-- Check if this cohort can.
|
||||||
local can=cohort:CanMission(Mission)
|
local can=cohort:CanMission(Mission)
|
||||||
|
|
||||||
if can then
|
if can then
|
||||||
@ -1774,6 +1801,26 @@ function LEGION:GetMissionFromRequest(Request)
|
|||||||
return self:GetMissionFromRequestID(Request.uid)
|
return self:GetMissionFromRequestID(Request.uid)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Fetch a payload from the airwing resources for a given unit and mission type.
|
||||||
|
-- The payload with the highest priority is preferred.
|
||||||
|
-- @param #LEGION self
|
||||||
|
-- @param #string UnitType The type of the unit.
|
||||||
|
-- @param #string MissionType The mission type.
|
||||||
|
-- @param #table Payloads Specific payloads only to be considered.
|
||||||
|
-- @return Ops.Airwing#AIRWING.Payload Payload table or *nil*.
|
||||||
|
function LEGION:FetchPayloadFromStock(UnitType, MissionType, Payloads)
|
||||||
|
-- Polymorphic. Will return something when called by airwing.
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return payload from asset back to stock.
|
||||||
|
-- @param #LEGION self
|
||||||
|
-- @param Functional.Warehouse#WAREHOUSE.Assetitem asset The squadron asset.
|
||||||
|
function LEGION:ReturnPayloadFromAsset(asset)
|
||||||
|
-- Polymorphic.
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@ -52,6 +52,8 @@
|
|||||||
-- @field #number Ndelivered Total number of cargo groups delivered.
|
-- @field #number Ndelivered Total number of cargo groups delivered.
|
||||||
-- @field #table pathsTransport Transport paths of `#OPSGROUP.Path`.
|
-- @field #table pathsTransport Transport paths of `#OPSGROUP.Path`.
|
||||||
-- @field #table pathsPickup Pickup paths of `#OPSGROUP.Path`.
|
-- @field #table pathsPickup Pickup paths of `#OPSGROUP.Path`.
|
||||||
|
-- @field Ops.Auftrag#AUFTRAG mission The mission attached to this transport.
|
||||||
|
-- @field #table assets Warehouse assets assigned for this transport.
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- *Victory is the beautiful, bright-colored flower. Transport is the stem without which it could never have blossomed.* -- Winston Churchill
|
--- *Victory is the beautiful, bright-colored flower. Transport is the stem without which it could never have blossomed.* -- Winston Churchill
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user