diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua index 12fca41cc..4d5512147 100644 --- a/Moose Development/Moose/Core/Zone.lua +++ b/Moose Development/Moose/Core/Zone.lua @@ -861,13 +861,29 @@ end function ZONE_RADIUS:GetRandomPointVec2( inner, outer ) self:F( self.ZoneName, inner, outer ) - local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2() ) + local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2( inner, outer ) ) self:T3( { PointVec2 } ) return PointVec2 end +--- Returns Returns a random Vec3 location within the zone. +-- @param #ZONE_RADIUS self +-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0. +-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. +-- @return Dcs.DCSTypes#Vec3 The random location within the zone. +function ZONE_RADIUS:GetRandomVec3( inner, outer ) + self:F( self.ZoneName, inner, outer ) + + local Vec2 = self:GetRandomVec2( inner, outer ) + + self:T3( { x = Vec2.x, y = self.y, z = Vec2.y } ) + + return { x = Vec2.x, y = self.y, z = Vec2.y } +end + + --- Returns a @{Point#POINT_VEC3} object reflecting a random 3D location within the zone. -- @param #ZONE_RADIUS self -- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0. @@ -876,7 +892,7 @@ end function ZONE_RADIUS:GetRandomPointVec3( inner, outer ) self:F( self.ZoneName, inner, outer ) - local PointVec3 = POINT_VEC3:NewFromVec2( self:GetRandomVec2() ) + local PointVec3 = POINT_VEC3:NewFromVec2( self:GetRandomVec2( inner, outer ) ) self:T3( { PointVec3 } ) diff --git a/Moose Development/Moose/Wrapper/Group.lua b/Moose Development/Moose/Wrapper/Group.lua index 267326066..2c3f8f271 100644 --- a/Moose Development/Moose/Wrapper/Group.lua +++ b/Moose Development/Moose/Wrapper/Group.lua @@ -917,59 +917,7 @@ function GROUP:GetMaxHeight() end --- SPAWNING - ---- Respawn the @{GROUP} using a (tweaked) template of the Group. --- The template must be retrieved with the @{Group#GROUP.GetTemplate}() function. --- The template contains all the definitions as declared within the mission file. --- To understand templates, do the following: --- --- * unpack your .miz file into a directory using 7-zip. --- * browse in the directory created to the file **mission**. --- * open the file and search for the country group definitions. --- --- Your group template will contain the fields as described within the mission file. --- --- This function will: --- --- * Get the current position and heading of the group. --- * When the group is alive, it will tweak the template x, y and heading coordinates of the group and the embedded units to the current units positions. --- * Then it will destroy the current alive group. --- * And it will respawn the group using your new template definition. --- @param Wrapper.Group#GROUP self --- @param #table Template The template of the Group retrieved with GROUP:GetTemplate() -function GROUP:Respawn( Template ) - - if self:IsAlive() then - local Vec3 = self:GetVec3() - Template.x = Vec3.x - Template.y = Vec3.z - --Template.x = nil - --Template.y = nil - - self:E( #Template.units ) - for UnitID, UnitData in pairs( self:GetUnits() ) do - local GroupUnit = UnitData -- Wrapper.Unit#UNIT - self:E( GroupUnit:GetName() ) - if GroupUnit:IsAlive() then - local GroupUnitVec3 = GroupUnit:GetVec3() - local GroupUnitHeading = GroupUnit:GetHeading() - Template.units[UnitID].alt = GroupUnitVec3.y - Template.units[UnitID].x = GroupUnitVec3.x - Template.units[UnitID].y = GroupUnitVec3.z - Template.units[UnitID].heading = GroupUnitHeading - self:E( { UnitID, Template.units[UnitID], Template.units[UnitID] } ) - end - end - - end - - self:Destroy() - _DATABASE:Spawn( Template ) - - self:ResetEvents() - -end +-- RESPAWNING --- Returns the group template from the @{DATABASE} (_DATABASE object). -- @param #GROUP self @@ -1017,6 +965,166 @@ function GROUP:SetTemplateCoalition( Template, CoalitionID ) end +--- Set the heading for the units in degrees within the respawned group. +-- @param #GROUP self +-- @param #number Heading The heading in meters. +-- @return #GROUP self +function GROUP:InitHeading( Heading ) + self.InitRespawnHeading = Heading + return self +end + + +--- Set the height for the units in meters for the respawned group. (This is applicable for air units). +-- @param #GROUP self +-- @param #number Height The height in meters. +-- @return #GROUP self +function GROUP:InitHeight( Height ) + self.InitRespawnHeight = Height + return self +end + + +--- Set the respawn @{Zone} for the respawned group. +-- @param #GROUP self +-- @param Core.Zone#ZONE Zone The zone in meters. +-- @return #GROUP self +function GROUP:InitZone( Zone ) + self.InitRespawnZone = Zone + return self +end + + +--- Randomize the positions of the units of the respawned group within the @{Zone}. +-- When a Respawn happens, the units of the group will be placed at random positions within the Zone (selected). +-- @param #GROUP self +-- @param #boolean PositionZone true will randomize the positions within the Zone. +-- @return #GROUP self +function GROUP:InitRandomizePositionZone( PositionZone ) + + self.InitRespawnRandomizePositionZone = PositionZone + self.InitRespawnRandomizePositionInner = nil + self.InitRespawnRandomizePositionOuter = nil + + return self +end + + +--- Randomize the positions of the units of the respawned group in a circle band. +-- When a Respawn happens, the units of the group will be positioned at random places within the Outer and Inner radius. +-- Thus, a band is created around the respawn location where the units will be placed at random positions. +-- @param #GROUP self +-- @param #boolean OuterRadius Outer band in meters from the center. +-- @param #boolean InnerRadius Inner band in meters from the center. +-- @return #GROUP self +function GROUP:InitRandomizePositionRadius( OuterRadius, InnerRadius ) + + self.InitRespawnRandomizePositionZone = nil + self.InitRespawnRandomizePositionOuter = OuterRadius + self.InitRespawnRandomizePositionInner = InnerRadius + + return self +end + + +--- Respawn the @{Group} at a @{Point}. +-- The method will setup the new group template according the Init(Respawn) settings provided for the group. +-- These settings can be provided by calling the relevant Init...() methods of the Group. +-- +-- - @{#GROUP.InitHeading}: Set the heading for the units in degrees within the respawned group. +-- - @{#GROUP.InitHeight}: Set the height for the units in meters for the respawned group. (This is applicable for air units). +-- - @{#GROUP.InitRandomizeHeading}: Randomize the headings for the units within the respawned group. +-- - @{#GROUP.InitZone}: Set the respawn @{Zone} for the respawned group. +-- - @{#GROUP.InitRandomizeZones}: Randomize the respawn @{Zone} between one of the @{Zone}s given for the respawned group. +-- - @{#GROUP.InitRandomizePositionZone}: Randomize the positions of the units of the respawned group within the @{Zone}. +-- - @{#GROUP.InitRandomizePositionRadius}: Randomize the positions of the units of the respawned group in a circle band. +-- - @{#GROUP.InitRandomizeTemplates}: Randomize the Template for the respawned group. +-- +-- +-- Notes: +-- +-- - When InitZone or InitRandomizeZones is not used, the position of the respawned group will be its current position. +-- - The current alive group will always be destroyed and respawned using the template definition. +-- +-- @param Wrapper.Group#GROUP self +-- @param #table Template (optional) The template of the Group retrieved with GROUP:GetTemplate(). If the template is not provided, the template will be retrieved of the group itself. +function GROUP:Respawn( Template, Reset ) + + if not Template then + Template = self:GetTemplate() + end + + if self:IsAlive() then + local Zone = self.InitRespawnZone -- Core.Zone#ZONE + local Vec3 = Zone and Zone:GetVec3() or self:GetVec3() + local From = { x = Template.x, y = Template.y } + Template.x = Vec3.x + Template.y = Vec3.z + --Template.x = nil + --Template.y = nil + + self:E( #Template.units ) + if Reset == true then + for UnitID, UnitData in pairs( self:GetUnits() ) do + local GroupUnit = UnitData -- Wrapper.Unit#UNIT + self:E( GroupUnit:GetName() ) + if GroupUnit:IsAlive() then + self:E( "Alive" ) + local GroupUnitVec3 = GroupUnit:GetVec3() + if Zone then + if self.InitRespawnRandomizePositionZone then + GroupUnitVec3 = Zone:GetRandomVec3() + else + if self.InitRespawnRandomizePositionInner and self.InitRespawnRandomizePositionOuter then + GroupUnitVec3 = POINT_VEC3:NewFromVec2( From ):GetRandomPointVec3InRadius( self.InitRespawnRandomizePositionsOuter, self.InitRespawnRandomizePositionsInner ) + else + GroupUnitVec3 = Zone:GetVec3() + end + end + end + + Template.units[UnitID].alt = self.InitRespawnHeight and self.InitRespawnHeight or GroupUnitVec3.y + Template.units[UnitID].x = ( Template.units[UnitID].x - From.x ) + GroupUnitVec3.x -- Keep the original x position of the template and translate to the new position. + Template.units[UnitID].y = ( Template.units[UnitID].y - From.y ) + GroupUnitVec3.z -- Keep the original z position of the template and translate to the new position. + Template.units[UnitID].heading = self.InitRespawnHeading and self.InitRespawnHeading or GroupUnit:GetHeading() + self:E( { UnitID, Template.units[UnitID], Template.units[UnitID] } ) + end + end + else + for UnitID, TemplateUnitData in pairs( Template.units ) do + self:E( "Reset" ) + local GroupUnitVec3 = { x = TemplateUnitData.x, y = TemplateUnitData.alt, z = TemplateUnitData.z } + if Zone then + if self.InitRespawnRandomizePositionZone then + GroupUnitVec3 = Zone:GetRandomVec3() + else + if self.InitRespawnRandomizePositionInner and self.InitRespawnRandomizePositionOuter then + GroupUnitVec3 = POINT_VEC3:NewFromVec2( From ):GetRandomPointVec3InRadius( self.InitRespawnRandomizePositionsOuter, self.InitRespawnRandomizePositionsInner ) + else + GroupUnitVec3 = Zone:GetVec3() + end + end + end + + Template.units[UnitID].alt = self.InitRespawnHeight and self.InitRespawnHeight or GroupUnitVec3.y + Template.units[UnitID].x = ( Template.units[UnitID].x - From.x ) + GroupUnitVec3.x -- Keep the original x position of the template and translate to the new position. + Template.units[UnitID].y = ( Template.units[UnitID].y - From.y ) + GroupUnitVec3.z -- Keep the original z position of the template and translate to the new position. + Template.units[UnitID].heading = self.InitRespawnHeading and self.InitRespawnHeading or TemplateUnitData.heading + self:E( { UnitID, Template.units[UnitID], Template.units[UnitID] } ) + end + end + + end + + self:Destroy() + _DATABASE:Spawn( Template ) + + self:ResetEvents() + +end + + + --- Return the mission template of the group.