1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2024-12-12 10:04:40 +02:00
RedMew/map_gen/presets/spiral_crossings.lua
2018-12-05 03:27:32 -05:00

213 lines
7.6 KiB
Lua

-- Map by Jayefuu and grilled ham, concept by claude47, 2018-12-02
-- SETUP INSTRUCTIONS:
-- This map preset will remove biters everywhere except near the ores.
-- Add market with /market
-- Hover over the market and run:
-- /silent-command game.player.selected.add_market_item{price={{MARKET_ITEM, 100}}, offer={type="give-item", item="landfill"}}
local b = require 'map_gen.shared.builders'
local math = require "utils.math"
local Perlin = require 'map_gen.shared.perlin_noise'
local Event = require 'utils.event'
local degrees = math.rad
local enemy_seed = 420420
local function value(base, mult, pow)
return function(x, y)
local d_sq = x * x + y * y
return base + mult * d_sq ^ (pow / 2) -- d ^ pow
end
end
local function no_resources(_, _, world, tile)
for _, e in ipairs(
world.surface.find_entities_filtered(
{type = 'resource', area = {{world.x, world.y}, {world.x + 1, world.y + 1}}}
)
) do
e.destroy()
end
return tile
end
local names = {
'biter-spawner',
'spitter-spawner',
'small-worm-turret',
'medium-worm-turret',
'big-worm-turret'
}
-- removes spawners when called so we can place our own
local function no_spawners(_, _, world, tile)
for _, e in ipairs(
world.surface.find_entities_filtered(
{force = 'enemy', name = names, position = {world.x, world.y}}
)
) do
e.destroy()
end
return tile
end
local spiral = b.circular_spiral(80, 90)
spiral = b.any {spiral, b.translate(b.circle(128), 12, -12)}
local wide_spiral = b.circular_spiral(60, 90) -- looks prettier, for use with starting ore and water
wide_spiral = b.any {wide_spiral, b.translate(b.circle(128), 12, -12)}
-- provides a shortcut between the spirals, at the cost of expensive landfill from the market
local function water_cross(x,y)
local abs_x = math.abs(x)
local abs_y = math.abs(y)
return not (abs_x > 4 and abs_y > 4)
end
water_cross = b.change_tile(water_cross, true, 'water')
-- make a spiral starting ore patch
local start_ore_patch = b.scale(wide_spiral, 0.1)
local function constant(amount)
return function()
return amount
end
end
local iron = b.resource(start_ore_patch, 'iron-ore', constant(500))
local copper = b.resource(start_ore_patch, 'copper-ore', constant(500))
local stone = b.resource(start_ore_patch, 'stone', constant(500))
local coal = b.resource(start_ore_patch, 'coal', constant(500))
start_ore_patch = b.segment_pattern {iron, copper, stone, coal}
local start_ore_bounds = b.circle(32)
start_ore_patch = b.choose(start_ore_bounds, start_ore_patch, b.empty_shape)
start_ore_patch = b.translate(start_ore_patch, 0, 32)
-- make some starting water
local start_water = b.scale(wide_spiral, 0.1)
start_water = b.choose(b.circle(26), start_water, b.empty_shape)
start_water = b.change_tile(start_water, true, 'water')
start_water = b.translate(start_water,0,-130)
-- ore generation
local patch = b.circle(18)
local small_patch = b.circle(12)
local patches = b.single_x_pattern(patch, 90)
local patches_wide = b.single_x_pattern(patch, 180)
local patches_wide_small = b.single_x_pattern(small_patch, 180)
local iron_patches = b.resource(patches, 'iron-ore', value(500, 0.8, 1.075))
local copper_patches = b.resource(patches, 'copper-ore', value(400, 0.75, 1.1))
local coal_patches = b.resource(patches_wide, 'coal', value(650, 0.75, 1.1))
local stone_patches = b.resource(patches_wide, 'stone', value(400, 0.75, 1.1))
local oil_patches = b.resource(b.throttle_world_xy(patches_wide_small,1,6,1,6), 'crude-oil', value(33000, 50, 1.05))
local uranium_patches = b.resource(patches_wide_small, 'uranium-ore', value(200, 0.75, 1.1))
local function ore_arm_bounds(x, _)
return x < 20
end
iron_patches = b.translate(b.choose(ore_arm_bounds, iron_patches, b.empty_shape),-160,0)
copper_patches = b.translate(b.choose(ore_arm_bounds, copper_patches, b.empty_shape),-210,0)
stone_patches = b.translate(b.choose(ore_arm_bounds, stone_patches, b.empty_shape),-230,0)
uranium_patches = b.translate(b.choose(ore_arm_bounds, uranium_patches, b.empty_shape),-320,0)
coal_patches = b.translate(b.choose(ore_arm_bounds, coal_patches, b.empty_shape),-180,0)
oil_patches = b.translate(b.choose(ore_arm_bounds, oil_patches, b.empty_shape),-270,0)
spiral = b.change_tile(spiral, true, 'grass-1')
spiral = b.apply_entity(spiral, b.rotate(coal_patches,degrees(45)))
spiral = b.apply_entity(spiral, b.rotate(oil_patches,degrees(45))) -- oil and coal have double spacing so they are interleaved
spiral = b.apply_entity(spiral, b.rotate(iron_patches,degrees(45+90)))
spiral = b.apply_entity(spiral, b.rotate(stone_patches,degrees(45+180)))
spiral = b.apply_entity(spiral, b.rotate(uranium_patches,degrees(45+180))) -- stone and uranium have double spacing so they are interleaved
spiral = b.apply_entity(spiral, b.rotate(copper_patches,degrees(45+270)))
-- Re-add the spawners we removed at the beginning so we can apply a pattern (cross) to their positions, aligning them with the ores
local worm_names = {'small-worm-turret', 'medium-worm-turret', 'big-worm-turret'}
local spawner_names = {'biter-spawner', 'spitter-spawner'}
local factor = 16 / (1024 * 32)
local max_chance = 1 / 4
local scale_factor = 4
local sf = 1 / scale_factor
local m = 1 / 600
local function enemy(x, y, world)
local d = math.sqrt(world.x * world.x + world.y * world.y)
if d < 80 then
return nil
end
local threshold = 1 - d * m
threshold = math.max(threshold, 0.5) -- -0.125)
x, y = x * sf, y * sf
if Perlin.noise(x, y, enemy_seed) > threshold then
if math.random(8) <= 2 then
local lvl
if d < 300 then
lvl = 1
elseif d < 650 then
lvl = 2
else
lvl = 3
end
local chance = math.min(max_chance, d * factor)
if math.random() < chance then
local worm_id
if d > 1000 then
local power = 1000 / d
worm_id = math.ceil((math.random() ^ power) * lvl)
else
worm_id = math.random(lvl)
end
return {name = worm_names[worm_id]}
end
else
local chance = math.min(max_chance, d * factor)
if math.random() < chance then
local spawner_id = math.random(2)
return {name = spawner_names[spawner_id]}
end
end
end
end
-- Maltese cross shape so the biter patches get wider the further from base
local gradient = 0.1
local tiles_half = (50) * 0.5
local function enemy_cross(x,y)
local abs_x = math.abs(x)
local abs_y = math.abs(y)
return not (abs_x > (tiles_half+(abs_y*gradient)) and abs_y > (tiles_half+(abs_x*gradient)))
end
enemy_cross = b.rotate(enemy_cross,degrees(45))
enemy = b.choose(enemy_cross,enemy,b.empty_shape)
water_cross = b.fish(water_cross, 0.01)
local map = b.any{
start_water,
spiral,
water_cross
}
map = b.apply_entity(map,start_ore_patch)
map = b.apply_effect(map, no_resources)
map = b.apply_effect(map, no_spawners) -- remove all spawners and worms
map = b.apply_entity(map, enemy) -- add the enemies we generated
local function on_init()
local player_force = game.forces.player
local enemy_force = game.forces.enemy
player_force.technologies["landfill"].enabled = false -- disable landfill
enemy_force.set_ammo_damage_modifier('melee', 1) -- +100% biter damage
enemy_force.set_ammo_damage_modifier('biological', 0.5) -- +50% spitter/worm damage
game.map_settings.enemy_expansion.enabled = false -- turn off expansion to compensave for harder biters
end
Event.on_init(on_init)
return map