mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-10-01 23:42:25 -04:00
This commit is contained in:
+356
-100
@@ -118,7 +118,7 @@ local function objectVisible(def)
|
||||
return true
|
||||
end
|
||||
|
||||
local function newEventObject(def)
|
||||
local function newEventObject(def, neighbor)
|
||||
-- Shallow-copy template so setobjectxy / removeobject cannot poison the
|
||||
-- shared events.lua / mapDef.objects tables for the rest of the session.
|
||||
local src = def or {}
|
||||
@@ -129,21 +129,26 @@ local function newEventObject(def)
|
||||
local lid = tonumber(def.localId or def.index) or 0
|
||||
local x = tonumber(def.x) or 0
|
||||
local y = tonumber(def.y) or 0
|
||||
local mt = tonumber(def.movementType) or 0
|
||||
local hostMv = GfxIds.hostMovement
|
||||
and GfxIds.hostMovement(mt, def.radius and def.radius.x, def.radius and def.radius.y)
|
||||
or nil
|
||||
local movement = def.movement
|
||||
or (hostMv and hostMv.movement)
|
||||
or "STAY"
|
||||
local range = def.range or (hostMv and hostMv.range) or "DOWN"
|
||||
local radius = def.radius or (hostMv and hostMv.radius)
|
||||
local rawMt = tonumber(def.movementType)
|
||||
local mt = rawMt or 0
|
||||
local spec
|
||||
if rawMt then
|
||||
spec = GfxIds.hostMovement(rawMt, def.rangeX, def.rangeY)
|
||||
else
|
||||
local r = def.radius or { x = 1, y = 1 }
|
||||
spec = {
|
||||
movement = def.movement or "STAY", range = def.range or "DOWN",
|
||||
rangeX = r.x, rangeY = r.y, radius = r,
|
||||
}
|
||||
end
|
||||
local facing = (def.facing and facingFromDef(def))
|
||||
or (rawMt and spec.face) or facingFromDef(def)
|
||||
local sprite = def.sprite
|
||||
local resolvedGfx = def.graphicsId or def.graphics
|
||||
do
|
||||
local okS, Space = pcall(require, "src.core.game3.scripting.space")
|
||||
if okS and Space and Space.resolveObjectGraphicsId then
|
||||
local gid = Space.resolveObjectGraphicsId(def)
|
||||
local gid = Space.resolveObjectGraphicsId(def, neighbor)
|
||||
if gid then resolvedGfx = gid end
|
||||
end
|
||||
end
|
||||
@@ -162,14 +167,18 @@ local function newEventObject(def)
|
||||
py = y * CELL,
|
||||
homeX = x,
|
||||
homeY = y,
|
||||
facing = facingFromDef(def),
|
||||
facing = facing,
|
||||
sprite = sprite or "SPRITE_YOUNGSTER",
|
||||
graphicsId = resolvedGfx,
|
||||
elevation = elev,
|
||||
movementType = mt,
|
||||
movement = movement,
|
||||
range = range,
|
||||
radius = radius or { x = 1, y = 1 },
|
||||
movement = spec.movement,
|
||||
range = spec.range,
|
||||
radius = spec.radius or { x = spec.rangeX, y = spec.rangeY },
|
||||
rangeX = spec.rangeX,
|
||||
rangeY = spec.rangeY,
|
||||
spec = spec,
|
||||
seqIndex = 0,
|
||||
sight = tonumber(def.sight or def.trainerRange) or 0,
|
||||
trainerType = tonumber(def.trainerType) or 0,
|
||||
scriptKey = def.scriptKey,
|
||||
@@ -187,7 +196,6 @@ local function newEventObject(def)
|
||||
targetY = y,
|
||||
stepFlip = false,
|
||||
animClock = 0,
|
||||
idleTimer = 30 + (lid * 17) % 60,
|
||||
scriptBusy = false,
|
||||
}
|
||||
end
|
||||
@@ -266,6 +274,21 @@ end
|
||||
|
||||
Objects.rememberPerm = rememberPerm
|
||||
|
||||
-- src/event_object_movement.c:4806
|
||||
local function setSpec(eo, mt)
|
||||
local spec = GfxIds.hostMovement(mt, eo.rangeX, eo.rangeY)
|
||||
spec.rangeX = tonumber(eo.rangeX) or 0
|
||||
spec.rangeY = tonumber(eo.rangeY) or 0
|
||||
spec.radius = { x = spec.rangeX, y = spec.rangeY }
|
||||
eo.movementType = tonumber(mt) or 0
|
||||
eo.spec = spec
|
||||
eo.movement = spec.movement
|
||||
eo.range = spec.range
|
||||
eo.radius = spec.radius
|
||||
eo.seqIndex = 0
|
||||
eo.idleTimer = nil
|
||||
end
|
||||
|
||||
local function applyPerm(eo, mapId)
|
||||
local bucket = Objects._perm[mapId]
|
||||
local row = bucket and bucket[eo.localId]
|
||||
@@ -285,15 +308,9 @@ local function applyPerm(eo, mapId)
|
||||
if eo.def then eo.def.y = row.y end
|
||||
end
|
||||
if row.movementType ~= nil then
|
||||
eo.movementType = row.movementType
|
||||
local hostMv = GfxIds.hostMovement and GfxIds.hostMovement(row.movementType)
|
||||
if hostMv then
|
||||
eo.movement = hostMv.movement
|
||||
eo.range = hostMv.range
|
||||
if hostMv.radius then eo.radius = hostMv.radius end
|
||||
end
|
||||
local face = ({ [7] = "up", [8] = "down", [9] = "left", [10] = "right" })[row.movementType]
|
||||
if face then eo.facing = face end
|
||||
setSpec(eo, row.movementType)
|
||||
-- src/event_object_movement.c:1378
|
||||
eo.facing = eo.spec.face
|
||||
-- src/event_object_movement.c:1569
|
||||
eo.invisible = tonumber(row.movementType) == MOVEMENT_TYPE_INVISIBLE
|
||||
if eo.def then eo.def.movementType = row.movementType end
|
||||
@@ -557,8 +574,10 @@ function Objects.at(tx, ty)
|
||||
for _, lid in ipairs(Objects._order) do
|
||||
local eo = Objects._byId[lid]
|
||||
if eo and eo.visible and not eo.hidden then
|
||||
if eo.cellX == tx and eo.cellY == ty then
|
||||
if eo.moving then return nil end
|
||||
-- src/event_object_movement.c:1281
|
||||
local cx = eo.moving and eo.targetX or eo.cellX
|
||||
local cy = eo.moving and eo.targetY or eo.cellY
|
||||
if cx == tx and cy == ty then
|
||||
return eo
|
||||
end
|
||||
end
|
||||
@@ -639,6 +658,36 @@ local function finishStep(eo, game)
|
||||
end
|
||||
end
|
||||
|
||||
-- src/event_object_movement.c:8866
|
||||
local STEP_PIXELS = {
|
||||
[16] = { 1 },
|
||||
[8] = { 2 },
|
||||
[6] = { 2, 3, 3 },
|
||||
[4] = { 4 },
|
||||
[2] = { 8 },
|
||||
-- src/event_object_movement.c:9029
|
||||
[11] = { 1, 2 },
|
||||
-- src/event_object_movement.c:8984
|
||||
[24] = { 1, 1, 0 },
|
||||
-- src/event_object_movement.c:8959
|
||||
[32] = { 1, 0 },
|
||||
}
|
||||
local STEP_OFFSETS = {}
|
||||
for frames, pat in pairs(STEP_PIXELS) do
|
||||
local cum, n = {}, 0
|
||||
for k = 1, frames do
|
||||
n = math.min(CELL, n + pat[(k - 1) % #pat + 1])
|
||||
cum[k] = n
|
||||
end
|
||||
STEP_OFFSETS[frames] = cum
|
||||
end
|
||||
|
||||
local function stepOffset(frames, progress, cells)
|
||||
local cum = cells == 1 and STEP_OFFSETS[frames]
|
||||
if cum then return cum[math.min(progress, frames)] end
|
||||
return math.floor(cells * CELL * math.min(progress, frames) / frames)
|
||||
end
|
||||
|
||||
local function tickMotion(eo, game)
|
||||
if not eo.moving then return false end
|
||||
eo.progress = eo.progress + 1
|
||||
@@ -646,9 +695,9 @@ local function tickMotion(eo, game)
|
||||
local frames = eo.stepFrames or WALK_FRAMES
|
||||
local dx = eo.targetX - eo.cellX
|
||||
local dy = eo.targetY - eo.cellY
|
||||
local t = math.min(1, eo.progress / frames)
|
||||
eo.px = eo.cellX * CELL + dx * CELL * t
|
||||
eo.py = eo.cellY * CELL + dy * CELL * t
|
||||
local off = stepOffset(frames, eo.progress, math.abs(dx) + math.abs(dy))
|
||||
eo.px = eo.cellX * CELL + (dx > 0 and off or dx < 0 and -off or 0)
|
||||
eo.py = eo.cellY * CELL + (dy > 0 and off or dy < 0 and -off or 0)
|
||||
if eo.progress >= frames then
|
||||
finishStep(eo, game)
|
||||
return true
|
||||
@@ -693,6 +742,16 @@ function Objects.scriptJump(eo, dir, distance)
|
||||
return true
|
||||
end
|
||||
|
||||
-- pokefirered/src/event_object_movement.c:5351 InitNpcForWalkSlower
|
||||
function Objects.pushStep(eo, dir, frames)
|
||||
local d = DELTA[dir]
|
||||
if not eo or not d or eo.moving then return false end
|
||||
eo.facing = dir
|
||||
beginStep(eo, eo.cellX + d[1], eo.cellY + d[2])
|
||||
eo.stepFrames = frames or WALK_FRAMES * 2
|
||||
return true
|
||||
end
|
||||
|
||||
function Objects.scriptFace(eo, dir)
|
||||
if not eo then return end
|
||||
local P = Player()
|
||||
@@ -795,7 +854,9 @@ local function advanceTrack(lid, tr, game)
|
||||
tr.sleep = act.frames or 32
|
||||
elseif act.kind == "face_original" then
|
||||
if eo and eo ~= Player() and eo.def then
|
||||
local origFace = facingFromDef(eo.def)
|
||||
-- src/event_object_movement.c:7016
|
||||
local origFace = eo.def.movementType ~= nil and GfxIds.initialFacing(eo.movementType)
|
||||
or facingFromDef(eo.def)
|
||||
Objects.scriptFace(eo, origFace)
|
||||
end
|
||||
elseif act.kind == "bow" then
|
||||
@@ -819,12 +880,18 @@ local function advanceTrack(lid, tr, game)
|
||||
elseif act.kind == "sleep" then
|
||||
tr.sleep = act.frames or 1
|
||||
elseif act.kind == "hide" then
|
||||
if eo and eo ~= Player() then
|
||||
-- pokefirered/src/event_object_movement.c:7054
|
||||
if eo == Player() then
|
||||
Player().setVisible(false)
|
||||
elseif eo then
|
||||
eo.hidden = true
|
||||
eo.visible = false
|
||||
end
|
||||
elseif act.kind == "show" then
|
||||
if eo and eo ~= Player() then
|
||||
-- pokefirered/src/event_object_movement.c:7061
|
||||
if eo == Player() then
|
||||
Player().setVisible(true)
|
||||
elseif eo then
|
||||
eo.hidden = false
|
||||
eo.visible = true
|
||||
end
|
||||
@@ -939,6 +1006,142 @@ local function raiseHandTick(eo)
|
||||
end
|
||||
end
|
||||
|
||||
local function checkSight(game, eo)
|
||||
local okTs, TrainerSight = pcall(require, "src.core.game3.trainer_sight")
|
||||
if okTs and TrainerSight and TrainerSight.check then
|
||||
TrainerSight.check(game, eo)
|
||||
end
|
||||
end
|
||||
|
||||
-- src/event_object_movement.c:4830
|
||||
local function stepCollision(eo, game, ctx, dir)
|
||||
local d = DELTA[dir]
|
||||
local tx, ty = eo.cellX + d[1], eo.cellY + d[2]
|
||||
-- src/event_object_movement.c:4861
|
||||
local rx = tonumber(eo.rangeX or (eo.radius and eo.radius.x)) or 0
|
||||
local ry = tonumber(eo.rangeY or (eo.radius and eo.radius.y)) or 0
|
||||
if (rx ~= 0 and math.abs(tx - eo.homeX) > rx) or (ry ~= 0 and math.abs(ty - eo.homeY) > ry) then
|
||||
return "range"
|
||||
end
|
||||
local ok
|
||||
if ctx then
|
||||
local Coll = Collision()
|
||||
ok = ctx.canEnter(tx, ty, eo.cellX, eo.cellY, dir)
|
||||
and not ctx.blocks(tx, ty, eo.localId)
|
||||
if ok and eo.mapDef and Coll.directionallyImpassableOn(
|
||||
eo.mapDef, eo.cellX, eo.cellY, tx, ty, dir) then
|
||||
ok = false
|
||||
end
|
||||
else
|
||||
local Coll = Collision()
|
||||
-- pokefirered/src/event_object_movement.c:8346 IsElevationMismatchAt
|
||||
local onWater = Coll.isWater(eo.cellX, eo.cellY)
|
||||
ok = Coll.canEnter(game, tx, ty,
|
||||
{ fromX = eo.cellX, fromY = eo.cellY, dir = dir, surfing = onWater })
|
||||
if ok and Coll.isWater(tx, ty) ~= onWater then ok = false end
|
||||
if Objects.playerBlocks(tx, ty) then ok = false end
|
||||
if Objects.blocks(tx, ty, eo.localId) then ok = false end
|
||||
end
|
||||
if not ok then return "blocked" end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- src/event_object_movement.c:3884
|
||||
local function walkOrInPlace(eo, dir, collision)
|
||||
eo.facing = dir
|
||||
if collision then
|
||||
beginStep(eo, eo.cellX, eo.cellY)
|
||||
else
|
||||
local d = DELTA[dir]
|
||||
beginStep(eo, eo.cellX + d[1], eo.cellY + d[2])
|
||||
end
|
||||
end
|
||||
|
||||
-- src/event_object_movement.c:2770
|
||||
local function playerCellFor(ctx)
|
||||
local P = Player()
|
||||
local px = P.moving and P.targetX or P.cellX
|
||||
local py = P.moving and P.targetY or P.cellY
|
||||
return px - (ctx and ctx.ox or 0), py - (ctx and ctx.oy or 0)
|
||||
end
|
||||
|
||||
local function trainerCloseToRunningPlayer(eo, ctx)
|
||||
local P = Player()
|
||||
if not (P and P.running) or P.biking or P.surfing then return false end
|
||||
local tt = tonumber(eo.trainerType) or 0
|
||||
if tt ~= 1 and tt ~= 3 then return false end
|
||||
local r = tonumber(eo.sight) or 0
|
||||
local px, py = playerCellFor(ctx)
|
||||
return math.abs(px - eo.cellX) <= r and math.abs(py - eo.cellY) <= r
|
||||
end
|
||||
|
||||
-- src/event_object_movement.c:2801
|
||||
local function vectorDirection(dx, dy)
|
||||
if math.abs(dx) > math.abs(dy) then return dx < 0 and "left" or "right" end
|
||||
return dy < 0 and "up" or "down"
|
||||
end
|
||||
|
||||
local function southNorth(dy) return dy < 0 and "up" or "down" end
|
||||
local function westEast(dx) return dx < 0 and "left" or "right" end
|
||||
|
||||
-- src/data/object_events/movement_type_func_tables.h:185
|
||||
local FOLLOW = {
|
||||
[0] = vectorDirection,
|
||||
[1] = function(_, dy) return southNorth(dy) end,
|
||||
[2] = function(dx) return westEast(dx) end,
|
||||
[3] = function(dx, dy)
|
||||
local d = vectorDirection(dx, dy)
|
||||
if d == "down" then d = westEast(dx); if d == "right" then d = "up" end
|
||||
elseif d == "right" then d = southNorth(dy); if d == "down" then d = "up" end end
|
||||
return d
|
||||
end,
|
||||
[4] = function(dx, dy)
|
||||
local d = vectorDirection(dx, dy)
|
||||
if d == "down" then d = westEast(dx); if d == "left" then d = "up" end
|
||||
elseif d == "left" then d = southNorth(dy); if d == "down" then d = "up" end end
|
||||
return d
|
||||
end,
|
||||
[5] = function(dx, dy)
|
||||
local d = vectorDirection(dx, dy)
|
||||
if d == "up" then d = westEast(dx); if d == "right" then d = "down" end
|
||||
elseif d == "right" then d = southNorth(dy); if d == "up" then d = "down" end end
|
||||
return d
|
||||
end,
|
||||
[6] = function(dx, dy)
|
||||
local d = vectorDirection(dx, dy)
|
||||
if d == "up" then d = westEast(dx); if d == "left" then d = "down" end
|
||||
elseif d == "left" then d = southNorth(dy); if d == "up" then d = "down" end end
|
||||
return d
|
||||
end,
|
||||
[7] = function(dx, dy)
|
||||
local d = vectorDirection(dx, dy)
|
||||
if d == "right" then d = southNorth(dy) end
|
||||
return d
|
||||
end,
|
||||
[8] = function(dx, dy)
|
||||
local d = vectorDirection(dx, dy)
|
||||
if d == "left" then d = southNorth(dy) end
|
||||
return d
|
||||
end,
|
||||
[9] = function(dx, dy)
|
||||
local d = vectorDirection(dx, dy)
|
||||
if d == "down" then d = westEast(dx) end
|
||||
return d
|
||||
end,
|
||||
[10] = function(dx, dy)
|
||||
local d = vectorDirection(dx, dy)
|
||||
if d == "up" then d = westEast(dx) end
|
||||
return d
|
||||
end,
|
||||
}
|
||||
|
||||
-- src/event_object_movement.c:2992
|
||||
local function followDirection(eo, follow, ctx)
|
||||
local px, py = playerCellFor(ctx)
|
||||
local fn = FOLLOW[follow] or FOLLOW[0]
|
||||
return fn(px - eo.cellX, py - eo.cellY)
|
||||
end
|
||||
|
||||
local function idleTick(eo, game, ctx)
|
||||
if eo.frozen or eo.scriptBusy or eo.moving or eo.hidden or not eo.visible then
|
||||
return
|
||||
@@ -951,75 +1154,94 @@ local function idleTick(eo, game, ctx)
|
||||
raiseHandTick(eo)
|
||||
return
|
||||
end
|
||||
eo.idleTimer = (eo.idleTimer or 0) - 1
|
||||
if eo.idleTimer > 0 then return end
|
||||
|
||||
local mv = tostring(eo.movement or "STAY"):upper()
|
||||
if mv == "STAY" then
|
||||
eo.idleTimer = 120
|
||||
if mv == "STAY" then return end
|
||||
local spec = eo.spec
|
||||
if not spec or spec.movement ~= mv then
|
||||
spec = { movement = mv, dirs = dirsForRange(eo.range), delays = "MEDIUM", follow = 0 }
|
||||
end
|
||||
|
||||
if mv == "BACK_FORTH" then
|
||||
-- src/event_object_movement.c:3849
|
||||
local dir = (eo.seqIndex or 0) ~= 0 and OPPOSITE_DIR[spec.face] or spec.face
|
||||
if (eo.seqIndex or 0) ~= 0 and eo.cellX == eo.homeX and eo.cellY == eo.homeY then
|
||||
eo.seqIndex = 0
|
||||
dir = OPPOSITE_DIR[dir]
|
||||
end
|
||||
local c = stepCollision(eo, game, ctx, dir)
|
||||
if c == "range" then
|
||||
eo.seqIndex = (eo.seqIndex or 0) + 1
|
||||
dir = OPPOSITE_DIR[dir]
|
||||
c = stepCollision(eo, game, ctx, dir)
|
||||
end
|
||||
walkOrInPlace(eo, dir, c)
|
||||
return
|
||||
end
|
||||
|
||||
if mv == "SEQUENCE" then
|
||||
-- src/event_object_movement.c:3949
|
||||
local idx = eo.seqIndex or 0
|
||||
if idx == spec.skipFrom and ((spec.skipAxis == "x" and eo.cellX == eo.homeX)
|
||||
or (spec.skipAxis == "y" and eo.cellY == eo.homeY)) then
|
||||
idx = spec.skipFrom + 1
|
||||
end
|
||||
-- src/event_object_movement.c:3914
|
||||
if idx == 3 and eo.cellX == eo.homeX and eo.cellY == eo.homeY then idx = 0 end
|
||||
local dir = spec.route[idx + 1]
|
||||
local c = stepCollision(eo, game, ctx, dir)
|
||||
if c == "range" then
|
||||
idx = (idx + 1) % 4
|
||||
dir = spec.route[idx + 1]
|
||||
c = stepCollision(eo, game, ctx, dir)
|
||||
end
|
||||
eo.seqIndex = idx
|
||||
walkOrInPlace(eo, dir, c)
|
||||
return
|
||||
end
|
||||
|
||||
local Rng = require("src.core.game3.rng")
|
||||
local dirs = dirsForRange(eo.range)
|
||||
if mv == "LOOK" or mv == "LOOK_AROUND" then
|
||||
local function pick(t) return t[(Rng.Random() % #t) + 1] end
|
||||
|
||||
if mv == "LOOK" or mv == "LOOK_AROUND" or mv == "ROTATE" then
|
||||
-- src/event_object_movement.c:3044
|
||||
local close = trainerCloseToRunningPlayer(eo, ctx)
|
||||
if eo.idleTimer == nil then
|
||||
eo.idleTimer = mv == "ROTATE" and 48 or pick(GfxIds.DELAYS[spec.delays or "MEDIUM"])
|
||||
end
|
||||
eo.idleTimer = eo.idleTimer - 1
|
||||
if eo.idleTimer > 0 and not close then return end
|
||||
local oldFacing = eo.facing
|
||||
local pickIdx = Rng.compat(1, #dirs)
|
||||
eo.facing = dirs[pickIdx] or dirs[1]
|
||||
eo.idleTimer = 48 + Rng.compat(0, 47)
|
||||
-- src/event_object_movement.c:2992
|
||||
local dir = close and followDirection(eo, spec.follow or 0, ctx)
|
||||
if not dir then
|
||||
dir = mv == "ROTATE" and spec.next[eo.facing] or pick(spec.dirs)
|
||||
end
|
||||
eo.facing = dir
|
||||
eo.idleTimer = mv == "ROTATE" and 48 or pick(GfxIds.DELAYS[spec.delays or "MEDIUM"])
|
||||
if not ctx and eo.facing ~= oldFacing and eo.sight and eo.sight > 0 then
|
||||
local okTs, TrainerSight = pcall(require, "src.core.game3.trainer_sight")
|
||||
if okTs and TrainerSight and TrainerSight.check then
|
||||
TrainerSight.check(game, eo)
|
||||
end
|
||||
checkSight(game, eo)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if mv == "WALK" then
|
||||
local pickIdx = Rng.compat(1, #dirs)
|
||||
local dir = dirs[pickIdx] or dirs[1]
|
||||
local d = DELTA[dir]
|
||||
local tx, ty = eo.cellX + d[1], eo.cellY + d[2]
|
||||
local rx = (eo.radius and eo.radius.x) or 1
|
||||
local ry = (eo.radius and eo.radius.y) or 1
|
||||
if math.abs(tx - eo.homeX) > rx or math.abs(ty - eo.homeY) > ry then
|
||||
eo.idleTimer = 30 + Rng.compat(0, 29)
|
||||
-- src/event_object_movement.c:2716
|
||||
if eo.idleTimer == nil then eo.idleTimer = pick(GfxIds.DELAYS.MEDIUM) end
|
||||
eo.idleTimer = eo.idleTimer - 1
|
||||
if eo.idleTimer > 0 then return end
|
||||
-- src/event_object_movement.c:2731
|
||||
local dir = pick(spec.dirs or dirsForRange(eo.range))
|
||||
eo.facing = dir
|
||||
eo.idleTimer = pick(GfxIds.DELAYS.MEDIUM)
|
||||
if stepCollision(eo, game, ctx, dir) then
|
||||
if not ctx and eo.sight and eo.sight > 0 then checkSight(game, eo) end
|
||||
return
|
||||
end
|
||||
local ok
|
||||
-- pokefirered/src/event_object_movement.c:4830 GetCollisionAtCoords
|
||||
if ctx then
|
||||
local Coll = Collision()
|
||||
ok = ctx.canEnter(tx, ty, eo.cellX, eo.cellY, dir)
|
||||
and not ctx.blocks(tx, ty, eo.localId)
|
||||
if ok and eo.mapDef and Coll.directionallyImpassableOn(
|
||||
eo.mapDef, eo.cellX, eo.cellY, tx, ty, dir) then
|
||||
ok = false
|
||||
end
|
||||
else
|
||||
local Coll = Collision()
|
||||
-- pokefirered/src/event_object_movement.c:8346 IsElevationMismatchAt
|
||||
local onWater = Coll.isWater(eo.cellX, eo.cellY)
|
||||
ok = Coll.canEnter(game, tx, ty,
|
||||
{ fromX = eo.cellX, fromY = eo.cellY, dir = dir, surfing = onWater })
|
||||
if ok and Coll.isWater(tx, ty) ~= onWater then ok = false end
|
||||
if Objects.playerBlocks(tx, ty) then ok = false end
|
||||
if Objects.blocks(tx, ty, eo.localId) then ok = false end
|
||||
end
|
||||
if ok then
|
||||
eo.facing = dir
|
||||
beginStep(eo, tx, ty)
|
||||
else
|
||||
eo.facing = dir -- turn toward blocked anyway
|
||||
if not ctx and eo.sight and eo.sight > 0 then
|
||||
local okTs, TrainerSight = pcall(require, "src.core.game3.trainer_sight")
|
||||
if okTs and TrainerSight and TrainerSight.check then
|
||||
TrainerSight.check(game, eo)
|
||||
end
|
||||
end
|
||||
end
|
||||
eo.idleTimer = 40 + Rng.compat(0, 49)
|
||||
local d = DELTA[dir]
|
||||
beginStep(eo, eo.cellX + d[1], eo.cellY + d[2])
|
||||
-- src/event_object_movement.c:8959
|
||||
if spec.slow then eo.stepFrames = WALK_FRAMES * 2 end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1041,12 +1263,31 @@ function Objects.update(game)
|
||||
end
|
||||
end
|
||||
|
||||
function Objects.spawnFromDefs(defs, mapDef)
|
||||
function Objects.spawnFromDefs(defs, mapDef, mapId)
|
||||
local pool = { byId = {}, order = {}, bounds = layoutBounds(mapDef), mapDef = mapDef }
|
||||
local Sp = mapId and Space()
|
||||
local nb = Sp and Sp.neighborObjectState and Sp.neighborObjectState(mapId)
|
||||
if mapId and not nb and not (Sp and Sp.mapId == mapId) then nb = { store = { flags = {}, vars = {} }, perm = {}, movementType = {} } end
|
||||
for _, def in ipairs(defs or {}) do
|
||||
local eo = newEventObject(def)
|
||||
local eo = newEventObject(def, nb)
|
||||
if eo.localId > 0 then
|
||||
eo.mapDef = mapDef
|
||||
if nb then
|
||||
local p = nb.perm[eo.localId]
|
||||
if p then
|
||||
eo.cellX, eo.cellY, eo.homeX, eo.homeY = p.x, p.y, p.x, p.y
|
||||
eo.targetX, eo.targetY = p.x, p.y
|
||||
eo.px, eo.py = p.x * CELL, p.y * CELL
|
||||
eo.def.x, eo.def.y = p.x, p.y
|
||||
end
|
||||
local mt = nb.movementType[eo.localId]
|
||||
if mt then
|
||||
Objects.setTrainerMovementType(eo, mt)
|
||||
-- pokefirered/src/event_object_movement.c:359
|
||||
eo.facing = GfxIds.initialFacing(mt)
|
||||
end
|
||||
if (tonumber(eo.graphicsId) or 0) >= 240 then eo.invisible = true end
|
||||
end
|
||||
pool.byId[eo.localId] = eo
|
||||
pool.order[#pool.order + 1] = eo.localId
|
||||
end
|
||||
@@ -1094,14 +1335,22 @@ function Objects.adoptPool(pool)
|
||||
for _, lid in ipairs(pool.order or {}) do
|
||||
local live = Objects._byId[lid]
|
||||
local ghost = pool.byId[lid]
|
||||
local wanders = live and tostring(live.movement or "STAY"):upper() == "WALK"
|
||||
if live and ghost and wanders and not ghost.moving then
|
||||
local mv = live and ghost and live.movement == ghost.movement
|
||||
and tostring(live.movement or "STAY"):upper()
|
||||
if mv == "WALK" or mv == "BACK_FORTH" or mv == "SEQUENCE" then
|
||||
live.cellX, live.cellY = ghost.cellX, ghost.cellY
|
||||
live.px, live.py = ghost.px, ghost.py
|
||||
live.targetX, live.targetY = ghost.targetX, ghost.targetY
|
||||
live.moving, live.progress = ghost.moving, ghost.progress
|
||||
live.stepFrames, live.animClock = ghost.stepFrames, ghost.animClock
|
||||
live.facing = ghost.facing
|
||||
live.stepFlip = ghost.stepFlip
|
||||
live.idleTimer = ghost.idleTimer
|
||||
live.seqIndex = ghost.seqIndex
|
||||
if live.def then live.def.x, live.def.y = live.cellX, live.cellY end
|
||||
elseif mv == "LOOK" or mv == "ROTATE" then
|
||||
live.facing = ghost.facing
|
||||
live.idleTimer = ghost.idleTimer
|
||||
end
|
||||
end
|
||||
return true
|
||||
@@ -1225,12 +1474,25 @@ function Objects.removeObject(localId)
|
||||
return true
|
||||
end
|
||||
|
||||
-- src/event_object_movement.c:2059
|
||||
local function setObjectInvisibility(localId, state)
|
||||
local lid = tonumber(localId) or 0
|
||||
if lid >= Objects.PLAYER_LOCAL_ID then
|
||||
Player().setVisible(not state)
|
||||
return true
|
||||
end
|
||||
local eo = Objects._byId[lid]
|
||||
if not eo then return false end
|
||||
eo.invisible = state
|
||||
return true
|
||||
end
|
||||
|
||||
function Objects.hideObject(localId)
|
||||
return Objects.removeObject(localId)
|
||||
return setObjectInvisibility(localId, true)
|
||||
end
|
||||
|
||||
function Objects.showObject(localId)
|
||||
return Objects.addObject(localId)
|
||||
return setObjectInvisibility(localId, false)
|
||||
end
|
||||
|
||||
function Objects.turnObject(localId, dir)
|
||||
@@ -1297,13 +1559,7 @@ function Objects.setTrainerMovementType(localId, mt)
|
||||
local eo = type(localId) == "table" and localId or Objects._byId[tonumber(localId) or 0]
|
||||
if not eo then return end
|
||||
mt = tonumber(mt) or 0
|
||||
eo.movementType = mt
|
||||
local hostMv = GfxIds.hostMovement and GfxIds.hostMovement(mt)
|
||||
if hostMv then
|
||||
eo.movement = hostMv.movement
|
||||
eo.range = hostMv.range
|
||||
if hostMv.radius then eo.radius = hostMv.radius end
|
||||
end
|
||||
setSpec(eo, mt)
|
||||
clearRaiseHand(eo)
|
||||
-- src/event_object_movement.c:4543
|
||||
if mt == MOVEMENT_TYPE_INVISIBLE then eo.invisible = true end
|
||||
|
||||
Reference in New Issue
Block a user