--[[-- Gui Module - Science Info - Adds a science info gui that shows production usage and net for the different science packs as well as an eta @gui Science-Info @alias science_info ]] local Gui = require 'expcore.gui' --- @dep expcore.gui local Roles = require 'expcore.roles' --- @dep expcore.gui local Event = require 'utils.event' --- @dep utils.event local config = require 'config.gui.science' --- @dep config.gui.science local Production = require 'modules.control.production' --- @dep modules.control.production local format_time = _C.format_time --- @dep expcore.common local null_time_short = {'science-info.eta-time',format_time(0,{hours=true,minutes=true,seconds=true,time=true,null=true})} local null_time_long = format_time(0,{hours=true,minutes=true,seconds=true,long=true,null=true}) --- Data label that contains the value and the surfix -- @element production_label local production_label = Gui.element(function(_,parent,production_label_data) local name = production_label_data.name local tooltip = production_label_data.tooltip local color = production_label_data.color -- Add an alignment for the number local alignment = Gui.alignment(parent,name) -- Add the main value label local element = alignment.add{ name = 'label', type = 'label', caption = production_label_data.caption, tooltip = tooltip } -- Change the style element.style.font_color = color -- Add the surfix label local surfix_element = parent.add{ name = 'surfix-'..name, type = 'label', caption = {'science-info.unit',production_label_data.surfix}, tooltip = tooltip } -- Change the style local surfix_element_style = surfix_element.style surfix_element_style.font_color = color surfix_element_style.right_margin = 1 -- Return the value label return element end) -- Get the data that is used with the production label local function get_production_label_data(name,tooltip,value,secondary) local data_colour = Production.get_color(config.color_clamp, value, secondary) local surfix, caption = Production.format_number(value) return { name = name, caption = caption, surfix = surfix, tooltip = tooltip, color = data_colour } end -- Updates a prodution label to match the current data local function update_production_label(parent,production_label_data) local name = production_label_data.name local tooltip = production_label_data.tooltip local color = production_label_data.color -- Update the production label local production_label_element = parent[name] and parent[name].label or production_label(parent,production_label_data) production_label_element.caption = production_label_data.caption production_label_element.tooltip = production_label_data.tooltip production_label_element.style.font_color = color -- Update the surfix label local surfix_element = parent['surfix-'..name] surfix_element.caption = {'science-info.unit',production_label_data.surfix} surfix_element.tooltip = tooltip surfix_element.style.font_color = color end --- Adds 4 elements that show the data for a science pack -- @element science_pack_base local science_pack_base = Gui.element(function(_,parent,science_pack_data) local science_pack = science_pack_data.science_pack -- Draw the icon for the science pack local icon_style = science_pack_data.icon_style local pack_icon = parent.add{ name = 'icon-'..science_pack, type = 'sprite-button', sprite = 'item/'..science_pack, tooltip = {'item-name.'..science_pack}, style = icon_style } -- Change the style of the icon local pack_icon_style = pack_icon.style pack_icon.ignored_by_interaction = true pack_icon_style.height = 55 if icon_style == 'slot_button' then pack_icon_style.padding = {0,-2} pack_icon_style.width = 36 end -- Draw the delta flow local delta_flow = parent.add{ name = 'delta-'..science_pack, type = 'frame', style = 'bordered_frame' } delta_flow.style.padding = {0,3} -- Draw the delta flow table local delta_table = delta_flow.add{ name = 'table', type = 'table', column_count = 2 } delta_table.style.padding = 0 -- Draw the production labels update_production_label(delta_table,science_pack_data.positive) update_production_label(delta_table,science_pack_data.negative) update_production_label(parent,science_pack_data.net) -- Return the pack icon return pack_icon end) local function get_science_pack_data(player,science_pack) local force = player.force -- Check that some packs have been made local total = Production.get_production_total(force, science_pack) local minute = Production.get_production(force, science_pack, defines.flow_precision_index.one_minute) if total.made == 0 then return end -- Get the icon style local icon_style = 'slot_button' local flux = Production.get_fluctuations(force, science_pack, defines.flow_precision_index.one_minute) if minute.net > 0 and flux.net > -config.color_flux/2 then icon_style = 'slot_sized_button_green' elseif flux.net < -config.color_flux then icon_style = 'slot_sized_button_red' elseif minute.made > 0 then icon_style = 'yellow_slot_button' end -- Return the pack data return { science_pack = science_pack, icon_style = icon_style, positive = get_production_label_data( 'pos-'..science_pack, {'science-info.pos-tooltip', total.made}, minute.made ), negative = get_production_label_data( 'neg-'..science_pack, {'science-info.neg-tooltip', total.used}, -minute.used ), net = get_production_label_data( 'net-'..science_pack, {'science-info.net-tooltip', total.net}, minute.net, minute.made+minute.used ) } end local function update_science_pack(pack_table,science_pack_data) if not science_pack_data then return end local science_pack = science_pack_data.science_pack pack_table.parent.non_made.visible = false -- Update the icon local pack_icon = pack_table['icon-'..science_pack] or science_pack_base(pack_table,science_pack_data) local icon_style = science_pack_data.icon_style pack_icon.style = icon_style local pack_icon_style = pack_icon.style pack_icon_style.height = 55 if icon_style == 'slot_button' then pack_icon_style.padding = {0,-2} pack_icon_style.width = 36 end -- Update the production labels local delta_table = pack_table['delta-'..science_pack].table update_production_label(delta_table,science_pack_data.positive) update_production_label(delta_table,science_pack_data.negative) update_production_label(pack_table,science_pack_data.net) end --- Gets the data that is used with the eta label local function get_eta_label_data(player) local force = player.force -- If there is no current research then return no research local research = force.current_research if not research then return { research = false } end local limit local progress = force.research_progress local remaining = research.research_unit_count*(1-progress) -- Check for the limiting science pack for _,ingredient in pairs(research.research_unit_ingredients) do local pack_name = ingredient.name local required = ingredient.amount * remaining local time = Production.get_consumsion_eta(force, pack_name, defines.flow_precision_index.one_minute, required) if not limit or limit < time then limit = time end end -- Return the caption and tooltip return limit and limit > 0 and { research = true, caption = format_time(limit,{hours=true,minutes=true,seconds=true,time=true}), tooltip = format_time(limit,{hours=true,minutes=true,seconds=true,long=true}) } or { research = false } end -- Updates the eta label local function update_eta_label(element,eta_label_data) -- If no research selected show null if not eta_label_data.research then element.caption = null_time_short element.tooltip = null_time_long return end -- Update the element element.caption = {'science-info.eta-time',eta_label_data.caption} element.tooltip = eta_label_data.tooltip end --- Main task list container for the left flow -- @element task_list_container local science_info_container = Gui.element(function(event_trigger,parent) local player = Gui.get_player_from_element(parent) -- Draw the internal container local container = Gui.container(parent,event_trigger,200) -- Draw the header Gui.header(container, {'science-info.main-caption'}, {'science-info.main-tooltip'}) -- Draw the scroll table for the tasks local scroll_table = Gui.scroll_table(container,178,4) -- Draw the no packs label local no_packs_label = scroll_table.parent.add{ name = 'non_made', type = 'label', caption = {'science-info.no-packs'} } -- Change the style of the no packs label local no_packs_style = no_packs_label.style no_packs_style.padding = {2,4} no_packs_style.single_line = false no_packs_style.width = 200 -- Add the footer and eta if config.show_eta then -- Draw the footer local footer = Gui.footer(container, {'science-info.eta-caption'}, {'science-info.eta-tooltip'}, true) -- Draw the eta label local eta_label = footer.add{ name = 'label', type = 'label', caption = null_time_short, tooltip = null_time_long, style = 'heading_1_label' } -- Update the eta update_eta_label(eta_label,get_eta_label_data(player)) end -- Add packs which have been made for _,science_pack in ipairs(config) do update_science_pack(scroll_table,get_science_pack_data(player,science_pack)) end -- Return the exteral container return container.parent end) :add_to_left_flow() --- Button on the top flow used to toggle the task list container -- @element toggle_left_element Gui.left_toolbar_button('entity/lab', {'science-info.main-tooltip'}, science_info_container, function(player) return Roles.player_allowed(player,'gui/science-info') end) --- Updates the gui every 1 second Event.on_nth_tick(60,function() local force_pack_data = {} local force_eta_data = {} for _,player in pairs(game.connected_players) do local force_name = player.force.name local frame = Gui.get_left_element(player,science_info_container) local container = frame.container -- Update the science packs local scroll_table = container.scroll.table local pack_data = force_pack_data[force_name] if not pack_data then -- No data in chache so it needs to be generated pack_data = {} force_pack_data[force_name] = pack_data for _,science_pack in ipairs(config) do local next_data = get_science_pack_data(player,science_pack) pack_data[science_pack] = next_data update_science_pack(scroll_table,next_data) end else -- Data found in chache is no need to generate it for _,next_data in ipairs(pack_data) do update_science_pack(scroll_table,next_data) end end -- Update the eta times if not config.show_eta then return end local eta_label = container.footer.alignment.label local eta_data = force_eta_data[force_name] if not eta_data then -- No data in chache so it needs to be generated eta_data = get_eta_label_data(player) force_eta_data[force_name] = eta_data update_eta_label(eta_label,eta_data) else -- Data found in chache is no need to generate it update_eta_label(eta_label,eta_data) end end end)