Path: blob/master/SonicMania/Objects/SSZ/Kabasira.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Kabasira Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectKabasira *Kabasira;1011void Kabasira_Update(void)12{13RSDK_THIS(Kabasira);1415StateMachine_Run(self->state);16}1718void Kabasira_LateUpdate(void) {}1920void Kabasira_StaticUpdate(void) {}2122void Kabasira_Draw(void)23{24RSDK_THIS(Kabasira);2526if (self->state == Kabasira_State_LaunchedAttack) {27self->drawFX = FX_SCALE | FX_FLIP;28RSDK.DrawSprite(&self->bodyAnimator, NULL, false);29RSDK.DrawSprite(&self->wingsAnimator, NULL, false);3031// Probably shouldn't be in Draw?32RSDK.ProcessAnimation(&self->wingsAnimator);33}34else {35int32 speed = (2 * (self->direction == FLIP_NONE) - 1);3637int32 angle = self->angle + 72 * speed;38if (angle < 0)39angle = ((-1 - angle) & -0x200) + angle + 0x200;40angle &= 0x1FF;4142int32 alpha = 0x100 / KABASIRA_BODY_COUNT; // default is 0x4043int32 angleVel = 24 * speed;4445for (int32 i = 0; i < KABASIRA_BODY_COUNT - 1; ++i) {46Kabasira_DrawSegment(angle, alpha);4748angle -= angleVel;49if (angle < 0)50angle = ((-1 - angle) & -0x200) + angle + 0x200;51angle &= 0x1FF;5253alpha += 0x100 / KABASIRA_BODY_COUNT; // default is 0x4054}5556Kabasira_DrawSegment(angle, alpha);57self->angle = angle;58}59}6061void Kabasira_Create(void *data)62{63RSDK_THIS(Kabasira);6465self->inkEffect = INK_ALPHA;66self->drawFX = FX_FLIP | FX_ROTATE | FX_SCALE;67self->scale.x = 0x200;68self->scale.y = 0x200;6970if (!SceneInfo->inEditor) {71self->visible = true;72self->drawGroup = Zone->objectDrawGroup[0];73self->startPos = self->position;74self->startDir = self->direction;75self->active = ACTIVE_BOUNDS;76self->updateRange.x = 0x800000;77self->updateRange.y = 0x800000;7879RSDK.SetSpriteAnimation(Kabasira->aniFrames, 0, &self->bodyAnimator, true, 0);80RSDK.SetSpriteAnimation(Kabasira->aniFrames, 1, &self->wingsAnimator, true, 0);81self->wingsAnimator.frameCount = 3;8283if (data) {84self->alpha = 0x80;85self->state = Kabasira_State_LaunchedAttack;86}87else {88self->wingsAnimator.frameCount = 3;89self->wingsAnimator.loopIndex = 0;9091self->state = Kabasira_State_Init;92}93}94}9596void Kabasira_StageLoad(void)97{98if (RSDK.CheckSceneFolder("SSZ1"))99Kabasira->aniFrames = RSDK.LoadSpriteAnimation("SSZ1/Kabasira.bin", SCOPE_STAGE);100else if (RSDK.CheckSceneFolder("SSZ2"))101Kabasira->aniFrames = RSDK.LoadSpriteAnimation("SSZ2/Kabasira.bin", SCOPE_STAGE);102103Kabasira->hitboxBadnik.left = -6;104Kabasira->hitboxBadnik.top = -6;105Kabasira->hitboxBadnik.right = 6;106Kabasira->hitboxBadnik.bottom = 6;107108Kabasira->onScreenRange.x = 0x60000;109Kabasira->onScreenRange.y = 0x60000;110111Kabasira->sfxPon = RSDK.GetSfx("Stage/Pon.wav");112Kabasira->sfxExplosion2 = RSDK.GetSfx("Stage/Explosion2.wav");113114DEBUGMODE_ADD_OBJ(Kabasira);115}116117void Kabasira_DebugSpawn(void)118{119RSDK_THIS(DebugMode);120121CREATE_ENTITY(Kabasira, NULL, self->position.x, self->position.y);122}123124void Kabasira_DebugDraw(void)125{126RSDK.SetSpriteAnimation(Kabasira->aniFrames, 0, &DebugMode->animator, true, 0);127RSDK.DrawSprite(&DebugMode->animator, NULL, false);128}129130bool32 Kabasira_HandleAnimations(uint8 angle)131{132RSDK_THIS(Kabasira);133134int32 rotation = 2 * angle;135int32 prevFrame = self->wingsAnimator.frameID % 3;136int32 frame = 0;137138switch (rotation >> 7) {139case 0:140case 2: frame = (rotation >> 5) & 3; break;141142case 1:143case 3: frame = 3 - ((rotation >> 5) & 3); break;144}145146int32 frameCount = 3 * frame;147self->wingsAnimator.loopIndex = frameCount;148self->wingsAnimator.frameID = prevFrame + frameCount;149self->wingsAnimator.frameCount = frameCount + 3;150151return rotation > 0x80 && rotation < 0x180;152}153154void Kabasira_DrawSegment(int32 angle, int32 alpha)155{156RSDK_THIS(Kabasira);157Vector2 drawPos;158159int32 rotation = 2 * angle;160drawPos.x = RSDK.Sin512(rotation) * 0xA00 + self->startPos.x;161drawPos.y = (RSDK.Cos512(angle) << 13) + self->startPos.y;162163int32 frame = 11 - rotation % 512 / 42 % 12;164RSDK.SetSpriteAnimation(Kabasira->aniFrames, 0, &self->bodyAnimator, true, frame);165166if (!self->bodyAnimator.frameID || self->bodyAnimator.frameID > 6) {167self->scale.x = 0x200;168self->scale.y = 0x200;169}170else {171self->scale.x = ((abs(2 * self->bodyAnimator.frameID - 7) << 5) / 5) + 480;172self->scale.y = self->scale.x;173}174175uint8 dir = Kabasira_HandleAnimations(angle) ? FLIP_X : FLIP_NONE;176int32 storedDir = self->direction;177int32 storedAlpha = self->alpha;178179if (self->angle < 0x100) {180self->direction = FLIP_NONE;181self->alpha = alpha;182RSDK.DrawSprite(&self->bodyAnimator, &drawPos, false);183184self->direction = dir;185alpha >>= 1;186self->alpha = alpha;187RSDK.DrawSprite(&self->wingsAnimator, &drawPos, false);188}189else {190self->direction = dir;191self->alpha = alpha >> 1;192RSDK.DrawSprite(&self->wingsAnimator, &drawPos, false);193194self->direction = FLIP_NONE;195self->alpha = alpha;196RSDK.DrawSprite(&self->bodyAnimator, &drawPos, false);197}198199self->alpha = storedAlpha;200self->direction = storedDir;201}202203void Kabasira_CheckPlayerCollisions(void)204{205RSDK_THIS(Kabasira);206207foreach_active(Player, player)208{209if (Player_CheckBadnikTouch(player, self, &Kabasira->hitboxBadnik))210Player_CheckBadnikBreak(player, self, true);211}212}213214void Kabasira_CheckOffScreen(void)215{216RSDK_THIS(Kabasira);217218if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {219self->position = self->startPos;220self->direction = self->startDir;221Kabasira_Create(NULL);222}223}224225void Kabasira_State_Init(void)226{227RSDK_THIS(Kabasira);228229self->active = ACTIVE_NORMAL;230self->angle = 0;231self->timer = 0;232233self->state = Kabasira_State_Moving;234Kabasira_State_Moving();235}236237void Kabasira_State_Moving(void)238{239RSDK_THIS(Kabasira);240241RSDK.ProcessAnimation(&self->wingsAnimator);242243self->angle += 2;244if (self->timer > 0) {245self->timer--;246}247else {248self->timer = 240;249if (RSDK.CheckOnScreen(self, &Kabasira->onScreenRange)) {250EntityPlayer *player = Player_GetNearestPlayer();251252if (player) {253RSDK.PlaySfx(Kabasira->sfxPon, false, 255);254255EntityKabasira *attack = CREATE_ENTITY(Kabasira, INT_TO_VOID(true), self->position.x, self->position.y);256int32 angle = RSDK.ATan2(player->position.x - self->position.x, player->position.y - self->position.y);257attack->velocity.x = RSDK.Cos256(angle) << 9;258attack->velocity.y = RSDK.Sin256(angle) << 9;259attack->direction = player->position.x < self->position.x;260}261}262}263264self->position.x = self->startPos.x + (0xA00 * RSDK.Sin512(2 * self->angle));265self->position.y = self->startPos.y + (RSDK.Cos512(self->angle) << 13);266267Kabasira_CheckPlayerCollisions();268Kabasira_CheckOffScreen();269}270271void Kabasira_State_LaunchedAttack(void)272{273RSDK_THIS(Kabasira);274275self->position.x += self->velocity.x;276self->position.y += self->velocity.y;277278foreach_active(Player, player)279{280if (Player_CheckBadnikTouch(player, self, &Kabasira->hitboxBadnik)) {281if (Player_CheckAttacking(player, self)) {282CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_ITEMBOX), self->position.x, self->position.y)->drawGroup = Zone->objectDrawGroup[1];283RSDK.PlaySfx(Kabasira->sfxExplosion2, false, 255);284285destroyEntity(self);286foreach_break;287}288else {289Player_Hurt(player, self);290}291}292}293}294295#if GAME_INCLUDE_EDITOR296void Kabasira_EditorDraw(void)297{298RSDK_THIS(Kabasira);299300RSDK.SetSpriteAnimation(Kabasira->aniFrames, 0, &self->bodyAnimator, false, 0);301RSDK.SetSpriteAnimation(Kabasira->aniFrames, 1, &self->wingsAnimator, false, 0);302self->startPos = self->position;303self->startDir = self->direction;304305Kabasira_Draw();306}307308void Kabasira_EditorLoad(void)309{310if (RSDK.CheckSceneFolder("SSZ1"))311Kabasira->aniFrames = RSDK.LoadSpriteAnimation("SSZ1/Kabasira.bin", SCOPE_STAGE);312else if (RSDK.CheckSceneFolder("SSZ2"))313Kabasira->aniFrames = RSDK.LoadSpriteAnimation("SSZ2/Kabasira.bin", SCOPE_STAGE);314315RSDK_ACTIVE_VAR(Kabasira, direction);316RSDK_ENUM_VAR("Left", FLIP_NONE);317RSDK_ENUM_VAR("Right", FLIP_X);318}319#endif320321void Kabasira_Serialize(void) { RSDK_EDITABLE_VAR(Kabasira, VAR_UINT8, direction); }322323324