Path: blob/master/SonicMania/Objects/FBZ/Cylinder.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Cylinder Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectCylinder *Cylinder;1011void Cylinder_Update(void)12{13RSDK_THIS(Cylinder);1415StateMachine_Run(self->state);16}1718void Cylinder_LateUpdate(void) {}1920void Cylinder_StaticUpdate(void) {}2122void Cylinder_Draw(void) {}2324void Cylinder_Create(void *data)25{26RSDK_THIS(Cylinder);2728if (!SceneInfo->inEditor) {29self->active = ACTIVE_BOUNDS;30self->visible = false;31self->drawGroup = Zone->objectDrawGroup[0];3233switch (self->type) {34case CYLINDER_TUBE_H:35self->updateRange.x = self->length << 16;36self->updateRange.y = self->radius << 16;3738self->hitboxRange.left = -self->length;39self->hitboxRange.top = -self->radius;40self->hitboxRange.right = self->length;41self->hitboxRange.bottom = self->radius;4243self->hitboxSize.left = -self->length;44self->hitboxSize.top = -self->radius;45self->hitboxSize.right = self->length;46self->hitboxSize.bottom = -self->radius + 8;4748self->state = Cylinder_State_TubeH;49break;5051case CYLINDER_TUBE_V:52self->updateRange.x = self->radius << 16;53self->updateRange.y = self->length << 16;5455self->hitboxRange.left = -self->radius;56self->hitboxRange.top = -self->length;57self->hitboxRange.right = self->radius;58self->hitboxRange.bottom = self->length;5960self->state = Cylinder_State_TubeV;61break;6263case CYLINDER_SPIRAL_LR:64self->updateRange.x = (self->radius + 112) << 16;65self->updateRange.y = self->length << 16;6667self->hitboxRange.left = -64 - self->radius;68self->hitboxRange.right = self->radius + 64;69self->hitboxRange.top = -self->length;70self->hitboxRange.bottom = self->length;7172self->hitboxL.left = -112 - self->radius;73self->hitboxL.right = -self->radius;74self->hitboxL.top = -self->length;75self->hitboxL.bottom = 64 - self->length;7677self->hitboxR.left = self->radius;78self->hitboxR.top = self->length - 64;79self->hitboxR.right = self->length + 112;80self->hitboxR.bottom = self->length;8182self->state = Cylinder_State_Spiral;83break;8485case CYLINDER_SPIRAL_RL:86self->updateRange.x = (self->radius + 112) << 16;87self->updateRange.y = self->length << 16;8889self->hitboxRange.left = -64 - self->radius;90self->hitboxRange.top = -self->length;91self->hitboxRange.right = self->radius + 64;92self->hitboxRange.bottom = self->length;9394self->hitboxL.left = -112 - self->radius;95self->hitboxL.top = self->length - 64;96self->hitboxL.right = -self->radius;97self->hitboxL.bottom = self->length;9899self->hitboxR.left = self->radius;100self->hitboxR.top = -self->length;101self->hitboxR.right = self->radius + 112;102self->hitboxR.bottom = 64 - self->length;103104self->state = Cylinder_State_Spiral;105break;106107case CYLINDER_INKROLLER:108self->updateRange.x = self->length << 16;109self->updateRange.y = self->radius << 16;110111self->hitboxRange.left = 16 - self->length;112self->hitboxRange.top = ~self->radius;113self->hitboxRange.right = self->length - 16;114self->hitboxRange.bottom = self->radius + 1;115116self->hitboxSize.left = -self->length;117self->hitboxSize.top = -self->radius;118self->hitboxSize.right = self->length;119self->hitboxSize.bottom = self->radius;120121self->state = Cylinder_State_InkRoller;122break;123124case CYLINDER_PILLAR:125self->visible = true;126self->updateRange.x = self->radius << 17;127self->updateRange.y = self->length << 17;128129self->hitboxRange.left = -16 - self->radius;130self->hitboxRange.top = -self->length;131self->hitboxRange.right = self->radius + 16;132self->hitboxRange.bottom = self->length;133self->length = 2 * self->length;134135self->state = Cylinder_State_Pillar;136break;137138default: break;139}140}141}142143void Cylinder_StageLoad(void) {}144145void Cylinder_State_TubeH(void)146{147RSDK_THIS(Cylinder);148149foreach_active(Player, player)150{151Hitbox *playerHitbox = Player_GetHitbox(player);152int32 radius = (self->radius - playerHitbox->bottom) << 6;153154if (self->playerStatus[player->playerID]) {155if (!Player_CheckCollisionTouch(player, self, &self->hitboxRange) || player->velocity.y <= -0x40000) {156if (((self->playerAngles[player->playerID] + 128) & 0x3FF) < 0x100)157player->velocity.y >>= 1;158else159player->velocity.y = 0;160161if (!player->onGround && player->velocity.y >= 0 && player->state != Player_State_FlyCarried162&& player->animator.animationID != ANI_SKID) {163RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_CS, &player->animator, true,16424 * self->playerAngles[player->playerID] / 1024);165}166167player->onGround = false;168self->playerStatus[player->playerID] = false;169}170else {171self->playerAngles[player->playerID] = (self->playerAngles[player->playerID] + 16) & 0x3FF;172player->position.y = radius * RSDK.Cos1024(self->playerAngles[player->playerID]) + self->position.y;173174if (player->state == Player_State_LookUp || player->state == Player_State_Crouch)175player->state = Player_State_Ground;176177if (player->state != Player_State_Ground || player->onGround || player->animator.animationID == ANI_SKID) {178if (player->state == Player_State_Roll) {179if (player->velocity.x)180player->direction = player->velocity.x > 0;181}182183player->onGround = true;184}185else {186RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_CS, &player->animator, true,18724 * self->playerAngles[player->playerID] / 1024);188player->onGround = true;189}190}191}192else if (Player_CheckCollisionTouch(player, self, &self->hitboxRange)) {193if (player->position.y - self->position.y > radius << 10 && player->velocity.y >= 0) {194player->position.y = self->position.y + (radius << 10);195player->velocity.y = 0;196player->onGround = true;197self->playerAngles[player->playerID] = 0;198self->playerStatus[player->playerID] = true;199}200}201}202}203204void Cylinder_State_TubeV(void)205{206RSDK_THIS(Cylinder);207208foreach_active(Player, player)209{210Hitbox *playerHitbox = Player_GetHitbox(player);211int32 radius = (self->radius - playerHitbox->bottom) << 6;212213if (self->playerStatus[player->playerID]) {214if (Player_CheckCollisionTouch(player, self, &self->hitboxRange)) {215self->playerAngles[player->playerID] = (self->playerAngles[player->playerID] + 16) & 0x3FF;216player->position.x = radius * RSDK.Cos1024(self->playerAngles[player->playerID]) + self->position.x;217player->rotation = 0x80;218RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_CS, &player->animator, true,219(24 * self->playerAngles[player->playerID] / 1024 + 12) % 24);220player->animator.rotationStyle = ROTSTYLE_FULL;221player->direction = player->velocity.y < 0;222}223else {224if (player->collisionMode == CMODE_LWALL)225player->angle = 0x40;226else if (player->collisionMode == CMODE_RWALL)227player->angle = 0xC0;228229player->onGround = false;230player->state = Player_State_Air;231self->playerStatus[player->playerID] = false;232}233}234else if (Player_CheckCollisionTouch(player, self, &self->hitboxRange)) {235if (abs(player->position.x - self->position.x) > (radius - 896) << 10) {236if (player->position.x - self->position.x <= 0) {237player->collisionMode = CMODE_RWALL;238self->playerAngles[player->playerID] = 0x200;239}240else {241player->collisionMode = CMODE_LWALL;242self->playerAngles[player->playerID] = 0x000;243}244245player->state = Player_State_Air;246player->nextAirState = StateMachine_None;247player->nextGroundState = StateMachine_None;248self->playerStatus[player->playerID] = 1;249}250}251}252}253254void Cylinder_State_Spiral(void)255{256RSDK_THIS(Cylinder);257258foreach_active(Player, player)259{260Hitbox *playerHitbox = Player_GetHitbox(player);261int32 radius = (self->radius - playerHitbox->bottom - 12) << 6;262263switch (self->playerStatus[player->playerID]) {264case 0:265if (player->onGround) {266bool32 collided = false;267if (Player_CheckCollisionTouch(player, self, &self->hitboxL) && player->groundVel > 0x30000)268collided = true;269if (Player_CheckCollisionTouch(player, self, &self->hitboxR) && player->groundVel < -0x30000)270collided = true;271272if (collided) {273self->playerStatus[player->playerID] = 1;274player->state = Cylinder_PlayerState_Spiral;275}276}277break;278279case 1:280if (player->groundVel <= 0x30000) {281if (player->groundVel >= -0x30000) {282player->onGround = false;283self->playerStatus[player->playerID] = 0;284}285else {286if (player->position.x <= self->position.x) {287self->playerAngles[player->playerID] = 768;288player->tileCollisions = TILECOLLISION_NONE;289self->playerStatus[player->playerID] = 2;290}291292int32 distance = (player->position.x - self->position.x) >> 16;293int32 right = self->hitboxR.right - 48;294if (distance < right) {295player->rotation = 256;296player->direction = FLIP_NONE;297RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_CS, &player->animator, true, 17 - 6 * distance / right);298player->animator.rotationStyle = ROTSTYLE_FULL;299}300301player->onGround = true;302player->velocity.y = 0;303}304}305else {306if (player->position.x >= self->position.x) {307self->playerAngles[player->playerID] = 768;308player->tileCollisions = TILECOLLISION_NONE;309self->playerStatus[player->playerID] = 2;310}311312int32 distance = (self->position.x - player->position.x) >> 16;313int32 right = -48 - self->hitboxL.left;314if (distance < right) {315player->rotation = 256;316player->direction = FLIP_X;317RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_CS, &player->animator, true, 17 - 6 * distance / right);318player->animator.rotationStyle = ROTSTYLE_FULL;319player->onGround = true;320player->velocity.y = 0;321}322323player->onGround = true;324player->velocity.y = 0;325}326break;327328case 2: {329self->playerAngles[player->playerID] = (self->playerAngles[player->playerID] + (player->groundVel >> 15)) & 0x3FF;330player->position.x = radius * RSDK.Cos1024(self->playerAngles[player->playerID]) + self->position.x;331332if (self->hitboxL.top >= self->hitboxR.top)333player->position.y -= (player->groundVel >> 2) & 0xFFFFE000;334else335player->position.y += (player->groundVel >> 2) & 0xFFFFE000;336player->direction = FLIP_X;337338int32 frame = 0;339if (player->groundVel <= 0) {340player->rotation = 0x80;341frame = 35 - 24 * self->playerAngles[player->playerID] / 0x400;342}343else {344player->rotation = 0x180;345frame = 24 * self->playerAngles[player->playerID] / 0x400;346}347348if (player->velocity.y < -0x40000) {349self->playerStatus[player->playerID] = 0;350player->tileCollisions = TILECOLLISION_DOWN;351}352else {353RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_CS, &player->animator, true, frame % 24);354player->animator.rotationStyle = ROTSTYLE_FULL;355player->onGround = true;356player->velocity.y = 0;357358if (player->groundVel <= 0) {359if (player->groundVel >= -0x30000) {360self->playerStatus[player->playerID] = 0;361player->tileCollisions = TILECOLLISION_DOWN;362}363else {364if (self->hitboxL.top < self->hitboxR.top) {365int32 maxY = self->position.y - (playerHitbox->bottom << 16) - self->updateRange.y + 0x400000;366if (player->position.y <= maxY) {367player->position.y = maxY;368self->playerStatus[player->playerID] = 3;369player->tileCollisions = TILECOLLISION_DOWN;370}371}372else if (player->position.y >= self->updateRange.y - (playerHitbox->bottom << 16) + self->position.y) {373player->position.y = self->updateRange.y - (playerHitbox->bottom << 16) + self->position.y;374self->playerStatus[player->playerID] = 3;375player->tileCollisions = TILECOLLISION_DOWN;376}377}378}379else {380if (player->groundVel <= 0x30000) {381self->playerStatus[player->playerID] = 0;382player->tileCollisions = TILECOLLISION_DOWN;383}384else if (self->hitboxL.top >= self->hitboxR.top) {385int32 maxY = self->position.y - (playerHitbox->bottom << 16) - self->updateRange.y + 0x400000;386if (player->position.y <= maxY) {387player->position.y = maxY;388self->playerStatus[player->playerID] = 3;389player->tileCollisions = TILECOLLISION_DOWN;390}391}392else if (player->position.y >= self->updateRange.y - (playerHitbox->bottom << 16) + self->position.y) {393player->position.y = self->updateRange.y - (playerHitbox->bottom << 16) + self->position.y;394self->playerStatus[player->playerID] = 3;395player->tileCollisions = TILECOLLISION_DOWN;396}397}398}399break;400}401402case 3: {403if (Player_CheckCollisionTouch(player, self, &self->hitboxRange)) {404if (abs(player->groundVel) <= 0x30000) {405self->playerStatus[player->playerID] = 0;406player->state = Player_State_Ground;407408if (player->groundVel <= 0) {409if (player->groundVel < 0)410player->direction = FLIP_X;411}412else {413player->direction = FLIP_NONE;414}415}416else {417player->onGround = true;418player->velocity.y = 0;419420if (player->groundVel >= 0) {421int32 distance = (player->position.x - self->position.x) >> 16;422int32 right = self->hitboxR.right - 48;423if (distance < right) {424player->rotation = 256;425player->direction = FLIP_X;426RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_CS, &player->animator, true, 17 - 6 * distance / right);427player->animator.rotationStyle = ROTSTYLE_FULL;428}429}430else {431int32 distance = (self->position.x - player->position.x) >> 16;432int32 right = -48 - self->hitboxL.left;433if (distance < right) {434player->rotation = 256;435player->direction = FLIP_NONE;436RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_CS, &player->animator, true, 17 - 6 * distance / right);437player->animator.rotationStyle = ROTSTYLE_FULL;438}439}440}441}442else {443self->playerStatus[player->playerID] = 0;444player->state = Player_State_Ground;445if (player->groundVel <= 0) {446if (player->groundVel < 0)447player->direction = FLIP_X;448}449else {450player->direction = FLIP_NONE;451}452}453break;454}455456default: break;457}458}459}460461void Cylinder_State_InkRoller(void)462{463RSDK_THIS(Cylinder);464465foreach_active(Player, player)466{467Hitbox *playerHitbox = Player_GetHitbox(player);468int32 radius = (self->radius + playerHitbox->bottom) << 6;469470if (self->playerStatus[player->playerID]) {471int32 angle = (self->playerAngles[player->playerID] + 8) & 0x3FF;472if (Player_CheckCollisionTouch(player, self, &self->hitboxRange) && !player->onGround) {473if ((player->position.y < self->position.y && player->velocity.y >= 0)474|| (player->position.y >= self->position.y && player->velocity.y <= 0)) {475476bool32 collided = true;477if (player->state == Cylinder_PlayerState_InkRoller_Stand) {478int32 frame = (24 - (24 * angle) / 1024) % 24;479if (player->groundVel)480RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_CS, &player->animator, true, frame);481else482RSDK.SetSpriteAnimation(player->aniFrames, ANI_STAND_CS, &player->animator, true, frame);483484player->animator.rotationStyle = ROTSTYLE_FULL;485player->rotation = 0x100;486487if (player->velocity.x)488player->direction = player->velocity.x > 0;489}490else {491if (player->state != Cylinder_PlayerState_InkRoller_Roll) {492collided = false;493}494else if (!player->velocity.x)495player->direction = player->velocity.x >> 31;496}497498if (collided) {499player->drawGroup = angle >= 0x200 ? Zone->playerDrawGroup[1] : Zone->playerDrawGroup[0];500self->playerAngles[player->playerID] = angle;501player->position.y = radius * RSDK.Cos1024(angle) + self->position.y;502player->abilityValue = player->position.y < self->position.y ? 0 : 0x80;503player->onGround = true;504}505else {506self->playerStatus[player->playerID] = 0;507}508}509}510else {511if (player->state != Player_State_FlyToPlayer && player->state != Player_State_ReturnToPlayer512&& player->state != Player_State_HoldRespawn) {513if (player->onGround || player->velocity.y < 0 || player->state == Player_State_FlyCarried514|| player->animator.animationID == ANI_SKID) {515if (player->onGround) {516if (player->animator.animationID != ANI_JUMP)517player->direction ^= FLIP_X;518519player->state = Player_State_Ground;520}521}522else {523player->state = Player_State_Air;524}525526player->onGround = false;527}528529self->playerStatus[player->playerID] = 0;530}531}532else {533if (Player_CheckCollisionTouch(player, self, &self->hitboxRange) && !player->onGround) {534if (535#if MANIA_USE_PLUS536player->state == Player_State_MightyHammerDrop ||537#endif538player->state == Player_State_BubbleBounce) {539player->onGround = true;540}541else if ((player->position.y < self->position.y && player->velocity.y >= 0)542|| (player->position.y >= self->position.y && player->velocity.y <= 0)) {543if (player->position.y >= self->position.y) {544player->position.y = self->position.y + (radius << 10);545self->playerAngles[player->playerID] = 0x000;546}547else {548player->position.y = self->position.y - (radius << 10);549self->playerAngles[player->playerID] = 0x200;550}551552player->onGround = true;553player->velocity.y = 0;554self->playerStatus[player->playerID] = 1;555556int32 frame = (ANI_STAND_CS - 24 * ((self->playerAngles[player->playerID] + 8) & 0x3FF) / 1024) % ANI_STAND_CS;557if (player->groundVel)558RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_CS, &player->animator, true, frame);559else560RSDK.SetSpriteAnimation(player->aniFrames, ANI_STAND_CS, &player->animator, true, frame);561player->animator.rotationStyle = ROTSTYLE_FULL;562563player->rotation = 0x100;564player->direction ^= FLIP_X;565player->nextAirState = StateMachine_None;566player->nextGroundState = StateMachine_None;567player->state = Cylinder_PlayerState_InkRoller_Stand;568}569}570}571}572}573574void Cylinder_State_Pillar(void)575{576RSDK_THIS(Cylinder);577578foreach_active(Player, player)579{580Hitbox *playerHitbox = Player_GetHitbox(player);581int32 top = self->position.y + (self->hitboxRange.top << 16);582int32 radius = (self->radius + playerHitbox->bottom) << 6;583584if (self->playerStatus[player->playerID]) {585bool32 hasInput = false;586if (player->groundVel > 0) {587if (player->left)588hasInput = true;589}590else if (player->groundVel < 0) {591if (!player->right) {592if (player->left)593hasInput = true;594}595else if (player->right) {596hasInput = true;597}598}599600if (Player_CheckCollisionTouch(player, self, &self->hitboxRange)) {601if (player->onGround) {602if (hasInput) {603if (player->velocity.y > 0x18000)604player->velocity.y = player->velocity.y - 0x2000;605606if (player->velocity.y < 0x18000)607player->velocity.y = 0x18000;608}609else {610if (player->velocity.y < 0x38000)611player->velocity.y = player->velocity.y + 0x2000;612613if (player->velocity.y > 0x38000)614player->velocity.y = 0x38000;615}616617player->position.y += player->velocity.y;618619int32 len = MIN(abs(player->position.y - top) >> 16, self->length);620int32 frame = 0;621622int32 angle = ((len << 10) / 0xC0 + (((uint32)player->groundVel >> 22) & 0x200)) & 0x3FF;623if (player->groundVel <= 0) {624frame = (24 - 24 * angle / 0x400) % 24;625player->direction = FLIP_NONE;626player->rotation = 0x80;627}628else {629angle = 0x3FF - angle;630frame = (24 * angle / 0x400 + 12) % 24;631player->direction = FLIP_X;632player->rotation = 0x180;633}634635player->position.x = radius * RSDK.Cos1024(angle) + self->position.x;636self->playerAngles[player->playerID] = angle;637player->drawGroup = angle >= 0x200 ? Zone->playerDrawGroup[1] : Zone->playerDrawGroup[0];638639RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_CS, &player->animator, true, frame);640player->animator.rotationStyle = ROTSTYLE_FULL;641642player->abilityValue = player->position.x < self->position.x ? 0 : 0x80;643player->onGround = true;644645if (player->jumpPress) {646RSDK.PlaySfx(Player->sfxJump, false, 255);647player->velocity.x = player->position.x < self->position.x ? -0x60000 : 0x60000;648RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);649player->onGround = false;650}651}652}653else {654if (!player->onGround && player->state != Player_State_FlyCarried) {655player->state = Player_State_Air;656player->onGround = false;657player->tileCollisions = TILECOLLISION_DOWN;658}659else if (player->onGround) {660player->state = Player_State_Ground;661662if (player->position.x >= self->position.x) {663player->angle = 64;664player->direction = FLIP_NONE;665if (hasInput || player->groundVel < player->velocity.y)666player->groundVel = player->velocity.y;667}668else {669player->angle = 192;670player->direction = FLIP_X;671if (hasInput || player->groundVel > -player->velocity.y)672player->groundVel = -player->velocity.y;673}674675if (player->animator.animationID == ANI_SPRING_CS) {676if (abs(player->groundVel) < 0xC0000) {677if (abs(player->groundVel) < 0x60000) {678if (abs(player->groundVel) < 0x40000)679RSDK.SetSpriteAnimation(player->aniFrames, ANI_WALK, &player->animator, false, 0);680else681RSDK.SetSpriteAnimation(player->aniFrames, ANI_JOG, &player->animator, false, 0);682}683else {684RSDK.SetSpriteAnimation(player->aniFrames, ANI_RUN, &player->animator, false, 1);685}686}687else {688RSDK.SetSpriteAnimation(player->aniFrames, ANI_DASH, &player->animator, false, 1);689}690}691692player->onGround = true;693player->tileCollisions = TILECOLLISION_DOWN;694}695696self->playerStatus[player->playerID] = 0;697}698}699else if (Player_CheckCollisionTouch(player, self, &self->hitboxRange) && player->onGround) {700if ((player->angle == 0x40 && player->groundVel > 0) || (player->angle == 0xC0 && player->groundVel < 0)) {701if (player->angle == 0x40 && player->direction == FLIP_X)702player->direction = FLIP_NONE;703704if (player->angle == 0xC0 && player->direction == FLIP_NONE)705player->direction = FLIP_X;706707if (player->position.x >= self->position.x) {708player->position.x = self->position.x + (radius << 10);709self->playerAngles[player->playerID] = 0;710}711else {712player->position.x = self->position.x - (radius << 10);713self->playerAngles[player->playerID] = 512;714}715716player->onGround = true;717player->velocity.x = 0;718self->playerStatus[player->playerID] = 1;719player->nextAirState = 0;720player->nextGroundState = 0;721player->state = Cylinder_PlayerState_Pillar;722player->tileCollisions = TILECOLLISION_NONE;723724if (abs(player->groundVel) > 0x18000) {725if (abs(player->groundVel) >= 0x38000)726player->velocity.y = 0x38000;727else if (player->groundVel >= 0)728player->velocity.y = player->groundVel;729else730player->velocity.y = -player->groundVel;731}732else {733player->velocity.y = 0x18000;734}735}736}737}738}739740void Cylinder_PlayerState_InkRoller_Stand(void)741{742RSDK_THIS(Player);743744Player_HandleGroundMovement();745746self->skidding = 0;747if (self->camera)748self->camera->disableYOffset = false;749750self->jumpAbilityState = 0;751752if (self->jumpPress) {753Player_Action_Jump(self);754755if (self->abilityValue == 128)756self->velocity.y = -self->velocity.y;757758self->direction ^= FLIP_X;759self->timer = 0;760}761else {762if (abs(self->groundVel) >= 0x8800 && !self->left && !self->right && self->down) {763if (self->abilityValue == 128)764self->position.y -= self->jumpOffset;765else766self->position.y += self->jumpOffset;767768RSDK.SetSpriteAnimation(self->aniFrames, ANI_JUMP, &self->animator, false, 0);769self->direction ^= FLIP_X;770self->state = Cylinder_PlayerState_InkRoller_Roll;771RSDK.PlaySfx(Player->sfxRoll, false, 255);772}773}774}775776void Cylinder_PlayerState_InkRoller_Roll(void)777{778RSDK_THIS(Player);779780int32 angle = self->angle;781self->angle = 0;782Player_HandleRollDeceleration();783784if (self->state == Player_State_Ground) {785self->direction ^= FLIP_X;786self->state = Cylinder_PlayerState_InkRoller_Stand;787}788789if (self->characterID == ID_TAILS)790self->animator.speed = 120;791else792self->animator.speed = ((abs(self->groundVel) * 0xF0) / 0x60000) + 0x30;793794if (self->animator.speed > 0xF0)795self->animator.speed = 0xF0;796797if (self->camera)798self->camera->disableYOffset = false;799800self->jumpAbilityState = 0;801self->angle = angle;802803if (self->jumpPress) {804Player_Action_Jump(self);805806if (self->abilityValue == 128)807self->velocity.y = -self->velocity.y;808809self->timer = 0;810}811}812813void Cylinder_PlayerState_Pillar(void)814{815RSDK_THIS(Player);816817if (self->onGround)818self->rotation = self->angle << 1;819}820821void Cylinder_PlayerState_Spiral(void)822{823RSDK_THIS(Player);824825self->down = false;826Player_State_Ground();827}828829#if GAME_INCLUDE_EDITOR830void Cylinder_EditorDraw(void)831{832RSDK_THIS(Cylinder);833834RSDK.DrawSprite(&Cylinder->animator, NULL, false);835836switch (self->type) {837case CYLINDER_TUBE_H:838self->updateRange.x = self->length << 16;839self->updateRange.y = self->radius << 16;840841self->hitboxRange.left = -self->length;842self->hitboxRange.top = -self->radius;843self->hitboxRange.right = self->length;844self->hitboxRange.bottom = self->radius;845break;846847case CYLINDER_TUBE_V:848self->updateRange.x = self->radius << 16;849self->updateRange.y = self->length << 16;850851self->hitboxRange.left = -self->radius;852self->hitboxRange.top = -self->length;853self->hitboxRange.right = self->radius;854self->hitboxRange.bottom = self->length;855break;856857case CYLINDER_SPIRAL_LR:858self->updateRange.x = (self->radius + 112) << 16;859self->updateRange.y = self->length << 16;860861self->hitboxRange.left = -64 - self->radius;862self->hitboxRange.right = self->radius + 64;863self->hitboxRange.top = -self->length;864self->hitboxRange.bottom = self->length;865866self->hitboxL.left = -112 - self->radius;867self->hitboxL.right = -self->radius;868self->hitboxL.top = -self->length;869self->hitboxL.bottom = 64 - self->length;870871self->hitboxR.left = self->radius;872self->hitboxR.top = self->length - 64;873self->hitboxR.right = self->length + 112;874self->hitboxR.bottom = self->length;875break;876877case CYLINDER_SPIRAL_RL:878self->updateRange.x = (self->radius + 112) << 16;879self->updateRange.y = self->length << 16;880881self->hitboxRange.left = -64 - self->radius;882self->hitboxRange.top = -self->length;883self->hitboxRange.right = self->radius + 64;884self->hitboxRange.bottom = self->length;885886self->hitboxL.left = -112 - self->radius;887self->hitboxL.top = self->length - 64;888self->hitboxL.right = -self->radius;889self->hitboxL.bottom = self->length;890891self->hitboxR.left = self->radius;892self->hitboxR.top = -self->length;893self->hitboxR.right = self->radius + 112;894self->hitboxR.bottom = 64 - self->length;895break;896897case CYLINDER_INKROLLER:898self->updateRange.x = self->length << 16;899self->updateRange.y = self->radius << 16;900901self->hitboxRange.left = 16 - self->length;902self->hitboxRange.top = ~self->radius;903self->hitboxRange.right = self->length - 16;904self->hitboxRange.bottom = self->radius + 1;905break;906907case CYLINDER_PILLAR:908self->updateRange.x = self->radius << 17;909self->updateRange.y = self->length << 17;910911self->hitboxRange.left = -16 - self->radius;912self->hitboxRange.top = -self->length;913self->hitboxRange.right = self->radius + 16;914self->hitboxRange.bottom = self->length;915break;916917default: break;918}919920if (showGizmos()) {921RSDK_DRAWING_OVERLAY(true);922923DrawHelpers_DrawHitboxOutline(self->position.x, self->position.y, &self->hitboxRange, FLIP_NONE, 0xFFFF00);924925if (self->type == CYLINDER_SPIRAL_LR || self->type == CYLINDER_SPIRAL_RL) {926DrawHelpers_DrawHitboxOutline(self->position.x, self->position.y, &self->hitboxL, FLIP_NONE, 0xFF0000);927DrawHelpers_DrawHitboxOutline(self->position.x, self->position.y, &self->hitboxR, FLIP_NONE, 0xFF0000);928}929930RSDK_DRAWING_OVERLAY(false);931}932}933934void Cylinder_EditorLoad(void)935{936Cylinder->aniFrames = RSDK.LoadSpriteAnimation("FBZ/Cylinder.bin", SCOPE_STAGE);937RSDK.SetSpriteAnimation(Cylinder->aniFrames, 0, &Cylinder->animator, true, 0);938939RSDK_ACTIVE_VAR(Cylinder, type);940RSDK_ENUM_VAR("Tube H", CYLINDER_TUBE_H);941RSDK_ENUM_VAR("Tube V", CYLINDER_TUBE_V);942RSDK_ENUM_VAR("FBZ Spiral - LR", CYLINDER_SPIRAL_LR);943RSDK_ENUM_VAR("FBZ Spiral - RL", CYLINDER_SPIRAL_RL);944RSDK_ENUM_VAR("Ink Roller", CYLINDER_INKROLLER);945RSDK_ENUM_VAR("Fixed V - L (Unused)", CYLINDER_FIXED_V_L);946RSDK_ENUM_VAR("Fixed V - R (Unused)", CYLINDER_FIXED_V_R);947RSDK_ENUM_VAR("SSZ1 Pillar", CYLINDER_PILLAR);948}949#endif950951void Cylinder_Serialize(void)952{953RSDK_EDITABLE_VAR(Cylinder, VAR_UINT8, type);954RSDK_EDITABLE_VAR(Cylinder, VAR_ENUM, length);955RSDK_EDITABLE_VAR(Cylinder, VAR_ENUM, radius);956}957958959