Merge pull request #6 from FlightControl-Master/develop

Develop
This commit is contained in:
Tony Goodale 2021-05-01 15:40:23 -07:00 committed by GitHub
commit edcdc057e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 853 additions and 242 deletions

View File

@ -26,24 +26,25 @@ init:
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
install:
- cmd:
# Outcomment if lua environment invalidates and needs to be reinstalled, otherwise all will run from the cache.
# - call choco install 7zip.commandline
# - call choco install lua51
# - call choco install luarocks
# - call refreshenv
# - call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
# - cmd: PATH = %PATH%;C:\ProgramData\chocolatey\lib\luarocks\luarocks-2.4.3-win32\systree\bin
# - cmd: set LUA_PATH = %LUA_PATH%;C:\ProgramData\chocolatey\lib\luarocks\luarocks-2.4.3-win32\systree\share\lua\5.1\?.lua;C:\ProgramData\chocolatey\lib\luarocks\luarocks-2.4.3-win32\systree\share\lua\5.1\?\init.lua
# - cmd: set LUA_CPATH = %LUA_CPATH%;C:\ProgramData\chocolatey\lib\luarocks\luarocks-2.4.3-win32\systree\lib\lua\5.1\?.dll
# - call luarocks install luasrcdiet
# - call luarocks install checks
# - call luarocks install luadocumentor
# - call luarocks install luacheck
call choco install 7zip.commandline
call choco install lua51
call choco install luarocks
call refreshenv
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
cmd: PATH = %PATH%;C:\ProgramData\chocolatey\lib\luarocks\luarocks-2.4.3-win32\systree\bin
cmd: set LUA_PATH = %LUA_PATH%;C:\ProgramData\chocolatey\lib\luarocks\luarocks-2.4.3-win32\systree\share\lua\5.1\?.lua;C:\ProgramData\chocolatey\lib\luarocks\luarocks-2.4.3-win32\systree\share\lua\5.1\?\init.lua
cmd: set LUA_CPATH = %LUA_CPATH%;C:\ProgramData\chocolatey\lib\luarocks\luarocks-2.4.3-win32\systree\lib\lua\5.1\?.dll
call luarocks install luasrcdiet
call luarocks install checks
call luarocks install luadocumentor
call luarocks install luacheck
#cache:
# - C:\ProgramData\chocolatey\lib
# - C:\ProgramData\chocolatey\bin
cache:
C:\ProgramData\chocolatey\lib
C:\ProgramData\chocolatey\bin
@ -51,8 +52,9 @@ build_script:
- ps: |
if( $env:appveyor_repo_branch -eq 'master' -or $env:appveyor_repo_branch -eq 'develop' )
{
echo "Hello World!"
$apiUrl = 'https://ci.appveyor.com/api'
$token = 'qts80b5kpq0ooj4x6vvw'
$token = 'v2.6hcv3ige78kg3yvg4ge8'
$headers = @{
"Authorization" = "Bearer $token"
"Content-type" = "application/json"
@ -65,7 +67,7 @@ build_script:
if( $env:appveyor_repo_branch -eq 'master' -or $env:appveyor_repo_branch -eq 'develop' )
{
$apiUrl = 'https://ci.appveyor.com/api'
$token = 'qts80b5kpq0ooj4x6vvw'
$token = 'v2.6hcv3ige78kg3yvg4ge8'
$headers = @{
"Authorization" = "Bearer $token"
"Content-type" = "application/json"

2
.gitignore vendored
View File

@ -18,6 +18,8 @@ local.properties
# External tool builders
.externalToolBuilders/
# AppVeyor
.appveyor/
# CDT-specific
.cproject

54
.luacheckrc Normal file
View File

@ -0,0 +1,54 @@
ignore = {
"011", -- A syntax error.
"021", -- An invalid inline option.
"022", -- An unpaired inline push directive.
"023", -- An unpaired inline pop directive.
"111", -- Setting an undefined global variable.
"112", -- Mutating an undefined global variable.
"113", -- Accessing an undefined global variable.
"121", -- Setting a read-only global variable.
"122", -- Setting a read-only field of a global variable.
"131", -- Unused implicitly defined global variable.
"142", -- Setting an undefined field of a global variable.
"143", -- Accessing an undefined field of a global variable.
"211", -- Unused local variable.
"212", -- Unused argument.
"213", -- Unused loop variable.
"221", -- Local variable is accessed but never set.
"231", -- Local variable is set but never accessed.
"232", -- An argument is set but never accessed.
"233", -- Loop variable is set but never accessed.
"241", -- Local variable is mutated but never accessed.
"311", -- Value assigned to a local variable is unused.
"312", -- Value of an argument is unused.
"313", -- Value of a loop variable is unused.
"314", -- Value of a field in a table literal is unused.
"321", -- Accessing uninitialized local variable.
"331", -- Value assigned to a local variable is mutated but never accessed.
"341", -- Mutating uninitialized local variable.
"411", -- Redefining a local variable.
"412", -- Redefining an argument.
"413", -- Redefining a loop variable.
"421", -- Shadowing a local variable.
"422", -- Shadowing an argument.
"423", -- Shadowing a loop variable.
"431", -- Shadowing an upvalue.
"432", -- Shadowing an upvalue argument.
"433", -- Shadowing an upvalue loop variable.
"511", -- Unreachable code.
"512", -- Loop can be executed at most once.
"521", -- Unused label.
"531", -- Left-hand side of an assignment is too short.
"532", -- Left-hand side of an assignment is too long.
"541", -- An empty do end block.
"542", -- An empty if branch.
"551", -- An empty statement.
"561", -- Cyclomatic complexity of a function is too high.
"571", -- A numeric for loop goes from #(expr) down to 1 or less without negative step.
"611", -- A line consists of nothing but whitespace.
"612", -- A line contains trailing whitespace.
"613", -- Trailing whitespace in a string.
"614", -- Trailing whitespace in a comment.
"621", -- Inconsistent indentation (SPACE followed by TAB).
"631", -- Line is too long.
}

View File

@ -143,7 +143,7 @@ end
-- @return #AI_A2A_CAP
function AI_A2A_CAP:New( AICap, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageMinSpeed, EngageMaxSpeed, PatrolAltType )
return self:New2( AICap, EngageMinSpeed, EngageMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolZone, PatrolMinSpeed, PatrolMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolAltType, PatrolAltType )
return self:New2( AICap, EngageMinSpeed, EngageMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolAltType, PatrolZone, PatrolMinSpeed, PatrolMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolAltType )
end

View File

@ -190,7 +190,7 @@ do -- ACT_ROUTE
self:F( { ZoneName = ZoneName } )
local Zone = Zone -- Core.Zone#ZONE
local ZoneCoord = Zone:GetCoordinate()
local ZoneDistance = ZoneCoord:Get2DDistance( self.Coordinate )
local ZoneDistance = ZoneCoord:Get2DDistance( Coordinate )
self:F( { ShortestDistance, ShortestReferenceName } )
if ShortestDistance == 0 or ZoneDistance < ShortestDistance then
ShortestDistance = ZoneDistance

View File

@ -676,6 +676,37 @@ do -- Event Handling
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
--- Paratrooper landing.
-- @function [parent=#BASE] OnEventParatrooperLanding
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
--- Discard chair after ejection.
-- @function [parent=#BASE] OnEventDiscardChairAfterEjection
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
--- Weapon add. Fires when entering a mission per pylon with the name of the weapon (double pylons not counted, infinite wep reload not counted.
-- @function [parent=#BASE] OnEventParatrooperLanding
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
--- Trigger zone.
-- @function [parent=#BASE] OnEventTriggerZone
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
--- Landing quality mark.
-- @function [parent=#BASE] OnEventLandingQualityMark
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
--- BDA.
-- @function [parent=#BASE] OnEventBDA
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
--- Occurs when a player enters a slot and takes control of an aircraft.
-- **NOTE**: This is a workaround of a long standing DCS bug with the PLAYER_ENTER_UNIT event.
-- initiator : The unit that is being taken control of.

View File

@ -241,13 +241,20 @@ EVENTS = {
Score = world.event.S_EVENT_SCORE or -1,
UnitLost = world.event.S_EVENT_UNIT_LOST or -1,
LandingAfterEjection = world.event.S_EVENT_LANDING_AFTER_EJECTION or -1,
-- Added with DCS 2.7.0
ParatrooperLanding = world.event.S_EVENT_PARATROOPER_LENDING or -1,
DiscardChairAfterEjection = world.event.S_EVENT_DISCARD_CHAIR_AFTER_EJECTION or -1,
WeaponAdd = world.event.S_EVENT_WEAPON_ADD or -1,
TriggerZone = world.event.S_EVENT_TRIGGER_ZONE or -1,
LandingQualityMark = world.event.S_EVENT_LANDING_QUALITY_MARK or -1,
BDA = world.event.S_EVENT_BDA or -1,
}
--- The Event structure
-- Note that at the beginning of each field description, there is an indication which field will be populated depending on the object type involved in the Event:
--
-- * A (Object.Category.)UNIT : A UNIT object type is involved in the Event.
-- * A (Object.Category.)STATIC : A STATIC object type is involved in the Event.µ
-- * A (Object.Category.)STATIC : A STATIC object type is involved in the Event.
--
-- @type EVENTDATA
-- @field #number id The identifier of the event.
@ -522,6 +529,37 @@ local _EVENTMETA = {
Event = "OnEventLandingAfterEjection",
Text = "S_EVENT_LANDING_AFTER_EJECTION"
},
-- Added with DCS 2.7.0
[EVENTS.ParatrooperLanding] = {
Order = 1,
Event = "OnEventParatrooperLanding",
Text = "S_EVENT_PARATROOPER_LENDING"
},
[EVENTS.DiscardChairAfterEjection] = {
Order = 1,
Event = "OnEventDiscardChairAfterEjection",
Text = "S_EVENT_DISCARD_CHAIR_AFTER_EJECTION"
},
[EVENTS.WeaponAdd] = {
Order = 1,
Event = "OnEventWeaponAdd",
Text = "S_EVENT_WEAPON_ADD"
},
[EVENTS.TriggerZone] = {
Order = 1,
Event = "OnEventTriggerZone",
Text = "S_EVENT_TRIGGER_ZONE"
},
[EVENTS.LandingQualityMark] = {
Order = 1,
Event = "OnEventLandingQualityMark",
Text = "S_EVENT_LANDING_QUALITYMARK"
},
[EVENTS.BDA] = {
Order = 1,
Event = "OnEventBDA",
Text = "S_EVENT_BDA"
},
}
@ -1011,6 +1049,14 @@ function EVENT:onEvent( Event )
Event.IniCoalition = 0
Event.IniCategory = 0
Event.IniTypeName = "Ejected Pilot"
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))
Event.IniUnitName = Event.IniDCSUnitName
Event.IniCoalition = 0
Event.IniCategory = 0
Event.IniTypeName = "Ejection Seat"
else
Event.IniDCSUnit = Event.initiator
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
@ -1077,13 +1123,34 @@ function EVENT:onEvent( Event )
end
if Event.TgtObjectCategory == Object.Category.STATIC then
BASE:T({StaticTgtEvent = Event.id})
-- get base data
Event.TgtDCSUnit = Event.target
if Event.target:isExist() and Event.id ~= 33 then -- leave out ejected seat object
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
Event.TgtUnitName = Event.TgtDCSUnitName
Event.TgtUnit = STATIC:FindByName( Event.TgtDCSUnitName, false )
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
else
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.TgtUnitName = Event.TgtDCSUnitName
elseif Event.id == 33 then
Event.TgtTypeName = "Ejection Seat"
Event.TgtDCSUnitName = string.format("Ejection Seat ID %s", tostring(Event.IniDCSUnitName))
Event.TgtUnitName = Event.TgtDCSUnitName
else
Event.TgtTypeName = "Static"
end
end
end
if Event.TgtObjectCategory == Object.Category.SCENERY then

View File

@ -2034,6 +2034,62 @@ do -- COORDINATE
trigger.action.removeMark( MarkID )
end
--- Line to all.
-- Creates a line on the F10 map from one point to another.
-- @param #COORDINATE self
-- @param #COORDINATE Endpoint COORDIANTE to where the line is drawn.
-- @param #number Coalition Coalition: All=-1, Neutral=0, Red=1, Blue=2. Default -1=All.
-- @param #number LineType Line type: 0=No line, 1=Solid, 2=Dashed, 3=Dotted, 4=Dot dash, 5=Long dash, 6=Two dash. Default 1=Solid.
-- @param #table Color RGB color table {r, g, b}, e.g. {1,0,0} for red (default).
-- @param #number Alpha Transparency [0,1]. Default 1.
-- @param #boolean ReadOnly (Optional) Mark is readonly and cannot be removed by users. Default false.
-- @param #string Text (Optional) Text displayed when mark is added. Default none.
-- @return #number The resulting Mark ID which is a number.
function COORDINATE:LineToAll(Endpoint, Coalition, LineType, Color, Alpha, ReadOnly, Text)
local MarkID = UTILS.GetMarkID()
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
trigger.action.lineToAll(Coalition, MarkID, self:GetVec3(), vec3, Color, LineType, ReadOnly, Text or "")
return MarkID
end
--- Circle to all.
-- Creates a circle on the map with a given radius, color, fill color, and outline.
-- @param #COORDINATE self
-- @param #COORDINATE Center COORDIANTE of the center of the circle.
-- @param #numberr Radius Radius in meters. Default 1000 m.
-- @param #number Coalition Coalition: All=-1, Neutral=0, Red=1, Blue=2. Default -1=All.
-- @param #number LineType Line type: 0=No line, 1=Solid, 2=Dashed, 3=Dotted, 4=Dot dash, 5=Long dash, 6=Two dash. Default 1=Solid.
-- @param #table Color RGB color table {r, g, b}, e.g. {1,0,0} for red (default).
-- @param #number Alpha Transparency [0,1]. Default 1.
-- @param #table FillColor RGB color table {r, g, b}, e.g. {1,0,0} for red (default).
-- @param #number FillAlpha Transparency [0,1]. Default 0.5.
-- @param #boolean ReadOnly (Optional) Mark is readonly and cannot be removed by users. Default false.
-- @param #string Text (Optional) Text displayed when mark is added. Default none.
-- @return #number The resulting Mark ID which is a number.
function COORDINATE:CircleToAll(Radius, Coalition, LineType, Color, Alpha, FillColor, FillAlpha, ReadOnly, Text)
local MarkID = UTILS.GetMarkID()
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 {1,0,0}
FillColor[4]=FillAlpha or 0.5
trigger.action.circleToAll(Coalition, MarkID, vec3, Radius, Color, FillColor, LineType, ReadOnly, Text or "")
return MarkID
end
end -- Markings

View File

@ -1152,6 +1152,10 @@ do -- Unit
-- @param #Unit self
-- @return #Unit.Desc
--- GROUND - Switch on/off radar emissions
-- @function [parent=#Unit] enableEmission
-- @param #Unit self
-- @param #boolean switch
Unit = {} --#Unit
@ -1222,7 +1226,7 @@ do -- Group
-- @param #Group self
-- @return #number
--- Returns initial size of the group. If some of the units will be destroyed, initial size of the group will not be changed. Initial size limits the unitNumber parameter for Group.getUnit() function.
--- Returns initial size of the group. If some of the units will be destroyed, initial size of the group will not be changed; Initial size limits the unitNumber parameter for Group.getUnit() function.
-- @function [parent=#Group] getInitialSize
-- @param #Group self
-- @return #number
@ -1237,6 +1241,11 @@ do -- Group
-- @param #Group self
-- @return #Controller
--- GROUND - Switch on/off radar emissions
-- @function [parent=#Group] enableEmission
-- @param #Group self
-- @param #boolean switch
Group = {} --#Group
end -- Group

View File

@ -20,7 +20,7 @@
-- @module Functional.Mantis
-- @image Functional.Mantis.jpg
-- Date: Feb 2021
-- Date: Apr 2021
-------------------------------------------------------------------------
--- **MANTIS** class, extends #Core.Base#BASE
@ -51,6 +51,7 @@
-- @field #number adv_state Advanced mode state tracker
-- @field #boolean advAwacs Boolean switch to use Awacs as a separate detection stream
-- @field #number awacsrange Detection range of an optional Awacs unit
-- @field #boolean UseEmOnOff Decide if we are using Emissions on/off (true) or AlarmState red/green (default)
-- @field Functional.Shorad#SHORAD Shorad SHORAD Object, if available
-- @field #boolean ShoradLink If true, #MANTIS has #SHORAD enabled
-- @field #number ShoradTime Timer in seconds, how long #SHORAD will be active after a detection inside of the defense range
@ -190,6 +191,7 @@ MANTIS = {
ShoradLink = false,
ShoradTime = 600,
ShoradActDistance = 15000,
UseEmOnOff = true,
}
-----------------------------------------------------------------------
@ -206,6 +208,7 @@ do
--@param #string coaltion Coalition side of your setup, e.g. "blue", "red" or "neutral"
--@param #boolean dynamic Use constant (true) filtering or just filter once (false, default) (optional)
--@param #string awacs Group name of your Awacs (optional)
--@param #boolean EmOnOff Make MANTIS switch Emissions on and off instead of changing the alarm state between RED and GREEN (optional, deault true)
--@return #MANTIS self
--@usage Start up your MANTIS with a basic setting
--
@ -227,7 +230,7 @@ do
-- `mybluemantis = MANTIS:New("bluemantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs")`
-- `mybluemantis:Start()`
--
function MANTIS:New(name,samprefix,ewrprefix,hq,coaltion,dynamic,awacs)
function MANTIS:New(name,samprefix,ewrprefix,hq,coaltion,dynamic,awacs, EmOnOff)
-- DONE: Create some user functions for these
-- DONE: Make HQ useful
@ -260,6 +263,12 @@ do
self.ShoradLink = false
self.ShoradTime = 600
self.ShoradActDistance = 15000
-- TODO: add emissions on/off when available .... in 2 weeks
if EmOnOff then
if EmOnOff == false then
self.UseEmOnOff = false
end
end
if type(awacs) == "string" then
self.advAwacs = true
@ -299,7 +308,7 @@ do
end
-- @field #string version
self.version="0.3.7"
self.version="0.4.1"
self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
return self
@ -458,6 +467,13 @@ do
end
end
--- Set using Emissions on/off instead of changing alarm state
-- @param #MANTIS self
-- @param #boolean switch Decide if we are changing alarm state or Emission state
function MANTIS:SetUsingEmOnOff(switch)
self.UseEmOnOff = switch or false
end
--- [Internal] Function to check if HQ is alive
-- @param #MANTIS self
-- @return #boolean True if HQ is alive, else false
@ -701,7 +717,13 @@ do
--cycle through groups and set alarm state etc
for _i,_group in pairs (SAM_Grps) do
local group = _group
-- TODO: add emissions on/off
if self.UseEmOnOff then
group:EnableEmission(false)
--group:SetAIOff()
else
group:OptionAlarmStateGreen() -- AI off
end
group:SetOption(AI.Option.Ground.id.AC_ENGAGEMENT_RANGE_RESTRICTION,engagerange) --default engagement will be 75% of firing range
if group:IsGround() then
local grpname = group:GetName()
@ -804,7 +826,12 @@ do
local IsInZone, Distance = self:CheckObjectInZone(detset, samcoordinate)
if IsInZone then --check any target in zone
if samgroup:IsAlive() then
-- switch off SAM
-- switch on SAM
if self.UseEmOnOff then
-- TODO: add emissions on/off
--samgroup:SetAIOn()
samgroup:EnableEmission(true)
end
samgroup:OptionAlarmStateRed()
-- link in to SHORAD if available
-- DONE: Test integration fully
@ -822,7 +849,13 @@ do
else
if samgroup:IsAlive() then
-- switch off SAM
if self.UseEmOnOff then
-- TODO: add emissions on/off
samgroup:EnableEmission(false)
--samgroup:SetAIOff()
else
samgroup:OptionAlarmStateGreen()
end
--samgroup:OptionROEWeaponFree()
--samgroup:SetAIOn()
local text = string.format("SAM %s switched to alarm state GREEN!", name)
@ -857,6 +890,11 @@ do
local name = _data[1]
local samgroup = GROUP:FindByName(name)
if samgroup:IsAlive() then
if self.UseEmOnOff then
-- TODO: add emissions on/off
--samgroup:SetAIOn()
samgroup:EnableEmission(true)
end
samgroup:OptionAlarmStateRed()
end -- end alive
end -- end for loop

View File

@ -109,7 +109,7 @@ function SEAD:New( SEADGroupPrefixes )
end
self:HandleEvent( EVENTS.Shot )
self:I("*** SEAD - Started Version 0.2.5")
self:I("*** SEAD - Started Version 0.2.7")
return self
end
@ -205,15 +205,18 @@ function SEAD:OnEventShot( EventData )
SEADWeaponName == "weapons.missiles.AGM_84H" --AGM84 anti-radiation missiles fired
--]]
if self:_CheckHarms(SEADWeaponName) then
local _targetskill = "Random"
local _targetMimgroupName = "none"
local _evade = math.random (1,100) -- random number for chance of evading action
local _targetMim = EventData.Weapon:getTarget() -- Identify target
local _targetMimname = Unit.getName(_targetMim) -- Unit name
local _targetMimgroup = Unit.getGroup(Weapon.getTarget(SEADWeapon)) --targeted group
local _targetMimgroupName = _targetMimgroup:getName() -- group name
local _targetskill = _DATABASE.Templates.Units[_targetMimname].Template.skill
local _targetUnit = UNIT:Find(_targetMim) -- Unit name by DCS Object
if _targetUnit and _targetUnit:IsAlive() then
local _targetMimgroup = _targetUnit:GetGroup()
local _targetMimgroupName = _targetMimgroup:GetName() -- group name
--local _targetskill = _DATABASE.Templates.Units[_targetUnit].Template.skill
self:T( self.SEADGroupPrefixes )
self:T( _targetMimgroupName )
end
-- see if we are shot at
local SEADGroupFound = false
for SEADGroupPrefixID, SEADGroupPrefix in pairs( self.SEADGroupPrefixes ) do
@ -249,6 +252,7 @@ function SEAD:OnEventShot( EventData )
local range = self.EngagementRange -- Feature Request #1355
self:T(string.format("*** SEAD - Engagement Range is %d", range))
id.ctrl:setOption(AI.Option.Ground.id.ALARM_STATE,AI.Option.Ground.val.ALARM_STATE.RED)
--id.groupName:enableEmission(true)
id.ctrl:setOption(AI.Option.Ground.id.AC_ENGAGEMENT_RANGE_RESTRICTION,range) --Feature Request #1355
self.SuppressedGroups[id.groupName] = nil --delete group id from table when done
end
@ -261,6 +265,7 @@ function SEAD:OnEventShot( EventData )
SuppressionEndTime = delay
}
Controller.setOption(_targetMimcont, AI.Option.Ground.id.ALARM_STATE,AI.Option.Ground.val.ALARM_STATE.GREEN)
--_targetMimgroup:enableEmission(false)
timer.scheduleFunction(SuppressionEnd, id, SuppressionEndTime) --Schedule the SuppressionEnd() function
end
end

View File

@ -18,7 +18,7 @@
-- @module Functional.Shorad
-- @image Functional.Shorad.jpg
--
-- Date: Feb 2021
-- Date: May 2021
-------------------------------------------------------------------------
--- **SHORAD** class, extends Core.Base#BASE
@ -38,6 +38,7 @@
-- @field #boolean DefendMavs Default true, intercept incoming AG-Missiles
-- @field #number DefenseLowProb Default 70, minimum detection limit
-- @field #number DefenseHighProb Default 90, maximim detection limit
-- @field #boolean UseEmOnOff Decide if we are using Emission on/off (default) or AlarmState red/green.
-- @extends Core.Base#BASE
--- *Good friends are worth defending.* Mr Tushman, Wonder (the Movie)
@ -95,6 +96,7 @@ SHORAD = {
DefendMavs = true,
DefenseLowProb = 70,
DefenseHighProb = 90,
UseEmOnOff = false,
}
-----------------------------------------------------------------------
@ -174,7 +176,8 @@ do
self.DefendMavs = true
self.DefenseLowProb = 70 -- probability to detect a missile shot, low margin
self.DefenseHighProb = 90 -- probability to detect a missile shot, high margin
self:I("*** SHORAD - Started Version 0.0.2")
self.UseEmOnOff = false -- Decide if we are using Emission on/off (default) or AlarmState red/green
self:I("*** SHORAD - Started Version 0.2.1")
-- Set the string id for output to DCS.log file.
self.lid=string.format("SHORAD %s | ", self.name)
self:_InitState()
@ -189,8 +192,13 @@ do
self:T({set = set})
local aliveset = set:GetAliveSet() --#table
for _,_group in pairs (aliveset) do
if self.UseEmOnOff then
--_group:SetAIOff()
_group:EnableEmission(false)
else
_group:OptionAlarmStateGreen() --Wrapper.Group#GROUP
end
end
-- gather entropy
for i=1,10 do
math.random()
@ -272,6 +280,13 @@ do
self.Radius = radius
end
--- Set using Emission on/off instead of changing alarm state
-- @param #SHORAD self
-- @param #boolean switch Decide if we are changing alarm state or AI state
function SHORAD:SetUsingEmOnOff(switch)
self.UseEmOnOff = switch or false
end
--- Check if a HARM was fired
-- @param #SHORAD self
-- @param #string WeaponName
@ -396,7 +411,12 @@ do
local function SleepShorad(group)
local groupname = group:GetName()
self.ActiveGroups[groupname] = nil
if self.UseEmOnOff then
group:EnableEmission(false)
--group:SetAIOff()
else
group:OptionAlarmStateGreen()
end
local text = string.format("Sleeping SHORAD %s", group:GetName())
self:T(text)
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
@ -407,6 +427,10 @@ do
local text = string.format("Waking up SHORAD %s", _group:GetName())
self:T(text)
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
if self.UseEmOnOff then
_group:SetAIOn()
_group:EnableEmission(true)
end
_group:OptionAlarmStateRed()
local groupname = _group:GetName()
if self.ActiveGroups[groupname] == nil then -- no timer yet for this group
@ -440,14 +464,21 @@ do
end
local text = string.format("%s Missile Launched = %s | Detected probability state is %s", self.lid, ShootingWeaponName, DetectedText)
self:T( text )
local m = MESSAGE:New(text,15,"Info"):ToAllIf(self.debug)
local m = MESSAGE:New(text,10,"Info"):ToAllIf(self.debug)
--
if (self:_CheckHarms(ShootingWeaponName) or self:_CheckMavs(ShootingWeaponName)) and IsDetected then
-- get target data
local targetdata = EventData.Weapon:getTarget() -- Identify target
local targetunitname = Unit.getName(targetdata) -- Unit name
local targetgroup = Unit.getGroup(Weapon.getTarget(ShootingWeapon)) --targeted group
local targetgroupname = targetgroup:getName() -- group name
local targetunit = UNIT:Find(targetdata)
--local targetunitname = Unit.getName(targetdata) -- Unit name
if targetunit and targetunit:IsAlive() then
local targetunitname = targetunit:GetName()
--local targetgroup = Unit.getGroup(Weapon.getTarget(ShootingWeapon)) --targeted group
local targetgroup = targetunit:GetGroup()
local targetgroupname = targetgroup:GetName() -- group name
local text = string.format("%s Missile Target = %s", self.lid, tostring(targetgroupname))
self:T( text )
local m = MESSAGE:New(text,10,"Info"):ToAllIf(self.debug)
-- check if we or a SAM site are the target
--local TargetGroup = EventData.TgtGroup -- Wrapper.Group#GROUP
local shotatus = self:_CheckShotAtShorad(targetgroupname) --#boolean
@ -460,6 +491,7 @@ do
end
end
end
end
--
end
-----------------------------------------------------------------------

View File

@ -7,7 +7,7 @@
-- * Wind direction and speed
-- * Visibility
-- * Cloud coverage, base and ceiling
-- * Temprature
-- * Temperature
-- * Dew point (approximate as there is no relative humidity in DCS yet)
-- * Pressure QNH/QFE
-- * Weather phenomena: rain, thunderstorm, fog, dust
@ -564,7 +564,7 @@ _ATIS={}
--- ATIS class version.
-- @field #string version
ATIS.version="0.9.0"
ATIS.version="0.9.1"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@ -580,6 +580,8 @@ ATIS.version="0.9.0"
-- DONE: Metric units.
-- DONE: Set UTC correction.
-- DONE: Set magnetic variation.
-- DONE: New DCS 2.7 weather presets.
-- DONE: whatever
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor
@ -1431,8 +1433,102 @@ function ATIS:onafterBroadcast(From, Event, To)
local cloudceil=clouds.base+clouds.thickness
local clouddens=clouds.density
-- Cloud preset (DCS 2.7)
local cloudspreset=clouds.preset or "Nothing"
-- Precepitation: 0=None, 1=Rain, 2=Thunderstorm, 3=Snow, 4=Snowstorm.
local precepitation=tonumber(clouds.iprecptns)
local precepitation=0
if cloudspreset:find("Preset10") then
-- Scattered 5
clouddens=4
elseif cloudspreset:find("Preset11") then
-- Scattered 6
clouddens=4
elseif cloudspreset:find("Preset12") then
-- Scattered 7
clouddens=4
elseif cloudspreset:find("Preset13") then
-- Broken 1
clouddens=7
elseif cloudspreset:find("Preset14") then
-- Broken 2
clouddens=7
elseif cloudspreset:find("Preset15") then
-- Broken 3
clouddens=7
elseif cloudspreset:find("Preset16") then
-- Broken 4
clouddens=7
elseif cloudspreset:find("Preset17") then
-- Broken 5
clouddens=7
elseif cloudspreset:find("Preset18") then
-- Broken 6
clouddens=7
elseif cloudspreset:find("Preset19") then
-- Broken 7
clouddens=7
elseif cloudspreset:find("Preset20") then
-- Broken 8
clouddens=7
elseif cloudspreset:find("Preset21") then
-- Overcast 1
clouddens=9
elseif cloudspreset:find("Preset22") then
-- Overcast 2
clouddens=9
elseif cloudspreset:find("Preset23") then
-- Overcast 3
clouddens=9
elseif cloudspreset:find("Preset24") then
-- Overcast 4
clouddens=9
elseif cloudspreset:find("Preset25") then
-- Overcast 5
clouddens=9
elseif cloudspreset:find("Preset26") then
-- Overcast 6
clouddens=9
elseif cloudspreset:find("Preset27") then
-- Overcast 7
clouddens=9
elseif cloudspreset:find("Preset1") then
-- Light Scattered 1
clouddens=1
elseif cloudspreset:find("Preset2") then
-- Light Scattered 2
clouddens=1
elseif cloudspreset:find("Preset3") then
-- High Scattered 1
clouddens=4
elseif cloudspreset:find("Preset4") then
-- High Scattered 2
clouddens=4
elseif cloudspreset:find("Preset5") then
-- Scattered 1
clouddens=4
elseif cloudspreset:find("Preset6") then
-- Scattered 2
clouddens=4
elseif cloudspreset:find("Preset7") then
-- Scattered 3
clouddens=4
elseif cloudspreset:find("Preset8") then
-- High Scattered 3
clouddens=4
elseif cloudspreset:find("Preset9") then
-- Scattered 4
clouddens=4
elseif cloudspreset:find("RainyPreset") then
-- Overcast + Rain
clouddens=9
if temperature>5 then
precepitation=1 -- rain
else
precepitation=3 -- snow
end
end
local CLOUDBASE=string.format("%d", UTILS.MetersToFeet(cloudbase))
local CLOUDCEIL=string.format("%d", UTILS.MetersToFeet(cloudceil))

View File

@ -119,6 +119,7 @@ AIRWING = {
pointsTANKER = {},
pointsAWACS = {},
wingcommander = nil,
markpoints = false,
}
--- Squadron asset.
@ -209,6 +210,7 @@ function AIRWING:New(warehousename, airwingname)
self.nflightsTANKERprobe=0
self.nflightsRecoveryTanker=0
self.nflightsRescueHelo=0
self.markpoints = false
------------------------
--- Pseudo Functions ---
@ -231,6 +233,24 @@ function AIRWING:New(warehousename, airwingname)
-- @param #AIRWING self
-- @param #number delay Delay in seconds.
--- On after "FlightOnMission" event. Triggered when an asset group starts a mission.
-- @function [parent=#AIRWING] OnAfterFlightOnMission
-- @param #AIRWING self
-- @param #string From The From state
-- @param #string Event The Event called
-- @param #string To The To state
-- @param Ops.FlightGroup#FLIGHTGROUP Flightgroup The Flightgroup on mission
-- @param Ops.Auftrag#AUFTRAG Mission The Auftrag of the Flightgroup
--- On after "AssetReturned" event. Triggered when an asset group returned to its airwing.
-- @function [parent=#AIRWING] OnAfterAssetReturned
-- @param #AIRWING self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Ops.Squadron#SQUADRON Squadron The asset squadron.
-- @param #AIRWING.SquadronAsset Asset The asset that returned.
return self
end
@ -647,6 +667,19 @@ function AIRWING:SetNumberTankerBoom(Nboom)
return self
end
--- Set markers on the map for Patrol Points.
-- @param #AIRWING self
-- @param #boolean onoff Set to true to switch markers on.
-- @return #AIRWING self
function AIRWING:ShowPatrolPointMarkers(onoff)
if onoff then
self.markpoints = true
else
self.markpoints = false
end
return self
end
--- Set number of TANKER flights with Probe constantly in the air.
-- @param #AIRWING self
-- @param #number Nprobe Number of flights. Default 1.
@ -688,13 +721,13 @@ end
--- Update marker of the patrol point.
-- @param #AIRWING.PatrolData point Patrol point table.
function AIRWING.UpdatePatrolPointMarker(point)
function AIRWING:UpdatePatrolPointMarker(point)
if self.markpoints then -- sometimes there's a direct call from #OPSGROUP
local text=string.format("%s Occupied=%d\nheading=%03d, leg=%d NM, alt=%d ft, speed=%d kts",
point.type, point.noccupied, point.heading, point.leg, point.altitude, point.speed)
point.marker:UpdateText(text, 1)
end
end
@ -717,9 +750,11 @@ function AIRWING:NewPatrolPoint(Type, Coordinate, Altitude, Speed, Heading, LegL
patrolpoint.altitude=Altitude or math.random(10,20)*1000
patrolpoint.speed=Speed or 350
patrolpoint.noccupied=0
patrolpoint.marker=MARKER:New(Coordinate, "New Patrol Point"):ToAll()
if self.markpoints then
patrolpoint.marker=MARKER:New(Coordinate, "New Patrol Point"):ToAll()
AIRWING.UpdatePatrolPointMarker(patrolpoint)
end
return patrolpoint
end
@ -928,7 +963,7 @@ function AIRWING:CheckCAP()
patrol.noccupied=patrol.noccupied+1
AIRWING.UpdatePatrolPointMarker(patrol)
if self.markpoints then AIRWING.UpdatePatrolPointMarker(patrol) end
self:AddMission(missionCAP)
@ -972,7 +1007,7 @@ function AIRWING:CheckTANKER()
patrol.noccupied=patrol.noccupied+1
AIRWING.UpdatePatrolPointMarker(patrol)
if self.markpoints then AIRWING.UpdatePatrolPointMarker(patrol) end
self:AddMission(mission)
@ -990,7 +1025,7 @@ function AIRWING:CheckTANKER()
patrol.noccupied=patrol.noccupied+1
AIRWING.UpdatePatrolPointMarker(patrol)
if self.markpoints then AIRWING.UpdatePatrolPointMarker(patrol) end
self:AddMission(mission)
@ -1018,7 +1053,7 @@ function AIRWING:CheckAWACS()
patrol.noccupied=patrol.noccupied+1
AIRWING.UpdatePatrolPointMarker(patrol)
if self.markpoints then AIRWING.UpdatePatrolPointMarker(patrol) end
self:AddMission(mission)
@ -1431,7 +1466,9 @@ function AIRWING:onafterMissionCancel(From, Event, To, Mission)
-- Info message.
self:I(self.lid..string.format("Cancel mission %s", Mission.name))
if Mission:IsPlanned() or Mission:IsQueued() or Mission:IsRequested() then
local Ngroups = Mission:CountOpsGroups()
if Mission:IsPlanned() or Mission:IsQueued() or Mission:IsRequested() or Ngroups == 0 then
Mission:Done()

View File

@ -17930,7 +17930,7 @@ function AIRBOSS:onbeforeSave(From, Event, To, path, filename)
-- Check default path.
if path==nil and not lfs then
self:E(self.lid.."WARNING: lfs not desanitized. Results will be saved in DCS installation root directory rather than your \"Saved Games\DCS\" folder.")
self:E(self.lid.."WARNING: lfs not desanitized. Results will be saved in DCS installation root directory rather than your \"Saved Games\\DCS\" folder.")
end
return true
@ -18037,7 +18037,7 @@ function AIRBOSS:onbeforeLoad(From, Event, To, path, filename)
-- Check default path.
if path==nil and not lfs then
self:E(self.lid.."WARNING: lfs not desanitized. Results will be saved in DCS installation root directory rather than your \"Saved Games\DCS\" folder.")
self:E(self.lid.."WARNING: lfs not desanitized. Results will be saved in DCS installation root directory rather than your \"Saved Games\\DCS\" folder.")
end
-- Set path or default.

View File

@ -140,6 +140,8 @@ FLIGHTGROUP = {
fuelcritical = nil,
fuelcriticalthresh = nil,
fuelcriticalrtb = false,
outofAAMrtb = true,
outofAGMrtb = true,
squadron = nil,
flightcontrol = nil,
flaghold = nil,
@ -147,6 +149,7 @@ FLIGHTGROUP = {
Tparking = nil,
menu = nil,
ishelo = nil,
RTBRecallCount = 0,
}
@ -210,7 +213,7 @@ FLIGHTGROUP.version="0.6.1"
-- TODO: Mark assigned parking spot on F10 map.
-- TODO: Let user request a parking spot via F10 marker :)
-- TODO: Monitor traveled distance in air ==> calculate fuel consumption ==> calculate range remaining. Will this give half way accurate results?
-- TODO: Out of AG/AA missiles. Safe state of out-of-ammo.
-- DONE: Out of AG/AA missiles. Safe state of out-of-ammo.
-- DONE: Add tasks.
-- DONE: Waypoints, read, add, insert, detour.
-- DONE: Get ammo.
@ -274,9 +277,9 @@ function FLIGHTGROUP:New(group)
self:AddTransition("*", "FuelLow", "*") -- Fuel state of group is low. Default ~25%.
self:AddTransition("*", "FuelCritical", "*") -- Fuel state of group is critical. Default ~10%.
self:AddTransition("*", "OutOfMissilesAA", "*") -- Group is out of A2A missiles. Not implemented yet!
self:AddTransition("*", "OutOfMissilesAG", "*") -- Group is out of A2G missiles. Not implemented yet!
self:AddTransition("*", "OutOfMissilesAS", "*") -- Group is out of A2G missiles. Not implemented yet!
self:AddTransition("*", "OutOfMissilesAA", "*") -- Group is out of A2A missiles.
self:AddTransition("*", "OutOfMissilesAG", "*") -- Group is out of A2G missiles.
self:AddTransition("*", "OutOfMissilesAS", "*") -- Group is out of A2S(ship) missiles. Not implemented yet!
self:AddTransition("Airborne", "EngageTarget", "Engaging") -- Engage targets.
self:AddTransition("Engaging", "Disengage", "Airborne") -- Engagement over.
@ -476,6 +479,32 @@ function FLIGHTGROUP:SetFuelLowRTB(switch)
return self
end
--- Set if flight is out of Air-Air-Missiles, flight goes RTB.
-- @param #FLIGHTGROUP self
-- @param #boolean switch If true or nil, flight goes RTB. If false, turn this off.
-- @return #FLIGHTGROUP self
function FLIGHTGROUP:SetOutOfAAMRTB(switch)
if switch==false then
self.outofAAMrtb=false
else
self.outofAAMrtb=true
end
return self
end
--- Set if flight is out of Air-Ground-Missiles, flight goes RTB.
-- @param #FLIGHTGROUP self
-- @param #boolean switch If true or nil, flight goes RTB. If false, turn this off.
-- @return #FLIGHTGROUP self
function FLIGHTGROUP:SetOutOfAGMRTB(switch)
if switch==false then
self.outofAGMrtb=false
else
self.outofAGMrtb=true
end
return self
end
--- Set if low fuel threshold is reached, flight tries to refuel at the neares tanker.
-- @param #FLIGHTGROUP self
-- @param #boolean switch If true or nil, flight goes for refuelling. If false, turn this off.
@ -1015,6 +1044,28 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
self:FuelCritical()
end
-- Out of AA Missiles? CAP, GCICAP, INTERCEPT
local CurrIsCap = false
-- Out of AG Missiles? BAI, SEAD, CAS, STRIKE
local CurrIsA2G = false
-- Check AUFTRAG Type
local CurrAuftrag = self:GetMissionCurrent()
if CurrAuftrag then
local CurrAuftragType = CurrAuftrag:GetType()
if CurrAuftragType == "CAP" or CurrAuftragType == "GCICAP" or CurrAuftragType == "INTERCEPT" then CurrIsCap = true end
if CurrAuftragType == "BAI" or CurrAuftragType == "CAS" or CurrAuftragType == "SEAD" or CurrAuftragType == "STRIKE" then CurrIsA2G = true end
end
-- Check A2A
if (not self:CanAirToAir(true)) and CurrIsCap then
self:OutOfMissilesAA()
end
-- Check A2G
if (not self:CanAirToGround(false)) and CurrIsA2G then
self:OutOfMissilesAG()
end
end
---
@ -2046,6 +2097,34 @@ function FLIGHTGROUP:onafterRespawn(From, Event, To, Template)
end
--- On after "OutOfMissilesAA" event.
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
function FLIGHTGROUP:onafterOutOfMissilesAA(From, Event, To)
self:I(self.lid.."Group is out of AA Missiles!")
if self.outofAAMrtb then
-- Back to destination or home.
local airbase=self.destbase or self.homebase
self:__RTB(-5,airbase)
end
end
--- On after "OutOfMissilesAG" event.
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
function FLIGHTGROUP:onafterOutOfMissilesAG(From, Event, To)
self:I(self.lid.."Group is out of AG Missiles!")
if self.outofAGMrtb then
-- Back to destination or home.
local airbase=self.destbase or self.homebase
self:__RTB(-5,airbase)
end
end
--- Check if flight is done, i.e.
--
-- * passed the final waypoint,
@ -2150,9 +2229,15 @@ function FLIGHTGROUP:onbeforeRTB(From, Event, To, airbase, SpeedTo, SpeedHold)
end
if not self.group:IsAirborne(true) then
self:I(self.lid..string.format("WARNING: Group is not AIRBORNE ==> RTB event is suspended for 10 sec."))
-- this should really not happen, either the AUFTRAG is cancelled before the group was airborne or it is stuck at the ground for some reason
self:I(self.lid..string.format("WARNING: Group is not AIRBORNE ==> RTB event is suspended for 20 sec."))
allowed=false
Tsuspend=-10
Tsuspend=-20
local groupspeed = self.group:GetVelocityMPS()
if groupspeed <= 1 then self.RTBRecallCount = self.RTBRecallCount+1 end
if self.RTBRecallCount > 6 then
self:Despawn(5)
end
end
-- Only if fuel is not low or critical.

View File

@ -1,6 +1,6 @@
--- **Ops** - Office of Military Intelligence.
--
-- ## Main Features:
-- **Main Features:**
--
-- * Detect and track contacts consistently
-- * Detect and track clusters of contacts consistently
@ -80,6 +80,7 @@
-- `local m = MESSAGE:New(text,15,"KGB"):ToAll()`
-- `end`
--
--
-- @field #INTEL
INTEL = {
ClassName = "INTEL",
@ -93,7 +94,7 @@ INTEL = {
ContactsUnknown = {},
Clusters = {},
clustercounter = 1,
clusterradius = 10,
clusterradius = 15,
}
--- Detected item info.
@ -130,7 +131,7 @@ INTEL = {
--- INTEL class version.
-- @field #string version
INTEL.version="0.2.0"
INTEL.version="0.2.1"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list
@ -350,7 +351,7 @@ function INTEL:RemoveRejectZone(RejectZone)
return self
end
--- Set forget contacts time interval. For unknown contacts only.
--- Set forget contacts time interval.
-- Previously known contacts that are not detected any more, are "lost" after this time.
-- This avoids fast oscillations between a contact being detected and undetected.
-- @param #INTEL self
@ -465,7 +466,7 @@ end
-- @param #number radius The radius of the clusters
-- @return #INTEL self
function INTEL:SetClusterRadius(radius)
local radius = radius or 10
local radius = radius or 15
self.clusterradius = radius
return self
end
@ -1155,7 +1156,7 @@ function INTEL:IsContactConnectedToCluster(contact, cluster)
--local dist=Contact.position:Get2DDistance(contact.position)
local dist=Contact.position:DistanceFromPointVec2(contact.position)
local radius = self.clusterradius or 10
local radius = self.clusterradius or 15
if dist<radius*1000 then
return true
end
@ -1285,7 +1286,13 @@ function INTEL:UpdateClusterMarker(cluster)
local text=string.format("Cluster #%d. Size %d, Units %d, TLsum=%d", cluster.index, cluster.size, unitcount, cluster.threatlevelSum)
if not cluster.marker then
cluster.marker=MARKER:New(cluster.coordinate, text):ToAll()
if self.coalition == coalition.side.RED then
cluster.marker=MARKER:New(cluster.coordinate, text):ToRed()
elseif self.coalition == coalition.side.BLUE then
cluster.marker=MARKER:New(cluster.coordinate, text):ToBlue()
else
cluster.marker=MARKER:New(cluster.coordinate, text):ToNeutral()
end
else
local refresh=false

View File

@ -340,6 +340,8 @@ OPSGROUP.version="0.7.1"
-- TODO: Invisible/immortal.
-- TODO: F10 menu.
-- TODO: Add pseudo function.
-- TODO: EPLRS datalink.
-- TODO: Emission on/off.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor

View File

@ -6,7 +6,7 @@
--
-- ### Contributions:
--
-- * FlightControl : Rework to OO framework
-- * FlightControl : Rework to OO framework.
--
-- @module Utils
-- @image MOOSE.JPG

View File

@ -362,6 +362,14 @@ AIRBASE.TheChannel = {
-- * AIRBASE.Syria.Beirut_Rafic_Hariri
-- * AIRBASE.Syria.An_Nasiriyah
-- * AIRBASE.Syria.Abu_al_Duhur
-- * AIRBASE.Syria.H4
-- * AIRBASE.Syria.Gaziantep
-- * AIRBASE.Syria.Rosh_Pina
-- * AIRBASE.Syria.Sayqal
-- * AIRBASE.Syria.Shayrat
-- * AIRBASE.Syria.Tiyas
-- * AIRBASE.Syria.Tha_lah
-- * AIRBASE.Syria.Naqoura
--
-- @field Syria
AIRBASE.Syria={
@ -398,6 +406,14 @@ AIRBASE.Syria={
["Beirut_Rafic_Hariri"]="Beirut-Rafic Hariri",
["An_Nasiriyah"]="An Nasiriyah",
["Abu_al_Duhur"]="Abu al-Duhur",
["H4"]="H4",
["Gaziantep"]="Gaziantep",
["Rosh_Pina"]="Rosh Pina",
["Sayqal"]="Sayqal",
["Shayrat"]="Shayrat",
["Tiyas"]="Tiyas",
["Tha_lah"]="Tha'lah",
["Naqoura"]="Naqoura",
}

View File

@ -1428,16 +1428,22 @@ end
-- @param DCS#Distance Radius The radius of the zone to deploy the fire at.
-- @param #number AmmoCount (optional) Quantity of ammunition to expand (omit to fire until ammunition is depleted).
-- @param #number WeaponType (optional) Enum for weapon type ID. This value is only required if you want the group firing to use a specific weapon, for instance using the task on a ship to force it to fire guided missiles at targets within cannon range. See http://wiki.hoggit.us/view/DCS_enum_weapon_flag
-- @param #number Altitude (Optional) Altitude in meters.
-- @param #number ASL Altitude is above mean sea level. Default is above ground level.
-- @return DCS#Task The DCS task structure.
function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius, AmmoCount, WeaponType )
function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius, AmmoCount, WeaponType, Altitude, ASL )
local DCSTask = {
id = 'FireAtPoint',
params = {
point = Vec2,
x=Vec2.x,
y=Vec2.y,
zoneRadius = Radius,
radius = Radius,
expendQty = 100, -- dummy value
expendQtyEnabled = false,
alt_type = ASL and 0 or 1
}
}
@ -1446,10 +1452,16 @@ function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius, AmmoCount, WeaponType )
DCSTask.params.expendQtyEnabled = true
end
if Altitude then
DCSTask.params.altitude=Altitude
end
if WeaponType then
DCSTask.params.weaponType=WeaponType
end
--self:I(DCSTask)
return DCSTask
end
@ -2896,7 +2908,7 @@ end
--- Set option for Rules of Engagement (ROE).
-- @param Wrapper.Controllable#CONTROLLABLE self
-- @param #number ROEvalue ROE value. See ENUMS.ROE.
-- @return Wrapper.Controllable#CONTROLLABLE self
-- @return #CONTROLLABLE self
function CONTROLLABLE:OptionROE(ROEvalue)
local DCSControllable = self:GetDCSObject()
@ -2938,8 +2950,8 @@ function CONTROLLABLE:OptionROEHoldFirePossible()
end
--- Weapons Hold: AI will hold fire under all circumstances.
-- @param Wrapper.Controllable#CONTROLLABLE self
-- @return Wrapper.Controllable#CONTROLLABLE self
-- @param #CONTROLLABLE self
-- @return #CONTROLLABLE self
function CONTROLLABLE:OptionROEHoldFire()
self:F2( { self.ControllableName } )
@ -3537,7 +3549,7 @@ end
-- Note that when WayPointInitialize is called, the Mission of the controllable is RESTARTED!
-- @param #CONTROLLABLE self
-- @param #table WayPoints If WayPoints is given, then use the route.
-- @return #CONTROLLABLE
-- @return #CONTROLLABLE self
function CONTROLLABLE:WayPointInitialize( WayPoints )
self:F( { WayPoints } )
@ -3568,7 +3580,7 @@ end
-- @param #number WayPoint The waypoint number. Note that the start waypoint on the route is WayPoint 1!
-- @param #number WayPointIndex When defining multiple WayPoint functions for one WayPoint, use WayPointIndex to set the sequence of actions.
-- @param #function WayPointFunction The waypoint function to be called when the controllable moves over the waypoint. The waypoint function takes variable parameters.
-- @return #CONTROLLABLE
-- @return #CONTROLLABLE self
function CONTROLLABLE:WayPointFunction( WayPoint, WayPointIndex, WayPointFunction, ... )
self:F2( { WayPoint, WayPointIndex, WayPointFunction } )
@ -3584,7 +3596,7 @@ end
-- @param #CONTROLLABLE self
-- @param #number WayPoint The WayPoint from where to execute the mission.
-- @param #number WaitTime The amount seconds to wait before initiating the mission.
-- @return #CONTROLLABLE
-- @return #CONTROLLABLE self
function CONTROLLABLE:WayPointExecute( WayPoint, WaitTime )
self:F( { WayPoint, WaitTime } )
@ -3667,7 +3679,9 @@ end
--- Sets Controllable Option for A2A attack range for AIR FIGHTER units.
-- @param #CONTROLLABLE self
-- @param #number Defines the range: MAX_RANGE = 0, NEZ_RANGE = 1, HALF_WAY_RMAX_NEZ = 2, TARGET_THREAT_EST = 3, RANDOM_RANGE = 4. Defaults to 3. See: https://wiki.hoggitworld.com/view/DCS_option_missileAttack
-- @param #number range Defines the range
-- @return #CONTROLLABLE self
-- @usage Range can be one of MAX_RANGE = 0, NEZ_RANGE = 1, HALF_WAY_RMAX_NEZ = 2, TARGET_THREAT_EST = 3, RANDOM_RANGE = 4. Defaults to 3. See: https://wiki.hoggitworld.com/view/DCS_option_missileAttack
function CONTROLLABLE:OptionAAAttackRange(range)
self:F2( { self.ControllableName } )
-- defaults to 3
@ -3718,6 +3732,7 @@ end
-- @param #number radius Radius of the relocation zone, default 500
-- @param #boolean onroad If true, route on road (less problems with AI way finding), default true
-- @param #boolean shortcut If true and onroad is set, take a shorter route - if available - off road, default false
-- @return #CONTROLLABLE self
function CONTROLLABLE:RelocateGroundRandomInRadius(speed, radius, onroad, shortcut)
self:F2( { self.ControllableName } )
@ -3741,3 +3756,24 @@ function CONTROLLABLE:RelocateGroundRandomInRadius(speed, radius, onroad, shortc
return self
end
--- Defines how long a GROUND unit/group will move to avoid an ongoing attack.
-- @param #CONTROLLABLE self
-- @param #number Seconds Any positive number: AI will disperse, but only for the specified time before continuing their route. 0: AI will not disperse.
-- @return #CONTROLLABLE self
function CONTROLLABLE:OptionDisperseOnAttack(Seconds)
self:F2( { self.ControllableName } )
-- Set default if not specified.
local seconds = Seconds or 0
local DCSControllable = self:GetDCSObject()
if DCSControllable then
local Controller = self:_GetController()
if Controller then
if self:IsGround() then
self:SetOption(AI.Option.GROUND.id.DISPERSE_ON_ATTACK, seconds)
end
end
return self
end
return nil
end

View File

@ -2169,40 +2169,6 @@ function GROUP:GetThreatLevel()
return threatlevelMax
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.
-- @return #number Threat level of the unit.
function GROUP:GetHighestThreat()
-- Get units of the group.
local units=self:GetUnits()
if units then
local threat=nil ; local maxtl=0
for _,_unit in pairs(units or {}) do
local unit=_unit --Wrapper.Unit#UNIT
if unit and unit:IsAlive() then
-- Threat level of group.
local tl=unit:GetThreatLevel()
-- Check if greater the current threat.
if tl>maxtl then
maxtl=tl
threat=unit
end
end
end
return threat, maxtl
end
return nil, nil
end
--- Returns true if the first unit of the GROUP is in the air.
-- @param Wrapper.Group#GROUP self
@ -2585,6 +2551,23 @@ do -- Players
end
--- GROUND - Switch on/off radar emissions
-- @param #GROUP self
-- @param #boolean switch
function GROUP:EnableEmission(switch)
self:F2( self.GroupName )
local switch = switch or false
local DCSUnit = self:GetDCSObject()
if DCSUnit then
DCSUnit:enableEmission(switch)
end
end
--do -- Smoke
--
----- Signal a flare at the position of the GROUP.

View File

@ -63,7 +63,7 @@
--
-- The UNIT class provides methods to obtain the current point or position of the DCS Unit.
-- The @{#UNIT.GetPointVec2}(), @{#UNIT.GetVec3}() will obtain the current **location** of the DCS Unit in a Vec2 (2D) or a **point** in a Vec3 (3D) vector respectively.
-- If you want to obtain the complete **3D position** including ori<EFBFBD>ntation and direction vectors, consult the @{#UNIT.GetPositionVec3}() method respectively.
-- If you want to obtain the complete **3D position** including orientation and direction vectors, consult the @{#UNIT.GetPositionVec3}() method respectively.
--
-- ## Test if alive
--
@ -154,8 +154,8 @@ function UNIT:Name()
return self.UnitName
end
--- @param #UNIT self
--- Get the DCS unit object.
-- @param #UNIT self
-- @return DCS#Unit
function UNIT:GetDCSObject()
@ -761,6 +761,41 @@ function UNIT:GetFuel()
return nil
end
--- Sets the passed group or unit objects radar emitters on or off. Can be used on sam sites for example to shut down the radar without setting AI off or changing the alarm state.
-- @param #UNIT self
-- @param #boolean Switch If `true` or `nil`, emission is enabled. If `false`, emission is turned off.
-- @return #UNIT self
function UNIT:SetEmission(Switch)
if Switch==nil then
Switch=true
end
local DCSUnit = self:GetDCSObject()
if DCSUnit then
DCSUnit:enableEmission(Switch)
end
return self
end
--- Sets the passed group or unit objects radar emitters ON. Can be used on sam sites for example to shut down the radar without setting AI off or changing the alarm state.
-- @param #UNIT self
-- @return #UNIT self
function UNIT:EnableEmission()
self:SetEmission(true)
return self
end
--- Sets the passed group or unit objects radar emitters OFF. Can be used on sam sites for example to shut down the radar without setting AI off or changing the alarm state.
-- @param #UNIT self
-- @return #UNIT self
function UNIT:DisableEmission()
self:SetEmission(false)
return self
end
--- Returns a list of one @{Wrapper.Unit}.
-- @param #UNIT self
-- @return #list<Wrapper.Unit#UNIT> A list of one @{Wrapper.Unit}.
@ -1393,3 +1428,21 @@ function UNIT:GetTemplateFuel()
return nil
end
--- GROUND - Switch on/off radar emissions.
-- @param #UNIT self
-- @param #boolean switch
function UNIT:EnableEmission(switch)
self:F2( self.UnitName )
local switch = switch or false
local DCSUnit = self:GetDCSObject()
if DCSUnit then
DCSUnit:enableEmission(switch)
end
end

View File

@ -1,3 +1,5 @@
[![Build status](https://ci.appveyor.com/api/projects/status/1y8nfmx7lwsn33tt?svg=true)](https://ci.appveyor.com/project/Applevangelist/MOOSE)
# MOOSE framework
MOOSE is a **M**ission **O**bject **O**riented **S**cripting **E**nvironment, and is meant for mission designers in DCS World.
@ -51,8 +53,6 @@ This repository contains all the demonstration missions in packed format (*.miz)
This repository contains all the demonstration missions in unpacked format. That means that there is no .miz file included, but all the .miz contents are unpacked.
## [MOOSE Web Site](https://flightcontrol-master.github.io/MOOSE_DOCS/)
Documentation on the MOOSE class hierarchy, usage guides and background information can be found here for normal users, beta testers and contributors.