mirror of
https://github.com/Refactorio/RedMew.git
synced 2024-12-16 10:19:27 +02:00
387 lines
13 KiB
Lua
387 lines
13 KiB
Lua
--[[-- info
|
|
Provides the ability to purchase items from the market.
|
|
]]
|
|
|
|
-- dependencies
|
|
local Event = require 'utils.event'
|
|
local Token = require 'utils.global_token'
|
|
local Task = require 'utils.Task'
|
|
local Gui = require 'utils.gui'
|
|
local Debug = require 'map_gen.Diggy.Debug'
|
|
local Template = require 'map_gen.Diggy.Template'
|
|
local Game = require 'utils.game'
|
|
local insert = table.insert
|
|
local force_control = require 'features.force_control'
|
|
local Experience = require 'map_gen.Diggy.Feature.Experience'
|
|
local max = math.max
|
|
local floor = math.floor
|
|
local utils = require 'utils.utils'
|
|
|
|
-- this
|
|
local MarketExchange = {}
|
|
|
|
local config = {}
|
|
|
|
local on_market_timeout_finished = Token.register(function(params)
|
|
Template.market(params.surface, params.position, params.player_force)
|
|
end)
|
|
|
|
---Updates market content with new items if they are to be unlocked
|
|
---Primarily used by the force control system at every level up
|
|
---@param market LuaEntity The market to be updated
|
|
---@param force LuaForce the force which the unlocking requirement should be based of
|
|
function MarketExchange.update_market_contents(market, force)
|
|
local add_market_item
|
|
local item_unlocked = false
|
|
|
|
for _, unlockable in pairs(config.unlockables) do
|
|
local is_in_range = force_control.get_force_data(force).current_level == unlockable.level
|
|
|
|
-- only add the item to the market if it's between the old and new stone range
|
|
if (is_in_range and unlockable.type == 'market') then
|
|
add_market_item = add_market_item or market.add_market_item
|
|
|
|
local name = unlockable.prototype.name
|
|
local price = unlockable.prototype.price
|
|
if type(price) == 'number' then
|
|
add_market_item({
|
|
price = {{config.currency_item, price}},
|
|
offer = {type = 'give-item', item = name, count = 1}
|
|
})
|
|
elseif type(price) == 'table' then
|
|
add_market_item({
|
|
price = price,
|
|
offer = {type = 'give-item', item = name, count = 1}
|
|
})
|
|
end
|
|
item_unlocked = true
|
|
|
|
end
|
|
end
|
|
end
|
|
|
|
local function redraw_title(data)
|
|
local force_data = force_control.get_force_data('player')
|
|
data.frame.caption = utils.comma_value(force_data.total_experience) .. ' total experience earned!'
|
|
end
|
|
|
|
local function get_data(unlocks, stone, type)
|
|
local result = {}
|
|
|
|
for _, data in pairs(unlocks) do
|
|
if data.level == stone and data.type == type then
|
|
insert(result, data)
|
|
end
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
local tag_label_stone = Gui.uid_name()
|
|
local tag_label_buff = Gui.uid_name()
|
|
local tag_label_item = Gui.uid_name()
|
|
|
|
local function apply_heading_style(style, width)
|
|
style.font = 'default-bold'
|
|
style.width = width
|
|
end
|
|
|
|
local function redraw_heading(data, header)
|
|
local head_condition = (header == 1)
|
|
local frame = (head_condition) and data.market_list_heading or data.buff_list_heading
|
|
local header_caption = (head_condition) and 'Reward Item' or 'Reward Buff'
|
|
Gui.clear(frame)
|
|
|
|
local heading_table = frame.add({type = 'table', column_count = 2})
|
|
apply_heading_style(heading_table.add({type = 'label', name = tag_label_stone, caption = 'Requirement'}).style, 100)
|
|
apply_heading_style(heading_table.add({type = 'label', name = tag_label_buff, caption = header_caption}).style, 220)
|
|
end
|
|
|
|
local function redraw_progressbar(data)
|
|
local force_data = force_control.get_force_data('player')
|
|
local flow = data.market_progressbars
|
|
Gui.clear(flow)
|
|
|
|
apply_heading_style(flow.add({type = 'label', tooltip = 'Currently at level: ' .. force_data.current_level .. '\nNext level at: ' .. utils.comma_value((force_data.total_experience - force_data.current_experience) + force_data.experience_level_up_cap) ..' xp\nRemaining xp: ' .. utils.comma_value(force_data.experience_level_up_cap - force_data.current_experience), name = 'Diggy.MarketExchange.Frame.Progress.Level', caption = 'Progress to next level:'}).style)
|
|
local level_progressbar = flow.add({type = 'progressbar', tooltip = floor(force_data.experience_percentage*100)*0.01 .. '% xp to next level'})
|
|
level_progressbar.style.width = 350
|
|
level_progressbar.value = force_data.experience_percentage * 0.01
|
|
end
|
|
|
|
local function redraw_table(data)
|
|
local market_scroll_pane = data.market_scroll_pane
|
|
Gui.clear(market_scroll_pane)
|
|
|
|
local buffs = {}
|
|
local items = {}
|
|
local last_stone = 0
|
|
local number_of_rows = 0
|
|
local row = {}
|
|
|
|
-- create the progress bars in the window
|
|
redraw_progressbar(data)
|
|
|
|
-- create table headings
|
|
redraw_heading(data, 1)
|
|
|
|
-- create table
|
|
for i = 1, #config.unlockables do
|
|
if config.unlockables[i].level ~= last_stone then
|
|
|
|
-- get items and buffs for each stone value
|
|
items = get_data(config.unlockables, config.unlockables[i].level, 'market')
|
|
|
|
-- get number of rows
|
|
number_of_rows = max(#buffs, #items)
|
|
|
|
-- loop through buffs and items for number of rows
|
|
for j = 1, number_of_rows do
|
|
local result = {}
|
|
local item = items[j]
|
|
local level = item.level
|
|
|
|
-- 1st column
|
|
result[1] = level
|
|
-- 3rd column
|
|
if items[j] ~= nil then
|
|
result[3] = '+ ' .. item.prototype.name
|
|
else
|
|
result[3] = ''
|
|
end
|
|
-- indicator to stop print stone number
|
|
if j > 1 then
|
|
result[4] = true
|
|
else
|
|
result[4] = false
|
|
end
|
|
-- indicator to draw horizontal line
|
|
if j == number_of_rows then
|
|
result[5] = true
|
|
else
|
|
result[5] = false
|
|
end
|
|
|
|
insert(row, result)
|
|
end
|
|
end
|
|
|
|
-- save lastStone
|
|
last_stone = config.unlockables[i].level
|
|
end
|
|
|
|
-- print table
|
|
for _, unlockable in pairs(row) do
|
|
local is_unlocked = unlockable[1] <= force_control.get_force_data('player').current_level
|
|
local list = market_scroll_pane.add {type = 'table', column_count = 2 }
|
|
|
|
list.style.horizontal_spacing = 16
|
|
|
|
local caption = ''
|
|
if unlockable[4] ~= true then
|
|
caption = 'Level ' .. unlockable[1]
|
|
else
|
|
caption = ''
|
|
end
|
|
local tag_stone = list.add {type = 'label', name = tag_label_stone, caption = caption, tooltip = 'XP: ' .. utils.comma_value(Experience.calculate_level_xp(unlockable[1]))}
|
|
tag_stone.style.minimal_width = 100
|
|
|
|
local tag_items = list.add {type = 'label', name = tag_label_item, caption = unlockable[3]}
|
|
tag_items.style.minimal_width = 220
|
|
|
|
-- draw horizontal line
|
|
if unlockable[5] == true then
|
|
list.draw_horizontal_line_after_headers = true
|
|
end
|
|
|
|
if (is_unlocked) then
|
|
tag_stone.style.font_color = {r = 1, g = 1, b = 1 }
|
|
tag_items.style.font_color = {r = 1, g = 1, b = 1 }
|
|
else
|
|
tag_stone.style.font_color = {r = 0.5, g = 0.5, b = 0.5 }
|
|
tag_items.style.font_color = {r = 0.5, g = 0.5, b = 0.5 }
|
|
end
|
|
end
|
|
end
|
|
|
|
local function redraw_buff(data) --! Almost equals to the redraw_table() function !
|
|
local buff_scroll_pane = data.buff_scroll_pane
|
|
Gui.clear(buff_scroll_pane)
|
|
|
|
local buffs = Experience.get_buffs()
|
|
local row = {}
|
|
local i = 0
|
|
for k, v in pairs(buffs) do
|
|
i = i + 1
|
|
local result = {}
|
|
|
|
-- 1st column
|
|
result[1] = 'All levels'
|
|
|
|
-- 2nd column
|
|
if k == 'mining_speed' then
|
|
result[2] = '+ '.. v.value .. '% mining speed'
|
|
elseif k == 'inventory_slot' then
|
|
if v.value > 1 then
|
|
result[2] = '+ '.. v.value .. ' inventory slots'
|
|
else
|
|
result[2] = '+ '.. v.value .. ' inventory slot'
|
|
end
|
|
elseif k == 'health_bonus' then
|
|
result[2] = '+ '.. v.value .. ' max health'
|
|
else
|
|
result[2] = 'Description missing: unknown buff. Please contact admin'
|
|
end
|
|
|
|
-- 3rd column
|
|
result[3] = ''
|
|
-- indicator to stop print level number
|
|
if i > 1 then
|
|
result[4] = true
|
|
else
|
|
result[4] = false
|
|
end
|
|
insert(row, result)
|
|
end
|
|
for _, unlockable in pairs(row) do
|
|
local list = buff_scroll_pane.add {type = 'table', column_count = 2 }
|
|
list.style.horizontal_spacing = 16
|
|
|
|
local caption = ''
|
|
if unlockable[4] ~= true then
|
|
caption = unlockable[1]
|
|
else
|
|
caption = ''
|
|
end
|
|
local tag_stone = list.add {type = 'label', name = buff_tag_label_stone, caption = caption}
|
|
tag_stone.style.minimal_width = 100
|
|
|
|
local tag_buffs = list.add {type = 'label', name = buff_tag_label_buff, caption = unlockable[2]}
|
|
tag_buffs.style.minimal_width = 220
|
|
|
|
tag_stone.style.font_color = {r = 1, g = 1, b = 1 }
|
|
tag_buffs.style.font_color = {r = 1, g = 1, b = 1 }
|
|
end
|
|
end
|
|
|
|
---Interface for force control system to access the primary market
|
|
---@return LuaEntity the primary market (The one at spawn)
|
|
function MarketExchange.get_market()
|
|
|
|
local markets = game.surfaces.nauvis.find_entities_filtered({name = 'market', position = config.market_spawn_position, limit = 1})
|
|
|
|
if (#markets == 0) then
|
|
Debug.print_position(config.market_spawn_position, 'Unable to find a market')
|
|
return
|
|
end
|
|
|
|
return markets[1]
|
|
end
|
|
|
|
local function on_placed_entity(event)
|
|
local market = event.entity
|
|
if 'market' ~= market.name then
|
|
return
|
|
end
|
|
end
|
|
|
|
function MarketExchange.get_extra_map_info(config)
|
|
return 'Market Exchange, come make a deal at the foreman\'s shop'
|
|
end
|
|
|
|
local function toggle(event)
|
|
local player = event.player
|
|
local left = player.gui.left
|
|
local frame = left['Diggy.MarketExchange.Frame']
|
|
|
|
if (frame and event.trigger == nil) then
|
|
Gui.destroy(frame)
|
|
return
|
|
elseif (frame) then
|
|
local data = Gui.get_data(frame)
|
|
redraw_title(data)
|
|
redraw_progressbar(data)
|
|
redraw_table(data)
|
|
return
|
|
end
|
|
|
|
frame = left.add({name = 'Diggy.MarketExchange.Frame', type = 'frame', direction = 'vertical'})
|
|
|
|
local market_progressbars = frame.add({type = 'flow', direction = 'vertical'})
|
|
local market_list_heading = frame.add({type = 'flow', direction = 'horizontal'})
|
|
|
|
local market_scroll_pane = frame.add({type = 'scroll-pane'})
|
|
market_scroll_pane.style.maximal_height = 300
|
|
|
|
local buff_list_heading = frame.add({type = 'flow', direction = 'horizontal'})
|
|
|
|
local buff_scroll_pane = frame.add({type = 'scroll-pane'})
|
|
buff_scroll_pane.style.maximal_height = 100
|
|
|
|
frame.add({ type = 'button', name = 'Diggy.MarketExchange.Button', caption = 'Close'})
|
|
|
|
local data = {
|
|
frame = frame,
|
|
market_progressbars = market_progressbars,
|
|
market_list_heading = market_list_heading,
|
|
market_scroll_pane = market_scroll_pane,
|
|
buff_list_heading = buff_list_heading,
|
|
buff_scroll_pane = buff_scroll_pane,
|
|
}
|
|
|
|
redraw_title(data)
|
|
redraw_table(data)
|
|
|
|
redraw_heading(data, 2)
|
|
redraw_buff(data)
|
|
|
|
Gui.set_data(frame, data)
|
|
|
|
end
|
|
|
|
local function on_player_created(event)
|
|
Game.get_player_by_index(event.player_index).gui.top.add({
|
|
name = 'Diggy.MarketExchange.Button',
|
|
type = 'sprite-button',
|
|
sprite = 'entity/market',
|
|
})
|
|
end
|
|
|
|
Gui.on_click('Diggy.MarketExchange.Button', toggle)
|
|
Gui.on_custom_close('Diggy.MarketExchange.Frame', function (event)
|
|
event.element.destroy()
|
|
end)
|
|
|
|
---Updates the market progress gui for every player that has it open
|
|
function MarketExchange.update_gui()
|
|
for _, p in ipairs(game.connected_players) do
|
|
local frame = p.gui.left['Diggy.MarketExchange.Frame']
|
|
|
|
if frame and frame.valid then
|
|
local data = {player = p, trigger = 'update_gui'}
|
|
toggle(data)
|
|
end
|
|
end
|
|
end
|
|
|
|
function MarketExchange.on_init()
|
|
Task.set_timeout_in_ticks(1, on_market_timeout_finished, {
|
|
surface = game.surfaces.nauvis,
|
|
position = config.market_spawn_position,
|
|
player_force = game.forces.player,
|
|
})
|
|
end
|
|
|
|
--[[--
|
|
Registers all event handlers.
|
|
]]
|
|
function MarketExchange.register(cfg)
|
|
config = cfg
|
|
|
|
--Events
|
|
Event.add(Template.events.on_placed_entity, on_placed_entity)
|
|
Event.add(defines.events.on_player_created, on_player_created)
|
|
Event.on_nth_tick(61, MarketExchange.update_gui)
|
|
end
|
|
|
|
return MarketExchange
|