Path: blob/master/SonicMania/Objects/FBZ/HangPoint.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: HangPoint Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectHangPoint *HangPoint;1011void HangPoint_Update(void)12{13RSDK_THIS(HangPoint);1415if (self->length > 0) {16bool32 isActive = true;17if (self->activePlayers == 2) {18EntityPlayer *player2 = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);19if (player2->sidekick)20isActive = false;21}2223for (int32 i = 0; i < PLAYER_COUNT; ++i) {24if (self->moveDistance[i])25isActive = false;26}2728if (self->pullPos > self->length) {29if (self->pullPos <= 0) {30self->activePlayers &= 0xF;31}32else {33self->velocity.y -= 0x1800;34if (self->velocity.y < -self->maxVel)35self->velocity.y = -self->maxVel;3637self->activePlayers |= 16 * self->activePlayers;38self->pullPos += self->velocity.y;39}40}41else {42if (!self->activePlayers || !isActive) {43self->active = ACTIVE_BOUNDS;44if (self->direction == FLIP_NONE) {45if (self->pullPos > 0) {46self->velocity.y -= 0x1000;47if (self->velocity.y < -self->maxVel)48self->velocity.y = -self->maxVel;4950self->pullPos += self->velocity.y;51}52}53else if (self->pullPos < self->length) {54self->velocity.y += 0x1000;55if (self->velocity.y > self->maxVel)56self->velocity.y = self->maxVel;5758self->pullPos += self->velocity.y;59if (self->pullPos > self->length) {60self->pullPos = self->length;61self->velocity.y = 0;62}63}64}65else {66if (self->direction) {67if (self->pullPos <= 0) {68self->activePlayers &= 0xF;69}70else {71self->velocity.y -= 0x1800;72if (self->velocity.y < -self->maxVel)73self->velocity.y = -self->maxVel;7475self->activePlayers |= 16 * self->activePlayers;76self->pullPos += self->velocity.y;77}78}79else {80if (self->pullPos >= self->length) {81self->activePlayers &= 0xF;82}83else {84self->velocity.y += 0x1800;85if (self->velocity.y > self->maxVel)86self->velocity.y = self->maxVel;8788self->pullPos += self->velocity.y;89if (self->pullPos > self->length) {90self->pullPos = self->length;91self->velocity.y = 0;92}9394self->activePlayers |= (self->activePlayers << 4);95}96}97}98}99100if (self->pullPos < 0) {101self->pullPos = 0;102self->velocity.y = 0;103}104}105106int32 storeX = self->position.x;107int32 storeY = self->position.y;108self->position.y += self->pullPos;109110foreach_active(Player, player)111{112int32 playerID = RSDK.GetEntitySlot(player);113114if (self->playerTimer[playerID] > 0)115self->playerTimer[playerID]--;116117if (!((1 << playerID) & self->activePlayers)) {118if (player->state != Player_State_Static && !self->playerTimer[playerID]) {119Hitbox *playerHitbox = Player_GetHitbox(player);120121Hitbox hitboxPlayer;122hitboxPlayer.left = playerHitbox->left;123hitboxPlayer.top = playerHitbox->top;124hitboxPlayer.right = playerHitbox->right;125hitboxPlayer.bottom = hitboxPlayer.top + 4;126if (RSDK.CheckObjectCollisionTouchBox(self, &HangPoint->hitboxGrab, player, &hitboxPlayer)) {127player->velocity.x = 0;128player->velocity.y = 0;129player->groundVel = 0;130player->onGround = false;131player->angle = 0;132player->rotation = 0;133player->position.x = self->position.x;134player->position.y = self->position.y;135player->position.y += ((HangPoint->hitboxGrab.top - playerHitbox->top) << 16)136+ (((HangPoint->hitboxGrab.bottom - HangPoint->hitboxGrab.top) << 15) & 0xFFFF0000);137player->tileCollisions = TILECOLLISION_NONE;138self->moveDistance[playerID] = 0;139140if (!self->activePlayers) {141if (self->direction == FLIP_X) {142if (self->pullPos <= self->length)143self->velocity.y = 0x20000;144}145else {146self->velocity.y = 0;147}148}149self->activePlayers |= 1 << playerID;150151RSDK.SetSpriteAnimation(player->aniFrames, ANI_HANG, &player->animator, false, 0);152player->nextAirState = StateMachine_None;153player->nextGroundState = StateMachine_None;154player->state = Player_State_Static;155player->abilityValues[0] = RSDK.Rand(0, 2);156RSDK.PlaySfx(Player->sfxGrab, false, 255);157self->active = ACTIVE_NORMAL;158}159}160}161else {162if (player->state == Player_State_Hurt) {163player->tileCollisions = TILECOLLISION_DOWN;164self->activePlayers &= ~(1 << playerID) & ~(1 << (playerID + PLAYER_COUNT));165self->moveDistance[playerID] = 0;166if (player->left || player->right || player->down || player->state == Player_State_Hurt)167self->playerTimer[playerID] = 64;168else169self->playerTimer[playerID] = 16;170}171else {172if (player->state != Player_State_Static || self->playerTimer[playerID]) {173self->activePlayers &= ~(1 << playerID);174175if (player->classID == Player->classID && Player_CheckValidState(player))176player->tileCollisions = TILECOLLISION_DOWN;177}178else {179Hitbox *playerHitbox = Player_GetHitbox(player);180player->velocity.x = 0;181player->velocity.y = 0;182player->groundVel = 0;183player->angle = 0;184player->rotation = 0;185player->position.x = self->position.x;186player->position.y = self->position.y;187player->position.y += (((HangPoint->hitboxGrab.bottom - HangPoint->hitboxGrab.top) << 15) & 0xFFFF0000)188+ ((HangPoint->hitboxGrab.top - playerHitbox->top) << 16);189190if (!self->moveDistance[playerID]) {191if (player->left)192player->direction = FLIP_X;193194if (player->right)195player->direction = FLIP_NONE;196197if (player->jumpPress) {198player->velocity.y = -0x40000;199RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);200player->animator.speed = 48;201player->applyJumpCap = false;202player->jumpAbilityState = 1;203player->state = Player_State_Air;204player->tileCollisions = TILECOLLISION_DOWN;205self->activePlayers &= ~(1 << playerID) & ~(1 << (playerID + PLAYER_COUNT));206207if (player->left || player->right || player->down || player->state == Player_State_Hurt) {208self->playerTimer[playerID] = 64;209HangPoint_HandlePlayerMovement(self, player, playerID);210}211else {212self->playerTimer[playerID] = 16;213HangPoint_HandlePlayerMovement(self, player, playerID);214}215}216else if ((!((1 << (playerID + 4)) & self->activePlayers) && (self->direction != FLIP_NONE || self->pullPos >= self->length)217&& (self->direction != FLIP_X || self->pullPos <= 0))218|| player->sidekick) {219220bool32 changedHangPoint = false;221if (player->left) {222foreach_active(HangPoint, point)223{224if (self != point) {225int32 distance = self->position.x - point->position.x;226if (distance < 0x220000 && distance > 0) {227if (abs(self->position.y - point->position.y - point->pullPos) < 0x40000) {228self->activePlayers &= ~(1 << playerID);229self->playerTimer[playerID] = 16;230point->activePlayers |= 1 << playerID;231point->moveDistance[playerID] = 0x200000;232point->playerTimer[playerID] = 0;233#if MANIA_USE_PLUS234if (player->characterID == ID_RAY) {235if (player->abilityValues[0])236RSDK.SetSpriteAnimation(player->aniFrames, ANI_HANG_MOVE, &player->animator, false, 6);237else238RSDK.SetSpriteAnimation(player->aniFrames, ANI_HANG_MOVE, &player->animator, false, 1);239}240else {241#endif242RSDK.SetSpriteAnimation(player->aniFrames, ANI_HANG_MOVE, &player->animator, false, 3);243#if MANIA_USE_PLUS244}245#endif246247player->position.x = point->position.x;248249if (RSDK.GetEntitySlot(point) < SceneInfo->entitySlot)250HangPoint_HandlePlayerMovement(point, player, playerID);251HangPoint_HandlePlayerMovement(self, player, playerID);252253changedHangPoint = true;254foreach_break;255}256}257}258}259}260else if (player->right) {261foreach_active(HangPoint, point)262{263if (self != point) {264int32 distance = point->position.x - self->position.x;265if (distance < 0x220000 && distance > 0) {266if (abs(self->position.y - point->position.y - point->pullPos) < 0x40000) {267self->activePlayers &= ~(1 << playerID);268self->playerTimer[playerID] = 16;269point->activePlayers |= 1 << playerID;270point->moveDistance[playerID] = -0x200000;271point->playerTimer[playerID] = 0;272273#if MANIA_USE_PLUS274if (player->characterID == ID_RAY) {275if (!player->abilityValues[0]) {276RSDK.SetSpriteAnimation(player->aniFrames, ANI_HANG_MOVE, &player->animator, false, 0);277}278else {279RSDK.SetSpriteAnimation(player->aniFrames, ANI_HANG_MOVE, &player->animator, false, 6);280}281}282else {283#endif284RSDK.SetSpriteAnimation(player->aniFrames, ANI_HANG_MOVE, &player->animator, false, 3);285#if MANIA_USE_PLUS286}287#endif288289player->position.x = point->position.x;290291if (RSDK.GetEntitySlot(point) < SceneInfo->entitySlot)292HangPoint_HandlePlayerMovement(point, player, playerID);293HangPoint_HandlePlayerMovement(self, player, playerID);294295changedHangPoint = true;296foreach_break;297}298}299}300}301}302303if (!changedHangPoint) {304#if MANIA_USE_PLUS305if (player->characterID == ID_RAY && player->abilityValues[0] == 1)306RSDK.SetSpriteAnimation(player->aniFrames, ANI_HANG2, &player->animator, false, 0);307else308#endif309RSDK.SetSpriteAnimation(player->aniFrames, ANI_HANG, &player->animator, false, 0);310311HangPoint_HandlePlayerMovement(self, player, playerID);312}313}314else {315#if MANIA_USE_PLUS316if (player->characterID == ID_RAY && player->abilityValues[0] == 1)317RSDK.SetSpriteAnimation(player->aniFrames, ANI_HANG2, &player->animator, false, 0);318else319#endif320RSDK.SetSpriteAnimation(player->aniFrames, ANI_HANG, &player->animator, false, 0);321322HangPoint_HandlePlayerMovement(self, player, playerID);323}324}325else {326HangPoint_HandlePlayerMovement(self, player, playerID);327}328}329}330}331}332333self->position.x = storeX;334self->position.y = storeY;335}336337void HangPoint_LateUpdate(void) {}338339void HangPoint_StaticUpdate(void) {}340341void HangPoint_Draw(void)342{343RSDK_THIS(HangPoint);344345Vector2 drawPos;346347drawPos.x = self->position.x;348drawPos.y = self->position.y + self->pullPos;349RSDK.DrawSprite(&HangPoint->animator, &drawPos, false);350351if (self->length) {352HangPoint->animator.frameID = 1;353int32 length = (self->pullPos >> 16) & 0xFF00;354355SpriteFrame *frame = RSDK.GetFrame(HangPoint->aniFrames, 0, HangPoint->animator.frameID);356357int32 extraLength = (self->pullPos >> 16) & 0x00FF;358frame->pivotY = -(self->pullPos >> 16);359frame->height = extraLength;360frame->sprY = 257 - extraLength;361RSDK.DrawSprite(&HangPoint->animator, &drawPos, false);362363frame->height = 256;364frame->sprY = 1;365while (length >= 256) {366frame->pivotY = -length;367RSDK.DrawSprite(&HangPoint->animator, &drawPos, false);368length -= 256;369}370HangPoint->animator.frameID = 0;371}372}373374void HangPoint_Create(void *data)375{376RSDK_THIS(HangPoint);377378if (!self->speed)379self->speed = 2;380381self->active = ACTIVE_BOUNDS;382self->updateRange.x = 0x400000;383self->visible = true;384self->updateRange.y = (self->length + 64) << 16;385self->drawGroup = Zone->objectDrawGroup[0];386if (!SceneInfo->inEditor) {387self->length = self->length << 16;388self->maxVel = self->speed << 15;389if (self->direction == FLIP_X)390self->pullPos = self->length;391}392}393394void HangPoint_StageLoad(void)395{396if (RSDK.CheckSceneFolder("FBZ"))397HangPoint->aniFrames = RSDK.LoadSpriteAnimation("FBZ/HangPoint.bin", SCOPE_STAGE);398399RSDK.SetSpriteAnimation(HangPoint->aniFrames, 0, &HangPoint->animator, true, 0);400401Hitbox *hitbox = RSDK.GetHitbox(&HangPoint->animator, 0);402HangPoint->hitboxGrab.top = hitbox->top;403HangPoint->hitboxGrab.left = hitbox->left;404HangPoint->hitboxGrab.bottom = hitbox->bottom;405HangPoint->hitboxGrab.right = hitbox->right;406}407408void HangPoint_HandlePlayerMovement(EntityHangPoint *self, EntityPlayer *player, int32 playerID)409{410if (self->moveDistance[playerID]) {411if (self->moveDistance[playerID] < 0) {412self->moveDistance[playerID] += 0x15556;413if (self->moveDistance[playerID] >= 0) {414self->moveDistance[playerID] = 0;415RSDK.PlaySfx(Player->sfxGrab, false, 255);416player->abilityValues[0] ^= 1;417}418}419else {420self->moveDistance[playerID] -= 0x15556;421if (self->moveDistance[playerID] <= 0) {422self->moveDistance[playerID] = 0;423RSDK.PlaySfx(Player->sfxGrab, false, 255);424player->abilityValues[0] ^= 1;425}426}427428player->position.x += self->moveDistance[playerID] & 0xFFFF0000;429if (player->jumpPress) {430player->velocity.y = -0x40000;431RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);432433player->applyJumpCap = false;434player->animator.speed = 48;435player->jumpAbilityState = 1;436player->state = Player_State_Air;437player->tileCollisions = TILECOLLISION_DOWN;438self->activePlayers &= ~(1 << playerID) & ~(1 << (playerID + 4));439self->moveDistance[playerID] = 0;440441if (player->left || player->right || player->down || player->state == Player_State_Hurt)442self->playerTimer[playerID] = 64;443else444self->playerTimer[playerID] = 16;445}446}447}448449#if GAME_INCLUDE_EDITOR450void HangPoint_EditorDraw(void)451{452RSDK_THIS(HangPoint);453454int32 len = self->length;455self->length <<= 16;456457self->pullPos = self->direction == FLIP_X ? self->length : 0;458HangPoint_Draw();459460if (self->length && showGizmos()) {461RSDK_DRAWING_OVERLAY(true);462self->inkEffect = INK_BLEND;463464int32 prevPullPos = self->pullPos;465self->pullPos = self->direction == FLIP_X ? 0 : self->length;466HangPoint_Draw();467468DrawHelpers_DrawArrow(self->position.x, self->position.y + prevPullPos, self->position.x, self->position.y + self->pullPos, 0x00FF00,469INK_NONE, 0xFF);470471RSDK_DRAWING_OVERLAY(false);472self->inkEffect = INK_NONE;473}474475self->length = len;476}477478void HangPoint_EditorLoad(void)479{480HangPoint->aniFrames = RSDK.LoadSpriteAnimation("FBZ/HangPoint.bin", SCOPE_STAGE);481RSDK.SetSpriteAnimation(HangPoint->aniFrames, 0, &HangPoint->animator, true, 0);482483RSDK_ACTIVE_VAR(HangPoint, direction);484RSDK_ENUM_VAR("Drop Down", FLIP_NONE);485RSDK_ENUM_VAR("Pull Up", FLIP_X);486}487#endif488489void HangPoint_Serialize(void)490{491RSDK_EDITABLE_VAR(HangPoint, VAR_ENUM, length);492RSDK_EDITABLE_VAR(HangPoint, VAR_UINT8, speed);493RSDK_EDITABLE_VAR(HangPoint, VAR_UINT8, direction);494}495496497