Wed, 27 Aug 2025 10:26:12 +0300
Lots of stuff
---@class FusionLabStorageData ---@field heat_interface LuaEntity heat buffer shadowing this entity ---@class FusionLabStorage ---@field fusion_labs table<LuaEntity, FusionLabStorageData>? storage = {} ---@param heat_interface LuaEntity local function init_heat_interface(heat_interface) heat_interface.custom_status = {diode=defines.entity_status_diode.green, label={"entity-status.normal"}} end local function init_storage() if storage.fusion_labs == nil then storage.fusion_labs = {} local num_labs = 0 for _, surface in pairs(game.surfaces) do for _, lab in pairs(surface.find_entities_filtered{name="fusion-lab"}) do if lab.valid then num_labs = num_labs + 1 local heat_interfaces = surface.find_entities_filtered{ name='fusion-lab-heat-interface', position=lab.position, limit = 1, } local heat_interface if #heat_interfaces == 0 then heat_interfaces = {lab.surface.create_entity{ name='fusion-lab-heat-interface', position=lab.position, force=lab.force, }} heat_interfaces[1].temperature = 15 heat_interfaces[1].destructible = false heat_interfaces[1].active = false init_heat_interface(heat_interfaces[1]) end storage.fusion_labs[lab] = { heat_interface = heat_interfaces[1], } end end end end end local function cleanup_labs() local new_storage_fusion_labs = {} for lab, lab_info in pairs(storage.fusion_labs or {}) do if lab.valid then new_storage_fusion_labs[lab] = lab_info end end storage.fusion_labs = new_storage_fusion_labs end script.on_nth_tick(31, function(event) init_storage() local need_cleanup = false for lab, lab_info in pairs(storage.fusion_labs or {}) do if not lab.valid then need_cleanup = true elseif lab.status == defines.entity_status.working then local heat_interface = lab_info.heat_interface if not heat_interface.valid then -- (╯°□°)╯︵ ┻━┻ game.print("[Fusion lab] Heat interface data corrupt, rebuilding") storage.fusion_labs = nil init_storage() return end lab.minable = (heat_interface.temperature <= 900) -- A cryogenic plant cooling hot fluoroketone voids 1320kW -- of heat energy, so the fusion lab with no modules just happens -- to conveniently radiate exactly half of that energy rate. -- -- The 0.341 here is 31/60*0.66 = 0.341 degrees of heat increase -- every 31 ticks, for 0.66 ℃/sec. it's written out as 0.341 to -- avoid potential floating point rounding errors. heat_interface.temperature = heat_interface.temperature + (1 + lab.consumption_bonus) * 0.341 if heat_interface.temperature > 600 then lab.surface.create_entity{ name = 'fusion-lab-smoke-source', position={lab.position.x + 3.5 * (math.random() - 0.5), lab.position.y + 3.5 * (math.random() - 0.5)}, force=lab.force, } end if heat_interface.temperature > 710.0 then lab.surface.create_entity{ name = 'crash-site-fire-flame', position={lab.position.x + 3.5 * (math.random() - 0.5), lab.position.y + 3.5 * (math.random() - 0.5)}, force=game.forces.neutral, } end end end if need_cleanup then cleanup_labs() end for _, player in pairs(game.players) do if player.gui.relative.fusion_lab_gui and player.opened and player.opened.name == "fusion-lab" then for lab, lab_info in pairs(storage.fusion_labs) do if lab == player.opened then local heat_interface = lab_info.heat_interface local gui = player.gui.relative.fusion_lab_gui gui.heat.value = heat_interface.temperature / 700 gui.heat.caption = {"format-degrees", string.format("%.2f", heat_interface.temperature)} end end end end end) script.on_event(defines.events.on_entity_died, function(event) local lab = event.entity event.entity.force = game.forces.neutral -- we can't rely on storage here; search for the heat interface on the map local heat_interfaces = lab.surface.find_entities_filtered{ name = 'fusion-lab-heat-interface', position = lab.position, limit = 1, } if #heat_interfaces > 0 then local heat_interface = heat_interfaces[1] if heat_interface.temperature > 700 then for _, ofs in pairs{ {0, 0}, {5, 0}, {-5, 0}, {0, 5}, {0, -5}, {1.5, 1.5}, {-1.5, 1.5}, {-1.5, -1.5}, {1.5, -1.5}} do local pos = { x = lab.position.x + ofs[1], y = lab.position.y + ofs[2]} lab.surface.create_entity{ name = 'artillery-projectile', position = pos, target = pos, force = game.forces.neutral, cause = event.entity, } end end heat_interface.destroy() end end, {{filter="name", name="fusion-lab"}}) ---@param event EventData local function on_fusion_lab_mined(event) init_storage() local entity = event.entity ---@type LuaEntity for _, heat_interface in pairs(entity.surface.find_entities_filtered{ name='fusion-lab-heat-interface', position = entity.position }) do heat_interface.destroy() end end local function on_fusion_lab_built(event) init_storage() local lab = event.entity heat_interface = lab.surface.create_entity{ name='fusion-lab-heat-interface', position=lab.position, force=lab.force, } heat_interface.temperature = 15 heat_interface.destructible = false heat_interface.active = false storage.fusion_labs[lab] = {heat_interface = heat_interface} end script.on_event(defines.events.on_player_mined_entity, on_fusion_lab_mined, {{filter="name", name="fusion-lab"}}) script.on_event(defines.events.on_robot_mined_entity, on_fusion_lab_mined, {{filter="name", name="fusion-lab"}}) script.on_event(defines.events.on_space_platform_mined_entity, on_fusion_lab_mined, {{filter="name", name="fusion-lab"}}) script.on_event(defines.events.on_built_entity, on_fusion_lab_built, {{filter="name", name="fusion-lab"}}) script.on_event(defines.events.on_robot_built_entity, on_fusion_lab_built, {{filter="name", name="fusion-lab"}}) script.on_event(defines.events.on_space_platform_built_entity, on_fusion_lab_built, {{filter="name", name="fusion-lab"}})