From eaeaeb0f7fecc00e7b5ad249b1f64149090a0e69 Mon Sep 17 00:00:00 2001
From: Isaac0-dev <62234577+Isaac0-dev@users.noreply.github.com>
Date: Thu, 6 Jun 2024 17:24:28 +1000
Subject: [PATCH] add a way for mods to get dynamic surfaces that belong to
specific objects (#59)
Adding this for collision minimap, but I'm sure it'd be useful for many other mods that deal with collision in this kind of way
exposes a function, obj_get_surface_from_index. pass in an object, and the index of the surface you want. numSurfaces is also added to know when to stop iterating through surfaces
Thanks to peachy for coming up with the better method of doing this
Co-authored-by: PeachyPeach <72323920+PeachyPeachSM64@users.noreply.github.com>
---
autogen/convert_structs.py | 3 ++-
autogen/lua_definitions/functions.lua | 7 +++++++
autogen/lua_definitions/structs.lua | 1 +
docs/lua/functions-5.md | 21 +++++++++++++++++++++
docs/lua/functions.md | 1 +
docs/lua/structs.md | 1 +
include/types.h | 2 ++
src/engine/surface_load.c | 22 ++++++++++++++++++++++
src/engine/surface_load.h | 1 +
src/game/spawn_object.c | 6 ++++++
src/pc/lua/smlua_cobject_autogen.c | 3 ++-
src/pc/lua/smlua_functions_autogen.c | 20 ++++++++++++++++++++
12 files changed, 86 insertions(+), 2 deletions(-)
diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py
index b333088f..6a53e222 100644
--- a/autogen/convert_structs.py
+++ b/autogen/convert_structs.py
@@ -84,6 +84,7 @@ override_field_invisible = {
"MarioState": [ "visibleToEnemies" ],
"NetworkPlayer": [ "gag", "moderator"],
"GraphNode": [ "_guard1", "_guard2" ],
+ "Object": [ "firstSurface" ],
}
override_field_deprecated = {
@@ -98,7 +99,7 @@ override_field_immutable = {
"Character": [ "*" ],
"NetworkPlayer": [ "*" ],
"TextureInfo": [ "*" ],
- "Object": ["oSyncID", "coopFlags", "oChainChompSegments", "oWigglerSegments", "oHauntedChairUnk100", "oTTCTreadmillBigSurface", "oTTCTreadmillSmallSurface", "bhvStackIndex", "respawnInfoType" ],
+ "Object": ["oSyncID", "coopFlags", "oChainChompSegments", "oWigglerSegments", "oHauntedChairUnk100", "oTTCTreadmillBigSurface", "oTTCTreadmillSmallSurface", "bhvStackIndex", "respawnInfoType", "numSurfaces" ],
"GlobalObjectAnimations": [ "*"],
"SpawnParticlesInfo": [ "model" ],
"MarioBodyState": [ "updateTorsoTime" ],
diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua
index b6ae3887..c76fa629 100644
--- a/autogen/lua_definitions/functions.lua
+++ b/autogen/lua_definitions/functions.lua
@@ -8908,6 +8908,13 @@ function load_object_collision_model()
-- ...
end
+--- @param o Object
+--- @param index integer
+--- @return Surface
+function obj_get_surface_from_index(o, index)
+ -- ...
+end
+
--- @class Pointer_integer
--- @class Pointer_BehaviorScript
--- @class Pointer_number
diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua
index f39f25ba..39299403 100644
--- a/autogen/lua_definitions/structs.lua
+++ b/autogen/lua_definitions/structs.lua
@@ -1145,6 +1145,7 @@
--- @field public hurtboxHeight number
--- @field public hurtboxRadius number
--- @field public numCollidedObjs integer
+--- @field public numSurfaces integer
--- @field public o1UpForceSpawn integer
--- @field public o1UpHiddenUnkF4 integer
--- @field public oAction integer
diff --git a/docs/lua/functions-5.md b/docs/lua/functions-5.md
index 41330aef..33eecbd0 100644
--- a/docs/lua/functions-5.md
+++ b/docs/lua/functions-5.md
@@ -4734,6 +4734,27 @@
+## [obj_get_surface_from_index](#obj_get_surface_from_index)
+
+### Lua Example
+`local SurfaceValue = obj_get_surface_from_index(o, index)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| o | [Object](structs.md#Object) |
+| index | `integer` |
+
+### Returns
+[Surface](structs.md#Surface)
+
+### C Prototype
+`struct Surface *obj_get_surface_from_index(struct Object *o, u32 index);`
+
+[:arrow_up_small:](#)
+
+
+
---
[< prev](functions-4.md) | [1](functions.md) | [2](functions-2.md) | [3](functions-3.md) | [4](functions-4.md) | 5]
diff --git a/docs/lua/functions.md b/docs/lua/functions.md
index 9b1eb885..80abecba 100644
--- a/docs/lua/functions.md
+++ b/docs/lua/functions.md
@@ -1846,6 +1846,7 @@
- [get_area_terrain_size](functions-5.md#get_area_terrain_size)
- [load_area_terrain](functions-5.md#load_area_terrain)
- [load_object_collision_model](functions-5.md#load_object_collision_model)
+ - [obj_get_surface_from_index](functions-5.md#obj_get_surface_from_index)
diff --git a/docs/lua/structs.md b/docs/lua/structs.md
index bededb1e..39c29bd7 100644
--- a/docs/lua/structs.md
+++ b/docs/lua/structs.md
@@ -1559,6 +1559,7 @@
| hurtboxHeight | `number` | |
| hurtboxRadius | `number` | |
| numCollidedObjs | `integer` | |
+| numSurfaces | `integer` | read-only |
| parentObj | [Object](structs.md#Object) | |
| platform | [Object](structs.md#Object) | |
| prevObj | [Object](structs.md#Object) | |
diff --git a/include/types.h b/include/types.h
index 9c7efcc2..a39ec00b 100644
--- a/include/types.h
+++ b/include/types.h
@@ -251,6 +251,8 @@ struct Object
/*?????*/ u8 setHome;
/*?????*/ u8 allowRemoteInteractions;
/*?????*/ u8 ctx;
+ /*?????*/ u32 firstSurface;
+ /*?????*/ u32 numSurfaces;
};
struct ObjectHitbox
diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c
index 3015b7b7..66b2067d 100644
--- a/src/engine/surface_load.c
+++ b/src/engine/surface_load.c
@@ -595,6 +595,12 @@ void clear_dynamic_surfaces(void) {
gSurfaceNodesAllocated = gNumStaticSurfaceNodes;
clear_spatial_partition(&gDynamicSurfacePartition[0][0]);
+
+ for (u16 i = 0; i < OBJECT_POOL_CAPACITY; i++) {
+ struct Object *obj = &gObjectPool[i];
+ obj->firstSurface = 0;
+ obj->numSurfaces = 0;
+ }
}
}
@@ -674,6 +680,15 @@ void load_object_surfaces(s16** data, s16* vertexData) {
struct Surface* surface = read_surface_data(vertexData, data);
if (surface != NULL) {
+
+ // Set index of first surface
+ if (gCurrentObject->firstSurface == 0) {
+ gCurrentObject->firstSurface = gSurfacesAllocated - 1;
+ }
+
+ // Increase surface count
+ gCurrentObject->numSurfaces++;
+
surface->object = gCurrentObject;
surface->type = surfaceType;
@@ -763,3 +778,10 @@ void load_object_collision_model(void) {
gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
}
}
+
+struct Surface *obj_get_surface_from_index(struct Object *o, u32 index) {
+ if (!o || o->firstSurface == 0) { return NULL; }
+ if (index >= o->numSurfaces) { return NULL; }
+ struct Surface *surf = sSurfacePool->buffer[o->firstSurface + index];
+ return surf;
+}
diff --git a/src/engine/surface_load.h b/src/engine/surface_load.h
index 30558132..e948c2e9 100644
--- a/src/engine/surface_load.h
+++ b/src/engine/surface_load.h
@@ -34,5 +34,6 @@ u32 get_area_terrain_size(s16 *data);
void load_area_terrain(s16 index, s16 *data, s8 *surfaceRooms, s16 *macroObjects);
void clear_dynamic_surfaces(void);
void load_object_collision_model(void);
+struct Surface *obj_get_surface_from_index(struct Object *o, u32 index);
#endif // SURFACE_LOAD_H
diff --git a/src/game/spawn_object.c b/src/game/spawn_object.c
index 497cfab2..23c1fb5f 100644
--- a/src/game/spawn_object.c
+++ b/src/game/spawn_object.c
@@ -233,6 +233,9 @@ void unload_object(struct Object *obj) {
smlua_call_event_hooks_object_param(HOOK_ON_SYNC_OBJECT_UNLOAD, obj);
}
+ obj->firstSurface = 0;
+ obj->numSurfaces = 0;
+
smlua_call_event_hooks_object_param(HOOK_ON_OBJECT_UNLOAD, obj);
deallocate_object(&gFreeObjectList, &obj->header);
@@ -338,6 +341,9 @@ struct Object *allocate_object(struct ObjectNode *objList) {
obj->usingObj = NULL;
+ obj->firstSurface = 0;
+ obj->numSurfaces = 0;
+
return obj;
}
diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c
index 3b9a7d61..ad533bd1 100644
--- a/src/pc/lua/smlua_cobject_autogen.c
+++ b/src/pc/lua/smlua_cobject_autogen.c
@@ -1269,7 +1269,7 @@ static struct LuaObjectField sNetworkPlayerFields[LUA_NETWORK_PLAYER_FIELD_COUNT
{ "type", LVT_U8, offsetof(struct NetworkPlayer, type), true, LOT_NONE },
};
-#define LUA_OBJECT_FIELD_COUNT 758
+#define LUA_OBJECT_FIELD_COUNT 759
static struct LuaObjectField sObjectFields[LUA_OBJECT_FIELD_COUNT] = {
{ "activeFlags", LVT_S16, offsetof(struct Object, activeFlags), false, LOT_NONE },
{ "allowRemoteInteractions", LVT_U8, offsetof(struct Object, allowRemoteInteractions), false, LOT_NONE },
@@ -1297,6 +1297,7 @@ static struct LuaObjectField sObjectFields[LUA_OBJECT_FIELD_COUNT] = {
{ "hurtboxHeight", LVT_F32, offsetof(struct Object, hurtboxHeight), false, LOT_NONE },
{ "hurtboxRadius", LVT_F32, offsetof(struct Object, hurtboxRadius), false, LOT_NONE },
{ "numCollidedObjs", LVT_S16, offsetof(struct Object, numCollidedObjs), false, LOT_NONE },
+ { "numSurfaces", LVT_U32, offsetof(struct Object, numSurfaces), true, LOT_NONE },
{ "o1UpForceSpawn", LVT_S32, offsetof(struct Object, o1UpForceSpawn), false, LOT_NONE },
{ "o1UpHiddenUnkF4", LVT_S32, offsetof(struct Object, o1UpHiddenUnkF4), false, LOT_NONE },
{ "oAction", LVT_S32, offsetof(struct Object, oAction), false, LOT_NONE },
diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c
index 200b8672..961f695c 100644
--- a/src/pc/lua/smlua_functions_autogen.c
+++ b/src/pc/lua/smlua_functions_autogen.c
@@ -32470,6 +32470,25 @@ int smlua_func_load_object_collision_model(UNUSED lua_State* L) {
return 1;
}
+int smlua_func_obj_get_surface_from_index(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_surface_from_index", 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_surface_from_index"); return 0; }
+ u32 index = smlua_to_integer(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "obj_get_surface_from_index"); return 0; }
+
+ smlua_push_object(L, LOT_SURFACE, obj_get_surface_from_index(o, index));
+
+ return 1;
+}
+
void smlua_bind_functions_autogen(void) {
@@ -34235,5 +34254,6 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "get_area_terrain_size", smlua_func_get_area_terrain_size);
smlua_bind_function(L, "load_area_terrain", smlua_func_load_area_terrain);
smlua_bind_function(L, "load_object_collision_model", smlua_func_load_object_collision_model);
+ smlua_bind_function(L, "obj_get_surface_from_index", smlua_func_obj_get_surface_from_index);
}