Path: blob/master/SonicMania/Objects/GHZ/Bridge.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Bridge Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectBridge *Bridge;1011void Bridge_Update(void)12{13RSDK_THIS(Bridge);1415if (self->stoodEntityCount) {16if (self->timer < 0x80)17self->timer += 8;18}19else {20if (self->timer) {21self->stoodEntity = (Entity *)-1;22self->timer -= 8;23}24else {25self->depression = 0;26}27}2829self->stoodEntityCount = 0;30self->bridgeDepth = (self->depression * self->timer) >> 7;3132foreach_active(Player, player)33{34Hitbox *playerHitbox = Player_GetHitbox(player);35if (player->state == Player_State_KnuxLedgePullUp)36continue;3738Bridge_HandleCollisions(player, self, playerHitbox, true, true);39}4041if (self->burnOffset != 0xFF)42Bridge_Burn(self->burnOffset);43}4445void Bridge_LateUpdate(void) {}4647void Bridge_StaticUpdate(void) {}4849void Bridge_Draw(void)50{51RSDK_THIS(Bridge);52int32 id = 0;53Vector2 drawPos;5455int32 size = self->stoodPos >> 20;56int32 ang = 0x80000;57drawPos.x = self->startPos + 0x80000;58for (int32 i = 0; i < size; ++i) {59drawPos.y = (self->bridgeDepth * RSDK.Sin512((ang << 7) / self->stoodPos) >> 9) + self->position.y;60RSDK.DrawSprite(&self->animator, &drawPos, false);61drawPos.x += 0x100000;62ang += 0x100000;63}64id = size;6566drawPos.y = self->bridgeDepth + self->position.y;67RSDK.DrawSprite(&self->animator, &drawPos, false);68drawPos.x += 0x100000;69++id;7071ang = 0x80000;72int32 divisor = self->endPos - self->startPos - self->stoodPos;73drawPos.x = self->endPos - 0x80000;74for (; id < self->length; ++id) {75drawPos.y = (self->bridgeDepth * RSDK.Sin512((ang << 7) / divisor) >> 9) + self->position.y;76RSDK.DrawSprite(&self->animator, &drawPos, false);77drawPos.x -= 0x100000;78ang += 0x100000;79}80}8182void Bridge_Create(void *data)83{84RSDK_THIS(Bridge);85self->visible = true;86++self->length;87self->drawGroup = Zone->objectDrawGroup[0];88self->active = ACTIVE_BOUNDS;89int32 len = self->length << 19;90self->startPos = self->position.x - len;91self->endPos = len + self->position.x;92self->updateRange.x = len;93self->updateRange.y = 0x800000;94self->stoodEntity = (Entity *)-1;95self->burnOffset = 0xFF;96RSDK.SetSpriteAnimation(Bridge->aniFrames, 0, &self->animator, true, 0);97}9899void Bridge_StageLoad(void)100{101if (RSDK.CheckSceneFolder("GHZ"))102Bridge->aniFrames = RSDK.LoadSpriteAnimation("GHZ/Bridge.bin", SCOPE_STAGE);103if (RSDK.CheckSceneFolder("HCZ"))104Bridge->aniFrames = RSDK.LoadSpriteAnimation("HCZ/Bridge.bin", SCOPE_STAGE);105if (RSDK.CheckSceneFolder("LRZ1"))106Bridge->aniFrames = RSDK.LoadSpriteAnimation("LRZ1/Bridge.bin", SCOPE_STAGE);107}108109void Bridge_Burn(int32 offset)110{111RSDK_THIS(Bridge);112113int32 size = self->stoodPos >> 20;114int32 spawnX = self->startPos + 0x80000;115int32 off = -offset;116int32 ang = 0x80000;117for (int32 i = 0; i < size; ++i) {118int32 sine = RSDK.Sin512((ang << 7) / self->stoodPos);119CREATE_ENTITY(BurningLog, INT_TO_VOID(8 * abs(off++) + 16), spawnX, (self->bridgeDepth * sine >> 9) + self->position.y);120ang += 0x100000;121spawnX += 0x100000;122}123124int32 id = size;125CREATE_ENTITY(BurningLog, INT_TO_VOID(8 * abs(id++ - offset) + 16), spawnX, self->bridgeDepth + self->position.y);126127spawnX = self->endPos - 0x80000;128int32 divisor = self->endPos - self->startPos - self->stoodPos;129ang = 0x80000;130if (id < self->length) {131off = offset - id;132for (; id < self->length; ++id, --off) {133int32 spawnY = (self->bridgeDepth * RSDK.Sin512((ang << 7) / divisor) >> 9) + self->position.y;134CREATE_ENTITY(BurningLog, INT_TO_VOID(8 * abs(self->length - abs(off) - offset) + 16), spawnX, spawnY);135ang += 0x100000;136spawnX -= 0x100000;137}138}139destroyEntity(self);140}141142bool32 Bridge_HandleCollisions(void *e, EntityBridge *self, Hitbox *entityHitbox, bool32 updateVars, bool32 isPlayer)143{144EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);145146// use EntityPlayer as the type so we can access player variables if needed147// if `isPlayer` is false, then only base entity variables will be accessed148EntityPlayer *entity = (EntityPlayer *)e;149150bool32 bridgeCollided = false;151152if (entity->position.x > self->startPos && entity->position.x < self->endPos) {153if (entity != self->stoodEntity) {154if (updateVars && !self->stoodEntityCount)155self->stoodPos = entity->position.x - self->startPos;156157if (entity->velocity.y >= 0) {158Hitbox hitboxBridge;159hitboxBridge.left = -0x400;160hitboxBridge.right = 0x400;161162int32 divisor = 0;163int32 ang = 0;164if (entity->position.x - self->startPos <= self->stoodPos) {165divisor = self->stoodPos;166ang = (entity->position.x - self->startPos) << 7;167}168else {169divisor = self->endPos - self->startPos - self->stoodPos;170ang = (self->endPos - entity->position.x) << 7;171}172173int32 hitY = (self->bridgeDepth * RSDK.Sin512(ang / divisor) >> 9) - 0x80000;174if (entity->velocity.y >= 0x8000) {175hitboxBridge.top = (hitY >> 16);176hitboxBridge.bottom = hitboxBridge.top + 8;177}178else {179hitboxBridge.bottom = (hitY >> 16);180hitboxBridge.top = hitboxBridge.bottom - 8;181}182183bool32 collided = false;184if (isPlayer)185collided = Player_CheckCollisionTouch(entity, self, &hitboxBridge);186else187collided = RSDK.CheckObjectCollisionTouchBox(self, &hitboxBridge, entity, entityHitbox);188189if (collided) {190entity->position.y = hitY + self->position.y - (entityHitbox->bottom << 16);191192if (updateVars) {193++self->stoodEntityCount;194if (!entity->onGround) {195entity->onGround = true;196entity->groundVel = entity->velocity.x;197}198199if (isPlayer)200entity->flailing = false;201202if (entity == player1) {203if (self->stoodEntity != (void *)-1 && self->stoodEntity != (void *)-2) {204int32 distance = self->endPos - self->startPos;205self->stoodPos = entity->position.x - self->startPos;206self->depression = (distance >> 13) * RSDK.Sin512((self->stoodPos >> 8) / (distance >> 16));207self->bridgeDepth = (self->depression * self->timer) >> 7;208}209210self->stoodEntity = entity;211if (entity->velocity.y < 0x10000)212self->timer = 0x80;213}214else {215if (self->stoodEntity == (void *)-1) {216self->stoodEntity = entity;217if (entity->velocity.y < 0x10000)218self->timer = 0x80;219}220221if (self->stoodEntity == (void *)-2)222self->stoodEntity = entity;223}224225if (!entity->onGround) {226entity->onGround = true;227entity->groundVel = entity->velocity.x;228}229230entity->velocity.y = 0;231232if (isPlayer) {233if (entity->shield == SHIELD_FIRE && self->burnable)234Bridge_Burn((entity->position.x - self->startPos) >> 20);235}236}237238bridgeCollided = true;239}240}241}242else if (updateVars) {243self->stoodPos = entity->position.x - self->startPos;244int32 distance = (self->endPos - self->startPos);245self->depression = RSDK.Sin512((self->stoodPos >> 8) / (distance >> 16)) * (distance >> 13);246247if (entity->position.y > self->position.y - 0x300000) {248if (entity->velocity.y >= 0) {249++self->stoodEntityCount;250entity->position.y = self->position.y + self->bridgeDepth - ((entityHitbox->bottom + 8) << 16);251252if (!entity->onGround) {253entity->onGround = true;254entity->groundVel = entity->velocity.x;255}256257entity->velocity.y = 0;258if (isPlayer) {259entity->flailing = false;260if (entity->shield == SHIELD_FIRE && self->burnable)261Bridge_Burn((entity->position.x - self->startPos) >> 20);262}263264bridgeCollided = true;265}266else {267self->stoodEntity = (void *)-2;268}269}270}271}272else if (entity == self->stoodEntity) {273self->timer = 32;274self->stoodEntity = (void *)-2;275}276277return bridgeCollided;278}279280#if GAME_INCLUDE_EDITOR281void Bridge_EditorDraw(void)282{283RSDK_THIS(Bridge);284int32 length = self->length++;285286int32 len = self->length << 19;287self->startPos = self->position.x - len;288self->endPos = len + self->position.x;289self->updateRange.x = len;290self->updateRange.y = 0x800000;291292Bridge_Draw();293294self->length = length;295}296297void Bridge_EditorLoad(void)298{299if (RSDK.CheckSceneFolder("GHZ"))300Bridge->aniFrames = RSDK.LoadSpriteAnimation("GHZ/Bridge.bin", SCOPE_STAGE);301if (RSDK.CheckSceneFolder("HCZ"))302Bridge->aniFrames = RSDK.LoadSpriteAnimation("HCZ/Bridge.bin", SCOPE_STAGE);303if (RSDK.CheckSceneFolder("LRZ1"))304Bridge->aniFrames = RSDK.LoadSpriteAnimation("LRZ1/Bridge.bin", SCOPE_STAGE);305}306#endif307308void Bridge_Serialize(void)309{310RSDK_EDITABLE_VAR(Bridge, VAR_UINT8, length);311RSDK_EDITABLE_VAR(Bridge, VAR_BOOL, burnable);312}313314315