feat: spuSellBlock slår salgssteder fra/til pr. savegame

This commit is contained in:
2026-09-30 23:35:01 +02:00
parent e229a27624
commit bb287a8154
7 changed files with 169 additions and 4 deletions
+2
View File
@@ -1478,6 +1478,7 @@ function ADRunsController.save()
if ADFieldSilos ~= nil then pcall(ADFieldSilos.save) end
-- kædens tilstand (tændte mellemled, pausede kæder, afviste forslag) — samme gem-regel som navnefilen
if ADChain ~= nil and ADChain.save ~= nil then pcall(ADChain.save) end
if ADSellBlock ~= nil and ADSellBlock.save ~= nil then pcall(ADSellBlock.save) end
-- navnefilen skal skrives under spillets gem: FS25 genskriver savegame-mappen, og filer ingen skriver
-- under gemningen forsvinder (in-game 27/9: ADSmartPickup_names.xml blev slettet ved første gem)
if ADNames ~= nil and ADNames.byId ~= nil then pcall(ADNames.save) end
@@ -1498,6 +1499,7 @@ function ADRunsController.load(adEnv)
pcall(ADRunsController.migrateBuildings, adEnv)
if ADFieldSilos ~= nil then pcall(ADFieldSilos.load) end
if ADChain ~= nil and ADChain.load ~= nil then pcall(ADChain.load) end
if ADSellBlock ~= nil and ADSellBlock.load ~= nil then pcall(ADSellBlock.load) end
if ADCpResume ~= nil then pcall(ADCpResume.load) end
local vehiclesById = getFarmVehiclesById(adEnv)
for _, run in ipairs(store.runs) do
+154
View File
@@ -0,0 +1,154 @@
-- AD Sell Block
-- Salgssteder spilleren har slået fra (in-game 30/9: "Market Price Liquid Fill Station" fra FarmFillStations gik i stå
-- ved aflæsning af gylle). Konsol: spuSellBlock viser salgsstederne; spuSellBlock <del af navn> slår dem fra/til.
-- Udkørsel (ADSources.findSellMarkers) og priser (ADSources.getMarketQuote) springer udelukkede over. Gemmes pr.
-- savegame i ADSmartPickup_sellblock.xml (skrives fra ADRunsController.save, som de andre filer).
ADSellBlock = {}
ADSellBlock.FILE_NAME = "ADSmartPickup_sellblock.xml"
ADSellBlock.ROOT = "sellBlock"
ADSellBlock.blocked = {} -- {[stationId] = visningsnavn}
-- ---- ren logik ----
-- stations = {{id, names = {...}}}, query = del af et navn (små/store bogstaver ligegyldige) -> matchende stationer
function ADSellBlock.match(stations, query)
local wanted = string.lower(tostring(query or ""))
local hits = {}
if wanted == "" then return hits end
for _, station in ipairs(stations or {}) do
for _, name in ipairs(station.names or {}) do
if string.find(string.lower(tostring(name)), wanted, 1, true) ~= nil then
table.insert(hits, station)
break
end
end
end
return hits
end
-- Ny tabel: hver station skiftes (fra -> til, til -> fra). Første navn huskes til visning.
function ADSellBlock.toggle(blocked, stations)
local result = {}
for id, name in pairs(blocked or {}) do result[id] = name end
for _, station in ipairs(stations or {}) do
if result[station.id] ~= nil then
result[station.id] = nil
else
result[station.id] = tostring((station.names or {})[1] or station.id)
end
end
return result
end
-- ---- spil ----
local function stationId(station)
local placeable = station ~= nil and station.owningPlaceable or nil
if placeable ~= nil and placeable.uniqueId ~= nil then return tostring(placeable.uniqueId) end
return nil
end
function ADSellBlock.isBlocked(station)
local id = stationId(station)
return id ~= nil and ADSellBlock.blocked[id] ~= nil
end
local function stationNames(station)
local names = {}
local placeable = station.owningPlaceable
if placeable ~= nil and placeable.getName ~= nil then
local ok, name = pcall(placeable.getName, placeable)
if ok and name ~= nil then table.insert(names, name) end
end
if station.getName ~= nil then
local ok, name = pcall(station.getName, station)
if ok and name ~= nil then table.insert(names, name) end
end
return names
end
-- Alle salgssteder med AD-markør -> {{id, names}} (markørens navn først: det spilleren ser i AutoDrive).
local function sellStations(adEnv)
local list, byId = {}, {}
local farmId = g_currentMission:getFarmId()
for _, marker in pairs(adEnv.ADGraphManager:getMapMarkers()) do
local station = ADSmartPickup.getUnloadStationAtWayPointId(adEnv, marker.id, farmId)
local id = station ~= nil and ADPrices.isSellingStation(station) and stationId(station) or nil
if id ~= nil then
if byId[id] == nil then
byId[id] = {id = id, names = {}}
table.insert(list, byId[id])
for _, name in ipairs(stationNames(station)) do table.insert(byId[id].names, name) end
end
table.insert(byId[id].names, 1, marker.name)
end
end
table.sort(list, function(a, b) return tostring(a.names[1]) < tostring(b.names[1]) end)
return list
end
function ADSellBlock:consoleSellBlock(...)
local query = table.concat({...}, " ")
local adEnv = FS25_AutoDrive
if adEnv == nil or adEnv.ADGraphManager == nil then return "AutoDrive ikke fundet" end
local stations = sellStations(adEnv)
if query == "" then
local lines = {"Salgssteder (spuSellBlock <del af navn> slår fra/til):"}
for _, station in ipairs(stations) do
table.insert(lines, string.format(" %s %s", ADSellBlock.blocked[station.id] ~= nil and "[FRA]" or "[til]", table.concat(station.names, " / ")))
end
return table.concat(lines, "\n")
end
local hits = ADSellBlock.match(stations, query)
if #hits == 0 then return string.format("Intet salgssted matcher '%s' (spuSellBlock uden navn viser listen)", query) end
ADSellBlock.blocked = ADSellBlock.toggle(ADSellBlock.blocked, hits)
local lines = {}
for _, station in ipairs(hits) do
local text = string.format("%s: %s", station.names[1], ADSellBlock.blocked[station.id] ~= nil and "slået FRA som salgssted" or "bruges igen")
table.insert(lines, text)
Logging.info("ADSmartPickup: salgssted " .. text)
end
if ADRunsController ~= nil and ADRunsController.save ~= nil then pcall(ADRunsController.save) end
return table.concat(lines, "\n")
end
local function getPath()
local path = ADRunsStorage ~= nil and ADRunsStorage.getPath() or nil
if path == nil then return nil end
return (path:gsub(ADRunsStorage.FILE_NAME .. "$", ADSellBlock.FILE_NAME))
end
function ADSellBlock.save()
local path = getPath()
if path == nil then return false end
local xmlFile = XMLFile.create("ADSmartPickupSellBlock", path, ADSellBlock.ROOT)
if xmlFile == nil then return false end
local index = 0
for id, name in pairs(ADSellBlock.blocked) do
local key = string.format("%s.station(%d)", ADSellBlock.ROOT, index)
xmlFile:setString(key .. "#id", id)
xmlFile:setString(key .. "#name", name)
index = index + 1
end
xmlFile:save()
xmlFile:delete()
return true
end
function ADSellBlock.load()
ADSellBlock.blocked = {}
local path = getPath()
if path == nil or not fileExists(path) then return end
local xmlFile = XMLFile.load("ADSmartPickupSellBlock", path)
if xmlFile == nil then return end
xmlFile:iterate(ADSellBlock.ROOT .. ".station", function(_, key)
local id = xmlFile:getString(key .. "#id")
if id ~= nil then ADSellBlock.blocked[id] = xmlFile:getString(key .. "#name") or id end
end)
xmlFile:delete()
end
if addConsoleCommand ~= nil then
addConsoleCommand("spuSellBlock", "Salgssteder: uden navn = liste; spuSellBlock <del af navn> slår fra/til", "consoleSellBlock", ADSellBlock)
end
+8 -3
View File
@@ -644,7 +644,12 @@ function ADSources.describeAccepted(station)
return table.concat(names, ", ")
end
-- Markører hvis aflæsningsstation er et rigtigt salgssted: { {marker, station} }.
-- Salgssted spilleren har slået fra (spuSellBlock, ADSellBlock).
function ADSources.isSellBlocked(station)
return ADSellBlock ~= nil and ADSellBlock.isBlocked ~= nil and ADSellBlock.isBlocked(station) == true
end
-- Markører hvis aflæsningsstation er et rigtigt salgssted (og ikke slået fra): { {marker, station} }.
function ADSources.getSellMarkers(adEnv, farmId)
return cacheGet("sellMarkers", tostring(farmId), 10000, function() return ADSources.findSellMarkers(adEnv, farmId) end)
end
@@ -653,7 +658,7 @@ function ADSources.findSellMarkers(adEnv, farmId)
local result = {}
for _, marker in pairs(adEnv.ADGraphManager:getMapMarkers()) do
local station = ADSmartPickup.getUnloadStationAtWayPointId(adEnv, marker.id, farmId)
if station ~= nil and ADPrices.isSellingStation(station) then
if station ~= nil and ADPrices.isSellingStation(station) and not ADSources.isSellBlocked(station) then
table.insert(result, {marker = marker, station = station})
end
end
@@ -1002,7 +1007,7 @@ function ADSources.getMarketQuote(fillType)
local storage = g_currentMission ~= nil and g_currentMission.storageSystem or nil
local best = nil
for _, station in pairs(storage ~= nil and storage:getUnloadingStations() or {}) do
if ADPrices.isSellingStation(station) and ADSources.stationAccepts(station, fillType) then
if ADPrices.isSellingStation(station) and not ADSources.isSellBlocked(station) and ADSources.stationAccepts(station, fillType) then
local quote = ADPrices.getQuote(station, fillType)
if quote ~= nil and (best == nil or quote.price > best.price) then
best = {price = quote.price, top = quote.top}
+2 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<modDesc descVersion="107">
<author>masterdraco</author>
<version>1.62.6.0</version>
<version>1.62.7.0</version>
<title>
<en>AD Smart Pickup</en>
</title>
@@ -33,6 +33,7 @@
<sourceFile filename="adOutbound.lua"/>
<sourceFile filename="adTipSide.lua"/>
<sourceFile filename="adLoadDiag.lua"/>
<sourceFile filename="adSellBlock.lua"/>
<sourceFile filename="adUnloadWait.lua"/>
<sourceFile filename="adFieldModel.lua"/>
<sourceFile filename="adFieldFleet.lua"/>