mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2024-12-30 23:17:53 +02:00
tweaks and fixes
This commit is contained in:
parent
736f556d82
commit
bef4bfea55
17
chatbot.lua
17
chatbot.lua
@ -17,7 +17,12 @@ local brain = {
|
||||
'If you have played for more than 5h in our maps then,',
|
||||
'you are eligible to run the command /jail and /free'
|
||||
},
|
||||
[3] = {'Scenario repository for download:', 'https://github.com/M3wM3w/ComfyFactorio'}
|
||||
[3] = {'Scenario repository for download:', 'https://github.com/M3wM3w/ComfyFactorio'},
|
||||
[4] = {
|
||||
'If you feel like the server is lagging, run the following command:',
|
||||
'/server-ups',
|
||||
'This will display the server UPS on your top right screen.'
|
||||
}
|
||||
}
|
||||
|
||||
local links = {
|
||||
@ -36,7 +41,8 @@ local links = {
|
||||
['stealing'] = brain[2],
|
||||
['stole'] = brain[2],
|
||||
['troll'] = brain[2],
|
||||
['trolling'] = brain[2]
|
||||
['lag'] = brain[4],
|
||||
['lagging'] = brain[4]
|
||||
}
|
||||
|
||||
local function on_player_created(event)
|
||||
@ -152,9 +158,6 @@ commands.add_command(
|
||||
|
||||
local function process_bot_answers(event)
|
||||
local player = game.players[event.player_index]
|
||||
if player.admin == true then
|
||||
return
|
||||
end
|
||||
local message = event.message
|
||||
message = string.lower(message)
|
||||
for word in string.gmatch(message, '%g+') do
|
||||
@ -171,6 +174,10 @@ local function on_console_chat(event)
|
||||
if not event.player_index then
|
||||
return
|
||||
end
|
||||
local secs = Server.get_current_time()
|
||||
if not secs then
|
||||
return
|
||||
end
|
||||
process_bot_answers(event)
|
||||
end
|
||||
|
||||
|
@ -13,6 +13,7 @@ require 'utils.datastore.color_data'
|
||||
require 'utils.datastore.session_data'
|
||||
require 'utils.datastore.jail_data'
|
||||
require 'utils.datastore.quickbar_data'
|
||||
require 'utils.datastore.logistics_data'
|
||||
require 'utils.datastore.message_on_join_data'
|
||||
require 'utils.datastore.player_tag_data'
|
||||
require 'chatbot'
|
||||
|
@ -1,5 +1,5 @@
|
||||
local Event = require 'utils.event'
|
||||
local Difficulty = require 'modules.difficulty_vote'
|
||||
local Difficulty = require 'maps.mountain_fortress_v3.difficulty_vote'
|
||||
|
||||
local Public = {}
|
||||
|
||||
|
@ -198,16 +198,18 @@ local function get_resource_market_buys()
|
||||
return buys
|
||||
end
|
||||
|
||||
local function get_market_item_list(market_types, rarity)
|
||||
local function get_market_item_list(rarity)
|
||||
if rarity < 1 then
|
||||
rarity = 1
|
||||
end
|
||||
if rarity > 10 then
|
||||
rarity = 10
|
||||
end
|
||||
local types = get_types()
|
||||
local list = {}
|
||||
for _, market_type in pairs(market_types) do
|
||||
for k, item in pairs(market[market_type]) do
|
||||
for i = 1, 9 do
|
||||
local branch = market[types[i]]
|
||||
for k, item in pairs(branch) do
|
||||
--if item.rarity <= rarity and item.rarity + 7 >= rarity then
|
||||
if item.rarity <= rarity then
|
||||
local price = random(floor(item.value * 0.75), floor(item.value * 1.25))
|
||||
@ -229,12 +231,7 @@ end
|
||||
|
||||
function Public.get_random_item(rarity, sell, buy)
|
||||
rarity = rarity or 0
|
||||
local types = get_types()
|
||||
table.shuffle_table(types)
|
||||
local items
|
||||
for i = 1, 9 do
|
||||
items = get_market_item_list({types[i]}, rarity)
|
||||
end
|
||||
local items = get_market_item_list(rarity)
|
||||
if not items then
|
||||
return
|
||||
end
|
||||
@ -244,7 +241,7 @@ function Public.get_random_item(rarity, sell, buy)
|
||||
|
||||
local items_return = {}
|
||||
|
||||
for i = 1, random(5, 10), 1 do
|
||||
for i = 1, 25, 1 do
|
||||
local item = items[i]
|
||||
if not item then
|
||||
break
|
||||
@ -256,14 +253,14 @@ function Public.get_random_item(rarity, sell, buy)
|
||||
|
||||
if sell then
|
||||
local sells = get_resource_market_sells()
|
||||
for i = 1, random(1, 20), 1 do
|
||||
for i = 1, random(1, 25), 1 do
|
||||
items_return[#items_return + 1] = sells[i]
|
||||
end
|
||||
end
|
||||
|
||||
if buy then
|
||||
local buys = get_resource_market_buys()
|
||||
for i = 1, random(1, 20), 1 do
|
||||
for i = 1, random(1, 25), 1 do
|
||||
items_return[#items_return + 1] = buys[i]
|
||||
end
|
||||
end
|
||||
@ -274,7 +271,7 @@ end
|
||||
function Public.mountain_market(surface, position, rarity, buy)
|
||||
local types = get_types()
|
||||
table.shuffle_table(types)
|
||||
local items = get_market_item_list({types[1], types[2], types[3]}, rarity)
|
||||
local items = get_market_item_list(rarity)
|
||||
if not items then
|
||||
return
|
||||
end
|
||||
|
@ -35,6 +35,10 @@ local spidertron_unlocked =
|
||||
end
|
||||
)
|
||||
|
||||
local calculate_hp = function(zone)
|
||||
return 2 + 0.2 * zone - 1 * floor(zone / 20)
|
||||
end
|
||||
|
||||
local first_player_to_zone =
|
||||
Token.register(
|
||||
function(data)
|
||||
@ -56,32 +60,6 @@ local artillery_warning =
|
||||
end
|
||||
)
|
||||
|
||||
local compare_collapse_and_train = function()
|
||||
local collapse_pos = Collapse.get_position()
|
||||
local locomotive = WPT.get('locomotive')
|
||||
if not locomotive or not locomotive.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local c_y = collapse_pos.y
|
||||
local t_y = locomotive.position.y
|
||||
|
||||
local gap_between_zones = WPT.get('gap_between_zones')
|
||||
|
||||
if c_y - t_y <= gap_between_zones.gap then
|
||||
if not gap_between_zones.set then
|
||||
Collapse.set_speed(8)
|
||||
Collapse.set_amount(6)
|
||||
gap_between_zones.set = true
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
Collapse.set_speed(6)
|
||||
Collapse.set_amount(11)
|
||||
gap_between_zones.set = false
|
||||
end
|
||||
|
||||
local function distance(player)
|
||||
local rpg_t = RPG_Settings.get('rpg_t')
|
||||
local rpg_extra = RPG_Settings.get('rpg_extra')
|
||||
@ -110,7 +88,7 @@ local function distance(player)
|
||||
WPT.set().placed_trains_in_zone.randomized = false
|
||||
WPT.set().placed_trains_in_zone.positions = {}
|
||||
raise_event(Balance.events.breached_wall, {})
|
||||
|
||||
--[[ global.biter_health_boost = calculate_hp(breached_wall) ]]
|
||||
if WPT.get('breached_wall') == WPT.get('spidertron_unlocked_at_wave') then
|
||||
local main_market_items = WPT.get('main_market_items')
|
||||
if not main_market_items['spidertron'] then
|
||||
@ -172,5 +150,4 @@ local function on_player_changed_position(event)
|
||||
distance(player)
|
||||
end
|
||||
|
||||
Event.on_nth_tick(100, compare_collapse_and_train)
|
||||
Event.add(defines.events.on_player_changed_position, on_player_changed_position)
|
||||
|
366
maps/mountain_fortress_v3/difficulty_vote.lua
Normal file
366
maps/mountain_fortress_v3/difficulty_vote.lua
Normal file
@ -0,0 +1,366 @@
|
||||
local Event = require 'utils.event'
|
||||
local Server = require 'utils.server'
|
||||
local Global = require 'utils.global'
|
||||
|
||||
local insert = table.insert
|
||||
local max = math.max
|
||||
|
||||
local this = {
|
||||
difficulties = {
|
||||
[1] = {
|
||||
name = 'Peaceful',
|
||||
index = 1,
|
||||
value = 0.25,
|
||||
color = {r = 0.00, g = 0.45, b = 0.00},
|
||||
print_color = {r = 0.00, g = 0.8, b = 0.00},
|
||||
count = 0
|
||||
},
|
||||
[2] = {
|
||||
name = 'Piece of cake',
|
||||
index = 2,
|
||||
value = 0.5,
|
||||
color = {r = 0.00, g = 0.35, b = 0.00},
|
||||
print_color = {r = 0.00, g = 0.6, b = 0.00},
|
||||
count = 0
|
||||
},
|
||||
[3] = {
|
||||
name = 'Easy',
|
||||
index = 3,
|
||||
value = 0.75,
|
||||
color = {r = 0.00, g = 0.25, b = 0.00},
|
||||
print_color = {r = 0.00, g = 0.4, b = 0.00},
|
||||
count = 0
|
||||
},
|
||||
[4] = {
|
||||
name = 'Normal',
|
||||
value = 1,
|
||||
index = 4,
|
||||
color = {r = 0.00, g = 0.00, b = 0.25},
|
||||
print_color = {r = 0.0, g = 0.0, b = 0.5},
|
||||
count = 0
|
||||
},
|
||||
[5] = {
|
||||
name = 'Hard',
|
||||
index = 5,
|
||||
value = 1.5,
|
||||
color = {r = 0.25, g = 0.00, b = 0.00},
|
||||
print_color = {r = 0.4, g = 0.0, b = 0.00},
|
||||
count = 0
|
||||
},
|
||||
[6] = {
|
||||
name = 'Nightmare',
|
||||
index = 6,
|
||||
value = 3,
|
||||
color = {r = 0.35, g = 0.00, b = 0.00},
|
||||
print_color = {r = 0.6, g = 0.0, b = 0.00},
|
||||
count = 0
|
||||
},
|
||||
[7] = {
|
||||
name = 'Impossible',
|
||||
index = 7,
|
||||
value = 5,
|
||||
color = {r = 0.45, g = 0.00, b = 0.00},
|
||||
print_color = {r = 0.8, g = 0.0, b = 0.00},
|
||||
count = 0
|
||||
}
|
||||
},
|
||||
tooltip = {
|
||||
[1] = '',
|
||||
[2] = '',
|
||||
[3] = '',
|
||||
[4] = '',
|
||||
[5] = '',
|
||||
[6] = '',
|
||||
[7] = ''
|
||||
},
|
||||
difficulty_vote_value = 1,
|
||||
difficulty_vote_index = 1,
|
||||
difficulty_poll_closing_timeout = 54000,
|
||||
difficulty_player_votes = {},
|
||||
gui_width = 108,
|
||||
name = 'Easy',
|
||||
button_tooltip = nil
|
||||
}
|
||||
|
||||
local Public = {}
|
||||
|
||||
Global.register(
|
||||
this,
|
||||
function(t)
|
||||
this = t
|
||||
end
|
||||
)
|
||||
|
||||
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(...)
|
||||
this.difficulty_poll_closing_timeout = ...
|
||||
end
|
||||
|
||||
function Public.get(key)
|
||||
if key then
|
||||
return this[key]
|
||||
else
|
||||
return this
|
||||
end
|
||||
end
|
||||
|
||||
function Public.difficulty_gui()
|
||||
local tooltip = 'Current difficulty of the map is ' .. this.difficulties[this.difficulty_vote_index].name .. '.'
|
||||
|
||||
for _, player in pairs(game.connected_players) do
|
||||
if player.gui.top['difficulty_gui'] then
|
||||
player.gui.top['difficulty_gui'].caption = this.difficulties[this.difficulty_vote_index].name
|
||||
player.gui.top['difficulty_gui'].tooltip = this.button_tooltip or tooltip
|
||||
player.gui.top['difficulty_gui'].style.font_color =
|
||||
this.difficulties[this.difficulty_vote_index].print_color
|
||||
else
|
||||
local b =
|
||||
player.gui.top.add {
|
||||
type = 'button',
|
||||
caption = this.difficulties[this.difficulty_vote_index].name,
|
||||
tooltip = tooltip,
|
||||
name = 'difficulty_gui'
|
||||
}
|
||||
b.style.font = 'heading-2'
|
||||
b.style.font_color = this.difficulties[this.difficulty_vote_index].print_color
|
||||
b.style.minimal_height = 38
|
||||
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
|
||||
|
||||
local highest = math.max(unpack(init.count))
|
||||
|
||||
local pre = {}
|
||||
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
|
||||
|
||||
local post = {}
|
||||
for i = 1, #pre do
|
||||
post[#post + 1] = pre[i].i
|
||||
end
|
||||
|
||||
highest = math.round(table.mean(post))
|
||||
|
||||
return highest
|
||||
end
|
||||
|
||||
local function poll_difficulty(player)
|
||||
if player.gui.center['difficulty_poll'] then
|
||||
player.gui.center['difficulty_poll'].destroy()
|
||||
return
|
||||
end
|
||||
if game.tick > this.difficulty_poll_closing_timeout then
|
||||
if player.online_time ~= 0 then
|
||||
local t = math.abs(math.floor((this.difficulty_poll_closing_timeout - game.tick) / 3600))
|
||||
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
|
||||
|
||||
local frame =
|
||||
player.gui.center.add {
|
||||
type = 'frame',
|
||||
caption = 'Vote difficulty:',
|
||||
name = 'difficulty_poll',
|
||||
direction = 'vertical'
|
||||
}
|
||||
for i = 1, #this.difficulties, 1 do
|
||||
local b = frame.add({type = 'button', name = tostring(i), caption = this.difficulties[i].name})
|
||||
b.style.font_color = this.difficulties[i].color
|
||||
b.style.font = 'heading-2'
|
||||
b.style.minimal_width = 160
|
||||
b.tooltip = this.tooltip[i]
|
||||
--[[ if this.difficulties[i].disabled then
|
||||
b.enabled = false
|
||||
end ]]
|
||||
end
|
||||
local b = frame.add({type = 'label', caption = '- - - - - - - - - - - - - - - - - -'})
|
||||
local b =
|
||||
frame.add(
|
||||
{
|
||||
type = 'button',
|
||||
name = 'close',
|
||||
caption = 'Close (' ..
|
||||
math.floor((this.difficulty_poll_closing_timeout - game.tick) / 3600) .. ' minutes left)'
|
||||
}
|
||||
)
|
||||
b.style.font_color = {r = 0.66, g = 0.0, b = 0.66}
|
||||
b.style.font = 'heading-3'
|
||||
b.style.minimal_width = 96
|
||||
end
|
||||
|
||||
local function set_difficulty()
|
||||
local index = highest_count(this.difficulties)
|
||||
|
||||
if this.difficulty_vote_index ~= index then
|
||||
local message =
|
||||
table.concat({'>> Map difficulty has changed to ', this.difficulties[index].name, ' difficulty!'})
|
||||
game.print(message, this.difficulties[index].print_color)
|
||||
Server.to_discord_embed(message)
|
||||
end
|
||||
this.difficulty_vote_index = index
|
||||
this.difficulty_vote_value = this.difficulties[index].value
|
||||
end
|
||||
|
||||
function Public.reset_difficulty_poll(tbl)
|
||||
if tbl then
|
||||
this.difficulty_vote_value = tbl.difficulty_vote_value or 1
|
||||
this.difficulty_vote_index = tbl.difficulty_vote_index or 1
|
||||
this.difficulty_player_votes = {}
|
||||
this.difficulty_poll_closing_timeout = tbl.difficulty_poll_closing_timeout or game.tick + 54000
|
||||
for _, p in pairs(game.connected_players) do
|
||||
if p.gui.center['difficulty_poll'] then
|
||||
p.gui.center['difficulty_poll'].destroy()
|
||||
end
|
||||
poll_difficulty(p)
|
||||
end
|
||||
for _, vote in pairs(this.difficulties) do
|
||||
vote.count = 0
|
||||
end
|
||||
Public.difficulty_gui()
|
||||
else
|
||||
this.difficulty_vote_value = 1
|
||||
this.difficulty_vote_index = 1
|
||||
this.difficulty_player_votes = {}
|
||||
this.difficulty_poll_closing_timeout = game.tick + 54000
|
||||
for _, p in pairs(game.connected_players) do
|
||||
if p.gui.center['difficulty_poll'] then
|
||||
p.gui.center['difficulty_poll'].destroy()
|
||||
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)
|
||||
local player = game.players[event.player_index]
|
||||
if game.tick < this.difficulty_poll_closing_timeout then
|
||||
if not this.difficulty_player_votes[player.name] then
|
||||
poll_difficulty(player)
|
||||
end
|
||||
else
|
||||
if player.gui.center['difficulty_poll'] then
|
||||
player.gui.center['difficulty_poll'].destroy()
|
||||
end
|
||||
end
|
||||
Public.difficulty_gui()
|
||||
end
|
||||
|
||||
local function on_player_left_game(event)
|
||||
if game.tick > this.difficulty_poll_closing_timeout then
|
||||
return
|
||||
end
|
||||
local player = game.players[event.player_index]
|
||||
if not this.difficulty_player_votes[player.name] then
|
||||
return
|
||||
end
|
||||
local index = this.difficulty_player_votes[player.name].index
|
||||
this.difficulties[index].count = this.difficulties[index].count - 1
|
||||
if this.difficulties[index].count <= 0 then
|
||||
this.difficulties[index].count = 0
|
||||
end
|
||||
this.difficulty_player_votes[player.name] = nil
|
||||
set_difficulty()
|
||||
Public.difficulty_gui()
|
||||
end
|
||||
|
||||
local function on_gui_click(event)
|
||||
if not event then
|
||||
return
|
||||
end
|
||||
if not event.element then
|
||||
return
|
||||
end
|
||||
if not event.element.valid then
|
||||
return
|
||||
end
|
||||
local player = game.players[event.element.player_index]
|
||||
if event.element.name == 'difficulty_gui' then
|
||||
poll_difficulty(player)
|
||||
return
|
||||
end
|
||||
if event.element.type ~= 'button' then
|
||||
return
|
||||
end
|
||||
if event.element.parent.name ~= 'difficulty_poll' then
|
||||
return
|
||||
end
|
||||
if event.element.name == 'close' then
|
||||
event.element.parent.destroy()
|
||||
return
|
||||
end
|
||||
if game.tick > this.difficulty_poll_closing_timeout then
|
||||
event.element.parent.destroy()
|
||||
return
|
||||
end
|
||||
|
||||
local i = tonumber(event.element.name)
|
||||
|
||||
if this.difficulty_player_votes[player.name] and this.difficulty_player_votes[player.name].index == i then
|
||||
player.print(
|
||||
'You have already voted for ' .. this.difficulties[i].name .. '.',
|
||||
this.difficulties[i].print_color
|
||||
)
|
||||
return
|
||||
end
|
||||
|
||||
if this.difficulty_player_votes[player.name] then
|
||||
local index = this.difficulty_player_votes[player.name].index
|
||||
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
|
||||
this.difficulty_player_votes[player.name] = {voted = true, index = i}
|
||||
|
||||
set_difficulty()
|
||||
Public.difficulty_gui()
|
||||
event.element.parent.destroy()
|
||||
game.print(
|
||||
player.name .. ' has voted for ' .. this.difficulties[i].name .. ' difficulty!',
|
||||
this.difficulties[i].print_color
|
||||
)
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
|
||||
Event.add(defines.events.on_player_left_game, on_player_left_game)
|
||||
Event.add(defines.events.on_gui_click, on_gui_click)
|
||||
|
||||
return Public
|
@ -11,7 +11,7 @@ local Functions = require 'modules.rpg.functions'
|
||||
local Mining = require 'maps.mountain_fortress_v3.mining'
|
||||
local Terrain = require 'maps.mountain_fortress_v3.terrain'
|
||||
local BiterHealthBooster = require 'modules.biter_health_booster'
|
||||
local Difficulty = require 'modules.difficulty_vote'
|
||||
local Difficulty = require 'maps.mountain_fortress_v3.difficulty_vote'
|
||||
local Traps = require 'maps.mountain_fortress_v3.traps'
|
||||
local Locomotive = require 'maps.mountain_fortress_v3.locomotive'
|
||||
local ExplosiveBullets = require 'maps.mountain_fortress_v3.explosive_gun_bullets'
|
||||
|
@ -5,7 +5,7 @@ local ICW = require 'maps.mountain_fortress_v3.icw.main'
|
||||
local WPT = require 'maps.mountain_fortress_v3.table'
|
||||
local WD = require 'modules.wave_defense.table'
|
||||
local Session = require 'utils.datastore.session_data'
|
||||
local Difficulty = require 'modules.difficulty_vote'
|
||||
local Difficulty = require 'maps.mountain_fortress_v3.difficulty_vote'
|
||||
local Jailed = require 'utils.datastore.jail_data'
|
||||
local RPG_Settings = require 'modules.rpg.table'
|
||||
local Functions = require 'modules.rpg.functions'
|
||||
@ -83,9 +83,11 @@ end
|
||||
local function add_random_loot_to_main_market(rarity)
|
||||
local main_market_items = WPT.get('main_market_items')
|
||||
local items = Market.get_random_item(rarity, true, false)
|
||||
if not items then
|
||||
return false
|
||||
end
|
||||
|
||||
local types = game.item_prototypes
|
||||
local ticker = 0
|
||||
|
||||
for k, v in pairs(main_market_items) do
|
||||
if not v.static then
|
||||
@ -97,7 +99,6 @@ local function add_random_loot_to_main_market(rarity)
|
||||
local price = v.price[1][2] + random(1, 15) * rarity
|
||||
local value = v.price[1][1]
|
||||
local stack = 1
|
||||
ticker = ticker + 1
|
||||
if v.offer.item == 'coin' then
|
||||
price = v.price[1][2]
|
||||
stack = v.offer.count
|
||||
@ -106,18 +107,14 @@ local function add_random_loot_to_main_market(rarity)
|
||||
end
|
||||
end
|
||||
|
||||
if main_market_items[v.offer.item] then
|
||||
main_market_items[v.offer.item] = nil
|
||||
end
|
||||
main_market_items[v.offer.item] = {
|
||||
stack = stack,
|
||||
value = value,
|
||||
price = price,
|
||||
tooltip = types[v.offer.item].localised_name,
|
||||
upgrade = false
|
||||
}
|
||||
if ticker >= 48 then
|
||||
break
|
||||
if not main_market_items[v.offer.item] then
|
||||
main_market_items[v.offer.item] = {
|
||||
stack = stack,
|
||||
value = value,
|
||||
price = price,
|
||||
tooltip = types[v.offer.item].localised_name,
|
||||
upgrade = false
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -976,7 +973,7 @@ local function gui_click(event)
|
||||
|
||||
local force = game.forces.player
|
||||
|
||||
force.manual_mining_speed_modifier = force.manual_mining_speed_modifier + 0.05
|
||||
force.manual_mining_speed_modifier = force.manual_mining_speed_modifier + this.pickaxe_speed_per_purchase
|
||||
|
||||
local force_mining_speed = WPT.get('force_mining_speed')
|
||||
force_mining_speed.speed = force.manual_mining_speed_modifier
|
||||
@ -1926,8 +1923,8 @@ function Public.get_items(reroll)
|
||||
if reroll then
|
||||
fixed_prices.chest_limit_cost = random(2000, 3000) * (1 + chest_limit_outside_upgrades)
|
||||
fixed_prices.health_cost = random(7000, 10000) * (1 + health_upgrades)
|
||||
fixed_prices.pickaxe_cost = random(2500, 4000) * (1 + pickaxe_tier)
|
||||
fixed_prices.reroll_cost = random(4000, 6000)
|
||||
fixed_prices.pickaxe_cost = random(1500, 2000)
|
||||
fixed_prices.reroll_cost = random(2000, 3000)
|
||||
fixed_prices.aura_cost = random(3000, 6000) * (1 + aura_upgrades)
|
||||
fixed_prices.xp_point_boost_cost = random(4000, 6000) * (1 + xp_points_upgrade)
|
||||
fixed_prices.explosive_bullets_cost = random(18000, 21000)
|
||||
|
@ -38,7 +38,7 @@ local Locomotive = require 'maps.mountain_fortress_v3.locomotive'
|
||||
local Score = require 'comfy_panel.score'
|
||||
local Poll = require 'comfy_panel.poll'
|
||||
local Collapse = require 'modules.collapse'
|
||||
local Difficulty = require 'modules.difficulty_vote'
|
||||
local Difficulty = require 'maps.mountain_fortress_v3.difficulty_vote'
|
||||
local Task = require 'utils.task'
|
||||
local Token = require 'utils.token'
|
||||
local Alert = require 'utils.alert'
|
||||
@ -125,7 +125,6 @@ end
|
||||
local set_difficulty = function()
|
||||
local Diff = Difficulty.get()
|
||||
local wave_defense_table = WD.get_table()
|
||||
local collapse_speed = WPT.get('collapse_speed')
|
||||
local collapse_amount = WPT.get('collapse_amount')
|
||||
local player_count = #game.connected_players
|
||||
if not Diff.difficulty_vote_value then
|
||||
@ -141,10 +140,13 @@ local set_difficulty = function()
|
||||
-- threat gain / wave
|
||||
wave_defense_table.threat_gain_multiplier = 1.2 + player_count * Diff.difficulty_vote_value * 0.1
|
||||
|
||||
local amount = player_count * 0.25 + 6
|
||||
local amount = player_count * 0.1
|
||||
amount = floor(amount)
|
||||
if amount > 10 then
|
||||
amount = 10
|
||||
if amount <= 0 then
|
||||
amount = 1
|
||||
end
|
||||
if amount > 5 then
|
||||
amount = 5
|
||||
end
|
||||
|
||||
local difficulty = Difficulty.get()
|
||||
@ -152,7 +154,6 @@ local set_difficulty = function()
|
||||
|
||||
if wave_defense_table.threat <= 0 then
|
||||
wave_defense_table.wave_interval = 1000
|
||||
return
|
||||
end
|
||||
if name == 'Insane' then
|
||||
wave_defense_table.wave_interval = 1800
|
||||
@ -169,26 +170,14 @@ local set_difficulty = function()
|
||||
end
|
||||
|
||||
if name == 'Insane' then
|
||||
Collapse.set_amount(12)
|
||||
Collapse.set_amount(10)
|
||||
elseif collapse_amount then
|
||||
Collapse.set_amount(collapse_amount)
|
||||
else
|
||||
Collapse.set_amount(amount)
|
||||
end
|
||||
|
||||
if name == 'Insane' then
|
||||
Collapse.set_speed(5)
|
||||
elseif collapse_speed then
|
||||
Collapse.set_speed(collapse_speed)
|
||||
else
|
||||
if player_count >= 8 and player_count <= 12 then
|
||||
Collapse.set_speed(8)
|
||||
elseif player_count >= 20 and player_count <= 24 then
|
||||
Collapse.set_speed(6)
|
||||
elseif player_count >= 35 then
|
||||
Collapse.set_speed(5)
|
||||
end
|
||||
end
|
||||
Collapse.set_speed(1)
|
||||
end
|
||||
|
||||
local render_direction = function(surface)
|
||||
@ -303,7 +292,9 @@ function Public.reset_map()
|
||||
Functions.reset_table()
|
||||
game.reset_time_played()
|
||||
WPT.reset_table()
|
||||
|
||||
Map_score.reset_score()
|
||||
|
||||
RPG_Func.rpg_reset_all_players()
|
||||
RPG_Settings.set_surface_name('mountain_fortress_v3')
|
||||
RPG_Settings.enable_health_and_mana_bars(true)
|
||||
@ -333,6 +324,7 @@ function Public.reset_map()
|
||||
|
||||
global.custom_highscore.description = 'Wagon distance reached:'
|
||||
Entities.set_scores()
|
||||
|
||||
AntiGrief.log_tree_harvest(true)
|
||||
AntiGrief.whitelist_types('tree', true)
|
||||
AntiGrief.enable_capsule_warning(false)
|
||||
@ -530,9 +522,6 @@ local on_research_finished = function(event)
|
||||
if research.name == 'steel-axe' then
|
||||
mining_speed_bonus = mining_speed_bonus + 0.5
|
||||
research.force.manual_mining_speed_modifier = mining_speed_bonus
|
||||
local msg =
|
||||
'Steel-axe technology has been researched, nerfing mining-speed.\nBuy Pickaxe-upgrades in the market!'
|
||||
Alert.alert_all_players(30, msg, nil, 'achievement/tech-maniac', 0.6)
|
||||
end -- +50% speed for steel-axe research
|
||||
|
||||
local force_name = research.force.name
|
||||
@ -736,6 +725,31 @@ local collapse_message =
|
||||
end
|
||||
)
|
||||
|
||||
local compare_collapse_and_train = function()
|
||||
local collapse_pos = Collapse.get_position()
|
||||
local locomotive = WPT.get('locomotive')
|
||||
if not locomotive or not locomotive.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local c_y = collapse_pos.y
|
||||
local t_y = locomotive.position.y
|
||||
|
||||
local gap_between_zones = WPT.get('gap_between_zones')
|
||||
|
||||
if c_y - t_y <= gap_between_zones.gap then
|
||||
if gap_between_zones.set then
|
||||
set_difficulty()
|
||||
gap_between_zones.set = false
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
Collapse.set_speed(1)
|
||||
Collapse.set_amount(4)
|
||||
gap_between_zones.set = true
|
||||
end
|
||||
|
||||
local collapse_after_wave_100 = function()
|
||||
local collapse_grace = WPT.get('collapse_grace')
|
||||
if not collapse_grace then
|
||||
@ -779,19 +793,23 @@ local on_tick = function()
|
||||
is_locomotive_valid()
|
||||
has_the_game_ended()
|
||||
chunk_load()
|
||||
end
|
||||
|
||||
if tick % 1200 == 0 then
|
||||
boost_difficulty()
|
||||
collapse_after_wave_100()
|
||||
Entities.set_scores()
|
||||
set_difficulty()
|
||||
local spawn_near_collapse = WPT.get('spawn_near_collapse')
|
||||
if spawn_near_collapse then
|
||||
local collapse_pos = Collapse.get_position()
|
||||
local position = surface.find_non_colliding_position('rocket-silo', collapse_pos, 128, 1)
|
||||
if position then
|
||||
WD.set_spawn_position(position)
|
||||
end
|
||||
if tick % 250 == 0 then
|
||||
compare_collapse_and_train()
|
||||
end
|
||||
|
||||
if tick % 1200 == 0 then
|
||||
boost_difficulty()
|
||||
collapse_after_wave_100()
|
||||
Entities.set_scores()
|
||||
set_difficulty()
|
||||
local spawn_near_collapse = WPT.get('spawn_near_collapse')
|
||||
if spawn_near_collapse then
|
||||
local collapse_pos = Collapse.get_position()
|
||||
local position = surface.find_non_colliding_position('rocket-silo', collapse_pos, 128, 1)
|
||||
if position then
|
||||
WD.set_spawn_position(position)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -804,27 +822,35 @@ local on_init = function()
|
||||
local difficulties = {
|
||||
[1] = {
|
||||
name = 'Easy',
|
||||
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}
|
||||
print_color = {r = 0.00, g = 0.4, b = 0.00},
|
||||
count = 0
|
||||
},
|
||||
[2] = {
|
||||
name = 'Normal',
|
||||
index = 2,
|
||||
value = 1,
|
||||
color = {r = 0.00, g = 0.00, b = 0.25},
|
||||
print_color = {r = 0.0, g = 0.0, b = 0.5}
|
||||
print_color = {r = 0.0, g = 0.0, b = 0.5},
|
||||
count = 0
|
||||
},
|
||||
[3] = {
|
||||
name = 'Hard',
|
||||
index = 3,
|
||||
value = 1.5,
|
||||
color = {r = 0.25, g = 0.25, b = 0.00},
|
||||
print_color = {r = 0.4, g = 0.0, b = 0.00}
|
||||
print_color = {r = 0.4, g = 0.0, b = 0.00},
|
||||
count = 0
|
||||
},
|
||||
[4] = {
|
||||
name = 'Insane',
|
||||
index = 4,
|
||||
value = 3,
|
||||
color = {r = 0.25, g = 0.00, b = 0.00},
|
||||
print_color = {r = 0.4, g = 0.0, b = 0.00}
|
||||
print_color = {r = 0.4, g = 0.0, b = 0.00},
|
||||
count = 0
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,6 +130,7 @@ function Public.reset_table()
|
||||
}
|
||||
this.aura_upgrades = 0
|
||||
this.pickaxe_tier = 1
|
||||
this.pickaxe_speed_per_purchase = 0.10
|
||||
this.health_upgrades = 0
|
||||
this.breached_wall = 1
|
||||
this.offline_players_enabled = true
|
||||
|
@ -1061,6 +1061,11 @@ local function on_player_used_capsule(event)
|
||||
return
|
||||
end
|
||||
|
||||
local function on_player_changed_surface(event)
|
||||
local player = game.get_player(event.player_index)
|
||||
RPG_GUI.draw_level_text(player)
|
||||
end
|
||||
|
||||
local function tick()
|
||||
local ticker = game.tick
|
||||
local count = #game.connected_players
|
||||
@ -1123,4 +1128,5 @@ Event.add(defines.events.on_player_respawned, on_player_respawned)
|
||||
Event.add(defines.events.on_player_rotated_entity, on_player_rotated_entity)
|
||||
Event.add(defines.events.on_pre_player_mined_item, on_pre_player_mined_item)
|
||||
Event.add(defines.events.on_player_used_capsule, on_player_used_capsule)
|
||||
Event.add(defines.events.on_player_changed_surface, on_player_changed_surface)
|
||||
Event.on_nth_tick(10, tick)
|
||||
|
@ -64,7 +64,7 @@ end
|
||||
|
||||
local function remove_trees(entity)
|
||||
local surface = entity.surface
|
||||
local radius = 10
|
||||
local radius = 15
|
||||
local pos = entity.position
|
||||
local area = {{pos.x - radius, pos.y - radius}, {pos.x + radius, pos.y + radius}}
|
||||
local trees = surface.find_entities_filtered {area = area, type = 'tree'}
|
||||
@ -79,7 +79,7 @@ end
|
||||
|
||||
local function remove_rocks(entity)
|
||||
local surface = entity.surface
|
||||
local radius = 10
|
||||
local radius = 15
|
||||
local pos = entity.position
|
||||
local area = {{pos.x - radius, pos.y - radius}, {pos.x + radius, pos.y + radius}}
|
||||
local rocks = surface.find_entities_filtered {area = area, type = 'simple-entity'}
|
||||
@ -289,10 +289,8 @@ local function set_enemy_evolution()
|
||||
evolution_factor = 1
|
||||
end
|
||||
|
||||
if this.threat > 50000 then
|
||||
biter_health_boost = math_round(biter_health_boost + (this.threat - 50000) * 0.000033, 3)
|
||||
biter_health_boost = math_round(biter_health_boost + (this.threat - 5000) * 0.000033, 3)
|
||||
--damage_increase = math_round(damage_increase + this.threat * 0.0000025, 3)
|
||||
end
|
||||
|
||||
global.biter_health_boost = biter_health_boost
|
||||
--game.forces.enemy.set_ammo_damage_modifier("melee", damage_increase)
|
||||
@ -392,8 +390,10 @@ local function set_next_wave()
|
||||
end
|
||||
|
||||
this.threat = this.threat + math_floor(threat_gain)
|
||||
this.last_wave = this.next_wave
|
||||
this.next_wave = game.tick + this.wave_interval
|
||||
if not this.wave_enforced then
|
||||
this.last_wave = this.next_wave
|
||||
this.next_wave = game.tick + this.wave_interval
|
||||
end
|
||||
if this.clear_corpses then
|
||||
local surface = game.surfaces[this.surface_index]
|
||||
for _, entity in pairs(surface.find_entities_filtered {type = 'corpse'}) do
|
||||
|
@ -11,6 +11,12 @@ Global.register(
|
||||
end
|
||||
)
|
||||
|
||||
function Public.debug_module()
|
||||
this.next_wave = 1000
|
||||
this.wave_interval = 500
|
||||
this.wave_enforced = true
|
||||
end
|
||||
|
||||
function Public.reset_wave_defense()
|
||||
this.boss_wave = false
|
||||
this.boss_wave_warning = false
|
||||
@ -48,6 +54,7 @@ function Public.reset_wave_defense()
|
||||
this.unit_group_command_step_length = 15
|
||||
this.unit_group_last_command = {}
|
||||
this.wave_interval = 3600
|
||||
this.wave_enforced = false
|
||||
this.wave_number = 0
|
||||
this.worm_building_chance = 3
|
||||
this.worm_building_density = 16
|
||||
|
133
utils/datastore/logistics_data.lua
Normal file
133
utils/datastore/logistics_data.lua
Normal file
@ -0,0 +1,133 @@
|
||||
local Token = require 'utils.token'
|
||||
local Color = require 'utils.color_presets'
|
||||
local Server = require 'utils.server'
|
||||
local Event = require 'utils.event'
|
||||
|
||||
local logistics_dataset = 'logistics'
|
||||
local logistics_dataset_modded = 'logistics_modded'
|
||||
local set_data = Server.set_data
|
||||
local try_get_data = Server.try_get_data
|
||||
|
||||
local Public = {}
|
||||
|
||||
local function is_game_modded()
|
||||
local i = 0
|
||||
for k, _ in pairs(game.active_mods) do
|
||||
i = i + 1
|
||||
if i > 1 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local fetch =
|
||||
Token.register(
|
||||
function(data)
|
||||
local key = data.key
|
||||
local value = data.value
|
||||
local player = game.players[key]
|
||||
if not player or not player.valid then
|
||||
return
|
||||
end
|
||||
if value then
|
||||
for i, item_name in pairs(value) do
|
||||
if item_name ~= nil and item_name ~= '' then
|
||||
player.set_personal_logistic_slot(i, item_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
--- Tries to get data from the webpanel and applies the value to the player.
|
||||
-- @param data_set player token
|
||||
function Public.fetch(key)
|
||||
local secs = Server.get_current_time()
|
||||
local dataset = logistics_dataset
|
||||
if not secs then
|
||||
local player = game.players[key]
|
||||
if not player or not player.valid then
|
||||
return
|
||||
end
|
||||
return
|
||||
else
|
||||
local game_has_mods = is_game_modded()
|
||||
if game_has_mods then
|
||||
dataset = logistics_dataset_modded
|
||||
end
|
||||
|
||||
try_get_data(dataset, key, fetch)
|
||||
end
|
||||
end
|
||||
|
||||
commands.add_command(
|
||||
'save-logistics',
|
||||
'Save your personal logistics preset so it´s always the same.',
|
||||
function()
|
||||
local player = game.player
|
||||
if not player or not player.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local secs = Server.get_current_time()
|
||||
if not secs then
|
||||
return
|
||||
end
|
||||
|
||||
local dataset = logistics_dataset
|
||||
|
||||
local game_has_mods = is_game_modded()
|
||||
if game_has_mods then
|
||||
dataset = logistics_dataset_modded
|
||||
end
|
||||
|
||||
local slots = {}
|
||||
|
||||
for i = 1, 100 do
|
||||
local slot = player.get_personal_logistic_slot(i)
|
||||
if slot ~= nil then
|
||||
slots[i] = slot.name
|
||||
end
|
||||
end
|
||||
if next(slots) then
|
||||
set_data(dataset, player.name, slots)
|
||||
player.print('Your personal logistics has been saved.', Color.success)
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
commands.add_command(
|
||||
'remove-logistics',
|
||||
'Removes your personal logistics preset from the datastore.',
|
||||
function()
|
||||
local player = game.player
|
||||
if not player or not player.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local dataset = logistics_dataset
|
||||
|
||||
local game_has_mods = is_game_modded()
|
||||
if game_has_mods then
|
||||
dataset = logistics_dataset_modded
|
||||
end
|
||||
|
||||
set_data(dataset, player.name, nil)
|
||||
player.print('Your personal logistics has been removed.', Color.success)
|
||||
end
|
||||
)
|
||||
|
||||
Event.add(
|
||||
defines.events.on_player_joined_game,
|
||||
function(event)
|
||||
local player = game.get_player(event.player_index)
|
||||
if not player or not player.valid then
|
||||
return
|
||||
end
|
||||
|
||||
Public.fetch(player.name)
|
||||
end
|
||||
)
|
||||
|
||||
return Public
|
@ -4,11 +4,23 @@ local Server = require 'utils.server'
|
||||
local Event = require 'utils.event'
|
||||
|
||||
local quickbar_dataset = 'quickbar'
|
||||
local quickbar_dataset_modded = 'quickbar_modded'
|
||||
local set_data = Server.set_data
|
||||
local try_get_data = Server.try_get_data
|
||||
|
||||
local Public = {}
|
||||
|
||||
local function is_game_modded()
|
||||
local i = 0
|
||||
for k, _ in pairs(game.active_mods) do
|
||||
i = i + 1
|
||||
if i > 1 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local fetch =
|
||||
Token.register(
|
||||
function(data)
|
||||
@ -32,6 +44,7 @@ local fetch =
|
||||
-- @param data_set player token
|
||||
function Public.fetch(key)
|
||||
local secs = Server.get_current_time()
|
||||
local dataset = quickbar_dataset
|
||||
if not secs then
|
||||
local player = game.players[key]
|
||||
if not player or not player.valid then
|
||||
@ -39,7 +52,12 @@ function Public.fetch(key)
|
||||
end
|
||||
return
|
||||
else
|
||||
try_get_data(quickbar_dataset, key, fetch)
|
||||
local game_has_mods = is_game_modded()
|
||||
if game_has_mods then
|
||||
dataset = quickbar_dataset_modded
|
||||
end
|
||||
|
||||
try_get_data(dataset, key, fetch)
|
||||
end
|
||||
end
|
||||
|
||||
@ -57,6 +75,13 @@ commands.add_command(
|
||||
return
|
||||
end
|
||||
|
||||
local dataset = quickbar_dataset
|
||||
|
||||
local game_has_mods = is_game_modded()
|
||||
if game_has_mods then
|
||||
dataset = quickbar_dataset_modded
|
||||
end
|
||||
|
||||
local slots = {}
|
||||
|
||||
for i = 1, 100 do
|
||||
@ -66,7 +91,7 @@ commands.add_command(
|
||||
end
|
||||
end
|
||||
if next(slots) then
|
||||
set_data(quickbar_dataset, player.name, slots)
|
||||
set_data(dataset, player.name, slots)
|
||||
player.print('Your quickbar has been saved.', Color.success)
|
||||
end
|
||||
end
|
||||
@ -81,7 +106,14 @@ commands.add_command(
|
||||
return
|
||||
end
|
||||
|
||||
set_data(quickbar_dataset, player.name, nil)
|
||||
local dataset = quickbar_dataset
|
||||
|
||||
local game_has_mods = is_game_modded()
|
||||
if game_has_mods then
|
||||
dataset = quickbar_dataset_modded
|
||||
end
|
||||
|
||||
set_data(dataset, player.name, nil)
|
||||
player.print('Your quickbar has been removed.', Color.success)
|
||||
end
|
||||
)
|
||||
|
@ -6,14 +6,16 @@ local Color = require 'utils.color_presets'
|
||||
local ups_label = GUI.uid_name()
|
||||
|
||||
local function validate_player(player)
|
||||
if not player or not player.valid then
|
||||
if not player then
|
||||
return false
|
||||
end
|
||||
if not player.valid then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function set_location(event)
|
||||
local player = game.get_player(event.player_index)
|
||||
local function set_location(player)
|
||||
local gui = player.gui
|
||||
local label = gui.screen[ups_label]
|
||||
if not label or not label.valid then
|
||||
@ -24,22 +26,21 @@ local function set_location(event)
|
||||
label.location = {x = res.width - 423 * uis, y = 30 * uis}
|
||||
end
|
||||
|
||||
local function create_label(player, label)
|
||||
local function create_label(player)
|
||||
local ups = Server.get_ups()
|
||||
local sUPS = 'SUPS = ' .. ups
|
||||
if not label or not label.valid then
|
||||
label =
|
||||
player.gui.screen.add(
|
||||
{
|
||||
type = 'label',
|
||||
name = ups_label,
|
||||
caption = sUPS
|
||||
}
|
||||
)
|
||||
local style = label.style
|
||||
style.font = 'default-game'
|
||||
return label
|
||||
end
|
||||
|
||||
local label =
|
||||
player.gui.screen.add(
|
||||
{
|
||||
type = 'label',
|
||||
name = ups_label,
|
||||
caption = sUPS
|
||||
}
|
||||
)
|
||||
local style = label.style
|
||||
style.font = 'default-game'
|
||||
return label
|
||||
end
|
||||
|
||||
Event.add(
|
||||
@ -50,9 +51,9 @@ Event.add(
|
||||
local label = player.gui.screen[ups_label]
|
||||
|
||||
if not label or not label.valid then
|
||||
label = create_label(player, label)
|
||||
label = create_label(player)
|
||||
end
|
||||
set_location(event)
|
||||
set_location(player)
|
||||
label.visible = false
|
||||
end
|
||||
)
|
||||
@ -64,10 +65,12 @@ Event.on_nth_tick(
|
||||
local ups = Server.get_ups()
|
||||
local caption = 'SUPS = ' .. ups
|
||||
local players = game.connected_players
|
||||
for _, player in pairs(players) do
|
||||
for i = 1, #players do
|
||||
local player = players[i]
|
||||
local label = player.gui.screen[ups_label]
|
||||
if label and label.valid then
|
||||
label.caption = caption
|
||||
set_location(player)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -88,17 +91,33 @@ commands.add_command(
|
||||
|
||||
local label = player.gui.screen[ups_label]
|
||||
if not label or not label.valid then
|
||||
label = create_label(player, label)
|
||||
label = create_label(player)
|
||||
end
|
||||
|
||||
if label.visible then
|
||||
label.visible = false
|
||||
player.print('Removed Server-UPS label.', Color.warning)
|
||||
else
|
||||
label.visible = true
|
||||
set_location(player)
|
||||
player.print('Added Server-UPS label.', Color.success)
|
||||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
Event.add(defines.events.on_player_display_resolution_changed, set_location)
|
||||
Event.add(defines.events.on_player_display_scale_changed, set_location)
|
||||
Event.add(
|
||||
defines.events.on_player_display_resolution_changed,
|
||||
function(event)
|
||||
local player = game.get_player(event.player_index)
|
||||
set_location(player)
|
||||
end
|
||||
)
|
||||
|
||||
Event.add(
|
||||
defines.events.on_player_display_scale_changed,
|
||||
function(event)
|
||||
local player = game.get_player(event.player_index)
|
||||
set_location(player)
|
||||
end
|
||||
)
|
||||
|
@ -89,7 +89,8 @@ Gui.on_click(
|
||||
input_text_box.text = concat {'global.tokens[', token_id, ']'}
|
||||
input_text_box.style.font_color = Color.black
|
||||
|
||||
local content = dump(Token.get_global(token_id)) or 'nil'
|
||||
local id = Token.get_global(token_id)
|
||||
local content = dump(id) or 'Could not load data.'
|
||||
right_panel.text = content
|
||||
end
|
||||
)
|
||||
|
@ -18,6 +18,17 @@ Global.register(
|
||||
end
|
||||
)
|
||||
|
||||
local function is_game_modded()
|
||||
local i = 0
|
||||
for k, _ in pairs(game.active_mods) do
|
||||
i = i + 1
|
||||
if i > 1 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local util = require('util')
|
||||
local crash_site = require('crash-site')
|
||||
|
||||
@ -191,17 +202,14 @@ end
|
||||
Event.on_init(
|
||||
function()
|
||||
local i = 0
|
||||
for k, _ in pairs(game.active_mods) do
|
||||
i = i + 1
|
||||
if i > 1 then
|
||||
this.modded = true
|
||||
this.disable_crashsite = false
|
||||
this.created_items = created_items()
|
||||
this.respawn_items = respawn_items()
|
||||
this.crashed_ship_items = ship_items()
|
||||
this.crashed_debris_items = debris_items()
|
||||
return true
|
||||
end
|
||||
local game_has_mods = is_game_modded()
|
||||
if game_has_mods then
|
||||
this.modded = true
|
||||
this.disable_crashsite = false
|
||||
this.created_items = created_items()
|
||||
this.respawn_items = respawn_items()
|
||||
this.crashed_ship_items = ship_items()
|
||||
this.crashed_debris_items = debris_items()
|
||||
end
|
||||
end
|
||||
)
|
||||
|
@ -1,8 +1,8 @@
|
||||
local inspect ={
|
||||
_VERSION = 'inspect.lua 3.1.0',
|
||||
_URL = 'http://github.com/kikito/inspect.lua',
|
||||
_DESCRIPTION = 'human-readable representations of tables',
|
||||
_LICENSE = [[
|
||||
local inspect = {
|
||||
_VERSION = 'inspect.lua 3.1.0',
|
||||
_URL = 'http://github.com/kikito/inspect.lua',
|
||||
_DESCRIPTION = 'human-readable representations of tables',
|
||||
_LICENSE = [[
|
||||
MIT LICENSE
|
||||
|
||||
Copyright (c) 2013 Enrique García Cota
|
||||
@ -30,313 +30,363 @@ local inspect ={
|
||||
|
||||
local tostring = tostring
|
||||
|
||||
inspect.KEY = setmetatable({}, {__tostring = function() return 'inspect.KEY' end})
|
||||
inspect.METATABLE = setmetatable({}, {__tostring = function() return 'inspect.METATABLE' end})
|
||||
inspect.KEY =
|
||||
setmetatable(
|
||||
{},
|
||||
{__tostring = function()
|
||||
return 'inspect.KEY'
|
||||
end}
|
||||
)
|
||||
inspect.METATABLE =
|
||||
setmetatable(
|
||||
{},
|
||||
{__tostring = function()
|
||||
return 'inspect.METATABLE'
|
||||
end}
|
||||
)
|
||||
|
||||
-- Apostrophizes the string if it has quotes, but not aphostrophes
|
||||
-- Otherwise, it returns a regular quoted string
|
||||
local function smartQuote(str)
|
||||
if str:match('"') and not str:match("'") then
|
||||
return "'" .. str .. "'"
|
||||
end
|
||||
return '"' .. str:gsub('"', '\\"') .. '"'
|
||||
if str:match('"') and not str:match("'") then
|
||||
return "'" .. str .. "'"
|
||||
end
|
||||
return '"' .. str:gsub('"', '\\"') .. '"'
|
||||
end
|
||||
|
||||
-- \a => '\\a', \0 => '\\0', 31 => '\31'
|
||||
local shortControlCharEscapes = {
|
||||
["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n",
|
||||
["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v"
|
||||
['\a'] = '\\a',
|
||||
['\b'] = '\\b',
|
||||
['\f'] = '\\f',
|
||||
['\n'] = '\\n',
|
||||
['\r'] = '\\r',
|
||||
['\t'] = '\\t',
|
||||
['\v'] = '\\v'
|
||||
}
|
||||
local longControlCharEscapes = {} -- \a => nil, \0 => \000, 31 => \031
|
||||
for i=0, 31 do
|
||||
local ch = string.char(i)
|
||||
if not shortControlCharEscapes[ch] then
|
||||
shortControlCharEscapes[ch] = "\\"..i
|
||||
longControlCharEscapes[ch] = string.format("\\%03d", i)
|
||||
end
|
||||
for i = 0, 31 do
|
||||
local ch = string.char(i)
|
||||
if not shortControlCharEscapes[ch] then
|
||||
shortControlCharEscapes[ch] = '\\' .. i
|
||||
longControlCharEscapes[ch] = string.format('\\%03d', i)
|
||||
end
|
||||
end
|
||||
|
||||
local function escape(str)
|
||||
return (str:gsub("\\", "\\\\")
|
||||
:gsub("(%c)%f[0-9]", longControlCharEscapes)
|
||||
:gsub("%c", shortControlCharEscapes))
|
||||
return (str:gsub('\\', '\\\\'):gsub('(%c)%f[0-9]', longControlCharEscapes):gsub('%c', shortControlCharEscapes))
|
||||
end
|
||||
|
||||
local function isIdentifier(str)
|
||||
return type(str) == 'string' and str:match( "^[_%a][_%a%d]*$" )
|
||||
return type(str) == 'string' and str:match('^[_%a][_%a%d]*$')
|
||||
end
|
||||
|
||||
local function isSequenceKey(k, sequenceLength)
|
||||
return type(k) == 'number'
|
||||
and 1 <= k
|
||||
and k <= sequenceLength
|
||||
and math.floor(k) == k
|
||||
return type(k) == 'number' and 1 <= k and k <= sequenceLength and math.floor(k) == k
|
||||
end
|
||||
|
||||
local defaultTypeOrders = {
|
||||
['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4,
|
||||
['function'] = 5, ['userdata'] = 6, ['thread'] = 7
|
||||
['number'] = 1,
|
||||
['boolean'] = 2,
|
||||
['string'] = 3,
|
||||
['table'] = 4,
|
||||
['function'] = 5,
|
||||
['userdata'] = 6,
|
||||
['thread'] = 7
|
||||
}
|
||||
|
||||
local function sortKeys(a, b)
|
||||
local ta, tb = type(a), type(b)
|
||||
local ta, tb = type(a), type(b)
|
||||
|
||||
-- strings and numbers are sorted numerically/alphabetically
|
||||
if ta == tb and (ta == 'string' or ta == 'number') then return a < b end
|
||||
-- strings and numbers are sorted numerically/alphabetically
|
||||
if ta == tb and (ta == 'string' or ta == 'number') then
|
||||
return a < b
|
||||
end
|
||||
|
||||
local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb]
|
||||
-- Two default types are compared according to the defaultTypeOrders table
|
||||
if dta and dtb then return defaultTypeOrders[ta] < defaultTypeOrders[tb]
|
||||
elseif dta then return true -- default types before custom ones
|
||||
elseif dtb then return false -- custom types after default ones
|
||||
end
|
||||
local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb]
|
||||
-- Two default types are compared according to the defaultTypeOrders table
|
||||
if dta and dtb then
|
||||
return defaultTypeOrders[ta] < defaultTypeOrders[tb]
|
||||
elseif dta then
|
||||
return true -- default types before custom ones
|
||||
elseif dtb then
|
||||
return false -- custom types after default ones
|
||||
end
|
||||
|
||||
-- custom types are sorted out alphabetically
|
||||
return ta < tb
|
||||
-- custom types are sorted out alphabetically
|
||||
return ta < tb
|
||||
end
|
||||
|
||||
-- For implementation reasons, the behavior of rawlen & # is "undefined" when
|
||||
-- tables aren't pure sequences. So we implement our own # operator.
|
||||
local function getSequenceLength(t)
|
||||
local len = 1
|
||||
local v = rawget(t,len)
|
||||
while v ~= nil do
|
||||
len = len + 1
|
||||
v = rawget(t,len)
|
||||
end
|
||||
return len - 1
|
||||
local len = 1
|
||||
local v = rawget(t, len)
|
||||
while v ~= nil do
|
||||
len = len + 1
|
||||
v = rawget(t, len)
|
||||
end
|
||||
return len - 1
|
||||
end
|
||||
|
||||
local function getNonSequentialKeys(t)
|
||||
local keys = {}
|
||||
local sequenceLength = getSequenceLength(t)
|
||||
for k,_ in pairs(t) do
|
||||
if not isSequenceKey(k, sequenceLength) then table.insert(keys, k) end
|
||||
end
|
||||
table.sort(keys, sortKeys)
|
||||
return keys, sequenceLength
|
||||
local keys = {}
|
||||
local sequenceLength = getSequenceLength(t)
|
||||
for k, _ in pairs(t) do
|
||||
if not isSequenceKey(k, sequenceLength) then
|
||||
table.insert(keys, k)
|
||||
end
|
||||
end
|
||||
table.sort(keys, sortKeys)
|
||||
return keys, sequenceLength
|
||||
end
|
||||
|
||||
local function getToStringResultSafely(t, mt)
|
||||
local __tostring = type(mt) == 'table' and rawget(mt, '__tostring')
|
||||
local str, ok
|
||||
if type(__tostring) == 'function' then
|
||||
ok, str = pcall(__tostring, t)
|
||||
str = ok and str or 'error: ' .. tostring(str)
|
||||
end
|
||||
if type(str) == 'string' and #str > 0 then return str end
|
||||
local __tostring = type(mt) == 'table' and rawget(mt, '__tostring')
|
||||
local str, ok
|
||||
if type(__tostring) == 'function' then
|
||||
ok, str = pcall(__tostring, t)
|
||||
str = ok and str or 'error: ' .. tostring(str)
|
||||
end
|
||||
if type(str) == 'string' and #str > 0 then
|
||||
return str
|
||||
end
|
||||
end
|
||||
|
||||
local function countTableAppearances(t, tableAppearances)
|
||||
tableAppearances = tableAppearances or {}
|
||||
tableAppearances = tableAppearances or {}
|
||||
|
||||
if type(t) == 'table' then
|
||||
if not tableAppearances[t] then
|
||||
tableAppearances[t] = 1
|
||||
for k,v in pairs(t) do
|
||||
countTableAppearances(k, tableAppearances)
|
||||
countTableAppearances(v, tableAppearances)
|
||||
end
|
||||
countTableAppearances(getmetatable(t), tableAppearances)
|
||||
else
|
||||
tableAppearances[t] = tableAppearances[t] + 1
|
||||
if type(t) == 'table' then
|
||||
if not tableAppearances[t] then
|
||||
tableAppearances[t] = 1
|
||||
for k, v in pairs(t) do
|
||||
countTableAppearances(k, tableAppearances)
|
||||
countTableAppearances(v, tableAppearances)
|
||||
end
|
||||
countTableAppearances(getmetatable(t), tableAppearances)
|
||||
else
|
||||
tableAppearances[t] = tableAppearances[t] + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return tableAppearances
|
||||
return tableAppearances
|
||||
end
|
||||
|
||||
local copySequence = function(s)
|
||||
local copy, len = {}, #s
|
||||
for i=1, len do copy[i] = s[i] end
|
||||
return copy, len
|
||||
local copy, len = {}, #s
|
||||
for i = 1, len do
|
||||
copy[i] = s[i]
|
||||
end
|
||||
return copy, len
|
||||
end
|
||||
|
||||
local function makePath(path, ...)
|
||||
local keys = {...}
|
||||
local newPath, len = copySequence(path)
|
||||
for i=1, #keys do
|
||||
newPath[len + i] = keys[i]
|
||||
end
|
||||
return newPath
|
||||
local keys = {...}
|
||||
local newPath, len = copySequence(path)
|
||||
for i = 1, #keys do
|
||||
newPath[len + i] = keys[i]
|
||||
end
|
||||
return newPath
|
||||
end
|
||||
|
||||
local function processRecursive(process, item, path, visited)
|
||||
|
||||
if item == nil then return nil end
|
||||
if visited[item] then return visited[item] end
|
||||
if item == nil then
|
||||
return nil
|
||||
end
|
||||
if visited[item] then
|
||||
return visited[item]
|
||||
end
|
||||
|
||||
local processed = process(item, path)
|
||||
if type(processed) == 'table' then
|
||||
local processedCopy = {}
|
||||
visited[item] = processedCopy
|
||||
local processedKey
|
||||
local processedCopy = {}
|
||||
visited[item] = processedCopy
|
||||
local processedKey
|
||||
|
||||
for k,v in pairs(processed) do
|
||||
processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited)
|
||||
if processedKey ~= nil then
|
||||
processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited)
|
||||
for k, v in pairs(processed) do
|
||||
processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited)
|
||||
if processedKey ~= nil then
|
||||
processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)
|
||||
setmetatable(processedCopy, mt)
|
||||
processed = processedCopy
|
||||
local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)
|
||||
setmetatable(processedCopy, mt)
|
||||
processed = processedCopy
|
||||
end
|
||||
return processed
|
||||
end
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
local Inspector = {}
|
||||
local Inspector_mt = {__index = Inspector}
|
||||
|
||||
function Inspector:puts(...)
|
||||
local args = {...}
|
||||
local buffer = self.buffer
|
||||
local len = #buffer
|
||||
for i=1, #args do
|
||||
len = len + 1
|
||||
buffer[len] = args[i]
|
||||
end
|
||||
local args = {...}
|
||||
local buffer = self.buffer
|
||||
local len = #buffer
|
||||
for i = 1, #args do
|
||||
len = len + 1
|
||||
buffer[len] = args[i]
|
||||
end
|
||||
end
|
||||
|
||||
function Inspector:down(f)
|
||||
self.level = self.level + 1
|
||||
f()
|
||||
self.level = self.level - 1
|
||||
self.level = self.level + 1
|
||||
f()
|
||||
self.level = self.level - 1
|
||||
end
|
||||
|
||||
function Inspector:tabify()
|
||||
self:puts(self.newline, string.rep(self.indent, self.level))
|
||||
self:puts(self.newline, string.rep(self.indent, self.level))
|
||||
end
|
||||
|
||||
function Inspector:alreadyVisited(v)
|
||||
return self.ids[v] ~= nil
|
||||
return self.ids[v] ~= nil
|
||||
end
|
||||
|
||||
function Inspector:getId(v)
|
||||
local id = self.ids[v]
|
||||
if not id then
|
||||
local tv = type(v)
|
||||
id = (self.maxIds[tv] or 0) + 1
|
||||
self.maxIds[tv] = id
|
||||
self.ids[v] = id
|
||||
end
|
||||
return tostring(id)
|
||||
local id = self.ids[v]
|
||||
if not id then
|
||||
local tv = type(v)
|
||||
id = (self.maxIds[tv] or 0) + 1
|
||||
self.maxIds[tv] = id
|
||||
self.ids[v] = id
|
||||
end
|
||||
return tostring(id)
|
||||
end
|
||||
|
||||
function Inspector:putKey(k)
|
||||
if isIdentifier(k) then return self:puts(k) end
|
||||
self:puts("[")
|
||||
self:putValue(k)
|
||||
self:puts("]")
|
||||
if isIdentifier(k) then
|
||||
return self:puts(k)
|
||||
end
|
||||
self:puts('[')
|
||||
self:putValue(k)
|
||||
self:puts(']')
|
||||
end
|
||||
|
||||
function Inspector:putTable(t)
|
||||
if t == inspect.KEY or t == inspect.METATABLE then
|
||||
self:puts(tostring(t))
|
||||
elseif self:alreadyVisited(t) then
|
||||
self:puts('<table ', self:getId(t), '>')
|
||||
elseif self.level >= self.depth then
|
||||
self:puts('{...}')
|
||||
else
|
||||
if self.tableAppearances[t] > 1 then self:puts('<', self:getId(t), '>') end
|
||||
if t == inspect.KEY or t == inspect.METATABLE then
|
||||
self:puts(tostring(t))
|
||||
elseif self:alreadyVisited(t) then
|
||||
self:puts('<table ', self:getId(t), '>')
|
||||
elseif self.level >= self.depth then
|
||||
self:puts('{...}')
|
||||
else
|
||||
if self.tableAppearances[t] > 1 then
|
||||
self:puts('<', self:getId(t), '>')
|
||||
end
|
||||
|
||||
local nonSequentialKeys, sequenceLength = getNonSequentialKeys(t)
|
||||
local mt = getmetatable(t)
|
||||
local toStringResult = getToStringResultSafely(t, mt)
|
||||
local nonSequentialKeys, sequenceLength = getNonSequentialKeys(t)
|
||||
local mt = getmetatable(t)
|
||||
local toStringResult = getToStringResultSafely(t, mt)
|
||||
|
||||
self:puts('{')
|
||||
self:down(function()
|
||||
if toStringResult then
|
||||
self:puts(' -- ', escape(toStringResult))
|
||||
if sequenceLength >= 1 then self:tabify() end
|
||||
end
|
||||
self:puts('{')
|
||||
self:down(
|
||||
function()
|
||||
if toStringResult then
|
||||
self:puts(' -- ', escape(toStringResult))
|
||||
if sequenceLength >= 1 then
|
||||
self:tabify()
|
||||
end
|
||||
end
|
||||
|
||||
local count = 0
|
||||
for i=1, sequenceLength do
|
||||
if count > 0 then self:puts(',') end
|
||||
self:puts(' ')
|
||||
self:putValue(t[i])
|
||||
count = count + 1
|
||||
end
|
||||
local count = 0
|
||||
for i = 1, sequenceLength do
|
||||
if count > 0 then
|
||||
self:puts(',')
|
||||
end
|
||||
self:puts(' ')
|
||||
self:putValue(t[i])
|
||||
count = count + 1
|
||||
end
|
||||
|
||||
for _,k in ipairs(nonSequentialKeys) do
|
||||
if count > 0 then self:puts(',') end
|
||||
self:tabify()
|
||||
self:putKey(k)
|
||||
self:puts(' = ')
|
||||
self:putValue(t[k])
|
||||
count = count + 1
|
||||
end
|
||||
for _, k in ipairs(nonSequentialKeys) do
|
||||
if count > 0 then
|
||||
self:puts(',')
|
||||
end
|
||||
self:tabify()
|
||||
self:putKey(k)
|
||||
self:puts(' = ')
|
||||
self:putValue(t[k])
|
||||
count = count + 1
|
||||
end
|
||||
|
||||
if mt then
|
||||
if count > 0 then self:puts(',') end
|
||||
self:tabify()
|
||||
self:puts('<metatable> = ')
|
||||
self:putValue(mt)
|
||||
end
|
||||
end)
|
||||
if mt then
|
||||
if count > 0 then
|
||||
self:puts(',')
|
||||
end
|
||||
self:tabify()
|
||||
self:puts('<metatable> = ')
|
||||
self:putValue(mt)
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
if #nonSequentialKeys > 0 or mt then -- result is multi-lined. Justify closing }
|
||||
self:tabify()
|
||||
elseif sequenceLength > 0 then -- array tables have one extra space before closing }
|
||||
self:puts(' ')
|
||||
if #nonSequentialKeys > 0 or mt then -- result is multi-lined. Justify closing }
|
||||
self:tabify()
|
||||
elseif sequenceLength > 0 then -- array tables have one extra space before closing }
|
||||
self:puts(' ')
|
||||
end
|
||||
|
||||
self:puts('}')
|
||||
end
|
||||
|
||||
self:puts('}')
|
||||
end
|
||||
end
|
||||
|
||||
function Inspector:putValue(v)
|
||||
local tv = type(v)
|
||||
local tv = type(v)
|
||||
|
||||
if tv == 'string' then
|
||||
self:puts(smartQuote(escape(v)))
|
||||
elseif tv == 'number' or tv == 'boolean' or tv == 'nil' or
|
||||
tv == 'cdata' or tv == 'ctype' then
|
||||
self:puts(tostring(v))
|
||||
elseif tv == 'table' then
|
||||
self:putTable(v)
|
||||
else
|
||||
self:puts('<',tv,' ',self:getId(v),'>')
|
||||
end
|
||||
if tv == 'string' then
|
||||
self:puts(smartQuote(escape(v)))
|
||||
elseif tv == 'number' or tv == 'boolean' or tv == 'nil' or tv == 'cdata' or tv == 'ctype' then
|
||||
self:puts(tostring(v))
|
||||
elseif tv == 'table' then
|
||||
self:putTable(v)
|
||||
else
|
||||
self:puts('<', tv, ' ', self:getId(v), '>')
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function inspect.inspect(root, options)
|
||||
options = options or {}
|
||||
options = options or {}
|
||||
|
||||
local depth = options.depth or math.huge
|
||||
local newline = options.newline or '\n'
|
||||
local indent = options.indent or ' '
|
||||
local process = options.process
|
||||
local depth = options.depth or math.huge
|
||||
local newline = options.newline or '\n'
|
||||
local indent = options.indent or ' '
|
||||
local process = options.process
|
||||
|
||||
if process then
|
||||
root = processRecursive(process, root, {}, {})
|
||||
end
|
||||
if process then
|
||||
root = processRecursive(process, root, {}, {})
|
||||
end
|
||||
|
||||
local inspector = setmetatable({
|
||||
depth = depth,
|
||||
level = 0,
|
||||
buffer = {},
|
||||
ids = {},
|
||||
maxIds = {},
|
||||
newline = newline,
|
||||
indent = indent,
|
||||
tableAppearances = countTableAppearances(root)
|
||||
}, Inspector_mt)
|
||||
local inspector =
|
||||
setmetatable(
|
||||
{
|
||||
depth = depth,
|
||||
level = 0,
|
||||
buffer = {},
|
||||
ids = {},
|
||||
maxIds = {},
|
||||
newline = newline,
|
||||
indent = indent,
|
||||
tableAppearances = countTableAppearances(root)
|
||||
},
|
||||
Inspector_mt
|
||||
)
|
||||
|
||||
inspector:putValue(root)
|
||||
inspector:putValue(root)
|
||||
|
||||
return table.concat(inspector.buffer)
|
||||
return table.concat(inspector.buffer)
|
||||
end
|
||||
|
||||
setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end })
|
||||
setmetatable(
|
||||
inspect,
|
||||
{__call = function(_, ...)
|
||||
return inspect.inspect(...)
|
||||
end}
|
||||
)
|
||||
|
||||
return inspect
|
||||
|
||||
|
112
utils/stats.lua
Normal file
112
utils/stats.lua
Normal file
@ -0,0 +1,112 @@
|
||||
local Public = {}
|
||||
|
||||
-- Get the mean value of a table
|
||||
function Public.mean(t)
|
||||
local sum = 0
|
||||
local count = 0
|
||||
|
||||
for k, v in pairs(t) do
|
||||
if type(v) == 'number' then
|
||||
sum = sum + v
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
|
||||
return (sum / count)
|
||||
end
|
||||
|
||||
-- Get the mode of a table. Returns a table of values.
|
||||
-- Works on anything (not just numbers).
|
||||
function Public.mode(t)
|
||||
local counts = {}
|
||||
|
||||
for k, v in pairs(t) do
|
||||
if counts[v] == nil then
|
||||
counts[v] = 1
|
||||
else
|
||||
counts[v] = counts[v] + 1
|
||||
end
|
||||
end
|
||||
|
||||
local biggestCount = 0
|
||||
|
||||
for k, v in pairs(counts) do
|
||||
if v > biggestCount then
|
||||
biggestCount = v
|
||||
end
|
||||
end
|
||||
|
||||
local temp = {}
|
||||
|
||||
for k, v in pairs(counts) do
|
||||
if v == biggestCount then
|
||||
table.insert(temp, k)
|
||||
end
|
||||
end
|
||||
|
||||
return temp
|
||||
end
|
||||
|
||||
-- Get the median of a table.
|
||||
function Public.median(t)
|
||||
local temp = {}
|
||||
|
||||
-- deep copy table so that when we sort it, the original is unchanged
|
||||
-- also weed out any non numbers
|
||||
for k, v in pairs(t) do
|
||||
if type(v) == 'number' then
|
||||
table.insert(temp, v)
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(temp)
|
||||
|
||||
-- If we have an even number of table elements or odd.
|
||||
if math.fmod(#temp, 2) == 0 then
|
||||
-- return mean value of middle two elements
|
||||
return (temp[#temp / 2] + temp[(#temp / 2) + 1]) / 2
|
||||
else
|
||||
-- return middle element
|
||||
return temp[math.ceil(#temp / 2)]
|
||||
end
|
||||
end
|
||||
|
||||
-- Get the standard deviation of a table
|
||||
function Public.standardDeviation(t)
|
||||
local m
|
||||
local vm
|
||||
local sum = 0
|
||||
local count = 0
|
||||
local result
|
||||
|
||||
m = Public.mean(t)
|
||||
|
||||
for k, v in pairs(t) do
|
||||
if type(v) == 'number' then
|
||||
vm = v - m
|
||||
sum = sum + (vm * vm)
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
|
||||
result = math.sqrt(sum / (count - 1))
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
-- Get the max and min for a table
|
||||
function Public.maxmin(t)
|
||||
local max = -math.huge
|
||||
local min = math.huge
|
||||
|
||||
for k, v in pairs(t) do
|
||||
if type(v) == 'number' then
|
||||
max = math.max(max, v)
|
||||
min = math.min(min, v)
|
||||
end
|
||||
end
|
||||
|
||||
return max, min
|
||||
end
|
||||
|
||||
return Public
|
@ -1,4 +1,5 @@
|
||||
--luacheck: globals table
|
||||
local Stats = require 'utils.stats'
|
||||
local random = math.random
|
||||
local floor = math.floor
|
||||
local remove = table.remove
|
||||
@ -276,4 +277,9 @@ table.merge = util.merge
|
||||
-- @return <boolean>
|
||||
table.equals = table.compare
|
||||
|
||||
--- Gets the median value out of a table.
|
||||
-- @param tbl1 <table>
|
||||
-- @return <int>
|
||||
table.mean = Stats.mean
|
||||
|
||||
return table
|
||||
|
Loading…
Reference in New Issue
Block a user