From a7d3854217054efe46265e60fd2ac152aca2bcf6 Mon Sep 17 00:00:00 2001 From: npc-strider Date: Mon, 24 Aug 2020 20:43:41 +0800 Subject: [PATCH] spidertron link tool 1 --- changelog.txt | 8 +- control.lua | 297 ++++++++++++++----- graphics/icons/spidertron-link-tool-mask.png | Bin 0 -> 281 bytes graphics/icons/spidertron-link-tool.png | Bin 0 -> 3065 bytes graphics/icons/spidertron-unlink-tool.png | Bin 0 -> 3421 bytes info.json | 2 +- make.sh | 6 + migrations/Spider_Control_0.4.0.lua | 3 + shortcuts.lua | 137 ++++++--- 9 files changed, 341 insertions(+), 112 deletions(-) create mode 100644 graphics/icons/spidertron-link-tool-mask.png create mode 100644 graphics/icons/spidertron-link-tool.png create mode 100644 graphics/icons/spidertron-unlink-tool.png create mode 100644 make.sh create mode 100644 migrations/Spider_Control_0.4.0.lua diff --git a/changelog.txt b/changelog.txt index 943a106..878493d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -36,7 +36,13 @@ Date: 2020-08-17 --------------------------------------------------------------------------------------------------- Version: 0.3.2 -Date: 2020-08-17 +Date: 2020-08-18 Bugfixes: - Fixed leader spidertron death causing a crash - Fixed incorrect global table initialization when a vanilla game receives the mode (which fixes crash on vehicle exit and spidertron exit in a previously vanilla game) + +--------------------------------------------------------------------------------------------------- +Version: 0.3.3 +Date: 2020-08-23 + Bugfixes: + - Hotfix: fixed missing check for invalid entity diff --git a/control.lua b/control.lua index 31524ed..e538551 100644 --- a/control.lua +++ b/control.lua @@ -20,6 +20,21 @@ local function give_tool(player, stack) end end +local function give_link_tool(index) + local d = global.spidercontrol_spidersquad[index] + if d then + if #d.spiders > 0 and d.spiders[1].spider_entity.valid then --- NEED TO CHECK THIS!!!!!!!!!!!!!!!!! CAN WE REMOVE IT? + local player = game.players[index] + if give_tool(player, {name="squad-spidertron-link-tool",count=1}) then + player.cursor_stack.connected_entity=d.spiders[1].spider_entity + end + -- give_tool(player, {name="spidertron-link-tool",count=1}) + else + give_tool(game.players[index], {name="squad-spidertron-unlink-tool",count=1}) + end + end +end + local function squad_center(spidersquad) local xbar=0 local ybar=0 @@ -51,31 +66,89 @@ local function spiderbot_select(event) if give_tool(player, {name="squad-spidertron-remote",count=1}) then player.cursor_stack.connected_entity=spiders[1] end + elseif event.item == "squad-spidertron-unlink-tool" and #spiders > 0 then + if #global.spidercontrol_linked_squads > 0 then + -- This is highly unoptimised, because we're searching through the list of all spidertrons and comparing it to the spidertrons in the selection box. Not quite the worst case, because everytime we get a match we remove it from the search list and we terminate the search when nothing is left in the search list. Can have a large UPS impact spike for bases with many squads that are very large, when a large selection of spidertrons are to be unlinked + -- Is there a way to attach an attribute directly to an entity, so that we don't need to search the whole global table?? That would improve speed by a lot + local ids = {} + local force = game.players[index].force.index + for i=1, #spiders do + ids[#ids+1] = spiders[i].unit_number + end + for i,t in pairs(global.spidercontrol_linked_squads) do + if #ids == 0 then break end + if force == t.force then + local pos = t.target.position + local c = 0 + for j, spider in pairs(t.spiders) do + if #ids == 0 then break end + + for k,id in pairs(ids) do + if spider.spider_entity.unit_number == id then + global.spidercontrol_linked_squads[i].spiders[j] = nil + table.remove(ids,k) + c = c + 1 + end + end + end + if c > 0 then + if t.target and t.target.valid then + game.forces[t.force].print({"", c.." spidertrons have been unlinked from a ", t.target.localised_name, " near [gps="..pos.x..","..pos.y.."]"}) + else + game.forces[t.force].print(c.." spidertrons have been unlinked from an entity near [gps="..pos.x..","..pos.y.."]") + end + end + end + end + end end end -local function validate_spiders(index) +local function validate_spiders(t, msg) local c=0 - if global.spidercontrol_spidersquad[index] then - --for i, spider_ in pairs(global.spidercontrol_spidersquad[index].spiders) do - for i, spider in pairs(global.spidercontrol_spidersquad[index].spiders) do - if not spider.spider_entity or not spider.spider_entity.valid then - global.spidercontrol_spidersquad[index].spiders[i] = nil + if t then + --for i, spider_ in pairs(t.spiders) do + for i, spider in pairs(t.spiders) do + local spider_entity = spider.spider_entity + if not spider_entity or not spider_entity.valid then + t.spiders[i] = nil c=c+1 end end if c > 0 then - game.players[index].print(c .. " units were destroyed or mined since the last position command was sent") --this is causing crashes for one user. states that the player does not exist (why?) needs more research + local str = c .. " units were destroyed or mined since the last position command was sent" + if type(msg) == "boolean" and msg == true then -- This is for messaging when a unit is destroyed + local pos = t.target.position + game.forces[t.force].print(str..". Position is near [gps="..pos.x..","..pos.y.."]") + else + game.players[msg].print(str) --this is causing crashes for one user. states that the player does not exist (why?) needs more research + end end return true + elseif type(msg) ~= "boolean" then + global.spidercontrol_spidersquad[msg] = {spiders={}} end end -local function spiderbot_designate(index, position) - if validate_spiders(index) then - local d_ = global.spidercontrol_spidersquad[index] +local function spiderbot_designate(index, position, force) + local d_ + local msg + if force then + d_ = global.spidercontrol_linked_squads[index] + msg = true + else + d_ = global.spidercontrol_spidersquad[index] + msg = index + end + + if validate_spiders(d_, msg) then local spidersquad = d_.spiders - local leader = d_.spider_leader + local leader + local follow + if not force then + leader = d_.spider_leader + follow = game.players[index].is_shortcut_toggled("squad-spidertron-follow") + end local l_d = {0,0} if leader then if spidersquad[leader] and spidersquad[leader].spider_entity.valid then @@ -89,7 +162,6 @@ local function spiderbot_designate(index, position) end - local follow = game.players[index].is_shortcut_toggled("squad-spidertron-follow") for i, spider_ in pairs(spidersquad) do if i ~= leader or not follow then local spider = spider_.spider_entity @@ -115,6 +187,7 @@ end local function initialize() if global.spidercontrol_spidersquad == nil then game.print("Create tables for spidertron control mod") + global.spidercontrol_linked_squads = {} global.spidercontrol_spidersquad = {} for _, player in pairs(game.players) do global.spidercontrol_spidersquad[player.index] = {spider_leader = nil, spiders={}} @@ -122,6 +195,27 @@ local function initialize() end end +local function squad_leader_state(index) + local player = game.players[index] + if player.vehicle and player.vehicle.type == "spider-vehicle" then + local unit_no = player.vehicle.unit_number + if validate_spiders(global.spidercontrol_spidersquad[index], index) then + local d = global.spidercontrol_spidersquad[index].spiders + if d then + for i, spider in pairs(d) do + -- game.print(spider.spider_entity.unit_number) + if spider.spider_entity.unit_number == unit_no then + global.spidercontrol_spidersquad[index].spider_leader = i + break + end + end + end + end + elseif player.vehicle == nil and global.spidercontrol_spidersquad[index] ~= nil then -- Why is it possible for this to be nil? + global.spidercontrol_spidersquad[index].spider_leader = nil + end +end + script.on_init(initialize) script.on_configuration_changed(initialize) --commands.add_command("spiderbot_initialize_variables", "debug: ensure that all global tables are not nil (should not happen in a normal game)", initialize) @@ -134,74 +228,75 @@ script.on_event(defines.events.on_player_used_spider_remote, function(event) local player = game.players[index] local cursor_stack = player.cursor_stack if cursor_stack then -- how can a player use a remote without a cursor_stack though??? - if cursor_stack.valid_for_read and cursor_stack.name == "squad-spidertron-remote" and event.success then - player.set_shortcut_toggled("squad-spidertron-follow", false) - spiderbot_designate(index, event.position) - elseif cursor_stack.valid_for_read and cursor_stack.name == "spidertron-remote" and event.success then -- WARNING: We're only overriding for the player's spidertron if it's the vanilla spidertron remote. Does not cover modded remotes! - -- Alter dy and dx - local unit_no = event.vehicle.unit_number - local d_ = global.spidercontrol_spidersquad[index] - local spidersquad = d_.spiders - local leader = d_.spider_leader + if cursor_stack.valid_for_read and event.success then + local cname = cursor_stack.name + if cname == "squad-spidertron-remote" then + player.set_shortcut_toggled("squad-spidertron-follow", false) + spiderbot_designate(index, event.position) + elseif cname == "spidertron-remote" then -- WARNING: We're only overriding for the player's spidertron if it's the vanilla spidertron remote. Does not cover modded remotes! + -- Alter dy and dx + local unit_no = event.vehicle.unit_number + local d_ = global.spidercontrol_spidersquad[index] -- Note : Decided against doing checks on a linked squad because it would involve checking that table which can be massively large (larger than player table) + if validate_spiders(d_, index) then + local spidersquad = d_.spiders + local leader = d_.spider_leader - if spidersquad then -- HELLO: if you are reading this and have an idea how to optimize it pls let me know (Not really critical as it's not in the tick loop, but could be problematic for very large squads ) - for i, spider in pairs(spidersquad) do --something something premature debugging evil, but seriously the amount of loops are worrying (for large squds). - if i ~= leader and spider.spider_entity.unit_number == unit_no then -- Don't alter dy and dx for the squad leader (leads to infinite walking) - local dest = event.position - local flat = {} -- repack the array (which is divided because of us storing dy and dx) into a flat one - for j, spider_ in pairs(spidersquad) do - if j == i then - flat[#flat+1] = {position = dest} -- need to predict where it will be and use that as a mean, not current location - else - flat[#flat+1] = spider_.spider_entity + -- HELLO: if you are reading this and have an idea how to optimize it pls let me know (Not really critical as it's not in the tick loop, but could be problematic for very large squads ) + for i, spider in pairs(spidersquad) do --something something premature debugging evil, but seriously the amount of loops are worrying (for large squds). + if i ~= leader and spider.spider_entity.unit_number == unit_no then -- Don't alter dy and dx for the squad leader (leads to infinite walking) + local dest = event.position + local flat = {} -- repack the array (which is divided because of us storing dy and dx) into a flat one + for j, spider_ in pairs(spidersquad) do + if j == i then + flat[#flat+1] = {position = dest} -- need to predict where it will be and use that as a mean, not current location + else + flat[#flat+1] = spider_.spider_entity + end end - end - local center = squad_center(flat) - -- tried to do something without calling this loop but it's the most reliable option + local center = squad_center(flat) + -- tried to do something without calling this loop but it's the most reliable option - --very interesting problem : because the mean of the squad is dependent on the positions of each squad member, varying the dy/dx parameters of only one spider (originally the one we're moving) results in this one being scaled off the 'actual' target location - at very far distances from the squad mean this becomes very noticeable. This means we need to calculate the mean of the entire squad if one has changed position. I noticed this error because of the fact that the offset was not constant but proportional to distance away from the mean - for k, spider_ in pairs(spidersquad) do - if k == i then - global.spidercontrol_spidersquad[index].spiders[k].d = { - dest.x - center[1], --dx - dest.y - center[2] --dy - } - else - local pos = spider_.spider_entity.position - global.spidercontrol_spidersquad[index].spiders[k].d = { - pos.x - center[1], --dx - pos.y - center[2] --dy - } + --very interesting problem : because the mean of the squad is dependent on the positions of each squad member, varying the dy/dx parameters of only one spider (originally the one we're moving) results in this one being scaled off the 'actual' target location - at very far distances from the squad mean this becomes very noticeable. This means we need to calculate the mean of the entire squad if one has changed position. I noticed this error because of the fact that the offset was not constant but proportional to distance away from the mean + for k, spider_ in pairs(spidersquad) do + if k == i then + global.spidercontrol_spidersquad[index].spiders[k].d = { + dest.x - center[1], --dx + dest.y - center[2] --dy + } + else + local pos = spider_.spider_entity.position + global.spidercontrol_spidersquad[index].spiders[k].d = { + pos.x - center[1], --dx + pos.y - center[2] --dy + } + end end + -- game.print("dx"..dest.x - center[1].."dy"..dest.y - center[2]) + break end - -- game.print("dx"..dest.x - center[1].."dy"..dest.y - center[2]) - break end end + elseif cname == "squad-spidertron-link-tool" then + if player.selected and player.selected.valid then + local selected = player.selected + local pos = selected.position + player.print({"", "Linked ".. #global.spidercontrol_spidersquad[index].spiders .. " spiders to ", selected.localised_name, " near [gps=" .. pos.x .. "," .. pos.y .. "]"}) + global.spidercontrol_linked_squads[#global.spidercontrol_linked_squads+1] = { + force=player.force.index, + target=selected, + spiders=util.table.deepcopy(global.spidercontrol_spidersquad[index].spiders) + } + global.spidercontrol_spidersquad[index] = {spider_leader = nil, spiders = {}} -- We're taking away player control of this squad! + -- Probably should print the squad ID, the target entity id and other information + else + local vehicle = event.vehicle + vehicle.autopilot_destination = vehicle.position + end end end end end) -local function squad_leader_state(index) - local player = game.players[index] - if player.vehicle and player.vehicle.type == "spider-vehicle" then - local unit_no = player.vehicle.unit_number - local d = global.spidercontrol_spidersquad[index].spiders - if d then - for i, spider in pairs(d) do - -- game.print(spider.spider_entity.unit_number) - if spider.spider_entity.valid and spider.spider_entity.unit_number == unit_no then - global.spidercontrol_spidersquad[index].spider_leader = i - break - end - end - end - elseif player.vehicle == nil then - global.spidercontrol_spidersquad[index].spider_leader = nil - end -end - script.on_event(defines.events.on_player_driving_changed_state, function (event) squad_leader_state(event.player_index) end) @@ -211,15 +306,18 @@ script.on_event(defines.events.on_player_died, function(event) end) script.on_event(defines.events.on_lua_shortcut, function (event) - if event.prototype_name == "squad-spidertron-follow" then + local name = event.prototype_name + if name == "squad-spidertron-follow" then local index = event.player_index squad_leader_state(index) spiderbot_follow(game.players[index]) + elseif name == "squad-spidertron-link-tool" then + give_link_tool(event.player_index) end end) script.on_event(defines.events.on_player_created, function (event) - global.spidercontrol_spidersquad[event.player_index] = {spiders={}} + global.spidercontrol_spidersquad[event.player_index] = {spider_leader = nil, spiders = {}} end) script.on_event("squad-spidertron-remote", function(event) @@ -235,17 +333,49 @@ script.on_event("squad-spidertron-switch-modes", function(event) local player = game.players[event.player_index] local cursor_stack = player.cursor_stack if cursor_stack and cursor_stack.valid_for_read then - if cursor_stack.name == "squad-spidertron-remote" then + local name = cursor_stack.name + if name == "squad-spidertron-remote" then give_tool(player, {name="squad-spidertron-remote-sel",count=1}) - elseif cursor_stack.name == "squad-spidertron-remote-sel" then + elseif name == "squad-spidertron-remote-sel" then local e = global.spidercontrol_spidersquad[event.player_index] if e.spiders[1] and e.spiders[1].spider_entity.valid and give_tool(player, {name="squad-spidertron-remote",count=1}) then player.cursor_stack.connected_entity=e.spiders[1].spider_entity end + -- -- Link pair + elseif name == "squad-spidertron-link-tool" then + give_tool(player, {name="squad-spidertron-unlink-tool",count=1}) + elseif name == "squad-spidertron-unlink-tool" then + give_link_tool(event.player_index) end end end) +script.on_event("squad-spidertron-link-tool", function(event) + give_link_tool(event.player_index) +end) + + + +-- -- - This stuff handles the link tool +-- script.on_event(defines.events.on_put_item, function(event) +-- local player = game.players[event.player_index] +-- local cursor_stack = player.cursor_stack +-- if cursor_stack and cursor_stack.valid_for_read then +-- if cursor_stack.name == "spidertron-link-tool" then + +-- game.print("HELLO") +-- end +-- end +-- end) + +-- script.on_event(defines.events.on_built_entity, function(event) +-- if event.created_entity.name == "spidertron-link-tool" then +-- event.created_entity.destroy() +-- -- give_tool(player, {name="spidertron-link-tool",count=1}) -- Not using because this can cause UPS lag if someone click-drags it within placement range! +-- game.print("HELLO") +-- end +-- end) + local mov_offset = settings.global["spidertron-follow-prediction-distance"].value --This is so the player stays within the spider squad when moving local mov_offset_diagonal = math.sqrt(mov_offset^2/2) @@ -293,7 +423,8 @@ script.on_nth_tick(update_interval, function(event) for _, player in pairs(game.players) do if player.is_shortcut_toggled("squad-spidertron-follow") and player.controller_type ~= 0 then -- 0 => defines.character.ghost (DEAD) local index = player.index - if global.spidercontrol_spidersquad[index].spiders[1] then + local chk = global.spidercontrol_spidersquad[index] + if chk and chk.spiders and #chk.spiders > 0 then local p_pos = player.position local pos = p_pos if player.walking_state.walking then @@ -304,4 +435,24 @@ script.on_nth_tick(update_interval, function(event) end end end + if #global.spidercontrol_linked_squads > 0 then -- Might put this on another update_interval loop so the lag can be adjusted accordingly. Use the old modulo trick for that. + for i,t in pairs(global.spidercontrol_linked_squads) do + -- local t = global.spidercontrol_linked_squads[i] + if t.spiders then + if t.target.valid then + if #t.spiders > 0 then + spiderbot_designate(i, t.target.position, true) + else + local pos = t.target.position + game.forces[t.force].print({"", "Spidertron squad has been destroyed or unlinked from ", t.target.localised_name, " near [gps="..pos.x..","..pos.y.."]"}) -- using force comms because this could be the death of a spidertron, not only removal + table.remove(global.spidercontrol_linked_squads,i) + end + else + local pos = t.spiders[1].spider_entity.position + game.forces[t.force].print("Target entity of spidertron squad has been destroyed or removed near [gps="..pos.x..","..pos.y.."]") + table.remove(global.spidercontrol_linked_squads,i) + end + end + end + end end) \ No newline at end of file diff --git a/graphics/icons/spidertron-link-tool-mask.png b/graphics/icons/spidertron-link-tool-mask.png new file mode 100644 index 0000000000000000000000000000000000000000..99a5dc49ce5db5c9245cca4af6b16e29ea5c527d GIT binary patch literal 281 zcmeAS@N?(olHy`uVBq!ia0vp^6+rC3!3HER`fe5iQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4ude`@%$AjK*4pME{-7;ac?g=3Nk409N5rUfBtcESIp;? w4fF2K-SI9zfcKcG#Px)j=E4DI%rN`R@F9@7wy@?cC(z{#p00i_>zopr0Iil|-T(jq literal 0 HcmV?d00001 diff --git a/graphics/icons/spidertron-link-tool.png b/graphics/icons/spidertron-link-tool.png new file mode 100644 index 0000000000000000000000000000000000000000..7bb38381daff42a4cb75bbbd7f525d595c668aa4 GIT binary patch literal 3065 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 Hu0mjfnTP{Z literal 0 HcmV?d00001 diff --git a/graphics/icons/spidertron-unlink-tool.png b/graphics/icons/spidertron-unlink-tool.png new file mode 100644 index 0000000000000000000000000000000000000000..fc4855947bb7c7e3cfd2ccaf81bf954753416247 GIT binary patch literal 3421 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 literal 0 HcmV?d00001 diff --git a/info.json b/info.json index 6baa9dc..dafde2a 100644 --- a/info.json +++ b/info.json @@ -1,6 +1,6 @@ { "name": "Spider_Control", - "version": "0.3.2", + "version": "0.4.0", "factorio_version": "1.0", "title": "Spidertron squad control", "author": "npc_strider(morley376)", diff --git a/make.sh b/make.sh new file mode 100644 index 0000000..6d22b1c --- /dev/null +++ b/make.sh @@ -0,0 +1,6 @@ +v=$(grep "\"version\"" info.json | sed 's|.*:||;s|[",]||g;s| ||g') +n=$(grep "\"name\"" info.json | sed 's|.*:||;s|[",]||g;s| ||g') +#echo ${n}_${v}.zip + +powershell -c "\$files = Get-ChildItem -Path . -Exclude .git,*.sh +Compress-Archive -Path \$files -DestinationPath ../${n}_${v}.zip" \ No newline at end of file diff --git a/migrations/Spider_Control_0.4.0.lua b/migrations/Spider_Control_0.4.0.lua new file mode 100644 index 0000000..82916b1 --- /dev/null +++ b/migrations/Spider_Control_0.4.0.lua @@ -0,0 +1,3 @@ +if global.spidercontrol_linked_squads == nil then + global.spidercontrol_linked_squads = {} +end \ No newline at end of file diff --git a/shortcuts.lua b/shortcuts.lua index 2ccc4b2..0ae4be5 100644 --- a/shortcuts.lua +++ b/shortcuts.lua @@ -8,6 +8,57 @@ require('util') +local item_remote_sel = { + type = "selection-tool", + name = "squad-spidertron-remote-sel", + icon = "__base__/graphics/icons/spidertron-remote.png", + -- icon_color_indicator_mask = "__base__/graphics/icons/spidertron-remote-mask.png", + icon_size = 64, icon_mipmaps = 4, + subgroup = "other", + flags = {"hidden", "not-stackable", "only-in-cursor"}, + order = "b[personal-transport]-c[spidertron]-b[squad-remote]", + stack_size = 1, + stackable = false, + selection_color = { r = 1, g = 0, b = 0 }, + alt_selection_color = { r = 1, g = 0, b = 0 }, + selection_mode = {"same-force", "entity-with-health"}, + alt_selection_mode = {"same-force", "entity-with-health"}, + selection_cursor_box_type = "copy", + alt_selection_cursor_box_type = "copy", + entity_type_filters = {"spider-vehicle"}, + tile_filters = {"lab-dark-1"}, + entity_filter_mode = "whitelist", + tile_filter_mode = "whitelist", + alt_entity_type_filters = {"spider-vehicle"}, + alt_tile_filters = {"lab-dark-1"}, + alt_entity_filter_mode = "whitelist", + alt_tile_filter_mode = "whitelist", + always_include_tiles = false +} + +local item_unlink_sel = util.table.deepcopy(item_remote_sel) +item_unlink_sel.name = "squad-spidertron-unlink-tool" +item_unlink_sel.icon = "__Spider_Control__/graphics/icons/spidertron-unlink-tool.png" + +local item_remote = { + type = "spidertron-remote", + name = "squad-spidertron-remote", + localised_name = "Spidertron squad remote", + icon = "__base__/graphics/icons/spidertron-remote.png", + icon_color_indicator_mask = "__base__/graphics/icons/spidertron-remote-mask.png", + icon_size = 64, icon_mipmaps = 4, + subgroup = "other", + flags = {"hidden", "not-stackable", "only-in-cursor"}, + order = "b[personal-transport]-c[spidertron]-b[remote]", + stack_size = 1 +} + +local item_link = util.table.deepcopy(item_remote) +item_link.name = "squad-spidertron-link-tool" +item_link.localised_name = "Spidertron link tool" +item_link.icon = "__Spider_Control__/graphics/icons/spidertron-link-tool.png" +item_link.icon_color_indicator_mask = "__Spider_Control__/graphics/icons/spidertron-link-tool-mask.png" + local shortcut_remote = { type = "shortcut", name = "squad-spidertron-remote", @@ -47,11 +98,18 @@ local shortcut_remote = { local shortcut_follow = util.table.deepcopy(shortcut_remote) shortcut_follow.name = "squad-spidertron-follow" shortcut_follow.action = "lua" -shortcut_follow.localised_name = "Follow player" +shortcut_follow.localised_name = "Spidertron follow player" shortcut_follow.associated_control_input = "squad-spidertron-follow" shortcut_follow.style = "blue" shortcut_follow.toggleable = true +local shortcut_link = util.table.deepcopy(shortcut_remote) +shortcut_link.name = "squad-spidertron-link-tool" +shortcut_link.action = "lua" +shortcut_link.localised_name = "Link spidertrons to entity" +shortcut_link.associated_control_input = "squad-spidertron-link-tool" +shortcut_link.style = "green" + local input_remote = { type = "custom-input", name = "squad-spidertron-remote", @@ -70,52 +128,57 @@ input_switch_modes.name = "squad-spidertron-switch-modes" input_switch_modes.localised_name = "Switch modes (between selecting and commanding)" input_switch_modes.key_sequence = "mouse-button-2" +local input_link = util.table.deepcopy(input_remote) +input_link.name = "squad-spidertron-link-tool" +input_link.localised_name = "Link spidertron squad to entity" +input_link.key_sequence = "ALT + Z" + data:extend( { shortcut_remote, shortcut_follow, + shortcut_link, + + item_remote_sel, + item_unlink_sel, { - type = "selection-tool", - name = "squad-spidertron-remote-sel", - icon = "__base__/graphics/icons/spidertron-remote.png", - -- icon_color_indicator_mask = "__base__/graphics/icons/spidertron-remote-mask.png", - icon_size = 64, icon_mipmaps = 4, - subgroup = "other", - flags = {"hidden", "not-stackable", "only-in-cursor"}, - order = "b[personal-transport]-c[spidertron]-b[squad-remote]", - stack_size = 1, - stackable = false, - selection_color = { r = 1, g = 0, b = 0 }, - alt_selection_color = { r = 1, g = 0, b = 0 }, - selection_mode = {"same-force", "entity-with-health"}, - alt_selection_mode = {"same-force", "entity-with-health"}, - selection_cursor_box_type = "copy", - alt_selection_cursor_box_type = "copy", - entity_type_filters = {"spider-vehicle"}, - tile_filters = {"lab-dark-1"}, - entity_filter_mode = "whitelist", - tile_filter_mode = "whitelist", - alt_entity_type_filters = {"spider-vehicle"}, - alt_tile_filters = {"lab-dark-1"}, - alt_entity_filter_mode = "whitelist", - alt_tile_filter_mode = "whitelist", - always_include_tiles = false + type = "simple-entity", + name = "spidertron-link-tool", + icon = "__base__/graphics/icons/ship-wreck/small-ship-wreck.png", + icon_size = 32, + flags = {"placeable-off-grid"}, + selectable_in_game = false, + map_color = {r=0, g=0, b=0}, + order = "a[spidertron-link-tool]", + max_health = 1, + collision_box = {{0, 0}, {0, 0}}, + collision_mask = {"layer-13"}, + picture = + { + filename = "__core__/graphics/empty.png", + width = 1, + height= 1 + } }, { - type = "spidertron-remote", - name = "squad-spidertron-remote", - localised_name = "Spidertron squad remote", - icon = "__base__/graphics/icons/spidertron-remote.png", - icon_color_indicator_mask = "__base__/graphics/icons/spidertron-remote-mask.png", - icon_size = 64, icon_mipmaps = 4, - subgroup = "other", - flags = {"hidden", "not-stackable", "only-in-cursor"}, - order = "b[personal-transport]-c[spidertron]-b[remote]", - stack_size = 1 + type = "item", + name = "spidertron-link-tool", + icon = "__base__/graphics/technology/laser.png", + icon_size = 128, + flags = {"only-in-cursor", "hidden"}, + place_result = "spidertron-link-tool", + subgroup = "capsule", + order = "zz", + stack_size = 1, + stackable = false }, + + item_remote, + item_link, input_remote, input_follow, - input_switch_modes + input_switch_modes, + input_link })