Path: blob/master/SonicMania/Objects/HCZ/MegaChopper.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: MegaChopper Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectMegaChopper *MegaChopper;1011void MegaChopper_Update(void)12{13RSDK_THIS(MegaChopper);1415StateMachine_Run(self->state);16}1718void MegaChopper_LateUpdate(void) {}1920void MegaChopper_StaticUpdate(void) {}2122void MegaChopper_Draw(void)23{24RSDK_THIS(MegaChopper);2526RSDK.DrawSprite(&self->animator, NULL, false);27}2829void MegaChopper_Create(void *data)30{31RSDK_THIS(MegaChopper);3233self->visible = true;34self->drawFX |= FX_FLIP;35self->drawGroup = Zone->playerDrawGroup[0] + 1;36self->startPos = self->position;37self->active = ACTIVE_BOUNDS;38self->updateRange.x = 0x800000;39self->updateRange.y = 0x800000;4041RSDK.SetSpriteAnimation(MegaChopper->aniFrames, 0, &self->animator, true, 0);42self->state = MegaChopper_State_Init;43}4445void MegaChopper_StageLoad(void)46{47if (RSDK.CheckSceneFolder("HCZ"))48MegaChopper->aniFrames = RSDK.LoadSpriteAnimation("HCZ/MegaChopper.bin", SCOPE_STAGE);4950MegaChopper->hitboxBadnik.left = -8;51MegaChopper->hitboxBadnik.top = -12;52MegaChopper->hitboxBadnik.right = 2;53MegaChopper->hitboxBadnik.bottom = 12;5455MegaChopper->hitboxChop.left = -1;56MegaChopper->hitboxChop.top = -1;57MegaChopper->hitboxChop.right = 1;58MegaChopper->hitboxChop.bottom = 1;5960DEBUGMODE_ADD_OBJ(MegaChopper);61}6263void MegaChopper_DebugSpawn(void)64{65RSDK_THIS(DebugMode);6667CREATE_ENTITY(MegaChopper, NULL, self->position.x, self->position.y);68}6970void MegaChopper_DebugDraw(void)71{72RSDK.SetSpriteAnimation(MegaChopper->aniFrames, 0, &DebugMode->animator, true, 0);73RSDK.DrawSprite(&DebugMode->animator, NULL, false);74}7576void MegaChopper_CheckPlayerCollisions(void)77{78RSDK_THIS(MegaChopper);7980foreach_active(Player, player)81{82if (Player_CheckBadnikTouch(player, self, &MegaChopper->hitboxBadnik)) {83int32 blink = player->blinkTimer;8485player->blinkTimer = 1;86if (!Player_CheckBadnikBreak(player, self, true) && Player_CheckCollisionTouch(player, self, &MegaChopper->hitboxChop)) {87self->grabbedPlayer = player;88self->playerPos.x = (self->position.x - player->position.x) & 0xFFFF0000;89self->playerPos.y = (self->position.y - player->position.y) & 0xFFFF0000;90self->playerDir = player->direction;9192if (player->stateInput == Player_Input_P1)93player->stateInput = MegaChopper_Input_GrabbedP1;94else if (player->stateInput == Player_Input_P2_Player)95player->stateInput = MegaChopper_Input_GrabbedP2;96else if (player->stateInput == Player_Input_P2_AI)97player->stateInput = MegaChopper_Input_GrabbedP2_AI;9899self->drawGroup = player->drawGroup + 1;100self->isPermanent = true;101self->state = MegaChopper_State_Chopping;102}103player->blinkTimer = blink;104foreach_break;105}106}107}108109void MegaChopper_CheckOffScreen(void)110{111RSDK_THIS(MegaChopper);112113if (!RSDK.CheckOnScreen(self, NULL) && RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange) == false) {114self->position = self->startPos;115116EntityPlayer *player = self->grabbedPlayer;117if (player) {118if (player->stateInput == MegaChopper_Input_GrabbedP1)119player->stateInput = Player_Input_P1;120else if (player->stateInput == MegaChopper_Input_GrabbedP2)121player->stateInput = Player_Input_P2_Player;122else if (player->stateInput == MegaChopper_Input_GrabbedP2_AI)123player->stateInput = Player_Input_P2_AI;124}125126self->nibbleTimer = 0;127self->isPermanent = false;128129MegaChopper_Create(NULL);130}131}132133void MegaChopper_Input_GrabbedP1(void)134{135RSDK_THIS(Player);136137Player_Input_P1();138139if (self->state != Player_State_Static) {140self->up = false;141self->down = false;142self->jumpPress = false;143self->jumpHold = false;144}145}146147void MegaChopper_Input_GrabbedP2(void)148{149RSDK_THIS(Player);150151Player_Input_P2_Player();152153self->up = false;154self->down = false;155self->jumpPress = false;156self->jumpHold = false;157158if (self->stateInput == Player_Input_P2_AI)159self->stateInput = MegaChopper_Input_GrabbedP2_AI;160}161162void MegaChopper_Input_GrabbedP2_AI(void)163{164RSDK_THIS(Player);165166Player_Input_P2_AI();167168self->up = false;169self->down = false;170self->jumpPress = false;171self->jumpHold = false;172173if (self->stateInput == Player_Input_P2_Player)174self->stateInput = MegaChopper_Input_GrabbedP2;175}176177void MegaChopper_State_Init(void)178{179RSDK_THIS(MegaChopper);180181if (self->position.y >= Water->waterLevel) {182self->active = ACTIVE_NORMAL;183self->velocity.x = -0x10000;184185self->state = MegaChopper_State_InWater;186MegaChopper_State_InWater();187}188else {189destroyEntity(self);190}191}192193void MegaChopper_State_InWater(void)194{195RSDK_THIS(MegaChopper);196197if (++self->animator.frameID == 6)198self->animator.frameID = 0;199200if (self->animator.frameID == 12)201self->animator.frameID = 6;202203EntityPlayer *player = Player_GetNearestPlayer();204if (self->position.x >= player->position.x) {205self->velocity.x -= 0x800;206207if (self->velocity.x < -0x20000)208self->velocity.x = -0x20000;209}210else {211self->velocity.x += 0x800;212213if (self->velocity.x > 0x20000)214self->velocity.x = 0x20000;215}216217self->position.y += self->position.y < player->position.y ? 0x2000 : -0x2000;218219self->direction = self->velocity.x > 0;220if (self->velocity.y > 0) {221self->velocity.y -= 0x3800;222223if (self->velocity.y < 0)224self->velocity.y = 0;225}226227self->position.x += self->velocity.x;228self->position.y += self->velocity.y;229230if (self->position.y < Water->waterLevel) {231bool32 inWater = false;232foreach_active(Water, water)233{234if (water->type == WATER_POOL && RSDK.CheckObjectCollisionTouchBox(water, &water->hitbox, self, &Water->hitboxPoint)) {235inWater = true;236}237}238239if (!inWater) {240self->velocity.x = self->direction == FLIP_NONE ? -0x20000 : 0x20000;241self->velocity.y = -0x40000;242self->state = MegaChopper_State_OutOfWater;243}244}245246MegaChopper_CheckPlayerCollisions();247MegaChopper_CheckOffScreen();248}249250void MegaChopper_State_OutOfWater(void)251{252RSDK_THIS(MegaChopper);253254if (++self->animator.frameID == 6)255self->animator.frameID = 0;256257if (self->animator.frameID == 12)258self->animator.frameID = 6;259260self->position.x += self->velocity.x;261self->position.y += self->velocity.y;262self->velocity.y += 0x1800;263264if (self->position.y >= Water->waterLevel) {265self->state = MegaChopper_State_InWater;266}267else {268foreach_active(Water, water)269{270if (water->type == WATER_POOL && RSDK.CheckObjectCollisionTouchBox(water, &water->hitbox, self, &Water->hitboxPoint)) {271self->state = MegaChopper_State_InWater;272}273}274}275276MegaChopper_CheckPlayerCollisions();277MegaChopper_CheckOffScreen();278}279280void MegaChopper_State_Chopping(void)281{282RSDK_THIS(MegaChopper);283284if (++self->animator.timer == 3) {285self->animator.timer = 0;286self->animator.frameID = (self->animator.frameID + 6) % 12;287}288289EntityPlayer *player = self->grabbedPlayer;290291if (!player) {292self->velocity.x = self->direction == FLIP_NONE ? 0x20000 : -0x20000;293self->velocity.y = -0x40000;294self->state = MegaChopper_State_ShakenOff;295}296else {297if (player->animator.animationID == ANI_JUMP) {298self->grabbedPlayer = NULL;299300if (player->stateInput == MegaChopper_Input_GrabbedP1)301player->stateInput = Player_Input_P1;302else if (player->stateInput == MegaChopper_Input_GrabbedP2)303player->stateInput = Player_Input_P2_Player;304else if (player->stateInput == MegaChopper_Input_GrabbedP2_AI)305player->stateInput = Player_Input_P2_AI;306307self->velocity.x = self->direction == FLIP_NONE ? 0x20000 : -0x20000;308self->velocity.y = -0x40000;309self->state = MegaChopper_State_ShakenOff;310}311else {312if (++self->nibbleTimer >= 60) {313self->nibbleTimer = 0;314315if (!player->rings || player->sidekick) {316Player_Hit(player);317player->velocity.x = player->position.x > self->position.x ? 0x20000 : -0x20000;318self->grabbedPlayer = NULL;319}320else {321player->rings--;322if (Ring->pan) {323int32 channel = RSDK.PlaySfx(Ring->sfxRing, false, 255);324RSDK.SetChannelAttributes(channel, 1.0, -1.0, 1.0);325Ring->pan = 0;326}327else {328int32 channel = RSDK.PlaySfx(Ring->sfxRing, false, 255);329RSDK.SetChannelAttributes(channel, 1.0, 1.0, 1.0);330Ring->pan = 1;331}332}333}334335if (self->grabbedPlayer) {336self->position.x = player->position.x + self->playerPos.x;337self->position.y = player->position.y + self->playerPos.y;338339if (player->direction != self->playerDir) {340self->direction ^= FLIP_X;341self->playerDir = player->direction;342}343344self->playerDir = player->direction;345if (self->lastShakeFlags) {346if (!self->shakeTimer) {347self->shakeCount = 0;348self->lastShakeFlags = 0;349}350else {351self->shakeTimer--;352353uint8 shakeFlags = 0;354if (player->left)355shakeFlags = 1;356if (player->right)357shakeFlags |= 2;358359if (shakeFlags) {360if (shakeFlags != 3 && shakeFlags != self->lastShakeFlags) {361self->lastShakeFlags = shakeFlags;362if (++self->shakeCount >= 6) {363self->grabbedPlayer = NULL;364365if (player->stateInput == MegaChopper_Input_GrabbedP1)366player->stateInput = Player_Input_P1;367else if (player->stateInput == MegaChopper_Input_GrabbedP2)368player->stateInput = Player_Input_P2_Player;369else if (player->stateInput == MegaChopper_Input_GrabbedP2_AI)370player->stateInput = Player_Input_P2_AI;371372self->velocity.x = self->direction == FLIP_NONE ? 0x20000 : -0x20000;373self->velocity.y = -0x40000;374self->state = MegaChopper_State_ShakenOff;375}376}377}378}379}380else if (player->left) {381self->lastShakeFlags = 1;382self->shakeTimer = 64;383}384else if (player->right) {385self->lastShakeFlags = 2;386self->shakeTimer = 64;387}388}389else {390if (player->stateInput == MegaChopper_Input_GrabbedP1)391player->stateInput = Player_Input_P1;392else if (player->stateInput == MegaChopper_Input_GrabbedP2)393player->stateInput = Player_Input_P2_Player;394else if (player->stateInput == MegaChopper_Input_GrabbedP2_AI)395player->stateInput = Player_Input_P2_AI;396397self->velocity.x = self->direction == FLIP_NONE ? 0x20000 : -0x20000;398self->velocity.y = -0x40000;399self->state = MegaChopper_State_ShakenOff;400}401}402}403404MegaChopper_CheckOffScreen();405}406407void MegaChopper_State_ShakenOff(void)408{409RSDK_THIS(MegaChopper);410411self->position.x += self->velocity.x;412self->position.y += self->velocity.y;413self->velocity.y += 0x3800;414415MegaChopper_CheckOffScreen();416}417418#if GAME_INCLUDE_EDITOR419void MegaChopper_EditorDraw(void) { MegaChopper_Draw(); }420421void MegaChopper_EditorLoad(void) { MegaChopper->aniFrames = RSDK.LoadSpriteAnimation("HCZ/MegaChopper.bin", SCOPE_STAGE); }422#endif423424void MegaChopper_Serialize(void) {}425426427