From a868ac94fe9af1730aaab353234346457a9cb52e Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sun, 2 Jun 2019 16:24:58 +0100 Subject: [PATCH 1/4] Added files --- config/_file_loader.lua | 1 + config/roles.lua | 1 + modules/gui/warps.lua | 7 +++++++ 3 files changed, 9 insertions(+) create mode 100644 modules/gui/warps.lua diff --git a/config/_file_loader.lua b/config/_file_loader.lua index 23eb99dd..fdeaaace 100644 --- a/config/_file_loader.lua +++ b/config/_file_loader.lua @@ -38,6 +38,7 @@ return { 'modules.gui.science-info', 'modules.gui.task-list', 'modules.gui.player-list', + 'modules.gui.warps', 'modules.commands.debug', -- Config Files 'config.expcore-commands.auth_admin', -- commands tagged with admin_only are blocked for non admins diff --git a/config/roles.lua b/config/roles.lua index 83f5d728..2f0e736c 100644 --- a/config/roles.lua +++ b/config/roles.lua @@ -193,6 +193,7 @@ local default = Roles.new_role('Guest','') 'gui/rocket-info', 'gui/science-info', 'gui/task-list', + 'gui/warp-list', } --- Jail role diff --git a/modules/gui/warps.lua b/modules/gui/warps.lua new file mode 100644 index 00000000..e3433dac --- /dev/null +++ b/modules/gui/warps.lua @@ -0,0 +1,7 @@ +local Gui = require 'expcore.gui' + +--- Registers the warp list +local warp_list = +Gui.new_left_frame('gui/warp-list') + +return warp_list \ No newline at end of file From 1da8f0f2144dd7eb92fcb32df1b7760441c89274 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Thu, 6 Jun 2019 23:12:42 +0100 Subject: [PATCH 2/4] Work warp list --- config/_file_loader.lua | 2 +- config/roles.lua | 3 +- config/warps.lua | 20 ++ locale/en/gui.cfg | 17 +- modules/gui/warp-list.lua | 602 ++++++++++++++++++++++++++++++++++++++ modules/gui/warps.lua | 7 - 6 files changed, 641 insertions(+), 10 deletions(-) create mode 100644 config/warps.lua create mode 100644 modules/gui/warp-list.lua delete mode 100644 modules/gui/warps.lua diff --git a/config/_file_loader.lua b/config/_file_loader.lua index fdeaaace..13ba8d39 100644 --- a/config/_file_loader.lua +++ b/config/_file_loader.lua @@ -36,9 +36,9 @@ return { -- GUI 'modules.gui.rocket-info', 'modules.gui.science-info', + 'modules.gui.warp-list', 'modules.gui.task-list', 'modules.gui.player-list', - 'modules.gui.warps', 'modules.commands.debug', -- Config Files 'config.expcore-commands.auth_admin', -- commands tagged with admin_only are blocked for non admins diff --git a/config/roles.lua b/config/roles.lua index 2f0e736c..bc73a5b5 100644 --- a/config/roles.lua +++ b/config/roles.lua @@ -159,7 +159,8 @@ Roles.new_role('Member','Mem') :set_custom_color{r=24,g=172,b=188} :set_parent('Regular') :allow{ - 'gui/task-list/edit' + 'gui/task-list/edit', + 'gui/warp-list/edit' } Roles.new_role('Regular','Reg') diff --git a/config/warps.lua b/config/warps.lua new file mode 100644 index 00000000..9b5996b5 --- /dev/null +++ b/config/warps.lua @@ -0,0 +1,20 @@ +return { + time_limit = 60, + minimum_distance = 25, + warp_radius = 4, + spawn_radius_scale = 5, + default_icon = 'discharge-defense-equipment', + user_can_edit_own_tasks = true, + only_admins_can_edit = false, + edit_warps_role_permision = 'gui/warp-list/edit', + entities = { + {'small-lamp',-3,-2},{'small-lamp',-3,2},{'small-lamp',3,-2},{'small-lamp',3,2}, + {'small-lamp',-2,-3},{'small-lamp',2,-3},{'small-lamp',-2,3},{'small-lamp',2,3}, + {'small-electric-pole',-3,-3},{'small-electric-pole',3,3},{'small-electric-pole',-3,3},{'small-electric-pole',3,-3} + }, + base_tile = 'tutorial-grid', + tiles = { + {-3,-2},{-3,-1},{-3,0},{-3,1},{-3,2},{3,-2},{3,-1},{3,0},{3,1},{3,2}, + {-2,-3},{-1,-3},{0,-3},{1,-3},{2,-3},{-2,3},{-1,3},{0,3},{1,3},{2,3} + } +} \ No newline at end of file diff --git a/locale/en/gui.cfg b/locale/en/gui.cfg index 872cdf3e..f8b8d997 100644 --- a/locale/en/gui.cfg +++ b/locale/en/gui.cfg @@ -77,4 +77,19 @@ confirm-tooltip=Save changes cancel-tooltip=Discard changes edit-tooltip=Currently being edited by: __1__ edit-tooltip-none=Currently being edited by: Nobody -discord-tooltip=Remove task \ No newline at end of file +discord-tooltip=Remove task + +[warp-list] +main-caption=Warp List +main-tooltip=Warp list, must be within __1__ tiles to use +sub-tooltip=Warps can only be used every 60 seconds and when within __1__ tiles +no-warps=You have no warps +cords=X: __1__ Y: __2__ +too-close=Cant make warp; too close to warp: __1__ +last-edit=Last edited by __1__ at __2__ +add-tooltip=Add new warp +confirm-tooltip=Save changes +cancel-tooltip=Discard changes +edit-tooltip=Currently being edited by: __1__ +edit-tooltip-none=Currently being edited by: Nobody +discord-tooltip=Remove warp \ No newline at end of file diff --git a/modules/gui/warp-list.lua b/modules/gui/warp-list.lua new file mode 100644 index 00000000..8df8ee78 --- /dev/null +++ b/modules/gui/warp-list.lua @@ -0,0 +1,602 @@ +local Gui = require 'expcore.gui' +local Store = require 'expcore.store' +local Global = require 'utils.global' +local Event = require 'utils.event' +local Roles = require 'expcore.roles' +local Token = require 'utils.token' +local config = require 'config.warps' +local format_time,table_keys,table_values,table_keysort = ext_require('expcore.common','format_time','table_keys','table_values','table_keysort') + +local warp_name_store = 'gui.left.warps.names' +local warp_icon_store = 'gui.left.warps.tags' + +local warp_details = {} +local force_warps = {} +Global.register({ + warp_details=warp_details, + force_warps=force_warps +},function(tbl) + force_warps = tbl.force_warps + warp_details = tbl.warp_details +end) + +local function player_allowed_edit(player,warp_id) + if warp_id then + local details = warp_details[warp_id] + if config.user_can_edit_own_tasks and details.last_edit_player == player.name then + return true + end + else + if config.any_user_can_add_new_task then + return true + end + end + + if config.only_admins_can_edit and not player.admin then + return false + end + + if config.edit_warps_role_permision and not Roles.player_allowed(player,config.edit_warps_role_permision) then + return false + end + + return true +end + +local function make_warp_tag(warp_id) + local warp = warp_details[warp_id] + if not warp then return end + + local icon = Store.get(warp_icon_store,warp_id) + local name = Store.get(warp_name_store,warp_id) + + if warp.tag and warp.tag.valid then + warp.tag.text = 'Warp: '..name + warp.tag.icon = {type='item',name=icon} + return + end + + local force = game.forces[warp.force] + local surface = warp.surface + local position = warp.position + + local tag = force.add_chart_tag(surface,{ + position={position.x+0.5,position.y+0.5}, + text='Warp: '..name, + icon={type='item',name=icon} + }) + + warp.tag = tag +end + +local function make_warp_area(warp_id) + local warp = warp_details[warp_id] + if not warp then return end + + local position = warp.position + local posx = position.x + local posy = position.y + local surface = warp.surface + local radius = config.warp_radius + local radius2 = radius^2 + + local old_tile = surface.get_tile(position).name + warp.old_tile = old_tile + + local base_tile = config.base_tile + local base_tiles = {} + local tiles = {} + -- this makes a base plate to make the warp point + for x = -radius, radius do + local x2 = x^2 + for y = -radius, radius do + local y2 = y^2 + if x2+y2 < radius2 then + table.insert(base_tiles,{name=base_tile,position={x+posx,y+posy}}) + end + end + end + surface.set_tiles(base_tiles) + + -- this adds the pattern and entities + for _,pos in pairs(config.tiles) do + table.insert(tiles,{name=base_tile,position={pos[1]+posx,pos[2]+posy}}) + end + surface.set_tiles(tiles) + + for _,entity in pairs(config.entities) do + entity = surface.create_entity{ + name=entity[1], + position={entity[2]+posx,entity[3]+posy}, + force='neutral' + } + entity.destructible = false + entity.health = 0 + entity.minable = false + entity.rotatable = false + end +end + +local function clear_warp_area(warp_id) + local warp = warp_details[warp_id] + if not warp then return end + + local position = warp.position + local surface = warp.surface + local radius = config.warp_radius + local radius2 = radius^2 + + local tiles = {} + -- clears the area where the warp was + for x = -radius, radius do + local x2 = x^2 + for y = -radius, radius do + local y2 = y^2 + if x2+y2 < radius2 then + table.insert(tiles,{name=warp.old_tile,position={x+position.x,y+position.y}}) + end + end + end + surface.set_tiles(tiles) + + local entities = surface.find_entities_filtered{ + force='neutral', + area={ + {position.x-radius,position.y-radius}, + {position.x+radius,position.y+radius} + } + } + for _,entity in pairs(entities) do if entity.name ~= 'player' then entity.destroy() end end + + if warp.tag and warp.tag.valid then warp.tag.destroy() end +end + +local function add_warp(player) + local warp_id = tostring(Token.uid()) + local force_name = player.force.name + + if not force_warps[force_name] then + force_warps[force_name] = {} + end + table.insert(force_warps[force_name],warp_id) + + local position = player.position + + warp_details[warp_id] = { + warp_id = warp_id, + force = force_name, + position = { + x=math.floor(position.x), + y=math.floor(position.y) + }, + surface = player.surface, + last_edit_player=player.name, + last_edit_time=game.tick, + editing={[player.name]=true} + } + + Store.set(warp_name_store,warp_id,'New warp') + Store.set(warp_icon_store,warp_id,config.default_icon) + + make_warp_area(warp_id) +end + +local function remove_warp(warp_id) + local force_name = warp_details[warp_id].force + local key = table.index_of(force_warps[force_name],warp_id) + force_warps[force_name][key] = nil + Store.clear(warp_name_store,warp_id) + Store.clear(warp_icon_store,warp_id) + warp_details[warp_id] = nil +end + +local goto_warp = Gui.uid_name() +Gui.on_click(goto_warp,function(event) + local player = event.player + local warp_id = event.element.parent.caption + local warp = warp_details[warp_id] + local surface = warp.surface + local position = warp.position + local goto_position = surface.find_non_colliding_position('character',position,32,1) + if player.driving then player.driving = false end + player.teleport(position,surface) +end) + +local add_new_warp = +Gui.new_button() +:set_sprites('utility/add') +:set_tooltip{'warp-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) + local position = player.position + local posx = position.x + local posy = position.y + local dist2 = config.minimum_distance^2 + + local warps = Store.get_children(warp_name_store) + for _,warp_id in pairs(warps) do + local warp = warp_details[warp_id] + local pos = warp.position + if (posx-pos.x)^2+(posy-pos.y)^2 < dist2 then + local warp_name = Store.get(warp_name_store,warp_id) + player.print{'warp-list.too-close',warp_name} + return + end + end + + add_warp(player) +end) + +local confirm_edit = +Gui.new_button() +:set_sprites('utility/downloaded') +:set_tooltip{'warp-list.confirm-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 warp_id = element.parent.name + local warp_name = element.parent.warp.text + local warp_icon = element.parent.parent['icon-'..warp_id].icon.elem_value + local warp = warp_details[warp_id] + warp.editing[player.name] = nil + warp.last_edit_player = player.name + warp.last_edit_time = game.tick + Store.set(warp_name_store,warp_id,warp_name) + Store.set(warp_icon_store,warp_id,warp_icon) +end) + +local generate_warp +local cancel_edit = +Gui.new_button() +:set_sprites('utility/close_black') +:set_tooltip{'warp-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) + local warp_id = element.parent.name + local details = warp_details[warp_id] + details.editing[player.name] = nil + generate_warp(player,element.parent.parent,warp_id) +end) + +local discord_warp = +Gui.new_button() +:set_sprites('utility/trash') +:set_tooltip{'warp-list.discord-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 warp_id = element.parent.caption + remove_warp(warp_id) +end) + +--- Opens edit mode for the task +local edit_warp = +Gui.new_button() +:set_sprites('utility/rename_icon_normal') +:set_tooltip{'warp-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 warp_id = element.parent.caption + local details = warp_details[warp_id] + details.editing[player.name] = true + generate_warp(player,element.parent.parent,warp_id) +end) + +--[[ 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_warp + >> discord_warp +]] +function generate_warp(player,element,warp_id) + local warp_name = Store.get(warp_name_store,warp_id) + local warp_icon = Store.get(warp_icon_store,warp_id) + local warp = warp_details[warp_id] + + local editing = warp.editing[player.name] + local last_edit_player = warp.last_edit_player + local last_edit_time = warp.last_edit_time + local warps = force_warps[player.force.name] + local position = warp.position + + if not warp_name then + -- task is nil so remove it from the list + element.parent.no_warps.visible = #warps == 0 + Gui.destory_if_valid(element['icon-'..warp_id]) + Gui.destory_if_valid(element['edit-'..warp_id]) + Gui.destory_if_valid(element[warp_id]) + + else + element.parent.no_warps.visible = false + -- if it is not already present then add it now + local warp_area = element[warp_id] + local icon_area = element['icon-'..warp_id] + if not warp_area then + -- area to store the warp icon + icon_area = + element.add{ + name='icon-'..warp_id, + type='flow', + caption=warp_id + } + Gui.set_padding(icon_area) + + -- area which stores the task and buttons + warp_area = + element.add{ + name=warp_id, + type='flow', + } + Gui.set_padding(warp_area) + + -- if the player can edit then it adds the edit and delete button + local flow = Gui.create_right_align(element,'edit-'..warp_id) + flow.caption = warp_id + + edit_warp(flow) + discord_warp(flow) + + end + + local edit_area = element['edit-'..warp_id] + local players = table_keys(warp.editing) + local allowed = player_allowed_edit(player,warp_id) + + edit_area.visible = allowed + + if #players > 0 then + edit_area[edit_warp.name].tooltip = {'task-list.edit-tooltip',table.concat(players,', ')} + else + edit_area[edit_warp.name].tooltip = {'task-list.edit-tooltip-none'} + end + + -- draws/updates the warp area + local element_type = warp_area.warp and warp_area.warp.type or nil + if not editing and element_type == 'label' then + -- update the label already present + warp_area.warp.caption = warp_name + warp_area.warp.tooltip = {'warp-list.last-edit',last_edit_player,format_time(last_edit_time)} + icon_area[goto_warp].sprite = 'item/'..warp_icon + + elseif not editing then + -- create the label, view mode + if element['edit-'..warp_id] then + element['edit-'..warp_id][edit_warp.name].enabled = true + end + + warp_area.clear() + + local label = + warp_area.add{ + name='warp', + type='label', + caption=warp_name, + tooltip={'warp-list.last-edit',last_edit_player,format_time(last_edit_time)} + } + label.style.single_line = false + label.style.maximal_width = 150 + + icon_area.clear() + + local btn = + icon_area.add{ + name=goto_warp, + type='sprite-button', + sprite='item/'..warp_icon, + style='quick_bar_slot_button', + tooltip={'warp-list.cords',position.x,position.y}, + } + btn.style.height = 32 + btn.style.width = 32 + + elseif editing and element_type ~= 'textfield' then + -- create the text field, edit mode, update it omited as value is being edited + if element['edit-'..warp_id] then + element['edit-'..warp_id][edit_warp.name].enabled = false + end + + warp_area.clear() + + local entry = + warp_area.add{ + name='warp', + type='textfield', + text=warp_name + } + entry.style.maximal_width = 150 + entry.style.height = 20 + + cancel_edit(warp_area) + confirm_edit(warp_area) + + icon_area.clear() + + local btn = + icon_area.add{ + name='icon', + type='choose-elem-button', + elem_type='item', + item=warp_icon, + tooltip={'warp-list.cords',position.x,position.y}, + } + btn.style.height = 32 + btn.style.width = 32 + + end + + 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 + + -- 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 header for the gui + local header = + container.add{ + name='header', + type='frame', + style='subheader_frame' + } + Gui.set_padding(header,2,2,4,4) + header.style.horizontally_stretchable = true + header.style.use_header_filler = false + + --- Caption for the header bar + header.add{ + type='label', + style='heading_1_label', + caption={'warp-list.main-caption'}, + tooltip={'warp-list.sub-tooltip',config.warp_radius} + } + + --- Right aligned button to toggle the section + if player_allowed_edit(player) then + local right_align = Gui.create_right_align(header) + add_new_warp(right_align) + end + + -- main flow for the data + local flow = + container.add{ + name='scroll', + type='scroll-pane', + direction='vertical', + horizontal_scroll_policy='never', + vertical_scroll_policy='auto-and-reserve-space' + } + Gui.set_padding(flow,1,1,2,2) + flow.style.horizontally_stretchable = true + flow.style.maximal_height = 258 + + -- message to say that you have no tasks + local non_made = + flow.add{ + name='no_warps', + type='label', + caption={'warp-list.no-warps'} + } + non_made.style.width = 200 + non_made.style.single_line = false + + -- table that stores all the data + local flow_table = + flow.add{ + name='table', + type='table', + column_count=3 + } + Gui.set_padding(flow_table) + flow_table.style.horizontally_stretchable = true + flow_table.style.top_cell_padding = 3 + flow_table.style.bottom_cell_padding = 3 + + return flow_table +end + +--- Registers the warp list +local warp_list = +Gui.new_left_frame('gui/warp-list') +:set_sprites('item/'..config.default_icon) +:set_tooltip{'warp-list.main-tooltip',config.warp_radius} +:set_direction('vertical') +:on_draw(function(player,element) + local data_table = generate_container(player,element) + local force_name = player.force.name + + local warps = force_warps[force_name] or {} + for _,warp_id in pairs(warps) do + generate_warp(player,data_table,warp_id) + end +end) +:on_update(function(player,element) + local data_table = element.container.scroll.table + local force_name = player.force.name + + local warps = force_warps[force_name] or {} + for _,warp_id in pairs(warps) do + generate_warp(player,data_table,warp_id) + end +end) + +Store.register(warp_name_store,function(value,warp_id) + if value == 'New warp' then return end + local warp = warp_details[warp_id] + local force = game.forces[warp.force] + + local names = {} + for _,_warp_id in pairs(force_warps[force.name]) do + local name = Store.get(warp_name_store,_warp_id) + names[name] = _warp_id + end + + force_warps[force.name] = table_values(table_keysort(names)) + + for _,player in pairs(force.players) do + warp_list:update(player) + end +end) + +Store.register(warp_icon_store,function(value,warp_id) + local warp = warp_details[warp_id] + local force = game.forces[warp.force] + + for _,player in pairs(force.players) do + local frame = warp_list:get_frame(player) + local element = frame.container.scroll.table + generate_warp(player,element,warp_id) + end + + if value then + make_warp_tag(warp_id) + else + clear_warp_area(warp_id) + end +end) + +return warp_list \ No newline at end of file diff --git a/modules/gui/warps.lua b/modules/gui/warps.lua deleted file mode 100644 index e3433dac..00000000 --- a/modules/gui/warps.lua +++ /dev/null @@ -1,7 +0,0 @@ -local Gui = require 'expcore.gui' - ---- Registers the warp list -local warp_list = -Gui.new_left_frame('gui/warp-list') - -return warp_list \ No newline at end of file From 4f53142683ab1515de3804246ce41d3e74403fc5 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Fri, 7 Jun 2019 18:34:56 +0100 Subject: [PATCH 3/4] All features added --- config/roles.lua | 1 + config/warps.lua | 4 +- expcore/common.lua | 83 +++++++++++++--- expcore/gui/progress-bar.lua | 6 +- locale/en/gui.cfg | 8 +- modules/gui/warp-list.lua | 185 +++++++++++++++++++++++++++++++---- 6 files changed, 244 insertions(+), 43 deletions(-) diff --git a/config/roles.lua b/config/roles.lua index bc73a5b5..f1ef1091 100644 --- a/config/roles.lua +++ b/config/roles.lua @@ -56,6 +56,7 @@ Roles.new_role('Administrator','Admin') :set_flag('report-immune') :set_parent('Moderator') :allow{ + 'gui/warp-list/no-limit', } Roles.new_role('Moderator','Mod') diff --git a/config/warps.lua b/config/warps.lua index 9b5996b5..9b357d7d 100644 --- a/config/warps.lua +++ b/config/warps.lua @@ -1,12 +1,14 @@ return { time_limit = 60, - minimum_distance = 25, + time_smothing = 10, + minimum_distance = 100, warp_radius = 4, spawn_radius_scale = 5, default_icon = 'discharge-defense-equipment', user_can_edit_own_tasks = true, only_admins_can_edit = false, edit_warps_role_permision = 'gui/warp-list/edit', + no_warp_limit_permision = 'gui/warp-list/no-limit', entities = { {'small-lamp',-3,-2},{'small-lamp',-3,2},{'small-lamp',3,-2},{'small-lamp',3,2}, {'small-lamp',-2,-3},{'small-lamp',2,-3},{'small-lamp',-2,3},{'small-lamp',2,3}, diff --git a/expcore/common.lua b/expcore/common.lua index bed708be..ee149dbe 100644 --- a/expcore/common.lua +++ b/expcore/common.lua @@ -510,26 +510,77 @@ function Common.auto_complete(options,input,use_key,rtn_key) return rtn[1] end ---- Returns all the keys of a table --- @tparam table tbl table the to get the keys of --- @treturn table an array of the table keys -function Common.table_keys(tbl) - local rtn = {} - for key,_ in pairs(tbl) do - table.insert(rtn,key) +--- Default table comparator sort function. +-- @local +-- @param x one comparator operand +-- @param y the other comparator operand +-- @return true if x logically comes before y in a list, false otherwise +local function sortFunc(x, y) --sorts tables with mixed index types. + local tx = type(x) + local ty = type(y) + if tx == ty then + if type(x) == 'string' then + return string.lower(x) < string.lower(y) + else + return x < y + end + elseif tx == 'number' then + return true --only x is a number and goes first + else + return false --only y is a number and goes first end - return rtn end ---- Returns all the values of a table --- @tparam table tbl table the to get the values of --- @treturn table an array of the table values -function Common.table_values(tbl) - local rtn = {} - for _,value in pairs(tbl) do - table.insert(rtn,value) +--- Returns a copy of all of the values in the table. +-- @tparam table table tbl the to copy the keys from, or an empty table if tbl is nil +-- @tparam[opt] boolean sorted whether to sort the keys (slower) or keep the random order from pairs() +-- @tparam[opt] boolean as_string whether to try and parse the values as strings, or leave them as their existing type +-- @treturn array an array with a copy of all the values in the table +function Common.table_values(tbl, sorted, as_string) + if not tbl then return {} end + local valueset = {} + local n = 0 + if as_string then --checking as_string /before/ looping is faster + for _, v in pairs(tbl) do + n = n + 1 + valueset[n] = tostring(v) + end + else + for _, v in pairs(tbl) do + n = n + 1 + valueset[n] = v + end end - return rtn + if sorted then + table.sort(valueset,sortFunc) + end + return valueset +end + +--- Returns a copy of all of the keys in the table. +-- @tparam table table tbl the to copy the keys from, or an empty table if tbl is nil +-- @tparam[opt] boolean sorted whether to sort the keys (slower) or keep the random order from pairs() +-- @tparam[opt] boolean as_string whether to try and parse the keys as strings, or leave them as their existing type +-- @treturn array an array with a copy of all the keys in the table +function Common.table_keys(tbl, sorted, as_string) + if not tbl then return {} end + local keyset = {} + local n = 0 + if as_string then --checking as_string /before/ looping is faster + for k, _ in pairs(tbl) do + n = n + 1 + keyset[n] = tostring(k) + end + else + for k, _ in pairs(tbl) do + n = n + 1 + keyset[n] = k + end + end + if sorted then + table.sort(keyset,sortFunc) + end + return keyset end --- Returns the list is a sorted way that would be expected by people (this is by key) diff --git a/expcore/gui/progress-bar.lua b/expcore/gui/progress-bar.lua index 1ab239dd..2200019d 100644 --- a/expcore/gui/progress-bar.lua +++ b/expcore/gui/progress-bar.lua @@ -258,6 +258,8 @@ local function change_value_prototype(self,amount,category,filter) local maximum = self.default_maximum or 1 local new_value = value + (amount/maximum) + self:set_store(category,new_value) + if self.count_down and new_value <= 0 or not self.count_down and new_value >= 1 then self:clear_store(category) @@ -265,9 +267,9 @@ local function change_value_prototype(self,amount,category,filter) if self.events.on_store_complete then self.events.on_store_complete(category,reset_store) end - end - self:set_store(category,new_value) + return + end return end diff --git a/locale/en/gui.cfg b/locale/en/gui.cfg index f8b8d997..1e4c4017 100644 --- a/locale/en/gui.cfg +++ b/locale/en/gui.cfg @@ -82,9 +82,9 @@ discord-tooltip=Remove task [warp-list] main-caption=Warp List main-tooltip=Warp list, must be within __1__ tiles to use -sub-tooltip=Warps can only be used every 60 seconds and when within __1__ tiles +sub-tooltip=Warps can only be used every __1__ seconds and when within __2__ tiles no-warps=You have no warps -cords=X: __1__ Y: __2__ +cords=Go to x __1__ y __2__ too-close=Cant make warp; too close to warp: __1__ last-edit=Last edited by __1__ at __2__ add-tooltip=Add new warp @@ -92,4 +92,6 @@ confirm-tooltip=Save changes cancel-tooltip=Discard changes edit-tooltip=Currently being edited by: __1__ edit-tooltip-none=Currently being edited by: Nobody -discord-tooltip=Remove warp \ No newline at end of file +discord-tooltip=Remove warp +timer-tooltip=Warp charge, charge time __1__ seconds +goto-disabled=You must be on a warp point and have a full charge to warp \ No newline at end of file diff --git a/modules/gui/warp-list.lua b/modules/gui/warp-list.lua index 8df8ee78..348f2e60 100644 --- a/modules/gui/warp-list.lua +++ b/modules/gui/warp-list.lua @@ -2,13 +2,18 @@ local Gui = require 'expcore.gui' local Store = require 'expcore.store' local Global = require 'utils.global' local Event = require 'utils.event' +local Game = require 'utils.game' local Roles = require 'expcore.roles' local Token = require 'utils.token' +local Colors = require 'resources.color_presets' local config = require 'config.warps' local format_time,table_keys,table_values,table_keysort = ext_require('expcore.common','format_time','table_keys','table_values','table_keysort') +local warp_list +local goto_warp = Gui.uid_name() local warp_name_store = 'gui.left.warps.names' local warp_icon_store = 'gui.left.warps.tags' +local warp_allowed_store = 'gui.left.warps.allowed' local warp_details = {} local force_warps = {} @@ -23,6 +28,9 @@ end) local function player_allowed_edit(player,warp_id) if warp_id then local details = warp_details[warp_id] + if not details.editing then + return false + end if config.user_can_edit_own_tasks and details.last_edit_player == player.name then return true end @@ -151,12 +159,41 @@ local function clear_warp_area(warp_id) if warp.tag and warp.tag.valid then warp.tag.destroy() end end +local function add_spawn(player) + local warp_id = tostring(Token.uid()) + local force = player.force + local force_name = force.name + local surface = player.surface + local spawn = force.get_spawn_position(surface) + + if not force_warps[force_name] then + force_warps[force_name] = {} + end + table.insert(force_warps[force_name],warp_id) + + warp_details[warp_id] = { + warp_id = warp_id, + force = force.name, + position = { + x=math.floor(spawn.x), + y=math.floor(spawn.y) + }, + surface = surface, + last_edit_player='System', + last_edit_time=game.tick, + editing=false + } + + Store.set(warp_name_store,warp_id,'Spawn') + Store.set(warp_icon_store,warp_id,config.default_icon) +end + local function add_warp(player) local warp_id = tostring(Token.uid()) local force_name = player.force.name if not force_warps[force_name] then - force_warps[force_name] = {} + add_spawn(player) end table.insert(force_warps[force_name],warp_id) @@ -190,7 +227,19 @@ local function remove_warp(warp_id) warp_details[warp_id] = nil end -local goto_warp = Gui.uid_name() +local warp_timer = +Gui.new_progressbar() +:set_tooltip{'warp-list.timer-tooltip',config.time_limit} +:set_default_maximum(config.time_limit*config.time_smothing) +:add_store(Gui.player_store) +:set_style(nil,function(style) + style.horizontally_stretchable = true + style.color = Colors.light_blue +end) +:on_store_complete(function(player_name,reset) + Store.set(warp_allowed_store,player_name,true) +end) + Gui.on_click(goto_warp,function(event) local player = event.player local warp_id = event.element.parent.caption @@ -199,7 +248,11 @@ Gui.on_click(goto_warp,function(event) local position = warp.position local goto_position = surface.find_non_colliding_position('character',position,32,1) if player.driving then player.driving = false end - player.teleport(position,surface) + player.teleport(goto_position,surface) + if config.no_warp_limit_permision and not Roles.player_allowed(player,config.no_warp_limit_permision) then + warp_timer:set_store(player.name,0) + Store.set(warp_allowed_store,player.name,false) + end end) local add_new_warp = @@ -279,7 +332,7 @@ Gui.new_button() style.width = 20 end) :on_click(function(player,element) - local warp_id = element.parent.caption + local warp_id = element.parent.name remove_warp(warp_id) end) @@ -294,10 +347,10 @@ Gui.new_button() style.width = 20 end) :on_click(function(player,element) - local warp_id = element.parent.caption + local warp_id = element.parent.name local details = warp_details[warp_id] details.editing[player.name] = true - generate_warp(player,element.parent.parent,warp_id) + generate_warp(player,element.parent.parent.parent,warp_id) end) --[[ Generates each task, handles both view and edit mode @@ -314,10 +367,10 @@ end) ]] function generate_warp(player,element,warp_id) local warp_name = Store.get(warp_name_store,warp_id) - local warp_icon = Store.get(warp_icon_store,warp_id) + local warp_icon = Store.get(warp_icon_store,warp_id) or config.default_icon local warp = warp_details[warp_id] - local editing = warp.editing[player.name] + local editing = warp.editing and warp.editing[player.name] local last_edit_player = warp.last_edit_player local last_edit_time = warp.last_edit_time local warps = force_warps[player.force.name] @@ -355,15 +408,15 @@ function generate_warp(player,element,warp_id) -- if the player can edit then it adds the edit and delete button local flow = Gui.create_right_align(element,'edit-'..warp_id) - flow.caption = warp_id + local sub_flow = flow.add{type='flow',name=warp_id} - edit_warp(flow) - discord_warp(flow) + edit_warp(sub_flow) + discord_warp(sub_flow) end - local edit_area = element['edit-'..warp_id] - local players = table_keys(warp.editing) + local edit_area = element['edit-'..warp_id][warp_id] + local players = warp.editing and table_keys(warp.editing) or {} local allowed = player_allowed_edit(player,warp_id) edit_area.visible = allowed @@ -384,8 +437,8 @@ function generate_warp(player,element,warp_id) elseif not editing then -- create the label, view mode - if element['edit-'..warp_id] then - element['edit-'..warp_id][edit_warp.name].enabled = true + if edit_area then + edit_area[edit_warp.name].enabled = true end warp_area.clear() @@ -413,10 +466,17 @@ function generate_warp(player,element,warp_id) btn.style.height = 32 btn.style.width = 32 + local timer = warp_timer:get_store(player_name) + local enabled = not timer and Store.get(warp_allowed_store,player.name) + btn.enabled = enabled + if not enabled then + btn.tooltip = {'warp-list.goto-disabled'} + end + elseif editing and element_type ~= 'textfield' then -- create the text field, edit mode, update it omited as value is being edited - if element['edit-'..warp_id] then - element['edit-'..warp_id][edit_warp.name].enabled = false + if edit_area then + edit_area[edit_warp.name].enabled = false end warp_area.clear() @@ -492,7 +552,7 @@ local function generate_container(player,element) type='label', style='heading_1_label', caption={'warp-list.main-caption'}, - tooltip={'warp-list.sub-tooltip',config.warp_radius} + tooltip={'warp-list.sub-tooltip',config.time_limit,config.warp_radius} } --- Right aligned button to toggle the section @@ -536,11 +596,13 @@ local function generate_container(player,element) flow_table.style.top_cell_padding = 3 flow_table.style.bottom_cell_padding = 3 + warp_timer(container) + return flow_table end --- Registers the warp list -local warp_list = +warp_list = Gui.new_left_frame('gui/warp-list') :set_sprites('item/'..config.default_icon) :set_tooltip{'warp-list.main-tooltip',config.warp_radius} @@ -558,6 +620,8 @@ end) local data_table = element.container.scroll.table local force_name = player.force.name + data_table.clear() + local warps = force_warps[force_name] or {} for _,warp_id in pairs(warps) do generate_warp(player,data_table,warp_id) @@ -565,17 +629,22 @@ end) end) Store.register(warp_name_store,function(value,warp_id) - if value == 'New warp' then return end local warp = warp_details[warp_id] local force = game.forces[warp.force] local names = {} + local spawn_id for _,_warp_id in pairs(force_warps[force.name]) do local name = Store.get(warp_name_store,_warp_id) - names[name] = _warp_id + if not warp_details[_warp_id].editing then + spawn_id = _warp_id + else + names[name.._warp_id] = _warp_id + end end force_warps[force.name] = table_values(table_keysort(names)) + table.insert(force_warps[force.name],1,spawn_id) for _,player in pairs(force.players) do warp_list:update(player) @@ -599,4 +668,78 @@ Store.register(warp_icon_store,function(value,warp_id) end end) +Store.register(warp_allowed_store,function(value,player_name) + local player = game.players[player_name] + local force = player.force + local frame = warp_list:get_frame(player_name) + local table_area = frame.container.scroll.table + local timer = warp_timer:get_store(player_name) + local state = not timer and value + + if force_warps[force.name] then + for _,warp_id in pairs(force_warps[force.name]) do + local element = table_area['icon-'..warp_id][goto_warp] + if element and element.valid then + element.enabled = state + if state then + local position = warp_details[warp_id].position + element.tooltip = {'warp-list.cords',position.x,position.y} + else + element.tooltip = {'warp-list.goto-disabled'} + end + end + end + end +end) + +local r2 = config.warp_radius^2 +local rs2 = (config.warp_radius*config.spawn_radius_scale)^2 +Event.on_nth_tick(60/config.time_smothing,function() + local categories = Store.get_children(warp_timer.store) + for _,category in pairs(categories) do + warp_timer:increment(1,category) + end + + for _,player in pairs(game.connected_players) do + local timer = warp_timer:get_store(player.name) + local role = config.no_warp_limit_permision and Roles.player_allowed(player,config.no_warp_limit_permision) + if not timer and not role then + local force = player.force + local warps = force_warps[force.name] + if warps then + local surface = player.surface.index + local pos = player.position + local px,py = pos.x,pos.y + + for _,warp_id in pairs(warps) do + local warp = warp_details[warp_id] + local wpos = warp.position + if warp.surface.index == surface then + local dx,dy = px-wpos.x,py-wpos.y + if not warp.editing and (dx*dx)+(dy*dy) < rs2 or (dx*dx)+(dy*dy) < r2 then + Store.set(warp_allowed_store,player.name,true) + return + end + end + end + + Store.set(warp_allowed_store,player.name,false) + end + end + end + +end) + +Event.add(defines.events.on_player_created,function(event) + local player = Game.get_player_by_index(event.player_index) + local force_name = player.force.name + + local allowed = config.no_warp_limit_permision and Roles.player_allowed(player,config.no_warp_limit_permision) or false + Store.set(warp_allowed_store,player.name,allowed) + + if not force_warps[force_name] then + add_spawn(player) + end +end) + return warp_list \ No newline at end of file From 9e5630e9d6df5d1291e27adca520ce45f1e3ba1d Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Fri, 7 Jun 2019 19:22:08 +0100 Subject: [PATCH 4/4] Finished comenting warps --- config/warps.lua | 27 +++--- locale/en/gui.cfg | 8 +- modules/gui/warp-list.lua | 199 +++++++++++++++++++++----------------- 3 files changed, 128 insertions(+), 106 deletions(-) diff --git a/config/warps.lua b/config/warps.lua index 9b357d7d..8ec573a3 100644 --- a/config/warps.lua +++ b/config/warps.lua @@ -1,21 +1,22 @@ +--- This file contains all the different settings for the warp system and gui return { - time_limit = 60, - time_smothing = 10, - minimum_distance = 100, - warp_radius = 4, - spawn_radius_scale = 5, - default_icon = 'discharge-defense-equipment', - user_can_edit_own_tasks = true, - only_admins_can_edit = false, - edit_warps_role_permision = 'gui/warp-list/edit', - no_warp_limit_permision = 'gui/warp-list/no-limit', - entities = { + recharge_time = 60, -- The amount of time in seconds that the player must wait between warps, acts as a balance + update_smothing = 10, -- Higher is better, the amount of smothing applied to recharge timer and other gui updates, max is 60 + minimum_distance = 100, -- The minimum distance that must be between warp points, creating new ones is blocked when too close + activation_range = 4, -- The distance the player must be to a warp in order to use the warp gui, gui can still be viewd but not used + spawn_activation_range = 20, -- A second activation range which is used for the forces spawn point + default_icon = 'discharge-defense-equipment', -- The deafult icon which is used by warps; must be an item name + user_can_edit_own_warps = true, -- When true the user can always edit warps which they created regaudless of other settings + only_admins_can_edit = false, -- When true only admins can edit warps + edit_warps_role_permision = 'gui/warp-list/edit', -- Role permission used by the role system to allow editing warps + bypass_warp_limits_permision = 'gui/warp-list/no-limit', -- Role permission used by the role system to allow bypassing the time and distance restrctions + entities = { -- The entites which are created for warps {'small-lamp',-3,-2},{'small-lamp',-3,2},{'small-lamp',3,-2},{'small-lamp',3,2}, {'small-lamp',-2,-3},{'small-lamp',2,-3},{'small-lamp',-2,3},{'small-lamp',2,3}, {'small-electric-pole',-3,-3},{'small-electric-pole',3,3},{'small-electric-pole',-3,3},{'small-electric-pole',3,-3} }, - base_tile = 'tutorial-grid', - tiles = { + base_tile = 'tutorial-grid', -- The tile which is used for the warps + tiles = { -- The tiles which are created for warps {-3,-2},{-3,-1},{-3,0},{-3,1},{-3,2},{3,-2},{3,-1},{3,0},{3,1},{3,2}, {-2,-3},{-1,-3},{0,-3},{1,-3},{2,-3},{-2,3},{-1,3},{0,3},{1,3},{2,3} } diff --git a/locale/en/gui.cfg b/locale/en/gui.cfg index 1e4c4017..b0052648 100644 --- a/locale/en/gui.cfg +++ b/locale/en/gui.cfg @@ -83,8 +83,6 @@ discord-tooltip=Remove task main-caption=Warp List main-tooltip=Warp list, must be within __1__ tiles to use sub-tooltip=Warps can only be used every __1__ seconds and when within __2__ tiles -no-warps=You have no warps -cords=Go to x __1__ y __2__ too-close=Cant make warp; too close to warp: __1__ last-edit=Last edited by __1__ at __2__ add-tooltip=Add new warp @@ -92,6 +90,8 @@ confirm-tooltip=Save changes cancel-tooltip=Discard changes edit-tooltip=Currently being edited by: __1__ edit-tooltip-none=Currently being edited by: Nobody -discord-tooltip=Remove warp +discard-tooltip=Remove warp timer-tooltip=Warp charge, charge time __1__ seconds -goto-disabled=You must be on a warp point and have a full charge to warp \ No newline at end of file +goto-tooltip=Go to x __1__ y __2__ +goto-disabled=You must be on a warp point and have a full charge to warp +goto-edit=Edit warp icon \ No newline at end of file diff --git a/modules/gui/warp-list.lua b/modules/gui/warp-list.lua index 348f2e60..08dfbc06 100644 --- a/modules/gui/warp-list.lua +++ b/modules/gui/warp-list.lua @@ -10,10 +10,9 @@ local config = require 'config.warps' local format_time,table_keys,table_values,table_keysort = ext_require('expcore.common','format_time','table_keys','table_values','table_keysort') local warp_list -local goto_warp = Gui.uid_name() local warp_name_store = 'gui.left.warps.names' local warp_icon_store = 'gui.left.warps.tags' -local warp_allowed_store = 'gui.left.warps.allowed' +local warp_player_in_range_store = 'gui.left.warps.allowed' local warp_details = {} local force_warps = {} @@ -25,13 +24,14 @@ Global.register({ warp_details = tbl.warp_details end) +--- Returns if a player is allowed to edit the given warp local function player_allowed_edit(player,warp_id) if warp_id then local details = warp_details[warp_id] if not details.editing then return false end - if config.user_can_edit_own_tasks and details.last_edit_player == player.name then + if config.user_can_edit_own_warps and details.last_edit_player == player.name then return true end else @@ -51,6 +51,7 @@ local function player_allowed_edit(player,warp_id) return true end +--- Makes a map marker for this warp; updates it if already present local function make_warp_tag(warp_id) local warp = warp_details[warp_id] if not warp then return end @@ -77,6 +78,7 @@ local function make_warp_tag(warp_id) warp.tag = tag end +-- This creates the area for the warp; this is not required but helps players know where the warps are local function make_warp_area(warp_id) local warp = warp_details[warp_id] if not warp then return end @@ -85,7 +87,7 @@ local function make_warp_area(warp_id) local posx = position.x local posy = position.y local surface = warp.surface - local radius = config.warp_radius + local radius = config.activation_range local radius2 = radius^2 local old_tile = surface.get_tile(position).name @@ -93,7 +95,6 @@ local function make_warp_area(warp_id) local base_tile = config.base_tile local base_tiles = {} - local tiles = {} -- this makes a base plate to make the warp point for x = -radius, radius do local x2 = x^2 @@ -106,12 +107,14 @@ local function make_warp_area(warp_id) end surface.set_tiles(base_tiles) - -- this adds the pattern and entities + -- this adds the tile pattern + local tiles = {} for _,pos in pairs(config.tiles) do table.insert(tiles,{name=base_tile,position={pos[1]+posx,pos[2]+posy}}) end surface.set_tiles(tiles) + -- this adds the enitites for _,entity in pairs(config.entities) do entity = surface.create_entity{ name=entity[1], @@ -125,15 +128,17 @@ local function make_warp_area(warp_id) end end +--- This removes the warp area, also restores the old tile local function clear_warp_area(warp_id) local warp = warp_details[warp_id] if not warp then return end local position = warp.position local surface = warp.surface - local radius = config.warp_radius + local radius = config.activation_range local radius2 = radius^2 + local base_tile = warp.old_tile local tiles = {} -- clears the area where the warp was for x = -radius, radius do @@ -141,12 +146,13 @@ local function clear_warp_area(warp_id) for y = -radius, radius do local y2 = y^2 if x2+y2 < radius2 then - table.insert(tiles,{name=warp.old_tile,position={x+position.x,y+position.y}}) + table.insert(tiles,{name=base_tile,position={x+position.x,y+position.y}}) end end end surface.set_tiles(tiles) + -- removes all entites (in the area) on the neutral force local entities = surface.find_entities_filtered{ force='neutral', area={ @@ -159,6 +165,7 @@ local function clear_warp_area(warp_id) if warp.tag and warp.tag.valid then warp.tag.destroy() end end +--- Speaial case for the warps; adds the spawn warp which cant be removed local function add_spawn(player) local warp_id = tostring(Token.uid()) local force = player.force @@ -188,6 +195,7 @@ local function add_spawn(player) Store.set(warp_icon_store,warp_id,config.default_icon) end +--- General case for the warps; will make a new warp and set the player to be editing it local function add_warp(player) local warp_id = tostring(Token.uid()) local force_name = player.force.name @@ -218,6 +226,7 @@ local function add_warp(player) make_warp_area(warp_id) end +--- Removes all refrences to a warp local function remove_warp(warp_id) local force_name = warp_details[warp_id].force local key = table.index_of(force_warps[force_name],warp_id) @@ -227,34 +236,49 @@ local function remove_warp(warp_id) warp_details[warp_id] = nil end +--- This timer controls when a player is able to warp, eg every 60 seconds local warp_timer = Gui.new_progressbar() -:set_tooltip{'warp-list.timer-tooltip',config.time_limit} -:set_default_maximum(config.time_limit*config.time_smothing) +:set_tooltip{'warp-list.timer-tooltip',config.recharge_time} +:set_default_maximum(math.floor(config.recharge_time*config.update_smothing)) :add_store(Gui.player_store) :set_style(nil,function(style) style.horizontally_stretchable = true style.color = Colors.light_blue end) :on_store_complete(function(player_name,reset) - Store.set(warp_allowed_store,player_name,true) + Store.set(warp_player_in_range_store,player_name,true) end) -Gui.on_click(goto_warp,function(event) - local player = event.player - local warp_id = event.element.parent.caption +--- When the button is clicked it will teleport the player +local goto_warp = +Gui.new_button() +:set_sprites('item/'..config.default_icon) +:set_tooltip{'warp-list.goto-tooltip',0,0} +:set_style('quick_bar_slot_button',function(style) + style.height = 32 + style.width = 32 +end) +:on_click(function(player,element) + local warp_id = element.parent.caption local warp = warp_details[warp_id] local surface = warp.surface - local position = warp.position + local position = { + x=warp.position.x+0.5, + y=warp.position.y+0.5 + } + local goto_position = surface.find_non_colliding_position('character',position,32,1) if player.driving then player.driving = false end player.teleport(goto_position,surface) - if config.no_warp_limit_permision and not Roles.player_allowed(player,config.no_warp_limit_permision) then + + if config.bypass_warp_limits_permision and not Roles.player_allowed(player,config.bypass_warp_limits_permision) then warp_timer:set_store(player.name,0) - Store.set(warp_allowed_store,player.name,false) + Store.set(warp_player_in_range_store,player.name,false) end end) +--- Will add a new warp to the list, checks if the player is too close to an existing one local add_new_warp = Gui.new_button() :set_sprites('utility/add') @@ -284,6 +308,7 @@ end) add_warp(player) end) +--- Confirms the edit to name or icon of the warp local confirm_edit = Gui.new_button() :set_sprites('utility/downloaded') @@ -305,6 +330,7 @@ end) Store.set(warp_icon_store,warp_id,warp_icon) end) +--- Cancels the editing changes of the selected warp name or icon local generate_warp local cancel_edit = Gui.new_button() @@ -322,10 +348,11 @@ end) generate_warp(player,element.parent.parent,warp_id) end) -local discord_warp = +--- Removes a warp from the list, including the physical area and map tag +local discard_warp = Gui.new_button() :set_sprites('utility/trash') -:set_tooltip{'warp-list.discord-tooltip'} +:set_tooltip{'warp-list.discard-tooltip'} :set_style('tool_button',function(style) Gui.set_padding_style(style,-2,-2,-2,-2) style.height = 20 @@ -336,7 +363,7 @@ end) remove_warp(warp_id) end) ---- Opens edit mode for the task +--- Opens edit mode for the warp local edit_warp = Gui.new_button() :set_sprites('utility/rename_icon_normal') @@ -355,15 +382,16 @@ end) --[[ Generates each task, handles both view and edit mode element - > count-"task_id" - >> label - > "task_id" - >> task + > icon-"warp_id" + >> goto_warp or icon + > "warp_id" + >> warp >> cancel_edit (edit mode) >> confirm_edit (edit mode) - > edit-"task_id" - >> edit_warp - >> discord_warp + > edit-"warp_id" + >> "warp_id" + >>> edit_warp + >>> discard_warp ]] function generate_warp(player,element,warp_id) local warp_name = Store.get(warp_name_store,warp_id) @@ -373,18 +401,15 @@ function generate_warp(player,element,warp_id) local editing = warp.editing and warp.editing[player.name] local last_edit_player = warp.last_edit_player local last_edit_time = warp.last_edit_time - local warps = force_warps[player.force.name] local position = warp.position if not warp_name then -- task is nil so remove it from the list - element.parent.no_warps.visible = #warps == 0 Gui.destory_if_valid(element['icon-'..warp_id]) Gui.destory_if_valid(element['edit-'..warp_id]) Gui.destory_if_valid(element[warp_id]) else - element.parent.no_warps.visible = false -- if it is not already present then add it now local warp_area = element[warp_id] local icon_area = element['icon-'..warp_id] @@ -411,7 +436,7 @@ function generate_warp(player,element,warp_id) local sub_flow = flow.add{type='flow',name=warp_id} edit_warp(sub_flow) - discord_warp(sub_flow) + discard_warp(sub_flow) end @@ -433,7 +458,7 @@ function generate_warp(player,element,warp_id) -- update the label already present warp_area.warp.caption = warp_name warp_area.warp.tooltip = {'warp-list.last-edit',last_edit_player,format_time(last_edit_time)} - icon_area[goto_warp].sprite = 'item/'..warp_icon + icon_area[goto_warp.name].sprite = 'item/'..warp_icon elseif not editing then -- create the label, view mode @@ -441,6 +466,21 @@ function generate_warp(player,element,warp_id) edit_area[edit_warp.name].enabled = true end + -- redraws the icon for the warp + icon_area.clear() + + local btn = goto_warp(icon_area) + btn.sprite = 'item/'..warp_icon + btn.tooltip = {'warp-list.goto-tooltip',position.x,position.y} + + local timer = warp_timer:get_store(player.name) + local enabled = not timer and Store.get(warp_player_in_range_store,player.name) + if not enabled then + btn.enabled = false + btn.tooltip = {'warp-list.goto-disabled'} + end + + -- redraws the label for the warp name warp_area.clear() local label = @@ -453,32 +493,27 @@ function generate_warp(player,element,warp_id) label.style.single_line = false label.style.maximal_width = 150 - icon_area.clear() - - local btn = - icon_area.add{ - name=goto_warp, - type='sprite-button', - sprite='item/'..warp_icon, - style='quick_bar_slot_button', - tooltip={'warp-list.cords',position.x,position.y}, - } - btn.style.height = 32 - btn.style.width = 32 - - local timer = warp_timer:get_store(player_name) - local enabled = not timer and Store.get(warp_allowed_store,player.name) - btn.enabled = enabled - if not enabled then - btn.tooltip = {'warp-list.goto-disabled'} - end - elseif editing and element_type ~= 'textfield' then -- create the text field, edit mode, update it omited as value is being edited if edit_area then edit_area[edit_warp.name].enabled = false end + -- redraws the icon for the warp and allows selection + icon_area.clear() + + local btn = + icon_area.add{ + name='icon', + type='choose-elem-button', + elem_type='item', + item=warp_icon, + tooltip={'warp-list.goto-edit'}, + } + btn.style.height = 32 + btn.style.width = 32 + + -- redraws the label for the warp name and allows editing warp_area.clear() local entry = @@ -493,19 +528,6 @@ function generate_warp(player,element,warp_id) cancel_edit(warp_area) confirm_edit(warp_area) - icon_area.clear() - - local btn = - icon_area.add{ - name='icon', - type='choose-elem-button', - elem_type='item', - item=warp_icon, - tooltip={'warp-list.cords',position.x,position.y}, - } - btn.style.height = 32 - btn.style.width = 32 - end end @@ -518,8 +540,8 @@ end >> header >>> right aligned add_new_task >> scroll - >>> no_tasks >>> table + >> warp_timer ]] local function generate_container(player,element) Gui.set_padding(element,2,2,2,2) @@ -552,7 +574,7 @@ local function generate_container(player,element) type='label', style='heading_1_label', caption={'warp-list.main-caption'}, - tooltip={'warp-list.sub-tooltip',config.time_limit,config.warp_radius} + tooltip={'warp-list.sub-tooltip',config.recharge_time,config.activation_range} } --- Right aligned button to toggle the section @@ -574,16 +596,6 @@ local function generate_container(player,element) flow.style.horizontally_stretchable = true flow.style.maximal_height = 258 - -- message to say that you have no tasks - local non_made = - flow.add{ - name='no_warps', - type='label', - caption={'warp-list.no-warps'} - } - non_made.style.width = 200 - non_made.style.single_line = false - -- table that stores all the data local flow_table = flow.add{ @@ -605,7 +617,7 @@ end warp_list = Gui.new_left_frame('gui/warp-list') :set_sprites('item/'..config.default_icon) -:set_tooltip{'warp-list.main-tooltip',config.warp_radius} +:set_tooltip{'warp-list.main-tooltip',config.activation_range} :set_direction('vertical') :on_draw(function(player,element) local data_table = generate_container(player,element) @@ -628,6 +640,7 @@ end) end end) +--- When the name of a warp is updated this is triggered Store.register(warp_name_store,function(value,warp_id) local warp = warp_details[warp_id] local force = game.forces[warp.force] @@ -651,6 +664,7 @@ Store.register(warp_name_store,function(value,warp_id) end end) +--- When the icon is updated this is called Store.register(warp_icon_store,function(value,warp_id) local warp = warp_details[warp_id] local force = game.forces[warp.force] @@ -668,7 +682,8 @@ Store.register(warp_icon_store,function(value,warp_id) end end) -Store.register(warp_allowed_store,function(value,player_name) +--- When the player leaves or enters range of a warp this is triggered +Store.register(warp_player_in_range_store,function(value,player_name) local player = game.players[player_name] local force = player.force local frame = warp_list:get_frame(player_name) @@ -678,12 +693,12 @@ Store.register(warp_allowed_store,function(value,player_name) if force_warps[force.name] then for _,warp_id in pairs(force_warps[force.name]) do - local element = table_area['icon-'..warp_id][goto_warp] + local element = table_area['icon-'..warp_id][goto_warp.name] if element and element.valid then element.enabled = state if state then local position = warp_details[warp_id].position - element.tooltip = {'warp-list.cords',position.x,position.y} + element.tooltip = {'warp-list.goto-tooltip',position.x,position.y} else element.tooltip = {'warp-list.goto-disabled'} end @@ -692,9 +707,10 @@ Store.register(warp_allowed_store,function(value,player_name) end end) -local r2 = config.warp_radius^2 -local rs2 = (config.warp_radius*config.spawn_radius_scale)^2 -Event.on_nth_tick(60/config.time_smothing,function() +--- Handles updating the timer and checking distance from a warp +local r2 = config.activation_range^2 +local rs2 = config.spawn_activation_range^2 +Event.on_nth_tick(math.floor(60/config.update_smothing),function() local categories = Store.get_children(warp_timer.store) for _,category in pairs(categories) do warp_timer:increment(1,category) @@ -702,10 +718,12 @@ Event.on_nth_tick(60/config.time_smothing,function() for _,player in pairs(game.connected_players) do local timer = warp_timer:get_store(player.name) - local role = config.no_warp_limit_permision and Roles.player_allowed(player,config.no_warp_limit_permision) + local role = config.bypass_warp_limits_permision and Roles.player_allowed(player,config.bypass_warp_limits_permision) + if not timer and not role then local force = player.force local warps = force_warps[force.name] + if warps then local surface = player.surface.index local pos = player.position @@ -717,25 +735,28 @@ Event.on_nth_tick(60/config.time_smothing,function() if warp.surface.index == surface then local dx,dy = px-wpos.x,py-wpos.y if not warp.editing and (dx*dx)+(dy*dy) < rs2 or (dx*dx)+(dy*dy) < r2 then - Store.set(warp_allowed_store,player.name,true) + Store.set(warp_player_in_range_store,player.name,true) return end end end - Store.set(warp_allowed_store,player.name,false) + Store.set(warp_player_in_range_store,player.name,false) end + end + end end) +--- When a player is created it will set them being in range to false to stop warping on join Event.add(defines.events.on_player_created,function(event) local player = Game.get_player_by_index(event.player_index) local force_name = player.force.name - local allowed = config.no_warp_limit_permision and Roles.player_allowed(player,config.no_warp_limit_permision) or false - Store.set(warp_allowed_store,player.name,allowed) + local allowed = config.bypass_warp_limits_permision and Roles.player_allowed(player,config.bypass_warp_limits_permision) or false + Store.set(warp_player_in_range_store,player.name,allowed) if not force_warps[force_name] then add_spawn(player)