mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Merge branch 'develop' into FF/Ops
This commit is contained in:
commit
375e7db449
@ -123,7 +123,7 @@ function MARKEROPS_BASE:New(Tagname,Keywords)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- (internal) Handle events.
|
--- (internal) Handle events.
|
||||||
-- @param #MARKEROPS self
|
-- @param #MARKEROPS_BASE self
|
||||||
-- @param Core.Event#EVENTDATA Event
|
-- @param Core.Event#EVENTDATA Event
|
||||||
function MARKEROPS_BASE:OnEventMark(Event)
|
function MARKEROPS_BASE:OnEventMark(Event)
|
||||||
self:T({Event})
|
self:T({Event})
|
||||||
@ -173,7 +173,7 @@ function MARKEROPS_BASE:OnEventMark(Event)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- (internal) Match tag.
|
--- (internal) Match tag.
|
||||||
-- @param #MARKEROPS self
|
-- @param #MARKEROPS_BASE self
|
||||||
-- @param #string Eventtext Text added to the marker.
|
-- @param #string Eventtext Text added to the marker.
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
function MARKEROPS_BASE:_MatchTag(Eventtext)
|
function MARKEROPS_BASE:_MatchTag(Eventtext)
|
||||||
@ -186,7 +186,7 @@ function MARKEROPS_BASE:_MatchTag(Eventtext)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- (internal) Match keywords table.
|
--- (internal) Match keywords table.
|
||||||
-- @param #MARKEROPS self
|
-- @param #MARKEROPS_BASE self
|
||||||
-- @param #string Eventtext Text added to the marker.
|
-- @param #string Eventtext Text added to the marker.
|
||||||
-- @return #table
|
-- @return #table
|
||||||
function MARKEROPS_BASE:_MatchKeywords(Eventtext)
|
function MARKEROPS_BASE:_MatchKeywords(Eventtext)
|
||||||
|
|||||||
@ -970,7 +970,7 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories )
|
|||||||
local SceneryName = ZoneObject:getName()
|
local SceneryName = ZoneObject:getName()
|
||||||
self.ScanData.Scenery[SceneryType] = self.ScanData.Scenery[SceneryType] or {}
|
self.ScanData.Scenery[SceneryType] = self.ScanData.Scenery[SceneryType] or {}
|
||||||
self.ScanData.Scenery[SceneryType][SceneryName] = SCENERY:Register( SceneryName, ZoneObject )
|
self.ScanData.Scenery[SceneryType][SceneryName] = SCENERY:Register( SceneryName, ZoneObject )
|
||||||
self:F2( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } )
|
self:T( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -1373,7 +1373,86 @@ function ZONE_RADIUS:GetRandomCoordinate(inner, outer, surfacetypes)
|
|||||||
return Coordinate
|
return Coordinate
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Returns a @{Core.Point#COORDINATE} object reflecting a random location within the zone where there are no **map objects** of type "Building".
|
||||||
|
-- Does not find statics you might have placed there. **Note** This might be quite CPU intensive, use with care.
|
||||||
|
-- @param #ZONE_RADIUS self
|
||||||
|
-- @param #number inner (Optional) Minimal distance from the center of the zone in meters. Default is 0m.
|
||||||
|
-- @param #number outer (Optional) Maximal distance from the outer edge of the zone in meters. Default is the radius of the zone.
|
||||||
|
-- @param #number distance (Optional) Minumum distance from any building coordinate. Defaults to 100m.
|
||||||
|
-- @param #boolean markbuildings (Optional) Place markers on found buildings (if any).
|
||||||
|
-- @param #boolean markfinal (Optional) Place marker on the final coordinate (if any).
|
||||||
|
-- @return Core.Point#COORDINATE The random coordinate or `nil` if cannot be found in 1000 iterations.
|
||||||
|
function ZONE_RADIUS:GetRandomCoordinateWithoutBuildings(inner,outer,distance,markbuildings,markfinal)
|
||||||
|
|
||||||
|
local dist = distance or 100
|
||||||
|
|
||||||
|
local objects = {}
|
||||||
|
|
||||||
|
if self.ScanData and self.ScanData.Scenery then
|
||||||
|
objects = self:GetScannedScenery()
|
||||||
|
else
|
||||||
|
self:Scan({Object.Category.SCENERY})
|
||||||
|
objects = self:GetScannedScenery()
|
||||||
|
end
|
||||||
|
|
||||||
|
local T0 = timer.getTime()
|
||||||
|
local T1 = timer.getTime()
|
||||||
|
|
||||||
|
|
||||||
|
local buildings = {}
|
||||||
|
if self.ScanData and self.ScanData.BuildingCoordinates then
|
||||||
|
buildings = self.ScanData.BuildingCoordinates
|
||||||
|
else
|
||||||
|
-- build table of buildings coordinates
|
||||||
|
for _,_object in pairs (objects) do
|
||||||
|
for _,_scen in pairs (_object) do
|
||||||
|
local scenery = _scen -- Wrapper.Scenery#SCENERY
|
||||||
|
local description=scenery:GetDesc()
|
||||||
|
if description and description.attributes and description.attributes.Buildings then
|
||||||
|
if markbuildings then
|
||||||
|
MARKER:New(scenery:GetCoordinate(),"Building"):ToAll()
|
||||||
|
end
|
||||||
|
buildings[#buildings+1] = scenery:GetCoordinate()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.ScanData.BuildingCoordinates = buildings
|
||||||
|
end
|
||||||
|
|
||||||
|
-- max 1000 tries
|
||||||
|
local rcoord = nil
|
||||||
|
local found = false
|
||||||
|
local iterations = 0
|
||||||
|
|
||||||
|
for i=1,1000 do
|
||||||
|
iterations = iterations + 1
|
||||||
|
rcoord = self:GetRandomCoordinate(inner,outer)
|
||||||
|
found = false
|
||||||
|
for _,_coord in pairs (buildings) do
|
||||||
|
local coord = _coord -- Core.Point#COORDINATE
|
||||||
|
-- keep >50m dist from buildings
|
||||||
|
if coord:Get2DDistance(rcoord) > dist then
|
||||||
|
found = true
|
||||||
|
else
|
||||||
|
found = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if found then
|
||||||
|
-- we have a winner!
|
||||||
|
if markfinal then
|
||||||
|
MARKER:New(rcoord,"FREE"):ToAll()
|
||||||
|
end
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
T1=timer.getTime()
|
||||||
|
|
||||||
|
self:T(string.format("Found a coordinate: %s | Iterations: %d | Time: %d",tostring(found),iterations,T1-T0))
|
||||||
|
|
||||||
|
if found then return rcoord else return nil end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- @type ZONE
|
--- @type ZONE
|
||||||
-- @extends #ZONE_RADIUS
|
-- @extends #ZONE_RADIUS
|
||||||
|
|||||||
@ -147,7 +147,7 @@
|
|||||||
-- * overestimation how far units can "see" and
|
-- * overestimation how far units can "see" and
|
||||||
-- * not taking into account that a SAM site will take (e.g for a SA-6) 30-40 seconds between switching on, acquiring the target and firing.
|
-- * not taking into account that a SAM site will take (e.g for a SA-6) 30-40 seconds between switching on, acquiring the target and firing.
|
||||||
--
|
--
|
||||||
-- An attacker doing 350knots will cover ca 180meters/second or thus more than 6km until the SA-6 fires. Use triggers zones and the ruler in the missione editor to understand distances and zones. Take into account that the ranges given by the circles
|
-- An attacker doing 350knots will cover ca 180meters/second or thus more than 6km until the SA-6 fires. Use triggers zones and the ruler in the mission editor to understand distances and zones. Take into account that the ranges given by the circles
|
||||||
-- in the mission editor are absolute maximum ranges; in-game this is rather 50-75% of that depending on the system. Fiddle with placement and options to see what works best for your scenario, and remember **everything in here is in meters**.
|
-- in the mission editor are absolute maximum ranges; in-game this is rather 50-75% of that depending on the system. Fiddle with placement and options to see what works best for your scenario, and remember **everything in here is in meters**.
|
||||||
--
|
--
|
||||||
-- # 2. Start up your MANTIS with a basic setting
|
-- # 2. Start up your MANTIS with a basic setting
|
||||||
@ -1515,7 +1515,7 @@ do
|
|||||||
-- @param #table samset Table of SAM data
|
-- @param #table samset Table of SAM data
|
||||||
-- @param #table detset Table of COORDINATES
|
-- @param #table detset Table of COORDINATES
|
||||||
-- @param #boolean dlink Using DLINK
|
-- @param #boolean dlink Using DLINK
|
||||||
-- @param #limit limit of SAM sites to go active on a contact
|
-- @param #number limit of SAM sites to go active on a contact
|
||||||
-- @return #MANTIS self
|
-- @return #MANTIS self
|
||||||
function MANTIS:_CheckLoop(samset,detset,dlink,limit)
|
function MANTIS:_CheckLoop(samset,detset,dlink,limit)
|
||||||
self:T(self.lid .. "CheckLoop " .. #detset .. " Coordinates")
|
self:T(self.lid .. "CheckLoop " .. #detset .. " Coordinates")
|
||||||
|
|||||||
@ -2185,7 +2185,7 @@ end
|
|||||||
--- **[GROUND]** Create an ARMORED ON GUARD mission.
|
--- **[GROUND]** Create an ARMORED ON GUARD mission.
|
||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
-- @param Core.Point#COORDINATE Coordinate Coordinate, where to stand guard.
|
-- @param Core.Point#COORDINATE Coordinate Coordinate, where to stand guard.
|
||||||
-- @param #string Formation Formation to take, e.g. "on Road", "Vee" etc.
|
-- @param #string Formation Formation to take, e.g. "On Road", "Vee" etc.
|
||||||
-- @return #AUFTRAG self
|
-- @return #AUFTRAG self
|
||||||
function AUFTRAG:NewARMOREDGUARD(Coordinate,Formation)
|
function AUFTRAG:NewARMOREDGUARD(Coordinate,Formation)
|
||||||
|
|
||||||
|
|||||||
@ -6421,7 +6421,7 @@ function OPSGROUP:onbeforeLaserOn(From, Event, To, Target)
|
|||||||
self.spot.element=element
|
self.spot.element=element
|
||||||
|
|
||||||
-- Height offset. No offset for aircraft. We take the height for ground or naval.
|
-- Height offset. No offset for aircraft. We take the height for ground or naval.
|
||||||
local offsetY=0
|
local offsetY=2 --2m for ARMYGROUP, else there might be no LOS
|
||||||
if self.isFlightgroup or self.isNavygroup then
|
if self.isFlightgroup or self.isNavygroup then
|
||||||
offsetY=element.height
|
offsetY=element.height
|
||||||
end
|
end
|
||||||
|
|||||||
@ -79,7 +79,7 @@ PLAYERTASK = {
|
|||||||
|
|
||||||
--- PLAYERTASK class version.
|
--- PLAYERTASK class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
PLAYERTASK.version="0.0.9"
|
PLAYERTASK.version="0.1.0"
|
||||||
|
|
||||||
--- Generic task condition.
|
--- Generic task condition.
|
||||||
-- @type PLAYERTASK.Condition
|
-- @type PLAYERTASK.Condition
|
||||||
@ -147,7 +147,7 @@ function PLAYERTASK:New(Type, Target, Repeat, Times, TTSType)
|
|||||||
self:AddTransition("*", "Cancel", "Done") -- Command to cancel the Task.
|
self:AddTransition("*", "Cancel", "Done") -- Command to cancel the Task.
|
||||||
self:AddTransition("*", "Success", "Done")
|
self:AddTransition("*", "Success", "Done")
|
||||||
self:AddTransition("*", "ClientAborted", "*")
|
self:AddTransition("*", "ClientAborted", "*")
|
||||||
self:AddTransition("*", "Failed", "*") -- Done or repeat --> PLANNED
|
self:AddTransition("*", "Failed", "Failed") -- Done or repeat --> PLANNED
|
||||||
self:AddTransition("*", "Status", "*")
|
self:AddTransition("*", "Status", "*")
|
||||||
self:AddTransition("*", "Stop", "Stopped")
|
self:AddTransition("*", "Stop", "Stopped")
|
||||||
|
|
||||||
@ -505,7 +505,7 @@ function PLAYERTASK:onafterStatus(From, Event, To)
|
|||||||
-- Any failure condition true?
|
-- Any failure condition true?
|
||||||
local failureCondition=self:_EvalConditionsAny(self.conditionFailure)
|
local failureCondition=self:_EvalConditionsAny(self.conditionFailure)
|
||||||
|
|
||||||
if failureCondition then
|
if failureCondition and status ~= "Failed" then
|
||||||
self:__Failed(-2)
|
self:__Failed(-2)
|
||||||
status = "Failed"
|
status = "Failed"
|
||||||
elseif successCondition then
|
elseif successCondition then
|
||||||
@ -703,6 +703,7 @@ do
|
|||||||
-- @field #string locale
|
-- @field #string locale
|
||||||
-- @field #boolean precisionbombing
|
-- @field #boolean precisionbombing
|
||||||
-- @field Ops.FlightGroup#FLIGHTGROUP LasingDrone
|
-- @field Ops.FlightGroup#FLIGHTGROUP LasingDrone
|
||||||
|
-- @field Core.MarkerOps_BASE#MARKEROPS_BASE MarkerOps
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -744,7 +745,7 @@ do
|
|||||||
-- * BAI - Battlefield air interdiction, same as above, but no friendlies around
|
-- * BAI - Battlefield air interdiction, same as above, but no friendlies around
|
||||||
-- * SEAD - Same as CAS, but the enemy ground units field AAA, SAM or EWR units
|
-- * SEAD - Same as CAS, but the enemy ground units field AAA, SAM or EWR units
|
||||||
-- * Bombing - Against static targets
|
-- * Bombing - Against static targets
|
||||||
-- * Precision Bombing - (if enabled) Laser-guided bombing, against static targets and high-value ground targets (MBTs etc)
|
-- * Precision Bombing - (if enabled) Laser-guided bombing, against **static targets** and **high-value (non-SAM) ground targets (MBTs etc)**
|
||||||
-- * Bomb Runway - Against Airbase runways (in effect, drop bombs over the runway)
|
-- * Bomb Runway - Against Airbase runways (in effect, drop bombs over the runway)
|
||||||
-- * ZONE and COORDINATE - Targets will be scanned for GROUND or STATIC enemy units and tasks created from these
|
-- * ZONE and COORDINATE - Targets will be scanned for GROUND or STATIC enemy units and tasks created from these
|
||||||
-- * Intercept - Any airborne targets, if the controller is of type "A2A"
|
-- * Intercept - Any airborne targets, if the controller is of type "A2A"
|
||||||
@ -874,9 +875,9 @@ do
|
|||||||
-- PILOTSTTS = ". Pilot(s): ",
|
-- PILOTSTTS = ". Pilot(s): ",
|
||||||
-- YES = "Yes",
|
-- YES = "Yes",
|
||||||
-- NO = "No",
|
-- NO = "No",
|
||||||
-- POINTEROVERTARGET = "%s, %s, pointer over target for task %03d, lasing!",
|
-- POINTEROVERTARGET = "%s, %s, pointer in reach for task %03d, lasing!",
|
||||||
-- POINTERTARGETREPORT = "\nPointer over target: %s\nLasing: %s",
|
-- POINTERTARGETREPORT = "\nPointer in reach: %s\nLasing: %s",
|
||||||
-- POINTERTARGETLASINGTTS = ". Pointer over target and lasing.",
|
-- POINTERTARGETLASINGTTS = ". Pointer in reach and lasing.",
|
||||||
-- },
|
-- },
|
||||||
--
|
--
|
||||||
-- e.g.
|
-- e.g.
|
||||||
@ -948,8 +949,18 @@ do
|
|||||||
-- function taskmanager:OnAfterRepeatOnFailed(From, Event, To, Task)
|
-- function taskmanager:OnAfterRepeatOnFailed(From, Event, To, Task)
|
||||||
-- ... your code here ...
|
-- ... your code here ...
|
||||||
-- end
|
-- end
|
||||||
--
|
--
|
||||||
-- ## 8 Discussion
|
-- ## 8 Using F10 map markers to create new targets
|
||||||
|
--
|
||||||
|
-- You can use F10 map markers to create new target points for player tasks.
|
||||||
|
-- Enable this option with e.g., setting the tag to be used to "TARGET":
|
||||||
|
--
|
||||||
|
-- taskmanager:EnableMarkerOps("TARGET")
|
||||||
|
--
|
||||||
|
-- Set a marker on the map and add the following text to create targets from it: "TARGET". This is effectively the same as adding a COORDINATE object as target.
|
||||||
|
-- The marker can be deleted any time.
|
||||||
|
--
|
||||||
|
-- ## 9 Discussion
|
||||||
--
|
--
|
||||||
-- If you have questions or suggestions, please visit the [MOOSE Discord](https://discord.gg/AeYAkHP) #ops-playertask channel.
|
-- If you have questions or suggestions, please visit the [MOOSE Discord](https://discord.gg/AeYAkHP) #ops-playertask channel.
|
||||||
--
|
--
|
||||||
@ -965,7 +976,7 @@ PLAYERTASKCONTROLLER = {
|
|||||||
PlayerMenu = {},
|
PlayerMenu = {},
|
||||||
usecluster = false,
|
usecluster = false,
|
||||||
MenuName = nil,
|
MenuName = nil,
|
||||||
ClusterRadius = 1250,
|
ClusterRadius = 0.5,
|
||||||
NoScreenOutput = false,
|
NoScreenOutput = false,
|
||||||
TargetRadius = 500,
|
TargetRadius = 500,
|
||||||
UseWhiteList = false,
|
UseWhiteList = false,
|
||||||
@ -991,6 +1002,17 @@ PLAYERTASKCONTROLLER.Type = {
|
|||||||
--- Define a new AUFTRAG Type
|
--- Define a new AUFTRAG Type
|
||||||
AUFTRAG.Type.PRECISIONBOMBING = "Precision Bombing"
|
AUFTRAG.Type.PRECISIONBOMBING = "Precision Bombing"
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @type SeadAttributes
|
||||||
|
-- @field #number SAM GROUP.Attribute.GROUND_SAM
|
||||||
|
-- @field #number AAA GROUP.Attribute.GROUND_AAA
|
||||||
|
-- @field #number EWR GROUP.Attribute.GROUND_EWR
|
||||||
|
PLAYERTASKCONTROLLER.SeadAttributes = {
|
||||||
|
SAM = GROUP.Attribute.GROUND_SAM,
|
||||||
|
AAA = GROUP.Attribute.GROUND_AAA,
|
||||||
|
EWR = GROUP.Attribute.GROUND_EWR,
|
||||||
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
-- @field Messages
|
-- @field Messages
|
||||||
PLAYERTASKCONTROLLER.Messages = {
|
PLAYERTASKCONTROLLER.Messages = {
|
||||||
@ -1045,9 +1067,9 @@ PLAYERTASKCONTROLLER.Messages = {
|
|||||||
PILOTSTTS = ". Pilot(s): ",
|
PILOTSTTS = ". Pilot(s): ",
|
||||||
YES = "Yes",
|
YES = "Yes",
|
||||||
NO = "No",
|
NO = "No",
|
||||||
POINTEROVERTARGET = "%s, %s, pointer over target for task %03d, lasing!",
|
POINTEROVERTARGET = "%s, %s, pointer in reach for task %03d, lasing!",
|
||||||
POINTERTARGETREPORT = "\nPointer over target: %s\nLasing: %s",
|
POINTERTARGETREPORT = "\nPointer in reach: %s\nLasing: %s",
|
||||||
POINTERTARGETLASINGTTS = ". Pointer over target and lasing.",
|
POINTERTARGETLASINGTTS = ". Pointer in reach and lasing.",
|
||||||
},
|
},
|
||||||
DE = {
|
DE = {
|
||||||
TASKABORT = "Auftrag abgebrochen!",
|
TASKABORT = "Auftrag abgebrochen!",
|
||||||
@ -1108,7 +1130,7 @@ PLAYERTASKCONTROLLER.Messages = {
|
|||||||
|
|
||||||
--- PLAYERTASK class version.
|
--- PLAYERTASK class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
PLAYERTASKCONTROLLER.version="0.1.25"
|
PLAYERTASKCONTROLLER.version="0.1.27"
|
||||||
|
|
||||||
--- Constructor
|
--- Constructor
|
||||||
-- @param #PLAYERTASKCONTROLLER self
|
-- @param #PLAYERTASKCONTROLLER self
|
||||||
@ -1132,7 +1154,7 @@ function PLAYERTASKCONTROLLER:New(Name, Coalition, Type, ClientFilter)
|
|||||||
self.usecluster = true
|
self.usecluster = true
|
||||||
end
|
end
|
||||||
|
|
||||||
self.ClusterRadius = 1250
|
self.ClusterRadius = 0.5
|
||||||
self.TargetRadius = 500
|
self.TargetRadius = 500
|
||||||
|
|
||||||
self.ClientFilter = ClientFilter or ""
|
self.ClientFilter = ClientFilter or ""
|
||||||
@ -1324,6 +1346,37 @@ function PLAYERTASKCONTROLLER:EnablePrecisionBombing(FlightGroup,LaserCode)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [User] Allow addition of targets with user F10 map markers.
|
||||||
|
-- @param #PLAYERTASKCONTROLLER self
|
||||||
|
-- @param #string Tag (Optional) The tagname to use to identify commands, defaults to "TASK"
|
||||||
|
-- @return #PLAYERTASKCONTROLLER self
|
||||||
|
function PLAYERTASKCONTROLLER:EnableMarkerOps(Tag)
|
||||||
|
self:T(self.lid.."EnableMarkerOps")
|
||||||
|
|
||||||
|
local tag = Tag or "TASK"
|
||||||
|
local MarkerOps = MARKEROPS_BASE:New(tag)
|
||||||
|
|
||||||
|
local function Handler(Keywords,Coord,Text)
|
||||||
|
if self.verbose then
|
||||||
|
local m = MESSAGE:New(string.format("Target added from marker at: %s", Coord:ToStringLLDMS()),15,"INFO"):ToAll()
|
||||||
|
end
|
||||||
|
self:AddTarget(Coord)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Event functions
|
||||||
|
function MarkerOps:OnAfterMarkAdded(From,Event,To,Text,Keywords,Coord)
|
||||||
|
Handler(Keywords,Coord,Text)
|
||||||
|
end
|
||||||
|
|
||||||
|
function MarkerOps:OnAfterMarkChanged(From,Event,To,Text,Keywords,Coord)
|
||||||
|
Handler(Keywords,Coord,Text)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.MarkerOps = MarkerOps
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- [Internal] Get player name
|
--- [Internal] Get player name
|
||||||
-- @param #PLAYERTASKCONTROLLER self
|
-- @param #PLAYERTASKCONTROLLER self
|
||||||
-- @param Wrapper.Client#CLIENT Client
|
-- @param Wrapper.Client#CLIENT Client
|
||||||
@ -1450,11 +1503,11 @@ end
|
|||||||
--- [User] Set the cluster radius if you want to use target clusters rather than single group detection.
|
--- [User] Set the cluster radius if you want to use target clusters rather than single group detection.
|
||||||
-- Note that for a controller type A2A target clustering is on by default. Also remember that the diameter of the resulting zone is double the radius.
|
-- Note that for a controller type A2A target clustering is on by default. Also remember that the diameter of the resulting zone is double the radius.
|
||||||
-- @param #PLAYERTASKCONTROLLER self
|
-- @param #PLAYERTASKCONTROLLER self
|
||||||
-- @param #number Radius Target cluster radius in meters. Default is 1250m or 0.67NM
|
-- @param #number Radius Target cluster radius in kilometers. Default is 0.5km.
|
||||||
-- @return #PLAYERTASKCONTROLLER self
|
-- @return #PLAYERTASKCONTROLLER self
|
||||||
function PLAYERTASKCONTROLLER:SetClusterRadius(Radius)
|
function PLAYERTASKCONTROLLER:SetClusterRadius(Radius)
|
||||||
self:T(self.lid.."SetClusterRadius")
|
self:T(self.lid.."SetClusterRadius")
|
||||||
self.ClusterRadius = Radius or 1250
|
self.ClusterRadius = Radius or 0.5
|
||||||
self.usecluster = true
|
self.usecluster = true
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -1595,7 +1648,7 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
|
|||||||
if self.LasingDrone and self.LasingDrone:IsAlive() then
|
if self.LasingDrone and self.LasingDrone:IsAlive() then
|
||||||
if self.LasingDrone.playertask and (not self.LasingDrone.playertask.busy) then
|
if self.LasingDrone.playertask and (not self.LasingDrone.playertask.busy) then
|
||||||
-- not busy, get a task
|
-- not busy, get a task
|
||||||
self:I(self.lid.."Sending lasing unit to target")
|
self:T(self.lid.."Sending lasing unit to target")
|
||||||
local task = self.PrecisionTasks:Pull() -- Ops.PlayerTask#PLAYERTASK
|
local task = self.PrecisionTasks:Pull() -- Ops.PlayerTask#PLAYERTASK
|
||||||
self.LasingDrone.playertask.id = task.PlayerTaskNr
|
self.LasingDrone.playertask.id = task.PlayerTaskNr
|
||||||
self.LasingDrone.playertask.busy = true
|
self.LasingDrone.playertask.busy = true
|
||||||
@ -1612,7 +1665,7 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
|
|||||||
local tgtzone = ZONE_RADIUS:New("ArmyGroup-"..math.random(1,10000),tgtcoord:GetVec2(),3000)
|
local tgtzone = ZONE_RADIUS:New("ArmyGroup-"..math.random(1,10000),tgtcoord:GetVec2(),3000)
|
||||||
local finalpos=nil -- Core.Point#COORDINATE
|
local finalpos=nil -- Core.Point#COORDINATE
|
||||||
for i=1,50 do
|
for i=1,50 do
|
||||||
finalpos = tgtzone:GetRandomCoordinate(2000,0,{land.SurfaceType.LAND,land.SurfaceType.ROAD,land.SurfaceType.SHALLOW_WATER})
|
finalpos = tgtzone:GetRandomCoordinate(2500,0,{land.SurfaceType.LAND,land.SurfaceType.ROAD,land.SurfaceType.SHALLOW_WATER})
|
||||||
if finalpos then
|
if finalpos then
|
||||||
if finalpos:IsLOS(tgtcoord,0) then
|
if finalpos:IsLOS(tgtcoord,0) then
|
||||||
break
|
break
|
||||||
@ -1621,7 +1674,7 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
|
|||||||
end
|
end
|
||||||
if finalpos then
|
if finalpos then
|
||||||
-- yeah we got one
|
-- yeah we got one
|
||||||
local auftrag = AUFTRAG:NewARMOREDGUARD(finalpos)
|
local auftrag = AUFTRAG:NewARMOREDGUARD(finalpos,"Off road")
|
||||||
local currmission = self.LasingDrone:GetMissionCurrent()
|
local currmission = self.LasingDrone:GetMissionCurrent()
|
||||||
self.LasingDrone:AddMission(auftrag)
|
self.LasingDrone:AddMission(auftrag)
|
||||||
if currmission then currmission:__Cancel(-2) end
|
if currmission then currmission:__Cancel(-2) end
|
||||||
@ -1638,7 +1691,7 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
|
|||||||
elseif self.LasingDrone.playertask and self.LasingDrone.playertask.busy then
|
elseif self.LasingDrone.playertask and self.LasingDrone.playertask.busy then
|
||||||
-- drone is busy, set up laser when over target
|
-- drone is busy, set up laser when over target
|
||||||
local task = self.PrecisionTasks:ReadByID(self.LasingDrone.playertask.id) -- Ops.PlayerTask#PLAYERTASK
|
local task = self.PrecisionTasks:ReadByID(self.LasingDrone.playertask.id) -- Ops.PlayerTask#PLAYERTASK
|
||||||
self:I("Looking at Task: "..task.PlayerTaskNr.." Type: "..task.Type.." State: "..task:GetState())
|
self:T("Looking at Task: "..task.PlayerTaskNr.." Type: "..task.Type.." State: "..task:GetState())
|
||||||
if (not task) or task:GetState() == "Done" or task:GetState() == "Stopped" then
|
if (not task) or task:GetState() == "Done" or task:GetState() == "Stopped" then
|
||||||
-- we're done here
|
-- we're done here
|
||||||
local task = self.PrecisionTasks:PullByID(self.LasingDrone.playertask.id) -- Ops.PlayerTask#PLAYERTASK
|
local task = self.PrecisionTasks:PullByID(self.LasingDrone.playertask.id) -- Ops.PlayerTask#PLAYERTASK
|
||||||
@ -1651,7 +1704,7 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
|
|||||||
self.LasingDrone.playertask.inreach = false
|
self.LasingDrone.playertask.inreach = false
|
||||||
self.LasingDrone.playertask.id = 0
|
self.LasingDrone.playertask.id = 0
|
||||||
self.LasingDrone.playertask.reachmessage = false
|
self.LasingDrone.playertask.reachmessage = false
|
||||||
self:I(self.lid.."Laser Off")
|
self:T(self.lid.."Laser Off")
|
||||||
else
|
else
|
||||||
-- not done yet
|
-- not done yet
|
||||||
local dcoord = self.LasingDrone:GetCoordinate()
|
local dcoord = self.LasingDrone:GetCoordinate()
|
||||||
@ -1659,7 +1712,7 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
|
|||||||
local dist = dcoord:Get2DDistance(tcoord)
|
local dist = dcoord:Get2DDistance(tcoord)
|
||||||
-- close enough?
|
-- close enough?
|
||||||
if dist < 3000 and not self.LasingDrone:IsLasing() then
|
if dist < 3000 and not self.LasingDrone:IsLasing() then
|
||||||
self:I(self.lid.."Laser On")
|
self:T(self.lid.."Laser On")
|
||||||
self.LasingDrone:__LaserOn(-1,tcoord)
|
self.LasingDrone:__LaserOn(-1,tcoord)
|
||||||
self.LasingDrone.playertask.inreach = true
|
self.LasingDrone.playertask.inreach = true
|
||||||
if not self.LasingDrone.playertask.reachmessage then
|
if not self.LasingDrone.playertask.reachmessage then
|
||||||
@ -1793,6 +1846,41 @@ function PLAYERTASKCONTROLLER:SetTaskBlackList(BlackList)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [User] Change the list of attributes, which are considered on GROUP or SET\_GROUP level of a target to create SEAD player tasks.
|
||||||
|
-- @param #PLAYERTASKCONTROLLER self
|
||||||
|
-- @param #table Attributes Table of attribute types considered to lead to a SEAD type player task.
|
||||||
|
-- @return #PLAYERTASKCONTROLLER self
|
||||||
|
-- @usage
|
||||||
|
-- Default attribute types are: GROUP.Attribute.GROUND_SAM, GROUP.Attribute.GROUND_AAA, and GROUP.Attribute.GROUND_EWR.
|
||||||
|
-- If you want to e.g. exclude AAA, so target groups with this attribute are assigned CAS or BAI tasks, and not SEAD, use this function as follows:
|
||||||
|
--
|
||||||
|
-- `mycontroller:SetSEADAttributes({GROUP.Attribute.GROUND_SAM, GROUP.Attribute.GROUND_EWR})`
|
||||||
|
--
|
||||||
|
function PLAYERTASKCONTROLLER:SetSEADAttributes(Attributes)
|
||||||
|
self:T(self.lid.."SetSEADAttributes")
|
||||||
|
if type(Attributes) ~= "table" then
|
||||||
|
Attributes = {Attributes}
|
||||||
|
end
|
||||||
|
self.SeadAttributes = Attributes
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Internal] Function the check against SeadAttributes
|
||||||
|
-- @param #PLAYERTASKCONTROLLER self
|
||||||
|
-- @param #string Attribute
|
||||||
|
-- @return #boolean IsSead
|
||||||
|
function PLAYERTASKCONTROLLER:_IsAttributeSead(Attribute)
|
||||||
|
self:T(self.lid.."_IsAttributeSead?")
|
||||||
|
local IsSead = false
|
||||||
|
for _,_attribute in pairs(self.SeadAttributes) do
|
||||||
|
if Attribute == _attribute then
|
||||||
|
IsSead = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return IsSead
|
||||||
|
end
|
||||||
|
|
||||||
--- [Internal] Add a task to the task queue
|
--- [Internal] Add a task to the task queue
|
||||||
-- @param #PLAYERTASKCONTROLLER self
|
-- @param #PLAYERTASKCONTROLLER self
|
||||||
-- @param Ops.Target#TARGET Target
|
-- @param Ops.Target#TARGET Target
|
||||||
@ -1820,22 +1908,22 @@ function PLAYERTASKCONTROLLER:_AddTask(Target)
|
|||||||
elseif targetobject:IsInstanceOf("GROUP") then
|
elseif targetobject:IsInstanceOf("GROUP") then
|
||||||
self:T("SEAD Check GROUP")
|
self:T("SEAD Check GROUP")
|
||||||
local attribute = targetobject:GetAttribute()
|
local attribute = targetobject:GetAttribute()
|
||||||
if attribute == GROUP.Attribute.GROUND_SAM or attribute == GROUP.Attribute.GROUND_AAA or attribute == GROUP.Attribute.GROUND_EWR then
|
if self:_IsAttributeSead(attribute) then
|
||||||
type = AUFTRAG.Type.SEAD
|
type = AUFTRAG.Type.SEAD
|
||||||
--ttstype = "suppress air defense"
|
--ttstype = "suppress air defense"
|
||||||
ttstype = self.gettext:GetEntry("SEADTTS",self.locale)
|
ttstype = self.gettext:GetEntry("SEADTTS",self.locale)
|
||||||
end
|
end
|
||||||
elseif targetobject:IsInstanceOf("SET_GROUP") then
|
elseif targetobject:IsInstanceOf("SET_GROUP") then
|
||||||
self:T("SEAD Check SET_GROUP")
|
self:T("SEAD Check SET_GROUP")
|
||||||
targetobject:ForEachGroup(
|
targetobject:ForEachGroup(
|
||||||
function (group)
|
function (group)
|
||||||
local attribute = group:GetAttribute()
|
local attribute = group:GetAttribute()
|
||||||
if attribute == GROUP.Attribute.GROUND_SAM or attribute == GROUP.Attribute.GROUND_AAA or attribute == GROUP.Attribute.GROUND_EWR then
|
if self:_IsAttributeSead(attribute) then
|
||||||
type = AUFTRAG.Type.SEAD
|
type = AUFTRAG.Type.SEAD
|
||||||
--ttstype = "suppress air defense"
|
--ttstype = "suppress air defense"
|
||||||
ttstype = self.gettext:GetEntry("SEADTTS",self.locale)
|
ttstype = self.gettext:GetEntry("SEADTTS",self.locale)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
elseif targetobject:IsInstanceOf("SET_UNIT") then
|
elseif targetobject:IsInstanceOf("SET_UNIT") then
|
||||||
self:T("SEAD Check SET_UNIT")
|
self:T("SEAD Check SET_UNIT")
|
||||||
@ -2313,19 +2401,21 @@ function PLAYERTASKCONTROLLER:_BuildMenus(Client)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- [User] Add agent group to INTEL detection
|
--- [User] Add agent group to INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this.
|
||||||
-- @param #PLAYERTASKCONTROLLER self
|
-- @param #PLAYERTASKCONTROLLER self
|
||||||
-- @param Wrapper.Group#GROUP Recce Group of agents. Can also be an @{Ops.OpsGroup#OPSGROUP} object.
|
-- @param Wrapper.Group#GROUP Recce Group of agents. Can also be an @{Ops.OpsGroup#OPSGROUP} object.
|
||||||
-- @return #PLAYERTASKCONTROLLER self
|
-- @return #PLAYERTASKCONTROLLER self
|
||||||
function PLAYERTASKCONTROLLER:AddAgent(Recce)
|
function PLAYERTASKCONTROLLER:AddAgent(Recce)
|
||||||
self:T(self.lid.."AddAgent: "..Recce:GetName())
|
self:T(self.lid.."AddAgent")
|
||||||
if self.Intel then
|
if self.Intel then
|
||||||
self.Intel:AddAgent(Recce)
|
self.Intel:AddAgent(Recce)
|
||||||
|
else
|
||||||
|
self:E(self.lid.."NO detection has been set up (yet)!")
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- [User] Add accept zone to INTEL detection
|
--- [User] Add accept zone to INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this.
|
||||||
-- @param #PLAYERTASKCONTROLLER self
|
-- @param #PLAYERTASKCONTROLLER self
|
||||||
-- @param Core.Zone#ZONE AcceptZone Add a zone to the accept zone set.
|
-- @param Core.Zone#ZONE AcceptZone Add a zone to the accept zone set.
|
||||||
-- @return #PLAYERTASKCONTROLLER self
|
-- @return #PLAYERTASKCONTROLLER self
|
||||||
@ -2333,11 +2423,13 @@ function PLAYERTASKCONTROLLER:AddAcceptZone(AcceptZone)
|
|||||||
self:T(self.lid.."AddAcceptZone")
|
self:T(self.lid.."AddAcceptZone")
|
||||||
if self.Intel then
|
if self.Intel then
|
||||||
self.Intel:AddAcceptZone(AcceptZone)
|
self.Intel:AddAcceptZone(AcceptZone)
|
||||||
|
else
|
||||||
|
self:E(self.lid.."NO detection has been set up (yet)!")
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- [User] Add reject zone to INTEL detection
|
--- [User] Add reject zone to INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this.
|
||||||
-- @param #PLAYERTASKCONTROLLER self
|
-- @param #PLAYERTASKCONTROLLER self
|
||||||
-- @param Core.Zone#ZONE RejectZone Add a zone to the reject zone set.
|
-- @param Core.Zone#ZONE RejectZone Add a zone to the reject zone set.
|
||||||
-- @return #PLAYERTASKCONTROLLER self
|
-- @return #PLAYERTASKCONTROLLER self
|
||||||
@ -2345,11 +2437,13 @@ function PLAYERTASKCONTROLLER:AddRejectZone(RejectZone)
|
|||||||
self:T(self.lid.."AddRejectZone")
|
self:T(self.lid.."AddRejectZone")
|
||||||
if self.Intel then
|
if self.Intel then
|
||||||
self.Intel:AddRejectZone(RejectZone)
|
self.Intel:AddRejectZone(RejectZone)
|
||||||
|
else
|
||||||
|
self:E(self.lid.."NO detection has been set up (yet)!")
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- [User] Remove accept zone from INTEL detection
|
--- [User] Remove accept zone from INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this.
|
||||||
-- @param #PLAYERTASKCONTROLLER self
|
-- @param #PLAYERTASKCONTROLLER self
|
||||||
-- @param Core.Zone#ZONE AcceptZone Add a zone to the accept zone set.
|
-- @param Core.Zone#ZONE AcceptZone Add a zone to the accept zone set.
|
||||||
-- @return #PLAYERTASKCONTROLLER self
|
-- @return #PLAYERTASKCONTROLLER self
|
||||||
@ -2357,11 +2451,13 @@ function PLAYERTASKCONTROLLER:RemoveAcceptZone(AcceptZone)
|
|||||||
self:T(self.lid.."RemoveAcceptZone")
|
self:T(self.lid.."RemoveAcceptZone")
|
||||||
if self.Intel then
|
if self.Intel then
|
||||||
self.Intel:RemoveAcceptZone(AcceptZone)
|
self.Intel:RemoveAcceptZone(AcceptZone)
|
||||||
|
else
|
||||||
|
self:E(self.lid.."NO detection has been set up (yet)!")
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- [User] Remove reject zone from INTEL detection
|
--- [User] Remove reject zone from INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this.
|
||||||
-- @param #PLAYERTASKCONTROLLER self
|
-- @param #PLAYERTASKCONTROLLER self
|
||||||
-- @param Core.Zone#ZONE RejectZone Add a zone to the reject zone set.
|
-- @param Core.Zone#ZONE RejectZone Add a zone to the reject zone set.
|
||||||
-- @return #PLAYERTASKCONTROLLER self
|
-- @return #PLAYERTASKCONTROLLER self
|
||||||
@ -2369,6 +2465,8 @@ function PLAYERTASKCONTROLLER:RemoveRejectZone(RejectZone)
|
|||||||
self:T(self.lid.."RemoveRejectZone")
|
self:T(self.lid.."RemoveRejectZone")
|
||||||
if self.Intel then
|
if self.Intel then
|
||||||
self.Intel:RemoveRejectZone(RejectZone)
|
self.Intel:RemoveRejectZone(RejectZone)
|
||||||
|
else
|
||||||
|
self:E(self.lid.."NO detection has been set up (yet)!")
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -2392,7 +2490,7 @@ function PLAYERTASKCONTROLLER:SetupIntel(RecceName)
|
|||||||
self.RecceSet = SET_GROUP:New():FilterCoalitions(self.CoalitionName):FilterPrefixes(RecceName):FilterStart()
|
self.RecceSet = SET_GROUP:New():FilterCoalitions(self.CoalitionName):FilterPrefixes(RecceName):FilterStart()
|
||||||
self.Intel = INTEL:New(self.RecceSet,self.Coalition,self.Name.."-Intel")
|
self.Intel = INTEL:New(self.RecceSet,self.Coalition,self.Name.."-Intel")
|
||||||
self.Intel:SetClusterAnalysis(true,false,false)
|
self.Intel:SetClusterAnalysis(true,false,false)
|
||||||
self.Intel:SetClusterRadius(self.ClusterRadius or 500)
|
self.Intel:SetClusterRadius(self.ClusterRadius or 0.5)
|
||||||
self.Intel.statusupdate = 25
|
self.Intel.statusupdate = 25
|
||||||
self.Intel:SetAcceptZones()
|
self.Intel:SetAcceptZones()
|
||||||
self.Intel:SetRejectZones()
|
self.Intel:SetRejectZones()
|
||||||
@ -2709,4 +2807,3 @@ end
|
|||||||
-- END PLAYERTASKCONTROLLER
|
-- END PLAYERTASKCONTROLLER
|
||||||
-----
|
-----
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1878,7 +1878,7 @@ function UTILS.GenerateVHFrequencies()
|
|||||||
-- known and sorted map-wise NDBs in kHz
|
-- known and sorted map-wise NDBs in kHz
|
||||||
local _skipFrequencies = {
|
local _skipFrequencies = {
|
||||||
214,274,291.5,295,297.5,
|
214,274,291.5,295,297.5,
|
||||||
300.5,304,307,309.5,311,312,312.5,316,
|
300.5,304,305,307,309.5,311,312,312.5,316,
|
||||||
320,324,328,329,330,332,336,337,
|
320,324,328,329,330,332,336,337,
|
||||||
342,343,348,351,352,353,358,
|
342,343,348,351,352,353,358,
|
||||||
363,365,368,372.5,374,
|
363,365,368,372.5,374,
|
||||||
|
|||||||
@ -2385,10 +2385,10 @@ function GROUP:GetAttribute()
|
|||||||
local infantry=self:HasAttribute("Infantry")
|
local infantry=self:HasAttribute("Infantry")
|
||||||
local artillery=self:HasAttribute("Artillery")
|
local artillery=self:HasAttribute("Artillery")
|
||||||
local tank=self:HasAttribute("Old Tanks") or self:HasAttribute("Modern Tanks")
|
local tank=self:HasAttribute("Old Tanks") or self:HasAttribute("Modern Tanks")
|
||||||
local aaa=self:HasAttribute("AAA")
|
local aaa=self:HasAttribute("AAA") and (not self:HasAttribute("SAM elements"))
|
||||||
local ewr=self:HasAttribute("EWR")
|
local ewr=self:HasAttribute("EWR")
|
||||||
local ifv=self:HasAttribute("IFV")
|
local ifv=self:HasAttribute("IFV")
|
||||||
local sam=self:HasAttribute("SAM elements") and (not self:HasAttribute("AAA"))
|
local sam=self:HasAttribute("SAM elements") or self:HasAttribute("Optical Tracker")
|
||||||
-- Train
|
-- Train
|
||||||
local train=self:GetCategory()==Group.Category.TRAIN
|
local train=self:GetCategory()==Group.Category.TRAIN
|
||||||
|
|
||||||
@ -2431,12 +2431,12 @@ function GROUP:GetAttribute()
|
|||||||
attribute=GROUP.Attribute.GROUND_ARTILLERY
|
attribute=GROUP.Attribute.GROUND_ARTILLERY
|
||||||
elseif tank then
|
elseif tank then
|
||||||
attribute=GROUP.Attribute.GROUND_TANK
|
attribute=GROUP.Attribute.GROUND_TANK
|
||||||
|
elseif ifv then
|
||||||
|
attribute=GROUP.Attribute.GROUND_IFV
|
||||||
elseif apc then
|
elseif apc then
|
||||||
attribute=GROUP.Attribute.GROUND_APC
|
attribute=GROUP.Attribute.GROUND_APC
|
||||||
elseif infantry then
|
elseif infantry then
|
||||||
attribute=GROUP.Attribute.GROUND_INFANTRY
|
attribute=GROUP.Attribute.GROUND_INFANTRY
|
||||||
elseif ifv then
|
|
||||||
attribute=GROUP.Attribute.GROUND_IFV
|
|
||||||
elseif truck then
|
elseif truck then
|
||||||
attribute=GROUP.Attribute.GROUND_TRUCK
|
attribute=GROUP.Attribute.GROUND_TRUCK
|
||||||
elseif train then
|
elseif train then
|
||||||
|
|||||||
@ -830,7 +830,9 @@ function UNIT:HasSEAD()
|
|||||||
|
|
||||||
local HasSEAD = false
|
local HasSEAD = false
|
||||||
if UnitSEADAttributes["RADAR_BAND1_FOR_ARM"] and UnitSEADAttributes["RADAR_BAND1_FOR_ARM"] == true or
|
if UnitSEADAttributes["RADAR_BAND1_FOR_ARM"] and UnitSEADAttributes["RADAR_BAND1_FOR_ARM"] == true or
|
||||||
UnitSEADAttributes["RADAR_BAND2_FOR_ARM"] and UnitSEADAttributes["RADAR_BAND2_FOR_ARM"] == true then
|
UnitSEADAttributes["RADAR_BAND2_FOR_ARM"] and UnitSEADAttributes["RADAR_BAND2_FOR_ARM"] == true or
|
||||||
|
UnitSEADAttributes["Optical Tracker"] and UnitSEADAttributes["Optical Tracker"] == true
|
||||||
|
then
|
||||||
HasSEAD = true
|
HasSEAD = true
|
||||||
end
|
end
|
||||||
return HasSEAD
|
return HasSEAD
|
||||||
@ -1067,7 +1069,7 @@ function UNIT:GetThreatLevel()
|
|||||||
if Descriptor then
|
if Descriptor then
|
||||||
|
|
||||||
local Attributes = Descriptor.attributes
|
local Attributes = Descriptor.attributes
|
||||||
|
|
||||||
if self:IsGround() then
|
if self:IsGround() then
|
||||||
|
|
||||||
local ThreatLevels = {
|
local ThreatLevels = {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user