mirror of
https://github.com/iTracerFacer/DCS_MissionDev.git
synced 2025-12-03 04:14:46 +00:00
Fixed catalog bug.
This commit is contained in:
parent
ec967de71e
commit
6cab918ad5
@ -195,7 +195,7 @@ CTLD.Config = {
|
||||
},
|
||||
-- Label placement tuning (simple):
|
||||
-- Effective extra offset from the circle edge = r * LabelOffsetRatio + LabelOffsetFromEdge
|
||||
LabelOffsetFromEdge = 0, -- meters beyond the zone radius to place the label (12 o'clock)
|
||||
LabelOffsetFromEdge = -50, -- meters beyond the zone radius to place the label (12 o'clock)
|
||||
LabelOffsetRatio = 0.5, -- fraction of the radius to add to the offset (e.g., 0.1 => +10% of r)
|
||||
LabelOffsetX = 200, -- meters: horizontal nudge; adjust if text appears left-anchored in your DCS build
|
||||
-- Per-kind label prefixes
|
||||
@ -728,6 +728,57 @@ local function _eventSend(self, group, side, key, data)
|
||||
st.lastKeyTimes[key] = now
|
||||
end
|
||||
|
||||
-- Format helpers for menu labels and recipe info
|
||||
function CTLD:_recipeTotalCrates(def)
|
||||
if not def then return 1 end
|
||||
if type(def.requires) == 'table' then
|
||||
local n = 0
|
||||
for _,qty in pairs(def.requires) do n = n + (qty or 0) end
|
||||
return math.max(1, n)
|
||||
end
|
||||
return math.max(1, def.required or 1)
|
||||
end
|
||||
|
||||
function CTLD:_friendlyNameForKey(key)
|
||||
local d = self.Config and self.Config.CrateCatalog and self.Config.CrateCatalog[key]
|
||||
if not d then return tostring(key) end
|
||||
return (d.menu or d.description or key)
|
||||
end
|
||||
|
||||
function CTLD:_formatMenuLabelWithCrates(key, def)
|
||||
local base = (def and (def.menu or def.description)) or key
|
||||
local total = self:_recipeTotalCrates(def)
|
||||
local suffix = (total == 1) and '1 crate' or (tostring(total)..' crates')
|
||||
return string.format('%s (%s)', base, suffix)
|
||||
end
|
||||
|
||||
function CTLD:_formatRecipeInfo(key, def)
|
||||
local lines = {}
|
||||
local title = self:_friendlyNameForKey(key)
|
||||
table.insert(lines, string.format('%s', title))
|
||||
if def and def.isFOB then table.insert(lines, '(FOB recipe)') end
|
||||
if def and type(def.requires) == 'table' then
|
||||
local total = self:_recipeTotalCrates(def)
|
||||
table.insert(lines, string.format('Requires: %d crate(s) total', total))
|
||||
table.insert(lines, 'Breakdown:')
|
||||
-- stable order
|
||||
local items = {}
|
||||
for k,qty in pairs(def.requires) do table.insert(items, {k=k, q=qty}) end
|
||||
table.sort(items, function(a,b) return tostring(a.k) < tostring(b.k) end)
|
||||
for _,it in ipairs(items) do
|
||||
local fname = self:_friendlyNameForKey(it.k)
|
||||
table.insert(lines, string.format('- %dx %s', it.q or 1, fname))
|
||||
end
|
||||
else
|
||||
local n = self:_recipeTotalCrates(def)
|
||||
table.insert(lines, string.format('Requires: %d crate(s)', n))
|
||||
end
|
||||
if def and def.dcsCargoType then
|
||||
table.insert(lines, string.format('Cargo type: %s', tostring(def.dcsCargoType)))
|
||||
end
|
||||
return table.concat(lines, '\n')
|
||||
end
|
||||
|
||||
-- Determine an approximate radius for a ZONE. Tries MOOSE radius, then trigger zone radius, then configured radius.
|
||||
function CTLD:_getZoneRadius(zone)
|
||||
if zone and zone.Radius then return zone.Radius end
|
||||
@ -1051,6 +1102,8 @@ function CTLD:BuildGroupMenus(group)
|
||||
end
|
||||
-- Request crate submenu per catalog entry
|
||||
local reqRoot = MENU_GROUP:New(group, 'Request Crate', root)
|
||||
-- Optional: parallel Recipe Info submenu to display detailed requirements
|
||||
local infoRoot = MENU_GROUP:New(group, 'Recipe Info', root)
|
||||
if self.Config.UseCategorySubmenus then
|
||||
local submenus = {}
|
||||
local function getSubmenu(catLabel)
|
||||
@ -1059,21 +1112,37 @@ function CTLD:BuildGroupMenus(group)
|
||||
end
|
||||
return submenus[catLabel]
|
||||
end
|
||||
local infoSubs = {}
|
||||
local function getInfoSub(catLabel)
|
||||
if not infoSubs[catLabel] then
|
||||
infoSubs[catLabel] = MENU_GROUP:New(group, catLabel, infoRoot)
|
||||
end
|
||||
return infoSubs[catLabel]
|
||||
end
|
||||
for key,def in pairs(self.Config.CrateCatalog) do
|
||||
local label = (def and (def.menu or def.description)) or key
|
||||
local label = self:_formatMenuLabelWithCrates(key, def)
|
||||
local sideOk = (not def.side) or def.side == self.Side
|
||||
if sideOk then
|
||||
local catLabel = (def and def.menuCategory) or 'Other'
|
||||
local parent = getSubmenu(catLabel)
|
||||
CMD(label, parent, function() self:RequestCrateForGroup(group, key) end)
|
||||
local infoParent = getInfoSub(catLabel)
|
||||
CMD((def and (def.menu or def.description)) or key, infoParent, function()
|
||||
local text = self:_formatRecipeInfo(key, def)
|
||||
_msgGroup(group, text)
|
||||
end)
|
||||
end
|
||||
end
|
||||
else
|
||||
for key,def in pairs(self.Config.CrateCatalog) do
|
||||
local label = (def and (def.menu or def.description)) or key
|
||||
local label = self:_formatMenuLabelWithCrates(key, def)
|
||||
local sideOk = (not def.side) or def.side == self.Side
|
||||
if sideOk then
|
||||
CMD(label, reqRoot, function() self:RequestCrateForGroup(group, key) end)
|
||||
CMD(((def and (def.menu or def.description)) or key)..' (info)', infoRoot, function()
|
||||
local text = self:_formatRecipeInfo(key, def)
|
||||
_msgGroup(group, text)
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1573,6 +1642,8 @@ function CTLD:BuildAtGroup(group)
|
||||
nearby = filtered
|
||||
if #nearby == 0 then
|
||||
_eventSend(self, group, nil, 'build_insufficient_crates', { build = 'asset' })
|
||||
-- Nudge players to use Recipe Info
|
||||
_msgGroup(group, 'Tip: Use CTLD → Recipe Info to see exact crate requirements for each build.')
|
||||
return
|
||||
end
|
||||
|
||||
@ -1685,6 +1756,54 @@ function CTLD:BuildAtGroup(group)
|
||||
end
|
||||
end
|
||||
_eventSend(self, group, nil, 'build_insufficient_crates', { build = 'asset' })
|
||||
-- Provide a short breakdown of most likely recipes and what is missing
|
||||
local suggestions = {}
|
||||
local function pushSuggestion(name, missingStr, haveParts, totalParts)
|
||||
table.insert(suggestions, { name = name, miss = missingStr, have = haveParts, total = totalParts })
|
||||
end
|
||||
-- consider composite recipes with at least one matching component nearby
|
||||
for rkey,cat in pairs(self.Config.CrateCatalog) do
|
||||
if type(cat.requires) == 'table' then
|
||||
local have, total, missingList = 0, 0, {}
|
||||
for reqKey,qty in pairs(cat.requires) do
|
||||
total = total + (qty or 0)
|
||||
local haveHere = math.min(qty or 0, counts[reqKey] or 0)
|
||||
have = have + haveHere
|
||||
local need = math.max(0, (qty or 0) - (counts[reqKey] or 0))
|
||||
if need > 0 then
|
||||
local fname = self:_friendlyNameForKey(reqKey)
|
||||
table.insert(missingList, string.format('%dx %s', need, fname))
|
||||
end
|
||||
end
|
||||
if have > 0 and have < total then
|
||||
local name = cat.description or cat.menu or rkey
|
||||
pushSuggestion(name, table.concat(missingList, ', '), have, total)
|
||||
end
|
||||
else
|
||||
-- single-key recipe: if some crates present but not enough
|
||||
local need = (cat and (cat.required or 1)) or 1
|
||||
local have = counts[rkey] or 0
|
||||
if have > 0 and have < need then
|
||||
local name = cat.description or cat.menu or rkey
|
||||
pushSuggestion(name, string.format('%d more crate(s) of %s', need - have, self:_friendlyNameForKey(rkey)), have, need)
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(suggestions, function(a,b)
|
||||
local ra = (a.total > 0) and (a.have / a.total) or 0
|
||||
local rb = (b.total > 0) and (b.have / b.total) or 0
|
||||
if ra == rb then return (a.total - a.have) < (b.total - b.have) end
|
||||
return ra > rb
|
||||
end)
|
||||
if #suggestions > 0 then
|
||||
local maxShow = math.min(2, #suggestions)
|
||||
for i=1,maxShow do
|
||||
local s = suggestions[i]
|
||||
_msgGroup(group, string.format('Missing for %s: %s', s.name, s.miss))
|
||||
end
|
||||
else
|
||||
_msgGroup(group, 'No matching recipe found with nearby crates. Check Recipe Info for requirements.')
|
||||
end
|
||||
end
|
||||
-- #endregion Build logic
|
||||
|
||||
|
||||
Binary file not shown.
@ -93,12 +93,10 @@ cat['RED_URAL_ZU23'] = { menuCategory='AAA', menu='Ural-375 ZU-23',
|
||||
cat['RED_SHILKA'] = { menuCategory='AAA', menu='ZSU-23-4 Shilka', description='ZSU-23-4 Shilka', dcsCargoType='container_cargo', required=1, side=RED, category=Group.Category.GROUND, build=singleUnit('ZSU-23-4 Shilka') }
|
||||
cat['RED_ZSU57_2'] = { menuCategory='AAA', menu='ZSU_57_2', description='ZSU_57_2', dcsCargoType='container_cargo', required=1, side=RED, category=Group.Category.GROUND, build=singleUnit('ZSU_57_2') }
|
||||
|
||||
-- SAM short range (BLUE)
|
||||
cat['BLUE_M1097_AVENGER'] = { menuCategory='SAM short range', menu='M1097 Avenger', description='M1097 Avenger', dcsCargoType='container_cargo', required=2, side=BLUE, category=Group.Category.GROUND, build=singleUnit('M1097 Avenger') }
|
||||
cat['BLUE_M48_CHAPARRAL'] = { menuCategory='SAM short range', menu='M48 Chaparral', description='M48 Chaparral', dcsCargoType='container_cargo', required=2, side=BLUE, category=Group.Category.GROUND, build=singleUnit('M48 Chaparral') }
|
||||
cat['BLUE_ROLAND_ADS'] = { menuCategory='SAM short range', menu='Roland ADS', description='Roland ADS', dcsCargoType='container_cargo', required=2, side=BLUE, category=Group.Category.GROUND, build=singleUnit('Roland ADS') }
|
||||
cat['BLUE_M6_LINEBACKER'] = { menuCategory='SAM short range', menu='M6 Linebacker', description='M6 Linebacker', dcsCargoType='container_cargo', required=1, side=BLUE, category=Group.Category.GROUND, build=singleUnit('M6 Linebacker') }
|
||||
-- Rapier components and site
|
||||
cat['BLUE_RAPIER_LN'] = { menuCategory='SAM short range', menu='Rapier Launcher', description='Rapier Launcher', dcsCargoType='container_cargo', required=1, side=BLUE, category=Group.Category.GROUND, build=singleUnit('rapier_fsa_launcher') }
|
||||
cat['BLUE_RAPIER_SR'] = { menuCategory='SAM short range', menu='Rapier SR', description='Rapier SR', dcsCargoType='container_cargo', required=1, side=BLUE, category=Group.Category.GROUND, build=singleUnit('rapier_fsa_blindfire_radar') }
|
||||
cat['BLUE_RAPIER_TR'] = { menuCategory='SAM short range', menu='Rapier Tracker', description='Rapier Tracker', dcsCargoType='container_cargo', required=1, side=BLUE, category=Group.Category.GROUND, build=singleUnit('rapier_fsa_optical_tracker_unit') }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user