Files
Bastiaan 757a36fc03 Merge pull request #486 from bbassie/feature/convert-configs
Convert the remaining scenario configs into features
2026-10-05 00:33:36 +01:00

213 lines
7.5 KiB
Lua

--[[-- Control - Degrading Tiles
When a player walks around the tiles under them will degrade over time, the same is true when entites are built
]]
local Feature = require("modules/exp_scenario/features")
local feature, config = Feature.register("degrading_tiles", {
weakness_value = 70, -- lower value will make tiles more likely to degrade
entities = Feature.set{ -- entities which degrade the tiles under them when they are placed
"stone-furnace", "steel-furnace", "electric-furnace", "assembling-machine-1", "assembling-machine-2", "assembling-machine-3",
"beacon", "centrifuge", "chemical-plant", "oil-refinery", "storage-tank", "nuclear-reactor",
"steam-engine", "steam-turbine", "boiler", "heat-exchanger", "stone-wall", "gate",
"gun-turret", "laser-turret", "flamethrower-turret", "radar", "lab", "big-electric-pole",
"substation", "rocket-silo", "pumpjack", "electric-mining-drill", "roboport", "accumulator",
},
})
local random = math.random
--- How "strong" a tile is, bigger number means less likely to degrade
local strengths = {
-- debug: /interface require('modules.addons.worn-paths')(player.name,true)
-- note: tiles are effected by the tiles around them, so player paths will not degrade as fast when made wider
-- note: values are relative to the tile with the highest value, recommended to keep highest tile as a "nice" number
-- note: tiles not in list will never degrade under any conditions (which is why some are omitted such as water)
["refined-concrete"] = 100,
["refined-hazard-concrete-left"] = 100,
["refined-hazard-concrete-right"] = 100,
["concrete"] = 90,
["hazard-concrete-left"] = 90,
["hazard-concrete-right"] = 90,
["stone-path"] = 80,
["red-desert-0"] = 80,
["dry-dirt"] = 50,
-- grass four (main grass tiles)
["grass-1"] = 50,
["grass-2"] = 40,
["grass-3"] = 30,
["grass-4"] = 25,
-- red three (main red tiles)
["red-desert-1"] = 40,
["red-desert-2"] = 30,
["red-desert-3"] = 25,
-- sand three (main sand tiles)
["sand-1"] = 40,
["sand-2"] = 30,
["sand-3"] = 25,
-- dirt 3 (main dirt tiles)
["dirt-1"] = 40,
["dirt-2"] = 30,
["dirt-3"] = 25,
-- last three/four (all sets of three merge here)
["dirt-4"] = 25,
["dirt-5"] = 30,
["dirt-6"] = 40,
-- ["dirt-7"]=0, -- last tile, nothing to degrade to
-- land fill chain
-- ["landfill"]=50,
-- ["water-shallow"]=90,
-- ["water-mud"]=0, -- last tile, nothing to degrade to
}
--- When a tile degrades it will turn into the next tile given here
local degrade_order = {
["refined-concrete"] = "concrete",
["refined-hazard-concrete-left"] = "hazard-concrete-left",
["refined-hazard-concrete-right"] = "hazard-concrete-right",
["concrete"] = "stone-path",
["hazard-concrete-left"] = "stone-path",
["hazard-concrete-right"] = "stone-path",
["stone-path"] = "dry-dirt",
["red-desert-0"] = "dry-dirt",
["dry-dirt"] = "dirt-4",
-- grass four (main grass tiles)
["grass-1"] = "grass-2",
["grass-2"] = "grass-3",
["grass-3"] = "grass-4",
["grass-4"] = "dirt-4",
-- red three (main red tiles)
["red-desert-1"] = "red-desert-2",
["red-desert-2"] = "red-desert-3",
["red-desert-3"] = "dirt-4",
-- sand three (main sand tiles)
["sand-1"] = "sand-2",
["sand-2"] = "sand-3",
["sand-3"] = "dirt-4",
-- dirt 3 (main dirt tiles)
["dirt-1"] = "dirt-2",
["dirt-2"] = "dirt-3",
["dirt-3"] = "dirt-4",
-- last three/four (all sets of three merge here)
["dirt-4"] = "dirt-5",
["dirt-5"] = "dirt-6",
["dirt-6"] = "dirt-7",
-- ["dirt-7"]=0, -- last tile, nothing to degrade to
-- land fill chain
-- ["landfill"]='grass-2', -- 'water-shallow'
-- ["water-shallow"]='water-mud',
-- ["water-mud"]=0, -- last tile, nothing to degrade to
}
--- Get the max tile strength
local max_strength = 0
for _, strength in pairs(strengths) do
if strength > max_strength then
max_strength = strength
end
end
--- Replace a tile with the next tile in the degrade chain
--- @param surface LuaSurface
--- @param position MapPosition.struct
local function degrade_tile(surface, position)
local tile = surface.get_tile(position.x, position.y)
local tile_name = tile.name
local degrade_tile_name = degrade_order[tile_name]
if not degrade_tile_name then return end
surface.set_tiles{ { name = degrade_tile_name, position = position } }
end
--- Replace all titles under an entity with the next tile in the degrade chain
--- @param entity LuaEntity
local function degrade_entity(entity)
if not config.entities[entity.name] then return end
local tiles = {}
local surface = entity.surface
local bounding_box = entity.bounding_box
local left_top = bounding_box.left_top
local right_bottom = bounding_box.right_bottom
for x = left_top.x, right_bottom.x do
for y = left_top.y, right_bottom.y do
local tile = surface.get_tile(x, y)
local tile_name = tile.name
local degrade_tile_name = degrade_order[tile_name]
if degrade_tile_name then
tiles[#tiles + 1] = { name = degrade_tile_name, position = { x, y } }
end
end
end
surface.set_tiles(tiles)
end
--- Covert strength of a tile into a probability to degrade (0 = impossible, 1 = certain)
--- @param strength number
--- @return number
local function get_probability(strength)
return 1.5 * (1 - (strength / max_strength)) / config.weakness_value
end
--- Gets the average tile strengths around position
--- @param surface LuaSurface
--- @param position MapPosition.struct
--- @return number?
local function get_tile_strength(surface, position)
local tile = surface.get_tile(position.x, position.y)
local tile_name = tile.name
local strength = strengths[tile_name]
if not strength then return end
for x = position.x - 1, position.x + 1 do
for y = position.y - 1, position.y + 1 do
local check_tile = surface.get_tile(x, y)
local check_tile_name = check_tile.name
local check_strength = strengths[check_tile_name] or 0
strength = strength + check_strength
end
end
return strength / 9
end
--- When the player changes position the tile will have a chance to downgrade
--- @param event EventData.on_player_changed_position
local function on_player_changed_position(event)
local player = game.players[event.player_index]
if player.controller_type ~= defines.controllers.character then return end
local surface = player.physical_surface
local position = player.physical_position
local strength = get_tile_strength(surface, position)
if not strength then return end
if get_probability(strength) > random() then
degrade_tile(surface, position)
end
end
--- When an entity is build there is a much higher chance that the tiles will degrade
--- @param event EventData.on_built_entity | EventData.on_robot_built_entity
local function on_built_entity(event)
local entity = event.entity
local strength = get_tile_strength(entity.surface, entity.position)
if not strength then return end
if get_probability(strength) * config.weakness_value > random() then
degrade_entity(entity)
end
end
local e = defines.events
return feature:guard{
events = {
[e.on_player_changed_position] = on_player_changed_position,
[e.on_robot_built_entity] = on_built_entity,
[e.on_built_entity] = on_built_entity,
},
}