Path: blob/master/SonicMania/Objects/AIZ/EncoreIntro.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: EncoreIntro Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89#if MANIA_USE_PLUS10ObjectEncoreIntro *EncoreIntro;1112void EncoreIntro_Update(void)13{14RSDK_THIS(EncoreIntro);1516if (!self->activated) {17foreach_active(Player, player)18{19if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {20EncoreIntro_SetupCutscene();21CutsceneSeq_SetSkipType(SKIPTYPE_RELOADSCN);22self->activated = true;23}24}25}2627if (self->skipPart2) {28EncoreIntro_SetupCutscenePart2();29CutsceneSeq_StartSequence(self, EncoreIntro_Cutscene_AIZEncore, EncoreIntro_Cutscene_CapsuleFound, EncoreIntro_Cutscene_BuddySelect,30EncoreIntro_Cutscene_ViewEncoreTutorial, EncoreIntro_Cutscene_MysticGetRuby, EncoreIntro_Cutscene_MysticStealRuby,31EncoreIntro_Cutscene_MysticEscape, EncoreIntro_Cutscene_AIZEncoreTutorial, EncoreIntro_Cutscene_CameraPanToHBHPile,32EncoreIntro_Cutscene_MysticPassRuby, EncoreIntro_Cutscene_KingActivate, EncoreIntro_Cutscene_RubyActivated,33EncoreIntro_Cutscene_RubyWarp, EncoreIntro_Cutscene_LoadGHZ, EncoreIntro_Cutscene_AwaitSaveFinish,34EncoreIntro_Cutscene_FadeOutAndReset, EncoreIntro_Cutscene_FadeInAndStart, EncoreIntro_Cutscene_SkipAndFadeOut,35EncoreIntro_Cutscene_AwaitSaveFinish, StateMachine_None);36self->skipPart2 = false;3738#if MANIA_USE_PLUS39CutsceneSeq_SetSkipType(SKIPTYPE_DISABLED);40#endif41}42}4344void EncoreIntro_LateUpdate(void) {}4546void EncoreIntro_StaticUpdate(void) {}4748void EncoreIntro_Draw(void) {}4950void EncoreIntro_Create(void *data)51{52RSDK_THIS(EncoreIntro);5354if (!SceneInfo->inEditor) {55INIT_ENTITY(self);56CutsceneRules_SetupEntity(self, &self->size, &self->hitbox);57EncoreIntro_SetupEntities();58self->active = ACTIVE_NORMAL;5960if (globals->enableIntro) {61foreach_all(HUD, hud)62{63HUD_MoveIn(hud);64hud->state = StateMachine_None;65}6667EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;68ruby->alpha = 0;69ruby->inkEffect = INK_ALPHA;70ruby->state = EncoreIntro_PhantomRuby_OscillateFX;71RSDK.SetSpriteAnimation(-1, -1, &ruby->flashAnimator, true, 0);72ruby->flashAnimator.animationID = -1;73}74else {75int32 id = RSDK.GetEntitySlot(self);7677foreach_all(Animals, animal)78{79if (RSDK.GetEntitySlot(animal) < id) {80destroyEntity(animal);81}82else {83foreach_break;84}85}86RSDK.ResetEntitySlot(id - 3, TYPE_BLANK, NULL);87RSDK.ResetEntitySlot(id - 2, TYPE_BLANK, NULL);88self->activated = true;89self->skipPart2 = true;90}91}92}9394void EncoreIntro_StageLoad(void)95{96EncoreIntro->aniFrames = RSDK.LoadSpriteAnimation("AIZ/Cutscene.bin", SCOPE_STAGE);9798EncoreIntro->sfxHighFive = RSDK.GetSfx("Stage/HighFive.wav");99EncoreIntro->sfxMysticPoof = RSDK.GetSfx("MSZ/MysticPoof.wav");100EncoreIntro->sfxKingCharge = RSDK.GetSfx("LRZ/KingCharge.wav");101EncoreIntro->sfxMysticHat = RSDK.GetSfx("MSZ/MysticHat.wav");102EncoreIntro->sfxMysticTransform = RSDK.GetSfx("MSZ/MysticTransform.wav");103EncoreIntro->sfxPon = RSDK.GetSfx("Stage/Pon.wav");104105Music_SetMusicTrack("BuddyBeat.ogg", TRACK_BUDDYBEAT, 85232);106}107108void EncoreIntro_SetupEntities(void)109{110foreach_all(PhantomRuby, ruby)111{112EncoreIntro->phantomRuby = ruby;113foreach_break;114}115116foreach_all(FXRuby, fxRuby)117{118EncoreIntro->fxRuby = fxRuby;119fxRuby->state = FXRuby_State_Shrinking;120fxRuby->outerRadius = 0;121foreach_break;122}123124foreach_all(RubyPortal, portal)125{126EncoreIntro->rubyPortal = portal;127foreach_break;128}129}130131void EncoreIntro_SetupCutscene(void)132{133RSDK_THIS(EncoreIntro);134135CutsceneSeq_StartSequence(self, EncoreIntro_Cutscene_SetupAIZEncore, EncoreIntro_Cutscene_PlayerAppear, EncoreIntro_Cutscene_RubyAppear,136EncoreIntro_Cutscene_PortalClose, EncoreIntro_Cutscene_Empty, EncoreIntro_Cutscene_BeginAIZEncore,137EncoreIntro_Cutscene_AIZEncore, EncoreIntro_Cutscene_CapsuleFound, EncoreIntro_Cutscene_BuddySelect,138EncoreIntro_Cutscene_ViewEncoreTutorial, EncoreIntro_Cutscene_MysticGetRuby, EncoreIntro_Cutscene_MysticStealRuby,139EncoreIntro_Cutscene_MysticEscape, EncoreIntro_Cutscene_AIZEncoreTutorial, EncoreIntro_Cutscene_CameraPanToHBHPile,140EncoreIntro_Cutscene_MysticPassRuby, EncoreIntro_Cutscene_KingActivate, EncoreIntro_Cutscene_RubyActivated,141EncoreIntro_Cutscene_RubyWarp, EncoreIntro_Cutscene_LoadGHZ, EncoreIntro_Cutscene_AwaitSaveFinish,142EncoreIntro_Cutscene_FadeOutAndReset, EncoreIntro_Cutscene_FadeInAndStart, EncoreIntro_Cutscene_SkipAndFadeOut,143EncoreIntro_Cutscene_AwaitSaveFinish, StateMachine_None);144145#if MANIA_USE_PLUS146CutsceneSeq_SetSkipType(SKIPTYPE_DISABLED);147#endif148}149150void EncoreIntro_SetupCutscenePart2(void)151{152RSDK_THIS(EncoreIntro);153EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);154EntityCamera *camera = RSDK_GET_ENTITY(SLOT_CAMERA1, Camera);155156player1->camera = camera;157player1->stateInput = Player_Input_P1;158player1->tileCollisions = TILECOLLISION_DOWN;159player1->onGround = true;160player1->state = Player_State_Ground;161camera->target = (Entity *)player1;162camera->state = Camera_State_FollowXY;163camera->position.x = player1->position.x;164165Vector2 size;166RSDK.GetLayerSize(Zone->fgLayer[0], &size, true);167Zone->cameraBoundsR[0] = size.x;168Zone->playerBoundsR[0] = size.x << 16;169Zone->playerBoundActiveR[0] = true;170Zone->cameraBoundsL[0] = (self->position.x >> 16) - ScreenInfo->center.x;171Zone->playerBoundsL[0] = Zone->cameraBoundsL[0] << 16;172Zone->playerBoundActiveL[0] = true;173174EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;175foreach_all(SchrodingersCapsule, capsule)176{177ruby->position.x = capsule->position.x;178ruby->state = EncoreIntro_PhantomRuby_OscillateFX;179ruby->startPos.y = capsule->position.y - 0x800000;180ruby->position.y = capsule->position.y - 0x800000;181}182}183184bool32 EncoreIntro_Cutscene_SetupAIZEncore(EntityCutsceneSeq *host)185{186EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);187188EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;189EntityFXRuby *fxRuby = EncoreIntro->fxRuby;190191// NOTE:192// ok idk HOW this is meant to be triggered193// I assume its via dying and hitting a StarPost194// big problem there: there aren't any!195// so there doesn't seem to be any way to get this to run normally196if (SceneInfo->minutes || SceneInfo->seconds) {197host->stateID = 21; // EncoreIntro_Cutscene_FadeOutAndReset198host->skipType = SKIPTYPE_DISABLED;199}200else {201if (!host->timer) {202globals->stock = ID_NONE;203globals->characterFlags = ID_SONIC;204Player_ChangeCharacter(player1, ID_SONIC);205destroyEntity(RSDK_GET_ENTITY(SLOT_PLAYER2, Player));206player1->alpha = 0;207player1->inkEffect = INK_ALPHA;208ruby->alpha = 0;209ruby->inkEffect = INK_ALPHA;210player1->position.y = ruby->position.y;211player1->state = Player_State_Static;212player1->stateInput = StateMachine_None;213CutsceneSeq_LockAllPlayerControl();214player1->groundVel = 0;215player1->velocity.x = 0;216player1->direction = FLIP_NONE;217foreach_all(CutsceneHBH, cutsceneHBH) { cutsceneHBH->drawGroup = Zone->objectDrawGroup[0]; }218Zone->cameraBoundsT[0] = Zone->cameraBoundsB[0] - SCREEN_YSIZE;219Zone->playerBoundsT[0] = Zone->cameraBoundsB[0] - SCREEN_YSIZE;220}221else if (host->timer == 240) {222fxRuby->delay = 32;223fxRuby->state = FXRuby_State_IncreaseStageDeform;224PhantomRuby_PlaySfx(RUBYSFX_ATTACK4);225Camera_ShakeScreen(0, 4, 4);226Music_TransitionTrack(TRACK_EGGMAN1, 0.01);227foreach_active(Animals, animal)228{229animal->behaviour = ANIMAL_BEHAVE_FREE;230animal->active = ACTIVE_NORMAL;231}232}233234if (host->timer < 360) {235RSDK.SetSpriteAnimation(player1->aniFrames, ANI_FAN, &player1->animator, false, 0);236player1->position.x += (player1->position.x - player1->position.x) >> 3;237player1->position.y += (0xA00 * RSDK.Sin256(2 * (host->timer - host->storedTimer)) + ruby->position.y - player1->position.y) >> 3;238player1->state = Player_State_Static;239}240else {241ruby->alpha = 0;242ruby->inkEffect = INK_ALPHA;243return true;244}245}246247return false;248}249250bool32 EncoreIntro_Cutscene_PlayerAppear(EntityCutsceneSeq *host)251{252EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);253254if (host->timer >= 60) {255player->alpha += 2;256if (player->alpha >= 0x100) {257player->inkEffect = INK_NONE;258RSDK.Sin256(2 * (host->timer - host->storedTimer));259RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);260player->state = Player_State_Air;261player->up = true;262host->values[0] = 1;263return true;264}265}266267return false;268}269270bool32 EncoreIntro_Cutscene_RubyAppear(EntityCutsceneSeq *host)271{272EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;273274if (host->timer >= 60) {275ruby->alpha += 2;276if (ruby->alpha >= 0x100) {277ruby->inkEffect = INK_NONE;278return true;279}280}281282return false;283}284285bool32 EncoreIntro_Cutscene_PortalClose(EntityCutsceneSeq *host)286{287EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;288EntityRubyPortal *portal = EncoreIntro->rubyPortal;289290if (host->timer >= 60) {291portal->alpha -= 4;292if (portal->alpha <= 0) {293destroyEntity(portal);294ruby->state = EncoreIntro_PhantomRuby_EscapeRight;295Music_FadeOut(0.012);296host->skipType = SKIPTYPE_DISABLED;297return true;298}299}300301return false;302}303304bool32 EncoreIntro_Cutscene_Empty(EntityCutsceneSeq *host)305{306return true; // what the307}308309bool32 EncoreIntro_Cutscene_BeginAIZEncore(EntityCutsceneSeq *host)310{311EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);312313if (host->timer == 60)314player->up = false;315316if (host->timer >= 120) {317foreach_all(TitleCard, titleCard)318{319titleCard->active = ACTIVE_NORMAL;320titleCard->state = TitleCard_State_SetupBGElements;321titleCard->stateDraw = TitleCard_Draw_SlideIn;322foreach_break;323}324foreach_all(HUD, hud)325{326hud->vsStates[0] = HUD_State_MoveIn;327hud->state = hud->vsStates[0];328}329Music_PlayTrack(TRACK_STAGE);330EncoreIntro_SetupCutscenePart2();331return true;332}333334return false;335}336337bool32 EncoreIntro_Cutscene_AIZEncore(EntityCutsceneSeq *host)338{339EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);340341RSDK_THIS(EncoreIntro);342EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;343344if (player->position.x <= self->position.x + 0x2000000) {345Zone->cameraBoundsL[0] = ScreenInfo->position.x;346Zone->playerBoundsL[0] = Zone->cameraBoundsL[0] << 16;347Zone->playerBoundActiveL[0] = true;348}349else {350Zone->cameraBoundsT[0] = 0;351Zone->playerBoundsT[0] = 0;352}353354if (ruby->onScreen) {355Zone->cameraBoundsT[0] = Zone->cameraBoundsB[0] - SCREEN_YSIZE;356Zone->playerBoundsT[0] = Zone->cameraBoundsB[0] - SCREEN_YSIZE;357Music_TransitionTrack(TRACK_EGGMAN1, 0.05);358return true;359}360361return false;362}363364bool32 EncoreIntro_Cutscene_CapsuleFound(EntityCutsceneSeq *host)365{366RSDK_THIS(EncoreIntro);367368EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);369EntityActClear *actClear = RSDK_GET_ENTITY(SLOT_ACTCLEAR, ActClear);370371if (!self->seenActClear) {372if (actClear->classID == ActClear->classID)373self->seenActClear = true;374}375else {376player->velocity.x = 0;377player->groundVel = 0;378if (actClear->classID != ActClear->classID) {379self->seenActClear = false;380Music_TransitionTrack(TRACK_EGGMAN2, 0.05);381382StarPost->playerPositions[0] = player->position;383StarPost->playerPositions[1] = player->position;384player->state = EncoreIntro_PlayerState_BuddySel;385player->stateInput = EncoreIntro_PlayerInput_BuddySel;386RSDK.SetSpriteAnimation(player->aniFrames, ANI_IDLE, &player->animator, true, 0);387388EntityPlayer *buddy1 = RSDK_GET_ENTITY(SLOT_PLAYER3, Player);389buddy1->state = Player_State_Ground;390RSDK.SetSpriteAnimation(buddy1->aniFrames, ANI_IDLE, &buddy1->animator, true, 0);391392EntityPlayer *buddy2 = RSDK_GET_ENTITY(SLOT_PLAYER4, Player);393buddy2->state = Player_State_Ground;394RSDK.SetSpriteAnimation(buddy2->aniFrames, ANI_IDLE, &buddy2->animator, true, 0);395return true;396}397}398399return false;400}401402bool32 EncoreIntro_Cutscene_BuddySelect(EntityCutsceneSeq *host)403{404EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);405406player->drawGroup = Zone->playerDrawGroup[1];407EntityPlayer *selBuddy = RSDK_GET_ENTITY(SLOT_PLAYER3, Player);408if (player->position.x > selBuddy->position.x - 0x380000) {409globals->characterFlags = ID_SONIC | ID_MIGHTY;410}411else {412selBuddy = RSDK_GET_ENTITY(SLOT_PLAYER4, Player);413if (player->position.x < selBuddy->position.x + 0x380000)414globals->characterFlags = ID_SONIC | ID_RAY;415else416return false;417}418player->state = EncoreIntro_PlayerState_HandleAir;419player->nextAirState = StateMachine_None;420player->nextGroundState = Player_State_Static;421player->onGround = false;422globals->stock = ID_NONE;423if (globals->characterFlags == (ID_SONIC | ID_RAY)) {424RSDK.SetSpriteAnimation(EncoreIntro->aniFrames, 0, &player->animator, true, 0);425player->velocity.x = -0xC000;426}427else {428RSDK.SetSpriteAnimation(EncoreIntro->aniFrames, 1, &player->animator, true, 0);429player->velocity.x = 0x8000;430}431player->velocity.y = -0x30000;432CutsceneSeq_LockPlayerControl(player);433player->stateInput = StateMachine_None;434435EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);436RSDK.CopyEntity(buddy, selBuddy, true);437buddy->drawGroup = Zone->playerDrawGroup[1];438buddy->state = EncoreIntro_PlayerState_HandleAir;439buddy->nextAirState = StateMachine_None;440buddy->nextGroundState = Player_State_Static;441buddy->onGround = false;442443if (globals->characterFlags == (ID_SONIC | ID_RAY)) {444RSDK.SetSpriteAnimation(EncoreIntro->aniFrames, 2, &buddy->animator, true, 0);445buddy->velocity.x = 0xC000;446}447else {448RSDK.SetSpriteAnimation(EncoreIntro->aniFrames, 3, &buddy->animator, true, 0);449buddy->velocity.x = -0x8000;450}451buddy->velocity.y = -0x30000;452globals->playerID = (buddy->characterID << 8) + ID_SONIC;453Music_FadeOut(0.025);454RSDK.PlaySfx(EncoreIntro->sfxHighFive, false, 0xFF);455456if (globals->characterFlags == (ID_SONIC | ID_RAY))457CREATE_ENTITY(AIZEncoreTutorial, INT_TO_VOID(5), (buddy->position.x >> 1) + (player->position.x >> 1), player->position.y - 0x480000);458else459CREATE_ENTITY(AIZEncoreTutorial, INT_TO_VOID(6), (buddy->position.x >> 1) + (player->position.x >> 1), player->position.y - 0x480000);460461return true;462}463464bool32 EncoreIntro_Cutscene_ViewEncoreTutorial(EntityCutsceneSeq *host)465{466EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);467EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);468469RSDK_THIS(EncoreIntro);470EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;471472HeavyMystic_HandleParticleFX();473if (player->onGround) {474RSDK.SetSpriteAnimation(player->aniFrames, ANI_IDLE, &player->animator, true, 0);475player->velocity.x = 0;476player->groundVel = 0;477}478479if (host->timer > 300)480player->direction = ruby->position.x < player->position.x;481482if (buddy->onGround) {483RSDK.SetSpriteAnimation(buddy->aniFrames, ANI_IDLE, &buddy->animator, true, 0);484buddy->velocity.x = 0;485buddy->groundVel = 0;486}487488if (host->timer > 300)489buddy->direction = ruby->position.x < buddy->position.x;490491if (host->timer == 18) {492if (globals->characterFlags == (ID_SONIC | ID_RAY)) {493player->velocity.x = 0;494buddy->velocity.x = 0;495}496}497else if (host->timer == 300) {498EntityPlayer *otherBuddy = RSDK_GET_ENTITY(SLOT_PLAYER3, Player);499if (!otherBuddy->classID)500otherBuddy = RSDK_GET_ENTITY(SLOT_PLAYER4, Player);501self->position.x = otherBuddy->position.x;502self->position.y = otherBuddy->position.y;503}504else {505if (host->timer != 420) {506if (host->timer == 480) {507EntityCutsceneHBH *mystic = CutsceneHBH_GetEntity(HBH_MYSTIC);508RSDK.SetSpriteAnimation(mystic->aniFrames, 1, &mystic->mainAnimator, true, 0);509}510else {511if (host->timer == 496) {512RSDK.PlaySfx(EncoreIntro->sfxMysticHat, false, 0xFF);513}514else if (host->timer < 570) {515EntityCutsceneHBH *mystic = CutsceneHBH_GetEntity(HBH_MYSTIC);516if (mystic->mainAnimator.frameID == mystic->mainAnimator.frameCount - 1)517RSDK.SetSpriteAnimation(mystic->aniFrames, 0, &mystic->mainAnimator, true, 0);518}519else {520return true;521}522}523}524else {525EntityCutsceneHBH *mystic = CutsceneHBH_GetEntity(HBH_MYSTIC);526EntityPlayer *otherBuddy = RSDK_GET_ENTITY(SLOT_PLAYER3, Player);527if (!otherBuddy->classID)528otherBuddy = RSDK_GET_ENTITY(SLOT_PLAYER4, Player);529mystic->position.x = otherBuddy->position.x;530mystic->position.y = otherBuddy->position.y;531mystic->direction = otherBuddy->direction ^ 1;532mystic->drawGroup = Zone->playerDrawGroup[1] - 1;533destroyEntity(otherBuddy);534535RSDK.PlaySfx(EncoreIntro->sfxMysticPoof, false, 0xFF);536CREATE_ENTITY(Explosion, INT_TO_VOID(2), mystic->position.x, mystic->position.y)->drawGroup = Zone->playerDrawGroup[1] - 1;537Music_PlayTrack(TRACK_HBHMISCHIEF);538539for (int32 i = 0; i < 2; ++i) {540EntityPlayer *playerPtr = RSDK_GET_ENTITY(i, Player);541playerPtr->state = Player_State_Air;542playerPtr->onGround = false;543playerPtr->velocity.y = -0x38000;544RSDK.SetSpriteAnimation(playerPtr->aniFrames, ANI_HURT, &playerPtr->animator, false, 0);545}546}547}548return false;549}550551bool32 EncoreIntro_Cutscene_MysticGetRuby(EntityCutsceneSeq *host)552{553EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);554EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);555EntityCamera *camera = RSDK_GET_ENTITY(SLOT_CAMERA1, Camera);556UNUSED(camera);557558RSDK_THIS(EncoreIntro);559EntityCutsceneHBH *mystic = CutsceneHBH_GetEntity(HBH_MYSTIC);560EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;561562player->direction = ruby->position.x < player->position.x;563buddy->direction = ruby->position.x < buddy->position.x;564565int32 offset = -0x320000;566if (buddy->direction)567offset = 0x320000;568int32 pos = offset + ruby->position.x;569570if (mystic->position.x != pos) {571if (mystic->position.x >= pos) {572mystic->position.x -= 0x20000;573if (mystic->position.x < offset + ruby->position.x)574mystic->position.x = offset + ruby->position.x;575}576else {577mystic->position.x += 0x20000;578if (mystic->position.x > offset + ruby->position.x)579mystic->position.x = offset + ruby->position.x;580}581582mystic->position.y -= 0x18000;583mystic->velocity.y = -0x18000;584if (host->timer > 24) {585RSDK.SetSpriteAnimation(player->aniFrames, ANI_LOOK_UP, &player->animator, false, 1);586if (player->animator.frameID == 5)587player->animator.speed = 0;588589RSDK.SetSpriteAnimation(buddy->aniFrames, ANI_LOOK_UP, &buddy->animator, false, 1);590if (buddy->animator.frameID == 5)591buddy->animator.speed = 0;592}593self->position.x = mystic->position.x;594self->position.y = mystic->position.y;595HeavyMystic_HandleParticleFX();596}597else {598RSDK.SetSpriteAnimation(player->aniFrames, ANI_LOOK_UP, &player->animator, false, 1);599if (player->animator.frameID == 5)600player->animator.speed = 0;601602RSDK.SetSpriteAnimation(buddy->aniFrames, ANI_LOOK_UP, &buddy->animator, false, 1);603if (buddy->animator.frameID == 5)604buddy->animator.speed = 0;605606if (mystic->position.y > ruby->startPos.y + 0x140000) {607mystic->position.y += mystic->velocity.y;608self->position.x = mystic->position.x;609self->position.y = mystic->position.y;610HeavyMystic_HandleParticleFX();611}612else {613RSDK.SetSpriteAnimation(mystic->aniFrames, 2, &mystic->mainAnimator, true, 0);614return true;615}616}617618return false;619}620621bool32 EncoreIntro_Cutscene_MysticStealRuby(EntityCutsceneSeq *host)622{623EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);624EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);625626RSDK_THIS(EncoreIntro);627EntityCutsceneHBH *mystic = CutsceneHBH_GetEntity(HBH_MYSTIC);628EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;629630player->direction = ruby->position.x < player->position.x;631buddy->direction = ruby->position.x < buddy->position.x;632633if (host->timer == 33) {634RSDK.PlaySfx(EncoreIntro->sfxMysticTransform, false, 255);635ruby->state = StateMachine_None;636}637else if (host->timer >= 34) {638if (ruby->position.y < mystic->position.y) {639ruby->startPos.y += 0x18000;640ruby->position.y += 0x18000;641}642else if (ruby->visible) {643ruby->visible = false;644}645else if (host->timer == 75) {646RSDK.SetSpriteAnimation(mystic->aniFrames, 0, &mystic->mainAnimator, true, 0);647Zone->cameraBoundsR[0] = 16 * RSDK.GetTileLayer(Zone->fgLayer[0])->width;648Zone->playerBoundsR[0] = 16 * RSDK.GetTileLayer(Zone->fgLayer[0])->width;649Zone->cameraBoundsT[0] = 784;650Zone->playerBoundsT[0] = 784;651mystic->direction = FLIP_NONE;652return true;653}654}655656self->position.x = mystic->position.x;657self->position.y = mystic->position.y;658HeavyMystic_HandleParticleFX();659return false;660}661662bool32 EncoreIntro_Cutscene_MysticEscape(EntityCutsceneSeq *host)663{664EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);665EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);666667RSDK_THIS(EncoreIntro);668EntityCutsceneHBH *mystic = CutsceneHBH_GetEntity(HBH_MYSTIC);669EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;670671player->direction = mystic->position.x < player->position.x;672buddy->direction = mystic->position.x < buddy->position.x;673if (host->timer >= 60) {674mystic->position.y -= 0x800000;675mystic->position.x = CutsceneHBH_GetEntity(HBH_KINGDAMAGED)->position.x - 0x580000;676ruby->position.y -= 0x800000;677SceneInfo->timeEnabled = true;678679player->state = Player_State_Ground;680player->stateInput = Player_Input_P1;681RSDK.SetSpriteAnimation(player->aniFrames, ANI_IDLE, &player->animator, true, 0);682683buddy->state = Player_State_Ground;684buddy->stateInput = Player_Input_P2_AI;685RSDK.SetSpriteAnimation(buddy->aniFrames, ANI_IDLE, &buddy->animator, true, 0);686return true;687}688else {689mystic->velocity.x += 0x1800;690if (mystic->velocity.x > 0x30000)691mystic->velocity.x = 0x30000;692if (mystic->onScreen == 1)693--host->timer;694mystic->position.x += mystic->velocity.x;695self->position.x = mystic->position.x;696self->position.y = mystic->position.y;697HeavyMystic_HandleParticleFX();698}699return false;700}701702bool32 EncoreIntro_Cutscene_AIZEncoreTutorial(EntityCutsceneSeq *host)703{704EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);705EntityCamera *camera = RSDK_GET_ENTITY(SLOT_CAMERA1, Camera);706707RSDK_THIS(AIZEncoreTutorial);708EntityCutsceneHBH *king = CutsceneHBH_GetEntity(HBH_KINGDAMAGED);709710if (player->position.x >= king->position.x - 0x2600000) {711self->position.x = player->position.x;712self->position.y = player->position.y;713player->stateInput = StateMachine_None;714if (player->onGround)715player->state = Player_State_Ground;716CutsceneSeq_LockAllPlayerControl();717718player->right = true;719if (player->velocity.x >= 0x20000)720player->velocity.x = 0x20000;721self->velocity.x = player->velocity.x;722camera->target = (Entity *)self;723CutsceneSeq_SetSkipTypeCallback(AIZEncoreTutorial_State_ReturnToCutscene);724HUD_MoveOut();725return true;726}727return false;728}729730bool32 EncoreIntro_Cutscene_CameraPanToHBHPile(EntityCutsceneSeq *host)731{732RSDK_THIS(EncoreIntro);733EntityCutsceneHBH *mystic = CutsceneHBH_GetEntity(HBH_MYSTIC);734EntityCutsceneHBH *king = CutsceneHBH_GetEntity(HBH_KINGDAMAGED);735EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);736EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);737738if (self->position.x >= king->position.x - 0x880000) {739if (self->velocity.x == 0x60000) {740player->groundVel = 0x30000;741player->velocity.x = 0x30000;742player->position.x = (ScreenInfo->position.x - 32) << 16;743buddy->groundVel = 0x30000;744buddy->position.x = (ScreenInfo->position.x - 96) << 16;745buddy->velocity.x = 0x30000;746buddy->drawFX &= ~FX_SCALE;747buddy->position.y = player->position.y;748buddy->state = Player_State_Ground;749buddy->tileCollisions = TILECOLLISION_DOWN;750buddy->stateInput = StateMachine_None;751buddy->scale.x = 0;752buddy->scale.y = 0;753buddy->drawGroup = player->drawGroup - 1;754}755756self->velocity.x -= 0x1800;757if (self->velocity.x < 0x4C000) {758player->right = false;759buddy->right = false;760player->up = true;761buddy->up = true;762}763if (buddy->state == Player_State_Ground && buddy->position.x >= player->position.x - 0x200000)764buddy->velocity.x = player->velocity.x;765if (self->velocity.x <= -0x2D000) {766RSDK.SetSpriteAnimation(mystic->aniFrames, 2, &mystic->mainAnimator, true, 0);767self->velocity.x = 0;768return true;769}770}771else {772self->velocity.x += 0x6000;773if (self->velocity.x > 0x60000)774self->velocity.x = 0x60000;775776player->state = Player_State_Ground;777player->right = true;778if (player->groundVel > 0x20000)779player->groundVel = 0x20000;780if (buddy->groundVel > ((buddy->position.x <= player->position.x) + 1) << 16)781buddy->groundVel = 0x20000;782}783784if (self->velocity.x > 0)785self->position.x += self->velocity.x;786787self->position.y = mystic->position.y;788if (self->position.x <= mystic->position.x) {789int32 storeX = self->position.x;790int32 storeY = self->position.y;791self->position.x = mystic->position.x;792self->position.y = mystic->position.y;793HeavyMystic_HandleParticleFX();794self->position.x = storeX;795self->position.y = storeY;796}797else {798self->position.x = mystic->position.x;799self->position.y = mystic->position.y;800HeavyMystic_HandleParticleFX();801}802803return false;804}805806bool32 EncoreIntro_Cutscene_MysticPassRuby(EntityCutsceneSeq *host)807{808EntityCutsceneHBH *mystic = CutsceneHBH_GetEntity(HBH_MYSTIC);809EntityCutsceneHBH *king = CutsceneHBH_GetEntity(HBH_KINGDAMAGED);810EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;811EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);812EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);813814player->timer = 0;815buddy->timer = 0;816if (buddy->state == Player_State_Ground && buddy->position.x >= player->position.x - 0x200000)817buddy->velocity.x = player->velocity.x;818819switch (host->timer) {820case 33:821RSDK.PlaySfx(EncoreIntro->sfxPon, false, 0xFF);822ruby->visible = true;823ruby->position.x = mystic->position.x + 0x320000;824ruby->position.y = mystic->position.y;825ruby->velocity.x = 0;826ruby->velocity.y = -0x40000;827ruby->state = EncoreIntro_PhantomRuby_Fall;828Music_TransitionTrack(TRACK_EGGMAN1, 0.025);829break;830case 40: mystic->drawGroup = Zone->playerDrawGroup[0]; break;831case 75:832RSDK.SetSpriteAnimation(mystic->aniFrames, 0, &mystic->mainAnimator, true, 0);833player->up = false;834buddy->up = false;835break;836default:837if (ruby->position.y >= king->position.y + 0x60000) {838ruby->position.y = king->position.y + 0x60000;839ruby->state = StateMachine_None;840RSDK.PlaySfx(Player->sfxGrab, false, 0xFF);841RSDK.SetSpriteAnimation(king->aniFrames, 3, &king->fxAnimator, true, 0);842return true;843}844break;845}846HeavyMystic_HandleParticleFX();847return false;848}849850bool32 EncoreIntro_Cutscene_KingActivate(EntityCutsceneSeq *host)851{852EntityCutsceneHBH *king = CutsceneHBH_GetEntity(HBH_KINGDAMAGED);853EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;854EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);855EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);856857player->timer = 0;858buddy->timer = 0;859if (buddy->state == Player_State_Ground && buddy->position.x >= player->position.x - 0x200000)860buddy->velocity.x = player->velocity.x;861862switch (host->timer) {863case 9: ruby->drawGroup = Zone->objectDrawGroup[0]; break;864865case 42: RSDK.SetSpriteAnimation(king->aniFrames, 2, &king->mainAnimator, true, 0); break;866867case 58:868case 66:869case 74: RSDK.PlaySfx(EncoreIntro->sfxKingCharge, false, 0xFF); break;870871case 102: return true;872873default: break;874}875HeavyMystic_HandleParticleFX();876return false;877}878879bool32 EncoreIntro_Cutscene_RubyActivated(EntityCutsceneSeq *host)880{881EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;882if (!host->timer)883PhantomRuby_SetupFlash(ruby);884if (ruby->flashFinished)885return true;886HeavyMystic_HandleParticleFX();887return false;888}889890bool32 EncoreIntro_Cutscene_RubyWarp(EntityCutsceneSeq *host)891{892EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;893EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);894EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);895896EntityFXRuby *fxRuby = NULL;897if (!host->timer) {898fxRuby = CREATE_ENTITY(FXRuby, NULL, ruby->position.x, ruby->position.y);899fxRuby->drawGroup = Zone->playerDrawGroup[1] + 1;900EncoreIntro->fxRuby = fxRuby;901PhantomRuby_PlaySfx(RUBYSFX_REDCUBE);902Camera_ShakeScreen(0, 4, 4);903player->drawGroup = Zone->playerDrawGroup[1] + 1;904if (buddy->classID == Player->classID)905buddy->drawGroup = Zone->playerDrawGroup[1] + 1;906}907else {908fxRuby = EncoreIntro->fxRuby;909}910911if (!host->values[0]) {912if (fxRuby->fullyExpanded) {913if (host->storedTimer) {914if (host->timer == host->storedTimer + 30) {915fxRuby->delay = 64;916fxRuby->state = FXRuby_State_IncreaseStageDeform;917PhantomRuby_PlaySfx(4);918Camera_ShakeScreen(0, 4, 4);919}920else if (host->timer == host->storedTimer + 210) {921fxRuby->delay = 32;922fxRuby->state = FXRuby_State_IncreaseStageDeform;923PhantomRuby_PlaySfx(RUBYSFX_ATTACK1);924Camera_ShakeScreen(0, 4, 4);925Music_FadeOut(0.025);926host->storedTimer = host->timer;927host->values[0] = 1;928}929}930else {931host->storedTimer = host->timer;932}933934if (host->timer >= host->storedTimer + 32) {935EntityPlayer *players[2];936players[0] = player;937players[1] = buddy;938939for (int32 i = 0, angle = 0; angle < 0x80; ++i, angle += 0x40) {940if (!players[i])941break;942EntityPlayer *playerPtr = players[i];943RSDK.SetSpriteAnimation(playerPtr->aniFrames, ANI_FAN, &playerPtr->animator, false, 0);944945playerPtr->position.x += (playerPtr->position.x - playerPtr->position.x) >> 3;946playerPtr->position.y +=947(0xA00 * RSDK.Sin256(2 * (host->timer + angle - host->storedTimer)) + ruby->position.y - playerPtr->position.y) >> 3;948playerPtr->tileCollisions = TILECOLLISION_NONE;949playerPtr->velocity.x = 0;950playerPtr->velocity.y = 0;951playerPtr->state = Player_State_Static;952}953}954}955}956else {957if (fxRuby->fadeWhite >= 512) {958if (fxRuby->fadeBlack >= 512) {959if (host->timer >= host->storedTimer + 150) {960return true;961}962}963else {964fxRuby->fadeBlack += 16;965}966}967else {968fxRuby->fadeWhite += 16;969}970}971HeavyMystic_HandleParticleFX();972973return false;974}975976bool32 EncoreIntro_Cutscene_LoadGHZ(EntityCutsceneSeq *host)977{978RSDK_THIS(EncoreIntro);979Player->playerCount = 2;980SaveGame_SavePlayerState();981SaveGame_GetSaveRAM()->saveState = SAVEGAME_INPROGRESS; // save file is active982RSDK.SetScene("Cutscenes", "Green Hill Zone");983EncoreIntro->awaitingSaveFinish = true;984SaveGame_SaveFile(EncoreIntro_SaveGameCB);985if (EncoreIntro->awaitingSaveFinish) {986UIWaitSpinner_StartWait();987if (EncoreIntro->awaitingSaveFinish)988return true;989}990RSDK.LoadScene();991destroyEntity(self);992993return false;994}995996bool32 EncoreIntro_Cutscene_AwaitSaveFinish(EntityCutsceneSeq *host)997{998RSDK_THIS(EncoreIntro);999if (!EncoreIntro->awaitingSaveFinish) {1000RSDK.LoadScene();1001destroyEntity(self);1002}1003return false;1004}10051006bool32 EncoreIntro_Cutscene_FadeOutAndReset(EntityCutsceneSeq *host)1007{1008EntityFXRuby *fxRuby = EncoreIntro->fxRuby;10091010if (fxRuby->fadeBlack >= 512) {1011EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);1012EntityCamera *camera = RSDK_GET_ENTITY(SLOT_CAMERA1, Camera);1013EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;1014destroyEntity(EncoreIntro->rubyPortal);10151016ruby->state = EncoreIntro_PhantomRuby_EscapeRight;1017ruby->inkEffect = INK_NONE;10181019player->inkEffect = INK_NONE;1020RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);1021player->state = Player_State_Air;1022player->up = true;1023player->camera = NULL;1024host->values[0] = true;1025player->stateInput = Player_Input_P1;1026player->tileCollisions = TILECOLLISION_DOWN;1027player->onGround = true;1028player->state = Player_State_Ground;1029player->camera = camera;10301031Camera_SetupLerp(CAMERA_LERP_NORMAL, 0, camera->position.x, camera->position.y, 0);1032camera->target = (Entity *)player;1033camera->state = Camera_State_FollowXY;10341035Hitbox *playerHitbox = Player_GetHitbox(player);1036while (1037!RSDK.ObjectTileGrip(player, player->collisionLayers, player->collisionMode, player->collisionPlane, 0, playerHitbox->bottom << 16, 8)) {1038player->position.y += 0x80000;1039}10401041if (!SceneInfo->minutes && !SceneInfo->seconds) {1042EntityTitleCard *titleCard = (EntityTitleCard *)CutsceneSeq_GetEntity(TitleCard->classID);1043titleCard->active = ACTIVE_NORMAL;1044titleCard->state = TitleCard_State_SetupBGElements;1045titleCard->stateDraw = TitleCard_Draw_SlideIn;1046}10471048Vector2 size;1049RSDK.GetLayerSize(Zone->fgLayer[0], &size, true);1050Zone->playerBoundsR[0] = size.x;1051Zone->cameraBoundsR[0] = size.x;1052Zone->playerBoundActiveR[0] = true;10531054foreach_all(HUD, hud)1055{1056hud->vsStates[0] = HUD_State_MoveIn;1057hud->state = hud->vsStates[0];1058}10591060foreach_all(SchrodingersCapsule, capsule)1061{1062ruby->position.x = capsule->position.x;1063ruby->startPos.y = capsule->position.y - 0x800000;1064ruby->state = EncoreIntro_PhantomRuby_OscillateFX;1065}10661067foreach_active(Animals, animal) { destroyEntity(animal); }1068return true;1069}1070else {1071fxRuby->fadeBlack += 16;1072}10731074return false;1075}10761077bool32 EncoreIntro_Cutscene_FadeInAndStart(EntityCutsceneSeq *host)1078{1079EntityFXRuby *fxRuby = EncoreIntro->fxRuby;10801081if (fxRuby->fadeBlack <= 0) {1082host->stateID = 6; // EncoreIntro_Cutscene_AIZEncore1083host->timer = 0;1084}1085else {1086fxRuby->fadeBlack -= 16;1087}10881089return false;1090}10911092// Called as skipCB when mystic shows up with the pile1093bool32 EncoreIntro_Cutscene_SkipAndFadeOut(EntityCutsceneSeq *host)1094{1095EntityFXRuby *fxRuby = EncoreIntro->fxRuby;10961097if (fxRuby->fadeWhite < 512) {1098fxRuby->fadeWhite += 16;1099}1100else if (fxRuby->fadeBlack < 512) {1101fxRuby->fadeBlack += 16;1102}1103else if (host->timer >= 150) {1104// Same as EncoreIntro_Cutscene_LoadGHZ but setting GHZ+1 to skip the intro cutscene1105RSDK_THIS(EncoreIntro);1106Player->playerCount = 2;1107SaveGame_SavePlayerState();1108SaveGame_GetSaveRAM()->saveState = SAVEGAME_INPROGRESS; // save file is active1109RSDK.SetScene("Encore Mode", "Green Hill Zone+ 1");1110EncoreIntro->awaitingSaveFinish = true;1111SaveGame_SaveFile(EncoreIntro_SaveGameCB);1112if (EncoreIntro->awaitingSaveFinish) {1113UIWaitSpinner_StartWait();1114if (EncoreIntro->awaitingSaveFinish)1115return true;1116}1117RSDK.LoadScene();1118destroyEntity(self);1119}11201121return false;1122}11231124void EncoreIntro_SaveGameCB(bool32 success)1125{1126UIWaitSpinner_FinishWait();1127EncoreIntro->awaitingSaveFinish = false;1128}11291130void EncoreIntro_PhantomRuby_OscillateFX(void)1131{1132EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;1133EntityFXRuby *fxRuby = EncoreIntro->fxRuby;11341135ruby->position.y = BadnikHelpers_Oscillate(ruby->startPos.y, 2, 10);1136fxRuby->position.x = ruby->position.x;1137fxRuby->position.y = ruby->position.y;1138}1139void EncoreIntro_PhantomRuby_EscapeRight(void)1140{1141EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;11421143if (ruby->velocity.x < 0x40000)1144ruby->velocity.x += 0x1800;1145ruby->angle += 2;1146ruby->position.x += ruby->velocity.x;1147ruby->position.y = (RSDK.Sin256(ruby->angle) << 10) + ruby->startPos.y;1148}1149void EncoreIntro_PhantomRuby_Fall(void)1150{1151EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;11521153ruby->position.x += ruby->velocity.x;1154ruby->position.y += ruby->velocity.y;1155ruby->velocity.y += 0x3800;1156}1157void EncoreIntro_PhantomRuby_CapsuleRiseUp(void)1158{1159EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;11601161ruby->active = ACTIVE_NORMAL;1162if (ruby->velocity.y <= -0x60000) {1163ruby->velocity.y = -ruby->velocity.y;1164ruby->velocity.x = 0;1165ruby->state = EncoreIntro_PhantomRuby_CapsuleFallDown;1166}1167else {1168ruby->position.y += ruby->velocity.y;1169ruby->velocity.y -= 0x3800;1170}1171RSDK.SetChannelAttributes(Music->channelID, 1.0 - (((ruby->startPos.y - ruby->position.y) >> 16) / 120.0), 0.0, 1.0);1172}1173void EncoreIntro_PhantomRuby_CapsuleFallDown(void)1174{1175EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;11761177if (ruby->velocity.x >= 60) {1178if (ruby->velocity.y <= 0) {1179ruby->velocity.y = 0;1180ruby->active = ACTIVE_BOUNDS;1181ruby->state = EncoreIntro_PhantomRuby_OscillateFX;1182}1183else {1184ruby->velocity.y -= 0x3800;1185ruby->position.y += ruby->velocity.y;1186}1187RSDK.SetChannelAttributes(Music->channelID, 1.0 - (((ruby->startPos.y - ruby->position.y) >> 16) / 120.0), 0.0, 1.0);1188}1189else {1190ruby->velocity.x++;1191}1192}11931194void EncoreIntro_PlayerState_BuddySel(void)1195{1196RSDK_THIS(Player);1197self->groundVel = CLAMP(self->groundVel, -0x20000, 0x20000);1198Player_State_Ground();1199}12001201void EncoreIntro_PlayerState_HandleAir(void)1202{1203Player_HandleAirFriction();1204Player_HandleAirMovement();1205}12061207void EncoreIntro_PlayerInput_BuddySel(void)1208{1209RSDK_THIS(Player);12101211ControllerInfo[CONT_P1].keyX.down = false;1212ControllerInfo[CONT_P1].keyX.press = false;1213ControllerInfo[CONT_P1].keyY.down = false;1214ControllerInfo[CONT_P1].keyY.press = false;1215ControllerInfo[CONT_P1].keyZ.down = false;1216ControllerInfo[CONT_P1].keyZ.press = false;1217ControllerInfo[CONT_P1].keyStart.down = false;1218ControllerInfo[CONT_P1].keyStart.press = false;1219ControllerInfo[CONT_P1].keySelect.down = false;1220ControllerInfo[CONT_P1].keySelect.press = false;12211222Player_Input_P1();12231224self->up = false;1225self->down = false;1226self->jumpPress = false;1227self->jumpHold = false;1228}12291230#if GAME_INCLUDE_EDITOR1231void EncoreIntro_EditorDraw(void)1232{1233RSDK_THIS(EncoreIntro);1234CutsceneRules_DrawCutsceneBounds(self, &self->size);1235}12361237void EncoreIntro_EditorLoad(void) {}1238#endif12391240void EncoreIntro_Serialize(void) { RSDK_EDITABLE_VAR(EncoreIntro, VAR_VECTOR2, size); }1241#endif124212431244