diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 8931448c..a106a5da 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -8100,6 +8100,11 @@ function collision_find_surface_on_ray(startX, startY, startZ, dirX, dirY, dirZ) -- ... end +--- @return WallCollisionData +function collision_get_temp_wall_collision_data() + -- ... +end + --- @return Surface function get_water_surface_pseudo_floor() -- ... diff --git a/docs/lua/functions-4.md b/docs/lua/functions-4.md index d4b35c93..34fdd6d4 100644 --- a/docs/lua/functions-4.md +++ b/docs/lua/functions-4.md @@ -7345,6 +7345,24 @@
+## [collision_get_temp_wall_collision_data](#collision_get_temp_wall_collision_data) + +### Lua Example +`local WallCollisionDataValue = collision_get_temp_wall_collision_data()` + +### Parameters +- None + +### Returns +[WallCollisionData](structs.md#WallCollisionData) + +### C Prototype +`struct WallCollisionData* collision_get_temp_wall_collision_data(void);` + +[:arrow_up_small:](#) + +
+ ## [get_water_surface_pseudo_floor](#get_water_surface_pseudo_floor) ### Lua Example diff --git a/docs/lua/functions.md b/docs/lua/functions.md index 64d72d4d..83cf2879 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -1503,6 +1503,7 @@ - smlua_collision_utils.h - [collision_find_surface_on_ray](functions-4.md#collision_find_surface_on_ray) + - [collision_get_temp_wall_collision_data](functions-4.md#collision_get_temp_wall_collision_data) - [get_water_surface_pseudo_floor](functions-4.md#get_water_surface_pseudo_floor) - [smlua_collision_util_get](functions-4.md#smlua_collision_util_get) diff --git a/src/engine/level_script.c b/src/engine/level_script.c index 4f351d18..175725a3 100644 --- a/src/engine/level_script.c +++ b/src/engine/level_script.c @@ -574,27 +574,40 @@ static void level_cmd_create_warp_node(void) { } static void level_cmd_create_instant_warp(void) { - s32 i; - struct InstantWarp *warp; + struct InstantWarp *warp = NULL; if (sCurrAreaIndex != -1) { if (gAreas[sCurrAreaIndex].instantWarps == NULL) { gAreas[sCurrAreaIndex].instantWarps = dynamic_pool_alloc(gLevelPool, 4 * sizeof(struct InstantWarp)); - for (i = INSTANT_WARP_INDEX_START; i < INSTANT_WARP_INDEX_STOP; i++) { + for (s32 i = INSTANT_WARP_INDEX_START; i < INSTANT_WARP_INDEX_STOP; i++) { gAreas[sCurrAreaIndex].instantWarps[i].id = 0; } } - warp = gAreas[sCurrAreaIndex].instantWarps + CMD_GET(u8, 2); + u8 warpIndex = CMD_GET(u8, 2); + if (warpIndex >= INSTANT_WARP_INDEX_STOP) { + LOG_ERROR("Instant warp index out of bounds: %u", warpIndex); + sCurrentCmd = CMD_NEXT; + return; + } - warp[0].id = 1; - warp[0].area = CMD_GET(u8, 3); + u8 areaIndex = CMD_GET(u8, 3); + if (areaIndex >= MAX_AREAS) { + LOG_ERROR("Instant warp area index out of bounds: %u", areaIndex); + sCurrentCmd = CMD_NEXT; + return; + } - warp[0].displacement[0] = CMD_GET(s16, 4); - warp[0].displacement[1] = CMD_GET(s16, 6); - warp[0].displacement[2] = CMD_GET(s16, 8); + warp = &gAreas[sCurrAreaIndex].instantWarps[warpIndex]; + + warp->id = 1; + warp->area = areaIndex; + + warp->displacement[0] = CMD_GET(s16, 4); + warp->displacement[1] = CMD_GET(s16, 6); + warp->displacement[2] = CMD_GET(s16, 8); } sCurrentCmd = CMD_NEXT; diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c index 037e847e..385d4843 100644 --- a/src/engine/surface_load.c +++ b/src/engine/surface_load.c @@ -31,34 +31,17 @@ SpatialPartitionCell gDynamicSurfacePartition[NUM_CELLS][NUM_CELLS]; /** * Pools of data to contain either surface nodes or surfaces. */ -struct SurfaceNode *sSurfaceNodePool = NULL; -struct Surface *sSurfacePool = NULL; - -/** - * The size of the surface pool (2300). - */ -s16 sSurfacePoolSize = 0; -u8 gSurfacePoolError = 0; +struct GrowingPool* sSurfaceNodePool = NULL; +struct GrowingPool* sSurfacePool = NULL; /** * Allocate the part of the surface node pool to contain a surface node. */ -static struct SurfaceNode *alloc_surface_node(void) { - struct SurfaceNode *node = &sSurfaceNodePool[gSurfaceNodesAllocated]; - gSurfaceNodesAllocated++; - - //! A bounds check! If there's more surface nodes than 7000 allowed, - // we, um... - // Perhaps originally just debug feedback? - if (gSurfaceNodesAllocated >= SURFACE_NODE_POOL_SIZE) { - gSurfacePoolError |= NOT_ENOUGH_ROOM_FOR_NODES; - return NULL; - } else { - gSurfacePoolError &= ~NOT_ENOUGH_ROOM_FOR_NODES; - } - +static struct SurfaceNode* alloc_surface_node(void) { + struct SurfaceNode* node = (struct SurfaceNode*)growing_pool_alloc(sSurfaceNodePool, sizeof(struct SurfaceNode)); node->next = NULL; + gSurfaceNodesAllocated++; return node; } @@ -66,20 +49,8 @@ static struct SurfaceNode *alloc_surface_node(void) { * Allocate the part of the surface pool to contain a surface and * initialize the surface. */ -static struct Surface *alloc_surface(void) { - - struct Surface *surface = &sSurfacePool[gSurfacesAllocated]; - gSurfacesAllocated++; - - //! A bounds check! If there's more surfaces than the 2300 allowed, - // we, um... - // Perhaps originally just debug feedback? - if (gSurfacesAllocated >= sSurfacePoolSize) { - gSurfacePoolError |= NOT_ENOUGH_ROOM_FOR_SURFACES; - return NULL; - } else { - gSurfacePoolError &= ~NOT_ENOUGH_ROOM_FOR_SURFACES; - } +static struct Surface* alloc_surface(void) { + struct Surface* surface = (struct Surface*)growing_pool_alloc(sSurfacePool, sizeof(struct Surface)); surface->type = 0; surface->force = 0; @@ -87,6 +58,8 @@ static struct Surface *alloc_surface(void) { surface->room = 0; surface->object = NULL; + gSurfacesAllocated++; + return surface; } @@ -549,9 +522,8 @@ void alloc_surface_pools(void) { clear_static_surfaces(); clear_dynamic_surfaces(); - sSurfacePoolSize = SURFACE_POOL_SIZE; - if (!sSurfaceNodePool) { sSurfaceNodePool = calloc(1, SURFACE_NODE_POOL_SIZE * sizeof(struct SurfaceNode)); } - if (!sSurfacePool) { sSurfacePool = calloc(1, sSurfacePoolSize * sizeof(struct Surface)); } + sSurfaceNodePool = growing_pool_init(sSurfaceNodePool, sizeof(struct SurfaceNode) * 1000); + sSurfacePool = growing_pool_init(sSurfacePool, sizeof(struct Surface) * 1000); gEnvironmentRegions = NULL; gSurfaceNodesAllocated = 0; @@ -784,7 +756,26 @@ void load_object_collision_model(void) { if (!gCurrentObject) { return; } if (gCurrentObject->collisionData == NULL) { return; } - s16 vertexData[600]; + s32 numVertices = 64; + if (gCurrentObject->collisionData[0] == COL_INIT()) { + numVertices = gCurrentObject->collisionData[1]; + } + if (numVertices <= 0) { + LOG_ERROR("Object collisions had invalid vertex count"); + return; + } + + static s32 sVertexDataCount = 0; + static s16* sVertexData = NULL; + + // allocate vertex data + if (numVertices > sVertexDataCount || sVertexData == NULL) { + if (sVertexData) { free(sVertexData); } + sVertexDataCount = numVertices; + if (sVertexDataCount < 64) { sVertexDataCount = 64; } + sVertexData = malloc((3 * sVertexDataCount + 1) * sizeof(s16)); + LOG_INFO("Reallocating object vertex data: %u", sVertexDataCount); + } s16* collisionData = gCurrentObject->collisionData; f32 tangibleDist = gCurrentObject->oCollisionDistance; @@ -806,11 +797,11 @@ void load_object_collision_model(void) { && (anyPlayerInTangibleRange) && !(gCurrentObject->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM)) { collisionData++; - transform_object_vertices(&collisionData, vertexData); + 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, vertexData); + load_object_surfaces(&collisionData, sVertexData); } } diff --git a/src/engine/surface_load.h b/src/engine/surface_load.h index a9029a38..30558132 100644 --- a/src/engine/surface_load.h +++ b/src/engine/surface_load.h @@ -26,7 +26,6 @@ typedef struct SurfaceNode SpatialPartitionCell[3]; extern SpatialPartitionCell gStaticSurfacePartition[NUM_CELLS][NUM_CELLS]; extern SpatialPartitionCell gDynamicSurfacePartition[NUM_CELLS][NUM_CELLS]; -extern u8 gSurfacePoolError; void alloc_surface_pools(void); diff --git a/src/game/area.c b/src/game/area.c index ef5375d8..4f997031 100644 --- a/src/game/area.c +++ b/src/game/area.c @@ -29,7 +29,7 @@ #include "pc/djui/djui_panel_pause.h" struct SpawnInfo gPlayerSpawnInfos[MAX_PLAYERS]; -struct Area gAreaData[8]; +struct Area gAreaData[MAX_AREAS]; struct WarpTransition gWarpTransition; diff --git a/src/game/area.h b/src/game/area.h index f1a607ca..14b8003c 100644 --- a/src/game/area.h +++ b/src/game/area.h @@ -26,6 +26,8 @@ struct ObjectWarpNode #define INSTANT_WARP_INDEX_START 0x00 // Equal and greater than Surface 0x1B #define INSTANT_WARP_INDEX_STOP 0x04 // Less than Surface 0x1F +#define MAX_AREAS 8 + struct InstantWarp { /*0x00*/ u8 id; // 0 = 0x1B / 1 = 0x1C / 2 = 0x1D / 3 = 0x1E diff --git a/src/game/behaviors/monty_mole.inc.c b/src/game/behaviors/monty_mole.inc.c index c1ee19ce..f8505461 100644 --- a/src/game/behaviors/monty_mole.inc.c +++ b/src/game/behaviors/monty_mole.inc.c @@ -410,6 +410,14 @@ void bhv_monty_mole_update(void) { o->oDeathSound = SOUND_OBJ_DYING_ENEMY1; cur_obj_update_floor_and_walls(); + // if we can't find our floor, set it to the hole's floor + if (!o->oFloor && o->oMontyMoleCurrentHole) { + struct Object* hole = o->oMontyMoleCurrentHole; + struct Surface* floor = NULL; + o->oFloorHeight = find_floor(hole->oPosX, hole->oPosY, hole->oPosZ, &floor); + o->oFloor = floor; + } + o->oMontyMoleHeightRelativeToFloor = o->oPosY - o->oFloorHeight; switch (o->oAction) { diff --git a/src/game/behaviors/pyramid_wall.inc.c b/src/game/behaviors/pyramid_wall.inc.c index 10d12890..ababf2c0 100644 --- a/src/game/behaviors/pyramid_wall.inc.c +++ b/src/game/behaviors/pyramid_wall.inc.c @@ -11,6 +11,10 @@ * positions. */ void bhv_ssl_moving_pyramid_wall_init(void) { + o->areaTimerType = AREA_TIMER_TYPE_LOOP; + o->areaTimer = 0; + o->areaTimerDuration = 200; + switch (o->oBehParams2ndByte) { case PYRAMID_WALL_BP_POSITION_HIGH: break; @@ -25,17 +29,6 @@ void bhv_ssl_moving_pyramid_wall_init(void) { o->oAction = PYRAMID_WALL_ACT_MOVING_UP; break; } - - if (!sync_object_is_initialized(o->oSyncID)) { - struct SyncObject *so = sync_object_init(o, SYNC_DISTANCE_ONLY_EVENTS); - if (so) { - sync_object_init_field(o, &o->oPrevAction); - sync_object_init_field(o, &o->oAction); - sync_object_init_field(o, &o->oTimer); - sync_object_init_field(o, &o->oVelY); - sync_object_init_field(o, &o->oPosY); - } - } } /** @@ -48,16 +41,14 @@ void bhv_ssl_moving_pyramid_wall_loop(void) { o->oVelY = -5.12f; if (o->oTimer == 100) { o->oAction = PYRAMID_WALL_ACT_MOVING_UP; - if (sync_object_is_owned_locally(o->oSyncID)) { - network_send_object(o); - } } break; case PYRAMID_WALL_ACT_MOVING_UP: o->oVelY = 5.12f; - if (o->oTimer == 100) + if (o->oTimer == 100) { o->oAction = PYRAMID_WALL_ACT_MOVING_DOWN; + } break; } diff --git a/src/game/characters.c b/src/game/characters.c index 684375a1..bff32ab9 100644 --- a/src/game/characters.c +++ b/src/game/characters.c @@ -555,7 +555,7 @@ f32 get_character_anim_offset(struct MarioState* m) { switch (sAnimTypes[animID]) { case ANIM_TYPE_LOWY: if (m->minimumBoneY < c->animOffsetLowYPoint) { - return -(m->minimumBoneY - c->animOffsetLowYPoint); + return c->animOffsetLowYPoint - m->minimumBoneY; } break; case ANIM_TYPE_FEET: @@ -584,10 +584,6 @@ void update_character_anim_offset(struct MarioState* m) { if (m->curAnimOffset > 40) { m->curAnimOffset = 40; } if (m->curAnimOffset < -40) { m->curAnimOffset = -40; } - if (m->action == ACT_JUMBO_STAR_CUTSCENE) { - marioObj->header.gfx.pos[1] = m->pos[1] + m->curAnimOffset; - } else { - marioObj->header.gfx.pos[1] += m->curAnimOffset; - } + marioObj->header.gfx.pos[1] = m->pos[1] + m->curAnimOffset; marioObj->header.gfx.node.flags |= GRAPH_RENDER_PLAYER; } \ No newline at end of file diff --git a/src/game/hud.c b/src/game/hud.c index c50e7452..7b7078d4 100644 --- a/src/game/hud.c +++ b/src/game/hud.c @@ -678,14 +678,6 @@ void render_hud(void) { render_hud_timer(); } - if (gSurfacePoolError & NOT_ENOUGH_ROOM_FOR_SURFACES) { - print_text(10, 40, "SURFACE POOL FULL"); - } - - if (gSurfacePoolError & NOT_ENOUGH_ROOM_FOR_NODES) { - print_text(10, 60, "SURFACE NODE POOL FULL"); - } - #if defined(DEVELOPMENT) extern bool configLuaProfiler; if (configLuaProfiler) { diff --git a/src/game/interaction.c b/src/game/interaction.c index 2662c106..65c35b58 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -1414,7 +1414,7 @@ u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object if (!m || !o) { return FALSE; } if (!is_player_active(m)) { return FALSE; } if (gServerSettings.playerInteractions == PLAYER_INTERACTIONS_NONE) { return FALSE; } - if (m->action == ACT_JUMBO_STAR_CUTSCENE) { return FALSE; } + if (m->action & ACT_FLAG_INTANGIBLE) { return FALSE; } struct MarioState* m2 = NULL; for (s32 i = 0; i < MAX_PLAYERS; i++) { @@ -1425,7 +1425,7 @@ u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object } } if (m2 == NULL) { return FALSE; } - if (m2->action == ACT_JUMBO_STAR_CUTSCENE) { return FALSE; } + if (m2->action & ACT_FLAG_INTANGIBLE) { return FALSE; } // vanish cap players can't interact u32 vanishFlags = (MARIO_VANISH_CAP | MARIO_CAP_ON_HEAD); diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index 9a4295fa..363e9b0a 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -1222,7 +1222,7 @@ static void geo_process_object(struct Object *node) { } } if (gCurGraphNodeMarioState != NULL) { - gCurGraphNodeMarioState->minimumBoneY = 999; + gCurGraphNodeMarioState->minimumBoneY = 9999; } } diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index ace55d83..36a877e4 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -27042,6 +27042,21 @@ int smlua_func_collision_find_surface_on_ray(lua_State* L) { return 1; } +int smlua_func_collision_get_temp_wall_collision_data(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", "collision_get_temp_wall_collision_data", 0, top); + return 0; + } + + + smlua_push_object(L, LOT_WALLCOLLISIONDATA, collision_get_temp_wall_collision_data()); + + return 1; +} + int smlua_func_get_water_surface_pseudo_floor(UNUSED lua_State* L) { if (L == NULL) { return 0; } @@ -31516,6 +31531,7 @@ void smlua_bind_functions_autogen(void) { // smlua_collision_utils.h smlua_bind_function(L, "collision_find_surface_on_ray", smlua_func_collision_find_surface_on_ray); + smlua_bind_function(L, "collision_get_temp_wall_collision_data", smlua_func_collision_get_temp_wall_collision_data); smlua_bind_function(L, "get_water_surface_pseudo_floor", smlua_func_get_water_surface_pseudo_floor); smlua_bind_function(L, "smlua_collision_util_get", smlua_func_smlua_collision_util_get); diff --git a/src/pc/lua/utils/smlua_collision_utils.c b/src/pc/lua/utils/smlua_collision_utils.c index e867e1e2..7b4ca407 100644 --- a/src/pc/lua/utils/smlua_collision_utils.c +++ b/src/pc/lua/utils/smlua_collision_utils.c @@ -171,3 +171,9 @@ struct Surface* get_water_surface_pseudo_floor(void) { Collision* smlua_collision_util_get(const char* name) { return dynos_collision_get(name); } + +struct WallCollisionData* collision_get_temp_wall_collision_data(void) { + static struct WallCollisionData sTmpWcd = { 0 }; + memset(&sTmpWcd, 0, sizeof(struct WallCollisionData)); + return &sTmpWcd; +} diff --git a/src/pc/lua/utils/smlua_collision_utils.h b/src/pc/lua/utils/smlua_collision_utils.h index 8430f957..47827a30 100644 --- a/src/pc/lua/utils/smlua_collision_utils.h +++ b/src/pc/lua/utils/smlua_collision_utils.h @@ -1,6 +1,8 @@ #ifndef SMLUA_COLLISION_UTILS_H #define SMLUA_COLLISION_UTILS_H +#include "engine/surface_collision.h" + struct RayIntersectionInfo { struct Surface* surface; Vec3f hitPos; @@ -118,4 +120,6 @@ struct Surface* get_water_surface_pseudo_floor(void); Collision* smlua_collision_util_get(const char* name); +struct WallCollisionData* collision_get_temp_wall_collision_data(void); + #endif diff --git a/src/pc/network/packets/packet_player.c b/src/pc/network/packets/packet_player.c index 61722ec0..5189d9cd 100644 --- a/src/pc/network/packets/packet_player.c +++ b/src/pc/network/packets/packet_player.c @@ -416,6 +416,7 @@ void network_update_player(void) { // figure out if we should send it or not static u8 sTicksSinceSend = 0; static u32 sLastPlayerAction = 0; + static u32 sLastPlayerParticles = 0; static f32 sLastStickX = 0; static f32 sLastStickY = 0; static u32 sLastButtonDown = 0; @@ -423,18 +424,20 @@ void network_update_player(void) { f32 stickDist = sqrtf(powf(sLastStickX - m->controller->stickX, 2) + powf(sLastStickY - m->controller->stickY, 2)); bool shouldSend = (sTicksSinceSend > 2) - || (sLastPlayerAction != m->action) - || (sLastButtonDown != m->controller->buttonDown) - || (sLastButtonPressed != m->controller->buttonPressed) + || (sLastPlayerAction != m->action) + || (sLastButtonDown != m->controller->buttonDown) + || (sLastButtonPressed != m->controller->buttonPressed) + || (sLastPlayerParticles != m->particleFlags) || (stickDist > 5.0f); if (!shouldSend) { sTicksSinceSend++; return; } network_send_player(0); sTicksSinceSend = 0; - sLastPlayerAction = m->action; - sLastStickX = m->controller->stickX; - sLastStickY = m->controller->stickY; - sLastButtonDown = m->controller->buttonDown; - sLastButtonPressed = m->controller->buttonPressed; + sLastPlayerAction = m->action; + sLastStickX = m->controller->stickX; + sLastStickY = m->controller->stickY; + sLastButtonDown = m->controller->buttonDown; + sLastButtonPressed = m->controller->buttonPressed; + sLastPlayerParticles = m->particleFlags; }