From 1bd61837f2a18c4ed308132952cf6aa9e2ab6d83 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Tue, 8 Nov 2016 18:38:30 +0100 Subject: [PATCH] Updated Task Processing logic. --- Moose Development/Moose/Core/Base.lua | 23 ++ Moose Development/Moose/Core/Event.lua | 278 ++++++++++-------- Moose Development/Moose/Core/StateMachine.lua | 41 ++- Moose Development/Moose/Fsm/Process.lua | 11 + Moose Development/Moose/Moose.lua | 2 +- Moose Development/Moose/Process/Account.lua | 30 +- Moose Development/Moose/Tasking/Mission.lua | 5 +- Moose Development/Moose/Tasking/Task.lua | 9 +- Moose Development/Moose/Tasking/Task_SEAD.lua | 2 +- .../Moose_Test_Task_SEAD.lua | 7 +- .../Moose_Test_Task_SEAD.miz | Bin 26171 -> 26271 bytes 11 files changed, 233 insertions(+), 175 deletions(-) diff --git a/Moose Development/Moose/Core/Base.lua b/Moose Development/Moose/Core/Base.lua index e3b6ec8b9..9db404093 100644 --- a/Moose Development/Moose/Core/Base.lua +++ b/Moose Development/Moose/Core/Base.lua @@ -192,6 +192,29 @@ function BASE:Event() return _EVENTDISPATCHER end +--- Remove all subscribed events +-- @param #BASE self +-- @return #BASE +function BASE:EventRemoveAll() + + _EVENTDISPATCHER:RemoveAll( self ) + + return self +end + +--- Subscribe to a S_EVENT_DEAD event. +-- @param #BASE self +-- @param #function EventFunction The function to be called when the event occurs for the unit. +-- @return #BASE +function BASE:EventOnDead( EventFunction ) + + _EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_DEAD ) + + return self +end + + + diff --git a/Moose Development/Moose/Core/Event.lua b/Moose Development/Moose/Core/Event.lua index 694099d59..e752a7d3e 100644 --- a/Moose Development/Moose/Core/Event.lua +++ b/Moose Development/Moose/Core/Event.lua @@ -81,7 +81,7 @@ end --- Initializes the Events structure for the event -- @param #EVENT self -- @param DCSWorld#world.event EventID --- @param #string EventClass +-- @param Core.Base#BASE EventClass -- @return #EVENT.Events function EVENT:Init( EventID, EventClass ) self:F3( { _EVENTCODES[EventID], EventClass } ) @@ -96,29 +96,42 @@ end --- Removes an Events entry -- @param #EVENT self --- @param Base#BASE EventSelf The self instance of the class for which the event is. +-- @param Core.Base#BASE EventClass The self instance of the class for which the event is. -- @param DCSWorld#world.event EventID -- @return #EVENT.Events -function EVENT:Remove( EventSelf, EventID ) - self:F3( { EventSelf, _EVENTCODES[EventID] } ) +function EVENT:Remove( EventClass, EventID ) + self:F3( { EventClass, _EVENTCODES[EventID] } ) - local EventClass = EventSelf:GetClassNameAndID() + local EventClass = EventClass self.Events[EventID][EventClass] = nil end +--- Clears all event subscriptions for a @{Core.Base#BASE} derived object. +-- @param #EVENT self +-- @param Core.Base#BASE EventObject +function EVENT:RemoveAll( EventObject ) + self:F3( { EventObject:GetClassNameAndID() } ) + + local EventClass = EventObject:GetClassNameAndID() + for EventID, EventData in pairs( self.Events ) do + self.Events[EventID][EventClass] = nil + end +end + + --- Create an OnDead event handler for a group -- @param #EVENT self -- @param #table EventTemplate -- @param #function EventFunction The function to be called when the event occurs for the unit. --- @param EventSelf The self instance of the class for which the event is. +-- @param EventClass The instance of the class for which the event is. -- @param #function OnEventFunction -- @return #EVENT -function EVENT:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, OnEventFunction ) +function EVENT:OnEventForTemplate( EventTemplate, EventFunction, EventClass, OnEventFunction ) self:F2( EventTemplate.name ) for EventUnitID, EventUnit in pairs( EventTemplate.units ) do - OnEventFunction( self, EventUnit.name, EventFunction, EventSelf ) + OnEventFunction( self, EventUnit.name, EventFunction, EventClass ) end return self end @@ -126,15 +139,15 @@ end --- Set a new listener for an S_EVENT_X event independent from a unit or a weapon. -- @param #EVENT self -- @param #function EventFunction The function to be called when the event occurs for the unit. --- @param Base#BASE EventSelf The self instance of the class for which the event is. +-- @param Base#BASE EventClass The self instance of the class for which the event is captured. When the event happens, the event process will be called in this class provided. -- @param EventID -- @return #EVENT -function EVENT:OnEventGeneric( EventFunction, EventSelf, EventID ) +function EVENT:OnEventGeneric( EventFunction, EventClass, EventID ) self:F2( { EventID } ) - local Event = self:Init( EventID, EventSelf:GetClassNameAndID() ) + local Event = self:Init( EventID, EventClass ) Event.EventFunction = EventFunction - Event.EventSelf = EventSelf + Event.EventClass = EventClass return self end @@ -143,19 +156,19 @@ end -- @param #EVENT self -- @param #string EventDCSUnitName -- @param #function EventFunction The function to be called when the event occurs for the unit. --- @param Base#BASE EventSelf The self instance of the class for which the event is. +-- @param Base#BASE EventClass The self instance of the class for which the event is. -- @param EventID -- @return #EVENT -function EVENT:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, EventID ) +function EVENT:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, EventID ) self:F2( EventDCSUnitName ) - local Event = self:Init( EventID, EventSelf:GetClassNameAndID() ) + local Event = self:Init( EventID, EventClass ) if not Event.IniUnit then Event.IniUnit = {} end Event.IniUnit[EventDCSUnitName] = {} Event.IniUnit[EventDCSUnitName].EventFunction = EventFunction - Event.IniUnit[EventDCSUnitName].EventSelf = EventSelf + Event.IniUnit[EventDCSUnitName].EventClass = EventClass return self end @@ -165,12 +178,12 @@ do -- OnBirth -- @param #EVENT self -- @param Group#GROUP EventGroup -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param EventSelf The self instance of the class for which the event is. + -- @param EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnBirthForTemplate( EventTemplate, EventFunction, EventSelf ) + function EVENT:OnBirthForTemplate( EventTemplate, EventFunction, EventClass ) self:F2( EventTemplate.name ) - self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnBirthForUnit ) + self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnBirthForUnit ) return self end @@ -178,12 +191,12 @@ do -- OnBirth --- Set a new listener for an S_EVENT_BIRTH event, and registers the unit born. -- @param #EVENT self -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf + -- @param Base#BASE EventClass -- @return #EVENT - function EVENT:OnBirth( EventFunction, EventSelf ) + function EVENT:OnBirth( EventFunction, EventClass ) self:F2() - self:OnEventGeneric( EventFunction, EventSelf, world.event.S_EVENT_BIRTH ) + self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_BIRTH ) return self end @@ -192,24 +205,24 @@ do -- OnBirth -- @param #EVENT self -- @param #string EventDCSUnitName The id of the unit for the event to be handled. -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf + -- @param Base#BASE EventClass -- @return #EVENT - function EVENT:OnBirthForUnit( EventDCSUnitName, EventFunction, EventSelf ) + function EVENT:OnBirthForUnit( EventDCSUnitName, EventFunction, EventClass ) self:F2( EventDCSUnitName ) - self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_BIRTH ) + self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_BIRTH ) return self end --- Stop listening to S_EVENT_BIRTH event. -- @param #EVENT self - -- @param Base#BASE EventSelf + -- @param Base#BASE EventClass -- @return #EVENT - function EVENT:OnBirthRemove( EventSelf ) + function EVENT:OnBirthRemove( EventClass ) self:F2() - self:Remove( EventSelf, world.event.S_EVENT_BIRTH ) + self:Remove( EventClass, world.event.S_EVENT_BIRTH ) return self end @@ -223,12 +236,12 @@ do -- OnCrash -- @param #EVENT self -- @param Group#GROUP EventGroup -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param EventSelf The self instance of the class for which the event is. + -- @param EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnCrashForTemplate( EventTemplate, EventFunction, EventSelf ) + function EVENT:OnCrashForTemplate( EventTemplate, EventFunction, EventClass ) self:F2( EventTemplate.name ) - self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnCrashForUnit ) + self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnCrashForUnit ) return self end @@ -236,12 +249,12 @@ do -- OnCrash --- Set a new listener for an S_EVENT_CRASH event. -- @param #EVENT self -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf + -- @param Base#BASE EventClass -- @return #EVENT - function EVENT:OnCrash( EventFunction, EventSelf ) + function EVENT:OnCrash( EventFunction, EventClass ) self:F2() - self:OnEventGeneric( EventFunction, EventSelf, world.event.S_EVENT_CRASH ) + self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_CRASH ) return self end @@ -250,24 +263,24 @@ do -- OnCrash -- @param #EVENT self -- @param #string EventDCSUnitName -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf The self instance of the class for which the event is. + -- @param Base#BASE EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnCrashForUnit( EventDCSUnitName, EventFunction, EventSelf ) + function EVENT:OnCrashForUnit( EventDCSUnitName, EventFunction, EventClass ) self:F2( EventDCSUnitName ) - self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_CRASH ) + self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_CRASH ) return self end --- Stop listening to S_EVENT_CRASH event. -- @param #EVENT self - -- @param Base#BASE EventSelf + -- @param Base#BASE EventClass -- @return #EVENT - function EVENT:OnCrashRemove( EventSelf ) + function EVENT:OnCrashRemove( EventClass ) self:F2() - self:Remove( EventSelf, world.event.S_EVENT_CRASH ) + self:Remove( EventClass, world.event.S_EVENT_CRASH ) return self end @@ -280,12 +293,12 @@ do -- OnDead -- @param #EVENT self -- @param Group#GROUP EventGroup -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param EventSelf The self instance of the class for which the event is. + -- @param EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnDeadForTemplate( EventTemplate, EventFunction, EventSelf ) + function EVENT:OnDeadForTemplate( EventTemplate, EventFunction, EventClass ) self:F2( EventTemplate.name ) - self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnDeadForUnit ) + self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnDeadForUnit ) return self end @@ -293,12 +306,12 @@ do -- OnDead --- Set a new listener for an S_EVENT_DEAD event. -- @param #EVENT self -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf + -- @param Base#BASE EventClass -- @return #EVENT - function EVENT:OnDead( EventFunction, EventSelf ) + function EVENT:OnDead( EventFunction, EventClass ) self:F2() - self:OnEventGeneric( EventFunction, EventSelf, world.event.S_EVENT_DEAD ) + self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_DEAD ) return self end @@ -308,24 +321,24 @@ do -- OnDead -- @param #EVENT self -- @param #string EventDCSUnitName -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf The self instance of the class for which the event is. + -- @param Base#BASE EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnDeadForUnit( EventDCSUnitName, EventFunction, EventSelf ) + function EVENT:OnDeadForUnit( EventDCSUnitName, EventFunction, EventClass ) self:F2( EventDCSUnitName ) - self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_DEAD ) + self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_DEAD ) return self end --- Stop listening to S_EVENT_DEAD event. -- @param #EVENT self - -- @param Base#BASE EventSelf + -- @param Base#BASE EventClass -- @return #EVENT - function EVENT:OnDeadRemove( EventSelf ) + function EVENT:OnDeadRemove( EventClass ) self:F2() - self:Remove( EventSelf, world.event.S_EVENT_DEAD ) + self:Remove( EventClass, world.event.S_EVENT_DEAD ) return self end @@ -338,12 +351,12 @@ do -- OnPilotDead --- Set a new listener for an S_EVENT_PILOT_DEAD event. -- @param #EVENT self -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf + -- @param Base#BASE EventClass -- @return #EVENT - function EVENT:OnPilotDead( EventFunction, EventSelf ) + function EVENT:OnPilotDead( EventFunction, EventClass ) self:F2() - self:OnEventGeneric( EventFunction, EventSelf, world.event.S_EVENT_PILOT_DEAD ) + self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_PILOT_DEAD ) return self end @@ -352,24 +365,24 @@ do -- OnPilotDead -- @param #EVENT self -- @param #string EventDCSUnitName -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf The self instance of the class for which the event is. + -- @param Base#BASE EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnPilotDeadForUnit( EventDCSUnitName, EventFunction, EventSelf ) + function EVENT:OnPilotDeadForUnit( EventDCSUnitName, EventFunction, EventClass ) self:F2( EventDCSUnitName ) - self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_PILOT_DEAD ) + self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_PILOT_DEAD ) return self end --- Stop listening to S_EVENT_PILOT_DEAD event. -- @param #EVENT self - -- @param Base#BASE EventSelf + -- @param Base#BASE EventClass -- @return #EVENT - function EVENT:OnPilotDeadRemove( EventSelf ) + function EVENT:OnPilotDeadRemove( EventClass ) self:F2() - self:Remove( EventSelf, world.event.S_EVENT_PILOT_DEAD ) + self:Remove( EventClass, world.event.S_EVENT_PILOT_DEAD ) return self end @@ -381,12 +394,12 @@ do -- OnLand -- @param #EVENT self -- @param #table EventTemplate -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param EventSelf The self instance of the class for which the event is. + -- @param EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnLandForTemplate( EventTemplate, EventFunction, EventSelf ) + function EVENT:OnLandForTemplate( EventTemplate, EventFunction, EventClass ) self:F2( EventTemplate.name ) - self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnLandForUnit ) + self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnLandForUnit ) return self end @@ -395,24 +408,24 @@ do -- OnLand -- @param #EVENT self -- @param #string EventDCSUnitName -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf The self instance of the class for which the event is. + -- @param Base#BASE EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnLandForUnit( EventDCSUnitName, EventFunction, EventSelf ) + function EVENT:OnLandForUnit( EventDCSUnitName, EventFunction, EventClass ) self:F2( EventDCSUnitName ) - self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_LAND ) + self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_LAND ) return self end --- Stop listening to S_EVENT_LAND event. -- @param #EVENT self - -- @param Base#BASE EventSelf + -- @param Base#BASE EventClass -- @return #EVENT - function EVENT:OnLandRemove( EventSelf ) + function EVENT:OnLandRemove( EventClass ) self:F2() - self:Remove( EventSelf, world.event.S_EVENT_LAND ) + self:Remove( EventClass, world.event.S_EVENT_LAND ) return self end @@ -425,12 +438,12 @@ do -- OnTakeOff -- @param #EVENT self -- @param #table EventTemplate -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param EventSelf The self instance of the class for which the event is. + -- @param EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnTakeOffForTemplate( EventTemplate, EventFunction, EventSelf ) + function EVENT:OnTakeOffForTemplate( EventTemplate, EventFunction, EventClass ) self:F2( EventTemplate.name ) - self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnTakeOffForUnit ) + self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnTakeOffForUnit ) return self end @@ -439,24 +452,24 @@ do -- OnTakeOff -- @param #EVENT self -- @param #string EventDCSUnitName -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf The self instance of the class for which the event is. + -- @param Base#BASE EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnTakeOffForUnit( EventDCSUnitName, EventFunction, EventSelf ) + function EVENT:OnTakeOffForUnit( EventDCSUnitName, EventFunction, EventClass ) self:F2( EventDCSUnitName ) - self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_TAKEOFF ) + self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_TAKEOFF ) return self end --- Stop listening to S_EVENT_TAKEOFF event. -- @param #EVENT self - -- @param Base#BASE EventSelf + -- @param Base#BASE EventClass -- @return #EVENT - function EVENT:OnTakeOffRemove( EventSelf ) + function EVENT:OnTakeOffRemove( EventClass ) self:F2() - self:Remove( EventSelf, world.event.S_EVENT_TAKEOFF ) + self:Remove( EventClass, world.event.S_EVENT_TAKEOFF ) return self end @@ -470,12 +483,12 @@ do -- OnEngineShutDown -- @param #EVENT self -- @param #table EventTemplate -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param EventSelf The self instance of the class for which the event is. + -- @param EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnEngineShutDownForTemplate( EventTemplate, EventFunction, EventSelf ) + function EVENT:OnEngineShutDownForTemplate( EventTemplate, EventFunction, EventClass ) self:F2( EventTemplate.name ) - self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnEngineShutDownForUnit ) + self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnEngineShutDownForUnit ) return self end @@ -484,24 +497,24 @@ do -- OnEngineShutDown -- @param #EVENT self -- @param #string EventDCSUnitName -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf The self instance of the class for which the event is. + -- @param Base#BASE EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnEngineShutDownForUnit( EventDCSUnitName, EventFunction, EventSelf ) + function EVENT:OnEngineShutDownForUnit( EventDCSUnitName, EventFunction, EventClass ) self:F2( EventDCSUnitName ) - self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_ENGINE_SHUTDOWN ) + self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_ENGINE_SHUTDOWN ) return self end --- Stop listening to S_EVENT_ENGINE_SHUTDOWN event. -- @param #EVENT self - -- @param Base#BASE EventSelf + -- @param Base#BASE EventClass -- @return #EVENT - function EVENT:OnEngineShutDownRemove( EventSelf ) + function EVENT:OnEngineShutDownRemove( EventClass ) self:F2() - self:Remove( EventSelf, world.event.S_EVENT_ENGINE_SHUTDOWN ) + self:Remove( EventClass, world.event.S_EVENT_ENGINE_SHUTDOWN ) return self end @@ -514,24 +527,24 @@ do -- OnEngineStartUp -- @param #EVENT self -- @param #string EventDCSUnitName -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf The self instance of the class for which the event is. + -- @param Base#BASE EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnEngineStartUpForUnit( EventDCSUnitName, EventFunction, EventSelf ) + function EVENT:OnEngineStartUpForUnit( EventDCSUnitName, EventFunction, EventClass ) self:F2( EventDCSUnitName ) - self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_ENGINE_STARTUP ) + self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_ENGINE_STARTUP ) return self end --- Stop listening to S_EVENT_ENGINE_STARTUP event. -- @param #EVENT self - -- @param Base#BASE EventSelf + -- @param Base#BASE EventClass -- @return #EVENT - function EVENT:OnEngineStartUpRemove( EventSelf ) + function EVENT:OnEngineStartUpRemove( EventClass ) self:F2() - self:Remove( EventSelf, world.event.S_EVENT_ENGINE_STARTUP ) + self:Remove( EventClass, world.event.S_EVENT_ENGINE_STARTUP ) return self end @@ -542,12 +555,12 @@ do -- OnShot --- Set a new listener for an S_EVENT_SHOT event. -- @param #EVENT self -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf The self instance of the class for which the event is. + -- @param Base#BASE EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnShot( EventFunction, EventSelf ) + function EVENT:OnShot( EventFunction, EventClass ) self:F2() - self:OnEventGeneric( EventFunction, EventSelf, world.event.S_EVENT_SHOT ) + self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_SHOT ) return self end @@ -556,24 +569,24 @@ do -- OnShot -- @param #EVENT self -- @param #string EventDCSUnitName -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf The self instance of the class for which the event is. + -- @param Base#BASE EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnShotForUnit( EventDCSUnitName, EventFunction, EventSelf ) + function EVENT:OnShotForUnit( EventDCSUnitName, EventFunction, EventClass ) self:F2( EventDCSUnitName ) - self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_SHOT ) + self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_SHOT ) return self end --- Stop listening to S_EVENT_SHOT event. -- @param #EVENT self - -- @param Base#BASE EventSelf + -- @param Base#BASE EventClass -- @return #EVENT - function EVENT:OnShotRemove( EventSelf ) + function EVENT:OnShotRemove( EventClass ) self:F2() - self:Remove( EventSelf, world.event.S_EVENT_SHOT ) + self:Remove( EventClass, world.event.S_EVENT_SHOT ) return self end @@ -586,12 +599,12 @@ do -- OnHit --- Set a new listener for an S_EVENT_HIT event. -- @param #EVENT self -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf The self instance of the class for which the event is. + -- @param Base#BASE EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnHit( EventFunction, EventSelf ) + function EVENT:OnHit( EventFunction, EventClass ) self:F2() - self:OnEventGeneric( EventFunction, EventSelf, world.event.S_EVENT_HIT ) + self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_HIT ) return self end @@ -600,24 +613,24 @@ do -- OnHit -- @param #EVENT self -- @param #string EventDCSUnitName -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf The self instance of the class for which the event is. + -- @param Base#BASE EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnHitForUnit( EventDCSUnitName, EventFunction, EventSelf ) + function EVENT:OnHitForUnit( EventDCSUnitName, EventFunction, EventClass ) self:F2( EventDCSUnitName ) - self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_HIT ) + self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_HIT ) return self end --- Stop listening to S_EVENT_HIT event. -- @param #EVENT self - -- @param Base#BASE EventSelf + -- @param Base#BASE EventClass -- @return #EVENT - function EVENT:OnHitRemove( EventSelf ) + function EVENT:OnHitRemove( EventClass ) self:F2() - self:Remove( EventSelf, world.event.S_EVENT_HIT ) + self:Remove( EventClass, world.event.S_EVENT_HIT ) return self end @@ -629,24 +642,24 @@ do -- OnPlayerEnterUnit --- Set a new listener for an S_EVENT_PLAYER_ENTER_UNIT event. -- @param #EVENT self -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf The self instance of the class for which the event is. + -- @param Base#BASE EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnPlayerEnterUnit( EventFunction, EventSelf ) + function EVENT:OnPlayerEnterUnit( EventFunction, EventClass ) self:F2() - self:OnEventGeneric( EventFunction, EventSelf, world.event.S_EVENT_PLAYER_ENTER_UNIT ) + self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_PLAYER_ENTER_UNIT ) return self end --- Stop listening to S_EVENT_PLAYER_ENTER_UNIT event. -- @param #EVENT self - -- @param Base#BASE EventSelf + -- @param Base#BASE EventClass -- @return #EVENT - function EVENT:OnPlayerEnterRemove( EventSelf ) + function EVENT:OnPlayerEnterRemove( EventClass ) self:F2() - self:Remove( EventSelf, world.event.S_EVENT_PLAYER_ENTER_UNIT ) + self:Remove( EventClass, world.event.S_EVENT_PLAYER_ENTER_UNIT ) return self end @@ -657,24 +670,24 @@ do -- OnPlayerLeaveUnit --- Set a new listener for an S_EVENT_PLAYER_LEAVE_UNIT event. -- @param #EVENT self -- @param #function EventFunction The function to be called when the event occurs for the unit. - -- @param Base#BASE EventSelf The self instance of the class for which the event is. + -- @param Base#BASE EventClass The self instance of the class for which the event is. -- @return #EVENT - function EVENT:OnPlayerLeaveUnit( EventFunction, EventSelf ) + function EVENT:OnPlayerLeaveUnit( EventFunction, EventClass ) self:F2() - self:OnEventGeneric( EventFunction, EventSelf, world.event.S_EVENT_PLAYER_LEAVE_UNIT ) + self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_PLAYER_LEAVE_UNIT ) return self end --- Stop listening to S_EVENT_PLAYER_LEAVE_UNIT event. -- @param #EVENT self - -- @param Base#BASE EventSelf + -- @param Base#BASE EventClass -- @return #EVENT - function EVENT:OnPlayerLeaveRemove( EventSelf ) + function EVENT:OnPlayerLeaveRemove( EventClass ) self:F2() - self:Remove( EventSelf, world.event.S_EVENT_PLAYER_LEAVE_UNIT ) + self:Remove( EventClass, world.event.S_EVENT_PLAYER_LEAVE_UNIT ) return self end @@ -718,15 +731,20 @@ function EVENT:onEvent( Event ) --Event.WeaponTgtDCSUnit = Event.Weapon:getTarget() end self:E( { _EVENTCODES[Event.id], Event.initiator, Event.IniDCSUnitName, Event.target, Event.TgtDCSUnitName, Event.weapon, Event.WeaponName } ) - for ClassName, EventData in pairs( self.Events[Event.id] ) do + + -- Okay, we got the event from DCS. Now loop the self.Events[] table for the received Event.id, and for each EventData registered, check if a function needs to be called. + for EventClass, EventData in pairs( self.Events[Event.id] ) do + -- If the EventData is for a UNIT, the call directly the EventClass EventFunction for that UNIT. if Event.IniDCSUnitName and EventData.IniUnit and EventData.IniUnit[Event.IniDCSUnitName] then - self:T( { "Calling event function for class ", ClassName, " unit ", Event.IniUnitName } ) - EventData.IniUnit[Event.IniDCSUnitName].EventFunction( EventData.IniUnit[Event.IniDCSUnitName].EventSelf, Event ) + self:T( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName } ) + EventData.IniUnit[Event.IniDCSUnitName].EventFunction( EventData.IniUnit[Event.IniDCSUnitName].EventClass, Event ) else + -- If the EventData is not bound to a specific unit, then call the EventClass EventFunction. + -- Note that here the EventFunction will need to implement and determine the logic for the relevant source- or target unit, or weapon. if Event.IniDCSUnit and not EventData.IniUnit then - if ClassName == EventData.EventSelf:GetClassNameAndID() then - self:T( { "Calling event function for class ", ClassName } ) - EventData.EventFunction( EventData.EventSelf, Event ) + if EventClass == EventData.EventClass then + self:T( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID() } ) + EventData.EventFunction( EventData.EventClass, Event ) end end end diff --git a/Moose Development/Moose/Core/StateMachine.lua b/Moose Development/Moose/Core/StateMachine.lua index ba8fb1261..fd353d464 100644 --- a/Moose Development/Moose/Core/StateMachine.lua +++ b/Moose Development/Moose/Core/StateMachine.lua @@ -251,29 +251,6 @@ function STATEMACHINE:todot(filename) dotfile:close() end ---- STATEMACHINE_PROCESS class --- @type STATEMACHINE_PROCESS --- @field Process#PROCESS Process --- @extends StateMachine#STATEMACHINE -STATEMACHINE_PROCESS = { - ClassName = "STATEMACHINE_PROCESS", -} - ---- Creates a new STATEMACHINE_PROCESS object. --- @param #STATEMACHINE_PROCESS self --- @return #STATEMACHINE_PROCESS -function STATEMACHINE_PROCESS:New( FSMT ) - - local self = BASE:Inherit( self, STATEMACHINE:New( FSMT ) ) -- StateMachine#STATEMACHINE_PROCESS - - return self -end - -function STATEMACHINE_PROCESS:_call_handler( handler, params ) - if handler then - return handler( self, unpack( params ) ) - end -end --- STATEMACHINE_TASK class -- @type STATEMACHINE_TASK @@ -357,6 +334,24 @@ function STATEMACHINE_CONTROLLABLE:_call_handler( handler, params ) end end +--- STATEMACHINE_PROCESS class +-- @type STATEMACHINE_PROCESS +-- @field Process#PROCESS Process +-- @extends Core.StateMachine#STATEMACHINE_CONTROLLABLE +STATEMACHINE_PROCESS = { + ClassName = "STATEMACHINE_PROCESS", +} + +--- Creates a new STATEMACHINE_PROCESS object. +-- @param #STATEMACHINE_PROCESS self +-- @return #STATEMACHINE_PROCESS +function STATEMACHINE_PROCESS:New( FSMT ) + + local self = BASE:Inherit( self, STATEMACHINE_CONTROLLABLE:New( FSMT ) ) -- StateMachine#STATEMACHINE_PROCESS + + return self +end + do -- STATEMACHINE_SET --- STATEMACHINE_SET class diff --git a/Moose Development/Moose/Fsm/Process.lua b/Moose Development/Moose/Fsm/Process.lua index a93a17552..73fbcd076 100644 --- a/Moose Development/Moose/Fsm/Process.lua +++ b/Moose Development/Moose/Fsm/Process.lua @@ -67,6 +67,15 @@ function PROCESS:GetMission() return self.ProcessTask.Mission end +function PROCESS:StartEvents() + +end + +function PROCESS:StopEvents() + + self:EventRemoveAll() +end + --- Assign the process to a @{Unit} and activate the process. -- @param #PROCESS self -- @param Unit#UNIT ProcessUnit @@ -76,6 +85,8 @@ function PROCESS:Assign( ProcessTask, ProcessUnit ) self:SetControllable( ProcessUnit ) self:SetTask( ProcessTask ) + self:StartEvents() + self.ProcessGroup = ProcessUnit:GetGroup() --self:Activate() diff --git a/Moose Development/Moose/Moose.lua b/Moose Development/Moose/Moose.lua index 685876f1c..4b3d81f29 100644 --- a/Moose Development/Moose/Moose.lua +++ b/Moose Development/Moose/Moose.lua @@ -62,7 +62,7 @@ Include.File( "Tasking/Task_A2G" ) -- The order of the declarations is important here. Don't touch it. --- Declare the event dispatcher based on the EVENT class -_EVENTDISPATCHER = EVENT:New() -- Event#EVENT +_EVENTDISPATCHER = EVENT:New() -- Core.Event#EVENT --- Declare the main database object, which is used internally by the MOOSE classes. _DATABASE = DATABASE:New() -- Database#DATABASE diff --git a/Moose Development/Moose/Process/Account.lua b/Moose Development/Moose/Process/Account.lua index 5be525333..7d40a916c 100644 --- a/Moose Development/Moose/Process/Account.lua +++ b/Moose Development/Moose/Process/Account.lua @@ -168,7 +168,7 @@ do -- PROCESS_ACCOUNT_DEADS ClassName = "PROCESS_ACCOUNT_DEADS", TargetSetUnit = nil, } - + --- Creates a new DESTROY process. -- @param #PROCESS_ACCOUNT_DEADS self @@ -183,11 +183,13 @@ do -- PROCESS_ACCOUNT_DEADS self.TargetSetUnit = TargetSetUnit self.TaskName = TaskName - _EVENTDISPATCHER:OnDead( self.EventDead, self ) - return self end + function PROCESS_ACCOUNT_DEADS:StartEvents() + self:EventOnDead( self.EventDead ) + end + --- Process Events --- StateMachine callback function @@ -209,13 +211,16 @@ do -- PROCESS_ACCOUNT_DEADS -- @param #string Event -- @param #string From -- @param #string To - function PROCESS_ACCOUNT_DEADS:onenterAccount( ProcessUnit, Event, From, To, Event ) + function PROCESS_ACCOUNT_DEADS:onenterAccount( ProcessUnit, EventData, Event, From, To ) + self:T( { ProcessUnit, EventData, Event, From, To } ) + + self:T({self.Controllable}) self.TargetSetUnit:Flush() - if self.TargetSetUnit:FindUnit( Event.IniUnitName ) then - self.TargetSetUnit:RemoveUnitsByName( Event.IniUnitName ) + if self.TargetSetUnit:FindUnit( EventData.IniUnitName ) then local TaskGroup = ProcessUnit:GetGroup() + self.TargetSetUnit:RemoveUnitsByName( EventData.IniUnitName ) MESSAGE:New( "You hit a target. Your group with assigned " .. self.TaskName .. " task has " .. self.TargetSetUnit:Count() .. " targets ( " .. self.TargetSetUnit:GetUnitTypesText() .. " ) left to be destroyed.", 15, "HQ" ):ToGroup( TaskGroup ) end end @@ -226,7 +231,7 @@ do -- PROCESS_ACCOUNT_DEADS -- @param #string Event -- @param #string From -- @param #string To - function PROCESS_ACCOUNT_DEADS:onafterEvent( ProcessUnit, Event, From, To, Event ) + function PROCESS_ACCOUNT_DEADS:onafterEvent( ProcessUnit, Event, From, To, EventData ) if self.TargetSetUnit:Count() > 0 then self:__More( 1 ) @@ -238,11 +243,12 @@ do -- PROCESS_ACCOUNT_DEADS --- DCS Events --- @param #PROCESS_ACCOUNT_DEADS self - -- @param Event#EVENTDATA Event - function PROCESS_ACCOUNT_DEADS:EventDead( Event ) - - if Event.IniDCSUnit then - self:__Event( 1 ) + -- @param Event#EVENTDATA EventData + function PROCESS_ACCOUNT_DEADS:EventDead( EventData ) + self:T( { "EventDead", EventData } ) + + if EventData.IniDCSUnit then + self:__Event( 1, EventData ) end end diff --git a/Moose Development/Moose/Tasking/Mission.lua b/Moose Development/Moose/Tasking/Mission.lua index a5d59800e..226a0266a 100644 --- a/Moose Development/Moose/Tasking/Mission.lua +++ b/Moose Development/Moose/Tasking/Mission.lua @@ -88,8 +88,9 @@ end -- @param #MISSION self function MISSION:SetPlannedMenu() - for _, Task in pairs( self.Tasks ) do - local Task = Task -- Task#TASK_BASE + self:E( self.Tasks ) + for _, TaskData in pairs( self.Tasks ) do + local Task = TaskData -- Tasking.Task#TASK_BASE Task:RemoveMenu() Task:SetPlannedMenu() end diff --git a/Moose Development/Moose/Tasking/Task.lua b/Moose Development/Moose/Tasking/Task.lua index 1744c7a99..5f7174736 100644 --- a/Moose Development/Moose/Tasking/Task.lua +++ b/Moose Development/Moose/Tasking/Task.lua @@ -186,7 +186,7 @@ function TASK_BASE:IsAssignedToGroup( TaskGroup ) return false end ---- Assign the @{Task}to an alive @{Unit}. +--- Assign the @{Task} to an alive @{Unit}. -- @param #TASK_BASE self -- @param Unit#UNIT TaskUnit -- @return #TASK_BASE self @@ -463,7 +463,7 @@ end function TASK_BASE:RemoveProcesses( TaskUnitName ) for ProcessID, ProcessData in pairs( self.Processes[TaskUnitName] ) do - local Process = ProcessData -- Process#PROCESS + local Process = ProcessData -- Process.Process#PROCESS Process:StopEvents() Process = nil self.Processes[TaskUnitName][ProcessID] = nil @@ -827,15 +827,14 @@ function TASK_BASE:OnSuccess( TaskUnit, Fsm, Event, From, To ) self:E("Success") self:UnAssignFromGroups() + self:RemoveMenu() local TaskGroup = TaskUnit:GetGroup() - self.Mission:SetPlannedMenu() self:StateSuccess() -- The task has become successful, the event catchers can be cleaned. - self:CleanUp() - + self:EventRemoveAll() end --- StateMachine callback function for a TASK diff --git a/Moose Development/Moose/Tasking/Task_SEAD.lua b/Moose Development/Moose/Tasking/Task_SEAD.lua index 3e6a46e10..bb2669b5c 100644 --- a/Moose Development/Moose/Tasking/Task_SEAD.lua +++ b/Moose Development/Moose/Tasking/Task_SEAD.lua @@ -39,7 +39,7 @@ do -- TASK_SEAD -- @param Zone#ZONE_BASE TargetZone -- @return #TASK_SEAD self function TASK_SEAD:New( Mission, SetGroup, TaskName, TargetSetUnit, TargetZone ) - local self = BASE:Inherit( self, TASK_BASE:New( Mission, SetGroup, TaskName, "SEAD", "A2G" ) ) + local self = BASE:Inherit( self, TASK_BASE:New( Mission, SetGroup, TaskName, "SEAD", "A2G" ) ) -- Tasking.Task_SEAD#TASK_SEAD self:F() self.TargetSetUnit = TargetSetUnit 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 c644de7cc..748afbd32 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 @@ -5,7 +5,7 @@ local Scoring = SCORING:New( "SEAD" ) Mission:AddScoring( Scoring ) local SEADSet = SET_GROUP:New():FilterPrefixes( "Test SEAD"):FilterStart() -local TargetSet = SET_UNIT:New():FilterPrefixes( "US Hawk SR" ):FilterStart() +local TargetSet = SET_UNIT:New():FilterPrefixes( "US Hawk SR" ):FilterOnce() local TargetZone = ZONE:New( "Target Zone" ) @@ -22,5 +22,10 @@ local AccountProcess = TaskSEAD:SetProcessTemplate( "ACCOUNT", PROCESS_ACCOUNT_D AccountProcess:AddScore( TaskSEAD, "Account", "destroyed a radar", 25 ) AccountProcess:AddScore( TaskSEAD, "Failed", "failed to destroy a radar", -100 ) +--local SmokeProcess = TaskSEAD:SetProcessTemplate( "SMOKE", PROCESS_SMOKE_TARGETS_ZONE:New( TargetSet, TargetZone ) ) +--SmokeProcess:SetAttackGroup( GROUP:FindByName( "SmokeGroup" ), "Watchdog" ) +--SmokeProcess:AddScore( TaskSEAD, "Account", "destroyed a radar", 25 ) +--SmokeProcess:AddScore( TaskSEAD, "Failed", "failed to destroy a radar", -100 ) + TaskSEAD:AssignToGroup( SEADSet:Get( "Test SEAD" ) ) 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 c2735ea44a0e5856ecdb23d073f409cd537be205..b1c35b57409162afd574dfc0114fb42996078a24 100644 GIT binary patch delta 11765 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 delta 11677 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 oXT?uCus|dDe>*?_&s5AL3`