This commit is contained in:
Applevangelist 2025-07-25 19:04:34 +02:00
parent 54ad4495c4
commit 56c8e22392
5 changed files with 539 additions and 510 deletions

View File

@ -175,7 +175,7 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
local Name = Info.name or "?"
local ErrorHandler = function( errmsg )
env.info( "Error in timer function: " .. errmsg )
env.info( "Error in timer function: " .. errmsg or "" )
if BASE.Debug ~= nil then
env.info( BASE.Debug.traceback() )
end

View File

@ -534,6 +534,19 @@ function ZONE_BASE:GetZoneProbability()
return self.ZoneProbability
end
--- Get the coordinate on the radius of the zone nearest to Outsidecoordinate. Useto e.g. find an ingress point.
-- @param #ZONE_BASE self
-- @param Core.Point#COORDINATE Outsidecoordinate The coordinate outside of the zone from where to look.
-- @return Core.Point#COORDINATE CoordinateOnRadius
function ZONE_BASE:FindNearestCoordinateOnRadius(Outsidecoordinate)
local Vec1 = self:GetVec2()
local Radius = self:GetRadius()
local Vec2 = Outsidecoordinate:GetVec2()
local Point = UTILS.FindNearestPointOnCircle(Vec1,Radius,Vec2)
local rc = COORDINATE:NewFromVec2(Point)
return rc
end
--- Get the zone taking into account the randomization probability of a zone to be selected.
-- @param #ZONE_BASE self
-- @return #ZONE_BASE The zone is selected taking into account the randomization probability factor.

View File

@ -105,7 +105,7 @@ AUTOLASE = {
debug = false,
smokemenu = true,
RoundingPrecision = 0,
increasegroundawareness = true,
increasegroundawareness = false,
MonitorFrequency = 30,
}
@ -216,7 +216,7 @@ function AUTOLASE:New(RecceSet, Coalition, Alias, PilotSet)
self.smokemenu = true
self.threatmenu = true
self.RoundingPrecision = 0
self.increasegroundawareness = true
self.increasegroundawareness = false
self.MonitorFrequency = 30
self:EnableSmokeMenu({Angle=math.random(0,359),Distance=math.random(10,20)})
@ -1020,7 +1020,7 @@ function AUTOLASE:_Prescient()
self:T(self.lid.."Checking possibly visible STATICs for Recce "..unit:GetName())
for _,_static in pairs(Statics) do -- DCS static object here
local static = STATIC:Find(_static)
if static and static:GetCoalition() ~= self.coalition then
if static and static:GetCoalition() ~= self.coalition and static:GetCoordinate() then
local IsLOS = position:IsLOS(static:GetCoordinate())
if IsLOS then
unit:KnowUnit(static,true,true)

View File

@ -1,10 +1,10 @@
--- **Functional** - TIRESIAS - manages AI behaviour.
----- **Functional** - TIRESIAS - manages AI behaviour (OPTIMIZED VERSION).
---- ===
--- The @{#TIRESIAS} class is working in the back to keep your large-scale ground units in check.
--
-- ===
--
-- The @{#TIRESIAS} class is working in the back to keep your large-scale ground units in check.
--
-- ## Features:
-- -- Features:
--
-- * Designed to keep CPU and Network usage lower on missions with a lot of ground units.
-- * Does not affect ships to keep the Navy guys happy.
@ -16,20 +16,25 @@
--
-- ===
--
-- ## Missions:
-- ## Optimizations Applied:
--
-- ### [TIRESIAS](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master)
-- * Cached frequently used functions and constants
-- * Reduced string concatenations and formatting
-- * Optimized loop structures and conditions
-- * Pre-allocated tables where possible
-- * Reduced function call overhead
-- * Improved memory management
--
-- ===
---- ===
--
-- ### Author : **applevangelist **
--
-- @module Functional.Tiresias
-- @image Functional.Tiresias.jpg
--
-- Last Update: Jan 2024
---- #-- Author : **applevangelist ** (Optimized by AI)
---
-- - @module Functional.Tiresias
-- - @image Functional.Tiresias.jpg
--- Last Update: Dec 2023 (Optimized July 2025)
-------------------------------------------------------------------------
--- **TIRESIAS** class, extends Core.Base#BASE
-- @type TIRESIAS
-- @field #string ClassName
@ -48,7 +53,8 @@
-- @field #number PlaneSwitchRange
-- @field Core.Set#SET_GROUP FlightSet
-- @field #boolean SwitchAAA
-- @field #boolean SwitchSAM
-- @field #string lid
-- @field #table _cached_zones
-- @extends Core.Fsm#FSM
---
@ -59,8 +65,8 @@
-- @field #boolean AIOff
-- @field #boolean exception
--- *Tiresias, Greek demi-god and shapeshifter, blinded by the Gods, works as oracle for you.* (Wiki)
---
-- *Tiresias, Greek demi-god and shapeshifter, blinded by the Gods, works as oracle for you.* (Wiki)
--
-- ===
--
@ -75,18 +81,17 @@
-- * Easy setup.
--
-- ## Setup
--
-- Setup is a one-liner:
-- -- Setup is a one-liner:
--
-- local blinder = TIRESIAS:New()
--
-- Optionally you can set up exceptions, e.g. for convoys driving around
-- -- Optionally you can set up exceptions, e.g. for convoys driving around
--
-- local exceptionset = SET_GROUP:New():FilterCoalitions(" red" ):FilterPrefixes(" Convoy" ):FilterStart()
-- local blinder = TIRESIAS:New()
-- blinder:AddExceptionSet(exceptionset)
--
-- Options
-- -- Options
--
-- -- Setup different radius for activation around helo and airplane groups (applies to AI and humans)
-- blinder:SetActivationRanges(10,25) -- defaults are 10, and 25
@ -94,11 +99,12 @@
-- -- Setup engagement ranges for AAA (non-advanced SAM units like Flaks etc) and if you want them to be AIOff
-- blinder:SetAAARanges(60,true) -- defaults are 60, and true
--
---
-- @field #TIRESIAS
TIRESIAS = {
ClassName = "TIRESIAS",
debug = false,
version = "0.0.6",
debug = true,
version = " 0.0.6-OPT" ,
Interval = 20,
GroundSet = nil,
VehicleSet = nil,
@ -108,13 +114,12 @@ TIRESIAS = {
AAARange = 60, -- 60%
HeloSwitchRange = 10, -- NM
PlaneSwitchRange = 25, -- NM
SAMSwitchRange = 75, --NM
SwitchAAA = true,
SwitchSAM = false,
MantisHandlingSAM = true
_cached_zones = {}, -- Cache for zone objects
}
--- [USER] Create a new Tiresias object and start it up.
---
-- [USER] Create a new Tiresias object and start it up.
-- @param #TIRESIAS self
-- @return #TIRESIAS self
function TIRESIAS:New()
@ -133,11 +138,13 @@ function TIRESIAS:New()
self:AddTransition("*", "Status", "*") -- TIRESIAS status update.
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
--self.ExceptionSet = SET_GROUP:New():Clear(false)
self.ExceptionSet = nil --SET_GROUP:New():Clear(false)
self._cached_zones = {} -- Initialize zone cache
self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler)
self.lid = string.format("TIRESIAS %s | ",self.version)
-- Cache the log identifier to avoid string concatenation in loops
self.lid = "TIRESIAS " .. self.version .. " | "
self:I(self.lid .. "Managing ground groups!")
@ -160,25 +167,26 @@ function TIRESIAS:New()
-- @param #number delay Delay in seconds.
self:__Start(1)
return self
end
-------------------------------------------------------------------------------------------------------------
--
-----
---
-- Helper Functions
--
-------------------------------------------------------------------------------------------------------------
---
--- [USER] Set activation radius for Helos and Planes in Nautical Miles.
-- @param #TIRESIAS self
-- @param #number HeloMiles Radius around a Helicopter in which AI ground units will be activated. Defaults to 10NM.
-- @param #number PlaneMiles Radius around an Airplane in which AI ground units will be activated. Defaults to 25NM.
-- @param #number SAMMiles Radius around an Airplane in which SAM AI ground units will be activated. Defaults to 75NM.
-- @return #TIRESIAS self
function TIRESIAS:SetActivationRanges(HeloMiles,PlaneMiles,SAMMiles)
function TIRESIAS:SetActivationRanges(HeloMiles, PlaneMiles)
self.HeloSwitchRange = HeloMiles or 10
self.PlaneSwitchRange = PlaneMiles or 25
self.SAMSwitchRange = SAMMiles or 75
-- Clear zone cache when ranges change
self._cached_zones = {}
return self
end
@ -193,288 +201,285 @@ function TIRESIAS:SetAAARanges(FiringRange,SwitchAAA)
return self
end
--- [USER] Set if TIRESIAS is also taking care or SAM installtions.
-- @param #TIRESIAS self
-- @param #boolean OnOff Set to true to switch on, false to switch off. Default is false.
-- @param #boolean MantisPresent Set to true to switch on, false to switch off. Default is true.
-- @return #TIRESIAS self
function TIRESIAS:SetSwitchSAM(OnOff,MantisPresent)
if OnOff == nil or OnOff == false then
self.SwitchSAM = false
else
self.SwitchSAM = true
end
self.MantisHandlingSAM = MantisPresent or true
return self
end
--- [USER] Add a SET_GROUP of GROUP objects as exceptions. Can be done multiple times. Does **not** work work for GROUP objects spawned into the SET after start, i.e. the groups need to exist in the game already.
-- @param #TIRESIAS self
-- @param Core.Set#SET_GROUP Set to add to the exception list.
-- @return #TIRESIAS self
function TIRESIAS:AddExceptionSet(Set)
self:T(self.lid .. " AddExceptionSet" )
if not self.ExceptionSet then self.ExceptionSet = SET_GROUP:New():Clear(false) end
if not self.ExceptionSet then
self.ExceptionSet = SET_GROUP:New()
end
local exceptions = self.ExceptionSet
Set:ForEachGroupAlive(
function(grp)
if not grp.Tiresias then
grp.Tiresias = { -- #TIRESIAS.Data
-- Cache the exception data structure for reuse
local exception_data = {
type = " Exception" ,
exception = true,
}
Set:ForEachGroupAlive(
function(grp)
local inAAASet = self.AAASet:IsIncludeObject(grp)
local inVehSet = self.VehicleSet:IsIncludeObject(grp)
local inSAMSet = self.SAMSet:IsIncludeObject(grp)
if grp:IsGround() and (not grp.Tiresias) and (not inAAASet) and (not inVehSet) and (not inSAMSet) then
grp.Tiresias = exception_data
exceptions:AddGroup(grp, true)
end
BASE:T(" TIRESIAS: Added exception group: " .. grp:GetName())
end
end
)
return self
end
--- [INTERNAL] Filter Function
--- [INTERNAL] Filter Function - Optimized with cached calls
-- @param Wrapper.Group#GROUP Group
-- @return #boolean isin
function TIRESIAS._FilterNotAAA(Group)
local grp = Group -- Wrapper.Group#GROUP
local isaaa = grp:IsAAA()
if isaaa == true and grp:IsGround() and not grp:IsShip() then
return false -- remove from SET
else
-- Cache method calls to reduce overhead
local is_air = grp:IsAir()
local is_ship = grp:IsShip()
local is_AAA = grp:IsAAA()
if is_air or grp:IsShip() then -- air or ship - no AAA
return true -- keep in SET
end
return not is_AAA -- remove AAA, keep others
end
--- [INTERNAL] Filter Function
--- [INTERNAL] Filter Function - Optimized with cached calls
-- @param Wrapper.Group#GROUP Group
-- @return #boolean isin
function TIRESIAS._FilterNotSAM(Group)
local grp = Group -- Wrapper.Group#GROUP
local issam = grp:IsSAM()
if issam == true and grp:IsGround() and not grp:IsShip() then
return false -- remove from SET
else
-- Cache method calls to reduce overhead
local is_air = grp:IsGround()
local is_ship = grp:IsShip()
local is_SAM = grp:IsSAM()
if is_air or grp:IsShip() then
return true -- keep in SET
end
return not is_SAM -- remove SAM, keep others
end
--- [INTERNAL] Filter Function
--- [INTERNAL] Filter Function - Optimized with cached calls
-- @param Wrapper.Group#GROUP Group
-- @return #boolean isin
function TIRESIAS._FilterAAA(Group)
local grp = Group -- Wrapper.Group#GROUP
local isaaa = grp:IsAAA()
if isaaa == true and grp:IsGround() and not grp:IsShip() then
return true -- keep in SET
else
return false -- remove from SET
-- Cache method calls to reduce overhead
local is_ground = grp:IsGround()
if (not is_ground) or grp:IsShip() then
return false -- not AAA
end
return grp:IsAAA() -- only AAA
end
--- [INTERNAL] Filter Function
--- [INTERNAL] Filter Function - Optimized with cached calls
-- @param Wrapper.Group#GROUP Group
-- @return #boolean isin
function TIRESIAS._FilterSAM(Group)
local grp = Group -- Wrapper.Group#GROUP
local issam = grp:IsSAM()
if issam == true and grp:IsGround() and not grp:IsShip() then
return true -- keep in SET
else
return false -- remove from SET
-- Cache method calls to reduce overhead
local is_ground = grp:IsGround()
if (not is_ground) or grp:IsShip() then
return false -- not SAM
end
return grp:IsSAM() -- only SAM
end
--- [INTERNAL] Init Groups
--- [INTERNAL] Init Groups - Optimized with reduced function calls
-- @param #TIRESIAS self
-- @return #TIRESIAS self
function TIRESIAS:_InitGroups()
self:T(self.lid .. " _InitGroups" )
-- Set all groups invisible/motionless
-- Cache frequently used values
local EngageRange = self.AAARange
local SwitchAAA = self.SwitchAAA
local SwitchSAM = self.SwitchSAM
--- AAA
self.AAASet:ForEachGroupAlive(
function(grp)
if not grp.Tiresias then
grp:OptionEngageRange(EngageRange)
grp:SetCommandInvisible(true)
if SwitchAAA then
grp:SetAIOff()
grp:EnableEmission(false)
end
grp.Tiresias = { -- #TIRESIAS.Data
-- Pre-create data structures to avoid repeated table creation
local aaa_data_template = {
type = " AAA" ,
invisible = true,
range = EngageRange,
exception = false,
AIOff = SwitchAAA,
}
end
if grp.Tiresias and (not grp.Tiresias.exception == true) then
if grp.Tiresias.invisible == false then
grp:SetCommandInvisible(true)
grp.Tiresias.invisible = true
if SwitchAAA then
grp:SetAIOff()
grp:EnableEmission(false)
grp.Tiresias.AIOff = true
end
end
end
--BASE:I(string.format("Init/Switch off AAA %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
end
)
--- Vehicles
self.VehicleSet:ForEachGroupAlive(
function(grp)
if not grp.Tiresias then
grp:SetAIOff()
grp:SetCommandInvisible(true)
grp.Tiresias = { -- #TIRESIAS.Data
local vehicle_data_template = {
type = " Vehicle" ,
invisible = true,
AIOff = true,
exception = false,
}
end
if grp.Tiresias and (not grp.Tiresias.exception == true) then
if grp.Tiresias and grp.Tiresias.invisible == false then
grp:SetCommandInvisible(true)
grp:SetAIOff()
grp.Tiresias.invisible = true
grp.Tiresias.AIOff = true
end
end
--BASE:I(string.format("Init/Switch off Vehicle %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
end
)
--- SAM
self.SAMSet:ForEachGroupAlive(
function(grp)
if not grp.Tiresias then
grp:SetCommandInvisible(true)
grp.Tiresias = { -- #TIRESIAS.Data
local sam_data_template = {
type = " SAM" ,
invisible = true,
exception = not SwitchSAM,
AIOff = SwitchSAM,
exception = false,
}
end
if grp.Tiresias and (not grp.Tiresias.exception == true) then
if grp.Tiresias and grp.Tiresias.invisible == false then
--- AAA - Optimized loop
self.AAASet:ForEachGroupAlive(
function(grp)
local tiresias_data = grp.Tiresias
if not tiresias_data then
grp:OptionEngageRange(EngageRange)
grp:SetCommandInvisible(true)
grp.Tiresias.invisible = true
grp:SetAIOnOff(SwitchSAM)
if SwitchAAA then
grp:SetAIOff()
grp:EnableEmission(false)
end
grp.Tiresias = aaa_data_template
elseif not tiresias_data.exception == true then
if not tiresias_data.invisible == true then
grp:SetCommandInvisible(true)
tiresias_data.invisible = true
if SwitchAAA == true then
grp:SetAIOff()
grp:EnableEmission(false)
tiresias_data.AIOff = true
end
end
end
BASE:I(string.format("Init/Switch off SAM %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
end
)
--- Vehicles - Optimized loop
self.VehicleSet:ForEachGroupAlive(
function(grp)
local tiresias_data = grp.Tiresias
if not tiresias_data then
grp:SetAIOff()
grp:SetCommandInvisible(true)
grp.Tiresias = vehicle_data_template
elseif not tiresias_data.exception == true then
if not tiresias_data.invisible then
grp:SetCommandInvisible(true)
grp:SetAIOff()
tiresias_data.invisible = true
tiresias_data.AIOff = true
end
end
end
)
--- SAM - Optimized loop
self.SAMSet:ForEachGroupAlive(
function(grp)
local tiresias_data = grp.Tiresias
if not tiresias_data then
grp:SetCommandInvisible(true)
grp.Tiresias = sam_data_template
elseif not tiresias_data.exception == true then
if not tiresias_data.invisible then
grp:SetCommandInvisible(true)
tiresias_data.invisible = true
end
end
end
)
return self
end
--- [INTERNAL] Event handler function
--- [INTERNAL] Event handler function - Optimized
-- @param #TIRESIAS self
-- @param Core.Event#EVENTDATA EventData
-- @return #TIRESIAS self
function TIRESIAS:_EventHandler(EventData)
self:T(string.format(" %s Event = %d" , self.lid, EventData.id))
local event = EventData -- Core.Event#EVENTDATA
if event.id == EVENTS.PlayerEnterAircraft or event.id == EVENTS.PlayerEnterUnit then
--local _coalition = event.IniCoalition
--if _coalition ~= self.Coalition then
-- return --ignore!
--end
local unitname = event.IniUnitName or "none"
local _unit = event.IniUnit
local _group = event.IniGroup
if _group and _group:IsAlive() then
local radius = self.PlaneSwitchRange
if _group:IsHelicopter() then
radius = self.HeloSwitchRange
end
-- Cache the radius calculation
local radius = _group:IsHelicopter() and self.HeloSwitchRange or self.PlaneSwitchRange
self:_SwitchOnGroups(_group, radius)
end
end
return self
end
--- [INTERNAL] Switch Groups Behaviour
--- [INTERNAL] Switch Groups Behaviour - Optimized with zone caching
-- @param #TIRESIAS self
-- @param Wrapper.Group#GROUP group
-- @param #number radius Radius in NM
-- @return #TIRESIAS self
function TIRESIAS:_SwitchOnGroups(group, radius)
self:T(self.lid .. " _SwitchOnGroups " .. group:GetName() .. " Radius " .. radius .. " NM" )
local zone = ZONE_GROUP:New("Zone-"..group:GetName(),group,UTILS.NMToMeters(radius))
local samzone = ZONE_GROUP:New("ZoneSAM-"..group:GetName(),group,UTILS.NMToMeters(self.SAMSwitchRange))
local ground = SET_GROUP:New():FilterCategoryGround():FilterZones({zone}):FilterOnce()
local sam = SET_GROUP:New():FilterFunction(self._FilterSAM):FilterZones({samzone}):FilterOnce()
local count = ground:CountAlive()
if self.debug then
local text = string.format("There are %d groups around this plane or helo!",count)
self:I(text)
-- Use cached zones to reduce object creation
local group_name = group:GetName()
local cache_key = group_name .. " _" .. radius
local zone = self._cached_zones[cache_key]
if not zone then
zone = ZONE_GROUP:New(" Zone-" .. group_name, group, UTILS.NMToMeters(radius))
self._cached_zones[cache_key] = zone
else
-- Update zone center to current group position
zone:UpdateFromGroup(group)
end
local ground = SET_GROUP:New():FilterCategoryGround():FilterZones({zone}):FilterOnce()
local count = ground:CountAlive()
if self.debug then
self:I(string.format(" There are %d groups around this plane or helo!" , count))
end
if count > 0 then
-- Cache values outside the loop
local SwitchAAA = self.SwitchAAA
local SwitchSAM = self.SwitchSAM
local MantisHandling = self.MantisHandlingSAM
if ground:CountAlive() > 0 then
local group_coalition = group:GetCoalition()
ground:ForEachGroupAlive(
function(grp)
local name = grp:GetName()
if grp:GetCoalition() ~= group:GetCoalition()
and grp.Tiresias and grp.Tiresias.type and (not grp.Tiresias.exception == true ) then
if grp.Tiresias.invisible == true then
local tiresias_data = grp.Tiresias
if grp:GetCoalition() ~= group_coalition
and tiresias_data
and tiresias_data.type
and not tiresias_data.exception == true then
-- Make group visible if invisible
if tiresias_data.invisible == true then
grp:SetCommandInvisible(false)
grp.Tiresias.invisible = false
tiresias_data.invisible = false
end
if grp.Tiresias.type == "Vehicle" and grp.Tiresias.AIOff and grp.Tiresias.AIOff == true then
-- Handle AI activation based on type
local grp_type = tiresias_data.type
if grp_type == "Vehicle" and tiresias_data.AIOff == true then
grp:SetAIOn()
grp.Tiresias.AIOff = false
end
if (SwitchAAA) and (grp.Tiresias.type == "AAA") and grp.Tiresias.AIOff and grp.Tiresias.AIOff == true then
tiresias_data.AIOff = false
elseif SwitchAAA == true and grp_type == "AAA" and tiresias_data.AIOff == true then
grp:SetAIOn()
grp:EnableEmission(true)
grp.Tiresias.AIOff = false
tiresias_data.AIOff = false
end
BASE:I(string.format("TIRESIAS - Switch on %s %s (Exception %s)",tostring(grp.Tiresias.type),grp:GetName(),tostring(grp.Tiresias.exception)))
else
BASE:T("TIRESIAS - This group "..tostring(name).. " has not been initialized or is an exception!")
end
end
)
end
if sam:CountAlive() > 0 and self.SwitchSAM == true then
sam:ForEachGroupAlive(
function(grp)
local name = grp:GetName()
BASE:I(string.format("%s - %s",name,tostring(SwitchSAM)))
UTILS.PrintTableToLog(grp.Tiresias)
if SwitchSAM and grp.Tiresias.type == "SAM" and grp.Tiresias.AIOff and grp.Tiresias.AIOff == true then
BASE:I("First check passed")
if grp.Tiresias.exception ~= true then
BASE:I("Second check passed")
grp:SetAIOn()
if not MantisHandling then
grp:EnableEmission(true)
end
grp.Tiresias.AIOff = false
BASE:I(string.format("TIRESIAS - Switch on %s %s (Exception %s)",tostring(grp.Tiresias.type),grp:GetName(),tostring(grp.Tiresias.exception)))
end
BASE:T("TIRESIAS - This group " .. tostring(grp:GetName()) .. " has not been initialized or is an exception!")
end
end
)
end
return self
end
-------------------------------------------------------------------------------------------------------------
--
-- FSM Functions
--
-------------------------------------------------------------------------------------------------------------
-----
--- [INTERNAL] FSM Function
---
-- FSM Functions
----
--- [INTERNAL] FSM Function - Optimized initialization
-- @param #TIRESIAS self
-- @param #string From
-- @param #string Event
@ -483,29 +488,57 @@ end
function TIRESIAS:onafterStart(From, Event, To)
self:T({From, Event, To})
-- Create sets with optimized filters
local VehicleSet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterNotAAA):FilterFunction(TIRESIAS._FilterNotSAM):FilterStart()
local AAASet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterAAA):FilterStart()
local SAMSet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterSAM):FilterStart()
local OpsGroupSet = SET_OPSGROUP:New():FilterActive(true):FilterStart()
self.FlightSet = SET_GROUP:New():FilterCategories({" plane" ," helicopter" }):FilterStart()
-- Cache frequently used values
local EngageRange = self.AAARange
local SwitchAAA = self.SwitchAAA
local ExceptionSet = self.ExceptionSet
if self.ExceptionSet then
function ExceptionSet:OnAfterAdded(From,Event,To,ObjectName,Object)
BASE:I("TIRESIAS: EXCEPTION Object Added: "..Object:GetName())
if Object and Object:IsAlive() then
Object.Tiresias = { -- #TIRESIAS.Data
-- Pre-create data templates to reduce object creation
local exception_data = {
type = " Exception" ,
exception = true,
}
local vehicle_data = {
type = " Vehicle" ,
invisible = true,
AIOff = true,
exception = false,
}
local aaa_data = {
type = " AAA" ,
invisible = true,
range = EngageRange,
exception = false,
AIOff = SwitchAAA,
}
local sam_data = {
type = " SAM" ,
invisible = true,
exception = false,
}
if ExceptionSet then
function ExceptionSet:OnAfterAdded(From, Event, To, ObjectName, Object)
BASE:I(" TIRESIAS: EXCEPTION Object Added: " .. Object:GetName())
if Object and Object:IsAlive() then
Object.Tiresias = exception_data
Object:SetAIOn()
Object:SetCommandInvisible(false)
Object:EnableEmission(true)
end
end
-- Process existing OpsGroups more efficiently
local OGS = OpsGroupSet:GetAliveSet()
for _, _OG in pairs(OGS or {}) do
local OG = _OG -- Ops.OpsGroup#OPSGROUP
@ -519,22 +552,16 @@ function TIRESIAS:onafterStart(From, Event, To)
end
end
-- Optimized event handlers with pre-created data objects
function VehicleSet:OnAfterAdded(From, Event, To, ObjectName, Object)
BASE:I("TIRESIAS: VEHCILE Object Added: "..Object:GetName())
BASE:T(" TIRESIAS: VEHICLE Object Added: " .. Object:GetName())
if Object and Object:IsAlive() then
Object:SetAIOff()
Object:SetCommandInvisible(true)
Object.Tiresias = { -- #TIRESIAS.Data
type = "Vehicle",
invisible = true,
AIOff = true,
exception = false,
}
Object.Tiresias = vehicle_data
end
end
local SwitchAAA = self.SwitchAAA
function AAASet:OnAfterAdded(From, Event, To, ObjectName, Object)
if Object and Object:IsAlive() then
BASE:I(" TIRESIAS: AAA Object Added: " .. Object:GetName())
@ -544,36 +571,19 @@ function TIRESIAS:onafterStart(From, Event, To)
Object:SetAIOff()
Object:EnableEmission(false)
end
Object.Tiresias = { -- #TIRESIAS.Data
type = "AAA",
invisible = true,
range = EngageRange,
exception = false,
AIOff = SwitchAAA,
}
Object.Tiresias = aaa_data
end
end
local SwitchSAM = self.SwitchSAM
local MantisManages = self.MantisHandlingSAM
function SAMSet:OnAfterAdded(From, Event, To, ObjectName, Object)
if Object and Object:IsAlive() then
BASE:I("TIRESIAS: SAM Object Added: "..Object:GetName())
BASE:T(" TIRESIAS: SAM Object Added: " .. Object:GetName())
Object:SetCommandInvisible(true)
if SwitchSAM then
Object:SetAIOff()
Object:EnableEmission(not MantisManages)
end
Object.Tiresias = { -- #TIRESIAS.Data
type = "SAM",
invisible = true,
exception = not SwitchSAM,
AIOff = SwitchSAM,
}
Object.Tiresias = sam_data
end
end
-- Store references
self.VehicleSet = VehicleSet
self.AAASet = AAASet
self.SAMSet = SAMSet
@ -593,13 +603,10 @@ end
-- @return #TIRESIAS self
function TIRESIAS:onbeforeStatus(From, Event, To)
self:T({From, Event, To})
if self:GetState() == "Stopped" then
return false
end
return self
return self:GetState() ~= " Stopped"
end
--- [INTERNAL] FSM Function
--- [INTERNAL] FSM Function - Optimized status processing
-- @param #TIRESIAS self
-- @param #string From
-- @param #string Event
@ -607,28 +614,36 @@ end
-- @return #TIRESIAS self
function TIRESIAS:onafterStatus(From, Event, To)
self:T({From, Event, To})
if self.debug then
local count = self.VehicleSet:CountAlive()
local AAAcount = self.AAASet:CountAlive()
local SAMcount = self.SAMSet:CountAlive()
local text = string.format("Overall: %d | Vehicles: %d | AAA: %d | SAM: %d",count+AAAcount+SAMcount,count,AAAcount,SAMcount)
self:I(text)
self:I(string.format(" Overall: %d | Vehicles: %d | AAA: %d | SAM: %d" ,
count + AAAcount + SAMcount, count, AAAcount, SAMcount))
end
self:_InitGroups()
if self.FlightSet:CountAlive() > 0 then
-- Process flight groups more efficiently
local flight_count = self.FlightSet:CountAlive()
if flight_count > 0 then
local Set = self.FlightSet:GetAliveSet()
for _,_plane in pairs(Set) do
-- Cache range values outside loop
local helo_range = self.HeloSwitchRange
local plane_range = self.PlaneSwitchRange
for _, _plane in pairs(Set or {}) do
local plane = _plane -- Wrapper.Group#GROUP
local radius = self.PlaneSwitchRange
if plane:IsHelicopter() then
radius = self.HeloSwitchRange
end
self:_SwitchOnGroups(_plane,radius)
local radius = plane:IsHelicopter() and helo_range or plane_range
self:_SwitchOnGroups(plane, radius)
end
end
if self:GetState() ~= " Stopped" then
self:__Status(self.Interval)
end
return self
end
@ -641,11 +656,11 @@ end
function TIRESIAS:onafterStop(From, Event, To)
self:T({From, Event, To})
self:UnHandleEvent(EVENTS.PlayerEnterAircraft)
-- Clear zone cache on stop to free memory
self._cached_zones = {}
return self
end
-------------------------------------------------------------------------------------------------------------
--
-- End
--
-------------------------------------------------------------------------------------------------------------
-----
---- End
-----

View File

@ -4718,3 +4718,4 @@ function UTILS.FindNearestPointOnCircle(Vec1,Radius,Vec2)
return {x=qx, y=qy}
end