diff --git a/CHANGES.md b/CHANGES.md index 6c0fc7a9..b088116f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,71 @@ +# Version 0.11.1 BETA +Release requirements: +1) Test this whole changelog for 0.11.0 and 0.11.1, and close the GitHub issues. +2) Do a full tutorial run and incorporate the simpler suggestions! +3) Prepare for a stable release: the usual final tests. Also Dtylua checks. +4) Add the JKM exception, both changelogs written, merge to next-update and then to main. + +## Summary +- This update features the second phase of the refactoring of the codebase into modules, making it easier to follow and maintain. It is also accompanied by some small additions, changes, and bugfixes. Improved systems include Kruise Kontrol, fast travel, and the rail builder. While a fair amount of testing has been done so far, new bugs may still emerge due to the refactor. + +## Info +- The second part of the refactoring into modules was completed. + * Files with multiple modules in them were split so that every module has one file and vice versa. + * Any Lua module being referenced within its own file is now called "mod" for brevity and simplicity. + * All Lua modules related to the runtime stage were moved to a "scripts" folder, matching modding conventions. + * Cleaned up several todo comments. + * More refactor work is needed later, to further clean up "control.lua". + +- Started using the GitHub Issues system to track all issues and some feature requests. The Discord channels will still be open for use but the goal is to log everything on GitHub. + +- Moved to using StyLua to standardize code formatting. It needs to be run after you finish making changes. GitHUb actions were added so that every commit is now checked for StyLua compliance. + +- A new menu system and other code infrastructure is being designed by @ahicks. It is being tested right now for circuit networks code and may be applied to the rest of the codebase later so that more flexible and useful menu designs can be supported later on. + +## Features +- The rail builder now supports adding left forks and right forks, giving a total of 4 possible forks. + +## Changes +- When reading the relative direction of the cursor or a scan list entry, if it is fully aligned in that cardinal or diagonal direction, the game will now also read out "aligned". + +- Checking for the nearest damaged entity will now also jump the cursor to the entity, making it easier to target it. + +- Items in hand can now have their logistic requests edited while the trash menu is open. + * You can now also check the request info for an item in a slot of the trash inventory, but you need to take it in hand to edit its requests. This is good because editing the requests for an item might have it automatically flushed out of the trash inventory without warning. + +- Closing the fast travel menu no longer returns the cursor to the player, and the cursor being jumped to a point when it is selected is now stated openly. + +- Improved integration for the mod Kruise Kontrol, by Klonan. + * KK actions will now be possible while in telestep mode. + * Pressing any walking key will no longer cancal KK actions because this was not working correctly. You must press "ENTER" to cancel actions. + +- Added a system for independently predicting and reporting the Kruise Kontrol status. + * The status checks what was targeted to initiate Kruise Kontrol and is updated accordingly. + * The status is reported regularly, although this report is often interrupted by cursor readouts. + * If the status was walking and the player has reached the destination and has not moved for 1 second, then the status automatically is assumed to be arrived. + * For other cases, the status reporting is finished only when you cancel Kruise Kontrol by pressing "Enter", because there may be ongoing actions despite the player standing still at the target location. + +## Bugfixes +- Fixed a locale error about teleporting the cursor. + +- Fixed lab module slots being incorrectly labeled as reserved for science packs. + +- Fixed an issue with the handling of the undocumented direction number 8, which represents "here". It is read out as an empty string. + +- Fixed a crash due to loading a cursor bookmark before having set any. + +- Fixed a crash when using area mining to clear rail objects including signals. + +- Fixed footstep sounds being wrongly played while navigating through menus. + +- Fixed a bug that was placing the mouse pointer incorrectly while in Remote View, and interfering with Kruise Kontrol. + +- Fixed a crash that occurs while rotating buildings. + +- Fixed some invalid keybinds. + +- Re-fixed the playing of multiple mining sounds while mining a resource. + # Version 0.11.0 BETA - EXPERIMENTAL Released preview 0.11.0e1 on April 27th, 2024. diff --git a/control.lua b/control.lua index fb29592a..ec9fd58e 100644 --- a/control.lua +++ b/control.lua @@ -27,8 +27,7 @@ local fa_blueprints = require("scripts.blueprints") local fa_travel = require("scripts.travel-tools") local fa_teleport = require("scripts.teleport") local fa_warnings = require("scripts.warnings") - -local circuit_networks = require("scripts.circuit-networks") +local fa_circuits = require("scripts.circuit-networks") groups = {} entity_types = {} @@ -731,7 +730,7 @@ function ent_info(pindex, ent, description) --game.print(result)--test elseif ent.type == "electric-pole" then --List connected wire neighbors - result = result .. wire_neighbours_info(ent, false) + result = result .. fa_circuits.wire_neighbours_info(ent, false) --Count number of entities being supplied within supply area. local pos = ent.position local sdist = ent.prototype.supply_area_distance @@ -756,7 +755,7 @@ function ent_info(pindex, ent, description) result = result .. " on, " end if (#ent.neighbours.red + #ent.neighbours.green) > 0 then result = result .. " observes circuit condition, " end - result = result .. wire_neighbours_info(ent, true) + result = result .. fa_circuits.wire_neighbours_info(ent, true) elseif ent.name == "rail-signal" or ent.name == "rail-chain-signal" then result = result .. ", " .. fa_rails.get_signal_state_info(ent) elseif ent.name == "roboport" then @@ -1029,7 +1028,9 @@ function ent_info(pindex, ent, description) result = result .. ", temperature " .. math.floor(ent.temperature) .. " degrees C " end end - if ent.type == "constant-combinator" then result = result .. constant_combinator_signals_info(ent, pindex) end + if ent.type == "constant-combinator" then + result = result .. fa_circuits.constant_combinator_signals_info(ent, pindex) + end return result end @@ -2535,10 +2536,10 @@ function menu_cursor_up(pindex) fa_blueprints.blueprint_book_menu_up(pindex) elseif players[pindex].menu == "circuit_network_menu" then general_mod_menu_up(pindex, players[pindex].circuit_network_menu, 0) - circuit_network_menu(pindex, nil, players[pindex].circuit_network_menu.index, false) + fa_circuits.circuit_network_menu_run(pindex, nil, players[pindex].circuit_network_menu.index, false) elseif players[pindex].menu == "signal_selector" then - signal_selector_group_up(pindex) - read_selected_signal_group(pindex, "") + fa_circuits.signal_selector_group_up(pindex) + fa_circuits.read_selected_signal_group(pindex, "") end end @@ -2797,11 +2798,11 @@ function menu_cursor_down(pindex) elseif players[pindex].menu == "blueprint_book_menu" then fa_blueprints.blueprint_book_menu_down(pindex) elseif players[pindex].menu == "circuit_network_menu" then - general_mod_menu_down(pindex, players[pindex].circuit_network_menu, CIRCUIT_NETWORK_MENU_LENGTH) - circuit_network_menu(pindex, nil, players[pindex].circuit_network_menu.index, false) + general_mod_menu_down(pindex, players[pindex].circuit_network_menu, fa_circuits.CN_MENU_LENGTH) + fa_circuits.circuit_network_menu_run(pindex, nil, players[pindex].circuit_network_menu.index, false) elseif players[pindex].menu == "signal_selector" then - signal_selector_group_down(pindex) - read_selected_signal_group(pindex, "") + fa_circuits.signal_selector_group_down(pindex) + fa_circuits.read_selected_signal_group(pindex, "") end end @@ -2957,8 +2958,8 @@ function menu_cursor_left(pindex) elseif players[pindex].menu == "structure-travel" then fa_travel.move_cursor_structure(pindex, 6) elseif players[pindex].menu == "signal_selector" then - signal_selector_signal_prev(pindex) - read_selected_signal_slot(pindex, "") + fa_circuits.signal_selector_signal_prev(pindex) + fa_circuits.read_selected_signal_slot(pindex, "") end end @@ -3131,8 +3132,8 @@ function menu_cursor_right(pindex) elseif players[pindex].menu == "structure-travel" then fa_travel.move_cursor_structure(pindex, 2) elseif players[pindex].menu == "signal_selector" then - signal_selector_signal_next(pindex) - read_selected_signal_slot(pindex, "") + fa_circuits.signal_selector_signal_next(pindex) + fa_circuits.read_selected_signal_slot(pindex, "") end end @@ -3275,7 +3276,8 @@ function on_tick(event) --Fix running speed bug (toggle walk also fixes it) fix_walk(pindex) end - elseif event.tick % 300 == 14 then + elseif event.tick % 500 == 14 then + --Run regular reminders for pindex, player in pairs(players) do --Tutorial reminder every 10 seconds until you open it if players[pindex].started ~= true then @@ -3284,6 +3286,10 @@ function on_tick(event) printout("Press 'H' to open the tutorial", pindex) elseif game.get_player(pindex).ticks_to_respawn ~= nil then printout(math.floor(game.get_player(pindex).ticks_to_respawn / 60) .. " seconds until respawn", pindex) + elseif players[pindex].kruise_kontrolling == true then + --Report the KK state + local result = kk_status_prediction(pindex) + printout(result, pindex) end end end @@ -3384,9 +3390,9 @@ function move(direction, pindex) else local tile = game.get_player(pindex).surface.get_tile(new_pos.x, new_pos.y) local sound_path = "tile-walking/" .. tile.name - if game.is_valid_sound_path(sound_path) then + if game.is_valid_sound_path(sound_path) and players[pindex].in_menu == false then game.get_player(pindex).play_sound({ path = "tile-walking/" .. tile.name, volume_modifier = 1 }) - else + elseif players[pindex].in_menu == false then game.get_player(pindex).play_sound({ path = "player-walk", volume_modifier = 1 }) end end @@ -3505,7 +3511,7 @@ function move_key(direction, event, force_single_tile) end --Stop kruise kontrol related permissions - players[pindex].kruise_kontrolling = false + --players[pindex].kruise_kontrolling = false end --Moves the cursor, and conducts an area scan for larger cursors. If the player is in a slow moving vehicle, it is stopped. @@ -4702,7 +4708,7 @@ function close_menu_resets(pindex) elseif players[pindex].menu == "blueprint_book_menu" then fa_blueprints.blueprint_book_menu_close(pindex) elseif players[pindex].menu == "circuit_network_menu" then - circuit_network_menu_close(pindex, false) + fa_circuits.circuit_network_menu_close(pindex, false) end if p.gui.screen["cursor-jump"] ~= nil then p.gui.screen["cursor-jump"].destroy() end @@ -5345,6 +5351,7 @@ script.on_event("mine-area", function(event) pindex = event.player_index if not check_for_player(pindex) then return end if players[pindex].in_menu then return end + local p = game.get_player(pindex) local ent = get_selected_ent(pindex) local cleared_count = 0 local cleared_total = 0 @@ -5389,11 +5396,8 @@ script.on_event("mine-area", function(event) name = { "straight-rail", "curved-rail", "rail-signal", "rail-chain-signal", "train-stop" }, }) for i, rail_ent in ipairs(rail_ents) do - if rail_ent.name == "straight-rail" or rail_ent.name == "curved-rail" then - fa_rails.mine_signals(rail_ent, pindex) - end - game.get_player(pindex).play_sound({ path = "entity-mined/straight-rail" }) - game.get_player(pindex).mine_entity(rail_ent, true) + p.play_sound({ path = "entity-mined/straight-rail" }) + p.mine_entity(rail_ent, true) cleared_count = cleared_count + 1 end rendering.draw_circle({ @@ -5967,9 +5971,9 @@ script.on_event("click-menu", function(event) local bpb_menu = players[pindex].blueprint_book_menu fa_blueprints.run_blueprint_book_menu(pindex, bpb_menu.index, bpb_menu.list_mode, true, false) elseif players[pindex].menu == "circuit_network_menu" then - circuit_network_menu(pindex, nil, players[pindex].circuit_network_menu.index, true, false) + fa_circuits.circuit_network_menu_run(pindex, nil, players[pindex].circuit_network_menu.index, true, false) elseif players[pindex].menu == "signal_selector" then - apply_selected_signal_to_enabled_condition( + fa_circuits.apply_selected_signal_to_enabled_condition( pindex, players[pindex].signal_selector.ent, players[pindex].signal_selector.editing_first_slot @@ -6133,7 +6137,7 @@ script.on_event("click-hand", function(event) printout(ent_counter .. " entities marked to be upgraded.", pindex) end elseif stack.name == "red-wire" or stack.name == "green-wire" or stack.name == "copper-cable" then - drag_wire_and_read(pindex) + fa_circuits.drag_wire_and_read(pindex) elseif stack.prototype ~= nil and stack.prototype.type == "capsule" then --If holding a capsule type, e.g. cliff explosives or robot capsules, or remotes, try to use it at the cursor position (no feedback about successful usage) local cursor_dist = util.distance(game.get_player(pindex).position, players[pindex].cursor_pos) @@ -6376,10 +6380,10 @@ script.on_event("open-circuit-menu", function(event) end if ent.type == "electric-pole" then --Open the menu - circuit_network_menu_open(pindex, ent) + fa_circuits.circuit_network_menu_open(pindex, ent) return elseif ent.type == "constant-combinator" then - circuit_network_menu_open(pindex, ent) + fa_circuits.circuit_network_menu_open(pindex, ent) return elseif ent.type == "arithmetic-combinator" or ent.type == "decider-combinator" then printout("Error: This combinator is not supported", pindex) @@ -6399,7 +6403,7 @@ script.on_event("open-circuit-menu", function(event) return end --Open the menu - circuit_network_menu_open(pindex, ent) + fa_circuits.circuit_network_menu_open(pindex, ent) elseif players[pindex].in_menu == false then local ent = p.selected or get_selected_ent(pindex) if ent == nil or ent.valid == false or (ent.get_control_behavior() == nil and ent.type ~= "electric-pole") then @@ -6410,10 +6414,10 @@ script.on_event("open-circuit-menu", function(event) p.opened = ent if ent.type == "electric-pole" then --Open the menu - circuit_network_menu_open(pindex, ent) + fa_circuits.circuit_network_menu_open(pindex, ent) return elseif ent.type == "constant-combinator" then - circuit_network_menu_open(pindex, ent) + fa_circuits.circuit_network_menu_open(pindex, ent) return elseif ent.type == "arithmetic-combinator" or ent.type == "decider-combinator" then printout("Error: This combinator is not supported", pindex) @@ -6427,7 +6431,7 @@ script.on_event("open-circuit-menu", function(event) return end --Open the menu - circuit_network_menu_open(pindex, ent) + fa_circuits.circuit_network_menu_open(pindex, ent) end end) @@ -7671,11 +7675,12 @@ end) function fix_walk(pindex) if not check_for_player(pindex) then return end if game.get_player(pindex).character == nil or game.get_player(pindex).character.valid == false then return end - if players[pindex].walk == 0 then + if players[pindex].walk == 0 and players[pindex].kruise_kontrolling ~= true then game.get_player(pindex).character_running_speed_modifier = -1 -- 100% - 100% = 0% else --walk > 0 game.get_player(pindex).character_running_speed_modifier = 0 -- 100% + 0 = 100% end + players[pindex].position = game.get_player(pindex).position end --Toggle building while walking @@ -7971,8 +7976,11 @@ script.on_event(defines.events.on_gui_confirmed, function(event) if valid_number then if players[pindex].signal_selector.ent.type == "constant-combinator" then --Constant combinators (set last signal value) - local success = - constant_combinator_set_last_signal_count(constant, players[pindex].signal_selector.ent, pindex) + local success = fa_circuits.constant_combinator_set_last_signal_count( + constant, + players[pindex].signal_selector.ent, + pindex + ) if success then printout("Set " .. result, pindex) else @@ -7991,7 +7999,7 @@ script.on_event(defines.events.on_gui_confirmed, function(event) "Set " .. result .. ", condition now checks if " - .. read_circuit_condition(players[pindex].signal_selector.ent, true), + .. fa_circuits.read_circuit_condition(players[pindex].signal_selector.ent, true), pindex ) end @@ -8510,7 +8518,7 @@ script.on_event("set-entity-filter-from-hand", function(event) printout(result, pindex) elseif ent.type == "constant-combinator" then --Remove the last signal - constant_combinator_remove_last_signal(ent, pindex) + fa_circuits.constant_combinator_remove_last_signal(ent, pindex) elseif ent.type == "inserter" then local result = set_inserter_filter_by_hand(pindex, ent) printout(result, pindex) @@ -8522,7 +8530,7 @@ script.on_event("set-entity-filter-from-hand", function(event) printout(result, pindex) elseif ent.type == "constant-combinator" then --Add a new signal - constant_combinator_add_stack_signal(ent, stack, pindex) + fa_circuits.constant_combinator_add_stack_signal(ent, stack, pindex) elseif ent.type == "inserter" then local result = set_inserter_filter_by_hand(pindex, ent) printout(result, pindex) @@ -8726,7 +8734,7 @@ script.on_event("debug-test-key", function(event) --end if ent and ent.type == "programmable-speaker" then --ent.play_note(12,1) - --play_selected_speaker_note(ent) + --fa_circuits.play_selected_speaker_note(ent) end --show_sprite_demo(pindex) --Character:move_to(players[pindex].cursor_pos, util.distance(players[pindex].position,players[pindex].cursor_pos), 100) @@ -9366,7 +9374,12 @@ function check_and_play_bump_alert_sound(pindex, this_tick) if p.walking_state.walking == false then return end --Return if not enough positions filled (trying 4 for now) - if players[pindex].bump.last_pos_4 == nil then return end + if players[pindex].bump.last_pos_4 == nil then + players[pindex].bump.filled = false + return + else + players[pindex].bump.filled = true + end --Return if bump sounded recently if this_tick - players[pindex].bump.last_bump_tick < 15 then return end @@ -9780,13 +9793,22 @@ function read_nearest_damaged_ent_info(pos, pindex) printout("No damaged structures within 1000 tiles.", pindex) return else + --Move cursor to closest + players[pindex].cursor_pos = closest.position + fa_graphics.draw_cursor_highlight(pindex, closest, nil, nil) + + --Report the result min_dist = math.floor(min_dist) local dir = fa_utils.get_direction_biased(closest.position, pos) + local aligned_note = "" + if fa_utils.is_direction_aligned(closest.position, pos) then aligned_note = "aligned " end local result = fa_localising.get(closest, pindex) .. " damaged at " .. min_dist .. " " + .. aligned_note .. fa_utils.direction_lookup(dir) + .. ", cursor moved. " printout(result, pindex) end end @@ -9822,19 +9844,32 @@ function read_pollution_level_at_position(pos, pindex) printout(result, pindex) end +--Enables remote view if not already, and then enables kruise kontrol script.on_event("klient-alt-move-to", function(event) local pindex = event.player_index if not check_for_player(pindex) then return end - + local p = game.get_player(pindex) if players[pindex].remote_view == true then + --Allow KK players[pindex].kruise_kontrolling = true + p.character_running_speed_modifier = 0 local kk_pos = players[pindex].cursor_pos + printout("Moving to " .. math.floor(kk_pos.x) .. ", " .. math.floor(kk_pos.y), pindex) + --Save what the player targetted + players[pindex].kk_pos = kk_pos + local kk_targets = p.surface.find_entities_filtered({ position = kk_pos, name = "highlight-box", invert = true }) + if kk_targets and #kk_targets > 0 then + players[pindex].kk_target = kk_targets[1] + else + players[pindex].kk_target = nil + end + --Close remote view toggle_remote_view(pindex, false, true) close_menu_resets(pindex) - printout("Moving to " .. math.floor(kk_pos.x) .. ", " .. math.floor(kk_pos.y), pindex) else players[pindex].kruise_kontrolling = false - toggle_remote_view(pindex, true) + fix_walk(pindex) + toggle_remote_view(pindex, true, false) sync_remote_view(pindex) printout("Opened in remote view, press again to confirm", pindex) end @@ -9843,7 +9878,74 @@ end) script.on_event("klient-cancel-enter", function(event) local pindex = event.player_index if not check_for_player(pindex) then return end - if players[pindex].kruise_kontrolling == true then printout("Cancelled action.", pindex) end - players[pindex].kruise_kontrolling = false - toggle_remote_view(pindex, false, true) + if players[pindex].kruise_kontrolling == true then + players[pindex].kruise_kontrolling = false + fix_walk(pindex) + toggle_remote_view(pindex, false, true) + close_menu_resets(pindex) + printout("Cancelled kruise kontrol action.", pindex) + end end) + +--Predicts what Kruise Kontrol is doing based on the current target +function kk_status_prediction(pindex) + --Predict the status based on the selected location and entity + local p = game.get_player(pindex) + local result = "Kruise Kontrol " + local target = players[pindex].kk_target + local target_pos = players[pindex].kk_pos + local walking = false + if target == nil or target.valid == false then + result = result .. "Walking" + walking = true + elseif target.type == "entity-ghost" then + result = result .. "Building ghosts" + elseif target.type == "resource" then + result = result .. "Mining" + elseif target.type == "unit" or target.type == "unit-spawner" or target.type == "turret" then + result = result .. "Fighting" + elseif target.to_be_deconstructed() == true then + result = result .. "Deconstructing marked buildings " + else + result = result .. "Walking" + walking = true + end + local target_dist = math.floor(util.distance(p.position, target_pos)) + local dist_info = ", " .. target_dist .. " tiles to target location" + if target_dist < 3 then dist_info = "" end + result = result .. dist_info + result = result .. ", press ENTER to exit Kruise Kontrol" + + --If KK is simply walking, check whether the character has stopped for 1 second, so that the status is assumed to be done + --Note: we do not do a distance check because if KK has ended and the player walks freely, the distance check fails. + --Note: This could have been applied to all KK states but it is hard to know whether a stopped player is finished + if walking and player_was_still_for_1_second(pindex) then + players[pindex].kruise_kontrolling = false + fix_walk(pindex) + toggle_remote_view(pindex, false, true) + result = "Kruise Kontrol arrived." + end + return result +end + +--Checks whether the player has not walked for 1 second. Uses the bump alert checks. +function player_was_still_for_1_second(pindex) + local b = players[pindex].bump + if b == nil or b.filled ~= true then + --It is too soon to report anything + return false + end + local diff_x1 = b.last_pos_1.x - b.last_pos_2.x + local diff_x2 = b.last_pos_2.x - b.last_pos_3.x + local diff_x3 = b.last_pos_3.x - b.last_pos_4.x + local diff_y1 = b.last_pos_1.y - b.last_pos_2.y + local diff_y2 = b.last_pos_2.y - b.last_pos_3.y + local diff_y3 = b.last_pos_3.y - b.last_pos_4.y + if (diff_x1 + diff_x2 + diff_x3 + diff_y1 + diff_y2 + diff_y3) == 0 then + --Confirmed no movement in the past 60 ticks + return true + else + --Confirmed some movement in the past 60 ticks + return false + end +end diff --git a/info.json b/info.json index 0c039bca..85dbfd88 100644 --- a/info.json +++ b/info.json @@ -1,6 +1,6 @@ { "name": "FactorioAccess", - "version": "0.11.0", + "version": "0.11.1", "title": "Factorio Access Mod", "author": "Crimso, SirFendi, Gweneph", "homepage": "https://github.com/Factorio-Access/FactorioAccess", diff --git a/scripts/blueprints.lua b/scripts/blueprints.lua index 953e1b5c..b992845b 100644 --- a/scripts/blueprints.lua +++ b/scripts/blueprints.lua @@ -1,4 +1,4 @@ ---Here: Functions related to blueprints and blueprint books +--Here: Functions related to ghosts, blueprints and blueprint books --Does not include event handlers local fa_utils = require("scripts.fa-utils") diff --git a/scripts/building-tools.lua b/scripts/building-tools.lua index 50614461..14d8e57e 100644 --- a/scripts/building-tools.lua +++ b/scripts/building-tools.lua @@ -467,7 +467,7 @@ function mod.rotate_building_info_read(event, forward) else printout(stack.name .. " never needs rotating.", pindex) end - elseif stack.valid_for_read and stack.is_blueprint and stack.is_blueprint_setup() then + elseif stack ~= nil and stack.valid_for_read and stack.is_blueprint and stack.is_blueprint_setup() then --Rotate blueprints: They are tracked separately, and we reset them to north when cursor stack changes game.get_player(pindex).play_sound({ path = "Rotate-Hand-Sound" }) players[pindex].blueprint_hand_direction = (players[pindex].blueprint_hand_direction + dirs.east * mult) @@ -1261,7 +1261,10 @@ function mod.build_preview_checks_info(stack, pindex) surf.find_entities_filtered({ type = "electric-pole", position = pos, radius = ent_p.max_wire_distance }) local poles = {} for i, v in pairs(pole_dict) do - if v.prototype.max_wire_distance ~= nil and v.prototype.max_wire_distance >= ent_p.max_wire_distance then --Select only the poles that can connect back + if + v.prototype.max_wire_distance >= ent_p.max_wire_distance + or v.prototype.max_wire_distance >= util.distance(v.position, pos) + then table.insert(poles, v) end end diff --git a/scripts/building-vehicle-sectors.lua b/scripts/building-vehicle-sectors.lua index 89ac3d7f..02080d7c 100644 --- a/scripts/building-vehicle-sectors.lua +++ b/scripts/building-vehicle-sectors.lua @@ -1,4 +1,4 @@ ---Here: functions specific to building menus +--Here: functions specific to the menus of buildings and vehicles. local util = require("util") local fa_utils = require("scripts.fa-utils") local fa_crafting = require("scripts.crafting") diff --git a/scripts/circuit-networks.lua b/scripts/circuit-networks.lua index 3e99b7c9..f3808bef 100644 --- a/scripts/circuit-networks.lua +++ b/scripts/circuit-networks.lua @@ -9,6 +9,8 @@ local multistate_switch = require("scripts.ui.low-level.multistate-switch") local dcb = defines.control_behavior +local mod = {} + -- We must be able to convert our descriptors into multistate switches. This -- will hopefully go away in future; the right move is to just feed to a menu -- abstraction directly. Since we also know that they cannot change for the @@ -63,7 +65,7 @@ local function make_read_switch_for_entity(entity) return uncached end -function drag_wire_and_read(pindex) +function mod.drag_wire_and_read(pindex) --Start/end dragging wire local p = game.get_player(pindex) local something_happened = p.drag_wire({ position = players[pindex].cursor_pos }) @@ -174,7 +176,7 @@ end --*** later: test ent.circuit_connection_definitions -function wire_neighbours_info(ent, read_network_ids) +function mod.wire_neighbours_info(ent, read_network_ids) --List connected electric poles local neighbour_count = 0 local result = "" @@ -231,7 +233,7 @@ function wire_neighbours_info(ent, read_network_ids) return result end -function localise_signal_name(signal, pindex) +function mod.localise_signal_name(signal, pindex) if signal == nil then return "nil" end local sig_name = signal.name local sig_type = signal.type @@ -256,7 +258,7 @@ function localise_signal_name(signal, pindex) return result end -function constant_combinator_count_valid_signals(ent) +local function constant_combinator_count_valid_signals(ent) local count = 0 local combinator = ent.get_control_behavior() local max_signals_count = combinator.signals_count @@ -266,7 +268,7 @@ function constant_combinator_count_valid_signals(ent) return count end -function constant_combinator_get_first_empty_slot_id(ent) +local function constant_combinator_get_first_empty_slot_id(ent) local combinator = ent.get_control_behavior() local max_signals_count = combinator.signals_count for i = 1, max_signals_count, 1 do @@ -275,7 +277,7 @@ function constant_combinator_get_first_empty_slot_id(ent) return max_signals_count end -function constant_combinator_signals_info(ent, pindex) +function mod.constant_combinator_signals_info(ent, pindex) local combinator = ent.get_control_behavior() local max_signals_count = combinator.signals_count local valid_signals_count = constant_combinator_count_valid_signals(ent) @@ -292,7 +294,7 @@ function constant_combinator_signals_info(ent, pindex) for i = 1, max_signals_count, 1 do local signal = combinator.get_signal(i) if signal.signal ~= nil then - local signal_name = localise_signal_name(signal.signal, pindex) + local signal_name = mod.localise_signal_name(signal.signal, pindex) if i > 1 then result = result .. " and " end result = result .. signal_name .. " times " .. signal.count .. ", " end @@ -302,7 +304,7 @@ function constant_combinator_signals_info(ent, pindex) return result end -function constant_combinator_add_stack_signal(ent, stack, pindex) +function mod.constant_combinator_add_stack_signal(ent, stack, pindex) local combinator = ent.get_control_behavior() local first_empty_slot = constant_combinator_get_first_empty_slot_id(ent) local new_signal_id = { type = "item", name = stack.name } @@ -311,7 +313,7 @@ function constant_combinator_add_stack_signal(ent, stack, pindex) printout("Added signal for " .. localising.get(stack, pindex), pindex) end -function constant_combinator_add_selector_signal(prototype, signal_type, ent, pindex) +function mod.constant_combinator_add_selector_signal(prototype, signal_type, ent, pindex) local combinator = ent.get_control_behavior() local first_empty_slot = constant_combinator_get_first_empty_slot_id(ent) local new_signal_id = { type = signal_type, name = prototype.name } @@ -320,13 +322,13 @@ function constant_combinator_add_selector_signal(prototype, signal_type, ent, pi printout("Added signal for " .. localising.get(prototype, pindex), pindex) end -function constant_combinator_remove_last_signal(ent, pindex) +function mod.constant_combinator_remove_last_signal(ent, pindex) local combinator = ent.get_control_behavior() local max_signals_count = combinator.signals_count for i = max_signals_count, 1, -1 do local signal = combinator.get_signal(i) if signal.signal ~= nil then - local signal_name = localise_signal_name(signal.signal, pindex) + local signal_name = mod.localise_signal_name(signal.signal, pindex) printout("Removed last signal " .. signal_name, pindex) combinator.set_signal(i, nil) return @@ -335,7 +337,7 @@ function constant_combinator_remove_last_signal(ent, pindex) printout("No signals to remove", pindex) end -function constant_combinator_type_last_signal_count(pindex, ent) +function mod.constant_combinator_type_last_signal_count(pindex, ent) players[pindex].signal_selector = {} players[pindex].signal_selector.ent = ent local frame = game.get_player(pindex).gui.screen.add({ type = "frame", name = "circuit-condition-constant" }) @@ -347,13 +349,13 @@ function constant_combinator_type_last_signal_count(pindex, ent) return "Type in a number press 'ENTER' to confirm, or press 'ESC' to exit" end -function constant_combinator_set_last_signal_count(value, ent, pindex) +function mod.constant_combinator_set_last_signal_count(value, ent, pindex) local combinator = ent.get_control_behavior() local max_signals_count = combinator.signals_count for i = max_signals_count, 1, -1 do local signal = combinator.get_signal(i) if signal.signal ~= nil then - local signal_name = localise_signal_name(signal.signal, pindex) + local signal_name = mod.localise_signal_name(signal.signal, pindex) signal.count = value combinator.set_signal(i, signal) return true @@ -365,7 +367,7 @@ end -- @param entity LuaEntity -- @param direction "prev"|"current"|"next" -- @returns string? -function read_mode_multistate_call(entity, direction) +function mod.read_mode_multistate_call(entity, direction) -- We're using this indirectly, so make Lua stop warning at the last line of -- this function. --- @type table? @@ -378,7 +380,7 @@ function read_mode_multistate_call(entity, direction) return switch[direction](entity.get_control_behavior()) end -function get_circuit_read_mode_name(ent) +local function get_circuit_read_mode_name(ent) local result = "None" local control = ent.get_control_behavior() @@ -420,14 +422,14 @@ function get_circuit_read_mode_name(ent) result = "None" else -- Try to go through the new code path. - local possible_new = read_mode_multistate_call(ent, "current") + local possible_new = mod.read_mode_multistate_call(ent, "current") if possible_new then result = possible_new end end return result end -function toggle_circuit_read_mode(ent) +local function toggle_circuit_read_mode(ent) local result = "" local changed = false local control = ent.get_control_behavior() @@ -470,7 +472,7 @@ function toggle_circuit_read_mode(ent) result = get_circuit_read_mode_name(ent) --laterdo** allow toggling some other read modes -- Try to go through the new code path. - local possible_new = read_mode_multistate_call(ent, "next") + local possible_new = mod.read_mode_multistate_call(ent, "next") if possible_new then result = possible_new changed = true @@ -479,7 +481,7 @@ function toggle_circuit_read_mode(ent) return result, changed end -function get_circuit_operation_mode_name(ent) +local function get_circuit_operation_mode_name(ent) local result = "None" local uses_condition = false local control = ent.get_control_behavior() @@ -558,7 +560,7 @@ function get_circuit_operation_mode_name(ent) return result, uses_condition end -function toggle_circuit_operation_mode(ent) +local function toggle_circuit_operation_mode(ent) local result = "None" local changed = false local control = ent.get_control_behavior() @@ -646,13 +648,13 @@ function toggle_circuit_operation_mode(ent) return result, changed end -function read_circuit_condition(ent, comparator_in_words) +function mod.read_circuit_condition(ent, comparator_in_words) local control = ent.get_control_behavior() local cond = control.circuit_condition.condition local fulfilled = control.circuit_condition.fulfilled local comparator = cond.comparator - local first_signal_name = localise_signal_name(cond.first_signal, pindex) - local second_signal_name = localise_signal_name(cond.second_signal, pindex) + local first_signal_name = mod.localise_signal_name(cond.first_signal, pindex) + local second_signal_name = mod.localise_signal_name(cond.second_signal, pindex) local result = "" if cond.second_signal == nil then second_signal_name = cond.constant @@ -679,7 +681,7 @@ function read_circuit_condition(ent, comparator_in_words) return result end -function toggle_condition_comparator(ent, pindex, comparator_in_words) +local function toggle_condition_comparator(ent, pindex, comparator_in_words) local circuit_condition = ent.get_control_behavior().circuit_condition local cond = circuit_condition.condition local comparator = cond.comparator @@ -723,26 +725,29 @@ function toggle_condition_comparator(ent, pindex, comparator_in_words) return comparator end -function write_condition_first_signal_item(circuit_condition, stack) - local cond = circuit_condition.condition +local function write_condition_first_signal_item(circuit_condition, stack) + local cond = table.deepcopy(circuit_condition.condition) cond.first_signal = { type = "item", name = stack.name } + circuit_condition = cond return end -function write_condition_second_signal_item(circuit_condition, stack) - local cond = circuit_condition.condition +local function write_condition_second_signal_item(circuit_condition, stack) + local cond = table.deepcopy(circuit_condition.condition) cond.second_signal = { type = "item", name = stack.name } + circuit_condition = cond return end -function write_condition_second_signal_constant(circuit_condition, constant) - local cond = circuit_condition.condition +local function write_condition_second_signal_constant(circuit_condition, constant) + local cond = table.deepcopy(circuit_condition.condition) cond.second_signal = nil cond.constant = constant + circuit_condition = cond return end -function play_selected_speaker_note(ent, mute) +function mod.play_selected_speaker_note(ent, mute) local control = ent.get_control_behavior() local ins_id = control.circuit_parameters.instrument_id if ins_id < 1 then @@ -795,7 +800,7 @@ end This menu opens when you press KEY when a building menu is open. ]] -function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) +function mod.circuit_network_menu_run(pindex, ent_in, menu_index, clicked, other_input) local index = menu_index local p = game.get_player(pindex) local ent = ent_in or p.opened @@ -840,11 +845,11 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) local result = "" if nwr ~= nil then if nwg ~= nil then result = result .. "Red network: " end - result = result .. circuit_network_signals_info(pindex, nwr) + result = result .. mod.circuit_network_signals_info(pindex, nwr) end if nwg ~= nil then if nwr ~= nil then result = result .. "Green network: " end - result = result .. circuit_network_signals_info(pindex, nwg) + result = result .. mod.circuit_network_signals_info(pindex, nwg) end if result == "" then result = "No signals at the moment" end printout(result, pindex) @@ -861,11 +866,11 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) local result = "" if nwr ~= nil then if nwg ~= nil then result = result .. "Red network: " end - result = result .. circuit_network_members_info(pindex, ent, defines.wire_type.red) + result = result .. mod.circuit_network_members_info(pindex, ent, defines.wire_type.red) end if nwg ~= nil then if nwr ~= nil then result = result .. "Green network: " end - result = result .. circuit_network_members_info(pindex, ent, defines.wire_type.green) + result = result .. mod.circuit_network_members_info(pindex, ent, defines.wire_type.green) end if result == "" then result = "Error: No network" end printout(result, pindex) @@ -882,11 +887,11 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) local result = "" if nwr ~= nil then if nwg ~= nil then result = result .. "Red network: " end - result = result .. circuit_network_neighbors_info(pindex, ent, defines.wire_type.red) + result = result .. mod.circuit_network_neighbors_info(pindex, ent, defines.wire_type.red) end if nwg ~= nil then if nwr ~= nil then result = result .. "Green network: " end - result = result .. circuit_network_neighbors_info(pindex, ent, defines.wire_type.green) + result = result .. mod.circuit_network_neighbors_info(pindex, ent, defines.wire_type.green) end if result == "" then result = "Error: No network" end printout(result, pindex) @@ -898,8 +903,8 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) if index > 3 then --(inventory edge: play sound and set index and call this menu again) p.play_sound({ path = "inventory-edge" }) - players[pindex].circuit_network_menu.index = 3 - circuit_network_menu(pindex, ent, players[pindex].circuit_network_menu.index, false, false) + players[pindex].mod.circuit_network_menu_run.index = 3 + mod.circuit_network_menu_run(pindex, ent, players[pindex].mod.circuit_network_menu_run.index, false, false) end return elseif ent.type == "constant-combinator" then @@ -909,7 +914,7 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) if not clicked then printout("Read combinator signals", pindex) else - local result = constant_combinator_signals_info(ent, pindex) + local result = mod.constant_combinator_signals_info(ent, pindex) printout(result, pindex) end elseif index == 5 then @@ -917,14 +922,14 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) if not clicked then printout("Add a signal from the selector", pindex) else - open_signal_selector(pindex, ent, nil) + mod.open_signal_selector(pindex, ent, nil) end elseif index == 6 then --Set a new count for the last signal if not clicked then printout("Set a new count for the last signal", pindex) else - result = constant_combinator_type_last_signal_count(pindex, ent) + result = mod.constant_combinator_type_last_signal_count(pindex, ent) printout(result, pindex) p.play_sound({ path = "Inventory-Move" }) end @@ -933,7 +938,7 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) if not clicked then printout("Delete the last signal", pindex) else - constant_combinator_remove_last_signal(ent, pindex) + mod.constant_combinator_remove_last_signal(ent, pindex) end elseif index == 8 then --Toggle switch @@ -951,8 +956,8 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) elseif index > 8 then --(inventory edge: play sound and set index and call this menu again) p.play_sound({ path = "inventory-edge" }) - players[pindex].circuit_network_menu.index = 8 - circuit_network_menu(pindex, ent, players[pindex].circuit_network_menu.index, false, false) + players[pindex].mod.circuit_network_menu_run.index = 8 + mod.circuit_network_menu_run(pindex, ent, players[pindex].mod.circuit_network_menu_run.index, false, false) end return else @@ -985,7 +990,7 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) local result = "" result = result .. "Reading mode: " .. read_mode .. ", " result = result .. "Operation mode: " .. op_mode .. ", " - if uses_condition == true then result = result .. read_circuit_condition(ent, true) end + if uses_condition == true then result = result .. mod.read_circuit_condition(ent, true) end printout(result, pindex) end elseif index == 5 then @@ -1026,7 +1031,7 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) local result = "Not using a condition" if uses_condition == true then result = "Navigate item groups with W and S and inidividual signals with A and D." - open_signal_selector(pindex, ent, true) + mod.open_signal_selector(pindex, ent, true) end printout(result, pindex) p.play_sound({ path = "Inventory-Move" }) @@ -1039,7 +1044,7 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) local result = "Not using a condition" if uses_condition == true then result = "Navigate item groups with W and S and inidividual signals with A and D." - open_signal_selector(pindex, ent, false) + mod.open_signal_selector(pindex, ent, false) end printout(result, pindex) p.play_sound({ path = "Inventory-Move" }) @@ -1050,7 +1055,7 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) printout("Set a constant number for enabled condition second signal", pindex) else local result = "Not using a condition" - if uses_condition == true then result = type_circuit_condition_constant(pindex, ent) end + if uses_condition == true then result = mod.type_circuit_condition_constant(pindex, ent) end printout(result, pindex) p.play_sound({ path = "Inventory-Move" }) end @@ -1061,12 +1066,18 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) elseif index == 12 then --(inventory edge: play sound and set index and call this menu again) p.play_sound({ path = "inventory-edge" }) - players[pindex].circuit_network_menu.index = 11 - circuit_network_menu(pindex, ent, players[pindex].circuit_network_menu.index, false, false) + players[pindex].mod.circuit_network_menu_run.index = 11 + mod.circuit_network_menu_run( + pindex, + ent, + players[pindex].mod.circuit_network_menu_run.index, + false, + false + ) end else --Programmable speaker menu - play_selected_speaker_note(ent, true) + mod.play_selected_speaker_note(ent, true) local params = ent.parameters local circuit_params = control.circuit_parameters local instruments = ent.prototype.instruments @@ -1083,7 +1094,7 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) else printout("Local", pindex) end - play_selected_speaker_note(ent) + mod.play_selected_speaker_note(ent) end elseif index == 12 then --Switch local playback volume up @@ -1095,7 +1106,7 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) if params.playback_volume > 1 then params.playback_volume = 1 end ent.parameters = params printout(ent.parameters.playback_volume, pindex) - play_selected_speaker_note(ent) + mod.play_selected_speaker_note(ent) end elseif index == 13 then --Switch local playback volume down @@ -1107,7 +1118,7 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) if params.playback_volume < 0 then params.playback_volume = 0 end ent.parameters = params printout(ent.parameters.playback_volume, pindex) - play_selected_speaker_note(ent) + mod.play_selected_speaker_note(ent) end elseif index == 14 then --Switch instrument up @@ -1129,7 +1140,7 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) control.circuit_parameters = params --Read instrument printout(instruments[ins_id].name, pindex) - play_selected_speaker_note(ent) + mod.play_selected_speaker_note(ent) end elseif index == 15 then --Switch instrument down @@ -1151,7 +1162,7 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) control.circuit_parameters = params --Read instrument printout(instruments[ins_id].name, pindex) - play_selected_speaker_note(ent) + mod.play_selected_speaker_note(ent) end elseif index == 16 then --Switch note up @@ -1171,7 +1182,7 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) control.circuit_parameters = params --Read note printout(notes[note_id], pindex) - play_selected_speaker_note(ent) + mod.play_selected_speaker_note(ent) end elseif index == 17 then --Switch note down @@ -1191,7 +1202,7 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) control.circuit_parameters = params --Read note printout(notes[note_id], pindex) - play_selected_speaker_note(ent) + mod.play_selected_speaker_note(ent) end elseif index == 18 then --Toggle if signal value is pitch @@ -1206,7 +1217,7 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) else printout("Disabled", pindex) end - play_selected_speaker_note(ent) + mod.play_selected_speaker_note(ent) end elseif index == 19 then --Toggle allow polyphony @@ -1221,13 +1232,19 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) else printout("Disabled polyphony", pindex) end - play_selected_speaker_note(ent) + mod.play_selected_speaker_note(ent) end elseif index == 20 then --(inventory edge: play sound and set index and call this menu again) p.play_sound({ path = "inventory-edge" }) - players[pindex].circuit_network_menu.index = 19 - circuit_network_menu(pindex, ent, players[pindex].circuit_network_menu.index, false, false) + players[pindex].mod.circuit_network_menu_run.index = 19 + mod.circuit_network_menu_run( + pindex, + ent, + players[pindex].mod.circuit_network_menu_run.index, + false, + false + ) end end end @@ -1235,17 +1252,17 @@ function circuit_network_menu(pindex, ent_in, menu_index, clicked, other_input) end end -CIRCUIT_NETWORK_MENU_LENGTH = 20 +mod.CN_MENU_LENGTH = 20 -function circuit_network_menu_open(pindex, ent) +function mod.circuit_network_menu_open(pindex, ent) if players[pindex].vanilla_mode then return end --Set the player menu tracker to this menu - players[pindex].menu = "circuit_network_menu" + players[pindex].menu = "mod.circuit_network_menu_run" players[pindex].in_menu = true players[pindex].move_queue = {} --Set the menu line counter to 0 - players[pindex].circuit_network_menu = { + players[pindex].mod.circuit_network_menu_run = { index = 0, } @@ -1253,18 +1270,18 @@ function circuit_network_menu_open(pindex, ent) game.get_player(pindex).play_sound({ path = "Open-Inventory-Sound" }) --Load menu - local cn_menu = players[pindex].circuit_network_menu - circuit_network_menu(pindex, ent, 0, false) + local cn_menu = players[pindex].mod.circuit_network_menu_run + mod.circuit_network_menu_run(pindex, ent, 0, false) end -function circuit_network_menu_close(pindex, mute_in) +function mod.circuit_network_menu_close(pindex, mute_in) local mute = mute_in --Set the player menu tracker to none players[pindex].menu = "none" players[pindex].in_menu = false --Set the menu line counter to 0 - players[pindex].circuit_network_menu.index = 0 + players[pindex].mod.circuit_network_menu_run.index = 0 --play sound if not mute then game.get_player(pindex).play_sound({ path = "Close-Inventory-Sound" }) end @@ -1276,8 +1293,41 @@ function circuit_network_menu_close(pindex, mute_in) if game.get_player(pindex).opened ~= nil then game.get_player(pindex).opened = nil end end +--Recursively checks circuit neighbors of the ent_in and adds them to the list of members +local function add_neighbors_to_circuit_network_member_list(list_in, ent_in, color_in, iteration_in, iteration_limit) + local list = list_in or {} + local ent = ent_in + local color = color_in or "red" + local iteration = iteration_in or 1 + + --Stop after iteration_limit to prevent UPS drain + if iteration > iteration_limit then return list end + + --Add this ent to the list if not already + if ent == nil or ent.valid == false then return list end + local num = ent.unit_number + local exists = false + for i, list_ent in ipairs(list) do + if list_ent.unit_number == num then + exists = true + --This ent was counted before already, so stop immediately + return list + end + end + if exists == false then table.insert(list, ent) end + + --Get all circuit neighbors and run again + iteration = iteration + 1 + local neighbors = ent.circuit_connected_entities[color] + if neighbors == nil or #neighbors == 0 then return list end + for i, neighbor_ent in ipairs(neighbors) do + add_neighbors_to_circuit_network_member_list(list, neighbor_ent, color, iteration, iteration_limit) + end + return list +end + --Reads the total list of the circuit network neighbors of this entity. Gives details. -function circuit_network_neighbors_info(pindex, ent, wire_type) +function mod.circuit_network_neighbors_info(pindex, ent, wire_type) local color = nil if wire_type == defines.wire_type.red then color = "red" @@ -1305,7 +1355,7 @@ function circuit_network_neighbors_info(pindex, ent, wire_type) end --Reads the total list of the circuit network neighbors of this entity, and then their neighbors, and then their neighbors recursively. -function circuit_network_members_info(pindex, ent, wire_type) +function mod.circuit_network_members_info(pindex, ent, wire_type) local color = nil if wire_type == defines.wire_type.red then color = "red" @@ -1333,41 +1383,8 @@ function circuit_network_members_info(pindex, ent, wire_type) return result end ---Recursively checks circuit neighbors of the ent_in and adds them to the list of members -function add_neighbors_to_circuit_network_member_list(list_in, ent_in, color_in, iteration_in, iteration_limit) - local list = list_in or {} - local ent = ent_in - local color = color_in or "red" - local iteration = iteration_in or 1 - - --Stop after iteration_limit to prevent UPS drain - if iteration > iteration_limit then return list end - - --Add this ent to the list if not already - if ent == nil or ent.valid == false then return list end - local num = ent.unit_number - local exists = false - for i, list_ent in ipairs(list) do - if list_ent.unit_number == num then - exists = true - --This ent was counted before already, so stop immediately - return list - end - end - if exists == false then table.insert(list, ent) end - - --Get all circuit neighbors and run again - iteration = iteration + 1 - local neighbors = ent.circuit_connected_entities[color] - if neighbors == nil or #neighbors == 0 then return list end - for i, neighbor_ent in ipairs(neighbors) do - add_neighbors_to_circuit_network_member_list(list, neighbor_ent, color, iteration, iteration_limit) - end - return list -end - --Lists first 10 signals in a circuit network -function circuit_network_signals_info(pindex, nw) +function mod.circuit_network_signals_info(pindex, nw) local signals = nw.signals local result = "" local total_signal_count = 0 @@ -1398,7 +1415,7 @@ function circuit_network_signals_info(pindex, nw) return result end -function build_signal_selector(pindex) +local function build_signal_selector(pindex) local item_group_names = {} local groups = fa_utils.get_iterable_array(game.item_group_prototypes) --game.item_group_prototypes --local item_group_array = get_iterable_array(game.item_group_prototypes) @@ -1430,7 +1447,7 @@ function build_signal_selector(pindex) end end -function open_signal_selector(pindex, ent, first) +function mod.open_signal_selector(pindex, ent, first) players[pindex].menu = "signal_selector" build_signal_selector(pindex) players[pindex].signal_selector.ent = ent @@ -1438,7 +1455,7 @@ function open_signal_selector(pindex, ent, first) end --Returns the currently selected item/fluid/virtual signal prototype and the signal type -function get_selected_signal_slot_with_type(pindex) +function mod.get_selected_signal_slot_with_type(pindex) if players[pindex].signal_selector == nil then build_signal_selector(pindex) end local group_index = players[pindex].signal_selector.group_index local signal_index = players[pindex].signal_selector.signal_index @@ -1453,7 +1470,7 @@ function get_selected_signal_slot_with_type(pindex) return signal, signal_type end -function read_selected_signal_group(pindex, start_phrase_in) +function mod.read_selected_signal_group(pindex, start_phrase_in) local start_phrase = start_phrase_in or "" local group_index = players[pindex].signal_selector.group_index local signal_index = players[pindex].signal_selector.signal_index @@ -1468,9 +1485,9 @@ function read_selected_signal_group(pindex, start_phrase_in) printout(result, pindex) end -function read_selected_signal_slot(pindex, start_phrase_in) +function mod.read_selected_signal_slot(pindex, start_phrase_in) local start_phrase = start_phrase_in or "" - local prototype, signal_type = get_selected_signal_slot_with_type(pindex) + local prototype, signal_type = mod.get_selected_signal_slot_with_type(pindex) local sig_name = localising.get(prototype, pindex) if prototype == nil or sig_name == nil then printout("Error: Missing signal", pindex) @@ -1481,15 +1498,15 @@ function read_selected_signal_slot(pindex, start_phrase_in) end --For an enabled condition, updates the relevant signal from the signal selector. For a constant combinator, the selected signal gets added. -function apply_selected_signal_to_enabled_condition(pindex, ent, first) +function mod.apply_selected_signal_to_enabled_condition(pindex, ent, first) local start_phrase = "" - local prototype, signal_type = get_selected_signal_slot_with_type(pindex) + local prototype, signal_type = mod.get_selected_signal_slot_with_type(pindex) if prototype == nil or prototype.valid == false then game.get_player(pindex).play_sound({ path = "utility/cannot_build" }) return end if ent.type == "constant-combinator" then - constant_combinator_add_selector_signal(prototype, signal_type, ent, pindex) + mod.constant_combinator_add_selector_signal(prototype, signal_type, ent, pindex) return end local control = ent.get_control_behavior() @@ -1505,18 +1522,18 @@ function apply_selected_signal_to_enabled_condition(pindex, ent, first) end circuit_condition.condition = cond ent.get_control_behavior().circuit_condition = circuit_condition - players[pindex].menu = "circuit_network_menu" + players[pindex].menu = "mod.circuit_network_menu_run" players[pindex].signal_selector = nil printout( set_message .. localising.get(prototype, pindex) .. ", condition now checks if " - .. read_circuit_condition(ent, true), + .. mod.read_circuit_condition(ent, true), pindex ) end -function type_circuit_condition_constant(pindex, ent) +function mod.type_circuit_condition_constant(pindex, ent) players[pindex].signal_selector = {} players[pindex].signal_selector.ent = ent local frame = game.get_player(pindex).gui.screen.add({ type = "frame", name = "circuit-condition-constant" }) @@ -1528,7 +1545,7 @@ function type_circuit_condition_constant(pindex, ent) return "Type in a number for comparing and press 'ENTER' to confirm, or press 'ESC' to exit" end -function signal_selector_group_up(pindex) +function mod.signal_selector_group_up(pindex) if players[pindex].signal_selector == nil then build_signal_selector(pindex) end game.get_player(pindex).play_sound({ path = "Inventory-Move" }) local jumps = 1 @@ -1559,7 +1576,7 @@ function signal_selector_group_up(pindex) return jumps end -function signal_selector_group_down(pindex) +function mod.signal_selector_group_down(pindex) if players[pindex].signal_selector == nil then build_signal_selector(pindex) end game.get_player(pindex).play_sound({ path = "Inventory-Move" }) local jumps = 1 @@ -1590,7 +1607,7 @@ function signal_selector_group_down(pindex) return jumps end -function signal_selector_signal_next(pindex) +function mod.signal_selector_signal_next(pindex) local group_index = players[pindex].signal_selector.group_index local group_name = players[pindex].signal_selector.group_names[group_index] local group = players[pindex].signal_selector.signals[group_name] @@ -1603,7 +1620,7 @@ function signal_selector_signal_next(pindex) end end -function signal_selector_signal_prev(pindex) +function mod.signal_selector_signal_prev(pindex) local group_index = players[pindex].signal_selector.group_index local group_name = players[pindex].signal_selector.group_names[group_index] local group = players[pindex].signal_selector.signals[group_name] @@ -1615,3 +1632,5 @@ function signal_selector_signal_prev(pindex) players[pindex].signal_selector.signal_index = #group end end + +return mod diff --git a/scripts/crafting.lua b/scripts/crafting.lua index b5a876c7..cc6c6575 100644 --- a/scripts/crafting.lua +++ b/scripts/crafting.lua @@ -1,4 +1,4 @@ ---Here: Crafting menu, crafting queue menu, technology menu, related functions +--Here: Crafting menu, crafting queue menu, and related functions local util = require("util") local fa_utils = require("scripts.fa-utils") diff --git a/scripts/fa-utils.lua b/scripts/fa-utils.lua index 0ee3ff2a..26c9ebb2 100644 --- a/scripts/fa-utils.lua +++ b/scripts/fa-utils.lua @@ -40,6 +40,7 @@ function mod.offset_position(oldpos, direction, distance) end end +--Reports the direction and distance of one point from another. Biased towards the diagonals. function mod.dir_dist(pos1, pos2) local x1 = pos1.x local x2 = pos2.x @@ -48,11 +49,14 @@ function mod.dir_dist(pos1, pos2) local y2 = pos2.y local dy = y2 - y1 if dx == 0 and dy == 0 then return { 8, 0 } end - local dir = math.atan2(dy, dx) --scaled -pi to pi 0 being east - dir = dir + math.sin(4 * dir) / 4 --bias towards the diagonals - dir = dir / math.pi -- now scaled as -0.5 north, 0 east, 0.5 south - dir = math.floor(dir * defines.direction.south + defines.direction.east + 0.5) --now scaled correctly - dir = dir % (2 * defines.direction.south) --now wrapped correctly + --Consistent way to calculate dir: + local dir = mod.get_direction_biased(pos2, pos1) --pos2 = that, pos1 = this + --Alternate way to calculate dir: + --local dir = math.atan2(dy, dx) --scaled -pi to pi 0 being east + --dir = dir + math.sin(4 * dir) / 4 --bias towards the diagonals + --dir = dir / math.pi -- now scaled as -0.5 north, 0 east, 0.5 south + --dir = math.floor(dir * defines.direction.south + defines.direction.east + 0.5) --now scaled correctly + --dir = dir % (2 * defines.direction.south) --now wrapped correctly local dist = math.sqrt(dx * dx + dy * dy) return { dir, dist } end @@ -159,6 +163,13 @@ function mod.get_direction_precise(pos_that, pos_this) return dir end +--Checks whether a cardinal or diagonal direction is precisely aligned. +function mod.is_direction_aligned(pos_that, pos_this) + local diff_x = math.abs(pos_this.x - pos_that.x) + local diff_y = math.abs(pos_this.y - pos_that.y) + return (diff_x < 1 or diff_y < 1 or (diff_x - diff_y) < 1) +end + --Converts an input direction into a localised string. --Note: Directions are integeres but we need to use only defines because they will change in update 2.0. Todo: localise error cases. function mod.direction_lookup(dir) @@ -646,12 +657,12 @@ function mod.get_substring_before_dash(str) end end -function mod.dir_dist_locale_h(dir_dist) - return { "access.dir-dist", { "access.direction", dir_dist[1] }, math.floor(dir_dist[2] + 0.5) } -end - +--Reads the localised result for the distance and direction from one point to the other. Also mentions if they are precisely aligned. function mod.dir_dist_locale(pos1, pos2) - return mod.dir_dist_locale_h(mod.dir_dist(pos1, pos2)) + local dir_dist = mod.dir_dist(pos1, pos2) + local aligned_note = "" + if mod.is_direction_aligned(pos1, pos2) then aligned_note = "aligned " end + return { "access.dir-dist", aligned_note .. mod.direction_lookup(dir_dist[1]), math.floor(dir_dist[2] + 0.5) } end function mod.ent_name_locale(ent) diff --git a/scripts/menu-search.lua b/scripts/menu-search.lua index c7f71791..3b941b30 100644 --- a/scripts/menu-search.lua +++ b/scripts/menu-search.lua @@ -4,6 +4,7 @@ local fa_utils = require("scripts.fa-utils") local fa_crafting = require("scripts.crafting") local localising = require("scripts.localising") local fa_sectors = require("scripts.building-vehicle-sectors") +local fa_circuits = require("scripts.circuit-networks") local mod = {} @@ -352,7 +353,7 @@ function mod.fetch_next(pindex, str, start_phrase_in) new_index = prototypes_find_index_of_next_name_match(group, search_index, str, pindex) while new_index <= 0 and tries < #players[pindex].signal_selector.group_names + 1 do players[pindex].menu_search_last_name = "(none)" - signal_selector_group_down(pindex) + fa_circuits.signal_selector_group_down(pindex) group_index = players[pindex].signal_selector.group_index group_name = players[pindex].signal_selector.group_names[group_index] group = players[pindex].signal_selector.signals[group_name] @@ -436,7 +437,7 @@ function mod.fetch_next(pindex, str, start_phrase_in) elseif players[pindex].menu == "signal_selector" then players[pindex].menu_search_index = new_index players[pindex].signal_selector.signal_index = new_index - read_selected_signal_slot(pindex, start_phrase) + fa_circuits.read_selected_signal_slot(pindex, start_phrase) else printout("Search error", pindex) return diff --git a/scripts/mining-tools.lua b/scripts/mining-tools.lua index 6a6f1ecc..74f48f66 100644 --- a/scripts/mining-tools.lua +++ b/scripts/mining-tools.lua @@ -7,10 +7,10 @@ function mod.play_mining_sound(pindex) --game.print("1",{volume_modifier=0})-- if player and player.mining_state.mining and player.selected and player.selected.valid then --game.print("2",{volume_modifier=0})-- - if player.selected.prototype.is_building then + if player.selected and player.selected.prototype.is_building then player.play_sound({ path = "player-mine" }) --game.print("3A",{volume_modifier=0})-- - else + elseif player.selected and player.selected.type ~= "resource" then player.play_sound({ path = "player-mine" }) --Mine other things, eg. character corpses, laterdo new sound --game.print("3B",{volume_modifier=0})-- end diff --git a/scripts/mouse.lua b/scripts/mouse.lua index c0a26866..71e926f6 100644 --- a/scripts/mouse.lua +++ b/scripts/mouse.lua @@ -7,19 +7,25 @@ local mod = {} --Moves the mouse pointer to the correct pixel on the screen for an input map position. If the position is off screen, then the pointer is centered on the player character instead. Does not run in vanilla mode or if the mouse is released from synchronizing. function mod.move_mouse_pointer(position, pindex) + local player = players[pindex] local pos = position + local screen = game.players[pindex].display_resolution + local screen_center = fa_utils.mult_position({ x = screen.width, y = screen.height }, 0.5) + local pixels = screen_center + local offset = { x = 0, y = 0 } if players[pindex].vanilla_mode or game.get_player(pindex).game_view_settings.update_entity_selection == true then return - elseif players[pindex].cursor and mod.cursor_position_is_on_screen_with_player_centered(pindex) == false then + elseif mod.cursor_position_is_on_screen_with_player_centered(pindex) == false then + --If the cursor is distant, center the pointer on the player pos = players[pindex].position - --move_mouse_pointer_map_mode(position,pindex) - --return + offset = fa_utils.mult_position(fa_utils.sub_position(pos, player.position), 32 * player.zoom) + elseif player.remote_view == true then + --If in remote view, + offset = { x = 0, y = 0 } + else + offset = fa_utils.mult_position(fa_utils.sub_position(pos, player.position), 32 * player.zoom) end - local player = players[pindex] - local pixels = fa_utils.mult_position(fa_utils.sub_position(pos, player.position), 32 * player.zoom) - local screen = game.players[pindex].display_resolution - local screen_c = { x = screen.width, y = screen.height } - pixels = fa_utils.add_position(pixels, fa_utils.mult_position(screen_c, 0.5)) + pixels = fa_utils.add_position(pixels, offset) mod.move_pointer_to_pixels(pixels.x, pixels.y, pindex) --game.get_player(pindex).print("moved to " .. math.floor(pixels.x) .. " , " .. math.floor(pixels.y), {volume_modifier=0})-- end diff --git a/scripts/rail-builder.lua b/scripts/rail-builder.lua index ba207508..3f0c9ca4 100644 --- a/scripts/rail-builder.lua +++ b/scripts/rail-builder.lua @@ -1,5 +1,5 @@ --Here: Functions about building rail systems, including the rail appender and everything called by the rail buidler menu ---Does not include event handlers +--Does not include event handlers, rail analysis ---@diagnostic disable: assign-type-mismatch local util = require("util") @@ -1877,8 +1877,8 @@ function mod.build_fork_at_end_rail(anchor_rail, pindex, include_forward, includ local is_end_rail local anchor_dir = anchor_rail.direction include_forward = include_forward or false - include_left = include_left or true - include_right = include_right or true + include_left = include_left or false + include_right = include_right or false --1. Firstly, check if the player has enough rails to place this (5 units) if not (stack.valid and stack.valid_for_read and stack.name == "rail" and stack.count >= 5) then @@ -2997,10 +2997,10 @@ function mod.build_fork_at_end_rail(anchor_rail, pindex, include_forward, includ --7. Sounds and results game.get_player(pindex).play_sound({ path = "entity-build/straight-rail" }) game.get_player(pindex).play_sound({ path = "entity-build/curved-rail" }) - local result = "Rail fork built with exits at " .. build_comment - if include_left then result = "left, " .. build_comment end - if include_right then result = "right, " .. build_comment end - if include_forward then result = "forward, " .. build_comment end + local result = "Rail fork built with exits at " + if include_left then result = result .. "left, " end + if include_right then result = result .. "right, " end + if include_forward then result = result .. "forward, " end result = result .. build_comment printout(result, pindex) return @@ -3040,6 +3040,7 @@ function mod.build_rail_bypass_junction(anchor_rail, pindex) --Check if the inventory has enough if players[pindex].inventory.lua_inventory.get_item_count("rail-chain-signal") < 4 then game.get_player(pindex).play_sound({ path = "utility/cannot_build" }) + game.get_player(pindex).clear_cursor() printout("You need at least 4 rail chain signals in your inventory to build this.", pindex) return else diff --git a/scripts/rails.lua b/scripts/rails.lua index 4814547d..511408d2 100644 --- a/scripts/rails.lua +++ b/scripts/rails.lua @@ -1,4 +1,4 @@ ---Here: Functions about rail systems, excluding building them +--Here: Functions about rail systems, excluding those about building them --Does not include event handlers local util = require("util") diff --git a/scripts/train-stops.lua b/scripts/train-stops.lua index 66ffdf71..0a926e61 100644 --- a/scripts/train-stops.lua +++ b/scripts/train-stops.lua @@ -1,4 +1,4 @@ ---Here: Functions relating to train train stops and train scheduling from them (a unique mod feature) +--Here: Functions relating to train train stops and train scheduling from them (which is a unique mod feature) --Does not include event handlers local mod = {} diff --git a/scripts/trains.lua b/scripts/trains.lua index 95eddeb1..ec623136 100644 --- a/scripts/trains.lua +++ b/scripts/trains.lua @@ -1,5 +1,5 @@ ---Here: Functions relating to train topics such as train info, train stops, train scheduling ---Does not include event handlers +--Here: Functions relating to train topics such as train info, instant train scheduling +--Does not include event handlers, train stops, rails local util = require("util") local fa_utils = require("scripts.fa-utils") diff --git a/scripts/worker-robots.lua b/scripts/worker-robots.lua index 460b4935..93feedf9 100644 --- a/scripts/worker-robots.lua +++ b/scripts/worker-robots.lua @@ -1,4 +1,4 @@ ---Here: Functions relating worker robots, roboports, logistic systems, blueprints and other planners, ghosts +--Here: Functions relating worker robots, roboports, logistic network systems --Does not include event handlers directly, but can have functions called by them. local util = require("util") local fa_utils = require("scripts.fa-utils")