Path: blob/master/SonicMania/Objects/HCZ/HCZSpikeBall.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: HCZSpikeBall Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89// NOTE:10// This is a mania-fied version of the spikeballs present on S3 hang conveyors.11// This object is 100% fully functional.12// However, they're never placed in any stage, Making them unused.1314ObjectHCZSpikeBall *HCZSpikeBall;1516void HCZSpikeBall_Update(void)17{18HCZSpikeBall_HandleConveyorMovement();19HCZSpikeBall_HandlePlayerInteractions();20}2122void HCZSpikeBall_LateUpdate(void) {}2324void HCZSpikeBall_StaticUpdate(void) {}2526void HCZSpikeBall_Draw(void)27{28RSDK_THIS(HCZSpikeBall);2930RSDK.DrawSprite(&self->animator, NULL, false);31}3233void HCZSpikeBall_Create(void *data)34{35RSDK_THIS(HCZSpikeBall);3637self->active = ACTIVE_BOUNDS;38self->drawGroup = Zone->objectDrawGroup[0];39self->startPos = self->position;40self->visible = true;41self->drawFX = FX_FLIP;42self->updateRange.x = 0x800000;43self->updateRange.y = 0x800000;4445self->hitbox.left = -10;46self->hitbox.top = -10;47self->hitbox.right = 10;48self->hitbox.bottom = 10;4950HCZSpikeBall_HandleConveyorSetup();51RSDK.SetSpriteAnimation(HCZSpikeBall->aniFrames, 0, &self->animator, true, 1);52}5354void HCZSpikeBall_StageLoad(void) { HCZSpikeBall->aniFrames = RSDK.LoadSpriteAnimation("HCZ/Platform.bin", SCOPE_STAGE); }5556void HCZSpikeBall_HandleConveyorSetup(void)57{58RSDK_THIS(HCZSpikeBall);5960if (!SceneInfo->inEditor) {61foreach_all(HangConveyor, conveyor)62{63if (MathHelpers_PointInHitbox(conveyor->position.x, conveyor->position.y, self->position.x, self->position.y, conveyor->direction,64&conveyor->hitboxSpikeBallRange)) {65self->conveyor = conveyor;66self->updateRange = conveyor->updateRange;67foreach_break;68}69}7071if (self->conveyor)72HCZSpikeBall_LinkToConveyor();73}74}7576void HCZSpikeBall_LinkToConveyor(void)77{78RSDK_THIS(HCZSpikeBall);7980EntityHangConveyor *conveyor = self->conveyor;81if (conveyor) {82Hitbox hitboxTop, hitboxLeft, hitboxBottom, hitboxRight;8384int32 len = 0;85if (conveyor->length != -3)86len = (conveyor->length + 3) << 20;8788hitboxTop.top = -26;89hitboxTop.bottom = -16;90hitboxTop.right = len >> 17;91hitboxTop.left = -hitboxTop.right;9293hitboxLeft.left = conveyor->hitboxSpikeBallRange.left;94hitboxLeft.top = conveyor->hitboxSpikeBallRange.top;95hitboxLeft.right = -hitboxTop.right;96hitboxLeft.bottom = conveyor->hitboxSpikeBallRange.bottom;9798hitboxBottom.left = -(len >> 17);99hitboxBottom.top = 16;100hitboxBottom.right = len >> 17;101hitboxBottom.bottom = 26;102103hitboxRight.left = len >> 17;104hitboxRight.top = hitboxLeft.top;105hitboxRight.right = conveyor->hitboxSpikeBallRange.right;106hitboxRight.bottom = hitboxLeft.bottom;107108if (MathHelpers_PointInHitbox(conveyor->position.x, conveyor->position.y, self->position.x, self->position.y, conveyor->direction,109&hitboxTop)) {110int32 dist = conveyor->position.x - (len >> 1);111if (conveyor->direction == FLIP_NONE)112dist = conveyor->position.x + (len >> 1);113self->intervalOffset = abs(self->position.x - (self->position.x - dist)) / 0x15555;114}115else if (MathHelpers_PointInHitbox(conveyor->position.x, conveyor->position.y, self->position.x, self->position.y, conveyor->direction,116&hitboxLeft)) {117int32 dist = len / 0x15555;118int32 angle = 0x180;119if (conveyor->direction) {120dist = 2 * (len / 0x15555) + 51;121angle = 0x80;122}123124int32 atan = RSDK.ATan2(self->position.x - conveyor->position.x - (len >> 1), self->position.y - conveyor->position.y);125self->intervalOffset = (abs(angle - 2 * atan) / 5) + dist;126}127else if (MathHelpers_PointInHitbox(conveyor->position.x, conveyor->position.y, self->position.x, self->position.y, conveyor->direction,128&hitboxBottom)) {129int32 dist = (len >> 1) + conveyor->position.x;130if (conveyor->direction == FLIP_NONE)131dist = conveyor->position.x - (len >> 1);132self->intervalOffset = abs((self->position.x - dist)) / 0x15555 + (len / 0x15555) + 51;133}134else if (MathHelpers_PointInHitbox(conveyor->position.x, conveyor->position.y, self->position.x, self->position.y, conveyor->direction,135&hitboxRight)) {136int32 dist = len / 0x15555;137int32 angle = 0x180;138if (!conveyor->direction) {139dist = 2 * (len / 0x15555) + 51;140angle = 0x80;141}142143int32 atan = RSDK.ATan2(self->position.x - (len >> 1) + conveyor->position.x, self->position.y - conveyor->position.y);144self->intervalOffset = (abs(angle - 2 * atan) / 5) + dist;145}146else {147self->intervalOffset = 0;148}149}150}151152void HCZSpikeBall_HandlePlayerInteractions(void)153{154RSDK_THIS(HCZSpikeBall);155foreach_active(Player, player)156{157// Oversight(?) Note:158// Due to this object being unused, it didn't get updated with mighty collision checks159// It's not 100% certain that it would've, but since the rest of the game's spiked objects do, this one could've too160if (Player_CheckCollisionTouch(player, self, &self->hitbox))161Player_Hurt(player, self);162}163}164165void HCZSpikeBall_HandleConveyorMovement(void)166{167RSDK_THIS(HCZSpikeBall);168169if (self->conveyor) {170int32 len = 0;171if (self->conveyor->length != -3)172len = (self->conveyor->length + 3) << 20;173174int32 interval = (2 * len + 0x8A3AE6) / 0x15555;175int32 timer = (self->intervalOffset + Zone->timer) % interval;176int32 conveyX = self->conveyor->position.x;177int32 conveyY = self->conveyor->position.y;178179if (timer < len / 0x15555) {180if (self->conveyor->direction == FLIP_NONE)181self->position.x = conveyX + (len >> 1);182else183self->position.x = conveyX - (len >> 1);184185self->position.x += 0x15555 * timer * (2 * (self->conveyor->direction != FLIP_NONE) - 1);186self->position.y = conveyY - 0x160000;187}188else if (timer < (len / 0x15555) + 51) {189int32 angle = timer - (len / 0x15555);190if (self->conveyor->direction == FLIP_NONE)191self->position.x = conveyX - (len >> 1);192else193self->position.x = conveyX + (len >> 1);194195int32 mult = self->conveyor->direction == FLIP_NONE ? -5 : 5;196197self->position.y = conveyY;198self->position.x += 0xB00 * RSDK.Cos512(angle * mult + 0x180);199self->position.y += 0xB00 * RSDK.Sin512(angle * mult + 0x180);200}201else if (timer >= 2 * (len / 0x15555) + 51) {202int32 angle = -51 - 2 * (len / 0x15555) + timer;203if (self->conveyor->direction == FLIP_NONE)204self->position.x = conveyX + (len >> 1);205else206self->position.x = conveyX - (len >> 1);207208int32 mult = self->conveyor->direction == FLIP_NONE ? -5 : 5;209210self->position.y = conveyY;211self->position.x += 0xB00 * RSDK.Cos512(angle * mult + 0x80);212self->position.y += 0xB00 * RSDK.Sin512(angle * mult + 0x80);213}214else {215if (self->conveyor->direction == FLIP_NONE)216self->position.x = conveyX - (len >> 1);217else218self->position.x = conveyX + (len >> 1);219220self->position.x += 0x15555 * (-51 - (len / 0x15555) + timer) * (2 * (self->conveyor->direction == FLIP_NONE) - 1);221self->position.y = conveyY + 0x160000;222}223}224}225226#if GAME_INCLUDE_EDITOR227void HCZSpikeBall_EditorDraw(void) { HCZSpikeBall_Draw(); }228229void HCZSpikeBall_EditorLoad(void) { HCZSpikeBall->aniFrames = RSDK.LoadSpriteAnimation("HCZ/Platform.bin", SCOPE_STAGE); }230#endif231232void HCZSpikeBall_Serialize(void) {}233234235