From 4eccdd0a0caff86c5af9c699a180f1f2991aa5e4 Mon Sep 17 00:00:00 2001 From: notnotmelon Date: Thu, 29 Aug 2024 20:39:25 -0500 Subject: [PATCH] fix: fix weird bugs related to the submarine --- lib/data-stage.lua | 14 ++++++++++-- lib/events.lua | 52 +++++++++++++++++++++++++++++++++++++++++++ scripts/drowning.lua | 6 ++++- scripts/submarine.lua | 13 ++++++----- 4 files changed, 77 insertions(+), 8 deletions(-) diff --git a/lib/data-stage.lua b/lib/data-stage.lua index 22564500..3fc75ce5 100644 --- a/lib/data-stage.lua +++ b/lib/data-stage.lua @@ -520,5 +520,15 @@ h2o.disallow_effectivity = function(recipe_categories) end end ----@diagnostic disable-next-line: duplicate-set-field -h2o.on_event = function() end +local delays = {} +for i = 0, 20 do + local n = 2 ^ i + delays[#delays + 1] = { + name = 'notnotmelon-ticked-script-delay-' .. n, + type = 'flying-text', + time_to_live = n, + speed = 0, + localised_name = 'Delayed script execution: ' .. n .. ' ticks' + } +end +data:extend(delays) \ No newline at end of file diff --git a/lib/events.lua b/lib/events.lua index eff8de46..e6e6928c 100644 --- a/lib/events.lua +++ b/lib/events.lua @@ -92,4 +92,56 @@ end for event, _ in pairs(gui_events) do h2o.on_event(event, process_gui_event) +end + +local delayed_functions = {} +---use this to execute a script after a delay +---example: +---h2o.register_delayed_function('my_delayed_func', function(param1, param2, param3) ... end) +---h2o.execute_later('my_delayed_func', 60, param1, param2, param3) +---The above code will execute my_delayed_func after waiting for 60 ticks +---@param function_key string +---@param ticks integer +---@param ... any +function h2o.execute_later(function_key, ticks, ...) + if ticks < 1 or ticks % 1 ~= 0 then error('Invalid delay: ' .. ticks) end + local highest = 1 + for _, n in pairs(powers_of_two) do + if n <= ticks then + highest = n + else + break + end + end + local flying_text = game.surfaces.nauvis.create_entity { + name = 'notnotmelon-ticked-script-delay-' .. highest, + position = {0, 0}, + create_build_effect_smoke = false, + text = '' + } + if not flying_text then error() end + global._delayed_functions = global._delayed_functions or {} + global._delayed_functions[script.register_on_entity_destroyed(flying_text)] = {function_key, ticks - highest, {...}} +end + +h2o.on_event(defines.events.on_entity_destroyed, function(event) + if not global._delayed_functions then return end + local data = global._delayed_functions[event.registration_number] + if not data then return end + global._delayed_functions[event.registration_number] = nil + + local function_key = data[1] + local ticks = data[2] + + if ticks == 0 then + local f = delayed_functions[function_key] + if not f then error('No function found for key: ' .. function_key) end + f(table.unpack(data[3])) + else + h2o.execute_later(function_key, ticks, table.unpack(data[3])) + end +end) + +function h2o.register_delayed_function(key, func) + delayed_functions[key] = func end \ No newline at end of file diff --git a/scripts/drowning.lua b/scripts/drowning.lua index b3237a81..95074a3f 100644 --- a/scripts/drowning.lua +++ b/scripts/drowning.lua @@ -18,7 +18,9 @@ h2o.on_nth_tick(UPDATE_RATE, function() local surface = player.surface local surface_name = surface.name - if surface_name ~= h2o.MARAXSIS_SURFACE_NAME and surface_name ~= h2o.TRENCH_SURFACE_NAME then + local is_maraxsis = surface_name == h2o.MARAXSIS_SURFACE_NAME + local is_trench = surface_name == h2o.TRENCH_SURFACE_NAME + if not is_maraxsis and not is_trench then goto continue end @@ -29,6 +31,8 @@ h2o.on_nth_tick(UPDATE_RATE, function() end local breath = global.breath[player.index] or FULL_BREATH_NUM_TICKS + local breath_loss = UPDATE_RATE + if is_trench then breath_loss = breath_loss * 4 end breath = math.max(0, breath - UPDATE_RATE) global.breath[player.index] = breath diff --git a/scripts/submarine.lua b/scripts/submarine.lua index 178b2d91..390c9a67 100644 --- a/scripts/submarine.lua +++ b/scripts/submarine.lua @@ -21,6 +21,7 @@ local function exit_submarine(event) if not safe_position then return end player.teleport(safe_position) end +h2o.register_delayed_function('exit_submarine', exit_submarine) ---when the player presses 'enter' on a submarine, should it succeed? ---@param player LuaPlayer @@ -62,7 +63,9 @@ local function enter_submarine(player, submarine) else submarine.set_driver(player) end + global.breath[player.index] = nil end +h2o.register_delayed_function('enter_submarine', enter_submarine) ---determines if the submarine should rise to the surface or sink to the bottom. returns nil if surface transfer is impossible ---@param submarine LuaEntity @@ -127,12 +130,12 @@ local function decend_or_ascend(submarine) if passenger then passenger.teleport(target_position, target_surface, true) - enter_submarine(passenger, submarine) + h2o.execute_later('enter_submarine', 1, passenger, submarine) end if driver then driver.teleport(target_position, target_surface, true) - enter_submarine(driver, submarine) + h2o.execute_later('enter_submarine', 1, driver, submarine) end return true @@ -150,7 +153,7 @@ h2o.on_event('toggle-driving', function(event) if submarine and submarines[submarine.name] and selected and selected.valid and selected == submarine then if not decend_or_ascend(submarine) then if surface.name == h2o.TRENCH_SURFACE_NAME then - enter_submarine(player, submarine) + h2o.execute_later('enter_submarine', 1, player, submarine) end end -- case 2: player is not hovering the sub but trying to exit. @@ -158,9 +161,9 @@ h2o.on_event('toggle-driving', function(event) elseif submarine and submarines[submarine.name] and not selected_submarine then if not decend_or_ascend(submarine) then if surface.name == h2o.TRENCH_SURFACE_NAME then - enter_submarine(player, submarine) + h2o.execute_later('enter_submarine', 1, player, submarine) else - exit_submarine(event) + h2o.execute_later('exit_submarine', 1, event) end end -- case 3: player is hovering the sub and trying to enter. the vanilla vechicle enter range is too low for water vehicles so we artificially increase it