1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-04-13 11:30:40 +02:00

Merge remote-tracking branch 'upstream/develop' into develop

This commit is contained in:
danielmartin0 2022-05-08 10:32:41 +01:00
commit 1ff3c8f5bd
17 changed files with 1049 additions and 160 deletions

View File

@ -421,6 +421,19 @@ for k, _ in pairs(item_worths) do
end
local size_of_item_names = #item_names
function Public.TweakItemWorth(updates)
item_names = {}
for k, v in pairs(updates) do
item_worths[k] = v
end
item_names = {}
for k, _ in pairs(item_worths) do
table_insert(item_names, k)
end
size_of_item_names = #item_names
end
local function get_raffle_keys()
local raffle_keys = {}
for i = 1, size_of_item_names, 1 do

View File

@ -72,7 +72,9 @@ end
local function scan_direction_full(surface, position, vector, room_max, room_min)
local best = {x = room_min, y = room_min}
local a = room_min + room_spacing + 1
-- make the center of the room a steps in the direction of vector.
-- +2 because with only +1 the calculation would end up overlapping quite often with the current position
local a = room_min + room_spacing + 2
local room_center_pos = {x = position.x + vector[1] * a, y = position.y + vector[2] * a}
local search_area = {

View File

@ -78,12 +78,12 @@ map_info_text=Expand into the depths for treasure.\nEverytime a new room is disc
descend=Descend to lower floor.\nEach floor has stronger enemies and better treasure.\nRIGHT-CLICK: Descend 5 floors.\nSHIFT-CLICK: Desscend to lowest accessible Floor.
ascend=Ascend to higher floor.\nRIGHT-CLICK: Ascend 5 floors.\nSHIFT-CLICK: Ascend to Floor 0.
depth=~ Floor __1__ | Depth __2__ ~
depth_tooltip=Evolution: __1__%\nEnemy Health: __2__%\nEnemy Damage: __3__%\nLoot Value: __4__\nTreasure rooms found: __5__ / 5\nHidden Technologies: __6__
depth_tooltip=Evolution: __1__%\nEnemy Health: __2__%\nEnemy Damage: __3__%\nLoot Value: __4__\nTreasure rooms found: __5__\nHidden Technologies: __6__
max_depth=You are on deepest level already!
min_depth=You are on highest level already!
only_on_spawn=You can change floors only on spawn.
level_required=You need level __1__ for travelling to next floor!
floor_size_required=You need to explore at least 60 rooms on this floor to access next floor!
floor_size_required=You need to explore at least __1__ rooms on this floor to access next floor!
travel_down=You have descended to deeper part of dungeon.
travel_up=You have ascended to previous part of dungeon.
first_visit=__1__ [lvl __2__] was first to reach Floor __3__!
@ -102,7 +102,7 @@ spidertron_not_allowed=Spidertrons are not allowed in first 20 floors!
[mountain_fortress]
map_info_main_caption=M O U N T A I N F O R T R E S S
map_info_sub_caption= ..diggy diggy choo choo..
map_info_text=The biters have caught the scent of fish in the cargo wagon.\nGuide the choo into the mountain and protect it as long as possible!\nThis however will not be an easy task,\nsince their strength and numbers increase over time.\n\nIn additon, the southern grounds collapse over time.\n\nDelve deep for greater treasures, but also face increased dangers.\nMining productivity research, will overhaul your mining equipment,\nreinforcing your pickaxe as well as increasing the size of your backpack.\n\nAs you dig, you will encounter impassable dark chasms or rivers.\nSome explosives may cause parts of the ceiling to crumble, filling the void, creating new ways.\nAll they need is a container and a well aimed shot.\n\nYou may find some supply goods, if you enter the wagon.\nGood luck on your journey!
map_info_text=The biters have caught the scent of fish in the cargo wagon.\nGuide the choo into the mountain and protect it as long as possible!\nThis however will not be an easy task,\nsince their strength and numbers increase over time.\n\nIn addition, the southern grounds collapse over time.\n\nDelve deep for greater treasures, but also face increased dangers.\nMining productivity research, will overhaul your mining equipment,\nreinforcing your pickaxe as well as increasing the size of your backpack.\n\nAs you dig, you will encounter impassable dark chasms or rivers.\nSome explosives may cause parts of the ceiling to crumble, filling the void, creating new ways.\nAll they need is a container and a well aimed shot.\n\nYou may find some supply goods, if you enter the wagon.\nGood luck on your journey!
[rocks_yield_ore_veins]
coal=coal

View File

@ -77,12 +77,12 @@ map_info_text=Отправляйтесь в глубины за сокровищ
descend=Спуститься на нижний этаж.\nНа каждом этаже более сильные враги и лучшие сокровища.\nПКМ: спуск на 5 этажей.\nShift+ЛКМ: спуск на самый нижний доступный этаж.
ascend=Подняться на верхний этаж.\nПКМ: подняться на 5 этажей.\nShift+ЛКМ: подняться на 0-й этаж.
depth=~ Этаж __1__ | Глубина __2__ ~
depth_tooltip=Эволюция: __1__%\nЗдоровье врагов: __2__%\nУрон врагов: __3__%\nЦенность добычи: __4__\nКомнат с сокровищами найдено: __5__ / 5\nСкрытых технологий: __6__
depth_tooltip=Эволюция: __1__%\nЗдоровье врагов: __2__%\nУрон врагов: __3__%\nЦенность добычи: __4__\nКомнат с сокровищами найдено: __5__\nСкрытых технологий: __6__
max_depth=Вы уже на самом глубоком уровне!
min_depth=Вы уже на самом верхнем уровне!
only_on_spawn=Вы можете изменить этаж только на точке появления.
level_required=Вам нужен __1__ уровень для перехода на следующий этаж!
floor_size_required=Вам нужно исследовать не менее 60 комнат на этом этаже, чтобы попасть на следующий этаж!
floor_size_required=Вам нужно исследовать не менее __1__ комнат на этом этаже, чтобы попасть на следующий этаж!
travel_down=Вы спустились в более глубокую часть подземелья.
travel_up=Вы поднялись в предыдущую часть подземелья.
first_visit=__1__ [ур. __2__] впервые достиг __3__ этажа!

View File

@ -78,12 +78,12 @@ map_info_text=Expand into the depths for treasure.\nEverytime a new room is disc
descend=Descend to lower floor.\nEach floor has stronger enemies and better treasure.\nRIGHT-CLICK: Descend 5 floors.\nSHIFT-CLICK: Desscend to lowest accessible Floor.
ascend=Ascend to higher floor.\nRIGHT-CLICK: Ascend 5 floors.\nSHIFT-CLICK: Ascend to Floor 0.
depth=~ Floor __1__ | Depth __2__ ~
depth_tooltip=Evolution: __1__%\nEnemy Health: __2__%\nEnemy Damage: __3__%\nLoot Value: __4__\nTreasure rooms found: __5__ / 5\nHidden Technologies: __6__
depth_tooltip=Evolution: __1__%\nEnemy Health: __2__%\nEnemy Damage: __3__%\nLoot Value: __4__\nTreasure rooms found: __5__\nHidden Technologies: __6__
max_depth=You are on deepest level already!
min_depth=You are on highest level already!
only_on_spawn=You can change floors only on spawn.
level_required=You need level __1__ for travelling to next floor!
floor_size_required=You need to explore at least 60 rooms on this floor to access next floor!
floor_size_required=You need to explore at least __1__ rooms on this floor to access next floor!
travel_down=You have descended to deeper part of dungeon.
travel_up=You have ascended to previous part of dungeon.
first_visit=__1__ [lvl __2__] was first to reach Floor __3__!

View File

@ -86,7 +86,9 @@ local function island(surface, room)
for x = 0, a, 1 do
for y = 0, a, 1 do
local p = {x = left_top.x + x, y = left_top.y + y}
if not math_abs(p.x - center_position.x) < room.radius * 0.6 and math_abs(p.y - center_position.y) < room.radius * 0.6 then
local inside_x = math_abs(p.x - center_position.x) < room.radius * 0.6
local inside_y = math_abs(p.y - center_position.y) < room.radius * 0.6
if not inside_x and not inside_y then
surface.set_tiles({{name = 'water', position = p}})
if math_random(1, 16) == 1 then
surface.create_entity({name = 'fish', position = p})
@ -104,7 +106,9 @@ local function cross(surface, room)
for x = 0, a, 1 do
for y = 0, a, 1 do
local p = {x = left_top.x + x, y = left_top.y + y}
if math_abs(p.x - center_position.x) > room.radius * 0.33 and math_abs(p.y - center_position.y) > room.radius * 0.33 then
local ok_x = math_abs(p.x - center_position.x) > (room.radius * 0.33)
local ok_y = math_abs(p.y - center_position.y) > (room.radius * 0.33)
if ok_x and ok_y then
surface.set_tiles({{name = 'water', position = p}})
if math_random(1, 16) == 1 then
surface.create_entity({name = 'fish', position = p})
@ -122,7 +126,9 @@ local function cross_inverted(surface, room)
for x = 0, a, 1 do
for y = 0, a, 1 do
local p = {x = left_top.x + x, y = left_top.y + y}
if not math_abs(p.x - center_position.x) > room.radius * 0.33 and math_abs(p.y - center_position.y) > room.radius * 0.33 then
local outside_x = math_abs(p.x - center_position.x) > room.radius * 0.33
local outside_y = math_abs(p.y - center_position.y) > room.radius * 0.33
if not outside_x and outside_y then
surface.set_tiles({{name = 'water', position = p}})
if math_random(1, 16) == 1 then
surface.create_entity({name = 'fish', position = p})
@ -200,8 +206,9 @@ local function biome(surface, room)
surface.set_tiles({{name = 'cyan-refined-concrete', position = tile.position}}, true)
end
water_shapes[math_random(1, #water_shapes)](surface, room)
local choice = math_random(1, #water_shapes)
-- choice = 5
water_shapes[choice](surface, room)
for key, tile in pairs(room.room_tiles) do
tile = surface.get_tile(tile.position)
if not tile.collides_with('resource-layer') then

View File

@ -53,6 +53,8 @@ end
local function dirtlands(surface, room)
local dungeontable = DungeonsTable.get_dungeontable()
local max_spawn = math.floor(dungeontable.depth[surface.index] / 8)
local max_worm = max_spawn + 1
local path_tile = 'dirt-' .. math_random(1, 3)
for _, tile in pairs(room.path_tiles) do
surface.set_tiles({{name = path_tile, position = tile.position}}, true)
@ -76,14 +78,16 @@ local function dirtlands(surface, room)
surface.create_entity({name = trees[math_random(1, size_of_trees)], position = tile.position})
end
end
if key % 128 == 1 and math_random(1, 2) == 1 and dungeontable.depth[surface.index] > 8 then
if key % 128 == 1 and math_random(1, 2) == 1 and max_spawn > 0 then
Functions.set_spawner_tier(
surface.create_entity({name = Functions.roll_spawner_name(), position = tile.position, force = dungeontable.enemy_forces[surface.index]}),
surface.index
)
max_spawn = max_spawn - 1
end
if math_random(1, 320) == 1 and dungeontable.depth[surface.index] > 8 then
surface.create_entity({name = Functions.roll_worm_name(surface.index), position = tile.position, force = dungeontable.enemy_forces[surface.index]})
if math_random(1, 320) == 1 and max_worm > 0 then
surface.create_entity({name = Functions.roll_worm_name(surface.index), position = tile.position, force = dungeontable.enemy_forces[surface.index]})
max_worm = max_worm - 1
end
if math_random(1, 512) == 1 then
Functions.create_scrap(surface, tile.position)

View File

@ -9,11 +9,16 @@ local rainbow_tiles = {
'purple-refined-concrete'
}
-- balanced the same as end-game rocks from functions.lua:rocky_loot
local ores = {
'copper-ore',
'copper-ore',
'copper-ore',
'iron-ore',
'iron-ore',
'iron-ore',
'iron-ore',
'coal',
'coal',
'stone'
}
@ -30,11 +35,20 @@ local function treasure(surface, room)
table_insert(tiles, tile)
end
local scale_factor = 5
if room.room_tiles[1] then
-- room.room_tiles[1] is set only if this is a real room not a walkway
-- Small rooms are 9x9, big ones are 29x29, so 100-1000 tiles
-- middle size about 400 tiles, but test at that showed treasure rooms over-buffed.
-- test#2 at 200.
scale_factor = 10 * 200 / #tiles
end
for _, tile in pairs(tiles) do
surface.set_tiles({{name = rainbow_tiles[math_random(1, 2)], position = tile.position}}, true)
if math_random(1, 3) == 1 then
surface.create_entity({name = ores[math_random(1, 6)], position = tile.position, amount = Functions.get_common_resource_amount(surface.index) * 5})
surface.create_entity({name = ores[math_random(1, #ores)], position = tile.position, amount = Functions.get_common_resource_amount(surface.index) * scale_factor})
end
end

View File

@ -1,5 +1,12 @@
local Public = {}
local FLOOR_ZERO_ROCK_ORE = 40
local ROCK_ORE_INCREASE_PER_FLOOR = 15
local FLOOR_FOR_MAX_ROCK_ORE = 15
local LOOT_EVOLUTION_SCALE_FACTOR = 0.9
local LOOT_MULTIPLIER = 3000
local EVOLUTION_PER_FLOOR = 0.06
local BiterRaffle = require 'functions.biter_raffle'
local LootRaffle = require 'functions.loot_raffle'
local Get_noise = require 'utils.get_noise'
@ -10,50 +17,87 @@ local math_random = math.random
local math_abs = math.abs
local math_floor = math.floor
-- Epic loot chest is 0.05 * (floor + 1) * 4000 * 8 + rand(512,1024)
-- So floor 0 = 2112 .. 2624
-- floor 4 = 8512 .. 9024
-- floor 9 = 16512 .. 17024
-- floor 19 = 32512 .. 33024
LootRaffle.TweakItemWorth({
['modular-armor'] = 512, -- floors 1-5 from research.lua
['power-armor'] = 4096, -- floors 8-13 from research.lua
['personal-laser-defense-equipment'] = 1536, -- floors 10-14 from research.lua
['power-armor-mk2'] = 24576, -- floors 14-21 from research.lua
-- reduce ammo/follower rates
['firearm-magazine'] = 8,
['piercing-rounds-magazine'] = 16,
['uranium-rounds-magazine'] = 128,
['shotgun-shell'] = 8,
['piercing-shotgun-shell'] = 64,
['flamethrower-ammo'] = 128,
['rocket'] = 16,
['explosive-rocket'] = 128,
['grenade'] = 32,
['cluster-grenade'] = 128,
['poison-capsule'] = 64,
['slowdown-capsule'] = 32,
['defender-capsule'] = 96,
['distractor-capsule'] = 512,
['destroyer-capsule'] = 2048,
})
function Public.get_dungeon_evolution_factor(surface_index)
local dungeontable = DungeonsTable.get_dungeontable()
local e = dungeontable.depth[surface_index] * 0.0005
local e = dungeontable.depth[surface_index] * EVOLUTION_PER_FLOOR / 100
if dungeontable.tiered then
e = math.min(e, (surface_index - dungeontable.original_surface_index) * 0.05 + 0.05)
e = math.min(e, (surface_index - dungeontable.original_surface_index) * EVOLUTION_PER_FLOOR + EVOLUTION_PER_FLOOR)
end
return e
end
function Public.get_loot_evolution_factor(surface_index)
return Public.get_dungeon_evolution_factor(surface_index) * LOOT_EVOLUTION_SCALE_FACTOR
end
local function blacklist(surface_index, special)
local dungeontable = DungeonsTable.get_dungeontable()
local evolution_factor = Public.get_dungeon_evolution_factor(surface_index)
local evolution_factor = Public.get_loot_evolution_factor(surface_index)
if special then
-- treasure rooms act as if they are 3 levels farther down.
evolution_factor = evolution_factor + 3 * EVOLUTION_PER_FLOOR
end
local blacklists = {}
--general unused items on dungeons
blacklists['cliff-explosives'] = true
--items that would trivialize stuff if dropped too early
if dungeontable.item_blacklist and not special then
if evolution_factor < 0.9 then
blacklists['discharge-defense-equipment'] = true
if dungeontable.item_blacklist then
if evolution_factor < 0.9 then -- floor 18
blacklists['power-armor-mk2'] = true
blacklists['fusion-reactor-equipment'] = true
blacklists['rocket-silo'] = true
blacklists['discharge-defense-remote'] = true
blacklists['atomic-bomb'] = true
end
if evolution_factor < 0.7 then
if evolution_factor < 0.7 then -- floor 14
blacklists['energy-shield-mk2-equipment'] = true
blacklists['personal-laser-defense-equipment'] = true
blacklists['personal-roboport-mk2-equipment'] = true
blacklists['battery-mk2-equipment'] = true
blacklists['nuclear-reactor'] = true
blacklists['artillery-turret'] = true
blacklists['artillery-wagon'] = true
blacklists['power-armor'] = true
end
if evolution_factor < 0.4 then
if evolution_factor < 0.55 then -- floor 11
blacklists['discharge-defense-equipment'] = true
blacklists['discharge-defense-remote'] = true
blacklists['nuclear-reactor'] = true
end
if evolution_factor < 0.4 then -- floor 8
blacklists['steam-turbine'] = true
blacklists['heat-exchanger'] = true
blacklists['heat-pipe'] = true
blacklists['express-loader'] = true
blacklists['modular-armor'] = true
blacklists['solar-panel-equipment'] = true
blacklists['energy-shield-equipment'] = true
blacklists['battery-equipment'] = true
blacklists['solar-panel-equipment'] = true
end
end
return blacklists
@ -99,13 +143,21 @@ function Public.get_common_resource_amount(surface_index)
local amount = math_random(350, 700) + Public.get_dungeon_evolution_factor(surface_index) * 16000
if dungeontable.tiered then
amount = amount / 8
local floor = surface_index - dungeontable.original_surface_index
-- rocks stop going up here, so more than make up for it in resources on ground
if floor > FLOOR_FOR_MAX_ROCK_ORE then
amount = amount * (1+(floor - FLOOR_FOR_MAX_ROCK_ORE)/10)
end
end
return amount
end
function Public.get_base_loot_value(surface_index)
return Public.get_loot_evolution_factor(surface_index) * LOOT_MULTIPLIER
end
local function get_loot_value(surface_index, multiplier)
local value = Public.get_dungeon_evolution_factor(surface_index) * 4000 * multiplier
return value
return Public.get_base_loot_value(surface_index) * multiplier
end
function Public.common_loot_crate(surface, position, special)
@ -138,6 +190,9 @@ end
function Public.epic_loot_crate(surface, position, special)
local dungeontable = DungeonsTable.get_dungeontable()
local loot_value = get_loot_value(surface.index, 8) + math_random(512, 1024)
if special then
loot_value = loot_value * 1.5
end
local bonus_loot = nil
if dungeontable.tiered and loot_value > 32000 and Public.get_dungeon_evolution_factor(surface.index) > 1 then
local bonus = special_loot(loot_value)
@ -217,6 +272,7 @@ function Public.laboratory(surface, position)
lab.minable = false
local evo = Public.get_dungeon_evolution_factor(surface.index)
local amount = math.min(200, math_floor(evo * 100))
amount = math.max(amount, 1)
lab.insert({name = 'automation-science-pack', count = math.min(200, math_floor(amount * 5))})
if evo >= 0.1 then
lab.insert({name = 'logistic-science-pack', count = math.min(200, math_floor(amount * 4))})
@ -332,17 +388,31 @@ function Public.create_scrap(surface, position)
surface.create_entity({name = scraps[math_random(1, #scraps)], position = position, force = 'neutral'})
end
function Public.on_marked_for_deconstruction(event)
local disabled_for_deconstruction = {
['fish'] = true,
['rock-huge'] = true,
['rock-big'] = true,
['sand-rock-big'] = true,
['crash-site-spaceship-wreck-small-1'] = true,
['crash-site-spaceship-wreck-small-2'] = true,
['crash-site-spaceship-wreck-small-3'] = true,
['crash-site-spaceship-wreck-small-4'] = true,
['crash-site-spaceship-wreck-small-5'] = true,
['crash-site-spaceship-wreck-small-6'] = true
}
if event.entity and event.entity.valid then
if disabled_for_deconstruction[event.entity.name] then
event.entity.cancel_deconstruction(game.players[event.player_index].force.name)
end
end
end
local function get_ore_amount(surface_index)
local scaling = game.forces.player.mining_drill_productivity_bonus
local amount = 5000 * Public.get_dungeon_evolution_factor(surface_index) * (1 + scaling)
if amount > 500 then
amount = 500
end
amount = math_random(math_floor(amount * 0.7), math_floor(amount * 1.3))
if amount < 1 then
amount = 1
end
return amount
local floor = surface_index - DungeonsTable.get_dungeontable().original_surface_index
local amount = FLOOR_ZERO_ROCK_ORE + ROCK_ORE_INCREASE_PER_FLOOR * math.min(FLOOR_FOR_MAX_ROCK_ORE, floor)
return math_random(math_floor(amount * 0.7), math_floor(amount * 1.3))
end
local function reward_ores(amount, mined_loot, surface, player, entity)
@ -399,7 +469,17 @@ function Public.rocky_loot(event)
end
local player = game.players[event.player_index]
local amount = math.ceil(get_ore_amount(player.surface.index))
local rock_mining = {'iron-ore', 'iron-ore', 'iron-ore', 'iron-ore', 'copper-ore', 'copper-ore', 'copper-ore', 'stone', 'stone', 'coal', 'coal'}
local rock_mining
local floor = player.surface.index - DungeonsTable.get_dungeontable().original_surface_index;
if floor < 10 then
-- early game science uses less copper and more iron/stone
rock_mining = {'iron-ore', 'iron-ore', 'iron-ore', 'iron-ore', 'copper-ore', 'copper-ore', 'stone', 'stone', 'coal', 'coal', 'coal'}
else
-- end game prod 3 base uses (for all-sciences) 1 stone : 2 coal : 3.5 copper : 4.5 iron
-- this is a decent approximation which will still require some modest amount of mining setup
-- coal gets 3 to compensate for coal-based power generation
rock_mining = {'iron-ore', 'iron-ore', 'iron-ore', 'iron-ore', 'copper-ore', 'copper-ore', 'copper-ore', 'stone', 'coal', 'coal', 'coal'}
end
local mined_loot = rock_mining[math_random(1, #rock_mining)]
local text = '+' .. amount .. ' [item=' .. mined_loot .. ']'
flying_text(player.surface, player.position, text, {r = 0.98, g = 0.66, b = 0.22})

View File

@ -30,19 +30,6 @@ local math_abs = math.abs
local math_floor = math.floor
local math_round = math.round
local disabled_for_deconstruction = {
['fish'] = true,
['rock-huge'] = true,
['rock-big'] = true,
['sand-rock-big'] = true,
['crash-site-spaceship-wreck-small-1'] = true,
['crash-site-spaceship-wreck-small-2'] = true,
['crash-site-spaceship-wreck-small-3'] = true,
['crash-site-spaceship-wreck-small-4'] = true,
['crash-site-spaceship-wreck-small-5'] = true,
['crash-site-spaceship-wreck-small-6'] = true
}
local function get_biome(position)
--if not a then return "concrete" end
if position.x ^ 2 + position.y ^ 2 < 6400 then
@ -359,12 +346,6 @@ local function on_entity_died(event)
expand(entity.surface, entity.position)
end
local function on_marked_for_deconstruction(event)
if disabled_for_deconstruction[event.entity.name] then
event.entity.cancel_deconstruction(game.players[event.player_index].force.name)
end
end
local function on_init()
local dungeontable = DungeonsTable.get_dungeontable()
local force = game.create_force('dungeon')
@ -445,7 +426,7 @@ end
local Event = require 'utils.event'
Event.on_init(on_init)
--Event.add(defines.events.on_tick, on_tick)
Event.add(defines.events.on_marked_for_deconstruction, on_marked_for_deconstruction)
Event.add(defines.events.on_marked_for_deconstruction, Functions.on_marked_for_deconstruction)
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
Event.add(defines.events.on_player_mined_entity, on_player_mined_entity)
Event.add(defines.events.on_chunk_generated, on_chunk_generated)

518
maps/dungeons/research.lua Normal file
View File

@ -0,0 +1,518 @@
--- Tuning factors
local first_research_room_min = 60
local first_research_floor_scale = 1
local last_research_room_max = 300
local last_research_floor_scale = 2.5
-- Early technologies are cheap and we have lots of excess resources for them. Slow down the early part of the
-- game and lower the technology price as people explore the dungeon to speed up the latter part of the game
local tech_scale_start_price = 20
local tech_scale_end_price = 5
local tech_scale_end_level = 25
---
local Global = require 'utils.global'
local DungeonsTable = require 'maps.dungeons.table'
local function dungeon_table()
return DungeonsTable.get_dungeontable()
end
local function floor_num(index)
return index - dungeon_table().original_surface_index
end
local function floor_size(index)
return dungeon_table().surface_size[index]
end
local function rooms_opened(index)
local d = dungeon_table()
local f = index - d.original_surface_index
if index > #d.depth then
return 0
end
return d.depth[index] - f * 100
end
-- variant 1, fixed set of research with 1 on specific floors
local Fixed = {}
local locked_researches = {
[0] = 'steel-axe',
[1] = 'heavy-armor',
[2] = 'military-2',
[3] = 'physical-projectile-damage-2',
[4] = 'oil-processing',
[5] = 'stronger-explosives-2',
[6] = 'military-science-pack',
[7] = 'rocketry',
[8] = 'chemical-science-pack',
[9] = 'military-3',
[10] = 'flamethrower',
[11] = 'distractor',
[12] = 'laser',
[13] = 'laser-shooting-speed-3',
[14] = 'power-armor',
[15] = 'nuclear-power',
[16] = 'production-science-pack',
[17] = 'energy-weapons-damage-3',
[18] = 'utility-science-pack',
[19] = 'kovarex-enrichment-process',
[20] = 'power-armor-mk2',
[22] = 'fusion-reactor-equipment',
[24] = 'discharge-defense-equipment',
[30] = 'atomic-bomb',
[35] = 'spidertron'
}
function Fixed.Init()
game.difficulty_settings.technology_price_multiplier = 3
for _, tech in pairs(locked_researches) do
game.forces.player.technologies[tech].enabled = false
end
end
local function get_surface_research(index)
return locked_researches[floor_num(index)]
end
function Fixed.techs_remain(index)
local tech = get_surface_research(index)
if tech and game.forces.player.technologies[tech].enabled == false then
return 1
end
return 0
end
function Fixed.unlock_research(surface_index)
local techs = game.forces.player.technologies
local tech = get_surface_research(surface_index)
if tech and techs[tech].enabled == false then
techs[tech].enabled = true
game.print({'dungeons_tiered.tech_unlock', '[technology=' .. tech .. ']', floor_num(surface_index)})
end
end
function Fixed.room_is_lab(index)
if floor_size(index) < 225 or math.random(1, 50) ~= 1 then
return false
end
local tech = get_surface_research(index)
return tech and game.forces.player.technologies[tech].enabled == false
end
function Fixed.noop()
end
Fixed.noop() -- eliminate luacheck warning
-- Variant 2, all research needs unlocking, several can be found on each floor
-- and the research is semi-randomly distributed. Research packs occur at the
-- first half of the ranges.
--
-- target most research found by floor 25; atomic bomb and spidertron 25-35
-- red(0-1), green(2-5), gray(4-9), blue(7-12),
-- blue/gray (10-14), purple(12-19), yellow(14-21), white(20-25)
local state = {}
local Variable = {}
Global.register(state, function(s) state = s end)
-- red floor 0&1 6.5
-- green floor 1-5 31/5 = 7.75
-- green floor 4-7 13/4 = 3.25
-- gray floor 6-9 14/4 = 3.5
-- blue 31
-- blue/gray 22
-- purple 18
-- yellow 46
-- white 10
-- spider/atomic 2
local all_research = {
-- always found on 0
-- { name = "automation", min = 0, max = 0 }, -- specially handled to always be found first.
{ name = "gun-turret", min = 0, max = 0 },
{ name = "logistics", min = 0, max = 0 },
{ name = "military", min = 0, max = 0 },
{ name = "stone-wall", min = 0, max = 0 },
{ name = "steel-axe", min = 0, max = 0 },
{ name = "steel-processing", min = 0, max = 0 },
{ name = "heavy-armor", min = 0, max = 0 },
{ name = "electronics", min = 0, max = 0 },
{ name = "fast-inserter", min = 1, max = 1 },
{ name = "optics", min = 1, max = 1 },
{ name = "weapon-shooting-speed-1", min = 1, max = 1 },
{ name = "physical-projectile-damage-1", min = 1, max = 1 },
-- green research (31+13)
{ name = "logistic-science-pack", min = 1, max = 1 },
{ name = "military-2", min = 1, max = 5 },
{ name = "automation-2", min = 1, max = 5 },
{ name = "fluid-handling", min = 1, max = 5 },
{ name = "flammables", min = 1, max = 5 },
{ name = "battery-equipment", min = 1, max = 5 },
{ name = "modules", min = 1, max = 5 },
{ name = "speed-module", min = 1, max = 5 },
{ name = "productivity-module", min = 1, max = 5 },
{ name = "effectivity-module", min = 1, max = 5 },
{ name = "advanced-material-processing", min = 1, max = 5 },
{ name = "circuit-network", min = 1, max = 5 },
{ name = "explosives", min = 1, max = 5 },
{ name = "toolbelt", min = 1, max = 5 },
{ name = "engine", min = 1, max = 5 },
{ name = "oil-processing", min = 1, max = 5 },
{ name = "stronger-explosives-1", min = 1, max = 5 },
{ name = "modular-armor", min = 1, max = 5 },
{ name = "solar-panel-equipment", min = 1, max = 5 },
{ name = "electric-energy-distribution-1", min = 1, max = 5 },
{ name = "battery", min = 1, max = 5 },
{ name = "electric-energy-accumulators", min = 1, max = 5 },
{ name = "stack-inserter", min = 1, max = 5 },
{ name = "sulfur-processing", min = 1, max = 5 },
{ name = "advanced-electronics", min = 1, max = 5 },
{ name = "logistics-2", min = 1, max = 5 },
{ name = "plastics", min = 1, max = 5 },
{ name = "physical-projectile-damage-2", min = 1, max = 5 },
{ name = "weapon-shooting-speed-2", min = 1, max = 5 },
{ name = "solar-energy", min = 1, max = 5 },
{ name = "mining-productivity-1", min = 1, max = 5 },
{ name = "night-vision-equipment", min = 3, max = 8 },
{ name = "belt-immunity-equipment", min = 3, max = 8 },
{ name = "railway", min = 3, max = 8 },
{ name = "automated-rail-transportation", min = 3, max = 8 },
{ name = "gate", min = 3, max = 8 },
{ name = "rail-signals", min = 3, max = 8 },
{ name = "research-speed-1", min = 3, max = 8 },
{ name = "automobilism", min = 3, max = 8 },
{ name = "fluid-wagon", min = 3, max = 8 },
{ name = "inserter-capacity-bonus-1", min = 3, max = 8 },
{ name = "concrete", min = 3, max = 8 },
{ name = "research-speed-2", min = 3, max = 8 },
{ name = "inserter-capacity-bonus-2", min = 3, max = 8 },
-- gray research (14)
{ name = "military-science-pack", min = 4, max = 5 },
{ name = "flamethrower", min = 5, max = 10 },
{ name = "refined-flammables-1", min = 5, max = 10 },
{ name = "defender", min = 5, max = 10 },
{ name = "rocketry", min = 5, max = 10 },
{ name = "energy-shield-equipment", min = 5, max = 10 },
{ name = "stronger-explosives-2", min = 5, max = 10 },
{ name = "follower-robot-count-1", min = 5, max = 10 },
{ name = "physical-projectile-damage-3", min = 5, max = 10 },
{ name = "weapon-shooting-speed-3", min = 5, max = 10 },
{ name = "refined-flammables-2", min = 5, max = 10 },
{ name = "follower-robot-count-2", min = 5, max = 10 },
{ name = "physical-projectile-damage-4", min = 5, max = 10 },
{ name = "weapon-shooting-speed-4", min = 5, max = 10 },
-- blue research 31
{ name = "chemical-science-pack", min = 7, max = 8 },
{ name = "electric-engine", min = 8, max = 13 },
{ name = "lubricant", min = 8, max = 13 },
{ name = "personal-roboport-equipment", min = 8, max = 13 },
{ name = "worker-robots-speed-1", min = 8, max = 13 },
{ name = "exoskeleton-equipment", min = 8, max = 13 },
{ name = "robotics", min = 8, max = 13 },
{ name = "advanced-oil-processing", min = 8, max = 13 },
{ name = "speed-module-2", min = 8, max = 13 },
{ name = "productivity-module-2", min = 8, max = 13 },
{ name = "effectivity-module-2", min = 8, max = 13 },
{ name = "laser", min = 8, max = 13 },
{ name = "braking-force-1", min = 8, max = 13 },
{ name = "electric-energy-distribution-2", min = 8, max = 13 },
{ name = "construction-robotics", min = 8, max = 13 },
{ name = "battery-mk2-equipment", min = 8, max = 13 },
{ name = "worker-robots-storage-1", min = 8, max = 13 },
{ name = "uranium-processing", min = 8, max = 13 },
{ name = "power-armor", min = 8, max = 13 },
{ name = "advanced-material-processing-2", min = 8, max = 13 },
{ name = "logistic-robotics", min = 8, max = 13 },
{ name = "research-speed-3", min = 8, max = 13 },
{ name = "inserter-capacity-bonus-3", min = 8, max = 13 },
{ name = "advanced-electronics-2", min = 8, max = 13 },
{ name = "low-density-structure", min = 8, max = 13 },
{ name = "rocket-fuel", min = 8, max = 13 },
{ name = "mining-productivity-2", min = 8, max = 13 },
{ name = "nuclear-power", min = 8, max = 13 },
{ name = "worker-robots-speed-2", min = 8, max = 13 },
{ name = "braking-force-2", min = 8, max = 13 },
{ name = "research-speed-4", min = 8, max = 13 },
-- blue/gray research
{ name = "laser-shooting-speed-1", min = 10, max = 14 },
{ name = "military-3", min = 10, max = 14 },
{ name = "explosive-rocketry", min = 10, max = 14 },
{ name = "energy-weapons-damage-1", min = 10, max = 14 },
{ name = "laser-shooting-speed-2", min = 10, max = 14 },
{ name = "personal-laser-defense-equipment", min = 10, max = 14 },
{ name = "discharge-defense-equipment", min = 10, max = 14 },
{ name = "laser-turret", min = 10, max = 14 },
{ name = "distractor", min = 10, max = 14 },
{ name = "energy-shield-mk2-equipment", min = 10, max = 14 },
{ name = "tank", min = 10, max = 14 },
{ name = "refined-flammables-3", min = 10, max = 14 },
{ name = "stronger-explosives-3", min = 10, max = 14 },
{ name = "follower-robot-count-3", min = 10, max = 14 },
{ name = "physical-projectile-damage-5", min = 10, max = 14 },
{ name = "weapon-shooting-speed-5", min = 10, max = 14 },
{ name = "energy-weapons-damage-2", min = 10, max = 14 },
{ name = "energy-weapons-damage-3", min = 10, max = 14 },
{ name = "energy-weapons-damage-4", min = 10, max = 14 },
{ name = "laser-shooting-speed-3", min = 10, max = 14 },
{ name = "laser-shooting-speed-4", min = 10, max = 14 },
{ name = "follower-robot-count-4", min = 10, max = 14 },
-- purple research
{ name = "production-science-pack", min = 11, max = 12 },
{ name = "nuclear-fuel-reprocessing", min = 12, max = 19 },
{ name = "effect-transmission", min = 12, max = 19 },
{ name = "automation-3", min = 12, max = 19 },
{ name = "coal-liquefaction", min = 12, max = 19 },
{ name = "braking-force-3", min = 12, max = 19 },
{ name = "inserter-capacity-bonus-4", min = 12, max = 19 },
{ name = "logistics-3", min = 12, max = 19 },
{ name = "worker-robots-storage-2", min = 12, max = 19 },
{ name = "speed-module-3", min = 12, max = 19 },
{ name = "productivity-module-3", min = 12, max = 19 },
{ name = "effectivity-module-3", min = 12, max = 19 },
{ name = "research-speed-5", min = 12, max = 19 },
{ name = "kovarex-enrichment-process", min = 12, max = 19 },
{ name = "inserter-capacity-bonus-5", min = 12, max = 19 },
{ name = "inserter-capacity-bonus-6", min = 12, max = 19 },
{ name = "braking-force-4", min = 12, max = 19 },
{ name = "braking-force-5", min = 12, max = 19 },
-- yellow research
{ name = "utility-science-pack", min = 13, max = 14 },
{ name = "worker-robots-speed-3", min = 14, max = 21 },
{ name = "worker-robots-speed-4", min = 14, max = 21 },
{ name = "worker-robots-speed-5", min = 14, max = 21 },
{ name = "worker-robots-speed-6", min = 14, max = 21 },
{ name = "personal-roboport-mk2-equipment", min = 14, max = 21 },
{ name = "rocket-control-unit", min = 14, max = 21 },
{ name = "logistic-system", min = 14, max = 21 },
{ name = "military-4", min = 14, max = 21 },
{ name = "fusion-reactor-equipment", min = 14, max = 21 },
{ name = "destroyer", min = 14, max = 21 },
{ name = "refined-flammables-4", min = 14, max = 21 },
{ name = "refined-flammables-5", min = 14, max = 21 },
{ name = "refined-flammables-6", min = 14, max = 21 },
{ name = "stronger-explosives-4", min = 14, max = 21 },
{ name = "stronger-explosives-5", min = 14, max = 21 },
{ name = "stronger-explosives-6", min = 14, max = 21 },
{ name = "power-armor-mk2", min = 14, max = 21 },
{ name = "physical-projectile-damage-6", min = 14, max = 21 },
{ name = "weapon-shooting-speed-6", min = 14, max = 21 },
{ name = "uranium-ammo", min = 14, max = 21 },
{ name = "artillery", min = 14, max = 21 },
{ name = "worker-robots-storage-3", min = 14, max = 21 },
{ name = "research-speed-6", min = 14, max = 21 },
{ name = "mining-productivity-3", min = 14, max = 21 },
{ name = "laser-shooting-speed-5", min = 14, max = 21 },
{ name = "laser-shooting-speed-6", min = 14, max = 21 },
{ name = "laser-shooting-speed-7", min = 14, max = 21 },
{ name = "energy-weapons-damage-5", min = 14, max = 21 },
{ name = "energy-weapons-damage-6", min = 14, max = 21 },
{ name = "follower-robot-count-5", min = 14, max = 21 },
{ name = "follower-robot-count-6", min = 14, max = 21 },
{ name = "braking-force-6", min = 14, max = 21 },
{ name = "braking-force-7", min = 14, max = 21 },
{ name = "inserter-capacity-bonus-7", min = 14, max = 21 },
-- white science and atomic/spider
{ name = "rocket-silo", min = 19, max = 20 },
{ name = "space-science-pack", min = 19, max = 20 },
{ name = "mining-productivity-4", min = 20, max = 25 },
{ name = "artillery-shell-range-1", min = 20, max = 25 },
{ name = "artillery-shell-speed-1", min = 20, max = 25 },
{ name = "energy-weapons-damage-7", min = 20, max = 25 },
{ name = "physical-projectile-damage-7", min = 20, max = 25 },
{ name = "refined-flammables-7", min = 20, max = 25 },
{ name = "stronger-explosives-7", min = 20, max = 25 },
{ name = "follower-robot-count-7", min = 20, max = 25 },
{ name = "spidertron", min = 22, max = 25 },
{ name = "atomic-bomb", min = 40, max = 50 },
-- -- ["landfill"] = { min = 1, max = 100 },
-- -- ["land-mine"] = { min = 1, max = 100 },
-- -- ["cliff-explosives"] = { min = 1, max = 100 },
}
local function get_research_by_floor(f)
local res = state.research_by_floor[f]
if res ~= nil then
return res
end
res = {}
state.research_by_floor[f] = res
return res
end
function Variable.calculate_distribution()
state.research_by_floor = {}
table.shuffle_table(all_research)
local technologies = game.forces.player.technologies
for i = 1, #all_research do
local v = all_research[i]
local floor1 = math.random(v.min, v.max)
local floor2 = math.random(v.min, v.max)
local res1 = get_research_by_floor(floor1)
local res2 = get_research_by_floor(floor2)
local res = res1
if #res2 < #res1 then
res = res2
end
technologies[v.name].enabled = false
technologies[v.name].visible_when_disabled = true
res[#res+1] = { name = v.name }
-- game.print('floor ' .. floor .. ' gets tech ' .. k .. ' count=' .. #res)
end
-- previous code did rooms_opened > 100 & 2% chance, ~150 mean to find the one tech
-- this is on average a bit easier, but overall probably harder because of the lack of tech
for f = 0, #state.research_by_floor do
local res = state.research_by_floor[f]
if res ~= nil and #res > 0 then
table.shuffle_table(res)
if f == 0 then
res[#res+1] = res[1]
res[1] = { name = "automation", min = 0, max = 0 }
technologies["automation"].enabled = false
technologies["automation"].visible_when_disabled = true
end
local room_max = last_research_room_max + math.ceil(f * last_research_floor_scale)
local min_room = first_research_room_min + math.floor(f * first_research_floor_scale)
local rooms_per_res = math.ceil(room_max - first_research_room_min) / #res
for i = 1,#res do
local range_min = min_room + rooms_per_res * (i - 1)
res[i].room = math.random(range_min, range_min + rooms_per_res - 1)
end
end
end
end
function Variable.LivePatch()
local d = dungeon_table()
Variable.calculate_distribution()
for f = 0, #state.research_by_floor do
local res = state.research_by_floor[f]
local rooms = rooms_opened(f + d.original_surface_index)
while res ~= nil and #res > 0 and res[1].room <= rooms do
local tech = res[1]
table.remove(res, 1)
game.forces.player.technologies[tech.name].enabled = true
game.print('live patch unlocked ' .. tech.name .. ' on floor ' .. f)
end
end
end
local function res_to_string(res)
local ret = {}
for f = 1, #res do
ret[f] = res[f].name .. "@" .. res[f].room
end
return ret
end
function Variable.dump_techs(max_floor)
if max_floor == nil then
max_floor = #state.research_by_floor
end
for f = 0, max_floor do
local res = state.research_by_floor[f]
if res == nil then
game.print('Floor ' .. f .. ': nothing remains')
else
game.print('Floor ' .. f .. ': ' .. #res .. ' ' .. table.concat(res_to_string(res), ' '))
end
end
end
function Variable.Init()
game.difficulty_settings.technology_price_multiplier = tech_scale_start_price
Variable.calculate_distribution()
end
function Variable.techs_remain(index)
if state.research_by_floor == nil then
return -999
end
local floor = floor_num(index)
if state.research_by_floor[floor] == nil then
return 0
end
return #state.research_by_floor[floor]
end
function Variable.relock_research()
for f = 0, #state.research_by_floor do
local res = state.research_by_floor[f]
if res ~= nil then
for r = 1, #res do
if game.forces.player.technologies[res[r].name].enabled then
game.print('BUGFIX: ' .. res[r].name .. ' was incorrectly enabled')
game.forces.player.technologies[res[r].name].enabled = false
end
end
end
end
end
function Variable.unlock_research(index)
Variable.relock_research()
local floor = floor_num(index)
local res = state.research_by_floor[floor]
if res == nil or #res == 0 then
game.print('BUG: tried to unlock research on ' .. index .. ' but none remain')
return
end
local tech = res[1]
table.remove(res, 1)
if game.forces.player.technologies[tech.name].enabled then
game.print('BUG: attempt to duplicate-unlock technology ' .. tech.name)
return
end
game.forces.player.technologies[tech.name].enabled = true
game.print({'dungeons_tiered.tech_unlock', '[technology=' .. tech.name .. ']', floor})
local floor_fraction = (tech_scale_end_level - floor) / tech_scale_end_level
if floor_fraction < 0 then
floor_fraction = 0
end
local tech_multiplier = tech_scale_end_price +
(tech_scale_start_price - tech_scale_end_price) * floor_fraction
if tech_multiplier < game.difficulty_settings.technology_price_multiplier then
game.difficulty_settings.technology_price_multiplier = tech_multiplier
game.print('Finding technology on floor ' .. floor .. ' made research easier')
end
Variable.relock_research()
end
function Variable.room_is_lab(index)
local res = state.research_by_floor[floor_num(index)]
if res == nil or #res == 0 then
return false
end
if game.forces.player.technologies[res[1].name].enabled then
game.print('BUG: attempt to duplicate-unlock technology ' .. res[1].name)
return false
end
return rooms_opened(index) >= res[1].room
end
function Variable.noop()
end
Variable.noop() -- eliminate luacheck warning if return Fixed is used
-- return Fixed
return Variable

View File

@ -4,6 +4,9 @@ require 'modules.mineable_wreckage_yields_scrap'
require 'modules.satellite_score'
require 'modules.charging_station'
-- Tuning constants
local MIN_ROOMS_TO_DESCEND = 100
local MapInfo = require 'modules.map_info'
local Room_generator = require 'functions.room_generator'
local RPG = require 'modules.rpg.main'
@ -12,8 +15,16 @@ local BiterRaffle = require 'functions.biter_raffle'
local Functions = require 'maps.dungeons.functions'
local Get_noise = require 'utils.get_noise'
local Alert = require 'utils.alert'
local Research = require 'maps.dungeons.research'
local DungeonsTable = require 'maps.dungeons.table'
local BottomFrame = require 'utils.gui.bottom_frame'
local Autostash = require 'modules.autostash'
local Panel = require 'utils.gui.config'
Panel.get('gui_config').spaghett.noop = true
local Collapse = require 'modules.collapse'
local Changelog = require 'modules.changelog'
require 'maps.dungeons.boss_arena'
require 'modules.melee_mode'
local Biomes = {}
Biomes.dirtlands = require 'maps.dungeons.biome_dirtlands'
@ -33,18 +44,17 @@ Biomes.laboratory = require 'maps.dungeons.biome_laboratory'
local math_random = math.random
local math_round = math.round
local disabled_for_deconstruction = {
['fish'] = true,
['rock-huge'] = true,
['rock-big'] = true,
['sand-rock-big'] = true,
['crash-site-spaceship-wreck-small-1'] = true,
['crash-site-spaceship-wreck-small-2'] = true,
['crash-site-spaceship-wreck-small-3'] = true,
['crash-site-spaceship-wreck-small-4'] = true,
['crash-site-spaceship-wreck-small-5'] = true,
['crash-site-spaceship-wreck-small-6'] = true
}
local function enable_hard_rooms(position, surface_index)
local dungeon_table = DungeonsTable.get_dungeontable()
local floor = surface_index - dungeon_table.original_surface_index
-- can make it out to ~200 before hitting the "must explore more" limit
-- 140 puts hard rooms halfway between the only dirtlands and the edge
local floor_mindist = 140 - floor * 10
if floor_mindist < 80 then -- all dirtlands within this
return true
end
return position.x ^ 2 + position.y ^ 2 > floor_mindist^2
end
local function get_biome(position, surface_index)
--if not a then return "concrete" end
@ -59,17 +69,21 @@ local function get_biome(position, surface_index)
if Get_noise('dungeons', position, seed + seed_addition * a) > 0.66 then
return 'glitch'
end
a = a + 1
if Get_noise('dungeons', position, seed + seed_addition * a) > 0.60 then
return 'doom'
end
a = a + 1
if Get_noise('dungeons', position, seed + seed_addition * a) > 0.62 then
return 'acid_zone'
end
a = a + 1
if Get_noise('dungeons', position, seed + seed_addition * a) > 0.60 then
return 'concrete'
if enable_hard_rooms(position, surface_index) then
a = a + 1
if Get_noise('dungeons', position, seed + seed_addition * a) > 0.60 then
return 'doom'
end
a = a + 1
if Get_noise('dungeons', position, seed + seed_addition * a) > 0.62 then
return 'acid_zone'
end
a = a + 1
if Get_noise('dungeons', position, seed + seed_addition * a) > 0.60 then
return 'concrete'
end
else
a = a + 3
end
a = a + 1
if Get_noise('dungeons', position, seed + seed_addition * a) > 0.71 then
@ -95,34 +109,6 @@ local function get_biome(position, surface_index)
return 'dirtlands'
end
local locked_researches = {
[0] = 'steel-axe',
[1] = 'heavy-armor',
[2] = 'military-2',
[3] = 'physical-projectile-damage-2',
[4] = 'oil-processing',
[5] = 'stronger-explosives-2',
[6] = 'military-science-pack',
[7] = 'rocketry',
[8] = 'chemical-science-pack',
[9] = 'military-3',
[10] = 'flamethrower',
[11] = 'distractor',
[12] = 'laser',
[13] = 'laser-shooting-speed-3',
[14] = 'power-armor',
[15] = 'nuclear-power',
[16] = 'production-science-pack',
[17] = 'energy-weapons-damage-3',
[18] = 'utility-science-pack',
[19] = 'kovarex-enrichment-process',
[20] = 'power-armor-mk2',
[22] = 'fusion-reactor-equipment',
[24] = 'discharge-defense-equipment',
[30] = 'atomic-bomb',
[35] = 'spidertron'
}
local function draw_arrows_gui()
for _, player in pairs(game.connected_players) do
if not player.gui.top.dungeon_down then
@ -134,20 +120,12 @@ local function draw_arrows_gui()
end
end
local function get_surface_research(index)
local dungeontable = DungeonsTable.get_dungeontable()
return locked_researches[index - dungeontable.original_surface_index]
end
local function draw_depth_gui()
local dungeontable = DungeonsTable.get_dungeontable()
local forceshp = BiterHealthBooster.get('biter_health_boost_forces')
for _, player in pairs(game.connected_players) do
local surface = player.surface
local techs = 0
if get_surface_research(surface.index) and game.forces.player.technologies[get_surface_research(surface.index)].enabled == false then
techs = 1
end
local techs = Research.techs_remain(surface.index)
local enemy_force = dungeontable.enemy_forces[surface.index]
if player.gui.top.dungeon_depth then
player.gui.top.dungeon_depth.destroy()
@ -162,7 +140,7 @@ local function draw_depth_gui()
Functions.get_dungeon_evolution_factor(surface.index) * 100,
forceshp[enemy_force.index] * 100,
math_round(enemy_force.get_ammo_damage_modifier('melee') * 100 + 100, 1),
Functions.get_dungeon_evolution_factor(surface.index) * 2000,
Functions.get_base_loot_value(surface.index),
dungeontable.treasures[surface.index],
techs
}
@ -180,15 +158,6 @@ local function draw_depth_gui()
end
end
local function unlock_researches(surface_index)
local dungeontable = DungeonsTable.get_dungeontable()
local tech = game.forces.player.technologies
if get_surface_research(surface_index) and tech[get_surface_research(surface_index)].enabled == false then
tech[get_surface_research(surface_index)].enabled = true
game.print({'dungeons_tiered.tech_unlock', '[technology=' .. get_surface_research(surface_index) .. ']', surface_index - dungeontable.original_surface_index})
end
end
local function expand(surface, position)
local dungeontable = DungeonsTable.get_dungeontable()
local forceshp = BiterHealthBooster.get('biter_health_boost_forces')
@ -208,19 +177,18 @@ local function expand(surface, position)
if not room then
return
end
if dungeontable.treasures[surface.index] < 5 and dungeontable.surface_size[surface.index] >= 225 and math.random(1, 50) == 1 then
local treasure_room_one_in = 30 + 15 * dungeontable.treasures[surface.index]
if dungeontable.surface_size[surface.index] >= 225 and math.random(1, treasure_room_one_in) == 1 and room.room_tiles[1] then
log('Found treasure room, change was 1 in ' .. treasure_room_one_in)
Biomes['treasure'](surface, room)
if room.room_tiles[1] then
dungeontable.treasures[surface.index] = dungeontable.treasures[surface.index] + 1
game.print({'dungeons_tiered.treasure_room', surface.index - dungeontable.original_surface_index}, {r = 0.88, g = 0.22, b = 0})
end
elseif
dungeontable.surface_size[surface.index] >= 225 and math.random(1, 50) == 1 and get_surface_research(surface.index) and
game.forces.player.technologies[get_surface_research(surface.index)].enabled == false
then
elseif Research.room_is_lab(surface.index) then
Biomes['laboratory'](surface, room)
if room.room_tiles[1] then
unlock_researches(surface.index)
Research.unlock_research(surface.index)
end
elseif math_random(1, 256) == 1 then
Biomes['market'](surface, room)
@ -298,14 +266,20 @@ end
local function init_player(player, surface)
if surface == game.surfaces['dungeons_floor0'] then
if player.character then
player.disassociate_character(player.character)
player.disassociate_character(player.character)
player.character.destroy()
end
player.set_controller({type = defines.controllers.god})
player.create_character()
if not player.connected then
log('BUG Player ' .. player.name .. ' is not connected; how did we get here?')
end
player.set_controller({type = defines.controllers.god})
player.teleport(surface.find_non_colliding_position('character', {0, 0}, 50, 0.5), surface)
if not player.create_character() then
log('BUG: create_character for ' .. player.name .. ' failed')
end
player.insert({name = 'raw-fish', count = 8})
player.set_quick_bar_slot(1, 'raw-fish')
player.insert({name = 'pistol', count = 1})
@ -424,7 +398,11 @@ local function on_player_joined_game(event)
end
local player = game.players[event.player_index]
if player.online_time == 0 then
init_player(player, game.surfaces['dungeons_floor0'])
init_player(player, game.surfaces['dungeons_floor0'])
end
if player.character == nil and player.ticks_to_respawn == nil then
log('BUG: ' .. player.name .. ' is missing associated character and is not waiting to respawn')
init_player(player, game.surfaces['dungeons_floor0'])
end
draw_light(player)
end
@ -489,12 +467,12 @@ local function on_player_mined_entity(event)
if not entity.valid then
return
end
local player = game.players[event.player_index]
if entity.name == 'rock-big' then
local size = dungeontable.surface_size[entity.surface.index]
if size < math.abs(entity.position.y) or size < math.abs(entity.position.x) then
entity.surface.create_entity({name = entity.name, position = entity.position})
entity.destroy()
local player = game.players[event.player_index]
RPG.gain_xp(player, -10)
Alert.alert_player_warning(player, 30, {'dungeons_tiered.too_small'}, {r = 0.98, g = 0.22, b = 0})
event.buffer.clear()
@ -527,14 +505,6 @@ local function on_entity_died(event)
expand(entity.surface, entity.position)
end
local function on_marked_for_deconstruction(event)
if event.entity and event.entity.valid then
if disabled_for_deconstruction[event.entity.name] then
event.entity.cancel_deconstruction(game.players[event.player_index].force.name)
end
end
end
local function get_map_gen_settings()
local settings = {
['seed'] = math_random(1, 1000000),
@ -557,8 +527,9 @@ local function get_lowest_safe_floor(player)
local level = rpg[player.index].level
local sizes = dungeontable.surface_size
local safe = dungeontable.original_surface_index
local min_size = 200 + MIN_ROOMS_TO_DESCEND / 4
for key, size in pairs(sizes) do
if size > 215 and level >= (key + 1 - dungeontable.original_surface_index) * 10 and game.surfaces[key + 1] then
if size >= min_size and level >= (key + 1 - dungeontable.original_surface_index) * 10 and game.surfaces[key + 1] then
safe = key + 1
else
break
@ -587,8 +558,8 @@ local function descend(player, button, shift)
end
local surface = game.surfaces[player.surface.index + 1]
if not surface then
if dungeontable.surface_size[player.surface.index] < 215 then
player.print({'dungeons_tiered.floor_size_required'})
if dungeontable.surface_size[player.surface.index] < 200 + MIN_ROOMS_TO_DESCEND/4 then
player.print({'dungeons_tiered.floor_size_required', MIN_ROOMS_TO_DESCEND})
return
end
surface = game.create_surface('dungeons_floor' .. player.surface.index - dungeontable.original_surface_index + 1, get_map_gen_settings())
@ -760,6 +731,9 @@ end
-- end
local function on_init()
-- dungeons depends on rpg.main depends on modules.explosives depends on modules.collapse
-- without disabling collapse, it starts logging lots of errors after ~1 week.
Collapse.start_now(false)
local dungeontable = DungeonsTable.get_dungeontable()
local forceshp = BiterHealthBooster.get('biter_health_boost_forces')
local force = game.create_force('dungeon')
@ -796,7 +770,6 @@ local function on_init()
game.map_settings.enemy_expansion.settler_group_min_size = 16
game.map_settings.enemy_expansion.max_expansion_distance = 16
game.map_settings.pollution.enemy_attack_pollution_consumption_modifier = 0.50
game.difficulty_settings.technology_price_multiplier = 3
dungeontable.tiered = true
dungeontable.depth[surface.index] = 0
@ -814,10 +787,13 @@ local function on_init()
game.forces.player.technologies['land-mine'].enabled = false
game.forces.player.technologies['landfill'].enabled = false
game.forces.player.technologies['cliff-explosives'].enabled = false
--recipes to be unlocked through playing--
for _, tech in pairs(locked_researches) do
game.forces.player.technologies[tech].enabled = false
end
Research.Init(dungeontable)
Autostash.insert_into_furnace(true)
Autostash.insert_into_wagon(false)
Autostash.bottom_button(true)
Autostash.set_dungeons_initial_level(surface.index)
BottomFrame.reset()
BottomFrame.activate_custom_buttons(true)
RPG.set_surface_name('dungeons_floor')
local rpg_table = RPG.get('rpg_extra')
rpg_table.personal_tax_rate = 0
@ -860,7 +836,7 @@ end
local Event = require 'utils.event'
Event.on_init(on_init)
Event.on_nth_tick(60, on_tick)
Event.add(defines.events.on_marked_for_deconstruction, on_marked_for_deconstruction)
Event.add(defines.events.on_marked_for_deconstruction, Functions.on_marked_for_deconstruction)
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
Event.add(defines.events.on_player_mined_entity, on_player_mined_entity)
Event.add(defines.events.on_built_entity, on_built_entity)
@ -873,3 +849,48 @@ Event.add(defines.events.on_surface_created, on_surface_created)
Event.add(defines.events.on_gui_click, on_gui_click)
Event.add(defines.events.on_player_changed_surface, on_player_changed_surface)
Event.add(defines.events.on_player_respawned, on_player_respawned)
Changelog.SetVersions({
{ ver = 'next', date = 'the future', desc = 'Make suggestions in the comfy #dungeons discord channel' },
{ ver = '1.1.1', date = '2022-04-10', desc = [[
Balancing patch
* Evolution goes up faster with floor level 0.05/level -> 0.06/level; e.g. floor 20 now like floor 24 before
* Now require 100 open rooms to descend
* Treasure rooms
* Occur less frequently as each subsequent one is found. was 1 in 30 + 10*Nfound now 1 in 30 + 15*Nfound
* Rebalanced ores to match end-game science needs. Was very low on copper
* Loot
* Ammo/follower robot frequency ~0.5x previous
* Loot is calculated at floor evolution * 0.9
* Loot/box down by 0.75x
* Rocks
* Ore from rocks from 25 + 25*floor to 40 + 15*floor capped at floor 15
* Rebalanced to include ~10% more coal to give coal for power
* Require getting to room 100 before you can descend
* Science from rooms 40-160+2.5*floor to 60-300+2.5*floor
* Atomic bomb research moved to 40-50
]]},
{ ver = '1.1', date = '2022-03-13', desc = [[
* All research is now found at random.
* Red science floors 0-1
* Green on floors 1-5
* Gray on floors 5-10
* Blue on floors 8-13
* Blue/gray on floors 10-14
* Purple on floors 12-19
* Yellow on floors 14-21
* White on floors 20-25
* Atomic Bomb/Spidertron on floors 22-25
* Add melee mode toggle to top bar. Keeps weapons in main inventory if possible.
* Ore from rocks nerfed. Used to hit max value on floor 2, now scales up from
floors 0-19 along with ore from rooms. After floor 20 ore from rooms scales up faster.
* Treasure rooms
* Rescaled to have similar total resources regardless of size
* Unlimited number of rooms but lower frequency
* Loot is limited to available loot 3 floors lower, but slightly more total value than before.
* Autostash and corpse clearing from Mountain Fortress enabled
* Harder rooms will occur somewhat farther out on the early floors.
* Spawners and worm counts bounded in early rooms.
]]},
{ ver = '1.0', date = 'past', desc = "Pre-changelog version of multi-floor dungeons" },
})

View File

@ -58,6 +58,12 @@ local function prepare_floaty_text(list, surface, position, name, count)
end
local function chest_is_valid(chest)
if this.dungeons_initial_level ~= nil then
-- transport chests always are valid targets
if chest.name == 'blue-chest' or chest.name == 'red-chest' then
return true
end
end
for _, e in pairs(
chest.surface.find_entities_filtered(
{
@ -685,6 +691,9 @@ function Public.bottom_button(value)
end
end
function Public.set_dungeons_initial_level(value)
this.dungeons_initial_level = value
end
Event.on_configuration_changed(do_whitelist)
Event.on_init(do_whitelist)

72
modules/changelog.lua Normal file
View File

@ -0,0 +1,72 @@
local Gui = require 'utils.gui'
local Token = require 'utils.token'
local module_name = Gui.uid_name()
local changelog = {
versions = {}
}
local Public = {}
function Public.SetVersions(versions)
for i = 1, #versions do
local v = versions[i]
if v.ver == nil or v.date == nil or v.desc == nil then
log('ERROR in changelog.SetVersions missing ver, date or desc from version#' .. i .. ' got:\n' .. serpent.line(v))
return
end
end
changelog.versions = versions
end
local function create_changelog(data)
local frame = data.frame
frame.clear()
frame.style.padding = 4
frame.style.margin = 0
local scroll =
frame.add {
type = 'scroll-pane',
name = 'scroll_changelog',
direction = 'vertical',
horizontal_scroll_policy = 'never',
vertical_scroll_policy = 'auto'
}
for i = 1, #changelog.versions do
local v = changelog.versions[i]
local l = scroll.add {type = 'label', caption = 'Version ' .. v.ver .. ' -- ' .. v.date}
l.style.font = 'heading-1'
l.style.font_color = {r = 0.2, g = 0.9, b = 0.2}
l.style.minimal_width = 780
l.style.horizontal_align = 'center'
l.style.vertical_align = 'center'
local c = scroll.add {type = 'label', caption = v.desc}
c.style.font = 'heading-2'
c.style.single_line = false
c.style.font_color = {r = 0.85, g = 0.85, b = 0.88}
c.style.minimal_width = 780
c.style.horizontal_align = 'left'
c.style.vertical_align = 'center'
local line_v = scroll.add {type = 'line'}
line_v.style.top_margin = 4
line_v.style.bottom_margin = 4
end
end
local create_changelog_token = Token.register(create_changelog)
Gui.on_click(
module_name,
function(event)
local player = event.player
Gui.reload_active_tab(player)
end
)
Gui.add_tab_to_gui({name = module_name, caption = 'Changelog', id = create_changelog_token, admin = false})
return Public

164
modules/melee_mode.lua Normal file
View File

@ -0,0 +1,164 @@
local Event = require 'utils.event'
local Global = require 'utils.global'
local state = {}
Global.register(state, function(s) state = s end)
local function create_gui_button(player)
if player.gui.top.melee_mode then
return
end
local tooltip = 'Melee/Ranged mode toggle. Guns and ammo will stay in inventory in melee mode and be restored in ranged mode'
local b = player.gui.top.add({
type = 'sprite-button',
sprite = 'item/pistol',
name = 'melee_mode',
tooltip = tooltip})
b.style.font_color = {r = 0.11, g = 0.8, b = 0.44}
b.style.font = 'heading-1'
b.style.minimal_height = 40
b.style.maximal_width = 40
b.style.minimal_width = 38
b.style.maximal_height = 38
b.style.padding = 1
b.style.margin = 0
end
local function on_player_joined_game(event)
create_gui_button(game.players[event.player_index])
end
local function move_to_main(player, from, to)
local ret = {}
if from == nil or to == nil then
return {}
end
for i = 1, #from do
local c = from[i]
if c.valid_for_read then
if to.can_insert(c) then
local amt = to.insert(c)
ret[#ret + 1] = { name=c.name, count=amt }
c.count = c.count - amt
else
player.print('Unable to move ' .. c.name .. ' to main inventory')
end
end
end
return ret
end
local function change_to_melee(player)
local main_inv = player.get_main_inventory()
local gun_inv = player.get_inventory(defines.inventory.character_guns)
local ammo_inv = player.get_inventory(defines.inventory.character_ammo)
if main_inv == nil or gun_inv == nil or ammo_inv == nil then
return false
end
local gun_moved = move_to_main(player, gun_inv, main_inv)
local ammo_moved = move_to_main(player, ammo_inv, main_inv)
state[player.index] = { gun = gun_moved, ammo = ammo_moved }
return true
end
local function try_move_from_main(main, to, what)
if what == nil or main == nil or to == nil then
return
end
for i = 1, #what do
local amt_out = main.remove(what[i])
if amt_out > 0 then
local amt_in = to.insert({name = what[i].name, count = amt_out})
if amt_in < amt_out then
main.insert({name = what[i].name, count = amt_out - amt_in})
end
end
end
end
local function change_to_ranged(player)
local moved = state[player.index]
if moved == nil then
moved = {}
end
local main_inv = player.get_main_inventory()
local gun_inv = player.get_inventory(defines.inventory.character_guns)
local ammo_inv = player.get_inventory(defines.inventory.character_ammo)
if main_inv == nil or gun_inv == nil or ammo_inv == nil then
return false
end
try_move_from_main(main_inv, gun_inv, moved.gun)
try_move_from_main(main_inv, ammo_inv, moved.ammo)
state[player.index] = {}
return true
end
local function on_gui_click(event)
if not event.element then
return
end
if not event.element.valid then
return
end
if event.element.name ~= 'melee_mode' then
return
end
local player = game.players[event.player_index]
local mm = player.gui.top.melee_mode
if mm.sprite == 'item/pistol' then
if change_to_melee(player) then
player.print('Switching to melee mode, ammo and weapons will stay in main inventory')
mm.sprite = 'item/dummy-steel-axe'
else
player.print('Unable to switch to melee mode. Are you dead?')
end
else
if change_to_ranged(player) then
player.print('Switching to ranged mode, trying to restore previous guns and ammo')
mm.sprite = 'item/pistol'
else
player.print('Unable to switch to ranged mode. Are you dead?')
end
end
end
local function moved_to_string(tbl)
local ret = ''
for i = 1, #tbl do
if ret ~= '' then
ret = ret .. ', '
end
ret = ret .. tbl[i].count .. ' ' .. tbl[i].name
end
return ret
end
local function player_inventory_changed(player_index, inv_id, name)
local player = game.players[player_index]
if player.gui.top.melee_mode.sprite == 'item/pistol' then
return
end
local inv = player.get_inventory(inv_id)
local moved = move_to_main(player, inv, player.get_main_inventory())
if #moved > 0 then
player.print('In melee mode, moved ' .. moved_to_string(moved) .. ' to main inventory')
end
if not inv.is_empty() then
player.print('WARNING: in melee mode, unable to empty ' .. name .. ' to main inventory')
end
end
local function on_player_ammo_inventory_changed(event)
player_inventory_changed(event.player_index, defines.inventory.character_ammo, 'ammo')
end
local function on_player_gun_inventory_changed(event)
player_inventory_changed(event.player_index, defines.inventory.character_guns, 'guns')
end
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
Event.add(defines.events.on_gui_click, on_gui_click)
Event.add(defines.events.on_player_ammo_inventory_changed, on_player_ammo_inventory_changed)
Event.add(defines.events.on_player_gun_inventory_changed, on_player_gun_inventory_changed)

View File

@ -1000,6 +1000,7 @@ spells[#spells + 1] = {
Public.projectile_types = {
['explosives'] = {name = 'grenade', count = 0.5, max_range = 32, tick_speed = 1},
['distractor-capsule'] = {name = 'distractor-capsule', count = 1, max_range = 32, tick_speed = 1},
['land-mine'] = {name = 'grenade', count = 1, max_range = 32, tick_speed = 1},
['grenade'] = {name = 'grenade', count = 1, max_range = 40, tick_speed = 1},
['cluster-grenade'] = {name = 'cluster-grenade', count = 1, max_range = 40, tick_speed = 3},

View File

@ -81,6 +81,9 @@ end
local function spaghett()
local spaghetti = this.gui_config.spaghett
if spaghetti.noop then
return
end
if spaghetti.enabled then
for _, f in pairs(game.forces) do
if f.technologies['logistic-system'].researched then