163 lines
6.9 KiB
Lua
163 lines
6.9 KiB
Lua
if unsupported then return end
|
|
|
|
local MARIO_HEAD_POS = 120
|
|
|
|
local sPlayerFirstPerson = {
|
|
pos = { x = 0, y = 0, z = 0 },
|
|
freecam = camera_config_is_free_cam_enabled(),
|
|
pitch = 0,
|
|
yaw = 0,
|
|
fov = 70
|
|
}
|
|
|
|
-- localize functions to improve performance - spectator.lua
|
|
local camera_config_get_x_sensitivity,camera_config_get_y_sensitivity,camera_config_is_x_inverted,camera_config_is_y_inverted,is_game_paused,djui_hud_get_raw_mouse_y,clamp,djui_hud_get_raw_mouse_x,vec3f_copy,mario_drop_held_object,set_mario_animation,vec3f_set,vec3f_mul,djui_hud_set_mouse_locked,camera_freeze,maxf,camera_config_is_free_cam_enabled,set_override_near,set_override_fov,camera_unfreeze,camera_config_is_mouse_look_enabled,allocate_mario_action = camera_config_get_x_sensitivity,camera_config_get_y_sensitivity,camera_config_is_x_inverted,camera_config_is_y_inverted,is_game_paused,djui_hud_get_raw_mouse_y,clamp,djui_hud_get_raw_mouse_x,vec3f_copy,mario_drop_held_object,set_mario_animation,vec3f_set,vec3f_mul,djui_hud_set_mouse_locked,camera_freeze,maxf,camera_config_is_free_cam_enabled,set_override_near,set_override_fov,camera_unfreeze,camera_config_is_mouse_look_enabled,allocate_mario_action
|
|
|
|
--- @param m MarioState
|
|
local function update_fp_camera(m)
|
|
gLakituState.mode = CAMERA_MODE_FREE_ROAM
|
|
gLakituState.defMode = CAMERA_MODE_FREE_ROAM
|
|
|
|
local sensX = 0.3 * camera_config_get_x_sensitivity()
|
|
local sensY = 0.4 * camera_config_get_y_sensitivity()
|
|
local invX = if_then_else(camera_config_is_x_inverted(), 1, -1)
|
|
local invY = if_then_else(camera_config_is_y_inverted(), 1, -1)
|
|
|
|
if not is_game_paused() then
|
|
-- update pitch
|
|
sPlayerFirstPerson.pitch = sPlayerFirstPerson.pitch - sensY * (invY * m.controller.extStickY - 1.5 * djui_hud_get_raw_mouse_y())
|
|
sPlayerFirstPerson.pitch = clamp(sPlayerFirstPerson.pitch, -0x3F00, 0x3F00)
|
|
|
|
-- update yaw
|
|
if (m.controller.buttonPressed & L_TRIG) ~= 0 then
|
|
sPlayerFirstPerson.yaw = m.faceAngle.y + 0x8000
|
|
else
|
|
sPlayerFirstPerson.yaw = sPlayerFirstPerson.yaw + sensX * (invX * m.controller.extStickX - 1.5 * djui_hud_get_raw_mouse_x())
|
|
end
|
|
sPlayerFirstPerson.yaw = (sPlayerFirstPerson.yaw + 0x10000) % 0x10000
|
|
end
|
|
|
|
gLakituState.yaw = sPlayerFirstPerson.yaw
|
|
m.area.camera.yaw = sPlayerFirstPerson.yaw
|
|
|
|
-- update pos
|
|
gLakituState.pos.x = sPlayerFirstPerson.pos.x + coss(sPlayerFirstPerson.pitch) * sins(sPlayerFirstPerson.yaw)
|
|
gLakituState.pos.y = sPlayerFirstPerson.pos.y + sins(sPlayerFirstPerson.pitch) + MARIO_HEAD_POS
|
|
gLakituState.pos.z = sPlayerFirstPerson.pos.z + coss(sPlayerFirstPerson.pitch) * coss(sPlayerFirstPerson.yaw)
|
|
vec3f_copy(m.area.camera.pos, gLakituState.pos)
|
|
vec3f_copy(gLakituState.curPos, gLakituState.pos)
|
|
vec3f_copy(gLakituState.goalPos, gLakituState.pos)
|
|
|
|
-- update focus
|
|
gLakituState.focus.x = sPlayerFirstPerson.pos.x - 100 * coss(sPlayerFirstPerson.pitch) * sins(sPlayerFirstPerson.yaw)
|
|
gLakituState.focus.y = sPlayerFirstPerson.pos.y - 100 * sins(sPlayerFirstPerson.pitch) + MARIO_HEAD_POS
|
|
gLakituState.focus.z = sPlayerFirstPerson.pos.z - 100 * coss(sPlayerFirstPerson.pitch) * coss(sPlayerFirstPerson.yaw)
|
|
vec3f_copy(m.area.camera.focus, gLakituState.focus)
|
|
vec3f_copy(gLakituState.curFocus, gLakituState.focus)
|
|
vec3f_copy(gLakituState.goalFocus, gLakituState.focus)
|
|
|
|
-- set other values
|
|
gLakituState.posHSpeed = 0
|
|
gLakituState.posVSpeed = 0
|
|
gLakituState.focHSpeed = 0
|
|
gLakituState.focVSpeed = 0
|
|
end
|
|
|
|
--- @param m MarioState
|
|
function set_mario_spectator(m)
|
|
if m.action ~= ACT_SPECTATOR then
|
|
sPlayerFirstPerson.pos = { x = m.pos.x, y = if_then_else(m.health > 0xFF, m.pos.y, gGlobalSyncTable.waterLevel), z = m.pos.z }
|
|
end
|
|
m.action = ACT_SPECTATOR
|
|
end
|
|
|
|
--- @param m MarioState
|
|
local function act_spectator(m)
|
|
mario_drop_held_object(m)
|
|
m.squishTimer = 0
|
|
|
|
set_mario_animation(m, MARIO_ANIM_DROWNING_PART2)
|
|
m.marioBodyState.eyeState = MARIO_EYES_DEAD
|
|
m.faceAngle.x = 0
|
|
m.faceAngle.z = 0
|
|
|
|
if gPlayerSyncTable[m.playerIndex].finished then
|
|
m.marioObj.header.gfx.node.flags = m.marioObj.header.gfx.node.flags & ~GRAPH_RENDER_ACTIVE
|
|
local goalPos = gLevels[gGlobalSyncTable.level].goalPos
|
|
vec3f_set(m.pos, goalPos.x, goalPos.y + 600, goalPos.z)
|
|
mario_set_full_health(m)
|
|
else
|
|
m.pos.y = gGlobalSyncTable.waterLevel - 70
|
|
vec3f_copy(m.marioObj.header.gfx.pos, m.pos)
|
|
vec3f_copy(m.marioObj.header.gfx.angle, m.faceAngle)
|
|
m.marioObj.header.gfx.angle.y = 0
|
|
m.health = 0xFF
|
|
m.healCounter = 0
|
|
m.hurtCounter = 0
|
|
end
|
|
|
|
if m.playerIndex ~= 0 then return end
|
|
|
|
if not is_game_paused() then
|
|
local forward = { x = sins(m.faceAngle.y), y = 0, z = coss(m.faceAngle.y) }
|
|
local right = { x = sins(m.faceAngle.y - 0x4000), y = 0, z = coss(m.faceAngle.y - 0x4000) }
|
|
local dir = { x = forward.x * m.controller.stickY + right.x * m.controller.stickX, y = 0, z = forward.z * m.controller.stickY + right.z * m.controller.stickX }
|
|
local speed = if_then_else((m.controller.buttonDown & B_BUTTON) ~= 0, 2, 1)
|
|
dir = vec3f_mul(dir, speed)
|
|
|
|
sPlayerFirstPerson.pos.x = sPlayerFirstPerson.pos.x + dir.x
|
|
sPlayerFirstPerson.pos.z = sPlayerFirstPerson.pos.z + dir.z
|
|
|
|
if (m.input & INPUT_A_DOWN) ~= 0 then
|
|
sPlayerFirstPerson.pos.y = sPlayerFirstPerson.pos.y + (50 * speed)
|
|
end
|
|
if (m.input & INPUT_Z_DOWN) ~= 0 then
|
|
sPlayerFirstPerson.pos.y = sPlayerFirstPerson.pos.y - (50 * speed)
|
|
end
|
|
end
|
|
|
|
m.faceAngle.y = m.area.camera.yaw + 0x8000
|
|
|
|
djui_hud_set_mouse_locked(not is_game_paused())
|
|
|
|
camera_freeze()
|
|
update_fp_camera(m)
|
|
end
|
|
|
|
--- @param m MarioState
|
|
local function on_set_mario_action(m)
|
|
if m.action == ACT_VERTICAL_WIND then
|
|
m.vel.y = maxf(m.vel.y, 0)
|
|
end
|
|
|
|
if m.playerIndex ~= 0 then return end
|
|
|
|
if m.action == ACT_SPECTATOR then
|
|
sPlayerFirstPerson.freecam = camera_config_is_free_cam_enabled()
|
|
camera_freeze()
|
|
set_override_near(45)
|
|
set_override_fov(sPlayerFirstPerson.fov)
|
|
sPlayerFirstPerson.pitch = 0
|
|
sPlayerFirstPerson.yaw = m.faceAngle.y + 0x8000
|
|
else
|
|
if sPlayerFirstPerson.freecam then
|
|
gLakituState.mode = CAMERA_MODE_NEWCAM
|
|
gLakituState.defMode = CAMERA_MODE_NEWCAM
|
|
end
|
|
camera_unfreeze()
|
|
set_override_near(0)
|
|
set_override_fov(0)
|
|
sPlayerFirstPerson.pitch = 0
|
|
sPlayerFirstPerson.yaw = 0
|
|
if not camera_config_is_mouse_look_enabled() then
|
|
djui_hud_set_mouse_locked(false)
|
|
end
|
|
end
|
|
end
|
|
|
|
ACT_SPECTATOR = allocate_mario_action(ACT_GROUP_AIRBORNE | ACT_FLAG_INVULNERABLE)
|
|
|
|
hook_event(HOOK_ON_SET_MARIO_ACTION, on_set_mario_action)
|
|
|
|
---@diagnostic disable-next-line: missing-parameter
|
|
hook_mario_action(ACT_SPECTATOR, act_spectator) |