Path: blob/master/SonicMania/Objects/HCZ/Jellygnite.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Jellygnite Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectJellygnite *Jellygnite;1011void Jellygnite_Update(void)12{13RSDK_THIS(Jellygnite);1415RSDK.ProcessAnimation(&self->bodyAnimator);16RSDK.ProcessAnimation(&self->backTentacleAnimator);17RSDK.ProcessAnimation(&self->frontTentacleAnimator);1819StateMachine_Run(self->state);2021if (self->state != Jellygnite_State_Init && self->classID == Jellygnite->classID) {22if (self->grabDelay > 0)23self->grabDelay--;2425Jellygnite_CheckPlayerCollisions();2627if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {28self->position = self->startPos;29self->direction = self->startDir;30self->visible = false;31self->timer = 0;32self->angle = 0;33self->frontTentacleAngle = 0;34self->oscillateAngle = 0;35self->grabbedPlayer = 0;36self->shakeTimer = 0;37self->shakeCount = 0;38self->lastShakeFlags = 0;3940Jellygnite_Create(NULL);41}42}43}4445void Jellygnite_LateUpdate(void) {}4647void Jellygnite_StaticUpdate(void)48{49foreach_active(Jellygnite, jellygnite) { RSDK.AddDrawListRef(Zone->objectDrawGroup[1], RSDK.GetEntitySlot(jellygnite)); }50}5152void Jellygnite_Draw(void)53{54RSDK_THIS(Jellygnite);5556Jellygnite_DrawBackTentacle();57Jellygnite_DrawFrontTentacle();5859RSDK.DrawSprite(&self->bodyAnimator, NULL, false);60}6162void Jellygnite_Create(void *data)63{64RSDK_THIS(Jellygnite);65self->visible = true;66self->drawGroup = Zone->objectDrawGroup[0];67self->startPos = self->position;68self->startDir = self->direction;69self->drawFX = FX_FLIP;70self->active = ACTIVE_BOUNDS;71self->updateRange.x = 0x800000;72self->updateRange.y = 0x800000;73self->state = Jellygnite_State_Init;74}7576void Jellygnite_StageLoad(void)77{78if (RSDK.CheckSceneFolder("HPZ"))79Jellygnite->aniFrames = RSDK.LoadSpriteAnimation("HPZ/Jellygnite.bin", SCOPE_STAGE);80else if (RSDK.CheckSceneFolder("HCZ"))81Jellygnite->aniFrames = RSDK.LoadSpriteAnimation("HCZ/Jellygnite.bin", SCOPE_STAGE);8283Jellygnite->hitbox.left = -14;84Jellygnite->hitbox.top = -14;85Jellygnite->hitbox.right = 14;86Jellygnite->hitbox.bottom = 14;8788Jellygnite->sfxGrab = RSDK.GetSfx("Global/Grab.wav");89Jellygnite->sfxElectrify = RSDK.GetSfx("Stage/Electrify2.wav");9091DEBUGMODE_ADD_OBJ(Jellygnite);92}9394void Jellygnite_DebugSpawn(void)95{96RSDK_THIS(Jellygnite);9798EntityJellygnite *jellygnite = CREATE_ENTITY(Jellygnite, NULL, self->position.x, self->position.y);99jellygnite->direction = self->direction;100jellygnite->startDir = self->direction;101}102103void Jellygnite_DebugDraw(void)104{105RSDK.SetSpriteAnimation(Jellygnite->aniFrames, 0, &DebugMode->animator, true, 0);106RSDK.DrawSprite(&DebugMode->animator, NULL, false);107}108109void Jellygnite_SetupAnimations(uint8 animationID)110{111RSDK_THIS(Jellygnite);112113switch (animationID) {114case JELLYGNITE_ANI_FLOATING:115RSDK.SetSpriteAnimation(Jellygnite->aniFrames, 0, &self->bodyAnimator, true, 0);116RSDK.SetSpriteAnimation(Jellygnite->aniFrames, 3, &self->frontTentacleAnimator, true, 0);117RSDK.SetSpriteAnimation(Jellygnite->aniFrames, 5, &self->backTentacleAnimator, true, 0);118break;119120case JELLYGNITE_ANI_ANGRY:121RSDK.SetSpriteAnimation(Jellygnite->aniFrames, 1, &self->bodyAnimator, true, 0);122RSDK.SetSpriteAnimation(Jellygnite->aniFrames, 3, &self->frontTentacleAnimator, true, 0);123RSDK.SetSpriteAnimation(Jellygnite->aniFrames, 5, &self->backTentacleAnimator, true, 0);124break;125126case JELLYGNITE_ANI_FLASHING:127RSDK.SetSpriteAnimation(Jellygnite->aniFrames, 2, &self->bodyAnimator, true, 0);128RSDK.SetSpriteAnimation(Jellygnite->aniFrames, 4, &self->frontTentacleAnimator, true, 0);129RSDK.SetSpriteAnimation(Jellygnite->aniFrames, 6, &self->backTentacleAnimator, true, 0);130break;131}132133self->prevAnimationID = animationID;134}135136void Jellygnite_CheckPlayerCollisions(void)137{138RSDK_THIS(Jellygnite);139140foreach_active(Player, player)141{142if (player != self->grabbedPlayer) {143if (Player_CheckCollisionTouch(player, self, &Jellygnite->hitbox) && self->state == Jellygnite_State_Swimming144&& player->position.y >= self->position.y) {145146self->state = Jellygnite_State_GrabbedPlayer;147Jellygnite_SetupAnimations(JELLYGNITE_ANI_ANGRY);148self->grabbedPlayer = player;149150if (Water) {151EntityWater *bubble = Water_GetPlayerBubble(player);152if (bubble) {153bubble->timer = 0;154Water_PopBigBubble(bubble, false);155}156}157158self->isPermanent = true;159RSDK.PlaySfx(Jellygnite->sfxGrab, false, 255);160player->velocity.x = 0;161player->velocity.y = 0;162player->groundVel = 0;163player->state = Player_State_Static;164player->nextAirState = StateMachine_None;165player->nextGroundState = StateMachine_None;166player->onGround = false;167player->direction = self->direction;168RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, true, 0);169player->animator.speed = 0;170player->direction = self->direction ^ FLIP_X;171}172173if (player != self->grabbedPlayer && player->position.y < self->position.y && Player_CheckBadnikTouch(player, self, &Jellygnite->hitbox)174&& Player_CheckBadnikBreak(player, self, false)) {175if (self->grabbedPlayer)176self->grabbedPlayer->state = Player_State_Air;177178destroyEntity(self);179}180}181}182}183184void Jellygnite_HandlePlayerStruggle(void)185{186RSDK_THIS(Jellygnite);187188EntityPlayer *player = self->grabbedPlayer;189190if (player) {191if (self->lastShakeFlags) {192if (!--self->shakeTimer) {193self->shakeCount = 0;194self->lastShakeFlags = 0;195}196197uint8 shakeFlags = 0;198if (player->left)199shakeFlags = 1;200if (player->right)201shakeFlags |= 2;202203if (shakeFlags && shakeFlags != 3 && shakeFlags != self->lastShakeFlags) {204self->lastShakeFlags = shakeFlags;205if (++self->shakeCount >= 4) {206player->state = Player_State_Air;207self->grabDelay = 16;208self->grabbedPlayer = NULL;209}210else {211self->shakeTimer = 64;212}213}214}215else {216if (player->left) {217self->lastShakeFlags = 1;218self->shakeTimer = 32;219}220221if (player->right) {222self->lastShakeFlags |= 2;223self->shakeTimer = 32;224}225}226227player->position.x = self->position.x;228player->position.y = self->position.y + 0xC0000;229}230}231232bool32 Jellygnite_CheckInWater(EntityPlayer *player)233{234RSDK_THIS(Jellygnite);235236if (player->position.y > Water->waterLevel)237return true;238239foreach_active(Water, water)240{241if (water->type == WATER_POOL) {242if (Player_CheckCollisionTouch(player, self, &water->hitbox)243&& RSDK.CheckObjectCollisionTouchBox(self, &Jellygnite->hitbox, water, &water->hitbox)) {244return true;245}246}247}248return false;249}250251void Jellygnite_DrawBackTentacle(void)252{253RSDK_THIS(Jellygnite);254255int32 angle = self->angle & 0x1FF;256int32 y = self->position.y + 0x70000;257258for (int32 i = 0; i < 4; ++i) {259Vector2 drawPos;260drawPos.x = self->position.x + (RSDK.Cos512(angle) << 9);261drawPos.y = y + (RSDK.Sin512(angle) << 8);262RSDK.DrawSprite(&self->backTentacleAnimator, &drawPos, false);263264angle = (angle + 0x20) & 0x1FF;265y += 0x60000;266}267}268269void Jellygnite_DrawFrontTentacle(void)270{271RSDK_THIS(Jellygnite);272273int32 x = 0;274int32 y = 0;275int32 ang = self->frontTentacleAngle;276for (int32 i = 0; i < 4; ++i) {277int32 angle = (ang >> 7) & 0x1FF;278x += 0x312 * RSDK.Sin512(angle);279y += 0x312 * RSDK.Cos512(angle);280281Vector2 drawPos;282drawPos.x = x + self->position.x - 0xD0000;283drawPos.y = y + self->position.y + 0x10000;284RSDK.DrawSprite(&self->frontTentacleAnimator, &drawPos, false);285286drawPos.x = -x;287drawPos.x = self->position.x + 0xD0000 - x;288RSDK.DrawSprite(&self->frontTentacleAnimator, &drawPos, false);289290ang <<= 1;291}292}293294void Jellygnite_State_Init(void)295{296RSDK_THIS(Jellygnite);297298if (self->position.y >= Water->waterLevel) {299self->active = ACTIVE_NORMAL;300self->timer = 0;301self->angle = 0;302self->frontTentacleAngle = 0;303self->oscillateAngle = 0;304self->grabbedPlayer = 0;305self->shakeTimer = 0;306self->shakeCount = 0;307self->lastShakeFlags = 0;308Jellygnite_SetupAnimations(JELLYGNITE_ANI_FLOATING);309310self->state = Jellygnite_State_Swimming;311Jellygnite_State_Swimming();312}313else {314destroyEntity(self);315}316}317318void Jellygnite_State_Swimming(void)319{320RSDK_THIS(Jellygnite);321322self->angle = (self->angle + 4) & 0x1FF;323self->frontTentacleAngle = RSDK.Sin512(self->angle) << 1;324325self->oscillateAngle = (self->oscillateAngle + 1) & 0x1FF;326self->position.x = (RSDK.Sin512(self->oscillateAngle) << 11) + self->startPos.x;327328EntityPlayer *playerPtr = Player_GetNearestPlayerX();329if (playerPtr) {330if (Jellygnite_CheckInWater(playerPtr)) {331if (self->position.y <= playerPtr->position.y - 0x200000) {332self->velocity.y += 0x800;333334if (self->velocity.y >= 0xC000)335self->velocity.y = 0xC000;336}337else {338self->velocity.y -= 0x800;339340if (self->velocity.y <= -0xC000)341self->velocity.y = -0xC000;342}343}344else {345self->velocity.y >>= 1;346}347}348349self->position.y += self->velocity.y;350351if (self->position.y - 0x100000 < Water->waterLevel && self->velocity.y < 0) {352self->position.y = self->position.y - self->velocity.y;353self->velocity.y = -self->velocity.y;354}355}356357void Jellygnite_State_GrabbedPlayer(void)358{359RSDK_THIS(Jellygnite);360361if (self->frontTentacleAngle >= 0x600) {362self->state = Jellygnite_State_Explode;363Jellygnite_SetupAnimations(JELLYGNITE_ANI_FLASHING);364RSDK.PlaySfx(Jellygnite->sfxElectrify, false, 255);365}366else {367self->frontTentacleAngle += 0x80;368}369370EntityPlayer *player = self->grabbedPlayer;371player->position.x = self->position.x;372player->position.y = self->position.y + 0xC0000;373}374375void Jellygnite_State_Explode(void)376{377RSDK_THIS(Jellygnite);378379Jellygnite_HandlePlayerStruggle();380381if (++self->timer == 60) {382EntityPlayer *player = self->grabbedPlayer;383if (player && player->state == Player_State_Static) {384Player_Hurt(player, self);385386if (player->state != Player_State_Hurt && Player_CheckValidState(player))387player->state = Player_State_Air;388389self->grabbedPlayer = NULL;390}391392CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_ENEMY), self->position.x, self->position.y)->drawGroup = Zone->objectDrawGroup[1];393RSDK.PlaySfx(Explosion->sfxDestroy, false, 255);394destroyEntity(self);395}396}397398#if GAME_INCLUDE_EDITOR399void Jellygnite_EditorDraw(void)400{401Jellygnite_SetupAnimations(JELLYGNITE_ANI_FLOATING);402403Jellygnite_Draw();404}405406void Jellygnite_EditorLoad(void)407{408if (RSDK.CheckSceneFolder("HPZ"))409Jellygnite->aniFrames = RSDK.LoadSpriteAnimation("HPZ/Jellygnite.bin", SCOPE_STAGE);410else if (RSDK.CheckSceneFolder("HCZ"))411Jellygnite->aniFrames = RSDK.LoadSpriteAnimation("HCZ/Jellygnite.bin", SCOPE_STAGE);412413RSDK_ACTIVE_VAR(Jellygnite, direction);414RSDK_ENUM_VAR("Left", FLIP_NONE);415RSDK_ENUM_VAR("Right", FLIP_X);416}417#endif418419void Jellygnite_Serialize(void) { RSDK_EDITABLE_VAR(Jellygnite, VAR_UINT8, direction); }420421422