Compare commits

..

38 Commits

Author SHA1 Message Date
Applevangelist a3d77a5a71 Merge remote-tracking branch 'origin/master' into develop 2025-12-30 09:26:48 +01:00
Applevangelist bff5f79282 Merge remote-tracking branch 'origin/master' into develop 2025-12-29 18:09:16 +01:00
Applevangelist a49288200e Merge remote-tracking branch 'origin/master' into develop 2025-12-29 14:01:43 +01:00
Applevangelist fc809964c7 Merge remote-tracking branch 'origin/master' into develop 2025-12-29 10:48:57 +01:00
Applevangelist 3f5936bceb Merge remote-tracking branch 'origin/master' into develop 2025-12-28 17:56:48 +01:00
Applevangelist fef1976a6f Merge remote-tracking branch 'origin/master' into develop 2025-12-28 16:52:14 +01:00
Applevangelist d16eb74e1b Merge remote-tracking branch 'origin/master' into develop 2025-12-28 14:06:38 +01:00
Thomas 646fa8b7e6 Merge pull request #2485 from FlightControl-Master/master
Merge
2025-12-28 09:01:42 +01:00
Thomas 7ff8978ca7 Merge pull request #2483 from FlightControl-Master/master
Merge from master
2025-12-24 08:21:06 +01:00
Applevangelist 635c8dc2ad Merge remote-tracking branch 'origin/master' into develop 2025-12-23 17:17:34 +01:00
Applevangelist 022854fa37 Merge remote-tracking branch 'origin/master' into develop 2025-12-22 14:10:14 +01:00
Applevangelist 1f062fe7b4 Merge remote-tracking branch 'origin/master' into develop 2025-12-22 12:22:13 +01:00
Applevangelist b9be0341f5 Merge remote-tracking branch 'origin/master' into develop 2025-12-21 19:17:31 +01:00
Applevangelist 28e08035f2 Merge remote-tracking branch 'origin/master' into develop
# Conflicts:
#	Moose Development/Moose/Ops/EasyA2G.lua
#	Moose Development/Moose/Ops/EasyGCICAP.lua
2025-12-21 15:40:46 +01:00
Applevangelist 3cac18f634 Merge remote-tracking branch 'origin/master' into develop 2025-12-21 12:50:04 +01:00
Applevangelist 1fbfc8f039 Merge remote-tracking branch 'origin/master' into develop 2025-12-21 11:44:00 +01:00
Thomas 47bb760d86 Merge pull request #2481 from FlightControl-Master/master
Merge
2025-12-21 09:26:19 +01:00
Thomas c24acd2681 Merge pull request #2478 from FlightControl-Master/master
Merge
2025-12-20 14:06:52 +01:00
Thomas b63fe40cc8 Merge pull request #2475 from FlightControl-Master/master
Merge from master
2025-12-18 10:20:06 +01:00
Thomas e41eec2238 Merge pull request #2473 from FlightControl-Master/master
Update Database.lua
2025-12-17 19:37:36 +01:00
Applevangelist 3c996b6dd7 Merge remote-tracking branch 'origin/master' into develop 2025-12-17 11:32:28 +01:00
Thomas 2012e81acb Merge pull request #2471 from FlightControl-Master/master
Merge from master
2025-12-16 08:40:00 +01:00
Thomas 4c841fd1d2 Merge pull request #2469 from FlightControl-Master/master
Merge from master
2025-12-15 17:41:37 +01:00
Applevangelist ef5c7e5972 Merge remote-tracking branch 'origin/master' into develop 2025-12-15 12:13:32 +01:00
Applevangelist 21c744b27a Merge remote-tracking branch 'origin/master' into develop 2025-12-15 09:41:13 +01:00
Applevangelist 38b36c0344 Merge remote-tracking branch 'origin/master' into develop 2025-12-14 16:05:44 +01:00
Applevangelist 5145dd14ea Merge remote-tracking branch 'origin/master' into develop 2025-12-14 14:37:36 +01:00
Applevangelist 51f40081f3 docu header 2025-12-12 12:51:44 +01:00
Applevangelist 7e878b5702 Merge remote-tracking branch 'origin/develop' into develop 2025-12-12 10:51:58 +01:00
Applevangelist 804e0ed69d Docu fixes 2025-12-12 10:51:55 +01:00
Thomas 46c0d47175 Update build-docs.yml 2025-12-11 16:37:30 +01:00
Applevangelist 147df1498e Merge remote-tracking branch 'origin/master' into develop 2025-12-11 15:48:41 +01:00
Applevangelist f9410a9169 #EASYA2G - Initial release 2025-12-11 15:48:13 +01:00
Applevangelist 9b3aa423aa xx 2025-12-11 09:34:19 +01:00
Applevangelist 07876cb46c Merge remote-tracking branch 'origin/develop' into develop 2025-12-10 11:30:59 +01:00
Applevangelist de48701d15 Merge remote-tracking branch 'origin/master' into develop 2025-12-10 11:30:55 +01:00
Applevangelist c5678404d5 Merge remote-tracking branch 'origin/master' into develop
# Conflicts:
#	Moose Development/Moose/Functional/PseudoATC.lua
2025-12-10 11:29:39 +01:00
Thomas 4e2dcb1c05 Merge pull request #2466 from FlightControl-Master/master
xx
2025-12-10 09:58:38 +01:00
29 changed files with 414 additions and 1358 deletions
+2 -2
View File
@@ -77,11 +77,11 @@ jobs:
- name: Install markdown (prereq for LuaDocumentor) - name: Install markdown (prereq for LuaDocumentor)
run: | run: |
sudo luarocks install markdown 0.32-2 sudo luarocks install markdown 0.33-1
- name: Install penlight (prereq for LuaDocumentor) - name: Install penlight (prereq for LuaDocumentor)
run: | run: |
sudo luarocks install penlight 1.11.0-1 sudo luarocks install penlight 1.14.0-3
- name: Install metalua-compiler (prereq for LuaDocumentor) - name: Install metalua-compiler (prereq for LuaDocumentor)
run: | run: |
+2 -2
View File
@@ -11,8 +11,8 @@
-- @module AI.AI_A2G_BAI -- @module AI.AI_A2G_BAI
-- @image AI_Air_To_Ground_Engage.JPG -- @image AI_Air_To_Ground_Engage.JPG
-- @type AI_A2G_BAI --- @type AI_A2G_BAI
-- @extends AI.AI_A2A_Engage#AI_A2A_Engage -- TODO: Documentation. This class does not exist, unable to determine what it extends. -- @extends AI.AI_Air_Engage#AI_A2A_Engage -- TODO: Documentation. This class does not exist, unable to determine what it extends.
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders. --- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
-- --
+1 -1
View File
@@ -31,7 +31,7 @@
-- @module AI.AI_CAP -- @module AI.AI_CAP
-- @image AI_Combat_Air_Patrol.JPG -- @image AI_Combat_Air_Patrol.JPG
-- @type AI_CAP_ZONE --- @type AI_CAP_ZONE
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling. -- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling.
-- @field Core.Zone#ZONE_BASE TargetZone The @{Core.Zone} where the patrol needs to be executed. -- @field Core.Zone#ZONE_BASE TargetZone The @{Core.Zone} where the patrol needs to be executed.
-- @extends AI.AI_Patrol#AI_PATROL_ZONE -- @extends AI.AI_Patrol#AI_PATROL_ZONE
+37 -19
View File
@@ -184,7 +184,6 @@ EVENT = {
ClassName = "EVENT", ClassName = "EVENT",
ClassID = 0, ClassID = 0,
MissionEnd = false, MissionEnd = false,
CreateMarkCoordinateOnEvent = false,
} }
world.event.S_EVENT_NEW_CARGO = world.event.S_EVENT_MAX + 1000 world.event.S_EVENT_NEW_CARGO = world.event.S_EVENT_MAX + 1000
@@ -340,18 +339,14 @@ EVENTS = {
-- @field #string WeaponName Name of the weapon. -- @field #string WeaponName Name of the weapon.
-- @field DCS#Unit WeaponTgtDCSUnit Target DCS unit of the weapon. -- @field DCS#Unit WeaponTgtDCSUnit Target DCS unit of the weapon.
-- --
-- @field Cargo.Cargo#CARGO Cargo The cargo object.
-- @field #string CargoName The name of the cargo object.
--
-- @field Core.Zone#ZONE Zone The zone object. -- @field Core.Zone#ZONE Zone The zone object.
-- @field #string ZoneName The name of the zone. -- @field #string ZoneName The name of the zone.
-- --
-- @field Wrapper.DynamicCargo#DYNAMICCARGO IniDynamicCargo The dynamic cargo object. -- @field Wrapper.DynamicCargo#DYNAMICCARGO IniDynamicCargo The dynamic cargo object.
-- @field #string IniDynamicCargoName The dynamic cargo unit name. -- @field #string IniDynamicCargoName The dynamic cargo unit name.
--
-- @field #number MarkCoalition Coalition of a marker (if any)
-- @field DCS#Vec3 MarkVec3 Position of a marker
-- @field #string MarkText Text content of a marker, if any
-- @field #number MarkID ID of the marker, for deletion
-- @field #number MarkGroupID Group ID of the group that created the marker
-- @field Core.Point#COORDINATE Coordinate object of the marker, only filled if EVENT.CreateMarkCoordinateOnEvent is set to true (off by default)
@@ -1068,6 +1063,36 @@ end
do -- Event Creation do -- Event Creation
--- Creation of a New Cargo Event.
-- @param #EVENT self
-- @param AI.AI_Cargo#AI_CARGO Cargo The Cargo created.
function EVENT:CreateEventNewCargo( Cargo )
self:F( { Cargo } )
local Event = {
id = EVENTS.NewCargo,
time = timer.getTime(),
cargo = Cargo,
}
world.onEvent( Event )
end
--- Creation of a Cargo Deletion Event.
-- @param #EVENT self
-- @param AI.AI_Cargo#AI_CARGO Cargo The Cargo created.
function EVENT:CreateEventDeleteCargo( Cargo )
self:F( { Cargo } )
local Event = {
id = EVENTS.DeleteCargo,
time = timer.getTime(),
cargo = Cargo,
}
world.onEvent( Event )
end
--- Creation of a New Zone Event. --- Creation of a New Zone Event.
-- @param #EVENT self -- @param #EVENT self
-- @param Core.Zone#ZONE_BASE Zone The Zone created. -- @param Core.Zone#ZONE_BASE Zone The Zone created.
@@ -1336,8 +1361,7 @@ function EVENT:onEvent( Event )
Event.IniDynamicCargoName = Event.IniUnitName Event.IniDynamicCargoName = Event.IniUnitName
Event.IniPlayerName = string.match(Event.IniUnitName,"^(.+)|%d%d:%d%d|PKG%d+") Event.IniPlayerName = string.match(Event.IniUnitName,"^(.+)|%d%d:%d%d|PKG%d+")
else else
--Event.IniUnit = CARGO:FindByName( Event.IniDCSUnitName ) Event.IniUnit = CARGO:FindByName( Event.IniDCSUnitName )
Event.IniUnit = STATIC:FindByName( Event.IniDCSUnitName, false )
end end
Event.IniCoalition = Event.IniDCSUnit:getCoalition() Event.IniCoalition = Event.IniDCSUnit:getCoalition()
Event.IniCategory = Event.IniDCSUnit:getDesc().category Event.IniCategory = Event.IniDCSUnit:getDesc().category
@@ -1350,9 +1374,7 @@ function EVENT:onEvent( Event )
Event.IniDCSUnit = Event.initiator Event.IniDCSUnit = Event.initiator
Event.IniDCSUnitName = ( Event.IniDCSUnit and Event.IniDCSUnit.getName ) and Event.IniDCSUnit:getName() or "Scenery no name "..math.random(1,20000) Event.IniDCSUnitName = ( Event.IniDCSUnit and Event.IniDCSUnit.getName ) and Event.IniDCSUnit:getName() or "Scenery no name "..math.random(1,20000)
Event.IniUnitName = Event.IniDCSUnitName Event.IniUnitName = Event.IniDCSUnitName
local ID = (Event.IniDCSUnit and Event.IniDCSUnit.getID) and Event.IniDCSUnit:getID() or Event.IniDCSUnitName Event.IniUnit = SCENERY:Register( Event.IniDCSUnitName, Event.initiator )
Event.IniUnit = (_SCENERY ~= nil) and _SCENERY[ID] or nil
--Event.IniUnit = SCENERY:Register( Event.IniDCSUnitName, Event.initiator )
Event.IniCategory = (Event.IniDCSUnit and Event.IniDCSUnit.getDesc ) and Event.IniDCSUnit:getDesc().category Event.IniCategory = (Event.IniDCSUnit and Event.IniDCSUnit.getDesc ) and Event.IniDCSUnit:getDesc().category
Event.IniTypeName = (Event.initiator and Event.initiator.isExist Event.IniTypeName = (Event.initiator and Event.initiator.isExist
and Event.initiator:isExist() and Event.IniDCSUnit and Event.IniDCSUnit.getTypeName) and Event.IniDCSUnit:getTypeName() or "SCENERY" and Event.initiator:isExist() and Event.IniDCSUnit and Event.IniDCSUnit.getTypeName) and Event.IniDCSUnit:getTypeName() or "SCENERY"
@@ -1456,9 +1478,7 @@ function EVENT:onEvent( Event )
Event.TgtDCSUnitName = Event.TgtDCSUnit.getName and Event.TgtDCSUnit:getName() or nil Event.TgtDCSUnitName = Event.TgtDCSUnit.getName and Event.TgtDCSUnit:getName() or nil
if Event.TgtDCSUnitName~=nil then if Event.TgtDCSUnitName~=nil then
Event.TgtUnitName = Event.TgtDCSUnitName Event.TgtUnitName = Event.TgtDCSUnitName
local ID = (Event.TgtDCSUnit and Event.TgtDCSUnit.getID) and Event.TgtDCSUnit:getID() or Event.TgtDCSUnitName Event.TgtUnit = SCENERY:Register( Event.TgtDCSUnitName, Event.target )
--Event.TgtUnit = SCENERY:Register( Event.TgtDCSUnitName, Event.target )
Event.TgtUnit = (_SCENERY ~= nil) and _SCENERY[ID] or nil
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName() Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
end end
@@ -1499,9 +1519,7 @@ function EVENT:onEvent( Event )
if Event.idx then if Event.idx then
Event.MarkID=Event.idx Event.MarkID=Event.idx
Event.MarkVec3=Event.pos Event.MarkVec3=Event.pos
if self.CreateMarkCoordinateOnEvent == true then Event.MarkCoordinate=COORDINATE:NewFromVec3(Event.pos)
Event.MarkCoordinate=COORDINATE:NewFromVec3(Event.pos)
end
Event.MarkText=Event.text Event.MarkText=Event.text
Event.MarkCoalition=Event.coalition Event.MarkCoalition=Event.coalition
Event.IniCoalition=Event.coalition Event.IniCoalition=Event.coalition
+1 -14
View File
@@ -3281,6 +3281,7 @@ do -- COORDINATE
return delta/60 return delta/60
end end
--- Return a BR string from a COORDINATE to the COORDINATE. --- Return a BR string from a COORDINATE to the COORDINATE.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #COORDINATE FromCoordinate The coordinate to measure the distance and the bearing from. -- @param #COORDINATE FromCoordinate The coordinate to measure the distance and the bearing from.
@@ -3294,20 +3295,6 @@ do -- COORDINATE
local Distance = self:Get2DDistance( FromCoordinate ) local Distance = self:Get2DDistance( FromCoordinate )
return "BR, " .. self:GetBRText( AngleRadians, Distance, Settings, nil, MagVar, Precision ) return "BR, " .. self:GetBRText( AngleRadians, Distance, Settings, nil, MagVar, Precision )
end end
--- Return a Bearing string from a COORDINATE to the (self) COORDINATE.
-- @param #COORDINATE self
-- @param #COORDINATE FromCoordinate The coordinate to measure the distance and the bearing from.
-- @param Core.Settings#SETTINGS Settings (optional) The settings. Can be nil, and in this case the default settings are used. If you want to specify your own settings, use the _SETTINGS object.
-- @param #boolean MagVar If true, also get angle in MagVar for BR/BRA
-- @param #number Precision Rounding precision, currently full km as default (=0)
-- @return #string The BR text.
function COORDINATE:ToStringBearing( FromCoordinate, Settings, MagVar, Precision )
local DirectionVec3 = FromCoordinate:GetDirectionVec3( self )
local AngleRadians = self:GetAngleRadians( DirectionVec3 )
--local Distance = self:Get2DDistance( FromCoordinate )
return self:GetBearingText(AngleRadians,Precision,Settings,MagVar)
end
--- Return a BRA string from a COORDINATE to the COORDINATE. --- Return a BRA string from a COORDINATE to the COORDINATE.
-- @param #COORDINATE self -- @param #COORDINATE self
+13 -12
View File
@@ -693,7 +693,7 @@ end
function AUTOLASE:GetLosFromUnit(Unit) function AUTOLASE:GetLosFromUnit(Unit)
local lasedistance = self.LaseDistance local lasedistance = self.LaseDistance
local unitheight = Unit:GetHeight() local unitheight = Unit:GetHeight()
local coord = Unit:GetCoord() local coord = Unit:GetCoordinate()
local landheight = coord:GetLandHeight() local landheight = coord:GetLandHeight()
local asl = unitheight - landheight local asl = unitheight - landheight
if asl > 100 then if asl > 100 then
@@ -845,7 +845,7 @@ function AUTOLASE:ShowStatus(Group,Unit)
locationstring = entry.coordinate:ToStringLLDDM(settings) locationstring = entry.coordinate:ToStringLLDDM(settings)
elseif settings:IsA2G_BR() then elseif settings:IsA2G_BR() then
-- attention this is the distance from the ASKING unit to target, not from RECCE to target! -- attention this is the distance from the ASKING unit to target, not from RECCE to target!
local startcoordinate = Unit:GetCoord() or Group:GetCoord() local startcoordinate = Unit:GetCoordinate() or Group:GetCoordinate()
locationstring = entry.coordinate:ToStringBR(startcoordinate,settings,false,self.RoundingPrecision) locationstring = entry.coordinate:ToStringBR(startcoordinate,settings,false,self.RoundingPrecision)
end end
end end
@@ -963,8 +963,8 @@ function AUTOLASE:CanLase(Recce,Unit)
end end
end end
-- calculate LOS -- calculate LOS
local reccecoord = Recce:GetCoord() local reccecoord = Recce:GetCoordinate()
local unitcoord = Unit:GetCoord() local unitcoord = Unit:GetCoordinate()
local islos = reccecoord:IsLOS(unitcoord,2.5) local islos = reccecoord:IsLOS(unitcoord,2.5)
-- calculate distance -- calculate distance
local distance = math.floor(reccecoord:Get3DDistance(unitcoord)) local distance = math.floor(reccecoord:Get3DDistance(unitcoord))
@@ -1020,8 +1020,8 @@ function AUTOLASE:_Prescient()
self:T(self.lid.."Checking possibly visible STATICs for Recce "..unit:GetName()) self:T(self.lid.."Checking possibly visible STATICs for Recce "..unit:GetName())
for _,_static in pairs(Statics) do -- DCS static object here for _,_static in pairs(Statics) do -- DCS static object here
local static = STATIC:Find(_static) local static = STATIC:Find(_static)
if static and static:GetCoalition() ~= self.coalition and static:GetCoord() then if static and static:GetCoalition() ~= self.coalition and static:GetCoordinate() then
local IsLOS = position:IsLOS(static:GetCoord()) local IsLOS = position:IsLOS(static:GetCoordinate())
if IsLOS then if IsLOS then
unit:KnowUnit(static,true,true) unit:KnowUnit(static,true,true)
end end
@@ -1081,7 +1081,7 @@ function AUTOLASE:onafterMonitor(From, Event, To)
local threat = contact.threatlevel or 0 local threat = contact.threatlevel or 0
local reccegrp = UNIT:FindByName(reccename) local reccegrp = UNIT:FindByName(reccename)
if reccegrp then if reccegrp then
local reccecoord = reccegrp:GetCoord() local reccecoord = reccegrp:GetCoordinate()
local distance = math.floor(reccecoord:Get3DDistance(coord)) local distance = math.floor(reccecoord:Get3DDistance(coord))
local text = string.format("%s of %s | Distance %d km | Threatlevel %d",contact.attribute, contact.groupname, math.floor(distance/1000), contact.threatlevel) local text = string.format("%s of %s | Distance %d km | Threatlevel %d",contact.attribute, contact.groupname, math.floor(distance/1000), contact.threatlevel)
report:Add(text) report:Add(text)
@@ -1120,6 +1120,7 @@ function AUTOLASE:onafterMonitor(From, Event, To)
local unit = _unit -- Wrapper.Unit#UNIT local unit = _unit -- Wrapper.Unit#UNIT
if unit and unit:IsAlive() then if unit and unit:IsAlive() then
local threat = unit:GetThreatLevel() local threat = unit:GetThreatLevel()
local coord = unit:GetCoordinate()
if threat >= self.minthreatlevel then if threat >= self.minthreatlevel then
local unitname = unit:GetName() local unitname = unit:GetName()
-- prefer radar units -- prefer radar units
@@ -1175,16 +1176,16 @@ function AUTOLASE:onafterMonitor(From, Event, To)
local code = self:GetLaserCode(reccename) local code = self:GetLaserCode(reccename)
local spot = SPOT:New(recce) local spot = SPOT:New(recce)
spot:LaseOn(unit,code,self.LaseDuration) spot:LaseOn(unit,code,self.LaseDuration)
local locationstring = unit:GetCoord():ToStringLLDDM() local locationstring = unit:GetCoordinate():ToStringLLDDM()
if _SETTINGS:IsA2G_MGRS() then if _SETTINGS:IsA2G_MGRS() then
local precision = _SETTINGS:GetMGRS_Accuracy() local precision = _SETTINGS:GetMGRS_Accuracy()
local settings = {} local settings = {}
settings.MGRS_Accuracy = precision settings.MGRS_Accuracy = precision
locationstring = unit:GetCoord():ToStringMGRS(settings) locationstring = unit:GetCoordinate():ToStringMGRS(settings)
elseif _SETTINGS:IsA2G_LL_DMS() then elseif _SETTINGS:IsA2G_LL_DMS() then
locationstring = unit:GetCoord():ToStringLLDMS(_SETTINGS) locationstring = unit:GetCoordinate():ToStringLLDMS(_SETTINGS)
elseif _SETTINGS:IsA2G_BR() then elseif _SETTINGS:IsA2G_BR() then
locationstring = unit:GetCoord():ToStringBULLS(self.coalition,_SETTINGS) locationstring = unit:GetCoordinate():ToStringBULLS(self.coalition,_SETTINGS)
end end
local laserspot = { -- #AUTOLASE.LaserSpot local laserspot = { -- #AUTOLASE.LaserSpot
@@ -1197,7 +1198,7 @@ function AUTOLASE:onafterMonitor(From, Event, To)
unitname = unitname, unitname = unitname,
reccename = reccename, reccename = reccename,
unittype = unit:GetTypeName(), unittype = unit:GetTypeName(),
coordinate = unit:GetCoord(), coordinate = unit:GetCoordinate(),
} }
if self.smoketargets then if self.smoketargets then
local coord = unit:GetCoordinate() local coord = unit:GetCoordinate()
+51 -178
View File
@@ -22,7 +22,7 @@
-- @module Functional.Mantis -- @module Functional.Mantis
-- @image Functional.Mantis.jpg -- @image Functional.Mantis.jpg
-- --
-- Last Update: January 2026 -- Last Update: December 2025
------------------------------------------------------------------------- -------------------------------------------------------------------------
--- **MANTIS** class, extends Core.Base#BASE --- **MANTIS** class, extends Core.Base#BASE
@@ -283,7 +283,7 @@
MANTIS = { MANTIS = {
ClassName = "MANTIS", ClassName = "MANTIS",
name = "mymantis", name = "mymantis",
version = "0.9.44", version = "0.9.42",
SAM_Templates_Prefix = "", SAM_Templates_Prefix = "",
SAM_Group = nil, SAM_Group = nil,
EWR_Templates_Prefix = "", EWR_Templates_Prefix = "",
@@ -337,8 +337,6 @@ MANTIS = {
DetectAccoustic = false, DetectAccoustic = false,
DetectAccousticRadius = 2000, DetectAccousticRadius = 2000,
DetectAccousticCategories = {Unit.Category.HELICOPTER}, DetectAccousticCategories = {Unit.Category.HELICOPTER},
ARMWeaponSeen = {},
InboundARMs = {},
} }
--- Advanced state enumerator --- Advanced state enumerator
@@ -374,25 +372,24 @@ MANTIS.radiusscale[MANTIS.SamType.POINT] = 3
-- @field #string Type #MANTIS.SamType of SAM, i.e. SHORT, MEDIUM or LONG (range) -- @field #string Type #MANTIS.SamType of SAM, i.e. SHORT, MEDIUM or LONG (range)
-- @field #string Radar Radar typename on unit level (used as key) -- @field #string Radar Radar typename on unit level (used as key)
-- @field #string Point Point defense capable -- @field #string Point Point defense capable
-- @field ARMCapacit ARMCapacity ie how many (H)ARMs the system can defend at the same time
MANTIS.SamData = { MANTIS.SamData = {
["Hawk"] = { Range=35, Blindspot=0, Height=12, Type="Medium", Radar="Hawk" }, -- measures in km ["Hawk"] = { Range=35, Blindspot=0, Height=12, Type="Medium", Radar="Hawk" }, -- measures in km
["NASAMS"] = { Range=14, Blindspot=0, Height=7, Type="Short", Radar="NSAMS", ARMCapacity=1 }, -- AIM 120B ["NASAMS"] = { Range=14, Blindspot=0, Height=7, Type="Short", Radar="NSAMS" }, -- AIM 120B
["Patriot"] = { Range=99, Blindspot=0, Height=25, Type="Long", Radar="Patriot str" }, ["Patriot"] = { Range=99, Blindspot=0, Height=25, Type="Long", Radar="Patriot str" },
["Rapier"] = { Range=10, Blindspot=0, Height=3, Type="Short", Radar="rapier" }, ["Rapier"] = { Range=10, Blindspot=0, Height=3, Type="Short", Radar="rapier" },
["SA-2"] = { Range=40, Blindspot=7, Height=25, Type="Medium", Radar="S_75M_Volhov" }, ["SA-2"] = { Range=40, Blindspot=7, Height=25, Type="Medium", Radar="S_75M_Volhov" },
["SA-3"] = { Range=18, Blindspot=6, Height=18, Type="Short", Radar="5p73 s-125 ln" }, ["SA-3"] = { Range=18, Blindspot=6, Height=18, Type="Short", Radar="5p73 s-125 ln" },
["SA-5"] = { Range=250, Blindspot=7, Height=40, Type="Long", Radar="5N62V" }, ["SA-5"] = { Range=250, Blindspot=7, Height=40, Type="Long", Radar="5N62V" },
["SA-6"] = { Range=25, Blindspot=0, Height=8, Type="Medium", Radar="1S91" }, ["SA-6"] = { Range=25, Blindspot=0, Height=8, Type="Medium", Radar="1S91" },
["SA-10"] = { Range=119, Blindspot=0, Height=18, Type="Long" , Radar="S-300PS 4", ARMCapacity=4}, ["SA-10"] = { Range=119, Blindspot=0, Height=18, Type="Long" , Radar="S-300PS 4"},
["SA-11"] = { Range=35, Blindspot=0, Height=20, Type="Medium", Radar="SA-11" }, ["SA-11"] = { Range=35, Blindspot=0, Height=20, Type="Medium", Radar="SA-11" },
["Roland"] = { Range=6, Blindspot=0, Height=5, Type="Short", Radar="Roland", ARMCapacity=1 }, ["Roland"] = { Range=6, Blindspot=0, Height=5, Type="Short", Radar="Roland" },
["Gepard"] = { Range=5, Blindspot=0, Height=4, Type="Point", Radar="Gepard" }, ["Gepard"] = { Range=5, Blindspot=0, Height=4, Type="Point", Radar="Gepard" },
["HQ-7"] = { Range=12, Blindspot=0, Height=3, Type="Short", Radar="HQ-7" }, ["HQ-7"] = { Range=12, Blindspot=0, Height=3, Type="Short", Radar="HQ-7" },
["SA-9"] = { Range=4, Blindspot=0, Height=3, Type="Point", Radar="Strela", Point="true" }, ["SA-9"] = { Range=4, Blindspot=0, Height=3, Type="Point", Radar="Strela", Point="true" },
["SA-8"] = { Range=10, Blindspot=0, Height=5, Type="Short", Radar="Osa 9A33" }, ["SA-8"] = { Range=10, Blindspot=0, Height=5, Type="Short", Radar="Osa 9A33" },
["SA-19"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Tunguska" }, ["SA-19"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Tunguska" },
["SA-15"] = { Range=11, Blindspot=0, Height=6, Type="Point", Radar="Tor 9A331", Point="true", ARMCapacity=2 }, ["SA-15"] = { Range=11, Blindspot=0, Height=6, Type="Point", Radar="Tor 9A331", Point="true" },
["SA-13"] = { Range=5, Blindspot=0, Height=3, Type="Point", Radar="Strela", Point="true" }, ["SA-13"] = { Range=5, Blindspot=0, Height=3, Type="Point", Radar="Strela", Point="true" },
["Avenger"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Avenger" }, ["Avenger"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Avenger" },
["Chaparral"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Chaparral" }, ["Chaparral"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Chaparral" },
@@ -400,23 +397,23 @@ MANTIS.SamData = {
["Silkworm"] = { Range=90, Blindspot=1, Height=0.2, Type="Long", Radar="Silkworm" }, ["Silkworm"] = { Range=90, Blindspot=1, Height=0.2, Type="Long", Radar="Silkworm" },
["C-RAM"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="HEMTT_C-RAM_Phalanx", Point="true" }, ["C-RAM"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="HEMTT_C-RAM_Phalanx", Point="true" },
-- units from HDS Mod, multi launcher options is tricky -- units from HDS Mod, multi launcher options is tricky
["SA-10B"] = { Range=75, Blindspot=0, Height=18, Type="Medium" , Radar="SA-10B", ARMCapacity=4}, ["SA-10B"] = { Range=75, Blindspot=0, Height=18, Type="Medium" , Radar="SA-10B"},
["SA-17"] = { Range=50, Blindspot=3, Height=50, Type="Medium", Radar="SA-17", ARMCapacity=4 }, ["SA-17"] = { Range=50, Blindspot=3, Height=50, Type="Medium", Radar="SA-17" },
["SA-20A"] = { Range=150, Blindspot=5, Height=27, Type="Long" , Radar="S-300PMU1", ARMCapacity=16}, ["SA-20A"] = { Range=150, Blindspot=5, Height=27, Type="Long" , Radar="S-300PMU1"},
["SA-20B"] = { Range=200, Blindspot=4, Height=27, Type="Long" , Radar="S-300PMU2", ARMCapacity=18}, ["SA-20B"] = { Range=200, Blindspot=4, Height=27, Type="Long" , Radar="S-300PMU2"},
["SA-21"] = { Range=380, Blindspot=5, Height=30, Type="Long" , Radar="92N6E"}, ["SA-21"] = { Range=380, Blindspot=5, Height=30, Type="Long" , Radar="92N6E"},
["S-300VM"] = { Range=200, Blindspot=5, Height=30, Type="Long" , Radar="9S32M", ARMCapacity=4}, ["S-300VM"] = { Range=200, Blindspot=5, Height=30, Type="Long" , Radar="9S32M"},
["S-300V4"] = { Range=380, Blindspot=5, Height=30, Type="Long" , Radar="9S32M", ARMCapacity=4}, ["S-300V4"] = { Range=380, Blindspot=5, Height=30, Type="Long" , Radar="9S32M"},
["S-400"] = { Range=250, Blindspot=5, Height=27, Type="Long" , Radar="92N6E", ARMCapacity=4}, ["S-400"] = { Range=250, Blindspot=5, Height=27, Type="Long" , Radar="92N6E"},
["HQ-2"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" }, ["HQ-2"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" },
["TAMIR IDFA"] = { Range=20, Blindspot=0.6, Height=12.3, Type="Short", Radar="IRON_DOME_LN" }, ["TAMIR IDFA"] = { Range=20, Blindspot=0.6, Height=12.3, Type="Short", Radar="IRON_DOME_LN" },
["STUNNER IDFA"] = { Range=250, Blindspot=1, Height=45, Type="Long", Radar="DAVID_SLING_LN" }, ["STUNNER IDFA"] = { Range=250, Blindspot=1, Height=45, Type="Long", Radar="DAVID_SLING_LN" },
["Nike"] = { Range=155, Blindspot=6, Height=30, Type="Long", Radar="HIPAR" }, ["Nike"] = { Range=155, Blindspot=6, Height=30, Type="Long", Radar="HIPAR" },
["Dog Ear"] = { Range=11, Blindspot=0, Height=9, Type="Point", Radar="Dog Ear", Point="true" }, ["Dog Ear"] = { Range=11, Blindspot=0, Height=9, Type="Point", Radar="Dog Ear", Point="true" },
-- CH Added to DCS core 2.9.19.x -- CH Added to DCS core 2.9.19.x
["Pantsir S1"] = { Range=20, Blindspot=1.2, Height=15, Type="Point", Radar="PantsirS1" , Point="true", ARMCapacity=3 }, ["Pantsir S1"] = { Range=20, Blindspot=1.2, Height=15, Type="Point", Radar="PantsirS1" , Point="true" },
["Tor M2"] = { Range=12, Blindspot=1, Height=10, Type="Point", Radar="TorM2", Point="true", ARMCapacity=4 }, ["Tor M2"] = { Range=12, Blindspot=1, Height=10, Type="Point", Radar="TorM2", Point="true" },
["IRIS-T SLM"] = { Range=40, Blindspot=0.5, Height=20, Type="Medium", Radar="CH_IRIST_SLM", ARMCapacity=12 }, -- 4 per starter, usually 3 starters in a battery ["IRIS-T SLM"] = { Range=40, Blindspot=0.5, Height=20, Type="Medium", Radar="CH_IRIST_SLM" },
} }
--- SAM data HDS --- SAM data HDS
@@ -432,13 +429,13 @@ MANTIS.SamDataHDS = {
-- group name MUST contain HDS to ID launcher type correctly! -- group name MUST contain HDS to ID launcher type correctly!
["SA-2 HDS"] = { Range=56, Blindspot=7, Height=30, Type="Medium", Radar="V759" }, ["SA-2 HDS"] = { Range=56, Blindspot=7, Height=30, Type="Medium", Radar="V759" },
["SA-3 HDS"] = { Range=20, Blindspot=6, Height=30, Type="Short", Radar="V-601P" }, ["SA-3 HDS"] = { Range=20, Blindspot=6, Height=30, Type="Short", Radar="V-601P" },
["SA-10B HDS"] = { Range=90, Blindspot=5, Height=25, Type="Long" , Radar="5P85CE ln", ARMCapacity=8}, -- V55RUD ["SA-10B HDS"] = { Range=90, Blindspot=5, Height=25, Type="Long" , Radar="5P85CE ln"}, -- V55RUD
["SA-10C HDS"] = { Range=75, Blindspot=5, Height=25, Type="Long" , Radar="5P85SE ln", ARMCapacity=3}, -- V55RUD ["SA-10C HDS"] = { Range=75, Blindspot=5, Height=25, Type="Long" , Radar="5P85SE ln"}, -- V55RUD
["SA-17 HDS"] = { Range=50, Blindspot=3, Height=50, Type="Medium", Radar="SA-17", ARMCapacity=4 }, ["SA-17 HDS"] = { Range=50, Blindspot=3, Height=50, Type="Medium", Radar="SA-17 " },
["SA-12 HDS 2"] = { Range=100, Blindspot=13, Height=30, Type="Long" , Radar="S-300V 9A82 l", ARMCapacity=12}, ["SA-12 HDS 2"] = { Range=100, Blindspot=13, Height=30, Type="Long" , Radar="S-300V 9A82 l"},
["SA-12 HDS 1"] = { Range=75, Blindspot=6, Height=25, Type="Long" , Radar="S-300V 9A83 l", ARMCapacity=12}, ["SA-12 HDS 1"] = { Range=75, Blindspot=6, Height=25, Type="Long" , Radar="S-300V 9A83 l"},
["SA-23 HDS 2"] = { Range=200, Blindspot=5, Height=37, Type="Long", Radar="S-300VM 9A82ME", ARMCapacity=14 }, ["SA-23 HDS 2"] = { Range=200, Blindspot=5, Height=37, Type="Long", Radar="S-300VM 9A82ME" },
["SA-23 HDS 1"] = { Range=100, Blindspot=1, Height=50, Type="Long", Radar="S-300VM 9A83ME", ARMCapacity=14 }, ["SA-23 HDS 1"] = { Range=100, Blindspot=1, Height=50, Type="Long", Radar="S-300VM 9A83ME" },
["HQ-2 HDS"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" }, ["HQ-2 HDS"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" },
["SAMPT Block 1 HDS"] = { Range=120, Blindspot=1, Height=20, Type="long", Radar="SAMPT_MLT_Blk1" }, -- Block 1 Launcher ["SAMPT Block 1 HDS"] = { Range=120, Blindspot=1, Height=20, Type="long", Radar="SAMPT_MLT_Blk1" }, -- Block 1 Launcher
["SAMPT Block 1INT HDS"] = { Range=150, Blindspot=1, Height=25, Type="long", Radar="SAMPT_MLT_Blk1NT" }, -- Block 1-INT Launcher ["SAMPT Block 1INT HDS"] = { Range=150, Blindspot=1, Height=25, Type="long", Radar="SAMPT_MLT_Blk1NT" }, -- Block 1-INT Launcher
@@ -482,21 +479,21 @@ MANTIS.SamDataCH = {
-- https://www.currenthill.com/ -- https://www.currenthill.com/
-- group name MUST contain CHM to ID launcher type correctly! -- group name MUST contain CHM to ID launcher type correctly!
["2S38 CHM"] = { Range=6, Blindspot=0.1, Height=4.5, Type="Short", Radar="2S38" }, ["2S38 CHM"] = { Range=6, Blindspot=0.1, Height=4.5, Type="Short", Radar="2S38" },
["PantsirS1 CHM"] = { Range=20, Blindspot=1.2, Height=15, Type="Point", Radar="PantsirS1", Point="true", ARMCapacity=3 }, ["PantsirS1 CHM"] = { Range=20, Blindspot=1.2, Height=15, Type="Point", Radar="PantsirS1", Point="true" },
["PantsirS2 CHM"] = { Range=30, Blindspot=1.2, Height=18, Type="Medium", Radar="PantsirS2", ARMCapacity=4 }, ["PantsirS2 CHM"] = { Range=30, Blindspot=1.2, Height=18, Type="Medium", Radar="PantsirS2" },
["PGL-625 CHM"] = { Range=10, Blindspot=1, Height=5, Type="Short", Radar="PGL_625" }, ["PGL-625 CHM"] = { Range=10, Blindspot=1, Height=5, Type="Short", Radar="PGL_625" },
["HQ-17A CHM"] = { Range=15, Blindspot=1.5, Height=10, Type="Short", Radar="HQ17A" }, ["HQ-17A CHM"] = { Range=15, Blindspot=1.5, Height=10, Type="Short", Radar="HQ17A" },
["M903PAC2 CHM"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="MIM104_M903_PAC2" }, ["M903PAC2 CHM"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="MIM104_M903_PAC2" },
["M903PAC3 CHM"] = { Range=160, Blindspot=1, Height=40, Type="Long", Radar="MIM104_M903_PAC3" }, ["M903PAC3 CHM"] = { Range=160, Blindspot=1, Height=40, Type="Long", Radar="MIM104_M903_PAC3" },
["TorM2 CHM"] = { Range=12, Blindspot=1, Height=10, Type="Point", Radar="TorM2", Point="true", ARMCapacity=3 }, ["TorM2 CHM"] = { Range=12, Blindspot=1, Height=10, Type="Point", Radar="TorM2", Point="true" },
["TorM2K CHM"] = { Range=12, Blindspot=1, Height=10, Type="Point", Radar="TorM2K", Point="true", ARMCapacity=4 }, ["TorM2K CHM"] = { Range=12, Blindspot=1, Height=10, Type="Point", Radar="TorM2K", Point="true" },
["TorM2M CHM"] = { Range=16, Blindspot=1, Height=10, Type="Point", Radar="TorM2M", Point="true", ARMCapacity=4 }, ["TorM2M CHM"] = { Range=16, Blindspot=1, Height=10, Type="Point", Radar="TorM2M", Point="true" },
["NASAMS3-AMRAAMER CHM"] = { Range=50, Blindspot=2, Height=35.7, Type="Medium", Radar="CH_NASAMS3_LN_AMRAAM_ER" }, ["NASAMS3-AMRAAMER CHM"] = { Range=50, Blindspot=2, Height=35.7, Type="Medium", Radar="CH_NASAMS3_LN_AMRAAM_ER" },
["NASAMS3-AIM9X2 CHM"] = { Range=20, Blindspot=0.2, Height=18, Type="Short", Radar="CH_NASAMS3_LN_AIM9X2" }, ["NASAMS3-AIM9X2 CHM"] = { Range=20, Blindspot=0.2, Height=18, Type="Short", Radar="CH_NASAMS3_LN_AIM9X2" },
["C-RAM CHM"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="CH_Centurion_C_RAM", Point="true" }, ["C-RAM CHM"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="CH_Centurion_C_RAM", Point="true" },
["PGZ-09 CHM"] = { Range=4, Blindspot=0.5, Height=3, Type="Point", Radar="CH_PGZ09", Point="true" }, ["PGZ-09 CHM"] = { Range=4, Blindspot=0.5, Height=3, Type="Point", Radar="CH_PGZ09", Point="true" },
["S350-9M100 CHM"] = { Range=15, Blindspot=1, Height=8, Type="Short", Radar="CH_S350_50P6_9M100", ARMCapacity=20 }, ["S350-9M100 CHM"] = { Range=15, Blindspot=1, Height=8, Type="Short", Radar="CH_S350_50P6_9M100" },
["S350-9M96D CHM"] = { Range=150, Blindspot=2.5, Height=30, Type="Long", Radar="CH_S350_50P6_9M96D", ARMCapacity=20 }, ["S350-9M96D CHM"] = { Range=150, Blindspot=2.5, Height=30, Type="Long", Radar="CH_S350_50P6_9M96D" },
["LAV-AD CHM"] = { Range=8, Blindspot=0.16, Height=4.8, Type="Short", Radar="CH_LAVAD" }, ["LAV-AD CHM"] = { Range=8, Blindspot=0.16, Height=4.8, Type="Short", Radar="CH_LAVAD" },
["HQ-22 CHM"] = { Range=170, Blindspot=5, Height=27, Type="Long", Radar="CH_HQ22_LN" }, ["HQ-22 CHM"] = { Range=170, Blindspot=5, Height=27, Type="Long", Radar="CH_HQ22_LN" },
["PGZ-95 CHM"] = { Range=2.5, Blindspot=0.5, Height=2, Type="Point", Radar="CH_PGZ95",Point="true" }, ["PGZ-95 CHM"] = { Range=2.5, Blindspot=0.5, Height=2, Type="Point", Radar="CH_PGZ95",Point="true" },
@@ -508,8 +505,8 @@ MANTIS.SamDataCH = {
["Skynex CHM"] = { Range=3.5, Blindspot=0.1, Height=3.5, Type="Point", Radar="CH_SkynexHX", Point="true" }, ["Skynex CHM"] = { Range=3.5, Blindspot=0.1, Height=3.5, Type="Point", Radar="CH_SkynexHX", Point="true" },
["Skyshield CHM"] = { Range=3.5, Blindspot=0.1, Height=3.5, Type="Point", Radar="CH_Skyshield_Gun", Point="true" }, ["Skyshield CHM"] = { Range=3.5, Blindspot=0.1, Height=3.5, Type="Point", Radar="CH_Skyshield_Gun", Point="true" },
["WieselOzelot CHM"] = { Range=8, Blindspot=0.16, Height=4.8, Type="Short", Radar="CH_Wiesel2Ozelot" }, ["WieselOzelot CHM"] = { Range=8, Blindspot=0.16, Height=4.8, Type="Short", Radar="CH_Wiesel2Ozelot" },
["BukM3-9M317M CHM"] = { Range=70, Blindspot=0.25, Height=35, Type="Medium", Radar="CH_BukM3_9A317M", ARMCapacity=20 }, ["BukM3-9M317M CHM"] = { Range=70, Blindspot=0.25, Height=35, Type="Medium", Radar="CH_BukM3_9A317M" },
["BukM3-9M317MA CHM"] = { Range=70, Blindspot=0.25, Height=35, Type="Medium", Radar="CH_BukM3_9A317MA", ARMCapacity=20 }, ["BukM3-9M317MA CHM"] = { Range=70, Blindspot=0.25, Height=35, Type="Medium", Radar="CH_BukM3_9A317MA" },
["SkySabre CHM"] = { Range=30, Blindspot=0.5, Height=10, Type="Medium", Radar="CH_SkySabreLN" }, ["SkySabre CHM"] = { Range=30, Blindspot=0.5, Height=10, Type="Medium", Radar="CH_SkySabreLN" },
["Stormer CHM"] = { Range=7.5, Blindspot=0.3, Height=7, Type="Short", Radar="CH_StormerHVM" }, ["Stormer CHM"] = { Range=7.5, Blindspot=0.3, Height=7, Type="Short", Radar="CH_StormerHVM" },
["THAAD CHM"] = { Range=200, Blindspot=40, Height=150, Type="Long", Radar="CH_THAAD_M1120" }, ["THAAD CHM"] = { Range=200, Blindspot=40, Height=150, Type="Long", Radar="CH_THAAD_M1120" },
@@ -628,8 +625,6 @@ do
self.autoshorad = true self.autoshorad = true
self.ShoradGroupSet = SET_GROUP:New() -- Core.Set#SET_GROUP self.ShoradGroupSet = SET_GROUP:New() -- Core.Set#SET_GROUP
self.FilterZones = Zones self.FilterZones = Zones
self.LastThreatEval = {}
self.InboundARMs = {}
self.SkateZones = nil self.SkateZones = nil
self.SkateNumber = 3 self.SkateNumber = 3
@@ -1809,7 +1804,6 @@ do
local group = GROUP:FindByName(grpname) -- Wrapper.Group#GROUP local group = GROUP:FindByName(grpname) -- Wrapper.Group#GROUP
local units = group:GetUnits() local units = group:GetUnits()
local SAMData = self.SamData local SAMData = self.SamData
local ARMCapacity
if mod then if mod then
SAMData = self.SamDataHDS SAMData = self.SamDataHDS
elseif sma then elseif sma then
@@ -1817,23 +1811,22 @@ do
elseif chm then elseif chm then
SAMData = self.SamDataCH SAMData = self.SamDataCH
end end
self:T("Looking to auto-match for "..grpname) --self:I("Looking to auto-match for "..grpname)
for _,_unit in pairs(units) do for _,_unit in pairs(units) do
local unit = _unit -- Wrapper.Unit#UNIT local unit = _unit -- Wrapper.Unit#UNIT
local typename = string.lower(unit:GetTypeName()) local type = string.lower(unit:GetTypeName())
self:T(string.format("Matching typename: %s",typename)) --self:I(string.format("Matching typename: %s",type))
for idx,entry in pairs(SAMData) do for idx,entry in pairs(SAMData) do
local _entry = entry -- #MANTIS.SamData local _entry = entry -- #MANTIS.SamData
local _radar = string.lower(_entry.Radar) local _radar = string.lower(_entry.Radar)
self:T(string.format("Trying typename: %s",_radar)) --self:I(string.format("Trying typename: %s",_radar))
if string.find(typename,_radar,1,true) then if string.find(type,_radar,1,true) then
type = _entry.Type type = _entry.Type
radiusscale = self.radiusscale[type] radiusscale = self.radiusscale[type]
range = _entry.Range * 1000 * radiusscale -- max firing range used as switch-on range = _entry.Range * 1000 * radiusscale -- max firing range used as switch-on
height = _entry.Height * 1000 -- max firing height height = _entry.Height * 1000 -- max firing height
blind = _entry.Blindspot * 100 -- blind spot range blind = _entry.Blindspot * 100 -- blind spot range
ARMCapacity = _entry.ARMCapacity --self:I(string.format("Match: %s - %s",_radar,type))
self:T(string.format("Match: %s - %s",_radar,type))
found = true found = true
break break
end end
@@ -1854,7 +1847,7 @@ do
if not found then if not found then
self:E(self.lid .. string.format("*****Could not match radar data for %s! Will default to midrange values!",grpname)) self:E(self.lid .. string.format("*****Could not match radar data for %s! Will default to midrange values!",grpname))
end end
return range, height, type, blind, ARMCapacity return range, height, type, blind
end end
--- [Internal] Function to get SAM firing data --- [Internal] Function to get SAM firing data
@@ -1875,7 +1868,6 @@ do
local HDSmod = false local HDSmod = false
local SMAMod = false local SMAMod = false
local CHMod = false local CHMod = false
local ARMCapacity = 0
if string.find(grpname,"HDS",1,true) then if string.find(grpname,"HDS",1,true) then
HDSmod = true HDSmod = true
elseif string.find(grpname,"SMA",1,true) then elseif string.find(grpname,"SMA",1,true) then
@@ -1893,7 +1885,6 @@ do
range = _entry.Range * 1000 * radiusscale -- max firing range range = _entry.Range * 1000 * radiusscale -- max firing range
height = _entry.Height * 1000 -- max firing height height = _entry.Height * 1000 -- max firing height
blind = _entry.Blindspot blind = _entry.Blindspot
ARMCapacity = _entry.ARMCapacity or 0
self:T("Matching Groupname = " .. grpname .. " Range= " .. range) self:T("Matching Groupname = " .. grpname .. " Range= " .. range)
found = true found = true
break break
@@ -1913,14 +1904,14 @@ do
end end
--- Tertiary filter if not found --- Tertiary filter if not found
if (not found) or HDSmod or SMAMod or CHMod then if (not found) or HDSmod or SMAMod or CHMod then
range, height, type, blind, ARMCapacity = self:_GetSAMDataFromUnits(grpname,HDSmod,SMAMod,CHMod) range, height, type = self:_GetSAMDataFromUnits(grpname,HDSmod,SMAMod,CHMod)
elseif not found then elseif not found then
self:E(self.lid .. string.format("*****Could not match radar data for %s! Will default to midrange values!",grpname)) self:E(self.lid .. string.format("*****Could not match radar data for %s! Will default to midrange values!",grpname))
end end
if found and string.find(grpname,"SHORAD",1,true) then if found and string.find(grpname,"SHORAD",1,true) then
type = MANTIS.SamType.POINT -- force short on match type = MANTIS.SamType.POINT -- force short on match
end end
return range, height, type, blind, ARMCapacity return range, height, type, blind
end end
--- [Internal] Function to set the SAM start state --- [Internal] Function to set the SAM start state
@@ -1955,9 +1946,8 @@ do
group:OptionEngageRange(engagerange) --default engagement will be 95% of firing range group:OptionEngageRange(engagerange) --default engagement will be 95% of firing range
local grpname = group:GetName() local grpname = group:GetName()
local grpcoord = group:GetCoordinate() local grpcoord = group:GetCoordinate()
local grprange,grpheight,type,blind,ARMCapacity = self:_GetSAMRange(grpname) local grprange,grpheight,type,blind = self:_GetSAMRange(grpname)
if ARMCapacity and ARMCapacity>0 then _group:SetProperty("ARMCapacity",ARMCapacity) end table.insert( SAM_Tbl, {grpname, grpcoord, grprange, grpheight, blind, type})
table.insert( SAM_Tbl, {grpname, grpcoord, grprange, grpheight, blind, type, ARMCapacity})
--table.insert( SEAD_Grps, grpname ) --table.insert( SEAD_Grps, grpname )
if type == MANTIS.SamType.LONG then if type == MANTIS.SamType.LONG then
table.insert( SAM_Tbl_lg, {grpname, grpcoord, grprange, grpheight, blind, type}) table.insert( SAM_Tbl_lg, {grpname, grpcoord, grprange, grpheight, blind, type})
@@ -2021,15 +2011,12 @@ do
if group:IsGround() and group:IsAlive() then if group:IsGround() and group:IsAlive() then
local grpname = group:GetName() local grpname = group:GetName()
local grpcoord = group:GetCoordinate() local grpcoord = group:GetCoordinate()
local grprange, grpheight,type,blind, ARMCapacity = self:_GetSAMRange(grpname) local grprange, grpheight,type,blind = self:_GetSAMRange(grpname)
-- TODO the below might stop working at some point after some hours, needs testing -- TODO the below might stop working at some point after some hours, needs testing
--local radaralive = group:IsSAM() --local radaralive = group:IsSAM()
if ARMCapacity and ARMCapacity>0 then _group:SetProperty("ARMCapacity",ARMCapacity) end
local radaralive = true local radaralive = true
table.insert( SAM_Tbl, {grpname, grpcoord, grprange, grpheight, blind, type, ARMCapacity}) -- make the table lighter, as I don't really use the zone here table.insert( SAM_Tbl, {grpname, grpcoord, grprange, grpheight, blind, type}) -- make the table lighter, as I don't really use the zone here
if type ~= MANTIS.SamType.POINT then table.insert( SEAD_Grps, grpname )
table.insert( SEAD_Grps, grpname )
end
if type == MANTIS.SamType.LONG and radaralive then if type == MANTIS.SamType.LONG and radaralive then
table.insert( SAM_Tbl_lg, {grpname, grpcoord, grprange, grpheight, blind, type}) table.insert( SAM_Tbl_lg, {grpname, grpcoord, grprange, grpheight, blind, type})
self:T({grpname,grprange, grpheight}) self:T({grpname,grprange, grpheight})
@@ -2111,97 +2098,6 @@ do
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- MANTIS main functions -- MANTIS main functions
----------------------------------------------------------------------- -----------------------------------------------------------------------
--- [Internal] Check if a system can and should defend for HARMs itself
-- @param #MANTIS self
-- @param Wrapper.Group#GROUP targetGroup
-- @param #string targetName
-- @param Wrapper.Group#GROUP attackerGroup
-- @param #string weaponName
-- @param Wrapper.Weapon#WEAPON weaponWrapper
-- @param #number tti
-- @param #number delay
-- @return #boolean Outcome
function MANTIS:SeadAllowSuppression(targetGroup, targetName, attackerGroup, weaponName, weaponWrapper, tti, delay)
self:T(self.lid.."SeadAllowSuppression")
--- Thanks to @Goon Jan 2026
----------------------------------------------------------------
-- LOG INCOMING REQUEST
----------------------------------------------------------------
self:T(string.format("MANTIS:SeadAllowSuppression REQUEST | target=%s | weapon=%s | tti=%s | delay=%s",tostring(targetName),
tostring(weaponName),tostring(tti),tostring(delay)))
----------------------------------------------------------------
-- LOOK UP ARM CAPACITY FOR THIS SAM
----------------------------------------------------------------
local armcap = targetGroup:GetProperty("ARMCapacity")
if not armcap then
for _, sam in pairs(self.SAM_Table or {}) do
if sam[1] == targetName then
armcap = sam[7] -- ARMCapacity
break
end
end
end
self:T(string.format("MANTIS:SeadAllowSuppression SAM DATA | target=%s | ARMCapacity=%s",tostring(targetName),armcap and tostring(armcap) or "nil"))
----------------------------------------------------------------
-- TRACK SEAD THREATS (PER TARGET)
----------------------------------------------------------------
local THREAT_WINDOW = 0.1 -- seconds
self.LastThreatEval = self.LastThreatEval or {}
self.InboundARMs = self.InboundARMs or {}
local now = timer.getTime()
local last = self.LastThreatEval[targetName] or 0
if (now - last) >= THREAT_WINDOW then
self.InboundARMs[targetName] = (self.InboundARMs[targetName] or 0) + 1
self.LastThreatEval[targetName] = now
self:T(string.format("MANTIS:SeadAllowSuppression NEW threat accepted | Δt=%.3f",now - last))
else
self:T(string.format("MANTIS:SeadAllowSuppression duplicate evaluation ignored | Δt=%.3f",now - last))
end
local inbound = self.InboundARMs[targetName] or 0
self:T(string.format("MANTIS:SeadAllowSuppression THREAT COUNT | target=%s | inboundThreats=%d",tostring(targetName),inbound))
----------------------------------------------------------------
-- DECISION GATE
----------------------------------------------------------------
-- No missiles left over → legacy behavior
if targetGroup and targetGroup:IsAlive() then
local AmmotT, AmmoS, _, _,AmmoM = targetGroup:GetAmmunition()
-- TODO Check C-RAM probably needs an exception as it is a gun, need to check its effectiveness
if AmmoM and AmmoM == 0 then
self:T(string.format("MANTIS:SeadAllowSuppression DECISION -> APPROVED (no MISSILES) | target=%s",tostring(targetName)))
return true
end
end
-- No ARM capacity defined → legacy behavior
if (not armcap) or armcap == 0 then
self:T(string.format("MANTIS:SeadAllowSuppression DECISION -> APPROVED (no ARMCAP) | target=%s",tostring(targetName)))
return true
end
-- Suppress only once enough threats accumulated
if inbound >= armcap then
self:T(string.format("MANTIS:SeadAllowSuppression DECISION -> APPROVED (inbound %d >= cap %d) | target=%s",inbound,armcap,tostring(targetName)))
return true
end
self:T(string.format("MANTIS:SeadAllowSuppression DECISION -> DENIED (inbound %d < cap %d) | target=%s",inbound,armcap,tostring(targetName)))
return false
end
--- [Internal] Check detection function --- [Internal] Check detection function
-- @param #MANTIS self -- @param #MANTIS self
@@ -2236,7 +2132,6 @@ function MANTIS:SeadAllowSuppression(targetGroup, targetName, attackerGroup, wea
if self.Shorad and self.Shorad.ActiveGroups and self.Shorad.ActiveGroups[name] then if self.Shorad and self.Shorad.ActiveGroups and self.Shorad.ActiveGroups[name] then
activeshorad = true activeshorad = true
end end
if samgroup:GetProperty("SHORAD_ACTIVE") == true and activeshorad == false then activeshorad = true end
if IsInZone and (not suppressed) and (not activeshorad) then --check any target in zone and not currently managed by SEAD if IsInZone and (not suppressed) and (not activeshorad) then --check any target in zone and not currently managed by SEAD
if samgroup:IsAlive() then if samgroup:IsAlive() then
-- switch on SAM -- switch on SAM
@@ -2252,7 +2147,6 @@ function MANTIS:SeadAllowSuppression(targetGroup, targetName, attackerGroup, wea
switch = true switch = true
end end
if self.SamStateTracker[name] ~= "RED" and switch then if self.SamStateTracker[name] ~= "RED" and switch then
self.SamStateTracker[name] = "RED"
self:__RedState(1,samgroup) self:__RedState(1,samgroup)
end end
-- DONE Restrict on Distance -- DONE Restrict on Distance
@@ -2285,8 +2179,8 @@ function MANTIS:SeadAllowSuppression(targetGroup, targetName, attackerGroup, wea
samgroup:OptionAlarmStateGreen() samgroup:OptionAlarmStateGreen()
end end
if self.SamStateTracker[name] ~= "GREEN" then if self.SamStateTracker[name] ~= "GREEN" then
self.SamStateTracker[name] = "GREEN"
self:__GreenState(1,samgroup) self:__GreenState(1,samgroup)
self.SamStateTracker[name] = "GREEN"
end end
if self.debug or self.verbose then if self.debug or self.verbose then
local text = string.format("SAM %s in alarm state GREEN!", name) local text = string.format("SAM %s in alarm state GREEN!", name)
@@ -2296,13 +2190,12 @@ function MANTIS:SeadAllowSuppression(targetGroup, targetName, attackerGroup, wea
end --end alive end --end alive
end --end check end --end check
end --for loop end --for loop
--[[
if self.debug or self.verbose or self.logsamstatus then if self.debug or self.verbose or self.logsamstatus then
for _,_status in pairs(self.SamStateTracker) do for _,_status in pairs(self.SamStateTracker) do
if _status == "GREEN" then if _status == "GREEN" then
instatusgreen=instatusgreen+1 instatusgreen=instatusgreen+1
elseif _status == "RED" then elseif _status == "RED" then
instatusred=instatusred+1 instatusred=instatusred+1
end end
end end
if self.Shorad then if self.Shorad then
@@ -2311,8 +2204,6 @@ function MANTIS:SeadAllowSuppression(targetGroup, targetName, attackerGroup, wea
end end
end end
end end
self:T(self.lid..string.format("SAM State Count: GREEN %d | RED %d | SHORAD %d",instatusred, instatusgreen, activeshorads))
--]]
return instatusred, instatusgreen, activeshorads return instatusred, instatusgreen, activeshorads
end end
@@ -2344,29 +2235,13 @@ function MANTIS:SeadAllowSuppression(targetGroup, targetName, attackerGroup, wea
local samset = self.SAM_Table_Short -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height local samset = self.SAM_Table_Short -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
local instatusreds, instatusgreens, activeshoradss = self:_CheckLoop(samset,detset,dlink,self.maxshortrange) local instatusreds, instatusgreens, activeshoradss = self:_CheckLoop(samset,detset,dlink,self.maxshortrange)
local samset = self.SAM_Table_PointDef -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height local samset = self.SAM_Table_PointDef -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
local instatusred, instatusgreen, activeshorads = self:_CheckLoop(samset,detset,dlink,self.maxpointdefrange) instatusred, instatusgreen, activeshorads = self:_CheckLoop(samset,detset,dlink,self.maxpointdefrange)
else else
local samset = self:_GetSAMTable() -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height local samset = self:_GetSAMTable() -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
local instatusred, instatusgreen, activeshorads = self:_CheckLoop(samset,detset,dlink,self.maxclassic) instatusred, instatusgreen, activeshorads = self:_CheckLoop(samset,detset,dlink,self.maxclassic)
end end
local function GetReport() local function GetReport()
if self.debug or self.verbose or self.logsamstatus then
for _,_status in pairs(self.SamStateTracker) do
if _status == "GREEN" then
instatusgreen=instatusgreen+1
elseif _status == "RED" then
instatusred=instatusred+1
end
end
if self.Shorad then
for _,_name in pairs(self.Shorad.ActiveGroups or {}) do
activeshorads=activeshorads+1
end
end
end
local statusreport = REPORT:New("\nMANTIS Status "..self.name) local statusreport = REPORT:New("\nMANTIS Status "..self.name)
statusreport:Add("+-----------------------------+") statusreport:Add("+-----------------------------+")
statusreport:Add(string.format("+ SAM in RED State: %2d",instatusred)) statusreport:Add(string.format("+ SAM in RED State: %2d",instatusred))
@@ -2469,7 +2344,6 @@ function MANTIS:SeadAllowSuppression(targetGroup, targetName, attackerGroup, wea
self.ShoradLink = true self.ShoradLink = true
self.Shorad.Groupset=self.ShoradGroupSet self.Shorad.Groupset=self.ShoradGroupSet
self.Shorad.debug = self.debug self.Shorad.debug = self.debug
self.Shorad:AddCallBack(self)
end end
if self.shootandscoot and self.SkateZones and self.Shorad then if self.shootandscoot and self.SkateZones and self.Shorad then
self.Shorad:AddScootZones(self.SkateZones,self.SkateNumber or 3,self.ScootRandom,self.ScootFormation) self.Shorad:AddScootZones(self.SkateZones,self.SkateNumber or 3,self.ScootRandom,self.ScootFormation)
@@ -2675,7 +2549,6 @@ function MANTIS:SeadAllowSuppression(targetGroup, targetName, attackerGroup, wea
function MANTIS:onafterSeadSuppressionEnd(From, Event, To, Group, Name) function MANTIS:onafterSeadSuppressionEnd(From, Event, To, Group, Name)
self:T({From, Event, To, Name}) self:T({From, Event, To, Name})
self.SuppressedGroups[Name] = false self.SuppressedGroups[Name] = false
self.InboundARMs[Name] = 0
return self return self
end end
@@ -2212,11 +2212,7 @@ function SCORING:ScoreCSV( PlayerName, TargetPlayerName, ScoreType, ScoreTimes,
local data = self:ReportScoreAllSummary("",true) local data = self:ReportScoreAllSummary("",true)
local text = "-- Playername;;Score;;Penalty\n" local text = "-- Playername;;Score;;Penalty\n"
for _playername,_data in pairs(data or {}) do for _playername,_data in pairs(data or {}) do
-- ReportTable[PlayerName] = {["Score"]=PlayerScore,["Penalty"]=PlayerPenalty} text = text..string.format("%s;;%d;;%d\n")
local Playername = _playername or "Ghost"
local Score = _data.Score or 0
local Penalty = _data.Penalty or 0
text = text..string.format("%s;;%d;;%d\n",Playername,Score,Penalty)
end end
UTILS.SaveToFile(path,filename,text) UTILS.SaveToFile(path,filename,text)
end end
+5 -16
View File
@@ -19,7 +19,7 @@
-- --
-- ### Authors: **applevangelist**, **FlightControl** -- ### Authors: **applevangelist**, **FlightControl**
-- --
-- Last Update: January 2026 -- Last Update: Dec 2024
-- --
-- === -- ===
-- --
@@ -157,7 +157,7 @@ function SEAD:New( SEADGroupPrefixes, Padding )
self:AddTransition("*", "ManageEvasion", "*") self:AddTransition("*", "ManageEvasion", "*")
self:AddTransition("*", "CalculateHitZone", "*") self:AddTransition("*", "CalculateHitZone", "*")
self:I("*** SEAD - Started Version 0.4.11") self:I("*** SEAD - Started Version 0.4.9")
return self return self
end end
@@ -318,7 +318,7 @@ function SEAD:onafterCalculateHitZone(From,Event,To,SEADWeapon,pos0,height,SEADG
elseif height <= 12500 then elseif height <= 12500 then
Ropt = Ropt * 0.98 Ropt = Ropt * 0.98
end end
local WeaponWrapper = WEAPON:New(SEADWeapon)
-- look at a couple of zones across the trajectory -- look at a couple of zones across the trajectory
for n=1,3 do for n=1,3 do
local dist = Ropt - ((n-1)*20000) local dist = Ropt - ((n-1)*20000)
@@ -342,7 +342,7 @@ function SEAD:onafterCalculateHitZone(From,Event,To,SEADWeapon,pos0,height,SEADG
_targetgroupname = tgtgrp:GetName() -- group name _targetgroupname = tgtgrp:GetName() -- group name
_targetskill = tgtgrp:GetUnit(1):GetSkill() _targetskill = tgtgrp:GetUnit(1):GetSkill()
self:T("*** Found Target = ".. _targetgroupname) self:T("*** Found Target = ".. _targetgroupname)
self:ManageEvasion(_targetskill,_targetgroup,pos0,"AGM_88",SEADGroup, 20, WeaponWrapper) self:ManageEvasion(_targetskill,_targetgroup,pos0,"AGM_88",SEADGroup, 20)
end end
--end --end
end end
@@ -442,18 +442,7 @@ function SEAD:onafterManageEvasion(From,Event,To,_targetskill,_targetgroup,SEADP
local SuppressionStartTime = timer.getTime() + delay local SuppressionStartTime = timer.getTime() + delay
local SuppressionEndTime = timer.getTime() + delay + _tti + self.Padding + delay local SuppressionEndTime = timer.getTime() + delay + _tti + self.Padding + delay
local _targetgroupname = _targetgroup:GetName() local _targetgroupname = _targetgroup:GetName()
local shoradactive = _targetgroup:GetProperty("SHORAD_ACTIVE") if not self.SuppressedGroups[_targetgroupname] then
if not self.SuppressedGroups[_targetgroupname] and shoradactive ~= true then
-- TODO: ask callback if suppression is allowed BEFORE scheduling timers
local allow = true
if self.UseCallBack and self.CallBack and self.CallBack.SeadAllowSuppression then
allow = self.CallBack:SeadAllowSuppression(_targetgroup,_targetgroupname,SEADGroup,SEADWeaponName,Weapon,_tti,delay)
end
if not allow then
self:T(string.format("*** SEAD - %s | Suppression vetoed by callback", _targetgroupname))
-- Important: do NOT schedule SuppressionStart/Stop and do NOT flip SuppressedGroups true.
return self
end
self:T(string.format("*** SEAD - %s | Parameters TTI %ds | Switch-Off in %ds",_targetgroupname,_tti,delay)) self:T(string.format("*** SEAD - %s | Parameters TTI %ds | Switch-Off in %ds",_targetgroupname,_tti,delay))
timer.scheduleFunction(SuppressionStart,{_targetgroup,_targetgroupname, SEADGroup},SuppressionStartTime) timer.scheduleFunction(SuppressionStart,{_targetgroup,_targetgroupname, SEADGroup},SuppressionStartTime)
timer.scheduleFunction(SuppressionStop,{_targetgroup,_targetgroupname},SuppressionEndTime) timer.scheduleFunction(SuppressionStop,{_targetgroup,_targetgroupname},SuppressionEndTime)
+57 -88
View File
@@ -21,7 +21,7 @@
-- @image Functional.Shorad.jpg -- @image Functional.Shorad.jpg
-- --
-- Date: Nov 2021 -- Date: Nov 2021
-- Last Update: Jan 2026 -- Last Update: Jan 2025
------------------------------------------------------------------------- -------------------------------------------------------------------------
--- **SHORAD** class, extends Core.Base#BASE --- **SHORAD** class, extends Core.Base#BASE
@@ -196,7 +196,7 @@ do
self.SmokeDecoyColor = SmokeDecoyColor or SMOKECOLOR.White self.SmokeDecoyColor = SmokeDecoyColor or SMOKECOLOR.White
end end
self:I("*** SHORAD - Started Version 0.3.6") self:I("*** SHORAD - Started Version 0.3.5")
-- Set the string id for output to DCS.log file. -- Set the string id for output to DCS.log file.
self.lid=string.format("SHORAD %s | ", self.name) self.lid=string.format("SHORAD %s | ", self.name)
self:_InitState() self:_InitState()
@@ -465,17 +465,6 @@ do
return returnname return returnname
end end
--- Set an object to call back when going evasive.
-- @param #SHORAD self
-- @param #table Object The object to call.
-- @return #SHORAD self
function SHORAD:AddCallBack(Object)
self:T({Class=Object.ClassName})
self.CallBack = Object
self.UseCallBack = true
return self
end
--- Smoke a SHORAD Group --- Smoke a SHORAD Group
-- @param #SHORAD self -- @param #SHORAD self
-- @param Wrapper.Group#GROUP Group The Shorad Group to Smoke -- @param Wrapper.Group#GROUP Group The Shorad Group to Smoke
@@ -535,56 +524,7 @@ do
-- mymantis:Start() -- mymantis:Start()
function SHORAD:onafterWakeUpShorad(From, Event, To, TargetGroup, Radius, ActiveTimer, TargetCat, ShotAt) function SHORAD:onafterWakeUpShorad(From, Event, To, TargetGroup, Radius, ActiveTimer, TargetCat, ShotAt)
self:T(self.lid .. " WakeUpShorad") self:T(self.lid .. " WakeUpShorad")
--self:T({TargetGroup, Radius, ActiveTimer, TargetCat}) self:T({TargetGroup, Radius, ActiveTimer, TargetCat})
local TDiff = 4
-- local function to switch off shorad again
local function SleepShorad(group)
if group and group:IsAlive() then
local groupname = group:GetName()
self.ActiveGroups[groupname] = nil
if self.UseEmOnOff then
group:EnableEmission(false)
else
group:OptionAlarmStateGreen()
end
group:SetProperty("SHORAD_ACTIVE",false)
local text = string.format("Sleeping SHORAD %s", group:GetName())
self:T(text)
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
--Shoot and Scoot
if self.shootandscoot then
self:__ShootAndScoot(1,group)
else
--group:RelocateGroundRandomInRadius(30,500,false,true,"Diamond",true)
end
end
end
local function WakeUp(_group,groupname)
-- shot at a group we protect
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:EnableEmission(true)
end
_group:OptionAlarmStateRed()
_group:SetProperty("SHORAD_ACTIVE",true)
self:_SmokeUnits(_group)
if self.ActiveGroups[groupname] == nil then -- no timer yet for this group
self.ActiveGroups[groupname] = { Timing = ActiveTimer }
local endtime = timer.getTime() + (ActiveTimer * math.random(75,100) / 100 ) -- randomize wakeup a bit
self.ActiveGroups[groupname].Timer = TIMER:New(SleepShorad,_group):Start(endtime)
--Shoot and Scoot
if self.shootandscoot then
self:__ShootAndScoot(TDiff,_group)
TDiff=TDiff+1
end
end
end
local targetcat = TargetCat or Object.Category.UNIT local targetcat = TargetCat or Object.Category.UNIT
local targetgroup = TargetGroup local targetgroup = TargetGroup
local targetvec2 = nil local targetvec2 = nil
@@ -601,41 +541,70 @@ do
local groupset = self.Groupset --Core.Set#SET_GROUP local groupset = self.Groupset --Core.Set#SET_GROUP
local shoradset = groupset:GetAliveSet() --#table local shoradset = groupset:GetAliveSet() --#table
-- local function to switch off shorad again
local function SleepShorad(group)
if group and group:IsAlive() then
local groupname = group:GetName()
self.ActiveGroups[groupname] = nil
if self.UseEmOnOff then
group:EnableEmission(false)
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)
--Shoot and Scoot
if self.shootandscoot then
self:__ShootAndScoot(1,group)
end
end
end
-- go through set and find the one(s) to activate -- go through set and find the one(s) to activate
local TDiff = 4
for _,_group in pairs (shoradset) do for _,_group in pairs (shoradset) do
local groupname = _group:GetName() local groupname = _group:GetName()
if groupname == TargetGroup and ShotAt==true then if groupname == TargetGroup and ShotAt==true then
-- Shot at a SHORAD group -- Shot at a SHORAD group
local allow = false if self.UseEmOnOff then
if self.CallBack and self.UseCallBack == true then _group:EnableEmission(false)
allow = self.CallBack:SeadAllowSuppression(_group,groupname)
end end
if allow == true then _group:OptionAlarmStateGreen()
if self.UseEmOnOff then self.ActiveGroups[groupname] = nil
_group:EnableEmission(false) local text = string.format("Shot at SHORAD %s! Evading!", _group:GetName())
end self:T(text)
_group:OptionAlarmStateGreen() local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
self.ActiveGroups[groupname] = nil self:_SmokeUnits(_group)
local text = string.format("Shot at SHORAD %s! Evading!", _group:GetName()) --Shoot and Scoot
self:T(text) if self.shootandscoot then
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug) self:__ShootAndScoot(1,_group)
self:_SmokeUnits(_group) end
elseif _group:IsAnyInZone(targetzone) or groupname == TargetGroup then
-- shot at a group we protect
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:EnableEmission(true)
end
_group:OptionAlarmStateRed()
self:_SmokeUnits(_group)
if self.ActiveGroups[groupname] == nil then -- no timer yet for this group
self.ActiveGroups[groupname] = { Timing = ActiveTimer }
local endtime = timer.getTime() + (ActiveTimer * math.random(75,100) / 100 ) -- randomize wakeup a bit
self.ActiveGroups[groupname].Timer = TIMER:New(SleepShorad,_group):Start(endtime)
--Shoot and Scoot --Shoot and Scoot
if self.shootandscoot then if self.shootandscoot then
self:__ShootAndScoot(1,_group) self:__ShootAndScoot(TDiff,_group)
else TDiff=TDiff+1
_group:RelocateGroundRandomInRadius(30,500,false,true,"Diamond",true)
end end
else
WakeUp(_group,groupname)
end end
elseif _group:IsAnyInZone(targetzone) or groupname == TargetGroup then end
WakeUp(_group,groupname) end
end -- end if
end -- end in pairs
return self return self
end end
@@ -751,7 +720,7 @@ do
-- @param Core.Event#EVENTDATA EventData The event details table data set -- @param Core.Event#EVENTDATA EventData The event details table data set
-- @return #SHORAD self -- @return #SHORAD self
function SHORAD:HandleEventShot( EventData ) function SHORAD:HandleEventShot( EventData )
--self:T( { EventData.id } ) self:T( { EventData } )
self:T(self.lid .. " HandleEventShot") self:T(self.lid .. " HandleEventShot")
local ShootingWeapon = EventData.Weapon -- Identify the weapon fired local ShootingWeapon = EventData.Weapon -- Identify the weapon fired
local ShootingWeaponName = EventData.WeaponName -- return weapon type local ShootingWeaponName = EventData.WeaponName -- return weapon type
@@ -776,7 +745,7 @@ do
-- Is there target data? -- Is there target data?
if not targetdata or self.debug then if not targetdata or self.debug then
if string.find(ShootingWeaponName,"AGM_88",1,true) then if string.find(ShootingWeaponName,"AGM_88",1,true) then
self:T("**** Tracking AGM-88 with no target data.") self:I("**** Tracking AGM-88 with no target data.")
local pos0 = EventData.IniUnit:GetCoordinate() local pos0 = EventData.IniUnit:GetCoordinate()
local fheight = EventData.IniUnit:GetHeight() local fheight = EventData.IniUnit:GetHeight()
self:__CalculateHitZone(20,ShootingWeapon,pos0,fheight,EventData.IniGroup) self:__CalculateHitZone(20,ShootingWeapon,pos0,fheight,EventData.IniGroup)
@@ -8597,8 +8597,8 @@ function WAREHOUSE:_DeleteStockItem(stockitem)
local item=self.stock[i] --#WAREHOUSE.Assetitem local item=self.stock[i] --#WAREHOUSE.Assetitem
if item.uid==stockitem.uid then if item.uid==stockitem.uid then
table.remove(self.stock,i) table.remove(self.stock,i)
-- remove also from warehouse DB (not good! causes an error if the asset needs to be added to a requesting wherehouse) -- remove also from warehouse DB
--_WAREHOUSEDB.Assets[stockitem.uid]=nil _WAREHOUSEDB.Assets[stockitem.uid]=nil
break break
end end
end end
@@ -116,6 +116,7 @@ __Moose.Include( 'Ops\\Operation.lua' )
__Moose.Include( 'Ops\\FlightControl.lua' ) __Moose.Include( 'Ops\\FlightControl.lua' )
__Moose.Include( 'Ops\\PlayerRecce.lua' ) __Moose.Include( 'Ops\\PlayerRecce.lua' )
__Moose.Include( 'Ops\\EasyGCICAP.lua' ) __Moose.Include( 'Ops\\EasyGCICAP.lua' )
__Moose.Include( 'Ops\\EasyA2G.lua' )
__Moose.Include( 'AI\\AI_Balancer.lua' ) __Moose.Include( 'AI\\AI_Balancer.lua' )
__Moose.Include( 'AI\\AI_Air.lua' ) __Moose.Include( 'AI\\AI_Air.lua' )
+13 -28
View File
@@ -331,34 +331,19 @@ function AIRWING:AddSquadron(Squadron)
local airbasename = self:GetAirbaseName() local airbasename = self:GetAirbaseName()
if airbasename then if airbasename then
local group = Squadron.templategroup local group = GROUP:FindByName(Squadron.templategroup)
if group then local Nunits = 1
local Nunits = 1 local units
local units if group then units = group:GetUnits() end
if group then units = group:GetUnits() end if units then Nunits = #units end
if units then Nunits = #units end local typename = Squadron.aircrafttype or "none"
local typename = Squadron.aircrafttype or "none" local NAssets = Squadron.Ngroups * Nunits
local NAssets = Squadron.Ngroups * Nunits local storage = STORAGE:New(airbasename)
local storage = STORAGE:New(airbasename) --self:T(self.lid.."Adding "..typename.." #"..NAssets)
if storage and storage.warehouse and storage:IsLimitedAircraft() and typename ~= "none" then
self:T(self.lid.."Adding "..typename.." #"..NAssets) local NInStore = storage:GetItemAmount(typename) or 0
if storage and storage.warehouse and storage:IsLimitedAircraft() and typename ~= "none" then if NAssets > NInStore then
local NInStore = storage:GetItemAmount(typename) or 0 storage:AddItem(typename,NAssets)
if NAssets > NInStore then
storage:AddItem(typename,NAssets)
end
end
local unit = group:GetUnit(1)
-- if storage is limited, add the amount of liquids needed
if unit and storage and storage.warehouse and storage:IsLimitedLiquids() and typename ~= "none" then
local fuel = unit:GetFuelMassMax()
local neededfuel = (fuel*NAssets) -- kgs of fuel
local NInStore = storage:GetLiquidAmount(STORAGE.Liquid.JETFUEL) or 0
self:T(string.format(self.lid.."Fuel Needed: %dt | Fuel in store: %dt",neededfuel/1000,NInStore/1000))
if neededfuel > NInStore then
storage:AddLiquid(STORAGE.Liquid.JETFUEL,neededfuel)
end
end end
end end
end end
+1 -1
View File
@@ -3060,7 +3060,7 @@ end
--- **[LEGION, COMMANDER, CHIEF]** Set the repeat delay in seconds after a mission is successful/failed. Only valid if the mission is handled by a LEGION (AIRWING, BRIGADE, FLEET) or higher level. --- **[LEGION, COMMANDER, CHIEF]** Set the repeat delay in seconds after a mission is successful/failed. Only valid if the mission is handled by a LEGION (AIRWING, BRIGADE, FLEET) or higher level.
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param #number Nrepeat Repeat delay in seconds. Default 1. -- @param #number RepeatDelay Repeat delay in seconds. Default 1.
-- @return #AUFTRAG self -- @return #AUFTRAG self
function AUFTRAG:SetRepeatDelay(RepeatDelay) function AUFTRAG:SetRepeatDelay(RepeatDelay)
self.repeatDelay = RepeatDelay self.repeatDelay = RepeatDelay
+2 -4
View File
@@ -31,7 +31,7 @@
-- @image OPS_CSAR.jpg -- @image OPS_CSAR.jpg
--- ---
-- Last Update Jan 2026 -- Last Update Dec 2025
------------------------------------------------------------------------- -------------------------------------------------------------------------
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM --- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
@@ -315,12 +315,10 @@ CSAR.AircraftType["MH-60R"] = 10
CSAR.AircraftType["OH-6A"] = 2 CSAR.AircraftType["OH-6A"] = 2
CSAR.AircraftType["OH58D"] = 2 CSAR.AircraftType["OH58D"] = 2
CSAR.AircraftType["CH-47Fbl1"] = 31 CSAR.AircraftType["CH-47Fbl1"] = 31
CSAR.AircraftType["AH-6J"] = 2
CSAR.AircraftType["MH-6J"] = 2
--- CSAR class version. --- CSAR class version.
-- @field #string version -- @field #string version
CSAR.version="1.0.36" CSAR.version="1.0.35"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list -- ToDo list
+105 -191
View File
@@ -25,7 +25,7 @@
-- @module Ops.CTLD -- @module Ops.CTLD
-- @image OPS_CTLD.jpg -- @image OPS_CTLD.jpg
-- Last Update Jan 2026 -- Last Update Dec 2025
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -193,7 +193,6 @@ CTLD_CARGO = {
-- @param Wrapper.Unit#UNIT Unit -- @param Wrapper.Unit#UNIT Unit
-- @return #boolean Outcome -- @return #boolean Outcome
function CTLD_CARGO:UnitCanCarry(Unit) function CTLD_CARGO:UnitCanCarry(Unit)
if not Unit then return false end
if self.TypeNames == nil then return true end if self.TypeNames == nil then return true end
local typename = Unit:GetTypeName() or "none" local typename = Unit:GetTypeName() or "none"
if self.TypeNames[typename] then if self.TypeNames[typename] then
@@ -638,7 +637,7 @@ CTLD_ENGINEERING = {
local crate = ctable[1] -- Ops.CTLD#CTLD_CARGO local crate = ctable[1] -- Ops.CTLD#CTLD_CARGO
local static = crate:GetPositionable() -- Wrapper.Static#STATIC local static = crate:GetPositionable() -- Wrapper.Static#STATIC
local crate_pos = static:GetCoordinate() -- Core.Point#COORDINATE local crate_pos = static:GetCoordinate() -- Core.Point#COORDINATE
local gpos = group:GetCoord() -- Core.Point#COORDINATE local gpos = group:GetCoordinate() -- Core.Point#COORDINATE
-- see how far we are from the crate -- see how far we are from the crate
local distance = self:_GetDistance(gpos,crate_pos) local distance = self:_GetDistance(gpos,crate_pos)
self:T(string.format("%s Distance to crate: %d", self.lid, distance)) self:T(string.format("%s Distance to crate: %d", self.lid, distance))
@@ -667,7 +666,7 @@ CTLD_ENGINEERING = {
--local COps = self.C_Ops -- Ops.CTLD#CTLD --local COps = self.C_Ops -- Ops.CTLD#CTLD
local group = self.Group -- Wrapper.Group#GROUP local group = self.Group -- Wrapper.Group#GROUP
local tgtpos = self.currwpt -- Core.Point#COORDINATE local tgtpos = self.currwpt -- Core.Point#COORDINATE
local gpos = group:GetCoord() -- Core.Point#COORDINATE local gpos = group:GetCoordinate() -- Core.Point#COORDINATE
-- see how far we are from the crate -- see how far we are from the crate
local distance = self:_GetDistance(gpos,tgtpos) local distance = self:_GetDistance(gpos,tgtpos)
self:T(string.format("%s Distance remaining: %d", self.lid, distance)) self:T(string.format("%s Distance remaining: %d", self.lid, distance))
@@ -1496,8 +1495,6 @@ CTLD.UnitTypeCapabilities = {
["SH-60B"] = {type="SH-60B", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16, cargoweightlimit = 3500}, -- 4t cargo, 20 (unsec) seats ["SH-60B"] = {type="SH-60B", 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 ["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}, ["Bronco-OV-10A"] = {type="Bronco-OV-10A", crates= false, troops=true, cratelimit = 0, trooplimit = 5, length = 13, cargoweightlimit = 1450},
["AH-6J"] = {type="AH-6J", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 7, cargoweightlimit = 550},
["MH-6J"] = {type="MH-6J", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 7, cargoweightlimit = 550},
["OH-6A"] = {type="OH-6A", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 7, cargoweightlimit = 550}, ["OH-6A"] = {type="OH-6A", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 7, cargoweightlimit = 550},
["OH58D"] = {type="OH58D", crates=false, troops=false, cratelimit = 0, trooplimit = 0, length = 14, cargoweightlimit = 400}, ["OH58D"] = {type="OH58D", crates=false, troops=false, cratelimit = 0, trooplimit = 0, length = 14, cargoweightlimit = 400},
["CH-47Fbl1"] = {type="CH-47Fbl1", crates=true, troops=true, cratelimit = 4, trooplimit = 31, length = 20, cargoweightlimit = 10800}, ["CH-47Fbl1"] = {type="CH-47Fbl1", crates=true, troops=true, cratelimit = 4, trooplimit = 31, length = 20, cargoweightlimit = 10800},
@@ -1516,7 +1513,7 @@ CTLD.FixedWingTypes = {
--- CTLD class version. --- CTLD class version.
-- @field #string version -- @field #string version
CTLD.version="1.3.43" CTLD.version="1.3.42"
--- Instantiate a new CTLD. --- Instantiate a new CTLD.
-- @param #CTLD self -- @param #CTLD self
@@ -2913,32 +2910,10 @@ end
-- @return #CTLD self -- @return #CTLD self
function CTLD:_LoadTroopsQuantity(Group, Unit, Cargo, quantity) function CTLD:_LoadTroopsQuantity(Group, Unit, Cargo, quantity)
local n = math.max(1, tonumber(quantity) or 1) local n = math.max(1, tonumber(quantity) or 1)
-- landed or hovering over load zone?
local grounded = not self:IsUnitInAir(Unit)
local hoverload = self:CanHoverLoad(Unit)
-- check if we are in LOAD zone
local inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD)
if not inzone then
inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP)
end
if not inzone then
self:_SendMessage("You are not close enough to a logistics zone!", 10, false, Group)
if not self.debug then return self end
elseif not grounded and not hoverload then
self:_SendMessage("You need to land or hover in position to load!", 10, false, Group)
if not self.debug then return self end
elseif self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
self:_SendMessage("You need to open the door(s) to load troops!", 10, false, Group)
if not self.debug then return self end
end
local prevSuppress = self.suppressmessages local prevSuppress = self.suppressmessages
self.suppressmessages = true self.suppressmessages = true
for i = 1, n do for i = 1, n do
timer.scheduleFunction(function() self:_LoadTroops(Group, Unit, Cargo) end, {}, timer.getTime() + 0.2 * i) timer.scheduleFunction(function() self:_LoadTroops(Group, Unit, Cargo, true) end, {}, timer.getTime() + 0.2 * i)
end end
timer.scheduleFunction(function() timer.scheduleFunction(function()
self.suppressmessages = prevSuppress self.suppressmessages = prevSuppress
@@ -2979,10 +2954,11 @@ function CTLD:_AddTroopQuantityMenus(Group, Unit, parentMenu, cargoObj)
if capacitySets < maxQuantity then maxQuantity = capacitySets end if capacitySets < maxQuantity then maxQuantity = capacitySets end
end end
for quantity = 1, maxQuantity do for quantity = 1, maxQuantity do
local m = MENU_GROUP:New(Group, tostring(quantity), parentMenu)
if quantity == 1 then if quantity == 1 then
MENU_GROUP_COMMAND:New(Group, tostring(quantity), parentMenu, self._LoadTroops, self, Group, Unit, cargoObj) MENU_GROUP_COMMAND:New(Group, "Load", m, self._LoadTroops, self, Group, Unit, cargoObj)
else else
MENU_GROUP_COMMAND:New(Group, tostring(quantity), parentMenu, self._LoadTroopsQuantity, self, Group, Unit, cargoObj, quantity) MENU_GROUP_COMMAND:New(Group, "Load", m, self._LoadTroopsQuantity, self, Group, Unit, cargoObj, quantity)
end end
end end
return self return self
@@ -3161,17 +3137,6 @@ function CTLD:_AddCrateQuantityMenus(Group, Unit, parentMenu, cargoObj, stockSum
return self return self
end end
--- User overrideable function to determine if a unit can get crates.
-- @param #CTLD self
-- @param Wrapper.Group#GROUP Group
-- @param Wrapper.Unit#UNIT Unit
-- @param #table Config Configuration entry for the unit.
-- @param #number quantity Number of crate sets requested.
-- @param #boolean quiet If true, do not send messages to the user.
function CTLD:CanGetUnits(Group, Unit, Config, quantity, quiet)
return true
end
--- (Internal) Spawn a “Get units” entry for a C-130J-30 at load zone. --- (Internal) Spawn a “Get units” entry for a C-130J-30 at load zone.
-- @param #CTLD self -- @param #CTLD self
-- @param Wrapper.Group#GROUP Group -- @param Wrapper.Group#GROUP Group
@@ -3202,9 +3167,6 @@ function CTLD:_C130GetUnits(Group, Unit, Name)
self:_SendMessage("You are not close enough to a logistics zone!",10,false,Group) self:_SendMessage("You are not close enough to a logistics zone!",10,false,Group)
return self return self
end end
if not self:CanGetUnits(Group, Unit, cfg, 1, false) then
return self
end
local coord = Unit:GetCoordinate() or Group:GetCoordinate() local coord = Unit:GetCoordinate() or Group:GetCoordinate()
local capabilities = self:_GetUnitCapabilities(Unit) local capabilities = self:_GetUnitCapabilities(Unit)
@@ -3390,7 +3352,7 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack, quiet, suppress
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
local canloadcratesno = capabilities.cratelimit local canloadcratesno = capabilities.cratelimit
local loaddist = self.CrateDistance or 35 local loaddist = self.CrateDistance or 35
local nearcrates, numbernearby = self:_FindCratesNearby(Group,Unit,loaddist,true,true,true) -- to ignore what's inside local nearcrates, numbernearby = self:_FindCratesNearby(Group,Unit,loaddist,true,true)
if numbernearby >= canloadcratesno and not drop then if numbernearby >= canloadcratesno and not drop then
self:_SendMessage("There are enough crates nearby already! Take care of those first!", 10, false, Group) self:_SendMessage("There are enough crates nearby already! Take care of those first!", 10, false, Group)
return false return false
@@ -3552,9 +3514,9 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack, quiet, suppress
Cargo:RemoveStock(requestedSets) Cargo:RemoveStock(requestedSets)
self:_RefreshCrateQuantityMenus(Group, Unit, Cargo) self:_RefreshCrateQuantityMenus(Group, Unit, Cargo)
end end
local text = string.format("%d crates for %s have been positioned near you!",number,cratename) local text = string.format("Crates for %s have been positioned near you!",cratename)
if drop then if drop then
text = string.format("%d crates for %s have been dropped!",number,cratename) text = string.format("Crates for %s have been dropped!",cratename)
self:__CratesDropped(1, Group, Unit, droppedcargo) self:__CratesDropped(1, Group, Unit, droppedcargo)
else else
if not quiet then if not quiet then
@@ -3650,7 +3612,7 @@ end
function CTLD:_ListCratesNearby( _group, _unit) function CTLD:_ListCratesNearby( _group, _unit)
self:T(self.lid .. " _ListCratesNearby") self:T(self.lid .. " _ListCratesNearby")
local finddist = self.CrateDistance or 35 local finddist = self.CrateDistance or 35
local crates,number,loadedbygc,indexgc = self:_FindCratesNearby(_group,_unit, finddist,true,true,true) -- #table local crates,number,loadedbygc,indexgc = self:_FindCratesNearby(_group,_unit, finddist,true,true) -- #table
if number > 0 or indexgc > 0 then if number > 0 or indexgc > 0 then
local text = REPORT:New("Crates Found Nearby:") local text = REPORT:New("Crates Found Nearby:")
text:Add("------------------------------------------------------------") text:Add("------------------------------------------------------------")
@@ -3749,7 +3711,7 @@ end
function CTLD:_RemoveCratesNearby(_group, _unit) function CTLD:_RemoveCratesNearby(_group, _unit)
self:T(self.lid.." _RemoveCratesNearby") self:T(self.lid.." _RemoveCratesNearby")
local finddist=self.CrateDistance or 35 local finddist=self.CrateDistance or 35
local crates,number=self:_FindCratesNearby(_group,_unit,finddist,true,true,true) local crates,number=self:_FindCratesNearby(_group,_unit,finddist,true,true)
if number>0 then if number>0 then
local removedIDs={} local removedIDs={}
local text=REPORT:New("Removing Crates Found Nearby:") local text=REPORT:New("Removing Crates Found Nearby:")
@@ -3862,7 +3824,7 @@ function CTLD:_FindCratesNearby( _group, _unit, _dist, _ignoreweight, ignoretype
self:T(self.lid .. " Loading restricted: " .. tostring(restricted)) self:T(self.lid .. " Loading restricted: " .. tostring(restricted))
local staticpos = static:GetCoordinate() --or dcsunitpos local staticpos = static:GetCoordinate() --or dcsunitpos
local cando = cargo:UnitCanCarry(_unit) local cando = cargo:UnitCanCarry(_unit)
if ignoretype == true then cando = true restricted = false end if ignoretype == true then cando = true end
self:T(self.lid .. " Unit can carry: " .. tostring(cando)) self:T(self.lid .. " Unit can carry: " .. tostring(cando))
--- Testing --- Testing
local distance=self:_GetDistance(location,staticpos) local distance=self:_GetDistance(location,staticpos)
@@ -4399,8 +4361,6 @@ function CTLD:_UnloadTroops(Group, Unit)
local loadedcargo = self.Loaded_Cargo[unitname] or {} -- #CTLD.LoadedCargo local loadedcargo = self.Loaded_Cargo[unitname] or {} -- #CTLD.LoadedCargo
-- looking for troops -- looking for troops
local cargotable = loadedcargo.Cargo local cargotable = loadedcargo.Cargo
local deployedTroopsByName = {}
local deployedEngineersByName = {}
for _,_cargo in pairs (cargotable) do for _,_cargo in pairs (cargotable) do
local cargo = _cargo -- #CTLD_CARGO local cargo = _cargo -- #CTLD_CARGO
local type = cargo:GetType() -- #CTLD_CARGO.Enum local type = cargo:GetType() -- #CTLD_CARGO.Enum
@@ -4457,22 +4417,12 @@ function CTLD:_UnloadTroops(Group, Unit)
self.Engineers = self.Engineers + 1 self.Engineers = self.Engineers + 1
local grpname = self.DroppedTroops[self.TroopCounter]:GetName() local grpname = self.DroppedTroops[self.TroopCounter]:GetName()
self.EngineersInField[self.Engineers] = CTLD_ENGINEERING:New(name, grpname) self.EngineersInField[self.Engineers] = CTLD_ENGINEERING:New(name, grpname)
deployedEngineersByName[name] = (deployedEngineersByName[name] or 0) + 1 self:_SendMessage(string.format("Dropped Engineers %s into action!",name), 10, false, Group)
else else
deployedTroopsByName[name] = (deployedTroopsByName[name] or 0) + 1 self:_SendMessage(string.format("Dropped Troops %s into action!",name), 10, false, Group)
end end
end -- if type end end -- if type end
end -- cargotable loop end -- cargotable loop
local parts = {}
for nName,nCount in pairs(deployedTroopsByName) do
parts[#parts + 1] = tostring(nCount).."x Troops "..nName
end
for nName,nCount in pairs(deployedEngineersByName) do
parts[#parts + 1] = tostring(nCount).."x Engineers "..nName
end
if #parts > 0 then
self:_SendMessage("Dropped "..table.concat(parts, ", ").." into action!", 10, false, Group)
end
else -- droppingatbase else -- droppingatbase
self:_SendMessage("Troops have returned to base!", 10, false, Group) self:_SendMessage("Troops have returned to base!", 10, false, Group)
self:__TroopsRTB(1, Group, Unit, zonename, zone) self:__TroopsRTB(1, Group, Unit, zonename, zone)
@@ -4664,10 +4614,11 @@ function CTLD:_BuildCrates(Group, Unit,Engineering,MultiDrop)
local baseDist = self.CrateDistance or 35 local baseDist = self.CrateDistance or 35
local finddist=baseDist local finddist=baseDist
--if Engineering and self.EngineerSearch and self.EngineerSearch>baseDist then --if Engineering and self.EngineerSearch and self.EngineerSearch>baseDist then
if Engineering and self.EngineerSearch and self.EngineerSearch>baseDist then -- this make also helicopter to be able to crates that are further away due to herc airdrop if self.EngineerSearch and self.EngineerSearch>baseDist then -- this make also helicopter to be able to crates that are further away due to herc airdrop
finddist=self.EngineerSearch finddist=self.EngineerSearch
finddist=self.EngineerSearch
end end
local crates,number = self:_FindCratesNearby(Group,Unit,finddist,true,true,not Engineering) -- #table local crates,number = self:_FindCratesNearby(Group,Unit, finddist,true,true) -- #table
local buildables = {} local buildables = {}
local foundbuilds = false local foundbuilds = false
local canbuild = false local canbuild = false
@@ -4691,12 +4642,11 @@ function CTLD:_BuildCrates(Group, Unit,Engineering,MultiDrop)
local isHercDrop=Crate:WasDropped(true) local isHercDrop=Crate:WasDropped(true)
if not isHercDrop and distToUnit>baseDist then if not isHercDrop and distToUnit>baseDist then
elseif self.UseC130LoadAndUnload and self:IsC130J(Unit) and distToUnit<15 then elseif self.UseC130LoadAndUnload and self:IsC130J(Unit) and distToUnit<15 then
-- self:_SendMessage("Please unload crates from the C-130 before building!",10,false,Group) self:_SendMessage("Please unload crates from the C-130 before building!",10,false,Group)
-- return self return self
elseif self.UseC130LoadAndUnload and self:IsHook(Unit) and distToUnit<5 then elseif self.UseC130LoadAndUnload and self:IsHook(Unit) and distToUnit<5 then
-- self:_SendMessage("Please unload crates from the CH-47 before building!",10,false,Group) self:_SendMessage("Please unload crates from the CH-47 before building!",10,false,Group)
-- return self return self
elseif self.UseC130LoadAndUnload and (Unit:GetTypeName()=="Mi-8MTV2" or Unit:GetTypeName()=="Mi-8MT") and distToUnit<8 then
else else
--local testmarker = ccoord:MarkToAll("Crate found",true,"Build Position") --local testmarker = ccoord:MarkToAll("Crate found",true,"Build Position")
if not buildables[name] then if not buildables[name] then
@@ -4768,7 +4718,7 @@ function CTLD:_BuildCrates(Group, Unit,Engineering,MultiDrop)
local base = Unit:GetCoordinate():Translate(20,hdg) local base = Unit:GetCoordinate():Translate(20,hdg)
if full == 1 then if full == 1 then
local cratesNow, numberNow = self:_FindCratesNearby(Group,Unit, finddist,true,true, not Engineering) local cratesNow, numberNow = self:_FindCratesNearby(Group,Unit, finddist,true,true)
self:_CleanUpCrates(cratesNow,build,numberNow) self:_CleanUpCrates(cratesNow,build,numberNow)
self:_RefreshLoadCratesMenu(Group,Unit) self:_RefreshLoadCratesMenu(Group,Unit)
if self.buildtime and self.buildtime > 0 then if self.buildtime and self.buildtime > 0 then
@@ -4785,7 +4735,7 @@ function CTLD:_BuildCrates(Group, Unit,Engineering,MultiDrop)
else else
local start = -((full-1)*sep)/2 local start = -((full-1)*sep)/2
for n=1,full do for n=1,full do
local cratesNow, numberNow = self:_FindCratesNearby(Group,Unit, finddist,true,true, not Engineering) local cratesNow, numberNow = self:_FindCratesNearby(Group,Unit, finddist,true,true)
self:_CleanUpCrates(cratesNow,build,numberNow) self:_CleanUpCrates(cratesNow,build,numberNow)
self:_RefreshLoadCratesMenu(Group,Unit) self:_RefreshLoadCratesMenu(Group,Unit)
local off = start + (n-1)*sep local off = start + (n-1)*sep
@@ -5579,25 +5529,13 @@ function CTLD:_RefreshF10Menus()
_group.CTLD_TroopMenus = {} _group.CTLD_TroopMenus = {}
if self.usesubcats then if self.usesubcats then
local subcatmenus = {} local subcatmenus = {}
local subcatcount = 0
local onlycat = nil
for catName, _ in pairs(self.subcatsTroop) do for catName, _ in pairs(self.subcatsTroop) do
subcatcount = subcatcount + 1 subcatmenus[catName] = MENU_GROUP:New(_group, catName, troopsmenu)
onlycat = catName
end
local useTroopSubcats = subcatcount > 1 or (subcatcount == 1 and onlycat ~= "Other")
if useTroopSubcats then
for catName, _ in pairs(self.subcatsTroop) do
subcatmenus[catName] = MENU_GROUP:New(_group, catName, troopsmenu)
end
end end
for _, cargoObj in pairs(self.Cargo_Troops) do for _, cargoObj in pairs(self.Cargo_Troops) do
if not cargoObj.DontShowInMenu then if not cargoObj.DontShowInMenu then
local menutext = cargoObj.Name local menutext = cargoObj.Name
local parent = troopsmenu local parent = subcatmenus[cargoObj.Subcategory] or troopsmenu
if useTroopSubcats and cargoObj.Subcategory and subcatmenus[cargoObj.Subcategory] then
parent = subcatmenus[cargoObj.Subcategory]
end
local mSet = MENU_GROUP:New(_group, menutext, parent) local mSet = MENU_GROUP:New(_group, menutext, parent)
_group.CTLD_TroopMenus[cargoObj.Name] = mSet _group.CTLD_TroopMenus[cargoObj.Name] = mSet
self:_AddTroopQuantityMenus(_group,_unit,mSet,cargoObj) self:_AddTroopQuantityMenus(_group,_unit,mSet,cargoObj)
@@ -6473,11 +6411,9 @@ function CTLD:_RefreshDropCratesMenu(Group, Unit)
-- @param Wrapper.Unit#UNIT Unit The calling unit. -- @param Wrapper.Unit#UNIT Unit The calling unit.
-- @param #number chunkID the Cargo ID -- @param #number chunkID the Cargo ID
-- @return #CTLD self -- @return #CTLD self
function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID, qty) function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID)
self:T(self.lid .. " _UnloadSingleTroopByID chunkID=" .. tostring(chunkID)) self:T(self.lid .. " _UnloadSingleTroopByID chunkID=" .. tostring(chunkID))
qty = qty or 1
local droppingatbase = false local droppingatbase = false
local inzone, zonename, zone, distance = self:IsUnitInZone(Unit, CTLD.CargoZoneType.LOAD) local inzone, zonename, zone, distance = self:IsUnitInZone(Unit, CTLD.CargoZoneType.LOAD)
if not inzone then if not inzone then
@@ -6516,92 +6452,80 @@ function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID, qty)
return self return self
end end
local deployedTroopsByName = {}
local deployedEngineersByName = {}
-- Drop the FIRST cargo in that chunk -- Drop the FIRST cargo in that chunk
for n = 1, qty do local foundCargo = chunk[1]
local foundCargo = chunk[1] if not foundCargo then
if not foundCargo then break end self:_SendMessage(string.format("No troop cargo at chunk %d!", chunkID), 10, false, Group)
if not self.debug then return self end
return self
end
local cType = foundCargo:GetType() local cType = foundCargo:GetType()
local name = foundCargo:GetName() or "none" local name = foundCargo:GetName() or "none"
local tmpl = foundCargo:GetTemplates() or {} local tmpl = foundCargo:GetTemplates() or {}
local zoneradius = self.troopdropzoneradius or 100 local zoneradius = self.troopdropzoneradius or 100
local factor = 1 local factor = 1
if isHerc then
factor = foundCargo:GetCratesNeeded() or 1
zoneradius = Unit:GetVelocityMPS() or 100
end
local zone = ZONE_GROUP:New(string.format("Unload zone-%s", unitName), Group, zoneradius * factor)
local randomcoord = zone:GetRandomCoordinate(10, 30 * factor)
local heading = Group:GetHeading() or 0
if grounded or hoverunload then
randomcoord = Group:GetCoordinate()
local Angle = (heading + 270) % 360
if isHerc or isHook then
Angle = (heading + 180) % 360
end
local offset = hoverunload and self.TroopUnloadDistHover or self.TroopUnloadDistGround
if isHerc then if isHerc then
factor = foundCargo:GetCratesNeeded() or 1 offset = self.TroopUnloadDistGroundHerc or 25
zoneradius = Unit:GetVelocityMPS() or 100
end end
local zone = ZONE_GROUP:New(string.format("Unload zone-%s", unitName), Group, zoneradius * factor)
local randomcoord = zone:GetRandomCoordinate(10, 30 * factor)
local heading = Group:GetHeading() or 0
if grounded or hoverunload then
randomcoord = Group:GetCoordinate()
local Angle = (heading + 270) % 360
if isHerc or isHook then
Angle = (heading + 180) % 360
end
local offset = hoverunload and self.TroopUnloadDistHover or self.TroopUnloadDistGround
if isHerc then
offset = self.TroopUnloadDistGroundHerc or 25
end
if isHook then
offset = self.TroopUnloadDistGroundHook or 15
if hoverunload and self.TroopUnloadDistHoverHook then
offset = self.TroopUnloadDistHoverHook or 5
end
end
randomcoord:Translate(offset, Angle, nil, true)
end
local tempcount = 0
if isHook then if isHook then
tempcount = self.ChinookTroopCircleRadius or 5 offset = self.TroopUnloadDistGroundHook or 15
end if hoverunload and self.TroopUnloadDistHoverHook then
for _, _template in pairs(tmpl) do offset = self.TroopUnloadDistHoverHook or 5
self.TroopCounter = self.TroopCounter + 1 end
tempcount = tempcount + 1
local alias = string.format("%s-%d", _template, math.random(1,100000))
local rad = 2.5 + (tempcount * 2)
local Positions = self:_GetUnitPositions(randomcoord, rad, heading, _template)
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template, alias)
:InitDelayOff()
:InitSetUnitAbsolutePositions(Positions)
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
:OnSpawnGroup(function(grp) grp.spawntime = timer.getTime() end)
:SpawnFromVec2(randomcoord:GetVec2())
self:__TroopsDeployed(1, Group, Unit, self.DroppedTroops[self.TroopCounter], cType)
end
foundCargo:SetWasDropped(true)
if cType == CTLD_CARGO.Enum.ENGINEERS then
self.Engineers = self.Engineers + 1
local grpname = self.DroppedTroops[self.TroopCounter]:GetName()
self.EngineersInField[self.Engineers] = CTLD_ENGINEERING:New(name, grpname)
deployedEngineersByName[name] = (deployedEngineersByName[name] or 0) + 1
else
deployedTroopsByName[name] = (deployedTroopsByName[name] or 0) + 1
end
table.remove(chunk, 1)
if #chunk == 0 then
self.TroopsIDToChunk[chunkID] = nil
break
end end
randomcoord:Translate(offset, Angle, nil, true)
end end
local parts = {} local tempcount = 0
for nName,nCount in pairs(deployedTroopsByName) do if isHook then
parts[#parts + 1] = tostring(nCount).."x Troops "..nName tempcount = self.ChinookTroopCircleRadius or 5
end end
for nName,nCount in pairs(deployedEngineersByName) do for _, _template in pairs(tmpl) do
parts[#parts + 1] = tostring(nCount).."x Engineers "..nName self.TroopCounter = self.TroopCounter + 1
tempcount = tempcount + 1
local alias = string.format("%s-%d", _template, math.random(1,100000))
local rad = 2.5 + (tempcount * 2)
local Positions = self:_GetUnitPositions(randomcoord, rad, heading, _template)
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template, alias)
:InitDelayOff()
:InitSetUnitAbsolutePositions(Positions)
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
:OnSpawnGroup(function(grp) grp.spawntime = timer.getTime() end)
:SpawnFromVec2(randomcoord:GetVec2())
self:__TroopsDeployed(1, Group, Unit, self.DroppedTroops[self.TroopCounter], cType)
end end
if #parts > 0 then
self:_SendMessage("Dropped "..table.concat(parts, ", ").." into action!", 10, false, Group) foundCargo:SetWasDropped(true)
if cType == CTLD_CARGO.Enum.ENGINEERS then
self.Engineers = self.Engineers + 1
local grpname = self.DroppedTroops[self.TroopCounter]:GetName()
self.EngineersInField[self.Engineers] = CTLD_ENGINEERING:New(name, grpname)
self:_SendMessage(string.format("Dropped Engineers %s into action!", name), 10, false, Group)
else
self:_SendMessage(string.format("Dropped Troops %s into action!", name), 10, false, Group)
end end
table.remove(chunk, 1)
if #chunk == 0 then
self.TroopsIDToChunk[chunkID] = nil
end
else else
-- Return to base logic, remove ONLY the first cargo -- Return to base logic, remove ONLY the first cargo
self:_SendMessage("Troops have returned to base!", 10, false, Group) self:_SendMessage("Troops have returned to base!", 10, false, Group)
@@ -6609,8 +6533,7 @@ function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID, qty)
if self.TroopsIDToChunk and self.TroopsIDToChunk[chunkID] then if self.TroopsIDToChunk and self.TroopsIDToChunk[chunkID] then
local chunk = self.TroopsIDToChunk[chunkID] local chunk = self.TroopsIDToChunk[chunkID]
for n = 1, qty do if #chunk > 0 then
if #chunk == 0 then break end
local firstObj = chunk[1] local firstObj = chunk[1]
local cName = firstObj:GetName() local cName = firstObj:GetName()
local gentroops = self.Cargo_Troops local gentroops = self.Cargo_Troops
@@ -6625,9 +6548,9 @@ function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID, qty)
end end
firstObj:SetWasDropped(true) firstObj:SetWasDropped(true)
table.remove(chunk, 1) table.remove(chunk, 1)
end if #chunk == 0 then
if #chunk == 0 then self.TroopsIDToChunk[chunkID] = nil
self.TroopsIDToChunk[chunkID] = nil end
end end
end end
end end
@@ -6674,13 +6597,11 @@ function CTLD:_RefreshDropTroopsMenu(Group, Unit)
if not theGroup.CTLDTopmenu then return end if not theGroup.CTLDTopmenu then return end
local topTroops = theGroup.MyTopTroopsMenu local topTroops = theGroup.MyTopTroopsMenu
if not topTroops then return end if not topTroops then return end
local dropTroopsMenu = topTroops.DropTroopsMenu if topTroops.DropTroopsMenu then
if dropTroopsMenu then topTroops.DropTroopsMenu:Remove()
dropTroopsMenu:RemoveSubMenus()
else
dropTroopsMenu = MENU_GROUP:New(theGroup, "Drop Troops", topTroops)
topTroops.DropTroopsMenu = dropTroopsMenu
end end
local dropTroopsMenu = MENU_GROUP:New(theGroup, "Drop Troops", topTroops)
topTroops.DropTroopsMenu = dropTroopsMenu
MENU_GROUP_COMMAND:New(theGroup, "Drop ALL troops", dropTroopsMenu, self._UnloadTroops, self, theGroup, theUnit) MENU_GROUP_COMMAND:New(theGroup, "Drop ALL troops", dropTroopsMenu, self._UnloadTroops, self, theGroup, theUnit)
local loadedData = self.Loaded_Cargo[theUnit:GetName()] local loadedData = self.Loaded_Cargo[theUnit:GetName()]
@@ -6704,22 +6625,15 @@ function CTLD:_RefreshDropTroopsMenu(Group, Unit)
for tName, objList in pairs(troopsByName) do for tName, objList in pairs(troopsByName) do
table.sort(objList, function(a,b) return a:GetID() < b:GetID() end) table.sort(objList, function(a,b) return a:GetID() < b:GetID() end)
local count = #objList local count = #objList
if count > 0 then
local chunkID = objList[1]:GetID()
self.TroopsIDToChunk[chunkID] = objList
local label = string.format("Drop %s (%d)", tName, count) local chunkID = objList[1]:GetID()
if count == 1 then self.TroopsIDToChunk[chunkID] = objList
MENU_GROUP_COMMAND:New(theGroup, label, dropTroopsMenu, self._UnloadSingleTroopByID, self, theGroup, theUnit, chunkID, 1)
else local label = string.format("Drop %s (%d)", tName, count)
local parentMenu = MENU_GROUP:New(theGroup, label, dropTroopsMenu) MENU_GROUP_COMMAND:New(theGroup, label, dropTroopsMenu, self._UnloadSingleTroopByID, self, theGroup, theUnit, chunkID)
for q = 1, count do
MENU_GROUP_COMMAND:New(theGroup, string.format("Drop (%d) %s", q, tName), parentMenu, self._UnloadSingleTroopByID, self, theGroup, theUnit, chunkID, q)
end
end
end
end end
end end
--- [Internal] Function to check if a template exists in the mission. --- [Internal] Function to check if a template exists in the mission.
-- @param #CTLD self -- @param #CTLD self
-- @param #table temptable Table of string names -- @param #table temptable Table of string names
+1 -11
View File
@@ -396,8 +396,7 @@ function CHIEF:New(Coalition, AgentSet, Alias)
self.TransportCategories = {Group.Category.HELICOPTER} self.TransportCategories = {Group.Category.HELICOPTER}
-- Create a new COMMANDER. -- Create a new COMMANDER.
self.commander=COMMANDER:New(Coalition, Alias) self.commander=COMMANDER:New(Coalition)
-- Add FSM transitions. -- Add FSM transitions.
-- From State --> Event --> To State -- From State --> Event --> To State
@@ -3358,15 +3357,6 @@ function CHIEF._CheckAssetProperties(Asset, Properties)
return false return false
end end
--- Checks whether or not any of the legions con run a mission.
-- @param #CHIEF self
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
-- @return #boolean If `true`, one of the cohorts can run the mission.
function CHIEF:CanMission(Mission)
return self.commander and self.commander:CanMission(Mission)
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-64
View File
@@ -1748,70 +1748,6 @@ function COMMANDER:_GetCohorts(Legions, Cohorts, Operation)
return cohorts return cohorts
end end
--- Checks whether or not any of the legions con run a mission.
-- @param #COMMANDER self
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
-- @return #boolean If `true`, one of the cohorts can run the mission.
function COMMANDER:CanMission(Mission)
local commander = self
-- Target position.
local TargetVec2 = Mission:GetTargetVec2()
local MaxWeight = nil
if Mission.NcarriersMin then
local legions = commander.legions
local cohorts = nil
if Mission.transportLegions or Mission.transportCohorts then
legions = Mission.transportLegions
cohorts = Mission.transportCohorts
end
-- Get transport cohorts.
local Cohorts = LEGION._GetCohorts(legions, cohorts)
-- Filter cohorts that can actually perform transport missions.
local transportcohorts = {}
for _, _cohort in pairs(Cohorts) do
local cohort = _cohort --Ops.Cohort#COHORT
-- Check if cohort can perform transport to target.
local can = LEGION._CohortCan(cohort, AUFTRAG.Type.OPSTRANSPORT, Mission.carrierCategories, Mission.carrierAttributes, Mission.carrierProperties, nil, TargetVec2)
-- MaxWeight of cargo assets is limited by the largets available cargo bay. We don't want to select, e.g., tanks that cannot be transported by APCs or helos.
if can and (MaxWeight == nil or cohort.cargobayLimit > MaxWeight) then
MaxWeight = cohort.cargobayLimit
end
end
end
local legions = commander.legions
local cohorts = nil
if Mission.specialLegions or Mission.specialCohorts then
legions = Mission.specialLegions
cohorts = Mission.specialCohorts
end
-- Get cohorts.
local Cohorts = LEGION._GetCohorts(legions, cohorts, Mission.operation, commander.opsqueue)
for _, _cohort in pairs(Cohorts) do
local cohort = _cohort --Ops.Cohort#COHORT
-- Check if cohort can do the mission.
local can = LEGION._CohortCan(cohort, Mission.type, nil, Mission.attributes, Mission.properties, { Mission.engageWeaponType }, TargetVec2, Mission.engageRange, Mission.refuelSystem, nil, MaxWeight)
if can then
return true
end
end
return false
end
--- Recruit assets for a given mission. --- Recruit assets for a given mission.
-- @param #COMMANDER self -- @param #COMMANDER self
-- @param Ops.Auftrag#AUFTRAG Mission The mission. -- @param Ops.Auftrag#AUFTRAG Mission The mission.
+6 -8
View File
@@ -21,7 +21,7 @@
-- --
------------------------------------------------------------------------- -------------------------------------------------------------------------
-- Date: Dec 2025 -- Date: Dec 2025
-- Last Update: Jan 2026 -- Last Update: Dec 2025
------------------------------------------------------------------------- -------------------------------------------------------------------------
-- --
-- === -- ===
@@ -293,7 +293,7 @@ EASYA2G = {
--- EASYA2G class version. --- EASYA2G class version.
-- @field #string version -- @field #string version
EASYA2G.version="0.1.4" EASYA2G.version="0.1.3"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
@@ -319,10 +319,6 @@ function EASYA2G:New(Alias, AirbaseName, Coalition, ScoutName)
-- defaults -- defaults
self.alias = Alias or AirbaseName.." A2G Wing" self.alias = Alias or AirbaseName.." A2G Wing"
-- Set some string id for output to DCS.log file.
self.lid=string.format("EASYA2G %s | ", self.alias)
self.coalitionname = string.lower(Coalition) or "blue" self.coalitionname = string.lower(Coalition) or "blue"
self.coalition = self.coalitionname == "blue" and coalition.side.BLUE or coalition.side.RED self.coalition = self.coalitionname == "blue" and coalition.side.BLUE or coalition.side.RED
self.wings = {} self.wings = {}
@@ -356,8 +352,10 @@ function EASYA2G:New(Alias, AirbaseName, Coalition, ScoutName)
self.FuelCriticalThreshold = 10 self.FuelCriticalThreshold = 10
self.showpatrolpointmarks = false self.showpatrolpointmarks = false
self.EngageTargetTypes = {"Ground"} self.EngageTargetTypes = {"Ground"}
self:SetDefaultTurnoverTime()
-- Set some string id for output to DCS.log file.
self.lid=string.format("EASYA2G %s | ", self.alias)
-- Add FSM transitions. -- Add FSM transitions.
-- From State --> Event --> To State -- From State --> Event --> To State
self:SetStartState("Stopped") self:SetStartState("Stopped")
@@ -548,7 +546,7 @@ function EASYA2G:_AddSquadron(TemplateName, SquadName, AirbaseName, AirFrames, S
Squadron_One:AddMissionCapability({AUFTRAG.Type.CAS, AUFTRAG.Type.CASENHANCED, AUFTRAG.Type.BAI, AUFTRAG.Type.ALERT5, AUFTRAG.Type.BOMBING, AUFTRAG.Type.STRIKE}) Squadron_One:AddMissionCapability({AUFTRAG.Type.CAS, AUFTRAG.Type.CASENHANCED, AUFTRAG.Type.BAI, AUFTRAG.Type.ALERT5, AUFTRAG.Type.BOMBING, AUFTRAG.Type.STRIKE})
--Squadron_One:SetFuelLowRefuel(true) --Squadron_One:SetFuelLowRefuel(true)
Squadron_One:SetFuelLowThreshold(0.3) Squadron_One:SetFuelLowThreshold(0.3)
Squadron_One:SetTurnoverTime(self.maintenancetime,self.repairtime) Squadron_One:SetTurnoverTime(10,20)
Squadron_One:SetModex(Modex) Squadron_One:SetModex(Modex)
Squadron_One:SetLivery(Livery) Squadron_One:SetLivery(Livery)
Squadron_One:SetSkill(Skill or AI.Skill.AVERAGE) Squadron_One:SetSkill(Skill or AI.Skill.AVERAGE)
+10 -26
View File
@@ -21,7 +21,7 @@
-- --
------------------------------------------------------------------------- -------------------------------------------------------------------------
-- Date: September 2023 -- Date: September 2023
-- Last Update: Jan 2026 -- Last Update: Aug 2025
------------------------------------------------------------------------- -------------------------------------------------------------------------
-- --
--- **Ops** - Easy GCI & CAP Manager --- **Ops** - Easy GCI & CAP Manager
@@ -89,8 +89,6 @@
-- @field #number FuelCriticalThreshold -- @field #number FuelCriticalThreshold
-- @field #boolean showpatrolpointmarks -- @field #boolean showpatrolpointmarks
-- @field #table EngageTargetTypes -- @field #table EngageTargetTypes
-- @field #number maintenancetime
-- @field #number repairtime
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
--- *“Airspeed, altitude, and brains. Two are always needed to successfully complete the flight.”* -- Unknown. --- *“Airspeed, altitude, and brains. Two are always needed to successfully complete the flight.”* -- Unknown.
@@ -286,7 +284,7 @@ EASYGCICAP = {
--- EASYGCICAP class version. --- EASYGCICAP class version.
-- @field #string version -- @field #string version
EASYGCICAP.version="0.1.34" EASYGCICAP.version="0.1.33"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- --
@@ -312,10 +310,6 @@ function EASYGCICAP:New(Alias, AirbaseName, Coalition, EWRName)
-- defaults -- defaults
self.alias = Alias or AirbaseName.." CAP Wing" self.alias = Alias or AirbaseName.." CAP Wing"
-- Set some string id for output to DCS.log file.
self.lid=string.format("EASYGCICAP %s | ", self.alias)
self.coalitionname = string.lower(Coalition) or "blue" self.coalitionname = string.lower(Coalition) or "blue"
self.coalition = self.coalitionname == "blue" and coalition.side.BLUE or coalition.side.RED self.coalition = self.coalitionname == "blue" and coalition.side.BLUE or coalition.side.RED
self.wings = {} self.wings = {}
@@ -349,8 +343,10 @@ function EASYGCICAP:New(Alias, AirbaseName, Coalition, EWRName)
self.FuelCriticalThreshold = 10 self.FuelCriticalThreshold = 10
self.showpatrolpointmarks = false self.showpatrolpointmarks = false
self.EngageTargetTypes = {"Air"} self.EngageTargetTypes = {"Air"}
self:SetDefaultTurnoverTime()
-- Set some string id for output to DCS.log file.
self.lid=string.format("EASYGCICAP %s | ", self.alias)
-- Add FSM transitions. -- Add FSM transitions.
-- From State --> Event --> To State -- From State --> Event --> To State
self:SetStartState("Stopped") self:SetStartState("Stopped")
@@ -612,18 +608,6 @@ function EASYGCICAP:SetDefaultMissionRange(Range)
return self return self
end end
--- Set default turnover times for squadrons in minutes
-- @param #EASYGCICAP self
-- @param #number MaintenanceTime Time in minutes it takes until a flight is combat ready again. Default is 5 min.
-- @param #number RepairTime Time in minutes it takes to repair a flight for each life point taken. Default is 10 min.
-- @return #EASYGCICAP self
function EASYGCICAP:SetDefaultTurnoverTime(MaintenanceTime,RepairTime)
self:T(self.lid.."SetDefaultTurnoverTime")
self.maintenancetime=MaintenanceTime or 5
self.repairtime=RepairTime or 10
return self
end
--- Set default number of airframes standing by for intercept tasks (visible on the airfield) --- Set default number of airframes standing by for intercept tasks (visible on the airfield)
-- @param #EASYGCICAP self -- @param #EASYGCICAP self
-- @param #number Airframes defaults to 2 -- @param #number Airframes defaults to 2
@@ -1233,7 +1217,7 @@ function EASYGCICAP:_AddSquadron(TemplateName, SquadName, AirbaseName, AirFrames
Squadron_One:AddMissionCapability({AUFTRAG.Type.CAP, AUFTRAG.Type.GCICAP, AUFTRAG.Type.INTERCEPT, AUFTRAG.Type.PATROLRACETRACK, AUFTRAG.Type.ALERT5}) Squadron_One:AddMissionCapability({AUFTRAG.Type.CAP, AUFTRAG.Type.GCICAP, AUFTRAG.Type.INTERCEPT, AUFTRAG.Type.PATROLRACETRACK, AUFTRAG.Type.ALERT5})
--Squadron_One:SetFuelLowRefuel(true) --Squadron_One:SetFuelLowRefuel(true)
Squadron_One:SetFuelLowThreshold(0.3) Squadron_One:SetFuelLowThreshold(0.3)
Squadron_One:SetTurnoverTime(self.maintenancetime,self.repairtime) Squadron_One:SetTurnoverTime(10,20)
Squadron_One:SetModex(Modex) Squadron_One:SetModex(Modex)
Squadron_One:SetLivery(Livery) Squadron_One:SetLivery(Livery)
Squadron_One:SetSkill(Skill or AI.Skill.AVERAGE) Squadron_One:SetSkill(Skill or AI.Skill.AVERAGE)
@@ -1264,7 +1248,7 @@ function EASYGCICAP:_AddReconSquadron(TemplateName, SquadName, AirbaseName, AirF
Squadron_One:AddMissionCapability({AUFTRAG.Type.RECON}) Squadron_One:AddMissionCapability({AUFTRAG.Type.RECON})
--Squadron_One:SetFuelLowRefuel(true) --Squadron_One:SetFuelLowRefuel(true)
Squadron_One:SetFuelLowThreshold(0.3) Squadron_One:SetFuelLowThreshold(0.3)
Squadron_One:SetTurnoverTime(self.maintenancetime,self.repairtime) Squadron_One:SetTurnoverTime(10,20)
Squadron_One:SetModex(Modex) Squadron_One:SetModex(Modex)
Squadron_One:SetLivery(Livery) Squadron_One:SetLivery(Livery)
Squadron_One:SetSkill(Skill or AI.Skill.AVERAGE) Squadron_One:SetSkill(Skill or AI.Skill.AVERAGE)
@@ -1298,7 +1282,7 @@ function EASYGCICAP:_AddTankerSquadron(TemplateName, SquadName, AirbaseName, Air
Squadron_One:AddMissionCapability({AUFTRAG.Type.TANKER}) Squadron_One:AddMissionCapability({AUFTRAG.Type.TANKER})
--Squadron_One:SetFuelLowRefuel(true) --Squadron_One:SetFuelLowRefuel(true)
Squadron_One:SetFuelLowThreshold(0.3) Squadron_One:SetFuelLowThreshold(0.3)
Squadron_One:SetTurnoverTime(self.maintenancetime,self.repairtime) Squadron_One:SetTurnoverTime(10,20)
Squadron_One:SetModex(Modex) Squadron_One:SetModex(Modex)
Squadron_One:SetLivery(Livery) Squadron_One:SetLivery(Livery)
Squadron_One:SetSkill(Skill or AI.Skill.AVERAGE) Squadron_One:SetSkill(Skill or AI.Skill.AVERAGE)
@@ -1335,7 +1319,7 @@ function EASYGCICAP:_AddAWACSSquadron(TemplateName, SquadName, AirbaseName, AirF
Squadron_One:AddMissionCapability({AUFTRAG.Type.AWACS}) Squadron_One:AddMissionCapability({AUFTRAG.Type.AWACS})
--Squadron_One:SetFuelLowRefuel(true) --Squadron_One:SetFuelLowRefuel(true)
Squadron_One:SetFuelLowThreshold(0.3) Squadron_One:SetFuelLowThreshold(0.3)
Squadron_One:SetTurnoverTime(self.maintenancetime,self.repairtime) Squadron_One:SetTurnoverTime(10,20)
Squadron_One:SetModex(Modex) Squadron_One:SetModex(Modex)
Squadron_One:SetLivery(Livery) Squadron_One:SetLivery(Livery)
Squadron_One:SetSkill(Skill or AI.Skill.AVERAGE) Squadron_One:SetSkill(Skill or AI.Skill.AVERAGE)
@@ -1642,7 +1626,7 @@ function EASYGCICAP:_StartIntel()
if self.usecorridors == true then if self.usecorridors == true then
BlueIntel:SetCorridorZones(self.corridorzones) BlueIntel:SetCorridorZones(self.corridorzones)
if self.corridorfloor or self.corridorceiling then if self.corridorfloor or self.corridorceiling then
BlueIntel:SetCorridorLimits(self.corridorfloor,self.corridorceiling) BlueIntel:SetCorridorLimitsFeet(self.corridorfloor,self.corridorceiling)
end end
end end
+5 -5
View File
@@ -1175,7 +1175,7 @@ function INTEL:_CreateContact(Positionable, RecceName)
item.category=3 --static:GetCategory() item.category=3 --static:GetCategory()
item.categoryname=static:GetCategoryName() or "Unknown" item.categoryname=static:GetCategoryName() or "Unknown"
item.threatlevel=static:GetThreatLevel() or 0 item.threatlevel=static:GetThreatLevel() or 0
item.position=static:GetCoord() item.position=static:GetCoordinate()
item.velocity=static:GetVelocityVec3() item.velocity=static:GetVelocityVec3()
item.speed=0 item.speed=0
item.recce=RecceName item.recce=RecceName
@@ -1282,15 +1282,15 @@ function INTEL:GetDetectedUnits(Unit, DetectedUnits, RecceDetecting, DetectVisua
local DetectionAccepted = true local DetectionAccepted = true
if self.RadarAcceptRange then if self.RadarAcceptRange then
local reccecoord = Unit:GetCoord() local reccecoord = Unit:GetCoordinate()
local coord = unit:GetCoord() local coord = unit:GetCoordinate()
local dist = math.floor(coord:Get2DDistance(reccecoord)/1000) -- km local dist = math.floor(coord:Get2DDistance(reccecoord)/1000) -- km
if dist > self.RadarAcceptRangeKilometers then DetectionAccepted = false end if dist > self.RadarAcceptRangeKilometers then DetectionAccepted = false end
end end
if self.RadarBlur then if self.RadarBlur then
local reccecoord = Unit:GetCoord() local reccecoord = Unit:GetCoordinate()
local coord = unit:GetCoord() local coord = unit:GetCoordinate()
local dist = math.floor(coord:Get2DDistance(reccecoord)/1000) -- km local dist = math.floor(coord:Get2DDistance(reccecoord)/1000) -- km
local AGL = unit:GetAltitude(true) local AGL = unit:GetAltitude(true)
local minheight = self.RadarBlurMinHeight or 250 -- meters local minheight = self.RadarBlurMinHeight or 250 -- meters
+9
View File
@@ -2741,6 +2741,15 @@ function OPSGROUP:IsOutOfTorpedos()
return self.outofTorpedos return self.outofTorpedos
end end
--- Check if the group is out of A2G Ammo
-- @param #OPSGROUP self
-- @return #boolean If `true`, group is out of torpedos.
function OPSGROUP:IsOutOfA2GAmmo()
if (self.outofMissilesAG and self.outofBombs and self.outofGuns) or self.outofAmmo then
return true
end
return false
end
--- Check if the group has currently switched a LASER on. --- Check if the group has currently switched a LASER on.
-- @param #OPSGROUP self -- @param #OPSGROUP self
+8 -66
View File
@@ -237,7 +237,7 @@ function PLAYERTASK:New(Type, Target, Repeat, Times, TTSType)
-- @param #string From From state. -- @param #string From From state.
-- @param #string Event Event. -- @param #string Event Event.
-- @param #string To To state. -- @param #string To To state.
-- @param #boolean Silent If true, suppress message output on cancel. -- @param #boolen Silent If true, suppress message output on cancel.
--- On After "Planned" event. Task has been planned. --- On After "Planned" event. Task has been planned.
-- @function [parent=#PLAYERTASK] OnAfterPilotPlanned -- @function [parent=#PLAYERTASK] OnAfterPilotPlanned
@@ -1599,7 +1599,6 @@ do
-- ELEVATION = "\nTarget Elevation: %s %s", -- ELEVATION = "\nTarget Elevation: %s %s",
-- METER = "meter", -- METER = "meter",
-- FEET = "feet", -- FEET = "feet",
-- INTERCEPTCOURSE = "Intercept course",
-- }, -- },
-- --
-- e.g. -- e.g.
@@ -1922,7 +1921,6 @@ PLAYERTASKCONTROLLER.Messages = {
DESTROYER = "Destroyer", DESTROYER = "Destroyer",
CARRIER = "Aircraft Carrier", CARRIER = "Aircraft Carrier",
RADIOS = "Radios", RADIOS = "Radios",
INTERCEPTCOURSE = "Intercept course",
}, },
DE = { DE = {
TASKABORT = "Auftrag abgebrochen!", TASKABORT = "Auftrag abgebrochen!",
@@ -2010,13 +2008,12 @@ PLAYERTASKCONTROLLER.Messages = {
DESTROYER = "Zerstörer", DESTROYER = "Zerstörer",
CARRIER = "Flugzeugträger", CARRIER = "Flugzeugträger",
RADIOS = "Frequenzen", RADIOS = "Frequenzen",
INTERCEPTCOURSE = "Abfangkurs",
}, },
} }
--- PLAYERTASK class version. --- PLAYERTASK class version.
-- @field #string version -- @field #string version
PLAYERTASKCONTROLLER.version="0.1.73" PLAYERTASKCONTROLLER.version="0.1.71"
--- Create and run a new TASKCONTROLLER instance. --- Create and run a new TASKCONTROLLER instance.
-- @param #PLAYERTASKCONTROLLER self -- @param #PLAYERTASKCONTROLLER self
@@ -3779,41 +3776,6 @@ function PLAYERTASKCONTROLLER:_ShowRadioInfo(Group, Client)
return self return self
end end
--- Calculate group future position after given seconds.
-- @param #PLAYERTASKCONTROLLER self
-- @param Wrapper.Group#GROUP group The group to calculate for.
-- @param #number seconds Time interval in seconds. Default is `self.prediction`.
-- @return Core.Point#COORDINATE Calculated future position of the cluster.
function PLAYERTASKCONTROLLER:_CalcGroupFuturePosition(group, seconds)
-- Get current position of the cluster.
local p=group:GetCoordinate()
-- Velocity vector in m/s.
local v=group:GetVelocityVec3()
-- Time in seconds.
local t=seconds or self.prediction
-- Extrapolated vec3.
local Vec3={x=p.x+v.x*t, y=p.y+v.y*t, z=p.z+v.z*t}
-- Future position.
local futureposition=COORDINATE:NewFromVec3(Vec3)
-- Create an arrow pointing in the direction of the movement.
if self.verbose == true then
local markerID = group:GetProperty("PLAYERTASK_ARROW")
if markerID then
COORDINATE:RemoveMark(markerID)
end
markerID = p:ArrowToAll(futureposition, self.coalition, {1,0,0}, 1, {1,1,0}, 0.5, 2, true, "Position Calc")
group:SetProperty("PLAYERTASK_ARROW",markerID)
end
return futureposition
end
--- [Internal] Flashing directional info for a client --- [Internal] Flashing directional info for a client
-- @param #PLAYERTASKCONTROLLER self -- @param #PLAYERTASKCONTROLLER self
-- @return #PLAYERTASKCONTROLLER self -- @return #PLAYERTASKCONTROLLER self
@@ -3823,34 +3785,16 @@ function PLAYERTASKCONTROLLER:_FlashInfo()
if _client and _client:IsAlive() then if _client and _client:IsAlive() then
if self.TasksPerPlayer:HasUniqueID(_playername) then if self.TasksPerPlayer:HasUniqueID(_playername) then
local task = self.TasksPerPlayer:ReadByID(_playername) -- Ops.PlayerTask#PLAYERTASK local task = self.TasksPerPlayer:ReadByID(_playername) -- Ops.PlayerTask#PLAYERTASK
local Coordinate = task.Target:GetCoordinate() -- Core.Point#COORDINATE local Coordinate = task.Target:GetCoordinate()
local CoordText = "" local CoordText = ""
if self.Type ~= PLAYERTASKCONTROLLER.Type.A2A and task.Type~=AUFTRAG.Type.INTERCEPT then if self.Type ~= PLAYERTASKCONTROLLER.Type.A2A and task.Type~=AUFTRAG.Type.INTERCEPT then
CoordText = Coordinate:ToStringA2G(_client, nil, self.ShowMagnetic) CoordText = Coordinate:ToStringA2G(_client, nil, self.ShowMagnetic)
local targettxt = self.gettext:GetEntry("TARGET",self.locale)
local text = targettxt..": "..CoordText
local m = MESSAGE:New(text,10,"Tasking"):ToClient(_client)
else else
CoordText = Coordinate:ToStringA2A(_client, nil, self.ShowMagnetic) CoordText = Coordinate:ToStringA2A(_client, nil, self.ShowMagnetic)
local targettxt = self.gettext:GetEntry("TARGET",self.locale)
local text = targettxt..": "..CoordText
-- calc intercept position
local name=task.Target:GetName()
local group = GROUP:FindByName(name)
local clientcoord = _client:GetCoordinate()
if group and clientcoord and group:IsAlive() and task.Type==AUFTRAG.Type.INTERCEPT then
local speed = math.max(UTILS.KnotsToMps(350) or _client:GetVelocityMPS())
local dist = Coordinate:Get3DDistance(clientcoord)
local iTime = math.floor(dist/speed)+5
if iTime < 10 then iTime = 10
elseif iTime > 600 then iTime = 600 end
local npos = self:_CalcGroupFuturePosition(group,iTime)
local BR = npos:ToStringBearing(clientcoord,nil,self.ShowMagnetic,0 )
local Intercepttext = self.gettext:GetEntry("INTERCEPTCOURSE",self.locale)
text = text .. "\n"..Intercepttext.." "..BR
end
local m = MESSAGE:New(text,10,"Tasking"):ToClient(_client)
end end
local targettxt = self.gettext:GetEntry("TARGET",self.locale)
local text = "Target: "..CoordText
local m = MESSAGE:New(text,10,"Tasking"):ToClient(_client)
end end
end end
end end
@@ -3939,10 +3883,8 @@ function PLAYERTASKCONTROLLER:_ActiveTaskInfo(Task, Group, Client)
Elevation = math.floor(UTILS.MetersToFeet(Elevation)) Elevation = math.floor(UTILS.MetersToFeet(Elevation))
end end
-- ELEVATION = "\nTarget Elevation: %s %s", -- ELEVATION = "\nTarget Elevation: %s %s",
if task.Type ~= AUFTRAG.Type.INTERCEPT then local elev = self.gettext:GetEntry("ELEVATION",self.locale)
local elev = self.gettext:GetEntry("ELEVATION",self.locale) text = text .. string.format(elev,tostring(math.floor(Elevation)),elevationmeasure)
text = text .. string.format(elev,tostring(math.floor(Elevation)),elevationmeasure)
end
-- Prec bombing -- Prec bombing
if task.Type == AUFTRAG.Type.PRECISIONBOMBING and self.precisionbombing then if task.Type == AUFTRAG.Type.PRECISIONBOMBING and self.precisionbombing then
if LasingDrone and LasingDrone.playertask then if LasingDrone and LasingDrone.playertask then
+4 -34
View File
@@ -310,7 +310,7 @@ _RECOVERYTANKERID=0
--- Class version. --- Class version.
-- @field #string version -- @field #string version
RECOVERYTANKER.version="1.0.11" RECOVERYTANKER.version="1.0.10"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
@@ -923,22 +923,6 @@ function RECOVERYTANKER:onafterStart(From, Event, To)
Spawn:InitRadioCommsOnOff(true) Spawn:InitRadioCommsOnOff(true)
Spawn:InitRadioFrequency(self.RadioFreq) Spawn:InitRadioFrequency(self.RadioFreq)
Spawn:InitRadioModulation(self.RadioModu) Spawn:InitRadioModulation(self.RadioModu)
if self.callsignname and self.callsignnumber then
local grp = GROUP:FindByName(self.tankergroupname)
if grp then
local typename = grp:GetTypeName() or ""
--self:I(self.lid.."Typename: "..typename)
local Name
local enumerator = CALLSIGN.Tanker
if typename == "A6E" then
enumerator = CALLSIGN.Intruder
end
Name = self:_GetCallsignName(self.callsignname,enumerator)
--self:I(self.lid.."CallsignName: "..Name)
Spawn:InitCallSign(self.callsignname,Name,self.callsignnumber,self.callsignnumber)
end
end
Spawn:InitModex(self.modex) Spawn:InitModex(self.modex)
-- Spawn on carrier. -- Spawn on carrier.
@@ -1206,9 +1190,9 @@ function RECOVERYTANKER:onafterPatternUpdate(From, Event, To)
-- Task combo. -- Task combo.
-- Be a tanker or be an AWACS. -- Be a tanker or be an AWACS.
local taskrole = self.tanker:EnRouteTaskTanker() local taskroll = self.tanker:EnRouteTaskTanker()
if self.awacs then if self.awacs then
taskrole=self.tanker:EnRouteTaskAWACS() taskroll=self.tanker:EnRouteTaskAWACS()
end end
--local taskeplrs=self.tanker:TaskEPLRS(true, 2) --local taskeplrs=self.tanker:TaskEPLRS(true, 2)
@@ -1217,7 +1201,7 @@ function RECOVERYTANKER:onafterPatternUpdate(From, Event, To)
local taskroute = self.tanker:TaskRoute(wp) local taskroute = self.tanker:TaskRoute(wp)
-- Note that the order is important here! tasktanker has to come first. Otherwise it does not work. -- Note that the order is important here! tasktanker has to come first. Otherwise it does not work.
local taskcombo = self.tanker:TaskCombo({taskrole, taskroute}) local taskcombo = self.tanker:TaskCombo({taskroll, taskroute})
-- Set task. -- Set task.
self.tanker:SetTask(taskcombo, 1) self.tanker:SetTask(taskcombo, 1)
@@ -1466,20 +1450,6 @@ function RECOVERYTANKER:_RefuelingStop(EventData)
end end
--- Get clear name callsign for spawn from enumerator
-- @param #RECOVERYTANKER self
-- @param #number Callsign
-- @param #table Enumerator The table of callsigns, e.g. `CALLSIGN.Tanker`
-- @return #string Name Name or "" if not found
function RECOVERYTANKER:_GetCallsignName(Callsign, Enumerator)
for name, value in pairs(Enumerator or {}) do
if value==Callsign then
return name
end
end
return ""
end
--- A unit crashed or died. --- A unit crashed or died.
-- @param #RECOVERYTANKER self -- @param #RECOVERYTANKER self
-- @param Core.Event#EVENTDATA EventData Event data. -- @param Core.Event#EVENTDATA EventData Event data.
-276
View File
@@ -1798,273 +1798,6 @@ ENUMS.Storage.weapons.missiles.Igla_S = 'weapons.missiles.Igla_S'
ENUMS.Storage.weapons.gunmounts.AKAN_NO_TRC = 'weapons.gunmounts.{AKAN_NO_TRC}' ENUMS.Storage.weapons.gunmounts.AKAN_NO_TRC = 'weapons.gunmounts.{AKAN_NO_TRC}'
ENUMS.Storage.weapons.gunmounts.AKAN = 'weapons.gunmounts.{AKAN}' ENUMS.Storage.weapons.gunmounts.AKAN = 'weapons.gunmounts.{AKAN}'
ENUMS.Storage.weapons.shells.M882_9x19 = 'weapons.shells.9x19_m882' ENUMS.Storage.weapons.shells.M882_9x19 = 'weapons.shells.9x19_m882'
ENUMS.Storage.weapons.adapters.HB_F_4E_ORD_LAU_77 = 'weapons.adapters.HB_F-4E_ORD_LAU_77'
ENUMS.Storage.weapons.adapters.hb_a_6e_lau7_adu299 = 'weapons.adapters.hb_a-6e_lau7_adu299'
ENUMS.Storage.weapons.bombs.AH6_SMOKE_BLUE = 'weapons.bombs.AH6_SMOKE_BLUE'
ENUMS.Storage.weapons.bombs.AH6_SMOKE_GREEN = 'weapons.bombs.AH6_SMOKE_GREEN'
ENUMS.Storage.weapons.bombs.AH6_SMOKE_RED = 'weapons.bombs.AH6_SMOKE_RED'
ENUMS.Storage.weapons.bombs.AH6_SMOKE_YELLOW = 'weapons.bombs.AH6_SMOKE_YELLOW'
ENUMS.Storage.weapons.missiles.HB_AGM_78 = 'weapons.missiles.HB_AGM_78'
ENUMS.Storage.weapons.missiles.V_1 = 'weapons.missiles.V-1'
ENUMS.Storage.weapons.shells.Oerlikon_20mm_HE = 'weapons.shells.Oerlikon_20mm_HE'
ENUMS.Storage.weapons.shells.RM_15cm_HE = 'weapons.shells.RM_15cm_HE'
ENUMS.Storage.weapons.shells.HE_T_MkII_40mm = 'weapons.shells.HE_T_MkII_40mm'
ENUMS.Storage.weapons.shells.APCBC = 'weapons.shells.APCBC'
ENUMS.Storage.weapons.shells.Sprgr_43_L71 = 'weapons.shells.Sprgr_43_L71'
ENUMS.Storage.weapons.shells.Mk_20_HE_shell = 'weapons.shells.Mk_20_HE_shell'
ENUMS.Storage.weapons.shells.Pzgr_39_42 = 'weapons.shells.Pzgr_39/42'
ENUMS.Storage.weapons.shells.M1_37mm_37AP_T = 'weapons.shells.M1_37mm_37AP-T'
ENUMS.Storage.weapons.shells.Sprgr_38 = 'weapons.shells.Sprgr_38'
ENUMS.Storage.weapons.shells.Sprgr_39 = 'weapons.shells.Sprgr_39'
ENUMS.Storage.weapons.shells.Pzgr_39_43 = 'weapons.shells.Pzgr_39/43'
ENUMS.Storage.weapons.shells.Pzgr_39_5cm = 'weapons.shells.Pzgr_39_5cm'
ENUMS.Storage.weapons.shells.AP_2A20_115mm = 'weapons.shells.2A20_115mm_AP'
ENUMS.Storage.weapons.shells.AP_T_MkI_40mm = 'weapons.shells.AP_T_MkI_40mm'
ENUMS.Storage.weapons.shells.AP_37x263 = 'weapons.shells.37x263_AP'
ENUMS.Storage.weapons.shells.AP_20x138B = 'weapons.shells.20x138B_AP'
ENUMS.Storage.weapons.shells.Besa7_92x57T = 'weapons.shells.Besa7_92x57T'
ENUMS.Storage.weapons.shells.Sprgr_34_L70 = 'weapons.shells.Sprgr_34_L70'
ENUMS.Storage.weapons.shells.QF94_AA_HE = 'weapons.shells.QF94_AA_HE'
ENUMS.Storage.weapons.shells.AH_6762x51mm_M62 = 'weapons.shells.AH-6 7.62x51mm M62'
ENUMS.Storage.weapons.shells.AH_6762x51mm_M80 = 'weapons.shells.AH-6 7.62x51mm M80'
ENUMS.Storage.weapons.shells.AH_6_762x51mm_M61 = 'weapons.shells.AH-6 7.62x51mm M61'
ENUMS.Storage.weapons.shells.leFH18_105HE = 'weapons.shells.leFH18_105HE'
ENUMS.Storage.weapons.shells.M63_37HE = 'weapons.shells.M63_37HE'
ENUMS.Storage.weapons.shells.QF95_206R_fixed = 'weapons.shells.QF95_206R_fixed'
ENUMS.Storage.weapons.shells.UBR_365_85AP = 'weapons.shells.UBR_365_85AP'
ENUMS.Storage.weapons.shells.M101 = 'weapons.shells.M101'
ENUMS.Storage.weapons.shells.HE_M1_Shell = 'weapons.shells.HE_M1_Shell'
ENUMS.Storage.weapons.shells.UO_365K_85HE = 'weapons.shells.UO_365K_85HE'
ENUMS.Storage.weapons.shells.Flak41_Sprgr_39 = 'weapons.shells.Flak41_Sprgr_39'
ENUMS.Storage.weapons.shells.M1_37mm_HE_T = 'weapons.shells.M1_37mm_HE-T'
ENUMS.Storage.weapons.shells.QF17_HE = 'weapons.shells.QF17_HE'
ENUMS.Storage.weapons.shells.Pzgr_39 = 'weapons.shells.Pzgr_39'
ENUMS.Storage.weapons.shells.Besa7_92x57 = 'weapons.shells.Besa7_92x57'
ENUMS.Storage.weapons.shells.I_Gr_33 = 'weapons.shells.I_Gr_33'
ENUMS.Storage.weapons.shells.M62_APC = 'weapons.shells.M62_APC'
ENUMS.Storage.weapons.shells.Mk_12_HE_shell = 'weapons.shells.Mk_12_HE_shell'
ENUMS.Storage.weapons.shells.M51_37AP = 'weapons.shells.M51_37AP'
ENUMS.Storage.weapons.shells.M42A1_HE = 'weapons.shells.M42A1_HE'
ENUMS.Storage.weapons.shells.HE_20x138B = 'weapons.shells.20x138B_HE'
ENUMS.Storage.weapons.shells.HE_37x263 = 'weapons.shells.37x263_HE'
ENUMS.Storage.weapons.shells.HE_2A20_115mm = 'weapons.shells.2A20_115mm_HE'
ENUMS.Storage.weapons.gunmounts.B17_TailTurret_M2_L = 'weapons.gunmounts.B17_TailTurret_M2_L'
ENUMS.Storage.weapons.gunmounts.AH6_M134L = 'weapons.gunmounts.{AH6_M134L}'
ENUMS.Storage.weapons.gunmounts.B17_Left_Nose_M2 = 'weapons.gunmounts.B17_Left_Nose_M2'
ENUMS.Storage.weapons.gunmounts.Ju88_Turret_Top_Right_MG_81 = 'weapons.gunmounts.Ju88_Turret_Top_Right_MG_81'
ENUMS.Storage.weapons.gunmounts.Ju88_Turret_Bottom_MG_81_L = 'weapons.gunmounts.Ju88_Turret_Bottom_MG_81_L'
ENUMS.Storage.weapons.gunmounts.B17_ChinTurret_M2_R = 'weapons.gunmounts.B17_ChinTurret_M2_R'
ENUMS.Storage.weapons.gunmounts.B17_Waist_Right_M2 = 'weapons.gunmounts.B17_Waist_Right_M2'
ENUMS.Storage.weapons.gunmounts.AH_6_Door_Gun = 'weapons.gunmounts.AH-6_Door_Gun'
ENUMS.Storage.weapons.gunmounts.B17_BallTurret_M2_L = 'weapons.gunmounts.B17_BallTurret_M2_L'
ENUMS.Storage.weapons.gunmounts.B17_BallTurret_M2_R = 'weapons.gunmounts.B17_BallTurret_M2_R'
ENUMS.Storage.weapons.gunmounts.B17_TopTurret_M2_R = 'weapons.gunmounts.B17_TopTurret_M2_R'
ENUMS.Storage.weapons.gunmounts.B17_Right_Nose_M2 = 'weapons.gunmounts.B17_Right_Nose_M2'
ENUMS.Storage.weapons.gunmounts.Ju88_Turret_Bottom_MG_81_R = 'weapons.gunmounts.Ju88_Turret_Bottom_MG_81_R'
ENUMS.Storage.weapons.gunmounts.B17_TopTurret_M2_L = 'weapons.gunmounts.B17_TopTurret_M2_L'
ENUMS.Storage.weapons.gunmounts.B17_Waist_Left_M2 = 'weapons.gunmounts.B17_Waist_Left_M2'
ENUMS.Storage.weapons.gunmounts.Ju88_Turret_ahead_MG_81 = 'weapons.gunmounts.Ju88_Turret_ahead_MG_81'
ENUMS.Storage.weapons.gunmounts.AH6_M134R = 'weapons.gunmounts.{AH6_M134R}'
ENUMS.Storage.weapons.gunmounts.Ju88_Turret_Top_Left_MG_81 = 'weapons.gunmounts.Ju88_Turret_Top_Left_MG_81'
ENUMS.Storage.weapons.gunmounts.B17_TailTurret_M2_R = 'weapons.gunmounts.B17_TailTurret_M2_R'
ENUMS.Storage.weapons.gunmounts.AKAN_NO_TRC = 'weapons.gunmounts.AKAN_NO_TRC'
ENUMS.Storage.weapons.gunmounts.AKAN = 'weapons.gunmounts.AKAN'
ENUMS.Storage.weapons.gunmounts.B17_ChinTurret_M2_L = 'weapons.gunmounts.B17_ChinTurret_M2_L'
ENUMS.Storage.weapons.gunmounts.AKAN = 'weapons.gunmounts.AKAN'
ENUMS.Storage.weapons.gunmounts.AKAN_NO_TRC = 'weapons.gunmounts.AKAN_NO_TRC'
ENUMS.Storage.weapons.gunmounts.AH_6_Door = 'weapons.gunmounts.{AH-6_Door}'
ENUMS.Storage.weapons.gunmounts.AH_6_FN_HMP400 = 'weapons.gunmounts.{AH-6_FN_HMP400}'
ENUMS.Storage.weapons.gunmounts.AH_6_M134L = 'weapons.gunmounts.AH-6_M134L'
ENUMS.Storage.weapons.gunmounts.AH_6_M134R = 'weapons.gunmounts.AH-6_M134R'
ENUMS.Storage.weapons.gunmounts.AH_6_HMP400 = 'weapons.gunmounts.AH-6_HMP400'
ENUMS.Storage.weapons.droptanks.PTB_800 = 'weapons.droptanks.PTB-800'
ENUMS.Storage.weapons.droptanks.PTB_275 = 'weapons.droptanks.PTB-275'
ENUMS.Storage.weapons.droptanks.HB_A6E_AERO1D_EMPTY = 'weapons.droptanks.HB_A6E_AERO1D_EMPTY'
ENUMS.Storage.weapons.droptanks.Drop_tank_75gal = 'weapons.droptanks.Drop tank 75gal'
ENUMS.Storage.weapons.droptanks.S_3_PTB = 'weapons.droptanks.S-3-PTB'
ENUMS.Storage.weapons.droptanks.PTB_3000 = 'weapons.droptanks.PTB-3000'
ENUMS.Storage.weapons.droptanks.HB_A6E_D704 = 'weapons.droptanks.HB_A6E_D704'
ENUMS.Storage.weapons.droptanks.PTB_1150_29 = 'weapons.droptanks.PTB-1150-29'
ENUMS.Storage.weapons.droptanks.f_18c_ptb = 'weapons.droptanks.f-18c-ptb'
ENUMS.Storage.weapons.droptanks.F4_BAK_L = 'weapons.droptanks.F4-BAK-L'
ENUMS.Storage.weapons.droptanks.HB_A6E_AERO1D = 'weapons.droptanks.HB_A6E_AERO1D'
ENUMS.Storage.weapons.droptanks.IAFS_ComboPak_100 = 'weapons.droptanks.{IAFS_ComboPak_100}'
ENUMS.Storage.weapons.droptanks.PTB_2000 = 'weapons.droptanks.PTB-2000'
ENUMS.Storage.weapons.droptanks.M2000_PTB = 'weapons.droptanks.M2000-PTB'
ENUMS.Storage.weapons.droptanks.PTB_150 = 'weapons.droptanks.PTB-150'
ENUMS.Storage.weapons.droptanks.PTB_1150 = 'weapons.droptanks.PTB-1150'
ENUMS.Storage.weapons.droptanks.fuel_tank_300gal = 'weapons.droptanks.fuel_tank_300gal'
ENUMS.Storage.weapons.droptanks.MIG_25_PTB = 'weapons.droptanks.MIG-25-PTB'
ENUMS.Storage.weapons.droptanks.PTB_1500 = 'weapons.droptanks.PTB-1500'
ENUMS.Storage.weapons.droptanks.MIG_23_PTB = 'weapons.droptanks.MIG-23-PTB'
ENUMS.Storage.weapons.droptanks.FT600 = 'weapons.droptanks.FT600'
ENUMS.Storage.weapons.droptanks.F15_PTB = 'weapons.droptanks.F15-PTB'
ENUMS.Storage.weapons.droptanks.ah6_auxtank = 'weapons.droptanks.ah6_auxtank'
ENUMS.Storage.weapons.droptanks.T_PTB = 'weapons.droptanks.T-PTB'
ENUMS.Storage.weapons.droptanks.fuel_tank_370gal = 'weapons.droptanks.fuel_tank_370gal'
ENUMS.Storage.weapons.droptanks.F4_BAK_C = 'weapons.droptanks.F4-BAK-C'
ENUMS.Storage.weapons.droptanks.F16_PTB_N2 = 'weapons.droptanks.F-16-PTB-N2'
ENUMS.Storage.weapons.droptanks.PTB_800 = 'weapons.droptanks.PTB-800'
ENUMS.Storage.weapons.droptanks.PTB_275 = 'weapons.droptanks.PTB-275'
ENUMS.Storage.weapons.droptanks.T_PTB = 'weapons.droptanks.T-PTB'
ENUMS.Storage.weapons.droptanks.F16_PTB_N2 = 'weapons.droptanks.F-16-PTB-N2'
ENUMS.Storage.weapons.droptanks.F4_BAK_C = 'weapons.droptanks.F4-BAK-C'
ENUMS.Storage.weapons.droptanks.PTB_1150_29 = 'weapons.droptanks.PTB-1150-29'
ENUMS.Storage.weapons.droptanks.PTB_1150 = 'weapons.droptanks.PTB-1150'
ENUMS.Storage.weapons.droptanks.fuel_tank_300gal = 'weapons.droptanks.fuel_tank_300gal'
ENUMS.Storage.weapons.droptanks.MIG_25_PTB = 'weapons.droptanks.MIG-25-PTB'
ENUMS.Storage.weapons.droptanks.PTB_1500 = 'weapons.droptanks.PTB-1500'
ENUMS.Storage.weapons.droptanks.FT600 = 'weapons.droptanks.FT600'
ENUMS.Storage.weapons.droptanks.Drop_tank_75gal = 'weapons.droptanks.Drop tank 75gal'
ENUMS.Storage.weapons.droptanks.F15_PTB = 'weapons.droptanks.F15-PTB'
ENUMS.Storage.weapons.droptanks.M2000_PTB = 'weapons.droptanks.M2000-PTB'
ENUMS.Storage.weapons.droptanks.PTB_150 = 'weapons.droptanks.PTB-150'
ENUMS.Storage.weapons.droptanks.F4_BAK_L = 'weapons.droptanks.F4-BAK-L'
ENUMS.Storage.weapons.droptanks.PTB_3000 = 'weapons.droptanks.PTB-3000'
ENUMS.Storage.weapons.droptanks.PTB_2000 = 'weapons.droptanks.PTB-2000'
ENUMS.Storage.weapons.droptanks.S_3_PTB = 'weapons.droptanks.S-3-PTB'
ENUMS.Storage.weapons.droptanks.fuel_tank_370gal = 'weapons.droptanks.fuel_tank_370gal'
ENUMS.Storage.weapons.droptanks.MIG_23_PTB = 'weapons.droptanks.MIG-23-PTB'
ENUMS.Storage.weapons.droptanks.f_18c_ptb = 'weapons.droptanks.f-18c-ptb'
ENUMS.Storage.weapons.containers.FN_HMP400_100 = 'weapons.containers.{FN_HMP400_100}'
ENUMS.Storage.weapons.containers.AN_M3 = 'weapons.containers.{AN-M3}'
ENUMS.Storage.weapons.containers.OH58D_M3P_L500 = 'weapons.containers.OH58D_M3P_L500'
ENUMS.Storage.weapons.containers.GIAT_M621_HE = 'weapons.containers.{GIAT_M621_HE}'
ENUMS.Storage.weapons.containers.KORD_12_7_MI24_L = 'weapons.containers.KORD_12_7_MI24_L'
ENUMS.Storage.weapons.containers.CH47_STBD_M240H = 'weapons.containers.{CH47_STBD_M240H}'
ENUMS.Storage.weapons.containers.CH47_AFT_M60D = 'weapons.containers.{CH47_AFT_M60D}'
ENUMS.Storage.weapons.containers.UPK_23_250_MiG_21 = 'weapons.containers.{UPK-23-250 MiG-21}'
ENUMS.Storage.weapons.containers.CH47_STBD_M134D = 'weapons.containers.{CH47_STBD_M134D}'
ENUMS.Storage.weapons.containers.GAU_12_Equalizer = 'weapons.containers.{GAU_12_Equalizer}'
ENUMS.Storage.weapons.containers.PKT_7_62 = 'weapons.containers.PKT_7_62'
ENUMS.Storage.weapons.containers.CH47_AFT_M240H = 'weapons.containers.{CH47_AFT_M240H}'
ENUMS.Storage.weapons.containers.GIAT_M621_SAPHEI = 'weapons.containers.{GIAT_M621_SAPHEI}'
ENUMS.Storage.weapons.containers.ADEN_GUNPOD = 'weapons.containers.{ADEN_GUNPOD}'
ENUMS.Storage.weapons.containers.GAU_12_Equalizer_HE = 'weapons.containers.{GAU_12_Equalizer_HE}'
ENUMS.Storage.weapons.containers.M60_SIDE_L = 'weapons.containers.M60_SIDE_L'
ENUMS.Storage.weapons.containers.KORD_12_7_MI24_R = 'weapons.containers.KORD_12_7_MI24_R'
ENUMS.Storage.weapons.containers.GIAT_M621_APHE = 'weapons.containers.{GIAT_M621_APHE}'
ENUMS.Storage.weapons.containers.MB339_ANM3_L = 'weapons.containers.{MB339_ANM3_L}'
ENUMS.Storage.weapons.containers.FN_HMP400 = 'weapons.containers.{FN_HMP400}'
ENUMS.Storage.weapons.containers.AH_6_Door = 'weapons.containers.{AH-6_Door}'
ENUMS.Storage.weapons.containers.MB339_DEFA553_L = 'weapons.containers.{MB339_DEFA553_L}'
ENUMS.Storage.weapons.containers.MB339_ANM3_R = 'weapons.containers.{MB339_ANM3_R}'
ENUMS.Storage.weapons.containers.PK_3 = 'weapons.containers.{PK-3}'
ENUMS.Storage.weapons.containers.GUV_VOG = 'weapons.containers.GUV_VOG'
ENUMS.Storage.weapons.containers.SA342_M134_SIDE_R = 'weapons.containers.{SA342_M134_SIDE_R}'
ENUMS.Storage.weapons.containers.OH58D_M3P_L100 = 'weapons.containers.OH58D_M3P_L100'
ENUMS.Storage.weapons.containers.MXU_648 = 'weapons.containers.MXU-648'
ENUMS.Storage.weapons.containers.OH58D_M3P_L400 = 'weapons.containers.OH58D_M3P_L400'
ENUMS.Storage.weapons.containers.FN_HMP400_200 = 'weapons.containers.{FN_HMP400_200}'
ENUMS.Storage.weapons.containers.GIAT_M621_HE = 'weapons.containers.{GIAT_M621_HE}'
ENUMS.Storage.weapons.containers.M134_L = 'weapons.containers.M134_L'
ENUMS.Storage.weapons.containers.OH58D_M3P_L200 = 'weapons.containers.OH58D_M3P_L200'
ENUMS.Storage.weapons.containers.GIAT_M621_AP = 'weapons.containers.{GIAT_M621_AP}'
ENUMS.Storage.weapons.containers.CH47_STBD_M134D = 'weapons.containers.{CH47_STBD_M134D}'
ENUMS.Storage.weapons.containers.PKT_7_62 = 'weapons.containers.PKT_7_62'
ENUMS.Storage.weapons.containers.OH58D_M3P_L300 = 'weapons.containers.OH58D_M3P_L300'
ENUMS.Storage.weapons.containers.GIAT_M621_SAPHEI = 'weapons.containers.{GIAT_M621_SAPHEI}'
ENUMS.Storage.weapons.containers.M60_SIDE_L = 'weapons.containers.M60_SIDE_L'
ENUMS.Storage.weapons.containers.CH47_PORT_M134D = 'weapons.containers.{CH47_PORT_M134D}'
ENUMS.Storage.weapons.containers.CH47_PORT_M60D = 'weapons.containers.{CH47_PORT_M60D}'
ENUMS.Storage.weapons.containers.ADEN_GUNPOD = 'weapons.containers.{ADEN_GUNPOD}'
ENUMS.Storage.weapons.containers.C_101_DEFA553 = 'weapons.containers.{C-101-DEFA553}'
ENUMS.Storage.weapons.containers.MB339_ANM3_R = 'weapons.containers.{MB339_ANM3_R}'
ENUMS.Storage.weapons.containers.CH47_AFT_M60D = 'weapons.containers.{CH47_AFT_M60D}'
ENUMS.Storage.weapons.containers.KORD_12_7 = 'weapons.containers.KORD_12_7'
ENUMS.Storage.weapons.containers.GIAT_M621_HEAP = 'weapons.containers.{GIAT_M621_HEAP}'
ENUMS.Storage.weapons.containers.CH47_AFT_M3M = 'weapons.containers.{CH47_AFT_M3M}'
ENUMS.Storage.weapons.containers.GUV_YakB_GSHP = 'weapons.containers.GUV_YakB_GSHP'
ENUMS.Storage.weapons.containers.R_73U = 'weapons.containers.R-73U'
ENUMS.Storage.weapons.containers.GUV_VOG = 'weapons.containers.GUV_VOG'
ENUMS.Storage.weapons.containers.KORD_12_7_MI24_L = 'weapons.containers.KORD_12_7_MI24_L'
ENUMS.Storage.weapons.containers.OH58D_M3P_L100 = 'weapons.containers.OH58D_M3P_L100'
ENUMS.Storage.weapons.containers.OH58D_M3P_L400 = 'weapons.containers.OH58D_M3P_L400'
ENUMS.Storage.weapons.containers.CH47_STBD_M240H = 'weapons.containers.{CH47_STBD_M240H}'
ENUMS.Storage.weapons.containers.CH47_PORT_M240H = 'weapons.containers.{CH47_PORT_M240H}'
ENUMS.Storage.weapons.containers.CC420_GUN_POD = 'weapons.containers.{CC420_GUN_POD}'
ENUMS.Storage.weapons.containers.FN_HMP400_100 = 'weapons.containers.{FN_HMP400_100}'
ENUMS.Storage.weapons.containers.MB339_ANM3_L = 'weapons.containers.{MB339_ANM3_L}'
ENUMS.Storage.weapons.containers.MB339_DEFA553_R = 'weapons.containers.{MB339_DEFA553_R}'
ENUMS.Storage.weapons.containers.GAU_12_Equalizer_HE = 'weapons.containers.{GAU_12_Equalizer_HE}'
ENUMS.Storage.weapons.containers.OH58D_M3P_L500 = 'weapons.containers.OH58D_M3P_L500'
ENUMS.Storage.weapons.containers.SUU_23_POD = 'weapons.containers.{SUU_23_POD}'
ENUMS.Storage.weapons.containers.PK_3 = 'weapons.containers.{PK-3}'
ENUMS.Storage.weapons.containers.AKAN = 'weapons.containers.{AKAN}'
ENUMS.Storage.weapons.containers.CH47_STBD_M60D = 'weapons.containers.{CH47_STBD_M60D}'
ENUMS.Storage.weapons.containers.SA342_M134_SIDE_R = 'weapons.containers.{SA342_M134_SIDE_R}'
ENUMS.Storage.weapons.containers.M60_SIDE_R = 'weapons.containers.M60_SIDE_R'
ENUMS.Storage.weapons.containers.GAU_12_Equalizer_AP = 'weapons.containers.{GAU_12_Equalizer_AP}'
ENUMS.Storage.weapons.containers.GAU_12_Equalizer = 'weapons.containers.{GAU_12_Equalizer}'
ENUMS.Storage.weapons.containers.KORD_12_7_MI24_R = 'weapons.containers.KORD_12_7_MI24_R'
ENUMS.Storage.weapons.containers.M134_SIDE_R = 'weapons.containers.M134_SIDE_R'
ENUMS.Storage.weapons.containers.AKAN_NO_TRC = 'weapons.containers.{AKAN_NO_TRC}'
ENUMS.Storage.weapons.containers.oh_58_brauning = 'weapons.containers.oh-58-brauning'
ENUMS.Storage.weapons.containers.MXU_648 = 'weapons.containers.MXU-648'
ENUMS.Storage.weapons.containers.M134_R = 'weapons.containers.M134_R'
ENUMS.Storage.weapons.containers.AN_M3 = 'weapons.containers.{AN-M3}'
ENUMS.Storage.weapons.containers.GIAT_M621_APHE = 'weapons.containers.{GIAT_M621_APHE}'
ENUMS.Storage.weapons.containers.AIM_9S = 'weapons.containers.AIM-9S'
ENUMS.Storage.weapons.containers.CH47_AFT_M240H = 'weapons.containers.{CH47_AFT_M240H}'
ENUMS.Storage.weapons.containers.FN_HMP400 = 'weapons.containers.{FN_HMP400}'
ENUMS.Storage.weapons.containers.M134_SIDE_L = 'weapons.containers.M134_SIDE_L'
ENUMS.Storage.weapons.containers.MB339_DEFA553_L = 'weapons.containers.{MB339_DEFA553_L}'
ENUMS.Storage.weapons.containers.MISC_1 = 'weapons.containers.{05544F1A-C39C-466b-BC37-5BD1D52E57BB}'
ENUMS.Storage.weapons.containers.MISC_2 = 'weapons.containers.{E92CBFE5-C153-11d8-9897-000476191836}'
ENUMS.Storage.weapons.containers.hvar_SmokeGenerator = 'weapons.containers.hvar_SmokeGenerator'
ENUMS.Storage.weapons.containers.INV_SMOKE_RED = 'weapons.containers.{INV-SMOKE-RED}'
ENUMS.Storage.weapons.containers.INV_SMOKE_YELLOW = 'weapons.containers.{INV-SMOKE-YELLOW}'
ENUMS.Storage.weapons.containers.INV_SMOKE_BLUE = 'weapons.containers.{INV-SMOKE-BLUE}'
ENUMS.Storage.weapons.containers.INV_SMOKE_GREEN = 'weapons.containers.{INV-SMOKE-GREEN}'
ENUMS.Storage.weapons.containers.INV_SMOKE_WHITE = 'weapons.containers.{INV-SMOKE-WHITE}'
ENUMS.Storage.weapons.containers.INV_SMOKE_ORANGE = 'weapons.containers.{INV-SMOKE-ORANGE}'
ENUMS.Storage.weapons.containers.GAU_12_Equalizer_AP = 'weapons.containers.{GAU_12_Equalizer_AP}'
ENUMS.Storage.weapons.containers.AH_6_Gunners = 'weapons.containers.{AH-6_Gunners}'
ENUMS.Storage.weapons.containers.AH_6_FN_HMP400 = 'weapons.containers.{AH-6_FN_HMP400}'
ENUMS.Storage.weapons.containers.R_73U = 'weapons.containers.R-73U'
ENUMS.Storage.weapons.containers.M60_SIDE_R = 'weapons.containers.M60_SIDE_R'
ENUMS.Storage.weapons.containers.CH47_AFT_M3M = 'weapons.containers.{CH47_AFT_M3M}'
ENUMS.Storage.weapons.containers.GUV_YakB_GSHP = 'weapons.containers.GUV_YakB_GSHP'
ENUMS.Storage.weapons.containers.RKL609_L = 'weapons.containers.{RKL609_L}'
ENUMS.Storage.weapons.containers.CH47_PORT_M134D = 'weapons.containers.{CH47_PORT_M134D}'
ENUMS.Storage.weapons.containers.CH47_PORT_M60D = 'weapons.containers.{CH47_PORT_M60D}'
ENUMS.Storage.weapons.containers.RKL609_R = 'weapons.containers.{RKL609_R}'
ENUMS.Storage.weapons.containers.C_101_DEFA553 = 'weapons.containers.{C-101-DEFA553}'
ENUMS.Storage.weapons.containers.AH6_M134L = 'weapons.containers.{AH6_M134L}'
ENUMS.Storage.weapons.containers.KORD_12_7 = 'weapons.containers.KORD_12_7'
ENUMS.Storage.weapons.containers.C130_M18_Sidearm = 'weapons.containers.{C130-M18-Sidearm}'
ENUMS.Storage.weapons.containers.GIAT_M621_HEAP = 'weapons.containers.{GIAT_M621_HEAP}'
ENUMS.Storage.weapons.containers.BRU_42_LS = 'weapons.containers.BRU-42_LS'
ENUMS.Storage.weapons.containers.CH47_STBD_M60D = 'weapons.containers.{CH47_STBD_M60D}'
ENUMS.Storage.weapons.containers.SUU_23_POD = 'weapons.containers.{SUU_23_POD}'
ENUMS.Storage.weapons.containers.M134_SIDE_R = 'weapons.containers.M134_SIDE_R'
ENUMS.Storage.weapons.containers.AKAN_NO_TRC = 'weapons.containers.{AKAN_NO_TRC}'
ENUMS.Storage.weapons.containers.oh_58_brauning = 'weapons.containers.oh-58-brauning'
ENUMS.Storage.weapons.containers.AH_6_DOORS = 'weapons.containers.{AH-6_DOORS}'
ENUMS.Storage.weapons.containers.CC420_GUN_POD = 'weapons.containers.{CC420_GUN_POD}'
ENUMS.Storage.weapons.containers.CH47_PORT_M240H = 'weapons.containers.{CH47_PORT_M240H}'
ENUMS.Storage.weapons.containers.MB339_DEFA553_R = 'weapons.containers.{MB339_DEFA553_R}'
ENUMS.Storage.weapons.containers.AIM_9S = 'weapons.containers.AIM-9S'
ENUMS.Storage.weapons.containers.hvar_SmokeGenerator = 'weapons.containers.hvar_SmokeGenerator'
ENUMS.Storage.weapons.containers.M134_L = 'weapons.containers.M134_L'
ENUMS.Storage.weapons.containers.AKAN = 'weapons.containers.{AKAN}'
ENUMS.Storage.weapons.containers.C130_Cargo_Bay_M4 = 'weapons.containers.{C130-Cargo-Bay-M4}'
ENUMS.Storage.weapons.containers.M134_SIDE_L = 'weapons.containers.M134_SIDE_L'
ENUMS.Storage.weapons.containers.FN_HMP400_200 = 'weapons.containers.{FN_HMP400_200}'
ENUMS.Storage.weapons.containers.OH58D_M3P_L200 = 'weapons.containers.OH58D_M3P_L200'
ENUMS.Storage.weapons.containers.GIAT_M621_AP = 'weapons.containers.{GIAT_M621_AP}'
ENUMS.Storage.weapons.containers.M134_R = 'weapons.containers.M134_R'
ENUMS.Storage.weapons.containers.OH58D_M3P_L300 = 'weapons.containers.OH58D_M3P_L300'
ENUMS.Storage.weapons.containers.AH6_M134R = 'weapons.containers.{AH6_M134R}'
ENUMS.Storage.weapons.torpedoes.G7A_T1 = 'weapons.torpedoes.G7A_T1'
-- UH-60L Mod -- UH-60L Mod
ENUMS.Storage.weapons.gunmounts.UH60LGAU19 = 'weapons.gunmounts.UH-60L GAU-19' ENUMS.Storage.weapons.gunmounts.UH60LGAU19 = 'weapons.gunmounts.UH-60L GAU-19'
@@ -2081,15 +1814,6 @@ ENUMS.Storage.weapons.gunmounts.UH60L_M60_GUNNER = 'weapons.gunmounts.{UH60L_M60
ENUMS.Storage.weapons.gunmounts.UH60L_M2_GUNNER = 'weapons.gunmounts.{UH60L_M2_GUNNER}' ENUMS.Storage.weapons.gunmounts.UH60L_M2_GUNNER = 'weapons.gunmounts.{UH60L_M2_GUNNER}'
ENUMS.Storage.weapons.gunmounts.UH60_M230_LEFT = 'weapons.gunmounts.{UH60_M230_LEFT}' ENUMS.Storage.weapons.gunmounts.UH60_M230_LEFT = 'weapons.gunmounts.{UH60_M230_LEFT}'
ENUMS.Storage.weapons.gunmounts.UH60_M230_RIGHT = 'weapons.gunmounts.{UH60_M230_RIGHT}' ENUMS.Storage.weapons.gunmounts.UH60_M230_RIGHT = 'weapons.gunmounts.{UH60_M230_RIGHT}'
ENUMS.Storage.weapons.containers.UH60_M134_RIGHT = 'weapons.containers.{UH60_M134_RIGHT}'
ENUMS.Storage.weapons.containers.UH60_M134_LEFT = 'weapons.containers.{UH60_M134_LEFT}'
ENUMS.Storage.weapons.containers.UH60_M230_LEFT = 'weapons.containers.{UH60_M230_LEFT}'
ENUMS.Storage.weapons.containers.UH60L_M134_GUNNER = 'weapons.containers.{UH60L_M134_GUNNER}'
ENUMS.Storage.weapons.containers.UH60_GAU19_LEFT = 'weapons.containers.{UH60_GAU19_LEFT}'
ENUMS.Storage.weapons.containers.UH60L_M60_GUNNER = 'weapons.containers.{UH60L_M60_GUNNER}'
ENUMS.Storage.weapons.containers.UH60_GAU19_RIGHT = 'weapons.containers.{UH60_GAU19_RIGHT}'
ENUMS.Storage.weapons.containers.UH60_M230_RIGHT = 'weapons.containers.{UH60_M230_RIGHT}'
ENUMS.Storage.weapons.containers.UH60L_M2_GUNNER = 'weapons.containers.{UH60L_M2_GUNNER}'
--- ---
-- @type ENUMS.FARPType -- @type ENUMS.FARPType
+4 -153
View File
@@ -1507,14 +1507,6 @@ function UTILS.VecSubstract(a, b)
return {x=a.x-b.x, y=a.y-b.y, z=a.z-b.z} return {x=a.x-b.x, y=a.y-b.y, z=a.z-b.z}
end end
--- Scale a 3D vectors by multiplication with s.
-- @param DCS#Vec3 v A Vector in 3D with x, y, z components.
-- @param #number s Scale
-- @return DCS#Vec3 Vec3
function UTILS.VecScale(v, s)
return {x = v.x * s, y = v.y * s, z = v.z * s}
end
--- Substract is not a word, don't want to rename the original function because it's been around since forever --- Substract is not a word, don't want to rename the original function because it's been around since forever
function UTILS.VecSubtract(a, b) function UTILS.VecSubtract(a, b)
return UTILS.VecSubstract(a, b) return UTILS.VecSubstract(a, b)
@@ -1528,14 +1520,6 @@ function UTILS.Vec2Substract(a, b)
return {x=a.x-b.x, y=a.y-b.y} return {x=a.x-b.x, y=a.y-b.y}
end end
--- Calculate the difference between two 3D vectors by substracting the x,y,z components from each other.
-- @param DCS#Vec3 a Vector in 3D with x, y, z components.
-- @param DCS#Vec3 b Vector in 3D with x, y, z components.
-- @return DCS#Vec3 Vector in 3D.
function UTILS.Vec3Substract(a, b)
return {x = a.x - b.x, y = a.y - b.y, z = a.z - b.z}
end
--- Substract is not a word, don't want to rename the original function because it's been around since forever --- Substract is not a word, don't want to rename the original function because it's been around since forever
function UTILS.Vec2Subtract(a, b) function UTILS.Vec2Subtract(a, b)
return UTILS.Vec2Substract(a, b) return UTILS.Vec2Substract(a, b)
@@ -1665,13 +1649,6 @@ function UTILS.Vec2Translate(a, distance, angle)
return {x=TX, y=TY} return {x=TX, y=TY}
end end
--- Calculate the lenght of a 3D vector
-- @param DCS#Vec3 v A Vector in 3D with x, y, z components.
-- @return #number length
function UTILS.Vec3Length(v)
return math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z)
end
--- Rotate 3D vector in the 2D (x,z) plane. y-component (usually altitude) unchanged. --- Rotate 3D vector in the 2D (x,z) plane. y-component (usually altitude) unchanged.
-- @param DCS#Vec3 a Vector in 3D with x, y, z components. -- @param DCS#Vec3 a Vector in 3D with x, y, z components.
-- @param #number angle Rotation angle in degrees. -- @param #number angle Rotation angle in degrees.
@@ -2923,27 +2900,16 @@ end
-- @param #boolean Cinematic (Optional, needs Structured = true) If true, place a fire/smoke effect on the dead static position. -- @param #boolean Cinematic (Optional, needs Structured = true) If true, place a fire/smoke effect on the dead static position.
-- @param #number Effect (Optional for Cinematic) What effect to use. Defaults to a random effect. Smoke presets are: 1=small smoke and fire, 2=medium smoke and fire, 3=large smoke and fire, 4=huge smoke and fire, 5=small smoke, 6=medium smoke, 7=large smoke, 8=huge smoke. -- @param #number Effect (Optional for Cinematic) What effect to use. Defaults to a random effect. Smoke presets are: 1=small smoke and fire, 2=medium smoke and fire, 3=large smoke and fire, 4=huge smoke and fire, 5=small smoke, 6=medium smoke, 7=large smoke, 8=huge smoke.
-- @param #number Density (Optional for Cinematic) What smoke density to use, can be 0 to 1. Defaults to 0.5. -- @param #number Density (Optional for Cinematic) What smoke density to use, can be 0 to 1. Defaults to 0.5.
-- @param #boolean Resurrection If true, dead units can be restored on load. Defaults to false.
-- @param #number ResurrectPercentage Use this percentage of probability to resurrect a unit. [0..100], defaults to 25.
-- @param #number Healmin If set, life points of a resurrected unit will be randomly restored to min this percentage. [0..100], defaults to 25.
-- @param #number Healmax If set, life points of a resurrected unit will be randomly restored to max this percentage. [0..100], defaults to 75.
-- @return #table Table of data objects (tables) containing groupname, coordinate and group object. Returns nil when file cannot be read. -- @return #table Table of data objects (tables) containing groupname, coordinate and group object. Returns nil when file cannot be read.
-- @return #table When using Cinematic: table of names of smoke and fire objects, so they can be extinguished with `COORDINATE.StopBigSmokeAndFire( name )` -- @return #table When using Cinematic: table of names of smoke and fire objects, so they can be extinguished with `COORDINATE.StopBigSmokeAndFire( name )`
function UTILS.LoadStationaryListOfGroups(Path,Filename,Reduce,Structured,Cinematic,Effect,Density,Resurrection,ResurrectPercentage,Healmin,Healmax) function UTILS.LoadStationaryListOfGroups(Path,Filename,Reduce,Structured,Cinematic,Effect,Density)
local healmin = Healmin or 25
local healmax = Healmax or 75
local resurrection = (Resurrection == true) and true or false
local resurrectpercentage = ResurrectPercentage or 25
local fires = {} local fires = {}
---
-- @param Core.Point#COORDINATE coord
local function Smokers(name,coord,effect,density) local function Smokers(name,coord,effect,density)
local eff = math.random(8) local eff = math.random(8)
if type(effect) == "number" then eff = effect end if type(effect) == "number" then eff = effect end
coord:BigSmokeAndFire( eff, Density, 300, 1, name ) coord:BigSmokeAndFire(eff,density,name)
table.insert(fires,name) table.insert(fires,name)
end end
@@ -2958,16 +2924,7 @@ function UTILS.LoadStationaryListOfGroups(Path,Filename,Reduce,Structured,Cinema
local name = _unit:GetName() local name = _unit:GetName()
Smokers(name,coordinate,Effect,Density) Smokers(name,coordinate,Effect,Density)
end end
-- TODO Resurrection logic _unit:Destroy(false)
local resurectok = math.random(1,100)
BASE:E(string.format("Load Group | Resurrection | Resurrect %s | Thresh %d | Random %d",tostring(resurrection),resurrectpercentage,resurectok))
if resurrection == true and (resurectok < resurrectpercentage) then
local heallife = math.random(healmin,healmax)
BASE:E("Load Group | Resurrection | Life "..heallife)
_unit:SetLife(heallife)
else
_unit:Destroy(false)
end
reduced = reduced + 1 reduced = reduced + 1
if reduced == anzahl then break end if reduced == anzahl then break end
end end
@@ -4618,18 +4575,6 @@ function UTILS.Vec2toVec3(vec,y)
end end
end end
-- Converts a Vec3 to a Vec2
-- @param vec3 the Vec3 to convert
-- @return Vec2 The Vec2 output
function UTILS.Vec3toVec2(Vec3)
if Vec3 and type(Vec3)=="table" then
local Vec2 = {}
Vec2.x = Vec3.x or 0
Vec2.y = Vec3.z or 0
return Vec2
end
end
--- Get the correction needed for true north in radians --- Get the correction needed for true north in radians
-- @param gPoint The map point vec2 or vec3 -- @param gPoint The map point vec2 or vec3
-- @return number correction -- @return number correction
@@ -5511,97 +5456,3 @@ function UTILS.GetMinimumBoundingCircle(points)
return welzlHelper(pts, #pts, {}) return welzlHelper(pts, #pts, {})
end end
--- Calculated optimal intercepting course (Bearing)
-- @param DCS#Vec3 A1 Position of flight one
-- @param DCS#Vec3 V1 VelocityVector of flight one
-- @param DCS#Vec3 A2 Position of flight two
-- @param #number V2_speed Speed of A2 in m/s
-- @return #number Bearing Bearing course for A2 to take for an intercept of A1 or nil if aspect is hot/cold.
function UTILS.CalculateInterceptBearing(A1, V1, A2, V2_speed)
local function berechne_bearing(richtung)
local bearing = math.deg(math.atan2(richtung.x, richtung.y))
if bearing < 0 then
bearing = bearing + 360
end
return bearing
end
local function vec_normalize(v)
local len = UTILS.Vec3Length(v)
if len == 0 then return {x = 0, y = 0, z = 0} end
return {x = v.x / len, y = v.y / len, z = v.z / len}
end
-- Relative Position von F1 zu F2
local rel_pos = UTILS.Vec3Substract(A1, A2)
local distance = UTILS.Vec3Length(rel_pos)
if distance == 0 then
return nil -- Bereits am gleichen Ort
end
-- Richtungsvektor von F2 zu F1 (normalisiert)
local richtung_zu_f1 = vec_normalize(rel_pos)
-- Prüfe HOT: F1 fliegt direkt auf F2 zu
-- Das ist der Fall wenn V1 in die entgegengesetzte Richtung von rel_pos zeigt
local v1_normalisiert = vec_normalize(V1)
local annaeherung = UTILS.VecDot(v1_normalisiert, richtung_zu_f1)
if annaeherung < -0.95 then -- F1 fliegt fast direkt auf F2 zu (Winkel > ~162°)
return nil -- Hot
end
-- Prüfe COLD: F1 fliegt parallel weg von F2
-- Berechne die Geschwindigkeitsdifferenz
local rel_velocity = UTILS.VecSubstract(V1, {x=0, y=0, z=0}) -- V1 relativ zu F2 (falls F2 stillsteht)
local flucht_komponente = UTILS.VecDot(vec_normalize(rel_velocity), richtung_zu_f1)
if flucht_komponente > 0.95 then -- F1 fliegt fast parallel weg (Winkel < ~18°)
return nil -- Cold
end
-- Geschwindigkeiten
local v1 = UTILS.Vec3Length(V1)
local v2 = V2_speed
-- Löse quadratische Gleichung für Abfangzeit t
local a = UTILS.VecDot(V1, V1) - v2 * v2
local b = 2 * UTILS.VecDot(rel_pos, V1)
local c = UTILS.VecDot(rel_pos, rel_pos)
local discriminant = b * b - 4 * a * c
if discriminant < 0 then
return nil -- Keine Lösung möglich
end
-- Wähle die positive, kleinste Lösung
local t1 = (-b + math.sqrt(discriminant)) / (2 * a)
local t2 = (-b - math.sqrt(discriminant)) / (2 * a)
local t = nil
if t1 > 0 and t2 > 0 then
t = math.min(t1, t2)
elseif t1 > 0 then
t = t1
elseif t2 > 0 then
t = t2
else
return nil -- Keine positive Lösung
end
-- Berechne Treffpunkt
local treffpunkt = UTILS.VecAdd(A1, UTILS.VecScale(V1, t))
-- Berechne Richtung zum Treffpunkt
local richtung = UTILS.VecSubstract(treffpunkt, A2)
-- Berechne Bearing
local bearing = berechne_bearing(richtung)
return UTILS.Round(bearing,0)
end
+66 -126
View File
@@ -718,62 +718,62 @@ AIRBASE.SouthAtlantic = {
--- Airbases of the Sinai map --- Airbases of the Sinai map
-- --
-- * `AIRBASE.Sinai.Abu_Rudeis` Abu Rudeis -- * `AIRBASE.SinaiMap.Abu_Rudeis` Abu Rudeis
-- * `AIRBASE.Sinai.Abu_Suwayr` Abu Suwayr -- * `AIRBASE.SinaiMap.Abu_Suwayr` Abu Suwayr
-- * `AIRBASE.Sinai.Al_Bahr_al_Ahmar` Al Bahr al Ahmar -- * `AIRBASE.SinaiMap.Al_Bahr_al_Ahmar` Al Bahr al Ahmar
-- * `AIRBASE.Sinai.Al_Ismailiyah` Al Ismailiyah -- * `AIRBASE.SinaiMap.Al_Ismailiyah` Al Ismailiyah
-- * `AIRBASE.Sinai.Al_Khatatbah` Al Khatatbah -- * `AIRBASE.SinaiMap.Al_Khatatbah` Al Khatatbah
-- * `AIRBASE.Sinai.Al_Mansurah` Al Mansurah -- * `AIRBASE.SinaiMap.Al_Mansurah` Al Mansurah
-- * `AIRBASE.Sinai.Al_Rahmaniyah_Air_Base` Al Rahmaniyah Air Base -- * `AIRBASE.SinaiMap.Al_Rahmaniyah_Air_Base` Al Rahmaniyah Air Base
-- * `AIRBASE.Sinai.As_Salihiyah` As Salihiyah -- * `AIRBASE.SinaiMap.As_Salihiyah` As Salihiyah
-- * `AIRBASE.Sinai.AzZaqaziq` AzZaqaziq -- * `AIRBASE.SinaiMap.AzZaqaziq` AzZaqaziq
-- * `AIRBASE.Sinai.Baluza` Baluza -- * `AIRBASE.SinaiMap.Baluza` Baluza
-- * `AIRBASE.Sinai.Ben_Gurion` Ben-Gurion -- * `AIRBASE.SinaiMap.Ben_Gurion` Ben-Gurion
-- * `AIRBASE.Sinai.Beni_Suef` Beni Suef -- * `AIRBASE.SinaiMap.Beni_Suef` Beni Suef
-- * `AIRBASE.Sinai.Bilbeis_Air_Base` Bilbeis Air Base -- * `AIRBASE.SinaiMap.Bilbeis_Air_Base` Bilbeis Air Base
-- * `AIRBASE.Sinai.Bir_Hasanah` Bir Hasanah -- * `AIRBASE.SinaiMap.Bir_Hasanah` Bir Hasanah
-- * `AIRBASE.Sinai.Birma_Air_Base` Birma Air Base -- * `AIRBASE.SinaiMap.Birma_Air_Base` Birma Air Base
-- * `AIRBASE.Sinai.Borg_El_Arab_International_Airport` Borg El Arab International Airport -- * `AIRBASE.SinaiMap.Borg_El_Arab_International_Airport` Borg El Arab International Airport
-- * `AIRBASE.Sinai.Cairo_International_Airport` Cairo International Airport -- * `AIRBASE.SinaiMap.Cairo_International_Airport` Cairo International Airport
-- * `AIRBASE.Sinai.Cairo_West` Cairo West -- * `AIRBASE.SinaiMap.Cairo_West` Cairo West
-- * `AIRBASE.Sinai.Damascus_Intl` Damascus Intl -- * `AIRBASE.SinaiMap.Damascus_Intl` Damascus Intl
-- * `AIRBASE.Sinai.Difarsuwar_Airfield` Difarsuwar Airfield -- * `AIRBASE.SinaiMap.Difarsuwar_Airfield` Difarsuwar Airfield
-- * `AIRBASE.Sinai.Ein_Shamer` Ein Shamer -- * `AIRBASE.SinaiMap.Ein_Shamer` Ein Shamer
-- * `AIRBASE.Sinai.El_Arish` El Arish -- * `AIRBASE.SinaiMap.El_Arish` El Arish
-- * `AIRBASE.Sinai.El_Gora` El Gora -- * `AIRBASE.SinaiMap.El_Gora` El Gora
-- * `AIRBASE.Sinai.El_Minya` El Minya -- * `AIRBASE.SinaiMap.El_Minya` El Minya
-- * `AIRBASE.Sinai.Fayed` Fayed -- * `AIRBASE.SinaiMap.Fayed` Fayed
-- * `AIRBASE.Sinai.Gebel_El_Basur_Air_Base` Gebel El Basur Air Base -- * `AIRBASE.SinaiMap.Gebel_El_Basur_Air_Base` Gebel El Basur Air Base
-- * `AIRBASE.Sinai.Hatzerim` Hatzerim -- * `AIRBASE.SinaiMap.Hatzerim` Hatzerim
-- * `AIRBASE.Sinai.Hatzor` Hatzor -- * `AIRBASE.SinaiMap.Hatzor` Hatzor
-- * `AIRBASE.Sinai.Hurghada_International_Airport` Hurghada International Airport -- * `AIRBASE.SinaiMap.Hurghada_International_Airport` Hurghada International Airport
-- * `AIRBASE.Sinai.Inshas_Airbase` Inshas Airbase -- * `AIRBASE.SinaiMap.Inshas_Airbase` Inshas Airbase
-- * `AIRBASE.Sinai.Jiyanklis_Air_Base` Jiyanklis Air Base -- * `AIRBASE.SinaiMap.Jiyanklis_Air_Base` Jiyanklis Air Base
-- * `AIRBASE.Sinai.Kedem` Kedem -- * `AIRBASE.SinaiMap.Kedem` Kedem
-- * `AIRBASE.Sinai.Khalkhalah_Air_Base` Khalkhalah Air Base -- * `AIRBASE.SinaiMap.Khalkhalah_Air_Base` Khalkhalah Air Base
-- * `AIRBASE.Sinai.Kibrit_Air_Base` Kibrit Air Base -- * `AIRBASE.SinaiMap.Kibrit_Air_Base` Kibrit Air Base
-- * `AIRBASE.Sinai.King_Feisal_Air_Base` King Feisal Air Base -- * `AIRBASE.SinaiMap.King_Feisal_Air_Base` King Feisal Air Base
-- * `AIRBASE.Sinai.Kom_Awshim` Kom Awshim -- * `AIRBASE.SinaiMap.Kom_Awshim` Kom Awshim
-- * `AIRBASE.Sinai.Megiddo` Megiddo -- * `AIRBASE.SinaiMap.Megiddo` Megiddo
-- * `AIRBASE.Sinai.Melez` Melez -- * `AIRBASE.SinaiMap.Melez` Melez
-- * `AIRBASE.Sinai.Mezzeh_Air_Base` Mezzeh Air Base -- * `AIRBASE.SinaiMap.Mezzeh_Air_Base` Mezzeh Air Base
-- * `AIRBASE.Sinai.Nevatim` Nevatim -- * `AIRBASE.SinaiMap.Nevatim` Nevatim
-- * `AIRBASE.Sinai.Ovda` Ovda -- * `AIRBASE.SinaiMap.Ovda` Ovda
-- * `AIRBASE.Sinai.Palmachim` Palmachim -- * `AIRBASE.SinaiMap.Palmachim` Palmachim
-- * `AIRBASE.Sinai.Quwaysina` Quwaysina -- * `AIRBASE.SinaiMap.Quwaysina` Quwaysina
-- * `AIRBASE.Sinai.Rafic_Hariri_Intl` Rafic Hariri Intl -- * `AIRBASE.SinaiMap.Rafic_Hariri_Intl` Rafic Hariri Intl
-- * `AIRBASE.Sinai.Ramat_David` Ramat David -- * `AIRBASE.SinaiMap.Ramat_David` Ramat David
-- * `AIRBASE.Sinai.Ramon_Airbase` Ramon Airbase -- * `AIRBASE.SinaiMap.Ramon_Airbase` Ramon Airbase
-- * `AIRBASE.Sinai.Ramon_International_Airport` Ramon International Airport -- * `AIRBASE.SinaiMap.Ramon_International_Airport` Ramon International Airport
-- * `AIRBASE.Sinai.Sde_Dov` Sde Dov -- * `AIRBASE.SinaiMap.Sde_Dov` Sde Dov
-- * `AIRBASE.Sinai.Sharm_El_Sheikh_International_Airport` Sharm El Sheikh International Airport -- * `AIRBASE.SinaiMap.Sharm_El_Sheikh_International_Airport` Sharm El Sheikh International Airport
-- * `AIRBASE.Sinai.St_Catherine` St Catherine -- * `AIRBASE.SinaiMap.St_Catherine` St Catherine
-- * `AIRBASE.Sinai.Taba_International_Airport` Taba International Airport -- * `AIRBASE.SinaiMap.Taba_International_Airport` Taba International Airport
-- * `AIRBASE.Sinai.Tabuk` Tabuk -- * `AIRBASE.SinaiMap.Tabuk` Tabuk
-- * `AIRBASE.Sinai.TabukHeliBase` TabukHeliBase -- * `AIRBASE.SinaiMap.TabukHeliBase` TabukHeliBase
-- * `AIRBASE.Sinai.Tel_Nof` Tel Nof -- * `AIRBASE.SinaiMap.Tel_Nof` Tel Nof
-- * `AIRBASE.Sinai.Wadi_Abu_Rish` Wadi Abu Rish -- * `AIRBASE.SinaiMap.Wadi_Abu_Rish` Wadi Abu Rish
-- * `AIRBASE.Sinai.Wadi_al_Jandali` Wadi al Jandali -- * `AIRBASE.SinaiMap.Wadi_al_Jandali` Wadi al Jandali
-- --
-- @field Sinai -- @field Sinai
AIRBASE.Sinai = { AIRBASE.Sinai = {
@@ -834,66 +834,6 @@ AIRBASE.Sinai = {
["Wadi_Abu_Rish"] = "Wadi Abu Rish", ["Wadi_Abu_Rish"] = "Wadi Abu Rish",
["Wadi_al_Jandali"] = "Wadi al Jandali", ["Wadi_al_Jandali"] = "Wadi al Jandali",
} }
---
-- @field SinaiMap
AIRBASE.SinaiMap = {
["Abu_Rudeis"] = "Abu Rudeis",
["Abu_Suwayr"] = "Abu Suwayr",
["Al_Bahr_al_Ahmar"] = "Al Bahr al Ahmar",
["Al_Ismailiyah"] = "Al Ismailiyah",
["Al_Khatatbah"] = "Al Khatatbah",
["Al_Mansurah"] = "Al Mansurah",
["Al_Rahmaniyah_Air_Base"] = "Al Rahmaniyah Air Base",
["As_Salihiyah"] = "As Salihiyah",
["AzZaqaziq"] = "AzZaqaziq",
["Baluza"] = "Baluza",
["Ben_Gurion"] = "Ben-Gurion",
["Beni_Suef"] = "Beni Suef",
["Bilbeis_Air_Base"] = "Bilbeis Air Base",
["Bir_Hasanah"] = "Bir Hasanah",
["Birma_Air_Base"] = "Birma Air Base",
["Borg_El_Arab_International_Airport"] = "Borg El Arab International Airport",
["Cairo_International_Airport"] = "Cairo International Airport",
["Cairo_West"] = "Cairo West",
["Damascus_Intl"] = "Damascus Intl",
["Difarsuwar_Airfield"] = "Difarsuwar Airfield",
["Ein_Shamer"] = "Ein Shamer",
["El_Arish"] = "El Arish",
["El_Gora"] = "El Gora",
["El_Minya"] = "El Minya",
["Fayed"] = "Fayed",
["Gebel_El_Basur_Air_Base"] = "Gebel El Basur Air Base",
["Hatzerim"] = "Hatzerim",
["Hatzor"] = "Hatzor",
["Hurghada_International_Airport"] = "Hurghada International Airport",
["Inshas_Airbase"] = "Inshas Airbase",
["Jiyanklis_Air_Base"] = "Jiyanklis Air Base",
["Kedem"] = "Kedem",
["Khalkhalah_Air_Base"] = "Khalkhalah Air Base",
["Kibrit_Air_Base"] = "Kibrit Air Base",
["King_Feisal_Air_Base"] = "King Feisal Air Base",
["Kom_Awshim"] = "Kom Awshim",
["Megiddo"] = "Megiddo",
["Melez"] = "Melez",
["Mezzeh_Air_Base"] = "Mezzeh Air Base",
["Nevatim"] = "Nevatim",
["Ovda"] = "Ovda",
["Palmachim"] = "Palmachim",
["Quwaysina"] = "Quwaysina",
["Rafic_Hariri_Intl"] = "Rafic Hariri Intl",
["Ramat_David"] = "Ramat David",
["Ramon_Airbase"] = "Ramon Airbase",
["Ramon_International_Airport"] = "Ramon International Airport",
["Sde_Dov"] = "Sde Dov",
["Sharm_El_Sheikh_International_Airport"] = "Sharm El Sheikh International Airport",
["St_Catherine"] = "St Catherine",
["Taba_International_Airport"] = "Taba International Airport",
["Tabuk"] = "Tabuk",
["TabukHeliBase"] = "TabukHeliBase",
["Tel_Nof"] = "Tel Nof",
["Wadi_Abu_Rish"] = "Wadi Abu Rish",
["Wadi_al_Jandali"] = "Wadi al Jandali",
}
--- Airbases of the Kola map --- Airbases of the Kola map
-- --
@@ -2169,7 +2109,7 @@ end
function AIRBASE:GetParkingSpotsNumber(termtype) function AIRBASE:GetParkingSpotsNumber(termtype)
-- Get free parking spots data. -- Get free parking spots data.
local parkingdata=self:GetParkingData(false) or {} local parkingdata=self:GetParkingData(false)
local nspots=0 local nspots=0
for _,parkingspot in pairs(parkingdata) do for _,parkingspot in pairs(parkingdata) do
@@ -2189,7 +2129,7 @@ end
function AIRBASE:GetFreeParkingSpotsNumber(termtype, allowTOAC) function AIRBASE:GetFreeParkingSpotsNumber(termtype, allowTOAC)
-- Get free parking spots data. -- Get free parking spots data.
local parkingdata=self:GetParkingData(true) or {} local parkingdata=self:GetParkingData(true)
local nfree=0 local nfree=0
for _,parkingspot in pairs(parkingdata) do for _,parkingspot in pairs(parkingdata) do
@@ -2212,7 +2152,7 @@ end
function AIRBASE:GetFreeParkingSpotsCoordinates(termtype, allowTOAC) function AIRBASE:GetFreeParkingSpotsCoordinates(termtype, allowTOAC)
-- Get free parking spots data. -- Get free parking spots data.
local parkingdata=self:GetParkingData(true) or {} local parkingdata=self:GetParkingData(true)
-- Put coordinates of free spots into table. -- Put coordinates of free spots into table.
local spots={} local spots={}
@@ -2311,7 +2251,7 @@ end
function AIRBASE:_InitParkingSpots() function AIRBASE:_InitParkingSpots()
-- Get parking data of all spots (free or occupied) -- Get parking data of all spots (free or occupied)
local parkingdata=self:GetParkingData(false) or {} local parkingdata=self:GetParkingData(false)
-- Init table. -- Init table.
self.parking={} self.parking={}
@@ -2387,10 +2327,10 @@ end
function AIRBASE:GetParkingSpotsTable(termtype) function AIRBASE:GetParkingSpotsTable(termtype)
-- Get parking data of all spots (free or occupied) -- Get parking data of all spots (free or occupied)
local parkingdata=self:GetParkingData(false) or {} local parkingdata=self:GetParkingData(false)
-- Get parking data of all free spots. -- Get parking data of all free spots.
local parkingfree=self:GetParkingData(true) or {} local parkingfree=self:GetParkingData(true)
-- Function to ckeck if any parking spot is free. -- Function to ckeck if any parking spot is free.
local function _isfree(_tocheck) local function _isfree(_tocheck)
@@ -2439,7 +2379,7 @@ end
function AIRBASE:GetFreeParkingSpotsTable(termtype, allowTOAC) function AIRBASE:GetFreeParkingSpotsTable(termtype, allowTOAC)
-- Get parking data of all free spots. -- Get parking data of all free spots.
local parkingfree=self:GetParkingData(true) or {} local parkingfree=self:GetParkingData(true)
-- Put coordinates of free spots into table. -- Put coordinates of free spots into table.
local freespots={} local freespots={}
@@ -2469,7 +2409,7 @@ end
function AIRBASE:GetParkingSpotData(TerminalID) function AIRBASE:GetParkingSpotData(TerminalID)
-- Get parking data. -- Get parking data.
local parkingdata=self:GetParkingSpotsTable() or {} local parkingdata=self:GetParkingSpotsTable()
for _,_spot in pairs(parkingdata) do for _,_spot in pairs(parkingdata) do
local spot=_spot --#AIRBASE.ParkingSpot local spot=_spot --#AIRBASE.ParkingSpot
@@ -2495,7 +2435,7 @@ function AIRBASE:MarkParkingSpots(termtype, mark)
end end
-- Get parking data from getParking() wrapper function. -- Get parking data from getParking() wrapper function.
local parkingdata=self:GetParkingSpotsTable(termtype) or {} local parkingdata=self:GetParkingSpotsTable(termtype)
-- Get airbase name. -- Get airbase name.
local airbasename=self:GetName() local airbasename=self:GetName()
@@ -2610,7 +2550,7 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
local markobstacles=false local markobstacles=false
-- Loop over all known parking spots -- Loop over all known parking spots
for _,parkingspot in pairs(parkingdata or {}) do for _,parkingspot in pairs(parkingdata) do
-- Coordinate of the parking spot. -- Coordinate of the parking spot.
local _spot=parkingspot.Coordinate -- Core.Point#COORDINATE local _spot=parkingspot.Coordinate -- Core.Point#COORDINATE
+6 -25
View File
@@ -1352,7 +1352,9 @@ function UNIT:GetThreatLevel()
end end
ThreatText = ThreatLevels[ThreatLevel + 1] ThreatText = ThreatLevels[ThreatLevel + 1]
elseif self:IsAir() then end
if self:IsAir() then
local ThreatLevels = { local ThreatLevels = {
[1] = "Unarmed", [1] = "Unarmed",
@@ -1395,7 +1397,9 @@ function UNIT:GetThreatLevel()
end end
ThreatText = ThreatLevels[ThreatLevel + 1] ThreatText = ThreatLevels[ThreatLevel + 1]
elseif self:IsShip() then end
if self:IsShip() then
--["Aircraft Carriers"] = {"Heavy armed ships",}, --["Aircraft Carriers"] = {"Heavy armed ships",},
--["Cruisers"] = {"Heavy armed ships",}, --["Cruisers"] = {"Heavy armed ships",},
@@ -1949,26 +1953,3 @@ end
function UNIT:SetValidateAndRepositionGroundUnits(Enabled) function UNIT:SetValidateAndRepositionGroundUnits(Enabled)
self.ValidateAndRepositionGroundUnits = Enabled self.ValidateAndRepositionGroundUnits = Enabled
end end
--- Get the max kgs of fuel this unit can hold in its *internal* tank(s) and overall (with external tanks) in kgs.
-- @param #UNIT self
-- @return #number InternalFuel Max internal fuel in kgs. Zero if it cannot be determined.
-- @return #number Overall Fuel Overall max in case there are external tanks in kgs. Zero if it cannot be determined.
function UNIT:GetFuelMassMax()
local Desc = self:GetDesc() or {}
local massFuelMax=Desc.fuelMassMax or 0
local relFuel=math.min(self:GetFuel() or 1.0, 1.0) -- We take 1.0 as max in case of external fuel tanks.
local massFuel=massFuelMax*relFuel
return massFuel, massFuelMax
end
--- Get the current kgs of fuel this unit holds in all of its tanks.
-- @param #UNIT self
-- @param #number Filling Fuel in kgs.
function UNIT:GetCurrentFuelKgs()
local fuel, maxfuel = self:GetFuelMassMax()
local relfuel = self:GetFuel()
local maxfilling = math.max(fuel,maxfuel)
local mass = maxfilling*relfuel
return mass
end
+1 -1
View File
@@ -350,7 +350,7 @@ end
-- myweapon:SetFuncImpact(OnImpact) -- myweapon:SetFuncImpact(OnImpact)
-- --
-- -- Start tracking. -- -- Start tracking.
-- myweapon:StartTrack() -- myweapon:Track()
-- --
function WEAPON:SetFuncImpact(FuncImpact, ...) function WEAPON:SetFuncImpact(FuncImpact, ...)
self.impactFunc=FuncImpact self.impactFunc=FuncImpact