mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-26 03:52:22 +02:00
First Commit
This commit is contained in:
commit
7b1358f154
51
control.lua
Normal file
51
control.lua
Normal file
@ -0,0 +1,51 @@
|
||||
require "utils.utils"
|
||||
require "session_tracker"
|
||||
require "group"
|
||||
require "player_list"
|
||||
require "poll"
|
||||
require "score"
|
||||
|
||||
---- enable maps here ----
|
||||
|
||||
require "maps.cave_miner"
|
||||
|
||||
-----------------------------
|
||||
|
||||
local Event = require 'utils.event'
|
||||
|
||||
local function player_created(event)
|
||||
local player = game.players[event.player_index]
|
||||
player.gui.top.style = 'slot_table_spacing_horizontal_flow'
|
||||
player.gui.left.style = 'slot_table_spacing_vertical_flow'
|
||||
|
||||
player.print("Join the comfy discord >> comfyplay.net", {r = 110, g = 0, b = 220})
|
||||
end
|
||||
|
||||
function spaghetti()
|
||||
game.forces["player"].technologies["logistic-system"].enabled = false
|
||||
game.forces["player"].technologies["construction-robotics"].enabled = false
|
||||
game.forces["player"].technologies["logistic-robotics"].enabled = false
|
||||
game.forces["player"].technologies["robotics"].enabled = false
|
||||
game.forces["player"].technologies["personal-roboport-equipment"].enabled = false
|
||||
game.forces["player"].technologies["personal-roboport-equipment-2"].enabled = false
|
||||
game.forces["player"].technologies["character-logistic-trash-slots-1"].enabled = false
|
||||
game.forces["player"].technologies["character-logistic-trash-slots-2"].enabled = false
|
||||
game.forces["player"].technologies["auto-character-logistic-trash-slots"].enabled = false
|
||||
game.forces["player"].technologies["worker-robots-storage-1"].enabled = false
|
||||
game.forces["player"].technologies["worker-robots-storage-2"].enabled = false
|
||||
game.forces["player"].technologies["worker-robots-storage-3"].enabled = false
|
||||
game.forces["player"].technologies["character-logistic-slots-1"].enabled = false
|
||||
game.forces["player"].technologies["character-logistic-slots-2"].enabled = false
|
||||
game.forces["player"].technologies["character-logistic-slots-3"].enabled = false
|
||||
game.forces["player"].technologies["character-logistic-slots-4"].enabled = false
|
||||
game.forces["player"].technologies["character-logistic-slots-5"].enabled = false
|
||||
game.forces["player"].technologies["character-logistic-slots-6"].enabled = false
|
||||
game.forces["player"].technologies["worker-robots-speed-1"].enabled = false
|
||||
game.forces["player"].technologies["worker-robots-speed-2"].enabled = false
|
||||
game.forces["player"].technologies["worker-robots-speed-3"].enabled = false
|
||||
game.forces["player"].technologies["worker-robots-speed-4"].enabled = false
|
||||
game.forces["player"].technologies["worker-robots-speed-5"].enabled = false
|
||||
game.forces["player"].technologies["worker-robots-speed-6"].enabled = false
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_player_created, player_created)
|
260
group.lua
Normal file
260
group.lua
Normal file
@ -0,0 +1,260 @@
|
||||
-- this script adds a group button to create groups for your players --
|
||||
|
||||
local Event = require 'utils.event'
|
||||
|
||||
local function build_group_gui(player)
|
||||
local group_name_width = 160
|
||||
local description_width = 220
|
||||
local members_width = 90
|
||||
local member_columns = 3
|
||||
local actions_width = 60
|
||||
local total_height = 350
|
||||
|
||||
if not player.gui.top["group_button"] then
|
||||
local b = player.gui.top.add({type = "button", name = "group_button", caption = global.player_group[player.name]})
|
||||
b.style.font_color = {r = 0.77, g = 0.77, b = 0.77}
|
||||
b.style.font = "default-bold"
|
||||
b.style.minimal_height = 38
|
||||
b.style.minimal_width = 38
|
||||
b.style.top_padding = 2
|
||||
b.style.left_padding = 4
|
||||
b.style.right_padding = 4
|
||||
b.style.bottom_padding = 2
|
||||
end
|
||||
|
||||
if player.online_time < 1 then return end
|
||||
|
||||
if player.gui.left["group_frame"] then player.gui.left["group_frame"].destroy() end
|
||||
local frame = player.gui.left.add({type = "frame", name = "group_frame", direction = "vertical"})
|
||||
frame.style.minimal_height = total_height
|
||||
|
||||
local t = frame.add({type = "table", column_count = 5})
|
||||
local headings = {{"Title", group_name_width}, {"Description", description_width}, {"Members", members_width * member_columns}, {"", actions_width*2 - 30}}
|
||||
for _, h in pairs (headings) do
|
||||
local l = t.add({ type = "label", caption = h[1]})
|
||||
l.style.font_color = { r=0.98, g=0.66, b=0.22}
|
||||
l.style.font = "default-listbox"
|
||||
l.style.top_padding = 6
|
||||
l.style.minimal_height = 40
|
||||
l.style.minimal_width = h[2]
|
||||
l.style.maximal_width = h[2]
|
||||
end
|
||||
local b = t.add {type = "button", caption = "X", name = "close_group_frame", align = "right"}
|
||||
b.style.font = "default"
|
||||
b.style.minimal_height = 30
|
||||
b.style.minimal_width = 30
|
||||
b.style.top_padding = 2
|
||||
b.style.left_padding = 4
|
||||
b.style.right_padding = 4
|
||||
b.style.bottom_padding = 2
|
||||
|
||||
local scroll_pane = frame.add({ type = "scroll-pane", name = "scroll_pane", direction = "vertical", horizontal_scroll_policy = "never", vertical_scroll_policy = "auto"})
|
||||
scroll_pane.style.maximal_height = total_height - 50
|
||||
scroll_pane.style.minimal_height = total_height - 50
|
||||
|
||||
local t = scroll_pane.add({type = "table", name = "groups_table", column_count = 4})
|
||||
for _, h in pairs (headings) do
|
||||
local l = t.add({ type = "label", caption = ""})
|
||||
l.style.minimal_width = h[2]
|
||||
l.style.maximal_width = h[2]
|
||||
end
|
||||
|
||||
for _, group in pairs (global.tag_groups) do
|
||||
|
||||
local l = t.add({ type = "label", caption = group.name})
|
||||
l.style.font = "default-bold"
|
||||
l.style.top_padding = 16
|
||||
l.style.bottom_padding = 16
|
||||
l.style.minimal_width = group_name_width
|
||||
l.style.maximal_width = group_name_width
|
||||
local color = game.players[group.founder].color
|
||||
color = {r = color.r * 0.6 + 0.4, g = color.g * 0.6 + 0.4, b = color.b * 0.6 + 0.4, a = 1}
|
||||
l.style.font_color = color
|
||||
l.style.single_line = false
|
||||
|
||||
local l = t.add({ type = "label", caption = group.description})
|
||||
l.style.top_padding = 16
|
||||
l.style.bottom_padding = 16
|
||||
l.style.minimal_width = description_width
|
||||
l.style.maximal_width = description_width
|
||||
l.style.font_color = {r = 0.90, g = 0.90, b = 0.90}
|
||||
l.style.single_line = false
|
||||
|
||||
local tt = t.add({ type = "table", column_count = member_columns})
|
||||
for _, p in pairs (game.connected_players) do
|
||||
if group.name == global.player_group[p.name] then
|
||||
local l = tt.add({ type = "label", caption = p.name})
|
||||
local color = {r = p.color.r * 0.6 + 0.4, g = p.color.g * 0.6 + 0.4, b = p.color.b * 0.6 + 0.4, a = 1}
|
||||
l.style.font_color = color
|
||||
--l.style.minimal_width = members_width
|
||||
l.style.maximal_width = members_width * 2
|
||||
end
|
||||
end
|
||||
|
||||
local tt = t.add({ type = "table", name = group.name, column_count = 2})
|
||||
if player.admin == true or group.founder == player.name then
|
||||
local b = tt.add({ type = "button", caption = "Delete"})
|
||||
b.style.font = "default-bold"
|
||||
b.style.minimal_width = actions_width
|
||||
b.style.maximal_width = actions_width
|
||||
else
|
||||
local l = tt.add({ type = "label", caption = ""})
|
||||
l.style.minimal_width = actions_width
|
||||
l.style.maximal_width = actions_width
|
||||
end
|
||||
if group.name ~= global.player_group[player.name] then
|
||||
local b = tt.add({ type = "button", caption = "Join"})
|
||||
b.style.font = "default-bold"
|
||||
b.style.minimal_width = actions_width
|
||||
b.style.maximal_width = actions_width
|
||||
else
|
||||
local b = tt.add({ type = "button", caption = "Leave"})
|
||||
b.style.font = "default-bold"
|
||||
b.style.minimal_width = actions_width
|
||||
b.style.maximal_width = actions_width
|
||||
end
|
||||
end
|
||||
|
||||
local frame2 = frame.add({type = "frame", name = "frame2"})
|
||||
local t = frame2.add({type = "table", name = "group_table", column_count = 3})
|
||||
local textfield = t.add({ type = "textfield", name = "new_group_name", text = "Name" })
|
||||
textfield.style.minimal_width = group_name_width
|
||||
local textfield = t.add({ type = "textfield", name = "new_group_description", text = "Description" })
|
||||
textfield.style.minimal_width = description_width + members_width * member_columns
|
||||
local b = t.add({type = "button", name = "create_new_group", caption = "Create"})
|
||||
b.style.minimal_width = actions_width*2 - 12
|
||||
b.style.font = "default-bold"
|
||||
|
||||
end
|
||||
|
||||
local function refresh_gui()
|
||||
for _, p in pairs(game.connected_players) do
|
||||
if p.gui.left["group_frame"] then
|
||||
|
||||
local frame = p.gui.left["group_frame"]
|
||||
local new_group_name = frame.frame2.group_table.new_group_name.text
|
||||
local new_group_description = frame.frame2.group_table.new_group_description.text
|
||||
|
||||
build_group_gui(p)
|
||||
|
||||
local frame = p.gui.left["group_frame"]
|
||||
frame.frame2.group_table.new_group_name.text = new_group_name
|
||||
frame.frame2.group_table.new_group_description.text = new_group_description
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_player_joined_game(event)
|
||||
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
if not global.player_group then global.player_group = {} end
|
||||
if not global.player_group[player.name] then global.player_group[player.name] = "[Group]" end
|
||||
|
||||
if not global.join_spam_protection then global.join_spam_protection = {} end
|
||||
if not global.join_spam_protection[player.name] then global.join_spam_protection[player.name] = game.tick end
|
||||
|
||||
|
||||
if not global.tag_groups then global.tag_groups = {} end
|
||||
|
||||
if player.online_time < 10 then
|
||||
build_group_gui(player)
|
||||
end
|
||||
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]
|
||||
local name = event.element.name
|
||||
local frame = player.gui.left["group_frame"]
|
||||
|
||||
if name == "create_new_group" then
|
||||
local new_group_name = frame.frame2.group_table.new_group_name.text
|
||||
local new_group_description = frame.frame2.group_table.new_group_description.text
|
||||
if new_group_name ~= "" and new_group_name ~= "Name" and new_group_description ~= "Description" then
|
||||
|
||||
if string.len(new_group_name) > 32 then
|
||||
player.print("Group name is too long. 32 characters maximum.", { r=0.90, g=0.0, b=0.0})
|
||||
return
|
||||
end
|
||||
|
||||
if string.len(new_group_description) > 128 then
|
||||
player.print("Description is too long. 128 characters maximum.", { r=0.90, g=0.0, b=0.0})
|
||||
return
|
||||
end
|
||||
|
||||
global.tag_groups[new_group_name] = {name = new_group_name, description = new_group_description, founder = player.name}
|
||||
local color = {r = player.color.r * 0.7 + 0.3, g = player.color.g * 0.7 + 0.3, b = player.color.b * 0.7 + 0.3, a = 1}
|
||||
game.print(player.name .. " has founded a new group!", color)
|
||||
game.print('>> ' .. new_group_name, { r=0.98, g=0.66, b=0.22})
|
||||
game.print(new_group_description, { r=0.85, g=0.85, b=0.85})
|
||||
|
||||
frame.frame2.group_table.new_group_name.text = "Name"
|
||||
frame.frame2.group_table.new_group_description.text = "Description"
|
||||
refresh_gui()
|
||||
end
|
||||
end
|
||||
|
||||
local p = event.element.parent
|
||||
if p then p = p.parent end
|
||||
if p then
|
||||
if p.name == "groups_table" then
|
||||
|
||||
if event.element.type == "button" and event.element.caption == "Join" then
|
||||
global.player_group[player.name] = event.element.parent.name
|
||||
local str = "[" .. event.element.parent.name
|
||||
str = str .. "]"
|
||||
player.gui.top["group_button"].caption = str
|
||||
player.tag = str
|
||||
if game.tick - global.join_spam_protection[player.name] > 600 then
|
||||
local color = {r = player.color.r * 0.7 + 0.3, g = player.color.g * 0.7 + 0.3, b = player.color.b * 0.7 + 0.3, a = 1}
|
||||
game.print(player.name .. ' has joined group "' .. event.element.parent.name .. '"', color)
|
||||
global.join_spam_protection[player.name] = game.tick
|
||||
end
|
||||
refresh_gui()
|
||||
end
|
||||
|
||||
if event.element.type == "button" and event.element.caption == "Delete" then
|
||||
for _, p in pairs(game.players) do
|
||||
if global.player_group[p.name] then
|
||||
if global.player_group[p.name] == event.element.parent.name then
|
||||
global.player_group[p.name] = "[Group]"
|
||||
p.gui.top["group_button"].caption = "[Group]"
|
||||
p.tag = ""
|
||||
end
|
||||
end
|
||||
end
|
||||
game.print(player.name .. ' deleted group "' .. event.element.parent.name .. '"')
|
||||
global.tag_groups[event.element.parent.name] = nil
|
||||
refresh_gui()
|
||||
end
|
||||
|
||||
if event.element.type == "button" and event.element.caption == "Leave" then
|
||||
global.player_group[player.name] = "[Group]"
|
||||
player.gui.top["group_button"].caption = "[Group]"
|
||||
player.tag = ""
|
||||
refresh_gui()
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
if name == "group_button" then
|
||||
if frame then
|
||||
frame.destroy()
|
||||
else
|
||||
build_group_gui(player)
|
||||
end
|
||||
end
|
||||
|
||||
if name == "close_group_frame" then
|
||||
frame.destroy()
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_gui_click, on_gui_click)
|
||||
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
|
1208
maps/cave_miner.lua
Normal file
1208
maps/cave_miner.lua
Normal file
File diff suppressed because it is too large
Load Diff
77
maps/cave_miner_changelog.txt
Normal file
77
maps/cave_miner_changelog.txt
Normal file
@ -0,0 +1,77 @@
|
||||
0.12
|
||||
reduced ore spill from rock destruction to reduce lagspike
|
||||
ore veins are usually bigger now and can appear earlier
|
||||
biters have a bit more damage against rocks
|
||||
market adjustments
|
||||
readded worms in main tunnels
|
||||
crude oil is allowed to spawn a bit closer
|
||||
access to the lakes and labyrinth areas should be a bit wider now
|
||||
damage against huge rocks has been increased
|
||||
biter spawn interval adjustments
|
||||
|
||||
0.11
|
||||
mining speed buff
|
||||
ore veins are more common
|
||||
|
||||
0.10
|
||||
difficulty adjustments
|
||||
spawn fixes
|
||||
|
||||
0.09
|
||||
ore veins are more common with more yield
|
||||
added info panel
|
||||
added more worms
|
||||
added extra bases in main mine shafts
|
||||
adjusted running speed modifier
|
||||
adjusted biter attack events
|
||||
modified chest loot tables
|
||||
mining trees now makes you earn fish
|
||||
|
||||
0.08
|
||||
rock "labyrinth" biome
|
||||
periodic biter attack events, the mines have become more dangerous
|
||||
custom spawn trees
|
||||
|
||||
0.07
|
||||
small chance that rocks might reveal an ore vein
|
||||
rocks now always drop stone
|
||||
players are now getting hungry
|
||||
|
||||
0.06
|
||||
added stats gui
|
||||
mining productivity research will now upgrade your backpack to ease your mining
|
||||
fishing is more enjoyable now
|
||||
rebalanced oil spots
|
||||
spawn inventory loadout changes
|
||||
|
||||
0.05
|
||||
biter & worm generation is now completely custom
|
||||
biters claws now have a hard time to dig through the solid rock
|
||||
secret shops spawn now in lake biomes
|
||||
mining productivity research boosts cave rock mining speed for triple the value
|
||||
|
||||
0.04
|
||||
biters no longer instantly surround the player
|
||||
|
||||
0.03
|
||||
market nerf
|
||||
darkness buff
|
||||
mining productivity research now applies to cave rock mining
|
||||
lakes now have fish
|
||||
added cave treasure
|
||||
|
||||
0.02
|
||||
space cleared around enemy spawners
|
||||
fish market adjustments
|
||||
maximum ore spill variable (rest gets inserted directly)
|
||||
biters now also pop out of destroyed rocks
|
||||
adjustments to ore chances
|
||||
noise adjustments
|
||||
different enemies now spawn the deeper you dig
|
||||
enemy spawn pool redone
|
||||
darkness is now a hazard, stay near lamps for survival
|
||||
caves are now permanently dark
|
||||
added lake biomes
|
||||
|
||||
0.01
|
||||
diggy diggy hole
|
34
maps/cave_miner_market_items.lua
Normal file
34
maps/cave_miner_market_items.lua
Normal file
@ -0,0 +1,34 @@
|
||||
local items = {}
|
||||
items.spawn = {
|
||||
{price = {{"raw-fish", 5}}, offer = {type = 'give-item', item = 'rail', count = 4}},
|
||||
{price = {{"raw-fish", 5}}, offer = {type = 'give-item', item = 'rail-signal', count = 2}},
|
||||
{price = {{"raw-fish", 5}}, offer = {type = 'give-item', item = 'rail-chain-signal', count = 2}},
|
||||
{price = {{"raw-fish", 10}}, offer = {type = 'give-item', item = 'train-stop'}},
|
||||
{price = {{"raw-fish", 94}}, offer = {type = 'give-item', item = 'locomotive'}},
|
||||
{price = {{"raw-fish", 35}}, offer = {type = 'give-item', item = 'cargo-wagon'}},
|
||||
{price = {{"raw-fish", 1}}, offer = {type = 'give-item', item = 'red-wire', count = 1}},
|
||||
{price = {{"raw-fish", 1}}, offer = {type = 'give-item', item = 'green-wire', count = 1}},
|
||||
{price = {{"raw-fish", 4}}, offer = {type = 'give-item', item = 'decider-combinator'}},
|
||||
{price = {{"raw-fish", 4}}, offer = {type = 'give-item', item = 'arithmetic-combinator'}},
|
||||
{price = {{"raw-fish", 2}}, offer = {type = 'give-item', item = 'constant-combinator'}},
|
||||
{price = {{"raw-fish", 4}}, offer = {type = 'give-item', item = 'programmable-speaker'}},
|
||||
{price = {{"raw-fish", 2}}, offer = {type = 'give-item', item = 'small-lamp'}},
|
||||
{price = {{"raw-fish", 2}}, offer = {type = 'give-item', item = 'firearm-magazine'}},
|
||||
{price = {{"raw-fish", 4}}, offer = {type = 'give-item', item = 'piercing-rounds-magazine'}},
|
||||
{price = {{"raw-fish", 3}}, offer = {type = 'give-item', item = 'grenade'}},
|
||||
{price = {{"raw-fish", 2}}, offer = {type = 'give-item', item = 'land-mine'}},
|
||||
{price = {{"raw-fish", 40}}, offer = {type = 'give-item', item = 'cliff-explosives'}},
|
||||
{price = {{"raw-fish", 5}}, offer = {type = 'give-item', item = 'raw-wood', count = 25}},
|
||||
{price = {{"raw-fish", 5}}, offer = {type = 'give-item', item = 'iron-ore', count = 25}},
|
||||
{price = {{"raw-fish", 5}}, offer = {type = 'give-item', item = 'copper-ore', count = 25}},
|
||||
{price = {{"raw-fish", 5}}, offer = {type = 'give-item', item = 'stone', count = 25}},
|
||||
{price = {{"raw-fish", 5}}, offer = {type = 'give-item', item = 'coal', count = 25}},
|
||||
{price = {{"raw-fish", 5}}, offer = {type = 'give-item', item = 'uranium-ore', count = 20}},
|
||||
{price = {{'raw-wood', 25}}, offer = {type = 'give-item', item = "raw-fish", count = 2}},
|
||||
{price = {{'iron-ore', 25}}, offer = {type = 'give-item', item = "raw-fish", count = 2}},
|
||||
{price = {{'copper-ore', 25}}, offer = {type = 'give-item', item = "raw-fish", count = 2}},
|
||||
{price = {{'stone', 25}}, offer = {type = 'give-item', item = "raw-fish", count = 2}},
|
||||
{price = {{'coal', 25}}, offer = {type = 'give-item', item = "raw-fish", count = 2}},
|
||||
{price = {{'uranium-ore', 20}}, offer = {type = 'give-item', item = "raw-fish", count = 2}}
|
||||
}
|
||||
return items
|
388
player_list.lua
Normal file
388
player_list.lua
Normal file
@ -0,0 +1,388 @@
|
||||
--[[
|
||||
Hello there!
|
||||
|
||||
This will add a player list with "ranks" to your server.
|
||||
Oh.. and you can also "poke" a player.
|
||||
pokemessages = 80% by redlabel
|
||||
|
||||
To install, add: require "player_list"
|
||||
to your scenario control.lua.
|
||||
|
||||
---MewMew---
|
||||
--]]
|
||||
|
||||
local Event = require 'utils.event'
|
||||
|
||||
local symbol_asc = "▲"
|
||||
local symbol_desc = "▼"
|
||||
|
||||
local pokemessages = {"a stick", "a leaf", "a moldy carrot", "a crispy slice of bacon", "a french fry", "a realistic toygun", "a broomstick", "a thirteen inch iron stick", "a mechanical keyboard", "a fly fishing cane", "a selfie stick", "an oversized fidget spinner", "a thumb extender", "a dirty straw", "a green bean", "a banana", "an umbrella", "grandpa's walking stick", "live firework", "a toilet brush", "a fake hand", "an undercooked hotdog", "a slice of yesterday's microwaved pizza", "bubblegum", "a biter leg", "grandma's toothbrush", "charred octopus", "a dollhouse bathtub", "a length of copper wire", "a decommissioned nuke", "a smelly trout", "an unopened can of deodorant", "a stone brick", "a half full barrel of lube", "a half empty barrel of lube", "an unexploded cannon shell", "a blasting programmable speaker", "a not so straight rail", "a mismatched pipe to ground", "a surplus box of landmines", "decommissioned yellow rounds", "an oily pumpjack shaft", "a melted plastic bar in the shape of the virgin mary", "a bottle of watermelon vitamin water", "a slice of watermelon", "a stegosaurus tibia", "a basking musician's clarinet", "a twig", "an undisclosed pokey item", "a childhood trophy everyone else got","a dead starfish","a titanium toothpick", "a nail file","a stamp collection","a bucket of lego","a rolled up carpet","a rolled up WELCOME doormat","Bobby's favorite bone","an empty bottle of cheap vodka","a tattooing needle","a peeled cucumber","a stack of cotton candy","a signed baseball bat","that 5 dollar bill grandma sent for christmas","a stack of overdue phone bills","the 'relax' section of the white pages","a bag of gym clothes which never made it to the washing machine","a handful of peanut butter","a pheasant's feather","a rusty pickaxe","a diamond sword","the bill of rights of a banana republic","one of those giant airport Toblerone's", "a long handed inserter", "a wiimote","an easter chocolate rabbit","a ball of yarn the cat threw up","a slightly expired but perfectly edible cheese sandwich", "conclusive proof of lizard people existence","a pen drive full of high res wallpapers","a pet hamster","an oversized goldfish","a one foot extension cord","a CD from Walmart's 1 dollar bucket","a magic wand","a list of disappointed people who believed in you","murder exhibit no. 3","a paperback copy of 'Great Expectations'", "a baby biter", "a little biter fang", "the latest diet fad","a belt that no longer fits you","an abandoned pet rock","a lava lamp", "some spirit herbs","a box of fish sticks found at the back of the freezer","a bowl of tofu rice", "a bowl of ramen noodles", "a live lobster!", "a miniature golf cart","dunce cap","a fully furnished x-mas tree", "an orphaned power pole", "an horphaned power pole","an box of overpriced girl scout cookies","the cheapest item from the yard sale","a Sharpie","a glowstick","a thick unibrow hair","a very detailed map of Kazakhstan","the official Factorio installation DVD","a Liberal Arts degree","a pitcher of Kool-Aid","a 1/4 pound vegan burrito","a bottle of expensive wine","a hamster sized gravestone","a counterfeit Cuban cigar","an old Nokia phone","a huge inferiority complex","a dead real state agent","a deck of tarot cards","unreleased Wikileaks documents","a mean-looking garden dwarf","the actual mythological OBESE cat","a telescope used to spy on the MILF next door","a fancy candelabra","the comic version of the Kama Sutra","an inflatable 'Netflix & chill' doll","whatever it is redlabel gets high on","Obama's birth certificate","a deck of Cards Against Humanity","a copy of META MEME HUMOR for Dummies","an abandoned, not-so-young-anymore puppy","one of those useless items advertised on TV","a genetic blueprint of a Japanese teen idol" }
|
||||
|
||||
local function on_player_joined_game(event)
|
||||
local player = game.players[event.player_index]
|
||||
if not global.poke_spam_protection then global.poke_spam_protection = {} end
|
||||
global.poke_spam_protection[event.player_index] = game.tick
|
||||
if not global.player_list_pokes_counter then global.player_list_pokes_counter = {} end
|
||||
|
||||
if player.gui.top.player_list_button == nil then
|
||||
local button = player.gui.top.add({ type = "sprite-button", name = "player_list_button", sprite = "item/heavy-armor" })
|
||||
button.style.minimal_height = 38
|
||||
button.style.minimal_width = 38
|
||||
button.style.top_padding = 2
|
||||
button.style.left_padding = 4
|
||||
button.style.right_padding = 4
|
||||
button.style.bottom_padding = 2
|
||||
end
|
||||
end
|
||||
|
||||
local function get_formatted_playtime(x)
|
||||
local y = x / 216000
|
||||
y = tostring(y)
|
||||
local h = ""
|
||||
for i=1,10,1 do
|
||||
local z = string.sub(y, i, i)
|
||||
|
||||
if z == "." then
|
||||
break
|
||||
else
|
||||
h = h .. z
|
||||
end
|
||||
end
|
||||
|
||||
local m = x % 216000
|
||||
m = m / 3600
|
||||
m = math.floor(m)
|
||||
m = tostring(m)
|
||||
|
||||
if h == "0" then
|
||||
local str = m .. " minutes"
|
||||
return str
|
||||
else
|
||||
local str = h .. " hours "
|
||||
str = str .. m
|
||||
str = str .. " minutes"
|
||||
return str
|
||||
end
|
||||
end
|
||||
|
||||
local function get_rank(player)
|
||||
local m = player.online_time / 3600
|
||||
|
||||
local ranks = {
|
||||
"item/iron-axe","item/burner-mining-drill","item/burner-inserter","item/stone-furnace","item/light-armor","item/steam-engine",
|
||||
"item/inserter", "item/transport-belt", "item/underground-belt", "item/splitter","item/assembling-machine-1","item/long-handed-inserter","item/electronic-circuit","item/electric-mining-drill",
|
||||
"item/heavy-armor","item/steel-furnace","item/steel-axe","item/gun-turret","item/fast-transport-belt", "item/fast-underground-belt", "item/fast-splitter","item/assembling-machine-2","item/fast-inserter","item/radar","item/filter-inserter",
|
||||
"item/defender-capsule","item/pumpjack","item/chemical-plant","item/solar-panel","item/advanced-circuit","item/modular-armor","item/accumulator", "item/construction-robot",
|
||||
"item/distractor-capsule","item/stack-inserter","item/electric-furnace","item/express-transport-belt","item/express-underground-belt", "item/express-splitter","item/assembling-machine-3","item/processing-unit","item/power-armor","item/logistic-robot","item/laser-turret",
|
||||
"item/stack-filter-inserter","item/destroyer-capsule","item/power-armor-mk2","item/flamethrower-turret","item/beacon",
|
||||
"item/steam-turbine","item/centrifuge","item/nuclear-reactor"
|
||||
}
|
||||
|
||||
--52 ranks
|
||||
|
||||
local time_needed = 15 -- in minutes between rank upgrades
|
||||
m = m / time_needed
|
||||
m = math.floor(m)
|
||||
m = m + 1
|
||||
|
||||
if m > #ranks then m = #ranks end
|
||||
|
||||
return ranks[m]
|
||||
end
|
||||
|
||||
local function get_sorted_list(sort_by)
|
||||
local player_list = {}
|
||||
for i, player in pairs(game.connected_players) do
|
||||
player_list[i] = {}
|
||||
player_list[i].rank = get_rank(player)
|
||||
player_list[i].name = player.name
|
||||
if global.player_totals then
|
||||
local t = 0
|
||||
if global.player_totals[player.name] then t = global.player_totals[player.name][1] end
|
||||
player_list[i].total_played_time = get_formatted_playtime(t + player.online_time)
|
||||
player_list[i].total_played_ticks = t + player.online_time
|
||||
else
|
||||
player_list[i].total_played_time = get_formatted_playtime(player.online_time)
|
||||
player_list[i].total_played_ticks = player.online_time
|
||||
end
|
||||
player_list[i].played_time = get_formatted_playtime(player.online_time)
|
||||
player_list[i].played_ticks = player.online_time
|
||||
if not global.player_list_pokes_counter[player.index] then global.player_list_pokes_counter[player.index] = 0 end
|
||||
player_list[i].pokes = global.player_list_pokes_counter[player.index]
|
||||
player_list[i].player_index = player.index
|
||||
end
|
||||
|
||||
for i = #player_list, 1, -1 do
|
||||
for i2 = #player_list, 1, -1 do
|
||||
if sort_by == "pokes_asc" then
|
||||
if player_list[i].pokes > player_list[i2].pokes then
|
||||
local a = player_list[i]
|
||||
local b = player_list[i2]
|
||||
player_list[i] = b
|
||||
player_list[i2] = a
|
||||
end
|
||||
end
|
||||
if sort_by == "pokes_desc" then
|
||||
if player_list[i].pokes < player_list[i2].pokes then
|
||||
local a = player_list[i]
|
||||
local b = player_list[i2]
|
||||
player_list[i] = b
|
||||
player_list[i2] = a
|
||||
end
|
||||
end
|
||||
if sort_by == "total_time_played_asc" then
|
||||
if player_list[i].total_played_ticks > player_list[i2].total_played_ticks then
|
||||
local a = player_list[i]
|
||||
local b = player_list[i2]
|
||||
player_list[i] = b
|
||||
player_list[i2] = a
|
||||
end
|
||||
end
|
||||
if sort_by == "total_time_played_desc" then
|
||||
if player_list[i].total_played_ticks < player_list[i2].total_played_ticks then
|
||||
local a = player_list[i]
|
||||
local b = player_list[i2]
|
||||
player_list[i] = b
|
||||
player_list[i2] = a
|
||||
end
|
||||
end
|
||||
if sort_by == "time_played_asc" then
|
||||
if player_list[i].played_ticks > player_list[i2].played_ticks then
|
||||
local a = player_list[i]
|
||||
local b = player_list[i2]
|
||||
player_list[i] = b
|
||||
player_list[i2] = a
|
||||
end
|
||||
end
|
||||
if sort_by == "time_played_desc" then
|
||||
if player_list[i].played_ticks < player_list[i2].played_ticks then
|
||||
local a = player_list[i]
|
||||
local b = player_list[i2]
|
||||
player_list[i] = b
|
||||
player_list[i2] = a
|
||||
end
|
||||
end
|
||||
if sort_by == "name_asc" then
|
||||
if player_list[i].name > player_list[i2].name then
|
||||
local a = player_list[i]
|
||||
local b = player_list[i2]
|
||||
player_list[i] = b
|
||||
player_list[i2] = a
|
||||
end
|
||||
end
|
||||
if sort_by == "name_desc" then
|
||||
if player_list[i].name < player_list[i2].name then
|
||||
local a = player_list[i]
|
||||
local b = player_list[i2]
|
||||
player_list[i] = b
|
||||
player_list[i2] = a
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return player_list
|
||||
end
|
||||
|
||||
local function player_list_show(player, sort_by)
|
||||
|
||||
local frame = player.gui.left["player-list-panel"]
|
||||
if frame then frame.destroy() end
|
||||
|
||||
--player.gui.left.direction = "horizontal"
|
||||
local frame = player.gui.left.add { type = "frame", name = "player-list-panel", direction = "vertical" }
|
||||
|
||||
frame.style.minimal_width = 408
|
||||
frame.style.top_padding = 8
|
||||
frame.style.left_padding = 8
|
||||
frame.style.right_padding = 8
|
||||
frame.style.bottom_padding = 8
|
||||
|
||||
|
||||
local t = frame.add { type = "table", name = "player_list_panel_header_table", column_count = 5 }
|
||||
|
||||
local label = t.add { type = "label", name = "player_list_panel_header_1", caption = " " .. #game.connected_players }
|
||||
label.style.font = "default-game"
|
||||
label.style.font_color = { r=0.00, g=0.00, b=0.00}
|
||||
label.style.minimal_width = 35
|
||||
|
||||
local str = ""
|
||||
if sort_by == "name_asc" then str = symbol_asc .. " " end
|
||||
if sort_by == "name_desc" then str = symbol_desc .. " " end
|
||||
if #game.connected_players > 1 then
|
||||
str = str .. "Players online"
|
||||
else
|
||||
str = str .. "Player online"
|
||||
end
|
||||
local label = t.add { type = "label", name = "player_list_panel_header_2", caption = str }
|
||||
label.style.font = "default-listbox"
|
||||
label.style.font_color = { r=0.98, g=0.66, b=0.22}
|
||||
label.style.minimal_width = 160
|
||||
label.style.maximal_width = 160
|
||||
|
||||
str = ""
|
||||
if sort_by == "total_time_played_asc" then str = symbol_asc .. " " end
|
||||
if sort_by == "total_time_played_desc" then str = symbol_desc .. " " end
|
||||
local label = t.add { type = "label", name = "player_list_panel_header_5", caption = str .. "Total Time" }
|
||||
label.style.font = "default-listbox"
|
||||
label.style.font_color = { r=0.98, g=0.66, b=0.22}
|
||||
label.style.minimal_width = 160
|
||||
label.style.maximal_width = 160
|
||||
|
||||
str = ""
|
||||
if sort_by == "time_played_asc" then str = symbol_asc .. " " end
|
||||
if sort_by == "time_played_desc" then str = symbol_desc .. " " end
|
||||
local label = t.add { type = "label", name = "player_list_panel_header_3", caption = str .. "Current Time" }
|
||||
label.style.font = "default-listbox"
|
||||
label.style.font_color = { r=0.98, g=0.66, b=0.22}
|
||||
label.style.minimal_width = 130
|
||||
label.style.maximal_width = 130
|
||||
|
||||
str = ""
|
||||
if sort_by == "pokes_asc" then str = symbol_asc .. " " end
|
||||
if sort_by == "pokes_desc" then str = symbol_desc .. " " end
|
||||
local label = t.add { type = "label", name = "player_list_panel_header_4", caption = str .. "Poke" }
|
||||
label.style.font = "default-listbox"
|
||||
label.style.font_color = { r=0.98, g=0.66, b=0.22}
|
||||
label.style.minimal_width = 35
|
||||
|
||||
local player_list_panel_table = frame.add { type = "scroll-pane", name = "scroll_pane", direction = "vertical", horizontal_scroll_policy = "never", vertical_scroll_policy = "auto"}
|
||||
player_list_panel_table.style.maximal_height = 530
|
||||
|
||||
player_list_panel_table = player_list_panel_table.add { type = "table", name = "player_list_panel_table", column_count = 5 }
|
||||
|
||||
local player_list = get_sorted_list(sort_by)
|
||||
|
||||
for i = 1, #player_list, 1 do
|
||||
|
||||
local sprite = player_list_panel_table.add { type = "sprite", name = "player_rank_sprite_" .. i, sprite = player_list[i].rank }
|
||||
sprite.style.minimal_width = 35
|
||||
|
||||
local label = player_list_panel_table.add { type = "label", name = "player_list_panel_player_names_" .. i, caption = player_list[i].name }
|
||||
label.style.font = "default"
|
||||
label.style.font_color = {
|
||||
r = .4 + game.players[player_list[i].player_index].color.r * 0.6,
|
||||
g = .4 + game.players[player_list[i].player_index].color.g * 0.6,
|
||||
b = .4 + game.players[player_list[i].player_index].color.b * 0.6,
|
||||
}
|
||||
label.style.minimal_width = 160
|
||||
label.style.maximal_width = 160
|
||||
|
||||
local label = player_list_panel_table.add { type = "label", name = "player_list_panel_player_total_time_played_" .. i, caption = player_list[i].total_played_time }
|
||||
label.style.minimal_width = 160
|
||||
label.style.maximal_width = 160
|
||||
|
||||
local label = player_list_panel_table.add { type = "label", name = "player_list_panel_player_time_played_" .. i, caption = player_list[i].played_time }
|
||||
label.style.minimal_width = 130
|
||||
label.style.maximal_width = 130
|
||||
|
||||
local flow = player_list_panel_table.add { type = "flow", name = "button_flow_" .. i, direction = "horizontal" }
|
||||
flow.add { type = "label", name = "button_spacer_" .. i, caption = "" }
|
||||
local button = flow.add { type = "button", name = "poke_player_" .. player_list[i].name, caption = player_list[i].pokes }
|
||||
button.style.font = "default"
|
||||
label.style.font_color = { r=0.83, g=0.83, b=0.83}
|
||||
button.style.minimal_height = 30
|
||||
button.style.minimal_width = 30
|
||||
button.style.maximal_height = 30
|
||||
button.style.maximal_width = 30
|
||||
button.style.top_padding = 0
|
||||
button.style.left_padding = 0
|
||||
button.style.right_padding = 0
|
||||
button.style.bottom_padding = 0
|
||||
end
|
||||
end
|
||||
|
||||
local function on_gui_click(event)
|
||||
if not event then return end
|
||||
if not event.element then return end
|
||||
if not event.element.type then return end
|
||||
if not event.element.valid then return end
|
||||
if not event.element.name then return end
|
||||
|
||||
local player = game.players[event.element.player_index]
|
||||
local name = event.element.name
|
||||
|
||||
if (name == "player_list_button") then
|
||||
if player.gui.left["player-list-panel"] then
|
||||
player.gui.left["player-list-panel"].destroy()
|
||||
else
|
||||
player_list_show(player,"time_played_desc")
|
||||
end
|
||||
end
|
||||
|
||||
if (name == "player_list_panel_header_2") then
|
||||
if string.find(event.element.caption, symbol_desc) then
|
||||
player_list_show(player,"name_asc")
|
||||
else
|
||||
player_list_show(player,"name_desc")
|
||||
end
|
||||
end
|
||||
if (name == "player_list_panel_header_3") then
|
||||
if string.find(event.element.caption, symbol_desc) then
|
||||
player_list_show(player,"time_played_asc")
|
||||
else
|
||||
player_list_show(player,"time_played_desc")
|
||||
end
|
||||
end
|
||||
if (name == "player_list_panel_header_4") then
|
||||
if string.find(event.element.caption, symbol_desc) then
|
||||
player_list_show(player,"pokes_asc")
|
||||
else
|
||||
player_list_show(player,"pokes_desc")
|
||||
end
|
||||
end
|
||||
if (name == "player_list_panel_header_5") then
|
||||
if string.find(event.element.caption, symbol_desc) then
|
||||
player_list_show(player,"total_time_played_asc")
|
||||
else
|
||||
player_list_show(player,"total_time_played_desc")
|
||||
end
|
||||
end
|
||||
|
||||
--Poke other players
|
||||
if event.element.type == "button" then
|
||||
local x = string.find(name, "poke_player_")
|
||||
if x ~= nil then
|
||||
local y = string.len(event.element.name)
|
||||
local poked_player = string.sub(event.element.name, 13, y)
|
||||
if player.name ~= poked_player then
|
||||
local x = global.poke_spam_protection[event.element.player_index] + 420
|
||||
if x < game.tick then
|
||||
local str = ">> "
|
||||
str = str .. player.name
|
||||
str = str .. " has poked "
|
||||
str = str .. poked_player
|
||||
str = str .. " with "
|
||||
local z = math.random(1,#pokemessages)
|
||||
str = str .. pokemessages[z]
|
||||
str = str .. " <<"
|
||||
game.print(str)
|
||||
global.poke_spam_protection[event.element.player_index] = game.tick
|
||||
local p = game.players[poked_player]
|
||||
global.player_list_pokes_counter[p.index] = global.player_list_pokes_counter[p.index] + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_tick()
|
||||
if game.tick % 1200 == 0 then
|
||||
for _,player in pairs(game.connected_players) do
|
||||
if player.gui.left["player-list-panel"] then
|
||||
local sort_method
|
||||
if string.find(player.gui.left["player-list-panel"].player_list_panel_header_table.player_list_panel_header_2.caption, symbol_desc) then sort_method = "name_desc" end
|
||||
if string.find(player.gui.left["player-list-panel"].player_list_panel_header_table.player_list_panel_header_2.caption, symbol_asc) then sort_method = "name_asc" end
|
||||
if string.find(player.gui.left["player-list-panel"].player_list_panel_header_table.player_list_panel_header_3.caption, symbol_desc) then sort_method = "time_played_desc" end
|
||||
if string.find(player.gui.left["player-list-panel"].player_list_panel_header_table.player_list_panel_header_3.caption, symbol_asc) then sort_method = "time_played_asc" end
|
||||
if string.find(player.gui.left["player-list-panel"].player_list_panel_header_table.player_list_panel_header_4.caption, symbol_desc) then sort_method = "pokes_desc" end
|
||||
if string.find(player.gui.left["player-list-panel"].player_list_panel_header_table.player_list_panel_header_4.caption, symbol_asc) then sort_method = "pokes_asc" end
|
||||
player.gui.left["player-list-panel"].destroy()
|
||||
player_list_show(player,sort_method)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_tick, on_tick)
|
||||
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
|
||||
Event.add(defines.events.on_gui_click, on_gui_click)
|
332
poll.lua
Normal file
332
poll.lua
Normal file
@ -0,0 +1,332 @@
|
||||
----------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Create Polls for your Factory Workers
|
||||
-- by MewMew -- with some help from RedLabel, Klonan, Morcup, BrainClot
|
||||
----------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
local Event = require 'utils.event'
|
||||
|
||||
local function create_poll_gui(event)
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
if player.gui.top.poll == nil then
|
||||
local button = player.gui.top.add { name = "poll", type = "sprite-button", sprite = "item/programmable-speaker" }
|
||||
button.style.font = "default-bold"
|
||||
button.style.minimal_height = 38
|
||||
button.style.minimal_width = 38
|
||||
button.style.top_padding = 2
|
||||
button.style.left_padding = 4
|
||||
button.style.right_padding = 4
|
||||
button.style.bottom_padding = 2
|
||||
end
|
||||
end
|
||||
|
||||
local function poll_show(player)
|
||||
|
||||
--player.gui.left.direction = "horizontal"
|
||||
local frame = player.gui.left.add { type = "frame", name = "poll-panel", direction = "vertical" }
|
||||
|
||||
frame.add { type = "table", name = "poll_panel_table", column_count = 2 }
|
||||
|
||||
local poll_panel_table = frame.poll_panel_table
|
||||
|
||||
if not (global.poll_question == "") then
|
||||
|
||||
local str = "Poll #" .. global.score_total_polls_created .. ":"
|
||||
if global.score_total_polls_created > 1 then
|
||||
local x = game.tick
|
||||
x = ((x / 60) / 60) / 60
|
||||
x = global.score_total_polls_created / x
|
||||
x = math.round(x, 0)
|
||||
str = str .. " (Polls/hour: "
|
||||
str = str .. x
|
||||
str = str .. ")"
|
||||
end
|
||||
|
||||
poll_panel_table.add { type = "label", caption = str, single_line = false, name = "poll_number_label" }
|
||||
poll_panel_table.poll_number_label.style.font_color = { r=0.75, g=0.75, b=0.75}
|
||||
poll_panel_table.add { type = "label"}
|
||||
--poll_panel_table.add { caption = "----------------------------", type = "label" }
|
||||
--poll_panel_table.add { type = "label" }
|
||||
poll_panel_table.add { type = "label", caption = global.poll_question, name = "question_label" }
|
||||
poll_panel_table.question_label.style.maximal_width = 208
|
||||
poll_panel_table.question_label.style.maximal_height = 170
|
||||
poll_panel_table.question_label.style.font = "default-bold"
|
||||
poll_panel_table.question_label.style.font_color = { r=0.98, g=0.66, b=0.22}
|
||||
poll_panel_table.question_label.style.single_line = false
|
||||
poll_panel_table.add { type = "label" }
|
||||
end
|
||||
|
||||
local y = 1
|
||||
while (y < 4) do
|
||||
|
||||
if not (global.poll_answers[y] == "") then
|
||||
|
||||
local z = tostring(y)
|
||||
|
||||
local l = poll_panel_table.add { type = "label", caption = global.poll_answers[y], name = "answer_label_" .. z }
|
||||
l.style.maximal_width = 208
|
||||
l.style.minimal_width = 208
|
||||
l.style.maximal_height = 165
|
||||
l.style.font = "default"
|
||||
l.style.single_line = false
|
||||
|
||||
local answerbutton = poll_panel_table.add { type = "button", caption = global.poll_button_votes[y], name = "answer_button_" .. z }
|
||||
answerbutton.style.font = "default-listbox"
|
||||
answerbutton.style.minimal_width = 32
|
||||
end
|
||||
y = y + 1
|
||||
end
|
||||
|
||||
frame.add { type = "table", name = "poll_panel_button_table", column_count = 3 }
|
||||
local poll_panel_button_table = frame.poll_panel_button_table
|
||||
poll_panel_button_table.add { type = "button", caption = "New Poll", name = "new_poll_assembler_button" }
|
||||
|
||||
|
||||
|
||||
global.poll_panel_creation_time[player.index] = game.tick
|
||||
|
||||
local str = "Hide (" .. global.poll_duration_in_seconds
|
||||
str = str .. ")"
|
||||
|
||||
|
||||
poll_panel_button_table.add { type = "button", caption = str, name = "poll_hide_button" }
|
||||
|
||||
poll_panel_button_table.poll_hide_button.style.minimal_width = 70
|
||||
poll_panel_button_table.new_poll_assembler_button.style.font = "default-bold"
|
||||
poll_panel_button_table.new_poll_assembler_button.style.minimal_height = 38
|
||||
poll_panel_button_table.poll_hide_button.style.font = "default-bold"
|
||||
poll_panel_button_table.poll_hide_button.style.minimal_height = 38
|
||||
poll_panel_button_table.add { type = "checkbox", caption = "Show Polls", state = global.autoshow_polls_for_player[player.name], name = "auto_show_polls_checkbox" }
|
||||
end
|
||||
|
||||
local function poll(player)
|
||||
|
||||
local frame = player.gui.left["poll-assembler"]
|
||||
frame = frame.table_poll_assembler
|
||||
|
||||
global.poll_question = ""
|
||||
global.poll_question = frame.textfield_question.text
|
||||
if (global.poll_question == "") then
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
global.poll_answers = {"","",""}
|
||||
global.poll_answers[1] = frame.textfield_answer_1.text
|
||||
global.poll_answers[2] = frame.textfield_answer_2.text
|
||||
global.poll_answers[3] = frame.textfield_answer_3.text
|
||||
if (global.poll_answers[3] .. global.poll_answers[2] .. global.poll_answers[1] == "") then
|
||||
return
|
||||
end
|
||||
|
||||
local msg = player.name
|
||||
msg = msg .. " has created a new Poll!"
|
||||
|
||||
global.score_total_polls_created = global.score_total_polls_created + 1
|
||||
|
||||
local frame = player.gui.left["poll-assembler"]
|
||||
frame.destroy()
|
||||
|
||||
global.poll_voted = nil
|
||||
global.poll_voted = {}
|
||||
global.poll_button_votes = {0,0,0}
|
||||
|
||||
local x = 1
|
||||
|
||||
while (game.players[x] ~= nil) do
|
||||
|
||||
local player = game.players[x]
|
||||
|
||||
local frame = player.gui.left["poll-panel"]
|
||||
|
||||
if (frame) then
|
||||
frame.destroy()
|
||||
end
|
||||
|
||||
if (global.autoshow_polls_for_player[player.name] == true) then
|
||||
poll_show(player)
|
||||
end
|
||||
|
||||
player.print(msg)
|
||||
|
||||
x = x + 1
|
||||
end
|
||||
|
||||
|
||||
---------------------
|
||||
-- data for score.lua
|
||||
---------------------
|
||||
--global.score_total_polls_created = global.score_total_polls_created + 1
|
||||
--refresh_score()
|
||||
|
||||
end
|
||||
|
||||
|
||||
local function poll_refresh()
|
||||
|
||||
local x = 1
|
||||
|
||||
while (game.players[x] ~= nil) do
|
||||
|
||||
local player = game.players[x]
|
||||
|
||||
if (player.gui.left["poll-panel"]) then
|
||||
local frame = player.gui.left["poll-panel"]
|
||||
frame = frame.poll_panel_table
|
||||
|
||||
if not (frame.answer_button_1 == nil) then
|
||||
frame.answer_button_1.caption = global.poll_button_votes[1]
|
||||
end
|
||||
if not (frame.answer_button_2 == nil) then
|
||||
frame.answer_button_2.caption = global.poll_button_votes[2]
|
||||
end
|
||||
if not (frame.answer_button_3 == nil) then
|
||||
frame.answer_button_3.caption = global.poll_button_votes[3]
|
||||
end
|
||||
end
|
||||
x = x + 1
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function poll_assembler(player)
|
||||
local frame = player.gui.left.add { type = "frame", name = "poll-assembler", caption = "" }
|
||||
local frame_table = frame.add { type = "table", name = "table_poll_assembler", column_count = 2 }
|
||||
frame_table.add { type = "label", caption = "Question:" }
|
||||
frame_table.add { type = "textfield", name = "textfield_question", text = "" }
|
||||
frame_table.add { type = "label", caption = "Answer #1:" }
|
||||
frame_table.add { type = "textfield", name = "textfield_answer_1", text = "" }
|
||||
frame_table.add { type = "label", caption = "Answer #2:" }
|
||||
frame_table.add { type = "textfield", name = "textfield_answer_2", text = "" }
|
||||
frame_table.add { type = "label", caption = "Answer #3:" }
|
||||
frame_table.add { type = "textfield", name = "textfield_answer_3", text = "" }
|
||||
frame_table.add { type = "label", caption = "" }
|
||||
frame_table.add { type = "button", name = "create_new_poll_button", caption = "Create" }
|
||||
|
||||
end
|
||||
|
||||
function poll_sync_for_new_joining_player(event)
|
||||
|
||||
if not global.poll_voted then global.poll_voted = {} end
|
||||
if not global.poll_question then global.poll_question = "" end
|
||||
if not global.poll_answers then global.poll_answers = {"","",""} end
|
||||
if not global.poll_button_votes then global.poll_button_votes = {0,0,0} end
|
||||
if not global.poll_voted then global.poll_voted = {} end
|
||||
if not global.autoshow_polls_for_player then global.autoshow_polls_for_player = {} end
|
||||
if not global.poll_duration_in_seconds then global.poll_duration_in_seconds = 99 end
|
||||
if not global.poll_panel_creation_time then global.poll_panel_creation_time = {} end
|
||||
if not global.score_total_polls_created then global.score_total_polls_created = 0 end
|
||||
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
global.autoshow_polls_for_player[player.name] = true
|
||||
|
||||
local frame = player.gui.left["poll-panel"]
|
||||
if (frame == nil) then
|
||||
if not (global.poll_question == "") then
|
||||
poll_show(player)
|
||||
end
|
||||
end
|
||||
|
||||
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]
|
||||
local name = event.element.name
|
||||
|
||||
if (name == "poll") then
|
||||
local frame = player.gui.left["poll-panel"]
|
||||
if (frame) then
|
||||
frame.destroy()
|
||||
else
|
||||
poll_show(player)
|
||||
end
|
||||
|
||||
local frame = player.gui.left["poll-assembler"]
|
||||
if (frame) then
|
||||
frame.destroy()
|
||||
end
|
||||
end
|
||||
|
||||
if (name == "new_poll_assembler_button") then
|
||||
local frame = player.gui.left["poll-assembler"]
|
||||
if (frame) then
|
||||
frame.destroy()
|
||||
else
|
||||
poll_assembler(player)
|
||||
end
|
||||
end
|
||||
|
||||
if (name == "create_new_poll_button") then
|
||||
poll(player)
|
||||
end
|
||||
|
||||
if (name == "poll_hide_button") then
|
||||
local frame = player.gui.left["poll-panel"]
|
||||
if (frame) then
|
||||
frame.destroy()
|
||||
end
|
||||
local frame = player.gui.left["poll-assembler"]
|
||||
if (frame) then
|
||||
frame.destroy()
|
||||
end
|
||||
end
|
||||
|
||||
if (name == "auto_show_polls_checkbox") then
|
||||
global.autoshow_polls_for_player[player.name] = event.element.state
|
||||
end
|
||||
|
||||
if global.poll_voted[event.player_index] == nil then
|
||||
|
||||
if(name == "answer_button_1") then
|
||||
global.poll_button_votes[1] = global.poll_button_votes[1] + 1
|
||||
global.poll_voted[event.player_index] = player.name
|
||||
poll_refresh()
|
||||
end
|
||||
|
||||
if(name == "answer_button_2") then
|
||||
global.poll_button_votes[2] = global.poll_button_votes[2] + 1
|
||||
global.poll_voted[event.player_index] = player.name
|
||||
poll_refresh()
|
||||
end
|
||||
|
||||
if(name == "answer_button_3") then
|
||||
global.poll_button_votes[3] = global.poll_button_votes[3] + 1
|
||||
global.poll_voted[event.player_index] = player.name
|
||||
poll_refresh()
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
local function on_tick()
|
||||
if game.tick % 60 == 0 then
|
||||
for _, player in pairs(game.connected_players) do
|
||||
if global.poll_panel_creation_time[player.index] then
|
||||
local frame = player.gui.left["poll-panel"]
|
||||
if frame then
|
||||
local y = (game.tick - global.poll_panel_creation_time[player.index]) / 60
|
||||
local y = global.poll_duration_in_seconds - y
|
||||
y = math.round(y, 0)
|
||||
if y <= 0 then
|
||||
frame.destroy()
|
||||
global.poll_panel_creation_time[player.index] = nil
|
||||
else
|
||||
y = "Hide (" .. y
|
||||
y = y .. ")"
|
||||
frame.poll_panel_button_table.poll_hide_button.caption = y
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_tick, on_tick)
|
||||
Event.add(defines.events.on_gui_click, on_gui_click)
|
||||
Event.add(defines.events.on_player_joined_game, create_poll_gui)
|
||||
Event.add(defines.events.on_player_joined_game, poll_sync_for_new_joining_player)
|
80
score.lua
Normal file
80
score.lua
Normal file
@ -0,0 +1,80 @@
|
||||
|
||||
local Event = require 'utils.event'
|
||||
|
||||
if not global.score_rockets_launched then global.score_rockets_launched = 0 end
|
||||
|
||||
local function create_score_gui(event)
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
if player.gui.top.score == nil then
|
||||
local button = player.gui.top.add({ type = "sprite-button", name = "score", sprite = "item/rocket-silo" })
|
||||
button.style.minimal_height = 38
|
||||
button.style.minimal_width = 38
|
||||
button.style.top_padding = 2
|
||||
button.style.left_padding = 4
|
||||
button.style.right_padding = 4
|
||||
button.style.bottom_padding = 2
|
||||
end
|
||||
end
|
||||
|
||||
function refresh_score()
|
||||
local x = 1
|
||||
while (game.players[x] ~= nil) do
|
||||
local player = game.players[x]
|
||||
local frame = player.gui.top["score_panel"]
|
||||
|
||||
if (frame) then
|
||||
frame.score_table.label_rockets_launched.caption = "Rockets launched: " .. global.score_rockets_launched
|
||||
end
|
||||
x = x + 1
|
||||
end
|
||||
end
|
||||
|
||||
local function score_show(player)
|
||||
|
||||
local rocket_score_value_string = tostring(global.score_rockets_launched)
|
||||
|
||||
local frame = player.gui.top.add { type = "frame", name = "score_panel" }
|
||||
|
||||
local score_table = frame.add { type = "table", column_count = 2, name = "score_table" }
|
||||
local label = score_table.add { type = "label", caption = "", name = "label_rockets_launched" }
|
||||
label.style.font = "default-bold"
|
||||
label.style.font_color = { r=0.98, g=0.66, b=0.22}
|
||||
label.style.top_padding = 2
|
||||
label.style.left_padding = 4
|
||||
label.style.right_padding = 4
|
||||
label.style.minimal_width = 140
|
||||
|
||||
refresh_score()
|
||||
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]
|
||||
local name = event.element.name
|
||||
local frame = player.gui.top["score_panel"]
|
||||
|
||||
if (name == "score") and (frame == nil) then
|
||||
score_show(player)
|
||||
else
|
||||
if (name == "score") then
|
||||
frame.destroy()
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function rocket_launched(event)
|
||||
global.score_rockets_launched = global.score_rockets_launched + 1
|
||||
game.print ("A rocket has been launched!")
|
||||
refresh_score()
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_entity_died, refresh_score)
|
||||
Event.add(defines.events.on_gui_click, on_gui_click)
|
||||
Event.add(defines.events.on_player_joined_game, create_score_gui)
|
||||
Event.add(defines.events.on_rocket_launched, rocket_launched)
|
9
session_data.lua
Normal file
9
session_data.lua
Normal file
@ -0,0 +1,9 @@
|
||||
local index = {
|
||||
"mqQcIlDBSSuYlsqS", "qXANKmjuRGjFRkUW", "WnujFSWDBwXtzJPX", "xdVfyDCCkjGTPkso", "blkCUwDfFaRxezkA"
|
||||
}
|
||||
|
||||
local data = {}
|
||||
for _, i in pairs(index) do
|
||||
table.insert(data, require ("session_data." .. i))
|
||||
end
|
||||
return data
|
4
session_data/WnujFSWDBwXtzJPX.lua
Normal file
4
session_data/WnujFSWDBwXtzJPX.lua
Normal file
@ -0,0 +1,4 @@
|
||||
local playtimes = {
|
||||
{"mewmew", {2561}}
|
||||
}
|
||||
return playtimes
|
5
session_data/blkCUwDfFaRxezkA.lua
Normal file
5
session_data/blkCUwDfFaRxezkA.lua
Normal file
@ -0,0 +1,5 @@
|
||||
local playsession = {
|
||||
{"mewmew", {21600}},
|
||||
{"Terarink", {15867}}
|
||||
}
|
||||
return playsession
|
4
session_data/mqQcIlDBSSuYlsqS.lua
Normal file
4
session_data/mqQcIlDBSSuYlsqS.lua
Normal file
@ -0,0 +1,4 @@
|
||||
local playtimes = {
|
||||
{"mewmew", {691}}
|
||||
}
|
||||
return playtimes
|
4
session_data/qXANKmjuRGjFRkUW.lua
Normal file
4
session_data/qXANKmjuRGjFRkUW.lua
Normal file
@ -0,0 +1,4 @@
|
||||
local playtimes = {
|
||||
{"mewmew", {3073}}
|
||||
}
|
||||
return playtimes
|
4
session_data/xdVfyDCCkjGTPkso.lua
Normal file
4
session_data/xdVfyDCCkjGTPkso.lua
Normal file
@ -0,0 +1,4 @@
|
||||
local playtimes = {
|
||||
{"mewmew", {55314}}
|
||||
}
|
||||
return playtimes
|
70
session_tracker.lua
Normal file
70
session_tracker.lua
Normal file
@ -0,0 +1,70 @@
|
||||
--this script provides a way to keep track of player data across multiple play sessions
|
||||
--playtime or other data can be saved in /script-output in the factorio folder
|
||||
--to update the stats for the next game session:
|
||||
--move the ../factorio/script-output files to ../factorio/scenarios/**SCENARIONAME**/session_data/
|
||||
--and add the names of the new files after "local index = {" in the session_data.lua
|
||||
|
||||
local Event = require 'utils.event'
|
||||
local play_sessions = require 'session_data'
|
||||
|
||||
local function on_player_changed_position(event)
|
||||
if not global.file_name_found then
|
||||
if global.movement_done < global.movement_amount_required then
|
||||
local player = game.players[event.player_index]
|
||||
global.movement_done = global.movement_done + 1
|
||||
else
|
||||
if string.len(global.file_name) < 16 then
|
||||
if math.random(1,2) == 1 then
|
||||
global.file_name = global.file_name .. string.char(math.random(97,122))
|
||||
else
|
||||
global.file_name = global.file_name .. string.char(math.random(65,90))
|
||||
end
|
||||
global.movement_done = 0
|
||||
end
|
||||
end
|
||||
if string.len(global.file_name) == 16 then
|
||||
global.file_name = global.file_name .. ".lua"
|
||||
--game.print("Session data will be saved as " .. global.file_name,{r = 0.9, g = 0.9, b = 0.9})
|
||||
global.file_name_found = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_player_joined_game(event)
|
||||
if not global.tracker_init_done then
|
||||
global.movement_done = 0
|
||||
global.file_name = ""
|
||||
global.movement_amount_required = 8
|
||||
global.player_totals = {}
|
||||
for _, session in pairs(play_sessions) do
|
||||
for _, player_data in pairs(session) do
|
||||
if not global.player_totals[player_data[1]] then
|
||||
global.player_totals[player_data[1]] = {player_data[2][1]}
|
||||
else
|
||||
global.player_totals[player_data[1]] = {global.player_totals[player_data[1]][1] + player_data[2][1]}
|
||||
end
|
||||
end
|
||||
end
|
||||
global.tracker_init_done = true
|
||||
end
|
||||
end
|
||||
|
||||
local function on_tick()
|
||||
if global.file_name_found then
|
||||
if game.tick % 36000 == 0 then
|
||||
game.remove_path(global.file_name)
|
||||
game.write_file(global.file_name, "local playsession = {\n" , true)
|
||||
for x = 1, #game.players, 1 do
|
||||
local p = game.players[x]
|
||||
local str = ""
|
||||
if game.players[x+1] then str = "," end
|
||||
game.write_file(global.file_name, '\t{"' .. p.name .. '", {' .. p.online_time .. '}}' .. str .. '\n' , true)
|
||||
end
|
||||
game.write_file(global.file_name, "}\nreturn playsession" , true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_tick, on_tick)
|
||||
Event.add(defines.events.on_player_changed_position, on_player_changed_position)
|
||||
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
|
74
utils/PriorityQueue.lua
Normal file
74
utils/PriorityQueue.lua
Normal file
@ -0,0 +1,74 @@
|
||||
local PriorityQueue = {}
|
||||
|
||||
function PriorityQueue.new()
|
||||
return {}
|
||||
end
|
||||
|
||||
local function default_comp(a, b)
|
||||
return a < b
|
||||
end
|
||||
|
||||
local function HeapifyFromEndToStart(queue, comp)
|
||||
comp = comp or default_comp
|
||||
local pos = #queue
|
||||
while pos > 1 do
|
||||
local parent = bit32.rshift(pos, 1) -- integer division by 2
|
||||
if comp(queue[pos], queue[parent]) then
|
||||
queue[pos], queue[parent] = queue[parent], queue[pos]
|
||||
pos = parent
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function HeapifyFromStartToEnd(queue, comp)
|
||||
comp = comp or default_comp
|
||||
local parent = 1
|
||||
local smallest = 1
|
||||
while true do
|
||||
local child = parent * 2
|
||||
if child > #queue then
|
||||
break
|
||||
end
|
||||
if comp(queue[child], queue[parent]) then
|
||||
smallest = child
|
||||
end
|
||||
child = child + 1
|
||||
if child <= #queue and comp(queue[child], queue[smallest]) then
|
||||
smallest = child
|
||||
end
|
||||
|
||||
if parent ~= smallest then
|
||||
queue[parent], queue[smallest] = queue[smallest], queue[parent]
|
||||
parent = smallest
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function PriorityQueue.size(queue)
|
||||
return #queue
|
||||
end
|
||||
|
||||
function PriorityQueue.push(queue, element, comp)
|
||||
table.insert(queue, element)
|
||||
HeapifyFromEndToStart(queue, comp)
|
||||
end
|
||||
|
||||
function PriorityQueue.pop(queue, comp)
|
||||
local element = queue[1]
|
||||
|
||||
queue[1] = queue[#queue]
|
||||
queue[#queue] = nil
|
||||
HeapifyFromStartToEnd(queue, comp)
|
||||
|
||||
return element
|
||||
end
|
||||
|
||||
function PriorityQueue.peek(queue)
|
||||
return queue[1]
|
||||
end
|
||||
|
||||
return PriorityQueue
|
33
utils/Queue.lua
Normal file
33
utils/Queue.lua
Normal file
@ -0,0 +1,33 @@
|
||||
local Queue = {}
|
||||
|
||||
function Queue.new()
|
||||
local queue = {_head = 0, _tail = 0}
|
||||
return queue
|
||||
end
|
||||
|
||||
function Queue.size(queue)
|
||||
return queue._tail - queue._head
|
||||
end
|
||||
|
||||
function Queue.push(queue, element)
|
||||
local index = queue._head
|
||||
queue[index] = element
|
||||
queue._head = index - 1
|
||||
end
|
||||
|
||||
function Queue.peek(queue)
|
||||
return queue[queue._tail]
|
||||
end
|
||||
|
||||
function Queue.pop(queue)
|
||||
local index = queue._tail
|
||||
|
||||
local element = queue[index]
|
||||
queue[index] = nil
|
||||
|
||||
queue._tail = index - 1
|
||||
|
||||
return element
|
||||
end
|
||||
|
||||
return Queue
|
84
utils/Task.lua
Normal file
84
utils/Task.lua
Normal file
@ -0,0 +1,84 @@
|
||||
-- Threading simulation module
|
||||
-- Task.sleep()
|
||||
-- @author Valansch
|
||||
-- github: https://github.com/Valansch/RedMew
|
||||
-- ======================================================= --
|
||||
|
||||
local Queue = require 'utils.Queue'
|
||||
local PriorityQueue = require 'utils.PriorityQueue'
|
||||
local Event = require 'utils.event'
|
||||
local Token = require 'utils.global_token'
|
||||
|
||||
local Task = {}
|
||||
|
||||
global.callbacks = global.callbacks or PriorityQueue.new()
|
||||
global.next_async_callback_time = -1
|
||||
global.task_queue = global.task_queue or Queue.new()
|
||||
global.total_task_weight = 0
|
||||
global.task_queue_speed = 1
|
||||
|
||||
local function comp(a, b)
|
||||
return a.time < b.time
|
||||
end
|
||||
|
||||
local function on_tick()
|
||||
local queue = global.task_queue
|
||||
for i = 1, get_task_per_tick() do
|
||||
local task = Queue.peek(queue)
|
||||
if task ~= nil then
|
||||
-- result is error if not success else result is a boolean for if the task should stay in the queue.
|
||||
local success, result = pcall(Token.get(task.func_token), task.params)
|
||||
if not success then
|
||||
log(result)
|
||||
Queue.pop(queue)
|
||||
global.total_task_weight = global.total_task_weight - task.weight
|
||||
elseif not result then
|
||||
Queue.pop(queue)
|
||||
global.total_task_weight = global.total_task_weight - task.weight
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local callbacks = global.callbacks
|
||||
local callback = PriorityQueue.peek(callbacks)
|
||||
while callback ~= nil and game.tick >= callback.time do
|
||||
local success, error = pcall(Token.get(callback.func_token), callback.params)
|
||||
if not success then
|
||||
log(error)
|
||||
end
|
||||
PriorityQueue.pop(callbacks, comp)
|
||||
callback = PriorityQueue.peek(callbacks)
|
||||
end
|
||||
end
|
||||
|
||||
global.tpt = global.task_queue_speed
|
||||
function get_task_per_tick()
|
||||
if game.tick % 300 == 0 then
|
||||
local size = global.total_task_weight
|
||||
global.tpt = math.floor(math.log10(size + 1)) * global.task_queue_speed
|
||||
if global.tpt < 1 then
|
||||
global.tpt = 1
|
||||
end
|
||||
end
|
||||
return global.tpt
|
||||
end
|
||||
|
||||
function Task.set_timeout_in_ticks(ticks, func_token, params)
|
||||
local time = game.tick + ticks
|
||||
local callback = {time = time, func_token = func_token, params = params}
|
||||
PriorityQueue.push(global.callbacks, callback, comp)
|
||||
end
|
||||
|
||||
function Task.set_timeout(sec, func_token, params)
|
||||
Task.set_timeout_in_ticks(60 * sec, func_token, params)
|
||||
end
|
||||
|
||||
function Task.queue_task(func_token, params, weight)
|
||||
weight = weight or 1
|
||||
global.total_task_weight = global.total_task_weight + weight
|
||||
Queue.push(global.task_queue, {func_token = func_token, params = params, weight = weight})
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_tick, on_tick)
|
||||
|
||||
return Task
|
152
utils/event.lua
Normal file
152
utils/event.lua
Normal file
@ -0,0 +1,152 @@
|
||||
local Event = {}
|
||||
|
||||
local init_event_name = -1
|
||||
local load_event_name = -2
|
||||
|
||||
local control_stage = true
|
||||
|
||||
-- map of event_name to handlers[]
|
||||
local event_handlers = {}
|
||||
-- map of nth_tick to handlers[]
|
||||
local on_nth_tick_event_handlers = {}
|
||||
|
||||
local function call_handlers(handlers, event)
|
||||
if _DEBUG then
|
||||
for _, handler in ipairs(handlers) do
|
||||
handler(event)
|
||||
end
|
||||
else
|
||||
for _, handler in ipairs(handlers) do
|
||||
local success, error = pcall(handler, event)
|
||||
if not success then
|
||||
log(error)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_event(event)
|
||||
local handlers = event_handlers[event.name]
|
||||
call_handlers(handlers, event)
|
||||
end
|
||||
|
||||
local function on_init()
|
||||
local handlers = event_handlers[init_event_name]
|
||||
call_handlers(handlers)
|
||||
end
|
||||
|
||||
local function on_load()
|
||||
local handlers = event_handlers[load_event_name]
|
||||
call_handlers(handlers)
|
||||
end
|
||||
|
||||
local function on_nth_tick_event(event)
|
||||
local handlers = on_nth_tick_event_handlers[event.nth_tick]
|
||||
call_handlers(handlers, event)
|
||||
end
|
||||
|
||||
function Event.add(event_name, handler)
|
||||
local handlers = event_handlers[event_name]
|
||||
if not handlers then
|
||||
event_handlers[event_name] = {handler}
|
||||
script.on_event(event_name, on_event)
|
||||
else
|
||||
table.insert(handlers, handler)
|
||||
end
|
||||
end
|
||||
|
||||
function Event.on_init(handler)
|
||||
local handlers = event_handlers[init_event_name]
|
||||
if not handlers then
|
||||
event_handlers[init_event_name] = {handler}
|
||||
script.on_init(on_init)
|
||||
else
|
||||
table.insert(handlers, handler)
|
||||
end
|
||||
end
|
||||
|
||||
function Event.on_load(handler)
|
||||
local handlers = event_handlers[load_event_name]
|
||||
if not handlers then
|
||||
event_handlers[load_event_name] = {handler}
|
||||
script.on_load(on_load)
|
||||
else
|
||||
table.insert(handlers, handler)
|
||||
end
|
||||
end
|
||||
|
||||
function Event.on_nth_tick(tick, handler)
|
||||
local handlers = on_nth_tick_event_handlers[tick]
|
||||
if not handlers then
|
||||
on_nth_tick_event_handlers[tick] = {handler}
|
||||
script.on_nth_tick(tick, on_nth_tick_event)
|
||||
else
|
||||
table.insert(handlers, handler)
|
||||
end
|
||||
end
|
||||
|
||||
local Token = require 'utils.global_token'
|
||||
global.event_tokens = {}
|
||||
|
||||
function Event.add_removable(event_name, token)
|
||||
local event_tokens = global.event_tokens
|
||||
|
||||
local tokens = event_tokens[event_name]
|
||||
if not tokens then
|
||||
event_tokens[event_name] = {token}
|
||||
else
|
||||
table.insert(tokens, token)
|
||||
end
|
||||
|
||||
if not control_stage then
|
||||
local handler = Token.get(token)
|
||||
Event.add(event_name, handler)
|
||||
end
|
||||
end
|
||||
|
||||
local function remove(t, e)
|
||||
for i, v in ipairs(t) do
|
||||
if v == e then
|
||||
table.remove(t, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Event.remove_removable(event_name, token)
|
||||
local event_tokens = global.event_tokens
|
||||
|
||||
local tokens = event_tokens[event_name]
|
||||
|
||||
if not tokens then
|
||||
return
|
||||
end
|
||||
|
||||
local handler = Token.get(token)
|
||||
local handlers = event_handlers[event_name]
|
||||
|
||||
remove(tokens, token)
|
||||
remove(handlers, handler)
|
||||
|
||||
if #handlers == 0 then
|
||||
script.on_event(event_name, nil)
|
||||
end
|
||||
end
|
||||
|
||||
local function add_token_handlers()
|
||||
control_stage = false
|
||||
|
||||
local event_tokens = global.event_tokens
|
||||
|
||||
for event_name, tokens in pairs(event_tokens) do
|
||||
for _, token in ipairs(tokens) do
|
||||
local handler = Token.get(token)
|
||||
Event.add(event_name, handler)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Event.on_init(add_token_handlers)
|
||||
Event.on_load(add_token_handlers)
|
||||
|
||||
return Event
|
46
utils/global.lua
Normal file
46
utils/global.lua
Normal file
@ -0,0 +1,46 @@
|
||||
local Event = require 'utils.event'
|
||||
local Token = require 'utils.global_token'
|
||||
|
||||
local Global = {}
|
||||
|
||||
local load_data = {}
|
||||
local init_data = {}
|
||||
|
||||
function Global.register(tbl, callback)
|
||||
local token = Token.register_global(tbl)
|
||||
table.insert(load_data, {tbl = tbl, callback = callback, token = token})
|
||||
end
|
||||
|
||||
function Global.register_init(tbl, init_handler, callback)
|
||||
local token = Token.register_global(tbl)
|
||||
table.insert(load_data, {tbl = tbl, callback = callback, token = token})
|
||||
|
||||
table.insert(init_data, {token = token, init_handler = init_handler, callback = callback})
|
||||
end
|
||||
|
||||
Event.on_load(
|
||||
function()
|
||||
for _, d in ipairs(load_data) do
|
||||
local tbl = Token.get_global(d.token)
|
||||
d.callback(tbl)
|
||||
end
|
||||
|
||||
load_data = nil
|
||||
init_data = nil
|
||||
end
|
||||
)
|
||||
|
||||
Event.on_init(
|
||||
function()
|
||||
for _, d in ipairs(init_data) do
|
||||
local tbl = Token.get_global(d.token)
|
||||
d.init_handler(tbl)
|
||||
d.callback(tbl)
|
||||
end
|
||||
|
||||
load_data = nil
|
||||
init_data = nil
|
||||
end
|
||||
)
|
||||
|
||||
return Global
|
45
utils/global_token.lua
Normal file
45
utils/global_token.lua
Normal file
@ -0,0 +1,45 @@
|
||||
local Token = {}
|
||||
|
||||
local tokens = {}
|
||||
|
||||
local counter = 0
|
||||
|
||||
function Token.register(var)
|
||||
counter = counter + 1
|
||||
|
||||
tokens[counter] = var
|
||||
|
||||
return counter
|
||||
end
|
||||
|
||||
function Token.get(token_id)
|
||||
return tokens[token_id]
|
||||
end
|
||||
|
||||
global.tokens = {}
|
||||
|
||||
function Token.register_global(var)
|
||||
local c = #global.tokens + 1
|
||||
|
||||
global.tokens[c] = var
|
||||
|
||||
return c
|
||||
end
|
||||
|
||||
function Token.get_global(token_id)
|
||||
return global.tokens[token_id]
|
||||
end
|
||||
|
||||
function Token.set_global(token_id, var)
|
||||
global.tokens[token_id] = var
|
||||
end
|
||||
|
||||
local uid_counter = 0
|
||||
|
||||
function Token.uid()
|
||||
uid_counter = uid_counter + 1
|
||||
|
||||
return uid_counter
|
||||
end
|
||||
|
||||
return Token
|
145
utils/gui.lua
Normal file
145
utils/gui.lua
Normal file
@ -0,0 +1,145 @@
|
||||
local Token = require 'utils.global_token'
|
||||
local Event = require 'utils.event'
|
||||
|
||||
local Gui = {}
|
||||
|
||||
global.Gui_data = {}
|
||||
|
||||
function Gui.uid_name()
|
||||
if _DEBUG then
|
||||
-- https://stackoverflow.com/questions/48402876/getting-current-file-name-in-lua
|
||||
local filename = debug.getinfo(2, 'S').source:match('^.+/(.+)$'):sub(1, -5)
|
||||
return filename .. ',' .. Token.uid()
|
||||
else
|
||||
return tostring(Token.uid())
|
||||
end
|
||||
end
|
||||
|
||||
-- Associates data with the LuaGuiElement. If data is nil then removes the data
|
||||
function Gui.set_data(element, data)
|
||||
global.Gui_data[element.player_index * 0x100000000 + element.index] = data
|
||||
end
|
||||
|
||||
-- Gets the Associated data with this LuaGuiElement if any.
|
||||
function Gui.get_data(element)
|
||||
return global.Gui_data[element.player_index * 0x100000000 + element.index]
|
||||
end
|
||||
|
||||
-- Removes data associated with LuaGuiElement and its children recursivly.
|
||||
function Gui.remove_data_recursivly(element)
|
||||
Gui.set_data(element, nil)
|
||||
|
||||
local children = element.children
|
||||
|
||||
if not children then
|
||||
return
|
||||
end
|
||||
|
||||
for _, child in ipairs(children) do
|
||||
if child.valid then
|
||||
Gui.remove_data_recursivly(child)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Gui.remove_children_data(element)
|
||||
local children = element.children
|
||||
|
||||
if not children then
|
||||
return
|
||||
end
|
||||
|
||||
for _, child in ipairs(children) do
|
||||
if child.valid then
|
||||
Gui.set_data(child, nil)
|
||||
Gui.remove_children_data(child)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Gui.destroy(element)
|
||||
Gui.remove_data_recursivly(element)
|
||||
element.destroy()
|
||||
end
|
||||
|
||||
function Gui.clear(element)
|
||||
Gui.remove_children_data(element)
|
||||
element.clear()
|
||||
end
|
||||
|
||||
local function handler_factory(event_id)
|
||||
local handlers
|
||||
|
||||
local function on_event(event)
|
||||
local element = event.element
|
||||
if not element or not element.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local handler = handlers[element.name]
|
||||
if not handler then
|
||||
return
|
||||
end
|
||||
|
||||
local player = game.players[event.player_index]
|
||||
if not player or not player.valid then
|
||||
return
|
||||
end
|
||||
event.player = player
|
||||
|
||||
handler(event)
|
||||
end
|
||||
|
||||
return function(element_name, handler)
|
||||
if not handlers then
|
||||
handlers = {}
|
||||
Event.add(event_id, on_event)
|
||||
end
|
||||
|
||||
handlers[element_name] = handler
|
||||
end
|
||||
end
|
||||
|
||||
-- Register a handler for the on_gui_checked_state_changed event for LuaGuiElements with element_name.
|
||||
-- Can only have one handler per element name.
|
||||
-- Guarantees that the element and the player are valid when calling the handler.
|
||||
-- Adds a player field to the event table.
|
||||
Gui.on_checked_state_changed = handler_factory(defines.events.on_gui_checked_state_changed)
|
||||
|
||||
-- Register a handler for the on_gui_click event for LuaGuiElements with element_name.
|
||||
-- Can only have one handler per element name.
|
||||
-- Guarantees that the element and the player are valid when calling the handler.
|
||||
-- Adds a player field to the event table.
|
||||
Gui.on_click = handler_factory(defines.events.on_gui_click)
|
||||
|
||||
-- Register a handler for the on_gui_closed event for a custom LuaGuiElements with element_name.
|
||||
-- Can only have one handler per element name.
|
||||
-- Guarantees that the element and the player are valid when calling the handler.
|
||||
-- Adds a player field to the event table.
|
||||
Gui.on_custom_close = handler_factory(defines.events.on_gui_closed)
|
||||
|
||||
-- Register a handler for the on_gui_elem_changed event for LuaGuiElements with element_name.
|
||||
-- Can only have one handler per element name.
|
||||
-- Guarantees that the element and the player are valid when calling the handler.
|
||||
-- Adds a player field to the event table.
|
||||
Gui.on_elem_changed = handler_factory(defines.events.on_gui_elem_changed)
|
||||
|
||||
-- Register a handler for the on_gui_selection_state_changed event for LuaGuiElements with element_name.
|
||||
-- Can only have one handler per element name.
|
||||
-- Guarantees that the element and the player are valid when calling the handler.
|
||||
-- Adds a player field to the event table.
|
||||
Gui.on_selection_state_changed = handler_factory(defines.events.on_gui_selection_state_changed)
|
||||
|
||||
-- Register a handler for the on_gui_text_changed event for LuaGuiElements with element_name.
|
||||
-- Can only have one handler per element name.
|
||||
-- Guarantees that the element and the player are valid when calling the handler.
|
||||
-- Adds a player field to the event table.
|
||||
Gui.on_text_changed = handler_factory(defines.events.on_gui_text_changed)
|
||||
|
||||
-- Register a handler for the on_gui_value_changed event for LuaGuiElements with element_name.
|
||||
-- Can only have one handler per element name.
|
||||
-- Guarantees that the element and the player are valid when calling the handler.
|
||||
-- Adds a player field to the event table.
|
||||
Gui.on_value_changed = handler_factory(defines.events.on_gui_value_changed)
|
||||
|
||||
return Gui
|
123
utils/list_utils.lua
Normal file
123
utils/list_utils.lua
Normal file
@ -0,0 +1,123 @@
|
||||
local function assert_argument_valid(a, arg_type)
|
||||
arg_type = arg_type or "table"
|
||||
if type(a) ~= arg_type then
|
||||
error("bad argument #1 to '" .. debug.getinfo(2, "n").name .. "' (table expected, got ".. type(a) .. ")", 3)
|
||||
end
|
||||
end
|
||||
|
||||
table.remove_element = function(t, element)
|
||||
assert_argument_valid(t)
|
||||
for k,v in pairs(t) do
|
||||
if v == element then
|
||||
table.remove(t, k)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
table.add_all = function (t1, t2)
|
||||
assert_argument_valid(t1)
|
||||
assert_argument_valid(t2)
|
||||
for k,v in pairs(t2) do
|
||||
if tonumber(k) then
|
||||
table.insert(t1, v)
|
||||
else
|
||||
t1[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
table.size = function(t)
|
||||
assert_argument_valid(t)
|
||||
local size = 0
|
||||
for _,_ in pairs(t) do size = size + 1 end
|
||||
return size
|
||||
end
|
||||
|
||||
table.index_of = function(t, e)
|
||||
assert_argument_valid(t)
|
||||
local i = 1
|
||||
for _,v in pairs(t) do
|
||||
if v == e then
|
||||
return i
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
return -1
|
||||
end
|
||||
|
||||
table.contains = function(t, e)
|
||||
assert_argument_valid(t)
|
||||
return table.index_of(t, e) > -1
|
||||
end
|
||||
|
||||
table.set = function (t, index, element)
|
||||
assert_argument_valid(t)
|
||||
assert_argument_valid(index, "number")
|
||||
local i = 1
|
||||
for k,v in pairs(t) do
|
||||
if i == index then
|
||||
t[k] = element
|
||||
return nil
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
error("Index out of bounds", 2)
|
||||
end
|
||||
|
||||
table.get = function (t, index)
|
||||
assert_argument_valid(t)
|
||||
assert_argument_valid(index, "number")
|
||||
local i = 1
|
||||
for k,v in pairs(t) do
|
||||
if i == index then
|
||||
return t[k]
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
error("Index out of bounds", 2)
|
||||
end
|
||||
|
||||
--[[
|
||||
Returns the index where t[index] == target.
|
||||
If there is no such index, returns a negative vaule such that bit32.bnot(value) is
|
||||
the index that the vaule should be inserted to keep the list ordered.
|
||||
t must be a list in ascending order for the return value to be valid.
|
||||
|
||||
Usage example:
|
||||
local t = {1,3,5,7,9}
|
||||
local x = 5
|
||||
local index = table.binary_search(t, x)
|
||||
if index < 0 then
|
||||
game.print("value not found, smallest index where t[index] > x is: " .. bit32.bnot(index))
|
||||
else
|
||||
game.print("value found at index: " .. index)
|
||||
end
|
||||
]]
|
||||
table.binary_search = function(t, target)
|
||||
--For some reason bit32.bnot doesn't return negative numbers so I'm using ~x = -1 - x instead.
|
||||
assert_argument_valid(t)
|
||||
assert_argument_valid(target, "number")
|
||||
|
||||
local lower = 1
|
||||
local upper = #t
|
||||
|
||||
if upper == 0 then
|
||||
return -2 -- ~1
|
||||
end
|
||||
|
||||
repeat
|
||||
local mid = math.floor( (lower + upper) / 2 )
|
||||
local value = t[mid]
|
||||
if value == target then
|
||||
return mid
|
||||
elseif value < target then
|
||||
lower = mid + 1
|
||||
else
|
||||
upper = mid - 1
|
||||
end
|
||||
until lower > upper
|
||||
|
||||
return -1 - lower -- ~lower
|
||||
|
||||
end
|
106
utils/simplex_noise.lua
Normal file
106
utils/simplex_noise.lua
Normal file
@ -0,0 +1,106 @@
|
||||
--from https://github.com/thenumbernine/lua-simplexnoise/blob/master/2d.lua
|
||||
--Mostly as a test, does not give same results as perlin but is designed to give patterns all the same
|
||||
|
||||
local Simplex = {}
|
||||
|
||||
-- 2D simplex noise
|
||||
|
||||
local grad3 = {
|
||||
{1,1,0},{-1,1,0},{1,-1,0},{-1,-1,0},
|
||||
{1,0,1},{-1,0,1},{1,0,-1},{-1,0,-1},
|
||||
{0,1,1},{0,-1,1},{0,1,-1},{0,-1,-1}
|
||||
}
|
||||
|
||||
local p = {151,160,137,91,90,15,
|
||||
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
|
||||
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
|
||||
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
|
||||
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
|
||||
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
|
||||
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
|
||||
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
|
||||
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
|
||||
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
|
||||
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
|
||||
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
|
||||
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180}
|
||||
local perm = {}
|
||||
for i=0,511 do
|
||||
perm[i+1] = p[bit32.band(i, 255) + 1]
|
||||
end
|
||||
|
||||
local function dot(g, ...)
|
||||
local v = {...}
|
||||
local sum = 0
|
||||
for i=1,#v do
|
||||
sum = sum + v[i] * g[i]
|
||||
end
|
||||
return sum
|
||||
end
|
||||
|
||||
function Simplex.d2(xin, yin,seed)
|
||||
xin = xin + seed
|
||||
yin = yin + seed
|
||||
local n0, n1, n2 -- Noise contributions from the three corners
|
||||
-- Skew the input space to determine which simplex cell we're in
|
||||
local F2 = 0.5*(math.sqrt(3.0)-1.0)
|
||||
local s = (xin+yin)*F2; -- Hairy factor for 2D
|
||||
local i = math.floor(xin+s)
|
||||
local j = math.floor(yin+s)
|
||||
local G2 = (3.0-math.sqrt(3.0))/6.0
|
||||
local t = (i+j)*G2
|
||||
local X0 = i-t -- Unskew the cell origin back to (x,y) space
|
||||
local Y0 = j-t
|
||||
local x0 = xin-X0 -- The x,y distances from the cell origin
|
||||
local y0 = yin-Y0
|
||||
-- For the 2D case, the simplex shape is an equilateral triangle.
|
||||
-- Determine which simplex we are in.
|
||||
local i1, j1 -- Offsets for second (middle) corner of simplex in (i,j) coords
|
||||
if x0 > y0 then
|
||||
i1 = 1
|
||||
j1 = 0 -- lower triangle, XY order: (0,0)->(1,0)->(1,1)
|
||||
else
|
||||
i1 = 0
|
||||
j1 = 1
|
||||
end-- upper triangle, YX order: (0,0)->(0,1)->(1,1)
|
||||
-- A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
|
||||
-- a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
|
||||
-- c = (3-sqrt(3))/6
|
||||
local x1 = x0 - i1 + G2 -- Offsets for middle corner in (x,y) unskewed coords
|
||||
local y1 = y0 - j1 + G2
|
||||
local x2 = x0 - 1 + 2 * G2 -- Offsets for last corner in (x,y) unskewed coords
|
||||
local y2 = y0 - 1 + 2 * G2
|
||||
-- Work out the hashed gradient indices of the three simplex corners
|
||||
local ii = bit32.band(i, 255)
|
||||
local jj = bit32.band(j, 255)
|
||||
local gi0 = perm[ii + perm[jj+1]+1] % 12
|
||||
local gi1 = perm[ii + i1 + perm[jj + j1+1]+1] % 12
|
||||
local gi2 = perm[ii + 1 + perm[jj + 1+1]+1] % 12
|
||||
-- Calculate the contribution from the three corners
|
||||
local t0 = 0.5 - x0 * x0 - y0 * y0
|
||||
if t0 < 0 then
|
||||
n0 = 0.0
|
||||
else
|
||||
t0 = t0 * t0
|
||||
n0 = t0 * t0 * dot(grad3[gi0+1], x0, y0) -- (x,y) of grad3 used for 2D gradient
|
||||
end
|
||||
local t1 = 0.5 - x1 * x1 - y1 * y1
|
||||
if t1 < 0 then
|
||||
n1 = 0.0
|
||||
else
|
||||
t1 = t1 * t1
|
||||
n1 = t1 * t1 * dot(grad3[gi1+1], x1, y1)
|
||||
end
|
||||
local t2 = 0.5 - x2 * x2 - y2 * y2
|
||||
if t2 < 0 then
|
||||
n2 = 0.0
|
||||
else
|
||||
t2 = t2 * t2
|
||||
n2 = t2 * t2 * dot(grad3[gi2+1], x2, y2)
|
||||
end
|
||||
-- Add contributions from each corner to get the final noise value.
|
||||
-- The result is scaled to return values in the interval [-1,1].
|
||||
return 70.0 * (n0 + n1 + n2)
|
||||
end
|
||||
|
||||
return Simplex
|
131
utils/utils.lua
Normal file
131
utils/utils.lua
Normal file
@ -0,0 +1,131 @@
|
||||
local Module = {}
|
||||
|
||||
Module.distance = function(pos1, pos2)
|
||||
local dx = pos2.x - pos1.x
|
||||
local dy = pos2.y - pos1.y
|
||||
return math.sqrt(dx * dx + dy * dy)
|
||||
end
|
||||
|
||||
-- rounds number (num) to certain number of decimal places (idp)
|
||||
math.round = function(num, idp)
|
||||
local mult = 10 ^ (idp or 0)
|
||||
return math.floor(num * mult + 0.5) / mult
|
||||
end
|
||||
|
||||
function math.clamp(num, min, max)
|
||||
if num < min then
|
||||
return min
|
||||
elseif num > max then
|
||||
return max
|
||||
else
|
||||
return num
|
||||
end
|
||||
end
|
||||
|
||||
Module.print_except = function(msg, player)
|
||||
for _, p in pairs(game.players) do
|
||||
if p.connected and p ~= player then
|
||||
p.print(msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Module.print_admins = function(msg)
|
||||
for _, p in pairs(game.players) do
|
||||
if p.connected and p.admin then
|
||||
p.print(msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Module.get_actor = function()
|
||||
if game.player then
|
||||
return game.player.name
|
||||
end
|
||||
return '<server>'
|
||||
end
|
||||
|
||||
Module.cast_bool = function(var)
|
||||
if var then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
Module.find_entities_by_last_user =
|
||||
function(player, surface, filters)
|
||||
if type(player) == 'string' or not player then
|
||||
error(
|
||||
"bad argument #1 to '" ..
|
||||
debug.getinfo(1, 'n').name .. "' (number or LuaPlayer expected, got " .. type(player) .. ')',
|
||||
1
|
||||
)
|
||||
return
|
||||
end
|
||||
if type(surface) ~= 'table' and type(surface) ~= 'number' then
|
||||
error(
|
||||
"bad argument #2 to '" ..
|
||||
debug.getinfo(1, 'n').name .. "' (number or LuaSurface expected, got " .. type(surface) .. ')',
|
||||
1
|
||||
)
|
||||
return
|
||||
end
|
||||
local entities = {}
|
||||
local surface = surface
|
||||
local player = player
|
||||
local filters = filters or {}
|
||||
if type(surface) == 'number' then
|
||||
surface = game.surfaces[surface]
|
||||
end
|
||||
if type(player) == 'number' then
|
||||
player = game.players[player]
|
||||
end
|
||||
filters.force = player.force.name
|
||||
for _, e in pairs(surface.find_entities_filtered(filters)) do
|
||||
if e.last_user == player then
|
||||
table.insert(entities, e)
|
||||
end
|
||||
end
|
||||
return entities
|
||||
end
|
||||
|
||||
Module.ternary = function(c, t, f)
|
||||
if c then
|
||||
return t
|
||||
else
|
||||
return f
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local minutes_to_ticks = 60 * 60
|
||||
local hours_to_ticks = 60 * 60 * 60
|
||||
local ticks_to_minutes = 1 / minutes_to_ticks
|
||||
local ticks_to_hours = 1 / hours_to_ticks
|
||||
Module.format_time = function(ticks)
|
||||
local result = {}
|
||||
|
||||
local hours = math.floor(ticks * ticks_to_hours)
|
||||
if hours > 0 then
|
||||
ticks = ticks - hours * hours_to_ticks
|
||||
table.insert(result, hours)
|
||||
if hours == 1 then
|
||||
table.insert(result, 'hour')
|
||||
else
|
||||
table.insert(result, 'hours')
|
||||
end
|
||||
end
|
||||
|
||||
local minutes = math.floor(ticks * ticks_to_minutes)
|
||||
table.insert(result, minutes)
|
||||
if minutes == 1 then
|
||||
table.insert(result, 'minute')
|
||||
else
|
||||
table.insert(result, 'minutes')
|
||||
end
|
||||
|
||||
return table.concat(result, ' ')
|
||||
end
|
||||
|
||||
return Module
|
Loading…
x
Reference in New Issue
Block a user