From 68eff636d9ad386a9859ffbf82eef65c35482060 Mon Sep 17 00:00:00 2001 From: MysterD Date: Tue, 18 Jan 2022 01:48:51 -0800 Subject: [PATCH] More Lua improvements, ported ACT_ROLL / ACT_ROLL_AIR from extended moveset --- build-windows-visual-studio/sm64ex.vcxproj | 6 + .../sm64ex.vcxproj.filters | 18 ++ mods/test.lua | 245 +++++++++++++++--- src/game/object_list_processor.c | 2 +- src/pc/lua/smlua.c | 14 +- src/pc/lua/smlua.h | 2 +- src/pc/lua/smlua_cobject.c | 20 +- src/pc/lua/smlua_functions.c | 161 +++++++++++- 8 files changed, 407 insertions(+), 61 deletions(-) diff --git a/build-windows-visual-studio/sm64ex.vcxproj b/build-windows-visual-studio/sm64ex.vcxproj index 2b40c1536..022a5dd95 100644 --- a/build-windows-visual-studio/sm64ex.vcxproj +++ b/build-windows-visual-studio/sm64ex.vcxproj @@ -3999,6 +3999,9 @@ + + + @@ -4441,6 +4444,9 @@ + + + diff --git a/build-windows-visual-studio/sm64ex.vcxproj.filters b/build-windows-visual-studio/sm64ex.vcxproj.filters index 9497a4b25..d689e2ce7 100644 --- a/build-windows-visual-studio/sm64ex.vcxproj.filters +++ b/build-windows-visual-studio/sm64ex.vcxproj.filters @@ -15297,6 +15297,15 @@ Source Files\src\pc\lua + + Source Files\src\pc\lua + + + Source Files\src\pc\lua + + + Source Files\src\pc\lua + @@ -16402,5 +16411,14 @@ Source Files\src\pc\lua + + Source Files\src\pc\lua + + + Source Files\src\pc\lua + + + Source Files\src\pc\lua + \ No newline at end of file diff --git a/mods/test.lua b/mods/test.lua index 3d864d475..9742616e5 100644 --- a/mods/test.lua +++ b/mods/test.lua @@ -10,10 +10,97 @@ for i=0,(MAX_PLAYERS-1) do gMarioStateExtras[i].spareInt = 0 end -function act_roll(mario_index) - print("rolling!") - local m = gMarioStates[mario_index] - local e = gMarioStateExtras[mario_index] +--------------------------------------------------------- + +function sins(theta) + return math.sin(theta * math.pi / (2 * 16384)) +end + +function coss(theta) + return math.cos(theta * math.pi / (2 * 16384)) +end + +--------------------------------------------------------- + +function increase_roll_yaw(m) + local newFacingDYaw = m.faceAngle.y - m.slideYaw + + if newFacingDYaw > 0 and newFacingDYaw <= 0x4000 then + newFacingDYaw = newFacingDYaw - 0x200 + if newFacingDYaw < 0 then + newFacingDYaw = 0 + end + elseif newFacingDYaw > -0x4000 and newFacingDYaw < 0 then + newFacingDYaw = newFacingDYaw + 0x200 + if newFacingDYaw > 0 then + newFacingDYaw = 0 + end + elseif newFacingDYaw > 0x4000 and newFacingDYaw < 0x8000 then + newFacingDYaw = newFacingDYaw + 0x200 + if newFacingDYaw > 0x8000 then + newFacingDYaw = 0x8000 + end + elseif newFacingDYaw > -0x8000 and newFacingDYaw < -0x4000 then + newFacingDYaw = newFacingDYaw - 0x200 + if newFacingDYaw < -0x8000 then + newFacingDYaw = -0x8000 + end + end + + if newFacingDYaw < -0x4000 or newFacingDYaw > 0x4000 then + m.faceAngle.y = m.faceAngle.y + 0x4000 + end +end + +function update_roll_sliding(m, stopSpeed) + local stopped = 0 + + local intendedDYaw = m.intendedYaw - m.slideYaw + local forward = coss(intendedDYaw) + local sideward = sins(intendedDYaw) + + --! 10k glitch + if forward < 0.0 and m.forwardVel >= 0.0 then + forward = forward * (0.5 + 0.5 * m.forwardVel / 100.0) + end + + local accel = 4.0 + local lossFactor = 0.994 + + local oldSpeed = math.sqrt(m.slideVelX * m.slideVelX + m.slideVelZ * m.slideVelZ) + + --! This is uses trig derivatives to rotate Mario's speed. + -- In vanilla, it was slightly off/asymmetric since it uses the new X speed, but the old + -- Z speed. I've gone and fixed it here. + local angleChange = (m.intendedMag / 32.0) --* 0.6 + local modSlideVelX = m.slideVelZ * angleChange * sideward * 0.05 + local modSlideVelZ = m.slideVelX * angleChange * sideward * 0.05 + + m.slideVelX = m.slideVelX + modSlideVelX + m.slideVelZ = m.slideVelZ - modSlideVelZ + + local newSpeed = math.sqrt(m.slideVelX * m.slideVelX + m.slideVelZ * m.slideVelZ) + + if oldSpeed > 0.0 and newSpeed > 0.0 then + m.slideVelX = m.slideVelX * oldSpeed / newSpeed + m.slideVelZ = m.slideVelZ * oldSpeed / newSpeed + end + + update_sliding_angle(m, accel, lossFactor) + increase_roll_yaw(m) + + if m.playerIndex == 0 and mario_floor_is_slope(m) == 0 and m.forwardVel * m.forwardVel < stopSpeed * stopSpeed then + mario_set_forward_vel(m, 0.0) + stopped = 1 + end + + return stopped +end + +--------------------------------------------------------- + +function act_roll(m) + local e = gMarioStateExtras[m.playerIndex] local MAX_NORMAL_ROLL_SPEED = 50.0 local ROLL_BOOST_GAIN = 10.0 @@ -31,56 +118,52 @@ function act_roll(mario_index) end elseif m.actionTimer >= ROLL_CANCEL_LOCKOUT_TIME or m.actionArg == 1 then if (m.input & INPUT_Z_DOWN) == 0 then - print("rolling -> walking") - return set_mario_action(mario_index, ACT_WALKING, 0); + return set_mario_action(m, ACT_WALKING, 0); end end if (m.input & INPUT_B_PRESSED) ~= 0 then - print("rolling -> rollout") - return set_jumping_action(mario_index, ACT_FORWARD_ROLLOUT, 0); + return set_jumping_action(m, ACT_FORWARD_ROLLOUT, 0); end if (m.input & INPUT_A_PRESSED) ~= 0 then - print("rolling -> long jump") - return set_jumping_action(mario_index, ACT_LONG_JUMP, 0); + return set_jumping_action(m, ACT_LONG_JUMP, 0); end if (m.controller.buttonPressed & R_TRIG) ~= 0 and m.actionTimer > 0 then m.vel.y = 19.0; - play_mario_sound(mario_index, SOUND_ACTION_TERRAIN_JUMP, 0); + play_mario_sound(m, SOUND_ACTION_TERRAIN_JUMP, 0); if e.spareInt >= BOOST_LOCKOUT_TIME then e.spareInt = 0; if m.forwardVel < MAX_NORMAL_ROLL_SPEED then - mario_set_forward_vel(mario_index, math.min(m.forwardVel + ROLL_BOOST_GAIN, MAX_NORMAL_ROLL_SPEED)); + mario_set_forward_vel(m, math.min(m.forwardVel + ROLL_BOOST_GAIN, MAX_NORMAL_ROLL_SPEED)); end m.particleFlags = m.particleFlags | PARTICLE_HORIZONTAL_STAR; -- ! playing this after the call to play_mario_sound seems to matter in making this sound play - ------ TODO: play_sound(SOUND_ACTION_SPIN, m.marioObj->header.gfx.cameraToObject); + local cx, cy, cz = get_camera_position() + play_sound(SOUND_ACTION_SPIN, cx, cy, cz) end - print("rolling -> rolling air") - return set_mario_action(mario_index, ACT_ROLL_AIR, m.actionArg); + return set_mario_action(m, ACT_ROLL_AIR, m.actionArg); end - set_mario_animation(mario_index, MARIO_ANIM_FORWARD_SPINNING); + set_mario_animation(m, MARIO_ANIM_FORWARD_SPINNING); - if update_sliding(mario_index, 10.0) ~= 0 then - print("rolling -> crouch slide") - return set_mario_action(mario_index, ACT_CROUCH_SLIDE, 0); + if update_roll_sliding(m, 10.0) ~= 0 then + return set_mario_action(m, ACT_CROUCH_SLIDE, 0); end - common_slide_action(mario_index, ACT_CROUCH_SLIDE, ACT_ROLL_AIR, MARIO_ANIM_FORWARD_SPINNING); + common_slide_action(m, ACT_CROUCH_SLIDE, ACT_ROLL_AIR, MARIO_ANIM_FORWARD_SPINNING); e.spareFloat = e.spareFloat + (0x80 * m.forwardVel); if e.spareFloat > 0x10000 then e.spareFloat = e.spareFloat - 0x10000; end - set_anim_to_frame(mario_index, 10 * e.spareFloat / 0x10000); + set_anim_to_frame(m, 10 * e.spareFloat / 0x10000); e.spareInt = e.spareInt + 1; @@ -89,34 +172,122 @@ function act_roll(mario_index) return 0; end -function act_roll_air(mario_index) - print("rolling air!") - return set_mario_action(mario_index, ACT_DIVE, 0); +function act_roll_air(m) + local e = gMarioStateExtras[m.playerIndex] + local MAX_NORMAL_ROLL_SPEED = 50.0 + local ROLL_AIR_CANCEL_LOCKOUT_TIME = 15 + + if m.actionTimer == 0 then + if m.prevAction ~= ACT_ROLL then + e.spareFloat = 0 + e.spareInt = 0 + end + end + + if (m.input & INPUT_Z_DOWN) == 0 and m.actionTimer >= ROLL_AIR_CANCEL_LOCKOUT_TIME then + return set_mario_action(m, ACT_FREEFALL, 0) + end + + set_mario_animation(m, MARIO_ANIM_FORWARD_SPINNING) + + local air_step = perform_air_step(m, 0) + if air_step == AIR_STEP_LANDED then + if check_fall_damage_or_get_stuck(m, ACT_HARD_BACKWARD_GROUND_KB) == 0 then + play_sound_and_spawn_particles(m, SOUND_ACTION_TERRAIN_STEP, 0) + return set_mario_action(m, ACT_ROLL, m.actionArg) + end + elseif air_step == AIR_STEP_HIT_WALL then + mario_bonk_reflection(m, false) + m.faceAngle.y = m.faceAngle.y + 0x8000 + + if m.vel.y > 0.0 then + m.vel.y = 0.0 + end + + m.particleFlags = m.particleFlags | PARTICLE_VERTICAL_STAR + return set_mario_action(m, ACT_BACKWARD_AIR_KB, 0) + end + + e.spareFloat = e.spareFloat + 0x80 * m.forwardVel + if e.spareFloat > 0x10000 then + e.spareFloat = e.spareFloat - 0x10000 + end + + set_anim_to_frame(m, 10 * e.spareFloat / 0x10000) + + e.spareInt = e.spareInt + 1 + m.actionTimer = m.actionTimer + 1 + + return false end + +--------------------------------------------------------- + function update() - --print("----------") - --print(gMarioStates) - --print(gMarioStates[0]) - --print(gMarioStates[0].pos) - --print(gMarioStates[0].pos.x) - --print(gMarioStates[0].pos.y) - --print(gMarioStates[0].pos.z) end -function mario_update(mario_index) - local m = gMarioStates[mario_index] +function mario_update(m) -- if m.vel.y > 0 then -- m.vel.y = m.vel.y + 2 -- end if m.action == ACT_DIVE_SLIDE then - set_mario_action(mario_index, ACT_ROLL, 0); + if (m.input & INPUT_ABOVE_SLIDE) == 0 then + if (m.input & INPUT_Z_DOWN) ~= 0 and m.actionTimer < 2 then + return set_mario_action(m, ACT_ROLL, 1) + elseif (m.input & INPUT_B_PRESSED) ~= 0 then + -- dive hop + -- m.vel.y = 21.0 + -- return set_mario_action(m, ACT_DIVE, 1) + end + end + m.actionTimer = m.actionTimer + 1 end -end -function override_mario_action(mario_index, action) - return (action == ACT_ROLL) or (action == ACT_ROLL_AIR) + if m.action == ACT_LONG_JUMP_LAND then + if (m.input & INPUT_Z_DOWN) ~= 0 and m.forwardVel > 15.0 and m.actionTimer < 1 then + play_mario_landing_sound_once(m, SOUND_ACTION_TERRAIN_LANDING); + return set_mario_action(m, ACT_ROLL, 1); + end + end + + if m.action == ACT_CROUCHING then + if (m.controller.buttonPressed & R_TRIG) ~= 0 then + m.vel.y = 19.0 + mario_set_forward_vel(m, 32.0) + play_mario_sound(m, SOUND_ACTION_TERRAIN_JUMP, 0) + + local cx, cy, cz = get_camera_position() + play_sound(SOUND_ACTION_SPIN, cx, cy, cz) + + return set_mario_action(m, ACT_ROLL_AIR, 0) + end + end + + if m.action == ACT_CROUCH_SLIDE then + if (m.controller.buttonPressed & R_TRIG) ~= 0 then + m.vel.y = 19.0 + mario_set_forward_vel(m, math.max(32, m.forwardVel)) + play_mario_sound(m, SOUND_ACTION_TERRAIN_JUMP, 0) + + local cx, cy, cz = get_camera_position() + play_sound(SOUND_ACTION_SPIN, cx, cy, cz) + + return set_mario_action(m, ACT_ROLL_AIR, 0) + end + end + + if m.action == ACT_GROUND_POUND_LAND then + if (m.controller.buttonPressed & R_TRIG) ~= 0 then + mario_set_forward_vel(m, 60) + + local cx, cy, cz = get_camera_position() + play_sound(SOUND_ACTION_SPIN, cx, cy, cz) + + return set_mario_action(m, ACT_ROLL, 0) + end + end end hook_event(HOOK_UPDATE, update) diff --git a/src/game/object_list_processor.c b/src/game/object_list_processor.c index ea484e182..292c14efe 100644 --- a/src/game/object_list_processor.c +++ b/src/game/object_list_processor.c @@ -286,7 +286,7 @@ void bhv_mario_update(void) { particleFlags = execute_mario_action(gCurrentObject); gCurrentObject->oMarioParticleFlags = particleFlags; - smlua_call_event_hooks_param(HOOK_MARIO_UPDATE, stateIndex); + smlua_call_event_hooks_mario_param(HOOK_MARIO_UPDATE, gMarioState); // Mario code updates MarioState's versions of position etc, so we need // to sync it with the Mario object diff --git a/src/pc/lua/smlua.c b/src/pc/lua/smlua.c index 55b06fa0f..96e3239cb 100644 --- a/src/pc/lua/smlua.c +++ b/src/pc/lua/smlua.c @@ -48,15 +48,18 @@ void smlua_call_event_hooks(enum LuaHookedEventType hookType) { } } -void smlua_call_event_hooks_param(enum LuaHookedEventType hookType, int param) { +void smlua_call_event_hooks_mario_param(enum LuaHookedEventType hookType, struct MarioState* m) { lua_State* L = gLuaState; struct LuaHookedEvent* hook = &sHookedEvents[hookType]; for (int i = 0; i < hook->count; i++) { // push the callback onto the stack lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]); - // push the param - lua_pushinteger(L, param); + // push mario state + lua_getglobal(L, "gMarioStates"); + lua_pushinteger(L, m->playerIndex); + lua_gettable(L, -2); + lua_remove(L, -2); // call the callback if (0 != lua_pcall(L, 1, 0, 0)) { @@ -101,8 +104,11 @@ bool smlua_call_action_hook(struct MarioState* m, s32* returnValue) { // push the callback onto the stack lua_rawgeti(L, LUA_REGISTRYINDEX, sHookedMarioActions[i].reference); - // push param + // push mario state + lua_getglobal(L, "gMarioStates"); lua_pushinteger(L, m->playerIndex); + lua_gettable(L, -2); + lua_remove(L, -2); // call the callback if (0 != lua_pcall(L, 1, 1, 0)) { diff --git a/src/pc/lua/smlua.h b/src/pc/lua/smlua.h index b9b606989..66fb492e2 100644 --- a/src/pc/lua/smlua.h +++ b/src/pc/lua/smlua.h @@ -24,7 +24,7 @@ enum LuaHookedEventType { extern lua_State* gLuaState; void smlua_call_event_hooks(enum LuaHookedEventType hookType); -void smlua_call_event_hooks_param(enum LuaHookedEventType hookType, int param); +void smlua_call_event_hooks_mario_param(enum LuaHookedEventType hookType, struct MarioState* m); bool smlua_call_action_hook(struct MarioState* m, s32* returnValue); diff --git a/src/pc/lua/smlua_cobject.c b/src/pc/lua/smlua_cobject.c index 3b7363482..1b4655eb4 100644 --- a/src/pc/lua/smlua_cobject.c +++ b/src/pc/lua/smlua_cobject.c @@ -181,16 +181,16 @@ static int smlua__get_field(lua_State* L) { u8* p = ((u8*)pointer) + data->valueOffset; switch (data->valueType) { - case LVT_U8: lua_pushinteger(L, *(u8* )p); break; - case LVT_U16: lua_pushinteger(L, *(u16*)p); break; - case LVT_U32: lua_pushinteger(L, *(u32*)p); break; - case LVT_S8: lua_pushinteger(L, *(s8* )p); break; - case LVT_S16: lua_pushinteger(L, *(s16*)p); break; - case LVT_S32: lua_pushinteger(L, *(s32*)p); break; - case LVT_F32: lua_pushnumber( L, *(f32*)p); break; - case LVT_VEC3S: smlua_push_object(L, LOT_VEC3S, p); break; - case LVT_VEC3F: smlua_push_object(L, LOT_VEC3F, p); break; - case LVT_CONTROLLER: smlua_push_object(L, LOT_CONTROLLER, p); break; + case LVT_U8: lua_pushinteger(L, *(u8* )p); break; + case LVT_U16: lua_pushinteger(L, *(u16*)p); break; + case LVT_U32: lua_pushinteger(L, *(u32*)p); break; + case LVT_S8: lua_pushinteger(L, *(s8* )p); break; + case LVT_S16: lua_pushinteger(L, *(s16*)p); break; + case LVT_S32: lua_pushinteger(L, *(s32*)p); break; + case LVT_F32: lua_pushnumber( L, *(f32*)p); break; + case LVT_VEC3S: smlua_push_object(L, LOT_VEC3S, p); break; + case LVT_VEC3F: smlua_push_object(L, LOT_VEC3F, p); break; + case LVT_CONTROLLER: smlua_push_object(L, LOT_CONTROLLER, *(struct Controller**)p); break; default: LOG_LUA("_get_field on unimplemented type '%d', key '%s'", data->valueType, key); return 0; diff --git a/src/pc/lua/smlua_functions.c b/src/pc/lua/smlua_functions.c index 18b4e0c96..5fc5b2475 100644 --- a/src/pc/lua/smlua_functions.c +++ b/src/pc/lua/smlua_functions.c @@ -7,32 +7,44 @@ #include "object_fields.h" int smlua_set_mario_action(lua_State* L) { - int index = lua_tointeger(L, -3); u32 action = lua_tointeger(L, -2); u32 actionArg = lua_tointeger(L, -1); + + lua_getfield(L, -3, "playerIndex"); + int index = lua_tointeger(L, -1); + lua_pushinteger(L, set_mario_action(&gMarioStates[index], action, actionArg)); return 1; } int smlua_set_jumping_action(lua_State* L) { - int index = lua_tointeger(L, -3); u32 action = lua_tointeger(L, -2); u32 actionArg = lua_tointeger(L, -1); + + lua_getfield(L, -3, "playerIndex"); + int index = lua_tointeger(L, -1); + lua_pushinteger(L, set_jumping_action(&gMarioStates[index], action, actionArg)); return 1; } int smlua_play_mario_sound(lua_State* L) { - int index = lua_tointeger(L, -3); s32 actionSound = lua_tointeger(L, -2); s32 marioSound = lua_tointeger(L, -1); + + lua_getfield(L, -3, "playerIndex"); + int index = lua_tointeger(L, -1); + play_mario_sound(&gMarioStates[index], actionSound, marioSound); return 1; } int smlua_mario_set_forward_vel(lua_State* L) { - int index = lua_tointeger(L, -2); f32 forwardVel = lua_tonumber(L, -1); + + lua_getfield(L, -2, "playerIndex"); + int index = lua_tointeger(L, -1); + mario_set_forward_vel(&gMarioStates[index], forwardVel); return 1; } @@ -46,37 +58,146 @@ int smlua_play_sound(lua_State* L) { } int smlua_set_mario_animation(lua_State* L) { - int index = lua_tointeger(L, -2); s32 targetAnimID = lua_tointeger(L, -1); + + lua_getfield(L, -2, "playerIndex"); + int index = lua_tointeger(L, -1); + lua_pushinteger(L, set_mario_animation(&gMarioStates[index], targetAnimID)); return 1; } int smlua_update_sliding(lua_State* L) { - int index = lua_tointeger(L, -2); f32 stopSpeed = lua_tonumber(L, -1); + + lua_getfield(L, -2, "playerIndex"); + int index = lua_tointeger(L, -1); + extern s32 update_sliding(struct MarioState* m, f32 stopSpeed); lua_pushinteger(L, update_sliding(&gMarioStates[index], stopSpeed)); return 1; } int smlua_common_slide_action(lua_State* L) { - int index = lua_tointeger(L, -4); u32 endAction = lua_tointeger(L, -3); u32 airAction = lua_tointeger(L, -2); u32 animation = lua_tointeger(L, -1); + + lua_getfield(L, -4, "playerIndex"); + int index = lua_tointeger(L, -1); + extern void common_slide_action(struct MarioState* m, u32 endAction, u32 airAction, s32 animation); common_slide_action(&gMarioStates[index], endAction, airAction, animation); return 1; } int smlua_set_anim_to_frame(lua_State* L) { - int index = lua_tointeger(L, -2); s16 animFrame = lua_tonumber(L, -1); + + lua_getfield(L, -2, "playerIndex"); + int index = lua_tointeger(L, -1); + set_anim_to_frame(&gMarioStates[index], animFrame); return 1; } +int smlua_update_sliding_angle(lua_State* L) { + f32 accel = lua_tonumber(L, -2); + f32 lossFactor = lua_tonumber(L, -1); + + lua_getfield(L, -3, "playerIndex"); + int index = lua_tointeger(L, -1); + + extern void update_sliding_angle(struct MarioState* m, f32 accel, f32 lossFactor); + update_sliding_angle(&gMarioStates[index], accel, lossFactor); + return 1; +} + +int smlua_mario_floor_is_slope(lua_State* L) { + lua_getfield(L, -1, "playerIndex"); + int index = lua_tointeger(L, -1); + + lua_pushinteger(L, mario_floor_is_slope(&gMarioStates[index])); + return 1; +} + +int smlua_perform_air_step(lua_State* L) { + u32 stepArg = lua_tointeger(L, -1); + + lua_getfield(L, -2, "playerIndex"); + int index = lua_tointeger(L, -1); + + extern s32 perform_air_step(struct MarioState* m, u32 stepArg); + lua_pushinteger(L, perform_air_step(&gMarioStates[index], stepArg)); + return 1; +} + +int smlua_check_fall_damage_or_get_stuck(lua_State* L) { + u32 hardFallAction = lua_tointeger(L, -1); + + lua_getfield(L, -2, "playerIndex"); + int index = lua_tointeger(L, -1); + + extern s32 check_fall_damage_or_get_stuck(struct MarioState* m, u32 hardFallAction); + lua_pushinteger(L, check_fall_damage_or_get_stuck(&gMarioStates[index], hardFallAction)); + return 1; +} + +int smlua_mario_bonk_reflection(lua_State* L) { + u32 negateSpeed = lua_tointeger(L, -1); + + lua_getfield(L, -2, "playerIndex"); + int index = lua_tointeger(L, -1); + + extern void mario_bonk_reflection(struct MarioState* m, u32 negateSpeed); + mario_bonk_reflection(&gMarioStates[index], negateSpeed); + return 1; +} + +int smlua_play_sound_and_spawn_particles(lua_State* L) { + u32 soundBits = lua_tointeger(L, -3); + u32 waveParticleType = lua_tointeger(L, -2); + + lua_getfield(L, -3, "playerIndex"); + int index = lua_tointeger(L, -1); + + extern void play_sound_and_spawn_particles(struct MarioState* m, u32 soundBits, u32 waveParticleType); + play_sound_and_spawn_particles(&gMarioStates[index], soundBits, waveParticleType); + return 1; +} + +int smlua_play_mario_landing_sound_once(lua_State* L) { + u32 soundBits = lua_tointeger(L, -1); + + lua_getfield(L, -2, "playerIndex"); + int index = lua_tointeger(L, -1); + + extern void play_mario_landing_sound_once(struct MarioState* m, u32 soundBits); + play_mario_landing_sound_once(&gMarioStates[index], soundBits); + return 1; +} + +int smlua_get_camera_position(lua_State* L) { + if (gMarioStates[0].marioObj == NULL) { + if (gCamera == NULL) { + lua_pushnumber(L, 0); + lua_pushnumber(L, 0); + lua_pushnumber(L, 0); + return 0; + } + lua_pushnumber(L, gCamera->pos[0]); + lua_pushnumber(L, gCamera->pos[1]); + lua_pushnumber(L, gCamera->pos[2]); + return 0; + } + + f32* pos = &gMarioStates[0].marioObj->header.gfx.cameraToObject[0]; + lua_pushnumber(L, pos[0]); + lua_pushnumber(L, pos[1]); + lua_pushnumber(L, pos[2]); + return 1; +} + void smlua_bind_functions(void) { lua_State* L = gLuaState; @@ -107,4 +228,28 @@ void smlua_bind_functions(void) { lua_pushcfunction(L, smlua_set_anim_to_frame); lua_setglobal(L, "set_anim_to_frame"); + lua_pushcfunction(L, smlua_update_sliding_angle); + lua_setglobal(L, "update_sliding_angle"); + + lua_pushcfunction(L, smlua_mario_floor_is_slope); + lua_setglobal(L, "mario_floor_is_slope"); + + lua_pushcfunction(L, smlua_perform_air_step); + lua_setglobal(L, "perform_air_step"); + + lua_pushcfunction(L, smlua_check_fall_damage_or_get_stuck); + lua_setglobal(L, "check_fall_damage_or_get_stuck"); + + lua_pushcfunction(L, smlua_mario_bonk_reflection); + lua_setglobal(L, "mario_bonk_reflection"); + + lua_pushcfunction(L, smlua_play_sound_and_spawn_particles); + lua_setglobal(L, "play_sound_and_spawn_particles"); + + lua_pushcfunction(L, smlua_play_mario_landing_sound_once); + lua_setglobal(L, "play_mario_landing_sound_once"); + + lua_pushcfunction(L, smlua_get_camera_position); + lua_setglobal(L, "get_camera_position"); + } \ No newline at end of file