Path: blob/master/src/game/behaviors/bowser_puzzle_piece.inc.c
7861 views
/**1* Behavior for the sliding Bowser puzzle in Lethal Lava Land.2*/34/*5* The pieces move in this order:6*7* 1, 2, 5, 6, 10, 9, 13, 12, 8, 7, 3, 48*9* Once they reach the end of the routine they follow it backwards until the10* puzzle is complete again.11*12* Note that pieces 11 and 14 do not move.13*/14static s8 sPieceActions01[] = { 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,152, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, -1 };16static s8 sPieceActions02[] = { 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,172, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, -1 };18static s8 sPieceActions05[] = { 2, 2, 2, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,192, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, -1 };20static s8 sPieceActions06[] = { 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2,212, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, -1 };22static s8 sPieceActions10[] = { 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 2, 2, 2, 2,232, 2, 2, 2, 2, 2, 6, 2, 2, 2, 2, 2, -1 };24static s8 sPieceActions09[] = { 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2,252, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, -1 };26static s8 sPieceActions13[] = { 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 2, 2,272, 2, 2, 2, 6, 2, 2, 2, 2, 2, 2, 2, -1 };28static s8 sPieceActions12[] = { 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2,292, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, -1 };30static s8 sPieceActions08[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 2,312, 2, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1 };32static s8 sPieceActions07[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2,332, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1 };34static s8 sPieceActions03[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2,355, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1 };36static s8 sPieceActions04[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4,372, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1 };38static s8 sPieceActions11[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,392, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1 };40static s8 sPieceActions14[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,412, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1 };4243struct BowserPuzzlePiece {44u8 model;45s8 xOffset;46s8 zOffset;47s8 initialAction;48s8 *actionList;49};5051/*52* The puzzle pieces are initially laid out in the following manner:53*54* +---+---+---+55* | 1 | 2 | * |56* +---+---+---+---+57* | 3 | 4 | 5 | 6 |58* +---+---+---+---+59* | 7 | 8 | 9 |10 |60* +---+---+---+---+61* |11 |12 |13 |14 |62* +---+---+---+---+63*64* (* = star platform)65*/66static struct BowserPuzzlePiece sBowserPuzzlePieces[] = {67{ MODEL_LLL_BOWSER_PIECE_1, -5, -15, 1, sPieceActions01 },68{ MODEL_LLL_BOWSER_PIECE_2, 5, -15, 0, sPieceActions02 },69{ MODEL_LLL_BOWSER_PIECE_3, -15, -5, 0, sPieceActions03 },70{ MODEL_LLL_BOWSER_PIECE_4, -5, -5, 0, sPieceActions04 },71{ MODEL_LLL_BOWSER_PIECE_5, 5, -5, 0, sPieceActions05 },72{ MODEL_LLL_BOWSER_PIECE_6, 15, -5, 0, sPieceActions06 },73{ MODEL_LLL_BOWSER_PIECE_7, -15, 5, 0, sPieceActions07 },74{ MODEL_LLL_BOWSER_PIECE_8, -5, 5, 0, sPieceActions08 },75{ MODEL_LLL_BOWSER_PIECE_9, 5, 5, 0, sPieceActions09 },76{ MODEL_LLL_BOWSER_PIECE_10, 15, 5, 0, sPieceActions10 },77{ MODEL_LLL_BOWSER_PIECE_11, -15, 15, 0, sPieceActions11 },78{ MODEL_LLL_BOWSER_PIECE_12, -5, 15, 0, sPieceActions12 },79{ MODEL_LLL_BOWSER_PIECE_13, 5, 15, 0, sPieceActions13 },80{ MODEL_LLL_BOWSER_PIECE_14, 15, 15, 0, sPieceActions14 }81};8283/**84* Spawn a single puzzle piece.85*/86void bhv_lll_bowser_puzzle_spawn_piece(s16 model, const BehaviorScript *behavior,87f32 xOffset, f32 zOffset,88s8 initialAction, s8 *actionList) {89struct Object *puzzlePiece = spawn_object(o, model, behavior);90puzzlePiece->oPosX += xOffset;91puzzlePiece->oPosY += 50.0f;92puzzlePiece->oPosZ += zOffset;93puzzlePiece->oAction = initialAction; // This action never gets executed.94puzzlePiece->oBowserPuzzlePieceActionList = actionList;95puzzlePiece->oBowserPuzzlePieceNextAction = actionList;96}9798/**99* Spawn the 14 puzzle pieces.100*/101void bhv_lll_bowser_puzzle_spawn_pieces(f32 pieceWidth) {102s32 i;103104// Spawn all 14 puzzle pieces.105for (i = 0; i < 14; i++)106bhv_lll_bowser_puzzle_spawn_piece(sBowserPuzzlePieces[i].model, bhvLllBowserPuzzlePiece,107sBowserPuzzlePieces[i].xOffset * pieceWidth / 10.0f,108sBowserPuzzlePieces[i].zOffset * pieceWidth / 10.0f,109sBowserPuzzlePieces[i].initialAction,110sBowserPuzzlePieces[i].actionList);111112// The pieces should only be spawned once so go to the next action.113o->oAction++;114}115116/*117* Does the initial spawn of the puzzle pieces and then waits to spawn 5 coins.118*/119void bhv_lll_bowser_puzzle_loop(void) {120s32 i;121UNUSED struct Object *sp28;122switch (o->oAction) {123case BOWSER_PUZZLE_ACT_SPAWN_PIECES:124bhv_lll_bowser_puzzle_spawn_pieces(480.0f);125break;126case BOWSER_PUZZLE_ACT_WAIT_FOR_COMPLETE:127// If both completion flags are set and Mario is within 1000 units...128if (o->oBowserPuzzleCompletionFlags == 3 && o->oDistanceToMario < 1000.0f) {129// Spawn 5 coins.130for (i = 0; i < 5; i++)131sp28 = spawn_object(o, MODEL_YELLOW_COIN, bhvSingleCoinGetsSpawned);132133// Reset completion flags (even though they never get checked again).134o->oBowserPuzzleCompletionFlags = 0;135136// Go to next action so we don't spawn 5 coins ever again.137o->oAction++;138}139break;140case BOWSER_PUZZLE_ACT_DONE:141break;142}143}144145/*146* Action 0 is never executed since it is not defined in any action lists.147*/148void bhv_lll_bowser_puzzle_piece_action_0(void) {149}150151/*152* Action 1 is never executed since it is not defined in any action lists.153*/154void bhv_lll_bowser_puzzle_piece_action_1(void) {155o->oPosY += 50.0f;156o->oAction = 3;157}158159/*160* Update the puzzle piece.161*/162void bhv_lll_bowser_puzzle_piece_update(void) {163s8 *nextAction = o->oBowserPuzzlePieceNextAction;164165// If Mario is standing on this puzzle piece, set a flag in the parent.166if (gMarioObject->platform == o)167o->parentObj->oBowserPuzzleCompletionFlags = 1;168169// If we should advance to the next action...170if (o->oBowserPuzzlePieceContinuePerformingAction == 0) {171// Start doing the next action.172cur_obj_change_action(*nextAction);173174// Advance the pointer to the next action.175nextAction++;176o->oBowserPuzzlePieceNextAction = nextAction;177178// If we're at the end of the list...179if (*nextAction == -1) {180// Set the other completion flag in the parent.181o->parentObj->oBowserPuzzleCompletionFlags |= 2;182183// The next action is the first action in the list again.184o->oBowserPuzzlePieceNextAction = o->oBowserPuzzlePieceActionList;185}186187// Keep doing this action until it's complete.188o->oBowserPuzzlePieceContinuePerformingAction = 1;189}190}191192void bhv_lll_bowser_puzzle_piece_move(f32 xOffset, f32 zOffset, s32 duration, UNUSED s32 a3) {193// For the first 20 frames, shake the puzzle piece up and down.194if (o->oTimer < 20) {195if (o->oTimer % 2)196o->oBowserPuzzlePieceOffsetY = 0.0f;197else198o->oBowserPuzzlePieceOffsetY = -6.0f;199} else {200// On frame 20, play the shifting sound.201if (o->oTimer == 20)202cur_obj_play_sound_2(SOUND_OBJ2_BOWSER_PUZZLE_PIECE_MOVE);203204// For the number of frames specified by duration, move the piece.205if (o->oTimer < duration + 20) {206o->oBowserPuzzlePieceOffsetX += xOffset;207o->oBowserPuzzlePieceOffsetZ += zOffset;208} else {209// This doesn't actually accomplish anything since210// cur_obj_change_action is going to be called before the211// next action is performed anyway.212o->oAction = 2;213214// Advance to the next action.215o->oBowserPuzzlePieceContinuePerformingAction = 0;216}217}218}219220void bhv_lll_bowser_puzzle_piece_idle(void) {221UNUSED s32 sp4;222223// For the first 24 frames, do nothing.224if (o->oTimer < 24)225sp4 = 0;226else227// Then advance to the next action.228o->oBowserPuzzlePieceContinuePerformingAction = 0;229}230231void bhv_lll_bowser_puzzle_piece_move_left(void) {232bhv_lll_bowser_puzzle_piece_move(-120.0f, 0.0f, 4, 4);233}234235void bhv_lll_bowser_puzzle_piece_move_right(void) {236bhv_lll_bowser_puzzle_piece_move(120.0f, 0.0f, 4, 5);237}238239void bhv_lll_bowser_puzzle_piece_move_up(void) {240bhv_lll_bowser_puzzle_piece_move(0.0f, -120.0f, 4, 6);241}242243void bhv_lll_bowser_puzzle_piece_move_down(void) {244bhv_lll_bowser_puzzle_piece_move(0.0f, 120.0f, 4, 3);245}246247void (*sBowserPuzzlePieceActions[])(void) = {248bhv_lll_bowser_puzzle_piece_action_0, bhv_lll_bowser_puzzle_piece_action_1,249bhv_lll_bowser_puzzle_piece_idle, bhv_lll_bowser_puzzle_piece_move_left,250bhv_lll_bowser_puzzle_piece_move_right, bhv_lll_bowser_puzzle_piece_move_up,251bhv_lll_bowser_puzzle_piece_move_down252};253254void bhv_lll_bowser_puzzle_piece_loop(void) {255bhv_lll_bowser_puzzle_piece_update();256257cur_obj_call_action_function(sBowserPuzzlePieceActions);258259o->oPosX = o->oBowserPuzzlePieceOffsetX + o->oHomeX;260o->oPosY = o->oBowserPuzzlePieceOffsetY + o->oHomeY;261o->oPosZ = o->oBowserPuzzlePieceOffsetZ + o->oHomeZ;262}263264265