mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-10-10 02:08:29 -04:00
213 lines
7.2 KiB
Lua
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
|