Warehouse v0.6.6

Again
This commit is contained in:
Frank 2018-12-09 19:32:39 +01:00
parent 9795d5655f
commit ecbdbedd96

View File

@ -69,6 +69,7 @@
-- @field #boolean autosave Automatically save assets to file when mission ends.
-- @field #string autosavepath Path where the asset file is saved on auto save.
-- @field #string autosavefilename File name of the auto asset save file. Default is auto generated from warehouse id and name.
-- @field #boolean safeparking If true, parking spots for aircraft are considered as occupied if e.g. a client aircraft is parked there. Default false.
-- @extends Core.Fsm#FSM
--- Have your assets at the right place at the right time - or not!
@ -624,7 +625,8 @@
-- The @{#WAREHOUSE.OnAfterAttacked} function can be used by the mission designer to react to the enemy attack. For example by deploying some or all ground troops
-- currently in stock to defend the warehouse. Note that the warehouse also has a self defence option which can be enabled by the @{#WAREHOUSE.SetAutoDefenceOn}()
-- function. In this case, the warehouse will automatically spawn all ground troops. If the spawn zone is further away from the warehouse zone, all mobile troops
-- are routed to the warehouse zone.
-- are routed to the warehouse zone. The self request which is triggered on an automatic defence has the assignment "AutoDefence". So you can use this to
-- give orders to the groups that were spawned using the @{#WAREHOUSE.OnAfterSelfRequest} function.
--
-- If only ground troops of the enemy coalition are present in the warehouse zone, the warehouse and all its assets falls into the hands of the enemy.
-- In this case the event **Captured** is triggered which can be captured by the @{#WAREHOUSE.OnAfterCaptured} function.
@ -1555,6 +1557,7 @@ WAREHOUSE = {
autosave = false,
autosavepath = nil,
autosavefile = nil,
saveparking = false,
}
--- Item of the warehouse stock table.
@ -1716,17 +1719,19 @@ WAREHOUSE.Quantity = {
--- Warehouse database. Note that this is a global array to have easier exchange between warehouses.
-- @type WAREHOUSE.db
-- @field #number AssetID Unique ID of each asset. This is a running number, which is increased each time a new asset is added.
-- @field #table Assets Table holding registered assets, which are of type @{Functional.Warehouse#WAREHOUSE.Assetitem}.
-- @field #table Assets Table holding registered assets, which are of type @{Functional.Warehouse#WAREHOUSE.Assetitem}.#
-- @field #number WarehouseID Unique ID of the warehouse. Running number.
-- @field #table Warehouses Table holding all defined @{#WAREHOUSE} objects by their unique ids.
WAREHOUSE.db = {
AssetID = 0,
Assets = {},
Warehouses = {}
AssetID = 0,
Assets = {},
WarehouseID = 0,
Warehouses = {}
}
--- Warehouse class version.
-- @field #string version
WAREHOUSE.version="0.6.4"
WAREHOUSE.version="0.6.6"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Warehouse todo list.
@ -1735,12 +1740,12 @@ WAREHOUSE.version="0.6.4"
-- TODO: Add check if assets "on the move" are stationary. Can happen if ground units get stuck in buildings. If stationary auto complete transport by adding assets to request warehouse? Time?
-- TODO: Optimize findpathonroad. Do it only once (first time) and safe paths between warehouses similar to off-road paths.
-- TODO: Spawn assets only virtually, i.e. remove requested assets from stock but do NOT spawn them ==> Interface to A2A dispatcher! Maybe do a negative sign on asset number?
-- TODO: Test capturing a neutral warehouse.
-- TODO: Make more examples: ARTY, CAP, ...
-- TODO: Check also general requests like all ground. Is this a problem for self propelled if immobile units are among the assets? Check if transport.
-- TODO: Handle the case when units of a group die during the transfer.
-- TODO: Added habours as interface for transport to from warehouses? Could make a rudimentary shipping dispatcher.
-- TODO: Add save/load capability of warehouse <==> percistance after mission restart. Difficult in lua!
-- DONE: Test capturing a neutral warehouse.
-- DONE: Add save/load capability of warehouse <==> percistance after mission restart. Difficult in lua!
-- DONE: Get cargo bay and weight from CARGO_GROUP and GROUP. No necessary any more!
-- DONE: Add possibility to set weight and cargo bay manually in AddAsset function as optional parameters.
-- DONE: Check overlapping aircraft sometimes.
@ -1787,7 +1792,7 @@ WAREHOUSE.version="0.6.4"
--- The WAREHOUSE constructor. Creates a new WAREHOUSE object from a static object. Parameters like the coalition and country are taken from the static object structure.
-- @param #WAREHOUSE self
-- @param Wrapper.Static#STATIC warehouse The physical structure of the warehouse.
-- @param Wrapper.Static#STATIC warehouse The physical structure representing the warehouse.
-- @param #string alias (Optional) Alias of the warehouse, i.e. the name it will be called when sending messages etc. Default is the name of the static
-- @return #WAREHOUSE self
function WAREHOUSE:New(warehouse, alias)
@ -1795,7 +1800,11 @@ function WAREHOUSE:New(warehouse, alias)
-- Check if just a string was given and convert to static.
if type(warehouse)=="string" then
warehouse=STATIC:FindByName(warehouse, true)
warehouse=UNIT:FindByName(warehouse)
if warehouse==nil then
env.info(string.format("No warehouse unit with name %s found trying static.", warehouse))
warehouse=STATIC:FindByName(warehouse, true)
end
end
-- Nil check.
@ -1818,7 +1827,13 @@ function WAREHOUSE:New(warehouse, alias)
-- Set some variables.
self.warehouse=warehouse
self.uid=tonumber(warehouse:GetID())
-- Increase global warehouse counter.
WAREHOUSE.db.WarehouseID=WAREHOUSE.db.WarehouseID+1
-- Set unique ID for this warehouse.
self.uid=WAREHOUSE.db.WarehouseID
--self.uid=tonumber(warehouse:GetID())
-- Closest of the same coalition but within a certain range.
local _airbase=self:GetCoordinate():GetClosestAirbase(nil, self:GetCoalition())
@ -1862,7 +1877,7 @@ function WAREHOUSE:New(warehouse, alias)
self:AddTransition("*", "Stop", "Stopped") -- Stop the warehouse.
self:AddTransition("Stopped", "Restart", "Running") -- Restart the warehouse when it was stopped before.
self:AddTransition("Loaded", "Restart", "Running") -- Restart the warehouse when assets were loaded from file before.
self:AddTransition("*", "Save", "*") -- TODO Save the warehouse state to disk.
self:AddTransition("*", "Save", "*") -- Save the warehouse state to disk.
self:AddTransition("*", "Attacked", "Attacked") -- Warehouse is under attack by enemy coalition.
self:AddTransition("Attacked", "Defeated", "Running") -- Attack by other coalition was defeated!
self:AddTransition("*", "ChangeCountry", "*") -- Change country (and coalition) of the warehouse. Warehouse is respawned!
@ -2363,6 +2378,24 @@ function WAREHOUSE:SetReportOff()
return self
end
--- Enable safe parking option, i.e. parking spots at an airbase will be considered as occupied when a client aircraft is parked there (even if the client slot is not taken by a player yet).
-- Note that also incoming aircraft can reserve/occupie parking spaces.
-- @param #WAREHOUSE self
-- @return #WAREHOUSE self
function WAREHOUSE:SetSafeParkingOn()
self.safeparking=true
return self
end
--- Disable safe parking option. Note that is the default setting.
-- @param #WAREHOUSE self
-- @return #WAREHOUSE self
function WAREHOUSE:SetSafeParkingOff()
self.safeparking=false
return self
end
--- Set interval of status updates. Note that normally only one request can be processed per time interval.
-- @param #WAREHOUSE self
-- @param #number timeinterval Time interval in seconds.
@ -3530,12 +3563,12 @@ function WAREHOUSE:onafterAddAsset(From, Event, To, group, ngroups, forceattribu
else
self:T(warehouse.wid..string.format("WARNING: Group %s is neither cargo nor transport!", group:GetName()))
end
end
-- If no assignment was given we take the assignment of the request if there is any.
if assignment==nil and request.assignment~=nil then
assignment=request.assignment
-- If no assignment was given we take the assignment of the request if there is any.
if assignment==nil and request.assignment~=nil then
assignment=request.assignment
end
end
end
@ -3588,6 +3621,7 @@ function WAREHOUSE:onafterAddAsset(From, Event, To, group, ngroups, forceattribu
else
self:E(self.wid.."ERROR: Unknown group added as asset!")
self:E({unknowngroup=group})
end
-- Update status.
@ -4620,7 +4654,7 @@ function WAREHOUSE:onafterAttacked(From, Event, To, Coalition, Country)
text=text..string.format("Deploying all %d ground assets.", nground)
-- Add self request.
self:AddRequest(self, WAREHOUSE.Descriptor.CATEGORY, Group.Category.GROUND, WAREHOUSE.Quantity.ALL, nil, nil , 0)
self:AddRequest(self, WAREHOUSE.Descriptor.CATEGORY, Group.Category.GROUND, WAREHOUSE.Quantity.ALL, nil, nil , 0, "AutoDefence")
else
text=text..string.format("No ground assets currently available.")
end
@ -6296,25 +6330,26 @@ function WAREHOUSE:_CheckRequestValid(request)
-- TODO: maybe only check if spots > 0 for the necessary terminal type? At least for FARPS.
-- Get necessary terminal type.
local termtype=self:_GetTerminal(asset.attribute)
local termtype_dep=self:_GetTerminal(asset.attribute, self:GetAirbaseCategory())
local termtype_des=self:_GetTerminal(asset.attribute, request.warehouse:GetAirbaseCategory())
-- Get number of parking spots.
local np_departure=self.airbase:GetParkingSpotsNumber(termtype)
local np_destination=request.airbase:GetParkingSpotsNumber(termtype)
local np_departure=self.airbase:GetParkingSpotsNumber(termtype_dep)
local np_destination=request.airbase:GetParkingSpotsNumber(termtype_des)
-- Debug info.
self:T(string.format("Asset attribute = %s, terminal type = %d, spots at departure = %d, destination = %d", asset.attribute, termtype, np_departure, np_destination))
self:T(string.format("Asset attribute = %s, DEPARTURE: terminal type = %d, spots = %d, DESTINATION: terminal type = %d, spots = %d", asset.attribute, termtype_dep, np_departure, termtype_des, np_destination))
-- Not enough parking at sending warehouse.
--if (np_departure < request.nasset) and not (self.category==Airbase.Category.SHIP or self.category==Airbase.Category.HELIPAD) then
if np_departure < nasset then
self:E(string.format("ERROR: Incorrect request. Not enough parking spots of terminal type %d at warehouse. Available spots %d < %d necessary.", termtype, np_departure, nasset))
self:E(string.format("ERROR: Incorrect request. Not enough parking spots of terminal type %d at warehouse. Available spots %d < %d necessary.", termtype_dep, np_departure, nasset))
valid=false
end
-- No parking at requesting warehouse.
if np_destination == 0 then
self:E(string.format("ERROR: Incorrect request. No parking spots of terminal type %d at requesting warehouse. Available spots = %d!", termtype, np_destination))
self:E(string.format("ERROR: Incorrect request. No parking spots of terminal type %d at requesting warehouse. Available spots = %d!", termtype_des, np_destination))
valid=false
end
@ -6452,7 +6487,7 @@ function WAREHOUSE:_CheckRequestValid(request)
self:T(text)
-- Get necessary terminal type for helos or transport aircraft.
local termtype=self:_GetTerminal(request.transporttype)
local termtype=self:_GetTerminal(request.transporttype, self:GetAirbaseCategory())
-- Get number of parking spots.
local np_departure=self.airbase:GetParkingSpotsNumber(termtype)
@ -6471,6 +6506,7 @@ function WAREHOUSE:_CheckRequestValid(request)
if request.transporttype==WAREHOUSE.TransportType.AIRPLANE then
-- Total number of parking spots for transport planes at destination.
termtype=self:_GetTerminal(request.transporttype, request.warehouse:GetAirbaseCategory())
local np_destination=request.airbase:GetParkingSpotsNumber(termtype)
-- Debug info.
@ -6912,13 +6948,13 @@ end
--- Get the proper terminal type based on generalized attribute of the group.
--@param #WAREHOUSE self
--@param #WAREHOUSE.Attribute _attribute Generlized attibute of unit.
--@param #number _category Airbase category.
--@return Wrapper.Airbase#AIRBASE.TerminalType Terminal type for this group.
function WAREHOUSE:_GetTerminal(_attribute)
function WAREHOUSE:_GetTerminal(_attribute, _category)
-- Default terminal is "large".
local _terminal=AIRBASE.TerminalType.OpenBig
if _attribute==WAREHOUSE.Attribute.AIR_FIGHTER then
-- Fighter ==> small.
_terminal=AIRBASE.TerminalType.FighterAircraft
@ -6928,6 +6964,15 @@ function WAREHOUSE:_GetTerminal(_attribute)
elseif _attribute==WAREHOUSE.Attribute.AIR_TRANSPORTHELO or _attribute==WAREHOUSE.Attribute.AIR_ATTACKHELO then
-- Helicopter.
_terminal=AIRBASE.TerminalType.HelicopterUsable
else
--_terminal=AIRBASE.TerminalType.OpenMedOrBig
end
-- For ships, we allow medium spots for all fixed wing aircraft. There are smaller tankers and AWACS aircraft that can use a carrier.
if _category==Airbase.Category.SHIP then
if not (_attribute==WAREHOUSE.Attribute.AIR_TRANSPORTHELO or _attribute==WAREHOUSE.Attribute.AIR_ATTACKHELO) then
_terminal=AIRBASE.TerminalType.OpenMedOrBig
end
end
return _terminal
@ -7002,20 +7047,6 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets)
table.insert(obstacles,{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?
local clients=_DATABASE.CLIENTS
for _,_client in pairs(clients) do
local client=_client --Wrapper.Client#CLIENT
env.info(string.format("FF Client name %s", client:GetName()))
local unit=UNIT:FindByName(client:GetName())
--local unit=client:GetClientGroupUnit()
local _coord=unit:GetCoordinate()
local _name=unit:GetName()
local _size=self:_GetObjectSize(client:GetClientGroupDCSUnit())
table.insert(obstacles,{coord=_coord, size=_size, name=_name, type="client"})
end
]]
end
-- Parking data for all assets.
@ -7026,7 +7057,7 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets)
local _asset=asset --#WAREHOUSE.Assetitem
-- Get terminal type of this asset
local terminaltype=self:_GetTerminal(asset.attribute)
local terminaltype=self:_GetTerminal(asset.attribute, self:GetAirbaseCategory())
-- Asset specific parking.
parking[_asset.uid]={}
@ -7048,10 +7079,17 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets)
local _toac=parkingspot.TOAC
--env.info(string.format("FF asset=%s (id=%d): needs terminal type=%d, id=%d, #obstacles=%d", _asset.templatename, _asset.uid, terminaltype, _termid, #obstacles))
-- Loop over all obstacles.
local free=true
local problem=nil
-- Safe parking using TO_AC from DCS result.
if self.safeparking and _toac then
free=false
self:T("Parking spot %d is occupied by other aircraft taking off or landing.", _termid)
end
-- Loop over all obstacles.
for _,obstacle in pairs(obstacles) do
-- Check if aircraft overlaps with any obstacle.