mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-29 04:06:39 +09:00
@@ -9,6 +9,6 @@ local Commands = require 'expcore.commands' --- @dep expcore.commands
|
||||
--- Opens the debug pannel for viewing tables.
|
||||
-- @command debug
|
||||
Commands.new_command('debug','Opens the debug pannel for viewing tables.')
|
||||
:register(function(player,raw)
|
||||
:register(function(player)
|
||||
DebugView.open_dubug(player)
|
||||
end)
|
||||
@@ -89,8 +89,8 @@ Tasks.remove_task(task_id)
|
||||
function Tasks.remove_task(task_id)
|
||||
local task = Store.get(task_store,task_id)
|
||||
local force_name = task.force_name
|
||||
Store.clear(task_store,task_id)
|
||||
table.remove_element(force_tasks[force_name],task_id)
|
||||
Store.clear(task_store,task_id)
|
||||
end
|
||||
|
||||
--[[-- Update the message and last edited information for a task
|
||||
|
||||
@@ -150,7 +150,7 @@ function Warps.make_warp_area(warp_id)
|
||||
local position = warp.position
|
||||
local posx = position.x
|
||||
local posy = position.y
|
||||
local radius = config.activation_range
|
||||
local radius = config.standard_proximity_radius
|
||||
local radius2 = radius^2
|
||||
|
||||
-- Get the tile that is being replaced, store.update not needed as we dont want it to trigger
|
||||
@@ -203,7 +203,7 @@ function Warps.remove_warp_area(warp_id)
|
||||
local warp = Store.get(warp_store,warp_id)
|
||||
local position = warp.position
|
||||
local surface = warp.surface
|
||||
local radius = config.activation_range
|
||||
local radius = config.standard_proximity_radius
|
||||
local radius2 = radius^2
|
||||
|
||||
-- Check that a warp area was created previously
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local table = require 'utils.table' --- @dep utils.table
|
||||
local Gui = require 'utils.gui' --- @dep utils.gui
|
||||
local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model
|
||||
local Event = require 'utils.event'
|
||||
local table = require 'utils.table'
|
||||
local Gui = require 'utils.gui'
|
||||
local Model = require 'modules.gui.debug.model'
|
||||
|
||||
local format = string.format
|
||||
local insert = table.insert
|
||||
@@ -19,13 +19,16 @@ local name_lookup = {}
|
||||
|
||||
-- GUI names
|
||||
local checkbox_name = Gui.uid_name()
|
||||
local filter_name = Gui.uid_name()
|
||||
local clear_filter_name = Gui.uid_name()
|
||||
|
||||
-- global tables
|
||||
local enabled = {}
|
||||
local last_events = {}
|
||||
global.debug_event_view = {
|
||||
enabled = enabled,
|
||||
last_events = last_events
|
||||
last_events = last_events,
|
||||
filter = ''
|
||||
}
|
||||
|
||||
function Public.on_open_debug()
|
||||
@@ -90,24 +93,73 @@ end
|
||||
|
||||
table.sort(grid_builder)
|
||||
|
||||
function Public.show(container)
|
||||
local main_frame_flow = container.add({type = 'flow', direction = 'vertical'})
|
||||
local scroll_pane = main_frame_flow.add({type = 'scroll-pane'})
|
||||
local gui_table = scroll_pane.add({type = 'table', column_count = 3, draw_horizontal_lines = true})
|
||||
|
||||
local function redraw_event_table(gui_table, filter)
|
||||
for _, event_name in pairs(grid_builder) do
|
||||
local index = events[event_name]
|
||||
gui_table.add({type = 'flow'}).add {
|
||||
name = checkbox_name,
|
||||
type = 'checkbox',
|
||||
state = enabled[index] or false,
|
||||
caption = event_name
|
||||
}
|
||||
if filter == '' or event_name:find(filter) then
|
||||
local index = events[event_name]
|
||||
gui_table.add({type = 'flow'}).add {
|
||||
name = checkbox_name,
|
||||
type = 'checkbox',
|
||||
state = enabled[index] or false,
|
||||
caption = event_name
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.show(container)
|
||||
local filter = global.debug_event_view.filter
|
||||
|
||||
local main_frame_flow = container.add({type = 'flow', direction = 'vertical'})
|
||||
|
||||
local filter_flow = main_frame_flow.add({type = 'flow', direction = 'horizontal'})
|
||||
filter_flow.add({type = 'label', caption = 'filter'})
|
||||
local filter_textfield = filter_flow.add({type = 'textfield', name = filter_name, text = filter})
|
||||
local clear_button = filter_flow.add({type = 'button', name = clear_filter_name, caption = 'clear'})
|
||||
|
||||
local scroll_pane = main_frame_flow.add({type = 'scroll-pane'})
|
||||
local gui_table = scroll_pane.add({type = 'table', column_count = 3, draw_horizontal_lines = true})
|
||||
|
||||
Gui.set_data(filter_textfield, gui_table)
|
||||
Gui.set_data(clear_button, {gui_table = gui_table, filter_textfield = filter_textfield})
|
||||
|
||||
redraw_event_table(gui_table, filter)
|
||||
end
|
||||
|
||||
Gui.on_checked_state_changed(checkbox_name, on_gui_checked_state_changed)
|
||||
|
||||
Gui.on_text_changed(
|
||||
filter_name,
|
||||
function(event)
|
||||
local element = event.element
|
||||
local gui_table = Gui.get_data(element)
|
||||
|
||||
local filter = element.text:gsub(' ', '_')
|
||||
|
||||
global.debug_event_view.filter = filter
|
||||
element.text = filter
|
||||
|
||||
gui_table.clear()
|
||||
redraw_event_table(gui_table, filter)
|
||||
end
|
||||
)
|
||||
|
||||
Gui.on_click(
|
||||
clear_filter_name,
|
||||
function(event)
|
||||
local element = event.element
|
||||
local data = Gui.get_data(element)
|
||||
local filter_textfield = data.filter_textfield
|
||||
local gui_table = data.gui_table
|
||||
|
||||
filter_textfield.text = ''
|
||||
global.debug_event_view.filter = ''
|
||||
|
||||
gui_table.clear()
|
||||
redraw_event_table(gui_table, '')
|
||||
end
|
||||
)
|
||||
|
||||
-- Event registers (TODO: turn to removable hooks.. maybe)
|
||||
for name, id in pairs(events) do
|
||||
name_lookup[id] = name
|
||||
|
||||
128
modules/gui/debug/expcore_gui_view.lua
Normal file
128
modules/gui/debug/expcore_gui_view.lua
Normal file
@@ -0,0 +1,128 @@
|
||||
local Gui = require 'utils.gui' --- @dep utils.gui
|
||||
local ExpGui = require 'expcore.gui' --- @dep utils.global
|
||||
local Color = require 'resources.color_presets' --- @dep resources.color_presets
|
||||
local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model
|
||||
|
||||
local dump = Model.dump
|
||||
local dump_text = Model.dump_text
|
||||
local concat = table.concat
|
||||
|
||||
local Public = {}
|
||||
|
||||
local header_name = Gui.uid_name()
|
||||
local left_panel_name = Gui.uid_name()
|
||||
local right_panel_name = Gui.uid_name()
|
||||
local input_text_box_name = Gui.uid_name()
|
||||
local refresh_name = Gui.uid_name()
|
||||
|
||||
Public.name = 'Elements'
|
||||
|
||||
function Public.show(container)
|
||||
local main_flow = container.add {type = 'flow', direction = 'horizontal'}
|
||||
|
||||
local left_panel = main_flow.add {type = 'scroll-pane', name = left_panel_name}
|
||||
local left_panel_style = left_panel.style
|
||||
left_panel_style.width = 300
|
||||
|
||||
for element_id, file_path in pairs(ExpGui.file_paths) do
|
||||
local header = left_panel.add({type = 'flow'}).add {type = 'label', name = header_name, caption = element_id..' - '..file_path}
|
||||
Gui.set_data(header, element_id)
|
||||
end
|
||||
|
||||
local right_flow = main_flow.add {type = 'flow', direction = 'vertical'}
|
||||
|
||||
local right_top_flow = right_flow.add {type = 'flow', direction = 'horizontal'}
|
||||
|
||||
local input_text_box = right_top_flow.add {type = 'text-box', name = input_text_box_name}
|
||||
local input_text_box_style = input_text_box.style
|
||||
input_text_box_style.horizontally_stretchable = true
|
||||
input_text_box_style.height = 32
|
||||
input_text_box_style.maximal_width = 1000
|
||||
|
||||
local refresh_button =
|
||||
right_top_flow.add {type = 'sprite-button', name = refresh_name, sprite = 'utility/reset', tooltip = 'refresh'}
|
||||
local refresh_button_style = refresh_button.style
|
||||
refresh_button_style.width = 32
|
||||
refresh_button_style.height = 32
|
||||
|
||||
local right_panel = right_flow.add {type = 'text-box', name = right_panel_name}
|
||||
right_panel.read_only = true
|
||||
right_panel.selectable = true
|
||||
|
||||
local right_panel_style = right_panel.style
|
||||
right_panel_style.vertically_stretchable = true
|
||||
right_panel_style.horizontally_stretchable = true
|
||||
right_panel_style.maximal_width = 1000
|
||||
right_panel_style.maximal_height = 1000
|
||||
|
||||
local data = {
|
||||
right_panel = right_panel,
|
||||
input_text_box = input_text_box,
|
||||
selected_header = nil
|
||||
}
|
||||
|
||||
Gui.set_data(input_text_box, data)
|
||||
Gui.set_data(left_panel, data)
|
||||
Gui.set_data(refresh_button, data)
|
||||
end
|
||||
|
||||
Gui.on_click(
|
||||
header_name,
|
||||
function(event)
|
||||
local element = event.element
|
||||
local element_id = Gui.get_data(element)
|
||||
|
||||
local left_panel = element.parent.parent
|
||||
local data = Gui.get_data(left_panel)
|
||||
local right_panel = data.right_panel
|
||||
local selected_header = data.selected_header
|
||||
local input_text_box = data.input_text_box
|
||||
|
||||
if selected_header then
|
||||
selected_header.style.font_color = Color.white
|
||||
end
|
||||
|
||||
element.style.font_color = Color.orange
|
||||
data.selected_header = element
|
||||
|
||||
input_text_box.text = concat {'Gui.defines[', element_id, ']'}
|
||||
input_text_box.style.font_color = Color.black
|
||||
|
||||
local content = dump(ExpGui.debug_info[element_id]) or 'nil'
|
||||
right_panel.text = content
|
||||
end
|
||||
)
|
||||
|
||||
local function update_dump(text_input, data, player)
|
||||
local suc, ouput = dump_text(text_input.text, player)
|
||||
if not suc then
|
||||
text_input.style.font_color = Color.red
|
||||
else
|
||||
text_input.style.font_color = Color.black
|
||||
data.right_panel.text = ouput
|
||||
end
|
||||
end
|
||||
|
||||
Gui.on_text_changed(
|
||||
input_text_box_name,
|
||||
function(event)
|
||||
local element = event.element
|
||||
local data = Gui.get_data(element)
|
||||
|
||||
update_dump(element, data, event.player)
|
||||
end
|
||||
)
|
||||
|
||||
Gui.on_click(
|
||||
refresh_name,
|
||||
function(event)
|
||||
local element = event.element
|
||||
local data = Gui.get_data(element)
|
||||
|
||||
local input_text_box = data.input_text_box
|
||||
|
||||
update_dump(input_text_box, data, event.player)
|
||||
end
|
||||
)
|
||||
|
||||
return Public
|
||||
@@ -24,8 +24,8 @@ function Public.show(container)
|
||||
local left_panel_style = left_panel.style
|
||||
left_panel_style.width = 300
|
||||
|
||||
for store_id, token_name in pairs(Store.file_paths) do
|
||||
local header = left_panel.add({type = 'flow'}).add {type = 'label', name = header_name, caption = store_id..' - '..token_name}
|
||||
for store_id, file_path in pairs(Store.file_paths) do
|
||||
local header = left_panel.add({type = 'flow'}).add {type = 'label', name = header_name, caption = store_id..' - '..file_path}
|
||||
Gui.set_data(header, store_id)
|
||||
end
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ local Public = {}
|
||||
local pages = {
|
||||
require 'modules.gui.debug.redmew_global_view',
|
||||
require 'modules.gui.debug.expcore_store_view',
|
||||
require 'modules.gui.debug.expcore_gui_view',
|
||||
require 'modules.gui.debug.global_view',
|
||||
require 'modules.gui.debug.package_view',
|
||||
require 'modules.gui.debug._g_view',
|
||||
@@ -31,7 +32,7 @@ function Public.open_dubug(player)
|
||||
return
|
||||
end
|
||||
|
||||
frame = center.add {type = 'frame', name = main_frame_name, caption = 'Debuggertron 3001', direction = 'vertical'}
|
||||
frame = center.add {type = 'frame', name = main_frame_name, caption = 'Debuggertron 3002', direction = 'vertical'}
|
||||
local frame_style = frame.style
|
||||
frame_style.height = 600
|
||||
frame_style.width = 900
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
--[[-- Gui Module - Player List
|
||||
- Adds a player list to show names and play time; also includes action buttons which can apply to players
|
||||
- Adds a player list to show names and play time; also includes action buttons which can preform actions to players
|
||||
@gui Player-List
|
||||
@alias player_list
|
||||
]]
|
||||
@@ -26,42 +26,21 @@ end)
|
||||
-- Set the config to use these stores
|
||||
config.set_store_uids(selected_player_store,selected_action_store)
|
||||
|
||||
--- Used to open the map on a player or toggle the settings
|
||||
local zoom_to_map_name = Gui.uid_name()
|
||||
Gui.on_click(zoom_to_map_name,function(event)
|
||||
local selected_player_name = event.element.caption
|
||||
local selected_player = Game.get_player_from_any(selected_player_name)
|
||||
if event.button == defines.mouse_button_type.left then
|
||||
-- LMB will open the map to the selected player
|
||||
local position = selected_player.position
|
||||
event.player.zoom_to_world(position,1.75)
|
||||
else
|
||||
-- RMB will toggle the settings
|
||||
local player = event.player
|
||||
local old_selected_player_name = Store.get(selected_player_store,player)
|
||||
if selected_player_name == old_selected_player_name then
|
||||
Store.clear(selected_player_store,player)
|
||||
else
|
||||
Store.set(selected_player_store,player,selected_player_name)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
--- Button used to open the action bar
|
||||
-- @element open_action_bar
|
||||
local open_action_bar =
|
||||
Gui.new_button()
|
||||
:set_sprites('utility/expand_dots_white')
|
||||
:set_tooltip{'player-list.open-action-bar'}
|
||||
:set_embedded_flow(function(element,selected_player_name)
|
||||
return selected_player_name
|
||||
end)
|
||||
:set_style('frame_button',function(style)
|
||||
Gui.set_padding_style(style,-2,-2,-2,-2)
|
||||
style.width = 8
|
||||
style.height = 14
|
||||
end)
|
||||
:on_click(function(player,element)
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/expand_dots_white',
|
||||
tooltip = {'player-list.open-action-bar'},
|
||||
style = 'frame_button'
|
||||
}
|
||||
:style{
|
||||
padding = -2,
|
||||
width = 8,
|
||||
height = 14
|
||||
}
|
||||
:on_click(function(player,element,_)
|
||||
local selected_player_name = element.parent.name
|
||||
local old_selected_player_name = Store.get(selected_player_store,player)
|
||||
if selected_player_name == old_selected_player_name then
|
||||
@@ -74,15 +53,14 @@ end)
|
||||
--- Button used to close the action bar
|
||||
-- @element close_action_bar
|
||||
local close_action_bar =
|
||||
Gui.new_button()
|
||||
:set_sprites('utility/close_black','utility/close_white')
|
||||
:set_tooltip{'player-list.close-action-bar'}
|
||||
:set_style('tool_button',function(style)
|
||||
Gui.set_padding_style(style,-1,-1,-1,-1)
|
||||
style.height = 28
|
||||
style.width = 28
|
||||
end)
|
||||
:on_click(function(player,element)
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/close_black',
|
||||
tooltip = {'player-list.close-action-bar'},
|
||||
style = 'shortcut_bar_button_red'
|
||||
}
|
||||
:style(Gui.sprite_style(30,-1,{ top_margin = -1, right_margin = -1 }))
|
||||
:on_click(function(player,_)
|
||||
Store.clear(selected_player_store,player)
|
||||
Store.clear(selected_action_store,player)
|
||||
end)
|
||||
@@ -90,14 +68,13 @@ end)
|
||||
--- Button used to confirm a reason
|
||||
-- @element reason_confirm
|
||||
local reason_confirm =
|
||||
Gui.new_button()
|
||||
:set_sprites('utility/confirm_slot')
|
||||
:set_tooltip{'player-list.reason-confirm'}
|
||||
:set_style('tool_button',function(style)
|
||||
Gui.set_padding_style(style,-1,-1,-1,-1)
|
||||
style.height = 28
|
||||
style.width = 28
|
||||
end)
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/confirm_slot',
|
||||
tooltip = {'player-list.reason-confirm'},
|
||||
style = 'shortcut_bar_button_green'
|
||||
}
|
||||
:style(Gui.sprite_style(30,-1,{ left_margin = -2, right_margin = -1 }))
|
||||
:on_click(function(player,element)
|
||||
local reason = element.parent.entry.text or 'Non Given'
|
||||
local action_name = Store.get(selected_action_store,player)
|
||||
@@ -108,109 +85,97 @@ end)
|
||||
element.parent.entry.text = ''
|
||||
end)
|
||||
|
||||
--[[ Creates the main gui areas for the player list
|
||||
element
|
||||
> container
|
||||
>> scroll
|
||||
>>> table
|
||||
>> action_bar
|
||||
]]
|
||||
local function generate_container(player,element)
|
||||
Gui.set_padding(element,2,2,2,2)
|
||||
element.style.minimal_width = 200
|
||||
--- Set of elements that are used to make up a row of the player table
|
||||
-- @element add_player_base
|
||||
local add_player_base =
|
||||
Gui.element(function(event_trigger,parent,player_data)
|
||||
-- Add the button to open the action bar
|
||||
local toggle_action_bar_flow = parent.add{ type = 'flow', name = player_data.name }
|
||||
open_action_bar(toggle_action_bar_flow)
|
||||
|
||||
-- main container which contains the other elements
|
||||
local container =
|
||||
element.add{
|
||||
name='container',
|
||||
type='frame',
|
||||
direction='vertical',
|
||||
style='window_content_frame_packed'
|
||||
-- Add the player name
|
||||
local player_name_flow = parent.add{ type = 'flow', 'player-name-'..player_data.index }
|
||||
local player_name = player_name_flow.add{
|
||||
type = 'label',
|
||||
name = event_trigger,
|
||||
caption = player_data.name,
|
||||
tooltip = {'player-list.open-map',player_data.name,player_data.tag,player_data.role_name}
|
||||
}
|
||||
Gui.set_padding(container)
|
||||
player_name.style.padding = {0,2,0,0}
|
||||
player_name.style.font_color = player_data.chat_color
|
||||
|
||||
-- 3 wide table to contain: action button, player name, and play time
|
||||
local list_table = Gui.create_scroll_table(container,3,188)
|
||||
|
||||
-- action bar which contains the different action buttons
|
||||
local action_bar =
|
||||
container.add{
|
||||
name='action_bar',
|
||||
type='frame',
|
||||
style='subfooter_frame'
|
||||
-- Add the time played label
|
||||
local alignment = Gui.alignment(parent,'player-time-'..player_data.index)
|
||||
local time_label = alignment.add{
|
||||
name = 'label',
|
||||
type = 'label',
|
||||
caption = player_data.caption,
|
||||
tooltip = player_data.tooltip
|
||||
}
|
||||
Gui.set_padding(action_bar,1,1,3,3)
|
||||
action_bar.style.horizontally_stretchable = true
|
||||
action_bar.style.height = 35
|
||||
time_label.style.padding = 0
|
||||
|
||||
-- reason bar which contains the reason text field and confirm button
|
||||
local reason_bar =
|
||||
container.add{
|
||||
name='reason_bar',
|
||||
type='frame',
|
||||
style='subfooter_frame'
|
||||
}
|
||||
Gui.set_padding(reason_bar,-1,-1,3,3)
|
||||
reason_bar.style.horizontally_stretchable = true
|
||||
reason_bar.style.height = 35
|
||||
local action_name = Store.get(selected_action_store,player)
|
||||
reason_bar.visible = action_name ~= nil
|
||||
return time_label
|
||||
end)
|
||||
:on_click(function(player,element,event)
|
||||
local selected_player_name = element.caption
|
||||
local selected_player = Game.get_player_from_any(selected_player_name)
|
||||
if event.button == defines.mouse_button_type.left then
|
||||
-- LMB will open the map to the selected player
|
||||
local position = selected_player.position
|
||||
event.player.zoom_to_world(position,1.75)
|
||||
else
|
||||
-- RMB will toggle the settings
|
||||
local old_selected_player_name = Store.get(selected_player_store,player)
|
||||
if selected_player_name == old_selected_player_name then
|
||||
Store.clear(selected_player_store,player)
|
||||
else
|
||||
Store.set(selected_player_store,player,selected_player_name)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- text entry for the reason bar
|
||||
local reason_field =
|
||||
reason_bar.add{
|
||||
name='entry',
|
||||
type='textfield',
|
||||
style='stretchable_textfield',
|
||||
tooltip={'player-list.reason-entry'}
|
||||
}
|
||||
Gui.set_padding(reason_field)
|
||||
reason_field.style.height = 28
|
||||
reason_field.style.minimal_width = 160
|
||||
|
||||
reason_confirm(reason_bar)
|
||||
|
||||
return list_table, action_bar
|
||||
-- Removes the three elements that are added as part of the base
|
||||
local function remove_player_base(parent,player)
|
||||
Gui.destroy_if_valid(parent[player.name])
|
||||
Gui.destroy_if_valid(parent['player-name-'..player.index])
|
||||
Gui.destroy_if_valid(parent['player-time-'..player.index])
|
||||
end
|
||||
|
||||
--- Adds buttons and permission flows to the action bar
|
||||
local function generate_action_bar(player,element)
|
||||
close_action_bar(element)
|
||||
local selected_player_name = Store.get(selected_player_store,player)
|
||||
-- Update the time label for a player using there player time data
|
||||
local function update_player_base(parent,player_time)
|
||||
local time_element = parent[player_time.element_name]
|
||||
if time_element and time_element.valid then
|
||||
time_element.label.caption = player_time.caption
|
||||
time_element.label.tooltip = player_time.tooltip
|
||||
end
|
||||
end
|
||||
|
||||
for action_name,buttons in pairs(config.buttons) do
|
||||
local permission_flow =
|
||||
element.add{
|
||||
type='flow',
|
||||
name=action_name
|
||||
}
|
||||
|
||||
for _,button in ipairs(buttons) do
|
||||
--- Adds all the buttons and flows that make up the action bar
|
||||
-- @element add_action_bar
|
||||
local add_action_bar_buttons =
|
||||
Gui.element(function(_,parent)
|
||||
close_action_bar(parent)
|
||||
-- Loop over all the buttons in the config
|
||||
for action_name,button_data in pairs(config.buttons) do
|
||||
-- Added the permission flow
|
||||
local permission_flow = parent.add{ type = 'flow', name = action_name }
|
||||
permission_flow.visible = false
|
||||
-- Add the buttons under that permission
|
||||
for _,button in ipairs(button_data) do
|
||||
button(permission_flow)
|
||||
end
|
||||
|
||||
if not Roles.player_allowed(player,action_name) then
|
||||
permission_flow.visible = false
|
||||
end
|
||||
|
||||
if buttons.auth and selected_player_name and not buttons.auth(player,selected_player_name) then
|
||||
permission_flow.visible = false
|
||||
end
|
||||
end
|
||||
|
||||
if not selected_player_name then
|
||||
element.visible = false
|
||||
end
|
||||
end
|
||||
return parent
|
||||
end)
|
||||
|
||||
--- Updates the action bar
|
||||
local player_list_name
|
||||
local function update_action_bar(player)
|
||||
local frame = Gui.classes.left_frames.get_frame(player_list_name,player)
|
||||
local element = frame.container.action_bar
|
||||
--- Updates the visible state of the action bar buttons
|
||||
local function update_action_bar(element)
|
||||
local player = Gui.get_player_from_element(element)
|
||||
local selected_player_name = Store.get(selected_player_store,player)
|
||||
|
||||
if not selected_player_name then
|
||||
-- Hide the action bar when no player is selected
|
||||
element.visible = false
|
||||
|
||||
else
|
||||
@@ -236,132 +201,213 @@ local function update_action_bar(player)
|
||||
end
|
||||
end
|
||||
|
||||
--- Adds a player to the player list
|
||||
local function add_player(list_table,player,role_name)
|
||||
open_action_bar(list_table,player.name)
|
||||
--- Main player list container for the left flow
|
||||
-- @element player_list_container
|
||||
local player_list_container =
|
||||
Gui.element(function(event_trigger,parent)
|
||||
-- Draw the internal container
|
||||
local container = Gui.container(parent,event_trigger,200)
|
||||
|
||||
-- flow to contain player_name to allow all to have trigger for zoom to map
|
||||
local player_name_flow =
|
||||
list_table.add{
|
||||
type='flow'
|
||||
-- Draw the scroll table for the players
|
||||
local scroll_table = Gui.scroll_table(container,184,3)
|
||||
|
||||
-- Change the style of the scroll table
|
||||
local scroll_table_style = scroll_table.style
|
||||
scroll_table_style.padding = {1,0,1,2}
|
||||
|
||||
-- Add the action bar
|
||||
local action_bar = Gui.footer(container,nil,nil,false,'action_bar')
|
||||
|
||||
-- Change the style of the action bar
|
||||
local action_bar_style = action_bar.style
|
||||
action_bar_style.height = 35
|
||||
action_bar_style.padding = {1,3}
|
||||
action_bar.visible = false
|
||||
|
||||
-- Add the buttons to the action bar
|
||||
add_action_bar_buttons(action_bar)
|
||||
|
||||
-- Add the reason bar
|
||||
local reason_bar = Gui.footer(container,nil,nil,false,'reason_bar')
|
||||
|
||||
-- Change the style of the reason bar
|
||||
local reason_bar_style = reason_bar.style
|
||||
reason_bar_style.height = 35
|
||||
reason_bar_style.padding = {-1,3}
|
||||
reason_bar.visible = false
|
||||
|
||||
-- Add the text entry for the reason bar
|
||||
local reason_field =
|
||||
reason_bar.add{
|
||||
name = 'entry',
|
||||
type = 'textfield',
|
||||
style = 'stretchable_textfield',
|
||||
tooltip = {'player-list.reason-entry'}
|
||||
}
|
||||
Gui.set_padding(player_name_flow)
|
||||
|
||||
-- player name with the tooltip of their highest role and in they colour
|
||||
local player_name =
|
||||
player_name_flow.add{
|
||||
name=zoom_to_map_name,
|
||||
type='label',
|
||||
caption=player.name,
|
||||
tooltip={'player-list.open-map',player.name,player.tag,role_name}
|
||||
}
|
||||
Gui.set_padding(player_name,0,0,0,2)
|
||||
player_name.style.font_color = player.chat_color
|
||||
-- Change the style of the text entry
|
||||
local reason_entry_style = reason_field.style
|
||||
reason_entry_style.padding = 0
|
||||
reason_entry_style.height = 28
|
||||
reason_entry_style.minimal_width = 160
|
||||
|
||||
-- flow which allows right align for the play time
|
||||
local time_flow = Gui.create_alignment(list_table,'player-time-'..player.index)
|
||||
-- Add the confirm reason button
|
||||
reason_confirm(reason_bar)
|
||||
|
||||
-- time given in Xh Ym and is right aligned
|
||||
-- Return the exteral container
|
||||
return container.parent
|
||||
end)
|
||||
:add_to_left_flow(true)
|
||||
|
||||
--- Button on the top flow used to toggle the player list container
|
||||
-- @element toggle_left_element
|
||||
Gui.left_toolbar_button('entity/character', {'player-list.main-tooltip'}, player_list_container, function(player)
|
||||
return Roles.player_allowed(player,'gui/player-list')
|
||||
end)
|
||||
|
||||
-- Get caption and tooltip format for a player
|
||||
local function get_time_formats(online_time,afk_time)
|
||||
local tick = game.tick > 0 and game.tick or 1
|
||||
local percent = math.round(player.online_time/tick,3)*100
|
||||
local time =
|
||||
time_flow.add{
|
||||
name='label',
|
||||
type='label',
|
||||
caption=format_time(player.online_time),
|
||||
tooltip={'player-list.afk-time',percent,format_time(player.afk_time,{minutes=true,long=true})}
|
||||
}
|
||||
Gui.set_padding(time)
|
||||
local percent = math.round(online_time/tick,3)*100
|
||||
local caption = format_time(online_time)
|
||||
local tooltip = {'player-list.afk-time', percent, format_time(afk_time,{minutes=true,long=true})}
|
||||
return caption, tooltip
|
||||
end
|
||||
|
||||
--- Adds fake players to the player list
|
||||
local function add_fake_players(list_table,count)
|
||||
local role_name = 'Fake Player'
|
||||
for i = 1,count do
|
||||
add_player(list_table,{
|
||||
name='Player '..i,
|
||||
index=0-i,
|
||||
tag='',
|
||||
online_time=math.random(0,game.tick),
|
||||
afk_time=math.random(0,game.tick),
|
||||
chat_color=table.get_random_dictionary_entry(Colors)
|
||||
},role_name)
|
||||
-- Get the player time to be used to update time label
|
||||
local function get_player_times()
|
||||
local ctn = 0
|
||||
local player_times = {}
|
||||
for _, player in pairs(game.connected_players) do
|
||||
ctn = ctn + 1
|
||||
-- Add the player time details to the array
|
||||
local caption, tooltip = get_time_formats(player.online_time, player.afk_time)
|
||||
player_times[ctn] = {
|
||||
element_name = 'player-time-'..player.index,
|
||||
caption = caption,
|
||||
tooltip = tooltip
|
||||
}
|
||||
end
|
||||
|
||||
return player_times
|
||||
end
|
||||
|
||||
--- Registers the player list
|
||||
-- @element player_list
|
||||
local player_list =
|
||||
Gui.new_left_frame('gui/player-list')
|
||||
:set_sprites('entity/character')
|
||||
:set_tooltip{'player-list.main-tooltip'}
|
||||
:set_open_by_default()
|
||||
:set_direction('vertical')
|
||||
:on_creation(function(player,element)
|
||||
local list_table,action_bar = generate_container(player,element)
|
||||
generate_action_bar(player,action_bar)
|
||||
|
||||
-- Get a sorted list of all online players
|
||||
local function get_player_list_order()
|
||||
-- Sort all the online players into roles
|
||||
local players = {}
|
||||
for _,next_player in pairs(game.connected_players) do
|
||||
local highest_role = Roles.get_player_highest_role(next_player)
|
||||
for _,player in pairs(game.connected_players) do
|
||||
local highest_role = Roles.get_player_highest_role(player)
|
||||
if not players[highest_role.name] then
|
||||
players[highest_role.name] = {}
|
||||
end
|
||||
table.insert(players[highest_role.name],next_player)
|
||||
table.insert(players[highest_role.name],player)
|
||||
end
|
||||
|
||||
-- Sort the players from roles into a set order
|
||||
local ctn = 0
|
||||
local player_list_order = {}
|
||||
for _,role_name in pairs(Roles.config.order) do
|
||||
if players[role_name] then
|
||||
for _,next_player in pairs(players[role_name]) do
|
||||
add_player(list_table,next_player,role_name)
|
||||
for _,player in pairs(players[role_name]) do
|
||||
ctn = ctn + 1
|
||||
-- Add the player data to the array
|
||||
local caption, tooltip = get_time_formats(player.online_time, player.afk_time)
|
||||
player_list_order[ctn] = {
|
||||
name = player.name,
|
||||
index = player.index,
|
||||
tag = player.tag,
|
||||
role_name = role_name,
|
||||
chat_color = player.chat_color,
|
||||
caption = caption,
|
||||
tooltip = tooltip
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--add_fake_players(list_table,6)
|
||||
--add_fake_players(list_table,20)
|
||||
end)
|
||||
:on_update(function(player,element)
|
||||
local list = element.container.scroll.table
|
||||
for _,next_player in pairs(game.connected_players) do
|
||||
local time_element_name = 'player-time-'..next_player.index
|
||||
local time_element = list[time_element_name]
|
||||
if time_element and time_element.valid then
|
||||
time_element.label.caption = format_time(next_player.online_time)
|
||||
local tick = game.tick > 0 and game.tick or 1
|
||||
local percent = math.round(next_player.online_time/tick,3)*100
|
||||
time_element.label.tooltip = {'player-list.afk-time',percent,format_time(next_player.afk_time,{minutes=true,long=true})}
|
||||
--[[Adds fake players to the player list
|
||||
for i = 1, 10 do
|
||||
local online_time = math.random(1,tick)
|
||||
local afk_time = math.random(online_time-(tick/10),tick)
|
||||
local caption, tooltip = get_time_formats(online_time, afk_time)
|
||||
player_list_order[ctn+i] = {
|
||||
name='Player '..i,
|
||||
index=0-i,
|
||||
tag='',
|
||||
role_name = 'Fake Player',
|
||||
chat_color = table.get_random_dictionary_entry(Colors),
|
||||
caption = caption,
|
||||
tooltip = tooltip
|
||||
}
|
||||
end]]
|
||||
|
||||
return player_list_order
|
||||
end
|
||||
|
||||
--- Update the play times every 30 sections
|
||||
Event.on_nth_tick(1800,function()
|
||||
local player_times = get_player_times()
|
||||
for _,player in pairs(game.connected_players) do
|
||||
local frame = Gui.get_left_element(player,player_list_container)
|
||||
local scroll_table = frame.container.scroll.table
|
||||
for _,player_time in pairs(player_times) do
|
||||
update_player_base(scroll_table,player_time)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
player_list_name = player_list:uid()
|
||||
--- When a player leaves only remove they entry
|
||||
Event.add(defines.events.on_player_left_game,function(event)
|
||||
local remove_player = event.player
|
||||
for _,player in pairs(game.connected_players) do
|
||||
local frame = Gui.get_left_element(player,player_list_container)
|
||||
local scroll_table = frame.container.scroll.table
|
||||
remove_player_base(scroll_table,remove_player)
|
||||
end
|
||||
end)
|
||||
|
||||
--- All other events require a full redraw of the table
|
||||
local function redraw_player_list()
|
||||
local player_list_order = get_player_list_order()
|
||||
for _,player in pairs(game.connected_players) do
|
||||
local frame = Gui.get_left_element(player,player_list_container)
|
||||
local scroll_table = frame.container.scroll.table
|
||||
scroll_table.clear()
|
||||
for _,next_player_data in ipairs(player_list_order) do
|
||||
add_player_base(scroll_table,next_player_data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_player_joined_game,redraw_player_list)
|
||||
Event.add(Roles.events.on_role_assigned,redraw_player_list)
|
||||
Event.add(Roles.events.on_role_unassigned,redraw_player_list)
|
||||
|
||||
--- When the action player is changed the action bar will update
|
||||
Store.watch(selected_player_store,function(value,player_name)
|
||||
local player = Game.get_player_from_any(player_name)
|
||||
update_action_bar(player)
|
||||
|
||||
-- Change the style of the option buttons
|
||||
local frame = player_list:get_frame(player)
|
||||
local data_table = frame.container.scroll.table
|
||||
local frame = Gui.get_left_element(player,player_list_container)
|
||||
local scroll_table = frame.container.scroll.table
|
||||
update_action_bar(frame.container.action_bar)
|
||||
for _,next_player in pairs(game.connected_players) do
|
||||
local element = data_table[next_player.name][open_action_bar.name]
|
||||
local element = scroll_table[next_player.name][open_action_bar.name]
|
||||
local style = 'frame_button'
|
||||
if next_player.name == value then
|
||||
style = 'tool_button'
|
||||
end
|
||||
element.style = style
|
||||
Gui.set_padding(element,-2,-2,-2,-2)
|
||||
element.style.width = 8
|
||||
element.style.height = 14
|
||||
local element_style = element.style
|
||||
element_style.padding = -2
|
||||
element_style.width = 8
|
||||
element_style.height = 14
|
||||
end
|
||||
end)
|
||||
|
||||
--- When the action name is changed the reason input will update
|
||||
Store.watch(selected_action_store,function(value,player_name)
|
||||
local player = Game.get_player_from_any(player_name)
|
||||
local frame = Gui.classes.left_frames.get_frame(player_list_name,player)
|
||||
local frame = Gui.get_left_element(player,player_list_container)
|
||||
local element = frame.container.reason_bar
|
||||
if value then
|
||||
-- if there is a new value then check the player is still online
|
||||
@@ -379,13 +425,4 @@ Store.watch(selected_action_store,function(value,player_name)
|
||||
element.visible = false
|
||||
|
||||
end
|
||||
end)
|
||||
|
||||
--- Many events which trigger the gui to be re drawn, it will also update the times every 30 seconds
|
||||
Event.on_nth_tick(1800,player_list 'update_all')
|
||||
Event.add(defines.events.on_player_joined_game,player_list 'redraw_all')
|
||||
Event.add(defines.events.on_player_left_game,player_list 'redraw_all')
|
||||
Event.add(Roles.events.on_role_assigned,player_list 'redraw_all')
|
||||
Event.add(Roles.events.on_role_unassigned,player_list 'redraw_all')
|
||||
|
||||
return player_list
|
||||
end)
|
||||
@@ -12,8 +12,15 @@ local format_time = ext_require('expcore.common','format_time') --- @dep expcore
|
||||
local Colors = require 'resources.color_presets' --- @dep resources.color_presets
|
||||
local Rockets = require 'modules.control.rockets' --- @dep modules.control.rockets
|
||||
|
||||
--- Gets if a player is allowed to use the action buttons
|
||||
local function player_allowed(player,action)
|
||||
local time_formats = {
|
||||
caption = function(value) return format_time(value, {minutes=true, seconds=true}) end,
|
||||
caption_hours = function(value) return format_time(value) end,
|
||||
tooltip = function(value) return format_time(value, {minutes=true, seconds=true, long=true}) end,
|
||||
tooltip_hours = function(value) return format_time(value, {hours=true, minutes=true, seconds=true, long=true}) end
|
||||
}
|
||||
|
||||
--- Check if a player is allowed to use certain interactions
|
||||
local function check_player_permissions(player,action)
|
||||
if not config.progress['allow_'..action] then
|
||||
return false
|
||||
end
|
||||
@@ -22,38 +29,48 @@ local function player_allowed(player,action)
|
||||
return false
|
||||
end
|
||||
|
||||
if config.progress[action..'_role_permission'] and not Roles.player_allowed(player,config.progress[action..'_role_permission']) then
|
||||
if config.progress[action..'_role_permission']
|
||||
and not Roles.player_allowed(player,config.progress[action..'_role_permission']) then
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--- Used on the name label to allow zoom to map
|
||||
-- @element zoom_to_map
|
||||
local zoom_to_map_name = Gui.uid_name()
|
||||
Gui.on_click(zoom_to_map_name,function(event)
|
||||
local rocket_silo_name = event.element.parent.caption
|
||||
local rocket_silo = Rockets.get_silo_entity(rocket_silo_name)
|
||||
event.player.zoom_to_world(rocket_silo.position,2)
|
||||
--- Button to toggle the auto launch on a rocket silo
|
||||
-- @elemeent toggle_launch
|
||||
local toggle_launch =
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/play',
|
||||
tooltip = {'rocket-info.toggle-rocket-tooltip'}
|
||||
}
|
||||
:style(Gui.sprite_style(16))
|
||||
:on_click(function(_,element,_)
|
||||
local rocket_silo_name = element.parent.name:sub(8)
|
||||
local rocket_silo = Rockets.get_silo_entity(rocket_silo_name)
|
||||
if rocket_silo.auto_launch then
|
||||
element.sprite = 'utility/play'
|
||||
element.tooltip = {'rocket-info.toggle-rocket-tooltip'}
|
||||
rocket_silo.auto_launch = false
|
||||
else
|
||||
element.sprite = 'utility/stop'
|
||||
element.tooltip = {'rocket-info.toggle-rocket-tooltip-disabled'}
|
||||
rocket_silo.auto_launch = true
|
||||
end
|
||||
end)
|
||||
|
||||
--- Used to launch the rocket, when it is ready
|
||||
--- Button to remotely launch a rocket from a silo
|
||||
-- @element launch_rocket
|
||||
local launch_rocket =
|
||||
Gui.new_button()
|
||||
:set_sprites('utility/center')
|
||||
:set_tooltip{'rocket-info.launch-tooltip'}
|
||||
:set_embedded_flow(function(element,rocket_silo_name)
|
||||
return 'launch-'..rocket_silo_name
|
||||
end)
|
||||
:set_style('tool_button',function(style)
|
||||
Gui.set_padding_style(style,-2,-2,-2,-2)
|
||||
style.width = 16
|
||||
style.height = 16
|
||||
end)
|
||||
:on_click(function(player,element)
|
||||
local rocket_silo_name = element.parent.name:sub(8)
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/center',
|
||||
tooltip = {'rocket-info.launch-tooltip'}
|
||||
}
|
||||
:style(Gui.sprite_style(16,-1))
|
||||
:on_click(function(player,element,_)
|
||||
local rocket_silo_name = element.parent.name:sub(8)
|
||||
local silo_data = Rockets.get_silo_data_by_name(rocket_silo_name)
|
||||
if silo_data.entity.launch_rocket() then
|
||||
silo_data.awaiting_reset = true
|
||||
@@ -66,457 +83,519 @@ end)
|
||||
end
|
||||
end)
|
||||
|
||||
--- Used to toggle the auto launch on a rocket
|
||||
-- @element toggle_rocket
|
||||
local toggle_rocket =
|
||||
Gui.new_button()
|
||||
:set_sprites('utility/play')
|
||||
:set_tooltip{'rocket-info.toggle-rocket-tooltip'}
|
||||
:set_embedded_flow(function(element,rocket_silo_name)
|
||||
return 'toggle-'..rocket_silo_name
|
||||
--- XY cords that allow zoom to map when pressed
|
||||
-- @element silo_cords
|
||||
local silo_cords =
|
||||
Gui.element(function(event_trigger,parent,silo_data)
|
||||
local silo_name = silo_data.silo_name
|
||||
local pos = silo_data.position
|
||||
local name = config.progress.allow_zoom_to_map and event_trigger or nil
|
||||
local tooltip = config.progress.allow_zoom_to_map and {'rocket-info.progress-label-tooltip'} or nil
|
||||
|
||||
-- Add the x cord flow
|
||||
local flow_x = parent.add{
|
||||
type ='flow',
|
||||
name = 'label-x-'..silo_name,
|
||||
caption = silo_name
|
||||
}
|
||||
flow_x.style.padding = {0,2,0,1}
|
||||
|
||||
-- Add the x cord label
|
||||
flow_x.add{
|
||||
type = 'label',
|
||||
name = name,
|
||||
caption = {'rocket-info.progress-x-pos',pos.x},
|
||||
tooltip = tooltip
|
||||
}
|
||||
|
||||
-- Add the y cord flow
|
||||
local flow_y = parent.add{
|
||||
type ='flow',
|
||||
name = 'label-y-'..silo_name,
|
||||
caption = silo_name
|
||||
}
|
||||
flow_y.style.padding = {0,2,0,1}
|
||||
|
||||
-- Add the y cord label
|
||||
flow_y.add{
|
||||
type = 'label',
|
||||
name = name,
|
||||
caption = {'rocket-info.progress-y-pos',pos.y},
|
||||
tooltip = tooltip
|
||||
}
|
||||
|
||||
end)
|
||||
:set_style('tool_button',function(style)
|
||||
Gui.set_padding_style(style,-2,-2,-2,-2)
|
||||
style.width = 16
|
||||
style.height = 16
|
||||
end)
|
||||
:on_click(function(player,element)
|
||||
local rocket_silo_name = element.parent.name:sub(8)
|
||||
:on_click(function(player,element,_)
|
||||
local rocket_silo_name = element.parent.caption
|
||||
local rocket_silo = Rockets.get_silo_entity(rocket_silo_name)
|
||||
if rocket_silo.auto_launch then
|
||||
element.sprite = 'utility/play'
|
||||
element.tooltip = {'rocket-info.toggle-rocket-tooltip'}
|
||||
rocket_silo.auto_launch = false
|
||||
else
|
||||
element.sprite = 'utility/stop'
|
||||
element.tooltip = {'rocket-info.toggle-rocket-tooltip-disabled'}
|
||||
rocket_silo.auto_launch = true
|
||||
end
|
||||
player.zoom_to_world(rocket_silo.position,2)
|
||||
end)
|
||||
|
||||
--- Used to toggle the visibility of the different sections
|
||||
-- @element toggle_section
|
||||
local toggle_section =
|
||||
Gui.new_button()
|
||||
:set_sprites('utility/expand_dark','utility/expand')
|
||||
:set_tooltip{'rocket-info.toggle-section-tooltip'}
|
||||
:set_style('tool_button',function(style)
|
||||
Gui.set_padding_style(style,-2,-2,-2,-2)
|
||||
style.height = 20
|
||||
style.width = 20
|
||||
end)
|
||||
:on_click(function(player,element)
|
||||
local flow_name = element.parent.caption
|
||||
local flow = element.parent.parent.parent[flow_name]
|
||||
if Gui.toggle_visible(flow) then
|
||||
element.sprite = 'utility/collapse_dark'
|
||||
element.hovered_sprite = 'utility/collapse'
|
||||
element.tooltip = {'rocket-info.toggle-section-collapse-tooltip'}
|
||||
else
|
||||
element.sprite = 'utility/expand_dark'
|
||||
element.hovered_sprite = 'utility/expand'
|
||||
element.tooltip = {'rocket-info.toggle-section-tooltip'}
|
||||
end
|
||||
--- Base element for each rocket in the progress list
|
||||
-- @element rocket_entry
|
||||
local rocket_entry =
|
||||
Gui.element(function(_,parent,silo_data)
|
||||
local silo_name = silo_data.silo_name
|
||||
local player = Gui.get_player_from_element(parent)
|
||||
|
||||
-- Add the toggle auto launch if the player is allowed it
|
||||
if check_player_permissions(player,'toggle_active') then
|
||||
local flow = parent.add{ type = 'flow', name = 'toggle-'..silo_name}
|
||||
local button = toggle_launch(flow)
|
||||
button.tooltip = silo_data.toggle_tooltip
|
||||
button.sprite = silo_data.toggle_sprite
|
||||
end
|
||||
|
||||
-- Add the remote launch if the player is allowed it
|
||||
if check_player_permissions(player,'remote_launch') then
|
||||
local flow = parent.add{ type = 'flow', name = 'launch-'..silo_name}
|
||||
local button = launch_rocket(flow)
|
||||
button.enabled = silo_data.allow_launch
|
||||
end
|
||||
|
||||
-- Draw the silo cords element
|
||||
silo_cords(parent,silo_data)
|
||||
|
||||
-- Add a progress label
|
||||
local alignment = Gui.alignment(parent,silo_name)
|
||||
local element =
|
||||
alignment.add{
|
||||
type = 'label',
|
||||
name = 'label',
|
||||
caption = silo_data.progress_caption,
|
||||
tooltip = silo_data.progress_tooltip
|
||||
}
|
||||
|
||||
-- Return the progress label
|
||||
return element
|
||||
end)
|
||||
|
||||
--- Used to create the three different sections
|
||||
local function create_section(container,section_name,table_size)
|
||||
-- Header for the section
|
||||
local header_area = Gui.create_header(
|
||||
container,
|
||||
{'rocket-info.section-caption-'..section_name},
|
||||
{'rocket-info.section-tooltip-'..section_name},
|
||||
true,
|
||||
section_name..'-header'
|
||||
)
|
||||
--- Data label which contains a name and a value label pair
|
||||
-- @element data_label
|
||||
local data_label =
|
||||
Gui.element(function(_,parent,label_data)
|
||||
local data_name = label_data.name
|
||||
local data_subname = label_data.subname
|
||||
local data_fullname = data_subname and data_name..data_subname or data_name
|
||||
|
||||
-- Right aligned button to toggle the section
|
||||
header_area.caption = section_name
|
||||
toggle_section(header_area)
|
||||
-- Add the name label
|
||||
local name_label = parent.add{
|
||||
type = 'label',
|
||||
name = data_fullname..'-label',
|
||||
caption = {'rocket-info.data-caption-'..data_name,data_subname},
|
||||
tooltip = {'rocket-info.data-tooltip-'..data_name,data_subname}
|
||||
}
|
||||
name_label.style.padding = {0,2}
|
||||
|
||||
-- Table used to store the data
|
||||
local flow_table = Gui.create_scroll_table(container,table_size,215,section_name)
|
||||
flow_table.parent.visible = false
|
||||
--- Right aligned label to store the data
|
||||
local alignment = Gui.alignment(parent,data_fullname)
|
||||
local element =
|
||||
alignment.add{
|
||||
type = 'label',
|
||||
name = 'label',
|
||||
caption = label_data.value,
|
||||
tooltip = label_data.tooltip
|
||||
}
|
||||
element.style.padding = {0,2}
|
||||
|
||||
return element
|
||||
end)
|
||||
|
||||
-- Used to update the captions and tooltips on the data labels
|
||||
local function update_data_labels(parent,data_label_data)
|
||||
for _, label_data in ipairs(data_label_data) do
|
||||
local data_name = label_data.subname and label_data.name..label_data.subname or label_data.name
|
||||
if not parent[data_name] then
|
||||
data_label(parent,label_data)
|
||||
else
|
||||
local data_label_element = parent[data_name].label
|
||||
data_label_element.tooltip = label_data.tooltip
|
||||
data_label_element.caption = label_data.value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Creates the main structure for the gui
|
||||
element
|
||||
> container
|
||||
local function get_progress_data(force_name)
|
||||
local force_silos = Rockets.get_silos(force_name)
|
||||
local progress_data = {}
|
||||
|
||||
>> stats-header
|
||||
>>> stats
|
||||
>>>> toggle_section.name
|
||||
>> stats
|
||||
>>> table
|
||||
for _, silo_data in pairs(force_silos) do
|
||||
local rocket_silo = silo_data.entity
|
||||
if not rocket_silo or not rocket_silo.valid then
|
||||
-- Remove from list if not valid
|
||||
force_silos[silo_data.name] = nil
|
||||
table.insert(progress_data,{
|
||||
silo_name = silo_data.name,
|
||||
remove = true
|
||||
})
|
||||
|
||||
>> milestones-header
|
||||
>>> milestones
|
||||
>>>> toggle_section.name
|
||||
>> milestones
|
||||
>>> table
|
||||
else
|
||||
-- Get the progress caption and tooltip
|
||||
local progress_color = Colors.white
|
||||
local progress_caption = {'rocket-info.progress-caption',rocket_silo.rocket_parts}
|
||||
local progress_tooltip = {'rocket-info.progress-tooltip',silo_data.launched or 0}
|
||||
local status = rocket_silo.status == defines.entity_status.waiting_to_launch_rocket
|
||||
if status and silo_data.awaiting_reset then
|
||||
progress_caption = {'rocket-info.progress-launched'}
|
||||
progress_color = Colors.green
|
||||
elseif status then
|
||||
progress_caption = {'rocket-info.progress-caption',100}
|
||||
progress_color = Colors.cyan
|
||||
else
|
||||
silo_data.awaiting_reset = false
|
||||
end
|
||||
|
||||
>> progress-header
|
||||
>>> progress
|
||||
>>>> toggle_section.name
|
||||
>> progress
|
||||
>>> table
|
||||
]]
|
||||
local function generate_container(player,element)
|
||||
Gui.set_padding(element,1,2,2,2)
|
||||
element.style.minimal_width = 200
|
||||
-- Get the toggle button data
|
||||
local toggle_tooltip = {'rocket-info.toggle-rocket-tooltip-disabled'}
|
||||
local toggle_sprite = 'utility/play'
|
||||
if rocket_silo.auto_launch then
|
||||
toggle_tooltip = {'rocket-info.toggle-rocket-tooltip'}
|
||||
toggle_sprite = 'utility/stop'
|
||||
end
|
||||
|
||||
-- main container which contains the other elements
|
||||
local container =
|
||||
element.add{
|
||||
name='container',
|
||||
type='frame',
|
||||
direction='vertical',
|
||||
style='window_content_frame_packed'
|
||||
}
|
||||
Gui.set_padding(container)
|
||||
|
||||
if config.stats.show_stats then
|
||||
create_section(container,'stats',2)
|
||||
end
|
||||
|
||||
if config.milestones.show_milestones then
|
||||
create_section(container,'milestones',2)
|
||||
end
|
||||
|
||||
if config.progress.show_progress then
|
||||
local col_count = 3
|
||||
if player_allowed(player,'remote_launch') then col_count = col_count+1 end
|
||||
if player_allowed(player,'toggle_active') then col_count = col_count+1 end
|
||||
create_section(container,'progress',col_count)
|
||||
--- label used when no active silos
|
||||
container.progress.add{
|
||||
type='label',
|
||||
name='no_silos',
|
||||
caption={'rocket-info.progress-no-silos'}
|
||||
}
|
||||
end
|
||||
-- Insert the gui data
|
||||
table.insert(progress_data,{
|
||||
silo_name = silo_data.name,
|
||||
position = rocket_silo.position,
|
||||
allow_launch = not silo_data.awaiting_reset and status or false,
|
||||
progress_color = progress_color,
|
||||
progress_caption = progress_caption,
|
||||
progress_tooltip = progress_tooltip,
|
||||
toggle_tooltip = toggle_tooltip,
|
||||
toggle_sprite = toggle_sprite
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
return progress_data
|
||||
end
|
||||
|
||||
--[[ Creates a text label followed by a data label, or updates them if already present
|
||||
element
|
||||
> "data_name_extra"-label
|
||||
> "data_name_extra"
|
||||
>> label
|
||||
]]
|
||||
local function create_label_value_pair(element,data_name,value,tooltip,extra)
|
||||
local data_name_extra = extra and data_name..extra or data_name
|
||||
if element[data_name_extra] then
|
||||
element[data_name_extra].label.caption = value
|
||||
element[data_name_extra].label.tooltip = tooltip
|
||||
else
|
||||
--- Label used with the data
|
||||
element.add{
|
||||
type='label',
|
||||
name=data_name_extra..'-label',
|
||||
caption={'rocket-info.data-caption-'..data_name,extra},
|
||||
tooltip={'rocket-info.data-tooltip-'..data_name,extra}
|
||||
}
|
||||
--- Right aligned label to store the data
|
||||
local right_flow = Gui.create_alignment(element,data_name_extra)
|
||||
right_flow.add{
|
||||
type='label',
|
||||
name='label',
|
||||
caption=value,
|
||||
tooltip=tooltip
|
||||
}
|
||||
end
|
||||
--- Update the build progress section
|
||||
local function update_build_progress(parent,progress_data)
|
||||
local show_message = true
|
||||
for _, silo_data in ipairs(progress_data) do
|
||||
parent.no_silos.visible = false
|
||||
local silo_name = silo_data.silo_name
|
||||
local progress_label = parent[silo_name]
|
||||
if silo_data.remove then
|
||||
-- Remove the rocket from the list
|
||||
Gui.destroy_if_valid(parent['toggle-'..silo_name])
|
||||
Gui.destroy_if_valid(parent['launch-'..silo_name])
|
||||
Gui.destroy_if_valid(parent['label-x-'..silo_name])
|
||||
Gui.destroy_if_valid(parent['label-y-'..silo_name])
|
||||
Gui.destroy_if_valid(parent[silo_name])
|
||||
|
||||
elseif not progress_label then
|
||||
-- Add the rocket to the list
|
||||
show_message = false
|
||||
rocket_entry(parent,silo_data)
|
||||
|
||||
else
|
||||
show_message = false
|
||||
-- Update the existing labels
|
||||
progress_label = progress_label.label
|
||||
progress_label.caption = silo_data.progress_caption
|
||||
progress_label.tooltip = silo_data.progress_tooltip
|
||||
progress_label.style.font_color = silo_data.progress_color
|
||||
|
||||
-- Update the toggle button
|
||||
local toggle_button = parent['toggle-'..silo_name]
|
||||
if toggle_button then
|
||||
toggle_button = toggle_button[toggle_launch.name]
|
||||
toggle_button.tooltip = silo_data.toggle_tooltip
|
||||
toggle_button.sprite = silo_data.toggle_sprite
|
||||
end
|
||||
|
||||
-- Update the launch button
|
||||
local launch_button = parent['launch-'..silo_name]
|
||||
if launch_button then
|
||||
launch_button = launch_button[launch_rocket.name]
|
||||
launch_button.enabled = silo_data.allow_launch
|
||||
end
|
||||
end
|
||||
end
|
||||
if show_message then parent.no_silos.visible = true end
|
||||
end
|
||||
|
||||
--- Creates a text and data label using times as the data
|
||||
local function create_label_value_pair_time(element,data_name,raw_value,no_hours,extra)
|
||||
local value = no_hours and format_time(raw_value,{minutes=true,seconds=true}) or format_time(raw_value)
|
||||
local tooltip = format_time(raw_value,{hours=not no_hours,minutes=true,seconds=true,long=true})
|
||||
create_label_value_pair(element,data_name,value,tooltip,extra)
|
||||
end
|
||||
|
||||
--- Adds the different data values to the stats section
|
||||
local function generate_stats(player,frame)
|
||||
if not config.stats.show_stats then return end
|
||||
local element = frame.container.stats.table
|
||||
local force_name = player.force.name
|
||||
--- Gets the label data for all the different stats
|
||||
local function get_stats_data(force_name)
|
||||
local force_rockets = Rockets.get_rocket_count(force_name)
|
||||
local stats = Rockets.get_stats(force_name)
|
||||
local stats = Rockets.get_stats(force_name)
|
||||
local stats_data = {}
|
||||
|
||||
if config.stats.show_first_rocket then
|
||||
create_label_value_pair_time(element,'first-launch',stats.first_launch or 0)
|
||||
-- Format the first launch data
|
||||
if config.stats.show_first_rocket then
|
||||
local value = stats.first_launch or 0
|
||||
table.insert(stats_data,{
|
||||
name = 'first-launch',
|
||||
value = time_formats.caption_hours(value),
|
||||
tooltip = time_formats.tooltip_hours(value)
|
||||
})
|
||||
end
|
||||
|
||||
-- Format the last launch data
|
||||
if config.stats.show_last_rocket then
|
||||
local value = stats.last_launch or 0
|
||||
table.insert(stats_data,{
|
||||
name = 'last-launch',
|
||||
value = time_formats.caption_hours(value),
|
||||
tooltip = time_formats.tooltip_hours(value)
|
||||
})
|
||||
end
|
||||
|
||||
if config.stats.show_last_rocket then
|
||||
create_label_value_pair_time(element,'last-launch',stats.last_launch or 0)
|
||||
end
|
||||
|
||||
if config.stats.show_fastest_rocket then
|
||||
create_label_value_pair_time(element,'fastest-launch',stats.fastest_launch or 0,true)
|
||||
-- Format fastest launch data
|
||||
if config.stats.show_fastest_rocket then
|
||||
local value = stats.fastest_launch or 0
|
||||
table.insert(stats_data,{
|
||||
name = 'fastest-launch',
|
||||
value = time_formats.caption_hours(value),
|
||||
tooltip = time_formats.tooltip_hours(value)
|
||||
})
|
||||
end
|
||||
|
||||
-- Format total rocket data
|
||||
if config.stats.show_total_rockets then
|
||||
local total_rockets = Rockets.get_game_rocket_count()
|
||||
total_rockets = total_rockets == 0 and 1 or total_rockets
|
||||
local percentage = math.round(force_rockets/total_rockets,3)*100
|
||||
create_label_value_pair(element,'total-rockets',force_rockets,{'rocket-info.value-tooltip-total-rockets',percentage})
|
||||
local percentage = math.round(force_rockets/total_rockets,3)*100
|
||||
table.insert(stats_data,{
|
||||
name = 'total-rockets',
|
||||
value = force_rockets,
|
||||
tooltip = {'rocket-info.value-tooltip-total-rockets',percentage}
|
||||
})
|
||||
end
|
||||
|
||||
-- Format game avg data
|
||||
if config.stats.show_game_avg then
|
||||
local avg = force_rockets > 0 and math.floor(game.tick/force_rockets) or 0
|
||||
create_label_value_pair_time(element,'avg-launch',avg,true)
|
||||
local avg = force_rockets > 0 and math.floor(game.tick/force_rockets) or 0
|
||||
table.insert(stats_data,{
|
||||
name = 'avg-launch',
|
||||
value = time_formats.caption(avg),
|
||||
tooltip = time_formats.tooltip(avg)
|
||||
})
|
||||
end
|
||||
|
||||
-- Format rolling avg data
|
||||
for _,avg_over in pairs(config.stats.rolling_avg) do
|
||||
local avg = Rockets.get_rolling_average(force_name,avg_over)
|
||||
create_label_value_pair_time(element,'avg-launch-n',avg,true,avg_over)
|
||||
end
|
||||
local avg = Rockets.get_rolling_average(force_name,avg_over)
|
||||
table.insert(stats_data,{
|
||||
name = 'avg-launch-n',
|
||||
subname = avg_over,
|
||||
value = time_formats.caption(avg),
|
||||
tooltip = time_formats.tooltip(avg)
|
||||
})
|
||||
end
|
||||
|
||||
-- Return formated data
|
||||
return stats_data
|
||||
end
|
||||
|
||||
--- Creates the list of milestones
|
||||
local function generate_milestones(player,frame)
|
||||
if not config.milestones.show_milestones then return end
|
||||
local element = frame.container.milestones.table
|
||||
local force_name = player.force.name
|
||||
local force_rockets = Rockets.get_rocket_count(force_name)
|
||||
--- Gets the label data for the milestones
|
||||
local function get_milestone_data(force_name)
|
||||
local force_rockets = Rockets.get_rocket_count(force_name)
|
||||
local milestone_data = {}
|
||||
|
||||
for _,milestone in ipairs(config.milestones) do
|
||||
for _,milestone in ipairs(config.milestones) do
|
||||
if milestone <= force_rockets then
|
||||
local time = Rockets.get_rocket_time(force_name,milestone)
|
||||
create_label_value_pair_time(element,'milestone-n',time,false,milestone)
|
||||
else
|
||||
create_label_value_pair_time(element,'milestone-n',0,false,milestone)
|
||||
local time = Rockets.get_rocket_time(force_name,milestone)
|
||||
table.insert(milestone_data,{
|
||||
name = 'milestone-n',
|
||||
subname = milestone,
|
||||
value = time_formats.caption_hours(time),
|
||||
tooltip = time_formats.tooltip_hours(time)
|
||||
})
|
||||
else
|
||||
table.insert(milestone_data,{
|
||||
name = 'milestone-n',
|
||||
subname = milestone,
|
||||
value = {'rocket-info.data-caption-milestone-next'},
|
||||
tooltip = {'rocket-info.data-tooltip-milestone-next'}
|
||||
})
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return milestone_data
|
||||
end
|
||||
|
||||
--- Creats the different buttons used with the rocket silos
|
||||
local function generate_progress_buttons(player,element,silo_data)
|
||||
local silo_name = silo_data.name
|
||||
local rocket_silo = silo_data.entity
|
||||
local status = rocket_silo.status == defines.entity_status.waiting_to_launch_rocket
|
||||
local active = rocket_silo.auto_launch
|
||||
-- Button to toggle a section dropdown
|
||||
-- @element toggle_section
|
||||
local toggle_section =
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/expand_dark',
|
||||
hovered_sprite = 'utility/expand',
|
||||
tooltip = {'rocket-info.toggle-section-tooltip'}
|
||||
}
|
||||
:style(Gui.sprite_style(20))
|
||||
:on_click(function(_,element,_)
|
||||
local header_flow = element.parent
|
||||
local flow_name = header_flow.caption
|
||||
local flow = header_flow.parent.parent[flow_name]
|
||||
if Gui.toggle_visible_state(flow) then
|
||||
element.sprite = 'utility/collapse_dark'
|
||||
element.hovered_sprite = 'utility/collapse'
|
||||
element.tooltip = {'rocket-info.toggle-section-collapse-tooltip'}
|
||||
else
|
||||
element.sprite = 'utility/expand_dark'
|
||||
element.hovered_sprite = 'utility/expand'
|
||||
element.tooltip = {'rocket-info.toggle-section-tooltip'}
|
||||
end
|
||||
end)
|
||||
|
||||
if player_allowed(player,'toggle_active') then
|
||||
local button_element = element['toggle-'..silo_name]
|
||||
-- Draw a section header and main scroll
|
||||
-- @element rocket_list_container
|
||||
local section =
|
||||
Gui.element(function(_,parent,section_name,table_size)
|
||||
-- Draw the header for the section
|
||||
local header = Gui.header(
|
||||
parent,
|
||||
{'rocket-info.section-caption-'..section_name},
|
||||
{'rocket-info.section-tooltip-'..section_name},
|
||||
true,
|
||||
section_name..'-header'
|
||||
)
|
||||
|
||||
if button_element then
|
||||
button_element = button_element[toggle_rocket.name]
|
||||
else
|
||||
button_element = toggle_rocket(element,silo_name)
|
||||
end
|
||||
-- Right aligned button to toggle the section
|
||||
header.caption = section_name
|
||||
toggle_section(header)
|
||||
|
||||
if active then
|
||||
button_element.tooltip = {'rocket-info.toggle-rocket-tooltip'}
|
||||
button_element.sprite = 'utility/stop'
|
||||
else
|
||||
button_element.tooltip = {'rocket-info.toggle-rocket-tooltip-disabled'}
|
||||
button_element.sprite = 'utility/play'
|
||||
end
|
||||
end
|
||||
-- Table used to store the data
|
||||
local scroll_table = Gui.scroll_table(parent,215,table_size,section_name)
|
||||
scroll_table.parent.visible = false
|
||||
|
||||
if player_allowed(player,'remote_launch') then
|
||||
local button_element = element['launch-'..silo_name]
|
||||
-- Return the flow table
|
||||
return scroll_table
|
||||
end)
|
||||
|
||||
if button_element then
|
||||
button_element = button_element[launch_rocket.name]
|
||||
else
|
||||
button_element = launch_rocket(element,silo_name)
|
||||
end
|
||||
--- Main gui container for the left flow
|
||||
-- @element rocket_list_container
|
||||
local rocket_list_container =
|
||||
Gui.element(function(event_trigger,parent)
|
||||
-- Draw the internal container
|
||||
local container = Gui.container(parent,event_trigger,200)
|
||||
|
||||
if silo_data.awaiting_reset then
|
||||
button_element.enabled = false
|
||||
else
|
||||
button_element.enabled = status
|
||||
end
|
||||
end
|
||||
-- Set the container style
|
||||
local style = container.style
|
||||
style.padding = 0
|
||||
|
||||
local player = Gui.get_player_from_element(parent)
|
||||
local force_name = player.force.name
|
||||
-- Draw stats section
|
||||
if config.stats.show_stats then
|
||||
update_data_labels(section(container,'stats',2),get_stats_data(force_name))
|
||||
end
|
||||
|
||||
-- Draw milestones section
|
||||
if config.milestones.show_milestones then
|
||||
update_data_labels(section(container,'milestones',2),get_milestone_data(force_name))
|
||||
end
|
||||
|
||||
-- Draw build progress list
|
||||
if config.progress.show_progress then
|
||||
local col_count = 3
|
||||
if check_player_permissions(player,'remote_launch') then col_count = col_count+1 end
|
||||
if check_player_permissions(player,'toggle_active') then col_count = col_count+1 end
|
||||
local progress = section(container,'progress',col_count)
|
||||
-- Label used when there are no active silos
|
||||
local no_silos = progress.add{
|
||||
type = 'label',
|
||||
name = 'no_silos',
|
||||
caption = {'rocket-info.progress-no-silos'}
|
||||
}
|
||||
no_silos.style.padding = {1,2}
|
||||
update_build_progress(progress,get_progress_data(force_name))
|
||||
end
|
||||
|
||||
-- Return the exteral container
|
||||
return container.parent
|
||||
end)
|
||||
:add_to_left_flow(function(player)
|
||||
return player.force.rockets_launched > 0 and Roles.player_allowed(player,'gui/rocket-info')
|
||||
end)
|
||||
|
||||
--- Button on the top flow used to toggle the container
|
||||
-- @element toggle_left_element
|
||||
Gui.left_toolbar_button('entity/rocket-silo', {'rocket-info.main-tooltip'}, rocket_list_container, function(player)
|
||||
return Roles.player_allowed(player,'gui/rocket-info')
|
||||
end)
|
||||
|
||||
--- Update the gui for all players on a force
|
||||
local function update_rocket_gui_all(force_name)
|
||||
local stats = get_stats_data(force_name)
|
||||
local milestones = get_milestone_data(force_name)
|
||||
local progress = get_progress_data(force_name)
|
||||
for _,player in pairs(game.forces[force_name].players) do
|
||||
local frame = Gui.get_left_element(player,rocket_list_container)
|
||||
local container = frame.container
|
||||
update_data_labels(container.stats.table,stats)
|
||||
update_data_labels(container.milestones.table,milestones)
|
||||
update_build_progress(container.progress.table,progress)
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Creates build progress section
|
||||
element
|
||||
> toggle-"silo_name" (generate_progress_buttons)
|
||||
> launch-"silo_name" (generate_progress_buttons)
|
||||
> label-x-"silo_name"
|
||||
>> "silo_name"
|
||||
> label-y-"silo_name"
|
||||
>> "silo_name"
|
||||
> "silo_name"
|
||||
>> label
|
||||
]]
|
||||
local function generate_progress(player,frame)
|
||||
if not config.progress.show_progress then return end
|
||||
local element = frame.container.progress.table
|
||||
local force = player.force
|
||||
local force_name = force.name
|
||||
local force_silos = Rockets.get_silos(force_name)
|
||||
|
||||
if not force_silos or table.size(force_silos) == 0 then
|
||||
element.parent.no_silos.visible = true
|
||||
|
||||
else
|
||||
element.parent.no_silos.visible = false
|
||||
|
||||
for _,silo_data in pairs(force_silos) do
|
||||
local silo_name = silo_data.name
|
||||
if not silo_data.entity or not silo_data.entity.valid then
|
||||
force_silos[silo_name] = nil
|
||||
Gui.destroy_if_valid(element['toggle-'..silo_name])
|
||||
Gui.destroy_if_valid(element['launch-'..silo_name])
|
||||
Gui.destroy_if_valid(element['label-x-'..silo_name])
|
||||
Gui.destroy_if_valid(element['label-y-'..silo_name])
|
||||
Gui.destroy_if_valid(element[silo_name])
|
||||
|
||||
elseif not element[silo_name] then
|
||||
local entity = silo_data.entity
|
||||
local progress = entity.rocket_parts
|
||||
local pos = {
|
||||
x=entity.position.x,
|
||||
y=entity.position.y
|
||||
}
|
||||
|
||||
generate_progress_buttons(player,element,silo_data)
|
||||
|
||||
--- Creates two flows and two labels for the X and Y position
|
||||
local name = config.progress.allow_zoom_to_map and zoom_to_map_name or nil
|
||||
local tooltip = config.progress.allow_zoom_to_map and {'rocket-info.progress-label-tooltip'} or nil
|
||||
local flow_x = element.add{
|
||||
type='flow',
|
||||
name='label-x-'..silo_name,
|
||||
caption=silo_name
|
||||
}
|
||||
Gui.set_padding(flow_x,0,0,1,2)
|
||||
flow_x.add{
|
||||
type='label',
|
||||
name=name,
|
||||
caption={'rocket-info.progress-x-pos',pos.x},
|
||||
tooltip=tooltip
|
||||
}
|
||||
|
||||
local flow_y = element.add{
|
||||
type='flow',
|
||||
name='label-y-'..silo_name,
|
||||
caption=silo_name
|
||||
}
|
||||
Gui.set_padding(flow_y,0,0,1,2)
|
||||
flow_y.add{
|
||||
type='label',
|
||||
name=name,
|
||||
caption={'rocket-info.progress-y-pos',pos.y},
|
||||
tooltip=tooltip
|
||||
}
|
||||
|
||||
--- Creates the progress value which is right aligned
|
||||
local right_flow = Gui.create_alignment(element,silo_name)
|
||||
right_flow.add{
|
||||
type='label',
|
||||
name='label',
|
||||
caption={'rocket-info.progress-caption',progress},
|
||||
tooltip={'rocket-info.progress-tooltip',silo_data.launched or 0}
|
||||
}
|
||||
|
||||
else
|
||||
local entity = silo_data.entity
|
||||
local progress = entity.rocket_parts
|
||||
local status = entity.status == 21
|
||||
|
||||
local label = element[silo_name].label
|
||||
label.caption = {'rocket-info.progress-caption',progress}
|
||||
label.tooltip = {'rocket-info.progress-tooltip',silo_data.launched or 0}
|
||||
|
||||
if status and silo_data.awaiting_reset then
|
||||
label.caption = {'rocket-info.progress-launched'}
|
||||
label.style.font_color = Colors.green
|
||||
elseif status then
|
||||
label.caption = {'rocket-info.progress-caption',100}
|
||||
label.style.font_color = Colors.cyan
|
||||
else
|
||||
silo_data.awaiting_reset = false
|
||||
label.style.font_color = Colors.white
|
||||
end
|
||||
|
||||
generate_progress_buttons(player,element,silo_data)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
--- Registers the rocket info
|
||||
-- @element rocket_info
|
||||
local rocket_info =
|
||||
Gui.new_left_frame('gui/rocket-info')
|
||||
:set_sprites('entity/rocket-silo')
|
||||
:set_post_authenticator(function(player,define_name)
|
||||
return player.force.rockets_launched > 0 and Gui.classes.toolbar.allowed(player,define_name)
|
||||
end)
|
||||
:set_open_by_default(function(player,define_name)
|
||||
return player.force.rockets_launched > 0
|
||||
end)
|
||||
:set_direction('vertical')
|
||||
:on_creation(function(player,element)
|
||||
generate_container(player,element)
|
||||
generate_stats(player,element)
|
||||
generate_milestones(player,element)
|
||||
generate_progress(player,element)
|
||||
end)
|
||||
:on_update(function(player,element)
|
||||
generate_stats(player,element)
|
||||
generate_milestones(player,element)
|
||||
generate_progress(player,element)
|
||||
end)
|
||||
|
||||
--- Event used to update the stats and the hui when a rocket is launched
|
||||
--- Event used to update the stats when a rocket is launched
|
||||
Event.add(defines.events.on_rocket_launched,function(event)
|
||||
local force = event.rocket_silo.force
|
||||
local rockets_launched = force.rockets_launched
|
||||
local first_rocket = rockets_launched == 1
|
||||
update_rocket_gui_all(force.name)
|
||||
if force.rockets_launched == 1 then
|
||||
for _,player in pairs(force.players) do
|
||||
Gui.update_top_flow(player)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
--- Updates all the guis (and toolbar since the button may now be visible)
|
||||
for _,player in pairs(force.players) do
|
||||
rocket_info:update(player)
|
||||
if first_rocket then
|
||||
Gui.update_toolbar(player)
|
||||
rocket_info:toggle(player)
|
||||
end
|
||||
end
|
||||
--- Update only the progress gui for a force
|
||||
local function update_rocket_gui_progress(force_name)
|
||||
local progress = get_progress_data(force_name)
|
||||
for _,player in pairs(game.forces[force_name].players) do
|
||||
local frame = Gui.get_left_element(player,rocket_list_container)
|
||||
local container = frame.container
|
||||
update_build_progress(container.progress.table,progress)
|
||||
end
|
||||
end
|
||||
|
||||
Event.on_nth_tick(150,function()
|
||||
for _,force in pairs(game.forces) do
|
||||
if #Rockets.get_silos(force.name) > 0 then
|
||||
update_rocket_gui_progress(force.name)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
--- Adds a silo to the list when it is built
|
||||
local function on_built(event)
|
||||
local entity = event.created_entity
|
||||
if entity.valid and entity.name == 'rocket-silo' then
|
||||
local force = entity.force
|
||||
|
||||
for _,player in pairs(force.players) do
|
||||
local frame = rocket_info:get_frame(player)
|
||||
generate_progress(player,frame)
|
||||
end
|
||||
update_rocket_gui_progress(entity.force.name)
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_built_entity,on_built)
|
||||
Event.add(defines.events.on_robot_built_entity,on_built)
|
||||
|
||||
--- Optimised update for only the build progress
|
||||
Event.on_nth_tick(150,function()
|
||||
for _,force in pairs(game.forces) do
|
||||
local silos = Rockets.get_silos(force.name)
|
||||
if #silos > 0 then
|
||||
for _,player in pairs(force.connected_players) do
|
||||
local frame = rocket_info:get_frame(player)
|
||||
generate_progress(player,frame)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
--- Redraw the progress section on role change
|
||||
local function role_update_event(event)
|
||||
local player = game.players[event.player_index]
|
||||
local container = Gui.get_left_element(player,rocket_list_container).container
|
||||
local progress = container.progress
|
||||
if config.progress.show_progress then
|
||||
progress.destroy()
|
||||
local col_count = 3
|
||||
if check_player_permissions(player,'remote_launch') then col_count = col_count+1 end
|
||||
if check_player_permissions(player,'toggle_active') then col_count = col_count+1 end
|
||||
progress = section(container,'progress',col_count)
|
||||
-- Label used when there are no active silos
|
||||
progress.add{
|
||||
type = 'label',
|
||||
name = 'no_silos',
|
||||
caption = {'rocket-info.progress-no-silos'}
|
||||
}
|
||||
update_build_progress(progress,get_progress_data(player.force.name))
|
||||
end
|
||||
end
|
||||
|
||||
--- Makes sure the right buttons are present when role changes
|
||||
Event.add(Roles.events.on_role_assigned,rocket_info 'redraw')
|
||||
Event.add(Roles.events.on_role_unassigned,rocket_info 'redraw')
|
||||
Event.add(Roles.events.on_role_assigned,role_update_event)
|
||||
Event.add(Roles.events.on_role_unassigned,role_update_event)
|
||||
|
||||
return rocket_info
|
||||
return rocket_list_container
|
||||
@@ -5,6 +5,7 @@
|
||||
]]
|
||||
|
||||
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 format_time = ext_require('expcore.common','format_time') --- @dep expcore.common
|
||||
local config = require 'config.science' --- @dep config.science
|
||||
@@ -13,275 +14,360 @@ local Production = require 'modules.control.production' --- @dep modules.control
|
||||
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})
|
||||
|
||||
--[[ Generates the main structure for the gui
|
||||
element
|
||||
> container
|
||||
>> header
|
||||
>> scroll
|
||||
>>> non_made
|
||||
>>> table
|
||||
>> footer (when eta is enabled)
|
||||
>>> eta-label
|
||||
>>> eta
|
||||
>>>> label
|
||||
]]
|
||||
local function generate_container(element)
|
||||
Gui.set_padding(element,1,2,2,2)
|
||||
element.style.minimal_width = 200
|
||||
--- 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
|
||||
|
||||
-- main container which contains the other elements
|
||||
local container =
|
||||
element.add{
|
||||
name='container',
|
||||
type='frame',
|
||||
direction='vertical',
|
||||
style='window_content_frame_packed'
|
||||
-- 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
|
||||
}
|
||||
Gui.set_padding(container)
|
||||
|
||||
-- main header for the gui
|
||||
Gui.create_header(
|
||||
container,
|
||||
{'science-info.main-caption'},
|
||||
{'science-info.main-tooltip'}
|
||||
)
|
||||
-- Change the style
|
||||
element.style.font_color = color
|
||||
|
||||
-- table that stores all the data
|
||||
local flow_table = Gui.create_scroll_table(container,4,185)
|
||||
|
||||
-- message to say that you have not made any packs yet
|
||||
local non_made =
|
||||
flow_table.parent.add{
|
||||
name='non_made',
|
||||
type='label',
|
||||
caption={'science-info.no-packs'}
|
||||
-- Add the surfix label
|
||||
local surfix_element =
|
||||
parent.add{
|
||||
name = 'surfix-'..name,
|
||||
type = 'label',
|
||||
caption = {'science-info.unit',production_label_data.surfix},
|
||||
tooltip = tooltip
|
||||
}
|
||||
non_made.style.width = 200
|
||||
non_made.style.single_line = false
|
||||
|
||||
local eta
|
||||
if config.show_eta then
|
||||
-- footer used to store the eta
|
||||
local footer =
|
||||
container.add{
|
||||
name='footer',
|
||||
type='frame',
|
||||
style='subheader_frame'
|
||||
}
|
||||
Gui.set_padding(footer,2,2,4,4)
|
||||
footer.style.horizontally_stretchable = true
|
||||
-- Change the style
|
||||
local surfix_element_style = surfix_element.style
|
||||
surfix_element_style.font_color = color
|
||||
surfix_element_style.right_margin = 1
|
||||
|
||||
-- label for the footer
|
||||
footer.add{
|
||||
name='eta-label',
|
||||
type='label',
|
||||
caption={'science-info.eta-caption'},
|
||||
tooltip={'science-info.eta-tooltip'},
|
||||
style='heading_1_label'
|
||||
}
|
||||
-- Return the value label
|
||||
return element
|
||||
end)
|
||||
|
||||
-- data for the footer
|
||||
local right_align = Gui.create_alignment(footer,'eta')
|
||||
eta =
|
||||
right_align.add{
|
||||
name='label',
|
||||
type='label',
|
||||
caption=null_time_short,
|
||||
tooltip=null_time_long,
|
||||
style='heading_1_label'
|
||||
}
|
||||
end
|
||||
|
||||
return flow_table, eta
|
||||
end
|
||||
|
||||
--[[ Adds two labels where one is right aligned and the other is a unit
|
||||
element
|
||||
> "name"
|
||||
>> label
|
||||
> spm-"name"
|
||||
]]
|
||||
local function add_data_label(element,name,value,secondary,tooltip)
|
||||
-- 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)
|
||||
|
||||
if element[name] then
|
||||
local data = element[name].label
|
||||
data.caption = caption
|
||||
data.tooltip = tooltip
|
||||
data.style.font_color = data_colour
|
||||
local label = element['spm-'..name]
|
||||
label.caption = {'science-info.unit',surfix}
|
||||
label.tooltip = tooltip
|
||||
label.style.font_color = data_colour
|
||||
|
||||
else
|
||||
-- right aligned number
|
||||
local right_align = Gui.create_alignment(element,name)
|
||||
local data =
|
||||
right_align.add{
|
||||
name='label',
|
||||
type='label',
|
||||
caption=caption,
|
||||
tooltip=tooltip
|
||||
}
|
||||
data.style.font_color = data_colour
|
||||
|
||||
-- adds the unit onto the end
|
||||
local label =
|
||||
element.add{
|
||||
name='spm-'..name,
|
||||
type='label',
|
||||
caption={'science-info.unit',surfix},
|
||||
tooltip=tooltip
|
||||
}
|
||||
label.style.font_color = data_colour
|
||||
end
|
||||
return {
|
||||
name = name,
|
||||
caption = caption,
|
||||
surfix = surfix,
|
||||
tooltip = tooltip,
|
||||
color = data_colour
|
||||
}
|
||||
end
|
||||
|
||||
--[[ Adds a science pack to the list
|
||||
element
|
||||
> icon-"science_pack"
|
||||
> delta-"science_pack"
|
||||
>> table
|
||||
>>> pos-"science_pack" (add_data_label)
|
||||
>>> neg-"science_pack" (add_data_label)
|
||||
> net-"science_pack" (add_data_label)
|
||||
]]
|
||||
local function generate_science_pack(player,element,science_pack)
|
||||
local total = Production.get_production_total(player.force, science_pack)
|
||||
local minute = Production.get_production(player.force, science_pack, defines.flow_precision_index.one_minute)
|
||||
if total.made > 0 then
|
||||
element.parent.non_made.visible = false
|
||||
-- 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
|
||||
|
||||
local icon_style = 'quick_bar_slot_button'
|
||||
local flux = Production.get_fluctuations(player.force, science_pack, defines.flow_precision_index.one_minute)
|
||||
if flux.net > -config.color_flux/2 then
|
||||
icon_style = 'green_slot_button'
|
||||
elseif flux.net < -config.color_flux then
|
||||
icon_style = 'red_slot_button'
|
||||
elseif minute.made > 0 then
|
||||
icon_style = 'selected_slot_button'
|
||||
end
|
||||
-- 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
|
||||
|
||||
local icon = element['icon-'..science_pack]
|
||||
-- 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
|
||||
|
||||
if icon then
|
||||
icon.style = icon_style
|
||||
icon.style.height = 55
|
||||
if icon_style == 'quick_bar_slot_button' then
|
||||
icon.style.width = 36
|
||||
Gui.set_padding(icon,0,0,-2,-2)
|
||||
end
|
||||
|
||||
else
|
||||
icon =
|
||||
element.add{
|
||||
name='icon-'..science_pack,
|
||||
type='sprite-button',
|
||||
sprite='item/'..science_pack,
|
||||
tooltip={'item-name.'..science_pack},
|
||||
style=icon_style
|
||||
}
|
||||
icon.style.height = 55
|
||||
if icon_style == 'quick_bar_slot_button' then
|
||||
icon.style.width = 36
|
||||
Gui.set_padding(icon,0,0,-2,-2)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local delta = element['delta-'..science_pack]
|
||||
|
||||
if not delta then
|
||||
delta =
|
||||
element.add{
|
||||
name='delta-'..science_pack,
|
||||
type='frame',
|
||||
style='bordered_frame'
|
||||
}
|
||||
Gui.set_padding(delta,0,0,3,3)
|
||||
|
||||
local delta_table =
|
||||
delta.add{
|
||||
name='table',
|
||||
type='table',
|
||||
column_count=2
|
||||
}
|
||||
Gui.set_padding(delta_table)
|
||||
end
|
||||
|
||||
add_data_label(delta.table,'pos-'..science_pack,minute.made,nil,{'science-info.pos-tooltip',total.made})
|
||||
add_data_label(delta.table,'neg-'..science_pack,-minute.used,nil,{'science-info.neg-tooltip',total.used})
|
||||
add_data_label(element,'net-'..science_pack,minute.net,minute.made+minute.used,{'science-info.net-tooltip',total.net})
|
||||
end
|
||||
end
|
||||
|
||||
--- Updates the eta label that was created with generate_container
|
||||
local function update_eta(player,element)
|
||||
if not config.show_eta then return 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_style.height = 55
|
||||
if icon_style == 'quick_bar_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 = 'quick_bar_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 = 'green_slot_button'
|
||||
elseif flux.net < -config.color_flux then
|
||||
icon_style = 'red_slot_button'
|
||||
elseif minute.made > 0 then
|
||||
icon_style = 'selected_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 == 'quick_bar_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
|
||||
element.caption = null_time_short
|
||||
element.tooltip = null_time_long
|
||||
return { research = false }
|
||||
end
|
||||
|
||||
else
|
||||
local progress = force.research_progress
|
||||
local remaining = research.research_unit_count*(1-progress)
|
||||
local limit
|
||||
|
||||
local stats = player.force.item_production_statistics
|
||||
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
|
||||
|
||||
if not limit or limit == -1 then
|
||||
element.caption = null_time_short
|
||||
element.tooltip = null_time_long
|
||||
|
||||
else
|
||||
element.caption = {'science-info.eta-time',format_time(limit,{hours=true,minutes=true,seconds=true,time=true})}
|
||||
element.tooltip = format_time(limit,{hours=true,minutes=true,seconds=true,long=true})
|
||||
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
|
||||
|
||||
--- Registers the science info
|
||||
-- @element science_info
|
||||
local science_info =
|
||||
Gui.new_left_frame('gui/science-info')
|
||||
:set_sprites('entity/lab')
|
||||
:set_direction('vertical')
|
||||
:set_tooltip{'science-info.main-tooltip'}
|
||||
:on_creation(function(player,element)
|
||||
local table, eta = generate_container(element)
|
||||
|
||||
for _,science_pack in ipairs(config) do
|
||||
generate_science_pack(player,table,science_pack)
|
||||
-- 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_eta(player,eta)
|
||||
-- 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)
|
||||
:on_update(function(player,element)
|
||||
local container = element.container
|
||||
local table = container.scroll.table
|
||||
local eta = container.footer.eta.label
|
||||
:add_to_left_flow()
|
||||
|
||||
for _,science_pack in ipairs(config) do
|
||||
generate_science_pack(player,table,science_pack)
|
||||
end
|
||||
|
||||
update_eta(player,eta)
|
||||
--- 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,science_info 'update_all')
|
||||
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
|
||||
|
||||
return science_info
|
||||
-- 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)
|
||||
@@ -1,5 +1,5 @@
|
||||
--[[-- Gui Module - Task List
|
||||
- Adds a task list to the game which players can add remove and edit items on
|
||||
- Adds a task list to the game which players can add, remove and edit items on
|
||||
@gui Task-List
|
||||
@alias task_list
|
||||
]]
|
||||
@@ -11,338 +11,406 @@ local config = require 'config.tasks' --- @dep config.tasks
|
||||
local format_time,table_keys = ext_require('expcore.common','format_time','table_keys') --- @dep expcore.common
|
||||
local Tasks = require 'modules.control.tasks' --- @dep modules.control.tasks
|
||||
|
||||
-- Styles used for sprite buttons
|
||||
local Styles = {
|
||||
sprite20 = Gui.sprite_style(20),
|
||||
sprite22 = Gui.sprite_style(20, nil, { right_margin = -3 })
|
||||
}
|
||||
|
||||
--- If a player is allowed to use the edit buttons
|
||||
local function player_allowed_edit(player,task)
|
||||
local function check_player_permissions(player,task)
|
||||
if task then
|
||||
-- When a task is given check if the player can edit it
|
||||
local allow_edit_task = config.allow_edit_task
|
||||
|
||||
-- Check if the player being the last to edit will override existing permisisons
|
||||
if config.user_can_edit_own_tasks and task.last_edit_name == player.name then
|
||||
return true
|
||||
end
|
||||
else
|
||||
if config.any_user_can_add_new_task then
|
||||
|
||||
-- Check player has permisison based on value in the config
|
||||
if allow_edit_task == 'all' then
|
||||
return true
|
||||
elseif allow_edit_task == 'admin' then
|
||||
return player.admin
|
||||
elseif allow_edit_task == 'expcore.roles' then
|
||||
return Roles.player_allowed(player,config.edit_tasks_role_permission)
|
||||
end
|
||||
end
|
||||
|
||||
if config.only_admins_can_edit and not player.admin then
|
||||
-- Return false as all other condidtions have not been met
|
||||
return false
|
||||
else
|
||||
-- When a task is not given check if the player can add a new task
|
||||
local allow_add_task = config.allow_add_task
|
||||
|
||||
-- Check player has permisison based on value in the config
|
||||
if allow_add_task == 'all' then
|
||||
return true
|
||||
elseif allow_add_task == 'admin' then
|
||||
return player.admin
|
||||
elseif allow_add_task == 'expcore.roles' then
|
||||
return Roles.player_allowed(player,config.expcore_roles_add_permission)
|
||||
end
|
||||
|
||||
-- Return false as all other condidtions have not been met
|
||||
return false
|
||||
end
|
||||
|
||||
if config.edit_tasks_role_permission and not Roles.player_allowed(player,config.edit_tasks_role_permission) then
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--- Button in the header to add a new task
|
||||
--- Button displayed in the ehader bar, used to add a new task
|
||||
-- @element add_new_task
|
||||
local add_new_task =
|
||||
Gui.new_button()
|
||||
:set_sprites('utility/add')
|
||||
:set_tooltip{'task-list.add-tooltip'}
|
||||
:set_style('tool_button',function(style)
|
||||
Gui.set_padding_style(style,-2,-2,-2,-2)
|
||||
style.height = 20
|
||||
style.width = 20
|
||||
end)
|
||||
:on_click(function(player,element)
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/add',
|
||||
tooltip = {'task-list.add-tooltip'},
|
||||
style = 'tool_button'
|
||||
}
|
||||
:style(Styles.sprite20)
|
||||
:on_click(function(player,_,_)
|
||||
Tasks.add_task(player.force.name,nil,player.name)
|
||||
end)
|
||||
|
||||
--- Used to save changes to a task
|
||||
-- @element confirm_edit
|
||||
local confirm_edit =
|
||||
Gui.new_button()
|
||||
:set_sprites('utility/downloaded')
|
||||
:set_tooltip{'task-list.confirm-tooltip'}
|
||||
:set_style('tool_button',function(style)
|
||||
Gui.set_padding_style(style,-2,-2,-2,-2)
|
||||
style.height = 20
|
||||
style.width = 20
|
||||
--- Button displayed next to tasks which the user is can edit, used to start editing a task
|
||||
-- @element edit_task
|
||||
local edit_task =
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/rename_icon_normal',
|
||||
tooltip = {'task-list.edit-tooltip-none'},
|
||||
style = 'tool_button'
|
||||
}
|
||||
:style(Styles.sprite20)
|
||||
:on_click(function(player,element,_)
|
||||
local task_id = element.parent.name:sub(6)
|
||||
Tasks.set_editing(task_id,player.name,true)
|
||||
end)
|
||||
:on_click(function(player,element)
|
||||
|
||||
--- Button displayed next to tasks which the user is can edit, used to delete a task from the list
|
||||
-- @element discard_task
|
||||
local discard_task =
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/trash',
|
||||
tooltip = {'task-list.discard-tooltip'},
|
||||
style = 'tool_button'
|
||||
}
|
||||
:style(Styles.sprite20)
|
||||
:on_click(function(_,element,_)
|
||||
local task_id = element.parent.name:sub(6)
|
||||
Tasks.remove_task(task_id)
|
||||
end)
|
||||
|
||||
--- Set of three elements which make up each row of the task table
|
||||
-- @element add_task_base
|
||||
local add_task_base =
|
||||
Gui.element(function(_,parent,task_id)
|
||||
-- Add the task number label
|
||||
local task_number = parent.add{
|
||||
name = 'count-'..task_id,
|
||||
type = 'label',
|
||||
caption = '0)'
|
||||
}
|
||||
task_number.style.left_margin = 1
|
||||
|
||||
-- Add a flow which will contain the task message and edit buttons
|
||||
local task_flow = parent.add{ name = task_id, type = 'flow', }
|
||||
task_flow.style.padding = 0
|
||||
|
||||
-- Add the two edit buttons outside the task flow
|
||||
local edit_flow = Gui.alignment(parent,'edit-'..task_id)
|
||||
edit_task(edit_flow)
|
||||
discard_task(edit_flow)
|
||||
|
||||
-- Return the task flow as the main element
|
||||
return task_flow
|
||||
end)
|
||||
|
||||
-- Removes the three elements that are added as part of the task base
|
||||
local function remove_task_base(parent,task_id)
|
||||
Gui.destroy_if_valid(parent['count-'..task_id])
|
||||
Gui.destroy_if_valid(parent['edit-'..task_id])
|
||||
Gui.destroy_if_valid(parent[task_id])
|
||||
end
|
||||
|
||||
--- Button displayed next to tasks which the user is currently editing, used to save changes
|
||||
-- @element confirm_edit
|
||||
local task_editing
|
||||
local confirm_edit =
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/downloaded',
|
||||
tooltip = {'task-list.confirm-tooltip'},
|
||||
style = 'shortcut_bar_button_green'
|
||||
}
|
||||
:style(Styles.sprite22)
|
||||
:on_click(function(player,element,_)
|
||||
local task_id = element.parent.name
|
||||
local new_message = element.parent.task.text
|
||||
local new_message = element.parent[task_editing.name].text
|
||||
Tasks.set_editing(task_id,player.name)
|
||||
Tasks.update_task(task_id,new_message,player.name)
|
||||
end)
|
||||
|
||||
--- Used to cancel any changes you made to a task
|
||||
--- Button displayed next to tasks which the user is currently editing, used to discard changes
|
||||
-- @element cancel_edit
|
||||
local cancel_edit =
|
||||
Gui.new_button()
|
||||
:set_sprites('utility/close_black')
|
||||
:set_tooltip{'task-list.cancel-tooltip'}
|
||||
:set_style('tool_button',function(style)
|
||||
Gui.set_padding_style(style,-2,-2,-2,-2)
|
||||
style.height = 20
|
||||
style.width = 20
|
||||
end)
|
||||
:on_click(function(player,element)
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/close_black',
|
||||
tooltip = {'task-list.cancel-tooltip'},
|
||||
style = 'shortcut_bar_button_red'
|
||||
}
|
||||
:style(Styles.sprite22)
|
||||
:on_click(function(player,element,_)
|
||||
local task_id = element.parent.name
|
||||
Tasks.set_editing(task_id,player.name)
|
||||
end)
|
||||
|
||||
--- Removes the task from the list
|
||||
-- @element discard_task
|
||||
local discard_task =
|
||||
Gui.new_button()
|
||||
:set_sprites('utility/trash')
|
||||
:set_tooltip{'task-list.discard-tooltip'}
|
||||
:set_style('tool_button',function(style)
|
||||
Gui.set_padding_style(style,-2,-2,-2,-2)
|
||||
style.height = 20
|
||||
style.width = 20
|
||||
--- Editing state for a task, contrins a text field and the two edit buttons
|
||||
-- @element task_editing
|
||||
task_editing =
|
||||
Gui.element(function(event_trigger,parent,task)
|
||||
local message = task.message
|
||||
|
||||
-- Draw the element
|
||||
local element =
|
||||
parent.add{
|
||||
name = event_trigger,
|
||||
type = 'textfield',
|
||||
text = message,
|
||||
clear_and_focus_on_right_click = true
|
||||
}
|
||||
|
||||
-- Add the edit buttons
|
||||
cancel_edit(parent)
|
||||
confirm_edit(parent)
|
||||
|
||||
-- Return the element
|
||||
return element
|
||||
end)
|
||||
:on_click(function(player,element)
|
||||
:style{
|
||||
maximal_width = 110,
|
||||
height = 20
|
||||
}
|
||||
:on_confirmed(function(player,element,_)
|
||||
local task_id = element.parent.name
|
||||
Tasks.remove_task(task_id)
|
||||
local new_message = element.text
|
||||
Tasks.set_editing(task_id,player.name)
|
||||
Tasks.update_task(task_id,new_message,player.name)
|
||||
end)
|
||||
|
||||
--- Opens edit mode for the task
|
||||
-- @element edit_task
|
||||
local edit_task =
|
||||
Gui.new_button()
|
||||
:set_sprites('utility/rename_icon_normal')
|
||||
:set_tooltip{'task-list.edit-tooltip-none'}
|
||||
:set_style('tool_button',function(style)
|
||||
Gui.set_padding_style(style,-2,-2,-2,-2)
|
||||
style.height = 20
|
||||
style.width = 20
|
||||
end)
|
||||
:on_click(function(player,element)
|
||||
local task_id = element.parent.name
|
||||
Tasks.set_editing(task_id,player.name,true)
|
||||
--- Default state for a task, contains only a label with the task message
|
||||
-- @element task_label
|
||||
local task_label =
|
||||
Gui.element(function(_,parent,task)
|
||||
local message = task.message
|
||||
local last_edit_name = task.last_edit_name
|
||||
local last_edit_time = task.last_edit_time
|
||||
-- Draw the element
|
||||
return parent.add{
|
||||
name = task_editing.name,
|
||||
type = 'label',
|
||||
caption = message,
|
||||
tooltip = {'task-list.last-edit', last_edit_name, format_time(last_edit_time)}
|
||||
}
|
||||
end)
|
||||
:style{
|
||||
single_line = false,
|
||||
maximal_width = 150
|
||||
}
|
||||
|
||||
--[[ Generates each task, handles both view and edit mode
|
||||
element
|
||||
> count-"task_id"
|
||||
>> label
|
||||
> "task_id"
|
||||
>> task
|
||||
>> cancel_edit (edit mode)
|
||||
>> confirm_edit (edit mode)
|
||||
> edit-"task_id"
|
||||
>> edit_task
|
||||
>> discard_task
|
||||
]]
|
||||
local function generate_task(player,element,task_id)
|
||||
--- Updates a task for a player
|
||||
local function update_task(player,task_table,task_id)
|
||||
local task = Tasks.get_task(task_id)
|
||||
local task_ids = Tasks.get_force_task_ids(player.force.name)
|
||||
local task_number = table.index_of(task_ids, task_id)
|
||||
|
||||
-- Task no longer exists so should be removed from the list
|
||||
if not task then
|
||||
-- task is nil so remove it from the list
|
||||
element.parent.no_tasks.visible = #task_ids == 1
|
||||
Gui.destroy_if_valid(element['count-'..task_id])
|
||||
Gui.destroy_if_valid(element['edit-'..task_id])
|
||||
Gui.destroy_if_valid(element[task_id])
|
||||
|
||||
else
|
||||
local message = task.message
|
||||
local editing = task.curently_editing[player.name]
|
||||
local last_edit_name = task.last_edit_name
|
||||
local last_edit_time = task.last_edit_time
|
||||
|
||||
element.parent.no_tasks.visible = false
|
||||
-- if it is not already present then add it now
|
||||
local task_area = element[task_id]
|
||||
if not task_area then
|
||||
-- label to show the task number
|
||||
element.add{
|
||||
name='count-'..task_id,
|
||||
type='label',
|
||||
caption=task_number..')'
|
||||
}
|
||||
|
||||
-- area which stores the task and buttons
|
||||
task_area =
|
||||
element.add{
|
||||
name=task_id,
|
||||
type='flow',
|
||||
}
|
||||
Gui.set_padding(task_area)
|
||||
|
||||
-- if the player can edit then it adds the edit and delete button
|
||||
local flow = Gui.create_alignment(element,'edit-'..task_id)
|
||||
local sub_flow = flow.add{type='flow',name=task_id}
|
||||
|
||||
edit_task(sub_flow)
|
||||
discard_task(sub_flow)
|
||||
|
||||
end
|
||||
|
||||
-- update the number indexes and the current editing players
|
||||
element['count-'..task_id].caption = task_number..')'
|
||||
|
||||
local edit_area = element['edit-'..task_id][task_id]
|
||||
local players = table_keys(task.editing)
|
||||
local allowed = player_allowed_edit(player,task)
|
||||
|
||||
edit_area.visible = allowed
|
||||
|
||||
if #players > 0 then
|
||||
edit_area[edit_task.name].tooltip = {'task-list.edit-tooltip',table.concat(players,', ')}
|
||||
else
|
||||
edit_area[edit_task.name].tooltip = {'task-list.edit-tooltip-none'}
|
||||
end
|
||||
|
||||
-- draws/updates the task area
|
||||
local element_type = task_area.task and task_area.task.type or nil
|
||||
if not editing and element_type == 'label' then
|
||||
-- update the label already present
|
||||
task_area.task.caption = message
|
||||
task_area.task.tooltip = {'task-list.last-edit',last_edit_name,format_time(last_edit_time)}
|
||||
|
||||
elseif not editing then
|
||||
-- create the label, view mode
|
||||
if edit_area then
|
||||
edit_area[edit_task.name].enabled = true
|
||||
end
|
||||
|
||||
task_area.clear()
|
||||
|
||||
local label =
|
||||
task_area.add{
|
||||
name='task',
|
||||
type='label',
|
||||
caption=message,
|
||||
tooltip={'task-list.last-edit',last_edit_name,format_time(last_edit_time)}
|
||||
}
|
||||
label.style.single_line = false
|
||||
label.style.maximal_width = 150
|
||||
|
||||
elseif editing and element_type ~= 'textfield' then
|
||||
-- create the text field, edit mode, update it omitted as value is being edited
|
||||
if edit_area then
|
||||
edit_area[edit_task.name].enabled = false
|
||||
end
|
||||
|
||||
task_area.clear()
|
||||
|
||||
local entry =
|
||||
task_area.add{
|
||||
name='task',
|
||||
type='textfield',
|
||||
text=message
|
||||
}
|
||||
entry.style.maximal_width = 150
|
||||
entry.style.height = 20
|
||||
|
||||
cancel_edit(task_area)
|
||||
confirm_edit(task_area)
|
||||
|
||||
end
|
||||
|
||||
task_table.parent.no_tasks.visible = #task_ids == 0
|
||||
remove_task_base(task_table,task_id)
|
||||
return
|
||||
end
|
||||
|
||||
-- Get the task flow for this task
|
||||
local task_flow = task_table[task_id] or add_task_base(task_table,task_id)
|
||||
task_table.parent.no_tasks.visible = false
|
||||
task_table['count-'..task_id].caption = task_number..')'
|
||||
|
||||
-- Update the edit flow
|
||||
local edit_flow = task_table['edit-'..task_id]
|
||||
local player_allowed_edit = check_player_permissions(player,task)
|
||||
local players_editing = table_keys(task.curently_editing)
|
||||
local edit_task_element = edit_flow[edit_task.name]
|
||||
local discard_task_element = edit_flow[discard_task.name]
|
||||
|
||||
edit_task_element.visible = player_allowed_edit
|
||||
discard_task_element.visible = player_allowed_edit
|
||||
if #players_editing > 0 then
|
||||
edit_task_element.hovered_sprite = 'utility/warning_icon'
|
||||
edit_task_element.tooltip = {'task-list.edit-tooltip',table.concat(players_editing,', ')}
|
||||
else
|
||||
edit_task_element.hovered_sprite = edit_task_element.sprite
|
||||
edit_task_element.tooltip = {'task-list.edit-tooltip-none'}
|
||||
end
|
||||
|
||||
-- Check if the player is was editing and/or currently editing
|
||||
local task_entry = task_flow[task_editing.name] or task_label(task_flow,task)
|
||||
local player_was_editing = task_entry.type == 'textfield'
|
||||
local player_is_editing = task.curently_editing[player.name]
|
||||
|
||||
-- Update the task flow
|
||||
if not player_was_editing and not player_is_editing then
|
||||
-- Update the task message label
|
||||
local message = task.message
|
||||
local last_edit_name = task.last_edit_name
|
||||
local last_edit_time = task.last_edit_time
|
||||
task_entry.caption = message
|
||||
task_entry.tooltip = {'task-list.last-edit', last_edit_name, format_time(last_edit_time)}
|
||||
|
||||
elseif player_was_editing and not player_is_editing then
|
||||
-- Player was editing but is no longer, remove text field and add label
|
||||
edit_task_element.enabled = true
|
||||
task_flow.clear()
|
||||
task_label(task_flow,task)
|
||||
|
||||
elseif not player_was_editing and player_is_editing then
|
||||
-- Player was not editing but now is, remove label and add text field
|
||||
edit_task_element.enabled = false
|
||||
task_flow.clear()
|
||||
task_editing(task_flow,task).focus()
|
||||
task_table.parent.scroll_to_element(task_flow,'top-third')
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
--[[ generates the main gui structure
|
||||
element
|
||||
> container
|
||||
>> header
|
||||
>>> right aligned add_new_task
|
||||
>> scroll
|
||||
>>> no_tasks
|
||||
>>> table
|
||||
]]
|
||||
local function generate_container(player,element)
|
||||
Gui.set_padding(element,2,2,2,2)
|
||||
element.style.minimal_width = 200
|
||||
-- Update all the tasks for a player
|
||||
local function update_all_tasks(player,scroll_table)
|
||||
local task_ids = Tasks.get_force_task_ids(player.force.name)
|
||||
if #task_ids > 0 then
|
||||
for _,task_id in ipairs(task_ids) do
|
||||
update_task(player,scroll_table,task_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- main container which contains the other elements
|
||||
local container =
|
||||
element.add{
|
||||
name='container',
|
||||
type='frame',
|
||||
direction='vertical',
|
||||
style='window_content_frame_packed'
|
||||
}
|
||||
Gui.set_padding(container)
|
||||
container.style.vertically_stretchable = false
|
||||
--- Main task list container for the left flow
|
||||
-- @element task_list_container
|
||||
local task_list_container =
|
||||
Gui.element(function(event_trigger,parent)
|
||||
-- Draw the internal container
|
||||
local container = Gui.container(parent,event_trigger,200)
|
||||
|
||||
-- main header for the gui
|
||||
local header_area = Gui.create_header(
|
||||
-- Draw the header
|
||||
local header = Gui.header(
|
||||
container,
|
||||
{'task-list.main-caption'},
|
||||
{'task-list.sub-tooltip'},
|
||||
true
|
||||
)
|
||||
|
||||
--- Right aligned button to toggle the section
|
||||
if player_allowed_edit(player) then
|
||||
add_new_task(header_area)
|
||||
end
|
||||
-- Draw the new task button
|
||||
local player = Gui.get_player_from_element(parent)
|
||||
local add_new_task_element = add_new_task(header)
|
||||
add_new_task_element.visible = check_player_permissions(player)
|
||||
|
||||
-- table that stores all the data
|
||||
local flow_table = Gui.create_scroll_table(container,3,185)
|
||||
flow_table.draw_horizontal_lines = true
|
||||
flow_table.vertical_centering = false
|
||||
flow_table.style.top_cell_padding = 3
|
||||
flow_table.style.bottom_cell_padding = 3
|
||||
-- Draw the scroll table for the tasks
|
||||
local scroll_table = Gui.scroll_table(container,190,3)
|
||||
scroll_table.draw_horizontal_lines = true
|
||||
scroll_table.vertical_centering = false
|
||||
|
||||
-- message to say that you have no tasks
|
||||
local non_made =
|
||||
flow_table.parent.add{
|
||||
name='no_tasks',
|
||||
type='label',
|
||||
caption={'task-list.no-tasks'}
|
||||
-- Change the style of the scroll table
|
||||
local scroll_table_style = scroll_table.style
|
||||
scroll_table_style.top_cell_padding = 3
|
||||
scroll_table_style.bottom_cell_padding = 3
|
||||
|
||||
-- Draw the no tasks label
|
||||
local no_tasks_label =
|
||||
scroll_table.parent.add{
|
||||
name = 'no_tasks',
|
||||
type = 'label',
|
||||
caption = {'task-list.no-tasks'}
|
||||
}
|
||||
non_made.style.width = 200
|
||||
non_made.style.single_line = false
|
||||
|
||||
return flow_table
|
||||
end
|
||||
-- Change the style of the no tasks label
|
||||
local no_tasks_style = no_tasks_label.style
|
||||
no_tasks_style.padding = {2,4}
|
||||
no_tasks_style.single_line = false
|
||||
no_tasks_style.width = 200
|
||||
|
||||
--- Registers the task list
|
||||
-- @element task_list
|
||||
local task_list =
|
||||
Gui.new_left_frame('gui/task-list')
|
||||
:set_sprites('utility/not_enough_repair_packs_icon')
|
||||
:set_direction('vertical')
|
||||
:set_tooltip{'task-list.main-tooltip'}
|
||||
:set_open_by_default()
|
||||
:on_creation(function(player,element)
|
||||
local data_table = generate_container(player,element)
|
||||
-- Add any existing tasks
|
||||
local task_ids = Tasks.get_force_task_ids(player.force.name)
|
||||
|
||||
for _,task_id in pairs(task_ids) do
|
||||
generate_task(player,data_table,task_id)
|
||||
if #task_ids > 0 then
|
||||
no_tasks_style.visible = false
|
||||
for _,task_id in ipairs(task_ids) do
|
||||
update_task(player,scroll_table,task_id)
|
||||
end
|
||||
end
|
||||
|
||||
-- Return the exteral container
|
||||
return container.parent
|
||||
end)
|
||||
:on_update(function(player,element)
|
||||
local data_table = element.container.scroll.table
|
||||
:add_to_left_flow(function(player)
|
||||
local task_ids = Tasks.get_force_task_ids(player.force.name)
|
||||
return #task_ids > 0
|
||||
end)
|
||||
|
||||
for _,task_id in pairs(task_ids) do
|
||||
generate_task(player,data_table,task_id)
|
||||
end
|
||||
--- Button on the top flow used to toggle the task list container
|
||||
-- @element toggle_left_element
|
||||
Gui.left_toolbar_button('utility/not_enough_repair_packs_icon', {'task-list.main-tooltip'}, task_list_container, function(player)
|
||||
return Roles.player_allowed(player,'gui/task-list')
|
||||
end)
|
||||
|
||||
--- When a new task is added it will udpate the task list for everyone on that force
|
||||
Tasks.on_update(function(task,task_id)
|
||||
local players
|
||||
Tasks.on_update(function(task,task_id,removed_task)
|
||||
-- Get the force to update, task is nil when removed
|
||||
local force
|
||||
if task then
|
||||
local force = game.forces[task.force_name]
|
||||
players = force.connected_players
|
||||
force = game.forces[task.force_name]
|
||||
else
|
||||
players = game.connected_players
|
||||
force = game.forces[removed_task.force_name]
|
||||
end
|
||||
|
||||
for _,player in pairs(players) do
|
||||
local frame = task_list:get_frame(player)
|
||||
local element = frame.container.scroll.table
|
||||
generate_task(player,element,task_id)
|
||||
-- Update the task for all the players on the force
|
||||
local task_ids = Tasks.get_force_task_ids(force.name)
|
||||
for _,player in pairs(force.connected_players) do
|
||||
local frame = Gui.get_left_element(player,task_list_container)
|
||||
local scroll_table = frame.container.scroll.table
|
||||
|
||||
-- Update the task that was changed
|
||||
update_task(player,scroll_table,task_id)
|
||||
|
||||
-- Update the numbering of the other tasks if the task was removed
|
||||
if not task then
|
||||
for task_number, next_task_id in pairs(task_ids) do
|
||||
scroll_table['count-'..next_task_id].caption = task_number..')'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
--- Update the tasks when the player joins
|
||||
Event.add(defines.events.on_player_joined_game,task_list 'redraw')
|
||||
Event.add(defines.events.on_player_joined_game,function(event)
|
||||
local player = game.players[event.player_index]
|
||||
local frame = Gui.get_left_element(player,task_list_container)
|
||||
local scroll_table = frame.container.scroll.table
|
||||
update_all_tasks(player,scroll_table)
|
||||
end)
|
||||
|
||||
--- Makes sure the right buttons are present when roles change
|
||||
Event.add(Roles.events.on_role_assigned,task_list 'redraw')
|
||||
Event.add(Roles.events.on_role_unassigned,task_list 'redraw')
|
||||
local function role_update_event(event)
|
||||
local player = game.players[event.player_index]
|
||||
local container = Gui.get_left_element(player,task_list_container).container
|
||||
|
||||
return task_list
|
||||
-- Update the tasks, incase the user can now edit them
|
||||
local scroll_table = container.scroll.table
|
||||
update_all_tasks(player,scroll_table)
|
||||
|
||||
-- Update the new task button incase the user can now add them
|
||||
local add_new_task_element = container.header.alignment[add_new_task.name]
|
||||
add_new_task_element.visible = check_player_permissions(player)
|
||||
end
|
||||
|
||||
Event.add(Roles.events.on_role_assigned,role_update_event)
|
||||
Event.add(Roles.events.on_role_unassigned,role_update_event)
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user