mirror of https://github.com/pmret/papermario.git
1704 lines
52 KiB
C
1704 lines
52 KiB
C
#include "common.h"
|
|
#include "ld_addrs.h"
|
|
#include "world/actions.h"
|
|
#include "sprite.h"
|
|
|
|
// TODO linker stuff
|
|
#define E20110_VRAM_DEF (void*)0x802B7000
|
|
#define E20EB0_VRAM_DEF (void*)0x802B7000
|
|
#define E21870_VRAM_DEF (void*)0x802B7000
|
|
#define E225B0_VRAM_DEF (void*)0x802B7000
|
|
|
|
extern f32 D_800F7B48;
|
|
extern s32 D_800F7B4C;
|
|
extern UNK_FUN_PTR(D_8010C93C);
|
|
extern s8 D_8015A57A;
|
|
extern s32 GoombarioGetTattleID;
|
|
|
|
s32 player_raycast_down(f32*, f32*, f32*, f32*);
|
|
s32 player_raycast_up_corner(f32* x, f32* y, f32* z, f32* length);
|
|
s32 player_raycast_general(s32, f32, f32, f32, f32, f32, f32, f32*, f32*, f32*, f32*, f32*, f32*, f32*);
|
|
void player_get_slip_vector(f32* outX, f32* outY, f32 x, f32 y, f32 nX, f32 nY);
|
|
void phys_update_standard(void);
|
|
void phys_update_lava_reset(void);
|
|
void update_player_blink(void);
|
|
void check_for_ispy(void);
|
|
void func_800E0330(void);
|
|
void check_for_pulse_stone(void);
|
|
void func_800E0374(void);
|
|
void func_800E04D0(void);
|
|
void func_800E0514(void);
|
|
void check_for_conversation_prompt(void);
|
|
void func_800E0658(void);
|
|
void func_800E069C(void);
|
|
void check_for_interactables(void);
|
|
void func_800E0AD0(void);
|
|
void func_800E0B14(void);
|
|
void update_partner_timers(void);
|
|
void func_800E0B90(void);
|
|
s32 get_player_back_anim(s32 arg0);
|
|
void appendGfx_player(void* data);
|
|
void appendGfx_player_spin(void* data);
|
|
void update_player_shadow(void);
|
|
|
|
s32 player_raycast_below(f32 yaw, f32 diameter, f32* outX, f32* outY, f32* outZ, f32* outLength, f32* hitRx, f32* hitRz,
|
|
f32* hitDirX, f32* hitDirZ) {
|
|
f32 x, y, z, length;
|
|
f32 inputX, inputY, inputZ, inputLength;
|
|
f32 cosTheta;
|
|
f32 sinTheta;
|
|
f32 temp_f20;
|
|
f32 cosTemp;
|
|
f32 sinTemp;
|
|
s32 hitObjectID;
|
|
s32 ret;
|
|
|
|
*hitRx = 0.0f;
|
|
*hitRz = 0.0f;
|
|
*hitDirX = 0.0f;
|
|
*hitDirZ = 0.0f;
|
|
inputLength = *outLength;
|
|
temp_f20 = diameter * 0.28f;
|
|
sin_cos_rad(yaw * TAU / 360.0f, &sinTheta, &cosTheta);
|
|
sinTemp = temp_f20 * sinTheta;
|
|
cosTemp = -temp_f20 * cosTheta;
|
|
inputX = *outX;
|
|
inputY = *outY;
|
|
inputZ = *outZ;
|
|
|
|
x = inputX + sinTemp;
|
|
y = inputY;
|
|
z = inputZ + cosTemp;
|
|
length = inputLength;
|
|
hitObjectID = player_raycast_down(&x, &y, &z, &length);
|
|
ret = -1;
|
|
if (hitObjectID >= 0 && length <= fabsf(*outLength)) {
|
|
*hitRx = -gGameStatusPtr->playerGroundTraceAngles.x;
|
|
*hitRz = -gGameStatusPtr->playerGroundTraceAngles.z;
|
|
*outX = x;
|
|
*outY = y;
|
|
*outZ = z;
|
|
*outLength = length;
|
|
*hitDirX = sinTemp;
|
|
*hitDirZ = cosTemp;
|
|
ret = hitObjectID;
|
|
}
|
|
|
|
x = inputX - sinTemp;
|
|
y = inputY;
|
|
z = inputZ - cosTemp;
|
|
length = inputLength;
|
|
hitObjectID = player_raycast_down(&x, &y, &z, &length);
|
|
if (hitObjectID >= 0 && length <= fabsf(*outLength)) {
|
|
*hitRx = -gGameStatusPtr->playerGroundTraceAngles.x;
|
|
*hitRz = -gGameStatusPtr->playerGroundTraceAngles.z;
|
|
*outX = x;
|
|
*outY = y;
|
|
*outZ = z;
|
|
*outLength = length;
|
|
*hitDirX = -sinTemp;
|
|
*hitDirZ = -cosTemp;
|
|
ret = hitObjectID;
|
|
}
|
|
|
|
x = inputX + cosTemp;
|
|
y = inputY;
|
|
z = inputZ + sinTemp;
|
|
length = inputLength;
|
|
hitObjectID = player_raycast_down(&x, &y, &z, &length);
|
|
if (hitObjectID >= 0 && length <= fabsf(*outLength)) {
|
|
*hitRx = -gGameStatusPtr->playerGroundTraceAngles.x;
|
|
*hitRz = -gGameStatusPtr->playerGroundTraceAngles.z;
|
|
*outX = x;
|
|
*outY = y;
|
|
*outZ = z;
|
|
*outLength = length;
|
|
*hitDirX = sinTemp;
|
|
*hitDirZ = cosTemp;
|
|
ret = hitObjectID;
|
|
}
|
|
|
|
x = inputX - cosTemp;
|
|
y = inputY;
|
|
z = inputZ - sinTemp;
|
|
length = inputLength;
|
|
hitObjectID = player_raycast_down(&x, &y, &z, &length);
|
|
if (hitObjectID >= 0 && length <= fabsf(*outLength)) {
|
|
*hitRx = -gGameStatusPtr->playerGroundTraceAngles.x;
|
|
*hitRz = -gGameStatusPtr->playerGroundTraceAngles.z;
|
|
*outX = x;
|
|
*outY = y;
|
|
*outZ = z;
|
|
*outLength = length;
|
|
*hitDirX = -sinTemp;
|
|
*hitDirZ = -cosTemp;
|
|
ret = hitObjectID;
|
|
}
|
|
|
|
x = inputX;
|
|
y = inputY;
|
|
z = inputZ;
|
|
length = inputLength;
|
|
hitObjectID = player_raycast_down(&x, &y, &z, &length);
|
|
if (hitObjectID >= 0 && length <= fabsf(*outLength)) {
|
|
*hitRx = -gGameStatusPtr->playerGroundTraceAngles.x;
|
|
*hitRz = -gGameStatusPtr->playerGroundTraceAngles.z;
|
|
*outX = x;
|
|
*outY = y;
|
|
*outZ = z;
|
|
*outLength = length;
|
|
*hitDirX = 0.0f;
|
|
*hitDirZ = 0.0f;
|
|
ret = hitObjectID;
|
|
}
|
|
|
|
if (ret < 0) {
|
|
*outX = x;
|
|
*outY = y;
|
|
*outZ = z;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
s32 player_raycast_below_cam_relative(PlayerStatus* playerStatus, f32* outX, f32* outY, f32* outZ, f32* outLength,
|
|
f32* hitRx, f32* hitRz, f32* hitDirX, f32* hitDirZ) {
|
|
f32 yaw = 0.0f;
|
|
|
|
if (playerStatus->spriteFacingAngle >= 90.0f && playerStatus->spriteFacingAngle < 270.0f) {
|
|
yaw = 180.0f;
|
|
}
|
|
|
|
return player_raycast_below(yaw - 90.0f + gCameras[gCurrentCameraID].currentYaw, playerStatus->colliderDiameter,
|
|
outX, outY, outZ, outLength, hitRx, hitRz, hitDirX, hitDirZ);
|
|
}
|
|
|
|
s32 player_raycast_down(f32* x, f32* y, f32* z, f32* length) {
|
|
f32 hitX;
|
|
f32 hitY;
|
|
f32 hitZ;
|
|
f32 hitDepth;
|
|
f32 hitNx;
|
|
f32 hitNy;
|
|
f32 hitNz;
|
|
s32 entityID, colliderID;
|
|
Entity* entity;
|
|
s32 ret = -1;
|
|
|
|
hitDepth = *length;
|
|
entityID = test_ray_entities(*x, *y, *z, 0.0f, -1.0f, 0.0f, &hitX, &hitY, &hitZ, &hitDepth, &hitNx, &hitNy, &hitNz);
|
|
if (entityID >= 0) {
|
|
entity = get_entity_by_index(entityID);
|
|
if (entity->alpha < 255) {
|
|
entity->unk_07 = 4;
|
|
entity->flags |= ENTITY_FLAGS_CONTINUOUS_COLLISION;
|
|
} else {
|
|
ret = entityID | COLLISION_WITH_ENTITY_BIT;
|
|
}
|
|
}
|
|
|
|
colliderID = test_ray_colliders(0x10000, *x, *y, *z, 0, -1.0f, 0, &hitX, &hitY, &hitZ, &hitDepth, &hitNx, &hitNy, &hitNz);
|
|
if (colliderID >= 0) {
|
|
ret = colliderID;
|
|
}
|
|
|
|
if (ret >= 0) {
|
|
*length = hitDepth;
|
|
*x = hitX;
|
|
*y = hitY;
|
|
*z = hitZ;
|
|
gGameStatusPtr->playerGroundTraceNormal.x = hitNx;
|
|
gGameStatusPtr->playerGroundTraceNormal.y = hitNy;
|
|
gGameStatusPtr->playerGroundTraceNormal.z = hitNz;
|
|
D_8010C938 = get_player_normal_yaw();
|
|
D_8010C990 = get_player_normal_pitch();
|
|
gGameStatusPtr->playerGroundTraceAngles.x = atan2(0.0f, 0.0f, hitNz * 100.0, hitNy * 100.0);
|
|
gGameStatusPtr->playerGroundTraceAngles.y = 0.0f;
|
|
gGameStatusPtr->playerGroundTraceAngles.z = atan2(0.0f, 0.0f, hitNx * 100.0, hitNy * 100.0);
|
|
} else {
|
|
gGameStatusPtr->playerGroundTraceAngles.x = 0.0f;
|
|
gGameStatusPtr->playerGroundTraceAngles.y = 0.0f;
|
|
gGameStatusPtr->playerGroundTraceAngles.z = 0.0f;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
s32 player_raycast_up_corners(PlayerStatus* player, f32* posX, f32* posY, f32* posZ, f32* hitDepth, f32 yaw) {
|
|
f32 startX;
|
|
f32 startY;
|
|
f32 startZ;
|
|
f32 depth;
|
|
f32 theta;
|
|
f32 deltaZ;
|
|
f32 deltaX;
|
|
f32 x,y,z;
|
|
s32 ret;
|
|
s32 hitID;
|
|
f32 radius;
|
|
|
|
radius = player->colliderDiameter * 0.3f;
|
|
theta = yaw * TAU / 360.0f;
|
|
deltaX = radius * sin_rad(theta);
|
|
deltaZ = -radius * cos_rad(theta);
|
|
|
|
x = *posX;
|
|
y = *posY;
|
|
z = *posZ;
|
|
|
|
depth = *hitDepth;
|
|
startX = x + deltaX;
|
|
startY = y;
|
|
startZ = z + deltaZ;
|
|
|
|
ret = -1;
|
|
hitID = player_raycast_up_corner(&startX, &startY, &startZ, &depth);
|
|
|
|
if (hitID < 0) {
|
|
startX = x - deltaX;
|
|
startY = y;
|
|
startZ = z - deltaZ;
|
|
hitID = player_raycast_up_corner(&startX, &startY, &startZ, &depth);
|
|
}
|
|
|
|
if (hitID < 0) {
|
|
startX = x + deltaZ;
|
|
startY = y;
|
|
startZ = z + deltaX;
|
|
hitID = player_raycast_up_corner(&startX, &startY, &startZ, &depth);
|
|
}
|
|
|
|
if (hitID < 0) {
|
|
startX = x - deltaZ;
|
|
startY = y;
|
|
startZ = z - deltaX;
|
|
hitID = player_raycast_up_corner(&startX, &startY, &startZ, &depth);
|
|
}
|
|
|
|
if (hitID >= 0) {
|
|
*posX = startX;
|
|
*posY = startY;
|
|
*posZ = startZ;
|
|
*hitDepth = depth;
|
|
ret = hitID;
|
|
}
|
|
|
|
if (ret < 0) {
|
|
*posX = startX;
|
|
*posY = startY;
|
|
*posZ = startZ;
|
|
*hitDepth = 0;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
s32 player_raycast_up_corner(f32* x, f32* y, f32* z, f32* length) {
|
|
f32 hitX;
|
|
f32 hitY;
|
|
f32 hitZ;
|
|
f32 hitDepth;
|
|
f32 hitNx;
|
|
f32 hitNy;
|
|
f32 hitNz;
|
|
s32 hitID;
|
|
Entity* entity;
|
|
s32 ret;
|
|
f32 sx, sy, sz;
|
|
f32 sx2, sy2, sz2;
|
|
f32 startX, startY, startZ;
|
|
|
|
ret = -1;
|
|
|
|
// needed to match
|
|
sx2 = sx = *x;
|
|
sy2 = sy = *y;
|
|
sz2 = sz = *z;
|
|
hitDepth = *length;
|
|
hitID = test_ray_colliders(0x10000, sx, sy, sz, 0.0f, 1.0f, 0.0f, &hitX, &hitY, &hitZ, &hitDepth, &hitNx, &hitNy, &hitNz);
|
|
if (hitID >= 0 && *length > hitDepth) {
|
|
*length = hitDepth;
|
|
ret = hitID;
|
|
*x = sx = sx2;
|
|
*y = sy = sy2;
|
|
*z = sz = sz2;
|
|
}
|
|
|
|
hitDepth = 10.0f;
|
|
hitID = test_ray_entities(*x, *y, *z, 0.0f, 1.0f, 0.0f, &hitX, &hitY, &hitZ, &hitDepth, &hitNx, &hitNy, &hitNz);
|
|
sx = sx2;
|
|
sy = sy2;
|
|
sz = sz2;
|
|
if (hitID >= 0 && *length > hitDepth) {
|
|
get_entity_by_index(hitID);
|
|
ret = hitID | COLLISION_WITH_ENTITY_BIT;
|
|
*length = hitDepth;
|
|
*x = sx;
|
|
*y = sy;
|
|
*z = sz;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
s32 player_test_lateral_overlap(s32 mode, PlayerStatus* playerStatus, f32* x, f32* y, f32* z, f32 length, f32 yaw) {
|
|
f32 sinTheta;
|
|
f32 cosTheta;
|
|
f32 hitX;
|
|
f32 hitY;
|
|
f32 hitZ;
|
|
f32 hitDepth;
|
|
f32 hitNx;
|
|
f32 hitNy;
|
|
f32 hitNz;
|
|
f32 slipDx;
|
|
f32 slipDz;
|
|
f32 depthDiff;
|
|
f32 radius;
|
|
f32 originalDepth;
|
|
s32 hitID;
|
|
f32 height;
|
|
f32 targetDx;
|
|
f32 targetDz;
|
|
f32 dx;
|
|
f32 dz;
|
|
s32 ret;
|
|
|
|
radius = playerStatus->colliderDiameter * 0.5f;
|
|
ret = -1;
|
|
|
|
if ((playerStatus->flags & (PLAYER_STATUS_FLAGS_FALLING | PLAYER_STATUS_FLAGS_JUMPING)) == 0) {
|
|
height = playerStatus->colliderHeight * 0.286f;
|
|
} else {
|
|
height = 1.0f;
|
|
}
|
|
|
|
sin_cos_rad(yaw * TAU / 360.0f, &sinTheta, &cosTheta);
|
|
cosTheta = -cosTheta;
|
|
hitDepth = length + radius;
|
|
hitID = player_raycast_general(mode, *x, *y + height, *z, sinTheta, 0, cosTheta, &hitX, &hitY, &hitZ, &hitDepth, &hitNx, &hitNy, &hitNz);
|
|
|
|
if (mode == 3) {
|
|
targetDx = 0.0f;
|
|
targetDz = 0.0f;
|
|
} else {
|
|
targetDx = length * sinTheta;
|
|
targetDz = length * cosTheta;
|
|
}
|
|
|
|
if (hitID >= 0) {
|
|
originalDepth = length + radius;
|
|
if (hitDepth <= originalDepth) {
|
|
depthDiff = hitDepth - originalDepth;
|
|
dx = depthDiff * sinTheta;
|
|
dz = depthDiff * cosTheta;
|
|
|
|
player_get_slip_vector(&slipDx, &slipDz, targetDx, targetDz, hitNx, hitNz);
|
|
*x += dx + slipDx;
|
|
*z += dz + slipDz;
|
|
ret = hitID;
|
|
}
|
|
}
|
|
|
|
*x += targetDx;
|
|
*z += targetDz;
|
|
return ret;
|
|
}
|
|
|
|
s32 player_raycast_general(s32 mode, f32 startX, f32 startY, f32 startZ, f32 dirX, f32 dirY, f32 dirZ, f32* hitX,
|
|
f32* hitY, f32* hitZ, f32* hitDepth, f32*hitNx, f32* hitNy, f32* hitNz) {
|
|
f32 nAngleX;
|
|
f32 nAngleZ;
|
|
s32 entityID;
|
|
s32 colliderID;
|
|
Entity* entity;
|
|
s32 ignoreFlags;
|
|
s32 ret;
|
|
|
|
entityID = test_ray_entities(startX, startY, startZ, dirX, dirY, dirZ, hitX, hitY, hitZ, hitDepth, hitNx, hitNy,
|
|
hitNz);
|
|
ret = -1;
|
|
if (entityID >= 0) {
|
|
entity = get_entity_by_index(entityID);
|
|
if (entity->alpha < 255) {
|
|
entity->unk_07 = 0;
|
|
entity->flags |= ENTITY_FLAGS_CONTINUOUS_COLLISION;
|
|
} else {
|
|
ret = entityID | COLLISION_WITH_ENTITY_BIT;
|
|
}
|
|
} else if (mode == 3) {
|
|
ret = test_ray_colliders(COLLIDER_FLAGS_IGNORE_SHELL, startX, startY, startZ, dirX, dirY, dirZ, hitX, hitY, hitZ, hitDepth,
|
|
hitNx, hitNy, hitNz);
|
|
}
|
|
|
|
if (mode == 1 || mode == 3)
|
|
return ret;
|
|
|
|
ignoreFlags = COLLIDER_FLAGS_IGNORE_PLAYER;
|
|
if (mode == 4) {
|
|
ignoreFlags = 0x80000;
|
|
}
|
|
colliderID = test_ray_colliders(ignoreFlags, startX, startY, startZ, dirX, dirY, dirZ, hitX, hitY, hitZ, hitDepth,
|
|
hitNx, hitNy, hitNz);
|
|
|
|
if (ret < 0) {
|
|
ret = colliderID;
|
|
}
|
|
|
|
if (ret >= 0) {
|
|
nAngleZ = 180.0f - atan2(0, 0, *hitNz * 100.0, *hitNy * 100.0);
|
|
nAngleX = 180.0f - atan2(0, 0, *hitNx * 100.0, *hitNy * 100.0);
|
|
|
|
if (!(nAngleZ == 90.0f && nAngleX == 90.0f || fabs(nAngleZ) >= 30.0 || fabs(nAngleX) >= 30.0)) {
|
|
ret = -1;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
s32 player_test_move_without_slipping(PlayerStatus* playerStatus, f32* x, f32* y, f32* z, f32 length, f32 yaw, s32* arg6) {
|
|
f32 sinTheta;
|
|
f32 cosTheta;
|
|
f32 hitX;
|
|
f32 hitY;
|
|
f32 hitZ;
|
|
f32 hitDepth;
|
|
f32 hitNx;
|
|
f32 hitNy;
|
|
f32 hitNz;
|
|
f32 slipDx;
|
|
f32 slipDz;
|
|
f32 depth;
|
|
f32 radius;
|
|
f32 depthDiff;
|
|
f32 height;
|
|
s32 ret;
|
|
s32 raycastID;
|
|
f32 targetDx;
|
|
f32 targetDz;
|
|
f32 dx, dz;
|
|
|
|
radius = playerStatus->colliderDiameter * 0.5f;
|
|
height = playerStatus->colliderHeight * 0.286f;
|
|
sin_cos_rad(yaw * TAU / 360.0f, &sinTheta, &cosTheta);
|
|
|
|
depth = length + radius;
|
|
cosTheta = -cosTheta;
|
|
hitDepth = depth;
|
|
dx = radius * sinTheta;
|
|
ret = -1;
|
|
|
|
raycastID = player_raycast_general(0, *x, *y + 0.1, *z, sinTheta, 0, cosTheta, &hitX, &hitY, &hitZ, &hitDepth, &hitNx, &hitNy, &hitNz);
|
|
if (raycastID >= 0 && hitDepth <= depth) {
|
|
*arg6 = 1;
|
|
}
|
|
|
|
depth = length + radius;
|
|
hitDepth = depth;
|
|
dz = radius * cosTheta;
|
|
|
|
raycastID = player_raycast_general(0, *x, *y + height, *z, sinTheta, 0, cosTheta, &hitX, &hitY, &hitZ, &hitDepth, &hitNx, &hitNy, &hitNz);
|
|
|
|
targetDx = 0.0f;
|
|
targetDz = 0.0f;
|
|
|
|
if ((raycastID >= 0) && (hitDepth <= depth)) {
|
|
depthDiff = hitDepth - depth;
|
|
dx = depthDiff * sinTheta;
|
|
dz = depthDiff * cosTheta;
|
|
player_get_slip_vector(&slipDx, &slipDz, 0.0f, 0.0f, hitNx, hitNz);
|
|
*x += dx + slipDx;
|
|
*z += dz + slipDz;
|
|
ret = raycastID;
|
|
}
|
|
*x += targetDx;
|
|
*z += targetDz;
|
|
return ret;
|
|
}
|
|
|
|
void player_get_slip_vector(f32* outX, f32* outY, f32 x, f32 y, f32 nX, f32 nY) {
|
|
f32 projectionLength = (x * nX) + (y * nY);
|
|
|
|
*outX = (x - projectionLength * nX) * 0.5f;
|
|
*outY = (y - projectionLength * nY) * 0.5f;
|
|
}
|
|
|
|
s32 player_test_move_with_slipping(PlayerStatus* playerStatus, f32* x, f32* y, f32* z, f32 length, f32 yaw) {
|
|
f32 sinTheta;
|
|
f32 cosTheta;
|
|
f32 hitX;
|
|
f32 hitY;
|
|
f32 hitZ;
|
|
f32 hitDepth;
|
|
f32 hitNx;
|
|
f32 hitNy;
|
|
f32 hitNz;
|
|
f32 slipDx;
|
|
f32 slipDz;
|
|
f32 radius;
|
|
f32 height;
|
|
s32 hitID;
|
|
f32 targetDx, targetDz;
|
|
f32 dx, dz;
|
|
f32 depthDiff;
|
|
s32 ret = -1;
|
|
|
|
height = 0.0f;
|
|
if ((playerStatus->flags & (PLAYER_STATUS_FLAGS_JUMPING | PLAYER_STATUS_FLAGS_FALLING)) == 0) {
|
|
height = 10.01f;
|
|
}
|
|
radius = playerStatus->colliderDiameter * 0.5f;
|
|
|
|
sin_cos_rad(yaw * TAU / 360.0f, &sinTheta, &cosTheta);
|
|
cosTheta = -cosTheta;
|
|
hitDepth = length + radius;
|
|
|
|
targetDx = length * sinTheta;
|
|
targetDz = length * cosTheta;
|
|
|
|
hitID = player_raycast_general(0, *x, *y + height, *z, sinTheta, 0, cosTheta, &hitX, &hitY, &hitZ, &hitDepth, &hitNx, &hitNy, &hitNz);
|
|
if (hitID >= 0 && (depthDiff = hitDepth, depthDiff <= length + radius)) {
|
|
depthDiff -= (length + radius);
|
|
dx = depthDiff * sinTheta;
|
|
dz = depthDiff * cosTheta;
|
|
player_get_slip_vector(&slipDx, &slipDz, targetDx, targetDz, hitNx, hitNz);
|
|
*x += dx + slipDx;
|
|
*z += dz + slipDz;
|
|
ret = hitID;
|
|
} else {
|
|
height = playerStatus->colliderHeight * 0.75;
|
|
hitID = player_raycast_general(0, *x, *y + height, *z, sinTheta, 0, cosTheta, &hitX, &hitY, &hitZ, &hitDepth, &hitNx, &hitNy, &hitNz);
|
|
if (hitID >= 0 && (depthDiff = hitDepth, depthDiff <= length + radius)) {
|
|
depthDiff -= (length + radius);
|
|
dx = depthDiff * sinTheta;
|
|
dz = depthDiff * cosTheta;
|
|
player_get_slip_vector(&slipDx, &slipDz, targetDx, targetDz, hitNx, hitNz);
|
|
*x += dx + slipDx;
|
|
*z += dz + slipDz;
|
|
ret = hitID;
|
|
}
|
|
}
|
|
|
|
*x += targetDx;
|
|
*z += targetDz;
|
|
return ret;
|
|
}
|
|
|
|
void update_player(void) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
CollisionStatus* collisionStatus = &gCollisionStatus;
|
|
GameStatus* gameStatus;
|
|
|
|
update_partner_timers();
|
|
|
|
if ((playerStatus->timeInAir > 100) || (playerStatus->position.y < -2000.0f)) {
|
|
if (!(playerStatus->animFlags & PLAYER_STATUS_ANIM_FLAGS_10000000)) {
|
|
playerStatus->timeInAir = 0;
|
|
playerStatus->position.x = playerStatus->lastGoodPosition.x;
|
|
playerStatus->position.y = playerStatus->lastGoodPosition.y;
|
|
playerStatus->position.z = playerStatus->lastGoodPosition.z;
|
|
|
|
if (playerStatus->animFlags & PLAYER_STATUS_ANIM_FLAGS_400000) {
|
|
Npc* partner;
|
|
|
|
playerStatus->animFlags |= PLAYER_STATUS_ANIM_FLAGS_20000000 | PLAYER_STATUS_ANIM_FLAGS_4;
|
|
partner = get_npc_unsafe(NPC_PARTNER);
|
|
partner->pos.x = playerStatus->lastGoodPosition.x;
|
|
partner->pos.y = playerStatus->lastGoodPosition.y + playerStatus->colliderHeight;
|
|
partner->pos.z = playerStatus->lastGoodPosition.z;
|
|
partner->moveToPos.y = playerStatus->lastGoodPosition.y;
|
|
} else {
|
|
playerStatus->timeInAir = 10;
|
|
}
|
|
}
|
|
}
|
|
|
|
collisionStatus->currentWall = -1;
|
|
collisionStatus->lastWallHammered = -1;
|
|
collisionStatus->currentInspect = -1;
|
|
collisionStatus->floorBelow = 1;
|
|
|
|
update_player_input();
|
|
playerStatus->flags &= ~PLAYER_STATUS_FLAGS_400;
|
|
update_player_blink();
|
|
|
|
if (playerStatus->flags & PLAYER_STATUS_ANIM_FLAGS_USING_PEACH_PHYSICS) {
|
|
phys_update_action_state();
|
|
if (!func_800E0208()) {
|
|
collision_main_lateral();
|
|
}
|
|
} else if (playerStatus->actionState != ACTION_STATE_HIT_LAVA) {
|
|
phys_update_standard();
|
|
} else {
|
|
phys_update_lava_reset();
|
|
}
|
|
|
|
if (playerStatus->flags & PLAYER_STATUS_FLAGS_4000) {
|
|
playerStatus->moveFrames--;
|
|
if (playerStatus->moveFrames <= 0) {
|
|
playerStatus->moveFrames = 0;
|
|
playerStatus->flags &= ~PLAYER_STATUS_FLAGS_4000;
|
|
}
|
|
}
|
|
|
|
if (!(playerStatus->animFlags & PLAYER_STATUS_ANIM_FLAGS_USING_PEACH_PHYSICS)) {
|
|
func_800EFD08();
|
|
}
|
|
|
|
func_800E0B90();
|
|
|
|
gameStatus = gGameStatusPtr;
|
|
gameStatus->playerPos.x = playerStatus->position.x;
|
|
gameStatus->playerPos.y = playerStatus->position.y;
|
|
gameStatus->playerPos.z = playerStatus->position.z;
|
|
gameStatus->playerYaw = playerStatus->currentYaw;
|
|
|
|
check_input_open_menus();
|
|
if (!(playerStatus->animFlags & PLAYER_STATUS_ANIM_FLAGS_USING_PEACH_PHYSICS)) {
|
|
check_input_status_menu();
|
|
}
|
|
|
|
update_player_shadow();
|
|
check_for_interactables();
|
|
check_for_conversation_prompt();
|
|
check_for_pulse_stone();
|
|
check_for_ispy();
|
|
|
|
playerStatus->extraVelocity.x = 0.0f;
|
|
playerStatus->extraVelocity.y = 0.0f;
|
|
playerStatus->extraVelocity.z = 0.0f;
|
|
playerStatus->flags &= ~PLAYER_STATUS_FLAGS_10;
|
|
playerStatus->animFlags &= ~PLAYER_STATUS_ANIM_FLAGS_8;
|
|
}
|
|
|
|
void check_input_use_partner(void) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
PlayerData* playerData = &gPlayerData;
|
|
u32 actionState = playerStatus->actionState;
|
|
|
|
if (!(playerStatus->animFlags & PLAYER_STATUS_ANIM_FLAGS_8BIT_MARIO)) {
|
|
if (playerStatus->animFlags & PLAYER_STATUS_ANIM_FLAGS_8 || playerStatus->inputEnabledCounter == 0) {
|
|
if (playerStatus->pressedButtons & BUTTON_C_DOWN && !(playerStatus->flags & PLAYER_STATUS_FLAGS_80) &&
|
|
!(playerStatus->pressedButtons & BUTTON_B) && !(playerStatus->animFlags & PLAYER_STATUS_FLAGS_1000) &&
|
|
actionState <= ACTION_STATE_RUN) {
|
|
|
|
if (playerData->currentPartner == PARTNER_GOOMBARIO) {
|
|
GoombarioGetTattleID = playerStatus->interactingWithID;
|
|
}
|
|
partner_use_ability();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void phys_update_standard(void) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
s32 flags;
|
|
|
|
check_input_use_partner();
|
|
phys_update_action_state();
|
|
|
|
if (!(playerStatus->flags & 8)) {
|
|
if (playerStatus->flags & 2) {
|
|
phys_update_jump();
|
|
}
|
|
}
|
|
|
|
if (playerStatus->flags & 4) {
|
|
if (!(playerStatus->flags & 8)) {
|
|
phys_update_falling();
|
|
}
|
|
}
|
|
|
|
check_input_midair_jump();
|
|
|
|
if (playerStatus->actionState != ACTION_STATE_SLIDING) {
|
|
collision_main_lateral();
|
|
collision_check_player_overlaps();
|
|
|
|
if (
|
|
collision_main_above() < 0 &&
|
|
playerStatus->timeInAir == 0 &&
|
|
playerStatus->animFlags & PLAYER_STATUS_ANIM_FLAGS_USING_PEACH_PHYSICS
|
|
) {
|
|
func_800E4F10();
|
|
}
|
|
|
|
if ((playerStatus->actionState != ACTION_STATE_ENEMY_FIRST_STRIKE)
|
|
&& (playerStatus->actionState != ACTION_STATE_STEP_UP)) {
|
|
phys_main_collision_below();
|
|
}
|
|
}
|
|
|
|
if (playerStatus->animFlags & 2) {
|
|
func_802BE070_31DBE0();
|
|
}
|
|
|
|
if (!(playerStatus->flags & PLAYER_STATUS_FLAGS_CAMERA_DOESNT_FOLLOW)) {
|
|
gCameras[CAM_DEFAULT].targetPos.x = playerStatus->position.x;
|
|
gCameras[CAM_DEFAULT].targetPos.y = playerStatus->position.y;
|
|
gCameras[CAM_DEFAULT].targetPos.z = playerStatus->position.z;
|
|
}
|
|
}
|
|
|
|
void phys_update_lava_reset(void) {
|
|
phys_update_action_state();
|
|
collision_main_lateral();
|
|
collision_lava_reset_check_additional_overlaps();
|
|
|
|
if (!(gPlayerStatusPtr->flags & PLAYER_STATUS_FLAGS_CAMERA_DOESNT_FOLLOW)) {
|
|
Camera* camera = &gCameras[CAM_DEFAULT];
|
|
|
|
camera->targetPos.x = gPlayerStatusPtr->position.x;
|
|
camera->targetPos.y = gPlayerStatusPtr->position.y;
|
|
camera->targetPos.z = gPlayerStatusPtr->position.z;
|
|
}
|
|
}
|
|
|
|
void clear_player_status(void) {
|
|
mem_clear(&gPlayerStatus, sizeof(gPlayerStatus));
|
|
}
|
|
|
|
void player_reset_data(void) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
|
|
mem_clear(playerStatus, sizeof(PlayerStatus));
|
|
playerStatus->flags = 1;
|
|
reset_player_status();
|
|
playerStatus->shadowID = create_shadow_type(0, playerStatus->position.x, playerStatus->position.y,
|
|
playerStatus->position.z);
|
|
func_800E6B68();
|
|
func_800E0B14();
|
|
func_800E069C();
|
|
func_800E0514();
|
|
func_800E0374();
|
|
func_800E5520();
|
|
}
|
|
|
|
s32 func_800DFCF4(void) {
|
|
if (gPartnerActionStatus.partnerActionState == PARTNER_ACTION_USE &&
|
|
(gPartnerActionStatus.actingPartner == PARTNER_WATT
|
|
|| gPartnerActionStatus.actingPartner == PARTNER_BOW
|
|
|| gPartnerActionStatus.actingPartner == PARTNER_SUSHIE
|
|
|| gPartnerActionStatus.actingPartner == PARTNER_PARAKARRY
|
|
|| gPartnerActionStatus.actingPartner == PARTNER_LAKILESTER)) {
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
s32 get_overriding_player_anim(s32 anim) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
PartnerActionStatus* partnerActionStatus = &gPartnerActionStatus;
|
|
|
|
if (playerStatus->actionState == ACTION_STATE_USE_SPINNING_FLOWER && anim != ANIM_1002B && anim != ANIM_MIDAIR_STILL) {
|
|
return -1;
|
|
}
|
|
|
|
if (partnerActionStatus->partnerActionState != PARTNER_ACTION_NONE) {
|
|
if (partnerActionStatus->actingPartner == PARTNER_LAKILESTER && anim == ANIM_10002) {
|
|
anim = ANIM_8000E;
|
|
}
|
|
|
|
if (partnerActionStatus->partnerActionState != PARTNER_ACTION_NONE && partnerActionStatus->actingPartner == PARTNER_BOW) {
|
|
if (anim != ANIM_CROUCH && anim != ANIM_10002) {
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (anim == ANIM_THUMBS_UP && partnerActionStatus->partnerActionState == PARTNER_ACTION_USE) {
|
|
return -1;
|
|
}
|
|
|
|
if (anim == ANIM_6000C || anim == ANIM_C0010 || anim == ANIM_10002) {
|
|
if (!(playerStatus->animFlags & PLAYER_STATUS_ANIM_FLAGS_USING_PEACH_PHYSICS)) {
|
|
if (!func_800DFCF4()) {
|
|
return -1;
|
|
}
|
|
} else if (!(playerStatus->animFlags & PLAYER_STATUS_ANIM_FLAGS_IN_DISGUISE)) {
|
|
anim = ANIM_C0010;
|
|
} else {
|
|
peach_set_disguise_anim(BasicPeachDisguiseAnims[playerStatus->peachDisguise].hold);
|
|
return -1;
|
|
}
|
|
} else if (playerStatus->animFlags & PLAYER_STATUS_ANIM_FLAGS_USING_PEACH_PHYSICS) {
|
|
if (playerStatus->unk_C4 && (anim == ANIM_C0000 || anim == ANIM_C0001 || anim == ANIM_C0002)) {
|
|
anim = ANIM_D0000;
|
|
}
|
|
}
|
|
|
|
if (anim == ANIM_80003) {
|
|
exec_ShakeCam1(0, 0, 2);
|
|
}
|
|
|
|
return anim;
|
|
}
|
|
|
|
void suggest_player_anim_clearUnkFlag(s32 anim) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
s32 newAnim = get_overriding_player_anim(anim);
|
|
|
|
if (newAnim != -1) {
|
|
playerStatus->anim = newAnim;
|
|
playerStatus->unk_BC = 0;
|
|
playerStatus->flags &= ~PLAYER_STATUS_FLAGS_10000000;
|
|
}
|
|
}
|
|
|
|
void force_player_anim(s32 anim) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
|
|
playerStatus->anim = anim;
|
|
playerStatus->unk_BC = 0;
|
|
playerStatus->flags &= ~PLAYER_STATUS_FLAGS_10000000;
|
|
}
|
|
|
|
void suggest_player_anim_setUnkFlag(s32 anim) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
s32 newAnim = get_overriding_player_anim(anim);
|
|
|
|
if (newAnim != -1) {
|
|
playerStatus->anim = newAnim;
|
|
playerStatus->unk_BC = 0;
|
|
playerStatus->flags |= PLAYER_STATUS_FLAGS_10000000;
|
|
}
|
|
}
|
|
|
|
void update_player_blink(void) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
s32 phi_a2 = 0;
|
|
u8 phi_v1;
|
|
u8* alpha;
|
|
|
|
if (gPartnerActionStatus.actingPartner == PARTNER_BOW) {
|
|
phi_a2 = gPartnerActionStatus.partnerActionState != PARTNER_ACTION_NONE;
|
|
}
|
|
|
|
if (playerStatus->blinkTimer > 0) {
|
|
playerStatus->blinkTimer--;
|
|
alpha = &playerStatus->alpha1;
|
|
if (!(gGameStatusPtr->frameCounter & 1)) {
|
|
if (phi_a2) {
|
|
phi_v1 = 0xC0;
|
|
} else {
|
|
phi_v1 = 0xFF;
|
|
}
|
|
} else {
|
|
phi_v1 = 0x60;
|
|
}
|
|
*alpha = phi_v1;
|
|
|
|
if (!playerStatus->blinkTimer) {
|
|
if (phi_a2) {
|
|
playerStatus->alpha1 = 0x80;
|
|
playerStatus->flags |= PLAYER_STATUS_FLAGS_8000;
|
|
} else {
|
|
playerStatus->alpha1 = 0xFF;
|
|
playerStatus->flags &= ~PLAYER_STATUS_FLAGS_8000;
|
|
}
|
|
} else {
|
|
playerStatus->flags |= PLAYER_STATUS_FLAGS_8000;
|
|
}
|
|
}
|
|
}
|
|
|
|
// dist_to_player2D
|
|
f32 get_xz_dist_to_player(f32 x, f32 z) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
|
|
return dist2D(x, z, playerStatus->position.x, playerStatus->position.z);
|
|
}
|
|
|
|
void enable_player_shadow(void) {
|
|
get_shadow_by_index(gPlayerStatus.shadowID)->flags &= ~1;
|
|
}
|
|
|
|
void disable_player_shadow(void) {
|
|
get_shadow_by_index(gPlayerStatus.shadowID)->flags |= 1;
|
|
}
|
|
|
|
s32 disable_player_static_collisions(void) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
|
|
playerStatus->flags |= PLAYER_STATUS_FLAGS_1000;
|
|
playerStatus->enableCollisionOverlapsCheck++;
|
|
return playerStatus->enableCollisionOverlapsCheck;
|
|
}
|
|
|
|
s32 enable_player_static_collisions(void) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
|
|
playerStatus->enableCollisionOverlapsCheck--;
|
|
if (playerStatus->enableCollisionOverlapsCheck == 0) {
|
|
playerStatus->flags &= ~PLAYER_STATUS_FLAGS_1000;
|
|
}
|
|
return playerStatus->enableCollisionOverlapsCheck;
|
|
}
|
|
|
|
s32 disable_player_input(void) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
|
|
playerStatus->flags |= PLAYER_STATUS_FLAGS_INPUT_DISABLED;
|
|
playerStatus->inputEnabledCounter++;
|
|
return playerStatus->inputEnabledCounter;
|
|
}
|
|
|
|
s32 enable_player_input(void) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
|
|
playerStatus->inputEnabledCounter--;
|
|
if (playerStatus->inputEnabledCounter == 0) {
|
|
playerStatus->flags &= ~PLAYER_STATUS_FLAGS_INPUT_DISABLED;
|
|
}
|
|
return playerStatus->inputEnabledCounter;
|
|
}
|
|
|
|
void func_800E01DC(void) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
|
|
if (playerStatus->animFlags & PLAYER_STATUS_ANIM_FLAGS_INTERACT_PROMPT_AVAILABLE) {
|
|
playerStatus->flags |= PLAYER_STATUS_FLAGS_8000000;
|
|
}
|
|
}
|
|
|
|
s32 func_800E0208(void) {
|
|
s32 ret = FALSE;
|
|
|
|
if (gGameStatusPtr->disableScripts &&
|
|
(gGameStatusPtr->currentButtons[0] & PLAYER_STATUS_FLAGS_10))
|
|
{
|
|
if (gPartnerActionStatus.partnerActionState == PARTNER_ACTION_NONE) {
|
|
set_action_state(ACTION_STATE_IDLE);
|
|
}
|
|
ret = TRUE;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void player_render_interact_prompts(void) {
|
|
func_800E0658();
|
|
func_800E0AD0();
|
|
func_800E04D0();
|
|
func_800E0330();
|
|
}
|
|
|
|
void check_for_ispy(void) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
|
|
if (D_8015A57A != 0 && D_8010C93C == NULL) {
|
|
if (!(playerStatus->animFlags &
|
|
(PLAYER_STATUS_ANIM_FLAGS_SPEECH_PROMPT_AVAILABLE | PLAYER_STATUS_ANIM_FLAGS_INTERACT_PROMPT_AVAILABLE))) {
|
|
dma_copy(E225B0_ROM_START, E225B0_ROM_END, E225B0_VRAM_DEF);
|
|
D_8010C93C = func_802B72C0_E22870;
|
|
}
|
|
}
|
|
|
|
if (D_8010C93C != NULL) {
|
|
D_8010C93C();
|
|
}
|
|
}
|
|
|
|
void func_800E0330(void) {
|
|
if ((gPlayerStatusPtr->animFlags & PLAYER_STATUS_ANIM_FLAGS_100) && (D_8010C93C != NULL)) {
|
|
func_802B7000_E225B0();
|
|
}
|
|
}
|
|
|
|
void func_800E0374(void) {
|
|
D_8010C93C = NULL;
|
|
gPlayerStatusPtr->animFlags &= ~PLAYER_STATUS_ANIM_FLAGS_100;
|
|
}
|
|
|
|
void check_for_pulse_stone(void) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
s32 dx, dy;
|
|
|
|
if (D_8010C920 == NULL) {
|
|
if (gPlayerStatus.animFlags & PLAYER_STATUS_ANIM_FLAGS_100) {
|
|
return;
|
|
}
|
|
|
|
if (gGameStatusPtr->areaID != AREA_SBK || gGameStatusPtr->isBattle) {
|
|
return;
|
|
}
|
|
|
|
dx = abs(gGameStatusPtr->mapID % 7 - 2);
|
|
dy = gGameStatusPtr->mapID / 7;
|
|
if ((dx + dy) > 5) {
|
|
return;
|
|
}
|
|
|
|
if (!(gPlayerStatus.animFlags & (PLAYER_STATUS_ANIM_FLAGS_USING_PULSE_STONE | PLAYER_STATUS_ANIM_FLAGS_40))) {
|
|
return;
|
|
}
|
|
|
|
if (gPlayerStatus.flags & PLAYER_STATUS_FLAGS_20 || gPlayerStatus.inputEnabledCounter) {
|
|
return;
|
|
}
|
|
|
|
if (!(gPlayerStatus.animFlags & (PLAYER_STATUS_ANIM_FLAGS_SPEECH_PROMPT_AVAILABLE | PLAYER_STATUS_ANIM_FLAGS_INTERACT_PROMPT_AVAILABLE))) {
|
|
dma_copy(E21870_ROM_START, E21870_ROM_END, E21870_VRAM_DEF);
|
|
D_8010C920 = func_802B7140;
|
|
}
|
|
}
|
|
|
|
if (D_8010C920 != NULL) {
|
|
D_8010C920();
|
|
}
|
|
}
|
|
|
|
void func_800E04D0(void) {
|
|
if ((gPlayerStatusPtr->animFlags & PLAYER_STATUS_ANIM_FLAGS_40) && (D_8010C920 != 0)) {
|
|
func_802B71D4();
|
|
}
|
|
}
|
|
|
|
void func_800E0514(void) {
|
|
D_8010C920 = 0;
|
|
gPlayerStatusPtr->animFlags &= ~PLAYER_STATUS_ANIM_FLAGS_40;
|
|
}
|
|
|
|
s32 has_valid_conversation_npc(void) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
Npc* npc = playerStatus->encounteredNPC;
|
|
s32 ret = FALSE;
|
|
s32 cond;
|
|
|
|
if (npc != NULL && !(npc->flags & 0x10000000)) {
|
|
cond = (playerStatus->flags & (PLAYER_STATUS_FLAGS_HAS_CONVERSATION_NPC | PLAYER_STATUS_FLAGS_INPUT_DISABLED))
|
|
== PLAYER_STATUS_FLAGS_HAS_CONVERSATION_NPC;
|
|
ret = cond;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void check_for_conversation_prompt(void) {
|
|
if (gPlayerStatus.animFlags & PLAYER_STATUS_ANIM_FLAGS_100 || D_8010C958 || D_8010C920) {
|
|
return;
|
|
}
|
|
|
|
if (D_8010C940 == NULL) {
|
|
if (gPlayerStatus.inputEnabledCounter || gPlayerStatus.flags & PLAYER_STATUS_FLAGS_20) {
|
|
return;
|
|
}
|
|
|
|
if (has_valid_conversation_npc()) {
|
|
D_8010C940 = NULL;
|
|
dma_copy(E20EB0_ROM_START, E20EB0_ROM_END, E20EB0_VRAM_DEF);
|
|
D_8010C940 = func_802B70B4_E201C4;
|
|
} else {
|
|
D_8010C940 = NULL;
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (D_8010C940 != NULL) {
|
|
D_8010C940();
|
|
}
|
|
}
|
|
|
|
void func_800E0658(void) {
|
|
if ((gPlayerStatusPtr->animFlags & PLAYER_STATUS_ANIM_FLAGS_SPEECH_PROMPT_AVAILABLE) && (D_8010C940 != 0)) {
|
|
func_802B71C8();
|
|
}
|
|
}
|
|
|
|
void func_800E069C(void) {
|
|
D_8010C940 = 0;
|
|
gPlayerStatusPtr->animFlags &= ~PLAYER_STATUS_ANIM_FLAGS_SPEECH_PROMPT_AVAILABLE;
|
|
}
|
|
|
|
void func_800E06C0(s32 arg0) {
|
|
D_8010C950 = (arg0 == 1);
|
|
}
|
|
|
|
s32 func_800E06D8(void) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
Npc* npc = playerStatus->encounteredNPC;
|
|
s32 temp = playerStatus->interactingWithID;
|
|
s32 wall;
|
|
|
|
if (playerStatus->timeInAir || playerStatus->inputEnabledCounter) {
|
|
return FALSE;
|
|
}
|
|
if (gCollisionStatus.currentWall == -1) {
|
|
return FALSE;
|
|
}
|
|
if (playerStatus->flags & PLAYER_STATUS_FLAGS_HAS_CONVERSATION_NPC && !(playerStatus->flags & PLAYER_STATUS_FLAGS_INPUT_DISABLED)
|
|
&& npc != NULL && npc->flags & NPC_FLAG_10000000) {
|
|
playerStatus->interactingWithID = -1;
|
|
return TRUE;
|
|
}
|
|
|
|
wall = gCollisionStatus.currentWall;
|
|
if (!(wall & COLLISION_WITH_ENTITY_BIT)) {
|
|
if (!should_collider_allow_interact(wall)) {
|
|
return FALSE;
|
|
}
|
|
} else if (!phys_can_player_interact()) {
|
|
playerStatus->interactingWithID = -1;
|
|
return FALSE;
|
|
} else if (get_entity_type(wall) == 0xC) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (temp == wall) {
|
|
if (playerStatus->flags & PLAYER_STATUS_FLAGS_8000000) {
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
playerStatus->flags &= ~PLAYER_STATUS_FLAGS_8000000;
|
|
}
|
|
playerStatus->interactingWithID = -1;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static const f32 padding = 0.0f;
|
|
|
|
void check_for_interactables(void) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
Npc* npc = gPlayerStatus.encounteredNPC;
|
|
s32 phi_s2;
|
|
|
|
if ((playerStatus->animFlags & PLAYER_STATUS_ANIM_FLAGS_100) || D_8010C940 || D_8010C920) {
|
|
return;
|
|
}
|
|
|
|
if (D_8010C958 == NULL) {
|
|
s32 curInteraction = gCollisionStatus.currentWall;
|
|
|
|
if (playerStatus->inputEnabledCounter != 0) {
|
|
if (gPlayerStatus.interactingWithID != curInteraction) {
|
|
gPlayerStatus.interactingWithID = curInteraction;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (playerStatus->timeInAir != 0) {
|
|
return;
|
|
}
|
|
|
|
if (curInteraction == -1) {
|
|
s32 floor = gCollisionStatus.currentFloor;
|
|
|
|
if ((floor >= 0) && (floor & COLLISION_WITH_ENTITY_BIT)) {
|
|
phi_s2 = 1;
|
|
curInteraction = floor;
|
|
switch (get_entity_type(floor)) {
|
|
case ENTITY_TYPE_PADLOCK:
|
|
case ENTITY_TYPE_PADLOCK_RED_FRAME:
|
|
case ENTITY_TYPE_PADLOCK_RED_FACE:
|
|
case ENTITY_TYPE_PADLOCK_BLUE_FACE:
|
|
case ENTITY_TYPE_PUSH_BLOCK:
|
|
case ENTITY_TYPE_CHEST:
|
|
case ENTITY_TYPE_SIGNPOST:
|
|
curInteraction = -1;
|
|
break;
|
|
}
|
|
} else if (((playerStatus->flags & (PLAYER_STATUS_FLAGS_HAS_CONVERSATION_NPC | PLAYER_STATUS_FLAGS_INPUT_DISABLED)) == PLAYER_STATUS_FLAGS_HAS_CONVERSATION_NPC)
|
|
&& (npc != NULL) && (npc->flags & NPC_FLAG_10000000)) {
|
|
curInteraction = npc->npcID | COLLISION_WITH_NPC_BIT;
|
|
if (playerStatus->interactingWithID == curInteraction) {
|
|
return;
|
|
}
|
|
phi_s2 = 0;
|
|
} else {
|
|
playerStatus->interactingWithID = -1;
|
|
playerStatus->flags &= ~PLAYER_STATUS_FLAGS_8000000;
|
|
return;
|
|
}
|
|
} else {
|
|
if (!(curInteraction & COLLISION_WITH_ENTITY_BIT)) {
|
|
phi_s2 = 0;
|
|
if (!(curInteraction & COLLISION_WITH_NPC_BIT)) {
|
|
if (!should_collider_allow_interact(curInteraction)) {
|
|
playerStatus->interactingWithID = -1;
|
|
playerStatus->flags &= ~PLAYER_STATUS_FLAGS_8000000;
|
|
return;
|
|
}
|
|
}
|
|
} else {
|
|
if (!phys_can_player_interact()) {
|
|
phi_s2 = 1;
|
|
playerStatus->interactingWithID = -1;
|
|
playerStatus->flags &= ~PLAYER_STATUS_FLAGS_8000000;
|
|
return;
|
|
}
|
|
phi_s2 = 1;
|
|
}
|
|
}
|
|
if (playerStatus->interactingWithID == curInteraction) {
|
|
if ((playerStatus->flags & PLAYER_STATUS_FLAGS_8000000)) {
|
|
return;
|
|
}
|
|
} else {
|
|
playerStatus->flags &= ~PLAYER_STATUS_FLAGS_8000000;
|
|
}
|
|
|
|
playerStatus->interactingWithID = curInteraction;
|
|
if ((phi_s2 == 0) || curInteraction >= 0 && get_entity_by_index(curInteraction)->flags & ENTITY_FLAGS_SHOWS_INSPECT_PROMPT) {
|
|
if (playerStatus->actionState == ACTION_STATE_IDLE || playerStatus->actionState == ACTION_STATE_WALK || playerStatus->actionState == ACTION_STATE_RUN) {
|
|
playerStatus->animFlags |= PLAYER_STATUS_ANIM_FLAGS_INTERACT_PROMPT_AVAILABLE;
|
|
func_800EF3D4(2);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!(playerStatus->animFlags & PLAYER_STATUS_ANIM_FLAGS_INTERACT_PROMPT_AVAILABLE)) {
|
|
func_800EF3D4(0);
|
|
repartner_set_tether_distance();
|
|
return;
|
|
}
|
|
|
|
if (D_8010C958 == NULL) {
|
|
dma_copy(E20110_ROM_START, E20110_ROM_END, E20110_VRAM_DEF);
|
|
D_8010C958 = func_802B70B4_E201C4;
|
|
|
|
}
|
|
|
|
if (D_8010C958 != NULL) {
|
|
D_8010C958();
|
|
}
|
|
}
|
|
|
|
void func_802B71E8_E202F8(void);
|
|
|
|
void func_800E0AD0(void) {
|
|
if ((gPlayerStatusPtr->animFlags & PLAYER_STATUS_FLAGS_10) && (D_8010C958 != 0)) {
|
|
func_802B71E8_E202F8();
|
|
}
|
|
}
|
|
|
|
void func_800E0B14(void) {
|
|
D_8010C958 = 0;
|
|
gPlayerStatusPtr->animFlags &= ~PLAYER_STATUS_FLAGS_10;
|
|
}
|
|
|
|
void update_partner_timers(void) {
|
|
PlayerData* playerData = &gPlayerData;
|
|
|
|
if (!gGameStatusPtr->isBattle) {
|
|
s32 i;
|
|
|
|
for (i = 1; i < ARRAY_COUNT(playerData->partnerUnlockedTime); i++) {
|
|
if (playerData->partners[i].enabled) {
|
|
playerData->partnerUnlockedTime[i] += 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void func_800E0B90(void) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
f32 cameraYaw = gCameras[gCurrentCameraID].currentYaw;
|
|
f32 temp_f20 = get_clamped_angle_diff(cameraYaw, playerStatus->currentYaw);
|
|
s32 trueAnim;
|
|
s32 animByte;
|
|
f32 unk_90;
|
|
s32 phi_v1;
|
|
f32 phi_f0;
|
|
|
|
D_800F7B48 = 0.0f;
|
|
if (temp_f20 < -5.0f && temp_f20 > -175.0f) {
|
|
temp_f20 = 0.0f;
|
|
phi_v1 = 0;
|
|
} else if (temp_f20 > 5.0f && temp_f20 < 175.0f) {
|
|
temp_f20 = 180.0f;
|
|
phi_v1 = 1;
|
|
} else {
|
|
temp_f20 = D_800F7B40;
|
|
phi_v1 = 2;
|
|
}
|
|
if (D_8010C95C != phi_v1 && phi_v1 != 2) {
|
|
D_8010C95C = phi_v1;
|
|
playerStatus->unk_90[gCurrentCameraID] = (phi_v1 != 0) ? 180.0f : -180.0f;
|
|
|
|
if (fabsf(get_clamped_angle_diff(cameraYaw, playerStatus->currentYaw)) >= 90.0f) {
|
|
playerStatus->unk_90[gCurrentCameraID] = -playerStatus->unk_90[gCurrentCameraID];
|
|
}
|
|
}
|
|
|
|
unk_90 = playerStatus->unk_90[gCurrentCameraID];
|
|
if (unk_90 != 0.0f) {
|
|
if (unk_90 < 0.0f) {
|
|
unk_90 += 28.0f;
|
|
if (unk_90 > 0.0f) {
|
|
unk_90 = 0.0f;
|
|
}
|
|
}
|
|
|
|
if (unk_90 > 0.0f) {
|
|
unk_90 -= 28.0f;
|
|
if (unk_90 < 0.0f) {
|
|
unk_90 = 0.0f;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (playerStatus->flags & 0x200000) {
|
|
unk_90 = 0.0f;
|
|
}
|
|
|
|
playerStatus->unk_90[gCurrentCameraID] = unk_90;
|
|
|
|
D_800F7B40 = unk_90 = clamp_angle(temp_f20);
|
|
unk_90 = clamp_angle(playerStatus->unk_90[gCurrentCameraID] + unk_90);
|
|
if (playerStatus->currentSpeed == 0.0f) {
|
|
D_800F7B48 = 0.0f;
|
|
}
|
|
|
|
trueAnim = playerStatus->anim;
|
|
if (playerStatus->flags & 0x20000) {
|
|
playerStatus->trueAnimation = trueAnim;
|
|
} else {
|
|
animByte = (trueAnim >> 0x10) & 0xFF;
|
|
|
|
if (playerStatus->actionState != 0xF && !(playerStatus->flags & 0x100000)) {
|
|
playerStatus->spriteFacingAngle = unk_90 + D_800F7B48;
|
|
trueAnim = playerStatus->anim;
|
|
if (!(playerStatus->flags & 0x10000000) &&
|
|
(animByte == 1 || animByte == 6 || animByte == 10) &&
|
|
fabsf(get_clamped_angle_diff(cameraYaw, playerStatus->currentYaw)) < 60.0f)
|
|
{
|
|
trueAnim = get_player_back_anim(trueAnim);
|
|
}
|
|
playerStatus->trueAnimation = trueAnim;
|
|
playerStatus->currentYaw = playerStatus->targetYaw;
|
|
} else {
|
|
trueAnim = playerStatus->anim;
|
|
if (!(playerStatus->flags & 0x10000000) &&
|
|
(animByte == 1 || animByte == 6 || animByte == 10) &&
|
|
playerStatus->spriteFacingAngle < 350.0f &&
|
|
playerStatus->spriteFacingAngle > 190.0f)
|
|
{
|
|
trueAnim = get_player_back_anim(trueAnim);
|
|
}
|
|
playerStatus->trueAnimation = trueAnim;
|
|
}
|
|
}
|
|
|
|
phi_f0 = 1.0f;
|
|
if (playerStatus->flags & 0x40000) {
|
|
phi_f0 = 0.5f;
|
|
}
|
|
if (playerStatus->flags & 0x20000000) {
|
|
phi_f0 = 0.0f;
|
|
}
|
|
playerStatus->unk_BC = spr_update_player_sprite(0, playerStatus->trueAnimation, phi_f0);
|
|
playerStatus->flags |= 0x40000000;
|
|
}
|
|
|
|
s32 get_player_back_anim(s32 arg0) {
|
|
s32 animByte = (arg0 >> 16) & 0xff;
|
|
s32 ret = 0;
|
|
|
|
if (animByte != 1) {
|
|
if (animByte != 6 && animByte != 10) {
|
|
return arg0;
|
|
}
|
|
|
|
if (animByte == 1) {
|
|
if (arg0 > 0x1000C) {
|
|
return arg0;
|
|
}
|
|
} else if (animByte == 6) {
|
|
if (arg0 == 0x6000C) {
|
|
ret = 0x6000D;
|
|
} else if (arg0 == 0x6000E) {
|
|
ret = 0x6000F;
|
|
} else if (arg0 == 0x60010) {
|
|
ret = 0x60011;
|
|
} else if (arg0 == 0x60012) {
|
|
ret = 0x60013;
|
|
} else if (arg0 == 0x60014) {
|
|
ret = 0x60015;
|
|
} else if (arg0 == 0x60016) {
|
|
ret = 0x60017;
|
|
} else if (arg0 == 0x60018) {
|
|
ret = 0x60019;
|
|
} else if (arg0 == 0x6001A) {
|
|
ret = 0x6001B;
|
|
}
|
|
} else if (animByte == 10) {
|
|
if (arg0 > 0xA0006) {
|
|
ret = arg0 + 1;
|
|
}
|
|
}
|
|
} else if (arg0 > 0x1000C) {
|
|
return arg0;
|
|
}
|
|
|
|
if (ret != 0) {
|
|
return ret;
|
|
} else {
|
|
return arg0 | 0x1000000;
|
|
}
|
|
|
|
}
|
|
|
|
void render_player(void) {
|
|
if (!gGameStatusPtr->disableScripts) {
|
|
render_player_model();
|
|
}
|
|
}
|
|
|
|
void render_player_model(void) {
|
|
RenderTask task;
|
|
RenderTask* rtPtr = &task;
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
s32 x, y, z;
|
|
s8 renderModeTemp;
|
|
void (*appendGfx)(void*);
|
|
|
|
if (playerStatus->flags & PLAYER_STATUS_FLAGS_40000000) {
|
|
playerStatus->flags &= ~PLAYER_STATUS_FLAGS_40000000;
|
|
get_screen_coords(gCurrentCamID, playerStatus->position.x, playerStatus->position.y,
|
|
playerStatus->position.z, &x, &y, &z);
|
|
if (!(playerStatus->flags & PLAYER_STATUS_FLAGS_20000)) {
|
|
if (playerStatus->alpha1 != playerStatus->alpha2) {
|
|
if (playerStatus->alpha1 < 254) {
|
|
if (!(playerStatus->animFlags & PLAYER_STATUS_ANIM_FLAGS_1000000)) {
|
|
renderModeTemp = RENDER_MODE_SURFACE_XLU_LAYER1;
|
|
} else {
|
|
renderModeTemp = RENDER_MODE_SURFACE_XLU_LAYER2;
|
|
}
|
|
|
|
playerStatus->renderMode = renderModeTemp;
|
|
func_802DDEE4(0, -1, 7, 0, 0, 0, playerStatus->alpha1, 0);
|
|
|
|
} else {
|
|
playerStatus->renderMode = RENDER_MODE_ALPHATEST;
|
|
func_802DDEE4(0, -1, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
}
|
|
|
|
playerStatus->alpha2 = playerStatus->alpha1;
|
|
|
|
} else {
|
|
playerStatus->renderMode = RENDER_MODE_SURFACE_XLU_LAYER1;
|
|
playerStatus->alpha2 = 0;
|
|
}
|
|
|
|
if (!(playerStatus->animFlags & PLAYER_STATUS_ANIM_FLAGS_IN_DISGUISE)) {
|
|
rtPtr->appendGfxArg = playerStatus;
|
|
rtPtr->distance = -z;
|
|
rtPtr->renderMode = playerStatus->renderMode;
|
|
|
|
|
|
if (!(playerStatus->flags & PLAYER_STATUS_ANIM_FLAGS_20000)) {
|
|
appendGfx = appendGfx_player;
|
|
} else {
|
|
appendGfx = appendGfx_player_spin;
|
|
}
|
|
|
|
rtPtr->appendGfx = appendGfx;
|
|
queue_render_task(rtPtr);
|
|
}
|
|
|
|
func_800F0C9C();
|
|
}
|
|
}
|
|
|
|
void appendGfx_player(void* data) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
Matrix4f sp20, sp60, spA0, spE0;
|
|
f32 temp_f0 = -gCameras[gCurrentCamID].currentYaw;
|
|
s32 phi_a0;
|
|
|
|
if (playerStatus->actionState == ACTION_STATE_SLIDING) {
|
|
guScaleF(spE0, SPRITE_PIXEL_SCALE, SPRITE_PIXEL_SCALE, SPRITE_PIXEL_SCALE);
|
|
guRotateF(sp20, temp_f0, 0.0f, 1.0f, 0.0f);
|
|
guMtxCatF(spE0, sp20, sp20);
|
|
guRotateF(spA0, playerStatus->spriteFacingAngle, 0.0f, 1.0f, 0.0f);
|
|
guMtxCatF(sp20, spA0, sp20);
|
|
guTranslateF(sp60, playerStatus->position.x, playerStatus->position.y - 1.0f, playerStatus->position.z);
|
|
guMtxCatF(sp20, sp60, sp20);
|
|
spr_draw_player_sprite(0, 0, 0, 0, sp20);
|
|
} else {
|
|
guRotateF(spA0, temp_f0, 0.0f, -1.0f, 0.0f);
|
|
guRotateF(sp20, clamp_angle(playerStatus->pitch), 0.0f, 0.0f, 1.0f);
|
|
guMtxCatF(spA0, sp20, sp20);
|
|
guTranslateF(sp60, 0.0f, -playerStatus->colliderHeight * 0.5f, 0.0f);
|
|
guMtxCatF(sp60, sp20, sp20);
|
|
guRotateF(spA0, temp_f0, 0.0f, 1.0f, 0.0f);
|
|
guMtxCatF(sp20, spA0, sp20);
|
|
guRotateF(spA0, playerStatus->spriteFacingAngle, 0.0f, 1.0f, 0.0f);
|
|
guMtxCatF(sp20, spA0, sp20);
|
|
guTranslateF(sp60, 0.0f, playerStatus->colliderHeight * 0.5f, 0.0f);
|
|
guMtxCatF(sp20, sp60, sp20);
|
|
guScaleF(spE0, SPRITE_PIXEL_SCALE, SPRITE_PIXEL_SCALE, SPRITE_PIXEL_SCALE);
|
|
guMtxCatF(sp20, spE0, sp20);
|
|
guTranslateF(sp60, playerStatus->position.x, playerStatus->position.y, playerStatus->position.z);
|
|
guMtxCatF(sp20, sp60, sp20);
|
|
|
|
if (playerStatus->animFlags & PLAYER_STATUS_ANIM_FLAGS_SHIVERING) {
|
|
playerStatus->animFlags = playerStatus->animFlags & ~PLAYER_STATUS_ANIM_FLAGS_SHIVERING;
|
|
playerStatus->unk_0A = 22;
|
|
func_802DDEE4(0, -1, 0, 0, 0, 0, 0, 0);
|
|
func_802DDFF8(playerStatus->anim, 5, 1, 1, 1, 0, 0);
|
|
}
|
|
|
|
if (playerStatus->unk_0A != 0) {
|
|
playerStatus->unk_0A--;
|
|
if (playerStatus->unk_0A == 0) {
|
|
func_802DDEE4(0, -1, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
}
|
|
|
|
phi_a0 = 0;
|
|
|
|
if (playerStatus->spriteFacingAngle >= 90.0f && playerStatus->spriteFacingAngle < 270.0f) {
|
|
phi_a0 = PLAYER_STATUS_ANIM_FLAGS_10000000;
|
|
}
|
|
|
|
spr_draw_player_sprite(phi_a0, 0, 0, 0, sp20);
|
|
}
|
|
|
|
D_800F7B4C++;
|
|
|
|
if (D_800F7B4C >= 3) {
|
|
D_800F7B4C = 0;
|
|
}
|
|
}
|
|
|
|
/// Only used when speedy spinning.
|
|
void appendGfx_player_spin(void* data) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
Matrix4f mtx;
|
|
Matrix4f translation;
|
|
Matrix4f rotation;
|
|
Matrix4f scale;
|
|
f32 yaw;
|
|
f32 blurAngle;
|
|
s32 tint;
|
|
f32 px, py, pz;
|
|
s32 x, y, z;
|
|
s32 i;
|
|
s32 flags;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
yaw = -gCameras[gCurrentCamID].currentYaw;
|
|
|
|
if (i == 0) {
|
|
if (playerStatus->spriteFacingAngle > 90.0f && playerStatus->spriteFacingAngle <= 180.0f) {
|
|
yaw = 180.0f - playerStatus->spriteFacingAngle;
|
|
} else {
|
|
if (playerStatus->spriteFacingAngle > 180.0f && playerStatus->spriteFacingAngle <= 270.0f) {
|
|
yaw = playerStatus->spriteFacingAngle - 180.0f;
|
|
} else if (playerStatus->spriteFacingAngle > 270.0f && playerStatus->spriteFacingAngle <= 360.0f) {
|
|
yaw = 360.0f - playerStatus->spriteFacingAngle;
|
|
} else {
|
|
yaw = playerStatus->spriteFacingAngle;
|
|
}
|
|
}
|
|
|
|
tint = yaw / 25.0f;
|
|
tint = 255 - (tint * 60);
|
|
if (tint < 100) {
|
|
tint = 100;
|
|
}
|
|
|
|
func_802DDFF8(0, 6, tint, tint, tint, 255, 0);
|
|
|
|
guRotateF(rotation, yaw, 0.0f, -1.0f, 0.0f);
|
|
guRotateF(mtx, clamp_angle(playerStatus->pitch), 0.0f, 0.0f, 1.0f);
|
|
guMtxCatF(rotation, mtx, mtx);
|
|
px = playerStatus->position.x;
|
|
py = playerStatus->position.y;
|
|
pz = playerStatus->position.z;
|
|
} else {
|
|
blurAngle = phys_get_spin_history(i, &x, &y, &z);
|
|
|
|
if (y == 0x80000000) {
|
|
py = playerStatus->position.y;
|
|
} else {
|
|
py = y;
|
|
}
|
|
|
|
px = playerStatus->position.x;
|
|
pz = playerStatus->position.z;
|
|
func_802DDEE4(0, -1, 7, 0, 0, 0, 64, 0);
|
|
guRotateF(mtx, yaw, 0.0f, -1.0f, 0.0f);
|
|
guRotateF(rotation, yaw, 0.0f, -1.0f, 0.0f);
|
|
guRotateF(mtx, blurAngle, 0.0f, 1.0f, 0.0f);
|
|
guMtxCatF(rotation, mtx, mtx);
|
|
}
|
|
|
|
guTranslateF(translation, 0.0f, -playerStatus->colliderHeight * 0.5f, 0.0f);
|
|
guMtxCatF(translation, mtx, mtx);
|
|
guRotateF(rotation, yaw, 0.0f, 1.0f, 0.0f);
|
|
guMtxCatF(mtx, rotation, mtx);
|
|
guRotateF(rotation, playerStatus->spriteFacingAngle, 0.0f, 1.0f, 0.0f);
|
|
guMtxCatF(mtx, rotation, mtx);
|
|
guTranslateF(translation, 0.0f, playerStatus->colliderHeight * 0.5f, 0.0f);
|
|
guMtxCatF(mtx, translation, mtx);
|
|
guScaleF(scale, SPRITE_PIXEL_SCALE, SPRITE_PIXEL_SCALE, SPRITE_PIXEL_SCALE);
|
|
guMtxCatF(mtx, scale, mtx);
|
|
guTranslateF(translation, px, py, pz);
|
|
guMtxCatF(mtx, translation, mtx);
|
|
|
|
if (playerStatus->spriteFacingAngle >= 90.0f && playerStatus->spriteFacingAngle < 270.0f) {
|
|
flags = 0x10000000;
|
|
} else {
|
|
flags = 0;
|
|
}
|
|
|
|
spr_draw_player_sprite(flags, 0, 0, 0, mtx);
|
|
}
|
|
}
|
|
|
|
void update_player_shadow(void) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
Shadow* shadow = get_shadow_by_index(gPlayerStatusPtr->shadowID);
|
|
Camera* camera = &gCameras[gCurrentCameraID];
|
|
f32 shadowScale = 0.0f;
|
|
f32 yawTemp = 0.0f;
|
|
f32 hitDirX, hitDirZ;
|
|
f32 hitRx, hitRz;
|
|
f32 x, y, z;
|
|
f32 playerX, playerZ;
|
|
s32 dist;
|
|
f32 raycastYaw;
|
|
|
|
if (playerStatus->spriteFacingAngle >= 90.0f && playerStatus->spriteFacingAngle < 270.0f) {
|
|
yawTemp = 180.0f;
|
|
}
|
|
|
|
raycastYaw = (yawTemp - 90.0f) + gCameras[gCurrentCameraID].currentYaw;
|
|
shadow->position.x = playerX = playerStatus->position.x;
|
|
shadow->position.z = playerZ = playerStatus->position.z;
|
|
x = playerX;
|
|
y = playerStatus->position.y + (playerStatus->colliderHeight / 3.5f);
|
|
z = playerZ;
|
|
shadowScale = 1024.0f;
|
|
gCollisionStatus.floorBelow = player_raycast_below(raycastYaw, playerStatus->colliderDiameter, &x, &y, &z,
|
|
&shadowScale, &hitRx, &hitRz, &hitDirX, &hitDirZ);
|
|
shadow->rotation.x = hitRx;
|
|
shadow->rotation.z = hitRz;
|
|
shadow->rotation.y = clamp_angle(-camera->currentYaw);
|
|
hitRx += 180.0f;
|
|
hitRz += 180.0f;
|
|
|
|
if (hitRx != 0.0f || hitRz != 0.0f) {
|
|
s32 dist = dist2D(x, z, playerStatus->position.x, playerStatus->position.z);
|
|
f32 tan = atan2(playerStatus->position.x, playerStatus->position.z, x, z);
|
|
s32 angleTemp = clamp_angle((-90.0f - tan) + get_player_normal_yaw());
|
|
|
|
if (gGameStatusPtr->playerGroundTraceNormal.y != 0.0f) {
|
|
y -= sqrtf(SQ(gGameStatusPtr->playerGroundTraceNormal.x) + SQ(gGameStatusPtr->playerGroundTraceNormal.z)) /
|
|
gGameStatusPtr->playerGroundTraceNormal.y * dist * sin_deg(angleTemp);
|
|
}
|
|
}
|
|
|
|
shadow->position.y = y;
|
|
shadow->alpha = (f64)playerStatus->alpha1 / 2;
|
|
|
|
if (!(gGameStatusPtr->peachFlags & 1)) {
|
|
set_standard_shadow_scale(shadow, shadowScale);
|
|
} else {
|
|
set_peach_shadow_scale(shadow, shadowScale);
|
|
}
|
|
}
|