1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-10 00:43:27 +02:00
ComfyFactorio/maps/pirates/gui/common.lua
2022-05-13 23:35:12 +01:00

531 lines
16 KiB
Lua

local Memory = require 'maps.pirates.memory'
local Common = require 'maps.pirates.common'
local CoreData = require 'maps.pirates.coredata'
-- local Utils = require 'maps.pirates.utils_local'
local Math = require 'maps.pirates.math'
local _inspect = require 'utils.inspect'.inspect
local Crew = require 'maps.pirates.crew'
-- local Progression = require 'maps.pirates.progression'
-- local Structures = require 'maps.pirates.structures.structures'
local Shop = require 'maps.pirates.shop.shop'
local Boats = require 'maps.pirates.structures.boats.boats'
local Surfaces = require 'maps.pirates.surfaces.surfaces'
local Public = {}
Public.bold_font_color = {255, 230, 192}
Public.default_font_color = {1, 1, 1}
Public.section_header_font_color = {r=0.40, g=0.80, b=0.60}
Public.subsection_header_font_color = {229, 255, 242}
Public.friendly_font_color = {240, 200, 255}
Public.sufficient_font_color = {66, 220, 124}
Public.insufficient_font_color = {1, 0.62, 0.19}
Public.achieved_font_color = {227, 250, 192}
Public.fuel_color_1 = {r=255, g=255, b=255}
Public.fuel_color_2 = {r=255, g=0, b=60}
Public.rage_font_color_1 = {r=1, g=1, b=1}
Public.rage_font_color_2 = {r=1, g=0.5, b=0.1}
Public.rage_font_color_3 = {r=1, g=0.1, b=0.05}
Public.default_window_positions = {
runs = {x = 10, y = 48},
crew = {x = 40, y = 48},
progress = {x = 250, y = 48},
fuel = {x = 468, y = 48},
minimap = {x = 10, y = 48},
color = {x = 160, y = 96},
}
function Public.new_window(player, name)
local global_memory = Memory.get_global_memory()
local gui_memory = global_memory.player_gui_memories[player.index]
local flow
flow = player.gui.screen.add{
type = 'frame',
name = name .. '_piratewindow',
direction = 'vertical'
}
if gui_memory and gui_memory[name] and gui_memory[name].position then
flow.location = gui_memory[name].position
else
flow.location = Public.default_window_positions[name]
end
flow.style = 'map_details_frame'
flow.style.minimal_width = 210
flow.style.natural_width = 210
flow.style.maximal_width = 270
flow.style.minimal_height = 80
flow.style.natural_height = 80
flow.style.maximal_height = 700
flow.style.padding = 10
return flow
end
function Public.update_gui_memory(player, namespace, key, value)
local global_memory = Memory.get_global_memory()
if not global_memory.player_gui_memories[player.index] then
global_memory.player_gui_memories[player.index] = {}
end
local gui_memory = global_memory.player_gui_memories[player.index]
if not gui_memory[namespace] then
gui_memory[namespace] = {}
end
gui_memory[namespace][key] = value
end
function Public.flow_add_floating_sprite_button(flow1, button_name, width)
width = width or 40
local flow2, flow3
flow2 = flow1.add({
name = button_name .. '_frame',
type = 'frame',
})
flow2.style.height = 40
flow2.style.margin = 0
flow2.style.left_padding = -4
flow2.style.top_padding = -4
flow2.style.right_margin = -2
flow2.style.width = width
flow3 = flow2.add({
name = button_name,
type = 'sprite-button',
})
flow3.style.height = 40
flow3.style.width = width
-- flow3.style.padding = -4
return flow3
end
function Public.flow_add_floating_button(flow1, button_name)
local flow2, flow3
flow2 = flow1.add({
name = button_name .. '_flow_1',
type = 'flow',
direction = 'vertical',
})
flow2.style.height = 40
-- flow2.style.left_padding = 4
-- flow2.style.top_padding = 0
-- flow2.style.right_margin = -2
flow2.style.natural_width = 40
flow3 = flow2.add({
name = button_name,
type = 'button',
})
flow3.style = 'dark_rounded_button'
-- flow3.style.minimal_width = 60
-- flow3.style.natural_width = 60
flow3.style.minimal_height = 40
flow3.style.maximal_height = 40
flow3.style.left_padding = 10
flow3.style.right_padding = 4
flow3.style.top_padding = 3
-- flow3.style.padding = -4
flow3.style.natural_width = 40
flow3.style.horizontally_stretchable = true
flow3 = flow2.add({
name = button_name .. '_flow_2',
type = 'flow',
})
flow3.style.natural_width = 20
flow3.style.top_margin = -37
flow3.style.left_margin = 10
flow3.style.right_margin = 9
flow3.ignored_by_interaction=true
return flow3
end
function Public.flow_add_shop_item(flow, name)
local flow2, flow3
local shop_data_1 = Shop.Captains.main_shop_data_1
local shop_data_2 = Shop.Captains.main_shop_data_2
local trade_data = shop_data_1[name] or shop_data_2[name]
if not trade_data then return end
flow2 = flow.add({
name = name,
type = 'flow',
direction = 'horizontal',
})
flow2.style.top_margin = 3
flow2.style.horizontal_align = 'center'
flow2.style.vertical_align = 'center'
flow2.tooltip = trade_data.tooltip
for k, v in pairs(trade_data.what_you_get_sprite_buttons) do
flow3 = flow2.add({
type = 'sprite-button',
name = k,
sprite = k,
enabled = false,
})
flow3.style.minimal_height = 40
flow3.style.maximal_height = 40
if v == false then
flow3.number = nil
else
flow3.number = v
end
flow3.tooltip = trade_data.tooltip
end
flow3 = flow2.add({
type = 'label',
name = 'for',
caption = 'for'
})
flow3.style.font = 'default-large'
flow3.style.font_color = Public.default_font_color
flow3.tooltip = trade_data.tooltip
for k, _ in pairs(trade_data.base_cost) do
flow3 = flow2.add({
name = 'cost_' .. k,
type = 'sprite-button',
enabled = false,
})
flow3.style.minimal_height = 40
flow3.style.maximal_height = 40
flow3.tooltip = trade_data.tooltip
if k == 'fuel' then
flow3.sprite = 'item/coal'
elseif k == 'coins' then
flow3.sprite = 'item/coin'
elseif k == 'iron_plates' then
flow3.sprite = 'item/iron-plate'
elseif k == 'copper_plates' then
flow3.sprite = 'item/copper-plate'
end
end
flow3 = flow2.add({
name = 'spacing',
type = 'flow',
direction = 'horizontal',
})
flow3.style.horizontally_stretchable = true
flow3 = flow2.add({
type = 'sprite-button',
name = 'buy_button',
caption = 'Buy'
})
flow3.style.font = 'default-large'
flow3.style.font_color = Public.default_font_color
flow3.style.height = 32
flow3.style.width = 50
flow3.style.padding = 0
flow3.style.margin = 0
return flow2
end
function Public.flow_add_section(flow, name, caption)
local flow2, flow3
flow2 = flow.add({
name = name,
type = 'flow',
direction = 'vertical',
})
flow2.style.bottom_margin = 5
flow3 = flow2.add({
type = 'label',
name = 'header',
caption = caption
})
flow3.style.font = 'heading-2'
flow3.style.font_color = Public.section_header_font_color
flow3.style.maximal_width = 300
-- flow3.style.maximal_width = 220
-- flow3.style.single_line = false
flow3 = flow2.add({
name = 'body',
type = 'flow',
direction = 'vertical',
})
flow3.style.left_margin = 5
return flow3
end
function Public.flow_add_subpanel(flow, name)
local flow2
flow2 = flow.add({
name = name,
type = 'frame',
direction = 'vertical',
})
flow2.style = 'subpanel_frame'
flow2.style.natural_width = 100
flow2.style.top_padding = -2
flow2.style.top_margin = -8
return flow2
end
function Public.flow_add_close_button(flow, close_button_name)
local flow2, flow3, flow4
flow2 = flow.add({
name = 'close_button_flow',
type = 'flow',
direction = 'vertical',
})
flow2.style.top_margin = -3
flow2.style.bottom_margin = -3
flow3 = flow2.add{type="flow", name='hflow', direction="horizontal"}
flow3.style.vertical_align = 'center'
flow4 = flow3.add{type="flow", name='spacing', direction="horizontal"}
flow4.style.horizontally_stretchable = true
flow4 = flow3.add({
type = 'button',
name = close_button_name,
caption = 'Close',
})
flow4.style = 'back_button'
flow4.style.minimal_width = 90
flow4.style.font = 'default-bold'
flow4.style.height = 28
flow4.style.horizontal_align = 'center'
return flow3
end
function Public.crew_overall_state_bools(player_index)
local global_memory = Memory.get_global_memory()
local memory = Memory.get_crew_memory()
--*** PLAYER STATUS ***--
local ret = {
adventuring = false,
spectating = false,
endorsing = false,
proposing = false,
sloops_full = false,
needs_more_capacity = false,
crew_count_capped = false,
needs_more_endorsers = false,
leaving = false,
proposal_can_launch = false,
}
if memory.crewstatus == Crew.enum.ADVENTURING then
for _, playerindex in pairs(memory.crewplayerindices) do
if player_index == playerindex then ret.adventuring = true end
end
for _, playerindex in pairs(memory.spectatorplayerindices) do
if player_index == playerindex then ret.spectating = true end
end
end
if memory.crewstatus == nil then
for _, crewid in pairs(global_memory.crew_active_ids) do
if global_memory.crew_memories[crewid].crewstatus == Crew.enum.LEAVING_INITIAL_DOCK then
for _, endorser_index in pairs(global_memory.crew_memories[crewid].original_proposal.endorserindices) do
if endorser_index == player_index then ret.leaving = true end
end
end
end
for _, proposal in pairs(global_memory.crewproposals) do
if #proposal.endorserindices > 0 and proposal.endorserindices[1] == player_index then
ret.proposing = true
if #global_memory.crew_active_ids >= 3 then
ret.sloops_full = true
elseif #global_memory.crew_active_ids >= global_memory.active_crews_cap then
ret.crew_count_capped = true
elseif global_memory.active_crews_cap > 1 and #global_memory.crew_active_ids == (global_memory.active_crews_cap - 1) and not ((global_memory.crew_memories[1] and global_memory.crew_memories[1].capacity >= Common.minimum_run_capacity_to_enforce_space_for) or (global_memory.crew_memories[2] and global_memory.crew_memories[2].capacity >= Common.minimum_run_capacity_to_enforce_space_for) or (global_memory.crew_memories[3] and global_memory.crew_memories[3].capacity >= Common.minimum_run_capacity_to_enforce_space_for)) and not (CoreData.capacity_options[proposal.capacity_option].value >= Common.minimum_run_capacity_to_enforce_space_for) then
ret.needs_more_capacity = true
elseif proposal.endorserindices and #global_memory.crew_active_ids > 0 and #proposal.endorserindices < Math.min(4, Math.ceil((#game.connected_players or 0)/5)) then
ret.needs_more_endorsers = true
end
if (not (ret.sloops_full or ret.needs_more_capacity or ret.needs_more_endorsers or ret.crew_count_capped)) then
ret.proposal_can_launch = true
end
end
for _, i in pairs(proposal.endorserindices) do
if player_index == i then ret.endorsing = true end
end
end
end
return ret
end
function Public.player_and_crew_state_bools(player)
local memory = Memory.get_crew_memory()
-- if memory.player_and_crew_state_bools_memoized and memory.player_and_crew_state_bools_memoized.tick > game.tick - 30 then -- auto-memoize and only update every half-second
-- return memory.player_and_crew_state_bools_memoized.ret
-- else
local destination = Common.current_destination()
local dynamic_data = destination.dynamic_data --assumes this always exists
local in_crowsnest_bool, in_hold_bool, in_cabin_bool, onmap_bool, eta_bool, approaching_bool, retreating_bool, atsea_sailing_bool, landed_bool, quest_bool, silo_bool, charged_bool, launched_bool, captain_bool, atsea_loading_bool, character_on_deck_bool, on_deck_standing_near_loco_bool, on_deck_standing_near_cabin_bool, on_deck_standing_near_crowsnest_bool, cost_bool, cost_includes_rocket_launch_bool, approaching_dock_bool, leaving_dock_bool, leave_anytime_bool
captain_bool = Common.is_captain(player)
in_crowsnest_bool = string.sub(player.surface.name, 9, 17) == 'Crowsnest'
in_hold_bool = string.sub(player.surface.name, 9, 12) == 'Hold'
in_cabin_bool = string.sub(player.surface.name, 9, 13) == 'Cabin'
onmap_bool = destination.surface_name and (player.surface.name == destination.surface_name or (
memory.boat and memory.boat.surface_name == destination.surface_name and (in_crowsnest_bool or in_hold_bool or in_cabin_bool)
))
if destination then
eta_bool = dynamic_data.time_remaining and dynamic_data.time_remaining > 0 and onmap_bool
approaching_bool = memory.boat and memory.boat.state == Boats.enum_state.APPROACHING and onmap_bool
retreating_bool = memory.boat and memory.boat.state == Boats.enum_state.RETREATING and onmap_bool
-- approaching_bool = memory.boat and memory.boat.state == Boats.enum_state.APPROACHING
atsea_sailing_bool = memory.boat and memory.boat.state == Boats.enum_state.ATSEA_SAILING
landed_bool = memory.boat and memory.boat.state == Boats.enum_state.LANDED
quest_bool = (dynamic_data.quest_type ~= nil) and onmap_bool
charged_bool = dynamic_data.silocharged
silo_bool = dynamic_data.rocketsilos and onmap_bool and ((dynamic_data.rocketsilos[1] and dynamic_data.rocketsilos[1].valid) or charged_bool)
launched_bool = dynamic_data.rocketlaunched
cost_bool = destination.static_params.base_cost_to_undock and (not atsea_sailing_bool) and (not retreating_bool)
cost_includes_rocket_launch_bool = cost_bool and destination.static_params.base_cost_to_undock['launch_rocket']
leave_anytime_bool = (landed_bool and not (eta_bool or cost_bool))
end
if memory.boat then
atsea_loading_bool = memory.boat.state == Boats.enum_state.ATSEA_LOADING_MAP and memory.loadingticks
character_on_deck_bool = player.character and player.character.position and player.surface.name and player.surface.name == memory.boat.surface_name
if character_on_deck_bool then
local BoatData = Boats.get_scope(memory.boat).Data
on_deck_standing_near_loco_bool = Math.distance(player.character.position, Math.vector_sum(memory.boat.position, BoatData.loco_pos)) < 2.5
on_deck_standing_near_cabin_bool = Math.distance(player.character.position, Math.vector_sum(memory.boat.position, BoatData.cabin_car)) < 2.0
on_deck_standing_near_crowsnest_bool = Math.distance(player.character.position, Math.vector_sum(memory.boat.position, BoatData.crowsnest_center)) < 2.5
end
approaching_dock_bool = destination.type == Surfaces.enum.DOCK and memory.boat.state == Boats.enum_state.APPROACHING
leaving_dock_bool = destination.type == Surfaces.enum.DOCK and memory.boat.state == Boats.enum_state.LEAVING_DOCK
end
local ret = {
in_crowsnest_bool = in_crowsnest_bool,
in_hold_bool = in_hold_bool,
in_cabin_bool = in_cabin_bool,
-- onmap_bool = onmap_bool,
eta_bool = eta_bool,
approaching_bool = approaching_bool,
retreating_bool = retreating_bool,
atsea_sailing_bool = atsea_sailing_bool,
-- landed_bool = landed_bool,
quest_bool = quest_bool,
silo_bool = silo_bool,
charged_bool = charged_bool,
launched_bool = launched_bool,
captain_bool = captain_bool,
atsea_loading_bool = atsea_loading_bool,
-- character_on_deck_bool = character_on_deck_bool,
on_deck_standing_near_loco_bool = on_deck_standing_near_loco_bool,
on_deck_standing_near_cabin_bool = on_deck_standing_near_cabin_bool,
on_deck_standing_near_crowsnest_bool = on_deck_standing_near_crowsnest_bool,
cost_bool = cost_bool,
cost_includes_rocket_launch_bool = cost_includes_rocket_launch_bool,
approaching_dock_bool = approaching_dock_bool,
leaving_dock_bool = leaving_dock_bool,
leave_anytime_bool = leave_anytime_bool
}
-- memory.player_and_crew_state_bools_memoized = {ret = ret, tick = game.tick}
return ret
-- end
end
function Public.update_listbox(listbox, table)
-- pass a table of strings of the form {'locale', unique_id, ...}
-- remove any that shouldn't be there
local marked_for_removal = {}
for index, item in pairs(listbox.items) do
local exists = false
for _, i in pairs(table) do
if tostring(i[2]) == item[2] then
exists = true
end
end
if exists == false then
marked_for_removal[#marked_for_removal + 1] = index
end
end
for i = #marked_for_removal, 1, -1 do
listbox.remove_item(marked_for_removal[i])
end
local indexalreadyat
for _, i in pairs(table) do
local contained = false
for index, item in pairs(listbox.items) do
if tostring(i[2]) == item[2] then
contained = true
indexalreadyat = index
end
end
if contained then
listbox.set_item(indexalreadyat, i)
else
listbox.add_item(i)
end
end
end
return Public