Merge branch 'master' into FF/MasterDevel

This commit is contained in:
Frank 2024-06-09 21:31:58 +02:00
commit 754430ba75
13 changed files with 539 additions and 466 deletions

View File

@ -1301,7 +1301,7 @@ function EVENT:onEvent( Event )
-- STATIC
---
Event.TgtDCSUnit = Event.target
if Event.target:isExist() and Event.id ~= 33 then -- leave out ejected seat object
if Event.target.isExist and Event.target:isExist() and Event.id ~= 33 then -- leave out ejected seat object, check that isExist exists (Kiowa Hellfire issue, Special K)
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
-- Workaround for borked target info on cruise missiles
if Event.TgtDCSUnitName and Event.TgtDCSUnitName ~= "" then

View File

@ -2,7 +2,7 @@
--
-- ===
--
-- ### Features:
-- ## Features:
--
-- * Setup mission sub menus.
-- * Setup mission command menus.
@ -44,7 +44,11 @@
-- * @{Core.Menu#MENU_GROUP_COMMAND}: Manages command menus for GROUPs.
--
-- ===
---
--
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/Core/Menu)
--
-- ===
--
-- ### Author: **FlightControl**
-- ### Contributions:
--
@ -166,7 +170,8 @@ function MENU_INDEX:Refresh( Group )
end
do -- MENU_BASE
--- @type MENU_BASE
---
-- @type MENU_BASE
-- @extends Core.Base#BASE
--- Defines the main MENU class where other MENU classes are derived from.
-- This is an abstract class, so don't use it.
@ -206,6 +211,7 @@ do -- MENU_BASE
return self
end
function MENU_BASE:SetParentMenu( MenuText, Menu )
if self.ParentMenu then
self.ParentMenu.Menus = self.ParentMenu.Menus or {}
@ -277,8 +283,10 @@ do -- MENU_BASE
end
end
do -- MENU_COMMAND_BASE
--- @type MENU_COMMAND_BASE
do
---
-- MENU_COMMAND_BASE
-- @type MENU_COMMAND_BASE
-- @field #function MenuCallHandler
-- @extends Core.Menu#MENU_BASE
@ -343,8 +351,10 @@ do -- MENU_COMMAND_BASE
end
end
do -- MENU_MISSION
--- @type MENU_MISSION
do
---
-- MENU_MISSION
-- @type MENU_MISSION
-- @extends Core.Menu#MENU_BASE
--- Manages the main menus for a complete mission.
--
@ -509,8 +519,9 @@ do -- MENU_MISSION_COMMAND
return self
end
end
do -- MENU_COALITION
--- @type MENU_COALITION
do
--- MENU_COALITION
-- @type MENU_COALITION
-- @extends Core.Menu#MENU_BASE
--- Manages the main menus for DCS.coalition.
@ -635,9 +646,10 @@ do -- MENU_COALITION
return self
end
end
do -- MENU_COALITION_COMMAND
do
--- @type MENU_COALITION_COMMAND
--- MENU_COALITION_COMMAND
-- @type MENU_COALITION_COMMAND
-- @extends Core.Menu#MENU_COMMAND_BASE
--- Manages the command menus for coalitions, which allow players to execute functions during mission execution.
@ -725,8 +737,11 @@ do
-- So every menu for a client created must be tracked so that program logic accidentally does not create.
-- the same menus twice during initialization logic.
-- These menu classes are handling this logic with this variable.
local _MENUGROUPS = {}
--- @type MENU_GROUP
---
-- @type MENU_GROUP
-- @extends Core.Menu#MENU_BASE
@ -757,7 +772,7 @@ do
-- MenuStatus[MenuGroupName]:Remove()
-- end
--
-- --- @param Wrapper.Group#GROUP MenuGroup
-- -- @param Wrapper.Group#GROUP MenuGroup
-- local function AddStatusMenu( MenuGroup )
-- local MenuGroupName = MenuGroup:GetName()
-- -- This would create a menu for the red coalition under the MenuCoalitionRed menu object.
@ -899,8 +914,8 @@ do
return self
end
--- @type MENU_GROUP_COMMAND
---
-- @type MENU_GROUP_COMMAND
-- @extends Core.Menu#MENU_COMMAND_BASE
--- The @{Core.Menu#MENU_GROUP_COMMAND} class manages the command menus for coalitions, which allow players to execute functions during mission execution.
@ -983,7 +998,8 @@ do
end
--- MENU_GROUP_DELAYED
do
--- @type MENU_GROUP_DELAYED
---
-- @type MENU_GROUP_DELAYED
-- @extends Core.Menu#MENU_BASE
@ -1034,6 +1050,7 @@ do
-- @param #MENU_GROUP_DELAYED self
-- @return #MENU_GROUP_DELAYED
function MENU_GROUP_DELAYED:Set()
if not self.GroupID then return end
do
if not self.MenuSet then
missionCommands.addSubMenuForGroup( self.GroupID, self.MenuText, self.MenuParentPath )
@ -1106,8 +1123,8 @@ do
return self
end
--- @type MENU_GROUP_COMMAND_DELAYED
---
-- @type MENU_GROUP_COMMAND_DELAYED
-- @extends Core.Menu#MENU_COMMAND_BASE
--- Manages the command menus for coalitions, which allow players to execute functions during mission execution.

View File

@ -509,10 +509,10 @@ function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,G
end
_MESSAGESRS.label = Label or MSRS.Label or "MESSAGE"
_MESSAGESRS.MSRS:SetLabel(Label or "MESSAGE")
_MESSAGESRS.MSRS:SetLabel(_MESSAGESRS.label)
_MESSAGESRS.port = Port or MSRS.port or 5002
_MESSAGESRS.MSRS:SetPort(Port or 5002)
_MESSAGESRS.MSRS:SetPort(_MESSAGESRS.port)
_MESSAGESRS.volume = Volume or MSRS.volume or 1
_MESSAGESRS.MSRS:SetVolume(_MESSAGESRS.volume)

View File

@ -1516,6 +1516,7 @@ do
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
self:HandleEvent( EVENTS.RemoveUnit, self._EventOnDeadOrCrash )
self:HandleEvent( EVENTS.PlayerLeaveUnit, self._EventOnDeadOrCrash )
if self.Filter.Zones then
self.ZoneTimer = TIMER:New(self._ContinousZoneFilter,self)
local timing = self.ZoneTimerInterval or 30

View File

@ -292,9 +292,10 @@ SPAWN = {
--- Enumerator for spawns at airbases
-- @type SPAWN.Takeoff
-- @extends Wrapper.Group#GROUP.Takeoff
-- @field #SPAWN.Takeoff Takeoff
-- @field #number Air Take off happens in air.
-- @field #number Runway Spawn on runway. Does not work in MP!
-- @field #number Hot Spawn at parking with engines on.
-- @field #number Cold Spawn at parking with engines off.
SPAWN.Takeoff = {
Air = 1,
Runway = 2,
@ -619,12 +620,14 @@ end
-- and any spaces before and after the resulting name are removed.
-- IMPORTANT! This method MUST be the first used after :New !!!
-- @param #SPAWN self
-- @param #boolean KeepUnitNames (optional) If true, the unit names are kept, false or not provided to make new unit names.
-- @param #boolean KeepUnitNames (optional) If true, the unit names are kept, false or not provided create new unit names.
-- @return #SPAWN self
function SPAWN:InitKeepUnitNames( KeepUnitNames )
self:F()
self.SpawnInitKeepUnitNames = KeepUnitNames or true
self.SpawnInitKeepUnitNames = false
if KeepUnitNames == true then self.SpawnInitKeepUnitNames = true end
return self
end
@ -1609,8 +1612,8 @@ function SPAWN:SpawnWithIndex( SpawnIndex, NoBirth )
RandomVec2 = PointVec3:GetRandomVec2InRadius( self.SpawnOuterRadius, self.SpawnInnerRadius )
numTries = numTries + 1
inZone = SpawnZone:IsVec2InZone(RandomVec2)
self:I("Retrying " .. numTries .. "spawn " .. SpawnTemplate.name .. " in Zone " .. SpawnZone:GetName() .. "!")
self:I(SpawnZone)
--self:I("Retrying " .. numTries .. "spawn " .. SpawnTemplate.name .. " in Zone " .. SpawnZone:GetName() .. "!")
--self:I(SpawnZone)
end
end
if (not inZone) then
@ -3276,7 +3279,7 @@ end
--- Get the index from a given group.
-- The function will search the name of the group for a #, and will return the number behind the #-mark.
function SPAWN:GetSpawnIndexFromGroup( SpawnGroup )
self:F2( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix, SpawnGroup } )
self:F3( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix, SpawnGroup } )
local IndexString = string.match( SpawnGroup:GetName(), "#(%d*)$" ):sub( 2 )
local Index = tonumber( IndexString )
@ -3288,7 +3291,7 @@ end
--- Return the last maximum index that can be used.
function SPAWN:_GetLastIndex()
self:F( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix } )
self:F3( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix } )
return self.SpawnMaxGroups
end
@ -3437,7 +3440,9 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) -- R2.2
if self.SpawnInitKeepUnitNames == false then
for UnitID = 1, #SpawnTemplate.units do
if not string.find(SpawnTemplate.units[UnitID].name,"#IFF_",1,true) then --Razbam IFF hack for F15E etc
SpawnTemplate.units[UnitID].name = string.format( SpawnTemplate.name .. '-%02d', UnitID )
end
SpawnTemplate.units[UnitID].unitId = nil
end
else
@ -3449,11 +3454,13 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) -- R2.2
local UnitPrefix, Rest
if SpawnInitKeepUnitIFF == false then
UnitPrefix, Rest = string.match( SpawnTemplate.units[UnitID].name, "^([^#]+)#?" ):gsub( "^%s*(.-)%s*$", "%1" )
self:T( { UnitPrefix, Rest } )
else
UnitPrefix=SpawnTemplate.units[UnitID].name
end
SpawnTemplate.units[UnitID].name = string.format( '%s#%03d-%02d', UnitPrefix, SpawnIndex, UnitID )
self:T( { UnitPrefix, Rest } )
--else
--UnitPrefix=SpawnTemplate.units[UnitID].name
end
--SpawnTemplate.units[UnitID].name = string.format( '%s#%03d-%02d', UnitPrefix, SpawnIndex, UnitID )
SpawnTemplate.units[UnitID].unitId = nil
end
end

View File

@ -3076,10 +3076,26 @@ function ZONE_POLYGON:NewFromDrawing(DrawingName)
-- points for the drawings are saved in local space, so add the object's map x and y coordinates to get
-- world space points we can use
for _, point in UTILS.spairs(object["points"]) do
-- check if we want to skip adding a point
local skip = false
local p = {x = object["mapX"] + point["x"],
y = object["mapY"] + point["y"] }
-- Check if the same coordinates already exist in the list, skip if they do
-- This can happen when drawing a Polygon in Free mode, DCS adds points on
-- top of each other that are in the `mission` file, but not visible in the
-- Mission Editor
for _, pt in pairs(points) do
if pt.x == p.x and pt.y == p.y then
skip = true
end
end
-- if it's a unique point, add it
if not skip then
table.add(points, p)
end
end
elseif object["polygonMode"] == "rect" then
-- the points for a rect are saved as local coordinates with an angle. To get the world space points from this
-- we need to rotate the points around the center of the rects by an angle. UTILS.RotatePointAroundPivot was
@ -3096,6 +3112,7 @@ function ZONE_POLYGON:NewFromDrawing(DrawingName)
points = {p1, p2, p3, p4}
else
-- bring the Arrow code over from Shape/Polygon
-- something else that might be added in the future
end
end

View File

@ -22,7 +22,7 @@
-- @module Functional.Mantis
-- @image Functional.Mantis.jpg
--
-- Last Update: Feb 2024
-- Last Update: May 2024
-------------------------------------------------------------------------
--- **MANTIS** class, extends Core.Base#BASE
@ -58,6 +58,7 @@
-- @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
-- @field #number ShoradActDistance Distance of an attacker in meters from a Mantis SAM site, on which Shorad will be switched on. Useful to not give away Shorad sites too early. Default 15km. Should be smaller than checkradius.
-- @field #boolean checkforfriendlies If true, do not activate a SAM installation if a friendly aircraft is in firing range.
-- @extends Core.Base#BASE
@ -187,29 +188,34 @@
-- -- This is effectively a 3-stage filter allowing for zone overlap. A coordinate is accepted first when
-- -- it is inside any AcceptZone. Then RejectZones are checked, which enforces both borders, but also overlaps of
-- -- Accept- and RejectZones. Last, if it is inside a conflict zone, it is accepted.
-- `mybluemantis:AddZones(AcceptZones,RejectZones,ConflictZones)`
-- mybluemantis:AddZones(AcceptZones,RejectZones,ConflictZones)
--
--
-- ### 2.1.2 Change the number of long-, mid- and short-range systems going live on a detected target:
--
-- -- parameters are numbers. Defaults are 1,2,2,6 respectively
-- `mybluemantis:SetMaxActiveSAMs(Short,Mid,Long,Classic)`
-- mybluemantis:SetMaxActiveSAMs(Short,Mid,Long,Classic)
--
-- ### 2.1.3 SHORAD will automatically be added from SAM sites of type "short-range"
--
-- ### 2.1.4 Advanced features
--
-- -- switch off auto mode **before** you start MANTIS.
-- `mybluemantis.automode = false`
-- mybluemantis.automode = false
--
-- -- switch off auto shorad **before** you start MANTIS.
-- `mybluemantis.autoshorad = false`
-- mybluemantis.autoshorad = false
--
-- -- scale of the activation range, i.e. don't activate at the fringes of max range, defaults below.
-- -- also see engagerange below.
-- ` self.radiusscale[MANTIS.SamType.LONG] = 1.1`
-- ` self.radiusscale[MANTIS.SamType.MEDIUM] = 1.2`
-- ` self.radiusscale[MANTIS.SamType.SHORT] = 1.3`
-- self.radiusscale[MANTIS.SamType.LONG] = 1.1
-- self.radiusscale[MANTIS.SamType.MEDIUM] = 1.2
-- self.radiusscale[MANTIS.SamType.SHORT] = 1.3
--
-- ### 2.1.5 Friendlies check in firing range
--
-- -- For some scenarios, like Cold War, it might be useful not to activate SAMs if friendly aircraft are around to avoid death by friendly fire.
-- mybluemantis.checkforfriendlies = true
--
-- # 3. Default settings [both modes unless stated otherwise]
--
@ -321,6 +327,7 @@ MANTIS = {
automode = true,
autoshorad = true,
ShoradGroupSet = nil,
checkforfriendlies = false,
}
--- Advanced state enumerator
@ -503,6 +510,7 @@ do
-- DONE: Allow tables of prefixes for the setup
-- DONE: Auto-Mode with range setups for various known SAM types.
self.name = name or "mymantis"
self.SAM_Templates_Prefix = samprefix or "Red SAM"
self.EWR_Templates_Prefix = ewrprefix or "Red EWR"
self.HQ_Template_CC = hq or nil
@ -631,7 +639,7 @@ do
-- TODO Version
-- @field #string version
self.version="0.8.16"
self.version="0.8.18"
self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
--- FSM Functions ---
@ -1222,10 +1230,10 @@ do
function MANTIS:_PreFilterHeight(height)
self:T(self.lid.."_PreFilterHeight")
local set = {}
local dlink = self.Detection -- Ops.Intelligence#INTEL_DLINK
local dlink = self.Detection -- Ops.Intel#INTEL_DLINK
local detectedgroups = dlink:GetContactTable()
for _,_contact in pairs(detectedgroups) do
local contact = _contact -- Ops.Intelligence#INTEL.Contact
local contact = _contact -- Ops.Intel#INTEL.Contact
local grp = contact.group -- Wrapper.Group#GROUP
if grp:IsAlive() then
if grp:GetHeight(true) < height then
@ -1255,6 +1263,10 @@ do
-- DEBUG
set = self:_PreFilterHeight(height)
end
local friendlyset -- Core.Set#SET_GROUP
if self.checkforfriendlies == true then
friendlyset = SET_GROUP:New():FilterCoalitions(self.Coalition):FilterCategories({"plane","helicopter"}):FilterFunction(function(grp) if grp and grp:InAir() then return true else return false end end):FilterOnce()
end
for _,_coord in pairs (set) do
local coord = _coord -- get current coord to check
-- output for cross-check
@ -1279,8 +1291,16 @@ do
local m = MESSAGE:New(text,10,"Check"):ToAllIf(self.debug)
self:T(self.lid..text)
end
-- friendlies around?
local nofriendlies = true
if self.checkforfriendlies == true then
local closestfriend, distance = friendlyset:GetClosestGroup(samcoordinate)
if closestfriend and distance and distance < rad then
nofriendlies = false
end
end
-- end output to cross-check
if targetdistance <= rad and zonecheck then
if targetdistance <= rad and zonecheck == true and nofriendlies == true then
return true, targetdistance
end
end
@ -1777,7 +1797,7 @@ do
-- @return #MANTIS self
function MANTIS:_CheckDLinkState()
self:T(self.lid .. "_CheckDLinkState")
local dlink = self.Detection -- Ops.Intelligence#INTEL_DLINK
local dlink = self.Detection -- Ops.Intel#INTEL_DLINK
local TS = timer.getAbsTime()
if not dlink:Is("Running") and (TS - self.DLTimeStamp > 29) then
self.DLink = false

View File

@ -292,10 +292,11 @@ CSAR.AircraftType["AH-64D_BLK_II"] = 2
CSAR.AircraftType["Bronco-OV-10A"] = 2
CSAR.AircraftType["MH-60R"] = 10
CSAR.AircraftType["OH-6A"] = 2
CSAR.AircraftType["OH-58D"] = 2
--- CSAR class version.
-- @field #string version
CSAR.version="1.0.23"
CSAR.version="1.0.24"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list

View File

@ -1250,11 +1250,12 @@ CTLD.UnitTypeCapabilities = {
["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
["Bronco-OV-10A"] = {type="Bronco-OV-10A", crates= false, troops=true, cratelimit = 0, trooplimit = 5, length = 13, cargoweightlimit = 1450},
["OH-6A"] = {type="OH-6A", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 7, cargoweightlimit = 550},
["OH-58D"] = {type="OH-58D", crates=false, troops=false, cratelimit = 0, trooplimit = 0, length = 14, cargoweightlimit = 400},
}
--- CTLD class version.
-- @field #string version
CTLD.version="1.0.53"
CTLD.version="1.0.54"
--- Instantiate a new CTLD.
-- @param #CTLD self

View File

@ -1951,6 +1951,8 @@ function UTILS.GMTToLocalTimeDifference()
return -3 -- Fireland is UTC-3 hours.
elseif theatre==DCSMAP.Sinai then
return 2 -- Currently map is +2 but should be +3 (DCS bug?)
elseif theatre==DCSMAP.Kola then
return 3 -- Currently map is +2 but should be +3 (DCS bug?)
else
BASE:E(string.format("ERROR: Unknown Map %s in UTILS.GMTToLocal function. Returning 0", tostring(theatre)))
return 0
@ -2247,6 +2249,11 @@ function UTILS.IsLoadingDoorOpen( unit_name )
return true
end
if type_name == " OH-58D" and (unit:getDrawArgumentValue(35) > 0 or unit:getDrawArgumentValue(421) == -1) then
BASE:T(unit_name .. " cargo door is open")
return true
end
return false
end -- nil
@ -2477,7 +2484,7 @@ function UTILS.SaveToFile(Path,Filename,Data)
return true
end
--- Function to save an object to a file
--- Function to load an object from a file.
-- @param #string Path The path to use. Use double backslashes \\\\ on Windows filesystems.
-- @param #string Filename The name of the file.
-- @return #boolean outcome True if reading is possible and successful, else false.

View File

@ -722,35 +722,35 @@ AIRBASE.Sinai = {
--- Airbases of the Kola map
--
-- * AIRBASE.Kola.Banak
-- * AIRBASE.Kola.Bas_100
-- * AIRBASE.Kola.Bodo
-- * AIRBASE.Kola.Jokkmokk
-- * AIRBASE.Kola.Kalixfors
-- * AIRBASE.Kola.Kemi_Tornio
-- * AIRBASE.Kola.Kiruna
-- * AIRBASE.Kola.Lakselv
-- * AIRBASE.Kola.Monchegorsk
-- * AIRBASE.Kola.Murmansk_International
-- * AIRBASE.Kola.Olenegorsk
-- * AIRBASE.Kola.Olenya
-- * AIRBASE.Kola.Rovaniemi
-- * AIRBASE.Kola.Severomorsk1
-- * AIRBASE.Kola.Severomorsk3
-- * AIRBASE.Kola.Severomorsk_1
-- * AIRBASE.Kola.Severomorsk_3
--
-- @field Kola
AIRBASE.Kola = {
["Banak"] = "Banak",
["Bas_100"] = "Bas 100",
["Bodo"] = "Bodo",
["Jokkmokk"] = "Jokkmokk",
["Kalixfors"] = "Kalixfors",
["Kemi_Tornio"] = "Kemi Tornio",
["Kiruna"] = "Kiruna",
["Lakselv"] = "Lakselv",
["Monchegorsk"] = "Monchegorsk",
["Murmansk_International"] = "Murmansk International",
["Olenegorsk"] = "Olenegorsk",
["Olenya"] = "Olenya",
["Rovaniemi"] = "Rovaniemi",
["Severomorsk1"] = "Severomorsk1",
["Severomorsk3"] = "Severomorsk3",
["Severomorsk_1"] = "Severomorsk-1",
["Severomorsk_3"] = "Severomorsk-3",
}
--- AIRBASE.ParkingSpot ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy".

View File

@ -1207,6 +1207,7 @@ function GROUP:GetCoordinate()
-- no luck, try the API way
local DCSGroup = Group.getByName(self.GroupName)
if DCSGroup then
local DCSUnits = DCSGroup:getUnits() or {}
for _,_unit in pairs(DCSUnits) do
if Object.isExist(_unit) then
@ -1219,6 +1220,7 @@ function GROUP:GetCoordinate()
end
end
end
end
BASE:E( { "Cannot GetCoordinate", Group = self, Alive = self:IsAlive() } )