Path: blob/master/SonicMania/Objects/LRZ/LRZConveyor.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: LRZConveyor Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectLRZConveyor *LRZConveyor;1011void LRZConveyor_Update(void)12{13RSDK_THIS(LRZConveyor);1415if (self->globalControl) {16self->off = LRZ2Setup->conveyorOff;17self->direction = self->startDir ^ LRZ2Setup->conveyorDir;18}19else {20LRZConveyor_HandleBehaviour();21}2223LRZConveyor_HandlePlayerInteractions();2425if (!self->off) {26RSDK.ProcessAnimation(&self->wheelAnimator);27RSDK.ProcessAnimation(&self->smallWheelAnimator);28}29}3031void LRZConveyor_LateUpdate(void) {}3233void LRZConveyor_StaticUpdate(void) {}3435void LRZConveyor_Draw(void)36{37LRZConveyor_DrawConveyorLines();38LRZConveyor_DrawWheels();39}4041void LRZConveyor_Create(void *data)42{43RSDK_THIS(LRZConveyor);4445self->active = ACTIVE_BOUNDS;46self->drawGroup = Zone->objectDrawGroup[0];47self->startPos = self->position;48self->updateRange.x = (self->length + 0x80) << 16;49self->updateRange.y = (self->length * (self->slope << 8)) + 0x800000;50self->visible = true;51self->drawFX = FX_FLIP;52self->isOff = self->off;53self->startDir = self->direction;5455if (SceneInfo->inEditor) {56if (!self->speed)57self->speed = 8;58}59else {60self->speed = abs(self->speed);61self->taggedButton = LRZ2Setup_SetupTagLink(self->buttonTag, (Entity *)self);62}6364self->hitbox.left = -8;65self->hitbox.top = -8;66self->hitbox.right = 8;67self->hitbox.bottom = 8;6869RSDK.SetSpriteAnimation(LRZConveyor->aniFrames, 0, &self->wheelAnimator, true, 0);70RSDK.SetSpriteAnimation(LRZConveyor->aniFrames, 1, &self->smallWheelAnimator, true, 0);71}7273void LRZConveyor_StageLoad(void)74{75LRZConveyor->aniFrames = RSDK.LoadSpriteAnimation("LRZ2/LRZConveyor.bin", SCOPE_STAGE);7677color lineColors[] = { 0x225BDD, 0x429AFD, 0x51DEFF, 0xAFFDF0 };78for (int32 i = 0; i < 0x40; ++i) LRZConveyor->lineColors[i] = lineColors[i & 3];79}8081void LRZConveyor_HandleBehaviour(void)82{83RSDK_THIS(LRZConveyor);8485if (self->buttonTag && self->taggedButton) {86switch (self->buttonBehavior) {87case LRZCONVEYOR_BEHAVIOR_CHANGEACTIVE:88if (self->taggedButton->activated)89self->off = self->isOff == 0;90break;9192case LRZCONVEYOR_BEHAVIOR_CHANGEACTIVE_TOGGLE: self->off = self->taggedButton->toggled ^ self->isOff; break;9394case LRZCONVEYOR_BEHAVIOR_CHANGEDIR:95if (self->taggedButton->activated)96self->direction = self->startDir == FLIP_NONE;97break;9899case LRZCONVEYOR_BEHAVIOR_CHANGEDIR_TOGGLE: self->direction = self->startDir ^ self->taggedButton->toggled; break;100101default: break;102}103}104}105106void LRZConveyor_HandlePlayerInteractions(void)107{108RSDK_THIS(LRZConveyor);109110int32 velX = (self->speed << 14) * (2 * (self->direction == FLIP_X) - 1);111112foreach_active(Player, player)113{114int32 side = LRZConveyor_HandlePlayerCollisions(self, player, NULL);115if (side == C_TOP && !self->off) {116if (player->onGround)117player->position.y += 0x10000;118else119player->velocity.x = velX;120121player->position.x += velX;122}123else if ((side == C_LEFT || side == C_RIGHT) && !self->off && !player->onGround) {124player->velocity.x = velX;125}126}127}128129int32 LRZConveyor_HandlePlayerCollisions(EntityLRZConveyor *conveyor, void *p, Hitbox *hitboxPtr)130{131EntityPlayer *player = (EntityPlayer *)p;132133Hitbox hitbox;134memset(&hitbox, 0, sizeof(hitbox));135136int32 distX = player->position.x - conveyor->position.x;137138hitbox.right = (conveyor->length + 32) >> 1;139hitbox.left = -(conveyor->length + 32) >> 1;140141if (abs(distX) >> 16 > conveyor->length >> 1) {142if (abs(distX) >> 16 <= (conveyor->length >> 1) + 16) {143int32 len = conveyor->length >> 1;144if (distX >= 0) {145if (distX >> 16 < len)146len = distX >> 16;147}148else {149len = -(conveyor->length >> 1);150if (distX >> 16 > len)151len = distX >> 16;152}153154int32 slope = (len * (conveyor->slope << 8)) >> 16;155int32 angle = RSDK.ATan2(distX - (conveyor->length << 15) * (((distX >> 31) & 0xFFFFFFFE) + 1), 0x100000);156hitbox.top = slope - (RSDK.Sin256(angle) >> 4);157hitbox.bottom = slope + (RSDK.Sin256(angle) >> 4);158}159}160else {161int32 slope = ((distX >> 16) * (conveyor->slope << 8)) >> 16;162hitbox.top = slope - 16;163hitbox.bottom = slope + 16;164}165166int32 storeDir = conveyor->direction;167conveyor->direction = FLIP_NONE;168169int32 side = C_NONE;170if (Player_CheckValidState(player)) {171side = Player_CheckCollisionBox(player, conveyor, &hitbox);172conveyor->direction = storeDir;173}174else {175Hitbox playerHitbox;176if (hitboxPtr) {177playerHitbox = *hitboxPtr;178}179else {180playerHitbox.left = -8;181playerHitbox.top = -8;182playerHitbox.right = 8;183playerHitbox.bottom = 8;184}185186side = MathHelpers_CheckBoxCollision(conveyor, &hitbox, player, &playerHitbox);187conveyor->direction = storeDir;188}189190return side;191}192193void LRZConveyor_DrawWheels(void)194{195RSDK_THIS(LRZConveyor);196197Vector2 drawPos = self->position;198drawPos.x -= self->length << 15;199drawPos.y -= (self->slope << 8) * (self->length >> 1);200RSDK.DrawSprite(&self->wheelAnimator, &drawPos, false);201202int32 len = self->length << 16;203if (len > 0x300000) {204int32 size = (len - 0x300001) / 0x300000 + 1;205206if ((len - 0x300001) / 0x300000 != -1) {207int32 incX = len / size;208209for (int32 i = 0; i < size; ++i) {210drawPos.x += incX;211drawPos.y += (incX >> 8) * self->slope;212RSDK.DrawSprite(&self->smallWheelAnimator, &drawPos, false);213}214}215}216217drawPos = self->position;218drawPos.x += self->length << 15;219drawPos.y += (self->slope << 8) * (self->length >> 1);220RSDK.DrawSprite(&self->wheelAnimator, &drawPos, false);221}222223void LRZConveyor_DrawDeformedLine(int32 startX, int32 startY, int32 endX, int32 endY, int32 offsetX, int32 offsetY, int32 len, color *color)224{225RSDK_THIS(LRZConveyor);226227int32 count = (self->length >> 1) + ((self->length & 1) != 0);228229int32 currentX = startX;230int32 currentY = startY;231for (int32 i = 0; i < count; ++i) {232int32 colorID = 0;233if (self->direction == FLIP_X)234colorID = count - len % count - 1;235else236colorID = len % count;237238if (!self->off)239colorID += Zone->timer >> 1;240241int32 prevX = currentX;242int32 prevY = currentY;243currentX += (endX - startX) / count;244currentY += (endY - startY) / count;245246uint32 lineColor = color ? *color : LRZConveyor->lineColors[(colorID % count) & 0x3F];247RSDK.DrawLine(prevX + offsetX, prevY + offsetY, currentX + offsetX, currentY + offsetY, lineColor, 0x7F, INK_NONE, false);248249++len;250}251}252253void LRZConveyor_DrawConveyorLines(void)254{255RSDK_THIS(LRZConveyor);256257color color = 0x51DEFF;258259int32 slopeLen = (self->length >> 1) * (self->slope << 8);260int32 startX = self->position.x - (self->length << 15);261int32 startY = slopeLen + self->position.y + 0xF0000;262int32 endX = self->position.x + (self->length << 15);263int32 endY = slopeLen + self->position.y - 0x100000;264int32 slopeY = self->position.y - slopeLen;265266int32 len = (self->length >> 1) + ((self->length & 1) != 0);267LRZConveyor_DrawDeformedLine(startX, slopeY - 0x100000, endX, endY, 0, 0, 0, NULL);268LRZConveyor_DrawDeformedLine(endX, startY, startX, slopeY + 0xF0000, 0, 0, len, NULL);269LRZConveyor_DrawDeformedLine(startX, slopeY - 0x100000, endX, endY, 0, 0x10000, 0, NULL);270LRZConveyor_DrawDeformedLine(endX, startY, startX, slopeY + 0xF0000, 0, -0x10000, len, NULL);271LRZConveyor_DrawDeformedLine(startX, slopeY - 0x100000, endX, endY, 0, 0x20000, 0, &color);272LRZConveyor_DrawDeformedLine(endX, startY, startX, slopeY + 0xF0000, 0, -0x20000, len, &color);273}274275#if GAME_INCLUDE_EDITOR276void LRZConveyor_EditorDraw(void)277{278RSDK_THIS(LRZConveyor);279280self->startPos = self->position;281self->updateRange.x = (self->length + 0x80) << 16;282self->updateRange.y = (self->length * (self->slope << 8)) + 0x800000;283self->startDir = self->direction;284285int32 speed = self->speed;286self->speed = abs(self->speed);287self->speed = speed;288289LRZConveyor_Draw();290291if (showGizmos()) {292self->taggedButton = LRZ2Setup_SetupTagLink(self->buttonTag, (Entity *)self);293294RSDK_DRAWING_OVERLAY(true);295if (self->taggedButton) {296DrawHelpers_DrawArrow(self->taggedButton->position.x, self->taggedButton->position.y, self->position.x, self->position.y, 0xFFFF00,297INK_NONE, 0xFF);298}299RSDK_DRAWING_OVERLAY(false);300}301}302303void LRZConveyor_EditorLoad(void)304{305LRZConveyor_StageLoad();306307RSDK_ACTIVE_VAR(LRZConveyor, direction);308RSDK_ENUM_VAR("Right", FLIP_NONE);309RSDK_ENUM_VAR("Left", FLIP_X);310311RSDK_ACTIVE_VAR(LRZConveyor, buttonBehavior);312RSDK_ENUM_VAR("Change Activated", LRZCONVEYOR_BEHAVIOR_CHANGEACTIVE);313RSDK_ENUM_VAR("Change Activated (Togglable)", LRZCONVEYOR_BEHAVIOR_CHANGEACTIVE_TOGGLE);314RSDK_ENUM_VAR("Change Direction", LRZCONVEYOR_BEHAVIOR_CHANGEDIR);315RSDK_ENUM_VAR("Change Direction (Togglable)", LRZCONVEYOR_BEHAVIOR_CHANGEDIR_TOGGLE);316}317#endif318319void LRZConveyor_Serialize(void)320{321RSDK_EDITABLE_VAR(LRZConveyor, VAR_UINT8, direction);322RSDK_EDITABLE_VAR(LRZConveyor, VAR_ENUM, slope);323RSDK_EDITABLE_VAR(LRZConveyor, VAR_UINT32, length);324RSDK_EDITABLE_VAR(LRZConveyor, VAR_ENUM, speed);325RSDK_EDITABLE_VAR(LRZConveyor, VAR_BOOL, globalControl);326RSDK_EDITABLE_VAR(LRZConveyor, VAR_ENUM, buttonTag);327RSDK_EDITABLE_VAR(LRZConveyor, VAR_UINT8, buttonBehavior);328RSDK_EDITABLE_VAR(LRZConveyor, VAR_BOOL, off);329}330331332