Path: blob/master/SonicMania/Objects/HCZ/HandLauncher.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: HandLauncher Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectHandLauncher *HandLauncher;1011void HandLauncher_Update(void)12{13RSDK_THIS(HandLauncher);1415if (self->handAnimator.animationID == 2 && self->handAnimator.frameID == self->handAnimator.frameCount - 1) // Finished "Hand Grab" Animation16RSDK.SetSpriteAnimation(HandLauncher->aniFrames, 3, &self->handAnimator, true, 0);17else if (self->handAnimator.animationID == 418&& self->handAnimator.frameID == self->handAnimator.frameCount - 1) // Finished "Hand Release" Animation19RSDK.SetSpriteAnimation(HandLauncher->aniFrames, 1, &self->handAnimator, true, 0);2021StateMachine_Run(self->state);2223if (self->grabDelay > 0)24self->grabDelay--;2526RSDK.ProcessAnimation(&self->baseAnimator);27RSDK.ProcessAnimation(&self->handAnimator);28}2930void HandLauncher_LateUpdate(void) {}3132void HandLauncher_StaticUpdate(void)33{34foreach_active(HandLauncher, launcher) { RSDK.AddDrawListRef(Zone->playerDrawGroup[1], RSDK.GetEntitySlot(launcher)); }35}3637void HandLauncher_Draw(void)38{39RSDK_THIS(HandLauncher);4041if (SceneInfo->currentDrawGroup == Zone->playerDrawGroup[1]) {42if (self->state == HandLauncher_State_GrabbedPlayer)43RSDK.DrawSprite(&self->handAnimator, NULL, false);44}45else {46RSDK.DrawSprite(&self->baseAnimator, NULL, false);47if (self->state != HandLauncher_State_GrabbedPlayer)48RSDK.DrawSprite(&self->handAnimator, NULL, false);49}50}5152void HandLauncher_Create(void *data)53{54RSDK_THIS(HandLauncher);5556self->active = ACTIVE_BOUNDS;57self->drawGroup = Zone->objectDrawGroup[0];58self->visible = true;59self->drawFX = FX_FLIP;6061if (!self->speed)62self->speed = 16;6364self->startPos = self->position;65self->updateRange.x = 0x800000;66self->updateRange.y = 0x800000;67self->state = HandLauncher_State_Init;68}6970void HandLauncher_StageLoad(void)71{72HandLauncher->active = ACTIVE_ALWAYS;7374HandLauncher->aniFrames = RSDK.LoadSpriteAnimation("HCZ/HandLauncher.bin", SCOPE_STAGE);7576// only the cheat code was removed from HCZ/HandPulley, the actual code for dunkey mode still remains in-tact77HandLauncher->sfxDunkey = RSDK.GetSfx("HCZ/Dunkey.wav");7879HandLauncher->hitboxRange.left = -24;80HandLauncher->hitboxRange.top = -240;81HandLauncher->hitboxRange.right = 24;82HandLauncher->hitboxRange.bottom = 0;8384HandLauncher->hitboxGrab.left = -4;85HandLauncher->hitboxGrab.top = -54;86HandLauncher->hitboxGrab.right = 4;87HandLauncher->hitboxGrab.bottom = 0;8889// No idea what ths was for tbh90HandLauncher->hitboxUnused.left = -32;91HandLauncher->hitboxUnused.top = 0;92HandLauncher->hitboxUnused.right = 32;93HandLauncher->hitboxUnused.bottom = 24;94}9596void HandLauncher_CheckPlayerCollisions(void)97{98RSDK_THIS(HandLauncher);99100if (self->grabDelay <= 0) {101foreach_active(Player, player)102{103int32 playerID = RSDK.GetEntitySlot(player);104105if ((self->state == HandLauncher_State_GrabbedPlayer || !player->sidekick) && !((1 << playerID) & self->activePlayers)) {106if (player->onGround) {107if (Player_CheckCollisionTouch(player, self, &HandLauncher->hitboxGrab)) {108self->activePlayers |= 1 << playerID;109player->groundVel = 0;110if (self->state != HandLauncher_State_GrabbedPlayer) {111if (HandLauncher->dunkeyMode)112RSDK.PlaySfx(HandLauncher->sfxDunkey, false, 0xFF);113else114RSDK.PlaySfx(Player->sfxRoll, false, 0xFF);115}116117if (!HandLauncher->dunkeyMode)118RSDK.PlaySfx(Player->sfxGrab, false, 0xFF);119120RSDK.SetSpriteAnimation(player->aniFrames, ANI_RUN, &player->animator, false, 0);121player->nextGroundState = StateMachine_None;122player->nextAirState = StateMachine_None;123player->rotation = 0;124player->state = Player_State_Static;125}126}127}128}129}130}131132bool32 HandLauncher_CheckPlayerInRange(void)133{134RSDK_THIS(HandLauncher);135136if (self->activePlayers)137return true;138139int32 storeX = self->position.x;140int32 storeY = self->position.y;141self->position = self->playerPos;142143bool32 inRange = false;144foreach_active(Player, player)145{146if (Player_CheckCollisionTouch(player, self, &HandLauncher->hitboxRange)) {147inRange = true;148foreach_break;149}150}151152self->position.x = storeX;153self->position.y = storeY;154return inRange;155}156157void HandLauncher_ReleasePlayers(void)158{159RSDK_THIS(HandLauncher);160161int32 releaseVel = self->speed * (2 * (self->direction == FLIP_NONE) - 1);162163foreach_active(Player, player)164{165int32 playerID = RSDK.GetEntitySlot(player);166167if (((1 << playerID) & self->activePlayers)) {168self->activePlayers &= ~(1 << playerID);169player->onGround = true;170player->groundVel = releaseVel << 16;171player->state = Player_State_Ground;172}173}174}175176void HandLauncher_HandleGrabbedPlayers(void)177{178RSDK_THIS(HandLauncher);179180foreach_active(Player, player)181{182int32 playerID = RSDK.GetEntitySlot(player);183if (((1 << playerID) & self->activePlayers)) {184player->velocity.x = 0;185player->velocity.y = 0;186player->direction = self->direction != FLIP_NONE;187player->position.x = self->position.x;188player->position.y = self->position.y - 0x140000;189if (self->playerPos.y - 0x140000 < player->position.y)190player->position.y -= 0x140000;191}192}193}194195void HandLauncher_State_Init(void)196{197RSDK_THIS(HandLauncher);198199self->hiddenPos = self->startPos;200self->hiddenPos.y += 0x4E0000;201202self->playerPos = self->hiddenPos;203self->playerPos.y -= 0x360000;204205self->position = self->hiddenPos;206207RSDK.SetSpriteAnimation(HandLauncher->aniFrames, 0, &self->baseAnimator, true, 0);208self->baseAnimator.speed = 0;209RSDK.SetSpriteAnimation(HandLauncher->aniFrames, 1, &self->handAnimator, true, 0);210211self->state = HandLauncher_State_AwaitPlayer;212}213214void HandLauncher_State_AwaitPlayer(void)215{216RSDK_THIS(HandLauncher);217218// Out of range, lower "Hand Position" to hide it219self->position = self->hiddenPos;220self->position.y -= ((self->hiddenPos.y - self->playerPos.y) >> 3) * MIN(self->timer, 8);221222if (self->timer > 0)223self->timer--;224225if (self->timer < 0)226self->timer = 0;227228if (HandLauncher_CheckPlayerInRange())229self->state = HandLauncher_State_TryGrabPlayer;230}231232void HandLauncher_State_TryGrabPlayer(void)233{234RSDK_THIS(HandLauncher);235236// In Range, raise "Hand Position" to show it237self->position = self->hiddenPos;238self->position.y -= ((self->hiddenPos.y - self->playerPos.y) >> 3) * MIN(self->timer, 8);239240if (self->timer < 8)241self->timer++;242243if (self->timer > 8)244self->timer = 8;245246HandLauncher_CheckPlayerCollisions();247248if (self->activePlayers) {249RSDK.SetSpriteAnimation(HandLauncher->aniFrames, 2, &self->handAnimator, true, 0);250self->timer = 0;251self->baseAnimator.speed = 1;252self->state = HandLauncher_State_GrabbedPlayer;253}254255HandLauncher_HandleGrabbedPlayers();256257if (!HandLauncher_CheckPlayerInRange())258self->state = HandLauncher_State_AwaitPlayer;259}260261void HandLauncher_State_GrabbedPlayer(void)262{263RSDK_THIS(HandLauncher);264265if (self->timer < 3) {266self->position = self->playerPos;267268int32 dist = (self->playerPos.y - self->startPos.y) / 3;269if (self->timer <= 3)270self->position.y -= dist * self->timer;271else272self->position.y -= dist * 3;273}274else {275if (self->timer < 63) {276self->position = self->startPos;277}278else if (self->timer < 66) {279self->position = self->playerPos;280int32 dist = (self->playerPos.y - self->startPos.y) / 3;281self->position.y -= dist * MIN(66 - self->timer, 3);282}283else {284HandLauncher_ReleasePlayers();285if (!HandLauncher->dunkeyMode)286RSDK.PlaySfx(Player->sfxRelease, false, 0xFF);287288RSDK.SetSpriteAnimation(HandLauncher->aniFrames, 4, &self->handAnimator, true, 0);289self->position = self->playerPos;290self->grabDelay = 30;291self->timer = 0;292self->baseAnimator.speed = 0;293self->state = HandLauncher_State_AwaitPlayer;294}295}296297if (self->state == HandLauncher_State_GrabbedPlayer)298self->timer++;299300HandLauncher_CheckPlayerCollisions();301HandLauncher_HandleGrabbedPlayers();302}303304#if GAME_INCLUDE_EDITOR305void HandLauncher_EditorDraw(void)306{307RSDK_THIS(HandLauncher);308309RSDK.SetSpriteAnimation(HandLauncher->aniFrames, 0, &self->baseAnimator, true, 0);310RSDK.SetSpriteAnimation(HandLauncher->aniFrames, 1, &self->handAnimator, true, 0);311312RSDK.DrawSprite(&self->baseAnimator, NULL, false);313RSDK.DrawSprite(&self->handAnimator, NULL, false);314315if (showGizmos()) {316self->hiddenPos = self->position;317self->hiddenPos.y += 0x4E0000;318self->inkEffect = INK_BLEND;319320RSDK.DrawSprite(&self->baseAnimator, &self->hiddenPos, false);321RSDK.DrawSprite(&self->handAnimator, &self->hiddenPos, false);322323self->inkEffect = INK_NONE;324}325}326327void HandLauncher_EditorLoad(void)328{329HandLauncher->aniFrames = RSDK.LoadSpriteAnimation("HCZ/HandLauncher.bin", SCOPE_STAGE);330331RSDK_ACTIVE_VAR(HandLauncher, direction);332RSDK_ENUM_VAR("Right", FLIP_NONE);333RSDK_ENUM_VAR("Left", FLIP_X);334}335#endif336337void HandLauncher_Serialize(void)338{339RSDK_EDITABLE_VAR(HandLauncher, VAR_UINT8, direction);340RSDK_EDITABLE_VAR(HandLauncher, VAR_UINT32, speed);341}342343344