- Improved transport assignments
This commit is contained in:
Frank
2021-09-25 20:18:16 +02:00
parent 972fa9f674
commit 994689f05a
7 changed files with 466 additions and 342 deletions
+14 -16
View File
@@ -91,7 +91,13 @@
-- @field Core.Set#SET_GROUP transportGroupSet Groups to be transported. -- @field Core.Set#SET_GROUP transportGroupSet Groups to be transported.
-- @field Core.Point#COORDINATE transportPickup Coordinate where to pickup the cargo. -- @field Core.Point#COORDINATE transportPickup Coordinate where to pickup the cargo.
-- @field Core.Point#COORDINATE transportDropoff Coordinate where to drop off the cargo. -- @field Core.Point#COORDINATE transportDropoff Coordinate where to drop off the cargo.
--
-- @field Ops.OpsTransport#OPSTRANSPORT opstransport OPS transport assignment. -- @field Ops.OpsTransport#OPSTRANSPORT opstransport OPS transport assignment.
-- @field #number NcarriersMin Min number of required carrier assets.
-- @field #number NcarriersMax Max number of required carrier assets.
-- @field Core.Zone#ZONE transportDeployZone Deploy zone of an OPSTRANSPORT.
-- @field Core.Zone#ZONE transportDisembarkZone Disembark zone of an OPSTRANSPORT.
-- @field #table transportLegions Legions explicitly requested for providing carrier assets.
-- --
-- @field #number artyRadius Radius in meters. -- @field #number artyRadius Radius in meters.
-- @field #number artyShots Number of shots fired. -- @field #number artyShots Number of shots fired.
@@ -588,7 +594,7 @@ function AUFTRAG:New(Type)
self:SetPriority() self:SetPriority()
self:SetTime() self:SetTime()
self:SetRequiredAssets() self:SetRequiredAssets()
self:SetRequiredCarriers() --self:SetRequiredCarriers()
self.engageAsGroup=true self.engageAsGroup=true
self.dTevaluate=5 self.dTevaluate=5
@@ -2182,14 +2188,11 @@ end
-- @param #number NcarriersMin Number of carriers *at least* required. Default 1. -- @param #number NcarriersMin Number of carriers *at least* required. Default 1.
-- @param #number NcarriersMax Number of carriers *at most* used for transportation. Default is same as `NcarriersMin`. -- @param #number NcarriersMax Number of carriers *at most* used for transportation. Default is same as `NcarriersMin`.
-- @return #AUFTRAG self -- @return #AUFTRAG self
function AUFTRAG:SetTransportForAssets(DeployZone, DisembarkZone, NcarriersMin, NcarriersMax) function AUFTRAG:SetRequiredTransport(DeployZone, DisembarkZone, NcarriersMin, NcarriersMax)
-- OPS transport from pickup to deploy zone. -- OPS transport from pickup to deploy zone.
self.opstransport=OPSTRANSPORT:New(nil, nil, DeployZone) self.transportDeployZone=DeployZone
self.transportDisembarkZone=DisembarkZone
if DisembarkZone then
self.opstransport:SetDisembarkZone(DisembarkZone)
end
-- Set required carriers. -- Set required carriers.
self:SetRequiredCarriers(NcarriersMin, NcarriersMax) self:SetRequiredCarriers(NcarriersMin, NcarriersMax)
@@ -2226,18 +2229,13 @@ end
-- @return #AUFTRAG self -- @return #AUFTRAG self
function AUFTRAG:SetRequiredCarriers(NcarriersMin, NcarriersMax) function AUFTRAG:SetRequiredCarriers(NcarriersMin, NcarriersMax)
self.nCarriersMin=NcarriersMin or 1 self.NcarriersMin=NcarriersMin or 1
self.nCarriersMax=NcarriersMax or self.nCarriersMin self.NcarriersMax=NcarriersMax or self.NcarriersMin
-- Ensure that max is at least equal to min. -- Ensure that max is at least equal to min.
if self.nCarriersMax<self.nCarriersMin then if self.NcarriersMax<self.NcarriersMin then
self.nCarriersMax=self.nCarriersMin self.NcarriersMax=self.NcarriersMin
end
-- Pass this on to the ops transport.
if self.opstransport then
self.opstransport:SetRequiredCarriers(NcarriersMin, NcarriersMax)
end end
return self return self
+1 -1
View File
@@ -224,7 +224,7 @@ end
--- Add a patrol Point for CAP missions. --- Add a patrol Point for CAP missions.
-- @param #BRIGADE self -- @param #BRIGADE self
-- @param Core.Zone#ZONE Rearming zone. -- @param Core.Zone#ZONE Rearming zone.
-- @return #AIRWING self -- @return #BRIGADE self
function BRIGADE:AddRearmingZone(RearmingZone) function BRIGADE:AddRearmingZone(RearmingZone)
local rearmingzone={} --#BRIGADE.RearmingZone local rearmingzone={} --#BRIGADE.RearmingZone
+9 -58
View File
@@ -989,7 +989,7 @@ end
-- @param #string Event Event. -- @param #string Event Event.
-- @param #string To To state. -- @param #string To To state.
-- @param #string Strategy -- @param #string Strategy
function CHIEF:onafterDefconChange(From, Event, To, Strategy) function CHIEF:onafterStrategyChange(From, Event, To, Strategy)
self:I(self.lid..string.format("Changing Strategy from %s --> %s", self.strategy, Strategy)) self:I(self.lid..string.format("Changing Strategy from %s --> %s", self.strategy, Strategy))
end end
@@ -1563,80 +1563,31 @@ function CHIEF:RecruitAssetsForZone(OpsZone, MissionType, NassetsMin, NassetsMax
if recruitedInf then if recruitedInf then
env.info(string.format("Recruited %d assets from for PATROL mission", #assetsInf)) env.info(string.format("Recruited %d assets from for PATROL mission", #assetsInf))
-- Get max weight.
local weightMax=nil
for _,_asset in pairs(assetsInf) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
if weightMax==nil or weightMax<=asset.weight then
weightMax=asset.weight
end
end
-- Recruite carrier assets. This need to be ground or helicopters to deploy at a zone.
local recruitedTrans, assetsTrans, legionsTrans=
LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.OPSTRANSPORT, nil, 1, 1, TargetVec2, nil, nil, nil, weightMax, {Group.Category.HELICOPTER, Group.Category.GROUND})
local transport=nil --Ops.OpsTransport#OPSTRANSPORT
if recruitedTrans then
env.info(string.format("Recruited %d assets for OPSTRANSPORT mission", #assetsTrans))
-- Create an OPSTRANSPORT assignment.
transport=OPSTRANSPORT:New(nil, nil, OpsZone.zone)
-- Add cargo assets to transport.
for _,_legion in pairs(legionsInf) do
local legion=_legion --Ops.Legion#LEGION
-- Pickup at spawnzone or at airbase if the legion warehouse has one. -- Recruit transport assets for infantry.
local pickupzone=legion.spawnzone local recruitedTrans, transport=LEGION.AssignAssetsForTransport(self.commander, self.commander.legions, assetsInf, 1, 1, OpsZone.zone, nil, {Group.Category.HELICOPTER, Group.Category.GROUND})
if legion.airbase and legion:IsRunwayOperational() then
pickupzone=ZONE_AIRBASE:New(legion.airbasename, 4000)
end
local tpz=transport:AddTransportZoneCombo(pickupzone, OpsZone.zone)
for _,_asset in pairs(assetsInf) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
if asset.legion.alias==legion.alias then
transport:AddAssetCargo(asset, tpz)
end
end
end
-- Add carrier assets.
for _,_asset in pairs(assetsTrans) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
transport:AddAsset(asset)
end
-- Assign TRANSPORT to legions. This also sends the request for the assets.
for _,_legion in pairs(legionsTrans) do
local legion=_legion --Ops.Legion#LEGION
self.commander:TransportAssign(legion, transport)
end
else
-- Uncrecruite
LEGION.UnRecruitAssets(assetsTrans)
end
-- Create Patrol zone mission. -- Create Patrol zone mission.
local mission=AUFTRAG:NewPATROLZONE(OpsZone.zone) local mission=AUFTRAG:NewPATROLZONE(OpsZone.zone)
mission:SetEngageDetected() mission:SetEngageDetected()
-- Add assets to mission.
for _,asset in pairs(assetsInf) do for _,asset in pairs(assetsInf) do
mission:AddAsset(asset) mission:AddAsset(asset)
end end
-- Attach OPS transport to mission.
mission.opstransport=transport mission.opstransport=transport
-- Assign mission to legions.
for _,_legion in pairs(legionsInf) do for _,_legion in pairs(legionsInf) do
local legion=_legion --Ops.Legion#LEGION local legion=_legion --Ops.Legion#LEGION
self.commander:MissionAssign(legion, mission) self.commander:MissionAssign(legion, mission)
end end
-- Attach mission to ops zone.
-- TODO: Need a better way!
OpsZone.missionPatrol=mission OpsZone.missionPatrol=mission
return true return true
+53 -151
View File
@@ -645,9 +645,6 @@ end
-- @param #COMMANDER self -- @param #COMMANDER self
function COMMANDER:CheckMissionQueue() function COMMANDER:CheckMissionQueue()
-- 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. -- Number of missions.
local Nmissions=#self.missionqueue local Nmissions=#self.missionqueue
@@ -708,69 +705,18 @@ function COMMANDER:CheckMissionQueue()
-- Escort requested and available. -- Escort requested and available.
if EscortAvail then if EscortAvail then
-- Check if mission assets need a transport. -- Check if mission assets need a transport.
if mission.opstransport then if mission.NcarriersMin then
-- Weight of the heaviest cargo group. Necessary condition that this fits into on carrier unit! -- Recruit carrier assets for transport.
local weightGroup=0 local Transport=nil
local Legions=mission.transportLegions or self.legions
-- Calculate the max weight of the cargo assets.
for _,_asset in pairs(assets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
local weight=asset.weight
if weight>weightGroup then
weightGroup=weight
end
end
env.info(string.format("FF mission requires transport for cargo weight %d", weightGroup)) TransportAvail, Transport=LEGION.AssignAssetsForTransport(self, Legions, assets, mission.NcarriersMin, mission.NcarriersMax, mission.transportDeployZone, mission.transportDisembarkZone)
-- Recruit transport assets. -- Add opstransport to mission.
local TransportAvail, assetsTrans, legionsTrans=self:RecruitAssetsForTransport(mission.opstransport, weightGroup) if TransportAvail and Transport then
mission.opstransport=Transport
if TransportAvail then
env.info(string.format("FF Transport available with %d carrier assets", #assetsTrans))
-- Add cargo assets to transport.
for _,_legion in pairs(legions) do
local legion=_legion --Ops.Legion#LEGION
-- Set pickup zone to spawn zone or airbase if the legion has one that is operational.
local pickupzone=legion.spawnzone
if legion.airbase and legion:IsRunwayOperational() then
pickupzone=ZONE_AIRBASE:New(legion.airbasename, 4000)
end
-- Add TZC from legion spawn zone to deploy zone.
local tpz=mission.opstransport:AddTransportZoneCombo(pickupzone, mission.opstransport:GetDeployZone())
mission.opstransport:SetEmbarkZone(legion.spawnzone, tpz)
-- Add cargo assets to transport.
for _,_asset in pairs(assets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
if asset.legion.alias==legion.alias then
mission.opstransport:AddAssetCargo(asset, tpz)
end
end
end
-- Add carrier assets.
for _,_asset in pairs(assetsTrans) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
mission.opstransport:AddAsset(asset)
end
-- Assign TRANSPORT to legions. This also sends the request for the assets.
for _,_legion in pairs(legionsTrans) do
local legion=_legion --Ops.Legion#LEGION
self:TransportAssign(legion, mission.opstransport)
end
else
-- Uncrecruit transport assets.
LEGION.UnRecruitAssets(assetsTrans)
end end
end end
@@ -856,102 +802,34 @@ end
--- Recruit assets performing an escort mission for a given asset. --- Recruit assets performing an escort mission for a given asset.
-- @param #COMMANDER self -- @param #COMMANDER self
-- @param Ops.Auftrag#AUFTRAG Mission The mission. -- @param Ops.Auftrag#AUFTRAG Mission The mission.
-- @param #table Assets Table of assets. -- @param #table Assets Table of assets to be escorted.
-- @return #boolean If `true`, enough assets could be recruited or no escort was required in the first place. -- @return #boolean If `true`, enough assets could be recruited or no escort was required in the first place.
function COMMANDER:RecruitAssetsForEscort(Mission, Assets) function COMMANDER:RecruitAssetsForEscort(Mission, Assets)
-- Cohorts.
local Cohorts=Mission.squadrons
if not Cohorts then
Cohorts={}
for _,_legion in pairs(Mission.specialLegions or self.legions) do
local legion=_legion --Ops.Legion#LEGION
-- Loops over cohorts.
for _,_cohort in pairs(legion.cohorts) do
local cohort=_cohort --Ops.Cohort#COHORT
table.insert(Cohorts, cohort)
end
end
end
-- Is an escort requested in the first place? -- Is an escort requested in the first place?
if Mission.NescortMin and Mission.NescortMax and (Mission.NescortMin>0 or Mission.NescortMax>0) then if Mission.NescortMin and Mission.NescortMax and (Mission.NescortMin>0 or Mission.NescortMax>0) then
-- Debug info. -- Cohorts.
self:I(self.lid..string.format("Reqested escort for mission %s [%s]. Required assets=%d-%d", Mission:GetName(), Mission:GetType(), Mission.NescortMin,Mission.NescortMax)) local Cohorts=Mission.squadrons
if not Cohorts then
-- Escorts for each asset. Cohorts={}
local Escorts={} for _,_legion in pairs(Mission.specialLegions or self.legions) do
local legion=_legion --Ops.Legion#LEGION
local EscortAvail=true -- Loops over cohorts.
for _,_asset in pairs(Assets) do for _,_cohort in pairs(legion.cohorts) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem local cohort=_cohort --Ops.Cohort#COHORT
table.insert(Cohorts, cohort)
-- Recruit escort asset for the mission asset.
local Erecruited, eassets, elegions=LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.ESCORT, nil, Mission.NescortMin, Mission.NescortMax)
if Erecruited then
Escorts[asset.spawngroupname]={EscortLegions=elegions, EscortAssets=eassets}
else
-- Could not find escort for this asset ==> Escort not possible ==> Break the loop.
EscortAvail=false
break
end
end
-- ALL escorts could be recruited.
if EscortAvail then
local N=0
for groupname,value in pairs(Escorts) do
local Elegions=value.EscortLegions
local Eassets=value.EscortAssets
for _,_legion in pairs(Elegions) do
local legion=_legion --Ops.Legion#LEGION
-- Create and ESCORT mission for this asset.
local escort=AUFTRAG:NewESCORT(groupname)
-- Reserve assts and add to mission.
for _,_asset in pairs(Eassets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
asset.isReserved=true
escort:AddAsset(asset)
N=N+1
end
-- Assign mission to legion.
self:MissionAssign(legion, escort)
end end
end end
-- Debug info.
self:I(self.lid..string.format("Recruited %d escort assets for mission %s [%s]", N, Mission:GetName(), Mission:GetType()))
-- Yup!
return true
else
-- Debug info.
self:I(self.lid..string.format("Could not get at least one escort for mission %s [%s]! Unrecruit all recruited assets", Mission:GetName(), Mission:GetType()))
-- Could not get at least one escort. Unrecruit all recruited ones.
for groupname,value in pairs(Escorts) do
local Eassets=value.EscortAssets
LEGION.UnRecruitAssets(Eassets)
end
-- No,no!
return false
end end
else -- Call LEGION function but provide COMMANDER as self.
-- No escort required. local assigned=LEGION.AssignAssetsForEscort(self, Cohorts, Assets, Mission.NescortMin, Mission.NescortMin)
return true
end return assigned
end
return true
end end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -1072,7 +950,7 @@ end
-- @return #table Legions that have recruited assets. -- @return #table Legions that have recruited assets.
function COMMANDER:RecruitAssetsForTransport(Transport, CargoWeight) function COMMANDER:RecruitAssetsForTransport(Transport, CargoWeight)
if weightGroup==0 then if CargoWeight==0 then
-- No cargo groups! -- No cargo groups!
return false, {}, {} return false, {}, {}
end end
@@ -1221,6 +1099,30 @@ function COMMANDER:GetLegionsForMission(Mission)
return legions return legions
end end
--- Get assets on given mission or missions.
-- @param #COMMANDER self
-- @param #table MissionTypes Types on mission to be checked. Default all.
-- @return #table Assets on pending requests.
function COMMANDER:GetAssetsOnMission(MissionTypes)
local assets={}
for _,_mission in pairs(self.missionqueue) do
local mission=_mission --Ops.Auftrag#AUFTRAG
-- Check if this mission type is requested.
if AUFTRAG.CheckMissionType(mission.type, MissionTypes) then
for _,_asset in pairs(mission.assets or {}) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
table.insert(assets, asset)
end
end
end
return assets
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+336 -108
View File
@@ -83,9 +83,11 @@ function LEGION:New(WarehouseName, LegionName)
-- From State --> Event --> To State -- From State --> Event --> To State
self:AddTransition("*", "MissionRequest", "*") -- Add a (mission) request to the warehouse. self:AddTransition("*", "MissionRequest", "*") -- Add a (mission) request to the warehouse.
self:AddTransition("*", "MissionCancel", "*") -- Cancel mission. self:AddTransition("*", "MissionCancel", "*") -- Cancel mission.
self:AddTransition("*", "MissionAssign", "*") -- Recruit assets, add to queue and request immediately.
self:AddTransition("*", "TransportRequest", "*") -- Add a (mission) request to the warehouse. self:AddTransition("*", "TransportRequest", "*") -- Add a (mission) request to the warehouse.
self:AddTransition("*", "TransportCancel", "*") -- Cancel transport. self:AddTransition("*", "TransportCancel", "*") -- Cancel transport.
self:AddTransition("*", "TransportAssign", "*") -- Recruit assets, add to queue and request immediately.
self:AddTransition("*", "OpsOnMission", "*") -- An OPSGROUP was send on a Mission (AUFTRAG). self:AddTransition("*", "OpsOnMission", "*") -- An OPSGROUP was send on a Mission (AUFTRAG).
@@ -118,18 +120,27 @@ 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 --- Triggers the FSM event "MissionAssign".
-- @function [parent=#LEGION] MissionAssign
-- @param #LEGION self -- @param #LEGION self
-- @param #number delay Delay in seconds. -- @param Ops.Legion#LEGION Legion The legion from which the mission assets are requested.
-- @param Ops.Auftrag#AUFTRAG Mission The mission. -- @param Ops.Auftrag#AUFTRAG Mission The mission.
--- On after "MissionCancel" event. --- Triggers the FSM event "MissionAssign" after a delay.
-- @function [parent=#LEGION] OnAfterMissionCancel -- @function [parent=#LEGION] __MissionAssign
-- @param #LEGION self
-- @param #number delay Delay in seconds.
-- @param Ops.Legion#LEGION Legion The legion from which the mission assets are requested.
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
--- On after "MissionAssign" event.
-- @function [parent=#LEGION] OnAfterMissionAssign
-- @param #LEGION self -- @param #LEGION self
-- @param #string From From state. -- @param #string From From state.
-- @param #string Event Event. -- @param #string Event Event.
-- @param #string To To state. -- @param #string To To state.
-- @param Ops.Legion#LEGION Legion The legion from which the mission assets are requested.
-- @param Ops.Auftrag#AUFTRAG Mission The mission. -- @param Ops.Auftrag#AUFTRAG Mission The mission.
@@ -153,6 +164,44 @@ function LEGION:New(WarehouseName, LegionName)
-- @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.
-- @function [parent=#LEGION] OnAfterMissionCancel
-- @param #LEGION self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
--- Triggers the FSM event "TransportAssign".
-- @function [parent=#LEGION] TransportAssign
-- @param #LEGION self
-- @param Ops.Legion#LEGION Legion The legion from which the transport assets are requested.
-- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport.
--- Triggers the FSM event "TransportAssign" after a delay.
-- @function [parent=#LEGION] __TransportAssign
-- @param #LEGION self
-- @param #number delay Delay in seconds.
-- @param Ops.Legion#LEGION Legion The legion from which the transport assets are requested.
-- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport.
--- On after "TransportAssign" event.
-- @function [parent=#LEGION] OnAfterTransportAssign
-- @param #LEGION self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Ops.Legion#LEGION Legion The legion from which the transport assets are requested.
-- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport.
--- Triggers the FSM event "TransportRequest". --- Triggers the FSM event "TransportRequest".
-- @function [parent=#LEGION] TransportRequest -- @function [parent=#LEGION] TransportRequest
-- @param #LEGION self -- @param #LEGION self
@@ -274,30 +323,6 @@ function LEGION:AddMission(Mission)
if Mission.type==AUFTRAG.Type.ALERT5 then if Mission.type==AUFTRAG.Type.ALERT5 then
Mission:_TargetFromObject(self:GetCoordinate()) Mission:_TargetFromObject(self:GetCoordinate())
end end
-- Add ops transport to transport Legions.
if Mission.opstransport and false then
local PickupZone=self.spawnzone
local DeployZone=Mission.opstransport.tzcDefault.DeployZone
-- Add a new TZC: from pickup here to the deploy zone.
local tzc=Mission.opstransport:AddTransportZoneCombo(PickupZone, DeployZone)
--TODO: Depending on "from where to where" the assets need to transported, we need to set ZONE_AIRBASE etc.
--Mission.opstransport:SetPickupZone(self.spawnzone)
--Mission.opstransport:SetEmbarkZone(self.spawnzone)
-- Loop over all defined transport legions.
for _,_legion in pairs(Mission.transportLegions) do
local legion=_legion --Ops.Legion#LEGION
-- Add ops transport to legion.
legion:AddOpsTransport(Mission.opstransport)
end
end
-- Add mission to queue. -- Add mission to queue.
table.insert(self.missionqueue, Mission) table.insert(self.missionqueue, Mission)
@@ -481,20 +506,38 @@ function LEGION:_GetNextMission()
-- Reserve assets and add to mission. -- Reserve assets and add to mission.
for _,_asset in pairs(assets) do for _,_asset in pairs(assets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
asset.isReserved=true
mission:AddAsset(asset) mission:AddAsset(asset)
end end
-- Recruit asset for escorting recruited mission assets. -- Recruit asset for escorting recruited mission assets.
local EscortAvail=self:RecruitAssetsForEscort(mission, assets) local EscortAvail=self:RecruitAssetsForEscort(mission, assets)
-- Transport available (or not required).
local TransportAvail=true
-- Is escort required and available? -- Is escort required and available?
if EscortAvail then if EscortAvail then
-- Recruit carrier assets for transport.
local Transport=nil
if mission.NcarriersMin then
local Legions=mission.transportLegions or {self}
TransportAvail, Transport=self:AssignAssetsForTransport(Legions, assets, mission.NcarriersMin, mission.NcarriersMax, mission.transportDeployZone, mission.transportDisembarkZone)
end
-- Add opstransport to mission.
if TransportAvail and Transport then
mission.opstransport=Transport
end
end
if EscortAvail and TransportAvail then
-- Got a missin. -- Got a missin.
return mission return mission
else else
-- Recruited assets but no requested escort available. Unrecruit assets! -- Recruited assets but no requested escort available. Unrecruit assets!
LEGION.UnRecruitAssets(assets, mission) LEGION.UnRecruitAssets(assets, mission)
end end
end -- recruited mission assets end -- recruited mission assets
@@ -552,7 +595,6 @@ function LEGION:_GetNextTransport()
-- Add asset to transport. -- Add asset to transport.
for _,_asset in pairs(assets) do for _,_asset in pairs(assets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
asset.isReserved=true
transport:AddAsset(asset) transport:AddAsset(asset)
end end
@@ -572,6 +614,27 @@ end
-- FSM Events -- FSM Events
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- On after "MissionAssign" event. Mission is added to a LEGION mission queue and already requested. Needs assets to be added to the mission already.
-- @param #LEGION self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Ops.Legion#LEGION Legion The LEGION.
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
function LEGION:onafterMissionAssign(From, Event, To, Legion, Mission)
-- Debug info.
self:I(self.lid..string.format("Assigning mission %s (%s) to legion %s", Mission.name, Mission.type, Legion.alias))
-- Add mission to legion.
Legion:AddMission(Mission)
-- Directly request the mission as the assets have already been selected.
Legion:MissionRequest(Mission)
end
--- On after "MissionRequest" event. Performs a self request to the warehouse for the mission assets. Sets mission status to REQUESTED. --- On after "MissionRequest" event. Performs a self request to the warehouse for the mission assets. Sets mission status to REQUESTED.
-- @param #LEGION self -- @param #LEGION self
-- @param #string From From state. -- @param #string From From state.
@@ -683,7 +746,27 @@ function LEGION:onafterMissionRequest(From, Event, To, Mission)
end end
--- On after "MissionRequest" event. Performs a self request to the warehouse for the mission assets. Sets mission status to REQUESTED. --- On after "TransportAssign" event. Transport is added to a LEGION transport queue and assets are requested from the LEGION warehouse.
-- @param #LEGION self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Ops.Legion#LEGION Legion The LEGION.
-- @param Ops.OpsTransport#OPSTRANSPORT The transport.
function LEGION:onafterTransportAssign(From, Event, To, Legion, Transport)
-- Debug info.
self:I(self.lid..string.format("Assigning transport %d to legion %s", Transport.uid, Legion.alias))
-- Add mission to legion.
Legion:AddOpsTransport(Transport)
-- Directly request the mission as the assets have already been selected.
Legion:TransportRequest(Transport)
end
--- On after "TransportRequest" event. Performs a self request to the warehouse for the transport assets. Sets transport status to REQUESTED.
-- @param #LEGION self -- @param #LEGION self
-- @param #string From From state. -- @param #string From From state.
-- @param #string Event Event. -- @param #string Event Event.
@@ -987,6 +1070,7 @@ function LEGION:onafterAssetSpawned(From, Event, To, group, asset, request)
-- Check if we have a cohort or if this was some other request. -- Check if we have a cohort or if this was some other request.
if cohort then if cohort then
-- Debug info.
self:I(self.lid..string.format("Cohort asset spawned %s", asset.spawngroupname)) self:I(self.lid..string.format("Cohort asset spawned %s", asset.spawngroupname))
-- Create a flight group. -- Create a flight group.
@@ -1666,6 +1750,8 @@ end
-- @param #LEGION self -- @param #LEGION self
-- @param Ops.OpsTransport#OPSTRANSPORT Transport The OPS transport. -- @param Ops.OpsTransport#OPSTRANSPORT Transport The OPS transport.
-- @return #boolean If `true`, enough assets could be recruited. -- @return #boolean If `true`, enough assets could be recruited.
-- @return #table assets Recruited assets.
-- @return #table legions Legions of recruited assets.
function LEGION:RecruitAssetsForTransport(Transport) function LEGION:RecruitAssetsForTransport(Transport)
-- Get all undelivered cargo ops groups. -- Get all undelivered cargo ops groups.
@@ -1716,82 +1802,15 @@ function LEGION:RecruitAssetsForEscort(Mission, Assets)
-- Debug info. -- Debug info.
self:I(self.lid..string.format("Reqested escort for mission %s [%s]. Required assets=%d-%d", Mission:GetName(), Mission:GetType(), Mission.NescortMin,Mission.NescortMax)) self:I(self.lid..string.format("Reqested escort for mission %s [%s]. Required assets=%d-%d", Mission:GetName(), Mission:GetType(), Mission.NescortMin,Mission.NescortMax))
-- Escorts for each asset. --TODO: Maybe add escortCohorts as mission option?
local Escorts={}
local EscortAvail=true -- Call LEGION function but provide COMMANDER as self.
for _,_asset in pairs(Assets) do local assigned=LEGION.AssignAssetsForEscort(self, self.cohorts, Assets, Mission.NescortMin, Mission.NescortMin)
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
-- Recruit escort asset for the mission asset.
local Erecruited, eassets, elegions=LEGION.RecruitCohortAssets(self.cohorts, AUFTRAG.Type.ESCORT, nil, Mission.NescortMin, Mission.NescortMax)
if Erecruited then
Escorts[asset.spawngroupname]={EscortLegions=elegions, EscortAssets=eassets}
else
-- Could not find escort for this asset ==> Escort not possible ==> Break the loop.
EscortAvail=false
break
end
end
-- ALL escorts could be recruited. return assigned
if EscortAvail then end
local N=0
for groupname,value in pairs(Escorts) do
local Elegions=value.EscortLegions
local Eassets=value.EscortAssets
for _,_legion in pairs(Elegions) do
local legion=_legion --Ops.Legion#LEGION
-- Create and ESCORT mission for this asset.
local escort=AUFTRAG:NewESCORT(groupname)
-- Reserve assts and add to mission.
for _,_asset in pairs(Eassets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
asset.isReserved=true
escort:AddAsset(asset)
N=N+1
end
-- Add mission.
legion:AddMission(escort)
-- Request mission.
legion:MissionRequest(escort)
end
end
-- Debug info.
self:I(self.lid..string.format("Recruited %d escort assets for mission %s [%s]", N, Mission:GetName(), Mission:GetType()))
-- Yup!
return true
else
-- Debug info.
self:I(self.lid..string.format("Could not get at least one escort for mission %s [%s]! Unrecruit all recruited assets", Mission:GetName(), Mission:GetType()))
-- Could not get at least one escort. Unrecruit all recruited ones.
for groupname,value in pairs(Escorts) do
local Eassets=value.EscortAssets
LEGION.UnRecruitAssets(Eassets)
end
-- No,no!
return false
end
else
-- No escort required.
return true
end
return true
end end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -2001,6 +2020,215 @@ function LEGION.UnRecruitAssets(Assets, Mission)
end end
--- Recruit and assign assets performing an escort mission for a given asset list. Note that each asset gets an escort.
-- @param #LEGION self
-- @param #table Cohorts Cohorts for escorting assets.
-- @param #table Assets Table of assets to be escorted.
-- @param #number NescortMin Min number of escort groups required per escorted asset.
-- @param #number NescortMax Max number of escort groups required per escorted asset.
-- @return #boolean If `true`, enough assets could be recruited or no escort was required in the first place.
function LEGION:AssignAssetsForEscort(Cohorts, Assets, NescortMin, NescortMax)
-- Is an escort requested in the first place?
if NescortMin and NescortMax and (NescortMin>0 or NescortMax>0) then
-- Debug info.
self:I(self.lid..string.format("Reqested escort for %d assets from %d cohorts. Required escort assets=%d-%d", #Assets, #Cohorts, NescortMin, NescortMax))
-- Escorts for each asset.
local Escorts={}
local EscortAvail=true
for _,_asset in pairs(Assets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
-- Target vector is the legion of the asset.
local TargetVec2=asset.legion:GetVec2()
-- We want airplanes for airplanes and helos for everything else.
local Categories={Group.Category.HELICOPTER}
if asset.category==Group.Category.AIRPLANE then
Categories={Group.Category.AIRPLANE}
end
-- Recruit escort asset for the mission asset.
local Erecruited, eassets, elegions=LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.ESCORT, nil, NescortMin, NescortMax, TargetVec2, nil, nil, nil, nil, Categories)
if Erecruited then
Escorts[asset.spawngroupname]={EscortLegions=elegions, EscortAssets=eassets}
else
-- Could not find escort for this asset ==> Escort not possible ==> Break the loop.
EscortAvail=false
break
end
end
-- ALL escorts could be recruited.
if EscortAvail then
local N=0
for groupname,value in pairs(Escorts) do
local Elegions=value.EscortLegions
local Eassets=value.EscortAssets
for _,_legion in pairs(Elegions) do
local legion=_legion --Ops.Legion#LEGION
-- Create and ESCORT mission for this asset.
local escort=AUFTRAG:NewESCORT(groupname)
-- Reserve assts and add to mission.
for _,_asset in pairs(Eassets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
escort:AddAsset(asset)
N=N+1
end
-- Assign mission to legion.
self:MissionAssign(legion, escort)
end
end
-- Debug info.
self:I(self.lid..string.format("Recruited %d escort assets", N))
-- Yup!
return true
else
-- Debug info.
self:I(self.lid..string.format("Could not get at least one escort!"))
-- Could not get at least one escort. Unrecruit all recruited ones.
for groupname,value in pairs(Escorts) do
local Eassets=value.EscortAssets
LEGION.UnRecruitAssets(Eassets)
end
-- No,no!
return false
end
else
-- No escort required.
return true
end
end
--- Recruit and assign assets performing an OPSTRANSPORT for a given asset list.
-- @param #LEGION self
-- @param #table Legions Transport legions.
-- @param #table CargoAssets Weight of the heaviest cargo group to be transported.
-- @param #number NcarriersMin Min number of carrier assets.
-- @param #number NcarriersMax Max number of carrier assets.
-- @param Core.Zone#ZONE DeployZone Deploy zone.
-- @param Core.Zone#ZONE DisembarkZone (Optional) Disembark zone.
-- @return #boolean If `true`, enough assets could be recruited and an OPSTRANSPORT object was created.
-- @return Ops.OpsTransport#OPSTRANSPORT Transport The transport.
function LEGION:AssignAssetsForTransport(Legions, CargoAssets, NcarriersMin, NcarriersMax, DeployZone, DisembarkZone, Categories, Attributes)
-- Is an escort requested in the first place?
if NcarriersMin and NcarriersMax and (NcarriersMin>0 or NcarriersMax>0) then
-- Cohorts.
local Cohorts={}
for _,_legion in pairs(Legions) do
local legion=_legion --Ops.Legion#LEGION
-- Check that runway is operational.
local Runway=legion:IsAirwing() and legion:IsRunwayOperational() or true
if legion:IsRunning() and Runway then
-- Loops over cohorts.
for _,_cohort in pairs(legion.cohorts) do
local cohort=_cohort --Ops.Cohort#COHORT
table.insert(Cohorts, cohort)
end
end
end
-- Get all legions and heaviest cargo group weight
local CargoLegions={} ; local CargoWeight=nil
for _,_asset in pairs(CargoAssets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
CargoLegions[asset.legion.alias]=asset.legion
if CargoWeight==nil or asset.weight>CargoWeight then
CargoWeight=asset.weight
end
end
-- Target is the deploy zone.
local TargetVec2=DeployZone:GetVec2()
-- Recruit assets and legions.
local TransportAvail, CarrierAssets, CarrierLegions=
LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.OPSTRANSPORT, nil, NcarriersMin, NcarriersMax, TargetVec2, nil, nil, nil, CargoWeight, Categories, Attributes)
if TransportAvail then
-- Create and OPSTRANSPORT assignment.
local Transport=OPSTRANSPORT:New(nil, nil, DeployZone)
if DisembarkZone then
Transport:SetDisembarkZone(DisembarkZone)
end
-- Debug info.
env.info(string.format("FF Transport available with %d carrier assets", #CarrierAssets))
-- Add cargo assets to transport.
for _,_legion in pairs(CargoLegions) do
local legion=_legion --Ops.Legion#LEGION
-- Set pickup zone to spawn zone or airbase if the legion has one that is operational.
local pickupzone=legion.spawnzone
if legion.airbase and legion:IsRunwayOperational() then
pickupzone=ZONE_AIRBASE:New(legion.airbasename, 4000)
end
-- Add TZC from legion spawn zone to deploy zone.
local tpz=Transport:AddTransportZoneCombo(pickupzone, Transport:GetDeployZone())
Transport:SetEmbarkZone(legion.spawnzone, tpz)
-- Add cargo assets to transport.
for _,_asset in pairs(CargoAssets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
if asset.legion.alias==legion.alias then
Transport:AddAssetCargo(asset, tpz)
end
end
end
-- Add carrier assets.
for _,_asset in pairs(CarrierAssets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
Transport:AddAsset(asset)
end
-- Assign TRANSPORT to legions. This also sends the request for the assets.
for _,_legion in pairs(CarrierLegions) do
local legion=_legion --Ops.Legion#LEGION
self:TransportAssign(legion, Transport)
end
-- Got transport.
return true, Transport
else
-- Uncrecruit transport assets.
LEGION.UnRecruitAssets(CarrierAssets)
return false, nil
end
return nil, nil
end
-- No transport requested in the first place.
return true, nil
end
--- Calculate the mission score of an asset. --- Calculate the mission score of an asset.
-- @param Functional.Warehouse#WAREHOUSE.Assetitem asset Asset -- @param Functional.Warehouse#WAREHOUSE.Assetitem asset Asset
+40 -2
View File
@@ -2311,6 +2311,43 @@ function OPSGROUP:IsLoaded(CarrierGroupName)
return self.cargoStatus==OPSGROUP.CargoStatus.LOADED return self.cargoStatus==OPSGROUP.CargoStatus.LOADED
end end
--- Check if the group is currently busy doing something.
--
-- * Boarding
-- * Rearming
-- * Returning
-- * Pickingup, Loading, Transporting, Unloading
-- * Engageing
--
-- @param #OPSGROUP self
-- @return #boolean If `true`, group is busy.
function OPSGROUP:IsBusy()
if self:IsBoarding() then
return true
end
if self:IsRearming() then
return true
end
if self:IsReturning() then
return true
end
-- Busy as carrier?
if self:IsPickingup() or self:IsLoading() or self:IsTransporting() or self:IsUnloading() then
return true
end
if self:IsEngaging() then
return true
end
return false
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Waypoint Functions -- Waypoint Functions
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -6995,7 +7032,8 @@ function OPSGROUP:onafterLoading(From, Event, To)
if cargo.opsgroup:IsNotCargo(true) and not isCarrier then if cargo.opsgroup:IsNotCargo(true) and not isCarrier then
-- Check if cargo is in embark/pickup zone. -- Check if cargo is in embark/pickup zone.
local inzone=cargo.opsgroup:IsInZone(self.cargoTZC.EmbarkZone) -- Added InUtero here, if embark zone is moving (ship) and cargo has been spawned late activated and its position is not updated. Not sure if that breaks something else!
local inzone=cargo.opsgroup:IsInZone(self.cargoTZC.EmbarkZone) --or cargo.opsgroup:IsInUtero()
-- Cargo MUST be inside zone or it will not be loaded! -- Cargo MUST be inside zone or it will not be loaded!
if inzone then if inzone then
@@ -7018,7 +7056,7 @@ function OPSGROUP:onafterLoading(From, Event, To)
else else
-- Debug info. -- Debug info.
self:T(self.lid..string.format("Cargo %s NOT in embark zone %s", cargo.opsgroup:GetName(), self.cargoTZC.EmbarkZone:GetName())) self:T(self.lid..string.format("Cargo %s NOT in embark zone %s (and not InUTERO)", cargo.opsgroup:GetName(), self.cargoTZC.EmbarkZone:GetName()))
end end
end end
+13 -6
View File
@@ -864,7 +864,8 @@ function OPSTRANSPORT:_DelCarrier(CarrierGroup)
end end
end end
if #self.carriers==0 then if #self.carriers==0 then
-- TODO: This call can be WRONG!
self:DeadCarrierAll() self:DeadCarrierAll()
end end
@@ -1948,18 +1949,24 @@ function OPSTRANSPORT:_CountCargosInZone(Zone, Delivered, Carrier, TransportZone
local N=0 local N=0
for _,_cargo in pairs(cargos) do for _,_cargo in pairs(cargos) do
local cargo=_cargo --Ops.OpsGroup#OPSGROUP local cargo=_cargo --Ops.OpsGroup#OPSGROUP
-- Is not cargo?
local isNotCargo=cargo:IsNotCargo(true) local isNotCargo=cargo:IsNotCargo(true)
if not isNotCargo then if not isNotCargo then
isNotCargo=iscarrier(cargo) isNotCargo=iscarrier(cargo)
end end
-- Is in zone?
local isInZone=cargo:IsInZone(Zone)
-- Is in utero?
local isInUtero=cargo:IsInUtero()
-- Debug info. -- Debug info.
--self:T2(self.lid..string.format("Cargo=%s: notcargo=%s, iscarrier=%s inzone=%s, inutero=%s", cargo:GetName(), tostring(cargo:IsNotCargo(true)), tostring(iscarrier(cargo)), tostring(cargo:IsInZone(Zone)), tostring(cargo:IsInUtero()) )) self:I(self.lid..string.format("Cargo=%s: notcargo=%s, iscarrier=%s inzone=%s, inutero=%s", cargo:GetName(), tostring(cargo:IsNotCargo(true)), tostring(iscarrier(cargo)), tostring(isInZone), tostring(isInUtero)))
-- We look for groups that are not cargo, in the zone or in utero. -- We look for groups that are not cargo, in the zone or in utero.
if isNotCargo and (cargo:IsInZone(Zone) or cargo:IsInUtero()) then if isNotCargo and (isInZone or isInUtero) then
N=N+1 N=N+1
end end
end end