diff --git a/Moose Development/Moose/Cargo/Cargo.lua b/Moose Development/Moose/Cargo/Cargo.lua index 07ee37a6d..2528b1b32 100644 --- a/Moose Development/Moose/Cargo/Cargo.lua +++ b/Moose Development/Moose/Cargo/Cargo.lua @@ -259,7 +259,7 @@ do -- CARGO self.Type = Type self.Name = Name - self.Weight = Weight + self.Weight = Weight or 0 self.CargoObject = nil self.CargoCarrier = nil -- Wrapper.Client#CLIENT self.Representable = false @@ -288,6 +288,34 @@ do -- CARGO return CargoFound end + --- Check if the cargo can be Boarded. + -- @param #CARGO self + function CARGO:CanBoard() + return true + end + + --- Check if the cargo can be Unboarded. + -- @param #CARGO self + function CARGO:CanUnboard() + return true + end + + --- Check if the cargo can be Loaded. + -- @param #CARGO self + function CARGO:CanLoad() + return true + end + + --- Check if the cargo can be Unloaded. + -- @param #CARGO self + function CARGO:CanUnload() + return true + end + + + + + --- Destroy the cargo. -- @param #CARGO self function CARGO:Destroy() @@ -315,6 +343,13 @@ do -- CARGO end end + --- Get the amount of Cargo. + -- @param #CARGO self + -- @return #number The amount of Cargo. + function CARGO:GetCount() + return 1 + end + --- Get the type of the Cargo. -- @param #CARGO self -- @return #string The type of the Cargo. @@ -569,8 +604,11 @@ do -- CARGO_REPRESENTABLE -- @param #number NearRadius (optional) -- @return #CARGO_REPRESENTABLE function CARGO_REPRESENTABLE:New( CargoObject, Type, Name, Weight, ReportRadius, NearRadius ) - local self = BASE:Inherit( self, CARGO:New( Type, Name, Weight, ReportRadius, NearRadius ) ) -- #CARGO_REPRESENTABLE + local self = BASE:Inherit( self, CARGO:New( Type, Name, Weight ) ) -- #CARGO_REPRESENTABLE self:F( { Type, Name, Weight, ReportRadius, NearRadius } ) + + self.ReportRadius = ReportRadius or 500 + self.NearRadius = NearRadius or 25 return self end diff --git a/Moose Development/Moose/Cargo/CargoCrate.lua b/Moose Development/Moose/Cargo/CargoCrate.lua index 3f943d1ed..1f083a010 100644 --- a/Moose Development/Moose/Cargo/CargoCrate.lua +++ b/Moose Development/Moose/Cargo/CargoCrate.lua @@ -42,19 +42,25 @@ do -- CARGO_CRATE -- @param Wrapper.Static#STATIC CargoStatic -- @param #string Type -- @param #string Name - -- @param #number Weight -- @param #number ReportRadius (optional) -- @param #number NearRadius (optional) -- @return #CARGO_CRATE - function CARGO_CRATE:New( CargoStatic, Type, Name, NearRadius ) - local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoStatic, Type, Name, nil, NearRadius ) ) -- #CARGO_CRATE + function CARGO_CRATE:New( CargoStatic, Type, Name, ReportRadius, NearRadius ) + local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoStatic, Type, Name, nil, ReportRadius, NearRadius ) ) -- #CARGO_CRATE self:F( { Type, Name, NearRadius } ) self.CargoObject = CargoStatic self:T( self.ClassName ) - self:SetEventPriority( 5 ) + -- Cargo objects are added to the _DATABASE and SET_CARGO objects. + _EVENTDISPATCHER:CreateEventNewCargo( self ) + + self:HandleEvent( EVENTS.Dead, self.OnEventCargoDead ) + self:HandleEvent( EVENTS.Crash, self.OnEventCargoDead ) + self:HandleEvent( EVENTS.PlayerLeaveUnit, self.OnEventCargoDead ) + + self:SetEventPriority( 4 ) return self end @@ -116,5 +122,104 @@ do -- CARGO_CRATE end end + --- Check if the cargo can be Boarded. + -- @param #CARGO_CRATE self + function CARGO_CRATE:CanBoard() + return false + end + + --- Check if the cargo can be Unboarded. + -- @param #CARGO_CRATE self + function CARGO_CRATE:CanUnboard() + return false + end + + --- Get the current Coordinate of the CargoGroup. + -- @param #CARGO_CRATE self + -- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup. + -- @return #nil There is no valid Cargo in the CargoGroup. + function CARGO_CRATE:GetCoordinate() + self:F() + + return self.CargoObject:GetCoordinate() + end + + --- Check if the CargoGroup is alive. + -- @param #CARGO_CRATE self + -- @return #boolean true if the CargoGroup is alive. + -- @return #boolean false if the CargoGroup is dead. + function CARGO_CRATE:IsAlive() + + local Alive = true + + -- When the Cargo is Loaded, the Cargo is in the CargoCarrier, so we check if the CargoCarrier is alive. + -- When the Cargo is not Loaded, the Cargo is the CargoObject, so we check if the CargoObject is alive. + if self:IsLoaded() then + Alive = Alive == true and self.CargoCarrier:IsAlive() + else + Alive = Alive == true and self.CargoObject:IsAlive() + end + + return Alive + + end + + + --- Route Cargo to Coordinate and randomize locations. + -- @param #CARGO_CRATE self + -- @param Core.Point#COORDINATE Coordinate + function CARGO_CRATE:RouteTo( Coordinate ) + self:F( {Coordinate = Coordinate } ) + + end + + + --- Check if Cargo is near to the Carrier. + -- The Cargo is near to the Carrier within NearRadius. + -- @param #CARGO_CRATE self + -- @param Wrapper.Group#GROUP CargoCarrier + -- @param #number NearRadius + -- @return #boolean The Cargo is near to the Carrier. + -- @return #nil The Cargo is not near to the Carrier. + function CARGO_CRATE:IsNear( CargoCarrier, NearRadius ) + self:F( {NearRadius = NearRadius } ) + + return self:IsNear( CargoCarrier:GetCoordinate(), NearRadius ) + end + + + --- Check if CargoGroup is in the ReportRadius for the Cargo to be Loaded. + -- @param #CARGO_CRATE self + -- @param Core.Point#Coordinate Coordinate + -- @return #boolean true if the CargoGroup is within the reporting radius. + function CARGO_CRATE:IsInRadius( Coordinate ) + self:F( { Coordinate } ) + + local Distance = 0 + if self:IsLoaded() then + Distance = Coordinate:DistanceFromPointVec2( self.CargoCarrier:GetPointVec2() ) + else + Distance = Coordinate:DistanceFromPointVec2( self.CargoObject:GetPointVec2() ) + end + self:T( Distance ) + + if Distance <= self.ReportRadius then + return true + else + return false + end + end + + --- Respawn the CargoGroup. + -- @param #CARGO_CRATE self + function CARGO_CRATE:Respawn() + + self:F( { "Respawning" } ) + + self:SetDeployed( false ) + self:SetStartState( "UnLoaded" ) + + end + end diff --git a/Moose Development/Moose/Cargo/CargoSlingload.lua b/Moose Development/Moose/Cargo/CargoSlingload.lua new file mode 100644 index 000000000..a610e4b34 --- /dev/null +++ b/Moose Development/Moose/Cargo/CargoSlingload.lua @@ -0,0 +1,180 @@ +--- **Cargo** -- Management of single cargo crates, which are based on a @{Static} object. The cargo can only be slingloaded. +-- +-- === +-- +-- ![Banner Image](..\Presentations\CARGO\Dia1.JPG) +-- +-- === +-- +-- ### [Demo Missions]() +-- +-- ### [YouTube Playlist]() +-- +-- === +-- +-- ### Author: **FlightControl** +-- ### Contributions: +-- +-- === +-- +-- @module CargoCrate + + +do -- CARGO_SLINGLOAD + + --- Models the behaviour of cargo crates, which can only be slingloaded. + -- @type CARGO_SLINGLOAD + -- @extends #CARGO_REPRESENTABLE + + --- # CARGO\_CRATE class, extends @{#CARGO_REPRESENTABLE} + -- + -- The CARGO\_CRATE class defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier. + -- + -- === + -- + -- @field #CARGO_SLINGLOAD + CARGO_SLINGLOAD = { + ClassName = "CARGO_SLINGLOAD" + } + + --- CARGO_SLINGLOAD Constructor. + -- @param #CARGO_SLINGLOAD self + -- @param Wrapper.Static#STATIC CargoStatic + -- @param #string Type + -- @param #string Name + -- @param #number ReportRadius (optional) + -- @param #number NearRadius (optional) + -- @return #CARGO_SLINGLOAD + function CARGO_SLINGLOAD:New( CargoStatic, Type, Name, ReportRadius, NearRadius ) + local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoStatic, Type, Name, nil, ReportRadius, NearRadius ) ) -- #CARGO_SLINGLOAD + self:F( { Type, Name, NearRadius } ) + + self.CargoObject = CargoStatic + + self:T( self.ClassName ) + + -- Cargo objects are added to the _DATABASE and SET_CARGO objects. + _EVENTDISPATCHER:CreateEventNewCargo( self ) + + self:HandleEvent( EVENTS.Dead, self.OnEventCargoDead ) + self:HandleEvent( EVENTS.Crash, self.OnEventCargoDead ) + self:HandleEvent( EVENTS.PlayerLeaveUnit, self.OnEventCargoDead ) + + self:SetEventPriority( 4 ) + + return self + end + + + --- Check if the cargo can be Boarded. + -- @param #CARGO_SLINGLOAD self + function CARGO_SLINGLOAD:CanBoard() + return false + end + + --- Check if the cargo can be Unboarded. + -- @param #CARGO_SLINGLOAD self + function CARGO_SLINGLOAD:CanUnboard() + return false + end + + --- Check if the cargo can be Loaded. + -- @param #CARGO_SLINGLOAD self + function CARGO_SLINGLOAD:CanLoad() + return false + end + + --- Check if the cargo can be Unloaded. + -- @param #CARGO_SLINGLOAD self + function CARGO_SLINGLOAD:CanUnload() + return false + end + + --- Get the current Coordinate of the CargoGroup. + -- @param #CARGO_SLINGLOAD self + -- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup. + -- @return #nil There is no valid Cargo in the CargoGroup. + function CARGO_SLINGLOAD:GetCoordinate() + self:F() + + return self.CargoObject:GetCoordinate() + end + + --- Check if the CargoGroup is alive. + -- @param #CARGO_SLINGLOAD self + -- @return #boolean true if the CargoGroup is alive. + -- @return #boolean false if the CargoGroup is dead. + function CARGO_SLINGLOAD:IsAlive() + + local Alive = true + + -- When the Cargo is Loaded, the Cargo is in the CargoCarrier, so we check if the CargoCarrier is alive. + -- When the Cargo is not Loaded, the Cargo is the CargoObject, so we check if the CargoObject is alive. + if self:IsLoaded() then + Alive = Alive == true and self.CargoCarrier:IsAlive() + else + Alive = Alive == true and self.CargoObject:IsAlive() + end + + return Alive + + end + + + --- Route Cargo to Coordinate and randomize locations. + -- @param #CARGO_SLINGLOAD self + -- @param Core.Point#COORDINATE Coordinate + function CARGO_SLINGLOAD:RouteTo( Coordinate ) + self:F( {Coordinate = Coordinate } ) + + end + + + --- Check if Cargo is near to the Carrier. + -- The Cargo is near to the Carrier within NearRadius. + -- @param #CARGO_SLINGLOAD self + -- @param Wrapper.Group#GROUP CargoCarrier + -- @param #number NearRadius + -- @return #boolean The Cargo is near to the Carrier. + -- @return #nil The Cargo is not near to the Carrier. + function CARGO_SLINGLOAD:IsNear( CargoCarrier, NearRadius ) + self:F( {NearRadius = NearRadius } ) + + return self:IsNear( CargoCarrier:GetCoordinate(), NearRadius ) + end + + + --- Check if CargoGroup is in the ReportRadius for the Cargo to be Loaded. + -- @param #CARGO_SLINGLOAD self + -- @param Core.Point#Coordinate Coordinate + -- @return #boolean true if the CargoGroup is within the reporting radius. + function CARGO_SLINGLOAD:IsInRadius( Coordinate ) + self:F( { Coordinate } ) + + local Distance = 0 + if self:IsLoaded() then + Distance = Coordinate:DistanceFromPointVec2( self.CargoCarrier:GetPointVec2() ) + else + Distance = Coordinate:DistanceFromPointVec2( self.CargoObject:GetPointVec2() ) + end + self:T( Distance ) + + if Distance <= self.ReportRadius then + return true + else + return false + end + end + + --- Respawn the CargoGroup. + -- @param #CARGO_SLINGLOAD self + function CARGO_SLINGLOAD:Respawn() + + self:F( { "Respawning" } ) + + self:SetDeployed( false ) + self:SetStartState( "UnLoaded" ) + + end + +end diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index d90e01284..01b1c64a0 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -450,8 +450,6 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category local GroupTemplateName = GroupName or env.getValueDictByKey( GroupTemplate.name ) - local TraceTable = {} - if not self.Templates.Groups[GroupTemplateName] then self.Templates.Groups[GroupTemplateName] = {} self.Templates.Groups[GroupTemplateName].Status = nil @@ -475,18 +473,7 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category self.Templates.Groups[GroupTemplateName].CoalitionID = CoalitionSide self.Templates.Groups[GroupTemplateName].CountryID = CountryID - - TraceTable[#TraceTable+1] = "Group" - TraceTable[#TraceTable+1] = self.Templates.Groups[GroupTemplateName].GroupName - - TraceTable[#TraceTable+1] = "Coalition" - TraceTable[#TraceTable+1] = self.Templates.Groups[GroupTemplateName].CoalitionID - TraceTable[#TraceTable+1] = "Category" - TraceTable[#TraceTable+1] = self.Templates.Groups[GroupTemplateName].CategoryID - TraceTable[#TraceTable+1] = "Country" - TraceTable[#TraceTable+1] = self.Templates.Groups[GroupTemplateName].CountryID - - TraceTable[#TraceTable+1] = "Units" + local UnitNames = {} for unit_num, UnitTemplate in pairs( GroupTemplate.units ) do @@ -510,10 +497,16 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category self.Templates.ClientsByID[UnitTemplate.unitId] = UnitTemplate end - TraceTable[#TraceTable+1] = self.Templates.Units[UnitTemplate.name].UnitName + UnitNames[#UnitNames+1] = self.Templates.Units[UnitTemplate.name].UnitName end - self:E( TraceTable ) + self:I( { Group = self.Templates.Groups[GroupTemplateName].GroupName, + Coalition = self.Templates.Groups[GroupTemplateName].CoalitionID, + Category = self.Templates.Groups[GroupTemplateName].CategoryID, + Country = self.Templates.Groups[GroupTemplateName].CountryID, + Units = UnitNames + } + ) end function DATABASE:GetGroupTemplate( GroupName ) @@ -530,8 +523,6 @@ end -- @return #DATABASE self function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, CategoryID, CountryID ) - local TraceTable = {} - local StaticTemplateName = env.getValueDictByKey(StaticTemplate.name) self.Templates.Statics[StaticTemplateName] = self.Templates.Statics[StaticTemplateName] or {} @@ -547,28 +538,22 @@ function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, Category self.Templates.Statics[StaticTemplateName].CoalitionID = CoalitionID self.Templates.Statics[StaticTemplateName].CountryID = CountryID + self:I( { Static = self.Templates.Statics[StaticTemplateName].StaticName, + Coalition = self.Templates.Statics[StaticTemplateName].CoalitionID, + Category = self.Templates.Statics[StaticTemplateName].CategoryID, + Country = self.Templates.Statics[StaticTemplateName].CountryID + } + ) + + self:AddStatic( StaticTemplateName ) - TraceTable[#TraceTable+1] = "Static" - TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].StaticName - - TraceTable[#TraceTable+1] = "Coalition" - TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].CoalitionID - TraceTable[#TraceTable+1] = "Category" - TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].CategoryID - TraceTable[#TraceTable+1] = "Country" - TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].CountryID - - self:E( TraceTable ) end --- @param #DATABASE self function DATABASE:GetStaticUnitTemplate( StaticName ) local StaticTemplate = self.Templates.Statics[StaticName].UnitTemplate - StaticTemplate.SpawnCoalitionID = self.Templates.Statics[StaticName].CoalitionID - StaticTemplate.SpawnCategoryID = self.Templates.Statics[StaticName].CategoryID - StaticTemplate.SpawnCountryID = self.Templates.Statics[StaticName].CountryID - return StaticTemplate + return StaticTemplate, self.Templates.Statics[StaticName].CoalitionID, self.Templates.Statics[StaticName].CategoryID, self.Templates.Statics[StaticName].CountryID end diff --git a/Moose Development/Moose/Core/SpawnStatic.lua b/Moose Development/Moose/Core/SpawnStatic.lua index 92a816257..118b74b8c 100644 --- a/Moose Development/Moose/Core/SpawnStatic.lua +++ b/Moose Development/Moose/Core/SpawnStatic.lua @@ -81,14 +81,16 @@ SPAWNSTATIC = { -- @param #SPAWNSTATIC self -- @param #string SpawnTemplatePrefix is the name of the Group in the ME that defines the Template. Each new group will have the name starting with SpawnTemplatePrefix. -- @return #SPAWNSTATIC -function SPAWNSTATIC:NewFromStatic( SpawnTemplatePrefix, CountryID ) --R2.1 +function SPAWNSTATIC:NewFromStatic( SpawnTemplatePrefix, SpawnCountryID ) --R2.1 local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC self:F( { SpawnTemplatePrefix } ) - local TemplateStatic = StaticObject.getByName( SpawnTemplatePrefix ) + local TemplateStatic, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticUnitTemplate( SpawnTemplatePrefix ) if TemplateStatic then self.SpawnTemplatePrefix = SpawnTemplatePrefix - self.CountryID = CountryID + self.CountryID = SpawnCountryID or CountryID + self.CategoryID = CategoryID + self.CoalitionID = CoalitionID self.SpawnIndex = 0 else error( "SPAWNSTATIC:New: There is no group declared in the mission editor with SpawnTemplatePrefix = '" .. SpawnTemplatePrefix .. "'" ) @@ -124,22 +126,28 @@ end function SPAWNSTATIC:Spawn( Heading, NewName ) --R2.3 self:F( { Heading, NewName } ) - local CountryName = _DATABASE.COUNTRY_NAME[self.CountryID] - local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix ) - StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex ) - StaticTemplate.heading = ( Heading / 180 ) * math.pi + if StaticTemplate then - StaticTemplate.CountryID = nil - StaticTemplate.CoalitionID = nil - StaticTemplate.CategoryID = nil + local CountryID = self.CountryID + local CountryName = _DATABASE.COUNTRY_NAME[CountryID] - local Static = coalition.addStaticObject( self.CountryID, StaticTemplate ) + StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex ) + StaticTemplate.heading = ( Heading / 180 ) * math.pi + + StaticTemplate.CountryID = nil + StaticTemplate.CoalitionID = nil + StaticTemplate.CategoryID = nil + + local Static = coalition.addStaticObject( CountryID, StaticTemplate ) + + self.SpawnIndex = self.SpawnIndex + 1 - self.SpawnIndex = self.SpawnIndex + 1 - - return Static + return Static + end + + return nil end @@ -153,30 +161,35 @@ end function SPAWNSTATIC:SpawnFromPointVec2( PointVec2, Heading, NewName ) --R2.1 self:F( { PointVec2, Heading, NewName } ) - local CountryName = _DATABASE.COUNTRY_NAME[self.CountryID] - local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix ) - StaticTemplate.x = PointVec2.x - StaticTemplate.y = PointVec2.z + if StaticTemplate then - StaticTemplate.units = nil - StaticTemplate.route = nil - StaticTemplate.groupId = nil + local CountryID = self.CountryID + local CountryName = _DATABASE.COUNTRY_NAME[CountryID] + StaticTemplate.x = PointVec2.x + StaticTemplate.y = PointVec2.z - StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex ) - StaticTemplate.heading = ( Heading / 180 ) * math.pi + StaticTemplate.units = nil + StaticTemplate.route = nil + StaticTemplate.groupId = nil + + StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex ) + StaticTemplate.heading = ( Heading / 180 ) * math.pi + + StaticTemplate.CountryID = nil + StaticTemplate.CoalitionID = nil + StaticTemplate.CategoryID = nil + + local Static = coalition.addStaticObject( CountryID, StaticTemplate ) + + self.SpawnIndex = self.SpawnIndex + 1 - StaticTemplate.CountryID = nil - StaticTemplate.CoalitionID = nil - StaticTemplate.CategoryID = nil + return Static + end - local Static = coalition.addStaticObject( self.CountryID, StaticTemplate ) - - self.SpawnIndex = self.SpawnIndex + 1 - - return Static + return nil end --- Creates a new @{Static} from a @{Zone}. diff --git a/Moose Development/Moose/Tasking/Task_CARGO.lua b/Moose Development/Moose/Tasking/Task_CARGO.lua index d59473047..efb21f018 100644 --- a/Moose Development/Moose/Tasking/Task_CARGO.lua +++ b/Moose Development/Moose/Tasking/Task_CARGO.lua @@ -13,6 +13,7 @@ -- The following classes are important to consider: -- -- * @{#TASK_CARGO_TRANSPORT}: Defines a task for a human player to transport a set of cargo between various zones. +-- * @{#TASK_CARGO_CSAR}: Defines a task for a human player to Search and Rescue wounded pilots. -- -- === -- @@ -173,7 +174,7 @@ do -- TASK_CARGO Fsm:AddProcess ( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( self.TaskBriefing ), { Assigned = "SelectAction", Rejected = "Reject" } ) - Fsm:AddTransition( { "Planned", "Assigned", "WaitingForCommand", "ArrivedAtPickup", "ArrivedAtDeploy", "Boarded", "UnBoarded", "Landed", "Boarding" }, "SelectAction", "*" ) + Fsm:AddTransition( { "Planned", "Assigned", "WaitingForCommand", "ArrivedAtPickup", "ArrivedAtDeploy", "Boarded", "UnBoarded", "Loaded", "UnLoaded", "Landed", "Boarding" }, "SelectAction", "*" ) Fsm:AddTransition( "*", "RouteToPickup", "RoutingToPickup" ) Fsm:AddProcess ( "RoutingToPickup", "RouteToPickupPoint", ACT_ROUTE_POINT:New(), { Arrived = "ArriveAtPickup", Cancelled = "CancelRouteToPickup" } ) @@ -191,10 +192,14 @@ do -- TASK_CARGO Fsm:AddTransition( "*", "PrepareBoarding", "AwaitBoarding" ) Fsm:AddTransition( "AwaitBoarding", "Board", "Boarding" ) Fsm:AddTransition( "Boarding", "Boarded", "Boarded" ) + + Fsm:AddTransition( "*", "Load", "Loaded" ) Fsm:AddTransition( "*", "PrepareUnBoarding", "AwaitUnBoarding" ) Fsm:AddTransition( "AwaitUnBoarding", "UnBoard", "UnBoarding" ) Fsm:AddTransition( "UnBoarding", "UnBoarded", "UnBoarded" ) + + Fsm:AddTransition( "*", "Unload", "Unloaded" ) Fsm:AddTransition( "*", "Planned", "Planned" ) @@ -254,7 +259,13 @@ do -- TASK_CARGO end if NotInDeployZones then if not TaskUnit:InAir() then - MENU_GROUP_COMMAND:New( TaskUnit:GetGroup(), "Board cargo " .. Cargo.Name, TaskUnit.Menu, self.MenuBoardCargo, self, Cargo ):SetTime(MenuTime) + if Cargo:CanBoard() == true then + MENU_GROUP_COMMAND:New( TaskUnit:GetGroup(), "Board cargo " .. Cargo.Name, TaskUnit.Menu, self.MenuBoardCargo, self, Cargo ):SetTime(MenuTime) + else + if Cargo:CanLoad() == true then + MENU_GROUP_COMMAND:New( TaskUnit:GetGroup(), "Load cargo " .. Cargo.Name, TaskUnit.Menu, self.MenuLoadCargo, self, Cargo ):SetTime(MenuTime) + end + end TaskUnit.Menu:SetTime( MenuTime ) end end @@ -267,7 +278,13 @@ do -- TASK_CARGO if Cargo:IsLoaded() then if not TaskUnit:InAir() then - MENU_GROUP_COMMAND:New( TaskUnit:GetGroup(), "Unboard cargo " .. Cargo.Name, TaskUnit.Menu, self.MenuUnBoardCargo, self, Cargo ):SetTime(MenuTime) + if Cargo:CanUnboard() == true then + MENU_GROUP_COMMAND:New( TaskUnit:GetGroup(), "Unboard cargo " .. Cargo.Name, TaskUnit.Menu, self.MenuUnboardCargo, self, Cargo ):SetTime(MenuTime) + else + if Cargo:CanUnload() == true then + MENU_GROUP_COMMAND:New( TaskUnit:GetGroup(), "Unload cargo " .. Cargo.Name, TaskUnit.Menu, self.MenuUnloadCargo, self, Cargo ):SetTime(MenuTime) + end + end TaskUnit.Menu:SetTime( MenuTime ) end -- Deployzones are optional zones that can be selected to request routing information. @@ -305,10 +322,18 @@ do -- TASK_CARGO self:__PrepareBoarding( 1.0, Cargo ) end - function Fsm:MenuUnBoardCargo( Cargo, DeployZone ) + function Fsm:MenuLoadCargo( Cargo ) + self:__Load( 1.0, Cargo ) + end + + function Fsm:MenuUnboardCargo( Cargo, DeployZone ) self:__PrepareUnBoarding( 1.0, Cargo, DeployZone ) end + function Fsm:MenuUnloadCargo( Cargo, DeployZone ) + self:__Unload( 1.0, Cargo, DeployZone ) + end + function Fsm:MenuRouteToPickup( Cargo ) self:__RouteToPickup( 1.0, Cargo ) end @@ -467,6 +492,7 @@ do -- TASK_CARGO self:__Board( -0.1 ) end end + --- @param #FSM_PROCESS self -- @param Wrapper.Unit#UNIT TaskUnit @@ -506,15 +532,31 @@ do -- TASK_CARGO self.Cargo:MessageToGroup( "Boarded ...", TaskUnit:GetGroup() ) - TaskUnit:AddCargo( self.Cargo ) + self:Load( self.Cargo ) + + end + + + --- @param #FSM_PROCESS self + -- @param Wrapper.Unit#UNIT TaskUnit + -- @param Tasking.Task_Cargo#TASK_CARGO Task + function Fsm:onafterLoad( TaskUnit, Task, From, Event, To, Cargo ) + + local TaskUnitName = TaskUnit:GetName() + self:F( { TaskUnit = TaskUnitName, Task = Task and Task:GetClassNameAndID() } ) + + if not Cargo:IsLoaded() then + Cargo:Load( TaskUnit ) + TaskUnit:AddCargo( Cargo ) + end self:__SelectAction( 1 ) -- TODO:I need to find a more decent solution for this. Task:E( { CargoPickedUp = Task.CargoPickedUp } ) - if self.Cargo:IsAlive() then + if Cargo:IsAlive() then if Task.CargoPickedUp then - Task:CargoPickedUp( TaskUnit, self.Cargo ) + Task:CargoPickedUp( TaskUnit, Cargo ) end end @@ -530,7 +572,7 @@ do -- TASK_CARGO -- @param To -- @param Cargo -- @param Core.Zone#ZONE_BASE DeployZone - function Fsm:onafterPrepareUnBoarding( TaskUnit, Task, From, Event, To, Cargo ) + function Fsm:onafterPrepareUnBoarding( TaskUnit, Task, From, Event, To, Cargo ) self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID(), From, Event, To, Cargo } ) self.Cargo = Cargo @@ -586,33 +628,51 @@ do -- TASK_CARGO self:F( { TaskUnit = TaskUnitName, Task = Task and Task:GetClassNameAndID() } ) self.Cargo:MessageToGroup( "UnBoarded ...", TaskUnit:GetGroup() ) + + self:Unload( self.Cargo ) + end - TaskUnit:RemoveCargo( self.Cargo ) + --- + -- @param #FSM_PROCESS self + -- @param Wrapper.Unit#UNIT TaskUnit + -- @param Tasking.Task_Cargo#TASK_CARGO Task + function Fsm:onafterUnload( TaskUnit, Task, From, Event, To, Cargo, DeployZone ) + + local TaskUnitName = TaskUnit:GetName() + self:F( { TaskUnit = TaskUnitName, Task = Task and Task:GetClassNameAndID() } ) + + if not Cargo:IsUnLoaded() then + if DeployZone then + Cargo:UnLoad( DeployZone:GetPointVec2(), 400, self ) + else + Cargo:UnLoad( TaskUnit:GetPointVec2():AddX(60), 400, self ) + end + end + TaskUnit:RemoveCargo( Cargo ) local NotInDeployZones = true for DeployZoneName, DeployZone in pairs( Task.DeployZones ) do - if self.Cargo:IsInZone( DeployZone ) then + if Cargo:IsInZone( DeployZone ) then NotInDeployZones = false end end if NotInDeployZones == false then - self.Cargo:SetDeployed( true ) + Cargo:SetDeployed( true ) end -- TODO:I need to find a more decent solution for this. Task:E( { CargoDeployed = Task.CargoDeployed and "true" or "false" } ) - Task:E( { CargoIsAlive = self.Cargo:IsAlive() and "true" or "false" } ) - if self.Cargo:IsAlive() then + Task:E( { CargoIsAlive = Cargo:IsAlive() and "true" or "false" } ) + if Cargo:IsAlive() then if Task.CargoDeployed then - Task:CargoDeployed( TaskUnit, self.Cargo, self.DeployZone ) + Task:CargoDeployed( TaskUnit, Cargo, self.DeployZone ) end end self:Planned() self:__SelectAction( 1 ) end - return self diff --git a/Moose Development/Moose/Tasking/Task_Cargo_Dispatcher.lua b/Moose Development/Moose/Tasking/Task_Cargo_Dispatcher.lua index df9c36dec..ca96b2d87 100644 --- a/Moose Development/Moose/Tasking/Task_Cargo_Dispatcher.lua +++ b/Moose Development/Moose/Tasking/Task_Cargo_Dispatcher.lua @@ -178,6 +178,9 @@ do -- TASK_CARGO_DISPATCHER Tasks = {}, CSAR = {}, CSARSpawned = 0, + + Transport = {}, + TransportCount = 0, } @@ -214,62 +217,163 @@ do -- TASK_CARGO_DISPATCHER return self end - + + + --- Handle the event when a pilot ejects. -- @param #TASK_CARGO_DISPATCHER self -- @param Core.Event#EVENTDATA EventData function TASK_CARGO_DISPATCHER:OnEventEjection( EventData ) + self:F( { EventData = EventData } ) + + if self.CSARTasks == true then - self:E( { EventData = EventData } ) - - self.CSARSpawned = self.CSARSpawned + 1 - - local PlaneUnit = EventData.IniUnit - local CSARName = EventData.IniUnitName - - local CargoPointVec2 = EventData.IniUnit:GetPointVec2() - local CargoCoalition = EventData.IniUnit:GetCoalition() - local CargoCountry = EventData.IniUnit:GetCountry() - - -- Only add a CSAR task if the coalition of the mission is equal to the coalition of the ejected unit. - - if CargoCoalition == self.Mission:GetCommandCenter():GetCoalition() then - - -- Create the CSAR Pilot SPAWN object. - -- Let us create the Template for the replacement Pilot :-) - local Template = { - ["visible"] = false, - ["hidden"] = false, - ["task"] = "Ground Nothing", - ["name"] = string.format( "CSAR Pilot#%03d", self.CSARSpawned ), - ["x"] = CargoPointVec2:GetLat(), - ["y"] = CargoPointVec2:GetLon(), - ["units"] = - { - [1] = - { - ["type"] = ( CargoCoalition == coalition.side.BLUE ) and "Soldier M4" or "Infantry AK", - ["name"] = string.format( "CSAR Pilot#%03d-01", self.CSARSpawned ), - ["skill"] = "Excellent", - ["playerCanDrive"] = false, - ["x"] = CargoPointVec2:GetLat(), - ["y"] = CargoPointVec2:GetLon(), - ["heading"] = EventData.IniUnit:GetHeading(), - }, -- end of [1] - }, -- end of ["units"] - } - - local CargoGroup = GROUP:NewTemplate( Template, CargoCoalition, Group.Category.GROUND, CargoCountry ) - - self.CSAR[#self.CSAR+1] = {} - self.CSAR[#self.CSAR].PilotGroup = CargoGroup - self.CSAR[#self.CSAR].Task = nil - + local CSARCoordinate = EventData.IniUnit:GetCoordinate() + local CSARCoalition = EventData.IniUnit:GetCoalition() + local CSARCountry = EventData.IniUnit:GetCountry() + local CSARHeading = EventData.IniUnit:GetHeading() + + -- Only add a CSAR task if the coalition of the mission is equal to the coalition of the ejected unit. + if CSARCoalition == self.Mission:GetCommandCenter():GetCoalition() then + local CSARTaskName = self:AddCSARTask( self.CSARTaskName, CSARCoordinate, CSARHeading, CSARCountry, self.CSARBriefing ) + self:SetCSARDeployZones( CSARTaskName, self.CSARDeployZones ) + end end return self end + + + --- Define one default deploy zone for all the cargo tasks. + -- @param #TASK_CARGO_DISPATCHER self + -- @param DefaultDeployZone A default deploy zone. + -- @return #TASK_CARGO_DISPATCHER + function TASK_CARGO_DISPATCHER:SetDefaultDeployZone( DefaultDeployZone ) + + self.DefaultDeployZones = { DefaultDeployZone } + + return self + end + + + --- Define the deploy zones for all the cargo tasks. + -- @param #TASK_CARGO_DISPATCHER self + -- @param DefaultDeployZones A list of the deploy zones. + -- @return #TASK_CARGO_DISPATCHER + -- + function TASK_CARGO_DISPATCHER:SetDefaultDeployZones( DefaultDeployZones ) + + self.DefaultDeployZones = DefaultDeployZones + + return self + end + + + --- Start the generation of CSAR tasks to retrieve a downed pilots. + -- You need to specify a task briefing, a task name, default deployment zone(s). + -- This method can only be used once! + -- @param #TASK_CARGO_DISPATCHER self + -- @param #string CSARTaskName The CSAR task name. + -- @param #string CSARDeployZones The zones to where the CSAR deployment should be directed. + -- @param #string CSARBriefing The briefing of the CSAR tasks. + -- @return #TASK_CARGO_DISPATCHER + function TASK_CARGO_DISPATCHER:StartCSARTasks( CSARTaskName, CSARDeployZones, CSARBriefing) + + if not self.CSARTasks then + self.CSARTasks = true + self.CSARTaskName = CSARTaskName + self.CSARDeployZones = CSARDeployZones + self.CSARBriefing = CSARBriefing + else + error( "TASK_CARGO_DISPATCHER: The generation of CSAR tasks has already started." ) + end + + return self + end + + + --- Stop the generation of CSAR tasks to retrieve a downed pilots. + -- @param #TASK_CARGO_DISPATCHER self + -- @return #TASK_CARGO_DISPATCHER + function TASK_CARGO_DISPATCHER:StopCSARTasks() + + if self.CSARTasks then + self.CSARTasks = nil + self.CSARTaskName = nil + self.CSARDeployZones = nil + self.CSARBriefing = nil + else + error( "TASK_CARGO_DISPATCHER: The generation of CSAR tasks was not yet started." ) + end + + return self + end + + + --- Add a CSAR task to retrieve a downed pilot. + -- You need to specify a coordinate from where the pilot will be spawned to be rescued. + -- @param #TASK_CARGO_DISPATCHER self + -- @param #string CSARTaskPrefix (optional) The prefix of the CSAR task. + -- @param Core.Point#COORDINATE CSARCoordinate The coordinate where a downed pilot will be spawned. + -- @param #number CSARHeading The heading of the pilot in degrees. + -- @param DCSCountry#Country CSARCountry The country ID of the pilot that will be spawned. + -- @param #string CSARBriefing The briefing of the CSAR task. + -- @return #string The CSAR Task Name as a string. The Task Name is the main key and is shown in the task list of the Mission Tasking menu. + -- @usage + -- + -- -- Add a CSAR task to rescue a downed pilot from within a coordinate. + -- local Coordinate = PlaneUnit:GetPointVec2() + -- TaskA2ADispatcher:AddCSARTask( Coordinate ) + -- + -- -- Add a CSAR task to rescue a downed pilot from within a coordinate of country RUSSIA, which is pointing to the west (270°). + -- local Coordinate = PlaneUnit:GetPointVec2() + -- TaskA2ADispatcher:AddCSARTask( Coordinate, 270, Country.RUSSIA ) + -- + function TASK_CARGO_DISPATCHER:AddCSARTask( CSARTaskPrefix, CSARCoordinate, CSARHeading, CSARCountry, CSARBriefing ) + + local CSARCoalition = self.Mission:GetCommandCenter():GetCoalition() + + CSARHeading = CSARHeading or 0 + CSARCountry = CSARCountry or self.Mission:GetCommandCenter():GetCountry() + + self.CSARSpawned = self.CSARSpawned + 1 + + local CSARTaskName = string.format( ( CSARTaskPrefix or "CSAR" ) .. ".%03d", self.CSARSpawned ) + + -- Create the CSAR Pilot SPAWN object. + -- Let us create the Template for the replacement Pilot :-) + local Template = { + ["visible"] = false, + ["hidden"] = false, + ["task"] = "Ground Nothing", + ["name"] = string.format( "CSAR Pilot#%03d", self.CSARSpawned ), + ["x"] = CSARCoordinate.x, + ["y"] = CSARCoordinate.z, + ["units"] = + { + [1] = + { + ["type"] = ( CSARCoalition == coalition.side.BLUE ) and "Soldier M4" or "Infantry AK", + ["name"] = string.format( "CSAR Pilot#%03d-01", self.CSARSpawned ), + ["skill"] = "Excellent", + ["playerCanDrive"] = false, + ["x"] = CSARCoordinate.x, + ["y"] = CSARCoordinate.z, + ["heading"] = CSARHeading, + }, -- end of [1] + }, -- end of ["units"] + } + + local CSARGroup = GROUP:NewTemplate( Template, CSARCoalition, Group.Category.GROUND, CSARCountry ) + + self.CSAR[CSARTaskName] = {} + self.CSAR[CSARTaskName].PilotGroup = CSARGroup + self.CSAR[CSARTaskName].Briefing = CSARBriefing + self.CSAR[CSARTaskName].Task = nil + + return CSARTaskName + end --- Define the radius to when a CSAR task will be generated for any downed pilot within range of the nearest CSAR airbase. @@ -294,11 +398,14 @@ do -- TASK_CARGO_DISPATCHER --- Define one deploy zone for the CSAR tasks. -- @param #TASK_CARGO_DISPATCHER self - -- @param DeployZone A deploy zone. + -- @param #string CSARTaskName (optional) The name of the CSAR task. + -- @param CSARDeployZone A CSAR deploy zone. -- @return #TASK_CARGO_DISPATCHER - function TASK_CARGO_DISPATCHER:SetCSARDeployZone( CSARDeployZone ) + function TASK_CARGO_DISPATCHER:SetCSARDeployZone( CSARTaskName, CSARDeployZone ) - self.CSARDeployZones = { CSARDeployZone } + if CSARTaskName then + self.CSAR[CSARTaskName].DeployZones = { CSARDeployZone } + end return self end @@ -306,16 +413,73 @@ do -- TASK_CARGO_DISPATCHER --- Define the deploy zones for the CSAR tasks. -- @param #TASK_CARGO_DISPATCHER self - -- @param CSARDeployZones A list of the deploy zones. + -- @param #string CSARTaskName (optional) The name of the CSAR task. + -- @param CSARDeployZones A list of the CSAR deploy zones. -- @return #TASK_CARGO_DISPATCHER - function TASK_CARGO_DISPATCHER:SetCSARDeployZones( CSARDeployZones ) + -- + function TASK_CARGO_DISPATCHER:SetCSARDeployZones( CSARTaskName, CSARDeployZones ) - self.CSARDeployZones = CSARDeployZones + if CSARTaskName and self.CSAR[CSARTaskName] then + self.CSAR[CSARTaskName].DeployZones = CSARDeployZones + end + + return self + end + + + --- Add a Transport task to transport cargo from fixed locations to a deployment zone. + -- @param #TASK_CARGO_DISPATCHER self + -- @param #string TransportTaskName (optional) The name of the transport task. + -- @param Core.SetCargo#SET_CARGO SetCargo The SetCargo to be transported. + -- @param #string Briefing The briefing of the task transport to be shown to the player. + -- @return #TASK_CARGO_DISPATCHER + -- @usage + -- + -- -- Add a Transport task to transport cargo of different types to a Transport Deployment Zone. + function TASK_CARGO_DISPATCHER:AddTransportTask( TransportTaskName, SetCargo, Briefing ) + + self.TransportCount = self.TransportCount + 1 + local TaskName = string.format( ( TransportTaskName or "Transport" ) .. ".%03d", self.TransportCount ) + + self.Transport[TaskName] = {} + self.Transport[TaskName].SetCargo = SetCargo + self.Transport[TaskName].Briefing = Briefing + self.Transport[TaskName].Task = nil + + return self + end + + + --- Define one deploy zone for the Transport tasks. + -- @param #TASK_CARGO_DISPATCHER self + -- @param #string TransportTaskName (optional) The name of the Transport task. + -- @param TransportDeployZone A Transport deploy zone. + -- @return #TASK_CARGO_DISPATCHER + function TASK_CARGO_DISPATCHER:SetTransportDeployZone( TransportTaskName, TransportDeployZone ) + + if TransportTaskName then + self.Transport[TransportTaskName].DeployZones = { TransportDeployZone } + end return self end + --- Define the deploy zones for the Transport tasks. + -- @param #TASK_CARGO_DISPATCHER self + -- @param #string TransportTaskName (optional) The name of the Transport task. + -- @param TransportDeployZones A list of the Transport deploy zones. + -- @return #TASK_CARGO_DISPATCHER + -- + function TASK_CARGO_DISPATCHER:SetTransportDeployZones( TransportTaskName, TransportDeployZones ) + + if TransportTaskName then + self.Transport[TransportTaskName].DeployZones = TransportDeployZones + end + + return self + end + --- Evaluates of a CSAR task needs to be started. -- @param #TASK_CARGO_DISPATCHER self -- @return Set#SET_CARGO The SetCargo to be rescued. @@ -368,17 +532,36 @@ do -- TASK_CARGO_DISPATCHER end -- Now that all obsolete tasks are removed, loop through the CSAR pilots. - for CSARID, CSARData in pairs( self.CSAR ) do + for CSARName, CSAR in pairs( self.CSAR ) do - if CSARData.Task then - else + if not CSAR.Task then -- New CSAR Task - local SetCargo = self:EvaluateCSAR( CSARData.PilotGroup ) - local CSARTask = TASK_CARGO_CSAR:New( Mission, self.SetGroup, string.format( "CSAR.%03d", CSARID ), SetCargo ) - CSARTask:SetDeployZones( self.CSARDeployZones or {} ) - Mission:AddTask( CSARTask ) - TaskReport:Add( CSARTask:GetName() ) - CSARData.Task = CSARTask + local SetCargo = self:EvaluateCSAR( CSAR.PilotGroup ) + CSAR.Task = TASK_CARGO_CSAR:New( Mission, self.SetGroup, CSARName, SetCargo, CSAR.Briefing ) + Mission:AddTask( CSAR.Task ) + TaskReport:Add( CSARName ) + if CSAR.DeployZones then + CSAR.Task:SetDeployZones( CSAR.DeployZones or {} ) + else + CSAR.Task:SetDeployZones( self.DefaultDeployZones or {} ) + end + end + end + + + -- Now that all obsolete tasks are removed, loop through the Transport tasks. + for TransportName, Transport in pairs( self.Transport ) do + + if not Transport.Task then + -- New Transport Task + Transport.Task = TASK_CARGO_TRANSPORT:New( Mission, self.SetGroup, TransportName, Transport.SetCargo, Transport.Briefing ) + Mission:AddTask( Transport.Task ) + TaskReport:Add( TransportName ) + if Transport.DeployZones then + Transport.Task:SetDeployZones( Transport.DeployZones or {} ) + else + Transport.Task:SetDeployZones( self.DefaultDeployZones or {} ) + end end end diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index 7da5fe917..1847a16cd 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -2783,16 +2783,6 @@ function CONTROLLABLE:IsAirPlane() return nil end -function CONTROLLABLE:GetSize() - - local DCSObject = self:GetDCSObject() - - if DCSObject then - return 1 - else - return 0 - end -end -- Message APIs \ No newline at end of file diff --git a/Moose Development/Moose/Wrapper/Positionable.lua b/Moose Development/Moose/Wrapper/Positionable.lua index 5a7f064c4..b36a2d88b 100644 --- a/Moose Development/Moose/Wrapper/Positionable.lua +++ b/Moose Development/Moose/Wrapper/Positionable.lua @@ -129,7 +129,7 @@ function POSITIONABLE:GetPointVec2() local PositionablePointVec2 = POINT_VEC2:NewFromVec3( PositionableVec3 ) - self:T2( PositionablePointVec2 ) + self:T( PositionablePointVec2 ) return PositionablePointVec2 end @@ -309,6 +309,18 @@ function POSITIONABLE:IsAboveRunway() end +function POSITIONABLE:GetSize() + + local DCSObject = self:GetDCSObject() + + if DCSObject then + return 1 + else + return 0 + end +end + + --- Returns the POSITIONABLE heading in degrees. -- @param Wrapper.Positionable#POSITIONABLE self diff --git a/Moose Development/Moose/Wrapper/Static.lua b/Moose Development/Moose/Wrapper/Static.lua index 28e7c364b..6479037a9 100644 --- a/Moose Development/Moose/Wrapper/Static.lua +++ b/Moose Development/Moose/Wrapper/Static.lua @@ -48,6 +48,24 @@ STATIC = { } +function STATIC:Register( StaticName ) + local self = BASE:Inherit( self, POSITIONABLE:New( StaticName ) ) + self.StaticName = StaticName + return self +end + + +--- Finds a STATIC from the _DATABASE using a DCSStatic object. +-- @param #STATIC self +-- @param Dcs.DCSWrapper.Static#Static DCSStatic An existing DCS Static object reference. +-- @return #STATIC self +function STATIC:Find( DCSStatic ) + + local StaticName = DCSStatic:getName() + local StaticFound = _DATABASE:FindStatic( StaticName ) + return StaticFound +end + --- Finds a STATIC from the _DATABASE using the relevant Static Name. -- As an optional parameter, a briefing text can be given also. -- @param #STATIC self @@ -71,12 +89,6 @@ function STATIC:FindByName( StaticName, RaiseError ) return nil end -function STATIC:Register( StaticName ) - local self = BASE:Inherit( self, POSITIONABLE:New( StaticName ) ) - self.StaticName = StaticName - return self -end - function STATIC:GetDCSObject() local DCSStatic = StaticObject.getByName( self.StaticName ) @@ -88,6 +100,27 @@ function STATIC:GetDCSObject() return nil end +--- Returns a list of one @{Static}. +-- @param #STATIC self +-- @return #list A list of one @{Static}. +function STATIC:GetUnits() + self:F2( { self.StaticName } ) + local DCSStatic = self:GetDCSObject() + + local Statics = {} + + if DCSStatic then + Statics[1] = STATIC:Find( DCSStatic ) + self:T3( Statics ) + return Statics + end + + return nil +end + + + + function STATIC:GetThreatLevel() return 1, "Static" @@ -101,7 +134,7 @@ function STATIC:ReSpawn( Coordinate, Heading ) -- todo: need to fix country - local SpawnStatic = SPAWNSTATIC:NewFromStatic( self.StaticName, country.id.USA ) + local SpawnStatic = SPAWNSTATIC:NewFromStatic( self.StaticName ) SpawnStatic:SpawnFromPointVec2( Coordinate, Heading, self.StaticName ) end diff --git a/Moose Setup/Moose.files b/Moose Setup/Moose.files index d1328835d..c206b5416 100644 --- a/Moose Setup/Moose.files +++ b/Moose Setup/Moose.files @@ -36,6 +36,7 @@ Wrapper/Scenery.lua Cargo/Cargo.lua Cargo/CargoUnit.lua +Cargo/CargoSlingload.lua Cargo/CargoCrate.lua Cargo/CargoGroup.lua