You've already forked Microtransactions64
mirror of
https://github.com/Print-and-Panic/Microtransactions64.git
synced 2026-01-21 10:17:19 -08:00
Configurable number of segments for Chain Chomp, Pokey, and Wiggler
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user