Merge remote-tracking branch 'origin/master' into develop

This commit is contained in:
Applevangelist 2024-08-10 09:58:49 +02:00
commit 50bbea327b
9 changed files with 508 additions and 108 deletions

View File

@ -1211,6 +1211,43 @@ function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, Category
return self return self
end end
--- Get a generic static cargo group template from scratch for dynamic cargo spawns register. Does not register the template!
-- @param #DATABASE self
-- @param #string Name Name of the static.
-- @param #string Typename Typename of the static. Defaults to "container_cargo".
-- @param #number Mass Mass of the static. Defaults to 0.
-- @param #number Coalition Coalition of the static. Defaults to coalition.side.BLUE.
-- @param #number Country Country of the static. Defaults to country.id.GERMANY.
-- @return #table Static template table.
function DATABASE:_GetGenericStaticCargoGroupTemplate(Name,Typename,Mass,Coalition,Country)
local StaticTemplate = {}
StaticTemplate.name = Name or "None"
StaticTemplate.units = { [1] = {
name = Name,
resourcePayload = {
["weapons"] = {},
["aircrafts"] = {},
["gasoline"] = 0,
["diesel"] = 0,
["methanol_mixture"] = 0,
["jet_fuel"] = 0,
},
["mass"] = Mass or 0,
["category"] = "Cargos",
["canCargo"] = true,
["type"] = Typename or "container_cargo",
["rate"] = 100,
["y"] = 0,
["x"] = 0,
["heading"] = 0,
}}
StaticTemplate.CategoryID = "static"
StaticTemplate.CoalitionID = Coalition or coalition.side.BLUE
StaticTemplate.CountryID = Country or country.id.GERMANY
UTILS.PrintTableToLog(StaticTemplate)
return StaticTemplate
end
--- Get static group template. --- Get static group template.
-- @param #DATABASE self -- @param #DATABASE self
-- @param #string StaticName Name of the static. -- @param #string StaticName Name of the static.

View File

@ -199,6 +199,7 @@
-- --
-- * @{#SPAWN.InitRepeat}() or @{#SPAWN.InitRepeatOnLanding}(): This method is used to re-spawn automatically the same group after it has landed. -- * @{#SPAWN.InitRepeat}() or @{#SPAWN.InitRepeatOnLanding}(): This method is used to re-spawn automatically the same group after it has landed.
-- * @{#SPAWN.InitRepeatOnEngineShutDown}(): This method is used to re-spawn automatically the same group after it has landed and it shuts down the engines at the ramp. -- * @{#SPAWN.InitRepeatOnEngineShutDown}(): This method is used to re-spawn automatically the same group after it has landed and it shuts down the engines at the ramp.
-- * @{#SPAWN.StopRepeat}(): This method is used to stop the repeater.
-- --
-- ### Link-16 Datalink STN and SADL IDs (limited at the moment to F15/16/18/AWACS/Tanker/B1B, but not the F15E for clients, SADL A10CII only) -- ### Link-16 Datalink STN and SADL IDs (limited at the moment to F15/16/18/AWACS/Tanker/B1B, but not the F15E for clients, SADL A10CII only)
-- --
@ -1411,6 +1412,30 @@ function SPAWN:InitArray( SpawnAngle, SpawnWidth, SpawnDeltaX, SpawnDeltaY )
return self return self
end end
--- Stop the SPAWN InitRepeat function (EVENT handler for takeoff, land and engine shutdown)
-- @param #SPAWN self
-- @return #SPAWN self
-- @usage
-- local spawn = SPAWN:New("Template Group")
-- :InitRepeatOnEngineShutDown()
-- local plane = spawn:Spawn() -- it is important that we keep the SPAWN object and do not overwrite it with the resulting GROUP object by just calling :Spawn()
--
-- -- later on
-- spawn:StopRepeat()
function SPAWN:StopRepeat()
if self.Repeat then
self:UnHandleEvent(EVENTS.Takeoff)
self:UnHandleEvent(EVENTS.Land)
end
if self.RepeatOnEngineShutDown then
self:UnHandleEvent(EVENTS.EngineShutdown)
end
self.Repeat = false
self.RepeatOnEngineShutDown = false
self.RepeatOnLanding = false
return self
end
do -- AI methods do -- AI methods
--- Turns the AI On or Off for the @{Wrapper.Group} when spawning. --- Turns the AI On or Off for the @{Wrapper.Group} when spawning.

View File

@ -189,6 +189,7 @@ function SPAWNSTATIC:NewFromType(StaticType, StaticCategory, CountryID)
self.InitStaticCategory=StaticCategory self.InitStaticCategory=StaticCategory
self.CountryID=CountryID or country.id.USA self.CountryID=CountryID or country.id.USA
self.SpawnTemplatePrefix=self.InitStaticType self.SpawnTemplatePrefix=self.InitStaticType
self.TemplateStaticUnit = {}
self.InitStaticCoordinate=COORDINATE:New(0, 0, 0) self.InitStaticCoordinate=COORDINATE:New(0, 0, 0)
self.InitStaticHeading=0 self.InitStaticHeading=0
@ -196,6 +197,61 @@ function SPAWNSTATIC:NewFromType(StaticType, StaticCategory, CountryID)
return self return self
end end
--- (Internal/Cargo) Init the resource table for STATIC object that should be spawned containing storage objects.
-- NOTE that you have to init many other parameters as the resources.
-- @param #SPAWNSTATIC self
-- @param #number CombinedWeight The weight this cargo object should have (some have fixed weights!), defaults to 1kg.
-- @return #SPAWNSTATIC self
function SPAWNSTATIC:_InitResourceTable(CombinedWeight)
if not self.TemplateStaticUnit.resourcePayload then
self.TemplateStaticUnit.resourcePayload = {
["weapons"] = {},
["aircrafts"] = {},
["gasoline"] = 0,
["diesel"] = 0,
["methanol_mixture"] = 0,
["jet_fuel"] = 0,
}
end
self:InitCargo(true)
self:InitCargoMass(CombinedWeight or 1)
return self
end
--- (User/Cargo) Add to resource table for STATIC object that should be spawned containing storage objects. Inits the object table if necessary and sets it to be cargo for helicopters.
-- @param #SPAWNSTATIC self
-- @param #string Type Type of cargo. Known types are: STORAGE.Type.WEAPONS, STORAGE.Type.LIQUIDS, STORAGE.Type.AIRCRAFT. Liquids are fuel.
-- @param #string Name Name of the cargo type. Liquids can be STORAGE.LiquidName.JETFUEL, STORAGE.LiquidName.GASOLINE, STORAGE.LiquidName.MW50 and STORAGE.LiquidName.DIESEL. The currently available weapon items are available in the `ENUMS.Storage.weapons`, e.g. `ENUMS.Storage.weapons.bombs.Mk_82Y`. Aircraft go by their typename.
-- @param #number Amount of tons (liquids) or number (everything else) to add.
-- @param #number CombinedWeight Combined weight to be set to this static cargo object. NOTE - some static cargo objects have fixed weights!
-- @return #SPAWNSTATIC self
function SPAWNSTATIC:AddCargoResource(Type,Name,Amount,CombinedWeight)
if not self.TemplateStaticUnit.resourcePayload then
self:_InitResourceTable(CombinedWeight)
end
if Type == STORAGE.Type.LIQUIDS and type(Name) == "string" then
self.TemplateStaticUnit.resourcePayload[Name] = Amount
else
self.TemplateStaticUnit.resourcePayload[Type] = {
[Name] = {
["amount"] = Amount,
}
}
end
UTILS.PrintTableToLog(self.TemplateStaticUnit)
return self
end
--- (User/Cargo) Resets resource table to zero for STATIC object that should be spawned containing storage objects. Inits the object table if necessary and sets it to be cargo for helicopters.
-- Handy if you spawn from cargo statics which have resources already set.
-- @param #SPAWNSTATIC self
-- @return #SPAWNSTATIC self
function SPAWNSTATIC:ResetCargoResources()
self.TemplateStaticUnit.resourcePayload = nil
self:_InitResourceTable()
return self
end
--- Initialize heading of the spawned static. --- Initialize heading of the spawned static.
-- @param #SPAWNSTATIC self -- @param #SPAWNSTATIC self
-- @param Core.Point#COORDINATE Coordinate Position where the static is spawned. -- @param Core.Point#COORDINATE Coordinate Position where the static is spawned.
@ -317,6 +373,25 @@ function SPAWNSTATIC:InitLinkToUnit(Unit, OffsetX, OffsetY, OffsetAngle)
return self return self
end end
--- Allows to place a CallFunction hook when a new static spawns.
-- The provided method will be called when a new group is spawned, including its given parameters.
-- The first parameter of the SpawnFunction is the @{Wrapper.Static#STATIC} that was spawned.
-- @param #SPAWNSTATIC self
-- @param #function SpawnCallBackFunction The function to be called when a group spawns.
-- @param SpawnFunctionArguments A random amount of arguments to be provided to the function when the group spawns.
-- @return #SPAWNSTATIC self
function SPAWNSTATIC:OnSpawnStatic( SpawnCallBackFunction, ... )
self:F( "OnSpawnStatic" )
self.SpawnFunctionHook = SpawnCallBackFunction
self.SpawnFunctionArguments = {}
if arg then
self.SpawnFunctionArguments = arg
end
return self
end
--- Spawn a new STATIC object. --- Spawn a new STATIC object.
-- @param #SPAWNSTATIC self -- @param #SPAWNSTATIC self
-- @param #number Heading (Optional) The heading of the static, which is a number in degrees from 0 to 360. Default is the heading of the template. -- @param #number Heading (Optional) The heading of the static, which is a number in degrees from 0 to 360. Default is the heading of the template.
@ -488,7 +563,7 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
-- ED's dirty way to spawn FARPS. -- ED's dirty way to spawn FARPS.
Static=coalition.addGroup(CountryID, -1, TemplateGroup) Static=coalition.addGroup(CountryID, -1, TemplateGroup)
-- Currently DCS 2.8 does not trigger birth events if FAPRS are spawned! -- Currently DCS 2.8 does not trigger birth events if FARPS are spawned!
-- We create such an event. The airbase is registered in Core.Event -- We create such an event. The airbase is registered in Core.Event
local Event = { local Event = {
id = EVENTS.Birth, id = EVENTS.Birth,
@ -503,6 +578,12 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
self:T2({Template=Template}) self:T2({Template=Template})
Static=coalition.addStaticObject(CountryID, Template) Static=coalition.addStaticObject(CountryID, Template)
end end
-- If there is a SpawnFunction hook defined, call it.
if self.SpawnFunctionHook then
-- delay calling this for .3 seconds so that it hopefully comes after the BIRTH event of the group.
self:ScheduleOnce(0.3,self.SpawnFunctionHook,mystatic, unpack(self.SpawnFunctionArguments))
end
return mystatic return mystatic
end end

View File

@ -1,5 +1,7 @@
--- **Functional** - Manage and track client slots easily to add your own client-based menus and modules to. --- **Functional** - Manage and track client slots easily to add your own client-based menus and modules to.
-- --
-- The @{#CLIENTWATCH} class adds a simplified way to create scripts and menus for individual clients. Instead of creating large algorithms and juggling multiple event handlers, you can simply provide one or more prefixes to the class and use the callback functions on spawn, despawn, and any aircraft related events to script to your hearts content.
--
-- === -- ===
-- --
-- ## Features: -- ## Features:
@ -10,51 +12,30 @@
-- * More reliable aircraft lost events for when DCS thinks the aircraft id dead but a dead event fails to trigger -- * More reliable aircraft lost events for when DCS thinks the aircraft id dead but a dead event fails to trigger
-- * Easily manage clients spawned in dynamic slots -- * Easily manage clients spawned in dynamic slots
-- --
-- ===
--
-- ## Missions:
--
-- ## [MOOSE - ALL Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS)
--
-- ===
--
-- The @{#CLIENTWATCH} class adds a simplified way to create scripts and menus for individual clients. Instead of creating large algorithms and juggling multiple event handlers, you can simply provide one or more prefixes to the class and use the callback functions on spawn, despawn, and any aircraft related events to script to your hearts content.
--
-- ==== -- ====
-- --
-- # YouTube Channel
--
-- ### [MOOSE YouTube Channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg)
--
-- ===
--
-- ### Author: **Statua** -- ### Author: **Statua**
-- --
-- ### Contributions: **FlightControl**: Wrapper.CLIENT -- ### Contributions: **FlightControl**: Wrapper.CLIENT
-- --
-- === -- ====
--
-- @module Functional.ClientWatch -- @module Functional.ClientWatch
-- @image ClientWatch.JPG -- @image clientwatch.jpg
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- CLIENTWATCH class --- CLIENTWATCH class
-- @type CLIENTWATCH -- @type CLIENTWATCH
-- @field #string ClassName Name of the class. -- @field #string ClassName Name of the class.
-- @field #boolean Debug Write Debug messages to DCS log file and send Debug messages to all players. -- @field #boolean Debug Write Debug messages to DCS log file and send Debug messages to all players.
-- @field #string lid String for DCS log file. -- @field #string lid String for DCS log file.
-- @extends Core.Fsm#FSM_CONTROLLABLE -- @extends Core.Fsm#FSM_CONTROLLABLE
--
--- Manage and track client slots easily to add your own client-based menus and modules to. --- Manage and track client slots easily to add your own client-based menus and modules to.
-- --
-- ## Creating a new instance -- ## Creating a new instance
-- --
-- To start, you must first create a new instance of the client manager and provide it with either a Wrapper.Client#CLIENT object, a string prefix of the unit name, or a table of string prefixes for unit names. These are used to capture the client unit when it spawns and apply your scripted functions to it. Only fixed wing and rotary wing aircraft controlled by players can be used by this class. -- To start, you must first create a new instance of the client manager and provide it with either a Wrapper.Client#CLIENT object, a string prefix of the unit name, or a table of string prefixes for unit names. These are used to capture the client unit when it spawns and apply your scripted functions to it. Only fixed wing and rotary wing aircraft controlled by players can be used by this class.
-- **This will not work if the client aircraft is alive!**
---
--**This will not work if the client aircraft is alive!**
-- --
-- ### Examples -- ### Examples
-- --
@ -125,34 +106,40 @@
-- --
-- ### Examples -- ### Examples
-- --
-- -- Show a message to player when they take damage from a weapon -- -- Show a message to player when they take damage from a weapon
-- local clientInstance = CLIENTWATCH:New("Rotary") -- local clientInstance = CLIENTWATCH:New("Rotary")
-- function clientInstance:OnAfterSpawn(From,Event,To,ClientObject) -- function clientInstance:OnAfterSpawn(From,Event,To,ClientObject)
-- function ClientObject:OnAfterHit(From,Event,To,EventData) -- function ClientObject:OnAfterHit(From,Event,To,EventData)
-- local typeShooter = EventData.IniTypeName -- local typeShooter = EventData.IniTypeName
-- local nameWeapon = EventData.weapon_name -- local nameWeapon = EventData.weapon_name
-- MESSAGE:New("A "..typeShooter.." hit you with a "..nameWeapon,20):ToUnit(ClientObject.Unit) -- MESSAGE:New("A "..typeShooter.." hit you with a "..nameWeapon,20):ToUnit(ClientObject.Unit)
-- end -- end
-- end -- end
--
-- --
-- @field #CLIENTWATCH -- @field #CLIENTWATCH
CLIENTWATCHTools = {}
CLIENTWATCH = {} CLIENTWATCH = {}
CLIENTWATCH.ClassName = "CLIENTWATCH" CLIENTWATCH.ClassName = "CLIENTWATCH"
CLIENTWATCH.Debug = false CLIENTWATCH.Debug = false
CLIENTWATCH.lid = nil CLIENTWATCH.lid = nil
--- CLIENTWATCH version.
-- @field #number version
CLIENTWATCH.version="1.0.0"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- @type CLIENTWATCHTools
-- @field #table Unit Wrapper.UNIT of the cient object
-- @field #table Group Wrapper.GROUP of the cient object
-- @field #table Client Wrapper.CLIENT of the cient object
-- @field #string PlayerName Name of the player controlling the client object
-- @field #string UnitName Name of the unit that is the client object
-- @field #string GroupName Name of the group the client object belongs to
CLIENTWATCHTools = {}
--- CLIENTWATCH version
-- @field #string version
CLIENTWATCH.version="1.0.1"
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Creates a new instance of CLIENTWATCH to add scripts to. Can be used multiple times with the same client/prefixes if you need it for multiple scripts. --- Creates a new instance of CLIENTWATCH to add scripts to. Can be used multiple times with the same client/prefixes if you need it for multiple scripts.
-- @param #CLIENTWATCH self -- @param #CLIENTWATCH self
-- @param Provide either a Wrapper.Client#CLIENT of the client you want to use, a #string prefix of the DCS UNIT name, or a #table of #string prefixes for multiple DCS UNIT names -- @param #string, #table, or Wrapper.Client#CLIENT client Takes multiple inputs. If provided a #string, it will watch for clients whos UNIT NAME or GROUP NAME matches part of the #string as a prefix. You can also provide it with a #table containing multiple #string prefixes. Lastly, you can provide it with a Wrapper.Client#CLIENT of the specific client you want to apply this to.
-- @return #CLIENTWATCH self -- @return #CLIENTWATCH self
function CLIENTWATCH:New(client) function CLIENTWATCH:New(client)
--Init FSM --Init FSM
@ -160,6 +147,15 @@ function CLIENTWATCH:New(client)
self:SetStartState( "Idle" ) self:SetStartState( "Idle" )
self:AddTransition( "*", "Spawn", "*" ) self:AddTransition( "*", "Spawn", "*" )
--- User function for OnAfter "Spawn" event.
-- @function [parent=#CLIENTWATCH] OnAfterSpawn
-- @param #CLIENTWATCH self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable Controllable of the group.
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #table clientObject Custom object that handles events and stores Moose object data. See top documentation for more details.
--Set up spawn tracking --Set up spawn tracking
if type(client) == "table" or type(client) == "string" then if type(client) == "table" or type(client) == "string" then
if type(client) == "table" then if type(client) == "table" then
@ -169,9 +165,12 @@ function CLIENTWATCH:New(client)
self.ClientName = client:GetName() self.ClientName = client:GetName()
self:HandleEvent(EVENTS.Birth) self:HandleEvent(EVENTS.Birth)
function self:OnEventBirth(eventdata) function self:OnEventBirth(eventdata)
if self.ClientName == eventdata.IniUnitName and eventdata.IniCategory <= 1 then if self.Debug then UTILS.PrintTableToLog(eventdata) end
local clientObject = CLIENTWATCHTools:_newClient(eventdata) if eventdata.IniCategory and eventdata.IniCategory <= 1 then
self:Spawn(clientObject) if self.ClientName == eventdata.IniUnitName then
local clientObject = CLIENTWATCHTools:_newClient(eventdata)
self:Spawn(clientObject)
end
end end
end end
@ -188,11 +187,14 @@ function CLIENTWATCH:New(client)
if tableValid then if tableValid then
self:HandleEvent(EVENTS.Birth) self:HandleEvent(EVENTS.Birth)
function self:OnEventBirth(eventdata) function self:OnEventBirth(eventdata)
if self.Debug then UTILS.PrintTableToLog(eventdata) end
for _,entry in pairs(client) do for _,entry in pairs(client) do
if string.match(eventdata.IniUnitName,entry) and eventdata.IniCategory == 1 then if eventdata.IniCategory and eventdata.IniCategory <= 1 then
local clientObject = CLIENTWATCHTools:_newClient(eventdata) if string.match(eventdata.IniUnitName,entry) or string.match(eventdata.IniGroupName,entry) then
self:Spawn(clientObject) local clientObject = CLIENTWATCHTools:_newClient(eventdata)
break self:Spawn(clientObject)
break
end
end end
end end
end end
@ -203,9 +205,12 @@ function CLIENTWATCH:New(client)
--SOLO STRING --SOLO STRING
self:HandleEvent(EVENTS.Birth) self:HandleEvent(EVENTS.Birth)
function self:OnEventBirth(eventdata) function self:OnEventBirth(eventdata)
if string.match(eventdata.IniUnitName,client) and eventdata.IniCategory == 1 then if self.Debug then UTILS.PrintTableToLog(eventdata) end
local clientObject = CLIENTWATCHTools:_newClient(eventdata) if eventdata.IniCategory and eventdata.IniCategory <= 1 then
self:Spawn(clientObject) if string.match(eventdata.IniUnitName,client) or string.match(eventdata.IniGroupName,client) then
local clientObject = CLIENTWATCHTools:_newClient(eventdata)
self:Spawn(clientObject)
end
end end
end end
end end

View File

@ -24,7 +24,7 @@
-- @module Ops.CTLD -- @module Ops.CTLD
-- @image OPS_CTLD.jpg -- @image OPS_CTLD.jpg
-- Last Update July 2024 -- Last Update Aug 2024
do do
@ -46,6 +46,7 @@ do
-- @field #string Subcategory Sub-category name. -- @field #string Subcategory Sub-category name.
-- @field #boolean DontShowInMenu Show this item in menu or not. -- @field #boolean DontShowInMenu Show this item in menu or not.
-- @field Core.Zone#ZONE Location Location (if set) where to get this cargo item. -- @field Core.Zone#ZONE Location Location (if set) where to get this cargo item.
-- @field #table ResourceMap Resource Map information table if it has been set for static cargo items.
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- ---
@ -122,14 +123,31 @@ CTLD_CARGO = {
self.Mark = nil self.Mark = nil
self.Subcategory = Subcategory or "Other" self.Subcategory = Subcategory or "Other"
self.DontShowInMenu = DontShowInMenu or false self.DontShowInMenu = DontShowInMenu or false
self.ResourceMap = nil
if type(Location) == "string" then if type(Location) == "string" then
Location = ZONE:New(Location) Location = ZONE:New(Location)
end end
self.Location = Location self.Location = Location
return self return self
end end
--- Query Location. --- Add Resource Map information table
-- @param #CTLD_CARGO self
-- @param #table ResourceMap
-- @return #CTLD_CARGO self
function CTLD_CARGO:SetStaticResourceMap(ResourceMap)
self.ResourceMap = ResourceMap
return self
end
--- Get Resource Map information table
-- @param #CTLD_CARGO self
-- @return #table ResourceMap
function CTLD_CARGO:GetStaticResourceMap()
return self.ResourceMap
end
--- Query Location.
-- @param #CTLD_CARGO self -- @param #CTLD_CARGO self
-- @return Core.Zone#ZONE location or `nil` if not set -- @return Core.Zone#ZONE location or `nil` if not set
function CTLD_CARGO:GetLocation() function CTLD_CARGO:GetLocation()
@ -752,10 +770,37 @@ do
-- my_ctld.nobuildmenu = false -- if set to true effectively enforces to have engineers build/repair stuff for you. -- my_ctld.nobuildmenu = false -- if set to true effectively enforces to have engineers build/repair stuff for you.
-- my_ctld.RadioSound = "beacon.ogg" -- -- this sound will be hearable if you tune in the beacon frequency. Add the sound file to your miz. -- my_ctld.RadioSound = "beacon.ogg" -- -- this sound will be hearable if you tune in the beacon frequency. Add the sound file to your miz.
-- my_ctld.RadioSoundFC3 = "beacon.ogg" -- this sound will be hearable by FC3 users (actually all UHF radios); change to something like "beaconsilent.ogg" and add the sound file to your miz if you don't want to annoy FC3 pilots. -- my_ctld.RadioSoundFC3 = "beacon.ogg" -- this sound will be hearable by FC3 users (actually all UHF radios); change to something like "beaconsilent.ogg" and add the sound file to your miz if you don't want to annoy FC3 pilots.
-- -- my_ctld.enableChinhookGCLoading = true -- this will effectively suppress the crate load and drop menus for CTLD for the Chinhook
-- ## 2.1 User functions
-- --
-- ### 2.1.1 Adjust or add chopper unit-type capabilities -- ## 2.1 CH-47 Chinhook support
--
-- The Chinhook comes with the option to use the ground crew menu to load and unload cargo into the Helicopter itself for better immersion. As well, it can sling-load cargo from ground. The cargo you can actually **create**
-- from this menu is limited to contain items from the airbase or FARP's resources warehouse and can take a number of shapes (static shapes in the category of cargo) independent of their contents. If you unload this
-- kind of cargo with the ground crew, the contents will be "absorbed" into the airbase or FARP you landed at, and the cargo static will be removed after ca 2 mins.
--
-- ## 2.1.1 Moose CTLD created crate cargo
--
-- Given the correct shape, Moose created cargo can be either loaded with the ground crew or via the F10 CTLD menu. **It is strongly recommend to either use the ground crew or CTLD to load/unload cargo**. Mix and match will not work here.
-- Static shapes loadable *into* the Chinhook are at the time of writing:
--
-- * Ammo crate (type "ammo_cargo")
-- * M117 bomb crate (type name "m117_cargo")
-- * Dual shell fuel barrels (type name "barrels")
-- * UH-1H net (type name "uh1h_cargo")
--
-- All other kinds of cargo can be sling-loaded.
--
-- ## 2.1.2 Recommended settings
--
-- my_ctld.basetype = "ammo_cargo"
-- my_ctld.forcehoverload = false -- no hover autoload, leads to cargo complications with ground crew created cargo items
-- my_ctld.pilotmustopendoors = true -- crew must open back loading door 50% (horizontal) or more
-- my_ctld.enableslingload = true -- will set cargo items as sling-loadable
-- my_ctld.enableChinhookGCLoading = true -- will effectively suppress the crate load and drop menus for CTLD for the Chinhook
--
-- ## 2.2 User functions
--
-- ### 2.2.1 Adjust or add chopper unit-type capabilities
-- --
-- Use this function to adjust what a heli type can or cannot do: -- Use this function to adjust what a heli type can or cannot do:
-- --
@ -780,8 +825,12 @@ do
-- ["MH-60R"] = {type="MH-60R", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16, cargoweightlimit = 3500}, -- 4t cargo, 20 (unsec) seats -- ["MH-60R"] = {type="MH-60R", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16, cargoweightlimit = 3500}, -- 4t cargo, 20 (unsec) seats
-- ["SH-60B"] = {type="SH-60B", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16, cargoweightlimit = 3500}, -- 4t cargo, 20 (unsec) seats -- ["SH-60B"] = {type="SH-60B", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16, cargoweightlimit = 3500}, -- 4t cargo, 20 (unsec) seats
-- ["Bronco-OV-10A"] = {type="Bronco-OV-10A", crates= false, troops=true, cratelimit = 0, trooplimit = 5, length = 13, cargoweightlimit = 1450}, -- ["Bronco-OV-10A"] = {type="Bronco-OV-10A", crates= false, troops=true, cratelimit = 0, trooplimit = 5, length = 13, cargoweightlimit = 1450},
-- ["Bronco-OV-10A"] = {type="Bronco-OV-10A", crates= false, troops=true, cratelimit = 0, trooplimit = 5, length = 13, cargoweightlimit = 1450},
-- ["OH-6A"] = {type="OH-6A", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 7, cargoweightlimit = 550},
-- ["OH-58D"] = {type="OH58D", crates=false, troops=false, cratelimit = 0, trooplimit = 0, length = 14, cargoweightlimit = 400},
-- ["CH-47Fbl1"] = {type="CH-47Fbl1", crates=true, troops=true, cratelimit = 4, trooplimit = 31, length = 20, cargoweightlimit = 8000},
-- --
-- ### 2.1.2 Activate and deactivate zones -- ### 2.2.2 Activate and deactivate zones
-- --
-- Activate a zone: -- Activate a zone:
-- --
@ -793,7 +842,7 @@ do
-- -- Deactivate zone called Name of type #CTLD.CargoZoneType ZoneType: -- -- Deactivate zone called Name of type #CTLD.CargoZoneType ZoneType:
-- my_ctld:DeactivateZone(Name,CTLD.CargoZoneType.DROP) -- my_ctld:DeactivateZone(Name,CTLD.CargoZoneType.DROP)
-- --
-- ## 2.1.3 Limit and manage available resources -- ## 2.2.3 Limit and manage available resources
-- --
-- When adding generic cargo types, you can effectively limit how many units can be dropped/build by the players, e.g. -- When adding generic cargo types, you can effectively limit how many units can be dropped/build by the players, e.g.
-- --
@ -1251,12 +1300,12 @@ CTLD.UnitTypeCapabilities = {
["Bronco-OV-10A"] = {type="Bronco-OV-10A", crates= false, troops=true, cratelimit = 0, trooplimit = 5, length = 13, cargoweightlimit = 1450}, ["Bronco-OV-10A"] = {type="Bronco-OV-10A", crates= false, troops=true, cratelimit = 0, trooplimit = 5, length = 13, cargoweightlimit = 1450},
["OH-6A"] = {type="OH-6A", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 7, cargoweightlimit = 550}, ["OH-6A"] = {type="OH-6A", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 7, cargoweightlimit = 550},
["OH-58D"] = {type="OH58D", crates=false, troops=false, cratelimit = 0, trooplimit = 0, length = 14, cargoweightlimit = 400}, ["OH-58D"] = {type="OH58D", crates=false, troops=false, cratelimit = 0, trooplimit = 0, length = 14, cargoweightlimit = 400},
["CH-47Fbl1"] = {type="CH-47Fbl1", crates=true, troops=true, cratelimit = 4, trooplimit = 31, length = 30, cargoweightlimit = 8000}, ["CH-47Fbl1"] = {type="CH-47Fbl1", crates=true, troops=true, cratelimit = 4, trooplimit = 31, length = 20, cargoweightlimit = 8000},
} }
--- CTLD class version. --- CTLD class version.
-- @field #string version -- @field #string version
CTLD.version="1.0.56" CTLD.version="1.0.58"
--- Instantiate a new CTLD. --- Instantiate a new CTLD.
-- @param #CTLD self -- @param #CTLD self
@ -1435,6 +1484,9 @@ function CTLD:New(Coalition, Prefixes, Alias)
self.movecratesbeforebuild = true self.movecratesbeforebuild = true
self.surfacetypes = {land.SurfaceType.LAND,land.SurfaceType.ROAD,land.SurfaceType.RUNWAY,land.SurfaceType.SHALLOW_WATER} self.surfacetypes = {land.SurfaceType.LAND,land.SurfaceType.ROAD,land.SurfaceType.RUNWAY,land.SurfaceType.SHALLOW_WATER}
-- Chinhook
self.enableChinhookGCLoading = true
local AliaS = string.gsub(self.alias," ","_") local AliaS = string.gsub(self.alias," ","_")
self.filename = string.format("CTLD_%s_Persist.csv",AliaS) self.filename = string.format("CTLD_%s_Persist.csv",AliaS)
@ -1592,7 +1644,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
-- @param Wrapper.Group#GROUP Group Group Object. -- @param Wrapper.Group#GROUP Group Group Object.
-- @param Wrapper.Unit#UNIT Unit Unit Object. -- @param Wrapper.Unit#UNIT Unit Unit Object.
-- @param #string ZoneName Name of the Zone where the Troops have been RTB'd. -- @param #string ZoneName Name of the Zone where the Troops have been RTB'd.
-- @param Core.Zone#ZONE_RADIUS ZoneObject of the Zone where the Troops have been RTB'd. -- @param Core.Zone#ZONE_Radius ZoneObject of the Zone where the Troops have been RTB'd.
--- FSM Function OnAfterTroopsPickedUp. --- FSM Function OnAfterTroopsPickedUp.
-- @function [parent=#CTLD] OnAfterTroopsPickedUp -- @function [parent=#CTLD] OnAfterTroopsPickedUp
@ -1719,8 +1771,6 @@ function CTLD:New(Coalition, Prefixes, Alias)
-- @param #string To State. -- @param #string To State.
-- @param Wrapper.Group#GROUP Group Group Object. -- @param Wrapper.Group#GROUP Group Group Object.
-- @param Wrapper.Unit#UNIT Unit Unit Object. -- @param Wrapper.Unit#UNIT Unit Unit Object.
-- @param #string ZoneName Name of the Zone where the Troops have been RTB'd.
-- @param Core.Zone#ZONE_RADIUS ZoneObject of the Zone where the Troops have been RTB'd.
--- FSM Function OnAfterLoad. --- FSM Function OnAfterLoad.
-- @function [parent=#CTLD] OnAfterLoad -- @function [parent=#CTLD] OnAfterLoad
@ -1827,7 +1877,7 @@ end
-- @param #CTLD self -- @param #CTLD self
-- @param Core.Event#EVENTDATA EventData -- @param Core.Event#EVENTDATA EventData
function CTLD:_EventHandler(EventData) function CTLD:_EventHandler(EventData)
self:T(string.format("%s Event = %d",self.lid, EventData.id)) self:I(string.format("%s Event = %d",self.lid, EventData.id))
local event = EventData -- Core.Event#EVENTDATA local event = EventData -- Core.Event#EVENTDATA
if event.id == EVENTS.PlayerEnterAircraft or event.id == EVENTS.PlayerEnterUnit then if event.id == EVENTS.PlayerEnterAircraft or event.id == EVENTS.PlayerEnterUnit then
local _coalition = event.IniCoalition local _coalition = event.IniCoalition
@ -1851,12 +1901,37 @@ function CTLD:_EventHandler(EventData)
self:_RefreshF10Menus() self:_RefreshF10Menus()
end end
return return
elseif event.id == EVENTS.PlayerLeaveUnit then elseif event.id == EVENTS.PlayerLeaveUnit or event.id == EVENTS.UnitLost then
-- remove from pilot table -- remove from pilot table
local unitname = event.IniUnitName or "none" local unitname = event.IniUnitName or "none"
self.CtldUnits[unitname] = nil self.CtldUnits[unitname] = nil
self.Loaded_Cargo[unitname] = nil self.Loaded_Cargo[unitname] = nil
self.MenusDone[unitname] = nil self.MenusDone[unitname] = nil
elseif event.id == EVENTS.Birth and event.IniObjectCategory == 6 and string.match(event.IniUnitName,".+|%d%d:%d%d|PKG%d+") then
--UTILS.PrintTableToLog(event)
---------------
-- New dynamic cargo system Handling
--------------
local function RegisterDynamicCargo()
local static = _DATABASE:AddStatic(event.IniUnitName)
if static then
static.DCSCargoObject = event.IniDCSUnit
local Mass = event.IniDCSUnit:getCargoWeight()
local country = event.IniDCSUnit:getCountry()
local template = _DATABASE:_GetGenericStaticCargoGroupTemplate(event.IniUnitName,event.IniTypeName,Mass,event.IniCoalition,country)
_DATABASE:_RegisterStaticTemplate(template,event.IniCoalition,"static",country)
self:I("**** Ground crew created static cargo added: "..event.IniUnitName .." | Weight in kgs: "..Mass)
local cargotype = self:AddStaticsCargo(event.IniUnitName,Mass,1,nil,true)
self.CrateCounter = self.CrateCounter + 1
self.Spawned_Crates[self.CrateCounter] = static
cargotype.Positionable = static
table.insert(self.Spawned_Cargo, cargotype)
end
end
self:ScheduleOnce(0.5,RegisterDynamicCargo)
---------------
-- End new dynamic cargo system Handling
--------------
end end
return self return self
end end
@ -2422,7 +2497,8 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
return self return self
end end
-- spawn crates in front of helicopter -- spawn crates in front of helicopter
local IsHerc = self:IsHercules(Unit) -- Herc local IsHerc = self:IsHercules(Unit) -- Herc, Bronco and Hook load from behind
local IsHook = self:IsHook(Unit) -- Herc, Bronco and Hook load from behind
local cargotype = Cargo -- Ops.CTLD#CTLD_CARGO local cargotype = Cargo -- Ops.CTLD#CTLD_CARGO
local number = number or cargotype:GetCratesNeeded() --#number local number = number or cargotype:GetCratesNeeded() --#number
local cratesneeded = cargotype:GetCratesNeeded() --#number local cratesneeded = cargotype:GetCratesNeeded() --#number
@ -2444,7 +2520,7 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
local rheading = 0 local rheading = 0
local angleOffNose = 0 local angleOffNose = 0
local addon = 0 local addon = 0
if IsHerc then if IsHerc or IsHook then
-- spawn behind the Herc -- spawn behind the Herc
addon = 180 addon = 180
end end
@ -2494,17 +2570,25 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
dist = dist - (20 + math.random(1,10)) dist = dist - (20 + math.random(1,10))
local width = width / 2 local width = width / 2
local Offy = math.random(-width,width) local Offy = math.random(-width,width)
self.Spawned_Crates[self.CrateCounter] = SPAWNSTATIC:NewFromType(basetype,"Cargos",self.cratecountry) local spawnstatic = SPAWNSTATIC:NewFromType(basetype,"Cargos",self.cratecountry)
:InitCargoMass(cgomass) :InitCargoMass(cgomass)
:InitCargo(self.enableslingload) :InitCargo(self.enableslingload)
:InitLinkToUnit(Ship,dist,Offy,0) :InitLinkToUnit(Ship,dist,Offy,0)
:Spawn(270,cratealias) if isstatic then
local map=cargotype:GetStaticResourceMap()
spawnstatic.TemplateStaticUnit.resourcePayload = map
end
self.Spawned_Crates[self.CrateCounter] = spawnstatic:Spawn(270,cratealias)
else else
self.Spawned_Crates[self.CrateCounter] = SPAWNSTATIC:NewFromType(basetype,"Cargos",self.cratecountry) local spawnstatic = SPAWNSTATIC:NewFromType(basetype,"Cargos",self.cratecountry)
:InitCoordinate(cratecoord) :InitCoordinate(cratecoord)
:InitCargoMass(cgomass) :InitCargoMass(cgomass)
:InitCargo(self.enableslingload) :InitCargo(self.enableslingload)
:Spawn(270,cratealias) if isstatic then
local map=cargotype:GetStaticResourceMap()
spawnstatic.TemplateStaticUnit.resourcePayload = map
end
self.Spawned_Crates[self.CrateCounter] = spawnstatic:Spawn(270,cratealias)
end end
local templ = cargotype:GetTemplates() local templ = cargotype:GetTemplates()
local sorte = cargotype:GetType() local sorte = cargotype:GetType()
@ -2514,9 +2598,13 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
if drop then if drop then
--CTLD_CARGO:New(ID, Name, Templates, Sorte, HasBeenMoved, LoadDirectly, CratesNeeded, Positionable, Dropped, PerCrateMass, Stock, Subcategory) --CTLD_CARGO:New(ID, Name, Templates, Sorte, HasBeenMoved, LoadDirectly, CratesNeeded, Positionable, Dropped, PerCrateMass, Stock, Subcategory)
realcargo = CTLD_CARGO:New(self.CargoCounter,cratename,templ,sorte,true,false,cratesneeded,self.Spawned_Crates[self.CrateCounter],true,cargotype.PerCrateMass,nil,subcat) realcargo = CTLD_CARGO:New(self.CargoCounter,cratename,templ,sorte,true,false,cratesneeded,self.Spawned_Crates[self.CrateCounter],true,cargotype.PerCrateMass,nil,subcat)
local map=cargotype:GetStaticResourceMap()
realcargo:SetStaticResourceMap(map)
table.insert(droppedcargo,realcargo) table.insert(droppedcargo,realcargo)
else else
realcargo = CTLD_CARGO:New(self.CargoCounter,cratename,templ,sorte,false,false,cratesneeded,self.Spawned_Crates[self.CrateCounter],false,cargotype.PerCrateMass,nil,subcat) realcargo = CTLD_CARGO:New(self.CargoCounter,cratename,templ,sorte,false,false,cratesneeded,self.Spawned_Crates[self.CrateCounter],false,cargotype.PerCrateMass,nil,subcat)
local map=cargotype:GetStaticResourceMap()
realcargo:SetStaticResourceMap(map)
end end
table.insert(self.Spawned_Cargo, realcargo) table.insert(self.Spawned_Cargo, realcargo)
end end
@ -2566,14 +2654,18 @@ function CTLD:InjectStatics(Zone, Cargo, RandomCoord)
basetype = cratetemplate basetype = cratetemplate
end end
self.CrateCounter = self.CrateCounter + 1 self.CrateCounter = self.CrateCounter + 1
self.Spawned_Crates[self.CrateCounter] = SPAWNSTATIC:NewFromType(basetype,"Cargos",self.cratecountry) local spawnstatic = SPAWNSTATIC:NewFromType(basetype,"Cargos",self.cratecountry)
:InitCargoMass(cgomass) :InitCargoMass(cgomass)
:InitCargo(self.enableslingload) :InitCargo(self.enableslingload)
:InitCoordinate(cratecoord) :InitCoordinate(cratecoord)
:Spawn(270,cratealias) if isstatic then
local map = cargotype:GetStaticResourceMap()
spawnstatic.TemplateStaticUnit.resourcePayload = map
end
self.Spawned_Crates[self.CrateCounter] = spawnstatic:Spawn(270,cratealias)
local templ = cargotype:GetTemplates() local templ = cargotype:GetTemplates()
local sorte = cargotype:GetType() local sorte = cargotype:GetType()
self.CargoCounter = self.CargoCounter + 1 --self.CargoCounter = self.CargoCounter + 1
cargotype.Positionable = self.Spawned_Crates[self.CrateCounter] cargotype.Positionable = self.Spawned_Crates[self.CrateCounter]
table.insert(self.Spawned_Cargo, cargotype) table.insert(self.Spawned_Cargo, cargotype)
return self return self
@ -2600,8 +2692,8 @@ end
function CTLD:_ListCratesNearby( _group, _unit) function CTLD:_ListCratesNearby( _group, _unit)
self:T(self.lid .. " _ListCratesNearby") self:T(self.lid .. " _ListCratesNearby")
local finddist = self.CrateDistance or 35 local finddist = self.CrateDistance or 35
local crates,number = self:_FindCratesNearby(_group,_unit, finddist,true) -- #table local crates,number,loadedbygc,indexgc = self:_FindCratesNearby(_group,_unit, finddist,true) -- #table
if number > 0 then if number > 0 or indexgc > 0 then
local text = REPORT:New("Crates Found Nearby:") local text = REPORT:New("Crates Found Nearby:")
text:Add("------------------------------------------------------------") text:Add("------------------------------------------------------------")
for _,_entry in pairs (crates) do for _,_entry in pairs (crates) do
@ -2618,6 +2710,19 @@ function CTLD:_ListCratesNearby( _group, _unit)
text:Add(" N O N E") text:Add(" N O N E")
end end
text:Add("------------------------------------------------------------") text:Add("------------------------------------------------------------")
if indexgc > 0 then
text:Add("Probably ground crew loaded (F8)")
for _,_entry in pairs (loadedbygc) do
local entry = _entry -- #CTLD_CARGO
local name = entry:GetName() --#string
local dropped = entry:WasDropped()
if dropped then
text:Add(string.format("Dropped crate for %s, %dkg",name, entry.PerCrateMass))
else
text:Add(string.format("Crate for %s, %dkg",name, entry.PerCrateMass))
end
end
end
self:_SendMessage(text:Text(), 30, true, _group) self:_SendMessage(text:Text(), 30, true, _group)
else else
self:_SendMessage(string.format("No (loadable) crates within %d meters!",finddist), 10, false, _group) self:_SendMessage(string.format("No (loadable) crates within %d meters!",finddist), 10, false, _group)
@ -2691,8 +2796,10 @@ end
-- @param Wrapper.Unit#UNIT _unit Unit -- @param Wrapper.Unit#UNIT _unit Unit
-- @param #number _dist Distance -- @param #number _dist Distance
-- @param #boolean _ignoreweight Find everything in range, ignore loadable weight -- @param #boolean _ignoreweight Find everything in range, ignore loadable weight
-- @return #table Table of crates -- @return #table Crates Table of crates
-- @return #number Number Number of crates found -- @return #number Number Number of crates found
-- @return #table CratesGC Table of crates possibly loaded by GC
-- @return #number NumberGC Number of crates possibly loaded by GC
function CTLD:_FindCratesNearby( _group, _unit, _dist, _ignoreweight) function CTLD:_FindCratesNearby( _group, _unit, _dist, _ignoreweight)
self:T(self.lid .. " _FindCratesNearby") self:T(self.lid .. " _FindCratesNearby")
local finddist = _dist local finddist = _dist
@ -2700,7 +2807,9 @@ function CTLD:_FindCratesNearby( _group, _unit, _dist, _ignoreweight)
local existingcrates = self.Spawned_Cargo -- #table local existingcrates = self.Spawned_Cargo -- #table
-- cycle -- cycle
local index = 0 local index = 0
local indexg = 0
local found = {} local found = {}
local LoadedbyGC = {}
local loadedmass = 0 local loadedmass = 0
local unittype = "none" local unittype = "none"
local capabilities = {} local capabilities = {}
@ -2713,20 +2822,47 @@ function CTLD:_FindCratesNearby( _group, _unit, _dist, _ignoreweight)
for _,_cargoobject in pairs (existingcrates) do for _,_cargoobject in pairs (existingcrates) do
local cargo = _cargoobject -- #CTLD_CARGO local cargo = _cargoobject -- #CTLD_CARGO
local static = cargo:GetPositionable() -- Wrapper.Static#STATIC -- crates local static = cargo:GetPositionable() -- Wrapper.Static#STATIC -- crates
local staticid = cargo:GetID()
local weight = cargo:GetMass() -- weight in kgs of this cargo local weight = cargo:GetMass() -- weight in kgs of this cargo
local staticid = cargo:GetID()
self:T(self.lid .. " Found cargo mass: " .. weight) self:T(self.lid .. " Found cargo mass: " .. weight)
if static and static:IsAlive() then local cargoalive = false -- TODO dyn cargo spawn workaround
local staticpos = static:GetCoordinate() local dcsunit = nil
local dcsunitpos = nil
if static.DCSCargoObject then
dcsunit = Unit.getByName(static.StaticName)
if dcsunit then
cargoalive = dcsunit:isExist() ~= nil and true or false
end
if cargoalive == true then
local dcsvec3 = dcsunit:getPoint() or dcsunit:getPosition().p or {x=0,y=0,z=0}
self:I({dcsvec3 = dcsunit:getPoint(), dcspos = dcsunit:getPosition().p})
if dcsvec3 then
dcsunitpos = COORDINATE:New(dcsvec3.x,dcsvec3.z,dcsvec3.y)
end
end
end
if static and (static:IsAlive() or cargoalive) then
local staticpos = static:GetCoordinate() or dcsunitpos
--- Testing
local landheight = staticpos:GetLandHeight()
local agl = staticpos.y-landheight
agl = UTILS.Round(agl,2)
local GCloaded = agl > 0 and true or false
--- Testing
local distance = self:_GetDistance(location,staticpos) local distance = self:_GetDistance(location,staticpos)
if distance <= finddist and static and (weight <= maxloadable or _ignoreweight) then self:I({name=static:GetName(),agl=agl,GCloaded=GCloaded,distance=string.format("%.2f",distance or 0)})
if (not GCloaded) and distance <= finddist and static and (weight <= maxloadable or _ignoreweight) then
index = index + 1 index = index + 1
table.insert(found, staticid, cargo) table.insert(found, staticid, cargo)
maxloadable = maxloadable - weight maxloadable = maxloadable - weight
end end
if GCloaded == true and distance < 10 and static then
indexg = indexg + 1
table.insert(LoadedbyGC,staticid, cargo)
end
end end
end end
return found, index return found, index, LoadedbyGC, indexg
end end
--- (Internal) Function to get and load nearby crates. --- (Internal) Function to get and load nearby crates.
@ -2748,6 +2884,13 @@ function CTLD:_LoadCratesNearby(Group, Unit)
local cratelimit = capabilities.cratelimit -- #number local cratelimit = capabilities.cratelimit -- #number
local grounded = not self:IsUnitInAir(Unit) local grounded = not self:IsUnitInAir(Unit)
local canhoverload = self:CanHoverLoad(Unit) local canhoverload = self:CanHoverLoad(Unit)
-- Door check
if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
self:_SendMessage("You need to open the door(s) to load cargo!", 10, false, Group)
if not self.debug then return self end
end
--- cases ------------------------------- --- cases -------------------------------
-- Chopper can\'t do crates - bark & return -- Chopper can\'t do crates - bark & return
-- Chopper can do crates - -- Chopper can do crates -
@ -2925,7 +3068,9 @@ function CTLD:_ListCargo(Group, Unit)
local loadedcargo = self.Loaded_Cargo[unitname] or {} -- #CTLD.LoadedCargo local loadedcargo = self.Loaded_Cargo[unitname] or {} -- #CTLD.LoadedCargo
local loadedmass = self:_GetUnitCargoMass(Unit) -- #number local loadedmass = self:_GetUnitCargoMass(Unit) -- #number
local maxloadable = self:_GetMaxLoadableMass(Unit) local maxloadable = self:_GetMaxLoadableMass(Unit)
if self.Loaded_Cargo[unitname] then local finddist = self.CrateDistance or 35
local _,_,loadedgc,loadedno = self:_FindCratesNearby(Group,Unit,finddist,true)
if self.Loaded_Cargo[unitname] or loadedno > 0 then
local no_troops = loadedcargo.Troopsloaded or 0 local no_troops = loadedcargo.Troopsloaded or 0
local no_crates = loadedcargo.Cratesloaded or 0 local no_crates = loadedcargo.Cratesloaded or 0
local cargotable = loadedcargo.Cargo or {} -- #table local cargotable = loadedcargo.Cargo or {} -- #table
@ -2947,7 +3092,7 @@ function CTLD:_ListCargo(Group, Unit)
report:Add("------------------------------------------------------------") report:Add("------------------------------------------------------------")
report:Add(" -- CRATES --") report:Add(" -- CRATES --")
local cratecount = 0 local cratecount = 0
for _,_cargo in pairs(cargotable) do for _,_cargo in pairs(cargotable or {}) do
local cargo = _cargo -- #CTLD_CARGO local cargo = _cargo -- #CTLD_CARGO
local type = cargo:GetType() -- #CTLD_CARGO.Enum local type = cargo:GetType() -- #CTLD_CARGO.Enum
if (type ~= CTLD_CARGO.Enum.TROOPS and type ~= CTLD_CARGO.Enum.ENGINEERS) and (not cargo:WasDropped() or self.allowcratepickupagain) then if (type ~= CTLD_CARGO.Enum.TROOPS and type ~= CTLD_CARGO.Enum.ENGINEERS) and (not cargo:WasDropped() or self.allowcratepickupagain) then
@ -2958,6 +3103,18 @@ function CTLD:_ListCargo(Group, Unit)
if cratecount == 0 then if cratecount == 0 then
report:Add(" N O N E") report:Add(" N O N E")
end end
if loadedno > 0 then
report:Add("------------------------------------------------------------")
report:Add(" -- CRATES loaded via F8 --")
for _,_cargo in pairs(loadedgc or {}) do
local cargo = _cargo -- #CTLD_CARGO
local type = cargo:GetType() -- #CTLD_CARGO.Enum
if (type ~= CTLD_CARGO.Enum.TROOPS and type ~= CTLD_CARGO.Enum.ENGINEERS) then
report:Add(string.format("Crate: %s size 1",cargo:GetName()))
loadedmass = loadedmass + cargo:GetMass()
end
end
end
report:Add("------------------------------------------------------------") report:Add("------------------------------------------------------------")
report:Add("Total Mass: ".. loadedmass .. " kg. Loadable: "..maxloadable.." kg.") report:Add("Total Mass: ".. loadedmass .. " kg. Loadable: "..maxloadable.." kg.")
local text = report:Text() local text = report:Text()
@ -3062,7 +3219,7 @@ function CTLD:_ListInventory(Group, Unit)
return self return self
end end
--- (Internal) Function to check if a unit is a Hercules C-130. --- (Internal) Function to check if a unit is a Hercules C-130 or a Bronco.
-- @param #CTLD self -- @param #CTLD self
-- @param Wrapper.Unit#UNIT Unit -- @param Wrapper.Unit#UNIT Unit
-- @return #boolean Outcome -- @return #boolean Outcome
@ -3074,6 +3231,17 @@ function CTLD:IsHercules(Unit)
end end
end end
--- (Internal) Function to check if a unit is a CH-47
-- @param #CTLD self
-- @param Wrapper.Unit#UNIT Unit
-- @return #boolean Outcome
function CTLD:IsHook(Unit)
if string.find(Unit:GetTypeName(),"CH.47") then
return true
else
return false
end
end
--- (Internal) Function to set troops positions of a template to a nice circle --- (Internal) Function to set troops positions of a template to a nice circle
-- @param #CTLD self -- @param #CTLD self
@ -3126,8 +3294,9 @@ function CTLD:_UnloadTroops(Group, Unit)
end end
-- check for hover unload -- check for hover unload
local hoverunload = self:IsCorrectHover(Unit) --if true we\'re hovering in parameters local hoverunload = self:IsCorrectHover(Unit) --if true we\'re hovering in parameters
local IsHerc = self:IsHercules(Unit) local IsHerc = self:IsHercules(Unit)
if IsHerc then local IsHook = self:IsHook(Unit)
if IsHerc and (not IsHook) then
-- no hover but airdrop here -- no hover but airdrop here
hoverunload = self:IsCorrectFlightParameters(Unit) hoverunload = self:IsCorrectFlightParameters(Unit)
end end
@ -3256,10 +3425,16 @@ function CTLD:_UnloadCrates(Group, Unit)
end end
end end
end end
-- Door check
if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
self:_SendMessage("You need to open the door(s) to drop cargo!", 10, false, Group)
if not self.debug then return self end
end
-- check for hover unload -- check for hover unload
local hoverunload = self:IsCorrectHover(Unit) --if true we\'re hovering in parameters local hoverunload = self:IsCorrectHover(Unit) --if true we\'re hovering in parameters
local IsHerc = self:IsHercules(Unit) local IsHerc = self:IsHercules(Unit)
if IsHerc then local IsHook = self:IsHook(Unit)
if IsHerc and (not IsHook) then
-- no hover but airdrop here -- no hover but airdrop here
hoverunload = self:IsCorrectFlightParameters(Unit) hoverunload = self:IsCorrectFlightParameters(Unit)
end end
@ -3726,6 +3901,8 @@ function CTLD:_RefreshF10Menus()
local capabilities = self:_GetUnitCapabilities(_unit) -- #CTLD.UnitTypeCapabilities local capabilities = self:_GetUnitCapabilities(_unit) -- #CTLD.UnitTypeCapabilities
local cantroops = capabilities.troops local cantroops = capabilities.troops
local cancrates = capabilities.crates local cancrates = capabilities.crates
local isHook = self:IsHook(_unit)
local nohookswitch = not (isHook and self.enableChinhookGCLoading)
-- top menu -- top menu
local topmenu = MENU_GROUP:New(_group,"CTLD",nil) local topmenu = MENU_GROUP:New(_group,"CTLD",nil)
local toptroops = nil local toptroops = nil
@ -3782,8 +3959,10 @@ function CTLD:_RefreshF10Menus()
local extractMenu1 = MENU_GROUP_COMMAND:New(_group, "Extract troops", toptroops, self._ExtractTroops, self, _group, _unit):Refresh() local extractMenu1 = MENU_GROUP_COMMAND:New(_group, "Extract troops", toptroops, self._ExtractTroops, self, _group, _unit):Refresh()
end end
-- sub menu crates management -- sub menu crates management
if cancrates then if cancrates then
local loadmenu = MENU_GROUP_COMMAND:New(_group,"Load crates",topcrates, self._LoadCratesNearby, self, _group, _unit) if nohookswitch then
local loadmenu = MENU_GROUP_COMMAND:New(_group,"Load crates",topcrates, self._LoadCratesNearby, self, _group, _unit)
end
local cratesmenu = MENU_GROUP:New(_group,"Get Crates",topcrates) local cratesmenu = MENU_GROUP:New(_group,"Get Crates",topcrates)
local packmenu = MENU_GROUP_COMMAND:New(_group, "Pack crates", topcrates, self._PackCratesNearby, self, _group, _unit) local packmenu = MENU_GROUP_COMMAND:New(_group, "Pack crates", topcrates, self._PackCratesNearby, self, _group, _unit)
local removecratesmenu = MENU_GROUP:New(_group, "Remove crates", topcrates) local removecratesmenu = MENU_GROUP:New(_group, "Remove crates", topcrates)
@ -3851,11 +4030,14 @@ function CTLD:_RefreshF10Menus()
end end
listmenu = MENU_GROUP_COMMAND:New(_group,"List crates nearby",topcrates, self._ListCratesNearby, self, _group, _unit) listmenu = MENU_GROUP_COMMAND:New(_group,"List crates nearby",topcrates, self._ListCratesNearby, self, _group, _unit)
local removecrates = MENU_GROUP_COMMAND:New(_group,"Remove crates nearby",removecratesmenu, self._RemoveCratesNearby, self, _group, _unit) local removecrates = MENU_GROUP_COMMAND:New(_group,"Remove crates nearby",removecratesmenu, self._RemoveCratesNearby, self, _group, _unit)
local unloadmenu = MENU_GROUP_COMMAND:New(_group,"Drop crates",topcrates, self._UnloadCrates, self, _group, _unit) local unloadmenu
if nohookswitch then
unloadmenu = MENU_GROUP_COMMAND:New(_group,"Drop crates",topcrates, self._UnloadCrates, self, _group, _unit)
end
if not self.nobuildmenu then if not self.nobuildmenu then
local buildmenu = MENU_GROUP_COMMAND:New(_group,"Build crates",topcrates, self._BuildCrates, self, _group, _unit) local buildmenu = MENU_GROUP_COMMAND:New(_group,"Build crates",topcrates, self._BuildCrates, self, _group, _unit)
local repairmenu = MENU_GROUP_COMMAND:New(_group,"Repair",topcrates, self._RepairCrates, self, _group, _unit):Refresh() local repairmenu = MENU_GROUP_COMMAND:New(_group,"Repair",topcrates, self._RepairCrates, self, _group, _unit):Refresh()
else elseif unloadmenu then
unloadmenu:Refresh() unloadmenu:Refresh()
end end
end end
@ -3948,15 +4130,22 @@ end
-- @param #string SubCategory Name of sub-category (optional). -- @param #string SubCategory Name of sub-category (optional).
-- @param #boolean DontShowInMenu (optional) If set to "true" this won't show up in the menu. -- @param #boolean DontShowInMenu (optional) If set to "true" this won't show up in the menu.
-- @param Core.Zone#ZONE Location (optional) If set, the cargo item is **only** available here. Can be a #ZONE object or the name of a zone as #string. -- @param Core.Zone#ZONE Location (optional) If set, the cargo item is **only** available here. Can be a #ZONE object or the name of a zone as #string.
-- @return #CTLD_CARGO CargoObject
function CTLD:AddStaticsCargo(Name,Mass,Stock,SubCategory,DontShowInMenu,Location) function CTLD:AddStaticsCargo(Name,Mass,Stock,SubCategory,DontShowInMenu,Location)
self:T(self.lid .. " AddStaticsCargo") self:T(self.lid .. " AddStaticsCargo")
self.CargoCounter = self.CargoCounter + 1 self.CargoCounter = self.CargoCounter + 1
local type = CTLD_CARGO.Enum.STATIC local type = CTLD_CARGO.Enum.STATIC
local template = STATIC:FindByName(Name,true):GetTypeName() local template = STATIC:FindByName(Name,true):GetTypeName()
local unittemplate = _DATABASE:GetStaticUnitTemplate(Name)
local ResourceMap = nil
if unittemplate and unittemplate.resourcePayload then
ResourceMap = UTILS.DeepCopy(unittemplate.resourcePayload)
end
-- Crates are not directly loadable -- Crates are not directly loadable
local cargo = CTLD_CARGO:New(self.CargoCounter,Name,template,type,false,false,1,nil,nil,Mass,Stock,SubCategory,DontShowInMenu,Location) local cargo = CTLD_CARGO:New(self.CargoCounter,Name,template,type,false,false,1,nil,nil,Mass,Stock,SubCategory,DontShowInMenu,Location)
cargo:SetStaticResourceMap(ResourceMap)
table.insert(self.Cargo_Statics,cargo) table.insert(self.Cargo_Statics,cargo)
return self return cargo
end end
--- User function - Get a *generic* static-type loadable as #CTLD_CARGO object. --- User function - Get a *generic* static-type loadable as #CTLD_CARGO object.
@ -3969,8 +4158,14 @@ function CTLD:GetStaticsCargoFromTemplate(Name,Mass)
self.CargoCounter = self.CargoCounter + 1 self.CargoCounter = self.CargoCounter + 1
local type = CTLD_CARGO.Enum.STATIC local type = CTLD_CARGO.Enum.STATIC
local template = STATIC:FindByName(Name,true):GetTypeName() local template = STATIC:FindByName(Name,true):GetTypeName()
local unittemplate = _DATABASE:GetStaticUnitTemplate(Name)
local ResourceMap = nil
if unittemplate and unittemplate.resourcePayload then
ResourceMap = UTILS.DeepCopy(unittemplate.resourcePayload)
end
-- Crates are not directly loadable -- Crates are not directly loadable
local cargo = CTLD_CARGO:New(self.CargoCounter,Name,template,type,false,false,1,nil,nil,Mass,1) local cargo = CTLD_CARGO:New(self.CargoCounter,Name,template,type,false,false,1,nil,nil,Mass,1)
cargo:SetStaticResourceMap(ResourceMap)
--table.insert(self.Cargo_Statics,cargo) --table.insert(self.Cargo_Statics,cargo)
return cargo return cargo
end end
@ -5336,7 +5531,9 @@ end
-- Events -- Events
self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler) self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler)
self:HandleEvent(EVENTS.PlayerEnterUnit, self._EventHandler) self:HandleEvent(EVENTS.PlayerEnterUnit, self._EventHandler)
self:HandleEvent(EVENTS.PlayerLeaveUnit, self._EventHandler) self:HandleEvent(EVENTS.PlayerLeaveUnit, self._EventHandler)
self:HandleEvent(EVENTS.UnitLost, self._EventHandler)
self:HandleEvent(EVENTS.Birth, self._EventHandler)
self:__Status(-5) self:__Status(-5)
-- AutoSave -- AutoSave
@ -5600,7 +5797,7 @@ end
-- @param Wrapper.Group#GROUP Group Group Object. -- @param Wrapper.Group#GROUP Group Group Object.
-- @param Wrapper.Unit#UNIT Unit Unit Object. -- @param Wrapper.Unit#UNIT Unit Unit Object.
-- @param #string ZoneName Name of the Zone where the Troops have been RTB'd. -- @param #string ZoneName Name of the Zone where the Troops have been RTB'd.
-- @param Core.Zone#ZONE_RADIUS ZoneObject of the Zone where the Troops have been RTB'd. -- @param Core.Zone#ZONE_Radius ZoneObject of the Zone where the Troops have been RTB'd.
-- @return #CTLD self -- @return #CTLD self
function CTLD:onbeforeTroopsRTB(From, Event, To, Group, Unit, ZoneName, ZoneObject) function CTLD:onbeforeTroopsRTB(From, Event, To, Group, Unit, ZoneName, ZoneObject)
self:T({From, Event, To}) self:T({From, Event, To})
@ -5948,7 +6145,9 @@ end
cargotemplates = UTILS.Split(cargotemplates,";") cargotemplates = UTILS.Split(cargotemplates,";")
injectstatic = CTLD_CARGO:New(nil,cargoname,cargotemplates,cargotype,true,true,size,nil,true,mass) injectstatic = CTLD_CARGO:New(nil,cargoname,cargotemplates,cargotype,true,true,size,nil,true,mass)
elseif cargotype == CTLD_CARGO.Enum.STATIC or cargotype == CTLD_CARGO.Enum.REPAIR then elseif cargotype == CTLD_CARGO.Enum.STATIC or cargotype == CTLD_CARGO.Enum.REPAIR then
injectstatic = CTLD_CARGO:New(nil,cargoname,cargotemplates,cargotype,true,true,size,nil,true,mass) injectstatic = CTLD_CARGO:New(nil,cargoname,cargotemplates,cargotype,true,true,size,nil,true,mass)
local map=cargotype:GetStaticResourceMap()
injectstatic:SetStaticResourceMap(map)
end end
if injectstatic then if injectstatic then
self:InjectStatics(dropzone,injectstatic) self:InjectStatics(dropzone,injectstatic)
@ -6304,6 +6503,8 @@ function CTLD_HERCULES:Cargo_SpawnDroppedAsCargo(_name, _pos)
self.CTLD.Spawned_Crates[self.CTLD.CrateCounter] = theStatic self.CTLD.Spawned_Crates[self.CTLD.CrateCounter] = theStatic
local newCargo = CTLD_CARGO:New(self.CTLD.CargoCounter, theCargo.Name, theCargo.Templates, theCargo.CargoType, true, false, theCargo.CratesNeeded, self.CTLD.Spawned_Crates[self.CTLD.CrateCounter], true, theCargo.PerCrateMass, nil, theCargo.Subcategory) local newCargo = CTLD_CARGO:New(self.CTLD.CargoCounter, theCargo.Name, theCargo.Templates, theCargo.CargoType, true, false, theCargo.CratesNeeded, self.CTLD.Spawned_Crates[self.CTLD.CrateCounter], true, theCargo.PerCrateMass, nil, theCargo.Subcategory)
local map=theCargo:GetStaticResourceMap()
newCargo:SetStaticResourceMap(map)
table.insert(self.CTLD.Spawned_Cargo, newCargo) table.insert(self.CTLD.Spawned_Cargo, newCargo)
newCargo:SetWasDropped(true) newCargo:SetWasDropped(true)
@ -6334,8 +6535,6 @@ function CTLD_HERCULES:Cargo_SpawnObjects(Cargo_Drop_initiator,Cargo_Drop_Direct
if offload_cargo == true or ParatrooperGroupSpawn == true then if offload_cargo == true or ParatrooperGroupSpawn == true then
if ParatrooperGroupSpawn == true then if ParatrooperGroupSpawn == true then
--self:Soldier_SpawnGroup(Cargo_Drop_initiator,Cargo_Content_position, Cargo_Type_name, CargoHeading, Cargo_Country, 0)
--self:Soldier_SpawnGroup(Cargo_Drop_initiator,Cargo_Content_position, Cargo_Type_name, CargoHeading, Cargo_Country, 5)
self:Soldier_SpawnGroup(Cargo_Drop_initiator,Cargo_Content_position, Cargo_Type_name, CargoHeading, Cargo_Country, 10) self:Soldier_SpawnGroup(Cargo_Drop_initiator,Cargo_Content_position, Cargo_Type_name, CargoHeading, Cargo_Country, 10)
else else
self:Cargo_SpawnGroup(Cargo_Drop_initiator,Cargo_Content_position, Cargo_Type_name, CargoHeading, Cargo_Country) self:Cargo_SpawnGroup(Cargo_Drop_initiator,Cargo_Content_position, Cargo_Type_name, CargoHeading, Cargo_Country)

View File

@ -2319,8 +2319,8 @@ function UTILS.IsLoadingDoorOpen( unit_name )
BASE:T(unit_name .. " cargo door is open") BASE:T(unit_name .. " cargo door is open")
return true return true
end end
if type_name == "CH-47Fbl1" and (unit:getDrawArgumentValue(86) > 0) then if type_name == "CH-47Fbl1" and (unit:getDrawArgumentValue(86) > 0.5) then
BASE:T(unit_name .. " rear cargo door is open") BASE:T(unit_name .. " rear cargo door is open")
return true return true
end end

View File

@ -721,11 +721,12 @@ AIRBASE.Sinai = {
--- Airbases of the Kola map --- Airbases of the Kola map
-- --
-- * AIRBASE.Kola.Banak -- * AIRBASE.Kola.Banak
-- * AIRBASE.Kola.Bas_100
-- * AIRBASE.Kola.Bodo -- * AIRBASE.Kola.Bodo
-- * AIRBASE.Kola.Jokkmokk -- * AIRBASE.Kola.Jokkmokk
-- * AIRBASE.Kola.Kalixfors -- * AIRBASE.Kola.Kalixfors
-- * AIRBASE.Kola.Kallax
-- * AIRBASE.Kola.Kemi_Tornio -- * AIRBASE.Kola.Kemi_Tornio
-- * AIRBASE.Kola.Kirkenes
-- * AIRBASE.Kola.Kiruna -- * AIRBASE.Kola.Kiruna
-- * AIRBASE.Kola.Monchegorsk -- * AIRBASE.Kola.Monchegorsk
-- * AIRBASE.Kola.Murmansk_International -- * AIRBASE.Kola.Murmansk_International
@ -733,11 +734,12 @@ AIRBASE.Sinai = {
-- * AIRBASE.Kola.Rovaniemi -- * AIRBASE.Kola.Rovaniemi
-- * AIRBASE.Kola.Severomorsk_1 -- * AIRBASE.Kola.Severomorsk_1
-- * AIRBASE.Kola.Severomorsk_3 -- * AIRBASE.Kola.Severomorsk_3
-- * AIRBASE.Kola.Vidsel
-- * AIRBASE.Kola.Vuojarvi
-- --
-- @field Kola -- @field Kola
AIRBASE.Kola = { AIRBASE.Kola = {
["Banak"] = "Banak", ["Banak"] = "Banak",
["Bas_100"] = "Bas 100",
["Bodo"] = "Bodo", ["Bodo"] = "Bodo",
["Jokkmokk"] = "Jokkmokk", ["Jokkmokk"] = "Jokkmokk",
["Kalixfors"] = "Kalixfors", ["Kalixfors"] = "Kalixfors",
@ -749,6 +751,10 @@ AIRBASE.Kola = {
["Rovaniemi"] = "Rovaniemi", ["Rovaniemi"] = "Rovaniemi",
["Severomorsk_1"] = "Severomorsk-1", ["Severomorsk_1"] = "Severomorsk-1",
["Severomorsk_3"] = "Severomorsk-3", ["Severomorsk_3"] = "Severomorsk-3",
["Vuojarvi"] = "Vuojarvi",
["Kirkenes"] = "Kirkenes",
["Kallax"] = "Kallax",
["Vidsel"] = "Vidsel",
} }
--- Airbases of the Afghanistan map --- Airbases of the Afghanistan map

View File

@ -178,7 +178,7 @@ end
-- @param #STATIC self -- @param #STATIC self
-- @return DCS static object -- @return DCS static object
function STATIC:GetDCSObject() function STATIC:GetDCSObject()
local DCSStatic = StaticObject.getByName( self.StaticName ) local DCSStatic = StaticObject.getByName( self.StaticName )
if DCSStatic then if DCSStatic then
return DCSStatic return DCSStatic
@ -330,3 +330,26 @@ function STATIC:FindAllByMatching( Pattern )
return GroupsFound return GroupsFound
end end
--- Get the Wrapper.Storage#STORAGE object of an static if it is used as cargo and has been set up as storage object.
-- @param #STATIC self
-- @return Wrapper.Storage#STORAGE Storage or `nil` if not fund or set up.
function STATIC:GetStaticStorage()
local name = self:GetName()
local storage = STORAGE:NewFromStaticCargo(name)
return storage
end
--- Get the Cargo Weight of a static object in kgs. Returns -1 if not found.
-- @param #STATIC self
-- @return #number Mass Weight in kgs.
function STATIC:GetCargoWeight()
local DCSObject = StaticObject.getByName(self.StaticName )
local mass = -1
if DCSObject then
mass = DCSObject:getCargoWeight() or 0
local masstxt = DCSObject:getCargoDisplayName() or "none"
--BASE:I("GetCargoWeight "..tostring(mass).." MassText "..masstxt)
end
return mass
end

View File

@ -147,9 +147,33 @@ STORAGE.Liquid = {
DIESEL = 3, DIESEL = 3,
} }
--- Liquid Names for the static cargo resource table.
-- @type STORAGE.LiquidName
-- @field #number JETFUEL "jet_fuel".
-- @field #number GASOLINE "gasoline".
-- @field #number MW50 "methanol_mixture".
-- @field #number DIESEL "diesel".
STORAGE.LiquidName = {
GASOLINE = "gasoline",
DIESEL = "diesel",
MW50 = "methanol_mixture",
JETFUEL = "jet_fuel",
}
--- Storage types.
-- @type STORAGE.Type
-- @field #number WEAPONS weapons.
-- @field #number LIQUIDS liquids. Also see #list<#STORAGE.Liquid> for types of liquids.
-- @field #number AIRCRAFT aircraft.
STORAGE.Type = {
WEAPONS = "weapons",
LIQUIDS = "liquids",
AIRCRAFT = "aircrafts",
}
--- STORAGE class version. --- STORAGE class version.
-- @field #string version -- @field #string version
STORAGE.version="0.0.2" STORAGE.version="0.0.3"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list