Path: blob/master/SonicMania/Objects/HCZ/HangConveyor.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: HangConveyor Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectHangConveyor *HangConveyor;1011void HangConveyor_Update(void)12{13RSDK_THIS(HangConveyor);1415RSDK.ProcessAnimation(&self->endAnimator);16RSDK.ProcessAnimation(&self->startAnimator);17RSDK.ProcessAnimation(&self->middleAnimator);1819if (RSDK.CheckOnScreen(self, &self->updateRange)) {20HangConveyor_HandlePlayerInteractions();21self->active = ACTIVE_NORMAL;22}23else {24for (int32 p = 0; p < PLAYER_COUNT; ++p) {25self->playerPositions[p].x = 0;26self->playerPositions[p].y = 0;27}2829self->active = ACTIVE_BOUNDS;30}31}3233void HangConveyor_LateUpdate(void) {}3435void HangConveyor_StaticUpdate(void) {}3637void HangConveyor_Draw(void) { HangConveyor_DrawSprites(); }3839void HangConveyor_Create(void *data)40{41RSDK_THIS(HangConveyor);4243self->active = ACTIVE_BOUNDS;44self->drawGroup = Zone->objectDrawGroup[0];45self->startPos = self->position;46self->visible = true;47self->drawFX = FX_FLIP;48self->updateRange.x = 0x800000;49self->updateRange.y = 0x800000;5051HangConveyor_SetupHitboxes();52self->updateRange.x += (self->hitboxFallCheckTop.right - self->hitboxFallCheckTop.left) << 16;5354RSDK.SetSpriteAnimation(HangConveyor->aniFrames, 0, &self->endAnimator, true, 0);55RSDK.SetSpriteAnimation(HangConveyor->aniFrames, 1, &self->startAnimator, true, 0);56RSDK.SetSpriteAnimation(HangConveyor->aniFrames, 2, &self->middleAnimator, true, 0);57}5859void HangConveyor_StageLoad(void) { HangConveyor->aniFrames = RSDK.LoadSpriteAnimation("HCZ/HangConveyor.bin", SCOPE_STAGE); }6061void HangConveyor_DrawSprites(void)62{63RSDK_THIS(HangConveyor);6465Vector2 drawPos = self->position;66drawPos.x += -0x80000 * (self->length != 1 ? self->length - 1 : 0);67int32 dirStore = self->direction;6869for (int32 i = 0; i < self->length; ++i) {70self->direction = dirStore != FLIP_NONE;71drawPos.y = self->position.y - 0x150000;72RSDK.DrawSprite(&self->middleAnimator, &drawPos, false);7374self->direction = dirStore == FLIP_NONE;75drawPos.y = self->position.y + 0x150000;76RSDK.DrawSprite(&self->middleAnimator, &drawPos, false);7778drawPos.x += 0x100000;79}8081self->direction = dirStore != FLIP_NONE;82drawPos.x = self->position.x;83drawPos.y = self->position.y;8485int32 len = self->length == 1 ? 4 : (self->length + 3);86if (dirStore) {87drawPos.x += len << 19;88}89else {90drawPos.x += -0x80000 * len;91}92RSDK.DrawSprite(&self->endAnimator, &drawPos, false);9394self->direction = dirStore == FLIP_NONE;95drawPos.x = self->position.x;96drawPos.y = self->position.y;9798if (dirStore) {99drawPos.x += -0x80000 * len;100}101else {102drawPos.x += len << 19;103}104RSDK.DrawSprite(&self->startAnimator, &drawPos, false);105106self->direction = dirStore;107}108109void HangConveyor_SetupHitboxes(void)110{111RSDK_THIS(HangConveyor);112113self->hitboxSpikeBallRange.left = -8 * (self->length != -6 ? self->length + 6 : 0);114self->hitboxSpikeBallRange.top = -24;115self->hitboxSpikeBallRange.right = 8 * (self->length != -6 ? self->length + 6 : 0);116self->hitboxSpikeBallRange.bottom = 24;117118self->hitboxFallCheckTop.left = -8 * (self->length != -2 ? self->length + 2 : 0);119self->hitboxFallCheckTop.top = -26;120self->hitboxFallCheckTop.right = 8 * (self->length != -2 ? self->length + 2 : 0);121self->hitboxFallCheckTop.bottom = -16;122123// Top Left End124self->endPosTopLeft.x = self->position.x + (self->hitboxFallCheckTop.left << 16);125self->endPosTopLeft.y = self->position.y - 0x150000;126127// Top Right End128self->endPosTopRight.x = self->position.x + (self->hitboxFallCheckTop.right << 16);129self->endPosTopRight.y = self->position.y - 0x150000;130131self->hitboxFallCheckBottom.left = -4 - 8 * (self->length != -2 ? self->length + 2 : 0);132self->hitboxFallCheckBottom.top = 16;133self->hitboxFallCheckBottom.right = 8 * (self->length != -2 ? self->length + 2 : 0) + 4;134self->hitboxFallCheckBottom.bottom = 26;135136// Bottom Left End137self->endPosBottomLeft.x = self->position.x + (self->hitboxFallCheckBottom.left << 16);138self->endPosBottomLeft.y = self->position.y + 0x150000;139140// Bottom Right End141self->endPosBottomRight.x = self->position.x + (self->hitboxFallCheckBottom.right << 16);142self->endPosBottomRight.y = self->position.y + 0x150000;143}144145void HangConveyor_HandlePlayerInteractions(void)146{147RSDK_THIS(HangConveyor);148149foreach_active(Player, player)150{151if (Player_CheckValidState(player)) {152int32 playerID = RSDK.GetEntitySlot(player);153154int32 playerY = player->position.y;155if (player->animator.animationID != ANI_POLE_SWING_V && player->animator.animationID != ANI_SHIMMY_MOVE)156playerY -= 0x180000;157158int32 prevX = self->playerPositions[playerID].x;159int32 prevY = self->playerPositions[playerID].y;160self->playerPositions[playerID].x = player->position.x;161self->playerPositions[playerID].y = playerY;162163if (abs(player->position.x - prevX) < 0x800000 && abs(playerY - prevY) < 0x800000 && (prevX || prevY)) {164bool32 collidedTop = MathHelpers_CheckPositionOverlap(player->position.x, playerY, prevX, prevY, self->endPosTopLeft.x,165self->endPosTopLeft.y, self->endPosTopRight.x, self->endPosTopRight.y);166collidedTop = collidedTop && !self->grabDelayTop[playerID];167168bool32 collidedBottom =169MathHelpers_CheckPositionOverlap(player->position.x, playerY, prevX, prevY, self->endPosBottomLeft.x, self->endPosBottomLeft.y,170self->endPosBottomRight.x, self->endPosBottomRight.y);171collidedBottom = collidedBottom && !self->grabDelayBottom[playerID];172173if (self->grabDelayTop[playerID] > 0)174self->grabDelayTop[playerID]--;175176if (self->grabDelayBottom[playerID] > 0)177self->grabDelayBottom[playerID]--;178179if (!((1 << playerID) & self->movementActivePlayers) && !(self->checkableActivePlayers & (1 << playerID))) {180if ((collidedTop || collidedBottom) && player->state != Player_State_Static && player->animator.animationID != ANI_HURT) {181self->movementActivePlayers |= (1 << playerID);182self->checkableActivePlayers |= (1 << playerID);183if (collidedTop) {184self->activePlayersTop |= 1 << playerID;185player->position.y = self->position.y - 0x150000;186}187if (collidedBottom) {188self->activePlayersBottom |= 1 << playerID;189player->position.y = self->position.y + 0x150000;190}191192RSDK.PlaySfx(Player->sfxGrab, false, 255);193RSDK.SetSpriteAnimation(player->aniFrames, ANI_POLE_SWING_V, &player->animator, true, 0);194player->animator.speed = 0;195player->nextGroundState = StateMachine_None;196player->nextAirState = StateMachine_None;197player->velocity.x = 0;198player->velocity.y = 0;199player->rotation = 0;200player->state = Player_State_Static;201}202}203204int32 newPlayerY = player->position.y;205if (player->animator.animationID != ANI_POLE_SWING_V && player->animator.animationID != ANI_SHIMMY_MOVE)206newPlayerY -= 0x180000;207208collidedTop = MathHelpers_PointInHitbox(self->position.x, self->position.y, player->position.x, newPlayerY, self->direction,209&self->hitboxFallCheckTop);210collidedBottom = MathHelpers_PointInHitbox(self->position.x, self->position.y, player->position.x, newPlayerY, self->direction,211&self->hitboxFallCheckBottom);212213if (((1 << playerID) & self->movementActivePlayers)) {214if (self->fanTimer[playerID] > 0) {215RSDK.SetSpriteAnimation(player->aniFrames, ANI_POLE_SWING_V, &player->animator, true, self->fanTimer[playerID] >> 1);216player->animator.speed = 0;217}218else if (player->left) {219RSDK.SetSpriteAnimation(player->aniFrames, ANI_SHIMMY_MOVE, &player->animator, false, 0);220player->direction = FLIP_X;221}222else if (player->right) {223RSDK.SetSpriteAnimation(player->aniFrames, ANI_SHIMMY_MOVE, &player->animator, false, 0);224player->direction = FLIP_NONE;225}226else if (!(player->animator.animationID == ANI_POLE_SWING_V && !player->animator.frameID)) {227RSDK.SetSpriteAnimation(player->aniFrames, ANI_POLE_SWING_V, &player->animator, false, 0);228player->animator.speed = 0;229}230231if ((1 << playerID) & self->activePlayersTop) {232player->position.y = self->position.y - 0x150000;233234int32 moveVelocity = 0;235if (self->direction) {236moveVelocity = 0x15555;237238if (player->right)239moveVelocity = 0x20000;240else if (player->left)241moveVelocity = 0xB000;242}243else {244moveVelocity = -0x15555;245246if (player->left)247moveVelocity = -0x20000;248if (player->right)249moveVelocity = -0xB000;250}251252player->position.x += moveVelocity;253}254255if ((1 << playerID) & self->activePlayersBottom) {256player->position.y = self->position.y + 0x150000;257258int32 moveVelocity = 0;259if (self->direction) {260moveVelocity = -0x15555;261262if (player->left)263moveVelocity = -0x20000;264else if (player->right)265moveVelocity = -0xB000;266}267else {268moveVelocity = 0x15555;269270if (player->right)271moveVelocity = 0x20000;272if (player->left)273moveVelocity = 0xB000;274}275276player->position.x += moveVelocity;277}278279bool32 noCollision = false;280if (((1 << playerID) & self->activePlayersTop) && !collidedTop)281noCollision = true;282if (((1 << playerID) & self->activePlayersBottom) && !collidedBottom)283noCollision = true;284285int32 anim = player->animator.animationID;286if (player->jumpPress || (anim != ANI_POLE_SWING_V && anim != ANI_SHIMMY_MOVE) || player->velocity.x || player->velocity.y287|| noCollision) {288289self->movementActivePlayers &= ~(1 << playerID);290player->position.y += 0x180000;291292if (!player->jumpPress || player->down) {293RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, true, 0);294player->state = Player_State_Air;295}296else {297Player_Action_Jump(player);298}299300if ((1 << playerID) & self->activePlayersTop)301self->grabDelayTop[playerID] = 60;302303if ((1 << playerID) & self->activePlayersBottom)304self->grabDelayBottom[playerID] = 60;305}306}307308if (!((1 << playerID) & self->movementActivePlayers) && ((1 << playerID) & self->checkableActivePlayers)) {309if (((1 << playerID) & self->activePlayersTop) && !Player_CheckCollisionTouch(player, self, &self->hitboxFallCheckTop)) {310self->activePlayersTop &= ~(1 << playerID);311self->checkableActivePlayers &= ~(1 << playerID);312}313314if (((1 << playerID) & self->activePlayersBottom) && !Player_CheckCollisionTouch(player, self, &self->hitboxFallCheckBottom)) {315self->activePlayersBottom &= ~(1 << playerID);316self->checkableActivePlayers &= ~(1 << playerID);317}318}319320if (!((1 << playerID) & self->movementActivePlayers))321self->fanTimer[playerID] = 0;322}323}324}325}326327#if GAME_INCLUDE_EDITOR328void HangConveyor_EditorDraw(void) { HangConveyor_DrawSprites(); }329330void HangConveyor_EditorLoad(void)331{332HangConveyor->aniFrames = RSDK.LoadSpriteAnimation("HCZ/HangConveyor.bin", SCOPE_STAGE);333334RSDK_ACTIVE_VAR(HangConveyor, direction);335RSDK_ENUM_VAR("No Flip", FLIP_NONE);336RSDK_ENUM_VAR("Flipped", FLIP_X);337}338#endif339340void HangConveyor_Serialize(void)341{342RSDK_EDITABLE_VAR(HangConveyor, VAR_UINT8, direction);343RSDK_EDITABLE_VAR(HangConveyor, VAR_UINT32, length);344}345346347