Path: blob/master/SonicMania/Objects/ERZ/PhantomKing.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: PhantomKing Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectPhantomKing *PhantomKing;1011void PhantomKing_Update(void)12{13RSDK_THIS(PhantomKing);1415if (self->invincibilityTimer > 0)16self->invincibilityTimer--;1718StateMachine_Run(self->state);19}2021void PhantomKing_LateUpdate(void) {}2223void PhantomKing_StaticUpdate(void) {}2425void PhantomKing_Draw(void)26{27RSDK_THIS(PhantomKing);2829if (self->stateDraw) {30StateMachine_Run(self->stateDraw);31}32else {33RSDK.DrawSprite(&self->basicAnimator, NULL, false);34}35}3637void PhantomKing_Create(void *data)38{39RSDK_THIS(PhantomKing);4041self->drawFX = FX_FLIP;42if (!SceneInfo->inEditor) {43self->updateRange.x = 0x800000;44self->updateRange.y = 0x1000000;45self->drawGroup = Zone->objectDrawGroup[0];46self->drawFX = FX_ROTATE | FX_FLIP;47self->type = VOID_TO_INT(data);4849switch (self->type) {50case PHANTOMKING_KING:51self->hitbox.left = -24;52self->hitbox.top = -24;53self->hitbox.right = 24;54self->hitbox.bottom = 24;5556self->active = ACTIVE_BOUNDS;57self->visible = false;58self->direction = FLIP_X;59self->health = 8;6061RSDK.SetSpriteAnimation(PhantomKing->aniFrames, 0, &self->headAnimator, true, 0);62RSDK.SetSpriteAnimation(PhantomKing->aniFrames, 1, &self->bodyAnimator, true, 0);63RSDK.SetSpriteAnimation(PhantomKing->aniFrames, 2, &self->beltAnimator, true, 0);64RSDK.SetSpriteAnimation(PhantomKing->aniFrames, 7, &self->particleAnimator, true, 0);65RSDK.SetSpriteAnimation(PhantomKing->aniFrames, 8, &self->rubyAnimator, true, 0);6667self->originPos = self->position;68self->state = PhantomKing_State_Initialize;69break;7071case PHANTOMKING_ARM_L:72case PHANTOMKING_ARM_R:73self->active = ACTIVE_NORMAL;74self->visible = true;7576RSDK.SetSpriteAnimation(PhantomKing->aniFrames, 3, &self->armAnimator, true, 0);77RSDK.SetSpriteAnimation(PhantomKing->aniFrames, 4, &self->cuffAnimator, true, 0);7879if (self->type == PHANTOMKING_ARM_L) {80RSDK.SetSpriteAnimation(PhantomKing->aniFrames, 6, &self->handAnimator, true, 0);81}82else {83self->drawGroup = Zone->playerDrawGroup[0];84RSDK.SetSpriteAnimation(PhantomKing->aniFrames, 5, &self->handAnimator, true, 0);85}8687self->stateDraw = PhantomKing_Draw_Arm;88self->state = PhantomKing_StateArm_Idle;89break;90}91}92}9394void PhantomKing_StageLoad(void)95{96PhantomKing->aniFrames = RSDK.LoadSpriteAnimation("Phantom/PhantomKing.bin", SCOPE_STAGE);9798PhantomKing->sfxHit = RSDK.GetSfx("Stage/BossHit.wav");99PhantomKing->sfxExplosion = RSDK.GetSfx("Stage/Explosion2.wav");100}101102void PhantomKing_CheckPlayerCollisions(void)103{104RSDK_THIS(PhantomKing);105106foreach_active(Player, player)107{108if (!self->invincibilityTimer && Player_CheckBadnikTouch(player, self, &self->hitbox) && Player_CheckBossHit(player, self)) {109PhantomKing_Hit();110}111}112}113114void PhantomKing_Oscillate(void)115{116RSDK_THIS(PhantomKing);117118self->angle = (self->angle + 3) & 0xFF;119self->position.y = (RSDK.Sin256(self->angle) << 10) + self->originPos.y;120}121122void PhantomKing_Hit(void)123{124RSDK_THIS(PhantomKing);125126foreach_all(PhantomRuby, ruby)127{128ruby->position.x = self->rubyPos.x;129ruby->position.y = self->rubyPos.y;130ruby->velocity.x = -0x20000;131ruby->velocity.y = -0x40000;132ruby->state = PhantomRuby_State_MoveGravity;133}134135self->drawRuby = false;136if (--self->health <= 0) {137self->originPos.x = self->position.x;138self->originPos.y = self->position.y;139self->state = PhantomKing_State_Explode;140self->velocity.y = -0x10000;141self->timer = 0;142143foreach_active(PKingAttack, attack)144{145if (attack->state == PKingAttack_State_Orbiting)146destroyEntity(attack);147}148149if (KleptoMobile->defeated)150SceneInfo->timeEnabled = false;151152Player_GiveScore(RSDK_GET_ENTITY(SLOT_PLAYER1, Player), 1000);153}154else {155self->invincibilityTimer = 48;156RSDK.PlaySfx(PhantomKing->sfxHit, false, 255);157self->state = PhantomKing_State_HitFall;158}159}160161void PhantomKing_Explode(void)162{163RSDK_THIS(PhantomKing);164165if (!(Zone->timer % 7)) {166RSDK.PlaySfx(PhantomKing->sfxExplosion, false, 255);167168if (Zone->timer & 8) {169int32 x = self->position.x + (RSDK.Rand(self->hitbox.left, self->hitbox.right) << 16);170int32 y = self->position.y + (RSDK.Rand(self->hitbox.top, self->hitbox.bottom) << 16);171CREATE_ENTITY(Explosion, INT_TO_VOID((RSDK.Rand(0, 256) > 192) + EXPLOSION_BOSS), x, y)->drawGroup = Zone->objectDrawGroup[1];172}173}174}175176void PhantomKing_HandleFrames(void)177{178RSDK_THIS(PhantomKing);179180RSDK.ProcessAnimation(&self->bodyAnimator);181182if (self->state != PhantomKing_State_WrestleEggman) {183int32 max = self->velocity.x >> 15;184185if (self->rotation >= max) {186if (self->rotation > max) {187self->rotation--;188if (self->rotation < max)189self->rotation = self->velocity.x >> 15;190}191}192else {193self->rotation++;194if (self->rotation > max)195self->rotation = max;196}197}198199int32 negAng = -self->rotation;200self->bodyAngle = (self->bodyAngle + 12) & 0x3FF;201202int32 x = 0x1C00 * RSDK.Sin512(negAng) + self->position.x;203int32 y = 0x1C00 * RSDK.Cos512(negAng) + self->position.y;204205int32 angle = self->bodyAngle;206207for (int32 i = 0; i < 10; i += 2) {208self->armPositions[i].x = x + 2 * RSDK.Cos512(self->rotation) * RSDK.Cos1024(angle);209self->armPositions[i].y = y + 2 * RSDK.Sin512(self->rotation) * RSDK.Cos1024(angle);210self->armAngles[i] = angle & 0x3FF;211212angle += 512;213214self->armPositions[i + 1].x = x + 2 * RSDK.Cos512(self->rotation) * RSDK.Cos1024(angle);215self->armPositions[i + 1].y = y + 2 * RSDK.Sin512(self->rotation) * RSDK.Cos1024(angle);216self->armAngles[i + 1] = angle & 0x3FF;217218x += RSDK.Sin512(negAng) << 10;219y += RSDK.Cos512(negAng) << 10;220angle += 0x240;221}222223self->rubyPos.x = self->position.x - 0x1400 * RSDK.Sin512(negAng);224self->rubyPos.y = self->position.y - 0x1400 * RSDK.Cos512(negAng);225if (self->direction) {226self->rubyPos.x -= 0x180 * RSDK.Cos512(negAng);227self->rubyPos.y -= 0x180 * RSDK.Sin512(negAng);228}229else {230self->rubyPos.x += 0x180 * RSDK.Cos512(negAng);231self->rubyPos.y += 0x180 * RSDK.Sin512(negAng);232}233}234235void PhantomKing_HandleAttacks(void)236{237RSDK_THIS(PhantomKing);238239EntityPlayer *player = Player_GetNearestPlayer();240bool32 launchedAttack = false;241242foreach_active(PKingAttack, attack)243{244if (attack->state == PKingAttack_State_Orbiting) {245PhantomRuby_PlaySfx(RSDK.Rand(RUBYSFX_ATTACK1, RUBYSFX_REDCUBE));246attack->type = PKINGATTACK_LAUNCHED;247int32 angle = RSDK.ATan2((player->position.x - attack->position.x) >> 16, (player->position.y - attack->position.y) >> 16);248249attack->targetVelocity.x = 0x600 * RSDK.Cos256(angle);250attack->targetVelocity.y = 0x600 * RSDK.Sin256(angle);251attack->drawGroup = Zone->objectDrawGroup[0];252attack->state = PKingAttack_State_OrbitLaunched;253launchedAttack = true;254foreach_break;255}256}257258if (!launchedAttack) {259// No More Attacks, lets make more260for (int32 i = 0; i < 0x3FC; i += 0xAA) {261EntityPKingAttack *attackOrb = CREATE_ENTITY(PKingAttack, INT_TO_VOID(PKINGATTACK_ORBIT), self->position.x, self->position.y);262attackOrb->angle = i;263attackOrb->target = (Entity *)self;264}265self->timer = -90;266}267}268269void PhantomKing_SwitchToEggman(void)270{271EntityKleptoMobile *eggmanPtr = NULL;272273foreach_active(KleptoMobile, eggman)274{275if (eggman->type == KLEPTOMOBILE_EGGMAN) {276EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);277278eggman->direction = FLIP_X;279if (RSDK.Rand(0, 2))280eggman->position.x = player1->position.x + 0x1000000;281else282eggman->position.x = player1->position.x - 0x1000000;283284eggman->position.y = player1->position.y + 0x800000;285eggman->originPos.y = player1->position.y + 0x800000;286eggman->holdingRuby = true;287eggman->velocity.x = 0;288eggman->velocity.y = 0;289eggman->state = KleptoMobile_State_MoveAround;290291eggmanPtr = eggman;292foreach_break;293}294}295296foreach_active(KleptoMobile, eggmanArm)297{298if (eggmanArm->type != KLEPTOMOBILE_EGGMAN) {299eggmanArm->position.x = eggmanPtr->position.x;300eggmanArm->position.y = eggmanPtr->position.y;301302for (int32 i = 0; i < 10; ++i) eggmanArm->armPositions[i] = eggmanPtr->position;303304eggmanArm->velocity.x = 0;305eggmanArm->velocity.y = 0;306}307}308}309310void PhantomKing_SetupKing(EntityPhantomKing *king)311{312king->originPos = king->position;313king->velocity.x = 0;314king->drawRuby = true;315316PhantomKing->boundsM = king->position.x;317PhantomKing->boundsL = PhantomKing->boundsM - 0x800000;318PhantomKing->boundsR = PhantomKing->boundsM + 0x800000;319PhantomKing->boundsT = (Zone->cameraBoundsT[0] + 48) << 16;320PhantomKing->boundsB = (Zone->cameraBoundsB[0] - 96) << 16;321322int32 slot = RSDK.GetEntitySlot(king);323RSDK_GET_ENTITY(slot - 1, PhantomKing)->state = PhantomKing_StateArm_Idle;324RSDK_GET_ENTITY(slot + 1, PhantomKing)->state = PhantomKing_StateArm_Idle;325king->state = PhantomKing_State_FlyAround;326}327328void PhantomKing_Draw_Body(void)329{330RSDK_THIS(PhantomKing);331332if (self->typeChangeTimer <= 0) {333if (self->invincibilityTimer & 1)334RSDK.CopyPalette(2, 128, 0, 128, 128);335}336else {337RSDK.SetLimitedFade(0, 1, 4, self->typeChangeTimer, 0, 48);338RSDK.SetLimitedFade(0, 1, 4, self->typeChangeTimer, 128, 256);339}340341RSDK.DrawSprite(&self->headAnimator, NULL, false);342RSDK.DrawSprite(&self->bodyAnimator, NULL, false);343344for (int32 i = 0; i < 10; ++i) {345if (self->armAngles[i] < 0x200) {346self->particleAnimator.frameID = self->armAngles[i] / 42 % 6;347RSDK.DrawSprite(&self->particleAnimator, &self->armPositions[i], false);348}349}350351self->drawFX = self->storeDrawFX | FX_ROTATE;352RSDK.DrawSprite(&self->beltAnimator, NULL, false);353self->drawFX = self->storeDrawFX | FX_ROTATE | FX_FLIP;354355for (int32 i = 0; i < 10; ++i) {356if (self->armAngles[i] >= 0x200) {357self->particleAnimator.frameID = self->armAngles[i] / 42 % 6;358RSDK.DrawSprite(&self->particleAnimator, &self->armPositions[i], false);359}360}361362if (self->drawRuby)363RSDK.DrawSprite(&self->rubyAnimator, &self->rubyPos, false);364365if (self->typeChangeTimer <= 0) {366if (self->invincibilityTimer & 1)367RSDK.CopyPalette(1, 128, 0, 128, 128);368}369else {370RSDK.CopyPalette(1, 0, 0, 0, 48);371RSDK.CopyPalette(1, 128, 0, 128, 128);372}373}374375void PhantomKing_Draw_Arm(void)376{377RSDK_THIS(PhantomKing);378379EntityPhantomKing *parent = self->parent;380381if (parent->typeChangeTimer > 0) {382RSDK.SetLimitedFade(0, 1, 4, parent->typeChangeTimer, 0, 48);383RSDK.SetLimitedFade(0, 1, 4, parent->typeChangeTimer, 128, 256);384}385386for (int32 i = 0; i < 6; ++i) RSDK.DrawSprite(&self->armAnimator, &self->armPositions[i], false);387388RSDK.DrawSprite(&self->cuffAnimator, &self->armPositions[6], false);389RSDK.DrawSprite(&self->handAnimator, &self->armPositions[6], false);390391if (parent->typeChangeTimer > 0) {392RSDK.CopyPalette(1, 0, 0, 0, 48);393RSDK.CopyPalette(1, 128, 0, 128, 128);394}395}396397void PhantomKing_State_Initialize(void)398{399RSDK_THIS(PhantomKing);400401if (++self->timer >= 8) {402self->position.y += 0x1000000;403self->timer = 0;404self->active = ACTIVE_NORMAL;405self->state = StateMachine_None;406}407}408409void PhantomKing_State_SetupArms(void)410{411RSDK_THIS(PhantomKing);412413self->direction = RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->position.x < self->position.x;414415if (++self->timer == 30) {416EntityPhantomKing *armL = RSDK_GET_ENTITY(SceneInfo->entitySlot - 1, PhantomKing);417RSDK.ResetEntity(armL, PhantomKing->classID, INT_TO_VOID(PHANTOMKING_ARM_L));418armL->position.x = self->position.x;419armL->position.y = self->position.y;420armL->parent = self;421armL->armRadius = 0x2800;422armL->armAngle = 96;423armL->armAngleOffset = 32;424425EntityPhantomKing *armR = RSDK_GET_ENTITY(SceneInfo->entitySlot + 1, PhantomKing);426RSDK.ResetEntity(armR, PhantomKing->classID, INT_TO_VOID(PHANTOMKING_ARM_R));427armR->position.x = self->position.x;428armR->position.y = self->position.y;429armR->parent = self;430armR->armRadius = 0x2800;431armR->armAngle = 96;432armR->armAngleOffset = 32;433434self->timer = 0;435self->visible = true;436self->stateDraw = PhantomKing_Draw_Body;437self->state = PhantomKing_State_EnterKing;438}439}440441void PhantomKing_State_EnterKing(void)442{443RSDK_THIS(PhantomKing);444445RSDK.ProcessAnimation(&self->beltAnimator);446447self->velocity.y -= 0x800;448449if (self->position.y <= self->originPos.y) {450self->originPos.x = self->position.x;451self->originPos.y = self->originPos.y;452self->position.y = self->originPos.y;453RSDK_GET_ENTITY(SceneInfo->entitySlot - 1, PhantomKing)->state = PhantomKing_StateArm_PullBack;454self->velocity.y = 0;455self->state = PhantomKing_State_InitialHover;456}457else {458self->position.y += self->velocity.y;459}460PhantomKing_HandleFrames();461}462463void PhantomKing_State_InitialHover(void)464{465RSDK_THIS(PhantomKing);466467RSDK.ProcessAnimation(&self->beltAnimator);468469PhantomKing_Oscillate();470471PhantomKing_HandleFrames();472473if (++self->timer >= 120) {474self->timer = 0;475self->state = PhantomKing_State_TakeRubyAway;476}477}478479void PhantomKing_State_TakeRubyAway(void)480{481RSDK_THIS(PhantomKing);482483RSDK.ProcessAnimation(&self->beltAnimator);484485PhantomKing_Oscillate();486487if (self->velocity.x < 0x40000)488self->velocity.x += 0x1800;489490self->position.x += self->velocity.x;491492PhantomKing_HandleFrames();493494if (++self->timer >= 180) {495RSDK_GET_ENTITY(SceneInfo->entitySlot - 1, PhantomKing)->state = PhantomKing_StateArm_Idle;496self->velocity.x = 0;497self->velocity.y = 0;498self->state = PhantomKing_State_RubyHoldHover;499self->finishedMovingRuby = true;500}501}502503void PhantomKing_State_RubyHoldHover(void)504{505RSDK_THIS(PhantomKing);506507RSDK.ProcessAnimation(&self->beltAnimator);508509PhantomKing_Oscillate();510511PhantomKing_HandleFrames();512}513514void PhantomKing_State_WrestleEggman(void)515{516RSDK_THIS(PhantomKing);517518RSDK.ProcessAnimation(&self->beltAnimator);519RSDK.ProcessAnimation(&self->rubyAnimator);520521PhantomKing_Oscillate();522523self->position.x += self->velocity.x;524self->position.y += self->velocity.y;525526PhantomKing_HandleFrames();527}528529void PhantomKing_State_FlyAround(void)530{531RSDK_THIS(PhantomKing);532533RSDK.ProcessAnimation(&self->beltAnimator);534535PhantomKing_Oscillate();536537PhantomKing_CheckPlayerCollisions();538539EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);540541int32 angle = RSDK.ATan2(self->position.x - player1->position.x, self->originPos.y - player1->position.y);542int32 x = (RSDK.Cos256(angle) << 15) + player1->position.x;543int32 y = (RSDK.Sin256(angle) << 15) + player1->position.y;544545if (x <= self->position.x) {546if (self->velocity.x > -0x20000)547self->velocity.x -= 0x800;548}549else {550if (self->velocity.x < 0x20000)551self->velocity.x += 0x800;552}553554int32 bottom = Zone->cameraBoundsB[0] << 16;555if (y > bottom - 0x400000)556y = bottom - 0x800000;557558if (y <= self->originPos.y) {559if (self->velocity.y > -0x20000)560self->velocity.y -= 0x800;561}562else {563if (self->velocity.y < 0x20000)564self->velocity.y += 0x800;565}566567self->originPos.y += self->velocity.y;568self->position.x += self->velocity.x;569self->direction = player1->position.x <= self->position.x;570571if (self->canLaunchAttacks) {572if (++self->timer >= 60) {573self->timer = 0;574PhantomKing_HandleAttacks();575}576}577else if (self->onScreen == 1) {578self->canLaunchAttacks = true;579}580581PhantomKing_HandleFrames();582}583584void PhantomKing_State_Switch(void)585{586RSDK_THIS(PhantomKing);587588if (++self->timer >= 120) {589self->timer = 0;590PhantomKing_SwitchToEggman();591self->state = StateMachine_None;592}593}594595void PhantomKing_State_HitFall(void)596{597RSDK_THIS(PhantomKing);598599RSDK.ProcessAnimation(&self->beltAnimator);600601self->position.y += self->velocity.y;602self->velocity.y -= 0x3800;603604if (self->position.y < -0x1000000) {605foreach_active(PKingAttack, attack)606{607if (attack->state == PKingAttack_State_Orbiting)608destroyEntity(attack);609}610611self->canLaunchAttacks = false;612self->velocity.y = 0;613self->timer = 0;614self->state = PhantomKing_State_Switch;615}616617PhantomKing_HandleFrames();618}619620void PhantomKing_StateArm_Idle(void)621{622RSDK_THIS(PhantomKing);623624EntityPhantomKing *parent = self->parent;625626int32 parentX = parent->position.x;627int32 parentY = parent->position.y;628629int32 moveX = 0;630int32 moveY = ((RSDK.Sin256(2 * (Zone->timer + (self->type << 6)) - 128) + 512) << 12) + parentY;631632self->direction = parent->direction;633int32 negAngle = -parent->rotation;634635int32 x = 0;636int32 y = 0;637638int32 x2 = 0;639int32 y2 = 0;640641if (self->direction) {642moveX = parentX - 0x300000;643x = 0xD00 * RSDK.Cos512(negAngle) + 0x300 * RSDK.Sin512(negAngle) + parent->position.x;644y = parent->position.y - 0xD00 * RSDK.Sin512(negAngle) + 0x300 * RSDK.Cos512(negAngle);645646if (self->type == PHANTOMKING_ARM_L) {647x += -0x1800 * RSDK.Cos512(negAngle);648y += 0x1800 * RSDK.Sin512(negAngle);649moveX -= 0x300000;650}651652x2 = ((self->position.x + x) >> 1) + 0x200000;653y2 = ((self->position.y + y) >> 1) + 0x200000;654}655else {656moveX = parentX + 0x300000;657x = 0x300 * RSDK.Sin512(negAngle) - 0xD00 * RSDK.Cos512(negAngle) + parent->position.x;658y = 0xD00 * RSDK.Sin512(negAngle) + 0x300 * RSDK.Cos512(negAngle) + parent->position.y;659660if (self->type == PHANTOMKING_ARM_L) {661x += 0x1800 * RSDK.Cos512(negAngle);662y += -0x1800 * RSDK.Sin512(negAngle);663moveX += 0x300000;664}665666x2 = ((self->position.x + x) >> 1) - 0x100000;667y2 = ((self->position.y + y) >> 1) + 0x100000;668}669670self->velocity.x += ((moveX - self->position.x) >> 5) - (self->velocity.x >> 3);671self->velocity.y += ((moveY - self->position.y) >> 5) - (self->velocity.y >> 3);672self->position.x += self->velocity.x;673self->position.y += self->velocity.y;674675int32 percent = 0x1800;676for (int32 i = 0; i < 7; ++i) {677self->armPositions[i] = MathHelpers_GetBezierPoint(percent, x, y, x2, y2, x2, y2, self->position.x, self->position.y);678percent += 0x2000;679}680681RSDK.ProcessAnimation(&self->cuffAnimator);682RSDK.ProcessAnimation(&self->handAnimator);683}684685void PhantomKing_StateArm_WrestleEggman(void)686{687RSDK_THIS(PhantomKing);688689EntityPhantomKing *parent = self->parent;690691self->direction = parent->direction;692int32 negAngle = -parent->rotation;693694int32 x = 0;695int32 y = 0;696697if (self->direction) {698x = parent->position.x + 0xD00 * RSDK.Cos512(negAngle) + 0x300 * RSDK.Sin512(negAngle);699y = parent->position.y - 0xD00 * RSDK.Sin512(negAngle) + 0x300 * RSDK.Cos512(negAngle);700701if (self->type == PHANTOMKING_ARM_L) {702x += -0x1800 * RSDK.Cos512(negAngle);703y += 0x1800 * RSDK.Sin512(negAngle);704}705}706else {707x = 0x300 * RSDK.Sin512(negAngle) - 0xD00 * RSDK.Cos512(negAngle) + parent->position.x;708y = 0xD00 * RSDK.Sin512(negAngle) + 0x300 * RSDK.Cos512(negAngle) + parent->position.y;709710if (self->type == PHANTOMKING_ARM_L) {711x += 0x1800 * RSDK.Cos512(negAngle);712y += -0x1800 * RSDK.Sin512(negAngle);713}714}715716int32 percent = 0x1800;717for (int32 i = 0; i < 7; ++i) {718self->armPositions[i] = MathHelpers_GetBezierPoint(percent, x, y, self->armBezierPos.x, self->armBezierPos.y, self->armBezierPos.x,719self->armBezierPos.y, self->position.x, self->position.y);720percent += 0x2000;721}722723RSDK.ProcessAnimation(&self->cuffAnimator);724RSDK.ProcessAnimation(&self->handAnimator);725}726727void PhantomKing_HandleArmMovement(void)728{729RSDK_THIS(PhantomKing);730731EntityPhantomKing *parent = self->parent;732733RSDK.Sin256(2 * (Zone->timer + (self->type << 6)) - 128);734++self->timer;735self->direction = parent->direction;736int32 negAngle = -parent->rotation;737738int32 x = 0;739int32 y = 0;740741int32 x2 = 0;742int32 y2 = 0;743744int32 x3 = 0;745int32 y3 = 0;746747if (self->direction) {748x = parent->position.x + 0xD00 * RSDK.Cos512(negAngle) + 0x300 * RSDK.Sin512(negAngle);749y = parent->position.y - 0xD00 * RSDK.Sin512(negAngle) + 0x300 * RSDK.Cos512(negAngle);750751if (self->type == PHANTOMKING_ARM_L) {752x += -0x1800 * RSDK.Cos512(negAngle);753y += 0x1800 * RSDK.Sin512(negAngle);754}755756x2 = x + self->armRadius * RSDK.Cos256(self->armAngle);757y2 = y + self->armRadius * RSDK.Sin256(self->armAngle);758x3 = x2 + self->armRadius * RSDK.Cos256(self->armAngleOffset + self->armAngle);759y3 = y2 + self->armRadius * RSDK.Sin256(self->armAngleOffset + self->armAngle);760}761else {762x = 0x300 * RSDK.Sin512(negAngle) - 0xD00 * RSDK.Cos512(negAngle) + parent->position.x;763y = 0xD00 * RSDK.Sin512(negAngle) + 0x300 * RSDK.Cos512(negAngle) + parent->position.y;764765if (self->type == PHANTOMKING_ARM_L) {766x += 0x1800 * RSDK.Cos512(negAngle);767y += -0x1800 * RSDK.Sin512(negAngle);768}769770x2 = x + self->armRadius * RSDK.Cos256(self->armAngle);771y2 = y + self->armRadius * RSDK.Sin256(self->armAngle);772x3 = x2 + self->armRadius * RSDK.Cos256(self->armAngleOffset + self->armAngle);773y3 = y2 + self->armRadius * RSDK.Sin256(self->armAngleOffset + self->armAngle);774}775776self->velocity.x += ((x3 - self->position.x) >> 5) - (self->velocity.x >> 3);777self->velocity.y += ((y3 - self->position.y) >> 5) - (self->velocity.y >> 3);778self->position.x += self->velocity.x;779self->position.y += self->velocity.y;780781int32 percent = 0x1800;782for (int32 i = 0; i < 7; ++i) {783self->armPositions[i] = MathHelpers_GetBezierPoint(percent, x, y, x2, y2, x2, y2, x3, y3);784percent += 0x2000;785}786787RSDK.ProcessAnimation(&self->cuffAnimator);788RSDK.ProcessAnimation(&self->handAnimator);789}790791void PhantomKing_StateArm_PullBack(void)792{793RSDK_THIS(PhantomKing);794795PhantomKing_HandleArmMovement();796797uint8 armFinished = 0;798799if (self->armAngle >= 0xC0)800armFinished = 1;801else802self->armAngle += 3;803804if (self->armAngleOffset >= 0x60)805++armFinished;806else807self->armAngleOffset += 3;808809if (armFinished == 2)810self->state = PhantomKing_StateArm_Point;811}812813void PhantomKing_StateArm_Point(void)814{815RSDK_THIS(PhantomKing);816817PhantomKing_HandleArmMovement();818819if (self->armAngle <= 0x80)820self->armAngle = 0x80;821else822self->armAngle -= 0x10;823824if (self->armAngleOffset <= 0x00)825self->armAngleOffset = 0x00;826else827self->armAngleOffset -= 0x10;828}829830void PhantomKing_DestroyEntity(void)831{832RSDK_THIS(PhantomKing);833834int32 slot = RSDK.GetEntitySlot(self);835EntityPhantomKing *armL = RSDK_GET_ENTITY(slot - 1, PhantomKing);836EntityPhantomKing *armR = RSDK_GET_ENTITY(slot + 1, PhantomKing);837838foreach_all(PKingAttack, attack) { destroyEntity(attack); }839840destroyEntity(armL);841destroyEntity(armR);842destroyEntity(self);843}844845void PhantomKing_State_Explode(void)846{847RSDK_THIS(PhantomKing);848849PhantomKing_Explode();850851if (++self->timer == 60)852self->state = PhantomKing_State_Destroyed;853}854855void PhantomKing_State_Destroyed(void)856{857RSDK_THIS(PhantomKing);858859self->velocity.y += 0x2800;860self->position.y += self->velocity.y;861862PhantomKing_Explode();863864if (self->position.y >= 0x2800000) {865PhantomKing->defeated = true;866867if (!KleptoMobile->defeated) {868PhantomKing_SwitchToEggman();869}870else {871foreach_all(ERZOutro, outro)872{873outro->active = ACTIVE_NORMAL;874foreach_break;875}876}877878PhantomKing_DestroyEntity();879}880881PhantomKing_HandleFrames();882}883884#if GAME_INCLUDE_EDITOR885void PhantomKing_EditorDraw(void)886{887RSDK_THIS(PhantomKing);888889self->originPos = self->position;890self->rotation = 0;891self->bodyAngle = 0;892self->bodyAnimator.speed = 0;893PhantomKing_HandleFrames();894895RSDK.SetSpriteAnimation(PhantomKing->aniFrames, 0, &self->headAnimator, false, 0);896RSDK.SetSpriteAnimation(PhantomKing->aniFrames, 1, &self->bodyAnimator, false, 0);897RSDK.SetSpriteAnimation(PhantomKing->aniFrames, 2, &self->beltAnimator, false, 0);898RSDK.SetSpriteAnimation(PhantomKing->aniFrames, 7, &self->particleAnimator, false, 0);899RSDK.SetSpriteAnimation(PhantomKing->aniFrames, 8, &self->rubyAnimator, false, 0);900901PhantomKing_Draw_Body();902}903904void PhantomKing_EditorLoad(void)905{906PhantomKing->aniFrames = RSDK.LoadSpriteAnimation("Phantom/PhantomKing.bin", SCOPE_STAGE);907908RSDK_ACTIVE_VAR(PhantomKing, type);909RSDK_ENUM_VAR("King", PHANTOMKING_KING);910}911#endif912913void PhantomKing_Serialize(void) { RSDK_EDITABLE_VAR(PhantomKing, VAR_ENUM, type); }914915916