mirror of
https://github.com/Refactorio/RedMew.git
synced 2025-01-05 22:53:39 +02:00
Merge pull request #523 from iltar/retailer-with-custom-gui
Added the crash-site GUI features to the retailer
This commit is contained in:
commit
0a076b5e1f
@ -1,10 +1,23 @@
|
||||
local Global = require 'utils.global'
|
||||
local insert = table.insert
|
||||
local Gui = require 'utils.gui'
|
||||
local Event = require 'utils.event'
|
||||
local PlayerStats = require 'features.player_stats'
|
||||
local Game = require 'utils.game'
|
||||
local math = require 'utils.math'
|
||||
local format = string.format
|
||||
local concat = table.concat
|
||||
local clamp = math.clamp
|
||||
local floor = math.floor
|
||||
local ceil = math.ceil
|
||||
local market_frame_name = Gui.uid_name()
|
||||
local item_button_name = Gui.uid_name()
|
||||
local count_slider_name = Gui.uid_name()
|
||||
local count_text_name = Gui.uid_name()
|
||||
|
||||
local Retailer = {}
|
||||
|
||||
---Global storage
|
||||
---Markets are indexed by the group_name and is a sequential list of LuaEntities
|
||||
---Markets are indexed by the position "x,y" and contains the group it belongs to
|
||||
---Items are indexed by the group name and is a list indexed by the item name and contains the prices per item
|
||||
local memory = {
|
||||
markets = {},
|
||||
@ -17,35 +30,6 @@ Global.register({
|
||||
memory = tbl.memory
|
||||
end)
|
||||
|
||||
---Add a market to the group_name retailer.
|
||||
---@param group_name string
|
||||
---@param market_entity LuaEntity
|
||||
function Retailer.add_market(group_name, market_entity)
|
||||
if not memory.markets[group_name] then
|
||||
memory.markets[group_name] = {market_entity}
|
||||
return
|
||||
end
|
||||
|
||||
insert(memory.markets[group_name], market_entity)
|
||||
end
|
||||
|
||||
---Sets an item for all the group_name markets.
|
||||
---@param group_name string
|
||||
---@param item_name string
|
||||
---@param prices table associative table where the key is the currency item and the value the amount of it
|
||||
function Retailer.set_item(group_name, item_name, prices)
|
||||
if not memory.items[group_name] then
|
||||
memory.items[group_name] = {}
|
||||
end
|
||||
|
||||
local market_format_prices = {}
|
||||
for currency, amount in pairs(prices) do
|
||||
insert(market_format_prices, {currency, amount})
|
||||
end
|
||||
|
||||
memory.items[group_name][item_name] = market_format_prices
|
||||
end
|
||||
|
||||
---Returns all item for the group_name retailer.
|
||||
---@param group_name string
|
||||
function Retailer.get_items(group_name)
|
||||
@ -63,42 +47,246 @@ function Retailer.remove_item(group_name, item_name)
|
||||
memory.items[group_name][item_name] = nil
|
||||
end
|
||||
|
||||
---Ships the current list of items with their prices to all markets for the group_name retailer.
|
||||
---@param group_name string
|
||||
function Retailer.ship_items(group_name)
|
||||
local markets = memory.markets[group_name]
|
||||
if not markets then
|
||||
return
|
||||
end
|
||||
local function redraw_market_items(data)
|
||||
local grid = data.grid
|
||||
|
||||
local market_items = memory.items[group_name]
|
||||
if not market_items then
|
||||
-- items have not been added yet
|
||||
return
|
||||
end
|
||||
Gui.clear(grid)
|
||||
|
||||
for _, market in ipairs(markets) do
|
||||
if market.valid then
|
||||
-- clean the current inventory
|
||||
local remove_market_item = market.remove_market_item
|
||||
-- remove re-indexes the offers, to prevent shifting, go backwards
|
||||
local current_market_items = market.get_market_items()
|
||||
if current_market_items then
|
||||
for current_index = #current_market_items, 1, -1 do
|
||||
remove_market_item(current_index)
|
||||
end
|
||||
end
|
||||
local count = data.count
|
||||
local market_items = data.market_items
|
||||
|
||||
-- re-add the whole list
|
||||
local add_market_item = market.add_market_item
|
||||
for item_name, prices in pairs(market_items) do
|
||||
add_market_item({
|
||||
price = prices,
|
||||
offer = {type = 'give-item', item = item_name, count = 1}
|
||||
})
|
||||
end
|
||||
for i, item in pairs(market_items) do
|
||||
local name = item.name
|
||||
local price = item.price
|
||||
|
||||
local price_per_item = format('%.2f', price)
|
||||
|
||||
local button = grid.add({type = 'flow'}).add({
|
||||
type = 'sprite-button',
|
||||
name = item_button_name,
|
||||
sprite = 'item/' .. name,
|
||||
number = count,
|
||||
tooltip = concat({name, ' price: ', price_per_item})
|
||||
})
|
||||
button.style = 'slot_button'
|
||||
|
||||
Gui.set_data(button, {index = i, data = data})
|
||||
|
||||
local message = ceil(price * count)
|
||||
if message == 1 then
|
||||
message = message .. ' coin'
|
||||
else
|
||||
message = message .. ' coins'
|
||||
end
|
||||
|
||||
local label = grid.add({type = 'label', caption = message})
|
||||
local label_style = label.style
|
||||
label_style.width = 80
|
||||
label_style.font = 'default-bold'
|
||||
end
|
||||
end
|
||||
|
||||
local function do_coin_label(player, label)
|
||||
local coin_count = player.get_item_count('coin')
|
||||
|
||||
if coin_count == 1 then
|
||||
label.caption = coin_count .. ' coin available'
|
||||
else
|
||||
label.caption = coin_count .. ' coins available'
|
||||
end
|
||||
end
|
||||
|
||||
local function draw_market_frame(player, group_name)
|
||||
local frame = player.gui.center.add({
|
||||
type = 'frame',
|
||||
name = market_frame_name,
|
||||
caption = 'Market',
|
||||
direction = 'vertical',
|
||||
})
|
||||
|
||||
local scroll_pane = frame.add({type = 'scroll-pane'})
|
||||
local scroll_style = scroll_pane.style
|
||||
scroll_style.maximal_height = 600
|
||||
|
||||
local grid = scroll_pane.add({type = 'table', column_count = 10})
|
||||
|
||||
local data = {
|
||||
grid = grid,
|
||||
count = 1,
|
||||
market_items = Retailer.get_items(group_name),
|
||||
}
|
||||
|
||||
redraw_market_items(data)
|
||||
|
||||
local coin_label = frame.add({type = 'label'})
|
||||
do_coin_label(player, coin_label)
|
||||
coin_label.style.font = 'default-bold'
|
||||
data.coin_label = coin_label
|
||||
|
||||
local count_flow = frame.add({type = 'flow'})
|
||||
|
||||
local count_slider = count_flow.add({
|
||||
type = 'slider',
|
||||
name = count_slider_name,
|
||||
minimum_value = 1,
|
||||
maximum_value = 7,
|
||||
value = 1,
|
||||
})
|
||||
local count_text = count_flow.add({
|
||||
type = 'text-box',
|
||||
name = count_text_name,
|
||||
text = '1',
|
||||
})
|
||||
|
||||
count_slider.style.width = 100
|
||||
count_text.style.width = 60
|
||||
|
||||
count_flow.add({type = 'label', caption = 'Quantity'}).style.font = 'default-bold'
|
||||
|
||||
data.slider = count_slider
|
||||
data.text = count_text
|
||||
|
||||
Gui.set_data(count_slider, data)
|
||||
Gui.set_data(count_text, data)
|
||||
|
||||
return frame
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_gui_opened, function (event)
|
||||
if not event.gui_type == defines.gui_type.entity then
|
||||
return
|
||||
end
|
||||
|
||||
local player = Game.get_player_by_index(event.player_index)
|
||||
if not player or not player.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local entity = event.entity
|
||||
if not entity or not entity.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local position = entity.position
|
||||
local group_name = memory.markets[position.x .. ',' .. position.y]
|
||||
if not group_name then
|
||||
return
|
||||
end
|
||||
|
||||
local frame = draw_market_frame(player, group_name)
|
||||
|
||||
player.opened = frame
|
||||
end)
|
||||
|
||||
Gui.on_custom_close(market_frame_name, function(event)
|
||||
local element = event.element
|
||||
Gui.destroy(element)
|
||||
end)
|
||||
|
||||
Event.add(defines.events.on_player_died, function(event)
|
||||
local player = Game.get_player_by_index(event.player_index or 0)
|
||||
|
||||
if not player or not player.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local element = player.gui.center
|
||||
|
||||
if element and element.valid then
|
||||
element = element[market_frame_name]
|
||||
if element and element.valid then
|
||||
Gui.destroy(element)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
Gui.on_value_changed(count_slider_name, function(event)
|
||||
local element = event.element
|
||||
local data = Gui.get_data(element)
|
||||
|
||||
local value = floor(element.slider_value)
|
||||
local count
|
||||
if value % 2 == 0 then
|
||||
count = 10 ^ (value * 0.5) * 0.5
|
||||
else
|
||||
count = 10 ^ ((value - 1) * 0.5)
|
||||
end
|
||||
|
||||
data.count = count
|
||||
data.text.text = count
|
||||
|
||||
redraw_market_items(data)
|
||||
end)
|
||||
|
||||
Gui.on_text_changed(count_text_name, function(event)
|
||||
local element = event.element
|
||||
local data = Gui.get_data(element)
|
||||
|
||||
local count = tonumber(element.text)
|
||||
|
||||
if count then
|
||||
count = floor(count)
|
||||
count = clamp(count, 1, 1000)
|
||||
data.count = count
|
||||
data.text.text = count
|
||||
else
|
||||
data.count = 1
|
||||
end
|
||||
|
||||
redraw_market_items(data)
|
||||
end)
|
||||
|
||||
Gui.on_click(item_button_name, function(event)
|
||||
local player = event.player
|
||||
local element = event.element
|
||||
local button_data = Gui.get_data(element)
|
||||
local data = button_data.data
|
||||
|
||||
local item = data.market_items[button_data.index]
|
||||
|
||||
local name = item.name
|
||||
local price = item.price
|
||||
local count = data.count
|
||||
|
||||
local cost = ceil(price * count)
|
||||
local coin_count = player.get_item_count('coin')
|
||||
|
||||
if cost > coin_count then
|
||||
player.print('Insufficient coins')
|
||||
return
|
||||
end
|
||||
|
||||
local inserted = player.insert({name = name, count = count})
|
||||
if inserted < count then
|
||||
player.print('Insufficient inventory space')
|
||||
if inserted > 0 then
|
||||
player.remove_item({name = name, count = inserted})
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
player.remove_item({name = 'coin', count = cost})
|
||||
do_coin_label(player, data.coin_label)
|
||||
PlayerStats.change_coin_spent(player.index, cost)
|
||||
end)
|
||||
|
||||
---Add a market to the group_name retailer.
|
||||
---@param group_name string
|
||||
---@param market_entity LuaEntity
|
||||
function Retailer.add_market(group_name, market_entity)
|
||||
local position = market_entity.position
|
||||
memory.markets[position.x .. ',' .. position.y] = group_name
|
||||
end
|
||||
|
||||
---Sets an item for all the group_name markets.
|
||||
---@param group_name string
|
||||
---@param prototype table with item name and price
|
||||
function Retailer.set_item(group_name, prototype)
|
||||
if not memory.items[group_name] then
|
||||
memory.items[group_name] = {}
|
||||
end
|
||||
|
||||
memory.items[group_name][prototype.name] = prototype
|
||||
end
|
||||
|
||||
return Retailer
|
||||
|
@ -3,7 +3,6 @@ local Event = require 'utils.event'
|
||||
local Game = require 'utils.game'
|
||||
local Global = require 'utils.global'
|
||||
local ForceControl = require 'features.force_control'
|
||||
local Debug = require 'map_gen.Diggy.Debug'
|
||||
local Retailer = require 'features.retailer'
|
||||
local Gui = require 'utils.gui'
|
||||
local force_control = require 'features.force_control'
|
||||
@ -83,11 +82,9 @@ function Experience.update_market_contents(force)
|
||||
local force_name = force.name
|
||||
for _, prototype in pairs(config.unlockables) do
|
||||
if (current_level >= prototype.level) then
|
||||
Retailer.set_item(force_name, prototype.name, {coin = prototype.price})
|
||||
Retailer.set_item(force_name, prototype)
|
||||
end
|
||||
end
|
||||
|
||||
Retailer.ship_items(force_name)
|
||||
end
|
||||
|
||||
---Updates a forces manual mining speed modifier. By removing active modifiers and re-adding
|
||||
|
@ -78,7 +78,6 @@ function StartingZone.register(config)
|
||||
market.destructible = false
|
||||
|
||||
Retailer.add_market(player_force.name, market)
|
||||
Retailer.ship_items(player_force.name)
|
||||
|
||||
player_force.add_chart_tag(surface, {
|
||||
text = 'Market',
|
||||
|
Loading…
Reference in New Issue
Block a user