fix: Fields under Stop alt-pause vises stoppet med [Start], [Start] genoptager kun den mark; listen skjules bag redigeringsvinduet (tekst skinnede igennem) (v1.59.3.0)

This commit is contained in:
2026-09-29 18:01:44 +02:00
parent 9b5d71b180
commit 0cac934480
8 changed files with 60 additions and 12 deletions
+17 -4
View File
@@ -291,6 +291,16 @@ function ADFieldJobs.awaitingPlayer(fieldId)
return nil return nil
end end
-- Under global pause: kun denne mark genoptages (de andre venter på Start alle). nil = pause igen.
function ADFieldJobs.setFieldResumed(id, isOn)
ADFieldJobs.state.resumed = ADFieldJobs.state.resumed or {}
ADFieldJobs.state.resumed[id] = isOn ~= false or nil
end
function ADFieldJobs.isFieldResumed(id)
return (ADFieldJobs.state.resumed or {})[id] == true
end
function ADFieldJobs.requestStart(id) function ADFieldJobs.requestStart(id)
ADFieldJobs.note(id, {startRequested = true}) ADFieldJobs.note(id, {startRequested = true})
end end
@@ -313,6 +323,7 @@ end
-- Pause (Stop alt og parkér): intet nyt sendes ud, ingen genstart efter indlæsning. Gemmes. -- Pause (Stop alt og parkér): intet nyt sendes ud, ingen genstart efter indlæsning. Gemmes.
function ADFieldJobs.setPaused(value) function ADFieldJobs.setPaused(value)
ADFieldJobs.state.paused = value == true ADFieldJobs.state.paused = value == true
ADFieldJobs.state.resumed = {}
ADFieldJobs.save() ADFieldJobs.save()
Logging.info(ADFieldJobs.LOG_PREFIX .. "markarbejde %s", value and "på pause" or "genoptaget") Logging.info(ADFieldJobs.LOG_PREFIX .. "markarbejde %s", value and "på pause" or "genoptaget")
end end
@@ -492,9 +503,11 @@ function ADFieldJobs.tick(adEnv, dt)
-- lidt efter start, og indtil da ligner de maskiner ledige (in-game 26/9: kultivatoren blev taget midt -- lidt efter start, og indtil da ligner de maskiner ledige (in-game 26/9: kultivatoren blev taget midt
-- i spillerens eget CP-job 45 s efter indlæsning) -- i spillerens eget CP-job 45 s efter indlæsning)
if ADFieldJobs.now < ADFieldJobs.STARTUP_GRACE_MS then return end if ADFieldJobs.now < ADFieldJobs.STARTUP_GRACE_MS then return end
-- Stop alt og parkér: intet sendes ud og intet genstartes, før spilleren trykker Start alle -- Stop alt og parkér: intet sendes ud og intet genstartes, før spilleren trykker Start alle — undtagen
if ADFieldJobs.state.paused then return end -- marker spilleren har genoptaget enkeltvis ([Start] i Fields-listen, ADFieldJobs.setFieldResumed)
if not ADFieldJobs.resumedAfterLoad then local paused, resumed = ADFieldJobs.state.paused, ADFieldJobs.state.resumed or {}
if paused and next(resumed) == nil then return end
if not paused and not ADFieldJobs.resumedAfterLoad then
-- én gang, før noget nyt sendes ud: CP-maskiner der var midt i et job, fortsætter (og tæller som aktive) -- én gang, før noget nyt sendes ud: CP-maskiner der var midt i et job, fortsætter (og tæller som aktive)
ADFieldJobs.resumedAfterLoad = true ADFieldJobs.resumedAfterLoad = true
local okResume, errResume = pcall(ADFieldWork.resumeAfterLoad, adEnv) local okResume, errResume = pcall(ADFieldWork.resumeAfterLoad, adEnv)
@@ -507,7 +520,7 @@ function ADFieldJobs.tick(adEnv, dt)
if ADPool ~= nil then infos = ADPool.queueOrder(infos, ADFieldJobs.waitingSince) end if ADPool ~= nil then infos = ADPool.queueOrder(infos, ADFieldJobs.waitingSince) end
for index, info in ipairs(infos) do for index, info in ipairs(infos) do
-- passive marker (der sker intet uden brugeren) vurderes kun i deres tiendedel af sekunderne -- passive marker (der sker intet uden brugeren) vurderes kun i deres tiendedel af sekunderne
if not ADFieldModel.isPassive(ADFieldJobs.getField(info.id)) or index % ADFieldJobs.PASSIVE_SLICES == slice then if (not paused or resumed[info.id]) and (not ADFieldModel.isPassive(ADFieldJobs.getField(info.id)) or index % ADFieldJobs.PASSIVE_SLICES == slice) then
stepped = stepped + 1 stepped = stepped + 1
local ok, err = pcall(stepField, adEnv, info, env) local ok, err = pcall(stepField, adEnv, info, env)
if not ok then Logging.warning(ADFieldJobs.LOG_PREFIX .. "F%s fejl: %s", tostring(info.id), tostring(err)) end if not ok then Logging.warning(ADFieldJobs.LOG_PREFIX .. "F%s fejl: %s", tostring(info.id), tostring(err)) end
+9 -2
View File
@@ -88,12 +88,19 @@ ADFieldView.ERROR_REASONS = {
spu_field_reason_tooNarrow = true, spu_field_reason_widthUnknown = true, spu_field_reason_noSowFruit = true, spu_field_reason_tooNarrow = true, spu_field_reason_widthUnknown = true, spu_field_reason_noSowFruit = true,
} }
-- s = {hasMarker, working, awaiting, startRequested, reasonKey} -> "running"|"waiting"|"error"|"stopped" -- Arbejder marken reelt? Under global pause (Stop alt) kun hvis spilleren har genoptaget netop den.
-- s = {working, paused, resumed}
function ADFieldView.isActiveWork(s)
return s.working == true and (not s.paused or s.resumed == true)
end
-- s = {hasMarker, working, paused, resumed, awaiting, startRequested, reasonKey} -> "running"|"waiting"|"error"|"stopped"
function ADFieldView.fieldStatus(s) function ADFieldView.fieldStatus(s)
if not s.hasMarker then return "error" end if not s.hasMarker then return "error" end
if s.reasonKey ~= nil and ADFieldView.ERROR_REASONS[s.reasonKey] then return "error" end if s.reasonKey ~= nil and ADFieldView.ERROR_REASONS[s.reasonKey] then return "error" end
if s.paused and not s.resumed then return "stopped" end
if s.awaiting or s.startRequested then return "waiting" end if s.awaiting or s.startRequested then return "waiting" end
if s.working then return s.reasonKey ~= nil and "waiting" or "running" end if ADFieldView.isActiveWork(s) then return s.reasonKey ~= nil and "waiting" or "running" end
if s.reasonKey ~= nil then return "waiting" end if s.reasonKey ~= nil then return "waiting" end
return "stopped" return "stopped"
end end
@@ -76,6 +76,8 @@ function SmartPickupFrame:openEditPanel(kind, id)
self.editPanelOpen, self.editPanelKind, self.editPanelId = true, kind, id self.editPanelOpen, self.editPanelKind, self.editPanelId = true, kind, id
self:closeGuide() self:closeGuide()
self.editOverlay:setVisible(true) self.editOverlay:setVisible(true)
-- listen skjules bag vinduet: dens tekster skinnede igennem panelet (in-game 29/9)
self.boxLayout:setVisible(false)
self:layoutEditPanel() self:layoutEditPanel()
self:requestRebuild() self:requestRebuild()
end end
@@ -85,6 +87,7 @@ function SmartPickupFrame:hideEditPanel()
self.editPanelOpen, self.editPanelKind, self.editPanelId = false, nil, nil self.editPanelOpen, self.editPanelKind, self.editPanelId = false, nil, nil
self:clearPanelRows() self:clearPanelRows()
if self.editOverlay ~= nil then self.editOverlay:setVisible(false) end if self.editOverlay ~= nil then self.editOverlay:setVisible(false) end
if self.boxLayout ~= nil then self.boxLayout:setVisible(true) end
end end
function SmartPickupFrame:closeEditPanel() function SmartPickupFrame:closeEditPanel()
+21 -5
View File
@@ -109,7 +109,8 @@ function SmartPickupFrame:fieldCells(row)
return { return {
name, crop, self:fieldPlanText(field, info), name, crop, self:fieldPlanText(field, info),
self.i18n:getText(field.plan.mode == "auto" and "spu_field_mode_auto" or "spu_field_mode_manual"), self.i18n:getText(field.plan.mode == "auto" and "spu_field_mode_auto" or "spu_field_mode_manual"),
self:fieldStatusText(field, info, true), self:fieldStatusText(field, info, true) .. ((ADFieldJobs.state.paused and not ADFieldJobs.isFieldResumed(info.id)
and ADFieldModel.isWorking(field)) and (" " .. self.i18n:getText("spu_field_pausedSuffix")) or ""),
ADFlowView.joinCounted(names, ", ", "-"), ADFlowView.joinCounted(names, ", ", "-"),
self:fieldActionText(info.id), self:fieldActionText(info.id),
} }
@@ -168,12 +169,19 @@ function SmartPickupFrame:refreshFieldLevels()
end end
end end
-- Arbejder marken reelt (ikke bare et plan-trin under Stop alt-pause)?
function SmartPickupFrame:fieldIsActive(id, field)
field = field or ADFieldJobs.getField(id)
return field ~= nil and ADFieldView.isActiveWork({working = ADFieldModel.isWorking(field),
paused = ADFieldJobs.state.paused == true, resumed = ADFieldJobs.isFieldResumed(id)})
end
-- [Start] kræver en markør (Stop/Overtag altid muligt når marken arbejder). -- [Start] kræver en markør (Stop/Overtag altid muligt når marken arbejder).
function SmartPickupFrame:fieldCanStart(id) function SmartPickupFrame:fieldCanStart(id)
local field, info = ADFieldJobs.getField(id), ADFields.getInfo(id) local field, info = ADFieldJobs.getField(id), ADFields.getInfo(id)
if field == nil or info == nil then return false end if field == nil or info == nil then return false end
return ADFieldView.canStart({hasMarker = info.markerId ~= nil, return ADFieldView.canStart({hasMarker = info.markerId ~= nil,
working = ADFieldModel.isWorking(field) or ADFieldJobs.awaitingPlayer(id) ~= nil}) working = self:fieldIsActive(id, field) or ADFieldJobs.awaitingPlayer(id) ~= nil})
end end
function SmartPickupFrame:fieldLevel(id) function SmartPickupFrame:fieldLevel(id)
@@ -181,6 +189,7 @@ function SmartPickupFrame:fieldLevel(id)
if field == nil or info == nil then return "stopped" end if field == nil or info == nil then return "stopped" end
local reason = type(field.reason) == "table" and field.reason.key or nil local reason = type(field.reason) == "table" and field.reason.key or nil
return ADFieldView.fieldStatus({hasMarker = info.markerId ~= nil, working = ADFieldModel.isWorking(field), return ADFieldView.fieldStatus({hasMarker = info.markerId ~= nil, working = ADFieldModel.isWorking(field),
paused = ADFieldJobs.state.paused == true, resumed = ADFieldJobs.isFieldResumed(id),
awaiting = ADFieldJobs.awaitingPlayer(id) ~= nil, awaiting = ADFieldJobs.awaitingPlayer(id) ~= nil,
startRequested = ADFieldJobs.isStartRequested ~= nil and ADFieldJobs.isStartRequested(id) or false, startRequested = ADFieldJobs.isStartRequested ~= nil and ADFieldJobs.isStartRequested(id) or false,
reasonKey = reason}) reasonKey = reason})
@@ -190,7 +199,7 @@ end
function SmartPickupFrame:fieldActionText(id, forButton) function SmartPickupFrame:fieldActionText(id, forButton)
local field = ADFieldJobs.getField(id) local field = ADFieldJobs.getField(id)
if ADFieldJobs.awaitingPlayer(id) ~= nil then return self.i18n:getText("spu_field_button_takeover") end if ADFieldJobs.awaitingPlayer(id) ~= nil then return self.i18n:getText("spu_field_button_takeover") end
local isWorking = field ~= nil and ADFieldModel.isWorking(field) local isWorking = self:fieldIsActive(id, field)
if forButton then return self.i18n:getText(isWorking and "spu_field_button_stop" or "spu_field_button_start") end if forButton then return self.i18n:getText(isWorking and "spu_field_button_stop" or "spu_field_button_start") end
return self.i18n:getText(isWorking and "spu_flowList_stop" or "spu_flowList_start") return self.i18n:getText(isWorking and "spu_flowList_stop" or "spu_flowList_start")
end end
@@ -340,7 +349,7 @@ function SmartPickupFrame:refreshFieldRows(adEnv)
if row ~= nil then if row ~= nil then
SmartPickupFrame.setCells(entry.cells, self:fieldCells(row)) SmartPickupFrame.setCells(entry.cells, self:fieldCells(row))
total = total + 1 total = total + 1
if ADFieldModel.isWorking(row.field) then working = working + 1 end if self:fieldIsActive(entry.id, row.field) then working = working + 1 end
end end
end end
self:refreshFieldLevels() self:refreshFieldLevels()
@@ -386,9 +395,16 @@ function SmartPickupFrame:toggleField(id)
ADFieldJobs.requestTakeover(id) ADFieldJobs.requestTakeover(id)
frame.statusOverride = string.format(frame.i18n:getText("spu_field_takeoverRequested"), id) frame.statusOverride = string.format(frame.i18n:getText("spu_field_takeoverRequested"), id)
frame.statusOverrideTicks = SmartPickupFrame.STATUS_OVERRIDE_TICKS frame.statusOverrideTicks = SmartPickupFrame.STATUS_OVERRIDE_TICKS
elseif ADFieldModel.isWorking(field) then elseif frame:fieldIsActive(id, field) then
ADFieldJobs.stopField(frame.getAdEnv(), id) ADFieldJobs.stopField(frame.getAdEnv(), id)
ADFieldJobs.setFieldResumed(id, false)
elseif ADFieldJobs.state.paused and ADFieldModel.isWorking(field) then
-- Stop alt-pause: kun denne mark genoptages fra sit trin (de andre venter på Start alle)
ADFieldJobs.setFieldResumed(id, true)
frame.statusOverride = string.format(frame.i18n:getText("spu_field_startRequested"), id)
frame.statusOverrideTicks = SmartPickupFrame.STATUS_OVERRIDE_TICKS
else else
if ADFieldJobs.state.paused then ADFieldJobs.setFieldResumed(id, true) end
local decision = ADFieldJobs.lastDecision[id] local decision = ADFieldJobs.lastDecision[id]
if decision == nil or decision.care == nil then if decision == nil or decision.care == nil then
ADFieldJobs.forceReady(id) ADFieldJobs.forceReady(id)
+1
View File
@@ -260,6 +260,7 @@
<text name="spu_flowList_status" text="Flows i gang: %d af %d"/> <text name="spu_flowList_status" text="Flows i gang: %d af %d"/>
<text name="spu_panel_flowTitle" text="Rediger flow: %s"/> <text name="spu_panel_flowTitle" text="Rediger flow: %s"/>
<text name="spu_panel_fieldTitle" text="Mark F%d"/> <text name="spu_panel_fieldTitle" text="Mark F%d"/>
<text name="spu_field_pausedSuffix" text="(pause)"/>
<text name="spu_newRunName" text="Flow %d"/> <text name="spu_newRunName" text="Flow %d"/>
<text name="spu_renameTitle" text="Navn på flow"/> <text name="spu_renameTitle" text="Navn på flow"/>
<text name="spu_deleteConfirm" text="Slet run '%s'? Dets kørende traktorer stoppes. Kan ikke fortrydes."/> <text name="spu_deleteConfirm" text="Slet run '%s'? Dets kørende traktorer stoppes. Kan ikke fortrydes."/>
+1
View File
@@ -260,6 +260,7 @@
<text name="spu_flowList_status" text="Flows running: %d of %d"/> <text name="spu_flowList_status" text="Flows running: %d of %d"/>
<text name="spu_panel_flowTitle" text="Edit flow: %s"/> <text name="spu_panel_flowTitle" text="Edit flow: %s"/>
<text name="spu_panel_fieldTitle" text="Field F%d"/> <text name="spu_panel_fieldTitle" text="Field F%d"/>
<text name="spu_field_pausedSuffix" text="(paused)"/>
<text name="spu_newRunName" text="Flow %d"/> <text name="spu_newRunName" text="Flow %d"/>
<text name="spu_renameTitle" text="Flow name"/> <text name="spu_renameTitle" text="Flow name"/>
<text name="spu_deleteConfirm" text="Delete run '%s'? Its running tractors will be stopped. This cannot be undone."/> <text name="spu_deleteConfirm" text="Delete run '%s'? Its running tractors will be stopped. This cannot be undone."/>
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?> <?xml version="1.0" encoding="utf-8" standalone="no"?>
<modDesc descVersion="107"> <modDesc descVersion="107">
<author>masterdraco</author> <author>masterdraco</author>
<version>1.59.2.0</version> <version>1.59.3.0</version>
<title> <title>
<en>AD Smart Pickup</en> <en>AD Smart Pickup</en>
</title> </title>
+7
View File
@@ -22,5 +22,12 @@ check("i ro", V.fieldStatus({hasMarker = true}), "stopped")
check("kan starte: med markør", V.canStart({hasMarker = true, working = false}), true) check("kan starte: med markør", V.canStart({hasMarker = true, working = false}), true)
check("kan starte: uden markør -> nej", V.canStart({hasMarker = false, working = false}), false) check("kan starte: uden markør -> nej", V.canStart({hasMarker = false, working = false}), false)
check("kan stoppe: uden markør men i gang", V.canStart({hasMarker = false, working = true}), true) check("kan stoppe: uden markør men i gang", V.canStart({hasMarker = false, working = true}), true)
-- global pause (Stop alt): arbejdstrin uden maskiner = stoppet, [Start] genoptager kun den mark (in-game 29/9)
check("pause: arbejdstrin -> stoppet", V.fieldStatus({hasMarker = true, working = true, paused = true}), "stopped")
check("pause: genoptaget mark -> kører", V.fieldStatus({hasMarker = true, working = true, paused = true, resumed = true}), "running")
check("pause: mangler markør stadig rød", V.fieldStatus({hasMarker = false, paused = true}), "error")
check("pause: arbejder-tæller falsk", V.isActiveWork({working = true, paused = true}), false)
check("pause: genoptaget arbejder-tæller sand", V.isActiveWork({working = true, paused = true, resumed = true}), true)
check("ingen pause: arbejder", V.isActiveWork({working = true}), true)
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL")) print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
os.exit(failures == 0 and 0 or 1) os.exit(failures == 0 and 0 or 1)