Path: blob/master/SonicMania/Objects/TMZ/SentryBug.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: SentryBug Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectSentryBug *SentryBug;1011void SentryBug_Update(void)12{13RSDK_THIS(SentryBug);1415RSDK.ProcessAnimation(&self->bugAnimator);1617StateMachine_Run(self->state);18StateMachine_Run(self->stateOrbs);19}2021void SentryBug_LateUpdate(void) {}2223void SentryBug_StaticUpdate(void) {}2425void SentryBug_Draw(void)26{27RSDK_THIS(SentryBug);2829if (self->orbsDetached) {30RSDK.DrawSprite(&self->bugAnimator, NULL, false);3132if (self->showNet) {33RSDK.MatrixScaleXYZ(&self->matTransform, self->netScale >> 4, self->netScale >> 4, self->netScale >> 4);34RSDK.MatrixTranslateXYZ(&self->matTransform, self->netPos.x, self->netPos.y, 0, false);35RSDK.MatrixRotateXYZ(&self->matWorld, self->netRotation, self->netRotation, 0);36RSDK.MatrixMultiply(&self->matWorld, &self->matWorld, &self->matTransform);3738RSDK.Prepare3DScene(SentryBug->sceneIndex);39RSDK.AddModelTo3DScene(SentryBug->meshFrames, SentryBug->sceneIndex, S3D_WIREFRAME, &self->matWorld, NULL, self->netColor);4041self->inkEffect = INK_ALPHA;42RSDK.Draw3DScene(SentryBug->sceneIndex);43self->inkEffect = INK_NONE;44}4546for (int32 angle = 0, i = 0; angle < 0xFC; ++i) {47self->orbAnimator.frameID = ((angle + self->netRotation + 8) >> 5) & 7;48if (self->netColor == 0xF0F000)49self->orbAnimator.frameID += 8;5051RSDK.DrawSprite(&self->orbAnimator, &self->orbPositions[i], false);5253angle += 42;54}55}56else {57RSDK.DrawSprite(&self->orbAnimator, &self->orbPositions[0], false);58RSDK.DrawSprite(&self->orbAnimator, &self->orbPositions[1], false);59RSDK.DrawSprite(&self->orbAnimator, &self->orbPositions[2], false);6061RSDK.DrawSprite(&self->bugAnimator, NULL, false);6263RSDK.DrawSprite(&self->orbAnimator, &self->orbPositions[3], false);64RSDK.DrawSprite(&self->orbAnimator, &self->orbPositions[4], false);65RSDK.DrawSprite(&self->orbAnimator, &self->orbPositions[5], false);66}67}6869void SentryBug_Create(void *data)70{71RSDK_THIS(SentryBug);7273self->drawFX = FX_FLIP;74if (!SceneInfo->inEditor) {75self->active = ACTIVE_BOUNDS;76self->updateRange.x = 0x800000;77self->updateRange.y = 0x800000;78self->visible = true;79self->drawGroup = Zone->objectDrawGroup[0];80self->amplitude.x >>= 10;81self->amplitude.y >>= 10;82self->originPos = self->position;83self->startPos = self->position;84self->netColor = 0xF02000;85self->alpha = 0x100;8687if (!self->speed)88self->speed = 4;8990if (self->amplitude.x >= 0)91RSDK.SetSpriteAnimation(SentryBug->aniFrames, 1, &self->bugAnimator, true, 6);92else93RSDK.SetSpriteAnimation(SentryBug->aniFrames, 0, &self->bugAnimator, true, 6);9495RSDK.SetSpriteAnimation(SentryBug->aniFrames, 2, &self->orbAnimator, true, 0);9697self->state = SentryBug_State_AwaitPlayer;98self->stateOrbs = SentryBug_StateOrbs_Attached;99}100}101102void SentryBug_StageLoad(void)103{104if (RSDK.CheckSceneFolder("TMZ1") || RSDK.CheckSceneFolder("TMZ2"))105SentryBug->aniFrames = RSDK.LoadSpriteAnimation("TMZ1/SentryBug.bin", SCOPE_STAGE);106107SentryBug->meshFrames = RSDK.LoadMesh("TMZ/OrbNet.bin", SCOPE_STAGE);108SentryBug->sceneIndex = RSDK.Create3DScene("View:SentryBug", 512, SCOPE_STAGE);109110SentryBug->hitbox.left = -12;111SentryBug->hitbox.top = -12;112SentryBug->hitbox.right = 12;113SentryBug->hitbox.bottom = 12;114115SentryBug->sfxPon = RSDK.GetSfx("Stage/Pon.wav");116SentryBug->sfxSwarm = RSDK.GetSfx("TMZ1/CyberSwarm.wav");117118DEBUGMODE_ADD_OBJ(SentryBug);119}120121void SentryBug_DebugSpawn(void)122{123RSDK_THIS(SentryBug);124125EntitySentryBug *sentryBug = CREATE_ENTITY(SentryBug, NULL, self->position.x, self->position.y);126sentryBug->amplitude.x = 0x1200;127sentryBug->amplitude.y = 0x400;128sentryBug->timer = 60;129}130131void SentryBug_DebugDraw(void)132{133RSDK.SetSpriteAnimation(SentryBug->aniFrames, 0, &DebugMode->animator, true, 0);134RSDK.DrawSprite(&DebugMode->animator, NULL, false);135}136137void SentryBug_CheckPlayerCollisions(void)138{139RSDK_THIS(SentryBug);140141foreach_active(Player, player)142{143if (Player_CheckBadnikTouch(player, self, &SentryBug->hitbox)) {144if (Player_CheckBadnikBreak(player, self, true))145RSDK.StopSfx(SentryBug->sfxSwarm);146}147}148}149150void SentryBug_SetupOrbDropVelocity(void)151{152RSDK_THIS(SentryBug);153154Vector2 *velocity = NULL;155if (self->bugAnimator.animationID == 1)156velocity = (Vector2 *)SentryBug->dropVelR;157else158velocity = (Vector2 *)SentryBug->dropVelL;159160for (int32 i = 0; i < 6; ++i) {161self->orbVelocities[i].x = velocity[i].x;162self->orbVelocities[i].y = velocity[i].y;163}164}165166void SentryBug_StateOrbs_Attached(void)167{168RSDK_THIS(SentryBug);169170Vector2 *offsets = NULL;171if (self->bugAnimator.animationID == 1)172offsets = (Vector2 *)&SentryBug->orbOffsets_Attached[12 * self->bugAnimator.frameID];173else174offsets = (Vector2 *)&SentryBug->orbOffsets_Attached[-12 * self->bugAnimator.frameID + 72];175176for (int32 i = 0; i < 6; ++i) {177self->orbPositions[i].x = self->position.x + offsets[i].x;178self->orbPositions[i].y = self->position.y + offsets[i].y;179}180}181182void SentryBug_StateOrbs_Dropped(void)183{184RSDK_THIS(SentryBug);185186for (int32 i = 0; i < 6; ++i) {187self->orbVelocities[i].y += 0x2800;188self->orbPositions[i].x += self->orbVelocities[i].x;189self->orbPositions[i].y += self->orbVelocities[i].y;190}191}192193void SentryBug_StateOrbs_BeginNetRotation(void)194{195RSDK_THIS(SentryBug);196197int32 angle = self->netRotation;198for (int32 i = 0; i < 6; ++i) {199int32 x = self->netScale * RSDK.Cos256(angle) + self->netPos.x;200int32 y = self->netScale * RSDK.Sin256(angle) + self->netPos.y;201202self->orbVelocities[i].x = (x - self->orbPositions[i].x) >> 3;203self->orbVelocities[i].y = (y - self->orbPositions[i].y) >> 3;204self->orbPositions[i].x += self->orbVelocities[i].x;205self->orbPositions[i].y += self->orbVelocities[i].y;206angle += 42;207}208209self->netRotation += 4;210}211212void SentryBug_StateOrbs_RotateAroundNet(void)213{214RSDK_THIS(SentryBug);215216int32 angle = self->netRotation;217for (int32 i = 0; i < 6; ++i) {218self->orbPositions[i].x = self->netScale * RSDK.Cos256(angle) + self->netPos.x;219self->orbPositions[i].y = self->netScale * RSDK.Sin256(angle) + self->netPos.y;220angle += 42;221}222223self->netRotation += 4;224}225226void SentryBug_StateOrbs_ReturnToSlots(void)227{228RSDK_THIS(SentryBug);229230Vector2 *offsets = NULL;231if (self->bugAnimator.animationID == 1)232offsets = (Vector2 *)&SentryBug->orbOffsets_Attached[12 * self->bugAnimator.frameID];233else234offsets = (Vector2 *)&SentryBug->orbOffsets_Attached[-12 * self->bugAnimator.frameID + 72];235236for (int32 i = 0; i < 6; ++i) {237self->orbVelocities[i].x = CLAMP((self->position.x + offsets[i].x - self->orbPositions[i].x) >> 3, -0xC0000, 0xC0000);238self->orbVelocities[i].y = CLAMP((self->position.y + offsets[i].y - self->orbPositions[i].y) >> 3, -0xC0000, 0xC0000);239240self->orbPositions[i].x += self->orbVelocities[i].x;241self->orbPositions[i].y += self->orbVelocities[i].y;242}243}244245void SentryBug_State_AwaitPlayer(void)246{247RSDK_THIS(SentryBug);248249int32 x = self->position.x;250251self->angle = (self->angle + self->speed) & 0x3FF;252self->position.x = self->amplitude.x * RSDK.Sin1024(self->angle) + self->originPos.x;253self->position.y = self->amplitude.y * RSDK.Sin1024(2 * self->angle) + self->originPos.y;254RSDK.SetSpriteAnimation(SentryBug->aniFrames, (x - self->position.x) < 0, &self->bugAnimator, false, 0);255256if (self->timer > 0)257self->timer--;258259EntityPlayer *player = Player_GetNearestPlayer();260if (player) {261if (!self->timer) {262int32 rx = (self->position.x - player->position.x) >> 16;263int32 ry = (self->position.y - player->position.y) >> 16;264265if (rx * rx + ry * ry < 0x2400) {266self->originPos.x = self->position.x;267self->originPos.y = self->position.y;268self->angle = 0;269self->playerPtr = player;270self->netScale = 0x6800;271self->drawGroup = Zone->objectDrawGroup[1];272self->active = ACTIVE_NORMAL;273274RSDK.PlaySfx(SentryBug->sfxPon, false, 255);275276SentryBug_SetupOrbDropVelocity();277self->stateOrbs = SentryBug_StateOrbs_Dropped;278279RSDK.PlaySfx(SentryBug->sfxSwarm, false, 255);280self->state = SentryBug_State_DropOrbs;281}282}283}284285SentryBug_CheckPlayerCollisions();286}287288void SentryBug_State_DropOrbs(void)289{290RSDK_THIS(SentryBug);291292EntityPlayer *player = self->playerPtr;293294self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 4, 10);295296self->netPos.x = player->position.x;297self->netPos.y = player->position.y;298299if (++self->timer == 120) {300self->timer = 0;301self->netScale = 0x6000;302self->stateOrbs = SentryBug_StateOrbs_RotateAroundNet;303self->showNet = true;304self->state = SentryBug_State_NetAppear;305}306307if (self->timer == 30) {308self->orbsDetached = true;309self->stateOrbs = SentryBug_StateOrbs_BeginNetRotation;310}311312SentryBug_CheckPlayerCollisions();313}314315void SentryBug_State_NetAppear(void)316{317RSDK_THIS(SentryBug);318319EntityPlayer *player = self->playerPtr;320321self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 4, 10);322323self->netPos.x += (player->position.x - self->netPos.x) >> 3;324self->netPos.y += (player->position.y - self->netPos.y) >> 3;325SentryBug_CheckPlayerCollisions();326327self->alpha = 0xA0 + (RSDK.Sin256(4 * Zone->timer) >> 2);328329if (++self->timer == 60) {330self->timer = 0;331self->state = SentryBug_State_NetShrink;332}333}334335void SentryBug_State_NetShrink(void)336{337RSDK_THIS(SentryBug);338339EntityPlayer *player = self->playerPtr;340341self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 4, 10);342343self->netPos.x += (player->position.x - self->netPos.x) >> 3;344self->netPos.y += ((player->position.y - self->netPos.y) >> 3);345346int32 rx = (self->netPos.x - self->position.x) >> 16;347int32 ry = (self->netPos.y - self->position.y) >> 16;348349self->alpha = 0xA0 + (RSDK.Sin256(4 * Zone->timer) >> 2);350351if (rx * rx + ry * ry <= 0x40000) {352if (self->netScale <= 0x1800) {353rx = (self->netPos.x - player->position.x) >> 16;354ry = (self->netPos.y - player->position.y) >> 16;355356if (rx * rx + ry * ry < 0x200 && Player_CheckValidState(player)) {357self->showNet = true;358self->alpha = 0x100;359self->state = SentryBug_State_NetFlash;360self->isPermanent = true;361}362else {363self->orbAnimator.frameID = 0;364self->orbsDetached = false;365self->stateOrbs = SentryBug_StateOrbs_ReturnToSlots;366self->state = SentryBug_State_ReturnToSlots;367RSDK.StopSfx(SentryBug->sfxSwarm);368}369}370else {371self->netScale -= 0x80;372}373374SentryBug_CheckPlayerCollisions();375}376else {377self->orbAnimator.frameID = 0;378self->orbsDetached = false;379380self->stateOrbs = SentryBug_StateOrbs_ReturnToSlots;381self->state = SentryBug_State_ReturnToSlots;382383RSDK.StopSfx(SentryBug->sfxSwarm);384}385}386387void SentryBug_State_NetFlash(void)388{389RSDK_THIS(SentryBug);390391EntityPlayer *player = self->playerPtr;392393self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 4, 10);394395self->netPos.x = player->position.x;396self->netPos.y = player->position.y;397398player->groundVel >>= 2;399player->velocity.x >>= 2;400player->velocity.y >>= 2;401402self->netColor = (Zone->timer & 2) ? 0xF0F000 : 0xF02000;403404if (++self->timer == 30) {405self->timer = 0;406Player_Hurt(player, self);407408self->orbAnimator.frameID = 0;409self->netColor = 0xF02000;410self->orbsDetached = false;411self->stateOrbs = SentryBug_StateOrbs_ReturnToSlots;412self->state = SentryBug_State_ReturnToSlots;413414RSDK.StopSfx(SentryBug->sfxSwarm);415self->isPermanent = false;416}417418SentryBug_CheckPlayerCollisions();419}420421void SentryBug_State_ReturnToSlots(void)422{423RSDK_THIS(SentryBug);424425if (self->alpha > 0)426self->alpha -= 0x40;427428self->velocity.x = (self->startPos.x - self->position.x) >> 4;429self->velocity.y = (self->startPos.y - self->position.y) >> 4;430431RSDK.SetSpriteAnimation(SentryBug->aniFrames, self->velocity.x > 0, &self->bugAnimator, false, 0);432433self->position.x += self->velocity.x;434self->position.y += self->velocity.y;435436if (++self->timer == 60) {437self->originPos.x = self->startPos.x;438self->originPos.y = self->startPos.y;439self->angle = 0;440self->timer = 60;441self->active = ACTIVE_BOUNDS;442self->drawGroup = Zone->objectDrawGroup[0];443self->stateOrbs = SentryBug_StateOrbs_Attached;444self->state = SentryBug_State_AwaitPlayer;445}446447SentryBug_CheckPlayerCollisions();448}449450#if GAME_INCLUDE_EDITOR451void SentryBug_EditorDraw(void)452{453RSDK_THIS(SentryBug);454455if (!self->speed)456self->speed = 4;457458self->originPos = self->position;459self->startPos = self->position;460461if (self->amplitude.x >= 0)462RSDK.SetSpriteAnimation(SentryBug->aniFrames, 1, &self->bugAnimator, true, 6);463else464RSDK.SetSpriteAnimation(SentryBug->aniFrames, 0, &self->bugAnimator, true, 6);465466RSDK.SetSpriteAnimation(SentryBug->aniFrames, 2, &self->orbAnimator, true, 0);467468RSDK.DrawSprite(&self->bugAnimator, NULL, false);469}470471void SentryBug_EditorLoad(void) { SentryBug->aniFrames = RSDK.LoadSpriteAnimation("TMZ1/SentryBug.bin", SCOPE_STAGE); }472#endif473474void SentryBug_Serialize(void)475{476RSDK_EDITABLE_VAR(SentryBug, VAR_UINT8, speed);477RSDK_EDITABLE_VAR(SentryBug, VAR_VECTOR2, amplitude);478}479480481