- 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

View File

@ -91,7 +91,13 @@
-- @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 transportDropoff Coordinate where to drop off the cargo.
--
-- @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 artyShots Number of shots fired.
@ -588,7 +594,7 @@ function AUFTRAG:New(Type)
self:SetPriority()
self:SetTime()
self:SetRequiredAssets()
self:SetRequiredCarriers()
--self:SetRequiredCarriers()
self.engageAsGroup=true
self.dTevaluate=5
@ -2182,14 +2188,11 @@ end
-- @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`.
-- @return #AUFTRAG self
function AUFTRAG:SetTransportForAssets(DeployZone, DisembarkZone, NcarriersMin, NcarriersMax)
function AUFTRAG:SetRequiredTransport(DeployZone, DisembarkZone, NcarriersMin, NcarriersMax)
-- OPS transport from pickup to deploy zone.
self.opstransport=OPSTRANSPORT:New(nil, nil, DeployZone)
if DisembarkZone then
self.opstransport:SetDisembarkZone(DisembarkZone)
end
self.transportDeployZone=DeployZone
self.transportDisembarkZone=DisembarkZone
-- Set required carriers.
self:SetRequiredCarriers(NcarriersMin, NcarriersMax)
@ -2226,18 +2229,13 @@ end
-- @return #AUFTRAG self
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.
if self.nCarriersMax<self.nCarriersMin then
self.nCarriersMax=self.nCarriersMin
end
-- Pass this on to the ops transport.
if self.opstransport then
self.opstransport:SetRequiredCarriers(NcarriersMin, NcarriersMax)
if self.NcarriersMax<self.NcarriersMin then
self.NcarriersMax=self.NcarriersMin
end
return self

View File

@ -224,7 +224,7 @@ end
--- Add a patrol Point for CAP missions.
-- @param #BRIGADE self
-- @param Core.Zone#ZONE Rearming zone.
-- @return #AIRWING self
-- @return #BRIGADE self
function BRIGADE:AddRearmingZone(RearmingZone)
local rearmingzone={} --#BRIGADE.RearmingZone

View File

@ -989,7 +989,7 @@ end
-- @param #string Event Event.
-- @param #string To To state.
-- @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))
end
@ -1563,80 +1563,31 @@ function CHIEF:RecruitAssetsForZone(OpsZone, MissionType, NassetsMin, NassetsMax
if recruitedInf then
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.
local pickupzone=legion.spawnzone
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
-- Recruit transport assets for infantry.
local recruitedTrans, transport=LEGION.AssignAssetsForTransport(self.commander, self.commander.legions, assetsInf, 1, 1, OpsZone.zone, nil, {Group.Category.HELICOPTER, Group.Category.GROUND})
-- Create Patrol zone mission.
local mission=AUFTRAG:NewPATROLZONE(OpsZone.zone)
mission:SetEngageDetected()
-- Add assets to mission.
for _,asset in pairs(assetsInf) do
mission:AddAsset(asset)
end
-- Attach OPS transport to mission.
mission.opstransport=transport
-- Assign mission to legions.
for _,_legion in pairs(legionsInf) do
local legion=_legion --Ops.Legion#LEGION
self.commander:MissionAssign(legion, mission)
end
-- Attach mission to ops zone.
-- TODO: Need a better way!
OpsZone.missionPatrol=mission
return true

View File

@ -645,9 +645,6 @@ end
-- @param #COMMANDER self
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.
local Nmissions=#self.missionqueue
@ -708,69 +705,18 @@ function COMMANDER:CheckMissionQueue()
-- Escort requested and available.
if EscortAvail then
-- Check if mission assets need a transport.
if mission.opstransport then
-- Check if mission assets need a transport.
if mission.NcarriersMin then
-- Weight of the heaviest cargo group. Necessary condition that this fits into on carrier unit!
local weightGroup=0
-- 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
-- Recruit carrier assets for transport.
local Transport=nil
local Legions=mission.transportLegions or self.legions
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.
local TransportAvail, assetsTrans, legionsTrans=self:RecruitAssetsForTransport(mission.opstransport, weightGroup)
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)
-- Add opstransport to mission.
if TransportAvail and Transport then
mission.opstransport=Transport
end
end
@ -856,102 +802,34 @@ end
--- Recruit assets performing an escort mission for a given asset.
-- @param #COMMANDER self
-- @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.
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?
if Mission.NescortMin and Mission.NescortMax and (Mission.NescortMin>0 or Mission.NescortMax>0) then
-- 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))
-- Escorts for each asset.
local Escorts={}
local EscortAvail=true
for _,_asset in pairs(Assets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
-- 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)
-- 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
-- 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
-- No escort required.
return true
end
-- Call LEGION function but provide COMMANDER as self.
local assigned=LEGION.AssignAssetsForEscort(self, Cohorts, Assets, Mission.NescortMin, Mission.NescortMin)
return assigned
end
return true
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -1072,7 +950,7 @@ end
-- @return #table Legions that have recruited assets.
function COMMANDER:RecruitAssetsForTransport(Transport, CargoWeight)
if weightGroup==0 then
if CargoWeight==0 then
-- No cargo groups!
return false, {}, {}
end
@ -1221,6 +1099,30 @@ function COMMANDER:GetLegionsForMission(Mission)
return legions
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
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -83,9 +83,11 @@ function LEGION:New(WarehouseName, LegionName)
-- From State --> Event --> To State
self:AddTransition("*", "MissionRequest", "*") -- Add a (mission) request to the warehouse.
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("*", "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).
@ -118,18 +120,27 @@ function LEGION:New(WarehouseName, LegionName)
-- @param #LEGION self
-- @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 #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 "MissionCancel" event.
-- @function [parent=#LEGION] OnAfterMissionCancel
--- Triggers the FSM event "MissionAssign" after a delay.
-- @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 #string From From state.
-- @param #string Event Event.
-- @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.
@ -153,6 +164,44 @@ function LEGION:New(WarehouseName, LegionName)
-- @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".
-- @function [parent=#LEGION] TransportRequest
-- @param #LEGION self
@ -274,30 +323,6 @@ function LEGION:AddMission(Mission)
if Mission.type==AUFTRAG.Type.ALERT5 then
Mission:_TargetFromObject(self:GetCoordinate())
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.
table.insert(self.missionqueue, Mission)
@ -481,20 +506,38 @@ function LEGION:_GetNextMission()
-- Reserve assets and add to mission.
for _,_asset in pairs(assets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
asset.isReserved=true
mission:AddAsset(asset)
end
-- Recruit asset for escorting recruited mission assets.
local EscortAvail=self:RecruitAssetsForEscort(mission, assets)
-- Transport available (or not required).
local TransportAvail=true
-- Is escort required and available?
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.
return mission
return mission
else
-- Recruited assets but no requested escort available. Unrecruit assets!
LEGION.UnRecruitAssets(assets, mission)
LEGION.UnRecruitAssets(assets, mission)
end
end -- recruited mission assets
@ -552,7 +595,6 @@ function LEGION:_GetNextTransport()
-- Add asset to transport.
for _,_asset in pairs(assets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
asset.isReserved=true
transport:AddAsset(asset)
end
@ -572,6 +614,27 @@ end
-- 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.
-- @param #LEGION self
-- @param #string From From state.
@ -683,7 +746,27 @@ function LEGION:onafterMissionRequest(From, Event, To, Mission)
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 #string From From state.
-- @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.
if cohort then
-- Debug info.
self:I(self.lid..string.format("Cohort asset spawned %s", asset.spawngroupname))
-- Create a flight group.
@ -1666,6 +1750,8 @@ end
-- @param #LEGION self
-- @param Ops.OpsTransport#OPSTRANSPORT Transport The OPS transport.
-- @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)
-- Get all undelivered cargo ops groups.
@ -1716,82 +1802,15 @@ function LEGION:RecruitAssetsForEscort(Mission, Assets)
-- 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))
-- Escorts for each asset.
local Escorts={}
--TODO: Maybe add escortCohorts as mission option?
local EscortAvail=true
for _,_asset in pairs(Assets) do
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
-- Call LEGION function but provide COMMANDER as self.
local assigned=LEGION.AssignAssetsForEscort(self, self.cohorts, Assets, Mission.NescortMin, Mission.NescortMin)
-- 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
-- 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 assigned
end
return true
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -2001,6 +2020,215 @@ function LEGION.UnRecruitAssets(Assets, Mission)
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.
-- @param Functional.Warehouse#WAREHOUSE.Assetitem asset Asset

View File

@ -2311,6 +2311,43 @@ function OPSGROUP:IsLoaded(CarrierGroupName)
return self.cargoStatus==OPSGROUP.CargoStatus.LOADED
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
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -6995,7 +7032,8 @@ function OPSGROUP:onafterLoading(From, Event, To)
if cargo.opsgroup:IsNotCargo(true) and not isCarrier then
-- 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!
if inzone then
@ -7018,7 +7056,7 @@ function OPSGROUP:onafterLoading(From, Event, To)
else
-- 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

View File

@ -864,7 +864,8 @@ function OPSTRANSPORT:_DelCarrier(CarrierGroup)
end
end
if #self.carriers==0 then
if #self.carriers==0 then
-- TODO: This call can be WRONG!
self:DeadCarrierAll()
end
@ -1948,18 +1949,24 @@ function OPSTRANSPORT:_CountCargosInZone(Zone, Delivered, Carrier, TransportZone
local N=0
for _,_cargo in pairs(cargos) do
local cargo=_cargo --Ops.OpsGroup#OPSGROUP
-- Is not cargo?
local isNotCargo=cargo:IsNotCargo(true)
if not isNotCargo then
isNotCargo=iscarrier(cargo)
end
end
-- Is in zone?
local isInZone=cargo:IsInZone(Zone)
-- Is in utero?
local isInUtero=cargo:IsInUtero()
-- 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.
if isNotCargo and (cargo:IsInZone(Zone) or cargo:IsInUtero()) then
if isNotCargo and (isInZone or isInUtero) then
N=N+1
end
end