Path: blob/master/SonicMania/Objects/PGZ/FrostThrower.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: FrostThrower Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectFrostThrower *FrostThrower;1011void FrostThrower_Update(void)12{13RSDK_THIS(FrostThrower);1415StateMachine_Run(self->state);16}1718void FrostThrower_LateUpdate(void) {}1920void FrostThrower_StaticUpdate(void) {}2122void FrostThrower_Draw(void)23{24RSDK_THIS(FrostThrower);2526RSDK.DrawSprite(&self->dispenseAnimator, NULL, false);2728if (self->isActive)29FrostThrower_DrawGustFX();30}3132void FrostThrower_Create(void *data)33{34RSDK_THIS(FrostThrower);3536self->active = ACTIVE_BOUNDS;37self->visible = true;38self->drawFX = FX_FLIP;39self->drawGroup = Zone->playerDrawGroup[0] + 1;40self->updateRange.x = 0x100000;41self->updateRange.y = 0x100000;4243self->hitbox.left = -14;44self->hitbox.right = 15;45self->maxGustCount[0] = 2;46self->maxGustCount[1] = 2;47self->maxGustCount[2] = 3;48self->maxGustCount[3] = 3;4950FrostThrower_HandleGustCount();51FrostThrower_HandleGustPos();5253RSDK.SetSpriteAnimation(FrostThrower->aniFrames, 0, &self->dispenseAnimator, true, 0);54RSDK.SetSpriteAnimation(FrostThrower->aniFrames, 1, &self->gustAnimator, true, 0);5556self->state = FrostThrower_State_AwaitInterval;57}5859void FrostThrower_StageLoad(void)60{61if (RSDK.CheckSceneFolder("PSZ1"))62FrostThrower->aniFrames = RSDK.LoadSpriteAnimation("PSZ1/FrostThrower.bin", SCOPE_STAGE); // this doesn't actually exist in the final game...63else if (RSDK.CheckSceneFolder("PSZ2"))64FrostThrower->aniFrames = RSDK.LoadSpriteAnimation("PSZ2/FrostThrower.bin", SCOPE_STAGE);6566FrostThrower->sfxFrostThrower = RSDK.GetSfx("PSZ/FrostThrower.wav");67FrostThrower->sfxFreeze = RSDK.GetSfx("PSZ/Freeze.wav");68}6970void FrostThrower_DrawGustFX(void)71{72RSDK_THIS(FrostThrower);7374int32 pos = 0;75for (int32 i = 0; i < 4; ++i) {76int32 count = MIN(self->gustCount[i], 3);7778RSDK.SetSpriteAnimation(FrostThrower->aniFrames, 1, &self->gustAnimator, true, i);79for (int32 p = 0; p < count; ++p) {80Vector2 drawPos;81drawPos.x = self->position.x + self->gustPos[pos + p].x;82drawPos.y = self->position.y + self->gustPos[pos + p].y;83RSDK.DrawSprite(&self->gustAnimator, &drawPos, false);84}8586pos += 3;87}88}8990void FrostThrower_CheckPlayerCollisions(void)91{92RSDK_THIS(FrostThrower);9394foreach_active(Player, player)95{96int32 playerID = RSDK.GetEntitySlot(player);9798if (Player_CheckCollisionTouch(player, self, &self->hitbox) && !Ice->playerTimers[playerID])99Ice_FreezePlayer(player);100}101}102103void FrostThrower_HandleGustCount(void)104{105RSDK_THIS(FrostThrower);106107for (int32 i = 0; i < 4; ++i) {108self->gustCount[i] = self->maxGustCount[i];109if (self->maxGustCount[i] > 1) {110if (RSDK.Rand(0, 10) <= 6)111self->gustCount[i] = RSDK.Rand(1, self->maxGustCount[i]);112}113}114}115116void FrostThrower_HandleGustPos(void)117{118RSDK_THIS(FrostThrower);119int32 pos = 0;120121int32 yMin[] = { 2, 20, 45, 55 };122int32 yMax[] = { 22, 45, 62, 78 };123int32 xMin[] = { -3, -5, -7, -9 };124int32 xMax[] = { 3, 5, 7, 9 };125for (int32 i = 0; i < 4; ++i) {126for (int32 p = 0; p < self->gustCount[i]; ++p) {127self->gustPos[pos + p].x = RSDK.Rand(xMin[i], xMax[i]) << 16;128self->gustPos[pos + p].y = RSDK.Rand(yMin[i], yMax[i]) << 16;129}130pos += 3;131}132}133134void FrostThrower_State_AwaitInterval(void)135{136RSDK_THIS(FrostThrower);137138if (!((Zone->timer + self->intervalOffset) % self->interval)) {139self->active = ACTIVE_NORMAL;140self->timer = 0;141self->isActive = true;142self->state = FrostThrower_State_Dispensing;143RSDK.PlaySfx(FrostThrower->sfxFrostThrower, false, 255);144}145}146147void FrostThrower_State_Dispensing(void)148{149RSDK_THIS(FrostThrower);150151self->hitbox.top = 0;152if (self->timer >= 20)153self->hitbox.bottom = 80;154else155self->hitbox.bottom = 4 * self->timer;156157FrostThrower_CheckPlayerCollisions();158159if (self->timer > 3)160self->maxGustCount[0] = 2;161else162self->maxGustCount[0] = 1;163164if (self->timer > 8)165self->maxGustCount[1] = 2;166else if (self->timer > 5)167self->maxGustCount[1] = 1;168else169self->maxGustCount[1] = 0;170171if (self->timer > 16)172self->maxGustCount[2] = 3;173else if (self->timer > 14)174self->maxGustCount[2] = 2;175else if (self->timer > 12)176self->maxGustCount[2] = 1;177else178self->maxGustCount[2] = 0;179180if (self->timer > 19)181self->maxGustCount[3] = 3;182else if (self->timer > 17)183self->maxGustCount[3] = 2;184else if (self->timer > 15)185self->maxGustCount[3] = 1;186else187self->maxGustCount[3] = 0;188189FrostThrower_HandleGustCount();190FrostThrower_HandleGustPos();191192if (++self->timer >= self->duration) {193self->state = FrostThrower_State_StopDispensing;194self->timer = 0;195}196}197198void FrostThrower_State_StopDispensing(void)199{200RSDK_THIS(FrostThrower);201202self->hitbox.top = 4 * self->timer;203self->hitbox.bottom = 80;204205FrostThrower_CheckPlayerCollisions();206207if (self->timer > 8)208self->maxGustCount[0] = 0;209else if (self->timer > 5)210self->maxGustCount[0] = 1;211else212self->maxGustCount[1] = 2;213214if (self->timer > 8)215self->maxGustCount[1] = 0;216else if (self->timer > 5)217self->maxGustCount[1] = 1;218else219self->maxGustCount[1] = 2;220221if (self->timer > 19)222self->maxGustCount[2] = 0;223else if (self->timer > 17)224self->maxGustCount[2] = 1;225else if (self->timer > 15)226self->maxGustCount[2] = 2;227else228self->maxGustCount[2] = 3;229230if (self->timer > 16)231self->maxGustCount[3] = 0;232else if (self->timer > 14)233self->maxGustCount[3] = 1;234else if (self->timer > 12)235self->maxGustCount[3] = 2;236else237self->maxGustCount[3] = 3;238239FrostThrower_HandleGustCount();240FrostThrower_HandleGustPos();241242if (self->timer++ >= 20) {243self->active = ACTIVE_BOUNDS;244self->isActive = false;245self->state = FrostThrower_State_AwaitInterval;246self->timer = 0;247}248}249250#if GAME_INCLUDE_EDITOR251void FrostThrower_EditorDraw(void)252{253RSDK_THIS(FrostThrower);254255RSDK.SetSpriteAnimation(FrostThrower->aniFrames, 0, &self->dispenseAnimator, true, 0);256RSDK.SetSpriteAnimation(FrostThrower->aniFrames, 1, &self->gustAnimator, true, 0);257258FrostThrower_Draw();259}260261void FrostThrower_EditorLoad(void)262{263if (RSDK.CheckSceneFolder("PSZ1"))264FrostThrower->aniFrames = RSDK.LoadSpriteAnimation("PSZ1/FrostThrower.bin", SCOPE_STAGE);265else if (RSDK.CheckSceneFolder("PSZ2"))266FrostThrower->aniFrames = RSDK.LoadSpriteAnimation("PSZ2/FrostThrower.bin", SCOPE_STAGE);267}268#endif269270void FrostThrower_Serialize(void)271{272RSDK_EDITABLE_VAR(FrostThrower, VAR_UINT16, interval);273RSDK_EDITABLE_VAR(FrostThrower, VAR_UINT16, intervalOffset);274RSDK_EDITABLE_VAR(FrostThrower, VAR_UINT16, duration);275}276277278