1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-10 00:43:27 +02:00
ComfyFactorio/modules/difficulty_vote_by_amount.lua

473 lines
13 KiB
Lua
Raw Normal View History

2020-10-24 14:46:14 +02:00
local Event = require 'utils.event'
2022-04-05 19:28:08 +02:00
local Gui = require 'utils.gui'
2020-10-24 14:46:14 +02:00
local Server = require 'utils.server'
local Global = require 'utils.global'
2020-12-14 20:36:37 +02:00
local SpamProtection = require 'utils.spam_protection'
2020-10-24 14:46:14 +02:00
2020-10-30 23:05:05 +02:00
local max = math.max
local round = math.round
2022-04-05 19:28:08 +02:00
local main_frame_name = Gui.uid_name()
local selection_button_name = Gui.uid_name()
local close_main_frame = Gui.uid_name()
local top_button_name = Gui.uid_name()
2020-10-24 14:46:14 +02:00
local this = {
difficulties = {
[1] = {
2020-10-30 18:32:40 +02:00
name = "I'm too young to die",
2020-10-24 14:46:14 +02:00
index = 1,
value = 0.75,
color = {r = 0.00, g = 0.25, b = 0.00},
print_color = {r = 0.00, g = 0.4, b = 0.00},
2020-10-30 23:05:05 +02:00
count = 0,
strength_modifier = 1.00,
boss_modifier = 6.0
2020-10-24 14:46:14 +02:00
},
2020-10-30 18:32:40 +02:00
[2] = {
name = 'Hurt me plenty',
index = 2,
2020-10-24 14:46:14 +02:00
value = 1,
color = {r = 0.00, g = 0.00, b = 0.25},
print_color = {r = 0.0, g = 0.0, b = 0.5},
2020-10-30 23:05:05 +02:00
count = 0,
strength_modifier = 1.25,
boss_modifier = 7.0
2020-10-24 14:46:14 +02:00
},
2020-10-30 18:32:40 +02:00
[3] = {
name = 'Ultra-violence',
index = 3,
2020-10-24 14:46:14 +02:00
value = 1.5,
2020-10-30 18:32:40 +02:00
color = {r = 255, g = 128, b = 0.00},
print_color = {r = 255, g = 128, b = 0.00},
2020-10-30 23:05:05 +02:00
count = 0,
strength_modifier = 1.75,
boss_modifier = 8.0
2020-10-24 14:46:14 +02:00
}
},
tooltip = {
[1] = '',
[2] = '',
[3] = ''
2020-10-24 14:46:14 +02:00
},
2023-08-10 14:29:05 +02:00
show_gui = true,
2022-07-10 19:41:54 +02:00
value = 0.75,
index = 1,
fair_vote = false,
2022-07-10 19:41:54 +02:00
closing_timeout = 54000,
all_votes = {},
2020-10-24 14:46:14 +02:00
gui_width = 108,
2021-11-28 21:42:38 +02:00
name = "I'm too young to die",
strength_modifier = 1.00,
2023-08-10 14:29:05 +02:00
boss_modifier = 6.0,
2020-10-24 14:46:14 +02:00
button_tooltip = nil
}
local Public = {}
Global.register(
this,
function(t)
this = t
end
)
2022-04-05 19:28:08 +02:00
local function clear_main_frame(player)
local screen = player.gui.center
if screen[main_frame_name] and screen[main_frame_name].valid then
screen[main_frame_name].destroy()
end
end
2024-05-27 20:30:03 +02:00
local function clear_top_frame(player)
local top = player.gui.top
if top[top_button_name] and top[top_button_name].valid then
top[top_button_name].destroy()
end
end
2020-10-24 14:46:14 +02:00
function Public.difficulty_gui()
2023-09-05 00:03:55 +02:00
if not this.show_gui then
return
end
2022-07-10 19:41:54 +02:00
local tooltip = 'Current difficulty of the map is ' .. this.difficulties[this.index].name .. '.'
2020-10-24 14:46:14 +02:00
for _, player in pairs(game.connected_players) do
2022-04-05 19:28:08 +02:00
local top = player.gui.top
if top[top_button_name] then
2022-07-10 19:41:54 +02:00
top[top_button_name].caption = this.difficulties[this.index].name
2022-04-05 19:28:08 +02:00
top[top_button_name].tooltip = this.button_tooltip or tooltip
2022-07-10 19:41:54 +02:00
top[top_button_name].style.font_color = this.difficulties[this.index].print_color
2020-10-24 14:46:14 +02:00
else
local b =
2022-04-05 19:28:08 +02:00
top.add {
2020-10-24 14:46:14 +02:00
type = 'button',
2022-07-10 19:41:54 +02:00
caption = this.difficulties[this.index].name,
2020-10-24 14:46:14 +02:00
tooltip = tooltip,
2022-04-05 19:28:08 +02:00
name = top_button_name
2020-10-24 14:46:14 +02:00
}
b.style.font = 'heading-2'
2022-07-10 19:41:54 +02:00
b.style.font_color = this.difficulties[this.index].print_color
2020-12-05 19:09:37 +02:00
b.style.minimal_height = 37
b.style.maximal_height = 37
2020-10-24 14:46:14 +02:00
b.style.minimal_width = this.gui_width
end
end
end
local function highest_count(tbl)
local init = {
count = {},
index = {}
}
for i = 1, #tbl do
init.count[#init.count + 1] = tbl[i].count
init.index[#init.index + 1] = tbl[i].index
end
2020-10-30 23:05:05 +02:00
local highest = max(unpack(init.count))
2020-10-24 14:46:14 +02:00
local pre = {}
2020-10-30 23:05:05 +02:00
if this.fair_vote then
for x = 1, #init.count do
if init.count[x] == highest then
pre[#pre + 1] = {i = init.index[x], c = init.count[x]}
end
end
else
for x = 1, #init.count do
if init.count[x] ~= 0 then
if round(init.count[x] / highest) == 1 then
pre[#pre + 1] = {i = init.index[x], c = init.count[x]}
end
end
2020-10-24 14:46:14 +02:00
end
end
local post = {}
for i = 1, #pre do
post[#post + 1] = pre[i].i
end
2020-10-30 23:05:05 +02:00
highest = round(table.mean(post))
2020-10-24 14:46:14 +02:00
return highest
end
local function poll_difficulty(player)
2022-04-05 19:28:08 +02:00
if player.gui.center[main_frame_name] then
clear_main_frame(player)
2020-10-24 14:46:14 +02:00
end
2022-04-05 19:28:08 +02:00
2023-09-05 00:03:55 +02:00
if not this.show_gui then
if player.gui.center[main_frame_name] then
clear_main_frame(player)
end
return
end
2022-07-10 19:41:54 +02:00
if game.tick > this.closing_timeout then
2020-10-24 14:46:14 +02:00
if player.online_time ~= 0 then
2022-07-10 19:41:54 +02:00
local t = math.abs(math.floor((this.closing_timeout - game.tick) / 3600))
2020-10-24 14:46:14 +02:00
local str = 'Votes have closed ' .. t
str = str .. ' minute'
if t > 1 then
str = str .. 's'
end
str = str .. ' ago.'
player.print(str)
end
return
end
2022-04-05 19:28:08 +02:00
local _, inside_frame = Gui.add_main_frame_with_toolbar(player, 'center', main_frame_name, nil, close_main_frame, 'Difficulty')
2022-07-10 19:41:54 +02:00
if not inside_frame then
return
end
2022-04-05 19:28:08 +02:00
2020-10-24 14:46:14 +02:00
for i = 1, #this.difficulties, 1 do
2022-04-05 19:28:08 +02:00
local button_flow =
inside_frame.add {
type = 'flow',
name = tostring(i)
}
local b = button_flow.add({type = 'button', name = selection_button_name, caption = this.difficulties[i].name})
2020-10-24 14:46:14 +02:00
b.style.font_color = this.difficulties[i].color
b.style.font = 'heading-2'
b.style.minimal_width = 160
b.tooltip = this.tooltip[i]
end
2022-04-05 19:28:08 +02:00
local label_flow =
inside_frame.add {
type = 'flow'
}
2022-04-18 01:18:58 +02:00
inside_frame.add({type = 'line'})
2022-04-05 19:28:08 +02:00
label_flow.style.horizontal_align = 'center'
label_flow.style.horizontally_stretchable = true
local timeleft_flow =
inside_frame.add {
type = 'flow'
}
timeleft_flow.style.horizontal_align = 'center'
timeleft_flow.style.horizontally_stretchable = true
2020-10-24 14:46:14 +02:00
local b =
2022-04-05 19:28:08 +02:00
timeleft_flow.add(
2020-10-24 14:46:14 +02:00
{
type = 'button',
2022-07-10 19:41:54 +02:00
caption = math.floor((this.closing_timeout - game.tick) / 3600) .. ' minutes left.'
2020-10-24 14:46:14 +02:00
}
)
b.style.font_color = {r = 0.66, g = 0.0, b = 0.66}
b.style.font = 'heading-3'
b.style.minimal_width = 96
2022-04-05 19:28:08 +02:00
b.enabled = false
2022-04-18 01:18:58 +02:00
inside_frame.add({type = 'line'})
2020-10-24 14:46:14 +02:00
end
local function set_difficulty()
local index = highest_count(this.difficulties)
if not index or not this.difficulties[index] then
2021-01-26 21:17:52 +02:00
return
end
2020-10-24 14:46:14 +02:00
2022-07-10 19:41:54 +02:00
if this.index ~= index then
2021-11-22 21:16:33 +02:00
local message = table.concat({'*** Map difficulty has changed to ', this.difficulties[index].name, ' difficulty! ***'})
2020-10-24 14:46:14 +02:00
game.print(message, this.difficulties[index].print_color)
Server.to_discord_embed(message)
end
2022-07-10 19:41:54 +02:00
this.index = index
this.name = this.difficulties[index].name
this.value = this.difficulties[index].value
2020-10-30 23:05:05 +02:00
this.boss_modifier = this.difficulties[index].boss_modifier
this.strength_modifier = this.difficulties[index].strength_modifier
2022-07-10 19:41:54 +02:00
this.button_tooltip = this.tooltip[index]
2020-10-24 14:46:14 +02:00
end
function Public.reset_difficulty_poll(tbl)
if tbl then
2022-07-10 19:41:54 +02:00
this.value = tbl.value or 0.75
this.index = tbl.index or 1
this.all_votes = {}
this.closing_timeout = tbl.closing_timeout or game.tick + 54000
2020-10-24 14:46:14 +02:00
for _, p in pairs(game.connected_players) do
2022-04-05 19:28:08 +02:00
if p.gui.center[main_frame_name] then
clear_main_frame(p)
2020-10-24 14:46:14 +02:00
end
poll_difficulty(p)
end
for _, vote in pairs(this.difficulties) do
vote.count = 0
end
Public.difficulty_gui()
else
2022-07-10 19:41:54 +02:00
this.value = 0.75
this.index = 1
this.all_votes = {}
this.closing_timeout = game.tick + 54000
2020-10-24 14:46:14 +02:00
for _, p in pairs(game.connected_players) do
2022-04-05 19:28:08 +02:00
if p.gui.center[main_frame_name] then
clear_main_frame(p)
2020-10-24 14:46:14 +02:00
end
poll_difficulty(p)
end
for _, vote in pairs(this.difficulties) do
vote.count = 0
end
Public.difficulty_gui()
end
end
local function on_player_joined_game(event)
2023-08-10 14:29:05 +02:00
if not this.show_gui then
return
end
2022-04-05 19:28:08 +02:00
local player = game.get_player(event.player_index)
2022-07-10 19:41:54 +02:00
if game.tick < this.closing_timeout then
if not this.all_votes[player.name] then
2020-10-24 14:46:14 +02:00
poll_difficulty(player)
end
else
2022-04-05 19:28:08 +02:00
clear_main_frame(player)
2020-10-24 14:46:14 +02:00
end
Public.difficulty_gui()
end
local function on_player_left_game(event)
2022-07-10 19:41:54 +02:00
if game.tick > this.closing_timeout then
2020-10-24 14:46:14 +02:00
return
end
2022-04-05 19:28:08 +02:00
local player = game.get_player(event.player_index)
2022-07-10 19:41:54 +02:00
if not this.all_votes[player.name] then
2020-10-24 14:46:14 +02:00
return
end
2022-07-10 19:41:54 +02:00
local index = this.all_votes[player.name].index
2020-10-24 14:46:14 +02:00
this.difficulties[index].count = this.difficulties[index].count - 1
if this.difficulties[index].count <= 0 then
this.difficulties[index].count = 0
end
2022-07-10 19:41:54 +02:00
this.all_votes[player.name] = nil
2020-10-24 14:46:14 +02:00
set_difficulty()
Public.difficulty_gui()
end
2020-10-30 23:05:05 +02:00
function Public.set_tooltip(...)
if type(...) == 'table' then
this.tooltip = ...
end
end
function Public.set_difficulties(...)
if type(...) == 'table' then
this.difficulties = ...
end
end
function Public.set_poll_closing_timeout(...)
2022-07-10 19:41:54 +02:00
this.closing_timeout = ...
end
--- Sets gui width
---@param number number
function Public.set_gui_width(number)
this.gui_width = number
2020-10-30 23:05:05 +02:00
end
function Public.get_fair_vote()
return this.fair_vote
end
function Public.set_fair_vote(value)
this.fair_vote = value or false
end
2023-08-10 14:29:05 +02:00
function Public.show_gui(state)
this.show_gui = state or false
end
2020-10-30 23:05:05 +02:00
function Public.get(key)
if key then
return this[key]
else
return this
end
end
2022-07-10 19:41:54 +02:00
function Public.set(key, value)
if key and (value or value == false) then
this[key] = value
return this[key]
elseif key then
return this[key]
else
return this
end
end
2022-04-05 19:28:08 +02:00
Gui.on_click(
selection_button_name,
function(event)
local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Poll difficulty selection frame name')
if is_spamming then
return
end
local element = event.element
if not element or not element.valid then
return
end
local player = event.player
2022-04-07 16:11:26 +02:00
if not player or not player.valid then
2022-04-05 19:28:08 +02:00
return
end
local i = tonumber(element.parent.name)
2022-07-10 19:41:54 +02:00
if game.tick > this.closing_timeout then
clear_main_frame(player)
return
end
2022-07-10 19:41:54 +02:00
if this.all_votes[player.name] and this.all_votes[player.name].index == i then
2022-04-05 19:28:08 +02:00
player.print('You have already voted for ' .. this.difficulties[i].name .. '.', this.difficulties[i].print_color)
clear_main_frame(player)
return
end
2022-07-10 19:41:54 +02:00
if this.all_votes[player.name] then
local index = this.all_votes[player.name].index
2022-04-05 19:28:08 +02:00
this.difficulties[index].count = this.difficulties[index].count - 1
if this.difficulties[index].count <= 0 then
this.difficulties[index].count = 0
end
end
this.difficulties[i].count = this.difficulties[i].count + 1
2022-07-10 19:41:54 +02:00
this.all_votes[player.name] = {voted = true, index = i}
2022-04-05 19:28:08 +02:00
set_difficulty()
Public.difficulty_gui()
clear_main_frame(player)
local message = '*** ' .. player.name .. ' has voted for ' .. this.difficulties[i].name .. ' difficulty! ***'
game.print(message, this.difficulties[i].print_color)
Server.to_discord_embed(message)
end
)
Gui.on_click(
top_button_name,
function(event)
local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Poll difficulty top button')
if is_spamming then
return
end
local player = event.player
2022-04-07 16:11:26 +02:00
if not player or not player.valid then
2022-04-05 19:28:08 +02:00
return
end
2022-07-10 19:41:54 +02:00
if game.tick > this.closing_timeout then
2022-04-05 19:28:08 +02:00
clear_main_frame(player)
return
end
2022-04-07 16:11:26 +02:00
2022-04-05 19:28:08 +02:00
local screen = player.gui.center
if screen[main_frame_name] and screen[main_frame_name].valid then
clear_main_frame(player)
else
poll_difficulty(player)
end
end
)
Gui.on_click(
close_main_frame,
function(event)
local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Poll difficulty close button')
if is_spamming then
return
end
local player = event.player
2022-04-07 16:11:26 +02:00
if not player or not player.valid then
2022-04-05 19:28:08 +02:00
return
end
clear_main_frame(player)
end
)
2021-05-25 22:19:20 +02:00
Event.add(defines.events.on_player_created, on_player_joined_game)
2020-10-24 14:46:14 +02:00
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
Event.add(defines.events.on_player_left_game, on_player_left_game)
2022-04-05 19:28:08 +02:00
Public.top_button_name = top_button_name
2024-05-27 20:30:03 +02:00
Public.clear_main_frame = clear_main_frame
Public.clear_top_frame = clear_top_frame
2020-10-24 14:46:14 +02:00
return Public