diff --git a/autogen/convert_functions.py b/autogen/convert_functions.py index 27348d30..9f784d9c 100644 --- a/autogen/convert_functions.py +++ b/autogen/convert_functions.py @@ -39,6 +39,7 @@ in_files = [ "src/game/object_helpers.c", "src/game/obj_behaviors.c", "src/game/obj_behaviors_2.c", + "src/game/spawn_sound.c", ] override_allowed_functions = { @@ -69,6 +70,7 @@ override_disallowed_functions = { "src/game/object_helpers.c": [ "spawn_obj", "^bhv_", "abs[fi]", "^bit_shift", "_debug$", "^stub_" ], "src/game/obj_behaviors.c": [ "debug_" ], "src/game/obj_behaviors_2.c": [ "wiggler_jumped_on_attack_handler", "huge_goomba_weakly_attacked" ], + "src/game/spawn_sound.c": [ "spawner" ], } lua_function_params = { diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py index 0c543ec8..a6ca42ab 100644 --- a/autogen/convert_structs.py +++ b/autogen/convert_structs.py @@ -16,6 +16,7 @@ in_files = [ 'src/game/object_helpers.h', 'src/game/mario_step.h', 'src/pc/lua/smlua_anim_utils.h', + 'src/game/spawn_sound.h', ] smlua_cobject_autogen = 'src/pc/lua/smlua_cobject_autogen' diff --git a/docs/lua/functions.md b/docs/lua/functions.md index fa5ff1cf..e5d85788 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -644,6 +644,15 @@
+- spawn_sound.c + - [calc_dist_to_volume_range_1](#calc_dist_to_volume_range_1) + - [calc_dist_to_volume_range_2](#calc_dist_to_volume_range_2) + - [cur_obj_play_sound_1](#cur_obj_play_sound_1) + - [cur_obj_play_sound_2](#cur_obj_play_sound_2) + - [exec_anim_sound_state](#exec_anim_sound_state) + +
+ - surface_collision.h - [find_ceil_height](#find_ceil_height) - [find_floor_height](#find_floor_height) @@ -11843,6 +11852,112 @@
+--- +# functions from spawn_sound.c + +
+ + +## [calc_dist_to_volume_range_1](#calc_dist_to_volume_range_1) + +### Lua Example +`local integerValue = calc_dist_to_volume_range_1(distance)` + +### Parameters +| Field | Type | +| ----- | ---- | +| distance | number | + +### Returns +- integer + +### C Prototype +`s32 calc_dist_to_volume_range_1(f32 distance);` + +[:arrow_up_small:](#) + +
+ +## [calc_dist_to_volume_range_2](#calc_dist_to_volume_range_2) + +### Lua Example +`local integerValue = calc_dist_to_volume_range_2(distance)` + +### Parameters +| Field | Type | +| ----- | ---- | +| distance | number | + +### Returns +- integer + +### C Prototype +`s32 calc_dist_to_volume_range_2(f32 distance);` + +[:arrow_up_small:](#) + +
+ +## [cur_obj_play_sound_1](#cur_obj_play_sound_1) + +### Lua Example +`cur_obj_play_sound_1(soundMagic)` + +### Parameters +| Field | Type | +| ----- | ---- | +| soundMagic | integer | + +### Returns +- None + +### C Prototype +`void cur_obj_play_sound_1(s32 soundMagic);` + +[:arrow_up_small:](#) + +
+ +## [cur_obj_play_sound_2](#cur_obj_play_sound_2) + +### Lua Example +`cur_obj_play_sound_2(soundMagic)` + +### Parameters +| Field | Type | +| ----- | ---- | +| soundMagic | integer | + +### Returns +- None + +### C Prototype +`void cur_obj_play_sound_2(s32 soundMagic);` + +[:arrow_up_small:](#) + +
+ +## [exec_anim_sound_state](#exec_anim_sound_state) + +### Lua Example +`exec_anim_sound_state(soundStates)` + +### Parameters +| Field | Type | +| ----- | ---- | +| soundStates | [SoundState](structs.md#SoundState) | + +### Returns +- None + +### C Prototype +`void exec_anim_sound_state(struct SoundState *soundStates);` + +[:arrow_up_small:](#) + +
+ --- # functions from surface_collision.h diff --git a/docs/lua/structs.md b/docs/lua/structs.md index ee6c7782..56d7bfb9 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -40,6 +40,7 @@ - [PlayerCameraState](#PlayerCameraState) - [PlayerGeometry](#PlayerGeometry) - [SPTask](#SPTask) +- [SoundState](#SoundState) - [SpawnInfo](#SpawnInfo) - [SpawnParticlesInfo](#SpawnParticlesInfo) - [Struct802A272C](#Struct802A272C) @@ -1603,6 +1604,19 @@
+## [SoundState](#SoundState) + +| Field | Type | Access | +| ----- | ---- | ------ | +| animFrame1 | integer | | +| animFrame2 | integer | | +| playSound | integer | | +| soundMagic | integer | | + +[:arrow_up_small:](#) + +
+ ## [SpawnInfo](#SpawnInfo) | Field | Type | Access | diff --git a/src/pc/lua/smlua_cobject.c b/src/pc/lua/smlua_cobject.c index b877e435..7798f09b 100644 --- a/src/pc/lua/smlua_cobject.c +++ b/src/pc/lua/smlua_cobject.c @@ -30,7 +30,7 @@ struct LuaObjectTable sLuaObjectTable[LOT_MAX] = { { LOT_VEC3F, sVec3fFields, LUA_VEC3F_FIELD_COUNT }, }; -static struct LuaObjectField* smlua_get_object_field(u16 lot, const char* key) { +struct LuaObjectField* smlua_get_object_field(u16 lot, const char* key) { if (lot > LOT_AUTOGEN_MIN) { return smlua_get_object_field_autogen(lot, key); } @@ -174,7 +174,7 @@ static int smlua_func_define_custom_obj_fields(lua_State* L) { return 1; } -static struct LuaObjectField* smlua_get_custom_field(lua_State* L, u32 lot, int keyIndex) { +struct LuaObjectField* smlua_get_custom_field(lua_State* L, u32 lot, int keyIndex) { LUA_STACK_CHECK_BEGIN(); static struct LuaObjectField lof = { 0 }; if (lot != LOT_OBJECT) { return NULL; } diff --git a/src/pc/lua/smlua_cobject.h b/src/pc/lua/smlua_cobject.h index 53c22a9b..9d0857c7 100644 --- a/src/pc/lua/smlua_cobject.h +++ b/src/pc/lua/smlua_cobject.h @@ -54,6 +54,8 @@ struct LuaObjectTable { bool smlua_valid_lot(u16 lot); bool smlua_valid_lvt(u16 lvt); +struct LuaObjectField* smlua_get_object_field(u16 lot, const char* key); +struct LuaObjectField* smlua_get_custom_field(lua_State* L, u32 lot, int keyIndex); void smlua_cobject_init_globals(void); void smlua_cobject_init_per_file_globals(char* path); void smlua_bind_cobject(void); diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index 0f6cb36e..5b22134f 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -11,6 +11,7 @@ #include "src/game/object_helpers.h" #include "src/game/mario_step.h" #include "src/pc/lua/smlua_anim_utils.h" +#include "src/game/spawn_sound.h" #include "include/object_fields.h" @@ -1403,6 +1404,14 @@ static struct LuaObjectField sPlayerGeometryFields[LUA_PLAYER_GEOMETRY_FIELD_COU { "waterHeight", LVT_F32, offsetof(struct PlayerGeometry, waterHeight), false, LOT_NONE }, }; +#define LUA_SOUND_STATE_FIELD_COUNT 4 +static struct LuaObjectField sSoundStateFields[LUA_SOUND_STATE_FIELD_COUNT] = { + { "animFrame1", LVT_S8, offsetof(struct SoundState, animFrame1), false, LOT_NONE }, + { "animFrame2", LVT_S8, offsetof(struct SoundState, animFrame2), false, LOT_NONE }, + { "playSound", LVT_S16, offsetof(struct SoundState, playSound), false, LOT_NONE }, + { "soundMagic", LVT_S32, offsetof(struct SoundState, soundMagic), false, LOT_NONE }, +}; + #define LUA_SPAWN_INFO_FIELD_COUNT 7 static struct LuaObjectField sSpawnInfoFields[LUA_SPAWN_INFO_FIELD_COUNT] = { { "activeAreaIndex", LVT_S8, offsetof(struct SpawnInfo, activeAreaIndex), false, LOT_NONE }, @@ -1590,6 +1599,7 @@ struct LuaObjectTable sLuaObjectAutogenTable[LOT_AUTOGEN_MAX - LOT_AUTOGEN_MIN] { LOT_PARALLELTRACKINGPOINT, sParallelTrackingPointFields, LUA_PARALLEL_TRACKING_POINT_FIELD_COUNT }, { LOT_PLAYERCAMERASTATE, sPlayerCameraStateFields, LUA_PLAYER_CAMERA_STATE_FIELD_COUNT }, { LOT_PLAYERGEOMETRY, sPlayerGeometryFields, LUA_PLAYER_GEOMETRY_FIELD_COUNT }, + { LOT_SOUNDSTATE, sSoundStateFields, LUA_SOUND_STATE_FIELD_COUNT }, { LOT_SPAWNINFO, sSpawnInfoFields, LUA_SPAWN_INFO_FIELD_COUNT }, { LOT_SPAWNPARTICLESINFO, sSpawnParticlesInfoFields, LUA_SPAWN_PARTICLES_INFO_FIELD_COUNT }, { LOT_STRUCT802A272C, sStruct802A272CFields, LUA_STRUCT802_A272_C_FIELD_COUNT }, diff --git a/src/pc/lua/smlua_cobject_autogen.h b/src/pc/lua/smlua_cobject_autogen.h index f7ea8ed8..0eaceeb1 100644 --- a/src/pc/lua/smlua_cobject_autogen.h +++ b/src/pc/lua/smlua_cobject_autogen.h @@ -42,6 +42,7 @@ enum LuaObjectAutogenType { LOT_PARALLELTRACKINGPOINT, LOT_PLAYERCAMERASTATE, LOT_PLAYERGEOMETRY, + LOT_SOUNDSTATE, LOT_SPAWNINFO, LOT_SPAWNPARTICLESINFO, LOT_STRUCT802A272C, diff --git a/src/pc/lua/smlua_functions.c b/src/pc/lua/smlua_functions.c index db8406fc..fd176352 100644 --- a/src/pc/lua/smlua_functions.c +++ b/src/pc/lua/smlua_functions.c @@ -1,4 +1,5 @@ #include "smlua.h" +#include "smlua_cobject.h" #include "game/level_update.h" #include "game/area.h" @@ -79,6 +80,83 @@ int smlua_func_init_mario_after_warp(lua_State* L) { return 1; } +int smlua_func_network_init_object(lua_State* L) { + if (!smlua_functions_valid_param_count(L, 3)) { return 0; } + + struct Object* obj = smlua_to_cobject(L, 1, LOT_OBJECT); + if (!gSmLuaConvertSuccess || obj == NULL) { return 0; } + + bool standardSync = smlua_to_boolean(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + + if (lua_type(L, 3) != LUA_TNIL && lua_type(L, 3) != LUA_TTABLE) { + LOG_LUA("network_init_object() called with an invalid type for param 3: %u", lua_type(L, 3)); + return 0; + } + + struct SyncObject* so = network_init_object(obj, standardSync ? 4000.0f : SYNC_DISTANCE_ONLY_EVENTS); + if (so == NULL) { + LOG_LUA("Failed to allocate sync object."); + return 0; + } + + if (lua_type(L, 3) == LUA_TTABLE) { + lua_pushnil(L); // first key + + while (lua_next(L, 3) != 0) { + // uses 'key' (at index -2) and 'value' (at index -1) + if (lua_type(L, -1) != LUA_TSTRING) { + LOG_LUA("Invalid type passed to network_init_object(): %u", lua_type(L, -1)); + lua_pop(L, 1); // pop value + continue; + } + const char* fieldIdentifier = smlua_to_string(L, -1); + if (!gSmLuaConvertSuccess || fieldIdentifier[0] != 'o') { + LOG_LUA("Invalid field passed to network_init_object()"); + lua_pop(L, 1); // pop value + continue; + } + + struct LuaObjectField* data = smlua_get_object_field(LOT_OBJECT, fieldIdentifier); + if (data == NULL) { + data = smlua_get_custom_field(L, LOT_OBJECT, lua_gettop(L)); + } + if (data == NULL) { + LOG_LUA("Invalid field passed to network_init_object(): %s", fieldIdentifier); + lua_pop(L, 1); // pop value + continue; + } + + u8* field = ((u8*)(intptr_t)obj) + data->valueOffset; + network_init_object_field(obj, field); + + lua_pop(L, 1); // pop value + } + lua_pop(L, 1); // pop key + } + + return 1; +} + +int smlua_func_network_send_object(lua_State* L) { + if (!smlua_functions_valid_param_count(L, 2)) { return 0; } + + struct Object* obj = smlua_to_cobject(L, 1, LOT_OBJECT); + if (!gSmLuaConvertSuccess || obj == NULL) { return 0; } + + bool reliable = smlua_to_boolean(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + + if (obj->oSyncID == 0 || gSyncObjects[obj->oSyncID].o != obj) { + LOG_LUA("Failed to retrieve sync object."); + return 0; + } + + network_send_object_reliability(obj, reliable); + + return 1; +} + ////////// // bind // ////////// @@ -91,4 +169,6 @@ void smlua_bind_functions(void) { smlua_bind_function(L, "coss", smlua_func_coss); smlua_bind_function(L, "atan2s", smlua_func_atan2s); smlua_bind_function(L, "init_mario_after_warp", smlua_func_init_mario_after_warp); -} \ No newline at end of file + smlua_bind_function(L, "network_init_object", smlua_func_network_init_object); + smlua_bind_function(L, "network_send_object", smlua_func_network_send_object); +} diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index ce0f56a0..18d4b3e1 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -7582,6 +7582,70 @@ int smlua_func_stop_shell_music(UNUSED lua_State* L) { return 1; } + /////////////////// + // spawn_sound.c // +/////////////////// + +int smlua_func_calc_dist_to_volume_range_1(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 1)) { return 0; } + + f32 distance = smlua_to_number(L, 1); + if (!gSmLuaConvertSuccess) { return 0; } + + extern s32 calc_dist_to_volume_range_1(f32 distance); + lua_pushinteger(L, calc_dist_to_volume_range_1(distance)); + + return 1; +} + +int smlua_func_calc_dist_to_volume_range_2(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 1)) { return 0; } + + f32 distance = smlua_to_number(L, 1); + if (!gSmLuaConvertSuccess) { return 0; } + + extern s32 calc_dist_to_volume_range_2(f32 distance); + lua_pushinteger(L, calc_dist_to_volume_range_2(distance)); + + return 1; +} + +int smlua_func_cur_obj_play_sound_1(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 1)) { return 0; } + + s32 soundMagic = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { return 0; } + + extern void cur_obj_play_sound_1(s32 soundMagic); + cur_obj_play_sound_1(soundMagic); + + return 1; +} + +int smlua_func_cur_obj_play_sound_2(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 1)) { return 0; } + + s32 soundMagic = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { return 0; } + + extern void cur_obj_play_sound_2(s32 soundMagic); + cur_obj_play_sound_2(soundMagic); + + return 1; +} + +int smlua_func_exec_anim_sound_state(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 1)) { return 0; } + + struct SoundState* soundStates = (struct SoundState*)smlua_to_cobject(L, 1, LOT_SOUNDSTATE); + if (!gSmLuaConvertSuccess) { return 0; } + + extern void exec_anim_sound_state(struct SoundState *soundStates); + exec_anim_sound_state(soundStates); + + return 1; +} + ///////////////////////// // surface_collision.h // ///////////////////////// @@ -8422,6 +8486,13 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "stop_cap_music", smlua_func_stop_cap_music); smlua_bind_function(L, "stop_shell_music", smlua_func_stop_shell_music); + // spawn_sound.c + smlua_bind_function(L, "calc_dist_to_volume_range_1", smlua_func_calc_dist_to_volume_range_1); + smlua_bind_function(L, "calc_dist_to_volume_range_2", smlua_func_calc_dist_to_volume_range_2); + smlua_bind_function(L, "cur_obj_play_sound_1", smlua_func_cur_obj_play_sound_1); + smlua_bind_function(L, "cur_obj_play_sound_2", smlua_func_cur_obj_play_sound_2); + smlua_bind_function(L, "exec_anim_sound_state", smlua_func_exec_anim_sound_state); + // surface_collision.h //smlua_bind_function(L, "find_ceil", smlua_func_find_ceil); <--- UNIMPLEMENTED smlua_bind_function(L, "find_ceil_height", smlua_func_find_ceil_height); diff --git a/src/pc/lua/smlua_hooks.c b/src/pc/lua/smlua_hooks.c index f4a25883..3048315d 100644 --- a/src/pc/lua/smlua_hooks.c +++ b/src/pc/lua/smlua_hooks.c @@ -305,6 +305,7 @@ u32 smlua_get_action_interaction_type(struct MarioState* m) { struct LuaHookedBehavior { u32 behaviorId; + u32 overrideId; BehaviorScript behavior[2]; int initReference; int loopReference; @@ -331,7 +332,7 @@ const BehaviorScript* get_lua_behavior_from_id(enum BehaviorId id) { if (L == NULL) { return false; } for (int i = 0; i < sHookedBehaviorsCount; i++) { struct LuaHookedBehavior* hooked = &sHookedBehaviors[i]; - if (hooked->behaviorId != id) { continue; } + if (hooked->behaviorId != id && hooked->overrideId != id) { continue; } return hooked->behavior; } return NULL; @@ -396,7 +397,8 @@ int smlua_hook_behavior(lua_State* L) { struct LuaHookedBehavior* hooked = &sHookedBehaviors[sHookedBehaviorsCount]; u16 customBehaviorId = (sHookedBehaviorsCount & 0xFFFF) | LUA_BEHAVIOR_FLAG; - hooked->behaviorId = overrideBehaviorId != 0 ? overrideBehaviorId : customBehaviorId; + hooked->behaviorId = customBehaviorId; + hooked->overrideId = (overrideBehaviorId == 0) ? customBehaviorId : overrideBehaviorId; hooked->behavior[0] = (((unsigned int) (((unsigned int)(0x00) & ((0x01 << (8)) - 1)) << (24))) | ((unsigned int) (((unsigned int)(objectList) & ((0x01 << (8)) - 1)) << (16)))); // gross. this is BEGIN(objectList) hooked->behavior[1] = (((unsigned int) (((unsigned int)(0x39) & ((0x01 << (8)) - 1)) << (24))) | ((unsigned int) (((unsigned int)(customBehaviorId) & ((0x01 << (16)) - 1)) << (0)))); // gross. this is ID(customBehaviorId) hooked->initReference = initReference; @@ -643,11 +645,13 @@ static void smlua_clear_hooks(void) { sHookedEvents[i].reference[j] = 0; } sHookedEvents[i].count = 0; + sHookedEvents[i].entry = NULL; } for (int i = 0; i < sHookedMarioActionsCount; i++) { sHookedMarioActions[i].action = 0; sHookedMarioActions[i].reference = 0; + sHookedMarioActions[i].entry = NULL; } sHookedMarioActionsCount = 0; @@ -659,6 +663,7 @@ static void smlua_clear_hooks(void) { sHookedChatCommands[i].description = NULL; sHookedChatCommands[i].reference = 0; + sHookedChatCommands[i].entry = NULL; } sHookedChatCommandsCount = 0; @@ -669,6 +674,7 @@ static void smlua_clear_hooks(void) { hooked->behavior[1] = 0; hooked->initReference = 0; hooked->loopReference = 0; + hooked->entry = NULL; } sHookedBehaviorsCount = 0; }