diff --git a/gas-boiler/changelog.txt b/gas-boiler/changelog.txt new file mode 100644 index 0000000..5adb839 --- /dev/null +++ b/gas-boiler/changelog.txt @@ -0,0 +1,55 @@ +--------------------------------------------------------------------------------------------------- +Version: 0.1.0 +Date: 2020-11-15 + + Changes: + - Incremented to version 1.0. + + Entities: + - Reduced fuel input fluid box to height 1. + +--------------------------------------------------------------------------------------------------- +Version: 0.0.5 +Date: 2020-02-03 + + Changes: + - Incremented to version 18. + - Copied old assembler 1 graphics from 0.17 + because they match the boiler's color. + +--------------------------------------------------------------------------------------------------- +Version: 0.0.4 +Date: 2019-11-26 + + Locale: + - Added Russian translations provided by Va7ya. + +--------------------------------------------------------------------------------------------------- +Version: 0.0.3 +Date: 2019-09-30 + + Graphics: + - Increased secondary draw orders on south- + facing fuel connection picture so it will + cover the working_light picture. I plan + to make a new working_light picture in + the long run. + + Fixes: + - Fixed changelog. + +--------------------------------------------------------------------------------------------------- +Version: 0.0.2 +Date: 2019-09-05 + + Fixes: + - Fixed version number. + +--------------------------------------------------------------------------------------------------- +Version: 0.0.1 +Date: 2019-09-05 + + Prototypes: + - Created new gas-boiler prototype to replace + multiple fluid-powered boiler entities in my + other mods. diff --git a/gas-boiler/data-updates.lua b/gas-boiler/data-updates.lua new file mode 100644 index 0000000..36e0e53 --- /dev/null +++ b/gas-boiler/data-updates.lua @@ -0,0 +1,4 @@ +require("factsheet") +if settings.startup["vanilla-fluid-fuel-values"].value then + apply_vanilla_fluid_fuel_stats() +end \ No newline at end of file diff --git a/gas-boiler/data.lua b/gas-boiler/data.lua new file mode 100644 index 0000000..ea03dd1 --- /dev/null +++ b/gas-boiler/data.lua @@ -0,0 +1,182 @@ +require("factsheet") +gf_boiler_entity = util.table.deepcopy(data.raw.boiler.boiler) +gf_boiler_entity.name = "gas-boiler" +gf_boiler_entity.icon = "__gas-boiler__/graphics/icons/gas-boiler.png" +gf_boiler_entity.icon_size = 32 +gf_boiler_entity.minable.result = "gas-boiler" +gf_boiler_entity.fast_replaceable_group = "boiler" +gf_boiler_entity.energy_source = { + type = "fluid", + fluid_box = { + base_area = 1, + height = 1, + base_level = -1, + pipe_covers = pipecoverspictures(), + pipe_picture = { + north = { + filename = "__gas-boiler__/graphics/entity/" + .."assembling-machine-1-pipe-N.png", + priority = "extra-high", + width = 35, + height = 18, + shift = util.by_pixel(2.5, 14), + hr_version = { + filename = "__gas-boiler__/graphics/entity/" + .."hr-assembling-machine-1-pipe-N.png", + priority = "extra-high", + width = 71, + height = 38, + shift = util.by_pixel(2.25, 13.5), + scale = 0.5 + } + }, + east = { + filename = "__gas-boiler__/graphics/entity/" + .."assembling-machine-1-pipe-E.png", + priority = "extra-high", + width = 20, + height = 38, + shift = util.by_pixel(-25, 1), + hr_version = { + filename = "__gas-boiler__/graphics/entity/" + .."hr-assembling-machine-1-pipe-E.png", + priority = "extra-high", + width = 42, + height = 76, + shift = util.by_pixel(-24.5, 1), + scale = 0.5 + } + }, + south = { + filename = "__gas-boiler__/graphics/entity/" + .."assembling-machine-1-pipe-S.png", + priority = "extra-high", + width = 44, + height = 31, + shift = util.by_pixel(0, -31.5), + hr_version = { + filename = "__gas-boiler__/graphics/entity/" + .."hr-assembling-machine-1-pipe-S.png", + priority = "extra-high", + width = 88, + height = 61, + shift = util.by_pixel(0, -31.25), + scale = 0.5 + } + }, + west = { + filename = "__gas-boiler__/graphics/entity/" + .."assembling-machine-1-pipe-W.png", + priority = "extra-high", + width = 19, + height = 37, + shift = util.by_pixel(25.5, 1.5), + hr_version = { + filename = "__gas-boiler__/graphics/entity/" + .."hr-assembling-machine-1-pipe-W.png", + priority = "extra-high", + width = 39, + height = 73, + shift = util.by_pixel(25.75, 1.25), + scale = 0.5 + } + } + }, + pipe_connections = { + {type = "input", position = {0, 1.5}}, + }, + secondary_draw_orders = { + south = 32, + north = -1, + east = -1, + west = -1, + } + }, + burns_fluid = true, + scale_fluid_usage = true, + emissions_per_minute = 30, + smoke = {{ + name = "smoke", + north_position = util.by_pixel(-38, -47.5), + south_position = util.by_pixel(38.5, -32), + east_position = util.by_pixel(20, -70), + west_position = util.by_pixel(-19, -8.5), + frequency = 15, + starting_vertical_speed = 0.3, + starting_frame_deviation = 0 + }}, + light_flicker = { + color = colors.gas_fire_glow, + minimum_light_size = 0.1, + light_intensity_to_size_coefficient = 1 + } +} +gf_boiler_entity.fire_flicker_enabled = false +gf_boiler_entity.fire_glow_flicker_enabled = false +gf_boiler_entity.fire = {} +gf_boiler_entity.fire_glow.north.filename = + "__gas-boiler__/graphics/entity/".. + "gas-boiler-N-light.png" +gf_boiler_entity.fire_glow.south.filename = + "__gas-boiler__/graphics/entity/".. + "gas-boiler-S-light.png" +gf_boiler_entity.fire_glow.east.filename = + "__gas-boiler__/graphics/entity/".. + "gas-boiler-E-light.png" +gf_boiler_entity.fire_glow.west.filename = + "__gas-boiler__/graphics/entity/".. + "gas-boiler-W-light.png" +gf_boiler_entity.fire_glow.north.hr_version.filename = + "__gas-boiler__/graphics/entity/".. + "hr-gas-boiler-N-light.png" +gf_boiler_entity.fire_glow.south.hr_version.filename = + "__gas-boiler__/graphics/entity/".. + "hr-gas-boiler-S-light.png" +gf_boiler_entity.fire_glow.east.hr_version.filename = + "__gas-boiler__/graphics/entity/".. + "hr-gas-boiler-E-light.png" +gf_boiler_entity.fire_glow.west.hr_version.filename = + "__gas-boiler__/graphics/entity/".. + "hr-gas-boiler-W-light.png" +gf_boiler_entity.fire_glow.north.apply_runtime_tint = true +gf_boiler_entity.fire_glow.south.apply_runtime_tint = true +gf_boiler_entity.fire_glow.east.apply_runtime_tint = true +gf_boiler_entity.fire_glow.west.apply_runtime_tint = true +gf_boiler_entity.fire_glow.north.tint={r=1,g=0.6,b=0.6,a=0.4} +gf_boiler_entity.fire_glow.south.tint={r=1,g=0.6,b=0.6,a=0.4} +gf_boiler_entity.fire_glow.east.tint={r=1,g=0.6,b=0.6,a=0.4} +gf_boiler_entity.fire_glow.west.tint={r=1,g=0.6,b=0.6,a=0.4} +gf_boiler_entity.fire_glow.north.blend_mode = "additive-soft" +gf_boiler_entity.fire_glow.south.blend_mode = "additive-soft" +gf_boiler_entity.fire_glow.east.blend_mode = "additive-soft" +gf_boiler_entity.fire_glow.west.blend_mode = "additive-soft" + + +gf_boiler_item = util.table.deepcopy(data.raw.item.boiler) +gf_boiler_item.name = "gas-boiler" +gf_boiler_item.icon_size = 32 +gf_boiler_item.icon = "__gas-boiler__/graphics/icons/gas-boiler.png" +gf_boiler_item.order = "b[steam-power]-b[gas-boiler]" +gf_boiler_item.place_result = "gas-boiler" + +gf_boiler_recipe = { + type = "recipe", + name = "gas-boiler", + enabled = false, + ingredients = {{ + "boiler",1 + },{ + "pump",1 + }}, + result = "gas-boiler" +} + +data:extend({ + gf_boiler_item, + gf_boiler_recipe, + gf_boiler_entity +}) +add_recipe_to_tech( + "fluid-handling", + "gas-boiler" +) \ No newline at end of file diff --git a/gas-boiler/factsheet.lua b/gas-boiler/factsheet.lua new file mode 100644 index 0000000..37a1a60 --- /dev/null +++ b/gas-boiler/factsheet.lua @@ -0,0 +1,3095 @@ +-- Freeware modding by Adamo +require("util") + +-- Basic utils +adamo = { + opts = { + logging = false, + debugging = false + }, + logfile = function(str) + if adamo.opts.log and string_or_bust(str) + and type(game) == 'table' + and type(game.write_file) == 'function' then + game.write_file("adamo.log",str,true) + end + end, + debugfile = function(str) + if adamo.opts.debugging and string_or_bust(str) + and type(game) == 'table' + and type(game.write_file) == 'function' then + game.write_file("adamo.debug",str,true) + end + end, + log = function(str) + if adamo.opts.log and string_or_bust(str) then + log(str) + end + end, + debug = function(str) + if adamo.opts.debugging and string_or_bust(str) then + log("[DEBUG] "..tostring(str)) + end + end +} + +-- Power production efficiencies. +-- Temps determined to maintain blueprint compatibility. +-- Applied by my physics mod. +boiler_eff = 0.85 +gen_eff = 0.5 +furnace_eff = 0.65 +reactor_eff = 0.80 +chem_temp_max = 315 +nuke_temp_max = 990 +reactor_consump_mult = 2.01 +chem_fuel_quotient = boiler_eff*gen_eff +nuke_fuel_quotient = reactor_eff*gen_eff +-- Based on theoretical max throughput +-- of a 3 meter^2 solar panel (5.1kW). +solar_panel_eff = 1/10 -- should be 6 kW +accumulator_power_quotient = 1/solar_panel_eff + +adamo.fuel = { + factors = { + ["topower"] = 1/60, + ["coal"] = 3, + ["light-oil"] = 10, + ["heavy-oil"] = 20, + ["petroleum-gas"] = 20, + ["crude-oil"] = 30, + ["methane"] = 50, + }, + values = { + ["sulfur"] = "600kJ" + } +} +adamo.fuel.factors["syngas"] = adamo.fuel.factors["methane"]*2 + +-- For backward compatibility. +fuelfactors = { + topower = adamo.fuel.factors.topower +} +fuelfactors["coal"] = adamo.fuel.factors["coal"] +fuelfactors["light-oil"] = adamo.fuel.factors["light-oil"] +fuelfactors["heavy-oil"] = adamo.fuel.factors["heavy-oil"] +fuelfactors["petroleum-gas"] = adamo.fuel.factors["petroleum-gas"] +fuelfactors["crude-oil"] = adamo.fuel.factors["crude-oil"] +fuelfactors["methane"] = adamo.fuel.factors["methane"] +fuelfactors["syngas"] = adamo.fuel.factors["syngas"] + +fuelvalues = { + sulfur = adamo.fuel.values.sulfur +} + +-- Chemical constants +adamo.chem = { + mult = { + fluid = 10 + }, + fluxables = { + ["iron-ore"] = "iron-plate", + ["copper-ore"] = "copper-plate" + }, + ratio = { + lime_per_clinker = 1, + gypsum_per_clinker = 1/100, + fluorite_per_clinker = 1/100, + clinker_per_cement = 10, + gypsum_per_cement = 1, + stone_per_concrete = 1, + cement_per_concrete = 1/10, + quartz_per_concrete = 1/5, + quartz_per_redchip = 3/5, + fluorite_per_HF = 1/20, + lime_per_battery = 1, + HF_per_battery = 10, + sulfur_per_flask = 1, + redchip_per_flask = 3, + } +} +adamo.chem.ratio.lime_per_cement = + adamo.chem.ratio.lime_per_clinker + * adamo.chem.ratio.clinker_per_cement +adamo.chem.ratio.lime_per_concrete = + adamo.chem.ratio.lime_per_cement + * adamo.chem.ratio.cement_per_concrete +adamo.chem.ratio.gypsum_per_lime = + adamo.chem.ratio.gypsum_per_cement + / adamo.chem.ratio.lime_per_cement +adamo.chem.ratio.quart_per_lime = + adamo.chem.ratio.quartz_per_concrete + / adamo.chem.ratio.lime_per_concrete +adamo.chem.ratio.fluorite_per_lime = + adamo.chem.ratio.fluorite_per_HF + * adamo.chem.ratio.HF_per_battery + / adamo.chem.ratio.lime_per_battery +adamo.chem.ratio.quartz_per_sulfur = + adamo.chem.ratio.quartz_per_redchip + * adamo.chem.ratio.redchip_per_flask + / adamo.chem.ratio.sulfur_per_flask + + +adamo.geo = { + ore = {}, + abundance = { + calcite = 0.6, + quartz, + gypsum, + sulfur, + fluorite, + coal, + } +} + + +-- values must be between 0 and 1 +local battery_share = 0.05 +local blue_flask_share = 0.1 +local coal_recovery = 0.075 +adamo.geo.abundance.fluorite = battery_share + *adamo.geo.abundance.calcite + *adamo.chem.ratio.fluorite_per_lime +adamo.geo.abundance.gypsum = adamo.geo.abundance.calcite + *adamo.chem.ratio.gypsum_per_lime +adamo.geo.abundance.quartz = adamo.geo.abundance.calcite + *adamo.chem.ratio.quart_per_lime +adamo.geo.abundance.sulfur = adamo.geo.abundance.fluorite + + ( + blue_flask_share + *adamo.geo.abundance.quartz + /adamo.chem.ratio.quartz_per_sulfur + ) +if adamo.geo.abundance.sulfur < 0 then + adamo.geo.abundance.sulfur = 0 +end +local sum = adamo.geo.abundance.calcite + +adamo.geo.abundance.fluorite + +adamo.geo.abundance.gypsum + +adamo.geo.abundance.quartz + +adamo.geo.abundance.sulfur +adamo.geo.abundance.coal = coal_recovery * (1 - sum) + + + +local quartz_recovery = 1/5 +local recover_ratio = 1/2 +local ore_mineral_norm = recover_ratio * 1 / ( + adamo.geo.abundance.fluorite + + adamo.geo.abundance.quartz + + adamo.geo.abundance.sulfur + ) + +adamo.geo.ore.mineral_results = { + ["adamo-chemical-fluorite"] = adamo.geo.abundance.fluorite + * ore_mineral_norm, + ["adamo-chemical-quartz"] = adamo.geo.abundance.quartz + * ore_mineral_norm, + ["SiSi-quartz"] = quartz_recovery*adamo.geo.abundance.quartz + * ore_mineral_norm, + ["sulfur"] = adamo.geo.abundance.sulfur + * ore_mineral_norm, + ["coal"] = adamo.geo.abundance.coal + * ore_mineral_norm, +} + +adamo.geo.ore.impurity_ratio = 1/20 + +-- Physical quantities +physical_units = { "J", "W", "C" } +metrics = { "K","M","G","T","P","E","Z","Y" } + +get_phynum_val = function(phynum) + local phynum,val = phynum_or_bust(phynum) + return val +end + +phynum_or_bust = function(phynum) + if type(phynum) == 'string' then + local val = phynum:match "[0-9%.]+" + local unit = phynum:match "%a+" + if val and unit then return val..unit,val,unit end + end + return nil,nil,nil +end + +energy_or_bust = function(energy) + if type(energy) == 'number' then + return energy..'J',energy,'J' + end + return phynum_or_bust(energy) +end + +power_or_bust = function(power) + if type(power) == 'number' then + return power..'W',power,'W' + end + return phynum_or_bust(power) +end + +energy_to_power = function(energy) + return energy_mult(energy,fuelfactors.topower) +end + +power_to_energy = function(energy) + return energy_div(energy,fuelfactors.topower) +end + +energy_mult = function(energy,mult) + local energy = energy_or_bust(energy) + return phynum_mult(energy,mult) +end + +energy_div = function(energy,div) + local energy = energy_or_bust(energy) + return phynum_div(energy,div) +end + +phynum_mult = function(phynum,mult) + local e,val,unit = phynum_or_bust(phynum) + if val and unit then e = (val*mult)..unit end + return e +end + +phynum_div = function(phynum,div) + local e,val,unit = phynum_or_bust(phynum) + if val and unit then e = (val/div)..unit end + return e +end + +add_prereq_to_tech = function(tech,prereq_name) + local tech = tech_or_bust(tech) + local prereq_name = string_or_bust(prereq_name) + if not tech or not prereq_name then return nil end + return add_string_to_list(tech.prerequisites,prereq_name) +end + +add_prereqs_to_tech = function (tech,prereq_table) + local prereq_table = table_or_bust(prereq_table) + if not prereq_table then return false end + local return_val = true + for _,prereq_name in pairs(prereq_table) do + if not add_prereq_to_tech(tech,prereq_name) then + return_val = false + end + end + return return_val +end + +remove_tech = function(old_tech) + local old_tech = tech_or_bust(old_tech) + if not old_tech then return false end + for _,tech in pairs(data.raw.technology) do + remove_val_from_table( + tech.prerequisites, + old_tech.name + ) + end + data.raw.technology[old_tech.name] = nil + return true +end + +add_recipe_to_tech = function(tech_name,recipe_name) + local recipe_name = string_name_or_bust(recipe_name) + local tech = false + if type(tech_name) == "table" + and tech_name.type == "technology" then + tech = tech_name + elseif type(tech_name) == "string" then + tech = data.raw["technology"][tech_name] + end + if tech then + if not tech.effects then + tech.effects = {{ + type="unlock-recipe", + recipe=recipe_name + }} + else + table.insert(tech.effects, { + type="unlock-recipe", + recipe=recipe_name + }) + end + return true + end + return false +end + +add_tech_recipe = function(tech_name,recipe_name) + return add_recipe_to_tech(tech_name,recipe_name) +end + +add_recipe_tech = function(tech_name,recipe_name) + return add_recipe_to_tech(tech_name,recipe_name) +end + +add_recipes_to_tech = function(tech_name,name_table) + if type(name_table) ~= "table" then return nil end + for _,name in pairs(name_table) do + add_recipe_to_tech(tech_name,name) + end +end + +move_recipe_to_tech = function(tech_name,recipe_name) + if add_tech_recipe(tech_name,recipe_name) then + remove_recipe_all_techs(recipe_name) + add_tech_recipe(tech_name,recipe_name) + return true + end + return false +end + +move_recipes_to_tech = function(tech_name,name_table) + if type(name_table) ~= "table" then return false end + for _,name in pairs(name_table) do + move_recipe_to_tech(tech_name,name) + end +end + +remove_recipe_all_techs = function(recipe_name) + for _,tech in pairs(data.raw.technology) do + remove_tech_recipe(tech.name,recipe_name) + end +end + +remove_tech_recipe = function(tech_name,recipe_name) + if type(recipe_name) == "table" then + remove_tech_recipes(recipe_name) + end + local recipe_name = string_name_or_bust(recipe_name) + if not recipe_name then return nil end + local tech = false + if type(tech_name) == "table" + and tech_name.type == "technology" then + tech = tech_name + elseif type(tech_name) == "string" then + tech = data.raw["technology"][tech_name] + end + if tech then + if not tech.effects then + return false + elseif type(tech.effects) == "table" then + return remove_val_from_table( + tech.effects, + { + type="unlock-recipe", + recipe=recipe_name + } + ) + end + return true + end + return false +end + +remove_tech_recipes = function(tech_name,name_table) + if type(name_table) ~= "table" then return nil end + for _,name in pairs(name_table) do + remove_tech_recipe(tech_name,name) + end +end + +find_recipe_techs = function(recipe_name) + local tech_names = {} + local recipe_name = string_name_or_bust(recipe_name) + for k,tech in pairs(data.raw.technology) do + local found_tech = false + if tech.effects then + for l,effect in pairs(tech.effects) do + if effect.type == "unlock-recipe" + and effect.recipe == recipe_name then + table.insert( + tech_names, + tech.name + ) + end + end + end + end + return tech_names +end + +all_recipes_of_category = function(category_str) + if category_str == "crafting" then + return smoosh_tables( + all_prototypes_with_value( + "recipe", + "category", + category_str + ), + all_prototypes_with_value( + "recipe", + "category", + nil + ) + ) + end + return all_prototypes_with_value( + "recipe", + "category", + category_str + ) +end + +mirror_recipe_in_techs = function(orig_recipe,new_recipe) + local tech_names = find_recipe_techs(orig_recipe) + for _,tech_name in pairs(tech_names) do + add_recipe_to_tech(tech_name,new_recipe) + end +end + +mult_recipe_energy = function(recipe,mult) + local recipe = recipe_or_bust(recipe) + if recipe.normal then + recipe.normal.energy_required = + (recipe.normal.energy_required or 0.5) + * mult + if recipe.expensive then + recipe.expensive.energy_required = + (recipe.expensive.energy_required or 0.5) + * mult + end + else + recipe.energy_required = + (recipe.energy_required or 0.5) + * mult + end +end + +get_recipe_category = function(recipe) + local recipe = recipe_or_bust(recipe) + if not recipe then return false end + if recipe.category then return recipe.category end + if recipe.expensive and recipe.expensive.category then + return recipe.expensive.category + end + if recipe.normal and recipe.normal.category then + return recipe.normal.category + end + return "crafting" +end + +get_recipe_energy = function(recipe) + local recipe = recipe_or_bust(recipe) + if not recipe then return nil,0,0 end + local normal_energy_required = 1 + local expensive_energy_required = 1 + if recipe.normal then + normal_energy_required = + recipe.normal.energy_required + if recipe.expensive then + expensive_energy_required = + recipe.expensive.energy_required + end + else + return (recipe.energy_required or 0.5) + end + return normal_energy_required,expensive_energy_required +end + +set_recipe_hidden = function(recipe) + recipe = table_or_bust(recipe) + if not recipe then return nil end + if recipe.normal + and type(recipe.normal) == "table" then + recipe.normal.hidden = true + end + if recipe.expensive + and type(recipe.expensive) == "table" then + recipe.expensive.hidden = true + end + recipe.hidden = true + return true +end + +mult_recipe_io = function(recipe,mult,name) + mult_in_recipe(recipe,mult,name) +end + +mult_in_recipe = function(recipe,mult,name) + if name then + replace_recipe_io(recipe,name,name,mult) + else + local ingredients,results = get_io_names(recipe) + for _,name in pairs(ingredients) do + replace_recipe_io(recipe,name,name,mult) + end + for _,name in pairs(results) do + replace_recipe_io(recipe,name,name,mult) + end + end +end + +replace_in_recipe_io = function(recipe,old_name,new_name,mult) + io_manip(recipe,old_name,new_name,mult) +end + +replace_recipe_io = function(recipe,old_name,new_name,mult) + replace_in_recipe(recipe,old_name,new_name,mult) +end + +replace_in_recipe = function(recipe,old_name,new_name,mult) + io_manip(recipe,old_name,new_name,mult) +end + +io_manip = function(io_handler,old_name,new_name,mult) + local io_handler = io_handler_or_bust(io_handler) + local old_name = string_name_or_bust(old_name) + local new_io_type = get_io_type(new_name) + local new_name = string_name_or_bust(new_name) + local new_normal = 0 + local new_expensive = 0 + local new_amount = 0 + if type(new_name) == "number" then + mult = new_name + new_name = old_name + end + if not io_handler or not old_name + or not new_name then return false end + if not new_io_type then new_io_type = "item" end + local mult = number_or_one(mult) + if io_handler.normal then + new_normal = io_manip( + io_handler.normal,old_name,new_name,mult + ) + end + if io_handler.expensive then + new_expensive = io_manip( + io_handler.expensive,old_name,new_name,mult + ) + end + if io_handler.result then + if io_handler.result == old_name then + if new_io_type == "item" then + io_handler.result = new_name + adamo.debug(io_handler.result..": "..(io_handler.result_count or 1)) + io_handler.result_count = + (io_handler.result_count or 1) + * mult + new_amount = io_handler.result_count + adamo.debug("Replaced as simple result. Count: "..new_amount) + else + if not io_handler.results then + io_handler.results = {} + end + table.insert( + io_handler.results, + { + name = new_name, + type = new_io_type, + amount = (io_handler.result_count or 1)*mult + } + ) + io_handler.main_product = new_name + new_amount = (io_handler.result_count or 1)*mult + io_handler.result = nil + io_handler.result_count = nil + adamo.debug("Moved result to results. Count: "..new_amount) + end + end + end + for _,ingredient in pairs(io_handler.ingredients or {}) do + if ingredient.name == old_name then + ingredient.name = new_name + ingredient.type = new_io_type + adamo.debug(ingredient.name..": "..ingredient.amount) + ingredient.amount = + (ingredient.amount or ingredient[2] or 1)*mult + ingredient[2] = nil + new_amount = ingredient.amount + adamo.debug("Replaced in table by name. Count: "..new_amount) + end + if ingredient[1] == old_name then + ingredient.name = new_name + ingredient.amount = + (ingredient[2] or ingredient.amount or 1)*mult + ingredient.type = new_io_type + ingredient[1] = nil + ingredient[2] = nil + new_amount = ingredient.amount + adamo.debug("Replaced in table by index. Count: "..new_amount) + end + if ingredient.name == nil + and ingredient[1] == nil then + ingredient = nil + end + end + for _,result in pairs(io_handler.results or {}) do + if result.name == old_name then + result.name = new_name + result.type = new_io_type + adamo.debug(result.name..": "..result.amount) + result.amount = math.floor( + (result.amount or result[2] or 1)*mult + ) + if new_io_type == "fluid" then + result.amount = + result.amount + *(result.probability or 1) + result.probability = nil + end + result[2] = nil + new_amount = result.amount + adamo.debug("Replaced in table by name. Count: "..new_amount) + end + if result[1] == old_name then + result.name = new_name + result.amount = math.floor( + (result[2] or result.amount or 1)*mult + ) + result.type = new_io_type + if new_io_type == "fluid" then + result.amount = + result.amount + *(result.probability or 1) + result.probability = nil + end + result[1] = nil + result[2] = nil + new_amount = result.amount + adamo.debug("Replaced in table by index. Count: "..new_amount) + end + if result.name == nil + and result[1] == nil then + result = nil + end + end + if io_handler.main_product == old_name then + adamo.debug("Replaced main product.") + io_handler.main_product = new_name + end + if io_handler.name then + adamo.debug( + 'Replaced '..(io_handler.name)..' IO: ' + ..old_name..' --> '..new_name..' ['..new_io_type..']' + .." x"..mult.." => {"..new_amount..", "..new_normal..", "..new_expensive.."}" + ) + end + return new_amount +end + +remove_ingredient = function(recipe,ingred_name) + local recipe = recipe_or_bust(recipe) + local ingred_name = + string_name_or_bust(ingred_name,count,prob) + local found_and_removed = false + if not recipe or not ingred_name + then return found_and_removed end + if recipe.expensive then + for _,ingredient + in pairs(recipe.expensive.ingredients or {}) + do + if ingredient.name == ingred_name + or ingredient[1] == ingred_name then + recipe.expensive.ingredients[_] = nil + found_and_removed = true + end + end + end + if recipe.normal then + for _,ingredient + in pairs(recipe.normal.ingredients or {}) + do + if ingredient.name == ingred_name + or ingredient[1] == ingred_name then + recipe.normal.ingredients[_] = nil + found_and_removed = true + end + end + end + for _,ingredient + in pairs(recipe.ingredients or {}) + do + if ingredient.name == ingred_name + or ingredient[1] == ingred_name then + recipe.ingredients[_] = nil + found_and_removed = true + end + end + return found_and_removed +end + +blend_io_if_match = function(io_base,io_counter) + local io_base = io_prototype_or_bust(io_base) + local io_counter = io_prototype_or_bust(io_counter) + if not io_counter or not io_base then return end + local found_match = false + if io_base.name == io_counter.name + and ( io_base.type == io_counter.type + or ( + io_base.type == "item" + or io_counter.type == "item" + ) + ) then + found_match = true + if io_base.probability or io_counter.probability then + io_base.probability = + ( + (io_base.probability or 1) + *io_base.amount + + + (io_counter.probability or 1) + *io_counter.amount + ) + /(io_base.amount + io_counter.amount) + if io_base.probability == 1 then + io_base.probability = nil + end + end + io_base.amount = io_base.amount + io_counter.amount + end + adamo.debug( + "Blended: " + ..tostring(io_base.name).."[" + ..tostring(io_base.amount)..", " + ..tostring(io_base.probability).."] <-> [" + ..tostring(io_counter.name).."[" + ..tostring(io_counter.amount)..", " + ..tostring(io_counter.probability).."]" + ) + return found_match +end + +add_ingredient = function(recipe,ingred,count,prob,catalyst_amount) + if type(count) == "number" and count == 0 then + return nil + end + if type(prob) == "number" and count == 0 then + return nil + end + local recipe = recipe_or_bust(recipe) + local ingred = io_prototype_or_bust(ingred,count,prob,catalyst_amount) + if type(prob) ~= "number" then prob = nil end + if not recipe or not ingred then return nil end + if uses_ingredient(recipe,ingred.name) then + if recipe.expensive then + for _,ingredient + in pairs(recipe.expensive.ingredients or {}) + do + blend_io_if_match(ingredient,ingred) + end + end + if recipe.normal then + for _,ingredient + in pairs(recipe.normal.ingredients or {}) + do + blend_io_if_match(ingredient,ingred) + end + end + for _,ingredient + in pairs(recipe.ingredients or {}) + do + blend_io_if_match(ingredient,ingred) + end + else + if recipe.expensive then + local exp_ingred = util.table.deepcopy(ingred) + if not recipe.expensive.ingredients then + recipe.expensive.ingredients = {} + end + table.insert(recipe.expensive.ingredients,exp_ingred) + end + if recipe.normal then + if not recipe.normal.ingredients then + recipe.normal.ingredients = {} + end + table.insert(recipe.normal.ingredients,ingred) + end + if recipe.ingredients then + table.insert(recipe.ingredients,ingred) + elseif not recipe.normal and not recipe.expensive + then + recipe.ingredients = {} + table.insert(recipe.ingredients,ingred) + end + end +end + +add_result = function(recipe,product,count,prob) + if type(count) == "number" and count == 0 then + return nil + end + if type(prob) == "number" and count == 0 then + return nil + end + local recipe = recipe_or_bust(recipe) + local product = io_prototype_or_bust(product,count,prob) + if not recipe or not product then return nil end + if type(count) ~= "number" then count = nil end + if type(prob) ~= "number" then prob = nil end + format_results(recipe) + if uses_result(recipe,product) then + if recipe.expensive then + for _,result + in pairs(recipe.expensive.results + or {recipe.expensive.result} + ) do + blend_io_if_match(result,product) + end + end + if recipe.normal then + for _,result + in pairs(recipe.normal.results + or {recipe.normal.result} + ) do + blend_io_if_match(result,product) + end + end + for _,result + in pairs(recipe.results + or {recipe.result} + ) do + blend_io_if_match(result,product) + end + else + if recipe.expensive then + local exp_product = util.table.deepcopy(product) + exp_product.amount = (exp_product.amount or 1)*2 + table.insert(recipe.expensive.results,exp_product) + end + if recipe.normal then + table.insert(recipe.normal.results,product) + end + if recipe.results then + table.insert(recipe.results,product) + elseif not recipe.normal and not recipe.expensive + then + recipe.results = {} + table.insert(recipe.results,product) + end + end +end + +move_result_to_main_product = function(recipe) + local recipe = recipe_or_bust(recipe) + if not recipe then return false end + if recipe.expensive then + if not recipe.expensive.results + or type(recipe.expensive.results) ~= "table" + then + if recipe.expensive.result then + recipe.expensive.results = {{ + type = "item", + name = recipe.expensive.result, + amount = + recipe.expensive.result_count + or 1 + }} + if not recipe.expensive.main_product then + recipe.expensive.main_product = + recipe.expensive.result + end + recipe.expensive.result = nil + recipe.expensive.result_count = nil + end + elseif recipe.expensive.result then + if not recipe.expensive.main_product then + recipe.expensive.main_product = + recipe.expensive.result + end + table.insert( + results, + { + type = "item", + name = recipe.expensive.result, + amount = + (recipe.expensive.result_count + or 1) + } + ) + recipe.expensive.result = nil + recipe.expensive.result_count = nil + end + end + if recipe.normal then + if not recipe.normal.results + or type(recipe.normal.results) ~= "table" + then + if recipe.normal.result then + recipe.normal.results = {{ + type = "item", + name = recipe.normal.result, + amount = + recipe.normal.result_count + or 1 + }} + if not recipe.normal.main_product then + recipe.normal.main_product = + recipe.normal.result + end + recipe.normal.result = nil + recipe.normal.result_count = nil + end + elseif recipe.normal.result then + if not recipe.normal.main_product then + recipe.normal.main_product = + recipe.normal.result + end + table.insert( + results, + { + type = "item", + name = recipe.normal.result, + amount = + (recipe.normal.result_count + or 1) + } + ) + recipe.normal.result = nil + recipe.normal.result_count = nil + end + end + if not recipe.results + or type(recipe.results) ~= "table" + then + if recipe.result then + recipe.results = {{ + type = "item", + name = recipe.result, + amount = + recipe.result_count + or 1 + }} + if not recipe.main_product then + recipe.main_product = + recipe.result + end + recipe.result = nil + recipe.result_count = nil + end + elseif recipe.result then + if not recipe.main_product then + recipe.main_product = + recipe.result + end + table.insert( + results, + { + type = "item", + name = recipe.result, + amount = + (recipe.result_count + or 1) + } + ) + recipe.result = nil + recipe.result_count = nil + end +end + +format_results = function(recipe) + local recipe = recipe_or_bust(recipe) + if not recipe then return false end + move_result_to_main_product(recipe) + -- needs to reformat the results table, yet. +end + +format_ingredients = function(recipe) + local recipe = recipe_or_bust(recipe) + if not recipe then return false end + if recipe.normal + and type(recipe.normal) == "table" then + for _,ingredient + in pairs(recipe.normal.ingredients or {}) do + if ingredient[1] then + ingredient.name = ingredient[1] + ingredient[1] = nil + end + if ingredient[2] then + ingredient.amount = ingredient[2] + ingredient[2] = nil + end + if ingredient.name + and not ingredient.type then + ingredient.type = "item" + end + end + end + if recipe.expensive + and type(recipe.expensive) == "table" then + for _,ingredient + in pairs(recipe.expensive.ingredients or {}) do + if ingredient[1] then + ingredient.name = ingredient[1] + ingredient[1] = nil + end + if ingredient[2] then + ingredient.amount = ingredient[2] + ingredient[2] = nil + end + if ingredient.name + and not ingredient.type then + ingredient.type = "item" + end + end + end + for _,ingredient + in pairs(recipe.ingredients or {}) do + if ingredient[1] then + ingredient.name = ingredient[1] + ingredient[1] = nil + end + if ingredient[2] then + ingredient.amount = ingredient[2] + ingredient[2] = nil + end + if ingredient.name + and not ingredient.type then + ingredient.type = "item" + end + end + return true +end + +set_main_product = function(recipe,name) + local recipe = recipe_or_bust(recipe) + local name = string_name_or_bust(name) + if not recipe or not name then return false end + if not uses_result(recipe,name) then return false end + if recipe.normal then + recipe.normal.main_product = name + end + if recipe.expensive then + recipe.expensive.main_product = name + end + if recipe.results or recipe.result then + recipe.main_product = name + end +end + +get_main_result = function(recipe) + local recipe = recipe_or_bust(recipe) + if not recipe then return nil,0,0,0 end + local result_name = nil + local result_count = nil + local expensive_result_count = 0 + local normal_result_count = 0 + if recipe.expensive then + if recipe.expensive.results then + for _,result + in pairs(recipe.expensive.results) do + if result_name == nil then + result_name = result.name or result[1] + end + if (result.name == result_name) + or (result[1] == result_name) then + expensive_result_count = + result.amount + or result[2] + end + end + elseif recipe.expensive.result then + if result_name == nil then + result_name = recipe.expensive.result + end + expensive_result_count = + recipe.expensive.result_count or 1 + end + end + if recipe.normal then + if recipe.normal.results then + for _,result + in pairs(recipe.normal.results) do + if result_name == nil then + result_name = result.name or result[1] + end + if (result.name == result_name) + or (result[1] == result_name) then + normal_result_count = + result.amount + or result[2] + end + end + elseif recipe.normal.result then + if result_name == nil then + result_name = recipe.normal.result + end + normal_result_count = + recipe.normal.result_count or 1 + end + end + if recipe.results then + for _,result + in pairs(recipe.results) do + if result_name == nil then + result_name = result.name or result[1] + end + if (result.name == result_name) + or (result[1] == result_name) then + result_count = + result.amount + or result[2] + end + end + elseif recipe.result then + result_count = recipe.result_count or 1 + result_name = recipe.result + end + if result_count == nil then + result_count = + normal_result_count + or expensive_result_count + or 0 + end + return result_name,result_count,expensive_result_count +end + +has_ingredients = function(recipe) + local recipe = recipe_or_bust(recipe) + if recipe then + if recipe.normal then + if recipe.normal.ingredients then + for _,ingredient + in pairs(recipe.normal.ingredients) do + if ingredient.amount + and ingredient.amount > 0 then + return true + end + if ingredient[2] + and ingredient[2] > 0 then + return true + end + end + end + end + if recipe.ingredients then + for _,ingredient in pairs(recipe.ingredients) do + if ingredient.amount + and ingredient.amount > 0 then + return true + end + if ingredient[2] + and ingredient[2] > 0 then + return true + end + end + end + end + return false +end + +has_results = function(recipe) + local recipe = recipe_or_bust(recipe) + if not recipe then return false end + if recipe.expensive then + if recipe.expensive.results then + for _,result + in pairs(recipe.expensive.results) do + if result.amount + and result.amount > 0 then + return true + end + if result[2] + and result[2] > 0 then + return true + end + end + end + if recipe.normal.result then return true end + end + if recipe.normal then + if recipe.normal.results then + for _,result + in pairs(recipe.normal.results) do + if result.amount + and result.amount > 0 then + return true + end + if result[2] + and result[2] > 0 then + return true + end + end + end + if recipe.normal.result then return true end + end + if recipe.results then + for _,result in pairs(recipe.results) do + if result.amount + and result.amount > 0 then + return true + end + if result[2] + and result[2] > 0 then + return true + end + end + end + if recipe.result then return true end + return false +end + +get_io_names = function(recipe) + local recipe = recipe_or_bust(recipe) + if not recipe or recipe.type ~= "recipe" then + return {} + end + local ingredients = {} + local results = {} + if recipe.expensive then + add_strings_to_list( + ingredients, + get_table_names(recipe.expensive.ingredients) + ) + add_strings_to_list( + results, + get_table_names(recipe.expensive.results) + ) + add_string_to_list( + results, + recipe.expensive.result + ) + end + if recipe.normal then + add_strings_to_list( + ingredients, + get_table_names(recipe.normal.ingredients) + ) + add_strings_to_list( + results, + get_table_names(recipe.normal.results) + ) + add_string_to_list( + results, + recipe.normal.result + ) + end + add_strings_to_list( + ingredients, + get_table_names(recipe.ingredients) + ) + add_strings_to_list( + results, + get_table_names(recipe.results) + ) + add_string_to_list( + results, + recipe.result + ) + return ingredients,results +end + +recipe_uses = function(recipe,name) + local name = string_name_or_bust(name) + local recipe = recipe_or_bust(recipe) + if not recipe or not name then return false end + local ingredients,results = get_io_names(recipe) + for _,ingredient_name in pairs(ingredients) do + if ingredient_name == name then + return true + end + end + for _,result_name in pairs(results) do + if (result_name) == name then + return true + end + end + return false +end + +uses_ingredient = function(recipe,name) + local name = string_name_or_bust(name) + local recipe = recipe_or_bust(recipe) + if not recipe or not name then return false end + local ingredients,results = get_io_names(recipe) + for _,ingredient_name in pairs(ingredients) do + if ingredient_name == name then + return true + end + end + return false +end + +uses_result = function(recipe,name) + local name = string_name_or_bust(name) + local recipe = recipe_or_bust(recipe) + if not recipe or not name then return false end + local ingredients,results = get_io_names(recipe) + for _,result_name in pairs(results) do + if (result_name) == name then + return true + end + end + return false +end + +get_io_type = function(prototype) + if type(prototype) == "table" then + local io_type = get_table_type(prototype) + if io_type == "item" then + return "item" + elseif io_type == "fluid" then + return "fluid" + end + end + if type(prototype) == "string" then + if data.raw.item[prototype] then + return "item" + elseif data.raw.fluid[prototype] then + return "fluid" + end + end + return nil +end + +get_table_type = function(prototype) + if type(prototype) == "table" then + return prototype.type + end + return nil +end + +get_table_names = function(prototable) + local names = {} + local prototable = table_or_bust(prototable) + if not prototable then return end + for _,prototype in pairs(prototable) do + prototype = table_or_bust(prototype) + if prototype then + if prototype.name + and type(prototype.name) == "string" then + table.insert( + names, + prototype.name + ) + elseif prototype[1] + and type(prototype[1]) == "string" then + table.insert( + names, + prototype[1] + ) + end + end + end + return names +end + +get_ingredient = function(recipe,index) + local recipe = recipe_or_bust(recipe) + if type(recipe) ~= "table" then return end + local ingredient_name = index + local ingredient_amount = 0 + local expensive_amount = 0 + if not has_ingredients(recipe) then return nil,0,0 end + if recipe.normal + and type(recipe.normal.ingredients) == "table" then + if type(ingredient_name) == "string" then + for _,ingredient + in pairs(recipe.normal.ingredients) do + if (ingredient.name == ingredient_name) + or (ingredient[1] == ingredient_name) + then + ingredient_amount = + ingredient.amount + or ingredient[2] + end + end + if ingredient_amount == 0 then + return nil,0,0 + end + if recipe.expensive then + for _,ingredient + in pairs(recipe.expensive.ingredients or {}) do + if (ingredient.name == ingredient_name) + or (ingredient[1] == ingredient_name) + then + expensive_amount = + ingredient.amount + or ingredient[2] + end + end + end + else + if type( + recipe.normal.ingredients[ingredient_name] + ) == "table" then + ingredient_amount = + recipe.normal + .ingredients[ingredient_name].amount + or recipe.normal + .ingredients[ingredient_name][2] + ingredient_name = + recipe.normal + .ingredients[ingredient_name].name + or recipe.normal + .ingredients[ingredient_name][1] + if recipe.expensive then + for _,ingredient + in pairs(recipe.expensive.ingredients) do + if ( + ingredient.name + == ingredient_name + ) or ( + ingredient[1] + == ingredient_name + ) then + expensive_amount = + ingredient.amount + or ingredient[2] + end + end + end + else + return nil,0,0 + end + end + else + if type(ingredient_name) == "string" then + for _,ingredient + in pairs(recipe.ingredients or {}) do + if (ingredient.name == ingredient_name) + or (ingredient[1] == ingredient_name) + then + ingredient_amount = + ingredient.amount + or ingredient[2] + end + end + if ingredient_amount == 0 then + return nil,0,0 + end + else + if type(recipe.ingredients[ingredient_name]) + == "table" then + ingredient_amount = + recipe.ingredients[ingredient_name] + .amount + or recipe.ingredients[ingredient_name][2] + ingredient_name = + recipe.ingredients[ingredient_name].name + or recipe.ingredients[ingredient_name][1] + else + return nil,0,0 + end + end + end + return ingredient_name,ingredient_amount,expensive_amount +end + +-- Might be broken +get_result = function(recipe,index) + local recipe = recipe_or_bust(recipe) + if not recipe then return end + format_results(recipe) + if not has_results(recipe) then return nil,0,0 end + local result_name = index + local result_amount = 0 + local expensive_amount = 0 + if recipe.normal + and type(recipe.normal.results) == "table" then + if type(result_name) == "string" then + for _,result in pairs(recipe.normal.results) do + if (result.name == result_name) + or (result[1] == result_name) + then + result_amount = + result.amount or result[2] + end + end + if result_amount == 0 then + return nil,0,0 + end + if recipe.expensive then + for _,result + in pairs(recipe.expensive.results or {}) do + if (result.name == result_name) + or (result[1] == result_name) + then + expensive_amount = + result.amount + or result[2] + end + end + end + else + if type( + recipe.normal.results[result_name] + ) == "table" then + result_amount = + recipe.normal + .results[result_name].amount + or recipe.normal + .results[result_name][2] + result_name = + recipe.normal + .results[result_name].name + or recipe.normal + .results[result_name][1] + if recipe.expensive then + for _,result + in pairs(recipe.expensive.results) do + if ( + result.name + == result_name + ) or ( + result[1] + == result_name + ) then + expensive_amount = + result.amount + or result[2] + end + end + end + else + return nil,0,0 + end + end + else + if type(result_name) == "string" then + for _,result + in pairs(recipe.results or {}) do + if (result.name == result_name) + or (result[1] == result_name) + then + result_amount = + result.amount + or result[2] + end + end + if result_amount == 0 then + return nil,0,0 + end + else + if type(recipe.results[result_name]) + == "table" then + result_amount = + recipe.results[result_name] + .amount + or recipe.results[result_name][2] + result_name = + recipe.results[result_name].name + or recipe.results[result_name][1] + else + return nil,0,0 + end + end + end + return result_name,result_amount,expensive_amount + +end + +set_productivity_recipe = function(recipe_name) + local recipe_name = string_name_or_bust(recipe_name) + if not recipe_name then return end + for k,v in pairs({ + data.raw.module["productivity-module"], + data.raw.module["productivity-module-2"], + data.raw.module["productivity-module-3"] + }) do + if v.limitation then + table.insert(v.limitation, recipe_name) + end + end +end + +set_productivity_recipes = function(recipe_names) + for _,recipe_name in pairs(recipe_names or {}) do + set_productivity_recipe(recipe_name) + end +end + +add_productivity_recipe = function(recipe_name) + set_productivity_recipe(recipe_name) +end + +add_productivity_recipes = function(recipe_names) + set_productivity_recipes(recipe_names) +end + +is_productivity_recipe = function(recipe_name) + local recipe_name = string_name_or_bust(recipe_name) + if not data.raw.recipe[recipe_name] then return false end + for k,listed_recipe_name in pairs( + data.raw.module["productivity-module"].limitation + ) do + if listed_recipe_name == recipe_name then + return true + end + end + return false +end + +find_unused_layer = function() + local unused_layers = { + "layer-11", + "layer-12", + "layer-13", + "layer-14", + "layer-15", + } + for i,data_type in pairs(data.raw) do + for j,data_obj in pairs(data_type) do + for k,layer + in pairs(data_obj.collision_mask or {}) do + for l,unused_layer in pairs(unused_layers) do + if layer == unused_layer then + unused_layers[l] = nil + end + end + end + end + end + for _,layer in pairs(unused_layers) do + return layer + end + return nil +end + +-- Not really checking if it's an entit, +-- but entity definitely has to have "order". +entity_or_bust = function(entity) + local entity = table_or_bust(entity) + return entity +end + +get_collision_lengths = function(entity) + local lengths = {0,0} + if entity_or_bust(entity) then + local colbox = entity.collision_box + if type(colbox) == "table" then + if type(colbox[1]) == "table" then + if type(colbox[1][1]) == "number" then + lengths[1] + = lengths[1] - colbox[1][1] + end + if type(colbox[1][2]) == "number" then + lengths[2] + = lengths[2] - colbox[1][2] + end + end + if type(colbox[2]) == "table" then + if type(colbox[2][1]) == "number" then + lengths[1] + = lengths[1] + colbox[2][1] + end + if type(colbox[2][2]) == "number" then + lengths[2] + = lengths[2] + colbox[2][2] + end + end + end + end + return lengths +end + +get_collision_hypotenuse = function(entity) + local len = get_collision_lengths(entity) + return math.sqrt(len[1]*len[1] + len[2]*len[2]) +end + +get_collision_area = function(entity) + local len = get_collision_lengths(entity) + return len[1]*len[2] +end + +set_pipe_distance = function(pipe, dist) + if data.raw["pipe-to-ground"][pipe] then + for _,connection in pairs( + data.raw["pipe-to-ground"][pipe] + .fluid_box.pipe_connections + ) do + if connection.max_underground_distance then + data.raw["pipe-to-ground"][pipe] + .fluid_box.pipe_connections[_] + .max_underground_distance = dist + end + end + end +end + +set_shift = function(shift, tab) + tab.shift = shift + if tab.hr_version then + tab.hr_version.shift = shift + end + return tab +end + +-- probably doesn't work as written: could work +-- with sufficiently large empty image. +empty_animation = function(frames,speed) + if type(frames) ~= "number" then + frames = 1 + end + if type(speed) ~= "number" then + speed = 1 + end + return { + frame_count = frames, + speed = speed, + type = "forward-then-backward", + filename = "__core__/graphics/empty.png", + priority = "extra-high", + line_length = 1/math.sqrt(frames), + width = 1, + height = 1 + } +end + +empty_sprite = function() + return { + filename = "__core__/graphics/empty.png", + priority = "extra-high", + width = 1, + height = 1, + hr_version = { + filename = "__core__/graphics/empty.png", + priority = "extra-high", + width = 1, + height = 1, + } + } +end + +emptysprite = function() + return empty_sprite() +end + +centrifuge_idle_layers = function(size,speed) + local size = number_or_one(size) + local speed = number_or_one(speed) + return {{ + filename = + "__base__/graphics/entity/" + .."centrifuge/centrifuge-C.png", + priority = "extra-high", + line_length = 8, + width = 119, + height = 107, + scale = size, + frame_count = 64, + animation_speed = speed, + shift = + util.by_pixel( + -0.5, + -26.5 + ), + hr_version = { + filename = + "__base__/graphics/entity/" + .."centrifuge/hr-centrifuge-C.png", + priority = "extra-high", + scale = size*0.5, + line_length = 8, + width = 237, + height = 214, + frame_count = 64, + animation_speed = speed, + shift = + util.by_pixel( + -0.25, + -26.5 + ) + } + },{ + filename = + "__base__/graphics/entity/" + .."centrifuge/centrifuge-C-shadow.png", + draw_as_shadow = true, + priority = "extra-high", + line_length = 8, + width = 132, + height = 74, + frame_count = 64, + scale = size, + animation_speed = speed, + shift = + util.by_pixel( + 20, + -10 + ), + hr_version = { + filename = + "__base__/graphics/entity/" + .."centrifuge/hr-centrifuge-C-shadow.png", + draw_as_shadow = true, + priority = "extra-high", + scale = size*0.5, + line_length = 8, + width = 279, + height = 152, + frame_count = 64, + animation_speed = speed, + shift = + util.by_pixel( + 16.75, + -10 + ) + } + },{ + filename = + "__base__/graphics/entity/" + .."centrifuge/centrifuge-B.png", + priority = "extra-high", + line_length = 8, + width = 78, + height = 117, + scale = size, + frame_count = 64, + animation_speed = speed, + shift = + util.by_pixel( + 23, + 6.5 + ), + hr_version = { + filename = + "__base__/graphics/entity/" + .."centrifuge/hr-centrifuge-B.png", + priority = "extra-high", + scale = size*0.5, + line_length = 8, + width = 156, + height = 234, + frame_count = 64, + animation_speed = speed, + shift = + util.by_pixel( + 23, + 6.5 + ) + } + },{ + filename = + "__base__/graphics/entity/" + .."centrifuge/centrifuge-B-shadow.png", + draw_as_shadow = true, + priority = "extra-high", + line_length = 8, + width = 124, + height = 74, + frame_count = 64, + scale = size, + animation_speed = speed, + shift = + util.by_pixel( + 63, + 16 + ), + hr_version = { + filename = + "__base__/graphics/entity/" + .."centrifuge/hr-centrifuge-B-shadow.png", + draw_as_shadow = true, + priority = "extra-high", + scale = size*0.5, + line_length = 8, + width = 251, + height = 149, + frame_count = 64, + animation_speed = speed, + shift = + util.by_pixel( + 63.25, + 15.25 + ) + } + },{ + filename = + "__base__/graphics/entity/" + .."centrifuge/centrifuge-A.png", + priority = "extra-high", + line_length = 8, + width = 70, + height = 123, + scale = size, + frame_count = 64, + animation_speed = speed, + shift = + util.by_pixel( + -26, + 3.5 + ), + hr_version = { + filename = + "__base__/graphics/entity/" + .."centrifuge/hr-centrifuge-A.png", + priority = "extra-high", + scale = size*0.5, + line_length = 8, + width = 139, + height = 246, + frame_count = 64, + animation_speed = speed, + shift = + util.by_pixel( + -26.25, + 3.5 + ) + } + },{ + filename = + "__base__/graphics/entity/" + .."centrifuge/centrifuge-A-shadow.png", + priority = "extra-high", + draw_as_shadow = true, + line_length = 8, + width = 108, + height = 54, + frame_count = 64, + scale = size, + animation_speed = speed, + shift = + util.by_pixel( + 6, + 27 + ), + hr_version = { + filename = + "__base__/graphics/entity/" + .."centrifuge/hr-centrifuge-A-shadow.png", + priority = "extra-high", + draw_as_shadow = true, + scale = size*0.5, + line_length = 8, + width = 230, + height = 124, + frame_count = 64, + animation_speed = speed, + shift = + util.by_pixel( + 8.5, + 23.5 + ) + } + }} +end + +bulkypipepictures = function() + local pipe_sprites = pipepictures() + return { + north = set_shift( + {0, 1}, + util.table + .deepcopy(pipe_sprites.straight_vertical) + ), + south = empty_sprite(), + east = set_shift( + {-1, 0}, + util.table + .deepcopy(pipe_sprites.straight_horizontal) + ), + west = set_shift( + {1, 0}, + util.table + .deepcopy(pipe_sprites.straight_horizontal) + ) + } +end + +chem_assembling_machine_fluid_boxes = function() + return {{ + production_type = "input", + pipe_picture = assembler3pipepictures(), + pipe_covers = pipecoverspictures(), + base_area = 1, + base_level = -1, + height = 2, + pipe_connections = {{ type="input-output", position = {0, -2} }}, + secondary_draw_orders = { north = -1 } + },{ + production_type = "input", + pipe_picture = assembler3pipepictures(), + pipe_covers = pipecoverspictures(), + base_area = 1, + base_level = -1, + height = 2, + pipe_connections = {{ type="input-output", position = {2, 0} }}, + secondary_draw_orders = { north = -1 } + },{ + production_type = "output", + pipe_picture = assembler3pipepictures(), + pipe_covers = pipecoverspictures(), + base_area = 1, + base_level = 1, + pipe_connections = {{ type="output", position = {-2, 0} }}, + secondary_draw_orders = { north = -1 } + },{ + production_type = "input", + pipe_picture = assembler3pipepictures(), + pipe_covers = pipecoverspictures(), + base_area = 1, + base_level = -1, + height = 2, + pipe_connections = {{ type="input-output", position = {0, 2} }}, + secondary_draw_orders = { north = -1 } + }, + off_when_no_fluid_recipe = true + } +end + +centrifuge_fluid_boxes = function() + return {{ + production_type = "input", + base_area = 1, + base_level = -1, + pipe_picture = assembler3pipepictures(), + pipe_covers = pipecoverspictures(), + pipe_connections = {{ + position = { + 0, + 2 + }, + }}, + secondary_draw_orders = { + north = -32, + west = -32, + east = -32, + south = 4 + } + },{ + production_type = "output", + base_area = 1, + base_level = 1, + pipe_picture = assembler3pipepictures(), + pipe_covers = pipecoverspictures(), + pipe_connections = {{ + position = { + -2, + 0 + }, + }}, + secondary_draw_orders = { + north = -32, + west = -32, + east = -32, + south = 4 + } + },{ + production_type = "output", + base_area = 1, + base_level = 1, + pipe_picture = assembler3pipepictures(), + pipe_covers = pipecoverspictures(), + pipe_connections = {{ + position = { + 0, + -2 + }, + }}, + secondary_draw_orders = { + north = -32, + west = -32, + east = -32, + south = 4 + } + },{ + production_type = "output", + base_area = 1, + base_level = 1, + pipe_picture = assembler3pipepictures(), + pipe_covers = pipecoverspictures(), + pipe_connections = {{ + position = { + 2, + 0 + }, + }}, + secondary_draw_orders = { + north = -32, + west = -32, + east = -32, + south = 4 + }, + }, + off_when_no_fluid_recipe = true + } +end + +trivial_smoke = function(opts) + return { + type = "trivial-smoke", + name = opts.name, + duration = opts.duration or 600, + fade_in_duration = opts.fade_in_duration or 0, + fade_away_duration = + opts.fade_away_duration + or ( + (opts.duration or 600) - (opts.fade_in_duration or 0) + ), + spread_duration = opts.spread_duration or 600, + start_scale = opts.start_scale or 0.20, + end_scale = opts.end_scale or 1.0, + color = opts.color, + cyclic = true, + affected_by_wind = opts.affected_by_wind or true, + animation = { + width = 152, + height = 120, + line_length = 5, + frame_count = 60, + shift = {-0.53125, -0.4375}, + priority = "high", + animation_speed = 0.25, + filename = "__base__/graphics/entity/smoke/smoke.png", + flags = { "smoke" } + } + } +end + + +apply_vanilla_fluid_fuel_stats = function() + local solid_fuel = + item_or_bust(data.raw.item["solid-fuel"]) + if not solid_fuel then return false end + local solid_fuel_value = get_fuel_value(solid_fuel) + apply_fluid_fuel_stat( + "light-oil", + energy_div( + solid_fuel_value, + fuelfactors["light-oil"] + ) + ) + apply_fluid_fuel_stat( + "heavy-oil", + energy_div( + solid_fuel_value, + fuelfactors["heavy-oil"] + ) + ) + apply_fluid_fuel_stat( + "petroleum-gas", + energy_div( + solid_fuel_value, + fuelfactors["petroleum-gas"] + ) + ) + apply_fluid_fuel_stat( + "crude-oil", + energy_div( + solid_fuel_value, + fuelfactors["crude-oil"] + ) + ) +end + +apply_fluid_fuel_stat = function(fluid,fuel_value,fuel_type) + local fluid = fluid_or_bust(fluid) + local fuel_value = string_or_bust(fuel_value) + if not fluid or not fuel_value then return nil end + local fuel_type = string_or_bust(fuel_type) + fluid.fuel_category = fuel_type + fluid.fuel_value = fuel_value + return fluid +end + +apply_sulfur_fuel_stats = function(sulfur) + if type(sulfur) ~= "table" + or sulfur.type ~= "item" + then + log("invalid sulfur item received") + return nil + end + local sulfur_fueltype = "sulfur" + sulfur.fuel_category = sulfur_fueltype + sulfur.fuel_emissions_multiplier = 12 + sulfur.fuel_value = fuelvalues.sulfur + sulfur.fuel_acceleration_multiplier = 0.4 + sulfur.fuel_glow_color = {r = 1, g = 0.2, b = 1} + add_fueltype_to_basic_burners(sulfur_fueltype) + return sulfur +end + +add_fueltype_to_basic_burners = function(fueltype) + if not data.raw["fuel-category"][fueltype] then + data:extend({ + {type="fuel-category",name=fueltype} + }) + end + add_fuel_type(data.raw.boiler.boiler,fueltype) + for _,ent in pairs(data.raw.car) do + if table_incl("chemical",get_fuel_types(ent)) + then + add_fuel_type(ent,fueltype) + end + end + add_fuel_type(data.raw.furnace["stone-furnace"],fueltype) + add_fuel_type(data.raw.furnace["steel-furnace"],fueltype) + for _,ent in pairs(data.raw.reactor) do + if table_incl("chemical",get_fuel_types(ent)) + then + add_fuel_type(ent,fueltype) + end + end + for _,ent in pairs(data.raw.lamp) do + if table_incl("chemical",get_fuel_types(ent)) + then + add_fuel_type(ent,fueltype) + end + end +end + +add_fuel_type = function(entity,fuel_type) + entity = table_or_bust(entity) + fuel_type = string_or_bust(fuel_type) + if not entity or not fuel_type then return false end + local energy_source = get_energy_source(entity) + if not energy_source then return false end + if is_burner(energy_source) then + if not energy_source.fuel_categories then + if energy_source.fuel_category then + energy_source + .fuel_categories = {energy_source.fuel_category} + else + energy_source.fuel_categories = {"chemical"} + end + energy_source.fuel_category = nil + end + add_string_to_list( + energy_source.fuel_categories, + fuel_type + ) + end +end + +get_fuel_value = function(prototype) + local prototype = table_or_bust(prototype) + local fuel_value = "0kW" + if not prototype then return fuel_value end + if prototype.type == "fluid" + or prototype.type == "item" then + fuel_value = prototype.fuel_value + end + if type(fuel_value) ~= "string" then return "0kW" end + return fuel_value +end + +get_fuel_types = function(entity) + entity = table_or_bust(entity) + if not entity then return {} end + local energy_source = get_energy_source(entity) + if not energy_source then return {} end + if is_burner(energy_source) then + if energy_source.fuel_categories then + return energy_source.fuel_categories + end + if energy_source.fuel_category then + return {energy_source.fuel_category} + end + return ({"chemical"}) + end + return {} +end + +uses_fuel_type = function(name,entity) + local name = string_name_or_bust(name) + local entity = table_or_bust(entity) + if entity and name + and table_incl(name,get_fuel_types(entity)) then + return true + end + return false +end + +is_burner = function(energy_source) + energy_source = table_or_bust(energy_source) + if not energy_source then return false end + if energy_source.type == "burner" + or not energy_source.type then + return true + end + return false +end + +get_energy_source = function(entity) + entity = entity_or_bust(entity) + if not entity then return nil end + if entity.burner then + return entity.burner + else + return entity.energy_source + end +end + +number_or_bust = function(number) + if type(number) ~= "number" then + return nil + end + return number +end + +number_or_one = function(number) + if type(number) ~= "number" then + number = 1 + end + return number +end + +number_or_zero = function(number) + if type(number) ~= "number" then + number = 0 + end + return number +end + +table_or_bust = function(prototype) + if type(prototype) == "table" then + return prototype + end + return nil +end + +string_or_bust = function(str) + if type(str) == "string" then + return str + end + return nil +end + +fluid_or_bust = function(prototype) + if type(prototype) == "table" + and prototype.type == "fluid" then + return prototype + end + if type(prototype) == "string" then + return fluid_or_bust(data.raw.fluid[prototype]) + end + return nil +end + +item_or_bust = function(prototype) + if type(prototype) == "table" then + for _,type in pairs(adamo.item.types) do + if prototype.type == type then + return prototype + end + end + end + if type(prototype) == "string" then + local item = adamo.get.from_types(adamo.item.types,prototype) + if item then return item end + end + return nil +end + +all_prototypes_with_value = function(type_tbl,key,val) + local type_tbl = prototype_table_or_bust(type_tbl) + if not type_tbl then return {} end + local prototypes = {} + for _,prototype in pairs(type_tbl) do + if prototype and type(prototype) == "table" + and prototype[key] == val then + table.insert(prototypes,prototype) + end + end + return prototypes +end + +prototype_table_or_bust = function(prototype_tbl) + if type(prototype_tbl) == "string" then + return data.raw[prototype_tbl] + else + return table_or_bust(prototype_tbl) + end +end + +io_prototype_or_bust = function(prototype,count,prob,catalyst_amount) + if type(prototype) == "table" then + if type(prototype.name) == "string" + and type(prototype.type) == "string" + and type(prototype.amount) == "number" then + return prototype + end + end + local new_prototype = construct_io_prototype( + prototype,count,prob,catalyst_amount + ) + if type(new_prototype.name) == "string" + and type(new_prototype.type) == "string" + and type(new_prototype.amount) == "number" then + prototype = new_prototype + return prototype + end + return nil +end + +construct_io_prototype = function( + prototype,count,prob,catalyst_amount +) + local new_prototype = {} + if type(prob) == "number" then + if prob < 0 or prob > 1 then prob = nil end + end + if type(count) == "number" then + if count < 0 then count = nil + elseif count < 1 then + prob = (prob or 1)*count + count = 1 + end + end + if type(count) ~= "number" then count = nil end + if type(prob) ~= "number" then prob = nil end + if type(prototype) == "table" then + new_prototype.name = prototype.name or prototype[1] + new_prototype.type = prototype.type or "item" + new_prototype.amount = + count or prototype.amount + or prototype[2] or 1 + new_prototype.catalyst_amount = + catalyst_amount + or prototype.catalyst_amount + new_prototype.probability = + prob or prototype.probability + end + if type(prototype) == "string" then + if data.raw.fluid[prototype] then + new_prototype.name = prototype + new_prototype.type = "fluid" + new_prototype.amount = count or 1 + if data.raw.item[prototype] then + new_prototype.type = "item" + new_prototype.catalyst_amount = + catalyst_amount + or prototype.catalyst_amount + new_prototype.probability = prob + end + else + new_prototype.name = prototype + new_prototype.type = "item" + new_prototype.amount = count or 1 + new_prototype.catalyst_amount = + catalyst_amount + or prototype.catalyst_amount + new_prototype.probability = prob + end + end + if new_prototype.type == "item" then + if new_prototype.amount < 0 then + elseif new_prototype.amount < 1 then + new_prototype.probability = + (new_prototype.probability or 1) + *new_prototype.amount + new_prototype.amount = 1 + end + elseif new_prototype.type == "fluid" and prob then + new_prototype.amount = new_prototype.amount*prob + end + adamo.debug( + "Constructed IO Prototype: " + ..new_prototype.name..": "..new_prototype.amount + ) + return new_prototype +end + +tech_or_bust = function(prototype) + if type(prototype) == "table" + and prototype.type == "technology" then + return prototype + end + if type(prototype) == "string" then + return data.raw.technology[prototype] + end + return nil +end + +recipe_or_bust = function(prototype) + if type(prototype) == "table" + and prototype.type == "recipe" then + return prototype + end + if type(prototype) == "string" then + return data.raw.recipe[prototype] + end + return nil +end + +io_handler_or_bust = function(io_handler) + local recipe = recipe_or_bust(io_handler) + if recipe then return recipe end + if type(io_handler) == "table" then + if type(io_handler.result) == "string" + or type(io_handler.results) == "table" + or type(io_handler.ingredients) == "table" then + return io_handler + end + end + return nil +end + +string_name_or_bust = function(prototype_name) + if type(prototype_name) == "string" then + return prototype_name + end + if type(prototype_name) == "table" then + return prototype_name.name + end + return nil +end + +add_strings_to_table = function(str_list,new_strings) + return add_strings_to_list(str_list,new_strings) +end + +add_strings_to_list = function(str_list,new_strings) + if type(new_strings) ~= "table" then + if type(str_list) == "table" then + return str_list + else + return {} + end + end + for _,str in pairs(new_strings) do + add_string_to_list(str_list,str) + end + if type(str_list) == "table" then + return str_list + else + return {} + end +end + +add_string_to_table = function(str_list,new_str) + return add_string_to_list(str_list,new_str) +end + +add_string_to_list = function(str_list,new_str) + if type(new_str) == "table" then + add_strings_to_list( + str_list, + new_str + ) + end + if type(str_list) ~= "table" then + if type(new_str) == "string" then + if type(str_list) == "string" then + str_list = { + str_list, + new_str + } + end + if str_list == nil then + str_list = {new_str} + end + return str_list + else + return str_list + end + end + for _,str in pairs(str_list) do + if str == new_str then + return str_list + end + end + if type(new_str) == "string" then + table.insert(str_list,new_str) + end + return str_list +end + +table_incl = function(val,comp) + comp = table_or_bust(comp) + if not val or not comp then return false end + for _,val_comp in pairs(comp) do + if val_comp == val then + return true + end + end + return false +end + +remove_val_from_table = function(tbl,val) + local tbl = table_or_bust(tbl) + local removed = false + for _,match in pairs(tbl or {}) do + if table_match(match,val) then + tbl[_] = nil + removed = true + end + end + return removed +end + +table_match = function(left_table,right_table) + if left_table == right_table then return true end + if type(left_table) == "table" + and type(right_table) == "table" + then + if #(left_table) ~= #(right_table) then + return false + end + for _,val in pairs(left_table) do + if not right_table[_] then return false end + if not table_match(right_table[_],val) then + return false + end + end + return true + end + return false +end + +smoosh_tables = function(left_table,right_table) + local left_table = table_or_bust(left_table) + local right_table = table_or_bust(right_table) + local new_table = {} + for _,entry in pairs(left_table or {}) do + table.insert(new_table,entry) + end + for _,entry in pairs(right_table or {}) do + table.insert(new_table,entry) + end + return new_table +end + +get_player_index = function(player) + local player = get_player(player) + if player then return player.index end + return nil +end + +get_player = function(player_index) + if type(player_index) == "table" then + if player_index.index then + return get_player(player_index.index) + end + end + if game and game.players and type(game.players) == "table" + and game.players[player_index] + and type(game.players[player_index]) == "table" + and game.players[player_index]['valid'] then + return game.players[player_index] + end + return nil +end + +get_player_armor_inventory = function(player) + local player = get_player(player) + if player then + return player.get_inventory(defines.inventory.character_armor) + end +end + +dict_to_str = function(dict) + local str = "{" + if table_or_bust(dict) then + str = str.."\n" + for key,val in pairs(dict) do + str = str.."\t"..tostring(key)..": "..tostring(val).."\n" + end + end + str = str.."}\n" + return str +end + + + +adamo.color = { + clear = {r=0,g=0,b=0,a=0}, + black = {}, + white = {r=1,g=1,b=1}, + red = {r=1,g=0,b=0}, + green = {r=0,g=1,b=0}, + blue = {r=0,g=0,b=1}, + yellow = {r=1,g=1,b=0}, + magenta = {r=1,b=0,g=1}, + cyan = {r=0,g=1,b=1}, + softpink = {r=255,g=150,b=150}, + softgreen = {r=126,g=255,b=126}, + darkgrey = {r=40,g=40,b=40}, + lowgrey = {r=80,g=80,b=80}, + midgrey = {r=127,g=127,b=127}, + highgrey = {r=204,g=204,b=204}, + darkbrown = {r=48,g=26,b=2}, + lowbrown = {r=84,g=50,b=13}, + midbrown = {r=145,g=95,b=41}, + highbrown = {r=222,g=184,b=135}, + hf_base = {r=46,g=51,b=5}, + hf_flow = {r=0.7,g=1,b=0.1}, + sodiumlamp = {r=255,g=223,b=0}, + syngasred = {r=255,g=120, b=110}, + heating_element_core = {r=255,g=50,b=0}, + heating_element_glow = {r=255,g=40,b=20}, + gas_fire_glow = {r=1,g=0.5,b=0.5}, + chemical_fire_glow = {r=255,g=63,b=0}, + is_clear = function(color) + if not color then return true end + local color = table_or_bust(color) + if color then + --color = util.table.deepcopy(color) + color = { + r = color.r or color[1] or 0, + g = color.g or color[2] or 0, + b = color.b or color[3] or 0, + a = color.a or color[4] or 1 + } + end + if color.r == 0 and color.g == 0 and color.b == 0 then return true end + --if adamo.obj.match(color,adamo.color.clear) then + -- return true + --end + return false + end +} + +adamo.item = { + types = { + "ammo", + "armor", + "blueprint", + "blueprint-book", + "capsule", + "copy-paste-tool", + "deconstruction-item", + "gun", + "item", + "item-with-entity-data", + "item-with-inventory", + "item-with-label", + "item-with-tags", + "mining-tool", + "module", + "rail-planner", + "repair-tool", + "selection-tool", + "tool", + "upgrade-item", + }, + color = { + ['chemical-science-pack'] = { + base_color = {r=90,g=200,b=220}, + flow_color = adamo.color.cyan + }, + ['coal'] = { + base_color = adamo.color.black, + flow_color = adamo.color.darkgrey + }, + ['adamo-chemical-fluorite'] = { + base_color = adamo.color.midgrey, + flow_color = adamo.color.hf_flow + }, + ['adamo-chemical-gypsum'] = { + base_color = adamo.color.highgrey, + flow_color = adamo.color.darkgrey + }, + ['adamo-chemical-calcite'] = { + base_color = adamo.color.highgrey, + flow_color = adamo.color.midgrey + }, + by_item = function(item) + local item = item_or_bust(item) + if item then return + adamo.shape.item_color(adamo.item.color[item.name]) + end + return adamo.shape.item_color() + end + }, + manifest = { + pu238 = { + "adamo-nuclear-Pu238-oxide", + "plutonium-238", + "pu-238" + }, + HF = { + "adamo-chemical-hydrofluoric-acid" + } + }, + -- Returns first item found. + find = function(name) + if string_or_bust(name) and adamo.item.manifest[name] then + for _,item_name in pairs(adamo.item.manifest[name]) do + local item = item_or_bust(item_name) + if item then return item end + local fluid = fluid_or_bust(item_name) + if fluid then return fluid end + end + end + return nil + end +} +adamo.finditem = function(name) + return adamo.item.find(name) +end + +adamo.get = { + from_types = function(types,name) + if not table_or_bust(types) or not string_or_bust(name) then + return nil + end + for _,category in pairs(types) do + if data.raw[category] and data.raw[category][name] then + return data.raw[category][name] + end + end + return nil + end, + recipe_tint = function(recipe) + local recipe = recipe_or_bust(recipe) + local tint = recipe.crafting_machine_tint + if recipe then + return adamo.shape.crafting_machine_tint(tint) + end + return { + primary = adamo.color.clear, + secondary = adamo.color.clear, + tertiary = adamo.color.clear, + quaternary = adamo.color.clear + } + end +} + +adamo.shapes = { + color = {["r"] = 0,["g"] = 0,["b"] = 0,["a"] = 255} +} + +adamo.shape = { + color = function(color) + local shape = util.table.deepcopy(adamo.shapes.color) + local color = table_or_bust(color) + if not color then return adamo.color.clear end + for field,val in pairs(adamo.shapes.color) do + if color[field] > 0 and color[field] < 1 then + shape[field] = shape[field]*255 + elseif color[field] then + shape[field] = color[field] + end + end + return shape + end, + item_color = function(item_color) + local item_color = table_or_bust(item_color) + if not item_color then return { + base_color = adamo.color.clear, + flow_color = adamo.color.clear + } end + return { + base_color = item_color.base_color or adamo.color.clear, + flow_color = item_color.flow_color or adamo.color.clear + } + end, + crafting_machine_tint = function(primary,secondary,tertiary,quaternary) + if not adamo.test.is_color(primary) then + + end + local crafting_machine_tint = primary + local tint = tint_or_bust(crafting_machine_tint) + if tint then + if type(tint.crafting_machine_tint) ~= "table" then + tint.crafting_machine_tint = + adamo.shape.crafting_machine_tint() + end + tint = tint.crafting_machine_tint + else + tint = table_or_bust(crafting_machine_tint) + end + if type(tint) ~= "table" then return { + primary = adamo.color.clear, + secondary = adamo.color.clear, + tertiary = adamo.color.clear, + quaternary = adamo.color.clear + } end + return { + primary = adamo.shape.color(tint.primary), + secondary = adamo.shape.color(tint.secondary), + tertiary = adamo.shape.color(tint.tertiary), + quaternary = adamo.shape.color(tint.quaternary), + } + end +} + +adamo.obj = { + match = function(obj1,obj2) + if type(obj1) ~= type(obj2) then return false end + if type(obj1) == "table" then + local internals_match = true + local tab1 = next(obj1) + local tab2 = next(obj2) + if not tab1 and not tab2 then return true end + if (tab1 and not tab2) + or (not tab1 and tab2) then + return false + end + for k,v in pairs(obj1) do + if obj2[k] then + if not adamo.obj.match(v,obj2[k]) then + internals_match = false + end + else return false + end + end + for k,v in pairs(obj2) do + if obj1[k] then + if not adamo.obj.match(v,obj1[k]) then + internals_match = false + end + else return false + end + end + return internals_match + else + return obj1 == obj2 + end + end, + stringify = function(obj,ml_mode,lead_str) + if type(obj) == "table" then + result = "{" + if (ml_mode) then result = result.."\n" end + for k,v in pairs(obj) do + if (ml_mode) then + result = result..(lead_str or "\t") + end + result = result + ..tostring(k)..": " + ..adamo.obj.stringify( + v,ml_mode,(lead_str or "\t").."\t" + ) + .."," + if (ml_mode) then result = result.."\n" end + end + result = result.."}" + else + result = tostring(obj) + end + return result + end +} + +colors = adamo.color + +adamo.recipe = { + -- Ingredient/result-based colors + tint = { + -- adamo.recipe.tint.apply + apply = function(recipe) + local recipe = recipe_or_bust(recipe) + if not recipe then return end + local tint = recipe.crafting_machine_tint + if not tint then + recipe.crafting_machine_tint = {} + tint = recipe.crafting_machine_tint + end + local old_tint = util.table.deepcopy(tint) + local ingredients,results = get_io_names(recipe) + adamo.debug("Applying tint to recipe "..recipe.name) + + local fields = {"quaternary","tertiary"} + for _,name in pairs(ingredients) do + adamo.debug("Checking flow_color "..name) + adamo.recipe.tint.fill(tint,name,"flow_color",fields) + end + + fields = {"primary","secondary"} + for _,name in pairs(results) do + adamo.debug("Checking base_color"..name) + adamo.recipe.tint.fill(tint,name,"base_color",fields) + end + + fields = {"secondary","primary"} + for _,name in pairs(ingredients) do + adamo.debug("Checking base_color "..name) + adamo.recipe.tint.fill(tint,name,"base_color",fields) + end + + fields = {"quaternary","tertiary","primary","secondary"} + for _,name in pairs(results) do + adamo.debug("Checking flow_color"..name) + adamo.recipe.tint.fill(tint,name,"flow_color",fields) + end + for _,name in pairs(ingredients) do + adamo.debug("Checking base_color "..name) + adamo.recipe.tint.fill(tint,name,"base_color",fields) + end + + fields = {"secondary","primary"} + for _,name in pairs(results) do + adamo.debug("Checking flow_color"..name) + adamo.recipe.tint.fill(tint,name,"flow_color",fields) + end + for _,name in pairs(ingredients) do + adamo.debug("Checking flow_color "..name) + adamo.recipe.tint.fill(tint,name,"flow_color",fields) + end + + if not adamo.obj.match(old_tint,tint) then + adamo.debug("Tint changed on recipe "..recipe.name..".") + adamo.debug("Old tint: "..adamo.obj.stringify(old_tint)) + --adamo.debug("New tint: "..adamo.obj.stringify(tint)) + --recipe.crafting_machine_tint = tint + adamo.debug( + "Recipe tint: " + ..adamo.obj.stringify(recipe.crafting_machine_tint) + ) + end + end, + fill = function(tint,name,color_type,fields) + local fluid = fluid_or_bust(name) + local item = item_or_bust(name) + if not table_or_bust(tint) + or not string_or_bust(color_type) + or not table_or_bust(fields) then + return + end + if fluid and fluid[color_type] then + for _,field in pairs(fields) do + if adamo.color.is_clear(tint[field]) then + adamo.debug( + "Applying {" + ..tostring(fluid[color_type].r) + ..", " + ..tostring(fluid[color_type].b) + ..", " + ..tostring(fluid[color_type].g) + ..", " + ..tostring(fluid[color_type].a) + .. "} to " + .. tostring(field) + ) + tint[field] = util.table.deepcopy(fluid[color_type]) + break + end + end + elseif item then + local item_colors = adamo.item.color.by_item(item) + for _,field in pairs(fields) do + if adamo.color.is_clear(tint[field]) then + adamo.debug( + "Applying {" + ..tostring(item_colors[color_type].r) + ..", " + ..tostring(item_colors[color_type].b) + ..", " + ..tostring(item_colors[color_type].g) + ..", " + ..tostring(item_colors[color_type].a) + .. "} to " + .. tostring(field) + ) + tint[field] = util.table.deepcopy(item_colors[color_type]) + break + end + end + end + end + } +} + + +adamo.test = { + unit ={ + recipe = { + tint = { + apply = function() + local tint + -- = adamo.example.recipe.tint + end + } + } + } +} + +adamo.example = { + recipe = { +-- ["crafting_machine_tint"] = { +-- ["primary"] = adamo.shapes.color, +-- ["secondary"] =, +-- ["tertiary"] =, +-- ["quaternary"] = +-- +-- }, +-- ["tinted"] = { +-- name = "test-recipe", +-- type = "recipe", +-- flow_color = +-- } + } +} \ No newline at end of file diff --git a/gas-boiler/graphics/entity/assembling-machine-1-pipe-E.png b/gas-boiler/graphics/entity/assembling-machine-1-pipe-E.png new file mode 100644 index 0000000..3e277b5 Binary files /dev/null and b/gas-boiler/graphics/entity/assembling-machine-1-pipe-E.png differ diff --git a/gas-boiler/graphics/entity/assembling-machine-1-pipe-N.png b/gas-boiler/graphics/entity/assembling-machine-1-pipe-N.png new file mode 100644 index 0000000..dca8cfb Binary files /dev/null and b/gas-boiler/graphics/entity/assembling-machine-1-pipe-N.png differ diff --git a/gas-boiler/graphics/entity/assembling-machine-1-pipe-S.png b/gas-boiler/graphics/entity/assembling-machine-1-pipe-S.png new file mode 100644 index 0000000..46f8dbd Binary files /dev/null and b/gas-boiler/graphics/entity/assembling-machine-1-pipe-S.png differ diff --git a/gas-boiler/graphics/entity/assembling-machine-1-pipe-W.png b/gas-boiler/graphics/entity/assembling-machine-1-pipe-W.png new file mode 100644 index 0000000..891dc99 Binary files /dev/null and b/gas-boiler/graphics/entity/assembling-machine-1-pipe-W.png differ diff --git a/gas-boiler/graphics/entity/gas-boiler-E-light.png b/gas-boiler/graphics/entity/gas-boiler-E-light.png new file mode 100644 index 0000000..5be1a17 Binary files /dev/null and b/gas-boiler/graphics/entity/gas-boiler-E-light.png differ diff --git a/gas-boiler/graphics/entity/gas-boiler-N-light.png b/gas-boiler/graphics/entity/gas-boiler-N-light.png new file mode 100644 index 0000000..6cdf641 Binary files /dev/null and b/gas-boiler/graphics/entity/gas-boiler-N-light.png differ diff --git a/gas-boiler/graphics/entity/gas-boiler-S-light.png b/gas-boiler/graphics/entity/gas-boiler-S-light.png new file mode 100644 index 0000000..c43ac39 Binary files /dev/null and b/gas-boiler/graphics/entity/gas-boiler-S-light.png differ diff --git a/gas-boiler/graphics/entity/gas-boiler-W-light.png b/gas-boiler/graphics/entity/gas-boiler-W-light.png new file mode 100644 index 0000000..2a907d7 Binary files /dev/null and b/gas-boiler/graphics/entity/gas-boiler-W-light.png differ diff --git a/gas-boiler/graphics/entity/hr-assembling-machine-1-pipe-E.png b/gas-boiler/graphics/entity/hr-assembling-machine-1-pipe-E.png new file mode 100644 index 0000000..62c198a Binary files /dev/null and b/gas-boiler/graphics/entity/hr-assembling-machine-1-pipe-E.png differ diff --git a/gas-boiler/graphics/entity/hr-assembling-machine-1-pipe-N.png b/gas-boiler/graphics/entity/hr-assembling-machine-1-pipe-N.png new file mode 100644 index 0000000..7b05264 Binary files /dev/null and b/gas-boiler/graphics/entity/hr-assembling-machine-1-pipe-N.png differ diff --git a/gas-boiler/graphics/entity/hr-assembling-machine-1-pipe-S.png b/gas-boiler/graphics/entity/hr-assembling-machine-1-pipe-S.png new file mode 100644 index 0000000..7600a04 Binary files /dev/null and b/gas-boiler/graphics/entity/hr-assembling-machine-1-pipe-S.png differ diff --git a/gas-boiler/graphics/entity/hr-assembling-machine-1-pipe-W.png b/gas-boiler/graphics/entity/hr-assembling-machine-1-pipe-W.png new file mode 100644 index 0000000..a11981e Binary files /dev/null and b/gas-boiler/graphics/entity/hr-assembling-machine-1-pipe-W.png differ diff --git a/gas-boiler/graphics/entity/hr-gas-boiler-E-light.png b/gas-boiler/graphics/entity/hr-gas-boiler-E-light.png new file mode 100644 index 0000000..1cd5460 Binary files /dev/null and b/gas-boiler/graphics/entity/hr-gas-boiler-E-light.png differ diff --git a/gas-boiler/graphics/entity/hr-gas-boiler-N-light.png b/gas-boiler/graphics/entity/hr-gas-boiler-N-light.png new file mode 100644 index 0000000..23fc12c Binary files /dev/null and b/gas-boiler/graphics/entity/hr-gas-boiler-N-light.png differ diff --git a/gas-boiler/graphics/entity/hr-gas-boiler-S-light.png b/gas-boiler/graphics/entity/hr-gas-boiler-S-light.png new file mode 100644 index 0000000..249fffa Binary files /dev/null and b/gas-boiler/graphics/entity/hr-gas-boiler-S-light.png differ diff --git a/gas-boiler/graphics/entity/hr-gas-boiler-W-light.png b/gas-boiler/graphics/entity/hr-gas-boiler-W-light.png new file mode 100644 index 0000000..f17d911 Binary files /dev/null and b/gas-boiler/graphics/entity/hr-gas-boiler-W-light.png differ diff --git a/gas-boiler/graphics/icons/gas-boiler.png b/gas-boiler/graphics/icons/gas-boiler.png new file mode 100644 index 0000000..47e348e Binary files /dev/null and b/gas-boiler/graphics/icons/gas-boiler.png differ diff --git a/gas-boiler/info.json b/gas-boiler/info.json new file mode 100644 index 0000000..1cdd270 --- /dev/null +++ b/gas-boiler/info.json @@ -0,0 +1,11 @@ +{ + "name": "gas-boiler", + "version": "0.1.0", + "title": "Gas-fired boiler", + "author": "adamo", + "dependencies": [ + "base" + ], + "description": "Fluid mechanics need not apply.", + "factorio_version": "1.0" +} diff --git a/gas-boiler/locale/en/base.cfg b/gas-boiler/locale/en/base.cfg new file mode 100644 index 0000000..f8f57ae --- /dev/null +++ b/gas-boiler/locale/en/base.cfg @@ -0,0 +1,13 @@ +gas-boiler=Gas-fired boiler + +[entity-name] +gas-boiler=Gas-fired boiler + +[entity-description] +gas-boiler=Burns fluids. + +[mod-setting-name] +vanilla-fluid-fuel-values=Make vanilla fluids burnable + +[mod-setting-description] +vanilla-fluid-fuel-values=Fuel_value from solid-fuel proportionally applied to vanilla petroleum fluids. \ No newline at end of file diff --git a/gas-boiler/locale/ru/base.cfg b/gas-boiler/locale/ru/base.cfg new file mode 100644 index 0000000..6ce380c --- /dev/null +++ b/gas-boiler/locale/ru/base.cfg @@ -0,0 +1,13 @@ +gas-boiler=Бойлер на жидком топливе + +[entity-name] +gas-boiler=Бойлер на жидком топливе + +[entity-description] +gas-boiler=Сжигает нефть и нефтепродукты для генерации пара. + +[mod-setting-name] +vanilla-fluid-fuel-values=Пропорциональность теплотворности + +[mod-setting-description] +vanilla-fluid-fuel-values=Теплотворность жидкостей пропорциональна теплотворности твердого топлива. diff --git a/gas-boiler/migrations/absorb_boilers.json b/gas-boiler/migrations/absorb_boilers.json new file mode 100644 index 0000000..e16ab56 --- /dev/null +++ b/gas-boiler/migrations/absorb_boilers.json @@ -0,0 +1,18 @@ +{ + "item": + [ + ["adamo-carbon-gas-fired-boiler","gas-boiler"], + ["adamo-cinefaction-gas-fired-boiler","gas-boiler"] + ], + "entity": + [ + ["adamo-carbon-gas-fired-boiler","gas-boiler"], + ["adamo-cinefaction-gas-fired-boiler","gas-boiler"] + ], + "recipe": + [ + ["adamo-carbon-gas-fired-boiler","gas-boiler"], + ["adamo-cinefaction-gas-fired-boiler","gas-boiler"] + ] +} + diff --git a/gas-boiler/settings.lua b/gas-boiler/settings.lua new file mode 100644 index 0000000..ceae0bf --- /dev/null +++ b/gas-boiler/settings.lua @@ -0,0 +1,7 @@ +data:extend({{ + name = "vanilla-fluid-fuel-values", + type = "bool-setting", + setting_type = "startup", + default_value = false, + order = "a" +}}) \ No newline at end of file