mirror of
https://github.com/peter-tanner/spidertron-squad-control.git
synced 2024-11-30 11:00:17 +08:00
First dev in 1.1: completely refactored control code, attempt spidertron
waypoints compatibility (in progress).
This commit is contained in:
parent
a7d3854217
commit
3840ea92cc
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
.vscode/
|
|
@ -46,3 +46,17 @@ Version: 0.3.3
|
|||
Date: 2020-08-23
|
||||
Bugfixes:
|
||||
- Hotfix: fixed missing check for invalid entity
|
||||
|
||||
---------------------------------------------------------------------------------------------------
|
||||
Version: 0.5.0
|
||||
Date: 2020-11-28
|
||||
Features:
|
||||
- NOTE: BETA RELEASE - USE AT YOUR OWN RISK!
|
||||
- Update mod to Factorio 1.1
|
||||
- Completely refactor code
|
||||
- Attempt at Spidertron Waypoints compatibility
|
||||
- 0NOTICE: THIS VERSION IS A WORK IN PROGRESS - CHANGELOG IS NOT FINAL
|
||||
- 1NOTICE: THIS VERSION IS A WORK IN PROGRESS - CHANGELOG IS NOT FINAL
|
||||
- 2NOTICE: THIS VERSION IS A WORK IN PROGRESS - CHANGELOG IS NOT FINAL
|
||||
- 3NOTICE: THIS VERSION IS A WORK IN PROGRESS - CHANGELOG IS NOT FINAL
|
||||
- 4NOTICE: THIS VERSION IS A WORK IN PROGRESS - CHANGELOG IS NOT FINAL
|
||||
|
|
463
control.lua
463
control.lua
|
@ -6,453 +6,62 @@
|
|||
* Spiderbot.
|
||||
--]]
|
||||
|
||||
-- /c for i=0,5 do game.player.insert("spidertron"); end; for i=0,2 do game.player.insert("spidertron-remote") end
|
||||
require("util")
|
||||
|
||||
local function give_tool(player, stack)
|
||||
if player.clean_cursor() and player.cursor_stack and player.cursor_stack.can_set_stack(stack) then
|
||||
if player.get_main_inventory() then
|
||||
player.get_main_inventory().remove("squad-spidertron-remote-sel")
|
||||
player.get_main_inventory().remove("squad-spidertron-remote")
|
||||
end
|
||||
player.cursor_stack.set_stack(stack)
|
||||
return true
|
||||
end
|
||||
end
|
||||
require("control.debug")
|
||||
-- REMEMBER TO COMMENT DEBUG OUT IN RELEASE!!
|
||||
-- REMEMBER TO COMMENT DEBUG OUT IN RELEASE!!
|
||||
-- REMEMBER TO COMMENT DEBUG OUT IN RELEASE!!
|
||||
-- REMEMBER TO COMMENT DEBUG OUT IN RELEASE!!
|
||||
-- REMEMBER TO COMMENT DEBUG OUT IN RELEASE!!
|
||||
|
||||
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
|
||||
local c=0
|
||||
for i=1, #spidersquad do
|
||||
c=c+1
|
||||
local pos = spidersquad[i].position
|
||||
xbar=xbar+pos.x
|
||||
ybar=ybar+pos.y
|
||||
end
|
||||
return {xbar/c,ybar/c}
|
||||
end
|
||||
|
||||
local function spiderbot_select(event)
|
||||
local index = event.player_index
|
||||
local spiders = event.entities
|
||||
if event.item == "squad-spidertron-remote-sel" and #spiders > 0 then
|
||||
local center = squad_center(spiders)
|
||||
global.spidercontrol_spidersquad[index] = {spiders={}} -- some future proofing here
|
||||
for i=1, #spiders do
|
||||
local spider = spiders[i]
|
||||
local pos = spider.position
|
||||
table.insert(global.spidercontrol_spidersquad[index].spiders, {
|
||||
spider_entity=spider,
|
||||
d={pos.x-center[1],pos.y-center[2]} -- dx and dy
|
||||
})
|
||||
end
|
||||
local player = game.players[index]
|
||||
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(t, msg)
|
||||
local c=0
|
||||
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
|
||||
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, 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
|
||||
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
|
||||
-- game.players[index].print("Leader "..leader)
|
||||
l_d = spidersquad[leader].d
|
||||
else
|
||||
game.players[index].print("Leader destroyed") -- In case destroyed by biters/nuke/whatever
|
||||
global.spidercontrol_spidersquad[index].spider_leader = nil
|
||||
leader = nil
|
||||
end
|
||||
end
|
||||
require("control.init")
|
||||
require("control.remote")
|
||||
require("control.give_remote")
|
||||
require("control.player_select")
|
||||
require("control.player_man_designate")
|
||||
require("control.player_follow")
|
||||
require("control.entity_follow")
|
||||
require("control.functions")
|
||||
-- require("control.select")
|
||||
|
||||
|
||||
for i, spider_ in pairs(spidersquad) do
|
||||
if i ~= leader or not follow then
|
||||
local spider = spider_.spider_entity
|
||||
local d = spider_.d
|
||||
spider.autopilot_destination = {position.x+d[1]-l_d[1], position.y+d[2]-l_d[2]} -- leader dy and dx offsets so that the leader itself becomes the new mean of the squad.
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
------------------------------------------------------------------------
|
||||
-- EVENTS
|
||||
------------------------------------------------------------------------
|
||||
|
||||
local function spiderbot_follow(player)
|
||||
if player.character then
|
||||
if player.is_shortcut_toggled("squad-spidertron-follow") then
|
||||
player.set_shortcut_toggled("squad-spidertron-follow", false)
|
||||
else
|
||||
player.set_shortcut_toggled("squad-spidertron-follow", true)
|
||||
end
|
||||
else
|
||||
player.print({"", {"error.error-message-box-title"}, ": ", {"player-doesnt-exist", {"gui.character"}}, " (", {"controller.god"}, "): ", {"gui-mod-info.status-disabled"}})
|
||||
end
|
||||
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={}}
|
||||
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
|
||||
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)
|
||||
|
||||
script.on_event(defines.events.on_player_alt_selected_area, spiderbot_select)
|
||||
script.on_event(defines.events.on_player_selected_area, spiderbot_select)
|
||||
|
||||
script.on_event(defines.events.on_player_used_spider_remote, function(event)
|
||||
local index = event.player_index
|
||||
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 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
|
||||
|
||||
-- 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
|
||||
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
|
||||
}
|
||||
end
|
||||
end
|
||||
-- game.print("dx"..dest.x - center[1].."dy"..dest.y - center[2])
|
||||
break
|
||||
end
|
||||
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
|
||||
-- Follow
|
||||
script.on_event("squad-spidertron-follow", function(event)
|
||||
-- squad_leader_state(event.player_index)
|
||||
SpiderbotFollow(game.players[event.player_index])
|
||||
end)
|
||||
|
||||
script.on_event(defines.events.on_player_driving_changed_state, function (event)
|
||||
squad_leader_state(event.player_index)
|
||||
end)
|
||||
|
||||
script.on_event(defines.events.on_player_died, function(event)
|
||||
squad_leader_state(event.player_index)
|
||||
-- link tool
|
||||
script.on_event("squad-spidertron-link-tool", function(event)
|
||||
GiveLinkTool(event.player_index)
|
||||
end)
|
||||
|
||||
script.on_event(defines.events.on_lua_shortcut, function (event)
|
||||
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])
|
||||
-- squad_leader_state(index)
|
||||
SpiderbotFollow(game.players[index])
|
||||
elseif name == "squad-spidertron-link-tool" then
|
||||
give_link_tool(event.player_index)
|
||||
GiveLinkTool(event.player_index)
|
||||
end
|
||||
end)
|
||||
|
||||
script.on_event(defines.events.on_player_created, function (event)
|
||||
global.spidercontrol_spidersquad[event.player_index] = {spider_leader = nil, spiders = {}}
|
||||
end)
|
||||
|
||||
script.on_event("squad-spidertron-remote", function(event)
|
||||
give_tool(game.players[event.player_index], {name="squad-spidertron-remote-sel",count=1})
|
||||
end)
|
||||
|
||||
script.on_event("squad-spidertron-follow", function(event)
|
||||
squad_leader_state(event.player_index)
|
||||
spiderbot_follow(game.players[event.player_index])
|
||||
end)
|
||||
|
||||
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
|
||||
local name = cursor_stack.name
|
||||
if name == "squad-spidertron-remote" then
|
||||
give_tool(player, {name="squad-spidertron-remote-sel",count=1})
|
||||
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)
|
||||
script.on_nth_tick(settings.global["spidertron-follow-update-interval"].value, function(event)
|
||||
UpdateFollow()
|
||||
UpdateFollowEntity()
|
||||
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
|
||||
-- script.on_event(defines.events.on_spider_command_completed, function (event)
|
||||
-- game.print(game.tick)
|
||||
-- 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)
|
||||
|
||||
local function pos_offset(position,dir)
|
||||
local def_dir = defines.direction
|
||||
local pos_x = position.x
|
||||
local pos_y = position.y
|
||||
|
||||
if dir == def_dir.north then
|
||||
pos_y = pos_y - mov_offset
|
||||
elseif dir == def_dir.northeast then
|
||||
-- game.print("ne")
|
||||
pos_x = pos_x + mov_offset_diagonal
|
||||
pos_y = pos_y - mov_offset_diagonal
|
||||
elseif dir == def_dir.east then
|
||||
-- game.print("e")
|
||||
pos_x = pos_x + mov_offset
|
||||
elseif dir == def_dir.southeast then
|
||||
-- game.print("se")
|
||||
pos_x = pos_x + mov_offset_diagonal
|
||||
pos_y = pos_y + mov_offset_diagonal
|
||||
elseif dir == def_dir.south then
|
||||
-- game.print("s")
|
||||
pos_y = pos_y + mov_offset
|
||||
elseif dir == def_dir.southwest then
|
||||
-- game.print("sw")
|
||||
pos_x = pos_x - mov_offset_diagonal
|
||||
pos_y = pos_y + mov_offset_diagonal
|
||||
elseif dir == def_dir.west then
|
||||
-- game.print("w")
|
||||
pos_x = pos_x - mov_offset
|
||||
else -- northwest
|
||||
-- game.print("nw")
|
||||
pos_x = pos_x - mov_offset_diagonal
|
||||
pos_y = pos_y - mov_offset_diagonal
|
||||
end
|
||||
|
||||
return {x=pos_x, y=pos_y}
|
||||
end
|
||||
|
||||
local update_interval = settings.global["spidertron-follow-update-interval"].value
|
||||
|
||||
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
|
||||
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
|
||||
local dir = player.walking_state.direction
|
||||
pos = pos_offset(p_pos,dir)
|
||||
end
|
||||
spiderbot_designate(index, pos)
|
||||
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)
|
||||
script.on_load(function()
|
||||
SpidertronWaypointsCompatibility()
|
||||
end)
|
||||
|
|
88
control/2dvec.lua
Normal file
88
control/2dvec.lua
Normal file
|
@ -0,0 +1,88 @@
|
|||
|
||||
|
||||
function IJMean(vectors)
|
||||
local sumx = 0
|
||||
local sumy = 0
|
||||
for i=1, #vectors do
|
||||
local vec = vectors[i]
|
||||
sumx = vec.x + sumx
|
||||
sumy = vec.y + sumy
|
||||
end
|
||||
return {
|
||||
x = sumx/#vectors,
|
||||
y = sumy/#vectors
|
||||
}
|
||||
end
|
||||
|
||||
function IJMeanEntity(entities)
|
||||
local sumx = 0
|
||||
local sumy = 0
|
||||
for i=1, #entities do
|
||||
local pos = entities[i].position
|
||||
sumx = pos.x + sumx
|
||||
sumy = pos.y + sumy
|
||||
end
|
||||
return {
|
||||
x = sumx/#entities,
|
||||
y = sumy/#entities
|
||||
}
|
||||
end
|
||||
|
||||
function IJDelta(vec1, vec2)
|
||||
local dx = vec2.x - vec1.x
|
||||
local dy = vec2.y - vec1.y
|
||||
return { x = dx, y = dy }
|
||||
end
|
||||
|
||||
function IJAdd(vec1, vec2)
|
||||
return {
|
||||
x = vec1.x + vec2.x,
|
||||
y = vec1.y + vec2.y
|
||||
}
|
||||
end
|
||||
|
||||
function IJSub(vec1, vec2)
|
||||
return {
|
||||
x = vec1.x - vec2.x,
|
||||
y = vec1.y - vec2.y
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
function IJAhead(vec, dir, dd)
|
||||
local dd_diagonal = math.sqrt(dd^2/2)
|
||||
local d = defines.direction
|
||||
local x = vec.x
|
||||
local y = vec.y
|
||||
|
||||
if dir == d.north then
|
||||
y = y - dd
|
||||
elseif dir == d.northeast then
|
||||
-- game.print("ne")
|
||||
x = x + dd_diagonal
|
||||
y = y - dd_diagonal
|
||||
elseif dir == d.east then
|
||||
-- game.print("e")
|
||||
x = x + dd
|
||||
elseif dir == d.southeast then
|
||||
-- game.print("se")
|
||||
x = x + dd_diagonal
|
||||
y = y + dd_diagonal
|
||||
elseif dir == d.south then
|
||||
-- game.print("s")
|
||||
y = y + dd
|
||||
elseif dir == d.southwest then
|
||||
-- game.print("sw")
|
||||
x = x - dd_diagonal
|
||||
y = y + dd_diagonal
|
||||
elseif dir == d.west then
|
||||
-- game.print("w")
|
||||
x = x - dd
|
||||
else -- northwest
|
||||
-- game.print("nw")
|
||||
x = x - dd_diagonal
|
||||
y = y - dd_diagonal
|
||||
end
|
||||
|
||||
return {x=x, y=y}
|
||||
end
|
9
control/debug.lua
Normal file
9
control/debug.lua
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
commands.add_command(
|
||||
"dvars",
|
||||
"debug: dump spider control vars",
|
||||
function (cmd)
|
||||
-- game.print(serpent.block(global.spidercontrol_player_s[cmd.player_index]))
|
||||
game.print(serpent.block(global.spidercontrol_linked_s))
|
||||
end
|
||||
)
|
11
control/entity_follow.lua
Normal file
11
control/entity_follow.lua
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
require("control.2dvec")
|
||||
|
||||
function UpdateFollowEntity()
|
||||
local links = global.spidercontrol_linked_s
|
||||
for i = 1, #links do
|
||||
if (#links[i].s > 0) then
|
||||
GotoEntity(i)
|
||||
end
|
||||
end
|
||||
end
|
218
control/functions.lua
Normal file
218
control/functions.lua
Normal file
|
@ -0,0 +1,218 @@
|
|||
|
||||
function SpidertronWaypointsCompatibility()
|
||||
-- Compatability for Spidertron Waypoints
|
||||
if remote.interfaces["SpidertronWaypoints"] then
|
||||
SPIDERTRON_WAYPOINTS = true
|
||||
-- local event_ids = remote.call("SpidertronWaypoints", "get_events")
|
||||
-- local on_spidertron_given_new_destination = event_ids.on_spidertron_given_new_destination
|
||||
-- script.on_event(on_spidertron_given_new_destination, function(event)
|
||||
-- game.print("New destination")
|
||||
-- Goto(global.spidercontrol_player_s[event.player_index].active, event.position)
|
||||
-- end)
|
||||
end
|
||||
end
|
||||
|
||||
function GiveStack(player, stack)
|
||||
if player.clear_cursor() and player.cursor_stack and player.cursor_stack.can_set_stack(stack) then
|
||||
if player.get_main_inventory() then
|
||||
player.get_main_inventory().remove("squad-spidertron-remote-sel")
|
||||
player.get_main_inventory().remove("squad-spidertron-remote")
|
||||
end
|
||||
player.cursor_stack.set_stack(stack)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function Remove(table, indices)
|
||||
local n = #table
|
||||
for i = 1, #indices do
|
||||
table[indices[i]] = nil
|
||||
end
|
||||
|
||||
local tmp = {}
|
||||
for i = 1, n do
|
||||
if (table[i] ~= nil) then
|
||||
tmp[#tmp+1] = table[i]
|
||||
end
|
||||
end
|
||||
|
||||
return tmp
|
||||
end
|
||||
|
||||
function Goto(spiders, center)
|
||||
local invalid = {}
|
||||
for i = 1, #spiders do
|
||||
local spider = spiders[i].spider
|
||||
local d = spiders[i].delta
|
||||
if spider.valid then
|
||||
spider.autopilot_destination = IJAdd(center, d)
|
||||
else
|
||||
invalid[#invalid+1] = i
|
||||
end
|
||||
end
|
||||
return Remove(spiders, invalid) -- We return an updated spider list (Remove any invalid spiders)
|
||||
end
|
||||
|
||||
local function drawSprite(surface, target, scale, force, tint)
|
||||
return rendering.draw_sprite({
|
||||
sprite="item/squad-spidertron-link-tool",
|
||||
target = target,
|
||||
surface = (target.surface or surface),
|
||||
x_scale = scale,
|
||||
y_scale = scale,
|
||||
only_in_alt_mode = true,
|
||||
forces = {force},
|
||||
tint = (tint or {r=1,g=1,b=1})
|
||||
})
|
||||
end
|
||||
-- rendering.draw_sprite({sprite="item/squad-spidertron-link-tool", target = game.player.selected, surface = game.player.surface, only_in_alt_mode = true, forces = {game.player.force}, tint = {r=1,g=1,b=1}})
|
||||
local function resetSprites(indices)
|
||||
if indices then
|
||||
for i = 1, #indices do
|
||||
rendering.destroy(indices[i])
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Original GotoPlayer function before waypoints compat.
|
||||
local function GotoPlayer_(index, position)
|
||||
local active = global.spidercontrol_player_s[index].active
|
||||
local active_n = #active
|
||||
local active_updated = Goto(active, position)
|
||||
global.spidercontrol_player_s[index].active = active_updated
|
||||
|
||||
if (active_n > #active_updated) then
|
||||
local str = (active_n - #active_updated) .. " units were destroyed or mined"
|
||||
game.players[index].print(str)
|
||||
end
|
||||
end
|
||||
|
||||
local function GotoPlayerSW(index, position)
|
||||
local active = global.spidercontrol_player_s[index].active
|
||||
local player = game.players[index]
|
||||
local linear = player.is_shortcut_toggled("spidertron-remote-waypoint")
|
||||
local cyclic = player.is_shortcut_toggled("spidertron-remote-patrol")
|
||||
if (cyclic) then
|
||||
active[1].spider.autopilot_destination = nil
|
||||
local patrol = global.spidercontrol_spidertronwaypoints_patrol[index]
|
||||
if (patrol) then
|
||||
local start = rendering.get_target(patrol[1]).position
|
||||
if (util.distance(position, start) < 5) then
|
||||
for j = 1, #active do
|
||||
local waypoints = {}
|
||||
for i = 1, #patrol do
|
||||
local position = IJAdd(
|
||||
rendering.get_target(patrol[i]).position,
|
||||
active[j].delta
|
||||
)
|
||||
waypoints[#waypoints+1] = {position = position}
|
||||
end
|
||||
|
||||
remote.call("SpidertronWaypoints", "assign_patrol", active[j].spider, waypoints)
|
||||
end
|
||||
resetSprites(patrol)
|
||||
global.spidercontrol_player_s[index].active = {}
|
||||
GiveStack(player, {name="squad-spidertron-remote-sel",count=1})
|
||||
player.set_shortcut_toggled("spidertron-remote-patrol", false)
|
||||
patrol = nil
|
||||
else
|
||||
patrol[#patrol+1] = drawSprite(player.surface, position, 1.5, player.force, {r=1.0,g=0.0,b=1.0})
|
||||
end
|
||||
else
|
||||
patrol = {drawSprite(player.surface, position, 1.5, player.force, {r=1.0,g=1.0,b=1.0})}
|
||||
end
|
||||
global.spidercontrol_spidertronwaypoints_patrol[index] = patrol
|
||||
elseif (linear) then
|
||||
local active_updated = Goto(active, position)
|
||||
for i = 1, #active_updated do
|
||||
local position = IJAdd(position, active_updated[i].delta)
|
||||
local waypoint = {{position = position}}
|
||||
remote.call("SpidertronWaypoints", "assign_waypoints", active_updated[i].spider, waypoint)
|
||||
end
|
||||
|
||||
resetSprites(global.spidercontrol_spidertronwaypoints_patrol[index])
|
||||
global.spidercontrol_spidertronwaypoints_patrol[index] = nil
|
||||
else
|
||||
GotoPlayer_(index, position)
|
||||
|
||||
resetSprites(global.spidercontrol_spidertronwaypoints_patrol[index])
|
||||
global.spidercontrol_spidertronwaypoints_patrol[index] = nil
|
||||
end
|
||||
end
|
||||
|
||||
function GotoPlayer(index, position)
|
||||
if SPIDERTRON_WAYPOINTS then
|
||||
GotoPlayerSW(index, position)
|
||||
else
|
||||
GotoPlayer_(index, position)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function GotoEntity(index)
|
||||
local t = global.spidercontrol_linked_s[index]
|
||||
local entity = t.target
|
||||
local active = t.s
|
||||
if entity.valid then
|
||||
local active_n = #active
|
||||
local pos = entity.position
|
||||
|
||||
local active_updated = Goto(active, pos)
|
||||
|
||||
global.spidercontrol_linked_s[index].s = active_updated
|
||||
|
||||
if (active_n > #active_updated) then
|
||||
local str = (active_n - #active_updated) .. " units were destroyed or mined near [gps="..pos.x..","..pos.y.."], linked to "..entity.localised_name
|
||||
game.forces[t.force].print(str)
|
||||
end
|
||||
|
||||
if (#active_updated == 0) then
|
||||
local str = {"", "Spidertron squad has been destroyed or unlinked from ", entity.localised_name, " near [gps="..pos.x..","..pos.y.."]"}
|
||||
game.forces[t.force].print(str) -- using force comms because this could be the death of a spidertron, not only removal
|
||||
end
|
||||
else
|
||||
local e = false
|
||||
for i = 1, #active do
|
||||
if (active[i].spider.valid) then
|
||||
e = active[i].spider
|
||||
end
|
||||
end
|
||||
if (e) then
|
||||
local pos = e.position
|
||||
game.forces[t.force].print("Target entity of spidertron squad has been destroyed or removed near [gps="..pos.x..","..pos.y.."]")
|
||||
else
|
||||
game.forces[t.force].print("Target entity of spidertron squad has been destroyed or removed")
|
||||
end
|
||||
|
||||
global.spidercontrol_linked_s = Remove(global.spidercontrol_linked_s, {index})
|
||||
end
|
||||
end
|
||||
|
||||
function FirstValid(entities)
|
||||
for i = 1, #entities do
|
||||
if entities[i] and entities[i].valid then
|
||||
return entities[i]
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- local function squad_center(spidersquad)
|
||||
-- local xbar=0
|
||||
-- local ybar=0
|
||||
-- local c=0
|
||||
-- for i=1, #spidersquad do
|
||||
-- c=c+1
|
||||
-- local pos = spidersquad[i].position
|
||||
-- xbar=xbar+pos.x
|
||||
-- ybar=ybar+pos.y
|
||||
-- end
|
||||
-- return {xbar/c,ybar/c}
|
||||
-- end
|
||||
|
||||
function Mean(list)
|
||||
local sum = 0
|
||||
for i=1, #list do
|
||||
sum=sum+list[i]
|
||||
end
|
||||
return sum/#list
|
||||
end
|
51
control/give_remote.lua
Normal file
51
control/give_remote.lua
Normal file
|
@ -0,0 +1,51 @@
|
|||
require("control.functions")
|
||||
|
||||
function GiveLinkTool(index)
|
||||
local d = global.spidercontrol_player_s[index].active
|
||||
if (#d > 0 and d[1].spider.valid) then
|
||||
local player = game.players[index]
|
||||
if GiveStack(player, {name="squad-spidertron-link-tool",count=1}) then
|
||||
player.cursor_stack.connected_entity = d[1].spider
|
||||
end
|
||||
else
|
||||
GiveStack(game.players[index], {name="squad-spidertron-unlink-tool",count=1})
|
||||
end
|
||||
end
|
||||
|
||||
script.on_event("squad-spidertron-remote", function(event)
|
||||
GiveStack(game.players[event.player_index], {name="squad-spidertron-remote-sel",count=1})
|
||||
end)
|
||||
|
||||
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
|
||||
local name = cursor_stack.name
|
||||
if name == "squad-spidertron-remote" then
|
||||
GiveStack(player, {name="squad-spidertron-remote-sel",count=1})
|
||||
elseif name == "squad-spidertron-remote-sel" then
|
||||
local e = global.spidercontrol_player_s[event.player_index].active
|
||||
if e[1] and e[1].spider.valid and GiveStack(player, {name="squad-spidertron-remote",count=1}) then
|
||||
player.cursor_stack.connected_entity = e[1].spider
|
||||
end
|
||||
-- -- Link pair
|
||||
elseif name == "squad-spidertron-link-tool" then
|
||||
GiveStack(player, {name="squad-spidertron-unlink-tool",count=1})
|
||||
elseif name == "squad-spidertron-unlink-tool" then
|
||||
GiveLinkTool(event.player_index)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
-- script.on_event(defines.events.on_lua_shortcut, function (event)
|
||||
-- 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
|
||||
-- GiveLinkTool(event.player_index)
|
||||
-- end
|
||||
-- end)
|
||||
|
17
control/init.lua
Normal file
17
control/init.lua
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
local function initialize()
|
||||
if global.spidercontrol_spidersquad == nil then
|
||||
game.print("Create tables for spidertron control mod")
|
||||
global.spidercontrol_linked_s = {}
|
||||
global.spidercontrol_player_s = {}
|
||||
global.spidercontrol_spidertronwaypoints_patrol = {}
|
||||
for _, player in pairs(game.players) do
|
||||
global.spidercontrol_player_s[player.index] = {active = {}, inactive = {}} -- Some future-proofing here
|
||||
end
|
||||
end
|
||||
SpidertronWaypointsCompatibility()
|
||||
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)
|
63
control/player_follow.lua
Normal file
63
control/player_follow.lua
Normal file
|
@ -0,0 +1,63 @@
|
|||
|
||||
local function spidertronWaypointsOverride(s)
|
||||
if SPIDERTRON_WAYPOINTS then
|
||||
for i = 1, #s do
|
||||
remote.call("SpidertronWaypoints", "clear_waypoints", s[i].spider.unit_number)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SpiderbotFollow(player)
|
||||
if player.character then
|
||||
if player.is_shortcut_toggled("squad-spidertron-follow") then
|
||||
player.set_shortcut_toggled("squad-spidertron-follow", false)
|
||||
local index = player.index
|
||||
GotoPlayer(index, player.position)
|
||||
spidertronWaypointsOverride(global.spidercontrol_player_s[index].active)
|
||||
else
|
||||
player.set_shortcut_toggled("squad-spidertron-follow", true)
|
||||
global.spidercontrol_player_s[player.index].p_pos = nil
|
||||
end
|
||||
else
|
||||
player.print({"", {"error.error-message-box-title"}, ": ", {"player-doesnt-exist", {"gui.character"}}, " (", {"controller.god"}, "): ", {"gui-mod-info.status-disabled"}})
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
local mov_offset = settings.global["spidertron-follow-prediction-distance"].value --This is so the player stays within the spider squad when moving
|
||||
|
||||
function UpdateFollow()
|
||||
for _, player in pairs(game.players) do
|
||||
if (player.controller_type ~= 0 and player.is_shortcut_toggled("squad-spidertron-follow")) then -- 0 => defines.character.ghost (DEAD)
|
||||
local index = player.index
|
||||
local active = global.spidercontrol_player_s[index].active
|
||||
if (active and #active > 0) then
|
||||
local p_pos = global.spidercontrol_player_s[index].p_pos
|
||||
local pos = player.position
|
||||
if ( p_pos == nil or p_pos.x ~= pos.x or p_pos.y ~= pos.y ) then
|
||||
|
||||
local vehicle = player.vehicle
|
||||
if (vehicle and vehicle.type == "spider-vehicle") then
|
||||
local un = vehicle.unit_number
|
||||
for i = 1, #active do
|
||||
if (active[i].spider.unit_number == un) then
|
||||
pos = IJSub(vehicle.position, active[i].delta)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- player.print("running" .. game.tick)
|
||||
if player.walking_state.walking then
|
||||
local dir = player.walking_state.direction
|
||||
pos = IJAhead(pos, dir, mov_offset)
|
||||
end
|
||||
GotoPlayer(index, pos)
|
||||
spidertronWaypointsOverride(active)
|
||||
global.spidercontrol_player_s[index].p_pos = player.position
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
100
control/player_man_designate.lua
Normal file
100
control/player_man_designate.lua
Normal file
|
@ -0,0 +1,100 @@
|
|||
require("control.functions")
|
||||
|
||||
local function moveTo(player, index, position)
|
||||
game.players[index].set_shortcut_toggled("squad-spidertron-follow", false)
|
||||
GotoPlayer(index, position)
|
||||
end
|
||||
|
||||
local function realign(s, vehicle, position, target)
|
||||
local unit_number = vehicle.unit_number
|
||||
for i = 1, #s do
|
||||
if (s[i].spider.unit_number == unit_number) then
|
||||
-- This commented-out targeting works relative to the mean of the group, not the target entity. It has its benefits but ultimately I preferred the target-based modification, so i've left this uncommented.
|
||||
-- if (s[i+1]) then -- Use another spidertron as a reference vector/position
|
||||
-- local origin = IJSub(s[i+1].spider.position, s[i+1].delta)
|
||||
-- s[i].delta = IJSub(position, origin)
|
||||
-- elseif (s[i-1]) then
|
||||
-- local origin = IJSub(s[i-1].spider.position, s[i-1].delta)
|
||||
-- s[i].delta = IJSub(position, origin)
|
||||
-- else
|
||||
-- -- spider list should never be a sparse list, so if nothing's adjacent it's a single spidertron
|
||||
-- s[i].delta = IJSub(position, vehicle.position) -- Not really good without a ref vector
|
||||
-- end
|
||||
s[i].delta = IJSub(position, target.position)
|
||||
return s
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function drawSprite(target, scale, force, tint, target_offset)
|
||||
return rendering.draw_sprite({
|
||||
sprite="item/squad-spidertron-link-tool",
|
||||
target = target,
|
||||
surface = target.surface,
|
||||
x_scale = scale,
|
||||
y_scale = scale,
|
||||
only_in_alt_mode = true,
|
||||
forces = {force},
|
||||
tint = (tint or {r=1,g=1,b=1}),
|
||||
target_offset = (target_offset or {x=0,y=0})
|
||||
})
|
||||
end
|
||||
|
||||
local function link(index, vehicle)
|
||||
local player = game.players[index]
|
||||
local n = #global.spidercontrol_player_s[index].active
|
||||
if player.selected and player.selected.valid and n > 0 then
|
||||
local selected = player.selected
|
||||
local pos = selected.position
|
||||
local scale = 1.5
|
||||
local force = player.force
|
||||
player.print({"", "Linked ".. n .. " spiders to ", selected.localised_name, " near [gps=" .. pos.x .. "," .. pos.y .. "]"})
|
||||
local sprite = drawSprite(selected, scale, force)
|
||||
local s = util.table.deepcopy(global.spidercontrol_player_s[index].active)
|
||||
for i = 1, #s do
|
||||
s[i].sprite = drawSprite(s[i].spider, scale, force, {r=1,g=0,b=0}, {x=0,y=-0.3})
|
||||
end
|
||||
global.spidercontrol_linked_s[#global.spidercontrol_linked_s+1] = {
|
||||
force=player.force.index,
|
||||
target=selected,
|
||||
sprite=sprite,
|
||||
s=s
|
||||
}
|
||||
global.spidercontrol_player_s[index].active = {} -- We're taking away player control of this squad!
|
||||
-- Probably should print the squad ID, the target entity id and other information
|
||||
GiveStack(player, {name="squad-spidertron-unlink-tool",count=1})
|
||||
end
|
||||
vehicle.autopilot_destination = vehicle.position -- Just to look better
|
||||
end
|
||||
|
||||
|
||||
script.on_event(defines.events.on_player_used_spider_remote, function(event)
|
||||
local index = event.player_index
|
||||
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 event.success then
|
||||
local cname = cursor_stack.name
|
||||
if cname == "squad-spidertron-remote" then
|
||||
moveTo(player, 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!
|
||||
local vehicle = event.vehicle
|
||||
local position = event.position
|
||||
local s = realign(global.spidercontrol_player_s[index].active, vehicle, position, player)
|
||||
if s then
|
||||
global.spidercontrol_player_s[index].active = s
|
||||
else
|
||||
local t = global.spidercontrol_linked_s
|
||||
for i = 1, #t do
|
||||
if realign(t[i].s, vehicle, position, t[i].target) then
|
||||
global.spidercontrol_linked_s[i].t = t
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif cname == "squad-spidertron-link-tool" then
|
||||
link(index, event.vehicle)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
140
control/player_select.lua
Normal file
140
control/player_select.lua
Normal file
|
@ -0,0 +1,140 @@
|
|||
|
||||
require("control.functions")
|
||||
require("control.2dvec")
|
||||
|
||||
local function messageSpiders(target, s, force, n)
|
||||
if target.valid then
|
||||
local pos = target.position
|
||||
game.forces[force].print({"", n.." spidertrons have been unlinked from a ", target.localised_name, " near [gps="..pos.x..","..pos.y.."]"})
|
||||
else
|
||||
local e = FirstValid(s)
|
||||
if e then
|
||||
local pos = e.position
|
||||
game.forces[force].print(n.." spidertrons have been unlinked from an entity near [gps="..pos.x..","..pos.y.."]")
|
||||
else
|
||||
game.forces[force].print(n.." spidertrons have been unlinked from an entity")
|
||||
end
|
||||
end
|
||||
end
|
||||
local function messageS(target, s, force)
|
||||
if target.valid then
|
||||
local pos = target.position
|
||||
game.forces[force].print({"", "Spidertron squad has been unlinked from ", target.localised_name, " near [gps="..pos.x..","..pos.y.."]"}) -- using force comms because this could be the death of a spidertron, not only removal
|
||||
else
|
||||
local e = FirstValid(s)
|
||||
if e then
|
||||
local pos = e.position
|
||||
game.forces[force].print({"", "Spidertron squad has been unlinked from a target near [gps="..pos.x..","..pos.y.."]"})
|
||||
else
|
||||
game.forces[force].print({"", "Spidertron squad has been unlinked from a target"})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function unitNumbers(entities)
|
||||
local ids = {}
|
||||
for i = 1, #entities do
|
||||
ids[#ids+1] = entities[i].unit_number
|
||||
end
|
||||
return ids
|
||||
end
|
||||
|
||||
local function spiderDeSelect(spiders, force)
|
||||
local ids = unitNumbers(spiders)
|
||||
local t = global.spidercontrol_linked_s
|
||||
local rem_t = {} --This part is really bad - I think it's O(N^3) worst case?
|
||||
for i = 1, #t do
|
||||
if (t[i].force == force and #ids > 0) then
|
||||
local s = t[i].s
|
||||
local rem_s = {}
|
||||
for j = 1, #s do
|
||||
local rem_id = {}
|
||||
for k = 1, #ids do
|
||||
if (ids[k] == s[j].spider.unit_number) then
|
||||
s[j].spider.autopilot_destination = nil
|
||||
rem_id[#rem_id+1] = k
|
||||
rem_s[#rem_s+1] = j
|
||||
-- game.print("REMOVE["..i.."]["..j.."]")
|
||||
end
|
||||
end
|
||||
if (#rem_id > 0) then
|
||||
ids = Remove(ids, rem_id)
|
||||
if (#ids == 0) then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if (#rem_s > 0) then
|
||||
local force = t[i].force
|
||||
local target = t[i].target
|
||||
for x = 1, #rem_s do
|
||||
rendering.destroy(s[rem_s[x]].sprite)
|
||||
end
|
||||
s = Remove(s, rem_s)
|
||||
messageSpiders(target, s, force, #rem_s)
|
||||
if (#s == 0) then
|
||||
rem_t[#rem_t+1] = i
|
||||
messageS(target, s, force)
|
||||
else
|
||||
global.spidercontrol_linked_s[i].s = s
|
||||
end
|
||||
end
|
||||
if (#ids == 0) then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if (#rem_t > 0) then -- Need to remove sprite
|
||||
for x = 1, #rem_t do
|
||||
rendering.destroy(t[rem_t[x]].sprite)
|
||||
end
|
||||
global.spidercontrol_linked_s = Remove(global.spidercontrol_linked_s, rem_t)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function spiderSelect(spiders, index)
|
||||
|
||||
local player = game.players[index]
|
||||
local force = player.force.index
|
||||
local mean = IJMeanEntity(spiders)
|
||||
global.spidercontrol_player_s[index].active = {}
|
||||
|
||||
spiderDeSelect(spiders, force) -- TO prevent double-linking (linking the same spider to 2 or more entities)
|
||||
if SPIDERTRON_WAYPOINTS then
|
||||
for i = 1, #spiders do
|
||||
remote.call("SpidertronWaypoints", "clear_waypoints", spiders[i].unit_number)
|
||||
spiders[i].autopilot_destination = nil
|
||||
end
|
||||
end
|
||||
-- spiderDeSelectPlayers(spiders, force) -- Y'know what, not sure if i can be arsed to deselect player squads...
|
||||
|
||||
for i=1, #spiders do
|
||||
table.insert(global.spidercontrol_player_s[index].active, {
|
||||
spider = spiders[i],
|
||||
delta = IJDelta(mean, spiders[i].position)
|
||||
})
|
||||
end
|
||||
|
||||
if GiveStack(player, {name="squad-spidertron-remote",count=1}) then
|
||||
player.cursor_stack.connected_entity=spiders[1]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function areaSelection(event)
|
||||
local index = event.player_index
|
||||
local spiders = event.entities -- We're only selecting spiders from our force (due to force filter)
|
||||
local item = event.item
|
||||
if #spiders > 0 then
|
||||
if item == "squad-spidertron-remote-sel" then
|
||||
spiderSelect(spiders, index)
|
||||
elseif item == "squad-spidertron-unlink-tool" then
|
||||
spiderDeSelect(spiders, spiders[1].force.index)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
script.on_event(defines.events.on_player_alt_selected_area, areaSelection)
|
||||
script.on_event(defines.events.on_player_selected_area, areaSelection)
|
2
control/remote.lua
Normal file
2
control/remote.lua
Normal file
|
@ -0,0 +1,2 @@
|
|||
-- Just need to claim this interface name.
|
||||
remote.add_interface("SpiderControl", {})
|
2
data.lua
2
data.lua
|
@ -6,4 +6,4 @@
|
|||
* Data
|
||||
--]]
|
||||
|
||||
require("shortcuts")
|
||||
require("prototypes.shortcuts")
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.4 KiB |
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "Spider_Control",
|
||||
"version": "0.4.0",
|
||||
"factorio_version": "1.0",
|
||||
"version": "0.5.0",
|
||||
"factorio_version": "1.1",
|
||||
"title": "Spidertron squad control",
|
||||
"author": "npc_strider(morley376)",
|
||||
"contact": "",
|
||||
|
|
13
make.sh
13
make.sh
|
@ -1,6 +1,13 @@
|
|||
# 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"
|
||||
|
||||
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
|
||||
echo ${n}_${v}.zip
|
||||
cd ..
|
||||
|
||||
powershell -c "\$files = Get-ChildItem -Path . -Exclude .git,*.sh
|
||||
Compress-Archive -Path \$files -DestinationPath ../${n}_${v}.zip"
|
||||
7z a -tzip ${n}_${v}.zip ./${n} -xr'!.git' -xr'!.gitignore' -xr'!*.pdn'
|
|
@ -8,6 +8,10 @@
|
|||
|
||||
require('util')
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- ITEMS
|
||||
------------------------------------------------------------------------
|
||||
|
||||
local item_remote_sel = {
|
||||
type = "selection-tool",
|
||||
name = "squad-spidertron-remote-sel",
|
||||
|
@ -59,15 +63,19 @@ 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"
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- SHORTCUTS
|
||||
------------------------------------------------------------------------
|
||||
|
||||
local shortcut_remote = {
|
||||
type = "shortcut",
|
||||
name = "squad-spidertron-remote",
|
||||
order = "a[squad-spidertron-remote]",
|
||||
action = "create-blueprint-item",
|
||||
action = "spawn-item",
|
||||
localised_name = "Spidertron squad remote",
|
||||
associated_control_input = "squad-spidertron-remote",
|
||||
technology_to_unlock = "spidertron",
|
||||
item_to_create = "squad-spidertron-remote-sel",
|
||||
item_to_spawn = "squad-spidertron-remote-sel",
|
||||
style = "red",
|
||||
icon =
|
||||
{
|
||||
|
@ -110,6 +118,10 @@ shortcut_link.localised_name = "Link spidertrons to entity"
|
|||
shortcut_link.associated_control_input = "squad-spidertron-link-tool"
|
||||
shortcut_link.style = "green"
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- CUSTOM INPUT
|
||||
------------------------------------------------------------------------
|
||||
|
||||
local input_remote = {
|
||||
type = "custom-input",
|
||||
name = "squad-spidertron-remote",
|
||||
|
@ -133,6 +145,10 @@ input_link.name = "squad-spidertron-link-tool"
|
|||
input_link.localised_name = "Link spidertron squad to entity"
|
||||
input_link.key_sequence = "ALT + Z"
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- EXTEND
|
||||
------------------------------------------------------------------------
|
||||
|
||||
data:extend(
|
||||
{
|
||||
shortcut_remote,
|
Loading…
Reference in New Issue
Block a user