-- AD Field Fleet -- Markflåden som ren logik: hvilken rolle et sæt har ud fra redskabernes specs, og hvilke ledige sæt der -- sendes til en mark. Kun sæt med flueben bruges; et sæt spilleren sidder i, røres aldrig. ADFieldFleet = {} -- Rækkefølge = prioritet når et køretøj har flere (såmaskine med gødning er såmaskine; traktor med plov er -- plov, ikke aflæsningsvogn). sprayRole kommer fra sprøjtens/sprederens fyld (gødning/kalk/ukrudt). ADFieldFleet.ROLE_SPECS = { {role = "harvester", spec = "spec_combine"}, {role = "baler", spec = "spec_baler"}, {role = "collector", spec = "spec_forageWagon"}, {role = "rake", spec = "spec_windrower"}, {role = "tedder", spec = "spec_tedder"}, {role = "mower", spec = "spec_mower"}, {role = "seeder", spec = "spec_sowingMachine"}, {role = "roller", spec = "spec_roller"}, {role = "weeder", spec = "spec_weeder"}, {role = "sprayRole"}, {role = "mulcher", spec = "spec_mulcher"}, {role = "cultivator", spec = "spec_cultivator"}, {role = "plow", spec = "spec_plow"}, {role = "baleCollector", spec = "canBaleCollect"}, {role = "unloader", spec = "canUnload"}, } function ADFieldFleet.roleFromSpecs(specs) for _, entry in ipairs(ADFieldFleet.ROLE_SPECS) do if entry.role == "sprayRole" then if specs.sprayRole ~= nil then return specs.sprayRole end elseif specs[entry.spec] then return entry.role end end return nil end -- Kandidater med rollen, sorteret nærmest først, delt i brugbare og afviste (med første grund). local function sortCandidates(candidates, role, x, z, requiredWidth, accept) local usable, sawRole, sawAccepted = {}, false, false local widthReason, widthArgs = nil, nil for _, candidate in ipairs(candidates) do if (candidate.role == role or (candidate.roles ~= nil and candidate.roles[role])) and candidate.enabled then sawRole = true if accept == nil or accept(candidate) then sawAccepted = true if not candidate.busy and not candidate.controlled then local ok, reason, args = ADFieldModel.checkWidth(role, candidate.width or 0, requiredWidth) if ok then local dx, dz = candidate.x - x, candidate.z - z -- spreder med en anden vare på skal tømmes først: kun hvis ingen anden kan local wrongFill = candidate.filledRole ~= nil and candidate.filledRole ~= role table.insert(usable, {candidate = candidate, distance = dx * dx + dz * dz, wrongFill = wrongFill}) elseif widthReason == nil then widthReason, widthArgs = reason, args end end end end end table.sort(usable, function(a, b) if a.wrongFill ~= b.wrongFill then return not a.wrongFill end return a.distance < b.distance end) local reason, args = nil, nil if not sawRole then reason = "noRig" elseif not sawAccepted then reason = "cannotDo" elseif widthReason ~= nil then reason, args = widthReason, widthArgs else reason = "allBusy" end return usable, reason, args end -- Nærmeste brugbare sæt. Grund når intet passer: noRig (ingen med flueben og rollen), cannotDo (ingen kan -- tage opgaven, fx afgrøden), allBusy, tooWide/tooNarrow (bredden, med tal fra den første). -- accept (valgfri): candidate -> bool, fx "høsteren kan tage hvede". -- Faste maskiner: rigIdsByField = {[fieldId] = {id, ...}}. En maskine der er fast på en ANDEN mark må -- ikke bruges her. Har marken selv faste maskiner med rollen, bruges kun de (marken venter på sin egen); -- ellers de frie. (in-game 26/9: sprøjten "til F22" blev sendt til F109.) function ADFieldFleet.filterDedicated(candidates, fieldId, role, rigIdsByField) local ownerOf, own = {}, {} for otherId, ids in pairs(rigIdsByField or {}) do for _, id in ipairs(ids or {}) do ownerOf[id] = otherId if otherId == fieldId then own[id] = true end end end local ownWithRole = {} for _, candidate in ipairs(candidates or {}) do local hasRole = candidate.role == role or (candidate.roles ~= nil and candidate.roles[role]) if own[candidate.id] and hasRole then table.insert(ownWithRole, candidate) end end if #ownWithRole > 0 then return ownWithRole end local free = {} for _, candidate in ipairs(candidates or {}) do if ownerOf[candidate.id] == nil then table.insert(free, candidate) end end return free end -- Gør en maskine fast på én mark (fjernes fra andre marker). Returnerer ny tabel {[fieldId] = ids}. function ADFieldFleet.dedicate(rigIdsByField, fieldId, vehicleId, isOn) local result = {} for otherId, ids in pairs(rigIdsByField or {}) do local copy = {} for _, id in ipairs(ids or {}) do if id ~= vehicleId then table.insert(copy, id) end end result[otherId] = copy end result[fieldId] = result[fieldId] or {} if isOn then table.insert(result[fieldId], vehicleId) end return result end function ADFieldFleet.pick(candidates, role, x, z, requiredWidth, accept) local usable, reason, args = sortCandidates(candidates, role, x, z, requiredWidth, accept) if usable[1] ~= nil then return usable[1].candidate end return nil, reason, args end -- n sæt på én gang (multi-tool kræver alle baner): de n nærmeste, ellers ingen. notEnough har {ledige, n}. function ADFieldFleet.pickMany(candidates, role, n, x, z, requiredWidth, accept) local usable, reason, args = sortCandidates(candidates, role, x, z, requiredWidth, accept) if #usable >= n then local picked = {} for index = 1, n do picked[index] = usable[index].candidate end return picked end if #usable > 0 then return nil, "notEnough", {#usable, n} end 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 copy[id] = (not copy[id]) or nil return copy end -- Til menuen: skjul maskiner der er faste på en ANDEN mark end den valgte. Returnerer synlige, antal -- skjulte og de marker de er faste på (sorteret). selectedFieldId nil = vis alle. function ADFieldFleet.visibleForField(rigs, selectedFieldId, rigIdsByField) if selectedFieldId == nil then return rigs, 0, {} end local ownerOf = {} for fieldId, ids in pairs(rigIdsByField or {}) do for _, id in ipairs(ids or {}) do ownerOf[id] = fieldId end end local visible, hidden, fieldSet = {}, 0, {} for _, rig in ipairs(rigs or {}) do local owner = ownerOf[rig.id] if owner ~= nil and owner ~= selectedFieldId then hidden = hidden + 1 fieldSet[owner] = true else table.insert(visible, rig) end end local fields = {} for fieldId in pairs(fieldSet) do table.insert(fields, fieldId) end table.sort(fields, function(a, b) return tostring(a) < tostring(b) end) return visible, hidden, fields end