Path: blob/master/SonicMania/Objects/SPZ/PopcornMachine.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: PopcornMachine Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectPopcornMachine *PopcornMachine;1011void PopcornMachine_Update(void)12{13RSDK_THIS(PopcornMachine);14StateMachine_Run(self->state);15}1617void PopcornMachine_LateUpdate(void) {}1819void PopcornMachine_StaticUpdate(void) {}2021void PopcornMachine_Draw(void)22{23RSDK_THIS(PopcornMachine);24Vector2 drawPos;2526// Draw Dispenser27drawPos.x = self->position.x;28drawPos.y = self->position.y;29drawPos.x += self->dispenserPos.x;30drawPos.y = drawPos.y - 0x200000 + self->dispenserPos.y;31self->animator.frameID = 9;32RSDK.DrawSprite(&self->animator, &drawPos, false);3334// Draw Dispenser Holder35drawPos = self->position;36drawPos.x += self->dispenserHolderPos.x;37drawPos.y = drawPos.y - 0x200000 + self->dispenserHolderPos.y;38self->animator.frameID = 10;39RSDK.DrawSprite(&self->animator, &drawPos, false);4041// Draw Sign42self->animator.frameID = 0;43RSDK.DrawSprite(&self->animator, NULL, false);4445// Draw Top46self->animator.frameID = 1;47RSDK.DrawSprite(&self->animator, NULL, false);4849// Draw Entries50switch (self->type) {51case POPCORNMACHINE_LEFT:52self->animator.frameID = 2;53RSDK.DrawSprite(&self->animator, NULL, false);54break;55case POPCORNMACHINE_RIGHT:56self->animator.frameID = 3;57RSDK.DrawSprite(&self->animator, NULL, false);58break;59case POPCORNMACHINE_BOTH:60self->animator.frameID = 2;61RSDK.DrawSprite(&self->animator, NULL, false);6263self->animator.frameID = 3;64RSDK.DrawSprite(&self->animator, NULL, false);65break;66}6768// Draw Top69drawPos = self->position;70drawPos.y += -0xD00000 - 0xA00000 * self->height;71int32 storeY1 = drawPos.y;72int32 storeY2 = self->position.y - 0x300000;73self->animator.frameID = 4;74RSDK.DrawSprite(&self->animator, &drawPos, false);7576self->animator.frameID = 5;77RSDK.DrawSprite(&self->animator, &drawPos, false);7879// Draw (Initial) Machine Glass Edges80self->animator.frameID = 6;81RSDK.DrawSprite(&self->animator, &drawPos, false);8283self->animator.frameID = 7;84RSDK.DrawSprite(&self->animator, &drawPos, false);8586// Draw Machine Glass Edges87for (int32 y = 0; y < self->height; ++y) {88drawPos.y += 0xA00000;89self->animator.frameID = 6;90RSDK.DrawSprite(&self->animator, &drawPos, false);91self->animator.frameID = 7;92RSDK.DrawSprite(&self->animator, &drawPos, false);93}9495// Draw City Reflection FX96RSDKScreenInfo *screen = &ScreenInfo[SceneInfo->currentScreenID];9798self->inkEffect = INK_ADD;99self->animator.frameID = 8;100RSDK.SetClipBounds(SceneInfo->currentScreenID, 0, (storeY1 >> 16) - screen->position.y, screen->size.x, (storeY2 >> 16) - screen->position.y + 1);101102drawPos = self->position;103drawPos.x -= 0x600000;104drawPos.y = (self->position.y + ((screen->center.y - 160 + screen->position.y) << 16)) >> 1;105RSDK.DrawSprite(&self->animator, &drawPos, false);106107drawPos.x += 0xC00000;108drawPos.y = (self->position.y + ((screen->center.y - 384 + screen->position.y) << 16)) >> 1;109self->direction = FLIP_XY;110RSDK.DrawSprite(&self->animator, &drawPos, false);111112self->direction = FLIP_NONE;113self->inkEffect = INK_NONE;114RSDK.SetClipBounds(SceneInfo->currentScreenID, 0, 0, screen->size.x, screen->size.y);115}116117void PopcornMachine_Create(void *data)118{119RSDK_THIS(PopcornMachine);120121if (!SceneInfo->inEditor) {122if (data) {123self->active = ACTIVE_NORMAL;124self->visible = false;125self->player = (EntityPlayer *)data;126self->state = PopcornMachine_StateController_ReadyPlayer;127}128else {129self->active = ACTIVE_BOUNDS;130self->updateRange.x = 0xB00000;131self->visible = true;132self->updateRange.y = 0xA00000 * self->height + 0x1000000;133self->drawGroup = Zone->objectDrawGroup[1];134self->drawFX = FX_FLIP;135self->alpha = 0xE0;136self->dispenserHolderPos.y = -0x100000;137self->dispenserPos.y = -0x100000;138139int32 top = -0x100 - 0xA0 * self->height;140self->hitboxSideL.top = top;141self->hitboxSideL.left = -128;142self->hitboxSideL.right = -120;143self->hitboxSideL.bottom = -32;144145self->hitboxSideR.left = 120;146self->hitboxSideR.top = top;147self->hitboxSideR.right = 128;148self->hitboxSideR.bottom = -32;149150self->hitboxTop.left = -128;151self->hitboxTop.top = top;152self->hitboxTop.right = 128;153self->hitboxTop.bottom = top + 16;154155self->state = PopcornMachine_State_Idle;156RSDK.SetSpriteAnimation(PopcornMachine->aniFrames, 0, &self->animator, true, 0);157}158}159}160161void PopcornMachine_StageLoad(void)162{163PopcornMachine->aniFrames = RSDK.LoadSpriteAnimation("SPZ1/PopcornMachine.bin", SCOPE_STAGE);164165PopcornMachine->hitboxEntryL.left = -176;166PopcornMachine->hitboxEntryL.right = -128;167PopcornMachine->hitboxEntryL.top = -16;168PopcornMachine->hitboxEntryL.bottom = 24;169170PopcornMachine->hitboxEntryR.left = 128;171PopcornMachine->hitboxEntryR.right = 176;172PopcornMachine->hitboxEntryR.top = -16;173PopcornMachine->hitboxEntryR.bottom = 24;174175PopcornMachine->sfxFanStart = RSDK.GetSfx("Stage/FanStart.wav");176PopcornMachine->sfxShoot = RSDK.GetSfx("Stage/Shoot1.wav");177PopcornMachine->sfxPopcornLaunch = RSDK.GetSfx("Stage/PopcornLaunch.wav");178}179180void PopcornMachine_LinkPlayer(EntityPlayer *player)181{182RSDK_THIS(PopcornMachine);183184player->nextAirState = StateMachine_None;185player->nextGroundState = StateMachine_None;186player->state = Player_State_Static;187player->onGround = false;188player->velocity.x = player->position.x < self->position.x ? 0xA0000 : -0xA0000;189player->tileCollisions = TILECOLLISION_NONE;190RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);191192EntityPopcornMachine *machine = CREATE_ENTITY(PopcornMachine, player, self->position.x, self->position.y);193machine->isPermanent = true;194machine->parent = self;195if (!player->sidekick)196machine->bounds[player->playerID] = Zone->cameraBoundsB[player->playerID];197}198void PopcornMachine_CheckPlayerCollisions(void)199{200RSDK_THIS(PopcornMachine);201202foreach_active(Player, player)203{204Player_CheckCollisionBox(player, self, &self->hitboxSideL);205Player_CheckCollisionBox(player, self, &self->hitboxSideR);206Player_CheckCollisionPlatform(player, self, &self->hitboxTop);207208if (player->state != Player_State_Static) {209210switch (self->type) {211case POPCORNMACHINE_LEFT:212if (player->onGround && Player_CheckCollisionTouch(player, self, &PopcornMachine->hitboxEntryL)) {213PopcornMachine_LinkPlayer(player);214}215else if (!player->onGround) {216Player_CheckCollisionBox(player, self, &PopcornMachine->hitboxEntryL);217}218break;219220case POPCORNMACHINE_RIGHT:221if (player->onGround && Player_CheckCollisionTouch(player, self, &PopcornMachine->hitboxEntryL)) {222PopcornMachine_LinkPlayer(player);223}224else if (!player->onGround) {225Player_CheckCollisionBox(player, self, &PopcornMachine->hitboxEntryR);226}227break;228229case POPCORNMACHINE_BOTH:230if (player->onGround) {231if (Player_CheckCollisionTouch(player, self, &PopcornMachine->hitboxEntryL)) {232PopcornMachine_LinkPlayer(player);233}234else {235if (Player_CheckCollisionTouch(player, self, &PopcornMachine->hitboxEntryR))236PopcornMachine_LinkPlayer(player);237}238}239else {240Player_CheckCollisionBox(player, self, &PopcornMachine->hitboxEntryL);241Player_CheckCollisionBox(player, self, &PopcornMachine->hitboxEntryR);242}243break;244}245}246}247}248249void PopcornMachine_State_Idle(void) { PopcornMachine_CheckPlayerCollisions(); }250251void PopcornMachine_State_ShowDispenser(void)252{253RSDK_THIS(PopcornMachine);254255PopcornMachine_CheckPlayerCollisions();256257self->dispenserHolderPos.y -= 0x8000;258if (self->dispenserHolderPos.y <= -0x200000)259self->dispenserHolderPos.y = -0x200000;260261self->dispenserPos.y -= 0x18000;262if (self->dispenserPos.y <= -0x400000) {263self->dispenserPos.y = -0x400000;264self->timer = 0;265self->state = PopcornMachine_State_Shaking;266}267}268269void PopcornMachine_State_Shaking(void)270{271RSDK_THIS(PopcornMachine);272273PopcornMachine_CheckPlayerCollisions();274275self->dispenserHolderPos.x = RSDK.Rand(-0x20000, 0x20000);276self->dispenserHolderPos.y = RSDK.Rand(-0x20000, 0x20000) - 0x1E0000;277278self->dispenserPos.x = RSDK.Rand(-0x20000, 0x20000);279self->dispenserPos.y = self->dispenserHolderPos.y - 0x1E0000 + RSDK.Rand(-0x20000, 0x20000);280281self->timer++;282if (self->timer >= 25 && self->timer < 160) {283if (!(self->timer & 1)) {284EntityPopcornKernel *kernel = CREATE_ENTITY(PopcornKernel, NULL, self->position.x, self->position.y - 0x400000);285kernel->velocity.x = RSDK.Rand(-0x30000, 0x30000);286kernel->velocity.y = RSDK.Rand(-0xC0000, -0x60000);287kernel->angleVel = RSDK.Rand(-0x60000, 0x60000);288kernel->bounds.x = self->position.x;289kernel->bounds.y = self->position.y;290}291292if (!(self->timer & 7))293RSDK.PlaySfx(PopcornMachine->sfxShoot, false, 255);294}295296if (self->timer == 160) {297foreach_active(PopcornKernel, kernel)298{299kernel->state = PopcornKernel_State_RiseUp;300kernel->velocity.x = 0;301kernel->velocity.y = RSDK.Rand(-0xA0000, -0x60000);302kernel->maxY = self->position.y - (0xA00000 * self->height) - 0xD00000;303}304305RSDK.PlaySfx(PopcornMachine->sfxPopcornLaunch, false, 255);306self->state = PopcornMachine_State_HideDispenser;307}308}309310void PopcornMachine_State_HideDispenser(void)311{312RSDK_THIS(PopcornMachine);313314PopcornMachine_CheckPlayerCollisions();315316self->dispenserHolderPos.y += 0x8000;317if (self->dispenserHolderPos.y >= 0)318self->dispenserHolderPos.y = 0;319320self->dispenserPos.y += 0x18000;321if (self->dispenserPos.y >= 0) {322self->dispenserPos.y = 0;323self->state = PopcornMachine_State_Idle;324}325}326327void PopcornMachine_StateController_ReadyPlayer(void)328{329RSDK_THIS(PopcornMachine);330331EntityPopcornMachine *parent = self->parent;332EntityPlayer *player = self->player;333334if (Player_CheckValidState(player)) {335if (player->position.y < self->position.y - 0x300000) {336player->position.y = self->position.y - 0x300000;337player->velocity.y = 0;338self->state = PopcornMachine_StateController_FirePlayer;339}340341if (!Player_CheckValidState(player)) {342if (!player->sidekick)343Zone->cameraBoundsB[player->playerID] = self->bounds[player->playerID];344345destroyEntity(self);346}347}348else {349destroyEntity(self);350}351352if (abs(self->position.x - player->position.x) < 0x100000) {353player->position.x = self->position.x;354player->groundVel = 0;355player->velocity.x = 0;356player->velocity.y = -0x80000;357358if (!player->sidekick)359Zone->cameraBoundsB[player->playerID] = (self->position.y >> 16) + 32;360361if (parent->state == PopcornMachine_State_Idle || parent->state == PopcornMachine_State_HideDispenser) {362parent->state = PopcornMachine_State_ShowDispenser;363RSDK.PlaySfx(PopcornMachine->sfxFanStart, false, 255);364}365366self->state = PopcornMachine_StateController_RisePlayer;367}368369if (!Player_CheckValidState(player)) {370if (!player->sidekick)371Zone->cameraBoundsB[player->playerID] = self->bounds[player->playerID];372373destroyEntity(self);374}375}376377void PopcornMachine_StateController_RisePlayer(void)378{379RSDK_THIS(PopcornMachine);380381EntityPlayer *player = self->player;382383if (Player_CheckValidState(player)) {384if (player->position.y < self->position.y - 0x300000) {385player->position.y = self->position.y - 0x300000;386player->velocity.y = 0;387self->state = PopcornMachine_StateController_FirePlayer;388}389390if (!Player_CheckValidState(player)) {391if (!player->sidekick)392Zone->cameraBoundsB[player->playerID] = self->bounds[player->playerID];393394destroyEntity(self);395}396}397else {398destroyEntity(self);399}400}401402void PopcornMachine_StateController_FirePlayer(void)403{404RSDK_THIS(PopcornMachine);405EntityPopcornMachine *parent = self->parent;406EntityPlayer *player = self->player;407408if (Player_CheckValidState(player)) {409if (parent->state == PopcornMachine_State_HideDispenser) {410player->state = Player_State_Air;411player->gravityStrength = 0x80;412player->velocity.y = -0xD8000 - (parent->height << 16);413player->position.y += player->velocity.y;414415RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);416if (!player->sidekick)417Zone->cameraBoundsB[player->playerID] = self->bounds[player->playerID];418419self->state = PopcornMachine_StateController_HandleFinish;420}421}422else {423destroyEntity(self);424}425}426427void PopcornMachine_StateController_HandleFinish(void)428{429RSDK_THIS(PopcornMachine);430EntityPopcornMachine *parent = self->parent;431EntityPlayer *player = self->player;432433if (Player_CheckValidState(player)) {434if (player->position.y < parent->position.y - 0xA00000 * parent->height + 0xD00000) {435player->tileCollisions = TILECOLLISION_DOWN;436Player_UpdatePhysicsState(player);437destroyEntity(self);438}439}440else {441destroyEntity(self);442}443}444445#if GAME_INCLUDE_EDITOR446void PopcornMachine_EditorDraw(void)447{448RSDK_THIS(PopcornMachine);449self->active = ACTIVE_BOUNDS;450self->updateRange.x = 0xB00000;451self->visible = true;452self->updateRange.y = 0xA00000 * self->height + 0x1000000;453self->drawGroup = Zone->objectDrawGroup[1];454self->drawFX = FX_FLIP;455self->alpha = 0xE0;456self->dispenserHolderPos.y = -0x100000;457self->dispenserPos.y = -0x100000;458RSDK.SetSpriteAnimation(PopcornMachine->aniFrames, 0, &self->animator, true, 0);459460// Draw !!461Vector2 drawPos;462463// Draw Dispenser464drawPos.x = self->position.x;465drawPos.y = self->position.y;466drawPos.x += self->dispenserPos.x;467drawPos.y = drawPos.y - 0x200000 + self->dispenserPos.y;468self->animator.frameID = 9;469RSDK.DrawSprite(&self->animator, &drawPos, false);470471// Draw Dispenser Holder472drawPos = self->position;473drawPos.x += self->dispenserHolderPos.x;474drawPos.y = drawPos.y - 0x200000 + self->dispenserHolderPos.y;475self->animator.frameID = 10;476RSDK.DrawSprite(&self->animator, &drawPos, false);477478// Draw Sign479self->animator.frameID = 0;480RSDK.DrawSprite(&self->animator, NULL, false);481482// Draw Top483self->animator.frameID = 1;484RSDK.DrawSprite(&self->animator, NULL, false);485486// Draw Entries487switch (self->type) {488case POPCORNMACHINE_LEFT:489self->animator.frameID = 2;490RSDK.DrawSprite(&self->animator, NULL, false);491break;492case POPCORNMACHINE_RIGHT:493self->animator.frameID = 3;494RSDK.DrawSprite(&self->animator, NULL, false);495break;496case POPCORNMACHINE_BOTH:497self->animator.frameID = 2;498RSDK.DrawSprite(&self->animator, NULL, false);499500self->animator.frameID = 3;501RSDK.DrawSprite(&self->animator, NULL, false);502break;503}504505// Draw Top506drawPos = self->position;507drawPos.y += -0xD00000 - 0xA00000 * self->height;508self->animator.frameID = 4;509RSDK.DrawSprite(&self->animator, &drawPos, false);510511self->animator.frameID = 5;512RSDK.DrawSprite(&self->animator, &drawPos, false);513514// Draw (Initial) Machine Glass Edges515self->animator.frameID = 6;516RSDK.DrawSprite(&self->animator, &drawPos, false);517518self->animator.frameID = 7;519RSDK.DrawSprite(&self->animator, &drawPos, false);520521// Draw Machine Glass Edges522for (int32 y = 0; y < self->height; ++y) {523drawPos.y += 0xA00000;524self->animator.frameID = 6;525RSDK.DrawSprite(&self->animator, &drawPos, false);526self->animator.frameID = 7;527RSDK.DrawSprite(&self->animator, &drawPos, false);528}529}530531void PopcornMachine_EditorLoad(void)532{533PopcornMachine->aniFrames = RSDK.LoadSpriteAnimation("SPZ1/PopcornMachine.bin", SCOPE_STAGE);534535RSDK_ACTIVE_VAR(PopcornMachine, type);536RSDK_ENUM_VAR("Left Entry", POPCORNMACHINE_LEFT);537RSDK_ENUM_VAR("Right Entry", POPCORNMACHINE_RIGHT);538RSDK_ENUM_VAR("Double Entry", POPCORNMACHINE_BOTH);539}540#endif541542void PopcornMachine_Serialize(void)543{544RSDK_EDITABLE_VAR(PopcornMachine, VAR_UINT8, type);545RSDK_EDITABLE_VAR(PopcornMachine, VAR_UINT8, height);546}547548549