diff --git a/Moose Development/Moose/Wrapper/Group.lua b/Moose Development/Moose/Wrapper/Group.lua index a37c32132..a8afc6fbe 100644 --- a/Moose Development/Moose/Wrapper/Group.lua +++ b/Moose Development/Moose/Wrapper/Group.lua @@ -1,9 +1,9 @@ --- **Wrapper** - GROUP wraps the DCS Class Group objects. --- +-- -- === --- +-- -- The @{#GROUP} class is a wrapper class to handle the DCS Group objects. --- +-- -- ## Features: -- -- * Support all DCS Group APIs. @@ -14,27 +14,27 @@ -- **IMPORTANT: ONE SHOULD NEVER SANITIZE these GROUP OBJECT REFERENCES! (make the GROUP object references nil).** -- -- === --- +-- -- For each DCS Group object alive within a running mission, a GROUP wrapper object (instance) will be created within the global _DATABASE object (an instance of @{Core.Database#DATABASE}). -- This is done at the beginning of the mission (when the mission starts), and dynamically when new DCS Group objects are spawned (using the @{Core.Spawn} class). --- +-- -- The GROUP class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference -- using the DCS Group or the DCS GroupName. -- -- The GROUP methods will reference the DCS Group object by name when it is needed during API execution. -- If the DCS Group object does not exist or is nil, the GROUP methods will return nil and may log an exception in the DCS.log file. --- +-- -- === --- +-- -- ### Author: **FlightControl** --- --- ### Contributions: --- +-- +-- ### Contributions: +-- -- * **Entropy**, **Afinegan**: Came up with the requirement for AIOnOff(). -- * **Applevangelist**: various --- +-- -- === --- +-- -- @module Wrapper.Group -- @image Wrapper_Group.JPG @@ -45,9 +45,9 @@ --- Wrapper class of the DCS world Group object. --- +-- -- ## Finding groups --- +-- -- The GROUP class provides the following functions to retrieve quickly the relevant GROUP instance: -- -- * @{#GROUP.Find}(): Find a GROUP instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Group object. @@ -57,28 +57,28 @@ -- -- ## Tasking of groups -- --- A GROUP is derived from the wrapper class CONTROLLABLE (@{Wrapper.Controllable#CONTROLLABLE}). +-- A GROUP is derived from the wrapper class CONTROLLABLE (@{Wrapper.Controllable#CONTROLLABLE}). -- See the @{Wrapper.Controllable} task methods section for a description of the task methods. -- -- But here is an example how a group can be assigned a task. --- +-- -- This test demonstrates the use(s) of the SwitchWayPoint method of the GROUP class. --- +-- -- First we look up the objects. We create a GROUP object `HeliGroup`, using the @{#GROUP:FindByName}() method, looking up the `"Helicopter"` group object. -- Same for the `"AttackGroup"`. --- +-- -- local HeliGroup = GROUP:FindByName( "Helicopter" ) -- local AttackGroup = GROUP:FindByName( "AttackGroup" ) --- --- Now we retrieve the @{Wrapper.Unit#UNIT} objects of the `AttackGroup` object, using the method `:GetUnits()`. --- +-- +-- Now we retrieve the @{Wrapper.Unit#UNIT} objects of the `AttackGroup` object, using the method `:GetUnits()`. +-- -- local AttackUnits = AttackGroup:GetUnits() --- +-- -- Tasks are actually text strings that we build using methods of GROUP. --- So first, we declare an list of `Tasks`. --- +-- So first, we declare an list of `Tasks`. +-- -- local Tasks = {} --- +-- -- Now we loop over the `AttackUnits` using a for loop. -- We retrieve the `AttackUnit` using the `AttackGroup:GetUnit()` method. -- Each `AttackUnit` found, will be attacked by `HeliGroup`, using the method `HeliGroup:TaskAttackUnit()`. @@ -86,74 +86,74 @@ -- The code will assign the task string command to the next element in the `Task` list, using `Tasks[#Tasks+1]`. -- This little code will take the count of `Task` using `#` operator, and will add `1` to the count. -- This result will be the index of the `Task` element. --- +-- -- for i = 1, #AttackUnits do -- local AttackUnit = AttackGroup:GetUnit( i ) -- Tasks[#Tasks+1] = HeliGroup:TaskAttackUnit( AttackUnit ) -- end --- +-- -- Once these tasks have been executed, a function `_Resume` will be called ... --- +-- -- Tasks[#Tasks+1] = HeliGroup:TaskFunction( "_Resume", { "''" } ) --- +-- -- -- @param Wrapper.Group#GROUP HeliGroup -- function _Resume( HeliGroup ) -- env.info( '_Resume' ) --- +-- -- HeliGroup:MessageToAll( "Resuming",10,"Info") -- end --- +-- -- Now here is where the task gets assigned! -- Using `HeliGroup:PushTask`, the task is pushed onto the task queue of the group `HeliGroup`. -- Since `Tasks` is an array of tasks, we use the `HeliGroup:TaskCombo` method to execute the tasks. -- The `HeliGroup:PushTask` method can receive a delay parameter in seconds. -- In the example, `30` is given as a delay. --- --- --- HeliGroup:PushTask( +-- +-- +-- HeliGroup:PushTask( -- HeliGroup:TaskCombo( -- Tasks --- ), 30 --- ) --- +-- ), 30 +-- ) +-- -- That's it! -- But again, please refer to the @{Wrapper.Controllable} task methods section for a description of the different task methods that are available. --- --- +-- +-- -- -- ### Obtain the mission from group templates --- +-- -- Group templates contain complete mission descriptions. Sometimes you want to copy a complete mission from a group and assign it to another: --- +-- -- * @{Wrapper.Controllable#CONTROLLABLE.TaskMission}: (AIR + GROUND) Return a mission task from a mission template. -- -- ## GROUP Command methods -- -- A GROUP is a @{Wrapper.Controllable}. See the @{Wrapper.Controllable} command methods section for a description of the command methods. --- +-- -- ## GROUP option methods -- -- A GROUP is a @{Wrapper.Controllable}. See the @{Wrapper.Controllable} option methods section for a description of the option methods. --- +-- -- ## GROUP Zone validation methods --- +-- -- The group can be validated whether it is completely, partly or not within a @{Core.Zone}. -- Use the following Zone validation methods on the group: --- +-- -- * @{#GROUP.IsCompletelyInZone}: Returns true if all units of the group are within a @{Core.Zone}. -- * @{#GROUP.IsPartlyInZone}: Returns true if some units of the group are within a @{Core.Zone}. -- * @{#GROUP.IsNotInZone}: Returns true if none of the group units of the group are within a @{Core.Zone}. --- +-- -- The zone can be of any @{Core.Zone} class derived from @{Core.Zone#ZONE_BASE}. So, these methods are polymorphic to the zones tested on. --- +-- -- ## GROUP AI methods --- +-- -- A GROUP has AI methods to control the AI activation. --- +-- -- * @{#GROUP.SetAIOnOff}(): Turns the GROUP AI On or Off. -- * @{#GROUP.SetAIOn}(): Turns the GROUP AI On. -- * @{#GROUP.SetAIOff}(): Turns the GROUP AI Off. --- +-- -- @field #GROUP GROUP GROUP = { ClassName = "GROUP", @@ -255,7 +255,7 @@ function GROUP:NewTemplate( GroupTemplate, CoalitionSide, CategoryID, CountryID if not _DATABASE.GROUPS[GroupName] then _DATABASE.GROUPS[GroupName] = self - end + end self:SetEventPriority( 4 ) return self @@ -270,9 +270,9 @@ end function GROUP:Register( GroupName ) local self = BASE:Inherit( self, CONTROLLABLE:New( GroupName ) ) -- #GROUP - + self.GroupName = GroupName - + self:SetEventPriority( 4 ) return self end @@ -308,20 +308,20 @@ end -- -- Find a group with a partial group name -- local grp = GROUP:FindByMatching( "Apple" ) -- -- will return e.g. a group named "Apple-1-1" --- +-- -- -- using a pattern -- local grp = GROUP:FindByMatching( ".%d.%d$" ) -- -- will return the first group found ending in "-1-1" to "-9-9", but not e.g. "-10-1" function GROUP:FindByMatching( Pattern ) local GroupFound = nil - + for name,group in pairs(_DATABASE.GROUPS) do if string.match(name, Pattern ) then GroupFound = group break end end - + return GroupFound end @@ -333,19 +333,19 @@ end -- -- Find all group with a partial group name -- local grptable = GROUP:FindAllByMatching( "Apple" ) -- -- will return all groups with "Apple" in the name --- +-- -- -- using a pattern -- local grp = GROUP:FindAllByMatching( ".%d.%d$" ) -- -- will return the all groups found ending in "-1-1" to "-9-9", but not e.g. "-10-1" or "-1-10" function GROUP:FindAllByMatching( Pattern ) local GroupsFound = {} - + for name,group in pairs(_DATABASE.GROUPS) do if string.match(name, Pattern ) then GroupsFound[#GroupsFound+1] = group end end - + return GroupsFound end @@ -366,12 +366,12 @@ end --- Returns the @{DCS#Position3} position vectors indicating the point and direction vectors in 3D of the POSITIONABLE within the mission. -- @param Wrapper.Positionable#POSITIONABLE self --- @return DCS#Position The 3D position vectors of the POSITIONABLE or #nil if the groups not existing or alive. +-- @return DCS#Position The 3D position vectors of the POSITIONABLE or #nil if the groups not existing or alive. function GROUP:GetPositionVec3() -- Overridden from POSITIONABLE:GetPositionVec3() self:F2( self.PositionableName ) local DCSPositionable = self:GetDCSObject() - + if DCSPositionable then local unit = DCSPositionable:getUnits()[1] if unit then @@ -380,19 +380,19 @@ function GROUP:GetPositionVec3() -- Overridden from POSITIONABLE:GetPositionVec3 return PositionablePosition end end - + return nil end --- Returns if the group is alive. -- The Group must: --- +-- -- * Exist at run-time. -- * Has at least one unit. --- +-- -- When the first @{Wrapper.Unit} of the group is active, it will return true. -- If the first @{Wrapper.Unit} of the group is inactive, it will return false. --- +-- -- @param #GROUP self -- @return #boolean `true` if the group is alive *and* active, `false` if the group is alive but inactive or `#nil` if the group does not exist anymore. function GROUP:IsAlive() @@ -416,17 +416,17 @@ end --- Returns if the group is activated. -- @param #GROUP self --- @return #boolean `true` if group is activated or `#nil` The group is not existing or alive. +-- @return #boolean `true` if group is activated or `#nil` The group is not existing or alive. function GROUP:IsActive() self:F2( self.GroupName ) local DCSGroup = self:GetDCSObject() -- DCS#Group - + if DCSGroup then local unit = DCSGroup:getUnit(1) if unit then local GroupIsActive = unit:isActive() - return GroupIsActive + return GroupIsActive end end @@ -454,21 +454,21 @@ end -- -- Ship unit example: destroy the Ship silently. -- Ship = GROUP:FindByName( "Ship" ) -- Ship:Destroy() --- +-- -- @usage -- -- Destroy without event generation example. -- Ship = GROUP:FindByName( "Boat" ) -- Ship:Destroy( false ) -- Don't generate an event upon destruction. --- +-- function GROUP:Destroy( GenerateEvent, delay ) self:F2( self.GroupName ) - + if delay and delay>0 then self:ScheduleOnce(delay, GROUP.Destroy, self, GenerateEvent) else local DCSGroup = self:GetDCSObject() - + if DCSGroup then for Index, UnitData in pairs( DCSGroup:getUnits() ) do if GenerateEvent and GenerateEvent == true then @@ -488,19 +488,19 @@ function GROUP:Destroy( GenerateEvent, delay ) DCSGroup = nil end end - + return nil end --- Returns category of the DCS Group. Returns one of --- +-- -- * Group.Category.AIRPLANE -- * Group.Category.HELICOPTER -- * Group.Category.GROUND -- * Group.Category.SHIP -- * Group.Category.TRAIN --- +-- -- @param #GROUP self -- @return DCS#Group.Category The category ID. function GROUP:GetCategory() @@ -584,12 +584,12 @@ function GROUP:HasAttribute(attribute, all) -- Get all units of the group. local _units=self:GetUnits() - + if _units then - + local _allhave=true local _onehas=false - + for _,_unit in pairs(_units) do local _unit=_unit --Wrapper.Unit#UNIT if _unit then @@ -599,17 +599,17 @@ function GROUP:HasAttribute(attribute, all) else _allhave=false end - end + end end - + if all==true then return _allhave else return _onehas end - + end - + return nil end @@ -622,27 +622,27 @@ function GROUP:GetSpeedMax() local DCSGroup = self:GetDCSObject() if DCSGroup then - + local Units=self:GetUnits() - + local speedmax=nil - + for _,unit in pairs(Units) do local unit=unit --Wrapper.Unit#UNIT - + local speed=unit:GetSpeedMax() - + if speedmax==nil or speed threatlevelMax then threatlevelMax=threatlevel @@ -2371,12 +2372,12 @@ end --- Returns true if the first unit of the GROUP is in the air. -- @param Wrapper.Group#GROUP self --- @return #boolean true if in the first unit of the group is in the air or #nil if the GROUP is not existing or not alive. +-- @return #boolean true if in the first unit of the group is in the air or #nil if the GROUP is not existing or not alive. function GROUP:InAir() self:F2( self.GroupName ) local DCSGroup = self:GetDCSObject() - + if DCSGroup then local DCSUnit = DCSGroup:getUnit(1) if DCSUnit then @@ -2385,7 +2386,7 @@ function GROUP:InAir() return GroupInAir end end - + return nil end @@ -2398,58 +2399,58 @@ function GROUP:IsAirborne(AllUnits) -- Get all units of the group. local units=self:GetUnits() - + if units then - + if AllUnits then - + --- We want to know if ALL units are airborne. for _,_unit in pairs(units) do local unit=_unit --Wrapper.Unit#UNIT - + if unit then - + -- Unit in air or not. local inair=unit:InAir() - + -- At least one unit is not in air. if not inair then return false end end - + end - + -- All units are in air. return true - + else - + --- We want to know if ANY unit is airborne. for _,_unit in pairs(units) do local unit=_unit --Wrapper.Unit#UNIT - + if unit then - + -- Unit in air or not. local inair=unit:InAir() - + if inair then -- At least one unit is in air. return true end - + end - + -- No unit is in air. return false - + end end end - + return nil end @@ -2458,17 +2459,17 @@ end --- Returns the DCS descriptor table of the nth unit of the group. -- @param #GROUP self -- @param #number n (Optional) The number of the unit for which the dscriptor is returned. --- @return DCS#Object.Desc The descriptor of the first unit of the group or #nil if the group does not exist any more. +-- @return DCS#Object.Desc The descriptor of the first unit of the group or #nil if the group does not exist any more. function GROUP:GetDCSDesc(n) -- Default. n=n or 1 - + local unit=self:GetUnit(n) if unit and unit:IsAlive()~=nil then local desc=unit:GetDesc() return desc end - + return nil end @@ -2530,14 +2531,14 @@ function GROUP:GetAttribute() elseif bomber then attribute=GROUP.Attribute.AIR_BOMBER elseif awacs then - attribute=GROUP.Attribute.AIR_AWACS + attribute=GROUP.Attribute.AIR_AWACS elseif transportplane then attribute=GROUP.Attribute.AIR_TRANSPORTPLANE elseif tanker then attribute=GROUP.Attribute.AIR_TANKER -- helos elseif attackhelicopter then - attribute=GROUP.Attribute.AIR_ATTACKHELO + attribute=GROUP.Attribute.AIR_ATTACKHELO elseif transporthelo then attribute=GROUP.Attribute.AIR_TRANSPORTHELO elseif uav then @@ -2550,15 +2551,15 @@ function GROUP:GetAttribute() elseif aaa then attribute=GROUP.Attribute.GROUND_AAA elseif artillery then - attribute=GROUP.Attribute.GROUND_ARTILLERY + attribute=GROUP.Attribute.GROUND_ARTILLERY elseif tank then - attribute=GROUP.Attribute.GROUND_TANK + attribute=GROUP.Attribute.GROUND_TANK elseif ifv then - attribute=GROUP.Attribute.GROUND_IFV + attribute=GROUP.Attribute.GROUND_IFV elseif apc then attribute=GROUP.Attribute.GROUND_APC elseif infantry then - attribute=GROUP.Attribute.GROUND_INFANTRY + attribute=GROUP.Attribute.GROUND_INFANTRY elseif truck then attribute=GROUP.Attribute.GROUND_TRUCK elseif train then @@ -2591,67 +2592,67 @@ end do -- Route methods - --- (AIR) Return the Group to an @{Wrapper.Airbase#AIRBASE}. + --- (AIR) Return the Group to an @{Wrapper.Airbase#AIRBASE}. -- The following things are to be taken into account: - -- + -- -- * The group is respawned to achieve the RTB, there may be side artefacts as a result of this. (Like weapons suddenly come back). -- * A group consisting out of more than one unit, may rejoin formation when respawned. -- * A speed can be given in km/h. If no speed is specified, the maximum speed of the first unit will be taken to return to base. -- * When there is no @{Wrapper.Airbase} object specified, the group will return to the home base if the route of the group is pinned at take-off or at landing to a base. -- * When there is no @{Wrapper.Airbase} object specified and the group route is not pinned to any airbase, it will return to the nearest airbase. - -- + -- -- @param #GROUP self -- @param Wrapper.Airbase#AIRBASE RTBAirbase (optional) The @{Wrapper.Airbase} to return to. If blank, the controllable will return to the nearest friendly airbase. - -- @param #number Speed (optional) The Speed, if no Speed is given, 80% of maximum Speed of the group is selected. + -- @param #number Speed (optional) The Speed, if no Speed is given, 80% of maximum Speed of the group is selected. -- @return #GROUP self function GROUP:RouteRTB( RTBAirbase, Speed ) self:F( { RTBAirbase:GetName(), Speed } ) - + local DCSGroup = self:GetDCSObject() - + if DCSGroup then - + if RTBAirbase then - + -- If speed is not given take 80% of max speed. local Speed=Speed or self:GetSpeedMax()*0.8 - + -- Curent (from) waypoint. local coord=self:GetCoordinate() local PointFrom=coord:WaypointAirTurningPoint(nil, Speed) - + -- Airbase coordinate. --local PointAirbase=RTBAirbase:GetCoordinate():SetAltitude(coord.y):WaypointAirTurningPoint(nil ,Speed) - + -- Landing waypoint. More general than prev version since it should also work with FAPRS and ships. - local PointLanding=RTBAirbase:GetCoordinate():WaypointAirLanding(Speed, RTBAirbase) - + local PointLanding=RTBAirbase:GetCoordinate():WaypointAirLanding(Speed, RTBAirbase) + -- Waypoint table. local Points={PointFrom, PointLanding} --local Points={PointFrom, PointAirbase, PointLanding} - + -- Debug info. self:T3(Points) -- Get group template. local Template=self:GetTemplate() - + -- Set route points. Template.route.points=Points - + -- Respawn the group. self:Respawn(Template, true) - + -- Route the group or this will not work. self:Route(Points) else - + -- Clear all tasks. self:ClearTasks() - + end end - + return self end @@ -2670,20 +2671,20 @@ do -- Event Handling -- @param #function EventFunction (optional) The function to be called when the event occurs for the GROUP. -- @return #GROUP function GROUP:HandleEvent( Event, EventFunction, ... ) - + self:EventDispatcher():OnEventForGroup( self:GetName(), EventFunction, self, Event, ... ) - + return self end - + --- UnSubscribe to a DCS event. -- @param #GROUP self -- @param Core.Event#EVENTS Event -- @return #GROUP function GROUP:UnHandleEvent( Event ) - + self:EventDispatcher():RemoveEvent( self, Event ) - + return self end @@ -2691,13 +2692,13 @@ do -- Event Handling -- @param #GROUP self -- @return #GROUP function GROUP:ResetEvents() - + self:EventDispatcher():Reset( self ) - + for UnitID, UnitData in pairs( self:GetUnits() ) do UnitData:ResetEvents() end - + return self end @@ -2710,11 +2711,11 @@ do -- Players -- @return #table The group has players, an array of player names is returned. -- @return #nil The group has no players function GROUP:GetPlayerNames() - + local HasPlayers = false - + local PlayerNames = {} - + local Units = self:GetUnits() for UnitID, UnitData in pairs( Units ) do local Unit = UnitData -- Wrapper.Unit#UNIT @@ -2723,14 +2724,14 @@ do -- Players PlayerNames = PlayerNames or {} table.insert( PlayerNames, PlayerName ) HasPlayers = true - end + end end - if HasPlayers == true then + if HasPlayers == true then self:F2( PlayerNames ) return PlayerNames end - + return nil end @@ -2739,35 +2740,35 @@ do -- Players -- @param #GROUP self -- @return #number The amount of players. function GROUP:GetPlayerCount() - + local PlayerCount = 0 - + local Units = self:GetUnits() for UnitID, UnitData in pairs( Units or {} ) do local Unit = UnitData -- Wrapper.Unit#UNIT local PlayerName = Unit:GetPlayerName() if PlayerName and PlayerName ~= "" then PlayerCount = PlayerCount + 1 - end + end end return PlayerCount end - + end --- GROUND - Switch on/off radar emissions for the group. -- @param #GROUP self -- @param #boolean switch If true, emission is enabled. If false, emission is disabled. --- @return #GROUP self +-- @return #GROUP self function GROUP:EnableEmission(switch) self:F2( self.GroupName ) local switch = switch or false - + local DCSUnit = self:GetDCSObject() - + if DCSUnit then - + DCSUnit:enableEmission(switch) end @@ -2778,7 +2779,7 @@ end --- Switch on/off invisible flag for the group. -- @param #GROUP self -- @param #boolean switch If true, Invisible is enabled. If false, Invisible is disabled. --- @return #GROUP self +-- @return #GROUP self function GROUP:SetCommandInvisible(switch) return self:CommandSetInvisible(switch) end @@ -2786,7 +2787,7 @@ end --- Switch on/off invisible flag for the group. -- @param #GROUP self -- @param #boolean switch If true, Invisible is enabled. If false, Invisible is disabled. --- @return #GROUP self +-- @return #GROUP self function GROUP:CommandSetInvisible(switch) self:F2( self.GroupName ) if switch==nil then @@ -2800,7 +2801,7 @@ end --- Switch on/off immortal flag for the group. -- @param #GROUP self -- @param #boolean switch If true, Immortal is enabled. If false, Immortal is disabled. --- @return #GROUP self +-- @return #GROUP self function GROUP:SetCommandImmortal(switch) return self:CommandSetImmortal(switch) end @@ -2808,7 +2809,7 @@ end --- Switch on/off immortal flag for the group. -- @param #GROUP self -- @param #boolean switch If true, Immortal is enabled. If false, Immortal is disabled. --- @return #GROUP self +-- @return #GROUP self function GROUP:CommandSetImmortal(switch) self:F2( self.GroupName ) if switch==nil then @@ -2855,17 +2856,17 @@ function GROUP:GetHighestThreat() if tl>maxtl then maxtl=tl threat=unit - end + end end end - return threat, maxtl + return threat, maxtl end return nil, nil end ---- Get TTS friendly, optionally customized callsign mainly for **player groups**. A customized callsign is taken from the #GROUP name, after an optional '#' sign, e.g. "Aerial 1-1#Ghostrider" resulting in "Ghostrider 9", or, +--- Get TTS friendly, optionally customized callsign mainly for **player groups**. A customized callsign is taken from the #GROUP name, after an optional '#' sign, e.g. "Aerial 1-1#Ghostrider" resulting in "Ghostrider 9", or, -- if that isn't available, from the playername, as set in the mission editor main screen under Logbook, after an optional '|' sign (actually, more of a personal call sign), e.g. "Apple|Moose" results in "Moose 9 1". Options see below. -- @param #GROUP self -- @param #boolean ShortCallsign Return a shortened customized callsign, i.e. "Ghostrider 9" and not "Ghostrider 9 1" @@ -2877,7 +2878,7 @@ end -- -- suppose there are three groups with one (client) unit each: -- -- Slot 1 -- with mission editor callsign Enfield-1 -- -- Slot 2 # Apollo 403 -- with mission editor callsign Enfield-2 --- -- Slot 3 | Apollo -- with mission editor callsign Enfield-3 +-- -- Slot 3 | Apollo -- with mission editor callsign Enfield-3 -- -- Slot 4 | Apollo -- with mission editor callsign Devil-4 -- -- and suppose these Custom CAP Flight Callsigns for use with TTS are set -- mygroup:GetCustomCallSign(true,false,{ @@ -2939,7 +2940,7 @@ function GROUP:GetCustomCallSign(ShortCallsign,Keepnumber,CallsignTranslations) end return callsign end - + -- AI or not personalized if ShortCallsign then callsign = callsignroot.." "..callnumbermajor -- Uzi/Victory 9 @@ -2949,7 +2950,7 @@ function GROUP:GetCustomCallSign(ShortCallsign,Keepnumber,CallsignTranslations) --self:I("Generated Callsign = " .. callsign) end - + return callsign end @@ -2963,21 +2964,21 @@ end -- @param #number LastWaypoint (optional) Waypoint number of carrier group that when reached, ends the recovery tanker task. -- @return #GROUP self function GROUP:SetAsRecoveryTanker(CarrierGroup,Speed,ToKIAS,Altitude,Delay,LastWaypoint) - + local speed = ToKIAS == true and UTILS.KnotsToAltKIAS(Speed,Altitude) or Speed speed = UTILS.KnotsToMps(speed) - + local alt = UTILS.FeetToMeters(Altitude) local delay = Delay or 1 - + local task = self:TaskRecoveryTanker(CarrierGroup,speed,alt,LastWaypoint) self:SetTask(task,delay) - + local tankertask = self:EnRouteTaskTanker() self:PushTask(tankertask,delay+2) - - return self + + return self end --- Get a list of Link16 S/TN data from a GROUP. Can (as of Nov 2023) be obtained from F-18, F-16, F-15E (not the user flyable one) and A-10C-II groups. @@ -3040,8 +3041,8 @@ function GROUP:IsAAA() local desc = unit:GetDesc() or {} local attr = desc.attributes or {} if unit:HasSEAD() then return false end - if attr["AAA"] or attr["SAM related"] then - issam = true + if attr["AAA"] or attr["SAM related"] then + issam = true end end return issam