local Ancient = {} --[[ IMPORTANT The pyramids and anomaly gate puzzle in-game is supposed to be the crowning achievement of completing Space Exploration. Please don't try to reverse engineer this code to figure out a solution to the puzzle, it will spoil it for you and for others. ]]-- -- STATIC if true then -- rectangles Ancient.name_tech_coordinates = mod_prefix .. "long-range-star-mapping" Ancient.name_tech_anchor = mod_prefix .. "dimensional-anchor" Ancient.name_gate_tryplace = mod_prefix .. "gate-tryplace" Ancient.name_gate_blocker = mod_prefix .. "gate-blocker" Ancient.name_gate_blocker_void = mod_prefix .. "gate-blocker-void" Ancient.name_gate_void_sprite = mod_prefix.."gate-void-sprite" Ancient.name_gate_glyph_prefix = mod_prefix.."glyph-a-energy-" Ancient.name_gate_glyph_locked_suffix = "-locked" Ancient.name_gate_light = mod_prefix .. "gate-light" Ancient.name_gate_light_middle = mod_prefix .. "gate-light-middle" Ancient.name_gate_lock_combinator = mod_prefix .. "gate-lock-combinator" Ancient.name_gate_lock_switch = mod_prefix .. "gate-lock-switch" Ancient.name_gate_fluid_input = mod_prefix .. "gate-tank-input" Ancient.name_gate_fluid_output = mod_prefix .. "gate-tank-output" Ancient.name_button_player_track_glyphs = "player_track_glyphs" Ancient.name_gate_cloud = mod_prefix .. "gate-cloud" Ancient.name_gate_spec_white = mod_prefix .. "gate-spec-white" Ancient.name_gate_spec_cyan = mod_prefix .. "gate-spec-cyan" Ancient.name_sound_gate_turning = mod_prefix .. "sound-continous-gate-turning" Ancient.name_sound_gate_power_on = mod_prefix .. "sound-continous-gate-power-on" Ancient.name_sound_gate_power_up = mod_prefix .. "sound-gate-power-up" Ancient.name_sound_gate_power_down = mod_prefix .. "sound-gate-power-down" Ancient.name_sound_gate_button = mod_prefix .. "sound-gate-button" Ancient.name_sound_gate_lock = mod_prefix .. "sound-gate-lock" Ancient.timer_power_up_complete = 395 -- based on audio Ancient.timer_power_up_ghyph_light_interval = 3 Ancient.timer_power_down_complete = 283 Ancient.timer_shunt_step = 0.03 Ancient.timer_shunt_glyph_lock = 1.09 Ancient.timer_shunt_complete = 3.5 Ancient.unit_power_draw = 10000000000/60 Ancient.gate_temperature_resting = 25 Ancient.gate_temperature_partial = -200 -- required for glyph lock Ancient.gate_temperature_required = -250 -- required for gate activation Ancient.gate_temperature_zero = -273.15 Ancient.gate_temperature_per_coolant_max = 1 Ancient.gate_temperature_per_coolant_min = 0.001 -- lerp between resting and zero Ancient.gate_temperature_return_per_tick = 0.00001 -- multiplied by -temp Ancient.gate_temperature_while_powered = 0.001 Ancient.gate_temperature_while_turning = 0.01 Ancient.gate_temperature_while_locked = 0.1 Ancient.gate_temperature_while_portal = 1 Ancient.gate_cloud_tint_1 = {r = 0.2, g = 0.6, b = 1} Ancient.gate_cloud_tint_2 = {r = 0.2, g = 0.2, b = 1} Ancient.vault_entrance_structures = { -- also used in zone deletion mod_prefix .. "pyramid-a", mod_prefix .. "pyramid-b", mod_prefix .. "pyramid-c", } Ancient.gate_default_position = {x =0, y = -128} Ancient.galaxy_ship_default_position = {x = 100, y = -400} -- rows Ancient.gate_blockers_phase_1 = { [-26] = {{-8,9}}, [-25] = {{-15,5}}, [-24] = {{-16,5}}, [-23] = {{-18,5}}, [-22] = {{-20,5}}, [-21] = {{-22,-9}}, [-20] = {{-24,-13}, {23,25}}, [-19] = {{-25,-16}}, [-18] = {{-27,-18}}, [-17] = {{-28,-20}, {21,23}}, [-16] = {{-29,-21}, {22,23}}, [-15] = {{-30,-22}}, [-14] = {{-31,-24}}, [-13] = {{-32,-25}}, [-12] = {{-34,-26}}, [-11] = {{-34,-27}}, [-10] = {{-34,-27}}, [-9] = {{-34,-28}}, [-8] = {{-34,-28}, {29,31}}, [-7] = {{-34,-29}, {30,31}}, [-6] = {{-35,-29}, {30,31}, {35,36}}, [-5] = {{-35,-30}, {35,36}}, [-4] = {{-35,-30}}, [-3] = {{-35,-30}}, [-2] = {{-35,-30}}, [-1] = {{-35,-30}}, [0] = {{-35,-30}}, [1] = {{-35,-30}}, [2] = {{-35,-30}}, [3] = {{-35,-30}, {35,36}}, [4] = {{-35,-30}, {35,36}}, [5] = {{-34,-29}}, [6] = {{-34,-29}}, [7] = {{-34,-28}}, [8] = {{-34,-28}}, [9] = {{-34,-27}}, [10] = {{-34,-26}, {27,28}}, [11] = {{-32,-28}, {26,28}}, [12] = {{-31,-28}, {25,28}}, [13] = {{-30,-28}, {29,31}}, [14] = {{-29,-28}, {29,30}}, [15] = {{21,23}}, [16] = {{-20,-19}}, [17] = {{-25,-23}, {18,19}, {25,26}}, [18] = {{-24,-23}}, [20] = {{8,9}}, [24] = {{-8,-7}}, [25] = {{-5,6}}, [26] = {{-4,5}}, } Ancient.gate_blockers_void_phase_1 = { [-21] = {{-9,5}}, [-20] = {{-13,5}}, [-19] = {{-16,5}}, [-18] = {{-18,5}}, [-17] = {{-20,21}}, [-16] = {{-21,22}}, [-15] = {{-22,23}}, [-14] = {{-24,23}}, [-13] = {{-25,23}}, [-12] = {{-26,23}}, [-11] = {{-27,23}}, [-10] = {{-27,23}}, [-9] = {{-28,23}}, [-8] = {{-28,29}}, [-7] = {{-29,30}}, [-6] = {{-29,30}}, [-5] = {{-30,31}}, [-4] = {{-30,31}}, [-3] = {{-30,31}}, [-2] = {{-30,31}}, [-1] = {{-30,31}}, [0] = {{-30,31}}, [1] = {{-30,31}}, [2] = {{-30,31}}, [3] = {{-30,28}}, [4] = {{-30,28}}, [5] = {{-29,28}}, [6] = {{-29,28}}, [7] = {{-28,28}}, [8] = {{-28,28}}, [9] = {{-27,28}}, [10] = {{-26,27}}, [11] = {{-20,26}}, [12] = {{-20,25}}, [13] = {{-20,23}}, [14] = {{-20,23}}, [15] = {{-20,21}}, [16] = {{-19,19}}, [17] = {{-7,18}}, [18] = {{-7,9}}, [19] = {{-7,9}}, [20] = {{-7,8}}, } Ancient.gate_blockers_phase_2 = { [-25] = {{5,16}}, [-24] = {{5,17}}, [-23] = {{5,19}}, [-22] = {{5,21}}, [-21] = {{10,23}}, [-20] = {{14,23}}, [-19] = {{17,26}}, [-18] = {{19,28}}, [-17] = {{23,29}}, [-16] = {{23,30}}, [-15] = {{23,31}}, [-14] = {{25,32}}, [-13] = {{26,33}}, [-12] = {{27,35}}, [-11] = {{28,35}}, [-10] = {{28,35}}, [-9] = {{29,35}}, [-8] = {{31,35}}, [-7] = {{31,35}}, [-6] = {{31,35}}, [-5] = {{31,35}}, [-4] = {{31,36}}, [-3] = {{31,36}}, [-2] = {{31,36}}, [-1] = {{31,36}}, [0] = {{31,36}}, [1] = {{31,36}}, [2] = {{31,36}}, [3] = {{31,35}}, [4] = {{31,35}}, [5] = {{30,35}}, [6] = {{30,35}}, [7] = {{29,35}}, [8] = {{29,35}}, [9] = {{28,35}}, [10] = {{28,35}}, [11] = {{-28,-25}, {28,33}}, [12] = {{-28,-24}, {28,32}}, [13] = {{-28,-23}, {24,29}}, [14] = {{-28,-22}, {23,29}}, [15] = {{-28,-20}, {23,29}}, [16] = {{-27,-20}, {20,28}}, [17] = {{-23,-17}, {19,25}}, [18] = {{-23,-15}, {16,25}}, [19] = {{-22,-10}, {11,23}}, [20] = {{-20,-7}, {9,21}}, [21] = {{-18,19}}, [22] = {{-16,17}}, [23] = {{-15,16}}, [24] = {{-7,9}}, } Ancient.gate_blockers_void_phase_2 = { [-21] = {{5,10}}, [-20] = {{5,14}}, [-19] = {{5,17}}, [-18] = {{5,19}}, [-14] = {{23,25}}, [-13] = {{23,26}}, [-12] = {{23,27}}, [-11] = {{23,28}}, [-10] = {{23,28}}, [-9] = {{23,29}}, [3] = {{28,31}}, [4] = {{28,31}}, [5] = {{28,30}}, [6] = {{28,30}}, [7] = {{28,29}}, [8] = {{28,29}}, [11] = {{-25,-20}}, [12] = {{-24,-20}}, [13] = {{-23,-20}, {23,24}}, [14] = {{-22,-20}}, [16] = {{19,20}}, [17] = {{-17,-7}}, [18] = {{-15,-7}, {9,16}}, [19] = {{-10,-7}, {9,11}}, } Ancient.gate_fragments = { [mod_prefix .. "gate-fragment-1"] = {placeable = true, position = {x = 28, y = -10}, required_position = {14,23}}, [mod_prefix .. "gate-fragment-2"] = {placeable = true, position = {x = 39, y = -3}, required_position = {1,22}}, [mod_prefix .. "gate-fragment-3"] = {placeable = true, position = {x = 38, y = 9.5}, required_position = {-13,20.5}}, [mod_prefix .. "gate-fragment-4"] = {placeable = true, position = {x = 41, y = 19}, required_position = {-24,14}}, [mod_prefix .. "gate-fragment-5"] = {placeable = true, position = {x = 40, y = 28}, required_position = {24,18}}, [mod_prefix .. "gate-fragment-6"] = {placeable = true, position = {x = 0, y = 24}, required_position = {21,17}}, [mod_prefix .. "gate-fragment-7"] = {placeable = true, position = {x = -23, y = 15}, required_position = {26,15}}, [mod_prefix .. "gate-fragment-8"] = {placeable = true, position = {x = 27.5, y = 26}, required_position = {31.5,8}}, [mod_prefix .. "gate-fragment-9"] = {placeable = true, position = {x = 52.5, y = 28.5}, required_position = {33.5,0.5}}, [mod_prefix .. "gate-fragment-10"] = {placeable = true, position = {x = 12, y = -19}, required_position = {32,-5}}, [mod_prefix .. "gate-fragment-11"] = {placeable = true, position = {x = 24, y = -18}, required_position = {34,-7}}, [mod_prefix .. "gate-fragment-12"] = {placeable = true, position = {x = 16, y = 24.5}, required_position = {30,-12.5}}, [mod_prefix .. "gate-fragment-13"] = {placeable = true, position = {x = -17, y = 21}, required_position = {14,-23}}, [mod_prefix .. "gate-fragment-14-a"] = {placeable = false, position = {x = -28, y = -4}}, [mod_prefix .. "gate-fragment-14-b"] = {placeable = false, position = {x = -8.5, y = -24}}, } Ancient.gate_parts_main = { [mod_prefix .. "gate-main-e"] = {32,0}, [mod_prefix .. "gate-main-en"] = {28.5,-15.5}, [mod_prefix .. "gate-main-es"] = {28.5,15}, [mod_prefix .. "gate-main-n"] = {0.5,-23}, [mod_prefix .. "gate-main-ne"] = {17.5,-20.5}, [mod_prefix .. "gate-main-nw"] = {-16.5,-20.5}, [mod_prefix .. "gate-main-s"] = {0.5,22.5}, [mod_prefix .. "gate-main-se"] = {16.5,19.5}, [mod_prefix .. "gate-main-sw"] = {-15.5,19.5}, [mod_prefix .. "gate-main-w"] = {-31,0}, [mod_prefix .. "gate-main-wn"] = {-27.5,-15.5}, [mod_prefix .. "gate-main-ws"] = {-27.5,15}, } Ancient.gate_parts_main_shadow = { [mod_prefix .. "gate-main-e-shadow"] = {35.5,0}, [mod_prefix .. "gate-main-en-shadow"] = {30.0,-14.5}, [mod_prefix .. "gate-main-es-shadow"] = {28.5,15}, [mod_prefix .. "gate-main-ne-shadow"] = {16.0,-20.5}, [mod_prefix .. "gate-main-s-shadow"] = {0.5,24.0}, [mod_prefix .. "gate-main-se-shadow"] = {16.5,21.5}, [mod_prefix .. "gate-main-sw-shadow"] = {-15.5,21.5}, [mod_prefix .. "gate-main-w-shadow"] = {-34,0}, [mod_prefix .. "gate-main-ws-shadow"] = {-27.5,15}, } Ancient.gate_parts_underlay = { [mod_prefix .. "gate-underlay-e"] = {32.5,-1}, [mod_prefix .. "gate-underlay-en"] = {28,-15}, [mod_prefix .. "gate-underlay-es"] = {27.5,12.5}, [mod_prefix .. "gate-underlay-n"] = {0.5,-23.5}, [mod_prefix .. "gate-underlay-ne"] = {19,-20}, [mod_prefix .. "gate-underlay-nw"] = {-18,-20}, [mod_prefix .. "gate-underlay-s"] = {0.5,22}, [mod_prefix .. "gate-underlay-se"] = {19.5,19}, [mod_prefix .. "gate-underlay-sw"] = {-18.5,19}, [mod_prefix .. "gate-underlay-w"] = {-31.5,-1}, [mod_prefix .. "gate-underlay-wn"] = {-27,-15}, [mod_prefix .. "gate-underlay-ws"] = {-26.5,12.5}, } Ancient.gate_parts_rails = { [mod_prefix .. "gate-rails-1"] = {-12.5,21}, [mod_prefix .. "gate-rails-2"] = {-30.5,8}, [mod_prefix .. "gate-rails-3"] = {-30.5,-10}, [mod_prefix .. "gate-rails-4"] = {-12.5,-23}, [mod_prefix .. "gate-rails-5"] = {13.5,-23}, [mod_prefix .. "gate-rails-6"] = {31.5,-10}, [mod_prefix .. "gate-rails-7"] = {31.5,8}, [mod_prefix .. "gate-rails-8"] = {13.5,21}, } Ancient.gate_parts_shunts = { [1] = {name = mod_prefix .. "gate-shunt-1", position = {-13,21.5}, lock_offset = {0.45,-0.8}}, [2] = {name = mod_prefix .. "gate-shunt-2", position = {-31,8.5}, lock_offset = {1.1,-0.4}}, [3] = {name = mod_prefix .. "gate-shunt-3", position = {-31,-10.5}, lock_offset = {1.1,0.4}}, [4] = {name = mod_prefix .. "gate-shunt-4", position = {-13,-23.5}, lock_offset = {0.45,0.8}}, [5] = {name = mod_prefix .. "gate-shunt-5", position = {14,-23.5}, lock_offset = {-0.45,0.8}}, [6] = {name = mod_prefix .. "gate-shunt-6", position = {32,-10.5}, lock_offset = {-1.1,0.4}}, [7] = {name = mod_prefix .. "gate-shunt-7", position = {32,8.5}, lock_offset = {-1.1,-0.4}}, [8] = {name = mod_prefix .. "gate-shunt-8", position = {14,21.5}, lock_offset = {-0.45,-0.8}}, } Ancient.gate_parts_addons = { [mod_prefix .. "gate-addon-1"] = {-13,22}, [mod_prefix .. "gate-addon-2"] = {-32,9}, [mod_prefix .. "gate-addon-3"] = {-32,-10}, [mod_prefix .. "gate-addon-4"] = {-13,-23}, [mod_prefix .. "gate-addon-5"] = {14,-23}, [mod_prefix .. "gate-addon-6"] = {33,-10}, [mod_prefix .. "gate-addon-7"] = {33,9}, [mod_prefix .. "gate-addon-8"] = {14,22}, } Ancient.gate_parts_lock_combinators = { [1] = {direction = defines.direction.south, position = {-13.062, 23.543}}, [2] = {direction = defines.direction.west, position = {-33.644, 8.933}}, [3] = {direction = defines.direction.west, position = {-33.625, -9.476}}, [4] = {direction = defines.direction.north, position = {-12.968, -24.746}}, [5] = {direction = defines.direction.north, position = {13.675, -24.753}}, [6] = {direction = defines.direction.east, position = {34.468, -10.558}}, [7] = {direction = defines.direction.east, position = {34.582, 8.433}}, [8] = {direction = defines.direction.south, position = {13.96, 23.519}}, } Ancient.gate_parts_lock_fluid_inputs = { [1] = {direction = defines.direction.south, position = {-14.5, 23.5}}, [2] = {direction = defines.direction.west, position = {-33.5, 7.5}}, [3] = {direction = defines.direction.west, position = {-33.5, -11.5}}, [4] = {direction = defines.direction.north, position = {-11.5, -24.5}}, [5] = {direction = defines.direction.north, position = {15.5, -24.5}}, [6] = {direction = defines.direction.east, position = {34.5, -8.5}}, [7] = {direction = defines.direction.east, position = {34.5, 10.5}}, [8] = {direction = defines.direction.south, position = {12.5, 23.5}}, } Ancient.gate_parts_lock_fluid_outputs = { [1] = {direction = defines.direction.south, position = {-11.5, 23.5}}, [2] = {direction = defines.direction.west, position = {-33.5, 10.5}}, [3] = {direction = defines.direction.west, position = {-33.5, -8.5}}, [4] = {direction = defines.direction.north, position = {-14.5, -24.5}}, [5] = {direction = defines.direction.north, position = {12.5, -24.5}}, [6] = {direction = defines.direction.east, position = {34.5, -11.5}}, [7] = {direction = defines.direction.east, position = {34.5, 7.5}}, [8] = {direction = defines.direction.south, position = {15.5, 23.5}}, } Ancient.gate_parts_platform = { name = mod_prefix .. "gate-platform", name_scaffold = mod_prefix .. "gate-platform-scaffold", position = {0.5,25}, energy_interface = { name = mod_prefix .. "gate-energy-interface", position = {0.5,25} }, buttons = { name_switch = mod_prefix .. "gate-platform-button-switch", left = {name = mod_prefix .. "gate-platform-button-left", position = {2.5234,26.04}, switch_position = {2.5234,26.04}}, middle = {name = mod_prefix .. "gate-platform-button-middle", position = {3.37,26.04}, switch_position = {3.37,26.04}}, right = {name = mod_prefix .. "gate-platform-button-right", position = {4.19,26.04}, switch_position = {4.19,26.04}}, }, indicators = { names = { [1] = mod_prefix .. "gate-platform-indicator-red", [2] = mod_prefix .. "gate-platform-indicator-yellow", [3] = mod_prefix .. "gate-platform-indicator-green", }, x_start = -2.789, x_spacing = 7/32, anchor_y = 24.859, temperature_y = 25.421, lock_y = 25.984, }, combinator = { name = mod_prefix .. "gate-platform-combinator", position = {4.55, 26.2} } } Ancient.gate_sound_positions = { [1] = {-13,21.5}, [2] = {-31,8.5}, [3] = {-31,-10.5}, [4] = {-13,-23.5}, [5] = {14,-23.5}, [6] = {32,-10.5}, [7] = {32,8.5}, [8] = {14,21.5}, [9] = {0.5,25}, -- platform } Ancient.gate_glyphs_x = 0.5 Ancient.gate_glyphs_x_mult = 33.4 Ancient.gate_glyphs_y = -0.9 Ancient.gate_glyphs_y_mult = 23.55 Ancient.gate_parts_locked_glyphs = { [1] = {-11.75,19.91}, [2] = {-29.09,7.64}, [3] = {-29.09,-9.66}, [4] = {-11.75,-21.91}, [5] = {12.75,-21.91}, [6] = {30.09,-9.66}, [7] = {30.09,7.64}, [8] = {12.75,19.91}, } Ancient.gate_acceleration = 0.002 Ancient.gate_decceleration = 0.02 Ancient.gate_max_speed = 0.1 Ancient.pyramid_width = 9*2 Ancient.pyramid_height = 7*2 Ancient.cartouche_path_width = 4 Ancient.cartouche_path_wall_width = 12 Ancient.cartouche_path_start = 0 Ancient.cartouche_path_wall_start = 30 Ancient.cartouche_path_end = 40 Ancient.cartouche_path_wall_end= 100 end local crypto = 0 local cryptl = 1 local cryptf = 5 local cryptc = 8 local crypte = 11 local crypti = 60 local cryptr = cryptl+math.sqrt(cryptf) local cryptg = (cryptr)/2 local crypta = (cryptl+cryptr)/3 local cryptb = (cryptr)/6 local cryptx = { cryptl,cryptg,crypto,cryptl,-cryptg,crypto,-cryptl,cryptg,crypto,-cryptl, -cryptg,crypto,cryptg,crypto,cryptl,cryptg,crypto,-cryptl,-cryptg,crypto, cryptl,-cryptg,crypto,-cryptl,crypto,cryptl,cryptg,crypto,cryptl,-cryptg, crypto,-cryptl,cryptg,crypto,-cryptl,-cryptg,cryptl,cryptl,cryptl,cryptl, cryptl,-cryptl,cryptl,-cryptl,cryptl,cryptl,-cryptl,-cryptl,-cryptl,cryptl, cryptl,-cryptl,cryptl,-cryptl,-cryptl,-cryptl,cryptl,-cryptl,-cryptl,-cryptl, crypta,cryptb,crypto,crypta,-cryptb,crypto,-crypta,cryptb,crypto,-crypta, -cryptb,crypto,cryptb,crypto,crypta,cryptb,crypto,-crypta,-cryptb,crypto, crypta,-cryptb,crypto,-crypta,crypto,crypta,cryptb,crypto,crypta,-cryptb, crypto,-crypta,cryptb,crypto,-crypta,-cryptb} local cryptv = { 1,29,30,1,30,14,1,14,21,1,21,13,1,13,29,2,32,31,2,31,15,2,15, 22,2,22,16,2,16,32,3,30,29,3,29,17,3,17,23,3,23,18,3,18,30,4,31,32,4,32,20,4,20, 24,4,24,19,4,19,31,5,21,22,5,22,15,5,15,25,5,25,13,5,13,21,6,22,21,6,21,14,6,14, 26,6,26,16,6,16,22,7,24,23,7,23,17,7,17,27,7,27,19,7,19,24,8,23,24,8,24,20,8,20, 28,8,28,18,8,18,23,9,25,27,9,27,17,9,17,29,9,29,13,9,13,25,10,28,26,10,26,14,10, 14,30,10,30,18,10,18,28,11,27,25,11,25,15,11,15,31,11,31,19,11,19,27,12,26,28, 12,28,20,12,20,32,12,32,16,12,16,26 } local cryptn = { 2,5,11,15,49,48,3,4,44,43,12,3,1,48,47,28,27,4,5,11,15,49,4,2, 27,26,21,25,5,1,48,47,28,5,3,25,24,45,44,1,2,27,26,21,1,4,44,43,12,11,2,3,25,24, 45,7,10,16,20,54,53,8,9,59,58,17,8,6,53,52,23,22,9,10,16,20,54,9,7,22,21,26,30, 10,6,53,52,23,10,8,30,29,60,59,6,7,22,21,26,6,9,59,58,17,16,7,8,30,29,60,12,15, 1,5,44,43,13,14,49,48,2,13,11,43,42,33,32,14,15,1,5,44,14,12,32,31,36,40,15,11, 43,42,33,15,13,40,39,50,49,11,12,32,31,36,11,14,49,48,2,1,12,13,40,39,50,17,20, 6,10,59,58,18,19,54,53,7,18,16,58,57,38,37,19,20,6,10,59,19,17,37,36,31,35,20 ,16,58,57,38,20,18,35,34,55,54,16,17,37,36,31,16,19,54,53,7,6,17,18,35,34,55,22, 25,26,30,9,8,23,24,4,3,27,23,21,8,7,53,52,24,25,26,30,9,24,22,52,51,41,45,25,21, 8,7,53,25,23,45,44,5,4,21,22,52,51,41,21,24,4,3,27,26,22,23,45,44,5,27,30,21,25, 4,3,28,29,9,8,22,28,26,3,2,48,47,29,30,21,25,4,29,27,47,46,56,60,30,26,3,2,48, 30,28,60,59,10,9,26,27,47,46,56,26,29,9,8,22,21,27,28,60,59,10,32,35,36,40,14, 13,33,34,19,18,37,33,31,13,12,43,42,34,35,36,40,14,34,32,42,41,51,55,35,31,13, 12,43,35,33,55,54,20,19,31,32,42,41,51,31,34,19,18,37,36,32,33,55,54,20,37,40, 31,35,19,18,38,39,14,13,32,38,36,18,17,58,57,39,40,31,35,19,39,37,57,56,46,50, 40,36,18,17,58,40,38,50,49,15,14,36,37,57,56,46,36,39,14,13,32,31,37,38,50,49, 15,42,45,51,55,34,33,43,44,24,23,52,43,41,33,32,13,12,44,45,51,55,34,44,42,12, 11,1,5,45,41,33,32,13,45,43,5,4,25,24,41,42,12,11,1,41,44,24,23,52,51,42,43,5,4, 25,47,50,56,60,29,28,48,49,39,38,57,48,46,28,27,3,2,49,50,56,60,29,49,47,2,1,11, 15,50,46,28,27,3,50,48,15,14,40,39,46,47,2,1,11,46,49,39,38,57,56,47,48,15,14, 40,52,55,41,45,24,23,53,54,34,33,42,53,51,23,22,8,7,54,55,41,45,24,54,52,7,6,16, 20,55,51,23,22,8,55,53,20,19,35,34,51,52,7,6,16,51,54,34,33,42,41,52,53,20,19, 35,57,60,46,50,39,38,58,59,29,28,47,58,56,38,37,18,17,59,60,46,50,39,59,57,17, 16,6,10,60,56,38,37,18,60,58,10,9,30,29,56,57,17,16,6,56,59,29,28,47,46,57,58, 10,9,30 } local crypts = {3,4,5,6,1,7,8,2,9,10,11} local cryptt = { 7,0,0,-1,-1,3,6,1,0,-4,3,6,6,0,0,1,4,2,6,0,1,3,-2,8,5,2,0,-9,6, 11,5,1,0,2,7,5,5,1,1,6,8,13,5,0,1,4,9,7,5,0,2,8,-5,15,4,3,0,-16,11,18,4,2,0,5, 12,10,4,2,1,11,13,20,4,1,1,7,14,12,4,1,2,13,15,22,4,0,2,9,16,14,4,0,3,15,-10,24, 3,4,0,-25,18,27,3,3,0,10,19,17,3,3,1,18,20,29,3,2,1,12,21,19,3,2,2,20,22,31,3,1, 2,14,23,21,3,1,3,22,24,33,3,0,3,16,25,23,3,0,4,24,-17,35,2,5,0,-36,27,38,2,4,0, 17,28,26,2,4,1,27,29,40,2,3,1,19,30,28,2,3,2,29,31,42,2,2,2,21,32,30,2,2,3,31, 33,44,2,1,3,23,34,32,2,1,4,33,35,46,2,0,4,25,36,34,2,0,5,35,-26,48,1,6,0,-49,38, 51,1,5,0,26,39,37,1,5,1,38,40,53,1,4,1,28,41,39,1,4,2,40,42,55,1,3,2,30,43,41,1, 3,3,42,44,57,1,2,3,32,45,43,1,2,4,44,46,59,1,1,4,34,47,45,1,1,5,46,48,61,1,0,5, 36,49,47,1,0,6,48,-37,63,0,7,0,-64,51,-64,0,6,0,37,52,50,0,6,1,51,53,-62,0,5,1, 39,54,52,0,5,2,53,55,-60,0,4,2,41,56,54,0,4,3,55,57,-58,0,3,3,43,58,56,0,3,4,57, 59,-56,0,2,4,45,60,58,0,2,5,59,61,-54,0,1,5,47,62,60,0,1,6,61,63,-52,0,0,6,49, 64,62,0,0,7,63,-50,-50 } function Ancient.cryptf1(a) local b = cryptt[a*6-5] local c = cryptt[a*6-4] local d = cryptt[a*6-3] if not (b + c + d == 6) then return {{(b + 1)/cryptc, c/cryptc, d/cryptc},{b/cryptc, (c + 1)/cryptc, d/cryptc},{b/cryptc, c/cryptc, (d + 1)/cryptc}} else return {{b/cryptc, (c + 1)/cryptc, (d + 1)/cryptc},{(b + 1)/cryptc, c/cryptc, (d + 1)/cryptc},{(b + 1)/cryptc, (c + 1)/cryptc, d/cryptc}} end end function Ancient.cryptf2(a,b,c,d) local e = {a[1],a[2],a[3]} local f = {b[1],b[2],b[3]} local g = {c[1],c[2],c[3]} if d then for _, h in pairs(d) do local w = Ancient.cryptf1(h) local n2a = { e[1] * w[1][1] + f[1] * w[1][2] + g[1] * w[1][3], e[2] * w[1][1] + f[2] * w[1][2] + g[2] * w[1][3], e[3] * w[1][1] + f[3] * w[1][2] + g[3] * w[1][3] } local n2b = { e[1] * w[2][1] + f[1] * w[2][2] + g[1] * w[2][3], e[2] * w[2][1] + f[2] * w[2][2] + g[2] * w[2][3], e[3] * w[2][1] + f[3] * w[2][2] + g[3] * w[2][3] } local n2c = { e[1] * w[3][1] + f[1] * w[3][2] + g[1] * w[3][3], e[2] * w[3][1] + f[2] * w[3][2] + g[2] * w[3][3], e[3] * w[3][1] + f[3] * w[3][2] + g[3] * w[3][3] } e = n2a f = n2b g = n2c end end return {e, f, g} end function Ancient.cryptf3 (a) local b = math.sqrt(a[1]*a[1] + a[2]*a[2] + a[3]*a[3]) return {a[1]/b, a[2]/b, a[3]/b} end function Ancient.cryptf4(a, b) local c = Ancient.cryptf5(a) local d = Ancient.cryptf2(c[1],c[2],c[3],b) return Ancient.cryptf3({ (d[1][1] + d[2][1] + d[3][1])/3, (d[1][2] + d[2][2] + d[3][2])/3, (d[1][3] + d[2][3] + d[3][3])/3 }) end function Ancient.cryptf4b(a) local b = Ancient.gtf(a[1]) local c = {} for i, j in pairs(a) do if i ~= 1 then table.insert(c, Ancient.gtt(j)) end end return Ancient.cryptf4(b, c) end function Ancient.cryptf5(a) local b = cryptv[a*3-2] local c = cryptv[a*3-1] local d = cryptv[a*3] return { Ancient.cryptf3({cryptx[b*3-2], cryptx[b*3-1], cryptx[b*3]}), Ancient.cryptf3({cryptx[c*3-2], cryptx[c*3-1], cryptx[c*3]}), Ancient.cryptf3({cryptx[d*3-2], cryptx[d*3-1], cryptx[d*3]})} end function Ancient.ftg(a) if not global.ftg then local ftg = {} for i = 1, crypti, 1 do ftg[i] = i end Util.shuffle(ftg) global.ftg = ftg end if a then return global.ftg[a] end end function Ancient.gtf(a) if not global.gtf then Ancient.ftg() local gtf = {} for i, j in pairs(global.ftg) do gtf[j] = i end global.gtf = gtf end if a then return global.gtf[a] end end function Ancient.gtt(a) if not global.gtt then local gtt = {} for i = 2, crypti+3, 1 do if not(i == 31 or i == 50) then gtt[#gtt+1] = i end end Util.shuffle(gtt) gtt[#gtt+1] = #gtt-10 gtt[#gtt+1] = #gtt+3 gtt[#gtt+1] = 1 gtt[#gtt+1] = (#gtt-1)/2 global.gtt = gtt end if a then return global.gtt[a] end end function Ancient.ttg(a) if not global.ttg then Ancient.gtt() local ttg = {} for i, j in pairs(global.gtt) do ttg[j] = i end global.ttg = ttg end if a then return global.ttg[a] end end function Ancient.cryptf6() if global.hcoord then return end Ancient.ftg() Ancient.gtt() local a = {} for i = 1, crypti, 1 do a[i] = i end Util.shuffle(a) local gdp = a[crypti] local gdpf = Ancient.gtf(gdp) a[crypti] = crypti+1 a[crypti+1] = crypti+2 a[crypti+2] = crypti+3 a[crypti+3] = crypti+4 Util.shuffle(a) local gda = {} local gdat = {} local gds = gdp for i = 1, cryptc-1, 1 do gda[i] = a[i] gdat[i] = Ancient.gtt(a[i]) gds = gds .. "|" .. a[i] end global.hcoord = Ancient.cryptf4(gdpf, gdat) global.gds = sha2.hash256(gds) local vgo = {} for i, j in pairs(gda) do if j <= 60 then vgo[#vgo + 1] = j end end local b = Ancient.ftg(cryptn[(gdpf-1)*crypte + math.random(1,crypte)]) if not Util.table_contains(vgo, b) then vgo[#vgo + 1] = b end while #vgo < 20 do local c = math.random(1,60) if c ~= gdp and not Util.table_contains(vgo, c) then vgo[#vgo + 1] = c end end Util.shuffle(vgo) local d = math.random(41,crypti) local e = table.deepcopy(global.ftg) Util.shuffle(e) for i, j in pairs(e) do if #vgo == d - 1 then vgo[#vgo + 1] = gdp end if j ~= gdp and not Util.table_contains(vgo, j)then vgo[#vgo + 1] = j end end global.vgo = vgo local gco = {} local f = {gdp} for i = 1, crypte, 1 do f[#f + 1] = Ancient.ftg(cryptn[(gdpf-1)*crypte+i]) end for i = 1, crypti, 1 do if not Util.table_contains(f, i) then gco[#gco+1] = i end end Util.shuffle(gco) for i = 31, crypti, 1 do f[#f+1] = gco[i] gco[i] = nil end Util.shuffle(f) for i, j in pairs(f) do gco[#gco+1] = j end global.gco = gco end function Ancient.cryptf7(a) a = table.deepcopy(a) for b,c in pairs(a) do a[b]=c*-1 end return a end function Ancient.place_cartouche_a(surface, glyph, position) local x = position.x or position[1] local y = position.y or position[2] surface.request_to_generate_chunks({x,y}, 1) surface.force_generate_chunk_requests() local entity entity = surface.create_entity{ name = mod_prefix .. "cartouche-a", position = {x,y} } entity.destructible = false entity = surface.create_entity{ name = mod_prefix .. "glyph-a-" .. glyph , position = {x,y-6/32} } entity.destructible = false for j = 1, crypte, 1 do local k = cryptn[(Ancient.gtf(glyph)-1) * crypte + crypts[j]] local jy = Util.cos((j-1)/crypte * 2 * Util.pi) * 4.5 local jx = Util.sin((j-1)/crypte * 2 * Util.pi) * 6.32 entity = surface.create_entity{ name = mod_prefix .. "glyph-a-" .. Ancient.ftg(k).."-small", position = {x + jx, y + jy - 4/32} } entity.destructible = false end end function Ancient.place_cartouche_b(surface, glyph, position) local entity local x = position.x or position[1] local y = position.y or position[2] local tes = Ancient.gtt(glyph) surface.request_to_generate_chunks({x,y}, 1) surface.force_generate_chunk_requests() if cryptt[tes*6-5] + cryptt[tes*6-4] + cryptt[tes*6-3] > 6 then entity = surface.create_entity{ name = mod_prefix .. "cartouche-b-a", position = {x,y} } entity.destructible = false entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. tes, position = {x,y-cryptc/32} } entity.destructible = false if cryptt[tes*6-2] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[tes*6-2].."-small", position = {x-1.6, y-0.5} } entity.destructible = false end if cryptt[tes*6-1] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[tes*6-1] .."-small", position = {x+1.6, y-0.5} } entity.destructible = false end if cryptt[tes*6] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[tes*6] .."-small", position = {x, y+1.5} } entity.destructible = false end else entity = surface.create_entity{ name = mod_prefix .. "cartouche-b-b", position = {x,y} } entity.destructible = false entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. tes, position = {x,y+4/32} } entity.destructible = false if cryptt[tes*6-2] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[tes*6-2].."-small", position = {x, y-1.5} } entity.destructible = false end if cryptt[tes*6-1] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[tes*6-1] .."-small", position = {x+1.6, y+0.5} } entity.destructible = false end if cryptt[tes*6] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[tes*6] .."-small", position = {x-1.6, y+0.5} } entity.destructible = false end end end function Ancient.assign_zone_next_glyph(zone) if not(zone.type == "planet" and zone.glyph==nil) then return end if zone.name == "Nauvis" or zone.is_homeworld or zone.ruins then return end Ancient.cryptf6() for _, g in pairs(global.vgo) do global.glyph_vaults = global.glyph_vaults or {} if not global.glyph_vaults[g] then zone.glyph = g global.glyph_vaults[g] = {} global.glyph_vaults[g][zone.index] = { glyph = g, zone_index = zone.index } if zone.surface_index then Ancient.make_vault_exterior(zone) end return end end end function Ancient.make_vault_exterior(zone) if zone.glyph == nil or zone.surface_index == nil then return end if zone.vault_pyramid and (not zone.vault_pyramid.valid) then zone.vault_pyramid = nil end if zone.vault_pyramid then return end local zone_surface = Zone.get_make_surface(zone) if not zone.seed then zone.seed = zone_surface.map_gen_settings.seed end local zrng = game.create_random_generator(zone.seed) local glyph = zone.glyph local pyramid_pos = zone.vault_pyramid_position or nil if not pyramid_pos then local base_pos for i = 1, 4, 1 do base_pos = {zrng(-256,256),zrng(-256,256)} zone_surface.request_to_generate_chunks(base_pos, 4) zone_surface.force_generate_chunk_requests() pyramid_pos = zone_surface.find_non_colliding_position(mod_prefix .. "pyramid-a", base_pos, 256, 1) if pyramid_pos then break end end if not pyramid_pos then pyramid_pos = base_pos end end local entity = Ancient.vault_entrance_structures[zrng(1,#Ancient.vault_entrance_structures)] local box = game.entity_prototypes[entity].collision_box local area = util.area_add_position(box, pyramid_pos) local entities = zone_surface.find_entities_filtered{ area = area } for _, entity in pairs(entities) do entity.destroy() end local pyramid = zone_surface.create_entity{ name = entity, position = pyramid_pos } pyramid.destructible = false zone.vault_pyramid = pyramid zone.vault_pyramid_position = pyramid_pos end function Ancient.make_vault_interior(zone) if zone.glyph == nil or zone.vault_pyramid == nil then return end if global.glyph_vaults[zone.glyph][zone.index].surface_index and game.surfaces[global.glyph_vaults[zone.glyph][zone.index].surface_index] then return -- already exists end local glyph = zone.glyph local surface_name = Ancient.vault_surface_name(zone, glyph) if game.surfaces[surface_name] then global.glyph_vaults[glyph][zone.index].surface_index = game.surfaces[surface_name].index return end local tile = "mineral-beige-dirt-1" local map_gen_settings = { autoplace_controls = { ["planet-size"] = { frequency = 1/1000, size = 1 } } } map_gen_settings.seed = glyph * 10000000 map_gen_settings.cliff_settings = {richness = 0} map_gen_settings.autoplace_settings={ ["decorative"]={ treat_missing_as_default=false, settings={ ['rock-medium-beige'] = {}, ['rock-small-beige'] = {}, ['rock-tiny-beige'] = {} } }, ["entity"]={ treat_missing_as_default=false, settings={ ['rock-huge-beige'] = {}, ['rock-big-beige'] = {}, ['biter-spawner'] = {}, ['spitter-spawner'] = {}, } }, ["tile"]={ treat_missing_as_default=false, settings={ --[mod_prefix.. "regolith"]={}, [tile]={}, ["out-of-map"]={} } }, } map_gen_settings.property_expression_names = { ["tile:"..tile..":probability"] = "vault-land-probability", ["tile:out-of-map:probability"] = 0, ["entity:biter-spawner:probability"] = 0, ["entity:spitter-spawner:probability"] = 0, } local surface = game.create_surface(surface_name, map_gen_settings) surface.freeze_daytime = true surface.daytime = 0.5 -- night surface.min_brightness = 0.02 surface.request_to_generate_chunks({0,0}, 2) surface.request_to_generate_chunks({0,32*1}, 2) surface.request_to_generate_chunks({0,32*2}, 2) surface.force_generate_chunk_requests() map_gen_settings.property_expression_names["entity:biter-spawner:probability"] = 0.01 surface.map_gen_settings = map_gen_settings surface.regenerate_entity({"biter-spawner"}) map_gen_settings.property_expression_names["entity:spitter-spawner:probability"] = 0.05 surface.map_gen_settings = map_gen_settings surface.regenerate_entity({"spitter-spawner"}) map_gen_settings.property_expression_names["entity:biter-spawner:probability"] = 0.05 surface.map_gen_settings = map_gen_settings local entities = surface.find_entities_filtered{ force = "enemy", area = {{-9,-11},{9,Ancient.cartouche_path_wall_end}} } for _, entity in pairs(entities) do entity.destroy() end local tiles = {} for i = -Ancient.cartouche_path_width/2,Ancient.cartouche_path_width/2,1 do for j = Ancient.cartouche_path_start,Ancient.cartouche_path_wall_start,1 do table.insert(tiles, {name = tile, position = {x=i,y=j}}) end end for i = -Ancient.cartouche_path_wall_width/2,Ancient.cartouche_path_wall_width/2,1 do for j = Ancient.cartouche_path_wall_start+1,Ancient.cartouche_path_end,1 do if i >= -Ancient.cartouche_path_width/2 and i <= Ancient.cartouche_path_width/2 then table.insert(tiles, {name = tile, position = {x=i,y=j}}) else table.insert(tiles, {name = "out-of-map", position = {x=i,y=j}}) end end end for i = -Ancient.cartouche_path_wall_width/2,Ancient.cartouche_path_wall_width/2,1 do for j = Ancient.cartouche_path_end+1,Ancient.cartouche_path_wall_end,1 do table.insert(tiles, {name = "out-of-map", position = {x=i,y=j}}) end end surface.set_tiles(tiles, true) local light = surface.create_entity{ name="se-lightbeam-a", position = {0,Ancient.cartouche_path_end}, target={0,0}, speed = 0 } light.destructible = false Ancient.place_cartouche_a(surface, glyph, {x=0,y=-6}) Ancient.place_cartouche_b(surface, glyph, {x=0,y=4}) local items = {"productivity-module-", "speed-module-", "effectivity-module-"} local chest = surface.create_entity{ name = mod_prefix .. "cartouche-chest", position = {0, -14}, force = "neutral" } chest.destructible = false -- mark that the module has been generated global.glyph_vaults_made_loot = global.glyph_vaults_made_loot or {} if not global.glyph_vaults_made_loot[glyph] then chest.insert({name = items[Ancient.gtf(zone.glyph)%#items+1].."9", amount = 1}) global.glyph_vaults_made_loot[glyph] = true end global.glyph_vaults[glyph][zone.index].surface_index = surface.index end function Ancient.vault_surface_name(zone, glyph) if not glyph then glyph = zone.glyph end return "Vault "..zone.index.."."..glyph end function Ancient.vault_from_surface(surface) if string.find(surface.name, "Vault ", 1, true) then for glyph, vaults in pairs(global.glyph_vaults) do for zone_index, try_vault in pairs(vaults) do if try_vault.surface_index == surface.index then return try_vault end end end end end function Ancient.make_test_surface() if game.surfaces["vault-test"] then game.delete_surface("vault-test") end Ancient.ftg() local map_gen_settings = { autoplace_controls = { ["planet-size"] = { frequency = 1/1000, size = 1 } } } map_gen_settings.autoplace_settings={ ["decorative"]={ treat_missing_as_default=false, settings={ ['rock-medium-beige'] = {}, ['rock-small-beige'] = {}, ['rock-tiny-beige'] = {} } }, ["entity"]={ treat_missing_as_default=false, settings={ ['rock-huge-beige'] = {}, ['rock-big-beige'] = {}, } }, ["tile"]={ treat_missing_as_default=false, settings={ --[mod_prefix.. "regolith"]={}, ["mineral-beige-dirt-1"]={}, ["out-of-map"]={} } }, } map_gen_settings.property_expression_names = { ["tile:mineral-beige-dirt-1:probability"] = "vault-land-probability", ["tile:out-of-map:probability"] = 0 } local surface = game.create_surface("vault-test", map_gen_settings) surface.freeze_daytime = true surface.daytime = 0.5 -- night surface.request_to_generate_chunks({0,0}, 1) surface.force_generate_chunk_requests() game.players[1].teleport({0,0}, surface) local entity for k = 1, crypti, 1 do local x = (k-1)%cryptc * 16 - 200 local y = math.floor((k-1)/cryptc)* 20 surface.request_to_generate_chunks({x,y}, 1) surface.force_generate_chunk_requests() entity = surface.create_entity{ name = mod_prefix .. "cartouche-a", position = {x,y} } entity.destructible = false entity = surface.create_entity{ name = mod_prefix .. "glyph-a-" .. Ancient.ftg(k), position = {x,y-6/32} } entity.destructible = false for j = 1, crypte, 1 do local k = cryptn[(k-1) * crypte + crypts[j]] local jy = Util.cos((j-1)/crypte * 2 * Util.pi) * 4.5 local jx = Util.sin((j-1)/crypte * 2 * Util.pi) * 6.32 entity = surface.create_entity{ name = mod_prefix .. "glyph-a-" .. Ancient.ftg(k).."-small", position = {x + jx, y + jy - 4/32} } entity.destructible = false end y = y + 8 i = Ancient.gtt(Ancient.ftg(k)) surface.request_to_generate_chunks({x,y}, 1) surface.force_generate_chunk_requests() if cryptt[i*6-5] + cryptt[i*6-4] + cryptt[i*6-3] > 6 then entity = surface.create_entity{ name = mod_prefix .. "cartouche-b-a", position = {x,y} } entity.destructible = false entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. i, position = {x,y-cryptc/32} } entity.destructible = false if cryptt[i*6-2] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[i*6-2].."-small", position = {x-1.6, y-0.5} } entity.destructible = false end if cryptt[i*6-1] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[i*6-1] .."-small", position = {x+1.6, y-0.5} } entity.destructible = false end if cryptt[i*6] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[i*6] .."-small", position = {x, y+1.5} } entity.destructible = false end else entity = surface.create_entity{ name = mod_prefix .. "cartouche-b-b", position = {x,y} } entity.destructible = false entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. i, position = {x,y+4/32} } entity.destructible = false if cryptt[i*6-2] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[i*6-2].."-small", position = {x, y-1.5} } entity.destructible = false end if cryptt[i*6-1] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[i*6-1] .."-small", position = {x+1.6, y+0.5} } entity.destructible = false end if cryptt[i*6] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[i*6] .."-small", position = {x-1.6, y+0.5} } entity.destructible = false end end end for i = 1, crypti, 1 do local x = (i-1)%cryptc * 16 local y = math.floor((i-1)/cryptc)* 12 surface.request_to_generate_chunks({x,y}, 1) surface.force_generate_chunk_requests() entity = surface.create_entity{ name = mod_prefix .. "cartouche-a", position = {x,y} } entity.destructible = false entity = surface.create_entity{ name = mod_prefix .. "glyph-a-" .. Ancient.ftg(i), position = {x,y-6/32} } entity.destructible = false for j = 1, crypte, 1 do local k = cryptn[(i-1) * crypte + crypts[j]] local jy = Util.cos((j-1)/crypte * 2 * Util.pi) * 4.5 local jx = Util.sin((j-1)/crypte * 2 * Util.pi) * 6.32 entity = surface.create_entity{ name = mod_prefix .. "glyph-a-" .. Ancient.ftg(k).."-small", position = {x + jx, y + jy - 4/32} } entity.destructible = false end end for i = 1, crypti+4, 1 do local x = -16 - (i-1)%cryptc * cryptc local y = math.floor((i-1)/cryptc)* 5 y = - 16 - cryptt[i*6-5] * 5 x = (-cryptt[i*6-4] + cryptt[i*6-3]) * 8 surface.request_to_generate_chunks({x,y}, 1) surface.force_generate_chunk_requests() if cryptt[i*6-5] + cryptt[i*6-4] + cryptt[i*6-3] > 6 then entity = surface.create_entity{ name = mod_prefix .. "cartouche-b-a", position = {x,y} } entity.destructible = false entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. i, position = {x,y-cryptc/32} } entity.destructible = false if cryptt[i*6-2] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[i*6-2].."-small", position = {x-1.6, y-0.5} } entity.destructible = false end if cryptt[i*6-1] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[i*6-1] .."-small", position = {x+1.6, y-0.5} } entity.destructible = false end if cryptt[i*6] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[i*6] .."-small", position = {x, y+1.5} } entity.destructible = false end else entity = surface.create_entity{ name = mod_prefix .. "cartouche-b-b", position = {x,y} } entity.destructible = false entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. i, position = {x,y+4/32} } entity.destructible = false if cryptt[i*6-2] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[i*6-2].."-small", position = {x, y-1.5} } entity.destructible = false end if cryptt[i*6-1] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[i*6-1] .."-small", position = {x+1.6, y+0.5} } entity.destructible = false end if cryptt[i*6] > 0 then entity = surface.create_entity{ name = mod_prefix .. "glyph-b-" .. cryptt[i*6] .."-small", position = {x-1.6, y+0.5} } entity.destructible = false end end end return surface end function Ancient.make_gate_blockers(surface, position, set, name) for y, row in pairs(set) do for _, start_end in pairs(row) do for x = start_end[1], start_end[2]-1, 1 do local entity = surface.create_entity{ name = name, position = {x = position.x + x, y = position.y + y} } entity.destructible = false end end end end function Ancient.make_gate_phase_1_blockers(surface, position) Ancient.make_gate_blockers(surface, position, Ancient.gate_blockers_phase_1, Ancient.name_gate_blocker) end function Ancient.make_gate_phase_1_void_blockers(surface, position) Ancient.make_gate_blockers(surface, position, Ancient.gate_blockers_void_phase_1, Ancient.name_gate_blocker_void) end function Ancient.make_gate_phase_2_blockers(surface, position) Ancient.make_gate_blockers(surface, position, Ancient.gate_blockers_phase_2, Ancient.name_gate_blocker) end function Ancient.make_gate_phase_2_void_blockers(surface, position) Ancient.make_gate_blockers(surface, position, Ancient.gate_blockers_void_phase_2, Ancient.name_gate_blocker_void) end function Ancient.make_gate(position) -- gate middle X tile is effectivly at +0.5 -- gate middle is along the actual y Ancient.cryptf6() local gate = { status = "fragments", status_progress = 0, rotation = 0, rotation_velocity = 0, -- -1 to 1 rotation_direction = 0, -- -1 to 1 } global.gate = gate gate.position = position local zone = Zone.from_name("Foenestra") local surface = Zone.get_make_surface(zone) gate.surface = surface gate.void_sprite = rendering.draw_sprite({ sprite= Ancient.name_gate_void_sprite, --sprite = "file/__space-exploration-graphics__/graphics/entity/gate/hr/void.png", --sprite = "virtual-signal.se-star", surface = surface, x_scale = 4, y_scale = 4, render_layer = "28", -- just above decals target = position, }) Ancient.make_gate_phase_1_blockers(surface, position) Ancient.make_gate_phase_1_void_blockers(surface, position) for fragment_name, fragment in pairs(Ancient.gate_fragments) do local entity = surface.create_entity{ name = fragment_name, position = {x = position.x + fragment.position.x, y = position.y + fragment.position.y} } entity.destructible = false end end function Ancient.check_gate_fragments() local gate = global.gate if not (gate and gate.status == "fragments") then return end local zone = Zone.from_name("Foenestra") local surface = Zone.get_make_surface(zone) for fragment_name, fragment in pairs(Ancient.gate_fragments) do if fragment.placeable then local entity = surface.find_entity(fragment_name, { x = gate.position.x + fragment.required_position[1], y = gate.position.y + fragment.required_position[2] }) if not entity then return end end end Ancient.gate_phase_2(gate) end function Ancient.gate_phase_2(gate) gate.status = "scaffold" local surface = gate.surface -- all here local fragment_names = {} for fragment_name, fragment in pairs(Ancient.gate_fragments) do table.insert(fragment_names, fragment_name) end local entities = surface.find_entities_filtered{name = fragment_names} for _, entity in pairs(entities) do entity.destroy() end Ancient.make_gate_phase_2_blockers(surface, gate.position) Ancient.make_gate_phase_2_void_blockers(surface, gate.position) for part_name, position in pairs(Ancient.gate_parts_main) do local entity = surface.create_entity{ name = part_name, position = {x = gate.position.x + position[1], y = gate.position.y + position[2]} } entity.destructible = false end for part_name, position in pairs(Ancient.gate_parts_main_shadow) do local entity = surface.create_entity{ name = part_name, position = {x = gate.position.x + position[1], y = gate.position.y + position[2]} } entity.destructible = false end for part_name, position in pairs(Ancient.gate_parts_underlay) do local entity = surface.create_entity{ name = part_name, position = {x = gate.position.x + position[1], y = gate.position.y + position[2]} } entity.destructible = false end local entity = surface.create_entity{ name = Ancient.name_gate_light_middle, target = {x = gate.position.x, y = gate.position.y + 1}, position = {x = gate.position.x, y = gate.position.y}, speed = 0 } entity.destructible = false gate.lock_switches = {} local i = 0 for part_name, position in pairs(Ancient.gate_parts_rails) do i = i + 1 local entity = surface.create_entity{ name = part_name, position = {x = gate.position.x + position[1], y = gate.position.y + position[2]} } entity.destructible = false local entity = surface.create_entity{ name = Ancient.name_gate_light, target = {x = gate.position.x + position[1], y = gate.position.y + position[2] + 1}, position = {x = gate.position.x + position[1], y = gate.position.y + position[2]}, speed = 0 } entity.destructible = false gate.lock_switches[i] = surface.create_entity{ name = Ancient.name_gate_lock_switch, position = {x = gate.position.x + position[1], y = gate.position.y + position[2]}, force = "neutral" } gate.lock_switches[i].destructible = false end gate.shunts = {} for i, part in pairs(Ancient.gate_parts_shunts) do gate.shunts[i] = surface.create_entity{ name = part.name, position = {x = gate.position.x + part.position[1], y = gate.position.y + part.position[2]} } gate.shunts[i].destructible = false end gate.platform_scaffold = surface.create_entity{ name = Ancient.gate_parts_platform.name_scaffold, position = {x = gate.position.x + Ancient.gate_parts_platform.position[1], y = gate.position.y + Ancient.gate_parts_platform.position[2]}, force = "neutral" } gate.platform_scaffold.destructible = false Ancient.update_unlocks() end function Ancient.gate_phase_3(gate) local surface = gate.surface gate.status = "unpowered" gate.status_progress = 0 if gate.platform_scaffold and gate.platform_scaffold.valid then -- give back any excess local inv = gate.platform_scaffold.get_inventory(defines.inventory.assembling_machine_input) if not inv.is_empty() then local pos = gate.platform_scaffold.position pos.x = pos.x - 8 pos.y = pos.y - 1 if not (gate.overflow_chest and gate.overflow_chest.valid) then gate.overflow_chest = gate.platform_scaffold.surface.create_entity{ name = "steel-chest", force = gate.platform_scaffold.force, position = pos } end for name, count in pairs(inv.get_contents()) do gate.overflow_chest.insert({name=name, count=count}) end end gate.platform_scaffold.destroy() end gate.platform_scaffold = nil for part_name, position in pairs(Ancient.gate_parts_addons) do local entity = surface.create_entity{ name = part_name, position = {x = gate.position.x + position[1], y = gate.position.y + position[2]} } entity.destructible = false end gate.lock_combinators = {} for i, part in pairs(Ancient.gate_parts_lock_combinators) do gate.lock_combinators[i] = surface.create_entity{ name = Ancient.name_gate_lock_combinator, position = {x = gate.position.x + part.position[1], y = gate.position.y + part.position[2]}, direction = part.direction, force = "neutral" } gate.lock_combinators[i].destructible = false gate.lock_combinators[i].operable = false gate.lock_combinators[i].rotatable = false end gate.lock_fluid_inputs = {} for i, part in pairs(Ancient.gate_parts_lock_fluid_inputs) do gate.lock_fluid_inputs[i] = surface.create_entity{ name = Ancient.name_gate_fluid_input, position = {x = gate.position.x + part.position[1], y = gate.position.y + part.position[2]}, direction = part.direction, force = "neutral" } gate.lock_fluid_inputs[i].destructible = false gate.lock_fluid_inputs[i].rotatable = false end gate.lock_fluid_outputs = {} for i, part in pairs(Ancient.gate_parts_lock_fluid_outputs) do gate.lock_fluid_outputs[i] = surface.create_entity{ name = Ancient.name_gate_fluid_output, position = {x = gate.position.x + part.position[1], y = gate.position.y + part.position[2]}, direction = part.direction, force = "neutral" } gate.lock_fluid_outputs[i].destructible = false gate.lock_fluid_outputs[i].rotatable = false end entity = surface.create_entity{ name = Ancient.gate_parts_platform.name, position = {x = gate.position.x + Ancient.gate_parts_platform.position[1], y = gate.position.y + Ancient.gate_parts_platform.position[2]} } entity.destructible = false gate.platform_combinator = surface.create_entity{ name = Ancient.gate_parts_platform.combinator.name, position = {x = gate.position.x + Ancient.gate_parts_platform.combinator.position[1], y = gate.position.y + Ancient.gate_parts_platform.combinator.position[2]}, direction = defines.direction.east, force = "neutral" } gate.platform_combinator.destructible = false gate.platform_combinator.rotatable = false gate.platform_energy_interfaces = {} gate.platform_energy_interfaces[9] = surface.create_entity{ name = Ancient.gate_parts_platform.energy_interface.name, position = {x = gate.position.x + Ancient.gate_parts_platform.energy_interface.position[1], y = gate.position.y + Ancient.gate_parts_platform.energy_interface.position[2]}, direction = defines.direction.north, force = "neutral" } gate.platform_energy_interfaces[9].destructible = false gate.platform_energy_interfaces[9].rotatable = false gate.buttons = {} gate.buttons.left_switch = surface.create_entity{ name = Ancient.gate_parts_platform.buttons.name_switch, position = { x = gate.position.x + Ancient.gate_parts_platform.buttons.left.switch_position[1], y = gate.position.y + Ancient.gate_parts_platform.buttons.left.switch_position[2]}, force = "neutral" } gate.buttons.left_switch.destructible = false gate.buttons.left_display = surface.create_entity{ name = Ancient.gate_parts_platform.buttons.left.name, position = { x = gate.position.x + Ancient.gate_parts_platform.buttons.left.position[1], y = gate.position.y + Ancient.gate_parts_platform.buttons.left.position[2]} } gate.buttons.left_display.graphics_variation = 1 gate.buttons.left_display.destructible = false gate.buttons.middle_switch = surface.create_entity{ name = Ancient.gate_parts_platform.buttons.name_switch, position = { x = gate.position.x + Ancient.gate_parts_platform.buttons.middle.switch_position[1], y = gate.position.y + Ancient.gate_parts_platform.buttons.middle.switch_position[2]}, force = "neutral" } gate.buttons.middle_switch.destructible = false gate.buttons.middle_display = surface.create_entity{ name = Ancient.gate_parts_platform.buttons.middle.name, position = { x = gate.position.x + Ancient.gate_parts_platform.buttons.middle.position[1], y = gate.position.y + Ancient.gate_parts_platform.buttons.middle.position[2]} } gate.buttons.middle_display.graphics_variation = 1 gate.buttons.middle_display.destructible = false gate.buttons.right_switch = surface.create_entity{ name = Ancient.gate_parts_platform.buttons.name_switch, position = { x = gate.position.x + Ancient.gate_parts_platform.buttons.right.switch_position[1], y = gate.position.y + Ancient.gate_parts_platform.buttons.right.switch_position[2]}, force = "neutral" } gate.buttons.right_switch.destructible = false gate.buttons.right_display = surface.create_entity{ name = Ancient.gate_parts_platform.buttons.right.name, position = { x = gate.position.x + Ancient.gate_parts_platform.buttons.right.position[1], y = gate.position.y + Ancient.gate_parts_platform.buttons.right.position[2]} } gate.buttons.right_display.graphics_variation = 1 gate.buttons.right_display.destructible = false Ancient.gate_set_glyph_order(gate) gate.glyphs = {} Ancient.update_unlocks() end function Ancient.gate_set_glyph_order(gate) if gate.glyph_order then return end local glyph_order = {} for i = 1,64,1 do glyph_order[i]=i end Util.shuffle(glyph_order) gate.glyph_order = glyph_order end function Ancient.gate_update_indicators_anchor(gate) gate.indicators = gate.indicators or {} gate.indicators.anchor = gate.indicators.anchor or {} gate.indicators.anchor.statuses = gate.indicators.anchor.statuses or {} gate.indicators.anchor.entities = gate.indicators.anchor.entities or {} local anchors = 0 local active_anchors = 0 if global.dimensional_anchors then for zone_index, anchor in pairs(global.dimensional_anchors) do anchors = anchors + 1 if anchor.active then active_anchors = active_anchors + 1 end end end for i = 1,8,1 do local status = 1 if anchors >= i then status = 2 end if active_anchors >= i then status = 3 end if gate.indicators.anchor.statuses[i] ~= status then gate.indicators.anchor.statuses[i] = status if gate.indicators.anchor.entities[i] and gate.indicators.anchor.entities[i] then gate.indicators.anchor.entities[i].destroy() end gate.indicators.anchor.entities[i] = gate.surface.create_entity{ name = Ancient.gate_parts_platform.indicators.names[status], position = { x = gate.position.x + Ancient.gate_parts_platform.indicators.x_start + Ancient.gate_parts_platform.indicators.x_spacing * (i - 1), y = gate.position.y + Ancient.gate_parts_platform.indicators.anchor_y} } end end end function Ancient.gate_update_indicators_temperature(gate) gate.indicators = gate.indicators or {} gate.indicators.temperature = gate.indicators.temperature or {} gate.indicators.temperature.statuses = gate.indicators.temperature.statuses or {} gate.indicators.temperature.entities = gate.indicators.temperature.entities or {} for i = 1,8,1 do local status = 1 if gate.lock_temperatures and gate.lock_temperatures[i] and gate.lock_temperatures[i] <= Ancient.gate_temperature_partial then status = 2 end if gate.lock_temperatures and gate.lock_temperatures[i] and gate.lock_temperatures[i] <= Ancient.gate_temperature_required then status = 3 end if gate.indicators.temperature.statuses[i] ~= status then gate.indicators.temperature.statuses[i] = status if gate.indicators.temperature.entities[i] and gate.indicators.temperature.entities[i] then gate.indicators.temperature.entities[i].destroy() end gate.indicators.temperature.entities[i] = gate.surface.create_entity{ name = Ancient.gate_parts_platform.indicators.names[status], position = { x = gate.position.x + Ancient.gate_parts_platform.indicators.x_start + Ancient.gate_parts_platform.indicators.x_spacing * (i - 1), y = gate.position.y + Ancient.gate_parts_platform.indicators.temperature_y} } end end end function Ancient.gate_update_indicators_lock(gate) gate.indicators = gate.indicators or {} gate.indicators.lock = gate.indicators.lock or {} gate.indicators.lock.statuses = gate.indicators.lock.statuses or {} gate.indicators.lock.entities = gate.indicators.lock.entities or {} for i = 1,8,1 do local status = 1 if gate.shunts_actions and gate.shunts_actions[i] and gate.shunts_actions[i].active then status = 2 end if gate.locked_glyphs and gate.locked_glyphs[i] then status = 3 end if gate.indicators.lock.statuses[i] ~= status then gate.indicators.lock.statuses[i] = status if gate.indicators.lock.entities[i] and gate.indicators.lock.entities[i] then gate.indicators.lock.entities[i].destroy() end gate.indicators.lock.entities[i] = gate.surface.create_entity{ name = Ancient.gate_parts_platform.indicators.names[status], position = { x = gate.position.x + Ancient.gate_parts_platform.indicators.x_start + Ancient.gate_parts_platform.indicators.x_spacing * (i - 1), y = gate.position.y + Ancient.gate_parts_platform.indicators.lock_y} } end end end function Ancient.gate_update_indicators(gate) -- don't update every frame, once per second is ok if gate.status == "fragments" or gate.status == "scaffold" or gate.status == "unpowered" or gate.status == "powering-up" or gate.status == "powering-down" then local indicators = gate.surface.find_entities_filtered{name=Ancient.gate_parts_platform.indicators.names} for _, indicator in pairs(indicators) do indicator.destroy() end gate.indicators = nil return end Ancient.gate_update_indicators_anchor(gate) Ancient.gate_update_indicators_temperature(gate) Ancient.gate_update_indicators_lock(gate) end function Ancient.gate_set_rotation(gate, direction) if direction == 0 then gate.rotation_direction = 0 gate.buttons.left_display.graphics_variation = 1 gate.buttons.middle_display.graphics_variation = 2 gate.buttons.right_display.graphics_variation = 1 gate.surface.create_entity{ name= Ancient.name_sound_gate_button, position= Ancient.gate_parts_platform.buttons.middle.position, target= gate.position, speed=0 } elseif direction == 1 then gate.rotation_direction = 1 gate.buttons.left_display.graphics_variation = 2 gate.buttons.middle_display.graphics_variation = 1 gate.buttons.right_display.graphics_variation = 1 gate.surface.create_entity{ name= Ancient.name_sound_gate_button, position= Ancient.gate_parts_platform.buttons.left.position, target= gate.position, speed=0 } elseif direction == -1 then gate.rotation_direction = -1 gate.buttons.left_display.graphics_variation = 1 gate.buttons.middle_display.graphics_variation = 1 gate.buttons.right_display.graphics_variation = 2 gate.surface.create_entity{ name= Ancient.name_sound_gate_button, position= Ancient.gate_parts_platform.buttons.right.position, target= gate.position, speed=0 } end end function Ancient.gate_activate_lock(gate, lock_id) gate.shunts_actions = gate.shunts_actions or {} gate.shunts_actions[lock_id] = gate.shunts_actions[lock_id] or { active = false, -- default progress = 0, -- 0 to 1, 1 is lock point, 1-2 is return } if not gate.shunts_actions[lock_id].active == true then gate.shunts_actions[lock_id].active = true gate.surface.create_entity{ name= Ancient.name_sound_gate_lock, position= {x = Ancient.gate_parts_shunts[lock_id].position[1] + gate.position.x, y = Ancient.gate_parts_shunts[lock_id].position[2] + gate.position.y} , target= gate.position, speed=0 } end Ancient.gate_clear_glyph(gate, lock_id) end function Ancient.on_player_rotated_entity(event) if event.entity and event.entity.valid then local entity = event.entity if event.entity.name == Ancient.gate_parts_platform.buttons.name_switch then local gate = global.gate if gate.status == "powered" then if entity == gate.buttons.left_switch then Ancient.gate_set_rotation(gate, 1) end if entity == gate.buttons.middle_switch then Ancient.gate_set_rotation(gate, 0) end if entity == gate.buttons.right_switch then Ancient.gate_set_rotation(gate, -1) end end elseif event.entity.name == Ancient.name_gate_lock_switch then local gate = global.gate if gate.status == "powered" then for i, switch in pairs(gate.lock_switches) do if entity == switch then Ancient.gate_activate_lock(gate, i) end end end end end end Event.addListener(defines.events.on_player_rotated_entity, Ancient.on_player_rotated_entity) function Ancient.on_entity_created(event) local entity if event.entity and event.entity.valid then entity = event.entity end if event.created_entity and event.created_entity.valid then entity = event.created_entity end if not entity then return end if entity.type == "simple-entity" then for fragment_name, fragment in pairs(Ancient.gate_fragments) do if entity.name == fragment_name then local anomaly = Zone.from_name("Foenestra") local anomaly_surface = Zone.get_surface(anomaly) if anomaly_surface and anomaly_surface.index == entity.surface.index then -- valid zone Ancient.check_gate_fragments() return else cancel_entity_creation(entity, event.player_index, "Cannot place here.") return end end end end end Event.addListener(defines.events.on_built_entity, Ancient.on_entity_created) Event.addListener(defines.events.on_robot_built_entity, Ancient.on_entity_created) Event.addListener(defines.events.script_raised_built, Ancient.on_entity_created) Event.addListener(defines.events.script_raised_revive, Ancient.on_entity_created) function Ancient.gate_begin_power_down(gate) gate.status = "powering-down" gate.status_progress = 0 gate.portal_leads_to = nil for j, sound_position in pairs(Ancient.gate_sound_positions) do gate.surface.create_entity{ name= Ancient.name_sound_gate_power_down, position= {x = sound_position[1] + gate.position.x, y = sound_position[2] + gate.position.y}, target= gate.position, speed=0 } end gate.rotation_velocity = 0 gate.rotation_direction = 0 Ancient.gate_remove_rotation_sounds(gate) Ancient.gate_remove_powered_sounds(gate) -- removed locked glyphs gate.locked_glyphs = {} if gate.locked_glyphs_entities then for _, entity in pairs(gate.locked_glyphs_entities) do if entity and entity.valid then entity.destroy() end end end -- removed extra power draw for i, entity in pairs(gate.platform_energy_interfaces) do if i ~= 9 then entity.destroy() gate.platform_energy_interfaces[i] = nil end end end function Ancient.gate_begin_power_up(gate) gate.queue_power_down = false gate.status = "powering-up" gate.status_progress = 0 for j, sound_position in pairs(Ancient.gate_sound_positions) do gate.surface.create_entity{ name= Ancient.name_sound_gate_power_up, position= {x = sound_position[1] + gate.position.x, y = sound_position[2] + gate.position.y}, target= gate.position, speed=0 } end end function Ancient.gate_power_up_complete(gate) gate.status = "powered" gate.status_progress = 0 Ancient.gate_update_indicators(gate) gate.powered_sounds = {} for j, sound_position in pairs(Ancient.gate_sound_positions) do gate.powered_sounds[j] = gate.surface.create_entity{ name= Ancient.name_sound_gate_power_on, position= {x = sound_position[1] + gate.position.x, y = sound_position[2] + gate.position.y}, target= gate.position, speed=0 } end end function Ancient.gate_evaluate_power(gate) local energy = 0 local energy_capacity = 0 for i, energy_interface in pairs(gate.platform_energy_interfaces) do energy = energy + energy_interface.energy energy_capacity = energy_capacity + energy_interface.prototype.electric_energy_source_prototype.buffer_capacity energy_interface.power_usage = Ancient.unit_power_draw end -- buffer capacity was reduced from local energy_of_required = energy/energy_capacity if energy_of_required < 0.99 then if gate.status == "powered" then Ancient.gate_begin_power_down(gate) gate.surface.print("Gate tried to draw more power than available.") else gate.queue_power_down = true end return end -- has power if gate.status == "unpowered" then Ancient.gate_begin_power_up(gate) end end function Ancient.gate_remove_powered_sounds(gate) if gate.powered_sounds then for _, sound in pairs(gate.powered_sounds) do if sound and sound.valid then sound.destroy() end end gate.powered_sounds = nil end end function Ancient.gate_remove_rotation_sounds(gate) if gate.rotation_sounds then for _, sound in pairs(gate.rotation_sounds) do if sound and sound.valid then sound.destroy() end end gate.rotation_sounds = nil end end function Ancient.gate_position_glyph(gate, glyph, index) glyph.teleport({ x = gate.position.x + Ancient.gate_glyphs_x - math.sin(2*math.pi*(index/64+gate.rotation/64))*Ancient.gate_glyphs_x_mult, y = gate.position.y + Ancient.gate_glyphs_y + math.cos(2*math.pi*(index/64+gate.rotation/64))*Ancient.gate_glyphs_y_mult }) end function Ancient.gate_position_glyphs(gate) if gate.glyphs then for i, glyph in pairs(gate.glyphs) do Ancient.gate_position_glyph(gate, glyph, i) end end end function Ancient.gate_update_temperatures(gate) gate.lock_temperatures = gate.lock_temperatures or {} for i = 1, 8, 1 do gate.lock_temperatures[i] = gate.lock_temperatures[i] or Ancient.gate_temperature_resting local diff = gate.lock_temperatures[i] - Ancient.gate_temperature_resting local change = -diff * Ancient.gate_temperature_return_per_tick if gate.status ~= "powering-down" and gate.status ~= "unpowered" then change = change + Ancient.gate_temperature_while_powered if gate.rotation_direction ~= 0 then change = change + Ancient.gate_temperature_while_turning end if gate.status == "opening-portal" or gate.status == "portal-open" then change = change + Ancient.gate_temperature_while_portal end if gate.locked_glyphs and gate.locked_glyphs[i] then change = change + Ancient.gate_temperature_while_locked end end gate.lock_temperatures[i] = gate.lock_temperatures[i] + change if gate.lock_temperatures[i] >= Ancient.gate_temperature_required then local fluid_available = gate.lock_fluid_inputs[i].get_fluid_count() if fluid_available > 0 then local fluid_in_output = gate.lock_fluid_outputs[i].get_fluid_count() -- from gate_temperature_resting to gate_temperature_zero local temp_range = math.abs(Ancient.gate_temperature_zero - Ancient.gate_temperature_resting) local temperature_as_percent = -(gate.lock_temperatures[i] - Ancient.gate_temperature_resting) / temp_range local fluid_efficiency = Util.lerp(Ancient.gate_temperature_per_coolant_max, Ancient.gate_temperature_per_coolant_min, temperature_as_percent) local temperature_drop_goal = (Ancient.gate_temperature_zero - gate.lock_temperatures[i]) / 10 -- don't do all in 1 step local fluid_required = math.min(100, math.max(0, -temperature_drop_goal / fluid_efficiency)) if fluid_required > 0 then local used_fluid = gate.lock_fluid_outputs[i].insert_fluid({name = name_thermofluid_hot, amount = math.min(fluid_available, fluid_required)}) if used_fluid > 0 then gate.lock_fluid_inputs[i].remove_fluid({name = name_thermofluid_supercooled, amount = used_fluid}) gate.lock_temperatures[i] = gate.lock_temperatures[i] - fluid_efficiency * used_fluid end end end end end end function Ancient.on_tick(event) if global.gate then local gate = global.gate if gate.status == "fragments" then -- nothing to do anymore elseif gate.status == "scaffold" then if gate.platform_scaffold.products_finished > 0 then Ancient.gate_phase_3(gate) end else Ancient.gate_evaluate_power(gate) if game.tick % 60 == 0 then Ancient.gate_update_temperatures(gate) Ancient.gate_update_indicators(gate) end if gate.status == "powering-up" then gate.status_progress = gate.status_progress + 1 local glyphs_active = math.min(64, (gate.status_progress - Ancient.timer_power_up_complete) / Ancient.timer_power_up_ghyph_light_interval + 65) gate.glyphs = gate.glyphs or {} if glyphs_active > #gate.glyphs then local i = #gate.glyphs + 1 gate.glyphs[i] = gate.surface.create_entity{ name = Ancient.name_gate_glyph_prefix .. gate.glyph_order[i], position = gate.position } Ancient.gate_position_glyph(gate, gate.glyphs[i], i) -- move to correct place gate.glyphs[i].destructible = false end if gate.status_progress > Ancient.timer_power_up_complete then if gate.queue_power_down == true then Ancient.gate_begin_power_down(gate) else Ancient.gate_power_up_complete(gate) end end end if gate.status == "powering-down" then gate.status_progress = gate.status_progress + 1 for _, glyph in pairs(gate.glyphs) do if glyph and glyph.valid then glyph.destroy() end end gate.glyphs = {} if gate.status_progress > Ancient.timer_power_down_complete then gate.status = "unpowered" gate.status_progress = 0 end end if gate.status == "powered" then if gate.rotation_direction == 0 then --gate.rotation_velocity = gate.rotation_velocity + math.min(math.max((gate.rotation_direction-gate.rotation_velocity),-Ancient.gate_decceleration), Ancient.gate_decceleration) if gate.rotation_velocity > 0 then local next_snap = math.ceil(gate.rotation) local next_snap_distance = math.max(0, next_snap - gate.rotation - 0.01) gate.rotation_velocity = gate.rotation_velocity + math.min(math.max((next_snap_distance-gate.rotation_velocity),-Ancient.gate_decceleration), Ancient.gate_acceleration) else local next_snap = math.floor(gate.rotation) local next_snap_distance = math.min(0, next_snap - gate.rotation + 0.01) gate.rotation_velocity = gate.rotation_velocity + math.min(math.max((next_snap_distance-gate.rotation_velocity),-Ancient.gate_acceleration), Ancient.gate_decceleration) end elseif math.abs(gate.rotation_direction-gate.rotation_velocity) >= 1 then gate.rotation_velocity = gate.rotation_velocity + math.min(math.max((gate.rotation_direction-gate.rotation_velocity),-Ancient.gate_decceleration), Ancient.gate_decceleration) else gate.rotation_velocity = gate.rotation_velocity + math.min(math.max((gate.rotation_direction-gate.rotation_velocity),-Ancient.gate_acceleration), Ancient.gate_acceleration) end gate.rotation = gate.rotation + gate.rotation_velocity * Ancient.gate_max_speed if math.abs(gate.rotation_velocity) > 0.01 then if not gate.rotation_sounds then gate.rotation_sounds = {} for j, sound_position in pairs(Ancient.gate_sound_positions) do gate.rotation_sounds[j] = gate.surface.create_entity{ name= Ancient.name_sound_gate_turning, position= {x = sound_position[1] + gate.position.x, y = sound_position[2] + gate.position.y}, target= gate.position, speed=0 } end end elseif gate.rotation_sounds then Ancient.gate_remove_rotation_sounds(gate) end if game.tick % 60 == 0 then Ancient.gate_try_open_portal(gate) end end if gate.status == "powered" or gate.status == "powering-up" then -- gate track rotation Ancient.gate_position_glyphs(gate) end if gate.status == "opening-portal" then gate.status_progress = gate.status_progress + 1 local open_percent = gate.status_progress / 600 rendering.set_x_scale(gate.activation_fx.cloud_1, 2.5 * open_percent) rendering.set_x_scale(gate.activation_fx.cloud_2, 2.5 * open_percent) rendering.set_y_scale(gate.activation_fx.cloud_1, 2 * open_percent) rendering.set_y_scale(gate.activation_fx.cloud_2, 2 * open_percent) for i = 0, 2, 1 do local angle = math.random() * 360 local target_offset = { x = -math.sin(2*math.pi*angle) * 30, y = math.cos(2*math.pi*angle) * 20 } local magnitude = Util.vector_length(target_offset); local target_position = {x = target_offset.x + gate.position.x, y = target_offset.y + gate.position.y} gate.surface.create_entity{ name = (i%2==0) and Ancient.name_gate_spec_white or Ancient.name_gate_spec_cyan, position = Util.lerp_vectors(gate.position, target_position, 0.1), target = target_position, speed = magnitude / 50 * (0.5 + math.random()) } end if gate.status_progress >= 600 then gate.status = "portal-open" gate.status_progress = 0 local coordinate = Ancient.cryptf4b(gate.locked_glyphs) for force_name in pairs(global.forces) do local force = game.forces[force_name] if force and force_name ~= "friendly" and force_name ~= "ignore" and force_name ~= "capture" and table_size(force.players) > 0 and Zone.is_visible_to_force(Zone.from_surface(gate.surface), force_name) then Ancient.add_to_coordinate_logs(force, gate.locked_glyphs, coordinate) end end local string = gate.locked_glyphs[1] for i = 2, 8 do string = string .. "|" .. gate.locked_glyphs[i] end local hash = sha2.hash256(string) game.print({"space-exploration.gate-portal-coordinates", Ancient.coordinate_to_string(coordinate)}) if hash == global.gds or (coordinate[1] == global.hcoord[1] and coordinate[2] == global.hcoord[2] and coordinate[3] == global.hcoord[3]) then gate.portal_leads_to = "home" game.print("The portal is stable and leads to your final destination. Enter the portal to win the game.") else local hash1 = string.sub(hash, 1, 1) if tonumber(hash1) then gate.portal_leads_to = "biter" game.print("Something is coming through the portal.") else game.print("The distortion is unstable. The distortion vector does not lead anywhere.") end end end end if gate.status == "portal-open" then -- TODO: check sequence and show victory screen if correct. -- otherwise chance for gate close or invasion from : biters / robots / ancients if gate.portal_leads_to and gate.queue_power_down ~= true then if gate.portal_leads_to == "home" then -- TODO: look for player in the portal. local characters = gate.surface.find_entities_filtered{type = "character", position = gate.position, radius = 5} if characters and #characters >= 1 then game.set_game_state{ game_finished=true, player_won=true, can_continue=true, victorious_force=characters[1].force } gate.status = "closing-portal" gate.status_progress = 0 gate.portal_leads_to = nil end for _, character in pairs(characters) do if character.player then local playerdata = get_make_playerdata(character.player) if playerdata and not playerdata.gate_victory then playerdata.gate_victory = game.tick character.player.print({"space-exploration.victory-message-gate-player"}) end end end else if game.tick % 10 == 0 then -- assume a biter world for now. local names = { "small-spitter", "small-biter", "medium-spitter", "medium-biter", "big-spitter", "big-biter", "behemoth-spitter", "behemoth-biter", } local name = names[math.random(#names)] local pos = gate.surface.find_non_colliding_position(name, gate.position, 10, 1, false) if pos then gate.surface.create_entity{name = name, position = pos, force = "enemy"} end end end else gate.status = "closing-portal" gate.status_progress = 0 gate.portal_leads_to = nil end end if gate.status == "closing-portal" then gate.status_progress = gate.status_progress + 1 local closed_percent = gate.status_progress / 600 local tint_1 = table.deepcopy(Ancient.gate_cloud_tint_1) local tint_2 = table.deepcopy(Ancient.gate_cloud_tint_2) for a, b in pairs(tint_1) do tint_1[a] = b * (1 - closed_percent) end for a, b in pairs(tint_2) do tint_2[a] = b * (1 - closed_percent) end rendering.set_color(gate.activation_fx.cloud_1, tint_1) rendering.set_color(gate.activation_fx.cloud_2, tint_2) if gate.status_progress >= 600 then Ancient.gate_begin_power_down(gate) end end -- shunts if gate.shunts_actions then for i, action in pairs(gate.shunts_actions) do if action.active then action.progress = action.progress + Ancient.timer_shunt_step if action.progress > Ancient.timer_shunt_glyph_lock and action.progress < (Ancient.timer_shunt_glyph_lock+Ancient.timer_shunt_step) and math.abs(gate.rotation_velocity) < 0.02 and gate.status == "powered" then -- Lock the glyph gate.locked_glyphs = gate.locked_glyphs or {} gate.locked_glyphs_entities = gate.locked_glyphs_entities or {} local glyph = Ancient.gate_get_glyph_at_lock(gate, i) Ancient.gate_lock_glyph(gate, i, glyph) Ancient.gate_update_indicators_lock(gate) end if action.progress > Ancient.timer_shunt_complete then action.progress = 0 action.active = false if not gate.locked_glyphs[i] then if gate.platform_energy_interfaces and gate.platform_energy_interfaces[i] and gate.platform_energy_interfaces[i].valid then gate.platform_energy_interfaces[i].destroy() end gate.platform_energy_interfaces[i] = nil end Ancient.gate_update_indicators(gate) end local track_pos = math.min(1, math.min(action.progress, Ancient.timer_shunt_complete -action.progress)) if action.progress < 1 then track_pos = track_pos * track_pos elseif action.progress > (Ancient.timer_shunt_complete - 1) then --track_pos = math.sqrt(track_pos) end local base_position = util.vectors_add(gate.position, {x = Ancient.gate_parts_shunts[i].position[1], y = Ancient.gate_parts_shunts[i].position[2]}) local locked_position = util.vectors_add(base_position, {x = Ancient.gate_parts_shunts[i].lock_offset[1], y = Ancient.gate_parts_shunts[i].lock_offset[2]}) gate.shunts[i].teleport(util.lerp_vectors(base_position, locked_position, track_pos)) end end end end end end Event.addListener(defines.events.on_tick, Ancient.on_tick) function Ancient.coordinate_to_string(coordinate) return coordinate[1] .. ", "..coordinate[2] .. ", " ..coordinate[3] end function Ancient.glyphs_to_string(glyphs) local glyphs_string = "" for _, glyph_id in pairs(glyphs) do glyphs_string = glyphs_string.."[img=entity/"..mod_prefix.."glyph-a-energy-"..glyph_id.."]" end return glyphs_string end function Ancient.get_coordinate_logs(force) local force_data = global.forces[force.name] if force_data then return force_data.coordinate_logs end end function Ancient.add_to_coordinate_logs(force, glyphs, coordinates) local force_data = global.forces[force.name] if force_data then local coordinate_logs = force_data.coordinate_logs or {} local glyph_coordinate_pair = {glyph_string = Ancient.glyphs_to_string(glyphs), coordinate_string = Ancient.coordinate_to_string(coordinates)} table.insert(coordinate_logs, glyph_coordinate_pair) force_data.coordinate_logs = coordinate_logs end end function Ancient.gate_clear_glyph(gate, lock_id, skip_indicators) gate.locked_glyphs = gate.locked_glyphs or {} gate.locked_glyphs[lock_id] = nil gate.locked_glyphs_entities = gate.locked_glyphs_entities or {} if gate.locked_glyphs_entities[lock_id] and gate.locked_glyphs_entities[lock_id].valid then gate.locked_glyphs_entities[lock_id].destroy() -- remove old end gate.locked_glyphs_entities[lock_id] = nil if not skip_indicators then Ancient.gate_update_indicators_lock(gate) end end function Ancient.gate_lock_glyph(gate, lock_id, glyph) -- real glyph id Ancient.gate_clear_glyph(gate, lock_id, true) if glyph and (lock_id > 1 or Ancient.gtf(glyph)) then gate.locked_glyphs[lock_id] = glyph gate.locked_glyphs_entities[lock_id] = gate.shunts[lock_id].surface.create_entity{ name = Ancient.name_gate_glyph_prefix .. glyph .. Ancient.name_gate_glyph_locked_suffix, -- suffix changes render layer position = { x = gate.position.x + Ancient.gate_parts_locked_glyphs[lock_id][1], y = gate.position.y + Ancient.gate_parts_locked_glyphs[lock_id][2] } } gate.locked_glyphs_entities[lock_id].destructible = false end if not (gate.platform_energy_interfaces[lock_id] and gate.platform_energy_interfaces[lock_id].valid) then gate.platform_energy_interfaces[lock_id] = gate.shunts[lock_id].surface.create_entity{ name = Ancient.gate_parts_platform.energy_interface.name, position = {x = gate.position.x + Ancient.gate_parts_platform.energy_interface.position[1], y = gate.position.y + Ancient.gate_parts_platform.energy_interface.position[2]}, direction = defines.direction.north, force = "neutral" } gate.platform_energy_interfaces[lock_id].destructible = false gate.platform_energy_interfaces[lock_id].rotatable = false gate.platform_energy_interfaces[lock_id].energy = 1000000000000 -- max out to start end Ancient.gate_update_indicators_lock(gate) end function Ancient.gate_try_open_portal(gate) if not (gate.locked_glyphs and gate.lock_temperatures and global.dimensional_anchors) then return end local n_locked = 0 for i = 1, 8, 1 do if not gate.locked_glyphs[i] then return end if not (gate.lock_temperatures[i] and gate.lock_temperatures[i] <= Ancient.gate_temperature_required) then return end end local active_anchors = 0 for zone_index, anchor in pairs(global.dimensional_anchors) do if anchor.active then active_anchors = active_anchors + 1 end end if active_anchors < 8 then return end -- still going, all good gate.status = "opening-portal" gate.status_progress = 0 gate.activation_fx = gate.activation_fx or {} for _, fx in pairs(gate.activation_fx) do rendering.destroy(fx) end gate.activation_fx.cloud_1 = rendering.draw_animation{ animation=Ancient.name_gate_cloud, target=gate.position, surface=gate.surface, x_scale = 2.5 / 100, y_scale = 2 / 100, tint = Ancient.gate_cloud_tint_1, animation_speed = -1 } gate.activation_fx.cloud_2 = rendering.draw_animation{ animation=Ancient.name_gate_cloud, target=gate.position, surface=gate.surface, x_scale = 2.5 / 100, y_scale = 2 / 100, tint = Ancient.gate_cloud_tint_2, animation_speed = 0.5, orientation = 0.5 } end function Ancient.gate_get_glyph_at_lock(gate, lock_id) local lock_rotation = (lock_id-0.5)/8*64 local effective_rotation = (lock_rotation - gate.rotation) local snapped_rotation = math.floor(effective_rotation +0.5) % 64 if snapped_rotation <= 0 then snapped_rotation = snapped_rotation + 64 end local glyph = gate.glyph_order[snapped_rotation] return glyph end function Ancient.on_research_finished(event) local force = event.research.force Ancient.update_force_unlocks(force.name) if event.research.name == Ancient.name_tech_coordinates then local force_data = global.forces[force.name] if force_data then if force.technologies[Ancient.name_tech_coordinates].enabled then local level = force.technologies[Ancient.name_tech_coordinates].level - 1 if force.technologies[Ancient.name_tech_coordinates].researched then level = level + 1 end if level >= 1 then if not force_data.coordinates_discovered then force_data.coordinates_discovered = {} end while level > #force_data.coordinates_discovered do local glyph_id = global.gco[#force_data.coordinates_discovered+1] table.insert(force_data.coordinates_discovered, glyph_id) local coordinate = Ancient.cryptf4b({glyph_id}) force.print({"space-exploration.starmapping-found-constellation", "[img=entity/"..mod_prefix .. "glyph-a-energy-"..glyph_id.."]"}) end end end end end end Event.addListener(defines.events.on_research_finished, Ancient.on_research_finished) function Ancient.update_force_unlocks(force_name) local force = game.forces[force_name] if global.gate and global.gate.status ~= "fragments" then if not force.technologies[Ancient.name_tech_coordinates].enabled then force.technologies[Ancient.name_tech_coordinates].enabled = true force.print({"space-exploration.technology-unlocked", "[img=technology."..Ancient.name_tech_coordinates.."]",{"technology-name."..Ancient.name_tech_coordinates}}) end if not force.technologies[Ancient.name_tech_anchor].enabled then force.print({"space-exploration.technology-unlocked", "[img=technology."..Ancient.name_tech_anchor.."]",{"technology-name."..Ancient.name_tech_anchor}}) force.technologies[Ancient.name_tech_anchor].enabled = true end else force.technologies[Ancient.name_tech_coordinates].enabled = false force.technologies[Ancient.name_tech_anchor].enabled = false end end function Ancient.update_unlocks() for force_name, forcedata in pairs(global.forces) do -- only player forces Ancient.update_force_unlocks(force_name) end end return Ancient