-- Give players the option to set their preferred role as a tag -- Version 0.1.6 -- https://github.com/Befzz/factorio_random/tree/master/scenarios/befzz_test -- Requires event.lua to work ( https://github.com/3RaGaming/utils ) -- SETTINGS local option_band_change_interval = 60 * 3 -- in ticks if not global.band_last_change then global.band_last_change = {} end -- Role list: "band_roles.lua" local band_roles = require "band_roles" local to_print, roles = band_roles.to_print, band_roles.roles do local i = 1 for _, roledata in pairs(roles) do roledata.index = i i = i + 1 end end local custom_roles = {} local expand_band_gui -- store current role local local_role local function create_band_gui(event) local player = game.players[event.player_index] global.band_last_change[event.player_index] = game.tick if player.gui.top.band_toggle_btn == nil then local button = player.gui.top.add { name = "band_toggle_btn", type = "sprite-button", caption = "Tag", style = "dialog_button_style" } button.style.font = "default-bold" button.style.minimal_height = 38 button.style.minimal_width = 38 button.style.top_padding = 2 button.style.left_padding = 4 button.style.right_padding = 4 button.style.bottom_padding = 2 -- expand_band_gui(player) end end -- Make a list of random names with roles local function test_fake_players( t ) local limit = math.random(20,120) local roles_ind = {} for role in pairs(roles) do table.insert( roles_ind, role) end for i = 1,limit do local rolei = math.random(1, #roles_ind) local role = roles_ind[rolei] table.insert(t[role], { "Fake#" .. (tostring(math.random())):sub(3,-math.random(1,10)), { r=math.random(), g=math.random(), b=math.random() } } ) end end local function get_random_from_table(tbl) return tbl[math.random(1,#tbl)] end local function subgui_update_role_counter(gui_parent, count_diff) local count_label if gui_parent["role_counter"] then count_label = gui_parent["role_counter"] else count_label = gui_parent.add {type = "label", caption = 0, name = "role_counter", single_line = false} count_label.style.font = "default-small-bold" count_label.style.maximal_height = 10 count_label.style.top_padding = 0 count_label.style.left_padding = 0 count_label.style.right_padding = 0 count_label.style.bottom_padding = 0 count_label.style.font_color = {r=.55,g=.55,b=.55} end local new_count = tonumber(count_label.caption) + count_diff count_label.caption = new_count if new_count == 0 then count_label.style.visible = false else count_label.style.visible = true end end local function subgui_add_player_label(gui_parent, pname, pcolor) local color_k = 0.6 local name_label = gui_parent.add {type = "label", name = "list_players_"..pname, caption = pname, want_ellipsis = true, single_line = false} name_label.style.font = "default" name_label.style.top_padding = 0 name_label.style.right_padding = 4 name_label.style.left_padding = 2 name_label.style.bottom_padding = 0 name_label.style.maximal_height = 11 name_label.style.minimal_height = 11 name_label.style.maximal_width = 120 name_label.style.minimal_width = 120 name_label.style.font_color = { r = .4 + pcolor.r * color_k, g = .4 + pcolor.g * color_k, b = .4 + pcolor.b * color_k, } end -- dev_icons(ctrl + click): show icon-choose buttons -- dev_addfakes(alt + click): add random number of player names w/ color expand_band_gui = function(player, dev_icons, dev_addfakes, right_click) player.gui.left.direction = "horizontal" local frame = player.gui.left["band_panel"] if (frame) then frame.destroy() if player.gui.center["textfield_item_icon_frame"] then player.gui.center["textfield_item_icon_frame"].destroy() end if player.tag ~= "" then player.gui.top.band_toggle_btn.tooltip = "Tag: "..player.tag.."\n Right Click to show offline players with tags." if player.admin then player.gui.top.band_toggle_btn.tooltip = player.gui.top.band_toggle_btn.tooltip.."\n CTRL + Click to explore icons.\n ALT + Click to add fake names" end end return end local player_role = player.tag:sub(2,-2) -- Will be filled: { roleN = {{name,color},...} , ...} local players_by_role = {} for role in pairs(roles) do players_by_role[role] = {} end for _,role in pairs(custom_roles) do roles[role] = nil end for _,cplayer in pairs(game.players) do local role = cplayer.tag:sub(2,-2) if role ~= "" and roles[role] == nil then players_by_role[role] = {} table.insert(custom_roles, role) roles[role] = {"item/iron-stick",tooltip = {"I'm sure he does something"},verbs = {"enlarged"}} end end if right_click then for _, oplayer in pairs(game.players) do local prole = oplayer.tag:sub(2,-2) if prole ~= "" then if oplayer.connected then table.insert( players_by_role[prole], {oplayer.name, oplayer.color}) else table.insert( players_by_role[prole], {oplayer.name, {r=0,g=0,b=0}}) end end end else for _, oplayer in pairs(game.connected_players) do local prole = oplayer.tag:sub(2,-2) if prole ~= "" then table.insert( players_by_role[prole], {oplayer.name, oplayer.color}) end end end if dev_addfakes then test_fake_players(players_by_role) end player.gui.top.band_toggle_btn.tooltip = "" local button--reusable variable :D local frame = player.gui.left.add { type = "frame", direction = "vertical", name = "band_panel", caption = "Choose your role:"} frame.style.font = "default-listbox" frame.style.font_color = { r=0.98, g=0.66, b=0.22} if dev_icons then local choose local chooselist = frame.add { type = "flow", direction = "horizontal" } -- ["signal"] = {type = "virtual", name = "signal-A"} for itype, ivalue in pairs({["item"] = "green-wire", ["entity"] = "medium-spitter", ["tile"] = "grass"}) do choose = chooselist.add { type = "choose-elem-button", elem_type = itype, [itype] = ivalue, name = "help_item_icon_choose_"..itype } choose.style.minimal_height = 36 choose.style.minimal_width = 36 choose.style.top_padding = 2 choose.style.left_padding = 2 choose.style.right_padding = 2 choose.style.bottom_padding = 2 end end local scroll = frame.add{type = "scroll-pane", name = "scroll", horizontal_scroll_policy = "never", vertical_scroll_policy = "auto"} scroll.style.maximal_height = 600 scroll.style.minimal_width = 250 scroll.style.bottom_padding = 10 local table_roles = scroll.add{type = "table", name = "table_roles", colspan = 2} table_roles.style.horizontal_spacing = 15 table_roles.style.vertical_spacing = 4 local name_label local pname local pcolor local show_role_tooltip = math.random() > .5 for role, role_icons in pairs(roles) do local role_line = table_roles.add { type = "flow", direction = "horizontal" } button = role_line.add { type = "sprite-button", sprite = get_random_from_table(role_icons), name = "band_role_"..role, style = "recipe_slot_button_style"} button.style.top_padding = 4 button.style.left_padding = 0 button.style.right_padding = 0 button.style.bottom_padding = 4 if show_role_tooltip and role_icons.tooltip then button.tooltip = get_random_from_table( role_icons.tooltip ) end local role_cap_line = role_line.add { type = "flow", name = "role_cap_line", direction = "horizontal" } role_cap_line.style.max_on_row = 1 local role_label = role_cap_line.add { type = "label", caption = role, single_line = true} -- role_label.style.minimal_width = 0 role_label.style.minimal_height = 0 role_label.style.maximal_height = 12 role_label.style.top_padding = 0 role_label.style.left_padding = 0 role_label.style.right_padding = 0 role_label.style.bottom_padding = 0 role_label.style.font = "default-bold" if role == player_role then role_label.style.font_color = {r=.7,g=1,b=.7} end subgui_update_role_counter(role_cap_line, #players_by_role[role]) local list_players = table_roles.add { type = "flow", direction = "horizontal" } list_players.style.max_on_row = 3 list_players.style.top_padding = 0 list_players.style.bottom_padding = 7 if players_by_role[role] then for _,pdata in pairs(players_by_role[role]) do pname = pdata[1] pcolor = pdata[2] subgui_add_player_label(list_players, pname, pcolor) end end end local close_btn_flow = frame.add { type = "flow", direction = "horizontal" } button = close_btn_flow.add { type = "button", caption = "Close", name = "band_close" } button.style.font = "default-bold" button.style.minimal_width = 80 button.style.maximal_height = 26 button.style.top_padding = 0 button.style.left_padding = 2 button.style.right_padding = 2 button.style.bottom_padding = 0 button = close_btn_flow.add { type = "button", caption = "Clear tag", name = "band_clear" } button.style.font = "default-bold" button.style.font_color = {r=1, g=.7, b=.7} button.style.minimal_width = 80 button.style.maximal_height = 28 button.style.top_padding = 0 button.style.left_padding = 2 button.style.right_padding = 2 button.style.bottom_padding = 0 end local function print_role_change(name, role) local str = nil if role then if roles[role].verbs and math.random() > 0.7 then str = (get_random_from_table(to_print)) else str = ("[%band] squad has `" .. get_random_from_table(roles[role].verbs) .. "` with %name.") end str = str:gsub('%%band', role) --[[elseif local_role then str = "%name is not in a squad anymore" if math.random() > .9 then str = str .. " (["..local_role.."] squad will miss you)." end]]-- end if str then str = str:gsub('%%name', name) game.print(str) end end -- messy (bcs WIP) local function update_player_role(player, role) global.update_player_name = player global.update_player_role_name = role if global.update_player_role_name then global.update_player_name.tag = "[" .. global.update_player_role_name .. "]" else global.update_player_name.tag = "" end print_role_change(global.update_player_name.name, global.update_player_role_name) expand_band_gui(player) expand_band_gui(player) local_role = role end local function on_gui_click(event) if not (event and event.element and event.element.valid) then return end local player = game.players[event.element.player_index] local name = event.element.name if (name == "band_toggle_btn") then --player, dev_icons, dev_addfakes expand_band_gui(player, player.admin and event.control, player.admin and event.alt, event.button == defines.mouse_button_type.right) end if (name == "band_close") then expand_band_gui(player) return end if (name == "band_clear") then update_player_role(player, nil) player.gui.top.band_toggle_btn.caption = "Tag" player.gui.top.band_toggle_btn.tooltip = "" player.gui.top.band_toggle_btn.sprite = "" return end --role button clicked if name:find("band_role_") == 1 then if not player.admin and event.tick - global.band_last_change[event.player_index] < option_band_change_interval then player.print("Too fast! Please wait... " .. math.floor(1+(global.band_last_change[event.player_index] + option_band_change_interval - event.tick)/60).." s.") return end local _,role_ind_start = name:find("band_role_") local name_role = name:sub(role_ind_start + 1) if player.tag:find(name_role) then -- current tag = new tag return end for role, role_icons in pairs(roles) do if (name_role == role) then global.band_last_change[event.player_index] = event.tick player.gui.top.band_toggle_btn.caption = "" player.gui.top.band_toggle_btn.sprite = event.element.sprite --get_random_from_table(role_icons) update_player_role(player, role) -- expand_band_gui(player) end end end end --handle choose-item button local function on_gui_elem_changed(event) if not (event and event.element and event.element.valid) then return end local player = game.players[event.element.player_index] local name = event.element.name if name:find("help_item_icon_choose") then if player.gui.center["textfield_item_icon_frame"] then player.gui.center["textfield_item_icon_frame"].destroy() end if event.element.elem_type and event.element.elem_value then local frame = player.gui.center.add{ type = "frame", name = "textfield_item_icon_frame", caption = "SpritePath"} frame.style.minimal_width = 310 local textfield -- if type(event.element.elem_value ) == 'table' then -- textfield = frame.add { name = "textfield_item_icon", type = "textfield", text = "virtual-signal/" .. event.element.elem_value.name } -- else textfield = frame.add { name = "textfield_item_icon", type = "textfield", text = event.element.elem_type .. "/" .. event.element.elem_value } -- end --buggy textfield.style.minimal_width = 300 end end end Event.register(defines.events.on_gui_elem_changed, on_gui_elem_changed) Event.register(defines.events.on_gui_click, on_gui_click) Event.register(defines.events.on_player_joined_game, create_band_gui)