From 52e69cb697f605ca3877d280801d54c88413050c Mon Sep 17 00:00:00 2001 From: funkyfranky Date: Thu, 2 Aug 2018 00:29:14 +0200 Subject: [PATCH] WAREHOUSE --- Moose Development/Moose/DCS.lua | 8 +- .../Moose/Functional/Warehouse.lua | 240 +++++++++++------- 2 files changed, 159 insertions(+), 89 deletions(-) diff --git a/Moose Development/Moose/DCS.lua b/Moose Development/Moose/DCS.lua index ba6bc1c42..c8e997f5c 100644 --- a/Moose Development/Moose/DCS.lua +++ b/Moose Development/Moose/DCS.lua @@ -81,11 +81,11 @@ do -- world --- Searches a defined volume of 3d space for the specified objects within it and then can run function on each returned object. See [hoggit](https://wiki.hoggitworld.com/view/DCS_func_searchObjects). -- @function [parent=#world] searchObjects - -- @param #DCS.Object.Category objectcategory Category (can be a table) of objects to search. - -- @param #DCS word.VolumeType volume Shape of the search area/volume. - -- @param #ObjectSeachHandler handler A function that handles the search. + -- @param DCS#Object.Category objectcategory Category (can be a table) of objects to search. + -- @param DCS#word.VolumeType volume Shape of the search area/volume. + -- @param ObjectSeachHandler handler A function that handles the search. -- @param #table any Additional data. - -- @return #DCS.unit + -- @return DCS#Unit --- Returns a table of mark panels indexed numerically that are present within the mission. See [hoggit](https://wiki.hoggitworld.com/view/DCS_func_getMarkPanels) -- @function [parent=#world] getMarkPanels diff --git a/Moose Development/Moose/Functional/Warehouse.lua b/Moose Development/Moose/Functional/Warehouse.lua index 524c8b779..bb13c9d07 100644 --- a/Moose Development/Moose/Functional/Warehouse.lua +++ b/Moose Development/Moose/Functional/Warehouse.lua @@ -1,4 +1,4 @@ ---- **Functional** - (R2.4) - Manages assets of an airbase and transportation to other airbases. +--- **Functional** - (R2.4) - Manages assets of an airbase and transportation to other airbases upon request. -- -- -- Features: @@ -19,7 +19,7 @@ -- @field #string ClassName Name of the class. -- @field DCS#Coalition coalition Coalition the warehouse belongs to. -- @field Core.Point#COORDINATE coordinate Coordinate of the warehouse. --- @field Wrapper.Airbase#AIRBASE airbase Airbase the warehouse belongs to. +-- @field Wrapper.Airbase#AIRBASE homebase Airbase the warehouse belongs to. -- @field #table stock Table holding all assets in stock. Table entries are of type @{#WAREHOUSE.Stock}. -- @extends Core.Fsm#FSM @@ -58,50 +58,50 @@ WAREHOUSE = { stock = {}, } ---- Type Warehouse stock table. table.insert(self.stock, {templatename=templategroupname, category=DCScategory, type=DCStype, transport=transport, fighther=fighter, tanker=tanker, awacs=awacs, artillery=artillery}) --- @type WAREHOUSE.Stock +--- Item of the warehouse stock table. +-- @type WAREHOUSE.Stockitem -- @field #string templatename Name of the template group. --- @field DCS#Category category Category of the group. Airplane, helicopter, ... --- @field #string type Type of the group --- @field #boolean fighter If true, group is a fighter airplane. --- @field #boolean attackhelo If true, group is an attack helicopter. --- @field #boolean transport If truie, group can transport other units either by air or ground. --- @field #boolean tanker If true, group is a tanker and can refuel other air units. --- @field #boolean awacs If true, group has AWACS capabilities. --- @field #boolean artillery If true, group is an artillery unit. +-- @field DCS#Group.Category category Category of the group. +-- @field #string unittype Type of the first unit of the group as obtained by the Object.getTypeName() DCS API function. +-- @field #WAREHOUSE.Attribute attribute Generalized attribute of the group. ---- Asset descriptor. --- @field Warehouse.AssetDescriptor Assetdescriptor +--- Descriptors enumerator describing the type of the asset in stock. +-- @type WAREHOUSE.Descriptor WAREHOUSE.Descriptor = { TEMPLATENAME="templatename", CATEGORY="category", - + UNITTYPE="unittype", + ATTRIBUTE="attribute", } ---- Warehouse classes. --- @field Warehouse.Class Class -WAREHOUSE.Class = { - TRANSPORT=1, - FIGHTER=2, - TANKER=3, - AWACS=4, - ARTY=5, - ATTACKHELO=6, +--- Warehouse unit categories. These are used for +-- @type WAREHOUSE.Attribute +WAREHOUSE.Attribute = { + TRANSPORT="transport", + FIGHTER="fighter", + TANKER="tanker", + AWACS="awacs", + ARTILLERY="artillery", + ATTACKHELICOPTER="attackhelicopter", + INFANTRY="infantry", + BOMBER="bomber", + TANK="tank", } ---- Warehouse categories --- @field Category -WAREHOUSE.Category = { +--- Cargo transport type. +-- @type WAREHOUSE.TransportType +-- @field #string AIRPLANE plane blabla +WAREHOUSE.TransportType = { AIRPLANE = "plane", HELICOPTER = "helo", - GROUND = "apc", + GROUND = "ground", SHIP = "ship", TRAIN = "train", - SELF = "self", + SELFPROPELLED = "selfporpelled", } --- Warehouse class version. --- @field #number version +-- @field #string version WAREHOUSE.version="0.1.0" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -164,9 +164,13 @@ function WAREHOUSE:NewAirbase(airbase) -- @function [parent=#WAREHOUSE] Request -- @param #WAREHOUSE self -- @param Wrapper.Airbase#AIRBASE Airbase Airbase requesting supply. - -- @param #string Asset Asset that is requested. - -- @param #number nAsset Number of assets requested. Default 1. - -- @param #string TransportType Type of transport: "Plane", "Helicopter", "APC" + -- @param #WAREHOUSE.Descriptor AssetDescriptor Descriptor describing the asset that is requested. + -- @param #depends 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. + -- + -- @usage mywarehouse:Request(AIRBASE:)... --- Triggers the FSM event "Request" after a delay. -- @function [parent=#WAREHOUSE] __Request @@ -221,22 +225,24 @@ end function WAREHOUSE:onafterStatus(From, Event, To) env.info("FF checking warehouse status of airbase "..self.homebase:GetName()) - env.info(string.format("FF warehouse at %s: number of stock = %d", self.homebase:GetName(), #self.stock)) - + --env.info(string.format("FF warehouse at %s: number of stock = %d", self.homebase:GetName(), #self.stock)) + self:_DisplayStockItems(self.stock) self:__Status(30) end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + + --- On before "Request" event. Checks if the request can be fullfilled. -- @param #WAREHOUSE self -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. -- @param Wrapper.Airbase#AIRBASE Airbase Airbase requesting supply. --- @param #string AssetDescriptor Asset that is requested. Can be "templatename", ... --- @param depends AssetDescriptorvalue Value of the asset descriptor. Type depends on descriptor, i.e. could be a string, --- @param #number nAssed Number of groups of that asset requested. --- @param #string TransportType Type of transport: "Plane", "Helicopter", "APC" +-- @param #WAREHOUSE.Descriptor AssetDescriptor Descriptor describing the asset that is requested. +-- @param depends 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. -- -- @usage mywarehouse:Request(AIRBASE:)... @@ -244,78 +250,83 @@ function WAREHOUSE:onbeforeRequest(From, Event, To, Airbase, AssetDescriptor, As -- Distance from warehouse to local distance=self.coordinate:Get2DDistance(Airbase:GetCoordinate()) - - -- - local _stockrequest=self._FilterStock(self.stock, AssetDescriptor, AssetDescriptorValue) + + -- Filter the requested assets. + local _stockrequest=self:_FilterStock(self.stock, AssetDescriptor, AssetDescriptorValue) -- Asset is not in stock ==> request denied. - if #_stockrequest==0 then - self:E(self.wid..string.format("Request denied! Asset is currently not in stock.")) + if #_stockrequest < nAsset then + self:E(self.wid..string.format("Request denied! Not enought assets currently in stock. Requested %d < %d in stock.", nAsset, #_stockrequest)) return false end + -- Shortcut local _TT=TransportType:lower() - if _TT==nil then - if AssetDescriptor=="" then - end - end - if TransportType:lower() == "plane" then + if _TT == WAREHOUSE.TransportType.AIRPLANE then + -- here check the availability of transport units! + elseif _TT == WAREHOUSE.TransportType.HELICOPTER then - elseif TransportType:lower() == "helicopter" then + elseif _TT == WAREHOUSE.TransportType.GROUND then - elseif TransportType:lower() == "apc" then + elseif _TT == WAREHOUSE.TransportType.SHIP then - elseif TransportType:lower() == "train" then + elseif _TT == WAREHOUSE.TransportType.TRAIN then - elseif TransportType:lower() == "ship" then - - elseif TransportType:lower() == "self" then + elseif _TT == WAREHOUSE.TransportType.SELFPROPELLED then else self:E(self.wid..string.format("ERROR: unknown transport type requested! type = %s", tostring(TransportType))) end + return true end ---- On after "Request" event. +--- On before "Request" event. Checks if the request can be fullfilled. -- @param #WAREHOUSE self -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. -- @param Wrapper.Airbase#AIRBASE Airbase Airbase requesting supply. --- @param #string Asset Asset that is requested. --- @param #number nAssed Number of groups of that asset requested. --- @param #string TransportType Type of transport: "Plane", "Helicopter", "APC" -function WAREHOUSE:onafterRequest(From, Event, To, Airbase, Asset, nAsset, TransportType) - env.info(string.format("FF airbase %s is requesting asset %s from warehouse %s", Airbase:GetName(), Asset, self.homebase:GetName())) +-- @param #WAREHOUSE.Descriptor AssetDescriptor Descriptor describing the asset that is requested. +-- @param depends 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. +-- +-- @usage mywarehouse:Request(AIRBASE:)... +function WAREHOUSE:onafterRequest(From, Event, To, Airbase, AssetDescriptor, AssetDescriptorValue, nAsset, TransportType) + env.info(self.wid..string.format("Airbase %s requesting asset %s = %s.", Airbase:GetName(), tostring(AssetDescriptor), tostring(AssetDescriptorValue))) local nAsset=nAsset or 1 - if TransportType=="Air" then + -- Filter the requested assets. + local _stock=self:_FilterStock(self.stock, AssetDescriptor, AssetDescriptorValue) - -- Get a random template from the stock list. - local _chosenone=math.random(#self.stock) --#WAREHOUSE.Stock + -- Get a random template from the stock list. + local _chosenone=math.random(#_stock) - - - -- Select template group name. - --TODO: FILTER HERE! - local template=self.stock[_chosenone].templatename + -- Select template group name. + local template=_stock[_chosenone].templatename + + + if TransportType==WAREHOUSE.TransportType.AIRPLANE then + if template then -- Spawn plane at warehouse homebase. + --TODO: this is wrong. we need to filter the transports and get the right template! local Plane=SPAWN:New(template):SpawnAtAirbase(Airbase, nil, nil, nil, false) if Plane==nil then -- Plane was not spawned correctly. Try again in 60 seconds. - self:__Request( 60, Airbase, Asset, nAsset, TransportType) + self:__Request(60, Airbase, AssetDescriptor, AssetDescriptorValue, nAsset, TransportType) return else - -- Remove chosen plane from list. - table.remove(self.stock,_chosenone) + -- Remove chosen asset from list. + table.remove(self.stock,_stock.pos) end -- New empty cargo set. @@ -354,8 +365,13 @@ function WAREHOUSE:onafterRequest(From, Event, To, Airbase, Asset, nAsset, Trans -- Trigger Delivered event. warehouse:__Delivered(1, group) end - + + else + self:E(self.wid.."ERROR: template does not exist!") end + + else + self:E(self.wid.."ERROR: unknown transport type!") end end @@ -406,25 +422,60 @@ function WAREHOUSE:AddAsset(templategroupname, ngroups, istransport) env.info(string.format("display name = %s", DCSdisplay)) env.info(string.format("category = %s", DCScategory)) env.info(string.format("type = %s", DCStype)) - env.info(string.format("attribute infantry = %s", tostring(group:HasAttribute("Infantry")))) self:E({desc=DCSdesc}) + -- Get generalized attributes. local transport=group:HasAttribute("Transport helicopters") or group:HasAttribute("Transports") or group:HasAttribute("Infantry carriers") local fighter=group:HasAttribute("Fighters") or group:HasAttribute("Interceptors") or group:HasAttribute("Multirole fighters") local tanker=group:HasAttribute("Tankers") local awacs=group:HasAttribute("AWACS") - local apc=group:HasAttribute("Infantry carriers") local artillery=group:HasAttribute("Artillery") - env.info(string.format("attribute transport = %s", tostring(transport))) - env.info(string.format("attribute apc = %s", tostring(apc))) - env.info(string.format("attribute figther = %s", tostring(fighter))) - env.info(string.format("attribute tanker = %s", tostring(tanker))) - env.info(string.format("attribute awacs = %s", tostring(awacs))) - env.info(string.format("attribute artillery = %s", tostring(artillery))) + local infantry=group:HasAttribute("Infantry") + local attackhelicopter=group:HasAttribute("Attack helicopters") + local bomber=group:HasAttribute("Bombers") + local tank=group:HasAttribute("Old Tanks") or group:HasAttribute("Modern Tanks") + + -- Debug output. + env.info(string.format("attribute transport = %s", tostring(transport))) + env.info(string.format("attribute figther = %s", tostring(fighter))) + env.info(string.format("attribute tanker = %s", tostring(tanker))) + env.info(string.format("attribute awacs = %s", tostring(awacs))) + env.info(string.format("attribute artillery = %s", tostring(artillery))) + env.info(string.format("attribute infantry = %s", tostring(infantry))) + env.info(string.format("attribute attackhelo = %s", tostring(attackhelicopter))) + env.info(string.format("attribute bomber = %s", tostring(bomber))) + env.info(string.format("attribute tank = %s", tostring(tank))) + + + local attribute="unknown" --#WAREHOUSE.Attribute + if transport then + attribute=WAREHOUSE.Attribute.TRANSPORT + elseif fighter then + attribute=WAREHOUSE.Attribute.FIGHTER + elseif tanker then + attribute=WAREHOUSE.Attribute.TANKER + elseif awacs then + attribute=WAREHOUSE.Attribute.AWACS + elseif artillery then + attribute=WAREHOUSE.Attribute.ARTILLERY + elseif infantry then + attribute=WAREHOUSE.Attribute.INFANTRY + elseif attackhelicopter then + attribute=WAREHOUSE.Attribute.ATTACKHELICOPTER + elseif bomber then + attribute=WAREHOUSE.Attribute.BOMBER + elseif tank then + attribute=WAREHOUSE.Attribute.TANK + end -- Add this n times to the table. for i=1,n do - table.insert(self.stock, {templatename=templategroupname, category=DCScategory, type=DCStype, transport=transport, fighther=fighter, tanker=tanker, awacs=awacs, artillery=artillery}) + local stockitem={} --#WAREHOUSE.Stockitem + stockitem.templatename=templategroupname + stockitem.category=DCScategory + stockitem.attribute=attribute + stockitem.unittype=DCStype + table.insert(self.stock, stockitem) end else @@ -441,15 +492,19 @@ end --- Filter stock assets by table entry. -- @param #WAREHOUSE self --- @param #WAREHOUSE.Stock stock +-- @param #table stock Table holding all assets in stock of the warehouse. Each entry is of type @{#WAREHOUSE.Stockitem}. -- @param #string item Descriptor --- @param depends value +-- @param depends value Value of the descriptor. +-- @return #table Filtered stock items table. function WAREHOUSE:_FilterStock(stock, item, value) + -- Filtered array. local filtered={} - for _,_stock in pairs(stock) do + -- Loop over stock items. + for _i,_stock in ipairs(stock) do if _stock[item]==value then + _stock.pos=_i table.insert(filtered, _stock) end end @@ -457,6 +512,21 @@ function WAREHOUSE:_FilterStock(stock, item, value) return filtered end +--- Filter stock assets by table entry. +-- @param #WAREHOUSE self +-- @param #table stock Table holding all assets in stock of the warehouse. Each entry is of type @{#WAREHOUSE.Stockitem}. +function WAREHOUSE:_DisplayStockItems(stock) + + local text=self.wid..string.format("Warehouse %s stock assets:\n", self.homebase:GetName()) + for _,_stock in pairs(stock) do + local mystock=_stock --#WAREHOUSE.Stockitem + text=text..string.format("template = %s, category = %d, unittype = %s, attribute = %s\n", mystock.templatename, mystock.category, mystock.unittype, mystock.attribute) + end + + env.info(text) + MESSAGE:New(text,30):ToAll() +end + ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------