Compare commits

..

50 Commits

Author SHA1 Message Date
Applevangelist
8099847e29 Fixes for DEAD event and extra nil checks 2022-05-04 10:25:50 +02:00
Applevangelist
6e8edd95ec GROUP - making GetCoordinate() a bit more resilient
POINT - slight changes to ToStringBRAANATO
2022-04-29 18:48:41 +02:00
Applevangelist
5112c9598b COORDINATE - added bogey option to COORDINATE:ToStringBRAANATO(FromCoordinate,Bogey,Spades) 2022-04-29 12:18:26 +02:00
Applevangelist
749158c086 Range added nil check 2022-04-29 12:09:57 +02:00
Applevangelist
b3d4024f21 Nicefy docs 2022-04-28 17:10:26 +02:00
Applevangelist
c283b66c1d added MESSAGE:ToUnit), altered MESSAGE:ToClient() accordingly 2022-04-28 16:58:37 +02:00
Applevangelist
3209843318 Added POSITIONABLE:MessageToSetUnit and POSITIONABLE:MessageToUnit 2022-04-28 16:55:31 +02:00
Applevangelist
d35e5cc0f7 Added USERSOUND:ToUnit 2022-04-28 16:50:59 +02:00
Applevangelist
e5eeb592a2 Enums - corrected Hawkeye, added Super_Hercules 2022-04-28 13:10:34 +02:00
Applevangelist
3d38f4d17a Enums - added a couple of names 2022-04-26 10:08:50 +02:00
Applevangelist
2d91647e0b QOL changes from DEVELOP 2022-04-25 10:36:36 +02:00
Applevangelist
cac0f30673 Update Moose.files (#1717) 2022-04-25 10:35:38 +02:00
Applevangelist
c5ecba3389 Menu cleanup for Refresh() 2022-04-24 14:05:45 +02:00
Applevangelist
e0397dff47 GROUP - overwrite GetHeight() inherited from POSITIONABLE with something that is actually working for groups 2022-04-24 13:50:07 +02:00
Applevangelist
e08fb2e972 Make BRAA heading a 3digit number 2022-04-22 13:31:58 +02:00
Applevangelist
c02ae82003 Point - added ToStringBRAANATO 2022-04-21 18:59:31 +02:00
Applevangelist
e6fc301b0d Utils Typo 2022-04-20 19:14:36 +02:00
Applevangelist
a385ed57fb ZONE - added example to Scan, some minor changes
SET_GROUP - clarified return value to be a table, not a SET
2022-04-20 14:03:18 +02:00
Applevangelist
09dafe4b1d UTILS - added BearingToCardinal, ToStringBRAANATO 2022-04-20 14:02:16 +02:00
Applevangelist
ba8505c983 FIFO 2022-04-14 15:54:38 +02:00
Applevangelist
fba359d389 LIFO/FIFO enforce unique id 2022-04-14 15:06:14 +02:00
Applevangelist
c56763b68f FIFO:HasUniqueID(UniqueID) 2022-04-14 11:11:33 +02:00
Applevangelist
03c2943545 Nicefy docs 2022-04-14 08:53:37 +02:00
Applevangelist
98039b9048 UTISL - FiFo/LiFo stacks 2022-04-14 08:12:29 +02:00
Applevangelist
5065d3b068 UTILS - added FiFo
CTLD - correct imperial hover check messages
2022-04-13 16:13:39 +02:00
Applevangelist
6828f7e262 UTILS - corrected door check for AH64 2022-04-12 08:23:18 +02:00
Applevangelist
a685f3ffbd MSRS - honor port setting and coalition. Repaired command string for .bat sound file production
Added mission slash in SOUNDFILE
2022-04-10 18:29:09 +02:00
Applevangelist
e84156d2e9 SRS - add port to docu 2022-04-10 10:18:12 +02:00
Applevangelist
0ce1c31e1c CSAR - added SRS port option 2022-04-10 09:29:22 +02:00
Applevangelist
f7e14bb60c SET - logic correction in :Remove() 2022-04-08 11:27:31 +02:00
Penecruz
7b907df816 Airboss V/STOL Case III and grading (#1708)
* Update Airboss.lua

* Fix syntax error

C
2022-04-08 07:16:23 +02:00
Frank
7f5be2829c Update Database.lua
- Template statics saved under first statics unit name so they can be found.
2022-04-04 16:50:17 +02:00
Applevangelist
fa5afae783 A2A Dispatcher - nil checks to evade dead units 2022-04-04 12:58:32 +02:00
Frank
b17507d0fa Update SpawnStatic.lua
- Fixed isCargo flag not honored.
2022-04-04 12:18:45 +02:00
Applevangelist
5ed43a3190 CTLD - build object at the 1st crate location not randomly around helo 2022-04-04 11:31:35 +02:00
Applevangelist
d2a5144a23 AIRBASE, added ["Deir_ez-Zor"] = "Deir ez-Zor", 2022-03-30 12:06:25 +02:00
Applevangelist
fb2031d7ca docu nicefy 2022-03-29 12:01:28 +02:00
Applevangelist
4a42571925 CTLD - corrected error in setting Hercules min and max drop height, added documentation 2022-03-29 08:52:33 +02:00
Applevangelist
38413625c2 AIRBASE - Add'l AB for the Channels map 2022-03-28 10:12:39 +02:00
Frank
2d544b7a98 Merge pull request #1698 from gavinedwards/airboss.hermes.include
Added Hermes section to Airboss.  Will require tuning.
2022-03-26 23:34:54 +01:00
Lt Cdr Gavin Edwards
b1e5e1840e Adding leading lines that I accidentally truncated. 2022-03-26 15:23:38 -07:00
Lt Cdr Gavin Edwards
e6f9b4a125 Added Hermes section to Airboss. Will require tuning. 2022-03-26 11:54:53 -07:00
Applevangelist
5260b2b430 And don't forget Fahrenheit 2022-03-26 14:46:52 +01:00
Applevangelist
0213bc7aef Correcting Celcius to Celsius 2022-03-26 14:43:06 +01:00
Applevangelist
ca8b0899d0 docu changes 2022-03-23 07:56:52 +01:00
Applevangelist
a1f5c0ab9b CSAR/CTLD - added type to script 2022-03-22 10:38:20 +01:00
Applevangelist
b0e3f82d27 AIRBASE - added 10 new AB names in Syria 2022-03-18 09:48:50 +01:00
Applevangelist
327ab4766b changed descriptions 2022-03-18 07:59:58 +01:00
Applevangelist
3aee8a49c1 Added CONTROLLABLE SetSpeed() and SetAltitude() 2022-03-18 07:39:48 +01:00
Applevangelist
57de0b7351 docu fixes 2022-03-16 08:45:27 +01:00
32 changed files with 3866 additions and 2081 deletions

10
.vs/VSWorkspaceState.json Normal file
View File

@@ -0,0 +1,10 @@
{
"ExpandedNodes": [
"",
"\\Moose Development",
"\\Moose Development\\Moose",
"\\Moose Development\\Moose\\Ops"
],
"SelectedNode": "\\Moose Development\\Moose\\Ops\\Airboss.lua",
"PreviewInSolutionExplorer": false
}

BIN
.vs/slnx.sqlite Normal file

Binary file not shown.

View File

@@ -2971,7 +2971,20 @@ do -- AI_A2A_DISPATCHER
for FriendlyDistance, AIFriendly in UTILS.spairs( DefenderFriendlies or {} ) do
-- We only allow to ENGAGE targets as long as the Units on both sides are balanced.
if AttackerCount > DefenderCount then
local Friendly = AIFriendly:GetGroup() -- Wrapper.Group#GROUP
--self:I("***** AI_A2A_DISPATCHER:CountDefendersToBeEngaged() *****\nThis is supposed to be a UNIT:")
if AIFriendly then
local classname = AIFriendly.ClassName or "No Class Name"
local unitname = AIFriendly.IdentifiableName or "No Unit Name"
--self:I("Class Name: " .. classname)
--self:I("Unit Name: " .. unitname)
--self:I({AIFriendly})
end
local Friendly = nil
if AIFriendly and AIFriendly:IsAlive() then
--self:I("AIFriendly alive, getting GROUP")
Friendly = AIFriendly:GetGroup() -- Wrapper.Group#GROUP
end
if Friendly and Friendly:IsAlive() then
-- Ok, so we have a friendly near the potential target.
-- Now we need to check if the AIGroup has a Task.
@@ -3570,7 +3583,7 @@ do -- AI_A2A_DISPATCHER
end
--- Assigns A2G AI Tasks in relation to the detected items.
-- @param #AI_A2G_DISPATCHER self
-- @param #AI_A2A_DISPATCHER self
function AI_A2A_DISPATCHER:Order( DetectedItem )
local detection = self.Detection -- Functional.Detection#DETECTION_AREAS

View File

@@ -731,13 +731,14 @@ end
-- @param #BASE self
-- @param DCS#Time EventTime The time stamp of the event.
-- @param DCS#Object Initiator The initiating object of the event.
function BASE:CreateEventCrash( EventTime, Initiator )
function BASE:CreateEventCrash( EventTime, Initiator, IniObjectCategory )
self:F( { EventTime, Initiator } )
local Event = {
id = world.event.S_EVENT_CRASH,
time = EventTime,
initiator = Initiator,
IniObjectCategory = IniObjectCategory,
}
world.onEvent( Event )

View File

@@ -757,7 +757,9 @@ function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, Category
local StaticTemplate = UTILS.DeepCopy( StaticTemplate )
local StaticTemplateName = env.getValueDictByKey( StaticTemplate.name )
local StaticTemplateGroupName = env.getValueDictByKey( StaticTemplate.name )
local StaticTemplateName=StaticTemplate.units[1].name
self.Templates.Statics[StaticTemplateName] = self.Templates.Statics[StaticTemplateName] or {}
@@ -765,7 +767,7 @@ function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, Category
StaticTemplate.CoalitionID = CoalitionID
StaticTemplate.CountryID = CountryID
self.Templates.Statics[StaticTemplateName].StaticName = StaticTemplateName
self.Templates.Statics[StaticTemplateName].StaticName = StaticTemplateGroupName
self.Templates.Statics[StaticTemplateName].GroupTemplate = StaticTemplate
self.Templates.Statics[StaticTemplateName].UnitTemplate = StaticTemplate.units[1]
self.Templates.Statics[StaticTemplateName].CategoryID = CategoryID

View File

@@ -131,8 +131,6 @@
-- * Weapon data: Certain events populate weapon information.
-- * Place data: Certain events populate place information.
--
-- Example code snippet:
--
-- --- This function is an Event Handling function that will be called when Tank1 is Dead.
-- -- EventData is an EVENTDATA structure.
-- -- We use the EventData.IniUnit to smoke the tank Green.
@@ -143,6 +141,7 @@
-- EventData.IniUnit:SmokeGreen()
-- end
--
--
-- Find below an overview which events populate which information categories:
--
-- ![Objects](..\Presentations\EVENT\Dia14.JPG)
@@ -152,7 +151,6 @@
-- In case a STATIC object is involved, the documentation indicates which fields will and won't not be populated.
-- The fields **IniObjectCategory** and **TgtObjectCategory** contain the indicator which **kind of object is involved** in the event.
-- You can use the enumerator **Object.Category.UNIT** and **Object.Category.STATIC** to check on IniObjectCategory and TgtObjectCategory.
--
-- Example code snippet:
--
-- if Event.IniObjectCategory == Object.Category.UNIT then
@@ -174,6 +172,7 @@
-- @module Core.Event
-- @image Core_Event.JPG
--- @type EVENT
-- @field #EVENT.Events Events
-- @extends Core.Base#BASE
@@ -195,6 +194,7 @@ world.event.S_EVENT_DELETE_ZONE_GOAL = world.event.S_EVENT_MAX + 1005
world.event.S_EVENT_REMOVE_UNIT = world.event.S_EVENT_MAX + 1006
world.event.S_EVENT_PLAYER_ENTER_AIRCRAFT = world.event.S_EVENT_MAX + 1007
--- The different types of events supported by MOOSE.
-- Use this structure to subscribe to events using the @{Core.Base#BASE.HandleEvent}() method.
-- @type EVENTS
@@ -227,13 +227,13 @@ EVENTS = {
MarkChange = world.event.S_EVENT_MARK_CHANGE,
MarkRemoved = world.event.S_EVENT_MARK_REMOVED,
-- Moose Events
NewCargo = world.event.S_EVENT_NEW_CARGO,
DeleteCargo = world.event.S_EVENT_DELETE_CARGO,
NewZone = world.event.S_EVENT_NEW_ZONE,
DeleteZone = world.event.S_EVENT_DELETE_ZONE,
NewZoneGoal = world.event.S_EVENT_NEW_ZONE_GOAL,
DeleteZoneGoal = world.event.S_EVENT_DELETE_ZONE_GOAL,
RemoveUnit = world.event.S_EVENT_REMOVE_UNIT,
NewCargo = world.event.S_EVENT_NEW_CARGO,
DeleteCargo = world.event.S_EVENT_DELETE_CARGO,
NewZone = world.event.S_EVENT_NEW_ZONE,
DeleteZone = world.event.S_EVENT_DELETE_ZONE,
NewZoneGoal = world.event.S_EVENT_NEW_ZONE_GOAL,
DeleteZoneGoal = world.event.S_EVENT_DELETE_ZONE_GOAL,
RemoveUnit = world.event.S_EVENT_REMOVE_UNIT,
PlayerEnterAircraft = world.event.S_EVENT_PLAYER_ENTER_AIRCRAFT,
-- 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
@@ -304,6 +304,8 @@ EVENTS = {
-- @field Core.ZONE#ZONE Zone The zone object.
-- @field #string ZoneName The name of the zone.
local _EVENTMETA = {
[world.event.S_EVENT_SHOT] = {
Order = 1,
@@ -560,6 +562,7 @@ local _EVENTMETA = {
},
}
--- The Events structure
-- @type EVENT.Events
-- @field #number IniUnit
@@ -573,11 +576,12 @@ function EVENT:New()
local self = BASE:Inherit( self, BASE:New() )
-- Add world event handler.
self.EventHandler = world.addEventHandler( self )
self.EventHandler = world.addEventHandler(self)
return self
end
--- Initializes the Events structure for the event.
-- @param #EVENT self
-- @param DCS#world.event EventID Event ID.
@@ -591,7 +595,7 @@ function EVENT:Init( EventID, EventClass )
self.Events[EventID] = {}
end
-- Each event has a sub-table of EventClasses, ordered by EventPriority.
-- Each event has a subtable of EventClasses, ordered by EventPriority.
local EventPriority = EventClass:GetEventPriority()
if not self.Events[EventID][EventPriority] then
@@ -599,7 +603,7 @@ function EVENT:Init( EventID, EventClass )
end
if not self.Events[EventID][EventPriority][EventClass] then
self.Events[EventID][EventPriority][EventClass] = {}
self.Events[EventID][EventPriority][EventClass] = {}
end
return self.Events[EventID][EventPriority][EventClass]
@@ -610,7 +614,7 @@ end
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
-- @param DCS#world.event EventID Event ID.
-- @return #EVENT self
function EVENT:RemoveEvent( EventClass, EventID )
function EVENT:RemoveEvent( EventClass, EventID )
-- Debug info.
self:F2( { "Removing subscription for class: ", EventClass:GetClassNameAndID() } )
@@ -634,7 +638,7 @@ end
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
-- @param DCS#world.event EventID Event ID.
-- @return #EVENT.Events
function EVENT:Reset( EventObject ) -- R2.1
function EVENT:Reset( EventObject ) --R2.1
self:F( { "Resetting subscriptions for class: ", EventObject:GetClassNameAndID() } )
@@ -653,11 +657,12 @@ function EVENT:Reset( EventObject ) -- R2.1
end
end
--- Clears all event subscriptions for a @{Core.Base#BASE} derived object.
-- @param #EVENT self
-- @param Core.Base#BASE EventClass The self class object for which the events are removed.
-- @return #EVENT self
function EVENT:RemoveAll( EventClass )
function EVENT:RemoveAll(EventClass)
local EventClassName = EventClass:GetClassNameAndID()
@@ -671,6 +676,8 @@ function EVENT:RemoveAll( EventClass )
return self
end
--- Create an OnDead event handler for a group
-- @param #EVENT self
-- @param #table EventTemplate
@@ -702,6 +709,7 @@ function EVENT:OnEventGeneric( EventFunction, EventClass, EventID )
return self
end
--- Set a new listener for an `S_EVENT_X` event for a UNIT.
-- @param #EVENT self
-- @param #string UnitName The name of the UNIT.
@@ -789,6 +797,7 @@ do -- OnDead
end
do -- OnLand
--- Create an OnLand event handler for a group
@@ -855,7 +864,7 @@ do -- Event Creation
id = EVENTS.NewCargo,
time = timer.getTime(),
cargo = Cargo,
}
}
world.onEvent( Event )
end
@@ -870,7 +879,7 @@ do -- Event Creation
id = EVENTS.DeleteCargo,
time = timer.getTime(),
cargo = Cargo,
}
}
world.onEvent( Event )
end
@@ -885,7 +894,7 @@ do -- Event Creation
id = EVENTS.NewZone,
time = timer.getTime(),
zone = Zone,
}
}
world.onEvent( Event )
end
@@ -900,7 +909,7 @@ do -- Event Creation
id = EVENTS.DeleteZone,
time = timer.getTime(),
zone = Zone,
}
}
world.onEvent( Event )
end
@@ -915,11 +924,12 @@ do -- Event Creation
id = EVENTS.NewZoneGoal,
time = timer.getTime(),
ZoneGoal = ZoneGoal,
}
}
world.onEvent( Event )
end
--- Creation of a ZoneGoal Deletion Event.
-- @param #EVENT self
-- @param Core.ZoneGoal#ZONE_GOAL ZoneGoal The ZoneGoal created.
@@ -930,11 +940,12 @@ do -- Event Creation
id = EVENTS.DeleteZoneGoal,
time = timer.getTime(),
ZoneGoal = ZoneGoal,
}
}
world.onEvent( Event )
end
--- Creation of a S_EVENT_PLAYER_ENTER_UNIT Event.
-- @param #EVENT self
-- @param Wrapper.Unit#UNIT PlayerUnit.
@@ -944,8 +955,8 @@ do -- Event Creation
local Event = {
id = EVENTS.PlayerEnterUnit,
time = timer.getTime(),
initiator = PlayerUnit:GetDCSObject(),
}
initiator = PlayerUnit:GetDCSObject()
}
world.onEvent( Event )
end
@@ -959,8 +970,8 @@ do -- Event Creation
local Event = {
id = EVENTS.PlayerEnterAircraft,
time = timer.getTime(),
initiator = PlayerUnit:GetDCSObject(),
}
initiator = PlayerUnit:GetDCSObject()
}
world.onEvent( Event )
end
@@ -972,24 +983,25 @@ end
-- @param #EVENTDATA Event Event data table.
function EVENT:onEvent( Event )
--- Function to handle errors.
local ErrorHandler = function( errmsg )
env.info( "Error in SCHEDULER function:" .. errmsg )
if BASE.Debug ~= nil then
env.info( debug.traceback() )
end
return errmsg
end
-- Get event meta data.
local EventMeta = _EVENTMETA[Event.id]
-- Check if this is a known event?
if EventMeta then
if self and self.Events and self.Events[Event.id] and self.MissionEnd == false and (Event.initiator ~= nil or (Event.initiator == nil and Event.id ~= EVENTS.PlayerLeaveUnit)) then
if self and self.Events and self.Events[Event.id] and self.MissionEnd==false and (Event.initiator~=nil or (Event.initiator==nil and Event.id~=EVENTS.PlayerLeaveUnit)) then
-- Check if mission has ended.
if Event.id and Event.id == EVENTS.MissionEnd then
self.MissionEnd = true
end
@@ -997,50 +1009,27 @@ function EVENT:onEvent( Event )
if Event.initiator then
Event.IniObjectCategory = Event.initiator:getCategory()
if Event.IniObjectCategory == Object.Category.UNIT then
Event.IniDCSUnit = Event.initiator
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
Event.IniUnitName = Event.IniDCSUnitName
Event.IniDCSGroup = Event.IniDCSUnit:getGroup()
Event.IniUnit = UNIT:FindByName( Event.IniDCSUnitName )
if not Event.IniUnit then
-- Unit can be a CLIENT. Most likely this will be the case ...
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
if Event.IniObjectCategory == Object.Category.STATIC then
if Event.id == 31 then
if Event.IniObjectCategory == Object.Category.STATIC then
---
-- Static
---
if Event.id==31 then
-- Event.initiator is a Static object representing the pilot. But getName() errors due to DCS bug.
Event.IniDCSUnit = Event.initiator
local ID = Event.initiator.id_
Event.IniDCSUnitName = string.format( "Ejected Pilot ID %s", tostring( ID ) )
local ID=Event.initiator.id_
Event.IniDCSUnitName = string.format("Ejected Pilot ID %s", tostring(ID))
Event.IniUnitName = Event.IniDCSUnitName
Event.IniCoalition = 0
Event.IniCategory = 0
Event.IniCategory = 0
Event.IniTypeName = "Ejected Pilot"
elseif Event.id == 33 then -- ejection seat discarded
elseif Event.id == 33 then -- ejection seat discarded
Event.IniDCSUnit = Event.initiator
local ID = Event.initiator.id_
Event.IniDCSUnitName = string.format( "Ejection Seat ID %s", tostring( ID ) )
local ID=Event.initiator.id_
Event.IniDCSUnitName = string.format("Ejection Seat ID %s", tostring(ID))
Event.IniUnitName = Event.IniDCSUnitName
Event.IniCoalition = 0
Event.IniCategory = 0
Event.IniCategory = 0
Event.IniTypeName = "Ejection Seat"
else
Event.IniDCSUnit = Event.initiator
@@ -1051,9 +1040,47 @@ function EVENT:onEvent( Event )
Event.IniCategory = Event.IniDCSUnit:getDesc().category
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
end
-- Dead events of units can be delayed and the initiator changed to a static.
-- Take care of that.
local Unit=UNIT:FindByName(Event.IniDCSUnitName)
if Unit then
Event.IniObjectCategory = Object.Category.UNIT
end
end
if Event.IniObjectCategory == Object.Category.UNIT then
---
-- Unit
---
Event.IniDCSUnit = Event.initiator
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
Event.IniUnitName = Event.IniDCSUnitName
Event.IniDCSGroup = Event.IniDCSUnit:getGroup()
Event.IniUnit = UNIT:FindByName( Event.IniDCSUnitName )
if not Event.IniUnit then
-- Unit can be a CLIENT. Most likely this will be the case ...
Event.IniUnit = CLIENT:FindByName( Event.IniDCSUnitName, '', true )
end
Event.IniDCSGroupName = Event.IniUnit and Event.IniUnit.GroupName or ""
if Event.IniDCSGroup and Event.IniDCSGroup:isExist() then
Event.IniDCSGroupName = Event.IniDCSGroup:getName()
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
Event.IniGroupName = Event.IniDCSGroupName
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.CARGO then
---
-- Cargo
---
Event.IniDCSUnit = Event.initiator
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
Event.IniUnitName = Event.IniDCSUnitName
@@ -1064,19 +1091,26 @@ function EVENT:onEvent( Event )
end
if Event.IniObjectCategory == Object.Category.SCENERY then
---
-- Scenery
---
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!
Event.IniTypeName = Event.initiator:isExist() and Event.IniDCSUnit:getTypeName() or "SCENERY"
end
if Event.IniObjectCategory == Object.Category.BASE then
---
-- Base Object
---
Event.IniDCSUnit = Event.initiator
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
Event.IniUnitName = Event.IniDCSUnitName
Event.IniUnit = AIRBASE:FindByName( Event.IniDCSUnitName )
Event.IniUnit = AIRBASE:FindByName(Event.IniDCSUnitName)
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
Event.IniCategory = Event.IniDCSUnit:getDesc().category
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
@@ -1084,7 +1118,12 @@ function EVENT:onEvent( Event )
end
if Event.target then
---
-- TARGET
---
-- Target category.
Event.TgtObjectCategory = Event.target:getCategory()
if Event.TgtObjectCategory == Object.Category.UNIT then
@@ -1097,9 +1136,7 @@ function EVENT:onEvent( Event )
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()
@@ -1118,18 +1155,18 @@ function EVENT:onEvent( Event )
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
else
Event.TgtDCSUnitName = string.format( "No target object for Event ID %s", tostring( Event.id ) )
Event.TgtDCSUnitName = string.format("No target object for Event ID %s", tostring(Event.id))
Event.TgtUnitName = Event.TgtDCSUnitName
Event.TgtUnit = nil
Event.TgtCoalition = 0
Event.TgtCategory = 0
if Event.id == 6 then
Event.TgtTypeName = "Ejected Pilot"
Event.TgtDCSUnitName = string.format( "Ejected Pilot ID %s", tostring( Event.IniDCSUnitName ) )
Event.TgtDCSUnitName = string.format("Ejected Pilot ID %s", tostring(Event.IniDCSUnitName))
Event.TgtUnitName = Event.TgtDCSUnitName
elseif Event.id == 33 then
Event.TgtTypeName = "Ejection Seat"
Event.TgtDCSUnitName = string.format( "Ejection Seat ID %s", tostring( Event.IniDCSUnitName ) )
Event.TgtDCSUnitName = string.format("Ejection Seat ID %s", tostring(Event.IniDCSUnitName))
Event.TgtUnitName = Event.TgtDCSUnitName
else
Event.TgtTypeName = "Static"
@@ -1147,6 +1184,7 @@ function EVENT:onEvent( Event )
end
end
-- Weapon.
if Event.weapon then
Event.Weapon = Event.weapon
Event.WeaponName = Event.Weapon:getTypeName()
@@ -1155,49 +1193,48 @@ function EVENT:onEvent( Event )
Event.WeaponCoalition = Event.WeaponUNIT and Event.Weapon:getCoalition()
Event.WeaponCategory = Event.WeaponUNIT and Event.Weapon:getDesc().category
Event.WeaponTypeName = Event.WeaponUNIT and Event.Weapon:getTypeName()
-- Event.WeaponTgtDCSUnit = Event.Weapon:getTarget()
--Event.WeaponTgtDCSUnit = Event.Weapon:getTarget()
end
-- Place should be given for takeoff and landing events as well as base captured. It should be a DCS airbase.
if Event.place then
if Event.id == EVENTS.LandingAfterEjection then
if Event.id==EVENTS.LandingAfterEjection then
-- Place is here the UNIT of which the pilot ejected.
-- local name=Event.place:getName() -- This returns a DCS error "Airbase doesn't exit" :(
--local name=Event.place:getName() -- This returns a DCS error "Airbase doesn't exit" :(
-- However, this is not a big thing, as the aircraft the pilot ejected from is usually long crashed before the ejected pilot touches the ground.
-- Event.Place=UNIT:Find(Event.place)
--Event.Place=UNIT:Find(Event.place)
else
Event.Place = AIRBASE:Find( Event.place )
Event.PlaceName = Event.Place:GetName()
Event.Place=AIRBASE:Find(Event.place)
Event.PlaceName=Event.Place:GetName()
end
end
-- Mark points.
if Event.idx then
Event.MarkID = Event.idx
Event.MarkVec3 = Event.pos
Event.MarkCoordinate = COORDINATE:NewFromVec3( Event.pos )
Event.MarkText = Event.text
Event.MarkCoalition = Event.coalition
Event.MarkID=Event.idx
Event.MarkVec3=Event.pos
Event.MarkCoordinate=COORDINATE:NewFromVec3(Event.pos)
Event.MarkText=Event.text
Event.MarkCoalition=Event.coalition
Event.MarkGroupID = Event.groupID
end
-- Cargo object.
if Event.cargo then
Event.Cargo = Event.cargo
Event.CargoName = Event.cargo.Name
end
-- Zone object.
if Event.zone then
Event.Zone = Event.zone
Event.ZoneName = Event.zone.ZoneName
end
-- Priority order.
local PriorityOrder = EventMeta.Order
local PriorityBegin = PriorityOrder == -1 and 5 or 1
local PriorityEnd = PriorityOrder == -1 and 1 or 5
if Event.IniObjectCategory ~= Object.Category.STATIC then
self:F( { EventMeta.Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } )
end
local PriorityEnd = PriorityOrder == -1 and 1 or 5
for EventPriority = PriorityBegin, PriorityEnd, PriorityOrder do
@@ -1206,12 +1243,12 @@ function EVENT:onEvent( Event )
-- Okay, we got the event from DCS. Now loop the SORTED self.EventSorted[] table for the received Event.id, and for each EventData registered, check if a function needs to be called.
for EventClass, EventData in pairs( self.Events[Event.id][EventPriority] ) do
-- if Event.IniObjectCategory ~= Object.Category.STATIC then
--if Event.IniObjectCategory ~= Object.Category.STATIC then
-- self:E( { "Evaluating: ", EventClass:GetClassNameAndID() } )
-- end
--end
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )
Event.IniGroup = Event.IniGroup or GROUP:FindByName( Event.IniDCSGroupName )
Event.TgtGroup = Event.TgtGroup or GROUP:FindByName( Event.TgtDCSGroupName )
-- If the EventData is for a UNIT, the call directly the EventClass EventFunction for that UNIT.
if EventData.EventUnit then
@@ -1221,39 +1258,35 @@ function EVENT:onEvent( Event )
Event.id == EVENTS.PlayerEnterUnit or
Event.id == EVENTS.Crash or
Event.id == EVENTS.Dead or
Event.id == EVENTS.RemoveUnit then
Event.id == EVENTS.RemoveUnit or
Event.id == EVENTS.UnitLost then
local UnitName = EventClass:GetName()
if (EventMeta.Side == "I" and UnitName == Event.IniDCSUnitName) or
(EventMeta.Side == "T" and UnitName == Event.TgtDCSUnitName) then
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 )
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]
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 )
local Result, Value = xpcall(
function()
return EventFunction( EventClass, Event )
end, ErrorHandler )
end
end
end
else
@@ -1271,48 +1304,43 @@ function EVENT:onEvent( Event )
Event.id == EVENTS.PlayerEnterUnit or
Event.id == EVENTS.Crash or
Event.id == EVENTS.Dead or
Event.id == EVENTS.RemoveUnit then
Event.id == EVENTS.RemoveUnit or
Event.id == EVENTS.UnitLost then
-- We can get the name of the EventClass, which is now always a GROUP object.
local GroupName = EventClass:GetName()
if (EventMeta.Side == "I" and GroupName == Event.IniDCSGroupName) or
(EventMeta.Side == "T" and GroupName == Event.TgtDCSGroupName) then
if ( EventMeta.Side == "I" and GroupName == Event.IniDCSGroupName ) or
( EventMeta.Side == "T" and GroupName == Event.TgtDCSGroupName ) 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 GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
end
local Result, Value = xpcall( function()
return EventData.EventFunction( EventClass, Event, unpack( EventData.Params ) )
end, ErrorHandler )
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]
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 )
local Result, Value = xpcall(
function()
return EventFunction( EventClass, Event, unpack( EventData.Params ) )
end, ErrorHandler )
end
end
end
else
-- The EventClass is not alive anymore, we remove it from the EventHandlers...
-- self:RemoveEvent( EventClass, Event.id )
--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
@@ -1321,28 +1349,25 @@ function EVENT:onEvent( Event )
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( function()
return EventData.EventFunction( EventClass, Event )
end, ErrorHandler )
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]
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 )
local Result, Value = xpcall(
function()
local Result, Value = EventFunction( EventClass, Event )
return Result, Value
end, ErrorHandler )
end
end
end
@@ -1365,7 +1390,7 @@ function EVENT:onEvent( Event )
self:T( { EventMeta.Text, Event } )
end
else
self:E( string.format( "WARNING: Could not get EVENTMETA data for event ID=%d! Is this an unknown/new DCS event?", tostring( Event.id ) ) )
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
Event = nil

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,8 @@
-- * Send message to all players.
-- * Send messages to a coalition.
-- * Send messages to a specific group.
-- * Send messages to a specific unit or client.
--
--
-- ===
--
@@ -35,6 +37,7 @@
--
-- * To a @{Client} using @{#MESSAGE.ToClient}().
-- * To a @{Wrapper.Group} using @{#MESSAGE.ToGroup}()
-- * To a @{Wrapper.Unit} using @{#MESSAGE.ToUnit}()
-- * To a coalition using @{#MESSAGE.ToCoalition}().
-- * To the red coalition using @{#MESSAGE.ToRed}().
-- * To the blue coalition using @{#MESSAGE.ToBlue}().
@@ -194,18 +197,21 @@ function MESSAGE:ToClient( Client, Settings )
if Client and Client:GetClientGroupID() then
if self.MessageType then
local Settings = Settings or (Client and _DATABASE:GetPlayerSettings( Client:GetPlayerName() )) or _SETTINGS -- Core.Settings#SETTINGS
local Settings = Settings or ( Client and _DATABASE:GetPlayerSettings( Client:GetPlayerName() ) ) or _SETTINGS -- Core.Settings#SETTINGS
self.MessageDuration = Settings:GetMessageTime( self.MessageType )
self.MessageCategory = "" -- self.MessageType .. ": "
end
local Unit = Client:GetClient()
if self.MessageDuration ~= 0 then
local ClientGroupID = Client:GetClientGroupID()
self:T( self.MessageCategory .. self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ) .. " / " .. self.MessageDuration )
trigger.action.outTextForGroup( ClientGroupID, self.MessageCategory .. self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ), self.MessageDuration, self.ClearScreen )
self:T( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration )
--trigger.action.outTextForGroup( ClientGroupID, self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration , self.ClearScreen)
trigger.action.outTextForUnit( Unit:GetID(), self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration , self.ClearScreen)
end
end
return self
end
@@ -232,6 +238,31 @@ function MESSAGE:ToGroup( Group, Settings )
return self
end
--- Sends a MESSAGE to a Unit.
-- @param #MESSAGE self
-- @param Wrapper.Unit#UNIT Unit to which the message is displayed.
-- @return #MESSAGE Message object.
function MESSAGE:ToUnit( Unit, Settings )
self:F( Unit.IdentifiableName )
if Unit then
if self.MessageType then
local Settings = Settings or ( Unit and _DATABASE:GetPlayerSettings( Unit:GetPlayerName() ) ) or _SETTINGS -- Core.Settings#SETTINGS
self.MessageDuration = Settings:GetMessageTime( self.MessageType )
self.MessageCategory = "" -- self.MessageType .. ": "
end
if self.MessageDuration ~= 0 then
self:T( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration )
trigger.action.outTextForUnit( Unit:GetID(), self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration, self.ClearScreen )
end
end
return self
end
--- Sends a MESSAGE to the Blue coalition.
-- @param #MESSAGE self
-- @return #MESSAGE

View File

@@ -194,7 +194,12 @@ do -- COORDINATE
-- ## 9) Coordinate text generation
--
-- * @{#COORDINATE.ToStringBR}(): Generates a Bearing & Range text in the format of DDD for DI where DDD is degrees and DI is distance.
-- * @{#COORDINATE.ToStringLL}(): Generates a Latutude & Longutude text.
-- * @{#COORDINATE.ToStringBRA}(): Generates a Bearing, Range & Altitude text.
-- * @{#COORDINATE.ToStringBRAANATO}(): Generates a Generates a Bearing, Range, Aspect & Altitude text in NATOPS.
-- * @{#COORDINATE.ToStringLL}(): Generates a Latutide & Longitude text.
-- * @{#COORDINATE.ToStringLLDMS}(): Generates a Lat, Lon, Degree, Minute, Second text.
-- * @{#COORDINATE.ToStringLLDDM}(): Generates a Lat, Lon, Degree, decimal Minute text.
-- * @{#COORDINATE.ToStringMGRS}(): Generates a MGRS grid coordinate text.
--
-- ## 10) Drawings on F10 map
--
@@ -912,7 +917,7 @@ do -- COORDINATE
-- The text will reflect the temperature like this:
--
-- - For Russian and European aircraft using the metric system - Degrees Celcius (°C)
-- - For American aircraft we link to the imperial system - Degrees Farenheit (°F)
-- - For American aircraft we link to the imperial system - Degrees Fahrenheit (°F)
--
-- A text containing a pressure will look like this:
--
@@ -932,7 +937,7 @@ do -- COORDINATE
if Settings:IsMetric() then
return string.format( " %-2.2f °C", DegreesCelcius )
else
return string.format( " %-2.2f °F", UTILS.CelciusToFarenheit( DegreesCelcius ) )
return string.format( " %-2.2f °F", UTILS.CelsiusToFahrenheit( DegreesCelcius ) )
end
else
return " no temperature"
@@ -1112,25 +1117,28 @@ do -- COORDINATE
-- @param #COORDINATE self
-- @param #number Distance The distance in meters.
-- @param Core.Settings#SETTINGS Settings
-- @param #string Language (optional) "EN" or "RU"
-- @param #number Precision (optional) round to this many decimal places
-- @return #string The distance text expressed in the units of measurement.
function COORDINATE:GetDistanceText( Distance, Settings, Language )
function COORDINATE:GetDistanceText( Distance, Settings, Language, Precision )
local Settings = Settings or _SETTINGS -- Core.Settings#SETTINGS
local Language = Language or "EN"
local Precision = Precision or 0
local DistanceText
if Settings:IsMetric() then
if Language == "EN" then
DistanceText = " for " .. UTILS.Round( Distance / 1000, 2 ) .. " km"
DistanceText = " for " .. UTILS.Round( Distance / 1000, Precision ) .. " km"
elseif Language == "RU" then
DistanceText = " за " .. UTILS.Round( Distance / 1000, 2 ) .. " километров"
DistanceText = " за " .. UTILS.Round( Distance / 1000, Precision ) .. " километров"
end
else
if Language == "EN" then
DistanceText = " for " .. UTILS.Round( UTILS.MetersToNM( Distance ), 2 ) .. " miles"
DistanceText = " for " .. UTILS.Round( UTILS.MetersToNM( Distance ), Precision ) .. " miles"
elseif Language == "RU" then
DistanceText = " за " .. UTILS.Round( UTILS.MetersToNM( Distance ), 2 ) .. " миль"
DistanceText = " за " .. UTILS.Round( UTILS.MetersToNM( Distance ), Precision ) .. " миль"
end
end
@@ -1208,7 +1216,7 @@ do -- COORDINATE
local Settings = Settings or _SETTINGS -- Core.Settings#SETTINGS
local BearingText = self:GetBearingText( AngleRadians, 0, Settings, Language )
local DistanceText = self:GetDistanceText( Distance, Settings, Language )
local DistanceText = self:GetDistanceText( Distance, Settings, Language, 0 )
local BRText = BearingText .. DistanceText
@@ -1226,7 +1234,7 @@ do -- COORDINATE
local Settings = Settings or _SETTINGS -- Core.Settings#SETTINGS
local BearingText = self:GetBearingText( AngleRadians, 0, Settings, Language )
local DistanceText = self:GetDistanceText( Distance, Settings, Language )
local DistanceText = self:GetDistanceText( Distance, Settings, Language, 0 )
local AltitudeText = self:GetAltitudeText( Settings, Language )
local BRAText = BearingText .. DistanceText .. AltitudeText -- When the POINT is a VEC2, there will be no altitude shown.
@@ -2164,14 +2172,21 @@ do -- COORDINATE
if ReadOnly==nil then
ReadOnly=false
end
local vec3=self:GetVec3()
Radius=Radius or 1000
Coalition=Coalition or -1
Color=Color or {1,0,0}
Color[4]=Alpha or 1.0
LineType=LineType or 1
FillColor=FillColor or Color
FillColor=FillColor or UTILS.DeepCopy(Color)
FillColor[4]=FillAlpha or 0.15
trigger.action.circleToAll(Coalition, MarkID, vec3, Radius, Color, FillColor, LineType, ReadOnly, Text or "")
return MarkID
end
@@ -2196,13 +2211,19 @@ do -- COORDINATE
if ReadOnly==nil then
ReadOnly=false
end
local vec3=Endpoint:GetVec3()
Coalition=Coalition or -1
Color=Color or {1,0,0}
Color[4]=Alpha or 1.0
LineType=LineType or 1
FillColor=FillColor or Color
FillColor=FillColor or UTILS.DeepCopy(Color)
FillColor[4]=FillAlpha or 0.15
trigger.action.rectToAll(Coalition, MarkID, self:GetVec3(), vec3, Color, FillColor, LineType, ReadOnly, Text or "")
return MarkID
end
@@ -2226,17 +2247,23 @@ do -- COORDINATE
if ReadOnly==nil then
ReadOnly=false
end
local point1=self:GetVec3()
local point2=Coord2:GetVec3()
local point3=Coord3:GetVec3()
local point4=Coord4:GetVec3()
Coalition=Coalition or -1
Color=Color or {1,0,0}
Color[4]=Alpha or 1.0
LineType=LineType or 1
FillColor=FillColor or Color
FillColor=FillColor or UTILS.DeepCopy(Color)
FillColor[4]=FillAlpha or 0.15
trigger.action.quadToAll(Coalition, MarkID, self:GetVec3(), point2, point3, point4, Color, FillColor, LineType, ReadOnly, Text or "")
trigger.action.quadToAll(Coalition, MarkID, point1, point2, point3, point4, Color, FillColor, LineType, ReadOnly, Text or "")
return MarkID
end
@@ -2320,11 +2347,15 @@ do -- COORDINATE
ReadOnly=false
end
Coalition=Coalition or -1
Color=Color or {1,0,0}
Color[4]=Alpha or 1.0
FillColor=FillColor or Color
FillColor=FillColor or UTILS.DeepCopy(Color)
FillColor[4]=FillAlpha or 0.3
FontSize=FontSize or 14
trigger.action.textToAll(Coalition, MarkID, self:GetVec3(), Color, FillColor, FontSize, ReadOnly, Text or "Hello World")
return MarkID
end
@@ -2346,13 +2377,19 @@ do -- COORDINATE
if ReadOnly==nil then
ReadOnly=false
end
local vec3=Endpoint:GetVec3()
Coalition=Coalition or -1
Color=Color or {1,0,0}
Color[4]=Alpha or 1.0
LineType=LineType or 1
FillColor=FillColor or Color
FillColor=FillColor or UTILS.DeepCopy(Color)
FillColor[4]=FillAlpha or 0.15
--trigger.action.textToAll(Coalition, MarkID, self:GetVec3(), Color, FillColor, FontSize, ReadOnly, Text or "Hello World")
trigger.action.arrowToAll(Coalition, MarkID, vec3, self:GetVec3(), Color, FillColor, LineType, ReadOnly, Text or "")
return MarkID
@@ -2727,7 +2764,53 @@ do -- COORDINATE
local Altitude = self:GetAltitudeText()
return "BRA, " .. self:GetBRAText( AngleRadians, Distance, Settings, Language )
end
--- Create a BRAA NATO call string to this COORDINATE from the FromCOORDINATE. Note - BRA delivered if no aspect can be obtained and "Merged" if range < 3nm
-- @param #COORDINATE self
-- @param #COORDINATE FromCoordinate The coordinate to measure the distance and the bearing from.
-- @param #boolean Bogey Add "Bogey" at the end if true (not yet declared hostile or friendly)
-- @param #boolean Spades Add "Spades" at the end if true (no IFF/VID ID yet known)
-- @return #string The BRAA text.
function COORDINATE:ToStringBRAANATO(FromCoordinate,Bogey,Spades)
-- Thanks to @Pikey
local BRAANATO = "Merged."
local currentCoord = FromCoordinate
local DirectionVec3 = FromCoordinate:GetDirectionVec3( self )
local AngleRadians = self:GetAngleRadians( DirectionVec3 )
local bearing = UTILS.Round( UTILS.ToDegree( AngleRadians ),0 )
local rangeMetres = self:Get2DDistance(currentCoord)
local rangeNM = UTILS.Round( UTILS.MetersToNM(rangeMetres), 0)
local aspect = self:ToStringAspect(currentCoord)
local alt = UTILS.Round(UTILS.MetersToFeet(self.y)/1000,0)--*1000
local track = UTILS.BearingToCardinal(bearing) or "North"
if rangeNM > 3 then
if aspect == "" then
BRAANATO = string.format("BRA, %03d, %d miles, Angels %d, Track %s",bearing, rangeNM, alt, track)
else
BRAANATO = string.format("BRAA, %03d, %d miles, Angels %d, %s, Track %s",bearing, rangeNM, alt, aspect, track)
end
if Bogey and Spades then
BRAANATO = BRAANATO..", Bogey, Spades."
elseif Bogey then
BRAANATO = BRAANATO..", Bogey."
elseif Spades then
BRAANATO = BRAANATO..", Spades."
else
BRAANATO = BRAANATO.."."
end
end
return BRAANATO
end
--- Return a BULLS string out of the BULLS of the coalition to the COORDINATE.
-- @param #COORDINATE self
-- @param DCS#coalition.side Coalition The coalition.

View File

@@ -201,7 +201,7 @@ do -- SET_BASE
self:F2( { ObjectName = ObjectName } )
local TriggerEvent = true
if NoTriggerEvent == false then
if NoTriggerEvent then
TriggerEvent = false
end
@@ -1004,7 +1004,7 @@ do -- SET_GROUP
--- Gets the Set.
-- @param #SET_GROUP self
-- @return #SET_GROUP self
-- @return #table Table of objects
function SET_GROUP:GetAliveSet()
self:F2()
@@ -1064,12 +1064,17 @@ do -- SET_GROUP
function SET_GROUP:AddGroup( group )
self:Add( group:GetName(), group )
-- I set the default cargo bay weight limit each time a new group is added to the set.
for UnitID, UnitData in pairs( group:GetUnits() ) do
UnitData:SetCargoBayWeightLimit()
if not DontSetCargoBayLimit then
-- I set the default cargo bay weight limit each time a new group is added to the set.
-- TODO Why is this here in the first place?
for UnitID, UnitData in pairs( group:GetUnits() ) do
if UnitData and UnitData:IsAlive() then
UnitData:SetCargoBayWeightLimit()
end
end
end
return self
end

View File

@@ -2827,21 +2827,40 @@ end
-- The method will search for a #-mark, and will return the text before the #-mark.
-- It will return nil of no prefix was found.
-- @param #SPAWN self
-- @param DCS#UNIT DCSUnit The @{DCSUnit} to be searched.
-- @return #string The prefix
-- @return #nil Nothing found
-- @param Wrapper.Group#GROUP SpawnGroup The GROUP object.
-- @return #string The prefix or #nil if nothing was found.
function SPAWN:_GetPrefixFromGroup( SpawnGroup )
self:F3( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix, SpawnGroup } )
local GroupName = SpawnGroup:GetName()
if GroupName then
local SpawnPrefix = string.match( GroupName, ".*#" )
if SpawnPrefix then
SpawnPrefix = SpawnPrefix:sub( 1, -2 )
end
local SpawnPrefix=self:_GetPrefixFromGroupName(GroupName)
return SpawnPrefix
end
return nil
end
--- Return the prefix of a spawned group.
-- The method will search for a `#`-mark, and will return the text before the `#`-mark. It will return nil of no prefix was found.
-- @param #SPAWN self
-- @param #string SpawnGroupName The name of the spawned group.
-- @return #string The prefix or #nil if nothing was found.
function SPAWN:_GetPrefixFromGroupName(SpawnGroupName)
if SpawnGroupName then
local SpawnPrefix=string.match(SpawnGroupName, ".*#")
if SpawnPrefix then
SpawnPrefix = SpawnPrefix:sub(1, -2)
end
return SpawnPrefix
end
return nil
end
@@ -3235,24 +3254,27 @@ function SPAWN:_OnBirth( EventData )
end
--- Obscolete
-- @todo Need to delete this... _DATABASE does this now ...
--- @param #SPAWN self
-- @param Core.Event#EVENTDATA EventData
function SPAWN:_OnDeadOrCrash( EventData )
self:F( self.SpawnTemplatePrefix )
local SpawnGroup = EventData.IniGroup
if SpawnGroup then
local EventPrefix = self:_GetPrefixFromGroup( SpawnGroup )
local unit=UNIT:FindByName(EventData.IniUnitName)
if unit then
local EventPrefix = self:_GetPrefixFromGroupName(unit.GroupName)
if EventPrefix then -- EventPrefix can be nil if no # is found, which means, no spawnable group!
self:T( { "Dead event: " .. EventPrefix } )
if EventPrefix == self.SpawnTemplatePrefix or (self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix) then
self.AliveUnits = self.AliveUnits - 1
self:T( "Alive Units: " .. self.AliveUnits )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
self.AliveUnits = self.AliveUnits - 1
self:T( "Alive Units: " .. self.AliveUnits )
end
end
end
end

View File

@@ -46,14 +46,14 @@
-- @field #number InitOffsetAngle Link offset angle in degrees.
-- @field #number InitStaticHeading Heading of the static.
-- @field #string InitStaticLivery Livery for aircraft.
-- @field #string InitStaticShape Shape of teh static.
-- @field #string InitStaticShape Shape of the static.
-- @field #string InitStaticType Type of the static.
-- @field #string InitStaticCategory Categrory of the static.
-- @field #string InitStaticName Name of the static.
-- @field Core.Point#COORDINATE InitStaticCoordinate Coordinate where to spawn the static.
-- @field #boolean InitDead Set static to be dead if true.
-- @field #boolean InitCargo If true, static can act as cargo.
-- @field #number InitCargoMass Mass of cargo in kg.
-- @field #boolean InitStaticDead Set static to be dead if true.
-- @field #boolean InitStaticCargo If true, static can act as cargo.
-- @field #number InitStaticCargoMass Mass of cargo in kg.
-- @extends Core.Base#BASE
@@ -260,7 +260,7 @@ end
-- @param #number Mass Mass of the cargo in kg.
-- @return #SPAWNSTATIC self
function SPAWNSTATIC:InitCargoMass(Mass)
self.InitCargoMass=Mass
self.InitStaticCargoMass=Mass
return self
end
@@ -269,7 +269,16 @@ end
-- @param #boolean IsCargo If true, this static can act as cargo.
-- @return #SPAWNSTATIC self
function SPAWNSTATIC:InitCargo(IsCargo)
self.InitCargo=IsCargo
self.InitStaticCargo=IsCargo
return self
end
--- Initialize as dead.
-- @param #SPAWNSTATIC self
-- @param #boolean IsCargo If true, this static is dead.
-- @return #SPAWNSTATIC self
function SPAWNSTATIC:InitDead(IsDead)
self.InitStaticDead=IsDead
return self
end
@@ -417,16 +426,16 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
Template.livery_id=self.InitStaticLivery
end
if self.InitDead~=nil then
Template.dead=self.InitDead
if self.InitStaticDead~=nil then
Template.dead=self.InitStaticDead
end
if self.InitCargo~=nil then
Template.canCargo=self.InitCargo
if self.InitStaticCargo~=nil then
Template.canCargo=self.InitStaticCargo
end
if self.InitCargoMass~=nil then
Template.mass=self.InitCargoMass
if self.InitStaticCargoMass~=nil then
Template.mass=self.InitStaticCargoMass
end
if self.InitLinkUnit then
@@ -479,6 +488,8 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
-- ED's dirty way to spawn FARPS.
Static=coalition.addGroup(CountryID, -1, TemplateGroup)
else
self:T("Spawning Static")
self:T2({Template=Template})
Static=coalition.addStaticObject(CountryID, Template)
end

File diff suppressed because it is too large Load Diff

View File

@@ -487,8 +487,10 @@ do -- Object
-- @field UNIT
-- @field WEAPON
-- @field STATIC
-- @field SCENERY
-- @field BASE
-- @field SCENERY
-- @field CARGO
--- @type Object.Desc
-- @extends #Desc

View File

@@ -2755,7 +2755,7 @@ function RANGE:_DisplayRangeWeather( _unitname )
local tW = string.format( "%.1f m/s", Ws )
local tP = string.format( "%.1f mmHg", P * hPa2mmHg )
if settings:IsImperial() then
-- tT=string.format("%d°F", UTILS.CelciusToFarenheit(T))
-- tT=string.format("%d°F", UTILS.CelsiusToFahrenheit(T))
tW = string.format( "%.1f knots", UTILS.MpsToKnots( Ws ) )
tP = string.format( "%.2f inHg", P * hPa2inHg )
end
@@ -3004,7 +3004,7 @@ function RANGE:_CheckInZone( _unitName )
Straferesult.rangename = self.rangename
-- Save trap sheet.
if playerData.targeton and self.targetsheet then
if playerData and playerData.targeton and self.targetsheet then
self:_SaveTargetSheet( _playername, result )
end
-- RangeBoss edit for strafe data saved to file
@@ -3524,7 +3524,7 @@ function RANGE:_TargetsheetOnOff( _unitname )
playerData.targeton = not playerData.targeton
-- Inform player.
if playerData.targeton == true then
if playerData and playerData.targeton == true then
text = string.format( "roger, your targetsheets are now SAVED." )
else
text = string.format( "affirm, your targetsheets are NOT SAVED." )

View File

@@ -4,6 +4,7 @@ __Moose.Include( 'Scripts/Moose/Utilities/Utils.lua' )
__Moose.Include( 'Scripts/Moose/Utilities/Profiler.lua' )
__Moose.Include( 'Scripts/Moose/Utilities/Templates.lua' )
__Moose.Include( 'Scripts/Moose/Utilities/STTS.lua' )
__Moose.Include( 'Scripts/Moose/Utilities/FiFo.lua' )
__Moose.Include( 'Scripts/Moose/Core/Base.lua' )
__Moose.Include( 'Scripts/Moose/Core/Beacon.lua' )

View File

@@ -32,9 +32,11 @@
-- * [USS George Washington](https://en.wikipedia.org/wiki/USS_George_Washington_(CVN-73)) (CVN-73) [Super Carrier Module]
-- * [USS Harry S. Truman](https://en.wikipedia.org/wiki/USS_Harry_S._Truman) (CVN-75) [Super Carrier Module]
-- * [USS Forrestal](https://en.wikipedia.org/wiki/USS_Forrestal_(CV-59)) (CV-59) [Heatblur Carrier Module]
-- * [HMS Hermes](https://en.wikipedia.org/wiki/HMS_Hermes_(R12)) (R12) [**WIP**]
-- * [USS Tarawa](https://en.wikipedia.org/wiki/USS_Tarawa_(LHA-1)) (LHA-1) [**WIP**]
-- * [USS America](https://en.wikipedia.org/wiki/USS_America_(LHA-6)) (LHA-6) [**WIP**]
-- * [Juan Carlos I](https://en.wikipedia.org/wiki/Spanish_amphibious_assault_ship_Juan_Carlos_I) (L61) [**WIP**]
-- * [HMAS Canberra](https://en.wikipedia.org/wiki/HMAS_Canberra_(L02)) (L02) [**WIP**]
--
-- **Supported Aircraft:**
--
@@ -51,9 +53,9 @@
--
-- At the moment, optimized parameters are available for the F/A-18C Hornet (Lot 20) and A-4E community mod as aircraft and the USS John C. Stennis as carrier.
--
-- The AV-8B Harrier, the USS Tarawa, USS America, HMAS Canberra and Juan Carlos I are WIP. The AV-8B harrier and the LHA's and LHD can only be used together, i.e. these ships are the only carriers the harrier is supposed to land on and
-- The AV-8B Harrier, HMS Hermes, the USS Tarawa, USS America, HMAS Canberra, and Juan Carlos I are WIP. The AV-8B harrier and the LHA's and LHD can only be used together, i.e. these ships are the only carriers the harrier is supposed to land on and
-- no other fixed wing aircraft (human or AI controlled) are supposed to land on these ships. Currently only Case I is supported. Case II/III take slightly different steps from the CVN carrier.
-- However, the two Case II/III pattern are very similar so this is not a big drawback.
-- However, if no offset is used for the holding radial this provides a very close representation of the V/STOL Case III, allowing for an approach to over the deck and a vertical landing.
--
-- Heatblur's mighty F-14B Tomcat has been added (March 13th 2019) as well. Same goes for the A version.
--
@@ -113,10 +115,11 @@
-- * [Harrier Ship Landing Mission with Auto LSO!](https://www.youtube.com/watch?v=lqmVvpunk2c)
-- * [Updated Airboss V/STOL Features USS Tarawa](https://youtu.be/K7I4pU6j718)
-- * [Harrier Practice pattern USS America](https://youtu.be/99NigITYmcI)
-- * [Harrier CASE III TACAN Approach USS Tarawa](https://www.youtube.com/watch?v=bTgJXZ9Mhdc&t=1s)
--
-- ===
--
-- ### Author: **funkyfranky**
-- ### Author: **funkyfranky** LHA and LHD V/STOL additions by **Pene**
-- ### Special Thanks To **Bankler**
-- For his great [Recovery Trainer](https://forums.eagle.ru/showthread.php?t=221412) mission and script!
-- His work was the initial inspiration for this class. Also note that this implementation uses some routines for determining the player position in Case I recoveries he developed.
@@ -1260,7 +1263,7 @@ AIRBOSS = {
--- Aircraft types capable of landing on carrier (human+AI).
-- @type AIRBOSS.AircraftCarrier
-- @field #string AV8B AV-8B Night Harrier. Works only with the USS Tarawa, USS America and Juan Carlos I.
-- @field #string AV8B AV-8B Night Harrier. Works only with the HMS Hermes, USS Tarawa, USS America, and Juan Carlos I.
-- @field #string A4EC A-4E Community mod.
-- @field #string HORNET F/A-18C Lot 20 Hornet by Eagle Dynamics.
-- @field #string F14A F-14A by Heatblur.
@@ -1296,6 +1299,7 @@ AIRBOSS.AircraftCarrier={
-- @field #string TRUMAN USS Harry S. Truman (CVN-75) [Super Carrier Module]
-- @field #string FORRESTAL USS Forrestal (CV-59) [Heatblur Carrier Module]
-- @field #string VINSON USS Carl Vinson (CVN-70) [Obsolete]
-- @field #string HERMES HMS Hermes (R12) [V/STOL Carrier]
-- @field #string TARAWA USS Tarawa (LHA-1) [V/STOL Carrier]
-- @field #string AMERICA USS America (LHA-6) [V/STOL Carrier]
-- @field #string JCARLOS Juan Carlos I (L61) [V/STOL Carrier]
@@ -1309,6 +1313,7 @@ AIRBOSS.CarrierType = {
STENNIS = "Stennis",
FORRESTAL = "Forrestal",
VINSON = "VINSON",
HERMES = "HERMES81",
TARAWA = "LHA_Tarawa",
AMERICA = "USS America LHA-6",
JCARLOS = "L61",
@@ -1980,6 +1985,9 @@ function AIRBOSS:New( carriername, alias )
elseif self.carriertype == AIRBOSS.CarrierType.VINSON then
-- TODO: Carl Vinson parameters.
self:_InitStennis()
elseif self.carriertype == AIRBOSS.CarrierType.HERMES then
-- Hermes parameters.
self:_InitHermes()
elseif self.carriertype == AIRBOSS.CarrierType.TARAWA then
-- Tarawa parameters.
self:_InitTarawa()
@@ -2082,7 +2090,7 @@ function AIRBOSS:New( carriername, alias )
-- cL:FlareYellow()
-- Carrier specific.
if self.carrier:GetTypeName() ~= AIRBOSS.CarrierType.TARAWA or self.carrier:GetTypeName() ~= AIRBOSS.CarrierType.AMERICA or self.carrier:GetTypeName() ~= AIRBOSS.CarrierType.JCARLOS or self.carrier:GetTypeName() ~= AIRBOSS.CarrierType.CANBERRA then
if self.carrier:GetTypeName() ~= AIRBOSS.CarrierType.HERMES or self.carrier:GetTypeName() ~= AIRBOSS.CarrierType.TARAWA or self.carrier:GetTypeName() ~= AIRBOSS.CarrierType.AMERICA or self.carrier:GetTypeName() ~= AIRBOSS.CarrierType.JCARLOS or self.carrier:GetTypeName() ~= AIRBOSS.CarrierType.CANBERRA then
-- Flare wires.
local w1 = stern:Translate( self.carrierparam.wire1, FB, true )
@@ -2811,13 +2819,29 @@ end
-- @param #number Low
-- @param #number LOW
-- @return #AIRBOSS self
function AIRBOSS:SetGlideslopeErrorThresholds( _max, _min, High, HIGH, Low, LOW )
self.gle._max = _max or 0.4
self.gle.High = High or 0.8
self.gle.HIGH = HIGH or 1.5
self.gle._min = _min or -0.3
self.gle.Low = Low or -0.6
self.gle.LOW = LOW or -0.9
function AIRBOSS:SetGlideslopeErrorThresholds(_max,_min, High, HIGH, Low, LOW)
--Check if V/STOL Carrier
if self.carriertype == AIRBOSS.CarrierType.HERMES or self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
-- allow a larger GSE for V/STOL operations --Pene Testing
self.gle._max=_max or 0.7
self.gle.High=High or 1.4
self.gle.HIGH=HIGH or 1.9
self.gle._min=_min or -0.5
self.gle.Low=Low or -1.2
self.gle.LOW=LOW or -1.5
-- CVN values
else
self.gle._max=_max or 0.4
self.gle.High=High or 0.8
self.gle.HIGH=HIGH or 1.5
self.gle._min=_min or -0.3
self.gle.Low=Low or -0.6
self.gle.LOW=LOW or -0.9
end
return self
end
@@ -2832,15 +2856,33 @@ end
-- @param #number RightMed
-- @param #number RIGHT
-- @return #AIRBOSS self
function AIRBOSS:SetLineupErrorThresholds( _max, _min, Left, LeftMed, LEFT, Right, RightMed, RIGHT )
self.lue._max = _max or 0.5
self.lue._min = _min or -0.5
self.lue.Left = Left or -1.0
self.lue.LeftMed = LeftMed or -2.0
self.lue.LEFT = LEFT or -3.0
self.lue.Right = Right or 1.0
self.lue.RightMed = RightMed or 2.0
self.lue.RIGHT = RIGHT or 3.0
function AIRBOSS:SetLineupErrorThresholds(_max,_min, Left, LeftMed, LEFT, Right, RightMed, RIGHT)
--Check if V/STOL Carrier -- Pene testing
if self.carriertype == AIRBOSS.CarrierType.HERMES or self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
-- V/STOL Values -- allow a larger LUE for V/STOL operations
self.lue._max=_max or 1.8
self.lue._min=_min or -1.8
self.lue.Left=Left or -2.8
self.lue.LeftMed=LeftMed or -3.8
self.lue.LEFT=LEFT or -4.5
self.lue.Right=Right or 2.8
self.lue.RightMed=RightMed or 3.8
self.lue.RIGHT=RIGHT or 4.5
-- CVN Values
else
self.lue._max=_max or 0.5
self.lue._min=_min or -0.5
self.lue.Left=Left or -1.0
self.lue.LeftMed=LeftMed or -2.0
self.lue.LEFT=LEFT or -3.0
self.lue.Right=Right or 1.0
self.lue.RightMed=RightMed or 2.0
self.lue.RIGHT=RIGHT or 3.0
end
return self
end
@@ -4384,6 +4426,46 @@ function AIRBOSS:_InitForrestal()
end
--- Init parameters for R12 HMS Hermes carrier.
-- @param #AIRBOSS self
function AIRBOSS:_InitHermes()
-- Init Stennis as default.
self:_InitStennis()
-- Carrier Parameters.
self.carrierparam.sterndist = -105
self.carrierparam.deckheight = 12 -- From model viewer WL0.
-- Total size of the carrier (approx as rectangle).
self.carrierparam.totlength = 228.19
self.carrierparam.totwidthport = 20.5
self.carrierparam.totwidthstarboard = 24.5
-- Landing runway.
self.carrierparam.rwyangle = 0
self.carrierparam.rwylength = 215
self.carrierparam.rwywidth = 13
-- Wires.
self.carrierparam.wire1 = nil
self.carrierparam.wire2 = nil
self.carrierparam.wire3 = nil
self.carrierparam.wire4 = nil
-- Late break.
self.BreakLate.name = "Late Break"
self.BreakLate.Xmin = -UTILS.NMToMeters( 1 ) -- Not more than 1 NM behind the boat. Last check was at 0.
self.BreakLate.Xmax = UTILS.NMToMeters( 5 ) -- Not more than 5 NM in front of the boat. Enough for late breaks?
self.BreakLate.Zmin = -UTILS.NMToMeters( 0.25 ) -- Not more than 0.25 NM port.
self.BreakLate.Zmax = UTILS.NMToMeters( 0.5 ) -- Not more than 0.5 NM starboard.
self.BreakLate.LimitXmin = 0 -- Check and next step 0.8 NM port and in front of boat.
self.BreakLate.LimitXmax = nil
self.BreakLate.LimitZmin = -UTILS.NMToMeters( 0.5 ) -- 926 m port, closer than the stennis as abeam is 0.8-1.0 rather than 1.2
self.BreakLate.LimitZmax = nil
end
--- Init parameters for LHA-1 Tarawa carrier.
-- @param #AIRBOSS self
function AIRBOSS:_InitTarawa()
@@ -5007,14 +5089,16 @@ function AIRBOSS:_GetAircraftAoA( playerData )
aoa.Fast = 8.25 -- =17.5/2
aoa.FAST = 8.00 -- =16.5/2
elseif harrier then
-- AV-8B Harrier parameters. Tuning done on the Fast AoA to allow for abeam and ninety at Nozzles 60 - 73.
aoa.SLOW = 14.0
aoa.Slow = 13.0
aoa.OnSpeedMax = 12.0
aoa.OnSpeed = 11.0
aoa.OnSpeedMin = 10.0
aoa.Fast = 8.0
aoa.FAST = 7.5
-- AV-8B Harrier parameters. Tuning done on the Fast AoA to allow for abeam and ninety at Nozzles 55. Pene testing
aoa.SLOW = 16.0
aoa.Slow = 13.5
aoa.OnSpeedMax = 12.5
aoa.OnSpeed = 10.0
aoa.OnSpeedMin = 9.5
aoa.Fast = 8.0
aoa.FAST = 7.5
end
return aoa
@@ -5273,8 +5357,8 @@ function AIRBOSS:_GetAircraftParameters( playerData, step )
elseif skyhawk then
alt = UTILS.FeetToMeters( 300 ) -- ?
elseif harrier then
-- 300-325 ft
alt = UTILS.FeetToMeters( 300 ) -- Need to verify
alt=UTILS.FeetToMeters(312)-- 300-325 ft
end
aoa = aoaac.OnSpeed
@@ -6209,7 +6293,7 @@ function AIRBOSS:_GetMarshalAltitude( stack, case )
p2 = Carrier:Translate( UTILS.NMToMeters( 1.5 ), hdg )
-- Tarawa,LHA,LHD Delta patterns.
if self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
if self.carriertype == AIRBOSS.CarrierType.HERMES or self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
-- Pattern is directly overhead the carrier.
p1 = Carrier:Translate( UTILS.NMToMeters( 1.0 ), hdg + 90 )
@@ -8048,7 +8132,7 @@ function AIRBOSS:OnEventLand( EventData )
self:T( self.lid .. text )
-- Check carrier type.
if self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
if self.carriertype == AIRBOSS.CarrierType.HERMES or self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
-- Power "Idle".
self:RadioTransmission( self.LSORadio, self.LSOCall.IDLE, false, 1, nil, true )
@@ -8083,7 +8167,7 @@ function AIRBOSS:OnEventLand( EventData )
-- AI unit landed --
--------------------
if self.carriertype ~= AIRBOSS.CarrierType.TARAWA or self.carriertype ~= AIRBOSS.CarrierType.AMERICA or self.carriertype ~= AIRBOSS.CarrierType.JCARLOS or self.carriertype ~= AIRBOSS.CarrierType.CANBERRA then
if self.carriertype ~= AIRBOSS.CarrierType.HERMES or self.carriertype ~= AIRBOSS.CarrierType.TARAWA or self.carriertype ~= AIRBOSS.CarrierType.AMERICA or self.carriertype ~= AIRBOSS.CarrierType.JCARLOS or self.carriertype ~= AIRBOSS.CarrierType.CANBERRA then
-- Coordinate at landing event
local coord = EventData.IniUnit:GetCoordinate()
@@ -9121,7 +9205,7 @@ function AIRBOSS:_CheckForLongDownwind( playerData )
local limit = UTILS.NMToMeters( -1.6 )
-- For the tarawa, other LHA and LHD we give a bit more space.
if self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
if self.carriertype == AIRBOSS.CarrierType.HERMES or self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
limit = UTILS.NMToMeters( -2.0 )
end
@@ -9208,7 +9292,7 @@ function AIRBOSS:_Ninety( playerData )
self:_PlayerHint( playerData )
-- Next step: wake.
if self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
if self.carriertype == AIRBOSS.CarrierType.HERMES or self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
-- Harrier has no wake stop. It stays port of the boat.
self:_SetPlayerStep( playerData, AIRBOSS.PatternStep.FINAL )
else
@@ -9464,8 +9548,9 @@ function AIRBOSS:_Groove( playerData )
-- Speed difference.
local dv = math.abs( vplayer - vcarrier )
-- Stable when speed difference < 20 km/h.
local stable = dv < 20
-- Stable when speed difference < 30 km/h.(16 Kts)Pene Testing
local stable=dv<30
-- Check if player is inside the zone.
if playerData.unit:IsInZone( ZoneALS ) and stable then
@@ -9497,8 +9582,8 @@ function AIRBOSS:_Groove( playerData )
-- Speed difference.
local dv = math.abs( vplayer - vcarrier )
-- Stable when v<10 km/h.
local stable = dv < 10
-- Stable when v<15 km/h.
local stable=dv<15
-- Radio Transmission "Stabilized" once the aircraft has been cleared to cross and is over the Landing Spot and stable.
if playerData.unit:IsInZone( ZoneLS ) and stable and playerData.stable == true then
@@ -9537,25 +9622,26 @@ function AIRBOSS:_Groove( playerData )
-- Nothing else necessary.
return
end
end
-- Long V/STOL groove time Wave Off over 75 seconds to IC - TOPGUN level Only. --pene testing (WIP)
-- if rho>=RAR and rho<=RIC and not playerData.waveoff and playerData.difficulty==AIRBOSS.Difficulty.HARD and playerData.actype== AIRBOSS.AircraftCarrier.AV8B then
-- Get groove time
-- local vSlow=groovedata.time
-- If too slow wave off.
-- if vSlow >75 then
-- LSO Wave off!
-- self:RadioTransmission(self.LSORadio, self.LSOCall.WAVEOFF, nil, nil, nil, true)
-- playerData.Tlso=timer.getTime()
-- Player was waved Off
-- playerData.waveoff=true
-- return
-- end
-- end
end
-- Long V/STOL groove time Wave Off over 75 seconds to IC - TOPGUN level Only. --pene testing (WIP)--- Need to think more about this.
--if rho>=RAR and rho<=RIC and not playerData.waveoff and playerData.difficulty==AIRBOSS.Difficulty.HARD and playerData.actype== AIRBOSS.AircraftCarrier.AV8B then
-- Get groove time
--local vSlow=groovedata.time
-- If too slow wave off.
--if vSlow >75 then
-- LSO Wave off!
--self:RadioTransmission(self.LSORadio, self.LSOCall.WAVEOFF, nil, nil, nil, true)
--playerData.Tlso=timer.getTime()
-- Player was waved Off
--playerData.waveoff=true
--return
--end
--end
-- Groovedata step.
groovedata.Step = playerData.step
@@ -9726,8 +9812,8 @@ function AIRBOSS:_CheckWaveOff( glideslopeError, lineupError, AoA, playerData )
-- For the harrier, we allow a bit more room.
if playerData.actype == AIRBOSS.AircraftCarrier.AV8B then
glMax = 2.6
glMin = -2.0
luAbs = 4.1 -- Testing Pene (WIP) needs feedback to tighten up tolerences.
glMin = -2.2 -- Testing, @Engines may be just dragging it in on Hermes, or the carrier parameters need adjusting.
luAbs = 4.1 -- Testing Pene.
end
@@ -9893,17 +9979,23 @@ function AIRBOSS:_GetSternCoord()
local hdg = self.carrier:GetHeading()
-- Final bearing (true).
local FB = self:GetFinalBearing()
local FB=self:GetFinalBearing()
local case=self.case
-- Stern coordinate (sterndist<0). Also translate 10 meters starboard wrt Final bearing.
self.sterncoord:UpdateFromCoordinate( self:GetCoordinate() )
-- local stern=self:GetCoordinate()
-- Stern coordinate (sterndist<0).
if self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
-- Tarawa: Translate 8 meters port.
self.sterncoord:Translate( self.carrierparam.sterndist, hdg, true, true ):Translate( 8, FB - 90, true, true )
elseif self.carriertype == AIRBOSS.CarrierType.STENNIS then
-- Stern coordinate (sterndist<0). --Pene testing Case III
if self.carriertype==AIRBOSS.CarrierType.HERMES or self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS or self.carriertype==AIRBOSS.CarrierType.CANBERRA then
if case==3 then
-- CASE III V/STOL translation Due over deck approach if needed.
self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(8, FB-90, true, true)
elseif case==2 or case==1 then
-- V/Stol: Translate 8 meters port.
self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(8, FB-90, true, true)
end
elseif self.carriertype==AIRBOSS.CarrierType.STENNIS then
-- Stennis: translate 7 meters starboard wrt Final bearing.
self.sterncoord:Translate( self.carrierparam.sterndist, hdg, true, true ):Translate( 7, FB + 90, true, true )
elseif self.carriertype == AIRBOSS.CarrierType.FORRESTAL then
@@ -10536,7 +10628,8 @@ function AIRBOSS:_GetZoneRunwayBox()
return self.zoneRunwaybox
end
--- Get zone of primary abeam landing position of USS Tarawa, USS America and Juan Carlos. Box length 50 meters and width 30 meters.
--- Get zone of primary abeam landing position of HMS Hermes, USS Tarawa, USS America and Juan Carlos. Box length 50 meters and width 30 meters.
--- Allow for Clear to land call from LSO approaching abeam the landing spot if stable as per NATOPS 00-80T
-- @param #AIRBOSS self
-- @return Core.Zone#ZONE_POLYGON Zone surrounding landing runway.
@@ -10548,9 +10641,9 @@ function AIRBOSS:_GetZoneAbeamLandingSpot()
-- Current carrier heading.
local FB = self:GetFinalBearing( false )
-- Coordinate array.
local p = {}
-- Coordinate array. Pene Testing extended Abeam landing spot V/STOL.
local p={}
-- Points.
p[1] = S:Translate( 15, FB ):Translate( 15, FB + 90 ) -- Top-Right
p[2] = S:Translate( -45, FB ):Translate( 15, FB + 90 ) -- Bottom-Right
@@ -10640,7 +10733,7 @@ function AIRBOSS:_GetZoneHolding( case, stack )
self.zoneHolding = ZONE_RADIUS:New( "CASE I Holding Zone", Post:GetVec2(), self.marshalradius )
-- Delta pattern.
if self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
if self.carriertype == AIRBOSS.CarrierType.HERMES or self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
self.zoneHolding = ZONE_RADIUS:New( "CASE I Holding Zone", self.carrier:GetVec2(), UTILS.NMToMeters( 5 ) )
end
@@ -10692,7 +10785,7 @@ function AIRBOSS:_GetZoneCommence( case, stack )
-- Three position
local Three = self:GetCoordinate():Translate( D, hdg + 275 )
if self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
if self.carriertype == AIRBOSS.CarrierType.HERMES or self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
local Dx = UTILS.NMToMeters( 2.25 )
@@ -10983,7 +11076,7 @@ function AIRBOSS:_GetAltCarrier( unit )
return h
end
--- Get optimal landing position of the aircraft. Usually between second and third wire. In case of Tarawa and America we take the abeam landing spot 120 ft abeam the 7.5 position, for the Juan Carlos I it is 120 ft and abeam the 5 position.
--- Get optimal landing position of the aircraft. Usually between second and third wire. In case of Tarawa, Canberrra, Juan Carlos and America we take the abeam landing spot 120 ft above and 21 ft abeam the 7.5 position, for the Juan Carlos I and HMS Hermes it is 120 ft above and 21 ft abeam the 5 position. For CASE III it is 120ft directly above the landing spot.
-- @param #AIRBOSS self
-- @return Core.Point#COORDINATE Optimal landing coordinate.
function AIRBOSS:_GetOptLandingCoordinate()
@@ -10993,45 +11086,28 @@ function AIRBOSS:_GetOptLandingCoordinate()
-- Stern coordinate.
-- local stern=self:_GetSternCoord()
-- Final bearing.
local FB = self:GetFinalBearing( false )
if self.carriertype == AIRBOSS.CarrierType.TARAWA then
local FB=self:GetFinalBearing(false)
local case=self.case
-- set Case III V/STOL abeam landing spot over deck -- Pene Testing
if self.carriertype==AIRBOSS.CarrierType.HERMES or self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS or self.carriertype==AIRBOSS.CarrierType.CANBERRA then
if case==3 then
self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate())
-- Altitude 120ft -- is this corect for Case III?
self.landingcoord:SetAltitude(UTILS.FeetToMeters(120))
elseif case==2 or case==1 then
-- Landing 100 ft abeam, 120 ft alt.
self.landingcoord:UpdateFromCoordinate( self:_GetLandingSpotCoordinate() ):Translate( 35, FB - 90, true, true )
-- stern=self:_GetLandingSpotCoordinate():Translate(35, FB-90)
self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate()):Translate(35, FB-90, true, true)
--stern=self:_GetLandingSpotCoordinate():Translate(35, FB-90)
-- Alitude 120 ft.
self.landingcoord:SetAltitude( UTILS.FeetToMeters( 120 ) )
elseif self.carriertype == AIRBOSS.CarrierType.AMERICA then
-- Landing 100 ft abeam, 120 ft alt. To allow adjustments to match different deck configurations.
self.landingcoord:UpdateFromCoordinate( self:_GetLandingSpotCoordinate() ):Translate( 35, FB - 90, true, true )
-- stern=self:_GetLandingSpotCoordinate():Translate(35, FB-90)
-- Alitude 120 ft.
self.landingcoord:SetAltitude( UTILS.FeetToMeters( 120 ) )
elseif self.carriertype == AIRBOSS.CarrierType.JCARLOS then
-- Landing 100 ft abeam, 120 ft alt.
self.landingcoord:UpdateFromCoordinate( self:_GetLandingSpotCoordinate() ):Translate( 35, FB - 90, true, true )
-- stern=self:_GetLandingSpotCoordinate():Translate(35, FB-90)
-- Alitude 120 ft.
self.landingcoord:SetAltitude( UTILS.FeetToMeters( 120 ) )
elseif self.carriertype == AIRBOSS.CarrierType.CANBERRA then
-- Landing 100 ft abeam, 120 ft alt.
self.landingcoord:UpdateFromCoordinate( self:_GetLandingSpotCoordinate() ):Translate( 35, FB - 90, true, true )
-- stern=self:_GetLandingSpotCoordinate():Translate(35, FB-90)
-- Alitude 120 ft.
self.landingcoord:SetAltitude( UTILS.FeetToMeters( 120 ) )
self.landingcoord:SetAltitude(UTILS.FeetToMeters(120))
end
else
-- Ideally we want to land between 2nd and 3rd wire.
@@ -11059,7 +11135,14 @@ function AIRBOSS:_GetLandingSpotCoordinate()
-- Stern coordinate.
-- local stern=self:_GetSternCoord()
if self.carriertype == AIRBOSS.CarrierType.TARAWA then
if self.carriertype==AIRBOSS.CarrierType.HERMES then
-- Landing 100 ft abeam, 100 alt.
local hdg = self:GetHeading()
-- Primary landing spot 5
self.landingspotcoord:Translate( 69, hdg, true, true ):SetAltitude( self.carrierparam.deckheight )
elseif self.carriertype == AIRBOSS.CarrierType.TARAWA then
-- Landing 100 ft abeam, 120 alt.
local hdg = self:GetHeading()
@@ -11649,15 +11732,17 @@ function AIRBOSS:_LSOgrade( playerData )
local G = GXX .. " " .. GIM .. " " .. " " .. GIC .. " " .. GAR
-- Count number of minor, normal and major deviations.
local N = nXX + nIM + nIC + nAR
local nL = count( G, '_' ) / 2
local nS = count( G, '%(' )
local nN = N - nS - nL
-- Groove time 15-18.99 sec for a unicorn. Or 65-70 for V/STOL unicorn.
local Tgroove = playerData.Tgroove
local TgrooveUnicorn = Tgroove and (Tgroove >= 15.0 and Tgroove <= 18.99) or false
local TgrooveVstolUnicorn = Tgroove and (Tgroove >= 60.0 and Tgroove <= 65.0) and playerData.actype == AIRBOSS.AircraftCarrier.AV8B or false
local N=nXX+nIM+nIC+nAR
local Nv=nXX+nIM
local nL=count(G, '_')/2
local nS=count(G, '%(')
local nN=N-nS-nL
local nNv=Nv-nS-nL
-- Groove time 15-18.99 sec for a unicorn. Or 60-65 for V/STOL unicorn.
local Tgroove=playerData.Tgroove
local TgrooveUnicorn=Tgroove and (Tgroove>=15.0 and Tgroove<=18.99) or false
local TgrooveVstolUnicorn=Tgroove and (Tgroove>=60.0 and Tgroove<=65.0)and playerData.actype==AIRBOSS.AircraftCarrier.AV8B or false
local grade
local points
@@ -11668,29 +11753,33 @@ function AIRBOSS:_LSOgrade( playerData )
G = "Unicorn"
else
-- Add AV-8B Harrier devation allowances due to lower groundspeed and 3x conventional groove time, this allows to maintain LSO tolerances while respecting the deviations are not unsafe. (WIP requires feedback)
-- Large devaitions still result in a No Grade, A Unicorn still requires a clean pass with no deviation.
if nL > 3 and playerData.actype == AIRBOSS.AircraftCarrier.AV8B then
-- Add AV-8B Harrier devation allowances due to lower groundspeed and 3x conventional groove time, this allows to maintain LSO tolerances while respecting the deviations are not unsafe.--Pene testing
-- Large devaitions still result in a No Grade, A Unicorn still requires a clean pass with no deviation.
if nL > 1 and playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
-- Larger deviations ==> "No grade" 2.0 points.
grade = "--"
points = 2.0
elseif nN > 2 and playerData.actype == AIRBOSS.AircraftCarrier.AV8B then
grade="--"
points=2.0
elseif nNv >= 1 and playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
-- Only average deviations ==> "Fair Pass" Pass with average deviations and corrections.
grade = "(OK)"
points = 3.0
elseif nL > 0 then
grade="(OK)"
points=3.0
elseif nNv < 1 and playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
-- Only minor average deviations ==> "OK" Pass with minor deviations and corrections. (test nNv<=1 and)
grade="OK"
points=4.0
elseif nL > 0 then
-- Larger deviations ==> "No grade" 2.0 points.
grade = "--"
points = 2.0
elseif nN > 0 then
grade="--"
points=2.0
elseif nN> 0 then
-- No larger but average deviations ==> "Fair Pass" Pass with average deviations and corrections.
grade = "(OK)"
points = 3.0
else
grade="(OK)"
points=3.0
else
-- Only minor corrections
grade = "OK"
points = 4.0
end
grade="OK"
points=4.0
end
end
@@ -11994,7 +12083,7 @@ function AIRBOSS:_GS( step, n )
if n == -1 then
gp = AIRBOSS.GroovePos.IC
elseif n == 1 then
if self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
if self.carriertype == AIRBOSS.CarrierType.HERMES or self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
gp = AIRBOSS.GroovePos.AL
else
gp = AIRBOSS.GroovePos.IW
@@ -13873,7 +13962,7 @@ function AIRBOSS:_IsCarrierAircraft( unit )
-- Special case for Harrier which can only land on Tarawa, LHA and LHD.
if aircrafttype == AIRBOSS.AircraftCarrier.AV8B then
if self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
if self.carriertype == AIRBOSS.CarrierType.HERMES or self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
return true
else
return false
@@ -13881,7 +13970,7 @@ function AIRBOSS:_IsCarrierAircraft( unit )
end
-- Also only Harriers can land on the Tarawa, LHA and LHD.
if self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
if self.carriertype == AIRBOSS.CarrierType.HERMES or self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
if aircrafttype ~= AIRBOSS.AircraftCarrier.AV8B then
return false
end
@@ -17238,7 +17327,7 @@ function AIRBOSS:_MarkCaseZones( _unitName, flare )
end
-- Tarawa, LHA and LHD landing spots.
if self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
if self.carriertype == AIRBOSS.CarrierType.HERMES or self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
text = text .. "\n* abeam landing stop with RED flares"
-- Abeam landing spot zone.
local ALSPT = self:_GetZoneAbeamLandingSpot()

View File

@@ -124,6 +124,7 @@
-- self.SRSPath = "E:\\Progra~1\\DCS-SimpleRadio-Standalone\\" -- adjust your own path in your SRS installation -- server(!)
-- self.SRSchannel = 300 -- radio channel
-- self.SRSModulation = radio.modulation.AM -- modulation
-- self.SRSport = 5002 -- and SRS port
-- --
-- self.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection --shagrat
-- self.wetfeettemplate = "man in floating thingy" -- if you use a mod to have a pilot in a rescue float, put the template name in here for wet feet spawns. Note: in conjunction with csarUsePara this might create dual ejected pilots in edge cases.
@@ -254,11 +255,12 @@ CSAR.AircraftType["Mi-8MT"] = 12
CSAR.AircraftType["Mi-24P"] = 8
CSAR.AircraftType["Mi-24V"] = 8
CSAR.AircraftType["Bell-47"] = 2
CSAR.AircraftType["UH-60L"] = 10
CSAR.AircraftType["UH-60L"] = 10
CSAR.AircraftType["AH-64D_BLK_II"] = 2
--- CSAR class version.
-- @field #string version
CSAR.version="1.0.4c"
CSAR.version="1.0.4e"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list
@@ -412,6 +414,7 @@ function CSAR:New(Coalition, Template, Alias)
self.SRSPath = "E:\\Progra~1\\DCS-SimpleRadio-Standalone\\" -- adjust your own path in your server(!)
self.SRSchannel = 300 -- radio channel
self.SRSModulation = radio.modulation.AM -- modulation
self.SRSport = 5002 -- port
------------------------
--- Pseudo Functions ---
@@ -1522,6 +1525,7 @@ function CSAR:_DisplayMessageToSAR(_unit, _text, _time, _clear, _speak, _overrid
local modulation = self.SRSModulation
local channel = self.SRSchannel
local msrs = MSRS:New(path,channel,modulation)
msrs:SetPort(self.SRSport)
msrs:PlaySoundText(srstext, 2)
end
return self

View File

@@ -28,7 +28,7 @@ do
------------------------------------------------------
--- **CTLD_ENGINEERING** class, extends Core.Base#BASE
--- @type CTLD_ENGINEERING
-- @type CTLD_ENGINEERING
-- @field #string ClassName
-- @field #string lid
-- @field #string Name
@@ -870,8 +870,12 @@ do
--
-- ## 5. Support for Hercules mod by Anubis
--
-- Basic support for the Hercules mod By Anubis has been build into CTLD. Currently this does **not** cover objects and troops which can
-- be loaded from the Rearm/Refuel menu, i.e. you can drop them into the field, but you cannot use them in functions scripted with this class.
-- Basic support for the Hercules mod By Anubis has been build into CTLD - that is you can load/drop/build the same objects as the helicopters.
-- To also cover objects and troops which can be loaded from the groud crew Rearm/Refuel menu, you need to use @{#CTLD_HERCULES.New}() and link
-- this object to your CTLD setup. In this case, do **not** use the `Hercules_Cargo.lua` or `Hercules_Cargo_CTLD.lua` which are part of the mod
-- in your mission!
--
-- ### 5.1 Create an own CTLD instance and allow the usage of the Hercules mod:
--
-- local my_ctld = CTLD:New(coalition.side.BLUE,{"Helicargo", "Hercules"},"Lufttransportbrigade I")
--
@@ -882,10 +886,33 @@ do
-- my_ctld.HercMaxAngels = 2000 -- for troop/cargo drop via chute in meters, ca 6000 ft
-- my_ctld.HercMaxSpeed = 77 -- 77mps or 270kph or 150kn
--
-- Hint: you can **only** airdrop from the Hercules if you are "in parameters", i.e. at or below `HercMaxSpeed` and in the AGL bracket between
-- `HercMinAngels` and `HercMaxAngels`!
--
-- Also, the following options need to be set to `true`:
--
-- my_ctld.useprefix = true -- this is true by default and MUST BE ON.
--
-- ### 5.2 Integrate Hercules ground crew loadable objects
--
-- Add ground crew loadable objects to your CTLD instance like so, where `my_ctld` is the previously created CTLD instance:
--
-- local herccargo = CTLD_HERCULES:New("blue", "Hercules Test", my_ctld)
--
-- You also need:
--
-- * A template called "Infantry" for 10 Paratroopers (as set via herccargo.infantrytemplate).
-- * Depending on what you are loading with the help of the ground crew, there are 42 more templates for the various vehicles that are loadable.
--
-- There's a **quick check output in the `dcs.log`** which tells you what's there and what not.
-- E.g.:
-- ...Checking template for APC BTR-82A Air [24998lb] (BTR-82A) ... MISSING)
-- ...Checking template for ART 2S9 NONA Skid [19030lb] (SAU 2-C9) ... MISSING)
-- ...Checking template for EWR SBORKA Air [21624lb] (Dog Ear radar) ... MISSING)
-- ...Checking template for Transport Tigr Air [15900lb] (Tigr_233036) ... OK)
--
-- Expected template names are the ones in the rounded brackets.
--
-- Standard transport capabilities as per the real Hercules are:
--
-- ["Hercules"] = {type="Hercules", crates=true, troops=true, cratelimit = 7, trooplimit = 64}, -- 19t cargo, 64 paratroopers
@@ -924,7 +951,6 @@ CTLD = {
FreeUHFFrequencies = {}, -- Table of UHF
FreeFMFrequencies = {}, -- Table of FM
CargoCounter = 0,
wpZones = {},
Cargo_Troops = {}, -- generic troops objects
Cargo_Crates = {}, -- generic crate objects
Loaded_Cargo = {}, -- cargo aboard units
@@ -1017,6 +1043,7 @@ CTLD.UnitTypes = {
["Hercules"] = {type="Hercules", crates=true, troops=true, cratelimit = 7, trooplimit = 64, length = 25, cargoweightlimit = 19000}, -- 19t cargo, 64 paratroopers.
--Actually it's longer, but the center coord is off-center of the model.
["UH-60L"] = {type="UH-60L", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16, cargoweightlimit = 3500}, -- 4t cargo, 20 (unsec) seats
["AH-64D_BLK_II"] = {type="AH-64D_BLK_II", crates=false, troops=true, cratelimit = 0, trooplimit = 2, length = 17, cargoweightlimit = 200}, -- 2 ppl **outside** the helo
}
--- CTLD class version.
@@ -1822,6 +1849,8 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop)
local drop = drop or false
local ship = nil
local width = 20
local distance = nil
local zone = nil
if not drop then
inzone = self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD)
if not inzone then
@@ -2686,6 +2715,8 @@ function CTLD:_BuildCrates(Group, Unit,Engineering)
local required = Crate:GetCratesNeeded()
local template = Crate:GetTemplates()
local ctype = Crate:GetType()
local ccoord = Crate:GetPositionable():GetCoordinate() -- Core.Point#COORDINATE
--local testmarker = ccoord:MarkToAll("Crate found",true,"Build Position")
if not buildables[name] then
local object = {} -- #CTLD.Buildable
object.Name = name
@@ -2694,6 +2725,7 @@ function CTLD:_BuildCrates(Group, Unit,Engineering)
object.Template = template
object.CanBuild = false
object.Type = ctype -- #CTLD_CARGO.Enum
object.Coord = ccoord:GetVec2()
buildables[name] = object
foundbuilds = true
else
@@ -2855,7 +2887,8 @@ function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation)
temptable = {temptable}
end
local zone = ZONE_GROUP:New(string.format("Unload zone-%s",unitname),Group,100)
local randomcoord = zone:GetRandomCoordinate(35):GetVec2()
--local randomcoord = zone:GetRandomCoordinate(35):GetVec2()
local randomcoord = Build.Coord or zone:GetRandomCoordinate(35):GetVec2()
if Repair then
randomcoord = RepairLocation:GetVec2()
end
@@ -2864,7 +2897,7 @@ function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation)
local alias = string.format("%s-%d", _template, math.random(1,100000))
if canmove then
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
:InitRandomizeUnits(true,20,2)
--:InitRandomizeUnits(true,20,2)
:InitDelayOff()
:SpawnFromVec2(randomcoord)
else -- don't random position of e.g. SAM units build as FOB
@@ -3786,8 +3819,8 @@ end
local ucoord = Unit:GetCoordinate()
local gheight = ucoord:GetLandHeight()
local aheight = uheight - gheight -- height above ground
local maxh = self.HercMinAngels-- 1500m
local minh = self.HercMaxAngels -- 5000m
local minh = self.HercMinAngels-- 1500m
local maxh = self.HercMaxAngels -- 5000m
local maxspeed = self.HercMaxSpeed -- 77 mps
-- DONE: TEST - Speed test for Herc, should not be above 280kph/150kn
local kmspeed = uspeed * 3.6
@@ -3815,7 +3848,7 @@ end
else
local minheight = UTILS.MetersToFeet(self.minimumHoverHeight)
local maxheight = UTILS.MetersToFeet(self.maximumHoverHeight)
text = string.format("Hover parameters (autoload/drop):\n - Min height %dm \n - Max height %dm \n - Max speed 6fts \n - In parameter: %s", minheight, maxheight, htxt)
text = string.format("Hover parameters (autoload/drop):\n - Min height %dft \n - Max height %dft \n - Max speed 6ftps \n - In parameter: %s", minheight, maxheight, htxt)
end
self:_SendMessage(text, 10, false, Group)
return self
@@ -5096,7 +5129,7 @@ function CTLD_HERCULES:Cargo_SpawnObjects(Cargo_Drop_initiator,Cargo_Drop_Direct
self:Soldier_SpawnGroup(Cargo_Drop_initiator,Cargo_Content_position, Cargo_Type_name, CargoHeading, Cargo_Country, 5)
self:Soldier_SpawnGroup(Cargo_Drop_initiator,Cargo_Content_position, Cargo_Type_name, CargoHeading, Cargo_Country, 10)
else
self:Cargo_SpawnGroup(Cargo_Drop_initiator,Cargo_Content_position, Cargo_Type_name, CargoHeading, Cargo_Country, 0)
self:Cargo_SpawnGroup(Cargo_Drop_initiator,Cargo_Content_position, Cargo_Type_name, CargoHeading, Cargo_Country)
end
else
if all_cargo_gets_destroyed == true or Cargo_over_water == true then

View File

@@ -45,6 +45,7 @@
-- @field Core.Point#COORDINATE coordinate Coordinate from where the transmission is send.
-- @field #string path Path to the SRS exe. This includes the final slash "/".
-- @field #string google Full path google credentials JSON file, e.g. "C:\Users\username\Downloads\service-account-file.json".
-- @field #string Label Label showing up on the SRS radio overlay. Default is "ROBOT". No spaces allowed.
-- @extends Core.Base#BASE
--- *It is a very sad thing that nowadays there is so little useless information.* - Oscar Wilde
@@ -106,6 +107,10 @@
--
-- Use @{#MSRS.SetCoordinate} to define the origin from where the transmission is broadcasted.
--
-- ## Set SRS Port
--
-- Use @{#MSRS.SetPort} to define the SRS port. Defaults to 5002.
--
-- @field #MSRS
MSRS = {
ClassName = "MSRS",
@@ -121,11 +126,12 @@ MSRS = {
volume = 1,
speed = 1,
coordinate = nil,
Label = "ROBOT",
}
--- MSRS class version.
-- @field #string version
MSRS.version="0.0.3"
MSRS.version="0.0.4"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@@ -160,6 +166,7 @@ function MSRS:New(PathToSRS, Frequency, Modulation)
self:SetModulations(Modulation)
self:SetGender()
self:SetCoalition()
self:SetLabel()
return self
end
@@ -202,12 +209,29 @@ function MSRS:GetPath()
return self.path
end
--- Set label.
-- @param #MSRS self
-- @param #number Label. Default "ROBOT"
-- @return #MSRS self
function MSRS:SetLabel(Label)
self.Label=Label or "ROBOT"
return self
end
--- Get label.
-- @param #MSRS self
-- @return #number Label.
function MSRS:GetLabel()
return self.Label
end
--- Set port.
-- @param #MSRS self
-- @param #number Port Port. Default 5002.
-- @return #MSRS self
function MSRS:SetPort(Port)
self.port=Port or 5002
return self
end
--- Get port.
@@ -223,6 +247,7 @@ end
-- @return #MSRS self
function MSRS:SetCoalition(Coalition)
self.coalition=Coalition or 0
return self
end
--- Get coalition.
@@ -391,7 +416,7 @@ function MSRS:PlaySoundFile(Soundfile, Delay)
local command=self:_GetCommand()
-- Append file.
command=command.." --file="..tostring(soundfile)
command=command..' --file="'..tostring(soundfile)..'"'
self:_ExecCommand(command)
@@ -634,8 +659,9 @@ end
-- @param #number volume Volume.
-- @param #number speed Speed.
-- @param #number port Port.
-- @param #string label Label, defaults to "ROBOT" (displayed sender name in the radio overlay of SRS) - No spaces allowed!
-- @return #string Command.
function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, speed, port)
function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, speed, port,label)
local path=self:GetPath() or STTS.DIRECTORY
local exe=STTS.EXECUTABLE or "DCS-SR-ExternalAudio.exe"
@@ -648,6 +674,7 @@ function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, sp
volume=volume or self.volume
speed=speed or self.speed
port=port or self.port
label=label or self.Label
-- Replace modulation
modus=modus:gsub("0", "AM")
@@ -657,12 +684,12 @@ function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, sp
--local command=string.format("%s --freqs=%s --modulations=%s --coalition=%d --port=%d --volume=%.2f --speed=%d", exe, freqs, modus, coal, port, volume, speed)
-- Command from orig STTS script. Works better for some unknown reason!
local command=string.format("start /min \"\" /d \"%s\" /b \"%s\" -f %s -m %s -c %s -p %s -n \"%s\" -h", path, exe, freqs, modus, coal, port, "ROBOT")
--local command=string.format("start /min \"\" /d \"%s\" /b \"%s\" -f %s -m %s -c %s -p %s -n \"%s\" -h", path, exe, freqs, modus, coal, port, "ROBOT")
--local command=string.format('start /b "" /d "%s" "%s" -f %s -m %s -c %s -p %s -n "%s" > bla.txt', path, exe, freqs, modus, coal, port, "ROBOT")
-- Command.
local command=string.format('%s/%s -f %s -m %s -c %s -p %s -n "%s"', path, exe, freqs, modus, coal, port, "ROBOT")
local command=string.format('"%s\\%s" -f %s -m %s -c %s -p %s -n "%s"', path, exe, freqs, modus, coal, port, label)
-- Set voice or gender/culture.
if voice then
@@ -671,7 +698,7 @@ function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, sp
else
-- Add gender.
if gender and gender~="female" then
command=command..string.format(" --gender=%s", tostring(gender))
command=command..string.format(" -g %s", tostring(gender))
end
-- Add culture.
if culture and culture~="en-GB" then

View File

@@ -183,13 +183,17 @@ do -- Sound File
--- Set path, where the sound file is located.
-- @param #SOUNDFILE self
-- @param #string Path Path to the directory, where the sound file is located.
-- @param #string Path Path to the directory, where the sound file is located. In case this is nil, it defaults to the DCS mission temp directory.
-- @return #SOUNDFILE self
function SOUNDFILE:SetPath(Path)
-- Init path.
self.path=Path or "l10n/DEFAULT/"
if not Path and self.useSRS then -- use path to mission temp dir
self.path = os.getenv('TMP') .. "\\DCS\\Mission\\l10n\\DEFAULT"
end
-- Remove (back)slashes.
local nmax=1000 ; local n=1
while (self.path:sub(-1)=="/" or self.path:sub(-1)==[[\]]) and n<=nmax do

View File

@@ -40,7 +40,7 @@ do -- UserSound
-- @param #USERSOUND self
-- @param #string UserSoundFileName The filename of the usersound.
-- @return #USERSOUND
function USERSOUND:New( UserSoundFileName ) --R2.3
function USERSOUND:New( UserSoundFileName )
local self = BASE:Inherit( self, BASE:New() ) -- #USERSOUND
@@ -58,7 +58,7 @@ do -- UserSound
-- local BlueVictory = USERSOUND:New( "BlueVictory.ogg" )
-- BlueVictory:SetFileName( "BlueVictoryLoud.ogg" ) -- Set the BlueVictory to change the file name to play a louder sound.
--
function USERSOUND:SetFileName( UserSoundFileName ) --R2.3
function USERSOUND:SetFileName( UserSoundFileName )
self.UserSoundFileName = UserSoundFileName
@@ -75,7 +75,7 @@ do -- UserSound
-- local BlueVictory = USERSOUND:New( "BlueVictory.ogg" )
-- BlueVictory:ToAll() -- Play the sound that Blue has won.
--
function USERSOUND:ToAll() --R2.3
function USERSOUND:ToAll()
trigger.action.outSound( self.UserSoundFileName )
@@ -91,7 +91,7 @@ do -- UserSound
-- local BlueVictory = USERSOUND:New( "BlueVictory.ogg" )
-- BlueVictory:ToCoalition( coalition.side.BLUE ) -- Play the sound that Blue has won to the blue coalition.
--
function USERSOUND:ToCoalition( Coalition ) --R2.3
function USERSOUND:ToCoalition( Coalition )
trigger.action.outSoundForCoalition(Coalition, self.UserSoundFileName )
@@ -107,7 +107,7 @@ do -- UserSound
-- local BlueVictory = USERSOUND:New( "BlueVictory.ogg" )
-- BlueVictory:ToCountry( country.id.USA ) -- Play the sound that Blue has won to the USA country.
--
function USERSOUND:ToCountry( Country ) --R2.3
function USERSOUND:ToCountry( Country )
trigger.action.outSoundForCountry( Country, self.UserSoundFileName )
@@ -123,9 +123,9 @@ do -- UserSound
-- @usage
-- local BlueVictory = USERSOUND:New( "BlueVictory.ogg" )
-- local PlayerGroup = GROUP:FindByName( "PlayerGroup" ) -- Search for the active group named "PlayerGroup", that contains a human player.
-- BlueVictory:ToGroup( PlayerGroup ) -- Play the sound that Blue has won to the player group.
-- BlueVictory:ToGroup( PlayerGroup ) -- Play the victory sound to the player group.
--
function USERSOUND:ToGroup( Group, Delay ) --R2.3
function USERSOUND:ToGroup( Group, Delay )
Delay=Delay or 0
if Delay>0 then
@@ -136,5 +136,27 @@ do -- UserSound
return self
end
--- Play the usersound to the given @{Wrapper.Unit}.
-- @param #USERSOUND self
-- @param Wrapper.Unit#UNIT Unit The @{Wrapper.Unit} to play the usersound to.
-- @param #number Delay (Optional) Delay in seconds, before the sound is played. Default 0.
-- @return #USERSOUND The usersound instance.
-- @usage
-- local BlueVictory = USERSOUND:New( "BlueVictory.ogg" )
-- local PlayerUnit = UNIT:FindByName( "PlayerUnit" ) -- Search for the active group named "PlayerUnit", a human player.
-- BlueVictory:ToUnit( PlayerUnit ) -- Play the victory sound to the player unit.
--
function USERSOUND:ToUnit( Unit, Delay )
Delay=Delay or 0
if Delay>0 then
SCHEDULER:New(nil, USERSOUND.ToUnit,{self, Unit}, Delay)
else
trigger.action.outSoundForUnit( Unit:GetID(), self.UserSoundFileName )
end
return self
end
end

View File

@@ -1,18 +1,18 @@
--- **Utilities** Enumerators.
--
--
-- An enumerator is a variable that holds a constant value. Enumerators are very useful because they make the code easier to read and to change in general.
--
--
-- For example, instead of using the same value at multiple different places in your code, you should use a variable set to that value.
-- If, for whatever reason, the value needs to be changed, you only have to change the variable once and do not have to search through you code and reset
-- every value by hand.
--
--
-- Another big advantage is that the LDT intellisense "knows" the enumerators. So you can use the autocompletion feature and do not have to keep all the
-- values in your head or look them up in the docs.
--
-- values in your head or look them up in the docs.
--
-- DCS itself provides a lot of enumerators for various things. See [Enumerators](https://wiki.hoggitworld.com/view/Category:Enumerators) on Hoggit.
--
--
-- Other Moose classes also have enumerators. For example, the AIRBASE class has enumerators for airbase names.
--
--
-- @module ENUMS
-- @image MOOSE.JPG
@@ -20,7 +20,7 @@
-- @type ENUMS
--- Because ENUMS are just better practice.
--
--
-- The ENUMS class adds some handy variables, which help you to make your code better and more general.
--
-- @field #ENUMS
@@ -30,16 +30,16 @@ ENUMS = {}
-- @type ENUMS.ROE
-- @field #number WeaponFree AI will engage any enemy group it detects. Target prioritization is based based on the threat of the target.
-- @field #number OpenFireWeaponFree AI will engage any enemy group it detects, but will prioritize targets specified in the groups tasking.
-- @field #number OpenFire AI will engage only targets specified in its tasking.
-- @field #number OpenFire AI will engage only targets specified in its taskings.
-- @field #number ReturnFire AI will only engage threats that shoot first.
-- @field #number WeaponHold AI will hold fire under all circumstances.
ENUMS.ROE = {
WeaponFree = 0,
OpenFireWeaponFree = 1,
OpenFire = 2,
ReturnFire = 3,
WeaponHold = 4,
}
WeaponFree=0,
OpenFireWeaponFree=1,
OpenFire=2,
ReturnFire=3,
WeaponHold=4,
}
--- Reaction On Threat.
-- @type ENUMS.ROT
@@ -49,11 +49,11 @@ ENUMS.ROE = {
-- @field #number BypassAndEscape AI will attempt to avoid enemy threat zones all together. This includes attempting to fly above or around threats.
-- @field #number AllowAbortMission If a threat is deemed severe enough the AI will abort its mission and return to base.
ENUMS.ROT = {
NoReaction = 0,
PassiveDefense = 1,
EvadeFire = 2,
BypassAndEscape = 3,
AllowAbortMission = 4,
NoReaction=0,
PassiveDefense=1,
EvadeFire=2,
BypassAndEscape=3,
AllowAbortMission=4,
}
--- Alarm state.
@@ -62,12 +62,12 @@ ENUMS.ROT = {
-- @field #number Green Group is not combat ready. Sensors are stowed if possible.
-- @field #number Red Group is combat ready and actively searching for targets. Some groups like infantry will not move in this state.
ENUMS.AlarmState = {
Auto = 0,
Green = 1,
Red = 2,
Auto=0,
Green=1,
Red=2,
}
--- Weapon types. See the [Weapon Flag](https://wiki.hoggitworld.com/view/DCS_enum_weapon_flag) enumerator on Hoggit wiki.
--- Weapon types. See the [Weapon Flag](https://wiki.hoggitworld.com/view/DCS_enum_weapon_flag) enumerotor on hoggit wiki.
-- @type ENUMS.WeaponFlag
ENUMS.WeaponFlag={
-- Bombs
@@ -111,7 +111,7 @@ ENUMS.WeaponFlag={
--
-- Bombs
GuidedBomb = 14, -- (LGB + TvGB + SNSGB)
AnyUnguidedBomb = 2147485680, -- (HeBomb + Penetrator + NapalmBomb + FAEBomb + ClusterBomb + Dispenser + CandleBomb + ParachuteBomb)
AnyUnguidedBomb = 2147485680, -- (HeBomb + Penetrator + NapalmBomb + FAEBomb + ClusterBomb + Dispencer + CandleBomb + ParachuteBomb)
AnyBomb = 2147485694, -- (GuidedBomb + AnyUnguidedBomb)
--- Rockets
AnyRocket = 30720, -- LightRocket + MarkerRocket + CandleRocket + HeavyRocket
@@ -123,9 +123,11 @@ ENUMS.WeaponFlag={
--- Air-To-Air Missiles
AnyAAM = 264241152, -- IR_AAM + SAR_AAM + AR_AAM + SRAAM + MRAAM + LRAAM
AnyAutonomousMissile = 36012032, -- IR_AAM + AntiRadarMissile + AntiShipMissile + FireAndForgetASM + CruiseMissile
AnyMissile = 268402688, -- AnyASM + AnyAAM
AnyMissile = 268402688, -- AnyASM + AnyAAM
--- Guns
Cannons = 805306368, -- GUN_POD + BuiltInCannon
--- Torpedo
Torpedo = 4294967296,
---
-- Even More Genral
Auto = 3221225470, -- Any Weapon (AnyBomb + AnyRocket + AnyMissile + Cannons)
@@ -133,9 +135,96 @@ ENUMS.WeaponFlag={
AnyAG = 2956984318, -- Any Air-To-Ground Weapon
AnyAA = 264241152, -- Any Air-To-Air Weapon
AnyUnguided = 2952822768, -- Any Unguided Weapon
AnyGuided = 268402702, -- Any Guided Weapon
AnyGuided = 268402702, -- Any Guided Weapon
}
--- Weapon types by category. See the [Weapon Flag](https://wiki.hoggitworld.com/view/DCS_enum_weapon_flag) enumerator on hoggit wiki.
-- @type ENUMS.WeaponType
-- @field #table Bomb Bombs.
-- @field #table Rocket Rocket.
-- @field #table Gun Guns.
-- @field #table Missile Missiles.
-- @field #table AAM Air-to-Air missiles.
-- @field #table Torpedo Torpedos.
-- @field #table Any Combinations.
ENUMS.WeaponType={}
ENUMS.WeaponType.Bomb={
-- Bombs
LGB = 2,
TvGB = 4,
SNSGB = 8,
HEBomb = 16,
Penetrator = 32,
NapalmBomb = 64,
FAEBomb = 128,
ClusterBomb = 256,
Dispencer = 512,
CandleBomb = 1024,
ParachuteBomb = 2147483648,
-- Combinations
GuidedBomb = 14, -- (LGB + TvGB + SNSGB)
AnyUnguidedBomb = 2147485680, -- (HeBomb + Penetrator + NapalmBomb + FAEBomb + ClusterBomb + Dispencer + CandleBomb + ParachuteBomb)
AnyBomb = 2147485694, -- (GuidedBomb + AnyUnguidedBomb)
}
ENUMS.WeaponType.Rocket={
-- Rockets
LightRocket = 2048,
MarkerRocket = 4096,
CandleRocket = 8192,
HeavyRocket = 16384,
-- Combinations
AnyRocket = 30720, -- LightRocket + MarkerRocket + CandleRocket + HeavyRocket
}
ENUMS.WeaponType.Gun={
-- Guns
GunPod = 268435456,
BuiltInCannon = 536870912,
-- Combinations
Cannons = 805306368, -- GUN_POD + BuiltInCannon
}
ENUMS.WeaponType.Missile={
-- Missiles
AntiRadarMissile = 32768,
AntiShipMissile = 65536,
AntiTankMissile = 131072,
FireAndForgetASM = 262144,
LaserASM = 524288,
TeleASM = 1048576,
CruiseMissile = 2097152,
AntiRadarMissile2 = 1073741824,
-- Combinations
GuidedASM = 1572864, -- (LaserASM + TeleASM)
TacticalASM = 1835008, -- (GuidedASM + FireAndForgetASM)
AnyASM = 4161536, -- (AntiRadarMissile + AntiShipMissile + AntiTankMissile + FireAndForgetASM + GuidedASM + CruiseMissile)
AnyASM2 = 1077903360, -- 4161536+1073741824,
AnyAutonomousMissile = 36012032, -- IR_AAM + AntiRadarMissile + AntiShipMissile + FireAndForgetASM + CruiseMissile
AnyMissile = 268402688, -- AnyASM + AnyAAM
}
ENUMS.WeaponType.AAM={
-- Air-To-Air Missiles
SRAM = 4194304,
MRAAM = 8388608,
LRAAM = 16777216,
IR_AAM = 33554432,
SAR_AAM = 67108864,
AR_AAM = 134217728,
-- Combinations
AnyAAM = 264241152, -- IR_AAM + SAR_AAM + AR_AAM + SRAAM + MRAAM + LRAAM
}
ENUMS.WeaponType.Torpedo={
-- Torpedo
Torpedo = 4294967296,
}
ENUMS.WeaponType.Any={
-- General combinations
Weapon = 3221225470, -- Any Weapon (AnyBomb + AnyRocket + AnyMissile + Cannons)
AG = 2956984318, -- Any Air-To-Ground Weapon
AA = 264241152, -- Any Air-To-Air Weapon
Unguided = 2952822768, -- Any Unguided Weapon
Guided = 268402702, -- Any Guided Weapon
}
--- Mission tasks.
-- @type ENUMS.MissionTask
-- @field #string NOTHING No special task. Group can perform the minimal tasks: Orbit, Refuelling, Follow and Aerobatics.
@@ -173,7 +262,7 @@ ENUMS.MissionTask={
TRANSPORT="Transport",
}
--- Formations (new). See the [Formations](https://wiki.hoggitworld.com/view/DCS_enum_formation) on Hoggit wiki.
--- Formations (new). See the [Formations](https://wiki.hoggitworld.com/view/DCS_enum_formation) on hoggit wiki.
-- @type ENUMS.Formation
ENUMS.Formation={}
ENUMS.Formation.FixedWing={}
@@ -216,23 +305,23 @@ ENUMS.Formation.FixedWing.FighterVic.Close = 917505
ENUMS.Formation.FixedWing.FighterVic.Open = 917506
ENUMS.Formation.RotaryWing={}
ENUMS.Formation.RotaryWing.Column={}
ENUMS.Formation.RotaryWing.Column.D70 = 720896
ENUMS.Formation.RotaryWing.Column.D70=720896
ENUMS.Formation.RotaryWing.Wedge={}
ENUMS.Formation.RotaryWing.Wedge.D70 = 8
ENUMS.Formation.RotaryWing.Wedge.D70=8
ENUMS.Formation.RotaryWing.FrontRight={}
ENUMS.Formation.RotaryWing.FrontRight.D300 = 655361
ENUMS.Formation.RotaryWing.FrontRight.D600 = 655362
ENUMS.Formation.RotaryWing.FrontRight.D300=655361
ENUMS.Formation.RotaryWing.FrontRight.D600=655362
ENUMS.Formation.RotaryWing.FrontLeft={}
ENUMS.Formation.RotaryWing.FrontLeft.D300 = 655617
ENUMS.Formation.RotaryWing.FrontLeft.D600 = 655618
ENUMS.Formation.RotaryWing.FrontLeft.D300=655617
ENUMS.Formation.RotaryWing.FrontLeft.D600=655618
ENUMS.Formation.RotaryWing.EchelonRight={}
ENUMS.Formation.RotaryWing.EchelonRight.D70 = 589825
ENUMS.Formation.RotaryWing.EchelonRight.D300 = 589826
ENUMS.Formation.RotaryWing.EchelonRight.D600 = 589827
ENUMS.Formation.RotaryWing.EchelonRight.D70 =589825
ENUMS.Formation.RotaryWing.EchelonRight.D300=589826
ENUMS.Formation.RotaryWing.EchelonRight.D600=589827
ENUMS.Formation.RotaryWing.EchelonLeft={}
ENUMS.Formation.RotaryWing.EchelonLeft.D70 = 590081
ENUMS.Formation.RotaryWing.EchelonLeft.D300 = 590082
ENUMS.Formation.RotaryWing.EchelonLeft.D600 = 590083
ENUMS.Formation.RotaryWing.EchelonLeft.D70 =590081
ENUMS.Formation.RotaryWing.EchelonLeft.D300=590082
ENUMS.Formation.RotaryWing.EchelonLeft.D600=590083
ENUMS.Formation.Vehicle={}
ENUMS.Formation.Vehicle.Vee="Vee"
ENUMS.Formation.Vehicle.EchelonRight="EchelonR"
@@ -244,34 +333,34 @@ ENUMS.Formation.Vehicle.Cone="Cone"
ENUMS.Formation.Vehicle.Diamond="Diamond"
--- Formations (old). The old format is a simplified version of the new formation enums, which allow more sophisticated settings.
-- See the [Formations](https://wiki.hoggitworld.com/view/DCS_enum_formation) on Hoggit wiki.
-- See the [Formations](https://wiki.hoggitworld.com/view/DCS_enum_formation) on hoggit wiki.
-- @type ENUMS.FormationOld
ENUMS.FormationOld={}
ENUMS.FormationOld.FixedWing={}
ENUMS.FormationOld.FixedWing.LineAbreast = 1
ENUMS.FormationOld.FixedWing.Trail = 2
ENUMS.FormationOld.FixedWing.Wedge = 3
ENUMS.FormationOld.FixedWing.EchelonRight = 4
ENUMS.FormationOld.FixedWing.EchelonLeft = 5
ENUMS.FormationOld.FixedWing.FingerFour = 6
ENUMS.FormationOld.FixedWing.SpreadFour = 7
ENUMS.FormationOld.FixedWing.BomberElement = 12
ENUMS.FormationOld.FixedWing.BomberElementHeight = 13
ENUMS.FormationOld.FixedWing.FighterVic = 14
ENUMS.FormationOld.FixedWing.LineAbreast=1
ENUMS.FormationOld.FixedWing.Trail=2
ENUMS.FormationOld.FixedWing.Wedge=3
ENUMS.FormationOld.FixedWing.EchelonRight=4
ENUMS.FormationOld.FixedWing.EchelonLeft=5
ENUMS.FormationOld.FixedWing.FingerFour=6
ENUMS.FormationOld.FixedWing.SpreadFour=7
ENUMS.FormationOld.FixedWing.BomberElement=12
ENUMS.FormationOld.FixedWing.BomberElementHeight=13
ENUMS.FormationOld.FixedWing.FighterVic=14
ENUMS.FormationOld.RotaryWing={}
ENUMS.FormationOld.RotaryWing.Wedge = 8
ENUMS.FormationOld.RotaryWing.Echelon = 9
ENUMS.FormationOld.RotaryWing.Front = 10
ENUMS.FormationOld.RotaryWing.Column = 11
ENUMS.FormationOld.RotaryWing.Wedge=8
ENUMS.FormationOld.RotaryWing.Echelon=9
ENUMS.FormationOld.RotaryWing.Front=10
ENUMS.FormationOld.RotaryWing.Column=11
--- Morse Code. See the [Wikipedia](https://en.wikipedia.org/wiki/Morse_code).
--
--
-- * Short pulse "*"
-- * Long pulse "-"
--
--
-- Pulses are separated by a blank character " ".
--
--
-- @type ENUMS.Morse
ENUMS.Morse={}
ENUMS.Morse.A="* -"
@@ -313,9 +402,9 @@ ENUMS.Morse.N0="- - - - -"
ENUMS.Morse[" "]=" "
--- ISO (639-1) 2-letter Language Codes. See the [Wikipedia](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).
--
--
-- @type ENUMS.ISOLang
ENUMS.ISOLang =
ENUMS.ISOLang =
{
Arabic = 'AR',
Chinese = 'ZH',
@@ -329,7 +418,7 @@ ENUMS.ISOLang =
}
--- Phonetic Alphabet (NATO). See the [Wikipedia](https://en.wikipedia.org/wiki/NATO_phonetic_alphabet).
--
--
-- @type ENUMS.Phonetic
ENUMS.Phonetic =
{
@@ -359,4 +448,114 @@ ENUMS.Phonetic =
X = 'Xray',
Y = 'Yankee',
Z = 'Zulu',
}
}
--- Reporting Names (NATO). See the [Wikipedia](https://en.wikipedia.org/wiki/List_of_NATO_reporting_names_for_fighter_aircraft).
-- DCS known aircraft types
--
-- @type ENUMS.ReportingName
ENUMS.ReportingName =
{
NATO = {
-- Fighters
Dragon = "JF-17", -- China, correctly Fierce Dragon, Thunder for PAC
Fagot = "MiG-15",
Farmer = "MiG-19", -- Shenyang J-6 and Mikoyan-Gurevich MiG-19
Felon = "Su-57",
Fencer = "Su-24",
Fishbed = "MiG-21",
Fitter = "Su-17", -- Sukhoi Su-7 and Su-17/Su-20/Su-22
Flogger = "MiG-23", --and MiG-27
Flogger_D = "MiG-27", --and MiG-23
Flagon = "Su-15",
Foxbat = "MiG-25",
Fulcrum = "MiG-29",
Foxhound = "MiG-31",
Flanker = "Su-27", -- Sukhoi Su-27/Su-30/Su-33/Su-35/Su-37 and Shenyang J-11/J-15/J-16
Flanker_C = "Su-30",
Flanker_E = "Su-35",
Flanker_F = "Su-37",
Flanker_L = "J-11A",
Firebird = "J-10",
Sea_Flanker = "Su-33",
Fullback = "Su-34", -- also Su-32
Frogfoot = "Su-25",
Tomcat = "F-14", -- Iran
Mirage = "Mirage", -- various non-NATO
Codling = "Yak-40",
Maya = "L-39",
-- Fighters US/NATO
Warthog = "A-10",
--Mosquito = "A-20",
Skyhawk = "A-4E",
Viggen = "AJS37",
Harrier = "AV-8B",
Spirit = "B-2",
Aviojet = "C-101",
Nighthawk = "F-117A",
Eagle = "F-15C",
Mudhen = "F-15E",
Viper = "F-16",
Phantom = "F-4E",
Tiger = "F-5", -- was thinking to name this MiG-25 ;)
Sabre = "F-86",
Hornet = "A-18", -- avoiding the slash
Hawk = "Hawk",
Albatros = "L-39",
Goshawk = "T-45",
Starfighter = "F-104",
Tornado = "Tornado",
-- Transport / Bomber / Others
Atlas = "A400",
Lancer = "B1-B",
Stratofortress = "B-52H",
Hercules = "C-130",
Super_Hercules = "Hercules",
Globemaster = "C-17",
Greyhound = "C-2A",
Galaxy = "C-5",
Hawkeye = "E-2D",
Sentry = "E-3A",
Stratotanker = "KC-135",
Extender = "KC-10",
Orion = "P-3C",
Viking = "S-3B",
Osprey = "V-22",
-- Bomber Rus
Badger = "H6-J",
Bear_J = "Tu-142", -- also Tu-95
Bear = "Tu-95", -- also Tu-142
Blinder = "Tu-22",
Blackjack = "Tu-160",
-- AIC / Transport / Other
Clank = "An-30",
Curl = "An-26",
Candid = "IL-76",
Midas = "IL-78",
Mainstay = "A-50",
Mainring = "KJ-2000", -- A-50 China
Yak = "Yak-52",
-- Helos
Helix = "Ka-27",
Shark = "Ka-50",
Hind = "Mi-24",
Halo = "Mi-26",
Hip = "Mi-8",
Havoc = "Mi-28",
Gazelle = "SA342",
-- Helos US
Huey = "UH-1H",
Cobra = "AH-1",
Apache = "AH-64",
Chinook = "CH-47",
Sea_Stallion = "CH-53",
Kiowa = "OH-58",
Seahawk = "SH-60",
Blackhawk = "UH-60",
Sea_King = "S-61",
-- Drones
UCAV = "WingLoong",
Reaper = "MQ-9",
Predator = "MQ-1A",
}
}

View File

@@ -0,0 +1,773 @@
--- **UTILS** - ClassicFiFo Stack.
--
-- ===
--
-- ## Main Features:
--
-- * Build a simple multi-purpose FiFo (First-In, First-Out) stack for generic data.
-- * [Wikipedia](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics)
--
-- ===
--
-- ### Author: **applevangelist**
-- @module Utils.FiFo
-- @image MOOSE.JPG
-- Date: April 2022
do
--- FIFO class.
-- @type FIFO
-- @field #string ClassName Name of the class.
-- @field #string lid Class id string for output to DCS log file.
-- @field #string version Version of FiFo
-- @field #number counter
-- @field #number pointer
-- @field #table stackbypointer
-- @field #table stackbyid
-- @extends Core.Base#BASE
---
-- @type FIFO.IDEntry
-- @field #number pointer
-- @field #table data
-- @field #table uniqueID
---
-- @field #FIFO
FIFO = {
ClassName = "FIFO",
lid = "",
version = "0.0.5",
counter = 0,
pointer = 0,
stackbypointer = {},
stackbyid = {}
}
--- Instantiate a new FIFO Stack
-- @param #FIFO self
-- @return #FIFO self
function FIFO:New()
-- Inherit everything from BASE class.
local self=BASE:Inherit(self, BASE:New())
self.pointer = 0
self.counter = 0
self.stackbypointer = {}
self.stackbyid = {}
self.uniquecounter = 0
-- Set some string id for output to DCS.log file.
self.lid=string.format("%s (%s) | ", "FiFo", self.version)
self:T(self.lid .."Created.")
return self
end
--- Empty FIFO Stack
-- @param #FIFO self
-- @return #FIFO self
function FIFO:Clear()
self:T(self.lid.."Clear")
self.pointer = 0
self.counter = 0
self.stackbypointer = nil
self.stackbyid = nil
self.stackbypointer = {}
self.stackbyid = {}
self.uniquecounter = 0
return self
end
--- FIFO Push Object to Stack
-- @param #FIFO self
-- @param #table Object
-- @param #string UniqueID (optional) - will default to current pointer + 1. Note - if you intend to use `FIFO:GetIDStackSorted()` keep the UniqueID numerical!
-- @return #FIFO self
function FIFO:Push(Object,UniqueID)
self:T(self.lid.."Push")
self:T({Object,UniqueID})
self.pointer = self.pointer + 1
self.counter = self.counter + 1
local uniID = UniqueID
if not UniqueID then
self.uniquecounter = self.uniquecounter + 1
uniID = self.uniquecounter
end
self.stackbyid[uniID] = { pointer = self.pointer, data = Object, uniqueID = uniID }
self.stackbypointer[self.pointer] = { pointer = self.pointer, data = Object, uniqueID = uniID }
return self
end
--- FIFO Pull Object from Stack
-- @param #FIFO self
-- @return #table Object or nil if stack is empty
function FIFO:Pull()
self:T(self.lid.."Pull")
if self.counter == 0 then return nil end
--local object = self.stackbypointer[self.pointer].data
--self.stackbypointer[self.pointer] = nil
local object = self.stackbypointer[1].data
self.stackbypointer[1] = nil
self.counter = self.counter - 1
--self.pointer = self.pointer - 1
self:Flatten()
return object
end
--- FIFO Pull Object from Stack by Pointer
-- @param #FIFO self
-- @param #number Pointer
-- @return #table Object or nil if stack is empty
function FIFO:PullByPointer(Pointer)
self:T(self.lid.."PullByPointer " .. tostring(Pointer))
if self.counter == 0 then return nil end
local object = self.stackbypointer[Pointer] -- #FIFO.IDEntry
self.stackbypointer[Pointer] = nil
if object then self.stackbyid[object.uniqueID] = nil end
self.counter = self.counter - 1
self:Flatten()
if object then
return object.data
else
return nil
end
end
--- FIFO Read, not Pull, Object from Stack by Pointer
-- @param #FIFO self
-- @param #number Pointer
-- @return #table Object or nil if stack is empty or pointer does not exist
function FIFO:ReadByPointer(Pointer)
self:T(self.lid.."ReadByPointer " .. tostring(Pointer))
if self.counter == 0 or not Pointer or not self.stackbypointer[Pointer] then return nil end
local object = self.stackbypointer[Pointer] -- #FIFO.IDEntry
if object then
return object.data
else
return nil
end
end
--- FIFO Read, not Pull, Object from Stack by UniqueID
-- @param #FIFO self
-- @param #number UniqueID
-- @return #table Object data or nil if stack is empty or ID does not exist
function FIFO:ReadByID(UniqueID)
self:T(self.lid.."ReadByID " .. tostring(UniqueID))
if self.counter == 0 or not UniqueID or not self.stackbyid[UniqueID] then return nil end
local object = self.stackbyid[UniqueID] -- #FIFO.IDEntry
if object then
return object.data
else
return nil
end
end
--- FIFO Pull Object from Stack by UniqueID
-- @param #FIFO self
-- @param #tableUniqueID
-- @return #table Object or nil if stack is empty
function FIFO:PullByID(UniqueID)
self:T(self.lid.."PullByID " .. tostring(UniqueID))
if self.counter == 0 then return nil end
local object = self.stackbyid[UniqueID] -- #FIFO.IDEntry
--self.stackbyid[UniqueID] = nil
if object then
return self:PullByPointer(object.pointer)
else
return nil
end
end
--- FIFO Housekeeping
-- @param #FIFO self
-- @return #FIFO self
function FIFO:Flatten()
self:T(self.lid.."Flatten")
-- rebuild stacks
local pointerstack = {}
local idstack = {}
local counter = 0
for _ID,_entry in pairs(self.stackbypointer) do
counter = counter + 1
pointerstack[counter] = { pointer = counter, data = _entry.data, uniqueID = _entry.uniqueID}
end
for _ID,_entry in pairs(pointerstack) do
idstack[_entry.uniqueID] = { pointer = _entry.pointer , data = _entry.data, uniqueID = _entry.uniqueID}
end
self.stackbypointer = nil
self.stackbypointer = pointerstack
self.stackbyid = nil
self.stackbyid = idstack
self.counter = counter
self.pointer = counter
return self
end
--- FIFO Check Stack is empty
-- @param #FIFO self
-- @return #boolean empty
function FIFO:IsEmpty()
self:T(self.lid.."IsEmpty")
return self.counter == 0 and true or false
end
--- FIFO Get stack size
-- @param #FIFO self
-- @return #number size
function FIFO:GetSize()
self:T(self.lid.."GetSize")
return self.counter
end
--- FIFO Get stack size
-- @param #FIFO self
-- @return #number size
function FIFO:Count()
self:T(self.lid.."Count")
return self.counter
end
--- FIFO Check Stack is NOT empty
-- @param #FIFO self
-- @return #boolean notempty
function FIFO:IsNotEmpty()
self:T(self.lid.."IsNotEmpty")
return not self:IsEmpty()
end
--- FIFO Get the data stack by pointer
-- @param #FIFO self
-- @return #table Table of #FIFO.IDEntry entries
function FIFO:GetPointerStack()
self:T(self.lid.."GetPointerStack")
return self.stackbypointer
end
--- FIFO Check if a certain UniqeID exists
-- @param #FIFO self
-- @return #boolean exists
function FIFO:HasUniqueID(UniqueID)
self:T(self.lid.."HasUniqueID")
if self.stackbyid[UniqueID] ~= nil then
return true
else
return false
end
end
--- FIFO Get the data stack by UniqueID
-- @param #FIFO self
-- @return #table Table of #FIFO.IDEntry entries
function FIFO:GetIDStack()
self:T(self.lid.."GetIDStack")
return self.stackbyid
end
--- FIFO Get table of UniqueIDs sorted smallest to largest
-- @param #FIFO self
-- @return #table Table with index [1] to [n] of UniqueID entries
function FIFO:GetIDStackSorted()
self:T(self.lid.."GetIDStackSorted")
local stack = self:GetIDStack()
local idstack = {}
for _id,_entry in pairs(stack) do
idstack[#idstack+1] = _id
self:T({"pre",_id})
end
local function sortID(a, b)
return a < b
end
table.sort(idstack)
return idstack
end
--- FIFO Get table of data entries
-- @param #FIFO self
-- @return #table Raw table indexed [1] to [n] of object entries - might be empty!
function FIFO:GetDataTable()
self:T(self.lid.."GetDataTable")
local datatable = {}
for _,_entry in pairs(self.stackbypointer) do
datatable[#datatable+1] = _entry.data
end
return datatable
end
--- FIFO Get sorted table of data entries by UniqueIDs (must be numerical UniqueIDs only!)
-- @param #FIFO self
-- @return #table Table indexed [1] to [n] of sorted object entries - might be empty!
function FIFO:GetSortedDataTable()
self:T(self.lid.."GetSortedDataTable")
local datatable = {}
local idtablesorted = self:GetIDStackSorted()
for _,_entry in pairs(idtablesorted) do
datatable[#datatable+1] = self:ReadByID(_entry)
end
return datatable
end
--- Iterate the FIFO and call an iterator function for the given FIFO data, providing the object for each element of the stack and optional parameters.
-- @param #FIFO self
-- @param #function IteratorFunction The function that will be called.
-- @param #table Arg (Optional) Further Arguments of the IteratorFunction.
-- @param #function Function (Optional) A function returning a #boolean true/false. Only if true, the IteratorFunction is called.
-- @param #table FunctionArguments (Optional) Function arguments.
-- @return #FIFO self
function FIFO:ForEach( IteratorFunction, Arg, Function, FunctionArguments )
self:T(self.lid.."ForEach")
local Set = self:GetPointerStack() or {}
Arg = Arg or {}
local function CoRoutine()
local Count = 0
for ObjectID, ObjectData in pairs( Set ) do
local Object = ObjectData.data
self:T( {Object} )
if Function then
if Function( unpack( FunctionArguments or {} ), Object ) == true then
IteratorFunction( Object, unpack( Arg ) )
end
else
IteratorFunction( Object, unpack( Arg ) )
end
Count = Count + 1
end
return true
end
local co = CoRoutine
local function Schedule()
local status, res = co()
self:T( { status, res } )
if status == false then
error( res )
end
if res == false then
return true -- resume next time the loop
end
return false
end
Schedule()
return self
end
--- FIFO Print stacks to dcs.log
-- @param #FIFO self
-- @return #FIFO self
function FIFO:Flush()
self:T(self.lid.."FiFo Flush")
self:I("FIFO Flushing Stack by Pointer")
for _id,_data in pairs (self.stackbypointer) do
local data = _data -- #FIFO.IDEntry
self:I(string.format("Pointer: %s | Entry: Number = %s Data = %s UniqueID = %s",tostring(_id),tostring(data.pointer),tostring(data.data),tostring(data.uniqueID)))
end
self:I("FIFO Flushing Stack by ID")
for _id,_data in pairs (self.stackbyid) do
local data = _data -- #FIFO.IDEntry
self:I(string.format("ID: %s | Entry: Number = %s Data = %s UniqueID = %s",tostring(_id),tostring(data.pointer),tostring(data.data),tostring(data.uniqueID)))
end
self:I("Counter = " .. self.counter)
self:I("Pointer = ".. self.pointer)
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- End FIFO
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- LIFO
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
do
--- **UTILS** - LiFo Stack.
--
-- **Main Features:**
--
-- * Build a simple multi-purpose LiFo (Last-In, First-Out) stack for generic data.
--
-- ===
--
-- ### Author: **applevangelist**
--- LIFO class.
-- @type LIFO
-- @field #string ClassName Name of the class.
-- @field #string lid Class id string for output to DCS log file.
-- @field #string version Version of LiFo
-- @field #number counter
-- @field #number pointer
-- @field #table stackbypointer
-- @field #table stackbyid
-- @extends Core.Base#BASE
---
-- @type LIFO.IDEntry
-- @field #number pointer
-- @field #table data
-- @field #table uniqueID
---
-- @field #LIFO
LIFO = {
ClassName = "LIFO",
lid = "",
version = "0.0.5",
counter = 0,
pointer = 0,
stackbypointer = {},
stackbyid = {}
}
--- Instantiate a new LIFO Stack
-- @param #LIFO self
-- @return #LIFO self
function LIFO:New()
-- Inherit everything from BASE class.
local self=BASE:Inherit(self, BASE:New())
self.pointer = 0
self.counter = 0
self.uniquecounter = 0
self.stackbypointer = {}
self.stackbyid = {}
-- Set some string id for output to DCS.log file.
self.lid=string.format("%s (%s) | ", "LiFo", self.version)
self:T(self.lid .."Created.")
return self
end
--- Empty LIFO Stack
-- @param #LIFO self
-- @return #LIFO self
function LIFO:Clear()
self:T(self.lid.."Clear")
self.pointer = 0
self.counter = 0
self.stackbypointer = nil
self.stackbyid = nil
self.stackbypointer = {}
self.stackbyid = {}
self.uniquecounter = 0
return self
end
--- LIFO Push Object to Stack
-- @param #LIFO self
-- @param #table Object
-- @param #string UniqueID (optional) - will default to current pointer + 1
-- @return #LIFO self
function LIFO:Push(Object,UniqueID)
self:T(self.lid.."Push")
self:T({Object,UniqueID})
self.pointer = self.pointer + 1
self.counter = self.counter + 1
local uniID = UniqueID
if not UniqueID then
self.uniquecounter = self.uniquecounter + 1
uniID = self.uniquecounter
end
self.stackbyid[uniID] = { pointer = self.pointer, data = Object, uniqueID = uniID }
self.stackbypointer[self.pointer] = { pointer = self.pointer, data = Object, uniqueID = uniID }
return self
end
--- LIFO Pull Object from Stack
-- @param #LIFO self
-- @return #table Object or nil if stack is empty
function LIFO:Pull()
self:T(self.lid.."Pull")
if self.counter == 0 then return nil end
local object = self.stackbypointer[self.pointer].data
self.stackbypointer[self.pointer] = nil
--local object = self.stackbypointer[1].data
--self.stackbypointer[1] = nil
self.counter = self.counter - 1
self.pointer = self.pointer - 1
self:Flatten()
return object
end
--- LIFO Pull Object from Stack by Pointer
-- @param #LIFO self
-- @param #number Pointer
-- @return #table Object or nil if stack is empty
function LIFO:PullByPointer(Pointer)
self:T(self.lid.."PullByPointer " .. tostring(Pointer))
if self.counter == 0 then return nil end
local object = self.stackbypointer[Pointer] -- #FIFO.IDEntry
self.stackbypointer[Pointer] = nil
if object then self.stackbyid[object.uniqueID] = nil end
self.counter = self.counter - 1
self:Flatten()
if object then
return object.data
else
return nil
end
end
--- LIFO Read, not Pull, Object from Stack by Pointer
-- @param #LIFO self
-- @param #number Pointer
-- @return #table Object or nil if stack is empty or pointer does not exist
function LIFO:ReadByPointer(Pointer)
self:T(self.lid.."ReadByPointer " .. tostring(Pointer))
if self.counter == 0 or not Pointer or not self.stackbypointer[Pointer] then return nil end
local object = self.stackbypointer[Pointer] -- #LIFO.IDEntry
if object then
return object.data
else
return nil
end
end
--- LIFO Read, not Pull, Object from Stack by UniqueID
-- @param #LIFO self
-- @param #number UniqueID
-- @return #table Object or nil if stack is empty or ID does not exist
function LIFO:ReadByID(UniqueID)
self:T(self.lid.."ReadByID " .. tostring(UniqueID))
if self.counter == 0 or not UniqueID or not self.stackbyid[UniqueID] then return nil end
local object = self.stackbyid[UniqueID] -- #LIFO.IDEntry
if object then
return object.data
else
return nil
end
end
--- LIFO Pull Object from Stack by UniqueID
-- @param #LIFO self
-- @param #tableUniqueID
-- @return #table Object or nil if stack is empty
function LIFO:PullByID(UniqueID)
self:T(self.lid.."PullByID " .. tostring(UniqueID))
if self.counter == 0 then return nil end
local object = self.stackbyid[UniqueID] -- #LIFO.IDEntry
--self.stackbyid[UniqueID] = nil
if object then
return self:PullByPointer(object.pointer)
else
return nil
end
end
--- LIFO Housekeeping
-- @param #LIFO self
-- @return #LIFO self
function LIFO:Flatten()
self:T(self.lid.."Flatten")
-- rebuild stacks
local pointerstack = {}
local idstack = {}
local counter = 0
for _ID,_entry in pairs(self.stackbypointer) do
counter = counter + 1
pointerstack[counter] = { pointer = counter, data = _entry.data, uniqueID = _entry.uniqueID}
end
for _ID,_entry in pairs(pointerstack) do
idstack[_entry.uniqueID] = { pointer = _entry.pointer , data = _entry.data, uniqueID = _entry.uniqueID}
end
self.stackbypointer = nil
self.stackbypointer = pointerstack
self.stackbyid = nil
self.stackbyid = idstack
self.counter = counter
self.pointer = counter
return self
end
--- LIFO Check Stack is empty
-- @param #LIFO self
-- @return #boolean empty
function LIFO:IsEmpty()
self:T(self.lid.."IsEmpty")
return self.counter == 0 and true or false
end
--- LIFO Get stack size
-- @param #LIFO self
-- @return #number size
function LIFO:GetSize()
self:T(self.lid.."GetSize")
return self.counter
end
--- LIFO Get stack size
-- @param #LIFO self
-- @return #number size
function LIFO:Count()
self:T(self.lid.."Count")
return self.counter
end
--- LIFO Check Stack is NOT empty
-- @param #LIFO self
-- @return #boolean notempty
function LIFO:IsNotEmpty()
self:T(self.lid.."IsNotEmpty")
return not self:IsEmpty()
end
--- LIFO Get the data stack by pointer
-- @param #LIFO self
-- @return #table Table of #LIFO.IDEntry entries
function LIFO:GetPointerStack()
self:T(self.lid.."GetPointerStack")
return self.stackbypointer
end
--- LIFO Get the data stack by UniqueID
-- @param #LIFO self
-- @return #table Table of #LIFO.IDEntry entries
function LIFO:GetIDStack()
self:T(self.lid.."GetIDStack")
return self.stackbyid
end
--- LIFO Get table of UniqueIDs sorted smallest to largest
-- @param #LIFO self
-- @return #table Table of #LIFO.IDEntry entries
function LIFO:GetIDStackSorted()
self:T(self.lid.."GetIDStackSorted")
local stack = self:GetIDStack()
local idstack = {}
for _id,_entry in pairs(stack) do
idstack[#idstack+1] = _id
self:T({"pre",_id})
end
local function sortID(a, b)
return a < b
end
table.sort(idstack)
return idstack
end
--- LIFO Check if a certain UniqeID exists
-- @param #LIFO self
-- @return #boolean exists
function LIFO:HasUniqueID(UniqueID)
self:T(self.lid.."HasUniqueID")
return self.stackbyid[UniqueID] and true or false
end
--- LIFO Print stacks to dcs.log
-- @param #LIFO self
-- @return #LIFO self
function LIFO:Flush()
self:T(self.lid.."FiFo Flush")
self:I("LIFO Flushing Stack by Pointer")
for _id,_data in pairs (self.stackbypointer) do
local data = _data -- #LIFO.IDEntry
self:I(string.format("Pointer: %s | Entry: Number = %s Data = %s UniqueID = %s",tostring(_id),tostring(data.pointer),tostring(data.data),tostring(data.uniqueID)))
end
self:I("LIFO Flushing Stack by ID")
for _id,_data in pairs (self.stackbyid) do
local data = _data -- #LIFO.IDEntry
self:I(string.format("ID: %s | Entry: Number = %s Data = %s UniqueID = %s",tostring(_id),tostring(data.pointer),tostring(data.data),tostring(data.uniqueID)))
end
self:I("Counter = " .. self.counter)
self:I("Pointer = ".. self.pointer)
return self
end
--- LIFO Get table of data entries
-- @param #LIFO self
-- @return #table Raw table indexed [1] to [n] of object entries - might be empty!
function LIFO:GetDataTable()
self:T(self.lid.."GetDataTable")
local datatable = {}
for _,_entry in pairs(self.stackbypointer) do
datatable[#datatable+1] = _entry.data
end
return datatable
end
--- LIFO Get sorted table of data entries by UniqueIDs (must be numerical UniqueIDs only!)
-- @param #LIFO self
-- @return #table Table indexed [1] to [n] of sorted object entries - might be empty!
function LIFO:GetSortedDataTable()
self:T(self.lid.."GetSortedDataTable")
local datatable = {}
local idtablesorted = self:GetIDStackSorted()
for _,_entry in pairs(idtablesorted) do
datatable[#datatable+1] = self:ReadByID(_entry)
end
return datatable
end
--- Iterate the LIFO and call an iterator function for the given LIFO data, providing the object for each element of the stack and optional parameters.
-- @param #LIFO self
-- @param #function IteratorFunction The function that will be called.
-- @param #table Arg (Optional) Further Arguments of the IteratorFunction.
-- @param #function Function (Optional) A function returning a #boolean true/false. Only if true, the IteratorFunction is called.
-- @param #table FunctionArguments (Optional) Function arguments.
-- @return #LIFO self
function LIFO:ForEach( IteratorFunction, Arg, Function, FunctionArguments )
self:T(self.lid.."ForEach")
local Set = self:GetPointerStack() or {}
Arg = Arg or {}
local function CoRoutine()
local Count = 0
for ObjectID, ObjectData in pairs( Set ) do
local Object = ObjectData.data
self:T( {Object} )
if Function then
if Function( unpack( FunctionArguments or {} ), Object ) == true then
IteratorFunction( Object, unpack( Arg ) )
end
else
IteratorFunction( Object, unpack( Arg ) )
end
Count = Count + 1
end
return true
end
local co = CoRoutine
local function Schedule()
local status, res = co()
self:T( { status, res } )
if status == false then
error( res )
end
if res == false then
return true -- resume next time the loop
end
return false
end
Schedule()
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- End LIFO
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
end

File diff suppressed because it is too large Load Diff

View File

@@ -315,7 +315,10 @@ AIRBASE.PersianGulf = {
-- * AIRBASE.TheChannel.Lympne
-- * AIRBASE.TheChannel.Detling
-- * AIRBASE.TheChannel.High_Halden
--
-- * AIRBASE.TheChannel.Biggin_Hill
-- * AIRBASE.TheChannel.Eastchurch
-- * AIRBASE.TheChannel.Headcorn
--
-- @field TheChannel
AIRBASE.TheChannel = {
["Abbeville_Drucat"] = "Abbeville Drucat",
@@ -327,6 +330,9 @@ AIRBASE.TheChannel = {
["Lympne"] = "Lympne",
["Detling"] = "Detling",
["High_Halden"] = "High Halden",
["Biggin_Hill"] = "Biggin Hill",
["Eastchurch"] = "Eastchurch",
["Headcorn"] = "Headcorn",
}
--- Airbases of the Syria map:
@@ -345,7 +351,6 @@ AIRBASE.TheChannel = {
-- * AIRBASE.Syria.Wujah_Al_Hajar
-- * AIRBASE.Syria.Al_Dumayr
-- * AIRBASE.Syria.Gazipasa
-- * AIRBASE.Syria.Ru_Convoy_4
-- * AIRBASE.Syria.Hatay
-- * AIRBASE.Syria.Nicosia
-- * AIRBASE.Syria.Pinarbashi
@@ -363,7 +368,6 @@ AIRBASE.TheChannel = {
-- * AIRBASE.Syria.Akrotiri
-- * AIRBASE.Syria.Naqoura
-- * AIRBASE.Syria.Gaziantep
-- * AIRBASE.Syria.CVN_71
-- * AIRBASE.Syria.Sayqal
-- * AIRBASE.Syria.Tiyas
-- * AIRBASE.Syria.Shayrat
@@ -384,61 +388,82 @@ AIRBASE.TheChannel = {
-- * AIRBASE.Syria.Beirut_Rafic_Hariri
-- * AIRBASE.Syria.An_Nasiriyah
-- * AIRBASE.Syria.Abu_al_Duhur
-- * AIRBASE.Syria.At_Tanf
-- * AIRBASE.Syria.H3
-- * AIRBASE.Syria.H3_Northwest
-- * AIRBASE.Syria.H3_Southwest
-- * AIRBASE.Syria.Kharab_Ishk
-- * AIRBASE.Syria.Raj_al_Issa_East
-- * AIRBASE.Syria.Raj_al_Issa_West
-- * AIRBASE.Syria.Ruwayshid
-- * AIRBASE.Syria.Sanliurfa
-- * AIRBASE.Syria.Tal_Siman
--
-- @field Syria
AIRBASE.Syria = {
["Kuweires"] = "Kuweires",
["Marj_Ruhayyil"] = "Marj Ruhayyil",
["Kiryat_Shmona"] = "Kiryat Shmona",
["Marj_as_Sultan_North"] = "Marj as Sultan North",
["Eyn_Shemer"] = "Eyn Shemer",
["Incirlik"] = "Incirlik",
["Damascus"] = "Damascus",
["Bassel_Al_Assad"] = "Bassel Al-Assad",
["Rosh_Pina"] = "Rosh Pina",
["Aleppo"] = "Aleppo",
["Al_Qusayr"] = "Al Qusayr",
["Wujah_Al_Hajar"] = "Wujah Al Hajar",
["Al_Dumayr"] = "Al-Dumayr",
["Gazipasa"] = "Gazipasa",
["Ru_Convoy_4"] = "Ru Convoy-4",
["Hatay"] = "Hatay",
["Nicosia"] = "Nicosia",
["Pinarbashi"] = "Pinarbashi",
["Paphos"] = "Paphos",
["Kingsfield"] = "Kingsfield",
["Thalah"] = "Tha'lah",
["Haifa"] = "Haifa",
["Khalkhalah"] = "Khalkhalah",
["Megiddo"] = "Megiddo",
["Lakatamia"] = "Lakatamia",
["Rayak"] = "Rayak",
["Larnaca"] = "Larnaca",
["Mezzeh"] = "Mezzeh",
["Gecitkale"] = "Gecitkale",
["Akrotiri"] = "Akrotiri",
["Naqoura"] = "Naqoura",
["Gaziantep"] = "Gaziantep",
["Sayqal"] = "Sayqal",
["Tiyas"] = "Tiyas",
["Shayrat"] = "Shayrat",
["Taftanaz"] = "Taftanaz",
["H4"] = "H4",
["King_Hussein_Air_College"] = "King Hussein Air College",
["Rene_Mouawad"] = "Rene Mouawad",
["Jirah"] = "Jirah",
["Ramat_David"] = "Ramat David",
["Qabr_as_Sitt"] = "Qabr as Sitt",
["Minakh"] = "Minakh",
["Adana_Sakirpasa"] = "Adana Sakirpasa",
["Palmyra"] = "Palmyra",
["Hama"] = "Hama",
["Ercan"] = "Ercan",
["Marj_as_Sultan_South"] = "Marj as Sultan South",
["Tabqa"] = "Tabqa",
["Beirut_Rafic_Hariri"] = "Beirut-Rafic Hariri",
["An_Nasiriyah"] = "An Nasiriyah",
["Abu_al_Duhur"] = "Abu al-Duhur",
--@field Syria
AIRBASE.Syria={
["Kuweires"]="Kuweires",
["Marj_Ruhayyil"]="Marj Ruhayyil",
["Kiryat_Shmona"]="Kiryat Shmona",
["Marj_as_Sultan_North"]="Marj as Sultan North",
["Eyn_Shemer"]="Eyn Shemer",
["Incirlik"]="Incirlik",
["Damascus"]="Damascus",
["Bassel_Al_Assad"]="Bassel Al-Assad",
["Rosh_Pina"]="Rosh Pina",
["Aleppo"]="Aleppo",
["Al_Qusayr"]="Al Qusayr",
["Wujah_Al_Hajar"]="Wujah Al Hajar",
["Al_Dumayr"]="Al-Dumayr",
["Gazipasa"]="Gazipasa",
-- ["Ru_Convoy_4"]="Ru Convoy-4",
["Hatay"]="Hatay",
["Nicosia"]="Nicosia",
["Pinarbashi"]="Pinarbashi",
["Paphos"]="Paphos",
["Kingsfield"]="Kingsfield",
["Thalah"]="Tha'lah",
["Haifa"]="Haifa",
["Khalkhalah"]="Khalkhalah",
["Megiddo"]="Megiddo",
["Lakatamia"]="Lakatamia",
["Rayak"]="Rayak",
["Larnaca"]="Larnaca",
["Mezzeh"]="Mezzeh",
["Gecitkale"]="Gecitkale",
["Akrotiri"]="Akrotiri",
["Naqoura"]="Naqoura",
["Gaziantep"]="Gaziantep",
["Sayqal"]="Sayqal",
["Tiyas"]="Tiyas",
["Shayrat"]="Shayrat",
["Taftanaz"]="Taftanaz",
["H4"]="H4",
["King_Hussein_Air_College"]="King Hussein Air College",
["Rene_Mouawad"]="Rene Mouawad",
["Jirah"]="Jirah",
["Ramat_David"]="Ramat David",
["Qabr_as_Sitt"]="Qabr as Sitt",
["Minakh"]="Minakh",
["Adana_Sakirpasa"]="Adana Sakirpasa",
["Palmyra"]="Palmyra",
["Hama"]="Hama",
["Ercan"]="Ercan",
["Marj_as_Sultan_South"]="Marj as Sultan South",
["Tabqa"]="Tabqa",
["Beirut_Rafic_Hariri"]="Beirut-Rafic Hariri",
["An_Nasiriyah"]="An Nasiriyah",
["Abu_al_Duhur"]="Abu al-Duhur",
["At_Tanf"]="At Tanf",
["H3"]="H3",
["H3_Northwest"]="H3 Northwest",
["H3_Southwest"]="H3 Southwest",
["Kharab_Ishk"]="Kharab Ishk",
["Raj_al_Issa_East"]="Raj al Issa East",
["Raj_al_Issa_West"]="Raj al Issa West",
["Ruwayshid"]="Ruwayshid",
["Sanliurfa"]="Sanliurfa",
["Tal_Siman"]="Tal Siman",
["Deir_ez-Zor"] = "Deir ez-Zor",
}
--- Airbases of the Mariana Islands map:

View File

@@ -3770,3 +3770,44 @@ function POSITIONABLE:IsSubmarine()
return nil
end
--- Sets the controlled group to go at the specified speed in meters per second.
-- @param #CONTROLLABLE self
-- @param #number Speed Speed in meters per second.
-- @param #boolean Keep (Optional) When set to true, will maintain the speed on passing waypoints. If not present or false, the controlled group will return to the speed as defined by their route.
-- @return #CONTROLLABLE self
function CONTROLLABLE:SetSpeed(Speed, Keep)
self:F2( { self.ControllableName } )
-- Set default if not specified.
local speed = Speed or 5
local DCSControllable = self:GetDCSObject()
if DCSControllable then
local Controller = self:_GetController()
if Controller then
Controller:setSpeed(speed, Keep)
end
end
return self
end
--- [AIR] Sets the controlled aircraft group to fly at the specified altitude in meters.
-- @param #CONTROLLABLE self
-- @param #number Altitude Altitude in meters.
-- @param #boolean Keep (Optional) When set to true, will maintain the altitude on passing waypoints. If not present or false, the controlled group will return to the altitude as defined by their route.
-- @param #string AltType (Optional) Specifies the altitude type used. If nil, the altitude type of the current waypoint will be used. Accepted values are "BARO" and "RADIO".
-- @return #CONTROLLABLE self
function CONTROLLABLE:SetAltitude(Altitude, Keep, AltType)
self:F2( { self.ControllableName } )
-- Set default if not specified.
local altitude = Altitude or 1000
local DCSControllable = self:GetDCSObject()
if DCSControllable then
local Controller = self:_GetController()
if Controller then
if self:IsAir() then
Controller:setAltitude(altitude, Keep, AltType)
end
end
end
return self
end

View File

@@ -384,7 +384,7 @@ end
-- So all event listeners will catch the destroy event of this group for each unit in the group.
-- To raise these events, provide the `GenerateEvent` parameter.
-- @param #GROUP self
-- @param #boolean GenerateEvent If true, a crash or dead event for each unit is generated. If false, if no event is triggered. If nil, a RemoveUnit event is triggered.
-- @param #boolean GenerateEvent If true, a crash [AIR] or dead [GROUND] event for each unit is generated. If false, if no event is triggered. If nil, a RemoveUnit event is triggered.
-- @param #number delay Delay in seconds before despawning the group.
-- @usage
-- -- Air unit example: destroy the Helicopter and generate a S_EVENT_CRASH for each unit in the Helicopter group.
@@ -622,7 +622,7 @@ function GROUP:GetUnits()
local DCSGroup = self:GetDCSObject()
if DCSGroup then
local DCSUnits = DCSGroup:getUnits()
local DCSUnits = DCSGroup:getUnits() or {}
local Units = {}
for Index, UnitData in pairs( DCSUnits ) do
Units[#Units+1] = UNIT:Find( UnitData )
@@ -680,6 +680,30 @@ function GROUP:GetUnit( UnitNumber )
return nil
end
--- Check if an (air) group is a client or player slot. Information is retrieved from the group template.
-- @param #GROUP self
-- @return #boolean If true, group is associated with a client or player slot.
function GROUP:IsPlayer()
-- Get group.
-- local group=self:GetGroup()
-- Units of template group.
local units=self:GetTemplate().units
-- Get numbers.
for _,unit in pairs(units) do
-- Check if unit name matach and skill is Client or Player.
if unit.name==self:GetName() and (unit.skill=="Client" or unit.skill=="Player") then
return true
end
end
return false
end
--- Returns the DCS Unit with number UnitNumber.
-- If the underlying DCS Unit does not exist, the method will return nil. .
-- @param #GROUP self
@@ -765,8 +789,7 @@ end
--- Returns the average velocity Vec3 vector.
-- @param Wrapper.Group#GROUP self
-- @return DCS#Vec3 The velocity Vec3 vector
-- @return #nil The GROUP is not existing or alive.
-- @return DCS#Vec3 The velocity Vec3 vector or `#nil` if the GROUP is not existing or alive.
function GROUP:GetVelocityVec3()
self:F2( self.GroupName )
@@ -797,11 +820,19 @@ function GROUP:GetVelocityVec3()
return nil
end
--- Returns the average group altitude in meters.
-- @param Wrapper.Group#GROUP self
-- @param #boolean FromGround Measure from the ground or from sea level (ASL). Provide **true** for measuring from the ground (AGL). **false** or **nil** if you measure from sea level.
-- @return #number The altitude of the group or nil if is not existing or alive.
function GROUP:GetAltitude(FromGround)
self:F2( self.GroupName )
return self:GetHeight(FromGround)
end
--- Returns the average group height in meters.
-- @param Wrapper.Group#GROUP self
-- @param #boolean FromGround Measure from the ground or from sea level. Provide **true** for measuring from the ground. **false** or **nil** if you measure from sea level.
-- @return DCS#Vec3 The height of the group or nil if is not existing or alive.
-- @param #boolean FromGround Measure from the ground or from sea level (ASL). Provide **true** for measuring from the ground (AGL). **false** or **nil** if you measure from sea level.
-- @return #number The height of the group or nil if is not existing or alive.
function GROUP:GetHeight( FromGround )
self:F2( self.GroupName )
@@ -901,6 +932,24 @@ function GROUP:GetTypeName()
return nil
end
--- [AIRPLANE] Get the NATO reporting name (platform, e.g. "Flanker") of a GROUP (note - first unit the group). "Bogey" if not found. Currently airplanes only!
--@param #GROUP self
--@return #string NatoReportingName or "Bogey" if unknown.
function GROUP:GetNatoReportingName()
self:F2( self.GroupName )
local DCSGroup = self:GetDCSObject()
if DCSGroup then
local GroupTypeName = DCSGroup:getUnit(1):getTypeName()
self:T3( GroupTypeName )
return UTILS.GetReportingName(GroupTypeName)
end
return "Bogey"
end
--- Gets the player name of the group.
-- @param #GROUP self
-- @return #string The player name of the group.
@@ -994,24 +1043,32 @@ end
-- @return Core.Point#COORDINATE The COORDINATE of the GROUP.
function GROUP:GetCoordinate()
local FirstUnit = self:GetUnit(1)
local Units = self:GetUnits() or {}
if FirstUnit then
local FirstUnitCoordinate = FirstUnit:GetCoordinate()
return FirstUnitCoordinate
for _,_unit in pairs(Units) do
local FirstUnit = _unit -- Wrapper.Unit#UNIT
if FirstUnit then
local FirstUnitCoordinate = FirstUnit:GetCoordinate()
if FirstUnitCoordinate then
local Heading = self:GetHeading()
FirstUnitCoordinate.Heading = Heading
return FirstUnitCoordinate
end
end
end
BASE:E( { "Cannot GetCoordinate", Group = self, Alive = self:IsAlive() } )
return nil
end
--- Returns a random @{DCS#Vec3} vector (point in 3D of the UNIT within the mission) within a range around the first UNIT of the GROUP.
-- @param #GROUP self
-- @param #number Radius
-- @return DCS#Vec3 The random 3D point vector around the first UNIT of the GROUP.
-- @return #nil The GROUP is invalid or empty
-- @param #number Radius Radius in meters.
-- @return DCS#Vec3 The random 3D point vector around the first UNIT of the GROUP or #nil The GROUP is invalid or empty.
-- @usage
-- -- If Radius is ignored, returns the DCS#Vec3 of first UNIT of the GROUP
function GROUP:GetRandomVec3(Radius)
@@ -1032,8 +1089,7 @@ end
--- Returns the mean heading of every UNIT in the GROUP in degrees
-- @param #GROUP self
-- @return #number mean heading of the GROUP
-- @return #nil The first UNIT is not existing or alive.
-- @return #number Mean heading of the GROUP in degrees or #nil The first UNIT is not existing or alive.
function GROUP:GetHeading()
self:F2(self.GroupName)
@@ -1061,8 +1117,8 @@ end
--- Return the fuel state and unit reference for the unit with the least
-- amount of fuel in the group.
-- @param #GROUP self
-- @return #number The fuel state of the unit with the least amount of fuel
-- @return #Unit reference to #Unit object for further processing
-- @return #number The fuel state of the unit with the least amount of fuel.
-- @return Wrapper.Unit#UNIT reference to #Unit object for further processing.
function GROUP:GetFuelMin()
self:F3(self.ControllableName)
@@ -1181,13 +1237,14 @@ function GROUP:IsInZone( Zone )
for UnitID, UnitData in pairs(self:GetUnits()) do
local Unit = UnitData -- Wrapper.Unit#UNIT
-- Get 2D vector. That's all we need for the zone check.
local vec2=Unit:GetVec2()
local vec2 = nil
if Unit then
-- Get 2D vector. That's all we need for the zone check.
vec2=Unit:GetVec2()
end
if Zone:IsVec2InZone(vec2) then
if vec2 and Zone:IsVec2InZone(vec2) then
return true -- At least one unit is in the zone. That is enough.
else
-- This one is not but another could be.
end
end
@@ -2609,6 +2666,7 @@ function GROUP:GetSkill()
return skill
end
--- Get the unit in the group with the highest threat level, which is still alive.
-- @param #GROUP self
-- @return Wrapper.Unit#UNIT The most dangerous unit in the group.

View File

@@ -382,7 +382,8 @@ function POSITIONABLE:GetCoordinate()
local PositionableVec3 = self:GetVec3()
local coord = COORDINATE:NewFromVec3( PositionableVec3 )
local heading = self:GetHeading()
coord.Heading = heading
-- Return a new coordinate object.
return coord
@@ -1176,6 +1177,30 @@ function POSITIONABLE:MessageToClient( Message, Duration, Client, Name )
return nil
end
--- Send a message to a @{Wrapper.Unit}.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #POSITIONABLE self
-- @param #string Message The message text
-- @param DCS#Duration Duration The duration of the message.
-- @param Wrapper.Unit#UNIT MessageUnit The UNIT object receiving the message.
-- @param #string Name (optional) The Name of the sender. If not provided, the Name is the type of the Positionable.
function POSITIONABLE:MessageToUnit( Message, Duration, MessageUnit, Name )
self:F2( { Message, Duration } )
local DCSObject = self:GetDCSObject()
if DCSObject then
if DCSObject:isExist() then
if MessageUnit:IsAlive() then
self:GetMessage( Message, Duration, Name ):ToUnit( MessageUnit )
else
BASE:E( { "Message not sent to Unit; Unit is not alive...", Message = Message, MessageUnit = MessageUnit } )
end
else
BASE:E( { "Message not sent to Unit; Positionable is not alive ...", Message = Message, Positionable = self, MessageUnit = MessageUnit } )
end
end
end
--- Send a message to a @{Wrapper.Group}.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #POSITIONABLE self
@@ -1249,6 +1274,30 @@ function POSITIONABLE:MessageToSetGroup( Message, Duration, MessageSetGroup, Nam
return nil
end
--- Send a message to a @{Core.Set#SET_UNIT}.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #POSITIONABLE self
-- @param #string Message The message text
-- @param DCS#Duration Duration The duration of the message.
-- @param Core.Set#SET_UNIT MessageSetUnit The SET_UNIT collection receiving the message.
-- @param #string Name (optional) The Name of the sender. If not provided, the Name is the type of the Positionable.
function POSITIONABLE:MessageToSetUnit( Message, Duration, MessageSetUnit, Name )
self:F2( { Message, Duration } )
local DCSObject = self:GetDCSObject()
if DCSObject then
if DCSObject:isExist() then
MessageSetUnit:ForEachUnit(
function( MessageGroup )
self:GetMessage( Message, Duration, Name ):ToUnit( MessageGroup )
end
)
end
end
return nil
end
--- Send a message to the players in the @{Wrapper.Group}.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #POSITIONABLE self

View File

@@ -1,46 +1,52 @@
--- **Wrapper** -- STATIC wraps the DCS StaticObject class.
--
--
-- ===
--
--
-- ### Author: **FlightControl**
--
--
-- ### Contributions: **funkyfranky**
--
--
-- ===
--
--
-- @module Wrapper.Static
-- @image Wrapper_Static.JPG
--- @type STATIC
-- @extends Wrapper.Positionable#POSITIONABLE
--- Wrapper class to handle Static objects.
--
--
-- Note that Statics are almost the same as Units, but they don't have a controller.
-- The @{Wrapper.Static#STATIC} class is a wrapper class to handle the DCS Static objects:
--
--
-- * Wraps the DCS Static objects.
-- * Support all DCS Static APIs.
-- * Enhance with Static specific APIs not in the DCS API set.
--
--
-- ## STATIC reference methods
--
--
-- For each DCS Static will have a STATIC wrapper object (instance) within the _@{DATABASE} object.
-- This is done at the beginning of the mission (when the mission starts).
--
--
-- The STATIC class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference
-- using the Static Name.
--
--
-- Another thing to know is that STATIC objects do not "contain" the DCS Static object.
-- The STATIc methods will reference the DCS Static object by name when it is needed during API execution.
-- If the DCS Static object does not exist or is nil, the STATIC methods will return nil and log an exception in the DCS.log file.
--
--
-- The STATIc class provides the following functions to retrieve quickly the relevant STATIC instance:
--
--
-- * @{#STATIC.FindByName}(): Find a STATIC instance from the _DATABASE object using a DCS Static name.
--
-- IMPORTANT: ONE SHOULD NEVER SANITIZE these STATIC OBJECT REFERENCES! (make the STATIC object references nil).
--
--
-- IMPORTANT: ONE SHOULD NEVER SANATIZE these STATIC OBJECT REFERENCES! (make the STATIC object references nil).
--
-- @field #STATIC
STATIC = { ClassName = "STATIC" }
STATIC = {
ClassName = "STATIC",
}
--- Register a static object.
-- @param #STATIC self
@@ -52,6 +58,7 @@ function STATIC:Register( StaticName )
return self
end
--- Finds a STATIC from the _DATABASE using a DCSStatic object.
-- @param #STATIC self
-- @param DCS#StaticObject DCSStatic An existing DCS Static object reference.
@@ -76,13 +83,13 @@ function STATIC:FindByName( StaticName, RaiseError )
-- Set static name.
self.StaticName = StaticName
if StaticFound then
return StaticFound
end
if RaiseError == nil or RaiseError == true then
error( "STATIC not found for: " .. StaticName )
if RaiseError == nil or RaiseError == true then
error( "STATIC not found for: " .. StaticName )
end
return nil
@@ -90,39 +97,38 @@ end
--- Destroys the STATIC.
-- @param #STATIC self
-- @param #boolean GenerateEvent (Optional) true to generate a crash or dead event, false to not generate any event. `nil` (default) creates a remove event.
-- @return #nil The DCS StaticObject is not existing or alive.
--
-- @param #boolean GenerateEvent (Optional) true if you want to generate a crash or dead event for the static.
-- @return #nil The DCS StaticObject is not existing or alive.
-- @usage
-- -- Air static example: destroy the static Helicopter and generate a S_EVENT_CRASH.
-- Helicopter = STATIC:FindByName( "Helicopter" )
-- Helicopter:Destroy( true )
--
--
-- @usage
-- -- Ground static example: destroy the static Tank and generate a S_EVENT_DEAD.
-- Tanks = UNIT:FindByName( "Tank" )
-- Tanks:Destroy( true )
--
--
-- @usage
-- -- Ship static example: destroy the Ship silently.
-- Ship = STATIC:FindByName( "Ship" )
-- Ship:Destroy()
--
--
-- @usage
-- -- Destroy without event generation example.
-- Ship = STATIC:FindByName( "Boat" )
-- Ship:Destroy( false ) -- Don't generate any event upon destruction.
--
-- Ship:Destroy( false ) -- Don't generate an event upon destruction.
--
function STATIC:Destroy( GenerateEvent )
self:F2( self.ObjectName )
local DCSObject = self:GetDCSObject()
if DCSObject then
local StaticName = DCSObject:getName()
self:F( { StaticName = StaticName } )
if GenerateEvent and GenerateEvent == true then
if self:IsAir() then
self:CreateEventCrash( timer.getTime(), DCSObject )
@@ -134,7 +140,7 @@ function STATIC:Destroy( GenerateEvent )
else
self:CreateEventRemoveUnit( timer.getTime(), DCSObject )
end
DCSObject:destroy()
return true
end
@@ -142,16 +148,17 @@ function STATIC:Destroy( GenerateEvent )
return nil
end
--- Get DCS object of static of static.
-- @param #STATIC self
-- @return DCS static object
function STATIC:GetDCSObject()
local DCSStatic = StaticObject.getByName( self.StaticName )
if DCSStatic then
return DCSStatic
end
return nil
end
@@ -163,7 +170,7 @@ function STATIC:GetUnits()
local DCSStatic = self:GetDCSObject()
local Statics = {}
if DCSStatic then
Statics[1] = STATIC:Find( DCSStatic )
self:T3( Statics )
@@ -173,6 +180,7 @@ function STATIC:GetUnits()
return nil
end
--- Get threat level of static.
-- @param #STATIC self
-- @return #number Threat level 1.
@@ -186,62 +194,65 @@ end
-- @param Core.Point#COORDINATE Coordinate The coordinate where to spawn the new Static.
-- @param #number Heading The heading of the static respawn in degrees. Default is 0 deg.
-- @param #number Delay Delay in seconds before the static is spawned.
function STATIC:SpawnAt( Coordinate, Heading, Delay )
function STATIC:SpawnAt(Coordinate, Heading, Delay)
Heading = Heading or 0
Heading=Heading or 0
if Delay and Delay > 0 then
SCHEDULER:New( nil, self.SpawnAt, { self, Coordinate, Heading }, Delay )
if Delay and Delay>0 then
SCHEDULER:New(nil, self.SpawnAt, {self, Coordinate, Heading}, Delay)
else
local SpawnStatic = SPAWNSTATIC:NewFromStatic( self.StaticName )
local SpawnStatic=SPAWNSTATIC:NewFromStatic(self.StaticName)
SpawnStatic:SpawnFromPointVec2( Coordinate, Heading, self.StaticName )
end
return self
end
--- Respawn the @{Wrapper.Unit} at the same location with the same properties.
-- This is useful to respawn a cargo after it has been destroyed.
-- @param #STATIC self
-- @param DCS#country.id CountryID (Optional) The country ID used for spawning the new static. Default is same as currently.
-- @param #number Delay (Optional) Delay in seconds before static is respawned. Default now.
function STATIC:ReSpawn( CountryID, Delay )
function STATIC:ReSpawn(CountryID, Delay)
if Delay and Delay > 0 then
SCHEDULER:New( nil, self.ReSpawn, { self, CountryID }, Delay )
if Delay and Delay>0 then
SCHEDULER:New(nil, self.ReSpawn, {self, CountryID}, Delay)
else
CountryID = CountryID or self:GetCountry()
local SpawnStatic = SPAWNSTATIC:NewFromStatic( self.StaticName, CountryID )
SpawnStatic:Spawn( nil, self.StaticName )
CountryID=CountryID or self:GetCountry()
local SpawnStatic=SPAWNSTATIC:NewFromStatic(self.StaticName, CountryID)
SpawnStatic:Spawn(nil, self.StaticName)
end
return self
end
--- Respawn the @{Wrapper.Unit} at a defined Coordinate with an optional heading.
-- @param #STATIC self
-- @param Core.Point#COORDINATE Coordinate The coordinate where to spawn the new Static.
-- @param #number Heading (Optional) The heading of the static respawn in degrees. Default is the current heading.
-- @param #number Delay (Optional) Delay in seconds before static is respawned. Default is now.
function STATIC:ReSpawnAt( Coordinate, Heading, Delay )
-- @param #number Heading (Optional) The heading of the static respawn in degrees. Default the current heading.
-- @param #number Delay (Optional) Delay in seconds before static is respawned. Default now.
function STATIC:ReSpawnAt(Coordinate, Heading, Delay)
-- Heading=Heading or 0
--Heading=Heading or 0
if Delay and Delay > 0 then
SCHEDULER:New( nil, self.ReSpawnAt, { self, Coordinate, Heading }, Delay )
if Delay and Delay>0 then
SCHEDULER:New(nil, self.ReSpawnAt, {self, Coordinate, Heading}, Delay)
else
local SpawnStatic = SPAWNSTATIC:NewFromStatic( self.StaticName, self:GetCountry() )
SpawnStatic:SpawnFromCoordinate( Coordinate, Heading, self.StaticName )
local SpawnStatic=SPAWNSTATIC:NewFromStatic(self.StaticName, self:GetCountry())
SpawnStatic:SpawnFromCoordinate(Coordinate, Heading, self.StaticName)
end
return self
end

View File

@@ -88,8 +88,9 @@
--
-- @field #UNIT UNIT
UNIT = {
ClassName="UNIT",
UnitName=nil,
ClassName="UNIT",
UnitName=nil,
GroupName=nil,
}
@@ -102,7 +103,7 @@ UNIT = {
-- Registration.
--- Create a new UNIT from DCSUnit.
-- @param #UNIT self
-- @param #string UnitName The name of the DCS unit.
@@ -110,11 +111,17 @@ UNIT = {
function UNIT:Register( UnitName )
-- Inherit CONTROLLABLE.
local self = BASE:Inherit( self, CONTROLLABLE:New( UnitName ) )
local self = BASE:Inherit( self, CONTROLLABLE:New( UnitName ) ) --#UNIT
-- Set unit name.
self.UnitName = UnitName
local unit=Unit.getByName(self.UnitName)
if unit then
self.GroupName=unit:getGroup():getName()
end
-- Set event prio.
self:SetEventPriority( 3 )
@@ -168,6 +175,9 @@ function UNIT:GetDCSObject()
return nil
end
--- Respawn the @{Wrapper.Unit} using a (tweaked) template of the parent Group.
--
-- This function will:
@@ -260,6 +270,8 @@ function UNIT:ReSpawnAt( Coordinate, Heading )
_DATABASE:Spawn( SpawnGroupTemplate )
end
--- Returns if the unit is activated.
-- @param #UNIT self
-- @return #boolean `true` if Unit is activated. `nil` The DCS Unit is not existing or alive.
@@ -296,6 +308,8 @@ function UNIT:IsAlive()
return nil
end
--- Returns the Unit's callsign - the localized string.
-- @param #UNIT self
-- @return #string The Callsign of the Unit.
@@ -401,6 +415,17 @@ function UNIT:GetClient()
return nil
end
--- [AIRPLANE] Get the NATO reporting name of a UNIT. Currently airplanes only!
--@param #UNIT self
--@return #string NatoReportingName or "Bogey" if unknown.
function UNIT:GetNatoReportingName()
local typename = self:GetTypeName()
return UTILS.GetReportingName(typename)
end
--- Returns the unit's number in the group.
-- The number is the same number the unit has in ME.
-- It may not be changed during the mission.
@@ -517,6 +542,63 @@ function UNIT:IsTanker()
return tanker, system
end
--- Check if the unit can supply ammo. Currently, we have
--
-- * M 818
-- * Ural-375
-- * ZIL-135
--
-- This list needs to be extended, if DCS adds other units capable of supplying ammo.
--
-- @param #UNIT self
-- @return #boolean If `true`, unit can supply ammo.
function UNIT:IsAmmoSupply()
-- Type name is the only thing we can check. There is no attribute (Sep. 2021) which would tell us.
local typename=self:GetTypeName()
if typename=="M 818" then
-- Blue ammo truck.
return true
elseif typename=="Ural-375" then
-- Red ammo truck.
return true
elseif typename=="ZIL-135" then
-- Red ammo truck. Checked that it can also provide ammo.
return true
end
return false
end
--- Check if the unit can supply fuel. Currently, we have
--
-- * M978 HEMTT Tanker
-- * ATMZ-5
-- * ATMZ-10
-- * ATZ-5
--
-- This list needs to be extended, if DCS adds other units capable of supplying fuel.
--
-- @param #UNIT self
-- @return #boolean If `true`, unit can supply fuel.
function UNIT:IsFuelSupply()
-- Type name is the only thing we can check. There is no attribute (Sep. 2021) which would tell us.
local typename=self:GetTypeName()
if typename=="M978 HEMTT Tanker" then
return true
elseif typename=="ATMZ-5" then
return true
elseif typename=="ATMZ-10" then
return true
elseif typename=="ATZ-5" then
return true
end
return false
end
--- Returns the unit's group if it exist and nil otherwise.
-- @param Wrapper.Unit#UNIT self
@@ -544,14 +626,14 @@ end
-- @return #string The name of the DCS Unit.
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetPrefix()
self:F2( self.UnitName )
self:F2( self.UnitName )
local DCSUnit = self:GetDCSObject()
if DCSUnit then
local UnitPrefix = string.match( self.UnitName, ".*#" ):sub( 1, -2 )
self:T3( UnitPrefix )
return UnitPrefix
local UnitPrefix = string.match( self.UnitName, ".*#" ):sub( 1, -2 )
self:T3( UnitPrefix )
return UnitPrefix
end
return nil
@@ -676,8 +758,6 @@ function UNIT:GetAmmunition()
return nammo, nshells, nrockets, nbombs, nmissiles
end
--- Returns the unit sensors.
-- @param #UNIT self
-- @return DCS#Unit.Sensors Table of sensors.
@@ -954,6 +1034,7 @@ end
-- @return #string Some text.
function UNIT:GetThreatLevel()
local ThreatLevel = 0
local ThreatText = ""
@@ -979,6 +1060,7 @@ function UNIT:GetThreatLevel()
"LR SAMs"
}
if Attributes["LR SAM"] then ThreatLevel = 10
elseif Attributes["MR SAM"] then ThreatLevel = 9
elseif Attributes["SR SAM"] and
@@ -992,7 +1074,7 @@ function UNIT:GetThreatLevel()
elseif ( Attributes["Tanks"] or Attributes["IFV"] ) and
not Attributes["ATGM"] then ThreatLevel = 3
elseif Attributes["Old Tanks"] or Attributes["APC"] or Attributes["Artillery"] then ThreatLevel = 2
elseif Attributes["Infantry"] then ThreatLevel = 1
elseif Attributes["Infantry"] or Attributes["EWR"] then ThreatLevel = 1
end
ThreatText = ThreatLevels[ThreatLevel+1]
@@ -1014,6 +1096,7 @@ function UNIT:GetThreatLevel()
"Fighter"
}
if Attributes["Fighters"] then ThreatLevel = 10
elseif Attributes["Multirole fighters"] then ThreatLevel = 9
elseif Attributes["Battleplanes"] then ThreatLevel = 8
@@ -1111,26 +1194,32 @@ end
-- @return true If the other DCS Unit is within the radius of the 2D point of the DCS Unit.
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:OtherUnitInRadius( AwaitUnit, Radius )
self:F2( { self.UnitName, AwaitUnit.UnitName, Radius } )
self:F2( { self.UnitName, AwaitUnit.UnitName, Radius } )
local DCSUnit = self:GetDCSObject()
if DCSUnit then
local UnitVec3 = self:GetVec3()
local AwaitUnitVec3 = AwaitUnit:GetVec3()
local UnitVec3 = self:GetVec3()
local AwaitUnitVec3 = AwaitUnit:GetVec3()
if (((UnitVec3.x - AwaitUnitVec3.x)^2 + (UnitVec3.z - AwaitUnitVec3.z)^2)^0.5 <= Radius) then
self:T3( "true" )
return true
else
self:T3( "false" )
return false
end
if (((UnitVec3.x - AwaitUnitVec3.x)^2 + (UnitVec3.z - AwaitUnitVec3.z)^2)^0.5 <= Radius) then
self:T3( "true" )
return true
else
self:T3( "false" )
return false
end
end
return nil
return nil
end
--- Returns if the unit is a friendly unit.
-- @param #UNIT self
-- @return #boolean IsFriendly evaluation result.

View File

@@ -5,6 +5,7 @@ Utilities/Enums.lua
Utilities/Profiler.lua
Utilities/Templates.lua
Utilities/STTS.lua
Utilities/FiFo.lua
Core/Base.lua
Core/Beacon.lua