Path: blob/master/SonicMania/Objects/PGZ/IceSpring.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: IceSpring Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectIceSpring *IceSpring;1011void IceSpring_Update(void)12{13RSDK_THIS(IceSpring);1415// this was unironically fun to decompile16// so many label jumps17// - RMG18self->activePlayers = 0;1920if (self->state) {21if (!self->animator.speed) {22// Bug Details:23// due to this foreach loop using playerID as a variable instead of player->playerID there's a bug where if you have P2 hit the spring24// while P1 is in debug mode the animator will be copied into P1's slot instead of P2's one Fix: use player->playerID or playerID =25// RSDK.GetEntitySlot(player) instead of a manual playerID variable26int32 playerID = 0;2728foreach_active(Player, player)29{30if (!self->planeFilter || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) {31int32 storeX = player->position.x;32int32 storeY = player->position.y;3334int32 collided = false;35if (player->state == Ice_PlayerState_Frozen)36collided = MathHelpers_CheckBoxCollision(self, &self->hitbox, player, &Ice->hitboxPlayerBlockOuter);37else38collided = MathHelpers_CheckBoxCollision(self, &self->hitbox, player, Player_GetHitbox(player));3940if (collided) {41int32 type = self->type;42bool32 canSpring = false;43switch (self->type) {44default:45case ICESPRING_DIAGONAL: break;4647case ICESPRING_VERTICAL: canSpring = (self->direction & FLIP_Y) ? collided == C_BOTTOM : collided == C_TOP; break;4849case ICESPRING_HORIZONTAL: canSpring = (self->direction & FLIP_X) ? collided == C_LEFT : collided == C_RIGHT; break;50}5152if (!canSpring && type == ICESPRING_DIAGONAL)53canSpring |= (player->onGround || player->velocity.y >= 0 || abs(player->velocity.x) > -player->velocity.y);5455if (canSpring) {56self->activePlayers |= 1 << playerID;57memcpy(&IceSpring->animators[playerID], &player->animator, sizeof(Animator));58}5960EntityShield *shield = RSDK_GET_ENTITY(Player->playerCount + RSDK.GetEntitySlot(player), Shield);61if (player->state != Ice_PlayerState_Frozen && shield->shieldAnimator.animationID != SHIELDANI_FIREATTACK62#if MANIA_USE_PLUS63&& player->state != Player_State_MightyHammerDrop64#endif65) {66if (player->shield == SHIELD_FIRE && player->invincibleTimer <= 0 && !self->shatterTimer) {67self->shatterTimer = 15;68Ice_ShatterGenerator(6, 8, 8, 0, 0, false);69}70}71else if (!canSpring72#if MANIA_USE_PLUS73|| player->state == Player_State_MightyHammerDrop74#endif75) {76switch (collided) {77case C_TOP: IceSpring_Shatter(0, 0); break;78case C_LEFT:79case C_RIGHT: IceSpring_Shatter(player->velocity.x, 0); break;80case C_BOTTOM: IceSpring_Shatter(0, player->velocity.y); break;81default: break;82}8384foreach_return;85}86}8788player->position.x = storeX;89player->position.y = storeY;90}9192++playerID;93}94}9596StateMachine_Run(self->state);9798for (int32 i = 0; i < Player->playerCount; ++i) {99if ((1 << i) & self->activePlayers) {100EntityPlayer *player = RSDK_GET_ENTITY(i, Player);101if (IceSpring->animators[i].animationID == ANI_JUMP)102memcpy(&player->animator, &IceSpring->animators[i], sizeof(Animator));103104player->applyJumpCap = false;105if (player->sidekick && self->activePlayers == 0b10) {106RSDK.SetSpriteAnimation(IceSpring->aniFrames, self->type, &self->animator, true, 0);107self->animator.speed = 0;108self->activePlayers = 0;109}110}111}112113RSDK.ProcessAnimation(&self->animator);114if (self->animator.frameID == 7)115IceSpring_Shatter(0, 0);116}117118if (self->shatterTimer > 0) {119if (self->animator.frameID <= 0) {120--self->shatterTimer;121if (self->shatterTimer <= 0)122IceSpring_Shatter(0, 0);123}124else125self->shatterTimer = 0;126}127}128129void IceSpring_LateUpdate(void) {}130131void IceSpring_StaticUpdate(void) {}132133void IceSpring_Draw(void)134{135RSDK_THIS(IceSpring);136137RSDK.DrawSprite(&self->animator, NULL, false);138}139140void IceSpring_Create(void *data)141{142RSDK_THIS(IceSpring);143144self->drawFX = FX_FLIP;145if (!SceneInfo->inEditor) {146self->type %= 3;147if (data) {148self->type = (VOID_TO_INT(data) >> 0) & 0xFF;149self->flipFlag = (VOID_TO_INT(data) >> 8) & 0xFF;150}151152RSDK.SetSpriteAnimation(IceSpring->aniFrames, self->type, &self->animator, true, 0);153self->active = ACTIVE_BOUNDS;154self->animator.speed = 0;155self->updateRange.x = 0x600000;156self->updateRange.y = 0x600000;157self->visible = true;158159if (self->planeFilter && ((uint8)(self->planeFilter - 1) & 2))160self->drawGroup = Zone->objectDrawGroup[1];161else162self->drawGroup = Zone->objectDrawGroup[0];163164switch (self->type) {165case ICESPRING_VERTICAL:166self->velocity.y = 0x80000 * (self->flipFlag ? 1 : -1);167self->direction = self->flipFlag;168169self->hitbox.left = -16;170self->hitbox.top = -8;171self->hitbox.right = 16;172self->hitbox.bottom = 8;173174self->state = Spring_State_Vertical;175break;176177case ICESPRING_HORIZONTAL:178self->velocity.x = 0x80000 * (self->flipFlag ? -1 : 1);179self->direction = self->flipFlag;180181self->hitbox.left = -8;182self->hitbox.top = -16;183self->hitbox.right = 8;184self->hitbox.bottom = 16;185186self->state = Spring_State_Horizontal;187break;188189case ICESPRING_DIAGONAL:190self->direction = self->flipFlag;191self->velocity.x = 0x54000 * ((self->flipFlag & 1) ? -1 : 1);192self->velocity.y = 0x54000 * ((self->flipFlag < 2) ? -1 : 1);193194self->hitbox.left = -12;195self->hitbox.top = -12;196self->hitbox.right = 12;197self->hitbox.bottom = 12;198199self->state = Spring_State_Diagonal;200break;201}202}203}204205void IceSpring_StageLoad(void)206{207IceSpring->aniFrames = RSDK.LoadSpriteAnimation("PSZ2/IceSpring.bin", SCOPE_STAGE);208209IceSpring->sfxBounce = RSDK.GetSfx("Global/Spring.wav");210IceSpring->sfxShatter = RSDK.GetSfx("Stage/WindowShatter.wav");211}212213void IceSpring_Shatter(int32 velX, int32 velY)214{215RSDK_THIS(IceSpring);216217RSDK.PlaySfx(IceSpring->sfxShatter, false, 255);218Ice_ShatterGenerator(16, 8, 8, velX, velY, false);219220if (self->type < ICESPRING_DIAGONAL)221destroyEntity(self);222else223self->animator.frameID = 7;224}225226#if GAME_INCLUDE_EDITOR227void IceSpring_EditorDraw(void)228{229RSDK_THIS(IceSpring);230231RSDK.SetSpriteAnimation(IceSpring->aniFrames, self->type % 3, &self->animator, true, 0);232self->direction = self->flipFlag & 3;233234IceSpring_Draw();235}236237void IceSpring_EditorLoad(void)238{239IceSpring->aniFrames = RSDK.LoadSpriteAnimation("PSZ2/IceSpring.bin", SCOPE_STAGE);240241RSDK_ACTIVE_VAR(IceSpring, type);242RSDK_ENUM_VAR("Vertical", ICESPRING_VERTICAL);243RSDK_ENUM_VAR("Horizontal", ICESPRING_HORIZONTAL);244RSDK_ENUM_VAR("Diagonal", ICESPRING_DIAGONAL);245246RSDK_ACTIVE_VAR(IceSpring, flipFlag);247RSDK_ENUM_VAR("No Flip", FLIP_NONE);248RSDK_ENUM_VAR("Flip X", FLIP_X);249RSDK_ENUM_VAR("Flip Y", FLIP_Y);250RSDK_ENUM_VAR("Flip XY", FLIP_XY);251252RSDK_ACTIVE_VAR(IceSpring, planeFilter);253RSDK_ENUM_VAR("None", PLANEFILTER_NONE);254RSDK_ENUM_VAR("AL", PLANEFILTER_AL);255RSDK_ENUM_VAR("BL", PLANEFILTER_BL);256RSDK_ENUM_VAR("AH", PLANEFILTER_AH);257RSDK_ENUM_VAR("BH", PLANEFILTER_BH);258}259#endif260261void IceSpring_Serialize(void)262{263RSDK_EDITABLE_VAR(IceSpring, VAR_ENUM, type);264RSDK_EDITABLE_VAR(IceSpring, VAR_ENUM, flipFlag);265RSDK_EDITABLE_VAR(IceSpring, VAR_BOOL, onGround);266RSDK_EDITABLE_VAR(IceSpring, VAR_UINT8, planeFilter);267}268269270