mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-12-15 20:42:27 +00:00
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:
parent
98891b7334
commit
9a934f8443
23 changed files with 388 additions and 61 deletions
|
|
@ -142,6 +142,7 @@ override_field_immutable = {
|
|||
"DialogEntry": [ "unused", "linesPerBox", "leftOffset", "width", "str", "text", "replaced"],
|
||||
"ModFsFile": [ "*" ],
|
||||
"ModFs": [ "*" ],
|
||||
"StaticObjectCollision": [ "*" ],
|
||||
}
|
||||
|
||||
override_field_version_excludes = {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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 |
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,12 @@ struct FloorGeometry
|
|||
f32 originOffset;
|
||||
};
|
||||
|
||||
struct StaticObjectCollision
|
||||
{
|
||||
u32 index;
|
||||
u16 length;
|
||||
};
|
||||
|
||||
extern Vec3f gFindWallDirection;
|
||||
extern u8 gFindWallDirectionActive;
|
||||
extern u8 gFindWallDirectionAirborne;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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| */
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ enum LuaObjectAutogenType {
|
|||
LOT_SPAWNPARTICLESINFO,
|
||||
LOT_STARPOSITIONS,
|
||||
LOT_STARSNEEDEDFORDIALOG,
|
||||
LOT_STATICOBJECTCOLLISION,
|
||||
LOT_SURFACE,
|
||||
LOT_TEXTUREINFO,
|
||||
LOT_TRANSITIONINFO,
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Loading…
Add table
Reference in a new issue