WAREHOUSE

This commit is contained in:
funkyfranky 2018-08-08 16:21:50 +02:00
parent a71c7dc181
commit b46c238dda
2 changed files with 403 additions and 361 deletions

View File

@ -1214,18 +1214,26 @@ do -- COORDINATE
return COORDINATE:NewFromVec2(vec2) return COORDINATE:NewFromVec2(vec2)
end end
--- Returns a table of coordinates to a destination using only roads.
--- Returns a table of coordinates to a destination using only roads or railroads.
-- The first point is the closest point on road of the given coordinate. -- The first point is the closest point on road of the given coordinate.
-- By default, the last point is the closest point on road of the ToCoord. Hence, the coordinate itself and the final ToCoord are not necessarily included in the path. -- By default, the last point is the closest point on road of the ToCoord. Hence, the coordinate itself and the final ToCoord are not necessarily included in the path.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #COORDINATE ToCoord Coordinate of destination. -- @param #COORDINATE ToCoord Coordinate of destination.
-- @param #boolean IncludeEndpoints (Optional) Include the coordinate itself and the ToCoordinate in the path. -- @param #boolean IncludeEndpoints (Optional) Include the coordinate itself and the ToCoordinate in the path.
-- @param #boolean Railroad (Optional) If true, path on railroad is returned. Default false.
-- @return #table Table of coordinates on road. If no path on road can be found, nil is returned or just the endpoints. -- @return #table Table of coordinates on road. If no path on road can be found, nil is returned or just the endpoints.
-- @return #number The length of the total path. -- @return #number The length of the total path.
function COORDINATE:GetPathOnRoad(ToCoord, IncludeEndpoints) function COORDINATE:GetPathOnRoad(ToCoord, IncludeEndpoints, Railroad)
-- Set road type.
local RoadType="roads"
if Railroad==true then
RoadType="railroads"
end
-- DCS API function returning a table of vec2. -- DCS API function returning a table of vec2.
local path = land.findPathOnRoads("roads", self.x, self.z, ToCoord.x, ToCoord.z) local path = land.findPathOnRoads(RoadType, self.x, self.z, ToCoord.x, ToCoord.z)
-- Array holding the path coordinates. -- Array holding the path coordinates.
local Path={} local Path={}

View File

@ -24,6 +24,7 @@
-- @field #boolean Report If true, send status messages to coalition. -- @field #boolean Report If true, send status messages to coalition.
-- @field DCS#Coalition coalition Coalition the warehouse belongs to. -- @field DCS#Coalition coalition Coalition the warehouse belongs to.
-- @field Wrapper.Airbase#AIRBASE homebase Airbase the warehouse belongs to. -- @field Wrapper.Airbase#AIRBASE homebase Airbase the warehouse belongs to.
-- @field DCS#Airbase.Category category Category of the home airbase, i.e. airdrome, helipad/farp or ship.
-- @field Core.Point#COORDINATE coordinate Coordinate of the warehouse. -- @field Core.Point#COORDINATE coordinate Coordinate of the warehouse.
-- @field Core.Zone#ZONE spawnzone Zone in which assets are spawned. -- @field Core.Zone#ZONE spawnzone Zone in which assets are spawned.
-- @field #string wid Identifier of the warehouse printed before other output to DCS.log file. -- @field #string wid Identifier of the warehouse printed before other output to DCS.log file.
@ -74,6 +75,7 @@ WAREHOUSE = {
Report = true, Report = true,
coalition = nil, coalition = nil,
homebase = nil, homebase = nil,
category = nil,
coordinate = nil, coordinate = nil,
spawnzone = nil, spawnzone = nil,
wid = nil, wid = nil,
@ -98,6 +100,7 @@ WAREHOUSE = {
-- @field #number uid Unique id of the queue item. -- @field #number uid Unique id of the queue item.
-- @field #number prio Priority of the request. -- @field #number prio Priority of the request.
-- @field Wrapper.Airbase#AIRBASE airbase Requesting airbase. -- @field Wrapper.Airbase#AIRBASE airbase Requesting airbase.
-- @field DCS#Airbase.Category category Category of the requesting airbase, i.e. airdrome, helipad/farp or ship.
-- @field #WAREHOUSE.Descriptor assetdesc Descriptor of the requested asset. -- @field #WAREHOUSE.Descriptor assetdesc Descriptor of the requested asset.
-- @field assetdescval Value of the asset descriptor. Type depends on descriptor. -- @field assetdescval Value of the asset descriptor. Type depends on descriptor.
-- @field #number nasset Number of asset groups requested. -- @field #number nasset Number of asset groups requested.
@ -187,6 +190,7 @@ function WAREHOUSE:NewAirbase(airbase)
self.homebase=airbase self.homebase=airbase
self.coordinate=airbase:GetCoordinate() self.coordinate=airbase:GetCoordinate()
self.coalition=airbase:GetCoalition() self.coalition=airbase:GetCoalition()
self.category=airbase:GetDesc().category
-- Get the closest point on road. -- Get the closest point on road.
local _road=self.coordinate:GetClosestPointToRoad():GetVec2() local _road=self.coordinate:GetClosestPointToRoad():GetVec2()
@ -225,21 +229,13 @@ function WAREHOUSE:NewAirbase(airbase)
--- Triggers the FSM event "Request". Executes a request if possible. --- Triggers the FSM event "Request". Executes a request if possible.
-- @function [parent=#WAREHOUSE] Request -- @function [parent=#WAREHOUSE] Request
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase requesting supply. -- @param #WAREHOUSE.Queueitem Request Information table of the request.
-- @param #WAREHOUSE.Descriptor AssetDescriptor Descriptor describing the asset that is requested.
-- @param AssetDescriptorValue Value of the asset descriptor. Type depends on descriptor, i.e. could be a string, etc.
-- @param #number nAsset Number of groups requested that match the asset specification.
-- @param #WAREHOUSE.TransportType TransportType Type of transport.
--- Triggers the FSM event "Request" after a delay. Executes a request if possible. --- Triggers the FSM event "Request" after a delay. Executes a request if possible.
-- @function [parent=#WAREHOUSE] __Request -- @function [parent=#WAREHOUSE] __Request
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param #number Delay Delay in seconds. -- @param #number Delay Delay in seconds.
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase requesting supply. -- @param #WAREHOUSE.Queueitem Request Information table of the request.
-- @param #WAREHOUSE.Descriptor AssetDescriptor Descriptor describing the asset that is requested.
-- @param AssetDescriptorValue Value of the asset descriptor. Type depends on descriptor, i.e. could be a string, etc.
-- @param #number nAsset Number of groups requested that match the asset specification.
-- @param #WAREHOUSE.TransportType TransportType Type of transport.
--- Triggers the FSM event "Delivered". A group has been delivered from the warehouse to another airbase or warehouse. --- Triggers the FSM event "Delivered". A group has been delivered from the warehouse to another airbase or warehouse.
@ -272,7 +268,7 @@ function WAREHOUSE:onafterStart(From, Event, To)
-- event takeoff -- event takeoff
-- event landing -- event landing
-- event crash/dead -- event crash/dead
-- event base captured ==> change coalition ==> add assets to other coalition. -- event base captured ==> change coalition ==> add assets to other coalition
self:__Status(5) self:__Status(5)
end end
@ -307,7 +303,7 @@ function WAREHOUSE:onafterStatus(From, Event, To)
-- Display complete list of stock itmes. -- Display complete list of stock itmes.
if self.Debug then if self.Debug then
--self:_DisplayStockItems(self.stock) --self:_DisplayStockItems(self.stock)
end end
-- Print queue. -- Print queue.
@ -315,46 +311,69 @@ function WAREHOUSE:onafterStatus(From, Event, To)
for _,_qitem in ipairs(self.queue) do for _,_qitem in ipairs(self.queue) do
local qitem=_qitem --#WAREHOUSE.Queueitem local qitem=_qitem --#WAREHOUSE.Queueitem
local text=string.format("uid=%d, prio=%d, airbase=%s, descriptor: %s=%s, nasssets=%d, transport=%s, ntransport=%d", local text=string.format("uid=%d, prio=%d, airbase=%s, descriptor: %s=%s, nasssets=%d, transport=%s, ntransport=%d",
qitem.uid, qitem.prio, qitem.airbase:GetName(), qitem.assetdesc,tostring(qitem.assetdescval),qitem.nasset,qitem.transporttype,qitem.ntransport) qitem.uid, qitem.prio, qitem.airbase:GetName(), qitem.assetdesc,tostring(qitem.assetdescval),qitem.nasset,qitem.transporttype,qitem.ntransport)
env.info(text) env.info(text)
end end
-- Check queue and handle requests if possible. -- Check queue and handle requests if possible.
self:_WorkQueue() local request=self:_CheckQueue()
-- Execute the request. If the request is really executed, it is also deleted from the queue.
if request then
--self:Request(request.airbase, request.assetdesc, request.assetdescval, request.nasset, request.transporttype, request.ntransport)
self:Request(request)
end
-- Call status again in 30 sec. -- Call status again in 30 sec.
--self:__Status(10) self:__Status(30)
end end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- On before "Request" event. Checks if the request can be fullfilled. --- On before "Request" event. Checks if the request can be fullfilled.
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase requesting supply. -- @param Wrapper.Airbase#AIRBASE Airbase airbase requesting supply.
-- @param #WAREHOUSE.Descriptor AssetDescriptor Descriptor describing the asset that is requested. -- @param #WAREHOUSE.Descriptor AssetDescriptor Descriptor describing the asset that is requested.
-- @param AssetDescriptorValue Value of the asset descriptor. Type depends on descriptor, i.e. could be a string, etc. -- @param AssetDescriptorValue Value of the asset descriptor. Type depends on descriptor, i.e. could be a string, etc.
-- @param #number nAsset Number of groups requested that match the asset specification. -- @param #number nAsset Number of groups requested that match the asset specification.
-- @param #WAREHOUSE.TransportType TransportType Type of transport. -- @param #WAREHOUSE.TransportType TransportType Type of transport.
-- @param #number nTransport Number of transport units requested. -- @param #number nTransport Number of transport units requested.
-- @param #number Prio Priority of the request. Number ranging from 1=high to 100=low. -- @param #number Prio Priority of the request. Number ranging from 1=high to 100=low.
function WAREHOUSE:AddRequest(Airbase, AssetDescriptor, AssetDescriptorValue, nAsset, TransportType, nTransport, Prio) function WAREHOUSE:AddRequest(airbase, AssetDescriptor, AssetDescriptorValue, nAsset, TransportType, nTransport, Prio)
nAsset=nAsset or 1
TransportType=TransportType or WAREHOUSE.TransportType.SELFPROPELLED
nTransport=nTransport or 1 nTransport=nTransport or 1
Prio=Prio or 50 Prio=Prio or 50
--TODO: check that
-- if warehouse or requestor is a FARP, plane asset and transport not possible
-- if requestor or warehouse is a SHIP, APC transport not possible, SELFPROPELLED only for AIR/SHIP
-- etc. etc...
local request_category=airbase:GetDesc().category
if self.category==Airbase.Category.HELIPAD or request_category==Airbase.Category.HELIPAD then
if TransportType==WAREHOUSE.TransportType.AIRPLANE then
self:E("ERROR: incorrect request. Warehouse or requestor is FARP. No transport by plane possible!")
return
end
end
-- Increase id. -- Increase id.
self.queueid=self.queueid+1 self.queueid=self.queueid+1
-- Request queue table item. -- Request queue table item.
local request={uid=self.queueid, prio=Prio, airbase=Airbase, assetdesc=AssetDescriptor, assetdescval=AssetDescriptorValue, nasset=nAsset, transporttype=TransportType, ntransport=nTransport} local request={uid=self.queueid, prio=Prio, airbase=airbase, category=request_category, assetdesc=AssetDescriptor, assetdescval=AssetDescriptorValue, nasset=nAsset, transporttype=TransportType, ntransport=nTransport}
-- Add request to queue. -- Add request to queue.
table.insert(self.queue, request) table.insert(self.queue, request)
end end
--- On before "Request" event. Checks if the request can be fullfilled. ---Sorts the queue and checks if the request can be fullfilled.
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
function WAREHOUSE:_WorkQueue() -- @return #WAREHOUSE.Queueitem Chosen request.
function WAREHOUSE:_CheckQueue()
-- Sort queue wrt to first prio and then qid. -- Sort queue wrt to first prio and then qid.
self:_SortQueue() self:_SortQueue()
@ -388,38 +407,29 @@ function WAREHOUSE:_WorkQueue()
end end
-- Execute request. -- Execute request.
if request then return request
self:Request(request.airbase, request.assetdesc, request.assetdescval, request.nasset, request.transporttype, request.ntransport)
end
end end
--- On before "Request" event. Checks if the request can be fullfilled. --- On before "Request" event. Checks if the request can be fullfilled.
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param #string From From state. -- @param #string From From state.
-- @param #string Event Event. -- @param #string Event Event.
-- @param #string To To state. -- @param #string To To state.
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase requesting supply. -- @param #WAREHOUSE.Queueitem Request Information table of the request.
-- @param #WAREHOUSE.Descriptor AssetDescriptor Descriptor describing the asset that is requested.
-- @param AssetDescriptorValue Value of the asset descriptor. Type depends on descriptor, i.e. could be a string, etc.
-- @param #number nAsset Number of groups requested that match the asset specification.
-- @param #WAREHOUSE.TransportType TransportType Type of transport.
-- @return #boolean If true, request is granted. -- @return #boolean If true, request is granted.
function WAREHOUSE:onbeforeRequest(From, Event, To, Airbase, AssetDescriptor, AssetDescriptorValue, nAsset, TransportType) function WAREHOUSE:onbeforeRequest(From, Event, To, Request)
env.info(self.wid..string.format("Airbase %s requesting asset %s = %s.", Airbase:GetName(), tostring(AssetDescriptor), tostring(AssetDescriptorValue))) --env.info(self.wid..string.format("Airbase %s requesting asset %s = %s.", Airbase:GetName(), tostring(AssetDescriptor), tostring(AssetDescriptorValue)))
-- Default. -- Distance from warehouse to requesting airbase.
nAsset=nAsset or 1 local distance=self.coordinate:Get2DDistance(Request.airbase:GetCoordinate())
TransportType=TransportType or WAREHOUSE.TransportType.SELFPROPELLED
-- Distance from warehouse to
local distance=self.coordinate:Get2DDistance(Airbase:GetCoordinate())
-- Filter the requested assets. -- Filter the requested assets.
local _stockrequest=self:_FilterStock(self.stock, AssetDescriptor, AssetDescriptorValue) local _stockrequest=self:_FilterStock(self.stock, Request.assetdesc, Request.assetdescval)
-- Asset is not in stock ==> request denied. -- Asset is not in stock ==> request denied.
if #_stockrequest < nAsset then if #_stockrequest < Request.nasset then
local text=string.format("Request denied! Not enought assets currently in stock. Requested %d < %d in stock.", nAsset, #_stockrequest) local text=string.format("Request denied! Not enough assets currently in stock. Requested %d < %d in stock.", Request.nasset, #_stockrequest)
MESSAGE:New(text, 10):ToCoalitionIf(self.coalition, self.Report or self.Debug) MESSAGE:New(text, 10):ToCoalitionIf(self.coalition, self.Report or self.Debug)
self:E(self.wid..text) self:E(self.wid..text)
return false return false
@ -429,15 +439,17 @@ function WAREHOUSE:onbeforeRequest(From, Event, To, Airbase, AssetDescriptor, As
local _stockitem=_stockrequest[1] --#WAREHOUSE.Stockitem local _stockitem=_stockrequest[1] --#WAREHOUSE.Stockitem
local _assetattribute=self:_GetAttribute(_stockitem.templatename) local _assetattribute=self:_GetAttribute(_stockitem.templatename)
-- Get assets in stock which are of the right type.
local _instock=self:_FilterStock(self.stock, WAREHOUSE.Descriptor.ATTRIBUTE, TransportType)
-- Check that a transport unit is available. -- Check that a transport unit is available.
if #_instock==0 and TransportType~=WAREHOUSE.TransportType.SELFPROPELLED then if Request.transporttype~=WAREHOUSE.TransportType.SELFPROPELLED then
local text=string.format("Request denied! No transport unit currently available.") local _instock=self:_FilterStock(self.stock, WAREHOUSE.Descriptor.ATTRIBUTE, Request.transporttype)
MESSAGE:New(text, 10):ToCoalitionIf(self.coalition, self.Report or self.Debug) if #_instock==0 then
self:E(self.wid..text) local text=string.format("Request denied! No transport unit currently available.")
return false MESSAGE:New(text, 10):ToCoalitionIf(self.coalition, self.Report or self.Debug)
self:E(self.wid..text)
return false
end
end end
-- TODO: For aircraft check that a parking spot is available. -- TODO: For aircraft check that a parking spot is available.
@ -445,41 +457,62 @@ function WAREHOUSE:onbeforeRequest(From, Event, To, Airbase, AssetDescriptor, As
return true return true
end end
--- On after "Request" event. Initiates the transport of the assets to the requesting airbase. --- On after "Request" event. Initiates the transport of the assets to the requesting airbase.
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param #string From From state. -- @param #string From From state.
-- @param #string Event Event. -- @param #string Event Event.
-- @param #string To To state. -- @param #string To To state.
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase requesting supply. -- @param #WAREHOUSE.Queueitem Request Information table of the request.
-- @param #WAREHOUSE.Descriptor AssetDescriptor Descriptor describing the asset that is requested. function WAREHOUSE:onafterRequest(From, Event, To, Request)
-- @param AssetDescriptorValue Value of the asset descriptor. Type depends on descriptor, i.e. could be a string, etc. --env.info(self.wid..string.format("Airbase %s requesting asset %s = %s.", Airbase:GetName(), tostring(AssetDescriptor), tostring(AssetDescriptorValue)))
-- @param #number nAsset Number of groups requested that match the asset specification.
-- @param #WAREHOUSE.TransportType TransportType Type of transport.
function WAREHOUSE:onafterRequest(From, Event, To, Airbase, AssetDescriptor, AssetDescriptorValue, nAsset, TransportType, nTransport)
env.info(self.wid..string.format("Airbase %s requesting asset %s = %s.", Airbase:GetName(), tostring(AssetDescriptor), tostring(AssetDescriptorValue)))
---------------------------------------------------------------- ----------------------------------------------------------------
-- Filter the requested assets. -- Filter the requested assets.
local _assetstock=self:_FilterStock(self.stock, AssetDescriptor, AssetDescriptorValue) local _assetstock=self:_FilterStock(self.stock, Request.assetdesc, Request.assetdescval)
-- Spawn the assets. -- Spawn the assets.
local _delid={} local _delid={}
local _spawngroups={} local _spawngroups={}
for i=1,nAsset do local _cargotype
local _cargocategory
for i=1,Request.nasset do
-- Get stock item. -- Get stock item.
local _assetitem=_assetstock[i] --#WAREHOUSE.Stockitem local _assetitem=_assetstock[i] --#WAREHOUSE.Stockitem
table.insert(_delid,_assetitem.id)
-- Find a random point within the spawn zone. -- Find a random point within the spawn zone.
local spawncoord=self.spawnzone:GetRandomCoordinate() local spawncoord=self.spawnzone:GetRandomCoordinate()
spawncoord:MarkToAll(string.format("spawnpoint %d",i)) spawncoord:MarkToAll(string.format("spawnpoint %d",i))
-- Spawn with ALIAS here or DCS crashes! -- Alias of the group. Spawn with ALIAS here or DCS crashes!
local _alias=string.format("%s_%d", _assetitem.templatename,_assetitem.id) local _alias=string.format("%s_WHID%04d", _assetitem.templatename,_assetitem.id)
_spawngroups[i]=SPAWN:NewWithAlias(_assetitem.templatename, _alias):SpawnFromCoordinate(spawncoord) local _spawn=SPAWN:NewWithAlias(_assetitem.templatename,_alias)
local _group
if _assetitem.category==Group.Category.GROUND then
-- Spawn ground troops.
_group=_spawn:SpawnFromCoordinate(spawncoord)
elseif _assetitem.category==Group.Category.AIRPLANE or _assetitem.category==Group.Category.HELICOPTER then
-- Spawn air units.
local _takeoff=SPAWN.Takeoff.Cold
local _terminal=AIRBASE.TerminalType.OpenBig
if _assetitem.attribute==WAREHOUSE.Attribute.FIGHTER then
_terminal=AIRBASE.TerminalType.FighterAircraft
elseif _assetitem.attribute==WAREHOUSE.Attribute.BOMBER then
_terminal=AIRBASE.TerminalType.OpenBig
end
_group=_spawn:InitUnControlled(true):SpawnAtAirbase(self.homebase,_takeoff, nil,_terminal, true)
elseif _assetitem.category==Group.Category.TRAIN then
end
if _group then
_spawngroups[i]=_group
_cargotype=_assetitem.attribute
_cargocategory=_assetitem.category
table.insert(_delid,_assetitem.id)
end
end end
-- Delete spawned items from warehouse stock. -- Delete spawned items from warehouse stock.
@ -490,12 +523,32 @@ function WAREHOUSE:onafterRequest(From, Event, To, Airbase, AssetDescriptor, Ass
---------------------------------------------------------------- ----------------------------------------------------------------
-- No transport unit requested. Assets go by themselfes. -- No transport unit requested. Assets go by themselfes.
if TransportType==WAREHOUSE.TransportType.SELFPROPELLED then if Request.transporttype==WAREHOUSE.TransportType.SELFPROPELLED then
for _i,_spawngroup in pairs(_spawngroups) do for _i,_spawngroup in pairs(_spawngroups) do
local group=_spawngroup --Wrapper.Group#GROUP local group=_spawngroup --Wrapper.Group#GROUP
local ToCoordinate=Airbase:GetZone():GetRandomCoordinate() local ToCoordinate=Request.airbase:GetZone():GetRandomCoordinate()
group:RouteGroundOnRoad(ToCoordinate)
if _cargocategory==Group.Category.GROUND then
self:_RouteGround(group, ToCoordinate)
elseif _cargocategory==Group.Category.AIRPLANE then
self:_RouteAir(group, Request.airbase)
elseif _cargocategory==Group.Category.HELICOPTER then
self:_RouteAir(group, Request.airbase)
elseif _cargocategory==Group.Category.SHIP then
elseif _cargocategory==Group.Category.TRAIN then
end
end end
-- Delete request from queue.
self:_DeleteQueueItem(Request.uid)
-- No cargo transport necessary.
return
end end
---------------------------------------------------------------- ----------------------------------------------------------------
@ -508,42 +561,32 @@ function WAREHOUSE:onafterRequest(From, Event, To, Airbase, AssetDescriptor, Ass
-- Add spawned groups to cargo group object. -- Add spawned groups to cargo group object.
for _i,_spawngroup in pairs(_spawngroups) do for _i,_spawngroup in pairs(_spawngroups) do
local _name=string.format("%s %d",AssetDescriptorValue, _i) local _name=string.format("%s %d", Request.assetdescval, _i)
env.info(string.format("FF cargo group %d: %s",_i,_name)) env.info(string.format("FF cargo group %d: %s",_i,_name))
local cargogroup = CARGO_GROUP:New(_spawngroup, AssetDescriptorValue, _name, _loadradius, _nearradius) local cargogroup = CARGO_GROUP:New(_spawngroup, Request.assetdescval, _name, _loadradius, _nearradius)
CargoGroups:AddCargo(cargogroup) CargoGroups:AddCargo(cargogroup)
end end
---------------------------------------------------------------- ----------------------------------------------------------------
--[[
-- Filter the requested assets.
local _transportitem --#WAREHOUSE.Stockitem
if TransportType ~= WAREHOUSE.TransportType.SELFPROPELLED then
local _transportstock=self:_FilterStock(self.stock, WAREHOUSE.Descriptor.ATTRIBUTE, TransportType)
local _chosenone=math.random(#_transportstock)
-- Select asset template group name.
_transportitem=_transportstock[_chosenone]
end
]]
local TransportSet = SET_GROUP:New() --:AddGroupsByName(Plane:GetName()) local TransportSet = SET_GROUP:New() --:AddGroupsByName(Plane:GetName())
-- Pickup and depoly locations. -- Pickup and depoly locations.
local PickupAirbaseSet = SET_AIRBASE:New():AddAirbase(self.homebase) local PickupAirbaseSet = SET_AIRBASE:New():AddAirbase(self.homebase)
local DeployAirbaseSet = SET_AIRBASE:New():AddAirbase(Airbase) local DeployAirbaseSet = SET_AIRBASE:New():AddAirbase(Request.airbase)
local DeployZoneSet = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart() local DeployZoneSet = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
--local bla=SET_ZONE:New():AddZonesByName(AddZoneNames)
local CargoTransport --AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER local CargoTransport --AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
-- Filter the requested transport assets. -- Filter the requested transport assets.
local _assetstock=self:_FilterStock(self.stock, WAREHOUSE.Descriptor.ATTRIBUTE, TransportType) local _assetstock=self:_FilterStock(self.stock, WAREHOUSE.Descriptor.ATTRIBUTE, Request.transporttype)
-- Dependent on transport type, spawn the transports and set up the dispatchers. -- Dependent on transport type, spawn the transports and set up the dispatchers.
if TransportType==WAREHOUSE.TransportType.AIRPLANE then if Request.transporttype==WAREHOUSE.TransportType.AIRPLANE then
-- Spawn the transport groups. -- Spawn the transport groups.
local _delid={} local _delid={}
for i=1,nTransport do for i=1,Request.ntransport do
-- Get stock item. -- Get stock item.
local _assetitem=_assetstock[i] --#WAREHOUSE.Stockitem local _assetitem=_assetstock[i] --#WAREHOUSE.Stockitem
@ -552,8 +595,9 @@ function WAREHOUSE:onafterRequest(From, Event, To, Airbase, AssetDescriptor, Ass
local _alias=string.format("%s_%d", _assetitem.templatename,_assetitem.id) local _alias=string.format("%s_%d", _assetitem.templatename,_assetitem.id)
-- Spawn plane at airport in uncontrolled state. -- Spawn plane at airport in uncontrolled state.
-- TODO: check terminal type. local _takeoff=SPAWN.Takeoff.Cold
local spawngroup=SPAWN:NewWithAlias(_assetitem.templatename,_alias):InitUnControlled(true):SpawnAtAirbase(self.homebase, SPAWN.Takeoff.Cold, nil, AIRBASE.TerminalType.OpenBig, false) local _terminal=AIRBASE.TerminalType.OpenBig
local spawngroup=SPAWN:NewWithAlias(_assetitem.templatename,_alias):InitUnControlled(true):SpawnAtAirbase(self.homebase,_takeoff, nil,_terminal, 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.
@ -574,56 +618,11 @@ function WAREHOUSE:onafterRequest(From, Event, To, Airbase, AssetDescriptor, Ass
-- Define dispatcher for this task. -- Define dispatcher for this task.
CargoTransport = AI_CARGO_DISPATCHER_AIRPLANE:New(TransportSet, CargoGroups, PickupAirbaseSet, DeployAirbaseSet) CargoTransport = AI_CARGO_DISPATCHER_AIRPLANE:New(TransportSet, CargoGroups, PickupAirbaseSet, DeployAirbaseSet)
elseif Request.transporttype==WAREHOUSE.TransportType.HELICOPTER then
--[[
-- Spawn plane at warehouse homebase.
--TODO: Check available parking spots in onbefore!
local Plane=SPAWN:New(_transportitem.templatename):InitUnControlled(true):SpawnAtAirbase(self.homebase, SPAWN.Takeoff.Cold, nil, AIRBASE.TerminalType.OpenBig, false)
if Plane==nil then
-- Plane was not spawned correctly. Try again in 60 seconds.
local text="Technical problems with the transport plane occurred. Request was cancelled! Try again later."
MESSAGE:New(text, 10):ToCoalitionIf(self.coalition, self.Report or self.Debug)
--TODO: Despawn asset units and but them back into the warehouse.
return
else
-- Remove chosen transport asset from list.
self:_DeleteStockItem(_transportitem.id)
end
-- Define cargo airplane object.
local CargoPlane = AI_CARGO_AIRPLANE:New(Plane, CargoGroups)
CargoPlane.Airbase=self.homebase
-- Pickup cargo at homebase.
CargoPlane:__Load(1, Plane:GetCoordinate())
-- Set warehouse state so that we can retreive it later.
Plane:SetState(Plane, "WAREHOUSE", self)
--- Once the cargo was loaded start off to deploy airbase.
function CargoPlane:OnAfterLoaded(Airplane, From, Event, To)
CargoPlane:__Deploy(10, Airbase)
end
--- Function called when cargo has arrived and was unloaded.
function CargoPlane:OnAfterUnloaded(Airplane, From, Event, To)
local group=CargoPlane.Cargo:GetObject()
local Airplane=Airplane --Wrapper.Group#GROUP
local warehouse=Airplane:GetState(Airplane, "WAREHOUSE") --#WAREHOUSE
-- Trigger Delivered event.
warehouse:__Delivered(1, group)
end
]]
elseif TransportType==WAREHOUSE.TransportType.HELICOPTER then
-- Spawn the transport groups. -- Spawn the transport groups.
local _delid={} local _delid={}
for i=1,nTransport do for i=1,Request.ntransport do
-- Get stock item. -- Get stock item.
local _assetitem=_assetstock[i] --#WAREHOUSE.Stockitem local _assetitem=_assetstock[i] --#WAREHOUSE.Stockitem
@ -633,7 +632,9 @@ function WAREHOUSE:onafterRequest(From, Event, To, Airbase, AssetDescriptor, Ass
-- Spawn plane at airport in uncontrolled state. -- Spawn plane at airport in uncontrolled state.
-- TODO: check terminal type. -- TODO: check terminal type.
local spawngroup=SPAWN:NewWithAlias(_assetitem.templatename,_alias):InitUnControlled(false):SpawnAtAirbase(self.homebase, SPAWN.Takeoff.Hot, nil, AIRBASE.TerminalType.HelicopterUsable, false) local _takeoff=SPAWN.Takeoff.Hot
local _terminal=AIRBASE.TerminalType.HelicopterUsable
local spawngroup=SPAWN:NewWithAlias(_assetitem.templatename,_alias):InitUnControlled(false):SpawnAtAirbase(self.homebase,_takeoff, nil,_terminal, 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.
@ -657,49 +658,11 @@ function WAREHOUSE:onafterRequest(From, Event, To, Airbase, AssetDescriptor, Ass
-- Home zone. -- Home zone.
CargoTransport:SetHomeZone(self.spawnzone) CargoTransport:SetHomeZone(self.spawnzone)
--CargoTransport = AI_CARGO_DISPATCHER_AIRPLANE:New(TransportSet, CargoGroups, PickupAirbasesSet, DeployAirbasesSet) elseif Request.transporttype==WAREHOUSE.TransportType.APC then
--[[
local Helo=SPAWN:New(_transportitem.templatename):SpawnAtAirbase(self.homebase, SPAWN.Takeoff.Cold, nil, AIRBASE.TerminalType.HelicopterUsable, false)
if Helo==nil then
-- Plane was not spawned correctly. Try again in 60 seconds.
local text="Technical problems with the transport helicopter occurred. Request was cancelled! Try again later."
return
else
-- Remove chosen transport asset from list.
self:_DeleteStockItem(_transportitem.id)
end
-- Define cargo airplane object.
local CargoHelo = AI_CARGO_HELICOPTER:New(Helo, CargoGroups)
-- Pickup cargo from the spawn zone.
CargoHelo:__Pickup(5, self.spawnzone:GetCoordinate())
--- Once the cargo was loaded start off to deploy airbase.
function CargoHelo:OnAfterLoaded(Carrier, From, Event, To)
CargoHelo:__Deploy(10, Airbase:GetZone():GetRandomCoordinate())
end
--- Function called when cargo has arrived and was unloaded.
function CargoHelo:OnAfterUnloaded(Airplane, From, Event, To)
local group=CargoHelo.Cargo:GetObject()
local Airplane=Airplane --Wrapper.Group#GROUP
local warehouse=Airplane:GetState(Airplane, "WAREHOUSE") --#WAREHOUSE
-- Trigger Delivered event.
warehouse:__Delivered(1, group)
end
]]
elseif TransportType==WAREHOUSE.TransportType.APC then
-- Spawn the transport groups. -- Spawn the transport groups.
local _delid={} local _delid={}
for i=1,nTransport do for i=1,Request.ntransport do
-- Get stock item. -- Get stock item.
local _assetitem=_assetstock[i] --#WAREHOUSE.Stockitem local _assetitem=_assetstock[i] --#WAREHOUSE.Stockitem
@ -729,45 +692,19 @@ function WAREHOUSE:onafterRequest(From, Event, To, Airbase, AssetDescriptor, Ass
-- Define dispatcher for this task. -- Define dispatcher for this task.
CargoTransport = AI_CARGO_DISPATCHER_APC:NewWithZones(TransportSet, CargoGroups, DeployZoneSet, 0) CargoTransport = AI_CARGO_DISPATCHER_APC:NewWithZones(TransportSet, CargoGroups, DeployZoneSet, 0)
--[[ elseif Request.transporttype==WAREHOUSE.TransportType.TRAIN then
-- Spawn APC in spawn zone.
local APC=SPAWN:New(_transportitem.templatename):SpawnFromCoordinate(self.spawnzone:GetCoordinate())
-- Set up cargo APC.
local CargoAPC=AI_CARGO_APC:New(APC, CargoGroups, 0)
-- Init pickup/loading of cargo. (No drive-to coordinate given, since we are already at in the spawn zone.)
CargoAPC:__Pickup(5)
--- Once the cargo was loaded start off to deploy airbase.
function CargoAPC:OnAfterLoaded(Airplane, From, Event, To)
CargoAPC:__Deploy(5, Airbase:GetZone():GetCoordinate())
end
--- Function called when cargo has arrived and was unloaded.
function CargoAPC:OnAfterUnloaded(Airplane, From, Event, To)
local group=CargoAPC.Cargo:GetObject()
local Airplane=Airplane --Wrapper.Group#GROUP
local warehouse=Airplane:GetState(Airplane, "WAREHOUSE") --#WAREHOUSE
-- Trigger Delivered event.
warehouse:__Delivered(1, group)
end
]]
elseif TransportType==WAREHOUSE.TransportType.TRAIN then
self:E(self.wid.."ERROR: transport by train not supported yet!") self:E(self.wid.."ERROR: transport by train not supported yet!")
return return
elseif TransportType==WAREHOUSE.TransportType.SHIP then elseif Request.transporttype==WAREHOUSE.TransportType.SHIP then
self:E(self.wid.."ERROR: transport by ship not supported yet!") self:E(self.wid.."ERROR: transport by ship not supported yet!")
return return
elseif TransportType==WAREHOUSE.TransportType.SELFPROPELLED then elseif Request.transporttype==WAREHOUSE.TransportType.SELFPROPELLED then
self:E(self.wid.."ERROR: transport type selfpropelled was already handled above. We should not get here!")
return return
else else
@ -799,6 +736,9 @@ function WAREHOUSE:onafterRequest(From, Event, To, Airbase, AssetDescriptor, Ass
-- Start dispatcher. -- Start dispatcher.
CargoTransport:__Start(5) CargoTransport:__Start(5)
-- Delete request from queue.
self:_DeleteQueueItem(Request.uid)
end end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -874,6 +814,104 @@ end
-- Helper functions -- Helper functions
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Route ground units to destination.
-- @param #WAREHOUSE self
-- @param Wrapper.Group#GROUP Group The ground group.
-- @param Core.Point#COORDINATE Coordinate of the destination.
-- @param #number Speed Speed in km/h to drive to the destination coordinate. Default is 60% of max possible speed the unit can go.
function WAREHOUSE:_RouteGround(Group, Coordinate, Speed)
if Group and Group:IsAlive() then
local _speed=Speed or Group:GetSpeedMax()*0.6
-- Create a
local Waypoints = Group:TaskGroundOnRoad(Coordinate, _speed, "Off Road", true)
-- Task function triggering the arrived event.
local TaskFunction = Group:TaskFunction("WAREHOUSE._Arrived", self)
-- Put task function on last waypoint.
local Waypoint = Waypoints[#Waypoints]
Group:SetTaskWaypoint( Waypoint, TaskFunction )
-- Route group to destination.
Group:Route(Waypoints, 1)
end
end
--- Task function for last waypoint. Triggering the Delivered event.
-- @param Wrapper.Group#GROUP Group The group that arrived.
-- @param #WAREHOUSE self
function WAREHOUSE._Arrived(Group, self)
--Trigger delivered event.
self:__Delivered(1, Group)
end
--- Route the airplane from one airbase another.
-- @param #AI_CARGO_AIRPLANE self
-- @param Wrapper.Group#GROUP Airplane Airplane group to be routed.
-- @param Wrapper.Airbase#AIRBASE ToAirbase Destination airbase.
-- @param #number Speed Speed in km/h. Default is 80% of max possible speed the group can do.
function WAREHOUSE:_RouteAir(Aircraft, ToAirbase, Speed)
if Aircraft and Aircraft:IsAlive() then
-- Set takeoff type.
local Takeoff = SPAWN.Takeoff.Cold
-- Get template of group.
local Template = Aircraft:GetTemplate()
-- Nil check
if Template==nil then
return
end
-- Waypoints of the route.
local Points={}
-- To point.
local AirbasePointVec2 = ToAirbase:GetPointVec2()
local ToWaypoint = AirbasePointVec2:WaypointAir(
POINT_VEC3.RoutePointAltType.BARO,
"Land",
"Landing",
Speed or Aircraft:GetSpeedMax()*0.8
)
ToWaypoint["airdromeId"] = ToAirbase:GetID()
ToWaypoint["speed_locked"] = true
-- Aibase id and category.
local AirbaseID = ToAirbase:GetID()
local AirbaseCategory = ToAirbase:GetDesc().category
if AirbaseCategory == Airbase.Category.SHIP or AirbaseCategory == Airbase.Category.HELIPAD then
ToWaypoint.linkUnit = AirbaseID
ToWaypoint.helipadId = AirbaseID
ToWaypoint.airdromeId = nil
elseif AirbaseCategory == Airbase.Category.AIRDROME then
ToWaypoint.airdromeId = AirbaseID
ToWaypoint.helipadId = nil
ToWaypoint.linkUnit = nil
end
-- Task function triggering the arrived event.
local Task = Aircraft:TaskFunction("WAREHOUSE._Arrived", self)
-- or
--ToWaypoint.task=Aircraft:TaskCombo({Task})
ToWaypoint.task={Task}
-- Second point of the route. First point is done in RespawnAtCurrentAirbase() routine.
Template.route.points[2] = ToWaypoint
-- Respawn group at the current airbase.
Aircraft:RespawnAtCurrentAirbase(Template, Takeoff, false)
end
end
--- Filter stock assets by table entry. --- Filter stock assets by table entry.
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param #table stock Table holding all assets in stock of the warehouse. Each entry is of type @{#WAREHOUSE.Stockitem}. -- @param #table stock Table holding all assets in stock of the warehouse. Each entry is of type @{#WAREHOUSE.Stockitem}.
@ -1029,10 +1067,11 @@ end
--- Delete item from stock. --- Delete item from stock.
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param #number uid The id of the item to be deleted. -- @param #number _uid The unique id of the item to be deleted.
function WAREHOUSE:_DeleteStockItem(uid) function WAREHOUSE:_DeleteStockItem(_uid)
for _i,_item in pairs(self.stock) do for _i,_item in pairs(self.stock) do
if _item.id==uid then local item=_item --#WAREHOUSE.Stockitem
if item.id==_uid then
self.stock[_i]=nil self.stock[_i]=nil
end end
end end
@ -1041,9 +1080,10 @@ end
--- Delete item from queue. --- Delete item from queue.
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param #number _uid The id of the item to be deleted. -- @param #number _uid The id of the item to be deleted.
function WAREHOUSE:_DeleteStockItem(_uid) function WAREHOUSE:_DeleteQueueItem(_uid)
for _i,_item in pairs(self.queue) do for _i,_item in pairs(self.queue) do
if _item.uid==_uid then local item=_item --#WAREHOUSE.Queueitem
if item.uid==_uid then
self.queue[_i]=nil self.queue[_i]=nil
end end
end end
@ -1060,12 +1100,6 @@ function WAREHOUSE:_SortQueue()
end end
table.sort(self.queue, _sort) table.sort(self.queue, _sort)
-- Debug output.
self:T3(self.wid.."Sorted queue wrt prio and uid:")
for i=1,#self.queue do
local _target=self.queue[i] --#WAREHOUSE#Queueitem
--self:T3(self.wid)..string.format("Queue %s", self:_TargetInfo(_target)))
end
end end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------