-- Smart Pickup — guiden "Opsæt mark" og fanen Markers knapper -- Henter det spil-afhængige (afgrøder der kan sås, slåafgrøder, halm, maskiner, marksiloer, siloer i nærheden) -- som `context` til ADFieldGuide og gemmer guidens resultat via ADFieldJobs. Selve trin-skærmen er fælles -- (gui/SmartPickupGuide.lua). Funktionerne lægges på SmartPickupFrame (indlæses efter SmartPickupFrame.lua). -- lagervalget viser de nærmeste siloer (plus valgte, marksiloer og gæringssiloer) SmartPickupFrame.FIELD_STORE_ROWS = 8 function SmartPickupFrame:initFieldButtons(i18n) self.fieldStartButtonInfo = {inputAction = InputAction.MENU_ACTIVATE, text = i18n:getText("spu_field_button_start"), callback = function() self:onClickFieldStartStop() end} self.fieldSetupButtonInfo = {inputAction = InputAction.MENU_EXTRA_1, text = i18n:getText("spu_guide_field_open"), callback = function() self:onClickFieldSetup() end} self.fieldFleetButtonInfo = {inputAction = InputAction.MENU_EXTRA_2, text = i18n:getText("spu_guide_fleet_open"), callback = function() self:onClickFieldFleet(true) end} self.fieldFleetCloseButtonInfo = {inputAction = InputAction.MENU_EXTRA_2, text = i18n:getText("spu_guide_fleet_close"), callback = function() self:onClickFieldFleet(false) end} self.fieldButtons = {self.backButtonInfo, self.fieldStartButtonInfo, self.fieldSetupButtonInfo, self.fieldFleetButtonInfo} self.fieldFleetButtons = {self.backButtonInfo, self.fieldFleetCloseButtonInfo} end function SmartPickupFrame:getFieldButtons() return self.fieldView == "fleet" and self.fieldFleetButtons or self.fieldButtons end -- ---- context til ADFieldGuide ---- -- {[fieldId] = rigIds} for alle marker function SmartPickupFrame.rigIdsByField() local byField = {} for fieldId, field in pairs(ADFieldJobs.state.fields) do byField[fieldId] = field.plan ~= nil and field.plan.rigIds or {} end return byField end local function fruitTypes() return g_fruitTypeManager ~= nil and g_fruitTypeManager.fruitTypes or {} end -- Afgrøder der kan sås, slåafgrøder (navne) og afgrøder med halm (skår efter mejetærskeren). function SmartPickupFrame:fruitContext() local sowable, straw, mowable = {}, {}, {} for _, fruit in ipairs(fruitTypes()) do if fruit.allowsSeeding ~= false and fruit.fillType ~= nil and fruit.name ~= nil then table.insert(sowable, {name = fruit.name, title = tostring(fruit.fillType.title or fruit.name)}) end local ok, hasStraw = pcall(function() return fruit.hasWindrow == true or fruit.windrowName ~= nil end) if ok and hasStraw and fruit.name ~= nil then straw[fruit.name] = true end end if ADFields ~= nil and g_fruitTypeManager ~= nil then for index in pairs(ADFields.getMowable()) do local fruit = g_fruitTypeManager:getFruitTypeByIndex(index) if fruit ~= nil and fruit.name ~= nil then mowable[fruit.name] = true end end end return sowable, mowable, straw end -- Markens vare ud fra kladdens plan (ensilage -> skår, hø -> tørskår, høst -> afgrøden); nil på bar mark. local function fieldFillType(info, plan) if info.kind == "mowable" then return ADFieldModel.product(plan, "mowable") == "hay" and info.hay or info.windrow end if info.kind == "harvest" then return info.harvestFillType end return nil end -- Siloer der tager markens vare: marksilo først, gæringssiloer, så de nærmeste (samme regel som før). function SmartPickupFrame:fieldStoreContext(adEnv, info, plan, chosenIds) local fillType = fieldFillType(info, plan) local farmId = g_currentMission:getFarmId() local fieldSilos, silosById = {}, {} for _, building in ipairs(ADFields.fieldSilos(adEnv, farmId, info)) do local markers = ADBuildings.getMarkers ~= nil and ADBuildings.getMarkers(building, "unload") or {} table.insert(fieldSilos, {id = building.id, name = tostring(building.name), text = markers[1] ~= nil and tostring(markers[1].name) or tostring(building.name)}) silosById[building.id] = true end if fillType == nil then return nil, 0, fieldSilos end local chosen = {} for _, id in ipairs(chosenIds or {}) do chosen[id] = true end local fermenterIds = {} if info.kind == "mowable" and ADFieldModel.product(plan, "mowable") == "silage" then for _, building in ipairs(ADFieldJobs.getFermenters(adEnv, farmId, fillType, info.x, info.z)) do fermenterIds[building.id] = true end end local entries = {} for _, building in ipairs(ADBuildings.list(adEnv, farmId)) do local isSilo = building.kind == "silo" and ADRunsController.canStoreAt(adEnv, building, {{fillType = fillType, isPallet = false}}) if chosen[building.id] or isSilo or fermenterIds[building.id] then local distance = nil local node = building.placeable ~= nil and building.placeable.rootNode or nil if node ~= nil and info.x ~= nil then local bx, _, bz = getWorldTranslation(node) distance = math.sqrt((bx - info.x) ^ 2 + (bz - info.z) ^ 2) end table.insert(entries, {id = building.id, building = building, distance = distance, chosen = chosen[building.id] == true, fieldSilo = silosById[building.id] == true, fermenter = fermenterIds[building.id] == true}) end end local shown, hidden = ADFieldView.storeRows(entries, SmartPickupFrame.FIELD_STORE_ROWS) local stores = {} for _, entry in ipairs(shown) do local building = entry.building local markers = ADBuildings.getMarkers ~= nil and ADBuildings.getMarkers(building, "unload") or {} -- det der skelner rækkerne først (rækken afkorter bagfra): markør, afstand, art — så bygningens navn local label = (markers[1] ~= nil and tostring(markers[1].name) or tostring(building.name)) .. ", " .. ADFieldView.distanceText(entry.distance) if entry.fieldSilo then label = label .. " (" .. self.i18n:getText("spu_field_fieldSilo") .. ")" end if entry.fermenter then label = label .. " (" .. self.i18n:getText("spu_field_fermenter") .. ")" end if markers[1] ~= nil then label = label .. " — " .. tostring(building.name) end table.insert(stores, {id = building.id, text = label}) end return stores, hidden, fieldSilos end -- Markerne til trin 1 ("F22 — Hvede — Venter"). function SmartPickupFrame:fieldPickList() local fields = {} for _, row in ipairs(ADFieldView.rows(ADFields.list(), ADFieldJobs.state.fields)) do local crop = ADFieldView.cropText(row.info, function(key) return self.i18n:getText(key) end) table.insert(fields, {id = row.info.id, text = string.format("F%d — %s — %s", row.info.id, crop, self:fieldStatusText(row.field, row.info, true))}) end return fields end -- context for en mark (info) med kladdens plan; info nil = trin 1 uden valgt mark. function SmartPickupFrame:fieldGuideContext(adEnv, info, plan, chosenStoreIds) local sowable, mowable, straw = self:fruitContext() local context = {info = info or {}, sowable = sowable, mowable = mowable, straw = straw, rigIdsByField = SmartPickupFrame.rigIdsByField(), fieldSilos = {}, storeHidden = 0, fields = self:fieldPickList(), rigs = {}} for _, rig in ipairs(ADFieldJobs.getRigs(adEnv)) do table.insert(context.rigs, {id = rig.id, role = rig.role, text = string.format("%s — %s", tostring(rig.label), self:roleText(rig.role))}) end if info ~= nil then context.stores, context.storeHidden, context.fieldSilos = self:fieldStoreContext(adEnv, info, plan or {}, chosenStoreIds) end return context end -- ---- hooks til den fælles guide-skærm ---- local function chosenStoreIds(guide) local ids = {} for _, id in ipairs(guide.draft.storeIds or {}) do table.insert(ids, id) end for _, id in ipairs(guide.draft.plan ~= nil and guide.draft.plan.storeBuildingIds or {}) do table.insert(ids, id) end return ids end SmartPickupFrame.GUIDE_HOOKS = SmartPickupFrame.GUIDE_HOOKS or {} SmartPickupFrame.GUIDE_HOOKS.field = { model = ADFieldGuide, tab = SmartPickupFrame.TAB_FIELDS, cannotAdvanceKey = "spu_guide_pickField", heading = function(frame, guide) if guide.draft.fieldId == nil then return frame.i18n:getText("spu_guide_field_titleNone") end return string.format(frame.i18n:getText("spu_guide_field_title"), guide.draft.fieldId) end, context = function(frame, adEnv, guide) local fieldId = guide.draft.fieldId if fieldId == nil then return frame:fieldGuideContext(adEnv, nil) end local info = ADFields.getInfo(fieldId) -- marken er solgt/bygget over mens guiden var åben if info == nil or info.cultivable == false then return nil end return frame:fieldGuideContext(adEnv, info, guide.draft.plan, chosenStoreIds(guide)) end, choose = function(frame, id, value) if id ~= "field" then return false end local info = ADFields.getInfo(value) if info == nil then return true end local field = ADFieldJobs.getField(value) frame.selectedFieldId = value frame.statusOverride = nil frame.guide = ADFieldGuide.pickField(frame.guide, field, frame:fieldGuideContext(frame.getAdEnv(), info, field.plan, field.plan.storeBuildingIds)) return true end, canAdvance = function(guide) return guide.draft.fieldId ~= nil end, startKey = function() return "spu_guide_runAuto" end, -- mål-afgrøde kører altid automatisk: ingen "Gem uden at starte" showSaveOnly = function(guide) return (guide.draft.plan.targetFruit or "") == "" end, save = function(frame, guide, start) frame:saveFieldGuide(guide, start) end, afterRows = function(frame, adEnv, guide) if guide.step ~= "summary" or guide.draft.fieldId == nil then return end local info = guide.context.info if info ~= nil and info.markerId == nil then frame:addTextRow(" " .. string.format(frame.i18n:getText("spu_guide_noMarker"), guide.draft.fieldId)) end end, } -- Gem: mål-afgrøde (hvis ændret), planen, og faste maskiner (fjernes fra andre marker). function SmartPickupFrame:saveFieldGuide(guide, start) local result = ADFieldGuide.result(guide, start) if result.fieldId == nil then return end if result.targetChanged then ADFieldJobs.setTarget(result.fieldId, result.targetFruit) end ADFieldJobs.setPlan(result.fieldId, result.plan) local byField = SmartPickupFrame.rigIdsByField() for fieldId, ids in pairs(ADFieldGuide.applyRigs(byField, result.fieldId, result.rigIds)) do if table.concat(byField[fieldId] or {}, " ") ~= table.concat(ids, " ") then ADFieldJobs.setPlan(fieldId, {rigIds = ids}) end end ADFieldJobs.log(result.fieldId, "guide gemt: mode=%s mål=%s faste=%s lager=%s", tostring(result.plan.mode), result.targetFruit ~= "" and result.targetFruit or "-", table.concat(result.rigIds, " "), table.concat(result.plan.storeBuildingIds or {}, " ")) self.selectedFieldId = result.fieldId self.statusOverride = string.format(self.i18n:getText("spu_guide_saved"), result.fieldId) self.statusOverrideTicks = SmartPickupFrame.STATUS_OVERRIDE_TICKS end -- ---- knapper og [Ret] ---- -- [Opsæt mark]: den valgte mark med de nuværende valg, ellers trin 1 (vælg mark). function SmartPickupFrame:onClickFieldSetup() self:safe(function(frame) local adEnv = frame.getAdEnv() if adEnv == nil then return end local info = frame.selectedFieldId ~= nil and ADFields.getInfo(frame.selectedFieldId) or nil frame.fieldView = nil if info == nil then frame:openGuide("field", ADFieldGuide.openPicker(frame:fieldGuideContext(adEnv, nil))) return end local field = ADFieldJobs.getField(info.id) frame:openGuide("field", ADFieldGuide.open(field, frame:fieldGuideContext(adEnv, info, field.plan, field.plan.storeBuildingIds))) end) end -- [Ret] på en resumé-linje i fanens oversigt: kun det ene trin; [Gem] gemmer og går tilbage. function SmartPickupFrame:openFieldStep(fieldId, step) local adEnv = self.getAdEnv() local info = ADFields.getInfo(fieldId) if adEnv == nil or info == nil then return end local field = ADFieldJobs.getField(fieldId) local context = self:fieldGuideContext(adEnv, info, field.plan, field.plan.storeBuildingIds) self:openGuide("field", ADFieldGuide.open(field, context, {step = step, single = true, returnTo = "close"})) end function SmartPickupFrame:onClickFieldFleet(show) self:safe(function(frame) frame.fieldView = show and "fleet" or nil frame:requestRebuild() end) end