diff --git a/README.md b/README.md index 6f39ac9c..1366db43 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,12 @@ These new worlds are compelling, but one question still lingers: where do we go --- +### DISCLAIMER + +This mod is currently non-functional. I am just claiming the name! Please wait until the release of Space Age to play this mod. + +--- + ### Welcome to Maraxsis Let me introduce this pristine, submerged world. Far away from the sun, this planet paradoxically maintains a comfortable temperature through a runaway greenhouse effect. Preliminary surface scans show an average temperature of 101°F. It's not too hot and not too cold, the perfect Goldilocks zone for liquid water. Maybe even too perfect... @@ -84,6 +90,18 @@ These specialized structures are designed to withstand the immense pressures of --- +### Pressure domes circuit connectivity + +Have you ever wanted to build a giant underwater disco dome in Factorio? No? Well I coded it anyway + +![](https://files.catbox.moe/ivqc9z.mp4) + +You can also connect the dome to a wire to read the entities inside. + +![](https://files.catbox.moe/gv0fmf.png) + +--- + ### Progression Maraxsis is available at the same time as Aquilo. The mod does not change any vanilla recipes meaning the mod can be seamlessly added to any existing Space Age save, even if the save is completed. The tech tree on Maraxsis is designed to be small, focused, and efficient. The mod leans heavily into the puzzle genera requiring creative setups to solve difficult challenges. Do you have what it takes to craft the hydraulic science pack? diff --git a/data.lua b/data.lua index 50c036cd..92ed99d0 100644 --- a/data.lua +++ b/data.lua @@ -31,3 +31,10 @@ require 'prototypes.hydraulic-science-pack' require 'prototypes.autoplace' require 'prototypes.tile.lava' require 'prototypes.tips-and-tricks.tips-and-tricks' + +data:extend{{ + type = 'custom-input', + name = 'open-gui', + key_sequence = '', + linked_game_control = 'open-gui' +}} \ No newline at end of file diff --git a/locale/en/locale.cfg b/locale/en/locale.cfg index 74eea616..f8f6b48d 100644 --- a/locale/en/locale.cfg +++ b/locale/en/locale.cfg @@ -1,3 +1,5 @@ +not-operable= + [mod-name] title=Maraxsis diff --git a/prototypes/pressure-dome.lua b/prototypes/pressure-dome.lua index d4dcdaba..d7bed59d 100644 --- a/prototypes/pressure-dome.lua +++ b/prototypes/pressure-dome.lua @@ -62,7 +62,7 @@ data:extend {{ category = 'crafting', }} -local size = 16 +local function collision_box() return {{-16, -16}, {16, 16}} end data:extend {{ type = 'simple-entity-with-owner', @@ -72,16 +72,15 @@ data:extend {{ icon_size = 64, flags = {'placeable-player', 'player-creation', 'not-on-map', 'not-blueprintable'}, max_health = 3000, - collision_box = {{-size, -size}, {size, size}}, + collision_box = collision_box(), minable = {mining_time = 1, result = 'h2o-pressure-dome'}, - selection_box = {{-size, -size}, {size, size}}, - drawing_box = {{-size, -size}, {size, size}}, + selection_box = collision_box(), + drawing_box = collision_box(), collision_mask = {}, render_layer = 'higher-object-under', selectable_in_game = false, - selection_priority = 40, picture = { - layers = {shadow, dome, light, light_2}, + layers = {shadow, dome}, }, build_sound = { filename = '__core__/sound/build-ghost-tile.ogg', @@ -93,6 +92,131 @@ data:extend {{ } }} +data:extend {h2o.merge(data.raw['lamp']['small-lamp'], { + type = 'lamp', + name = 'h2o-pressure-dome-lamp', + localised_name = {'entity-name.h2o-pressure-dome'}, + localised_description = {'entity-description.h2o-pressure-dome'}, + remove_decoratives = 'false', + icon = '__maraxsis__/graphics/icons/pressure-dome.png', + icon_size = 64, + flags = {'placeable-player', 'player-creation', 'not-on-map', 'not-blueprintable'}, + max_health = 3000, + collision_box = collision_box(), + selection_box = {{-0.01, -0.01}, {0.01, 0.01}}, + selection_priority = 0, + drawing_box = collision_box(), + collision_mask = {}, + selectable_in_game = true, + picture_on = light, + picture_off = h2o.empty_image(), + circuit_wire_max_distance = 16, + energy_usage_per_tick = '2MW', + glow_size = 65, + light = { + size = 65, + color = { + b = 0.75, + g = 1, + r = 1 + }, + intensity = 0.9, + }, + light_when_colored = { + color = { + b = 0.75, + g = 1, + r = 1 + }, + intensity = 0, + size = 65, + }, +})} + +data:extend{h2o.merge(data.raw['constant-combinator']['constant-combinator'], { + type = 'constant-combinator', + name = 'h2o-pressure-dome-combinator', + localised_name = {'entity-name.h2o-pressure-dome'}, + localised_description = {'entity-description.h2o-pressure-dome'}, + remove_decoratives = 'false', + icon = '__maraxsis__/graphics/icons/pressure-dome.png', + icon_size = 64, + flags = {'placeable-player', 'player-creation', 'not-on-map', 'not-blueprintable', 'hidden'}, + max_health = 3000, + selectable_in_game = false, + item_slot_count = 500, + activity_led_light_offsets = { + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0} + }, + circuit_wire_connection_points = { + { + shadow = {red = {0, 0}, green = {0, 0}}, + wire = {red = {0, 0}, green = {0, 0}} + }, + { + shadow = {red = {0, 0}, green = {0, 0}}, + wire = {red = {0, 0}, green = {0, 0}} + }, + { + shadow = {red = {0, 0}, green = {0, 0}}, + wire = {red = {0, 0}, green = {0, 0}} + }, + { + shadow = {red = {0, 0}, green = {0, 0}}, + wire = {red = {0, 0}, green = {0, 0}} + } + }, + draw_copper_wires = false, + draw_circuit_wires = false, + sprites = 'nil', + activity_led_sprites = 'nil', + activity_led_light = 'nil', + collision_mask = {}, +})} + +local function shift_the_circuit_connection_point(entity, x, y) + local connection = entity.circuit_wire_connection_point or { + wire = {copper = {x = 0, y = 0}, green = {x = 0, y = 0}, red = {x = 0, y = 0}}, + shadow = {copper = {x = 0, y = 0}, green = {x = 0, y = 0}, red = {x = 0, y = 0}}, + } + + local function adjust_shift(vector) + if not vector then return end + vector.x = (vector[1] or vector.x or 0) + x + vector.y = (vector[2] or vector.y or 0) + y + end + + for _, connection in pairs(connection) do + for _, color in pairs(connection) do + adjust_shift(color) + end + end + + for _, sprite in pairs(entity.circuit_connector_sprites) do + adjust_shift(sprite.shift or {}) + if sprite.hr_version then + adjust_shift(sprite.hr_version.shift or {}) + end + for _, layer in pairs(sprite.layers or {}) do + adjust_shift(layer.shift or {}) + if layer.hr_version then + adjust_shift(layer.hr_version.shift or {}) + end + end + if sprite.picture then + adjust_shift(sprite.picture.shift or {}) + if sprite.picture.hr_version then + adjust_shift(sprite.picture.hr_version.shift or {}) + end + end + end +end + +shift_the_circuit_connection_point(data.raw['lamp']['h2o-pressure-dome-lamp'], 4, 17) + data:extend {{ type = 'trivial-smoke', name = 'h2o-invisible-smoke', diff --git a/scripts/composite-entity.lua b/scripts/composite-entity.lua index 62867b4f..2732f289 100644 --- a/scripts/composite-entity.lua +++ b/scripts/composite-entity.lua @@ -46,7 +46,7 @@ h2o.on_event('on_built', on_built) local function on_destroyed(event) local entity = event.entity - if not composite_entity_creation[entity.name] then return end + if not entity.valid or not composite_entity_creation[entity.name] then return end local sub_entities = global.composite_entities[entity.unit_number] if not sub_entities then return end for _, sub_entity in pairs(sub_entities) do diff --git a/scripts/pressure-dome.lua b/scripts/pressure-dome.lua index 58cb15bc..d28770b1 100644 --- a/scripts/pressure-dome.lua +++ b/scripts/pressure-dome.lua @@ -137,6 +137,93 @@ local function count_points_in_dome(pressure_dome_data, entity) return count end +local function create_dome_light(dome) + if not dome.valid then error('Attempted to circuit connect an invalid dome! Please report this.') end + + local light = dome.surface.create_entity { + name = 'h2o-pressure-dome-lamp', + position = dome.position, + force = dome.force, + create_build_effect_smoke = false, + } + + light.minable = false + light.destructible = false + + local control_behavior = light.get_or_create_control_behavior() + control_behavior.circuit_condition = { + condition = { + first_signal = {type = 'virtual', name = 'signal-dot'}, + comparator = '=', + constant = 0, + } + } + + return light +end + +local function create_dome_combinator(pressure_dome_data) + local light = pressure_dome_data.light + if not light or not light.valid then + light = create_dome_light(pressure_dome_data.entity) + pressure_dome_data.light = light + end + + local combinator = light.surface.create_entity { + name = 'h2o-pressure-dome-combinator', + position = light.position, + force = light.force, + create_build_effect_smoke = false, + } + + combinator.minable = false + combinator.destructible = false + combinator.operable = false + + local red_success = combinator.connect_neighbour { + wire = defines.wire_type.red, + target_entity = light, + } + local green_success = combinator.connect_neighbour { + wire = defines.wire_type.green, + target_entity = light, + } + + assert(red_success, 'Failed to connect red wire to the dome light. Please report this!') + assert(green_success, 'Failed to connect green wire to the dome light. Please report this!') + + pressure_dome_data.combinator = combinator + return combinator +end + +local function update_combinator(pressure_dome_data) + local combinator = pressure_dome_data.combinator + if not combinator or not combinator.valid then + combinator = create_dome_combinator(pressure_dome_data) + end + + local all_machines_inside = {} + for _, e in pairs(pressure_dome_data.contained_entities) do + if e.valid then + for _, item_to_place in pairs(e.prototype.items_to_place_this or {}) do + all_machines_inside[item_to_place.name] = (all_machines_inside[item_to_place.name] or 0) + 1 + end + end + end + + local control_behavior = combinator.get_or_create_control_behavior() + control_behavior.parameters = nil + local parameters = {} + for name, count in pairs(all_machines_inside) do + parameters[#parameters + 1] = { + signal = {type = 'item', name = name}, + count = count, + index = #parameters + 1, + } + end + control_behavior.parameters = parameters +end + h2o.on_event('on_built', function(event) local entity = event.entity or event.created_entity if not entity.valid or entity.name == 'h2o-pressure-dome' then return end @@ -156,6 +243,7 @@ h2o.on_event('on_built', function(event) end end table.insert(pressure_dome_data.contained_entities, entity) + update_combinator(pressure_dome_data) else h2o.cancel_creation(entity, event.player_index, {'cant-build-reason.entity-in-the-way', dome.localised_name}) end @@ -175,7 +263,7 @@ local function place_tiles(pressure_dome_data) for xx = -math.floor(size), math.floor(size) do for yy = -math.floor(size), math.floor(size) do - if is_point_in_polygon(xx + 0.5, yy + 0.5) then + if is_point_in_polygon(xx + 0.5, yy) then local x, y = x + xx, y + yy tiles[#tiles + 1] = {name = 'h2o-pressure-dome-tile', position = {x, y}} end @@ -205,7 +293,7 @@ local function unplace_tiles(pressure_dome_data) for _, tile in pairs(tiles_in_square) do local tile_position = tile.position local xx, yy = tile_position.x, tile_position.y - if is_point_in_polygon(xx - x + 0.5, yy - y + 0.5) then + if is_point_in_polygon(xx - x + 0.5, yy - y) then tiles[#tiles + 1] = {name = tile.hidden_tile or DEFAULT_MARAXSIS_TILE, position = {xx, yy}} end end @@ -299,6 +387,8 @@ h2o.on_event('on_built', function(event) return end + local light = create_dome_light(entity) + entity.minable = false entity.destructible = false @@ -308,9 +398,11 @@ h2o.on_event('on_built', function(event) position = entity.position, surface = entity.surface, contained_entities = contained_entities, + light = light, collision_boxes = {}, } + update_combinator(pressure_dome_data) place_collision_boxes(pressure_dome_data) place_tiles(pressure_dome_data) entity.health = entity.prototype.max_health @@ -338,6 +430,7 @@ local function delete_invalid_entities_from_contained_entities_list(pressure_dom end end pressure_dome_data.contained_entities = new_contained + update_combinator(pressure_dome_data) break end end @@ -449,6 +542,8 @@ h2o.on_event('on_destroyed', function(event) global.pressure_domes[unit_number] = nil unplace_tiles(pressure_dome_data) destroy_collision_boxes(pressure_dome_data) + local light = pressure_dome_data.light + if light and light.valid then light.destroy() end if event.name == defines.events.on_entity_died then on_dome_died(event, pressure_dome_data) end @@ -510,4 +605,49 @@ h2o.on_event(defines.events.on_entity_damaged, function(event) collision_box.health = entity.health end end +end) + +local function figure_out_wire_type(player) + local cursor_stack = player.cursor_stack + if cursor_stack and cursor_stack.valid_for_read then + local stack_name = cursor_stack.name + if stack_name == 'red-wire' then + return defines.wire_type.red + elseif stack_name == 'green-wire' then + return defines.wire_type.green + elseif stack_name == 'copper-cable' then + return defines.wire_type.copper + end + end + + return nil +end + +h2o.on_event('open-gui', function(event) + local player = game.get_player(event.player_index) + if not player or not player.valid then return end + local entity = player.selected + if not entity or not entity.valid then return end + + if entity.name ~= 'h2o-pressure-dome-collision' then return end + + local pressure_dome_data = find_pressure_dome_data_by_collision_entity(entity) + if not pressure_dome_data then return end + local light = pressure_dome_data.light + if not light or not light.valid then + local dome = pressure_dome_data.entity + if not dome.valid then return end + pressure_dome_data.light = create_dome_light(dome) + end + + local wire_type = figure_out_wire_type(player) + if wire_type then + player.selected = light + player.drag_wire{position = light.position} + player.selected = entity + return + end + + player.opened = nil + player.opened = light end) \ No newline at end of file