2020-06-02 16:44:34 +00:00
|
|
|
#include <PR/ultratypes.h>
|
2019-08-25 04:46:40 +00:00
|
|
|
|
|
|
|
#include "engine/math_util.h"
|
|
|
|
#include "engine/surface_collision.h"
|
2020-06-02 16:44:34 +00:00
|
|
|
#include "level_update.h"
|
|
|
|
#include "object_fields.h"
|
|
|
|
#include "object_helpers.h"
|
2019-08-25 04:46:40 +00:00
|
|
|
#include "object_list_processor.h"
|
2020-06-02 16:44:34 +00:00
|
|
|
#include "platform_displacement.h"
|
|
|
|
#include "types.h"
|
2019-08-25 04:46:40 +00:00
|
|
|
|
|
|
|
u16 D_8032FEC0 = 0;
|
|
|
|
|
|
|
|
u32 unused_8032FEC4[4] = { 0 };
|
|
|
|
|
|
|
|
struct Object *gMarioPlatform = NULL;
|
|
|
|
|
|
|
|
/**
|
2020-06-02 16:44:34 +00:00
|
|
|
* Determine if Mario is standing on a platform object, meaning that he is
|
2019-08-25 04:46:40 +00:00
|
|
|
* within 4 units of the floor. Set his referenced platform object accordingly.
|
|
|
|
*/
|
|
|
|
void update_mario_platform(void) {
|
2020-08-07 05:52:32 +00:00
|
|
|
for (int i = 0; i < MAX_PLAYERS; i++) {
|
|
|
|
struct Surface *floor;
|
|
|
|
UNUSED u32 unused;
|
|
|
|
f32 marioX;
|
|
|
|
f32 marioY;
|
|
|
|
f32 marioZ;
|
|
|
|
f32 floorHeight;
|
|
|
|
u32 awayFromFloor;
|
|
|
|
|
|
|
|
struct Object* player = gMarioStates[i].marioObj;
|
|
|
|
|
|
|
|
if (player == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
2019-08-25 04:46:40 +00:00
|
|
|
|
2020-08-07 05:52:32 +00:00
|
|
|
//! If Mario moves onto a rotating platform in a PU, the find_floor call
|
|
|
|
// will detect the platform and he will end up receiving a large amount
|
|
|
|
// of displacement since he is considered to be far from the platform's
|
|
|
|
// axis of rotation.
|
2019-08-25 04:46:40 +00:00
|
|
|
|
2020-08-07 05:52:32 +00:00
|
|
|
marioX = player->oPosX;
|
|
|
|
marioY = player->oPosY;
|
|
|
|
marioZ = player->oPosZ;
|
|
|
|
floorHeight = find_floor(marioX, marioY, marioZ, &floor);
|
2019-08-25 04:46:40 +00:00
|
|
|
|
2020-08-07 05:52:32 +00:00
|
|
|
if (absf(marioY - floorHeight) < 4.0f) {
|
|
|
|
awayFromFloor = 0;
|
|
|
|
} else {
|
|
|
|
awayFromFloor = 1;
|
|
|
|
}
|
2019-08-25 04:46:40 +00:00
|
|
|
|
2020-08-07 05:52:32 +00:00
|
|
|
switch (awayFromFloor) {
|
|
|
|
case 1:
|
2019-08-25 04:46:40 +00:00
|
|
|
gMarioPlatform = NULL;
|
2020-08-07 05:52:32 +00:00
|
|
|
player->platform = NULL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0:
|
|
|
|
if (floor != NULL && floor->object != NULL) {
|
|
|
|
gMarioPlatform = floor->object;
|
|
|
|
player->platform = floor->object;
|
|
|
|
} else {
|
|
|
|
gMarioPlatform = NULL;
|
|
|
|
player->platform = NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2019-08-25 04:46:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-02 16:44:34 +00:00
|
|
|
* Get Mario's position and store it in x, y, and z.
|
2019-08-25 04:46:40 +00:00
|
|
|
*/
|
|
|
|
void get_mario_pos(f32 *x, f32 *y, f32 *z) {
|
|
|
|
*x = gMarioStates[0].pos[0];
|
|
|
|
*y = gMarioStates[0].pos[1];
|
|
|
|
*z = gMarioStates[0].pos[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-02 16:44:34 +00:00
|
|
|
* Set Mario's position.
|
2019-08-25 04:46:40 +00:00
|
|
|
*/
|
|
|
|
void set_mario_pos(f32 x, f32 y, f32 z) {
|
|
|
|
gMarioStates[0].pos[0] = x;
|
|
|
|
gMarioStates[0].pos[1] = y;
|
|
|
|
gMarioStates[0].pos[2] = z;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-02 16:44:34 +00:00
|
|
|
* Apply one frame of platform rotation to Mario or an object using the given
|
2019-08-25 04:46:40 +00:00
|
|
|
* platform. If isMario is 0, use gCurrentObject.
|
|
|
|
*/
|
2020-08-07 05:52:32 +00:00
|
|
|
void apply_platform_displacement(u32 playerIndex, struct Object *platform) {
|
2019-08-25 04:46:40 +00:00
|
|
|
f32 x;
|
|
|
|
f32 y;
|
|
|
|
f32 z;
|
|
|
|
f32 platformPosX;
|
|
|
|
f32 platformPosY;
|
|
|
|
f32 platformPosZ;
|
|
|
|
Vec3f currentObjectOffset;
|
|
|
|
Vec3f relativeOffset;
|
|
|
|
Vec3f newObjectOffset;
|
|
|
|
Vec3s rotation;
|
|
|
|
UNUSED s16 unused1;
|
|
|
|
UNUSED s16 unused2;
|
|
|
|
UNUSED s16 unused3;
|
|
|
|
f32 displaceMatrix[4][4];
|
|
|
|
|
|
|
|
rotation[0] = platform->oAngleVelPitch;
|
|
|
|
rotation[1] = platform->oAngleVelYaw;
|
|
|
|
rotation[2] = platform->oAngleVelRoll;
|
|
|
|
|
2020-08-07 05:52:32 +00:00
|
|
|
if (playerIndex != (u32)-1) {
|
2019-08-25 04:46:40 +00:00
|
|
|
D_8032FEC0 = 0;
|
2020-08-07 05:52:32 +00:00
|
|
|
x = gMarioStates[playerIndex].pos[0];
|
|
|
|
y = gMarioStates[playerIndex].pos[1];
|
|
|
|
z = gMarioStates[playerIndex].pos[2];
|
2019-08-25 04:46:40 +00:00
|
|
|
} else {
|
|
|
|
x = gCurrentObject->oPosX;
|
|
|
|
y = gCurrentObject->oPosY;
|
|
|
|
z = gCurrentObject->oPosZ;
|
|
|
|
}
|
|
|
|
|
|
|
|
x += platform->oVelX;
|
|
|
|
z += platform->oVelZ;
|
|
|
|
|
|
|
|
if (rotation[0] != 0 || rotation[1] != 0 || rotation[2] != 0) {
|
|
|
|
unused1 = rotation[0];
|
|
|
|
unused2 = rotation[2];
|
|
|
|
unused3 = platform->oFaceAngleYaw;
|
|
|
|
|
2020-08-07 05:52:32 +00:00
|
|
|
if (playerIndex != (u32)-1) {
|
|
|
|
gMarioStates[playerIndex].faceAngle[1] += rotation[1];
|
2019-09-01 19:50:50 +00:00
|
|
|
}
|
2019-08-25 04:46:40 +00:00
|
|
|
|
|
|
|
platformPosX = platform->oPosX;
|
|
|
|
platformPosY = platform->oPosY;
|
|
|
|
platformPosZ = platform->oPosZ;
|
|
|
|
|
|
|
|
currentObjectOffset[0] = x - platformPosX;
|
|
|
|
currentObjectOffset[1] = y - platformPosY;
|
|
|
|
currentObjectOffset[2] = z - platformPosZ;
|
|
|
|
|
|
|
|
rotation[0] = platform->oFaceAnglePitch - platform->oAngleVelPitch;
|
|
|
|
rotation[1] = platform->oFaceAngleYaw - platform->oAngleVelYaw;
|
|
|
|
rotation[2] = platform->oFaceAngleRoll - platform->oAngleVelRoll;
|
|
|
|
|
|
|
|
mtxf_rotate_zxy_and_translate(displaceMatrix, currentObjectOffset, rotation);
|
|
|
|
linear_mtxf_transpose_mul_vec3f(displaceMatrix, relativeOffset, currentObjectOffset);
|
|
|
|
|
|
|
|
rotation[0] = platform->oFaceAnglePitch;
|
|
|
|
rotation[1] = platform->oFaceAngleYaw;
|
|
|
|
rotation[2] = platform->oFaceAngleRoll;
|
|
|
|
|
|
|
|
mtxf_rotate_zxy_and_translate(displaceMatrix, currentObjectOffset, rotation);
|
|
|
|
linear_mtxf_mul_vec3f(displaceMatrix, newObjectOffset, relativeOffset);
|
|
|
|
|
|
|
|
x = platformPosX + newObjectOffset[0];
|
|
|
|
y = platformPosY + newObjectOffset[1];
|
|
|
|
z = platformPosZ + newObjectOffset[2];
|
|
|
|
}
|
|
|
|
|
2020-08-07 05:52:32 +00:00
|
|
|
if (playerIndex != (u32)-1) {
|
|
|
|
gMarioStates[playerIndex].pos[0] = x;
|
|
|
|
gMarioStates[playerIndex].pos[1] = y;
|
|
|
|
gMarioStates[playerIndex].pos[2] = z;
|
2019-08-25 04:46:40 +00:00
|
|
|
} else {
|
|
|
|
gCurrentObject->oPosX = x;
|
|
|
|
gCurrentObject->oPosY = y;
|
|
|
|
gCurrentObject->oPosZ = z;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-02 16:44:34 +00:00
|
|
|
* If Mario's platform is not null, apply platform displacement.
|
2019-08-25 04:46:40 +00:00
|
|
|
*/
|
|
|
|
void apply_mario_platform_displacement(void) {
|
2020-08-07 05:52:32 +00:00
|
|
|
for (int i = 0; i < MAX_PLAYERS; i++) {
|
|
|
|
struct Object* player = gMarioStates[i].marioObj;
|
|
|
|
if (player == NULL) { continue; }
|
2019-08-25 04:46:40 +00:00
|
|
|
|
2020-08-07 05:52:32 +00:00
|
|
|
struct Object *platform = player->platform;
|
|
|
|
if (!(gTimeStopState & TIME_STOP_ACTIVE) && player != NULL && platform != NULL) {
|
|
|
|
apply_platform_displacement(i, platform);
|
|
|
|
}
|
2019-09-01 19:50:50 +00:00
|
|
|
}
|
2019-08-25 04:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef VERSION_JP
|
|
|
|
/**
|
2020-06-02 16:44:34 +00:00
|
|
|
* Set Mario's platform to NULL.
|
2019-08-25 04:46:40 +00:00
|
|
|
*/
|
|
|
|
void clear_mario_platform(void) {
|
|
|
|
gMarioPlatform = NULL;
|
|
|
|
}
|
|
|
|
#endif
|