Path: blob/master/SonicMania/Objects/FBZ/Crane.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Crane Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectCrane *Crane;1011void Crane_Update(void)12{13RSDK_THIS(Crane);1415StateMachine_Run(self->state);1617RSDK.ProcessAnimation(&self->frontAnimator);18RSDK.ProcessAnimation(&self->backAnimator);19}2021void Crane_LateUpdate(void) {}2223void Crane_StaticUpdate(void)24{25foreach_active(Crane, crane) { RSDK.AddDrawListRef(Zone->playerDrawGroup[0] + 1, RSDK.GetEntitySlot(crane)); }26}2728void Crane_Draw(void)29{30RSDK_THIS(Crane);3132if (SceneInfo->currentDrawGroup == self->drawGroup) {33SpriteFrame *frame = RSDK.GetFrame(Crane->aniFrames, 4, 0);34int32 height = (self->position.y - self->startPos.y) >> 16;35frame->sprY = 230 - height;36frame->height = height;37frame->pivotY = -16 - height;38RSDK.DrawSprite(&self->chainAnimator, NULL, false);39RSDK.DrawSprite(&self->backAnimator, NULL, false);40}41else {42RSDK.DrawSprite(&self->frontAnimator, NULL, false);43}44}4546void Crane_Create(void *data)47{48RSDK_THIS(Crane);4950self->visible = true;51self->drawGroup = Zone->objectDrawGroup[0];52self->startPos = self->position;53self->startDir = self->direction;54self->active = ACTIVE_BOUNDS;55self->updateRange.x = 0x800000;56self->updateRange.y = 0x800000;57self->drawFX = FX_FLIP;5859// Frame 3???? that doesn't exist60// Note: it *does* for anim 0 & 1 though, likely where the cause stems from61RSDK.SetSpriteAnimation(Crane->aniFrames, 2, &self->frontAnimator, true, 3);62RSDK.SetSpriteAnimation(Crane->aniFrames, 3, &self->backAnimator, true, 3);63RSDK.SetSpriteAnimation(Crane->aniFrames, 4, &self->chainAnimator, true, 0);64self->state = Crane_State_Init;65}6667void Crane_StageLoad(void)68{69Crane->aniFrames = RSDK.LoadSpriteAnimation("FBZ/Crane.bin", SCOPE_STAGE);7071Crane->hitboxUnused.left = -8;72Crane->hitboxUnused.top = -8;73Crane->hitboxUnused.right = 8;74Crane->hitboxUnused.bottom = 8;7576Crane->hitboxRange.left = -8;77Crane->hitboxRange.top = 0;78Crane->hitboxRange.right = 8;79Crane->hitboxRange.bottom = 128;8081Crane->hitboxGrab.left = -8;82Crane->hitboxGrab.top = 0;83Crane->hitboxGrab.right = 8;84Crane->hitboxGrab.bottom = 16;8586Crane->active = ACTIVE_ALWAYS;8788Crane->sfxGrab = RSDK.GetSfx("Global/Grab.wav");8990DEBUGMODE_ADD_OBJ(Crane);91}9293void Crane_DebugSpawn(void)94{95RSDK_THIS(Crane);9697EntityCrane *crane = CREATE_ENTITY(Crane, NULL, self->position.x, self->position.y);98crane->direction = self->direction;99crane->startDir = self->direction;100}101102void Crane_DebugDraw(void)103{104RSDK.SetSpriteAnimation(Crane->aniFrames, 0, &DebugMode->animator, true, 0);105RSDK.DrawSprite(&DebugMode->animator, NULL, false);106}107108void Crane_HandlePlayerInteractions(void)109{110RSDK_THIS(Crane);111112foreach_active(Player, player)113{114if (!self->grabbedPlayer) {115if ((self->playerType != CRANE_PLAYER1_ONLY || !player->sidekick) && (self->playerType != CRANE_PLAYER2_ONLY || player->sidekick)) {116if (Player_CheckCollisionTouch(player, self, &Crane->hitboxGrab)) {117RSDK.PlaySfx(Crane->sfxGrab, false, 255);118self->state = Crane_State_RiseUp;119self->isPermanent = true;120RSDK.SetSpriteAnimation(Crane->aniFrames, 0, &self->frontAnimator, true, 0);121RSDK.SetSpriteAnimation(Crane->aniFrames, 1, &self->backAnimator, true, 0);122self->grabbedPlayer = player;123player->velocity.x = 0;124player->velocity.y = 0;125player->groundVel = 0;126player->state = Player_State_Static;127player->nextGroundState = StateMachine_None;128player->nextAirState = StateMachine_None;129player->onGround = false;130player->direction = self->direction;131RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, true, 0);132player->animator.speed = 0;133}134}135}136}137}138139void Crane_CheckOffScreen(void)140{141RSDK_THIS(Crane);142143if (!RSDK.CheckOnScreen(self, &self->updateRange)) {144int32 x = self->position.x;145int32 y = self->position.y;146self->position.x = self->startPos.x;147self->position.y = self->startPos.y;148if (RSDK.CheckOnScreen(self, &self->updateRange)) {149self->position.x = x;150self->position.y = y;151}152else {153self->grabbedPlayer = NULL;154self->delay = 0;155self->timer = 0;156self->direction = self->startDir;157self->visible = false;158self->state = Crane_State_CheckOffScreen;159}160}161}162163void Crane_State_CheckOffScreen(void)164{165RSDK_THIS(Crane);166167if (!RSDK.CheckOnScreen(self, &self->updateRange)) {168self->state = Crane_State_Init;169Crane_Create(NULL);170}171}172173void Crane_State_Init(void)174{175RSDK_THIS(Crane);176177self->active = ACTIVE_NORMAL;178if (!self->startType) {179self->state = Crane_State_CheckForPlayers;180Crane_State_CheckForPlayers();181}182else {183self->position.y += 0x400000;184self->timer = -1;185self->state = Crane_State_CheckGrab;186187Crane_HandlePlayerInteractions();188Crane_CheckOffScreen();189}190}191192void Crane_State_CheckForPlayers(void)193{194RSDK_THIS(Crane);195196foreach_active(Player, player)197{198if (Player_CheckCollisionTouch(player, self, &Crane->hitboxRange)) {199self->timer = 32;200self->state = Crane_State_LowerToGrab;201}202}203204Crane_CheckOffScreen();205}206207void Crane_State_LowerToGrab(void)208{209RSDK_THIS(Crane);210211Crane_HandlePlayerInteractions();212Crane_CheckOffScreen();213214--self->timer;215if (self->state == Crane_State_LowerToGrab) {216if (self->timer >= 0)217self->position.y += 0x20000;218else219self->state = Crane_State_CheckGrab;220}221}222223void Crane_State_CheckGrab(void)224{225Crane_HandlePlayerInteractions();226Crane_CheckOffScreen();227}228229void Crane_State_RiseUp(void)230{231RSDK_THIS(Crane);232if (++self->timer < 32) {233self->position.y -= 0x20000;234235EntityPlayer *player = self->grabbedPlayer;236if (player) {237if (Player_CheckValidState(player)) {238player->animator.speed = 0;239player->position.x = self->position.x;240player->position.y = self->position.y;241if (self->direction) {242player->position.x += 0x20000;243player->position.y += 0xE0000;244}245else {246player->position.x -= 0x20000;247player->position.y += 0xE0000;248}249}250else {251self->grabbedPlayer = NULL;252}253}254}255else {256self->delay = 1;257self->timer = 16;258self->velocity.x = 0;259self->state = Crane_State_ToDest1stHalf;260}261262Crane_CheckOffScreen();263}264265void Crane_State_ToDest1stHalf(void)266{267RSDK_THIS(Crane);268269self->velocity.x += 0x1000;270if (self->direction == FLIP_NONE) {271self->position.x += self->velocity.x;272if (self->position.x >= self->startPos.x + (self->distance << 15))273self->state = Crane_State_ToDest2ndHalf;274}275else {276self->position.x -= self->velocity.x;277if (self->position.x <= self->startPos.x - (self->distance << 15))278self->state = Crane_State_ToDest2ndHalf;279}280281EntityPlayer *player = self->grabbedPlayer;282if (player) {283if (Player_CheckValidState(player)) {284player->animator.speed = 0;285player->position.x = self->position.x;286player->position.y = self->position.y;287if (self->direction) {288player->position.x += 0x20000;289player->position.y += 0xE0000;290}291else {292player->position.x -= 0x20000;293player->position.y += 0xE0000;294}295}296else {297self->grabbedPlayer = NULL;298}299}300301Crane_CheckOffScreen();302}303304void Crane_State_ToDest2ndHalf(void)305{306RSDK_THIS(Crane);307308EntityPlayer *player = self->grabbedPlayer;309310self->velocity.x -= 0x1000;311if (self->direction == FLIP_NONE)312self->position.x += self->velocity.x;313else314self->position.x -= self->velocity.x;315316if (self->velocity.x <= 0) {317if (player) {318if (Player_CheckValidState(player))319player->state = Player_State_Air;320else321self->grabbedPlayer = NULL;322}323324RSDK.SetSpriteAnimation(Crane->aniFrames, 2, &self->frontAnimator, true, 0);325RSDK.SetSpriteAnimation(Crane->aniFrames, 3, &self->backAnimator, true, 0);326self->delay = 30;327self->state = Crane_State_DropDelay;328self->isPermanent = false;329}330331if (player) {332if (Player_CheckValidState(player)) {333player->animator.speed = 0;334player->position.x = self->position.x;335player->position.y = self->position.y;336if (self->direction) {337player->position.x += 0x20000;338player->position.y += 0xE0000;339}340else {341player->position.x -= 0x20000;342player->position.y += 0xE0000;343}344}345else {346self->grabbedPlayer = NULL;347}348}349350Crane_CheckOffScreen();351}352353void Crane_State_DropDelay(void)354{355RSDK_THIS(Crane);356357if (--self->delay <= 0)358self->state = Crane_State_ToStart1stHalf;359360Crane_HandlePlayerInteractions();361Crane_CheckOffScreen();362}363364void Crane_State_ToStart1stHalf(void)365{366RSDK_THIS(Crane);367368self->velocity.x -= 0x1000;369if (self->direction) {370self->position.x -= self->velocity.x;371if (self->position.x >= self->startPos.x - (self->distance << 15))372self->state = Crane_State_ToStart2ndHalf;373}374else {375self->position.x += self->velocity.x;376if (self->position.x <= self->startPos.x + (self->distance << 15))377self->state = Crane_State_ToStart2ndHalf;378}379380Crane_CheckOffScreen();381}382383void Crane_State_ToStart2ndHalf(void)384{385RSDK_THIS(Crane);386self->velocity.x += 0x1000;387388if (self->direction)389self->position.x -= self->velocity.x;390else391self->position.x += self->velocity.x;392393if (self->velocity.x >= 0) {394if (self->startType) {395self->timer = 32;396self->state = Crane_State_LowerToGrab;397self->grabbedPlayer = NULL;398}399else {400self->state = Crane_State_CheckForPlayers;401self->grabbedPlayer = NULL;402}403}404405Crane_CheckOffScreen();406}407408#if GAME_INCLUDE_EDITOR409void Crane_EditorDraw(void)410{411RSDK_THIS(Crane);412413RSDK.SetSpriteAnimation(Crane->aniFrames, 2, &self->frontAnimator, true, 2);414RSDK.SetSpriteAnimation(Crane->aniFrames, 3, &self->backAnimator, true, 2);415RSDK.SetSpriteAnimation(Crane->aniFrames, 4, &self->chainAnimator, true, 0);416417Vector2 drawPos = self->position;418if (self->startType)419drawPos.y += 0x400000;420421RSDK.DrawSprite(&self->chainAnimator, &drawPos, false);422RSDK.DrawSprite(&self->backAnimator, &drawPos, false);423RSDK.DrawSprite(&self->frontAnimator, &drawPos, false);424425if (showGizmos()) {426self->inkEffect = INK_BLEND;427428uint8 mode = 0;429self->velocity.x = 0;430while (true) {431switch (mode) {432default: break;433case 0:434self->velocity.x += 0x1000;435if (self->direction == FLIP_NONE) {436drawPos.x += self->velocity.x;437if (drawPos.x >= self->position.x + (self->distance << 15))438mode = 1;439}440else {441drawPos.x -= self->velocity.x;442if (drawPos.x <= self->position.x - (self->distance << 15))443mode = 1;444}445break;446447case 1:448self->velocity.x -= 0x1000;449if (self->direction == FLIP_NONE)450drawPos.x += self->velocity.x;451else452drawPos.x -= self->velocity.x;453454if (self->velocity.x <= 0)455mode = 2;456break;457}458459if (mode > 1)460break;461}462463RSDK.DrawSprite(&self->chainAnimator, &drawPos, false);464RSDK.DrawSprite(&self->backAnimator, &drawPos, false);465RSDK.DrawSprite(&self->frontAnimator, &drawPos, false);466467DrawHelpers_DrawArrow(self->position.x, self->position.y, drawPos.x, drawPos.y, 0x00FF00, INK_NONE, 0xFF);468469self->inkEffect = INK_NONE;470}471}472473void Crane_EditorLoad(void)474{475Crane->aniFrames = RSDK.LoadSpriteAnimation("FBZ/Crane.bin", SCOPE_STAGE);476477RSDK_ACTIVE_VAR(Crane, direction);478RSDK_ENUM_VAR("Right", FLIP_NONE);479RSDK_ENUM_VAR("Left", FLIP_X);480481RSDK_ACTIVE_VAR(Crane, startType);482RSDK_ENUM_VAR("Up", CRANE_START_UP);483RSDK_ENUM_VAR("Down", CRANE_START_DOWN);484485RSDK_ACTIVE_VAR(Crane, playerType);486RSDK_ENUM_VAR("Player Only", CRANE_PLAYER1_ONLY);487RSDK_ENUM_VAR("Sidekick Only", CRANE_PLAYER2_ONLY);488RSDK_ENUM_VAR("Any Player", CRANE_PLAYER_ALL);489}490#endif491492void Crane_Serialize(void)493{494RSDK_EDITABLE_VAR(Crane, VAR_UINT8, direction);495RSDK_EDITABLE_VAR(Crane, VAR_UINT16, distance);496RSDK_EDITABLE_VAR(Crane, VAR_UINT8, startType);497RSDK_EDITABLE_VAR(Crane, VAR_UINT8, playerType);498}499500501