1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2024-12-26 22:56:43 +02:00

Misc tweaks and bug fixes

This commit is contained in:
Gerkiz 2024-10-21 15:43:41 +02:00
parent f5f9b86f2f
commit b09b781902
14 changed files with 69 additions and 1340 deletions

View File

@ -244,7 +244,8 @@ stds.factorio_control = {
'mod_name',
'get_event_order',
'generate_event_name',
'register_on_entity_destroyed'
'register_on_entity_destroyed',
'active_mods'
},
other_fields = false
},
@ -479,6 +480,7 @@ stds.factorio_control = {
-- Writing access is given to the mod-id field (for mod-wise saved data).
-- (http://lua-api.factorio.com/latest/storage.html)
'storage',
'helpers',
-- @MOD@: Keep it organized, use this variable for anything that "NEEDS" to be global for some reason.
'MOD'
}

View File

@ -64,6 +64,7 @@ coins_left=Coins left: __1__
market_name=Market
search_text=Search:
quantity_text=Quantity:
quality_text=Quality:
limit_reached=Max limit reached!
chests_full=You can't purchase more chests.
chest_bought_info=__1__ __2__ has bought the chest limit upgrade for __3__ coins.

View File

@ -597,6 +597,8 @@ local wake_up_the_biters = function (surface)
FDT.set('spawned_biters', actual_biters)
end
print('Waking up idle biters!')
surface.set_multi_command(
{
command = {
@ -1458,6 +1460,10 @@ local on_tick = function ()
end
end
if game.tick % 2000 == 0 then
wake_up_the_biters(surface)
end
if game.tick % this.wave_interval == this.wave_interval - 1 then
if surface.peaceful_mode == true then
return

View File

@ -4,7 +4,6 @@
local Public = require 'maps.fish_defender_v2.core'
local Gui = require 'utils.gui'
require 'modules.rocket_launch_always_yields_science'
require 'modules.launch_fish_to_win'
require 'modules.biters_yield_coins'
require 'modules.custom_death_messages'
@ -1211,6 +1210,12 @@ local function on_robot_built_entity(event)
end
end
local function on_rocket_launched(event)
local rocket_inventory = event.rocket.cargo_pod.get_inventory(defines.inventory.cargo_unit)
rocket_inventory.clear()
rocket_inventory.insert({ name = 'space-science-pack', count = 200 })
end
local function on_player_changed_position(event)
local player = game.get_player(event.player_index)
local active_surface_index = Public.get('active_surface_index')
@ -1627,6 +1632,7 @@ end
local on_init = Public.on_init
Event.add(defines.events.on_rocket_launched, on_rocket_launched)
Event.add(defines.events.on_gui_click, on_gui_click)
Event.add(defines.events.on_market_item_purchased, on_market_item_purchased)
Event.add(defines.events.on_player_respawned, on_player_respawned)

View File

@ -1,983 +0,0 @@
--luacheck: ignore
local Event = require 'utils.event'
local simplex_noise = require 'utils.math.simplex_noise'.d2
local NoiseVectors = require 'utils.functions.noise_vector_path'
local MapFunctions = require 'utils.tools.map_functions'
local Scheduler = require 'utils.scheduler'
local island_radius = 6
local random = math.random
local sqrt = math.sqrt
local abs = math.abs
local ceil = math.ceil
local floor = math.floor
local rock_raffle = {
'big-sand-rock',
'big-sand-rock',
'big-rock',
'big-rock',
'big-rock',
'big-rock',
'big-rock',
'big-rock',
'huge-rock'
}
local draw_path_tile_whitelist = {
['water'] = true,
['deepwater'] = true
}
local path_tile_names = {
'grass-2',
'grass-3',
'grass-4',
'dirt-1',
'dirt-2',
'dirt-3',
'dirt-4',
'dirt-5',
'dirt-6',
'dirt-7'
}
local function get_brush_unfiltered(size)
local vectors = {}
for x = size, size * -1, -1 do
for y = size * -1, size, 1 do
vectors[#vectors + 1] = { x = x, y = y }
end
end
return vectors
end
local function get_vector(position)
if position.x < 0 and position.y < 0 then
return { -1, -1 }
end
if position.x > 0 and position.y > 0 then
return { 1, 1 }
end
if position.x > 0 and position.y < 0 then
return { 1, -1 }
end
if position.x < 0 and position.y > 0 then
return { -1, 1 }
end
end
local function add_path_decoratives(surface, tiles)
local d = storage.decorative_names[random(1, #storage.decorative_names)]
for _, t in pairs(tiles) do
local noise = simplex_noise(t.position.x * 0.075, t.position.y * 0.075, game.surfaces[1].map_gen_settings.seed)
if random(1, 3) == 1 and noise > 0 then
surface.create_decoratives { check_collision = false, decoratives = { { name = d, position = t.position, amount = floor(abs(noise * 3)) + 1 } } }
end
end
end
local place_bridge_token =
Scheduler.set(
function (event)
log(serpent.block('place_bridge_token'))
local surface = event.surface
-- add_path_decoratives(surface, storage.old_path_tiles)
for _, tile in pairs(storage.old_path_tiles) do
local new_tile = surface.get_tile(tile.position)
if new_tile and new_tile.valid and new_tile.name == 'water' then
surface.set_tiles({ { name = tile.name, position = tile.position } })
end
end
storage.old_path_tiles = nil
end
)
local slowly_place_brige_tiles_token =
Scheduler.set(
function (event)
local positions = event.positions
local surface = event.surface
log(serpent.block('setting tiles'))
surface.set_tiles(positions, true)
end
)
local calculate_bridge_token =
Scheduler.set(
function (event)
local seed_1 = event.seed_1
local seed_2 = event.seed_2
local m = event.m
local vector = event.vector
local base_vector = event.base_vector
local minimal_movement = event.minimal_movement
local position = storage.position
local surface = event.surface
local whitelist = event.whitelist
local tile_name = event.tile_name
local brush_vectors = event.brush_vectors
local tick_index = event.tick_index
local positions = {}
for _, brush in pairs(brush_vectors) do
local p = { x = position.x + brush.x, y = position.y + brush.y }
if whitelist then
local tile = surface.get_tile(p)
if tile.valid then
if whitelist[tile.name] then
storage.path_tiles[#storage.path_tiles + 1] = { name = tile_name, position = p }
positions[#positions + 1] = { name = tile_name, position = p }
end
end
end
end
Scheduler.timeout(tick_index, slowly_place_brige_tiles_token, { positions = positions, surface = surface })
-- surface.set_tiles(positions, true)
storage.old_path_tiles = storage.path_tiles
local noise = simplex_noise(position.x * m, position.y * m, seed_1)
local noise_2 = simplex_noise(position.x * m, position.y * m, seed_2)
vector[1] = base_vector[1] + noise
vector[2] = base_vector[2] + noise_2
if abs(vector[1]) < minimal_movement and abs(vector[2]) < minimal_movement then
local i = random(1, 2)
if vector[i] < 0 then
vector[i] = minimal_movement * -1
else
vector[i] = minimal_movement
end
end
storage.position = { x = position.x + vector[1], y = position.y + vector[2] }
end
)
local noise_vector_tiles_path_token =
Scheduler.set(
function (event)
local surface = event.surface
local tbl_tiles = event.tbl_tiles
local position = storage.position
local length = event.length
local brush_size = event.brush_size
local whitelist = event.whitelist
local seed_1 = event.seed_1
local seed_2 = event.seed_2
local m = event.m
storage.vector = {}
local minimal_movement = 0.40
local brush_vectors = get_brush_unfiltered(brush_size)
local tile_name = tbl_tiles[random(1, #tbl_tiles)]
local base_vector = get_vector(position)
game.print(serpent.block(base_vector))
if (base_vector[1] == 1 or base_vector[1] == -1) and random(1, 2) == 1 then
base_vector = { base_vector[1], 1 }
end
local callback = Scheduler.get(calculate_bridge_token)
Scheduler.return_callback(
function (data)
for _ = 1, length, 1 do
data.tick_index = data.tick_index + 10
callback(
{
seed_1 = seed_1,
seed_2 = seed_2,
m = m,
vector = storage.vector,
base_vector = base_vector,
minimal_movement = minimal_movement,
position = position,
surface = surface,
whitelist = whitelist,
tile_name = tile_name,
brush_vectors = brush_vectors,
tick_index = data.tick_index
}
)
data.tick_index = data.tick_index + 1
end
end
)
end
)
local function shuffle(tbl)
local size = #tbl
for i = size, 1, -1 do
local rand = random(size)
tbl[i], tbl[rand] = tbl[rand], tbl[i]
end
return tbl
end
local function is_inside_island(x, y, radius)
radius = radius or island_radius
local distance_to_center = sqrt(x ^ 2 + y ^ 2)
return distance_to_center < radius
end
local request_to_generate_chunks_token =
Scheduler.set(
function (event)
local size = event.size
local surface = event.surface
local position = event.position or storage.path_tiles[#storage.path_tiles].position
surface.request_to_generate_chunks(position, size)
game.surfaces['island'].request_to_generate_chunks(position, size)
log(serpent.block('generating chunks'))
log(serpent.block(game.tick))
end
)
local function resource_placement(surface, position, name, amount, tiles)
local w_max = 256
local h_max = 256
local biases = { [0] = { [0] = 1 } }
local ti = 1
local function grow(grid, t)
local old = {}
local new_count = 0
for x, _ in pairs(grid) do
for y, _ in pairs(_) do
table.insert(old, { x, y })
end
end
for _, pos in pairs(old) do
local x, y = pos[1], pos[2]
for dx = -1, 1, 1 do
for dy = -1, 1, 1 do
local a, b = x + dx, y + dy
if (random() > 0.9) and (abs(a) < w_max) and (abs(b) < h_max) then
grid[a] = grid[a] or {}
if not grid[a][b] then
grid[a][b] = 1 - (t / tiles)
new_count = new_count + 1
if (new_count + t) == tiles then
return new_count
end
end
end
end
end
end
return new_count
end
repeat
ti = ti + grow(biases, ti)
until ti >= tiles
local total_bias = 0
for _, d in pairs(biases) do
for _, bias in pairs(d) do
total_bias = total_bias + bias
end
end
for x, _ in pairs(biases) do
for y, bias in pairs(_) do
local c = amount * (bias / total_bias)
if c < 1 then
c = 1
end
surface.create_entity {
name = name,
amount = c,
force = 'neutral',
position = { position.x + x, position.y + y }
}
end
end
end
local function island_noise(p, seed_1, seed_2, seed_3, divided_by)
local noise_1 = simplex_noise(p.x * seed_m1, p.y * seed_m1, seed_1)
local noise_2 = simplex_noise(p.x * seed_m2, p.y * seed_m2, seed_2)
local noise_3 = simplex_noise(p.x * seed_m3, p.y * seed_m3, seed_3)
local noise = abs(noise_1 + noise_2 + noise_3)
divided_by = divided_by or 2.3
noise = noise / divided_by
return noise
end
local function find_dirt_tiles(surface, positions)
local tiles = {}
for i = 1, 8, 1 do
local vectors = { { 1, i }, { -1, i * -1 }, { i, 1 }, { i * -1, -1 } }
if storage.current_stage == 1 then
vectors = shuffle(vectors)
end
for _, v in pairs(vectors) do
for _, tile_data in pairs(positions) do
local pos = { x = tile_data.position.x + v[1], y = tile_data.position.y + v[2] }
local tile = surface.get_tile(pos)
if tile and tile.valid and tile.name ~= 'water' then
tiles[#tiles + 1] = tile.position
end
end
end
end
return tiles
end
function find_dirt_tile(surface, position)
for i = 1, 64, 1 do
local vectors = { { 1, i }, { -1, i * -1 }, { i, 1 }, { i * -1, -1 } }
if storage.current_stage == 1 then
vectors = shuffle(vectors)
end
for _, v in pairs(vectors) do
local pos = { x = position.x + v[1], y = position.y + v[2] }
local tile = surface.get_tile(pos)
if tile and tile.valid and tile.name == 'water' then
return tile.position
end
end
end
end
local function get_radius(position, size, divided_by)
local noise = island_noise(position, seed_1, seed_2, seed_3, divided_by)
local rr = size
return rr * 0.5 + noise * rr * 0.5
end
local function print_grid_value(value, surface, position, scale, offset)
if not storage.debug_island_values then
return
end
local is_string = type(value) == 'string'
local color = { r = 1, g = 1, b = 1 }
local text = value
if not is_string then
scale = scale or 1
offset = offset or 0
position = { x = position.x + offset, y = position.y + offset }
local r = math.max(1, value) / scale
local g = 1 - abs(value) / scale
local b = math.min(1, value) / scale
if (r > 0) then
r = 0
end
if (b < 0) then
b = 0
end
if (g < 0) then
g = 0
end
r = abs(r)
color = { r = r, g = g, b = b }
text = floor(100 * value) * 0.01
if (0 == text) then
text = '0.00'
end
end
text = tostring(text)
local text_entity = surface.find_entity('flying-text', position)
if text_entity then
text_entity.text = text
text_entity.color = color
return
end
surface.create_entity {
name = 'flying-text',
color = color,
text = text,
position = position
}.active = false
end
local place_tiles_token =
Scheduler.set(
function (event)
local positions = event.positions
local position = event.position
local radius = event.radius
local count = event.count
local surface = event.surface
storage.market_positions = storage.market_positions or {}
storage.tiles = storage.tiles or {}
local tiles = {}
for i = 1, count do
local x = positions[i].x
local y = positions[i].y
local p = { x = x + position.x, y = y + position.y }
local tile_data = surface.get_tile(p)
if tile_data and tile_data.valid and (tile_data.name == 'water' or tile_data.name == 'deepwater') then
local distance = sqrt(x ^ 2 + y ^ 2)
local tile
local watery_tile
local noise_radius = get_radius(p, radius)
local market_radius = get_radius(p, radius - 10, 22)
local main_tile = game.surfaces['island'].get_tile(x, y)
if distance > market_radius - (radius + 4) * 0.135 and distance < market_radius - (radius - 4) * 0.135 then
if main_tile and main_tile.valid and distance < radius then
tile = { name = main_tile.name, position = p }
end
storage.market_positions[#storage.market_positions + 1] = p
print_grid_value(noise_radius, surface, p, 2, 0)
end
if distance < noise_radius - radius * 0.15 then
if main_tile and main_tile.valid then
tile = { name = main_tile.name, position = p }
end
elseif distance < noise_radius - 10 then
watery_tile = { name = 'deepwater', position = p }
end
if tile then
tiles[#tiles + 1] = tile
storage.tiles[#storage.tiles + 1] = tile
end
if watery_tile then
tiles[#tiles + 1] = watery_tile
end
end
end
game.forces.player.chart(surface, { { position.x - 124, position.y - 124 }, { position.x + 124, position.y + 124 } })
surface.set_tiles(tiles, true)
end
)
local do_place_decorative_token =
Scheduler.set(
function (event)
local count = event.count
local pos_tbl = event.pos_tbl
local surface = event.surface
for i = 1, count do
local decorative = pos_tbl[i]
if decorative then
local position = decorative.position
local name = decorative.name
local amount = decorative.amount
surface.create_decoratives {
check_collision = true,
decoratives = { { name = name, position = position, amount = amount } }
}
end
end
end
)
local do_place_simple_entities_token =
Scheduler.set(
function (event)
local count = event.count
local pos_tbl = event.pos_tbl
local surface = event.surface
local seed = event.seed
local tree = storage.tree_raffle[random(1, #storage.tree_raffle)]
for i = 1, count do
local position = pos_tbl[i]
if position then
if random(1, 32) == 1 then
local noise = simplex_noise(position.x * 0.02, position.y * 0.02, seed)
if noise > 0.75 or noise < -0.75 then
surface.create_entity({ name = rock_raffle[random(1, #rock_raffle)], position = position })
end
end
if surface.can_place_entity({ name = 'wooden-chest', position = position }) then
if random(1, 64) == 1 then
if simplex_noise(position.x * 0.02, position.y * 0.02, seed) > 0.25 then
surface.create_entity({ name = tree, position = position })
end
end
end
if surface.can_place_entity({ name = 'wooden-chest', position = position }) then
if random(1, 128) == 1 then
if simplex_noise(position.x * 0.02, position.y * 0.02, seed) > 0.25 then
local corpse = storage.corpses_raffle[random(1, #storage.corpses_raffle)]
local c = surface.create_entity({ name = corpse, position = position })
if c and c.valid then
c.corpse_expires = false
end
end
end
end
end
end
end
)
local create_new_surface_token =
Scheduler.set(
function (event)
if game.surfaces['island'] then
return
end
local radius = event.radius
local map_gen_settings = {}
map_gen_settings.height = radius
map_gen_settings.width = radius
map_gen_settings.water = 0.001
map_gen_settings.terrain_segmentation = 8
map_gen_settings.seed = random(1, 999999999)
map_gen_settings.cliff_settings = { cliff_elevation_interval = random(2, 16), cliff_elevation_0 = random(2, 16) }
map_gen_settings.autoplace_controls = {
['coal'] = { frequency = 0, size = 0, richness = 0 },
['stone'] = { frequency = 0, size = 0, richness = 0 },
['copper-ore'] = { frequency = 0, size = 0, richness = 0 },
['iron-ore'] = { frequency = 0, size = 0, richness = 0 },
['uranium-ore'] = { frequency = 0, size = 0, richness = 0 },
['crude-oil'] = { frequency = 0, size = 0, richness = 0 },
['trees'] = { frequency = 50, size = 0.1, richness = random(0, 10) * 0.1 },
['enemy-base'] = { frequency = 'none', size = 'none', richness = 'none' }
}
map_gen_settings.autoplace_settings = {
['tile'] = {
settings = {
['deepwater'] = { frequency = 1, size = 0, richness = 1 },
['deepwater-green'] = { frequency = 1, size = 0, richness = 1 },
['water'] = { frequency = 1, size = 0, richness = 1 },
['water-green'] = { frequency = 1, size = 0, richness = 1 },
['water-mud'] = { frequency = 1, size = 0, richness = 1 },
['water-shallow'] = { frequency = 1, size = 0, richness = 1 }
},
treat_missing_as_default = true
}
}
map_gen_settings.property_expression_names = {
['control-setting:aux:bias'] = '-0.500000',
['control-setting:moisture:bias'] = '0.500000',
['control-setting:moisture:frequency:multiplier'] = '4.000000',
['starting-lake-noise-amplitude'] = 0,
['starting-area'] = 0
}
if not game.surfaces['island'] then
game.create_surface('island', map_gen_settings)
local surface = game.surfaces['island']
---@diagnostic disable-next-line: param-type-mismatch
surface.request_to_generate_chunks({ 0, 0 }, ceil(max_island_radius / 32))
end
end
)
local clear_globals_token =
Scheduler.set(
function ()
storage.tiles = {}
storage.market_positions = {}
end
)
local function add_market_slot(market)
market.add_market_item(
{
price = { { 'coin', 1 } },
offer = { type = 'nothing', effect_description = 'Progress onwards to the next island!' }
}
)
end
function test(event)
local surface = event.surface
local radius = (event.radius / 2) - 10
local position = event.position
local tiles = surface.find_tiles_filtered({ name = 'water', area = { { position.x - radius, position.y - radius }, { position.x + radius, position.y + radius } } })
if storage.current_stage == 1 then
tiles = shuffle(tiles)
end
local pos = storage.market_positions[#storage.market_positions]
local new_tile = find_dirt_tile(surface, pos)
local new_pos = surface.find_non_colliding_position('rocket-silo', new_tile, 0, 4)
if new_pos then
local p = new_pos
local market = surface.create_entity({ name = 'market', position = p, force = 'player' })
if market and market.valid then
market.minable = false
market.destructible = false
rendering.draw_text {
text = 'Checkpoint ' .. storage.current_stage,
surface = surface,
target = { market.position.x, market.position.y - 3.5 },
color = { r = 0.98, g = 0.77, b = 0.22 },
scale = 2,
font = 'heading-1',
alignment = 'center',
scale_with_zoom = false
}
add_market_slot(market)
Scheduler.timeout(10, request_to_generate_chunks_token, { size = 8, surface = surface, position = market.position, sleep = game.tick + 500 })
end
MapFunctions.draw_noise_tile_circle(p, 'blue-refined-concrete', surface, 12)
end
end
local create_market_token =
Scheduler.set(
function (event)
local surface = event.surface
local radius = (event.radius / 2) - 10
local position = event.position
local tiles = surface.find_tiles_filtered({ name = 'water', area = { { position.x - radius, position.y - radius }, { position.x + radius, position.y + radius } } })
if storage.current_stage == 1 then
tiles = shuffle(tiles)
end
local pos = storage.market_positions[#storage.market_positions]
local new_tile = find_dirt_tile(surface, pos)
local new_pos = surface.find_non_colliding_position('rocket-silo', new_tile, 0, 4)
if new_pos then
local p = new_pos
local market = surface.create_entity({ name = 'market', position = p, force = 'player' })
if market and market.valid then
market.minable = false
market.destructible = false
rendering.draw_text {
text = 'Checkpoint ' .. storage.current_stage,
surface = surface,
target = { market.position.x, market.position.y - 3.5 },
color = { r = 0.98, g = 0.77, b = 0.22 },
scale = 2,
font = 'heading-1',
alignment = 'center',
scale_with_zoom = false
}
add_market_slot(market)
Scheduler.timeout(10, request_to_generate_chunks_token, { size = 8, surface = surface, position = market.position, sleep = game.tick + 500 })
end
MapFunctions.draw_noise_tile_circle(p, 'blue-refined-concrete', surface, 12)
end
end
)
local do_place_entities_token =
Scheduler.set(
function (event)
local surface = event.surface
local position = event.position
local radius = event.radius
local main_island = event.main_island
if main_island then
MapFunctions.draw_noise_tile_circle(position, 'concrete', surface, 12)
local chest_pos = {
{ x = position.x + 1, y = position.y + 5 * 0.5 },
{ x = position.x - 1, y = position.y + 6 },
{ x = position.x + 1, y = position.y - 5 * -0.5 },
{ x = position.x - 1, y = position.y + 10 * -1 }
}
shuffle(chest_pos)
local chest_raff = {
'crash-site-chest-1',
'crash-site-chest-1',
'crash-site-chest-2',
'crash-site-chest-2'
}
storage.infini_chest = surface.create_entity({ name = chest_raff[random(1, #chest_raff)], position = { chest_pos[1].x, chest_pos[1].y }, force = 'neutral' })
storage.infini_chest.operable = false
storage.infini_chest.destructible = false
storage.infini_chest.minable = false
rendering.draw_text {
text = 'Free ammo',
surface = surface,
target = storage.infini_chest,
color = { r = 0.98, g = 0.77, b = 0.22 },
scale = 1.25,
font = 'heading-1',
alignment = 'center',
scale_with_zoom = false
}
local _y = 55
local ore_positions = {
{ x = position.x + 19, y = _y },
{ x = position.x - 52, y = _y * 0.5 },
{ x = position.x + 33, y = 0 },
{ x = position.x - 52, y = _y * -0.5 },
{ x = position.x + 25, y = _y * -1 }
}
shuffle(ore_positions)
resource_placement(surface, ore_positions[1], 'copper-ore', 150000, 550)
resource_placement(surface, ore_positions[2], 'iron-ore', 150000, 550)
resource_placement(surface, ore_positions[3], 'coal', 130000, 550)
resource_placement(surface, ore_positions[4], 'stone', 130000, 550)
end
local decoratives = game.surfaces['island'].find_decoratives_filtered({ area = { { position.x - 100, position.y - 100 }, { position.x + 100, position.y + 100 } } })
Scheduler.return_callback(
function (data)
for _, decorative in pairs(decoratives) do
local start_index = (data.table_index - 1) * data.total_calls + 1
local end_index = start_index + data.total_calls - 1
data.pos_tbl[data.point_index] = { position = { position.x + decorative.position.x, position.y + decorative.position.y }, name = decorative.decorative.name, amount = decorative.amount }
if data.iterator_index == end_index or data.iterator_index > #decoratives then
data.table_index = data.table_index + 1
data.tick_index = data.tick_index + 1
Scheduler.timeout(data.tick_index, do_place_decorative_token, { pos_tbl = data.pos_tbl, count = data.total_calls, surface = surface })
data.pos_tbl = {}
data.point_index = 1
if data.table_index > #decoratives then
break
end
end
data.iterator_index = data.iterator_index + 1
data.point_index = data.point_index + 1
end
end
)
local seed = random(1, 1000000)
Scheduler.return_callback(
function (data)
for _, t in pairs(storage.tiles) do
local start_index = (data.table_index - 1) * data.total_calls + 1
local end_index = start_index + data.total_calls - 1
data.pos_tbl[data.point_index] = t.position
if data.iterator_index == end_index or data.iterator_index > #storage.tiles then
data.table_index = data.table_index + 1
data.tick_index = data.tick_index + 1
Scheduler.timeout(data.tick_index, do_place_simple_entities_token, { pos_tbl = data.pos_tbl, count = data.total_calls, surface = surface, seed = seed, child_id = do_place_decorative_token })
data.pos_tbl = {}
data.point_index = 1
if data.table_index > #storage.tiles then
break
end
end
data.iterator_index = data.iterator_index + 1
data.point_index = data.point_index + 1
end
end
)
Scheduler.timeout(5, create_market_token, { child_id = do_place_simple_entities_token, surface = surface, position = position, radius = radius })
Scheduler.timeout(15, clear_globals_token, { child_id = create_market_token })
storage.gamestate = 33
end
)
local draw_island_inner_task_token =
Scheduler.set(
function (event)
local surface = event.surface
local position = event.position
local radius = event.radius
local main_island = event.main_island or false
game.print('running')
local count = 1
local c = 1
local positions = {}
for y = radius * -1, radius, 1 do
for x = radius * -1, radius, 1 do
positions[count] = { x = x, y = y }
count = count + 1
if count == 256 then
c = c + 1
Scheduler.timeout(c, place_tiles_token, { positions = positions, position = position, radius = radius, count = 255, surface = surface })
count = 1
positions = {}
end
end
end
Scheduler.timeout(50, do_place_entities_token, { surface = surface, position = position, radius = radius, child_id = place_tiles_token, main_island = main_island })
end
)
local set_new_island_token =
Scheduler.set(
function ()
local position = storage.path_tiles[#storage.path_tiles].position
local radius = storage.stages[storage.current_stage].size
storage.path_tiles = nil
draw_main_island(position, radius)
end
)
local draw_bridge_token =
Scheduler.set(
function (event)
log(serpent.block('drawing bridge'))
log(serpent.block(game.tick))
local position = event.position
local surface = event.surface
local seed_1 = random(1, 10000000)
local seed_2 = random(1, 10000000)
local m = random(1, 100) * 0.001
storage.path_tiles = {}
Scheduler.timeout(
1,
noise_vector_tiles_path_token,
{
surface = surface,
tbl_tiles = path_tile_names,
position = position,
length = 200,
brush_size = 6,
whitelist = draw_path_tile_whitelist,
seed_1 = seed_1,
seed_2 = seed_2,
m = m
},
'noise_vector_tiles_path_1'
)
-- local test = storage.path_tiles[#storage.path_tiles].position
-- game.print('[gps=' .. test.x .. ',' .. test.y .. ',' .. surface.name .. ']')
-- Scheduler.timeout(
-- 20,
-- noise_vector_tiles_path_token,
-- {
-- surface = surface,
-- tbl_tiles = {'deepwater'},
-- position = position,
-- length = 200,
-- brush_size = 10,
-- whitelist = {['water'] = true},
-- seed_1 = seed_1,
-- seed_2 = seed_2,
-- m = m,
-- child_id = 'noise_vector_tiles_path_1'
-- },
-- 'noise_vector_tiles_path_2'
-- )
Scheduler.timeout(10, request_to_generate_chunks_token, { size = 8, surface = surface, sleep = game.tick + 500 })
storage.current_stage = storage.current_stage + 1
Scheduler.timeout(20, set_new_island_token, { child_id = request_to_generate_chunks_token, sleep = game.tick + 200 })
-- Scheduler.timeout(
-- 30,
-- place_bridge_token,
-- {
-- surface = surface,
-- child_id = {'noise_vector_tiles_path_2', set_new_island_token, create_new_surface_token, draw_island_inner_task_token}
-- }
-- )
end
)
function draw_main_island(position, radius, main_island)
local surface = game.surfaces[1]
position = position or { x = 0, y = 0 }
radius = radius or 200
if (position.x == 0 and position.y == 0) then
main_island = true
end
if not seed_1 then
seed_1 = random(1, 9999999)
seed_2 = random(1, 9999999)
seed_3 = random(1, 9999999)
seed_m1 = (random(8, 16) * 0.1) / radius
seed_m2 = (random(12, 24) * 0.1) / radius
seed_m3 = (random(50, 100) * 0.1) / radius
end
Scheduler.timeout(5, create_new_surface_token, { sleep = game.tick + 10 })
Scheduler.timeout(10, draw_island_inner_task_token, { child_id = create_new_surface_token, surface = surface, radius = radius, position = position, main_island = main_island })
storage.gamestate = 33
end
local function on_chunk_generated(event)
if event.surface.index ~= 1 then
return
end
local left_top = event.area.left_top
local surface = event.surface
for x = 0, 31, 1 do
for y = 0, 31, 1 do
local position = { x = left_top.x + x, y = left_top.y + y }
if not is_inside_island(position.x, position.y) then
surface.set_tiles { { name = 'water', position = position } }
else
surface.set_tiles({ { name = 'black-refined-concrete', position = position } }, true)
end
end
end
end
local function on_market_item_purchased(event)
local entity = event.market
if not entity or not entity.valid then
return
end
local offer_index = event.offer_index
local offers = entity.get_market_items()
local bought_offer = offers[offer_index].offer
if bought_offer.type ~= 'nothing' then
return
end
if string.find(bought_offer.effect_description, 'onwards') then
-- entity.remove_market_item(1)
-- entity.operable = false
storage.position = entity.position
game.print('bought offer')
Scheduler.timeout(1, draw_bridge_token, { surface = entity.surface, position = storage.position, child_id = request_to_generate_chunks_token })
end
end
Event.add(defines.events.on_chunk_generated, on_chunk_generated)
Event.add(defines.events.on_market_item_purchased, on_market_item_purchased)

View File

@ -1,265 +0,0 @@
--map by gerkiz and kyte
--luacheck: ignore
local Event = require 'utils.event'
require 'maps.wip.func'
local Map = require 'modules.map_info'
local Task = require 'utils.task_token'
max_island_radius = 256
local set_gamestate_token =
Task.register(
function ()
storage.gamestate = 1
end
)
local function create_stage_gui(player)
if player.gui.top.stage_gui then
return
end
local element = player.gui.top.add({ type = 'frame', name = 'stage_gui', caption = ' ' })
local style = element.style
style.minimal_height = 38
style.maximal_height = 38
style.minimal_width = 140
style.top_padding = 2
style.left_padding = 4
style.right_padding = 4
style.bottom_padding = 2
style.font_color = { r = 155, g = 85, b = 25 }
style.font = 'default-large-bold'
end
function update_stage_gui()
if not storage.stages then
return
end
local caption = 'Level: ' .. storage.current_level
caption = caption .. ' | Stage: '
local stage = storage.current_stage
if stage > #storage.stages - 1 then
stage = #storage.stages - 1
end
caption = caption .. stage
caption = caption .. '/'
caption = caption .. #storage.stages - 1
caption = caption .. ' | Bugs remaining: '
caption = caption .. storage.alive_enemies
for _, player in pairs(game.connected_players) do
if player.gui.top.stage_gui then
player.gui.top.stage_gui.caption = caption
end
end
end
local function bring_players()
local surface = game.surfaces[1]
for _, player in pairs(game.connected_players) do
if player.position.y < -1 then
if player.character then
if player.character.valid then
local p = surface.find_non_colliding_position('character', { 0, 2 }, 8, 0.5)
if not p then
player.teleport({ 0, 2 }, surface)
end
player.teleport(p, surface)
end
end
end
end
end
local function drift_corpses_toward_beach()
local surface = game.surfaces[1]
for _, corpse in pairs(surface.find_entities_filtered({ name = 'character-corpse' })) do
if corpse.position.y < 0 then
if surface.get_tile(corpse.position).collides_with('resource') then
corpse.clone {
position = { corpse.position.x, corpse.position.y + (math.random(50, 250) * 0.01) },
surface = surface,
force = corpse.force.name
}
corpse.destroy()
end
end
end
end
local function set_next_level()
storage.alive_enemies = 0
storage.alive_boss_enemy_count = 0
storage.current_level = storage.current_level + 1
if storage.current_level > 1 then
bring_players()
end
storage.current_stage = 1
storage.path_tiles = nil
--game.print("Level " .. storage.current_level)
update_stage_gui()
storage.gamestate = 2
end
local function earn_credits(amount)
for _, player in pairs(game.connected_players) do
player.play_sound { path = 'utility/armor_insert', volume_modifier = 0.85 }
end
game.print(amount .. ' credits have been transfered to the factory.', { r = 255, g = 215, b = 0 })
storage.credits = storage.credits + amount
end
local function wait_until_stage_is_beaten()
if storage.alive_enemies >= 0 then
return
end
local reward_amount
local gamestate = 2
local base_reward = 250 * storage.current_level
if storage.stages[storage.current_stage].size then
if storage.current_stage < #storage.stages - 1 then
reward_amount = base_reward + storage.current_stage * storage.current_level * 50
else
reward_amount = base_reward + storage.current_stage * storage.current_level * 150
end
else
game.print('Final Stage complete!')
game.print('Level is collapsing!!', { r = 255, g = 0, b = 0 })
gamestate = 6
end
if reward_amount then
earn_credits(reward_amount)
update_stage_gui()
end
storage.current_stage = storage.current_stage + 1
storage.gamestate = gamestate
end
local function on_player_joined_game(event)
local player = game.players[event.player_index]
-- create_stage_gui(player)
-- update_stage_gui()
if player.online_time > 0 then
return
end
player.insert({ name = 'pistol', count = 1 })
player.insert({ name = 'firearm-magazine', count = 32 })
end
local function on_init()
local T = Map.Pop_info()
T.localised_category = 'wip'
T.main_caption_color = { r = 150, g = 150, b = 0 }
T.sub_caption_color = { r = 0, g = 150, b = 0 }
game.create_force('enemy_spawners')
game.forces.enemy_spawners.set_friend('enemy', true)
game.forces.enemy.set_friend('enemy_spawners', true)
local surface = game.surfaces[1]
surface.request_to_generate_chunks({ x = 0, y = 0 }, 6)
local mgs = game.surfaces[1].map_gen_settings
mgs.water = 9.9
mgs.property_expression_names = {
['control-setting:aux:bias'] = '0.500000',
['control-setting:aux:frequency:multiplier'] = '6.000000',
['control-setting:moisture:bias'] = '-0.050000',
['control-setting:moisture:frequency:multiplier'] = '6.000000',
elevation = '0_17-island'
}
game.surfaces[1].map_gen_settings = mgs
local blacklist = {
['dark-mud-decal'] = true,
['sand-dune-decal'] = true,
['light-mud-decal'] = true,
['puberty-decal'] = true,
['sand-decal'] = true,
['red-desert-decal'] = true
}
storage.decorative_names = {}
for k, v in pairs(prototypes.decorative) do
if not blacklist[k] then
if v.autoplace_specification then
storage.decorative_names[#storage.decorative_names + 1] = k
end
end
end
storage.shopping_chests = {}
storage.dump_chests = {}
storage.registerd_shopping_chests = {}
storage.credits = 0
game.create_force('shopping_chests')
game.forces.player.set_friend('shopping_chests', true)
game.forces.shopping_chests.set_friend('player', true)
local tree_raffle = {}
for _, e in pairs(prototypes.entity) do
if e.type == 'tree' then
table.insert(tree_raffle, e.name)
end
end
storage.tree_raffle = tree_raffle
local corpses_raffle = {}
for _, e in pairs(prototypes.entity) do
if e.type == 'corpse' then
table.insert(corpses_raffle, e.name)
end
end
storage.corpses_raffle = corpses_raffle
storage.stages = {}
local island_level = 12
for _ = 1, 20 do
storage.stages[#storage.stages + 1] = {
size = 16 + (32 + island_level) * 1.5
}
island_level = island_level + 5
end
storage.stages[#storage.stages].final = true
storage.level_vectors = {}
storage.alive_boss_enemy_entities = {}
storage.current_level = 0
storage.gamestate = 0
Task.set_timeout_in_ticks(30, set_gamestate_token)
game.forces.player.set_spawn_position({ 0, 2 }, surface)
end
local gamestate_functions = {
[1] = set_next_level,
[2] = draw_main_island,
[3] = draw_the_island,
[4] = wait_until_stage_is_beaten
}
local function on_tick()
if game.tick % 25 == 0 and gamestate_functions[storage.gamestate] then
gamestate_functions[storage.gamestate]()
end
if game.tick % 150 == 0 then
drift_corpses_toward_beach()
if storage.infini_chest and storage.infini_chest.valid then
storage.infini_chest.insert({ name = 'firearm-magazine', count = 1 })
end
end
end
Event.on_init(on_init)
Event.add(defines.events.on_tick, on_tick)
Event.add(defines.events.on_player_joined_game, on_player_joined_game)

View File

@ -1,52 +0,0 @@
-- one table to rule them all!
local Global = require 'utils.global'
local Event = require 'utils.event'
local this = {}
local Public = {}
Global.register(
this,
function(tbl)
this = tbl
end
)
function Public.reset_main_table()
end
function Public.get(key)
if key then
return this[key]
else
return this
end
end
function Public.set(key, value)
if key and (value or value == false) then
this[key] = value
return this[key]
elseif key then
return this[key]
else
return this
end
end
function Public.remove(key, sub_key)
if key and sub_key then
if this[key] and this[key][sub_key] then
this[key][sub_key] = nil
end
elseif key then
if this[key] then
this[key] = nil
end
end
end
Event.on_init(Public.reset_main_table)
return Public

View File

@ -255,6 +255,16 @@ local function get_nearby_chests(player, a, furnace, wagon)
return { chest = chests, inventory = inventories }
end
local function check_if_valid_requests(chest)
local requests = 0
if chest.type == 'logistic-container' then
local lp = chest.get_logistic_point(defines.logistic_member_index.logistic_container)
local filters = LP.get_filters(lp)
requests = #filters
end
return requests > 0
end
local function insert_to_furnace(player_inventory, chests, name, count, floaty_text_list)
local try = 0
@ -466,7 +476,7 @@ local function insert_item_into_chest(stack, chests, filtered_chests, name, floa
--Attempt to store in chests that already have the same item.
for chestnr, chest in pairs(chests.chest) do
if container[chest.type] then
if chest.request_slot_count and chest.request_slot_count > 0 then
if check_if_valid_requests(chest) then
goto continue
end
local chest_inventory = chests.inventory[chestnr]
@ -487,7 +497,7 @@ local function insert_item_into_chest(stack, chests, filtered_chests, name, floa
--Attempt to store in empty chests.
for chestnr, chest in pairs(filtered_chests.chest) do
if container[chest.type] then
if chest.request_slot_count and chest.request_slot_count > 0 then
if check_if_valid_requests(chest) then
goto continue
end
local chest_inventory = filtered_chests.inventory[chestnr]
@ -513,7 +523,7 @@ local function insert_item_into_chest(stack, chests, filtered_chests, name, floa
local item_subgroup = prototypes.item[name].subgroup.name
if item_subgroup then
for chestnr, chest in pairs(filtered_chests.chest) do
if chest.request_slot_count and chest.request_slot_count > 0 then
if check_if_valid_requests(chest) then
goto continue
end
if container[chest.type] then
@ -543,7 +553,7 @@ local function insert_item_into_chest(stack, chests, filtered_chests, name, floa
--Attempt to store in mixed chests.
for chestnr, chest in pairs(filtered_chests.chest) do
if container[chest.type] then
if chest.request_slot_count and chest.request_slot_count > 0 then
if check_if_valid_requests(chest) then
goto continue
end
local chest_inventory = filtered_chests.inventory[chestnr]
@ -576,6 +586,7 @@ local function auto_stash(player, event)
return
end
local inventory = player.get_main_inventory()
if not inventory then return end
if inventory.is_empty() then
player.print(module_name .. 'Inventory is empty.', Color.warning)
return

View File

@ -339,7 +339,7 @@ function Public.get_last_spell_cast(player)
return false
end
local position = player.position
local position = player.physical_position
local cast_radius = 1
local cast_area = {
left_top = { x = rpg_t.last_spell_cast.x - cast_radius, y = rpg_t.last_spell_cast.y - cast_radius },
@ -709,7 +709,8 @@ function Public.update_tidal_wave()
local next_offset_y = cause_position.y + wave.direction[2] * (i + 1) - j * wave.direction[1]
local next_position = { next_offset_x, next_offset_y }
surface.create_entity({ name = 'water-splash', position = position })
surface.create_entity({ name = 'big-demolisher-fissure', position = position })
-- surface.create_entity({ name = 'water-splash', position = position })
-- surface.create_trivial_smoke({name = 'poison-capsule-smoke', position = position})
local sound = 'utility/build_small'
wave_player.play_sound { path = sound, volume_modifier = 1 }
@ -733,7 +734,8 @@ function Public.update_tidal_wave()
local next_offset_y = cause_position.y + wave.direction[2] * (i + 1) - j * wave.direction[1]
local next_position = { next_offset_x, next_offset_y }
-- surface.create_trivial_smoke({name = 'poison-capsule-smoke', position = position})
surface.create_entity({ name = 'water-splash', position = position })
-- surface.create_entity({ name = 'water-splash', position = position })
surface.create_entity({ name = 'big-demolisher-fissure', position = position })
local sound = 'utility/build_small'
wave_player.play_sound { path = sound, volume_modifier = 1 }
@ -820,7 +822,7 @@ function Public.update_player_stats(player)
end
function Public.level_up_effects(player)
local position = { x = player.position.x - 0.75, y = player.position.y - 1 }
local position = { x = player.physical_position.x - 0.75, y = player.physical_position.y - 1 }
player.create_local_flying_text(
{
position = position,
@ -850,7 +852,7 @@ function Public.level_up_effects(player)
end
function Public.cast_spell(player, failed)
local position = { x = player.position.x - 0.75, y = player.position.y - 1 }
local position = { x = player.physical_position.x - 0.75, y = player.physical_position.y - 1 }
local b = 0.75
if not failed then
for _ = 1, 3, 1 do
@ -890,7 +892,7 @@ function Public.cast_spell(player, failed)
end
function Public.xp_effects(player)
local position = { x = player.position.x - 0.75, y = player.position.y - 1 }
local position = { x = player.physical_position.x - 0.75, y = player.physical_position.y - 1 }
player.create_local_flying_text(
{
position = position,
@ -920,7 +922,7 @@ function Public.xp_effects(player)
end
function Public.boost_effects(player)
local position = { x = player.position.x - 0.75, y = player.position.y - 1 }
local position = { x = player.physical_position.x - 0.75, y = player.physical_position.y - 1 }
local b = 0.75
for _ = 1, 10, 1 do
local p = {
@ -1088,7 +1090,7 @@ function Public.get_heal_modifier_from_using_fish(player)
local base_amount = 80
local rng = random(base_amount, base_amount * rpg_extra.heal_modifier)
local char = player.character
local position = player.position
local position = player.physical_position
if char and char.valid then
local health = player.character_health_bonus + 250
local color
@ -1507,6 +1509,9 @@ function Public.gain_xp(player, amount, added_to_pool, text)
end
local rpg_extra = Public.get('rpg_extra')
local rpg_t = Public.get_value_from_player(player.index)
if not rpg_t then
return
end
if Public.level_limit_exceeded(player) then
add_to_global_pool(amount, false)
@ -1520,7 +1525,7 @@ function Public.gain_xp(player, amount, added_to_pool, text)
local text_to_draw
if rpg_t.capped then
if rpg_t and rpg_t.capped then
rpg_t.capped = false
end
@ -1570,7 +1575,7 @@ function Public.gain_xp(player, amount, added_to_pool, text)
player.create_local_flying_text {
text = text_to_draw,
position = player.position,
position = player.physical_position,
color = xp_floating_text_color,
time_to_live = 340,
speed = 2
@ -1634,7 +1639,7 @@ local damage_player_over_time_token =
return
end
player.character.health = player.character.health - (player.character.health * 0.05)
player.character.surface.create_entity({ name = 'water-splash', position = player.position })
player.character.surface.create_entity({ name = 'water-splash', position = player.physical_position })
end
)

View File

@ -349,9 +349,11 @@ local function regen_health_player(players)
for i = 1, #players do
local player = players[i]
local heal_per_tick = Public.get_heal_modifier(player)
if heal_per_tick <= 0 then
if heal_per_tick and heal_per_tick <= 0 then
goto continue
end
if not heal_per_tick then goto continue end
heal_per_tick = round(heal_per_tick)
if player and player.valid and not player.in_combat then
if player.character and player.character.valid then
@ -469,7 +471,7 @@ local function on_entity_damaged(event)
return
end
local position = p.position
local position = p.physical_position
local area = {
left_top = { x = position.x - 5, y = position.y - 5 },
@ -687,6 +689,7 @@ local function on_pre_player_mined_item(event)
end
local rpg_t = Public.get_value_from_player(player.index)
if not rpg_t then return end
if rpg_t.last_mined_entity_position.x == entity.position.x and rpg_t.last_mined_entity_position.y == entity.position.y then
return
end
@ -961,7 +964,7 @@ local function on_player_used_capsule(event)
return Public.cast_spell(player, true)
end
if not Math2D.bounding_box.contains_point(area, player.position) then
if not Math2D.bounding_box.contains_point(area, player.physical_position) then
Public.cast_spell(player, true)
return
end

View File

@ -48,7 +48,7 @@ repeat_sound_token =
if event.once then
player.play_sound { path = sound, volume_modifier = 1 }
if player.character ~= nil then
player.character.surface.create_entity({ name = 'water-splash', position = player.position })
player.character.surface.create_entity({ name = 'water-splash', position = player.physical_position })
end
return
end
@ -61,7 +61,7 @@ repeat_sound_token =
player.play_sound { path = sound, volume_modifier = 1 }
if player.character ~= nil then
player.character.surface.create_entity({ name = 'water-splash', position = player.position })
player.character.surface.create_entity({ name = 'water-splash', position = player.physical_position })
end
Task.set_timeout_in_ticks(30, repeat_sound_token, event)
end
@ -133,7 +133,7 @@ local function area_of_effect(player, position, state, radius, callback, find_en
end
local cs = player.surface
local cp = position or player.position
local cp = position or player.physical_position
if radius and radius > 256 then
radius = 256
@ -1141,7 +1141,7 @@ spells[#spells + 1] = {
callback = function (data)
local player = data.player
local surface = data.surface
local old_position = player.position
local old_position = player.physical_position
Public.register_cooldown_for_spell(player)

View File

@ -163,23 +163,21 @@ local function get_spawn_pos()
local inverted = Public.get('inverted')
if inverted then
if initial_position.y - target.position.y < -10 then
initial_position = { x = initial_position.x, y = initial_position.y + 50 }
initial_position = { x = initial_position.x, y = initial_position.y }
end
else
if initial_position.y - target.position.y > 10 then
initial_position = { x = initial_position.x, y = initial_position.y - 50 }
initial_position = { x = initial_position.x, y = initial_position.y }
end
end
local located_position = find_initial_spot(surface, initial_position)
local valid_position = surface.find_non_colliding_position('stone-furnace', located_position, 32, 1)
local debug = Public.get('debug')
if debug then
if valid_position then
local x = valid_position.x
local y = valid_position.y
game.print('[gps=' .. x .. ',' .. y .. ',' .. surface.name .. ']')
end
if valid_position then
local x = valid_position.x
local y = valid_position.y
game.print('[gps=' .. x .. ',' .. y .. ',' .. surface.name .. ']')
end
if not valid_position then
@ -1175,7 +1173,7 @@ local function spawn_unit_group(fs, only_bosses)
local generated_units = Public.get('generated_units')
local unit_group = surface.create_unit_group({ position = spawn_position, force = force }) --[[@as UnitGroup]]
local unit_group = surface.create_unit_group({ position = spawn_position, force = force }) --[[@as LuaCommandable]]
event_data.unit_group = unit_group

View File

@ -44,9 +44,6 @@ Public.ranks = {
'item/electric-mining-drill',
'item/electric-mining-drill',
'item/electric-mining-drill',
'item/dummy-steel-axe',
'item/dummy-steel-axe',
'item/dummy-steel-axe',
'item/heavy-armor',
'item/heavy-armor',
'item/heavy-armor',

View File

@ -189,7 +189,7 @@ function table.shuffle_table(t, rng)
end
end
---Shuffles a table of objects with a position, leaving objects closer to position to be earlier in the table (one time semi-sort)
---Shuffles a table of objects with a position, leaving objects closer to position to be earlier in the table (one time semi-sort)
---@param tbl table #table to shuffle, all elements in it have to be table objects that have position key
---@param position MapPosition|{x:double,y:double}
function table.shuffle_by_distance(tbl, position)
@ -215,19 +215,19 @@ end
function table.spairs(t, order)
-- collect the keys
local keys = {}
for k in pairs(t) do keys[#keys+1] = k end
for k in pairs(t) do keys[#keys + 1] = k end
-- if order function given, sort by it by passing the table and keys a, b,
-- otherwise just sort the keys
if order then
table.sort(keys, function(a,b) return order(t, a, b) end)
table.sort(keys, function (a, b) return order(t, a, b) end)
else
table.sort(keys)
end
-- return the iterator function
local i = 0
return function()
return function ()
i = i + 1
if keys[i] then
return keys[i], t[keys[i]]