From bbc539fac66d982739e28c57053829572ae92a2f Mon Sep 17 00:00:00 2001 From: Statua <54192360+Statua@users.noreply.github.com> Date: Fri, 9 Aug 2024 11:16:18 -0500 Subject: [PATCH 1/2] Update ClientWatch.lua (#2155) -Attempted a fix for the documentation -Added GROUPNAME to the prefix check to allow users to check either groupname or unitname -Added IniCategory nil and value check to birth event process to prevent errors and slightly improve performance --- .../Moose/Functional/ClientWatch.lua | 109 +++++++++--------- 1 file changed, 57 insertions(+), 52 deletions(-) diff --git a/Moose Development/Moose/Functional/ClientWatch.lua b/Moose Development/Moose/Functional/ClientWatch.lua index 308937f9c..c2be6ab53 100644 --- a/Moose Development/Moose/Functional/ClientWatch.lua +++ b/Moose Development/Moose/Functional/ClientWatch.lua @@ -1,5 +1,7 @@ --- **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: @@ -10,51 +12,30 @@ -- * 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 -- --- === --- --- ## 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** -- -- ### Contributions: **FlightControl**: Wrapper.CLIENT -- --- === --- +-- ==== -- @module Functional.ClientWatch --- @image ClientWatch.JPG +-- @image clientwatch.jpg ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - --- CLIENTWATCH class -- @type CLIENTWATCH -- @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 #string lid String for DCS log file. -- @extends Core.Fsm#FSM_CONTROLLABLE --- --- Manage and track client slots easily to add your own client-based menus and modules to. -- -- ## 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. - ---- ---**This will not work if the client aircraft is alive!** +-- **This will not work if the client aircraft is alive!** -- -- ### Examples -- @@ -125,34 +106,40 @@ -- -- ### Examples -- - -- -- Show a message to player when they take damage from a weapon - -- local clientInstance = CLIENTWATCH:New("Rotary") - -- function clientInstance:OnAfterSpawn(From,Event,To,ClientObject) - -- function ClientObject:OnAfterHit(From,Event,To,EventData) - -- local typeShooter = EventData.IniTypeName - -- local nameWeapon = EventData.weapon_name - -- MESSAGE:New("A "..typeShooter.." hit you with a "..nameWeapon,20):ToUnit(ClientObject.Unit) - -- end - -- end --- +-- -- Show a message to player when they take damage from a weapon +-- local clientInstance = CLIENTWATCH:New("Rotary") +-- function clientInstance:OnAfterSpawn(From,Event,To,ClientObject) +-- function ClientObject:OnAfterHit(From,Event,To,EventData) +-- local typeShooter = EventData.IniTypeName +-- local nameWeapon = EventData.weapon_name +-- MESSAGE:New("A "..typeShooter.." hit you with a "..nameWeapon,20):ToUnit(ClientObject.Unit) +-- end +-- end -- -- @field #CLIENTWATCH - -CLIENTWATCHTools = {} CLIENTWATCH = {} CLIENTWATCH.ClassName = "CLIENTWATCH" CLIENTWATCH.Debug = false 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. -- @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 function CLIENTWATCH:New(client) --Init FSM @@ -160,6 +147,15 @@ function CLIENTWATCH:New(client) self:SetStartState( "Idle" ) 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 if type(client) == "table" or type(client) == "string" then if type(client) == "table" then @@ -169,9 +165,12 @@ function CLIENTWATCH:New(client) self.ClientName = client:GetName() self:HandleEvent(EVENTS.Birth) function self:OnEventBirth(eventdata) - if self.ClientName == eventdata.IniUnitName and eventdata.IniCategory <= 1 then - local clientObject = CLIENTWATCHTools:_newClient(eventdata) - self:Spawn(clientObject) + if self.Debug then UTILS.PrintTableToLog(eventdata) end + if eventdata.IniCategory and eventdata.IniCategory <= 1 then + if self.ClientName == eventdata.IniUnitName then + local clientObject = CLIENTWATCHTools:_newClient(eventdata) + self:Spawn(clientObject) + end end end @@ -188,11 +187,14 @@ function CLIENTWATCH:New(client) if tableValid then self:HandleEvent(EVENTS.Birth) function self:OnEventBirth(eventdata) + if self.Debug then UTILS.PrintTableToLog(eventdata) end for _,entry in pairs(client) do - if string.match(eventdata.IniUnitName,entry) and eventdata.IniCategory == 1 then - local clientObject = CLIENTWATCHTools:_newClient(eventdata) - self:Spawn(clientObject) - break + if eventdata.IniCategory and eventdata.IniCategory <= 1 then + if string.match(eventdata.IniUnitName,entry) or string.match(eventdata.IniGroupName,entry) then + local clientObject = CLIENTWATCHTools:_newClient(eventdata) + self:Spawn(clientObject) + break + end end end end @@ -203,9 +205,12 @@ function CLIENTWATCH:New(client) --SOLO STRING self:HandleEvent(EVENTS.Birth) function self:OnEventBirth(eventdata) - if string.match(eventdata.IniUnitName,client) and eventdata.IniCategory == 1 then - local clientObject = CLIENTWATCHTools:_newClient(eventdata) - self:Spawn(clientObject) + if self.Debug then UTILS.PrintTableToLog(eventdata) end + if eventdata.IniCategory and eventdata.IniCategory <= 1 then + 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 From 7ae98ef5f9056b2e5d7bfec6d38f5ebd78614bb8 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sat, 10 Aug 2024 09:58:18 +0200 Subject: [PATCH 2/2] # DCS 2.9.7.58923 - Fixes for the Chinhook and handling of dynamically spawned cargo stuff. Additional Kola airbase names. --- Moose Development/Moose/Core/Database.lua | 37 +++ Moose Development/Moose/Core/Spawn.lua | 25 ++ Moose Development/Moose/Core/SpawnStatic.lua | 83 +++++- Moose Development/Moose/Ops/CTLD.lua | 297 ++++++++++++++++--- Moose Development/Moose/Utilities/Utils.lua | 4 +- Moose Development/Moose/Wrapper/Airbase.lua | 10 +- Moose Development/Moose/Wrapper/Static.lua | 25 +- Moose Development/Moose/Wrapper/Storage.lua | 26 +- 8 files changed, 451 insertions(+), 56 deletions(-) diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index 184525502..602f9d469 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -1211,6 +1211,43 @@ function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, Category return self 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. -- @param #DATABASE self -- @param #string StaticName Name of the static. diff --git a/Moose Development/Moose/Core/Spawn.lua b/Moose Development/Moose/Core/Spawn.lua index 5e8621921..1c2610f27 100644 --- a/Moose Development/Moose/Core/Spawn.lua +++ b/Moose Development/Moose/Core/Spawn.lua @@ -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.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) -- @@ -1411,6 +1412,30 @@ function SPAWN:InitArray( SpawnAngle, SpawnWidth, SpawnDeltaX, SpawnDeltaY ) return self 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 --- Turns the AI On or Off for the @{Wrapper.Group} when spawning. diff --git a/Moose Development/Moose/Core/SpawnStatic.lua b/Moose Development/Moose/Core/SpawnStatic.lua index f6a082ddf..965f86f00 100644 --- a/Moose Development/Moose/Core/SpawnStatic.lua +++ b/Moose Development/Moose/Core/SpawnStatic.lua @@ -189,6 +189,7 @@ function SPAWNSTATIC:NewFromType(StaticType, StaticCategory, CountryID) self.InitStaticCategory=StaticCategory self.CountryID=CountryID or country.id.USA self.SpawnTemplatePrefix=self.InitStaticType + self.TemplateStaticUnit = {} self.InitStaticCoordinate=COORDINATE:New(0, 0, 0) self.InitStaticHeading=0 @@ -196,6 +197,61 @@ function SPAWNSTATIC:NewFromType(StaticType, StaticCategory, CountryID) return self 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. -- @param #SPAWNSTATIC self -- @param Core.Point#COORDINATE Coordinate Position where the static is spawned. @@ -317,6 +373,25 @@ function SPAWNSTATIC:InitLinkToUnit(Unit, OffsetX, OffsetY, OffsetAngle) return self 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. -- @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. @@ -488,7 +563,7 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID) -- ED's dirty way to spawn FARPS. 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 local Event = { id = EVENTS.Birth, @@ -503,6 +578,12 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID) self:T2({Template=Template}) Static=coalition.addStaticObject(CountryID, Template) 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 end diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index 8bb2ad496..e32720028 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -24,7 +24,7 @@ -- @module Ops.CTLD -- @image OPS_CTLD.jpg --- Last Update July 2024 +-- Last Update Aug 2024 do @@ -46,6 +46,7 @@ do -- @field #string Subcategory Sub-category name. -- @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 #table ResourceMap Resource Map information table if it has been set for static cargo items. -- @extends Core.Base#BASE --- @@ -122,14 +123,31 @@ CTLD_CARGO = { self.Mark = nil self.Subcategory = Subcategory or "Other" self.DontShowInMenu = DontShowInMenu or false + self.ResourceMap = nil if type(Location) == "string" then Location = ZONE:New(Location) end self.Location = Location return self 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 -- @return Core.Zone#ZONE location or `nil` if not set 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.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. --- --- ## 2.1 User functions +-- my_ctld.enableChinhookGCLoading = true -- this will effectively suppress the crate load and drop menus for CTLD for the Chinhook -- --- ### 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: -- @@ -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 -- ["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}, +-- ["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: -- @@ -793,7 +842,7 @@ do -- -- Deactivate zone called Name of type #CTLD.CargoZoneType ZoneType: -- 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. -- @@ -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}, ["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 = 30, cargoweightlimit = 8000}, + ["CH-47Fbl1"] = {type="CH-47Fbl1", crates=true, troops=true, cratelimit = 4, trooplimit = 31, length = 20, cargoweightlimit = 8000}, } --- CTLD class version. -- @field #string version -CTLD.version="1.0.56" +CTLD.version="1.0.58" --- Instantiate a new CTLD. -- @param #CTLD self @@ -1435,6 +1484,9 @@ function CTLD:New(Coalition, Prefixes, Alias) self.movecratesbeforebuild = true 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," ","_") 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.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. + -- @param Core.Zone#ZONE_Radius ZoneObject of the Zone where the Troops have been RTB'd. --- FSM Function OnAfterTroopsPickedUp. -- @function [parent=#CTLD] OnAfterTroopsPickedUp @@ -1719,8 +1771,6 @@ function CTLD:New(Coalition, Prefixes, Alias) -- @param #string To State. -- @param Wrapper.Group#GROUP Group Group 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. -- @function [parent=#CTLD] OnAfterLoad @@ -1827,7 +1877,7 @@ end -- @param #CTLD self -- @param Core.Event#EVENTDATA 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 if event.id == EVENTS.PlayerEnterAircraft or event.id == EVENTS.PlayerEnterUnit then local _coalition = event.IniCoalition @@ -1851,12 +1901,37 @@ function CTLD:_EventHandler(EventData) self:_RefreshF10Menus() end return - elseif event.id == EVENTS.PlayerLeaveUnit then + elseif event.id == EVENTS.PlayerLeaveUnit or event.id == EVENTS.UnitLost then -- remove from pilot table local unitname = event.IniUnitName or "none" self.CtldUnits[unitname] = nil self.Loaded_Cargo[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 return self end @@ -2422,7 +2497,8 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack) return self end -- 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 number = number or 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 angleOffNose = 0 local addon = 0 - if IsHerc then + if IsHerc or IsHook then -- spawn behind the Herc addon = 180 end @@ -2494,17 +2570,25 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack) dist = dist - (20 + math.random(1,10)) local width = width / 2 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) :InitCargo(self.enableslingload) :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 - self.Spawned_Crates[self.CrateCounter] = SPAWNSTATIC:NewFromType(basetype,"Cargos",self.cratecountry) + local spawnstatic = SPAWNSTATIC:NewFromType(basetype,"Cargos",self.cratecountry) :InitCoordinate(cratecoord) :InitCargoMass(cgomass) :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 local templ = cargotype:GetTemplates() local sorte = cargotype:GetType() @@ -2514,9 +2598,13 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack) if drop then --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) + local map=cargotype:GetStaticResourceMap() + realcargo:SetStaticResourceMap(map) table.insert(droppedcargo,realcargo) 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 table.insert(self.Spawned_Cargo, realcargo) end @@ -2566,14 +2654,18 @@ function CTLD:InjectStatics(Zone, Cargo, RandomCoord) basetype = cratetemplate end 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) :InitCargo(self.enableslingload) :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 sorte = cargotype:GetType() - self.CargoCounter = self.CargoCounter + 1 + --self.CargoCounter = self.CargoCounter + 1 cargotype.Positionable = self.Spawned_Crates[self.CrateCounter] table.insert(self.Spawned_Cargo, cargotype) return self @@ -2600,8 +2692,8 @@ end function CTLD:_ListCratesNearby( _group, _unit) self:T(self.lid .. " _ListCratesNearby") local finddist = self.CrateDistance or 35 - local crates,number = self:_FindCratesNearby(_group,_unit, finddist,true) -- #table - if number > 0 then + local crates,number,loadedbygc,indexgc = self:_FindCratesNearby(_group,_unit, finddist,true) -- #table + if number > 0 or indexgc > 0 then local text = REPORT:New("Crates Found Nearby:") text:Add("------------------------------------------------------------") for _,_entry in pairs (crates) do @@ -2618,6 +2710,19 @@ function CTLD:_ListCratesNearby( _group, _unit) text:Add(" N O N E") end 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) else 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 #number _dist Distance -- @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 #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) self:T(self.lid .. " _FindCratesNearby") local finddist = _dist @@ -2700,7 +2807,9 @@ function CTLD:_FindCratesNearby( _group, _unit, _dist, _ignoreweight) local existingcrates = self.Spawned_Cargo -- #table -- cycle local index = 0 + local indexg = 0 local found = {} + local LoadedbyGC = {} local loadedmass = 0 local unittype = "none" local capabilities = {} @@ -2713,20 +2822,47 @@ function CTLD:_FindCratesNearby( _group, _unit, _dist, _ignoreweight) for _,_cargoobject in pairs (existingcrates) do local cargo = _cargoobject -- #CTLD_CARGO local static = cargo:GetPositionable() -- Wrapper.Static#STATIC -- crates - local staticid = cargo:GetID() local weight = cargo:GetMass() -- weight in kgs of this cargo + local staticid = cargo:GetID() self:T(self.lid .. " Found cargo mass: " .. weight) - if static and static:IsAlive() then - local staticpos = static:GetCoordinate() + local cargoalive = false -- TODO dyn cargo spawn workaround + 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) - 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 table.insert(found, staticid, cargo) maxloadable = maxloadable - weight end + if GCloaded == true and distance < 10 and static then + indexg = indexg + 1 + table.insert(LoadedbyGC,staticid, cargo) + end end end - return found, index + return found, index, LoadedbyGC, indexg end --- (Internal) Function to get and load nearby crates. @@ -2748,6 +2884,13 @@ function CTLD:_LoadCratesNearby(Group, Unit) local cratelimit = capabilities.cratelimit -- #number local grounded = not self:IsUnitInAir(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 ------------------------------- -- Chopper can\'t do crates - bark & return -- Chopper can do crates - @@ -2925,7 +3068,9 @@ function CTLD:_ListCargo(Group, Unit) local loadedcargo = self.Loaded_Cargo[unitname] or {} -- #CTLD.LoadedCargo local loadedmass = self:_GetUnitCargoMass(Unit) -- #number 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_crates = loadedcargo.Cratesloaded or 0 local cargotable = loadedcargo.Cargo or {} -- #table @@ -2947,7 +3092,7 @@ function CTLD:_ListCargo(Group, Unit) report:Add("------------------------------------------------------------") report:Add(" -- CRATES --") local cratecount = 0 - for _,_cargo in pairs(cargotable) do + for _,_cargo in pairs(cargotable 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) and (not cargo:WasDropped() or self.allowcratepickupagain) then @@ -2958,6 +3103,18 @@ function CTLD:_ListCargo(Group, Unit) if cratecount == 0 then report:Add(" N O N E") 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("Total Mass: ".. loadedmass .. " kg. Loadable: "..maxloadable.." kg.") local text = report:Text() @@ -3062,7 +3219,7 @@ function CTLD:_ListInventory(Group, Unit) return self 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 Wrapper.Unit#UNIT Unit -- @return #boolean Outcome @@ -3074,6 +3231,17 @@ function CTLD:IsHercules(Unit) 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 -- @param #CTLD self @@ -3126,8 +3294,9 @@ function CTLD:_UnloadTroops(Group, Unit) end -- check for hover unload local hoverunload = self:IsCorrectHover(Unit) --if true we\'re hovering in parameters - local IsHerc = self:IsHercules(Unit) - if IsHerc then + local IsHerc = self:IsHercules(Unit) + local IsHook = self:IsHook(Unit) + if IsHerc and (not IsHook) then -- no hover but airdrop here hoverunload = self:IsCorrectFlightParameters(Unit) end @@ -3256,10 +3425,16 @@ function CTLD:_UnloadCrates(Group, Unit) 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 local hoverunload = self:IsCorrectHover(Unit) --if true we\'re hovering in parameters local IsHerc = self:IsHercules(Unit) - if IsHerc then + local IsHook = self:IsHook(Unit) + if IsHerc and (not IsHook) then -- no hover but airdrop here hoverunload = self:IsCorrectFlightParameters(Unit) end @@ -3726,6 +3901,8 @@ function CTLD:_RefreshF10Menus() local capabilities = self:_GetUnitCapabilities(_unit) -- #CTLD.UnitTypeCapabilities local cantroops = capabilities.troops local cancrates = capabilities.crates + local isHook = self:IsHook(_unit) + local nohookswitch = not (isHook and self.enableChinhookGCLoading) -- top menu local topmenu = MENU_GROUP:New(_group,"CTLD",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() end -- sub menu crates management - if cancrates then - local loadmenu = MENU_GROUP_COMMAND:New(_group,"Load crates",topcrates, self._LoadCratesNearby, self, _group, _unit) + if cancrates then + 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 packmenu = MENU_GROUP_COMMAND:New(_group, "Pack crates", topcrates, self._PackCratesNearby, self, _group, _unit) local removecratesmenu = MENU_GROUP:New(_group, "Remove crates", topcrates) @@ -3851,11 +4030,14 @@ function CTLD:_RefreshF10Menus() end 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 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 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() - else + elseif unloadmenu then unloadmenu:Refresh() end end @@ -3948,15 +4130,22 @@ end -- @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 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) self:T(self.lid .. " AddStaticsCargo") self.CargoCounter = self.CargoCounter + 1 local type = CTLD_CARGO.Enum.STATIC 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 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) - return self + return cargo end --- 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 local type = CTLD_CARGO.Enum.STATIC 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 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) return cargo end @@ -5336,7 +5531,9 @@ end -- Events self:HandleEvent(EVENTS.PlayerEnterAircraft, 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) -- AutoSave @@ -5600,7 +5797,7 @@ end -- @param Wrapper.Group#GROUP Group Group 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. + -- @param Core.Zone#ZONE_Radius ZoneObject of the Zone where the Troops have been RTB'd. -- @return #CTLD self function CTLD:onbeforeTroopsRTB(From, Event, To, Group, Unit, ZoneName, ZoneObject) self:T({From, Event, To}) @@ -5948,7 +6145,9 @@ end cargotemplates = UTILS.Split(cargotemplates,";") 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 - 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 if injectstatic then self:InjectStatics(dropzone,injectstatic) @@ -6304,6 +6503,8 @@ function CTLD_HERCULES:Cargo_SpawnDroppedAsCargo(_name, _pos) 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 map=theCargo:GetStaticResourceMap() + newCargo:SetStaticResourceMap(map) table.insert(self.CTLD.Spawned_Cargo, newCargo) 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 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) else self:Cargo_SpawnGroup(Cargo_Drop_initiator,Cargo_Content_position, Cargo_Type_name, CargoHeading, Cargo_Country) diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua index 033157ee3..d347cc082 100644 --- a/Moose Development/Moose/Utilities/Utils.lua +++ b/Moose Development/Moose/Utilities/Utils.lua @@ -2319,8 +2319,8 @@ function UTILS.IsLoadingDoorOpen( unit_name ) BASE:T(unit_name .. " cargo door is open") return true 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") return true end diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua index 23d82593a..4d9e068a1 100644 --- a/Moose Development/Moose/Wrapper/Airbase.lua +++ b/Moose Development/Moose/Wrapper/Airbase.lua @@ -721,11 +721,12 @@ AIRBASE.Sinai = { --- Airbases of the Kola map -- -- * AIRBASE.Kola.Banak --- * AIRBASE.Kola.Bas_100 -- * AIRBASE.Kola.Bodo -- * AIRBASE.Kola.Jokkmokk -- * AIRBASE.Kola.Kalixfors +-- * AIRBASE.Kola.Kallax -- * AIRBASE.Kola.Kemi_Tornio +-- * AIRBASE.Kola.Kirkenes -- * AIRBASE.Kola.Kiruna -- * AIRBASE.Kola.Monchegorsk -- * AIRBASE.Kola.Murmansk_International @@ -733,11 +734,12 @@ AIRBASE.Sinai = { -- * AIRBASE.Kola.Rovaniemi -- * AIRBASE.Kola.Severomorsk_1 -- * AIRBASE.Kola.Severomorsk_3 +-- * AIRBASE.Kola.Vidsel +-- * AIRBASE.Kola.Vuojarvi -- -- @field Kola AIRBASE.Kola = { ["Banak"] = "Banak", - ["Bas_100"] = "Bas 100", ["Bodo"] = "Bodo", ["Jokkmokk"] = "Jokkmokk", ["Kalixfors"] = "Kalixfors", @@ -749,6 +751,10 @@ AIRBASE.Kola = { ["Rovaniemi"] = "Rovaniemi", ["Severomorsk_1"] = "Severomorsk-1", ["Severomorsk_3"] = "Severomorsk-3", + ["Vuojarvi"] = "Vuojarvi", + ["Kirkenes"] = "Kirkenes", + ["Kallax"] = "Kallax", + ["Vidsel"] = "Vidsel", } --- Airbases of the Afghanistan map diff --git a/Moose Development/Moose/Wrapper/Static.lua b/Moose Development/Moose/Wrapper/Static.lua index 916b78a84..557d117cc 100644 --- a/Moose Development/Moose/Wrapper/Static.lua +++ b/Moose Development/Moose/Wrapper/Static.lua @@ -178,7 +178,7 @@ end -- @param #STATIC self -- @return DCS static object function STATIC:GetDCSObject() - local DCSStatic = StaticObject.getByName( self.StaticName ) + local DCSStatic = StaticObject.getByName( self.StaticName ) if DCSStatic then return DCSStatic @@ -330,3 +330,26 @@ function STATIC:FindAllByMatching( Pattern ) return GroupsFound 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 diff --git a/Moose Development/Moose/Wrapper/Storage.lua b/Moose Development/Moose/Wrapper/Storage.lua index 6f154c575..9e750d779 100644 --- a/Moose Development/Moose/Wrapper/Storage.lua +++ b/Moose Development/Moose/Wrapper/Storage.lua @@ -147,9 +147,33 @@ STORAGE.Liquid = { 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. -- @field #string version -STORAGE.version="0.0.2" +STORAGE.version="0.0.3" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list