0.3.2: Bugfixes and fixed global table init

This commit is contained in:
Peter 2020-08-18 18:52:32 +08:00
parent 39afc00b75
commit 398ed6fc87
3 changed files with 72 additions and 57 deletions

View File

@ -33,3 +33,10 @@ Date: 2020-08-17
- If the player is inisde a spidertron while in follow mode, they will not move to the 'mean' of the squad - If the player is inisde a spidertron while in follow mode, they will not move to the 'mean' of the squad
- Regular remotes can be used on spidertrons to relocate their position in the squad - Regular remotes can be used on spidertrons to relocate their position in the squad
- Regular remotes can be used on a spidertron with a player inside of it to move it and the squad to a position - Regular remotes can be used on a spidertron with a player inside of it to move it and the squad to a position
---------------------------------------------------------------------------------------------------
Version: 0.3.2
Date: 2020-08-17
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)

View File

@ -6,10 +6,11 @@
* Spiderbot. * 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") require("util")
local function give_tool(player, stack) local function give_tool(player, stack)
if player.clean_cursor() and player.cursor_stack.can_set_stack(stack) then if player.clean_cursor() and player.cursor_stack and player.cursor_stack.can_set_stack(stack) then
if player.get_main_inventory() then if player.get_main_inventory() then
player.get_main_inventory().remove("squad-spidertron-remote-sel") player.get_main_inventory().remove("squad-spidertron-remote-sel")
player.get_main_inventory().remove("squad-spidertron-remote") player.get_main_inventory().remove("squad-spidertron-remote")
@ -24,9 +25,8 @@ local function squad_center(spidersquad)
local ybar=0 local ybar=0
local c=0 local c=0
for i=1, #spidersquad do for i=1, #spidersquad do
local spider = spidersquad[i]
c=c+1 c=c+1
local pos = spider.position local pos = spidersquad[i].position
xbar=xbar+pos.x xbar=xbar+pos.x
ybar=ybar+pos.y ybar=ybar+pos.y
end end
@ -58,15 +58,14 @@ local function validate_spiders(index)
local c=0 local c=0
if global.spidercontrol_spidersquad[index] then 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
local d = global.spidercontrol_spidersquad[index].spiders for i, spider in pairs(global.spidercontrol_spidersquad[index].spiders) do
for i=1, #d do if not spider.spider_entity or not spider.spider_entity.valid then
if not d[i].spider_entity.valid then global.spidercontrol_spidersquad[index].spiders[i] = nil
table.remove(global.spidercontrol_spidersquad[index].spiders,i)
c=c+1 c=c+1
end end
end end
if c > 0 then if c > 0 then
game.players[index].print(c .. " units were destroyed or mined since the last position command was sent") 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
end end
return true return true
end end
@ -79,7 +78,7 @@ local function spiderbot_designate(index, position)
local leader = d_.spider_leader local leader = d_.spider_leader
local l_d = {0,0} local l_d = {0,0}
if leader then if leader then
if spidersquad[leader].spider_entity.valid then if spidersquad[leader] and spidersquad[leader].spider_entity.valid then
-- game.players[index].print("Leader "..leader) -- game.players[index].print("Leader "..leader)
l_d = spidersquad[leader].d l_d = spidersquad[leader].d
else else
@ -91,9 +90,8 @@ local function spiderbot_designate(index, position)
local follow = game.players[index].is_shortcut_toggled("squad-spidertron-follow") local follow = game.players[index].is_shortcut_toggled("squad-spidertron-follow")
for i=1, #spidersquad do for i, spider_ in pairs(spidersquad) do
if i ~= leader or not follow then if i ~= leader or not follow then
local spider_ = spidersquad[i]
local spider = spider_.spider_entity local spider = spider_.spider_entity
local d = spider_.d 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. 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.
@ -116,7 +114,11 @@ end
local function initialize() local function initialize()
if global.spidercontrol_spidersquad == nil then if global.spidercontrol_spidersquad == nil then
game.print("Create tables for spidertron control mod")
global.spidercontrol_spidersquad = {} global.spidercontrol_spidersquad = {}
for _, player in pairs(game.players) do
global.spidercontrol_spidersquad[player.index] = {spider_leader = nil, spiders={}}
end
end end
end end
@ -131,6 +133,7 @@ script.on_event(defines.events.on_player_used_spider_remote, function(event)
local index = event.player_index local index = event.player_index
local player = game.players[index] local player = game.players[index]
local cursor_stack = player.cursor_stack 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 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) player.set_shortcut_toggled("squad-spidertron-follow", false)
spiderbot_designate(index, event.position) spiderbot_designate(index, event.position)
@ -142,29 +145,29 @@ script.on_event(defines.events.on_player_used_spider_remote, function(event)
local leader = d_.spider_leader 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 ) 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=1, #spidersquad do --something something premature debugging evil, but seriously the amount of loops are worrying (for large squds). 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 spidersquad[i].spider_entity.unit_number == unit_no then -- Don't alter dy and dx for the squad leader (leads to infinite walking) 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 dest = event.position
local flat = {} -- repack the array (which is divided because of us storing dy and dx) into a flat one local flat = {} -- repack the array (which is divided because of us storing dy and dx) into a flat one
for j=1, #spidersquad do for j, spider_ in pairs(spidersquad) do
if j == i then 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 flat[#flat+1] = {position = dest} -- need to predict where it will be and use that as a mean, not current location
else else
flat[#flat+1] = spidersquad[j].spider_entity flat[#flat+1] = spider_.spider_entity
end end
end end
local center = squad_center(flat) local center = squad_center(flat)
-- tried to do something without calling this loop but it's the most reliable option -- 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 --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=1, #spidersquad do for k, spider_ in pairs(spidersquad) do
if k == i then if k == i then
global.spidercontrol_spidersquad[index].spiders[k].d = { global.spidercontrol_spidersquad[index].spiders[k].d = {
dest.x - center[1], --dx dest.x - center[1], --dx
dest.y - center[2] --dy dest.y - center[2] --dy
} }
else else
local pos = spidersquad[k].spider_entity.position local pos = spider_.spider_entity.position
global.spidercontrol_spidersquad[index].spiders[k].d = { global.spidercontrol_spidersquad[index].spiders[k].d = {
pos.x - center[1], --dx pos.x - center[1], --dx
pos.y - center[2] --dy pos.y - center[2] --dy
@ -177,6 +180,7 @@ script.on_event(defines.events.on_player_used_spider_remote, function(event)
end end
end end
end end
end
end) end)
local function squad_leader_state(index) local function squad_leader_state(index)
@ -185,9 +189,9 @@ local function squad_leader_state(index)
local unit_no = player.vehicle.unit_number local unit_no = player.vehicle.unit_number
local d = global.spidercontrol_spidersquad[index].spiders local d = global.spidercontrol_spidersquad[index].spiders
if d then if d then
for i=1, #d do for i, spider in pairs(d) do
-- game.print(d[i].spider_entity.unit_number) -- game.print(spider.spider_entity.unit_number)
if d[i].spider_entity.unit_number == unit_no then if spider.spider_entity.valid and spider.spider_entity.unit_number == unit_no then
global.spidercontrol_spidersquad[index].spider_leader = i global.spidercontrol_spidersquad[index].spider_leader = i
break break
end end
@ -202,6 +206,10 @@ script.on_event(defines.events.on_player_driving_changed_state, function (event)
squad_leader_state(event.player_index) squad_leader_state(event.player_index)
end) end)
script.on_event(defines.events.on_player_died, function(event)
squad_leader_state(event.player_index)
end)
script.on_event(defines.events.on_lua_shortcut, function (event) script.on_event(defines.events.on_lua_shortcut, function (event)
if event.prototype_name == "squad-spidertron-follow" then if event.prototype_name == "squad-spidertron-follow" then
local index = event.player_index local index = event.player_index
@ -226,12 +234,12 @@ end)
script.on_event("squad-spidertron-switch-modes", function(event) script.on_event("squad-spidertron-switch-modes", function(event)
local player = game.players[event.player_index] local player = game.players[event.player_index]
local cursor_stack = player.cursor_stack local cursor_stack = player.cursor_stack
if cursor_stack.valid_for_read then if cursor_stack and cursor_stack.valid_for_read then
if cursor_stack.name == "squad-spidertron-remote" then if cursor_stack.name == "squad-spidertron-remote" then
give_tool(player, {name="squad-spidertron-remote-sel",count=1}) give_tool(player, {name="squad-spidertron-remote-sel",count=1})
elseif cursor_stack.name == "squad-spidertron-remote-sel" then elseif cursor_stack.name == "squad-spidertron-remote-sel" then
local e = global.spidercontrol_spidersquad[event.player_index] local e = global.spidercontrol_spidersquad[event.player_index]
if e.spiders and e.spiders[1].spider_entity.valid and give_tool(player, {name="squad-spidertron-remote",count=1}) then 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 player.cursor_stack.connected_entity=e.spiders[1].spider_entity
end end
end end
@ -283,7 +291,7 @@ local update_interval = settings.global["spidertron-follow-update-interval"].val
script.on_nth_tick(update_interval, function(event) script.on_nth_tick(update_interval, function(event)
for _, player in pairs(game.players) do for _, player in pairs(game.players) do
if player.is_shortcut_toggled("squad-spidertron-follow") then if player.is_shortcut_toggled("squad-spidertron-follow") and player.controller_type ~= 0 then -- 0 => defines.character.ghost (DEAD)
local index = player.index local index = player.index
if global.spidercontrol_spidersquad[index].spiders[1] then if global.spidercontrol_spidersquad[index].spiders[1] then
local p_pos = player.position local p_pos = player.position

View File

@ -1,6 +1,6 @@
{ {
"name": "Spider_Control", "name": "Spider_Control",
"version": "0.3.1", "version": "0.3.2",
"factorio_version": "1.0", "factorio_version": "1.0",
"title": "Spidertron squad control", "title": "Spidertron squad control",
"author": "npc_strider(morley376)", "author": "npc_strider(morley376)",