-- AD Prices -- Prisregel for udkørsel: hvor tæt er salgsstedets pris på årets toppris for varen? -- Grundlaget er spillets faste sæsonkurve (fillType.economy.factors[1..12], samme data som -- prisgrafen i Priser-menuen; metode fra Distribution Redux): kurve-% = faktor nu ÷ årets højeste. -- Oven på det ganges stationens egen afvigelse (effektiv pris ÷ stationens grundpris nu), så -- prisfald efter salg og stor efterspørgsel tæller med — stor efterspørgsel giver > 100 %. -- Sværhedsgraden skalerer begge priser ens og falder ud af regnestykket. Flade kurver -- (top/bund under FLAT_THRESHOLD) regnes som 100 %, så varer uden sæson aldrig strander. -- De rene funktioner øverst har ingen spil-API; getQuote er spil-adapteren. ADPrices = {} ADPrices.LOG_PREFIX = "ADSmartPickup: " -- top/bund under dette = ingen reel sæson (Distribution Redux bruger samme grænse) ADPrices.FLAT_THRESHOLD = 1.02 function ADPrices.maxFactor(factors) local best = nil for _, factor in pairs(factors or {}) do if type(factor) == "number" and (best == nil or factor > best) then best = factor end end return best or 1 end function ADPrices.topPrice(baseNow, factorNow, maxFactor) if baseNow == nil or baseNow <= 0 then return 0 end if factorNow == nil or factorNow <= 0 or maxFactor == nil or maxFactor <= 0 then return baseNow end return baseNow * maxFactor / factorNow end function ADPrices.percentOfTop(price, top) if top == nil or top <= 0 or price == nil then return 0 end return math.floor(100 * price / top + 0.5) end function ADPrices.minFactor(factors) local best = nil for _, factor in pairs(factors or {}) do if type(factor) == "number" and (best == nil or factor < best) then best = factor end end return best or 1 end -- Kurve-%: nuværende periodes faktor ÷ årets højeste, afrundet. 100 uden kurve, uden periode -- eller når kurven er flad. function ADPrices.curvePercent(factors, period) if factors == nil or period == nil then return 100 end local now, max, min = tonumber(factors[period]), ADPrices.maxFactor(factors), ADPrices.minFactor(factors) if now == nil or now <= 0 or max <= 0 or min <= 0 or (max / min) < ADPrices.FLAT_THRESHOLD then return 100 end return math.floor(100 * now / max + 0.5) end -- Rigtige salgssteder: SellingStation der sælger (fabrikkers aflæsningsstationer er -- også SellingStation-objekter, men med isSellingPoint = false) og vises i Priser-menuen. -- Fabrikkers og staldes egne indleveringer bruger også SellingStation-klassen (TMR-fabrikken -- endda med isSellingPoint = true) — de er mål for forsyning, aldrig markeder. function ADPrices.isSellingStation(station) if station == nil or station.isa == nil or SellingStation == nil or station:isa(SellingStation) ~= true then return false end if station.isSellingPoint ~= true or station.hideFromPricesMenu then return false end -- Afleveringer til GÅRDENS EGNE fabrikker/stalde er ikke salg. En fremmed produktion (fx kortets -- mejeri, ejer 0) køber varen og er et rigtigt salgssted. Ukendt ejer = regnes som egen. local placeable = station.owningPlaceable if placeable ~= nil and (placeable.spec_productionPoint ~= nil or placeable.getHusbandryFillLevel ~= nil) then return not ADPrices.isOwnedByPlayer(placeable) end return true end function ADPrices.isOwnedByPlayer(placeable) local owner = nil if placeable.getOwnerFarmId ~= nil then local ok, value = pcall(placeable.getOwnerFarmId, placeable) if ok then owner = value end elseif placeable.ownerFarmId ~= nil then owner = placeable.ownerFarmId end if owner == nil then return true end local farmId = g_currentMission ~= nil and g_currentMission.getFarmId ~= nil and g_currentMission:getFarmId() or 1 return owner == farmId end local function getCurrentPeriod() local environment = g_currentMission ~= nil and g_currentMission.environment or nil return environment ~= nil and environment.currentPeriod or nil end -- {price, top, percent} for varen ved stationen; nil hvis stationen ikke kan prissætte den. -- percent = kurve-% (faktor nu ÷ årets højeste). Stationens `fillTypePrices` bruges IKKE som -- reference: in-game (23/9) gav effektiv 1602 mod grundpris 505 = 317 %, fordi grundprisen -- hverken indeholder sværhedsgrad eller prisskala. top = prisen der svarer til 100 % af kurven. function ADPrices.getQuote(station, fillType) if station == nil or station.getEffectiveFillTypePrice == nil then return nil end local ok, effective = pcall(station.getEffectiveFillTypePrice, station, fillType) if not ok or type(effective) ~= "number" then return nil end local fillTypeDesc = g_fillTypeManager ~= nil and g_fillTypeManager.getFillTypeByIndex ~= nil and g_fillTypeManager:getFillTypeByIndex(fillType) or nil local factors = fillTypeDesc ~= nil and fillTypeDesc.economy ~= nil and fillTypeDesc.economy.factors or nil local percent = ADPrices.curvePercent(factors, getCurrentPeriod()) local top = percent > 0 and (effective * 100 / percent) or effective return {price = effective, top = top, percent = percent} end -- Højeste pris-%, ved lighed højeste pris. nil ved tom liste. function ADPrices.bestQuote(quotes) local best = nil for _, quote in ipairs(quotes or {}) do if best == nil or quote.percent > best.percent or (quote.percent == best.percent and quote.price > best.price) then best = quote end end return best end