Warehouse 0.2.3w

This commit is contained in:
funkyfranky 2018-08-21 16:38:55 +02:00
parent e40105495a
commit 31a5bfee9e

View File

@ -38,7 +38,7 @@
-- @field #number uid Unit identifier of the warehouse. Derived from the associated airbase. -- @field #number uid Unit identifier of the warehouse. Derived from the associated airbase.
-- @field #number markerid ID of the warehouse marker at the airbase. -- @field #number markerid ID of the warehouse marker at the airbase.
-- @field #number dTstatus Time interval in seconds of updating the warehouse status and processing new events. Default 30 seconds. -- @field #number dTstatus Time interval in seconds of updating the warehouse status and processing new events. Default 30 seconds.
-- @field #number assetid Unique id of asset items in stock. Essentially a running number starting at one and incremented when a new asset is added. -- @field #number queueid Unit id of each request in the queue. Essentially a running number starting at one and incremented when a new request is added.
-- @field #table stock Table holding all assets in stock. Table entries are of type @{#WAREHOUSE.Assetitem}. -- @field #table stock Table holding all assets in stock. Table entries are of type @{#WAREHOUSE.Assetitem}.
-- @field #table queue Table holding all queued requests. Table entries are of type @{#WAREHOUSE.Queueitem}. -- @field #table queue Table holding all queued requests. Table entries are of type @{#WAREHOUSE.Queueitem}.
-- @field #table pending Table holding all pending requests, i.e. those that are currently in progress. Table entries are of type @{#WAREHOUSE.Pendingitem}. -- @field #table pending Table holding all pending requests, i.e. those that are currently in progress. Table entries are of type @{#WAREHOUSE.Pendingitem}.
@ -105,7 +105,6 @@ WAREHOUSE = {
uid = nil, uid = nil,
markerid = nil, markerid = nil,
dTstatus = 30, dTstatus = 30,
assetid = 0,
queueid = 0, queueid = 0,
stock = {}, stock = {},
queue = {}, queue = {},
@ -210,7 +209,7 @@ WAREHOUSE.db = {
--- Warehouse class version. --- Warehouse class version.
-- @field #string version -- @field #string version
WAREHOUSE.version="0.2.3" WAREHOUSE.version="0.2.3w"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Warehouse todo list. -- TODO: Warehouse todo list.
@ -674,7 +673,6 @@ function WAREHOUSE:onafterStop(From, Event, To)
-- Clear all pending schedules. -- Clear all pending schedules.
self.CallScheduler:Clear() self.CallScheduler:Clear()
end end
--- On after "Pause" event. Pauses the warehouse, i.e. no requests are processed. However, new requests and new assets can be added in this state. --- On after "Pause" event. Pauses the warehouse, i.e. no requests are processed. However, new requests and new assets can be added in this state.
@ -703,8 +701,8 @@ end
-- @param #string Event Event. -- @param #string Event Event.
-- @param #string To To state. -- @param #string To To state.
function WAREHOUSE:onafterStatus(From, Event, To) function WAREHOUSE:onafterStatus(From, Event, To)
self:E(self.wid..string.format("Checking status of warehouse %s.", self.alias)) self:E(self.wid..string.format("Checking status of warehouse %s. Current FSM state %s. Global warehouse asssets = %d.", self.alias, self:GetState(), #WAREHOUSE.db.Assets))
env.info(string.format("FF number of global assets = %d, current asset id = %d", #WAREHOUSE.db.Assets, WAREHOUSE.db.AssetID)) --env.info(string.format("FF number of global assets = %d, current asset id = %d", #WAREHOUSE.db.Assets, WAREHOUSE.db.AssetID))
-- Print status. -- Print status.
self:_DisplayStatus() self:_DisplayStatus()
@ -713,14 +711,15 @@ function WAREHOUSE:onafterStatus(From, Event, To)
self:_CheckConquered() self:_CheckConquered()
-- Print queue. -- Print queue.
self:_PrintQueue(self.queue, "Queue waiting") self:_PrintQueue(self.queue, "Queue waiting - before request")
self:_PrintQueue(self.pending, "Queue pending") self:_PrintQueue(self.pending, "Queue pending - before request")
-- Check if requests are valid and remove invalid one. -- Check if requests are valid and remove invalid one.
self:_CheckRequestConsistancy(self.queue) self:_CheckRequestConsistancy(self.queue)
-- If warehouse is running than requests can be processed. -- If warehouse is running than requests can be processed.
if self:IsRunning() or self:IsAttacked() then if self:IsRunning() or self:IsAttacked() then
-- Check queue and handle requests if possible. -- Check queue and handle requests if possible.
local request=self:_CheckQueue() local request=self:_CheckQueue()
@ -728,6 +727,11 @@ function WAREHOUSE:onafterStatus(From, Event, To)
if request then if request then
self:Request(request) self:Request(request)
end end
-- Print queue after processing requests.
self:_PrintQueue(self.queue, "Queue waiting - after request")
self:_PrintQueue(self.pending, "Queue pending - after request")
end end
-- Update warhouse marker on F10 map. -- Update warhouse marker on F10 map.
@ -761,7 +765,7 @@ function WAREHOUSE:onafterAddAsset(From, Event, To, group, ngroups)
group=GROUP:FindByName(group) group=GROUP:FindByName(group)
end end
env.info(string.format("Adding asset group %s", group:GetName())) self:E(string.format("Adding %d assets of group %s.", n, group:GetName()))
if group then if group then
@ -770,24 +774,20 @@ function WAREHOUSE:onafterAddAsset(From, Event, To, group, ngroups)
-- Check if this is an known or a new asset group. -- Check if this is an known or a new asset group.
if aid~=nil and wid~=nil then if aid~=nil and wid~=nil then
env.info(string.format("Adding known! asset group %s with id %d", group:GetName(), aid))
-- We got a warehouse and asset id ==> this is an "old" group. -- We got a warehouse and asset id ==> this is an "old" group.
local asset=self:_FindAssetInDB(group) local asset=self:_FindAssetInDB(group)
env.info(string.format("Adding known! asset group %s with id %d", group:GetName(), aid))
-- Note the group is only added once, i.e. the ngroups parameter is ignored here. -- Note the group is only added once, i.e. the ngroups parameter is ignored here.
-- This is because usually these request comes from an asset that has been transfered from another warehouse and hence should only be added once. -- This is because usually these request comes from an asset that has been transfered from another warehouse and hence should only be added once.
if asset~=nil then if asset~=nil then
env.info(string.format("Adding new asset to stock. asset id = %d, attribute = %s", asset.uid, asset.attribute)) self:E(string.format("Adding new asset with id = %d, attribute = %s to warehouse stock.", asset.uid, asset.attribute))
table.insert(self.stock, asset) table.insert(self.stock, asset)
else else
env.error("ERROR known asset could not be found in global warehouse db!") env.error("ERROR known asset could not be found in global warehouse db!")
end end
else else
env.info("Asset unkonwn ==> registering in DB!")
-- 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)
@ -878,7 +878,6 @@ function WAREHOUSE:_RegisterAsset(group, ngroups)
local asset={} --#WAREHOUSE.Assetitem local asset={} --#WAREHOUSE.Assetitem
-- Increase asset unique id counter. -- Increase asset unique id counter.
self.assetid=self.assetid+1
WAREHOUSE.db.AssetID=WAREHOUSE.db.AssetID+1 WAREHOUSE.db.AssetID=WAREHOUSE.db.AssetID+1
-- Set parameters. -- Set parameters.
@ -1036,12 +1035,7 @@ function WAREHOUSE:_SpawnAssetAircraft(asset, request, parking)
spawnpoint.helipadId = nil spawnpoint.helipadId = nil
end end
-- Get the right terminal type for this kind of aircraft. -- Check enough parking spots.
--local terminaltype=self:_GetTerminal(asset.attribute)
-- Get parking data.
--local parking=self.airbase:GetFreeParkingSpotsTable(terminaltype)
if AirbaseCategory == Airbase.Category.HELIPAD or AirbaseCategory == Airbase.Category.SHIP then if AirbaseCategory == Airbase.Category.HELIPAD or AirbaseCategory == Airbase.Category.SHIP then
--TODO Figure out what's necessary in this case. --TODO Figure out what's necessary in this case.
@ -1421,7 +1415,7 @@ function WAREHOUSE:onafterRequest(From, Event, To, Request)
-- Now we try to find all parking spots for all cargo groups in advance. Due to the for loop, the parking spots do not get updated while spawning. -- Now we try to find all parking spots for all cargo groups in advance. Due to the for loop, the parking spots do not get updated while spawning.
local Parking={} local Parking={}
if _transportcategory==Group.Category.AIRPLANE or _transportcategory==Group.Category.HELICOPTER then if _transportcategory==Group.Category.AIRPLANE or _transportcategory==Group.Category.HELICOPTER then
Parking=self:_GetParkingForAssets(_assetstock) Parking=self:_FindParkingForAssets(self.airbase,_assetstock)
end end
-- Transport assets table. -- Transport assets table.
@ -1442,10 +1436,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 _takeoff=SPAWN.Takeoff.Cold local spawngroup=self:_SpawnAssetAircraft(_assetitem, Pending, Parking[_assetitem.uid])
--local spawn=SPAWN:NewWithAlias(_assetitem.templatename,_alias)
local spawn=SPAWN:NewFromTemplate(_assetitem.template,_assetitem.templatename,_alias):InitCoalition(self.coalition):InitCountry(self.country)
local spawngroup=spawn:InitUnControlled(true):SpawnAtAirbase(self.airbase,_takeoff, nil, nil, false, _parking)
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.
@ -1474,17 +1465,12 @@ function WAREHOUSE:onafterRequest(From, Event, To, Request)
-- Get stock item. -- Get stock item.
local _assetitem=_assetstock[i] --#WAREHOUSE.Assetitem local _assetitem=_assetstock[i] --#WAREHOUSE.Assetitem
local _parking=Parking[i]
-- Spawn with ALIAS here or DCS crashes! -- Spawn with ALIAS here or DCS crashes!
--local _alias=string.format("%s_%d", _assetitem.templatename,_assetitem.id)
local _alias=self:_Alias(_assetitem, Request) local _alias=self:_Alias(_assetitem, Request)
-- Spawn helo at airport. -- Spawn plane at airport in uncontrolled state.
local _takeoff=SPAWN.Takeoff.Hot local spawngroup=self:_SpawnAssetAircraft(_assetitem, Pending, Parking[_assetitem.uid])
--local spawn=SPAWN:NewWithAlias(_assetitem.templatename,_alias)
local spawn=SPAWN:NewFromTemplate(_assetitem.template,_assetitem.templatename,_alias):InitCoalition(self.coalition):InitCountry(self.country)
local spawngroup=spawn:InitUnControlled(false):SpawnAtAirbase(self.airbase,_takeoff, nil, nil, false, _parking)
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.
@ -1523,10 +1509,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 ground asset.
--local spawn=SPAWN:NewWithAlias(_assetitem.templatename,_alias) local spawngroup=self:_SpawnAssetGround(_assetitem, Request)
local spawn=SPAWN:NewFromTemplate(_assetitem.template,_assetitem.templatename,_alias):InitCoalition(self.coalition):InitCountry(self.country)
local spawngroup=spawn:SpawnFromCoordinate(self.spawnzone:GetRandomCoordinate())
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.
@ -1600,7 +1584,7 @@ function WAREHOUSE:onafterRequest(From, Event, To, Request)
Carrier:SmokeRed() Carrier:SmokeRed()
-- Add carrier back to warehouse stock. Actual unit is destroyed. -- Add carrier back to warehouse stock. Actual unit is destroyed.
warehouse:AddAsset(Carrier, 1) warehouse:AddAsset(Carrier)
end end
@ -1643,7 +1627,8 @@ function WAREHOUSE:_SpawnAssetRequest(Request)
-- Now we try to find all parking spots for all cargo groups in advance. Due to the for loop, the parking spots do not get updated while spawning. -- Now we try to find all parking spots for all cargo groups in advance. Due to the for loop, the parking spots do not get updated while spawning.
local Parking={} local Parking={}
if _cargocategory==Group.Category.AIRPLANE or _cargocategory==Group.Category.HELICOPTER then if _cargocategory==Group.Category.AIRPLANE or _cargocategory==Group.Category.HELICOPTER then
Parking=self:_GetParkingForAssets(_assetstock) Parking=self:_FindParkingForAssets(self.airbase,_assetstock)
--Parking=self:_GetParkingForAssets(_assetstock)
end end
-- Spawn aircraft in uncontrolled state if request comes from the same warehouse. -- Spawn aircraft in uncontrolled state if request comes from the same warehouse.
@ -1666,23 +1651,14 @@ function WAREHOUSE:_SpawnAssetRequest(Request)
-- Get stock item. -- Get stock item.
local _assetitem=_assetstock[i] --#WAREHOUSE.Assetitem local _assetitem=_assetstock[i] --#WAREHOUSE.Assetitem
-- Find a random point within the spawn zone.
local spawncoord=self.spawnzone:GetRandomCoordinate()
-- Alias of the group. -- Alias of the group.
local _alias=self:_Alias(_assetitem, Request) local _alias=self:_Alias(_assetitem, Request)
-- Spawn object. Spawn with ALIAS here or DCS crashes! -- Spawn an asset group.
--local _spawn=SPAWN:NewFromTemplate(_assetitem.template,_assetitem.templatename,_alias):InitCoalition(self.coalition):InitCountry(self.country)
--local _spawn=SPAWN:NewWithAlias(_assetitem.templatename,_alias):InitCoalition(self.coalition):InitCountry(self.country):InitUnControlled(UnControlled):InitAIOnOff(AIOnOff)
local _group=nil --Wrapper.Group#GROUP local _group=nil --Wrapper.Group#GROUP
local _attribute=_assetitem.attribute
if _assetitem.category==Group.Category.GROUND then if _assetitem.category==Group.Category.GROUND then
-- Spawn ground troops. -- Spawn ground troops.
--_group=_spawn:SpawnFromCoordinate(spawncoord)
_group=self:_SpawnAssetGround(_assetitem, Request) _group=self:_SpawnAssetGround(_assetitem, Request)
elseif _assetitem.category==Group.Category.AIRPLANE or _assetitem.category==Group.Category.HELICOPTER then elseif _assetitem.category==Group.Category.AIRPLANE or _assetitem.category==Group.Category.HELICOPTER then
@ -1690,7 +1666,6 @@ 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=_spawn:SpawnAtAirbase(self.airbase, SPAWN.Takeoff.Cold, nil, nil, true, Parking[i])
_group=self:_SpawnAssetAircraft(_assetitem, Request, Parking[i]) _group=self:_SpawnAssetAircraft(_assetitem, Request, Parking[i])
elseif _assetitem.category==Group.Category.TRAIN then elseif _assetitem.category==Group.Category.TRAIN then
@ -1708,7 +1683,7 @@ function WAREHOUSE:_SpawnAssetRequest(Request)
_groupset:AddGroup(_group) _groupset:AddGroup(_group)
table.insert(_assets, _assetitem) table.insert(_assets, _assetitem)
else else
self:E(self.wid.."ERROR: cargo asset could not be spawned!") self:E(self.wid.."ERROR: Cargo asset could not be spawned!")
end end
end end
@ -1792,7 +1767,7 @@ function WAREHOUSE:onafterArrived(From, Event, To, group)
end end
-- Move asset from pending queue into new warehouse. -- Move asset from pending queue into new warehouse.
request.warehouse:__AddAsset(60, group, 1) request.warehouse:__AddAsset(60, group)
-- All cargo delivered. -- All cargo delivered.
if request and ncargo==0 then if request and ncargo==0 then
@ -1913,7 +1888,8 @@ end
-- @param DCS#country.id Country which is attacking the warehouse. -- @param DCS#country.id Country which is attacking the warehouse.
function WAREHOUSE:onafterAttacked(From, Event, To, Coalition, Country) function WAREHOUSE:onafterAttacked(From, Event, To, Coalition, Country)
self:E(self.wid..string.format("Our warehouse is under attack!")) self:E(self.wid..string.format("Our warehouse is under attack!"))
--TODO: Spawn all ground units in the spawnzone?
-- Spawn all ground units in the spawnzone?
self:AddRequest(self, WAREHOUSE.Descriptor.CATEGORY, Group.Category.GROUND, "all", nil, nil , 0) self:AddRequest(self, WAREHOUSE.Descriptor.CATEGORY, Group.Category.GROUND, "all", nil, nil , 0)
end end
@ -1969,6 +1945,17 @@ function WAREHOUSE:onafterCaptured(From, Event, To, Coalition, Country)
end end
--- On after "Destroyed" event. Warehouse was destroyed. Service is stopped.
-- @param #WAREHOUSE self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
function WAREHOUSE:onafterDestroyed(From, Event, To)
self:E(self.wid..string.format("Our warehouse was destroyed!"))
-- Stop warehouse FSM.
self:Stop()
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Routing functions -- Routing functions
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -2187,7 +2174,7 @@ function WAREHOUSE:_OnEventBirth(EventData)
local group=EventData.IniGroup local group=EventData.IniGroup
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))
end end
end end
end end
@ -2196,21 +2183,45 @@ end
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param Core.Event#EVENTDATA EventData Event data. -- @param Core.Event#EVENTDATA EventData Event data.
function WAREHOUSE:_OnEventEngineStartup(EventData) function WAREHOUSE:_OnEventEngineStartup(EventData)
self:E(self.wid..string.format("Warehouse %s captured event engine startup!",self.alias)) self:T3(self.wid..string.format("Warehouse %s captured event engine startup!",self.alias))
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 engine startup of its asset unit %s.", self.alias, EventData.IniUnitName))
end
end
end end
--- Warehouse event handling function. --- Warehouse event handling function.
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param Core.Event#EVENTDATA EventData Event data. -- @param Core.Event#EVENTDATA EventData Event data.
function WAREHOUSE:_OnEventTakeOff(EventData) function WAREHOUSE:_OnEventTakeOff(EventData)
self:E(self.wid..string.format("Warehouse %s captured event takeoff!",self.alias)) self:T3(self.wid..string.format("Warehouse %s captured event takeoff!",self.alias))
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 takeoff of its asset unit %s.", self.alias, EventData.IniUnitName))
end
end
end end
--- Warehouse event handling function. --- Warehouse event handling function.
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param Core.Event#EVENTDATA EventData Event data. -- @param Core.Event#EVENTDATA EventData Event data.
function WAREHOUSE:_OnEventLanding(EventData) function WAREHOUSE:_OnEventLanding(EventData)
self:E(self.wid..string.format("Warehouse %s captured event landing!",self.alias)) self:T3(self.wid..string.format("Warehouse %s captured event landing!",self.alias))
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 landing of its asset unit %s.", self.alias, EventData.IniUnitName))
end
end
end end
--- Warehouse event handling function. --- Warehouse event handling function.
@ -2232,8 +2243,7 @@ function WAREHOUSE:_OnEventCrashOrDead(EventData)
local warehousename=self.warehouse:GetName() local warehousename=self.warehouse:GetName()
if EventData.IniUnitName==warehousename then if EventData.IniUnitName==warehousename then
env.info(self.wid..string.format("Warehouse %s alias %s was destroyed!", warehousename, self.alias)) env.info(self.wid..string.format("Warehouse %s alias %s was destroyed!", warehousename, self.alias))
--TODO: Add destroy event. self:Destroyed()
self:__Stop(1)
end end
end end
@ -2251,8 +2261,7 @@ function WAREHOUSE:_OnEventBaseCaptured(EventData)
return return
end end
if EventData and EventData.id==world.event.S_EVENT_BASE_CAPTURED then if EventData and EventData.Place then
if EventData.Place then
-- Place is the airbase that was captured. -- Place is the airbase that was captured.
local airbase=EventData.Place --Wrapper.Airbase#AIRBASE local airbase=EventData.Place --Wrapper.Airbase#AIRBASE
@ -2268,8 +2277,10 @@ function WAREHOUSE:_OnEventBaseCaptured(EventData)
-- Warehouse is blue, airbase is blue self.airbase is nil and blue (re-)captures it ==> self.airbase=Event.Place -- Warehouse is blue, airbase is blue self.airbase is nil and blue (re-)captures it ==> self.airbase=Event.Place
if self.airbase==nil then if self.airbase==nil then
-- Warehouse lost this airbase previously and not it was re-captured. -- Warehouse lost this airbase previously and not it was re-captured.
env.info("FF airbase of warehouse is nil")
if coalitionAirbase == self.coalition then if coalitionAirbase == self.coalition then
self.airbase=airbase self.airbase=airbase
env.info("FF air")
end end
else else
-- Captured airbase belongs to this warehouse but was captured by other coaltion. -- Captured airbase belongs to this warehouse but was captured by other coaltion.
@ -2280,7 +2291,6 @@ function WAREHOUSE:_OnEventBaseCaptured(EventData)
end end
end end
end
end end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -2702,12 +2712,9 @@ function WAREHOUSE:_CheckRequestNow(request)
local _assetattribute=_assets[1].attribute local _assetattribute=_assets[1].attribute
local _assetcategory=_assets[1].category local _assetcategory=_assets[1].category
-- Check available parking for asset units. -- Check available parking for air asset units.
local Parkingdata
local Parking
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
Parkingdata=self.airbase:GetParkingSpotsTable() local Parking=self:_FindParkingForAssets(self.airbase,_assets)
Parking, Parkingdata=self:_GetParkingForAssets(_assets, Parkingdata)
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("Request denied! Not enough free parking spots for all assets at the moment.")
MESSAGE:New(text, 5):ToCoalitionIf(self.coalition, self.Report or self.Debug) MESSAGE:New(text, 5):ToCoalitionIf(self.coalition, self.Report or self.Debug)
@ -2741,7 +2748,7 @@ function WAREHOUSE:_CheckRequestNow(request)
-- Check available parking for transport units. -- Check available parking for transport units.
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
Parking, Parkingdata=self:_GetParkingForAssets(_transports, Parkingdata) 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("Request denied! Not enough free parking spots for all transports at the moment.")
MESSAGE:New(text, 5):ToCoalitionIf(self.coalition, self.Report or self.Debug) MESSAGE:New(text, 5):ToCoalitionIf(self.coalition, self.Report or self.Debug)
@ -2893,6 +2900,148 @@ function WAREHOUSE:_GetParkingForAssets(assetlist, parkingdata)
return assetparking, parkingdata return assetparking, parkingdata
end end
----------------
--- Seach unoccupied parking spots at the airbase for a list of assets. For each asset group a list of parking spots is returned.
-- During the search also the not yet spawned asset aircraft are considered.
-- If not enough spots for all asset units could be found, the routine returns nil!
-- @param #WAREHOUSE self
-- @param Wrapper.Airbase#AIRBASE airbase The airbase where we search for parking spots.
-- @param #table assets A table of assets for which the parking spots are needed.
-- @return #table Table of coordinates and terminal IDs of free parking spots. Each table entry has the elements .Coordinate and .TerminalID.
function WAREHOUSE:_FindParkingForAssets(airbase, assets)
-- Init default
local scanradius=50
local scanunits=true
local scanstatics=true
local scanscenery=false
local verysafe=false
-- Function calculating the overlap of two (square) objects.
local function _overlap(l1,l2,dist)
local safedist=(l1/2+l2/2)*1.1
local safe = (dist > safedist)
self:T3(string.format("l1=%.1f l2=%.1f s=%.1f d=%.1f ==> safe=%s", l1,l2,safedist,dist,tostring(safe)))
return safe
end
-- Get parking spot data table. This contains all free and "non-free" spots.
local parkingdata=airbase:GetParkingSpotsTable()
-- List of obstacles.
local obstacles={}
-- Loop over all parking spots and get the obstacles.
-- TODO: How long does this take on very large airbases, i.e. those with hundereds of parking spots?
for _,parkingspot in pairs(parkingdata) do
-- Coordinate of the parking spot.
local _spot=parkingspot.Coordinate -- Core.Point#COORDINATE
local _termid=parkingspot.TerminalID
-- Obstacles at or around this parking spot.
obstacles[_termid]={}
-- Scan a radius of 50 meters around the spot.
local _,_,_,_units,_statics,_sceneries=_spot:ScanObjects(scanradius, scanunits, scanstatics, scanscenery)
-- Check all units.
for _,_unit in pairs(_units) do
local unit=_unit --Wrapper.Unit#UNIT
local _coord=unit:GetCoordinate()
local _size=self:_GetObjectSize(unit:GetDCSObject())
local _name=unit:GetName()
table.insert(obstacles[_termid],{coord=_coord, size=_size, name=_name, type="unit"})
end
-- Check all statics.
for _,static in pairs(_statics) do
local _vec3=static:getPoint()
local _coord=COORDINATE:NewFromVec3(_vec3)
local _name=static:getName()
local _size=self:_GetObjectSize(static:GetDCSObject())
table.insert(obstacles[_termid],{coord=_coord, size=_size, name=_name, type="static"})
end
-- Check all scenery.
for _,scenery in pairs(_sceneries) do
local _vec3=scenery:getPoint()
local _coord=COORDINATE:NewFromVec3(_vec3)
local _name=scenery:getTypeName()
local _size=self:_GetObjectSize(scenery:GetDCSObject())
table.insert(obstacles[_termid],{coord=_coord, size=_size, name=_name, type="scenery"})
end
-- TODO Clients? Unoccupied client aircraft are also important! Are they already included in scanned units maybe?
end
-- Parking data for all assets.
local parking={}
-- Loop over all assets that need a parking psot.
for _,asset in pairs(assets) do
local _asset=asset --#WAREHOUSE.Assetitem
local terminaltype=self:_GetTerminal(asset.attribute)
-- Asset specific parking.
parking[_asset.uid]={}
-- Loop over all units - each one needs a spot.
for i=1,_asset.nunits do
-- Loop over all parking spots.
for _,parkingspot in pairs(parkingdata) do
-- Check correct terminal type for asset. We don't want helos in shelters etc.
if AIRBASE._CheckTerminalType(parkingspot.TerminalType,terminaltype) then
-- Coordinate of the parking spot.
local _spot=parkingspot.Coordinate -- Core.Point#COORDINATE
local _termid=parkingspot.TerminalID
-- Loop over all obstacles.
local free=true
for _,obstacle in pairs(obstacles[_termid]) do
-- Check if aircraft overlaps with any obstacle.
local safe=_overlap(_asset.size, obstacle.size, _spot:Get2DDistance(obstacle.coord))
-- Spot is blocked.
if not safe then
free=false
break
end
end
if free then
-- Add parkingspot for this asset unit.
table.insert(parking[_asset.uid], parkingspot)
-- Add the unit as obstacle so that this spot will not be available for the next unit.
-- TODO Alternatively, I could remove this parking spot from the table, right?
obstacles[_termid]={coord=_spot, size=_asset.size, name=_asset.templatename, type="asset"}
else
-- Not enough parking available!
return nil
end
end -- check terminal type
end -- loop over parking spots
end -- loop over asset units
end -- loop over asset groups
return parking
end
-----------------
--- Get the request belonging to a group. --- Get the request belonging to a group.
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param Wrapper.Group#GROUP group The group from which the info is gathered. -- @param Wrapper.Group#GROUP group The group from which the info is gathered.
@ -3154,6 +3303,21 @@ function WAREHOUSE:_GetAttribute(groupname)
return attribute return attribute
end end
--- Size of the bounding box of a DCS object derived from the DCS descriptor table. If boundinb box is nil, a size of zero is returned.
-- @param #WAREHOUSE self
-- @param DCS#Object DCSobject The DCS object for which the size is needed.
-- @return #number Max size of object in meters.
function WAREHOUSE:_GetObjectSize(DCSobject)
local DCSdesc=DCSobject:getDesc()
if DCSdesc.box then
local x=DCSdesc.box.max.x+math.abs(DCSdesc.box.min.x) --length
local y=DCSdesc.box.max.y+math.abs(DCSdesc.box.min.y) --height
local z=DCSdesc.box.max.z+math.abs(DCSdesc.box.min.z) --width
return math.max(x,z), x , y, z
end
return 0,0,0,0
end
--- Returns the number of assets for each generalized attribute. --- Returns the number of assets for each generalized attribute.
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param #table stock The stock of the warehouse. -- @param #table stock The stock of the warehouse.