mirror of
https://github.com/iTracerFacer/DCS_MissionDev.git
synced 2025-12-03 04:14:46 +00:00
Deployed JTAC's working for the first time. Yay chatgpt.
This commit is contained in:
parent
be4bbe85c5
commit
80669513b8
@ -169,7 +169,7 @@ CTLD.Config = {
|
|||||||
-- 2 = INFO - Important state changes, initialization, cleanup (default for production)
|
-- 2 = INFO - Important state changes, initialization, cleanup (default for production)
|
||||||
-- 3 = VERBOSE - Detailed operational info (zone validation, menus, builds, MEDEVAC events)
|
-- 3 = VERBOSE - Detailed operational info (zone validation, menus, builds, MEDEVAC events)
|
||||||
-- 4 = DEBUG - Everything including hover checks, crate pickups, detailed troop spawns
|
-- 4 = DEBUG - Everything including hover checks, crate pickups, detailed troop spawns
|
||||||
LogLevel = 2, -- lowered from DEBUG (4) to INFO (2) for production performance
|
LogLevel = 4, -- lowered from DEBUG (4) to INFO (2) for production performance
|
||||||
MessageDuration = 15, -- seconds for on-screen messages
|
MessageDuration = 15, -- seconds for on-screen messages
|
||||||
|
|
||||||
-- === Menu & Catalog ===
|
-- === Menu & Catalog ===
|
||||||
@ -298,6 +298,7 @@ CTLD.Config = {
|
|||||||
|
|
||||||
JTAC = {
|
JTAC = {
|
||||||
Enabled = true,
|
Enabled = true,
|
||||||
|
Verbose = true, -- when true, emit detailed JTAC registration & target scan logs
|
||||||
AutoLase = {
|
AutoLase = {
|
||||||
Enabled = true,
|
Enabled = true,
|
||||||
SearchRadius = 8000, -- meters to scan for enemy targets
|
SearchRadius = 8000, -- meters to scan for enemy targets
|
||||||
@ -319,7 +320,7 @@ CTLD.Config = {
|
|||||||
Enabled = true,
|
Enabled = true,
|
||||||
Duration = 15,
|
Duration = 15,
|
||||||
},
|
},
|
||||||
Verbose = true, -- when true, emit detailed JTAC registration & target scan logs
|
|
||||||
},
|
},
|
||||||
|
|
||||||
-- === Combat Automation ===
|
-- === Combat Automation ===
|
||||||
@ -3294,6 +3295,14 @@ function CTLD:New(cfg)
|
|||||||
local ok, err = pcall(function() o:_tickJTACs() end)
|
local ok, err = pcall(function() o:_tickJTACs() end)
|
||||||
if not ok then _logError('JTAC tick scheduler error: '..tostring(err)) end
|
if not ok then _logError('JTAC tick scheduler error: '..tostring(err)) end
|
||||||
end, {}, jtacInterval, jtacInterval)
|
end, {}, jtacInterval, jtacInterval)
|
||||||
|
_logInfo(string.format('JTAC init: Enabled=TRUE AutoLase=%s SearchRadius=%s Refresh=%s IdleRescan=%s LockType=%s Verbose=%s Interval=%.1f',
|
||||||
|
tostring(o.Config.JTAC.AutoLase and o.Config.JTAC.AutoLase.Enabled ~= false),
|
||||||
|
tostring(o.Config.JTAC.AutoLase and o.Config.JTAC.AutoLase.SearchRadius),
|
||||||
|
tostring(o.Config.JTAC.AutoLase and o.Config.JTAC.AutoLase.RefreshSeconds),
|
||||||
|
tostring(o.Config.JTAC.AutoLase and o.Config.JTAC.AutoLase.IdleRescanSeconds),
|
||||||
|
tostring(o.Config.JTAC.LockType),
|
||||||
|
tostring(o.Config.JTAC.Verbose),
|
||||||
|
jtacInterval))
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(CTLD._instances, o)
|
table.insert(CTLD._instances, o)
|
||||||
@ -3861,6 +3870,10 @@ function CTLD:BuildGroupMenus(group)
|
|||||||
CMD('Clear All MEDEVAC Missions', medevacAdminRoot, function() self:ClearAllMEDEVACMissions(group) end)
|
CMD('Clear All MEDEVAC Missions', medevacAdminRoot, function() self:ClearAllMEDEVACMissions(group) end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Operations (root) -> List JTAC Status (placed at bottom of Operations)
|
||||||
|
CMD('List JTAC Status', opsRoot, function() self:ListJTACStatus(group) end)
|
||||||
|
CMD('JTAC Diagnostics', opsRoot, function() self:JTACDiagnostics(group) end)
|
||||||
|
|
||||||
-- Logistics -> Request Crate and Recipe Info
|
-- Logistics -> Request Crate and Recipe Info
|
||||||
CMD('Show Onboard Manifest', logRoot, function() self:ShowOnboardManifest(group) end)
|
CMD('Show Onboard Manifest', logRoot, function() self:ShowOnboardManifest(group) end)
|
||||||
local reqRoot = MENU_GROUP:New(group, 'Request Crate', logRoot)
|
local reqRoot = MENU_GROUP:New(group, 'Request Crate', logRoot)
|
||||||
@ -4999,6 +5012,9 @@ function CTLD:BuildSpecificAtGroup(group, recipeKey, opts)
|
|||||||
_eventSend(self, group, nil, 'build_started', { build = def.description or recipeKey })
|
_eventSend(self, group, nil, 'build_started', { build = def.description or recipeKey })
|
||||||
local g = _coalitionAddGroup(def.side or self.Side, def.category or Group.Category.GROUND, gdata, self.Config)
|
local g = _coalitionAddGroup(def.side or self.Side, def.category or Group.Category.GROUND, gdata, self.Config)
|
||||||
if not g then _eventSend(self, group, nil, 'build_failed', { reason = 'DCS group spawn error' }); return end
|
if not g then _eventSend(self, group, nil, 'build_failed', { reason = 'DCS group spawn error' }); return end
|
||||||
|
if self.Config.JTAC and self.Config.JTAC.Verbose then
|
||||||
|
_logInfo(string.format('JTAC pre: post-build (composite) key=%s group=%s', tostring(recipeKey), tostring(g:getName())))
|
||||||
|
end
|
||||||
self:_maybeRegisterJTAC(recipeKey, def, g)
|
self:_maybeRegisterJTAC(recipeKey, def, g)
|
||||||
for reqKey,qty in pairs(def.requires) do consumeCrates(reqKey, qty or 0) end
|
for reqKey,qty in pairs(def.requires) do consumeCrates(reqKey, qty or 0) end
|
||||||
_eventSend(self, nil, self.Side, 'build_success_coalition', { build = def.description or recipeKey, player = _playerNameFromGroup(group) })
|
_eventSend(self, nil, self.Side, 'build_success_coalition', { build = def.description or recipeKey, player = _playerNameFromGroup(group) })
|
||||||
@ -5040,6 +5056,9 @@ function CTLD:BuildSpecificAtGroup(group, recipeKey, opts)
|
|||||||
_eventSend(self, group, nil, 'build_started', { build = def.description or recipeKey })
|
_eventSend(self, group, nil, 'build_started', { build = def.description or recipeKey })
|
||||||
local g = _coalitionAddGroup(def.side or self.Side, def.category or Group.Category.GROUND, gdata, self.Config)
|
local g = _coalitionAddGroup(def.side or self.Side, def.category or Group.Category.GROUND, gdata, self.Config)
|
||||||
if not g then _eventSend(self, group, nil, 'build_failed', { reason = 'DCS group spawn error' }); return end
|
if not g then _eventSend(self, group, nil, 'build_failed', { reason = 'DCS group spawn error' }); return end
|
||||||
|
if self.Config.JTAC and self.Config.JTAC.Verbose then
|
||||||
|
_logInfo(string.format('JTAC pre: post-build (single) key=%s group=%s', tostring(recipeKey), tostring(g:getName())))
|
||||||
|
end
|
||||||
self:_maybeRegisterJTAC(recipeKey, def, g)
|
self:_maybeRegisterJTAC(recipeKey, def, g)
|
||||||
consumeCrates(recipeKey, need)
|
consumeCrates(recipeKey, need)
|
||||||
_eventSend(self, nil, self.Side, 'build_success_coalition', { build = def.description or recipeKey, player = _playerNameFromGroup(group) })
|
_eventSend(self, nil, self.Side, 'build_success_coalition', { build = def.description or recipeKey, player = _playerNameFromGroup(group) })
|
||||||
@ -5083,9 +5102,26 @@ function CTLD:_definitionIsJTAC(def)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function CTLD:_maybeRegisterJTAC(recipeKey, def, dcsGroup)
|
function CTLD:_maybeRegisterJTAC(recipeKey, def, dcsGroup)
|
||||||
if not (self.Config.JTAC and self.Config.JTAC.Enabled) then return end
|
if not (self.Config.JTAC and self.Config.JTAC.Enabled) then
|
||||||
if not self:_definitionIsJTAC(def) then return end
|
if self.Config and self.Config.JTAC and self.Config.JTAC.Verbose then
|
||||||
if not dcsGroup then return end
|
_logInfo('JTAC check: JTAC disabled in config; skipping registration')
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not self:_definitionIsJTAC(def) then
|
||||||
|
if self.Config and self.Config.JTAC and self.Config.JTAC.Verbose then
|
||||||
|
local hasRoles = (def and type(def.roles) == 'table') and table.concat((function(r) local t={} for i,v in ipairs(r) do t[i]=tostring(v) end return t end)(def.roles),'|') or '(none)'
|
||||||
|
local hasJTAC = (def and type(def.jtac) == 'table') and 'yes' or 'no'
|
||||||
|
_logInfo(string.format('JTAC check: definition not JTAC. key=%s jtacTable=%s roles=%s isJTAC=%s', tostring(recipeKey), hasJTAC, hasRoles, tostring(def and def.isJTAC)))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not dcsGroup then
|
||||||
|
if self.Config and self.Config.JTAC and self.Config.JTAC.Verbose then
|
||||||
|
_logInfo(string.format('JTAC check: no DCS group to register. key=%s', tostring(recipeKey)))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
if self.Config.JTAC and self.Config.JTAC.Verbose then
|
if self.Config.JTAC and self.Config.JTAC.Verbose then
|
||||||
_logInfo(string.format('JTAC check: attempting registration. key=%s unitType=%s group=%s', tostring(recipeKey), tostring(def and def.unitType or def and def.description or 'n/a'), tostring(dcsGroup and dcsGroup.getName and dcsGroup:getName() or '')))
|
_logInfo(string.format('JTAC check: attempting registration. key=%s unitType=%s group=%s', tostring(recipeKey), tostring(def and def.unitType or def and def.description or 'n/a'), tostring(dcsGroup and dcsGroup.getName and dcsGroup:getName() or '')))
|
||||||
end
|
end
|
||||||
@ -5162,9 +5198,7 @@ function CTLD:_registerJTACGroup(recipeKey, def, dcsGroup)
|
|||||||
code = code,
|
code = code,
|
||||||
})
|
})
|
||||||
|
|
||||||
if self.Config.JTAC and self.Config.JTAC.Verbose then
|
_logInfo(string.format('JTAC registered: group=%s friendlyName=%s code=%s platform=%s verbose=%s', tostring(groupName), tostring(friendlyName), tostring(code), tostring(platform), tostring(self.Config.JTAC and self.Config.JTAC.Verbose)))
|
||||||
_logInfo(string.format('JTAC registered: group=%s friendlyName=%s code=%s platform=%s', tostring(groupName), tostring(friendlyName), tostring(code), tostring(platform)))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function CTLD:_announceJTAC(msgKey, entry, payload)
|
function CTLD:_announceJTAC(msgKey, entry, payload)
|
||||||
@ -5347,6 +5381,65 @@ function CTLD:_processJTACEntry(groupName, entry, now)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function CTLD:ListJTACStatus(group)
|
||||||
|
local lines = {}
|
||||||
|
table.insert(lines, 'JTAC Status')
|
||||||
|
table.insert(lines, '')
|
||||||
|
if not self._jtacRegistry or not next(self._jtacRegistry) then
|
||||||
|
table.insert(lines, '(none registered)')
|
||||||
|
else
|
||||||
|
local now = timer.getTime()
|
||||||
|
for gname, entry in pairs(self._jtacRegistry) do
|
||||||
|
local tgt = entry.currentTarget and entry.currentTarget.label or '(idle)'
|
||||||
|
local age = entry.currentTarget and (now - (entry.currentTarget.firstSeen or now)) or 0
|
||||||
|
local nextScan = entry.nextScan and (entry.nextScan - now) or -1
|
||||||
|
table.insert(lines, string.format('- %s code=%s plat=%s state=%s target=%s age=%.0fs nextScan=%.0fs',
|
||||||
|
entry.displayName or gname, tostring(entry.code), tostring(entry.platform), tostring(entry.lastState), tgt, age, nextScan))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local text = table.concat(lines, '\n')
|
||||||
|
if group and group:IsAlive() then
|
||||||
|
MESSAGE:New(text, 20):ToGroup(group)
|
||||||
|
else
|
||||||
|
_msgCoalition(self.Side, text, 20)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function CTLD:JTACDiagnostics(group)
|
||||||
|
local lines = {}
|
||||||
|
table.insert(lines, 'JTAC Diagnostics')
|
||||||
|
local cfg = self.Config.JTAC or {}
|
||||||
|
table.insert(lines, string.format('Enabled=%s Verbose=%s LockType=%s', tostring(cfg.Enabled), tostring(cfg.Verbose), tostring(cfg.LockType)))
|
||||||
|
local auto = cfg.AutoLase or {}
|
||||||
|
table.insert(lines, string.format('AutoLase Enabled=%s Radius=%s Refresh=%s IdleRescan=%s LostRetry=%s', tostring(auto.Enabled), tostring(auto.SearchRadius), tostring(auto.RefreshSeconds), tostring(auto.IdleRescanSeconds), tostring(auto.LostRetrySeconds)))
|
||||||
|
local countCatalog = 0
|
||||||
|
local jtacKeys = {}
|
||||||
|
for key,def in pairs(self.Config.CrateCatalog or {}) do
|
||||||
|
if self:_definitionIsJTAC(def) then
|
||||||
|
countCatalog = countCatalog + 1
|
||||||
|
table.insert(jtacKeys, key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.insert(lines, string.format('Catalog JTAC Definitions: %d', countCatalog))
|
||||||
|
if #jtacKeys > 0 then
|
||||||
|
table.insert(lines, 'Keys: '..table.concat(jtacKeys, ', '))
|
||||||
|
end
|
||||||
|
local regCount = 0
|
||||||
|
for _ in pairs(self._jtacRegistry or {}) do regCount = regCount + 1 end
|
||||||
|
table.insert(lines, string.format('Registered JTAC Groups: %d', regCount))
|
||||||
|
if regCount > 0 then
|
||||||
|
for gname, entry in pairs(self._jtacRegistry) do
|
||||||
|
table.insert(lines, string.format(' Reg: %s code=%s state=%s', gname, tostring(entry.code), tostring(entry.lastState)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local text = table.concat(lines, '\n')
|
||||||
|
if group and group:IsAlive() then
|
||||||
|
MESSAGE:New(text, 25):ToGroup(group)
|
||||||
|
else
|
||||||
|
_msgCoalition(self.Side, text, 25)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function CTLD:_findJTACNewTarget(entry, jtacPoint, radius, lockType)
|
function CTLD:_findJTACNewTarget(entry, jtacPoint, radius, lockType)
|
||||||
local enemy = _enemySide(entry and entry.side or self.Side)
|
local enemy = _enemySide(entry and entry.side or self.Side)
|
||||||
local best
|
local best
|
||||||
@ -6108,6 +6201,9 @@ end
|
|||||||
function CTLD:BuildAtGroup(group, opts)
|
function CTLD:BuildAtGroup(group, opts)
|
||||||
local unit = group:GetUnit(1)
|
local unit = group:GetUnit(1)
|
||||||
if not unit or not unit:IsAlive() then return end
|
if not unit or not unit:IsAlive() then return end
|
||||||
|
if self.Config.JTAC and self.Config.JTAC.Verbose then
|
||||||
|
_logInfo(string.format('JTAC trace: entering BuildAtGroup for group=%s', tostring(group:GetName())))
|
||||||
|
end
|
||||||
-- Build cooldown/confirmation guardrails
|
-- Build cooldown/confirmation guardrails
|
||||||
local now = timer.getTime()
|
local now = timer.getTime()
|
||||||
local gname = group:GetName()
|
local gname = group:GetName()
|
||||||
@ -6211,6 +6307,11 @@ function CTLD:BuildAtGroup(group, opts)
|
|||||||
_eventSend(self, group, nil, 'build_started', { build = cat.description or recipeKey })
|
_eventSend(self, group, nil, 'build_started', { build = cat.description or recipeKey })
|
||||||
local g = _coalitionAddGroup(cat.side or self.Side, cat.category or Group.Category.GROUND, gdata, self.Config)
|
local g = _coalitionAddGroup(cat.side or self.Side, cat.category or Group.Category.GROUND, gdata, self.Config)
|
||||||
if g then
|
if g then
|
||||||
|
if self.Config.JTAC and self.Config.JTAC.Verbose then
|
||||||
|
_logInfo(string.format('JTAC trace: composite build spawned group=%s recipe=%s', tostring(g:getName()), tostring(recipeKey)))
|
||||||
|
end
|
||||||
|
-- Register JTAC if applicable (composite recipe)
|
||||||
|
self:_maybeRegisterJTAC(recipeKey, cat, g)
|
||||||
for reqKey,qty in pairs(cat.requires) do consumeCrates(reqKey, qty) end
|
for reqKey,qty in pairs(cat.requires) do consumeCrates(reqKey, qty) end
|
||||||
-- No site cap counters when caps are disabled
|
-- No site cap counters when caps are disabled
|
||||||
_eventSend(self, nil, self.Side, 'build_success_coalition', { build = cat.description or recipeKey, player = _playerNameFromGroup(group) })
|
_eventSend(self, nil, self.Side, 'build_success_coalition', { build = cat.description or recipeKey, player = _playerNameFromGroup(group) })
|
||||||
@ -6262,6 +6363,11 @@ function CTLD:BuildAtGroup(group, opts)
|
|||||||
_eventSend(self, group, nil, 'build_started', { build = cat.description or key })
|
_eventSend(self, group, nil, 'build_started', { build = cat.description or key })
|
||||||
local g = _coalitionAddGroup(cat.side or self.Side, cat.category or Group.Category.GROUND, gdata, self.Config)
|
local g = _coalitionAddGroup(cat.side or self.Side, cat.category or Group.Category.GROUND, gdata, self.Config)
|
||||||
if g then
|
if g then
|
||||||
|
if self.Config.JTAC and self.Config.JTAC.Verbose then
|
||||||
|
_logInfo(string.format('JTAC trace: single build spawned group=%s key=%s', tostring(g:getName()), tostring(key)))
|
||||||
|
end
|
||||||
|
-- Register JTAC if applicable (single-unit recipe)
|
||||||
|
self:_maybeRegisterJTAC(key, cat, g)
|
||||||
consumeCrates(key, cat.required or 1)
|
consumeCrates(key, cat.required or 1)
|
||||||
-- No single-unit cap counters when caps are disabled
|
-- No single-unit cap counters when caps are disabled
|
||||||
_eventSend(self, nil, self.Side, 'build_success_coalition', { build = cat.description or key, player = _playerNameFromGroup(group) })
|
_eventSend(self, nil, self.Side, 'build_success_coalition', { build = cat.description or key, player = _playerNameFromGroup(group) })
|
||||||
|
|||||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user