Implemented event dispatching for GROUP

-- Created EVT-200 test mission
-- Documentation
This commit is contained in:
FlightControl 2017-03-07 09:15:44 +01:00
parent ef67c82c0f
commit af85399975
7 changed files with 201 additions and 66990 deletions

View File

@ -50,11 +50,14 @@
--
-- * **None** ( Group ): The process is not started yet.
-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone.
-- * **Returning** ( Group ): The AI is returning to Base..
-- * **Returning** ( Group ): The AI is returning to Base.
-- * **Stopped** ( Group ): The process is stopped.
-- * **Crashed** ( Group ): The AI has crashed or is dead.
--
-- ### 1.2.2) AI_PATROL_ZONE Events
--
-- * **Start** ( Group ): Start the process.
-- * **Stop** ( Group ): Stop the process.
-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
-- * **RTB** ( Group ): Route the AI to the home base.
-- * **Detect** ( Group ): The AI is detecting targets.

View File

@ -165,7 +165,9 @@
--
-- Hereby the change log:
--
-- * 2016-02-07: Did a complete revision of the Event Handing API and underlying mechanisms.
-- * 2017-03-07: Added the correct event dispatching in case the event is subscribed by a GROUP.
--
-- * 2017-02-07: Did a complete revision of the Event Handing API and underlying mechanisms.
--
-- ===
--
@ -179,10 +181,6 @@
--
-- @module Event
-- TODO: Need to update the EVENTDATA documentation with IniPlayerName and TgtPlayerName
-- TODO: Need to update the EVENTDATA documentation with IniObjectCategory and TgtObjectCategory
--- The EVENT structure
-- @type EVENT
@ -443,8 +441,9 @@ function EVENT:Remove( EventClass, EventID )
self.Events[EventID][EventPriority][EventClass] = nil
end
--- Removes an Events entry for a Unit
--- Removes an Events entry for a UNIT.
-- @param #EVENT self
-- @param #string UnitName The name of the UNIT.
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
-- @param Dcs.DCSWorld#world.event EventID
-- @return #EVENT.Events
@ -457,6 +456,21 @@ function EVENT:RemoveForUnit( UnitName, EventClass, EventID )
Event.IniUnit[UnitName] = nil
end
--- Removes an Events entry for a GROUP.
-- @param #EVENT self
-- @param #string GroupName The name of the GROUP.
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
-- @param Dcs.DCSWorld#world.event EventID
-- @return #EVENT.Events
function EVENT:RemoveForGroup( GroupName, EventClass, EventID )
self:F3( { EventClass, _EVENTMETA[EventID].Text } )
local EventClass = EventClass
local EventPriority = EventClass:GetEventPriority()
local Event = self.Events[EventID][EventPriority][EventClass]
Event.IniGroup[GroupName] = nil
end
--- Clears all event subscriptions for a @{Base#BASE} derived object.
-- @param #EVENT self
-- @param Core.Base#BASE EventObject
@ -505,23 +519,43 @@ function EVENT:OnEventGeneric( EventFunction, EventClass, EventID )
end
--- Set a new listener for an S_EVENT_X event
--- Set a new listener for an S_EVENT_X event for a UNIT.
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param #string UnitName The name of the UNIT.
-- @param #function EventFunction The function to be called when the event occurs for the GROUP.
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
-- @param EventID
-- @return #EVENT
function EVENT:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, EventID )
self:F2( EventDCSUnitName )
function EVENT:OnEventForUnit( UnitName, EventFunction, EventClass, EventID )
self:F2( UnitName )
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].EventClass = EventClass
Event.IniUnit[UnitName] = {}
Event.IniUnit[UnitName].EventFunction = EventFunction
Event.IniUnit[UnitName].EventClass = EventClass
return self
end
--- Set a new listener for an S_EVENT_X event for a GROUP.
-- @param #EVENT self
-- @param #string GroupName The name of the GROUP.
-- @param #function EventFunction The function to be called when the event occurs for the GROUP.
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
-- @param EventID
-- @return #EVENT
function EVENT:OnEventForGroup( GroupName, EventFunction, EventClass, EventID )
self:F2( GroupName )
local Event = self:Init( EventID, EventClass )
if not Event.IniGroup then
Event.IniGroup = {}
end
Event.IniGroup[GroupName] = {}
Event.IniGroup[GroupName].EventFunction = EventFunction
Event.IniGroup[GroupName].EventClass = EventClass
return self
end
@ -1084,7 +1118,9 @@ function EVENT:onEvent( Event )
if Event.IniDCSGroup and Event.IniDCSGroup:isExist() then
Event.IniDCSGroupName = Event.IniDCSGroup:getName()
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
self:E( { IniGroup = Event.IniGroup } )
if Event.IniGroup then
Event.IniGroupName = Event.IniDCSGroupName
end
end
Event.IniPlayerName = Event.IniDCSUnit:getPlayerName()
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
@ -1125,6 +1161,10 @@ function EVENT:onEvent( Event )
Event.TgtDCSGroupName = ""
if Event.TgtDCSGroup and Event.TgtDCSGroup:isExist() then
Event.TgtDCSGroupName = Event.TgtDCSGroup:getName()
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )
if Event.TgtGroup then
Event.TgtGroupName = Event.TgtDCSGroupName
end
end
Event.TgtPlayerName = Event.TgtDCSUnit:getPlayerName()
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
@ -1170,6 +1210,8 @@ function EVENT:onEvent( Event )
-- Okay, we got the event from DCS. Now loop the SORTED self.EventSorted[] 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][EventPriority] ) do
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
-- 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
@ -1177,8 +1219,7 @@ function EVENT:onEvent( Event )
-- First test if a EventFunction is Set, otherwise search for the default function
if EventData.IniUnit[Event.IniDCSUnitName].EventFunction then
self:E( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
self:E( { "Calling EventFunction for UNIT ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
local Result, Value = xpcall(
function()
@ -1193,7 +1234,6 @@ function EVENT:onEvent( Event )
-- Now call the default event function.
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
local Result, Value = xpcall(
function()
@ -1204,38 +1244,69 @@ function EVENT:onEvent( Event )
end
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 the EventData is for a GROUP, the call directly the EventClass EventFunction for the UNIT in that GROUP.
if Event.IniDCSUnitName and Event.IniDCSGroupName and Event.IniGroupName and EventData.IniGroup and EventData.IniGroup[Event.IniGroupName] then
-- First test if a EventFunction is Set, otherwise search for the default function
if EventData.IniGroup[Event.IniGroupName].EventFunction then
if EventClass == EventData.EventClass then
self:E( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
-- First test if a EventFunction is Set, otherwise search for the default function
if EventData.EventFunction then
local Result, Value = xpcall(
function()
return EventData.IniGroup[Event.IniGroupName].EventFunction( EventClass, Event )
end, ErrorHandler )
else
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
local EventFunction = EventClass[ _EVENTMETA[Event.id].Event ]
if EventFunction and type( EventFunction ) == "function" then
-- Now call the default event function.
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } )
-- There is an EventFunction defined, so call the EventFunction.
self:E( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), EventPriority } )
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
local Result, Value = xpcall(
function()
return EventData.EventFunction( EventClass, Event )
return EventFunction( EventClass, Event )
end, ErrorHandler )
else
end
end
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 EventClass == EventData.EventClass then
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
local EventFunction = EventClass[ _EVENTMETA[Event.id].Event ]
if EventFunction and type( EventFunction ) == "function" then
-- Now call the default event function.
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
-- First test if a EventFunction is Set, otherwise search for the default function
if EventData.EventFunction then
-- There is an EventFunction defined, so call the EventFunction.
self:E( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), EventPriority } )
local Result, Value = xpcall(
function()
return EventFunction( EventClass, Event )
return EventData.EventFunction( EventClass, Event )
end, ErrorHandler )
else
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
local EventFunction = EventClass[ _EVENTMETA[Event.id].Event ]
if EventFunction and type( EventFunction ) == "function" then
-- Now call the default event function.
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
local Result, Value = xpcall(
function()
return EventFunction( EventClass, Event )
end, ErrorHandler )
end
end
end
end

View File

@ -897,4 +897,29 @@ function GROUP:OnReSpawn( ReSpawnFunction )
self.ReSpawnFunction = ReSpawnFunction
end
do -- Event Handling
--- Subscribe to a DCS Event.
-- @param #GROUP self
-- @param Core.Event#EVENTS Event
-- @param #function EventFunction (optional) The function to be called when the event occurs for the GROUP.
-- @return #GROUP
function GROUP:HandleEvent( Event, EventFunction )
self:EventDispatcher():OnEventForGroup( self:GetName(), EventFunction, self, Event )
return self
end
--- UnSubscribe to a DCS event.
-- @param #GROUP self
-- @param Core.Event#EVENTS Event
-- @return #GROUP
function GROUP:UnHandleEvent( Event )
self:EventDispatcher():RemoveForGroup( self:GetName(), self, Event )
return self
end
end

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
---
-- Name: EVT-200 - GROUP OnEventShot Example
-- Author: FlightControl
-- Date Created: 07 Mar 2017
--
-- # Situation:
--
-- Two groups of planes are flying in the air and shoot an missile to a multitude of ground targets.
--
-- # Test cases:
--
-- 1. Observe the planes shooting the missile.
-- 2. Observe when the planes shoots the missile, a dcs.log entry is written in the logging.
-- 3. Check the contents of the fields of the S_EVENT_SHOT entry.
-- 4. The planes of GROUP "Group Plane A", should only send a message when they shoot a missile.
-- 5. The planes of GROUP "Group Plane B", should NOT send a message when they shoot a missile.
local PlaneGroup = GROUP:FindByName( "Group Plane A" )
PlaneGroup:HandleEvent( EVENTS.Shot )
function PlaneGroup:OnEventShot( EventData )
self:E( "I just fired a missile and I am part of " .. EventData.IniGroupName )
EventData.IniUnit:MessageToAll( "I just fired a missile and I am part of " .. EventData.IniGroupName, 15, "Alert!" )
end