Path: blob/master/SonicMania/Objects/LRZ/LRZConvItem.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: LRZConvItem Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectLRZConvItem *LRZConvItem;1011void LRZConvItem_Update(void)12{13RSDK_THIS(LRZConvItem);1415StateMachine_Run(self->state);1617RSDK.ProcessAnimation(&self->animator);18}1920void LRZConvItem_LateUpdate(void) {}2122void LRZConvItem_StaticUpdate(void) {}2324void LRZConvItem_Draw(void)25{26RSDK_THIS(LRZConvItem);2728RSDK.DrawSprite(&self->animator, NULL, false);29}3031void LRZConvItem_Create(void *data)32{33RSDK_THIS(LRZConvItem);3435if (data)36self->type = VOID_TO_INT(data);3738self->active = ACTIVE_BOUNDS;39self->drawGroup = Zone->objectDrawGroup[0];40self->startPos = self->position;41self->visible = true;42self->drawFX = FX_FLIP;43self->updateRange.x = 0x800000;44self->updateRange.y = 0x800000;4546RSDK.SetSpriteAnimation(LRZConvItem->aniFrames, self->type, &self->animator, true, 0);4748if (!SceneInfo->inEditor) {49switch (self->type) {50case LRZCONVITEM_ROCK: self->state = LRZConvItem_State_Rock; break;51case LRZCONVITEM_SPIKEBALL: self->state = LRZConvItem_State_SpikeBall; break;52}53}54}5556void LRZConvItem_StageLoad(void)57{58LRZConvItem->aniFrames = RSDK.LoadSpriteAnimation("LRZ2/LRZConvItem.bin", SCOPE_STAGE);5960LRZConvItem_SetupHitboxes();6162LRZConvItem->sfxSizzle = RSDK.GetSfx("LRZ/Sizzle.wav");63}6465void LRZConvItem_SetupHitboxes(void)66{67LRZConvItem->hitboxRock.left = -16;68LRZConvItem->hitboxRock.top = -16;69LRZConvItem->hitboxRock.right = 16;70LRZConvItem->hitboxRock.bottom = 16;7172LRZConvItem->hitboxSpikeball.left = -10;73LRZConvItem->hitboxSpikeball.top = -10;74LRZConvItem->hitboxSpikeball.right = 10;75LRZConvItem->hitboxSpikeball.bottom = 10;76}7778Vector2 LRZConvItem_HandleLRZConvPhys(void *e)79{80EntityLRZConvItem *entity = (EntityLRZConvItem *)e;8182Vector2 moveOffset;83moveOffset.x = 0;84moveOffset.y = 0;85if (RSDK.CheckSceneFolder("LRZ2")) {86int32 storeX = entity->position.x;87int32 storeY = entity->position.y;8889Hitbox hitbox;90hitbox.left = 0;91hitbox.top = 0;92hitbox.right = 0;93hitbox.bottom = 0;9495if (entity->classID == LRZConvItem->classID)96hitbox = LRZConvItem->hitboxRock;97else if (entity->classID == ItemBox->classID)98hitbox = ItemBox->hitboxItemBox;99else if (entity->classID == Iwamodoki->classID)100hitbox = Iwamodoki->hitboxBadnik;101102// Handle Object-Based Conveyor interactions103bool32 conveyorCollided = false;104if (LRZConveyor) {105foreach_active(LRZConveyor, conveyor)106{107int32 moveX = (conveyor->speed << 14) * (2 * (conveyor->direction == FLIP_X) - 1);108if (LRZConveyor_HandlePlayerCollisions(conveyor, entity, &hitbox) == C_TOP) {109conveyorCollided = true;110if (conveyor->off) {111entity->velocity.x = 0;112}113else {114entity->position.y += 0x10000;115entity->active = ACTIVE_NORMAL;116entity->velocity.x = moveX;117}118}119}120}121122// Try to collide with the floor123int32 prevY = entity->position.y;124bool32 tileCollided = RSDK.ObjectTileGrip(entity, Zone->collisionLayers, CMODE_FLOOR, 0, 0, hitbox.bottom << 16, 4);125if (!tileCollided) {126if (!RSDK.ObjectTileGrip(entity, Zone->collisionLayers, CMODE_FLOOR, 0, (hitbox.right << 16) - 0x10000, hitbox.bottom << 16, 4)127|| !RSDK.ObjectTileGrip(entity, Zone->collisionLayers, CMODE_FLOOR, 0, (hitbox.right << 16) - 0x10000, hitbox.bottom << 16, 4)) {128if (RSDK.ObjectTileGrip(entity, Zone->collisionLayers, CMODE_FLOOR, 0, (hitbox.left + 1) << 16, hitbox.bottom << 16, 4)) {129tileCollided =130RSDK.ObjectTileGrip(entity, Zone->collisionLayers, CMODE_FLOOR, 0, (hitbox.left + 1) << 16, hitbox.bottom << 16, 4);131}132}133}134135bool32 prevOnGround = entity->onGround;136entity->onGround = false;137if (tileCollided || conveyorCollided)138entity->onGround = true;139140int32 tileInfo = 0;141uint8 behaviour = LRZ2_TFLAGS_NORMAL;142143// try to grab tile info & behaviour for tile-based conveyor interactions144LRZ2Setup_GetTileInfo(entity->position.x, entity->position.y + (hitbox.bottom << 16), 0, 0, entity->collisionPlane, &tileInfo, &behaviour);145if (behaviour == LRZ2_TFLAGS_NORMAL) {146LRZ2Setup_GetTileInfo(entity->position.x + (hitbox.right << 16), entity->position.y + (hitbox.bottom << 16), 0, 0, entity->collisionPlane,147&tileInfo, &behaviour);148}149if (behaviour == LRZ2_TFLAGS_NORMAL) {150LRZ2Setup_GetTileInfo(entity->position.x + (hitbox.left << 16), entity->position.y + (hitbox.bottom << 16), 0, 0, entity->collisionPlane,151&tileInfo, &behaviour);152}153if (behaviour == LRZ2_TFLAGS_NORMAL) {154LRZ2Setup_GetTileInfo(entity->position.x, entity->position.y + (hitbox.bottom << 16), 0, 0, entity->collisionPlane, &tileInfo,155&behaviour);156}157158bool32 lavaCollided = false;159bool32 tileConveyorCollided = false;160switch (behaviour) {161case LRZ2_TFLAGS_NORMAL: break;162163case LRZ2_TFLAGS_LAVA:164entity->active = ACTIVE_NORMAL;165166if (prevY > entity->position.y)167entity->position.y = prevY;168169lavaCollided = true;170break;171172case LRZ2_TFLAGS_CONVEYOR_L:173tileConveyorCollided = true;174entity->active = ACTIVE_NORMAL;175176if (entity->onGround) {177if (LRZ2Setup->conveyorOff)178entity->velocity.x = 0;179else180entity->velocity.x = (2 * ((((tileInfo & 0x400) != 0) ^ LRZ2Setup->conveyorDir) != 0) - 1) << 17;181}182break;183184case LRZ2_TFLAGS_CONVEYOR_R:185tileConveyorCollided = true;186entity->active = ACTIVE_NORMAL;187188if (entity->onGround) {189if (LRZ2Setup->conveyorOff)190entity->velocity.x = 0;191else192entity->velocity.x = (2 * ((((tileInfo & 0x400) != 0) ^ LRZ2Setup->conveyorDir) != 1) - 1) << 17;193}194break;195}196197if (tileCollided) {198if ((lavaCollided ^ 1) && (abs(entity->velocity.x) > 0) && (tileConveyorCollided ^ 1))199entity->velocity.x = 0;200}201202// Apply Gravity203if (entity->onGround)204entity->velocity.y = 0;205else206entity->velocity.y += 0x3800;207208bool32 wallCollided = false;209if (entity->velocity.x < 0)210wallCollided = RSDK.ObjectTileCollision(entity, Zone->collisionLayers, CMODE_FLOOR, 0, hitbox.left << 16, hitbox.top << 16, false);211else if (entity->velocity.x > 0)212wallCollided = RSDK.ObjectTileCollision(entity, Zone->collisionLayers, CMODE_FLOOR, 0, hitbox.right << 16, hitbox.top << 16, false);213214// Apply Lava Physics215if (lavaCollided) {216if (!prevOnGround && entity->onGround) {217RSDK.PlaySfx(LRZConvItem->sfxSizzle, false, 0xFF);218entity->velocity.x >>= 1;219}220221if (entity->classID != LRZConvItem->classID || entity->type) {222entity->velocity.y = 0x4000;223}224else {225if (!entity->velocity.x)226entity->velocity.y = 0x4000;227else228entity->velocity.y = 0;229}230}231232if (wallCollided)233entity->velocity.x = 0;234235entity->position.x += entity->velocity.x;236entity->position.y += entity->velocity.y;237moveOffset.x = entity->position.x - storeX;238moveOffset.y = entity->position.y - storeY;239240if (lavaCollided && !RSDK.CheckOnScreen(entity, &entity->updateRange))241destroyEntity(entity);242}243return moveOffset;244}245246void LRZConvItem_State_Rock(void)247{248RSDK_THIS(LRZConvItem);249250int32 x = self->position.x;251int32 y = self->position.y;252Vector2 moveOffset = LRZConvItem_HandleLRZConvPhys(self);253254int32 storeX = self->position.x;255int32 storeY = self->position.y;256self->position.x = x;257self->position.y = y;258259foreach_active(Player, player)260{261switch (Player_CheckCollisionBox(player, self, &LRZConvItem->hitboxRock)) {262case C_TOP:263player->position.x += moveOffset.x;264player->position.y += moveOffset.y;265if (moveOffset.y <= 0)266player->collisionFlagV |= 1;267break;268269case C_LEFT: player->collisionFlagH |= 1; break;270case C_RIGHT: player->collisionFlagH |= 2; break;271272case C_BOTTOM:273if (moveOffset.y >= 0)274player->collisionFlagV |= 2;275break;276277default: break;278}279}280281self->position.x = storeX;282self->position.y = storeY;283}284285void LRZConvItem_State_SpikeBall(void)286{287RSDK_THIS(LRZConvItem);288289LRZConvItem_HandleLRZConvPhys(self);290291foreach_active(Player, player)292{293if (Player_CheckCollisionTouch(player, self, &LRZConvItem->hitboxSpikeball)) {294#if MANIA_USE_PLUS295if (!Player_CheckMightyUnspin(player, 0x400, true, &player->uncurlTimer))296#endif297Player_Hurt(player, self);298}299}300}301302#if GAME_INCLUDE_EDITOR303void LRZConvItem_EditorDraw(void)304{305RSDK_THIS(LRZConvItem);306307RSDK.SetSpriteAnimation(LRZConvItem->aniFrames, self->type, &self->animator, true, 0);308309LRZConvItem_Draw();310}311312void LRZConvItem_EditorLoad(void)313{314LRZConvItem->aniFrames = RSDK.LoadSpriteAnimation("LRZ2/LRZConvItem.bin", SCOPE_STAGE);315316RSDK_ACTIVE_VAR(LRZConvItem, type);317RSDK_ENUM_VAR("Rock", LRZCONVITEM_ROCK);318RSDK_ENUM_VAR("Spike Ball", LRZCONVITEM_SPIKEBALL);319}320#endif321322void LRZConvItem_Serialize(void) { RSDK_EDITABLE_VAR(LRZConvItem, VAR_UINT8, type); }323324325