mirror of
				https://github.com/coop-deluxe/sm64coopdx.git
				synced 2025-10-30 08:01:01 +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
	
	 Cooliokid956
						Cooliokid956