Add OBJ_FLAG_VELOCITY_PLATFORM for velocity-based platform displacement for certain objects like the TTC treadmills

This commit is contained in:
Arceveti
2021-09-09 12:09:13 -07:00
parent caab929608
commit b80529d0e9
3 changed files with 95 additions and 93 deletions

View File

@@ -115,7 +115,7 @@
// Often used to end behavior scripts that do not contain an infinite loop.
#define BREAK() \
BC_B(0x0A)
// Exits the behavior script, unused.
#define BREAK_UNUSED() \
BC_B(0x0B)
@@ -176,15 +176,15 @@
#define ADD_INT_RAND_RSHIFT(field, min, rshift) \
BC_BBH(0x17, field, min), \
BC_H(rshift)
// No operation. Unused.
#define CMD_NOP_1(field) \
BC_BB(0x18, field)
// No operation. Unused.
#define CMD_NOP_2(field) \
BC_BB(0x19, field)
// No operation. Unused.
#define CMD_NOP_3(field) \
BC_BB(0x1A, field)
@@ -5473,7 +5473,11 @@ const BehaviorScript bhvTTCPendulum[] = {
const BehaviorScript bhvTTCTreadmill[] = {
BEGIN(OBJ_LIST_SURFACE),
#ifdef PLATFORM_DISPLACEMENT_2
OR_INT(oFlags, (OBJ_FLAG_COMPUTE_DIST_TO_MARIO | OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE | OBJ_FLAG_VELOCITY_PLATFORM)),
#else
OR_INT(oFlags, (OBJ_FLAG_COMPUTE_DIST_TO_MARIO | OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE)),
#endif
SET_FLOAT(oCollisionDistance, 750),
CALL_NATIVE(bhv_ttc_treadmill_init),
DELAY(1),

View File

@@ -43,10 +43,8 @@
#define OBJ_FLAG_1000 (1 << 12) // 0x00001000
#define OBJ_FLAG_COMPUTE_ANGLE_TO_MARIO (1 << 13) // 0x00002000
#define OBJ_FLAG_PERSISTENT_RESPAWN (1 << 14) // 0x00004000
#define OBJ_FLAG_8000 (1 << 15) // 0x00008000
#ifdef AUTO_COLLISION_DISTANCE
#define OBJ_FLAG_VELOCITY_PLATFORM (1 << 15) // 0x00008000
#define OBJ_FLAG_DONT_CALC_COLL_DIST (1 << 16) // 0x00010000
#endif
#define OBJ_FLAG_EMIT_LIGHT (1 << 17) // 0x00020000
#define OBJ_FLAG_HITBOX_WAS_SET (1 << 30) // 0x40000000

View File

@@ -97,15 +97,15 @@ extern s32 gGlobalTimer;
* Upscale or downscale a vector by another vector.
*/
static void scale_vec3f(Vec3f dst, Vec3f src, Vec3f scale, u32 doInverted) {
if (doInverted) {
dst[0] = src[0] / scale[0];
dst[1] = src[1] / scale[1];
dst[2] = src[2] / scale[2];
} else {
dst[0] = src[0] * scale[0];
dst[1] = src[1] * scale[1];
dst[2] = src[2] * scale[2];
}
if (doInverted) {
dst[0] = src[0] / scale[0];
dst[1] = src[1] / scale[1];
dst[2] = src[2] / scale[2];
} else {
dst[0] = src[0] * scale[0];
dst[1] = src[1] * scale[1];
dst[2] = src[2] * scale[2];
}
}
/**
@@ -113,74 +113,74 @@ static void scale_vec3f(Vec3f dst, Vec3f src, Vec3f scale, u32 doInverted) {
* platform.
*/
void apply_platform_displacement(struct PlatformDisplacementInfo *displaceInfo, Vec3f pos, s16 *yaw, struct Object *platform) {
Vec3f platformPos;
Vec3f posDifference;
Vec3f yawVec;
Vec3f scaledPos;
// Determine how much Mario turned on his own since last frame
s16 yawDifference = *yaw - displaceInfo->prevYaw;
Vec3f platformPos;
Vec3f posDifference;
Vec3f yawVec;
Vec3f scaledPos;
// Determine how much Mario turned on his own since last frame
s16 yawDifference = *yaw - displaceInfo->prevYaw;
// Avoid a crash if the platform unloaded its collision while stood on
if (platform->header.gfx.throwMatrix == NULL) return;
// Avoid a crash if the platform unloaded its collision while stood on
if (platform->header.gfx.throwMatrix == NULL) return;
vec3f_copy(platformPos, (*platform->header.gfx.throwMatrix)[3]);
vec3f_copy(platformPos, (*platform->header.gfx.throwMatrix)[3]);
// Determine how far Mario moved on his own since last frame
vec3f_copy(posDifference, pos);
vec3f_sub(posDifference, displaceInfo->prevPos);
// Determine how far Mario moved on his own since last frame
vec3f_copy(posDifference, pos);
vec3f_sub(posDifference, displaceInfo->prevPos);
if ((platform == displaceInfo->prevPlatform) && (gGlobalTimer == displaceInfo->prevTimer + 1)) {
// Transform from relative positions to world positions
scale_vec3f(scaledPos, displaceInfo->prevTransformedPos, platform->header.gfx.scale, FALSE);
linear_mtxf_mul_vec3f(*platform->header.gfx.throwMatrix, pos, scaledPos);
if ((platform == displaceInfo->prevPlatform) && (gGlobalTimer == displaceInfo->prevTimer + 1)) {
// Transform from relative positions to world positions
scale_vec3f(scaledPos, displaceInfo->prevTransformedPos, platform->header.gfx.scale, FALSE);
linear_mtxf_mul_vec3f(*platform->header.gfx.throwMatrix, pos, scaledPos);
// Add on how much Mario moved in the previous frame
vec3f_add(pos, posDifference);
// Add on how much Mario moved in the previous frame
vec3f_add(pos, posDifference);
// Calculate new yaw
linear_mtxf_mul_vec3f(*platform->header.gfx.throwMatrix, yawVec, displaceInfo->prevTransformedYawVec);
*yaw = atan2s(yawVec[2], yawVec[0]) + yawDifference;
} else {
// First frame of standing on the platform, don't calculate a new position
vec3f_sub(pos, platformPos);
}
// Calculate new yaw
linear_mtxf_mul_vec3f(*platform->header.gfx.throwMatrix, yawVec, displaceInfo->prevTransformedYawVec);
*yaw = atan2s(yawVec[2], yawVec[0]) + yawDifference;
} else {
// First frame of standing on the platform, don't calculate a new position
vec3f_sub(pos, platformPos);
}
// Apply displacement specifically for TTC Treadmills
if (platform->behavior == segmented_to_virtual(bhvTTCTreadmill)) {
// Apply velocity-based displacement for certain objects (like the TTC Treadmills)
if (platform->oFlags & OBJ_FLAG_VELOCITY_PLATFORM) {
pos[0] += platform->oVelX;
pos[1] += platform->oVelY;
pos[2] += platform->oVelZ;
}
// Transform from world positions to relative positions for use next frame
linear_mtxf_transpose_mul_vec3f(*platform->header.gfx.throwMatrix, scaledPos, pos);
scale_vec3f(displaceInfo->prevTransformedPos, scaledPos, platform->header.gfx.scale, TRUE);
vec3f_add(pos, platformPos);
// If the object is Mario, set inertia
if (pos == gMarioState->pos) {
vec3f_copy(sMarioAmountDisplaced, pos);
vec3f_sub(sMarioAmountDisplaced, displaceInfo->prevPos);
vec3f_sub(sMarioAmountDisplaced, posDifference);
// Transform from world positions to relative positions for use next frame
linear_mtxf_transpose_mul_vec3f(*platform->header.gfx.throwMatrix, scaledPos, pos);
scale_vec3f(displaceInfo->prevTransformedPos, scaledPos, platform->header.gfx.scale, TRUE);
vec3f_add(pos, platformPos);
// Make sure inertia isn't set on the first frame otherwise the previous value isn't cleared
if ((platform != displaceInfo->prevPlatform) || (gGlobalTimer != displaceInfo->prevTimer + 1)) {
vec3f_set(sMarioAmountDisplaced, 0.f, 0.f, 0.f);
}
}
// If the object is Mario, set inertia
if (pos == gMarioState->pos) {
vec3f_copy(sMarioAmountDisplaced, pos);
vec3f_sub(sMarioAmountDisplaced, displaceInfo->prevPos);
vec3f_sub(sMarioAmountDisplaced, posDifference);
// Update info for next frame
// Update position
vec3f_copy(displaceInfo->prevPos, pos);
// Make sure inertia isn't set on the first frame otherwise the previous value isn't cleared
if ((platform != displaceInfo->prevPlatform) || (gGlobalTimer != displaceInfo->prevTimer + 1)) {
vec3f_set(sMarioAmountDisplaced, 0.f, 0.f, 0.f);
}
}
// Set yaw info
vec3f_set(yawVec, sins(*yaw), 0, coss(*yaw));
linear_mtxf_transpose_mul_vec3f(*platform->header.gfx.throwMatrix, displaceInfo->prevTransformedYawVec, yawVec);
displaceInfo->prevYaw = *yaw;
// Update info for next frame
// Update position
vec3f_copy(displaceInfo->prevPos, pos);
// Update platform and timer
displaceInfo->prevPlatform = platform;
displaceInfo->prevTimer = gGlobalTimer;
// Set yaw info
vec3f_set(yawVec, sins(*yaw), 0, coss(*yaw));
linear_mtxf_transpose_mul_vec3f(*platform->header.gfx.throwMatrix, displaceInfo->prevTransformedYawVec, yawVec);
displaceInfo->prevYaw = *yaw;
// Update platform and timer
displaceInfo->prevPlatform = platform;
displaceInfo->prevTimer = gGlobalTimer;
}
// Doesn't change in the code, set this to FALSE if you don't want inertia
@@ -193,23 +193,23 @@ static u8 sInertiaFirstFrame = FALSE;
* Apply inertia based on Mario's last platform.
*/
static void apply_mario_inertia(void) {
// On the first frame of leaving the ground, boost Mario's y velocity
if (sInertiaFirstFrame) {
gMarioState->vel[1] += sMarioAmountDisplaced[1];
}
// On the first frame of leaving the ground, boost Mario's y velocity
if (sInertiaFirstFrame) {
gMarioState->vel[1] += sMarioAmountDisplaced[1];
}
// Apply sideways inertia
gMarioState->pos[0] += sMarioAmountDisplaced[0];
gMarioState->pos[2] += sMarioAmountDisplaced[2];
// Apply sideways inertia
gMarioState->pos[0] += sMarioAmountDisplaced[0];
gMarioState->pos[2] += sMarioAmountDisplaced[2];
// Drag
sMarioAmountDisplaced[0] *= 0.97f;
sMarioAmountDisplaced[2] *= 0.97f;
// Drag
sMarioAmountDisplaced[0] *= 0.97f;
sMarioAmountDisplaced[2] *= 0.97f;
// Stop applying inertia once Mario has landed, or when ground pounding
if (!(gMarioState->action & ACT_FLAG_AIR) || (gMarioState->action == ACT_GROUND_POUND)) {
sShouldApplyInertia = FALSE;
}
// Stop applying inertia once Mario has landed, or when ground pounding
if (!(gMarioState->action & ACT_FLAG_AIR) || (gMarioState->action == ACT_GROUND_POUND)) {
sShouldApplyInertia = FALSE;
}
}
/**
@@ -220,14 +220,14 @@ void apply_mario_platform_displacement(void) {
platform = gMarioPlatform;
if (!(gTimeStopState & TIME_STOP_ACTIVE) && gMarioObject != NULL) {
if (platform != NULL) {
apply_platform_displacement(&sMarioDisplacementInfo, gMarioState->pos, &gMarioState->faceAngle[1], platform);
sShouldApplyInertia = TRUE;
sInertiaFirstFrame = TRUE;
} else if (sShouldApplyInertia && gDoInertia) {
apply_mario_inertia();
sInertiaFirstFrame = FALSE;
}
if (platform != NULL) {
apply_platform_displacement(&sMarioDisplacementInfo, gMarioState->pos, &gMarioState->faceAngle[1], platform);
sShouldApplyInertia = TRUE;
sInertiaFirstFrame = TRUE;
} else if (sShouldApplyInertia && gDoInertia) {
apply_mario_inertia();
sInertiaFirstFrame = FALSE;
}
}
}
#else
@@ -271,9 +271,9 @@ void apply_platform_displacement(u32 isMario, struct Object *platform) {
unused1 = rotation[0];
unused2 = rotation[2];
unused3 = platform->oFaceAngleYaw;
if (isMario) {
gMarioStates[0].faceAngle[1] += rotation[1];
}
if (isMario) {
gMarioStates[0].faceAngle[1] += rotation[1];
}
platformPosX = platform->oPosX;
platformPosY = platform->oPosY;
platformPosZ = platform->oPosZ;