diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index a0cebabb4..314b6460c 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -1505,15 +1505,24 @@ do -- COORDINATE --- Creates an explosion at the point of a certain intensity. -- @param #COORDINATE self - -- @param #number ExplosionIntensity Intensity of the explosion in kg TNT. - function COORDINATE:Explosion( ExplosionIntensity ) + -- @param #number ExplosionIntensity Intensity of the explosion in kg TNT. Default 100 kg. + -- @param #number Delay Delay before explosion in seconds. + -- @return #COORDINATE self + function COORDINATE:Explosion( ExplosionIntensity, Delay ) self:F2( { ExplosionIntensity } ) - trigger.action.explosion( self:GetVec3(), ExplosionIntensity ) + ExplosionIntensity=ExplosionIntensity or 100 + if Delay and Delay>0 then + SCHEDULER:New(nil, self.Explosion, {self,ExplosionIntensity}, Delay) + else + trigger.action.explosion( self:GetVec3(), ExplosionIntensity ) + end + return self end --- Creates an illumination bomb at the point. -- @param #COORDINATE self - -- @param #number power + -- @param #number power Power of illumination bomb in Candela. + -- @return #COORDINATE self function COORDINATE:IlluminationBomb(power) self:F2() trigger.action.illuminationBomb( self:GetVec3(), power ) diff --git a/Moose Development/Moose/Functional/Range.lua b/Moose Development/Moose/Functional/Range.lua index 52e3a24cf..c3f9ee12e 100644 --- a/Moose Development/Moose/Functional/Range.lua +++ b/Moose Development/Moose/Functional/Range.lua @@ -1185,7 +1185,7 @@ function RANGE:OnEventShot(EventData) -- Weapon data. local _weapon = EventData.Weapon:getTypeName() -- should be the same as Event.WeaponTypeName - local _weaponStrArray = self:_split(_weapon,"%.") + local _weaponStrArray = UTILS.Split(_weapon,"%.") local _weaponName = _weaponStrArray[#_weaponStrArray] -- Debug info. diff --git a/Moose Development/Moose/Functional/Warehouse.lua b/Moose Development/Moose/Functional/Warehouse.lua index 3ce11bb07..3537c42d5 100644 --- a/Moose Development/Moose/Functional/Warehouse.lua +++ b/Moose Development/Moose/Functional/Warehouse.lua @@ -3675,6 +3675,8 @@ function WAREHOUSE:_RegisterAsset(group, ngroups, forceattribute, forcecargobay, local SpeedMax=group:GetSpeedMax() local RangeMin=group:GetRange() local smax,sx,sy,sz=_GetObjectSize(Descriptors) + + --self:E(Descriptors) -- Get weight and cargo bay size in kg. local weight=0 @@ -6379,6 +6381,7 @@ function WAREHOUSE:_CheckRequestValid(request) if inwater then self:E("ERROR: Incorrect request. Ground asset requested but at least one spawn zone is in water!") + --valid=false valid=false end diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index a068d6a72..039afe898 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -830,6 +830,101 @@ function CONTROLLABLE:TaskEPLRS(SwitchOnOff, idx) end +--- Used in conjunction with the embarking task for a transport helicopter group. The Ground units will move to the specified location and wait to be picked up by a helicopter. +-- The helicopter will then fly them to their dropoff point defined by another task for the ground forces; DisembarkFromTransport task. +-- The controllable has to be an infantry group! +-- @param #CONTROLLABLE self +-- @param Core.Point#COORDINATE Coordinate Coordinates where AI is expecting to be picked up. +-- @param #number Radius Radius in meters. +-- @return #table Embark to transport task. +function CONTROLLABLE:TaskEmbarkToTransport(Coordinate, Radius) + + local EmbarkToTransport = { + id="EmbarkToTransport ", + enabled=true, + auto=false, + params={ + x=Coordinate.x, + y=Coordinate.z, + zoneRadius=Radius, + selectedType="UH-1H", + } + } + + self:E(EmbarkToTransport) + return EmbarkToTransport +end + +--- Specifies the location an infantry group that is being transported by helicopters will be unloaded at. Used in conjunction with the EmbarkToTransport task. +-- The CONTROLLABLE has to be an infantry group! +-- @param #CONTROLLABLE self +-- @param Core.Point#COORDINATE Coordinate Coordinates where AI is expecting to be picked up. +-- @param #number Radius Radius in meters. +-- @return #table Embark to transport task. +function CONTROLLABLE:TaskDisembarkFromTransport(Coordinate, Radius) + + local DisembarkFromTransport={ + id="DisembarkFromTransport", + params = { + x=Coordinate.x, + y=Coordinate.y, + zoneRadius=Radius, + }} + + return DisembarkFromTransport +end + +--- Used in conjunction with the EmbarkToTransport task for a ground infantry group, the controlled helicopter flight will land at the specified coordinates, +-- pick up boarding troops and transport them to that groups DisembarkFromTransport task. +-- The CONTROLLABLE has to be a helicopter group! +-- @param #CONTROLLABLE self +-- @param Core.Set#SET_GROUP GroupSet Set of groups to be embarked by the controllable. +-- @param Core.Point#COORDINATE Coordinate Coordinate of embarking. +-- @param #number Duration Duration of embarking in seconds. +-- @return #table Embarking task. +function CONTROLLABLE:TaskEmbarking(GroupSet, Coordinate, Duration) + + -- Create table of group IDs. + local gids={} + for _,_group in pairs(GroupSet:GetAliveSet()) do + local group=_group --Wrapper.Group#GROUP + table.insert(gids, group:GetID()) + end + + -- Group ID of controllable. + local id=self:GetID() + + -- Distribution + local distribution={} + distribution[id]=gids + + local durationFlag=false + if Duration then + durationFlag=true + else + Duration=300 + end + + local DCStask={ + id="Embarking", + params={ + selectedTransport=self:GetID(), + distributionFlag=true, + distribution=distribution, + groupsForEmbarking=gids, + durationFlag=durationFlag, + distribution=distribution, + duration=Duration, + x=Coordinate.x, + y=Coordinate.z, + } + } + + self:E(DCStask) + + return DCStask +end + -- TASKS FOR AIR CONTROLLABLES --- (AIR) Attack a Controllable. -- @param #CONTROLLABLE self @@ -890,17 +985,16 @@ end --- (AIR) Attack the Unit. -- @param #CONTROLLABLE self --- @param Wrapper.Unit#UNIT AttackUnit The UNIT. --- @param #boolean GroupAttack (optional) If true, all units in the group will attack the Unit when found. --- @param DCS#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion. --- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. --- @param DCS#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. --- @param #number Altitude (optional) The altitude from where to attack. --- @param #boolean Visible (optional) not a clue. --- @param #number WeaponType (optional) The WeaponType. +-- @param Wrapper.Unit#UNIT AttackUnit The UNIT to be attacked +-- @param #boolean GroupAttack (Optional) If true, all units in the group will attack the Unit when found. Default false. +-- @param DCS#AI.Task.WeaponExpend WeaponExpend (Optional) Determines how many weapons will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion. +-- @param #number AttackQty (Optional) Limits maximal quantity of attack. The aicraft/controllable will not make more attacks than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. +-- @param DCS#Azimuth Direction (Optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. +-- @param #number Altitude (Optional) The (minimum) altitude in meters from where to attack. Default 2000 m. +-- @param #number WeaponType (optional) The WeaponType. See [DCS Enumerator Weapon Type](https://wiki.hoggitworld.com/view/DCS_enum_weapon_flag) on Hoggit. -- @return DCS#Task The DCS task structure. -function CONTROLLABLE:TaskAttackUnit( AttackUnit, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, Visible, WeaponType ) - self:F2( { self.ControllableName, AttackUnit, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, Visible, WeaponType } ) +function CONTROLLABLE:TaskAttackUnit(AttackUnit, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType) + self:F2({self.ControllableName, AttackUnit, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType}) local DCSTask DCSTask = { @@ -908,12 +1002,11 @@ function CONTROLLABLE:TaskAttackUnit( AttackUnit, GroupAttack, WeaponExpend, Att params = { unitId = AttackUnit:GetID(), groupAttack = GroupAttack or false, - visible = Visible or false, expend = WeaponExpend or "Auto", directionEnabled = Direction and true or false, - direction = Direction, + direction = math.rad(Direction or 0), altitudeEnabled = Altitude and true or false, - altitude = Altitude or 30, + altitude = Altitude or 2000, attackQtyLimit = AttackQty and true or false, attackQty = AttackQty, weaponType = WeaponType @@ -1798,6 +1891,7 @@ end +--[[ --- (AIR) Move the controllable to a Vec2 Point, wait for a defined duration and embark a controllable. -- @param #CONTROLLABLE self @@ -1846,6 +1940,8 @@ function CONTROLLABLE:TaskEmbarkToTransport( Point, Radius ) return DCSTask end +]] + --- This creates a Task element, with an action to call a function as part of a Wrapped Task. -- This Task can then be embedded at a Waypoint by calling the method @{#CONTROLLABLE.SetTaskWaypoint}. -- @param #CONTROLLABLE self diff --git a/Moose Development/Moose/Wrapper/Group.lua b/Moose Development/Moose/Wrapper/Group.lua index 25b6a9f91..4b6e77bea 100644 --- a/Moose Development/Moose/Wrapper/Group.lua +++ b/Moose Development/Moose/Wrapper/Group.lua @@ -653,6 +653,49 @@ function GROUP:GetSize() return nil end +--- Count number of alive units in the group. +-- @param #GROUP self +-- @return #number Number of alive units +function GROUP:CountAliveUnits() + self:F3( { self.GroupName } ) + local DCSGroup = self:GetDCSObject() + + if DCSGroup then + local units=self:GetUnits() + local n=0 + for _,_unit in pairs(units) do + local unit=_unit --Wrapper.Unit#UNIT + if unit and unit:IsAlive() then + n=n+1 + end + end + return n + end + + return nil +end + +--- Get the first unit of the group which is alive. +-- @param #GROUP self +-- @return Wrapper.Unit#UNIT First unit alive. +function GROUP:GetFirstUnitAlive() + self:F3({self.GroupName}) + local DCSGroup = self:GetDCSObject() + + if DCSGroup then + local units=self:GetUnits() + for _,_unit in pairs(units) do + local unit=_unit --Wrapper.Unit#UNIT + if unit and unit:IsAlive() then + return unit + end + end + end + + return nil +end + + --- Returns the average velocity Vec3 vector. -- @param Wrapper.Group#GROUP self @@ -1463,6 +1506,16 @@ function GROUP:InitRandomizePositionRadius( OuterRadius, InnerRadius ) return self end +--- Set respawn coordinate. +-- @param #GROUP self +-- @param Core.Point#COORDINATE coordinate Coordinate where the group should be respawned. +-- @return #GROUP self +function GROUP:InitCoordinate(coordinate) + self:F({coordinate=coordinate}) + self.InitCoord=coordinate + return self +end + --- Sets the radio comms on or off when the group is respawned. Same as checking/unchecking the COMM box in the mission editor. -- @param #GROUP self -- @param #boolean switch If true (or nil), enables the radio comms. If false, disables the radio for the spawned group. @@ -1603,6 +1656,11 @@ function GROUP:Respawn( Template, Reset ) end end + -- Coordinate where the group should be respawned. + if self.InitCoord then + GroupUnitVec3=self.InitCoord:GetVec3() + end + -- Altitude Template.units[UnitID].alt = self.InitRespawnHeight and self.InitRespawnHeight or GroupUnitVec3.y @@ -1647,6 +1705,11 @@ function GROUP:Respawn( Template, Reset ) end end + -- Coordinate where the group should be respawned. + if self.InitCoord then + GroupUnitVec3=self.InitCoord:GetVec3() + end + -- Set altitude. Template.units[UnitID].alt = self.InitRespawnHeight and self.InitRespawnHeight or GroupUnitVec3.y diff --git a/Moose Development/Moose/Wrapper/Static.lua b/Moose Development/Moose/Wrapper/Static.lua index 68c224922..1f2568a73 100644 --- a/Moose Development/Moose/Wrapper/Static.lua +++ b/Moose Development/Moose/Wrapper/Static.lua @@ -142,7 +142,9 @@ function STATIC:Destroy( GenerateEvent ) end - +--- Get DCS object of static of static. +-- @param #STATIC self +-- @return DCS static object function STATIC:GetDCSObject() local DCSStatic = StaticObject.getByName( self.StaticName ) @@ -172,45 +174,72 @@ function STATIC:GetUnits() end - - +--- Get threat level of static. +-- @param #STATIC self +-- @return #number Threat level 1. +-- @return #string "Static" function STATIC:GetThreatLevel() - return 1, "Static" end ---- Respawn the @{Wrapper.Unit} using a (tweaked) template of the parent Group. +--- Spawn the @{Wrapper.Static} at a specific coordinate and heading. -- @param #STATIC self -- @param Core.Point#COORDINATE Coordinate The coordinate where to spawn the new Static. --- @param #number Heading The heading of the unit respawn. -function STATIC:SpawnAt( Coordinate, Heading ) +-- @param #number Heading The heading of the static respawn in degrees. Default is 0 deg. +-- @param #number Delay Delay in seconds before the static is spawned. +function STATIC:SpawnAt( Coordinate, Heading, Delay ) - local SpawnStatic = SPAWNSTATIC:NewFromStatic( self.StaticName ) + Heading=Heading or 0 + + if Delay and Delay>0 then + SCHEDULER:New(nil, self.SpawnAt, {self, Coordinate, Heading}, Delay) + else + + local SpawnStatic = SPAWNSTATIC:NewFromStatic( self.StaticName ) - SpawnStatic:SpawnFromPointVec2( Coordinate, Heading, self.StaticName ) + SpawnStatic:SpawnFromPointVec2( Coordinate, Heading, self.StaticName ) + + end end --- Respawn the @{Wrapper.Unit} at the same location with the same properties. -- This is useful to respawn a cargo after it has been destroyed. -- @param #STATIC self --- @param DCS#country.id countryid The country ID used for spawning the new static. -function STATIC:ReSpawn(countryid) +-- @param DCS#country.id countryid The country ID used for spawning the new static. Default is same as currently. +-- @param #number Delay Delay in seconds before static is respawned. +function STATIC:ReSpawn(countryid, Delay) - local SpawnStatic = SPAWNSTATIC:NewFromStatic( self.StaticName, countryid ) + countryid=countryid or self:GetCountry() + + if Delay and Delay>0 then + SCHEDULER:New(nil, self.ReSpawn, {self, countryid}, Delay) + else + + local SpawnStatic = SPAWNSTATIC:NewFromStatic( self.StaticName, countryid ) - SpawnStatic:ReSpawn() + SpawnStatic:ReSpawn() + + end end --- Respawn the @{Wrapper.Unit} at a defined Coordinate with an optional heading. -- @param #STATIC self -- @param Core.Point#COORDINATE Coordinate The coordinate where to spawn the new Static. --- @param #number Heading The heading of the unit respawn. -function STATIC:ReSpawnAt( Coordinate, Heading ) +-- @param #number Heading The heading of the static respawn in degrees. Default is 0 deg. +-- @param #number Delay Delay in seconds before static is respawned. +function STATIC:ReSpawnAt( Coordinate, Heading, Delay ) - local SpawnStatic = SPAWNSTATIC:NewFromStatic( self.StaticName ) + Heading=Heading or 0 + + if Delay and Delay>0 then + SCHEDULER:New(nil, self.ReSpawnAt, {self, Coordinate, Heading}, Delay) + else - SpawnStatic:ReSpawnAt( Coordinate, Heading ) + local SpawnStatic = SPAWNSTATIC:NewFromStatic( self.StaticName ) + + SpawnStatic:ReSpawnAt( Coordinate, Heading ) + end end diff --git a/Moose Development/Moose/Wrapper/Unit.lua b/Moose Development/Moose/Wrapper/Unit.lua index 100f27206..1ef55065d 100644 --- a/Moose Development/Moose/Wrapper/Unit.lua +++ b/Moose Development/Moose/Wrapper/Unit.lua @@ -817,16 +817,22 @@ function UNIT:Explode(power, delay) -- Default. power=power or 100 - -- Check if delay or not. - if delay and delay>0 then - -- Delayed call. - SCHEDULER:New(nil, self.Explode, {self, power}, delay) - else - -- Create an explotion at the coordinate of the unit. - self:GetCoordinate():Explosion(power) + local DCSUnit = self:GetDCSObject() + if DCSUnit then + + -- Check if delay or not. + if delay and delay>0 then + -- Delayed call. + SCHEDULER:New(nil, self.Explode, {self, power}, delay) + else + -- Create an explotion at the coordinate of the unit. + self:GetCoordinate():Explosion(power) + end + + return self end - - return self + + return nil end -- Is functions