sm64coopdx/mods/flood/spectator.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)