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;
}