242 lines
13 KiB
Lua
242 lines
13 KiB
Lua
-- 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 = {}, rigs = {}}
|
|
-- marklisten bruges kun i trin 1 (guiden åbnet uden valgt mark)
|
|
if info == nil then context.fields = self:fieldPickList() end
|
|
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)
|
|
-- markens form ændret siden kurserne blev lavet: gemte Courseplay-kurser til marken glemmes
|
|
local fieldInfo = ADFields.getInfo(result.fieldId)
|
|
if fieldInfo ~= nil and ADCourseCache ~= nil then ADCourseCache.checkField(result.fieldId, fieldInfo.shapeSig) end
|
|
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
|