platform_displacement.c (5111B)
1 #include <PR/ultratypes.h> 2 3 #include "engine/math_util.h" 4 #include "engine/surface_collision.h" 5 #include "level_update.h" 6 #include "object_fields.h" 7 #include "object_helpers.h" 8 #include "object_list_processor.h" 9 #include "platform_displacement.h" 10 #include "types.h" 11 12 u16 D_8032FEC0 = 0; 13 14 u32 unused_8032FEC4[4] = { 0 }; 15 16 struct Object *gMarioPlatform = NULL; 17 18 /** 19 * Determine if Mario is standing on a platform object, meaning that he is 20 * within 4 units of the floor. Set his referenced platform object accordingly. 21 */ 22 void update_mario_platform(void) { 23 struct Surface *floor; 24 UNUSED u8 filler[4]; 25 f32 marioX; 26 f32 marioY; 27 f32 marioZ; 28 f32 floorHeight; 29 u32 awayFromFloor; 30 31 if (gMarioObject == NULL) { 32 return; 33 } 34 35 //! If Mario moves onto a rotating platform in a PU, the find_floor call 36 // will detect the platform and he will end up receiving a large amount 37 // of displacement since he is considered to be far from the platform's 38 // axis of rotation. 39 40 marioX = gMarioObject->oPosX; 41 marioY = gMarioObject->oPosY; 42 marioZ = gMarioObject->oPosZ; 43 floorHeight = find_floor(marioX, marioY, marioZ, &floor); 44 45 if (absf(marioY - floorHeight) < 4.0f) { 46 awayFromFloor = 0; 47 } else { 48 awayFromFloor = 1; 49 } 50 51 switch (awayFromFloor) { 52 case 1: 53 gMarioPlatform = NULL; 54 gMarioObject->platform = NULL; 55 break; 56 57 case 0: 58 if (floor != NULL && floor->object != NULL) { 59 gMarioPlatform = floor->object; 60 gMarioObject->platform = floor->object; 61 } else { 62 gMarioPlatform = NULL; 63 gMarioObject->platform = NULL; 64 } 65 break; 66 } 67 } 68 69 /** 70 * Get Mario's position and store it in x, y, and z. 71 */ 72 void get_mario_pos(f32 *x, f32 *y, f32 *z) { 73 *x = gMarioStates[0].pos[0]; 74 *y = gMarioStates[0].pos[1]; 75 *z = gMarioStates[0].pos[2]; 76 } 77 78 /** 79 * Set Mario's position. 80 */ 81 void set_mario_pos(f32 x, f32 y, f32 z) { 82 gMarioStates[0].pos[0] = x; 83 gMarioStates[0].pos[1] = y; 84 gMarioStates[0].pos[2] = z; 85 } 86 87 /** 88 * Apply one frame of platform rotation to Mario or an object using the given 89 * platform. If isMario is false, use gCurrentObject. 90 */ 91 void apply_platform_displacement(u32 isMario, struct Object *platform) { 92 f32 x; 93 f32 y; 94 f32 z; 95 f32 platformPosX; 96 f32 platformPosY; 97 f32 platformPosZ; 98 Vec3f currentObjectOffset; 99 Vec3f relativeOffset; 100 Vec3f newObjectOffset; 101 Vec3s rotation; 102 UNUSED s16 unusedPitch; 103 UNUSED s16 unusedRoll; 104 UNUSED s16 unusedYaw; 105 f32 displaceMatrix[4][4]; 106 107 rotation[0] = platform->oAngleVelPitch; 108 rotation[1] = platform->oAngleVelYaw; 109 rotation[2] = platform->oAngleVelRoll; 110 111 if (isMario) { 112 D_8032FEC0 = 0; 113 get_mario_pos(&x, &y, &z); 114 } else { 115 x = gCurrentObject->oPosX; 116 y = gCurrentObject->oPosY; 117 z = gCurrentObject->oPosZ; 118 } 119 120 x += platform->oVelX; 121 z += platform->oVelZ; 122 123 if (rotation[0] != 0 || rotation[1] != 0 || rotation[2] != 0) { 124 unusedPitch = rotation[0]; 125 unusedRoll = rotation[2]; 126 unusedYaw = platform->oFaceAngleYaw; 127 128 if (isMario) { 129 gMarioStates[0].faceAngle[1] += rotation[1]; 130 } 131 132 platformPosX = platform->oPosX; 133 platformPosY = platform->oPosY; 134 platformPosZ = platform->oPosZ; 135 136 currentObjectOffset[0] = x - platformPosX; 137 currentObjectOffset[1] = y - platformPosY; 138 currentObjectOffset[2] = z - platformPosZ; 139 140 rotation[0] = platform->oFaceAnglePitch - platform->oAngleVelPitch; 141 rotation[1] = platform->oFaceAngleYaw - platform->oAngleVelYaw; 142 rotation[2] = platform->oFaceAngleRoll - platform->oAngleVelRoll; 143 144 mtxf_rotate_zxy_and_translate(displaceMatrix, currentObjectOffset, rotation); 145 linear_mtxf_transpose_mul_vec3f(displaceMatrix, relativeOffset, currentObjectOffset); 146 147 rotation[0] = platform->oFaceAnglePitch; 148 rotation[1] = platform->oFaceAngleYaw; 149 rotation[2] = platform->oFaceAngleRoll; 150 151 mtxf_rotate_zxy_and_translate(displaceMatrix, currentObjectOffset, rotation); 152 linear_mtxf_mul_vec3f(displaceMatrix, newObjectOffset, relativeOffset); 153 154 x = platformPosX + newObjectOffset[0]; 155 y = platformPosY + newObjectOffset[1]; 156 z = platformPosZ + newObjectOffset[2]; 157 } 158 159 if (isMario) { 160 set_mario_pos(x, y, z); 161 } else { 162 gCurrentObject->oPosX = x; 163 gCurrentObject->oPosY = y; 164 gCurrentObject->oPosZ = z; 165 } 166 } 167 168 /** 169 * If Mario's platform is not null, apply platform displacement. 170 */ 171 void apply_mario_platform_displacement(void) { 172 struct Object *platform = gMarioPlatform; 173 174 if (!(gTimeStopState & TIME_STOP_ACTIVE) && gMarioObject != NULL && platform != NULL) { 175 apply_platform_displacement(TRUE, platform); 176 } 177 } 178 179 #ifndef VERSION_JP 180 /** 181 * Set Mario's platform to NULL. 182 */ 183 void clear_mario_platform(void) { 184 gMarioPlatform = NULL; 185 } 186 #endif