Path: blob/master/SonicMania/Objects/CPZ/CPZBoss.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: CPZBoss Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"8#include <time.h>910ObjectCPZBoss *CPZBoss;1112void CPZBoss_Update(void)13{14RSDK_THIS(CPZBoss);1516StateMachine_Run(self->state);17}1819void CPZBoss_LateUpdate(void) {}2021void CPZBoss_StaticUpdate(void) {}2223void CPZBoss_Draw(void)24{25RSDK_THIS(CPZBoss);2627RSDK.DrawSprite(&self->characterAnimator, NULL, false);28RSDK.DrawSprite(&self->enterAnimator, &self->startPos, false);29RSDK.DrawSprite(&self->panelAnimator, &self->startPos, false);30}3132void CPZBoss_Create(void *data)33{34RSDK_THIS(CPZBoss);3536if (!SceneInfo->inEditor) {37if (globals->gameMode == MODE_TIMEATTACK) {38destroyEntity(self);39}40else {41self->drawGroup = Zone->playerDrawGroup[0];42self->startPos = self->position;43self->active = ACTIVE_BOUNDS;44self->visible = true;45self->updateRange.x = 0x800000;46self->updateRange.y = 0x800000;4748if (self->type == CPZBOSS_PLAYER) {49self->drawFX = FX_FLIP;50self->state = CPZBoss_State_SetupArena;51}52else {53RSDK.SetSpriteAnimation(CPZBoss->aniFrames, 2, &self->characterAnimator, true, 0);54RSDK.SetSpriteAnimation(CPZBoss->aniFrames, 0, &self->panelAnimator, true, 0);55}56}57}58}5960void CPZBoss_StageLoad(void)61{62CPZBoss->aniFrames = RSDK.LoadSpriteAnimation("Eggman/EggmanCPZ.bin", SCOPE_STAGE);6364CPZBoss->hitboxPlayerTrigger.left = -16;65CPZBoss->hitboxPlayerTrigger.top = 8;66CPZBoss->hitboxPlayerTrigger.right = 16;67CPZBoss->hitboxPlayerTrigger.bottom = 16;6869CPZBoss->sfxExplosion = RSDK.GetSfx("Stage/Explosion2.wav");7071RSDK.SetDrawGroupProperties(Zone->objectDrawGroup[1], false, StateMachine_None);72RSDK.SetDrawGroupProperties(Zone->objectDrawGroup[1] + 1, false, StateMachine_None);73}7475void CPZBoss_DrawHook_SetupPuyoHUD(void) { RSDK.SetClipBounds(0, 0, 24, ScreenInfo->size.x, ScreenInfo->size.y); }76void CPZBoss_DrawHook_RemovePuyoHUD(void) { RSDK.SetClipBounds(0, 0, 0, ScreenInfo->size.x, ScreenInfo->size.y); }7778void CPZBoss_Explode_Eggman(void)79{80RSDK_THIS(CPZBoss);8182if (!(Zone->timer % 3)) {83RSDK.PlaySfx(CPZBoss->sfxExplosion, false, 0xFF);84if (Zone->timer & 4) {85int32 x = self->explosionPos.x + RSDK.Rand(-0x300000, 0x300000);86int32 y = self->explosionPos.y + RSDK.Rand(-0x100000, 0x100000);87CREATE_ENTITY(Explosion, INT_TO_VOID((RSDK.Rand(0, 256) > 192) + EXPLOSION_BOSS), x, y)->drawGroup = Zone->hudDrawGroup;88}89}90}9192void CPZBoss_Explode_Player(void)93{94RSDK_THIS(CPZBoss);9596if (!(Zone->timer % 3)) {97RSDK.PlaySfx(CPZBoss->sfxExplosion, false, 0xFF);98if (Zone->timer & 4) {99int32 x = self->position.x + RSDK.Rand(-0x100000, 0x100000);100int32 y = self->position.y + RSDK.Rand(-0x100000, 0x100000);101CREATE_ENTITY(Explosion, INT_TO_VOID((RSDK.Rand(0, 256) > 192) + EXPLOSION_BOSS), x, y)->drawGroup = Zone->hudDrawGroup;102}103}104}105106bool32 CPZBoss_CheckMatchReset(void)107{108RSDK_THIS(CPZBoss);109110if (!RSDK.CheckOnScreen(self, NULL)) {111RSDK.SetDrawGroupProperties(Zone->objectDrawGroup[1], false, StateMachine_None);112RSDK.SetDrawGroupProperties(Zone->objectDrawGroup[1] + 1, false, StateMachine_None);113Music_TransitionTrack(TRACK_STAGE, 0.0125);114PuyoBean->comboChainCount[0] = 0;115PuyoBean->disableBeanLink[0] = 0;116PuyoBean->comboChainCount[1] = 0;117PuyoBean->disableBeanLink[1] = 0;118119for (int32 i = 0; i < 0x100; ++i) PuyoBean->playfield[i] = NULL;120121foreach_all(PuyoBean, bean) { destroyEntity(bean); }122123int32 layerID = RSDK.GetTileLayerID("FG High");124RSDK.CopyTileLayer(layerID, 438, 150, layerID, 452, 150, 6, 2);125SceneInfo->timeEnabled = true;126CPZBoss_Create(NULL);127128return true;129}130return false;131}132133void CPZBoss_State_SetupArena(void)134{135RSDK_THIS(CPZBoss);136137if (++self->timer >= 8) {138SceneInfo->timeEnabled = false;139Music_SetMusicTrack("BossPuyo.ogg", TRACK_EGGMAN2, 846720);140Music_TransitionTrack(TRACK_EGGMAN2, 0.0125);141142EntityCPZBoss *target = RSDK_GET_ENTITY(SceneInfo->entitySlot + 1, CPZBoss);143Camera_SetupLerp(CAMERA_LERP_SIN1024_2, 0, target->position.x, target->position.y, 8);144145foreach_active(HUD, hud) { CPZBoss->hudSlotID = RSDK.GetEntitySlot(hud); }146147HUD_MoveOut();148149foreach_active(Player, player)150{151if (player->sidekick)152player->active = ACTIVE_NEVER;153else154player->velocity.y = 0;155}156157switch (GET_CHARACTER_ID(1)) {158default:159case ID_SONIC: CPZBoss->playerFrames = RSDK.LoadSpriteAnimation("CPZ/MBMSonic.bin", SCOPE_STAGE); break;160case ID_TAILS: CPZBoss->playerFrames = RSDK.LoadSpriteAnimation("CPZ/MBMTails.bin", SCOPE_STAGE); break;161case ID_KNUCKLES: CPZBoss->playerFrames = RSDK.LoadSpriteAnimation("CPZ/MBMKnux.bin", SCOPE_STAGE); break;162#if MANIA_USE_PLUS163case ID_MIGHTY: CPZBoss->playerFrames = RSDK.LoadSpriteAnimation("CPZ/MBMMighty.bin", SCOPE_STAGE); break;164case ID_RAY: CPZBoss->playerFrames = RSDK.LoadSpriteAnimation("CPZ/MBMRay.bin", SCOPE_STAGE); break;165#endif166}167168RSDK.SetSpriteAnimation(CPZBoss->playerFrames, 1, &self->enterAnimator, true, 0);169RSDK.SetSpriteAnimation(CPZBoss->playerFrames, 0, &self->panelAnimator, true, 0);170self->timer = 0;171self->active = ACTIVE_NORMAL;172self->state = CPZBoss_State_EnterPlayer;173}174}175176void CPZBoss_State_EnterPlayer(void)177{178RSDK_THIS(CPZBoss);179180if (!CPZBoss_CheckMatchReset() && ++self->timer >= 30) {181foreach_active(Player, player)182{183if (!player->sidekick)184player->velocity.y = 0x80000;185}186187self->state = CPZBoss_State_CheckPlayerReady;188}189}190191void CPZBoss_State_CheckPlayerReady(void)192{193RSDK_THIS(CPZBoss);194195if (!CPZBoss_CheckMatchReset()) {196foreach_active(Player, player)197{198if (Player_CheckCollisionTouch(player, self, &CPZBoss->hitboxPlayerTrigger)) {199if (player->sidekick) {200player->state = Player_State_Air;201}202else {203player->visible = false;204player->active = ACTIVE_NEVER;205player->up = false;206player->down = false;207player->left = false;208player->right = false;209player->jumpPress = false;210player->jumpHold = false;211player->position.x = self->position.x;212player->position.y = self->position.y;213player->velocity.x = 0;214player->velocity.y = 0;215RSDK.SetSpriteAnimation(-1, 0, &self->enterAnimator, true, 0);216RSDK.SetSpriteAnimation(CPZBoss->playerFrames, 1, &self->characterAnimator, true, 1);217self->direction = FLIP_X;218self->state = CPZBoss_State_PlayPlayerEnterAnim;219}220}221}222}223}224225void CPZBoss_State_PlayPlayerEnterAnim(void)226{227RSDK_THIS(CPZBoss);228229if (!CPZBoss_CheckMatchReset()) {230RSDK.ProcessAnimation(&self->characterAnimator);231232if (self->characterAnimator.frameID == self->characterAnimator.frameCount - 1) {233foreach_active(CPZBoss, boss)234{235if (boss->type == CPZBOSS_EGGMAN) {236RSDK.SetSpriteAnimation(CPZBoss->aniFrames, 4, &boss->characterAnimator, true, 0);237boss->state = CPZBoss_State_HandleMatch_Eggman;238}239}240self->state = CPZBoss_State_SetupMatch;241}242}243}244245void CPZBoss_State_SetupMatch(void)246{247RSDK_THIS(CPZBoss);248249if (!CPZBoss_CheckMatchReset() && ++self->timer == 60) {250foreach_active(CPZShutter, shutter) { shutter->state = CPZShutter_State_Open; }251int32 key = (int32)time(NULL);252int32 rand = RSDK.RandSeeded(0, 512, &key);253254int32 matchCount = 0;255foreach_active(PuyoMatch, match)256{257RSDK.SetSpriteAnimation(-1, 0, &match->beanRAnimator, true, 0);258RSDK.SetSpriteAnimation(-1, 0, &match->beanLAnimator, true, 0);259match->state = PuyoMatch_State_HandleMatch;260match->matchKey = rand;261PuyoMatch_SetupNextBeans(match);262263if (match->playerID == 1) {264match->stateInput = PuyoAI_Input_AI;265PuyoAI->isAI[match->playerID] = false;266PuyoAI->lastBeanY[match->playerID] = PUYO_PLAYFIELD_H;267PuyoAI->desiredColumn[match->playerID] = 0;268PuyoAI->desiredRotation[match->playerID] = 0;269PuyoAI->isAI[match->playerID] = true;270PuyoAI->controlInterval[match->playerID] = 16;271PuyoAI->controlChance[match->playerID] = 50;272}273274CPZBoss->managers[matchCount++] = match;275}276277self->direction = FLIP_NONE;278RSDK.SetSpriteAnimation(CPZBoss->playerFrames, 2, &self->characterAnimator, false, 0);279self->state = CPZBoss_State_HandleMatch_Player;280RSDK.SetDrawGroupProperties(Zone->objectDrawGroup[1], false, CPZBoss_DrawHook_SetupPuyoHUD);281RSDK.SetDrawGroupProperties(Zone->objectDrawGroup[1] + 1, false, CPZBoss_DrawHook_RemovePuyoHUD);282}283}284285void CPZBoss_State_HandleMatch_Player(void)286{287RSDK_THIS(CPZBoss);288289if (!CPZBoss_CheckMatchReset()) {290RSDK.ProcessAnimation(&self->characterAnimator);291292EntityPuyoMatch *manager = CPZBoss->managers[self->type];293if (self->characterAnimator.animationID == 2) {294if (manager) {295EntityPuyoBean *bean = manager->beanPtr;296if (bean) {297if (bean->state == PuyoBean_State_JunkLand) {298RSDK.SetSpriteAnimation(CPZBoss->playerFrames, 3, &self->characterAnimator, false, 0);299}300else {301if (bean->down)302self->characterAnimator.frameID = 3;303else if (bean->left)304self->characterAnimator.frameID = 1;305else if (bean->right)306self->characterAnimator.frameID = 2;307308if (bean->rotateRight)309self->characterAnimator.frameID = 4;310else if (bean->rotateLeft)311self->characterAnimator.frameID = 5;312}313}314}315}316else if (self->characterAnimator.animationID == 3 && self->characterAnimator.frameID == self->characterAnimator.frameCount - 1) {317RSDK.SetSpriteAnimation(CPZBoss->playerFrames, 2, &self->characterAnimator, false, 0);318}319320if (ControllerInfo[CONT_P1].keyStart.press) {321if (RSDK_GET_ENTITY(SLOT_PAUSEMENU, PauseMenu)->classID == TYPE_BLANK) {322RSDK.ResetEntitySlot(SLOT_PAUSEMENU, PauseMenu->classID, NULL);323RSDK.PlaySfx(PauseMenu->sfxAccept, false, 0xFF);324RSDK.SetEngineState(ENGINESTATE_FROZEN);325}326}327328if (manager) {329if (manager->state == PuyoMatch_State_Lose) {330PuyoBean_DestroyPuyoBeans();331self->timer = 0;332self->state = CPZBoss_State_HandleMatchFinish_PlayerLose;333PuyoAI->isAI[0] = false;334PuyoAI->isAI[1] = false;335RSDK.SetSpriteAnimation(CPZBoss->playerFrames, 3, &self->characterAnimator, false, 0);336}337}338}339}340341void CPZBoss_State_HandleMatch_Eggman(void)342{343RSDK_THIS(CPZBoss);344345if (!CPZBoss_CheckMatchReset()) {346RSDK.ProcessAnimation(&self->characterAnimator);347348EntityPuyoMatch *manager = CPZBoss->managers[self->type];349if (self->characterAnimator.animationID == 2) {350if (manager) {351EntityPuyoBean *bean = manager->beanPtr;352if (bean && bean->state == PuyoBean_State_JunkLand)353RSDK.SetSpriteAnimation(CPZBoss->aniFrames, 3, &self->characterAnimator, false, 0);354}355}356else {357if (self->characterAnimator.animationID == 3 || self->characterAnimator.animationID == 4) {358if (self->characterAnimator.frameID == self->characterAnimator.frameCount - 1)359RSDK.SetSpriteAnimation(CPZBoss->aniFrames, 2, &self->characterAnimator, false, 0);360}361}362363if (manager) {364if (manager->state == PuyoMatch_State_Lose) {365PuyoBean_DestroyPuyoBeans();366self->state = CPZBoss_State_HandleMatchFinish_EggmanLose;367self->explosionPos.x = self->position.x + 0x400000;368self->explosionPos.y = (ScreenInfo->size.y + ScreenInfo->position.y) << 16;369RSDK.SetSpriteAnimation(CPZBoss->aniFrames, 3, &self->characterAnimator, false, 0);370}371}372}373}374375void CPZBoss_State_HandleMatchFinish_EggmanLose(void)376{377RSDK_THIS(CPZBoss);378379if (!CPZBoss_CheckMatchReset()) {380RSDK.ProcessAnimation(&self->characterAnimator);381382CPZBoss_Explode_Eggman();383384self->explosionPos.y -= 0x40000;385if (self->explosionPos.y < self->position.y - 0xD00000) {386RSDK.SetSpriteAnimation(CPZBoss->aniFrames, 5, &self->characterAnimator, false, 0);387self->state = CPZBoss_State_PlayerWin;388foreach_active(CPZShutter, shutter) { shutter->state = CPZShutter_State_Close; }389}390}391}392393void CPZBoss_State_PlayerWin(void)394{395RSDK_THIS(CPZBoss);396397if (!CPZBoss_CheckMatchReset()) {398RSDK.ProcessAnimation(&self->characterAnimator);399400CPZBoss_Explode_Player();401402if (++self->timer == 60) {403self->timer = 0;404self->active = ACTIVE_NORMAL;405self->state = CPZBoss_State_EggmanFall;406RSDK.SetSpriteAnimation(CPZBoss->playerFrames, 1, &self->enterAnimator, true, 0);407RSDK.SetSpriteAnimation(CPZBoss->aniFrames, 6, &self->characterAnimator, false, 0);408Music_TransitionTrack(TRACK_STAGE, 0.0125);409410RSDK.PlaySfx(PuyoBean->sfxFall, false, 255);411foreach_active(TippingPlatform, platform)412{413if (platform->bossID == TIPPINGPLATFORM_EGGMAN) {414platform->state = TippingPlatform_State_Tipping_Boss;415platform->timer = 120;416}417}418419foreach_active(CPZBoss, boss)420{421if (!boss->type) {422boss->state = CPZBoss_State_PlayerExit;423RSDK.SetSpriteAnimation(-1, 0, &boss->characterAnimator, false, 0);424RSDK.SetSpriteAnimation(CPZBoss->playerFrames, 1, &boss->enterAnimator, true, 0);425426foreach_all(Player, player)427{428player->up = false;429player->down = false;430player->left = false;431player->right = false;432player->velocity.x = 0;433player->velocity.y = 0;434player->groundVel = 0;435if (!player->sidekick)436player->stateInput = StateMachine_None;437player->visible = true;438player->active = ACTIVE_NORMAL;439player->position.x = boss->position.x;440player->position.y = boss->position.y;441}442}443}444}445}446}447448void CPZBoss_State_HandleMatchFinish_PlayerLose(void)449{450RSDK_THIS(CPZBoss);451452if (!CPZBoss_CheckMatchReset()) {453RSDK.ProcessAnimation(&self->characterAnimator);454455if (++self->timer == 60) {456self->timer = 0;457self->state = (Type_StateMachine)CPZBoss_CheckMatchReset;458RSDK.PlaySfx(PuyoBean->sfxFall, false, 255);459foreach_active(TippingPlatform, platform)460{461if (platform->bossID == TIPPINGPLATFORM_PLAYER) {462platform->state = TippingPlatform_State_Tipping_Boss;463platform->timer = 120;464}465}466467foreach_all(Player, player)468{469player->visible = true;470player->active = ACTIVE_NORMAL;471player->position.x = self->position.x;472player->position.y = self->position.y;473player->drawGroup = Zone->playerDrawGroup[0];474player->state = Player_State_Air;475player->onGround = false;476player->velocity.y = -0x20000;477RSDK.AddDrawListRef(Zone->playerDrawGroup[0], RSDK.GetEntitySlot(&player));478RSDK.SetSpriteAnimation(player->aniFrames, ANI_HURT, &player->animator, false, 0);479RSDK.SetSpriteAnimation(-1, 0, &self->characterAnimator, false, 0);480RSDK.SetSpriteAnimation(CPZBoss->playerFrames, 1, &self->enterAnimator, true, 0);481}482483foreach_active(CPZShutter, shutter)484{485shutter->active = ACTIVE_NORMAL;486shutter->state = CPZShutter_State_Close;487}488489EntityHUD *hud = RSDK_GET_ENTITY(CPZBoss->hudSlotID, HUD);490RSDK.ResetEntity(hud, HUD->classID, NULL);491HUD_MoveIn(hud);492}493}494}495496void CPZBoss_State_EggmanFall(void)497{498RSDK_THIS(CPZBoss);499500RSDK.ProcessAnimation(&self->characterAnimator);501if (self->timer > 32) {502self->velocity.y += 0x2800;503self->position.y += self->velocity.y;504}505506if (++self->timer == 95)507self->state = StateMachine_None;508}509510void CPZBoss_State_PlayerExit(void)511{512RSDK_THIS(CPZBoss);513514if (++self->timer == 240) {515self->timer = 0;516foreach_active(Player, player)517{518player->state = Player_State_Air;519player->nextAirState = StateMachine_None;520player->nextGroundState = StateMachine_None;521player->applyJumpCap = false;522player->onGround = false;523player->position.x = self->position.x;524player->position.y = self->position.y;525player->velocity.x = 0;526player->velocity.y = -0x80000;527RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);528Zone->playerBoundActiveR[player->playerID] = true;529}530531EntityTransportTube *tube = RSDK_GET_ENTITY(SceneInfo->entitySlot + 3, TransportTube);532tube->dirMask = TRANSPORTTUBE_DIR_S | TRANSPORTTUBE_DIR_E;533TransportTube_SetupDirections(tube);534535EntityHUD *hud = RSDK_GET_ENTITY(CPZBoss->hudSlotID, HUD);536RSDK.ResetEntity(hud, HUD->classID, NULL);537HUD_MoveIn(hud);538539self->active = ACTIVE_NORMAL;540self->state = CPZBoss_State_Destroyed;541}542}543544void CPZBoss_State_Destroyed(void)545{546RSDK_THIS(CPZBoss);547548if (++self->timer == 24) {549for (int32 i = 0; i < Player->playerCount; ++i) {550EntityPlayer *player = RSDK_GET_ENTITY(i, Player);551if (player->camera)552player->camera->state = Camera_State_FollowXY;553if (!player->sidekick)554player->stateInput = Player_Input_P1;555}556557self->active = ACTIVE_BOUNDS;558self->state = StateMachine_None;559}560}561562#if GAME_INCLUDE_EDITOR563void CPZBoss_EditorDraw(void)564{565RSDK_THIS(CPZBoss);566self->startPos = self->position;567568if (self->type == CPZBOSS_PLAYER) {569self->drawFX = FX_FLIP;570RSDK.SetSpriteAnimation(CPZBoss->playerFrames, 1, &self->enterAnimator, true, 0);571RSDK.SetSpriteAnimation(CPZBoss->playerFrames, 0, &self->panelAnimator, true, 0);572RSDK.SetSpriteAnimation(-1, 0, &self->characterAnimator, true, 0);573}574else {575RSDK.SetSpriteAnimation(CPZBoss->aniFrames, 2, &self->characterAnimator, true, 0);576RSDK.SetSpriteAnimation(CPZBoss->aniFrames, 0, &self->panelAnimator, true, 0);577RSDK.SetSpriteAnimation(-1, 0, &self->enterAnimator, true, 0);578}579580CPZBoss_Draw();581}582583void CPZBoss_EditorLoad(void)584{585CPZBoss->aniFrames = RSDK.LoadSpriteAnimation("Eggman/EggmanCPZ.bin", SCOPE_STAGE);586CPZBoss->playerFrames = RSDK.LoadSpriteAnimation("CPZ/MBMSonic.bin", SCOPE_STAGE);587588RSDK_ACTIVE_VAR(CPZBoss, type);589RSDK_ENUM_VAR("Player", CPZBOSS_PLAYER);590RSDK_ENUM_VAR("Eggman", CPZBOSS_EGGMAN);591}592#endif593594void CPZBoss_Serialize(void) { RSDK_EDITABLE_VAR(CPZBoss, VAR_UINT8, type); }595596597