Path: blob/master/SonicMania/Objects/MMZ/Scarab.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Scarab Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectScarab *Scarab;1011void Scarab_Update(void)12{13RSDK_THIS(Scarab);1415RSDK.ProcessAnimation(&self->bodyAnimator);16RSDK.ProcessAnimation(&self->backLegAnimator);17RSDK.ProcessAnimation(&self->frontLegAnimator);1819self->moveOffset.x = -self->position.x;20self->moveOffset.y = -self->position.y;2122StateMachine_Run(self->state);2324self->moveOffset.x += self->position.x;25self->moveOffset.y += self->position.y;2627Scarab_CheckPlayerCollisions();28Scarab_HandleChildMove();29Scarab_HandlePlayerGrab();3031if (self->state != Scarab_State_Init) {32if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {33int32 x = -self->position.x;34int32 y = -self->position.y;3536self->direction = self->startDir;37self->position = self->startPos;38self->moveOffset.x = self->position.x + x;39self->moveOffset.y = self->position.y + y;4041Scarab_HandleChildMove();42Scarab_Create(NULL);43}44}45}4647void Scarab_LateUpdate(void) {}4849void Scarab_StaticUpdate(void)50{51foreach_active(Scarab, scarab) { RSDK.AddDrawListRef(scarab->drawGroupHigh, RSDK.GetEntitySlot(scarab)); }52}5354void Scarab_Draw(void)55{56RSDK_THIS(Scarab);5758if (SceneInfo->currentDrawGroup == self->drawGroupHigh) {59RSDK.DrawSprite(&self->frontLegAnimator, NULL, false);60}61else {62RSDK.DrawSprite(&self->backLegAnimator, NULL, false);63RSDK.DrawSprite(&self->bodyAnimator, NULL, false);64}65}6667void Scarab_Create(void *data)68{69RSDK_THIS(Scarab);7071self->visible = true;72self->drawGroup = Zone->objectDrawGroup[0];7374if (self->planeFilter == PLANEFILTER_NONE) {75self->drawGroupLow = Zone->objectDrawGroup[0];76self->drawGroupHigh = Zone->playerDrawGroup[1];77}78else if ((uint8)(self->planeFilter - 1) & 2) {79self->drawGroupLow = Zone->objectDrawGroup[1];80self->drawGroupHigh = Zone->playerDrawGroup[1];81}82else {83self->drawGroupLow = Zone->objectDrawGroup[0];84self->drawGroupHigh = Zone->playerDrawGroup[0];85}8687self->drawFX = FX_FLIP;88self->active = ACTIVE_BOUNDS;89self->updateRange.x = 0x800000;90self->updateRange.y = 0x800000;9192if (!self->amplitude)93self->amplitude = 100;9495self->startPos = self->position;96self->startDir = self->direction;97self->state = Scarab_State_Init;98}99100void Scarab_StageLoad(void)101{102if (RSDK.CheckSceneFolder("MMZ"))103Scarab->aniFrames = RSDK.LoadSpriteAnimation("MMZ/Scarab.bin", SCOPE_STAGE);104105Scarab->hitboxBadnik.left = -16;106Scarab->hitboxBadnik.top = -14;107Scarab->hitboxBadnik.right = 14;108Scarab->hitboxBadnik.bottom = 6;109110Scarab->hitboxGrab.left = -48;111Scarab->hitboxGrab.top = -14;112Scarab->hitboxGrab.right = -17;113Scarab->hitboxGrab.bottom = 6;114115Scarab->active = ACTIVE_ALWAYS;116117DEBUGMODE_ADD_OBJ(Scarab);118}119120void Scarab_DebugSpawn(void)121{122RSDK_THIS(Scarab);123124EntityScarab *scarab = CREATE_ENTITY(Scarab, NULL, self->position.x, self->position.y);125scarab->direction = self->direction;126scarab->startDir = self->direction;127}128129void Scarab_DebugDraw(void)130{131RSDK.SetSpriteAnimation(Scarab->aniFrames, 4, &DebugMode->animator, true, 0);132RSDK.DrawSprite(&DebugMode->animator, NULL, false);133134RSDK.SetSpriteAnimation(Scarab->aniFrames, 0, &DebugMode->animator, true, 0);135RSDK.DrawSprite(&DebugMode->animator, NULL, false);136137RSDK.SetSpriteAnimation(Scarab->aniFrames, 2, &DebugMode->animator, true, 0);138RSDK.DrawSprite(&DebugMode->animator, NULL, false);139}140141void Scarab_CheckPlayerCollisions(void)142{143RSDK_THIS(Scarab);144145foreach_active(Player, player)146{147if (self->planeFilter <= 0 || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) {148int32 playerID = RSDK.GetEntitySlot(player);149if (Player_CheckBadnikTouch(player, self, &Scarab->hitboxBadnik)) {150Scarab_HandlePlayerRelease();151Player_CheckBadnikBreak(player, self, true);152}153154if (!self->childCount) {155if (Player_CheckCollisionTouch(player, self, &Scarab->hitboxGrab)) {156if (!((1 << playerID) & self->grabbedPlayers) && !self->playerTimers[playerID]) {157self->grabbedPlayers |= 1 << playerID;158RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);159player->groundVel = 0;160player->onGround = false;161player->tileCollisions = TILECOLLISION_NONE;162player->state = Player_State_Static;163player->nextAirState = StateMachine_None;164player->nextGroundState = StateMachine_None;165self->isPermanent = true;166}167}168}169}170}171}172173void Scarab_HandleChildMove(void)174{175RSDK_THIS(Scarab);176177int32 slot = SceneInfo->entitySlot + 1;178for (int32 c = 0; c < self->childCount; ++c) {179EntityItemBox *child = RSDK_GET_ENTITY(slot + c, ItemBox);180child->position.x += self->moveOffset.x;181child->position.y += self->moveOffset.y;182183if (child->classID == ItemBox->classID)184child->moveOffset = self->moveOffset;185}186}187188void Scarab_HandlePlayerGrab(void)189{190RSDK_THIS(Scarab);191192foreach_active(Player, player)193{194int32 playerID = RSDK.GetEntitySlot(player);195if ((1 << playerID) & self->grabbedPlayers) {196if (self->playerTimers[playerID] < 60 && player->interaction && player->state == Player_State_Static) {197player->position.x = self->position.x + ((2 * (self->direction != FLIP_NONE) - 1) << 21);198player->position.y = self->position.y - 0xA0000;199player->velocity.x = self->state == Scarab_State_Move ? (0x6000 * self->moveDir) : 0;200player->velocity.y = 0;201++self->playerTimers[playerID];202}203else {204self->grabbedPlayers &= ~(1 << playerID);205self->playerTimers[playerID] = -10;206207if (player->state != Player_State_FlyToPlayer && player->state != Player_State_ReturnToPlayer) {208player->tileCollisions = TILECOLLISION_DOWN;209player->state = Player_State_Air;210player->velocity.x = 0xA0000 * (2 * (self->direction != FLIP_NONE) - 1);211player->velocity.y = 0;212}213214self->isPermanent = false;215}216}217else {218if (self->playerTimers[playerID] < 0)219self->playerTimers[playerID]++;220}221}222}223224void Scarab_HandlePlayerRelease(void)225{226RSDK_THIS(Scarab);227228foreach_active(Player, player)229{230int32 playerID = RSDK.GetEntitySlot(player);231232if ((1 << playerID) & self->grabbedPlayers) {233self->grabbedPlayers &= ~(1 << playerID);234self->playerTimers[playerID] = -10;235236if (player->state != Player_State_FlyToPlayer && player->state != Player_State_ReturnToPlayer) {237player->tileCollisions = TILECOLLISION_DOWN;238player->state = Player_State_Air;239player->velocity.x = 0xA0000 * (2 * (self->direction != FLIP_NONE) - 1);240player->velocity.y = 0;241}242243self->isPermanent = false;244}245}246}247248void Scarab_State_Init(void)249{250RSDK_THIS(Scarab);251252self->active = ACTIVE_NORMAL;253self->state = Scarab_State_Move;254self->pullCount = 0;255self->timer = 0;256self->moveDir = 2 * (self->direction != FLIP_NONE) - 1;257258RSDK.SetSpriteAnimation(Scarab->aniFrames, 1, &self->bodyAnimator, true, 0);259RSDK.SetSpriteAnimation(Scarab->aniFrames, 5, &self->backLegAnimator, true, 0);260RSDK.SetSpriteAnimation(Scarab->aniFrames, 3, &self->frontLegAnimator, true, 0);261262Scarab_State_Move();263}264265void Scarab_State_Move(void)266{267RSDK_THIS(Scarab);268269if (self->frontLegAnimator.frameID == self->frontLegAnimator.frameCount - 1)270++self->pullCount;271272if (self->pullCount == 9) {273RSDK.SetSpriteAnimation(Scarab->aniFrames, 0, &self->bodyAnimator, true, 0);274RSDK.SetSpriteAnimation(Scarab->aniFrames, 4, &self->backLegAnimator, true, 0);275RSDK.SetSpriteAnimation(Scarab->aniFrames, 2, &self->frontLegAnimator, true, 0);276self->timer = 45;277self->state = Scarab_State_Wait;278}279280int32 x = self->position.x + 0x6000 * self->moveDir;281int32 y = self->position.y;282283self->position.x = x;284if (abs(x - self->startPos.x) < (self->amplitude << 16) && RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x60000, 2)) {285self->position.x = x;286}287else {288self->position.y = y;289self->position.x = self->startPos.x + (self->amplitude << 16) * self->moveDir;290self->moveDir = -self->moveDir;291}292293RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x60000, 4);294}295296void Scarab_State_Wait(void)297{298RSDK_THIS(Scarab);299300if (self->timer <= 0) {301RSDK.SetSpriteAnimation(Scarab->aniFrames, 1, &self->bodyAnimator, true, 0);302RSDK.SetSpriteAnimation(Scarab->aniFrames, 5, &self->backLegAnimator, true, 0);303RSDK.SetSpriteAnimation(Scarab->aniFrames, 3, &self->frontLegAnimator, true, 0);304305self->pullCount = 0;306self->state = Scarab_State_Move;307}308else {309self->timer--;310}311}312313#if GAME_INCLUDE_EDITOR314void Scarab_EditorDraw(void)315{316RSDK_THIS(Scarab);317318RSDK.SetSpriteAnimation(Scarab->aniFrames, 0, &self->bodyAnimator, true, 0);319RSDK.DrawSprite(&self->bodyAnimator, NULL, false);320321RSDK.SetSpriteAnimation(Scarab->aniFrames, 4, &self->backLegAnimator, true, 0);322RSDK.DrawSprite(&self->backLegAnimator, NULL, false);323324RSDK.SetSpriteAnimation(Scarab->aniFrames, 2, &self->frontLegAnimator, true, 0);325RSDK.DrawSprite(&self->frontLegAnimator, NULL, false);326327if (showGizmos()) {328RSDK_DRAWING_OVERLAY(true);329330for (int32 s = SceneInfo->entitySlot + 1, i = 0; i < self->childCount; ++i) {331Entity *child = RSDK_GET_ENTITY_GEN(s + i);332if (!child)333continue;334335DrawHelpers_DrawArrow(self->position.x, self->position.y, child->position.x, child->position.y, 0xE0E0E0, INK_NONE, 0xFF);336}337338RSDK_DRAWING_OVERLAY(false);339}340}341342void Scarab_EditorLoad(void)343{344Scarab->aniFrames = RSDK.LoadSpriteAnimation("MMZ/Scarab.bin", SCOPE_STAGE);345346RSDK_ACTIVE_VAR(Scarab, planeFilter);347RSDK_ENUM_VAR("None", PLANEFILTER_NONE);348RSDK_ENUM_VAR("AL", PLANEFILTER_AL);349RSDK_ENUM_VAR("BL", PLANEFILTER_BL);350RSDK_ENUM_VAR("AH", PLANEFILTER_AH);351RSDK_ENUM_VAR("BH", PLANEFILTER_BH);352353RSDK_ACTIVE_VAR(Scarab, direction);354RSDK_ENUM_VAR("Left", FLIP_NONE);355RSDK_ENUM_VAR("Right", FLIP_X);356}357#endif358359void Scarab_Serialize(void)360{361RSDK_EDITABLE_VAR(Scarab, VAR_UINT8, direction);362RSDK_EDITABLE_VAR(Scarab, VAR_INT32, amplitude);363RSDK_EDITABLE_VAR(Scarab, VAR_UINT8, childCount);364RSDK_EDITABLE_VAR(Scarab, VAR_ENUM, planeFilter);365}366367368