fix(kæde): afhængigheds-advarsel uden støj fra auto-flows, alternative opskrifter og kæder

- Auto-flowets mål tæller kun for varer gården forbruger (eller en kæde vil
  have); stald-foder/auto-behov uden kendt forbrug er ikke nødvendigt. Manuel
  flow-vare og kæde-input gælder også uden kendte lagerdage.
- En slukket opskrift springes over, når en anden tændt opskrift i samme
  fabrik laver varen.
- Behov kun fra kæder giver ingen advarsel/post (Task 10 melder kæderne).
This commit is contained in:
2026-09-30 15:13:15 +02:00
parent 9fde03f950
commit e9f1251471
5 changed files with 66 additions and 18 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ står i [docs/BRUGERMANUAL.md](docs/BRUGERMANUAL.md) (dansk) og [docs/USER_MANUA
## 1.61 — Produktionskæder
- **1.61.0** Produktionskæder: slå et produkt til i en fabrik, og moden holder det kørende helt tilbage til marken. Kæden regner baglæns gennem dine egne fabrikker og stalde til afgrøderne og ser 12 måneder frem. Ny fane **Kæder** med træ pr. rod-produktion, farvet status, fold ud/ind og **[Pause]**/**[Start]**. Marker markeret **Fri til kæden** skifter afgrøde automatisk (højst 2 i minuttet); andre marker får forslag med **[Godkend]**/**[Afvis]** (højst 3 pr. afgrøde) i fanen og som ét samlet punkt i **Kræver handling**. En afgrøde, du selv har valgt, ændres aldrig. Mellemled tændes og slukkes kun igen, hvis kæden tændte dem. Flows **Kæde: <vare> → <bygning>** oprettes med en ledig pool-traktor og tipvogn (ellers stoppet: *mangler traktor/vogn*; paller altid stoppet) og stoppes, ikke slettes, når kæden slås fra. Dine egne tændte produktioner bruges som kilde først; slukker du en produktion, tænder kæden den ikke igen, før du tænder en ny. Stoppede kædeflows slippes af kæden. Ingen handlinger de første 2 minutter, ingen markskift før alle marker er scannet, og intet slukkes ved delvise læsefejl. Begrænsninger: intet køb, ingen dyrekøb, flerårige afgrøder og græsmarker skiftes aldrig, grundudbytte uden gødningsbonus. **Vigtigt:** hver produktion, du tænder i en fabrik, prøver moden at forsyne — tænd kun det, du vil have produceret; sluk produktionen eller tryk [Pause] for at stoppe kæden. Manglende led forklares i klart sprog med råd (*Ingen af dine fabrikker laver Mel — byg en eller køb*, *Mølle kan kun lave 800 af 1.0k/md*, *Dine stalde leverer ikke nok Mælk …*, *… er slukket af dig*, *Kredsløb omkring …*): som rød tekst under varen i fanen Kæder, som én rød linje pr. kæde i **Kræver handling** (højst 2; klik åbner kæden foldet ud) og som engangsbesked med kædens navn foran, når et nyt led mangler (ikke i opstartsfristen eller mens markerne scannes). Nyt **statusvindue** på skærmen (i stil med Simple Inspector), som slås til/fra med **venstre Alt + Insert** (kan ændres under Styring; virker til fods og i køretøjer): øverst til højre under info-boksen vises flow-traktorernes handling og fyld, markarbejde i gang, kæder med manglende led og advarsler (slukkede nødvendige fabrikker, køretøjer der har stået stille over 2 min — solgte vises ikke —, ventende kædeforslag); traktorlinjernes farve følger flowets niveau som Flows-listen — højst 18 linjer, opdateres hvert sekund, skjules ved menu/dialog, skjult HUD og søvn; tændt/slukket gemmes pr. bruger i `modSettings/FS25_ADSmartPickup/status.xml`. **Advarsel når en nødvendig fabrik slukkes** (også uden kæder): slukker du en produktion, hvis vare et tændt flow kører (valgt vare eller målet tager den i auto), en stald æder eller en aktiv kæde bruger, kommer én besked pr. slukning (*Advarsel: du slukkede Fermenteringssilo 3 (Ensilage) — Cow Food, Goat Food +1 bruger det. Lageret rækker ca. 12 dage.*) og en rød linje *Slukket men nødvendig: …* i **Kræver handling** (højst 2; klik åbner fanen Fabrikker, eller Kæder hvis kun en kæde bruger varen) og i statusvinduet, så længe den er slukket og nødvendig. Ingen advarsel når en anden tændt produktion dækker med nok kapacitet, lageret rækker over 60 dage, kæden selv slukkede den, eller den allerede var slukket ved indlæsning; produktioner ingen bruger, advarer aldrig. Manual og ordliste opdateret.
- **1.61.0** Produktionskæder: slå et produkt til i en fabrik, og moden holder det kørende helt tilbage til marken. Kæden regner baglæns gennem dine egne fabrikker og stalde til afgrøderne og ser 12 måneder frem. Ny fane **Kæder** med træ pr. rod-produktion, farvet status, fold ud/ind og **[Pause]**/**[Start]**. Marker markeret **Fri til kæden** skifter afgrøde automatisk (højst 2 i minuttet); andre marker får forslag med **[Godkend]**/**[Afvis]** (højst 3 pr. afgrøde) i fanen og som ét samlet punkt i **Kræver handling**. En afgrøde, du selv har valgt, ændres aldrig. Mellemled tændes og slukkes kun igen, hvis kæden tændte dem. Flows **Kæde: <vare> → <bygning>** oprettes med en ledig pool-traktor og tipvogn (ellers stoppet: *mangler traktor/vogn*; paller altid stoppet) og stoppes, ikke slettes, når kæden slås fra. Dine egne tændte produktioner bruges som kilde først; slukker du en produktion, tænder kæden den ikke igen, før du tænder en ny. Stoppede kædeflows slippes af kæden. Ingen handlinger de første 2 minutter, ingen markskift før alle marker er scannet, og intet slukkes ved delvise læsefejl. Begrænsninger: intet køb, ingen dyrekøb, flerårige afgrøder og græsmarker skiftes aldrig, grundudbytte uden gødningsbonus. **Vigtigt:** hver produktion, du tænder i en fabrik, prøver moden at forsyne — tænd kun det, du vil have produceret; sluk produktionen eller tryk [Pause] for at stoppe kæden. Manglende led forklares i klart sprog med råd (*Ingen af dine fabrikker laver Mel — byg en eller køb*, *Mølle kan kun lave 800 af 1.0k/md*, *Dine stalde leverer ikke nok Mælk …*, *… er slukket af dig*, *Kredsløb omkring …*): som rød tekst under varen i fanen Kæder, som én rød linje pr. kæde i **Kræver handling** (højst 2; klik åbner kæden foldet ud) og som engangsbesked med kædens navn foran, når et nyt led mangler (ikke i opstartsfristen eller mens markerne scannes). Nyt **statusvindue** på skærmen (i stil med Simple Inspector), som slås til/fra med **venstre Alt + Insert** (kan ændres under Styring; virker til fods og i køretøjer): øverst til højre under info-boksen vises flow-traktorernes handling og fyld, markarbejde i gang, kæder med manglende led og advarsler (slukkede nødvendige fabrikker, køretøjer der har stået stille over 2 min — solgte vises ikke —, ventende kædeforslag); traktorlinjernes farve følger flowets niveau som Flows-listen — højst 18 linjer, opdateres hvert sekund, skjules ved menu/dialog, skjult HUD og søvn; tændt/slukket gemmes pr. bruger i `modSettings/FS25_ADSmartPickup/status.xml`. **Advarsel når en nødvendig fabrik slukkes** (også uden kæder): slukker du en produktion, hvis vare et tændt flow kører (valgt vare, eller målet tager den i auto og gården forbruger den), en stald æder eller en aktiv kæde bruger sammen med et flow/en stald, kommer én besked pr. slukning (*Advarsel: du slukkede Fermenteringssilo 3 (Ensilage) — Cow Food, Goat Food +1 bruger det. Lageret rækker ca. 12 dage.*) og en rød linje *Slukket men nødvendig: …* i **Kræver handling** (højst 2; klik åbner fanen Fabrikker) og i statusvinduet, så længe den er slukket og nødvendig. Ingen advarsel når en anden opskrift i samme fabrik laver varen og er tændt, en anden tændt produktion dækker med nok kapacitet, kun kæder bruger varen (meldes som manglende led), lageret rækker over 60 dage, kæden selv slukkede den, eller den allerede var slukket ved indlæsning; produktioner ingen bruger, advarer aldrig. Manual og ordliste opdateret.
## 1.60 — "Kræver handling" → flow, menuplacering, flow-vogne i guiden
+10 -1
View File
@@ -334,8 +334,17 @@ function ADChainData.dependencyInputs(data, chain, flows)
end
end
table.sort(goods)
-- auto-flowets mål tager mange varer (fx biogas: korn, ensilage, gylle): kun varer gården faktisk forbruger
-- (stald eller fabrik) eller en kæde vil have, tæller
local consumed = {}
for _, name in ipairs(goods) do
local rate = (data.rates or {})[name]
if (rate ~= nil and (rate.consumption or 0) > 0) or ((chain ~= nil and chain.demand or {})[name] or 0) > 0 then
table.insert(consumed, name)
end
end
local needed = ADDependency.neededOutputs(flows, data.barnFood, ADChainData.chainInputs(chain, data.fillTitles),
#goods > 0 and ADChainData.acceptsMap(data, flows, goods) or {})
#consumed > 0 and ADChainData.acceptsMap(data, flows, consumed) or {})
local adjustment = data.timeAdjustment or 1
local capacity, demand, stockDays = {}, {}, {}
for name, perMonth in pairs(ADDependency.capacity(data.recipes)) do capacity[name] = perMonth * adjustment end
+38 -10
View File
@@ -23,24 +23,27 @@ end
-- flows = {{name, kind, stopped, targetBuildingIds, ingredientMode, ingredients}}
-- barnFood = {[vare] = {staldnavn...}}, chainInputs = {[vare] = {kædenavn...}}
-- accepts = {[bygnings-id] = {[vare] = true}}: hvad auto-flowenes mål tager (adapteren slår op)
-- -> {[vare] = {users = {navn...}, onlyChain}} (brugere i rækkefølgen flows, stalde, kæder; hver kun én gang)
-- -> {[vare] = {users = {navn...}, onlyChain, strong}} (brugere i rækkefølgen flows, stalde, kæder; hver kun én gang).
-- strong = varen er valgt som manuel vare i et flow eller er kæde-input: behovet gælder også uden kendt forbrug.
-- Stald-foder og auto-flowenes mål er "svage": uden kendt forbrug (lagerdage) er de ikke nødvendige.
function ADDependency.neededOutputs(flows, barnFood, chainInputs, accepts)
local result = {}
local function add(name, user, isChain)
local function add(name, user, isChain, isStrong)
if name == nil or user == nil then return end
local entry = result[name]
if entry == nil then
entry = {users = {}, onlyChain = true}
entry = {users = {}, onlyChain = true, strong = false}
result[name] = entry
end
if not isChain then entry.onlyChain = false end
if isStrong then entry.strong = true end
if not contains(entry.users, user) then table.insert(entry.users, user) end
end
for _, flow in ipairs(flows or {}) do
if flow.kind ~= "outbound" and not flow.stopped then
local user = tostring(flow.name or "?")
if flow.ingredientMode == "manual" then
for _, name in ipairs(flow.ingredients or {}) do add(name, user, false) end
for _, name in ipairs(flow.ingredients or {}) do add(name, user, false, true) end
else
for _, building in ipairs(flow.targetBuildingIds or {}) do
for _, name in ipairs(sortedKeys((accepts or {})[building])) do add(name, user, false) end
@@ -52,7 +55,7 @@ function ADDependency.neededOutputs(flows, barnFood, chainInputs, accepts)
for _, barn in ipairs(barnFood[name]) do add(name, tostring(barn), false) end
end
for _, name in ipairs(sortedKeys(chainInputs)) do
for _, root in ipairs(chainInputs[name]) do add(name, tostring(root), true) end
for _, root in ipairs(chainInputs[name]) do add(name, tostring(root), true, true) end
end
return result
end
@@ -91,13 +94,34 @@ local function stockLasts(name, stockDays)
return days ~= nil and days > ADDependency.STOCK_DAYS_OK
end
-- {[bygning|vare] = true} for tændte opskrifter: spilleren har valgt hvilken opskrift i fabrikken der kører.
local function enabledInBuilding(recipes)
local result = {}
for _, recipe in ipairs(recipes or {}) do
if recipe.enabled then
for name, amount in pairs(recipe.outputs or {}) do
if (amount or 0) > 0 then result[tostring(recipe.building) .. "|" .. name] = true end
end
end
end
return result
end
-- Er behovet for varen reelt? Kun kæder: nej (Task 10 melder kæderne). Svagt behov (stald-foder, auto-flowets mål)
-- kræver kendt forbrug (lagerdage); manuel flow-vare og kæde-input gælder også uden.
local function isNeeded(need, name, stockDays)
if need == nil or need.onlyChain then return false end
return need.strong == true or (stockDays or {})[name] ~= nil
end
-- Første nødvendige, udækkede vare (efter navn) for en slukket produktion (ikke kædens) -> advarsel eller nil.
local function check(recipe, needed, stockDays, otherCapacity, demand)
local function check(recipe, needed, stockDays, otherCapacity, demand, alternatives)
if recipe.enabled or recipe.byChain then return nil end
for _, name in ipairs(sortedKeys(recipe.outputs)) do
local need = (needed or {})[name]
if need ~= nil and (recipe.outputs[name] or 0) > 0 and not isCovered(name, otherCapacity, demand)
and not stockLasts(name, stockDays) then
if isNeeded(need, name, stockDays) and (recipe.outputs[name] or 0) > 0
and not alternatives[tostring(recipe.building) .. "|" .. name]
and not isCovered(name, otherCapacity, demand) and not stockLasts(name, stockDays) then
local days = (stockDays or {})[name]
return {recipeKey = recipe.key, building = recipe.building, buildingName = recipe.buildingName, fillType = name,
users = need.users, onlyChain = need.onlyChain == true, days = days}
@@ -109,8 +133,9 @@ end
-- Alle slukkede, nødvendige produktioner (én pr. fabrik) — "Slukket men nødvendig" i Kræver handling.
function ADDependency.offNeeded(recipes, needed, stockDays, otherCapacity, demand)
local result, seen = {}, {}
local alternatives = enabledInBuilding(recipes)
for _, recipe in ipairs(recipes or {}) do
local warning = check(recipe, needed, stockDays, otherCapacity, demand)
local warning = check(recipe, needed, stockDays, otherCapacity, demand, alternatives)
if warning ~= nil and not seen[tostring(warning.building)] then
seen[tostring(warning.building)] = true
table.insert(result, warning)
@@ -119,14 +144,17 @@ function ADDependency.offNeeded(recipes, needed, stockDays, otherCapacity, deman
return result
end
-- Fælles regler (warnings og offNeeded): ingen advarsel når en anden opskrift i SAMME fabrik laver varen og er
-- tændt, når andre tændte produktioner dækker behovet, når lageret rækker > 60 dage, eller når kun kæder bruger varen.
-- Nye slukninger siden sidste evaluering: tændt i prevEnabled, slukket nu, nødvendig og ikke dækket.
-- prevEnabled = nil (første evaluering efter indlæsning) -> ingen. Én pr. fabrik og vare.
function ADDependency.warnings(prevEnabled, recipes, needed, stockDays, otherCapacity, demand)
local result, seen = {}, {}
if prevEnabled == nil then return result end
local alternatives = enabledInBuilding(recipes)
for _, recipe in ipairs(recipes or {}) do
if prevEnabled[recipe.key] then
local warning = check(recipe, needed, stockDays, otherCapacity, demand)
local warning = check(recipe, needed, stockDays, otherCapacity, demand, alternatives)
local id = warning ~= nil and (tostring(warning.building) .. "|" .. warning.fillType) or nil
if warning ~= nil and not seen[id] then
seen[id] = true
+8 -3
View File
@@ -694,9 +694,12 @@ Beskederne:
Slukker du en produktion, som gården er afhængig af, advarer moden dig — også når ingen kæde er i gang. En
produktion er nødvendig, når en af dens varer bruges af gården:
- et tændt forsyningsflow kører varen (valgt som vare, eller flowets mål tager varen i auto),
- et tændt forsyningsflow har varen valgt som vare,
- et tændt flow i auto kører til et mål, der tager varen, og gården forbruger varen,
- en stald æder varen lige nu, eller
- en aktiv kæde har varen som input.
- en aktiv kæde har varen som input (bruger kun kæder varen, meldes det i stedet som manglende led, se ovenfor).
Ved flows i auto og stalde skal gårdens forbrug af varen kendes; ellers regnes varen ikke som nødvendig.
Eksempel: du slukker fermenteringssiloerne, men flowene *Cow Food*, *Goat Food* og *Biogas Silage* henter
ensilage. Så kommer beskeden *Advarsel: du slukkede Fermenteringssilo 3 (Ensilage) — Cow Food, Goat Food +1
@@ -705,10 +708,12 @@ de). Beskeden kommer én gang pr. slukning, højst et minut efter.
Så længe produktionen er slukket og stadig nødvendig, står der en rød linje i **Kræver handling**:
*Slukket men nødvendig: Fermenteringssilo 3* (højst 2; også i statusvinduet under Advarsler). Et klik åbner
lagerfanen **Fabrikker** — eller **Kæder**, hvis kun en kæde bruger varen.
lagerfanen **Fabrikker**.
Der advares ikke, når:
- en anden opskrift i samme fabrik laver varen og er tændt (du har valgt, hvilken opskrift der kører — fx én
ensilage-opskrift i en fermenteringssilo),
- en anden tændt produktion laver varen med nok kapacitet,
- gården har lager til mere end 60 dage,
- kæden selv slukkede produktionen, eller
+9 -3
View File
@@ -710,9 +710,13 @@ The messages:
If you switch off a production the farm depends on, the mod warns you — also when no chain is running. A
production is needed when one of its goods is used by the farm:
- a running supply flow carries the goods (chosen as goods, or the flow's target takes the goods in auto),
- a running supply flow has the goods chosen as goods,
- a running flow in auto goes to a target that takes the goods, and the farm consumes the goods,
- a barn is eating the goods right now, or
- an active chain has the goods as input.
- an active chain has the goods as input (if only chains use the goods, it is reported as a missing link
instead, see above).
For auto flows and barns the farm's consumption of the goods must be known; otherwise the goods do not count as needed.
Example: you switch off the fermenting silos, but the flows *Cow Food*, *Goat Food* and *Biogas Silage* fetch
silage. You then get the message *Warning: you switched off Fermenting silo 3 (Silage) — Cow Food, Goat Food
@@ -721,10 +725,12 @@ The message comes once per switch-off, at most a minute later.
As long as the production is off and still needed, **Needs attention** shows a red line: *Switched off but
needed: Fermenting silo 3* (at most 2; also in the status window under Warnings). Clicking opens the storage
tab **Factories** — or **Chains** if only a chain uses the goods.
tab **Factories**.
No warning when:
- another recipe in the same factory makes the goods and is on (you chose which recipe runs — for example one
silage recipe in a fermenting silo),
- another running production makes the goods with enough capacity,
- the farm has stock for more than 60 days,
- the chain switched the production off itself, or