mirror of
https://github.com/Refactorio/RedMew.git
synced 2024-12-14 10:13:13 +02:00
384 lines
13 KiB
Lua
384 lines
13 KiB
Lua
local b = require 'map_gen.shared.builders'
|
|
local Perlin = require 'map_gen.shared.perlin_noise'
|
|
local Global = require 'utils.global'
|
|
local Event = require 'utils.event'
|
|
local math = require 'utils.math'
|
|
local table = require 'utils.table'
|
|
local Task = require 'utils.task'
|
|
local Token = require 'utils.token'
|
|
local Utils = require 'utils.core'
|
|
local RS = require 'map_gen.shared.redmew_surface'
|
|
local DayNight = require 'map_gen.shared.day_night'
|
|
local ScenarioInfo = require 'features.gui.info'
|
|
local Toast = require 'features.gui.toast'
|
|
local Retailer = require 'features.retailer'
|
|
|
|
local MGSP = require 'resources.map_gen_settings'
|
|
local DSP = require 'resources.difficulty_settings'
|
|
local market_items = require 'resources.market_items'
|
|
|
|
local noise = Perlin.noise
|
|
local remove = table.remove
|
|
local insert = table.insert
|
|
local format = string.format
|
|
|
|
local config = global.config
|
|
|
|
-- Local constants
|
|
|
|
-- Startup bonus
|
|
local timeout_duration = 20 * 60 -- 20 min timeouts means the bonuses are gone at 2hr
|
|
local startup_bonus = 50 -- mining multiplier
|
|
local toast_duration = 15 -- secs
|
|
|
|
-- Multipliers added as the last number to make it easier to read/understand the deviation from norms
|
|
local map_settings = {
|
|
pollution = {
|
|
enabled = true,
|
|
diffusion_ratio = (0.02 * 20),
|
|
ageing = (1 * 0.1)
|
|
},
|
|
enemy_evolution = {
|
|
enabled = true,
|
|
time_factor = (0.000004 * 0.025),
|
|
destroy_factor = (0.002 * 0.025),
|
|
pollution_factor = (0.000015 * 0.025)
|
|
},
|
|
enemy_expansion = {
|
|
enabled = true,
|
|
max_expansion_distance = (7 * 2),
|
|
enemy_building_influence_radius = (2 / 2),
|
|
min_expansion_cooldown = ((4 * 3600) / 4),
|
|
max_expansion_cooldown = ((60 * 3600) / 4)
|
|
},
|
|
unit_group = {
|
|
max_group_radius = (30.0 * 2),
|
|
max_member_speedup_when_behind = (1.4 * 10),
|
|
max_member_slowdown_when_ahead = (0.6 * 2),
|
|
max_group_slowdown_factor = (0.3 * 3)
|
|
}
|
|
}
|
|
|
|
-- Setup
|
|
|
|
-- Enable infinite storage chest
|
|
config.infinite_storage_chest.enabled = true
|
|
config.infinite_storage_chest.cost = 35
|
|
|
|
-- Enable hydra
|
|
config.hail_hydra.enabled = true
|
|
|
|
config.hail_hydra.hydras = {
|
|
-- spitters
|
|
['small-spitter'] = {['small-spitter'] = 0.1},
|
|
['medium-spitter'] = {['small-spitter'] = 0.2, ['medium-spitter'] = 0.1},
|
|
['big-spitter'] = {['small-spitter'] = 0.3, ['medium-spitter'] = 0.2, ['big-spitter'] = 0.1},
|
|
['behemoth-spitter'] = {['small-spitter'] = 0.4, ['medium-spitter'] = 0.3, ['big-spitter'] = 0.2, ['behemoth-spitter'] = 0.1},
|
|
-- biters
|
|
['small-biter'] = {['small-biter'] = 0.2},
|
|
['medium-biter'] = {['small-biter'] = 0.4, ['medium-biter'] = 0.2},
|
|
['big-biter'] = {['small-biter'] = 0.6, ['medium-biter'] = 0.4, ['big-biter'] = 0.4},
|
|
['behemoth-biter'] = {['small-biter'] = 0.8, ['medium-biter'] = 0.6, ['big-biter'] = 0.4, ['behemoth-biter'] = 0.2},
|
|
-- worms
|
|
['small-worm-turret'] = {['small-biter'] = 2.5, ['medium-biter'] = 0.05},
|
|
['medium-worm-turret'] = {['small-biter'] = 5, ['medium-biter'] = 2.5, ['big-biter'] = 0.05},
|
|
['big-worm-turret'] = {['small-biter'] = 10, ['medium-biter'] = 5, ['big-biter'] = 2.5, ['behemoth-biter'] = 0.05}
|
|
}
|
|
|
|
-- Scenario info
|
|
local map_extra_info =
|
|
[[
|
|
- There are infinite ores in every direction
|
|
- Technology is very, very expensive
|
|
- You have done basic research into how to build a factory
|
|
- The market does not offer what it normally does
|
|
- The biters are plentiful, but seem slow to evolve
|
|
- The sun's position seems unchanging.
|
|
]]
|
|
ScenarioInfo.set_map_name('The 1000 Yard Stare')
|
|
ScenarioInfo.set_map_description('Resources are not an issue as you march your way through the tech tree.')
|
|
ScenarioInfo.add_map_extra_info(map_extra_info .. '- Your miners and your hands will work extra hard when you first arrive\nBut they will tire over time.')
|
|
|
|
-- Redmew surface
|
|
RS.set_first_player_position_check_override(true)
|
|
RS.set_spawn_island_tile('sand-1')
|
|
RS.set_map_gen_settings(
|
|
{
|
|
MGSP.ore_oil_none,
|
|
MGSP.cliff_none,
|
|
MGSP.starting_area_very_low,
|
|
MGSP.enemy_very_high,
|
|
MGSP.sand_only
|
|
}
|
|
)
|
|
RS.set_difficulty_settings({DSP.tech_x1000})
|
|
RS.set_map_settings({map_settings})
|
|
|
|
-- Setup market inventory
|
|
if config.market.enabled then
|
|
local items_to_add = {
|
|
{name = 'modular-armor', stack_limit = 1, player_limit = 1, price = 50},
|
|
{name = 'power-armor', stack_limit = 1, player_limit = 1, price = 2000},
|
|
{name = 'fusion-reactor-equipment', stack_limit = 1, player_limit = 1, price = 300},
|
|
{name = 'energy-shield-equipment', stack_limit = 1, player_limit = 1, price = 350},
|
|
{name = 'defender-capsule', stack_limit = 25, player_limit = 25, price = 1},
|
|
{name = 'distractor-capsule', stack_limit = 50, player_limit = 50, price = 10},
|
|
{name = 'destroyer-capsule', price = 50}
|
|
}
|
|
local items_to_drop = {
|
|
'tank-cannon',
|
|
'tank-machine-gun',
|
|
'artillery-wagon-cannon',
|
|
'artillery-turret',
|
|
'artillery-targeting-remote',
|
|
'defender-capsule',
|
|
'destroyer-capsule',
|
|
'programmable-speaker',
|
|
'personal-laser-defense-equipment'
|
|
}
|
|
|
|
-- Remove items_to_drop from marker
|
|
for i = #market_items, 1, -1 do
|
|
local name = market_items[i].name
|
|
|
|
if table.array_contains(items_to_drop, name) then
|
|
remove(market_items, i)
|
|
end
|
|
end
|
|
|
|
-- Add items_to_add to market
|
|
for i = 1, #items_to_add do
|
|
insert(market_items, items_to_add[i])
|
|
end
|
|
end
|
|
|
|
--- A timeout loop that decreases the mining bonus until < 1 then eliminates it and enables the productivity research
|
|
local timeout_token
|
|
local function decrease_boost()
|
|
local force = game.forces.player
|
|
force.mining_drill_productivity_bonus = force.mining_drill_productivity_bonus / 2
|
|
force.manual_mining_speed_modifier = force.manual_mining_speed_modifier / 2
|
|
force.manual_crafting_speed_modifier = force.manual_crafting_speed_modifier / 2
|
|
if force.mining_drill_productivity_bonus < 1 then
|
|
force.mining_drill_productivity_bonus = 0
|
|
force.manual_mining_speed_modifier = 0
|
|
force.manual_crafting_speed_modifier = 0
|
|
force.technologies['mining-productivity-1'].enabled = true
|
|
Toast.toast_all_players(toast_duration, 'Your hands and all miners seem to have returned to their normal speeds.')
|
|
Utils.print_admins('The mining and crafting bonuses are finished. Mining productivity research has been unlocked (lol).', nil)
|
|
ScenarioInfo.set_map_extra_info(map_extra_info)
|
|
return
|
|
end
|
|
Toast.toast_all_players(toast_duration, 'Your hands and the miners seem to be slowing.')
|
|
Utils.print_admins(format('The mining bonuses are now only %sx, crafting bonus is %sx', force.mining_drill_productivity_bonus, force.manual_crafting_speed_modifier), nil)
|
|
Task.set_timeout(timeout_duration, timeout_token, nil)
|
|
end
|
|
timeout_token = Token.register(decrease_boost)
|
|
|
|
-- Initial techs, setting day_night cycle, placing market
|
|
Event.on_init(
|
|
function()
|
|
local force = game.forces.player
|
|
local surface = RS.get_surface()
|
|
local pos = {0, -15}
|
|
|
|
-- Techs
|
|
force.technologies['automation'].researched = true
|
|
force.technologies['turrets'].researched = true
|
|
force.technologies['military'].researched = true
|
|
force.technologies['logistics'].researched = true
|
|
if config.redmew_qol.enabled and config.redmew_qol.loaders.enabled then
|
|
force.recipes['loader'].enabled = true
|
|
end
|
|
|
|
-- DayNight call
|
|
DayNight.set_fixed_brightness(1, RS.get_surface())
|
|
|
|
if config.market.enabled then
|
|
config.market.create_standard_market = false
|
|
-- Market creation
|
|
local market = surface.create_entity({name = 'market', position = pos})
|
|
market.destructible = false
|
|
Retailer.add_market('items', market)
|
|
if table.size(Retailer.get_items('items')) == 0 then
|
|
for _, prototype in pairs(market_items) do
|
|
Retailer.set_item('items', prototype)
|
|
end
|
|
end
|
|
force.add_chart_tag(surface, {icon = {type = 'item', name = config.market.currency}, position = pos, text = 'Market'})
|
|
end
|
|
|
|
-- Startup bonus
|
|
force.technologies['mining-productivity-1'].enabled = false
|
|
force.mining_drill_productivity_bonus = startup_bonus
|
|
force.manual_mining_speed_modifier = startup_bonus
|
|
force.manual_crafting_speed_modifier = startup_bonus / 10
|
|
Task.set_timeout(timeout_duration, timeout_token, nil)
|
|
end
|
|
)
|
|
|
|
-- Map
|
|
|
|
-- Constants
|
|
local value = 4294967294
|
|
local oil_scale = 1 / 64
|
|
local oil_threshold = 0.6
|
|
|
|
local uranium_scale = 1 / 128
|
|
local uranium_threshold = 0.65
|
|
|
|
local density_scale = 1 / 48
|
|
local density_threshold = 0.5
|
|
local density_multiplier = 50
|
|
|
|
-- Local Globals
|
|
local oil_seed
|
|
local uranium_seed
|
|
local density_seed
|
|
|
|
Global.register_init(
|
|
{},
|
|
function(tbl)
|
|
tbl.seed = RS.get_surface().map_gen_settings.seed
|
|
end,
|
|
function(tbl)
|
|
local seed = tbl.seed
|
|
oil_seed = seed
|
|
uranium_seed = seed * 2
|
|
density_seed = seed * 3
|
|
end
|
|
)
|
|
|
|
-- Functions
|
|
|
|
local function constant(amount)
|
|
return function()
|
|
return amount
|
|
end
|
|
end
|
|
|
|
local oil_shape = b.throttle_world_xy(b.full_shape, 1, 8, 1, 8)
|
|
local oil_resource = b.resource(oil_shape, 'crude-oil', constant(value))
|
|
|
|
local uranium_resource = b.resource(b.full_shape, 'uranium-ore', constant(value))
|
|
|
|
local ores = {
|
|
{resource = b.resource(b.full_shape, 'iron-ore', constant(value)), weight = 6},
|
|
{resource = b.resource(b.full_shape, 'copper-ore', constant(value)), weight = 4},
|
|
{resource = b.resource(b.full_shape, 'stone', constant(value)), weight = 1},
|
|
{resource = b.resource(b.full_shape, 'coal', constant(value)), weight = 2}
|
|
}
|
|
|
|
local weighted_ores = b.prepare_weighted_array(ores)
|
|
local total_ores = weighted_ores.total
|
|
|
|
local ore_circle = b.circle(12)
|
|
local start_ores = {
|
|
b.resource(ore_circle, 'iron-ore', constant(value)),
|
|
b.resource(ore_circle, 'copper-ore', constant(value)),
|
|
b.resource(ore_circle, 'coal', constant(value)),
|
|
b.resource(ore_circle, 'stone', constant(value))
|
|
}
|
|
|
|
local bigger_circle = b.circle(100) -- To exclude water from the start area.
|
|
ore_circle =
|
|
b.any {
|
|
ore_circle,
|
|
bigger_circle
|
|
}
|
|
|
|
local start_segment = b.segment_pattern(start_ores)
|
|
|
|
local function ore(x, y, world)
|
|
local start_ore = start_segment(x, y, world)
|
|
if start_ore then
|
|
return start_ore
|
|
end
|
|
|
|
local oil_x, oil_y = x * oil_scale, y * oil_scale
|
|
|
|
local oil_noise = noise(oil_x, oil_y, oil_seed)
|
|
if oil_noise > oil_threshold then
|
|
return oil_resource(x, y, world)
|
|
end
|
|
|
|
local uranium_x, uranium_y = x * uranium_scale, y * uranium_scale
|
|
local uranium_noise = noise(uranium_x, uranium_y, uranium_seed)
|
|
if uranium_noise > uranium_threshold then
|
|
return uranium_resource(x, y, world)
|
|
end
|
|
|
|
local i = math.random() * total_ores
|
|
local index = table.binary_search(weighted_ores, i)
|
|
if (index < 0) then
|
|
index = bit32.bnot(index)
|
|
end
|
|
|
|
local resource = ores[index].resource
|
|
|
|
local entity = resource(x, y, world)
|
|
local density_x, density_y = x * density_scale, y * density_scale
|
|
local density_noise = noise(density_x, density_y, density_seed)
|
|
|
|
if density_noise > density_threshold then
|
|
entity.amount = entity.amount * density_multiplier
|
|
end
|
|
entity.enable_tree_removal = false
|
|
return entity
|
|
end
|
|
|
|
local worms = {
|
|
'small-worm-turret',
|
|
'medium-worm-turret',
|
|
'big-worm-turret'
|
|
}
|
|
|
|
local max_worm_chance = 1 / 384
|
|
local worm_chance_factor = 1 / (192 * 512)
|
|
|
|
local function enemy(_, _, world)
|
|
local wx, wy = world.x, world.y
|
|
local d = math.sqrt(wx * wx + wy * wy)
|
|
|
|
local worm_chance = d - 128
|
|
|
|
if worm_chance > 0 then
|
|
worm_chance = worm_chance * worm_chance_factor
|
|
worm_chance = math.min(worm_chance, max_worm_chance)
|
|
|
|
if math.random() < worm_chance then
|
|
if d < 384 then
|
|
return {name = 'small-worm-turret'}
|
|
else
|
|
local max_lvl
|
|
local min_lvl
|
|
if d < 768 then
|
|
max_lvl = 2
|
|
min_lvl = 1
|
|
else
|
|
max_lvl = 3
|
|
min_lvl = 2
|
|
end
|
|
local lvl = math.random() ^ (768 / d) * max_lvl
|
|
lvl = math.ceil(lvl)
|
|
lvl = math.clamp(lvl, min_lvl, 3)
|
|
return {name = worms[lvl]}
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local water = b.circle(8)
|
|
water = b.change_tile(water, true, 'water')
|
|
water = b.any {b.rectangle(16, 4), b.rectangle(4, 16), water}
|
|
|
|
local start = b.if_else(water, b.full_shape)
|
|
start = b.change_map_gen_collision_tile(start, 'water-tile', 'grass-1')
|
|
|
|
local map = b.choose(ore_circle, start, b.full_shape)
|
|
|
|
map = b.apply_entity(map, ore)
|
|
map = b.apply_entity(map, enemy)
|
|
|
|
return map
|