diff --git a/Moose Development/Moose/Core/Base.lua b/Moose Development/Moose/Core/Base.lua index fa3d4fcfd..94d13a9a0 100644 --- a/Moose Development/Moose/Core/Base.lua +++ b/Moose Development/Moose/Core/Base.lua @@ -741,7 +741,31 @@ do -- Event Handling -- @function [parent=#BASE] OnEventPlayerEnterAircraft -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. - + + --- Occurs when a player creates a dynamic cargo object from the F8 ground crew menu. + -- *** NOTE *** this is a workarounf for DCS not creating these events as of Aug 2024. + -- @function [parent=#BASE] OnEventNewDynamicCargo + -- @param #BASE self + -- @param Core.Event#EVENTDATA EventData The EventData structure. + + --- Occurs when a player loads a dynamic cargo object with the F8 ground crew menu into a helo. + -- *** NOTE *** this is a workarounf for DCS not creating these events as of Aug 2024. + -- @function [parent=#BASE] OnEventDynamicCargoLoaded + -- @param #BASE self + -- @param Core.Event#EVENTDATA EventData The EventData structure. + + --- Occurs when a player unloads a dynamic cargo object with the F8 ground crew menu from a helo. + -- *** NOTE *** this is a workarounf for DCS not creating these events as of Aug 2024. + -- @function [parent=#BASE] OnEventDynamicCargoUnloaded + -- @param #BASE self + -- @param Core.Event#EVENTDATA EventData The EventData structure. + + --- Occurs when a dynamic cargo crate is removed. + -- *** NOTE *** this is a workarounf for DCS not creating these events as of Aug 2024. + -- @function [parent=#BASE] OnEventDynamicCargoRemoved + -- @param #BASE self + -- @param Core.Event#EVENTDATA EventData The EventData structure. + end --- Creation of a Birth Event. @@ -862,6 +886,62 @@ end world.onEvent(Event) end + + --- Creation of a S_EVENT_NEW_DYNAMIC_CARGO event. + -- @param #BASE self + -- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object + function BASE:CreateEventNewDynamicCargo(DynamicCargo) + self:F({DynamicCargo}) + local Event = { + id = EVENTS.NewDynamicCargo, + time = timer.getTime(), + dynamiccargo = DynamicCargo, + initiator = DynamicCargo:GetDCSObject(), + } + world.onEvent( Event ) + end + + --- Creation of a S_EVENT_DYNAMIC_CARGO_LOADED event. + -- @param #BASE self + -- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object + function BASE:CreateEventDynamicCargoLoaded(DynamicCargo) + self:F({DynamicCargo}) + local Event = { + id = EVENTS.DynamicCargoLoaded, + time = timer.getTime(), + dynamiccargo = DynamicCargo, + initiator = DynamicCargo:GetDCSObject(), + } + world.onEvent( Event ) + end + + --- Creation of a S_EVENT_DYNAMIC_CARGO_UNLOADED event. + -- @param #BASE self + -- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object + function BASE:CreateEventDynamicCargoUnloaded(DynamicCargo) + self:F({DynamicCargo}) + local Event = { + id = EVENTS.DynamicCargoUnloaded, + time = timer.getTime(), + dynamiccargo = DynamicCargo, + initiator = DynamicCargo:GetDCSObject(), + } + world.onEvent( Event ) + end + + --- Creation of a S_EVENT_DYNAMIC_CARGO_REMOVED event. + -- @param #BASE self + -- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object + function BASE:CreateEventDynamicCargoRemoved(DynamicCargo) + self:F({DynamicCargo}) + local Event = { + id = EVENTS.DynamicCargoRemoved, + time = timer.getTime(), + dynamiccargo = DynamicCargo, + initiator = DynamicCargo:GetDCSObject(), + } + world.onEvent( Event ) + end --- The main event handling function... This function captures all events generated for the class. -- @param #BASE self diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index 602f9d469..5ce11f221 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -20,6 +20,7 @@ -- * Manage database of hits to units and statics. -- * Manage database of destroys of units and statics. -- * Manage database of @{Core.Zone#ZONE_BASE} objects. +-- * Manage database of @{Wrapper.DynamicCargo#DYNAMICCARGO} objects alive in the mission. -- -- === -- @@ -39,6 +40,7 @@ -- @field #table STORAGES DCS warehouse storages. -- @field #table STNS Used Link16 octal numbers for F16/15/18/AWACS planes. -- @field #table SADL Used Link16 octal numbers for A10/C-II planes. +-- @field #table DYNAMICCARGO Dynamic Cargo objects. -- @extends Core.Base#BASE --- Contains collections of wrapper objects defined within MOOSE that reflect objects within the simulator. @@ -54,6 +56,7 @@ -- * PLAYERS -- * CARGOS -- * STORAGES (DCS warehouses) +-- * DYNAMICCARGO -- -- On top, for internal MOOSE administration purposes, the DATABASE administers the Unit and Group TEMPLATES as defined within the Mission Editor. -- @@ -97,6 +100,7 @@ DATABASE = { STORAGES = {}, STNS={}, SADL={}, + DYNAMICCARGO={}, } local _DATABASECoalition = @@ -143,6 +147,8 @@ function DATABASE:New() self:HandleEvent( EVENTS.DeleteZone ) --self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventOnPlayerEnterUnit ) -- This is not working anymore!, handling this through the birth event. self:HandleEvent( EVENTS.PlayerLeaveUnit, self._EventOnPlayerLeaveUnit ) + -- DCS 2.9.7 Moose own dynamic cargo events + self:HandleEvent( EVENTS.DynamicCargoRemoved, self._EventOnDynamicCargoRemoved) self:_RegisterTemplates() self:_RegisterGroupsAndUnits() @@ -224,6 +230,34 @@ function DATABASE:FindStatic( StaticName ) return StaticFound end +--- Add a DynamicCargo to the database. +-- @param #DATABASE self +-- @param #string Name Name of the dynamic cargo. +-- @return Wrapper.DynamicCargo#DYNAMICCARGO The dynamic cargo object. +function DATABASE:AddDynamicCargo( Name ) + if not self.DYNAMICCARGO[Name] then + self.DYNAMICCARGO[Name] = DYNAMICCARGO:Register(Name) + return self.DYNAMICCARGO[Name] + end + return nil +end + +--- Finds a DYNAMICCARGO based on the Dynamic Cargo Name. +-- @param #DATABASE self +-- @param #string DynamicCargoName +-- @return Wrapper.DynamicCargo#DYNAMICCARGO The found DYNAMICCARGO. +function DATABASE:FindDynamicCargo( DynamicCargoName ) + local StaticFound = self.DYNAMICCARGO[DynamicCargoName] + return StaticFound +end + +--- Deletes a DYNAMICCARGO from the DATABASE based on the Dynamic Cargo Name. +-- @param #DATABASE self +function DATABASE:DeleteDynamicCargo( DynamicCargoName ) + self.DYNAMICCARGO[DynamicCargoName] = nil + return self +end + --- Adds a Airbase based on the Airbase Name in the DATABASE. -- @param #DATABASE self -- @param #string AirbaseName The name of the airbase. @@ -1244,7 +1278,7 @@ function DATABASE:_GetGenericStaticCargoGroupTemplate(Name,Typename,Mass,Coaliti StaticTemplate.CategoryID = "static" StaticTemplate.CoalitionID = Coalition or coalition.side.BLUE StaticTemplate.CountryID = Country or country.id.GERMANY - UTILS.PrintTableToLog(StaticTemplate) + --UTILS.PrintTableToLog(StaticTemplate) return StaticTemplate end @@ -1568,7 +1602,7 @@ end -- @param #DATABASE self -- @param Core.Event#EVENTDATA Event function DATABASE:_EventOnBirth( Event ) - self:F( { Event } ) + self:T( { Event } ) if Event.IniDCSUnit then @@ -1576,7 +1610,17 @@ function DATABASE:_EventOnBirth( Event ) -- Add static object to DB. self:AddStatic( Event.IniDCSUnitName ) + + elseif Event.IniObjectCategory == Object.Category.CARGO and string.match(Event.IniUnitName,".+|%d%d:%d%d|PKG%d+") then + -- Add dynamic cargo object to DB + + local cargo = self:AddDynamicCargo(Event.IniDCSUnitName) + + self:I(string.format("Adding dynamic cargo %s", tostring(Event.IniDCSUnitName))) + + self:CreateEventNewDynamicCargo( cargo ) + else if Event.IniObjectCategory == Object.Category.UNIT then @@ -1762,6 +1806,15 @@ function DATABASE:_EventOnPlayerEnterUnit( Event ) end end +--- Handles the OnDynamicCargoRemoved event to clean the active dynamic cargo table. +-- @param #DATABASE self +-- @param Core.Event#EVENTDATA Event +function DATABASE:_EventOnDynamicCargoRemoved( Event ) + self:T( { Event } ) + if Event.IniDynamicCargoName then + self:DeleteDynamicCargo(Event.IniDynamicCargoName) + end +end --- Handles the OnPlayerLeaveUnit event to clean the active players table. -- @param #DATABASE self diff --git a/Moose Development/Moose/Core/Event.lua b/Moose Development/Moose/Core/Event.lua index 1d713607c..3997fbdf5 100644 --- a/Moose Development/Moose/Core/Event.lua +++ b/Moose Development/Moose/Core/Event.lua @@ -194,6 +194,11 @@ world.event.S_EVENT_NEW_ZONE_GOAL = world.event.S_EVENT_MAX + 1004 world.event.S_EVENT_DELETE_ZONE_GOAL = world.event.S_EVENT_MAX + 1005 world.event.S_EVENT_REMOVE_UNIT = world.event.S_EVENT_MAX + 1006 world.event.S_EVENT_PLAYER_ENTER_AIRCRAFT = world.event.S_EVENT_MAX + 1007 +-- dynamic cargo +world.event.S_EVENT_NEW_DYNAMIC_CARGO = world.event.S_EVENT_MAX + 1008 +world.event.S_EVENT_DYNAMIC_CARGO_LOADED = world.event.S_EVENT_MAX + 1009 +world.event.S_EVENT_DYNAMIC_CARGO_UNLOADED = world.event.S_EVENT_MAX + 1010 +world.event.S_EVENT_DYNAMIC_CARGO_REMOVED = world.event.S_EVENT_MAX + 1011 --- The different types of events supported by MOOSE. @@ -275,7 +280,12 @@ EVENTS = { SimulationFreeze = world.event.S_EVENT_SIMULATION_FREEZE or -1, SimulationUnfreeze = world.event.S_EVENT_SIMULATION_UNFREEZE or -1, HumanAircraftRepairStart = world.event.S_EVENT_HUMAN_AIRCRAFT_REPAIR_START or -1, - HumanAircraftRepairFinish = world.event.S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH or -1, + HumanAircraftRepairFinish = world.event.S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH or -1, + -- dynamic cargo + NewDynamicCargo = world.event.S_EVENT_NEW_DYNAMIC_CARGO or -1, + DynamicCargoLoaded = world.event.S_EVENT_DYNAMIC_CARGO_LOADED or -1, + DynamicCargoUnloaded = world.event.S_EVENT_DYNAMIC_CARGO_UNLOADED or -1, + DynamicCargoRemoved = world.event.S_EVENT_DYNAMIC_CARGO_REMOVED or -1, } @@ -334,6 +344,9 @@ EVENTS = { -- -- @field Core.Zone#ZONE Zone The zone object. -- @field #string ZoneName The name of the zone. +-- +-- @field Wrapper.DynamicCargo#DYNAMICCARGO IniDynamicCargo The dynamic cargo object. +-- @field #string IniDynamicCargoName The dynamic cargo unit name. @@ -730,6 +743,31 @@ local _EVENTMETA = { Side = "I", Event = "OnEventHumanAircraftRepairFinish", Text = "S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH" + }, + -- dynamic cargo + [EVENTS.NewDynamicCargo] = { + Order = 1, + Side = "I", + Event = "OnEventNewDynamicCargo", + Text = "S_EVENT_NEW_DYNAMIC_CARGO" + }, + [EVENTS.DynamicCargoLoaded] = { + Order = 1, + Side = "I", + Event = "OnEventDynamicCargoLoaded", + Text = "S_EVENT_DYNAMIC_CARGO_LOADED" + }, + [EVENTS.DynamicCargoUnloaded] = { + Order = 1, + Side = "I", + Event = "OnEventDynamicCargoUnloaded", + Text = "S_EVENT_DYNAMIC_CARGO_UNLOADED" + }, + [EVENTS.DynamicCargoRemoved] = { + Order = 1, + Side = "I", + Event = "OnEventDynamicCargoRemoved", + Text = "S_EVENT_DYNAMIC_CARGO_REMOVED" }, } @@ -1146,7 +1184,63 @@ do -- Event Creation world.onEvent( Event ) end - + + --- Creation of a S_EVENT_NEW_DYNAMIC_CARGO event. + -- @param #EVENT self + -- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object + function EVENT:CreateEventNewDynamicCargo(DynamicCargo) + self:F({DynamicCargo}) + local Event = { + id = EVENTS.NewDynamicCargo, + time = timer.getTime(), + dynamiccargo = DynamicCargo, + initiator = DynamicCargo:GetDCSObject(), + } + world.onEvent( Event ) + end + + --- Creation of a S_EVENT_DYNAMIC_CARGO_LOADED event. + -- @param #EVENT self + -- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object + function EVENT:CreateEventDynamicCargoLoaded(DynamicCargo) + self:F({DynamicCargo}) + local Event = { + id = EVENTS.DynamicCargoLoaded, + time = timer.getTime(), + dynamiccargo = DynamicCargo, + initiator = DynamicCargo:GetDCSObject(), + } + world.onEvent( Event ) + end + + --- Creation of a S_EVENT_DYNAMIC_CARGO_UNLOADED event. + -- @param #EVENT self + -- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object + function EVENT:CreateEventDynamicCargoUnloaded(DynamicCargo) + self:F({DynamicCargo}) + local Event = { + id = EVENTS.DynamicCargoUnloaded, + time = timer.getTime(), + dynamiccargo = DynamicCargo, + initiator = DynamicCargo:GetDCSObject(), + } + world.onEvent( Event ) + end + + --- Creation of a S_EVENT_DYNAMIC_CARGO_REMOVED event. + -- @param #EVENT self + -- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object + function EVENT:CreateEventDynamicCargoRemoved(DynamicCargo) + self:F({DynamicCargo}) + local Event = { + id = EVENTS.DynamicCargoRemoved, + time = timer.getTime(), + dynamiccargo = DynamicCargo, + initiator = DynamicCargo:GetDCSObject(), + } + world.onEvent( Event ) + end + end --- Main event function. @@ -1261,7 +1355,13 @@ function EVENT:onEvent( Event ) Event.IniDCSUnit = Event.initiator Event.IniDCSUnitName = Event.IniDCSUnit:getName() Event.IniUnitName = Event.IniDCSUnitName - Event.IniUnit = CARGO:FindByName( Event.IniDCSUnitName ) + if string.match(Event.IniUnitName,".+|%d%d:%d%d|PKG%d+") then + Event.IniDynamicCargo = DYNAMICCARGO:FindByName(Event.IniUnitName) + Event.IniDynamicCargoName = Event.IniUnitName + Event.IniPlayerName = string.match(Event.IniUnitName,"^(.+)|%d%d:%d%d|PKG%d+") + else + Event.IniUnit = CARGO:FindByName( Event.IniDCSUnitName ) + end Event.IniCoalition = Event.IniDCSUnit:getCoalition() Event.IniCategory = Event.IniDCSUnit:getDesc().category Event.IniTypeName = Event.IniDCSUnit:getTypeName() @@ -1425,6 +1525,12 @@ function EVENT:onEvent( Event ) Event.Cargo = Event.cargo Event.CargoName = Event.cargo.Name end + + -- Dynamic cargo Object + if Event.dynamiccargo then + Event.IniDynamicCargo = Event.dynamiccargo + Event.IniDynamicCargoName = Event.IniDynamicCargo.StaticName + end -- Zone object. if Event.zone then diff --git a/Moose Development/Moose/Modules_local.lua b/Moose Development/Moose/Modules_local.lua index ecb494af1..15c6bcba5 100644 --- a/Moose Development/Moose/Modules_local.lua +++ b/Moose Development/Moose/Modules_local.lua @@ -47,6 +47,7 @@ __Moose.Include( 'Wrapper\\Marker.lua' ) __Moose.Include( 'Wrapper\\Net.lua' ) __Moose.Include( 'Wrapper\\Weapon.lua' ) __Moose.Include( 'Wrapper\\Storage.lua' ) +__Moose.Include( 'Wrapper\\DynamicCargo.lua' ) __Moose.Include( 'Cargo\\Cargo.lua' ) __Moose.Include( 'Cargo\\CargoUnit.lua' ) @@ -81,6 +82,7 @@ __Moose.Include( 'Functional\\AICSAR.lua' ) __Moose.Include( 'Functional\\AmmoTruck.lua' ) __Moose.Include( 'Functional\\Tiresias.lua' ) __Moose.Include( 'Functional\\Stratego.lua' ) +__Moose.Include( 'Functional\\ClientWatch.lua' ) __Moose.Include( 'Ops\\Airboss.lua' ) __Moose.Include( 'Ops\\RecoveryTanker.lua' ) diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index 93b9e7013..d416f9a67 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -1879,7 +1879,7 @@ end -- @param #CTLD self -- @param Core.Event#EVENTDATA EventData function CTLD:_EventHandler(EventData) - self:I(string.format("%s Event = %d",self.lid, EventData.id)) + self:T(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 @@ -1930,7 +1930,7 @@ function CTLD:_EventHandler(EventData) table.insert(self.Spawned_Cargo, cargotype) end end - self:ScheduleOnce(0.5,RegisterDynamicCargo) + --self:ScheduleOnce(0.5,RegisterDynamicCargo) --------------- -- End new dynamic cargo system Handling -------------- diff --git a/Moose Development/Moose/Wrapper/DynamicCargo.lua b/Moose Development/Moose/Wrapper/DynamicCargo.lua new file mode 100644 index 000000000..82b9074bb --- /dev/null +++ b/Moose Development/Moose/Wrapper/DynamicCargo.lua @@ -0,0 +1,381 @@ +--- **Wrapper** - Dynamic Cargo create from the F8 menu. +-- +-- ## Main Features: +-- +-- * Convenient access to DCS API functions +-- +-- === +-- +-- ## Example Missions: +-- +-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/Wrapper/Storage). +-- +-- === +-- +-- ### Author: **Applevangelist** +-- +-- === +-- @module Wrapper.DynamicCargo +-- @image Wrapper_Storage.png + + +--- DYNAMICCARGO class. +-- @type DYNAMICCARGO +-- @field #string ClassName Name of the class. +-- @field #number verbose Verbosity level. +-- @field #string lid Class id string for output to DCS log file. +-- @field Wrapper.Storage#STORAGE warehouse The STORAGE object. +-- @field #string version. +-- @field #string CargoState. +-- @field #table DCS#Vec3 LastPosition. +-- @field #number Interval Check Interval. 20 secs default. +-- @field #boolean testing +-- @extends Wrapper.Positionable#POSITIONABLE + +--- *The capitalist cannot store labour-power in warehouses after he has bought it, as he may do with the raw material.* -- Karl Marx +-- +-- === +-- +-- # The DYNAMICCARGO Concept +-- +-- The DYNAMICCARGO class offers an easy-to-use wrapper interface to all DCS API functions of DCS dynamically spawned cargo crates. +-- We named the class DYNAMICCARGO, because the name WAREHOUSE is already taken by another MOOSE class.. +-- +-- # Constructor +-- +-- @field #DYNAMICCARGO +DYNAMICCARGO = { + ClassName = "DYNAMICCARGO", + verbose = 0, + testing = true, +} + +--- Liquid types. +-- @type DYNAMICCARGO.Liquid +-- @field #number JETFUEL Jet fuel (0). +-- @field #number GASOLINE Aviation gasoline (1). +-- @field #number MW50 MW50 (2). +-- @field #number DIESEL Diesel (3). +DYNAMICCARGO.Liquid = { + JETFUEL = 0, + GASOLINE = 1, + MW50 = 2, + DIESEL = 3, +} + +--- Liquid Names for the static cargo resource table. +-- @type DYNAMICCARGO.LiquidName +-- @field #number JETFUEL "jet_fuel". +-- @field #number GASOLINE "gasoline". +-- @field #number MW50 "methanol_mixture". +-- @field #number DIESEL "diesel". +DYNAMICCARGO.LiquidName = { + GASOLINE = "gasoline", + DIESEL = "diesel", + MW50 = "methanol_mixture", + JETFUEL = "jet_fuel", +} + +--- Storage types. +-- @type DYNAMICCARGO.Type +-- @field #number WEAPONS weapons. +-- @field #number LIQUIDS liquids. Also see #list<#DYNAMICCARGO.Liquid> for types of liquids. +-- @field #number AIRCRAFT aircraft. +DYNAMICCARGO.Type = { + WEAPONS = "weapons", + LIQUIDS = "liquids", + AIRCRAFT = "aircrafts", +} + +--- State types +-- @type DYNAMICCARGO.State +-- @field #string NEW +-- @field #string LOADED +-- @field #string UNLOADED +-- @field #string REMOVED +DYNAMICCARGO.State = { + NEW = "NEW", + LOADED = "LOADED", + UNLOADED = "UNLOADED", + REMOVED = "REMOVED", +} + +--- Helo types possible. +-- @type DYNAMICCARGO.AircraftTypes +DYNAMICCARGO.AircraftTypes = { + ["CH-47Fbl1"] = "CH-47Fbl1", +} + +--- Helo types possible. +-- @type DYNAMICCARGO.AircraftDimensions +DYNAMICCARGO.AircraftDimensions = { + ["CH-47Fbl1"] = { + ["width"] = 8, + ["height"] = 6, + ["length"] = 22, + ["ropelength"] = 30, + }, +} + +--- DYNAMICCARGO class version. +-- @field #string version +DYNAMICCARGO.version="0.0.1" + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- TODO list +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +-- TODO: A lot... + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- Constructor +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +--- Create a new DYNAMICCARGO object from the DCS static cargo object. +-- @param #DYNAMICCARGO self +-- @param #string CargoName Name of the Cargo. +-- @return #DYNAMICCARGO self +function DYNAMICCARGO:Register(CargoName) + + -- Inherit everything from BASE class. + local self=BASE:Inherit(self, POSITIONABLE:New(CargoName)) -- #DYNAMICCARGO + + self.StaticName = CargoName + + self.LastPosition = self:GetCoordinate() + + self.CargoState = DYNAMICCARGO.State.NEW + + self.Interval = 10 + + local DCSObject = self:GetDCSObject() + + if DCSObject then + local warehouse = STORAGE:NewFromDynamicCargo(CargoName) + self.warehouse = warehouse + end + + self.lid = string.format("DYNAMICCARGO %s", CargoName) + + self:ScheduleOnce(self.Interval,DYNAMICCARGO._UpdatePosition,self) + + if not _DYNAMICCARGO_HELOS then + _DYNAMICCARGO_HELOS = SET_CLIENT:New():FilterAlive():FilterFunction(DYNAMICCARGO._FilterHeloTypes):FilterStart() + end + + return self +end + +--- Get DCS object. +-- @param #DYNAMICCARGO self +-- @return DCS static object +function DYNAMICCARGO:GetDCSObject() + local DCSStatic = Unit.getByName( self.StaticName ) + if DCSStatic then + return DCSStatic + end + return nil +end + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- User API Functions +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +--- Find last known position of this DYNAMICCARGO +-- @param #DYNAMICCARGO self +-- @return DCS#Vec3 Position in 3D space +function DYNAMICCARGO:GetLastPosition() + return self.LastPosition +end + +--- Find current state of this DYNAMICCARGO +-- @param #DYNAMICCARGO self +-- @return string The current state +function DYNAMICCARGO:GetState() + return self.CargoState +end + +--- Find a DYNAMICCARGO in the **_DATABASE** using the name associated with it. +-- @param #DYNAMICCARGO self +-- @param #string Name The dynamic cargo name +-- @return #DYNAMICCARGO self +function DYNAMICCARGO:FindByName( Name ) + local storage = _DATABASE:FindDynamicCargo( Name ) + return storage +end + +--- Find the first(!) DYNAMICCARGO matching using patterns. Note that this is **a lot** slower than `:FindByName()`! +-- @param #DYNAMICCARGO self +-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_\(Regular_Expressions\)) for regular expressions in LUA. +-- @return #DYNAMICCARGO The DYNAMICCARGO. +-- @usage +-- -- Find a dynamic cargo with a partial dynamic cargo name +-- local grp = DYNAMICCARGO:FindByMatching( "Apple" ) +-- -- will return e.g. a dynamic cargo named "Apple|08:00|PKG08" +-- +-- -- using a pattern +-- local grp = DYNAMICCARGO:FindByMatching( ".%d.%d$" ) +-- -- will return the first dynamic cargo found ending in "-1-1" to "-9-9", but not e.g. "-10-1" +function DYNAMICCARGO:FindByMatching( Pattern ) + local GroupFound = nil + + for name,static in pairs(_DATABASE.DYNAMICCARGO) do + if string.match(name, Pattern ) then + GroupFound = static + break + end + end + + return GroupFound +end + +--- Find all DYNAMICCARGO objects matching using patterns. Note that this is **a lot** slower than `:FindByName()`! +-- @param #DYNAMICCARGO self +-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_\(Regular_Expressions\)) for regular expressions in LUA. +-- @return #table Groups Table of matching #DYNAMICCARGO objects found +-- @usage +-- -- Find all dynamic cargo with a partial dynamic cargo name +-- local grptable = DYNAMICCARGO:FindAllByMatching( "Apple" ) +-- -- will return all dynamic cargos with "Apple" in the name +-- +-- -- using a pattern +-- local grp = DYNAMICCARGO:FindAllByMatching( ".%d.%d$" ) +-- -- will return the all dynamic cargos found ending in "-1-1" to "-9-9", but not e.g. "-10-1" or "-1-10" +function DYNAMICCARGO:FindAllByMatching( Pattern ) + local GroupsFound = {} + + for name,static in pairs(_DATABASE.DYNAMICCARGO) do + if string.match(name, Pattern ) then + GroupsFound[#GroupsFound+1] = static + end + end + + return GroupsFound +end + +--- Get the #STORAGE object from this dynamic cargo. +-- @param #DYNAMICCARGO self +-- @return Wrapper.Storage#STORAGE Storage The #STORAGE object +function DYNAMICCARGO:GetStorageObject() + return self.warehouse +end + +--- Get the weight in kgs from this dynamic cargo. +-- @param #DYNAMICCARGO self +-- @return #number Weight in kgs. +function DYNAMICCARGO:GetCargoWeight() + local DCSObject = self:GetDCSObject() + if DCSObject then + local weight = DCSObject:getCargoWeight() + return weight + else + return 0 + end +end + +--- Get the cargo display name from this dynamic cargo. +-- @param #DYNAMICCARGO self +-- @return #string The display name +function DYNAMICCARGO:GetCargoDisplayName() + local DCSObject = self:GetDCSObject() + if DCSObject then + local weight = DCSObject:getCargoDisplayName() + return weight + else + return self.StaticName + end +end + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- Private Functions +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +--- [Internal] Update internal states. +-- @param #DYNAMICCARGO self +-- @return #DYNAMICCARGO self +function DYNAMICCARGO:_UpdatePosition() + self:T(self.lid.." _UpdatePositionAndState") + if self:IsAlive() then + local pos = self:GetCoordinate() + if self.testing then + self:I(string.format("Cargo position: x=%d, y=%d, z=%d",pos.x,pos.y,pos.z)) + self:I(string.format("Last position: x=%d, y=%d, z=%d",self.LastPosition.x,self.LastPosition.y,self.LastPosition.z)) + end + if UTILS.Round(UTILS.VecDist3D(pos,self.LastPosition),2) > 0.5 then + -- moved + if self.CargoState == DYNAMICCARGO.State.NEW then + self:I(self.lid.." moved! NEW -> LOADED") + self.CargoState = DYNAMICCARGO.State.LOADED + _DATABASE:CreateEventDynamicCargoLoaded(self) + elseif self.CargoState == DYNAMICCARGO.State.LOADED then + -- TODO add checker if we are in flight somehow + -- ensure not just the helo is moving + local count = _DYNAMICCARGO_HELOS:CountAlive() + -- Testing + local landheight = pos:GetLandHeight() + local agl = pos.y-landheight + agl = UTILS.Round(agl,2) + self:T(self.lid.." AGL: "..agl or -1) + local isunloaded = true + if count > 0 and (agl > 0 or self.testing) then + self:T(self.lid.." Possible alive helos: "..count or -1) + if agl ~= 0 or self.testing then + isunloaded = false + local set = _DYNAMICCARGO_HELOS:GetAliveSet() + for _,_helo in pairs (set or {}) do + local helo = _helo -- Wrapper.Client#CLIENT + self:I(self.lid.." Checking: "..helo:GetPlayerName()) + local hpos = helo:GetCoordinate() + hpos:MarkToAll("Helo position",true,"helo") + pos:MarkToAll("Cargo position",true,"cargo") + local typename = helo:GetTypeName() + if hpos then + local dimensions = DYNAMICCARGO.AircraftDimensions[typename] + if dimensions then + hpos:SmokeOrange() + local delta2D = hpos:Get2DDistance(pos) + local delta3D = hpos:Get3DDistance(pos) + if self.testing then + self:I(string.format("Cargo relative position: 2D %dm | 3D %dm",delta2D,delta3D)) + self:I(string.format("Helo dimension: length %dm | width %dm | rope %dm",dimensions.length,dimensions.width,dimensions.ropelength)) + end + if delta2D > dimensions.length or delta2D > dimensions.width or delta3D > dimensions.ropelength then + isunloaded = true + end + end + end + end + end + if isunloaded then + self:I(self.lid.." moved! LOADED -> UNLOADED") + self.CargoState = DYNAMICCARGO.State.UNLOADED + _DATABASE:CreateEventDynamicCargoUnloaded(self) + end + end + end + self.LastPosition = pos + end + -- come back laters + self:ScheduleOnce(self.Interval,DYNAMICCARGO._UpdatePosition,self) + else + -- we are dead + self:I(self.lid.." dead! " ..self.CargoState.."-> REMOVED") + self.CargoState = DYNAMICCARGO.State.REMOVED + _DATABASE:CreateEventDynamicCargoRemoved(self) + end + return self +end + +--- [Internal] Track helos for loaded/unloaded decision making. +-- @param Wrapper.Client#CLIENT client +-- @return #boolean IsIn +function DYNAMICCARGO._FilterHeloTypes(client) + if not client then return false end + local typename = client:GetTypeName() + local isinclude = DYNAMICCARGO.AircraftTypes[typename] ~= nil and true or false + return isinclude +end + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/Moose Development/Moose/Wrapper/Storage.lua b/Moose Development/Moose/Wrapper/Storage.lua index 9e750d779..15cbf995d 100644 --- a/Moose Development/Moose/Wrapper/Storage.lua +++ b/Moose Development/Moose/Wrapper/Storage.lua @@ -226,6 +226,26 @@ function STORAGE:NewFromStaticCargo(StaticCargoName) return self end +--- Create a new STORAGE object from an DCS static cargo object. +-- @param #STORAGE self +-- @param #string DynamicCargoName Unit name of the dynamic cargo. +-- @return #STORAGE self +function STORAGE:NewFromDynamicCargo(DynamicCargoName) + + -- Inherit everything from BASE class. + local self=BASE:Inherit(self, BASE:New()) -- #STORAGE + + self.airbase=Unit.getByName(DynamicCargoName) + + if Airbase.getWarehouse then + self.warehouse=Warehouse.getCargoAsWarehouse(self.airbase) + end + + self.lid = string.format("STORAGE %s", DynamicCargoName) + + return self +end + --- Airbases only - Find a STORAGE in the **_DATABASE** using the name associated airbase. -- @param #STORAGE self