COMMANDER

- Added OPS transport (untested)
This commit is contained in:
Frank 2021-09-13 08:31:00 +02:00
parent 6a6cb1961d
commit 1d0eb9806d
9 changed files with 672 additions and 257 deletions

View File

@ -2223,6 +2223,20 @@ do -- ZONE_AIRBASE
self._.ZoneAirbase = Airbase self._.ZoneAirbase = Airbase
self._.ZoneVec2Cache = self._.ZoneAirbase:GetVec2() self._.ZoneVec2Cache = self._.ZoneAirbase:GetVec2()
if Airbase:IsShip() then
self.isShip=true
self.isHelipad=false
self.isAirdrome=false
elseif Airbase:IsHelipad() then
self.isShip=false
self.isHelipad=true
self.isAirdrome=false
elseif Airbase:IsAirdrome() then
self.isShip=false
self.isHelipad=false
self.isAirdrome=true
end
-- Zone objects are added to the _DATABASE and SET_ZONE objects. -- Zone objects are added to the _DATABASE and SET_ZONE objects.
_EVENTDISPATCHER:CreateEventNewZone( self ) _EVENTDISPATCHER:CreateEventNewZone( self )

View File

@ -1866,6 +1866,9 @@ function WAREHOUSE:New(warehouse, alias)
self.isunit=false self.isunit=false
else else
self.isunit=true self.isunit=true
if warehouse:IsShip() then
self.isShip=true
end
end end
end end
@ -1909,8 +1912,14 @@ function WAREHOUSE:New(warehouse, alias)
end end
-- Define warehouse and default spawn zone. -- Define warehouse and default spawn zone.
self.zone=ZONE_RADIUS:New(string.format("Warehouse zone %s", self.warehouse:GetName()), warehouse:GetVec2(), 500) if self.isShip then
self.spawnzone=ZONE_RADIUS:New(string.format("Warehouse %s spawn zone", self.warehouse:GetName()), warehouse:GetVec2(), 250) self.zone=ZONE_AIRBASE:New(self.warehouse:GetName(), 1000)
self.spawnzone=ZONE_AIRBASE:New(self.warehouse:GetName(), 1000)
else
self.zone=ZONE_RADIUS:New(string.format("Warehouse zone %s", self.warehouse:GetName()), warehouse:GetVec2(), 500)
self.spawnzone=ZONE_RADIUS:New(string.format("Warehouse %s spawn zone", self.warehouse:GetName()), warehouse:GetVec2(), 250)
end
-- Defaults -- Defaults
self:SetMarker(true) self:SetMarker(true)
@ -4507,6 +4516,11 @@ function WAREHOUSE:onafterRequest(From, Event, To, Request)
return return
end end
-- Trigger event.
if spawngroup then
self:__AssetSpawned(0.01, spawngroup, _assetitem, Request)
end
end end
-- Init problem table. -- Init problem table.
@ -5336,24 +5350,6 @@ function WAREHOUSE:onafterRunwayRepaired(From, Event, To)
end end
--- On before "AssetSpawned" event. Checks whether the asset was already set to "spawned" for groups with multiple units.
-- @param #WAREHOUSE self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Wrapper.Group#GROUP group The group spawned.
-- @param #WAREHOUSE.Assetitem asset The asset that is dead.
-- @param #WAREHOUSE.Pendingitem request The request of the dead asset.
function WAREHOUSE:onbeforeAssetSpawned(From, Event, To, group, asset, request)
if asset.spawned then
--return false
else
--return true
end
return true
end
--- On after "AssetSpawned" event triggered when an asset group is spawned into the cruel world. --- On after "AssetSpawned" event triggered when an asset group is spawned into the cruel world.
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param #string From From state. -- @param #string From From state.
@ -5368,6 +5364,24 @@ function WAREHOUSE:onafterAssetSpawned(From, Event, To, group, asset, request)
-- Sete asset state to spawned. -- Sete asset state to spawned.
asset.spawned=true asset.spawned=true
-- Set spawn group name.
asset.spawngroupname=group:GetName()
-- Remove asset from stock.
self:_DeleteStockItem(asset)
-- Add group.
if asset.iscargo==true then
request.cargogroupset=request.cargogroupset or SET_GROUP:New()
request.cargogroupset:AddGroup(group)
else
request.transportgroupset=request.transportgroupset or SET_GROUP:New()
request.transportgroupset:AddGroup(group)
end
-- Set warehouse state.
group:SetState(group, "WAREHOUSE", self)
-- Check if all assets groups are spawned and trigger events. -- Check if all assets groups are spawned and trigger events.
local n=0 local n=0
@ -5718,15 +5732,15 @@ function WAREHOUSE:_SpawnAssetRequest(Request)
if asset.category==Group.Category.GROUND then if asset.category==Group.Category.GROUND then
-- Spawn ground troops. -- Spawn ground troops.
_group=self:_SpawnAssetGroundNaval(_alias, asset, Request, self.spawnzone) _group=self:_SpawnAssetGroundNaval(_alias, asset, Request, self.spawnzone, Request.lateActivation)
elseif asset.category==Group.Category.AIRPLANE or asset.category==Group.Category.HELICOPTER then elseif asset.category==Group.Category.AIRPLANE or asset.category==Group.Category.HELICOPTER then
-- Spawn air units. -- Spawn air units.
if Parking[asset.uid] then if Parking[asset.uid] then
_group=self:_SpawnAssetAircraft(_alias, asset, Request, Parking[asset.uid], UnControlled) _group=self:_SpawnAssetAircraft(_alias, asset, Request, Parking[asset.uid], UnControlled, Request.lateActivation)
else else
_group=self:_SpawnAssetAircraft(_alias, asset, Request, nil, UnControlled) _group=self:_SpawnAssetAircraft(_alias, asset, Request, nil, UnControlled, Request.lateActivation)
end end
elseif asset.category==Group.Category.TRAIN then elseif asset.category==Group.Category.TRAIN then
@ -5736,7 +5750,7 @@ function WAREHOUSE:_SpawnAssetRequest(Request)
--TODO: Rail should only get one asset because they would spawn on top! --TODO: Rail should only get one asset because they would spawn on top!
-- Spawn naval assets. -- Spawn naval assets.
_group=self:_SpawnAssetGroundNaval(_alias, asset, Request, self.spawnzone) _group=self:_SpawnAssetGroundNaval(_alias, asset, Request, self.spawnzone, Request.lateActivation)
end end
--self:E(self.lid.."ERROR: Spawning of TRAIN assets not possible yet!") --self:E(self.lid.."ERROR: Spawning of TRAIN assets not possible yet!")
@ -5744,11 +5758,16 @@ function WAREHOUSE:_SpawnAssetRequest(Request)
elseif asset.category==Group.Category.SHIP then elseif asset.category==Group.Category.SHIP then
-- Spawn naval assets. -- Spawn naval assets.
_group=self:_SpawnAssetGroundNaval(_alias, asset, Request, self.portzone) _group=self:_SpawnAssetGroundNaval(_alias, asset, Request, self.portzone, Request.lateActivation)
else else
self:E(self.lid.."ERROR: Unknown asset category!") self:E(self.lid.."ERROR: Unknown asset category!")
end end
-- Trigger event.
if _group then
self:__AssetSpawned(0.01, _group, asset, Request)
end
end end
@ -5761,9 +5780,9 @@ end
-- @param #WAREHOUSE.Assetitem asset Ground asset that will be spawned. -- @param #WAREHOUSE.Assetitem asset Ground asset that will be spawned.
-- @param #WAREHOUSE.Queueitem request Request belonging to this asset. Needed for the name/alias. -- @param #WAREHOUSE.Queueitem request Request belonging to this asset. Needed for the name/alias.
-- @param Core.Zone#ZONE spawnzone Zone where the assets should be spawned. -- @param Core.Zone#ZONE spawnzone Zone where the assets should be spawned.
-- @param #boolean aioff If true, AI of ground units are set to off. -- @param #boolean lateactivated If true, groups are spawned late activated.
-- @return Wrapper.Group#GROUP The spawned group or nil if the group could not be spawned. -- @return Wrapper.Group#GROUP The spawned group or nil if the group could not be spawned.
function WAREHOUSE:_SpawnAssetGroundNaval(alias, asset, request, spawnzone, aioff) function WAREHOUSE:_SpawnAssetGroundNaval(alias, asset, request, spawnzone, lateactivated)
if asset and (asset.category==Group.Category.GROUND or asset.category==Group.Category.SHIP or asset.category==Group.Category.TRAIN) then if asset and (asset.category==Group.Category.GROUND or asset.category==Group.Category.SHIP or asset.category==Group.Category.TRAIN) then
@ -5806,6 +5825,11 @@ function WAREHOUSE:_SpawnAssetGroundNaval(alias, asset, request, spawnzone, aiof
end end
end end
-- Late activation.
template.lateActivation=lateactivated
env.info("FF lateActivation="..tostring(template.lateActivation))
template.route.points[1].x = coord.x template.route.points[1].x = coord.x
template.route.points[1].y = coord.z template.route.points[1].y = coord.z
@ -5817,14 +5841,6 @@ function WAREHOUSE:_SpawnAssetGroundNaval(alias, asset, request, spawnzone, aiof
-- Spawn group. -- Spawn group.
local group=_DATABASE:Spawn(template) --Wrapper.Group#GROUP local group=_DATABASE:Spawn(template) --Wrapper.Group#GROUP
-- Activate group. Should only be necessary for late activated groups.
--group:Activate()
-- Switch AI off if desired. This works only for ground and naval groups.
if aioff then
group:SetAIOff()
end
return group return group
end end
@ -5838,8 +5854,9 @@ end
-- @param #WAREHOUSE.Queueitem request Request belonging to this asset. Needed for the name/alias. -- @param #WAREHOUSE.Queueitem request Request belonging to this asset. Needed for the name/alias.
-- @param #table parking Parking data for this asset. -- @param #table parking Parking data for this asset.
-- @param #boolean uncontrolled Spawn aircraft in uncontrolled state. -- @param #boolean uncontrolled Spawn aircraft in uncontrolled state.
-- @param #boolean lateactivated If true, groups are spawned late activated.
-- @return Wrapper.Group#GROUP The spawned group or nil if the group could not be spawned. -- @return Wrapper.Group#GROUP The spawned group or nil if the group could not be spawned.
function WAREHOUSE:_SpawnAssetAircraft(alias, asset, request, parking, uncontrolled) function WAREHOUSE:_SpawnAssetAircraft(alias, asset, request, parking, uncontrolled, lateactivated)
if asset and asset.category==Group.Category.AIRPLANE or asset.category==Group.Category.HELICOPTER then if asset and asset.category==Group.Category.AIRPLANE or asset.category==Group.Category.HELICOPTER then
@ -6329,54 +6346,13 @@ function WAREHOUSE:_OnEventBirth(EventData)
local request=self:GetRequestByID(rid) local request=self:GetRequestByID(rid)
if asset and request then if asset and request then
if asset.spawned and type(asset.spawned)=="boolean" and asset.spawned==true then
return
end
-- Debug message. -- Debug message.
self:T(self.lid..string.format("Warehouse %s captured event birth of request ID=%d, asset ID=%d, unit %s spawned=%s", self.alias, request.uid, asset.uid, EventData.IniUnitName, tostring(asset.spawned))) self:T(self.lid..string.format("Warehouse %s captured event birth of request ID=%d, asset ID=%d, unit %s spawned=%s", self.alias, request.uid, asset.uid, EventData.IniUnitName, tostring(asset.spawned)))
-- Set born to true. -- Set born to true.
request.born=true request.born=true
if not asset.spawned then
asset.spawned=1
else
asset.spawned=asset.spawned+1
end
-- Birth is triggered for each unit. We need to make sure not to call this too often!
if asset.spawned==asset.nunits then
-- Remove asset from stock.
self:_DeleteStockItem(asset)
-- Set spawned switch.
asset.spawned=true
asset.spawngroupname=group:GetName()
-- Add group.
if asset.iscargo==true then
request.cargogroupset=request.cargogroupset or SET_GROUP:New()
request.cargogroupset:AddGroup(group)
else
request.transportgroupset=request.transportgroupset or SET_GROUP:New()
request.transportgroupset:AddGroup(group)
end
-- Set warehouse state.
group:SetState(group, "WAREHOUSE", self)
-- Asset spawned FSM function.
-- This needs to be delayed a bit for all units to be present. Especially, since MOOSE needs a birth event for UNITs to be added to the _DATABASE.
self:__AssetSpawned(0.1, group, asset, request)
--self:AssetSpawned(group, asset, request)
end
else else
self:E(self.lid..string.format("ERROR: Either asset AID=%s or request RID=%s are nil in event birth of unit %s", tostring(aid), tostring(rid), tostring(EventData.IniUnitName))) self:E(self.lid..string.format("ERROR: Either asset AID=%s or request RID=%s are nil in event birth of unit %s", tostring(aid), tostring(rid), tostring(EventData.IniUnitName)))
end end
@ -7076,10 +7052,9 @@ function WAREHOUSE:_CheckRequestValid(request)
-- Check that both spawn zones are not in water. -- Check that both spawn zones are not in water.
local inwater=self.spawnzone:GetCoordinate():IsSurfaceTypeWater() or request.warehouse.spawnzone:GetCoordinate():IsSurfaceTypeWater() local inwater=self.spawnzone:GetCoordinate():IsSurfaceTypeWater() or request.warehouse.spawnzone:GetCoordinate():IsSurfaceTypeWater()
if inwater then if inwater and not request.lateActivation then
self:E("ERROR: Incorrect request. Ground asset requested but at least one spawn zone is in water!") self:E("ERROR: Incorrect request. Ground asset requested but at least one spawn zone is in water!")
--valid=false return false
valid=false
end end
-- No ground assets directly to or from ships. -- No ground assets directly to or from ships.

View File

@ -299,6 +299,32 @@ function CHIEF:RemoveMission(Mission)
return self return self
end end
--- Add transport to transport queue of the COMMANDER.
-- @param #CHIEF self
-- @param Ops.OpsTransport#OPSTRANSPORT Transport Transport to be added.
-- @return #CHIEF self
function CHIEF:AddOpsTransport(Transport)
Transport.chief=self
self.commander:AddOpsTransport(Transport)
return self
end
--- Remove transport from queue.
-- @param #CHIEF self
-- @param Ops.OpsTransport#OPSTRANSPORT Transport Transport to be removed.
-- @return #CHIEF self
function CHIEF:RemoveTransport(Transport)
Transport.chief=nil
self.commander:RemoveTransport(Transport)
return self
end
--- Add target. --- Add target.
-- @param #CHIEF self -- @param #CHIEF self
-- @param Ops.Target#TARGET Target Target object to be added. -- @param Ops.Target#TARGET Target Target object to be added.

View File

@ -19,6 +19,7 @@
-- @field #string lid Class id string for output to DCS log file. -- @field #string lid Class id string for output to DCS log file.
-- @field #table legions Table of legions which are commanded. -- @field #table legions Table of legions which are commanded.
-- @field #table missionqueue Mission queue. -- @field #table missionqueue Mission queue.
-- @field #table transportqueue Transport queue.
-- @field Ops.ChiefOfStaff#CHIEF chief Chief of staff. -- @field Ops.ChiefOfStaff#CHIEF chief Chief of staff.
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
@ -37,6 +38,7 @@ COMMANDER = {
verbose = 0, verbose = 0,
legions = {}, legions = {},
missionqueue = {}, missionqueue = {},
transportqueue = {},
} }
--- COMMANDER class version. --- COMMANDER class version.
@ -80,6 +82,9 @@ function COMMANDER:New()
self:AddTransition("*", "MissionAssign", "*") -- Mission is assigned to a or multiple LEGIONs. self:AddTransition("*", "MissionAssign", "*") -- Mission is assigned to a or multiple LEGIONs.
self:AddTransition("*", "MissionCancel", "*") -- COMMANDER cancels a mission. self:AddTransition("*", "MissionCancel", "*") -- COMMANDER cancels a mission.
self:AddTransition("*", "TransportAssign", "*") -- Transport is assigned to a or multiple LEGIONs.
self:AddTransition("*", "TransportCancel", "*") -- COMMANDER cancels a Transport.
------------------------ ------------------------
--- Pseudo Functions --- --- Pseudo Functions ---
------------------------ ------------------------
@ -155,6 +160,43 @@ function COMMANDER:New()
-- @param #string To To state. -- @param #string To To state.
-- @param Ops.Auftrag#AUFTRAG Mission The mission. -- @param Ops.Auftrag#AUFTRAG Mission The mission.
--- Triggers the FSM event "TransportAssign" after a delay.
-- @function [parent=#COMMANDER] __TransportAssign
-- @param #COMMANDER self
-- @param #number delay Delay in seconds.
-- @param Ops.Legion#LEGION Legion The Legion.
-- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport.
--- On after "TransportAssign" event.
-- @function [parent=#COMMANDER] OnAfterTransportAssign
-- @param #COMMANDER 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 Transport The transport.
--- Triggers the FSM event "TransportCancel".
-- @function [parent=#COMMANDER] TransportCancel
-- @param #COMMANDER self
-- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport.
--- Triggers the FSM event "TransportCancel" after a delay.
-- @function [parent=#COMMANDER] __TransportCancel
-- @param #COMMANDER self
-- @param #number delay Delay in seconds.
-- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport.
--- On after "TransportCancel" event.
-- @function [parent=#COMMANDER] OnAfterTransportCancel
-- @param #COMMANDER self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport.
return self return self
end end
@ -225,6 +267,21 @@ function COMMANDER:AddMission(Mission)
return self return self
end end
--- Add transport to queue.
-- @param #COMMANDER self
-- @param Ops.OpsTransport#OPSTRANSPORT Transport The OPS transport to be added.
-- @return #COMMANDER self
function COMMANDER:AddOpsTransport(Transport)
Transport.commander=self
Transport.statusCommander=TRANSPORT.Status.PLANNED
table.insert(self.transportqueue, Transport)
return self
end
--- Remove mission from queue. --- Remove mission from queue.
-- @param #COMMANDER self -- @param #COMMANDER self
-- @param Ops.Auftrag#AUFTRAG Mission Mission to be removed. -- @param Ops.Auftrag#AUFTRAG Mission Mission to be removed.
@ -246,6 +303,27 @@ function COMMANDER:RemoveMission(Mission)
return self return self
end end
--- Remove transport from queue.
-- @param #COMMANDER self
-- @param Ops.OpsTransport#OPSTRANSPORT Transport The OPS transport to be removed.
-- @return #COMMANDER self
function COMMANDER:RemoveTransport(Transport)
for i,_transport in pairs(self.transportqueue) do
local transport=_transport --Ops.OpsTransport#OPSTRANSPORT
if transport.uid==Transport.uid then
self:I(self.lid..string.format("Removing mission %s (%s) status=%s from queue", transport.uid, transport:GetState()))
transport.commander=nil
table.remove(self.transportqueue, i)
break
end
end
return self
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Start & Status -- Start & Status
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -292,6 +370,8 @@ function COMMANDER:onafterStatus(From, Event, To)
-- Check mission queue and assign one PLANNED mission. -- Check mission queue and assign one PLANNED mission.
self:CheckMissionQueue() self:CheckMissionQueue()
-- Check mission queue and assign one PLANNED mission
--- ---
-- LEGIONS -- LEGIONS
@ -387,6 +467,20 @@ function COMMANDER:onafterStatus(From, Event, To)
end end
self:I(self.lid..text) self:I(self.lid..text)
end end
---
-- TRANSPORTS
---
-- Transport queue.
if self.verbose>=2 and #self.transportqueue>0 then
local text="Transport queue:"
for i,_transport in pairs(self.transportqueue) do
local transport=_transport --Ops.OpsTransport#OPSTRANSPORT
text=text..string.format("\n[%d] UID=%d: status=%s", i, transport.uid, transport:GetState())
end
self:I(self.lid..text)
end
self:__Status(-30) self:__Status(-30)
end end
@ -455,8 +549,31 @@ function COMMANDER:onafterMissionCancel(From, Event, To, Mission)
end end
--- On after "MissionAssign" event. Mission is added to a LEGION mission queue.
-- @param #COMMANDER 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
function COMMANDER:onafterTransportAssign(From, Event, To, Legion, Transport)
-- Debug info.
self:I(self.lid..string.format("Assigning transport %d to legion %s", Transport.uid, Legion.alias))
-- Set mission commander status to QUEUED as it is now queued at a legion.
Transport.statusCommander=OPSTRANSPORT.Status.QUEUED
-- Add mission to legion.
Legion:AddOpsTransport(Transport)
-- Directly request the mission as the assets have already been selected.
Legion:TransportRequest(Transport)
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Resources -- Mission Functions
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Check mission queue and assign ONE planned mission. --- Check mission queue and assign ONE planned mission.
@ -538,113 +655,6 @@ function COMMANDER:CheckMissionQueue()
end end
--- Check all legions if they are able to do a specific mission type at a certain location with a given number of assets.
-- @param #COMMANDER self
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
-- @return #table Table of LEGIONs that can do the mission and have at least one asset available right now.
function COMMANDER:GetLegionsForMission(Mission)
-- Table of legions that can do the mission.
local legions={}
-- Loop over all legions.
for _,_legion in pairs(self.legions) do
local legion=_legion --Ops.Legion#LEGION
-- Count number of assets in stock.
local Nassets=0
if legion:IsAirwing() then
Nassets=legion:CountAssetsWithPayloadsInStock(Mission.payloads, {Mission.type}, Attributes)
else
Nassets=legion:CountAssets(true, {Mission.type}, Attributes) --Could also specify the attribute if Air or Ground mission.
end
-- Has it assets that can?
if Nassets>0 and false then
-- Get coordinate of the target.
local coord=Mission:GetTargetCoordinate()
if coord then
-- Distance from legion to target.
local distance=UTILS.MetersToNM(coord:Get2DDistance(legion:GetCoordinate()))
-- Round: 55 NM ==> 5.5 ==> 6, 63 NM ==> 6.3 ==> 6
local dist=UTILS.Round(distance/10, 0)
-- Debug info.
self:I(self.lid..string.format("Got legion %s with Nassets=%d and dist=%.1f NM, rounded=%.1f", legion.alias, Nassets, distance, dist))
-- Add legion to table of legions that can.
table.insert(legions, {airwing=legion, distance=distance, dist=dist, targetcoord=coord, nassets=Nassets})
end
end
-- Add legion if it can provide at least 1 asset.
if Nassets>0 then
table.insert(legions, legion)
end
end
return legions
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 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:CountAssets(InStock, MissionTypes, Attributes)
local N=0
for _,_legion in pairs(self.legions) do
local legion=_legion --Ops.Legion#LEGION
N=N+legion:CountAssets(InStock, MissionTypes, Attributes)
end
return N
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
--- Recruit assets for a given mission. --- Recruit assets for a given mission.
-- @param #COMMANDER self -- @param #COMMANDER self
@ -757,7 +767,7 @@ function COMMANDER:RecruitAssets(Mission)
-- Add assets to mission. -- Add assets to mission.
for i=1,Nassets do for i=1,Nassets do
local asset=Assets[i] --Functional.Warehouse#WAREHOUSE.Assetitem local asset=Assets[i] --Functional.Warehouse#WAREHOUSE.Assetitem
self:T(self.lid..string.format("Adding asset %s to mission %s [%s]", asset.spawngroupname, Mission.name, Mission.type)) asset.isReserved=true
Mission:AddAsset(asset) Mission:AddAsset(asset)
Legions[asset.legion.alias]=asset.legion Legions[asset.legion.alias]=asset.legion
end end
@ -832,6 +842,393 @@ function COMMANDER:_OptimizeAssetSelection(assets, Mission, includePayload)
end end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Transport Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Check transport queue and assign ONE planned transport.
-- @param #COMMANDER self
function COMMANDER:CheckTransportQueue()
-- Number of missions.
local Ntransports=#self.transportqueue
-- Treat special cases.
if Ntransports==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.transportqueue, _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 _,_transport in pairs(self.transportqueue) do
local transport=_transport --Ops.OpsTransport#OPSTRANSPORT
if transport.importance and transport.importance<vip then
vip=transport.importance
end
end
for _,_transport in pairs(self.transportqueue) do
local transport=_transport --Ops.OpsTransport#OPSTRANSPORT
-- We look for PLANNED missions.
if transport:IsPlanned() and transport:IsReadyToGo() and (transport.importance==nil or transport.importance<=vip) then
---
-- PLANNNED Mission
--
-- 1. Select best assets from legions
-- 2. Assign mission to legions that have the best assets.
---
-- Recruite assets from legions.
local recruited, legions=self:RecruitAssetsForTransport(transport)
if recruited then
for _,_legion in pairs(legions) do
local legion=_legion --Ops.Legion#LEGION
-- Debug message.
self:I(self.lid..string.format("Assigning transport UID=%d to legion %s", transport.uid, legion.alias))
-- Add mission to legion.
self:TransportAssign(legion, transport)
end
-- Only ONE transport is assigned.
return
end
else
---
-- Missions NOT in PLANNED state
---
end
end
end
--- Recruit assets for a given transport.
-- @param #COMMANDER self
-- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport.
-- @return #boolean If `true`, enough assets could be recruited.
-- @return #table Legions that have recruited assets.
function COMMANDER:RecruitAssetsForTransport(Transport)
-- Get all undelivered cargo ops groups.
local cargoOpsGroups=Transport:GetCargoOpsGroups(false)
local weightGroup=0
-- At least one group should be spawned.
if #cargoOpsGroups>0 then
-- Calculate the max weight so we know which cohorts can provide carriers.
for _,_opsgroup in pairs(cargoOpsGroups) do
local opsgroup=_opsgroup --Ops.OpsGroup#OPSGROUP
local weight=opsgroup:GetWeightTotal()
if weight>weightGroup then
weightGroup=weight
end
end
else
-- No cargo groups!
return false, {}
end
-- The recruited assets.
local Assets={}
-- Legions we consider for selecting assets.
local legions=self.legions
--TODO: Setting of Mission.squadrons (cohorts) will not work here!
-- Legions which have the best assets for the Mission.
local Legions={}
for _,_legion in pairs(legions) do
local legion=_legion --Ops.Legion#LEGION
-- Number of payloads in stock per aircraft type.
local Npayloads={}
-- First get payloads for aircraft types of squadrons.
for _,_cohort in pairs(legion.cohorts) do
local cohort=_cohort --Ops.Cohort#COHORT
if Npayloads[cohort.aircrafttype]==nil then
Npayloads[cohort.aircrafttype]=legion:IsAirwing() and legion:CountPayloadsInStock(AUFTRAG.Type.OPSTRANSPORT, cohort.aircrafttype) or 999
self:I(self.lid..string.format("Got N=%d payloads for mission type %s [%s]", Npayloads[cohort.aircrafttype], AUFTRAG.Type.OPSTRANSPORT, cohort.aircrafttype))
end
end
-- Loops over cohorts.
for _,_cohort in pairs(legion.cohorts) do
local cohort=_cohort --Ops.Cohort#COHORT
local npayloads=Npayloads[cohort.aircrafttype]
if cohort:IsOnDuty() and npayloads>0 and cohort:CheckMissionCapability({AUFTRAG.Type.OPSTRANSPORT}) and cohort.cargobayLimit>=weightGroup then
-- Recruit assets from squadron.
local assets, npayloads=cohort:RecruitAssets(AUFTRAG.Type.OPSTRANSPORT, npayloads)
Npayloads[cohort.aircrafttype]=npayloads
for _,asset in pairs(assets) do
table.insert(Assets, asset)
end
end
end
end
-- Now we have a long list with assets.
self:_OptimizeAssetSelectionForTransport(Assets, Transport)
for _,_asset in pairs(Assets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
if asset.legion:IsAirwing() then
-- Only assets that have no payload. Should be only spawned assets!
if not asset.payload then
-- Fetch payload for asset. This can be nil!
asset.payload=asset.legion:FetchPayloadFromStock(asset.unittype, AUFTRAG.Type.OPSTRANSPORT)
end
end
end
-- Remove assets that dont have a payload.
for i=#Assets,1,-1 do
local asset=Assets[i] --Functional.Warehouse#WAREHOUSE.Assetitem
if asset.legion:IsAirwing() and not asset.payload then
table.remove(Assets, i)
end
end
-- Number of required carriers.
local NreqMin,NreqMax=Transport:GetRequiredCarriers()
-- Number of assets. At most NreqMax.
local Nassets=math.min(#Assets, NreqMax)
if Nassets>=NreqMin then
---
-- Found enough assets
---
-- Add assets to transport.
for i=1,Nassets do
local asset=Assets[i] --Functional.Warehouse#WAREHOUSE.Assetitem
asset.isReserved=true
Transport:AddAsset(asset)
Legions[asset.legion.alias]=asset.legion
end
-- Return payloads of not needed assets.
for i=Nassets+1,#Assets do
local asset=Assets[i] --Functional.Warehouse#WAREHOUSE.Assetitem
if asset.legion:IsAirwing() and not asset.spawned then
self:T(self.lid..string.format("Returning payload from asset %s", asset.spawngroupname))
asset.legion:ReturnPayloadFromAsset(asset)
end
end
-- Found enough assets.
return true, Legions
else
---
-- NOT enough assets
---
-- Return payloads of assets.
if self:IsAirwing() then
for i=1,#Assets do
local asset=Assets[i] --Functional.Warehouse#WAREHOUSE.Assetitem
if asset.legion:IsAirwing() and not asset.spawned then
self:T2(self.lid..string.format("Returning payload from asset %s", asset.spawngroupname))
asset.legion:ReturnPayloadFromAsset(asset)
end
end
end
-- Not enough assets found.
return false, {}
end
return nil, {}
end
--- Optimize chosen assets for the given transport.
-- @param #COMMANDER self
-- @param #table assets Table of (unoptimized) assets.
-- @param Ops.OpsTransport#OPSTRANSPORT Transport Transport assignment.
function COMMANDER:_OptimizeAssetSelectionForTransport(assets, Transport)
-- Calculate the mission score of all assets.
for _,_asset in pairs(assets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
asset.score=asset.legion:CalculateAssetTransportScore(asset, Transport)
end
--- Sort assets wrt to their mission score. Higher is better.
local function optimize(a, b)
local assetA=a --Functional.Warehouse#WAREHOUSE.Assetitem
local assetB=b --Functional.Warehouse#WAREHOUSE.Assetitem
-- Higher score wins. If equal score ==> closer wins.
return (assetA.score>assetB.score)
end
table.sort(assets, optimize)
-- Remove distance parameter.
local text=string.format("Optimized %d assets for %s mission (payload=%s):", #assets, Mission.type, tostring(includePayload))
for i,Asset in pairs(assets) do
local asset=Asset --Functional.Warehouse#WAREHOUSE.Assetitem
text=text..string.format("\n%s %s: score=%d", asset.squadname, asset.spawngroupname, asset.score)
asset.dist=nil
asset.score=nil
end
self:T2(self.lid..text)
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Resources
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 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 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:CountAssets(InStock, MissionTypes, Attributes)
local N=0
for _,_legion in pairs(self.legions) do
local legion=_legion --Ops.Legion#LEGION
N=N+legion:CountAssets(InStock, MissionTypes, Attributes)
end
return N
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
--- Check all legions if they are able to do a specific mission type at a certain location with a given number of assets.
-- @param #COMMANDER self
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
-- @return #table Table of LEGIONs that can do the mission and have at least one asset available right now.
function COMMANDER:GetLegionsForMission(Mission)
-- Table of legions that can do the mission.
local legions={}
-- Loop over all legions.
for _,_legion in pairs(self.legions) do
local legion=_legion --Ops.Legion#LEGION
-- Count number of assets in stock.
local Nassets=0
if legion:IsAirwing() then
Nassets=legion:CountAssetsWithPayloadsInStock(Mission.payloads, {Mission.type}, Attributes)
else
Nassets=legion:CountAssets(true, {Mission.type}, Attributes) --Could also specify the attribute if Air or Ground mission.
end
-- Has it assets that can?
if Nassets>0 and false then
-- Get coordinate of the target.
local coord=Mission:GetTargetCoordinate()
if coord then
-- Distance from legion to target.
local distance=UTILS.MetersToNM(coord:Get2DDistance(legion:GetCoordinate()))
-- Round: 55 NM ==> 5.5 ==> 6, 63 NM ==> 6.3 ==> 6
local dist=UTILS.Round(distance/10, 0)
-- Debug info.
self:I(self.lid..string.format("Got legion %s with Nassets=%d and dist=%.1f NM, rounded=%.1f", legion.alias, Nassets, distance, dist))
-- Add legion to table of legions that can.
table.insert(legions, {airwing=legion, distance=distance, dist=dist, targetcoord=coord, nassets=Nassets})
end
end
-- Add legion if it can provide at least 1 asset.
if Nassets>0 then
table.insert(legions, legion)
end
end
return legions
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -1374,16 +1374,17 @@ end
-- @param Wrapper.Airbase#AIRBASE.ParkingSpot Spot Parking Spot. -- @param Wrapper.Airbase#AIRBASE.ParkingSpot Spot Parking Spot.
function FLIGHTGROUP:onafterElementParking(From, Event, To, Element, Spot) function FLIGHTGROUP:onafterElementParking(From, Event, To, Element, Spot)
-- Set parking spot.
if Spot then
self:_SetElementParkingAt(Element, Spot)
end
-- Debug info. -- Debug info.
self:T(self.lid..string.format("Element parking %s at spot %s", Element.name, Element.parking and tostring(Element.parking.TerminalID) or "N/A")) self:T(self.lid..string.format("Element parking %s at spot %s", Element.name, Element.parking and tostring(Element.parking.TerminalID) or "N/A"))
-- Set element status. -- Set element status.
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.PARKING) self:_UpdateStatus(Element, OPSGROUP.ElementStatus.PARKING)
if Spot then
self:_SetElementParkingAt(Element, Spot)
end
if self:IsTakeoffCold() then if self:IsTakeoffCold() then
-- Wait for engine startup event. -- Wait for engine startup event.
elseif self:IsTakeoffHot() then elseif self:IsTakeoffHot() then
@ -1660,11 +1661,16 @@ end
-- @param #string Event Event. -- @param #string Event Event.
-- @param #string To To state. -- @param #string To To state.
function FLIGHTGROUP:onafterParking(From, Event, To) function FLIGHTGROUP:onafterParking(From, Event, To)
self:T(self.lid..string.format("Flight is parking"))
-- Get closest airbase
local airbase=self:GetClosestAirbase() --self.group:GetCoordinate():GetClosestAirbase() local airbase=self:GetClosestAirbase() --self.group:GetCoordinate():GetClosestAirbase()
local airbasename=airbase:GetName() or "unknown" local airbasename=airbase:GetName() or "unknown"
-- Debug info
self:T(self.lid..string.format("Flight is parking at airbase %s", airbasename))
-- Set current airbase.
self.currbase=airbase
-- Parking time stamp. -- Parking time stamp.
self.Tparking=timer.getAbsTime() self.Tparking=timer.getAbsTime()

View File

@ -256,8 +256,11 @@ function LEGION:AddMission(Mission)
-- Add ops transport to transport Legions. -- Add ops transport to transport Legions.
if Mission.opstransport then if Mission.opstransport then
local PickupZone=self.spawnzone
local DeployZone=Mission.opstransport.tzcDefault.DeployZone
-- Add a new TZC: from pickup here to the deploy zone. -- Add a new TZC: from pickup here to the deploy zone.
local tzc=Mission.opstransport:AddTransportZoneCombo(self.spawnzone, Mission.opstransport.tzcDefault.DeployZone) 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. --TODO: Depending on "from where to where" the assets need to transported, we need to set ZONE_AIRBASE etc.
@ -601,6 +604,17 @@ function LEGION:onafterMissionRequest(From, Event, To, Mission)
-- 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.
Mission.requestID[self.alias]=self.queueid Mission.requestID[self.alias]=self.queueid
-- Get request.
local request=self:GetRequestByID(self.queueid)
if request then
if self.isShip then
self:T(self.lid.."FF request late activated")
request.lateActivation=true
end
end
end end
end end
@ -653,7 +667,6 @@ 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[self.alias]=self.queueid OpsTransport.requestID[self.alias]=self.queueid
end end
end end
@ -1571,7 +1584,7 @@ function LEGION:RecruitAssets(Mission)
MissionType=Mission.alert5MissionType MissionType=Mission.alert5MissionType
end end
Npayloads[cohort.aircrafttype]=self:IsAirwing() and self:CountPayloadsInStock(MissionType, cohort.aircrafttype, Mission.payloads) or 999 Npayloads[cohort.aircrafttype]=self:IsAirwing() and self:CountPayloadsInStock(MissionType, cohort.aircrafttype, Mission.payloads) or 999
self:I(self.lid..string.format("Got N=%d payloads for mission type=%s and unit type=%s", Npayloads[cohort.aircrafttype], MissionType, cohort.aircrafttype)) self:T2(self.lid..string.format("Got N=%d payloads for mission type=%s and unit type=%s", Npayloads[cohort.aircrafttype], MissionType, cohort.aircrafttype))
end end
end end
@ -1818,6 +1831,9 @@ function LEGION:RecruitAssetsForTransport(Transport)
weightGroup=weight weightGroup=weight
end end
end end
else
-- No cargo groups!
return false
end end
@ -1829,7 +1845,7 @@ function LEGION:RecruitAssetsForTransport(Transport)
local cohort=_cohort --Ops.Cohort#COHORT local cohort=_cohort --Ops.Cohort#COHORT
if Npayloads[cohort.aircrafttype]==nil then if Npayloads[cohort.aircrafttype]==nil then
Npayloads[cohort.aircrafttype]=self:IsAirwing() and self:CountPayloadsInStock(AUFTRAG.Type.OPSTRANSPORT, cohort.aircrafttype) or 999 Npayloads[cohort.aircrafttype]=self:IsAirwing() and self:CountPayloadsInStock(AUFTRAG.Type.OPSTRANSPORT, cohort.aircrafttype) or 999
self:I(self.lid..string.format("Got N=%d payloads for mission type=%s and unit type=%s", Npayloads[cohort.aircrafttype], AUFTRAG.Type.OPSTRANSPORT, cohort.aircrafttype)) self:T2(self.lid..string.format("Got N=%d payloads for mission type=%s and unit type=%s", Npayloads[cohort.aircrafttype], AUFTRAG.Type.OPSTRANSPORT, cohort.aircrafttype))
end end
end end
@ -1858,7 +1874,7 @@ function LEGION:RecruitAssetsForTransport(Transport)
end end
-- Sort asset list. Best ones come first. -- Sort asset list. Best ones come first.
self:_OptimizeAssetSelectionForTransport(Assets, Transport, false) self:_OptimizeAssetSelectionForTransport(Assets, Transport)
-- If airwing, get the best payload available. -- If airwing, get the best payload available.
if self:IsAirwing() then if self:IsAirwing() then
@ -2019,7 +2035,8 @@ function LEGION:CalculateAssetTransportScore(asset, Transport)
-- Reduce score for legions that are futher away. -- Reduce score for legions that are futher away.
score=score-distance score=score-distance
--TODO: Check cargo bay capacity. -- Add 1 score point for each 10 kg of cargo bay.
score=score+UTILS.Round(asset.cargobaymax/10, 0)
--TODO: Check ALERT 5 for Transports. --TODO: Check ALERT 5 for Transports.
if asset.spawned then if asset.spawned then

View File

@ -467,12 +467,12 @@ OPSGROUP.version="0.7.5"
-- TODO: Invisible/immortal. -- TODO: Invisible/immortal.
-- TODO: F10 menu. -- TODO: F10 menu.
-- TODO: Add pseudo function. -- TODO: Add pseudo function.
-- TODO: Options EPLRS
-- TODO: Afterburner restrict -- TODO: Afterburner restrict
-- TODO: What more options? -- TODO: What more options?
-- TODO: Damage? -- TODO: Damage?
-- TODO: Shot events? -- TODO: Shot events?
-- TODO: Marks to add waypoints/tasks on-the-fly. -- TODO: Marks to add waypoints/tasks on-the-fly.
-- DONE: Options EPLRS
-- DONE: A lot. -- DONE: A lot.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -3344,8 +3344,9 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
-- Target -- Target
local target=Task.dcstask.params.target --Ops.Target#TARGET local target=Task.dcstask.params.target --Ops.Target#TARGET
Task.dcstask.params.lastindex=1 self.lastindex=1
-- Target object and zone.
local object=target.targets[1] --Ops.Target#TARGET.Object local object=target.targets[1] --Ops.Target#TARGET.Object
local zone=object.Object --Core.Zone#ZONE local zone=object.Object --Core.Zone#ZONE
@ -4495,9 +4496,10 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint)
-- SPECIAL TASK: Recon Mission -- SPECIAL TASK: Recon Mission
--- ---
-- TARGET.
local target=task.dcstask.params.target --Ops.Target#TARGET local target=task.dcstask.params.target --Ops.Target#TARGET
local n=task.dcstask.params.lastindex+1 local n=self.lastindex+1
if n<=#target.targets then if n<=#target.targets then
@ -4528,7 +4530,7 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint)
wp.missionUID=mission and mission.auftragsnummer or nil wp.missionUID=mission and mission.auftragsnummer or nil
-- Increase counter. -- Increase counter.
task.dcstask.params.lastindex=task.dcstask.params.lastindex+1 self.lastindex=self.lastindex+1
else else
@ -4599,7 +4601,7 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint)
-- Passing mission waypoint? -- Passing mission waypoint?
if Waypoint.missionUID then if Waypoint.missionUID then
self:T(self.lid.."FF passing mission waypoint") self:T2(self.lid..string.format("Passing mission waypoint"))
end end
-- Check if all tasks/mission are done? -- Check if all tasks/mission are done?
@ -6636,24 +6638,17 @@ function OPSGROUP:onafterPickup(From, Event, To)
-- Flight Group -- Flight Group
--- ---
-- Activate uncontrolled group.
if self:IsParking() and self:IsUncontrolled() then
self:StartUncontrolled()
end
if airbasePickup then if airbasePickup then
--- ---
-- Pickup at airbase -- Pickup at airbase
--- ---
-- Current airbase.
local airbaseCurrent=self.currbase
if airbaseCurrent then
-- Activate uncontrolled group.
if self:IsParking() and self:IsUncontrolled() then
self:StartUncontrolled()
end
end
-- Order group to land at an airbase. -- Order group to land at an airbase.
self:__LandAtAirbase(-0.1, airbasePickup) self:__LandAtAirbase(-0.1, airbasePickup)
@ -6662,11 +6657,6 @@ function OPSGROUP:onafterPickup(From, Event, To)
--- ---
-- Helo can also land in a zone (NOTE: currently VTOL cannot!) -- Helo can also land in a zone (NOTE: currently VTOL cannot!)
--- ---
-- Activate uncontrolled group.
if self:IsParking() and self:IsUncontrolled() then
self:StartUncontrolled(0.5)
end
-- If this is a helo and no ZONE_AIRBASE was given, we make the helo land in the pickup zone. -- If this is a helo and no ZONE_AIRBASE was given, we make the helo land in the pickup zone.
local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate, nil, self:GetWaypointCurrent().uid, UTILS.MetersToFeet(self.altitudeCruise), false) ; waypoint.detour=1 local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate, nil, self:GetWaypointCurrent().uid, UTILS.MetersToFeet(self.altitudeCruise), false) ; waypoint.detour=1
@ -7004,22 +6994,16 @@ function OPSGROUP:onafterTransport(From, Event, To)
-- Add waypoint. -- Add waypoint.
if self:IsFlightgroup() then if self:IsFlightgroup() then
-- Activate uncontrolled group.
if self:IsParking() and self:IsUncontrolled() then
self:StartUncontrolled()
end
if airbaseDeploy then if airbaseDeploy then
--- ---
-- Deploy at airbase -- Deploy at airbase
--- ---
local airbaseCurrent=self.currbase
if airbaseCurrent then
-- Activate uncontrolled group.
if self:IsParking() and self:IsUncontrolled() then
self:StartUncontrolled()
end
end
-- Order group to land at an airbase. -- Order group to land at an airbase.
self:__LandAtAirbase(-0.1, airbaseDeploy) self:__LandAtAirbase(-0.1, airbaseDeploy)

View File

@ -53,6 +53,8 @@
-- @field #table assets Warehouse assets assigned for this transport. -- @field #table assets Warehouse assets assigned for this transport.
-- @field #table legions Assigned legions. -- @field #table legions Assigned legions.
-- @field #table statusLegion Transport status of all assigned LEGIONs. -- @field #table statusLegion Transport status of all assigned LEGIONs.
-- @field #string statusCommander Staus of the COMMANDER.
-- @field Ops.Commander#COMMANDER commander Commander of the transport.
-- @field #table requestID The ID of the queued warehouse request. Necessary to cancel the request if the transport was cancelled before the request is processed. -- @field #table requestID The ID of the queued warehouse request. Necessary to cancel the request if the transport was cancelled before the request is processed.
-- --
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
@ -133,6 +135,9 @@ OPSTRANSPORT = {
-- @field #string SCHEDULED Transport is scheduled in the cargo queue. -- @field #string SCHEDULED Transport is scheduled in the cargo queue.
-- @field #string EXECUTING Transport is being executed. -- @field #string EXECUTING Transport is being executed.
-- @field #string DELIVERED Transport was delivered. -- @field #string DELIVERED Transport was delivered.
-- @field #string CANCELLED Transport was cancelled.
-- @field #string SUCCESS Transport was a success.
-- @field #string FAILED Transport failed.
OPSTRANSPORT.Status={ OPSTRANSPORT.Status={
PLANNED="planned", PLANNED="planned",
QUEUED="queued", QUEUED="queued",
@ -140,6 +145,9 @@ OPSTRANSPORT.Status={
SCHEDULED="scheduled", SCHEDULED="scheduled",
EXECUTING="executing", EXECUTING="executing",
DELIVERED="delivered", DELIVERED="delivered",
CANCELLED="cancelled",
SUCCESS="success",
FAILED="failed",
} }
--- Pickup and deploy set. --- Pickup and deploy set.
@ -177,14 +185,14 @@ _OPSTRANSPORTID=0
--- Army Group version. --- Army Group version.
-- @field #string version -- @field #string version
OPSTRANSPORT.version="0.4.2" OPSTRANSPORT.version="0.5.0"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Allow multiple pickup/depoly zones.
-- TODO: Stop/abort transport. -- TODO: Stop/abort transport.
-- DONE: Allow multiple pickup/depoly zones.
-- DONE: Add start conditions. -- DONE: Add start conditions.
-- DONE: Check carrier(s) dead. -- DONE: Check carrier(s) dead.
@ -459,20 +467,6 @@ function OPSTRANSPORT:AddCargoGroups(GroupSet, TransportZoneCombo)
-- Call iteravely for each group. -- Call iteravely for each group.
self:AddCargoGroups(group, TransportZoneCombo) self:AddCargoGroups(group, TransportZoneCombo)
--[[
local cargo=self:_CreateCargoGroupData(group)
if cargo then
-- Add to main table.
table.insert(self.cargos, cargo)
self.Ncargo=self.Ncargo+1
-- Add to TZC table.
table.insert(TransportZoneCombo.Cargos, cargo)
TransportZoneCombo.Ncargo=TransportZoneCombo.Ncargo+1
end
]]
end end
end end

View File

@ -110,14 +110,16 @@ function PLATOON:AddWeaponRange(RangeMin, RangeMax, BitType)
self.weaponData[tostring(weapon.BitType)]=weapon self.weaponData[tostring(weapon.BitType)]=weapon
-- Debug info. -- Debug info.
env.info(string.format("FF Adding weapon data: Bit=%s, Rmin=%d m, Rmax=%d m", tostring(weapon.BitType), weapon.RangeMin, weapon.RangeMax)) self:T(self.lid..string.format("Adding weapon data: Bit=%s, Rmin=%d m, Rmax=%d m", tostring(weapon.BitType), weapon.RangeMin, weapon.RangeMax))
local text="Weapon data:" if self.verbose>=2 then
for _,_weapondata in pairs(self.weaponData) do local text="Weapon data:"
local weapondata=_weapondata for _,_weapondata in pairs(self.weaponData) do
text=text..string.format("\n- Bit=%s, Rmin=%d m, Rmax=%d m", tostring(weapondata.BitType), weapondata.RangeMin, weapondata.RangeMax) local weapondata=_weapondata
text=text..string.format("\n- Bit=%s, Rmin=%d m, Rmax=%d m", tostring(weapondata.BitType), weapondata.RangeMin, weapondata.RangeMax)
end
self:I(self.lid..text)
end end
self:I(self.lid..text)
return self return self
end end