Path: blob/master/SonicMania/Objects/GHZ/Chopper.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Chopper Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectChopper *Chopper;1011void Chopper_Update(void)12{13RSDK_THIS(Chopper);14StateMachine_Run(self->state);15}1617void Chopper_LateUpdate(void) {}1819void Chopper_StaticUpdate(void) {}2021void Chopper_Draw(void)22{23RSDK_THIS(Chopper);24RSDK.DrawSprite(&self->animator, NULL, false);25}2627void Chopper_Create(void *data)28{29RSDK_THIS(Chopper);30self->visible = true;31self->drawGroup = Zone->objectDrawGroup[0];32self->startPos = self->position;33self->startDir = self->direction;34self->active = ACTIVE_BOUNDS;35self->updateRange.x = 0x800000;36self->updateRange.y = 0x1200000;37self->drawFX = FX_FLIP;38self->state = Chopper_State_Init;39}4041void Chopper_StageLoad(void)42{43if (RSDK.CheckSceneFolder("GHZ"))44Chopper->aniFrames = RSDK.LoadSpriteAnimation("GHZ/Chopper.bin", SCOPE_STAGE);4546Chopper->hitboxJump.left = -10;47Chopper->hitboxJump.top = -20;48Chopper->hitboxJump.right = 6;49Chopper->hitboxJump.bottom = 20;5051Chopper->hitboxSwim.left = -20;52Chopper->hitboxSwim.top = -6;53Chopper->hitboxSwim.right = 20;54Chopper->hitboxSwim.bottom = 10;5556Chopper->hitboxRange.left = -160;57Chopper->hitboxRange.top = -32;58Chopper->hitboxRange.right = 16;59Chopper->hitboxRange.bottom = 32;6061Chopper->hitboxWater.left = -20;62Chopper->hitboxWater.top = -24;63Chopper->hitboxWater.right = 20;64Chopper->hitboxWater.bottom = -16;6566DEBUGMODE_ADD_OBJ(Chopper);67}68void Chopper_DebugDraw(void)69{70RSDK.SetSpriteAnimation(Chopper->aniFrames, 0, &DebugMode->animator, true, 0);71RSDK.DrawSprite(&DebugMode->animator, NULL, false);72}7374void Chopper_DebugSpawn(void)75{76RSDK_THIS(DebugMode);7778CREATE_ENTITY(Chopper, NULL, self->position.x, self->position.y);79}8081void Chopper_CheckOffScreen(void)82{83RSDK_THIS(Chopper);8485if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {86self->position.x = self->startPos.x;87self->position.y = self->startPos.y;88self->direction = self->startDir;89Chopper_Create(NULL);90}91}9293void Chopper_CheckPlayerCollisions_Jump(void)94{95RSDK_THIS(Chopper);9697foreach_active(Player, player)98{99if (Player_CheckBadnikTouch(player, self, &Chopper->hitboxJump))100Player_CheckBadnikBreak(player, self, true);101}102}103104void Chopper_CheckPlayerCollisions_Swim(void)105{106RSDK_THIS(Chopper);107108foreach_active(Player, player)109{110if (Player_CheckBadnikTouch(player, self, &Chopper->hitboxSwim))111Player_CheckBadnikBreak(player, self, true);112}113}114115void Chopper_State_Init(void)116{117RSDK_THIS(Chopper);118119self->active = ACTIVE_NORMAL;120self->velocity.x = -0x10000;121122if (self->type == CHOPPER_JUMP) {123RSDK.SetSpriteAnimation(Chopper->aniFrames, 0, &self->animator, true, 0);124self->state = Chopper_State_Jump;125Chopper_State_Jump();126}127else {128RSDK.SetSpriteAnimation(Chopper->aniFrames, 1, &self->animator, true, 0);129self->state = Chopper_State_Swim;130self->timer = 512;131132if (!self->direction)133self->velocity.x = -0x4000;134else135self->velocity.x = 0x4000;136Chopper_State_Swim();137}138}139140void Chopper_State_Jump(void)141{142RSDK_THIS(Chopper);143144self->position.y += self->velocity.y;145self->velocity.y += 0x1800;146147if (self->velocity.y < -0x38000) {148self->animator.speed = 1;149}150else {151if (self->velocity.y > 0x38000) {152self->animator.frameID = 0;153self->animator.speed = 0;154}155else {156self->animator.speed = 2;157}158}159160if (self->position.y > self->startPos.y) {161self->position.y = self->startPos.y;162self->velocity.y = -0x70000;163}164165RSDK.ProcessAnimation(&self->animator);166167Chopper_CheckPlayerCollisions_Jump();168Chopper_CheckOffScreen();169}170171void Chopper_State_Swim(void)172{173RSDK_THIS(Chopper);174175self->position.x += self->velocity.x;176177bool32 hitWall = false;178if (self->direction) {179hitWall = RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_LWALL, 0, 0x100000, 0, true);180hitWall |= RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_LWALL, 0, 0x100000, -0xF0000, true);181hitWall |= RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_LWALL, 0, 0x100000, 0xF0000, true);182}183else {184hitWall = RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_RWALL, 0, -0x100000, 0, true);185hitWall |= RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_RWALL, 0, -0x100000, -0xF0000, true);186hitWall |= RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_RWALL, 0, -0x100000, 0xF0000, true);187}188189if (--self->timer <= 0 || hitWall) {190self->direction ^= FLIP_X;191self->velocity.x = -self->velocity.x;192self->timer = 512;193}194195if (self->charge) {196foreach_active(Player, player)197{198if (Player_CheckCollisionTouch(player, self, &Chopper->hitboxRange)) {199self->state = Chopper_State_ChargeDelay;200RSDK.SetSpriteAnimation(Chopper->aniFrames, 2, &self->animator, false, 0);201self->timer = 16;202if (!self->direction)203self->velocity.x = -0x20000;204else205self->velocity.x = 0x20000;206207if (abs(player->position.y - self->position.y) > 0x100000) {208if (player->position.y < self->position.y)209self->velocity.y = -0x8000;210else211self->velocity.y = 0x8000;212}213}214}215}216217RSDK.ProcessAnimation(&self->animator);218219Chopper_CheckPlayerCollisions_Swim();220Chopper_CheckOffScreen();221}222223void Chopper_State_ChargeDelay(void)224{225RSDK_THIS(Chopper);226227if (!self->timer)228self->state = Chopper_State_Charge;229else230--self->timer;231232RSDK.ProcessAnimation(&self->animator);233Chopper_CheckPlayerCollisions_Swim();234Chopper_CheckOffScreen();235}236237void Chopper_State_Charge(void)238{239RSDK_THIS(Chopper);240self->position.x += self->velocity.x;241self->position.y += self->velocity.y;242243bool32 hitWall = false;244if (self->direction) {245hitWall = RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_LWALL, 0, 0x100000, 0, true);246hitWall |= RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_LWALL, 0, 0x100000, -0xF0000, true);247hitWall |= RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_LWALL, 0, 0x100000, 0xF0000, true);248}249else {250hitWall = RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_RWALL, 0, -0x100000, 0, true);251hitWall |= RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_RWALL, 0, -0x100000, -0xF0000, true);252hitWall |= RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_RWALL, 0, -0x100000, 0xF0000, true);253}254255if (hitWall) {256RSDK.SetSpriteAnimation(Chopper->aniFrames, 1, &self->animator, false, 0);257self->timer = 512;258self->velocity.y = 0;259if (self->direction == FLIP_X)260self->velocity.x = -0x4000;261else262self->velocity.x = 0x4000;263self->direction ^= FLIP_X;264self->state = Chopper_State_Swim;265266hitWall = false;267}268else if (self->velocity.y >= 0) {269if (self->velocity.y > 0)270hitWall = RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x100000, true);271}272else {273hitWall = RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_ROOF, 0, 0, -0x100000, true);274foreach_active(Water, water)275{276if (water->type == WATER_POOL)277hitWall |= !RSDK.CheckObjectCollisionTouchBox(water, &water->hitbox, self, &Chopper->hitboxWater);278}279}280281if (hitWall) {282RSDK.SetSpriteAnimation(Chopper->aniFrames, 1, &self->animator, false, 0);283self->timer = 512;284self->velocity.y = 0;285if (self->direction == FLIP_NONE)286self->velocity.x = -0x4000;287else288self->velocity.x = 0x4000;289self->state = Chopper_State_Swim;290}291292RSDK.ProcessAnimation(&self->animator);293Chopper_CheckPlayerCollisions_Swim();294Chopper_CheckOffScreen();295}296297#if GAME_INCLUDE_EDITOR298void Chopper_EditorDraw(void)299{300RSDK_THIS(Chopper);301if (self->type == CHOPPER_JUMP)302RSDK.SetSpriteAnimation(Chopper->aniFrames, 0, &self->animator, true, 0);303else304RSDK.SetSpriteAnimation(Chopper->aniFrames, 1, &self->animator, true, 0);305306Chopper_Draw();307}308309void Chopper_EditorLoad(void)310{311Chopper->aniFrames = RSDK.LoadSpriteAnimation("GHZ/Chopper.bin", SCOPE_STAGE);312313RSDK_ACTIVE_VAR(Chopper, type);314RSDK_ENUM_VAR("Jump", CHOPPER_JUMP);315RSDK_ENUM_VAR("Swim", CHOPPER_SWIM);316317// Only used with "Swim" type, "Jump" type ignores it318RSDK_ACTIVE_VAR(Chopper, direction);319RSDK_ENUM_VAR("Left", FLIP_NONE);320RSDK_ENUM_VAR("Right", FLIP_X);321}322#endif323324void Chopper_Serialize(void)325{326RSDK_EDITABLE_VAR(Chopper, VAR_UINT8, type);327RSDK_EDITABLE_VAR(Chopper, VAR_UINT8, direction);328RSDK_EDITABLE_VAR(Chopper, VAR_BOOL, charge);329}330331332