diff --git a/Dcs/DCSworld.lua b/Dcs/DCSworld.lua new file mode 100644 index 000000000..5bcb203d2 --- /dev/null +++ b/Dcs/DCSworld.lua @@ -0,0 +1,35 @@ +------------------------------------------------------------------------------- +-- @module DCSWorld + +--- @type world +-- @field #world.event event + + +--- @type world.event +-- @field S_EVENT_INVALID +-- @field S_EVENT_SHOT +-- @field S_EVENT_HIT +-- @field S_EVENT_TAKEOFF +-- @field S_EVENT_LAND +-- @field S_EVENT_CRASH +-- @field S_EVENT_EJECTION +-- @field S_EVENT_REFUELING +-- @field S_EVENT_DEAD +-- @field S_EVENT_PILOT_DEAD +-- @field S_EVENT_BASE_CAPTURED +-- @field S_EVENT_MISSION_START +-- @field S_EVENT_MISSION_END +-- @field S_EVENT_TOOK_CONTROL +-- @field S_EVENT_REFUELING_STOP +-- @field S_EVENT_BIRTH +-- @field S_EVENT_HUMAN_FAILURE +-- @field S_EVENT_ENGINE_STARTUP +-- @field S_EVENT_ENGINE_SHUTDOWN +-- @field S_EVENT_PLAYER_ENTER_UNIT +-- @field S_EVENT_PLAYER_LEAVE_UNIT +-- @field S_EVENT_PLAYER_COMMENT +-- @field S_EVENT_SHOOTING_START +-- @field S_EVENT_SHOOTING_END +-- @field S_EVENT_MAX + +world = {} --#world \ No newline at end of file diff --git a/Moose/Base.lua b/Moose/Base.lua index f806d0c2e..d5b7d43b6 100644 --- a/Moose/Base.lua +++ b/Moose/Base.lua @@ -46,6 +46,8 @@ FORMATION = { Cone = "Cone" } + + --- The base constructor. This is the top top class of all classed defined within the MOOSE. -- Any new class needs to be derived from this class for proper inheritance. -- @param #BASE self @@ -140,6 +142,18 @@ function BASE:AddEvent( Event, EventFunction ) return self end +--- Returns the event dispatcher +-- @param #BASE self +-- @return Event#EVENT +function BASE:Event() + + return _EventDispatcher +end + + + + + --- Enable the event listeners for the class. -- @param #BASE self -- @return #BASE @@ -253,8 +267,8 @@ end -- @param #BASE self -- @param DCSTypes#Event event function BASE:onEvent(event) + --self:F( { BaseEventCodes[event.id], event } ) - --env.info( 'onEvent Table self = ' .. tostring(self) ) if self then for EventID, EventObject in pairs( self.Events ) do if EventObject.EventEnabled then @@ -269,8 +283,8 @@ function BASE:onEvent(event) if event.target and event.target:isExist() then event.TgtUnitName = event.target:getName() end - self:T( { BaseEventCodes[event.id], event } ) - EventObject.EventFunction( self, event ) + --self:T( { BaseEventCodes[event.id], event } ) + --EventObject.EventFunction( self, event ) end end end diff --git a/Moose/Event.lua b/Moose/Event.lua new file mode 100644 index 000000000..6346dbf4f --- /dev/null +++ b/Moose/Event.lua @@ -0,0 +1,282 @@ +--- The EVENT class models an efficient event handling process between other classes and its units, weapons. +-- @module Event +-- @author FlightControl + +Include.File( "Routines" ) +Include.File( "Base" ) + +--- The EVENT structure +-- @type EVENT +-- @field #EVENT.Events Events +EVENT = { + ClassName = "EVENT", + ClassID = 0, +} + +local EVENTCODES = { + "S_EVENT_SHOT", + "S_EVENT_HIT", + "S_EVENT_TAKEOFF", + "S_EVENT_LAND", + "S_EVENT_CRASH", + "S_EVENT_EJECTION", + "S_EVENT_REFUELING", + "S_EVENT_DEAD", + "S_EVENT_PILOT_DEAD", + "S_EVENT_BASE_CAPTURED", + "S_EVENT_MISSION_START", + "S_EVENT_MISSION_END", + "S_EVENT_TOOK_CONTROL", + "S_EVENT_REFUELING_STOP", + "S_EVENT_BIRTH", + "S_EVENT_HUMAN_FAILURE", + "S_EVENT_ENGINE_STARTUP", + "S_EVENT_ENGINE_SHUTDOWN", + "S_EVENT_PLAYER_ENTER_UNIT", + "S_EVENT_PLAYER_LEAVE_UNIT", + "S_EVENT_PLAYER_COMMENT", + "S_EVENT_SHOOTING_START", + "S_EVENT_SHOOTING_END", + "S_EVENT_MAX", +} + + +--- The Events structure +-- @type EVENT.Events +-- @field #number IniUnit + +function EVENT:New() + local self = BASE:Inherit( self, BASE:New() ) + self:F() + self.EventHandler = world.addEventHandler( self ) + return self +end + + +--- Initializes the Events structure for the event +-- @param #EVENT self +-- @param DCSWorld#world.event EventID +-- @param #string EventClass +-- @return #EVENT.Events +function EVENT:Init( EventID, EventClass ) + self:F( EventID, EventClass ) + if not self.Events[EventID] then + self.Events[EventID] = {} + end + if not self.Events[EventID][EventClass] then + self.Events[EventID][EventClass] = {} + end + if not self.Events[EventID][EventClass].IniUnit then + self.Events[EventID][EventClass].IniUnit = {} + end + return self.Events[EventID][EventClass] +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 #function OnEventFunction +-- @return #EVENT +function EVENT:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, OnEventFunction ) + self:F( EventTemplate ) + + for EventUnitID, EventUnit in pairs( EventTemplate.units ) do + OnEventFunction( self, EventUnit.name, EventFunction, EventSelf ) + end + return self +end + + +--- Set a new listener for an S_EVENT_X event +-- @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 EventID +-- @return #EVENT +function EVENT:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, EventID ) + self:F( EventDCSUnitName ) + + local Event = self:Init( EventID, EventSelf:GetClassNameAndID() ) + Event.IniUnit[EventDCSUnitName] = {} + Event.IniUnit[EventDCSUnitName].EventFunction = EventFunction + Event.IniUnit[EventDCSUnitName].EventSelf = EventSelf + return self +end + + +--- Create an OnBirth event handler for a group +-- @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. +-- @return #EVENT +function EVENT:OnBirthForTemplate( EventTemplate, EventFunction, EventSelf ) + self:F( { EventTemplate } ) + + return self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnBirth ) +end + +--- Set a new listener for an S_EVENT_BIRTH event. +-- @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 +-- @return #EVENT +function EVENT:OnBirth( EventDCSUnitName, EventFunction, EventSelf ) + self:F( EventDCSUnitName ) + + return self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_BIRTH ) +end + +--- Create an OnCrash event handler for a group +-- @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. +-- @return #EVENT +function EVENT:OnCrashForTemplate( EventTemplate, EventFunction, EventSelf ) + self:F( EventTemplate ) + + return self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnCrash ) +end + +--- Set a new listener for an S_EVENT_CRASH event. +-- @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. +-- @return #EVENT +function EVENT:OnCrash( EventDCSUnitName, EventFunction, EventSelf ) + self:F( EventDCSUnitName ) + + return self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_CRASH ) +end + +--- Create an OnDead event handler for a group +-- @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. +-- @return #EVENT +function EVENT:OnDeadForTemplate( EventTemplate, EventFunction, EventSelf ) + self:F( EventTemplate ) + + return self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnDead ) +end + +--- Set a new listener for an S_EVENT_DEAD event. +-- @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. +-- @return #EVENT +function EVENT:OnDead( EventDCSUnitName, EventFunction, EventSelf ) + self:F( EventDCSUnitName ) + + return self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_DEAD ) +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. +-- @return #EVENT +function EVENT:OnLandForTemplate( EventTemplate, EventFunction, EventSelf ) + self:F( EventTemplate ) + + return self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnLand ) +end + +--- Set a new listener for an S_EVENT_LAND event. +-- @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. +-- @return #EVENT +function EVENT:OnLand( EventDCSUnitName, EventFunction, EventSelf ) + self:F( EventDCSUnitName ) + + return self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_LAND ) +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. +-- @return #EVENT +function EVENT:OnTakeOffForTemplate( EventTemplate, EventFunction, EventSelf ) + self:F( EventTemplate ) + + return self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnTakeOff ) +end + +--- Set a new listener for an S_EVENT_LAND event. +-- @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. +-- @return #EVENT +function EVENT:OnTakeOff( EventDCSUnitName, EventFunction, EventSelf ) + self:F( EventDCSUnitName ) + + return self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_TAKEOFF ) +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. +-- @return #EVENT +function EVENT:OnEngineShutDownForTemplate( EventTemplate, EventFunction, EventSelf ) + self:F( EventTemplate ) + + return self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnEngineShutDown ) +end + +--- Set a new listener for an S_EVENT_LAND event. +-- @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. +-- @return #EVENT +function EVENT:OnEngineShutDown( EventDCSUnitName, EventFunction, EventSelf ) + self:F( EventDCSUnitName ) + + return self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_ENGINE_SHUTDOWN ) +end + + + +function EVENT:onEvent( Event ) + self:F( { EVENTCODES[Event.id], Event } ) + + if self and self.Events and self.Events[Event.id] then + local IniDCSUnit = Event.initiator + if IniDCSUnit and IniDCSUnit:getCategory() == Object.Category.UNIT then + Event.IniUnitName = IniDCSUnit:getName() + end + local TgtDCSUnit = Event.target + if TgtDCSUnit and TgtDCSUnit:isExist() and TgtDCSUnit:getCategory() == Object.Category.UNIT then + Event.TgtUnitName = TgtDCSUnit:getName() + end + for ClassName, EventData in pairs( self.Events[Event.id] ) do + if Event.IniUnitName and EventData.IniUnit and EventData.IniUnit[Event.IniUnitName] then + self:T( { "Calling event function for class ", ClassName, " unit ", Event.IniUnitName } ) + EventData.IniUnit[Event.IniUnitName].EventFunction( EventData.IniUnit[Event.IniUnitName].EventSelf, Event ) + end + end + end +end + + + +--- Declare the event dispatcher based on the EVENT class +_EventDispatcher = EVENT:New() -- #EVENT + diff --git a/Moose/Spawn.lua b/Moose/Spawn.lua index be3462ccf..f61f351ad 100644 --- a/Moose/Spawn.lua +++ b/Moose/Spawn.lua @@ -75,6 +75,7 @@ Include.File( "Base" ) Include.File( "Database" ) Include.File( "Group" ) Include.File( "Zone" ) +Include.File( "Event" ) --- SPAWN Class -- @type SPAWN @@ -122,9 +123,9 @@ function SPAWN:New( SpawnTemplatePrefix ) error( "SPAWN:New: There is no group declared in the mission editor with SpawnTemplatePrefix = '" .. SpawnTemplatePrefix .. "'" ) end - self:AddEvent( world.event.S_EVENT_BIRTH, self._OnBirth ) - self:AddEvent( world.event.S_EVENT_DEAD, self._OnDeadOrCrash ) - self:AddEvent( world.event.S_EVENT_CRASH, self._OnDeadOrCrash ) + --self:AddEvent( world.event.S_EVENT_BIRTH, self._OnBirth ) + --self:AddEvent( world.event.S_EVENT_DEAD, self._OnDeadOrCrash ) + --self:AddEvent( world.event.S_EVENT_CRASH, self._OnDeadOrCrash ) self:EnableEvents() @@ -165,11 +166,11 @@ function SPAWN:NewWithAlias( SpawnTemplatePrefix, SpawnAliasPrefix ) error( "SPAWN:New: There is no group declared in the mission editor with SpawnTemplatePrefix = '" .. SpawnTemplatePrefix .. "'" ) end - self:AddEvent( world.event.S_EVENT_BIRTH, self._OnBirth ) - self:AddEvent( world.event.S_EVENT_DEAD, self._OnDeadOrCrash ) - self:AddEvent( world.event.S_EVENT_CRASH, self._OnDeadOrCrash ) + --self:AddEvent( world.event.S_EVENT_BIRTH, self._OnBirth ) + --self:AddEvent( world.event.S_EVENT_DEAD, self._OnDeadOrCrash ) + --self:AddEvent( world.event.S_EVENT_CRASH, self._OnDeadOrCrash ) - self:EnableEvents() + --self:EnableEvents() return self end @@ -282,16 +283,16 @@ end -- -- Re-SPAWN the Group(s) after each landing and Engine Shut-Down automatically. -- SpawnRU_SU34 = SPAWN:New( 'TF1 RU Su-34 Krymsk@AI - Attack Ships' ):Schedule( 2, 3, 1800, 0.4 ):SpawnUncontrolled():RandomizeRoute( 1, 1, 3000 ):RepeatOnEngineShutDown() function SPAWN:Repeat() - self:F( { self.SpawnTemplatePrefix } ) + self:F( { self.SpawnTemplatePrefix, self.SpawnIndex } ) self.SpawnRepeat = true self.RepeatOnEngineShutDown = false self.RepeatOnLanding = true - self:AddEvent( world.event.S_EVENT_LAND, self._OnLand ) - self:AddEvent( world.event.S_EVENT_TAKEOFF, self._OnTakeOff ) - self:AddEvent( world.event.S_EVENT_ENGINE_SHUTDOWN, self._OnEngineShutDown ) - self:EnableEvents() + --self:AddEvent( world.event.S_EVENT_LAND, self._OnLand ) + --self:AddEvent( world.event.S_EVENT_TAKEOFF, self._OnTakeOff ) + --self:AddEvent( world.event.S_EVENT_ENGINE_SHUTDOWN, self._OnEngineShutDown ) + --self:EnableEvents() return self end @@ -386,6 +387,9 @@ function SPAWN:Array( SpawnAngle, SpawnWidth, SpawnDeltaX, SpawnDeltaY ) self.SpawnGroups[SpawnGroupID].Visible = true self.SpawnGroups[SpawnGroupID].Group = _Database:Spawn( self.SpawnGroups[SpawnGroupID].SpawnTemplate ) + self:Event():OnBirthForGroup( self.SpawnGroups[SpawnGroupID].Group, self._OnBirth, self ) + self:Event():OnCrashForGroup( self.SpawnGroups[SpawnGroupID].Group, self._OnBirth, self ) + self:Event():OnDeadForGroup ( self.SpawnGroups[SpawnGroupID].Group, self._OnBirth, self ) SpawnX = SpawnXIndex * SpawnDeltaX SpawnY = SpawnYIndex * SpawnDeltaY @@ -443,6 +447,20 @@ function SPAWN:SpawnWithIndex( SpawnIndex ) self.SpawnGroups[self.SpawnIndex].Group:Activate() else self:T( self.SpawnGroups[self.SpawnIndex].SpawnTemplate ) + _EventDispatcher:OnBirthForTemplate( self.SpawnGroups[self.SpawnIndex].SpawnTemplate, self._OnBirth, self ) + _EventDispatcher:OnCrashForTemplate( self.SpawnGroups[self.SpawnIndex].SpawnTemplate, self._OnDeadOrCrash, self ) + _EventDispatcher:OnDeadForTemplate( self.SpawnGroups[self.SpawnIndex].SpawnTemplate, self._OnDeadOrCrash, self ) + + if self.SpawnRepeat then + _EventDispatcher:OnTakeOffForTemplate( self.SpawnGroups[self.SpawnIndex].SpawnTemplate, self._OnTakeOff, self ) + end + if self.RepeatOnLanding then + _EventDispatcher:OnLandForTemplate( self.SpawnGroups[self.SpawnIndex].SpawnTemplate, self._OnLand, self ) + end + if self.RepeatOnEngineShutDown then + _EventDispatcher:OnEngineShutDownForTemplate( self.SpawnGroups[self.SpawnIndex].SpawnTemplate, self._OnEngineShutDown, self ) + end + self.SpawnGroups[self.SpawnIndex].Group = _Database:Spawn( self.SpawnGroups[self.SpawnIndex].SpawnTemplate ) -- If there is a SpawnFunction hook defined, call it. diff --git a/Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz b/Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz index 361cf596f..4a1b110f2 100644 Binary files a/Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz and b/Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz differ diff --git a/Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz b/Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz index 2ac75d628..acdcc9062 100644 Binary files a/Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz and b/Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz differ