mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Merge branch 'master-353-task-cargo-transport' into enhancement-353-task-cargo-transport
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
||||
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Utils/lua/5.1/bin/luadocumentor.bat}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value=""Moose\Core\*.lua" "Moose\Wrapper\*.lua" "Moose\Actions\*.lua" "Moose\Functional\*.lua" "Moose\Tasking\*.lua" "Moose\Utilities\*.lua" "Moose\AI\*.lua" --dir "${workspace_loc:/Moose_Framework/docs/Documentation} --style ${workspace_loc:/Moose_Framework/docs/Stylesheet/stylesheet.css}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Moose Development}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Utils/luadocumentor.bat}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Utils}"/>
|
||||
</launchConfiguration>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
||||
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Utils/lua/5.1/bin/lua.exe}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Utils/luarocks/lua5.1.exe}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value=""Moose_Create.lua" "D" "${current_date}" "${workspace_loc:/Moose_Framework//Moose Development/Moose}" "${workspace_loc:/Moose_Framework/Moose Mission Setup}""/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Moose Mission Setup}"/>
|
||||
</launchConfiguration>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
||||
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Utils/lua/5.1/bin/lua.exe}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Utils/luarocks/lua5.1.exe}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value=""Moose_Create.lua" "S" "${current_date}" "${workspace_loc:/Moose_Framework//Moose Development/Moose}" "${workspace_loc:/Moose_Framework/Moose Mission Setup}""/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Moose Mission Setup}"/>
|
||||
</launchConfiguration>
|
||||
|
||||
@@ -4,6 +4,5 @@
|
||||
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Moose Mission Setup/Moose Mission Update/Moose_Update_Missions.bat}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value=""${folder_prompt}""/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Moose Mission Setup/Moose Mission Update}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Missions}"/>
|
||||
</launchConfiguration>
|
||||
|
||||
@@ -219,9 +219,9 @@ local _ClassID = 0
|
||||
BASE = {
|
||||
ClassName = "BASE",
|
||||
ClassID = 0,
|
||||
_Private = {},
|
||||
Events = {},
|
||||
States = {}
|
||||
States = {},
|
||||
_ = {},
|
||||
}
|
||||
|
||||
--- The Formation Class
|
||||
@@ -360,7 +360,7 @@ do -- Event Handling
|
||||
-- @param #BASE self
|
||||
-- @return #number The @{Event} processing Priority.
|
||||
function BASE:GetEventPriority()
|
||||
return self._Private.EventPriority or 5
|
||||
return self._.EventPriority or 5
|
||||
end
|
||||
|
||||
--- Set the Class @{Event} processing Priority.
|
||||
@@ -370,7 +370,7 @@ do -- Event Handling
|
||||
-- @param #number EventPriority The @{Event} processing Priority.
|
||||
-- @return self
|
||||
function BASE:SetEventPriority( EventPriority )
|
||||
self._Private.EventPriority = EventPriority
|
||||
self._.EventPriority = EventPriority
|
||||
end
|
||||
|
||||
--- Remove all subscribed events
|
||||
|
||||
@@ -46,6 +46,7 @@ DATABASE = {
|
||||
Templates = {
|
||||
Units = {},
|
||||
Groups = {},
|
||||
Statics = {},
|
||||
ClientsByName = {},
|
||||
ClientsByID = {},
|
||||
},
|
||||
@@ -318,7 +319,7 @@ function DATABASE:Spawn( SpawnTemplate )
|
||||
SpawnTemplate.CountryID = nil
|
||||
SpawnTemplate.CategoryID = nil
|
||||
|
||||
self:_RegisterTemplate( SpawnTemplate, SpawnCoalitionID, SpawnCategoryID, SpawnCountryID )
|
||||
self:_RegisterGroupTemplate( SpawnTemplate, SpawnCoalitionID, SpawnCategoryID, SpawnCountryID )
|
||||
|
||||
self:T3( SpawnTemplate )
|
||||
coalition.addGroup( SpawnCountryID, SpawnCategoryID, SpawnTemplate )
|
||||
@@ -354,7 +355,7 @@ end
|
||||
-- @param #DATABASE self
|
||||
-- @param #table GroupTemplate
|
||||
-- @return #DATABASE self
|
||||
function DATABASE:_RegisterTemplate( GroupTemplate, CoalitionID, CategoryID, CountryID )
|
||||
function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionID, CategoryID, CountryID )
|
||||
|
||||
local GroupTemplateName = env.getValueDictByKey(GroupTemplate.name)
|
||||
|
||||
@@ -432,6 +433,54 @@ function DATABASE:GetGroupTemplate( GroupName )
|
||||
return GroupTemplate
|
||||
end
|
||||
|
||||
--- Private method that registers new Static Templates within the DATABASE Object.
|
||||
-- @param #DATABASE self
|
||||
-- @param #table GroupTemplate
|
||||
-- @return #DATABASE self
|
||||
function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, CategoryID, CountryID )
|
||||
|
||||
local TraceTable = {}
|
||||
|
||||
local StaticTemplateName = env.getValueDictByKey(StaticTemplate.name)
|
||||
|
||||
self.Templates.Statics[StaticTemplateName] = self.Templates.Statics[StaticTemplateName] or {}
|
||||
|
||||
StaticTemplate.CategoryID = CategoryID
|
||||
StaticTemplate.CoalitionID = CoalitionID
|
||||
StaticTemplate.CountryID = CountryID
|
||||
|
||||
self.Templates.Statics[StaticTemplateName].StaticName = StaticTemplateName
|
||||
self.Templates.Statics[StaticTemplateName].GroupTemplate = StaticTemplate
|
||||
self.Templates.Statics[StaticTemplateName].UnitTemplate = StaticTemplate.units[1]
|
||||
self.Templates.Statics[StaticTemplateName].CategoryID = CategoryID
|
||||
self.Templates.Statics[StaticTemplateName].CoalitionID = CoalitionID
|
||||
self.Templates.Statics[StaticTemplateName].CountryID = CountryID
|
||||
|
||||
|
||||
TraceTable[#TraceTable+1] = "Static"
|
||||
TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].GroupName
|
||||
|
||||
TraceTable[#TraceTable+1] = "Coalition"
|
||||
TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].CoalitionID
|
||||
TraceTable[#TraceTable+1] = "Category"
|
||||
TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].CategoryID
|
||||
TraceTable[#TraceTable+1] = "Country"
|
||||
TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].CountryID
|
||||
|
||||
self:E( TraceTable )
|
||||
end
|
||||
|
||||
|
||||
--- @param #DATABASE self
|
||||
function DATABASE:GetStaticUnitTemplate( StaticName )
|
||||
local StaticTemplate = self.Templates.Statics[StaticName].UnitTemplate
|
||||
StaticTemplate.SpawnCoalitionID = self.Templates.Statics[StaticName].CoalitionID
|
||||
StaticTemplate.SpawnCategoryID = self.Templates.Statics[StaticName].CategoryID
|
||||
StaticTemplate.SpawnCountryID = self.Templates.Statics[StaticName].CountryID
|
||||
return StaticTemplate
|
||||
end
|
||||
|
||||
|
||||
function DATABASE:GetGroupNameFromUnitName( UnitName )
|
||||
return self.Templates.Units[UnitName].GroupName
|
||||
end
|
||||
@@ -798,6 +847,7 @@ function DATABASE:OnEventDeleteCargo( EventData )
|
||||
end
|
||||
|
||||
|
||||
--- @param #DATABASE self
|
||||
function DATABASE:_RegisterTemplates()
|
||||
self:F2()
|
||||
|
||||
@@ -853,11 +903,18 @@ function DATABASE:_RegisterTemplates()
|
||||
|
||||
--self.Units[coa_name][countryName][category] = {}
|
||||
|
||||
for group_num, GroupTemplate in pairs(obj_type_data.group) do
|
||||
for group_num, Template in pairs(obj_type_data.group) do
|
||||
|
||||
if GroupTemplate and GroupTemplate.units and type(GroupTemplate.units) == 'table' then --making sure again- this is a valid group
|
||||
self:_RegisterTemplate(
|
||||
GroupTemplate,
|
||||
if obj_type_name ~= "static" and Template and Template.units and type(Template.units) == 'table' then --making sure again- this is a valid group
|
||||
self:_RegisterGroupTemplate(
|
||||
Template,
|
||||
CoalitionSide,
|
||||
_DATABASECategory[string.lower(CategoryName)],
|
||||
CountryID
|
||||
)
|
||||
else
|
||||
self:_RegisterStaticTemplate(
|
||||
Template,
|
||||
CoalitionSide,
|
||||
_DATABASECategory[string.lower(CategoryName)],
|
||||
CountryID
|
||||
|
||||
@@ -235,7 +235,7 @@ EVENTS = {
|
||||
-- Note that at the beginning of each field description, there is an indication which field will be populated depending on the object type involved in the Event:
|
||||
--
|
||||
-- * A (Object.Category.)UNIT : A UNIT object type is involved in the Event.
|
||||
-- * A (Object.Category.)STATIC : A STATIC object type is involved in the Event.µ
|
||||
-- * A (Object.Category.)STATIC : A STATIC object type is involved in the Event.µ
|
||||
--
|
||||
-- @type EVENTDATA
|
||||
-- @field #number id The identifier of the event.
|
||||
@@ -280,116 +280,139 @@ EVENTS = {
|
||||
local _EVENTMETA = {
|
||||
[world.event.S_EVENT_SHOT] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventShot",
|
||||
Text = "S_EVENT_SHOT"
|
||||
},
|
||||
[world.event.S_EVENT_HIT] = {
|
||||
Order = 1,
|
||||
Side = "T",
|
||||
Event = "OnEventHit",
|
||||
Text = "S_EVENT_HIT"
|
||||
},
|
||||
[world.event.S_EVENT_TAKEOFF] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventTakeoff",
|
||||
Text = "S_EVENT_TAKEOFF"
|
||||
},
|
||||
[world.event.S_EVENT_LAND] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventLand",
|
||||
Text = "S_EVENT_LAND"
|
||||
},
|
||||
[world.event.S_EVENT_CRASH] = {
|
||||
Order = -1,
|
||||
Side = "I",
|
||||
Event = "OnEventCrash",
|
||||
Text = "S_EVENT_CRASH"
|
||||
},
|
||||
[world.event.S_EVENT_EJECTION] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventEjection",
|
||||
Text = "S_EVENT_EJECTION"
|
||||
},
|
||||
[world.event.S_EVENT_REFUELING] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventRefueling",
|
||||
Text = "S_EVENT_REFUELING"
|
||||
},
|
||||
[world.event.S_EVENT_DEAD] = {
|
||||
Order = -1,
|
||||
Side = "I",
|
||||
Event = "OnEventDead",
|
||||
Text = "S_EVENT_DEAD"
|
||||
},
|
||||
[world.event.S_EVENT_PILOT_DEAD] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventPilotDead",
|
||||
Text = "S_EVENT_PILOT_DEAD"
|
||||
},
|
||||
[world.event.S_EVENT_BASE_CAPTURED] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventBaseCaptured",
|
||||
Text = "S_EVENT_BASE_CAPTURED"
|
||||
},
|
||||
[world.event.S_EVENT_MISSION_START] = {
|
||||
Order = 1,
|
||||
Side = "N",
|
||||
Event = "OnEventMissionStart",
|
||||
Text = "S_EVENT_MISSION_START"
|
||||
},
|
||||
[world.event.S_EVENT_MISSION_END] = {
|
||||
Order = 1,
|
||||
Side = "N",
|
||||
Event = "OnEventMissionEnd",
|
||||
Text = "S_EVENT_MISSION_END"
|
||||
},
|
||||
[world.event.S_EVENT_TOOK_CONTROL] = {
|
||||
Order = 1,
|
||||
Side = "N",
|
||||
Event = "OnEventTookControl",
|
||||
Text = "S_EVENT_TOOK_CONTROL"
|
||||
},
|
||||
[world.event.S_EVENT_REFUELING_STOP] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventRefuelingStop",
|
||||
Text = "S_EVENT_REFUELING_STOP"
|
||||
},
|
||||
[world.event.S_EVENT_BIRTH] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventBirth",
|
||||
Text = "S_EVENT_BIRTH"
|
||||
},
|
||||
[world.event.S_EVENT_HUMAN_FAILURE] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventHumanFailure",
|
||||
Text = "S_EVENT_HUMAN_FAILURE"
|
||||
},
|
||||
[world.event.S_EVENT_ENGINE_STARTUP] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventEngineStartup",
|
||||
Text = "S_EVENT_ENGINE_STARTUP"
|
||||
},
|
||||
[world.event.S_EVENT_ENGINE_SHUTDOWN] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventEngineShutdown",
|
||||
Text = "S_EVENT_ENGINE_SHUTDOWN"
|
||||
},
|
||||
[world.event.S_EVENT_PLAYER_ENTER_UNIT] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventPlayerEnterUnit",
|
||||
Text = "S_EVENT_PLAYER_ENTER_UNIT"
|
||||
},
|
||||
[world.event.S_EVENT_PLAYER_LEAVE_UNIT] = {
|
||||
Order = -1,
|
||||
Side = "I",
|
||||
Event = "OnEventPlayerLeaveUnit",
|
||||
Text = "S_EVENT_PLAYER_LEAVE_UNIT"
|
||||
},
|
||||
[world.event.S_EVENT_PLAYER_COMMENT] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventPlayerComment",
|
||||
Text = "S_EVENT_PLAYER_COMMENT"
|
||||
},
|
||||
[world.event.S_EVENT_SHOOTING_START] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventShootingStart",
|
||||
Text = "S_EVENT_SHOOTING_START"
|
||||
},
|
||||
[world.event.S_EVENT_SHOOTING_END] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventShootingEnd",
|
||||
Text = "S_EVENT_SHOOTING_END"
|
||||
},
|
||||
@@ -417,13 +440,6 @@ function EVENT:New()
|
||||
return self
|
||||
end
|
||||
|
||||
function EVENT:EventText( EventID )
|
||||
|
||||
local EventText = _EVENTMETA[EventID].Text
|
||||
|
||||
return EventText
|
||||
end
|
||||
|
||||
|
||||
--- Initializes the Events structure for the event
|
||||
-- @param #EVENT self
|
||||
@@ -435,7 +451,7 @@ function EVENT:Init( EventID, EventClass )
|
||||
|
||||
if not self.Events[EventID] then
|
||||
-- Create a WEAK table to ensure that the garbage collector is cleaning the event links when the object usage is cleaned.
|
||||
self.Events[EventID] = setmetatable( {}, { __mode = "k" } )
|
||||
self.Events[EventID] = {}
|
||||
end
|
||||
|
||||
-- Each event has a subtable of EventClasses, ordered by EventPriority.
|
||||
@@ -445,53 +461,56 @@ function EVENT:Init( EventID, EventClass )
|
||||
end
|
||||
|
||||
if not self.Events[EventID][EventPriority][EventClass] then
|
||||
self.Events[EventID][EventPriority][EventClass] = setmetatable( {}, { __mode = "v" } )
|
||||
self.Events[EventID][EventPriority][EventClass] = {}
|
||||
end
|
||||
return self.Events[EventID][EventPriority][EventClass]
|
||||
end
|
||||
|
||||
--- Removes an Events entry
|
||||
--- Removes a subscription
|
||||
-- @param #EVENT self
|
||||
-- @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:Remove( EventClass, EventID )
|
||||
self:F3( { EventClass, _EVENTMETA[EventID].Text } )
|
||||
|
||||
local EventClass = EventClass
|
||||
self:E( { "Removing subscription for class: ", EventClass:GetClassNameAndID() } )
|
||||
|
||||
local EventPriority = EventClass:GetEventPriority()
|
||||
|
||||
self.EventsDead = self.EventsDead or {}
|
||||
self.EventsDead[EventID] = self.EventsDead[EventID] or {}
|
||||
self.EventsDead[EventID][EventPriority] = self.EventsDead[EventID][EventPriority] or {}
|
||||
self.EventsDead[EventID][EventPriority][EventClass] = self.Events[EventID][EventPriority][EventClass]
|
||||
|
||||
self.Events[EventID][EventPriority][EventClass] = nil
|
||||
|
||||
end
|
||||
|
||||
--- Removes an Events entry for a UNIT.
|
||||
--- Resets subscriptions
|
||||
-- @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
|
||||
function EVENT:RemoveForUnit( UnitName, EventClass, EventID )
|
||||
self:F3( { EventClass, _EVENTMETA[EventID].Text } )
|
||||
function EVENT:Reset( EventObject )
|
||||
|
||||
local EventClass = EventClass
|
||||
local EventPriority = EventClass:GetEventPriority()
|
||||
local Event = self.Events[EventID][EventPriority][EventClass]
|
||||
Event.EventUnit[UnitName] = nil
|
||||
self:E( { "Resetting subscriptions for class: ", EventObject:GetClassNameAndID() } )
|
||||
|
||||
local EventPriority = EventObject:GetEventPriority()
|
||||
for EventID, EventData in pairs( self.Events ) do
|
||||
if self.EventsDead then
|
||||
if self.EventsDead[EventID] then
|
||||
if self.EventsDead[EventID][EventPriority] then
|
||||
if self.EventsDead[EventID][EventPriority][EventObject] then
|
||||
self.Events[EventID][EventPriority][EventObject] = self.EventsDead[EventID][EventPriority][EventObject]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
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.EventGroup[GroupName] = nil
|
||||
end
|
||||
|
||||
|
||||
--- Clears all event subscriptions for a @{Base#BASE} derived object.
|
||||
-- @param #EVENT self
|
||||
@@ -535,7 +554,6 @@ function EVENT:OnEventGeneric( EventFunction, EventClass, EventID )
|
||||
|
||||
local EventData = self:Init( EventID, EventClass )
|
||||
EventData.EventFunction = EventFunction
|
||||
EventData.EventClass = EventClass
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -552,12 +570,8 @@ function EVENT:OnEventForUnit( UnitName, EventFunction, EventClass, EventID )
|
||||
self:F2( UnitName )
|
||||
|
||||
local EventData = self:Init( EventID, EventClass )
|
||||
if not EventData.EventUnit then
|
||||
EventData.EventUnit = {}
|
||||
end
|
||||
EventData.EventUnit[UnitName] = {}
|
||||
EventData.EventUnit[UnitName].EventFunction = EventFunction
|
||||
EventData.EventUnit[UnitName].EventClass = EventClass
|
||||
EventData.EventUnit = true
|
||||
EventData.EventFunction = EventFunction
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -572,12 +586,8 @@ function EVENT:OnEventForGroup( GroupName, EventFunction, EventClass, EventID )
|
||||
self:F2( GroupName )
|
||||
|
||||
local Event = self:Init( EventID, EventClass )
|
||||
if not Event.EventGroup then
|
||||
Event.EventGroup = {}
|
||||
end
|
||||
Event.EventGroup[GroupName] = {}
|
||||
Event.EventGroup[GroupName].EventFunction = EventFunction
|
||||
Event.EventGroup[GroupName].EventClass = EventClass
|
||||
Event.EventGroup = true
|
||||
Event.EventFunction = EventFunction
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -736,10 +746,10 @@ function EVENT:onEvent( Event )
|
||||
return errmsg
|
||||
end
|
||||
|
||||
self:E( _EVENTMETA[Event.id].Text, Event )
|
||||
|
||||
local EventMeta = _EVENTMETA[Event.id]
|
||||
|
||||
if self and self.Events and self.Events[Event.id] then
|
||||
|
||||
|
||||
if Event.initiator then
|
||||
|
||||
@@ -849,12 +859,12 @@ function EVENT:onEvent( Event )
|
||||
Event.CargoName = Event.cargo.Name
|
||||
end
|
||||
|
||||
local PriorityOrder = _EVENTMETA[Event.id].Order
|
||||
local PriorityOrder = EventMeta.Order
|
||||
local PriorityBegin = PriorityOrder == -1 and 5 or 1
|
||||
local PriorityEnd = PriorityOrder == -1 and 1 or 5
|
||||
|
||||
if Event.IniObjectCategory ~= 3 then
|
||||
self:E( { _EVENTMETA[Event.id].Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } )
|
||||
self:E( { EventMeta.Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } )
|
||||
end
|
||||
|
||||
for EventPriority = PriorityBegin, PriorityEnd, PriorityOrder do
|
||||
@@ -864,187 +874,144 @@ 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
|
||||
|
||||
self:E( { "Evaluating: ", EventClass:GetClassNameAndID() } )
|
||||
|
||||
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
|
||||
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )
|
||||
|
||||
-- If the EventData is for a UNIT, the call directly the EventClass EventFunction for that UNIT.
|
||||
if ( Event.IniDCSUnitName and EventData.EventUnit and EventData.EventUnit[Event.IniDCSUnitName] ) or
|
||||
( Event.TgtDCSUnitName and EventData.EventUnit and EventData.EventUnit[Event.TgtDCSUnitName] ) then
|
||||
if EventData.EventUnit then
|
||||
|
||||
if EventData.EventUnit[Event.IniDCSUnitName] then
|
||||
|
||||
-- First test if a EventFunction is Set, otherwise search for the default function
|
||||
if EventData.EventUnit[Event.IniDCSUnitName].EventFunction then
|
||||
-- So now the EventClass must be a UNIT class!!! We check if it is still "Alive".
|
||||
if EventClass:IsAlive() or
|
||||
Event.id == EVENTS.Crash or
|
||||
Event.id == EVENTS.Dead then
|
||||
|
||||
if Event.IniObjectCategory ~= 3 then
|
||||
self:E( { "Calling EventFunction for UNIT ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
|
||||
end
|
||||
|
||||
local Result, Value = xpcall(
|
||||
function()
|
||||
return EventData.EventUnit[Event.IniDCSUnitName].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.
|
||||
local UnitName = EventClass:GetName()
|
||||
|
||||
if ( EventMeta.Side == "I" and UnitName == Event.IniDCSUnitName ) or
|
||||
( EventMeta.Side == "T" and UnitName == Event.TgtDCSUnitName ) then
|
||||
|
||||
-- First test if a EventFunction is Set, otherwise search for the default function
|
||||
if EventData.EventFunction then
|
||||
|
||||
if Event.IniObjectCategory ~= 3 then
|
||||
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||
self:E( { "Calling EventFunction for UNIT ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
|
||||
end
|
||||
|
||||
|
||||
local Result, Value = xpcall(
|
||||
function()
|
||||
return EventFunction( EventClass, Event )
|
||||
return EventData.EventFunction( EventClass, Event )
|
||||
end, ErrorHandler )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if EventData.EventUnit[Event.TgtDCSUnitName] then
|
||||
|
||||
-- First test if a EventFunction is Set, otherwise search for the default function
|
||||
if EventData.EventUnit[Event.TgtDCSUnitName].EventFunction then
|
||||
|
||||
if Event.IniObjectCategory ~= 3 then
|
||||
self:E( { "Calling EventFunction for UNIT ", EventClass:GetClassNameAndID(), ", Unit ", Event.TgtUnitName, EventPriority } )
|
||||
end
|
||||
|
||||
local Result, Value = xpcall(
|
||||
function()
|
||||
return EventData.EventUnit[Event.TgtDCSUnitName].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.
|
||||
if Event.IniObjectCategory ~= 3 then
|
||||
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||
|
||||
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 ]
|
||||
if EventFunction and type( EventFunction ) == "function" then
|
||||
|
||||
-- Now call the default event function.
|
||||
if Event.IniObjectCategory ~= 3 then
|
||||
self:E( { "Calling " .. EventMeta.Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||
end
|
||||
|
||||
local Result, Value = xpcall(
|
||||
function()
|
||||
return EventFunction( EventClass, Event )
|
||||
end, ErrorHandler )
|
||||
end
|
||||
|
||||
local Result, Value = xpcall(
|
||||
function()
|
||||
return EventFunction( EventClass, Event )
|
||||
end, ErrorHandler )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
-- The EventClass is not alive anymore, we remove it from the EventHandlers...
|
||||
self:Remove( EventClass, Event.id )
|
||||
end
|
||||
else
|
||||
|
||||
-- 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.EventGroup and EventData.EventGroup[Event.IniGroupName] ) or
|
||||
( Event.TgtDCSUnitName and Event.TgtDCSGroupName and Event.TgtGroupName and EventData.EventGroup and EventData.EventGroup[Event.TgtGroupName] ) then
|
||||
if EventData.EventGroup then
|
||||
|
||||
if EventData.EventGroup[Event.IniGroupName] then
|
||||
-- First test if a EventFunction is Set, otherwise search for the default function
|
||||
if EventData.EventGroup[Event.IniGroupName].EventFunction then
|
||||
-- So now the EventClass must be a GROUP class!!! We check if it is still "Alive".
|
||||
if EventClass:IsAlive() or
|
||||
Event.id == EVENTS.Crash or
|
||||
Event.id == EVENTS.Dead then
|
||||
|
||||
if Event.IniObjectCategory ~= 3 then
|
||||
self:E( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
|
||||
end
|
||||
|
||||
local Result, Value = xpcall(
|
||||
function()
|
||||
return EventData.EventGroup[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.
|
||||
if Event.IniObjectCategory ~= 3 then
|
||||
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||
end
|
||||
|
||||
local Result, Value = xpcall(
|
||||
function()
|
||||
return EventFunction( EventClass, Event )
|
||||
end, ErrorHandler )
|
||||
end
|
||||
end
|
||||
end
|
||||
-- We can get the name of the EventClass, which is now always a GROUP object.
|
||||
local GroupName = EventClass:GetName()
|
||||
|
||||
if ( EventMeta.Side == "I" and GroupName == Event.IniDCSGroupName ) or
|
||||
( EventMeta.Side == "T" and GroupName == Event.TgtDCSGroupName ) then
|
||||
|
||||
if EventData.EventGroup[Event.TgtGroupName] then
|
||||
if EventData.EventGroup[Event.TgtGroupName].EventFunction then
|
||||
|
||||
if Event.IniObjectCategory ~= 3 then
|
||||
self:E( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.TgtUnitName, EventPriority } )
|
||||
end
|
||||
|
||||
local Result, Value = xpcall(
|
||||
function()
|
||||
return EventData.EventGroup[Event.TgtGroupName].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.
|
||||
if Event.IniObjectCategory ~= 3 then
|
||||
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||
end
|
||||
|
||||
local Result, Value = xpcall(
|
||||
function()
|
||||
return EventFunction( EventClass, Event )
|
||||
end, ErrorHandler )
|
||||
end
|
||||
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 or Event.WeaponUNIT) and not EventData.EventUnit ) or
|
||||
Event.Cargo then
|
||||
|
||||
if EventClass == EventData.EventClass then
|
||||
|
||||
-- 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.
|
||||
|
||||
if Event.IniObjectCategory ~= 3 then
|
||||
self:E( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||
end
|
||||
self:E( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
|
||||
end
|
||||
|
||||
local Result, Value = xpcall(
|
||||
function()
|
||||
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 ]
|
||||
local EventFunction = EventClass[ EventMeta.Event ]
|
||||
if EventFunction and type( EventFunction ) == "function" then
|
||||
|
||||
-- Now call the default event function.
|
||||
if Event.IniObjectCategory ~= 3 then
|
||||
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||
self:E( { "Calling " .. EventMeta.Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||
end
|
||||
|
||||
|
||||
local Result, Value = xpcall(
|
||||
function()
|
||||
local Result, Value = EventFunction( EventClass, Event )
|
||||
return Result, Value
|
||||
return EventFunction( EventClass, Event )
|
||||
end, ErrorHandler )
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
-- The EventClass is not alive anymore, we remove it from the EventHandlers...
|
||||
self:Remove( EventClass, Event.id )
|
||||
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 not EventData.EventUnit then
|
||||
|
||||
-- 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.
|
||||
if Event.IniObjectCategory ~= 3 then
|
||||
self:E( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||
end
|
||||
local Result, Value = xpcall(
|
||||
function()
|
||||
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 ]
|
||||
if EventFunction and type( EventFunction ) == "function" then
|
||||
|
||||
-- Now call the default event function.
|
||||
if Event.IniObjectCategory ~= 3 then
|
||||
self:E( { "Calling " .. EventMeta.Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||
end
|
||||
|
||||
local Result, Value = xpcall(
|
||||
function()
|
||||
local Result, Value = EventFunction( EventClass, Event )
|
||||
return Result, Value
|
||||
end, ErrorHandler )
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1052,7 +1019,7 @@ function EVENT:onEvent( Event )
|
||||
end
|
||||
end
|
||||
else
|
||||
self:E( { _EVENTMETA[Event.id].Text, Event } )
|
||||
self:E( { EventMeta.Text, Event } )
|
||||
end
|
||||
|
||||
Event = nil
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- **Core** - The RADIO class is responsible for **transmitting radio communications**.
|
||||
--
|
||||
-- --- bitmap
|
||||
-- 
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -27,19 +27,20 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Authors: Hugues "Grey_Echo" Bousquet
|
||||
-- ### Author: Hugues "Grey_Echo" Bousquet
|
||||
--
|
||||
-- @module Radio
|
||||
|
||||
|
||||
--- # 1) RADIO class, extends @{Base#BASE}
|
||||
--
|
||||
-- ## 1.1) RADIO usage
|
||||
--
|
||||
-- There are 3 steps to a successful radio transmission.
|
||||
--
|
||||
-- * First, you need to **"add" a @{#RADIO} object** to your @{Positionable#POSITIONABLE}. This is done using the @{Positionable#POSITIONABLE.GetRadio}() function,
|
||||
-- * First, you need to **"add a @{#RADIO} object** to your @{Positionable#POSITIONABLE}. This is done using the @{Positionable#POSITIONABLE.GetRadio}() function,
|
||||
-- * Then, you will **set the relevant parameters** to the transmission (see below),
|
||||
-- * When done, you can actually **broadcast the transmission** (i.e. play the sound) with the @{Positionable#POSITIONABLE.Broadcast}() function.
|
||||
-- * When done, you can actually **broadcast the transmission** (i.e. play the sound) with the @{RADIO.Broadcast}() function.
|
||||
--
|
||||
-- Methods to set relevant parameters for both a @{Unit#UNIT} or a @{Group#GROUP} or any other @{Positionable#POSITIONABLE}
|
||||
--
|
||||
@@ -53,7 +54,7 @@
|
||||
-- * @{#RADIO.SetSubtitle}() : Set both the subtitle and its duration,
|
||||
-- * @{#RADIO.NewUnitTransmission}() : Shortcut to set all the relevant parameters in one method call
|
||||
--
|
||||
-- Additional Methods to set relevant parameters if the transmiter is any other @{Wrapper.Positionable#POSITIONABLE}
|
||||
-- Additional Methods to set relevant parameters if the transmiter is any other @{Positionable#POSITIONABLE}
|
||||
--
|
||||
-- * @{#RADIO.SetPower}() : Sets the power of the antenna in Watts
|
||||
-- * @{#RADIO.NewGenericTransmission}() : Shortcut to set all the relevant parameters in one method call
|
||||
@@ -68,7 +69,7 @@
|
||||
-- * Note that if the transmission has a subtitle, it will be readable, regardless of the quality of the transmission.
|
||||
--
|
||||
-- @type RADIO
|
||||
-- @field Wrapper.Positionable#POSITIONABLE Positionable The transmiter
|
||||
-- @field Positionable#POSITIONABLE Positionable The transmiter
|
||||
-- @field #string FileName Name of the sound file
|
||||
-- @field #number Frequency Frequency of the transmission in Hz
|
||||
-- @field #number Modulation Modulation of the transmission (either radio.modulation.AM or radio.modulation.FM)
|
||||
|
||||
@@ -1374,7 +1374,7 @@ function SET_UNIT:ForEachUnitCompletelyInZone( ZoneObject, IteratorFunction, ...
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Unit#UNIT UnitObject
|
||||
function( ZoneObject, UnitObject )
|
||||
if UnitObject:IsCompletelyInZone( ZoneObject ) then
|
||||
if UnitObject:IsInZone( ZoneObject ) then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
|
||||
177
Moose Development/Moose/Core/SpawnStatic.lua
Normal file
177
Moose Development/Moose/Core/SpawnStatic.lua
Normal file
@@ -0,0 +1,177 @@
|
||||
--- **Core** -- Spawn dynamically new STATICs in your missions.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
-- SPAWNSTATIC spawns static structures in your missions dynamically. See below the SPAWNSTATIC class documentation.
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
-- # Demo Missions
|
||||
--
|
||||
-- ### [SPAWNSTATIC Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/SPS - Spawning Statics)
|
||||
--
|
||||
-- ### [SPAWNSTATIC Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SPS%20-%20Spawning%20Statics)
|
||||
--
|
||||
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
-- # YouTube Channel
|
||||
--
|
||||
-- ### [SPAWNSTATIC YouTube Channel]()
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
-- # **API CHANGE HISTORY**
|
||||
--
|
||||
-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
|
||||
--
|
||||
-- * **Added** parts are expressed in bold type face.
|
||||
-- * _Removed_ parts are expressed in italic type face.
|
||||
--
|
||||
-- Hereby the change log:
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # **AUTHORS and CONTRIBUTIONS**
|
||||
--
|
||||
-- ### Contributions:
|
||||
--
|
||||
-- ### Authors:
|
||||
--
|
||||
-- * **FlightControl**: Design & Programming
|
||||
--
|
||||
-- @module SpawnStatic
|
||||
|
||||
|
||||
|
||||
--- @type SPAWNSTATIC
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
--- # SPAWNSTATIC class, extends @{Base#BASE}
|
||||
--
|
||||
-- The SPAWNSTATIC class allows to spawn dynamically new @{Static}s.
|
||||
-- Through creating a copy of an existing static object template as defined in the Mission Editor (ME),
|
||||
-- SPAWNSTATIC can retireve the properties of the defined static object template (like type, category etc), and "copy"
|
||||
-- these properties to create a new static object and place it at the desired coordinate.
|
||||
--
|
||||
-- New spawned @{Static}s get **the same name** as the name of the template Static,
|
||||
-- or gets the given name when a new name is provided at the Spawn method.
|
||||
-- By default, spawned @{Static}s will follow a naming convention at run-time:
|
||||
--
|
||||
-- * Spawned @{Static}s will have the name _StaticName_#_nnn_, where _StaticName_ is the name of the **Template Static**,
|
||||
-- and _nnn_ is a **counter from 0 to 99999**.
|
||||
--
|
||||
--
|
||||
-- ## SPAWNSTATIC construction methods
|
||||
--
|
||||
-- Create a new SPAWNSTATIC object with the @{#SPAWNSTATIC.NewFromStatic}():
|
||||
--
|
||||
-- * @{#SPAWNSTATIC.NewFromStatic}(): Creates a new SPAWNSTATIC object given a name that is used as the base of the naming of each spawned Static.
|
||||
--
|
||||
-- ## **Spawn** methods
|
||||
--
|
||||
-- Groups can be spawned at different times and methods:
|
||||
--
|
||||
-- * @{#SPAWNSTATIC.SpawnFromPointVec2}(): Spawn a new group from a POINT_VEC2 coordinate.
|
||||
-- (The group will be spawned at land height ).
|
||||
-- * @{#SPAWNSTATIC.SpawnFromZone}(): Spawn a new group in a @{Zone}.
|
||||
--
|
||||
-- @field #SPAWNSTATIC SPAWNSTATIC
|
||||
--
|
||||
SPAWNSTATIC = {
|
||||
ClassName = "SPAWNSTATIC",
|
||||
}
|
||||
|
||||
|
||||
--- @type SPAWNSTATIC.SpawnZoneTable
|
||||
-- @list <Core.Zone#ZONE_BASE> SpawnZone
|
||||
|
||||
|
||||
--- Creates the main object to spawn a @{Static} defined in the ME.
|
||||
-- @param #SPAWNSTATIC self
|
||||
-- @param #string SpawnTemplatePrefix is the name of the Group in the ME that defines the Template. Each new group will have the name starting with SpawnTemplatePrefix.
|
||||
-- @return #SPAWNSTATIC
|
||||
function SPAWNSTATIC:NewFromStatic( SpawnTemplatePrefix, CountryID )
|
||||
local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC
|
||||
self:F( { SpawnTemplatePrefix } )
|
||||
|
||||
local TemplateStatic = StaticObject.getByName( SpawnTemplatePrefix )
|
||||
if TemplateStatic then
|
||||
self.SpawnTemplatePrefix = SpawnTemplatePrefix
|
||||
self.CountryID = CountryID
|
||||
self.SpawnIndex = 0
|
||||
else
|
||||
error( "SPAWNSTATIC:New: There is no group declared in the mission editor with SpawnTemplatePrefix = '" .. SpawnTemplatePrefix .. "'" )
|
||||
end
|
||||
|
||||
self:SetEventPriority( 5 )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Creates the main object to spawn a @{Static} based on a type name.
|
||||
-- @param #SPAWNSTATIC self
|
||||
-- @param #string SpawnTypeName is the name of the type.
|
||||
-- @return #SPAWNSTATIC
|
||||
function SPAWNSTATIC:NewFromType( SpawnTypeName, SpawnShapeName, SpawnCategory, CountryID )
|
||||
local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC
|
||||
self:F( { SpawnTypeName } )
|
||||
|
||||
self.SpawnTypeName = SpawnTypeName
|
||||
self.CountryID = CountryID
|
||||
self.SpawnIndex = 0
|
||||
|
||||
self:SetEventPriority( 5 )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Creates a new @{Static} from a POINT_VEC2.
|
||||
-- @param #SPAWNSTATIC self
|
||||
-- @param Core.Point#POINT_VEC2 PointVec2 The 2D coordinate where to spawn the static.
|
||||
-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
|
||||
-- @param #string (optional) The name of the new static.
|
||||
-- @return #SPAWNSTATIC
|
||||
function SPAWNSTATIC:SpawnFromPointVec2( PointVec2, Heading, NewName )
|
||||
self:F( { PointVec2, Heading, NewName } )
|
||||
|
||||
local CountryName = _DATABASE.COUNTRY_NAME[self.CountryID]
|
||||
|
||||
local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix )
|
||||
|
||||
StaticTemplate.x = PointVec2:GetLat()
|
||||
StaticTemplate.y = PointVec2:GetLon()
|
||||
|
||||
StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex )
|
||||
StaticTemplate.heading = ( Heading / 180 ) * math.pi
|
||||
|
||||
StaticTemplate.CountryID = nil
|
||||
StaticTemplate.CoalitionID = nil
|
||||
StaticTemplate.CategoryID = nil
|
||||
|
||||
local Static = coalition.addStaticObject( self.CountryID, StaticTemplate )
|
||||
|
||||
self.SpawnIndex = self.SpawnIndex + 1
|
||||
|
||||
return Static
|
||||
end
|
||||
|
||||
--- Creates a new @{Static} from a @{Zone}.
|
||||
-- @param #SPAWNSTATIC self
|
||||
-- @param Core.Zone#ZONE_BASE Zone The Zone where to spawn the static.
|
||||
-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
|
||||
-- @param #string (optional) The name of the new static.
|
||||
-- @return #SPAWNSTATIC
|
||||
function SPAWNSTATIC:SpawnFromZone( Zone, Heading, NewName )
|
||||
self:F( { Zone, Heading, NewName } )
|
||||
|
||||
local Static = self:SpawnFromPointVec2( Zone:GetPointVec2(), Heading, NewName )
|
||||
|
||||
return Static
|
||||
end
|
||||
|
||||
@@ -7,8 +7,25 @@
|
||||
-- DETECTION classes facilitate the detection of enemy units within the battle zone executed by FACs (Forward Air Controllers) or RECCEs (Reconnassance Units).
|
||||
-- DETECTION uses the in-built detection capabilities of DCS World, but adds new functionalities.
|
||||
--
|
||||
-- Please watch this [youtube video](https://youtu.be/C7p81dUwP-E) that explains the detection concepts.
|
||||
-- Find the DETECTION classes documentation further in this document in the globals section.
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
-- # Demo Missions
|
||||
--
|
||||
-- ### [DETECTION Demo Missions and Source Code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/DET%20-%20Detection)
|
||||
--
|
||||
-- ### [DETECTION Demo Missions, only for Beta Testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/DET%20-%20Detection)
|
||||
--
|
||||
-- ### [ALL Demo Missions pack of the Latest Release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
-- # YouTube Channel
|
||||
--
|
||||
-- ### [DETECTION YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl3Cf5jpI6BS0sBOVWK__tji)
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
-- ### Contributions:
|
||||
--
|
||||
@@ -23,16 +40,24 @@
|
||||
|
||||
do -- DETECTION_BASE
|
||||
|
||||
--- # 1) DETECTION_BASE class, extends @{Fsm#FSM}
|
||||
--- @type DETECTION_BASE
|
||||
-- @field Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role.
|
||||
-- @field Dcs.DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected.
|
||||
-- @field #DETECTION_BASE.DetectedObjects DetectedObjects The list of detected objects.
|
||||
-- @field #table DetectedObjectsIdentified Map of the DetectedObjects identified.
|
||||
-- @field #number DetectionRun
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- DETECTION_BASE class, extends @{Fsm#FSM}
|
||||
--
|
||||
-- The DETECTION_BASE class defines the core functions to administer detected objects.
|
||||
-- The DETECTION_BASE class will detect objects within the battle zone for a list of @{Group}s detecting targets following (a) detection method(s).
|
||||
--
|
||||
-- ## 1.1) DETECTION_BASE constructor
|
||||
-- ## DETECTION_BASE constructor
|
||||
--
|
||||
-- Construct a new DETECTION_BASE instance using the @{#DETECTION_BASE.New}() method.
|
||||
--
|
||||
-- ## 1.2) DETECTION_BASE initialization
|
||||
-- ## Initialization
|
||||
--
|
||||
-- By default, detection will return detected objects with all the detection sensors available.
|
||||
-- However, you can ask how the objects were found with specific detection methods.
|
||||
@@ -48,7 +73,29 @@ do -- DETECTION_BASE
|
||||
-- * @{#DETECTION_BASE.InitDetectRWR}(): Detected using RWR.
|
||||
-- * @{#DETECTION_BASE.InitDetectDLINK}(): Detected using DLINK.
|
||||
--
|
||||
-- ## 1.3) DETECTION_BASE derived classes group the detected units into a DetectedItems[] list
|
||||
-- ## **Filter** detected units based on **category of the unit**
|
||||
--
|
||||
-- Filter the detected units based on Unit.Category using the method @{#DETECTION_BASE.FilterCategories}().
|
||||
-- The different values of Unit.Category can be:
|
||||
--
|
||||
-- * Unit.Category.AIRPLANE
|
||||
-- * Unit.Category.GROUND_UNIT
|
||||
-- * Unit.Category.HELICOPTER
|
||||
-- * Unit.Category.SHIP
|
||||
-- * Unit.Category.STRUCTURE
|
||||
--
|
||||
-- Multiple Unit.Category entries can be given as a table and then these will be evaluated as an OR expression.
|
||||
--
|
||||
-- Example to filter a single category (Unit.Category.AIRPLANE).
|
||||
--
|
||||
-- DetectionObject:FilterCategories( Unit.Category.AIRPLANE )
|
||||
--
|
||||
-- Example to filter multiple categories (Unit.Category.AIRPLANE, Unit.Category.HELICOPTER). Note the {}.
|
||||
--
|
||||
-- DetectionObject:FilterCategories( { Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
|
||||
--
|
||||
--
|
||||
-- ## **DETECTION_ derived classes** group the detected units into a **DetectedItems[]** list
|
||||
--
|
||||
-- DETECTION_BASE derived classes build a list called DetectedItems[], which is essentially a first later
|
||||
-- of grouping of detected units. Each DetectedItem within the DetectedItems[] list contains
|
||||
@@ -67,7 +114,7 @@ do -- DETECTION_BASE
|
||||
-- * A DetectedSet from the DetectedItems[] list can be retrieved using the method @{Detection#DETECTION_BASE.GetDetectedSet}( DetectedItemIndex ).
|
||||
-- This method retrieves the Set from a DetectedItem element from the DetectedItem list (DetectedItems[ DetectedItemIndex ].Set ).
|
||||
--
|
||||
-- ## 1.4) Apply additional Filters to fine-tune the detected objects
|
||||
-- ## **Visual filters** to fine-tune the probability of the detected objects
|
||||
--
|
||||
-- By default, DCS World will return any object that is in LOS and within "visual reach", or detectable through one of the electronic detection means.
|
||||
-- That being said, the DCS World detection algorithm can sometimes be unrealistic.
|
||||
@@ -88,7 +135,8 @@ do -- DETECTION_BASE
|
||||
-- I advise however, that, when you first use the DETECTION derived classes, that you don't use these filters.
|
||||
-- Only when you experience unrealistic behaviour in your missions, these filters could be applied.
|
||||
--
|
||||
-- ### 1.4.1 ) Distance visual detection probability
|
||||
--
|
||||
-- ### Distance visual detection probability
|
||||
--
|
||||
-- Upon a **visual** detection, the further away a detected object is, the less likely it is to be detected properly.
|
||||
-- Also, the speed of accurate detection plays a role.
|
||||
@@ -102,7 +150,7 @@ do -- DETECTION_BASE
|
||||
--
|
||||
-- Use the method @{Detection#DETECTION_BASE.SetDistanceProbability}() to set the probability factor upon a 10 km distance.
|
||||
--
|
||||
-- ### 1.4.2 ) Alpha Angle visual detection probability
|
||||
-- ### Alpha Angle visual detection probability
|
||||
--
|
||||
-- Upon a **visual** detection, the higher the unit is during the detecting process, the more likely the detected unit is to be detected properly.
|
||||
-- A detection at a 90% alpha angle is the most optimal, a detection at 10% is less and a detection at 0% is less likely to be correct.
|
||||
@@ -114,7 +162,7 @@ do -- DETECTION_BASE
|
||||
--
|
||||
-- Use the method @{Detection#DETECTION_BASE.SetAlphaAngleProbability}() to set the probability factor if 0°.
|
||||
--
|
||||
-- ### 1.4.3 ) Cloudy Zones detection probability
|
||||
-- ### Cloudy Zones detection probability
|
||||
--
|
||||
-- Upon a **visual** detection, the more a detected unit is within a cloudy zone, the less likely the detected unit is to be detected successfully.
|
||||
-- The Cloudy Zones work with the ZONE_BASE derived classes. The mission designer can define within the mission
|
||||
@@ -129,12 +177,12 @@ do -- DETECTION_BASE
|
||||
-- Typically, this kind of filter would be applied for very specific areas were a detection needs to be very realisting for
|
||||
-- AI not to detect so easily targets within a forrest or village rich area.
|
||||
--
|
||||
-- ## 1.5 ) Accept / Reject detected units
|
||||
-- ## Accept / Reject detected units
|
||||
--
|
||||
-- DETECTION_BASE can accept or reject successful detections based on the location of the detected object,
|
||||
-- if it is located in range or located inside or outside of specific zones.
|
||||
--
|
||||
-- ### 1.5.1 ) Detection acceptance of within range limit
|
||||
-- ### Detection acceptance of within range limit
|
||||
--
|
||||
-- A range can be set that will limit a successful detection for a unit.
|
||||
-- Use the method @{Detection#DETECTION_BASE.SetAcceptRange}() to apply a range in meters till where detected units will be accepted.
|
||||
@@ -151,7 +199,7 @@ do -- DETECTION_BASE
|
||||
-- Detection:Start()
|
||||
--
|
||||
--
|
||||
-- ### 1.5.2 ) Detection acceptance if within zone(s).
|
||||
-- ### Detection acceptance if within zone(s).
|
||||
--
|
||||
-- Specific ZONE_BASE object(s) can be given as a parameter, which will only accept a detection if the unit is within the specified ZONE_BASE object(s).
|
||||
-- Use the method @{Detection#DETECTION_BASE.SetAcceptZones}() will accept detected units if they are within the specified zones.
|
||||
@@ -171,7 +219,7 @@ do -- DETECTION_BASE
|
||||
-- -- Start the Detection.
|
||||
-- Detection:Start()
|
||||
--
|
||||
-- ### 1.5.3 ) Detection rejectance if within zone(s).
|
||||
-- ### Detection rejectance if within zone(s).
|
||||
--
|
||||
-- Specific ZONE_BASE object(s) can be given as a parameter, which will reject detection if the unit is within the specified ZONE_BASE object(s).
|
||||
-- Use the method @{Detection#DETECTION_BASE.SetRejectZones}() will reject detected units if they are within the specified zones.
|
||||
@@ -192,29 +240,24 @@ do -- DETECTION_BASE
|
||||
-- -- Start the Detection.
|
||||
-- Detection:Start()
|
||||
--
|
||||
-- ## 1.6) DETECTION_BASE is a Finite State Machine
|
||||
-- ## DETECTION_BASE is a Finite State Machine
|
||||
--
|
||||
-- Various Events and State Transitions can be tailored using DETECTION_BASE.
|
||||
--
|
||||
-- ### 1.6.1) DETECTION_BASE States
|
||||
-- ### DETECTION_BASE States
|
||||
--
|
||||
-- * **Detecting**: The detection is running.
|
||||
-- * **Stopped**: The detection is stopped.
|
||||
--
|
||||
-- ### 1.6.2) DETECTION_BASE Events
|
||||
-- ### DETECTION_BASE Events
|
||||
--
|
||||
-- * **Start**: Start the detection process.
|
||||
-- * **Detect**: Detect new units.
|
||||
-- * **Detected**: New units have been detected.
|
||||
-- * **Stop**: Stop the detection process.
|
||||
--
|
||||
-- @field #DETECTION_BASE DETECTION_BASE
|
||||
--
|
||||
-- @type DETECTION_BASE
|
||||
-- @field Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role.
|
||||
-- @field Dcs.DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected.
|
||||
-- @field #DETECTION_BASE.DetectedObjects DetectedObjects The list of detected objects.
|
||||
-- @field #table DetectedObjectsIdentified Map of the DetectedObjects identified.
|
||||
-- @field #number DetectionRun
|
||||
-- @extends Core.Fsm#FSM
|
||||
DETECTION_BASE = {
|
||||
ClassName = "DETECTION_BASE",
|
||||
DetectionSetGroup = nil,
|
||||
@@ -267,11 +310,19 @@ do -- DETECTION_BASE
|
||||
self.DetectionInterval = 30
|
||||
|
||||
self:InitDetectVisual( true )
|
||||
self:InitDetectOptical( false )
|
||||
self:InitDetectRadar( false )
|
||||
self:InitDetectRWR( false )
|
||||
self:InitDetectIRST( false )
|
||||
self:InitDetectDLINK( false )
|
||||
self:InitDetectOptical( true )
|
||||
self:InitDetectRadar( true )
|
||||
self:InitDetectRWR( true )
|
||||
self:InitDetectIRST( true )
|
||||
self:InitDetectDLINK( true )
|
||||
|
||||
self:FilterCategories( {
|
||||
Unit.Category.AIRPLANE,
|
||||
Unit.Category.GROUND_UNIT,
|
||||
Unit.Category.HELICOPTER,
|
||||
Unit.Category.SHIP,
|
||||
Unit.Category.STRUCTURE
|
||||
} )
|
||||
|
||||
-- Create FSM transitions.
|
||||
|
||||
@@ -498,9 +549,8 @@ do -- DETECTION_BASE
|
||||
|
||||
for DetectionObjectID, Detection in pairs( DetectedTargets ) do
|
||||
local DetectedObject = Detection.object -- Dcs.DCSWrapper.Object#Object
|
||||
self:T2( DetectedObject )
|
||||
|
||||
if DetectedObject and DetectedObject:isExist() and DetectedObject.id_ < 50000000 then
|
||||
if DetectedObject and DetectedObject:isExist() and DetectedObject.id_ < 50000000 then -- and ( DetectedObject:getCategory() == Object.Category.UNIT or DetectedObject:getCategory() == Object.Category.STATIC ) then
|
||||
|
||||
local DetectionAccepted = true
|
||||
|
||||
@@ -515,10 +565,14 @@ do -- DETECTION_BASE
|
||||
( DetectedObjectVec3.y - DetectionGroupVec3.y )^2 +
|
||||
( DetectedObjectVec3.z - DetectionGroupVec3.z )^2
|
||||
) ^ 0.5 / 1000
|
||||
|
||||
local DetectedUnitCategory = DetectedObject:getDesc().category
|
||||
|
||||
self:T( { "Detected Target", DetectionGroupName, DetectedObjectName, Distance } )
|
||||
|
||||
self:T( { "Detected Target:", DetectionGroupName, DetectedObjectName, Distance, DetectedUnitCategory, DetectedCategory } )
|
||||
|
||||
-- Calculate Acceptance
|
||||
|
||||
DetectionAccepted = self._.FilterCategories[DetectedUnitCategory] ~= nil and DetectionAccepted or false
|
||||
|
||||
if self.AcceptRange and Distance > self.AcceptRange then
|
||||
DetectionAccepted = false
|
||||
@@ -625,10 +679,10 @@ do -- DETECTION_BASE
|
||||
end
|
||||
|
||||
if self.DetectionCount > 0 and self.DetectionRun == self.DetectionCount then
|
||||
self:__Detect( self.DetectionInterval )
|
||||
|
||||
self:T( "--> Create Detection Sets" )
|
||||
self:CreateDetectionSets()
|
||||
|
||||
self:__Detect( self.DetectionInterval )
|
||||
end
|
||||
|
||||
end
|
||||
@@ -645,6 +699,8 @@ do -- DETECTION_BASE
|
||||
function DETECTION_BASE:InitDetectVisual( DetectVisual )
|
||||
|
||||
self.DetectVisual = DetectVisual
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Detect Optical.
|
||||
@@ -655,6 +711,8 @@ do -- DETECTION_BASE
|
||||
self:F2()
|
||||
|
||||
self.DetectOptical = DetectOptical
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Detect Radar.
|
||||
@@ -665,6 +723,8 @@ do -- DETECTION_BASE
|
||||
self:F2()
|
||||
|
||||
self.DetectRadar = DetectRadar
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Detect IRST.
|
||||
@@ -675,6 +735,8 @@ do -- DETECTION_BASE
|
||||
self:F2()
|
||||
|
||||
self.DetectIRST = DetectIRST
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Detect RWR.
|
||||
@@ -685,6 +747,8 @@ do -- DETECTION_BASE
|
||||
self:F2()
|
||||
|
||||
self.DetectRWR = DetectRWR
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Detect DLINK.
|
||||
@@ -695,9 +759,52 @@ do -- DETECTION_BASE
|
||||
self:F2()
|
||||
|
||||
self.DetectDLINK = DetectDLINK
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
do -- Filter methods
|
||||
|
||||
--- Filter the detected units based on Unit.Category
|
||||
-- The different values of Unit.Category can be:
|
||||
--
|
||||
-- * Unit.Category.AIRPLANE
|
||||
-- * Unit.Category.GROUND_UNIT
|
||||
-- * Unit.Category.HELICOPTER
|
||||
-- * Unit.Category.SHIP
|
||||
-- * Unit.Category.STRUCTURE
|
||||
--
|
||||
-- Multiple Unit.Category entries can be given as a table and then these will be evaluated as an OR expression.
|
||||
--
|
||||
-- Example to filter a single category (Unit.Category.AIRPLANE).
|
||||
--
|
||||
-- DetectionObject:FilterCategories( Unit.Category.AIRPLANE )
|
||||
--
|
||||
-- Example to filter multiple categories (Unit.Category.AIRPLANE, Unit.Category.HELICOPTER). Note the {}.
|
||||
--
|
||||
-- DetectionObject:FilterCategories( { Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
|
||||
--
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param #list<Dcs.DCSUnit#Unit> FilterCategories The Categories entries
|
||||
-- @return #DETECTION_BASE self
|
||||
function DETECTION_BASE:FilterCategories( FilterCategories )
|
||||
self:F2()
|
||||
|
||||
self._.FilterCategories = {}
|
||||
if type( FilterCategories ) == "table" then
|
||||
for CategoryID, Category in pairs( FilterCategories ) do
|
||||
self._.FilterCategories[Category] = Category
|
||||
end
|
||||
else
|
||||
self._.FilterCategories[FilterCategories] = FilterCategories
|
||||
end
|
||||
return self
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
do
|
||||
|
||||
|
||||
@@ -1,112 +1,26 @@
|
||||
--- Single-Player:**Yes** / Multi-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**All** --
|
||||
-- **Spawn groups of units dynamically in your missions.**
|
||||
--- **Functional** -- Spawn dynamically new GROUPs in your missions.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ===
|
||||
-- ====
|
||||
--
|
||||
-- # 1) @{#SPAWN} class, extends @{Base#BASE}
|
||||
-- The documentation of the SPAWN class can be found further in this document.
|
||||
--
|
||||
-- The @{#SPAWN} class allows to spawn dynamically new groups, based on pre-defined initialization settings, modifying the behaviour when groups are spawned.
|
||||
-- For each group to be spawned, within the mission editor, a group has to be created with the "late activation flag" set. We call this group the *"Spawn Template"* of the SPAWN object.
|
||||
-- A reference to this Spawn Template needs to be provided when constructing the SPAWN object, by indicating the name of the group within the mission editor in the constructor methods.
|
||||
-- ====
|
||||
--
|
||||
-- Within the SPAWN object, there is an internal index that keeps track of which group from the internal group list was spawned.
|
||||
-- When new groups get spawned by using the SPAWN methods (see below), it will be validated whether the Limits (@{#SPAWN.Limit}) of the SPAWN object are not reached.
|
||||
-- When all is valid, a new group will be created by the spawning methods, and the internal index will be increased with 1.
|
||||
-- # Demo Missions
|
||||
--
|
||||
-- Regarding the name of new spawned groups, a _SpawnPrefix_ will be assigned for each new group created.
|
||||
-- If you want to have the Spawn Template name to be used as the _SpawnPrefix_ name, use the @{#SPAWN.New} constructor.
|
||||
-- However, when the @{#SPAWN.NewWithAlias} constructor was used, the Alias name will define the _SpawnPrefix_ name.
|
||||
-- Groups will follow the following naming structure when spawned at run-time:
|
||||
-- ### [SPAWN Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/SPA%20-%20Spawning)
|
||||
--
|
||||
-- 1. Spawned groups will have the name _SpawnPrefix_#ggg, where ggg is a counter from 0 to 999.
|
||||
-- 2. Spawned units will have the name _SpawnPrefix_#ggg-uu, where uu is a counter from 0 to 99 for each new spawned unit belonging to the group.
|
||||
--
|
||||
-- Some additional notes that need to be remembered:
|
||||
--
|
||||
-- * Templates are actually groups defined within the mission editor, with the flag "Late Activation" set. As such, these groups are never used within the mission, but are used by the @{#SPAWN} module.
|
||||
-- * It is important to defined BEFORE you spawn new groups, a proper initialization of the SPAWN instance is done with the options you want to use.
|
||||
-- * When designing a mission, NEVER name groups using a "#" within the name of the group Spawn Template(s), or the SPAWN module logic won't work anymore.
|
||||
--
|
||||
-- ## 1.1) SPAWN construction methods
|
||||
--
|
||||
-- Create a new SPAWN object with the @{#SPAWN.New}() or the @{#SPAWN.NewWithAlias}() methods:
|
||||
--
|
||||
-- * @{#SPAWN.New}(): Creates a new SPAWN object taking the name of the group that represents the GROUP Template (definition).
|
||||
-- * @{#SPAWN.NewWithAlias}(): Creates a new SPAWN object taking the name of the group that represents the GROUP Template (definition), and gives each spawned @{Group} an different name.
|
||||
-- ### [SPAWN Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SPA%20-%20Spawning)
|
||||
--
|
||||
-- It is important to understand how the SPAWN class works internally. The SPAWN object created will contain internally a list of groups that will be spawned and that are already spawned.
|
||||
-- The initialization methods will modify this list of groups so that when a group gets spawned, ALL information is already prepared when spawning. This is done for performance reasons.
|
||||
-- So in principle, the group list will contain all parameters and configurations after initialization, and when groups get actually spawned, this spawning can be done quickly and efficient.
|
||||
--
|
||||
-- ## 1.2) SPAWN initialization methods
|
||||
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
|
||||
--
|
||||
-- A spawn object will behave differently based on the usage of **initialization** methods, which all start with the **Init** prefix:
|
||||
-- ====
|
||||
--
|
||||
-- * @{#SPAWN.InitKeepUnitNames}(): Keeps the unit names as defined within the mission editor, but note that anything after a # mark is ignored, and any spaces before and after the resulting name are removed. IMPORTANT! This method MUST be the first used after :New !!!
|
||||
-- * @{#SPAWN.InitLimit}(): Limits the amount of groups that can be alive at the same time and that can be dynamically spawned.
|
||||
-- * @{#SPAWN.InitRandomizeRoute}(): Randomize the routes of spawned groups, and for air groups also optionally the height.
|
||||
-- * @{#SPAWN.InitRandomizeTemplate}(): Randomize the group templates so that when a new group is spawned, a random group template is selected from one of the templates defined.
|
||||
-- * @{#SPAWN.InitUnControlled}(): Spawn plane groups uncontrolled.
|
||||
-- * @{#SPAWN.InitArray}(): Make groups visible before they are actually activated, and order these groups like a batallion in an array.
|
||||
-- * @{#SPAWN.InitRepeat}(): Re-spawn groups when they land at the home base. Similar methods are @{#SPAWN.InitRepeatOnLanding} and @{#SPAWN.InitRepeatOnEngineShutDown}.
|
||||
-- * @{#SPAWN.InitRandomizePosition}(): Randomizes the position of @{Group}s that are spawned within a **radius band**, given an Outer and Inner radius, from the point that the spawn happens.
|
||||
-- * @{#SPAWN.InitRandomizeUnits}(): Randomizes the @{Unit}s in the @{Group} that is spawned within a **radius band**, given an Outer and Inner radius.
|
||||
-- * @{#SPAWN.InitRandomizeZones}(): Randomizes the spawning between a predefined list of @{Zone}s that are declared using this function. Each zone can be given a probability factor.
|
||||
-- * @{#SPAWN.InitAIOn}(): Turns the AI On when spawning the new @{Group} object.
|
||||
-- * @{#SPAWN.InitAIOff}(): Turns the AI Off when spawning the new @{Group} object.
|
||||
-- * @{#SPAWN.InitAIOnOff}(): Turns the AI On or Off when spawning the new @{Group} object.
|
||||
-- # YouTube Channel
|
||||
--
|
||||
-- ## 1.3) SPAWN spawning methods
|
||||
--
|
||||
-- Groups can be spawned at different times and methods:
|
||||
--
|
||||
-- * @{#SPAWN.Spawn}(): Spawn one new group based on the last spawned index.
|
||||
-- * @{#SPAWN.ReSpawn}(): Re-spawn a group based on a given index.
|
||||
-- * @{#SPAWN.SpawnScheduled}(): Spawn groups at scheduled but randomized intervals. You can use @{#SPAWN.SpawnScheduleStart}() and @{#SPAWN.SpawnScheduleStop}() to start and stop the schedule respectively.
|
||||
-- * @{#SPAWN.SpawnFromVec3}(): Spawn a new group from a Vec3 coordinate. (The group will can be spawned at a point in the air).
|
||||
-- * @{#SPAWN.SpawnFromVec2}(): Spawn a new group from a Vec2 coordinate. (The group will be spawned at land height ).
|
||||
-- * @{#SPAWN.SpawnFromStatic}(): Spawn a new group from a structure, taking the position of a @{Static}.
|
||||
-- * @{#SPAWN.SpawnFromUnit}(): Spawn a new group taking the position of a @{Unit}.
|
||||
-- * @{#SPAWN.SpawnInZone}(): Spawn a new group in a @{Zone}.
|
||||
--
|
||||
-- Note that @{#SPAWN.Spawn} and @{#SPAWN.ReSpawn} return a @{GROUP#GROUP.New} object, that contains a reference to the DCSGroup object.
|
||||
-- You can use the @{GROUP} object to do further actions with the DCSGroup.
|
||||
--
|
||||
-- ## 1.4) Retrieve alive GROUPs spawned by the SPAWN object
|
||||
--
|
||||
-- The SPAWN class administers which GROUPS it has reserved (in stock) or has created during mission execution.
|
||||
-- Every time a SPAWN object spawns a new GROUP object, a reference to the GROUP object is added to an internal table of GROUPS.
|
||||
-- SPAWN provides methods to iterate through that internal GROUP object reference table:
|
||||
--
|
||||
-- * @{#SPAWN.GetFirstAliveGroup}(): Will find the first alive GROUP it has spawned, and return the alive GROUP object and the first Index where the first alive GROUP object has been found.
|
||||
-- * @{#SPAWN.GetNextAliveGroup}(): Will find the next alive GROUP object from a given Index, and return a reference to the alive GROUP object and the next Index where the alive GROUP has been found.
|
||||
-- * @{#SPAWN.GetLastAliveGroup}(): Will find the last alive GROUP object, and will return a reference to the last live GROUP object and the last Index where the last alive GROUP object has been found.
|
||||
--
|
||||
-- You can use the methods @{#SPAWN.GetFirstAliveGroup}() and sequently @{#SPAWN.GetNextAliveGroup}() to iterate through the alive GROUPS within the SPAWN object, and to actions... See the respective methods for an example.
|
||||
-- The method @{#SPAWN.GetGroupFromIndex}() will return the GROUP object reference from the given Index, dead or alive...
|
||||
--
|
||||
-- ## 1.5) SPAWN object cleaning
|
||||
--
|
||||
-- Sometimes, it will occur during a mission run-time, that ground or especially air objects get damaged, and will while being damged stop their activities, while remaining alive.
|
||||
-- In such cases, the SPAWN object will just sit there and wait until that group gets destroyed, but most of the time it won't,
|
||||
-- and it may occur that no new groups are or can be spawned as limits are reached.
|
||||
-- To prevent this, a @{#SPAWN.InitCleanUp}() initialization method has been defined that will silently monitor the status of each spawned group.
|
||||
-- Once a group has a velocity = 0, and has been waiting for a defined interval, that group will be cleaned or removed from run-time.
|
||||
-- There is a catch however :-) If a damaged group has returned to an airbase within the coalition, that group will not be considered as "lost"...
|
||||
-- In such a case, when the inactive group is cleaned, a new group will Re-spawned automatically.
|
||||
-- This models AI that has succesfully returned to their airbase, to restart their combat activities.
|
||||
-- Check the @{#SPAWN.InitCleanUp}() for further info.
|
||||
--
|
||||
-- ## 1.6) Catch the @{Group} spawn event in a callback function!
|
||||
--
|
||||
-- When using the SpawnScheduled method, new @{Group}s are created following the schedule timing parameters.
|
||||
-- When a new @{Group} is spawned, you maybe want to execute actions with that group spawned at the spawn event.
|
||||
-- To SPAWN class supports this functionality through the @{#SPAWN.OnSpawnGroup}( **function( SpawnedGroup ) end ** ) method, which takes a function as a parameter that you can define locally.
|
||||
-- Whenever a new @{Group} is spawned, the given function is called, and the @{Group} that was just spawned, is given as a parameter.
|
||||
-- As a result, your spawn event handling function requires one parameter to be declared, which will contain the spawned @{Group} object.
|
||||
-- A coding example is provided at the description of the @{#SPAWN.OnSpawnGroup}( **function( SpawnedGroup ) end ** ) method.
|
||||
-- ### [SPAWN YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl1jirWIo4t4YxqN-HxjqRkL)
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
@@ -119,44 +33,34 @@
|
||||
--
|
||||
-- Hereby the change log:
|
||||
--
|
||||
-- 2017-04-08: SPAWN:**InitDelayOnOff( DelayOnOff )** added.
|
||||
-- 2017-04-08: SPAWN:**InitDelayOn()** added.
|
||||
-- 2017-04-08: SPAWN:**InitDelayOff()** added.
|
||||
--
|
||||
-- 2017-03-14: SPAWN:**InitKeepUnitNames()** added.
|
||||
-- 2017-03-14: SPAWN:**InitRandomizePosition( RandomizePosition, OuterRadious, InnerRadius )** added.
|
||||
-- 2017-03-14: SPAWN:**InitRandomizePosition( RandomizePosition, OuterRadious, InnerRadius )** added.
|
||||
--
|
||||
-- 2017-02-04: SPAWN:InitUnControlled( **UnControlled** ) replaces SPAWN:InitUnControlled().
|
||||
-- 2017-02-04: SPAWN:InitUnControlled( **UnControlled** ) replaces SPAWN:InitUnControlled().
|
||||
--
|
||||
-- 2017-01-24: SPAWN:**InitAIOnOff( AIOnOff )** added.
|
||||
--
|
||||
-- 2017-01-24: SPAWN:**InitAIOn()** added.
|
||||
--
|
||||
-- 2017-01-24: SPAWN:**InitAIOff()** added.
|
||||
--
|
||||
-- 2016-08-15: SPAWN:**InitCleanUp**( SpawnCleanUpInterval ) replaces SPAWN:_CleanUp_( SpawnCleanUpInterval ).
|
||||
-- 2017-01-24: SPAWN:**InitAIOnOff( AIOnOff )** added.
|
||||
-- 2017-01-24: SPAWN:**InitAIOn()** added.
|
||||
-- 2017-01-24: SPAWN:**InitAIOff()** added.
|
||||
--
|
||||
-- 2016-08-15: SPAWN:**InitCleanUp**( SpawnCleanUpInterval ) replaces SPAWN:_CleanUp_( SpawnCleanUpInterval ).
|
||||
-- 2016-08-15: SPAWN:**InitRandomizeZones( SpawnZones )** added.
|
||||
--
|
||||
-- 2016-08-14: SPAWN:**OnSpawnGroup**( SpawnCallBackFunction, ... ) replaces SPAWN:_SpawnFunction_( SpawnCallBackFunction, ... ).
|
||||
--
|
||||
-- 2016-08-14: SPAWN.SpawnInZone( Zone, __RandomizeGroup__, SpawnIndex ) replaces SpawnInZone( Zone, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ).
|
||||
--
|
||||
-- 2016-08-14: SPAWN.SpawnFromVec3( Vec3, SpawnIndex ) replaces SpawnFromVec3( Vec3, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ):
|
||||
--
|
||||
-- 2016-08-14: SPAWN.SpawnFromVec2( Vec2, SpawnIndex ) replaces SpawnFromVec2( Vec2, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ):
|
||||
--
|
||||
-- 2016-08-14: SPAWN.SpawnFromUnit( SpawnUnit, SpawnIndex ) replaces SpawnFromUnit( SpawnUnit, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ):
|
||||
--
|
||||
-- 2016-08-14: SPAWN.SpawnFromUnit( SpawnUnit, SpawnIndex ) replaces SpawnFromStatic( SpawnStatic, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ):
|
||||
--
|
||||
-- 2016-08-14: SPAWN.**InitRandomizeUnits( RandomizeUnits, OuterRadius, InnerRadius )** added:
|
||||
--
|
||||
-- 2016-08-14: SPAWN.**Init**Limit( SpawnMaxUnitsAlive, SpawnMaxGroups ) replaces SPAWN._Limit_( SpawnMaxUnitsAlive, SpawnMaxGroups ):
|
||||
--
|
||||
-- 2016-08-14: SPAWN.**Init**Array( SpawnAngle, SpawnWidth, SpawnDeltaX, SpawnDeltaY ) replaces SPAWN._Array_( SpawnAngle, SpawnWidth, SpawnDeltaX, SpawnDeltaY ).
|
||||
--
|
||||
-- 2016-08-14: SPAWN.**Init**RandomizeRoute( SpawnStartPoint, SpawnEndPoint, SpawnRadius, SpawnHeight ) replaces SPAWN._RandomizeRoute_( SpawnStartPoint, SpawnEndPoint, SpawnRadius, SpawnHeight ).
|
||||
--
|
||||
-- 2016-08-14: SPAWN.**Init**RandomizeTemplate( SpawnTemplatePrefixTable ) replaces SPAWN._RandomizeTemplate_( SpawnTemplatePrefixTable ).
|
||||
--
|
||||
-- 2016-08-14: SPAWN.**Init**UnControlled() replaces SPAWN._UnControlled_().
|
||||
-- 2016-08-14: SPAWN:**OnSpawnGroup**( SpawnCallBackFunction, ... ) replaces SPAWN:_SpawnFunction_( SpawnCallBackFunction, ... ).
|
||||
-- 2016-08-14: SPAWN.SpawnInZone( Zone, __RandomizeGroup__, SpawnIndex ) replaces SpawnInZone( Zone, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ).
|
||||
-- 2016-08-14: SPAWN.SpawnFromVec3( Vec3, SpawnIndex ) replaces SpawnFromVec3( Vec3, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ).
|
||||
-- 2016-08-14: SPAWN.SpawnFromVec2( Vec2, SpawnIndex ) replaces SpawnFromVec2( Vec2, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ).
|
||||
-- 2016-08-14: SPAWN.SpawnFromUnit( SpawnUnit, SpawnIndex ) replaces SpawnFromUnit( SpawnUnit, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ).
|
||||
-- 2016-08-14: SPAWN.SpawnFromUnit( SpawnUnit, SpawnIndex ) replaces SpawnFromStatic( SpawnStatic, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ).
|
||||
-- 2016-08-14: SPAWN.**InitRandomizeUnits( RandomizeUnits, OuterRadius, InnerRadius )** added.
|
||||
-- 2016-08-14: SPAWN.**Init**Limit( SpawnMaxUnitsAlive, SpawnMaxGroups ) replaces SPAWN._Limit_( SpawnMaxUnitsAlive, SpawnMaxGroups ).
|
||||
-- 2016-08-14: SPAWN.**Init**Array( SpawnAngle, SpawnWidth, SpawnDeltaX, SpawnDeltaY ) replaces SPAWN._Array_( SpawnAngle, SpawnWidth, SpawnDeltaX, SpawnDeltaY ).
|
||||
-- 2016-08-14: SPAWN.**Init**RandomizeRoute( SpawnStartPoint, SpawnEndPoint, SpawnRadius, SpawnHeight ) replaces SPAWN._RandomizeRoute_( SpawnStartPoint, SpawnEndPoint, SpawnRadius, SpawnHeight ).
|
||||
-- 2016-08-14: SPAWN.**Init**RandomizeTemplate( SpawnTemplatePrefixTable ) replaces SPAWN._RandomizeTemplate_( SpawnTemplatePrefixTable ).
|
||||
-- 2016-08-14: SPAWN.**Init**UnControlled() replaces SPAWN._UnControlled_().
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -177,7 +81,6 @@
|
||||
|
||||
--- SPAWN Class
|
||||
-- @type SPAWN
|
||||
-- @extends Core.Base#BASE
|
||||
-- @field ClassName
|
||||
-- @field #string SpawnTemplatePrefix
|
||||
-- @field #string SpawnAliasPrefix
|
||||
@@ -186,6 +89,214 @@
|
||||
-- @field #number SpawnIndex
|
||||
-- @field #number MaxAliveGroups
|
||||
-- @field #SPAWN.SpawnZoneTable SpawnZoneTable
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
--- # SPAWN class, extends @{Base#BASE}
|
||||
--
|
||||
-- The SPAWN class allows to spawn dynamically new groups.
|
||||
-- Each SPAWN object needs to be have a related **template group** setup in the Mission Editor (ME),
|
||||
-- which is a normal group with the **Late Activation** flag set.
|
||||
-- This template group will never be activated in your mission.
|
||||
-- SPAWN uses that **template group** to reference to all the characteristics
|
||||
-- (air, ground, livery, unit composition, formation, skill level etc) of each new group to be spawned.
|
||||
--
|
||||
-- Therefore, when creating a SPAWN object, the @{#SPAWN.New} and @{#SPAWN.NewWithAlias} require
|
||||
-- **the name of the template group** to be given as a string to those constructor methods.
|
||||
--
|
||||
-- Initialization settings can be applied on the SPAWN object,
|
||||
-- which modify the behaviour or the way groups are spawned.
|
||||
-- These initialization methods have the prefix **Init**.
|
||||
-- There are also spawn methods with the prefix **Spawn** and will spawn new groups in various ways.
|
||||
--
|
||||
-- ### IMPORTANT! The methods with prefix **Init** must be used before any methods with prefix **Spawn** method are used, or unexpected results may appear!!!
|
||||
--
|
||||
-- Because SPAWN can spawn multiple groups of a template group,
|
||||
-- SPAWN has an **internal index** that keeps track
|
||||
-- which was the latest group that was spawned.
|
||||
--
|
||||
-- **Limits** can be set on how many groups can be spawn in each SPAWN object,
|
||||
-- using the method @{#SPAWN.InitLimit}. SPAWN has 2 kind of limits:
|
||||
--
|
||||
-- * The maximum amount of @{Unit}s that can be **alive** at the same time...
|
||||
-- * The maximum amount of @{Group}s that can be **spawned**... This is more of a **resource**-type of limit.
|
||||
--
|
||||
-- When new groups get spawned using the **Spawn** methods,
|
||||
-- it will be evaluated whether any limits have been reached.
|
||||
-- When no spawn limit is reached, a new group will be created by the spawning methods,
|
||||
-- and the internal index will be increased with 1.
|
||||
--
|
||||
-- These limits ensure that your mission does not accidentally get flooded with spawned groups.
|
||||
-- Additionally, it also guarantees that independent of the group composition,
|
||||
-- at any time, the most optimal amount of groups are alive in your mission.
|
||||
-- For example, if your template group has a group composition of 10 units, and you specify a limit of 100 units alive at the same time,
|
||||
-- with unlimited resources = :InitLimit( 100, 0 ) and 10 groups are alive, but two groups have only one unit alive in the group,
|
||||
-- then a sequent Spawn(Scheduled) will allow a new group to be spawned!!!
|
||||
--
|
||||
-- ### IMPORTANT!! If a limit has been reached, it is possible that a **Spawn** method returns **nil**, meaning, no @{Group} had been spawned!!!
|
||||
--
|
||||
-- Spawned groups get **the same name** as the name of the template group.
|
||||
-- Spawned units in those groups keep _by default_ **the same name** as the name of the template group.
|
||||
-- However, because multiple groups and units are created from the template group,
|
||||
-- a suffix is added to each spawned group and unit.
|
||||
--
|
||||
-- Newly spawned groups will get the following naming structure at run-time:
|
||||
--
|
||||
-- 1. Spawned groups will have the name _GroupName_#_nnn_, where _GroupName_ is the name of the **template group**,
|
||||
-- and _nnn_ is a **counter from 0 to 999**.
|
||||
-- 2. Spawned units will have the name _GroupName_#_nnn_-_uu_,
|
||||
-- where _uu_ is a **counter from 0 to 99** for each new spawned unit belonging to the group.
|
||||
--
|
||||
-- That being said, there is a way to keep the same unit names!
|
||||
-- The method @{#SPAWN.InitKeepUnitNames}() will keep the same unit names as defined within the template group, thus:
|
||||
--
|
||||
-- 3. Spawned units will have the name _UnitName_#_nnn_-_uu_,
|
||||
-- where _UnitName_ is the **unit name as defined in the template group*,
|
||||
-- and _uu_ is a **counter from 0 to 99** for each new spawned unit belonging to the group.
|
||||
--
|
||||
-- Some **additional notes that need to be considered!!**:
|
||||
--
|
||||
-- * templates are actually groups defined within the mission editor, with the flag "Late Activation" set.
|
||||
-- As such, these groups are never used within the mission, but are used by the @{#SPAWN} module.
|
||||
-- * It is important to defined BEFORE you spawn new groups,
|
||||
-- a proper initialization of the SPAWN instance is done with the options you want to use.
|
||||
-- * When designing a mission, NEVER name groups using a "#" within the name of the group Spawn template(s),
|
||||
-- or the SPAWN module logic won't work anymore.
|
||||
--
|
||||
-- ## SPAWN construction methods
|
||||
--
|
||||
-- Create a new SPAWN object with the @{#SPAWN.New}() or the @{#SPAWN.NewWithAlias}() methods:
|
||||
--
|
||||
-- * @{#SPAWN.New}(): Creates a new SPAWN object taking the name of the group that represents the GROUP template (definition).
|
||||
-- * @{#SPAWN.NewWithAlias}(): Creates a new SPAWN object taking the name of the group that represents the GROUP template (definition), and gives each spawned @{Group} an different name.
|
||||
--
|
||||
-- It is important to understand how the SPAWN class works internally. The SPAWN object created will contain internally a list of groups that will be spawned and that are already spawned.
|
||||
-- The initialization methods will modify this list of groups so that when a group gets spawned, ALL information is already prepared when spawning. This is done for performance reasons.
|
||||
-- So in principle, the group list will contain all parameters and configurations after initialization, and when groups get actually spawned, this spawning can be done quickly and efficient.
|
||||
--
|
||||
-- ## SPAWN **Init**ialization methods
|
||||
--
|
||||
-- A spawn object will behave differently based on the usage of **initialization** methods, which all start with the **Init** prefix:
|
||||
--
|
||||
-- ### Unit Names
|
||||
--
|
||||
-- * @{#SPAWN.InitKeepUnitNames}(): Keeps the unit names as defined within the mission editor, but note that anything after a # mark is ignored, and any spaces before and after the resulting name are removed. IMPORTANT! This method MUST be the first used after :New !!!
|
||||
--
|
||||
-- ### Route randomization
|
||||
--
|
||||
-- * @{#SPAWN.InitRandomizeRoute}(): Randomize the routes of spawned groups, and for air groups also optionally the height.
|
||||
--
|
||||
-- ### Group composition randomization
|
||||
--
|
||||
-- * @{#SPAWN.InitRandomizeTemplate}(): Randomize the group templates so that when a new group is spawned, a random group template is selected from one of the templates defined.
|
||||
--
|
||||
-- ### Uncontrolled
|
||||
--
|
||||
-- * @{#SPAWN.InitUnControlled}(): Spawn plane groups uncontrolled.
|
||||
--
|
||||
-- ### Array formation
|
||||
--
|
||||
-- * @{#SPAWN.InitArray}(): Make groups visible before they are actually activated, and order these groups like a batallion in an array.
|
||||
--
|
||||
-- ### Position randomization
|
||||
--
|
||||
-- * @{#SPAWN.InitRandomizePosition}(): Randomizes the position of @{Group}s that are spawned within a **radius band**, given an Outer and Inner radius, from the point that the spawn happens.
|
||||
-- * @{#SPAWN.InitRandomizeUnits}(): Randomizes the @{Unit}s in the @{Group} that is spawned within a **radius band**, given an Outer and Inner radius.
|
||||
-- * @{#SPAWN.InitRandomizeZones}(): Randomizes the spawning between a predefined list of @{Zone}s that are declared using this function. Each zone can be given a probability factor.
|
||||
--
|
||||
-- ### Enable / Disable AI when spawning a new @{Group}
|
||||
--
|
||||
-- * @{#SPAWN.InitAIOn}(): Turns the AI On when spawning the new @{Group} object.
|
||||
-- * @{#SPAWN.InitAIOff}(): Turns the AI Off when spawning the new @{Group} object.
|
||||
-- * @{#SPAWN.InitAIOnOff}(): Turns the AI On or Off when spawning the new @{Group} object.
|
||||
--
|
||||
-- ### Limit scheduled spawning
|
||||
--
|
||||
-- * @{#SPAWN.InitLimit}(): Limits the amount of groups that can be alive at the same time and that can be dynamically spawned.
|
||||
--
|
||||
-- ### Delay initial scheduled spawn
|
||||
--
|
||||
-- * @{#SPAWN.InitDelayOnOff}(): Turns the inital delay On/Off when scheduled spawning the first @{Group} object.
|
||||
-- * @{#SPAWN.InitDelayOn}(): Turns the inital delay On when scheduled spawning the first @{Group} object.
|
||||
-- * @{#SPAWN.InitDelayOff}(): Turns the inital delay Off when scheduled spawning the first @{Group} object.
|
||||
--
|
||||
-- ### Repeat spawned @{Group}s upon landing
|
||||
--
|
||||
-- * @{#SPAWN.InitRepeat}() or @{#SPAWN.InitRepeatOnLanding}(): This method is used to re-spawn automatically the same group after it has landed.
|
||||
-- * @{#SPAWN.InitRepeatOnEngineShutDown}(): This method is used to re-spawn automatically the same group after it has landed and it shuts down the engines at the ramp.
|
||||
--
|
||||
--
|
||||
-- ## SPAWN **Spawn** methods
|
||||
--
|
||||
-- Groups can be spawned at different times and methods:
|
||||
--
|
||||
-- ### **Single** spawning methods
|
||||
--
|
||||
-- * @{#SPAWN.Spawn}(): Spawn one new group based on the last spawned index.
|
||||
-- * @{#SPAWN.ReSpawn}(): Re-spawn a group based on a given index.
|
||||
-- * @{#SPAWN.SpawnFromVec3}(): Spawn a new group from a Vec3 coordinate. (The group will can be spawned at a point in the air).
|
||||
-- * @{#SPAWN.SpawnFromVec2}(): Spawn a new group from a Vec2 coordinate. (The group will be spawned at land height ).
|
||||
-- * @{#SPAWN.SpawnFromStatic}(): Spawn a new group from a structure, taking the position of a @{Static}.
|
||||
-- * @{#SPAWN.SpawnFromUnit}(): Spawn a new group taking the position of a @{Unit}.
|
||||
-- * @{#SPAWN.SpawnInZone}(): Spawn a new group in a @{Zone}.
|
||||
--
|
||||
-- Note that @{#SPAWN.Spawn} and @{#SPAWN.ReSpawn} return a @{GROUP#GROUP.New} object, that contains a reference to the DCSGroup object.
|
||||
-- You can use the @{GROUP} object to do further actions with the DCSGroup.
|
||||
--
|
||||
-- ### **Scheduled** spawning methods
|
||||
--
|
||||
-- * @{#SPAWN.SpawnScheduled}(): Spawn groups at scheduled but randomized intervals.
|
||||
-- * @{#SPAWN.SpawnScheduledStart}(): Start or continue to spawn groups at scheduled time intervals.
|
||||
-- * @{#SPAWN.SpawnScheduledStop}(): Stop the spawning of groups at scheduled time intervals.
|
||||
--
|
||||
--
|
||||
--
|
||||
-- ## Retrieve alive GROUPs spawned by the SPAWN object
|
||||
--
|
||||
-- The SPAWN class administers which GROUPS it has reserved (in stock) or has created during mission execution.
|
||||
-- Every time a SPAWN object spawns a new GROUP object, a reference to the GROUP object is added to an internal table of GROUPS.
|
||||
-- SPAWN provides methods to iterate through that internal GROUP object reference table:
|
||||
--
|
||||
-- * @{#SPAWN.GetFirstAliveGroup}(): Will find the first alive GROUP it has spawned, and return the alive GROUP object and the first Index where the first alive GROUP object has been found.
|
||||
-- * @{#SPAWN.GetNextAliveGroup}(): Will find the next alive GROUP object from a given Index, and return a reference to the alive GROUP object and the next Index where the alive GROUP has been found.
|
||||
-- * @{#SPAWN.GetLastAliveGroup}(): Will find the last alive GROUP object, and will return a reference to the last live GROUP object and the last Index where the last alive GROUP object has been found.
|
||||
--
|
||||
-- You can use the methods @{#SPAWN.GetFirstAliveGroup}() and sequently @{#SPAWN.GetNextAliveGroup}() to iterate through the alive GROUPS within the SPAWN object, and to actions... See the respective methods for an example.
|
||||
-- The method @{#SPAWN.GetGroupFromIndex}() will return the GROUP object reference from the given Index, dead or alive...
|
||||
--
|
||||
-- ## Spawned cleaning of inactive groups
|
||||
--
|
||||
-- Sometimes, it will occur during a mission run-time, that ground or especially air objects get damaged, and will while being damged stop their activities, while remaining alive.
|
||||
-- In such cases, the SPAWN object will just sit there and wait until that group gets destroyed, but most of the time it won't,
|
||||
-- and it may occur that no new groups are or can be spawned as limits are reached.
|
||||
-- To prevent this, a @{#SPAWN.InitCleanUp}() initialization method has been defined that will silently monitor the status of each spawned group.
|
||||
-- Once a group has a velocity = 0, and has been waiting for a defined interval, that group will be cleaned or removed from run-time.
|
||||
-- There is a catch however :-) If a damaged group has returned to an airbase within the coalition, that group will not be considered as "lost"...
|
||||
-- In such a case, when the inactive group is cleaned, a new group will Re-spawned automatically.
|
||||
-- This models AI that has succesfully returned to their airbase, to restart their combat activities.
|
||||
-- Check the @{#SPAWN.InitCleanUp}() for further info.
|
||||
--
|
||||
-- ## Catch the @{Group} Spawn Event in a callback function!
|
||||
--
|
||||
-- When using the @{#SPAWN.SpawnScheduled)() method, new @{Group}s are created following the spawn time interval parameters.
|
||||
-- When a new @{Group} is spawned, you maybe want to execute actions with that group spawned at the spawn event.
|
||||
-- The SPAWN class supports this functionality through the method @{#SPAWN.OnSpawnGroup}( **function( SpawnedGroup ) end ** ),
|
||||
-- which takes a function as a parameter that you can define locally.
|
||||
-- Whenever a new @{Group} is spawned, the given function is called, and the @{Group} that was just spawned, is given as a parameter.
|
||||
-- As a result, your spawn event handling function requires one parameter to be declared, which will contain the spawned @{Group} object.
|
||||
-- A coding example is provided at the description of the @{#SPAWN.OnSpawnGroup}( **function( SpawnedGroup ) end ** ) method.
|
||||
--
|
||||
-- ## Delay the initial spawning
|
||||
--
|
||||
-- When using the @{#SPAWN.SpawnScheduled)() method, the default behaviour of this method will be that it will spawn the initial (first) @{Group}
|
||||
-- immediately when :SpawnScheduled() is initiated. The methods @{#SPAWN.InitDelayOnOff}() and @{#SPAWN.InitDelayOn}() can be used to
|
||||
-- activate a delay before the first @{Group} is spawned. For completeness, a method @{#SPAWN.InitDelayOff}() is also available, that
|
||||
-- can be used to switch off the initial delay. Because there is no delay by default, this method would only be used when a
|
||||
-- @{#SPAWN.SpawnScheduledStop}() ; @{#SPAWN.SpawnScheduledStart}() sequence would have been used.
|
||||
--
|
||||
--
|
||||
-- @field #SPAWN SPAWN
|
||||
--
|
||||
SPAWN = {
|
||||
ClassName = "SPAWN",
|
||||
SpawnTemplatePrefix = nil,
|
||||
@@ -227,6 +338,7 @@ function SPAWN:New( SpawnTemplatePrefix )
|
||||
self.AIOnOff = true -- The AI is on by default when spawning a group.
|
||||
self.SpawnUnControlled = false
|
||||
self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name.
|
||||
self.DelayOnOff = false -- No intial delay when spawning the first group.
|
||||
|
||||
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
|
||||
else
|
||||
@@ -270,6 +382,7 @@ function SPAWN:NewWithAlias( SpawnTemplatePrefix, SpawnAliasPrefix )
|
||||
self.AIOnOff = true -- The AI is on by default when spawning a group.
|
||||
self.SpawnUnControlled = false
|
||||
self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name.
|
||||
self.DelayOnOff = false -- No intial delay when spawning the first group.
|
||||
|
||||
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
|
||||
else
|
||||
@@ -626,6 +739,36 @@ do -- AI methods
|
||||
|
||||
end -- AI methods
|
||||
|
||||
do -- Delay methods
|
||||
--- Turns the Delay On or Off for the first @{Group} scheduled spawning.
|
||||
-- The default value is that for scheduled spawning, there is an initial delay when spawning the first @{Group}.
|
||||
-- @param #SPAWN self
|
||||
-- @param #boolean DelayOnOff A value of true sets the Delay On, a value of false sets the Delay Off.
|
||||
-- @return #SPAWN The SPAWN object
|
||||
function SPAWN:InitDelayOnOff( DelayOnOff )
|
||||
|
||||
self.DelayOnOff = DelayOnOff
|
||||
return self
|
||||
end
|
||||
|
||||
--- Turns the Delay On for the @{Group} when spawning.
|
||||
-- @param #SPAWN self
|
||||
-- @return #SPAWN The SPAWN object
|
||||
function SPAWN:InitDelayOn()
|
||||
|
||||
return self:InitDelayOnOff( true )
|
||||
end
|
||||
|
||||
--- Turns the Delay Off for the @{Group} when spawning.
|
||||
-- @param #SPAWN self
|
||||
-- @return #SPAWN The SPAWN object
|
||||
function SPAWN:InitDelayOff()
|
||||
|
||||
return self:InitDelayOnOff( false )
|
||||
end
|
||||
|
||||
end -- Delay methods
|
||||
|
||||
--- Will spawn a group based on the internal index.
|
||||
-- Note: Uses @{DATABASE} module defined in MOOSE.
|
||||
-- @param #SPAWN self
|
||||
@@ -669,6 +812,8 @@ function SPAWN:ReSpawn( SpawnIndex )
|
||||
SpawnGroup:ReSpawnFunction()
|
||||
end
|
||||
|
||||
SpawnGroup:ResetEvents()
|
||||
|
||||
return SpawnGroup
|
||||
end
|
||||
|
||||
@@ -787,7 +932,11 @@ function SPAWN:SpawnScheduled( SpawnTime, SpawnTimeVariation )
|
||||
self:F( { SpawnTime, SpawnTimeVariation } )
|
||||
|
||||
if SpawnTime ~= nil and SpawnTimeVariation ~= nil then
|
||||
self.SpawnScheduler = SCHEDULER:New( self, self._Scheduler, {}, 1, SpawnTime, SpawnTimeVariation )
|
||||
local InitialDelay = 0
|
||||
if self.DelayOnOff == true then
|
||||
InitialDelay = math.random( SpawnTime - SpawnTime * SpawnTimeVariation, SpawnTime + SpawnTime * SpawnTimeVariation )
|
||||
end
|
||||
self.SpawnScheduler = SCHEDULER:New( self, self._Scheduler, {}, InitialDelay, SpawnTime, SpawnTimeVariation )
|
||||
end
|
||||
|
||||
return self
|
||||
@@ -795,17 +944,23 @@ end
|
||||
|
||||
--- Will re-start the spawning scheduler.
|
||||
-- Note: This method is only required to be called when the schedule was stopped.
|
||||
-- @param #SPAWN self
|
||||
-- @return #SPAWN
|
||||
function SPAWN:SpawnScheduleStart()
|
||||
self:F( { self.SpawnTemplatePrefix } )
|
||||
|
||||
self.SpawnScheduler:Start()
|
||||
return self
|
||||
end
|
||||
|
||||
--- Will stop the scheduled spawning scheduler.
|
||||
-- @param #SPAWN self
|
||||
-- @return #SPAWN
|
||||
function SPAWN:SpawnScheduleStop()
|
||||
self:F( { self.SpawnTemplatePrefix } )
|
||||
|
||||
self.SpawnScheduler:Stop()
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
@@ -926,7 +1081,7 @@ end
|
||||
function SPAWN:SpawnFromUnit( HostUnit, SpawnIndex )
|
||||
self:F( { self.SpawnTemplatePrefix, HostUnit, SpawnIndex } )
|
||||
|
||||
if HostUnit and HostUnit:IsAlive() then -- and HostUnit:getUnit(1):inAir() == false then
|
||||
if HostUnit and HostUnit:IsAlive() ~= nil then -- and HostUnit:getUnit(1):inAir() == false then
|
||||
return self:SpawnFromVec3( HostUnit:GetVec3(), SpawnIndex )
|
||||
end
|
||||
|
||||
|
||||
@@ -834,6 +834,9 @@ function GROUP:Respawn( Template )
|
||||
|
||||
self:Destroy()
|
||||
_DATABASE:Spawn( Template )
|
||||
|
||||
self:ResetEvents()
|
||||
|
||||
end
|
||||
|
||||
--- Returns the group template from the @{DATABASE} (_DATABASE object).
|
||||
@@ -1077,7 +1080,21 @@ do -- Event Handling
|
||||
-- @return #GROUP
|
||||
function GROUP:UnHandleEvent( Event )
|
||||
|
||||
self:EventDispatcher():RemoveForGroup( self:GetName(), self, Event )
|
||||
self:EventDispatcher():Remove( self, Event )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Reset the subscriptions.
|
||||
-- @param #GROUP self
|
||||
-- @return #GROUP
|
||||
function GROUP:ResetEvents()
|
||||
|
||||
self:EventDispatcher():Reset( self )
|
||||
|
||||
for UnitID, UnitData in pairs( self:GetUnits() ) do
|
||||
UnitData:ResetEvents()
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -990,5 +990,16 @@ do -- Event Handling
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Reset the subscriptions.
|
||||
-- @param #UNIT self
|
||||
-- @return #UNIT
|
||||
function UNIT:ResetEvents()
|
||||
|
||||
self:EventDispatcher():Reset( self )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user