Path: blob/master/SonicMania/Objects/PGZ/Crate.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Crate Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectCrate *Crate;1011void Crate_Update(void)12{13RSDK_THIS(Crate);1415if (self->collision != PLATFORM_C_SOLID || !Crate_Collide()) {16if (self->animator.animationID) {17StateMachine_Run(self->state);18}19else {20Platform_Update();21}22}23}2425void Crate_LateUpdate(void) {}2627void Crate_StaticUpdate(void) {}2829void Crate_Draw(void)30{31RSDK_THIS(Crate);32RSDK.DrawSprite(&self->animator, &self->drawPos, false);33}3435void Crate_Create(void *data)36{37RSDK_THIS(Crate);3839int32 frameID = self->frameID;40if (frameID == 3)41self->collision = PLATFORM_C_NONE;42else43self->collision = PLATFORM_C_SOLID;4445Platform_Create(NULL);46self->frameID = frameID;4748if (!SceneInfo->inEditor) {49self->hitbox.left = -24;50self->hitbox.top = -24;51self->hitbox.right = 24;52self->hitbox.bottom = 24;5354self->active = ACTIVE_XBOUNDS;55self->drawFX = FX_SCALE | FX_FLIP;56self->scale.x = 0x200;57self->scale.y = 0x200;58self->drawGroup = frameID == 3 ? Zone->objectDrawGroup[0] : Zone->objectDrawGroup[1];59RSDK.SetSpriteAnimation(Crate->aniFrames, 0, &self->animator, true, frameID);60self->state = Crate_State_None;61}62}6364void Crate_StageLoad(void)65{66if (RSDK.CheckSceneFolder("PSZ1"))67Crate->aniFrames = RSDK.LoadSpriteAnimation("PSZ1/Crate.bin", SCOPE_STAGE);6869Crate->sfxExplosion2 = RSDK.GetSfx("Stage/Explosion2.wav");70}7172void Crate_Break(EntityCrate *create)73{74for (int32 s = 0; s < 64; ++s) {75// ice is used to create a shattering effect76int32 x = create->position.x + (RSDK.Rand(-24, 25) << 16);77int32 y = create->position.y + (RSDK.Rand(-24, 25) << 16);78EntityIce *ice = CREATE_ENTITY(Ice, INT_TO_VOID(ICE_CHILD_SHARD), x, y);7980ice->velocity.x = RSDK.Rand(-6, 8) << 15;81ice->velocity.y = RSDK.Rand(-10, 2) << 15;82ice->direction = RSDK.Rand(0, 4);83ice->blockAnimator.speed = RSDK.Rand(1, 4);84ice->drawGroup = Zone->objectDrawGroup[0] + 1;8586switch (create->animator.frameID) {87case 0:88case 3: RSDK.SetSpriteAnimation(Crate->aniFrames, 1, &ice->blockAnimator, true, 0); break;8990case 1:91case 2:92if (RSDK.Rand(0, 6) >= 2)93RSDK.SetSpriteAnimation(Crate->aniFrames, 2, &ice->blockAnimator, true, 0);94else95RSDK.SetSpriteAnimation(Crate->aniFrames, 3, &ice->blockAnimator, true, 0);96break;9798default: break;99}100}101102RSDK.PlaySfx(Crate->sfxExplosion2, false, 255);103create->position.y -= 0x10000;104105foreach_active(Crate, crate)106{107if (crate != create && crate->state == Crate_State_None108&& RSDK.CheckObjectCollisionTouchBox(create, &create->hitbox, crate, &crate->hitbox)) {109crate->state = Crate_State_ApplyGravity;110}111}112113destroyEntity(create);114}115void Crate_MoveY(EntityCrate *self, int32 offset)116{117self->drawPos.y += offset;118self->centerPos.x = self->drawPos.x;119self->centerPos.y = self->drawPos.y;120self->position.x = self->drawPos.x;121self->position.y = self->drawPos.y;122123int32 start = (self->drawPos.y - 0x300000) & 0xFFFF0000;124foreach_active(Crate, crate)125{126if (crate != self && RSDK.CheckObjectCollisionBox(self, &self->hitbox, crate, &crate->hitbox, true) == C_TOP)127Crate_MoveY(crate, start - crate->drawPos.y);128}129}130bool32 Crate_Collide(void)131{132RSDK_THIS(Crate);133134foreach_active(Player, player)135{136int32 storeX = player->position.x;137int32 storeY = player->position.y;138int32 storeXVel = player->velocity.x;139int32 storeYVel = player->velocity.y;140int32 storeVel = player->groundVel;141int32 storeGrounded = player->onGround;142Hitbox *playerHitbox = Player_GetHitbox(player);143144int32 shieldAnim = RSDK_GET_ENTITY(Player->playerCount + RSDK.GetEntitySlot(player), Shield)->shieldAnimator.animationID;145146switch (MathHelpers_CheckBoxCollision(self, &self->hitbox, player, playerHitbox)) {147default:148case C_NONE:149player->velocity.x = storeXVel;150player->velocity.y = storeYVel;151player->position.x = storeX;152player->position.y = storeY;153Player_CheckCollisionBox(player, self, &self->hitbox);154break;155156case C_TOP:157if (self->frameID != 1) {158player->velocity.x = storeXVel;159player->velocity.y = storeYVel;160player->position.x = storeX;161player->position.y = storeY;162Player_CheckCollisionBox(player, self, &self->hitbox);163break;164}165#if MANIA_USE_PLUS166else if (player->state == Player_State_MightyHammerDrop) {167player->velocity.y -= 0x10000;168Crate_Break(self);169player->velocity.x = storeXVel;170player->velocity.y = storeYVel;171player->position.x = storeX;172player->position.y = storeY;173player->groundVel = storeVel;174player->onGround = storeGrounded;175foreach_return true;176}177#endif178else if (player->shield == SHIELD_BUBBLE && player->invincibleTimer <= 0) {179if (shieldAnim == 8 && player->velocity.y >= 0x80000) {180Crate_Break(self);181player->velocity.x = storeXVel;182player->velocity.y = storeYVel;183player->position.x = storeX;184player->position.y = storeY;185player->groundVel = storeVel;186player->onGround = storeGrounded;187foreach_return true;188}189}190191player->velocity.x = storeXVel;192player->velocity.y = storeYVel;193player->position.x = storeX;194player->position.y = storeY;195Player_CheckCollisionBox(player, self, &self->hitbox);196break;197198case C_LEFT:199case C_RIGHT:200if (self->frameID != 1 || player->shield != SHIELD_FIRE || player->invincibleTimer > 0 || shieldAnim != 2) {201player->velocity.x = storeXVel;202player->velocity.y = storeYVel;203player->position.x = storeX;204player->position.y = storeY;205Player_CheckCollisionBox(player, self, &self->hitbox);206}207else if (player->position.x < self->position.x) {208player->velocity.x = storeXVel;209player->velocity.y = storeYVel;210player->position.x = storeX;211player->position.y = storeY;212213if (player->velocity.x >= 0x78000) {214Crate_Break(self);215player->groundVel = storeVel;216player->onGround = storeGrounded;217foreach_return true;218}219else {220Player_CheckCollisionBox(player, self, &self->hitbox);221}222}223else {224player->velocity.x = storeXVel;225player->velocity.y = storeYVel;226player->position.x = storeX;227player->position.y = storeY;228229if (player->velocity.x <= -0x78000) {230Crate_Break(self);231232player->groundVel = storeVel;233player->onGround = storeGrounded;234foreach_return true;235}236else {237Player_CheckCollisionBox(player, self, &self->hitbox);238}239}240break;241242case C_BOTTOM:243if (self->collisionOffset.y >= 0)244player->collisionFlagV |= 2;245246player->velocity.x = storeXVel;247player->velocity.y = storeYVel;248player->position.x = storeX;249player->position.y = storeY;250Player_CheckCollisionBox(player, self, &self->hitbox);251break;252}253}254255return false;256}257void Crate_State_None(void)258{259// hehe260}261void Crate_State_ApplyGravity(void)262{263RSDK_THIS(Crate);264265self->position.y -= 0x10000;266267foreach_active(Crate, crate)268{269if (crate != self && crate->state == Crate_State_None && RSDK.CheckObjectCollisionTouchBox(self, &self->hitbox, crate, &crate->hitbox)) {270crate->state = Crate_State_ApplyGravity;271}272}273274self->position.y += 0x10000;275self->timer = 15;276self->state = Crate_State_WaitToFall;277}278void Crate_State_WaitToFall(void)279{280RSDK_THIS(Crate);281282if (--self->timer <= 0)283self->state = Crate_State_Fall;284}285void Crate_State_Fall(void)286{287RSDK_THIS(Crate);288289self->drawPos.y += self->velocity.y;290291int32 x = self->position.x;292int32 y = self->position.y;293294self->velocity.y += 0x3800;295self->position.x = self->drawPos.x;296self->position.y = self->drawPos.y;297298if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, 0, CMODE_FLOOR, 0, 0x180000, true)) {299self->velocity.y = 0;300self->state = Crate_State_None;301}302else {303foreach_active(Crate, crate)304{305if (crate != self && !crate->velocity.y && RSDK.CheckObjectCollisionBox(crate, &crate->hitbox, self, &self->hitbox, true) == C_TOP) {306self->velocity.y = 0;307self->state = Crate_State_None;308}309}310}311312self->drawPos.x = self->position.x;313self->drawPos.y = self->position.y;314self->centerPos.x = self->position.x;315self->centerPos.y = self->position.y;316317self->position.x = x;318self->position.y = y;319}320321#if GAME_INCLUDE_EDITOR322void Crate_EditorDraw(void)323{324RSDK_THIS(Crate);325326RSDK.SetSpriteAnimation(Crate->aniFrames, 0, &self->animator, true, self->frameID);327self->drawPos = self->position;328329Crate_Draw();330331if (showGizmos()) {332RSDK_DRAWING_OVERLAY(true);333334for (int32 s = SceneInfo->entitySlot + 1, i = 0; i < self->childCount; ++i) {335Entity *child = RSDK_GET_ENTITY_GEN(s + i);336if (!child)337continue;338339DrawHelpers_DrawArrow(self->position.x, self->position.y, child->position.x, child->position.y, 0xE0E0E0, INK_NONE, 0xFF);340}341342RSDK_DRAWING_OVERLAY(false);343}344}345346void Crate_EditorLoad(void)347{348Crate->aniFrames = RSDK.LoadSpriteAnimation("PSZ1/Crate.bin", SCOPE_STAGE);349350RSDK_ACTIVE_VAR(Crate, frameID);351RSDK_ENUM_VAR("Blue", CRATE_FRAME_BLUE);352RSDK_ENUM_VAR("Orange (Broken)", CRATE_FRAME_ORANGE_BROKEN);353RSDK_ENUM_VAR("Orange", CRATE_FRAME_ORANGE);354RSDK_ENUM_VAR("Blue (BG)", CRATE_FRAME_BLUE_BG);355}356#endif357358void Crate_Serialize(void)359{360RSDK_EDITABLE_VAR(Crate, VAR_UINT8, frameID);361RSDK_EDITABLE_VAR(Crate, VAR_ENUM, childCount);362RSDK_EDITABLE_VAR(Crate, VAR_BOOL, ignoreItemBox);363}364365366