Implement FakeObjects (Just poles for now)
Build libsm64 / Build libsm64 for linux (push) Successful in 33s
Build libsm64 / Build libsm64 for web (push) Successful in 30s
Build libsm64 / Build libsm64 for windows (push) Successful in 23s

This commit is contained in:
2026-05-31 16:44:11 -05:00
parent b096207a10
commit ede2099ff5
12 changed files with 418 additions and 25 deletions
+125 -9
View File
@@ -38,6 +38,8 @@
#include "load_tex_data.h"
#include "obj_pool.h"
#include "fake_interaction.h"
#include "object_fields.h"
#include "FakeObject.h"
static struct AllocOnlyPool *s_mario_geo_pool = NULL;
static struct GraphNode *s_mario_graph_node = NULL;
@@ -51,6 +53,7 @@ struct MarioInstance
};
struct ObjPool s_mario_instance_pool = {0, 0};
struct ObjPool s_fakeobj_instance_pool = {0, 0};
static void update_button(bool on, u16 button)
{
@@ -109,8 +112,7 @@ SM64_LIB_FN void sm64_register_play_sound_function(SM64PlaySoundFunctionPtr play
SM64_LIB_FN void sm64_global_init(const uint8_t *rom, uint8_t *outTexture)
{
if (s_init_global)
sm64_global_terminate();
if (s_init_global) sm64_global_terminate();
s_init_global = true;
@@ -128,9 +130,8 @@ SM64_LIB_FN void sm64_global_terminate(void)
if (s_init_one_mario)
{
for (int i = 0; i < s_mario_instance_pool.size; ++i)
if (s_mario_instance_pool.objects[i] != NULL)
sm64_mario_delete(i);
for (int i = 0; i < s_mario_instance_pool.size; ++i) if (s_mario_instance_pool.objects[i] != NULL) sm64_mario_delete(i);
for (int i = 0; i < s_fakeobj_instance_pool.size; ++i) if (s_fakeobj_instance_pool.objects[i] != NULL) sm64_fake_object_delete(i);
obj_pool_free_all(&s_mario_instance_pool);
}
@@ -257,6 +258,10 @@ SM64_LIB_FN void sm64_mario_tick(int32_t marioId, const struct SM64MarioInputs *
apply_mario_platform_displacement();
bhv_mario_update();
gMarioState->marioObj->collidedObjInteractTypes = 0;
gMarioState->marioObj->numCollidedObjs = 0;
update_mario_platform(); // TODO platform grabbed here and used next tick could be a use-after-free
gfx_adapter_bind_output_buffers(outBuffers);
@@ -623,6 +628,119 @@ SM64_LIB_FN void sm64_mario_extend_cap(int32_t marioId, uint16_t capTime)
gMarioState->capTimer += capTime;
}
SM64_LIB_FN int32_t sm64_fake_object_create(float x, float y, float z, int32_t preset)
{
struct GlobalState *state = g_state;
if (state == NULL)
{
DEBUG_PRINT("Tried to create fake object without an active Mario state.");
return -1;
}
int32_t objectIndex = obj_pool_alloc_index(&s_fakeobj_instance_pool, sizeof(struct FakeObject));
struct FakeObject *fake = (struct FakeObject *)s_fakeobj_instance_pool.objects[objectIndex];
fake_object_init(fake, x, y, z);
fake_object_set_preset(fake, preset);
return objectIndex;
}
SM64_LIB_FN void sm64_fake_object_delete(int32_t objectId)
{
if (objectId >= s_fakeobj_instance_pool.size || s_fakeobj_instance_pool.objects[objectId] == NULL)
{
DEBUG_PRINT("Tried to use non-existant Object with ID: %d", objectId);
return;
}
struct FakeObject *fake = s_fakeobj_instance_pool.objects[objectId];
struct MarioState *m = &g_state->mgMarioStateVal;
uint32_t action = m->action;
if (m->interactObj == &fake->object || m->usedObj == &fake->object || m->heldObj == &fake->object)
{
m->interactObj = NULL;
m->usedObj = NULL;
m->heldObj = NULL;
switch (action)
{
case ACT_HOLDING_POLE:
case ACT_CLIMBING_POLE:
case ACT_TOP_OF_POLE:
m->action = ACT_FREEFALL;
break;
default:
m->action = ACT_IDLE;
break;
}
m->actionState = 0;
}
if (m->marioBodyState != NULL && m->heldObj == NULL)
{
vec3f_set(m->marioBodyState->heldObjLastPosition, 0.0f, 0.0f, 0.0f);
}
obj_pool_free_index(&s_fakeobj_instance_pool, (uint32_t)objectId);
}
SM64_LIB_FN void sm64_fake_object_set_position(int32_t objectId, float x, float y, float z)
{
if (objectId >= s_fakeobj_instance_pool.size || s_fakeobj_instance_pool.objects[objectId] == NULL)
{
DEBUG_PRINT("Tried to use non-existant Object with ID: %d", objectId);
return;
}
struct FakeObject *fake = s_fakeobj_instance_pool.objects[objectId];
fake->object.oPosX = x;
fake->object.oPosY = y;
fake->object.oPosZ = z;
fake_object_sync_position(fake);
}
SM64_LIB_FN void sm64_fake_object_set_hitbox(int32_t objectId, float radius, float height, float downOffset)
{
if (objectId >= s_fakeobj_instance_pool.size || s_fakeobj_instance_pool.objects[objectId] == NULL)
{
DEBUG_PRINT("Tried to use non-existant Object with ID: %d", objectId);
return;
}
struct FakeObject *fake = s_fakeobj_instance_pool.objects[objectId];
fake->object.hitboxRadius = radius;
fake->object.hitboxHeight = height;
fake->object.hitboxDownOffset = downOffset;
}
SM64_LIB_FN void sm64_fake_object_tick(int32_t objectId)
{
if (objectId >= s_fakeobj_instance_pool.size || s_fakeobj_instance_pool.objects[objectId] == NULL)
{
DEBUG_PRINT("Tried to use non-existant Object with ID: %d", objectId);
return;
}
struct FakeObject *fake = s_fakeobj_instance_pool.objects[objectId];
struct GlobalState *state = g_state;
struct MarioState *m = state != NULL ? &state->mgMarioStateVal : NULL;
struct Object *obj = &fake->object;
obj->oInteractStatus = 0;
if (m == NULL)
{
return;
}
if (fake_object_overlaps_mario(fake, m))
{
fake_object_add_collision(fake, m);
}
}
SM64_LIB_FN bool sm64_mario_attack(int32_t marioId, float x, float y, float z, float hitboxHeight)
{
if (marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL)
@@ -653,12 +771,10 @@ SM64_LIB_FN void sm64_surface_object_delete(uint32_t objectId)
// A mario standing on the platform that is being destroyed will have a pointer to freed memory if we don't clear it.
for (int i = 0; i < s_mario_instance_pool.size; ++i)
{
if (s_mario_instance_pool.objects[i] == NULL)
continue;
if (s_mario_instance_pool.objects[i] == NULL) continue;
struct GlobalState *state = ((struct MarioInstance *)s_mario_instance_pool.objects[i])->globalState;
if (state->mgMarioObject->platform == surfaces_object_get_transform_ptr(objectId))
state->mgMarioObject->platform = NULL;
if (state->mgMarioObject->platform == surfaces_object_get_transform_ptr(objectId)) state->mgMarioObject->platform = NULL;
}
surfaces_unload_object(objectId);