Files
gen1recomp/src/core/game3/dive.lua
T
bryanthaboi 690f0cd9a1 TOUCHDOWN
2026-09-27 16:07:31 -04:00

213 lines
7.2 KiB
Lua

-- pokeemerald/src/field_control_avatar.c:940
local Dive = {}
-- pokeemerald/include/constants/map_types.h:9
Dive.MAP_TYPE_UNDERWATER = 5
Dive._task = nil
local function MB() return require("src.core.game3.mb") end
local function mbIs(beh, ...)
if beh == nil then return false end
for i = 1, select("#", ...) do
local id = MB().id((select(i, ...)))
if id ~= nil and beh == id then return true end
end
return false
end
-- pokeemerald/src/metatile_behavior.c:853
function Dive.isDiveable(beh)
return mbIs(beh, "INTERIOR_DEEP_WATER", "DEEP_WATER", "SOOTOPOLIS_DEEP_WATER")
end
-- pokeemerald/src/metatile_behavior.c:863
function Dive.isUnableToEmerge(beh)
return mbIs(beh, "NO_SURFACING", "SEAWEED_NO_SURFACING")
end
local function session()
local Runtime = package.loaded["src.core.game3.runtime"]
return Runtime and Runtime.getSession and Runtime.getSession() or nil
end
local function currentDef()
local Map = package.loaded["src.core.game3.map"]
return Map and Map.currentDef and Map.currentDef() or nil, Map and Map.current or nil
end
function Dive.enabled(sess)
local ok, Capabilities = pcall(require, "src.core.game3.capabilities")
if not ok then return false end
local okH, has = pcall(Capabilities.has, sess or session(), "dive")
return okH and has == true
end
function Dive.isUnderwaterMap(def)
return type(def) == "table" and tonumber(def.mapType) == Dive.MAP_TYPE_UNDERWATER
end
-- pokeemerald/src/overworld.c:756 SetDiveWarp
local function setDiveWarp(dir, def, mapId, x, y, sess)
local c = def and def[dir]
if type(c) == "table" and type(c.map) == "string" then
return { map = c.map, x = x, y = y }
end
local Space = package.loaded["src.core.game3.scripting.space"]
if Space and Space.runOnDiveWarp then Space.runOnDiveWarp(mapId) end
local w = sess and sess.diveWarp
-- pokeemerald/src/overworld.c:563 IsDummyWarp
if type(w) ~= "table" or type(w.map) ~= "string" or (tonumber(w.x) or -1) < 0 then return nil end
return { map = w.map, x = tonumber(w.x), y = tonumber(w.y), warpId = w.warpId }
end
-- pokeemerald/src/field_control_avatar.c:965 TrySetDiveWarp
function Dive.trySetDiveWarp(sess)
sess = sess or session()
local P = require("src.core.game3.player")
local Collision = require("src.core.game3.collision")
local def, mapId = currentDef()
local x, y = P.cellX, P.cellY
local beh = Collision.behavior(x, y)
if Dive.isUnderwaterMap(def) and not Dive.isUnableToEmerge(beh) then
local dest = setDiveWarp("emerge", def, mapId, x, y, sess)
if dest then return 1, dest end
elseif Dive.isDiveable(beh) then
local dest = setDiveWarp("dive", def, mapId, x, y, sess)
if dest then return 2, dest end
end
return 0, nil
end
local function badge(sess)
local FieldMoves = require("src.core.game3.field_moves")
local Space = package.loaded["src.core.game3.scripting.space"]
return FieldMoves.hasBadge({ store = Space and Space.store, session = sess }, "DIVE")
end
local function fieldFree()
local Field = package.loaded["src.core.game3.field"]
if not (Field and Field.running) or Field.locked then return false end
local Space = package.loaded["src.core.game3.scripting.space"]
if not (Space and Space.active and Space.startScript) then return false end
if Space.vm and Space.vm.isRunning and Space.vm:isRunning() then return false end
local P = require("src.core.game3.player")
if P.moving or P.jumping then return false end
local Warp = package.loaded["src.core.game3.warp"]
if Warp and Warp.isBusy and Warp.isBusy() then return false end
return Dive._task == nil
end
local function startScript(label)
local Space = package.loaded["src.core.game3.scripting.space"]
local key = Space.scriptKey(label)
if not key then error("dive: script " .. label .. " is not in the script cache", 0) end
return Space.startScript(key) and true or false
end
-- pokeemerald/src/field_control_avatar.c:463 TrySetupDiveDownScript
function Dive.tryDiveDown()
local sess = session()
if not Dive.enabled(sess) or not fieldFree() then return false end
if not badge(sess) then return false end
local code = Dive.trySetDiveWarp(sess)
if code ~= 2 then return false end
return startScript("EventScript_UseDive")
end
-- pokeemerald/src/field_control_avatar.c:473 TrySetupDiveEmergeScript
function Dive.tryEmerge()
local sess = session()
if not Dive.enabled(sess) or not fieldFree() then return false end
if not badge(sess) then return false end
if not Dive.isUnderwaterMap((currentDef())) then return false end
local code = Dive.trySetDiveWarp(sess)
if code ~= 1 then return false end
return startScript("EventScript_UseDiveUnderwater")
end
function Dive.isActive()
return Dive._task ~= nil
end
-- pokeemerald/src/field_effect.c:1902 FldEff_UseDive
function Dive.useDive(slot, mon)
local sess = session()
if not mon and sess and sess.party and slot then mon = sess.party[slot + 1] end
local Field = require("src.core.game3.field")
local Task = require("src.core.game3.task")
local t = { state = 0, mon = mon }
Dive._task = t
Field.lock()
Field.holdInput(true)
Task.spawn(function()
local Space = package.loaded["src.core.game3.scripting.space"]
if t.state == 0 then
if Space and Space.vm and Space.vm:isRunning() then return false end
Field.lock()
t.state = 1
-- pokeemerald/src/field_effect.c:1924
require("src.core.game3.field_move_show_mon").start(t.mon, { pose = true }, function() t.state = 2 end)
return false
elseif t.state == 1 then
Field.lock()
return false
end
-- pokeemerald/src/field_effect.c:1933
Dive._task = nil
Field.holdInput(false)
local code, dest = Dive.trySetDiveWarp(sess)
if code ~= 0 and dest then
require("src.core.game3.audio").playSe(require("src.core.game3.se_ids").SE_M_DIVE)
local Runtime = package.loaded["src.core.game3.runtime"]
require("src.core.game3.warp").startDive(Runtime and Runtime._mod, Runtime and Runtime._game, dest.map, dest.x, dest.y)
else
Field.unlock()
end
return true
end)
return true
end
-- pokeemerald/src/overworld.c:911 GetAdjustedInitialTransitionFlags
function Dive.syncAvatar()
if not Dive.enabled() then return end
local P = require("src.core.game3.player")
local def = currentDef()
if not def then return end
local under = Dive.isUnderwaterMap(def)
if under == (P.underwater == true) then return end
if P.moving then return end
if under then
P.underwater = true
P.surfing = false
return
end
P.underwater = false
local Collision = require("src.core.game3.collision")
if Collision.isSurfable and Collision.isSurfable(Collision.behavior(P.cellX, P.cellY)) then
P.surfing = true
local Audio = require("src.core.game3.audio")
if Audio.canOverrideMapMusic(Audio.MUS_SURF) then
Audio.playMapSong(Audio.MUS_SURF, { mapSong = Audio._mapSong })
end
end
end
function Dive.reset()
Dive._task = nil
end
function Dive.install()
local FieldEffects = require("src.core.game3.field_effects")
if FieldEffects.HANDLERS.FLDEFF_USE_DIVE then return end
-- pokeemerald/src/field_effect.c:1902
FieldEffects.HANDLERS.FLDEFF_USE_DIVE = function()
return Dive.useDive(FieldEffects.fieldEffectArgument(0, 0))
end
end
return Dive