Merge pull request #1275 from FlightControl-Master/FF/Develop

Ff/develop
This commit is contained in:
Frank 2020-02-17 23:42:47 +01:00 committed by GitHub
commit 0c32c35c27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 1244 additions and 765 deletions

View File

@ -626,6 +626,55 @@ do -- Event Handling
-- @param #BASE self -- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure. -- @param Core.Event#EVENTDATA EventData The EventData structure.
--- Unknown precisely what creates this event, likely tied into newer damage model. Will update this page when new information become available.
--
-- * initiator: The unit that had the failure.
--
-- @function [parent=#BASE] OnEventDetailedFailure
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
--- Occurs when any modification to the "Score" as seen on the debrief menu would occur.
-- There is no information on what values the score was changed to. Event is likely similar to player_comment in this regard.
-- @function [parent=#BASE] OnEventScore
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
--- Occurs on the death of a unit. Contains more and different information. Similar to unit_lost it will occur for aircraft before the aircraft crash event occurs.
--
-- * initiator: The unit that killed the target
-- * target: Target Object
-- * weapon: Weapon Object
--
-- @function [parent=#BASE] OnEventKill
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
--- Occurs when any modification to the "Score" as seen on the debrief menu would occur.
-- There is no information on what values the score was changed to. Event is likely similar to player_comment in this regard.
-- @function [parent=#BASE] OnEventScore
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
--- Occurs when the game thinks an object is destroyed.
--
-- * initiator: The unit that is was destroyed.
--
-- @function [parent=#BASE] OnEventUnitLost
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
--- Occurs shortly after the landing animation of an ejected pilot touching the ground and standing up. Event does not occur if the pilot lands in the water and sub combs to Davey Jones Locker.
--
-- * initiator: Static object representing the ejected pilot. Place : Aircraft that the pilot ejected from.
-- * place: may not return as a valid object if the aircraft has crashed into the ground and no longer exists.
-- * subplace: is always 0 for unknown reasons.
--
-- @function [parent=#BASE] OnEventLandingAfterEjection
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
end end

View File

@ -247,12 +247,15 @@ end
--- Adds a Airbase based on the Airbase Name in the DATABASE. --- Adds a Airbase based on the Airbase Name in the DATABASE.
-- @param #DATABASE self -- @param #DATABASE self
-- @param #string AirbaseName The name of the airbase -- @param #string AirbaseName The name of the airbase.
-- @return Wrapper.Airbase#AIRBASE Airbase object.
function DATABASE:AddAirbase( AirbaseName ) function DATABASE:AddAirbase( AirbaseName )
if not self.AIRBASES[AirbaseName] then if not self.AIRBASES[AirbaseName] then
self.AIRBASES[AirbaseName] = AIRBASE:Register( AirbaseName ) self.AIRBASES[AirbaseName] = AIRBASE:Register( AirbaseName )
end end
return self.AIRBASES[AirbaseName]
end end
@ -893,6 +896,7 @@ end
--- @param #DATABASE self --- @param #DATABASE self
function DATABASE:_RegisterAirbases() function DATABASE:_RegisterAirbases()
--[[
local CoalitionsData = { AirbasesRed = coalition.getAirbases( coalition.side.RED ), AirbasesBlue = coalition.getAirbases( coalition.side.BLUE ), AirbasesNeutral = coalition.getAirbases( coalition.side.NEUTRAL ) } local CoalitionsData = { AirbasesRed = coalition.getAirbases( coalition.side.RED ), AirbasesBlue = coalition.getAirbases( coalition.side.BLUE ), AirbasesNeutral = coalition.getAirbases( coalition.side.NEUTRAL ) }
for CoalitionId, CoalitionData in pairs( CoalitionsData ) do for CoalitionId, CoalitionData in pairs( CoalitionsData ) do
for DCSAirbaseId, DCSAirbase in pairs( CoalitionData ) do for DCSAirbaseId, DCSAirbase in pairs( CoalitionData ) do
@ -903,6 +907,18 @@ function DATABASE:_RegisterAirbases()
self:AddAirbase( DCSAirbaseName ) self:AddAirbase( DCSAirbaseName )
end end
end end
]]
for DCSAirbaseId, DCSAirbase in pairs(world.getAirbases()) do
local DCSAirbaseName = DCSAirbase:getName()
-- This gives the incorrect value to be inserted into the airdromeID for DCS 2.5.6!
local airbaseID=DCSAirbase:getID()
local airbase=self:AddAirbase( DCSAirbaseName )
self:I(string.format("Register Airbase: %s, getID=%d, GetID=%d (unique=%d)", DCSAirbaseName, DCSAirbase:getID(), airbase:GetID(), airbase:GetID(true)))
end
return self return self
end end

View File

@ -221,9 +221,11 @@ EVENTS = {
PlayerComment = world.event.S_EVENT_PLAYER_COMMENT, PlayerComment = world.event.S_EVENT_PLAYER_COMMENT,
ShootingStart = world.event.S_EVENT_SHOOTING_START, ShootingStart = world.event.S_EVENT_SHOOTING_START,
ShootingEnd = world.event.S_EVENT_SHOOTING_END, ShootingEnd = world.event.S_EVENT_SHOOTING_END,
-- Added with DCS 2.5.1
MarkAdded = world.event.S_EVENT_MARK_ADDED, MarkAdded = world.event.S_EVENT_MARK_ADDED,
MarkChange = world.event.S_EVENT_MARK_CHANGE, MarkChange = world.event.S_EVENT_MARK_CHANGE,
MarkRemoved = world.event.S_EVENT_MARK_REMOVED, MarkRemoved = world.event.S_EVENT_MARK_REMOVED,
-- Moose Events
NewCargo = world.event.S_EVENT_NEW_CARGO, NewCargo = world.event.S_EVENT_NEW_CARGO,
DeleteCargo = world.event.S_EVENT_DELETE_CARGO, DeleteCargo = world.event.S_EVENT_DELETE_CARGO,
NewZone = world.event.S_EVENT_NEW_ZONE, NewZone = world.event.S_EVENT_NEW_ZONE,
@ -231,6 +233,12 @@ EVENTS = {
NewZoneGoal = world.event.S_EVENT_NEW_ZONE_GOAL, NewZoneGoal = world.event.S_EVENT_NEW_ZONE_GOAL,
DeleteZoneGoal = world.event.S_EVENT_DELETE_ZONE_GOAL, DeleteZoneGoal = world.event.S_EVENT_DELETE_ZONE_GOAL,
RemoveUnit = world.event.S_EVENT_REMOVE_UNIT, RemoveUnit = world.event.S_EVENT_REMOVE_UNIT,
-- Added with DCS 2.5.6
DetailedFailure = world.event.S_EVENT_DETAILED_FAILURE or -1, --We set this to -1 for backward compatibility to DCS 2.5.5 and earlier
Kill = world.event.S_EVENT_KILL or -1,
Score = world.event.S_EVENT_SCORE or -1,
UnitLost = world.event.S_EVENT_UNIT_LOST or -1,
LandingAfterEjection = world.event.S_EVENT_LANDING_AFTER_EJECTION or -1,
} }
--- The Event structure --- The Event structure
@ -481,6 +489,32 @@ local _EVENTMETA = {
Event = "OnEventRemoveUnit", Event = "OnEventRemoveUnit",
Text = "S_EVENT_REMOVE_UNIT" Text = "S_EVENT_REMOVE_UNIT"
}, },
-- Added with DCS 2.5.6
[EVENTS.DetailedFailure] = {
Order = 1,
Event = "OnEventDetailedFailure",
Text = "S_EVENT_DETAILED_FAILURE"
},
[EVENTS.Kill] = {
Order = 1,
Event = "OnEventKill",
Text = "S_EVENT_KILL"
},
[EVENTS.Score] = {
Order = 1,
Event = "OnEventScore",
Text = "S_EVENT_SCORE"
},
[EVENTS.UnitLost] = {
Order = 1,
Event = "OnEventUnitLost",
Text = "S_EVENT_UNIT_LOST"
},
[EVENTS.LandingAfterEjection] = {
Order = 1,
Event = "OnEventLandingAfterEjection",
Text = "S_EVENT_LANDING_AFTER_EJECTION"
},
} }
@ -881,258 +915,213 @@ function EVENT:onEvent( Event )
end end
-- Get event meta data.
local EventMeta = _EVENTMETA[Event.id] local EventMeta = _EVENTMETA[Event.id]
--self:E( { EventMeta.Text, Event } ) -- Activate the see all incoming events ... -- Check if this is a known event?
if EventMeta then
if self and if self and
self.Events and self.Events and
self.Events[Event.id] and self.Events[Event.id] and
self.MissionEnd == false and self.MissionEnd == false and
( Event.initiator ~= nil or ( Event.initiator == nil and Event.id ~= EVENTS.PlayerLeaveUnit ) ) then ( Event.initiator ~= nil or ( Event.initiator == nil and Event.id ~= EVENTS.PlayerLeaveUnit ) ) then
if Event.id and Event.id == EVENTS.MissionEnd then if Event.id and Event.id == EVENTS.MissionEnd then
self.MissionEnd = true self.MissionEnd = true
end end
if Event.initiator then if Event.initiator then
Event.IniObjectCategory = Event.initiator:getCategory() Event.IniObjectCategory = Event.initiator:getCategory()
if Event.IniObjectCategory == Object.Category.UNIT then if Event.IniObjectCategory == Object.Category.UNIT then
Event.IniDCSUnit = Event.initiator Event.IniDCSUnit = Event.initiator
Event.IniDCSUnitName = Event.IniDCSUnit:getName() Event.IniDCSUnitName = Event.IniDCSUnit:getName()
Event.IniUnitName = Event.IniDCSUnitName Event.IniUnitName = Event.IniDCSUnitName
Event.IniDCSGroup = Event.IniDCSUnit:getGroup() Event.IniDCSGroup = Event.IniDCSUnit:getGroup()
Event.IniUnit = UNIT:FindByName( Event.IniDCSUnitName ) Event.IniUnit = UNIT:FindByName( Event.IniDCSUnitName )
if not Event.IniUnit then if not Event.IniUnit then
-- Unit can be a CLIENT. Most likely this will be the case ... -- Unit can be a CLIENT. Most likely this will be the case ...
Event.IniUnit = CLIENT:FindByName( Event.IniDCSUnitName, '', true ) Event.IniUnit = CLIENT:FindByName( Event.IniDCSUnitName, '', true )
end
Event.IniDCSGroupName = ""
if Event.IniDCSGroup and Event.IniDCSGroup:isExist() then
Event.IniDCSGroupName = Event.IniDCSGroup:getName()
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
--if Event.IniGroup then
Event.IniGroupName = Event.IniDCSGroupName
--end
end
Event.IniPlayerName = Event.IniDCSUnit:getPlayerName()
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
Event.IniCategory = Event.IniDCSUnit:getDesc().category
end end
Event.IniDCSGroupName = ""
if Event.IniDCSGroup and Event.IniDCSGroup:isExist() then if Event.IniObjectCategory == Object.Category.STATIC then
Event.IniDCSGroupName = Event.IniDCSGroup:getName() Event.IniDCSUnit = Event.initiator
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName ) Event.IniDCSUnitName = Event.IniDCSUnit:getName()
--if Event.IniGroup then Event.IniUnitName = Event.IniDCSUnitName
Event.IniGroupName = Event.IniDCSGroupName Event.IniUnit = STATIC:FindByName( Event.IniDCSUnitName, false )
--end Event.IniCoalition = Event.IniDCSUnit:getCoalition()
Event.IniCategory = Event.IniDCSUnit:getDesc().category
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
end end
Event.IniPlayerName = Event.IniDCSUnit:getPlayerName()
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
Event.IniCategory = Event.IniDCSUnit:getDesc().category
end
if Event.IniObjectCategory == Object.Category.STATIC then if Event.IniObjectCategory == Object.Category.CARGO then
Event.IniDCSUnit = Event.initiator Event.IniDCSUnit = Event.initiator
Event.IniDCSUnitName = Event.IniDCSUnit:getName() Event.IniDCSUnitName = Event.IniDCSUnit:getName()
Event.IniUnitName = Event.IniDCSUnitName Event.IniUnitName = Event.IniDCSUnitName
Event.IniUnit = STATIC:FindByName( Event.IniDCSUnitName, false ) Event.IniUnit = CARGO:FindByName( Event.IniDCSUnitName )
Event.IniCoalition = Event.IniDCSUnit:getCoalition() Event.IniCoalition = Event.IniDCSUnit:getCoalition()
Event.IniCategory = Event.IniDCSUnit:getDesc().category Event.IniCategory = Event.IniDCSUnit:getDesc().category
Event.IniTypeName = Event.IniDCSUnit:getTypeName() Event.IniTypeName = Event.IniDCSUnit:getTypeName()
end end
if Event.IniObjectCategory == Object.Category.CARGO then if Event.IniObjectCategory == Object.Category.SCENERY then
Event.IniDCSUnit = Event.initiator Event.IniDCSUnit = Event.initiator
Event.IniDCSUnitName = Event.IniDCSUnit:getName() Event.IniDCSUnitName = Event.IniDCSUnit:getName()
Event.IniUnitName = Event.IniDCSUnitName Event.IniUnitName = Event.IniDCSUnitName
Event.IniUnit = CARGO:FindByName( Event.IniDCSUnitName ) Event.IniUnit = SCENERY:Register( Event.IniDCSUnitName, Event.initiator )
Event.IniCoalition = Event.IniDCSUnit:getCoalition() Event.IniCategory = Event.IniDCSUnit:getDesc().category
Event.IniCategory = Event.IniDCSUnit:getDesc().category Event.IniTypeName = Event.initiator:isExist() and Event.IniDCSUnit:getTypeName() or "SCENERY" -- TODO: Bug fix for 2.1!
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
end
if Event.IniObjectCategory == Object.Category.SCENERY then
Event.IniDCSUnit = Event.initiator
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
Event.IniUnitName = Event.IniDCSUnitName
Event.IniUnit = SCENERY:Register( Event.IniDCSUnitName, Event.initiator )
Event.IniCategory = Event.IniDCSUnit:getDesc().category
Event.IniTypeName = Event.initiator:isExist() and Event.IniDCSUnit:getTypeName() or "SCENERY" -- TODO: Bug fix for 2.1!
end
end
if Event.target then
Event.TgtObjectCategory = Event.target:getCategory()
if Event.TgtObjectCategory == Object.Category.UNIT then
Event.TgtDCSUnit = Event.target
Event.TgtDCSGroup = Event.TgtDCSUnit:getGroup()
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
Event.TgtUnitName = Event.TgtDCSUnitName
Event.TgtUnit = UNIT:FindByName( Event.TgtDCSUnitName )
Event.TgtDCSGroupName = ""
if Event.TgtDCSGroup and Event.TgtDCSGroup:isExist() then
Event.TgtDCSGroupName = Event.TgtDCSGroup:getName()
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )
--if Event.TgtGroup then
Event.TgtGroupName = Event.TgtDCSGroupName
--end
end end
Event.TgtPlayerName = Event.TgtDCSUnit:getPlayerName()
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
end end
if Event.TgtObjectCategory == Object.Category.STATIC then if Event.target then
Event.TgtDCSUnit = Event.target
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName() Event.TgtObjectCategory = Event.target:getCategory()
Event.TgtUnitName = Event.TgtDCSUnitName
Event.TgtUnit = STATIC:FindByName( Event.TgtDCSUnitName, false ) if Event.TgtObjectCategory == Object.Category.UNIT then
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition() Event.TgtDCSUnit = Event.target
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category Event.TgtDCSGroup = Event.TgtDCSUnit:getGroup()
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName() Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
Event.TgtUnitName = Event.TgtDCSUnitName
Event.TgtUnit = UNIT:FindByName( Event.TgtDCSUnitName )
Event.TgtDCSGroupName = ""
if Event.TgtDCSGroup and Event.TgtDCSGroup:isExist() then
Event.TgtDCSGroupName = Event.TgtDCSGroup:getName()
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )
--if Event.TgtGroup then
Event.TgtGroupName = Event.TgtDCSGroupName
--end
end
Event.TgtPlayerName = Event.TgtDCSUnit:getPlayerName()
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
end
if Event.TgtObjectCategory == Object.Category.STATIC then
Event.TgtDCSUnit = Event.target
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
Event.TgtUnitName = Event.TgtDCSUnitName
Event.TgtUnit = STATIC:FindByName( Event.TgtDCSUnitName, false )
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
end
if Event.TgtObjectCategory == Object.Category.SCENERY then
Event.TgtDCSUnit = Event.target
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
Event.TgtUnitName = Event.TgtDCSUnitName
Event.TgtUnit = SCENERY:Register( Event.TgtDCSUnitName, Event.target )
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
end
end end
if Event.TgtObjectCategory == Object.Category.SCENERY then if Event.weapon then
Event.TgtDCSUnit = Event.target Event.Weapon = Event.weapon
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName() Event.WeaponName = Event.Weapon:getTypeName()
Event.TgtUnitName = Event.TgtDCSUnitName Event.WeaponUNIT = CLIENT:Find( Event.Weapon, '', true ) -- Sometimes, the weapon is a player unit!
Event.TgtUnit = SCENERY:Register( Event.TgtDCSUnitName, Event.target ) Event.WeaponPlayerName = Event.WeaponUNIT and Event.Weapon:getPlayerName()
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category Event.WeaponCoalition = Event.WeaponUNIT and Event.Weapon:getCoalition()
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName() Event.WeaponCategory = Event.WeaponUNIT and Event.Weapon:getDesc().category
Event.WeaponTypeName = Event.WeaponUNIT and Event.Weapon:getTypeName()
--Event.WeaponTgtDCSUnit = Event.Weapon:getTarget()
end end
end
if Event.weapon then -- Place should be given for takeoff and landing events as well as base captured. It should be a DCS airbase.
Event.Weapon = Event.weapon if Event.place then
Event.WeaponName = Event.Weapon:getTypeName() if Event.id==EVENTS.LandingAfterEjection then
Event.WeaponUNIT = CLIENT:Find( Event.Weapon, '', true ) -- Sometimes, the weapon is a player unit! -- Place is here the UNIT of which the pilot ejected.
Event.WeaponPlayerName = Event.WeaponUNIT and Event.Weapon:getPlayerName() Event.Place=UNIT:Find(Event.place)
Event.WeaponCoalition = Event.WeaponUNIT and Event.Weapon:getCoalition() else
Event.WeaponCategory = Event.WeaponUNIT and Event.Weapon:getDesc().category Event.Place=AIRBASE:Find(Event.place)
Event.WeaponTypeName = Event.WeaponUNIT and Event.Weapon:getTypeName() Event.PlaceName=Event.Place:GetName()
--Event.WeaponTgtDCSUnit = Event.Weapon:getTarget() end
end end
-- Place should be given for takeoff and landing events as well as base captured. It should be a DCS airbase. -- Mark points.
if Event.place then if Event.idx then
Event.Place=AIRBASE:Find(Event.place) Event.MarkID=Event.idx
Event.PlaceName=Event.Place:GetName() Event.MarkVec3=Event.pos
end Event.MarkCoordinate=COORDINATE:NewFromVec3(Event.pos)
Event.MarkText=Event.text
Event.MarkCoalition=Event.coalition
Event.MarkGroupID = Event.groupID
end
-- Mark points. if Event.cargo then
if Event.idx then Event.Cargo = Event.cargo
Event.MarkID=Event.idx Event.CargoName = Event.cargo.Name
Event.MarkVec3=Event.pos end
Event.MarkCoordinate=COORDINATE:NewFromVec3(Event.pos)
Event.MarkText=Event.text
Event.MarkCoalition=Event.coalition
Event.MarkGroupID = Event.groupID
end
if Event.cargo then if Event.zone then
Event.Cargo = Event.cargo Event.Zone = Event.zone
Event.CargoName = Event.cargo.Name Event.ZoneName = Event.zone.ZoneName
end end
if Event.zone then local PriorityOrder = EventMeta.Order
Event.Zone = Event.zone local PriorityBegin = PriorityOrder == -1 and 5 or 1
Event.ZoneName = Event.zone.ZoneName local PriorityEnd = PriorityOrder == -1 and 1 or 5
end
local PriorityOrder = EventMeta.Order if Event.IniObjectCategory ~= Object.Category.STATIC then
local PriorityBegin = PriorityOrder == -1 and 5 or 1 self:F( { EventMeta.Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } )
local PriorityEnd = PriorityOrder == -1 and 1 or 5 end
if Event.IniObjectCategory ~= Object.Category.STATIC then for EventPriority = PriorityBegin, PriorityEnd, PriorityOrder do
self:F( { EventMeta.Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } )
end
for EventPriority = PriorityBegin, PriorityEnd, PriorityOrder do if self.Events[Event.id][EventPriority] then
if self.Events[Event.id][EventPriority] then -- 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
-- 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. --if Event.IniObjectCategory ~= Object.Category.STATIC then
for EventClass, EventData in pairs( self.Events[Event.id][EventPriority] ) do -- self:E( { "Evaluating: ", EventClass:GetClassNameAndID() } )
--end
--if Event.IniObjectCategory ~= Object.Category.STATIC then Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
-- self:E( { "Evaluating: ", EventClass:GetClassNameAndID() } ) Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )
--end
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName ) -- If the EventData is for a UNIT, the call directly the EventClass EventFunction for that UNIT.
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName ) if EventData.EventUnit then
-- If the EventData is for a UNIT, the call directly the EventClass EventFunction for that UNIT. -- So now the EventClass must be a UNIT class!!! We check if it is still "Alive".
if EventData.EventUnit then
-- So now the EventClass must be a UNIT class!!! We check if it is still "Alive".
if EventClass:IsAlive() or
Event.id == EVENTS.PlayerEnterUnit or
Event.id == EVENTS.Crash or
Event.id == EVENTS.Dead or
Event.id == EVENTS.RemoveUnit then
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:F( { "Calling EventFunction for UNIT ", 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 ]
if EventFunction and type( EventFunction ) == "function" then
-- Now call the default event function.
if Event.IniObjectCategory ~= 3 then
self:F( { "Calling " .. EventMeta.Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
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:RemoveEvent( 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 EventData.EventGroup then
-- So now the EventClass must be a GROUP class!!! We check if it is still "Alive".
if EventClass:IsAlive() or if EventClass:IsAlive() or
Event.id == EVENTS.PlayerEnterUnit or Event.id == EVENTS.PlayerEnterUnit or
Event.id == EVENTS.Crash or Event.id == EVENTS.Crash or
Event.id == EVENTS.Dead or Event.id == EVENTS.Dead or
Event.id == EVENTS.RemoveUnit then Event.id == EVENTS.RemoveUnit then
-- We can get the name of the EventClass, which is now always a GROUP object. local UnitName = EventClass:GetName()
local GroupName = EventClass:GetName()
if ( EventMeta.Side == "I" and GroupName == Event.IniDCSGroupName ) or if ( EventMeta.Side == "I" and UnitName == Event.IniDCSUnitName ) or
( EventMeta.Side == "T" and GroupName == Event.TgtDCSGroupName ) then ( EventMeta.Side == "T" and UnitName == Event.TgtDCSUnitName ) then
-- First test if a EventFunction is Set, otherwise search for the default function -- First test if a EventFunction is Set, otherwise search for the default function
if EventData.EventFunction then if EventData.EventFunction then
if Event.IniObjectCategory ~= 3 then if Event.IniObjectCategory ~= 3 then
self:F( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } ) self:F( { "Calling EventFunction for UNIT ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
end end
local Result, Value = xpcall( local Result, Value = xpcall(
function() function()
return EventData.EventFunction( EventClass, Event, unpack( EventData.Params ) ) return EventData.EventFunction( EventClass, Event )
end, ErrorHandler ) end, ErrorHandler )
else else
@ -1143,74 +1132,129 @@ function EVENT:onEvent( Event )
-- Now call the default event function. -- Now call the default event function.
if Event.IniObjectCategory ~= 3 then if Event.IniObjectCategory ~= 3 then
self:F( { "Calling " .. EventMeta.Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } ) self:F( { "Calling " .. EventMeta.Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
end end
local Result, Value = xpcall( local Result, Value = xpcall(
function() function()
return EventFunction( EventClass, Event, unpack( EventData.Params ) ) return EventFunction( EventClass, Event )
end, ErrorHandler ) end, ErrorHandler )
end end
end end
end end
else else
-- The EventClass is not alive anymore, we remove it from the EventHandlers... -- The EventClass is not alive anymore, we remove it from the EventHandlers...
--self:RemoveEvent( EventClass, Event.id ) self:RemoveEvent( EventClass, Event.id )
end end
else else
-- If the EventData is not bound to a specific unit, then call the EventClass EventFunction. -- If the EventData is for a GROUP, the call directly the EventClass EventFunction for the UNIT in that GROUP.
-- Note that here the EventFunction will need to implement and determine the logic for the relevant source- or target unit, or weapon. if EventData.EventGroup then
if not EventData.EventUnit then
-- First test if a EventFunction is Set, otherwise search for the default function -- So now the EventClass must be a GROUP class!!! We check if it is still "Alive".
if EventData.EventFunction then if EventClass:IsAlive() or
Event.id == EVENTS.PlayerEnterUnit or
Event.id == EVENTS.Crash or
Event.id == EVENTS.Dead or
Event.id == EVENTS.RemoveUnit then
-- There is an EventFunction defined, so call the EventFunction. -- We can get the name of the EventClass, which is now always a GROUP object.
if Event.IniObjectCategory ~= 3 then local GroupName = EventClass:GetName()
self:F2( { "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. if ( EventMeta.Side == "I" and GroupName == Event.IniDCSGroupName ) or
local EventFunction = EventClass[ EventMeta.Event ] ( EventMeta.Side == "T" and GroupName == Event.TgtDCSGroupName ) then
if EventFunction and type( EventFunction ) == "function" then
-- Now call the default event function. -- First test if a EventFunction is Set, otherwise search for the default function
if Event.IniObjectCategory ~= 3 then if EventData.EventFunction then
self:F2( { "Calling " .. EventMeta.Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
if Event.IniObjectCategory ~= 3 then
self:F( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
end
local Result, Value = xpcall(
function()
return EventData.EventFunction( EventClass, Event, unpack( EventData.Params ) )
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:F( { "Calling " .. EventMeta.Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } )
end
local Result, Value = xpcall(
function()
return EventFunction( EventClass, Event, unpack( EventData.Params ) )
end, ErrorHandler )
end
end end
end
else
-- The EventClass is not alive anymore, we remove it from the EventHandlers...
--self:RemoveEvent( 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:F2( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), EventPriority } )
end
local Result, Value = xpcall( local Result, Value = xpcall(
function() function()
local Result, Value = EventFunction( EventClass, Event ) return EventData.EventFunction( EventClass, Event )
return Result, Value
end, ErrorHandler ) end, ErrorHandler )
end else
end
-- 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:F2( { "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
end end
end end
end end
end end
end
-- When cargo was deleted, it may probably be because of an S_EVENT_DEAD. -- When cargo was deleted, it may probably be because of an S_EVENT_DEAD.
-- However, in the loading logic, an S_EVENT_DEAD is also generated after a Destroy() call. -- However, in the loading logic, an S_EVENT_DEAD is also generated after a Destroy() call.
-- And this is a problem because it will remove all entries from the SET_CARGOs. -- And this is a problem because it will remove all entries from the SET_CARGOs.
-- To prevent this from happening, the Cargo object has a flag NoDestroy. -- To prevent this from happening, the Cargo object has a flag NoDestroy.
-- When true, the SET_CARGO won't Remove the Cargo object from the set. -- When true, the SET_CARGO won't Remove the Cargo object from the set.
-- But we need to switch that flag off after the event handlers have been called. -- But we need to switch that flag off after the event handlers have been called.
if Event.id == EVENTS.DeleteCargo then if Event.id == EVENTS.DeleteCargo then
Event.Cargo.NoDestroy = nil Event.Cargo.NoDestroy = nil
end
else
self:T( { EventMeta.Text, Event } )
end end
else else
self:T( { EventMeta.Text, Event } ) self:E(string.format("WARNING: Could not get EVENTMETA data for event ID=%d! Is this an unknown/new DCS event?", tostring(Event.id)))
end end
Event = nil Event = nil

View File

@ -730,11 +730,14 @@ do -- FSM
if not self._EventSchedules[EventName] then if not self._EventSchedules[EventName] then
CallID = self.CallScheduler:Schedule( self, self._handler, { EventName, ... }, DelaySeconds or 1, nil, nil, nil, 4, true ) CallID = self.CallScheduler:Schedule( self, self._handler, { EventName, ... }, DelaySeconds or 1, nil, nil, nil, 4, true )
self._EventSchedules[EventName] = CallID self._EventSchedules[EventName] = CallID
self:T2(string.format("NEGATIVE Event %s delayed by %.1f sec SCHEDULED with CallID=%s", EventName, DelaySeconds, tostring(CallID)))
else else
self:T2(string.format("NEGATIVE Event %s delayed by %.1f sec CANCELLED as we already have such an event in the queue.", EventName, DelaySeconds))
-- reschedule -- reschedule
end end
else else
CallID = self.CallScheduler:Schedule( self, self._handler, { EventName, ... }, DelaySeconds or 1, nil, nil, nil, 4, true ) CallID = self.CallScheduler:Schedule( self, self._handler, { EventName, ... }, DelaySeconds or 1, nil, nil, nil, 4, true )
self:T2(string.format("Event %s delayed by %.1f sec SCHEDULED with CallID=%s", EventName, DelaySeconds, tostring(CallID)))
end end
else else
error( "FSM: An asynchronous event trigger requires a DelaySeconds parameter!!! This can be positive or negative! Sorry, but will not process this." ) error( "FSM: An asynchronous event trigger requires a DelaySeconds parameter!!! This can be positive or negative! Sorry, but will not process this." )

View File

@ -357,7 +357,7 @@ do -- COORDINATE
-- @return #table Table of DCS static objects found. -- @return #table Table of DCS static objects found.
-- @return #table Table of DCS scenery objects found. -- @return #table Table of DCS scenery objects found.
function COORDINATE:ScanObjects(radius, scanunits, scanstatics, scanscenery) function COORDINATE:ScanObjects(radius, scanunits, scanstatics, scanscenery)
self:F(string.format("Scanning in radius %.1f m.", radius)) self:F(string.format("Scanning in radius %.1f m.", radius or 100))
local SphereSearch = { local SphereSearch = {
id = world.VolumeType.SPHERE, id = world.VolumeType.SPHERE,
@ -437,9 +437,11 @@ do -- COORDINATE
end end
for _,static in pairs(Statics) do for _,static in pairs(Statics) do
self:T(string.format("Scan found static %s", static:getName())) self:T(string.format("Scan found static %s", static:getName()))
_DATABASE:AddStatic(static:getName())
end end
for _,scenery in pairs(Scenery) do for _,scenery in pairs(Scenery) do
self:T(string.format("Scan found scenery %s", scenery:getTypeName())) self:T(string.format("Scan found scenery %s typename=%s", scenery:getName(), scenery:getTypeName()))
SCENERY:Register(scenery:getName(), scenery)
end end
return gotunits, gotstatics, gotscenery, Units, Statics, Scenery return gotunits, gotstatics, gotscenery, Units, Statics, Scenery
@ -1213,34 +1215,64 @@ do -- COORDINATE
--- Build an ground type route point. --- Build an ground type route point.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #number Speed (optional) Speed in km/h. The default speed is 20 km/h. -- @param #number Speed (Optional) Speed in km/h. The default speed is 20 km/h.
-- @param #string Formation (optional) The route point Formation, which is a text string that specifies exactly the Text in the Type of the route point, like "Vee", "Echelon Right". -- @param #string Formation (Optional) The route point Formation, which is a text string that specifies exactly the Text in the Type of the route point, like "Vee", "Echelon Right".
-- @param #table DCSTasks A table of DCS tasks that are executed at the waypoints. Mind the curly brackets {}! -- @param #table DCSTasks (Optional) A table of DCS tasks that are executed at the waypoints. Mind the curly brackets {}!
-- @return #table The route point. -- @return #table The route point.
function COORDINATE:WaypointGround( Speed, Formation, DCSTasks ) function COORDINATE:WaypointGround( Speed, Formation, DCSTasks )
self:F2( { Formation, Speed } ) self:F2( { Speed, Formation, DCSTasks } )
local RoutePoint = {} local RoutePoint = {}
RoutePoint.x = self.x
RoutePoint.y = self.z
RoutePoint.action = Formation or "" RoutePoint.x = self.x
--RoutePoint.formation_template = Formation and "" or nil RoutePoint.y = self.z
RoutePoint.alt = self:GetLandHeight()+1 -- self.y
RoutePoint.alt_type = COORDINATE.WaypointAltType.BARO
RoutePoint.action = Formation or "Off Road"
RoutePoint.formation_template=""
RoutePoint.ETA=0
RoutePoint.ETA_locked=true
RoutePoint.speed = ( Speed or 20 ) / 3.6 RoutePoint.speed = ( Speed or 20 ) / 3.6
RoutePoint.speed_locked = true RoutePoint.speed_locked = true
-- ["task"] = RoutePoint.task = {}
-- { RoutePoint.task.id = "ComboTask"
-- ["id"] = "ComboTask", RoutePoint.task.params = {}
-- ["params"] = RoutePoint.task.params.tasks = DCSTasks or {}
-- {
-- ["tasks"] = return RoutePoint
-- { end
-- }, -- end of ["tasks"]
-- }, -- end of ["params"] --- Build route waypoint point for Naval units.
-- }, -- end of ["task"] -- @param #COORDINATE self
-- @param #number Speed (Optional) Speed in km/h. The default speed is 20 km/h.
-- @param #string Depth (Optional) Dive depth in meters. Only for submarines. Default is COORDINATE.y component.
-- @param #table DCSTasks (Optional) A table of DCS tasks that are executed at the waypoints. Mind the curly brackets {}!
-- @return #table The route point.
function COORDINATE:WaypointNaval( Speed, Depth, DCSTasks )
self:F2( { Speed, Depth, DCSTasks } )
local RoutePoint = {}
RoutePoint.x = self.x
RoutePoint.y = self.z
RoutePoint.alt = Depth or self.y -- Depth is for submarines only. Ships should have alt=0.
RoutePoint.alt_type = "BARO"
RoutePoint.type = "Turning Point"
RoutePoint.action = "Turning Point"
RoutePoint.formation_template = ""
RoutePoint.ETA=0
RoutePoint.ETA_locked=true
RoutePoint.speed = ( Speed or 20 ) / 3.6
RoutePoint.speed_locked = true
RoutePoint.task = {} RoutePoint.task = {}
RoutePoint.task.id = "ComboTask" RoutePoint.task.id = "ComboTask"

View File

@ -509,14 +509,17 @@ end
-- @param #SPAWN self -- @param #SPAWN self
-- @param #string AirbaseName Name of the airbase. -- @param #string AirbaseName Name of the airbase.
-- @param #number Takeoff (Optional) Takeoff type. Can be SPAWN.Takeoff.Hot (default), SPAWN.Takeoff.Cold or SPAWN.Takeoff.Runway. -- @param #number Takeoff (Optional) Takeoff type. Can be SPAWN.Takeoff.Hot (default), SPAWN.Takeoff.Cold or SPAWN.Takeoff.Runway.
-- @param #number TerminalTyple (Optional) The terminal type.
-- @return #SPAWN self -- @return #SPAWN self
function SPAWN:InitAirbase( AirbaseName, Takeoff ) function SPAWN:InitAirbase( AirbaseName, Takeoff, TerminalType )
self:F( ) self:F( )
self.SpawnInitAirbase=AIRBASE:FindByName(AirbaseName) self.SpawnInitAirbase=AIRBASE:FindByName(AirbaseName)
self.SpawnInitTakeoff=Takeoff or SPAWN.Takeoff.Hot self.SpawnInitTakeoff=Takeoff or SPAWN.Takeoff.Hot
self.SpawnInitTerminalType=TerminalType
return self return self
end end
@ -1133,7 +1136,7 @@ function SPAWN:Spawn()
self:F( { self.SpawnTemplatePrefix, self.SpawnIndex, self.AliveUnits } ) self:F( { self.SpawnTemplatePrefix, self.SpawnIndex, self.AliveUnits } )
if self.SpawnInitAirbase then if self.SpawnInitAirbase then
return self:SpawnAtAirbase(self.SpawnInitAirbase, self.SpawnInitTakeoff) return self:SpawnAtAirbase(self.SpawnInitAirbase, self.SpawnInitTakeoff, nil, self.SpawnInitTerminalType)
else else
return self:SpawnWithIndex( self.SpawnIndex + 1 ) return self:SpawnWithIndex( self.SpawnIndex + 1 )
end end

View File

@ -19,6 +19,8 @@
do -- UserFlag do -- UserFlag
--- @type USERFLAG --- @type USERFLAG
-- @field #string ClassName Name of the class
-- @field #string UserFlagName Name of the flag.
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
@ -30,7 +32,8 @@ do -- UserFlag
-- --
-- @field #USERFLAG -- @field #USERFLAG
USERFLAG = { USERFLAG = {
ClassName = "USERFLAG", ClassName = "USERFLAG",
UserFlagName = nil,
} }
--- USERFLAG Constructor. --- USERFLAG Constructor.
@ -46,6 +49,12 @@ do -- UserFlag
return self return self
end end
--- Get the userflag name.
-- @param #USERFLAG self
-- @return #string Name of the user flag.
function USERFLAG:GetName()
return self.UserFlagName
end
--- Set the userflag to a given Number. --- Set the userflag to a given Number.
-- @param #USERFLAG self -- @param #USERFLAG self

View File

@ -428,6 +428,10 @@ do -- Types
-- @type TaskArray -- @type TaskArray
-- @list <#Task> -- @list <#Task>
---
--@type WaypointAir
--@field #boolean lateActivated
--@field #boolean uncontrolled
end -- end --
@ -1205,6 +1209,7 @@ do -- AI
-- @field TAKEOFF -- @field TAKEOFF
-- @field TAKEOFF_PARKING -- @field TAKEOFF_PARKING
-- @field TURNING_POINT -- @field TURNING_POINT
-- @field TAKEOFF_PARKING_HOT
-- @field LAND -- @field LAND
--- @type AI.Task.TurnMethod --- @type AI.Task.TurnMethod
@ -1242,7 +1247,7 @@ do -- AI
-- @field #AI.Option.Naval.id id -- @field #AI.Option.Naval.id id
-- @field #AI.Option.Naval.val val -- @field #AI.Option.Naval.val val
--TODO: work on formation
--- @type AI.Option.Air.id --- @type AI.Option.Air.id
-- @field NO_OPTION -- @field NO_OPTION
-- @field ROE -- @field ROE
@ -1252,6 +1257,33 @@ do -- AI
-- @field FORMATION -- @field FORMATION
-- @field RTB_ON_BINGO -- @field RTB_ON_BINGO
-- @field SILENCE -- @field SILENCE
-- @field RTB_ON_OUT_OF_AMMO
-- @field ECM_USING
-- @field PROHIBIT_AA
-- @field PROHIBIT_JETT
-- @field PROHIBIT_AB
-- @field PROHIBIT_AG
-- @field MISSILE_ATTACK
-- @field PROHIBIT_WP_PASS_REPORT
--- @type AI.Option.Air.id.FORMATION
-- @field LINE_ABREAST
-- @field TRAIL
-- @field WEDGE
-- @field ECHELON_RIGHT
-- @field ECHELON_LEFT
-- @field FINGER_FOUR
-- @field SPREAD_FOUR
-- @field WW2_BOMBER_ELEMENT
-- @field WW2_BOMBER_ELEMENT_HEIGHT
-- @field WW2_FIGHTER_VIC
-- @field HEL_WEDGE
-- @field HEL_ECHELON
-- @field HEL_FRONT
-- @field HEL_COLUMN
-- @field COMBAT_BOX
-- @field JAVELIN_DOWN
--- @type AI.Option.Air.val --- @type AI.Option.Air.val
-- @field #AI.Option.Air.val.ROE ROE -- @field #AI.Option.Air.val.ROE ROE
@ -1285,11 +1317,26 @@ do -- AI
-- @field WHEN_FLYING_IN_SAM_WEZ -- @field WHEN_FLYING_IN_SAM_WEZ
-- @field WHEN_FLYING_NEAR_ENEMIES -- @field WHEN_FLYING_NEAR_ENEMIES
--- @type AI.Option.Air.val.ECM_USING
-- @field NEVER_USE
-- @field USE_IF_ONLY_LOCK_BY_RADAR
-- @field USE_IF_DETECTED_LOCK_BY_RADAR
-- @field ALWAYS_USE
--- @type AI.Option.Air.val.MISSILE_ATTACK
-- @field MAX_RANGE
-- @field NEZ_RANGE
-- @field HALF_WAY_RMAX_NEZ
-- @field TARGET_THREAT_EST
-- @field RANDOM_RANGE
--- @type AI.Option.Ground.id --- @type AI.Option.Ground.id
-- @field NO_OPTION -- @field NO_OPTION
-- @field ROE @{#AI.Option.Ground.val.ROE} -- @field ROE @{#AI.Option.Ground.val.ROE}
-- @field DISPERSE_ON_ATTACK true or false -- @field DISPERSE_ON_ATTACK true or false
-- @field ALARM_STATE @{#AI.Option.Ground.val.ALARM_STATE} -- @field ALARM_STATE @{#AI.Option.Ground.val.ALARM_STATE}
-- @field ENGAGE_AIR_WEAPONS
--- @type AI.Option.Ground.val --- @type AI.Option.Ground.val
-- @field #AI.Option.Ground.val.ROE ROE -- @field #AI.Option.Ground.val.ROE ROE

View File

@ -516,7 +516,7 @@ RANGE.MenuF10Root=nil
--- Range script version. --- Range script version.
-- @field #string version -- @field #string version
RANGE.version="2.2.1" RANGE.version="2.2.2"
--TODO list: --TODO list:
--TODO: Verbosity level for messages. --TODO: Verbosity level for messages.
@ -754,7 +754,7 @@ function RANGE:onafterStart()
if self.rangecontrolfreq then if self.rangecontrolfreq then
-- Radio queue. -- Radio queue.
self.rangecontrol=RADIOQUEUE:New(self.rangecontrolfreq) self.rangecontrol=RADIOQUEUE:New(self.rangecontrolfreq, nil, self.rangename)
-- Init numbers. -- Init numbers.
self.rangecontrol:SetDigit(0, RANGE.Sound.RC0.filename, RANGE.Sound.RC0.duration, self.soundpath) self.rangecontrol:SetDigit(0, RANGE.Sound.RC0.filename, RANGE.Sound.RC0.duration, self.soundpath)
@ -778,7 +778,7 @@ function RANGE:onafterStart()
if self.instructorfreq then if self.instructorfreq then
-- Radio queue. -- Radio queue.
self.instructor=RADIOQUEUE:New(self.instructorfreq) self.instructor=RADIOQUEUE:New(self.instructorfreq, nil, self.rangename)
-- Init numbers. -- Init numbers.
self.instructor:SetDigit(0, RANGE.Sound.IR0.filename, RANGE.Sound.IR0.duration, self.soundpath) self.instructor:SetDigit(0, RANGE.Sound.IR0.filename, RANGE.Sound.IR0.duration, self.soundpath)
@ -1341,9 +1341,9 @@ function RANGE:AddBombingTargetUnit(unit, goodhitrange, randommove)
-- Debug or error output. -- Debug or error output.
if _isstatic==true then if _isstatic==true then
self:T(self.id..string.format("Adding STATIC bombing target %s with good hit range %d. Random move = %s.", name, goodhitrange, tostring(randommove))) self:I(self.id..string.format("Adding STATIC bombing target %s with good hit range %d. Random move = %s.", name, goodhitrange, tostring(randommove)))
elseif _isstatic==false then elseif _isstatic==false then
self:T(self.id..string.format("Adding UNIT bombing target %s with good hit range %d. Random move = %s.", name, goodhitrange, tostring(randommove))) self:I(self.id..string.format("Adding UNIT bombing target %s with good hit range %d. Random move = %s.", name, goodhitrange, tostring(randommove)))
else else
self:E(self.id..string.format("ERROR! No bombing target with name %s could be found. Carefully check all UNIT and STATIC names defined in the mission editor!", name)) self:E(self.id..string.format("ERROR! No bombing target with name %s could be found. Carefully check all UNIT and STATIC names defined in the mission editor!", name))
end end
@ -2967,10 +2967,10 @@ function RANGE:_AddF10Commands(_unitName)
missionCommands.addCommandForGroup(_gid, "Strafe Pits", _infoPath, self._DisplayStrafePits, self, _unitName) missionCommands.addCommandForGroup(_gid, "Strafe Pits", _infoPath, self._DisplayStrafePits, self, _unitName)
end end
else else
self:T(self.id.."Could not find group or group ID in AddF10Menu() function. Unit name: ".._unitName) self:E(self.id.."Could not find group or group ID in AddF10Menu() function. Unit name: ".._unitName)
end end
else else
self:T(self.id.."Player unit does not exist in AddF10Menu() function. Unit name: ".._unitName) self:E(self.id.."Player unit does not exist in AddF10Menu() function. Unit name: ".._unitName)
end end
end end

View File

@ -523,7 +523,7 @@ _ATIS={}
--- ATIS class version. --- ATIS class version.
-- @field #string version -- @field #string version
ATIS.version="0.6.2" ATIS.version="0.6.3"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
@ -1143,6 +1143,10 @@ function ATIS:onafterBroadcast(From, Event, To)
local WINDFROM=string.format("%03d", windFrom-magvar) local WINDFROM=string.format("%03d", windFrom-magvar)
local WINDSPEED=string.format("%d", UTILS.MpsToKnots(windSpeed)) local WINDSPEED=string.format("%d", UTILS.MpsToKnots(windSpeed))
if WINDFROM=="000" then
WINDFROM="360"
end
if self.metric then if self.metric then
WINDSPEED=string.format("%d", windSpeed) WINDSPEED=string.format("%d", windSpeed)
end end
@ -1151,27 +1155,7 @@ function ATIS:onafterBroadcast(From, Event, To)
--- Runway --- --- Runway ---
-------------- --------------
-- Get active runway data based on wind direction. local runway, rwyLeft=self:GetActiveRunway()
local runact=self.airbase:GetActiveRunway(self.runwaym2t)
-- Active runway "31".
local runway=self:GetMagneticRunway(windFrom) or runact.idx
-- Left or right in case there are two runways with the same heading.
local rwyLeft=nil
-- Check if user explicitly specified a runway.
if self.activerunway then
-- Get explicit runway heading if specified.
local runwayno=self:GetRunwayWithoutLR(self.activerunway)
if runwayno~="" then
runway=runwayno
end
-- Was "L"eft or "R"ight given?
rwyLeft=self:GetRunwayLR(self.activerunway)
end
------------ ------------
--- Time --- --- Time ---
@ -1772,11 +1756,41 @@ end
-- Misc Functions -- Misc Functions
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Get runway from user supplied magnetic heading. --- Get active runway runway.
-- @param #ATIS self -- @param #ATIS self
-- @return #string Runway magnetic heading divided by ten (and rounded). Eg, "13" for 130°. -- @return #string Active runway, e.g. "31" for 310 deg.
-- @return #boolean Use Left=true, Right=false, or nil.
function ATIS:GetActiveRunway() function ATIS:GetActiveRunway()
local coord=self.airbase:GetCoordinate()
local height=coord:GetLandHeight()
-- Get wind direction and speed in m/s.
local windFrom, windSpeed=coord:GetWind(height+10)
-- Get active runway data based on wind direction.
local runact=self.airbase:GetActiveRunway(self.runwaym2t)
-- Active runway "31".
local runway=self:GetMagneticRunway(windFrom) or runact.idx
-- Left or right in case there are two runways with the same heading.
local rwyLeft=nil
-- Check if user explicitly specified a runway.
if self.activerunway then
-- Get explicit runway heading if specified.
local runwayno=self:GetRunwayWithoutLR(self.activerunway)
if runwayno~="" then
runway=runwayno
end
-- Was "L"eft or "R"ight given?
rwyLeft=self:GetRunwayLR(self.activerunway)
end
return runway, rwyLeft
end end
--- Get runway from user supplied magnetic heading. --- Get runway from user supplied magnetic heading.

View File

@ -1,3 +1,11 @@
--- **Utilities** Enumerators.
--
-- See the [Simulator Scripting Engine Documentation](https://wiki.hoggitworld.com/view/Simulator_Scripting_Engine_Documentation) on Hoggit for further explanation and examples.
--
-- @module DCS
-- @image MOOSE.JPG
ENUMS = {} ENUMS = {}
ENUMS.ROE = { ENUMS.ROE = {
@ -13,3 +21,29 @@ ENUMS.ROT = {
EvadeFire = 3, EvadeFire = 3,
Vertical = 4 Vertical = 4
} }
ENUMS.WeaponFlag={
-- Auto
Auto=1073741822,
-- Bombs
LGB=2,
TvGB=4,
SNSGB=8,
HEBomb=16,
Penetrator=32,
NapalmBomb=64,
FAEBomb=128,
ClusterBomb=256,
Dispencer=512,
CandleBomb=1024,
ParachuteBomb=2147483648,
GuidedBomb=14, -- (LGB + TvGB + SNSGB)
AnyUnguidedBomb=2147485680, -- (HeBomb + Penetrator + NapalmBomb + FAEBomb + ClusterBomb + Dispencer + CandleBomb + ParachuteBomb)
AnyBomb=2147485694, -- (GuidedBomb + AnyUnguidedBomb)
-- Rockets
LightRocket=2048,
MarkerRocket=4096,
CandleRocket=8192,
HeavyRocket=16384,
AnyRocket=30720 -- (LightRocket + MarkerRocket + CandleRocket + HeavyRocket)
}

View File

@ -342,8 +342,9 @@ AIRBASE.TerminalType = {
-- @return Wrapper.Airbase#AIRBASE -- @return Wrapper.Airbase#AIRBASE
function AIRBASE:Register( AirbaseName ) function AIRBASE:Register( AirbaseName )
local self = BASE:Inherit( self, POSITIONABLE:New( AirbaseName ) ) local self = BASE:Inherit( self, POSITIONABLE:New( AirbaseName ) ) --#AIRBASE
self.AirbaseName = AirbaseName self.AirbaseName = AirbaseName
self.AirbaseID = self:GetID(true)
self.AirbaseZone = ZONE_RADIUS:New( AirbaseName, self:GetVec2(), 2500 ) self.AirbaseZone = ZONE_RADIUS:New( AirbaseName, self:GetVec2(), 2500 )
return self return self
end end
@ -380,7 +381,7 @@ function AIRBASE:FindByID(id)
for name,_airbase in pairs(_DATABASE.AIRBASES) do for name,_airbase in pairs(_DATABASE.AIRBASES) do
local airbase=_airbase --#AIRBASE local airbase=_airbase --#AIRBASE
local aid=tonumber(airbase:GetID()) local aid=tonumber(airbase:GetID(true))
if aid==id then if aid==id then
return airbase return airbase
@ -430,6 +431,54 @@ function AIRBASE.GetAllAirbases(coalition, category)
return airbases return airbases
end end
--- Get ID of the airbase.
-- @param #AIRBASE self
-- @param #boolean unique (Optional) If true, ships will get a negative sign as the unit ID might be the same as an airbase ID. Default off!
-- @return #number The airbase ID.
function AIRBASE:GetID(unique)
if self.AirbaseID then
return unique and self.AirbaseID or math.abs(self.AirbaseID)
else
for DCSAirbaseId, DCSAirbase in pairs(world.getAirbases()) do
-- Get the airbase name.
local AirbaseName = DCSAirbase:getName()
-- This gives the incorrect value to be inserted into the airdromeID for DCS 2.5.6!
local airbaseID=tonumber(DCSAirbase:getID())
-- No way AFIK to get the DCS version. So we check if the event exists. That should tell us if we are on DCS 2.5.6 or prior to that.
if world.event.S_EVENT_KILL and world.event.S_EVENT_KILL>0 and self:GetAirbaseCategory()==Airbase.Category.AIRDROME then
-- We have to take the key value of this loop!
airbaseID=DCSAirbaseId
-- Now another quirk: for Caucasus, we need to add 11 to the key value to get the correct ID. See https://forums.eagle.ru/showpost.php?p=4210774&postcount=11
if UTILS.GetDCSMap()==DCSMAP.Caucasus then
airbaseID=airbaseID+11
end
end
if AirbaseName==self.AirbaseName then
if self:GetAirbaseCategory()==Airbase.Category.SHIP then
-- Ships get a negative sign as their unit number might be the same as the ID of another airbase.
return unique and -airbaseID or airbaseID
else
return airbaseID
end
end
end
end
return nil
end
--- Returns a table of parking data for a given airbase. If the optional parameter *available* is true only available parking will be returned, otherwise all parking at the base is returned. Term types have the following enumerated values: --- Returns a table of parking data for a given airbase. If the optional parameter *available* is true only available parking will be returned, otherwise all parking at the base is returned. Term types have the following enumerated values:
-- --

View File

@ -312,6 +312,7 @@ function CONTROLLABLE:ClearTasks()
if DCSControllable then if DCSControllable then
local Controller = self:_GetController() local Controller = self:_GetController()
env.info("FF clearing tasks!")
Controller:resetTask() Controller:resetTask()
return self return self
end end
@ -860,34 +861,18 @@ function CONTROLLABLE:TaskAttackGroup( AttackGroup, WeaponType, WeaponExpend, At
-- } -- }
-- } -- }
local DirectionEnabled = nil
if Direction then
DirectionEnabled = true
else
DirectionEnabled = false
Direction=0
end
local AltitudeEnabled = nil local DCSTask = { id = 'AttackGroup',
if Altitude then
AltitudeEnabled = true
else
AltitudeEnabled = false
Altitude=0
end
local DCSTask
DCSTask = { id = 'AttackGroup',
params = { params = {
groupId = AttackGroup:GetID(), groupId = AttackGroup:GetID(),
weaponType = WeaponType, weaponType = WeaponType or 1073741822,
expend = WeaponExpend, expend = WeaponExpend or "Auto",
attackQty = AttackQty, attackQtyLimit = AttackQty and true or false,
directionEnabled = DirectionEnabled, attackQty = AttackQty,
direction = Direction, directionEnabled = Direction and true or false,
altitudeEnabled = AltitudeEnabled, direction = Direction and math.rad(Direction) or nil,
altitude = Altitude, altitudeEnabled = Altitude and true or false,
attackQtyLimit = AttackQtyLimit, altitude = Altitude,
}, },
}, },
@ -912,16 +897,16 @@ function CONTROLLABLE:TaskAttackUnit(AttackUnit, GroupAttack, WeaponExpend, Atta
DCSTask = { DCSTask = {
id = 'AttackUnit', id = 'AttackUnit',
params = { params = {
unitId = AttackUnit:GetID(), unitId = AttackUnit:GetID(),
groupAttack = GroupAttack or false, groupAttack = GroupAttack and GroupAttack or false,
expend = WeaponExpend or "Auto", expend = WeaponExpend or "Auto",
directionEnabled = Direction and true or false, directionEnabled = Direction and true or false,
direction = math.rad(Direction or 0), direction = Direction and math.rad(Direction) or nil,
altitudeEnabled = Altitude and true or false, altitudeEnabled = Altitude and true or false,
altitude = Altitude or math.max(1000, AttackUnit:GetAltitude()), altitude = Altitude,
attackQtyLimit = AttackQty and true or false, attackQtyLimit = AttackQty and true or false,
attackQty = AttackQty, attackQty = AttackQty,
weaponType = WeaponType weaponType = WeaponType or 1073741822,
} }
} }
@ -945,25 +930,6 @@ end
function CONTROLLABLE:TaskBombing( Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType, Divebomb ) function CONTROLLABLE:TaskBombing( Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType, Divebomb )
self:F( { self.ControllableName, Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType, Divebomb } ) self:F( { self.ControllableName, Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType, Divebomb } )
local _groupattack=false
if GroupAttack then
_groupattack=GroupAttack
end
local _direction=0
local _directionenabled=false
if Direction then
_direction=math.rad(Direction)
_directionenabled=true
end
local _altitude=5000
local _altitudeenabled=false
if Altitude then
_altitude=Altitude
_altitudeenabled=true
end
local _attacktype=nil local _attacktype=nil
if Divebomb then if Divebomb then
_attacktype="Dive" _attacktype="Dive"
@ -974,18 +940,19 @@ function CONTROLLABLE:TaskBombing( Vec2, GroupAttack, WeaponExpend, AttackQty, D
DCSTask = { DCSTask = {
id = 'Bombing', id = 'Bombing',
params = { params = {
x = Vec2.x, point = Vec2,
y = Vec2.y, x = Vec2.x,
groupAttack = _groupattack, y = Vec2.y,
expend = WeaponExpend or "Auto", groupAttack = GroupAttack and GroupAttack or false,
attackQtyLimit = false, --AttackQty and true or false, expend = WeaponExpend or "Auto",
attackQty = AttackQty or 1, attackQtyLimit = AttackQty and true or false,
directionEnabled = _directionenabled, attackQty = AttackQty,
direction = _direction, directionEnabled = Direction and true or false,
altitudeEnabled = _altitudeenabled, direction = Direction and math.rad(Direction) or nil,
altitude = _altitude, altitudeEnabled = Altitude and true or false,
weaponType = WeaponType, altitude = Altitude,
--attackType=_attacktype, weaponType = WeaponType or 1073741822,
attackType = _attacktype,
}, },
} }
@ -997,7 +964,7 @@ end
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @param DCS#Vec2 Vec2 2D-coordinates of the point to deliver weapon at. -- @param DCS#Vec2 Vec2 2D-coordinates of the point to deliver weapon at.
-- @param #boolean GroupAttack (Optional) If true, all units in the group will attack the Unit when found. -- @param #boolean GroupAttack (Optional) If true, all units in the group will attack the Unit when found.
-- @param DCS#AI.Task.WeaponExpend WeaponExpend (Optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion. -- @param DCS#AI.Task.WeaponExpend WeaponExpend (Optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit will choose expend on its own discretion.
-- @param #number AttackQty (Optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. -- @param #number AttackQty (Optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param DCS#Azimuth Direction (Optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. -- @param DCS#Azimuth Direction (Optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param #number Altitude (Optional) The altitude [meters] from where to attack. Default 30 m. -- @param #number Altitude (Optional) The altitude [meters] from where to attack. Default 30 m.
@ -1010,18 +977,18 @@ function CONTROLLABLE:TaskAttackMapObject( Vec2, GroupAttack, WeaponExpend, Atta
DCSTask = { DCSTask = {
id = 'AttackMapObject', id = 'AttackMapObject',
params = { params = {
point = Vec2, point = Vec2,
x = Vec2.x, x = Vec2.x,
y = Vec2.y, y = Vec2.y,
groupAttack = GroupAttack or false, groupAttack = GroupAttack or false,
expend = WeaponExpend or "Auto", expend = WeaponExpend or "Auto",
attackQtyLimit = AttackQty and true or false, attackQtyLimit = AttackQty and true or false,
attackQty = AttackQty, attackQty = AttackQty,
directionEnabled = Direction and true or false, directionEnabled = Direction and true or false,
direction = Direction, direction = Direction,
altitudeEnabled = Altitude and true or false, altitudeEnabled = Altitude and true or false,
altitude = Altitude or 30, altitude = Altitude,
weaponType = WeaponType or 1073741822, weaponType = WeaponType or 1073741822,
}, },
}, },
@ -1030,48 +997,140 @@ function CONTROLLABLE:TaskAttackMapObject( Vec2, GroupAttack, WeaponExpend, Atta
end end
--- (AIR) Delivering weapon via CarpetBombing (all bombers in formation release at same time) at the point on the ground.
-- @param #CONTROLLABLE self
-- @param DCS#Vec2 Vec2 2D-coordinates of the point to deliver weapon at.
-- @param #boolean GroupAttack (optional) If true, all units in the group will attack the Unit when found.
-- @param DCS#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit will choose expend on its own discretion.
-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param DCS#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param #number Altitude (optional) The altitude from where to attack.
-- @param #number WeaponType (optional) The WeaponType.
-- @param #number CarpetLength (optional) default to 500 m.
-- @return DCS#Task The DCS task structure.
function CONTROLLABLE:TaskCarpetBombing(Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType, CarpetLength)
self:F2( { self.ControllableName, Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType, CarpetLength } )
-- Build Task Structure
local DCSTask = {
id = 'CarpetBombing',
params = {
attackType = "Carpet",
point = Vec2,
x = Vec2.x,
y = Vec2.y,
groupAttack = GroupAttack and GroupAttack or false,
carpetLength = CarpetLength or 500,
weaponType = WeaponType or ENUMS.WeaponFlag.AnyBomb,
expend = WeaponExpend or "All",
attackQtyLimit = AttackQty and true or false,
attackQty = AttackQty,
directionEnabled = Direction and true or false,
direction = Direction and math.rad(Direction) or nil,
altitudeEnabled = Altitude and true or false,
altitude = Altitude,
}
}
return DCSTask
end
--- (AIR) Following another airborne controllable.
-- The unit / controllable will follow lead unit of another controllable, wingmens of both controllables will continue following their leaders.
-- Used to support CarpetBombing Task
-- @param #CONTROLLABLE self
-- @param #CONTROLLABLE FollowControllable The controllable to be followed.
-- @param DCS#Vec3 Vec3 Position of the unit / lead unit of the controllable relative lead unit of another controllable in frame reference oriented by course of lead unit of another controllable. If another controllable is on land the unit / controllable will orbit around.
-- @param #number LastWaypointIndex Detach waypoint of another controllable. Once reached the unit / controllable Follow task is finished.
-- @return DCS#Task The DCS task structure.
function CONTROLLABLE:TaskFollowBigFormation(FollowControllable, Vec3, LastWaypointIndex )
local DCSTask = {
id = 'FollowBigFormation',
params = {
groupId = FollowControllable:GetID(),
pos = Vec3,
lastWptIndexFlag = LastWaypointIndex and true or false,
lastWptIndex = LastWaypointIndex
}
}
return DCSTask
end
--- (AIR) Move the controllable to a Vec2 Point, wait for a defined duration and embark a controllable.
-- @param #CONTROLLABLE self
-- @param DCS#Vec2 Vec2 The point where to wait. Needs to have x and y components.
-- @param Core.Set#SET_GROUP GroupSetForEmparking Set of groups to embark.
-- @param #number Duration (Optional) The maximum duration in seconds to wait until all groups have embarked.
-- @param Core.Set#SET_GROUP (Optional) DistributionGroupSet Set of groups identifying the groups needing to board specific helicopters.
-- @return DCS#Task The DCS task structure.
function CONTROLLABLE:TaskEmbarking(Vec2, GroupSetForEmbarking, Duration, DistributionGroupSet)
-- Table of group IDs for embarking.
local g4e={}
if GroupSetForEmbarking then
for _,_group in pairs(GroupSetForEmbarking:GetSet()) do
local group=_group --Wrapper.Group#GROUP
table.insert(g4e, group:GetID())
end
else
self:E("ERROR: No groups for embarking specified!")
return nil
end
-- Table of group IDs for embarking.
local Distribution={}
if DistributionGroupSet then
for _,_group in pairs(DistributionGroupSet:GetSet()) do
local group=_group --Wrapper.Group#GROUP
table.insert(Distribution, group:GetID())
end
end
local DCSTask = {
id = 'Embarking',
params = {
Vec2 = Vec2,
x = Vec2.x,
y = Vec2.y,
groupsForEmbarking = g4e,
durationFlag = Duration and true or false,
duration = Duration,
distributionFlag = DistributionGroupSet and true or false,
distribution = Distribution,
}
}
self:T3( { DCSTask } )
return DCSTask
end
--- (AIR) Orbit at a specified position at a specified alititude during a specified duration with a specified speed. --- (AIR) Orbit at a specified position at a specified alititude during a specified duration with a specified speed.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @param DCS#Vec2 Point The point to hold the position. -- @param DCS#Vec2 Point The point to hold the position.
-- @param #number Altitude The altitude [m] to hold the position. -- @param #number Altitude The altitude AGL in meters to hold the position.
-- @param #number Speed The speed [m/s] flying when holding the position. -- @param #number Speed The speed [m/s] flying when holding the position.
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:TaskOrbitCircleAtVec2( Point, Altitude, Speed ) function CONTROLLABLE:TaskOrbitCircleAtVec2( Point, Altitude, Speed )
self:F2( { self.ControllableName, Point, Altitude, Speed } ) self:F2( { self.ControllableName, Point, Altitude, Speed } )
-- pattern = enum AI.Task.OribtPattern, local DCSTask = {
-- point = Vec2, id = 'Orbit',
-- point2 = Vec2, params = {
-- speed = Distance, pattern = AI.Task.OrbitPattern.CIRCLE,
-- altitude = Distance point = Point,
speed = Speed,
local LandHeight = land.getHeight( Point ) altitude = Altitude + land.getHeight( Point )
self:T3( { LandHeight } )
local DCSTask = { id = 'Orbit',
params = { pattern = AI.Task.OrbitPattern.CIRCLE,
point = Point,
speed = Speed,
altitude = Altitude + LandHeight
} }
} }
-- local AITask = { id = 'ControlledTask',
-- params = { task = { id = 'Orbit',
-- params = { pattern = AI.Task.OrbitPattern.CIRCLE,
-- point = Point,
-- speed = Speed,
-- altitude = Altitude + LandHeight
-- }
-- },
-- stopCondition = { duration = Duration
-- }
-- }
-- }
-- )
return DCSTask return DCSTask
end end
@ -1111,7 +1170,7 @@ end
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @param #number Altitude The altitude [m] to hold the position. -- @param #number Altitude The altitude [m] to hold the position.
-- @param #number Speed The speed [m/s] flying when holding the position. -- @param #number Speed The speed [m/s] flying when holding the position.
-- @param Core.Point#COORDINATE Coordinate (optional) The coordinate where to orbit. If the coordinate is not given, then the current position of the controllable is used. -- @param Core.Point#COORDINATE Coordinate (Optional) The coordinate where to orbit. If the coordinate is not given, then the current position of the controllable is used.
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:TaskOrbitCircle( Altitude, Speed, Coordinate ) function CONTROLLABLE:TaskOrbitCircle( Altitude, Speed, Coordinate )
self:F2( { self.ControllableName, Altitude, Speed } ) self:F2( { self.ControllableName, Altitude, Speed } )
@ -1139,10 +1198,6 @@ function CONTROLLABLE:TaskHoldPosition()
end end
--- (AIR) Delivering weapon on the runway. See [hoggit](https://wiki.hoggitworld.com/view/DCS_task_bombingRunway) --- (AIR) Delivering weapon on the runway. See [hoggit](https://wiki.hoggitworld.com/view/DCS_task_bombingRunway)
-- --
-- Make sure the aircraft has the following role: -- Make sure the aircraft has the following role:
@ -1165,36 +1220,18 @@ end
function CONTROLLABLE:TaskBombingRunway(Airbase, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack) function CONTROLLABLE:TaskBombingRunway(Airbase, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack)
self:F2( { self.ControllableName, Airbase, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack } ) self:F2( { self.ControllableName, Airbase, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack } )
-- BombingRunway = { local DCSTask = {
-- id = 'BombingRunway', id = 'BombingRunway',
-- params = {
-- runwayId = AirdromeId,
-- weaponType = number,
-- expend = enum AI.Task.WeaponExpend,
-- attackQty = number,
-- direction = Azimuth,
-- groupAttack = boolean,
-- }
-- }
-- Defaults.
WeaponType=WeaponType or 2147485694
WeaponExpend=WeaponExpend or AI.Task.WeaponExpend.ALL
AttackQty=AttackQty or 1
local DCSTask
DCSTask = { id = 'BombingRunway',
params = { params = {
runwayId = Airbase:GetID(), runwayId = Airbase:GetID(),
weaponType = WeaponType, weaponType = WeaponType or ENUMS.WeaponFlag.AnyBomb,
expend = WeaponExpend, expend = WeaponExpend or AI.Task.WeaponExpend.ALL,
attackQty = AttackQty, attackQty = AttackQty or 1,
direction = Direction, direction = Direction and math.rad(Direction) or nil,
groupAttack = GroupAttack, groupAttack = GroupAttack and GroupAttack or false,
}, },
}, }
self:T3( { DCSTask } )
return DCSTask return DCSTask
end end
@ -1203,16 +1240,9 @@ end
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @return DCS#Task The DCS task structure. -- @return DCS#Task The DCS task structure.
function CONTROLLABLE:TaskRefueling() function CONTROLLABLE:TaskRefueling()
self:F2( { self.ControllableName } )
-- Refueling = {
-- id = 'Refueling',
-- params = {}
-- }
local DCSTask={id='Refueling', params={}} local DCSTask={id='Refueling', params={}}
self:T3( { DCSTask } )
return DCSTask return DCSTask
end end
@ -1222,37 +1252,16 @@ end
-- @param DCS#Vec2 Point The point where to land. -- @param DCS#Vec2 Point The point where to land.
-- @param #number Duration The duration in seconds to stay on the ground. -- @param #number Duration The duration in seconds to stay on the ground.
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:TaskLandAtVec2( Point, Duration ) function CONTROLLABLE:TaskLandAtVec2(Vec2, Duration)
self:F2( { self.ControllableName, Point, Duration } )
-- Land = { local DCSTask = {
-- id= 'Land', id = 'Land',
-- params = { params = {
-- point = Vec2, point = Vec2,
-- durationFlag = boolean, durationFlag = Duration and true or false,
-- duration = Time duration = Duration,
-- } },
-- } }
local DCSTask
if Duration and Duration > 0 then
DCSTask = { id = 'Land',
params = {
point = Point,
durationFlag = true,
duration = Duration,
},
}
else
DCSTask = { id = 'Land',
params = {
point = Point,
durationFlag = false,
},
}
end
self:T3( DCSTask )
return DCSTask return DCSTask
end end
@ -1307,14 +1316,13 @@ function CONTROLLABLE:TaskFollow( FollowControllable, Vec3, LastWaypointIndex )
lastWptIndexFlagChangedManually = true lastWptIndexFlagChangedManually = true
end end
local DCSTask local DCSTask = {
DCSTask = {
id = 'Follow', id = 'Follow',
params = { params = {
groupId = FollowControllable:GetID(), groupId = FollowControllable:GetID(),
pos = Vec3, pos = Vec3,
lastWptIndexFlag = LastWaypointIndexFlag, lastWptIndexFlag = LastWaypointIndexFlag,
lastWptIndex = LastWaypointIndex, lastWptIndex = LastWaypointIndex,
lastWptIndexFlagChangedManually = lastWptIndexFlagChangedManually, lastWptIndexFlagChangedManually = lastWptIndexFlagChangedManually,
} }
} }
@ -1332,7 +1340,7 @@ end
-- @param DCS#Vec3 Vec3 Position of the unit / lead unit of the controllable relative lead unit of another controllable in frame reference oriented by course of lead unit of another controllable. If another controllable is on land the unit / controllable will orbit around. -- @param DCS#Vec3 Vec3 Position of the unit / lead unit of the controllable relative lead unit of another controllable in frame reference oriented by course of lead unit of another controllable. If another controllable is on land the unit / controllable will orbit around.
-- @param #number LastWaypointIndex Detach waypoint of another controllable. Once reached the unit / controllable Follow task is finished. -- @param #number LastWaypointIndex Detach waypoint of another controllable. Once reached the unit / controllable Follow task is finished.
-- @param #number EngagementDistance Maximal distance from escorted controllable to threat. If the threat is already engaged by escort escort will disengage if the distance becomes greater than 1.5 * engagementDistMax. -- @param #number EngagementDistance Maximal distance from escorted controllable to threat. If the threat is already engaged by escort escort will disengage if the distance becomes greater than 1.5 * engagementDistMax.
-- @param DCS#AttributeNameArray TargetTypes Array of AttributeName that is contains threat categories allowed to engage. -- @param DCS#AttributeNameArray TargetTypes Array of AttributeName that is contains threat categories allowed to engage. Default {"Air"}.
-- @return DCS#Task The DCS task structure. -- @return DCS#Task The DCS task structure.
function CONTROLLABLE:TaskEscort( FollowControllable, Vec3, LastWaypointIndex, EngagementDistance, TargetTypes ) function CONTROLLABLE:TaskEscort( FollowControllable, Vec3, LastWaypointIndex, EngagementDistance, TargetTypes )
self:F2( { self.ControllableName, FollowControllable, Vec3, LastWaypointIndex, EngagementDistance, TargetTypes } ) self:F2( { self.ControllableName, FollowControllable, Vec3, LastWaypointIndex, EngagementDistance, TargetTypes } )
@ -1349,22 +1357,16 @@ function CONTROLLABLE:TaskEscort( FollowControllable, Vec3, LastWaypointIndex, E
-- } -- }
-- } -- }
local LastWaypointIndexFlag = false
if LastWaypointIndex then
LastWaypointIndexFlag = true
end
TargetTypes=TargetTypes or {}
local DCSTask local DCSTask
DCSTask = { id = 'Escort', DCSTask = {
id = 'Escort',
params = { params = {
groupId = FollowControllable:GetID(), groupId = FollowControllable:GetID(),
pos = Vec3, pos = Vec3,
lastWptIndexFlag = LastWaypointIndexFlag, lastWptIndexFlag = LastWaypointIndex and true or false,
lastWptIndex = LastWaypointIndex, lastWptIndex = LastWaypointIndex,
engagementDistMax = EngagementDistance, engagementDistMax = EngagementDistance,
targetTypes = TargetTypes, targetTypes = TargetTypes or {"Air"},
}, },
}, },
@ -1423,21 +1425,7 @@ end
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @return DCS#Task The DCS task structure. -- @return DCS#Task The DCS task structure.
function CONTROLLABLE:TaskHold() function CONTROLLABLE:TaskHold()
self:F2( { self.ControllableName } ) local DCSTask = {id = 'Hold', params = {}}
-- Hold = {
-- id = 'Hold',
-- params = {
-- }
-- }
local DCSTask
DCSTask = { id = 'Hold',
params = {
}
}
self:T3( { DCSTask } )
return DCSTask return DCSTask
end end
@ -1456,23 +1444,13 @@ end
function CONTROLLABLE:TaskFAC_AttackGroup( AttackGroup, WeaponType, Designation, Datalink ) function CONTROLLABLE:TaskFAC_AttackGroup( AttackGroup, WeaponType, Designation, Datalink )
self:F2( { self.ControllableName, AttackGroup, WeaponType, Designation, Datalink } ) self:F2( { self.ControllableName, AttackGroup, WeaponType, Designation, Datalink } )
-- FAC_AttackGroup = { local DCSTask = {
-- id = 'FAC_AttackGroup', id = 'FAC_AttackGroup',
-- params = {
-- groupId = Group.ID,
-- weaponType = number,
-- designation = enum AI.Task.Designation,
-- datalink = boolean
-- }
-- }
local DCSTask
DCSTask = { id = 'FAC_AttackGroup',
params = { params = {
groupId = AttackGroup:GetID(), groupId = AttackGroup:GetID(),
weaponType = WeaponType, weaponType = WeaponType,
designation = Designation, designation = Designation,
datalink = Datalink, datalink = Datalink,
} }
} }
@ -1486,26 +1464,18 @@ end
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @param DCS#Distance Distance Maximal distance from the target to a route leg. If the target is on a greater distance it will be ignored. -- @param DCS#Distance Distance Maximal distance from the target to a route leg. If the target is on a greater distance it will be ignored.
-- @param DCS#AttributeNameArray TargetTypes Array of target categories allowed to engage. -- @param DCS#AttributeNameArray TargetTypes Array of target categories allowed to engage.
-- @param #number Priority All enroute tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. -- @param #number Priority All enroute tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. Default 0.
-- @return DCS#Task The DCS task structure. -- @return DCS#Task The DCS task structure.
function CONTROLLABLE:EnRouteTaskEngageTargets( Distance, TargetTypes, Priority ) function CONTROLLABLE:EnRouteTaskEngageTargets( Distance, TargetTypes, Priority )
self:F2( { self.ControllableName, Distance, TargetTypes, Priority } ) self:F2( { self.ControllableName, Distance, TargetTypes, Priority } )
-- EngageTargets ={ local DCSTask = {
-- id = 'EngageTargets', id = 'EngageTargets',
-- params = {
-- maxDist = Distance,
-- targetTypes = array of AttributeName,
-- priority = number
-- }
-- }
local DCSTask
DCSTask = { id = 'EngageTargets',
params = { params = {
maxDist = Distance, maxDistEnabled = Distance and true or false,
targetTypes = TargetTypes, maxDist = Distance,
priority = Priority targetTypes = TargetTypes or {"Air"},
priority = Priority or 0,
} }
} }
@ -1519,29 +1489,19 @@ end
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @param DCS#Vec2 Vec2 2D-coordinates of the zone. -- @param DCS#Vec2 Vec2 2D-coordinates of the zone.
-- @param DCS#Distance Radius Radius of the zone. -- @param DCS#Distance Radius Radius of the zone.
-- @param DCS#AttributeNameArray TargetTypes Array of target categories allowed to engage. -- @param DCS#AttributeNameArray (Optional) TargetTypes Array of target categories allowed to engage. Default {"Air"}.
-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. -- @param #number Priority (Optional) All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. Default 0.
-- @return DCS#Task The DCS task structure. -- @return DCS#Task The DCS task structure.
function CONTROLLABLE:EnRouteTaskEngageTargetsInZone( Vec2, Radius, TargetTypes, Priority ) function CONTROLLABLE:EnRouteTaskEngageTargetsInZone( Vec2, Radius, TargetTypes, Priority )
self:F2( { self.ControllableName, Vec2, Radius, TargetTypes, Priority } ) self:F2( { self.ControllableName, Vec2, Radius, TargetTypes, Priority } )
-- EngageTargetsInZone = { local DCSTask = {
-- id = 'EngageTargetsInZone', id = 'EngageTargetsInZone',
-- params = {
-- point = Vec2,
-- zoneRadius = Distance,
-- targetTypes = array of AttributeName,
-- priority = number
-- }
-- }
local DCSTask
DCSTask = { id = 'EngageTargetsInZone',
params = { params = {
point = Vec2, point = Vec2,
zoneRadius = Radius, zoneRadius = Radius,
targetTypes = TargetTypes, targetTypes = TargetTypes or {"Air"},
priority = Priority priority = Priority or 0
} }
} }
@ -1580,29 +1540,19 @@ function CONTROLLABLE:EnRouteTaskEngageGroup( AttackGroup, Priority, WeaponType,
-- } -- }
-- } -- }
local DirectionEnabled = nil local DCSTask = {
if Direction then id = 'EngageControllable',
DirectionEnabled = true
end
local AltitudeEnabled = nil
if Altitude then
AltitudeEnabled = true
end
local DCSTask
DCSTask = { id = 'EngageControllable',
params = { params = {
groupId = AttackGroup:GetID(), groupId = AttackGroup:GetID(),
weaponType = WeaponType, weaponType = WeaponType,
expend = WeaponExpend, expend = WeaponExpend or "Auto",
attackQty = AttackQty, directionEnabled = Direction and true or false,
directionEnabled = DirectionEnabled, direction = Direction,
direction = Direction, altitudeEnabled = Altitude and true or false,
altitudeEnabled = AltitudeEnabled, altitude = Altitude,
altitude = Altitude, attackQtyLimit = AttackQty and true or false,
attackQtyLimit = AttackQtyLimit, attackQty = AttackQty,
priority = Priority, priority = Priority or 1,
}, },
}, },
@ -1624,36 +1574,22 @@ end
-- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft. -- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft.
-- @return DCS#Task The DCS task structure. -- @return DCS#Task The DCS task structure.
function CONTROLLABLE:EnRouteTaskEngageUnit( EngageUnit, Priority, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, Visible, ControllableAttack ) function CONTROLLABLE:EnRouteTaskEngageUnit( EngageUnit, Priority, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, Visible, ControllableAttack )
self:F2( { self.ControllableName, EngageUnit, Priority, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, Visible, ControllableAttack } ) self:F2( { self.ControllableName, EngageUnit, Priority, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, Visible, ControllableAttack } )
-- EngageUnit = { local DCSTask = {
-- id = 'EngageUnit', id = 'EngageUnit',
-- params = {
-- unitId = Unit.ID,
-- weaponType = number,
-- expend = enum AI.Task.WeaponExpend
-- attackQty = number,
-- direction = Azimuth,
-- attackQtyLimit = boolean,
-- controllableAttack = boolean,
-- priority = number,
-- }
-- }
local DCSTask
DCSTask = { id = 'EngageUnit',
params = { params = {
unitId = EngageUnit:GetID(), unitId = EngageUnit:GetID(),
priority = Priority or 1, priority = Priority or 1,
groupAttack = GroupAttack or false, groupAttack = GroupAttack and GroupAttack or false,
visible = Visible or false, visible = Visible and Visible or false,
expend = WeaponExpend or "Auto", expend = WeaponExpend or "Auto",
directionEnabled = Direction and true or false, directionEnabled = Direction and true or false,
direction = Direction, direction = Direction and math.rad(Direction) or nil,
altitudeEnabled = Altitude and true or false, altitudeEnabled = Altitude and true or false,
altitude = Altitude, altitude = Altitude,
attackQtyLimit = AttackQty and true or false, attackQtyLimit = AttackQty and true or false,
attackQty = AttackQty, attackQty = AttackQty,
controllableAttack = ControllableAttack, controllableAttack = ControllableAttack,
}, },
}, },
@ -1670,17 +1606,7 @@ end
function CONTROLLABLE:EnRouteTaskAWACS( ) function CONTROLLABLE:EnRouteTaskAWACS( )
self:F2( { self.ControllableName } ) self:F2( { self.ControllableName } )
-- AWACS = { local DCSTask = {id = 'AWACS', params = {}}
-- id = 'AWACS',
-- params = {
-- }
-- }
local DCSTask
DCSTask = { id = 'AWACS',
params = {
}
}
self:T3( { DCSTask } ) self:T3( { DCSTask } )
return DCSTask return DCSTask
@ -1693,17 +1619,7 @@ end
function CONTROLLABLE:EnRouteTaskTanker( ) function CONTROLLABLE:EnRouteTaskTanker( )
self:F2( { self.ControllableName } ) self:F2( { self.ControllableName } )
-- Tanker = { local DCSTask = {id = 'Tanker', params = {}}
-- id = 'Tanker',
-- params = {
-- }
-- }
local DCSTask
DCSTask = { id = 'Tanker',
params = {
}
}
self:T3( { DCSTask } ) self:T3( { DCSTask } )
return DCSTask return DCSTask
@ -1718,17 +1634,7 @@ end
function CONTROLLABLE:EnRouteTaskEWR( ) function CONTROLLABLE:EnRouteTaskEWR( )
self:F2( { self.ControllableName } ) self:F2( { self.ControllableName } )
-- EWR = { local DCSTask = {id = 'EWR', params = {}}
-- id = 'EWR',
-- params = {
-- }
-- }
local DCSTask
DCSTask = { id = 'EWR',
params = {
}
}
self:T3( { DCSTask } ) self:T3( { DCSTask } )
return DCSTask return DCSTask
@ -1742,33 +1648,22 @@ end
-- If the task is assigned to the controllable lead unit will be a FAC. -- If the task is assigned to the controllable lead unit will be a FAC.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @param Wrapper.Controllable#CONTROLLABLE AttackGroup Target CONTROLLABLE. -- @param Wrapper.Controllable#CONTROLLABLE AttackGroup Target CONTROLLABLE.
-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. -- @param #number Priority (Optional) All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. Default is 0.
-- @param #number WeaponType Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. -- @param #number WeaponType (Optional) Bitmask of weapon types those allowed to use. Default is "Auto".
-- @param DCS#AI.Task.Designation Designation (optional) Designation type. -- @param DCS#AI.Task.Designation Designation (Optional) Designation type.
-- @param #boolean Datalink (optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default. -- @param #boolean Datalink (optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default.
-- @return DCS#Task The DCS task structure. -- @return DCS#Task The DCS task structure.
function CONTROLLABLE:EnRouteTaskFAC_EngageGroup( AttackGroup, Priority, WeaponType, Designation, Datalink ) function CONTROLLABLE:EnRouteTaskFAC_EngageGroup( AttackGroup, Priority, WeaponType, Designation, Datalink )
self:F2( { self.ControllableName, AttackGroup, WeaponType, Priority, Designation, Datalink } ) self:F2( { self.ControllableName, AttackGroup, WeaponType, Priority, Designation, Datalink } )
-- FAC_EngageControllable = { local DCSTask = {
-- id = 'FAC_EngageControllable', id = 'FAC_EngageControllable',
-- params = {
-- groupId = Group.ID,
-- weaponType = number,
-- designation = enum AI.Task.Designation,
-- datalink = boolean,
-- priority = number,
-- }
-- }
local DCSTask
DCSTask = { id = 'FAC_EngageControllable',
params = { params = {
groupId = AttackGroup:GetID(), groupId = AttackGroup:GetID(),
weaponType = WeaponType, weaponType = WeaponType or "Auto",
designation = Designation, designation = Designation,
datalink = Datalink, datalink = Datalink and Datalink or false,
priority = Priority, priority = Priority or 0,
} }
} }
@ -1939,9 +1834,12 @@ function CONTROLLABLE:TaskEmbarkToTransport( Point, Radius )
self:F2( { self.ControllableName, Point, Radius } ) self:F2( { self.ControllableName, Point, Radius } )
local DCSTask --DCS#Task local DCSTask --DCS#Task
DCSTask = { id = 'EmbarkToTransport', DCSTask = {
params = { x = Point.x, id = 'EmbarkToTransport',
y = Point.y, params = {
point = Point,
x = Point.x,
y = Point.y,
zoneRadius = Radius, zoneRadius = Radius,
} }
} }
@ -2193,8 +2091,13 @@ end
function CONTROLLABLE:TaskRoute( Points ) function CONTROLLABLE:TaskRoute( Points )
self:F2( Points ) self:F2( Points )
local DCSTask local DCSTask = {
DCSTask = { id = 'Mission', params = { route = { points = Points, }, }, } id = 'Mission',
params = {
airborne = self:IsAir(),
route = {points = Points},
},
}
self:T3( { DCSTask } ) self:T3( { DCSTask } )
return DCSTask return DCSTask

View File

@ -173,6 +173,62 @@ GROUPTEMPLATE.Takeoff = {
[GROUP.Takeoff.Cold] = { "TakeOffParking", "From Parking Area" } [GROUP.Takeoff.Cold] = { "TakeOffParking", "From Parking Area" }
} }
--- Generalized group attributes. See [DCS attributes](https://wiki.hoggitworld.com/view/DCS_enum_attributes) on hoggit.
-- @type GROUP.Attribute
-- @field #string AIR_TRANSPORTPLANE Airplane with transport capability. This can be used to transport other assets.
-- @field #string AIR_AWACS Airborne Early Warning and Control System.
-- @field #string AIR_FIGHTER Fighter, interceptor, ... airplane.
-- @field #string AIR_BOMBER Aircraft which can be used for strategic bombing.
-- @field #string AIR_TANKER Airplane which can refuel other aircraft.
-- @field #string AIR_TRANSPORTHELO Helicopter with transport capability. This can be used to transport other assets.
-- @field #string AIR_ATTACKHELO Attack helicopter.
-- @field #string AIR_UAV Unpiloted Aerial Vehicle, e.g. drones.
-- @field #string AIR_OTHER Any airborne unit that does not fall into any other airborne category.
-- @field #string GROUND_APC Infantry carriers, in particular Amoured Personell Carrier. This can be used to transport other assets.
-- @field #string GROUND_TRUCK Unarmed ground vehicles, which has the DCS "Truck" attribute.
-- @field #string GROUND_INFANTRY Ground infantry assets.
-- @field #string GROUND_ARTILLERY Artillery assets.
-- @field #string GROUND_TANK Tanks (modern or old).
-- @field #string GROUND_TRAIN Trains. Not that trains are **not** yet properly implemented in DCS and cannot be used currently.
-- @field #string GROUND_EWR Early Warning Radar.
-- @field #string GROUND_AAA Anti-Aircraft Artillery.
-- @field #string GROUND_SAM Surface-to-Air Missile system or components.
-- @field #string GROUND_OTHER Any ground unit that does not fall into any other ground category.
-- @field #string NAVAL_AIRCRAFTCARRIER Aircraft carrier.
-- @field #string NAVAL_WARSHIP War ship, i.e. cruisers, destroyers, firgates and corvettes.
-- @field #string NAVAL_ARMEDSHIP Any armed ship that is not an aircraft carrier, a cruiser, destroyer, firgatte or corvette.
-- @field #string NAVAL_UNARMEDSHIP Any unarmed naval vessel.
-- @field #string NAVAL_OTHER Any naval unit that does not fall into any other naval category.
-- @field #string OTHER_UNKNOWN Anything that does not fall into any other category.
GROUP.Attribute = {
AIR_TRANSPORTPLANE="Air_TransportPlane",
AIR_AWACS="Air_AWACS",
AIR_FIGHTER="Air_Fighter",
AIR_BOMBER="Air_Bomber",
AIR_TANKER="Air_Tanker",
AIR_TRANSPORTHELO="Air_TransportHelo",
AIR_ATTACKHELO="Air_AttackHelo",
AIR_UAV="Air_UAV",
AIR_OTHER="Air_OtherAir",
GROUND_APC="Ground_APC",
GROUND_TRUCK="Ground_Truck",
GROUND_INFANTRY="Ground_Infantry",
GROUND_ARTILLERY="Ground_Artillery",
GROUND_TANK="Ground_Tank",
GROUND_TRAIN="Ground_Train",
GROUND_EWR="Ground_EWR",
GROUND_AAA="Ground_AAA",
GROUND_SAM="Ground_SAM",
GROUND_OTHER="Ground_OtherGround",
NAVAL_AIRCRAFTCARRIER="Naval_AircraftCarrier",
NAVAL_WARSHIP="Naval_WarShip",
NAVAL_ARMEDSHIP="Naval_ArmedShip",
NAVAL_UNARMEDSHIP="Naval_UnarmedShip",
NAVAL_OTHER="Naval_OtherNaval",
OTHER_UNKNOWN="Other_Unknown",
}
--- Create a new GROUP from a given GroupTemplate as a parameter. --- Create a new GROUP from a given GroupTemplate as a parameter.
-- Note that the GroupTemplate is NOT spawned into the mission. -- Note that the GroupTemplate is NOT spawned into the mission.
-- It is merely added to the @{Core.Database}. -- It is merely added to the @{Core.Database}.
@ -810,7 +866,7 @@ end
function GROUP:Activate() function GROUP:Activate()
self:F2( { self.GroupName } ) self:F2( { self.GroupName } )
trigger.action.activateGroup( self:GetDCSObject() ) trigger.action.activateGroup( self:GetDCSObject() )
return self:GetDCSObject() return self
end end
@ -1678,7 +1734,7 @@ function GROUP:Respawn( Template, Reset )
self:F(GroupUnit:GetName()) self:F(GroupUnit:GetName())
if GroupUnit:IsAlive() then if GroupUnit:IsAlive() then
self:F("Alive") self:I("FF Alive")
-- Get unit position vector. -- Get unit position vector.
local GroupUnitVec3 = GroupUnit:GetVec3() local GroupUnitVec3 = GroupUnit:GetVec3()
@ -1722,7 +1778,7 @@ function GROUP:Respawn( Template, Reset )
end end
end end
else -- Reset=false or nil elseif Reset==false then -- Reset=false or nil
-- Loop over template units. -- Loop over template units.
for UnitID, TemplateUnitData in pairs( Template.units ) do for UnitID, TemplateUnitData in pairs( Template.units ) do
@ -1764,6 +1820,29 @@ function GROUP:Respawn( Template, Reset )
self:F( { UnitID, Template.units[UnitID], Template.units[UnitID] } ) self:F( { UnitID, Template.units[UnitID], Template.units[UnitID] } )
end end
else
local units=self:GetUnits()
-- Loop over template units.
for UnitID, Unit in pairs(Template.units) do
for _,_unit in pairs(units) do
local unit=_unit --Wrapper.Unit#UNIT
if unit:GetName()==Unit.name then
local coord=unit:GetCoordinate()
local heading=unit:GetHeading()
Unit.x=coord.x
Unit.y=coord.z
Unit.alt=coord.y
Unit.heading=math.rad(heading)
Unit.psi=-Unit.heading
end
end
end
end end
end end
@ -2091,6 +2170,117 @@ function GROUP:GetDCSDesc(n)
return nil return nil
end end
--- Get the generalized attribute of a self.
-- Note that for a heterogenious self, the attribute is determined from the attribute of the first unit!
-- @param #GROUP self
-- @return #string Generalized attribute of the self.
function GROUP:GetAttribute()
-- Default
local attribute=GROUP.Attribute.OTHER_UNKNOWN --#GROUP.Attribute
if self then
-----------
--- Air ---
-----------
-- Planes
local transportplane=self:HasAttribute("Transports") and self:HasAttribute("Planes")
local awacs=self:HasAttribute("AWACS")
local fighter=self:HasAttribute("Fighters") or self:HasAttribute("Interceptors") or self:HasAttribute("Multirole fighters") or (self:HasAttribute("Bombers") and not self:HasAttribute("Strategic bombers"))
local bomber=self:HasAttribute("Strategic bombers")
local tanker=self:HasAttribute("Tankers")
local uav=self:HasAttribute("UAVs")
-- Helicopters
local transporthelo=self:HasAttribute("Transport helicopters")
local attackhelicopter=self:HasAttribute("Attack helicopters")
--------------
--- Ground ---
--------------
-- Ground
local apc=self:HasAttribute("Infantry carriers")
local truck=self:HasAttribute("Trucks") and self:GetCategory()==Group.Category.GROUND
local infantry=self:HasAttribute("Infantry")
local artillery=self:HasAttribute("Artillery")
local tank=self:HasAttribute("Old Tanks") or self:HasAttribute("Modern Tanks")
local aaa=self:HasAttribute("AAA")
local ewr=self:HasAttribute("EWR")
local sam=self:HasAttribute("SAM elements") and (not self:HasAttribute("AAA"))
-- Train
local train=self:GetCategory()==Group.Category.TRAIN
-------------
--- Naval ---
-------------
-- Ships
local aircraftcarrier=self:HasAttribute("Aircraft Carriers")
local warship=self:HasAttribute("Heavy armed ships")
local armedship=self:HasAttribute("Armed ships")
local unarmedship=self:HasAttribute("Unarmed ships")
-- Define attribute. Order is important.
if transportplane then
attribute=GROUP.Attribute.AIR_TRANSPORTPLANE
elseif awacs then
attribute=GROUP.Attribute.AIR_AWACS
elseif fighter then
attribute=GROUP.Attribute.AIR_FIGHTER
elseif bomber then
attribute=GROUP.Attribute.AIR_BOMBER
elseif tanker then
attribute=GROUP.Attribute.AIR_TANKER
elseif transporthelo then
attribute=GROUP.Attribute.AIR_TRANSPORTHELO
elseif attackhelicopter then
attribute=GROUP.Attribute.AIR_ATTACKHELO
elseif uav then
attribute=GROUP.Attribute.AIR_UAV
elseif apc then
attribute=GROUP.Attribute.GROUND_APC
elseif infantry then
attribute=GROUP.Attribute.GROUND_INFANTRY
elseif artillery then
attribute=GROUP.Attribute.GROUND_ARTILLERY
elseif tank then
attribute=GROUP.Attribute.GROUND_TANK
elseif aaa then
attribute=GROUP.Attribute.GROUND_AAA
elseif ewr then
attribute=GROUP.Attribute.GROUND_EWR
elseif sam then
attribute=GROUP.Attribute.GROUND_SAM
elseif truck then
attribute=GROUP.Attribute.GROUND_TRUCK
elseif train then
attribute=GROUP.Attribute.GROUND_TRAIN
elseif aircraftcarrier then
attribute=GROUP.Attribute.NAVAL_AIRCRAFTCARRIER
elseif warship then
attribute=GROUP.Attribute.NAVAL_WARSHIP
elseif armedship then
attribute=GROUP.Attribute.NAVAL_ARMEDSHIP
elseif unarmedship then
attribute=GROUP.Attribute.NAVAL_UNARMEDSHIP
else
if self:IsGround() then
attribute=GROUP.Attribute.GROUND_OTHER
elseif self:IsShip() then
attribute=GROUP.Attribute.NAVAL_OTHER
elseif self:IsAir() then
attribute=GROUP.Attribute.AIR_OTHER
else
attribute=GROUP.Attribute.OTHER_UNKNOWN
end
end
end
return attribute
end
do -- Route methods do -- Route methods
--- (AIR) Return the Group to an @{Wrapper.Airbase#AIRBASE}. --- (AIR) Return the Group to an @{Wrapper.Airbase#AIRBASE}.

View File

@ -31,6 +31,11 @@ SCENERY = {
} }
--- Register scenery object as POSITIONABLE.
--@param #SCENERY self
--@param #string SceneryName Scenery name.
--@param #DCS.Object SceneryObject DCS scenery object.
--@return #SCENERY Scenery object.
function SCENERY:Register( SceneryName, SceneryObject ) function SCENERY:Register( SceneryName, SceneryObject )
local self = BASE:Inherit( self, POSITIONABLE:New( SceneryName ) ) local self = BASE:Inherit( self, POSITIONABLE:New( SceneryName ) )
self.SceneryName = SceneryName self.SceneryName = SceneryName
@ -38,11 +43,17 @@ function SCENERY:Register( SceneryName, SceneryObject )
return self return self
end end
--- Register scenery object as POSITIONABLE.
--@param #SCENERY self
--@return #DCS.Object DCS scenery object.
function SCENERY:GetDCSObject() function SCENERY:GetDCSObject()
return self.SceneryObject return self.SceneryObject
end end
--- Register scenery object as POSITIONABLE.
--@param #SCENERY self
--@return #number Threat level 0.
--@return #string "Scenery".
function SCENERY:GetThreatLevel() function SCENERY:GetThreatLevel()
return 0, "Scenery" return 0, "Scenery"
end end

View File

@ -478,8 +478,7 @@ end
--- Returns the Unit's ammunition. --- Returns the Unit's ammunition.
-- @param #UNIT self -- @param #UNIT self
-- @return DCS#Unit.Ammo -- @return DCS#Unit.Ammo Table with ammuntion of the unit (or nil). This can be a complex table!
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetAmmo() function UNIT:GetAmmo()
self:F2( self.UnitName ) self:F2( self.UnitName )
@ -664,8 +663,7 @@ end
--- Returns relative amount of fuel (from 0.0 to 1.0) the UNIT has in its internal tanks. If there are additional fuel tanks the value may be greater than 1.0. --- Returns relative amount of fuel (from 0.0 to 1.0) the UNIT has in its internal tanks. If there are additional fuel tanks the value may be greater than 1.0.
-- @param #UNIT self -- @param #UNIT self
-- @return #number The relative amount of fuel (from 0.0 to 1.0). -- @return #number The relative amount of fuel (from 0.0 to 1.0) or *nil* if the DCS Unit is not existing or alive.
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetFuel() function UNIT:GetFuel()
self:F3( self.UnitName ) self:F3( self.UnitName )
@ -1207,3 +1205,80 @@ do -- Detection
end end
end end
--- Get the unit table from a unit's template.
-- @param #UNIT self
-- @return #table Table of the unit template (deep copy) or #nil.
function UNIT:GetTemplate()
local group=self:GetGroup()
local name=self:GetName()
if group then
local template=group:GetTemplate()
if template then
for _,unit in pairs(template.units) do
if unit.name==name then
return UTILS.DeepCopy(unit)
end
end
end
end
return nil
end
--- Get the payload table from a unit's template.
-- The payload table has elements:
--
-- * pylons
-- * fuel
-- * chaff
-- * gun
--
-- @param #UNIT self
-- @return #table Payload table (deep copy) or #nil.
function UNIT:GetTemplatePayload()
local unit=self:GetTemplate()
if unit then
return unit.payload
end
return nil
end
--- Get the pylons table from a unit's template. This can be a complex table depending on the weapons the unit is carrying.
-- @param #UNIT self
-- @return #table Table of pylons (deepcopy) or #nil.
function UNIT:GetTemplatePylons()
local payload=self:GetTemplatePayload()
if payload then
return payload.pylons
end
return nil
end
--- Get the fuel of the unit from its template.
-- @param #UNIT self
-- @return #number Fuel of unit in kg.
function UNIT:GetTemplateFuel()
local payload=self:GetTemplatePayload()
if payload then
return payload.fuel
end
return nil
end