From 9ab3a2f74de3db0d3e478d2a8d61c0906d395fe0 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Wed, 30 Nov 2016 10:40:31 +0100 Subject: [PATCH] STATEMACHINE_TEMPLATE is added to template statemachines... It is working now, and NOW SWITCHING SLOTS of PLAYERS ALSO WORKS IN TASKING!!! Jippie!!! The next thing is to debug the DETECTION_DISPATCHER... And make STATEMACHINE_TEMPLATE now as a parameter to create new STATEMACHINEs, instead of that ugly table construction. The, I need to modify the New: Methods of each STATEMACHINE_PROCESS to be initialized with a TEMPLATE... Maybe I can commit already and just implement this later ... --- Moose Development/Moose/Core/StateMachine.lua | 72 ++++++++++++++- Moose Development/Moose/Process/Account.lua | 2 +- Moose Development/Moose/Process/Assign.lua | 35 ++++++- Moose Development/Moose/Process/Route.lua | 2 +- Moose Development/Moose/Process/Smoke.lua | 2 +- .../Moose/Tasking/CommandCenter.lua | 6 +- Moose Development/Moose/Tasking/Task.lua | 87 +++++++++++++----- Moose Development/Moose/Utilities/Utils.lua | 8 +- Moose Development/Moose/Wrapper/Unit.lua | 48 +++++----- .../Moose_Test_Task_SEAD.lua | 31 ++++--- .../Moose_Test_Task_SEAD.miz | Bin 27918 -> 28428 bytes .../Tasking/DCS World - MOOSE - Tasking.pptx | Bin 5416684 -> 5416770 bytes 12 files changed, 215 insertions(+), 78 deletions(-) diff --git a/Moose Development/Moose/Core/StateMachine.lua b/Moose Development/Moose/Core/StateMachine.lua index ecbf176f8..7220b8a97 100644 --- a/Moose Development/Moose/Core/StateMachine.lua +++ b/Moose Development/Moose/Core/StateMachine.lua @@ -74,6 +74,8 @@ function STATEMACHINE:SetInitialState( State ) self.current = State end + + function STATEMACHINE:AddAction( From, Event, To ) local event = {} @@ -87,6 +89,8 @@ function STATEMACHINE:AddAction( From, Event, To ) end + + --- Set the default @{Process} template with key ProcessName providing the ProcessClass and the process object when it is assigned to a @{Controllable} by the task. -- @return Process#PROCESS function STATEMACHINE:AddProcess( From, Event, Process, ReturnEvents ) @@ -164,7 +168,7 @@ function STATEMACHINE._handler( self, EventName, ... ) self:E( { EventName, ... } ) local can, to = self:can( EventName ) - self:E( { EventName, can, to } ) + self:E( { EventName, self.current, can, to } ) local ReturnValues = nil @@ -544,3 +548,69 @@ function STATEMACHINE_SET:_call_handler( handler, params ) end end + +--- STATEMACHINE_TEMPLATE class +-- @type STATEMACHINE_TEMPLATE +-- @extends Core.Base#BASE +STATEMACHINE_TEMPLATE = { + ClassName = "STATEMACHINE_TEMPLATE", +} + +--- Creates a new STATEMACHINE_TEMPLATE object. +-- @param #STATEMACHINE_TEMPLATE self +-- @return #STATEMACHINE_TEMPLATE +function STATEMACHINE_TEMPLATE:New( options ) + + -- Inherits from BASE + local self = BASE:Inherit( self, BASE:New() ) -- #STATEMACHINE_TEMPLATE + + self._Transitions = self.Transitions or {} + self._Processes = self.Processes or {} + + return self +end + +function STATEMACHINE_TEMPLATE:AddTransition( From, Event, To ) + + local Transition = {} + Transition.From = From + Transition.Event = Event + Transition.To = To + + self._Transitions[Transition] = Transition +end + +function STATEMACHINE_TEMPLATE:GetTransitions() + + return self._Transitions +end + +--- Set the default @{Process} template with key ProcessName providing the ProcessClass and the process object when it is assigned to a @{Controllable} by the task. +-- @return Process#PROCESS +function STATEMACHINE_TEMPLATE:AddProcess( From, Event, ProcessTemplate, ReturnEvents ) + + local Process = {} + Process.From = From + Process.Event = Event + Process.Process = ProcessTemplate[1] + Process.Arguments = ProcessTemplate[2] + Process.ReturnEvents = ReturnEvents + + -- Make the reference table weak. + -- setmetatable( self.options.subs, { __mode = "v" } ) + self._Processes[Process] = Process + + return ProcessTemplate +end + +function STATEMACHINE_TEMPLATE:GetProcesses() + + return self._Processes +end + +function STATEMACHINE_TEMPLATE:CopyCallHandler( Fsm, OnAction, Transition ) + self:E( { Fsm.ClassName, OnAction, Transition } ) + if OnAction and Transition and self[OnAction .. Transition] then + Fsm[OnAction .. Transition] = self[OnAction .. Transition] + end +end diff --git a/Moose Development/Moose/Process/Account.lua b/Moose Development/Moose/Process/Account.lua index 804b41fd9..581e99368 100644 --- a/Moose Development/Moose/Process/Account.lua +++ b/Moose Development/Moose/Process/Account.lua @@ -178,7 +178,7 @@ do -- PROCESS_ACCOUNT_DEADS -- @param Set#SET_UNIT TargetSetUnit -- @param #string TaskName function PROCESS_ACCOUNT_DEADS:Template( TargetSetUnit, TaskName ) - return { self, arg } + return { self, { TargetSetUnit, TaskName } } end diff --git a/Moose Development/Moose/Process/Assign.lua b/Moose Development/Moose/Process/Assign.lua index 11d80cb57..0724d55d6 100644 --- a/Moose Development/Moose/Process/Assign.lua +++ b/Moose Development/Moose/Process/Assign.lua @@ -84,7 +84,7 @@ do -- PROCESS_ASSIGN --- PROCESS_ASSIGN class -- @type PROCESS_ASSIGN - -- @field Task#TASK_BASE Task + -- @field Tasking.Task#TASK_BASE Task -- @field Unit#UNIT ProcessUnit -- @field Zone#ZONE_BASE TargetZone -- @extends Fsm.Process#PROCESS @@ -128,7 +128,7 @@ do -- PROCESS_ASSIGN_ACCEPT -- @field Task#TASK_BASE Task -- @field Unit#UNIT ProcessUnit -- @field Zone#ZONE_BASE TargetZone - -- @extends Process#PROCESS + -- @extends Fsm.Process#PROCESS PROCESS_ASSIGN_ACCEPT = { ClassName = "PROCESS_ASSIGN_ACCEPT", } @@ -159,17 +159,34 @@ do -- PROCESS_ASSIGN_ACCEPT --- StateMachine callback function -- @param #PROCESS_ASSIGN_ACCEPT self - -- @param Controllable#CONTROLLABLE ProcessUnit + -- @param Wrapper.Unit#UNIT ProcessUnit -- @param #string Event -- @param #string From -- @param #string To function PROCESS_ASSIGN_ACCEPT:onafterStart( ProcessUnit, Event, From, To ) self:E( { ProcessUnit, Event, From, To } ) - MESSAGE:New( self.TaskBriefing, 30, "Task Assignment" ):ToGroup( ProcessUnit:GetGroup() ) + local ProcessGroup = ProcessUnit:GetGroup() + MESSAGE:New( self.TaskBriefing, 30, ProcessUnit:GetPlayerName() .. " Task Acceptance" ):ToGroup( ProcessGroup ) self:__Assign( 1 ) end + + --- StateMachine callback function + -- @param #PROCESS_ASSIGN_ACCEPT self + -- @param Wrapper.Unit#UNIT ProcessUnit + -- @param #string Event + -- @param #string From + -- @param #string To + function PROCESS_ASSIGN_ACCEPT:onenterAssigned( ProcessUnit, Event, From, To ) + self:E( { ProcessUnit, Event, From, To } ) + + local ProcessGroup = ProcessUnit:GetGroup() + + MESSAGE:New( "You are assigned to the task " .. self.Task:GetName(), 30, ProcessUnit:GetPlayerName() .. ": Task Assignment" ):ToGroup( ProcessGroup ) + + self.Task:Assign() + end end -- PROCESS_ASSIGN_ACCEPT @@ -185,6 +202,16 @@ do -- PROCESS_ASSIGN_MENU_ACCEPT PROCESS_ASSIGN_MENU_ACCEPT = { ClassName = "PROCESS_ASSIGN_MENU_ACCEPT", } + + --- Init. + -- @param #PROCESS_ASSIGN_MENU_ACCEPT self + -- @param #string TaskName + -- @param #string TaskBriefing + -- @return #PROCESS_ASSIGN_MENU_ACCEPT self + function PROCESS_ASSIGN_MENU_ACCEPT:Template( TaskName, TaskBriefing ) + + return { self, { TaskName, TaskBriefing } } + end --- Creates a new task assignment state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator. diff --git a/Moose Development/Moose/Process/Route.lua b/Moose Development/Moose/Process/Route.lua index ba3451623..a5ad80715 100644 --- a/Moose Development/Moose/Process/Route.lua +++ b/Moose Development/Moose/Process/Route.lua @@ -200,7 +200,7 @@ do -- PROCESS_ROUTE_ZONE -- @param #PROCESS_ROUTE_ZONE self -- @param Zone#ZONE_BASE TargetZone function PROCESS_ROUTE_ZONE:Template( TargetZone ) - return { self, arg } + return { self, { TargetZone } } end diff --git a/Moose Development/Moose/Process/Smoke.lua b/Moose Development/Moose/Process/Smoke.lua index 62805b9e4..4cad8227c 100644 --- a/Moose Development/Moose/Process/Smoke.lua +++ b/Moose Development/Moose/Process/Smoke.lua @@ -156,7 +156,7 @@ do -- PROCESS_SMOKE_TARGETS_ZONE -- @param Set#SET_UNIT TargetSetUnit -- @param Zone#ZONE_BASE TargetZone function PROCESS_SMOKE_TARGETS_ZONE:Template( TargetSetUnit, TargetZone ) - return { self, arg } + return { self, { TargetSetUnit, TargetZone } } end --- Creates a new target smoking state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator. diff --git a/Moose Development/Moose/Tasking/CommandCenter.lua b/Moose Development/Moose/Tasking/CommandCenter.lua index 059792c98..5e8f4ca71 100644 --- a/Moose Development/Moose/Tasking/CommandCenter.lua +++ b/Moose Development/Moose/Tasking/CommandCenter.lua @@ -69,12 +69,12 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName ) self:EventOnBirth( --- @param Core.Event#EVENTDATA EventData - function( HQ, EventData ) + function( self, EventData ) self:E( { EventData } ) local EventGroup = GROUP:Find( EventData.IniDCSGroup ) - if EventGroup and HQ:HasGroup( EventGroup ) then + if EventGroup and self:HasGroup( EventGroup ) then local MenuReporting = MENU_GROUP:New( EventGroup, "Reporting", self.CommandCenterMenu ) - local MenuMissions = MENU_GROUP_COMMAND:New( EventGroup, "Missions", MenuReporting, HQ.ReportMissions, HQ, EventGroup ) + local MenuMissions = MENU_GROUP_COMMAND:New( EventGroup, "Missions", MenuReporting, self.ReportMissions, self, EventGroup ) end end ) diff --git a/Moose Development/Moose/Tasking/Task.lua b/Moose Development/Moose/Tasking/Task.lua index 9d7245a8b..c0c4974af 100644 --- a/Moose Development/Moose/Tasking/Task.lua +++ b/Moose Development/Moose/Tasking/Task.lua @@ -53,8 +53,8 @@ -- @type TASK_BASE -- @field Scheduler#SCHEDULER TaskScheduler -- @field Mission#MISSION Mission --- @field Core.StateMachine#STATEMACHINE_PROCESS FsmTemplate --- @field Set#SET_GROUP SetGroup The Set of Groups assigned to the Task +-- @field Core.Set#SET_GROUP SetGroup The Set of Groups assigned to the Task +-- @field Core.StateMachine#STATEMACHINE_TEMPLATE FsmTemplate -- @extends Core.StateMachine#STATEMACHINE_TASK TASK_BASE = { ClassName = "TASK_BASE", @@ -98,13 +98,35 @@ function TASK_BASE:New( Mission, SetGroupAssign, TaskName, TaskType ) self:SetID( Mission:GetNextTaskID( self ) ) -- The Mission orchestrates the task sequences .. self.TaskBriefing = "You are invited for the task: " .. self.TaskName .. "." + + self.FsmTemplate = self.FsmTemplate or STATEMACHINE_TEMPLATE:New( {} ) - self.FsmTemplate = self.FsmTemplate or STATEMACHINE_PROCESS:New( {} ) - self.FsmTemplate:SetTask( self ) + -- Handle the birth of new planes within the assigned set. + self:EventOnPlayerEnterUnit( + --- @param #TASK_BASE self + -- @param Core.Event#EVENTDATA EventData + function( self, EventData ) + self:E( "In EnterUnit" ) + self:E( { "State", self:GetState() } ) + if self:IsStateAssigned() then + local TaskUnit = EventData.IniUnit + local TaskGroup = EventData.IniUnit:GetGroup() + self:E( self.SetGroup:IsIncludeObject( TaskGroup ) ) + if self.SetGroup:IsIncludeObject( TaskGroup ) then + self:AssignToUnit( TaskUnit ) + end + end + end + ) return self end +function TASK_BASE:GetFsmTemplate() + + return self.FsmTemplate +end + function TASK_BASE:GetMission() return self.Mission @@ -117,10 +139,7 @@ function TASK_BASE:GetGroups() return self.SetGroup end -function TASK_BASE:GetFsmTemplate() - return self.FsmTemplate -end --- Assign the @{Task}to a @{Group}. -- @param #TASK_BASE self @@ -166,18 +185,30 @@ end function TASK_BASE:AssignToUnit( TaskUnit ) self:F( TaskUnit:GetName() ) - -- Copy the FsmTemplate, which is not assigned to a Unit. - -- Assign the FsmTemplate to the TaskUnit. - local FsmTemplate = self:GetFsmTemplate() - local FsmUnit = UTILS.DeepCopy( FsmTemplate ) -- Core.StateMachine#STATEMACHINE_PROCESS + -- Assign a new FsmUnit to TaskUnit. + local FsmUnit = self:SetStateMachine( TaskUnit, STATEMACHINE_PROCESS:New() ) -- Core.StateMachine#STATEMACHINE_PROCESS + self:E({"Address FsmUnit", tostring( FsmUnit ) } ) FsmUnit:Assign( self, TaskUnit ) - -- Assign each FsmSub in FsmUnit to the TaskUnit. - -- (This is not done during the copy). - self:E(FsmUnit:GetSubs()) - for FsmSubID, FsmSub in pairs( FsmUnit:GetSubs() ) do - self:E( { "Sub ID", FsmSub.fsm:GetClassNameAndID(), FsmSubID } ) - FsmSub.fsm:Assign( self, TaskUnit ) + for TransitionID, Transition in pairs( self.FsmTemplate:GetTransitions() ) do + FsmUnit:AddAction( Transition.From, Transition.Event, Transition.To ) + self.FsmTemplate:CopyCallHandler( FsmUnit, "onenter", Transition.From ) + self.FsmTemplate:CopyCallHandler( FsmUnit, "onleave", Transition.From ) + self.FsmTemplate:CopyCallHandler( FsmUnit, "onenter", Transition.To ) + self.FsmTemplate:CopyCallHandler( FsmUnit, "onleave", Transition.To ) + self.FsmTemplate:CopyCallHandler( FsmUnit, "onbefore", Transition.Event ) + self.FsmTemplate:CopyCallHandler( FsmUnit, "onafter", Transition.Event ) + end + + for ProcessID, Process in pairs( self.FsmTemplate:GetProcesses() ) do + self:E( Process ) + local FsmProcess = FsmUnit:AddProcess(Process.From, Process.Event, Process.Process:New( unpack( Process.Arguments ) ), Process.ReturnEvents ) + self.FsmTemplate:CopyCallHandler( FsmProcess, "onenter", Process.From ) + self.FsmTemplate:CopyCallHandler( FsmProcess, "onleave", Process.From ) + self.FsmTemplate:CopyCallHandler( FsmProcess, "onbefore", Process.Event ) + self.FsmTemplate:CopyCallHandler( FsmProcess, "onafter", Process.Event ) + + FsmProcess:Assign( self, TaskUnit ) end -- Set the events @@ -190,8 +221,6 @@ function TASK_BASE:AssignToUnit( TaskUnit ) FsmUnit:SetInitialState( "Planned" ) FsmUnit:Accept() -- Each Task needs to start with an Accept event to start the flow. - - return self end @@ -265,18 +294,14 @@ end --- Set the menu options of the @{Task} to all the groups in the SetGroup. -- @param #TASK_BASE self --- @return #TASK_BASE self function TASK_BASE:SetMenu() for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do - if not self:IsAssignedToGroup( TaskGroup ) then - self:SetPlannedMenuForGroup( TaskGroup, self:GetTaskName() ) - else - self:SetAssignedMenuForGroup( TaskGroup ) - end + self:SetMenuForGroup( TaskGroup ) end end + --- Remove the menu options of the @{Task} to all the groups in the SetGroup. -- @param #TASK_BASE self -- @return #TASK_BASE self @@ -288,6 +313,17 @@ function TASK_BASE:RemoveMenu() end +--- Set the Menu for a Group +-- @param #TASK_BASE self +function TASK_BASE:SetMenuForGroup( TaskGroup ) + + if not self:IsAssignedToGroup( TaskGroup ) then + self:SetPlannedMenuForGroup( TaskGroup, self:GetTaskName() ) + else + self:SetAssignedMenuForGroup( TaskGroup ) + end +end + --- Set the planned menu option of the @{Task}. -- @param #TASK_BASE self @@ -718,6 +754,7 @@ function TASK_BASE:onenterAssigned( Event, From, To ) self:E("Assigned") + end diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua index bb0e0f88a..3cf7c34ec 100644 --- a/Moose Development/Moose/Utilities/Utils.lua +++ b/Moose Development/Moose/Utilities/Utils.lua @@ -113,11 +113,11 @@ UTILS.OneLineSerialize = function( tbl ) -- serialization of a table all on a s tbl_str[#tbl_str + 1] = table.concat(val_str) end elseif type(val) == 'function' then - -- tbl_str[#tbl_str + 1] = "function " .. tostring(ind) - -- tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it + tbl_str[#tbl_str + 1] = "f() " .. tostring(ind) + tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it else --- env.info('unable to serialize value type ' .. routines.utils.basicSerialize(type(val)) .. ' at index ' .. tostring(ind)) --- env.info( debug.traceback() ) + env.info('unable to serialize value type ' .. routines.utils.basicSerialize(type(val)) .. ' at index ' .. tostring(ind)) + env.info( debug.traceback() ) end end diff --git a/Moose Development/Moose/Wrapper/Unit.lua b/Moose Development/Moose/Wrapper/Unit.lua index c13354f99..e3dc53000 100644 --- a/Moose Development/Moose/Wrapper/Unit.lua +++ b/Moose Development/Moose/Wrapper/Unit.lua @@ -1,8 +1,8 @@ --- This module contains the UNIT class. -- --- 1) @{Unit#UNIT} class, extends @{Controllable#CONTROLLABLE} +-- 1) @{#UNIT} class, extends @{Controllable#CONTROLLABLE} -- =========================================================== --- The @{Unit#UNIT} class is a wrapper class to handle the DCS Unit objects: +-- The @{#UNIT} class is a wrapper class to handle the DCS Unit objects: -- -- * Support all DCS Unit APIs. -- * Enhance with Unit specific APIs not in the DCS Unit API set. @@ -122,7 +122,7 @@ UNIT = { --- Create a new UNIT from DCSUnit. -- @param #UNIT self -- @param #string UnitName The name of the DCS unit. --- @return Unit#UNIT +-- @return #UNIT function UNIT:Register( UnitName ) local self = BASE:Inherit( self, CONTROLLABLE:New( UnitName ) ) self.UnitName = UnitName @@ -134,7 +134,7 @@ end --- Finds a UNIT from the _DATABASE using a DCSUnit object. -- @param #UNIT self -- @param DCSUnit#Unit DCSUnit An existing DCS Unit object reference. --- @return Unit#UNIT self +-- @return #UNIT self function UNIT:Find( DCSUnit ) local UnitName = DCSUnit:getName() @@ -145,7 +145,7 @@ end --- Find a UNIT in the _DATABASE using the name of an existing DCS Unit. -- @param #UNIT self -- @param #string UnitName The Unit Name. --- @return Unit#UNIT self +-- @return #UNIT self function UNIT:FindByName( UnitName ) local UnitFound = _DATABASE:FindUnit( UnitName ) @@ -182,7 +182,7 @@ end -- * When the unit is alive, it will tweak the template x, y and heading coordinates of the group and the embedded units to the current units positions. -- * Then it will respawn the re-modelled group. -- --- @param Unit#UNIT self +-- @param #UNIT self -- @param DCSTypes#Vec3 SpawnVec3 The position where to Spawn the new Unit at. -- @param #number Heading The heading of the unit respawn. function UNIT:ReSpawn( SpawnVec3, Heading ) @@ -200,7 +200,7 @@ function UNIT:ReSpawn( SpawnVec3, Heading ) self:E( #SpawnGroupTemplate.units ) for UnitID, UnitData in pairs( SpawnGroup:GetUnits() ) do - local GroupUnit = UnitData -- Unit#UNIT + local GroupUnit = UnitData -- #UNIT self:E( GroupUnit:GetName() ) if GroupUnit:IsAlive() then local GroupUnitVec3 = GroupUnit:GetVec3() @@ -225,7 +225,7 @@ function UNIT:ReSpawn( SpawnVec3, Heading ) self:E( { UnitTemplateID, SpawnGroupTemplate.units[UnitTemplateID], SpawnGroupTemplate.units[UnitTemplateID] } ) else self:E( SpawnGroupTemplate.units[UnitTemplateID].name ) - local GroupUnit = UNIT:FindByName( SpawnGroupTemplate.units[UnitTemplateID].name ) -- Unit#UNIT + local GroupUnit = UNIT:FindByName( SpawnGroupTemplate.units[UnitTemplateID].name ) -- #UNIT if GroupUnit and GroupUnit:IsAlive() then local GroupUnitVec3 = GroupUnit:GetVec3() local GroupUnitHeading = GroupUnit:GetHeading() @@ -262,7 +262,7 @@ end --- Returns if the unit is activated. --- @param Unit#UNIT self +-- @param #UNIT self -- @return #boolean true if Unit is activated. -- @return #nil The DCS Unit is not existing or alive. function UNIT:IsActive() @@ -282,7 +282,7 @@ end --- Returns the Unit's callsign - the localized string. --- @param Unit#UNIT self +-- @param #UNIT self -- @return #string The Callsign of the Unit. -- @return #nil The DCS Unit is not existing or alive. function UNIT:GetCallsign() @@ -301,7 +301,7 @@ end --- Returns name of the player that control the unit or nil if the unit is controlled by A.I. --- @param Unit#UNIT self +-- @param #UNIT self -- @return #string Player Name -- @return #nil The DCS Unit is not existing or alive. function UNIT:GetPlayerName() @@ -325,7 +325,7 @@ end -- The number is the same number the unit has in ME. -- It may not be changed during the mission. -- If any unit in the group is destroyed, the numbers of another units will not be changed. --- @param Unit#UNIT self +-- @param #UNIT self -- @return #number The Unit number. -- @return #nil The DCS Unit is not existing or alive. function UNIT:GetNumber() @@ -343,7 +343,7 @@ end --- Returns the unit's group if it exist and nil otherwise. -- @param Wrapper.Unit#UNIT self --- @return Group#GROUP The Group of the Unit. +-- @return Wrapper.Group#GROUP The Group of the Unit. -- @return #nil The DCS Unit is not existing or alive. function UNIT:GetGroup() self:F2( self.UnitName ) @@ -364,7 +364,7 @@ end --- Returns the prefix name of the DCS Unit. A prefix name is a part of the name before a '#'-sign. -- DCS Units spawned with the @{SPAWN} class contain a '#'-sign to indicate the end of the (base) DCS Unit name. -- The spawn sequence number and unit number are contained within the name after the '#' sign. --- @param Unit#UNIT self +-- @param #UNIT self -- @return #string The name of the DCS Unit. -- @return #nil The DCS Unit is not existing or alive. function UNIT:GetPrefix() @@ -382,7 +382,7 @@ function UNIT:GetPrefix() end --- Returns the Unit's ammunition. --- @param Unit#UNIT self +-- @param #UNIT self -- @return DCSUnit#Unit.Ammo -- @return #nil The DCS Unit is not existing or alive. function UNIT:GetAmmo() @@ -399,7 +399,7 @@ function UNIT:GetAmmo() end --- Returns the unit sensors. --- @param Unit#UNIT self +-- @param #UNIT self -- @return DCSUnit#Unit.Sensors -- @return #nil The DCS Unit is not existing or alive. function UNIT:GetSensors() @@ -419,7 +419,7 @@ end -- unit:hasSensors(Unit.SensorType.RADAR, Unit.RadarType.AS) --- Returns if the unit has sensors of a certain type. --- @param Unit#UNIT self +-- @param #UNIT self -- @return #boolean returns true if the unit has specified types of sensors. This function is more preferable than Unit.getSensors() if you don't want to get information about all the unit's sensors, and just want to check if the unit has specified types of sensors. -- @return #nil The DCS Unit is not existing or alive. function UNIT:HasSensors( ... ) @@ -436,7 +436,7 @@ function UNIT:HasSensors( ... ) end --- Returns if the unit is SEADable. --- @param Unit#UNIT self +-- @param #UNIT self -- @return #boolean returns true if the unit is SEADable. -- @return #nil The DCS Unit is not existing or alive. function UNIT:HasSEAD() @@ -462,7 +462,7 @@ end -- -- * First value indicates if at least one of the unit's radar(s) is on. -- * Second value is the object of the radar's interest. Not nil only if at least one radar of the unit is tracking a target. --- @param Unit#UNIT self +-- @param #UNIT self -- @return #boolean Indicates if at least one of the unit's radar(s) is on. -- @return DCSObject#Object The object of the radar's interest. Not nil only if at least one radar of the unit is tracking a target. -- @return #nil The DCS Unit is not existing or alive. @@ -480,7 +480,7 @@ function UNIT:GetRadar() end --- Returns relative amount of fuel (from 0.0 to 1.0) the unit has in its internal tanks. If there are additional fuel tanks the value may be greater than 1.0. --- @param Unit#UNIT self +-- @param #UNIT self -- @return #number The relative amount of fuel (from 0.0 to 1.0). -- @return #nil The DCS Unit is not existing or alive. function UNIT:GetFuel() @@ -497,7 +497,7 @@ function UNIT:GetFuel() end --- Returns the unit's health. Dead units has health <= 1.0. --- @param Unit#UNIT self +-- @param #UNIT self -- @return #number The Unit's health value. -- @return #nil The DCS Unit is not existing or alive. function UNIT:GetLife() @@ -514,7 +514,7 @@ function UNIT:GetLife() end --- Returns the Unit's initial health. --- @param Unit#UNIT self +-- @param #UNIT self -- @return #number The Unit's initial health value. -- @return #nil The DCS Unit is not existing or alive. function UNIT:GetLife0() @@ -625,8 +625,8 @@ end --- Returns true if there is an **other** DCS Unit within a radius of the current 2D point of the DCS Unit. --- @param Unit#UNIT self --- @param Unit#UNIT AwaitUnit The other UNIT wrapper object. +-- @param #UNIT self +-- @param #UNIT AwaitUnit The other UNIT wrapper object. -- @param Radius The radius in meters with the DCS Unit in the centre. -- @return true If the other DCS Unit is within the radius of the 2D point of the DCS Unit. -- @return #nil The DCS Unit is not existing or alive. diff --git a/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.lua b/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.lua index 99ea17156..dfd3b5721 100644 --- a/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.lua +++ b/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.lua @@ -61,7 +61,8 @@ local TaskSEAD = TASK_BASE:New( Mission, SEADSet, "SEAD Radars", "SEAD" ) -- Tas -- There can be many copied FsmSEAD objects internally active within TaskSEAD, for each pilot that joined the Task one is instantiated. -- The reason why this is done, is that each unit as a role within the Task, and can have different status. -- Therefore, the FsmSEAD is a TEMPLATE PROCESS of the TASK, and must be designed as a UNIT with a player is executing that PROCESS. -local FsmSEAD = TaskSEAD:GetFsmTemplate() + +local FsmSEADTemplate = TaskSEAD:GetFsmTemplate() -- Adding a new sub-process to the Task Template. -- At first, the task needs to be accepted by a pilot. @@ -74,10 +75,10 @@ local FsmSEAD = TaskSEAD:GetFsmTemplate() -- 4.1 When the return state is Assigned, fire the event in the Task FsmSEAD:Route() -- 4.2 When the return state is Rejected, fire the event in the Task FsmSEAD:Eject() -- All other AddProcess calls are working in a similar manner. -FsmSEAD:AddProcess( "Planned", "Accept", PROCESS_ASSIGN_ACCEPT:New( "SEAD the Area" ), { Assigned = "Route", Rejected = "Eject" } ) +FsmSEADTemplate:AddProcess ( "Planned", "Accept", PROCESS_ASSIGN_ACCEPT:Template( "SEAD the Area" ), { Assigned = "Route", Rejected = "Eject" } ) -- Same, adding a process. -FsmSEAD:AddProcess( "Assigned", "Route", PROCESS_ROUTE_ZONE:New( TargetZone, 3000 ), { Arrived = "Update" } ) +FsmSEADTemplate:AddProcess ( "Assigned", "Route", PROCESS_ROUTE_ZONE:Template( TargetZone, 3000 ), { Arrived = "Update" } ) -- Adding a new Action... -- Actions define also the flow of the Task, but the actions will need to be programmed within your script. @@ -86,22 +87,24 @@ FsmSEAD:AddProcess( "Assigned", "Route", PROCESS_ROUTE_ZONE:New( TargetZone -- 1. State From "Rejected". When the FsmSEAD is in state "Rejected", the event "Eject" can be fired. -- 2. Event "Eject". This event can be triggered synchronously through FsmSEAD:Eject() or asynchronously through FsmSEAD:__Eject(secs). -- 3. State To "Planned". After the event has been fired, the FsmSEAD will transition to Planned. -FsmSEAD:AddAction ( "Rejected", "Eject", "Planned" ) -FsmSEAD:AddAction ( "Arrived", "Update", "Updated" ) -FsmSEAD:AddProcess( "Updated", "Account", PROCESS_ACCOUNT_DEADS:New( TargetSet, "SEAD" ), { Accounted = "Success" } ) -FsmSEAD:AddProcess( "Updated", "Smoke", PROCESS_SMOKE_TARGETS_ZONE:New( TargetSet, TargetZone ) ) -FsmSEAD:AddAction ( "Accounted", "Success", "Success" ) -FsmSEAD:AddAction ( "*", "Fail", "Failed" ) +FsmSEADTemplate:AddTransition ( "Rejected", "Eject", "Planned" ) +FsmSEADTemplate:AddTransition ( "Arrived", "Update", "Updated" ) +FsmSEADTemplate:AddProcess ( "Updated", "Account", PROCESS_ACCOUNT_DEADS:Template( TargetSet, "SEAD" ), { Accounted = "Success" } ) +FsmSEADTemplate:AddProcess ( "Updated", "Smoke", PROCESS_SMOKE_TARGETS_ZONE:Template( TargetSet, TargetZone ) ) +FsmSEADTemplate:AddTransition ( "Accounted", "Success", "Success" ) +FsmSEADTemplate:AddTransition ( "*", "Fail", "Failed" ) -- Now we will set the SCORING. Scoring is set using the TaskSEAD object. -- Scores can be set on the status of the Task, and on Process level. -TaskSEAD:AddScoreTask( "Success", "Destroyed all target radars", 250 ) -TaskSEAD:AddScoreTask( "Failed", "Failed to destroy all target radars", -100 ) +--FsmSEADTemplate:AddScoreTask( "Success", "Destroyed all target radars", 250 ) +--FsmSEADTemplate:AddScoreTask( "Failed", "Failed to destroy all target radars", -100 ) -TaskSEAD:AddScoreProcess( "Account", "Account", "destroyed a radar", 25 ) -TaskSEAD:AddScoreProcess( "Account", "Failed", "failed to destroy a radar", -10 ) +--TaskSEAD:AddScoreProcess( "Account", "Account", "destroyed a radar", 25 ) +--TaskSEAD:AddScoreProcess( "Account", "Failed", "failed to destroy a radar", -10 ) -function FsmSEAD:onenterUpdated( TaskUnit ) + + +function FsmSEADTemplate:onenterUpdated( TaskUnit ) self:E( { self } ) self:Account() self:Smoke() diff --git a/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.miz b/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.miz index 0f5cd8705851e84741d15a56a5b9b8812625047d..8877febb9e034e643fc513ba1938de64b454dcc2 100644 GIT binary patch delta 13971 zcmZ|0b8seY@b4XKW7~E%wsptO#aA0C>b(C9uIj0o zp1HdF`Od-1r*7~?0PWKT0oJTvqQ9i|F)n^{>t$K!Hz4j6)&cZ_h5Uy zd00X?zE|C^7=K?CTL(n=uzg*a-3rs=wyJB-@gV^}PwrLM zxs=!deNH4znl!(Fk%HPQTnm~r-Jc#mk=NAJD#Z*N6O;e;Szsuvs@sW!%deX6z~fV! zD5X7=RG$NqeFjRCXN&qu%A?VM*yy5L)@2Jqs)!H^P1A7mkR-&yw)j=VtyNX`30-TwRWm4VVTg`4SaH@oB%Zms(<=zvT9L;_@R zev?f){ijWZ1Y}*r#)%=Sx)^)MLoZbnK!qHth<=isx^6W87dq2H613Q9T|s>9T4cSg zqVF~MyRvW9hLk*M5-5O_GANMk@EV+_z~w^1hrN8qavS2>?J~> zQyy8*0G%zgFa!xAeIwz*X%y`$_Vhp~uRSAPpB*vqcjaRVzn5|p|9T&sL=8rFWb^>~ zAUt2GntfO!^JQ_bJKrBeQ;^nFvAOQ+#x+}uRRzO+Vn!GiS@2FYA&BBX73LIP&P)DE zW97#PVoa$a6~v^^FQ5h`1b!KI_)d>g3VY8~v_`M}4)=N=y`IEZFb0;e?juqx$@)r>hO>6b46^SRAZHor2Ym3*_~keug8e6gxtpf|6>*HM&3 z129kA2%7xfdsJ9|5A{%J+Pg|O8{7}kCj8qdIZw+Z{kNzeeo{nD$2I{1Vs;RlgG-7a z@TW?Cg@S*L)$~PIfJ!&@kFKdYY88;aeSE3)hwdu<3c91F1UYJVX_hqXBf4P(HH4H% z3R3jTri4{Daj1h(9&9jUwt3DVZz)Qzw6WY?%s|wF*(ys0dTUOKzH_EtugUt!&#)1> zPlh|9!(A=A+(92G5WXu_eltM~O^0_5ph(UMsLaoUtQ4jNW#t6``wPL7ZunMd;y8HD z5TyKlmo8H+zgGwT&bD9uo>=P1`A^N7g%p}mbGg1Z3^jgFHtXt{jH*{H#Jbsd(!Rc~ zq6Dl%_5%rb9vMvz5EMp- zi(g?)#BxP7l(&x}D?jlkhgfqzY`kL(?fPp;ZP}ut8ugd)U!tt|Ml*$${ti{s)Y5F; zRuIq4e7lQ~;WT*A+)AXi?mt+Z>L78LT4cLnd*a*>kObo|m~6*!06CUquq}b-)okTB z{(a(V6ftp4lrT#*g(v|+NXWD(ptbU{<3yg!!Mt4E_9oH&UN%`?QmoM(a_o-00F{x1 z1BgnZ{UASeweJ~hHaz=@a5^K81?HXYIT1?1u;6+sv)%PFd6_RgQ`@$K-cZWFJNrN9 ztgvzs2qA>tV(|3g0V2!;-N5KTBZNwrK+Qg(Bdh4n_FyMO7WXo6k^J3rU=@Bd88Jz} z?1AbDcCq`F#*sjwSI2XMC7IWlkcY$jp#itsk9x7GXgIz|6dxk110n3`iWPPBVuaQi z`@CJ;0g#m0gIdogl^i@NP-gJn%f~O%i}oW?qlpIWM>4=Ny9KDEXT?2bu;^J~0qjlJ1v zxGC{Gv8DH|&%}kUB=rl#G>!L9=$zNGN1|@=nnO|&O!I)&<)2i846tBt_!^c%xP~&J zvD#cq>@^%>$m56r)H-uNrQVplNB?1A60w$GCDJ@J)fM3%W0-x4K;yk5TAVA~wCm~B zUmbQeZtxh-3<$c}{MvCY=NQwu%4{X-WxRL8#TL_mzy#AKP5%&oC)u4vO7);NLgild zQ>nZ2%TKo?^Ibm<0`oi1VCe0fkQ!|-XMg|Kf71V$RdnMv`>A7@RM!OqLG>v6=!?1p z`AYi5?~h-g4-7cQfdh}AT7u}q;tPKjN=b?n`jF?w^e6HWRij;{;V$kt1Zfl*ou1z_ zLkrxZh%|gUvjuf>pthd7W64@FeA4)0{_UL$T!FzQo0#(5xY|K|fSU)e5z8~l>Si)% zxfQ`Uo_5)f&>?k0l7h6Gk!W_CGAfN8f(bD^nRy2p>BE<5o!hI^{m%jy z5@9k7s5|O|Ly3hXT#sGB(+_HJf%uGn^73$8nw+*I-y3HgMr2xe!FWxWu#~-y^3jEq z__w$J&U8+v0iXGJs%uiuJEsz8b^A8f%c|ph)y3I0Jt2OWuOOS$S>RQoZTh3HYa#{a zfU)_m^-^L4N<_b_SqQ09Axgtg{_`}`k_Rw7Z8RTDq9+{F9hkK&ju8k`NGK@Dmxo0glaJXG@X-2(cu3R;GR62Y>~4 z{=HuNc*q#=LoD?bRG)ZERL++hV409G9U?al=rnjpGU#DzmO1>h7k}p3+PM)1n9R-1 z^)5p1;MsigWc15-2^XAzfx6UFFK!g;j#gv$?LuABUXcMFR@uO#eF90IHwxy>Hfuz; z65DM`;It~9!oVhnnQ!ut4;*XzsX9}>KVmJPd zq7&zuoQ(KICcEHQBT3KuaXy|SPpwOrE}-`nFM)o;0|M4@;RjC|0s^;M6>#3DWvLev za$0&4KOCfuM&RH+62YLw!QSX`s$Q*h0G11qsy@TWbS8@rFVP&#^l;WP?MeJcJQ zs^2=@;X4*6#J-7qhpQlC*=`{6iyB}iR3M^!*~8$d)i2g`mxG<}LFF1dv<;AaVS5vF zO|O}_6Rw`RD(NQF;!S7eX zfQ#KuwsrMrNyoWx8)WCq0=F+fE|)I`9uM^!pWdkkfrw+cYO;Vvx7^%XR{xXjC){bh z#5A(M@doRQ3c9oH%8Tq~VI8PnreqlolD*R};`tjvzj z^Be>fnA^i_@KQeoi?{hvYDj^p#r8j9TW>WhB z<-tpj6Ke#k&ZxTSBBR1pvnHbk3(&EPocVd4E2~ns+D5XU-hY@~RoKMGQYHD^>5CtG{zSXE)H&@AE=tw+;>3H-Q_c5q^1+-I*UJ{1*cu9AmmOC;H<` zqd0+BEt#SWVoqfhgXsdQ%wt6d67{$63vSb%4Si%&}Xcb4qMBu%%w&uBQ>-HGc?DBPgdMUs?)@j|Q4I~=hxO^*o z`z-C&5B);=s%`pX(th_eCiwLNWCY4%t(ZjdB`rQ3wil7#KGji=eH=~Ntrs3N$p?7! zW4>JFGF4YIu0QPd0RwPBH`eVhy{M9+X^2~a*z1B@_U@nM+aDu?+n=c)UV7JdUNjx< zCmn~~*SfXtbK#)v|k{v6s zeZ3@aU0tuW>fA}&r&UT#o^Dh}h_|g}Nt=ro>*}GaMIQNMw!@Ci4@&Sp`|0>?KGhi5 z=^fS8^@8I~?JNI2oqVS-Ym0!@_&zyx^Aym&!Q{?`|8-z`QnfKYN^HaO-Xwm?#(;M5 z;rwI&O;ihai|PP#@Lq1b23pr&ofil^qAx7f>36@!f4pt-8?RAC&r{xJw2DvDCzGo+ z%Whn50qutR^y@qh@fF@?x^X+V&Fv`ej;eXt@AAAWmWk-*8msz2XX6o&$^WPu`jOSF z)7IP0|D-`@-sup;cXX*N=x#23<#QvHky>uqSx=OQYY>Cp3-E4<8>3B03W5h@t5N&u z;xMdz(zbA;qh0*L0dq4)pl+tCOM;y&Z#TbX#?nw@{DVT>*U?217on^2c*txqwyKh7 zZKnNW`uMur+4mx$;v;EXkc!I3KZ8{GamavqiF=k2vs9UlQ5BP#f)-po zKe#2r&eUL~FRHn+yGl~OV$l?Nw&K178$AG0V>W4bV9&WTRo&^m@J+v^QlfJ-O zZ~NxJO})2_Ea-ifjrZ<@vWhYJYV`K-fhs^ZBQY-6DAg5OY+t8we|ErWf5z`EWB-)n zq}Ma%y0o^xq@C}A0uKU=ilJN-@YrP9c)+)87!L}0#@ci{BBzMspzs6MNzxCZBKHxvzH2L|1e6@bocz@Kl0}t(+_3oXe_58mv_xU zRd#*Sby;)h(Je9ZmjE$ zaZ!3XeiWgw*f>i8Nh2>f-dqRje90Jr3jE)l(*5#A>pw`Q@zx;QUwm01(21n!&ITWc%__ctkhZPyo2Iw>_& zNCRyVrN!zzseDFeLBpXIi;Xy3ZDblU=AOp7a-;$=*V-(BYbF&482+6px8_?4V%-yZ zc+GOv;?o-Rm@?Sm{u_GhXpA~M6DSH%)02YfjD~)VcwsXJXnH8C0^s&1@*j`B@dy^f2`pD&locm#cxG++xr- zA&n+KPb5H@6aC?#NbKC86g+bGR@#d;^HR5wW3x12RW#Tdstt70AzraAuscKWjW z+G*N|6gexDj{2-5UJ<;99)ij&jSb~!y>nX*Ke04`TBEEBW#S(zAsAfF8eDZt5KZk5 zLk}G;%C~}*SDj^Vn`m#FDaZwF3iUF{)OlBm@7>wj;M?NQ;o z>~$KjYRz7ETH*7W?j|;$2~$t{M2$Lm9mq7yP{$)74Dp87w`$yb->#;GIy?x4(EXu@ z+b(Z`3u`rTfV5vV1x6XBLL^LagKXa8A#-BejiWuSBVl*jP;}-WIZXIMs6VV)5b)j8qfVfDU9_R*d!`KoUT(8KCIz((rCnd~xiX{M^LC<9)o683y}G?(=C~nZ3~%b?%gV2v zSFMXQh4dYrEKB$D(-JuU2u6>eMA%L6wjHao74eU1WevFh@fcu9S^_GE3!h;O|cI@-z#qxCt zf!Ys|uHm}47EN@XbyT^1Ysq|4*hj_io;=8}IJ>w*8LDz1tw>eV;$bSV+5B2L(mq${s##=*2@n!>m7_t-EWW#h;y2$w>aaKEtFBc7woUeFcaQ!a zDdv%eMcN5=YffUBJXM#}&Nkq{>b^p29oD4RaFo7y@TgPrw|re)(LuYvYO%{dGDHgj8B9iR_~ZsZY8LH659*U~-vtiIbx zVU$h%=@?75#yiv$s!RbiVHZ@2q1Q`*n?M>d5X}uXZ!*kndx;S2mb^<$`w-N)J8QgT zZ4N=kaW^ zt?6MKRA;>c*o>`-d|dC)MDa8yy$b*L$eu8=?NZzixG^33B!I5@lDP4oO3o*v-2`3q zl%40=iLfw=I!=ITUBg)ei${NU1N}8=9r>d~8NHjED;E@C&3?q|18n30fj+)di8e7? zH#Y{<`*uVII4&7dT+azOsBakCV^QtgT7Ov!Ik9`3lCjT;MU=6&Pa3s0*ElggF8TC( za=ST(whLH_C~p2fpqVpje;vB3flhfW4c^^u!l&c+F;y?*tv6Z9uk3|3+x1=E#2Kab znPZo<5Ab=-O!4_=N12A0DfXu|hS$fFkQ|32npbaNCuP1~qCZLbdj^DCY2rKYnK*1- z-ax6q6Ku2s#YQXd?+`RhbetkCso=khv!6RZG{Y+vxM+ch!B zx%!!k_3|f~v72Ss!_C>!v{HUpwL!z2Q!#C4SrFjN);)e(oy#cOlHxQSb7PjDm7S^O zxSfeHM}g#RM^;Mc176t{{(Mm^>MRlTDfxnLn07q=>$xN_1o2_3EpSPalZurMO3Zj>YoTS`T`A8 z=t;gyYtvNa922n*uh#pn*53B)-^!C?klZ`&C}8bzGIpR50-eQ2fCoo&oMn|(-M0#} zp#%{S)GTtF_S!OA{?$}=0T&+5i$m86&kege$rZCy$AUYx)tgaSySBtJTc=H6D*4v4 zyQ?LN|K*2tQ-pEn^j!H)F4NvY~fX{?XCWIg9&xq1Ld_O5kEwjn}z$HpfoW zG9e3RcEe!4UCNVzzWzoA+3+kteC>=Vci-;EdyfUB5#;xFS-x?yspr}x|5RRfvXpJt zT)6QBRcftlAPR*@*+tHM^=)3w8|__%^GLd+^>kQ1qq(jVf3aR&T?1@7tED^Hgs+}b zREWcvYGuBGobk*(okugtc4d_H!ExIx<@tcE@8QLw?E2)rQX!CwyPI<|gqzeDds7_} z>g8Y?8KhahCcnB1l3m%vQH^gjUD1?2R~-(GdbB&g{A+h5BbJ#WkE{TQax+EV;sZMC z>5Xo_x0NbkmwjNhdH}7?FGe7Edq$Jdd=6S0bnH5pf`jHUT|Qq|+yg^8H*1b7+8Obw zR4q$)>UT1#YI)QL z1S?}OZjdUB#ozybhHe{q)PceLRWTSC9i1^4*%a#Ju5HMubhNk!iYGoODPZGEm;NDoFekBI>h6+#>r;B}klLhQ|6i`d2UMNKpEj zfl?W?I8sH>e?A!e=a%NTTZow7Zv8)phUdPm9vgWyRj(g;G+j~*;30Ubve5(`NQWVOJ(2(zPjKWF4rdR8kOME62^1AXBu3VO*KEz*V&KGp^hWdrwBQ4+Ua@r{uIVV2sT6tt*jk4o>8u4cde5rPZHYQQ#;kKDpYdf ztq6i@_Cx8$H#*W|MC9ZBuSOS*4Fo4u&w=;vZ?$e|>mxx1n`27mu$7U}` z@8#<;B?r2DX~TUF<^7KT2{19*d#<1TV^V&WX9Oje9`kPnW8@^SO6jciI^3mT*`nGilpn%y-*~b51{cXPBeu zQ?UVlF6T6{%&>$Ce6~igk$a2zjC2*|1&1>*agL)vKmOt;uv4dM7|2mS>;R7#Bjj*9 zSUZg!pja;iZ*3+Yn%MPW0#B73sVV^#S!dRV?5BSgM_p6Ar}G!hDVA9Y;Zxz?;`m9| z=j$2e1Rs?3*P#N!(b1_L{==Q&vG_(R$g`l;tyB1|k|GSt5U!F8l7?iAmc+D9WTY zbD8GB!SWy?)}ghRN}?QJYg2@v6f$7gVjx4`{$5Yb?(%zBtUjF~!!K*32kR3`pk6dk zC#y8dA*nQi>!%%IDjce%oRF}BQsIi5rM+e|{9?IWLDH8c!>LT3_Xnrh(sp1oq*4m; z>Iq1?0^-)6_8J%3B87Gzf6y)yiqy_#gj*UL+n98zn}(bArVtr&uL|L%#;`~AJaM{Z zape~=QY%`@IkXAI?(~~rr$6Ou8t=Zy_Q4ew5pyY9ibDhkke_TP);pp@97Z^DFuEn= zzyTeW?6%L}X=T5N>P9(nP%Mwv@^RR#kVHJwfCrtOd?*8UxhxIyL~*l<3a-zH-xE^T zcpU*_?jLz0FRnacAy6%w5~DDAkur!Yj*8&HFCzphw(YSRxzfi&S_;qN?vXI&q5C-D%eOt|I#IFMmsY`1X- z=-?YJGdYhy>`1Ht(>)ot9lwYKoR+|Bx=V`54X+&yOAsqc4^505QP01D0Zp|MGJ3Tj z0|dS`P*FSx2jonr5$onbOM|G+VH6A(;S2?Hy}4NZzK>uzSD_PgeM1-3o)r*}0QdYm zx#;KKwKnG9udW=AE@X)^d*5P}pT4&P+$YiEF#63_0ahIa<2Z6kf(|0}zy=RZ_*Pi` z>#xAD(yEzLCWG9K>>4MU+Orq3rrQ#J@(lhNgW{}m(Fkiu`97Hg!1P*KbS-o~&3 zu#QAi1GH8FjWLP5#@iLwoyH%AT2#b9xjv{`3R%BGfP}eJeo=Kel zagp0o%Eixav*MzoKApqI)PX4h&dKs1+w#S{qN_1LqAcD9n53}XABN)?o)+c{)CyV_ zDzx!mqiGIyo2xX-_}uSzEQ2uYJCxHq*j?&14gMi3!VxSw8dP zLY!&Dd*g~NEP@03Giw!2ElM|lEoeD+LgKt_$$?8_6`3b>aDkG=JaToVRA~{clF*w{$&!A8ZBUC#NIGYkxS-|kambWzg&g;KLUylZe zHzwv}Cq6L(Xox%{{(w;c)3RyjmEaY=tvav}&44H6U)cjs>91ft9;7@TjEHr*xG{t`aSC|*F!;yFRTk+)L zC2d{@1V7o%Gct-RaL|wg8Egmd8q?uivgXPLMkCN?m6M@J;K|cN|LXMH>2M|`?S#u` z@DM{CXXMjWYOC;;ljk`T52%j)iu&{gE2=RV9S*E?L)>q4iINpfbDsxiI=!3 z)>4Hhvb4_G{}WvRrYbE{(PgCm3rJcFEQRG=q*f5SiGV{a^5Gntfxw+^Rd(i36Igf& zSJDEFAzzhN9X7!L6Uc8EX3+{uJh3rAGTX6NC@J_$8>J)=KAZpnM&6)>){oek+dVmd z|KgEE;o}=)0e~_VL-lSispenZNH1S0;TuO4xmFE8RVcXunh0X&x;PgcPc~Tw-wMyM z2@CmF%7ua(&o`G6g+(Ib!i!nn(u*JGi+$&4=Y;ulI0(>&>rrp2U;6=4L(vo^cvKE_ zPH7Uj6^&dXv(u-)@6e?kek~yLL@8|^nn;6znkB~PKkVt0M+j5mvau(QI26qq!N7n^ z|DTweBir}Y9q}^0sd2dq$s{IJo6oyXO7e?H)BR=EXt{ik zsh;p$jI|%!^HGG7pE4o8^D%k58FLIORx}*E1dc=T!bkxkdIA5v$8?2=0SRP-2_K0Z z#_FqFyR~Kti@J9STmX&z8QJ#@4x8gf7X*drr>TMjV1~z^g9wQ>>`eKxo0BtV-8x$Q zrZ)zTQ%1ee)}=r}YL6xjT7ui&hZ#bKViOiO;=(8q_tWFMm;c<1tQ{TN5GzuWWX}1j zl+S?ydxmgFE}V)HSV+Ge_Sd$fAI-haS5|3(Ez>D|ju~I$i zHh@vWz^Q7%W-+?hoy>Tl_51x4NUX9pQ&1>m0??BB(_ZbvQG=`L=uZf-_EJo6l7bKW zzRz+Z{4BIYi;ZcFD=X(n0x55VARQIL;Bgek#3-}nHRLLO5E>Cl70ZnS&nv`GFGmEX z(Mxy^1yR7Z4^n?6Am*L6eP`d7$v7&wiBc2Zryb4aU4EgFp7MHX&$I)%ay}G)gBc}U zz^F*PbYd(lXr%50kDY0Wn?8*{Ekj`VPesTq9OX^|e(r03O$&nmQABZa{t@o^=*^;S z#7HVyP`_z?25*#z6v#p(#Sx2uKBn6iU{; zmIe)=5rq3M5{3-$xG@`yKqb*{VQ(aKz$VwPtc_7EW`L6YBgT+1u;M!@Y!8m7>lOv) zu=OB%BXz;N{OY-U!IT*vShkhq#vlqAEJaY*R6ENh3Bj?)fT8rv;mfQi0*V#Fo@8un zR4pCoA$;^IFD`-*?fRhpGVlnFM{q?>F6)DL(KzT=K>EOk<`vcW`g3e zwSJL_rj^6wLWfNeg8VJX$iF37m|#*YJ&GD@zTP)(;C|!A_)z-lj|O4^OHk!~kduWm z5$Sq}RJM_Dcs82d*1#}nL9Mq6auvj)4&h$lcarD(?ajf`ZClS-Hv51lNlTPD2-^?3 zi=685KeExFs9c|+k5-T?TngN9`=0{2%CjNc`Pp3jO_5p1H#smUV7hMpP3!iw3cV)o zs(%EhfYwE=$F5Kdi1tv-yOoCqaI#nWi|!3&6u`prjiQ48kVGGj!~d%kQAt1o)U;F@ zXf(u#K>8>jMpXYUk92ZSuA1IGTK0p^V33Lj)-nFyQI!*cz^I{&iK1?)8(b8?EMtBK z1>n8444x%rhRBD^B{x>yw&LXbmK@}CAwLaHbigVj!9(LpMk@CujIbK{BB z9ytWbGA5F#J(Sm0pujygVp0KDC&DKWEe_MpnI&0;jKHOKMj~{kXSEK-K-lN#WjMQ+ z_xX_PnJP1I>xd87cPvV>D9P=c!PbzBJY*z~6>o)#EVL?&Bo7Y1xsXmHI4M`$eY{NQ zl{d06*gXUlDj^PHFuFOjyDXD_Kqv__pcrOZ+XURn{^-TJl*f9~i5Vz!mPiM7-;ZFd z*u+SMqU`b)^HVzfbW8sX!#td5}!d-6*t?Gg7aXC}ibr~S`Ymsz`I)h1*D zpNrBNHPtt|LNEh1ZI$6^4 zQm*OlDU-_NnsWvJv!6y|#;IgpNdo|g3(?R@l)Y`KV$Q2@EYLNBFZ57~S(6mUK-o1vwUnqT(Poctf!SV`XX0h@=$q=*C8J zc*Es*KKy#l1zQGush8@YLRdDCFrzDcC;UglS!HSVpWA@51aShjKWFEC6`L4Xl)|2Y zgwO>-P#nIlz{>R4$ebrie_Ene6h--8`+d?{rrt?>;}n%o_}|H1#{06So2Kl4C_jQ- z3CWlR#}A%8u}m@V;I~Q)2y@ zRTPgRbz~m&$a+WpSp;(0Y@~r|dfU&BGg%^WZ-RO*@Ey2JGElC- zylKr$c<6tB>|=)yl}Af#h?$EqdcTD+q1n6;x7{p`UttmUH&^oi$CYI-C;Q~wPCQ8o z_2Dz4k{N>o0et%=t+e=*5j#mK5EMVo0Qgx{5;jTD(jP<=kSK=9HB_XtLTSs|o0mb; zuIipFq;RSNhreeby^0>IW&c*I`T}u~;hIe}F-j+Cf(gh9Js`ATT8os8VEwg*HkMD6 zrbkzqzj4>}KirKC<$lj(AsN#b1+A);sizm`Y(f)CUKA7iWilGPgtNeGj3}kRY8VrY z6O_7GLQ9}YETJed!ICvwpJ&oQ&mYq4fMUqMG20&l)LxxTMi1Cd zpu~@t?tHjORwcr8GN zjGW=;(?jIS+bcJMUkV?x^q2UHxXQO+rO}Mk!H_o3#Q*!L-dSSO$N0;zz8GY*S9Z9} zbn;(5L1B^lw^OeFIR!lL>`s2j`O%ZISRRfp)Vgr{rY>zuYA}0FL!d+iz6YnUTksEI95nJB#7xOpLm^>_oH)iA%EHXkXYeD5uP8%@KNg6=AP*51K z0O)$+gTba-=W7?@;(A@4^UTMr82@oHLAp+L|Sb*fCiQEjt6NMq3j zNL#Q!rIJ!cql(EMGIZGH4ef>18ExS`DKLYP7NT<)6ND6R%(P|lP&%F}>_OjCv}wVB z!f1hORoT%B^c#bD1{Z%ejkxfUXP(i}#9~)9^5G2R^BGKJwXr}F7I)zDeQU~DKi4II za_R8*cky5lp!gB@_20)u;EJz1x?Gb1F(A>5#;9}OK{-1*7pL;TTPlSOnNsoZA@qTj zU(bS%)9>h4Xy|L|gDp-4wxuNH=DDdpZ%X4xBA5g+noyHN-h1!pI>HO(!Y?)H=Cf?6*koKapd)HWpV0n`^t!z& zq$8N<_p8umAGq}k^@WA0UmnGfqvS|pKbyMD5<)!t>+A-VUM-9P$Y`+?cc delta 13428 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