Path: blob/master/SonicMania/Objects/HCZ/Gondola.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Gondola Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectGondola *Gondola;1011void Gondola_Update(void)12{13RSDK_THIS(Gondola);1415self->collisionOffset.x = -self->drawPos.x;16self->collisionOffset.y = -self->drawPos.y;17self->centerPos.x += self->velocity.x;18self->centerPos.y += self->velocity.y;1920if (self->activePlayers) {21if (self->stoodAngle < self->maxStoodAngle)22self->stoodAngle += 4;23}24else {25if (self->stoodAngle > 0)26self->stoodAngle -= 4;27}2829Gondola_HandleWaterFloating();30Gondola_HandleTilting();31Gondola_HandleMoveVelocity();3233if (self->onGround && self->velocity.y > 0)34self->velocity.y = 0;3536self->drawPos.x = self->centerPos.x + (RSDK.Sin256(self->stoodAngle) << 10);37self->drawPos.y = self->centerPos.y + (RSDK.Sin512(self->floatAngle * 2) * 0x180);3839if (!self->onGround)40++self->floatAngle;4142self->position.x = self->drawPos.x & 0xFFFF0000;43self->position.y = self->drawPos.y & 0xFFFF0000;44Gondola_HandleTileCollisions();4546self->drawGroup = self->onGround ? Zone->objectDrawGroup[0] : Zone->playerDrawGroup[0];47self->collisionOffset.x += self->position.x;48self->collisionOffset.y += self->position.y;49Gondola_HandlePlayerInteractions();50}5152void Gondola_LateUpdate(void) {}5354void Gondola_StaticUpdate(void) {}5556void Gondola_Draw(void)57{58RSDK_THIS(Gondola);5960RSDK.DrawSprite(&self->animator, NULL, false);61}6263void Gondola_Create(void *data)64{65RSDK_THIS(Gondola);6667self->active = ACTIVE_NORMAL;68self->drawGroup = Zone->playerDrawGroup[1];6970self->startPos = self->position;71self->drawPos = self->position;72self->centerPos = self->position;7374self->visible = true;75self->drawFX = FX_ROTATE | FX_FLIP;76self->updateRange.x = 0x800000;77self->updateRange.y = 0x800000;78self->drawGroup = Zone->playerDrawGroup[0];7980self->hitbox.left = -76;81self->hitbox.top = -12;82self->hitbox.right = 76;83self->hitbox.bottom = 4;8485RSDK.SetSpriteAnimation(Gondola->aniFrames, 0, &self->animator, true, 0);86}8788void Gondola_StageLoad(void) { Gondola->aniFrames = RSDK.LoadSpriteAnimation("HCZ/Gondola.bin", SCOPE_STAGE); }8990int32 Gondola_GetWaterLevel(void)91{92RSDK_THIS(Gondola);9394if (self->position.y < Water->waterLevel) {95foreach_active(Water, water)96{97if (water->type == WATER_POOL && RSDK.CheckObjectCollisionTouchBox(water, &water->hitbox, self, &Water->hitboxPoint)) {98return water->position.y + (water->hitbox.top << 16);99}100}101}102103return Water->waterLevel;104}105106void Gondola_HandleWaterFloating(void)107{108RSDK_THIS(Gondola);109110int32 waterLevel = Gondola_GetWaterLevel();111112self->waterDistance = self->centerPos.y - waterLevel;113self->waterInRange = abs(self->centerPos.y - waterLevel) < 0x40000;114115if (abs(self->centerPos.y - waterLevel) >= 0x40000) {116if (self->centerPos.y - waterLevel < -0x80000) {117self->velocity.y += 0x3800;118}119else {120if (self->centerPos.y <= waterLevel)121self->velocity.y = 0;122else123self->velocity.y = -Water->waterMoveSpeed;124}125}126else {127if (Water->targetWaterLevel > Water->waterLevel) {128self->velocity.y = Water->waterMoveSpeed;129}130else {131if (self->centerPos.y <= waterLevel)132self->velocity.y = 0;133else134self->velocity.y = -Water->waterMoveSpeed;135}136}137138if (self->minY) {139if (self->centerPos.y <= self->minY << 16) {140self->centerPos.y = self->minY << 16;141142if (self->velocity.y < 0)143self->velocity.y = 0;144}145}146147if (self->maxY) {148if (self->centerPos.y >= self->maxY << 16) {149self->centerPos.y = self->maxY << 16;150151if (self->velocity.y > 0)152self->velocity.y = 0;153}154}155}156157void Gondola_HandleTilting(void)158{159RSDK_THIS(Gondola);160161int32 targetRotation = 0;162163if (!self->onGround) {164foreach_active(Player, player)165{166if (((1 << RSDK.GetEntitySlot(player)) & self->activePlayers))167targetRotation += (player->position.x - self->centerPos.x) >> 21;168}169}170171if (self->rotation < targetRotation)172self->rotation++;173else if (self->rotation > targetRotation)174self->rotation--;175}176177void Gondola_HandleMoveVelocity(void)178{179RSDK_THIS(Gondola);180181if (!self->onGround) {182foreach_active(Player, player)183{184int32 playerID = RSDK.GetEntitySlot(player);185186if (!player->sidekick) {187if (((1 << playerID) & self->activePlayers)) {188self->velocity.x = (player->position.x - self->centerPos.x) >> 5;189}190else {191if (self->velocity.x > 0) {192self->velocity.x -= 0x200;193194if (self->velocity.x < 0)195self->velocity.x = 0;196}197else if (self->velocity.x < 0) {198self->velocity.x += 0x200;199200if (self->velocity.x > 0)201self->velocity.x = 0;202}203}204}205}206}207}208209void Gondola_HandleTileCollisions(void)210{211RSDK_THIS(Gondola);212213if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, self->hitbox.bottom << 16, true)) {214self->maxStoodAngle = 0;215216if (self->velocity.y > 0)217self->velocity.y = 0;218219self->onGround = true;220}221else {222self->maxStoodAngle = 64;223self->onGround = false;224}225226if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_ROOF, 0, 0, self->hitbox.top << 16, true) && self->velocity.y < 0) {227self->velocity.y = 0;228}229230// RWall = Right side of the wall, so this would collide with the *left* side of the boat231if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_RWALL, 0, (self->hitbox.left - 8) << 16, 0, true)) {232if (self->velocity.x < 0)233self->velocity.x = 0;234235self->stoppedL = true;236}237else {238self->stoppedL = false;239}240241// LWall = Left side of the wall, so this would collide with the *right* side of the boat242if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_LWALL, 0, (self->hitbox.right + 8) << 16, 0, true)) {243if (self->velocity.x > 0)244self->velocity.x = 0;245246self->stoppedR = true;247}248else {249self->stoppedR = false;250}251252self->drawPos.x = self->position.x;253self->drawPos.y = self->position.y;254}255256void Gondola_HandlePlayerInteractions(void)257{258RSDK_THIS(Gondola);259260if (self->onGround) {261self->activePlayers = 0;262}263else {264foreach_active(Player, player)265{266int32 playerID = RSDK.GetEntitySlot(player);267268if (((1 << playerID) & self->activePlayers)) {269player->position.x += self->collisionOffset.x;270player->position.y += self->collisionOffset.y + 0x10000;271272if (!player->sidekick && !Gondola->hasAchievement) {273if (!Gondola->taggedBoatIDs[self->boatID]) {274Gondola->taggedBoatIDs[self->boatID] = true;275276if (Gondola->taggedBoatIDs[0] && Gondola->taggedBoatIDs[1] && Gondola->taggedBoatIDs[2]) {277API_UnlockAchievement(&achievementList[ACH_HCZ]);278Gondola->hasAchievement = true;279}280}281}282}283284if (Player_CheckCollisionPlatform(player, self, &self->hitbox))285self->activePlayers |= 1 << playerID;286else287self->activePlayers &= ~(1 << playerID);288}289}290}291292#if GAME_INCLUDE_EDITOR293void Gondola_EditorDraw(void) { Gondola_Draw(); }294295void Gondola_EditorLoad(void)296{297Gondola->aniFrames = RSDK.LoadSpriteAnimation("HCZ/Gondola.bin", SCOPE_STAGE);298299RSDK_ACTIVE_VAR(Gondola, direction);300RSDK_ENUM_VAR("No Flip", FLIP_NONE);301RSDK_ENUM_VAR("Flip X", FLIP_X);302303RSDK_ACTIVE_VAR(Gondola, boatID);304RSDK_ENUM_VAR("Boat 1", 0);305RSDK_ENUM_VAR("Boat 2", 1);306RSDK_ENUM_VAR("Boat 3", 2);307}308#endif309310void Gondola_Serialize(void)311{312RSDK_EDITABLE_VAR(Gondola, VAR_UINT8, direction);313RSDK_EDITABLE_VAR(Gondola, VAR_ENUM, minY);314RSDK_EDITABLE_VAR(Gondola, VAR_ENUM, maxY);315RSDK_EDITABLE_VAR(Gondola, VAR_UINT8, boatID);316}317318319