2018-11-18 18:12:00 +02:00
--[[-- 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 Global = require ' utils.global '
local Game = require ' utils.game '
local insert = table.insert
2018-11-24 11:45:43 +02:00
local force_control = require ' features.force_control '
local Experience = require ' map_gen.Diggy.Feature.Experience '
2018-11-18 18:12:00 +02:00
local max = math.max
2018-11-24 11:45:43 +02:00
local floor = math.floor
2018-11-18 18:12:00 +02:00
local utils = require ' utils.utils '
local prefix = ' ## - '
-- this
local MarketExchange = { }
local config = { }
local on_market_timeout_finished = Token.register ( function ( params )
Template.market ( params.surface , params.position , params.player_force , { } )
end )
2018-11-24 11:45:43 +02:00
---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 )
2018-11-18 18:12:00 +02:00
local add_market_item
local item_unlocked = false
2018-11-21 15:42:39 +02:00
2018-11-18 18:12:00 +02:00
for _ , unlockable in pairs ( config.unlockables ) do
2018-11-24 11:45:43 +02:00
local is_in_range = force_control.get_force_data ( force ) . current_level == unlockable.level
2018-11-18 18:12:00 +02:00
-- 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 )
2018-11-24 11:45:43 +02:00
local force_data = force_control.get_force_data ( ' player ' )
data.frame . caption = utils.comma_value ( force_data.total_experience ) .. ' total experience earned! '
2018-11-18 18:12:00 +02:00
end
local function get_data ( unlocks , stone , type )
local result = { }
for _ , data in pairs ( unlocks ) do
2018-11-24 11:45:43 +02:00
if data.level == stone and data.type == type then
2018-11-18 18:12:00 +02:00
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 )
2018-11-24 11:45:43 +02:00
local force_data = force_control.get_force_data ( ' player ' )
2018-11-18 18:12:00 +02:00
local flow = data.market_progressbars
Gui.clear ( flow )
2018-11-24 11:45:43 +02:00
apply_heading_style ( flow.add ( { type = ' label ' , tooltip = ' Currently at level: ' .. force_data.current_level .. ' \n Next level at: ' .. utils.comma_value ( ( force_data.total_experience - force_data.current_experience ) + force_data.experience_level_up_cap ) .. ' xp \n Remaining 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 ' } )
2018-11-18 18:12:00 +02:00
level_progressbar.style . width = 350
2018-11-24 11:45:43 +02:00
level_progressbar.value = force_data.experience_percentage * 0.01
2018-11-18 18:12:00 +02:00
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
2018-11-24 11:45:43 +02:00
if config.unlockables [ i ] . level ~= last_stone then
2018-11-18 18:12:00 +02:00
-- get items and buffs for each stone value
2018-11-24 11:45:43 +02:00
items = get_data ( config.unlockables , config.unlockables [ i ] . level , ' market ' )
2018-11-18 18:12:00 +02:00
-- 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
2018-11-24 11:45:43 +02:00
result [ 1 ] = level
2018-11-18 18:12:00 +02:00
-- 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
2018-11-24 11:45:43 +02:00
last_stone = config.unlockables [ i ] . level
2018-11-18 18:12:00 +02:00
end
-- print table
for _ , unlockable in pairs ( row ) do
2018-11-24 11:45:43 +02:00
local is_unlocked = unlockable [ 1 ] <= force_control.get_force_data ( ' player ' ) . current_level
2018-11-18 18:12:00 +02:00
local list = market_scroll_pane.add { type = ' table ' , column_count = 2 }
list.style . horizontal_spacing = 16
local caption = ' '
if unlockable [ 4 ] ~= true then
2018-11-24 11:45:43 +02:00
caption = ' Level ' .. unlockable [ 1 ]
2018-11-18 18:12:00 +02:00
else
caption = ' '
end
2018-11-24 11:45:43 +02:00
local tag_stone = list.add { type = ' label ' , name = tag_label_stone , caption = caption , tooltip = ' XP: ' .. utils.comma_value ( Experience.calculate_level_xp ( unlockable [ 1 ] ) ) }
2018-11-18 18:12:00 +02:00
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 )
2018-11-24 11:45:43 +02:00
local buffs = Experience.get_buffs ( )
2018-11-18 18:12:00 +02:00
local row = { }
2018-11-24 11:45:43 +02:00
local i = 0
for k , v in pairs ( buffs ) do
i = i + 1
2018-11-18 18:12:00 +02:00
local result = { }
-- 1st column
result [ 1 ] = ' All levels '
-- 2nd column
2018-11-24 11:45:43 +02:00
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 '
2018-11-18 18:12:00 +02:00
else
2018-11-24 11:45:43 +02:00
result [ 2 ] = ' + ' .. v.value .. ' inventory slot '
2018-11-18 18:12:00 +02:00
end
2018-11-24 11:45:43 +02:00
elseif k == ' health_bonus ' then
result [ 2 ] = ' + ' .. v.value .. ' max health '
2018-11-18 18:12:00 +02:00
else
result [ 2 ] = ' Description missing: unknown buff. Please contact admin '
end
2018-11-21 15:42:39 +02:00
2018-11-18 18:12:00 +02:00
-- 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 )
2018-11-21 15:42:39 +02:00
end
2018-11-18 18:12:00 +02:00
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
2018-11-24 11:45:43 +02:00
---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 ' )
2018-11-18 18:12:00 +02:00
return
end
2018-11-24 11:45:43 +02:00
return markets [ 1 ]
2018-11-18 18:12:00 +02:00
end
local function on_placed_entity ( event )
local market = event.entity
2018-11-24 11:45:43 +02:00
if ' market ' ~= market.name then
2018-11-18 18:12:00 +02:00
return
end
end
function MarketExchange . get_extra_map_info ( config )
2018-11-24 11:45:43 +02:00
return ' Market Exchange, come make a deal at the foreman \' s shop '
2018-11-18 18:12:00 +02:00
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
2018-11-21 15:42:39 +02:00
2018-11-18 18:12:00 +02:00
local buff_list_heading = frame.add ( { type = ' flow ' , direction = ' horizontal ' } )
2018-11-21 15:42:39 +02:00
2018-11-18 18:12:00 +02:00
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 )
2018-11-21 15:42:39 +02:00
2018-11-18 18:12:00 +02:00
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 )
2018-11-24 11:45:43 +02:00
---Updates the market progress gui for every player that has it open
2018-11-18 18:12:00 +02:00
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 ( 50 , on_market_timeout_finished , {
surface = game.surfaces . nauvis ,
position = config.market_spawn_position ,
player_force = game.forces . player ,
} )
2018-11-24 11:45:43 +02:00
2018-11-18 18:12:00 +02:00
end
--[[--
Registers all event handlers .
] ]
function MarketExchange . register ( cfg )
config = cfg
2018-11-24 11:45:43 +02:00
--Events
2018-11-18 18:12:00 +02:00
Event.add ( Template.events . on_placed_entity , on_placed_entity )
Event.add ( defines.events . on_player_created , on_player_created )
2018-11-24 11:45:43 +02:00
Event.on_nth_tick ( 61 , MarketExchange.update_gui )
2018-11-18 18:12:00 +02:00
end
return MarketExchange