From 9220cc58a904c08f4ac1532049042d10fa015eba Mon Sep 17 00:00:00 2001 From: MewMew <=> Date: Tue, 26 Feb 2019 18:42:36 +0100 Subject: [PATCH] updates --- control.lua | 7 +- maps/deep_jungle.lua | 5 +- maps/fish_defender.lua | 1 - maps/spiral_troopers.lua | 27 +- poll.lua | 1518 ++++++++++++++++++++++++++++++++------ poll_old.lua | 262 +++++++ 6 files changed, 1549 insertions(+), 271 deletions(-) create mode 100644 poll_old.lua diff --git a/control.lua b/control.lua index cc14c875..63b01acc 100644 --- a/control.lua +++ b/control.lua @@ -1,7 +1,7 @@ server_commands = require 'utils.server' require "utils.server_commands" require "utils.utils" -require "utils.corpse_util" +--require "utils.corpse_util" --disable for hunger games require "chatbot" require "commands" require "session_tracker" @@ -10,7 +10,7 @@ require "antigrief_admin_panel" require "group" require "player_list" require "poll" -require "score" +--require "score" ---- enable modules here ---- --require "maps.tools.cheat_mode" @@ -27,6 +27,7 @@ require "score" --require "maps.modules.dynamic_landfill" --require "maps.modules.players_trample_paths" --require "maps.modules.hunger_games" +--require "maps.modules.explosive_player_respawn" --require "maps.modules.burden" ----------------------------- @@ -42,7 +43,7 @@ require "score" --require "maps.fish_defender" --require "maps.mountain_fortress" --require "maps.stoneblock" -require "maps.deep_jungle" +--require "maps.deep_jungle" --require "maps.crossing" --require "maps.anarchy" --require "maps.railworld" diff --git a/maps/deep_jungle.lua b/maps/deep_jungle.lua index 2fe725a0..ccdeb8dd 100644 --- a/maps/deep_jungle.lua +++ b/maps/deep_jungle.lua @@ -1,17 +1,14 @@ --deep jungle-- mewmew made this -- -require "maps.modules.fluids_are_explosive" -require "maps.modules.explosives_are_explosive" require "maps.modules.railgun_enhancer" require "maps.modules.dynamic_landfill" require "maps.modules.spawners_contain_biters" require "maps.modules.biters_yield_coins" require "maps.modules.rocks_yield_coins" -require "maps.modules.explosive_player_respawn" require "maps.modules.flashlight_toggle_button" require "maps.modules.splice_double" require "maps.modules.spitters_spit_biters" require "maps.modules.biters_double_hp" -require "maps.modules.biters_double_damage" +require "maps.modules.rocks_broken_paint_tiles" require "maps.modules.rocks_yield_ore" local map_functions = require "maps.tools.map_functions" diff --git a/maps/fish_defender.lua b/maps/fish_defender.lua index 915a1eed..5b3e402b 100644 --- a/maps/fish_defender.lua +++ b/maps/fish_defender.lua @@ -11,7 +11,6 @@ require "maps.modules.custom_death_messages" require "maps.modules.splice_double" require "maps.modules.spitters_spit_biters" require "maps.modules.biters_double_hp" -require "maps.modules.custom_death_messages" local event = require 'utils.event' local map_functions = require "maps.tools.map_functions" diff --git a/maps/spiral_troopers.lua b/maps/spiral_troopers.lua index ed64b53f..59a4a6de 100644 --- a/maps/spiral_troopers.lua +++ b/maps/spiral_troopers.lua @@ -1,7 +1,10 @@ --spiral troopers-- mewmew wrote this -- inspired from kyte local event = require 'utils.event' -require "maps.tools.map_pregen" +require "maps.modules.dynamic_landfill" +require "maps.modules.spawners_contain_biters" +require "maps.modules.satellite_score" + local map_functions = require "maps.tools.map_functions" --require "rewards" @@ -543,17 +546,6 @@ local function on_robot_built_entity(event) on_built_entity(event) end -local biter_building_inhabitants = {} -biter_building_inhabitants[1] = {{"small-biter",8,16}} -biter_building_inhabitants[2] = {{"small-biter",16,24}} -biter_building_inhabitants[3] = {{"small-biter",8,16},{"medium-biter",4,8}} -biter_building_inhabitants[4] = {{"small-biter",4,8},{"medium-biter",6,10}} -biter_building_inhabitants[5] = {{"small-biter",5,6},{"medium-biter",8,12}} -biter_building_inhabitants[6] = {{"small-biter",2,4},{"medium-biter",6,8},{"big-biter",2,4}} -biter_building_inhabitants[7] = {{"medium-biter",6,8},{"big-biter",4,6}} -biter_building_inhabitants[8] = {{"medium-biter",2,4},{"big-biter",6,8}} -biter_building_inhabitants[9] = {{"medium-biter",2,3},{"big-biter",8,10},{"behemoth-biter",1,2}} -biter_building_inhabitants[10] = {{"big-biter",4,8},{"behemoth-biter",3,4}} local entity_drop_amount = { ['small-biter'] = {low = 10, high = 20}, ['small-spitter'] = {low = 10, high = 20}, @@ -566,15 +558,8 @@ local entity_drop_amount = { local ore_spill_raffle = {"iron-ore","iron-ore","iron-ore","iron-ore","iron-ore","coal","coal","coal","copper-ore","copper-ore","stone", "landfill"} local function on_entity_died(event) - if event.entity.name == "biter-spawner" or event.entity.name == "spitter-spawner" then - local e = math.ceil(game.forces.enemy.evolution_factor*10, 0) - for _, t in pairs (biter_building_inhabitants[e]) do - for x = 1, math.random(t[2],t[3]), 1 do - local p = event.entity.surface.find_non_colliding_position(t[1] , event.entity.position, 6, 1) - if p then event.entity.surface.create_entity {name=t[1], position=p} end - end - end - if math.random(1, 75) == 1 then + if event.entity.name == "biter-spawner" or event.entity.name == "spitter-spawner" then + if math.random(1, 50) == 1 then local amount = 100000 * (1 + (game.forces.enemy.evolution_factor * 20)) event.entity.surface.create_entity({name = "crude-oil", position = event.entity.position, amount = amount}) end diff --git a/poll.lua b/poll.lua index 80d9d49a..5316f77c 100644 --- a/poll.lua +++ b/poll.lua @@ -1,262 +1,1296 @@ --- create polls for players to vote on --- by MewMew -- with some help from RedLabel, Klonan, Morcup, BrainClot +local Gui = require 'utils.gui' +local Global = require 'utils.global' +local Event = require 'utils.event' +local Game = require 'utils.game' -local event = require 'utils.event' -local poll_duration_in_seconds = 99 +local insert = table.insert -local function create_poll_gui(player) - if player.gui.top.poll then return end - local button = player.gui.top.add { name = "poll", type = "sprite-button", sprite = "item/programmable-speaker", tooltip = "Show current poll" } - 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 +local default_poll_duration = 300 * 60 -- in ticks +local duration_max = 3600 -- in seconds +local duration_step = 15 -- in seconds + +local duration_slider_max = duration_max / duration_step +local tick_duration_step = duration_step * 60 +local inv_tick_duration_step = 1 / tick_duration_step + +local normal_color = {r = 250, g = 235, b = 215} +local focus_color = {r = 255, g = 165, b = 0} + +local polls = {} +local polls_counter = {0} +local no_notify_players = {} +local player_poll_index = {} +local player_create_poll_data = {} + +Global.register( + { + polls = polls, + polls_counter = polls_counter, + no_notify_players = no_notify_players, + player_poll_index = player_poll_index, + player_create_poll_data = player_create_poll_data + }, + function(tbl) + polls = tbl.polls + polls_counter = tbl.polls_counter + no_notify_players = tbl.no_notify_players + player_poll_index = tbl.player_poll_index + player_create_poll_data = tbl.player_create_poll_data + end +) + +local main_button_name = Gui.uid_name() +local main_frame_name = Gui.uid_name() +local create_poll_button_name = Gui.uid_name() +local notify_checkbox_name = Gui.uid_name() + +local poll_view_back_name = Gui.uid_name() +local poll_view_forward_name = Gui.uid_name() +local poll_view_vote_name = Gui.uid_name() +local poll_view_edit_name = Gui.uid_name() + +local create_poll_frame_name = Gui.uid_name() +local create_poll_duration_name = Gui.uid_name() +local create_poll_label_name = Gui.uid_name() +local create_poll_question_name = Gui.uid_name() +local create_poll_answer_name = Gui.uid_name() +local create_poll_add_answer_name = Gui.uid_name() +local create_poll_delete_answer_name = Gui.uid_name() +local create_poll_close_name = Gui.uid_name() +local create_poll_clear_name = Gui.uid_name() +local create_poll_edit_name = Gui.uid_name() +local create_poll_confirm_name = Gui.uid_name() +local create_poll_delete_name = Gui.uid_name() + +local function poll_id() + local count = polls_counter[1] + 1 + polls_counter[1] = count + return count end -local function poll_show(player) - if player.gui.left["poll-panel"] then player.gui.left["poll-panel"].destroy() end - - global.poll_panel_creation_times[player.index] = {player_index = player.index, tick = 5940} - - local frame = player.gui.left.add { type = "frame", name = "poll-panel", direction = "vertical" } - - local t = frame.add { type = "table", name = "poll_panel_table", column_count = 2 } - - if global.poll_question ~= "" then - - local str = "Poll #" .. global.score_total_polls_created .. ":" - if global.score_total_polls_created > 1 then - local x = game.tick - x = ((x / 60) / 60) / 60 - x = global.score_total_polls_created / x - x = math.round(x, 0) - str = str .. " (Polls/hour: " - str = str .. x - str = str .. ")" - end - - t.add { type = "label", caption = str, single_line = false, name = "poll_number_label" } - t.poll_number_label.style.font_color = { r=0.75, g=0.75, b=0.75} - t.add { type = "label"} - t.add { type = "label", caption = global.poll_question, name = "question_label" } - t.question_label.style.maximal_width = 208 - t.question_label.style.maximal_height = 170 - t.question_label.style.font = "default-bold" - t.question_label.style.font_color = { r=0.98, g=0.66, b=0.22} - t.question_label.style.single_line = false - t.add { type = "label" } - end - - for i = 1, 3, 1 do - if global.poll_answers[i] ~= "" then - local l = t.add({type = "label", caption = global.poll_answers[i], name = "answer_label_" .. tostring(i)}) - l.style.maximal_width = 208 - l.style.minimal_width = 208 - l.style.maximal_height = 165 - l.style.font = "default" - l.style.single_line = false - local b = t.add({type = "button", caption = global.poll_button_votes[i], name = "answer_button_" .. tostring(i)}) - b.style.font = "default-listbox" - b.style.minimal_width = 32 - end - end - - local t = frame.add { type = "table", name = "poll_panel_button_table", column_count = 3 } - - t.add { type = "button", caption = "New Poll", name = "new_poll_assembler_button" } - - local str = "Hide (" .. poll_duration_in_seconds - str = str .. ")" - - t.add { type = "button", caption = str, name = "poll_hide_button" } - - t.poll_hide_button.style.minimal_width = 70 - t.new_poll_assembler_button.style.font = "default-bold" - t.new_poll_assembler_button.style.minimal_height = 38 - t.poll_hide_button.style.font = "default-bold" - t.poll_hide_button.style.minimal_height = 38 - t.add { type = "checkbox", caption = "Show Polls", state = global.autoshow_polls_for_player[player.name], name = "auto_show_polls_checkbox" } +local function apply_direction_button_style(button) + local button_style = button.style + button_style.width = 24 + button_style.height = 24 + button_style.top_padding = 0 + button_style.bottom_padding = 0 + button_style.left_padding = 0 + button_style.right_padding = 0 + button_style.font = 'default-listbox' end -local function poll(player) - local frame = player.gui.left["poll-assembler"] - frame = frame.table_poll_assembler - - if frame.textfield_question.text == "" then return end - if frame.textfield_answer_1.text == "" and frame.textfield_answer_2.text == "" and frame.textfield_answer_3.text == "" then return end - - global.poll_question = frame.textfield_question.text - global.poll_answers = {frame.textfield_answer_1.text, frame.textfield_answer_2.text, frame.textfield_answer_3.text} - - local msg = player.name - msg = msg .. " has created a new Poll!" - - global.score_total_polls_created = global.score_total_polls_created + 1 - - player.gui.left["poll-assembler"].destroy() - - global.poll_voted = {} - global.poll_button_votes = {0,0,0} - - for _, player in pairs(game.players) do - if player.gui.left["poll-panel"] then - player.gui.left["poll-panel"].destroy() - end - if global.autoshow_polls_for_player[player.name] == true then - poll_show(player) - end - player.print(msg, { r=0.22, g=0.99, b=0.99}) - end +local function apply_button_style(button) + local button_style = button.style + button_style.font = 'default-bold' + button_style.height = 26 + button_style.top_padding = 0 + button_style.bottom_padding = 0 + button_style.left_padding = 2 + button_style.right_padding = 2 end -local function poll_refresh() - for _, player in pairs(game.players) do - if player.gui.left["poll-panel"] then - local frame = player.gui.left["poll-panel"] - frame = frame.poll_panel_table - if frame.answer_button_1 then frame.answer_button_1.caption = global.poll_button_votes[1] end - if frame.answer_button_2 then frame.answer_button_2.caption = global.poll_button_votes[2] end - if frame.answer_button_3 then frame.answer_button_3.caption = global.poll_button_votes[3] end - end - end +local function do_remaining_time(poll, remaining_time_label) + local end_tick = poll.end_tick + if end_tick == -1 then + remaining_time_label.caption = 'Endless Poll.' + return true + end + + local ticks = end_tick - game.tick + if ticks < 0 then + remaining_time_label.caption = 'Poll Finished.' + return false + else + local time = math.ceil(ticks / 60) + remaining_time_label.caption = 'Remaining Time: ' .. time + return true + end end -local function poll_assembler(player) - local frame = player.gui.left.add { type = "frame", name = "poll-assembler", caption = "" } - local frame_table = frame.add { type = "table", name = "table_poll_assembler", column_count = 2 } - frame_table.add { type = "label", caption = "Question:" } - frame_table.add { type = "textfield", name = "textfield_question", text = "" } - frame_table.add { type = "label", caption = "Answer #1:" } - frame_table.add { type = "textfield", name = "textfield_answer_1", text = "" } - frame_table.add { type = "label", caption = "Answer #2:" } - frame_table.add { type = "textfield", name = "textfield_answer_2", text = "" } - frame_table.add { type = "label", caption = "Answer #3:" } - frame_table.add { type = "textfield", name = "textfield_answer_3", text = "" } - frame_table.add { type = "label", caption = "" } - frame_table.add { type = "button", name = "create_new_poll_button", caption = "Create" } +local function send_poll_result_to_discord(poll) + local result = {'Poll #', poll.id} + + local created_by_player = poll.created_by + if created_by_player and created_by_player.valid then + insert(result, ' Created by ') + insert(result, created_by_player.name) + end + + local edited_by_players = poll.edited_by + if next(edited_by_players) then + insert(result, ' Edited by ') + for pi, _ in pairs(edited_by_players) do + local p = game.players[pi] + if p and p.valid then + insert(result, p.name) + insert(result, ', ') + end + end + table.remove(result) + end + + insert(result, '\\n**Question: ') + insert(result, poll.question) + insert(result, '**\\n') + + local answers = poll.answers + local answers_count = #answers + for i, a in pairs(answers) do + insert(result, '[') + insert(result, a.voted_count) + insert(result, '] - ') + insert(result, a.text) + if i ~= answers_count then + insert(result, '\\n') + end + end + + local message = table.concat(result) + server_commands.to_discord_embed(message) end -function on_player_joined_game(event) - if not global.poll_init_done then - global.poll_panel_creation_times = {} - global.poll_voted = {} - global.poll_question = "" - global.poll_answers = {"","",""} - global.poll_button_votes = {0,0,0} - global.poll_voted = {} - global.autoshow_polls_for_player = {} - global.score_total_polls_created = 0 - global.poll_init_done = true - end - - local player = game.players[event.player_index] - - if not global.autoshow_polls_for_player[player.name] then global.autoshow_polls_for_player[player.name] = true end - - create_poll_gui(player) - - if global.poll_question == "" then return end - - poll_show(player) +local function redraw_poll_viewer_content(data) + local poll_viewer_content = data.poll_viewer_content + local remaining_time_label = data.remaining_time_label + local poll_index = data.poll_index + local player = poll_viewer_content.gui.player + + data.vote_buttons = nil + Gui.remove_data_recursively(poll_viewer_content) + poll_viewer_content.clear() + + local poll = polls[poll_index] + if not poll then + return + end + + local answers = poll.answers + local voters = poll.voters + + local tooltips = {} + for _, a in pairs(answers) do + tooltips[a] = {} + end + + for player_index, answer in pairs(voters) do + local p = Game.get_player_by_index(player_index) + insert(tooltips[answer], p.name) + end + + for a, t in pairs(tooltips) do + if #t == 0 then + tooltips[a] = '' + else + tooltips[a] = table.concat(t, ', ') + end + end + + local created_by_player = poll.created_by + local created_by_text + if created_by_player and created_by_player.valid then + created_by_text = ' Created by ' .. created_by_player.name + else + created_by_text = '' + end + + local top_flow = poll_viewer_content.add {type = 'flow', direction = 'horizontal'} + top_flow.add {type = 'label', caption = table.concat {'Poll #', poll.id, created_by_text}} + + local edited_by_players = poll.edited_by + if next(edited_by_players) then + local edit_names = {'Edited by '} + for pi, _ in pairs(edited_by_players) do + local p = Game.get_player_by_index(pi) + if p and p.valid then + insert(edit_names, p.name) + insert(edit_names, ', ') + end + end + + table.remove(edit_names) + local edit_text = table.concat(edit_names) + + top_flow.add {type = 'label', caption = edit_text, tooltip = edit_text} + end + + local poll_enabled = do_remaining_time(poll, remaining_time_label) + + local question_flow = poll_viewer_content.add {type = 'table', column_count = 2} + + if global.trusted_players[player.name] or player.admin then + local edit_button = + question_flow.add { + type = 'sprite-button', + name = poll_view_edit_name, + sprite = 'utility/rename_icon_normal', + tooltip = 'Edit Poll.' + } + + local edit_button_style = edit_button.style + edit_button_style.width = 26 + edit_button_style.height = 26 + end + + local question_label = question_flow.add {type = 'label', caption = poll.question} + question_label.style.height = 32 + question_label.style.font_color = focus_color + question_label.style.font = 'default-listbox' + + local grid = poll_viewer_content.add {type = 'table', column_count = 2} + + local answer = voters[player.index] + local vote_buttons = {} + for i, a in pairs(answers) do + local vote_button_flow = grid.add {type = 'flow'} + local vote_button = + vote_button_flow.add { + type = 'button', + name = poll_view_vote_name, + caption = a.voted_count, + enabled = poll_enabled + } + + local tooltip = tooltips[a] + if tooltip ~= '' then + vote_button.tooltip = tooltip + end + + local vote_button_style = vote_button.style + vote_button_style.height = 24 + vote_button_style.width = 26 + vote_button_style.font = 'default-small' + vote_button_style.top_padding = 0 + vote_button_style.bottom_padding = 0 + vote_button_style.left_padding = 0 + vote_button_style.right_padding = 0 + + if answer == a then + vote_button_style.font_color = focus_color + vote_button_style.disabled_font_color = focus_color + end + + Gui.set_data(vote_button, {answer = a, data = data}) + vote_buttons[i] = vote_button + + local label = grid.add {type = 'label', caption = a.text} + label.style.height = 24 + end + + data.vote_buttons = vote_buttons end -local function on_gui_click(event) - if not event then return end - if not event.element then return end - if not event.element.valid then return end - - local player = game.players[event.element.player_index] - local name = event.element.name - - if name == "poll" then - global.poll_panel_creation_times[player.index] = nil - - local frame = player.gui.left["poll-panel"] - if frame then - frame.destroy() - else - poll_show(player) - end - - local frame = player.gui.left["poll-assembler"] - if frame then - frame.destroy() - end - end - - if name == "new_poll_assembler_button" then - local frame = player.gui.left["poll-assembler"] - if (frame) then - frame.destroy() - else - poll_assembler(player) - end - end - - if name == "create_new_poll_button" then - poll(player) - end - - if name == "poll_hide_button" then - player.gui.left["poll-panel"].destroy() - global.poll_panel_creation_times[player.index] = nil - if player.gui.left["poll-assembler"] then - player.gui.left["poll-assembler"].destroy() - end - end - - if name == "auto_show_polls_checkbox" then - global.autoshow_polls_for_player[player.name] = event.element.state - end - - if global.poll_voted[event.player_index] == nil then - - if name == "answer_button_1" then - global.poll_button_votes[1] = global.poll_button_votes[1] + 1 - global.poll_voted[event.player_index] = player.name - poll_refresh() - end - - if name == "answer_button_2" then - global.poll_button_votes[2] = global.poll_button_votes[2] + 1 - global.poll_voted[event.player_index] = player.name - poll_refresh() - end - - if name == "answer_button_3" then - global.poll_button_votes[3] = global.poll_button_votes[3] + 1 - global.poll_voted[event.player_index] = player.name - poll_refresh() - end - - end +local function update_poll_viewer(data) + local back_button = data.back_button + local forward_button = data.forward_button + local poll_index_label = data.poll_index_label + local poll_index = data.poll_index + + if #polls == 0 then + poll_index = 0 + else + poll_index = math.clamp(poll_index, 1, #polls) + end + + data.poll_index = poll_index + + if poll_index == 0 then + poll_index_label.caption = 'No Polls' + else + poll_index_label.caption = table.concat {'Poll ', poll_index, ' / ', #polls} + end + + back_button.enabled = poll_index > 1 + forward_button.enabled = poll_index < #polls + + redraw_poll_viewer_content(data) end -local function process_timeout(creation_time) - local player = game.players[creation_time.player_index] - local frame = player.gui.left["poll-panel"] - global.poll_panel_creation_times[player.index].tick = global.poll_panel_creation_times[player.index].tick - 60 - if global.poll_panel_creation_times[player.index].tick <= 0 then - if frame then frame.destroy() end - global.poll_panel_creation_times[player.index] = nil - return - else - if frame then - frame.poll_panel_button_table.poll_hide_button.caption = "Hide (" .. math.ceil(global.poll_panel_creation_times[player.index].tick / 60) .. ")" - end - end +local function draw_main_frame(left, player) + local frame = left.add {type = 'frame', name = main_frame_name, caption = 'Polls', direction = 'vertical'} + frame.style.maximal_width = 320 + + local poll_viewer_top_flow = frame.add {type = 'table', column_count = 5} + poll_viewer_top_flow.style.horizontal_spacing = 0 + + local back_button = poll_viewer_top_flow.add {type = 'button', name = poll_view_back_name, caption = '◀'} + apply_direction_button_style(back_button) + + local forward_button = poll_viewer_top_flow.add {type = 'button', name = poll_view_forward_name, caption = '▶'} + apply_direction_button_style(forward_button) + + local poll_index_label = poll_viewer_top_flow.add {type = 'label'} + poll_index_label.style.left_padding = 8 + + local spacer = poll_viewer_top_flow.add {type = 'flow'} + spacer.style.horizontally_stretchable = true + + local remaining_time_label = poll_viewer_top_flow.add {type = 'label'} + + local poll_viewer_content = frame.add {type = 'scroll-pane'} + poll_viewer_content.style.maximal_height = 250 + poll_viewer_content.style.width = 300 + + local poll_index = player_poll_index[player.index] or #polls + + local data = { + back_button = back_button, + forward_button = forward_button, + poll_index_label = poll_index_label, + poll_viewer_content = poll_viewer_content, + remaining_time_label = remaining_time_label, + poll_index = poll_index + } + + Gui.set_data(frame, data) + Gui.set_data(back_button, data) + Gui.set_data(forward_button, data) + + update_poll_viewer(data) + + frame.add { + type = 'checkbox', + name = notify_checkbox_name, + caption = 'Notify me about polls.', + state = not no_notify_players[player.index], + tooltip = 'Receive a message when new polls are created and popup the poll.' + } + + local bottom_flow = frame.add {type = 'flow', direction = 'horizontal'} + + local left_flow = bottom_flow.add {type = 'flow'} + left_flow.style.align = 'left' + left_flow.style.horizontally_stretchable = true + + local close_button = left_flow.add {type = 'button', name = main_button_name, caption = 'Close'} + apply_button_style(close_button) + + local right_flow = bottom_flow.add {type = 'flow'} + right_flow.style.align = 'right' + + if global.trusted_players[player.name] or player.admin then + local create_poll_button = + right_flow.add {type = 'button', name = create_poll_button_name, caption = 'Create Poll'} + apply_button_style(create_poll_button) + else + local create_poll_button = + right_flow.add { + type = 'button', + caption = 'Create Poll', + enabled = false, + tooltip = 'Sorry, you need to be a regular to create polls.' + } + apply_button_style(create_poll_button) + end end -local function on_tick() - if game.tick % 60 ~= 0 then return end - for _, creation_time in pairs(global.poll_panel_creation_times) do - process_timeout(creation_time) - end +local function remove_create_poll_frame(create_poll_frame, player_index) + local data = Gui.get_data(create_poll_frame) + + data.edit_mode = nil + player_create_poll_data[player_index] = data + + Gui.remove_data_recursively(create_poll_frame) + create_poll_frame.destroy() end -event.add(defines.events.on_tick, on_tick) -event.add(defines.events.on_gui_click, on_gui_click) -event.add(defines.events.on_player_joined_game, on_player_joined_game) \ No newline at end of file +local function remove_main_frame(main_frame, left, player) + local player_index = player.index + local data = Gui.get_data(main_frame) + player_poll_index[player_index] = data.poll_index + + Gui.remove_data_recursively(main_frame) + main_frame.destroy() + + local create_poll_frame = left[create_poll_frame_name] + if create_poll_frame and create_poll_frame.valid then + remove_create_poll_frame(create_poll_frame, player_index) + end +end + +local function toggle(event) + local left = event.player.gui.left + local main_frame = left[main_frame_name] + + if main_frame then + remove_main_frame(main_frame, left, event.player) + else + draw_main_frame(left, event.player) + end +end + +local function update_duration(slider) + local slider_data = Gui.get_data(slider) + local label = slider_data.duration_label + local value = slider.slider_value + + value = math.floor(value) + + slider_data.data.duration = value * tick_duration_step + + if value == 0 then + label.caption = 'Endless Poll.' + else + label.caption = value * duration_step .. ' seconds.' + end +end + +local function redraw_create_poll_content(data) + local grid = data.grid + local answers = data.answers + + Gui.remove_data_recursively(grid) + grid.clear() + + grid.add {type = 'flow'} + grid.add { + type = 'label', + caption = 'Duration:', + tooltip = 'Pro tip: Use mouse wheel or arrow keys for more fine control.' + } + + local duration_flow = grid.add {type = 'flow', direction = 'horizontal'} + local duration_slider = + duration_flow.add { + type = 'slider', + name = create_poll_duration_name, + minimum_value = 0, + maximum_value = duration_slider_max, + value = math.floor(data.duration * inv_tick_duration_step) + } + duration_slider.style.width = 100 + + data.duration_slider = duration_slider + + local duration_label = duration_flow.add {type = 'label'} + + Gui.set_data(duration_slider, {duration_label = duration_label, data = data}) + + update_duration(duration_slider) + + grid.add {type = 'flow'} + local question_label = + grid.add({type = 'flow'}).add {type = 'label', name = create_poll_label_name, caption = 'Question:'} + + local question_textfield = + grid.add({type = 'flow'}).add {type = 'textfield', name = create_poll_question_name, text = data.question} + question_textfield.style.width = 400 + + Gui.set_data(question_label, question_textfield) + Gui.set_data(question_textfield, data) + + local edit_mode = data.edit_mode + for count, answer in pairs(answers) do + local delete_flow = grid.add {type = 'flow'} + + local delete_button + if edit_mode or count ~= 1 then + delete_button = + delete_flow.add { + type = 'sprite-button', + name = create_poll_delete_answer_name, + sprite = 'utility/remove', + tooltip = 'Delete answer field.' + } + delete_button.style.height = 26 + delete_button.style.width = 26 + else + delete_flow.style.height = 26 + delete_flow.style.width = 26 + end + + local label_flow = grid.add {type = 'flow'} + local label = + label_flow.add { + type = 'label', + name = create_poll_label_name, + caption = table.concat {'Answer #', count, ':'} + } + + local textfield_flow = grid.add {type = 'flow'} + + local textfield = textfield_flow.add {type = 'textfield', name = create_poll_answer_name, text = answer.text} + textfield.style.width = 400 + Gui.set_data(textfield, {answers = answers, count = count}) + + if delete_button then + Gui.set_data(delete_button, {data = data, count = count}) + end + + Gui.set_data(label, textfield) + end +end + +local function draw_create_poll_frame(parent, player, previous_data) + previous_data = previous_data or player_create_poll_data[player.index] + + local edit_mode + local question + local answers + local duration + local title_text + local confirm_text + local confirm_name + if previous_data then + edit_mode = previous_data.edit_mode + + question = previous_data.question + + answers = {} + for i, a in pairs(previous_data.answers) do + answers[i] = {text = a.text, source = a} + end + + duration = previous_data.duration + else + question = '' + answers = {{text = ''}, {text = ''}, {text = ''}} + duration = default_poll_duration + end + + if edit_mode then + title_text = 'Edit Poll #' .. previous_data.id + confirm_text = 'Edit Poll' + confirm_name = create_poll_edit_name + else + title_text = 'New Poll' + confirm_text = 'Create Poll' + confirm_name = create_poll_confirm_name + end + + local frame = + parent.add {type = 'frame', name = create_poll_frame_name, caption = title_text, direction = 'vertical'} + frame.style.maximal_width = 320 + + local scroll_pane = frame.add {type = 'scroll-pane', vertical_scroll_policy = 'always'} + scroll_pane.style.maximal_height = 250 + scroll_pane.style.maximal_width = 300 + + local grid = scroll_pane.add {type = 'table', column_count = 3} + + local data = { + frame = frame, + grid = grid, + question = question, + answers = answers, + duration = duration, + previous_data = previous_data, + edit_mode = edit_mode + } + + Gui.set_data(frame, data) + + redraw_create_poll_content(data) + + local add_answer_button = + scroll_pane.add { + type = 'button', + name = create_poll_add_answer_name, + caption = 'Add Answer' + } + apply_button_style(add_answer_button) + Gui.set_data(add_answer_button, data) + + local bottom_flow = frame.add {type = 'flow', direction = 'horizontal'} + + local left_flow = bottom_flow.add {type = 'flow'} + left_flow.style.align = 'left' + left_flow.style.horizontally_stretchable = true + + local close_button = left_flow.add {type = 'button', name = create_poll_close_name, caption = 'Close'} + apply_button_style(close_button) + Gui.set_data(close_button, frame) + + local clear_button = left_flow.add {type = 'button', name = create_poll_clear_name, caption = 'Clear'} + apply_button_style(clear_button) + Gui.set_data(clear_button, data) + + local right_flow = bottom_flow.add {type = 'flow'} + right_flow.style.align = 'right' + + if edit_mode then + local delete_button = right_flow.add {type = 'button', name = create_poll_delete_name, caption = 'Delete'} + apply_button_style(delete_button) + Gui.set_data(delete_button, data) + end + + local confirm_button = right_flow.add {type = 'button', name = confirm_name, caption = confirm_text} + apply_button_style(confirm_button) + Gui.set_data(confirm_button, data) +end + +local function show_new_poll(poll_data) + local message = + table.concat {poll_data.created_by.name, ' has created a new Poll #', poll_data.id, ': ', poll_data.question} + + for _, p in pairs(game.connected_players) do + local left = p.gui.left + local frame = left[main_frame_name] + if no_notify_players[p.index] then + if frame and frame.valid then + local data = Gui.get_data(frame) + update_poll_viewer(data) + end + else + p.print(message) + + if frame and frame.valid then + local data = Gui.get_data(frame) + data.poll_index = #polls + update_poll_viewer(data) + else + player_poll_index[p.index] = nil + draw_main_frame(left, p) + end + end + end +end + +local function create_poll(event) + local player = event.player + local data = Gui.get_data(event.element) + + local frame = data.frame + local question = data.question + + if not question:find('%S') then + event.player.print('Sorry, the poll needs a question.') + return + end + + local answers = {} + for _, a in pairs(data.answers) do + local text = a.text + if text:find('%S') then + local index = #answers + 1 + answers[index] = {text = text, index = index, voted_count = 0} + end + end + + if #answers < 1 then + player.print('Sorry, the poll needs at least one answer.') + return + end + + player_create_poll_data[player.index] = nil + + local tick = game.tick + local duration = data.duration + local end_tick + + if duration == 0 then + end_tick = -1 + else + end_tick = tick + duration + end + + local poll_data = { + id = poll_id(), + question = question, + answers = answers, + voters = {}, + start_tick = tick, + end_tick = end_tick, + duration = duration, + created_by = event.player, + edited_by = {} + } + + insert(polls, poll_data) + + show_new_poll(poll_data) + send_poll_result_to_discord(poll_data) + + Gui.remove_data_recursively(frame) + frame.destroy() +end + +local function update_vote(voters, answer, direction) + local count = answer.voted_count + direction + answer.voted_count = count + + local tooltip = {} + for pi, a in pairs(voters) do + if a == answer then + local player = Game.get_player_by_index(pi) + insert(tooltip, player.name) + end + end + + return tostring(count), table.concat(tooltip, ', ') +end + +local function vote(event) + local player_index = event.player_index + local voted_button = event.element + local button_data = Gui.get_data(voted_button) + local answer = button_data.answer + + local poll_index = button_data.data.poll_index + local poll = polls[poll_index] + + local voters = poll.voters + + local previous_vote_answer = voters[player_index] + if previous_vote_answer == answer then + return + end + + local vote_index = answer.index + + voters[player_index] = answer + + local previous_vote_button_count + local previous_vote_button_tooltip + local previous_vote_index + if previous_vote_answer then + previous_vote_button_count, previous_vote_button_tooltip = update_vote(voters, previous_vote_answer, -1) + previous_vote_index = previous_vote_answer.index + end + + local vote_button_count, vote_button_tooltip = update_vote(voters, answer, 1) + + for _, p in pairs(game.connected_players) do + local frame = p.gui.left[main_frame_name] + if frame and frame.valid then + local data = Gui.get_data(frame) + + if data.poll_index == poll_index then + local vote_buttons = data.vote_buttons + if previous_vote_answer then + local vote_button = vote_buttons[previous_vote_index] + vote_button.caption = previous_vote_button_count + vote_button.tooltip = previous_vote_button_tooltip + + if p.index == player_index then + local vote_button_style = vote_button.style + vote_button_style.font_color = normal_color + vote_button_style.disabled_font_color = normal_color + end + end + + local vote_button = vote_buttons[vote_index] + vote_button.caption = vote_button_count + vote_button.tooltip = vote_button_tooltip + + if p.index == player_index then + local vote_button_style = vote_button.style + vote_button_style.font_color = focus_color + vote_button_style.disabled_font_color = focus_color + end + end + end + end +end + +local function player_joined(event) + local player = Game.get_player_by_index(event.player_index) + if not player or not player.valid then + return + end + + local gui = player.gui + if gui.top[main_button_name] ~= nil then + local frame = gui.left[main_frame_name] + if frame and frame.valid then + local data = Gui.get_data(frame) + update_poll_viewer(data) + end + else + gui.top.add {type = 'sprite-button', name = main_button_name, sprite = 'item/programmable-speaker'} + end +end + +local function tick() + for _, p in pairs(game.connected_players) do + local frame = p.gui.left[main_frame_name] + if frame and frame.valid then + local data = Gui.get_data(frame) + local poll = polls[data.poll_index] + if poll then + local poll_enabled = do_remaining_time(poll, data.remaining_time_label) + + if not poll_enabled then + for _, v in pairs(data.vote_buttons) do + v.enabled = poll_enabled + end + end + end + end + end +end + +Event.add(defines.events.on_player_joined_game, player_joined) +Event.on_nth_tick(60, tick) + +Gui.on_click(main_button_name, toggle) + +Gui.on_click( + create_poll_button_name, + function(event) + local player = event.player + local left = player.gui.left + local frame = left[create_poll_frame_name] + if frame and frame.valid then + remove_create_poll_frame(frame, player.index) + else + draw_create_poll_frame(left, player) + end + end +) + +Gui.on_click( + poll_view_edit_name, + function(event) + local player = event.player + local left = player.gui.left + local frame = left[create_poll_frame_name] + + if frame and frame.valid then + Gui.remove_data_recursively(frame) + frame.destroy() + end + + local main_frame = left[main_frame_name] + local frame_data = Gui.get_data(main_frame) + local poll = polls[frame_data.poll_index] + + poll.edit_mode = true + draw_create_poll_frame(left, player, poll) + end +) + +Gui.on_value_changed( + create_poll_duration_name, + function(event) + update_duration(event.element) + end +) + +Gui.on_click( + create_poll_delete_answer_name, + function(event) + local button_data = Gui.get_data(event.element) + local data = button_data.data + + table.remove(data.answers, button_data.count) + redraw_create_poll_content(data) + end +) + +Gui.on_click( + create_poll_label_name, + function(event) + local textfield = Gui.get_data(event.element) + textfield.focus() + end +) + +Gui.on_text_changed( + create_poll_question_name, + function(event) + local textfield = event.element + local data = Gui.get_data(textfield) + + data.question = textfield.text + end +) + +Gui.on_text_changed( + create_poll_answer_name, + function(event) + local textfield = event.element + local data = Gui.get_data(textfield) + + data.answers[data.count].text = textfield.text + end +) + +Gui.on_click( + create_poll_add_answer_name, + function(event) + local data = Gui.get_data(event.element) + + insert(data.answers, {text = ''}) + redraw_create_poll_content(data) + end +) + +Gui.on_click( + create_poll_close_name, + function(event) + local frame = Gui.get_data(event.element) + remove_create_poll_frame(frame, event.player_index) + end +) + +Gui.on_click( + create_poll_clear_name, + function(event) + local data = Gui.get_data(event.element) + + local slider = data.duration_slider + slider.slider_value = math.floor(default_poll_duration * inv_tick_duration_step) + update_duration(slider) + + data.question = '' + + local answers = data.answers + for i = 1, #answers do + answers[i].text = '' + end + + redraw_create_poll_content(data) + end +) + +Gui.on_click(create_poll_confirm_name, create_poll) + +Gui.on_click( + create_poll_delete_name, + function(event) + local player = event.player + local data = Gui.get_data(event.element) + local frame = data.frame + local poll = data.previous_data + + Gui.remove_data_recursively(frame) + frame.destroy() + + player_create_poll_data[player.index] = nil + + local removed_index + for i, p in pairs(polls) do + if p == poll then + table.remove(polls, i) + removed_index = i + break + end + end + + if not removed_index then + return + end + + local message = table.concat {player.name, ' has deleted Poll #', poll.id, ': ', poll.question} + + for _, p in pairs(game.connected_players) do + if not no_notify_players[p.index] then + p.print(message) + end + + local main_frame = p.gui.left[main_frame_name] + if main_frame and main_frame.valid then + local main_frame_data = Gui.get_data(main_frame) + local poll_index = main_frame_data.poll_index + + if removed_index < poll_index then + main_frame_data.poll_index = poll_index - 1 + end + + update_poll_viewer(main_frame_data) + end + end + end +) + +Gui.on_click( + create_poll_edit_name, + function(event) + local player = event.player + local data = Gui.get_data(event.element) + local frame = data.frame + local poll = data.previous_data + + local new_question = data.question + if not new_question:find('%S') then + player.print('Sorry, the poll needs a question.') + return + end + + local new_answer_set = {} + local new_answers = {} + for _, a in pairs(data.answers) do + if a.text:find('%S') then + local source = a.source + local index = #new_answers + 1 + if source then + new_answer_set[source] = a + source.text = a.text + source.index = index + new_answers[index] = source + else + new_answers[index] = {text = a.text, index = index, voted_count = 0} + end + end + end + + if not next(new_answers) then + player.print('Sorry, the poll needs at least one answer.') + return + end + + Gui.remove_data_recursively(frame) + frame.destroy() + + local player_index = player.index + + player_create_poll_data[player_index] = nil + + local old_answers = poll.answers + local voters = poll.voters + for _, a in pairs(old_answers) do + if not new_answer_set[a] then + for pi, a2 in pairs(voters) do + if a == a2 then + voters[pi] = nil + end + end + end + end + + poll.question = new_question + poll.answers = new_answers + poll.edited_by[player_index] = true + + local start_tick = game.tick + local duration = data.duration + local end_tick + + if duration == 0 then + end_tick = -1 + else + end_tick = start_tick + duration + end + + poll.start_tick = start_tick + poll.end_tick = end_tick + poll.duration = duration + + local poll_index + for i, p in pairs(polls) do + if poll == p then + poll_index = i + break + end + end + + if not poll_index then + insert(polls, poll) + poll_index = #polls + end + + local message = table.concat {player.name, ' has edited Poll #', poll.id, ': ', poll.question} + + for _, p in pairs(game.connected_players) do + local main_frame = p.gui.left[main_frame_name] + + if no_notify_players[p.index] then + if main_frame and main_frame.valid then + local main_frame_data = Gui.get_data(main_frame) + update_poll_viewer(main_frame_data) + end + else + p.print(message) + if main_frame and main_frame.valid then + local main_frame_data = Gui.get_data(main_frame) + main_frame_data.poll_index = poll_index + update_poll_viewer(main_frame_data) + else + draw_main_frame(p.gui.left, p) + end + end + end + end +) + +Gui.on_click( + notify_checkbox_name, + function(event) + local player_index = event.player_index + local checkbox = event.element + + local new_state + if checkbox.state then + new_state = nil + else + new_state = true + end + + no_notify_players[player_index] = new_state + end +) + +local function do_direction(event, sign) + local count + if event.shift then + count = #polls + else + local button = event.button + if button == defines.mouse_button_type.right then + count = 5 + else + count = 1 + end + end + + count = count * sign + + local data = Gui.get_data(event.element) + data.poll_index = data.poll_index + count + update_poll_viewer(data) +end + +Gui.on_click( + poll_view_back_name, + function(event) + do_direction(event, -1) + end +) + +Gui.on_click( + poll_view_forward_name, + function(event) + do_direction(event, 1) + end +) + +Gui.on_click(poll_view_vote_name, vote) + +Gui.allow_player_to_toggle_top_element_visibility(main_button_name) + +local Class = {} + +function Class.validate(data) + if type(data) ~= 'table' then + return false, 'argument must be of type table' + end + + local question = data.question + if type(question) ~= 'string' or question == '' then + return false, 'field question must be a non empty string.' + end + + local answers = data.answers + if type(answers) ~= 'table' then + return false, 'answers field must be an array.' + end + + if #answers == 0 then + return false, 'answer array must contain at least one entry.' + end + + for _, a in pairs(answers) do + if type(a) ~= 'string' or a == '' then + return false, 'answers must be a non empty string.' + end + end + + local duration = data.duration + local duration_type = type(duration) + if duration_type == 'number' then + if duration < 0 then + return false, 'duration cannot be negative, set duration to 0 for endless poll.' + end + elseif duration_type ~= 'nil' then + return false, 'duration must be of type number or nil' + end + + return true +end + +function Class.poll(data) + local suc, error = Class.validate(data) + if not suc then + return false, error + end + + local answers = {} + for index, a in pairs(data.answers) do + if a ~= '' then + insert(answers, {text = a, index = index, voted_count = 0}) + end + end + + local duration = data.duration + if duration then + duration = duration * 60 + else + duration = default_poll_duration + end + + local start_tick = game.tick + local end_tick + if duration == 0 then + end_tick = -1 + else + end_tick = start_tick + duration + end + + local id = poll_id() + + local poll_data = { + id = id, + question = data.question, + answers = answers, + voters = {}, + start_tick = start_tick, + end_tick = end_tick, + duration = duration, + created_by = game.player or {name = '', valid = true}, + edited_by = {} + } + + insert(polls, poll_data) + + show_new_poll(poll_data) + send_poll_result_to_discord(poll_data) + + return true, id +end + +function Class.poll_result(id) + if type(id) ~= 'number' then + return 'poll-id must be a number' + end + + for _, poll_data in pairs(polls) do + if poll_data.id == id then + local result = {'Question: ', poll_data.question, ' Answers: '} + local answers = poll_data.answers + local answers_count = #answers + for i, a in pairs(answers) do + insert(result, '( [') + insert(result, a.voted_count) + insert(result, '] - ') + insert(result, a.text) + insert(result, ' )') + if i ~= answers_count then + insert(result, ', ') + end + end + + return table.concat(result) + end + end + + return table.concat {'poll #', id, ' not found'} +end + +function Class.send_poll_result_to_discord(id) + if type(id) ~= 'number' then + server_commands.to_discord_embed('poll-id must be a number') + return + end + + for _, poll_data in pairs(polls) do + if poll_data.id == id then + send_poll_result_to_discord(poll_data) + return + end + end + + local message = table.concat {'poll #', id, ' not found'} + server_commands.to_discord_embed(message) +end + +return Class \ No newline at end of file diff --git a/poll_old.lua b/poll_old.lua new file mode 100644 index 00000000..80d9d49a --- /dev/null +++ b/poll_old.lua @@ -0,0 +1,262 @@ +-- create polls for players to vote on +-- by MewMew -- with some help from RedLabel, Klonan, Morcup, BrainClot + +local event = require 'utils.event' +local poll_duration_in_seconds = 99 + +local function create_poll_gui(player) + if player.gui.top.poll then return end + local button = player.gui.top.add { name = "poll", type = "sprite-button", sprite = "item/programmable-speaker", tooltip = "Show current poll" } + 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 +end + +local function poll_show(player) + if player.gui.left["poll-panel"] then player.gui.left["poll-panel"].destroy() end + + global.poll_panel_creation_times[player.index] = {player_index = player.index, tick = 5940} + + local frame = player.gui.left.add { type = "frame", name = "poll-panel", direction = "vertical" } + + local t = frame.add { type = "table", name = "poll_panel_table", column_count = 2 } + + if global.poll_question ~= "" then + + local str = "Poll #" .. global.score_total_polls_created .. ":" + if global.score_total_polls_created > 1 then + local x = game.tick + x = ((x / 60) / 60) / 60 + x = global.score_total_polls_created / x + x = math.round(x, 0) + str = str .. " (Polls/hour: " + str = str .. x + str = str .. ")" + end + + t.add { type = "label", caption = str, single_line = false, name = "poll_number_label" } + t.poll_number_label.style.font_color = { r=0.75, g=0.75, b=0.75} + t.add { type = "label"} + t.add { type = "label", caption = global.poll_question, name = "question_label" } + t.question_label.style.maximal_width = 208 + t.question_label.style.maximal_height = 170 + t.question_label.style.font = "default-bold" + t.question_label.style.font_color = { r=0.98, g=0.66, b=0.22} + t.question_label.style.single_line = false + t.add { type = "label" } + end + + for i = 1, 3, 1 do + if global.poll_answers[i] ~= "" then + local l = t.add({type = "label", caption = global.poll_answers[i], name = "answer_label_" .. tostring(i)}) + l.style.maximal_width = 208 + l.style.minimal_width = 208 + l.style.maximal_height = 165 + l.style.font = "default" + l.style.single_line = false + local b = t.add({type = "button", caption = global.poll_button_votes[i], name = "answer_button_" .. tostring(i)}) + b.style.font = "default-listbox" + b.style.minimal_width = 32 + end + end + + local t = frame.add { type = "table", name = "poll_panel_button_table", column_count = 3 } + + t.add { type = "button", caption = "New Poll", name = "new_poll_assembler_button" } + + local str = "Hide (" .. poll_duration_in_seconds + str = str .. ")" + + t.add { type = "button", caption = str, name = "poll_hide_button" } + + t.poll_hide_button.style.minimal_width = 70 + t.new_poll_assembler_button.style.font = "default-bold" + t.new_poll_assembler_button.style.minimal_height = 38 + t.poll_hide_button.style.font = "default-bold" + t.poll_hide_button.style.minimal_height = 38 + t.add { type = "checkbox", caption = "Show Polls", state = global.autoshow_polls_for_player[player.name], name = "auto_show_polls_checkbox" } +end + +local function poll(player) + local frame = player.gui.left["poll-assembler"] + frame = frame.table_poll_assembler + + if frame.textfield_question.text == "" then return end + if frame.textfield_answer_1.text == "" and frame.textfield_answer_2.text == "" and frame.textfield_answer_3.text == "" then return end + + global.poll_question = frame.textfield_question.text + global.poll_answers = {frame.textfield_answer_1.text, frame.textfield_answer_2.text, frame.textfield_answer_3.text} + + local msg = player.name + msg = msg .. " has created a new Poll!" + + global.score_total_polls_created = global.score_total_polls_created + 1 + + player.gui.left["poll-assembler"].destroy() + + global.poll_voted = {} + global.poll_button_votes = {0,0,0} + + for _, player in pairs(game.players) do + if player.gui.left["poll-panel"] then + player.gui.left["poll-panel"].destroy() + end + if global.autoshow_polls_for_player[player.name] == true then + poll_show(player) + end + player.print(msg, { r=0.22, g=0.99, b=0.99}) + end +end + +local function poll_refresh() + for _, player in pairs(game.players) do + if player.gui.left["poll-panel"] then + local frame = player.gui.left["poll-panel"] + frame = frame.poll_panel_table + if frame.answer_button_1 then frame.answer_button_1.caption = global.poll_button_votes[1] end + if frame.answer_button_2 then frame.answer_button_2.caption = global.poll_button_votes[2] end + if frame.answer_button_3 then frame.answer_button_3.caption = global.poll_button_votes[3] end + end + end +end + +local function poll_assembler(player) + local frame = player.gui.left.add { type = "frame", name = "poll-assembler", caption = "" } + local frame_table = frame.add { type = "table", name = "table_poll_assembler", column_count = 2 } + frame_table.add { type = "label", caption = "Question:" } + frame_table.add { type = "textfield", name = "textfield_question", text = "" } + frame_table.add { type = "label", caption = "Answer #1:" } + frame_table.add { type = "textfield", name = "textfield_answer_1", text = "" } + frame_table.add { type = "label", caption = "Answer #2:" } + frame_table.add { type = "textfield", name = "textfield_answer_2", text = "" } + frame_table.add { type = "label", caption = "Answer #3:" } + frame_table.add { type = "textfield", name = "textfield_answer_3", text = "" } + frame_table.add { type = "label", caption = "" } + frame_table.add { type = "button", name = "create_new_poll_button", caption = "Create" } +end + +function on_player_joined_game(event) + if not global.poll_init_done then + global.poll_panel_creation_times = {} + global.poll_voted = {} + global.poll_question = "" + global.poll_answers = {"","",""} + global.poll_button_votes = {0,0,0} + global.poll_voted = {} + global.autoshow_polls_for_player = {} + global.score_total_polls_created = 0 + global.poll_init_done = true + end + + local player = game.players[event.player_index] + + if not global.autoshow_polls_for_player[player.name] then global.autoshow_polls_for_player[player.name] = true end + + create_poll_gui(player) + + if global.poll_question == "" then return end + + poll_show(player) +end + +local function on_gui_click(event) + if not event then return end + if not event.element then return end + if not event.element.valid then return end + + local player = game.players[event.element.player_index] + local name = event.element.name + + if name == "poll" then + global.poll_panel_creation_times[player.index] = nil + + local frame = player.gui.left["poll-panel"] + if frame then + frame.destroy() + else + poll_show(player) + end + + local frame = player.gui.left["poll-assembler"] + if frame then + frame.destroy() + end + end + + if name == "new_poll_assembler_button" then + local frame = player.gui.left["poll-assembler"] + if (frame) then + frame.destroy() + else + poll_assembler(player) + end + end + + if name == "create_new_poll_button" then + poll(player) + end + + if name == "poll_hide_button" then + player.gui.left["poll-panel"].destroy() + global.poll_panel_creation_times[player.index] = nil + if player.gui.left["poll-assembler"] then + player.gui.left["poll-assembler"].destroy() + end + end + + if name == "auto_show_polls_checkbox" then + global.autoshow_polls_for_player[player.name] = event.element.state + end + + if global.poll_voted[event.player_index] == nil then + + if name == "answer_button_1" then + global.poll_button_votes[1] = global.poll_button_votes[1] + 1 + global.poll_voted[event.player_index] = player.name + poll_refresh() + end + + if name == "answer_button_2" then + global.poll_button_votes[2] = global.poll_button_votes[2] + 1 + global.poll_voted[event.player_index] = player.name + poll_refresh() + end + + if name == "answer_button_3" then + global.poll_button_votes[3] = global.poll_button_votes[3] + 1 + global.poll_voted[event.player_index] = player.name + poll_refresh() + end + + end +end + +local function process_timeout(creation_time) + local player = game.players[creation_time.player_index] + local frame = player.gui.left["poll-panel"] + global.poll_panel_creation_times[player.index].tick = global.poll_panel_creation_times[player.index].tick - 60 + if global.poll_panel_creation_times[player.index].tick <= 0 then + if frame then frame.destroy() end + global.poll_panel_creation_times[player.index] = nil + return + else + if frame then + frame.poll_panel_button_table.poll_hide_button.caption = "Hide (" .. math.ceil(global.poll_panel_creation_times[player.index].tick / 60) .. ")" + end + end +end + +local function on_tick() + if game.tick % 60 ~= 0 then return end + for _, creation_time in pairs(global.poll_panel_creation_times) do + process_timeout(creation_time) + end +end + +event.add(defines.events.on_tick, on_tick) +event.add(defines.events.on_gui_click, on_gui_click) +event.add(defines.events.on_player_joined_game, on_player_joined_game) \ No newline at end of file