Static Object Collision / Check for freed CObject (#924)

* Static Object Collision

* no soc surface pool; bnot

* Isaac review

---------

Co-authored-by: PeachyPeachSM64 <72323920+PeachyPeachSM64@users.noreply.github.com>
This commit is contained in:
Cooliokid956 2025-10-21 12:04:05 -05:00 committed by GitHub
parent 98891b7334
commit 9a934f8443
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 388 additions and 61 deletions

View file

@ -142,6 +142,7 @@ override_field_immutable = {
"DialogEntry": [ "unused", "linesPerBox", "leftOffset", "width", "str", "text", "replaced"],
"ModFsFile": [ "*" ],
"ModFs": [ "*" ],
"StaticObjectCollision": [ "*" ],
}
override_field_version_excludes = {

View file

@ -10956,6 +10956,9 @@ SURFACE_FLAG_DYNAMIC = (1 << 0)
--- @type integer
SURFACE_FLAG_NO_CAM_COLLISION = (1 << 1)
--- @type integer
SURFACE_FLAG_INTANGIBLE = (1 << 2)
--- @type integer
SURFACE_FLAG_X_PROJECTION = (1 << 3)

View file

@ -12295,6 +12295,27 @@ function load_object_collision_model()
-- ...
end
--- @return StaticObjectCollision
--- Loads the object's collision data into static collision. You may run this only once to capture the object's collision at that frame.
function load_static_object_collision()
-- ...
end
--- @param col StaticObjectCollision
--- @param tangible boolean
--- Toggles a collection of static object surfaces
function toggle_static_object_collision(col, tangible)
-- ...
end
--- @param col StaticObjectCollision
--- @param index integer
--- @return Surface
--- Gets a surface corresponding to `index` from the static object collision
function get_static_object_surface(col, index)
-- ...
end
--- @param o Object
--- @param index integer
--- @return Surface

View file

@ -2337,6 +2337,10 @@
--- @field public dialog5 integer
--- @field public dialog6 integer
--- @class StaticObjectCollision
--- @field public index integer
--- @field public length integer
--- @class Surface
--- @field public type integer
--- @field public flags integer

View file

@ -4620,6 +4620,7 @@
- SURFACE_CLASS_NOT_SLIPPERY
- SURFACE_FLAG_DYNAMIC
- SURFACE_FLAG_NO_CAM_COLLISION
- SURFACE_FLAG_INTANGIBLE
- SURFACE_FLAG_X_PROJECTION
- HAZARD_TYPE_LAVA_FLOOR
- HAZARD_TYPE_LAVA_WALL

View file

@ -32,6 +32,75 @@ Loads the object's collision data into dynamic collision. You must run this ever
<br />
## [load_static_object_collision](#load_static_object_collision)
### Description
Loads the object's collision data into static collision. You may run this only once to capture the object's collision at that frame.
### Lua Example
`local StaticObjectCollisionValue = load_static_object_collision()`
### Parameters
- None
### Returns
[StaticObjectCollision](structs.md#StaticObjectCollision)
### C Prototype
`struct StaticObjectCollision *load_static_object_collision();`
[:arrow_up_small:](#)
<br />
## [toggle_static_object_collision](#toggle_static_object_collision)
### Description
Toggles a collection of static object surfaces
### Lua Example
`toggle_static_object_collision(col, tangible)`
### Parameters
| Field | Type |
| ----- | ---- |
| col | [StaticObjectCollision](structs.md#StaticObjectCollision) |
| tangible | `boolean` |
### Returns
- None
### C Prototype
`void toggle_static_object_collision(struct StaticObjectCollision *col, bool tangible);`
[:arrow_up_small:](#)
<br />
## [get_static_object_surface](#get_static_object_surface)
### Description
Gets a surface corresponding to `index` from the static object collision
### Lua Example
`local SurfaceValue = get_static_object_surface(col, index)`
### Parameters
| Field | Type |
| ----- | ---- |
| col | [StaticObjectCollision](structs.md#StaticObjectCollision) |
| index | `integer` |
### Returns
[Surface](structs.md#Surface)
### C Prototype
`struct Surface *get_static_object_surface(struct StaticObjectCollision *col, u32 index);`
[:arrow_up_small:](#)
<br />
## [obj_get_surface_from_index](#obj_get_surface_from_index)
### Description

View file

@ -2189,6 +2189,9 @@
- surface_load.h
- [load_object_collision_model](functions-7.md#load_object_collision_model)
- [load_static_object_collision](functions-7.md#load_static_object_collision)
- [toggle_static_object_collision](functions-7.md#toggle_static_object_collision)
- [get_static_object_surface](functions-7.md#get_static_object_surface)
- [obj_get_surface_from_index](functions-7.md#obj_get_surface_from_index)
- [surface_has_force](functions-7.md#surface_has_force)

View file

@ -105,6 +105,7 @@
- [SpawnParticlesInfo](#SpawnParticlesInfo)
- [StarPositions](#StarPositions)
- [StarsNeededForDialog](#StarsNeededForDialog)
- [StaticObjectCollision](#StaticObjectCollision)
- [Surface](#Surface)
- [TextureInfo](#TextureInfo)
- [TransitionInfo](#TransitionInfo)
@ -3210,6 +3211,17 @@
<br />
## [StaticObjectCollision](#StaticObjectCollision)
| Field | Type | Access |
| ----- | ---- | ------ |
| index | `integer` | read-only |
| length | `integer` | read-only |
[:arrow_up_small:](#)
<br />
## [Surface](#Surface)
| Field | Type | Access |

View file

@ -163,6 +163,7 @@
#define SURFACE_FLAG_DYNAMIC (1 << 0)
#define SURFACE_FLAG_NO_CAM_COLLISION (1 << 1)
#define SURFACE_FLAG_INTANGIBLE (1 << 2)
#define SURFACE_FLAG_X_PROJECTION (1 << 3)
#define HAZARD_TYPE_LAVA_FLOOR 1

View file

@ -137,9 +137,8 @@ static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode,
surfaceNode = surfaceNode->next;
// Exclude a large number of walls immediately to optimize.
if (y < surf->lowerY || y > surf->upperY) {
continue;
}
if (y < surf->lowerY || y > surf->upperY) { continue; }
if (surf->flags & SURFACE_FLAG_INTANGIBLE) { continue; }
if (gLevelValues.fixCollisionBugs && gLevelValues.fixCollisionBugsRoundedCorners && !gFindWallDirectionAirborne) {
// Check AABB to exclude walls before doing expensive triangle check
@ -399,6 +398,8 @@ static struct Surface *find_ceil_from_list(struct SurfaceNode *surfaceNode, s32
surf = surfaceNode->surface;
surfaceNode = surfaceNode->next;
if (surf->flags & SURFACE_FLAG_INTANGIBLE) { continue; }
x1 = surf->vertex1[0];
z1 = surf->vertex1[2];
z2 = surf->vertex2[2];
@ -622,7 +623,8 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
if (surf == NULL) { break; }
surfaceNode = surfaceNode->next;
interpolate = gInterpolatingSurfaces;
if (surf->flags & SURFACE_FLAG_INTANGIBLE) { continue; }
if (gCheckingSurfaceCollisionsForObject != NULL) {
if (surf->object != gCheckingSurfaceCollisionsForObject) {
continue;

View file

@ -38,6 +38,12 @@ struct FloorGeometry
f32 originOffset;
};
struct StaticObjectCollision
{
u32 index;
u16 length;
};
extern Vec3f gFindWallDirection;
extern u8 gFindWallDirectionActive;
extern u8 gFindWallDirectionAirborne;

View file

@ -28,12 +28,48 @@
SpatialPartitionCell gStaticSurfacePartition[NUM_CELLS][NUM_CELLS];
SpatialPartitionCell gDynamicSurfacePartition[NUM_CELLS][NUM_CELLS];
/**
* The total number of surface nodes allocated (a node is allocated for each
* spatial partition cell that a surface intersects).
*/
s32 gSurfaceNodesAllocated;
/**
* The total number of surfaces allocated.
*/
s32 gSurfacesAllocated;
/**
* The number of nodes that have been created for static surfaces.
*/
s32 gNumStaticSurfaceNodes;
/**
* The number of static surfaces in the pool.
*/
s32 gNumStaticSurfaces;
/**
* The number of nodes that have been created for static object collision surfaces.
*/
s32 gNumSOCSurfaceNodes;
/**
* The number of static object collision surfaces in the pool.
*/
s32 gNumSOCSurfaces;
/**
* Pools of data to contain either surface nodes or surfaces.
*/
static struct GrowingArray *sSurfaceNodePool = NULL;
static struct GrowingArray *sSurfacePool = NULL;
/**
* Pool of data for static object collisions.
*/
static struct GrowingArray *sSOCPool = NULL;
/**
* Allocate the part of the surface node pool to contain a surface node.
*/
@ -51,6 +87,10 @@ static struct Surface *alloc_surface(void) {
return growing_array_alloc(sSurfacePool, sizeof(struct Surface));
}
static struct StaticObjectCollision *alloc_static_object_collision(void) {
return growing_array_alloc(sSOCPool, sizeof(struct StaticObjectCollision));
}
/**
* Iterates through the entire partition, clearing the surfaces.
*/
@ -71,6 +111,7 @@ static void clear_spatial_partition(SpatialPartitionCell *cells) {
*/
static void clear_static_surfaces(void) {
clear_spatial_partition(&gStaticSurfacePartition[0][0]);
sSOCPool = growing_array_init(sSOCPool, 0x100, malloc, smlua_free_soc);
}
/**
@ -479,6 +520,8 @@ void alloc_surface_pools(void) {
gSurfacesAllocated = 0;
gNumStaticSurfaceNodes = 0;
gNumStaticSurfaces = 0;
gNumSOCSurfaceNodes = 0;
gNumSOCSurfaces = 0;
gCCMEnteredSlide = 0;
reset_red_coins_collected();
@ -586,6 +629,8 @@ void load_area_terrain(s16 index, s16 *data, s8 *surfaceRooms, s16 *macroObjects
gNumStaticSurfaceNodes = gSurfaceNodesAllocated;
gNumStaticSurfaces = gSurfacesAllocated;
gNumSOCSurfaceNodes = 0;
gNumSOCSurfaces = 0;
}
/**
@ -593,8 +638,8 @@ void load_area_terrain(s16 index, s16 *data, s8 *surfaceRooms, s16 *macroObjects
*/
void clear_dynamic_surfaces(void) {
if (!(gTimeStopState & TIME_STOP_ACTIVE)) {
gSurfacesAllocated = gNumStaticSurfaces;
gSurfaceNodesAllocated = gNumStaticSurfaceNodes;
gSurfacesAllocated = gNumStaticSurfaces + gNumSOCSurfaces;
gSurfaceNodesAllocated = gNumStaticSurfaceNodes + gNumSOCSurfaceNodes;
clear_spatial_partition(&gDynamicSurfacePartition[0][0]);
@ -650,7 +695,7 @@ void transform_object_vertices(s16 **data, s16 *vertexData) {
/**
* Load in the surfaces for the gCurrentObject. This includes setting the flags, exertion, and room.
*/
void load_object_surfaces(s16** data, s16* vertexData) {
void load_object_surfaces(s16** data, s16* vertexData, bool isSOC) {
if (!gCurrentObject) { return; }
s32 surfaceType;
s32 i;
@ -682,15 +727,16 @@ 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;
if (!isSOC) {
// Set index of first surface
if (gCurrentObject->firstSurface == 0) {
gCurrentObject->firstSurface = gSurfacesAllocated - 1;
}
// Increase surface count
gCurrentObject->numSurfaces++;
}
// Increase surface count
gCurrentObject->numSurfaces++;
surface->object = gCurrentObject;
surface->type = surfaceType;
@ -702,7 +748,7 @@ void load_object_surfaces(s16** data, s16* vertexData) {
surface->flags |= flags;
surface->room = (s8)room;
add_surface(surface, TRUE);
add_surface(surface, !isSOC);
}
if (hasForce) {
@ -716,9 +762,12 @@ void load_object_surfaces(s16** data, s16* vertexData) {
/**
* Transform an object's vertices, reload them, and render the object.
*/
void load_object_collision_model(void) {
static void load_object_collision_model_internal(bool isSOC) {
static bool sIsLoadingCollision = false;
if (!gCurrentObject) { return; }
if (gCurrentObject->collisionData == NULL) { return; }
if (sIsLoadingCollision) { return; }
s32 numVertices = 64;
if (gCurrentObject->collisionData[0] == COL_INIT()) {
@ -736,6 +785,9 @@ void load_object_collision_model(void) {
static s32 sVertexDataCount = 0;
static s16* sVertexData = NULL;
// start loading collision
sIsLoadingCollision = true;
// allocate vertex data
if (numVertices > sVertexDataCount || sVertexData == NULL) {
if (sVertexData) { free(sVertexData); }
@ -746,39 +798,99 @@ void load_object_collision_model(void) {
}
s16* collisionData = gCurrentObject->collisionData;
f32 tangibleDist = gCurrentObject->oCollisionDistance;
u8 anyPlayerInTangibleRange = FALSE;
for (s32 i = 0; i < MAX_PLAYERS; i++) {
f32 dist = dist_between_objects(gCurrentObject, gMarioStates[i].marioObj);
if (dist < tangibleDist) { anyPlayerInTangibleRange = TRUE; }
if (!isSOC) {
f32 tangibleDist = gCurrentObject->oCollisionDistance;
for (s32 i = 0; i < MAX_PLAYERS; i++) {
f32 dist = dist_between_objects(gCurrentObject, gMarioStates[i].marioObj);
if (dist < tangibleDist) { anyPlayerInTangibleRange = TRUE; }
}
// If the object collision is supposed to be loaded more than the
// drawing distance of 4000, extend the drawing range.
if (gCurrentObject->oCollisionDistance > 4000.0f) {
gCurrentObject->oDrawingDistance = gCurrentObject->oCollisionDistance;
}
}
// If the object collision is supposed to be loaded more than the
// drawing distance of 4000, extend the drawing range.
if (gCurrentObject->oCollisionDistance > 4000.0f) {
gCurrentObject->oDrawingDistance = gCurrentObject->oCollisionDistance;
}
// Update if no Time Stop, in range, and in the current room.
if (!(gTimeStopState & TIME_STOP_ACTIVE)
// Update if no Time Stop, in range, and in the current room. (or if static)
if (isSOC ||
(!(gTimeStopState & TIME_STOP_ACTIVE)
&& (anyPlayerInTangibleRange)
&& !(gCurrentObject->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM)) {
&& !(gCurrentObject->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM))
) {
collisionData++;
transform_object_vertices(&collisionData, sVertexData);
// TERRAIN_LOAD_CONTINUE acts as an "end" to the terrain data.
while (*collisionData != TERRAIN_LOAD_CONTINUE) {
load_object_surfaces(&collisionData, sVertexData);
load_object_surfaces(&collisionData, sVertexData, isSOC);
}
}
f32 marioDist = dist_between_objects(gCurrentObject, gMarioStates[0].marioObj);
if (marioDist < gCurrentObject->oDrawingDistance * draw_distance_scalar()) {
gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
} else {
gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
if (!isSOC) {
f32 marioDist = dist_between_objects(gCurrentObject, gMarioStates[0].marioObj);
if (marioDist < gCurrentObject->oDrawingDistance * draw_distance_scalar()) {
gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
} else {
gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
}
}
// stop loading collision
sIsLoadingCollision = false;
}
void load_object_collision_model(void) {
load_object_collision_model_internal(false);
}
struct StaticObjectCollision *load_static_object_collision() {
struct StaticObjectCollision *col;
u32 lastSurfaceIndex = gSurfacesAllocated;
u32 lastSurfaceNodeIndex = gSurfaceNodesAllocated;
u32 lastSOCSurfaceIndex = gNumStaticSurfaces + gNumSOCSurfaces;
u32 lastSOCSurfaceNodeIndex = gNumStaticSurfaceNodes + gNumSOCSurfaceNodes;
load_object_collision_model_internal(true);
// Reorder surfaces and nodes and update SOC variables
u32 addedSurfaces = gSurfacesAllocated - lastSurfaceIndex;
u32 addedSurfaceNodes = gSurfaceNodesAllocated - lastSurfaceNodeIndex;
if (addedSurfaces > 0) {
growing_array_move(sSurfacePool, lastSurfaceIndex, lastSOCSurfaceIndex, addedSurfaces);
gNumSOCSurfaces += addedSurfaces;
}
if (addedSurfaceNodes > 0) {
growing_array_move(sSurfaceNodePool, lastSurfaceNodeIndex, lastSOCSurfaceNodeIndex, addedSurfaceNodes);
gNumSOCSurfaceNodes += addedSurfaceNodes;
}
col = alloc_static_object_collision();
col->index = lastSOCSurfaceIndex;
col->length = addedSurfaces;
return col;
}
void toggle_static_object_collision(struct StaticObjectCollision *col, bool tangible) {
for (s32 i = 0; i < col->length; i++) {
struct Surface *surf = sSurfacePool->buffer[col->index + i];
if (tangible) {
surf->flags &= ~SURFACE_FLAG_INTANGIBLE;
} else {
surf->flags |= SURFACE_FLAG_INTANGIBLE;
}
}
}
struct Surface *get_static_object_surface(struct StaticObjectCollision *col, u32 index) {
if (!col) { return NULL; }
if (index >= col->length) { return NULL; }
struct Surface *surf = sSurfacePool->buffer[col->index + index];
return surf;
}
struct Surface *obj_get_surface_from_index(struct Object *o, u32 index) {

View file

@ -27,6 +27,13 @@ typedef struct SurfaceNode SpatialPartitionCell[3];
extern SpatialPartitionCell gStaticSurfacePartition[NUM_CELLS][NUM_CELLS];
extern SpatialPartitionCell gDynamicSurfacePartition[NUM_CELLS][NUM_CELLS];
extern s32 gSurfaceNodesAllocated;
extern s32 gSurfacesAllocated;
extern s32 gNumStaticSurfaceNodes;
extern s32 gNumStaticSurfaces;
extern s32 gNumSOCSurfaceNodes;
extern s32 gNumSOCSurfaces;
void alloc_surface_pools(void);
u32 get_area_terrain_size(s16 *data);
@ -38,6 +45,15 @@ Loads the object's collision data into dynamic collision.
You must run this every frame in your object's behavior loop for it to have collision
|descriptionEnd| */
void load_object_collision_model(void);
/* |description|
Loads the object's collision data into static collision.
You may run this only once to capture the object's collision at that frame.
|descriptionEnd| */
struct StaticObjectCollision *load_static_object_collision();
/* |description|Toggles a collection of static object surfaces|descriptionEnd| */
void toggle_static_object_collision(struct StaticObjectCollision *col, bool tangible);
/* |description|Gets a surface corresponding to `index` from the static object collision|descriptionEnd| */
struct Surface *get_static_object_surface(struct StaticObjectCollision *col, u32 index);
/* |description|Gets a surface corresponding to `index` from the surface pool buffer|descriptionEnd| */
struct Surface *obj_get_surface_from_index(struct Object *o, u32 index);
/* |description|Checks if a surface has force|descriptionEnd| */

View file

@ -220,6 +220,32 @@ void *growing_array_alloc(struct GrowingArray *array, u32 size) {
return NULL;
}
void growing_array_move(struct GrowingArray *array, u32 from, u32 to, u32 count) {
if (array && array->buffer && count > 0 &&
(to < from || to > from + count) &&
(from + count) <= array->count && to <= array->count) {
void **temp = malloc(sizeof(void *) * count);
if (!temp) { return; }
// Copy elements to move to temporary buffer
memcpy(temp, array->buffer + from, sizeof(void *) * count);
// Remove copied elements from the array
memmove(array->buffer + from, array->buffer + (from + count), sizeof(void *) * (array->count - (from + count)));
// Make place for the copied elements
// If moving left to right, account for the removed elements
if (to > from) { to -= count; }
memmove(array->buffer + (to + count), array->buffer + to, sizeof(void *) * (array->count - (to + count)));
// Insert copied elements
memcpy(array->buffer + to, temp, sizeof(void *) * count);
free(temp);
}
}
void growing_array_free(struct GrowingArray **array) {
if (*array) {
for (u32 i = 0; i != (*array)->capacity; ++i) {

View file

@ -77,6 +77,7 @@ void growing_pool_free_pool(struct GrowingPool *pool);
struct GrowingArray *growing_array_init(struct GrowingArray *array, u32 capacity, GrowingArrayAllocFunc alloc, GrowingArrayFreeFunc free);
void *growing_array_alloc(struct GrowingArray *array, u32 size);
void growing_array_move(struct GrowingArray *array, u32 from, u32 to, u32 count);
void growing_array_free(struct GrowingArray **array);
void growing_array_debug_print(struct GrowingArray *array, const char *name, s32 x, s32 y);

View file

@ -122,27 +122,6 @@ const BehaviorScript *gCurBhvCommand;
*/
s16 gPrevFrameObjectCount;
/**
* The total number of surface nodes allocated (a node is allocated for each
* spatial partition cell that a surface intersects).
*/
s32 gSurfaceNodesAllocated;
/**
* The total number of surfaces allocated.
*/
s32 gSurfacesAllocated;
/**
* The number of nodes that have been created for surfaces.
*/
s32 gNumStaticSurfaceNodes;
/**
* The number of surfaces in the pool.
*/
s32 gNumStaticSurfaces;
struct Object* gCheckingSurfaceCollisionsForObject = NULL;
s16 gCheckingSurfaceCollisionsForCamera;
s16 gFindFloorIncludeSurfaceIntangible;

View file

@ -91,11 +91,6 @@ extern struct Object *gCurrentObject;
extern const BehaviorScript *gCurBhvCommand;
extern s16 gPrevFrameObjectCount;
extern s32 gSurfaceNodesAllocated;
extern s32 gSurfacesAllocated;
extern s32 gNumStaticSurfaceNodes;
extern s32 gNumStaticSurfaces;
extern struct Object* gCheckingSurfaceCollisionsForObject;
extern s16 gCheckingSurfaceCollisionsForCamera;
extern s16 gFindFloorIncludeSurfaceIntangible;

View file

@ -650,6 +650,12 @@ int smlua__eq(lua_State *L) {
return 1;
}
int smlua__bnot(lua_State *L) {
const CObject *a = lua_touserdata(L, 1);
lua_pushboolean(L, !a || a->freed);
return 1;
}
static int smlua_cpointer_get(lua_State* L) {
const CPointer *cptr = lua_touserdata(L, 1);
const char *key = lua_tostring(L, 2);
@ -690,6 +696,7 @@ void smlua_cobject_init_globals(void) {
{ "__index", smlua__get_field },
{ "__newindex", smlua__set_field },
{ "__eq", smlua__eq },
{ "__bnot", smlua__bnot },
{ "__metatable", NULL },
{ NULL, NULL }
};
@ -700,6 +707,7 @@ void smlua_cobject_init_globals(void) {
{ "__index", smlua_cpointer_get },
{ "__newindex", smlua_cpointer_set },
{ "__eq", smlua__eq },
{ "__bnot", smlua__bnot },
{ "__metatable", NULL },
{ NULL, NULL }
};

View file

@ -2742,6 +2742,12 @@ static struct LuaObjectField sStarsNeededForDialogFields[LUA_STARS_NEEDED_FOR_DI
{ "dialog6", LVT_U16, offsetof(struct StarsNeededForDialog, dialog6), false, LOT_NONE, 1, sizeof(u16) },
};
#define LUA_STATIC_OBJECT_COLLISION_FIELD_COUNT 2
static struct LuaObjectField sStaticObjectCollisionFields[LUA_STATIC_OBJECT_COLLISION_FIELD_COUNT] = {
{ "index", LVT_U32, offsetof(struct StaticObjectCollision, index), true, LOT_NONE, 1, sizeof(u32) },
{ "length", LVT_U16, offsetof(struct StaticObjectCollision, length), true, LOT_NONE, 1, sizeof(u16) },
};
#define LUA_SURFACE_FIELD_COUNT 16
static struct LuaObjectField sSurfaceFields[LUA_SURFACE_FIELD_COUNT] = {
{ "flags", LVT_S8, offsetof(struct Surface, flags), false, LOT_NONE, 1, sizeof(s8) },
@ -2980,6 +2986,7 @@ struct LuaObjectTable sLuaObjectAutogenTable[LOT_AUTOGEN_MAX - LOT_AUTOGEN_MIN]
{ LOT_SPAWNPARTICLESINFO, sSpawnParticlesInfoFields, LUA_SPAWN_PARTICLES_INFO_FIELD_COUNT },
{ LOT_STARPOSITIONS, sStarPositionsFields, LUA_STAR_POSITIONS_FIELD_COUNT },
{ LOT_STARSNEEDEDFORDIALOG, sStarsNeededForDialogFields, LUA_STARS_NEEDED_FOR_DIALOG_FIELD_COUNT },
{ LOT_STATICOBJECTCOLLISION, sStaticObjectCollisionFields, LUA_STATIC_OBJECT_COLLISION_FIELD_COUNT },
{ LOT_SURFACE, sSurfaceFields, LUA_SURFACE_FIELD_COUNT },
{ LOT_TEXTUREINFO, sTextureInfoFields, LUA_TEXTURE_INFO_FIELD_COUNT },
{ LOT_TRANSITIONINFO, sTransitionInfoFields, LUA_TRANSITION_INFO_FIELD_COUNT },
@ -3110,6 +3117,7 @@ const char *sLuaLotNames[] = {
[LOT_SPAWNPARTICLESINFO] = "SpawnParticlesInfo",
[LOT_STARPOSITIONS] = "StarPositions",
[LOT_STARSNEEDEDFORDIALOG] = "StarsNeededForDialog",
[LOT_STATICOBJECTCOLLISION] = "StaticObjectCollision",
[LOT_SURFACE] = "Surface",
[LOT_TEXTUREINFO] = "TextureInfo",
[LOT_TRANSITIONINFO] = "TransitionInfo",

View file

@ -123,6 +123,7 @@ enum LuaObjectAutogenType {
LOT_SPAWNPARTICLESINFO,
LOT_STARPOSITIONS,
LOT_STARSNEEDEDFORDIALOG,
LOT_STATICOBJECTCOLLISION,
LOT_SURFACE,
LOT_TEXTUREINFO,
LOT_TRANSITIONINFO,

View file

@ -4543,6 +4543,7 @@ char gSmluaConstants[] = ""
"SURFACE_CLASS_NOT_SLIPPERY=0x0015\n"
"SURFACE_FLAG_DYNAMIC=(1 << 0)\n"
"SURFACE_FLAG_NO_CAM_COLLISION=(1 << 1)\n"
"SURFACE_FLAG_INTANGIBLE=(1 << 2)\n"
"SURFACE_FLAG_X_PROJECTION=(1 << 3)\n"
"HAZARD_TYPE_LAVA_FLOOR=1\n"
"HAZARD_TYPE_LAVA_WALL=2\n"

View file

@ -36485,6 +36485,59 @@ int smlua_func_load_object_collision_model(UNUSED lua_State* L) {
return 1;
}
int smlua_func_load_static_object_collision(UNUSED lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 0) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "load_static_object_collision", 0, top);
return 0;
}
smlua_push_object(L, LOT_STATICOBJECTCOLLISION, load_static_object_collision(), NULL);
return 1;
}
int smlua_func_toggle_static_object_collision(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", "toggle_static_object_collision", 2, top);
return 0;
}
struct StaticObjectCollision* col = (struct StaticObjectCollision*)smlua_to_cobject(L, 1, LOT_STATICOBJECTCOLLISION);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "toggle_static_object_collision"); return 0; }
bool tangible = smlua_to_boolean(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "toggle_static_object_collision"); return 0; }
toggle_static_object_collision(col, tangible);
return 1;
}
int smlua_func_get_static_object_surface(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", "get_static_object_surface", 2, top);
return 0;
}
struct StaticObjectCollision* col = (struct StaticObjectCollision*)smlua_to_cobject(L, 1, LOT_STATICOBJECTCOLLISION);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "get_static_object_surface"); return 0; }
u32 index = smlua_to_integer(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "get_static_object_surface"); return 0; }
smlua_push_object(L, LOT_SURFACE, get_static_object_surface(col, index), NULL);
return 1;
}
int smlua_func_obj_get_surface_from_index(lua_State* L) {
if (L == NULL) { return 0; }
@ -38657,6 +38710,9 @@ void smlua_bind_functions_autogen(void) {
// surface_load.h
smlua_bind_function(L, "load_object_collision_model", smlua_func_load_object_collision_model);
smlua_bind_function(L, "load_static_object_collision", smlua_func_load_static_object_collision);
smlua_bind_function(L, "toggle_static_object_collision", smlua_func_toggle_static_object_collision);
smlua_bind_function(L, "get_static_object_surface", smlua_func_get_static_object_surface);
smlua_bind_function(L, "obj_get_surface_from_index", smlua_func_obj_get_surface_from_index);
smlua_bind_function(L, "surface_has_force", smlua_func_surface_has_force);

View file

@ -69,5 +69,6 @@ void smlua_free(void *ptr, u16 lot);
static inline void smlua_free_##name(void *ptr) { smlua_free(ptr, lot); }
smlua_free_lot(surface, LOT_SURFACE);
smlua_free_lot(soc, LOT_STATICOBJECTCOLLISION);
#endif