Path: blob/master/SonicMania/Objects/MSZ/RollerMKII.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: RollerMKII Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectRollerMKII *RollerMKII;1011void RollerMKII_Update(void)12{13RSDK_THIS(RollerMKII);1415StateMachine_Run(self->state);16}1718void RollerMKII_LateUpdate(void) {}1920void RollerMKII_StaticUpdate(void) {}2122void RollerMKII_Draw(void)23{24RSDK_THIS(RollerMKII);2526RSDK.DrawSprite(&self->animator, NULL, false);27}2829void RollerMKII_Create(void *data)30{31RSDK_THIS(RollerMKII);3233self->visible = true;34self->drawGroup = Zone->objectDrawGroup[0];35self->startPos = self->position;36self->startDir = self->direction;37self->drawFX = FX_FLIP;38self->active = ACTIVE_BOUNDS;39self->updateRange.x = 0x1000000;40self->updateRange.y = 0x1000000;41self->onGround = false;42self->tileCollisions = TILECOLLISION_DOWN;43self->collisionLayers = Zone->collisionLayers;44self->collisionPlane = 0;45RSDK.SetSpriteAnimation(RollerMKII->aniFrames, 0, &self->animator, true, 5);46self->state = RollerMKII_State_Init;47}4849void RollerMKII_StageLoad(void)50{51if (RSDK.CheckSceneFolder("MSZ"))52RollerMKII->aniFrames = RSDK.LoadSpriteAnimation("MSZ/RollerMKII.bin", SCOPE_STAGE);5354RollerMKII->hitboxOuter_Rolling.left = -9;55RollerMKII->hitboxOuter_Rolling.top = -14;56RollerMKII->hitboxOuter_Rolling.right = 9;57RollerMKII->hitboxOuter_Rolling.bottom = 14;5859RollerMKII->hitboxInner_Rolling.left = -8;60RollerMKII->hitboxInner_Rolling.top = -14;61RollerMKII->hitboxInner_Rolling.right = 8;62RollerMKII->hitboxInner_Rolling.bottom = 14;6364RollerMKII->hitboxOuter_Idle.left = -9;65RollerMKII->hitboxOuter_Idle.top = -14;66RollerMKII->hitboxOuter_Idle.right = 9;67RollerMKII->hitboxOuter_Idle.bottom = 24;6869RollerMKII->hitboxInner_Idle.left = -8;70RollerMKII->hitboxInner_Idle.top = -14;71RollerMKII->hitboxInner_Idle.right = 8;72RollerMKII->hitboxInner_Idle.bottom = 24;7374// Hitbox for interacting with player75RollerMKII->hitboxBadnik.left = -14;76RollerMKII->hitboxBadnik.top = -14;77RollerMKII->hitboxBadnik.right = 14;78RollerMKII->hitboxBadnik.bottom = 14;7980// Hitbox for interacting with other objects81// It's.... the same... as above???82RollerMKII->hitboxObject.left = -14;83RollerMKII->hitboxObject.top = -14;84RollerMKII->hitboxObject.right = 14;85RollerMKII->hitboxObject.bottom = 14;8687RollerMKII->sfxBumper = RSDK.GetSfx("Stage/Bumper3.wav");88RollerMKII->sfxJump = RSDK.GetSfx("Stage/Jump2.wav");89RollerMKII->sfxDropDash = RSDK.GetSfx("Global/DropDash.wav");90RollerMKII->sfxRelease = RSDK.GetSfx("Global/Release.wav");91RollerMKII->sfxSkidding = RSDK.GetSfx("Global/Skidding.wav");9293DEBUGMODE_ADD_OBJ(RollerMKII);94}9596void RollerMKII_DebugSpawn(void)97{98RSDK_THIS(DebugMode);99100EntityRollerMKII *rollerMKII = CREATE_ENTITY(RollerMKII, NULL, self->position.x, self->position.y);101rollerMKII->direction = self->direction;102rollerMKII->startDir = self->direction;103}104105void RollerMKII_DebugDraw(void)106{107RSDK.SetSpriteAnimation(RollerMKII->aniFrames, 0, &DebugMode->animator, true, 1);108RSDK.DrawSprite(&DebugMode->animator, NULL, false);109}110111void RollerMKII_CheckOffScreen(void)112{113RSDK_THIS(RollerMKII);114115if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {116self->position = self->startPos;117self->direction = self->startDir;118RollerMKII_Create(NULL);119}120}121122void RollerMKII_CheckPlayerCollisions(void)123{124RSDK_THIS(RollerMKII);125126foreach_active(Player, player)127{128if (Player_CheckBadnikTouch(player, self, &RollerMKII->hitboxBadnik))129Player_CheckBadnikBreak(player, self, true);130}131}132133void RollerMKII_CheckPlayerCollisions_Rolling(void)134{135RSDK_THIS(RollerMKII);136137foreach_active(Player, player)138{139if (Player_CheckBadnikTouch(player, self, &RollerMKII->hitboxBadnik)) {140141int32 anim = player->animator.animationID;142bool32 shouldBump = false;143144#if MANIA_USE_PLUS145if (player->state == Player_State_MightyHammerDrop) {146Player_CheckBadnikBreak(player, self, true);147}148else {149shouldBump = player->characterID == ID_MIGHTY && (anim == ANI_CROUCH || player->jumpAbilityState > 1);150#endif151if (Player_CheckAttacking(player, self) || shouldBump) {152RSDK.PlaySfx(RollerMKII->sfxBumper, false, 255);153int32 angle = RSDK.ATan2(player->position.x - self->position.x, player->position.y - self->position.y);154int32 velX = 0x380 * RSDK.Cos256(angle);155int32 velY = 0x380 * RSDK.Sin256(angle);156157if (anim != ANI_FLY && anim != ANI_FLY_LIFT_TIRED) {158if (player->state != Player_State_TailsFlight) {159if (player->state != Player_State_DropDash)160player->state = Player_State_Air;161if (anim != ANI_JUMP && anim != ANI_DASH)162player->animator.animationID = ANI_WALK;163}164}165166#if MANIA_USE_PLUS167if (player->characterID != ID_MIGHTY || player->jumpAbilityState <= 1) {168#endif169player->velocity.x = velX;170player->groundVel = velX;171player->applyJumpCap = false;172if (player->characterID == ID_KNUCKLES && player->animator.animationID == ANI_GLIDE) {173RSDK.SetSpriteAnimation(player->aniFrames, ANI_GLIDE_DROP, &player->animator, false, 0);174player->state = Player_State_KnuxGlideDrop;175}176player->velocity.y = velY;177player->onGround = false;178player->tileCollisions = TILECOLLISION_DOWN;179#if MANIA_USE_PLUS180}181#endif182RSDK.PlaySfx(RollerMKII->sfxBumper, false, 255);183RSDK.SetSpriteAnimation(RollerMKII->aniFrames, 2, &self->animator, true, 0);184self->velocity.y = -0x40000;185self->velocity.x = -velX;186self->onGround = false;187self->touchedGround = 0;188self->timer = 45;189self->state = RollerMKII_State_Bumped;190self->direction = player->position.x < self->position.x;191}192else {193Player_Hurt(player, self);194}195#if MANIA_USE_PLUS196}197#endif198}199}200}201202int32 RollerMKII_HandleObjectCollisions(Entity *otherEntity, Hitbox *hitbox)203{204RSDK_THIS(RollerMKII);205206int32 velX = self->velocity.x;207int32 side = RSDK.CheckObjectCollisionBox(otherEntity, hitbox, self, &RollerMKII->hitboxObject, true);208209if ((side == C_LEFT && velX > 0) || (side == C_RIGHT && velX < 0)) {210if (self->state != RollerMKII_State_Bumped) {211RSDK.PlaySfx(RollerMKII->sfxBumper, false, 255);212RSDK.SetSpriteAnimation(RollerMKII->aniFrames, 0, &self->animator, true, 0);213self->velocity.y = -0x40000;214self->onGround = false;215self->touchedGround = 0;216self->timer = 30;217self->velocity.x = velX < 0 ? 0x20000 : -0x20000;218self->state = RollerMKII_State_Bumped;219self->direction = self->position.x < Player_GetNearestPlayer()->position.x;220}221}222return side;223}224225bool32 RollerMKII_HandlePlatformCollisions(EntityPlatform *platform)226{227RSDK_THIS(RollerMKII);228bool32 collided = false;229230if (platform->state != Platform_State_Falling2 && platform->state != Platform_State_Hold) {231platform->position.x = platform->drawPos.x - platform->collisionOffset.x;232platform->position.y = platform->drawPos.y - platform->collisionOffset.y;233if (platform->collision) {234if (platform->collision != PLATFORM_C_SOLID) {235if (platform->collision == PLATFORM_C_TILED236&& RSDK.CheckObjectCollisionTouchBox(platform, &platform->hitbox, self, &RollerMKII->hitboxObject)) {237if (self->collisionLayers & Zone->moveLayerMask) {238TileLayer *move = RSDK.GetTileLayer(Zone->moveLayer);239move->position.x = -(platform->drawPos.x + platform->tileOrigin.x) >> 16;240move->position.y = -(platform->drawPos.y + platform->tileOrigin.y) >> 16;241}242243if (self->velocity.y >= 0x3800)244collided = true;245}246}247else {248Hitbox *hitbox = RSDK.GetHitbox(&platform->animator, 1);249collided = RollerMKII_HandleObjectCollisions((Entity *)platform, hitbox);250}251}252else {253Hitbox *hitbox = RSDK.GetHitbox(&platform->animator, 0);254RSDK.CheckObjectCollisionPlatform(platform, hitbox, self, &RollerMKII->hitboxObject, true);255}256257platform->position = platform->centerPos;258}259260return collided;261}262263void RollerMKII_HandleCollisions(void)264{265RSDK_THIS(RollerMKII);266267foreach_all(PlaneSwitch, planeSwitch)268{269PlaneSwitch_CheckCollisions(planeSwitch, self, planeSwitch->flags, planeSwitch->size, true, Zone->playerDrawGroup[0],270Zone->playerDrawGroup[1]);271}272273foreach_all(Platform, platform) { RollerMKII_HandlePlatformCollisions(platform); }274foreach_all(Spikes, spikes) { RollerMKII_HandleObjectCollisions((Entity *)spikes, &spikes->hitbox); }275foreach_all(BreakableWall, wall) { RollerMKII_HandleObjectCollisions((Entity *)wall, &wall->hitbox); }276277if (!self->collisionMode && self->state != RollerMKII_State_Bumped) {278bool32 collided = self->direction == FLIP_X279? RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_RWALL, self->collisionPlane, -0xA0000, 0, false)280: RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_LWALL, self->collisionPlane, 0xA0000, 0, false);281if (collided) {282RSDK.PlaySfx(RollerMKII->sfxBumper, false, 255);283RSDK.SetSpriteAnimation(RollerMKII->aniFrames, 0, &self->animator, true, 0);284self->onGround = false;285self->velocity.x = self->direction == FLIP_X ? 0x20000 : -0x20000;286self->velocity.y = -0x40000;287self->touchedGround = 0;288self->timer = 30;289self->state = RollerMKII_State_Bumped;290self->direction = self->position.x < Player_GetNearestPlayer()->position.x;291}292}293}294295void RollerMKII_State_Init(void)296{297RSDK_THIS(RollerMKII);298299self->active = ACTIVE_NORMAL;300self->velocity.x = 0;301self->velocity.y = 0;302self->groundVel = 0;303self->touchedGround = 0;304305self->state = RollerMKII_State_Idle;306RollerMKII_State_Idle();307}308309void RollerMKII_State_Idle(void)310{311RSDK_THIS(RollerMKII);312313RSDK.ProcessAnimation(&self->animator);314315Vector2 range = { 0x200000, 0x200000 };316317if (self->timer) {318self->timer--;319}320else if (RSDK.CheckOnScreen(self, &range)) {321bool32 wallCollided = false;322if (self->direction == FLIP_X)323wallCollided = RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_RWALL, self->collisionPlane, -0x180000, 0, false);324else325wallCollided = RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_LWALL, self->collisionPlane, 0x180000, 0, false);326327if (wallCollided)328self->direction ^= FLIP_X;329330foreach_active(Player, player)331{332if (self->direction) {333if (player->position.x < self->position.x) {334if (self->position.x - player->position.x < 0x800000) {335self->velocity.y = -0x40000;336RSDK.SetSpriteAnimation(RollerMKII->aniFrames, 1, &self->animator, true, 0);337338self->playerPtr = player;339RSDK.PlaySfx(RollerMKII->sfxJump, false, 0xFF);340341self->state = RollerMKII_State_SpinUp;342}343}344}345else {346if (player->position.x > self->position.x) {347if (player->position.x - self->position.x < 0x800000) {348self->velocity.y = -0x40000;349RSDK.SetSpriteAnimation(RollerMKII->aniFrames, 1, &self->animator, true, 0);350351self->playerPtr = player;352RSDK.PlaySfx(RollerMKII->sfxJump, false, 0xFF);353354self->state = RollerMKII_State_SpinUp;355}356}357}358}359}360361RollerMKII_CheckPlayerCollisions();362RollerMKII_CheckOffScreen();363}364365void RollerMKII_State_SpinUp(void)366{367RSDK_THIS(RollerMKII);368369self->position.x += self->velocity.x;370self->position.y += self->velocity.y;371self->velocity.y += 0x3800;372373RSDK.ProcessAnimation(&self->animator);374375if (self->velocity.y > 0) {376self->timer = 15;377RSDK.PlaySfx(RollerMKII->sfxDropDash, false, 255);378self->state = RollerMKII_State_RollDelay;379}380381if (self->animator.frameID <= 4)382RollerMKII_CheckPlayerCollisions();383else384RollerMKII_CheckPlayerCollisions_Rolling();385386RollerMKII_CheckOffScreen();387}388389void RollerMKII_State_RollDelay(void)390{391RSDK_THIS(RollerMKII);392393RSDK.ProcessAnimation(&self->animator);394395if (!--self->timer)396self->state = RollerMKII_State_Rolling_Air;397398RollerMKII_CheckPlayerCollisions_Rolling();399RollerMKII_CheckOffScreen();400}401402void RollerMKII_State_Rolling_Air(void)403{404RSDK_THIS(RollerMKII);405406if (!self->touchedGround) {407if (self->position.x <= self->playerPtr->position.x) {408self->direction = FLIP_NONE;409410if (self->velocity.x < 0x80000)411self->velocity.x += 0x3800;412}413else {414self->direction = FLIP_X;415416if (self->velocity.x > -0x80000)417self->velocity.x -= 0x3800;418}419}420421RSDK.ProcessObjectMovement(self, &RollerMKII->hitboxOuter_Rolling, &RollerMKII->hitboxInner_Rolling);422423self->velocity.y += 0x3800;424425RollerMKII_HandleCollisions();426427if (self->onGround) {428if (abs(self->angle) & 0x60) {429self->state = RollerMKII_State_Rolling_Ground;430}431else {432if (self->velocity.x)433self->groundVel = self->velocity.x;434435if (!self->touchedGround) {436self->touchedGround = true;437438if (self->direction == FLIP_NONE) {439self->groundVel = 0x80000;440self->velocity.x = 0x80000;441}442else {443self->groundVel = -0x80000;444self->velocity.x = -0x80000;445}446self->velocity.y = -0x20000;447448self->onGround = false;449RSDK.StopSfx(RollerMKII->sfxDropDash);450RSDK.PlaySfx(RollerMKII->sfxRelease, false, 255);451Hitbox *hitbox = RSDK.GetHitbox(&self->animator, 0);452453EntityDust *dust = CREATE_ENTITY(Dust, self, self->position.x, self->position.y + 0xE0000);454RSDK.SetSpriteAnimation(Dust->aniFrames, 2, &dust->animator, true, 0);455dust->state = Dust_State_DustPuff;456dust->position.y += hitbox->bottom << 16;457dust->direction = self->direction;458dust->drawGroup = self->drawGroup;459dust->position.x += self->direction ? 0x90000 : -0x90000;460}461else if (self->velocity.y <= 0x10000) {462self->state = RollerMKII_State_Rolling_Ground;463}464else {465self->velocity.y = -0x20000;466self->onGround = false;467}468}469470self->direction = self->groundVel < 0;471}472473RSDK.ProcessAnimation(&self->animator);474475RollerMKII_CheckPlayerCollisions_Rolling();476RollerMKII_CheckOffScreen();477}478479void RollerMKII_State_Rolling_Ground(void)480{481RSDK_THIS(RollerMKII);482483if (!self->collisionMode) {484if (self->position.x <= self->playerPtr->position.x) {485self->direction = FLIP_NONE;486487if (self->groundVel < 0x80000) {488self->groundVel += 0x3800;489490if (self->groundVel > 0) {491self->groundVel += 0x1400;492493if (self->groundVel >= -0x40000) {494self->timer = 0;495}496else {497RSDK.PlaySfx(RollerMKII->sfxSkidding, false, 255);498self->timer = (self->timer + 1) & 3;499if (!self->timer)500CREATE_ENTITY(Dust, NULL, self->position.x, self->position.y + 0xE0000)->state = Dust_State_DustPuff;501}502}503}504}505else {506self->direction = FLIP_X;507508if (self->groundVel > -0x80000) {509self->groundVel -= 0x3800;510511if (self->groundVel > 0) {512self->groundVel += 0x1400;513514if (self->groundVel <= 0x40000) {515self->timer = 0;516}517else {518RSDK.PlaySfx(RollerMKII->sfxSkidding, false, 255);519self->timer = (self->timer + 1) & 3;520if (!self->timer)521CREATE_ENTITY(Dust, NULL, self->position.x, self->position.y + 0xE0000)->state = Dust_State_DustPuff;522}523}524}525}526}527528RSDK.ProcessObjectMovement(self, &RollerMKII->hitboxOuter_Rolling, &RollerMKII->hitboxInner_Rolling);529530self->groundVel += (RSDK.Sin256(self->angle) << 13 >> 8);531if (self->collisionMode != CMODE_FLOOR) {532if (self->angle >= 0x40 && self->angle <= 0xC0 && self->groundVel <= 0x20000) {533self->onGround = false;534self->angle = 0;535self->collisionMode = 0;536}537}538539RollerMKII_HandleCollisions();540541if (!self->onGround && self->state != RollerMKII_State_Bumped)542self->state = RollerMKII_State_Rolling_Air;543544RSDK.ProcessAnimation(&self->animator);545546RollerMKII_CheckPlayerCollisions_Rolling();547RollerMKII_CheckOffScreen();548}549550void RollerMKII_State_Bumped(void)551{552RSDK_THIS(RollerMKII);553554RSDK.ProcessObjectMovement(self, &RollerMKII->hitboxOuter_Idle, &RollerMKII->hitboxInner_Idle);555556self->velocity.y += 0x3800;557RollerMKII_HandleCollisions();558559if (self->onGround) {560self->groundVel = 0;561self->velocity.x = 0;562self->velocity.y = 0;563self->state = RollerMKII_State_Idle;564RSDK.SetSpriteAnimation(RollerMKII->aniFrames, 0, &self->animator, true, 0);565}566567RSDK.ProcessAnimation(&self->animator);568RollerMKII_CheckOffScreen();569}570571#if GAME_INCLUDE_EDITOR572void RollerMKII_EditorDraw(void) { RollerMKII_Draw(); }573574void RollerMKII_EditorLoad(void)575{576RollerMKII->aniFrames = RSDK.LoadSpriteAnimation("MSZ/RollerMKII.bin", SCOPE_STAGE);577578RSDK_ACTIVE_VAR(RollerMKII, direction);579RSDK_ENUM_VAR("Right", FLIP_NONE);580RSDK_ENUM_VAR("Left", FLIP_X);581}582#endif583584void RollerMKII_Serialize(void) { RSDK_EDITABLE_VAR(RollerMKII, VAR_UINT8, direction); }585586587