Path: blob/master/SonicMania/Objects/PGZ/PetalPile.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: PetalPile Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectPetalPile *PetalPile;1011void PetalPile_Update(void)12{13RSDK_THIS(PetalPile);1415StateMachine_Run(self->state);1617if (!self->animator.animationID)18RSDK.ProcessAnimation(&self->animator);19}2021void PetalPile_LateUpdate(void) {}2223void PetalPile_StaticUpdate(void) {}2425void PetalPile_Draw(void)26{27RSDK_THIS(PetalPile);28StateMachine_Run(self->stateDraw);29}3031void PetalPile_Create(void *data)32{33RSDK_THIS(PetalPile);3435self->active = ACTIVE_BOUNDS;36self->visible = true;37self->drawGroup = Zone->objectDrawGroup[1];38self->drawFX = FX_FLIP;39self->updateRange.x = 0x100000;40self->updateRange.y = 0x100000;4142if (SceneInfo->inEditor) {43if (!self->maxSpeed.x)44self->maxSpeed.x = 0x18000;4546if (!self->pileSize.x && !self->pileSize.y) {47self->pileSize.x = 0x300000;48self->pileSize.y = 0x80000;49}50}51else {52if (self->tileLayer)53self->layerID = RSDK.GetTileLayerID("FG Low");54else55self->layerID = RSDK.GetTileLayerID("FG High");56}5758RSDK.SetSpriteAnimation(PetalPile->aniFrames, 0, &self->animator, true, 0);59self->state = PetalPile_State_Init;60}6162void PetalPile_StageLoad(void)63{64if (RSDK.CheckSceneFolder("PSZ1"))65PetalPile->aniFrames = RSDK.LoadSpriteAnimation("PSZ1/Petal.bin", SCOPE_STAGE);66else if (RSDK.CheckSceneFolder("PSZ2"))67PetalPile->aniFrames = RSDK.LoadSpriteAnimation("PSZ2/Petal.bin", SCOPE_STAGE);6869PetalPile->sfxPetals = RSDK.GetSfx("PSZ/Petals.wav");70}7172int32 PetalPile_GetLeafPattern(Vector2 *patternPtr)73{74RSDK_THIS(PetalPile);7576int32 count = PetalPile->patternSize[self->leafPattern];77int32 *pattern = NULL;78switch (self->leafPattern) {79case PETALPILE_PATTERN_0: pattern = PetalPile->pattern1; break;80case PETALPILE_PATTERN_1: pattern = PetalPile->pattern2; break;81case PETALPILE_PATTERN_2: pattern = PetalPile->pattern3; break;82case PETALPILE_PATTERN_3: pattern = PetalPile->pattern4; break;83case PETALPILE_PATTERN_4: pattern = PetalPile->pattern5; break;84default: return 0;85}8687int32 sizeX = MAX(self->pileSize.x, 0x20000);88int32 sizeY = MAX(self->pileSize.y, 0x20000);89for (int32 i = 0; i < count; ++i) {90patternPtr[i].x = pattern[(i * 2) + 0] * (sizeX >> 17);91patternPtr[i].y = pattern[(i * 2) + 1] * (sizeY >> 17);92}9394return count;95}9697void PetalPile_State_Init(void)98{99RSDK_THIS(PetalPile);100101self->hitbox.left = -(self->pileSize.x >> 17);102self->hitbox.top = -(self->pileSize.y >> 17);103self->hitbox.right = self->pileSize.x >> 17;104self->hitbox.bottom = self->pileSize.y >> 17;105106if (self->noRemoveTiles) {107self->state = PetalPile_State_SetupEmitter;108PetalPile_State_SetupEmitter();109}110else {111self->state = PetalPile_State_HandleInteractions;112PetalPile_State_HandleInteractions();113}114}115116void PetalPile_State_HandleInteractions(void)117{118RSDK_THIS(PetalPile);119120foreach_active(Player, player)121{122if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {123if (!player->sidekick) {124if (abs(player->groundVel) >= 0x60000 || player->velocity.y > 0x60000 || player->velocity.y < -0x70000125|| player->state == Player_State_Spindash || player->state == Player_State_DropDash) {126bool32 isFast = false;127if (player->state == Player_State_Spindash || player->state == Player_State_DropDash || abs(player->groundVel) >= 0x60000)128isFast = true;129130self->petalDir = isFast * (2 * (player->direction != FLIP_NONE) - 1);131132if (player->state == Player_State_Spindash || player->state == Player_State_DropDash)133self->petalRadius = 0xF5555;134else135self->petalRadius = 0xB5555;136137self->petalVel = player->groundVel >> 1;138self->distance.x = player->position.x - self->position.x;139self->distance.y = 0;140RSDK.PlaySfx(PetalPile->sfxPetals, false, 255);141self->state = PetalPile_State_SetupEmitter;142143foreach_break;144}145}146147if (!self->emitterMode && abs(player->groundVel) < 0x60000 && abs(player->groundVel) > abs(self->maxSpeed.x))148player->groundVel =149player->groundVel - ((abs(player->groundVel) - abs(self->maxSpeed.x)) >> 1) * (((player->groundVel >> 31) & -2) + 1);150}151}152153if (self->state != PetalPile_State_SetupEmitter) {154Hitbox hitbox;155hitbox.left = -8;156hitbox.top = -8;157hitbox.right = 8;158hitbox.bottom = 8;159160foreach_active(Explosion, explosion)161{162if (RSDK.CheckObjectCollisionTouchBox(self, &self->hitbox, explosion, &hitbox)) {163self->petalDir = 0;164self->petalRadius = 0xF5555;165self->distance.x = explosion->position.x - self->position.x;166self->distance.y = 0;167RSDK.PlaySfx(PetalPile->sfxPetals, false, 255);168self->state = PetalPile_State_SetupEmitter;169170foreach_break;171}172}173}174}175176void PetalPile_State_SetupEmitter(void)177{178RSDK_THIS(PetalPile);179180Vector2 pattern[0x100];181memset(pattern, 0, sizeof(pattern));182int32 count = PetalPile_GetLeafPattern(pattern);183184int32 offsetX = 0, offsetY = 0;185switch (self->petalDir) {186case -1:187offsetX = self->position.x + ((self->hitbox.right + 16) << 16);188offsetY = self->position.y + ((self->hitbox.bottom + 32) << 16);189break;190191case 0:192offsetX = self->position.x + self->distance.x;193offsetY = self->position.y + ((self->hitbox.bottom + 32) << 16);194break;195196case 1:197offsetX = self->position.x + ((self->hitbox.left - 16) << 16);198offsetY = self->position.y + ((self->hitbox.bottom + 32) << 16);199break;200}201202int32 pos = 0;203for (int32 i = 0; i < count; ++i) pos = MAX(pos, abs((self->position.x - offsetX) + pattern[i].x));204205for (int32 i = 0; i < count; ++i) {206int32 spawnX = pattern[i].x + self->position.x;207int32 spawnY = pattern[i].y + self->position.y;208209int32 angle = RSDK.ATan2(spawnX - offsetX, spawnY - offsetY);210EntityPetalPile *petal = CREATE_ENTITY(PetalPile, self, spawnX, spawnY);211petal->state = PetalPile_StateLeaf_Setup;212petal->stateDraw = PetalPile_Draw_Leaf;213214int32 radius = self->petalRadius >> 1;215if (self->petalDir) {216petal->direction = self->petalDir <= 0;217petal->petalVel = self->petalVel;218radius = (self->petalRadius >> 8) * ((16 * (abs(spawnX - offsetX) / (pos >> 16))) >> 12);219petal->timer = (pos - abs(spawnX - offsetX)) >> 18;220}221else {222petal->direction = ZONE_RAND(FLIP_NONE, FLIP_X);223}224225petal->velStore.x = (radius >> 8) * RSDK.Cos256(angle);226petal->velStore.y = (radius >> 9) * RSDK.Sin256(angle) - 0x20000;227petal->drawGroup = self->tileLayer ? Zone->objectDrawGroup[0] : Zone->objectDrawGroup[1];228}229230if (self->emitterMode) {231self->state = PetalPile_State_Emitter;232}233else {234if (!self->noRemoveTiles) {235int32 left = (self->position.x >> 16) + self->hitbox.left;236int32 right = (self->position.x >> 16) + self->hitbox.right;237int32 top = (self->position.y >> 16) + self->hitbox.top;238int32 bottom = (self->position.y >> 16) + self->hitbox.bottom;239240int32 sizeX = (right >> 4) - (left >> 4);241int32 sizeY = (bottom >> 4) - (top >> 4);242for (int32 x = 0; x <= sizeX; ++x) {243for (int32 y = 0; y <= sizeY; ++y) {244RSDK.SetTile(self->layerID, x + (left >> 4), y + (top >> 4), -1);245}246}247}248249destroyEntity(self);250}251}252253void PetalPile_State_Emitter(void)254{255RSDK_THIS(PetalPile);256257bool32 collided = false;258foreach_active(Player, player)259{260if (Player_CheckCollisionTouch(player, self, &self->hitbox))261collided = true;262}263264if (!collided)265self->state = PetalPile_State_Init;266}267268void PetalPile_StateLeaf_Setup(void)269{270RSDK_THIS(PetalPile);271272self->hitbox.left = -1;273self->hitbox.top = -1;274self->hitbox.right = 1;275self->hitbox.bottom = 1;276277self->active = ACTIVE_NORMAL;278self->updateRange.x = 0x10000;279self->updateRange.y = 0x10000;280RSDK.SetSpriteAnimation(PetalPile->aniFrames, 0, &self->animator, true, 0);281282self->state = PetalPile_StateLeaf_Delay;283PetalPile_StateLeaf_Delay();284}285286void PetalPile_StateLeaf_Delay(void)287{288RSDK_THIS(PetalPile);289290if (self->timer <= 0) {291self->state = PetalPile_StateLeaf_HandleVelocity;292self->timer = 0;293self->velocity = self->velStore;294}295else {296self->timer--;297}298299if (!RSDK.CheckOnScreen(self, &self->updateRange))300destroyEntity(self);301}302303void PetalPile_StateLeaf_HandleVelocity(void)304{305RSDK_THIS(PetalPile);306307if (self->petalVel > 0) {308self->petalVel -= 4096;309if (self->petalVel < 0)310self->petalVel = 0;311}312else if (self->petalVel < 0) {313self->petalVel += 0x1000;314if (self->petalVel > 0)315self->petalVel = 0;316}317318self->position.x += self->petalVel;319320if (self->velocity.x <= 0)321self->velocity.x += MIN(abs(self->velocity.x), 0x8000);322else323self->velocity.x -= MIN(abs(self->velocity.x), 0x8000);324self->velocity.y += 0x4000;325326if (self->velocity.y > 0)327self->velocity.y = 0;328329self->position.x += self->velocity.x;330self->position.y += self->velocity.y;331332if (++self->timer > 2) {333if (ZONE_RAND(0, 10) > 6)334self->direction = self->direction == FLIP_NONE;335336self->timer = 0;337}338339if (self->velocity.y >= 0 && !self->velocity.x) {340self->petalOffset = ZONE_RAND(0, 255);341self->state = PetalPile_StateLeaf_Fall;342}343344if (!RSDK.CheckOnScreen(self, &self->updateRange))345destroyEntity(self);346}347348void PetalPile_StateLeaf_Fall(void)349{350RSDK_THIS(PetalPile);351352if (self->petalVel > 0) {353self->petalVel -= 4096;354if (self->petalVel < 0)355self->petalVel = 0;356}357else if (self->petalVel < 0) {358self->petalVel += 0x1000;359if (self->petalVel > 0)360self->petalVel = 0;361}362363self->position.x += self->petalVel;364365self->velocity.y += 0x4000;366if (self->velocity.y > 0x10000)367self->velocity.y = 0x10000;368369self->velocity.x = RSDK.Sin256(4 * self->petalOffset) << 8;370371self->position.x += self->velocity.x;372self->position.y += self->velocity.y;373374++self->timer;375if (self->timer > 3) {376if (ZONE_RAND(0, 10) > 6)377self->direction = self->direction == FLIP_NONE;378379self->timer = 0;380}381382if (!RSDK.CheckOnScreen(self, &self->updateRange))383destroyEntity(self);384385self->petalOffset++;386}387388void PetalPile_Draw_Leaf(void)389{390RSDK_THIS(PetalPile);391392RSDK.DrawSprite(&self->animator, NULL, false);393}394395#if GAME_INCLUDE_EDITOR396void PetalPile_EditorDraw(void)397{398RSDK_THIS(PetalPile);399400DrawHelpers_DrawRectOutline(self->position.x, self->position.y, self->pileSize.x, self->pileSize.y, 0xFFFF00);401}402403void PetalPile_EditorLoad(void)404{405if (RSDK.CheckSceneFolder("PSZ1"))406PetalPile->aniFrames = RSDK.LoadSpriteAnimation("PSZ1/Petal.bin", SCOPE_STAGE);407else if (RSDK.CheckSceneFolder("PSZ2"))408PetalPile->aniFrames = RSDK.LoadSpriteAnimation("PSZ2/Petal.bin", SCOPE_STAGE);409410RSDK_ACTIVE_VAR(PetalPile, leafPattern);411RSDK_ENUM_VAR("Pattern 0", PETALPILE_PATTERN_0);412RSDK_ENUM_VAR("Pattern 1", PETALPILE_PATTERN_1);413RSDK_ENUM_VAR("Pattern 2", PETALPILE_PATTERN_2);414RSDK_ENUM_VAR("Pattern 3", PETALPILE_PATTERN_3);415RSDK_ENUM_VAR("Pattern 4", PETALPILE_PATTERN_4);416417RSDK_ACTIVE_VAR(PetalPile, tileLayer);418RSDK_ENUM_VAR("FG High", PETALPILE_FGHIGH);419RSDK_ENUM_VAR("FG Low", PETALPILE_FGLOW);420}421#endif422423void PetalPile_Serialize(void)424{425RSDK_EDITABLE_VAR(PetalPile, VAR_INT8, leafPattern);426RSDK_EDITABLE_VAR(PetalPile, VAR_INT8, tileLayer);427RSDK_EDITABLE_VAR(PetalPile, VAR_VECTOR2, pileSize);428RSDK_EDITABLE_VAR(PetalPile, VAR_VECTOR2, maxSpeed);429RSDK_EDITABLE_VAR(PetalPile, VAR_BOOL, emitterMode);430}431432433