diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua
index a3143cc5..dfd74aa6 100644
--- a/autogen/lua_definitions/constants.lua
+++ b/autogen/lua_definitions/constants.lua
@@ -12584,9 +12584,21 @@ GRAPH_NODE_GUARD = 0xAA
--- @type integer
MAX_PLAYERS = 16
+--- @type integer
+OBJECT_CUSTOM_FIELDS_START = (OBJECT_NUM_REGULAR_FIELDS)
+
--- @type integer
OBJECT_MAX_BHV_STACK = 16
+--- @type integer
+OBJECT_NUM_CUSTOM_FIELDS = 0x10
+
+--- @type integer
+OBJECT_NUM_FIELDS = (OBJECT_CUSTOM_FIELDS_START + OBJECT_NUM_CUSTOM_FIELDS)
+
+--- @type integer
+OBJECT_NUM_REGULAR_FIELDS = 0x50
+
--- @type integer
PLAY_MODE_CHANGE_AREA = 3
diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua
index 172ac491..b9acd8cd 100644
--- a/autogen/lua_definitions/functions.lua
+++ b/autogen/lua_definitions/functions.lua
@@ -9386,6 +9386,35 @@ function obj_get_collided_object(o, index)
-- ...
end
+--- @param o Object
+--- @param fieldIndex integer
+--- @return number
+function obj_get_field_f32(o, fieldIndex)
+ -- ...
+end
+
+--- @param o Object
+--- @param fieldIndex integer
+--- @param fieldSubIndex integer
+--- @return integer
+function obj_get_field_s16(o, fieldIndex, fieldSubIndex)
+ -- ...
+end
+
+--- @param o Object
+--- @param fieldIndex integer
+--- @return integer
+function obj_get_field_s32(o, fieldIndex)
+ -- ...
+end
+
+--- @param o Object
+--- @param fieldIndex integer
+--- @return integer
+function obj_get_field_u32(o, fieldIndex)
+ -- ...
+end
+
--- @param objList ObjectList
--- @return Object
function obj_get_first(objList)
@@ -9532,6 +9561,39 @@ function obj_move_xyz(o, dx, dy, dz)
-- ...
end
+--- @param o Object
+--- @param fieldIndex integer
+--- @param value number
+--- @return nil
+function obj_set_field_f32(o, fieldIndex, value)
+ -- ...
+end
+
+--- @param o Object
+--- @param fieldIndex integer
+--- @param fieldSubIndex integer
+--- @param value integer
+--- @return nil
+function obj_set_field_s16(o, fieldIndex, fieldSubIndex, value)
+ -- ...
+end
+
+--- @param o Object
+--- @param fieldIndex integer
+--- @param value integer
+--- @return nil
+function obj_set_field_s32(o, fieldIndex, value)
+ -- ...
+end
+
+--- @param o Object
+--- @param fieldIndex integer
+--- @param value integer
+--- @return nil
+function obj_set_field_u32(o, fieldIndex, value)
+ -- ...
+end
+
--- @param o Object
--- @param modelId ModelExtendedId
--- @return nil
diff --git a/docs/lua/constants.md b/docs/lua/constants.md
index f180873e..2deced44 100644
--- a/docs/lua/constants.md
+++ b/docs/lua/constants.md
@@ -4459,7 +4459,11 @@
- COOP_OBJ_FLAG_NON_SYNC
- GRAPH_NODE_GUARD
- MAX_PLAYERS
+- OBJECT_CUSTOM_FIELDS_START
- OBJECT_MAX_BHV_STACK
+- OBJECT_NUM_CUSTOM_FIELDS
+- OBJECT_NUM_FIELDS
+- OBJECT_NUM_REGULAR_FIELDS
- PLAY_MODE_CHANGE_AREA
- PLAY_MODE_CHANGE_LEVEL
- PLAY_MODE_FRAME_ADVANCE
diff --git a/docs/lua/functions-5.md b/docs/lua/functions-5.md
index 2383065f..88d79b70 100644
--- a/docs/lua/functions-5.md
+++ b/docs/lua/functions-5.md
@@ -2618,6 +2618,91 @@
+## [obj_get_field_f32](#obj_get_field_f32)
+
+### Lua Example
+`local numberValue = obj_get_field_f32(o, fieldIndex)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| o | [Object](structs.md#Object) |
+| fieldIndex | `integer` |
+
+### Returns
+- `number`
+
+### C Prototype
+`f32 obj_get_field_f32(struct Object *o, s32 fieldIndex);`
+
+[:arrow_up_small:](#)
+
+
+
+## [obj_get_field_s16](#obj_get_field_s16)
+
+### Lua Example
+`local integerValue = obj_get_field_s16(o, fieldIndex, fieldSubIndex)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| o | [Object](structs.md#Object) |
+| fieldIndex | `integer` |
+| fieldSubIndex | `integer` |
+
+### Returns
+- `integer`
+
+### C Prototype
+`s16 obj_get_field_s16(struct Object *o, s32 fieldIndex, s32 fieldSubIndex);`
+
+[:arrow_up_small:](#)
+
+
+
+## [obj_get_field_s32](#obj_get_field_s32)
+
+### Lua Example
+`local integerValue = obj_get_field_s32(o, fieldIndex)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| o | [Object](structs.md#Object) |
+| fieldIndex | `integer` |
+
+### Returns
+- `integer`
+
+### C Prototype
+`s32 obj_get_field_s32(struct Object *o, s32 fieldIndex);`
+
+[:arrow_up_small:](#)
+
+
+
+## [obj_get_field_u32](#obj_get_field_u32)
+
+### Lua Example
+`local integerValue = obj_get_field_u32(o, fieldIndex)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| o | [Object](structs.md#Object) |
+| fieldIndex | `integer` |
+
+### Returns
+- `integer`
+
+### C Prototype
+`u32 obj_get_field_u32(struct Object *o, s32 fieldIndex);`
+
+[:arrow_up_small:](#)
+
+
+
## [obj_get_first](#obj_get_first)
### Lua Example
@@ -3072,6 +3157,95 @@
+## [obj_set_field_f32](#obj_set_field_f32)
+
+### Lua Example
+`obj_set_field_f32(o, fieldIndex, value)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| o | [Object](structs.md#Object) |
+| fieldIndex | `integer` |
+| value | `number` |
+
+### Returns
+- None
+
+### C Prototype
+`void obj_set_field_f32(struct Object *o, s32 fieldIndex, f32 value);`
+
+[:arrow_up_small:](#)
+
+
+
+## [obj_set_field_s16](#obj_set_field_s16)
+
+### Lua Example
+`obj_set_field_s16(o, fieldIndex, fieldSubIndex, value)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| o | [Object](structs.md#Object) |
+| fieldIndex | `integer` |
+| fieldSubIndex | `integer` |
+| value | `integer` |
+
+### Returns
+- None
+
+### C Prototype
+`void obj_set_field_s16(struct Object *o, s32 fieldIndex, s32 fieldSubIndex, s16 value);`
+
+[:arrow_up_small:](#)
+
+
+
+## [obj_set_field_s32](#obj_set_field_s32)
+
+### Lua Example
+`obj_set_field_s32(o, fieldIndex, value)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| o | [Object](structs.md#Object) |
+| fieldIndex | `integer` |
+| value | `integer` |
+
+### Returns
+- None
+
+### C Prototype
+`void obj_set_field_s32(struct Object *o, s32 fieldIndex, s32 value);`
+
+[:arrow_up_small:](#)
+
+
+
+## [obj_set_field_u32](#obj_set_field_u32)
+
+### Lua Example
+`obj_set_field_u32(o, fieldIndex, value)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| o | [Object](structs.md#Object) |
+| fieldIndex | `integer` |
+| value | `integer` |
+
+### Returns
+- None
+
+### C Prototype
+`void obj_set_field_u32(struct Object *o, s32 fieldIndex, u32 value);`
+
+[:arrow_up_small:](#)
+
+
+
## [obj_set_model_extended](#obj_set_model_extended)
### Lua Example
diff --git a/docs/lua/functions.md b/docs/lua/functions.md
index 6c32e341..75955e61 100644
--- a/docs/lua/functions.md
+++ b/docs/lua/functions.md
@@ -1739,6 +1739,10 @@
- [obj_check_overlap_with_hitbox_params](functions-5.md#obj_check_overlap_with_hitbox_params)
- [obj_count_objects_with_behavior_id](functions-5.md#obj_count_objects_with_behavior_id)
- [obj_get_collided_object](functions-5.md#obj_get_collided_object)
+ - [obj_get_field_f32](functions-5.md#obj_get_field_f32)
+ - [obj_get_field_s16](functions-5.md#obj_get_field_s16)
+ - [obj_get_field_s32](functions-5.md#obj_get_field_s32)
+ - [obj_get_field_u32](functions-5.md#obj_get_field_u32)
- [obj_get_first](functions-5.md#obj_get_first)
- [obj_get_first_with_behavior_id](functions-5.md#obj_get_first_with_behavior_id)
- [obj_get_first_with_behavior_id_and_field_f32](functions-5.md#obj_get_first_with_behavior_id_and_field_f32)
@@ -1761,6 +1765,10 @@
- [obj_is_secret](functions-5.md#obj_is_secret)
- [obj_is_valid_for_interaction](functions-5.md#obj_is_valid_for_interaction)
- [obj_move_xyz](functions-5.md#obj_move_xyz)
+ - [obj_set_field_f32](functions-5.md#obj_set_field_f32)
+ - [obj_set_field_s16](functions-5.md#obj_set_field_s16)
+ - [obj_set_field_s32](functions-5.md#obj_set_field_s32)
+ - [obj_set_field_u32](functions-5.md#obj_set_field_u32)
- [obj_set_model_extended](functions-5.md#obj_set_model_extended)
- [obj_set_vel](functions-5.md#obj_set_vel)
- [set_whirlpools](functions-5.md#set_whirlpools)
diff --git a/include/types.h b/include/types.h
index 547021e7..2d77d927 100644
--- a/include/types.h
+++ b/include/types.h
@@ -19,8 +19,6 @@
#define BAD_RETURN(cmd) cmd
#endif
-#define OBJECT_MAX_BHV_STACK 16
-
struct Controller
{
/*0x00*/ s16 rawStickX; //
@@ -190,6 +188,12 @@ struct ObjectNode
// NOTE: Since ObjectNode is the first member of Object, it is difficult to determine
// whether some of these pointers point to ObjectNode or Object.
+#define OBJECT_MAX_BHV_STACK 16
+#define OBJECT_NUM_REGULAR_FIELDS 0x50
+#define OBJECT_NUM_CUSTOM_FIELDS 0x10
+#define OBJECT_CUSTOM_FIELDS_START (OBJECT_NUM_REGULAR_FIELDS)
+#define OBJECT_NUM_FIELDS (OBJECT_CUSTOM_FIELDS_START + OBJECT_NUM_CUSTOM_FIELDS)
+
struct Object
{
/*0x000*/ struct ObjectNode header;
@@ -203,21 +207,21 @@ struct Object
union
{
// Object fields. See object_fields.h.
- u32 asU32[0x50];
- s32 asS32[0x50];
- s16 asS16[0x50][2];
- f32 asF32[0x50];
+ u32 asU32[OBJECT_NUM_FIELDS];
+ s32 asS32[OBJECT_NUM_FIELDS];
+ s16 asS16[OBJECT_NUM_FIELDS][2];
+ f32 asF32[OBJECT_NUM_FIELDS];
} rawData;
union {
- s16 *asS16P[0x50];
- s32 *asS32P[0x50];
- struct AnimationTable *asAnims[0x50];
- struct Waypoint *asWaypoint[0x50];
- struct ChainSegment *asChainSegment[0x50];
- struct Object *asObject[0x50];
- struct Surface *asSurface[0x50];
- void *asVoidPtr[0x50];
- const void *asConstVoidPtr[0x50];
+ s16 *asS16P[OBJECT_NUM_FIELDS];
+ s32 *asS32P[OBJECT_NUM_FIELDS];
+ struct AnimationTable *asAnims[OBJECT_NUM_FIELDS];
+ struct Waypoint *asWaypoint[OBJECT_NUM_FIELDS];
+ struct ChainSegment *asChainSegment[OBJECT_NUM_FIELDS];
+ struct Object *asObject[OBJECT_NUM_FIELDS];
+ struct Surface *asSurface[OBJECT_NUM_FIELDS];
+ void *asVoidPtr[OBJECT_NUM_FIELDS];
+ const void *asConstVoidPtr[OBJECT_NUM_FIELDS];
} ptrData;
/*0x1C8*/ u32 unused1;
/*0x1CC*/ const BehaviorScript *curBhvCommand;
diff --git a/src/game/spawn_object.c b/src/game/spawn_object.c
index c903b1b3..497cfab2 100644
--- a/src/game/spawn_object.c
+++ b/src/game/spawn_object.c
@@ -279,7 +279,7 @@ struct Object *allocate_object(struct ObjectNode *objList) {
obj->collidedObjInteractTypes = 0;
obj->numCollidedObjs = 0;
- for (s32 i = 0; i < 0x50; i++) {
+ for (s32 i = 0; i < OBJECT_NUM_FIELDS; i++) {
obj->rawData.asS32[i] = 0;
obj->ptrData.asVoidPtr[i] = NULL;
}
diff --git a/src/pc/lua/smlua_cobject.c b/src/pc/lua/smlua_cobject.c
index 9eaebc0f..9cc36f28 100644
--- a/src/pc/lua/smlua_cobject.c
+++ b/src/pc/lua/smlua_cobject.c
@@ -124,7 +124,12 @@ bool smlua_valid_lvt(u16 lvt) {
// obj behavior //
//////////////////
-#define CUSTOM_FIELD_MAX 11
+static const struct { enum LuaValueType lvt; const char *name; } sCustomFieldValidTypes[] = {
+ { LVT_U32, "u32" },
+ { LVT_S32, "s32" },
+ { LVT_F32, "f32" },
+};
+
#define CUSTOM_FIELD_ITEM_LEN 48
struct CustomFieldItem {
char key[CUSTOM_FIELD_ITEM_LEN];
@@ -168,6 +173,24 @@ static void smlua_add_custom_field_linked(struct CustomFieldItem** head, struct
}
}
+static enum LuaValueType smlua_get_custom_field_type(const char *name) {
+ for (s32 i = 0; i != ARRAY_COUNT(sCustomFieldValidTypes); ++i) {
+ if (strcmp(name, sCustomFieldValidTypes[i].name) == 0) {
+ return sCustomFieldValidTypes[i].lvt;
+ }
+ }
+ return LVT_MAX;
+}
+
+static const char *smlua_get_custom_field_type_name(enum LuaValueType lvt) {
+ for (s32 i = 0; i != ARRAY_COUNT(sCustomFieldValidTypes); ++i) {
+ if (lvt == sCustomFieldValidTypes[i].lvt) {
+ return sCustomFieldValidTypes[i].name;
+ }
+ }
+ return NULL;
+}
+
static int smlua_func_define_custom_obj_fields(lua_State* L) {
LUA_STACK_CHECK_BEGIN();
if (!smlua_functions_valid_param_count(L, 1)) { return 0; }
@@ -183,7 +206,7 @@ static int smlua_func_define_custom_obj_fields(lua_State* L) {
}
struct CustomFieldItem* customFieldsHead = NULL;
- struct CustomFieldItem customFields[CUSTOM_FIELD_MAX] = { 0 };
+ struct CustomFieldItem customFields[OBJECT_NUM_CUSTOM_FIELDS] = { 0 };
u16 customFieldCount = 0;
// get _custom_object_fields
@@ -227,16 +250,13 @@ static int smlua_func_define_custom_obj_fields(lua_State* L) {
}
const char* value = smlua_to_string(L, valueIndex);
- enum LuaValueType lvt = LVT_U32;
- if (!strcmp(value, "u32")) { lvt = LVT_U32; }
- else if (!strcmp(value, "s32")) { lvt = LVT_S32; }
- else if (!strcmp(value, "f32")) { lvt = LVT_F32; }
- else {
+ enum LuaValueType lvt = smlua_get_custom_field_type(value);
+ if (lvt == LVT_MAX) {
LOG_LUA_LINE("Invalid value name for define_custom_obj_fields()");
return 0;
}
- if (customFieldCount >= CUSTOM_FIELD_MAX) {
+ if (customFieldCount >= OBJECT_NUM_CUSTOM_FIELDS) {
LOG_LUA_LINE("Ran out of custom fields!");
return 0;
}
@@ -250,14 +270,9 @@ static int smlua_func_define_custom_obj_fields(lua_State* L) {
lua_settop(L, iterationTop);
struct CustomFieldItem* node = customFieldsHead;
- u32 fieldIndex = 0x1B;
+ u32 fieldIndex = OBJECT_CUSTOM_FIELDS_START;
while (node != NULL) {
- // keep fieldIndex in range
- if (fieldIndex < 0x1B) {
- fieldIndex = 0x1B;
- } else if (fieldIndex > 0x22 && fieldIndex < 0x48) {
- fieldIndex = 0x48;
- } else if (fieldIndex > 0x4A) {
+ if (fieldIndex >= OBJECT_NUM_FIELDS) {
LOG_LUA_LINE("Ran out of custom fields!");
return 0;
}
@@ -278,7 +293,7 @@ static int smlua_func_define_custom_obj_fields(lua_State* L) {
}
lua_settable(L, -3); // set _custom_object_fields
- LOG_INFO("Registered custom object field: %02X - %s", fieldIndex, node->key);
+ LOG_INFO("Registered custom object field: 0x%02X as %s - %s", fieldIndex, smlua_get_custom_field_type_name(node->lvt), node->key);
fieldIndex++;
@@ -326,7 +341,7 @@ struct LuaObjectField* smlua_get_custom_field(lua_State* L, u32 lot, int keyInde
lua_rawget(L, -2);
u32 fieldIndex = smlua_to_integer(L, -1);
lua_pop(L, 1);
- bool validFieldIndex = (fieldIndex >= 0x1B && fieldIndex <= 0x22) || (fieldIndex >= 0x48 && fieldIndex <= 0x4A);
+ bool validFieldIndex = (fieldIndex >= OBJECT_CUSTOM_FIELDS_START && fieldIndex < OBJECT_NUM_FIELDS);
if (!gSmLuaConvertSuccess || !validFieldIndex) {
lua_pop(L, 1); // pop value table
lua_pop(L, 1); // pop _custom_fields
diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c
index f6722c90..e63748b2 100644
--- a/src/pc/lua/smlua_constants_autogen.c
+++ b/src/pc/lua/smlua_constants_autogen.c
@@ -4381,7 +4381,6 @@ char gSmluaConstants[] = ""
"TERRAIN_WATER = 0x0005\n"
"TERRAIN_SLIDE = 0x0006\n"
"TERRAIN_MASK = 0x0007\n"
-"OBJECT_MAX_BHV_STACK = 16\n"
"SPTASK_STATE_NOT_STARTED = 0\n"
"SPTASK_STATE_RUNNING = 1\n"
"SPTASK_STATE_INTERRUPTED = 2\n"
@@ -4399,6 +4398,11 @@ char gSmluaConstants[] = ""
"ANIM_FLAG_6 = (1 << 6)\n"
"ANIM_FLAG_7 = (1 << 7)\n"
"GRAPH_NODE_GUARD = 0xAA\n"
+"OBJECT_MAX_BHV_STACK = 16\n"
+"OBJECT_NUM_REGULAR_FIELDS = 0x50\n"
+"OBJECT_NUM_CUSTOM_FIELDS = 0x10\n"
+"OBJECT_CUSTOM_FIELDS_START = (OBJECT_NUM_REGULAR_FIELDS)\n"
+"OBJECT_NUM_FIELDS = (OBJECT_CUSTOM_FIELDS_START + OBJECT_NUM_CUSTOM_FIELDS)\n"
"PLAY_MODE_NORMAL = 0\n"
"PLAY_MODE_PAUSED = 2\n"
"PLAY_MODE_CHANGE_AREA = 3\n"
diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c
index 79c414ed..611697ad 100644
--- a/src/pc/lua/smlua_functions_autogen.c
+++ b/src/pc/lua/smlua_functions_autogen.c
@@ -30656,6 +30656,84 @@ int smlua_func_obj_get_collided_object(lua_State* L) {
return 1;
}
+int smlua_func_obj_get_field_f32(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 2) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "obj_get_field_f32", 2, top);
+ return 0;
+ }
+
+ struct Object* o = (struct Object*)smlua_to_cobject(L, 1, LOT_OBJECT);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "obj_get_field_f32"); return 0; }
+ s32 fieldIndex = smlua_to_integer(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "obj_get_field_f32"); return 0; }
+
+ lua_pushnumber(L, obj_get_field_f32(o, fieldIndex));
+
+ return 1;
+}
+
+int smlua_func_obj_get_field_s16(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", "obj_get_field_s16", 3, top);
+ return 0;
+ }
+
+ struct Object* o = (struct Object*)smlua_to_cobject(L, 1, LOT_OBJECT);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "obj_get_field_s16"); return 0; }
+ s32 fieldIndex = smlua_to_integer(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "obj_get_field_s16"); return 0; }
+ s32 fieldSubIndex = smlua_to_integer(L, 3);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "obj_get_field_s16"); return 0; }
+
+ lua_pushinteger(L, obj_get_field_s16(o, fieldIndex, fieldSubIndex));
+
+ return 1;
+}
+
+int smlua_func_obj_get_field_s32(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 2) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "obj_get_field_s32", 2, top);
+ return 0;
+ }
+
+ struct Object* o = (struct Object*)smlua_to_cobject(L, 1, LOT_OBJECT);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "obj_get_field_s32"); return 0; }
+ s32 fieldIndex = smlua_to_integer(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "obj_get_field_s32"); return 0; }
+
+ lua_pushinteger(L, obj_get_field_s32(o, fieldIndex));
+
+ return 1;
+}
+
+int smlua_func_obj_get_field_u32(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 2) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "obj_get_field_u32", 2, top);
+ return 0;
+ }
+
+ struct Object* o = (struct Object*)smlua_to_cobject(L, 1, LOT_OBJECT);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "obj_get_field_u32"); return 0; }
+ s32 fieldIndex = smlua_to_integer(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "obj_get_field_u32"); return 0; }
+
+ lua_pushinteger(L, obj_get_field_u32(o, fieldIndex));
+
+ return 1;
+}
+
int smlua_func_obj_get_first(lua_State* L) {
if (L == NULL) { return 0; }
@@ -31058,6 +31136,92 @@ int smlua_func_obj_move_xyz(lua_State* L) {
return 1;
}
+int smlua_func_obj_set_field_f32(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", "obj_set_field_f32", 3, top);
+ return 0;
+ }
+
+ struct Object* o = (struct Object*)smlua_to_cobject(L, 1, LOT_OBJECT);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "obj_set_field_f32"); return 0; }
+ s32 fieldIndex = smlua_to_integer(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "obj_set_field_f32"); return 0; }
+ f32 value = smlua_to_number(L, 3);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "obj_set_field_f32"); return 0; }
+
+ obj_set_field_f32(o, fieldIndex, value);
+
+ return 1;
+}
+
+int smlua_func_obj_set_field_s16(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 4) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "obj_set_field_s16", 4, top);
+ return 0;
+ }
+
+ struct Object* o = (struct Object*)smlua_to_cobject(L, 1, LOT_OBJECT);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "obj_set_field_s16"); return 0; }
+ s32 fieldIndex = smlua_to_integer(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "obj_set_field_s16"); return 0; }
+ s32 fieldSubIndex = smlua_to_integer(L, 3);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "obj_set_field_s16"); return 0; }
+ s16 value = smlua_to_integer(L, 4);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "obj_set_field_s16"); return 0; }
+
+ obj_set_field_s16(o, fieldIndex, fieldSubIndex, value);
+
+ return 1;
+}
+
+int smlua_func_obj_set_field_s32(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", "obj_set_field_s32", 3, top);
+ return 0;
+ }
+
+ struct Object* o = (struct Object*)smlua_to_cobject(L, 1, LOT_OBJECT);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "obj_set_field_s32"); return 0; }
+ s32 fieldIndex = smlua_to_integer(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "obj_set_field_s32"); return 0; }
+ s32 value = smlua_to_integer(L, 3);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "obj_set_field_s32"); return 0; }
+
+ obj_set_field_s32(o, fieldIndex, value);
+
+ return 1;
+}
+
+int smlua_func_obj_set_field_u32(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", "obj_set_field_u32", 3, top);
+ return 0;
+ }
+
+ struct Object* o = (struct Object*)smlua_to_cobject(L, 1, LOT_OBJECT);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "obj_set_field_u32"); return 0; }
+ s32 fieldIndex = smlua_to_integer(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "obj_set_field_u32"); return 0; }
+ u32 value = smlua_to_integer(L, 3);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "obj_set_field_u32"); return 0; }
+
+ obj_set_field_u32(o, fieldIndex, value);
+
+ return 1;
+}
+
int smlua_func_obj_set_model_extended(lua_State* L) {
if (L == NULL) { return 0; }
@@ -33812,6 +33976,10 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "obj_check_overlap_with_hitbox_params", smlua_func_obj_check_overlap_with_hitbox_params);
smlua_bind_function(L, "obj_count_objects_with_behavior_id", smlua_func_obj_count_objects_with_behavior_id);
smlua_bind_function(L, "obj_get_collided_object", smlua_func_obj_get_collided_object);
+ smlua_bind_function(L, "obj_get_field_f32", smlua_func_obj_get_field_f32);
+ smlua_bind_function(L, "obj_get_field_s16", smlua_func_obj_get_field_s16);
+ smlua_bind_function(L, "obj_get_field_s32", smlua_func_obj_get_field_s32);
+ smlua_bind_function(L, "obj_get_field_u32", smlua_func_obj_get_field_u32);
smlua_bind_function(L, "obj_get_first", smlua_func_obj_get_first);
smlua_bind_function(L, "obj_get_first_with_behavior_id", smlua_func_obj_get_first_with_behavior_id);
smlua_bind_function(L, "obj_get_first_with_behavior_id_and_field_f32", smlua_func_obj_get_first_with_behavior_id_and_field_f32);
@@ -33834,6 +34002,10 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "obj_is_secret", smlua_func_obj_is_secret);
smlua_bind_function(L, "obj_is_valid_for_interaction", smlua_func_obj_is_valid_for_interaction);
smlua_bind_function(L, "obj_move_xyz", smlua_func_obj_move_xyz);
+ smlua_bind_function(L, "obj_set_field_f32", smlua_func_obj_set_field_f32);
+ smlua_bind_function(L, "obj_set_field_s16", smlua_func_obj_set_field_s16);
+ smlua_bind_function(L, "obj_set_field_s32", smlua_func_obj_set_field_s32);
+ smlua_bind_function(L, "obj_set_field_u32", smlua_func_obj_set_field_u32);
smlua_bind_function(L, "obj_set_model_extended", smlua_func_obj_set_model_extended);
smlua_bind_function(L, "obj_set_vel", smlua_func_obj_set_vel);
smlua_bind_function(L, "set_whirlpools", smlua_func_set_whirlpools);
diff --git a/src/pc/lua/smlua_hooks.c b/src/pc/lua/smlua_hooks.c
index 9c3f7df9..31f1dfc2 100644
--- a/src/pc/lua/smlua_hooks.c
+++ b/src/pc/lua/smlua_hooks.c
@@ -1379,7 +1379,7 @@ int smlua_hook_custom_bhv(BehaviorScript *bhvScript, const char *bhvName) {
if (L != NULL) {
lua_pushinteger(L, customBehaviorId);
lua_setglobal(L, bhvName);
- LOG_INFO("Registered custom behavior: %04hX - %s", customBehaviorId, bhvName);
+ LOG_INFO("Registered custom behavior: 0x%04hX - %s", customBehaviorId, bhvName);
}
return 1;
@@ -1518,7 +1518,7 @@ int smlua_hook_behavior(lua_State* L) {
// It's also used for some things that would normally access a LUA behavior instead.
lua_pushinteger(L, customBehaviorId);
lua_setglobal(L, bhvName);
- LOG_INFO("Registered custom behavior: %04hX - %s", customBehaviorId, bhvName);
+ LOG_INFO("Registered custom behavior: 0x%04hX - %s", customBehaviorId, bhvName);
// return behavior ID
lua_pushinteger(L, customBehaviorId);
diff --git a/src/pc/lua/utils/smlua_obj_utils.c b/src/pc/lua/utils/smlua_obj_utils.c
index e2a5e955..3a891633 100644
--- a/src/pc/lua/utils/smlua_obj_utils.c
+++ b/src/pc/lua/utils/smlua_obj_utils.c
@@ -138,7 +138,7 @@ struct Object *obj_get_first_with_behavior_id(enum BehaviorId behaviorId) {
}
struct Object *obj_get_first_with_behavior_id_and_field_s32(enum BehaviorId behaviorId, s32 fieldIndex, s32 value) {
- if (fieldIndex < 0 || fieldIndex >= 0x50) { return NULL; }
+ if (fieldIndex < 0 || fieldIndex >= OBJECT_NUM_FIELDS) { return NULL; }
const BehaviorScript* behavior = get_behavior_from_id(behaviorId);
u32 sanityDepth = 0;
behavior = smlua_override_behavior(behavior);
@@ -155,7 +155,7 @@ struct Object *obj_get_first_with_behavior_id_and_field_s32(enum BehaviorId beha
}
struct Object *obj_get_first_with_behavior_id_and_field_f32(enum BehaviorId behaviorId, s32 fieldIndex, f32 value) {
- if (fieldIndex < 0 || fieldIndex >= 0x50) { return NULL; }
+ if (fieldIndex < 0 || fieldIndex >= OBJECT_NUM_FIELDS) { return NULL; }
const BehaviorScript* behavior = get_behavior_from_id(behaviorId);
behavior = smlua_override_behavior(behavior);
if (behavior) {
@@ -229,7 +229,7 @@ struct Object *obj_get_next_with_same_behavior_id(struct Object *o) {
}
struct Object *obj_get_next_with_same_behavior_id_and_field_s32(struct Object *o, s32 fieldIndex, s32 value) {
- if (fieldIndex < 0 || fieldIndex >= 0x50) { return NULL; }
+ if (fieldIndex < 0 || fieldIndex >= OBJECT_NUM_FIELDS) { return NULL; }
if (o) {
for (struct Object *obj = obj_get_next(o); obj != NULL; obj = obj_get_next(obj)) {
if (obj->behavior == o->behavior && obj->activeFlags != ACTIVE_FLAG_DEACTIVATED && obj->OBJECT_FIELD_S32(fieldIndex) == value) {
@@ -241,7 +241,7 @@ struct Object *obj_get_next_with_same_behavior_id_and_field_s32(struct Object *o
}
struct Object *obj_get_next_with_same_behavior_id_and_field_f32(struct Object *o, s32 fieldIndex, f32 value) {
- if (fieldIndex < 0 || fieldIndex >= 0x50) { return NULL; }
+ if (fieldIndex < 0 || fieldIndex >= OBJECT_NUM_FIELDS) { return NULL; }
if (o) {
for (struct Object *obj = obj_get_next(o); obj != NULL; obj = obj_get_next(obj)) {
if (obj->behavior == o->behavior && obj->activeFlags != ACTIVE_FLAG_DEACTIVATED && obj->OBJECT_FIELD_F32(fieldIndex) == value) {
@@ -259,6 +259,66 @@ struct Object *obj_get_collided_object(struct Object *o, s16 index) {
return NULL;
}
+//
+// Object fields
+//
+
+u32 obj_get_field_u32(struct Object *o, s32 fieldIndex) {
+ if (o && fieldIndex >= 0 && fieldIndex < OBJECT_NUM_FIELDS) {
+ return o->OBJECT_FIELD_U32(fieldIndex);
+ }
+ return 0;
+}
+
+s32 obj_get_field_s32(struct Object *o, s32 fieldIndex) {
+ if (o && fieldIndex >= 0 && fieldIndex < OBJECT_NUM_FIELDS) {
+ return o->OBJECT_FIELD_S32(fieldIndex);
+ }
+ return 0;
+}
+
+f32 obj_get_field_f32(struct Object *o, s32 fieldIndex) {
+ if (o && fieldIndex >= 0 && fieldIndex < OBJECT_NUM_FIELDS) {
+ return o->OBJECT_FIELD_F32(fieldIndex);
+ }
+ return 0;
+}
+
+s16 obj_get_field_s16(struct Object *o, s32 fieldIndex, s32 fieldSubIndex) {
+ if (o && fieldIndex >= 0 && fieldIndex < OBJECT_NUM_FIELDS && fieldSubIndex >= 0 && fieldSubIndex < 2) {
+ return o->OBJECT_FIELD_S16(fieldIndex, fieldSubIndex);
+ }
+ return 0;
+}
+
+void obj_set_field_u32(struct Object *o, s32 fieldIndex, u32 value) {
+ if (o && fieldIndex >= 0 && fieldIndex < OBJECT_NUM_FIELDS) {
+ o->OBJECT_FIELD_U32(fieldIndex) = value;
+ }
+}
+
+void obj_set_field_s32(struct Object *o, s32 fieldIndex, s32 value) {
+ if (o && fieldIndex >= 0 && fieldIndex < OBJECT_NUM_FIELDS) {
+ o->OBJECT_FIELD_S32(fieldIndex) = value;
+ }
+}
+
+void obj_set_field_f32(struct Object *o, s32 fieldIndex, f32 value) {
+ if (o && fieldIndex >= 0 && fieldIndex < OBJECT_NUM_FIELDS) {
+ o->OBJECT_FIELD_F32(fieldIndex) = value;
+ }
+}
+
+void obj_set_field_s16(struct Object *o, s32 fieldIndex, s32 fieldSubIndex, s16 value) {
+ if (o && fieldIndex >= 0 && fieldIndex < OBJECT_NUM_FIELDS && fieldSubIndex >= 0 && fieldSubIndex < 2) {
+ o->OBJECT_FIELD_S16(fieldIndex, fieldSubIndex) = value;
+ }
+}
+
+//
+// Misc object helpers
+//
+
struct SpawnParticlesInfo* obj_get_temp_spawn_particles_info(enum ModelExtendedId modelId) {
static struct SpawnParticlesInfo sTmpSpi = { 0 };
memset(&sTmpSpi, 0, sizeof(struct SpawnParticlesInfo));
@@ -413,7 +473,7 @@ void set_whirlpools(f32 x, f32 y, f32 z, s16 strength, s16 area, s32 index) {
#ifdef DEVELOPMENT
void obj_randomize(struct Object* o) {
if (!o) { return; }
- for (int i = 0; i < 80; i++) {
+ for (int i = 0; i < OBJECT_NUM_FIELDS; i++) {
if (rand() % 10 < 5) {
o->rawData.asU32[i] = rand() % 10;
} else {
diff --git a/src/pc/lua/utils/smlua_obj_utils.h b/src/pc/lua/utils/smlua_obj_utils.h
index 48b0963f..e90fac0e 100644
--- a/src/pc/lua/utils/smlua_obj_utils.h
+++ b/src/pc/lua/utils/smlua_obj_utils.h
@@ -34,7 +34,23 @@ s32 obj_count_objects_with_behavior_id(enum BehaviorId behaviorId);
struct Object *obj_get_collided_object(struct Object *o, s16 index);
-// misc obj helpers
+//
+// Object fields
+//
+
+u32 obj_get_field_u32(struct Object *o, s32 fieldIndex);
+s32 obj_get_field_s32(struct Object *o, s32 fieldIndex);
+f32 obj_get_field_f32(struct Object *o, s32 fieldIndex);
+s16 obj_get_field_s16(struct Object *o, s32 fieldIndex, s32 fieldSubIndex);
+
+void obj_set_field_u32(struct Object *o, s32 fieldIndex, u32 value);
+void obj_set_field_s32(struct Object *o, s32 fieldIndex, s32 value);
+void obj_set_field_f32(struct Object *o, s32 fieldIndex, f32 value);
+void obj_set_field_s16(struct Object *o, s32 fieldIndex, s32 fieldSubIndex, s16 value);
+
+//
+// Misc object helpers
+//
struct SpawnParticlesInfo* obj_get_temp_spawn_particles_info(enum ModelExtendedId modelId);
struct ObjectHitbox* get_temp_object_hitbox(void);
diff --git a/src/pc/network/packets/packet_object.c b/src/pc/network/packets/packet_object.c
index 459e051d..b1ec3fca 100644
--- a/src/pc/network/packets/packet_object.c
+++ b/src/pc/network/packets/packet_object.c
@@ -150,7 +150,7 @@ static void packet_write_object_full_sync(struct Packet* p, struct Object* o) {
if (!so || !so->fullObjectSync) { return; }
// write all of raw data
- packet_write(p, o->rawData.asU32, sizeof(u32) * 80);
+ packet_write(p, o->rawData.asU32, sizeof(u32) * OBJECT_NUM_FIELDS);
}
static void packet_read_object_full_sync(struct Packet* p, struct Object* o) {
@@ -158,7 +158,7 @@ static void packet_read_object_full_sync(struct Packet* p, struct Object* o) {
if (!so || !so->fullObjectSync) { return; }
// read all of raw data
- packet_read(p, o->rawData.asU32, sizeof(u32) * 80);
+ packet_read(p, o->rawData.asU32, sizeof(u32) * OBJECT_NUM_FIELDS);
}
// ----- standard fields ----- //
diff --git a/src/pc/network/packets/packet_player.c b/src/pc/network/packets/packet_player.c
index aa3c89e8..38f44cb7 100644
--- a/src/pc/network/packets/packet_player.c
+++ b/src/pc/network/packets/packet_player.c
@@ -18,7 +18,7 @@
#pragma pack(1)
struct PacketPlayerData {
- u32 rawData[80];
+ u32 rawData[OBJECT_NUM_REGULAR_FIELDS];
s16 cRawStickX;
s16 cRawStickY;
@@ -86,7 +86,7 @@ static void read_packet_data(struct PacketPlayerData* data, struct MarioState* m
u8 customFlags = SET_BIT((m->freeze > 0), 0);
- memcpy(data->rawData, m->marioObj->rawData.asU32, sizeof(u32) * 80);
+ memcpy(data->rawData, m->marioObj->rawData.asU32, sizeof(u32) * OBJECT_NUM_REGULAR_FIELDS);
data->nodeFlags = m->marioObj->header.gfx.node.flags;
data->cRawStickX = m->controller->rawStickX;
@@ -148,7 +148,7 @@ static void write_packet_data(struct PacketPlayerData* data, struct MarioState*
u8* customFlags, u32* heldSyncID, u32* heldBySyncID,
u32* riddenSyncID, u32* interactSyncID, u32* usedSyncID,
u32* platformSyncID) {
- memcpy(m->marioObj->rawData.asU32, data->rawData, sizeof(u32) * 80);
+ memcpy(m->marioObj->rawData.asU32, data->rawData, sizeof(u32) * OBJECT_NUM_REGULAR_FIELDS);
m->marioObj->header.gfx.node.flags = data->nodeFlags;
m->controller->rawStickX = data->cRawStickX;
diff --git a/src/pc/network/packets/packet_spawn_objects.c b/src/pc/network/packets/packet_spawn_objects.c
index 89e8f40a..37ee7373 100644
--- a/src/pc/network/packets/packet_spawn_objects.c
+++ b/src/pc/network/packets/packet_spawn_objects.c
@@ -22,7 +22,7 @@ struct SpawnObjectData {
u32 model;
u32 behaviorId;
s16 activeFlags;
- s32 rawData[80];
+ s32 rawData[OBJECT_NUM_FIELDS];
u8 setHome;
u8 globalPlayerIndex;
u16 extendedModelId;
@@ -102,7 +102,7 @@ void network_send_spawn_objects_to(u8 sendToLocalIndex, struct Object* objects[]
packet_write(&p, &model, sizeof(u32));
packet_write(&p, &behaviorId, sizeof(u32));
packet_write(&p, &o->activeFlags, sizeof(s16));
- packet_write(&p, o->rawData.asU32, sizeof(u32) * 0x50);
+ packet_write(&p, o->rawData.asU32, sizeof(u32) * OBJECT_NUM_FIELDS);
packet_write(&p, &o->header.gfx.scale[0], sizeof(f32));
packet_write(&p, &o->header.gfx.scale[1], sizeof(f32));
packet_write(&p, &o->header.gfx.scale[2], sizeof(f32));
@@ -144,7 +144,7 @@ void network_receive_spawn_objects(struct Packet* p) {
packet_read(p, &data.model, sizeof(u32));
packet_read(p, &data.behaviorId, sizeof(u32));
packet_read(p, &data.activeFlags, sizeof(s16));
- packet_read(p, &data.rawData, sizeof(u32) * 0x50);
+ packet_read(p, &data.rawData, sizeof(u32) * OBJECT_NUM_FIELDS);
packet_read(p, &scale[0], sizeof(f32));
packet_read(p, &scale[1], sizeof(f32));
packet_read(p, &scale[2], sizeof(f32));
@@ -227,7 +227,7 @@ void network_receive_spawn_objects(struct Packet* p) {
o->coopFlags |= COOP_OBJ_FLAG_NETWORK;
o->setHome = data.setHome;
- memcpy(o->rawData.asU32, data.rawData, sizeof(u32) * 80);
+ memcpy(o->rawData.asU32, data.rawData, sizeof(u32) * OBJECT_NUM_FIELDS);
o->header.gfx.scale[0] = scale[0];
o->header.gfx.scale[1] = scale[1];