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 b333088f2..6a53e2226 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 b6ae3887d..c76fa6296 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 f39f25bae..39299403a 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 41330aeff..33eecbd0e 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 9b1eb8857..80abecba2 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 bededb1e3..39c29bd72 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 9c7efcc26..a39ec00be 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 3015b7b79..66b2067d8 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 30558132b..e948c2e99 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 497cfab26..23c1fb5f8 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 3b9a7d61e..ad533bd1d 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 200b86722..961f695cc 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);
}