Path: blob/master/SonicMania/Objects/SPZ/LottoBall.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: LottoBall Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectLottoBall *LottoBall;1011void LottoBall_Update(void)12{13RSDK_THIS(LottoBall);1415StateMachine_Run(self->state);1617self->angle += self->angleVel;18self->rotation = (self->angle >> 15) & 0x1FF;19}2021void LottoBall_LateUpdate(void) {}2223void LottoBall_StaticUpdate(void) {}2425void LottoBall_Draw(void)26{27RSDK_THIS(LottoBall);2829Vector2 drawPos;30if (self->isVisible[SceneInfo->currentScreenID] || (!self->isUIBall && self->state != LottoBall_State_Collected)) {31RSDK.DrawSprite(&self->ballAnimator, NULL, self->isUIBall);3233switch (self->type) {34case LOTTOBALL_BLUE:35case LOTTOBALL_YELLOW:36case LOTTOBALL_MULTI:37RSDK.DrawSprite(&self->leftNumAnimator, NULL, self->isUIBall);38RSDK.DrawSprite(&self->rightNumAnimator, NULL, self->isUIBall);39break;4041case LOTTOBALL_EGGMAN: RSDK.DrawSprite(&self->leftNumAnimator, NULL, self->isUIBall); break;4243case LOTTOBALL_BIG:44self->drawFX = FX_SCALE | FX_ROTATE;45drawPos.x = self->position.x;46drawPos.y = self->position.y;47drawPos.y += RSDK.Sin256(self->timer) << 10;48RSDK.DrawSprite(&self->leftNumAnimator, &drawPos, self->isUIBall);4950self->drawFX = FX_SCALE;51break;5253case LOTTOBALL_TOTAL:54drawPos = self->position;55drawPos.x -= 0x90000;56self->rightNumAnimator.frameID = self->lottoNum / 100;57RSDK.DrawSprite(&self->rightNumAnimator, &drawPos, self->isUIBall);5859drawPos.x += 0x90000;60self->rightNumAnimator.frameID = (self->lottoNum / 10) % 10;61RSDK.DrawSprite(&self->rightNumAnimator, &drawPos, self->isUIBall);6263drawPos.x += 0x90000;64self->rightNumAnimator.frameID = self->lottoNum % 10;65RSDK.DrawSprite(&self->rightNumAnimator, &drawPos, self->isUIBall);66break;6768default: break;69}70}71}7273void LottoBall_Create(void *data)74{75RSDK_THIS(LottoBall);7677if (!SceneInfo->inEditor) {78self->drawFX = FX_ROTATE;79RSDK.SetSpriteAnimation(LottoBall->aniFrames, 0, &self->ballAnimator, true, self->type);8081switch (self->type) {82case LOTTOBALL_BLUE:83case LOTTOBALL_YELLOW:84RSDK.SetSpriteAnimation(LottoBall->aniFrames, 1, &self->leftNumAnimator, true, self->lottoNum / 10);85RSDK.SetSpriteAnimation(LottoBall->aniFrames, 2, &self->rightNumAnimator, true, self->lottoNum % 10);86break;8788case LOTTOBALL_MULTI:89self->lottoNum %= 10;90RSDK.SetSpriteAnimation(LottoBall->aniFrames, 1, &self->leftNumAnimator, true, self->lottoNum % 10);91RSDK.SetSpriteAnimation(LottoBall->aniFrames, 2, &self->rightNumAnimator, true, 10);92break;9394case LOTTOBALL_EGGMAN: RSDK.SetSpriteAnimation(LottoBall->aniFrames, 1, &self->leftNumAnimator, true, 11); break;9596default: break;97}9899self->active = ACTIVE_BOUNDS;100self->updateRange.x = 0x400000;101self->updateRange.y = 0xE00000;102self->gravityStrength = 0x3800;103self->visible = true;104self->drawGroup = Zone->objectDrawGroup[0];105self->startPos = self->position;106}107}108109void LottoBall_StageLoad(void)110{111LottoBall->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/LottoBall.bin", SCOPE_STAGE);112113LottoBall->sfxLottoBounce = RSDK.GetSfx("Stage/LottoBounce.wav");114LottoBall->sfxSpew = RSDK.GetSfx("Stage/SpewBall.wav");115}116117void LottoBall_CheckOffScreen(void)118{119RSDK_THIS(LottoBall);120121self->angleVel = 0;122if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {123self->angle = 0;124self->velocity.x = 0;125self->velocity.y = 0;126self->position = self->startPos;127self->active = ACTIVE_BOUNDS;128self->state = StateMachine_None;129}130}131132void LottoBall_State_FallIntoMachine(void)133{134RSDK_THIS(LottoBall);135136if (self->parent) {137if (self->timer) {138self->timer--;139}140else {141if (self->position.y >= self->parent->position.y - 0x200000) {142self->state = LottoBall_State_InMachine;143}144else {145if (self->position.x >= self->parent->position.x)146self->velocity.x -= self->gravityStrength;147else148self->velocity.x += self->gravityStrength;149}150151self->velocity.y += self->gravityStrength;152self->position.x += self->velocity.x;153self->position.y += self->velocity.y;154self->angleVel = self->velocity.x;155}156}157}158159void LottoBall_State_InMachine(void)160{161RSDK_THIS(LottoBall);162163EntityLottoMachine *parent = self->parent;164if (parent) {165self->velocity.y += self->gravityStrength;166self->position.x += self->velocity.x;167self->position.y += self->velocity.y;168169if (self->timer) {170self->timer--;171}172else {173int32 vel = (abs(self->velocity.x) + abs(parent->spinSpeed) + abs(self->velocity.y)) >> 1;174if (vel > 0x60000) {175vel = 0x60000;176}177else if (vel < 0x30000) {178vel = 0x30000;179self->timer = RSDK.Rand(16, 32);180}181182if (!(Zone->timer & 0xF))183RSDK.PlaySfx(LottoBall->sfxLottoBounce, false, 255);184185foreach_active(LottoBall, ball)186{187if (ball != self) {188int32 rx = (self->position.x - ball->position.x) >> 16;189int32 ry = (self->position.y - ball->position.y) >> 16;190191if (rx * rx + ry * ry < 0x100) {192int32 angle = RSDK.ATan2(rx, ry);193self->velocity.x = (vel * RSDK.Cos256(angle)) >> 8;194self->velocity.y = (vel * RSDK.Sin256(angle)) >> 8;195}196}197}198}199200int32 rx = (self->position.x - parent->position.x) >> 16;201int32 ry = (self->position.y - parent->position.y) >> 16;202if (rx * rx + ry * ry > 0x1B90) {203int32 angle = RSDK.ATan2(rx, (self->position.y - parent->position.y) >> 16);204self->position.x = 0x5400 * RSDK.Cos256(angle) + parent->position.x;205self->position.y = 0x5400 * RSDK.Sin256(angle) + parent->position.y;206switch (((angle + 0x20) & 0xFF) >> 6) {207case 0:208case 2:209self->timer = 8;210self->velocity.x = -self->velocity.x >> 1;211break;212213case 1:214self->velocity.y = -self->velocity.y >> 1;215self->velocity.x -= parent->spinSpeed;216if (parent->state == LottoMachine_State_Startup) {217self->active = ACTIVE_NORMAL;218self->state = LottoBall_CheckOffScreen;219}220break;221222case 3:223self->velocity.y = MAX(-self->velocity.y >> 1, 0x10000);224self->velocity.x += parent->spinSpeed;225break;226}227}228229if (self->velocity.x >= -0x40000) {230if (self->velocity.x > 0x40000)231self->velocity.x = 0x40000;232self->angleVel = self->velocity.x + self->velocity.y;233}234else {235self->velocity.x = -0x40000;236self->angleVel = self->velocity.x + self->velocity.y;237}238}239}240241void LottoBall_State_Collected(void)242{243RSDK_THIS(LottoBall);244245if (self->parent) {246if (self->timer == 8)247RSDK.PlaySfx(LottoBall->sfxSpew, false, 0xFF);248249if (self->timer > 16) {250self->velocity.y += self->gravityStrength;251self->position.y += self->velocity.y;252}253254if (++self->timer > 48) {255self->drawFX |= FX_SCALE;256self->timer = 0;257self->isUIBall = true;258self->scale.x = 0x200;259self->scale.y = 0x200;260self->drawGroup = Zone->hudDrawGroup;261self->active = ACTIVE_NORMAL;262self->state = LottoBall_State_CollectFall;263264RSDK.SetSpriteAnimation(LottoBall->aniFrames, self->ballAnimator.animationID + 3, &self->ballAnimator, true, self->ballAnimator.frameID);265RSDK.SetSpriteAnimation(LottoBall->aniFrames, (self->leftNumAnimator.animationID + 3), &self->leftNumAnimator, true,266self->leftNumAnimator.frameID);267RSDK.SetSpriteAnimation(LottoBall->aniFrames, (self->rightNumAnimator.animationID + 3), &self->rightNumAnimator, true,268self->rightNumAnimator.frameID);269270self->position.x = self->bounds.x - 0x1880000;271self->position.y = ((ScreenInfo->size.y - 160) << 16);272self->velocity.x = 0x80000;273self->velocity.y = 0x40000;274}275}276}277278void LottoBall_State_CollectFall(void)279{280RSDK_THIS(LottoBall);281282if (self->parent) {283self->velocity.y += 0x4800;284self->position.x += self->velocity.x;285self->position.y += self->velocity.y;286287if (self->position.x > self->bounds.x)288self->position.x = self->bounds.x;289290if (self->position.y > self->bounds.y) {291self->position.y = self->bounds.y;292self->velocity.y = -(self->velocity.y >> 1);293294if (self->position.x >= self->bounds.x) {295self->position.x = self->bounds.x;296self->state = StateMachine_None;297}298}299}300}301302void LottoBall_State_SetupUIBall(void)303{304RSDK_THIS(LottoBall);305306++self->timer;307self->position.x += ((ScreenInfo->center.x << 16) - self->position.x) >> 3;308309if (self->timer > 24) {310self->scale.x -= (self->scale.x >> 3);311self->scale.y -= (self->scale.y >> 3);312313if (self->scale.x < 8) {314self->position = self->startPos;315self->scale.y = 8;316self->scale.x = 8;317self->angle = 0;318self->velocity.x = 0;319self->velocity.y = 0;320self->active = ACTIVE_BOUNDS;321self->isUIBall = false;322self->drawGroup = Zone->objectDrawGroup[0];323self->isVisible[0] = false;324self->isVisible[1] = false;325self->isVisible[2] = false;326self->isVisible[3] = false;327self->state = LottoBall_State_EnterUIBall;328329RSDK.SetSpriteAnimation(LottoBall->aniFrames, self->ballAnimator.animationID - 3, &self->ballAnimator, true, self->ballAnimator.frameID);330RSDK.SetSpriteAnimation(LottoBall->aniFrames, self->leftNumAnimator.animationID - 3, &self->leftNumAnimator, true,331self->leftNumAnimator.frameID);332RSDK.SetSpriteAnimation(LottoBall->aniFrames, self->rightNumAnimator.animationID - 3, &self->rightNumAnimator, true,333self->rightNumAnimator.frameID);334}335}336}337338void LottoBall_State_EnterUIBall(void)339{340RSDK_THIS(LottoBall);341342self->scale.x += self->scale.x >> 3;343self->scale.y += self->scale.y >> 3;344345if (self->scale.x >= 0x200) {346self->drawFX &= ~FX_SCALE;347self->scale.y = 0x200;348self->scale.x = 0x200;349self->state = StateMachine_None;350}351}352353void LottoBall_State_ShowUIBall(void)354{355RSDK_THIS(LottoBall);356357self->timer += 8;358359int32 scale = MIN(self->scale.x + ((0x214 - self->scale.x) >> 3), 0x200);360self->scale.x = scale;361self->scale.y = scale;362363if (self->timer > 512) {364self->timer = 0;365self->type = LOTTOBALL_TOTAL;366self->state = LottoBall_State_SetupUIBall;367self->lottoNum = abs(self->ringCount);368RSDK.SetSpriteAnimation(LottoBall->aniFrames, self->ringCount < 0 ? 8 : 7, &self->rightNumAnimator, true, 0);369}370}371372#if GAME_INCLUDE_EDITOR373void LottoBall_EditorDraw(void)374{375RSDK_THIS(LottoBall);376377RSDK.SetSpriteAnimation(LottoBall->aniFrames, 0, &self->ballAnimator, true, self->type);378379switch (self->type) {380case LOTTOBALL_BLUE:381case LOTTOBALL_YELLOW:382RSDK.SetSpriteAnimation(LottoBall->aniFrames, 1, &self->leftNumAnimator, true, self->lottoNum / 10);383RSDK.SetSpriteAnimation(LottoBall->aniFrames, 2, &self->rightNumAnimator, true, self->lottoNum % 10);384break;385386case LOTTOBALL_MULTI:387self->lottoNum %= 10;388RSDK.SetSpriteAnimation(LottoBall->aniFrames, 1, &self->leftNumAnimator, true, self->lottoNum % 10);389RSDK.SetSpriteAnimation(LottoBall->aniFrames, 2, &self->rightNumAnimator, true, 10);390break;391392case LOTTOBALL_EGGMAN: RSDK.SetSpriteAnimation(LottoBall->aniFrames, 1, &self->leftNumAnimator, true, 11); break;393394default: break;395}396397self->updateRange.x = 0x400000;398self->updateRange.y = 0xE00000;399self->visible = true;400self->drawGroup = Zone->objectDrawGroup[0];401402LottoBall_Draw();403}404405void LottoBall_EditorLoad(void)406{407LottoBall->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/LottoBall.bin", SCOPE_STAGE);408409RSDK_ACTIVE_VAR(LottoBall, type);410RSDK_ENUM_VAR("Blue", LOTTOBALL_BLUE);411RSDK_ENUM_VAR("Yellow", LOTTOBALL_YELLOW);412RSDK_ENUM_VAR("Multiplier", LOTTOBALL_MULTI);413RSDK_ENUM_VAR("Eggman", LOTTOBALL_EGGMAN);414}415#endif416417void LottoBall_Serialize(void)418{419RSDK_EDITABLE_VAR(LottoBall, VAR_UINT8, type);420RSDK_EDITABLE_VAR(LottoBall, VAR_UINT8, lottoNum);421}422423424