Path: blob/master/SonicMania/Objects/SSZ/BouncePlant.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: BouncePlant Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectBouncePlant *BouncePlant;1011void BouncePlant_Update(void)12{13RSDK_THIS(BouncePlant);14if (self->stood) {15if (self->instantRecoil) {16self->depression = 0x100;17}18else {19if (self->depression < 0x100)20self->depression += 0x20;21}22}23else {24if (self->depression > 0)25self->depression -= 0x10;26}2728self->stood = false;29self->instantRecoil = false;30foreach_active(Player, player)31{32if (abs(player->position.x - self->position.x) <= 0x320000 && (player->velocity.y >= 0 || player->onGround)) {33Hitbox *playerHitbox = Player_GetHitbox(player);3435if (self->stood) {36int32 posY = BoucePlant_GetNodeY(player->position.x) + self->stoodPos.y - (playerHitbox->bottom << 16) - 0x40000;37if (player->position.y > posY - 0x80000) {38player->velocity.x += RSDK.Sin256(self->angle) << 13 >> 8;39player->position.y = posY;40player->velocity.y = 0;41player->onGround = true;42player->groundedStore = true;43player->angle = 0;44player->collisionMode = CMODE_FLOOR;45player->groundVel = player->velocity.x;46if (player->state == Player_State_KnuxGlideSlide || player->state == Player_State_KnuxGlideDrop)47player->state = Player_State_Ground;48}49}50else {51int32 posY = BoucePlant_GetNodeStandY(player->position.x) + self->position.y - (playerHitbox->bottom << 16) - 0x40000;52if (player->position.y > posY - 0x80000 && player->position.y < self->position.y + 0x400000) {53player->position.y = posY;54if (abs(player->velocity.x) > 0xC0000)55self->instantRecoil = true;5657if (abs(player->position.x - self->centerX) >= abs(player->velocity.x)) {58player->velocity.x += RSDK.Sin256(self->angle) << 13 >> 8;59player->velocity.y = 0;60player->onGround = true;61player->groundedStore = true;62player->angle = 0;63player->collisionMode = CMODE_FLOOR;64player->groundVel = player->velocity.x;6566if (player->state == Player_State_KnuxGlideSlide || player->state == Player_State_KnuxGlideDrop6768#if MANIA_USE_PLUS69|| player->state == Player_State_MightyHammerDrop70#endif71) {72player->state = Player_State_Ground;73}74}75else if (self->depression > 0xA0) {76if (self->direction == FLIP_NONE)77player->velocity.x = -0xB4000;78else79player->velocity.x = 0xB4000;80player->velocity.y = -0xB4000;81player->onGround = false;82player->state = Player_State_Air;83RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_DIAGONAL, &player->animator, false, 0);84RSDK.PlaySfx(BouncePlant->sfxBouncePlant, false, 255);85}86else if (abs(player->groundVel) <= 0xC00000) {87player->velocity.x += RSDK.Sin256(self->angle) << 13 >> 8;88player->velocity.y = 0;89player->onGround = true;90player->groundedStore = true;91player->angle = 0;92player->collisionMode = CMODE_FLOOR;93player->groundVel = player->velocity.x;9495if (player->state == Player_State_KnuxGlideSlide || player->state == Player_State_KnuxGlideDrop96#if MANIA_USE_PLUS97|| player->state == Player_State_MightyHammerDrop98#endif99) {100player->state = Player_State_Ground;101}102}103else {104if (self->direction == FLIP_NONE)105player->velocity.x = -0xB4000;106else107player->velocity.x = 0xB4000;108player->velocity.y = -0xB4000;109player->onGround = false;110player->state = Player_State_Air;111RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_DIAGONAL, &player->animator, false, 0);112RSDK.PlaySfx(BouncePlant->sfxBouncePlant, false, 255);113}114self->stood = true;115self->recoilDuration = 60;116self->stoodPos.x = player->position.x;117self->stoodPos.y = self->position.y + BoucePlant_GetNodeStandY(player->position.x);118}119}120}121}122123if (self->stood) {124for (int32 i = 0; i < BOUNCEPLANT_NODE_COUNT; ++i) self->drawPos[i].y = self->stoodPos.y + BoucePlant_GetNodeY(self->drawPos[i].x);125}126else {127if (self->recoilDuration <= 0) {128for (int32 i = 0; i < BOUNCEPLANT_NODE_COUNT; ++i) self->drawPos[i] = self->nodeStartPos[i];129}130else {131self->recoilDuration--;132133for (int32 i = 0; i < BOUNCEPLANT_NODE_COUNT; ++i) {134self->recoilVelocity[i] += ((self->nodeStartPos[i].y - self->drawPos[i].y) >> 3) - (self->recoilVelocity[i] >> 3);135self->drawPos[i].y += self->recoilVelocity[i];136}137}138}139}140141void BouncePlant_LateUpdate(void) {}142143void BouncePlant_StaticUpdate(void) {}144145void BouncePlant_Draw(void)146{147RSDK_THIS(BouncePlant);148149for (int32 i = 0; i < BOUNCEPLANT_NODE_COUNT; ++i) {150RSDK.DrawSprite(&self->nodeAnimator, &self->drawPos[i], false);151RSDK.DrawSprite(&self->decorAnimators[i], &self->drawPos[i], false);152}153}154155void BouncePlant_Create(void *data)156{157RSDK_THIS(BouncePlant);158if (!SceneInfo->inEditor) {159self->visible = true;160self->drawGroup = Zone->objectDrawGroup[0];161self->active = ACTIVE_BOUNDS;162self->updateRange.x = 0x800000;163self->updateRange.y = 0x800000;164BoucePlant_SetupNodePositions();165166if (self->direction) {167self->centerX = self->position.x - 0x180000;168self->angle = 0x40;169}170else {171self->centerX = self->position.x + 0x180000;172self->angle = 0xC0;173}174175RSDK.SetSpriteAnimation(BouncePlant->aniFrames, 1, &self->nodeAnimator, true, 0);176for (int32 i = 0; i < BOUNCEPLANT_NODE_COUNT; ++i) {177RSDK.SetSpriteAnimation(BouncePlant->aniFrames, 1, &self->decorAnimators[i], true, RSDK.Rand(1, 8));178self->drawPos[i].x = self->nodeStartPos[i].x;179self->drawPos[i].y = self->nodeStartPos[i].y;180}181}182}183184void BouncePlant_StageLoad(void)185{186BouncePlant->aniFrames = RSDK.LoadSpriteAnimation("SSZ1/Plants.bin", SCOPE_STAGE);187188BouncePlant->hitbox.left = -50;189BouncePlant->hitbox.left = -12;190BouncePlant->hitbox.right = 50;191BouncePlant->hitbox.right = 8;192193BouncePlant->sfxBouncePlant = RSDK.GetSfx("SSZ1/BouncePlant.wav");194}195196void BoucePlant_SetupNodePositions(void)197{198RSDK_THIS(BouncePlant);199200if (self->direction == FLIP_NONE) {201int32 x = self->position.x - 0x2A0000;202for (int32 i = 0; i < BOUNCEPLANT_NODE_COUNT; ++i) {203self->nodeStartPos[i].x = x;204x += 0xC0000;205}206}207else {208int32 x = self->position.x + 0x2A0000;209for (int32 i = 0; i < BOUNCEPLANT_NODE_COUNT; ++i) {210self->nodeStartPos[i].x = x;211x -= 0xC0000;212}213}214215int32 y = self->position.y + 0x2A0000;216for (int32 i = 0; i < BOUNCEPLANT_NODE_COUNT; ++i) {217self->nodeStartPos[i].y = y;218y -= 0xC0000;219}220}221222int32 BoucePlant_GetNodeStandY(int32 x)223{224RSDK_THIS(BouncePlant);225226int32 dist = 0;227int32 pos = 0;228if (self->direction == FLIP_NONE) {229int32 right = self->position.x + 0x180000;230dist = self->position.x - x;231if (x > right)232pos = 3 * (right - x);233else234pos = (right - x) / 3;235}236else {237int32 left = self->position.x - 0x180000;238dist = x - self->position.x;239if (x < left)240pos = 3 * (x - left);241else242pos = (x - left) / 3;243}244245dist = CLAMP(dist, -0x320000, 0x320000);246pos = CLAMP(pos + 0x200000, -0x320000, 0x320000);247return dist + ((self->depression * (pos - dist)) >> 8);248}249250int32 BoucePlant_GetNodeY(int32 x)251{252RSDK_THIS(BouncePlant);253254int32 y = 0;255int32 distanceX = 0;256int32 distanceY = 0;257if (self->direction) {258y = (x - self->stoodPos.x) >> 15;259if (x < self->stoodPos.x) {260distanceX = (self->stoodPos.x - self->nodeStartPos[BOUNCEPLANT_NODE_COUNT - 1].x) >> 16;261distanceY = (self->stoodPos.y - self->nodeStartPos[BOUNCEPLANT_NODE_COUNT - 1].y) >> 16;262}263else {264distanceX = (self->nodeStartPos[0].x - self->stoodPos.x) >> 16;265distanceY = (self->nodeStartPos[0].y - self->stoodPos.y) >> 16;266}267}268else {269y = (self->stoodPos.x - x) >> 15;270if (x > self->stoodPos.x) {271distanceX = (self->nodeStartPos[BOUNCEPLANT_NODE_COUNT - 1].x - self->stoodPos.x) >> 16;272distanceY = (self->stoodPos.y - self->nodeStartPos[BOUNCEPLANT_NODE_COUNT - 1].y) >> 16;273}274else {275distanceX = (self->stoodPos.x - self->nodeStartPos[0].x) >> 16;276distanceY = (self->nodeStartPos[0].y - self->stoodPos.y) >> 16;277}278}279280if (distanceX > 0)281y = y * distanceY / distanceX;282return y << 15;283}284285#if GAME_INCLUDE_EDITOR286void BouncePlant_EditorDraw(void)287{288RSDK_THIS(BouncePlant);289290self->drawGroup = Zone->objectDrawGroup[0];291self->updateRange.x = 0x800000;292self->updateRange.y = 0x800000;293BoucePlant_SetupNodePositions();294295if (self->direction) {296self->centerX = self->position.x - 0x180000;297self->angle = 0x40;298}299else {300self->centerX = self->position.x + 0x180000;301self->angle = 0xC0;302}303304RSDK.SetSpriteAnimation(BouncePlant->aniFrames, 1, &self->nodeAnimator, true, 0);305for (int32 i = 0; i < BOUNCEPLANT_NODE_COUNT; ++i) {306RSDK.SetSpriteAnimation(BouncePlant->aniFrames, 1, &self->decorAnimators[i], true, 1);307self->drawPos[i].x = self->nodeStartPos[i].x;308self->drawPos[i].y = self->nodeStartPos[i].y;309}310311BouncePlant_Draw();312}313314void BouncePlant_EditorLoad(void)315{316BouncePlant->aniFrames = RSDK.LoadSpriteAnimation("SSZ1/Plants.bin", SCOPE_STAGE);317318RSDK_ACTIVE_VAR(BouncePlant, direction);319RSDK_ENUM_VAR("No Flip", FLIP_NONE);320RSDK_ENUM_VAR("Flip X", FLIP_X);321}322#endif323324void BouncePlant_Serialize(void) { RSDK_EDITABLE_VAR(BouncePlant, VAR_UINT8, direction); }325326327