mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-08 00:39:30 +02:00
cf95b8e91a
Removes broken spells from objective Fixes broken teleport when final battle Lowered the length of final battle to max 15m
1384 lines
60 KiB
Lua
1384 lines
60 KiB
Lua
local Event = require 'utils.event'
|
|
local SpamProtection = require 'utils.spam_protection'
|
|
local Public = require 'maps.mountain_fortress_v3.table'
|
|
local Alert = require 'utils.alert'
|
|
local Stateful = require 'maps.mountain_fortress_v3.stateful.table'
|
|
local Gui = require 'utils.gui'
|
|
local WD = require 'modules.wave_defense.table'
|
|
local Collapse = require 'modules.collapse'
|
|
local Task = require 'utils.task_token'
|
|
local Core = require 'utils.core'
|
|
local Server = require 'utils.server'
|
|
local LinkedChests = require 'maps.mountain_fortress_v3.icw.linked_chests'
|
|
local Discord = require 'utils.discord'
|
|
local format_number = require 'util'.format_number
|
|
local Explosives = require 'modules.explosives'
|
|
|
|
local zone_settings = Public.zone_settings
|
|
local send_ping_to_channel = Discord.channel_names.mtn_channel
|
|
local main_button_name = Gui.uid_name()
|
|
local main_frame_name = Gui.uid_name()
|
|
local boss_frame_name = Gui.uid_name()
|
|
local close_button = Gui.uid_name()
|
|
local close_buffs_window_name = Gui.uid_name()
|
|
local buffs_window_name = Gui.uid_name()
|
|
local on_click_buff_name = Gui.uid_name()
|
|
local random = math.random
|
|
local floor = math.floor
|
|
local scenario_name = Public.scenario_name
|
|
local main_frame
|
|
|
|
local function create_particles(surface, name, position, amount, cause_position)
|
|
local d1 = (-100 + random(0, 200)) * 0.0004
|
|
local d2 = (-100 + random(0, 200)) * 0.0004
|
|
|
|
name = name or 'leaf-particle'
|
|
|
|
if cause_position then
|
|
d1 = (cause_position.x - position.x) * 0.025
|
|
d2 = (cause_position.y - position.y) * 0.025
|
|
end
|
|
|
|
for _ = 1, amount, 1 do
|
|
local m = random(4, 10)
|
|
local m2 = m * 0.005
|
|
|
|
surface.create_particle(
|
|
{
|
|
name = name,
|
|
position = position,
|
|
frame_speed = 1,
|
|
vertical_speed = 0.130,
|
|
height = 0,
|
|
movement = {
|
|
(m2 - (random(0, m) * 0.01)) + d1,
|
|
(m2 - (random(0, m) * 0.01)) + d2
|
|
}
|
|
}
|
|
)
|
|
end
|
|
end
|
|
|
|
local spread_particles_token =
|
|
Task.register(
|
|
function (event)
|
|
local player_index = event.player_index
|
|
local player = game.get_player(player_index)
|
|
if not player or not player.valid then
|
|
return
|
|
end
|
|
local particle = event.particle
|
|
|
|
create_particles(player.surface, particle, player.position, 128)
|
|
end
|
|
)
|
|
|
|
local function pretty_format(input)
|
|
local action = string.gsub(input, '-', ' ')
|
|
local result = string.upper(string.sub(action, 1, 1)) .. string.sub(action, 2)
|
|
return result
|
|
end
|
|
|
|
local function notify_won_to_discord(buff)
|
|
if not buff then
|
|
return error('Buff is required when sending message to discord.', 2)
|
|
end
|
|
local server_name_matches = Server.check_server_name(scenario_name)
|
|
|
|
local stateful = Public.get_stateful()
|
|
|
|
local wave = WD.get_wave()
|
|
local date = Server.get_start_time()
|
|
game.server_save('Complete_Mtn_v3_' .. tostring(date) .. '_wave' .. tostring(wave))
|
|
|
|
local time_played = Core.format_time(game.ticks_played)
|
|
local total_players = #game.players
|
|
local total_connected_players = #game.connected_players
|
|
local pickaxe_upgrades = Public.pickaxe_upgrades
|
|
local upgrades = Public.get('upgrades')
|
|
local pick_tier = pickaxe_upgrades[upgrades.pickaxe_tier]
|
|
|
|
local text = {
|
|
title = 'Game won!',
|
|
description = 'Game statistics from the game is below',
|
|
color = 'success',
|
|
field1 = {
|
|
text1 = 'Time played:',
|
|
text2 = time_played,
|
|
inline = 'false'
|
|
},
|
|
field2 = {
|
|
text1 = 'Rounds survived:',
|
|
text2 = stateful.rounds_survived,
|
|
inline = 'false'
|
|
},
|
|
field3 = {
|
|
text1 = 'Wave:',
|
|
text2 = format_number(wave, true),
|
|
inline = 'false'
|
|
},
|
|
field4 = {
|
|
text1 = 'Total connected players:',
|
|
text2 = total_players,
|
|
inline = 'false'
|
|
},
|
|
field5 = {
|
|
text1 = 'Pickaxe Upgrade:',
|
|
text2 = pick_tier .. ' (' .. upgrades.pickaxe_tier .. ')',
|
|
inline = 'false'
|
|
},
|
|
field6 = {
|
|
text1 = 'Connected players:',
|
|
text2 = total_connected_players,
|
|
inline = 'false'
|
|
},
|
|
field7 = {
|
|
text1 = 'Buff granted:',
|
|
text2 = buff.discord,
|
|
inline = 'false'
|
|
}
|
|
}
|
|
if server_name_matches then
|
|
Server.to_discord_named_parsed_embed(send_ping_to_channel, text)
|
|
else
|
|
Server.to_discord_embed_parsed(text)
|
|
end
|
|
end
|
|
|
|
local function clear_all_frames()
|
|
Core.iter_players(
|
|
function (player)
|
|
local b_frame = player.gui.screen[boss_frame_name]
|
|
if b_frame then
|
|
Gui.remove_data_recursively(b_frame)
|
|
b_frame.destroy()
|
|
end
|
|
|
|
local frame = player.gui.screen[main_frame_name]
|
|
if frame then
|
|
Gui.remove_data_recursively(frame)
|
|
frame.destroy()
|
|
end
|
|
end
|
|
)
|
|
end
|
|
|
|
local function refresh_frames()
|
|
Core.iter_connected_players(
|
|
function (player)
|
|
local frame = player.gui.screen[main_frame_name]
|
|
if frame and frame.valid then
|
|
Gui.remove_data_recursively(frame)
|
|
frame.destroy()
|
|
main_frame(player)
|
|
else
|
|
main_frame(player)
|
|
end
|
|
end
|
|
)
|
|
end
|
|
|
|
local warn_player_sound_token =
|
|
Task.register(
|
|
function (event)
|
|
local player_index = event.player_index
|
|
local player = game.get_player(player_index)
|
|
if not player or not player.valid then
|
|
return
|
|
end
|
|
local particle = event.particle
|
|
|
|
player.play_sound { path = 'utility/new_objective', volume_modifier = 0.75 }
|
|
|
|
create_particles(player.surface, particle, player.position, 128)
|
|
end
|
|
)
|
|
|
|
local function create_button(player)
|
|
if Gui.get_mod_gui_top_frame() then
|
|
local b =
|
|
Gui.add_mod_button(
|
|
player,
|
|
{
|
|
type = 'sprite-button',
|
|
name = main_button_name,
|
|
sprite = 'utility/custom_tag_icon',
|
|
tooltip = 'Has information about all objectives that needs to be completed',
|
|
style = Gui.button_style
|
|
}
|
|
)
|
|
if b then
|
|
b.style.font_color = { 165, 165, 165 }
|
|
b.style.font = 'heading-3'
|
|
b.style.minimal_height = 36
|
|
b.style.maximal_height = 36
|
|
b.style.minimal_width = 40
|
|
b.style.padding = -2
|
|
end
|
|
else
|
|
local b =
|
|
player.gui.top.add(
|
|
{
|
|
type = 'sprite-button',
|
|
name = main_button_name,
|
|
sprite = 'utility/custom_tag_icon',
|
|
tooltip = 'Has information about all objectives that needs to be completed',
|
|
style = Gui.button_style
|
|
}
|
|
)
|
|
b.style.minimal_height = 38
|
|
b.style.maximal_height = 38
|
|
end
|
|
end
|
|
|
|
local function create_input_element(frame, type, value, items, index, tooltip, custom_space)
|
|
if type == 'slider' then
|
|
return frame.add({ type = 'slider', value = value, minimum_value = 0, maximum_value = 1 })
|
|
end
|
|
if type == 'boolean' then
|
|
return frame.add({ type = 'checkbox', state = value })
|
|
end
|
|
if type == 'label' then
|
|
local label = frame.add({ type = 'label', caption = value })
|
|
label.style.font = 'default-listbox'
|
|
label.tooltip = tooltip or ''
|
|
if custom_space then
|
|
label.style.minimal_height = custom_space
|
|
end
|
|
return label
|
|
end
|
|
if type == 'dropdown' then
|
|
return frame.add({ type = 'drop-down', items = items, selected_index = index })
|
|
end
|
|
return frame.add({ type = 'text-box', text = value })
|
|
end
|
|
|
|
local function play_game_won()
|
|
Explosives.disable(false)
|
|
Core.iter_connected_players(
|
|
function (player)
|
|
Explosives.detonate_entity(player)
|
|
player.play_sound { path = 'utility/game_won', volume_modifier = 0.75 }
|
|
Task.set_timeout_in_ticks(10, spread_particles_token, { player_index = player.index, particle = 'iron-ore-particle' })
|
|
Task.set_timeout_in_ticks(15, spread_particles_token, { player_index = player.index, particle = 'branch-particle' })
|
|
Task.set_timeout_in_ticks(20, spread_particles_token, { player_index = player.index, particle = 'copper-ore-particle' })
|
|
Task.set_timeout_in_ticks(25, spread_particles_token, { player_index = player.index, particle = 'branch-particle' })
|
|
Task.set_timeout_in_ticks(30, spread_particles_token, { player_index = player.index, particle = 'stone-particle' })
|
|
Task.set_timeout_in_ticks(35, spread_particles_token, { player_index = player.index, particle = 'branch-particle' })
|
|
Task.set_timeout_in_ticks(40, spread_particles_token, { player_index = player.index, particle = 'coal-particle' })
|
|
Task.set_timeout_in_ticks(45, spread_particles_token, { player_index = player.index, particle = 'branch-particle' })
|
|
end
|
|
)
|
|
end
|
|
|
|
local function play_achievement_unlocked()
|
|
Core.iter_connected_players(
|
|
function (player)
|
|
player.play_sound { path = 'utility/achievement_unlocked', volume_modifier = 0.75 }
|
|
Task.set_timeout_in_ticks(10, spread_particles_token, { player_index = player.index, particle = 'iron-ore-particle' })
|
|
Task.set_timeout_in_ticks(15, spread_particles_token, { player_index = player.index, particle = 'branch-particle' })
|
|
Task.set_timeout_in_ticks(20, spread_particles_token, { player_index = player.index, particle = 'copper-ore-particle' })
|
|
Task.set_timeout_in_ticks(25, spread_particles_token, { player_index = player.index, particle = 'branch-particle' })
|
|
Task.set_timeout_in_ticks(30, spread_particles_token, { player_index = player.index, particle = 'stone-particle' })
|
|
Task.set_timeout_in_ticks(35, spread_particles_token, { player_index = player.index, particle = 'branch-particle' })
|
|
Task.set_timeout_in_ticks(40, spread_particles_token, { player_index = player.index, particle = 'coal-particle' })
|
|
Task.set_timeout_in_ticks(45, spread_particles_token, { player_index = player.index, particle = 'branch-particle' })
|
|
end
|
|
)
|
|
end
|
|
|
|
local function alert_players_sound()
|
|
Core.iter_connected_players(
|
|
function (player)
|
|
Task.set_timeout_in_ticks(10, warn_player_sound_token, { player_index = player.index, particle = 'iron-ore-particle' })
|
|
Task.set_timeout_in_ticks(20, warn_player_sound_token, { player_index = player.index, particle = 'branch-particle' })
|
|
Task.set_timeout_in_ticks(30, warn_player_sound_token, { player_index = player.index, particle = 'copper-ore-particle' })
|
|
Task.set_timeout_in_ticks(40, warn_player_sound_token, { player_index = player.index, particle = 'branch-particle' })
|
|
Task.set_timeout_in_ticks(50, warn_player_sound_token, { player_index = player.index, particle = 'stone-particle' })
|
|
Task.set_timeout_in_ticks(60, warn_player_sound_token, { player_index = player.index, particle = 'branch-particle' })
|
|
Task.set_timeout_in_ticks(70, warn_player_sound_token, { player_index = player.index, particle = 'coal-particle' })
|
|
Task.set_timeout_in_ticks(80, warn_player_sound_token, { player_index = player.index, particle = 'branch-particle' })
|
|
end
|
|
)
|
|
end
|
|
|
|
local function spacer(frame)
|
|
local flow = frame.add({ type = 'flow' })
|
|
flow.style.minimal_height = 2
|
|
end
|
|
|
|
local function objective_frames(stateful, player_frame, objective, data)
|
|
local objective_name = objective.name
|
|
if objective_name == 'supplies' or objective_name == 'single_item' then
|
|
local supplies = stateful.objectives.supplies
|
|
local tbl = player_frame.add { type = 'table', column_count = 2 }
|
|
tbl.style.horizontally_stretchable = true
|
|
local left_flow = tbl.add({ type = 'flow' })
|
|
left_flow.style.horizontal_align = 'left'
|
|
left_flow.style.horizontally_stretchable = true
|
|
|
|
if objective_name == 'single_item' then
|
|
left_flow.add({ type = 'label', caption = { 'stateful.production_single' }, tooltip = { 'stateful.production_tooltip' } })
|
|
else
|
|
left_flow.add({ type = 'label', caption = { 'stateful.production' }, tooltip = { 'stateful.production_tooltip' } })
|
|
end
|
|
player_frame.add({ type = 'line', direction = 'vertical' })
|
|
local right_flow = tbl.add({ type = 'flow' })
|
|
right_flow.style.horizontal_align = 'right'
|
|
right_flow.style.horizontally_stretchable = true
|
|
|
|
if objective_name == 'single_item' then
|
|
if stateful.objectives_completed.single_item then
|
|
data.single_item_complete = right_flow.add({ type = 'label', caption = ' [img=utility/check_mark_green]', tooltip = { 'stateful.tooltip_completed' } })
|
|
else
|
|
data.single_item_complete = right_flow.add({ type = 'label', caption = ' [img=utility/not_available]', tooltip = { 'stateful.tooltip_not_completed' } })
|
|
end
|
|
else
|
|
if stateful.objectives_completed.supplies then
|
|
data.supply_completed = right_flow.add({ type = 'label', caption = ' [img=utility/check_mark_green]', tooltip = { 'stateful.tooltip_completed' } })
|
|
else
|
|
data.supply_completed = right_flow.add({ type = 'label', caption = ' [img=utility/not_available]', tooltip = { 'stateful.tooltip_not_completed' } })
|
|
end
|
|
end
|
|
|
|
if not data.supply then
|
|
data.supply = {}
|
|
end
|
|
|
|
local flow = player_frame.add({ type = 'flow' })
|
|
local item_table = flow.add({ type = 'table', name = 'item_table', column_count = 3 })
|
|
if objective_name ~= 'single_item' then
|
|
data.supply[#data.supply + 1] = item_table.add({ type = 'sprite-button', name = supplies[1].name, sprite = 'item/' .. supplies[1].name, enabled = false, number = supplies[1].count })
|
|
data.supply[#data.supply + 1] = item_table.add({ type = 'sprite-button', name = supplies[2].name, sprite = 'item/' .. supplies[2].name, enabled = false, number = supplies[2].count })
|
|
data.supply[#data.supply + 1] = item_table.add({ type = 'sprite-button', name = supplies[3].name, sprite = 'item/' .. supplies[3].name, enabled = false, number = supplies[3].count })
|
|
else
|
|
local single_item = stateful.objectives.single_item
|
|
data.single_item = item_table.add({ type = 'sprite-button', name = single_item.name, sprite = 'item/' .. single_item.name, enabled = false, number = single_item.count })
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
local callback = Task.get(objective.token)
|
|
|
|
local _, objective_locale_left, objective_locale_right, tooltip_left, tooltip_right = callback()
|
|
|
|
local tbl = player_frame.add { type = 'table', column_count = 2 }
|
|
tbl.style.horizontally_stretchable = true
|
|
local left_flow = tbl.add({ type = 'flow' })
|
|
left_flow.style.horizontal_align = 'left'
|
|
left_flow.style.horizontally_stretchable = true
|
|
|
|
left_flow.add({ type = 'label', caption = objective_locale_left, tooltip = tooltip_left })
|
|
local right_flow = tbl.add({ type = 'flow' })
|
|
right_flow.style.horizontal_align = 'right'
|
|
right_flow.style.horizontally_stretchable = true
|
|
|
|
local objective_locale_right_label = right_flow.add({ type = 'label', caption = objective_locale_right, tooltip = tooltip_right })
|
|
data.random_objectives[#data.random_objectives + 1] = { name = objective_name, frame = objective_locale_right_label }
|
|
return
|
|
end
|
|
|
|
local function buff_window(player)
|
|
local buff_frame_name, inside_table = Gui.add_main_frame_with_toolbar(player, 'center', buffs_window_name, nil, close_buffs_window_name, 'Buffs gathered')
|
|
if not buff_frame_name then
|
|
return
|
|
end
|
|
if not inside_table then
|
|
return
|
|
end
|
|
|
|
local stateful = Public.get_stateful()
|
|
|
|
local inside_table_style = inside_table.style
|
|
inside_table_style.width = 530
|
|
|
|
local info_text = inside_table.add({ type = 'label', caption = 'All the buffs that have been gathered throughout the runs!' })
|
|
local info_text_style = info_text.style
|
|
info_text_style.font = 'heading-2'
|
|
info_text_style.padding = 0
|
|
info_text_style.left_padding = 10
|
|
info_text_style.horizontal_align = 'left'
|
|
info_text_style.vertical_align = 'bottom'
|
|
info_text_style.font_color = { 0.55, 0.55, 0.99 }
|
|
|
|
local buff_pane = inside_table.add({ type = 'scroll-pane' })
|
|
local ns = buff_pane.style
|
|
ns.vertically_squashable = true
|
|
ns.bottom_padding = 5
|
|
ns.left_padding = 5
|
|
ns.right_padding = 5
|
|
ns.top_padding = 5
|
|
|
|
buff_pane.add({ type = 'line' })
|
|
|
|
local starting_items_label = buff_pane.add({ type = 'label', caption = 'Starting items' })
|
|
local starting_items_label_style = starting_items_label.style
|
|
starting_items_label_style.font = 'heading-3'
|
|
starting_items_label_style.padding = 0
|
|
starting_items_label_style.horizontal_align = 'left'
|
|
starting_items_label_style.font_color = { 0.55, 0.55, 0.99 }
|
|
|
|
local starting_grid = buff_pane.add({ type = 'table', column_count = 8 })
|
|
|
|
buff_pane.add({ type = 'line' })
|
|
|
|
local force_label = buff_pane.add({ type = 'label', caption = 'Force Buffs' })
|
|
local force_label_style = force_label.style
|
|
force_label_style.font = 'heading-3'
|
|
force_label_style.padding = 0
|
|
force_label_style.horizontal_align = 'left'
|
|
force_label_style.font_color = { 0.55, 0.55, 0.99 }
|
|
local force_grid = buff_pane.add({ type = 'table', column_count = 2 })
|
|
|
|
buff_pane.add({ type = 'line' })
|
|
|
|
local custom_label = buff_pane.add({ type = 'label', caption = 'Custom Buffs' })
|
|
local custom_label_style = custom_label.style
|
|
custom_label_style.font = 'heading-3'
|
|
custom_label_style.padding = 0
|
|
custom_label_style.horizontal_align = 'left'
|
|
custom_label_style.font_color = { 0.55, 0.55, 0.99 }
|
|
local custom_grid = buff_pane.add({ type = 'table', column_count = 2 })
|
|
|
|
if stateful.buffs and next(stateful.buffs) then
|
|
if stateful.buffs_collected and next(stateful.buffs_collected) then
|
|
if stateful.buffs_collected.starting_items then
|
|
for item_name, item_data in pairs(stateful.buffs_collected.starting_items) do
|
|
-- local text = pretty_format(item_name) .. ': [font=font-bold]' .. item_data.count
|
|
local text = '[font=default-large] [item=' .. item_name .. '][/font]' .. ': [font=default-bold]' .. item_data.count .. '[/font]'
|
|
create_input_element(starting_grid, 'label', text, nil, nil, item_data.discord, 30)
|
|
end
|
|
end
|
|
|
|
for name, buff_data in pairs(stateful.buffs_collected) do
|
|
if type(buff_data.amount) ~= 'table' and buff_data.force then
|
|
local c = buff_data.count
|
|
local text
|
|
if name == 'xp_level' or name == 'xp_bonus' or name == 'character_health_bonus' then
|
|
text = '[font=default-bold]' .. Stateful.buff_to_string[name] .. ': ' .. c .. '[/font]'
|
|
else
|
|
text = '[font=default-bold]' .. Stateful.buff_to_string[name] .. ': ' .. (c * 100) .. '%[/font]'
|
|
end
|
|
|
|
create_input_element(force_grid, 'label', text, nil, nil, buff_data.discord)
|
|
end
|
|
|
|
if name ~= 'starting_items' and not buff_data.force then
|
|
if buff_data.name then
|
|
local text_to_place = buff_data.count or 'Unlocked'
|
|
local text = '[font=default-bold]' .. buff_data.name .. ': ' .. text_to_place .. ' [/font]'
|
|
create_input_element(custom_grid, 'label', text, nil, nil, buff_data.discord)
|
|
else
|
|
for _, buff in pairs(buff_data) do
|
|
local text_to_place = buff.count or 'Unlocked'
|
|
local text = '[font=default-bold]' .. pretty_format(buff.name) .. ': ' .. text_to_place .. ' [/font]'
|
|
create_input_element(custom_grid, 'label', text, nil, nil, buff.discord)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
player.opened = buff_frame_name
|
|
end
|
|
|
|
local function boss_frame(player, alert)
|
|
local main_winning_frame = player.gui.screen[main_frame_name]
|
|
if main_winning_frame then
|
|
Gui.remove_data_recursively(main_winning_frame)
|
|
main_winning_frame.destroy()
|
|
end
|
|
local main_player_boss_frame = player.gui.screen[boss_frame_name]
|
|
if main_player_boss_frame then
|
|
Gui.remove_data_recursively(main_player_boss_frame)
|
|
main_player_boss_frame.destroy()
|
|
end
|
|
|
|
local data = {}
|
|
|
|
local stateful = Public.get_stateful()
|
|
local collection = stateful.collection
|
|
|
|
local frame = player.gui.screen.add { type = 'frame', name = boss_frame_name, caption = { 'stateful.win_conditions' }, direction = 'vertical' }
|
|
if not alert then
|
|
frame.location = { x = 1, y = 45 }
|
|
else
|
|
frame.location = { x = 1, y = 123 }
|
|
end
|
|
frame.style.maximal_height = 500
|
|
frame.style.minimal_width = 200
|
|
frame.style.maximal_width = 400
|
|
local season_tbl = frame.add { type = 'table', column_count = 2 }
|
|
season_tbl.style.horizontally_stretchable = true
|
|
|
|
local season_left_flow = season_tbl.add({ type = 'flow' })
|
|
season_left_flow.style.horizontal_align = 'left'
|
|
season_left_flow.style.horizontally_stretchable = true
|
|
|
|
season_left_flow.add({ type = 'label', caption = { 'stateful.season' }, tooltip = { 'stateful.season_tooltip', stateful.time_to_reset } })
|
|
frame.add({ type = 'line', direction = 'vertical' })
|
|
local season_right_flow = season_tbl.add({ type = 'flow' })
|
|
season_right_flow.style.horizontal_align = 'right'
|
|
season_right_flow.style.horizontally_stretchable = true
|
|
|
|
data.season_label = season_right_flow.add({ type = 'label', caption = stateful.season })
|
|
|
|
spacer(frame)
|
|
|
|
local rounds_survived_tbl = frame.add { type = 'table', column_count = 2 }
|
|
rounds_survived_tbl.style.horizontally_stretchable = true
|
|
|
|
local rounds_survived_left_flow = rounds_survived_tbl.add({ type = 'flow' })
|
|
rounds_survived_left_flow.style.horizontal_align = 'left'
|
|
rounds_survived_left_flow.style.horizontally_stretchable = true
|
|
|
|
rounds_survived_left_flow.add({ type = 'label', caption = { 'stateful.rounds_survived' }, tooltip = { 'stateful.rounds_survived_tooltip' } })
|
|
frame.add({ type = 'line', direction = 'vertical' })
|
|
local rounds_survived_right_flow = rounds_survived_tbl.add({ type = 'flow' })
|
|
rounds_survived_right_flow.style.horizontal_align = 'right'
|
|
rounds_survived_right_flow.style.horizontally_stretchable = true
|
|
|
|
data.rounds_survived_label = rounds_survived_right_flow.add({ type = 'label', caption = stateful.rounds_survived })
|
|
spacer(frame)
|
|
|
|
frame.add({ type = 'line' })
|
|
|
|
spacer(frame)
|
|
|
|
if not collection.game_won then
|
|
local objective_tbl = frame.add { type = 'table', column_count = 2 }
|
|
objective_tbl.style.horizontally_stretchable = true
|
|
|
|
if collection.gather_time <= 0 then
|
|
local survive_for_left_flow = objective_tbl.add({ type = 'flow' })
|
|
survive_for_left_flow.style.horizontal_align = 'left'
|
|
survive_for_left_flow.style.horizontally_stretchable = true
|
|
|
|
survive_for_left_flow.add({ type = 'label', caption = { 'stateful.survive_for' } })
|
|
frame.add({ type = 'line', direction = 'vertical' })
|
|
local survive_for_right_flow = objective_tbl.add({ type = 'flow' })
|
|
survive_for_right_flow.style.horizontal_align = 'right'
|
|
survive_for_right_flow.style.horizontally_stretchable = true
|
|
|
|
local survive_for_timer = floor(collection.survive_for / 60 / 60) .. 'm'
|
|
|
|
if collection.survive_for / 60 / 60 <= 1 then
|
|
survive_for_timer = floor(collection.survive_for / 60) .. 's'
|
|
end
|
|
|
|
if collection.survive_for <= 0 then
|
|
data.survive_for = survive_for_right_flow.add({ type = 'label', caption = { 'stateful.won' } })
|
|
else
|
|
data.survive_for = survive_for_right_flow.add({ type = 'label', caption = survive_for_timer })
|
|
end
|
|
end
|
|
-- new frame
|
|
local biter_sprites_tbl = objective_tbl.add({ type = 'flow' })
|
|
biter_sprites_tbl.style.horizontal_align = 'left'
|
|
biter_sprites_tbl.style.horizontally_stretchable = true
|
|
|
|
biter_sprites_tbl.add({ type = 'label', caption = { 'stateful.biter_sprites' } })
|
|
else
|
|
local objective_tbl = frame.add { type = 'table', column_count = 2 }
|
|
objective_tbl.style.horizontally_stretchable = true
|
|
|
|
local game_won_left_flow = objective_tbl.add({ type = 'flow' })
|
|
game_won_left_flow.style.horizontal_align = 'left'
|
|
game_won_left_flow.style.horizontally_stretchable = true
|
|
|
|
game_won_left_flow.add({ type = 'label', caption = { 'stateful.game_won' } })
|
|
end
|
|
|
|
local close = frame.add({ type = 'button', name = close_button, caption = 'Close' })
|
|
close.style.horizontally_stretchable = true
|
|
Gui.set_data(frame, data)
|
|
end
|
|
|
|
local function refresh_boss_frame()
|
|
Core.iter_connected_players(
|
|
function (player)
|
|
boss_frame(player)
|
|
end
|
|
)
|
|
end
|
|
|
|
main_frame = function (player)
|
|
local main_player_frame = player.gui.screen[main_frame_name]
|
|
if main_player_frame then
|
|
Gui.remove_data_recursively(main_player_frame)
|
|
main_player_frame.destroy()
|
|
end
|
|
|
|
local data = {}
|
|
|
|
local stateful = Public.get_stateful()
|
|
local breached_wall = Public.get('breached_wall')
|
|
breached_wall = breached_wall - 1
|
|
local wave_number = WD.get('wave_number')
|
|
|
|
local frame = player.gui.screen.add { type = 'frame', name = main_frame_name, caption = { 'stateful.win_conditions' }, direction = 'vertical', tooltip = { 'stateful.win_conditions_tooltip' } }
|
|
if Gui.get_mod_gui_top_frame() then
|
|
frame.location = { x = 0, y = 67 }
|
|
else
|
|
frame.location = { x = 1, y = 45 }
|
|
end
|
|
frame.style.maximal_height = 700
|
|
frame.style.minimal_width = 200
|
|
frame.style.maximal_width = 400
|
|
local season_tbl = frame.add { type = 'table', column_count = 2 }
|
|
season_tbl.style.horizontally_stretchable = true
|
|
|
|
local season_left_flow = season_tbl.add({ type = 'flow' })
|
|
season_left_flow.style.horizontal_align = 'left'
|
|
season_left_flow.style.horizontally_stretchable = true
|
|
|
|
season_left_flow.add({ type = 'label', caption = { 'stateful.season' }, tooltip = { 'stateful.season_tooltip', stateful.time_to_reset } })
|
|
frame.add({ type = 'line', direction = 'vertical' })
|
|
local season_right_flow = season_tbl.add({ type = 'flow' })
|
|
season_right_flow.style.horizontal_align = 'right'
|
|
season_right_flow.style.horizontally_stretchable = true
|
|
|
|
data.season_label = season_right_flow.add({ type = 'label', caption = stateful.season })
|
|
|
|
spacer(frame)
|
|
|
|
local rounds_survived_tbl = frame.add { type = 'table', column_count = 2 }
|
|
rounds_survived_tbl.style.horizontally_stretchable = true
|
|
|
|
local rounds_survived_left_flow = rounds_survived_tbl.add({ type = 'flow' })
|
|
rounds_survived_left_flow.style.horizontal_align = 'left'
|
|
rounds_survived_left_flow.style.horizontally_stretchable = true
|
|
|
|
rounds_survived_left_flow.add({ type = 'label', caption = { 'stateful.rounds_survived' }, tooltip = { 'stateful.rounds_survived_tooltip' } })
|
|
frame.add({ type = 'line', direction = 'vertical' })
|
|
local rounds_survived_right_flow = rounds_survived_tbl.add({ type = 'flow' })
|
|
rounds_survived_right_flow.style.horizontal_align = 'right'
|
|
rounds_survived_right_flow.style.horizontally_stretchable = true
|
|
|
|
data.rounds_survived_label = rounds_survived_right_flow.add({ type = 'label', caption = stateful.rounds_survived })
|
|
spacer(frame)
|
|
|
|
frame.add({ type = 'line' })
|
|
|
|
spacer(frame)
|
|
|
|
if stateful.buffs and next(stateful.buffs) then
|
|
local buff_tbl = frame.add { type = 'table', column_count = 2 }
|
|
buff_tbl.style.horizontally_stretchable = true
|
|
|
|
local buff_left_flow = buff_tbl.add({ type = 'flow' })
|
|
buff_left_flow.style.horizontal_align = 'left'
|
|
buff_left_flow.style.horizontally_stretchable = true
|
|
|
|
local buff_right_flow = buff_tbl.add({ type = 'flow' })
|
|
buff_right_flow.style.horizontal_align = 'right'
|
|
buff_right_flow.style.horizontally_stretchable = true
|
|
|
|
buff_right_flow.add({ name = on_click_buff_name, type = 'label', caption = '[img=utility/center]', tooltip = { 'stateful.buff_tooltip_click' } })
|
|
|
|
local buff_label = buff_left_flow.add({ type = 'label', caption = { 'stateful.buffs' }, tooltip = { 'stateful.buff_tooltip' } })
|
|
buff_label.style.single_line = false
|
|
frame.add({ type = 'line', direction = 'vertical' })
|
|
|
|
spacer(frame)
|
|
|
|
frame.add({ type = 'line' })
|
|
end
|
|
|
|
spacer(frame)
|
|
|
|
if stateful.objectives_completed.boss_time then
|
|
local gather_objective_tbl = frame.add { type = 'table', column_count = 2 }
|
|
gather_objective_tbl.style.horizontally_stretchable = true
|
|
|
|
local gather_warning_flow = gather_objective_tbl.add({ type = 'flow' })
|
|
gather_warning_flow.style.horizontal_align = 'left'
|
|
gather_warning_flow.style.horizontally_stretchable = true
|
|
|
|
gather_warning_flow.add({ type = 'label', caption = { 'stateful.gather' } })
|
|
frame.add({ type = 'line', direction = 'vertical' })
|
|
|
|
local objective_tbl = frame.add { type = 'table', column_count = 2 }
|
|
objective_tbl.style.horizontally_stretchable = true
|
|
|
|
local warn_timer_flow_left = objective_tbl.add({ type = 'flow' })
|
|
warn_timer_flow_left.style.horizontal_align = 'left'
|
|
warn_timer_flow_left.style.horizontally_stretchable = true
|
|
|
|
warn_timer_flow_left.add({ type = 'label', caption = { 'stateful.warp' }, tooltip = { 'stateful.warp_tooltip' } })
|
|
frame.add({ type = 'line', direction = 'vertical' })
|
|
|
|
local warn_timer_flow_right = objective_tbl.add({ type = 'flow' })
|
|
warn_timer_flow_right.style.horizontal_align = 'right'
|
|
warn_timer_flow_right.style.horizontally_stretchable = true
|
|
|
|
local time_left = floor(stateful.collection.gather_time / 60 / 60) .. 'm'
|
|
|
|
if stateful.collection.gather_time / 60 / 60 <= 1 then
|
|
time_left = floor(stateful.collection.gather_time / 60) .. 's'
|
|
end
|
|
|
|
data.gather_time_label = warn_timer_flow_right.add({ type = 'label', caption = time_left })
|
|
else
|
|
local objective_tbl = frame.add { type = 'table', column_count = 2 }
|
|
objective_tbl.style.horizontally_stretchable = true
|
|
|
|
local zone_left_flow = objective_tbl.add({ type = 'flow' })
|
|
zone_left_flow.style.horizontal_align = 'left'
|
|
zone_left_flow.style.horizontally_stretchable = true
|
|
|
|
zone_left_flow.add({ type = 'label', caption = { 'stateful.zone' }, tooltip = { 'stateful.zone_tooltip' } })
|
|
frame.add({ type = 'line', direction = 'vertical' })
|
|
local zone_right_flow = objective_tbl.add({ type = 'flow' })
|
|
zone_right_flow.style.horizontal_align = 'right'
|
|
zone_right_flow.style.horizontally_stretchable = true
|
|
|
|
if breached_wall >= stateful.objectives.randomized_zone then
|
|
data.randomized_zone_label = zone_right_flow.add({ type = 'label', caption = breached_wall .. '/' .. stateful.objectives.randomized_zone .. ' [img=utility/check_mark_green]', tooltip = { 'stateful.tooltip_completed' } })
|
|
else
|
|
data.randomized_zone_label = zone_right_flow.add({ type = 'label', caption = breached_wall .. '/' .. stateful.objectives.randomized_zone .. ' [img=utility/not_available]', tooltip = { 'stateful.tooltip_not_completed' } })
|
|
end
|
|
|
|
-- new frame
|
|
local wave_left_flow = objective_tbl.add({ type = 'flow' })
|
|
wave_left_flow.style.horizontal_align = 'left'
|
|
wave_left_flow.style.horizontally_stretchable = true
|
|
|
|
wave_left_flow.add({ type = 'label', caption = { 'stateful.wave' }, tooltip = { 'stateful.wave_tooltip' } })
|
|
frame.add({ type = 'line', direction = 'vertical' })
|
|
local wave_right_flow = objective_tbl.add({ type = 'flow' })
|
|
wave_right_flow.style.horizontal_align = 'right'
|
|
wave_right_flow.style.horizontally_stretchable = true
|
|
|
|
if wave_number >= stateful.objectives.randomized_wave then
|
|
data.randomized_wave_label = wave_right_flow.add({ type = 'label', caption = wave_number .. '/' .. stateful.objectives.randomized_wave .. ' [img=utility/check_mark_green]', tooltip = { 'stateful.tooltip_completed' } })
|
|
else
|
|
data.randomized_wave_label = wave_right_flow.add({ type = 'label', caption = wave_number .. '/' .. stateful.objectives.randomized_wave .. ' [img=utility/not_available]', tooltip = { 'stateful.tooltip_not_completed' } })
|
|
end
|
|
|
|
--dynamic conditions
|
|
data.random_objectives = {}
|
|
|
|
for index = 1, #stateful.selected_objectives do
|
|
local objective = stateful.selected_objectives[index]
|
|
objective_frames(stateful, frame, objective, data)
|
|
end
|
|
end
|
|
|
|
-- warn players
|
|
spacer(frame)
|
|
frame.add({ type = 'line' })
|
|
spacer(frame)
|
|
-- if not stateful.collection.final_arena_disabled then
|
|
-- local final_label = frame.add({type = 'label', caption = {'stateful.tooltip_final'}})
|
|
-- final_label.style.single_line = false
|
|
-- else
|
|
-- local final_label_disabled = frame.add({type = 'label', caption = {'stateful.tooltip_final_disabled'}})
|
|
-- final_label_disabled.style.single_line = false
|
|
-- local reason_label = frame.add({type = 'label', caption = {'stateful.tooltip_completing'}})
|
|
-- reason_label.style.single_line = false
|
|
-- end
|
|
-- spacer(frame)
|
|
-- frame.add({type = 'line'})
|
|
spacer(frame)
|
|
|
|
local close = frame.add({ type = 'button', name = close_button, caption = 'Close' })
|
|
close.style.horizontally_stretchable = true
|
|
Gui.set_data(frame, data)
|
|
end
|
|
|
|
local function update_data()
|
|
local players = game.connected_players
|
|
local stateful = Public.get_stateful()
|
|
local breached_wall = Public.get('breached_wall')
|
|
if not breached_wall then
|
|
return
|
|
end
|
|
|
|
breached_wall = breached_wall - 1
|
|
local wave_number = WD.get('wave_number')
|
|
local collection = stateful.collection
|
|
|
|
for i = 1, #players do
|
|
local player = players[i]
|
|
local f = player.gui.screen[main_frame_name]
|
|
local b = player.gui.screen[boss_frame_name]
|
|
local data = Gui.get_data(f)
|
|
local data_boss = Gui.get_data(b)
|
|
|
|
if data then
|
|
if data.season_label and data.season_label.valid then
|
|
data.season_label.caption = stateful.season
|
|
end
|
|
if data.rounds_survived_label and data.rounds_survived_label.valid then
|
|
data.rounds_survived_label.caption = stateful.rounds_survived
|
|
end
|
|
if data.randomized_zone_label and data.randomized_zone_label.valid and stateful.objectives.randomized_zone then
|
|
if breached_wall >= stateful.objectives.randomized_zone then
|
|
data.randomized_zone_label.caption = breached_wall .. '/' .. stateful.objectives.randomized_zone .. ' [img=utility/check_mark_green]'
|
|
data.randomized_zone_label.tooltip = { 'stateful.tooltip_completed' }
|
|
else
|
|
data.randomized_zone_label.caption = breached_wall .. '/' .. stateful.objectives.randomized_zone .. ' [img=utility/not_available]'
|
|
end
|
|
end
|
|
|
|
if data.randomized_wave_label and data.randomized_wave_label.valid and stateful.objectives.randomized_wave then
|
|
if wave_number >= stateful.objectives.randomized_wave then
|
|
data.randomized_wave_label.caption = wave_number .. '/' .. stateful.objectives.randomized_wave .. ' [img=utility/check_mark_green]'
|
|
data.randomized_wave_label.tooltip = { 'stateful.tooltip_completed' }
|
|
else
|
|
data.randomized_wave_label.caption = wave_number .. '/' .. stateful.objectives.randomized_wave .. ' [img=utility/not_available]'
|
|
end
|
|
end
|
|
|
|
if data.supply and next(data.supply) then
|
|
local items_done = 0
|
|
local supplies = stateful.objectives.supplies
|
|
if supplies then
|
|
for index = 1, #data.supply do
|
|
local frame = data.supply[index]
|
|
if frame and frame.valid then
|
|
local supplies_data = supplies[index]
|
|
local count = Stateful.get_item_produced_count(supplies_data.name)
|
|
if count then
|
|
if not supplies_data.total then
|
|
supplies_data.total = supplies_data.count
|
|
end
|
|
supplies_data.count = supplies_data.total - count
|
|
if supplies_data.count <= 0 then
|
|
supplies_data.count = 0
|
|
items_done = items_done + 1
|
|
frame.number = nil
|
|
frame.sprite = 'utility/check_mark_green'
|
|
else
|
|
frame.number = supplies_data.count
|
|
frame.tooltip = 'Crafted: ' .. count .. '\nNeeded: ' .. (supplies_data.total or 0)
|
|
end
|
|
if items_done == 3 then
|
|
if data.supply_completed and data.supply_completed.valid then
|
|
data.supply_completed.caption = ' [img=utility/check_mark_green]'
|
|
end
|
|
end
|
|
else
|
|
frame.number = supplies_data.count
|
|
frame.tooltip = 'Crafted: 0\nNeeded: ' .. (supplies_data.total or 0)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if data.single_item and data.single_item.valid then
|
|
local single_item = stateful.objectives.single_item
|
|
if single_item then
|
|
local frame = data.single_item
|
|
local count = Stateful.get_item_produced_count(single_item.name)
|
|
if count then
|
|
if not single_item.total then
|
|
single_item.total = single_item.count
|
|
end
|
|
single_item.count = single_item.total - count
|
|
if single_item.count <= 0 then
|
|
single_item.count = 0
|
|
frame.number = nil
|
|
frame.sprite = 'utility/check_mark_green'
|
|
if data.single_item_complete and data.single_item_complete.valid then
|
|
data.single_item_complete.caption = ' [img=utility/check_mark_green]'
|
|
end
|
|
else
|
|
frame.number = single_item.count
|
|
frame.tooltip = count .. ' / ' .. single_item.total
|
|
frame.tooltip = 'Crafted: ' .. count .. '\nNeeded: ' .. (single_item.total or 0)
|
|
end
|
|
else
|
|
frame.number = single_item.count
|
|
frame.tooltip = 'Crafted: 0\nNeeded: ' .. (single_item.total or 0)
|
|
end
|
|
end
|
|
end
|
|
|
|
if stateful.collection.gather_time and data.gather_time_label and data.gather_time_label.valid then
|
|
local time_left = floor(stateful.collection.gather_time / 60 / 60) .. 'm'
|
|
|
|
if stateful.collection.gather_time / 60 / 60 <= 1 then
|
|
time_left = floor(stateful.collection.gather_time / 60) .. 's'
|
|
end
|
|
data.gather_time_label.caption = time_left
|
|
end
|
|
|
|
if data.random_objectives and next(data.random_objectives) then
|
|
for index = 1, #data.random_objectives do
|
|
local frame_data = data.random_objectives[index]
|
|
local name = frame_data.name
|
|
local frame = frame_data.frame
|
|
for objective_index = 1, #stateful.selected_objectives do
|
|
local objective = stateful.selected_objectives[objective_index]
|
|
local objective_name = objective.name
|
|
local callback = Task.get(objective.token)
|
|
local _, _, objective_locale_right, _, objective_tooltip_right = callback()
|
|
if name == objective_name and frame and frame.valid then
|
|
frame.caption = objective_locale_right
|
|
frame.tooltip = objective_tooltip_right
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if data_boss then
|
|
if data_boss.season_label and data_boss.season_label.valid then
|
|
data_boss.season_label.caption = stateful.season
|
|
end
|
|
if data_boss.rounds_survived_label and data_boss.rounds_survived_label.valid then
|
|
data_boss.rounds_survived_label.caption = stateful.rounds_survived
|
|
end
|
|
|
|
if collection.survive_for and data_boss.survive_for and data_boss.survive_for.valid then
|
|
if not stateful.objectives_completed.warn_players then
|
|
stateful.objectives_completed.warn_players = true
|
|
alert_players_sound()
|
|
end
|
|
|
|
local survive_for_timer = floor(collection.survive_for / 60 / 60) .. 'm'
|
|
|
|
if collection.survive_for / 60 / 60 <= 1 then
|
|
survive_for_timer = floor(collection.survive_for / 60) .. 's'
|
|
end
|
|
|
|
if collection.survive_for <= 0 then
|
|
data_boss.survive_for.caption = { 'stateful.won' }
|
|
else
|
|
data_boss.survive_for.caption = survive_for_timer
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function update_raw()
|
|
local game_lost = Public.get('game_lost')
|
|
|
|
if game_lost then
|
|
clear_all_frames()
|
|
return
|
|
end
|
|
|
|
local stateful = Public.get_stateful()
|
|
if not stateful or not stateful.objectives then
|
|
return
|
|
end
|
|
local breached_wall = Public.get('breached_wall')
|
|
if not breached_wall then
|
|
return
|
|
end
|
|
local wave_number = WD.get('wave_number')
|
|
local collection = stateful.collection
|
|
local tick = game.tick
|
|
|
|
breached_wall = breached_wall - 1
|
|
if stateful.objectives.randomized_zone then
|
|
if breached_wall >= stateful.objectives.randomized_zone then
|
|
if not stateful.objectives_completed.randomized_zone then
|
|
stateful.objectives_completed.randomized_zone = true
|
|
stateful.objectives_time_spent.randomized_zone = tick
|
|
play_achievement_unlocked()
|
|
Alert.alert_all_players(100, 'Objective: **breach zone** has been complete!')
|
|
Server.to_discord_embed('Objective: **breach zone** has been complete!')
|
|
stateful.objectives_completed_count = stateful.objectives_completed_count + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
if stateful.objectives.randomized_wave then
|
|
if wave_number >= stateful.objectives.randomized_wave then
|
|
if not stateful.objectives_completed.randomized_wave then
|
|
stateful.objectives_completed.randomized_wave = true
|
|
stateful.objectives_time_spent.randomized_wave = tick
|
|
|
|
play_achievement_unlocked()
|
|
Alert.alert_all_players(100, 'Objective: **survive until wave** has been complete!')
|
|
Server.to_discord_embed('Objective: **survive until wave** has been complete!')
|
|
stateful.objectives_completed_count = stateful.objectives_completed_count + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
if stateful.objectives.supplies and next(stateful.objectives.supplies) then
|
|
local items_done = 0
|
|
for index = 1, #stateful.objectives.supplies do
|
|
local supplies_data = stateful.objectives.supplies[index]
|
|
local count = Stateful.get_item_produced_count(supplies_data.name)
|
|
if count then
|
|
if not supplies_data.total then
|
|
supplies_data.total = supplies_data.count
|
|
end
|
|
supplies_data.count = supplies_data.total - count
|
|
if supplies_data.count <= 0 then
|
|
supplies_data.count = 0
|
|
items_done = items_done + 1
|
|
end
|
|
if items_done == 3 then
|
|
if not stateful.objectives_completed.supplies then
|
|
stateful.objectives_completed.supplies = true
|
|
stateful.objectives_time_spent.supplies = tick
|
|
Alert.alert_all_players(100, 'Objective: **produce 3 items multiple times** has been complete!')
|
|
Server.to_discord_embed('Objective: **produce 3 items multiple times** has been complete!')
|
|
play_achievement_unlocked()
|
|
stateful.objectives_completed_count = stateful.objectives_completed_count + 1
|
|
end
|
|
end
|
|
else
|
|
if not supplies_data.total then
|
|
supplies_data.total = supplies_data.count
|
|
end
|
|
supplies_data.count = supplies_data.total
|
|
end
|
|
end
|
|
end
|
|
|
|
if stateful.objectives.single_item then
|
|
local count = Stateful.get_item_produced_count(stateful.objectives.single_item.name)
|
|
if count then
|
|
if not stateful.objectives.single_item.total then
|
|
stateful.objectives.single_item.total = stateful.objectives.single_item.count
|
|
end
|
|
stateful.objectives.single_item.count = stateful.objectives.single_item.total - count
|
|
if stateful.objectives.single_item.count <= 0 then
|
|
stateful.objectives.single_item.count = 0
|
|
if not stateful.objectives_completed.single_item then
|
|
stateful.objectives_completed.single_item = true
|
|
stateful.objectives_time_spent.single_item = tick
|
|
play_achievement_unlocked()
|
|
Alert.alert_all_players(100, 'Objective: **produce an item multiple times** has been completed!')
|
|
Server.to_discord_embed('Objective: **produce an item multiple times** has been completed!')
|
|
stateful.objectives_completed_count = stateful.objectives_completed_count + 1
|
|
end
|
|
end
|
|
else
|
|
if not stateful.objectives.single_item.total then
|
|
stateful.objectives.single_item.total = stateful.objectives.single_item.count
|
|
end
|
|
|
|
stateful.objectives.single_item.count = stateful.objectives.single_item.total
|
|
end
|
|
end
|
|
|
|
if collection.gather_time and not collection.final_arena_disabled then
|
|
collection.gather_time = collection.gather_time_timer - tick
|
|
if collection.gather_time > 0 then
|
|
collection.gather_time = collection.gather_time
|
|
elseif collection.gather_time and collection.gather_time <= 0 then
|
|
collection.gather_time = 0
|
|
if not collection.gather_time_done then
|
|
collection.gather_time_done = true
|
|
if not collection.clear_rocks then
|
|
Public.find_rocks_and_slowly_remove()
|
|
collection.clear_rocks = true
|
|
end
|
|
LinkedChests.clear_linked_frames()
|
|
stateful.final_battle = true
|
|
Public.set('final_battle', true)
|
|
WD.set('final_battle', true)
|
|
|
|
collection.survive_for = game.tick + Stateful.scale((5 * 3600), (15 * 3600))
|
|
collection.survive_for_timer = collection.survive_for
|
|
WD.disable_spawning_biters(false)
|
|
Public.allocate()
|
|
Public.set_final_battle()
|
|
Server.to_discord_embed('Final battle starts now!')
|
|
refresh_boss_frame()
|
|
end
|
|
end
|
|
end
|
|
|
|
if collection.survive_for and collection.survive_for_timer then
|
|
collection.survive_for = collection.survive_for_timer - tick
|
|
if not collection.survive_for_alerted and collection.gather_time <= 0 then
|
|
collection.survive_for_alerted = true
|
|
refresh_boss_frame()
|
|
end
|
|
|
|
if collection.survive_for and collection.survive_for < 0 then
|
|
collection.survive_for = 0
|
|
if collection.game_won and not collection.game_won_notified then
|
|
game.print('[color=yellow][Mtn v3][/color] Game won!')
|
|
collection.game_won = true
|
|
stateful.collection.gather_time = 0
|
|
stateful.collection.gather_time_timer = 0
|
|
collection.survive_for = 0
|
|
collection.survive_for_timer = 0
|
|
refresh_frames()
|
|
|
|
local reversed = Public.get_stateful_settings('reversed')
|
|
if reversed then
|
|
Public.set_stateful_settings('reversed', false)
|
|
else
|
|
Public.set_stateful_settings('reversed', true)
|
|
end
|
|
|
|
collection.game_won_notified = true
|
|
refresh_boss_frame()
|
|
play_game_won()
|
|
WD.disable_spawning_biters(true)
|
|
Collapse.start_now(false)
|
|
WD.nuke_wave_gui()
|
|
Server.to_discord_embed('Game won!')
|
|
stateful.rounds_survived = stateful.rounds_survived + 1
|
|
stateful.selected_objectives = nil
|
|
local buff = Stateful.save_settings()
|
|
notify_won_to_discord(buff)
|
|
local locomotive = Public.get('locomotive')
|
|
if locomotive and locomotive.valid then
|
|
locomotive.surface.spill_item_stack(locomotive.position, { name = 'coin', count = 512 }, false)
|
|
end
|
|
Public.set('game_reset_tick', 5400)
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
if stateful.selected_objectives and next(stateful.selected_objectives) then
|
|
for objective_index = 1, #stateful.selected_objectives do
|
|
local objective = stateful.selected_objectives[objective_index]
|
|
local objective_name = objective.name
|
|
local callback = Task.get(objective.token)
|
|
local completed, _, _ = callback()
|
|
if completed and completed == true and not stateful.objectives_completed[objective_name] then
|
|
stateful.objectives_completed[objective_name] = true
|
|
stateful.objectives_time_spent[objective_name] = tick
|
|
Alert.alert_all_players(100, 'Objective: **' .. objective_name .. '** has been completed!')
|
|
Server.to_discord_embed('Objective: **' .. objective_name .. '** has been completed!')
|
|
play_achievement_unlocked()
|
|
stateful.objectives_completed_count = stateful.objectives_completed_count + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
if stateful.objectives_completed_count == stateful.tasks_required_to_win and not stateful.objectives_completed.boss_time then
|
|
stateful.objectives_completed.boss_time = true
|
|
|
|
Server.to_discord_embed('All objectives has been completed! Take your time to prepare for the final push!')
|
|
Alert.alert_all_players(300, 'All objectives has been completed!')
|
|
Alert.alert_all_players(300, 'Take your time to prepare for the final push!')
|
|
|
|
if stateful.collection.final_arena_disabled then
|
|
game.print('[color=yellow][Mtn v3][/color] Game won!')
|
|
game.print('[color=yellow][Mtn v3][/color] Final battle arena is currently being tweaked.')
|
|
collection.game_won = true
|
|
stateful.collection.gather_time = 0
|
|
stateful.collection.gather_time_timer = 0
|
|
collection.survive_for = 0
|
|
collection.survive_for_timer = 0
|
|
refresh_frames()
|
|
|
|
local reversed = Public.get_stateful_settings('reversed')
|
|
if reversed then
|
|
Public.set_stateful_settings('reversed', false)
|
|
else
|
|
Public.set_stateful_settings('reversed', true)
|
|
end
|
|
|
|
collection.game_won_notified = true
|
|
refresh_boss_frame()
|
|
play_game_won()
|
|
WD.disable_spawning_biters(true)
|
|
Collapse.start_now(false)
|
|
WD.nuke_wave_gui()
|
|
Server.to_discord_embed('Game won!')
|
|
stateful.rounds_survived = stateful.rounds_survived + 1
|
|
stateful.selected_objectives = nil
|
|
local buff = Stateful.save_settings()
|
|
notify_won_to_discord(buff)
|
|
local locomotive = Public.get('locomotive')
|
|
if locomotive and locomotive.valid then
|
|
locomotive.surface.spill_item_stack(locomotive.position, { name = 'coin', count = 512 }, false)
|
|
end
|
|
Public.set('game_reset_tick', 5400)
|
|
return
|
|
end
|
|
|
|
stateful.collection.gather_time = tick + (10 * 3600)
|
|
stateful.collection.gather_time_timer = tick + (10 * 3600)
|
|
game.forces.enemy.evolution_factor = 1
|
|
play_achievement_unlocked()
|
|
local reverse_position = zone_settings.zone_depth * (breached_wall + 1)
|
|
local reversed = Public.get_stateful_settings('reversed')
|
|
if not reversed then
|
|
reverse_position = reverse_position * -1
|
|
end
|
|
Explosives.disable(true)
|
|
WD.disable_spawning_biters(true)
|
|
WD.set_track_bosses_only(false)
|
|
Collapse.set_reverse_position({ 0, reverse_position })
|
|
Collapse.set_reverse_direction()
|
|
Collapse.reverse_start_now(true)
|
|
Alert.alert_all_players(200, 'Reverse collapse has been initiated!')
|
|
Server.to_discord_embed('Reverse collapse has been initiated!')
|
|
-- Public.stateful_blueprints.blueprint()
|
|
WD.nuke_wave_gui()
|
|
WD.set('final_battle', true)
|
|
Public.set('pre_final_battle', true)
|
|
|
|
refresh_frames()
|
|
end
|
|
end
|
|
|
|
local function on_player_joined_game(event)
|
|
local player = game.players[event.player_index]
|
|
if not player then
|
|
return
|
|
end
|
|
|
|
if not player.gui.top[main_button_name] then
|
|
create_button(player)
|
|
end
|
|
end
|
|
|
|
Gui.on_click(
|
|
main_button_name,
|
|
function (event)
|
|
local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Mtn v3 open stateful Button')
|
|
if is_spamming then
|
|
return
|
|
end
|
|
|
|
local game_lost = Public.get('game_lost')
|
|
if game_lost then
|
|
clear_all_frames()
|
|
return
|
|
end
|
|
|
|
local player = event.player
|
|
if not player or not player.valid then
|
|
return
|
|
end
|
|
|
|
local final_battle = Public.get_stateful('final_battle')
|
|
|
|
if final_battle then
|
|
local frame = player.gui.screen[boss_frame_name]
|
|
if frame then
|
|
Gui.remove_data_recursively(frame)
|
|
frame.destroy()
|
|
else
|
|
Gui.clear_all_active_frames(player)
|
|
boss_frame(player)
|
|
end
|
|
else
|
|
local frame = player.gui.screen[main_frame_name]
|
|
if frame then
|
|
Gui.remove_data_recursively(frame)
|
|
frame.destroy()
|
|
else
|
|
Gui.clear_all_active_frames(player)
|
|
main_frame(player)
|
|
end
|
|
end
|
|
end
|
|
)
|
|
|
|
Gui.on_click(
|
|
close_button,
|
|
function (event)
|
|
local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Mtn v3 close stateful Button')
|
|
if is_spamming then
|
|
return
|
|
end
|
|
|
|
local player = event.player
|
|
if not player or not player.valid then
|
|
return
|
|
end
|
|
|
|
local frame = player.gui.screen[main_frame_name]
|
|
|
|
if frame then
|
|
Gui.remove_data_recursively(frame)
|
|
frame.destroy()
|
|
end
|
|
|
|
local frame_boss = player.gui.screen[boss_frame_name]
|
|
|
|
if frame_boss then
|
|
Gui.remove_data_recursively(frame_boss)
|
|
frame_boss.destroy()
|
|
end
|
|
end
|
|
)
|
|
|
|
Gui.on_click(
|
|
close_buffs_window_name,
|
|
function (event)
|
|
local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Buff Close Button')
|
|
if is_spamming then
|
|
return
|
|
end
|
|
local player = event.player
|
|
local center = player.gui.center
|
|
if not player or not player.valid or not player.character then
|
|
return
|
|
end
|
|
|
|
local frame_buff = center[buffs_window_name]
|
|
if frame_buff and frame_buff.valid then
|
|
Gui.remove_data_recursively(frame_buff)
|
|
frame_buff.destroy()
|
|
end
|
|
end
|
|
)
|
|
|
|
Gui.on_custom_close(
|
|
buffs_window_name,
|
|
function (event)
|
|
local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Buff Custom Close')
|
|
if is_spamming then
|
|
return
|
|
end
|
|
local player = event.player
|
|
local center = player.gui.center
|
|
if not player or not player.valid or not player.character then
|
|
return
|
|
end
|
|
|
|
local frame_buff = center[buffs_window_name]
|
|
if frame_buff and frame_buff.valid then
|
|
Gui.remove_data_recursively(frame_buff)
|
|
frame_buff.destroy()
|
|
end
|
|
end
|
|
)
|
|
|
|
Gui.on_click(
|
|
on_click_buff_name,
|
|
function (event)
|
|
local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Buff Open Button')
|
|
if is_spamming then
|
|
return
|
|
end
|
|
local player = event.player
|
|
local center = player.gui.center
|
|
if not player or not player.valid or not player.character then
|
|
return
|
|
end
|
|
|
|
local frame_buff = center[buffs_window_name]
|
|
if frame_buff and frame_buff.valid then
|
|
Gui.remove_data_recursively(frame_buff)
|
|
frame_buff.destroy()
|
|
else
|
|
buff_window(player)
|
|
end
|
|
end
|
|
)
|
|
|
|
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
|
|
Event.on_nth_tick(30, update_data)
|
|
Event.on_nth_tick(30, update_raw)
|
|
|
|
Public.boss_frame = boss_frame
|
|
Public.clear_all_frames = clear_all_frames
|
|
Stateful.refresh_frames = refresh_frames
|
|
|
|
return Public
|