diff --git a/.idea/misc.xml b/.idea/misc.xml index 9f2b25a..44d46bc 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,5 +1,8 @@ + + + \ No newline at end of file diff --git a/src/FakeObject.c b/src/FakeObject.c index ea80b9f..34b8cda 100644 --- a/src/FakeObject.c +++ b/src/FakeObject.c @@ -14,6 +14,53 @@ #include "libsm64.h" #include #include +#include "decomp/shim.h" + +#define o gCurrentObject + +struct Object *cur_obj_find_nearest_pole(void) +{ + struct Object *closestObj = NULL; + struct Object *obj; + f32 minDist = 0x20000; + + for (s32 i = 0; i < s_fakeobj_instance_pool.size; i++) + { + obj = s_fakeobj_instance_pool.objects[i]; + + if (obj == NULL) + continue; + + if (obj->activeFlags == ACTIVE_FLAG_DEACTIVATED) + continue; + + if (!(obj->oInteractType & INTERACT_POLE)) + continue; + + if (obj == o) + continue; + + f32 objDist = dist_between_objects(o, obj); + + if (objDist < minDist) + { + closestObj = obj; + minDist = objDist; + } + } + + return closestObj; +} + +f32 dist_between_objects(struct Object *obj1, struct Object *obj2) +{ + if (obj1 == NULL || obj2 == NULL) { return 0; } + f32 dx = obj1->oPosX - obj2->oPosX; + f32 dy = obj1->oPosY - obj2->oPosY; + f32 dz = obj1->oPosZ - obj2->oPosZ; + + return sqrtf(dx * dx + dy * dy + dz * dz); +} void fake_object_init(struct FakeObject *fake, float x, float y, float z) { diff --git a/src/FakeObject.h b/src/FakeObject.h index 996d0f3..254c843 100644 --- a/src/FakeObject.h +++ b/src/FakeObject.h @@ -16,6 +16,9 @@ struct FakeObject struct Object object; }; +struct Object* cur_obj_find_nearest_pole(void); +f32 dist_between_objects(struct Object *obj1, struct Object *obj2); + void fake_object_init(struct FakeObject *fake, float x, float y, float z); void fake_object_sync_position(struct FakeObject *fake); diff --git a/src/decomp/game/mario_actions_automatic.c b/src/decomp/game/mario_actions_automatic.c index eef46b2..81c4526 100644 --- a/src/decomp/game/mario_actions_automatic.c +++ b/src/decomp/game/mario_actions_automatic.c @@ -21,6 +21,7 @@ #include "../include/object_fields.h" #include "../include/mario_geo_switch_case_ids.h" #include "../../rumble.h" +#include "../../FakeObject.h" static Vec3f gVec3fZero = {0.0f, 0.0f, 0.0f}; @@ -35,16 +36,21 @@ static Vec3f gVec3fZero = {0.0f, 0.0f, 0.0f}; void add_tree_leaf_particles(struct MarioState *m) { f32 leafHeight; - s32 isOnTree = false;//(m->usedObj->behavior == segmented_to_virtual(bhvTree)); + s32 isOnTree = false; //(m->usedObj->behavior == segmented_to_virtual(bhvTree)); - if (isOnTree) { + if (isOnTree) + { // make leaf effect spawn higher on the Shifting Sand Land palm tree - if (gCurrLevelNum == LEVEL_SSL) { + if (gCurrLevelNum == LEVEL_SSL) + { leafHeight = 250.0f; - } else { + } + else + { leafHeight = 100.0f; } - if (m->pos[1] - m->floorHeight > leafHeight) { + if (m->pos[1] - m->floorHeight > leafHeight) + { m->particleFlags |= PARTICLE_LEAF; } } @@ -52,24 +58,33 @@ void add_tree_leaf_particles(struct MarioState *m) void play_climbing_sounds(struct MarioState *m, s32 b) { - s32 isOnTree = false;//(m->usedObj->behavior == segmented_to_virtual(bhvTree)); + s32 isOnTree = false; //(m->usedObj->behavior == segmented_to_virtual(bhvTree)); - if (b == 1) { - if (is_anim_past_frame(m, 1)) { - play_sound(isOnTree ? SOUND_ACTION_CLIMB_UP_TREE : SOUND_ACTION_CLIMB_UP_POLE, - m->marioObj->header.gfx.cameraToObject); + if (b == 1) + { + if (is_anim_past_frame(m, 1)) + { + play_sound(isOnTree ? SOUND_ACTION_CLIMB_UP_TREE : SOUND_ACTION_CLIMB_UP_POLE, m->marioObj->header.gfx.cameraToObject); } - } else { - play_sound(isOnTree ? SOUND_MOVING_SLIDE_DOWN_TREE : SOUND_MOVING_SLIDE_DOWN_POLE, - m->marioObj->header.gfx.cameraToObject); + } + else + { + play_sound(isOnTree ? SOUND_MOVING_SLIDE_DOWN_TREE : SOUND_MOVING_SLIDE_DOWN_POLE, m->marioObj->header.gfx.cameraToObject); } } s32 set_pole_position(struct MarioState *m, f32 offsetY) { - if (!m->isLocal && m->usedObj == NULL) + if (!m) { return 0;} + if (m->usedObj == NULL) { - return POLE_NONE; + m->usedObj = cur_obj_find_nearest_pole(); + } + + if (m->usedObj == NULL) + { + set_mario_action(m, ACT_FREEFALL, 0); + return POLE_FELL_OFF; } UNUSED s32 unused1; @@ -146,7 +161,11 @@ s32 set_pole_position(struct MarioState *m, f32 offsetY) s32 act_holding_pole(struct MarioState *m) { + if (!m) { return 0; } struct Object *marioObj = m->marioObj; + if (m->usedObj == NULL) { m->usedObj = cur_obj_find_nearest_pole(); } + if (m->usedObj == NULL) { return FALSE; } + f32 poleStickY = -m->controller->stickY; #ifdef VERSION_JP @@ -155,9 +174,7 @@ s32 act_holding_pole(struct MarioState *m) add_tree_leaf_particles(m); m->faceAngle[1] += 0x8000; return set_mario_action(m, ACT_WALL_KICK_AIR, 0); - } - - if (m->input & INPUT_Z_PRESSED) + } if (m->input & INPUT_Z_PRESSED) { add_tree_leaf_particles(m); m->forwardVel = -2.0f; @@ -181,12 +198,7 @@ s32 act_holding_pole(struct MarioState *m) if (poleStickY > 16.0f) { - f32 poleTop = m->pos[1] + 1000; - - if (m->usedObj != NULL) - { - poleTop = m->usedObj->hitboxHeight - 100.0f; - } + f32 poleTop = m->usedObj->hitboxHeight - 100.0f; // const BehaviorScript *poleBehavior = virtual_to_segmented(0x13, m->usedObj->behavior); if (marioObj->oMarioPolePos < poleTop - 0.4f) @@ -241,6 +253,8 @@ s32 act_holding_pole(struct MarioState *m) s32 act_climbing_pole(struct MarioState *m) { + if (!m) { return 0; } + if (m->usedObj == NULL) { m->usedObj = cur_obj_find_nearest_pole(); } s32 sp24; struct Object *marioObj = m->marioObj; s16 cameraAngle = m->area->camera->yaw; @@ -284,6 +298,8 @@ s32 act_climbing_pole(struct MarioState *m) s32 act_grab_pole_slow(struct MarioState *m) { + if (!m) { return 0; } + if (m->usedObj == NULL) { m->usedObj = cur_obj_find_nearest_pole(); } play_sound_if_no_flag(m, SOUND_MARIO_WHOA, MARIO_MARIO_SOUND_PLAYED); if (set_pole_position(m, 0.0f) == POLE_NONE) @@ -301,6 +317,8 @@ s32 act_grab_pole_slow(struct MarioState *m) s32 act_grab_pole_fast(struct MarioState *m) { + if (!m) { return 0; } + if (m->usedObj == NULL) { m->usedObj = cur_obj_find_nearest_pole(); } struct Object *marioObj = m->marioObj; play_sound_if_no_flag(m, SOUND_MARIO_WHOA, MARIO_MARIO_SOUND_PLAYED); @@ -330,6 +348,8 @@ s32 act_grab_pole_fast(struct MarioState *m) s32 act_top_of_pole_transition(struct MarioState *m) { + if (!m) { return 0; } + if (m->usedObj == NULL) { m->usedObj = cur_obj_find_nearest_pole(); } struct Object *marioObj = m->marioObj; marioObj->oMarioPoleYawVel = 0; @@ -356,8 +376,9 @@ s32 act_top_of_pole_transition(struct MarioState *m) s32 act_top_of_pole(struct MarioState *m) { - UNUSED - struct Object *marioObj = m->marioObj; + if (!m) { return 0; } + UNUSED struct Object *marioObj = m->marioObj; + if (m->usedObj == NULL) { m->usedObj = cur_obj_find_nearest_pole(); } f32 poleStickY = -m->controller->stickY; if (m->input & INPUT_A_PRESSED) @@ -435,8 +456,7 @@ s32 update_hang_moving(struct MarioState *m) m->forwardVel = maxSpeed; } - m->faceAngle[1] = - m->intendedYaw - approach_s32((s16)(m->intendedYaw - m->faceAngle[1]), 0, 0x800, 0x800); + m->faceAngle[1] = m->intendedYaw - approach_s32((s16)(m->intendedYaw - m->faceAngle[1]), 0, 0x800, 0x800); m->slideYaw = m->faceAngle[1]; m->slideVelX = m->forwardVel * sins(m->faceAngle[1]); @@ -739,9 +759,7 @@ s32 act_ledge_climb_slow(struct MarioState *m) m->actionTimer++; - if (m->actionTimer >= 28 - && m->input - & (INPUT_NONZERO_ANALOG | INPUT_A_PRESSED | INPUT_OFF_FLOOR | INPUT_ABOVE_SLIDE)) + if (m->actionTimer >= 28 && m->input & (INPUT_NONZERO_ANALOG | INPUT_A_PRESSED | INPUT_OFF_FLOOR | INPUT_ABOVE_SLIDE)) { climb_up_ledge(m); return check_common_action_exits(m); @@ -810,8 +828,7 @@ s32 act_grabbed(struct MarioState *m) queue_rumble_data(5, 60); // #endif - return set_mario_action(m, m->forwardVel >= 0.0f ? ACT_THROWN_FORWARD : ACT_THROWN_BACKWARD, - thrown); + return set_mario_action(m, m->forwardVel >= 0.0f ? ACT_THROWN_FORWARD : ACT_THROWN_BACKWARD, thrown); } set_mario_animation(m, MARIO_ANIM_BEING_GRABBED); @@ -920,6 +937,8 @@ s32 act_in_cannon(struct MarioState *m) s32 act_tornado_twirling(struct MarioState *m) { + if (!m) { return 0; } + if (m->usedObj == NULL) { return FALSE; } struct SM64SurfaceCollisionData *floor; Vec3f nextPos; struct Object *marioObj = m->marioObj; diff --git a/src/decomp/shim.h b/src/decomp/shim.h index 6fa33a8..dc8342f 100644 --- a/src/decomp/shim.h +++ b/src/decomp/shim.h @@ -68,7 +68,19 @@ static void print_text_fmt_int(s32 x, s32 y, const char *str, s32 n) { } -static s16 level_trigger_warp(struct MarioState *m, s32 warpOp) { return 0; } +static s16 level_trigger_warp(struct MarioState *m, s32 warpOp) +{ + if (warpOp == WARP_OP_DEATH && m->health > 0xFF) + { + m->health = 0xFF; + } + if (warpOp == WARP_OP_WARP_FLOOR && m->health > 0xFF) + { + m->health = 0xFF; + return 20; + } + return 0; +} //static void play_cap_music(u16 seqArgs) {} //static void fadeout_cap_music(void) {} //static void stop_cap_music(void) {} diff --git a/src/libsm64.c b/src/libsm64.c index 449008f..ac7c9e5 100644 --- a/src/libsm64.c +++ b/src/libsm64.c @@ -655,28 +655,12 @@ SM64_LIB_FN void sm64_fake_object_delete(int32_t objectId) 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) { diff --git a/src/libsm64.h b/src/libsm64.h index 085865b..b10fcef 100644 --- a/src/libsm64.h +++ b/src/libsm64.h @@ -8,6 +8,8 @@ #include #include +#include "obj_pool.h" + #if defined(_WIN32) #ifdef SM64_LIB_EXPORT #define SM64_LIB_FN __declspec(dllexport) @@ -154,6 +156,8 @@ enum SM64_GEO_MAX_TRIANGLES = 1024, }; +extern struct ObjPool s_fakeobj_instance_pool; + typedef void (*SM64RumbleCallbackFunctionPtr)(int32_t marioId, int16_t level, int16_t time); extern SM64_LIB_FN void sm64_register_rumble_callback_function(SM64RumbleCallbackFunctionPtr rumbleCallbackFunction);