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
+1 -1
View File
@@ -279,6 +279,7 @@
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_EXISTING_ENUM_ARRANGEMENT/@EntryValue" value="false" type="bool" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_EXISTING_ENUM_ARRANGEMENT/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LABELED_STATEMENT_STYLE/@EntryValue" value="ON_SINGLE_LINE" type="string" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LABELED_STATEMENT_STYLE/@EntryValue" value="ON_SINGLE_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_DEREF_IN_TRAILING_RETURN_TYPES/@EntryValue" value="ON_SINGLE_LINE" type="string" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_DEREF_IN_TRAILING_RETURN_TYPES/@EntryValue" value="ON_SINGLE_LINE" type="string" />
@@ -330,7 +331,6 @@
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ENUMERATION_STYLE/@EntryValue" value="CHOP_ALWAYS" type="string" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ENUMERATION_STYLE/@EntryValue" value="CHOP_ALWAYS" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_LINES/@EntryValue" value="false" type="bool" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_LINES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" /> <option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=05D45346A5B5B54F93A9F94C46B14079/@EntryIndexRemoved" value="true" type="bool" /> <option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=05D45346A5B5B54F93A9F94C46B14079/@EntryIndexRemoved" value="true" type="bool" />
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=05D45346A5B5B54F93A9F94C46B14079/@EntryIndexedValue" value="" type="string" /> <option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=05D45346A5B5B54F93A9F94C46B14079/@EntryIndexedValue" value="" type="string" />
Generated
-1
View File
@@ -2,6 +2,5 @@
<project version="4"> <project version="4">
<component name="VcsDirectoryMappings"> <component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" /> <mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/test/imgui" vcs="Git" />
</component> </component>
</project> </project>
+170
View File
@@ -0,0 +1,170 @@
//
// Created by nepushiro on 5/29/26.
//
#include "FakeObject.h"
#include <string.h>
#include "decomp/global_state.h"
#include "decomp/engine/math_util.h"
#include "decomp/game/interaction.h"
#include "decomp/game/object_stuff.h"
#include "decomp/include/object_fields.h"
#include "libsm64.h"
#include <stdint.h>
#include <stdbool.h>
void fake_object_init(struct FakeObject *fake, float x, float y, float z)
{
memset(fake, 0, sizeof(*fake));
struct Object *obj = &fake->object;
obj->activeFlags = ACTIVE_FLAG_ACTIVE | ACTIVE_FLAG_UNK8;
obj->parentObj = NULL;
obj->prevObj = NULL;
obj->collidedObjInteractTypes = 0;
obj->numCollidedObjs = 0;
for (s32 i = 0; i < 0x50; i++)
{
#ifdef _WIN32
obj->rawData.asS32[i] = 0;
#endif
#ifdef _WIN64
obj->ptrData.asVoidPtr[i] = NULL;
#endif
}
obj->unused1 = 0;
obj->bhvStackIndex = 0;
obj->bhvDelayTimer = 0;
obj->hitboxRadius = 50.0f;
obj->hitboxHeight = 100.0f;
obj->hurtboxRadius = 0.0f;
obj->hurtboxHeight = 0.0f;
obj->hitboxDownOffset = 0.0f;
obj->unused2 = 0;
obj->platform = NULL;
obj->collisionData = NULL;
obj->oIntangibleTimer = -1;
obj->oDamageOrCoinValue = 0;
obj->oHealth = 2048;
obj->oCollisionDistance = 1000.0f;
obj->oDrawingDistance = 4000.0f;
mtxf_identity(obj->transform);
obj->respawnInfoType = RESPAWN_INFO_TYPE_NULL;
obj->respawnInfo = NULL;
obj->oDistanceToMario = 19000.0f;
obj->oRoom = -1;
obj->oInteractType = 0;
obj->oInteractionSubtype = 0;
obj->oHeldState = 0;
obj->oAction = 0;
obj->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
obj->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
obj->header.gfx.node.flags &= ~GRAPH_RENDER_BILLBOARD;
obj->header.gfx.pos[0] = x;
obj->header.gfx.pos[1] = y;
obj->header.gfx.pos[2] = z;
obj->header.gfx.angle[0] = 0;
obj->header.gfx.angle[1] = 0;
obj->header.gfx.angle[2] = 0;
obj->header.gfx.throwMatrix = NULL;
obj->header.gfx.sharedChild = NULL;
obj->header.gfx.animInfo.curAnim = NULL;
obj->header.gfx.animInfo.animID = 0;
obj->header.gfx.animInfo.animFrame = 0;
obj->header.gfx.animInfo.animTimer = 0;
obj->oPosX = x;
obj->oPosY = y;
obj->oPosZ = z;
obj->oMoveAnglePitch = 0;
obj->oMoveAngleYaw = 0;
obj->oMoveAngleRoll = 0;
obj->oFaceAnglePitch = 0;
obj->oFaceAngleYaw = 0;
obj->oFaceAngleRoll = 0;
}
void fake_object_sync_position(struct FakeObject *fake)
{
struct Object *obj = &fake->object;
obj->header.gfx.pos[0] = obj->oPosX;
obj->header.gfx.pos[1] = obj->oPosY;
obj->header.gfx.pos[2] = obj->oPosZ;
}
bool fake_object_overlaps_mario(struct FakeObject *fake, struct MarioState *m)
{
struct Object *obj = &fake->object;
float dx = obj->oPosX - m->pos[0];
float dz = obj->oPosZ - m->pos[2];
float radius = obj->hitboxRadius;
float top = obj->oPosY + obj->hitboxHeight;
float bottom = obj->oPosY - obj->hitboxDownOffset;
if ((dx * dx) + (dz * dz) > radius * radius)
{
return false;
}
if (m->pos[1] < bottom || m->pos[1] > top)
{
return false;
}
return true;
}
void fake_object_add_collision(struct FakeObject *fake, struct MarioState *m)
{
struct Object *obj = &fake->object;
if (obj->oHeldState != 0)
{
return;
}
m->marioObj->collidedObjInteractTypes |= obj->oInteractType;
if (m->marioObj->numCollidedObjs < 4)
{
m->marioObj->collidedObjs[m->marioObj->numCollidedObjs++] = obj;
}
}
void fake_object_apply_pole(struct FakeObject *fake)
{
(void)fake;
}
void fake_object_set_preset(struct FakeObject *fake, uint32_t preset)
{
struct Object *obj = &fake->object;
switch (preset)
{
case 1:
obj->oInteractType = INTERACT_POLE;
obj->oInteractionSubtype = 0;
obj->hitboxRadius = 60.0f;
obj->hitboxHeight = 1000.0f;
obj->hitboxDownOffset = 0.0f;
break;
case 0: default:
obj->oInteractType = 0;
obj->oInteractionSubtype = 0;
obj->hitboxRadius = 50.0f;
obj->hitboxHeight = 100.0f;
obj->hitboxDownOffset = 0.0f;
break;
}
}
+25
View File
@@ -0,0 +1,25 @@
//
// Created by nepushiro on 5/29/26.
//
#ifndef LIBSM64_FAKEOBJECT_H
#define LIBSM64_FAKEOBJECT_H
#endif //LIBSM64_FAKEOBJECT_H
#include <stdint.h>
#include <types.h>
#include <stdbool.h>
struct FakeObject
{
struct Object object;
};
void fake_object_init(struct FakeObject *fake, float x, float y, float z);
void fake_object_sync_position(struct FakeObject *fake);
bool fake_object_overlaps_mario(struct FakeObject *fake, struct MarioState *m);
void fake_object_add_collision(struct FakeObject *fake, struct MarioState *m);
void fake_object_apply_pole(struct FakeObject *fake);
void fake_object_set_preset(struct FakeObject *fake, uint32_t preset);
+57 -1
View File
@@ -71,6 +71,62 @@ static u32 interact_noop(struct MarioState *m, u32 interactType, struct Object *
return FALSE; return FALSE;
} }
void push_mario_out_of_object(struct MarioState *m, struct Object *o, f32 padding);
void reset_mario_pitch(struct MarioState *m);
static u32 interact_pole(struct MarioState *m, u32 interactType, struct Object *o)
{
s32 actionId = m->action & ACT_ID_MASK;
if (actionId >= 0x080 && actionId < 0x0A0)
{
#if defined(VERSION_SH) || defined(VERSION_CN)
f32 velConv = m->forwardVel; // conserve the velocity.
struct Object *marioObj = m->marioObj;
u32 lowSpeed;
#else
u32 lowSpeed = (m->forwardVel <= 10.0f);
struct Object *marioObj = m->marioObj;
#endif
if (!(m->prevAction & ACT_FLAG_ON_POLE) || m->usedObj != o)
{
#if defined(VERSION_SH) || defined(VERSION_CN)
lowSpeed = (velConv <= 10.0f);
#endif
mario_stop_riding_and_holding(m);
m->interactObj = o;
m->usedObj = o;
m->vel[1] = 0.0f;
m->forwardVel = 0.0f;
marioObj->oMarioPoleUnk108 = 0;
marioObj->oMarioPoleYawVel = 0;
marioObj->oMarioPolePos = m->pos[1] - o->oPosY;
if (lowSpeed)
{
return set_mario_action(m, ACT_GRAB_POLE_SLOW, 0);
}
#if defined(VERSION_SH) || defined(VERSION_CN)
marioObj->oMarioPoleYawVel = (s32)(velConv * 0x100 + 0x1000);
#else
marioObj->oMarioPoleYawVel = (s32)(m->forwardVel * 0x100 + 0x1000);
#endif
reset_mario_pitch(m);
#if ENABLE_RUMBLE
queue_rumble_data(5, 80);
#endif
return set_mario_action(m, ACT_GRAB_POLE_FAST, 0);
}
}
return FALSE;
}
static struct InteractionHandler sInteractionHandlers[] = { static struct InteractionHandler sInteractionHandlers[] = {
{INTERACT_COIN, interact_noop}, {INTERACT_COIN, interact_noop},
{INTERACT_WATER_RING, interact_noop}, {INTERACT_WATER_RING, interact_noop},
@@ -94,7 +150,7 @@ static struct InteractionHandler sInteractionHandlers[] = {
{INTERACT_HIT_FROM_BELOW, interact_noop}, {INTERACT_HIT_FROM_BELOW, interact_noop},
{INTERACT_BOUNCE_TOP, interact_noop}, {INTERACT_BOUNCE_TOP, interact_noop},
{INTERACT_DAMAGE, interact_noop}, {INTERACT_DAMAGE, interact_noop},
{INTERACT_POLE, interact_noop}, {INTERACT_POLE, interact_pole},
{INTERACT_HOOT, interact_noop}, {INTERACT_HOOT, interact_noop},
{INTERACT_BREAKABLE, interact_noop}, {INTERACT_BREAKABLE, interact_noop},
{INTERACT_KOOPA, interact_noop}, {INTERACT_KOOPA, interact_noop},
+12 -10
View File
@@ -123,8 +123,7 @@ s32 set_pole_position(struct MarioState *m, f32 offsetY)
} }
vec3f_copy(m->marioObj->header.gfx.pos, m->pos); vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
vec3s_set(m->marioObj->header.gfx.angle, m->usedObj->oMoveAnglePitch, m->faceAngle[1], vec3s_set(m->marioObj->header.gfx.angle, m->usedObj->oMoveAnglePitch, m->faceAngle[1], m->usedObj->oMoveAngleRoll);
m->usedObj->oMoveAngleRoll);
return result; return result;
} }
@@ -132,6 +131,7 @@ s32 set_pole_position(struct MarioState *m, f32 offsetY)
s32 act_holding_pole(struct MarioState *m) s32 act_holding_pole(struct MarioState *m)
{ {
struct Object *marioObj = m->marioObj; struct Object *marioObj = m->marioObj;
f32 poleStickY = -m->controller->stickY;
#ifdef VERSION_JP #ifdef VERSION_JP
if (m->input & INPUT_A_PRESSED) if (m->input & INPUT_A_PRESSED)
@@ -163,7 +163,7 @@ s32 act_holding_pole(struct MarioState *m)
} }
#endif #endif
if (m->controller->stickY > 16.0f) if (poleStickY > 16.0f)
{ {
f32 poleTop = m->usedObj->hitboxHeight - 100.0f; f32 poleTop = m->usedObj->hitboxHeight - 100.0f;
// const BehaviorScript *poleBehavior = virtual_to_segmented(0x13, m->usedObj->behavior); // const BehaviorScript *poleBehavior = virtual_to_segmented(0x13, m->usedObj->behavior);
@@ -174,15 +174,15 @@ s32 act_holding_pole(struct MarioState *m)
} }
// if (poleBehavior != bhvGiantPole && m->controller->stickY > 50.0f) { // if (poleBehavior != bhvGiantPole && m->controller->stickY > 50.0f) {
if (m->controller->stickY > 50.0f) if (poleStickY > 50.0f)
{ {
return set_mario_action(m, ACT_TOP_OF_POLE_TRANSITION, 0); return set_mario_action(m, ACT_TOP_OF_POLE_TRANSITION, 0);
} }
} }
if (m->controller->stickY < -16.0f) if (poleStickY < -16.0f)
{ {
marioObj->oMarioPoleYawVel -= m->controller->stickY * 2; marioObj->oMarioPoleYawVel -= poleStickY * 2;
if (marioObj->oMarioPoleYawVel > 0x1000) if (marioObj->oMarioPoleYawVel > 0x1000)
{ {
marioObj->oMarioPoleYawVel = 0x1000; marioObj->oMarioPoleYawVel = 0x1000;
@@ -223,6 +223,7 @@ s32 act_climbing_pole(struct MarioState *m)
s32 sp24; s32 sp24;
struct Object *marioObj = m->marioObj; struct Object *marioObj = m->marioObj;
s16 cameraAngle = m->area->camera->yaw; s16 cameraAngle = m->area->camera->yaw;
f32 poleStickY = -m->controller->stickY;
#ifndef VERSION_JP #ifndef VERSION_JP
if (m->health < 0x100) if (m->health < 0x100)
@@ -240,18 +241,18 @@ s32 act_climbing_pole(struct MarioState *m)
return set_mario_action(m, ACT_WALL_KICK_AIR, 0); return set_mario_action(m, ACT_WALL_KICK_AIR, 0);
} }
if (m->controller->stickY < 8.0f) if (poleStickY < 8.0f)
{ {
return set_mario_action(m, ACT_HOLDING_POLE, 0); return set_mario_action(m, ACT_HOLDING_POLE, 0);
} }
marioObj->oMarioPolePos += m->controller->stickY / 8.0f; marioObj->oMarioPolePos += poleStickY / 8.0f;
marioObj->oMarioPoleYawVel = 0; marioObj->oMarioPoleYawVel = 0;
m->faceAngle[1] = cameraAngle - approach_s32((s16)(cameraAngle - m->faceAngle[1]), 0, 0x400, 0x400); m->faceAngle[1] = cameraAngle - approach_s32((s16)(cameraAngle - m->faceAngle[1]), 0, 0x400, 0x400);
if (set_pole_position(m, 0.0f) == POLE_NONE) if (set_pole_position(m, 0.0f) == POLE_NONE)
{ {
sp24 = m->controller->stickY / 4.0f * 0x10000; sp24 = poleStickY / 4.0f * 0x10000;
set_mario_anim_with_accel(m, MARIO_ANIM_CLIMB_UP_POLE, sp24); set_mario_anim_with_accel(m, MARIO_ANIM_CLIMB_UP_POLE, sp24);
add_tree_leaf_particles(m); add_tree_leaf_particles(m);
play_climbing_sounds(m, 1); play_climbing_sounds(m, 1);
@@ -336,12 +337,13 @@ s32 act_top_of_pole(struct MarioState *m)
{ {
UNUSED UNUSED
struct Object *marioObj = m->marioObj; struct Object *marioObj = m->marioObj;
f32 poleStickY = -m->controller->stickY;
if (m->input & INPUT_A_PRESSED) if (m->input & INPUT_A_PRESSED)
{ {
return set_mario_action(m, ACT_TOP_OF_POLE_JUMP, 0); return set_mario_action(m, ACT_TOP_OF_POLE_JUMP, 0);
} }
if (m->controller->stickY < -16.0f) if (poleStickY < -16.0f)
{ {
return set_mario_action(m, ACT_TOP_OF_POLE_TRANSITION, 1); return set_mario_action(m, ACT_TOP_OF_POLE_TRANSITION, 1);
} }
+3
View File
@@ -3,6 +3,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "../obj_pool.h"
struct GlobalState *g_state = 0; struct GlobalState *g_state = 0;
struct GlobalState *global_state_create(void) struct GlobalState *global_state_create(void)
@@ -21,5 +23,6 @@ void global_state_bind(struct GlobalState *state)
void global_state_delete(struct GlobalState *state) void global_state_delete(struct GlobalState *state)
{ {
obj_pool_free_all(&state->mgFakeObjects);
free(state); free(state);
} }
+3 -1
View File
@@ -2,6 +2,7 @@
#include "include/types.h" #include "include/types.h"
#include "game/area.h" #include "game/area.h"
#include "../obj_pool.h"
struct GlobalState struct GlobalState
{ {
@@ -41,6 +42,7 @@ struct GlobalState
struct Area *mgCurrentArea; struct Area *mgCurrentArea;
struct Object *mgCurrentObject; struct Object *mgCurrentObject;
struct Object *mgMarioObject; struct Object *mgMarioObject;
struct ObjPool mgFakeObjects;
struct MarioAnimation mD_80339D10; struct MarioAnimation mD_80339D10;
struct MarioState mgMarioStateVal; struct MarioState mgMarioStateVal;
}; };
@@ -54,4 +56,4 @@ extern struct GlobalState *global_state_create(void);
extern void global_state_bind(struct GlobalState *state); extern void global_state_bind(struct GlobalState *state);
extern void global_state_delete(struct GlobalState *state); extern void global_state_delete(struct GlobalState *state);
+125 -9
View File
@@ -38,6 +38,8 @@
#include "load_tex_data.h" #include "load_tex_data.h"
#include "obj_pool.h" #include "obj_pool.h"
#include "fake_interaction.h" #include "fake_interaction.h"
#include "object_fields.h"
#include "FakeObject.h"
static struct AllocOnlyPool *s_mario_geo_pool = NULL; static struct AllocOnlyPool *s_mario_geo_pool = NULL;
static struct GraphNode *s_mario_graph_node = 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_mario_instance_pool = {0, 0};
struct ObjPool s_fakeobj_instance_pool = {0, 0};
static void update_button(bool on, u16 button) 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) SM64_LIB_FN void sm64_global_init(const uint8_t *rom, uint8_t *outTexture)
{ {
if (s_init_global) if (s_init_global) sm64_global_terminate();
sm64_global_terminate();
s_init_global = true; s_init_global = true;
@@ -128,9 +130,8 @@ SM64_LIB_FN void sm64_global_terminate(void)
if (s_init_one_mario) if (s_init_one_mario)
{ {
for (int i = 0; i < s_mario_instance_pool.size; ++i) for (int i = 0; i < s_mario_instance_pool.size; ++i) if (s_mario_instance_pool.objects[i] != NULL) sm64_mario_delete(i);
if (s_mario_instance_pool.objects[i] != NULL) for (int i = 0; i < s_fakeobj_instance_pool.size; ++i) if (s_fakeobj_instance_pool.objects[i] != NULL) sm64_fake_object_delete(i);
sm64_mario_delete(i);
obj_pool_free_all(&s_mario_instance_pool); 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(); apply_mario_platform_displacement();
bhv_mario_update(); 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 update_mario_platform(); // TODO platform grabbed here and used next tick could be a use-after-free
gfx_adapter_bind_output_buffers(outBuffers); 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; 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) 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) 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. // 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) for (int i = 0; i < s_mario_instance_pool.size; ++i)
{ {
if (s_mario_instance_pool.objects[i] == NULL) if (s_mario_instance_pool.objects[i] == NULL) continue;
continue;
struct GlobalState *state = ((struct MarioInstance *)s_mario_instance_pool.objects[i])->globalState; struct GlobalState *state = ((struct MarioInstance *)s_mario_instance_pool.objects[i])->globalState;
if (state->mgMarioObject->platform == surfaces_object_get_transform_ptr(objectId)) if (state->mgMarioObject->platform == surfaces_object_get_transform_ptr(objectId)) state->mgMarioObject->platform = NULL;
state->mgMarioObject->platform = NULL;
} }
surfaces_unload_object(objectId); surfaces_unload_object(objectId);
+17 -2
View File
@@ -1,9 +1,12 @@
#ifndef LIB_SM64_H #ifndef LIB_SM64_H
#define LIB_SM64_H #define LIB_SM64_H
#include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h>
#include <math.h>
#if defined(_WIN32) #if defined(_WIN32)
#ifdef SM64_LIB_EXPORT #ifdef SM64_LIB_EXPORT
@@ -146,7 +149,9 @@ struct SM64SurfaceCollisionData
enum enum
{ {
SM64_TEXTURE_WIDTH = 64 * 11, SM64_TEXTURE_HEIGHT = 64, SM64_GEO_MAX_TRIANGLES = 1024, SM64_TEXTURE_WIDTH = 64 * 11,
SM64_TEXTURE_HEIGHT = 64,
SM64_GEO_MAX_TRIANGLES = 1024,
}; };
typedef void (*SM64RumbleCallbackFunctionPtr)(int32_t marioId, int16_t level, int16_t time); typedef void (*SM64RumbleCallbackFunctionPtr)(int32_t marioId, int16_t level, int16_t time);
@@ -259,6 +264,16 @@ extern SM64_LIB_FN uint16_t sm64_get_current_background_music();
extern SM64_LIB_FN void sm64_play_sound(int32_t soundBits, float *pos); extern SM64_LIB_FN void sm64_play_sound(int32_t soundBits, float *pos);
extern SM64_LIB_FN int32_t sm64_fake_object_create(float x, float y, float z, int32_t preset);
extern SM64_LIB_FN void sm64_fake_object_delete(int32_t objectId);
extern SM64_LIB_FN void sm64_fake_object_set_position(int32_t objectId, float x, float y, float z);
extern SM64_LIB_FN void sm64_fake_object_set_hitbox(int32_t objectId, float radius, float height, float downOffset);
extern SM64_LIB_FN void sm64_fake_object_tick(int32_t objectId);
extern SM64_LIB_FN void sm64_play_sound_global(int32_t soundBits); extern SM64_LIB_FN void sm64_play_sound_global(int32_t soundBits);
extern SM64_LIB_FN void sm64_set_sound_volume(float vol); extern SM64_LIB_FN void sm64_set_sound_volume(float vol);
+1
View File
@@ -3,6 +3,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <stdbool.h>
#include "decomp/include/types.h" #include "decomp/include/types.h"
#include "decomp/include/surface_terrains.h" #include "decomp/include/surface_terrains.h"
+4
View File
@@ -800,6 +800,9 @@ int main(void)
sm64_static_surfaces_load(surfaces, surfaces_count); sm64_static_surfaces_load(surfaces, surfaces_count);
int32_t marioId = sm64_mario_create(-6558, 0, 6464); int32_t marioId = sm64_mario_create(-6558, 0, 6464);
int thing = sm64_fake_object_create(-6558.0f, 0.0f, 6200.0f, 1);
sm64_fake_object_set_hitbox(thing, 32.0f, 800.0f * 2, 800);
printf("MarioID: %i\n", marioId); printf("MarioID: %i\n", marioId);
free(rom); free(rom);
@@ -958,6 +961,7 @@ int main(void)
tick -= 1.f / 30; tick -= 1.f / 30;
sm64_mario_tick(marioId, &marioInputs, &marioState, &marioGeometry); sm64_mario_tick(marioId, &marioInputs, &marioState, &marioGeometry);
sm64_fake_object_tick(thing);
memcpy(currPos, marioState.position, sizeof(currPos)); memcpy(currPos, marioState.position, sizeof(currPos));
memcpy(currGeoPos, marioGeometry.position, sizeof(currGeoPos)); memcpy(currGeoPos, marioGeometry.position, sizeof(currGeoPos));