From 133910ac3b642ce131a4a57f3b0ed33c9e424992 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Fri, 30 Jun 2017 10:27:44 +0200 Subject: [PATCH] New revised CLEANUP class --- Moose Development/Moose/Core/Base.lua | 4 - Moose Development/Moose/Core/Database.lua | 5 + Moose Development/Moose/Core/Point.lua | 8 + .../Moose/Functional/CleanUp.lua | 248 +++++----- Moose Development/Moose/Wrapper/Airbase.lua | 8 + docs/Documentation/AI_A2A.html | 1 + docs/Documentation/Airbase.html | 24 + docs/Documentation/Base.html | 4 - docs/Documentation/Cargo.html | 1 + docs/Documentation/CleanUp.html | 462 +----------------- docs/Documentation/Designate.html | 1 + docs/Documentation/Detection.html | 4 +- docs/Documentation/Mission.html | 126 ++++- docs/Documentation/Movement.html | 4 - docs/Documentation/Point.html | 24 + docs/Documentation/Scoring.html | 52 ++ docs/Documentation/Spawn.html | 12 +- docs/Documentation/SpawnStatic.html | 1 - docs/Documentation/Spot.html | 4 - docs/Documentation/Task.html | 29 +- docs/Documentation/Task_A2A.html | 38 ++ docs/Documentation/Task_A2G.html | 38 ++ docs/Documentation/Task_Cargo.html | 3 +- docs/Presentations/CLEANUP/Dia1.JPG | Bin 0 -> 229956 bytes 24 files changed, 524 insertions(+), 577 deletions(-) create mode 100644 docs/Presentations/CLEANUP/Dia1.JPG diff --git a/Moose Development/Moose/Core/Base.lua b/Moose Development/Moose/Core/Base.lua index e06eaf308..a40e4d729 100644 --- a/Moose Development/Moose/Core/Base.lua +++ b/Moose Development/Moose/Core/Base.lua @@ -4,10 +4,6 @@ -- -- === -- --- The @{#BASE} class is the core root class from where every other class in moose is derived. --- --- === --- -- ### Author: **Sven Van de Velde (FlightControl)** -- ### Contributions: -- diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index 788aa2c00..b4a9319b9 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -375,7 +375,12 @@ function DATABASE:Spawn( SpawnTemplate ) SpawnTemplate.CountryID = SpawnCountryID SpawnTemplate.CategoryID = SpawnCategoryID + -- Ensure that for the spawned group and its units, there are GROUP and UNIT objects created in the DATABASE. local SpawnGroup = self:AddGroup( SpawnTemplate.name ) + for UnitID, UnitData in pairs( SpawnTemplate.units ) do + self:AddUnit( UnitData.name ) + end + return SpawnGroup end diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index b3796752d..bb36cabe8 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -279,6 +279,14 @@ do -- COORDINATE return RandomVec3 end + + --- Return the height of the land at the coordinate. + -- @param #COORDINATE self + -- @return #number + function COORDINATE:GetLandHeight() + local Vec2 = { x = self.x, y = self.z } + return land.getHeight( Vec2 ) + end function COORDINATE:SetHeading( Heading ) diff --git a/Moose Development/Moose/Functional/CleanUp.lua b/Moose Development/Moose/Functional/CleanUp.lua index 79aa2dc6b..e7eef2813 100644 --- a/Moose Development/Moose/Functional/CleanUp.lua +++ b/Moose Development/Moose/Functional/CleanUp.lua @@ -1,56 +1,99 @@ --- **Functional** -- The CLEANUP class keeps an area clean of crashing or colliding airplanes. It also prevents airplanes from firing within this area. -- +-- ![Banner Image](..\Presentations\CLEANUP\Dia1.JPG) +-- +-- === +-- +-- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Contributions: +-- -- ==== +-- -- @module CleanUp - - - - - ---- The CLEANUP class. --- @type CLEANUP +--- @type CLEANUP -- @extends Core.Base#BASE +-- @field #map<#string,Wrapper.Airbase#AIRBASE> Airbases Map of Airbases. + +--- # CLEANUP, extends @{Base#BASE} +-- +-- The CLEANUP class keeps airbases clean, and tries to guarantee continuous airbase operations, even under combat. +-- +-- @field CLEANUP CLEANUP = { ClassName = "CLEANUP", - ZoneNames = {}, - TimeInterval = 300, + TimeInterval = 0.2, CleanUpList = {}, + Airbases = {}, } --- Creates the main object which is handling the cleaning of the debris within the given Zone Names. -- @param #CLEANUP self --- @param #table ZoneNames Is a table of zone names where the debris should be cleaned. Also a single string can be passed with one zone name. --- @param #number TimeInterval The interval in seconds when the clean activity takes place. The default is 300 seconds, thus every 5 minutes. +-- @param #list<#string> AirbaseNames Is a table of airbase names where the debris should be cleaned. Also a single string can be passed with one airbase name. -- @return #CLEANUP -- @usage -- -- Clean these Zones. --- CleanUpAirports = CLEANUP:New( { 'CLEAN Tbilisi', 'CLEAN Kutaisi' }, 150 ) +-- CleanUpAirports = CLEANUP:New( { AIRBASE.Caucasus.Tbilisi, AIRBASE.Caucasus.Kutaisi ) -- or --- CleanUpTbilisi = CLEANUP:New( 'CLEAN Tbilisi', 150 ) --- CleanUpKutaisi = CLEANUP:New( 'CLEAN Kutaisi', 600 ) -function CLEANUP:New( ZoneNames, TimeInterval ) +-- CleanUpTbilisi = CLEANUP:New( AIRBASE.Caucasus.Tbilisi ) +-- CleanUpKutaisi = CLEANUP:New( AIRBASE.Caucasus.Kutaisi ) +function CLEANUP:New( AirbaseNames ) local self = BASE:Inherit( self, BASE:New() ) -- #CLEANUP - self:F( { ZoneNames, TimeInterval } ) + self:F( { AirbaseNames } ) - if type( ZoneNames ) == 'table' then - self.ZoneNames = ZoneNames + if type( AirbaseNames ) == 'table' then + for AirbaseID, AirbaseName in pairs( AirbaseNames ) do + self:AddAirbase( AirbaseName ) + end else - self.ZoneNames = { ZoneNames } - end - if TimeInterval then - self.TimeInterval = TimeInterval + local AirbaseName = AirbaseNames + self:AddAirbase( AirbaseName ) end self:HandleEvent( EVENTS.Birth ) - self.CleanUpScheduler = SCHEDULER:New( self, self._CleanUpScheduler, {}, 1, TimeInterval ) + self.CleanUpScheduler = SCHEDULER:New( self, self._CleanUpScheduler, {}, 1, self.TimeInterval ) return self end +--- Adds an airbase to the airbase validation list. +-- @param #CLEANUP self +-- @param #string AirbaseName +-- @return #CLEANUP +function CLEANUP:AddAirbase( AirbaseName ) + self.Airbases[AirbaseName] = AIRBASE:FindByName( AirbaseName ) + self:F({"Airbase:", AirbaseName, self.Airbases[AirbaseName]:GetDesc()}) + + return self +end + +--- Removes an airbase from the airbase validation list. +-- @param #CLEANUP self +-- @param #string AirbaseName +-- @return #CLEANUP +function CLEANUP:RemoveAirbase( AirbaseName ) + self.Airbases[AirbaseName] = nil + return self +end + + + +function CLEANUP:IsInAirbase( Vec2 ) + + local InAirbase = false + for AirbaseName, Airbase in pairs( self.Airbases ) do + local Airbase = Airbase -- Wrapper.Airbase#AIRBASE + if Airbase:GetZone():IsVec2InZone( Vec2 ) then + InAirbase = true + break; + end + end + + return InAirbase +end --- Destroys a group from the simulator, but checks first if it is still existing! -- @param #CLEANUP self @@ -65,29 +108,25 @@ function CLEANUP:_DestroyGroup( GroupObject, CleanUpGroupName ) end end ---- Destroys a @{DCSWrapper.Unit#Unit} from the simulator, but checks first if it is still existing! +--- Destroys a @{Unit} from the simulator, but checks first if it is still existing! -- @param #CLEANUP self --- @param Dcs.DCSWrapper.Unit#Unit CleanUpUnit The object to be destroyed. --- @param #string CleanUpUnitName The Unit name ... -function CLEANUP:_DestroyUnit( CleanUpUnit, CleanUpUnitName ) - self:F( { CleanUpUnit, CleanUpUnitName } ) +-- @param Wrapper.Unit#UNIT CleanUpUnit The object to be destroyed. +function CLEANUP:_DestroyUnit( CleanUpUnit ) + self:F( { CleanUpUnit } ) if CleanUpUnit then - local CleanUpGroup = Unit.getGroup(CleanUpUnit) + local CleanUpUnitName = CleanUpUnit:GetName() + local CleanUpGroup = CleanUpUnit:GetGroup() -- TODO Client bug in 1.5.3 - if CleanUpGroup and CleanUpGroup:isExist() then - local CleanUpGroupUnits = CleanUpGroup:getUnits() + if CleanUpGroup:IsAlive() then + local CleanUpGroupUnits = CleanUpGroup:GetUnits() if #CleanUpGroupUnits == 1 then - local CleanUpGroupName = CleanUpGroup:getName() - --self:CreateEventCrash( timer.getTime(), CleanUpUnit ) - CleanUpGroup:destroy() - self:T( { "Destroyed Group:", CleanUpGroupName } ) + local CleanUpGroupName = CleanUpGroup:GetName() + CleanUpGroup:Destroy() else - CleanUpUnit:destroy() - self:T( { "Destroyed Unit:", CleanUpUnitName } ) + CleanUpUnit:Destroy() end - self.CleanUpList[CleanUpUnitName] = nil -- Cleaning from the list - CleanUpUnit = nil + self.CleanUpList[CleanUpUnitName] = nil end end end @@ -107,7 +146,7 @@ end --- @param #CLEANUP self -- @param Core.Event#EVENTDATA EventData -function CLEANUP:_OnEventBirth( EventData ) +function CLEANUP:OnEventBirth( EventData ) self:F( { EventData } ) self.CleanUpList[EventData.IniDCSUnitName] = {} @@ -116,13 +155,13 @@ function CLEANUP:_OnEventBirth( EventData ) self.CleanUpList[EventData.IniDCSUnitName].CleanUpGroupName = EventData.IniDCSGroupName self.CleanUpList[EventData.IniDCSUnitName].CleanUpUnitName = EventData.IniDCSUnitName - EventData.IniUnit:HandleEvent( EVENTS.EngineShutdown , self._EventAddForCleanUp ) - EventData.IniUnit:HandleEvent( EVENTS.EngineStartup, self._EventAddForCleanUp ) - EventData.IniUnit:HandleEvent( EVENTS.Hit, self._EventAddForCleanUp ) - EventData.IniUnit:HandleEvent( EVENTS.PilotDead, self._EventCrash ) - EventData.IniUnit:HandleEvent( EVENTS.Dead, self._EventCrash ) - EventData.IniUnit:HandleEvent( EVENTS.Crash, self._EventCrash ) - EventData.IniUnit:HandleEvent( EVENTS.Shot, self._EventShot ) + self:HandleEvent( EVENTS.EngineShutdown , self._EventAddForCleanUp ) + self:HandleEvent( EVENTS.EngineStartup, self._EventAddForCleanUp ) + self:HandleEvent( EVENTS.Hit, self._EventAddForCleanUp ) + self:HandleEvent( EVENTS.PilotDead, self.OnEventCrash ) + self:HandleEvent( EVENTS.Dead, self.OnEventCrash ) + self:HandleEvent( EVENTS.Crash, self.OnEventCrash ) + self:HandleEvent( EVENTS.Shot, self.OnEventShot ) end @@ -130,7 +169,7 @@ end -- Crashed units go into a CleanUpList for removal. -- @param #CLEANUP self -- @param Dcs.DCSTypes#Event event -function CLEANUP:_EventCrash( Event ) +function CLEANUP:OnEventCrash( Event ) self:F( { Event } ) --TODO: This stuff is not working due to a DCS bug. Burning units cannot be destroyed. @@ -141,54 +180,53 @@ function CLEANUP:_EventCrash( Event ) -- self:T("after deactivateGroup") -- event.initiator:destroy() - self.CleanUpList[Event.IniDCSUnitName] = {} - self.CleanUpList[Event.IniDCSUnitName].CleanUpUnit = Event.IniDCSUnit - self.CleanUpList[Event.IniDCSUnitName].CleanUpGroup = Event.IniDCSGroup - self.CleanUpList[Event.IniDCSUnitName].CleanUpGroupName = Event.IniDCSGroupName - self.CleanUpList[Event.IniDCSUnitName].CleanUpUnitName = Event.IniDCSUnitName + if Event.IniDCSUnitName then + self.CleanUpList[Event.IniDCSUnitName] = {} + self.CleanUpList[Event.IniDCSUnitName].CleanUpUnit = Event.IniDCSUnit + self.CleanUpList[Event.IniDCSUnitName].CleanUpGroup = Event.IniDCSGroup + self.CleanUpList[Event.IniDCSUnitName].CleanUpGroupName = Event.IniDCSGroupName + self.CleanUpList[Event.IniDCSUnitName].CleanUpUnitName = Event.IniDCSUnitName + end end --- Detects if a unit shoots a missile. --- If this occurs within one of the zones, then the weapon used must be destroyed. +-- If this occurs within one of the airbases, then the weapon used must be destroyed. -- @param #CLEANUP self --- @param Dcs.DCSTypes#Event event -function CLEANUP:_EventShot( Event ) +-- @param Core.Event#EVENTDATA Event +function CLEANUP:OnEventShot( Event ) self:F( { Event } ) - -- Test if the missile was fired within one of the CLEANUP.ZoneNames. - local CurrentLandingZoneID = 0 - CurrentLandingZoneID = routines.IsUnitInZones( Event.IniDCSUnit, self.ZoneNames ) - if ( CurrentLandingZoneID ) then - -- Okay, the missile was fired within the CLEANUP.ZoneNames, destroy the fired weapon. - --_SEADmissile:destroy() - SCHEDULER:New( self, CLEANUP._DestroyMissile, { Event.Weapon }, 0.1 ) + -- Test if the missile was fired within one of the CLEANUP.AirbaseNames. + if self:IsInAirbase( Event.IniUnit:GetVec2() ) then + -- Okay, the missile was fired within the CLEANUP.AirbaseNames, destroy the fired weapon. + self:_DestroyMissile( Event.Weapon ) end end ---- Detects if the Unit has an S_EVENT_HIT within the given ZoneNames. If this is the case, destroy the unit. +--- Detects if the Unit has an S_EVENT_HIT within the given AirbaseNames. If this is the case, destroy the unit. -- @param #CLEANUP self --- @param Dcs.DCSTypes#Event event -function CLEANUP:_EventHitCleanUp( Event ) +-- @param Core.Event#EVENTDATA Event +function CLEANUP:OnEventHit( Event ) self:F( { Event } ) - if Event.IniDCSUnit then - if routines.IsUnitInZones( Event.IniDCSUnit, self.ZoneNames ) ~= nil then + if Event.IniUnit then + if self:IsInAirbase( Event.IniUnit:GetVec2() ) then self:T( { "Life: ", Event.IniDCSUnitName, ' = ', Event.IniDCSUnit:getLife(), "/", Event.IniDCSUnit:getLife0() } ) if Event.IniDCSUnit:getLife() < Event.IniDCSUnit:getLife0() then self:T( "CleanUp: Destroy: " .. Event.IniDCSUnitName ) - SCHEDULER:New( self, CLEANUP._DestroyUnit, { Event.IniDCSUnit }, 0.1 ) + CLEANUP:_DestroyUnit( Event.IniUnit ) end end end - if Event.TgtDCSUnit then - if routines.IsUnitInZones( Event.TgtDCSUnit, self.ZoneNames ) ~= nil then + if Event.TgtUnit then + if self:IsInAirbase( Event.TgtUnit:GetVec2() ) then self:T( { "Life: ", Event.TgtDCSUnitName, ' = ', Event.TgtDCSUnit:getLife(), "/", Event.TgtDCSUnit:getLife0() } ) if Event.TgtDCSUnit:getLife() < Event.TgtDCSUnit:getLife0() then self:T( "CleanUp: Destroy: " .. Event.TgtDCSUnitName ) - SCHEDULER:New( self, CLEANUP._DestroyUnit, { Event.TgtDCSUnit }, 0.1 ) + CLEANUP:_DestroyUnit( Event.TgtUnit ) end end end @@ -210,14 +248,16 @@ function CLEANUP:_AddForCleanUp( CleanUpUnit, CleanUpUnitName ) end ---- Detects if the Unit has an S_EVENT_ENGINE_SHUTDOWN or an S_EVENT_HIT within the given ZoneNames. If this is the case, add the Group to the CLEANUP List. +--- Detects if the Unit has an S_EVENT_ENGINE_SHUTDOWN or an S_EVENT_HIT within the given AirbaseNames. If this is the case, add the Group to the CLEANUP List. -- @param #CLEANUP self --- @param Dcs.DCSTypes#Event event +-- @param Core.Event#EVENTDATA Event function CLEANUP:_EventAddForCleanUp( Event ) + self:F({Event}) + if Event.IniDCSUnit then if self.CleanUpList[Event.IniDCSUnitName] == nil then - if routines.IsUnitInZones( Event.IniDCSUnit, self.ZoneNames ) ~= nil then + if self:IsInAirbase( Event.IniUnit:GetVec2() ) then self:_AddForCleanUp( Event.IniDCSUnit, Event.IniDCSUnitName ) end end @@ -225,7 +265,7 @@ function CLEANUP:_EventAddForCleanUp( Event ) if Event.TgtDCSUnit then if self.CleanUpList[Event.TgtDCSUnitName] == nil then - if routines.IsUnitInZones( Event.TgtDCSUnit, self.ZoneNames ) ~= nil then + if self:IsInAirbase( Event.TgtUnit:GetVec2() ) then self:_AddForCleanUp( Event.TgtDCSUnit, Event.TgtDCSUnitName ) end end @@ -233,64 +273,50 @@ function CLEANUP:_EventAddForCleanUp( Event ) end -local CleanUpSurfaceTypeText = { - "LAND", - "SHALLOW_WATER", - "WATER", - "ROAD", - "RUNWAY" - } --- At the defined time interval, CleanUp the Groups within the CleanUpList. -- @param #CLEANUP self function CLEANUP:_CleanUpScheduler() - self:F( { "CleanUp Scheduler" } ) local CleanUpCount = 0 for CleanUpUnitName, UnitData in pairs( self.CleanUpList ) do CleanUpCount = CleanUpCount + 1 - self:T( { CleanUpUnitName, UnitData } ) - local CleanUpUnit = Unit.getByName(UnitData.CleanUpUnitName) + local CleanUpUnit = UNIT:FindByName( CleanUpUnitName ) + local CleanUpDCSUnit = Unit.getByName( CleanUpUnitName ) local CleanUpGroupName = UnitData.CleanUpGroupName - local CleanUpUnitName = UnitData.CleanUpUnitName + if CleanUpUnit then - self:T( { "CleanUp Scheduler", "Checking:", CleanUpUnitName } ) + if _DATABASE:GetStatusGroup( CleanUpGroupName ) ~= "ReSpawn" then - local CleanUpUnitVec3 = CleanUpUnit:getPoint() - --self:T( CleanUpUnitVec3 ) - local CleanUpUnitVec2 = {} - CleanUpUnitVec2.x = CleanUpUnitVec3.x - CleanUpUnitVec2.y = CleanUpUnitVec3.z - --self:T( CleanUpUnitVec2 ) - local CleanUpSurfaceType = land.getSurfaceType(CleanUpUnitVec2) - --self:T( CleanUpSurfaceType ) - - if CleanUpUnit and CleanUpUnit:getLife() <= CleanUpUnit:getLife0() * 0.95 then - if CleanUpSurfaceType == land.SurfaceType.RUNWAY then - if CleanUpUnit:inAir() then - local CleanUpLandHeight = land.getHeight(CleanUpUnitVec2) - local CleanUpUnitHeight = CleanUpUnitVec3.y - CleanUpLandHeight - self:T( { "CleanUp Scheduler", "Height = " .. CleanUpUnitHeight } ) + + local CleanUpCoordinate = CleanUpUnit:GetCoordinate() + + if CleanUpDCSUnit and CleanUpDCSUnit:getLife() <= CleanUpDCSUnit:getLife0() * 0.95 then + if CleanUpUnit:IsAboveRunway() then + if CleanUpUnit:InAir() then + + local CleanUpLandHeight = CleanUpCoordinate:GetLandHeight() + local CleanUpUnitHeight = CleanUpCoordinate.y - CleanUpLandHeight + if CleanUpUnitHeight < 30 then self:T( { "CleanUp Scheduler", "Destroy " .. CleanUpUnitName .. " because below safe height and damaged." } ) - self:_DestroyUnit(CleanUpUnit, CleanUpUnitName) + self:_DestroyUnit( CleanUpUnit ) end else self:T( { "CleanUp Scheduler", "Destroy " .. CleanUpUnitName .. " because on runway and damaged." } ) - self:_DestroyUnit(CleanUpUnit, CleanUpUnitName) + self:_DestroyUnit(CleanUpUnit ) end end end -- Clean Units which are waiting for a very long time in the CleanUpZone. if CleanUpUnit then - local CleanUpUnitVelocity = CleanUpUnit:getVelocity() - local CleanUpUnitVelocityTotal = math.abs(CleanUpUnitVelocity.x) + math.abs(CleanUpUnitVelocity.y) + math.abs(CleanUpUnitVelocity.z) - if CleanUpUnitVelocityTotal < 1 then + local CleanUpUnitVelocity = CleanUpUnit:GetVelocityKMH() + if CleanUpUnitVelocity < 1 then if UnitData.CleanUpMoved then if UnitData.CleanUpTime + 180 <= timer.getTime() then self:T( { "CleanUp Scheduler", "Destroy due to not moving anymore " .. CleanUpUnitName } ) - self:_DestroyUnit(CleanUpUnit, CleanUpUnitName) + self:_DestroyUnit( CleanUpUnit ) end end else @@ -301,11 +327,11 @@ function CLEANUP:_CleanUpScheduler() else -- Do nothing ... - self.CleanUpList[CleanUpUnitName] = nil -- Not anymore in the DCSRTE + self.CleanUpList[CleanUpUnitName] = nil end else self:T( "CleanUp: Group " .. CleanUpUnitName .. " cannot be found in DCS RTE, removing ..." ) - self.CleanUpList[CleanUpUnitName] = nil -- Not anymore in the DCSRTE + self.CleanUpList[CleanUpUnitName] = nil end end self:T(CleanUpCount) diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua index 58b0010b3..fab9998b3 100644 --- a/Moose Development/Moose/Wrapper/Airbase.lua +++ b/Moose Development/Moose/Wrapper/Airbase.lua @@ -149,6 +149,7 @@ function AIRBASE:Register( AirbaseName ) local self = BASE:Inherit( self, POSITIONABLE:New( AirbaseName ) ) self.AirbaseName = AirbaseName + self.AirbaseZone = ZONE_RADIUS:New( AirbaseName, self:GetVec2(), 8000 ) return self end @@ -185,5 +186,12 @@ function AIRBASE:GetDCSObject() return nil end +--- Get the airbase zone. +-- @param #AIRBASE self +-- @return Core.Zone#ZONE_RADIUS The zone radius of the airbase. +function AIRBASE:GetZone() + return self.AirbaseZone +end + diff --git a/docs/Documentation/AI_A2A.html b/docs/Documentation/AI_A2A.html index ee2dc9007..2a24504d1 100644 --- a/docs/Documentation/AI_A2A.html +++ b/docs/Documentation/AI_A2A.html @@ -575,6 +575,7 @@
+ #number AI_A2A.IdleCount diff --git a/docs/Documentation/Airbase.html b/docs/Documentation/Airbase.html index 47a104aa6..d176bb9fc 100644 --- a/docs/Documentation/Airbase.html +++ b/docs/Documentation/Airbase.html @@ -157,6 +157,12 @@ AIRBASE:GetDCSObject() + + + + AIRBASE:GetZone() + +

Get the airbase zone.

@@ -317,6 +323,24 @@ self

+ +
+
+
+ + +AIRBASE:GetZone() + +
+
+ +

Get the airbase zone.

+ +

Return value

+ +

Core.Zone#ZONE_RADIUS: +The zone radius of the airbase.

+
diff --git a/docs/Documentation/Base.html b/docs/Documentation/Base.html index b3ba6c7bc..5d0f76673 100644 --- a/docs/Documentation/Base.html +++ b/docs/Documentation/Base.html @@ -114,10 +114,6 @@
-

The #BASE class is the core root class from where every other class in moose is derived.

- -
-

Author: Sven Van de Velde (FlightControl)

Contributions:

diff --git a/docs/Documentation/Cargo.html b/docs/Documentation/Cargo.html index d774a472f..e3fae231c 100644 --- a/docs/Documentation/Cargo.html +++ b/docs/Documentation/Cargo.html @@ -2934,6 +2934,7 @@ The range till cargo will board.

+ CARGO_UNIT.CargoCarrier diff --git a/docs/Documentation/CleanUp.html b/docs/Documentation/CleanUp.html index 3433cec11..73f6287e3 100644 --- a/docs/Documentation/CleanUp.html +++ b/docs/Documentation/CleanUp.html @@ -110,13 +110,24 @@

It also prevents airplanes from firing within this area.

+

Banner Image

+
+

Author: Sven Van de Velde (FlightControl)

+

Contributions:

+ +
+ +

Global(s)

@@ -124,99 +135,15 @@

Type CLEANUP

CLEANUP +

CLEANUP, extends Base#BASE

+ +

The CLEANUP class keeps airbases clean, and tries to guarantee continuous airbase operations, even under combat.

- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CLEANUP.ClassNameCLEANUP.< - -
CLEANUP.CleanUpList - +

string,Wrapper.Airbase#AIRBASE> Airbases Map of Airbases.

CLEANUP.CleanUpScheduler -
CLEANUP:New(ZoneNames, TimeInterval) -

Creates the main object which is handling the cleaning of the debris within the given Zone Names.

-
CLEANUP.TimeInterval - -
CLEANUP.ZoneNames - -
CLEANUP:_AddForCleanUp(CleanUpUnit, CleanUpUnitName) -

Add the DCSWrapper.Unit#Unit to the CleanUpList for CleanUp.

-
CLEANUP:_CleanUpScheduler() -

At the defined time interval, CleanUp the Groups within the CleanUpList.

-
CLEANUP:_DestroyGroup(GroupObject, CleanUpGroupName) -

Destroys a group from the simulator, but checks first if it is still existing!

-
CLEANUP:_DestroyMissile(MissileObject) - -
CLEANUP:_DestroyUnit(CleanUpUnit, CleanUpUnitName) -

Destroys a DCSWrapper.Unit#Unit from the simulator, but checks first if it is still existing!

-
CLEANUP:_EventAddForCleanUp(event, Event) -

Detects if the Unit has an SEVENTENGINESHUTDOWN or an SEVENT_HIT within the given ZoneNames.

-
CLEANUP:_EventCrash(event, Event) -

Detects if a crash event occurs.

-
CLEANUP:_EventHitCleanUp(event, Event) -

Detects if the Unit has an SEVENTHIT within the given ZoneNames.

-
CLEANUP:_EventShot(event, Event) -

Detects if a unit shoots a missile.

-
CLEANUP:_OnEventBirth(EventData) -
@@ -225,13 +152,16 @@
- #CLEANUP + CLEANUP
+

CLEANUP, extends Base#BASE

+ +

The CLEANUP class keeps airbases clean, and tries to guarantee continuous airbase operations, even under combat.

@@ -239,35 +169,18 @@

Type CleanUp

Type CLEANUP

- -

The CLEANUP class.

- -

Field(s)

+

Field(s)

- #string - -CLEANUP.ClassName + #map + +CLEANUP.<
- - -
-
-
-
- - - -CLEANUP.CleanUpList - -
-
- - +

string,Wrapper.Airbase#AIRBASE> Airbases Map of Airbases.

@@ -283,336 +196,13 @@ - -
-
-
- - -CLEANUP:New(ZoneNames, TimeInterval) - -
-
- -

Creates the main object which is handling the cleaning of the debris within the given Zone Names.

- -

Parameters

-
    -
  • - -

    #table ZoneNames : -Is a table of zone names where the debris should be cleaned. Also a single string can be passed with one zone name.

    - -
  • -
  • - -

    #number TimeInterval : -The interval in seconds when the clean activity takes place. The default is 300 seconds, thus every 5 minutes.

    - -
  • -
-

Return value

- -

#CLEANUP:

- - -

Usage:

-
 -- Clean these Zones.
-CleanUpAirports = CLEANUP:New( { 'CLEAN Tbilisi', 'CLEAN Kutaisi' }, 150 )
-or
-CleanUpTbilisi = CLEANUP:New( 'CLEAN Tbilisi', 150 )
-CleanUpKutaisi = CLEANUP:New( 'CLEAN Kutaisi', 600 )
- -
-
-
-
- - - -CLEANUP.TimeInterval - -
-
- - - -
-
-
-
- - - -CLEANUP.ZoneNames - -
-
- - - -
-
-
-
- - -CLEANUP:_AddForCleanUp(CleanUpUnit, CleanUpUnitName) - -
-
- -

Add the DCSWrapper.Unit#Unit to the CleanUpList for CleanUp.

- -

Parameters

-
    -
  • - -

    CleanUpUnit :

    - -
  • -
  • - -

    CleanUpUnitName :

    - -
  • -
-
-
-
-
- - -CLEANUP:_CleanUpScheduler() - -
-
- -

At the defined time interval, CleanUp the Groups within the CleanUpList.

- -
-
-
-
- - -CLEANUP:_DestroyGroup(GroupObject, CleanUpGroupName) - -
-
- -

Destroys a group from the simulator, but checks first if it is still existing!

- -

Parameters

-
    -
  • - -

    Dcs.DCSWrapper.Group#Group GroupObject : -The object to be destroyed.

    - -
  • -
  • - -

    #string CleanUpGroupName : -The groupname...

    - -
  • -
-
-
-
-
- - -CLEANUP:_DestroyMissile(MissileObject) - -
-
- - - - -

TODO check Dcs.DCSTypes#Weapon -- Destroys a missile from the simulator, but checks first if it is still existing! - @param #CLEANUP self - @param Dcs.DCSTypes#Weapon MissileObject

- -

Parameter

-
    -
  • - -

    MissileObject :

    - -
  • -
-
-
-
-
- - -CLEANUP:_DestroyUnit(CleanUpUnit, CleanUpUnitName) - -
-
- -

Destroys a DCSWrapper.Unit#Unit from the simulator, but checks first if it is still existing!

- -

Parameters

-
    -
  • - -

    Dcs.DCSWrapper.Unit#Unit CleanUpUnit : -The object to be destroyed.

    - -
  • -
  • - -

    #string CleanUpUnitName : -The Unit name ...

    - -
  • -
-
-
-
-
- - -CLEANUP:_EventAddForCleanUp(event, Event) - -
-
- -

Detects if the Unit has an SEVENTENGINESHUTDOWN or an SEVENT_HIT within the given ZoneNames.

- - -

If this is the case, add the Group to the CLEANUP List.

- -

Parameters

- -
-
-
-
- - -CLEANUP:_EventCrash(event, Event) - -
-
- -

Detects if a crash event occurs.

- - -

Crashed units go into a CleanUpList for removal.

- -

Parameters

- -
-
-
-
- - -CLEANUP:_EventHitCleanUp(event, Event) - -
-
- -

Detects if the Unit has an SEVENTHIT within the given ZoneNames.

- - -

If this is the case, destroy the unit.

- -

Parameters

- -
-
-
-
- - -CLEANUP:_EventShot(event, Event) - -
-
- -

Detects if a unit shoots a missile.

- - -

If this occurs within one of the zones, then the weapon used must be destroyed.

- -

Parameters

- -
-
-
-
- - -CLEANUP:_OnEventBirth(EventData) - -
-
- - - -

Parameter

-
+

Type list

+ +

Type map

+ diff --git a/docs/Documentation/Designate.html b/docs/Documentation/Designate.html index c0c7ee573..70e3562df 100644 --- a/docs/Documentation/Designate.html +++ b/docs/Documentation/Designate.html @@ -900,6 +900,7 @@ function below will use the range 1-7 just in case

+ DESIGNATE.LaserCodes diff --git a/docs/Documentation/Detection.html b/docs/Documentation/Detection.html index 141b7d951..d18ec397a 100644 --- a/docs/Documentation/Detection.html +++ b/docs/Documentation/Detection.html @@ -2393,7 +2393,6 @@ The index of the DetectedItem.

- #number DETECTION_BASE.DetectedItemCount @@ -2407,7 +2406,6 @@ The index of the DetectedItem.

- #number DETECTION_BASE.DetectedItemMax @@ -2565,7 +2563,7 @@ The index of the DetectedItem.

- #number + DETECTION_BASE.DetectionInterval diff --git a/docs/Documentation/Mission.html b/docs/Documentation/Mission.html index 84ce45974..d34e8e4e1 100644 --- a/docs/Documentation/Mission.html +++ b/docs/Documentation/Mission.html @@ -133,6 +133,12 @@ MISSION:AbortUnit(PlayerUnit)

Aborts a PlayerUnit from the Mission.

+ + + + MISSION:AddPlayerName(PlayerName) + + @@ -211,6 +217,12 @@ MISSION:GetNextTaskID(Task)

Return the next Task ID to be completed within the Mission.

+ + + + MISSION:GetPlayerNames() + + @@ -294,13 +306,19 @@ MISSION:MenuReportBriefing(ReportGroup) - +

Reports the briefing.

MISSION:MenuReportPlayersPerTask(ReportGroup) + + + + MISSION:MenuReportPlayersProgress(ReportGroup) + + @@ -312,7 +330,7 @@ MISSION:MenuReportTasksSummary(ReportGroup) - +

Report the task summary.

@@ -499,6 +517,12 @@ MISSION:ReportPlayersPerTask(ReportGroup)

Create an active player report of the Mission.

+ + + + MISSION:ReportPlayersProgress(ReportGroup) + +

Create an Mission Progress report of the Mission.

@@ -644,6 +668,27 @@ The CLIENT or UNIT of the Player joining the Mission.

+ +MISSION:AddPlayerName(PlayerName) + +
+
+ + + +

Parameter

+
    +
  • + +

    PlayerName :

    + +
  • +
+
+
+
+
+ MISSION:AddScoring(Scoring) @@ -915,6 +960,19 @@ is the Task object.

Tasking.Task#TASK: The task added.

+ +
+
+
+ + +MISSION:GetPlayerNames() + +
+
+ + +
@@ -1242,13 +1300,14 @@ true if Unit is part of a Task in the Mission.

- +

Reports the briefing.

Parameter

  • -

    ReportGroup :

    +

    Wrapper.Group#GROUP ReportGroup : +The group to which the report needs to be sent.

@@ -1265,6 +1324,27 @@ true if Unit is part of a Task in the Mission.

+

Parameter

+ +
+
+
+
+ + +MISSION:MenuReportPlayersProgress(ReportGroup) + +
+
+ + +

Parameter

  • @@ -1311,7 +1391,7 @@ The status

- +

Report the task summary.

Parameter

    @@ -2283,6 +2363,42 @@ self

    #string:

    +
+
+
+
+ + +MISSION:ReportPlayersProgress(ReportGroup) + +
+
+ +

Create an Mission Progress report of the Mission.

+ + +

This reports provides a one liner per player of the mission achievements per task.

+ +
Mission "<MissionName>" - <MissionStatus> - Active Players Report
+ - Player <PlayerName>: Task <TaskName> <TaskStatus>: <Progress>
+ - Player <PlayerName>: Task <TaskName> <TaskStatus>: <Progress>
+ - ..
+
+ + +

Parameter

+
    +
  • + +

    ReportGroup :

    + +
  • +
+

Return value

+ +

#string:

+ +
diff --git a/docs/Documentation/Movement.html b/docs/Documentation/Movement.html index be5ce073c..4307c3aaa 100644 --- a/docs/Documentation/Movement.html +++ b/docs/Documentation/Movement.html @@ -227,7 +227,6 @@ on defined intervals (currently every minute).

- #number MOVEMENT.AliveUnits @@ -236,9 +235,6 @@ on defined intervals (currently every minute).

- -

Contains the counter how many units are currently alive

-
diff --git a/docs/Documentation/Point.html b/docs/Documentation/Point.html index f204d56d9..ba2001e76 100644 --- a/docs/Documentation/Point.html +++ b/docs/Documentation/Point.html @@ -267,6 +267,12 @@ COORDINATE:GetDistanceText(Distance, Settings)

Provides a distance text expressed in the units of measurement.

+ + + + COORDINATE:GetLandHeight() + +

Return the height of the land at the coordinate.

@@ -1498,6 +1504,24 @@ The distance in meters.

#string: The distance text expressed in the units of measurement.

+ +
+
+
+ + +COORDINATE:GetLandHeight() + +
+
+ +

Return the height of the land at the coordinate.

+ +

Return value

+ +

#number:

+ +
diff --git a/docs/Documentation/Scoring.html b/docs/Documentation/Scoring.html index 1bf9e8bd7..3bf1d6c90 100644 --- a/docs/Documentation/Scoring.html +++ b/docs/Documentation/Scoring.html @@ -414,6 +414,12 @@ Various methods exist to configure:

SCORING.CoalitionChangePenalty + + + + SCORING.DisplayMessagePrefix + + @@ -642,6 +648,12 @@ Various methods exist to configure:

SCORING:SetCoalitionChangePenalty(CoalitionChangePenalty)

When a player changes the coalition, he can receive a penalty score.

+ + + + SCORING:SetDisplayMessagePrefix(DisplayMessagePrefix) + +

Set a prefix string that will be displayed at each scoring message sent.

@@ -1038,6 +1050,19 @@ The Score value.

+ +
+
+
+ + +SCORING.DisplayMessagePrefix + +
+
+ + +
@@ -1889,6 +1914,33 @@ The amount of penalty that is given.

#SCORING:

+ +
+
+
+ + +SCORING:SetDisplayMessagePrefix(DisplayMessagePrefix) + +
+
+ +

Set a prefix string that will be displayed at each scoring message sent.

+ +

Parameter

+
    +
  • + +

    #string DisplayMessagePrefix : +(Default="Scoring: ") The scoring prefix string.

    + +
  • +
+

Return value

+ +

#SCORING:

+ +
diff --git a/docs/Documentation/Spawn.html b/docs/Documentation/Spawn.html index 6161409ef..0f27003d1 100644 --- a/docs/Documentation/Spawn.html +++ b/docs/Documentation/Spawn.html @@ -2194,6 +2194,9 @@ The group that was spawned. You can use this group for further actions.

+ +

Don't repeat the group from Take-Off till Landing and back Take-Off by ReSpawning.

+
@@ -2743,6 +2746,9 @@ when nothing was spawned.

+ +

By default, no InitLimit

+
@@ -2778,7 +2784,7 @@ when nothing was spawned.

- + #number SPAWN.SpawnMaxGroups @@ -2795,7 +2801,7 @@ when nothing was spawned.

- + #number SPAWN.SpawnMaxUnitsAlive @@ -3123,7 +3129,7 @@ Spawn_BE_KA50 = SPAWN:New( 'BE KA-50@RAMP-Ground Defense' ):Schedule( 600, 0.5 )
- + #boolean SPAWN.SpawnUnControlled diff --git a/docs/Documentation/SpawnStatic.html b/docs/Documentation/SpawnStatic.html index d8aa5e633..bc91b9624 100644 --- a/docs/Documentation/SpawnStatic.html +++ b/docs/Documentation/SpawnStatic.html @@ -436,7 +436,6 @@ ptional) The name of the new static.

- #number SPAWNSTATIC.SpawnIndex diff --git a/docs/Documentation/Spot.html b/docs/Documentation/Spot.html index 5fdc3b305..ead3792db 100644 --- a/docs/Documentation/Spot.html +++ b/docs/Documentation/Spot.html @@ -765,7 +765,6 @@ true if it is lasing

- SPOT.ScheduleID @@ -779,7 +778,6 @@ true if it is lasing

- SPOT.SpotIR @@ -793,7 +791,6 @@ true if it is lasing

- SPOT.SpotLaser @@ -807,7 +804,6 @@ true if it is lasing

- SPOT.Target diff --git a/docs/Documentation/Task.html b/docs/Documentation/Task.html index 1cf449b57..5ea8d8586 100644 --- a/docs/Documentation/Task.html +++ b/docs/Documentation/Task.html @@ -249,6 +249,12 @@ TASK:GetPlayerNames()

Create a list of the players in the Task.

+ + + + TASK:GetPlayerProgress(PlayerName) + + @@ -1329,6 +1335,27 @@ The total number of players in the task.

+ +TASK:GetPlayerProgress(PlayerName) + +
+
+ + + +

Parameter

+
    +
  • + +

    PlayerName :

    + +
  • +
+
+
+
+
+ TASK:GetProcessTemplate(ProcessName) @@ -3037,7 +3064,7 @@ Fsm#FSM_PROCESS

diff --git a/docs/Documentation/Task_A2A.html b/docs/Documentation/Task_A2A.html index 584ef585f..5cc0a0d9d 100644 --- a/docs/Documentation/Task_A2A.html +++ b/docs/Documentation/Task_A2A.html @@ -159,6 +159,12 @@ based on the tasking capabilities defined in Task#TA

Type TASK_A2A

+ + + + + + + + @@ -478,6 +490,19 @@ The task is given a name and a briefing, that is used in the menu structure and
+ +TASK_A2A:GetGoalTotal() + +
+
+ + + +
+
+
+
+ TASK_A2A:GetPlannedMenuText() @@ -671,6 +696,19 @@ If the TargetZone parameter is specified, the player will be routed to the cente

#TASK_A2A: self

+ +
+
+
+ + +TASK_A2A:SetGoalTotal() + +
+
+ + +
diff --git a/docs/Documentation/Task_A2G.html b/docs/Documentation/Task_A2G.html index 6b55b2294..058ae5687 100644 --- a/docs/Documentation/Task_A2G.html +++ b/docs/Documentation/Task_A2G.html @@ -159,6 +159,12 @@ based on the tasking capabilities defined in Task#TA

Type TASK_A2G

TASK_A2A:GetGoalTotal() + +
TASK_A2A:GetPlannedMenuText() @@ -192,6 +198,12 @@ based on the tasking capabilities defined in Task#TA TASK_A2A:New(Mission, SetAttack, TaskName, UnitSetTargets, TargetDistance, TargetZone, TargetSetUnit, TaskType, TaskBriefing)

Instantiates a new TASK_A2A.

+
TASK_A2A:SetGoalTotal() +
+ + + + + + + + @@ -468,6 +480,19 @@ based on detected enemy ground targets.

+ +TASK_A2G:GetGoalTotal() + +
+
+ + + +
+
+
+
+ TASK_A2G:GetPlannedMenuText() @@ -661,6 +686,19 @@ If the TargetZone parameter is specified, the player will be routed to the cente

#TASK_A2G: self

+ +
+
+
+ + +TASK_A2G:SetGoalTotal() + +
+
+ + +
diff --git a/docs/Documentation/Task_Cargo.html b/docs/Documentation/Task_Cargo.html index 8c17ced64..76e219e8b 100644 --- a/docs/Documentation/Task_Cargo.html +++ b/docs/Documentation/Task_Cargo.html @@ -510,7 +510,7 @@ based on the tasking capabilities defined in Task#TA
- + Core.Cargo#CARGO_GROUP FSM_PROCESS.Cargo @@ -524,6 +524,7 @@ based on the tasking capabilities defined in Task#TA
+ FSM_PROCESS.DeployZone diff --git a/docs/Presentations/CLEANUP/Dia1.JPG b/docs/Presentations/CLEANUP/Dia1.JPG new file mode 100644 index 0000000000000000000000000000000000000000..25433557605ab45ecc251578b37c8a2dcd505954 GIT binary patch literal 229956 zcmbTdcQ{;6{6D&~SV4#cAr?va5G9Gu>LJm44}u_Sh_&hpf*@rrtCzJTdMA4HV3#N> zdM6fZ$?7Hg&-dQ@{OZ-T@)8YTCP+Ys}BQ=QTIxXE*gW8*bYZO4>HA>+B^!loG@YQnwB@@-H z`=U>&ZyUY>J%BQcg`vLE@TgREuo(T`<`uX14!=&zdWVhu?tgsz4+R7zB&DQfAhN2@ zo~x;AXlfaon3|beys&g|eC_1y;_3$T@%8f$2!uy`h>VK<_~~Nc6DQMJ-xq%M@GlSCnl$+|11%fS5}E@r1hQMz5Rp3qkqRI z|AUJH0Q^5;{cmLd4_r)FxUNxB0x3cNgNx#t|J4m-qNKVnN`338A?OwK_5-mn8fF#L z*Q$=|JmN;%EcV{NX<2zC{`|M|KhXXUWdHAgh5!FT_P>Gs-?*j$^gxQM$pbP0lmOdw zGWPVAdQUq*<)AX(JC@{TxVPo>^O*KcJ7|J+=)fKrDI4xuXjLeDjey>-Xn?NH{xdaB zdFFmzBjEc-1{+wmaAUfQoxeU*1PgmW7=@ejR!RKLLpu^UO3d}+-C3tNj^DuR-$1(s z9?^bi*{Gh#kJe4l*Upy0^Id0WV`C#sSN>_;+q@-~hCon#Bu0?3@*F#tD7-3PXqYC2 z*iWvzb-q-ZW*zP}rS_f)KH}YZ&8aa3i>Mpj__2q1O z{#cp|hHI5G^Ghp~fMbrQ!pu5wyc5P!Z65IeC$pDjHH5t!ldm+HUl4=yI$txDqho!;id0zr<%G3H#X@4}JVgHWE0drff z#pu2n)HJl}+AHi`Q#69ZM`LKxD0orB84r3YzCWWgBHv&$P*z+RtP=_TY}8R%9(V(* zSv>#ZVryW;6Mna$FQo@^(H1Fb?xgJn_mQ+r`=y{UezTY%$nj+K3ww-d)U0zo+!ST? z2u)9r8Dw0W(a3#|ACg%3pNrNhMXrs5JG)cHifMta(_M?@%r{RpGHbo_X zr=j?nq?2ekG8%KSKadkK)1nW$8_dvk%_f#sLdj0DO1uIb^A7RgrOfz<7m1Q~Egz zfBYY_+k#^7ZH+a-7p}HYR`K?!J*JT|&=wbk15Q577#C#|$d7gg7)vGdA{=HSG^V@c zyc^nW%e0b-uFD~uZW^P|`d!Xqm!Ug^ti3aml;q9b5F2>?ijKv(7mhTMUh|8Q=bkZb z>Q2Orr1ax)nu(Q}%*JKEf?QjF%oHGYuUm<|7eAiG)&s0(zXT{I-l@8+63~GS<#Mrj z-@y(VnYjc^7{A$iN91t3yh}r*r>)G2Vtn8s3 z+~k&e&1R26tWB_BpIQKcy>R&hDtY59(ydO+Wib8r3y=H@$;vo6O4L=-l%l}Cw=4Xav7cq zt^+pfhm!7YSgG6baOdo!LO&#qzfH1i({Aj8Z7Lz%l>0FOHy#PfSGFBTc-qJYjocHh z)q@Ai!Ht!-7LG?!{wv{ZEX4y>E_sG@{^Qn^M@pGm`E%+z8mg z%oWAl5Qa9ujO@tMVsg8|q|~d`te1_BSGS~{b((9F(&rrDx9#$F^Jw#mnFQ}26)xMe zRj6)t(qCzowv81(|%@9VZL3*&Kd(@1PJ#UiYT> zVDSN_u*o>9N|F&)3X{r}R_LttAfBr;;(Wn2&orRdv;!}nr4Rp&3Yf#$HU|r$)5IA5 zZ8Uv;@N8H>iC)n<-E+a7v5=VrYldRxl#-svXZ@^!V6&hNr_lLuky!@WJ?)8^GCoGm zSj%fmVvF%D3OD$M)ieu=!*LjeAfsbdAe6s>J)2rY5XZmnY92@Jt*+%a)Qk*4kNCwj zl9fLm9`v+d0_2VMJ9_`hLiKxiffI%7*~^8T0InK(2M51Dqv_JGqD;X1ONrqPGUu*= zbQA0c2idA2hsu<9LsdXZnS#W6eZ%>bEWK}q86RQD+~1b~VLUhp`Ea9yFJ%Ys?ZO-M zDmA7p^Fg^9pcikm&t;WNEaRWIQRkE$yFV)eCqVgk@{|HD0Wl9btk7`~yq0m)+m+9+ z8o7mL(Dtcwf@;f{t1T-u;F`egN=(gShbAFixggz|bx^Ufh^<8=kiUiV4o?MK2h#}} zPbsJ(?PpWXns|VT>Teewn*l;<{+>cN=HG)`PMKzyi*X4jez`X2x*(&9 zlYYCM_ez4GN@*x2^K>ZaBu?&kSOX?;>&GmYoKxDP@IognRDb&BdyA0ZqEwD(>vLI? z;;$c1XA!V7(jCsQ)B)2gu&$3A=7xF zrSZ?8m`@WGmhiRQ`>*MNK%`V`nZB5WNrs5}JUcstfNYB{lULtkn7gR0KF?U~(xQGc z=@Xhj!Y5SU{yFrNs?dqWkC#_Oj>|{$paz4C ziK-^(ddPEwG`VV$y6_}+6+hp5wqZ$7-_2cT(Ujl8O-Ry`Zi9ps*9aS1+Ui9KU-aha zSEx9Eyo)|0lD^};Z4ri$%wWOgX?IT!TTJSJxl87qRWo`9b$4Z*SL6O$>XWds$6G@TK$tG=t1qXcA)-;E1@L^R`FY zK^U4YtQD6X>Cttzkg_aLMK)Ey>2Pmo;uQwrCaE-{?Z8&ZS@9c76!#6Z-)ih19`-q$ zLeUyDVmxZPIUyk;U0?Y(>NwyPQlI^6>oyxXYZzVDK{|L45jl9B4wHFeG#B;3P5&2Q z|71sP2~LnXIVvD~Do^XTX_>sX_Tfq^d86^Nz>ECX_3O2m##b9?<6Na5M0PwdPqMw& z)T5xS>_J9dr`UBYgXSQ`fSl`VV}#?jY?#KZ6oU$pJ4WumN_`b^+&D^fv-7?zI>-sF zOjuP!!;Mu|0u>9!QI!plo{erf#vZfThK>##kJ2EjdPv&l;gcr0Xr0gcw$@oG?0+Ho z+ApI6v!p0+dWo!DIhTM6!z96}v%nnoLD>`gqz`qK%U*#BvU~rGkEq@%%Px;dk?l<* z@7d06Gl-|V`2EK%er@)|7(dX%j*~wuoPprjNqY1$kj0SJg+Y`C%5hSU2Jo)n>|_+R zQr*Br-q@F99ctKAz62Z?*K;<5<7J2kxs3g3R&LwkoAA*LBtsyPa{p}oM^*}C4tXG* z$^b`A7qWIHHGu8>I79K4W{AK{uVC>t+2L|_%^n~dbG+S(IwgXFti#n+D(m>Jbxz+# ziI&~eV)>S0>*&CrfVp1gYaxbNdnDy(7C?oWOb2oI+cQoI{#v+;F6#0w|94;0JHnyV2P0SLRZwpwN zXjpjz^#1e=-18JiIGinIRDu~6EPV_%=gxoQY{$P?ScMsc>~1P{wlJeLN5f)6FIt!> zx_U|)mKTF)9fu!;Q%n2pU(M6VyG;OCS~Y9CFpKKPM5aS4Vcff$;W{xZE~3XlJc|JB=U_bYATTN3c&&EDyG zbulBkI*gw=Dc5ODYtaicM0&=%eRh1h{M(w&fyzMf4Cds7Y07lS3g$yzR#6A z!F1SNH_G#h)kNftwEV*t-K_Uf(F?zY{xwd$X*^srHV`5 z?>NPMEkE&Jk)Qr<&L2bnJD!beQn3~sCw&CX`V}h|Bv}0(r1iTlO4n%dIR^kb`(9zd z753=Auj!RZpa33{-V3Qp(Mtf$iG!q6ZW(ib+L~7oEq-?L_{ZtKq(<*)&Z^v}dv+Da zOWCu=Mcjiaf~8&iisz&zf4fV7;5QCH#!i@a{R&sjW4~9J$ZKnA#z$%R zrH9jEQU_-r3u;~k{(UY3ziK0NGE>5YlBMeH zK3cI*OFh}JEZER!mh>+#l}iAo1`Bb(9Wz^$%*D*@1^E{FW!bbg77}>tz2O8FVYdzq zP^_m$&Z|9Zc->#%0e6ZP%)w=l*}3ZcA(7I9Q%Tlr`V4&`ZxZ=e*m-s3Y2IrPdjCv- zRbCWAWZ@f$3&6iQ%vLVhV~VFBhNY*x?Ry_&Y-k~U)I@C2D`{#mpw|eo_9*}Zyu{$N zNwE4=8E#8BmZM;0==%a_f`Zo#(NR0<#Y1-DhS@Tr@LcKcr$is} z8nxi>8%&OBKrq$Tv57f-h80AHoxLcn4Tg@G8805FYD?>tborz}D-I~V4nE{7sizlH zI58~}t;d}0m@WvRCU+9X%jMACZ0Z9j5>{UVq4)OyunZl~YKm13$iD>iDeC>s(i-Yl z*7H_6H~Ff^cEouJD1(?#5B}ZBa(m8BjG0ecilbH^kvI8*@rI=%@*#NUgFat*pKPi( z;fz{IA}z;-XRWD=45P&b3Fr$JGp?K&UW!qsu;WqpnEA#c(=dF&USTfwLKDbYc(bI& zTb6q-JzcVc3l|pq>#MbtCSkbjXHEcjz-^tvl4Ro*TwiRNZi6pD@odCY(-YUm!sFmc zLCn{{dnSRjt~`fXfO!!o+~5CM$xSOlc zH8XLRu3Lf%7e!NO;|C(h!%2y-2-NXiKftu;1b<_;-2sQoj=Y3yRs!_R`7@Vu|jO2$v0AMFWqJ4Ka2RCcl zn=*J}hjU}Jy(k9N3966Bm%$;m8kDC6{2Ms9Udt{>i#DNW(T5TVm26}LxgM7xO@g)5|gwfqmn}~6wDjdD1K`nBFQ%N!LJ%i{( ztE)1n=#P;G=v1n+I0u$%=k-A?@|Ub0KZ5-@3b=PS^3kiRrqsGo`~9 zVurS$`)zs8a+9%D`71?(o%z-}3+u@FG}1q_Tt&{LM6?|O*kEV=I-j)ttZ(-k+~eL& zar4#s>$`EEE6>Y9%+|AlV3a+%q|0?|xV!c$FKh$AG6{`TBc%C=? z=~0gp_!7XFU6SC(e6QSS_)O^0snEXCzfHxY`87pQP5kZJv|OyF%<@td`R%(X{!RL; z)+!1mUxyB|%T~OK_2=Y6SO(-WD?h8T;390~u$mc1ufCTT@az^IaNbn=YClt5sc;T^ z*;VzWLNp?d4bG_5)BNdyy`q6~4|Tqn6H*BF>69jnjja-X`=9?op;N8KjN2uE316T! zGs;ilhmZ(pC(l<)OQ$7wY|NxjNx?KU9$4HFWE?p=%(H)OjEce?cWdNowNv(LY?D@l zr&IF9(Mu_Pj_XmWQ-rFG-hn$04%x#7)$VL`3#r$8G6dt?Ok-j3YGYgfMw;6aF=By) z7FL@1E-M&@SiyfXTq$pNZgpZrCQ<@NVpq~tr0I!ZxG}Y41l8&6iSuVOgfl-Kaw<>o z*Ht`pVC;7s&9(-2NH=Rppak~GLrJQ|#~AK zf|4~~T`W1me09-Ffr>KZWj&XGIdom2hzPaaK3fC(sPg`-KZ;#ik8 zbujGMKHRoT8U)4nU&Y$-Z9j9+p8L7&p0oblN>208hO80h&!e`hLBmA<(2S7+f<{-p zf_h;dz>Z8Noj+W=u@C0Oy%{R?_7c(T_-fwwhKz66FTl?9LU^4OyGCPcyUo^f&pIPM z$180faE<;{WAil}PO_-B+nIGZy9CIVN3MNRGq9_GEFMaD&Iew_9n#g_nvWJZl}<+Y zI@oY;3u-C9JK4rb^PC;zzdeqA=Ri4BiUWX$Sx$nk2DT_R_|sjFFA?L(kVJave%TPE z<i(g%rfZZXo{Nc%PAtyBU&BW8~t)EYJZevfRqm4*!97oG3>AZTI)zOPdl+FcZ zTCJ30>QQH^B_hx2hbmrGHOKPzo5%G~U}Zf&M&Qj@GSK$NRugCY(g?>1G0V{80_j10 z8D6g&5|vH>1Thxw_xG@8&9!s@tIs_zzhkB$exoF+{Un4L>ktQ0I0?l(d~8qLyaed~ zOj~`|?u)Y-?MW=7-Kb|( z0*2`Nq2I=y#(1HNwQs2wdwGK*AidQTzqyuf+8HSB4@r+ZNCq!S%>1?qyb&={rYP^| zf5<$S208d@f?y2ET)Wn97Z`6pB-N;NIMj9w`5K_p1d;G%}_d|Fz;?HEJw^u^B?%c*$!c z98c$5hX&qW{7a10|5=GjS{_I7*nMH~XnNEN}FQ#JTnp|Hd?B2q=MUkz(dGQ<2)}GLu9f z$dao1__`n7Fx|WFL7~dbn4Vssq?^=ann~+goJ#QwnryrVQPOJsZ{N)MoSwznv1(nv zaK99rAQ% zkyXGv(DZ};z(%o__l0K!VuzHjibSNWm|h(H!Pi0(JxIq40TOfHAO5idUvNjtasFT+ zPYyf%T3*X8_tp!Ns#kS8%$xdpM^sq(-bb^^CmJJYw zQ$(Bme!Qvo6jTd&BA^=!qP;XIdCvPN7RA?oo&@V#6#!-pn z_T`hMuvtgv0yY@}=0L)^N(L`~_mfwtnD`8&M6e(n#M}k(g0}P237Ym`8CmYuu`w(p zSy+oK(>t7f*2xtt*MkizeJ$dlFTsyg*a)zwQOoWh=E@KeT&=k#QC}Y%unh)aWrK{F zuU!WU%lQ?M7xugtA|DhTrygwLj(48Ind+#ukh-FYp1+Xd!=>mbV#EY#%kVpTn-)2r zBMlry9pCqGkwM?NRo?5(TKE1b5F5Qb;V-R(Vw^=`Twv!=7<01#00NZ4FlphDnk3WtT= zV!|Lu!ol-T>~I_f?w9`VD$1)9R7kpzSfUOj9}ndeY@ZrjLpUH?_Ef42F*$h}ZOt5h z2m8Ri+_xEx`}xM3{;XvFOb8Ba_~uGA{e5P2-ERj__VncS8Gs9xSbA5HGzWF+d!WquE| zMxaNNx1drHh}(Ywt6wu7jcIZ+9$y&-lgK8DS~!!AAE#IIzA<`497X5-i$+0E(ccG0 zF!GRt6O?|T9QfUzI3!?dop=L|pDHkFDV6E;A+x#!n*4T<*RfP04`z0kxq?X{YxL^- z14?YuaC+xFInPxb;j^k$TxB0uAif-ix0EWnVk4M67M({8!FC5Sy}jA8F>xNAGQd&a z{6!DKvB{vn1Mkjw&VM0|%jZy?H%=l~h9_M?gh9XMF&#Le=7<@+d4zT0eHyz38$k-- z@<9bLg0KTN7F+>g7Wx=OklWc@1x%u zd5M$93;j88ygvEqLBNJ(*gi@3O?&_jPNV9#f04+9V?XT4o7NKuoQ4~S(yYlXMP?6^ z1*fo#4$9rrQfPYE&{a-b+nqb@J}|EN5)hXE*rX(+Hs{++A5?&;+~4=05M^jRh+X~S zc?l5kGUsHYc*$nhPapAU=p@)(YD~B01~*j)QNgwT&af2`T(8h@VlMSvL2^^*?(g}) zM+gsc4cf%qGOQuN9uX(=_D{K+$5V9pb)G^_(G9b|&VK8-Y{Goj09*F9jahGIIqU&}GwVLe;ALSp~5~6){G?04FiApazB=(51LTT5lfvA z6dz^TNM9~{v-&BHJe#{mdMWwIXVN@%=jXwIGmnMlJkI#AK%?Oe*q7Vd%y(JQekH?Y zkP-aeZ7lbBhL|JTyEHh+?2Bs|ZvfreQ=a|O8rfT`GHsQ;q8EGyAx93Ds5ODHR=dvk zR{);o=(jikg~kGo-40q1bvxfR-*@KF!>|H-ba6fPzwgJGdrcPyaPA!x+LG_kKM3cW zF2F1d*E`ku@(AMIa)#Q-j)%^C5Pq$0_jGz-=(k_@=sOHY($|>z=k)5d>R>azD(6RN zU0&2?$7$cp{ErRygXEh{^8HyYdd(w7&!@Q|7s4S)^5gL2vGM41{ebV-0FOBlJrN~_ z+8BR&Px0C?%9U8jQ8yd*Bxis9wA&a+&%w#KZr6WK5A|&j>V;b`MV-MZFjRAlN~B@< z?EadV;P{ukmQL=uYUU0ZY)F#dsW!?4|;3qu;L(=a?eAb3tmc=}8c~dhm z6Z5?H#2cS-y(n|dpRIWXrx(FREqyoKeAEim#>7{ zE6PCoqcbk$BYy6lUzw>c{eP-y=x2&d(pK-%q@|?oK1Z8v_oq9$ou>5T^d>9J>bG0Q zniu~bTlgBr4%R-Ff1I*&?A_V4P9d39SN&vteO&#+(;V#w@&D+iVr3MHJmr-n?4%!O zFQNv59Oo&jKl#BCCvQNh3Q zr0(c`GW-3;HMb9)?kx9i53QE5YkJ2OBSmBlH0a*TEpoe2Lx4L9;(9ZYcmUj#oxg}n z(Ne8rt(_}V^vX9KGwgjdnYE(55{8|<;1vAObJo`GOXS1AuR#=oi*1EqU>}}j>a+(Z z^nQ?BiD!LC*vV>43pI4mO%1Wr6c=zn(%t=qb|~OMGLEMK%~u9xh;0?aNmVltGR`vd z-fYgjLQokG)vTA?K2}hhr~Nf)q%M#;Qg;rd2fJWiG3Z3ScU7P7*pxZUE~{mh8sm98 zN|4C-G&>6jSdDy}0r1%j%rED753tF6$Y<2hoJ_)ch5pR7X$sum7~mI#)+?sT;PM3D z&8b&0gPs_^K>nGi(6{tkRTAi-bjn;gS_?_c3*?WNjfK-)>^!RE^q)VT^70&{zU)fYAY2>V22s} z(r zM)p}9eI&6^Bb{*9Oi>Z-8O5SN5ky;Q8M9!t&eb9HY{a*oC%vIPRzIl(ydQ5Mh^jr6Ea| zxAHf)F99yDhr_I=S~aN5j{zN~bLfPu#A~wYji=i0c!rx9w{4fq%D$;T%(5Bvkfd8d zg_(A3`~*-_6P-3g9M*)^7U=)I)!z<{{wwiPkg?izT%`2o^M)!@u3U7&ru&!k9AR^# ze|HEj){ZyCUW77pbexU1ipl&)620l2G&X$9KYE(>M_{CLKuyZ;?dpW;Zlfk1d^)ns zEhW0Jd5~XSgoOY{&Q69U5DtrbNRgn4xvcB`Wv@zMVMBzS4MUdWRja9gNZC#)J?S!Rf%|n(E6K!sW9%IkX4w5x)Nf&5 zv4pRHz37+LX-M1ZJC>yq?u439 z0+!9&=SBXBFO}K5XED25Dt_8tP>&1!Hno1c48sDVLBWJtMdQtdH6`nSY{mKOZ9ymB zHHiHpo(Wp|BPchK7QV?htI zH(m-in8TiB1^xc2H6z08X8e6-IY6*ti851}!q{`OY)#@fiLYqjj@bL70* z=NIh%8AlqnOD0G~G5_fK36d`+^6Zs8xiv4j@;ga<&)ZgUj_N_zlQQ|Amg>)eVR)PH zYPDg*1ee~soJ-|;QekKOJY_o5!ddqnCWD4K8vl;v(D!ge>G&S9C}O_bSU<~1*X<&d z>;D^DNGXa(Sbcvs4(F}E&8wB$3V$MVCe%6-!ZN4H9-8Fu;0McUH_c*j4YhX<7-q-p zswN>N#5CG{e}>`r%ZWcP?p=(v{uo&@O;?_L_9X(70o|~!6;zD&mA&qXykqgt{}$=n za|&w#3Jbgajq&FE-J$7O&D%`7@zT_Umf*av0e3n>xJN^N6LNJ`$VmGU5Bz41ii{X) ztZj;A@_FF)&r{>?$+-5DXXyx!D!$|azsOCgeWi~Buwai4GR*ar>GPIYd~jGC*l&Zp zv1M5E${$V)%UZGZI8!@MkY}uLIa#g!^GQ;H+c2E}$0>cx>Wn8K{&T}D$lC729D50P zt<;ra0TyfMp!B8mBfT7jG8Naz|N8ghceRsB4DOx-cb-n6Kb-5#x%LHSRE-XxQqMCp zUthBobs;=j`k<|5d$267@`Q)qNneM3o|_~tqwCcE%d77Ft^8L=Z$jT9 zD&*zddgt2FwC-|p{UOX^4i|oS#FRP*8(HyGE?Ute|sz&bmS$_Lsm3*TC zW}xj955(TBH(LQ(v&79x?@VUTRUM1*C4U$W7rN?CthR59g3ARZP*!+;e?r_fI!F_ z)^%Gr;5f>4GL7v>p6k5W>s*E)gM&M$v3qB;awT?WtXu-zWr~EYJx+1*s0C)#NbJ16 zj!|HnC$E-L>xP;1_woRojY2WIqeeY1lTHgc_W;IEVpD;pq$#nM39 z!Iki@Slv!;`ASb<8HTQY&+vE01nFNzAKm{eE9Ja=HKWG!9wz8Yzh)%rF@^gjdt3Lp z7!0qoV`&|Aa#Q3u13|x+?q1k#aGhB8Vp9LjEd@co!A-@Z5J>T=nCpzmv%XOu39MdA z4{>rVGgTO{Nbi*4g~+D2JK)(aQFFB}?W^aAZPmy#6>bSU8Oc3uhrX8`@k_S$BSe@e za~%`f>IA&m?DjB0TmpCQE$?B%Giwu_+3>a%T7c(3?jT@`;Q2@ou7z)2nP-Q2Gx+H} z=g)q81eCvX!Ym`aic6%+a|S6$*)zxiL>|1h;65~O$aAuO@i3u$Y#AK8N78Yc_1nSx z;|wP8CIE#d%B1`0#S!2W`k^~(a{j#gWW%c;IHsK*zN3A={T}e2?@@lk%SN1MYDad) zr=uhLbZL*P2wEZZu4y0a_!LgqEx2N;p!+4y?w5s^#OcFz9M}~P1Pmwg7xeZ$xC4MV zPPfPhiW^u)PldKjh*u*|2}48P>z+;H2Aq}@`A_tG`{Lf!s?U4H$0v^dqfXNCY50RL|_P1ApfWL9S$gR6yT$ZtJ6?d`X$JQgPCdvC8IQcFYHC zAo+@f=C(xTOjD53-H;2*211DGPUvNkB@K&*r$ep!3*z3L7K7GJf0 z&v)rZ8K;NGYdI5&p`dej>T%A>^Rq>tGdGL3I=9X`k=~7G?)+Pv25x*Sf8;d3tSm44 z7pn$|@PdSc1J>N!g+4UOqi<)y7HZwpox+S)fQ?)K#%-^U?YP5aIpvNbyd9-q&1_iN zPSMfZ^7kXeM`VgTN|il&rih4bApDxMkoT@IG%j;D_cHl241@-Y_< z(#j0#&@D?Fn_dc>jRsb5)NDx=;fSo2e!ZJWCfmB&Onu!?cD-(j4Gt}6akKjNb4J^a zsdvBZA-OAp<2w5V6GqTe(fC21R-p1GgB)zYhgFuAK_#Yf0|_}`k;-zrYij#L_U_uB z_i6y8FmkuEfOtT+xF9EQk%3y^I>?e#_J(KoDY!QbN7D8z?AEY`9j}%bV~b_!F)gCj z@fnRZ4)!0?-?>Mg-)B0VG_>RYY(vAc+9#gVFKJwO>4#qJIJ@c#c(!%-5GTa3 zVMGBb^!0~LBaLM;ap$PWQ^}w0@l3SVXuDoCyL>`7|Dn5WrE-(_SaoJiV?^TW=HuIc zx4;2r>kP6J_x~)l z0c{Q{K`--fb-^2|YW1dwII&JlR>gR^ZUJvxUXFYDZ+F7uvqn!)$&R2Ke%&%D;l&9yy-ioxd4Vj)(>3NXwb*ASQHW ztJYr$dSFC-^XDyR-@Ja*b7rga7xNSs8 z?LfenKk0ZnDymOw8dxgVyX%Ke#+|Td$IEIjG7z!Q4ds{_S5v$Uz`UlS(}Z<{1D6br zpLK*Un+oYi?U3qK%v2@R(IS6C^L$PNs$+TjE(w!{2>tze`!XW`Xr&Xp6rxq4!a; zg{Qp}_cDBe>ruDeF0aEsO}y2?MqcL_kt~;(+Xyc$Zf4mpAX6CVn<1&>C57D^3D!Py z8=Hb^L%+~s+p_0ELrUM5Q7DURnRS>XH+_btXB#V9#zG&dHvBL3hX$ls_&A>iij9lWhoGY%t5TbE%+=R4F)T;;q$1X<{1Ez z^5a2b>c04jTGeV-jwofqS?Jx`qFcH*-oWB!n(WbHu=CAmuB;e99FfOUK|S;mVEP0y zgYbVfT=<1Hd#@c=1Ob~QI0`we@>FE!FGo5ILOVR?N1Ix$Z%T!G>3i@#U!aeyKt5_4kU`WNeuWV&K zV)Xdf>%(AfK@=3!^g8N^pzC$7hq>Im&^Y8n>jNIIpRJdqbN@{ai7au#OT z2KHiXVZCa zok;ZNRe|t?%LPr?nChA249F-2RivzXJB_ipdjE8vn+v>9&u~0qUkpX*S&UgxqT$lq z%U7vrDW$Y8()rY~#z%JVVX;~#;;V7-VkMjl?>P&<)^`EG!B@wuyihZdW{~43k%rz9 zsXBLY0EGhv2e@)_B0Z7YYQxv@t!@^Zv~g=D{s69nm36!d>5gfN{;y>EDR#rNJ%d>{ zj3eS@hJvbHh^dbWQLLU`Sr?>6HBE-&NzbcoQT~<41#H zh+-0+`Zy2_H-EYqVEp5f{s1+U%2I- zW%|QS;lDngwAJ44)j46s;7pU|$J$5k-C{1ioYTyW!B)_i4?QyNptgL7M zS5N6%4)arH>AQ2-o^SP2srPYI;YUtuRBz85|J6ONValz`;7Ta8z86ov#_Y?s$a0`q zkiMKG0Lw-FzWckbbm`20spqYvn1`86SK5D{@C1W@J~+SPVTfjs$Ku^R3s0`4MWuH~ z3hud86S_6OAJivCwmK|q*hK%A>%^QV0fvZIFhdIHxWz??!`_@|v>zMma zJJer_NIw+OKVPc3XPBupEc0=&KNBBzb-W|^&RT}b1r;Qi_k6PSW`4>w#r#$ zJ(xk5r?0i$DVNB+AuK%S`G`;VyKq--ob{P0tfc}sp> z2L*3y(pCQYTSWbHQNr&fx83u+lwN%Eq_19>F>ThAt9u6I0t13IFFp}PHF?LbR%hW>QD;-?z8 zVMw$$og1P*h3!jvUiZJpQ7IP$d*Q9Ys^cuzNH}xT4rI4TI57|YfqC=V+2KW7AXXfM zzG9j%GB0A^!iG#`URpSM&*xMSjoWd4<4!_I@$m$86;yB?_6t%&!L8;m$7UTP*ttbv znM6WTT=*KPP2%D~{A_u4Z``Tr(EjA!lhN(7VsSj%>Nn)dcQy6O{XAh?r8#-8z@u+J zjrjMjRcKX6VAa@(iZxSUvJjFnRI3Oa?bV|o`Y%`@Zn@k=U33N$abEm3Z32x8AY?xP?hQ%$G}+??kqo%No2$iG!Qm$MN5TY3#nsMg|NjXZtrQp=I*7cu#{&IQ9_q z&P8OSa{p_AgfhzcmDKNLXnGVj=yNUIyLP4?2oYtV^0i}w9EKk+h#O=KhUrF^u!jxBVq% zm6`8-{6(Or9#ZbM6i?1Tr2!R(TXwpiLTQubuGEW|#C)yzEo7R7dgg z;xTbz)|e;y-w%2(H*y1&GEdluf-9xN*auXpo2obTfUj^?1eOJzq55_S^N_nK&`J&rS%xA@gLL z$TQJmNHG%IKP*JQywAL*Lgsm|UoVlJG#EhSe0VccjN0F!=)#vblyBZk6xVX!5Th&% z_uSG_Gyt5=frvUF>BeP-#tlQV(VQlMJ4WX9`}Rw~27Kffvhg@nOU0Zcj+yD7VV9#r z7&4-kJ}i(tQ%}(Q6RaUItjf_;xC{@CgsAr`vu|nS`jU|Q2a33O*v6KL(tpHYEz=o6f(&XBH7AvpfwQj6SGSN zcNmpg^@-OI!>BrgsSPgutlI3DaMZAD_%?rl9irO6pa7k(^$=e0WB*(?pKj@2jh z$=`x)OqT>Buzj&fAjs8ey_cslE*j=jgMnK{=8yUggG@ioA$CQSw5IAC^f2c%r8MS8 z&X2<7fFoByd%z2^K@H+Wtuv45*Cv*q75A=A?zCLgJet=IXBHrgj=SNL>Dn+)m*FR4 zb+zaCbngNPt$G{0FX_?1?Kdy@caJzbVpm?=G1ui$lxD#Tjm+06_Ds-_5tTMVS?PBK zF9DC|1KG*u987$@!ZWMKdUQUZ+LzIW^M0F(sTZ|sY($iL64&3ICe9Kq+*4N`s?4NI zKof#u0HP)2Z7vF$Zca1pq~H$``ntU*Ihsbd2Sy_WwL|H0Gw2vIwytDjljgdwzIMA6 z{wk$VP&&Ct8Zat_a~kCF^#|58^2K30X}v+9tgodUTcAE@E34UYl)n#Wka@oF!zNAc z$1sFx(F3H0CQkx>xY6uBPBmwezwysbfZ~!|_@~psMu5XkSsA~2UF6j2Crcf>68J<; z=<5zxGA&O+%3>mlmJdy~Z5SVdOa(zulm-Q*k#;nwq=dxi zlF>c7Lj)AY#^?@-(Ip*92&0E|*MQO8^}KukfqmF@-`jN_@jD$KQ@wD5HH_#iHIRJe z&*Za$nDnB12W1*@|8`&>%%yb>mTbV*YC@eLnL3 zSUI)262Y%+u}abg6392>U(hOVkA!nct*D25Zn)lYy`YxL2krQm>!lO6pPUuf$8d-I z2bjjOoZND0nsKzWvA)?Zw z+n;?%TP%XbJ<<6_l{%{V3J#35d1>=c={yA253cG6j0*QJPD+hGDcR8H7V)$9P;Yj5 zR``A|Rz6;AEVPOhy}JrG^3|ZNR$JzD0X>!)Vz*lJlWAgeed_pNm=|NM^vOdi%r%0;vCWQJFq849SNbsm(1_g zlk)eTD-yC^4Q$HE_XX$FjC=_KtBb2A7X?rUf7T*F} z!GhdAax=NY6~aAhpWISgMhp~K%-TV0R0#pgyZ?f7fmBnfZ>C=Wq6b3}&0wb-?&i2v z2WV!r0f!*lGoSgPIC=-dw=AK0zTt4sUxhULCs>5#OTY@c_n-**Lrj zIOs0#uvVl>FUTeT*Bzs-r8;{(@_+_dv|}IWN0t2K1^HNzL2u?_?|fV$gQ^Dy7o&U8 zQOrA@^usKCXK}d)v?DKD2=)yJVT{HiXT6yUh2_1dLWaCtf;j!P7*HVAbm(Nhu&$_+ zEavDg!CrOL>2&b@LSOfc{cLj*MHkTn<5kEoCtT@DqhLpJ{Y29A%=n@#$DjEEd0SP{ z?!{9&QD(zdE6TTT`8q`!_Qlr|pGLXT&Dl=1j;axNR99(=(iqu?EI#{p6w9%6dLs)& zetql@J#apwXlykM&{|=@Oq(xH%2x+1FajxiK&I!qY_~b478_z@8Os5Tqsk)=E0v>V zTK(Y*R2@IB14Tvml!OmO^9`u%I5fSIOwjX|LRHUfUB`70YPi3DD5cF7DL<@m^&@~L zQwuh~6fMFhj;!D|1fmaPADD>|;+xP^m<{R5#pv+HJoE}l8p&gUtzEN>GSsmZNo{fh zb^Ee`1Q+0fBr*FZ&a6VqL)}gjYFM| zr)9<~tNR8D=EQ0vG5|1<@C;g7wV0C>jTVrxJ}{e#_x=~%%u!I9RsL_`1iByemK~Y9J4G4-6}awLoUBXx(x6mbv=}F8ltsb zw;JbAf9yKHYPbo27$^b+_uO>y@Bvz@IJSC|-{Uxk9pBzK!!756gvRI@uH+$e3u%vQ zCg-v*Te_oLlNC@8=O41DCi2IA9Jg)SmOZ2980E$^>C|hdEz427^Qn@{&ID?_O$G**)#5 zidBe|1MK$_rwG~hlc!^W_fn^3p8lCY8pNVs>hR9h?IdCr@|CDD*CSnGyBGt92jK4; zwcK_PE1rI9iDMZ(t4o&nN=Y)ZnO`C(H(G|WUu@yPW5&}LSCd4D)&g!OTl4^TogCXCoNacbaISk~*b#&&?$tmR|e=*PWkqslRTpB$X#% z0Q%CZXX~9VhWvilJW{boqV6(m=7a1OcoyV+MXEdUE>k%Cv9xkiqep;PkibLB
TASK_A2G:GetGoalTotal() + +
TASK_A2G:GetPlannedMenuText() @@ -192,6 +198,12 @@ based on the tasking capabilities defined in Task#TA TASK_A2G:New(Mission, SetGroup, TaskName, UnitSetTargets, TargetDistance, TargetZone, TargetSetUnit, TaskType, TaskBriefing)

Instantiates a new TASK_A2G.

+
TASK_A2G:SetGoalTotal() +