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;
}