Path: blob/master/SonicMania/Objects/ERZ/PhantomHand.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: PhantomHand Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectPhantomHand *PhantomHand;1011void PhantomHand_Update(void)12{13RSDK_THIS(PhantomHand);1415StateMachine_Run(self->state);16}1718void PhantomHand_LateUpdate(void) {}1920void PhantomHand_StaticUpdate(void) {}2122void PhantomHand_Draw(void)23{24RSDK_THIS(PhantomHand);2526RSDK.CopyPalette(1, 128, 0, 128, 128);2728self->inkEffect = INK_ADD;29RSDK.DrawSprite(&self->handAnimator, NULL, false);3031if (self->state != PhantomHand_State_Disappear) {32self->inkEffect = INK_ALPHA;33self->alpha = 0xD0;34RSDK.DrawSprite(&self->crystalAnimator, NULL, false);3536self->inkEffect = INK_ADD;37self->alpha = 0x100;38RSDK.DrawSprite(&self->shineAnimator, NULL, false);39}40}4142void PhantomHand_Create(void *data)43{44RSDK_THIS(PhantomHand);4546if (!SceneInfo->inEditor) {47self->visible = true;48self->drawGroup = Zone->objectDrawGroup[0];49self->parent = (Entity *)data;50self->targetPos = self->position;51self->active = ACTIVE_NORMAL;52self->inkEffect = INK_ADD;53self->drawFX = FX_FLIP | FX_SCALE;54self->alpha = 0x100;55self->updateRange.x = 0x800000;56self->updateRange.y = 0x800000;57self->timerDecreaseSpeed = 64;58self->state = PhantomHand_State_Summon;59RSDK.SetSpriteAnimation(PhantomHand->aniFrames, 0, &self->handAnimator, true, 0);60}61}6263void PhantomHand_StageLoad(void)64{65PhantomHand->aniFrames = RSDK.LoadSpriteAnimation("Phantom/PhantomHand.bin", SCOPE_STAGE);6667PhantomHand->hitbox.left = -20;68PhantomHand->hitbox.top = -20;69PhantomHand->hitbox.right = 20;70PhantomHand->hitbox.bottom = 20;7172int32 pos = 3;73for (int32 i = 0; i < PhantomHand->debrisInfo[0]; ++i) {74PhantomHand->debrisInfo[pos + 0] = RSDK.Rand(-0x20000, 0x20000);75PhantomHand->debrisInfo[pos + 1] = RSDK.Rand(-0x10000, -0x40000);7677pos += 4;78}7980PhantomHand->grabbedPlayers[0] = false;81PhantomHand->grabbedPlayers[1] = false;82PhantomHand->grabbedPlayers[2] = false;83PhantomHand->grabbedPlayers[3] = false;84}8586void PhantomHand_CheckPlayerGrab(int32 playerX, int32 playerY)87{88RSDK_THIS(PhantomHand);8990if (self->position.x >= playerX) {91if (self->position.x > playerX) {92int32 dist = MIN((self->position.x - playerX) >> 5, 0x10000);93self->position.x -= dist;94}95}96else {97int32 dist = MIN((playerX - self->position.x) >> 5, 0x10000);98self->position.x += dist;99}100101if (self->targetPos.y < playerY)102self->targetPos.y += 0x10000;103104if (playerY <= self->targetPos.y)105self->position.y += (playerY - self->position.y) >> 3;106else107self->position.y = self->targetPos.y;108109foreach_active(Player, player)110{111if (player->state != Player_State_Static) {112int32 rx = (player->position.x - self->position.x) >> 16;113int32 ry = (player->position.y - self->position.y) >> 16;114if (rx * rx + ry * ry < 0x100) {115if (!PhantomHand->grabbedPlayers[player->playerID]) {116PhantomHand->grabbedPlayers[player->playerID] = true;117self->state = PhantomHand_State_GrabbedPlayer;118}119}120}121}122}123124void PhantomHand_State_Summon(void)125{126RSDK_THIS(PhantomHand);127128if (!self->timer)129RSDK.PlaySfx(PhantomEgg->sfxSummon, false, 255);130131self->position.x += self->velocity.x;132if (self->timer > 0)133self->timerDecreaseSpeed -= 4;134135self->timer += self->timerDecreaseSpeed;136137if (self->timer < 0x200 && self->timerDecreaseSpeed < 0) {138self->timer = 0x200;139self->state = PhantomHand_State_Appear;140}141142self->scaleAngle += 8;143self->scale.x = self->timer + ((self->timer * RSDK.Sin256(self->scaleAngle)) >> 11);144self->scale.y = self->timer + ((self->timer * RSDK.Cos256(self->scaleAngle)) >> 11);145}146147void PhantomHand_State_Appear(void)148{149RSDK_THIS(PhantomHand);150151RSDK.ProcessAnimation(&self->handAnimator);152153self->scaleAngle += 16;154self->position.x += self->velocity.x;155156self->scale.x = ((self->timer * RSDK.Sin256(self->scaleAngle)) >> 11) + 0x200;157self->scale.y = ((self->timer * RSDK.Cos256(self->scaleAngle)) >> 11) + 0x200;158159if (self->timer <= 0) {160self->drawFX = FX_FLIP;161162if (Player->playerCount < 2)163self->state = PhantomHand_State_TryGrabPlayer;164else165self->state = PhantomHand_State_TryGrabPlayers;166}167else {168self->timer -= 32;169}170}171172void PhantomHand_State_TryGrabPlayer(void)173{174RSDK_THIS(PhantomHand);175176RSDK.ProcessAnimation(&self->handAnimator);177178EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);179180if (player1->interaction == true && player1->state == Player_State_Static) {181self->state = PhantomHand_State_Disappear;182}183else {184if ((self->direction && player1->position.x <= PhantomEgg->boundsM) || (!self->direction && player1->position.x >= PhantomEgg->boundsM))185PhantomHand_CheckPlayerGrab(self->parent->position.x, player1->position.y);186else187PhantomHand_CheckPlayerGrab(player1->position.x, player1->position.y);188}189}190191void PhantomHand_State_TryGrabPlayers(void)192{193RSDK_THIS(PhantomHand);194195RSDK.ProcessAnimation(&self->handAnimator);196197bool32 playersActive = true;198for (int32 i = SLOT_PLAYER1; i < SLOT_PLAYER1 + 2; ++i) {199EntityPlayer *player = RSDK_GET_ENTITY(i, Player);200if (player->classID == Player->classID)201playersActive = playersActive && player->interaction && player->state == Player_State_Static;202}203204if (playersActive) {205self->state = PhantomHand_State_Disappear;206}207else {208int32 dist = 0x7FFFFFFF;209210EntityPlayer *playerPtr = NULL;211if (self->direction == FLIP_NONE) {212foreach_active(Player, player)213{214if (player->state != Player_State_Static && self->position.x - player->position.x < dist) {215dist = self->position.x - self->position.x;216playerPtr = player;217}218}219}220else {221foreach_active(Player, player)222{223if (player->state != Player_State_Static && player->position.x - self->position.x < dist) {224dist = player->position.x - self->position.x;225playerPtr = player;226}227}228}229230if (playerPtr)231PhantomHand_CheckPlayerGrab(playerPtr->position.x, playerPtr->position.y);232}233}234235void PhantomHand_State_GrabbedPlayer(void)236{237RSDK_THIS(PhantomHand);238239foreach_active(Player, player)240{241if (Player_CheckCollisionTouch(player, self, &PhantomHand->hitbox)) {242player->state = Player_State_Static;243player->nextAirState = StateMachine_None;244player->nextGroundState = StateMachine_None;245player->position.x = self->position.x;246player->position.y = self->position.y;247player->velocity.x = 0;248player->velocity.y = 0;249player->onGround = false;250player->groundVel = 0;251252if (!player->playerID)253self->doScanlineCB = true;254255RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);256}257}258259if (++self->grabTimer == 8) {260self->grabTimer = 0;261RSDK.SetSpriteAnimation(PhantomHand->aniFrames, 1, &self->handAnimator, true, 0);262self->state = PhantomHand_State_Clasp;263}264}265266void PhantomHand_State_Clasp(void)267{268RSDK_THIS(PhantomHand);269270RSDK.ProcessAnimation(&self->handAnimator);271272if (self->handAnimator.frameID == 5)273self->drawGroup = Zone->objectDrawGroup[1];274275if (self->handAnimator.frameID == 10) {276RSDK.SetSpriteAnimation(PhantomHand->aniFrames, 2, &self->crystalAnimator, true, 0);277self->state = PhantomHand_State_Crystalize;278}279}280281void PhantomHand_State_Crystalize(void)282{283RSDK_THIS(PhantomHand);284285RSDK.ProcessAnimation(&self->handAnimator);286RSDK.ProcessAnimation(&self->crystalAnimator);287288if (self->crystalAnimator.frameID == self->crystalAnimator.frameCount - 1) {289RSDK.SetSpriteAnimation(-1, 0, &self->handAnimator, true, 0);290RSDK.SetSpriteAnimation(PhantomHand->aniFrames, 3, &self->shineAnimator, true, 0);291self->state = PhantomHand_State_Shine;292}293}294295void PhantomHand_State_Shine(void)296{297RSDK_THIS(PhantomHand);298299RSDK.ProcessAnimation(&self->shineAnimator);300301if (self->shineAnimator.frameID == self->shineAnimator.frameCount - 1) {302RSDK.SetSpriteAnimation(-1, 0, &self->shineAnimator, true, 0);303304if (self->doScanlineCB)305PhantomEgg_SetupWarpFX();306307self->state = StateMachine_None;308}309}310311void PhantomHand_State_BreakApart(void)312{313RSDK_THIS(PhantomHand);314315Debris_CreateFromEntries(PhantomHand->aniFrames, PhantomHand->debrisInfo, 4);316RSDK.PlaySfx(PhantomEgg->sfxExplosion2, false, 255);317318foreach_active(Player, player)319{320if (Player_CheckCollisionTouch(player, self, &PhantomHand->hitbox)) {321player->state = Player_State_Air;322player->velocity.y = -0x40000;323player->onGround = false;324player->groundVel = 0;325PhantomHand->grabbedPlayers[player->playerID] = false;326RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);327}328}329330destroyEntity(self);331}332333void PhantomHand_State_Disappear(void)334{335RSDK_THIS(PhantomHand);336337if (self->alpha <= 0)338destroyEntity(self);339else340self->alpha -= 8;341}342343#if GAME_INCLUDE_EDITOR344void PhantomHand_EditorDraw(void)345{346RSDK_THIS(PhantomHand);347RSDK.SetSpriteAnimation(PhantomHand->aniFrames, 0, &self->handAnimator, true, 0);348349RSDK.DrawSprite(&self->handAnimator, NULL, false);350}351352void PhantomHand_EditorLoad(void) { PhantomHand->aniFrames = RSDK.LoadSpriteAnimation("Phantom/PhantomHand.bin", SCOPE_STAGE); }353#endif354355void PhantomHand_Serialize(void) {}356357358