diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py
index 40fb5f646..3a88390ec 100644
--- a/autogen/convert_structs.py
+++ b/autogen/convert_structs.py
@@ -118,7 +118,7 @@ override_field_immutable = {
"GlobalObjectAnimations": [ "*"],
"SpawnParticlesInfo": [ "model" ],
"WaterDropletParams": [ "model" ],
- "MarioBodyState": [ "updateTorsoTime", "updateHeadPosTime", "animPartsPos", "currAnimPart" ],
+ "MarioBodyState": [ "updateTorsoTime", "updateHeadPosTime", "animPartsPos", "animPartsRot", "currAnimPart" ],
"Area": [ "localAreaTimer", "nextSyncID", "objectSpawnInfos", "paintingWarpNodes", "warpNodes" ],
"Mod": [ "*" ],
"ModFile": [ "*" ],
diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua
index 3348ebd77..816cc8018 100644
--- a/autogen/lua_definitions/functions.lua
+++ b/autogen/lua_definitions/functions.lua
@@ -11410,6 +11410,15 @@ function get_mario_anim_part_pos(m, animPart, pos)
-- ...
end
+--- @param m MarioState
+--- @param animPart integer
+--- @param rot Vec3s
+--- @return boolean
+--- Retrieves the animated part rotation associated to `animPart` from the MarioState `m` and stores it into `rot`. Returns `true` on success or `false` on failure
+function get_mario_anim_part_rot(m, animPart, rot)
+ -- ...
+end
+
--- @return integer
--- Gets the current save file number (1-indexed)
function get_current_save_file_num()
diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua
index c145789d7..c971ce2ff 100644
--- a/autogen/lua_definitions/structs.lua
+++ b/autogen/lua_definitions/structs.lua
@@ -1086,6 +1086,7 @@
--- @field public torsoPos Vec3f
--- @field public heldObjLastPosition Vec3f
--- @field public animPartsPos Vec3f[]
+--- @field public animPartsRot Vec3s[]
--- @field public currAnimPart integer
--- @field public updateTorsoTime integer
--- @field public updateHeadPosTime integer
diff --git a/docs/lua/functions-7.md b/docs/lua/functions-7.md
index d8c287a05..3373d70ee 100644
--- a/docs/lua/functions-7.md
+++ b/docs/lua/functions-7.md
@@ -1416,6 +1416,31 @@ Retrieves the animated part position associated to `animPart` from the MarioStat
+## [get_mario_anim_part_rot](#get_mario_anim_part_rot)
+
+### Description
+Retrieves the animated part rotation associated to `animPart` from the MarioState `m` and stores it into `rot`. Returns `true` on success or `false` on failure
+
+### Lua Example
+`local booleanValue = get_mario_anim_part_rot(m, animPart, rot)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| m | [MarioState](structs.md#MarioState) |
+| animPart | `integer` |
+| rot | [Vec3s](structs.md#Vec3s) |
+
+### Returns
+- `boolean`
+
+### C Prototype
+`bool get_mario_anim_part_rot(struct MarioState *m, u32 animPart, VEC_OUT Vec3s rot);`
+
+[:arrow_up_small:](#)
+
+
+
## [get_current_save_file_num](#get_current_save_file_num)
### Description
diff --git a/docs/lua/functions.md b/docs/lua/functions.md
index 959c0f30e..e2cff77bf 100644
--- a/docs/lua/functions.md
+++ b/docs/lua/functions.md
@@ -2031,6 +2031,7 @@
- [get_hand_foot_pos_y](functions-7.md#get_hand_foot_pos_y)
- [get_hand_foot_pos_z](functions-7.md#get_hand_foot_pos_z)
- [get_mario_anim_part_pos](functions-7.md#get_mario_anim_part_pos)
+ - [get_mario_anim_part_rot](functions-7.md#get_mario_anim_part_rot)
- [get_current_save_file_num](functions-7.md#get_current_save_file_num)
- [save_file_get_using_backup_slot](functions-7.md#save_file_get_using_backup_slot)
- [save_file_set_using_backup_slot](functions-7.md#save_file_set_using_backup_slot)
diff --git a/docs/lua/structs.md b/docs/lua/structs.md
index ee844a0df..f189b286d 100644
--- a/docs/lua/structs.md
+++ b/docs/lua/structs.md
@@ -1596,6 +1596,7 @@
| torsoPos | [Vec3f](structs.md#Vec3f) | read-only |
| heldObjLastPosition | [Vec3f](structs.md#Vec3f) | read-only |
| animPartsPos | `Array` <`Vec3f`> | read-only |
+| animPartsRot | `Array` <`Vec3s`> | read-only |
| currAnimPart | `integer` | read-only |
| updateTorsoTime | `integer` | read-only |
| updateHeadPosTime | `integer` | read-only |
diff --git a/include/types.h b/include/types.h
index e1fcc6c67..ea64ff19b 100644
--- a/include/types.h
+++ b/include/types.h
@@ -420,6 +420,7 @@ struct MarioBodyState
Vec3f heldObjLastPosition; /// also known as HOLP
Vec3f animPartsPos[MARIO_ANIM_PART_MAX];
+ Vec3s animPartsRot[MARIO_ANIM_PART_MAX];
u32 currAnimPart;
u32 updateTorsoTime;
diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c
index 85286a1b8..e744bdd21 100644
--- a/src/game/rendering_graph_node.c
+++ b/src/game/rendering_graph_node.c
@@ -1145,13 +1145,16 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) {
// Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; }
- // Mario anim part pos
+ // Mario anim part pos and rot
if (gCurMarioBodyState && !gCurGraphNodeHeldObject && gCurMarioBodyState->currAnimPart > MARIO_ANIM_PART_NONE && gCurMarioBodyState->currAnimPart < MARIO_ANIM_PART_MAX) {
get_pos_from_transform_mtx(
gCurMarioBodyState->animPartsPos[gCurMarioBodyState->currAnimPart],
gMatStack[gMatStackIndex],
*gCurGraphNodeCamera->matrixPtr
);
+
+ Vec3s rot = { rotation[2], rotation[0], rotation[1] };
+ vec3s_copy(gCurMarioBodyState->animPartsRot[gCurMarioBodyState->currAnimPart], rot);
}
if (gCurGraphNodeMarioState != NULL) {
@@ -1777,13 +1780,16 @@ static void geo_process_bone(struct GraphNodeBone *node) {
// Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; }
- // Mario anim part pos
+ // Mario anim part pos and rot
if (gCurMarioBodyState && !gCurGraphNodeHeldObject && gCurMarioBodyState->currAnimPart > MARIO_ANIM_PART_NONE && gCurMarioBodyState->currAnimPart < MARIO_ANIM_PART_MAX) {
get_pos_from_transform_mtx(
gCurMarioBodyState->animPartsPos[gCurMarioBodyState->currAnimPart],
gMatStack[gMatStackIndex],
*gCurGraphNodeCamera->matrixPtr
);
+
+ Vec3s rot = { rotation[2], rotation[0], rotation[1] };
+ vec3s_copy(gCurMarioBodyState->animPartsRot[gCurMarioBodyState->currAnimPart], rot);
}
if (gCurGraphNodeMarioState != NULL) {
diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c
index 5150d1d39..e2cbf87ea 100644
--- a/src/pc/lua/smlua_cobject_autogen.c
+++ b/src/pc/lua/smlua_cobject_autogen.c
@@ -1354,11 +1354,12 @@ static struct LuaObjectField sMarioAnimationFields[LUA_MARIO_ANIMATION_FIELD_COU
{ "targetAnim", LVT_COBJECT_P, offsetof(struct MarioAnimation, targetAnim), false, LOT_ANIMATION, 1, sizeof(struct Animation*) },
};
-#define LUA_MARIO_BODY_STATE_FIELD_COUNT 28
+#define LUA_MARIO_BODY_STATE_FIELD_COUNT 29
static struct LuaObjectField sMarioBodyStateFields[LUA_MARIO_BODY_STATE_FIELD_COUNT] = {
{ "action", LVT_U32, offsetof(struct MarioBodyState, action), false, LOT_NONE, 1, sizeof(u32) },
{ "allowPartRotation", LVT_U8, offsetof(struct MarioBodyState, allowPartRotation), false, LOT_NONE, 1, sizeof(u8) },
{ "animPartsPos", LVT_COBJECT, offsetof(struct MarioBodyState, animPartsPos), true, LOT_VEC3F, MARIO_ANIM_PART_MAX, sizeof(Vec3f) },
+ { "animPartsRot", LVT_COBJECT, offsetof(struct MarioBodyState, animPartsRot), true, LOT_VEC3S, MARIO_ANIM_PART_MAX, sizeof(Vec3s) },
{ "capState", LVT_S8, offsetof(struct MarioBodyState, capState), false, LOT_NONE, 1, sizeof(s8) },
{ "currAnimPart", LVT_U32, offsetof(struct MarioBodyState, currAnimPart), true, LOT_NONE, 1, sizeof(u32) },
{ "eyeState", LVT_S8, offsetof(struct MarioBodyState, eyeState), false, LOT_NONE, 1, sizeof(s8) },
diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c
index 41df9c493..60ced0477 100644
--- a/src/pc/lua/smlua_functions_autogen.c
+++ b/src/pc/lua/smlua_functions_autogen.c
@@ -34127,6 +34127,31 @@ int smlua_func_get_mario_anim_part_pos(lua_State* L) {
return 1;
}
+int smlua_func_get_mario_anim_part_rot(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 3) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "get_mario_anim_part_rot", 3, top);
+ return 0;
+ }
+
+ struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIOSTATE);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "get_mario_anim_part_rot"); return 0; }
+ u32 animPart = smlua_to_integer(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "get_mario_anim_part_rot"); return 0; }
+
+ Vec3s rot;
+ smlua_get_vec3s(rot, 3);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "get_mario_anim_part_rot"); return 0; }
+
+ lua_pushboolean(L, get_mario_anim_part_rot(m, animPart, rot));
+
+ smlua_push_vec3s(rot, 3);
+
+ return 1;
+}
+
int smlua_func_get_current_save_file_num(UNUSED lua_State* L) {
if (L == NULL) { return 0; }
@@ -38916,6 +38941,7 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "get_hand_foot_pos_y", smlua_func_get_hand_foot_pos_y);
smlua_bind_function(L, "get_hand_foot_pos_z", smlua_func_get_hand_foot_pos_z);
smlua_bind_function(L, "get_mario_anim_part_pos", smlua_func_get_mario_anim_part_pos);
+ smlua_bind_function(L, "get_mario_anim_part_rot", smlua_func_get_mario_anim_part_rot);
smlua_bind_function(L, "get_current_save_file_num", smlua_func_get_current_save_file_num);
smlua_bind_function(L, "save_file_get_using_backup_slot", smlua_func_save_file_get_using_backup_slot);
smlua_bind_function(L, "save_file_set_using_backup_slot", smlua_func_save_file_set_using_backup_slot);
diff --git a/src/pc/lua/utils/smlua_misc_utils.c b/src/pc/lua/utils/smlua_misc_utils.c
index 01968c484..bff36cbbf 100644
--- a/src/pc/lua/utils/smlua_misc_utils.c
+++ b/src/pc/lua/utils/smlua_misc_utils.c
@@ -376,6 +376,13 @@ bool get_mario_anim_part_pos(struct MarioState *m, u32 animPart, VEC_OUT Vec3f p
return true;
}
+bool get_mario_anim_part_rot(struct MarioState *m, u32 animPart, VEC_OUT Vec3s rot) {
+ if (!m) { return false; }
+ if (animPart >= MARIO_ANIM_PART_MAX) { return false; }
+ vec3s_copy(rot, m->marioBodyState->animPartsRot[animPart]);
+ return true;
+}
+
///
s16 get_current_save_file_num(void) {
diff --git a/src/pc/lua/utils/smlua_misc_utils.h b/src/pc/lua/utils/smlua_misc_utils.h
index f7a022d38..5171af3ee 100644
--- a/src/pc/lua/utils/smlua_misc_utils.h
+++ b/src/pc/lua/utils/smlua_misc_utils.h
@@ -169,6 +169,10 @@ f32 get_hand_foot_pos_z(struct MarioState* m, u8 index);
Retrieves the animated part position associated to `animPart` from the MarioState `m` and stores it into `pos`. Returns `true` on success or `false` on failure
|descriptionEnd| */
bool get_mario_anim_part_pos(struct MarioState *m, u32 animPart, VEC_OUT Vec3f pos);
+/* |description|
+Retrieves the animated part rotation associated to `animPart` from the MarioState `m` and stores it into `rot`. Returns `true` on success or `false` on failure
+|descriptionEnd| */
+bool get_mario_anim_part_rot(struct MarioState *m, u32 animPart, VEC_OUT Vec3s rot);
/* |description|Gets the current save file number (1-indexed)|descriptionEnd| */
s16 get_current_save_file_num(void);