Warehouse v0.2.6

Several fixes including BoundZone.
Warehouse ID is not number not string.
Updated Documentation.
Fixed bug that invalid requests are not recognized.
This commit is contained in:
funkyfranky 2018-08-26 17:29:31 +02:00
parent b8a83aadb2
commit 64355fb772
3 changed files with 310 additions and 195 deletions

View File

@ -1,4 +1,4 @@
--- **Functional** - (R2.4) - Manages assets of an airbase and transportation to other airbases upon request. --- **Functional** - (R2.5) - Simulation of logistics.
-- --
-- --
-- Features: -- Features:
@ -10,6 +10,8 @@
-- --
-- # QUICK START GUIDE -- # QUICK START GUIDE
-- --
-- **WIP**
--
-- === -- ===
-- --
-- ### Authors: **funkyfranky** -- ### Authors: **funkyfranky**
@ -23,7 +25,7 @@
-- @field #boolean Debug If true, send debug messages to all. -- @field #boolean Debug If true, send debug messages to all.
-- @field #boolean Report If true, send status messages to coalition. -- @field #boolean Report If true, send status messages to coalition.
-- @field Wrapper.Static#STATIC warehouse The phyical warehouse structure. -- @field Wrapper.Static#STATIC warehouse The phyical warehouse structure.
-- @field DCS#coalition.side coalition Coalition ID the warehouse belongs to. -- @field DCS#coalition.side coalition Coalition side the warehouse belongs to.
-- @field DCS#country.id country Country ID the warehouse belongs to. -- @field DCS#country.id country Country ID the warehouse belongs to.
-- @field #string alias Alias of the warehouse. Name its called when sending messages. -- @field #string alias Alias of the warehouse. Name its called when sending messages.
-- @field Core.Zone#ZONE zone Zone around the warehouse. If this zone is captured, the warehouse and all its assets goes to the capturing coaliton. -- @field Core.Zone#ZONE zone Zone around the warehouse. If this zone is captured, the warehouse and all its assets goes to the capturing coaliton.
@ -63,20 +65,50 @@
-- --
-- ![Banner Image](..\Presentations\WAREHOUSE\Warehouse_Main.JPG) -- ![Banner Image](..\Presentations\WAREHOUSE\Warehouse_Main.JPG)
-- --
-- # What is a warehouse? -- # The Warehouse Concept
--
-- The MOOSE warehouse adds a new logistic component to the DCS World. *Assets*, i.e. ground, airborne and naval units, can be transferred from one place
-- to another in a realistic and highly automatic fashion. In contrast to a "DCS warehouse" these assets have a physical representation in game. In particular,
-- this means they can be destroyed during the transport, add more life to the DCS world etc.
--
-- Or, in other words, on a scale between 1 and 10, how important do you reckon it is to have the right assets at the right place in a conflict?
--
-- The warehouse adresses exactly this "problem" by simulating it in a realistic way while at the same time adding more life and dynamics to the DCS World.
--
-- This comes along with some additional interesting stategic aspects since capturing/defending and destroying/protecting an enemy or your
-- own warehous becomes of critical importance for the development of a conflict.
--
-- In essence, creating an efficient network of warehouses is vital for the success of a battle or even the whole war. Likewise, of course, cutting off the enemy
-- of important supply lines by capturing or destroying warehouses or their associated infrastructure is equally important.
--
-- ## What is a warehouse?
-- A warehouse is an abstract object represented by a physical (static) building that can hold virtual assets in stock. -- A warehouse is an abstract object represented by a physical (static) building that can hold virtual assets in stock.
-- It can but it must not be associated with a particular airbase. The associated airbase can be an airdrome, a Helipad/FARP or a ship. -- It can but it must not be associated with a particular airbase. The associated airbase can be an airdrome, a Helipad/FARP or a ship.
-- --
-- If another another warehouse requests assets, the corresponding troops are spawned at the warehouse and being transported to the requestor or go their -- If another warehouse requests assets, the corresponding troops are spawned at the warehouse and being transported to the requestor or go their
-- by themselfs. Once arrived at the requesting warehouse, the assets go into the stock of the requestor and can be reactivated when necessary. -- by themselfs. Once arrived at the requesting warehouse, the assets go into the stock of the requestor and can be activated/deployed when necessary.
-- --
-- ## What assets can be stored? -- ## What assets can be stored?
-- Any kind of ground or airborn asset can be stored. Ships not supported at the moment due to the fact that airbases are bound to airbases which are -- Any kind of ground or airborne asset can be stored. Ships not supported at the moment due to the fact that airbases are bound to airbases which are
-- normally not located near the sea. -- normally not located near the sea.
-- --
-- # Creating a new warehouse -- ## What means of transportation are available?
-- Firstly, all mobile assets can be send from warehouse to another on their own.
-- --
-- A MOOSE warehouse must be represented in game by a phyical static object. For example, the mission editor already has warehouse as static object available. -- * Ground vehicles will use the road infrastructure
-- * Airborne units are get a flightplan from the airbase the sending warehouse to the airbase of the receiving warehouse. This already implies that for airborne
-- assets both warehouses need an airbase. If either one of the warehouses does not have an associated airbase, transportation of airborne assest is not possible.
-- * Naval units can be exchanged between warehouses which posses a port/habour. Also shipping lanes must be specified manually but the user since DCS does not provide these.
-- * Trains use the available railroad infrastructure and both warehouses must have a connection to the railroad. Unfortunately, however, trains are not yet implemented to
-- a reasonable degree in DCS at the moment and hence cannot be used yet.
--
-- Furthermore, ground assets can be transferred between warehouses by transport units. These are APCs, helicopters and airplanes. The transportation process is modelled
-- in a realistic way by using the corresponding cargo dispatcher classes, i.e. @{AI.AI_Cargo_Dispatcher_APC#AI_DISPATCHER_APC},
-- @{AI.AI_Cargo_Dispatcher_Helicopter#AI_DISPATCHER_HELICOPTER} and @{AI.AI_Cargo_Dispatcher_Airplane#AI_DISPATCHER_AIRPLANE}.
--
-- # Creating a Warehouse
--
-- A MOOSE warehouse must be represented in game by a phyical *static* object. For example, the mission editor already has warehouse as static object available.
-- This would be a good first choice but any static object will do. -- This would be a good first choice but any static object will do.
-- --
-- The positioning of the warehouse static object is very important for a couple of reasons. Firtly, a warehouse needs a good infrastructure so that spawned assets -- The positioning of the warehouse static object is very important for a couple of reasons. Firtly, a warehouse needs a good infrastructure so that spawned assets
@ -93,7 +125,7 @@
-- --
-- # Adding Assets -- # Adding Assets
-- --
-- Assets can be added to the warehouse stock by using the @{#WAREHOUSE.AddAsset}(*group*, *ngroups*) function. The parameter *group* has to be a MOOSE @{Wrapper.Group#GROUP}. -- Assets can be added to the warehouse stock by using the @{#WAREHOUSE.AddAsset}(*group*, *ngroups*, *forceattribute*) function. The parameter *group* has to be a MOOSE @{Wrapper.Group#GROUP}.
-- The parameter *ngroups* specifies how many clones of this group are added to the stock. -- The parameter *ngroups* specifies how many clones of this group are added to the stock.
-- --
-- Note that the group should be a late activated template group, which was defined in the mission editor. -- Note that the group should be a late activated template group, which was defined in the mission editor.
@ -103,7 +135,10 @@
-- --
-- This will add five infantry groups to the warehouse stock. -- This will add five infantry groups to the warehouse stock.
-- --
-- Note that you can also add assets with a delay by using the @{#WAREHOUSE.__AddAsset}(*delay*, *group*, *ngroups*), where *delay* is the delay in seconds before the asset is added. -- Note that you can also add assets with a delay by using the @{#WAREHOUSE.__AddAsset}(*delay*, *group*, *ngroups*, *foceattribute*), where *delay* is the delay in seconds before the asset is added.
--
-- By default, the generalized attribute of the asset is determined automatically from the DCS descriptor attributes. However, this might not always result in the desired outcome.
-- Therefore, it is possible, to force a generalized attribute for the asset with the third optional parameter *forceattribute*, which is of type @{#WAREHOUSE.Attribute}.
-- --
-- # Requesting Assets -- # Requesting Assets
-- --
@ -190,17 +225,17 @@
-- The variable *groupset* is a @{Core.Set#SET_GOUP} object and holds all asset groups from the request. The code above shows, how the mission designer can access the groups -- The variable *groupset* is a @{Core.Set#SET_GOUP} object and holds all asset groups from the request. The code above shows, how the mission designer can access the groups
-- for further tasking. Here, the groups are only smoked but, of course, you can use them for whatever task you imagine. -- for further tasking. Here, the groups are only smoked but, of course, you can use them for whatever task you imagine.
-- --
-- Note that airborn groups are spawned in uncontrolled state and need to be activated first before they can start their assigned mission. -- Note that airborne groups are spawned in uncontrolled state and need to be activated first before they can start their assigned mission.
-- --
-- # Strategic Tasks -- # Strategic Considerations
-- --
-- Due to the fact that a warehouse holds (or can hold) a lot of valuable assets, it makes a juicy task for enemy attacks. -- Due to the fact that a warehouse holds (or can hold) a lot of valuable assets, it makes a (potentially) juicy target for enemy attacks.
-- There are several interesting situations, which can occurr. -- There are several interesting situations, which can occurr.
-- --
-- ## Capturing a Warehouse' Airbase -- ## Capturing a Warehouse' Airbase
-- --
-- If a warehouse has an associated airbase, it can be captured by the enemy. In this case, the warehouse looses it ability so employ all airborn assets and is also cut-off -- If a warehouse has an associated airbase, it can be captured by the enemy. In this case, the warehouse looses it ability so employ all airborne assets and is also cut-off
-- from supply by airborn units. -- from supply by airborne units.
-- --
-- Technically, the capturing of the airbase is triggered by the DCS S_EVENT_CAPTURE_BASE event. So the capturing takes place when only enemy ground units are in the -- Technically, the capturing of the airbase is triggered by the DCS S_EVENT_CAPTURE_BASE event. So the capturing takes place when only enemy ground units are in the
-- airbase zone whilst no ground units of the present airbase owner are in that zone. -- airbase zone whilst no ground units of the present airbase owner are in that zone.
@ -213,7 +248,7 @@
-- --
-- ## Capturing the Warehouse -- ## Capturing the Warehouse
-- --
-- A warehouse can also be captured by the enemy coaltion. If enemy groups enter the warehouse zone the event **Attacked** is triggered which can be captured by the -- A warehouse can also be captured by the enemy coalition. If enemy ground troops enter the warehouse zone the event **Attacked** is triggered which can be captured by the
-- @{#WAREHOUSE.OnAfterAttacked} event. -- @{#WAREHOUSE.OnAfterAttacked} event.
-- --
-- If a warehouse is attacked it will spawn all its ground assets in the spawn zone which can than be used to defend the warehouse zone. -- If a warehouse is attacked it will spawn all its ground assets in the spawn zone which can than be used to defend the warehouse zone.
@ -230,12 +265,13 @@
-- gone as well. So a warehouse should be properly defended. -- gone as well. So a warehouse should be properly defended.
-- --
-- Upon destruction of the warehouse, the event **Destroyed** is triggered, which can be captured by the @{#WAREHOUSE.OnAfterDestroyed} function. -- Upon destruction of the warehouse, the event **Destroyed** is triggered, which can be captured by the @{#WAREHOUSE.OnAfterDestroyed} function.
-- So the mission designer can invene at this point and for example choose to spawn all or paricular types of assets before the warehouse is gone for good. -- So the mission designer can intervene at this point and for example choose to spawn all or paricular types of assets before the warehouse is gone for good.
-- --
-- === -- ===
-- --
-- # Examples -- # Examples
-- --
-- **WIP**
-- --
-- --
-- @field #WAREHOUSE -- @field #WAREHOUSE
@ -313,7 +349,6 @@ WAREHOUSE = {
-- @field #string ATTRIBUTE Generalized attribute @{#WAREHOUSE.Attribute}. -- @field #string ATTRIBUTE Generalized attribute @{#WAREHOUSE.Attribute}.
-- @field #string CATEGORY Asset category of type DCS#Group.Category, i.e. GROUND, AIRPLANE, HELICOPTER, SHIP, TRAIN. -- @field #string CATEGORY Asset category of type DCS#Group.Category, i.e. GROUND, AIRPLANE, HELICOPTER, SHIP, TRAIN.
WAREHOUSE.Descriptor = { WAREHOUSE.Descriptor = {
--ID="id",
TEMPLATENAME="templatename", TEMPLATENAME="templatename",
UNITTYPE="unittype", UNITTYPE="unittype",
ATTRIBUTE="attribute", ATTRIBUTE="attribute",
@ -382,15 +417,17 @@ WAREHOUSE.db = {
--- Warehouse class version. --- Warehouse class version.
-- @field #string version -- @field #string version
WAREHOUSE.version="0.2.6w" WAREHOUSE.version="0.2.6"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Warehouse todo list. -- TODO: Warehouse todo list.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Add transport units from dispatchers back to warehouse stock once they completed their mission.
-- TODO: Add harbours and ports.
-- TODO: Add shipping lanes between warehouses.
-- TODO: Set ROE for spawned groups. -- TODO: Set ROE for spawned groups.
-- TODO: Add possibility to add active groups. Need to create a pseudo template before destroy. -- TODO: Add possibility to add active groups. Need to create a pseudo template before destroy.
-- DONE: If warehouse is destoyed, all asssets are gone.
-- TODO: Write documentation. -- TODO: Write documentation.
-- TODO: Handle the case when units of a group die during the transfer. Adjust template?! See Grouping in SPAWN. -- TODO: Handle the case when units of a group die during the transfer. Adjust template?! See Grouping in SPAWN.
-- TODO: Handle cases with immobile units. -- TODO: Handle cases with immobile units.
@ -398,6 +435,10 @@ WAREHOUSE.version="0.2.6w"
-- TODO: Handle cases for aircraft carriers and other ships. Place warehouse on carrier possible? On others probably not - exclude them? -- TODO: Handle cases for aircraft carriers and other ships. Place warehouse on carrier possible? On others probably not - exclude them?
-- TODO: Add general message function for sending to coaliton or debug. -- TODO: Add general message function for sending to coaliton or debug.
-- TODO: Fine tune event handlers. -- TODO: Fine tune event handlers.
-- TODO: Add save/load capability of warehouse <==> percistance after mission restart.
-- TODO: Improve generalized attributes.
-- TODO: Add a time stamp when an asset is added to the stock and for requests
-- DONE: If warehouse is destoyed, all asssets are gone.
-- DONE: Add event handlers. -- DONE: Add event handlers.
-- DONE: Add AI_CARGO_AIRPLANE -- DONE: Add AI_CARGO_AIRPLANE
-- DONE: Add AI_CARGO_APC -- DONE: Add AI_CARGO_APC
@ -444,7 +485,7 @@ function WAREHOUSE:New(warehouse, alias)
-- Set some variables. -- Set some variables.
self.warehouse=warehouse self.warehouse=warehouse
self.uid=warehouse:GetID() self.uid=tonumber(warehouse:GetID())
self.coalition=warehouse:GetCoalition() self.coalition=warehouse:GetCoalition()
self.country=warehouse:GetCountry() self.country=warehouse:GetCountry()
self.coordinate=warehouse:GetCoordinate() self.coordinate=warehouse:GetCoordinate()
@ -465,6 +506,7 @@ function WAREHOUSE:New(warehouse, alias)
self:SetStartState("Stopped") self:SetStartState("Stopped")
-- Add FSM transitions. -- Add FSM transitions.
-- From State --> Event --> To State
self:AddTransition("Stopped", "Load", "Stopped") -- TODO Load the warehouse state. No sure if it should be in stopped state. self:AddTransition("Stopped", "Load", "Stopped") -- TODO Load the warehouse state. No sure if it should be in stopped state.
self:AddTransition("Stopped", "Start", "Running") -- Start the warehouse. self:AddTransition("Stopped", "Start", "Running") -- Start the warehouse.
self:AddTransition("*", "Status", "*") -- Status update. self:AddTransition("*", "Status", "*") -- Status update.
@ -488,8 +530,9 @@ function WAREHOUSE:New(warehouse, alias)
self:AddTransition("*", "AirbaseRecaptured", "*") -- TODO Airbase was re-captured from other coalition. self:AddTransition("*", "AirbaseRecaptured", "*") -- TODO Airbase was re-captured from other coalition.
self:AddTransition("*", "Destroyed", "*") -- TODO Warehouse was destoryed. All assets in stock are gone and warehouse is stopped. self:AddTransition("*", "Destroyed", "*") -- TODO Warehouse was destoryed. All assets in stock are gone and warehouse is stopped.
------------------------
-- Pseudo Functions --- Pseudo Functions ---
------------------------
--- Triggers the FSM event "Start". Starts the warehouse. Initializes parameters and starts event handlers. --- Triggers the FSM event "Start". Starts the warehouse. Initializes parameters and starts event handlers.
-- @function [parent=#WAREHOUSE] Start -- @function [parent=#WAREHOUSE] Start
@ -528,7 +571,6 @@ function WAREHOUSE:New(warehouse, alias)
-- @param #number delay Delay in seconds. -- @param #number delay Delay in seconds.
--- Triggers the FSM event "Status". Queue is updated and requests are executed. --- Triggers the FSM event "Status". Queue is updated and requests are executed.
-- @function [parent=#WAREHOUSE] Status -- @function [parent=#WAREHOUSE] Status
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
@ -544,6 +586,7 @@ function WAREHOUSE:New(warehouse, alias)
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param Wrapper.Group#GROUP group Group to be added as new asset. -- @param Wrapper.Group#GROUP group Group to be added as new asset.
-- @param #number ngroups Number of groups to add to the warehouse stock. Default is 1. -- @param #number ngroups Number of groups to add to the warehouse stock. Default is 1.
-- @param #WAREHOUSE.Attribute forceattribute (Optional) Explicitly force a generalized attribute for the asset. This has to be an @{#WAREHOUSE.Attribute}.
--- Trigger the FSM event "AddAsset" with a delay. Add an airplane group to the warehouse stock. --- Trigger the FSM event "AddAsset" with a delay. Add an airplane group to the warehouse stock.
-- @function [parent=#WAREHOUSE] __AddAsset -- @function [parent=#WAREHOUSE] __AddAsset
@ -551,6 +594,7 @@ function WAREHOUSE:New(warehouse, alias)
-- @param #number delay Delay in seconds. -- @param #number delay Delay in seconds.
-- @param Wrapper.Group#GROUP group Group to be added as new asset. -- @param Wrapper.Group#GROUP group Group to be added as new asset.
-- @param #number ngroups Number of groups to add to the warehouse stock. Default is 1. -- @param #number ngroups Number of groups to add to the warehouse stock. Default is 1.
-- @param #WAREHOUSE.Attribute forceattribute (Optional) Explicitly force a generalized attribute for the asset. This has to be an @{#WAREHOUSE.Attribute}.
--- Triggers the FSM event "AddRequest". Add a request to the warehouse queue, which is processed when possible. --- Triggers the FSM event "AddRequest". Add a request to the warehouse queue, which is processed when possible.
@ -811,6 +855,13 @@ function WAREHOUSE:IsAttacked()
return self:is("Attacked") return self:is("Attacked")
end end
--- Check if the warehouse is stopped.
-- @param #WAREHOUSE self
-- @return #boolean If true, the warehouse is stopped.
function WAREHOUSE:IsStopped()
return self:is("Stopped")
end
--- Check if the warehouse has a road connection to another warehouse. Both warehouses need to be started! --- Check if the warehouse has a road connection to another warehouse. Both warehouses need to be started!
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param #WAREHOUSE warehouse The remote warehose to where the connection is checked. -- @param #WAREHOUSE warehouse The remote warehose to where the connection is checked.
@ -881,10 +932,13 @@ function WAREHOUSE:onafterStart(From, Event, To)
self.category=-1 -- The -1 indicates that we dont have an airbase at this warehouse. self.category=-1 -- The -1 indicates that we dont have an airbase at this warehouse.
end end
-- THIS! caused aircraft to be spawned and started but they would never begin their route!
-- VERY strange. Need to test more.
--[[
-- Debug mark warehouse & spawn zone. -- Debug mark warehouse & spawn zone.
self.zone:BoundZone(30, self.country) self.zone:BoundZone(30, self.country)
self.spawnzone:BoundZone(30, self.country) self.spawnzone:BoundZone(30, self.country)
]]
-- Get the closest point on road wrt spawnzone of ground assets. -- Get the closest point on road wrt spawnzone of ground assets.
local _road=self.spawnzone:GetCoordinate():GetClosestPointToRoad() local _road=self.spawnzone:GetCoordinate():GetClosestPointToRoad()
@ -932,6 +986,7 @@ function WAREHOUSE:onafterStart(From, Event, To)
-- Start the status monitoring. -- Start the status monitoring.
self:__Status(1) self:__Status(1)
end end
--- On after "Stop" event. Stops the warehouse, unhandles all events. --- On after "Stop" event. Stops the warehouse, unhandles all events.
@ -1035,7 +1090,8 @@ end
-- @param #string To To state. -- @param #string To To state.
-- @param Wrapper.Group#GROUP group Group or template group to be added to the warehouse stock. -- @param Wrapper.Group#GROUP group Group or template group to be added to the warehouse stock.
-- @param #number ngroups Number of groups to add to the warehouse stock. Default is 1. -- @param #number ngroups Number of groups to add to the warehouse stock. Default is 1.
function WAREHOUSE:onafterAddAsset(From, Event, To, group, ngroups) -- @param #WAREHOUSE.Attribute forceattribute (Optional) Explicitly force a generalized attribute for the asset. This has to be an @{#WAREHOUSE.Attribute}.
function WAREHOUSE:onafterAddAsset(From, Event, To, group, ngroups, forceattribute)
-- Set default. -- Set default.
local n=ngroups or 1 local n=ngroups or 1
@ -1070,7 +1126,7 @@ function WAREHOUSE:onafterAddAsset(From, Event, To, group, ngroups)
else else
-- This is a group that is not in the db yet. Add it n times. -- This is a group that is not in the db yet. Add it n times.
local assets=self:_RegisterAsset(group, n) local assets=self:_RegisterAsset(group, n, forceattribute)
-- Add created assets to stock of this warehouse. -- Add created assets to stock of this warehouse.
for _,asset in pairs(assets) do for _,asset in pairs(assets) do
@ -1082,7 +1138,7 @@ function WAREHOUSE:onafterAddAsset(From, Event, To, group, ngroups)
-- TODO: This causes a problem, when a completely new asset is added, i.e. not from a template group. -- TODO: This causes a problem, when a completely new asset is added, i.e. not from a template group.
-- Need to create a "zombie" template group maybe? -- Need to create a "zombie" template group maybe?
if group:IsAlive()==true then if group:IsAlive()==true then
env.info("FF destorying group "..group:GetName()) self:E(self.wid..string.format("Destroying group %s.", group:GetName()))
group:Destroy() group:Destroy()
end end
@ -1117,8 +1173,9 @@ end
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param Wrapper.Group#GROUP group The group that will be added to the warehouse stock. -- @param Wrapper.Group#GROUP group The group that will be added to the warehouse stock.
-- @param #number ngroups Number of groups to be added. -- @param #number ngroups Number of groups to be added.
-- @param #string forceattribute Forced generalized attribute.
-- @return #table A table containing all registered assets. -- @return #table A table containing all registered assets.
function WAREHOUSE:_RegisterAsset(group, ngroups) function WAREHOUSE:_RegisterAsset(group, ngroups, forceattribute)
-- Set default. -- Set default.
local n=ngroups or 1 local n=ngroups or 1
@ -1147,8 +1204,8 @@ function WAREHOUSE:_RegisterAsset(group, ngroups)
local RangeMin=group:GetRange() local RangeMin=group:GetRange()
local smax,sx,sy,sz=_GetObjectSize(DCSdesc) local smax,sx,sy,sz=_GetObjectSize(DCSdesc)
-- Get the generalized attribute. -- Set/get the generalized attribute.
local attribute=self:_GetAttribute(templategroupname) local attribute=forceattribute or self:_GetAttribute(templategroupname)
-- Table for returned assets. -- Table for returned assets.
local assets={} local assets={}
@ -1219,8 +1276,9 @@ end
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @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 boolean aioff If true, AI of ground units are set to off.
-- @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:_SpawnAssetGround(asset, request) function WAREHOUSE:_SpawnAssetGround(asset, request, aioff)
if asset and asset.category==Group.Category.GROUND then if asset and asset.category==Group.Category.GROUND then
@ -1262,8 +1320,13 @@ function WAREHOUSE:_SpawnAssetGround(asset, request)
-- Spawn group. -- Spawn group.
local group=_DATABASE:Spawn(template) --Wrapper.Group#GROUP local group=_DATABASE:Spawn(template) --Wrapper.Group#GROUP
-- Activate group. -- Activate group. Should only be necessary for late activated groups.
group:Activate() --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
@ -1276,23 +1339,27 @@ 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 #table parking Parking data for this asset. -- @param #table parking Parking data for this asset.
-- @param #boolean uncontrolled Spawn aircraft in uncontrolled state.
-- @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(asset, request, parking) function WAREHOUSE:_SpawnAssetAircraft(asset, request, parking, uncontrolled)
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
-- Prepare spawn template. -- Prepare the spawn template.
local template=self:_SpawnAssetPrepareTemplate(asset, request) local template=self:_SpawnAssetPrepareTemplate(asset, request)
-- Set and empty route. -- Set route points.
if request.transporttype==WAREHOUSE.TransportType.SELFPROPELLED then if request.transporttype==WAREHOUSE.TransportType.SELFPROPELLED then
-- Get flight path.
template.route.points=self:_GetFlightplan(asset, self.airbase, request.warehouse.airbase)
--template.route.points[1] = {}
else
template.route.points[1] = {}
end
-- Get flight path if the group goes to another warehouse by itself.
template.route.points=self:_GetFlightplan(asset, self.airbase, request.warehouse.airbase)
else
-- First route point is the warehouse airbase.
template.route.points[1]=self.airbase:GetCoordinate():WaypointAir("BARO", COORDINATE.WaypointType.TakeOffParking, COORDINATE.WaypointAction.FromParkingArea, 0, true, self.airbase, nil, "Spawnpoint")
--[[
-- Link. -- Link.
local spawnpoint=template.route.points[1] local spawnpoint=template.route.points[1]
@ -1300,9 +1367,8 @@ function WAREHOUSE:_SpawnAssetAircraft(asset, request, parking)
spawnpoint.type = COORDINATE.WaypointType.TakeOffParking spawnpoint.type = COORDINATE.WaypointType.TakeOffParking
spawnpoint.action = COORDINATE.WaypointAction.FromParkingArea spawnpoint.action = COORDINATE.WaypointAction.FromParkingArea
-- Get airbase ID and category. --spawnpoint.type = COORDINATE.WaypointType.TakeOffParkingHot
local AirbaseID = self.airbase:GetID() --spawnpoint.action = COORDINATE.WaypointAction.FromParkingAreaHot
local AirbaseCategory = self.category
-- Set airbase ID. -- Set airbase ID.
if AirbaseCategory == Airbase.Category.HELIPAD or AirbaseCategory == Airbase.Category.SHIP then if AirbaseCategory == Airbase.Category.HELIPAD or AirbaseCategory == Airbase.Category.SHIP then
@ -1314,6 +1380,13 @@ function WAREHOUSE:_SpawnAssetAircraft(asset, request, parking)
spawnpoint.linkUnit = nil spawnpoint.linkUnit = nil
spawnpoint.helipadId = nil spawnpoint.helipadId = nil
end end
]]
end
-- Get airbase ID and category.
local AirbaseID = self.airbase:GetID()
local AirbaseCategory = self.category
-- Check enough parking spots. -- Check enough parking spots.
if AirbaseCategory == Airbase.Category.HELIPAD or AirbaseCategory == Airbase.Category.SHIP then if AirbaseCategory == Airbase.Category.HELIPAD or AirbaseCategory == Airbase.Category.SHIP then
@ -1351,7 +1424,7 @@ function WAREHOUSE:_SpawnAssetAircraft(asset, request, parking)
local coord=parking[i].Coordinate --Core.Point#COORDINATE local coord=parking[i].Coordinate --Core.Point#COORDINATE
local terminal=parking[i].TerminalID --#number local terminal=parking[i].TerminalID --#number
coord:MarkToAll(string.format("spawnplace unit %s terminal %d", unit.name, terminal)) coord:MarkToAll(string.format("Spawnplace unit %s terminal %d", unit.name, terminal))
unit.x=coord.x unit.x=coord.x
unit.y=coord.z unit.y=coord.z
@ -1364,27 +1437,26 @@ function WAREHOUSE:_SpawnAssetAircraft(asset, request, parking)
end end
-- Set general spawnpoint position. -- Set general spawnpoint position.
local abc=self.airbase:GetCoordinate() --local abc=self.airbase:GetCoordinate()
spawnpoint.x = template.units[1].x --spawnpoint.x = template.units[1].x
spawnpoint.y = template.units[1].y --spawnpoint.y = template.units[1].y
spawnpoint.alt = template.units[1].alt --spawnpoint.alt = template.units[1].alt
-- And template position. -- And template position.
template.x = template.units[1].x template.x = template.units[1].x
template.y = template.units[1].y template.y = template.units[1].y
-- Uncontrolled spawning. -- Uncontrolled spawning.
template.uncontrolled=true template.uncontrolled=uncontrolled
-- Debug info. -- Debug info.
self:E({airtemplate=template}) self:T2({airtemplate=template})
-- Spawn group. -- Spawn group.
local group=_DATABASE:Spawn(template) --Wrapper.Group#GROUP local group=_DATABASE:Spawn(template) --Wrapper.Group#GROUP
-- Activate group. -- Activate group - should only be necessary for late activated groups.
group:Activate() --group:Activate()
return group return group
end end
@ -1402,6 +1474,7 @@ function WAREHOUSE:_SpawnAssetPrepareTemplate(asset, request)
-- Create an own copy of the template! -- Create an own copy of the template!
local template=UTILS.DeepCopy(asset.template) local template=UTILS.DeepCopy(asset.template)
--local template=asset.template
-- Set unique name. -- Set unique name.
template.name=self:_Alias(asset, request) template.name=self:_Alias(asset, request)
@ -1413,11 +1486,17 @@ function WAREHOUSE:_SpawnAssetPrepareTemplate(asset, request)
-- Nillify the group ID. -- Nillify the group ID.
template.groupId=nil template.groupId=nil
-- For group units, visible needs to be false.
if asset.category==Group.Category.GROUND then
template.visible=false
end
-- No late activation. -- No late activation.
template.lateActivation=false template.lateActivation=false
-- Set and empty route. -- Set and empty route.
template.route = {} template.route = {}
template.route.routeRelativeTOT=true
template.route.points = {} template.route.points = {}
-- Handle units. -- Handle units.
@ -1429,7 +1508,7 @@ function WAREHOUSE:_SpawnAssetPrepareTemplate(asset, request)
-- Nillify the unit ID. -- Nillify the unit ID.
unit.unitId=nil unit.unitId=nil
-- Set unit name. -- Set unit name: <alias>-01, <alias>-02, ...
unit.name=string.format("%s-%02d", template.name , i) unit.name=string.format("%s-%02d", template.name , i)
end end
@ -1606,35 +1685,38 @@ function WAREHOUSE:onafterRequest(From, Event, To, Request)
-- No transport unit requested. Assets go by themselfes. -- No transport unit requested. Assets go by themselfes.
if Request.transporttype==WAREHOUSE.TransportType.SELFPROPELLED then if Request.transporttype==WAREHOUSE.TransportType.SELFPROPELLED then
env.info("FF selfpropelled") self:I(self.wid..string.format("Got selfpropelled request for %d assets.",_spawngroups:Count()))
for _,_spawngroup in pairs(_spawngroups:GetSetObjects()) do for _,_spawngroup in pairs(_spawngroups:GetSetObjects()) do
-- Group intellisense.
local group=_spawngroup --Wrapper.Group#GROUP local group=_spawngroup --Wrapper.Group#GROUP
-- Route cargo to their destination. -- Route cargo to their destination.
if _cargocategory==Group.Category.GROUND then if _cargocategory==Group.Category.GROUND then
env.info("FF route ground "..group:GetName()) self:I(self.wid..string.format("Route ground group %s.", group:GetName()))
-- Random place in the spawn zone of the requesting warehouse. -- Random place in the spawn zone of the requesting warehouse.
local ToCoordinate=Request.warehouse.spawnzone:GetRandomCoordinate() local ToCoordinate=Request.warehouse.spawnzone:GetRandomCoordinate()
ToCoordinate:MarkToAll("Destination") ToCoordinate:MarkToAll(string.format("Destination of group %s", group:GetName()))
-- Route ground. -- Route ground.
self:_RouteGround(group, Request) self:_RouteGround(group, Request)
elseif _cargocategory==Group.Category.AIRPLANE or _cargocategory==Group.Category.HELICOPTER then elseif _cargocategory==Group.Category.AIRPLANE or _cargocategory==Group.Category.HELICOPTER then
env.info("FF route aircraft "..group:GetName()) self:I(self.wid..string.format("Route airborne group %s.", group:GetName()))
-- Route plane the the requesting warehouses airbase. -- Route plane the the requesting warehouses airbase.
-- Actually, the route is already set. We only need to activate the uncontrolled group. -- Actually, the route is already set. We only need to activate the uncontrolled group.
self:_RouteAir(group, Request.airbase) self:_RouteAir(group, Request.airbase)
elseif _cargocategory==Group.Category.SHIP then elseif _cargocategory==Group.Category.SHIP then
self:E("ERROR: self propelled ship not implemented yet!") self:E("ERROR: self propelled ship not implemented yet!")
elseif _cargocategory==Group.Category.TRAIN then elseif _cargocategory==Group.Category.TRAIN then
env.info("FF route train "..group:GetName()) self:I(self.wid..string.format("Route train group %s.", group:GetName()))
-- Route train to the rail connection of the requesting warehouse. -- Route train to the rail connection of the requesting warehouse.
self:_RouteTrain(group, Request.warehouse.rail) self:_RouteTrain(group, Request.warehouse.rail)
@ -1732,7 +1814,7 @@ function WAREHOUSE:onafterRequest(From, Event, To, Request)
local _alias=self:_Alias(_assetitem, Request) local _alias=self:_Alias(_assetitem, Request)
-- Spawn plane at airport in uncontrolled state. -- Spawn plane at airport in uncontrolled state.
local spawngroup=self:_SpawnAssetAircraft(_assetitem, Pending, Parking[_assetitem.uid]) local spawngroup=self:_SpawnAssetAircraft(_assetitem, Pending, Parking[_assetitem.uid], true)
if spawngroup then if spawngroup then
-- Set state of warehouse so we can retrieve it later. -- Set state of warehouse so we can retrieve it later.
@ -1768,8 +1850,8 @@ function WAREHOUSE:onafterRequest(From, Event, To, Request)
-- Spawn with ALIAS here or DCS crashes! -- Spawn with ALIAS here or DCS crashes!
local _alias=self:_Alias(_assetitem, Request) local _alias=self:_Alias(_assetitem, Request)
-- Spawn plane at airport in uncontrolled state. -- Spawn plane at airport in controlled state. They need to fly to the spawn zone.
local spawngroup=self:_SpawnAssetAircraft(_assetitem, Pending, Parking[_assetitem.uid]) local spawngroup=self:_SpawnAssetAircraft(_assetitem, Pending, Parking[_assetitem.uid], false)
if spawngroup then if spawngroup then
-- Set state of warehouse so we can retrieve it later. -- Set state of warehouse so we can retrieve it later.
@ -1795,7 +1877,7 @@ function WAREHOUSE:onafterRequest(From, Event, To, Request)
-- Home zone. -- Home zone.
--CargoTransport:Setairbase(self.airbase) --CargoTransport:Setairbase(self.airbase)
--CargoTransport:SetHomeZone(self.spawnzone) CargoTransport:SetHomeZone(self.spawnzone)
elseif Request.transporttype==WAREHOUSE.TransportType.APC then elseif Request.transporttype==WAREHOUSE.TransportType.APC then
----------- -----------
@ -1861,12 +1943,12 @@ function WAREHOUSE:onafterRequest(From, Event, To, Request)
--- Function called when cargo has arrived and was unloaded. --- Function called when cargo has arrived and was unloaded.
function CargoTransport:OnAfterUnloaded(From, Event, To, Carrier, Cargo) function CargoTransport:OnAfterUnloaded(From, Event, To, Carrier, Cargo)
env.info("FF: OnAfterUnloaded") self:I("FF OnAfterUnloaded:")
self:E({From=From}) self:I({From=From})
self:E({Event=Event}) self:I({Event=Event})
self:E({To=To}) self:I({To=To})
self:E({Carrier=Carrier}) self:I({Carrier=Carrier})
self:E({Cargo=Cargo}) self:I({Cargo=Cargo})
-- Get group obejet. -- Get group obejet.
local group=Cargo:GetObject() --Wrapper.Group#GROUP local group=Cargo:GetObject() --Wrapper.Group#GROUP
@ -1970,16 +2052,22 @@ function WAREHOUSE:_SpawnAssetRequest(Request)
--TODO: spawn only so many groups as there are parking spots. Adjust request and create a new one with the reduced number! --TODO: spawn only so many groups as there are parking spots. Adjust request and create a new one with the reduced number!
-- Spawn air units. -- Spawn air units.
_group=self:_SpawnAssetAircraft(_assetitem, Request, Parking[_assetitem.uid]) _group=self:_SpawnAssetAircraft(_assetitem, Request, Parking[_assetitem.uid], UnControlled)
elseif _assetitem.category==Group.Category.TRAIN then elseif _assetitem.category==Group.Category.TRAIN then
-- Spawn train. -- Spawn train.
if self.rail then if self.rail then
--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!
_group=_spawn:SpawnFromCoordinate(self.rail) --_group=_spawn:SpawnFromCoordinate(self.rail)
end end
self:E(self.wid.."ERROR: Spawning of TRAIN assets not possible yet!")
elseif _assetitem.category==Group.Category.SHIP then
self:E(self.wid.."ERROR: Spawning of SHIP assets not possible yet!")
else
end end
-- Add group to group set and asset list. -- Add group to group set and asset list.
@ -2170,10 +2258,10 @@ end
-- @param #WAREHOUSE.Pendingitem request Pending self request. -- @param #WAREHOUSE.Pendingitem request Pending self request.
function WAREHOUSE:onafterSelfRequest(From, Event, To, groupset, request) function WAREHOUSE:onafterSelfRequest(From, Event, To, groupset, request)
self:E(self.wid..string.format("Assets spawned at warehouse %s after self request!", self.alias)) -- Debug info.
self:I(self.wid..string.format("Assets spawned at warehouse %s after self request!", self.alias))
env.info("FF spawned groupas at self request") -- Debug info.
-- Put assets in new warehouse.
for _,_group in pairs(groupset:GetSetObjects()) do for _,_group in pairs(groupset:GetSetObjects()) do
local group=_group --Wrapper.Group#GROUP local group=_group --Wrapper.Group#GROUP
local text=string.format("Group name = %s, IsAlive=%s.", tostring(group:GetName()), tostring(group:IsAlive())) local text=string.format("Group name = %s, IsAlive=%s.", tostring(group:GetName()), tostring(group:IsAlive()))
@ -2339,9 +2427,6 @@ function WAREHOUSE:_RouteGround(group, request)
local _speed=group:GetSpeedMax()*0.7 local _speed=group:GetSpeedMax()*0.7
-- Create task. -- Create task.
-- DONE: It might be necessary to ALWAYS route the group to the road connection first.
-- At the moment, the random spawn point might give another first road point which could also be a dead end like in Kobuliti(?).
-- TODO: Might be necessary to include the current coordinate as first waypoint?!
-- Waypoints for road-to-road connection. -- Waypoints for road-to-road connection.
local Waypoints, canroad = group:TaskGroundOnRoad(request.warehouse.road, _speed, "Off Road", false, self.road) local Waypoints, canroad = group:TaskGroundOnRoad(request.warehouse.road, _speed, "Off Road", false, self.road)
@ -2371,24 +2456,28 @@ function WAREHOUSE:_RouteGround(group, request)
end end
--- Route the airplane from one airbase another. --- Route the airplane from one airbase another. Activates uncontrolled aircraft and sets ROE/ROT for ferry flights.
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param Wrapper.Group#GROUP Aircraft Airplane group to be routed. -- @param Wrapper.Group#GROUP Aircraft Airplane group to be routed.
function WAREHOUSE:_RouteAir(aircraft) function WAREHOUSE:_RouteAir(aircraft)
if aircraft and aircraft:IsAlive()~=nil then if aircraft and aircraft:IsAlive()~=nil then
-- Start command. -- Debug info.
local StartCommand = {id = 'Start', params = {}} self:T2(self.wid..string.format("RouteAir aircraft group %s alive=%s", aircraft:GetName(), tostring(aircraft:IsAlive())))
aircraft:SetCommand(StartCommand)
-- Give start command to activate uncontrolled aircraft.
aircraft:SetCommand({id='Start', params={}})
-- Debug info.
self:T2(self.wid..string.format("RouteAir aircraft group %s alive=%s (after start command)", aircraft:GetName(), tostring(aircraft:IsAlive())))
-- Set ROE and alaram state. -- Set ROE and alaram state.
aircraft:OptionROEReturnFire() aircraft:OptionROEReturnFire()
aircraft:OptionROTPassiveDefense() aircraft:OptionROTPassiveDefense()
else else
self:E(string.format("ERROR: aircraft %s cannot be routed since it does not exist or is not alive %s!", tostring(Aircraft:GetName()), tostring(Aircraft:IsAlive()))) self:E(string.format("ERROR: aircraft %s cannot be routed since it does not exist or is not alive %s!", tostring(aircraft:GetName()), tostring(aircraft:IsAlive())))
end end
end end
@ -2422,9 +2511,9 @@ end
-- @param Wrapper.Group#GROUP group The group that arrived. -- @param Wrapper.Group#GROUP group The group that arrived.
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
function WAREHOUSE._Arrived(group, warehouse) function WAREHOUSE._Arrived(group, warehouse)
env.info(warehouse.wid..string.format("Group %s arrived", tostring(group:GetName()))) env.info(warehouse.wid..string.format("Group %s arrived at destination.", tostring(group:GetName())))
--Trigger delivered event. --Trigger "Arrived" event.
warehouse:__Arrived(1, group) warehouse:__Arrived(1, group)
end end
@ -2438,7 +2527,7 @@ function WAREHOUSE:_ArrivedSimple(group)
--local self:_GetIDsFromGroup(group) --local self:_GetIDsFromGroup(group)
env.info(self.wid..string.format("Group %s arrived at warehouse ", tostring(group:GetName()))) env.info(self.wid..string.format("Group %s arrived at warehouse ", tostring(group:GetName())))
--Trigger delivered event. --Trigger "Arrived event.
self:__Arrived(1, group) self:__Arrived(1, group)
end end
@ -2484,7 +2573,7 @@ function WAREHOUSE:_OnEventArrived(EventData)
self:__Arrived(dt, group) self:__Arrived(dt, group)
else else
self:E(string.format("Group that arrived did not belong to a warehouse. Warehouse ID=%s, Asset ID=%s, Request ID=%s.", tostring(wid), tostring(aid), tostring(rid))) self:T3(string.format("Group that arrived did not belong to a warehouse. Warehouse ID=%s, Asset ID=%s, Request ID=%s.", tostring(wid), tostring(aid), tostring(rid)))
end end
end end
end end
@ -2495,13 +2584,17 @@ end
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param Core.Event#EVENTDATA EventData Event data. -- @param Core.Event#EVENTDATA EventData Event data.
function WAREHOUSE:_OnEventBirth(EventData) function WAREHOUSE:_OnEventBirth(EventData)
self:T3(self.wid..string.format("Warehouse %s captured event birth!", self.alias)) self:T3(self.wid..string.format("Warehouse %s (id=%s) captured event birth!", self.alias, self.uid))
if EventData and EventData.IniGroup then if EventData and EventData.IniGroup then
local group=EventData.IniGroup local group=EventData.IniGroup
-- env.info(string.format("FF birth of group %s (alive=%s) unit %s", tostring(EventData.IniGroupName), tostring(EventData.IniGroup:IsAlive()), tostring(EventData.IniUnitName)))
-- Note: Remember, group:IsAlive might(?) not return true here.
local wid,aid,rid=self:_GetIDsFromGroup(group) local wid,aid,rid=self:_GetIDsFromGroup(group)
if wid==self.uid then if wid==self.uid then
self:E(self.wid..string.format("Warehouse %s captured event birth of its asset unit %s.", self.alias, EventData.IniUnitName)) self:E(self.wid..string.format("Warehouse %s captured event birth of its asset unit %s.", self.alias, EventData.IniUnitName))
else
--self:T3({wid=wid, uid=self.uid, match=(wid==self.uid), tw=type(wid), tu=type(self.uid)})
end end
end end
end end
@ -2570,7 +2663,7 @@ end
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param Core.Event#EVENTDATA EventData Event data. -- @param Core.Event#EVENTDATA EventData Event data.
function WAREHOUSE:_OnEventCrashOrDead(EventData) function WAREHOUSE:_OnEventCrashOrDead(EventData)
self:E(self.wid..string.format("Warehouse %s captured event dead or crash!",self.alias)) self:T3(self.wid..string.format("Warehouse %s captured event dead or crash!",self.alias))
if EventData and EventData.IniUnit then if EventData and EventData.IniUnit then
@ -2582,6 +2675,15 @@ function WAREHOUSE:_OnEventCrashOrDead(EventData)
end end
end end
-- Check if an asset unit was destroyed.
if EventData and EventData.IniGroup then
local group=EventData.IniGroup
local wid,aid,rid=self:_GetIDsFromGroup(group)
if wid==self.uid then
self:E(self.wid..string.format("Warehouse %s captured event dead or crash of its asset unit %s.", self.alias, EventData.IniUnitName))
end
end
end end
--- Warehouse event handling function. --- Warehouse event handling function.
@ -2778,7 +2880,7 @@ end
-- @param #table queue The queue which is holding the requests to check. -- @param #table queue The queue which is holding the requests to check.
-- @return #boolean If true, request can be executed. If false, something is not right. -- @return #boolean If true, request can be executed. If false, something is not right.
function WAREHOUSE:_CheckRequestConsistancy(queue) function WAREHOUSE:_CheckRequestConsistancy(queue)
env.info("FF checking request consistancy!") self:T3(self.wid..string.format("Number of queued requests = %d", #queue))
-- Requests to delete. -- Requests to delete.
local invalid={} local invalid={}
@ -2786,6 +2888,9 @@ function WAREHOUSE:_CheckRequestConsistancy(queue)
for _,_request in pairs(queue) do for _,_request in pairs(queue) do
local request=_request --#WAREHOUSE.Queueitem local request=_request --#WAREHOUSE.Queueitem
-- Debug info.
self:T2(self.wid..string.format("Checking request = %d.", request.uid))
-- Let's assume everything is fine. -- Let's assume everything is fine.
local valid=true local valid=true
@ -2806,6 +2911,13 @@ function WAREHOUSE:_CheckRequestConsistancy(queue)
valid=false valid=false
end end
-- Is receiving warehouse stopped?
if request.warehouse:IsStopped() then
self:E(self.wid..string.format("ERROR: Incorrect request. Requesting warehouse is stopped!"))
valid=false
end
-- Asset is air, ground etc.
local asset_air=false local asset_air=false
local asset_plane=false local asset_plane=false
local asset_helo=false local asset_helo=false
@ -2830,7 +2942,7 @@ function WAREHOUSE:_CheckRequestConsistancy(queue)
-- Only one train due to finding spawn placen on rail! -- Only one train due to finding spawn placen on rail!
--nAsset=1 --nAsset=1
else else
self:E("ERROR: incorrect request. Asset Descriptor missmatch! Has to be Group.Cagetory.AIRPLANE, ...") self:E("ERROR: Incorrect request. Asset Descriptor missmatch! Has to be Group.Cagetory.AIRPLANE, ...")
valid=false valid=false
end end
@ -2851,7 +2963,7 @@ function WAREHOUSE:_CheckRequestConsistancy(queue)
elseif request.assetdescval==WAREHOUSE.Attribute.INFANTRY then elseif request.assetdescval==WAREHOUSE.Attribute.INFANTRY then
asset_ground=true asset_ground=true
elseif request.assetdescval==WAREHOUSE.Attribute.OTHER then elseif request.assetdescval==WAREHOUSE.Attribute.OTHER then
self:E("ERROR: incorrect request. Asset attribute WAREHOUSE.Attribute.OTHER is not valid!") self:E("ERROR: Incorrect request. Asset attribute WAREHOUSE.Attribute.OTHER is not valid!")
valid=false valid=false
elseif request.assetdescval==WAREHOUSE.Attribute.SHIP then elseif request.assetdescval==WAREHOUSE.Attribute.SHIP then
asset_naval=true asset_naval=true
@ -2870,7 +2982,7 @@ function WAREHOUSE:_CheckRequestConsistancy(queue)
elseif request.assetdescval==WAREHOUSE.Attribute.TRUCK then elseif request.assetdescval==WAREHOUSE.Attribute.TRUCK then
asset_ground=true asset_ground=true
else else
self:E("ERROR: incorrect request. Unknown asset attribute!") self:E("ERROR: Incorrect request. Unknown asset attribute!")
valid=false valid=false
end end
end end
@ -2882,13 +2994,14 @@ function WAREHOUSE:_CheckRequestConsistancy(queue)
------------------------------------------- -------------------------------------------
-- Case where the units go my themselves -- -- Case where the units go my themselves --
------------------------------------------- -------------------------------------------
if asset_air then if asset_air then
if asset_plane then if asset_plane then
-- No airplane to or from FARPS. -- No airplane to or from FARPS.
if request.category==Airbase.Category.HELIPAD or self.category==Airbase.Category.HELIPAD then if request.category==Airbase.Category.HELIPAD or self.category==Airbase.Category.HELIPAD then
self:E("ERROR: incorrect request. Asset aircraft requestst but warehouse or requestor is HELIPAD/FARP!") self:E("ERROR: Incorrect request. Asset airplane requested but warehouse or requestor is HELIPAD/FARP!")
valid=false valid=false
end end
@ -2897,10 +3010,10 @@ function WAREHOUSE:_CheckRequestConsistancy(queue)
elseif asset_helo then elseif asset_helo then
-- Helos need a FARP or AIRBASE or SHIP for spawning. Event if they go there they "cannot" be spawned again. -- Helos need a FARP or AIRBASE or SHIP for spawning. Also at the the receiving warehouse. So even if they could go there they "cannot" be spawned again.
-- Unless I allow spawning of helos in the the spawn zone. But one should place at least a FARP there. -- Unless I allow spawning of helos in the the spawn zone. But one should place at least a FARP there.
if self.category==-1 or request.category==-1 then if self.category==-1 or request.category==-1 then
self:E("ERROR: incorrect request. Helos need a AIRBASE/HELIPAD/SHIP as home/destinaion base!") self:E("ERROR: Incorrect request. Helos need a AIRBASE/HELIPAD/SHIP as home/destination base!")
valid=false valid=false
end end
@ -2908,7 +3021,7 @@ function WAREHOUSE:_CheckRequestConsistancy(queue)
-- All aircraft need an airbase of any type as depature or destination. -- All aircraft need an airbase of any type as depature or destination.
if self.airbase==nil or request.airbase==nil then if self.airbase==nil or request.airbase==nil then
self:E("ERROR: incorrect request. Either warehouse or requesting warehouse does not have any kind of airbase!") self:E("ERROR: Incorrect request. Either warehouse or requesting warehouse does not have any kind of airbase!")
valid=false valid=false
end end
@ -2917,57 +3030,42 @@ function WAREHOUSE:_CheckRequestConsistancy(queue)
-- No ground assets directly to or from ships. -- No ground assets directly to or from ships.
-- TODO: May needs refinement if warehouse is on land and requestor is ship in harbour?! -- TODO: May needs refinement if warehouse is on land and requestor is ship in harbour?!
if (request.category==Airbase.Category.SHIP or self.category==Airbase.Category.SHIP) then if (request.category==Airbase.Category.SHIP or self.category==Airbase.Category.SHIP) then
self:E("ERROR: incorrect request. Ground asset requested but warehouse or requestor is SHIP!") self:E("ERROR: Incorrect request. Ground asset requested but warehouse or requestor is SHIP!")
valid=false valid=false
end end
if asset_train then if asset_train then
-- Check if there is a valid path on rail. -- Check if there is a valid path on rail.
valid=self:HasConnectionRail(request.warehouse) local hasrail=self:HasConnectionRail(request.warehouse)
--[[ if not hasrail then
if self.rail and request.warehouse.rail then self:E("ERROR: Incorrect request. No valid path on rail for train assets!")
local onrail=self.rail:GetPathOnRoad(request.warehouse.rail, false, true)
if onrail==nil then
self:E("ERROR: incorrect request. No valid path on rail for train assets!")
valid=false valid=false
end end
else
self:E("ERROR: incorrect request. Either warehouse or requesting warehouse have no connection to rail!")
valid=false
end
]]
else else
-- Check if there is a valid path on road. -- Check if there is a valid path on road.
valid=self:HasConnectionRoad(request.warehouse) local hasroad=self:HasConnectionRoad(request.warehouse)
--[[ if not hasroad then
if self.road and request.warehouse.road then self:E("ERROR: Incorrect request. No valid path on road for ground assets!")
local onroad=self.road:GetPathOnRoad(request.warehouse.road, false, false)
if onroad==nil then
self:E("ERROR: incorrect request. No valid path on road for ground assets!")
valid=false valid=false
end end
else
self:E("ERROR: incorrect request. Either warehouse or requesting warehouse have no connection to road!")
valid=false
end
]]
end end
elseif asset_naval then elseif asset_naval then
self:E("ERROR: incorrect request. Naval units not supported yet!") self:E("ERROR: Incorrect request. Naval units not supported yet!")
valid=false valid=false
end end
else else
-------------------------------
-- Assests need a transport. -- Assests need a transport ---
-------------------------------
if request.transporttype==WAREHOUSE.TransportType.AIRPLANE then if request.transporttype==WAREHOUSE.TransportType.AIRPLANE then
-- Airplanes only to AND from airdromes. -- Airplanes only to AND from airdromes.
if self.category~=Airbase.Category.AIRDROME or request.category~=Airbase.Category.AIRDROME then if self.category~=Airbase.Category.AIRDROME or request.category~=Airbase.Category.AIRDROME then
self:E("ERROR: incorrect request. Warehouse or requestor does not have an airdrome. No transport by plane possible!") self:E("ERROR: Incorrect request. Warehouse or requestor does not have an airdrome. No transport by plane possible!")
valid=false valid=false
end end
@ -2979,44 +3077,51 @@ function WAREHOUSE:_CheckRequestConsistancy(queue)
-- No transport to or from ships -- No transport to or from ships
if self.category==Airbase.Category.SHIP or request.category==Airbase.Category.SHIP then if self.category==Airbase.Category.SHIP or request.category==Airbase.Category.SHIP then
self:E("ERROR: incorrect request. Warehouse or requestor is SHIP. No transport by APC possible!") self:E("ERROR: Incorrect request. Warehouse or requestor is SHIP. No transport by APC possible!")
valid=false
end
-- Check if there is a valid path on road.
local hasroad=self:HasConnectionRoad(request.warehouse)
if not hasroad then
self:E("ERROR: Incorrect request. No valid path on road for ground transport assets!")
valid=false valid=false
end end
elseif request.transporttype==WAREHOUSE.TransportType.HELICOPTER then elseif request.transporttype==WAREHOUSE.TransportType.HELICOPTER then
-- Transport by helicopters ==> need airbase for spawning but not for delivering to the zone. -- Transport by helicopters ==> need airbase for spawning but not for delivering to the spawn zone of the receiver.
if self.category==-1 then if self.category==-1 then
self:E("ERROR: incorrect request. Warehouse has no airbase. Transport by helicopter not possible!") self:E("ERROR: Incorrect request. Warehouse has no airbase. Transport by helicopter not possible!")
valid=false valid=false
end end
elseif request.transporttype==WAREHOUSE.TransportType.SHIP then elseif request.transporttype==WAREHOUSE.TransportType.SHIP then
-- Transport by ship. -- Transport by ship.
self:E("ERROR: incorrect request. Transport by SHIP not implemented yet!") self:E("ERROR: Incorrect request. Transport by SHIP not implemented yet!")
valid=false valid=false
elseif request.transporttype==WAREHOUSE.TransportType.TRAIN then elseif request.transporttype==WAREHOUSE.TransportType.TRAIN then
-- Only one train due to limited spawn place.
--nTransport=1
-- Transport by train. -- Transport by train.
self:E("ERROR: incorrect request. Transport by TRAIN not implemented yet!") self:E("ERROR: Incorrect request. Transport by TRAIN not implemented yet!")
valid=false valid=false
else else
-- No match. -- No match.
self:E("ERROR: incorrect request. Transport type unknown!") self:E("ERROR: Incorrect request. Transport type unknown!")
valid=false valid=false
end end
end end
-- Add request as unvalid and delete it later. -- Add request as unvalid and delete it later.
if not valid then if valid==false then
self:E(self.wid..string.format("Got invalid request id=%d.", request.uid))
table.insert(invalid, request) table.insert(invalid, request)
else
self:T3(self.wid..string.format("Got valid request id=%d.", request.uid))
end end
end -- loop queue items. end -- loop queue items.
@ -3024,7 +3129,7 @@ function WAREHOUSE:_CheckRequestConsistancy(queue)
-- Delete invalid requests. -- Delete invalid requests.
for _,_request in pairs(invalid) do for _,_request in pairs(invalid) do
self:E(self.wid..string.format("Deleting invalid request %d",_request.uid)) self:E(self.wid..string.format("Deleting invalid request id=%d.",_request.uid))
self:_DeleteQueueItem(_request, self.queue) self:_DeleteQueueItem(_request, self.queue)
end end
@ -3037,14 +3142,23 @@ end
-- @return #boolean If true, request can be executed. If false, something is not right. -- @return #boolean If true, request can be executed. If false, something is not right.
function WAREHOUSE:_CheckRequestNow(request) function WAREHOUSE:_CheckRequestNow(request)
-- Assume request is okay and check scenarios.
local okay=true local okay=true
-- Check if receiving warehouse is running.
if not request.warehouse:IsRunning() then
local text=string.format("Warehouse %s: Request denied! Receiving warehouse %s is not running. Current state %s.", self.alias, request.warehouse.alias, request.warehouse:GetState())
MESSAGE:New(text, 5):ToCoalitionIf(self.coalition, self.Report or self.Debug)
self:E(self.wid..text)
okay=false
end
-- Check if number of requested assets is in stock. -- Check if number of requested assets is in stock.
local _assets,_nassets,_enough=self:_FilterStock(self.stock, request.assetdesc, request.assetdescval, request.nasset) local _assets,_nassets,_enough=self:_FilterStock(self.stock, request.assetdesc, request.assetdescval, request.nasset)
-- Check if enough assets are in stock. -- Check if enough assets are in stock.
if not _enough then if not _enough then
local text=string.format("Request denied! Not enough (cargo) assets currently available.") local text=string.format("Warehouse %s: Request denied! Not enough (cargo) assets currently available.", self.alias)
MESSAGE:New(text, 5):ToCoalitionIf(self.coalition, self.Report or self.Debug) MESSAGE:New(text, 5):ToCoalitionIf(self.coalition, self.Report or self.Debug)
self:E(self.wid..text) self:E(self.wid..text)
okay=false okay=false
@ -3061,7 +3175,7 @@ function WAREHOUSE:_CheckRequestNow(request)
if self.airbase and (_assetcategory==Group.Category.AIRPLANE or _assetcategory==Group.Category.HELICOPTER) then if self.airbase and (_assetcategory==Group.Category.AIRPLANE or _assetcategory==Group.Category.HELICOPTER) then
local Parking=self:_FindParkingForAssets(self.airbase,_assets) local Parking=self:_FindParkingForAssets(self.airbase,_assets)
if Parking==nil then if Parking==nil then
local text=string.format("Request denied! Not enough free parking spots for all assets at the moment.") local text=string.format("Warehouse %s: Request denied! Not enough free parking spots for all assets at the moment.", self.alias)
MESSAGE:New(text, 5):ToCoalitionIf(self.coalition, self.Report or self.Debug) MESSAGE:New(text, 5):ToCoalitionIf(self.coalition, self.Report or self.Debug)
self:E(self.wid..text) self:E(self.wid..text)
okay=false okay=false
@ -3078,7 +3192,7 @@ function WAREHOUSE:_CheckRequestNow(request)
-- Check if enough transport units are available. -- Check if enough transport units are available.
if not _enough then if not _enough then
local text=string.format("Request denied! Not enough transport units currently available.") local text=string.format("Warehouse %s: Request denied! Not enough transport assets currently available.", self.alias)
MESSAGE:New(text, 5):ToCoalitionIf(self.coalition, self.Report or self.Debug) MESSAGE:New(text, 5):ToCoalitionIf(self.coalition, self.Report or self.Debug)
self:E(self.wid..text) self:E(self.wid..text)
okay=false okay=false
@ -3095,7 +3209,7 @@ function WAREHOUSE:_CheckRequestNow(request)
if self.airbase and (_transportcategory==Group.Category.AIRPLANE or _transportcategory==Group.Category.HELICOPTER) then if self.airbase and (_transportcategory==Group.Category.AIRPLANE or _transportcategory==Group.Category.HELICOPTER) then
local Parking=self:_FindParkingForAssets(self.airbase,_transports) local Parking=self:_FindParkingForAssets(self.airbase,_transports)
if Parking==nil then if Parking==nil then
local text=string.format("Request denied! Not enough free parking spots for all transports at the moment.") local text=string.format("Warehouse %s: Request denied! Not enough free parking spots for all transports at the moment.", self.alias)
MESSAGE:New(text, 5):ToCoalitionIf(self.coalition, self.Report or self.Debug) MESSAGE:New(text, 5):ToCoalitionIf(self.coalition, self.Report or self.Debug)
self:E(self.wid..text) self:E(self.wid..text)
okay=false okay=false
@ -3237,7 +3351,8 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets)
local _vec3=static:getPoint() local _vec3=static:getPoint()
local _coord=COORDINATE:NewFromVec3(_vec3) local _coord=COORDINATE:NewFromVec3(_vec3)
local _name=static:getName() local _name=static:getName()
local _size=self:_GetObjectSize(static:GetDCSObject()) --env.info("FF static name = "..tostring(_name))
local _size=self:_GetObjectSize(static)
table.insert(obstacles[_termid],{coord=_coord, size=_size, name=_name, type="static"}) table.insert(obstacles[_termid],{coord=_coord, size=_size, name=_name, type="static"})
end end
@ -3246,7 +3361,7 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets)
local _vec3=scenery:getPoint() local _vec3=scenery:getPoint()
local _coord=COORDINATE:NewFromVec3(_vec3) local _coord=COORDINATE:NewFromVec3(_vec3)
local _name=scenery:getTypeName() local _name=scenery:getTypeName()
local _size=self:_GetObjectSize(scenery:GetDCSObject()) local _size=self:_GetObjectSize(scenery)
table.insert(obstacles[_termid],{coord=_coord, size=_size, name=_name, type="scenery"}) table.insert(obstacles[_termid],{coord=_coord, size=_size, name=_name, type="scenery"})
end end
@ -3818,7 +3933,7 @@ end
-- @return #table Table of flightplan coordinates. -- @return #table Table of flightplan coordinates.
function WAREHOUSE:_GetFlightplan(asset, departure, destination) function WAREHOUSE:_GetFlightplan(asset, departure, destination)
-- Parameters -- Parameters in SI units.
local Vmax=asset.speedmax/3.6 local Vmax=asset.speedmax/3.6
local Range=asset.range local Range=asset.range
local _category=asset.category local _category=asset.category

View File

@ -661,8 +661,9 @@ function GROUP:GetDCSUnits()
end end
--- Activates a GROUP. --- Activates a late activated GROUP.
-- @param #GROUP self -- @param #GROUP self
-- @return #GROUP self
function GROUP:Activate() function GROUP:Activate()
self:F2( { self.GroupName } ) self:F2( { self.GroupName } )
trigger.action.activateGroup( self:GetDCSObject() ) trigger.action.activateGroup( self:GetDCSObject() )

View File

@ -54,8 +54,7 @@ end
--- Returns the unit's unique identifier. --- Returns the unit's unique identifier.
-- @param Wrapper.Object#OBJECT self -- @param Wrapper.Object#OBJECT self
-- @return DCS#Object.ID ObjectID -- @return DCS#Object.ID ObjectID or #nil if the DCS Object is not existing or alive. Note that the ID is passed as a string and not a number.
-- @return #nil The DCS Object is not existing or alive.
function OBJECT:GetID() function OBJECT:GetID()
local DCSObject = self:GetDCSObject() local DCSObject = self:GetDCSObject()