Aleksei-bird 7c9c708c92 Первый фикс
Пачки некоторых позиций увеличены
2024-03-01 20:54:33 +03:00

518 lines
18 KiB
Lua

local floor = math.floor
local function add_to_description(type, prototype, localised_string)
if prototype.localised_description and prototype.localised_description ~= '' then
prototype.localised_description = {'', prototype.localised_description, '\n', localised_string}
return
end
local place_result = prototype.place_result or prototype.placed_as_equipment_result
if type == 'item' and place_result then
for _, machine in pairs(data.raw) do
machine = machine[place_result]
if machine and machine.localised_description then
prototype.localised_description = {
'?',
{'', machine.localised_description, '\n', localised_string},
localised_string
}
return
end
end
local entity_type = prototype.place_result and 'entity' or 'equipment'
prototype.localised_description = {
'?',
{'', {entity_type .. '-description.' .. place_result}, '\n', localised_string},
{'', {type .. '-description.' .. prototype.name}, '\n', localised_string},
localised_string
}
else
prototype.localised_description = {
'?',
{'', {type .. '-description.' .. prototype.name}, '\n', localised_string},
localised_string
}
end
end
local function contains(tbl, goal, f)
for _, v in pairs(tbl) do
if f then
if f(v) == goal then return true end
else
if v == goal then return true end
end
end
return false
end
local function localised_string_contains(localised_string, key)
if type(localised_string) ~= 'table' then
return false
end
if localised_string[1] == key then
return localised_string[1]
end
for k, v in ipairs(localised_string) do
if k ~= 1 then
local result = localised_string_contains(v, key)
if result then return result end
end
end
return false
end
local prefixes = {
[''] = 1,
k = 1000,
K = 1000,
M = 1000000,
G = 1000000000,
T = 1000000000000,
P = 1000000000000000,
E = 1000000000000000000,
Z = 1000000000000000000000,
Y = 1000000000000000000000000
}
local function energy_to_number(energy)
local amount, unit, _ = string.match(energy, '(%d+)(%a-)[JW]')
return tonumber(amount) * prefixes[unit]
end
local function map(tbl, f)
local result = {}
for k, v in pairs(tbl) do
result[k] = f(v, k, tbl)
end
return result
end
local function localised_string_depth(localised_string)
if type(localised_string) ~= 'table' then
return 0
end
local result = 0
for k, v in pairs(localised_string) do
if k ~= 1 then
local depth = localised_string_depth(v)
if depth > result then
result = depth
end
end
end
return result + 1
end
-- productivity
local recipes = {}
for module_name, mod in pairs(data.raw.module) do
if mod.limitation and mod.effect.productivity and module_name:find('pyveganism') == nil then
for recipe_name, recipe in pairs(data.raw.recipe) do
if not recipes[recipe_name] and contains(mod.limitation, recipe_name) then
add_to_description('recipe', recipe, {'description.productivity-message'})
recipes[recipe_name] = true
end
end
end
end
-- allowed modules
if settings.startup['ed-allowed-modules'].value then
for _, prototype in ipairs{'lab', 'assembling-machine', 'furnace', 'rocket-silo', 'beacon', 'mining-drill'} do
for _, machine in pairs(data.raw[prototype]) do
if (prototype == 'lab' or prototype == 'mining-drill') and machine.allowed_effects == nil then
machine.allowed_effects = {'speed', 'productivity', 'consumption', 'pollution'}
end
local modules = machine.module_specification
if modules and tonumber(modules.module_slots) and tonumber(modules.module_slots) > 0 and machine.allowed_effects and machine.allowed_effects ~= {} then
add_to_description('entity', machine, {'description.module-slots', tostring(machine.module_specification.module_slots)})
local allowed
if type(machine.allowed_effects) == 'string' then
allowed = {machine.allowed_effects}
elseif type(machine.allowed_effects) == 'table' then
allowed = machine.allowed_effects
end
if not contains(allowed, 'speed') then
add_to_description('entity', machine, {'description.speed-module-limitation'})
end
if not contains(allowed, 'productivity') then
add_to_description('entity', machine, {'description.productivity-module-limitation'})
end
if not contains(allowed, 'consumption') then
add_to_description('entity', machine, {'description.consumption-module-limitation'})
end
end
end
end
end
-- building size
if settings.startup['ed-building-size'].value then
for _, prototype in pairs(data.raw) do
for item_name, item in pairs(prototype) do
if item.stack_size then
if item.place_result then
for _, entity in pairs(data.raw) do
for _, entity in pairs(entity) do
if entity.minable and entity.minable.result == item_name and (entity.flags == nil or contains(entity.flags, 'placeable-off-grid') == false) then
local box = entity.collision_box
if box then
local x = math.ceil(box[2][2] * 2) / 2 - math.floor(box[1][2] * 2) / 2
local y = math.ceil(box[2][1] * 2) / 2 - math.floor(box[1][1] * 2) / 2
if x > 1 or y > 1 then
if y > x then x, y = y, x end
add_to_description('entity', entity, {'description.building-size', tostring(x), tostring(y)})
end
end
goto done
end
end
end
::done::
end
else break end
end
end
end
-- resistances for military entities
if settings.startup['ed-military-resistances'].value then
for _, prototype in pairs(data.raw) do
for _, entity in pairs(prototype) do
if entity.stack_size then break end
if entity.attack_parameters or (entity.flags and contains(entity.flags, 'placeable-enemy')) then
entity.hide_resistances = false
end
end
end
for _, prototype in ipairs{'wall', 'gate', 'car', 'artillery-wagon'} do
for _, entity in pairs(data.raw[prototype]) do
entity.hide_resistances = false
end
end
end
-- heat
if settings.startup['ed-heat'].value then
for _, name in ipairs{'reactor', 'heat-pipe'} do
for _, prototype in pairs(data.raw[name]) do
local buffer = prototype.heat_buffer
add_to_description('entity', prototype, {'description.max-heat', buffer.max_temperature})
add_to_description('entity', prototype, {(name == 'reactor') and 'description.heat-loss-reactor' or 'description.heat-loss-pipe', buffer.min_temperature_gradient or 1})
end
end
end
-- solar ratios
if settings.startup['ed-solar-ratios'].value then
for _, prototype in ipairs{'accumulator', 'solar-panel'} do
for name, machine in pairs(data.raw[prototype]) do
for _, item in pairs(data.raw.item) do
if item.place_result == name then
item.localised_description = item.localised_description or machine.localised_description or ''
end
end
end
end
local empty_table = function() return {} end
local accumulators_perfect = map(data.raw.accumulator, empty_table)
local accumulators_imperfect = map(data.raw.accumulator, empty_table)
local solar_panels_perfect = map(data.raw['solar-panel'], empty_table)
local solar_panels_imperfect = map(data.raw['solar-panel'], empty_table)
local accumulator_count = 0
local solar_count = 0
for _, _ in pairs(data.raw['solar-panel']) do
solar_count = solar_count + 1
end
for accumulator_name, accumulator in pairs(data.raw.accumulator) do
accumulator_count = accumulator_count + 1
local accumulator_localised_name = accumulator.localised_name or {'entity-name.' .. accumulator_name}
local accumulator_size = accumulator.energy_source.buffer_capacity
if accumulator_size == '1J' then goto a end
for solar_name, solar in pairs(data.raw['solar-panel']) do
local solar_localised_name = solar.localised_name or {'entity-name.' .. solar_name}
local panel_production = solar.production
if panel_production == '1W' then goto s end
local ratio = energy_to_number(panel_production) / energy_to_number(accumulator_size) * 70
local integer = math.floor(ratio)
local decimal = ratio - integer
local pn, n, N = 0, 1
local pd, d, D = 1, 0
local x, perfect, q, Q
repeat
x = x and 1 / (x - q) or decimal
q, Q = math.floor(x), math.floor(x + 0.5)
pn, n, N = n, q * n + pn, Q * n + pn
pd, d, D = d, q * d + pd, Q * d + pd
perfect = decimal - N/D
until math.abs(perfect) < 0.00000001
perfect = perfect == 0
if perfect then
local accumulator_ratio = N + D * integer
local solar_ratio = D
table.insert(accumulators_perfect[accumulator_name], {'description.solar-ratio', solar_localised_name, accumulator_ratio, solar_ratio})
table.insert(solar_panels_perfect[solar_name], {'description.solar-ratio', accumulator_localised_name, solar_ratio, accumulator_ratio})
else
table.insert(accumulators_imperfect[accumulator_name], {'description.solar-ratio-imperfect', solar_localised_name , math.floor(0.5 + ratio * 1000) / 1000})
table.insert(solar_panels_imperfect[solar_name], {'description.solar-ratio-imperfect', accumulator_localised_name, math.floor(0.5 + 1 / ratio * 1000) / 1000})
end
::s::
end
::a::
end
for name, accumulator in pairs(data.raw.accumulator) do
if solar_count + localised_string_depth(accumulator.localised_description) > 18 then goto next end
for _, perfect in pairs(accumulators_perfect[name]) do
add_to_description('entity', accumulator, perfect)
end
for _, perfect in pairs(accumulators_imperfect[name]) do
add_to_description('entity', accumulator, perfect)
end
::next::
end
for name, solar in pairs(data.raw['solar-panel']) do
if accumulator_count + localised_string_depth(solar.localised_description) > 18 then goto next end
for _, perfect in pairs(solar_panels_perfect[name]) do
add_to_description('entity', solar, perfect)
end
for _, perfect in pairs(solar_panels_imperfect[name]) do
add_to_description('entity', solar, perfect)
end
::next::
end
end
-- radar range
if settings.startup['ed-radar-stats'].value then
for _, radar in pairs(data.raw.radar) do
add_to_description('entity', radar, {'description.radar-primary-range', radar.max_distance_of_nearby_sector_revealed})
add_to_description('entity', radar, {'description.radar-secondary-range', radar.max_distance_of_sector_revealed})
add_to_description('entity', radar, {'description.radar-scan-time', math.floor(0.5 + energy_to_number(radar.energy_per_sector) / energy_to_number(radar.energy_usage) * 100) / 100})
end
end
-- inserters
if settings.startup['ed-inserter-stats'].value then
local inserter_stack_size = 1
local stack_inserter_stack_size = 1
for _, technology in pairs(data.raw.technology) do
if technology.hidden ~= true and technology.enabled ~= false and technology.effects then
for _, effect in ipairs(technology.effects) do
if effect.type == 'inserter-stack-size-bonus' then
inserter_stack_size = inserter_stack_size + effect.modifier
elseif effect.type == 'stack-inserter-capacity-bonus' then
stack_inserter_stack_size = stack_inserter_stack_size + effect.modifier
end
end
end
end
local fastest_belt
local slowest_belt
for _, belt in pairs(data.raw['transport-belt']) do
local speed = belt.speed * 480
if 0 < speed and speed < 200 then
if fastest_belt == nil or speed > fastest_belt then
fastest_belt = speed
end
if slowest_belt == nil or speed < slowest_belt then
slowest_belt = speed
end
end
end
for inserter_name, inserter in pairs(data.raw.inserter) do
local multiplier_1 = inserter.stack and 2 or 1
local multiplier_2 = inserter.stack and stack_inserter_stack_size or inserter_stack_size
local hand_speed = inserter.rotation_speed * 57.75
for _, item in pairs(data.raw.item) do
if item.place_result == inserter_name then
item.localised_description = item.localised_description or inserter.localised_description or ''
end
end
add_to_description('entity', inserter, {
'',
{'description.inserter-speed'},
{'description.inserter-speed-chest-to-chest'},
{'description.inserter-stack-size', multiplier_1, math.floor(0.5 + hand_speed * multiplier_1 * 100) / 100},
{'description.inserter-stack-size', multiplier_2, math.floor(0.5 + hand_speed * multiplier_2 * 100) / 100},
{'description.inserter-speed-chest-to-belt'},
{'description.inserter-stack-size', multiplier_1, math.floor(0.5 + 1 / (1 / hand_speed / multiplier_1 + 0.0445272463 * multiplier_1 / slowest_belt) * 100) / 100},
{'description.inserter-belt-speed', slowest_belt},
'\n',
{'description.inserter-stack-size', multiplier_2, math.floor(0.5 + 1 / (1 / hand_speed / multiplier_2 + 0.0445272463 * multiplier_2 / fastest_belt) * 100) / 100},
{'description.inserter-belt-speed', fastest_belt},
'\n',
{'description.inserter-speed-belt-to-chest'},
{'description.inserter-stack-size-guess', multiplier_1, math.floor(0.5 + 1 / (1 / hand_speed / multiplier_1 + 0.055 * multiplier_1 / slowest_belt) * 10) / 10},
{'description.inserter-belt-speed', slowest_belt},
'\n',
{'description.inserter-stack-size-guess', multiplier_2, math.floor(0.5 + 1 / (1 / hand_speed / multiplier_2 + 0.055 * multiplier_2 / fastest_belt) * 10) / 10},
{'description.inserter-belt-speed', fastest_belt},
})
end
end
-- SE build restrictions
if mods['space-exploration'] then
for _, building in pairs(data.raw) do
for _, building in pairs(building) do
if building.localised_description then
local placement = localised_string_contains(building.localised_description, 'placement_restriction_line')
if placement then
add_to_description('entity', building, placement)
end
end
end
end
end
-- tank size and pressure
if settings.startup['ed-tank-size'].value then
for prototype_name, tank in pairs(data.raw) do
for tank_name, tank in pairs(tank) do
local box = tank.fluid_box
if box then
if tank.minable then
local size = (box.height or 1) * (box.base_area or 1)
local pressure = (box.height or 1) + (box.base_level or 0)
if prototype_name ~= 'storage-tank' or pressure ~= 1 then
add_to_description('entity', tank, {'description.tank-size', size * 100})
add_to_description('entity', tank, {'description.pressure', pressure * 100})
end
end
else break end
end
end
end
-- fluid colors
if settings.startup['ed-fluid-colors'].value then
local function interpret_color(color)
local r = color.r or color[1] or 0
local g = color.g or color[2] or 0
local b = color.b or color[3] or 0
local a = color.a or color[4] or 1
if r <= 1 and g <= 1 and b <= 1 and a <= 1 then
r = r * 255
g = g * 255
b = b * 255
end
return '[color=' .. tostring(floor(r)) .. ',' .. tostring(floor(g)) .. ',' .. tostring(floor(b)) .. '] ■[/color]'
end
for _, fluid in pairs(data.raw.fluid) do
if fluid.localised_name and fluid.localised_name ~= '' then
fluid.localised_name = {'', fluid.localised_name, interpret_color(fluid.base_color)}
else
fluid.localised_name = {'', {'fluid-name.' .. fluid.name}, interpret_color(fluid.base_color)}
end
end
end
-- deadlock stacking & item stack sizes
for _, prototype in pairs(data.raw) do
for item_name, item in pairs(prototype) do
if item.stack_size and not item_name:find('^big%-data%-') then
add_to_description('item', item, {'description.stack-size', tostring(item.stack_size)})
if mods['deadlock-beltboxes-loaders'] and data.raw.item['deadlock-stack-' .. item_name] then
add_to_description('item', item, {'description.stackable'})
end
else break end
end
end
-- voiding
if settings.startup['ed-voiding'].value then
local void_categories = {
['incineration'] = {'incinerator', 'electric-incinerator'},
['fuel-incineration'] = {'electric-incinerator'},
['flaring'] = {'vent-stack', 'flare-stack'},
['py-incineration'] = {'py-burner'},
['py-venting'] = {'py-gas-vent'},
['py-runoff'] = {'py-sinkhole'},
['angels-chemical-void'] = {'angels-flare-stack'},
['angels-water-void'] = {'clarifier'}
}
for _, recipe in pairs(data.raw.recipe) do
if recipe.category and void_categories[recipe.category] then
recipe.always_show_products = true
local difficulty = recipe.normal or recipe.expensive or recipe
local ingredient = difficulty.ingredients[1]
if ingredient == nil then break end
if ingredient[1] then
ingredient = {type = 'item', name = ingredient[1], amount = ingredient[2]}
end
local target
local target_type = 'item'
if ingredient.type == 'item' then
for _, prototype in pairs(data.raw) do
for _, item in pairs(prototype) do
if item.stack_size and prototype[ingredient.name] then
target = prototype[ingredient.name]
goto done
end
break
end
end
::done::
elseif ingredient.type == 'fluid' then
target = data.raw.fluid[ingredient.name]
target_type = 'fluid'
end
for _, machine in ipairs(void_categories[recipe.category]) do
machine = data.raw.furnace[machine] or data.raw['assembling-machine'][machine]
if machine then
add_to_description(target_type, target, {
'description.voidable',
machine.localised_name or {'entity-name.' .. machine.name},
math.floor(0.5 + ingredient.amount / (difficulty.energy_required or 0.5) * 100) / 100
})
end
end
end
end
end