From ff43340b0bd7c28f7a9cb952d804bdc0952ed83b Mon Sep 17 00:00:00 2001 From: Arceveti <73617174+Arceveti@users.noreply.github.com> Date: Thu, 30 Sep 2021 15:09:01 -0700 Subject: [PATCH] Configurable number of segments for Chain Chomp, Pokey, and Wiggler --- include/config.h | 8 ++ include/object_constants.h | 2 +- src/game/behaviors/chain_chomp.inc.c | 126 ++++++++------------------- src/game/behaviors/pokey.inc.c | 38 ++++---- src/game/behaviors/wiggler.inc.c | 80 +++++++---------- src/game/object_helpers.c | 9 +- src/game/object_helpers.h | 8 +- 7 files changed, 95 insertions(+), 176 deletions(-) diff --git a/include/config.h b/include/config.h index 99adb2e6..93afe862 100644 --- a/include/config.h +++ b/include/config.h @@ -123,6 +123,14 @@ // -- SPECIFIC OBJECT SETTINGS -- // Allow for retries on collecting the remaining blue coins from a blue coin switch #define BLUE_COIN_SWITCH_RETRY +// The number of chain balls the Chain Chomp has. Vanilla is 5. +#define CHAIN_CHOMP_NUM_SEGMENTS 5 + +// The number of parts Pokey has, including the head. Vanilla is 5, max is 30. +#define POKEY_NUM_SEGMENTS 5 + +// The number of segments Wiggler has, not including the head. Vanilla is 4. +#define WIGGLER_NUM_SEGMENTS 4 // -- CUTSCENE SKIPS -- // Skip peach letter cutscene diff --git a/include/object_constants.h b/include/object_constants.h index 8bfe26dc..a80e5981 100644 --- a/include/object_constants.h +++ b/include/object_constants.h @@ -1282,7 +1282,7 @@ /* Pokey Body Part */ /* oBehParams2ndByte */ #define POKEY_PART_BP_HEAD 0x0 - #define POKEY_PART_BP_LOWEST POKEY_NUM_PARTS-0x1 + #define POKEY_PART_BP_LOWEST (POKEY_NUM_SEGMENTS - 0x1) /* Swoop */ /* oAction */ diff --git a/src/game/behaviors/chain_chomp.inc.c b/src/game/behaviors/chain_chomp.inc.c index 609ec508..48468d78 100644 --- a/src/game/behaviors/chain_chomp.inc.c +++ b/src/game/behaviors/chain_chomp.inc.c @@ -32,11 +32,8 @@ void bhv_chain_chomp_chain_part_update(void) { obj_mark_for_deletion(o); } else if (o->oBehParams2ndByte != CHAIN_CHOMP_CHAIN_PART_BP_PIVOT) { struct ChainSegment *segment = &o->parentObj->oChainChompSegments[o->oBehParams2ndByte]; - // Set position relative to the pivot - o->oPosX = o->parentObj->parentObj->oPosX + segment->posX; - o->oPosY = o->parentObj->parentObj->oPosY + segment->posY; - o->oPosZ = o->parentObj->parentObj->oPosZ + segment->posZ; + vec3_sum(&o->oPosVec, &o->parentObj->parentObj->oPosVec, segment->pos); } else if (o->parentObj->oChainChompReleaseStatus != CHAIN_CHOMP_NOT_RELEASED) { cur_obj_update_floor_and_walls(); cur_obj_move_standard(78); @@ -51,14 +48,14 @@ static void chain_chomp_act_uninitialized(void) { s32 i; if (o->oDistanceToMario < 3000.0f) { - segments = mem_pool_alloc(gObjectMemoryPool, 5 * sizeof(struct ChainSegment)); + segments = mem_pool_alloc(gObjectMemoryPool, CHAIN_CHOMP_NUM_SEGMENTS * sizeof(struct ChainSegment)); if (segments != NULL) { // Each segment represents the offset of a chain part to the pivot. // Segment 0 connects the pivot to the chain chomp itself. Segment // 1 connects the pivot to the chain part next to the chain chomp // (chain part 1), etc. o->oChainChompSegments = segments; - for (i = 0; i <= 4; i++) { + for (i = 0; i < CHAIN_CHOMP_NUM_SEGMENTS; i++) { chain_segment_init(&segments[i]); } @@ -70,7 +67,7 @@ static void chain_chomp_act_uninitialized(void) { != NULL) { // Spawn the non-pivot chain parts, starting from the chain // chomp and moving toward the pivot - for (i = 1; i <= 4; i++) { + for (i = 1; i < CHAIN_CHOMP_NUM_SEGMENTS; i++) { spawn_object_relative(i, 0, 0, 0, o, MODEL_METALLIC_BALL, bhvChainChompChainPart); } @@ -86,69 +83,31 @@ static void chain_chomp_act_uninitialized(void) { * part as well as from the pivot. */ static void chain_chomp_update_chain_segments(void) { - struct ChainSegment *prevSegment; - struct ChainSegment *segment; - f32 offsetX; - f32 offsetY; - f32 offsetZ; - f32 offset; - f32 segmentVelY; - f32 maxTotalOffset; - s32 i; - - if (o->oVelY < 0.0f) { - segmentVelY = o->oVelY; - } else { - segmentVelY = -20.0f; - } - // Segment 0 connects the pivot to the chain chomp itself, and segment i>0 // connects the pivot to chain part i (1 is closest to the chain chomp). - - for (i = 1; i <= 4; i++) { - prevSegment = &o->oChainChompSegments[i - 1]; - segment = &o->oChainChompSegments[i]; + s32 i; + for (i = 1; i < CHAIN_CHOMP_NUM_SEGMENTS; i++) { + struct ChainSegment *prevSegment = &o->oChainChompSegments[i - 1]; + struct ChainSegment *segment = &o->oChainChompSegments[i]; // Apply gravity - - if ((segment->posY += segmentVelY) < 0.0f) { - segment->posY = 0.0f; + f32 segmentVelY = ((o->oVelY < 0.0f) ? o->oVelY : -20.0f); + segment->pos[1] += segmentVelY; + if (segment->pos[1] < 0.0f) { + segment->pos[1] = 0.0f; } - // Cap distance to previous chain part (so that the tail follows the - // chomp) + // Cap distance to previous chain part (so that the tail follows the chomp) + Vec3f offset; + vec3_diff(offset, segment->pos, prevSegment->pos); + vec3_normalize_max(offset, o->oChainChompMaxDistBetweenChainParts); - offsetX = segment->posX - prevSegment->posX; - offsetY = segment->posY - prevSegment->posY; - offsetZ = segment->posZ - prevSegment->posZ; - offset = sqrtf(offsetX * offsetX + offsetY * offsetY + offsetZ * offsetZ); + // Cap distance to pivot (so that it stretches when the chomp moves far from the wooden post) + vec3_add(offset, prevSegment->pos); + f32 maxTotalDist = o->oChainChompMaxDistFromPivotPerChainPart * (CHAIN_CHOMP_NUM_SEGMENTS - i); + vec3_normalize_max(offset, maxTotalDist); - if (offset > o->oChainChompMaxDistBetweenChainParts) { - offset = o->oChainChompMaxDistBetweenChainParts / offset; - offsetX *= offset; - offsetY *= offset; - offsetZ *= offset; - } - - // Cap distance to pivot (so that it stretches when the chomp moves far - // from the wooden post) - - offsetX += prevSegment->posX; - offsetY += prevSegment->posY; - offsetZ += prevSegment->posZ; - offset = sqrtf(offsetX * offsetX + offsetY * offsetY + offsetZ * offsetZ); - - maxTotalOffset = o->oChainChompMaxDistFromPivotPerChainPart * (5 - i); - if (offset > maxTotalOffset) { - offset = maxTotalOffset / offset; - offsetX *= offset; - offsetY *= offset; - offsetZ *= offset; - } - - segment->posX = offsetX; - segment->posY = offsetY; - segment->posZ = offsetZ; + vec3_copy(segment->pos, offset); } } @@ -157,7 +116,8 @@ static void chain_chomp_update_chain_segments(void) { * distance between chain parts. Restore these values to normal. */ static void chain_chomp_restore_normal_chain_lengths(void) { - approach_f32_ptr(&o->oChainChompMaxDistFromPivotPerChainPart, 750.0f / 5, 4.0f); + // approach_f32_ptr(&o->oChainChompMaxDistFromPivotPerChainPart, 750.0f / CHAIN_CHOMP_NUM_SEGMENTS, 4.0f); + approach_f32_ptr(&o->oChainChompMaxDistFromPivotPerChainPart, 150.0f, 4.0f); o->oChainChompMaxDistBetweenChainParts = o->oChainChompMaxDistFromPivotPerChainPart; } @@ -182,8 +142,8 @@ static void chain_chomp_sub_act_turn(void) { cur_obj_play_sound_2(SOUND_GENERAL_CHAIN_CHOMP2); o->oSubAction = CHAIN_CHOMP_SUB_ACT_LUNGE; - o->oChainChompMaxDistFromPivotPerChainPart = 900.0f / 5; - + // o->oChainChompMaxDistFromPivotPerChainPart = 900.0f / CHAIN_CHOMP_NUM_SEGMENTS; + o->oChainChompMaxDistFromPivotPerChainPart = 180.0f; o->oForwardVel = 140.0f; o->oVelY = 20.0f; o->oGravity = 0.0f; @@ -227,8 +187,7 @@ static void chain_chomp_sub_act_lunge(void) { o->oTimer = 0; } else { // Turn toward pivot - cur_obj_rotate_yaw_toward(atan2s(o->oChainChompSegments[0].posZ, o->oChainChompSegments[0].posX), - 0x1000); + cur_obj_rotate_yaw_toward(atan2s(o->oChainChompSegments[0].pos[2], o->oChainChompSegments[0].pos[0]), 0x1000); if (o->oChainChompSignedMaxDistBetweenChainParts != 0.0f) { approach_f32_ptr(&o->oChainChompSignedMaxDistBetweenChainParts, 0.0f, 0.8f); @@ -392,40 +351,27 @@ static void chain_chomp_act_move(void) { cur_obj_move_standard(78); // Segment 0 connects the pivot to the chain chomp itself - o->oChainChompSegments[0].posX = o->oPosX - o->parentObj->oPosX; - o->oChainChompSegments[0].posY = o->oPosY - o->parentObj->oPosY; - o->oChainChompSegments[0].posZ = o->oPosZ - o->parentObj->oPosZ; + vec3_diff(o->oChainChompSegments[0].pos, &o->oPosVec, &o->parentObj->oPosVec); - o->oChainChompDistToPivot = - sqrtf(o->oChainChompSegments[0].posX * o->oChainChompSegments[0].posX - + o->oChainChompSegments[0].posY * o->oChainChompSegments[0].posY - + o->oChainChompSegments[0].posZ * o->oChainChompSegments[0].posZ); + o->oChainChompDistToPivot = vec3_mag(o->oChainChompSegments[0].pos); // If the chain is fully stretched - maxDistToPivot = o->oChainChompMaxDistFromPivotPerChainPart * 5; + maxDistToPivot = o->oChainChompMaxDistFromPivotPerChainPart * CHAIN_CHOMP_NUM_SEGMENTS; if (o->oChainChompDistToPivot > maxDistToPivot) { f32 ratio = maxDistToPivot / o->oChainChompDistToPivot; o->oChainChompDistToPivot = maxDistToPivot; - o->oChainChompSegments[0].posX *= ratio; - o->oChainChompSegments[0].posY *= ratio; - o->oChainChompSegments[0].posZ *= ratio; + vec3_mul_val(o->oChainChompSegments[0].pos, ratio); if (o->oChainChompReleaseStatus == CHAIN_CHOMP_NOT_RELEASED) { // Restrict chain chomp position - o->oPosX = o->parentObj->oPosX + o->oChainChompSegments[0].posX; - o->oPosY = o->parentObj->oPosY + o->oChainChompSegments[0].posY; - o->oPosZ = o->parentObj->oPosZ + o->oChainChompSegments[0].posZ; - + vec3_sum(&o->oPosVec, &o->parentObj->oPosVec, o->oChainChompSegments[0].pos); o->oChainChompRestrictedByChain = TRUE; } else { // Move pivot like the chain chomp is pulling it along f32 oldPivotY = o->parentObj->oPosY; - - o->parentObj->oPosX = o->oPosX - o->oChainChompSegments[0].posX; - o->parentObj->oPosY = o->oPosY - o->oChainChompSegments[0].posY; + vec3_diff(&o->parentObj->oPosVec, &o->oPosVec, o->oChainChompSegments[0].pos); o->parentObj->oVelY = o->parentObj->oPosY - oldPivotY; - o->parentObj->oPosZ = o->oPosZ - o->oChainChompSegments[0].posZ; } } else { o->oChainChompRestrictedByChain = FALSE; @@ -436,7 +382,8 @@ static void chain_chomp_act_move(void) { // Begin a lunge if mario tries to attack if (obj_check_attacks(&sChainChompHitbox, o->oAction)) { o->oSubAction = CHAIN_CHOMP_SUB_ACT_LUNGE; - o->oChainChompMaxDistFromPivotPerChainPart = 900.0f / 5; + // o->oChainChompMaxDistFromPivotPerChainPart = 900.0f / CHAIN_CHOMP_NUM_SEGMENTS; + o->oChainChompMaxDistFromPivotPerChainPart = 180.0f; // ((CHAIN_CHOMP_NUM_SEGMENTS * 180.0f) / CHAIN_CHOMP_NUM_SEGMENTS); o->oForwardVel = 0.0f; o->oVelY = 300.0f; o->oGravity = -4.0f; @@ -491,8 +438,7 @@ void bhv_wooden_post_update(void) { // Stay still until mario is done ground pounding o->oWoodenPostMarioPounding = cur_obj_is_mario_ground_pounding_platform(); } else if ((o->oWoodenPostOffsetY += o->oWoodenPostSpeedY) < -190.0f) { - // Once pounded, if this is the chain chomp's post, release the chain - // chomp + // Once pounded, if this is the chain chomp's post, release the chain chomp o->oWoodenPostOffsetY = -190.0f; if (o->parentObj != o) { play_puzzle_jingle(); @@ -512,7 +458,7 @@ void bhv_wooden_post_update(void) { o->oWoodenPostTotalMarioAngle += (s16)(o->oAngleToMario - o->oWoodenPostPrevAngleToMario); if (ABSI(o->oWoodenPostTotalMarioAngle) > 0x30000 && o->oTimer < 200) { obj_spawn_loot_yellow_coins(o, 5, 20.0f); - set_object_respawn_info_bits(o, 1); + set_object_respawn_info_bits(o, RESPAWN_INFO_TYPE_32); } } diff --git a/src/game/behaviors/pokey.inc.c b/src/game/behaviors/pokey.inc.c index fc29ff56..346beea6 100644 --- a/src/game/behaviors/pokey.inc.c +++ b/src/game/behaviors/pokey.inc.c @@ -36,15 +36,12 @@ static u8 sPokeyBodyPartAttackHandlers[] = { /** * Update function for pokey body part. - * The behavior parameter is the body part's index from 0 to 4, with 0 at the - * top. + * The behavior parameter is the body part's index from POKEY_PART_BP_HEAD to POKEY_PART_BP_LOWEST, + * with POKEY_PART_BP_HEAD at the top. */ void bhv_pokey_body_part_update(void) { // PARTIAL_UPDATE - s16 offsetAngle; - f32 baseHeight; - if (obj_update_standard_actions(3.0f)) { if (o->parentObj->oAction == POKEY_ACT_UNLOAD_PARTS) { obj_mark_for_deletion(o); @@ -79,12 +76,12 @@ void bhv_pokey_body_part_update(void) { } //! Pausing causes jumps in offset angle - offsetAngle = o->oBehParams2ndByte * 0x4000 + gGlobalTimer * 0x800; + s16 offsetAngle = o->oBehParams2ndByte * 0x4000 + gGlobalTimer * 0x800; o->oPosX = o->parentObj->oPosX + coss(offsetAngle) * 6.0f; o->oPosZ = o->parentObj->oPosZ + sins(offsetAngle) * 6.0f; // This is the height of the tower beneath the body part - baseHeight = o->parentObj->oPosY + f32 baseHeight = o->parentObj->oPosY + (120 * (o->parentObj->oPokeyNumAliveBodyParts - o->oBehParams2ndByte) - 240) + 120.0f * o->parentObj->oPokeyBottomBodyPartSize; @@ -96,18 +93,14 @@ void bhv_pokey_body_part_update(void) { } // Only the head has loot coins - if (o->oBehParams2ndByte == 0) { - o->oNumLootCoins = 1; - } else { - o->oNumLootCoins = 0; - } + o->oNumLootCoins = (o->oBehParams2ndByte == POKEY_PART_BP_HEAD); // If the body part was attacked, then die. If the head was killed, // then die after a delay. if (obj_handle_attacks(&sPokeyBodyPartHitbox, o->oAction, sPokeyBodyPartAttackHandlers)) { o->parentObj->oPokeyNumAliveBodyParts--; - if (o->oBehParams2ndByte == 0) { + if (o->oBehParams2ndByte == POKEY_PART_BP_HEAD) { o->parentObj->oPokeyHeadWasKilled = TRUE; // Last minute change to blue coins - not sure why they didn't // just set it to -1 above @@ -140,20 +133,19 @@ void bhv_pokey_body_part_update(void) { } /** - * When mario gets within range, spawn the 5 body parts and enter the wander - * action. + * When mario gets within range, spawn the POKEY_NUM_SEGMENTS body parts and enter the wander action. */ static void pokey_act_uninitialized(void) { struct Object *bodyPart; s32 i; s16 partModel; - if (o->oDistanceToMario < 2000.0f) { + if (o->oDistanceToMario < 4000.0f) { partModel = MODEL_POKEY_HEAD; - for (i = 0; i < 5; i++) { + for (i = 0; i < POKEY_NUM_SEGMENTS; i++) { // Spawn body parts at y offsets 480, 360, 240, 120, 0 - // behavior param 0 = head, 4 = lowest body part + // behavior param POKEY_PART_BP_HEAD = head, POKEY_PART_BP_LOWEST = lowest body part bodyPart = spawn_object_relative(i, 0, -i * 120 + 480, 0, o, partModel, bhvPokeyBodyPart); if (bodyPart != NULL) { @@ -163,8 +155,8 @@ static void pokey_act_uninitialized(void) { partModel = MODEL_POKEY_BODY_PART; } - o->oPokeyAliveBodyPartFlags = 0x1F; - o->oPokeyNumAliveBodyParts = 5; + o->oPokeyAliveBodyPartFlags = BITMASK(POKEY_NUM_SEGMENTS); + o->oPokeyNumAliveBodyParts = POKEY_NUM_SEGMENTS; o->oPokeyBottomBodyPartSize = 1.0f; o->oAction = POKEY_ACT_WANDER; } @@ -180,9 +172,9 @@ static void pokey_act_wander(void) { s32 targetAngleOffset; struct Object *bodyPart; - if (o->oPokeyNumAliveBodyParts == 0) { + if (o->oPokeyNumAliveBodyParts == POKEY_PART_BP_HEAD) { obj_mark_for_deletion(o); - } else if (o->oDistanceToMario > 2500.0f) { + } else if (o->oDistanceToMario > 4500.0f) { o->oAction = POKEY_ACT_UNLOAD_PARTS; o->oForwardVel = 0.0f; } else { @@ -195,7 +187,7 @@ static void pokey_act_wander(void) { o->oForwardVel = 5.0f; // If a body part is missing, replenish it after 100 frames - if (o->oPokeyNumAliveBodyParts < 5) { + if (o->oPokeyNumAliveBodyParts < POKEY_NUM_SEGMENTS) { if (o->oTimer > 100) { // Because the body parts shift index whenever a body part // is killed, the new part's index is equal to the number diff --git a/src/game/behaviors/wiggler.inc.c b/src/game/behaviors/wiggler.inc.c index 410297ec..98e7d2d0 100644 --- a/src/game/behaviors/wiggler.inc.c +++ b/src/game/behaviors/wiggler.inc.c @@ -62,28 +62,23 @@ static f32 sWigglerSpeeds[] = { 2.0f, 40.0f, 30.0f, 16.0f }; * attack. */ void bhv_wiggler_body_part_update(void) { - f32 dx; - f32 dy; - f32 dz; + Vec3f d; f32 dxz; struct ChainSegment *segment = &o->parentObj->oWigglerSegments[o->oBehParams2ndByte]; f32 posOffset; cur_obj_scale(o->parentObj->header.gfx.scale[0]); - o->oFaceAnglePitch = segment->pitch; - o->oFaceAngleYaw = segment->yaw; + o->oFaceAnglePitch = segment->angle[0]; + o->oFaceAngleYaw = segment->angle[1]; // TODO: What is this for? posOffset = -37.5f * o->header.gfx.scale[0]; - dy = posOffset * coss(o->oFaceAnglePitch) - posOffset; + d[1] = posOffset * coss(o->oFaceAnglePitch) - posOffset; dxz = posOffset * sins(o->oFaceAnglePitch); - dx = dxz * sins(o->oFaceAngleYaw); - dz = dxz * coss(o->oFaceAngleYaw); - - o->oPosX = segment->posX + dx; - o->oPosY = segment->posY + dy; - o->oPosZ = segment->posZ + dz; + d[0] = dxz * sins(o->oFaceAngleYaw); + d[2] = dxz * coss(o->oFaceAngleYaw); + vec3_sum(&o->oPosVec, segment->pos, d); if (o->oPosY < o->parentObj->oWigglerFallThroughFloorsHeight) { //! Since position is recomputed each frame, tilting the wiggler up @@ -91,13 +86,12 @@ void bhv_wiggler_body_part_update(void) { // the floor o->oPosY += -30.0f; cur_obj_update_floor_height(); - if (o->oFloorHeight > o->oPosY) // TODO: Check ineq swap - { + if (o->oFloorHeight > o->oPosY) { // TODO: Check ineq swap o->oPosY = o->oFloorHeight; } } - segment->posY = o->oPosY; + segment->pos[1] = o->oPosY; // Inherit walking animation speed from wiggler cur_obj_init_animation_with_accel_and_sound(0, o->parentObj->oWigglerWalkAnimSpeed); @@ -120,27 +114,23 @@ void wiggler_init_segments(void) { struct ChainSegment *segments; struct Object *bodyPart; - segments = mem_pool_alloc(gObjectMemoryPool, 4 * sizeof(struct ChainSegment)); + segments = mem_pool_alloc(gObjectMemoryPool, WIGGLER_NUM_SEGMENTS * sizeof(struct ChainSegment)); if (segments != NULL) { // Each segment represents the global position and orientation of each // object. Segment 0 represents the wiggler's head, and segment i>0 // represents body part i. o->oWigglerSegments = segments; - for (i = 0; i <= 3; i++) { + for (i = 0; i < WIGGLER_NUM_SEGMENTS; i++) { chain_segment_init(segments + i); - - (segments + i)->posX = o->oPosX; - (segments + i)->posY = o->oPosY; - (segments + i)->posZ = o->oPosZ; - - (segments + i)->pitch = o->oFaceAnglePitch; - (segments + i)->yaw = o->oFaceAngleYaw; + vec3_copy((segments + i)->pos, &o->oPosVec); + (segments + i)->angle[0] = o->oFaceAnglePitch; + (segments + i)->angle[1] = o->oFaceAngleYaw; } o->header.gfx.animInfo.animFrame = -1; // Spawn each body part - for (i = 1; i <= 3; i++) { + for (i = 1; i < WIGGLER_NUM_SEGMENTS; i++) { bodyPart = spawn_object_relative(i, 0, 0, 0, o, MODEL_WIGGLER_BODY, bhvWigglerBody); if (bodyPart != NULL) { @@ -166,9 +156,7 @@ void wiggler_init_segments(void) { void wiggler_update_segments(void) { struct ChainSegment *prevBodyPart; struct ChainSegment *bodyPart; - f32 dx; - f32 dy; - f32 dz; + Vec3f d; s16 dpitch; s16 dyaw; f32 dxz; @@ -177,33 +165,31 @@ void wiggler_init_segments(void) { segmentLength = 35.0f * o->header.gfx.scale[0]; - for (i = 1; i <= 3; i++) { + for (i = 1; i < WIGGLER_NUM_SEGMENTS; i++) { prevBodyPart = &o->oWigglerSegments[i - 1]; bodyPart = &o->oWigglerSegments[i]; - dx = bodyPart->posX - prevBodyPart->posX; - dy = bodyPart->posY - prevBodyPart->posY; - dz = bodyPart->posZ - prevBodyPart->posZ; + vec3_diff(d, bodyPart->pos, prevBodyPart->pos); // As the head turns, propagate this rotation backward if the difference // is more than 45 degrees - dyaw = atan2s(-dz, -dx) - prevBodyPart->yaw; + dyaw = atan2s(-d[2], -d[0]) - prevBodyPart->angle[1]; clamp_s16(&dyaw, -0x2000, 0x2000); - bodyPart->yaw = prevBodyPart->yaw + dyaw; + bodyPart->angle[1] = prevBodyPart->angle[1] + dyaw; // As the head tilts, propagate the tilt backward - dxz = sqrtf(sqr(dx) + sqr(dz)); - dpitch = atan2s(dxz, dy) - prevBodyPart->pitch; + dxz = sqrtf(sqr(d[0]) + sqr(d[2])); + dpitch = atan2s(dxz, d[1]) - prevBodyPart->angle[0]; clamp_s16(&dpitch, -0x2000, 0x2000); - bodyPart->pitch = prevBodyPart->pitch + dpitch; + bodyPart->angle[0] = prevBodyPart->angle[0] + dpitch; // Set the body part's position relative to the previous body part's // position, using the current body part's angles. This means that the // head can rotate up to 45 degrees without the body moving - bodyPart->posY = segmentLength * sins(bodyPart->pitch) + prevBodyPart->posY; - dxz = segmentLength * coss(bodyPart->pitch); - bodyPart->posX = prevBodyPart->posX - dxz * sins(bodyPart->yaw); - bodyPart->posZ = prevBodyPart->posZ - dxz * coss(bodyPart->yaw); + bodyPart->pos[1] = segmentLength * sins(bodyPart->angle[0]) + prevBodyPart->pos[1]; + dxz = segmentLength * coss(bodyPart->angle[0]); + bodyPart->pos[0] = prevBodyPart->pos[0] - dxz * sins(bodyPart->angle[1]); + bodyPart->pos[2] = prevBodyPart->pos[2] - dxz * coss(bodyPart->angle[1]); } } @@ -213,8 +199,6 @@ void wiggler_init_segments(void) { * If attacked by mario, enter either the jumped on or knockback action. */ static void wiggler_act_walk(void) { - s16 yawTurnSpeed; - o->oWigglerWalkAnimSpeed = 0.06f * o->oForwardVel; // Update text if necessary @@ -260,7 +244,7 @@ static void wiggler_act_walk(void) { // If moving at high speeds, could overflow. But can't reach such speeds // in practice - yawTurnSpeed = (s16)(30.0f * o->oForwardVel); + s16 yawTurnSpeed = (s16)(30.0f * o->oForwardVel); cur_obj_rotate_yaw_toward(o->oWigglerTargetYaw, yawTurnSpeed); obj_face_yaw_approach(o->oMoveAngleYaw, 2 * yawTurnSpeed); @@ -437,11 +421,9 @@ void bhv_wiggler_update(void) { } // Update segment 0 with data from the wiggler object - o->oWigglerSegments[0].posX = o->oPosX; - o->oWigglerSegments[0].posY = o->oPosY; - o->oWigglerSegments[0].posZ = o->oPosZ; - o->oWigglerSegments[0].pitch = o->oFaceAnglePitch; - o->oWigglerSegments[0].yaw = o->oFaceAngleYaw; + vec3_copy(o->oWigglerSegments[0].pos, &o->oPosVec); + o->oWigglerSegments[0].angle[0] = o->oFaceAnglePitch; + o->oWigglerSegments[0].angle[1] = o->oFaceAngleYaw; // Update the rest of the segments to follow segment 0 wiggler_update_segments(); diff --git a/src/game/object_helpers.c b/src/game/object_helpers.c index e1d9040d..78b046c5 100644 --- a/src/game/object_helpers.c +++ b/src/game/object_helpers.c @@ -1717,13 +1717,8 @@ s32 cur_obj_follow_path(UNUSED s32 unusedArg) { } void chain_segment_init(struct ChainSegment *segment) { - segment->posX = 0.0f; - segment->posY = 0.0f; - segment->posZ = 0.0f; - - segment->pitch = 0; - segment->yaw = 0; - segment->roll = 0; + vec3_zero(segment->pos); + vec3_zero(segment->angle); } f32 random_f32_around_zero(f32 diameter) { diff --git a/src/game/object_helpers.h b/src/game/object_helpers.h index ca2a42c4..b1fc1ea3 100644 --- a/src/game/object_helpers.h +++ b/src/game/object_helpers.h @@ -9,12 +9,8 @@ // used for chain chomp and wiggler struct ChainSegment { - f32 posX; - f32 posY; - f32 posZ; - s16 pitch; - s16 yaw; - s16 roll; + Vec3f pos; + Vec3s angle; }; #define WATER_DROPLET_FLAG_RAND_ANGLE (1 << 1) // 0x02