You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

830 lines
36 KiB

local Interburbulator = {}
--[[
-- have 4 shield projectors.
-- have 1 laser turet.
-- have n input addon?
A group of 3 bots are on a planet.
Antikythera / Aigilia / Eunomia
Tritan Aurum 1.6180339
Tritan Argent 2.41421356
Tritan Brontion 3.3027756
Plectrum Princeps 2.4450076
Plectrum Aurum 0.6180339
Plectrum Argent 1.41421356
Plectrum Brontion 2.3027756
Brontion Burble 33027756
The bots ask for numbers.
The bots move into a triangle and project a hololographic grid.
Interburbulator bots move to intersection points.
Hovering an Interburbulator makes them say their numbers.
-- The grid resolution is controlled by A coordinate interface.
-- need an associated ruin.
]]
Interburbulator.display_width_tiles = 16
Interburbulator.threshold = 0.000000000000001
Interburbulator.name_interburbulator_gui_root = mod_prefix.."interburbulator-control"
Interburbulator.robot_color = {r=1, g=1, b=1, a=0.1}
Interburbulator.attempts_locked_timeout = 60*15 -- 15 seconds, claimed to reset after 20s but assume lower UPS
Interburbulator.challenges = {
{ -- 1
grid = 3,
target = {2,2},
set = { {1,0,0}, {1,1,0}, {1,0,1}},
prize = {name = "raw-fish", count = 1},
attempts = 7,
success_text_prize = {"space-exploration.interburbulator_success_prize_1"}
},
{ -- 2
grid = 4,
target = {2,3},
set = { {1,0,0}, {0,1,0}, {0,0,1}},
prize = {name = mod_prefix.."machine-learning-data", count = 100},
attempts = 6,
success_text_prize = {"space-exploration.interburbulator_success_prize_2"}
},
{ -- 3
grid = 5,
target = {3,1},
set = { {1,1,1}, {0,1,0}, {0,0,1}},
prize = {name = mod_prefix.."significant-data", count = 100},
attempts = 6,
success_text_prize = {"space-exploration.interburbulator_success_prize_3"}
},
{ -- 4
grid = 6,
target = {4,4},
set = { {-1,0,0}, {0,1,0}, {0,0,1}},
prize = {name = "spidertron", count = 1},
attempts = 5,
success_text_prize = {"space-exploration.interburbulator_success_prize_4"}
},
{ -- 5
grid = 7,
target = {2,4},
set = { {1,0,0}, {0,2,0}, {0,0,7}},
attempts = 5,
prize = {name = "effectivity-module-9", count = 1},
success_text_prize = {"space-exploration.interburbulator_success_prize_5"}
},
{ -- 6
grid = 8,
target = {7,7},
set = { {1,6,1}, {8,0,3}, {3,9,8}},
prize = {name = "speed-module-9", count = 1},
attempts = 4,
success_text_prize = {"space-exploration.interburbulator_success_prize_6"}
},
{ -- 7
grid = 10,
target = {3,6},
set = { {0.1,0.6,0.1}, {0.8,-0.1,0.3}, {0.3,0.9,0.8}},
prize = {name = "productivity-module-9", count = 1},
attempts = 4,
success_text_prize = {"space-exploration.interburbulator_success_prize_7"}
},
{ -- 8
grid = 15,
target = {13,15},
set = { {0.87,0.49,0.89}, {0.48,0.48,0.2}, {0.45,0.86,0.83}},
prize = {name = mod_prefix.."wide-beacon-2", count = 4},
attempts = 3,
success_text_prize = {"space-exploration.interburbulator_success_prize_8"}
},
{ -- 9
grid = 20,
target = {17,2},
set = { {-436,563,-811}, {772,30,917}, {980,576,286}},
prize = {name = mod_prefix.."naquium-processor", count = 8},
attempts = 3,
success_text_prize = {"space-exploration.interburbulator_success_prize_9"}
},
{ -- 10
grid = 50,
target = {33,44},
set = { {1.618033,0.9887498,0.48204586}, {2.414213,0.5623730,0.9504880}, {3.302775,0.6377319,0.9464655}},
prize = {name = mod_prefix.."arcosphere", count = 10},
attempts = 2,
success_text_prize = {"space-exploration.interburbulator_success_prize_10"}
},
}
Interburbulator.success_freeplay = {}
for i = 1, 5 do
table.insert(Interburbulator.success_freeplay, "interburbulator_success_freeplay_"..i)
end
Interburbulator.success_repeat = {}
for i = 1, 6 do
table.insert(Interburbulator.success_repeat, "interburbulator_success_repeat_"..i)
end
Interburbulator.fail_text = {}
Interburbulator.fail_bad_text = {}
for i = 1, 39 do
table.insert(Interburbulator.fail_text, "interburbulator_fail_easy_"..i)
end
for i = 1, 10 do
table.insert(Interburbulator.fail_bad_text, "interburbulator_fail_offgrid_"..i)
end
for i = 1, 9 do
table.insert(Interburbulator.fail_text, "interburbulator_fail_mixed_"..i)
table.insert(Interburbulator.fail_bad_text, "interburbulator_fail_mixed_"..i)
end
Interburbulator.locked_text = {}
for i = 1, 6 do
table.insert(Interburbulator.locked_text, "interburbulator_challenge_locked_"..i)
end
function Interburbulator.message(player, text)
player.print({"space-exploration.interburbulator_speak", text})
end
function Interburbulator.make_interburbulator(zone, position)
if global.interburbulator then return end -- don't make 2
global.interburbulator = {
zone = zone,
position = position or {x=0, y=0},
challenge_index = 1,
challenge_set = nil, -- only used when you set a custom/random challenge.
challenge_grid_size = nil, -- only used when you set a custom/random challenge.
challenge_cell = nil, -- only used when you set a custom/random challenge.
guessed_vector = nil, -- shown after a guess
guessed_position = nil, -- shown after a guess
guessed_cell = nil, -- shown after a guess
guessed_player_index = nil,
shape_ids = {},
prizes_won = {}, -- could be indexed by player-challenge but for now just challenge
freeplay_unlocked = false
}
zone.interburbulator = global.interburbulator
Interburbulator.build_platform()
end
function Interburbulator.build_platform()
if global.interburbulator.robot and global.interburbulator.robot.valid and global.interburbulator.interface and global.interburbulator.interface.valid then return end
local surface = Zone.get_surface(global.interburbulator.zone)
if surface then
surface.request_to_generate_chunks(global.interburbulator.position)
surface.force_generate_chunk_requests()
Ruin.build({ruin_name = "interburbulator-platform", surface_index = surface.index, position = global.interburbulator.position})
global.interburbulator.light = rendering.draw_light{
sprite = mod_prefix.."interburbulator-light",
surface = surface,
target = global.interburbulator.position,
intesity = 2,
}
global.interburbulator.grid = rendering.draw_sprite{
sprite = mod_prefix.."interburbulator-grid",
surface = surface,
target = global.interburbulator.position,
tint = {r=0.5,b=0.5,g=0.5},
draw_on_ground = true,
alignment = "center"
}
global.interburbulator.robot = surface.find_entities_filtered{name=mod_prefix.."burbulator"}[1]
global.interburbulator.interface = surface.find_entities_filtered{name=mod_prefix.."interburbulator-control"}[1]
global.interburbulator.robot.color = Interburbulator.robot_color
global.interburbulator.robot_text = rendering.draw_text{
surface = surface,
target = global.interburbulator.robot,
text = {"space-exploration.interburbulator_robot_name"},
color = {r=0.6,g=0,b=0},
alignment = "center",
target_offset = {0, -3.5}
}
game.print({"space-exploration.interburbulator_speak", {"space-exploration.interburbulator_greeting", global.interburbulator.zone.name, Zone.get_star_from_child( global.interburbulator.zone).name}})
end
end
function Interburbulator.on_nth_tick_300()
if global.interburbulator and global.interburbulator.robot and global.interburbulator.robot.valid then
local orientation = Util.orientation_from_to(global.interburbulator.position, global.interburbulator.robot.position) + 0.25 -- why is this 0.25 off?
if orientation > 0.5 then orientation = orientation - 1 end -- -0.5 to 0.5
orientation = orientation * 0.8 - 0.2 + 0.4 * math.random()
local pos = Util.orientation_to_vector(orientation, math.random(12,15))
global.interburbulator.robot.autopilot_destination = Util.vectors_add(global.interburbulator.position, pos)
if math.random() < 0.1 then
global.interburbulator.robot.autopilot_destination = Util.vectors_add(global.interburbulator.position, {x = 0, y = -10})
end
global.interburbulator.robot.insert({name="rocket", count = 10})
global.interburbulator.robot.color = Interburbulator.robot_color
end
end
Event.addListener("on_nth_tick_300", Interburbulator.on_nth_tick_300) -- 5s
function Interburbulator.clear_display()
if global.interburbulator.shape_ids then
for _, shape_id in pairs(global.interburbulator.shape_ids) do
if rendering.is_valid(shape_id) then rendering.destroy(shape_id) end
end
end
global.interburbulator.shape_ids = {}
end
function Interburbulator.get_attempts(challenge_index)
global.interburbulator.challenge_attempts = global.interburbulator.challenge_attempts or {}
global.interburbulator.challenge_attempts[challenge_index] = global.interburbulator.challenge_attempts[challenge_index] or {
attempts = 0,
tick = game.tick
}
-- reset
if global.interburbulator.challenge_attempts[challenge_index].attempts >= Interburbulator.challenges[challenge_index].attempts and game.tick > global.interburbulator.challenge_attempts[challenge_index].tick + Interburbulator.attempts_locked_timeout then
global.interburbulator.challenge_attempts[challenge_index].attempts = 0
global.interburbulator.challenge_attempts[challenge_index].tick = game.tick
end
return global.interburbulator.challenge_attempts[challenge_index]
end
function Interburbulator.increase_attempts(challenge_index)
Interburbulator.get_attempts(challenge_index)
global.interburbulator.challenge_attempts[challenge_index].attempts =
global.interburbulator.challenge_attempts[challenge_index].attempts + 1
global.interburbulator.challenge_attempts[challenge_index].tick = game.tick
end
function Interburbulator.update(player)
if not global.interburbulator then return end
Interburbulator.clear_display()
local surface = Zone.get_surface(global.interburbulator.zone)
if not surface then return end
local vs_abc = global.interburbulator.challenge_set -- vector set: points a, b, and c. Point d is inferred to complete the square
local cells_w = global.interburbulator.challenge_grid_size
local target_cell = global.interburbulator.challenge_cell
local width
if global.interburbulator.challenge_index then
vs_abc = Interburbulator.challenges[global.interburbulator.challenge_index].set
cells_w = Interburbulator.challenges[global.interburbulator.challenge_index].grid
target_cell = Interburbulator.challenges[global.interburbulator.challenge_index].target
end
if cells_w then
Interburbulator.draw_grid(surface, cells_w)
width = Interburbulator.display_width_tiles * cells_w/(cells_w+2)
if target_cell then
local box = {
{(target_cell[1]-1)/cells_w, (target_cell[2]-1)/cells_w},
{target_cell[1]/cells_w, target_cell[2]/cells_w}
}
table.insert(global.interburbulator.shape_ids, rendering.draw_rectangle{
surface = surface,
color = {r=0.4,b=0,g=0,a=0.4},
filled = true,
left_top = { x = global.interburbulator.position.x -width/2 + box[1][1] * width, y = global.interburbulator.position.y -width/2 + box[1][2] * width },
right_bottom = { x = global.interburbulator.position.x -width/2 + box[2][1] * width, y = global.interburbulator.position.y -width/2 + box[2][2] * width },
draw_on_ground = true,
})
end
else
return
end
local v_e = global.interburbulator.guessed_vector
if v_e and v_e[1] == 0 and v_e[2] == 0 and v_e[3] == 0 then
v_e = nil
end
if not (vs_abc and v_e) then return end
local v_a2b = {} -- a to b
local v_a2c = {} -- a to c
local n_e = Util.nvector_normalise(v_e) -- the normal of point e
local v_bc = {} -- the bc midpoint
local v_abc = {} -- the abc midpoint
for i = 1, #v_e do
v_bc[i] = (vs_abc[2][i]+vs_abc[3][i])/2
v_a2b[i] = vs_abc[2][i]-vs_abc[1][i]
v_a2c[i] = vs_abc[3][i]-vs_abc[1][i]
v_abc[i] = (vs_abc[1][i] + vs_abc[2][i] + vs_abc[3][i]) / 3
end
local n_abc = Util.nvector_normalise(v_abc) -- the normal of the abc mid point
local n_abc_cross = Util.vector_cross(v_a2b, v_a2c)
local n_abc_cross = {n_abc_cross.x, n_abc_cross.y, n_abc_cross.z}
-- m_i: the magnitude multiplier for vector e where it would intersect with the abc plane
local m_i = Util.nvector_dot(n_abc_cross, Util.nvector_multiply(vs_abc[1], -1)) / Util.nvector_dot(Util.nvector_multiply(v_e, -1), n_abc_cross)
local v_i = Util.nvector_multiply(v_e, m_i) -- i, the point on the abc plane where e intersects
local v_a2i = {} -- bc_mid to a
local v_bc2a = {} -- bc_mid to a
local v_bc2b = {} -- bc_mid to b (to c is negative this vector)
local v_bc2i = {} -- bc_mid to the i intersection
for i = 1, #v_e do
v_a2i[i] = v_i[i]-vs_abc[1][i]
v_bc2a[i] = vs_abc[1][i]-v_bc[i]
v_bc2b[i] = vs_abc[2][i]-v_bc[i]
v_bc2i[i] = v_i[i]-v_bc[i]
end
-- need to de-skew the space
local sets = {{1,2},{1,3},{2,3}}
local mi_a2b
local mi_a2c
for _, set in pairs(sets) do
local u = set[1]
local v = set[2]
if mi_a2b == nil or tostring(mi_a2b) == "nan" then
mi_a2b = (v_a2i[v]*v_a2c[u]-v_a2i[u]*v_a2c[v])/(v_a2c[u]*v_a2b[v]-v_a2c[v]*v_a2b[u])
end
if mi_a2c == nil or tostring(mi_a2c) == "nan" then
mi_a2c = (v_a2i[v]*v_a2b[u]-v_a2i[u]*v_a2b[v])/(v_a2b[u]*v_a2c[v]-v_a2b[v]*v_a2c[u])
end
end
local cursor_point_2d = {
mi_a2b,
mi_a2c,
}
-- handle innacuracy
if cursor_point_2d[1] < 0 and cursor_point_2d[1] > -Interburbulator.threshold then
cursor_point_2d[1] = 0
end
if cursor_point_2d[2] < 0 and cursor_point_2d[2] > -Interburbulator.threshold then
cursor_point_2d[2] = 0
end
local best_box
local best_cell
for k = 0, cells_w do
for j = 0, cells_w do
local box
if not best_box then
box = {{k/cells_w, j/cells_w}, {(k+1)/cells_w, (j+1)/cells_w}}
if cursor_point_2d[1] >= box[1][1]
and cursor_point_2d[1] <= box[2][1]
and cursor_point_2d[2] >= box[1][2]
and cursor_point_2d[2] <= box[2][2] then
best_box = box
best_cell = {k+1, j+1}
end
end
end
end
local challenge_index = global.interburbulator.challenge_index
local attempts = 0
local allow = true
if challenge_index then
attempts = Interburbulator.get_attempts(challenge_index).attempts
if attempts >= Interburbulator.challenges[challenge_index].attempts then
allow = false
if player then
Interburbulator.message(player, {"space-exploration."..Interburbulator.locked_text[math.random(#Interburbulator.locked_text)]})
end
end
end
if allow then
if cursor_point_2d and cursor_point_2d[1] > -0.1 and cursor_point_2d[1] < 1.1
and cursor_point_2d[2] > -0.1 and cursor_point_2d[2] < 1.1 then
table.insert(global.interburbulator.shape_ids, rendering.draw_circle{
surface = surface,
color = {r=1,b=0,g=1},
filled = true,
radius = 0.2,
target = {x = global.interburbulator.position.x -width/2 + width * cursor_point_2d[1], y = global.interburbulator.position.y -width/2 + width * cursor_point_2d[2]},
draw_on_ground = true,
})
end
if best_box then
table.insert(global.interburbulator.shape_ids, rendering.draw_rectangle{
surface = surface,
color = {r=0.4,b=0,g=0.4,a=0.4},
filled = true,
left_top = { x = global.interburbulator.position.x -width/2 + best_box[1][1] * width, y = global.interburbulator.position.y -width/2 + best_box[1][2] * width },
right_bottom = { x = global.interburbulator.position.x -width/2 + best_box[2][1] * width, y = global.interburbulator.position.y -width/2 + best_box[2][2] * width },
draw_on_ground = true,
})
table.insert(global.interburbulator.shape_ids, rendering.draw_rectangle{
surface = surface,
color = {r=1,b=0,g=1,a=0.4},
filled = false,
left_top = { x = global.interburbulator.position.x -width/2 + best_box[1][1] * width, y = global.interburbulator.position.y -width/2 + best_box[1][2] * width },
right_bottom = { x = global.interburbulator.position.x -width/2 + best_box[2][1] * width, y = global.interburbulator.position.y -width/2 + best_box[2][2] * width },
draw_on_ground = true,
})
end
if player and global.interburbulator.challenge_index then
if best_cell and target_cell and best_cell[1] == target_cell[1] and best_cell[2] == target_cell[2] then
global.interburbulator.prizes_won = global.interburbulator.prizes_won or {}
if not global.interburbulator.prizes_won[global.interburbulator.challenge_index] then
global.interburbulator.prizes_won[global.interburbulator.challenge_index] = player.index
local prize = Interburbulator.challenges[global.interburbulator.challenge_index].prize
local inserted = 0
if player.character and player.character.surface == surface then
inserted = player.insert(prize)
end
local remain = (prize.count or 1) - inserted
if remain > 0 then
surface.spill_item_stack(
Util.vectors_add({x=0,y=2.25}, global.interburbulator.interface.position),
{name = prize.name, count = remain},
true,
player.force,
false)
end
Interburbulator.message(player, {
"space-exploration.simple-a-b-space",
Interburbulator.challenges[global.interburbulator.challenge_index].success_text_prize or Interburbulator.success_text_prize,
{"space-exploration.simple-a-b-space", (prize.count or 1) .." [img=item/"..prize.name.."] ", {"item-name."..prize.name}}
})
else
Interburbulator.message(player, {"space-exploration."..Interburbulator.success_repeat[math.random(#Interburbulator.success_repeat)]})
end
if table_size(global.interburbulator.prizes_won) >= 5 and not global.interburbulator.freeplay_unlocked then
global.interburbulator.freeplay_unlocked = true
Interburbulator.message(player, {"space-exploration.interburbulator_freeplay_unlocked"})
end
else
Interburbulator.increase_attempts(global.interburbulator.challenge_index)
if best_box then
Interburbulator.message(player, {"space-exploration."..Interburbulator.fail_text[math.random(#Interburbulator.fail_text)]})
else
Interburbulator.message(player, {"space-exploration."..Interburbulator.fail_bad_text[math.random(#Interburbulator.fail_bad_text)]})
end
if player and challenge_index then
attempts = Interburbulator.get_attempts(challenge_index).attempts
if attempts >= Interburbulator.challenges[challenge_index].attempts then
Interburbulator.message(player, {"space-exploration."..Interburbulator.locked_text[math.random(#Interburbulator.locked_text)]})
end
end
end
end
end
end
function Interburbulator.draw_grid(surface, cells_w)
local pos = global.interburbulator.position
local width = Interburbulator.display_width_tiles * cells_w/(cells_w+2)
for i = 1, cells_w+1 do
local p = (i-1)/(cells_w)
table.insert(global.interburbulator.shape_ids, rendering.draw_line{
surface = surface,
from = {x = pos.x - width/2, y = pos.y - width/2 + p * width},
to = {x = pos.x + width/2, y = pos.y - width/2 + p * width},
color = {r=0.5,b=0,g=0,a=0.5},
width = 1,
draw_on_ground = true
})
table.insert(global.interburbulator.shape_ids, rendering.draw_line{
surface = surface,
from = {x = pos.x - width/2 + p * width, y = pos.y - width/2},
to = {x = pos.x - width/2 + p * width, y = pos.y + width/2},
color = {r=0.5,b=0,g=0,a=0.5},
width = 1,
draw_on_ground = true
})
end
end
function Interburbulator.gui_close(player)
local gui = player.gui.screen
local root = gui[Interburbulator.name_interburbulator_gui_root]
if root then root.destroy() end
end
function Interburbulator.gui_update(player)
local root = player.gui.screen[Interburbulator.name_interburbulator_gui_root]
if not root then return end
local vs_abc = global.interburbulator.challenge_set
local cells_w = global.interburbulator.challenge_grid_size
local target_cell = global.interburbulator.challenge_cell
if global.interburbulator.challenge_index then
vs_abc = Interburbulator.challenges[global.interburbulator.challenge_index].set
cells_w = Interburbulator.challenges[global.interburbulator.challenge_index].grid
target_cell = Interburbulator.challenges[global.interburbulator.challenge_index].target
end
if target_cell then
target_cell = target_cell[1]..","..target_cell[2]
end
local challenge = util.find_first_descendant_by_name(root, "challenges")
local active_name
--if global.interburbulator.challenge_set then active_name = "challenge_random" end -- need to be able to click multiple times
if global.interburbulator.challenge_index then active_name = "challenge_"..global.interburbulator.challenge_index end
for _, button in pairs(challenge.children) do
button.enabled = true
if button.name == active_name then
button.enabled = false
end
end
if cells_w then util.find_first_descendant_by_name(root, "grid_textbox").text = ""..cells_w end
if target_cell then util.find_first_descendant_by_name(root, "target_textbox").text = ""..target_cell end
local prize_lab = util.find_first_descendant_by_name(root, "prize_lab")
if prize_lab then
if global.interburbulator.challenge_index then
local prize = Interburbulator.challenges[global.interburbulator.challenge_index].prize
local claimed = global.interburbulator.prizes_won and global.interburbulator.prizes_won[global.interburbulator.challenge_index]
local caption = {
"space-exploration.interburbulator_caption_prize",
(prize.count or 1),
"[img=item/"..prize.name.."]",
{"item-name."..prize.name},
claimed and {"space-exploration.interburbulator_caption_claimed"} or ""
}
prize_lab.caption = caption
else
prize_lab.caption = ""
end
end
if vs_abc then
local top_left = util.find_first_descendant_by_name(root, "top_left")
top_left.x.textbox.text = ""..vs_abc[1][1]
top_left.y.textbox.text = ""..vs_abc[1][2]
top_left.z.textbox.text = ""..vs_abc[1][3]
local top_right = util.find_first_descendant_by_name(root, "top_right")
top_right.x.textbox.text = ""..vs_abc[2][1]
top_right.y.textbox.text = ""..vs_abc[2][2]
top_right.z.textbox.text = ""..vs_abc[2][3]
local bottom_left = util.find_first_descendant_by_name(root, "bottom_left")
bottom_left.x.textbox.text = ""..vs_abc[3][1]
bottom_left.y.textbox.text = ""..vs_abc[3][2]
bottom_left.z.textbox.text = ""..vs_abc[3][3]
end
if global.interburbulator.challenge_index then
local attempts = Interburbulator.get_attempts(global.interburbulator.challenge_index).attempts
local attempts_max = Interburbulator.challenges[global.interburbulator.challenge_index].attempts
if attempts < attempts_max then
util.find_first_descendant_by_name(root, "attempt").caption = {"space-exploration.interburbulator_attempt_limited", attempts, attempts_max }
else
util.find_first_descendant_by_name(root, "attempt").caption = {"space-exploration.interburbulator_attempt_locked"}
end
else
util.find_first_descendant_by_name(root, "attempt").caption = {"space-exploration.interburbulator_attempt"}
end
if global.interburbulator.guessed_vector then
local attempt = util.find_first_descendant_by_name(root, "attempt")
if attempt.x.textbox.text == "" then attempt.x.textbox.text = ""..global.interburbulator.guessed_vector[1] end
if attempt.y.textbox.text == "" then attempt.y.textbox.text = ""..global.interburbulator.guessed_vector[2] end
if attempt.z.textbox.text == "" then attempt.z.textbox.text = ""..global.interburbulator.guessed_vector[3] end
end
local challenge_random = util.find_first_descendant_by_name(root, "challenge_random")
if challenge_random then
challenge_random.caption = {global.interburbulator.freeplay_unlocked and "space-exploration.interburbulator_freeplay" or "space-exploration.interburbulator_random"}
end
end
function Interburbulator.enable_textfields(element, enabled)
if element.type == "textfield" then
element.enabled = enabled
else
for _, child in pairs(element.children) do
if child.name ~= "attempt" then
Interburbulator.enable_textfields(child, enabled)
end
end
end
end
function Interburbulator.gui_open(player)
Interburbulator.gui_close(player)
local gui = player.gui.screen
local container = gui.add{ type = "frame", name = Interburbulator.name_interburbulator_gui_root, direction="vertical"}
player.opened = container
local title_flow = container.add{ type="flow", name="unit_number", direction="horizontal"}
local title = title_flow.add{ type="label", name="title", caption={"space-exploration.interburbulator_game_title"}, style="heading_1_label"}
title.ignored_by_interaction = true
if gui_name == "screen" then title_flow.drag_target = container end
-- Trying to make the fancy "Drag me" vertical bars...
local drag_handle = title_flow.add{type = "empty-widget", style = "draggable_space_header", direction="horizontal"}
drag_handle.drag_target = container
drag_handle.style.minimal_width = 20
drag_handle.style.horizontally_stretchable = true
drag_handle.style.vertically_stretchable = true
local close = title_flow.add{type="sprite-button", name=mod_prefix .. "-interburbulator-close", sprite = "utility/close_white", style="informatron_close_button"}
close.style.width = 28
close.style.height = 28
close.style.top_margin = 0
local intro = container.add{type="label", name="intro", caption={"space-exploration.interburbulator_introduction"}}
intro.style.single_line = false
intro.style.width = 500
intro.style.top_margin = 10
intro.style.bottom_margin = 10
local challenges = container.add{type="flow", name="challenges", direction="horizontal"}
challenges.style.bottom_margin = 10
for i = 1, 10 do
local button = challenges.add{type = "button", name = "challenge_"..i, caption = i}
button.style.minimal_width = 32
end
local button = challenges.add{type = "button", name = "challenge_random", caption = {
global.interburbulator.freeplay_unlocked and "space-exploration.interburbulator_freeplay" or "space-exploration.interburbulator_random"
}}
local grid = container.add{type="flow", name="grid_target", direction="horizontal"}
grid.style.vertical_align = "center"
local grid_lab = grid.add{type="label", name="grid_lab", caption={"space-exploration.interburbulator_grid_size"}}
local grid_textbox = grid.add{type="textfield", name="grid_textbox", numeric = true, allow_decimal = false, allow_negative = false}
grid_textbox.style.width = 100
local target_lab = grid.add{type="label", name="target_lab", caption={"space-exploration.interburbulator_target_cell"}}
target_lab.style.left_margin = 10
local target_textbox = grid.add{type="textfield", name="target_textbox"}
target_textbox.style.width = 100
local settings_flow1 = container.add{type = "flow", name="settings_flow1", direction = "horizontal"} settings_flow1.style.top_margin = 10
local settings_flow2 = container.add{type = "flow", name="settings_flow2", direction = "horizontal"}
local top_left = settings_flow1.add{type = "frame", name="top_left", direction="vertical", caption = {"space-exploration.interburbulator_top_left"}} top_left.style.width = 250
local top_right = settings_flow1.add{type = "frame", name="top_right", direction="vertical", caption = {"space-exploration.interburbulator_top_right"}} top_right.style.width = 250
local bottom_left = settings_flow2.add{type = "frame", name="bottom_left", direction="vertical", caption = {"space-exploration.interburbulator_bottom_left"}} bottom_left.style.width = 250
local attempt = settings_flow2.add{type = "frame", name="attempt", direction="vertical", caption = {"space-exploration.interburbulator_attempt"}} attempt.style.width = 250
for _, frame in pairs({top_left, top_right, bottom_left, attempt}) do
local x = frame.add{type="flow", name="x", direction="horizontal"} x.add{type="label", name="lab", caption="X: "} x.add{type="textfield", name="textbox", numeric = true, allow_decimal = true, allow_negative = true}
local y = frame.add{type="flow", name="y", direction="horizontal"} y.add{type="label", name="lab", caption="Y: "} y.add{type="textfield", name="textbox", numeric = true, allow_decimal = true, allow_negative = true}
local z = frame.add{type="flow", name="z", direction="horizontal"} z.add{type="label", name="lab", caption="Z: "} z.add{type="textfield", name="textbox", numeric = true, allow_decimal = true, allow_negative = true}
end
local bottom_table = container.add{ type="table", name="bottom_table", column_count=2, draw_horizontal_lines=false}
bottom_table.style.horizontally_stretchable = true
bottom_table.style.vertical_align = "bottom"
bottom_table.style.column_alignments[1] = "left" -- title, search, zone list table
bottom_table.style.column_alignments[2] = "right" -- starmap, close, selected zone info
local prize_lab = bottom_table.add{type="label", name="prize_lab"}
prize_lab.style.horizontally_stretchable = true
local submit = bottom_table.add{type="button", name=mod_prefix .. "-interburbulator-submit", style="confirm_button", caption={"space-exploration.interburbulator_submit"}}
submit.style.top_margin = 10
--Interburbulator.enable_textfields(container, false)
Interburbulator.gui_update(player)
--container.force_auto_center()
end
function Interburbulator.submit(player, skip_warnings)
local root = player.gui.screen[Interburbulator.name_interburbulator_gui_root]
if not root then return end
if global.interburbulator.freeplay_unlocked and not global.interburbulator.challenge_index then
Interburbulator.challenge_from_gui(player)
end
local attempt = util.find_first_descendant_by_name(root, "attempt")
local attempt_x = tonumber(attempt.x.textbox.text)
local attempt_y = tonumber(attempt.y.textbox.text)
local attempt_z = tonumber(attempt.z.textbox.text)
if attempt_x and attempt_y and attempt_z and not(attempt_x==0 and attempt_y==0 and attempt_z==0) then
global.interburbulator.guessed_vector = {attempt_x,attempt_y,attempt_z} -- shown after a guess
else
if not skip_warnings then
Interburbulator.message(player, "Invalid attempt vector")
end
end
global.interburbulator.guessed_player_index = player.index
Interburbulator.update(player)
Interburbulator.gui_update(player)
end
function Interburbulator.activate_challenge(challenge_index, player)
global.interburbulator.guessed_vector = nil
global.interburbulator.guessed_position = nil
global.interburbulator.guessed_cell = nil
global.interburbulator.guessed_player_index = nil
if Interburbulator.challenges[challenge_index] then
global.interburbulator.challenge_index = challenge_index
global.interburbulator.challenge_set = nil
global.interburbulator.challenge_grid_size = nil
global.interburbulator.challenge_cell = nil
else -- assume random
global.interburbulator.challenge_index = nil
global.interburbulator.challenge_grid_size = math.random(5,50)
global.interburbulator.challenge_cell = {math.random(2,global.interburbulator.challenge_grid_size-1), math.random(2,global.interburbulator.challenge_grid_size-1)}
local multiplier = 1
if math.random() < 0.23 then
multiplier = math.random() * 1000
end
global.interburbulator.challenge_set = {
{(-1+math.random()*2) *multiplier,(-1+math.random()*2) *multiplier,(-1+math.random()*2) *multiplier},
{(-1+math.random()*2) *multiplier,(-1+math.random()*2) *multiplier,(-1+math.random()*2) *multiplier},
{(-1+math.random()*2) *multiplier,(-1+math.random()*2) *multiplier,(-1+math.random()*2) *multiplier},
}
end
Interburbulator.update(player)
Interburbulator.gui_update(player)
end
function Interburbulator.challenge_from_gui(player)
local root = player.gui.screen[Interburbulator.name_interburbulator_gui_root]
if not root then return end
local grid_textbox = util.find_first_descendant_by_name(root, "grid_textbox")
local target_textbox = util.find_first_descendant_by_name(root, "target_textbox")
local top_left = util.find_first_descendant_by_name(root, "top_left")
local top_right = util.find_first_descendant_by_name(root, "top_right")
local bottom_left = util.find_first_descendant_by_name(root, "bottom_left")
local function number_or_random(inp)
return tonumber(inp) or math.random()
end
global.interburbulator.challenge_set = {
{number_or_random(top_left.x.textbox.text),number_or_random(top_left.y.textbox.text),number_or_random(top_left.z.textbox.text)},
{number_or_random(top_right.x.textbox.text),number_or_random(top_right.y.textbox.text),number_or_random(top_right.z.textbox.text)},
{number_or_random(bottom_left.x.textbox.text),number_or_random(bottom_left.y.textbox.text),number_or_random(bottom_left.z.textbox.text)},
}
local cells_w = tonumber(grid_textbox.text) or 5
cells_w = math.min(50, math.max(5, cells_w))
global.interburbulator.challenge_grid_size = cells_w
local target_cell = target_textbox.text
local parts = Util.split(target_cell, ",")
local x = 2
local y = 2
if #parts == 2 then
x = math.min(cells_w, math.max(1, Util.string_to_number(parts[1]) or 2))
y = math.min(cells_w, math.max(1, Util.string_to_number(parts[2]) or 2))
end
global.interburbulator.challenge_cell = {x, y}
end
function Interburbulator.on_gui_click(event)
if not (event.element and event.element.valid) then return end
local element = event.element
local player = game.players[event.player_index]
root = gui_element_or_parent(element, Interburbulator.name_interburbulator_gui_root)
if element.parent and element.parent.name == "challenges" then
if element.name == "challenge_random" then
Interburbulator.activate_challenge("random", player)
else
local challenge_index = Util.string_to_number(Util.replace(element.name, "challenge_", ""))
Interburbulator.activate_challenge(challenge_index, player)
end
elseif element.name == mod_prefix .. "-interburbulator-close" then
Interburbulator.gui_close(player)
elseif element.name == mod_prefix .. "-interburbulator-submit" then
Interburbulator.submit(player)
end
end
Event.addListener(defines.events.on_gui_click, Interburbulator.on_gui_click)
function Interburbulator.on_gui_opened(event)
local player = game.players[event.player_index]
if event.entity and event.entity.valid and event.entity.name == mod_prefix.."interburbulator-control" then
player.opened = nil
if player.character and player.character.surface == event.entity.surface and Util.vectors_delta_length(player.character.position, event.entity.position) < 5 then
Interburbulator.gui_open(player)
Interburbulator.update() --Interburbulator.update(player)
else
event.entity.surface.create_entity{
name = "flying-text",
position = event.entity.position,
text = {"space-exploration.out_of_reach"},
render_player_index = player.index,
}
end
end
end
Event.addListener(defines.events.on_gui_opened, Interburbulator.on_gui_opened)
function Interburbulator.on_gui_text_changed(event)
if not (event.element and event.element.valid) then return end
local element = event.element
local player = game.players[event.player_index]
root = gui_element_or_parent(element, Interburbulator.name_interburbulator_gui_root)
if not (root and global.interburbulator) then return end
if element.parent and element.parent.parent and element.parent.parent.name == "attempt" then
-- always allowed
else
if not global.interburbulator.freeplay_unlocked then
Interburbulator.message(player, {"space-exploration.interburbulator_deny_freeplay_"..(game.tick%6+1)})
Interburbulator.gui_update(player)
end
end
end
Event.addListener(defines.events.on_gui_text_changed, Interburbulator.on_gui_text_changed)
function Interburbulator.on_gui_confirmed(event)
if not (event.element and event.element.valid) then return end
local element = event.element
local player = game.players[event.player_index]
root = gui_element_or_parent(element, Interburbulator.name_interburbulator_gui_root)
if not (root and global.interburbulator) then return end
Interburbulator.submit(player, true)
end
Event.addListener(defines.events.on_gui_confirmed, Interburbulator.on_gui_confirmed)
return Interburbulator