Path: blob/master/SonicMania/Objects/MMZ/SizeLaser.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: SizeLaser Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectSizeLaser *SizeLaser;1011void SizeLaser_Update(void)12{13RSDK_THIS(SizeLaser);1415self->mainAnimator.frameID = (Zone->timer >> 2) & 1;16self->impactAnimator.frameID = (Zone->timer >> 2) & 1;1718StateMachine_Run(self->state);19}2021void SizeLaser_LateUpdate(void) {}2223void SizeLaser_StaticUpdate(void)24{25foreach_active(Player, player)26{27int32 playerID = RSDK.GetEntitySlot(player);2829SizeLaser->playerPositions[playerID].x = player->position.x;30SizeLaser->playerPositions[playerID].y = player->position.y;3132if (player->scale.x > 0x200) {3334Hitbox *playerHitbox = Player_GetHitbox(player);35SizeLaser->playerOuterBox[playerID].left = (player->scale.x * playerHitbox->left) >> 9;36SizeLaser->playerOuterBox[playerID].top = (player->scale.x * playerHitbox->top) >> 9;37SizeLaser->playerOuterBox[playerID].right = (player->scale.x * playerHitbox->right) >> 9;38SizeLaser->playerOuterBox[playerID].bottom = (player->scale.x * playerHitbox->bottom) >> 9;3940playerHitbox = Player_GetAltHitbox(player);41SizeLaser->playerInnerBox[playerID].left = (player->scale.x * playerHitbox->left) >> 9;42SizeLaser->playerInnerBox[playerID].top = (player->scale.x * playerHitbox->top) >> 9;43SizeLaser->playerInnerBox[playerID].right = (player->scale.x * playerHitbox->right) >> 9;44SizeLaser->playerInnerBox[playerID].bottom = (player->scale.x * playerHitbox->bottom) >> 9;4546player->outerbox = &SizeLaser->playerOuterBox[playerID];47player->innerbox = &SizeLaser->playerInnerBox[playerID];48}49}50}5152void SizeLaser_Draw(void)53{54RSDK_THIS(SizeLaser);5556RSDK.DrawSprite(&self->mainAnimator, NULL, false);5758if (self->state == SizeLaser_State_Impact)59RSDK.DrawSprite(&self->impactAnimator, &self->impactPos, false);60}6162void SizeLaser_Create(void *data)63{64RSDK_THIS(SizeLaser);6566self->drawFX = FX_FLIP;67if (!SceneInfo->inEditor) {68int32 type = VOID_TO_INT(data);69self->visible = true;70self->updateRange.x = 0x800000;71self->updateRange.y = 0x800000;7273if (!type) {74self->active = ACTIVE_BOUNDS;75self->drawGroup = Zone->objectDrawGroup[0] + 1;7677self->state = SizeLaser_State_Emitter;78switch (self->orientation) {79case SIZELASER_ORIENTATION_DOWN:80self->direction = FLIP_NONE;81RSDK.SetSpriteAnimation(SizeLaser->aniFrames, 2 * self->type, &self->mainAnimator, true, 0);82break;8384case SIZELASER_ORIENTATION_RIGHT:85case SIZELASER_ORIENTATION_LEFT:86self->direction = self->orientation == SIZELASER_ORIENTATION_LEFT ? FLIP_X : FLIP_NONE;87RSDK.SetSpriteAnimation(SizeLaser->aniFrames, 2 * self->type + 1, &self->mainAnimator, true, 0);88break;89}90}91else {92type--;93self->active = ACTIVE_NORMAL;94self->drawGroup = Zone->objectDrawGroup[0];95self->orientation = type >> 2;96self->type = type & 1;9798self->state = SizeLaser_State_Laser;99switch (self->orientation) {100default:101case SIZELASER_ORIENTATION_DOWN:102self->velocity.y = 0x40000;103104RSDK.SetSpriteAnimation(SizeLaser->aniFrames, 2 * (self->type + 2), &self->mainAnimator, true, 0);105RSDK.SetSpriteAnimation(SizeLaser->aniFrames, 2 * (self->type + 4), &self->impactAnimator, true, 0);106break;107108case SIZELASER_ORIENTATION_RIGHT:109case SIZELASER_ORIENTATION_LEFT:110self->direction = self->orientation == SIZELASER_ORIENTATION_LEFT ? FLIP_X : FLIP_NONE;111self->velocity.x = self->orientation == SIZELASER_ORIENTATION_LEFT ? -0x40000 : 0x40000;112113RSDK.SetSpriteAnimation(SizeLaser->aniFrames, 2 * self->type + 5, &self->mainAnimator, true, 0);114RSDK.SetSpriteAnimation(SizeLaser->aniFrames, 2 * self->type + 9, &self->impactAnimator, true, 0);115break;116}117}118}119}120121void SizeLaser_StageLoad(void)122{123SizeLaser->aniFrames = RSDK.LoadSpriteAnimation("MMZ/SizeLaser.bin", SCOPE_STAGE);124125switch (GET_CHARACTER_ID(1)) {126case ID_SONIC: SizeLaser->sonicFrames = RSDK.LoadSpriteAnimation("Players/ChibiSonic.bin", SCOPE_STAGE); break;127128case ID_TAILS:129SizeLaser->tailsFrames = RSDK.LoadSpriteAnimation("Players/ChibiTails.bin", SCOPE_STAGE);130SizeLaser->tailFrames = RSDK.LoadSpriteAnimation("Players/CTailSprite.bin", SCOPE_STAGE);131break;132133case ID_KNUCKLES: SizeLaser->knuxFrames = RSDK.LoadSpriteAnimation("Players/ChibiKnux.bin", SCOPE_STAGE); break;134135#if MANIA_USE_PLUS136case ID_MIGHTY: SizeLaser->mightyFrames = RSDK.LoadSpriteAnimation("Players/ChibiMighty.bin", SCOPE_STAGE); break;137138case ID_RAY: SizeLaser->rayFrames = RSDK.LoadSpriteAnimation("Players/ChibiRay.bin", SCOPE_STAGE); break;139#endif140141default: break;142}143144switch (GET_CHARACTER_ID(2)) {145case ID_SONIC: SizeLaser->sonicFrames = RSDK.LoadSpriteAnimation("Players/ChibiSonic.bin", SCOPE_STAGE); break;146147case ID_TAILS:148SizeLaser->tailsFrames = RSDK.LoadSpriteAnimation("Players/ChibiTails.bin", SCOPE_STAGE);149SizeLaser->tailFrames = RSDK.LoadSpriteAnimation("Players/CTailSprite.bin", SCOPE_STAGE);150break;151152case ID_KNUCKLES: SizeLaser->knuxFrames = RSDK.LoadSpriteAnimation("Players/ChibiKnux.bin", SCOPE_STAGE); break;153154#if MANIA_USE_PLUS155case ID_MIGHTY: SizeLaser->mightyFrames = RSDK.LoadSpriteAnimation("Players/ChibiMighty.bin", SCOPE_STAGE); break;156157case ID_RAY: SizeLaser->rayFrames = RSDK.LoadSpriteAnimation("Players/ChibiRay.bin", SCOPE_STAGE); break;158#endif159160default: break;161}162163SizeLaser->hitbox.left = -4;164SizeLaser->hitbox.top = -4;165SizeLaser->hitbox.right = 4;166SizeLaser->hitbox.bottom = 4;167168SizeLaser->sfxShrink2 = RSDK.GetSfx("MMZ/Shrink2.wav");169SizeLaser->sfxGrow2 = RSDK.GetSfx("MMZ/Grow2.wav");170171Soundboard_LoadSfx("MMZ/SizeLaser.wav", true, SizeLaser_SfxCheck_SizeLaser, StateMachine_None);172}173174bool32 SizeLaser_SfxCheck_SizeLaser(void)175{176int32 activeCount = 0;177178foreach_active(SizeLaser, entity)179{180if (entity->onScreen)181++activeCount;182}183184return activeCount > 0;185}186187void SizeLaser_SetPlayerSize(EntityPlayer *player, bool32 isChibi)188{189if (isChibi) {190switch (player->characterID) {191default:192case ID_SONIC:193player->aniFrames = SizeLaser->sonicFrames;194player->tailFrames = -1;195player->isChibi = isChibi;196break;197198case ID_TAILS:199player->aniFrames = SizeLaser->tailsFrames;200player->tailFrames = SizeLaser->tailFrames;201player->isChibi = isChibi;202break;203204case ID_KNUCKLES:205player->aniFrames = SizeLaser->knuxFrames;206player->tailFrames = -1;207player->isChibi = isChibi;208break;209210#if MANIA_USE_PLUS211case ID_MIGHTY:212player->aniFrames = SizeLaser->mightyFrames;213player->tailFrames = -1;214player->isChibi = isChibi;215break;216217case ID_RAY:218player->aniFrames = SizeLaser->rayFrames;219player->tailFrames = -1;220player->isChibi = isChibi;221break;222#endif223}224}225else {226switch (player->characterID) {227default:228case ID_SONIC:229player->aniFrames = Player->sonicFrames;230player->tailFrames = -1;231player->isChibi = isChibi;232break;233234case ID_TAILS:235player->aniFrames = Player->tailsFrames;236player->tailFrames = Player->tailsTailsFrames;237player->isChibi = false;238break;239240case ID_KNUCKLES:241player->aniFrames = Player->knuxFrames;242player->tailFrames = -1;243player->isChibi = isChibi;244break;245246#if MANIA_USE_PLUS247case ID_MIGHTY:248player->aniFrames = Player->mightyFrames;249player->tailFrames = -1;250player->isChibi = isChibi;251break;252253case ID_RAY:254player->aniFrames = Player->rayFrames;255player->tailFrames = -1;256player->isChibi = isChibi;257break;258#endif259}260}261}262263// used to have a sidekick resize to match the leader's size264void SizeLaser_PlayerState_Resize(void)265{266// ???267EntityPlayer *self = RSDK_GET_ENTITY(SceneInfo->entitySlot, Player);268269EntityPlayer *leader = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);270271self->position.x = leader->position.x;272self->position.y = leader->position.y;273274self->position.x += self->abilityValues[0];275self->position.y += self->abilityValues[1];276277if (self->abilityValues[0] <= 0) {278if (self->abilityValues[0] < 0) {279self->abilityValues[0] -= self->abilityValues[0] >> 4;280281if (self->abilityValues[0] > 0)282self->abilityValues[0] = 0;283}284}285else {286self->abilityValues[0] -= self->abilityValues[0] >> 4;287288if (self->abilityValues[0] < 0)289self->abilityValues[0] = 0;290}291292if (self->abilityValues[1] <= 0) {293if (self->abilityValues[1] < 0) {294self->abilityValues[1] -= self->abilityValues[0] >> 4;295296if (self->abilityValues[1] > 0)297self->abilityValues[1] = 0;298}299}300else {301self->abilityValues[1] -= self->abilityValues[0] >> 4;302303if (self->abilityValues[1] < 0)304self->abilityValues[1] = 0;305}306307if (leader->state == SizeLaser_PlayerState_ShrinkChibi) {308if (leader->state == SizeLaser_PlayerState_GrowNormal || !leader->isChibi) {309self->state = SizeLaser_PlayerState_GrowNormal;310self->interaction = false;311}312}313else if (leader->isChibi) {314self->state = SizeLaser_PlayerState_ShrinkChibi;315self->interaction = false;316}317}318319void SizeLaser_PlayerState_GrowNormal(void)320{321// ???322EntityPlayer *self = RSDK_GET_ENTITY(SceneInfo->entitySlot, Player);323324StateMachine(state) = self->abilityPtrs[0];325StateMachine_Run(state);326327if (self->scale.x >= 0x200) {328self->drawFX &= ~FX_SCALE;329self->isChibi = false;330self->scale.x = 0x200;331self->scale.y = 0x200;332self->interaction = true;333self->state = Player_State_Air;334Player_UpdatePhysicsState(self);335self->jumpOffset = self->characterID == ID_TAILS ? 0 : 0x50000;336}337else {338self->state = SizeLaser_PlayerState_GrowNormal;339self->scale.x += 6;340self->scale.y = self->scale.x;341}342}343344void SizeLaser_PlayerState_ShrinkChibi(void)345{346// ???347EntityPlayer *self = RSDK_GET_ENTITY(SceneInfo->entitySlot, Player);348349StateMachine(state) = self->abilityPtrs[0];350StateMachine_Run(state);351352if (self->scale.x <= 0x140) {353switch (self->characterID) {354default:355case ID_SONIC:356self->aniFrames = SizeLaser->sonicFrames;357self->tailFrames = -1;358break;359360case ID_TAILS:361self->aniFrames = SizeLaser->tailsFrames;362self->tailFrames = SizeLaser->tailFrames;363break;364365case ID_KNUCKLES:366self->aniFrames = SizeLaser->knuxFrames;367self->tailFrames = -1;368break;369370#if MANIA_USE_PLUS371case ID_MIGHTY:372self->aniFrames = SizeLaser->mightyFrames;373self->tailFrames = -1;374break;375376case ID_RAY:377self->aniFrames = SizeLaser->rayFrames;378self->tailFrames = -1;379break;380#endif381}382383self->jumpOffset = 0x40000;384RSDK.SetSpriteAnimation(self->aniFrames, ANI_HURT, &self->animator, false, 0);385self->isChibi = true;386self->drawFX &= ~FX_SCALE;387self->scale.x = 0x200;388self->scale.y = 0x200;389self->interaction = true;390391self->state = Player_State_Air;392Player_UpdatePhysicsState(self);393}394else {395self->state = SizeLaser_PlayerState_ShrinkChibi;396self->scale.x -= 6;397self->scale.y = self->scale.x;398}399}400401void SizeLaser_PlayerState_GrowGiant(void)402{403EntityPlayer *self = RSDK_GET_ENTITY(SceneInfo->entitySlot, Player);404405StateMachine(state) = self->abilityPtrs[0];406StateMachine_Run(state);407408if (self->scale.x >= 0x300) {409self->scale.x = 0x300;410self->scale.y = 0x300;411self->interaction = true;412self->state = Player_State_Air;413Player_UpdatePhysicsState(self);414}415else {416self->state = SizeLaser_PlayerState_GrowGiant;417self->scale.x += 8;418self->scale.y = self->scale.x;419}420}421422void SizeLaser_CheckPlayerCollisions(void)423{424RSDK_THIS(SizeLaser);425426int32 entityX = self->position.x;427int32 entityY = self->position.y;428429int32 extendX1[2];430int32 extendY1[2];431int32 extendX2[2];432int32 extendY2[2];433434switch (self->orientation) {435default: break;436437case SIZELASER_ORIENTATION_DOWN:438extendX1[0] = entityX - 0x80000;439extendX1[1] = entityX + 0x80000;440441extendY1[0] = entityY - 0x200000;442extendY1[1] = entityY - 0x200000;443444extendX2[0] = entityX - 0x80000;445extendX2[1] = entityX + 0x80000;446447extendY2[0] = entityY + (self->extend << 16);448extendY2[1] = entityY + (self->extend << 16);449break;450451case SIZELASER_ORIENTATION_RIGHT:452extendX1[0] = entityX - 0x200000;453extendX1[1] = entityX - 0x200000;454455extendY1[0] = entityY - 0x80000;456extendY1[1] = entityY + 0x80000;457458extendX2[0] = entityX + (self->extend << 16);459extendX2[1] = entityX + (self->extend << 16);460461extendY2[1] = entityY + 0x80000;462extendY2[0] = entityY - 0x80000;463break;464465case SIZELASER_ORIENTATION_LEFT:466extendX1[0] = entityX - 0x200000;467extendX1[1] = entityX;468469extendY1[0] = entityY - 0x80000;470extendY1[1] = entityY + 0x80000;471472extendX2[0] = entityX + 0x200000;473extendX2[1] = entityX - (self->extend << 16);474475extendY2[0] = entityY + 0x80000;476extendY2[1] = entityY - 0x80000;477break;478}479480foreach_active(Player, player)481{482int32 playerID = RSDK.GetEntitySlot(player);483if (MathHelpers_CheckPositionOverlap(SizeLaser->playerPositions[playerID].x, SizeLaser->playerPositions[playerID].y, player->position.x,484player->position.y, extendX1[0], extendY1[0], extendX2[0], extendY2[0])485|| MathHelpers_CheckPositionOverlap(SizeLaser->playerPositions[playerID].x, SizeLaser->playerPositions[playerID].y, player->position.x,486player->position.y, extendX1[1], extendY1[1], extendX2[1], extendY2[1])) {487488if (self->type) {489if (player->state == SizeLaser_PlayerState_ShrinkChibi || player->state == SizeLaser_PlayerState_GrowNormal || !player->isChibi) {490if (player->state != SizeLaser_PlayerState_GrowGiant && player->scale.x > 0x400) {491player->onGround = false;492player->interaction = false;493player->velocity.y = -0x40000;494player->nextAirState = StateMachine_None;495player->nextGroundState = StateMachine_None;496player->velocity.x = player->direction ? 0x20000 : -0x20000;497player->drawFX |= FX_SCALE;498player->scale.x = 0x200;499player->scale.y = 0x200;500player->tileCollisions = TILECOLLISION_DOWN;501RSDK.SetSpriteAnimation(player->aniFrames, ANI_HURT, &player->animator, false, 0);502player->abilityPtrs[0] = Player_State_Hurt;503player->state = SizeLaser_PlayerState_GrowGiant;504}505}506else {507player->onGround = false;508player->interaction = false;509player->velocity.y = -0x40000;510player->nextAirState = StateMachine_None;511player->nextGroundState = StateMachine_None;512player->velocity.x = player->direction ? 0x20000 : -0x20000;513player->drawFX |= FX_SCALE;514player->scale.x = 0x140;515player->scale.y = 0x140;516switch (player->characterID) {517default:518case ID_SONIC:519if (player->superState == SUPERSTATE_SUPER)520player->aniFrames = Player->superFrames;521else522player->aniFrames = Player->sonicFrames;523player->tailFrames = -1;524break;525526case ID_TAILS:527player->aniFrames = Player->tailsFrames;528player->tailFrames = Player->tailsTailsFrames;529break;530531case ID_KNUCKLES:532player->aniFrames = Player->knuxFrames;533player->tailFrames = -1;534break;535536#if MANIA_USE_PLUS537case ID_MIGHTY:538player->aniFrames = Player->mightyFrames;539player->tailFrames = -1;540break;541542case ID_RAY:543player->aniFrames = Player->rayFrames;544player->tailFrames = -1;545break;546#endif547}548549RSDK.SetSpriteAnimation(player->aniFrames, ANI_HURT, &player->animator, false, 0);550RSDK.PlaySfx(SizeLaser->sfxGrow2, false, 255);551player->tileCollisions = TILECOLLISION_DOWN;552player->abilityPtrs[0] = Player_State_Hurt;553player->state = SizeLaser_PlayerState_GrowNormal;554}555}556else if (player->state != SizeLaser_PlayerState_ShrinkChibi && player->state != SizeLaser_PlayerState_GrowNormal && !player->isChibi) {557player->onGround = false;558player->interaction = false;559player->velocity.y = -0x40000;560player->nextAirState = StateMachine_None;561player->nextGroundState = StateMachine_None;562player->velocity.x = player->direction ? 0x20000 : -0x20000;563player->drawFX |= FX_SCALE;564player->scale.x = 0x200;565player->scale.y = 0x200;566RSDK.SetSpriteAnimation(player->aniFrames, ANI_HURT, &player->animator, false, 0);567RSDK.PlaySfx(SizeLaser->sfxShrink2, false, 0xFF);568player->tileCollisions = TILECOLLISION_DOWN;569player->abilityPtrs[0] = Player_State_Hurt;570player->state = SizeLaser_PlayerState_ShrinkChibi;571}572}573}574}575576void SizeLaser_State_Emitter(void)577{578RSDK_THIS(SizeLaser);579580if (self->timer < 24 && !(self->timer & 1))581CREATE_ENTITY(SizeLaser, INT_TO_VOID(self->type + (self->orientation << 2) + 1), self->position.x, self->position.y);582SizeLaser_CheckPlayerCollisions();583584self->timer = (self->timer + 1) & 0x1F;585}586587void SizeLaser_State_Laser(void)588{589RSDK_THIS(SizeLaser);590591self->position.x += self->velocity.x;592self->position.y += self->velocity.y;593594bool32 collided = false;595switch (self->orientation) {596case SIZELASER_ORIENTATION_DOWN: collided = RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x40000, false); break;597case SIZELASER_ORIENTATION_RIGHT: collided = RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_LWALL, 0, 0x40000, 0, false); break;598case SIZELASER_ORIENTATION_LEFT: collided = RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_RWALL, 0, -0x40000, 0, false); break;599}600601if (collided) {602self->impactPos.x = self->position.x;603self->impactPos.y = self->position.y;604self->state = SizeLaser_State_Impact;605}606}607608void SizeLaser_State_Impact(void)609{610RSDK_THIS(SizeLaser);611612self->position.x += self->velocity.x;613self->position.y += self->velocity.y;614615if (++self->timer == 4)616destroyEntity(self);617}618619#if GAME_INCLUDE_EDITOR620void SizeLaser_EditorDraw(void)621{622RSDK_THIS(SizeLaser);623624switch (self->orientation) {625case SIZELASER_ORIENTATION_DOWN:626self->direction = FLIP_NONE;627RSDK.SetSpriteAnimation(SizeLaser->aniFrames, 2 * self->type, &self->mainAnimator, true, 0);628break;629630case SIZELASER_ORIENTATION_RIGHT:631case SIZELASER_ORIENTATION_LEFT:632self->direction = self->orientation == SIZELASER_ORIENTATION_LEFT ? FLIP_X : FLIP_NONE;633RSDK.SetSpriteAnimation(SizeLaser->aniFrames, 2 * self->type + 1, &self->mainAnimator, true, 0);634break;635}636637RSDK.DrawSprite(&self->mainAnimator, NULL, false);638639if (showGizmos()) {640RSDK_DRAWING_OVERLAY(true);641642int32 extendX = 0, extendY = 0;643switch (self->orientation) {644case SIZELASER_ORIENTATION_DOWN: extendY = (self->extend << 16); break;645646case SIZELASER_ORIENTATION_RIGHT: extendX = (self->extend << 16); break;647648case SIZELASER_ORIENTATION_LEFT: extendX = -(self->extend << 16); break;649}650651DrawHelpers_DrawArrow(self->position.x, self->position.y, self->position.x + extendX, self->position.y + extendY, 0x00FF00, INK_NONE, 0xFF);652653RSDK_DRAWING_OVERLAY(false);654}655}656657void SizeLaser_EditorLoad(void)658{659SizeLaser->aniFrames = RSDK.LoadSpriteAnimation("MMZ/SizeLaser.bin", SCOPE_STAGE);660661RSDK_ACTIVE_VAR(SizeLaser, type);662RSDK_ENUM_VAR("Shrink", SIZELASER_SHRINK);663RSDK_ENUM_VAR("Grow", SIZELASER_GROW);664665RSDK_ACTIVE_VAR(SizeLaser, orientation);666RSDK_ENUM_VAR("Down", SIZELASER_ORIENTATION_DOWN);667RSDK_ENUM_VAR("Right", SIZELASER_ORIENTATION_RIGHT);668RSDK_ENUM_VAR("Left", SIZELASER_ORIENTATION_LEFT);669}670#endif671672void SizeLaser_Serialize(void)673{674RSDK_EDITABLE_VAR(SizeLaser, VAR_UINT8, type);675RSDK_EDITABLE_VAR(SizeLaser, VAR_UINT8, orientation);676RSDK_EDITABLE_VAR(SizeLaser, VAR_ENUM, extend);677}678679680