feat(marker): mål-afgrøde pr. mark ('vælg mark + afgrøde, glem den') + brug alle ledige maskiner (standard)
This commit is contained in:
@@ -89,6 +89,12 @@ function ADFieldFleet.pickMany(candidates, role, n, x, z, requiredWidth, accept)
|
||||
return nil, reason, args
|
||||
end
|
||||
|
||||
-- Må sættet sendes ud? "all" (standard): alle ledige maskiner; "ticked": kun med flueben.
|
||||
function ADFieldFleet.isEnabled(mode, enabledIds, id)
|
||||
if mode == "ticked" then return (enabledIds or {})[id] == true end
|
||||
return true
|
||||
end
|
||||
|
||||
function ADFieldFleet.toggle(enabledIds, id)
|
||||
local copy = {}
|
||||
for key, value in pairs(enabledIds or {}) do copy[key] = value end
|
||||
|
||||
@@ -9,7 +9,8 @@ ADFieldJobs.LOG_PREFIX = "ADSmartPickup: "
|
||||
ADFieldJobs.TICK_MS = 1000
|
||||
-- Courseplay kan efterlade hjørner på skæve marker: efter så mange færdige ture pr. sæt går marken videre.
|
||||
ADFieldJobs.MAX_PASSES = 2
|
||||
ADFieldJobs.state = {fields = {}, fleet = {}, assignments = {}}
|
||||
-- fleetMode: "all" = alle ledige maskiner (standard, "vælg og glem"), "ticked" = kun med flueben
|
||||
ADFieldJobs.state = {fields = {}, fleet = {}, assignments = {}, fleetMode = "all"}
|
||||
-- mark-id -> {mower = kursus, rake = kursus, <trin> = fælles multi-tool-kursus}: kopier (kun i hukommelsen;
|
||||
-- efter genindlæsning hentes slå-/rivekurset fra maskinen, som CP selv gemmer kurset på)
|
||||
ADFieldJobs.courses = {}
|
||||
@@ -46,6 +47,14 @@ function ADFieldJobs.decide(field, info, assignments, now, env)
|
||||
end
|
||||
return {action = "start"}
|
||||
end
|
||||
-- mål-afgrøde på en bar mark: klargør og så så snart målet kan sås
|
||||
if info ~= nil and info.kind == "bare" and field.plan.targetFruit ~= nil and field.plan.targetFruit ~= "" then
|
||||
local plantable = env ~= nil and env.plantable ~= nil and env.plantable(field.plan.targetFruit) or false
|
||||
if ADFieldModel.shouldStartBare(field, "bare", plantable) then
|
||||
if not hasMarker then return {action = "wait"} end
|
||||
return {action = "start"}
|
||||
end
|
||||
end
|
||||
if not ADFieldModel.isWorking(field) then
|
||||
local care = ADFieldModel.careNeed(field, info)
|
||||
if care == nil then return {action = "none"} end
|
||||
@@ -124,6 +133,7 @@ function ADFieldJobs.load()
|
||||
local ok, loaded = pcall(ADFieldStorage.load)
|
||||
if ok then
|
||||
ADFieldJobs.state.fields, ADFieldJobs.state.fleet = loaded.fields, loaded.fleet
|
||||
ADFieldJobs.state.fleetMode = loaded.fleetMode or "all"
|
||||
else
|
||||
Logging.warning(ADFieldJobs.LOG_PREFIX .. "marker kunne ikke indlæses: %s", tostring(loaded))
|
||||
end
|
||||
@@ -143,6 +153,17 @@ function ADFieldJobs.forceReady(id)
|
||||
ADFieldJobs.setField(ADFieldModel.forceReady(ADFieldJobs.getField(id)))
|
||||
end
|
||||
|
||||
function ADFieldJobs.setTarget(id, fruitName)
|
||||
ADFieldJobs.setField(ADFieldModel.setTarget(ADFieldJobs.getField(id), fruitName))
|
||||
ADFieldJobs.log(id, "mål-afgrøde: %s", fruitName ~= "" and fruitName or "ingen")
|
||||
ADFieldJobs.save()
|
||||
end
|
||||
|
||||
function ADFieldJobs.setFleetMode(mode)
|
||||
ADFieldJobs.state.fleetMode = mode
|
||||
ADFieldJobs.save()
|
||||
end
|
||||
|
||||
function ADFieldJobs.toggleFleet(vehicleId)
|
||||
ADFieldJobs.state.fleet = ADFieldFleet.toggle(ADFieldJobs.state.fleet, vehicleId)
|
||||
ADFieldJobs.save()
|
||||
@@ -192,7 +213,14 @@ function ADFieldJobs.environment()
|
||||
local weather = g_currentMission.environment.weather
|
||||
return weather ~= nil and weather.getIsRaining ~= nil and weather:getIsRaining() or false
|
||||
end)
|
||||
return {raining = ok and raining == true}
|
||||
return {
|
||||
raining = ok and raining == true,
|
||||
-- kan afgrøden (navn) sås i den aktuelle periode?
|
||||
plantable = function(name)
|
||||
local fruit = g_fruitTypeManager ~= nil and g_fruitTypeManager:getFruitTypeByName(name) or nil
|
||||
return fruit ~= nil and ADCpBridge.isPlantableNow(fruit.index)
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
-- Seneste beslutning pr. mark (GUI viser pleje-behov og grunde).
|
||||
@@ -206,7 +234,7 @@ local function stepField(adEnv, info)
|
||||
local decision = ADFieldJobs.decide(field, info, assignments, ADFieldJobs.now, ADFieldJobs.environment())
|
||||
ADFieldJobs.lastDecision[info.id] = decision
|
||||
if decision.action == "start" then
|
||||
local started = ADFieldModel.start(field, info.kind, info.needs)
|
||||
local started = ADFieldModel.start(field, info.kind, info.needs, info.fruitName)
|
||||
started.lastFruit = info.kind == "harvest" and info.fruitName or field.lastFruit
|
||||
ADFieldJobs.setField(started)
|
||||
ADFieldJobs.log(info.id, "starter (%s: %s)", tostring(info.kind), started.stage)
|
||||
|
||||
@@ -42,7 +42,7 @@ KNOWN_STAGES.careLiming = true
|
||||
local DEFAULT_PLAN = {
|
||||
mode = "manual", product = "auto", rake = false, rigs = 1, unloaders = 1,
|
||||
mulch = false, lime = true, soil = "auto", sow = false, sowFruit = "", roll = false,
|
||||
fertilize = true, weed = true,
|
||||
fertilize = true, weed = true, targetFruit = "", prepAfterMow = false,
|
||||
}
|
||||
local SOIL_VALUES = {auto = true, cultivate = true, plow = true, none = true}
|
||||
local PRODUCTS = {auto = true, silage = true, hay = true, harvest = true}
|
||||
@@ -123,9 +123,51 @@ function ADFieldModel.workStages(plan, kind, needs)
|
||||
if product == "hay" then table.insert(stages, "tedding") end
|
||||
if plan.rake then table.insert(stages, "raking") end
|
||||
table.insert(stages, "collecting")
|
||||
-- mål-afgrøde på en slåmark med en anden afgrøde: efter sidste slæt klargøres og sås målet
|
||||
if plan.prepAfterMow then
|
||||
for _, stage in ipairs(ADFieldModel.prepStages(plan, needs)) do table.insert(stages, stage) end
|
||||
end
|
||||
return stages
|
||||
end
|
||||
|
||||
-- Mål-afgrøde ("vælg mark + afgrøde, glem den"): planen udfyldes ud fra hvad der står på marken nu.
|
||||
-- Står målet der allerede som slåafgrøde (græs -> græs): bare slå igen og igen. Ellers: høst/slå det der
|
||||
-- står, klargør og så målet. Kører altid automatisk. Uden mål returneres planen uændret.
|
||||
function ADFieldModel.applyTarget(plan, kind, currentFruit)
|
||||
local copy = copyPlan(plan)
|
||||
if copy.targetFruit == nil or copy.targetFruit == "" then return copy end
|
||||
copy.mode = "auto"
|
||||
copy.sowFruit = copy.targetFruit
|
||||
if kind == "mowable" then
|
||||
copy.prepAfterMow = currentFruit ~= copy.targetFruit
|
||||
copy.sow = copy.prepAfterMow
|
||||
else
|
||||
copy.prepAfterMow = false
|
||||
copy.sow = true
|
||||
end
|
||||
return copy
|
||||
end
|
||||
|
||||
-- Vælg mål-afgrøde fra menuen ("" = ingen). Med mål kører marken automatisk; en færdig/klar mark sættes
|
||||
-- til venter, så den kan starte forfra. Uden mål: tilbage til manuel.
|
||||
function ADFieldModel.setTarget(field, fruitName)
|
||||
local copy = copyField(field)
|
||||
copy.plan.targetFruit = fruitName or ""
|
||||
copy.plan.mode = copy.plan.targetFruit ~= "" and "auto" or "manual"
|
||||
if not ADFieldModel.isWorking(field) and field.stage == "done" then
|
||||
copy.stage = "idle"
|
||||
end
|
||||
return copy
|
||||
end
|
||||
|
||||
-- Bar mark med mål-afgrøde starter selv klargøring + såning, når målet kan sås nu.
|
||||
function ADFieldModel.shouldStartBare(field, kind, plantableNow)
|
||||
if field.plan.targetFruit == nil or field.plan.targetFruit == "" then return false end
|
||||
-- kun fra idle: efter egen såning står marken "done" (nysået kan læses som bar) — ingen dobbelt-såning
|
||||
if kind ~= "bare" or field.stage ~= "idle" then return false end
|
||||
return plantableNow == true
|
||||
end
|
||||
|
||||
-- Krævet bredde for et sæt: kun læssevognen uden riv skal dække slåmaskinens baner.
|
||||
function ADFieldModel.requiredWidth(field, role)
|
||||
if role == "collector" and not field.plan.rake then
|
||||
@@ -210,9 +252,11 @@ local function freshCycle(copy)
|
||||
end
|
||||
|
||||
-- Første trin i kæden. En tom kæde (bar mark uden jordbehandling eller såning) -> færdig.
|
||||
function ADFieldModel.start(field, kind, needs)
|
||||
-- currentFruit (valgfri): afgrøden på marken nu; med mål-afgrøde udfyldes planen ud fra den.
|
||||
function ADFieldModel.start(field, kind, needs, currentFruit)
|
||||
local copy = copyField(field)
|
||||
local stages = ADFieldModel.workStages(field.plan, kind, needs)
|
||||
copy.plan = ADFieldModel.applyTarget(copy.plan, kind, currentFruit)
|
||||
local stages = ADFieldModel.workStages(copy.plan, kind, needs)
|
||||
copy.stage = stages[1] or "done"
|
||||
copy.kind = kind or "mowable"
|
||||
freshCycle(copy)
|
||||
@@ -379,6 +423,7 @@ function ADFieldModel.toRecord(field)
|
||||
rigs = plan.rigs, unloaders = plan.unloaders, mulch = flag(plan.mulch), lime = flag(plan.lime),
|
||||
soil = plan.soil, sow = flag(plan.sow), sowFruit = plan.sowFruit or "", roll = flag(plan.roll),
|
||||
fertilize = flag(plan.fertilize), weed = flag(plan.weed),
|
||||
targetFruit = plan.targetFruit or "", prepAfterMow = flag(plan.prepAfterMow),
|
||||
kind = field.kind or "", lastFruit = field.lastFruit or "", care = table.concat(care, " "),
|
||||
mowWidth = field.mowWidth or 0,
|
||||
mowVehicle = field.mowVehicleId or "",
|
||||
@@ -415,6 +460,8 @@ function ADFieldModel.fromRecord(record)
|
||||
plan.roll = readFlag(record.roll, false)
|
||||
plan.fertilize = readFlag(record.fertilize, true)
|
||||
plan.weed = readFlag(record.weed, true)
|
||||
plan.targetFruit = record.targetFruit or ""
|
||||
plan.prepAfterMow = readFlag(record.prepAfterMow, false)
|
||||
field.kind = readText(record.kind)
|
||||
field.lastFruit = readText(record.lastFruit)
|
||||
for stage, runs in string.gmatch(record.care or "", "(%w+)=(%d+)") do field.careRuns[stage] = tonumber(runs) end
|
||||
|
||||
@@ -11,7 +11,7 @@ ADFieldStorage.FIELD_TYPES = {
|
||||
id = "Int", stage = "String", mode = "String", product = "String", rake = "Int", store = "String",
|
||||
rigs = "Int", unloaders = "Int", mulch = "Int", lime = "Int", soil = "String", sow = "Int",
|
||||
sowFruit = "String", roll = "Int", fertilize = "Int", weed = "Int",
|
||||
kind = "String", lastFruit = "String", care = "String",
|
||||
kind = "String", lastFruit = "String", care = "String", targetFruit = "String", prepAfterMow = "Int",
|
||||
mowWidth = "Float", mowVehicle = "String", rakeVehicle = "String", windrowOffset = "String",
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ function ADFieldStorage.save(state)
|
||||
ADFieldStorage.writeRecord(xmlFile, string.format("%s.field(%d)", ADFieldStorage.ROOT, index), ADFieldModel.toRecord(field))
|
||||
index = index + 1
|
||||
end
|
||||
xmlFile:setString(ADFieldStorage.ROOT .. "#fleetMode", state.fleetMode or "all")
|
||||
local vehicleIndex = 0
|
||||
for vehicleId in pairs(state.fleet) do
|
||||
xmlFile:setString(string.format("%s.fleet.vehicle(%d)#id", ADFieldStorage.ROOT, vehicleIndex), vehicleId)
|
||||
@@ -57,11 +58,12 @@ function ADFieldStorage.save(state)
|
||||
end
|
||||
|
||||
function ADFieldStorage.load()
|
||||
local result = {fields = {}, fleet = {}}
|
||||
local result = {fields = {}, fleet = {}, fleetMode = "all"}
|
||||
local path = ADFieldStorage.getPath()
|
||||
if path == nil or not fileExists(path) then return result end
|
||||
local xmlFile = XMLFile.load("ADSmartPickupFields", path)
|
||||
if xmlFile == nil then return result end
|
||||
result.fleetMode = xmlFile:getString(ADFieldStorage.ROOT .. "#fleetMode") == "ticked" and "ticked" or "all"
|
||||
xmlFile:iterate(ADFieldStorage.ROOT .. ".field", function(_, key)
|
||||
local field = ADFieldModel.fromRecord(ADFieldStorage.readRecord(xmlFile, key))
|
||||
if field.id ~= nil then result.fields[field.id] = field end
|
||||
|
||||
@@ -113,7 +113,7 @@ function ADFieldWork.getRigs(adEnv)
|
||||
local x, z = vehiclePosition(vehicle)
|
||||
local rig = {
|
||||
id = id, vehicle = vehicle, role = role, label = ADRuns.vehicleLabel(vehicle),
|
||||
enabled = state.fleet[id] == true,
|
||||
enabled = ADFieldFleet.isEnabled(state.fleetMode, state.fleet, id),
|
||||
-- optaget: vores egen opgave, et Smart Pickup-flow, eller AutoDrive/Courseplay kører den allerede
|
||||
-- (fx spillerens egen parkeringstur) — den må ikke kapres midt i en anden kørsel
|
||||
busy = state.assignments[id] ~= nil or ADRunsController.getRunForVehicle(vehicle) ~= nil
|
||||
|
||||
@@ -9,6 +9,7 @@ SmartPickupFrame.FIELD_ROW_KINDS = {
|
||||
fieldProduct = true, fieldMode = true, fieldRake = true, fieldStore = true, fleetVehicle = true,
|
||||
fieldRigs = true, fieldUnloaders = true, fieldMulch = true, fieldLime = true, fieldSoil = true,
|
||||
fieldSow = true, fieldSowFruit = true, fieldRoll = true, fieldFertilize = true, fieldWeed = true,
|
||||
fieldTarget = true, fleetMode = true,
|
||||
}
|
||||
SmartPickupFrame.ROLE_KEYS = {
|
||||
mower = "spu_field_role_mower", tedder = "spu_field_role_tedder", rake = "spu_field_role_rake",
|
||||
@@ -62,12 +63,36 @@ function SmartPickupFrame:fieldStatusText(field, info)
|
||||
if decision ~= nil and decision.care ~= nil and not ADFieldModel.isWorking(field) then
|
||||
text = text .. " — " .. string.format(self.i18n:getText("spu_field_careNeed"), self.i18n:getText("spu_field_stage_" .. decision.care))
|
||||
end
|
||||
local target = field.plan.targetFruit
|
||||
if target ~= nil and target ~= "" and info.kind == "bare" and field.stage == "idle" and not ADFieldJobs.environment().plantable(target) then
|
||||
text = text .. " — " .. string.format(self.i18n:getText("spu_field_waitSowing"), self:fruitTitle(target))
|
||||
end
|
||||
local reason = self:fieldReasonText(field.reason)
|
||||
if reason ~= nil then text = text .. ": " .. reason end
|
||||
return text
|
||||
end
|
||||
|
||||
-- Hvad moden gør med marken frem mod mål-afgrøden (én linje under valget).
|
||||
function SmartPickupFrame:targetSummary(field, info)
|
||||
local target = self:fruitTitle(field.plan.targetFruit)
|
||||
if info.kind == "bare" then
|
||||
return string.format(self.i18n:getText("spu_field_target_bare"), target)
|
||||
end
|
||||
if info.fruitName == field.plan.targetFruit and info.kind == "mowable" then
|
||||
return string.format(self.i18n:getText("spu_field_target_keep"), target)
|
||||
end
|
||||
return string.format(self.i18n:getText("spu_field_target_switch"), tostring(info.cropTitle or "-"), target)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:fruitTitle(name)
|
||||
local fruit = g_fruitTypeManager ~= nil and name ~= nil and name ~= "" and g_fruitTypeManager:getFruitTypeByName(name) or nil
|
||||
return fruit ~= nil and fruit.fillType ~= nil and tostring(fruit.fillType.title) or tostring(name)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:fieldPlanText(field, info)
|
||||
if field.plan.targetFruit ~= nil and field.plan.targetFruit ~= "" then
|
||||
return "-> " .. self:fruitTitle(field.plan.targetFruit)
|
||||
end
|
||||
local text = self.i18n:getText(ADFieldView.planKey(field.plan, info.kind))
|
||||
if field.plan.rake and info.kind == "mowable" then text = text .. " + " .. self.i18n:getText("spu_field_plan_rake") end
|
||||
if field.plan.sow and info.kind ~= "mowable" then text = text .. " + " .. self.i18n:getText("spu_field_plan_sow") end
|
||||
@@ -116,9 +141,9 @@ local function numberTexts(from, to)
|
||||
return texts, values
|
||||
end
|
||||
|
||||
-- Afgrøder der kan sås (første valg: samme som den høstede).
|
||||
function SmartPickupFrame:sowFruitChoices()
|
||||
local texts, values = {self.i18n:getText("spu_field_sowSame")}, {""}
|
||||
-- Afgrøder der kan sås (første valg: samme som den høstede / ingen mål-afgrøde).
|
||||
function SmartPickupFrame:sowFruitChoices(firstKey)
|
||||
local texts, values = {self.i18n:getText(firstKey or "spu_field_sowSame")}, {""}
|
||||
for _, fruit in ipairs(g_fruitTypeManager ~= nil and g_fruitTypeManager.fruitTypes or {}) do
|
||||
if fruit.allowsSeeding ~= false and fruit.fillType ~= nil and fruit.name ~= nil then
|
||||
table.insert(texts, tostring(fruit.fillType.title or fruit.name))
|
||||
@@ -165,7 +190,14 @@ function SmartPickupFrame:fillFieldDetail(adEnv, info)
|
||||
local yesNo = {i18n:getText("ui_no"), i18n:getText("ui_yes")}
|
||||
local crop = info.kind == "bare" and i18n:getText("spu_field_bare") or tostring(info.cropTitle or "-")
|
||||
self:addTextRow(string.format(i18n:getText("spu_field_section"), info.id, crop))
|
||||
self:addToggleRow("fieldMode", i18n:getText("spu_field_mode"), {i18n:getText("spu_field_mode_manual"), i18n:getText("spu_field_mode_auto")}, plan.mode == "auto")
|
||||
local targetTexts, targetValues = self:sowFruitChoices("spu_field_target_none")
|
||||
self:addChoiceRow("fieldTarget", i18n:getText("spu_field_target"), targetTexts, targetValues, plan.targetFruit or "")
|
||||
local hasTarget = plan.targetFruit ~= nil and plan.targetFruit ~= ""
|
||||
if hasTarget then
|
||||
self:addTextRow(" " .. self:targetSummary(field, info))
|
||||
else
|
||||
self:addToggleRow("fieldMode", i18n:getText("spu_field_mode"), {i18n:getText("spu_field_mode_manual"), i18n:getText("spu_field_mode_auto")}, plan.mode == "auto")
|
||||
end
|
||||
local rigTexts, rigValues = numberTexts(1, ADFieldModel.MAX_RIGS)
|
||||
self:addChoiceRow("fieldRigs", i18n:getText("spu_field_rigs"), rigTexts, rigValues, plan.rigs or 1)
|
||||
if info.kind == "mowable" then
|
||||
@@ -182,10 +214,14 @@ function SmartPickupFrame:fillFieldDetail(adEnv, info)
|
||||
local soilTexts = {}
|
||||
for _, value in ipairs(SmartPickupFrame.SOIL_VALUES) do table.insert(soilTexts, i18n:getText("spu_field_soil_" .. value)) end
|
||||
self:addChoiceRow("fieldSoil", i18n:getText("spu_field_soil"), soilTexts, SmartPickupFrame.SOIL_VALUES, plan.soil or "auto")
|
||||
self:addToggleRow("fieldSow", i18n:getText("spu_field_sow"), yesNo, plan.sow == true)
|
||||
if plan.sow then
|
||||
local fruitTexts, fruitValues = self:sowFruitChoices()
|
||||
self:addChoiceRow("fieldSowFruit", i18n:getText("spu_field_sowFruit"), fruitTexts, fruitValues, plan.sowFruit or "")
|
||||
if not hasTarget then
|
||||
self:addToggleRow("fieldSow", i18n:getText("spu_field_sow"), yesNo, plan.sow == true)
|
||||
if plan.sow then
|
||||
local fruitTexts, fruitValues = self:sowFruitChoices()
|
||||
self:addChoiceRow("fieldSowFruit", i18n:getText("spu_field_sowFruit"), fruitTexts, fruitValues, plan.sowFruit or "")
|
||||
end
|
||||
end
|
||||
if hasTarget or plan.sow then
|
||||
self:addToggleRow("fieldRoll", i18n:getText("spu_field_roll"), yesNo, plan.roll == true)
|
||||
end
|
||||
end
|
||||
@@ -286,6 +322,8 @@ end
|
||||
function SmartPickupFrame:fillFleetRows(adEnv)
|
||||
local i18n = self.i18n
|
||||
self:addTextRow(i18n:getText("spu_field_section_fleet"))
|
||||
local useAll = ADFieldJobs.state.fleetMode ~= "ticked"
|
||||
self:addToggleRow("fleetMode", i18n:getText("spu_field_fleetAll"), {i18n:getText("ui_no"), i18n:getText("ui_yes")}, useAll)
|
||||
local rigs = ADFieldJobs.getRigs(adEnv)
|
||||
table.sort(rigs, function(a, b)
|
||||
if a.role ~= b.role then return a.role < b.role end
|
||||
@@ -332,6 +370,12 @@ function SmartPickupFrame:onClickFieldRow(state, data)
|
||||
local id = frame.selectedFieldId
|
||||
if data.kind == "fleetVehicle" then
|
||||
ADFieldJobs.toggleFleet(data.vehicleId)
|
||||
elseif data.kind == "fleetMode" then
|
||||
ADFieldJobs.setFleetMode(isOn and "all" or "ticked")
|
||||
elseif id == nil then
|
||||
return
|
||||
elseif data.kind == "fieldTarget" then
|
||||
ADFieldJobs.setTarget(id, data.values ~= nil and data.values[state] or "")
|
||||
elseif id == nil then
|
||||
return
|
||||
elseif SmartPickupFrame.PLAN_CHOICES[data.kind] ~= nil then
|
||||
|
||||
@@ -153,6 +153,13 @@
|
||||
<text name="spu_field_weed" text="Bekæmp ukrudt"/>
|
||||
<text name="spu_field_notice_done" text="er færdig"/>
|
||||
<text name="spu_field_reason_rain" text="venter på tørvejr"/>
|
||||
<text name="spu_field_target" text="Afgrøde på marken (moden passer resten)"/>
|
||||
<text name="spu_field_target_none" text="Ingen — planlæg selv"/>
|
||||
<text name="spu_field_target_bare" text="Klargøres og tilsås med %s, så snart det er såtid"/>
|
||||
<text name="spu_field_target_keep" text="%s står allerede: slås og samles op, hver gang den er klar"/>
|
||||
<text name="spu_field_target_switch" text="%s får lov at vokse færdig og høstes/slås; derefter klargøres og tilsås med %s"/>
|
||||
<text name="spu_field_waitSowing" text="venter på såtid for %s"/>
|
||||
<text name="spu_field_fleetAll" text="Brug alle ledige maskiner (Nej = kun med flueben)"/>
|
||||
<text name="spu_button_start" text="Start run"/>
|
||||
<text name="spu_button_stop" text="Stop run"/>
|
||||
<text name="spu_button_new" text="Nyt run"/>
|
||||
|
||||
@@ -153,6 +153,13 @@
|
||||
<text name="spu_field_weed" text="Control weeds"/>
|
||||
<text name="spu_field_notice_done" text="is done"/>
|
||||
<text name="spu_field_reason_rain" text="waiting for dry weather"/>
|
||||
<text name="spu_field_target" text="Crop on the field (the mod handles the rest)"/>
|
||||
<text name="spu_field_target_none" text="None — plan it yourself"/>
|
||||
<text name="spu_field_target_bare" text="Prepared and sown with %s as soon as it is sowing time"/>
|
||||
<text name="spu_field_target_keep" text="%s is already there: mowed and collected every time it is ready"/>
|
||||
<text name="spu_field_target_switch" text="%s is left to finish growing and is harvested/mowed; then the field is prepared and sown with %s"/>
|
||||
<text name="spu_field_waitSowing" text="waiting for sowing time for %s"/>
|
||||
<text name="spu_field_fleetAll" text="Use all free machines (No = only ticked ones)"/>
|
||||
<text name="spu_button_start" text="Start run"/>
|
||||
<text name="spu_button_stop" text="Stop run"/>
|
||||
<text name="spu_button_new" text="New run"/>
|
||||
|
||||
Reference in New Issue
Block a user