Path: blob/master/SonicMania/Objects/HCZ/Current.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Current Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectCurrent *Current;1011void Current_Update(void)12{13RSDK_THIS(Current);1415EntityButton *button = self->taggedButton;16if (!button || button->activated) {17self->activated = true;18StateMachine_Run(self->state);19}20}2122void Current_LateUpdate(void) {}2324void Current_StaticUpdate(void)25{26if (Water) {27int32 offsetH = 0;28int32 offsetV = 0;2930foreach_active(Water, water)31{32if (water->state == Water_State_BigBubble && water->activePlayers) {33foreach_active(Current, current)34{35if (current->planeFilter <= 0 || water->collisionPlane == ((uint8)(current->planeFilter - 1) & 1)) {36int32 strength = current->strength << 15;37if (MathHelpers_PointInHitbox(current->position.x, current->position.y, water->position.x, water->position.y,38current->direction, ¤t->hitbox)) {39if (current->state == Current_State_WaterUp)40offsetV -= strength;4142if (current->state == Current_State_WaterDown)43offsetV += strength;4445if (current->state == Current_State_WaterLeft)46offsetH -= strength;4748if (current->state == Current_State_WaterRight)49offsetH += strength;50}51}52}5354if (water->bubbleVelocity.x < offsetH) {55water->bubbleVelocity.x += 0x6000;5657if (water->bubbleVelocity.x > offsetH)58water->bubbleVelocity.x = offsetH;59}6061if (water->bubbleVelocity.x > offsetH) {62water->bubbleVelocity.x -= 0x6000;6364if (water->bubbleVelocity.x < offsetH)65water->bubbleVelocity.x = offsetH;66}6768if (water->bubbleVelocity.y < offsetV) {69water->bubbleVelocity.y += 0x6000;7071if (water->bubbleVelocity.y > offsetV)72water->bubbleVelocity.y = offsetV;73}7475if (water->bubbleVelocity.y > offsetV) {76water->bubbleVelocity.y -= 0x6000;7778if (water->bubbleVelocity.y < offsetV)79water->bubbleVelocity.y = offsetV;80}81}82}83}8485foreach_active(Player, player)86{87int32 playerID = RSDK.GetEntitySlot(player);8889bool32 active = false;90foreach_active(Current, current)91{92if (current->activated) {93if (current->type < CURRENT_W_LEFT) {94if ((current->planeFilter <= 0 || player->collisionPlane == ((uint8)(current->planeFilter - 1) & 1))95&& (!current->waterOnly || player->underwater)) {96if (Player_CheckCollisionTouch(player, current, ¤t->hitbox)) {97Current->activePlayers |= 1 << playerID;98active = true;99foreach_break;100}101}102}103}104}105106if (!active)107Current->activePlayers &= ~(1 << playerID);108}109}110111void Current_Draw(void)112{113RSDK_THIS(Current);114115RSDK.DrawSprite(&self->animator, NULL, false);116}117118void Current_Create(void *data)119{120RSDK_THIS(Current);121122self->drawFX = FX_FLIP;123if (!SceneInfo->inEditor) {124if (data) {125self->active = ACTIVE_NORMAL;126self->inkEffect = INK_ADD;127self->visible = true;128self->updateRange.x = TO_FIXED(512);129self->updateRange.y = TO_FIXED(256);130131if (VOID_TO_INT(data) == CURRENT_CHILD_WIND) {132self->drawFX = FX_SCALE | FX_FLIP;133self->scale.x = 0x400;134self->scale.y = 0x100;135RSDK.SetSpriteAnimation(Current->aniFrames, 1, &self->animator, true, ZONE_RAND(0, 4));136}137else {138RSDK.SetSpriteAnimation(Water->aniFrames, 5, &self->animator, true, 0);139self->alpha = 0x200;140}141142self->state = Current_State_Child;143}144else {145self->visible = false;146self->updateRange.x = self->size.x >> 1;147self->updateRange.y = self->size.y >> 1;148self->active = ACTIVE_BOUNDS;149150self->hitbox.left = -(self->size.x >> 17);151self->hitbox.right = self->size.x >> 17;152self->hitbox.top = -(self->size.y >> 17);153self->hitbox.bottom = self->size.y >> 17;154155Current_SetupTagLink();156switch (self->type) {157case CURRENT_C_LEFT: self->state = Current_State_WaterLeft; break;158case CURRENT_C_RIGHT: self->state = Current_State_WaterRight; break;159case CURRENT_C_UP: self->state = Current_State_WaterUp; break;160case CURRENT_C_DOWN: self->state = Current_State_WaterDown; break;161case CURRENT_W_LEFT: self->state = Current_State_PushLeft; break;162case CURRENT_W_RIGHT: self->state = Current_State_PushRight; break;163case CURRENT_W_UP: self->state = Current_State_PushUp; break;164case CURRENT_W_DOWN: self->state = Current_State_PushDown; break;165default: break;166}167}168}169}170171void Current_StageLoad(void)172{173if (RSDK.CheckSceneFolder("FBZ"))174Current->aniFrames = RSDK.LoadSpriteAnimation("FBZ/Current.bin", SCOPE_STAGE);175else176Current->aniFrames = RSDK.LoadSpriteAnimation("Global/TicMark.bin", SCOPE_STAGE);177178RSDK.SetSpriteAnimation(Current->aniFrames, 0, &Current->animator, true, 0);179180Current->sfxRush = RSDK.GetSfx("Stage/Rush.wav");181}182183void Current_SetupTagLink(void)184{185RSDK_THIS(Current);186187self->taggedButton = NULL;188EntityButton *taggedButton = RSDK_GET_ENTITY(RSDK.GetEntitySlot(self) - 1, Button);189190if (self->buttonTag > 0) {191bool32 matchedTag = false;192if (Button) {193foreach_all(Button, button)194{195if (button->tag == self->buttonTag) {196taggedButton = button;197matchedTag = true;198foreach_break;199}200}201}202203if (PullChain && !matchedTag) {204foreach_all(PullChain, chain)205{206if (chain->tag == self->buttonTag) {207taggedButton = (EntityButton *)chain;208matchedTag = true;209foreach_break;210}211}212}213}214215if (taggedButton) {216if ((Button && taggedButton->classID == Button->classID) || (PullChain && taggedButton->classID == PullChain->classID)) {217int32 distX = abs(self->position.x - taggedButton->position.x) + TO_FIXED(128);218int32 distY = abs(self->position.y - taggedButton->position.y) + TO_FIXED(128);219220if (self->updateRange.x < distX)221self->updateRange.x = distX;222223if (self->updateRange.y < distY)224self->updateRange.y = distY;225226self->taggedButton = taggedButton;227}228}229}230231Vector2 Current_GetBubbleSpawnPosHorizontal(uint8 right)232{233RSDK_THIS(Current);234235int32 x = 0;236if (right) {237x = self->position.x - (self->size.x >> 1) - 0x200000;238if ((ScreenInfo->position.x - 64) << 16 > x)239x = (ScreenInfo->position.x - 64) << 16;240}241else {242x = (self->size.x >> 1) + self->position.x + 0x200000;243if ((ScreenInfo->position.x + 64 + ScreenInfo->size.x) << 16 < x)244x = (ScreenInfo->position.x + 64 + ScreenInfo->size.x) << 16;245}246247int32 maxY = self->position.y - (self->size.y >> 1) - 0x200000;248if ((ScreenInfo->position.y - 64) << 16 > maxY)249maxY = (ScreenInfo->position.y - 64) << 16;250251int32 screenY = (ScreenInfo->position.y + 64 + ScreenInfo->size.y) << 16;252int32 minY = (self->size.y >> 1) + self->position.y + 0x200000;253if (screenY < minY)254minY = screenY;255256int32 randMax = (minY - maxY) >> 20;257if (!randMax)258randMax = 1;259260Vector2 bubblePos;261bubblePos.x = x;262if (randMax <= 0)263bubblePos.y = maxY;264else265bubblePos.y = maxY + (ZONE_RAND(0, randMax) << 20);266return bubblePos;267}268269Vector2 Current_GetBubbleSpawnPosVertical(uint8 down)270{271RSDK_THIS(Current);272273int32 y = 0;274if (down) {275y = self->position.y - (self->size.y >> 1) - 0x200000;276if ((ScreenInfo->position.y - 64) << 16 > y)277y = (ScreenInfo->position.y - 64) << 16;278}279else {280y = (self->size.y >> 1) + self->position.y + 0x200000;281if ((ScreenInfo->position.y + 64 + ScreenInfo->size.y) << 16 < y)282y = (ScreenInfo->position.y + 64 + ScreenInfo->size.y) << 16;283}284285int32 maxX = self->position.x - (self->size.x >> 1) - 0x200000;286if ((ScreenInfo->position.x - 64) << 16 > maxX)287maxX = (ScreenInfo->position.x - 64) << 16;288289int32 screenX = (ScreenInfo->position.x + 64 + ScreenInfo->size.x) << 16;290int32 minX = (self->size.x >> 1) + self->position.x + 0x200000;291if (screenX < minX)292minX = screenX;293294int32 max = (minX - maxX) >> 20;295if (!max)296max = 1;297298Vector2 bubblePos;299if (max <= 0) {300bubblePos.x = maxX;301bubblePos.y = y;302}303else {304bubblePos.x = maxX + (RSDK.Rand(0, max) << 20);305bubblePos.y = y;306}307return bubblePos;308}309310void Current_State_WaterLeft(void)311{312RSDK_THIS(Current);313314foreach_active(Player, player)315{316int32 playerID = RSDK.GetEntitySlot(player);317318if ((self->planeFilter <= 0 || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) && (!self->waterOnly || player->underwater)) {319320if (Player_CheckValidState(player)) {321if ((1 << playerID) & self->activePlayers) {322if (!Player_CheckCollisionTouch(player, self, &self->hitbox) || player->state == Player_State_HoldRespawn) {323if (player->state != Player_State_HoldRespawn)324player->state = Player_State_Air;325326int32 x = self->position.x + ((self->hitbox.right - 32) << 16);327self->activePlayers &= ~(1 << playerID);328if (RSDK.CheckSceneFolder("FBZ") && !player->sidekick && self->fbzAchievement && self->playerPositions[playerID].x >= x329&& player->position.x < self->position.x) {330API_UnlockAchievement(&achievementList[ACH_FBZ]);331}332self->playerPositions[playerID].x = 0;333self->playerPositions[playerID].y = 0;334}335}336else if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {337self->playerPositions[playerID].x = player->position.x;338self->playerPositions[playerID].y = player->position.y;339self->activePlayers |= 1 << playerID;340}341342if ((1 << playerID) & self->activePlayers) {343bool32 inBubble = false;344if (Water)345inBubble = Water_GetPlayerBubble(player) != NULL;346347if (player->state != Player_State_Hurt && player->state != Player_State_HoldRespawn) {348int32 anim = player->animator.animationID;349if (anim != ANI_CLING && anim != ANI_SHAFT_SWING) {350player->onGround = false;351player->nextGroundState = StateMachine_None;352player->nextAirState = StateMachine_None;353player->velocity.x = -(self->strength << 15);354player->groundVel = player->velocity.x;355356if (!inBubble) {357RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);358player->tileCollisions = TILECOLLISION_DOWN;359player->nextAirState = StateMachine_None;360player->nextGroundState = StateMachine_None;361player->state = Current_PlayerState_Left;362}363}364365if (player->up)366player->velocity.y = -0x10000;367else if (player->down)368player->velocity.y = 0x10000;369else370player->velocity.y = 0;371}372}373}374else {375self->activePlayers &= ~(1 << playerID);376}377}378}379380if (Water) {381if (!(Zone->timer & 7)) {382Vector2 pos = Current_GetBubbleSpawnPosHorizontal(false);383EntityCurrent *child = CREATE_ENTITY(Current, INT_TO_VOID(CURRENT_CHILD_BUBBLE), pos.x, pos.y);384385child->drawGroup = Zone->objectDrawGroup[1];386child->strength = (self->strength + (self->strength >> 3)) >> 1;387child->size.x = self->position.x - (self->size.x >> 1) + 0x400000;388child->drawGroup = Zone->playerDrawGroup[0];389if (child->position.x < (self->position.x + (self->size.x >> 1)))390child->alpha = 0xF0;391}392}393}394395void Current_State_WaterRight(void)396{397RSDK_THIS(Current);398399foreach_active(Player, player)400{401int32 playerID = RSDK.GetEntitySlot(player);402403if ((self->planeFilter <= 0 || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) && (!self->waterOnly || player->underwater)) {404405if (Player_CheckValidState(player)) {406if ((1 << playerID) & self->activePlayers) {407if (!Player_CheckCollisionTouch(player, self, &self->hitbox) || player->state == Player_State_HoldRespawn) {408if (player->state != Player_State_HoldRespawn)409player->state = Player_State_Air;410self->activePlayers &= ~(1 << playerID);411}412}413else if (Player_CheckCollisionTouch(player, self, &self->hitbox))414self->activePlayers |= 1 << playerID;415416if ((1 << playerID) & self->activePlayers) {417bool32 inBubble = false;418if (Water)419inBubble = Water_GetPlayerBubble(player) != NULL;420421if (player->state != Player_State_Hurt && player->state != Player_State_HoldRespawn) {422int32 anim = player->animator.animationID;423if (anim != ANI_CLING && anim != ANI_SHAFT_SWING) {424player->onGround = false;425player->nextGroundState = StateMachine_None;426player->nextAirState = StateMachine_None;427player->velocity.x = self->strength << 15;428player->groundVel = player->velocity.x;429if (!inBubble) {430RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);431player->tileCollisions = TILECOLLISION_DOWN;432player->nextAirState = StateMachine_None;433player->nextGroundState = StateMachine_None;434player->state = Current_PlayerState_Right;435}436}437438if (player->up)439player->velocity.y = -0x10000;440else if (player->down)441player->velocity.y = 0x10000;442else443player->velocity.y = 0;444}445}446}447else {448self->activePlayers &= ~(1 << playerID);449}450}451}452453if (Water) {454if (!(Zone->timer & 7)) {455Vector2 pos = Current_GetBubbleSpawnPosHorizontal(true);456EntityCurrent *child = CREATE_ENTITY(Current, INT_TO_VOID(CURRENT_CHILD_BUBBLE), pos.x, pos.y);457458child->drawGroup = Zone->objectDrawGroup[1];459child->strength = (self->strength + (self->strength >> 3)) >> 1;460child->size.x = (self->size.x >> 1) + self->position.x - 0x400000;461child->type = CURRENT_C_RIGHT;462child->drawGroup = Zone->playerDrawGroup[0];463if (child->position.x > (self->position.x - (self->size.x >> 1)))464child->alpha = 0xF0;465}466}467}468469void Current_State_WaterUp(void)470{471RSDK_THIS(Current);472473foreach_active(Player, player)474{475int32 playerID = RSDK.GetEntitySlot(player);476477if ((self->planeFilter <= 0 || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) && (!self->waterOnly || player->underwater)) {478479if (Player_CheckValidState(player)) {480if ((1 << playerID) & self->activePlayers) {481if (!Player_CheckCollisionTouch(player, self, &self->hitbox) || player->state == Player_State_HoldRespawn) {482if (player->state != Player_State_HoldRespawn)483player->state = Player_State_Air;484self->activePlayers &= ~(1 << playerID);485}486}487else if (Player_CheckCollisionTouch(player, self, &self->hitbox))488self->activePlayers |= 1 << playerID;489490if ((1 << playerID) & self->activePlayers) {491bool32 inBubble = false;492if (Water)493inBubble = Water_GetPlayerBubble(player) != NULL;494495if (player->state != Player_State_Hurt && player->state != Player_State_HoldRespawn) {496int32 anim = player->animator.animationID;497if (anim != ANI_CLING && anim != ANI_SHAFT_SWING) {498player->onGround = false;499player->nextGroundState = StateMachine_None;500player->nextAirState = StateMachine_None;501player->velocity.y = -(self->strength << 15);502if (!inBubble) {503RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);504player->tileCollisions = TILECOLLISION_DOWN;505player->nextAirState = StateMachine_None;506player->nextGroundState = StateMachine_None;507player->state = Current_PlayerState_Up;508}509}510511if (player->left) {512player->velocity.x = -0x10000;513player->groundVel = -0x10000;514}515else if (player->right) {516player->velocity.x = 0x10000;517player->groundVel = 0x10000;518}519else {520player->velocity.x = 0;521}522}523}524}525else {526self->activePlayers &= ~(1 << playerID);527}528}529}530531if (Water) {532if (!(Zone->timer & 7)) {533Vector2 pos = Current_GetBubbleSpawnPosVertical(false);534EntityCurrent *child = CREATE_ENTITY(Current, INT_TO_VOID(CURRENT_CHILD_BUBBLE), pos.x, pos.y);535536child->drawGroup = Zone->objectDrawGroup[1];537child->strength = (self->strength + (self->strength >> 3)) >> 1;538child->size.y = (self->position.y - (self->size.y >> 1)) + 0x400000;539child->type = CURRENT_C_UP;540child->drawGroup = Zone->playerDrawGroup[0];541if (child->position.y < (self->position.y + (self->size.y >> 1)))542child->alpha = 0xF0;543}544}545}546547void Current_State_WaterDown(void)548{549RSDK_THIS(Current);550551foreach_active(Player, player)552{553int32 playerID = RSDK.GetEntitySlot(player);554555if ((self->planeFilter <= 0 || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) && (!self->waterOnly || player->underwater)) {556557if (Player_CheckValidState(player)) {558if ((1 << playerID) & self->activePlayers) {559if (!Player_CheckCollisionTouch(player, self, &self->hitbox) || player->state == Player_State_HoldRespawn) {560if (player->state != Player_State_HoldRespawn)561player->state = Player_State_Air;562563self->activePlayers &= ~(1 << playerID);564}565}566else if (Player_CheckCollisionTouch(player, self, &self->hitbox))567self->activePlayers |= 1 << playerID;568569if ((1 << playerID) & self->activePlayers) {570bool32 inBubble = false;571if (Water)572inBubble = Water_GetPlayerBubble(player) != NULL;573574if (player->state != Player_State_Hurt && player->state != Player_State_HoldRespawn) {575int32 anim = player->animator.animationID;576if (anim != ANI_CLING && anim != ANI_SHAFT_SWING) {577player->onGround = false;578player->nextGroundState = StateMachine_None;579player->nextAirState = StateMachine_None;580player->velocity.y = self->strength << 15;581582if (!inBubble) {583RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);584player->tileCollisions = TILECOLLISION_DOWN;585player->nextAirState = StateMachine_None;586player->nextGroundState = StateMachine_None;587player->state = Current_PlayerState_Down;588}589}590591if (player->left) {592player->velocity.x = -0x10000;593player->groundVel = -0x10000;594}595else if (player->right) {596player->velocity.x = 0x10000;597player->groundVel = 0x10000;598}599else {600player->velocity.x = 0;601}602}603}604}605else {606self->activePlayers &= ~(1 << playerID);607}608}609}610611if (Water) {612if (!(Zone->timer & 7)) {613Vector2 pos = Current_GetBubbleSpawnPosVertical(true);614EntityCurrent *child = CREATE_ENTITY(Current, INT_TO_VOID(CURRENT_CHILD_BUBBLE), pos.x, pos.y);615616child->drawGroup = Zone->objectDrawGroup[1];617child->strength = (self->strength + (self->strength >> 3)) >> 1;618child->size.y = (self->size.y >> 1) + self->position.y - 0x400000;619child->type = CURRENT_C_DOWN;620child->drawGroup = Zone->playerDrawGroup[0];621if (child->position.y > (self->position.y - (self->size.y >> 1)))622child->alpha = 0xF0;623}624}625}626627void Current_State_PushLeft(void)628{629RSDK_THIS(Current);630631foreach_active(Player, player)632{633if ((self->planeFilter <= 0 || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) && (!self->waterOnly || player->underwater)) {634if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {635int32 anim = player->animator.animationID;636if (anim != ANI_CLING && anim != ANI_SHAFT_SWING)637player->position.x += -(self->strength << 15);638}639}640}641642if (!(Zone->timer & 7)) {643Vector2 pos = Current_GetBubbleSpawnPosHorizontal(0);644EntityCurrent *child = CREATE_ENTITY(Current, INT_TO_VOID(CURRENT_CHILD_WIND), pos.x, pos.y);645646child->drawGroup = Zone->objectDrawGroup[1];647child->strength = 4 * self->strength + RSDK.Rand(1 - self->strength, 5);648child->size.x = self->position.x - (self->size.x >> 1) + 0x400000;649if (child->position.x < (self->position.x + (self->size.x >> 1)))650child->alpha = 0xF0;651}652}653654void Current_State_PushRight(void)655{656RSDK_THIS(Current);657658foreach_active(Player, player)659{660if ((self->planeFilter <= 0 || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) && (!self->waterOnly || player->underwater)) {661if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {662int32 anim = player->animator.animationID;663if (anim != ANI_CLING && anim != ANI_SHAFT_SWING)664player->position.x += self->strength << 15;665}666}667}668}669670void Current_State_PushUp(void)671{672RSDK_THIS(Current);673674foreach_active(Player, player)675{676if ((self->planeFilter <= 0 || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) && (!self->waterOnly || player->underwater)) {677if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {678int32 anim = player->animator.animationID;679if (anim != ANI_CLING && anim != ANI_SHAFT_SWING && !player->onGround)680player->position.y += -(self->strength << 15);681}682}683}684}685686void Current_State_PushDown(void)687{688RSDK_THIS(Current);689690foreach_active(Player, player)691{692if ((self->planeFilter <= 0 || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) && (!self->waterOnly || player->underwater)) {693if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {694int32 anim = player->animator.animationID;695if (anim != ANI_CLING && anim != ANI_SHAFT_SWING && !player->onGround)696player->position.y += self->strength << 15;697}698}699}700}701702void Current_State_Child(void)703{704RSDK_THIS(Current);705RSDK.ProcessAnimation(&self->animator);706707switch (self->type) {708case CURRENT_C_LEFT:709self->position.x -= self->strength << 17;710if (self->position.x < self->size.x) {711self->alpha -= 8;712}713else {714if (self->alpha < 0xF0)715self->alpha += 8;716}717break;718719case CURRENT_C_RIGHT:720self->position.x += self->strength << 17;721if (self->position.x >= self->size.x) {722if (self->alpha < 0xF0)723self->alpha += 8;724}725else {726self->alpha -= 8;727}728break;729730case CURRENT_C_UP:731self->position.y -= self->strength << 17;732if (self->position.y >= self->size.y) {733if (self->alpha < 0xF0)734self->alpha += 8;735}736else {737self->alpha -= 8;738}739break;740741case CURRENT_C_DOWN:742self->position.y += self->strength << 17;743if (self->position.y >= self->size.y) {744if (self->alpha < 0xF0)745self->alpha += 8;746}747else {748self->alpha -= 8;749}750break;751752default: break;753}754755if ((Water && self->position.y < Water->waterLevel) || !RSDK.CheckOnScreen(self, NULL) || !self->alpha)756destroyEntity(self);757}758759void Current_PlayerState_Left(void)760{761RSDK_THIS(Player);762763Hitbox *hitbox = Player_GetHitbox(self);764RSDK.ObjectTileCollision(self, self->collisionLayers, CMODE_ROOF, self->collisionPlane, hitbox->left << 16, hitbox->top << 16, true);765RSDK.ObjectTileCollision(self, self->collisionLayers, CMODE_FLOOR, self->collisionPlane, hitbox->left << 16, hitbox->bottom << 16, true);766}767768void Current_PlayerState_Right(void)769{770RSDK_THIS(Player);771772Hitbox *hitbox = Player_GetHitbox(self);773RSDK.ObjectTileCollision(self, self->collisionLayers, CMODE_ROOF, self->collisionPlane, hitbox->right << 16, hitbox->top << 16, true);774RSDK.ObjectTileCollision(self, self->collisionLayers, CMODE_FLOOR, self->collisionPlane, hitbox->right << 16, hitbox->bottom << 16, true);775}776777void Current_PlayerState_Up(void)778{779RSDK_THIS(Player);780781Hitbox *hitbox = Player_GetHitbox(self);782RSDK.ObjectTileCollision(self, self->collisionLayers, CMODE_RWALL, self->collisionPlane, hitbox->left << 16, hitbox->top << 16, true);783RSDK.ObjectTileCollision(self, self->collisionLayers, CMODE_LWALL, self->collisionPlane, hitbox->right << 16, hitbox->top << 16, true);784}785786void Current_PlayerState_Down(void)787{788RSDK_THIS(Player);789790Hitbox *hitbox = Player_GetHitbox(self);791RSDK.ObjectTileCollision(self, self->collisionLayers, CMODE_RWALL, self->collisionPlane, hitbox->left << 16, hitbox->bottom << 16, true);792RSDK.ObjectTileCollision(self, self->collisionLayers, CMODE_LWALL, self->collisionPlane, hitbox->right << 16, hitbox->bottom << 16, true);793}794795#if GAME_INCLUDE_EDITOR796void Current_EditorDraw(void)797{798RSDK_THIS(Current);799800self->updateRange.x = self->size.x >> 1;801self->updateRange.y = self->size.y >> 1;802803RSDK.SetSpriteAnimation(Current->aniFrames, 1, &Current->animator, true, 0);804self->direction = FLIP_NONE;805806RSDK.DrawSprite(&Current->animator, NULL, false);807808if (showGizmos()) {809RSDK_DRAWING_OVERLAY(true);810DrawHelpers_DrawRectOutline(self->position.x, self->position.y, self->size.x, self->size.y, 0xFFFF00);811812RSDK.SetSpriteAnimation(Current->aniFrames, 0, &Current->animator, true, 0);813Vector2 drawPos;814drawPos.x = self->position.x;815drawPos.y = self->position.y;816drawPos.x -= self->size.x >> 1;817drawPos.y -= self->size.y >> 1;818819self->direction = FLIP_NONE;820RSDK.DrawSprite(&Current->animator, &drawPos, false);821822drawPos.x += self->size.x;823self->direction = FLIP_X;824RSDK.DrawSprite(&Current->animator, &drawPos, false);825826drawPos.y += self->size.y;827self->direction = FLIP_XY;828RSDK.DrawSprite(&Current->animator, &drawPos, false);829830drawPos.x -= self->size.x;831self->direction = FLIP_Y;832RSDK.DrawSprite(&Current->animator, &drawPos, false);833RSDK_DRAWING_OVERLAY(false);834835Current_SetupTagLink();836837RSDK_DRAWING_OVERLAY(true);838if (self->taggedButton) {839DrawHelpers_DrawArrow(self->taggedButton->position.x, self->taggedButton->position.y, self->position.x, self->position.y, 0xFFFF00,840INK_NONE, 0xFF);841}842RSDK_DRAWING_OVERLAY(false);843}844}845846void Current_EditorLoad(void)847{848Current->aniFrames = RSDK.LoadSpriteAnimation("FBZ/Current.bin", SCOPE_STAGE);849RSDK.SetSpriteAnimation(Current->aniFrames, 1, &Current->animator, true, 0);850851RSDK_ACTIVE_VAR(Current, type);852RSDK_ENUM_VAR("Current - Left", CURRENT_C_LEFT);853RSDK_ENUM_VAR("Current - Right", CURRENT_C_RIGHT);854RSDK_ENUM_VAR("Current - Up", CURRENT_C_UP);855RSDK_ENUM_VAR("Current - Down", CURRENT_C_DOWN);856RSDK_ENUM_VAR("Wind - Left", CURRENT_W_LEFT);857RSDK_ENUM_VAR("Wind - Right", CURRENT_W_RIGHT);858RSDK_ENUM_VAR("Wind - Up", CURRENT_W_UP);859RSDK_ENUM_VAR("Wind - Down", CURRENT_W_DOWN);860861RSDK_ACTIVE_VAR(Current, planeFilter);862RSDK_ENUM_VAR("None", PLANEFILTER_NONE);863RSDK_ENUM_VAR("AL", PLANEFILTER_AL);864RSDK_ENUM_VAR("BL", PLANEFILTER_BL);865RSDK_ENUM_VAR("AH", PLANEFILTER_AH);866RSDK_ENUM_VAR("BH", PLANEFILTER_BH);867}868#endif869870void Current_Serialize(void)871{872RSDK_EDITABLE_VAR(Current, VAR_ENUM, type);873RSDK_EDITABLE_VAR(Current, VAR_VECTOR2, size);874RSDK_EDITABLE_VAR(Current, VAR_UINT8, strength);875RSDK_EDITABLE_VAR(Current, VAR_ENUM, buttonTag);876RSDK_EDITABLE_VAR(Current, VAR_ENUM, planeFilter);877RSDK_EDITABLE_VAR(Current, VAR_BOOL, waterOnly);878RSDK_EDITABLE_VAR(Current, VAR_BOOL, fbzAchievement);879}880881882