diff --git a/data-final-fixes.lua b/data-final-fixes.lua index 1bb8bb5b..941fdc05 100644 --- a/data-final-fixes.lua +++ b/data-final-fixes.lua @@ -7,6 +7,138 @@ local flib = require('__flib__.data-util') local icon_encoded_position = { { icon = "__LogisticTrainNetwork__/graphics/icons/encoded-position.png", icon_size = 64, tint = {r=1, g=1, b=1, a=1} } } +local icon_empty = { { icon = "__core__/graphics/empty.png", icon_size = 1, tint = {r=1, g=1, b=1, a=1} } } +local proto_empty = { icons = icon_empty } + +local function is_hidden(proto) + if proto.flags then + for _,flag in pairs(proto.flags) do + if (flag == "hidden") then + return true + end + end + end + return false +end + +local function scaled_icon(icon, second) + local size = icon.icon_size or 32 + local shift = icon.shift or {0, 0} + -- empty icon scales things up 32 times bigger and we want half size + local scale = (icon.scale or 32 / size) / 64 + local dx + if second then + dx = 0.25 + else + dx = -0.25 + end + return { + icon = icon.icon, + icon_size = size, + icon_mipmaps = icon.icon_mipmaps or 0, + tint = icon.tint, + scale = scale, + -- empty icon scales things up 32 times bigger and we want half size + shift = { + shift[1] / 64 + dx, + shift[2] / 64, + }, + } +end + +local function scale_icons(icons, proto, second) + if proto.icon then + local icon = { + icon = proto.icon, + icon_size = proto.icon_size, + icon_mipmaps = proto.icon_mipmaps, + tint = {r=1, g=1, b=1, a=1} + } + icons[#icons+1] = scaled_icon(icon, second) + elseif proto.icons then + for _, v in pairs(proto.icons) do + icons[#icons+1] = scaled_icon(v, second) + end + end +end + +local function train_signal(loco, wagon, order, suffix) + local wagoncount = 0 + if not is_hidden(wagon) then + wagoncount = wagoncount + 1 + -- scale icons + local icons = {} + scale_icons(icons, loco, false) + scale_icons(icons, wagon, true) + -- create signal + local localised_name + local loco_name = loco.localized_name or loco.name + local wagon_name = wagon.localized_name or wagon.name + + if loco.type == "virtual-signal" then + if wagon.type == "virtual-signal" then + localised_name = {"virtual-signal-name.ltn-train-any-any", suffix} + else + localised_name = {"virtual-signal-name.ltn-train-any", wagon_name} + end + else + if wagon.type == "virtual-signal" then + localised_name = {"virtual-signal-name.ltn-train-any", loco_name} + else + localised_name = {"virtual-signal-name.ltn-train", loco_name, wagon_name} + end + end + + local signal = { + type = "virtual-signal", + name = "ltn-train-"..suffix.."-"..loco.name.."-"..wagon.name, + icons = flib.create_icons(proto_empty, icons) or empty_icon, + icon_size = nil, + subgroup = "ltn-train-signal-"..suffix, + order = order, + localised_name = localised_name, + } + data:extend({signal}) + end +end + +local function train_signals(loco, lococount) + if not is_hidden(loco) then + -- add cargo wagons to train + local wagoncount = 0 + for _, wagon in pairs(data.raw["cargo-wagon"]) do + wagoncount = wagoncount + 1 + local order = "a-cargo-"..string.format("%02d", lococount)..string.format("%02d", wagoncount) + train_signal(loco, wagon, order, "cargo") + end + if wagoncount > 1 then + local order = "a-cargo-"..string.format("%02d", lococount).."00" + train_signal(loco, data.raw["virtual-signal"]["ltn-position-any-cargo-wagon"], oder, "cargo") + end + -- add fluid wagons to train + wagoncount = 0 + for _, wagon in pairs(data.raw["fluid-wagon"]) do + wagoncount = wagoncount + 1 + local order = "a-fluid-"..string.format("%02d", lococount)..string.format("%02d", wagoncount) + train_signal(loco, wagon, order, "fluid") + end + if wagoncount > 1 then + local order = "a-cargo-"..string.format("%02d", lococount).."00" + train_signal(loco, data.raw["virtual-signal"]["ltn-position-any-fluid-wagon"], order, "fluid") + end + -- add fluid wagons to train + wagoncount = 0 + for _, wagon in pairs(data.raw["artillery-wagon"]) do + wagoncount = wagoncount + 1 + local order = "a-artillery-"..string.format("%02d", lococount)..string.format("%02d", wagoncount) + train_signal(loco, wagon, order, "artillery") + end + if wagoncount > 1 then + local order = "a-artillery-"..string.format("%02d", lococount).."00" + train_signal(loco, data.raw["virtual-signal"]["ltn-position-any-artillery-wagon"], order, "artillery") + end + end +end local lococount = 0 for _, loco in pairs(data.raw["locomotive"]) do @@ -21,6 +153,10 @@ for _, loco in pairs(data.raw["locomotive"]) do localised_name = {"virtual-signal-name.ltn-position", loco.localised_name or {"entity-name." .. loco.name}} } data:extend({signal}) + train_signals(loco, lococount) +end +if lococount > 1 then + train_signals(data.raw["virtual-signal"]["ltn-position-any-locomotive"], 0) end local wagoncount = 0 @@ -87,3 +223,5 @@ end data.raw["constant-combinator"]["logistic-train-stop-output"].item_slot_count = 4 + lococount + wagoncount + wagoncount_fluid + wagoncount_artillery + itemcount + fluidcount log("[LTN] found "..tostring(itemcount).." items, "..tostring(fluidcount).." fluids, "..tostring(lococount).." locomotives, "..tostring(wagoncount + wagoncount_fluid + wagoncount_artillery).." wagons") +for _, loco in pairs(data.raw["locomotive"]) do +end diff --git a/locale/en/base.cfg b/locale/en/base.cfg index 7af179ef..1b5315c0 100644 --- a/locale/en/base.cfg +++ b/locale/en/base.cfg @@ -49,6 +49,9 @@ ltn-provider-stack-threshold=Provide Stack Threshold ltn-provider-priority=Provide Priority ltn-locked-slots=Locked Slots per Wagon ltn-disable-warnings=Disable Warning Messages +ltn-train=Train with __1__ and __2__ +ltn-train-any=Any train with __1__ +ltn-train-any-any=Any __1__ train [ltn-message] error-duplicated-unit-number=[LTN] Error: Duplicated unit_number __1__. @@ -64,6 +67,7 @@ warning-dispatcher-disabled=[LTN] Warning: Dispatcher disabled. No deliveries wi empty-depot-item=[LTN] No train to transport items found in depots. Skipping item processing. empty-depot-fluid=[LTN] No train to transport fluids found in depots. Skipping fluid processing. +empty-depot-artillery=[LTN] No artillery train found in depots. Skipping artillery processing. no-provider-found=[LTN] Requester __1__: No station supplying __2__ found in networks __3__. provider-found=[LTN] Provider __1__: priority: __2__, deliveries: __3__, available: __4__ __5__. no-train-found=[LTN] No train to transport from __1__ to __2__ in networks __3__ with length between __4__ and __5__ found in Depot. diff --git a/prototypes/signals.lua b/prototypes/signals.lua index 942de7b7..90464553 100644 --- a/prototypes/signals.lua +++ b/prototypes/signals.lua @@ -148,6 +148,24 @@ data:extend({ group = "signals", order = "ltn4[ltn-position-signal-artillery-wagon]" }, + { + type = "item-subgroup", + name = "ltn-train-signal-cargo", + group = "signals", + order = "ltn4[ltn-train-signal-cargo]" + }, + { + type = "item-subgroup", + name = "ltn-train-signal-fluid", + group = "signals", + order = "ltn4[ltn-train-signal-fluid]" + }, + { + type = "item-subgroup", + name = "ltn-train-signal-artillery", + group = "signals", + order = "ltn4[ltn-train-signal-artillery]" + }, { type = "virtual-signal", name = "ltn-position-any-locomotive", diff --git a/script/constants.lua b/script/constants.lua index 8964a594..d01d9f6b 100644 --- a/script/constants.lua +++ b/script/constants.lua @@ -73,4 +73,9 @@ btest = bit32.btest band = bit32.band min = math.min ceil = math.ceil -sort = table.sort \ No newline at end of file +sort = table.sort + +-- train signals types +TRAIN_CARGO = "ltn-train-cargo" +TRAIN_FLUID = "ltn-train-fluid" +TRAIN_ARTILLERY = "ltn-train-artillery" diff --git a/script/dispatcher.lua b/script/dispatcher.lua index 4b6ff5ac..3b6a8a78 100644 --- a/script/dispatcher.lua +++ b/script/dispatcher.lua @@ -115,7 +115,7 @@ function OnTick(event) elseif global.tick_state == 3 then -- parse requests and dispatch trains if dispatcher_enabled then - if debug_log then log("(OnTick) Available train capacity: "..global.Dispatcher.availableTrains_total_capacity.." item stacks, "..global.Dispatcher.availableTrains_total_fluid_capacity.. " fluid capacity.") end + if debug_log then log("(OnTick) Available train capacity: "..global.Dispatcher.availableTrains_total_capacity.." item stacks, "..global.Dispatcher.availableTrains_total_fluid_capacity.. " fluid capacity, "..global.Dispatcher.availableTrains_total_artillery_capacity.." artillery capacity.") end for i = 1, dispatcher_updates_per_tick, 1 do -- reset on invalid index if global.tick_request_index and not global.Dispatcher.Requests[global.tick_request_index] then @@ -203,7 +203,9 @@ end local condition_circuit_red = {type = "circuit", compare_type = "and", condition = {comparator = "=", first_signal = {type = "virtual", name = "signal-red"}, constant = 0} } local condition_circuit_green = {type = "circuit", compare_type = "or", condition = {comparator = "≥", first_signal = {type = "virtual", name = "signal-green"}, constant = 1} } local condition_wait_empty = {type = "empty", compare_type = "and" } +local condition_wait_full = {type = "full", compare_type = "or" } local condition_finish_loading = {type = "inactivity", compare_type = "and", ticks = 120 } +local condition_inactive = {type = "inactivity", compare_type = "or", ticks = 600 } -- local condition_stop_timeout -- set in settings.lua to capture changes function NewScheduleRecord(stationName, condType, condComp, itemlist, countOverride) @@ -262,6 +264,44 @@ function NewScheduleRecord(stationName, condType, condComp, itemlist, countOverr record.wait_conditions[#record.wait_conditions+1] = condition_circuit_red record.wait_conditions[#record.wait_conditions+1] = condition_circuit_green end + + elseif condType == "circuit" then + if condComp then + -- provider + record.wait_conditions[#record.wait_conditions+1] = { + type = "circuit", + compare_type = "and", + condition = {comparator = "!=", first_signal = {type = "virtual", name = itemlist}, constant = 0}, + } + if global.TrainSignals[itemlist].type == "artillery" then + if schedule_cc then + record.wait_conditions[#record.wait_conditions+1] = condition_circuit_red + end + record.wait_conditions[#record.wait_conditions+1] = condition_wait_full + end + else + --requester + if global.TrainSignals[itemlist].type == "artillery" then + record.wait_conditions[#record.wait_conditions+1] = condition_wait_empty + if schedule_cc then + record.wait_conditions[#record.wait_conditions+1] = condition_circuit_red + end + record.wait_conditions[#record.wait_conditions+1] = condition_inactive + if schedule_cc then + record.wait_conditions[#record.wait_conditions+1] = condition_circuit_red + end + end + record.wait_conditions[#record.wait_conditions+1] = { + type = "circuit", + compare_type = "or", + condition = {comparator = "!=", first_signal = {type = "virtual", name = itemlist}, constant = 0}, + } + end + -- with circuit control enabled keep trains waiting until red = 0 and force them out with green ≥ 1 + if schedule_cc then + record.wait_conditions[#record.wait_conditions+1] = condition_circuit_red + record.wait_conditions[#record.wait_conditions+1] = condition_circuit_green + end end return record end @@ -359,8 +399,10 @@ local function getFreeTrains(nextStop, min_carriages, max_carriages, type, size) if type == "item" then -- subtract locked slots from every cargo wagon inventorySize = trainData.capacity - (nextStop.locked_slots * #trainData.train.cargo_wagons) - else + elseif type == "fluid" then inventorySize = trainData.fluid_capacity + else + inventorySize = GetTrainSignalCount(trainData.train, type) end if debug_log then @@ -463,35 +505,48 @@ function ProcessRequest(reqIndex, request) -- find providers for requested item local itype, iname = match(item, match_string) - if not (itype and iname and (game.item_prototypes[iname] or game.fluid_prototypes[iname])) then + if not (itype and iname and (game.item_prototypes[iname] or game.fluid_prototypes[iname] or game.virtual_signal_prototypes[iname])) then if message_level >= 1 then printmsg({"ltn-message.error-parse-item", item}, requestForce) end if debug_log then log("(ProcessRequests) could not parse "..item) end -- goto skipRequestItem return nil end + -- skip if no trains are available local localname + local capacity + local msg if itype == "fluid" then localname = game.fluid_prototypes[iname].localised_name - -- skip if no trains are available - if (global.Dispatcher.availableTrains_total_fluid_capacity or 0) == 0 then - create_alert(requestStation.entity, "depot-empty", {"ltn-message.empty-depot-fluid"}, requestForce) - if message_level >= 1 then printmsg({"ltn-message.empty-depot-fluid"}, requestForce, true) end - if debug_log then log("Skipping request "..to.." {"..to_network_id_string.."}: "..item..". No trains available.") end - script.raise_event(on_dispatcher_no_train_found_event, {to = to, to_id = toID, network_id = requestStation.network_id, item = item}) - return nil - end - else + capacity = global.Dispatcher.availableTrains_total_fluid_capacity or 0 + msg = "ltn-message.empty-depot-fluid" + elseif itype == "item" then localname = game.item_prototypes[iname].localised_name - -- skip if no trains are available - if (global.Dispatcher.availableTrains_total_capacity or 0) == 0 then - create_alert(requestStation.entity, "depot-empty", {"ltn-message.empty-depot-item"}, requestForce) - if message_level >= 1 then printmsg({"ltn-message.empty-depot-item"}, requestForce, true) end - if debug_log then log("Skipping request "..to.." {"..to_network_id_string.."}: "..item..". No trains available.") end - script.raise_event(on_dispatcher_no_train_found_event, {to = to, to_id = toID, network_id = requestStation.network_id, item = item}) - return nil + capacity = global.Dispatcher.availableTrains_total_capacity or 0 + msg = "ltn-message.empty-depot-item" + elseif itype == "virtual" then + local signal = game.virtual_signal_prototypes[iname] + localname = signal.localised_name + signal_type = global.TrainSignals[iname].type + if signal_type == "cargo" then + capacity = global.Dispatcher.availableTrains_total_capacity or 0 + msg = "ltn-message.empty-depot-item" + elseif signal_type == "fluid" then + capacity = global.Dispatcher.availableTrains_total_fluid_capacity or 0 + msg = "ltn-message.empty-depot-fluid" + elseif signal_type == "artillery" then + capacity = global.Dispatcher.availableTrains_total_artillery_capacity or 0 + msg = "ltn-message.empty-depot-artillery" end end + if capacity == 0 then + -- no suitable train + create_alert(requestStation.entity, "depot-empty", {msg}, requestForce) + if message_level >= 1 then printmsg({msg}, requestForce, true) end + if debug_log then log("Skipping request "..to.." {"..to_network_id_string.."}: "..item..". No trains available.") end + script.raise_event(on_dispatcher_no_train_found_event, {to = to, to_id = toID, network_id = requestStation.network_id, item = item}) + return nil + end -- get providers ordered by priority local providers = getProviders(requestStation, item, count, min_carriages, max_carriages) @@ -524,7 +579,7 @@ function ProcessRequest(reqIndex, request) end local stacks = deliverySize -- for fluids stack = tanker capacity - if itype ~= "fluid" then + if itype == "item" then stacks = ceil(deliverySize / game.item_prototypes[iname].stack_size) -- calculate amount of stacks item count will occupy end @@ -542,8 +597,8 @@ function ProcessRequest(reqIndex, request) local totalStacks = stacks if debug_log then log("created new order "..from.." >> "..to..": "..deliverySize.." "..item.." in "..stacks.."/"..totalStacks.." stacks, min length: "..min_carriages.." max length: "..max_carriages) end - -- find possible mergeable items, fluids can't be merged in a sane way - if itype ~= "fluid" then + -- find possible mergeable items, fluids and trains can't be merged in a sane way + if itype == "item" then for merge_item, merge_count_req in pairs(global.Dispatcher.Requests_by_Stop[toID]) do local merge_type, merge_name = match(merge_item, match_string) if merge_type and merge_name and game.item_prototypes[merge_name] then @@ -570,7 +625,12 @@ function ProcessRequest(reqIndex, request) end -- find train - local free_trains = getFreeTrains(providerData, min_carriages, max_carriages, itype, totalStacks) + local free_trains + if itype == "virtual" then + free_trains = getFreeTrains(providerData, min_carriages, max_carriages, iname, totalStacks) + else + free_trains = getFreeTrains(providerData, min_carriages, max_carriages, itype, totalStacks) + end if not free_trains then create_alert(requestStation.entity, "depot-empty", {"ltn-message.no-train-found", from, to, matched_network_id_string, tostring(min_carriages), tostring(max_carriages) }, requestForce) if message_level >= 1 then printmsg({"ltn-message.no-train-found", from_gps, to_gps, matched_network_id_string, tostring(min_carriages), tostring(max_carriages) }, requestForce, true) end @@ -590,8 +650,8 @@ function ProcessRequest(reqIndex, request) -- recalculate delivery amount to fit in train if trainInventorySize < totalStacks then -- recalculate partial shipment - if itype == "fluid" then - -- fluids are simple + if (itype == "fluid") or (itype == "virtual") then + -- fluids and trains are simple loadingList[1].count = trainInventorySize else -- items need a bit more math @@ -633,14 +693,22 @@ function ProcessRequest(reqIndex, request) else if debug_log then log("(ProcessRequest) Warning: creating schedule without temporary stop for provider.") end end - schedule.records[#schedule.records + 1] = NewScheduleRecord(from, "item_count", "≥", loadingList) + if itype == "virtual" then + schedule.records[#schedule.records + 1] = NewScheduleRecord(from, "circuit", true, iname) + else + schedule.records[#schedule.records + 1] = NewScheduleRecord(from, "item_count", "≥", loadingList) + end if to_rail and to_rail_direction then schedule.records[#schedule.records + 1] = NewTempScheduleRecord(to_rail, to_rail_direction) else if debug_log then log("(ProcessRequest) Warning: creating schedule without temporary stop for requester.") end end - schedule.records[#schedule.records + 1] = NewScheduleRecord(to, "item_count", "=", loadingList, 0) + if itype == "virtual" then + schedule.records[#schedule.records + 1] = NewScheduleRecord(to, "circuit", false, iname) + else + schedule.records[#schedule.records + 1] = NewScheduleRecord(to, "item_count", "=", loadingList, 0) + end -- log("DEBUG: schedule = "..serpent.block(schedule)) selectedTrain.schedule = schedule @@ -693,6 +761,7 @@ function ProcessRequest(reqIndex, request) shipment = shipment} global.Dispatcher.availableTrains_total_capacity = global.Dispatcher.availableTrains_total_capacity - global.Dispatcher.availableTrains[selectedTrain.id].capacity global.Dispatcher.availableTrains_total_fluid_capacity = global.Dispatcher.availableTrains_total_fluid_capacity - global.Dispatcher.availableTrains[selectedTrain.id].fluid_capacity + global.Dispatcher.availableTrains_total_artillery_capacity = global.Dispatcher.availableTrains_total_artillery_capacity - global.Dispatcher.availableTrains[selectedTrain.id].artillery global.Dispatcher.availableTrains[selectedTrain.id] = nil -- train is no longer available => set depot to yellow diff --git a/script/init.lua b/script/init.lua index 794502f5..3c6ad4ce 100644 --- a/script/init.lua +++ b/script/init.lua @@ -4,8 +4,67 @@ * See LICENSE.md in the project directory for license information. --]] +require "script.constants" + ---- INITIALIZATION ---- +local function addTrainSignals(loco) + local cargocount = 0 + local fluidcount = 0 + local artillerycount = 0 + for _, wagon in pairs(game.entity_prototypes) do + if wagon.type == "cargo-wagon" then + cargocount = cargocount + 1 + signal = TRAIN_CARGO.."-"..loco.."-"..wagon.name + global.TrainSignals[signal] = { + locomotive = loco, + wagon = wagon.name, + type = "cargo", + } + elseif wagon.type == "fluid-wagon" then + fluidcount = fluidcount + 1 + signal = TRAIN_FLUID.."-"..loco.."-"..wagon.name + global.TrainSignals[signal] = { + locomotive = loco, + wagon = wagon.name, + type = "fluid", + } + elseif wagon.type == "artillery-wagon" then + artillerycount = artillerycount + 1 + signal = TRAIN_ARTILLERY.."-"..loco.."-"..wagon.name + global.TrainSignals[signal] = { + locomotive = loco, + wagon = wagon.name, + type = "artillery", + } + end + end + if cargocount > 1 then + signal = TRAIN_CARGO.."-"..loco.."-any" + global.TrainSignals[signal] = { + locomotive = loco, + wagon = "any", + type = "cargo", + } + end + if fluidcount > 1 then + signal = TRAIN_FLUID.."-"..loco.."-any" + global.TrainSignals[signal] = { + locomotive = loco, + wagon = "any", + type = "fluid", + } + end + if artillerycount > 1 then + signal = TRAIN_ARTILLERY.."-"..loco.."-any" + global.TrainSignals[signal] = { + locomotive = loco, + wagon = "any", + type = "artillery", + } + end +end + local function initialize(oldVersion, newVersion) --log("oldVersion: "..tostring(oldVersion)..", newVersion: "..tostring(newVersion)) @@ -25,6 +84,7 @@ local function initialize(oldVersion, newVersion) global.Dispatcher.availableTrains = global.Dispatcher.availableTrains or {} global.Dispatcher.availableTrains_total_capacity = global.Dispatcher.availableTrains_total_capacity or 0 global.Dispatcher.availableTrains_total_fluid_capacity = global.Dispatcher.availableTrains_total_fluid_capacity or 0 + global.Dispatcher.availableTrains_total_artillery_capacity = global.Dispatcher.availableTrains_total_artillery_capacity or 0 global.Dispatcher.Provided = global.Dispatcher.Provided or {} -- dictionary [type,name] used to quickly find available items global.Dispatcher.Provided_by_Stop = global.Dispatcher.Provided_by_Stop or {} -- dictionary [stopID]; used only by interface global.Dispatcher.Requests = global.Dispatcher.Requests or {} -- array of requests sorted by priority and age; used to loop over all requests @@ -35,6 +95,19 @@ local function initialize(oldVersion, newVersion) ---- initialize stops global.LogisticTrainStops = global.LogisticTrainStops or {} + -- create a list of train signals + global.TrainSignals = {} + local lococount = 0 + for _, loco in pairs(game.entity_prototypes) do + if loco.type == "locomotive" then + lococount = lococount + 1 + addTrainSignals(loco.name) + end + end + if lococount > 1 then + addTrainSignals("any") + end + -- clean obsolete global global.Dispatcher.Requested = nil global.Dispatcher.Orders = nil @@ -225,6 +298,7 @@ local function updateAllTrains() } global.Dispatcher.availableTrains_total_capacity = 0 global.Dispatcher.availableTrains_total_fluid_capacity = 0 + global.Dispatcher.availableTrains_total_artillery_capacity = 0 global.Dispatcher.availableTrains = {} -- remove all parked train from logistic stops diff --git a/script/stop-events.lua b/script/stop-events.lua index 1e84b91b..d959ea98 100644 --- a/script/stop-events.lua +++ b/script/stop-events.lua @@ -195,6 +195,7 @@ function RemoveStop(stopID) if stop and stop.is_depot and stop.parked_train_id and global.Dispatcher.availableTrains[stop.parked_train_id] then global.Dispatcher.availableTrains_total_capacity = global.Dispatcher.availableTrains_total_capacity - global.Dispatcher.availableTrains[stop.parked_train_id].capacity global.Dispatcher.availableTrains_total_fluid_capacity = global.Dispatcher.availableTrains_total_fluid_capacity - global.Dispatcher.availableTrains[stop.parked_train_id].fluid_capacity + global.Dispatcher.availableTrains_total_artillery_capacity = global.Dispatcher.availableTrains_total_artillery_capacity - global.Dispatcher.availableTrains[stop.parked_train_id].artillery global.Dispatcher.availableTrains[stop.parked_train_id] = nil end diff --git a/script/stop-update.lua b/script/stop-update.lua index 66c43887..5b08bbf5 100644 --- a/script/stop-update.lua +++ b/script/stop-update.lua @@ -37,6 +37,7 @@ local function remove_available_train(trainID) if debug_log then log("(UpdateStop) removing available train "..tostring(trainID).." from depot." ) end global.Dispatcher.availableTrains_total_capacity = global.Dispatcher.availableTrains_total_capacity - global.Dispatcher.availableTrains[trainID].capacity global.Dispatcher.availableTrains_total_fluid_capacity = global.Dispatcher.availableTrains_total_fluid_capacity - global.Dispatcher.availableTrains[trainID].fluid_capacity + global.Dispatcher.availableTrains_total_artillery_capacity = global.Dispatcher.availableTrains_total_artillery_capacity - global.Dispatcher.availableTrains[trainID].artillery global.Dispatcher.availableTrains[trainID] = nil end @@ -128,9 +129,11 @@ function UpdateStop(stopID, stop) for _,v in pairs(signals) do if v.signal.name and v.signal.type then - if v.signal.type ~= signal_type_virtual then + if v.signal.type ~= signal_type_virtual then -- add item and fluid signals to new array signals_filtered[v.signal] = v.count + elseif global.TrainSignals[v.signal.name] then + signals_filtered[v.signal] = v.count elseif ControlSignals[v.signal.name] then -- read out control signals if v.signal.name == ISDEPOT and v.count > 0 then @@ -247,8 +250,10 @@ function UpdateStop(stopID, stop) local traincount = 0 if signal_type == "fluid" then traincount = stop.parked_train.get_fluid_count(signal_name) - else + elseif signal_type == "item" then traincount = stop.parked_train.get_item_count(signal_name) + elseif signal_type == "virtual" then + traincount = GetTrainSignalCount(stop.parked_train, signal.name) end if delivery.to_id == stop.entity.unit_number then diff --git a/script/train-events.lua b/script/train-events.lua index a80f9ad6..48e1cd70 100644 --- a/script/train-events.lua +++ b/script/train-events.lua @@ -94,7 +94,7 @@ function TrainArrives(train) end -- make train available for new deliveries - local capacity, fluid_capacity = GetTrainCapacity(train) + local capacity, fluid_capacity, artillery = GetTrainCapacity(train) global.Dispatcher.availableTrains[train.id] = { train = train, surface = loco.surface, @@ -102,10 +102,12 @@ function TrainArrives(train) depot_priority = stop.depot_priority, network_id = stop.network_id, capacity = capacity, - fluid_capacity = fluid_capacity + fluid_capacity = fluid_capacity, + artillery = artillery, } global.Dispatcher.availableTrains_total_capacity = global.Dispatcher.availableTrains_total_capacity + capacity global.Dispatcher.availableTrains_total_fluid_capacity = global.Dispatcher.availableTrains_total_fluid_capacity + fluid_capacity + global.Dispatcher.availableTrains_total_artillery_capacity = global.Dispatcher.availableTrains_total_artillery_capacity + artillery -- log("added available train "..train.id..", inventory: "..tostring(global.Dispatcher.availableTrains[train.id].capacity)..", fluid capacity: "..tostring(global.Dispatcher.availableTrains[train.id].fluid_capacity)) -- reset schedule @@ -199,6 +201,7 @@ function TrainLeaves(trainID) if global.Dispatcher.availableTrains[trainID] then -- trains are normally removed when deliveries are created global.Dispatcher.availableTrains_total_capacity = global.Dispatcher.availableTrains_total_capacity - global.Dispatcher.availableTrains[trainID].capacity global.Dispatcher.availableTrains_total_fluid_capacity = global.Dispatcher.availableTrains_total_fluid_capacity - global.Dispatcher.availableTrains[trainID].fluid_capacity + global.Dispatcher.availableTrains_total_artillery_capacity = global.Dispatcher.availableTrains_total_artillery_capacity - global.Dispatcher.availableTrains[trainID].artillery global.Dispatcher.availableTrains[trainID] = nil end if stop.error_code == 0 then diff --git a/script/utils.lua b/script/utils.lua index c650a615..d71d04b6 100644 --- a/script/utils.lua +++ b/script/utils.lua @@ -27,6 +27,7 @@ end function GetTrainCapacity(train) local inventorySize = 0 local fluidCapacity = 0 + local artillery = 0 if train and train.valid then for _,wagon in pairs(train.cargo_wagons) do local capacity = global.WagonCapacity[wagon.name] or getCargoWagonCapacity(wagon) @@ -36,8 +37,13 @@ function GetTrainCapacity(train) local capacity = global.WagonCapacity[wagon.name] or getFluidWagonCapacity(wagon) fluidCapacity = fluidCapacity + capacity end + for _,carriage in pairs(train.carriages) do + if carriage.type == "artillery-wagon" then + artillery = 1 + end + end end - return inventorySize, fluidCapacity + return inventorySize, fluidCapacity, artillery end -- returns rich text string for train stops, or nil if entity is invalid @@ -61,4 +67,54 @@ function Make_Train_RichText(train, train_name) else return format("[train=] %s", train_name) end -end \ No newline at end of file +end + +-- returns 1 if the train counts for the virtual signal +function GetTrainSignalCount(train, signal) + -- log("(GetTrainSignalCount) for train "..train.id.." and signal "..signal..")") + locomotives = {} + cargo = {} + fluid = {} + artillery = {} + -- summarize train composition + for _,carriage in pairs(train.carriages) do + local proto = carriage.prototype + if carriage.type == "locomotive" then + locomotives[proto.name] = true + elseif carriage.type == "cargo-wagon" then + cargo[proto.name] = true + elseif carriage.type == "fluid-wagon" then + fluid[proto.name] = true + elseif carriage.type == "artillery-wagon" then + artillery[proto.name] = true + end + end + -- split signal name into parts + local t = global.TrainSignals[signal] + local train_type = t.type + local loco_type = t.locomotive + local wagon_type = t.wagon + --log("(GetTrainSignalCount) train_type = "..train_type..", loco_type = "..loco_type..", wagon_type = "..wagon_type) + -- match locomotive + if (loco_type ~= "any") and (locomotives[loco_type] == nil) then + -- train doesn't have the right locmotive + return 0 + end + -- match type of train + local wagons + if train_type == "cargo" then + wagons = cargo + elseif train_type == "fluid" then + wagons = fluid + elseif train_type == "artillery" then + wagons = artillery + else + -- no idea what train type that is + return 0 + end + -- match wagon + if (wagon_type == "any") or wagons[wagon_type] then + return 1 + end + return 0 +end