1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2025-03-17 21:08:08 +02:00

Updates/frontier v6 (#1431)

* New terrain gen

* Artillery targeting

* Fix silo positioning

* Frontier v6 tweaks
This commit is contained in:
RedRafe 2024-08-28 18:06:34 +02:00 committed by GitHub
parent a5a61b9a32
commit 7789ac4ec6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 628 additions and 60 deletions

View File

@ -1,24 +1,75 @@
local Event = require 'utils.event'
local Global = require 'utils.global'
local Task = require 'utils.task'
local Token = require 'utils.token'
local register_on_entity_destroyed = script.register_on_entity_destroyed
local Public = {}
local turrets_map = {}
local register_map = {}
local primitives = { index = nil }
local Artillery = {
enabled = true,
turret_name = 'artillery-turret',
character_projectile = 'artillery-projectile',
structure_projectile = 'rocket',
target_force = 'player',
last_fire = 0,
fire_interval = 60, -- ticks
cooldown = 480, -- ticks
min_range = 32, -- tiles
max_range = 224, -- tiles
max_targeting_attempts = 10,
range_modifier = nil,
manual_range_modifier = nil,
creation_distance = 1.6,
target_offset = { -0.15625, -0.07812 },
target_entities = {
'artillery-turret',
'artillery-wagon',
'car',
'cargo-wagon',
'character',
'flamethrower-turret',
'fluid-wagon',
'furnace',
'gun-turret',
'lab',
'laser-turret',
'locomotive',
'radar',
'silo',
'spidertron',
'tank',
},
}
Global.register(
{
turrets_map = turrets_map,
register_map = register_map,
primitives = primitives,
artillery = Artillery,
},
function(tbl)
turrets_map = tbl.turrets_map
register_map = tbl.register_map
primitives = tbl.primitives
Artillery = tbl.artillery
end)
local function distance(posA, posB)
return math.sqrt((posA.x - posB.x)^2 + (posA.y - posB.y)^2)
end
function Public.get_artillery_settings()
return Artillery
end
function Public.set_artillery_settings(key, value)
Artillery[key] = value
end
function Public.register(entity, refill_name)
if not (entity and entity.valid) then
return
@ -30,8 +81,9 @@ function Public.register(entity, refill_name)
local is_item = game.item_prototypes[refill_name] and true or false
local is_fluid = game.fluid_prototypes[refill_name] and true or false
local is_artillery = entity.prototype.type == Artillery.turret_name
if not (is_item or is_fluid )then
if not (is_item or is_fluid or is_artillery) then
return
end
@ -42,11 +94,18 @@ function Public.register(entity, refill_name)
entity = entity,
refill = refill_name,
is_fluid = is_fluid,
is_artillery = is_artillery,
destroy_id = destroy_id
}
if data.is_artillery then
data.next_fire = game.tick
end
if data.is_fluid then
data.capacity = data.entity.fluidbox.get_capacity(1)
data.fluid_stack = {
name = data.refill,
amount = data.entity.fluidbox.get_capacity(1) or 100
}
else
data.item_stack = {
name = data.refill,
@ -75,6 +134,65 @@ function Public.reset()
end
end
local artillery_projectile_token = Token.register(function(data)
local surface = data.surface
local target = data.target
local source = data.source
if not (surface and surface.valid) then return end
if not (target and target.valid) then return end
if not (source and source.valid) then return end
surface.create_entity{
name = data.name,
position = data.position,
target = target,
source = source,
force = 'enemy',
speed = 1.5,
}
end)
local function simulate_automatic_artillery(data)
if data.next_fire > game.tick then
return
end
local entity = data.entity
local surface = entity.surface
local source_position = entity.position
local range_modifier = Artillery.range_modifier or entity.force.artillery_range_modifier or 0
local manual_range_modifier = Artillery.manual_range_modifier or entity.prototype.manual_range_modifier or 0
local params = {
position = source_position,
radius = Artillery.max_range * (1 + range_modifier) * (1 + manual_range_modifier),
name = Artillery.target_entities,
force = Artillery.target_force,
limit = Artillery.max_targeting_attempts,
}
local targets = surface.find_entities_filtered(params)
if #targets == 0 then
return
end
for i = 1, #targets do
local target = targets[i]
if distance(source_position, target.position) > Artillery.min_range then
Task.set_timeout_in_ticks(Artillery.fire_interval, artillery_projectile_token, {
surface = surface,
name = target.name == 'character' and Artillery.character_projectile or Artillery.structure_projectile,
position = target.position,
target = target,
source = entity,
force = 'enemy',
speed = 1.5,
})
data.next_fire = game.tick + Artillery.cooldown
Artillery.last_fire = game.tick
break
end
end
end
local function on_entity_destroyed(event)
local destroy_id = event.registration_number
local unit_id = event.unit_number
@ -96,10 +214,11 @@ local function on_tick()
return
end
if Artillery.enabled and data.is_artillery and ((Artillery.last_fire + Artillery.fire_interval) < game.tick) then
simulate_automatic_artillery(data)
end
if data.is_fluid then
local fb = data.entity.fluidbox[1]
fb.name = data.refill
fb.amount = data.capacity
data.entity.insert_fluid(data.fluid_stack)
else
data.entity.insert(data.item_stack)
end

View File

@ -397,13 +397,18 @@ Event.on_init(function()
end)
Event.add(defines.events.on_research_finished, function(event)
for _, effect in pairs(event.research.effects or {}) do
local technology = event.research
if technology.force.name ~= 'player' then
return
end
for _, effect in pairs(technology.effects or {}) do
if effect.recipe then
add_recipe_products(game.forces.player.recipes[effect.recipe])
end
end
if event.research.name == 'space-science-pack' then
if technology.name == 'space-science-pack' then
item_unlocked['space-science-pack'] = item_worths['space-science-pack']
end
end)

View File

@ -84,8 +84,10 @@ Enemy.commands = {
data.target = target
data.stage = Enemy.stages.attack
unit_group.set_command {
type = defines.command.attack,
target = target,
type = defines.command.attack_area,--defines.command.attack,
destination = target.position,
radius = 15,
--target = target,
distraction = defines.distraction.by_damage
}
if Public.get()._DEBUG_AI then
@ -102,6 +104,31 @@ Enemy.stages = {
fail = 5,
}
Enemy.turret_raffle = {
-- sets must have at least 1 valid turret and 1 valid refill for function(x_distance, evolution)
['base'] = {
['gun-turret'] = { weight = 16, min_distance = 0, refill = { 'firearm-magazine', 'piercing-rounds-magazine', 'uranium-rounds-magazine' } },
['flamethrower-turret'] = { weight = 2, min_distance = 800, refill = { 'crude-oil', 'heavy-oil', 'light-oil' } },
['artillery-turret'] = { weight = 16, min_distance = 2800, refill = { 'artillery-shell' } }
},
['Krastorio2'] = {
['gun-turret'] = { weight = 16, min_distance = 0, refill = { 'rifle-magazine', 'armor-piercing-rifle-magazine', 'uranium-rifle-magazine', 'imersite-rifle-magazine' } },
['flamethrower-turret'] = { weight = 2, min_distance = 800, refill = { 'crude-oil', 'heavy-oil', 'light-oil' } },
['kr-railgun-turret'] = { weight = 128, min_distance = 1400, refill = { 'basic-railgun-shell', 'explosion-railgun-shell', 'antimatter-railgun-shell' } },
['kr-rocket-turret'] = { weight = 16, min_distance = 2000, refill = { 'explosive-turret-rocket', 'nuclear-turret-rocket', 'antimatter-turret-rocket' } },
['artillery-turret'] = { weight = 16, min_distance = 2800, refill = { 'artillery-shell', 'nuclear-artillery-shell', 'antimatter-artillery-shell' } },
},
['zombiesextended-core'] = {
['gun-turret'] = { weight = 16, min_distance = 0, refill = { 'firearm-magazine', 'assault-ammo-mk1', 'uranium-rounds-magazine', 'assault-ammo-mk2' } },
['gun-turret-mk1'] = { weight = 64, min_distance = 750, refill = { 'piercing-rounds-magazine', 'assault-ammo-mk1', 'assault-ammo-mk2', 'assault-ammo-mk3' } },
['gun-turret-mk2'] = { weight = 256, min_distance = 1500, refill = { 'assault-ammo-mk1', 'uranium-rounds-magazine', 'assault-ammo-mk2', 'assault-ammo-mk3' } },
['flamethrower-turret'] = { weight = 2, min_distance = 800, refill = { 'crude-oil', 'heavy-oil', 'light-oil' } },
['flamethrower-turret-mk1'] = { weight = 4, min_distance = 1200, refill = { 'crude-oil', 'heavy-oil', 'light-oil' } },
['flamethrower-turret-mk2'] = { weight = 16, min_distance = 1500, refill = { 'crude-oil', 'heavy-oil', 'light-oil' } },
['artillery-turret'] = { weight = 128, min_distance = 2800, refill = { 'artillery-shell' } }
}
}
function Enemy.ai_take_control(unit_group)
local this = Public.get()
if not this.unit_groups[unit_group.group_number] then
@ -302,6 +329,37 @@ function Enemy.on_spawner_died(event)
end
end
function Enemy.roll_turret(x_distance, evolution)
local set = Enemy.turret_raffle['base']
if script.active_mods['Krastorio2'] then
set = Enemy.turret_raffle['Krastorio2']
end
if script.active_mods['zombiesextended-core'] then
set = Enemy.turret_raffle['zombiesextended-core']
end
local weighted_turrets_table = {}
for name, data in pairs(set) do
if data.min_distance < x_distance then
table.insert(weighted_turrets_table, { name, data.weight })
end
end
local turret = Table.get_random_weighted(weighted_turrets_table)
local refills = set[turret].refill
local refill
if evolution < 0.2 then
refill = refills[1]
elseif evolution < 0.5 then
refill = refills[2] or refills[#refills]
elseif evolution < 0.75 then
refill = refills[3] or refills[#refills]
else
refill = refills[4] or refills[#refills]
end
return turret, refill
end
function Enemy.spawn_turret_outpost(position)
local this = Public.get()
if position.x < this.right_boundary * 32 + this.wall_width then
@ -325,31 +383,25 @@ function Enemy.spawn_turret_outpost(position)
end
local evolution = game.forces.enemy.evolution_factor
local ammo = 'firearm-magazine'
if math_random() < evolution then
ammo = 'piercing-rounds-magazine'
end
if math_random() < evolution then
ammo = 'uranium-rounds-magazine'
end
for _, v in pairs({
{ x = -5, y = 0 },
{ x = 5, y = 0 },
{ x = 0, y = 5 },
{ x = 0, y = -5 },
{ x = -5, y = 0, direction = defines.direction.west },
{ x = 5, y = 0, direction = defines.direction.east },
{ x = 0, y = 5, direction = defines.direction.south },
{ x = 0, y = -5, direction = defines.direction.north },
}) do
local pos = surface.find_non_colliding_position('gun-turret', { position.x + v.x, position.y + v.y }, 2, 0.5)
local turret_name, refill_name = Enemy.roll_turret(position.x, evolution)
local pos = surface.find_non_colliding_position(turret_name, { position.x + v.x, position.y + v.y }, 2, 0.5)
if pos then
local turret = surface.create_entity {
name = 'gun-turret',
name = turret_name,
position = pos,
force = 'enemy',
move_stuck_players = true,
create_build_effect_smoke = true,
direction = v.direction,
}
if turret and turret.valid then
EnemyTurret.register(turret, ammo)
EnemyTurret.register(turret, refill_name)
end
end
end
@ -405,4 +457,12 @@ function Enemy.artillery_explosion(data)
end
Enemy.artillery_explosion_token = Token.register(Enemy.artillery_explosion)
function Enemy.on_research_finished(technology)
if technology.force.name ~= 'player' then
return
end
game.forces.enemy.technologies[technology.name].researched = true
end
return Enemy

View File

@ -9,7 +9,6 @@ local Enemy = require 'map_gen.maps.frontier.modules.enemy'
local Terrain = require 'map_gen.maps.frontier.modules.terrain'
local math_abs = math.abs
local math_ceil = math.ceil
local math_clamp = math.clamp
local math_floor = math.floor
local math_max = math.max
local math_min = math.min
@ -134,6 +133,7 @@ function RocketSilo.move_silo(position)
if old_silo then
local result_inventory = old_silo.get_output_inventory().get_contents()
Terrain.clear_area{ surface = surface, position = new_position, size = 12 }
new_silo = old_silo.clone { position = new_position, force = old_silo.force, create_build_effect_smoke = true }
old_silo.destroy()
local chest = surface.create_entity { name = 'steel-chest', position = old_position, force = 'player', move_stuck_players = true }
@ -160,10 +160,11 @@ function RocketSilo.move_silo(position)
for _ = 1, 12 do
Task.set_timeout_in_ticks(math_random(30, 4 * 60), Enemy.artillery_explosion_token, { surface_name = surface.name, position = spawn_target.position })
end
for t = 1, math_clamp(math_floor((#game.connected_players) / 2 + 0.5), 1, 5) do
if this.spawn_enemy_wave then
for t = 1, math.clamp(math_floor((#game.connected_players) / 2 + 0.5), 1, 5) do
Task.set_timeout(15 * t, Enemy.spawn_enemy_wave_token, spawn_target.position)
end
break
end
end
end
@ -172,6 +173,7 @@ function RocketSilo.move_silo(position)
enemy_evolution.time_factor = enemy_evolution.time_factor * 1.01
else
init = true
Terrain.clear_area{ surface = surface, position = new_position, size = 12 }
new_silo = surface.create_entity { name = 'rocket-silo', position = new_position, force = 'player', move_stuck_players = true }
end
@ -194,6 +196,8 @@ function RocketSilo.move_silo(position)
game.print({'frontier.silo_backward', x_diff})
end
end
else
log('Could not place silo '..serpent.line(new_position))
end
end
RocketSilo.move_silo_token = Token.register(RocketSilo.move_silo)
@ -352,4 +356,21 @@ function RocketSilo.kraken_eat_entity(entity)
entity.die('enemy')
end
function RocketSilo.on_research_finished(technology)
if technology.force.name ~= 'player' then
return
end
local this = Public.get()
local recipes = technology.force.recipes
if recipes['rocket-silo'] then
recipes['rocket-silo'].enabled = false
end
if this.rockets_launched == 0 and recipes['landfill'].enabled then
recipes['landfill'].enabled = false
end
if this.rockets_launched > 0 and not recipes['landfill'].enabled then
recipes['landfill'].enabled = true
end
end
return RocketSilo

View File

@ -6,6 +6,7 @@ local Queue = require 'utils.queue'
local RS = require 'map_gen.shared.redmew_surface'
local Public = require 'map_gen.maps.frontier.shared.core'
local math_abs = math.abs
local math_ceil = math.ceil
local math_clamp = math.clamp
local math_floor = math.floor
local math_max = math.max
@ -17,23 +18,39 @@ local q_pop = Queue.pop
local simplex = Noise.d2
local autoplace_controls = {
['coal'] = { frequency = 1.1, richness = 0.6, size = 0.75 },
['copper-ore'] = { frequency = 1.2, richness = 0.6, size = 0.75 },
['crude-oil'] = { frequency = 1, richness = 0.6, size = 0.75 },
['coal'] = { frequency = 1.3, richness = 0.7, size = 0.80 },
['copper-ore'] = { frequency = 1.4, richness = 0.7, size = 0.85 },
['crude-oil'] = { frequency = 1, richness = 0.9, size = 0.95 },
['enemy-base'] = { frequency = 6, richness = 0.6, size = 4 },
['iron-ore'] = { frequency = 1.135, richness = 0.6, size = 0.85 },
['iron-ore'] = { frequency = 1.6, richness = 0.8, size = 1.15 },
['stone'] = { frequency = 1, richness = 0.6, size = 0.65 },
['trees'] = { frequency = 1, richness = 0.6, size = 1 },
['uranium-ore'] = { frequency = 0.5, richness = 0.6, size = 0.5 },
['trees'] = { frequency = 1, richness = 0.6, size = 1.2 },
['uranium-ore'] = { frequency = 0.5, richness = 0.6, size = 0.6 },
}
local blacklisted_resources = {
['uranium-ore'] = true,
['crude-oil'] = true,
}
local noise_weights = {
{ modifier = 0.0042, weight = 1.000 },
{ modifier = 0.0310, weight = 0.080 },
{ modifier = 0.1000, weight = 0.025 },
local noises = {
['dungeon_sewer'] = {{ modifier = 0.00055, weight = 1.05 }, { modifier = 0.0062, weight = 0.024 }, { modifier = 0.0275, weight = 0.00135 }},
['cave_miner_01'] = {{ modifier = 0.002, weight = 1 }, { modifier = 0.003, weight = 0.5 }, { modifier = 0.01, weight = 0.01 }, { modifier = 0.1, weight = 0.015 }},
['oasis'] = {{ modifier = 0.00165, weight = 1.1 }, { modifier = 0.00275, weight = 0.55 }, { modifier = 0.011, weight = 0.165 }, { modifier = 0.11, weight = 0.0187 }},
['dungeons'] = {{ modifier = 0.0028, weight = 0.99 }, { modifier = 0.0059, weight = 0.21 }},
['cave_rivers_2'] = {{ modifier = 0.0035, weight = 0.90 }, { modifier = 0.0088, weight = 0.15 }, { modifier = 0.051, weight = 0.011 }},
['cave_miner_02'] = {{ modifier = 0.006, weight = 1 }, { modifier = 0.02, weight = 0.15 }, { modifier = 0.25, weight = 0.025 }},
['large_caves'] = {{ modifier = 0.055, weight = 0.045 }, { modifier = 0.11, weight = 0.042 }, { modifier = 0.00363, weight = 1.05 }, { modifier = 0.01, weight = 0.23 }},
['no_rocks'] = {{ modifier = 0.00495, weight = 0.945 }, { modifier = 0.01665, weight = 0.2475 }, { modifier = 0.0435, weight = 0.0435 }, { modifier = 0.07968, weight = 0.0315 }},
['scrapyard'] = {{ modifier = 0.0055, weight = 1.1 }, { modifier = 0.011, weight = 0.385 }, { modifier = 0.055, weight = 0.253 }, { modifier = 0.11, weight = 0.121 }},
['scrapyard_2'] = {{ modifier = 0.0066, weight = 1.1 }, { modifier = 0.044, weight = 0.165 }, { modifier = 0.242, weight = 0.055 }, { modifier = 0.055, weight = 0.352 }},
['smol_areas'] = {{ modifier = 0.0052, weight = 0.83 }, { modifier = 0.139, weight = 0.144 }, { modifier = 0.129, weight = 0.072 }, { modifier = 0.111, weight = 0.01 }},
['cave_rivers'] = {{ modifier = 0.0053, weight = 0.71 }, { modifier = 0.0086, weight = 0.24 }, { modifier = 0.070, weight = 0.025 }},
['small_caves'] = {{ modifier = 0.0066, weight = 1.1 }, { modifier = 0.044, weight = 0.165 }, { modifier = 0.242, weight = 0.055 }},
['forest_location'] = {{ modifier = 0.0066, weight = 1.1 }, { modifier = 0.011, weight = 0.275 }, { modifier = 0.055, weight = 0.165 }, { modifier = 0.11, weight = 0.0825 }},
['small_caves_2'] = {{ modifier = 0.0099, weight = 1.1 }, { modifier = 0.055, weight = 0.275 }, { modifier = 0.275, weight = 0.055 }},
['forest_density'] = {{ modifier = 0.01, weight = 1 }, { modifier = 0.05, weight = 0.5 }, { modifier = 0.1, weight = 0.025 }},
['cave_ponds'] = {{ modifier = 0.014, weight = 0.77 }, { modifier = 0.18, weight = 0.085 }},
['no_rocks_2'] = {{ modifier = 0.0184, weight = 1.265 }, { modifier = 0.143, weight = 0.1045 }},
['mixed_ore'] = {{ modifier = 0.0042, weight = 1.000 }, { modifier = 0.0310, weight = 0.080 }, { modifier = 0.1000, weight = 0.025 }},
}
local mixed_ores = { 'iron-ore', 'copper-ore', 'iron-ore', 'stone', 'copper-ore', 'iron-ore', 'copper-ore', 'iron-ore', 'coal', 'iron-ore', 'copper-ore', 'iron-ore', 'stone', 'copper-ore', 'coal'}
@ -119,8 +136,9 @@ function Terrain.get_map()
return map
end
function Terrain.noise_pattern(position, seed)
function Terrain.noise_pattern(feature, position, seed)
local noise, d = 0, 0
local noise_weights = noises[feature]
for i = 1, #noise_weights do
local nw = noise_weights[i]
noise = noise + simplex(position.x * nw.modifier, position.y * nw.modifier, seed) * nw.weight
@ -163,7 +181,7 @@ function Terrain.mixed_resources(surface, area)
for y = 0, 31 do
local position = { x = left_top.x + x, y = left_top.y + y }
if can_place_entity({ name = 'iron-ore', position = position }) then
local noise = Terrain.noise_pattern(position, seed)
local noise = Terrain.noise_pattern('mixed_ore', position, seed)
if math_abs(noise) > 0.77 then
local idx = math_floor(noise * 25 + math_abs(position.x) * 0.05) % #mixed_ores + 1
local amount = this.ore_base_quantity * chunks * 35 + math_random(100)
@ -285,4 +303,194 @@ function Terrain.reveal_spawn_area()
surface.force_generate_chunk_requests()
end
function Terrain.block_tile_placement(event)
local this = Public.get()
local surface = game.get_surface(event.surface_index)
if surface.name ~= Public.surface().name then
return
end
local left = -(this.kraken_distance + this.left_boundary * 32)
local tiles = {}
for _, tile in pairs(event.tiles) do
if tile.position.x <= left then
tiles[#tiles + 1] = { name = tile.old_tile.name, position = tile.position }
end
end
if #tiles > 0 then
surface.set_tiles(tiles, true)
end
end
function Terrain.reshape_land(surface, area)
local this = Public.get()
local right_boundary = this.right_boundary * 32 + this.wall_width + 4
local left_top = { x = math_max(area.left_top.x, -this.left_boundary * 32), y = area.left_top.y }
local right_bottom = area.right_bottom
if left_top.x >= right_bottom.x then
return
end
local seed = surface.map_gen_settings.seed
local count_entities = surface.count_entities_filtered
local noise_pattern = Terrain.noise_pattern
local function is_ore(position)
return count_entities{
position = { x = position.x + 0.5, y = position.y + 0.5 },
type = 'resource',
limit = 1,
} > 0
end
local function do_tile(x, y)
if math_abs(y) > this.height * 16 then
return
end
if math_abs(x) < 16 and math_abs(y) < 16 then
return
end
if math_abs(x - this.x) < 16 and math_abs(y - this.y) < 16 then
return
end
local p = { x = x, y = y }
local cave_rivers = noise_pattern('cave_rivers', p, seed)
local no_rocks = noise_pattern('no_rocks', p, seed)
local cave_ponds = noise_pattern('cave_ponds', p, 2 * seed)
local small_caves = noise_pattern('dungeons', p, 2 * seed)
-- Chasms
if cave_ponds < 0.110 and cave_ponds > 0.112 then
if small_caves > 0.5 or small_caves < -0.5 then
return { name = 'out-of-map', position = p }
end
end
-- Rivers
if cave_rivers < 0.044 and cave_rivers > -0.072 then
if cave_ponds > 0.1 then
if not is_ore(p) then
return { name = 'water-shallow', position = p }
else
return { name = 'cyan-refined-concrete', position = p }
end
end
end
-- Water Ponds
if cave_ponds > 0.6 then
if cave_ponds > 0.74 then
return { name = x < right_boundary and 'acid-refined-concrete' or 'orange-refined-concrete', position = p }
end
if not is_ore(p) then
return { name = x < right_boundary and 'green-refined-concrete' or 'red-refined-concrete', position = p }
else
return { name = 'cyan-refined-concrete', position = p }
end
end
if cave_ponds > 0.622 then
if cave_ponds > 0.542 then
if cave_rivers > -0.302 then
return { name = 'refined-hazard-concrete-right', position = p }
end
end
end
-- Worm oil
if no_rocks < 0.029 and no_rocks > -0.245 then
if small_caves > 0.081 then
return { name = x < right_boundary and'brown-refined-concrete' or 'black-refined-concrete', position = p }
end
end
-- Chasms2
if small_caves < -0.54 and cave_ponds < -0.5 then
if not is_ore(p) then
return { name = 'out-of-map', position = p }
end
end
end
local tiles = {}
for x = 0, math_min(right_bottom.x - left_top.x, 31) do
for y = 0, 31 do
local tile = do_tile(left_top.x + x, left_top.y + y)
if tile then tiles[#tiles +1] = tile end
end
end
surface.set_tiles(tiles, true)
end
function Terrain.clear_area(args)
if not (args.position and args.surface) then
return
end
local surface = args.surface
local position = args.position
surface.request_to_generate_chunks({ x = position.x, y = position.x }, math_ceil((args.radius or args.size or 32) / 32))
surface.force_generate_chunk_requests()
if args.name then
local cb = game.entity_prototypes[args.name].collision_box
local area = {
left_top = {
x = position.x - cb.left_top.x,
y = position.y - cb.left_top.y,
},
right_bottom = {
x = position.x + cb.right_bottom.x,
y = position.y + cb.right_bottom.y,
}
}
for _, e in pairs(surface.find_entities_filtered{ area = area, collision_mask = {'player-layer', 'object-layer'}}) do
e.destroy()
end
local tiles = {}
for _, t in pairs(surface.find_tiles_filtered{ area = area }) do
if t.collides_with('item-layer') then
tiles[#tiles +1] = { name = 'nuclear-ground', position = t.position }
end
end
surface.set_tiles(tiles, true)
return true
elseif args.radius then
for _, e in pairs(surface.find_entities_filtered{ position = position, radius = args.radius, collision_mask = {'player-layer', 'object-layer'}}) do
e.destroy()
end
local tiles = {}
for _, t in pairs(surface.find_tiles_filtered{ position = position, radius = args.radius }) do
if t.collides_with('item-layer') then
tiles[#tiles +1] = { name = 'nuclear-ground', position = t.position }
end
end
surface.set_tiles(tiles, true)
return true
elseif args.size then
local size = args.size
local area = {
left_top = {
x = position.x - size,
y = position.y - size,
},
right_bottom = {
x = position.x + size,
y = position.y + size,
}
}
for _, e in pairs(surface.find_entities_filtered{ area = area, collision_mask = {'player-layer', 'object-layer'}}) do
e.destroy()
end
local tiles = {}
for _, t in pairs(surface.find_tiles_filtered{ area = area }) do
if t.collides_with('item-layer') then
tiles[#tiles +1] = { name = 'nuclear-ground', position = t.position }
end
end
surface.set_tiles(tiles, true)
return true
end
end
return Terrain

View File

@ -1,5 +1,6 @@
local Command = require 'utils.command'
local Event = require 'utils.event'
local DebugTerrain = require 'map_gen.maps.frontier.shared.debug_terrain'
local math = require 'utils.math'
local Ranks = require 'resources.ranks'
local ScenarioInfo = require 'features.gui.info'
@ -161,6 +162,11 @@ local function on_chunk_generated(event)
return
end
if Public.get()._DEBUG_NOISE then
DebugTerrain.on_chunk_generated(event)
return
end
-- scale freshly generated ore by a scale factor
Terrain.scale_resource_richness(surface, area)
@ -169,9 +175,18 @@ local function on_chunk_generated(event)
-- add extra rocks
Terrain.rich_rocks(surface, area)
-- special tiles
Terrain.reshape_land(surface, area)
end
Event.add(defines.events.on_chunk_generated, on_chunk_generated)
local function on_tile_built(event)
Terrain.block_tile_placement(event)
end
Event.add(defines.events.on_player_built_tile, on_tile_built)
Event.add(defines.events.on_robot_built_tile, on_tile_built)
local function on_entity_died(event)
local entity = event.entity
if not (entity and entity.valid) then
@ -201,9 +216,13 @@ end
Event.add(defines.events.on_entity_died, on_entity_died)
local function on_research_finished(event)
local recipes = event.research.force.recipes
if recipes['rocket-silo'] then
recipes['rocket-silo'].enabled = false
local technology = event.research
if not (technology and technology.valid) then
return
end
if technology.force.name == 'player' then
RocketSilo.on_research_finished(technology)
Enemy.on_research_finished(technology)
end
end
Event.add(defines.events.on_research_finished, on_research_finished)

View File

@ -26,16 +26,14 @@ Public.PROD_PENALTY = 1.2 * 1.4^5
local this = {
rounds = 0,
-- Map gen
chart_queue = Queue.new(),
silo_starting_x = 1700,
height = 36, -- in chunks, height of the ribbon world
left_boundary = 8, -- in chunks, distance to water body
right_boundary = 11, -- in chunks, distance to wall/biter presence
wall_width = 5, -- in tiles
rock_richness = 1, -- how many rocks/chunk
ore_base_quantity = 11, -- base ore quantity, everything is scaled up from this
ore_chunk_scale = 32 * 20,-- sets how fast the ore will increase from spawn, lower = faster
@ -44,26 +42,22 @@ local this = {
kraken_contributors = {}, -- list of players eaten by kraken
death_contributions = {}, -- list of all players deaths
-- Satellites to win
-- Rocket silo position management
x = 0,
y = 0,
rocket_silo = nil,
silo_starting_x = 1700,
move_buffer = 0,
rocket_step = 500, -- rocket/tiles ratio
min_step = 500, -- minimum tiles to move
max_distance = 100000, -- maximum x distance of rocket silo
rockets_to_win = 1,
rockets_launched = 0,
rockets_per_death = 0, -- how many extra launch needed for each death
scenario_finished = false,
-- Loot chests
loot_budget = 48,
loot_richness = 1,
-- Rocket silo position management
x = 0,
y = 0,
rocket_silo = nil,
move_buffer = 0,
rocket_step = 500, -- rocket/tiles ratio
min_step = 500, -- minimum tiles to move
max_distance = 100000, -- maximum x distance of rocket silo
-- Enemy data
spawn_enemy_wave = false,
invincible = {},
target_entities = {},
unit_groups = {},
@ -74,8 +68,11 @@ local this = {
-- Debug
_DEBUG_AI = false,
_DEBUG_SHOP = false,
_DEBUG_NOISE = false,
-- Markets
loot_budget = 48,
loot_richness = 1,
banned_items = {
['rocket-silo'] = true,
['space-science-pack'] = true,

View File

@ -19,4 +19,39 @@ function Debug.log(data)
log(serpent.block(data))
end
local function noise_to_tile_map(noise)
if noise > 80 / 100 then
return 'red-refined-concrete'
elseif noise > 45 / 100 then
return 'orange-refined-concrete'
elseif noise > 10 / 100 then
return 'yellow-refined-concrete'
elseif noise > -10 / 100 then
return 'green-refined-concrete'
elseif noise > -45 / 100 then
return 'cyan-refined-concrete'
elseif noise > -80 / 100 then
return 'blue-refined-concrete'
else
return 'black-refined-concrete'
end
end
function Debug.show_noise_value(surface, position, noise, render_values)
surface.set_tiles({{
name = noise_to_tile_map(noise),
position = position,
}}, false, true, true, false)
if render_values then
rendering.draw_text{
text = string.format('%.2f', noise),
surface = surface,
target = position,
draw_on_ground = true,
color = { 255, 255, 255 },
only_in_alt_mode = true,
}
end
end
return Debug

View File

@ -0,0 +1,104 @@
local Public = {}
local Debug = require 'map_gen.maps.frontier.shared.debug'
local Noise = require 'map_gen.shared.simplex_noise'
local simplex_noise = Noise.d2
-- add or use noise templates from here
local noises = {
['dungeon_sewer'] = {{ modifier = 0.00055, weight = 1.05 }, { modifier = 0.0062, weight = 0.024 }, { modifier = 0.0275, weight = 0.00135 }},
['cave_miner_01'] = {{ modifier = 0.002, weight = 1 }, { modifier = 0.003, weight = 0.5 }, { modifier = 0.01, weight = 0.01 }, { modifier = 0.1, weight = 0.015 }},
['oasis'] = {{ modifier = 0.00165, weight = 1.1 }, { modifier = 0.00275, weight = 0.55 }, { modifier = 0.011, weight = 0.165 }, { modifier = 0.11, weight = 0.0187 }},
['dungeons'] = {{ modifier = 0.0028, weight = 0.99 }, { modifier = 0.0059, weight = 0.21 }},
['cave_rivers_2'] = {{ modifier = 0.0035, weight = 0.90 }, { modifier = 0.0088, weight = 0.15 }, { modifier = 0.051, weight = 0.011 }},
['cave_miner_02'] = {{ modifier = 0.006, weight = 1 }, { modifier = 0.02, weight = 0.15 }, { modifier = 0.25, weight = 0.025 }},
['large_caves'] = {{ modifier = 0.055, weight = 0.045 }, { modifier = 0.11, weight = 0.042 }, { modifier = 0.00363, weight = 1.05 }, { modifier = 0.01, weight = 0.23 }},
['no_rocks'] = {{ modifier = 0.00495, weight = 0.945 }, { modifier = 0.01665, weight = 0.2475 }, { modifier = 0.0435, weight = 0.0435 }, { modifier = 0.07968, weight = 0.0315 }},
['scrapyard'] = {{ modifier = 0.0055, weight = 1.1 }, { modifier = 0.011, weight = 0.385 }, { modifier = 0.055, weight = 0.253 }, { modifier = 0.11, weight = 0.121 }},
['scrapyard_2'] = {{ modifier = 0.0066, weight = 1.1 }, { modifier = 0.044, weight = 0.165 }, { modifier = 0.242, weight = 0.055 }, { modifier = 0.055, weight = 0.352 }},
['smol_areas'] = {{ modifier = 0.0052, weight = 0.83 }, { modifier = 0.139, weight = 0.144 }, { modifier = 0.129, weight = 0.072 }, { modifier = 0.111, weight = 0.01 }},
['cave_rivers'] = {{ modifier = 0.0053, weight = 0.71 }, { modifier = 0.0086, weight = 0.24 }, { modifier = 0.070, weight = 0.025 }},
['small_caves'] = {{ modifier = 0.0066, weight = 1.1 }, { modifier = 0.044, weight = 0.165 }, { modifier = 0.242, weight = 0.055 }},
['forest_location'] = {{ modifier = 0.0066, weight = 1.1 }, { modifier = 0.011, weight = 0.275 }, { modifier = 0.055, weight = 0.165 }, { modifier = 0.11, weight = 0.0825 }},
['small_caves_2'] = {{ modifier = 0.0099, weight = 1.1 }, { modifier = 0.055, weight = 0.275 }, { modifier = 0.275, weight = 0.055 }},
['forest_density'] = {{ modifier = 0.01, weight = 1 }, { modifier = 0.05, weight = 0.5 }, { modifier = 0.1, weight = 0.025 }},
['cave_ponds'] = {{ modifier = 0.014, weight = 0.77 }, { modifier = 0.18, weight = 0.085 }},
['no_rocks_2'] = {{ modifier = 0.0184, weight = 1.265 }, { modifier = 0.143, weight = 0.1045 }},
}
-- returns a float number between -1 and 1
function Public.get_noise(name, pos, seed)
local noise = 0
local d = 0
for i = 1, #noises[name] do
local mod = noises[name]
noise = noise + simplex_noise(pos.x * mod[i].modifier, pos.y * mod[i].modifier, seed) * mod[i].weight
d = d + mod[i].weight
seed = seed + seed / seed
end
noise = noise / d
return noise
end
function Public.on_chunk_generated(event)
local area = event.area
local right_boundary = 12 * 32
local left_top = { x = math.max(area.left_top.x, right_boundary), y = area.left_top.y }
local right_bottom = area.right_bottom
if left_top.x >= right_bottom.x then
return
end
local x_min = left_top.x
local surface = event.surface
local seed = surface.map_gen_settings.seed
local STEP = 18 * 32
local limit = right_boundary + STEP
local noise_id = false
if not noise_id and x_min < limit then noise_id = 'dungeon_sewer' end limit = limit + STEP
if not noise_id and x_min < limit then noise_id = 'cave_miner_01' end limit = limit + STEP
if not noise_id and x_min < limit then noise_id = 'oasis' end limit = limit + STEP
if not noise_id and x_min < limit then noise_id = 'dungeons' end limit = limit + STEP
if not noise_id and x_min < limit then noise_id = 'cave_rivers_2' end limit = limit + STEP
if not noise_id and x_min < limit then noise_id = 'cave_miner_02' end limit = limit + STEP
if not noise_id and x_min < limit then noise_id = 'large_caves' end limit = limit + STEP
if not noise_id and x_min < limit then noise_id = 'no_rocks' end limit = limit + STEP
if not noise_id and x_min < limit then noise_id = 'scrapyard' end limit = limit + STEP
if not noise_id and x_min < limit then noise_id = 'scrapyard_2' end limit = limit + STEP
if not noise_id and x_min < limit then noise_id = 'smol_areas' end limit = limit + STEP
if not noise_id and x_min < limit then noise_id = 'cave_rivers' end limit = limit + STEP
if not noise_id and x_min < limit then noise_id = 'small_caves' end limit = limit + STEP
if not noise_id and x_min < limit then noise_id = 'forest_location' end limit = limit + STEP
if not noise_id and x_min < limit then noise_id = 'small_caves_2' end limit = limit + STEP
if not noise_id and x_min < limit then noise_id = 'forest_density' end limit = limit + STEP
if not noise_id and x_min < limit then noise_id = 'cave_ponds' end limit = limit + STEP
if not noise_id and x_min < limit then noise_id = 'no_rocks_2' end
if not noise_id then return end
local compute_noise = Public.get_noise
local show_noise = Debug.show_noise_value
for x = 0, 31 do
for y = 0, 31 do
local position = { x = left_top.x + x, y = left_top.y + y }
local noise = compute_noise(noise_id, position, seed)
show_noise(surface, position, noise)
end
end
local chunkpos = event.position
if (chunkpos.x) % 18 == 0 and (chunkpos.y == 1) then
rendering.draw_text{
text = noise_id,
surface = surface,
target = { x = left_top.x + 16, y = left_top.y + 16},
target_offset = {x = - 2 * 32, y = 0 },
scale = 128,
color = { 255, 255, 255 },
draw_on_ground = true,
only_in_alt_mode = true,
}
end
end
return Public