diff --git a/Moose Development/Moose/Cargo/CargoCrate.lua b/Moose Development/Moose/Cargo/CargoCrate.lua index b12869c16..92fccec02 100644 --- a/Moose Development/Moose/Cargo/CargoCrate.lua +++ b/Moose Development/Moose/Cargo/CargoCrate.lua @@ -154,7 +154,7 @@ do -- CARGO_CRATE if self.CargoObject then self:T("Destroying") self.NoDestroy = true - self.CargoObject:Destroy() + self.CargoObject:Destroy( false ) -- Do not generate a remove unit event, because we want to keep the template for later respawn in the database. --local Coordinate = self.CargoObject:GetCoordinate():GetRandomCoordinateInRadius( 50, 20 ) --self.CargoObject:ReSpawnAt( Coordinate, 0 ) end diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index e53ee7c6a..56b3faa46 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -672,10 +672,12 @@ end --- Private method that registers new Static Templates within the DATABASE Object. -- @param #DATABASE self --- @param #table GroupTemplate +-- @param #table StaticTemplate -- @return #DATABASE self function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, CategoryID, CountryID ) + local StaticTemplate = UTILS.DeepCopy( StaticTemplate ) + local StaticTemplateName = env.getValueDictByKey(StaticTemplate.name) self.Templates.Statics[StaticTemplateName] = self.Templates.Statics[StaticTemplateName] or {} @@ -704,11 +706,17 @@ end --- @param #DATABASE self -function DATABASE:GetStaticUnitTemplate( StaticName ) - local StaticTemplate = self.Templates.Statics[StaticName].UnitTemplate +function DATABASE:GetStaticGroupTemplate( StaticName ) + local StaticTemplate = self.Templates.Statics[StaticName].GroupTemplate return StaticTemplate, self.Templates.Statics[StaticName].CoalitionID, self.Templates.Statics[StaticName].CategoryID, self.Templates.Statics[StaticName].CountryID end +--- @param #DATABASE self +function DATABASE:GetStaticUnitTemplate( StaticName ) + local UnitTemplate = self.Templates.Statics[StaticName].UnitTemplate + return UnitTemplate, self.Templates.Statics[StaticName].CoalitionID, self.Templates.Statics[StaticName].CategoryID, self.Templates.Statics[StaticName].CountryID +end + function DATABASE:GetGroupNameFromUnitName( UnitName ) return self.Templates.Units[UnitName].GroupName diff --git a/Moose Development/Moose/Core/Spawn.lua b/Moose Development/Moose/Core/Spawn.lua index 86e495c34..614422720 100644 --- a/Moose Development/Moose/Core/Spawn.lua +++ b/Moose Development/Moose/Core/Spawn.lua @@ -1,4 +1,4 @@ ---- **Core** -- SPAWN class dynamically spawns new groups of units in your missions. +--- **Core** --Spawn dynamically new GROUPs of UNITs in your missions. -- -- === -- diff --git a/Moose Development/Moose/Core/SpawnStatic.lua b/Moose Development/Moose/Core/SpawnStatic.lua index cf4b648d5..47db57503 100644 --- a/Moose Development/Moose/Core/SpawnStatic.lua +++ b/Moose Development/Moose/Core/SpawnStatic.lua @@ -82,7 +82,7 @@ function SPAWNSTATIC:NewFromStatic( SpawnTemplatePrefix, SpawnCountryID ) --R2.1 local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC self:F( { SpawnTemplatePrefix } ) - local TemplateStatic, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticUnitTemplate( SpawnTemplatePrefix ) + local TemplateStatic, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate( SpawnTemplatePrefix ) if TemplateStatic then self.SpawnTemplatePrefix = SpawnTemplatePrefix self.CountryID = SpawnCountryID or CountryID @@ -90,7 +90,7 @@ function SPAWNSTATIC:NewFromStatic( SpawnTemplatePrefix, SpawnCountryID ) --R2.1 self.CoalitionID = CoalitionID self.SpawnIndex = 0 else - error( "SPAWNSTATIC:New: There is no group declared in the mission editor with SpawnTemplatePrefix = '" .. SpawnTemplatePrefix .. "'" ) + error( "SPAWNSTATIC:New: There is no static declared in the mission editor with SpawnTemplatePrefix = '" .. SpawnTemplatePrefix .. "'" ) end self:SetEventPriority( 5 ) @@ -124,25 +124,22 @@ end function SPAWNSTATIC:Spawn( Heading, NewName ) --R2.3 self:F( { Heading, NewName } ) - local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix ) + local StaticTemplate, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate( self.SpawnTemplatePrefix ) if StaticTemplate then - local CountryID = self.CountryID - local CountryName = _DATABASE.COUNTRY_NAME[CountryID] + local StaticUnitTemplate = StaticTemplate.units[1] 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 ) + _DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, CategoryID, CountryID ) + + local Static = coalition.addStaticObject( CountryID, StaticTemplate.units[1] ) self.SpawnIndex = self.SpawnIndex + 1 - return Static + return _DATABASE:FindStatic(Static:getName()) end return nil @@ -159,32 +156,31 @@ end function SPAWNSTATIC:SpawnFromPointVec2( PointVec2, Heading, NewName ) --R2.1 self:F( { PointVec2, Heading, NewName } ) - local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix ) + local StaticTemplate, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate( self.SpawnTemplatePrefix ) if StaticTemplate then - - local CountryID = self.CountryID - local CountryName = _DATABASE.COUNTRY_NAME[CountryID] - - StaticTemplate.x = PointVec2.x - StaticTemplate.y = PointVec2.z - StaticTemplate.units = nil + local StaticUnitTemplate = StaticTemplate.units[1] + + StaticUnitTemplate.x = PointVec2.x + StaticUnitTemplate.y = PointVec2.z + StaticTemplate.route = nil StaticTemplate.groupId = nil StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex ) - StaticTemplate.heading = ( Heading / 180 ) * math.pi + StaticUnitTemplate.name = StaticTemplate.name + StaticUnitTemplate.heading = ( Heading / 180 ) * math.pi - StaticTemplate.CountryID = nil - StaticTemplate.CoalitionID = nil - StaticTemplate.CategoryID = nil + _DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, CategoryID, CountryID) - local Static = coalition.addStaticObject( CountryID, StaticTemplate ) + self:F({StaticTemplate = StaticTemplate}) + + local Static = coalition.addStaticObject( CountryID, StaticTemplate.units[1] ) self.SpawnIndex = self.SpawnIndex + 1 - return _DATABASE:AddStatic(Static:getName()) + return _DATABASE:FindStatic(Static:getName()) end return nil @@ -197,7 +193,7 @@ end -- @return #SPAWNSTATIC function SPAWNSTATIC:ReSpawn(countryid) - local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix ) + local StaticTemplate, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate( self.SpawnTemplatePrefix ) if StaticTemplate then @@ -208,13 +204,9 @@ function SPAWNSTATIC:ReSpawn(countryid) StaticTemplate.route = nil StaticTemplate.groupId = nil - StaticTemplate.CountryID = nil - StaticTemplate.CoalitionID = nil - StaticTemplate.CategoryID = nil + local Static = coalition.addStaticObject( CountryID, StaticTemplate.units[1] ) - local Static = coalition.addStaticObject( CountryID, StaticTemplate ) - - return _DATABASE:AddStatic(Static:getName()) + return _DATABASE:FindStatic(Static:getName()) end return nil @@ -228,24 +220,20 @@ end -- @return #SPAWNSTATIC function SPAWNSTATIC:ReSpawnAt( Coordinate, Heading ) - local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix ) + local StaticTemplate, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate( self.SpawnTemplatePrefix ) if StaticTemplate then - local CountryID = self.CountryID - - StaticTemplate.x = Coordinate.x - StaticTemplate.y = Coordinate.z + local StaticUnitTemplate = StaticTemplate.units[1] + + StaticUnitTemplate.x = Coordinate.x + StaticUnitTemplate.y = Coordinate.z - StaticTemplate.heading = Heading and ( ( Heading / 180 ) * math.pi ) or StaticTemplate.heading - - StaticTemplate.CountryID = nil - StaticTemplate.CoalitionID = nil - StaticTemplate.CategoryID = nil + StaticUnitTemplate.heading = Heading and ( ( Heading / 180 ) * math.pi ) or StaticTemplate.heading - local Static = coalition.addStaticObject( CountryID, StaticTemplate ) + local Static = coalition.addStaticObject( CountryID, StaticTemplate.units[1] ) - return _DATABASE:AddStatic(Static:getName()) + return _DATABASE:FindStatic(Static:getName()) end return nil @@ -263,6 +251,6 @@ function SPAWNSTATIC:SpawnFromZone( Zone, Heading, NewName ) --R2.1 local Static = self:SpawnFromPointVec2( Zone:GetPointVec2(), Heading, NewName ) - return _DATABASE:AddStatic(Static:getName()) + return Static end diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index 256294fac..9c9e89e37 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -26,13 +26,13 @@ -- * Handle local Controllable Controller. -- * Manage the "state" of the DCS Controllable. -- --- ## CONTROLLABLE constructor +-- # 1) CONTROLLABLE constructor -- -- The CONTROLLABLE class provides the following functions to construct a CONTROLLABLE instance: -- -- * @{#CONTROLLABLE.New}(): Create a CONTROLLABLE instance. -- --- ## CONTROLLABLE Task methods +-- # 2) CONTROLLABLE Task methods -- -- Several controllable task methods are available that help you to prepare tasks. -- These methods return a string consisting of the task description, which can then be given to either a @{Wrapper.Controllable#CONTROLLABLE.PushTask} or @{Wrapper.Controllable#SetTask} method to assign the task to the CONTROLLABLE. @@ -40,7 +40,7 @@ -- Each task description where applicable indicates for which controllable category the task is valid. -- There are 2 main subdivisions of tasks: Assigned tasks and EnRoute tasks. -- --- ### Task assignment +-- ## 2.1) Task assignment -- -- Assigned task methods make the controllable execute the task where the location of the (possible) targets of the task are known before being detected. -- This is different from the EnRoute tasks, where the targets of the task need to be detected before the task can be executed. @@ -71,7 +71,7 @@ -- * @{#CONTROLLABLE.TaskRouteToZone}: (AIR + GROUND) Route the controllable to a given zone. -- * @{#CONTROLLABLE.TaskReturnToBase}: (AIR) Route the controllable to an airbase. -- --- ### EnRoute assignment +-- ## 2.2) EnRoute assignment -- -- EnRoute tasks require the targets of the task need to be detected by the controllable (using its sensors) before the task can be executed: -- @@ -84,7 +84,7 @@ -- * @{#CONTROLLABLE.EnRouteTaskFAC_EngageControllable}: (AIR + GROUND) The task makes the controllable/unit a FAC and lets the FAC to choose the target (enemy ground controllable) as well as other assigned targets. -- * @{#CONTROLLABLE.EnRouteTaskTanker}: (AIR) Aircraft will act as a tanker for friendly units. No parameters. -- --- ### Task preparation +-- ## 2.3) Task preparation -- -- There are certain task methods that allow to tailor the task behaviour: -- @@ -93,7 +93,7 @@ -- * @{#CONTROLLABLE.TaskCondition}: Return a condition section for a controlled task. -- * @{#CONTROLLABLE.TaskControlled}: Return a Controlled Task taking a Task and a TaskCondition. -- --- ### Call a function as a Task +-- ## 2.4) Call a function as a Task -- -- A function can be called which is part of a Task. The method @{#CONTROLLABLE.TaskFunction}() prepares -- a Task that can call a GLOBAL function from within the Controller execution. @@ -102,27 +102,27 @@ -- -- Demonstration Mission: [GRP-502 - Route at waypoint to random point](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/release-2-2-pre/GRP - Group Commands/GRP-502 - Route at waypoint to random point) -- --- ### Tasks at Waypoints +-- ## 2.5) Tasks at Waypoints -- -- Special Task methods are available to set tasks at certain waypoints. -- The method @{#CONTROLLABLE.SetTaskWaypoint}() helps preparing a Route, embedding a Task at the Waypoint of the Route. -- -- This creates a Task element, with an action to call a function as part of a Wrapped Task. -- --- ### Obtain the mission from controllable templates +-- ## 2.6) Obtain the mission from controllable templates -- -- Controllable templates contain complete mission descriptions. Sometimes you want to copy a complete mission from a controllable and assign it to another: -- -- * @{#CONTROLLABLE.TaskMission}: (AIR + GROUND) Return a mission task from a mission template. -- --- ## CONTROLLABLE Command methods +-- # 3) Command methods -- -- Controllable **command methods** prepare the execution of commands using the @{#CONTROLLABLE.SetCommand} method: -- -- * @{#CONTROLLABLE.CommandDoScript}: Do Script command. -- * @{#CONTROLLABLE.CommandSwitchWayPoint}: Perform a switch waypoint command. -- --- ## Routing of Controllables +-- # 4) Routing of Controllables -- -- Different routing methods exist to route GROUPs and UNITs to different locations: -- @@ -130,11 +130,11 @@ -- * @{#CONTROLLABLE.RouteGroundTo}(): Make the GROUND Controllable to drive towards a specific coordinate. -- * @{#CONTROLLABLE.RouteAirTo}(): Make the AIR Controllable to fly towards a specific coordinate. -- --- ## Option methods +-- # 5) Option methods -- -- Controllable **Option methods** change the behaviour of the Controllable while being alive. -- --- ### Rule of Engagement: +-- ## 5.1) Rule of Engagement: -- -- * @{#CONTROLLABLE.OptionROEWeaponFree} -- * @{#CONTROLLABLE.OptionROEOpenFire} @@ -148,7 +148,7 @@ -- * @{#CONTROLLABLE.OptionROEReturnFirePossible} -- * @{#CONTROLLABLE.OptionROEEvadeFirePossible} -- --- ### Rule on thread: +-- ## 5.2) Rule on thread: -- -- * @{#CONTROLLABLE.OptionROTNoReaction} -- * @{#CONTROLLABLE.OptionROTPassiveDefense} @@ -162,6 +162,12 @@ -- * @{#CONTROLLABLE.OptionROTEvadeFirePossible} -- * @{#CONTROLLABLE.OptionROTVerticalPossible} -- +-- ## 5.3) Alarm state: +-- +-- * @{#CONTROLLABLE.OptionAlarmStateAuto} +-- * @{#CONTROLLABLE.OptionAlarmStateGreen} +-- * @{#CONTROLLABLE.OptionAlarmStateRed} +-- -- @field #CONTROLLABLE CONTROLLABLE = { ClassName = "CONTROLLABLE", diff --git a/Moose Development/Moose/Wrapper/Static.lua b/Moose Development/Moose/Wrapper/Static.lua index ef488443c..fd20f3328 100644 --- a/Moose Development/Moose/Wrapper/Static.lua +++ b/Moose Development/Moose/Wrapper/Static.lua @@ -89,6 +89,59 @@ function STATIC:FindByName( StaticName, RaiseError ) return nil end +--- Destroys the STATIC. +-- @param #STATIC self +-- @param #boolean GenerateEvent (Optional) true if you want to generate a crash or dead event for the static. +-- @return #nil The DCS StaticObject is not existing or alive. +-- @usage +-- -- Air static example: destroy the static Helicopter and generate a S_EVENT_CRASH. +-- Helicopter = STATIC:FindByName( "Helicopter" ) +-- Helicopter:Destroy( true ) +-- +-- @usage +-- -- Ground static example: destroy the static Tank and generate a S_EVENT_DEAD. +-- Tanks = UNIT:FindByName( "Tank" ) +-- Tanks:Destroy( true ) +-- +-- @usage +-- -- Ship static example: destroy the Ship silently. +-- Ship = STATIC:FindByName( "Ship" ) +-- Ship:Destroy() +-- +-- @usage +-- -- Destroy without event generation example. +-- Ship = STATIC:FindByName( "Boat" ) +-- Ship:Destroy( false ) -- Don't generate an event upon destruction. +-- +function STATIC:Destroy( GenerateEvent ) + self:F2( self.ObjectName ) + + local DCSObject = self:GetDCSObject() + + if DCSObject then + + local StaticName = DCSObject:getName() + self:F( { StaticName = StaticName } ) + + if GenerateEvent and GenerateEvent == true then + if self:IsAir() then + self:CreateEventCrash( timer.getTime(), DCSObject ) + else + self:CreateEventDead( timer.getTime(), DCSObject ) + end + elseif GenerateEvent == false then + -- Do nothing! + else + self:CreateEventRemoveUnit( timer.getTime(), DCSObject ) + end + + DCSObject:destroy() + end + + return nil +end + + function STATIC:GetDCSObject() local DCSStatic = StaticObject.getByName( self.StaticName )