From 31c993c6ebb6636f3774c294925768c54bd9f8c9 Mon Sep 17 00:00:00 2001 From: masterdraco Date: Sun, 27 Sep 2026 10:42:42 +0200 Subject: [PATCH] =?UTF-8?q?feat(gui):=20fanen=20Marksiloer=20=E2=80=94=20t?= =?UTF-8?q?il/fra,=20maks.=20vogne,=20mindste=20m=C3=A6ngde,=20g=C3=A5rdla?= =?UTF-8?q?gre,=20status=20pr.=20silo=20(v1.36.0.0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FS25_ADSmartPickup/adSmartPickup.lua | 1 + .../gui/SmartPickupFieldSiloTab.lua | 83 +++++++++++++++++++ FS25_ADSmartPickup/gui/SmartPickupFrame.lua | 25 ++++-- FS25_ADSmartPickup/l10n/l10n_da.xml | 17 ++++ FS25_ADSmartPickup/l10n/l10n_en.xml | 17 ++++ FS25_ADSmartPickup/modDesc.xml | 2 +- 6 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 FS25_ADSmartPickup/gui/SmartPickupFieldSiloTab.lua diff --git a/FS25_ADSmartPickup/adSmartPickup.lua b/FS25_ADSmartPickup/adSmartPickup.lua index a62b66c..5719a7f 100644 --- a/FS25_ADSmartPickup/adSmartPickup.lua +++ b/FS25_ADSmartPickup/adSmartPickup.lua @@ -26,6 +26,7 @@ if ADSmartPickup.dir ~= nil and source ~= nil then source(ADSmartPickup.dir .. "gui/SmartPickupFlowTab.lua") source(ADSmartPickup.dir .. "gui/SmartPickupFieldTab.lua") source(ADSmartPickup.dir .. "gui/SmartPickupMonthTab.lua") + source(ADSmartPickup.dir .. "gui/SmartPickupFieldSiloTab.lua") source(ADSmartPickup.dir .. "gui/SmartPickupGuide.lua") source(ADSmartPickup.dir .. "gui/SmartPickupFieldGuide.lua") source(ADSmartPickup.dir .. "gui/SmartPickupFlowGuide.lua") diff --git a/FS25_ADSmartPickup/gui/SmartPickupFieldSiloTab.lua b/FS25_ADSmartPickup/gui/SmartPickupFieldSiloTab.lua new file mode 100644 index 0000000..841bcdb --- /dev/null +++ b/FS25_ADSmartPickup/gui/SmartPickupFieldSiloTab.lua @@ -0,0 +1,83 @@ +-- Smart Pickup — fanen Marksiloer +-- Opsætning (til/fra, maks. vogne, mindste mængde, gårdlagre) og status for marksilo-flowet. +-- Klik går til onClickFieldSiloRow; reglerne ligger i ADFieldSilos/ADFieldSiloPlanner. + +SmartPickupFrame.FIELDSILO_ROW_KINDS = {fsEnabled = true, fsMaxVehicles = true, fsMinLiters = true, fsStore = true} + +local function numberTexts(from, to) + local texts = {} + for n = from, to do table.insert(texts, tostring(n)) end + return texts +end + +local function literTexts() + local texts = {} + for _, liters in ipairs(ADFieldSiloConfig.MIN_LITERS_CHOICES) do table.insert(texts, string.format("%d l", liters)) end + return texts +end + +local function indexOf(list, value) + for index, entry in ipairs(list) do if entry == value then return index end end + return 1 +end + +function SmartPickupFrame:fillFieldSiloRows(adEnv) + local i18n, cfg = self.i18n, ADFieldSilos.config + local onOff = {i18n:getText("ui_no"), i18n:getText("ui_yes")} + self:addToggleRow("fsEnabled", i18n:getText("spu_fs_enabled"), onOff, cfg.enabled) + local maxOption = self:addToggleRow("fsMaxVehicles", i18n:getText("spu_fs_maxVehicles"), numberTexts(1, ADFieldSiloConfig.MAX_VEHICLES), false) + maxOption:setState(cfg.maxVehicles, false) + local minOption = self:addToggleRow("fsMinLiters", i18n:getText("spu_fs_minLiters"), literTexts(), false) + minOption:setState(indexOf(ADFieldSiloConfig.MIN_LITERS_CHOICES, cfg.minLiters), false) + + local plan = ADFieldSilos.lastPlan + local waiting = 0 + for _, entry in ipairs(plan ~= nil and plan.status or {}) do if entry.state == "ok" then waiting = waiting + 1 end end + self:addTextRow(string.format(i18n:getText("spu_fs_status"), ADFieldSilos.loanCount(), cfg.maxVehicles, waiting)) + if #cfg.storeIds == 0 then self:addTextRow(i18n:getText("spu_fs_noStores")) end + + self:addTextRow(i18n:getText("spu_fs_silosTitle")) + if plan == nil or #plan.status == 0 then + self:addTextRow(" " .. i18n:getText("spu_fs_nothing")) + else + self:addCellRow(self.fieldPrefab, {i18n:getText("spu_fs_col_silo"), i18n:getText("spu_col_crop"), i18n:getText("spu_fs_col_liters"), + i18n:getText("spu_fs_col_onWay"), i18n:getText("spu_fs_col_state"), ""}) + for _, entry in ipairs(plan.status) do + local desc = g_fillTypeManager:getFillTypeByIndex(entry.fillType) + local title = desc ~= nil and (desc.title or desc.name) or tostring(entry.fillType) + local state = i18n:getText("spu_fs_state_" .. entry.state) + if entry.state == "noFarmStore" then state = string.format(state, title) end + self:addCellRow(self.fieldPrefab, {tostring(entry.siloName), title, string.format("%d", math.floor(entry.liters)), + string.format("%d", math.floor(entry.onWay)), state, ""}) + end + end + + self:addTextRow(i18n:getText("spu_fs_storesTitle")) + local farmId = g_currentMission:getFarmId() + for _, building in ipairs(ADBuildings.list(adEnv, farmId)) do + if building.kind == "silo" then + local option = self:addToggleRow("fsStore", tostring(building.name), onOff, ADFieldSiloConfig.hasStore(cfg, building.id)) + self.rowData[option] = {kind = "fsStore", buildingId = building.id} + end + end +end + +function SmartPickupFrame:onClickFieldSiloRow(state, data) + self:safe(function(frame) + local cfg = ADFieldSilos.config + if data.kind == "fsEnabled" then + cfg = ADFieldSiloConfig.with(cfg, {enabled = state == SmartPickupFrame.STATE_ON}) + elseif data.kind == "fsMaxVehicles" then + cfg = ADFieldSiloConfig.with(cfg, {maxVehicles = state}) + elseif data.kind == "fsMinLiters" then + cfg = ADFieldSiloConfig.with(cfg, {minLiters = ADFieldSiloConfig.MIN_LITERS_CHOICES[state]}) + elseif data.kind == "fsStore" then + cfg = ADFieldSiloConfig.toggleStore(cfg, data.buildingId) + end + ADFieldSilos.setConfig(cfg) + pcall(ADFieldSilos.save) + local adEnv = frame.getAdEnv() + if adEnv ~= nil then pcall(ADFieldSilos.planNow, adEnv) end + frame:requestRebuild() + end) +end diff --git a/FS25_ADSmartPickup/gui/SmartPickupFrame.lua b/FS25_ADSmartPickup/gui/SmartPickupFrame.lua index cc62ba5..9ea701f 100644 --- a/FS25_ADSmartPickup/gui/SmartPickupFrame.lua +++ b/FS25_ADSmartPickup/gui/SmartPickupFrame.lua @@ -11,12 +11,14 @@ SmartPickupFrame.STATUS_OVERRIDE_TICKS = 6 SmartPickupFrame.MAX_STATUS_REASONS = 3 SmartPickupFrame.LOG_PREFIX = "ADSmartPickup: " SmartPickupFrame.STATE_OFF, SmartPickupFrame.STATE_ON = 1, 2 -SmartPickupFrame.TAB_OVERVIEW, SmartPickupFrame.TAB_FLOWS, SmartPickupFrame.TAB_FIELDS, SmartPickupFrame.TAB_MONTH = 1, 2, 3, 4 +SmartPickupFrame.TAB_OVERVIEW, SmartPickupFrame.TAB_FLOWS, SmartPickupFrame.TAB_FIELDS, SmartPickupFrame.TAB_MONTH, SmartPickupFrame.TAB_FIELDSILOS = 1, 2, 3, 4, 5 -- Måned-fanen genopbygges hvert N. sekund (ingen klikbare rækker, så fokus går ikke tabt) SmartPickupFrame.MONTH_REBUILD_TICKS = 5 +-- Marksilo-fanen har klikbare valg: genopbygges sjældnere, så fokus ikke rykker midt i et valg +SmartPickupFrame.FIELDSILO_REBUILD_TICKS = 30 -- Lagerfaner: én pr. bygningstype (indeks -> kind i ADSources.getFarmInventory) -SmartPickupFrame.TAB_NAMES = {"spu_tab_overview", "spu_tab_flows", "spu_tab_fields", "spu_tab_month", "spu_tab_factories", "spu_tab_silos", "spu_tab_barns", "spu_tab_sheds"} -SmartPickupFrame.TAB_KINDS = {[5] = "factory", [6] = "silo", [7] = "husbandry", [8] = "objectStorage"} +SmartPickupFrame.TAB_NAMES = {"spu_tab_overview", "spu_tab_flows", "spu_tab_fields", "spu_tab_month", "spu_tab_fieldsilos", "spu_tab_factories", "spu_tab_silos", "spu_tab_barns", "spu_tab_sheds"} +SmartPickupFrame.TAB_KINDS = {[6] = "factory", [7] = "silo", [8] = "husbandry", [9] = "objectStorage"} function SmartPickupFrame.getTabKind(tab) return SmartPickupFrame.TAB_KINDS[tab] @@ -412,6 +414,17 @@ function SmartPickupFrame:rebuild() self:restoreFocusIfLost() return end + if self.currentTab == SmartPickupFrame.TAB_FIELDSILOS then + if adEnv ~= nil then + self:fillFieldSiloRows(adEnv) + end + self.monthRebuildTicks = SmartPickupFrame.FIELDSILO_REBUILD_TICKS + self:colorRows() + self.boxLayout:invalidateLayout() + self:refreshButtons() + self:restoreFocusIfLost() + return + end if self.currentTab == SmartPickupFrame.TAB_MONTH then if adEnv ~= nil then self:fillMonthRows(adEnv) @@ -554,7 +567,7 @@ function SmartPickupFrame:refreshButtons() wanted = self.overviewButtons elseif self.currentTab == SmartPickupFrame.TAB_FIELDS then wanted = self:getFieldButtons() - elseif self.currentTab == SmartPickupFrame.TAB_MONTH then + elseif self.currentTab == SmartPickupFrame.TAB_MONTH or self.currentTab == SmartPickupFrame.TAB_FIELDSILOS then wanted = self.monthButtons end if self.menuButtonInfo ~= wanted then @@ -576,7 +589,7 @@ function SmartPickupFrame:refreshLive() self:setStatusText(self.i18n:getText("spu_status_noAd")) return end - if self.currentTab == SmartPickupFrame.TAB_MONTH then + if self.currentTab == SmartPickupFrame.TAB_MONTH or self.currentTab == SmartPickupFrame.TAB_FIELDSILOS then self.monthRebuildTicks = (self.monthRebuildTicks or 0) - 1 if self.monthRebuildTicks <= 0 then self:requestRebuild() end self:refreshButtons() @@ -659,6 +672,8 @@ function SmartPickupFrame:onClickIngredient(state, element) local data = self.rowData[element] if data ~= nil and data.kind == "guideRow" then return self:onClickGuideRow(state, data) + elseif data ~= nil and SmartPickupFrame.FIELDSILO_ROW_KINDS ~= nil and SmartPickupFrame.FIELDSILO_ROW_KINDS[data.kind] then + return self:onClickFieldSiloRow(state, data) elseif data ~= nil and SmartPickupFrame.FIELD_ROW_KINDS[data.kind] then return self:onClickFieldRow(state, data) end diff --git a/FS25_ADSmartPickup/l10n/l10n_da.xml b/FS25_ADSmartPickup/l10n/l10n_da.xml index 0c98df5..da84f0b 100644 --- a/FS25_ADSmartPickup/l10n/l10n_da.xml +++ b/FS25_ADSmartPickup/l10n/l10n_da.xml @@ -463,5 +463,22 @@ + + + + + + + + + + + + + + + + + diff --git a/FS25_ADSmartPickup/l10n/l10n_en.xml b/FS25_ADSmartPickup/l10n/l10n_en.xml index c482904..c6200c1 100644 --- a/FS25_ADSmartPickup/l10n/l10n_en.xml +++ b/FS25_ADSmartPickup/l10n/l10n_en.xml @@ -463,5 +463,22 @@ + + + + + + + + + + + + + + + + + diff --git a/FS25_ADSmartPickup/modDesc.xml b/FS25_ADSmartPickup/modDesc.xml index aff94c1..12b0419 100644 --- a/FS25_ADSmartPickup/modDesc.xml +++ b/FS25_ADSmartPickup/modDesc.xml @@ -1,7 +1,7 @@ masterdraco - 1.35.3.0 + 1.36.0.0 <en>AD Smart Pickup</en>