Path: blob/master/SonicMania/Objects/PGZ/Ice.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Ice Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectIce *Ice;1011void Ice_Update(void)12{13RSDK_THIS(Ice);1415StateMachine_Run(self->state);16}1718void Ice_LateUpdate(void) {}1920void Ice_StaticUpdate(void)21{22for (int32 i = 0; i < Player->playerCount; ++i) {23if (Ice->playerTimers[i] > 0)24Ice->playerTimers[i]--;25}26}2728void Ice_Draw(void)29{30RSDK_THIS(Ice);3132StateMachine_Run(self->stateDraw);33}3435void Ice_Create(void *data)36{37RSDK_THIS(Ice);3839if (!SceneInfo->inEditor) {40self->drawFX = FX_FLIP;41self->drawGroup = Zone->playerDrawGroup[0] + 1;42self->visible = true;4344if (data) {45self->active = ACTIVE_NORMAL;4647switch (VOID_TO_INT(data)) {48case ICE_CHILD_PLAYER:49self->hitboxBlock.left = -24;50self->hitboxBlock.top = -24;51self->hitboxBlock.right = 24;52self->hitboxBlock.bottom = 24;5354RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_PLAYERBLOCK, &self->blockAnimator, true, 0);5556self->isPermanent = true;57self->state = Ice_State_PlayerBlock;58self->stateDraw = Ice_Draw_PlayerBlock;59break;6061case ICE_CHILD_PILLAR:62self->updateRange.x = 0x800000;63self->updateRange.y = 0x800000;6465self->hitboxBlock.left = -19;66self->hitboxBlock.top = -110;67self->hitboxBlock.right = 19;68self->hitboxBlock.bottom = 0;6970self->hitboxPlayerBlockCheck.left = -19;71self->hitboxPlayerBlockCheck.top = -110;72self->hitboxPlayerBlockCheck.right = 19;73self->hitboxPlayerBlockCheck.bottom = 0;7475self->glintTimer = 240;76self->alpha = 0x80;7778RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_PILLARBLOCK, &self->blockAnimator, true, 0);79RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_PILLARGLINT, &self->glintAnimator, true, 0);8081self->state = Ice_State_IceBlock;82self->stateDraw = Ice_Draw_Pillar;83break;84case ICE_CHILD_SHARD:85self->updateRange.x = 0x400000;86self->updateRange.y = 0x400000;8788RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_SHARD, &self->blockAnimator, true, 0);8990self->state = Ice_State_Shard;91self->stateDraw = Ice_Draw_Shard;92break;93}94}95else {96self->active = ACTIVE_BOUNDS;97self->updateRange.x = 0x800000;98self->updateRange.y = 0x800000;99100RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_ICEBLOCK, &self->blockAnimator, true, self->size);101switch (self->type) {102case ICE_BLOCK: RSDK.SetSpriteAnimation(-1, ICEANI_ICEBLOCK, &self->contentsAnimator, true, 0); break;103case ICE_1RING: RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_RINGS, &self->contentsAnimator, true, 0); break;104case ICE_3RINGS: RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_RINGS, &self->contentsAnimator, true, 1); break;105case ICE_5RINGS: RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_RINGS, &self->contentsAnimator, true, 2); break;106107case ICE_SPIKES:108self->subType = self->subType & 3;109RSDK.SetSpriteAnimation(Spikes->aniFrames, self->subType >> 1, &self->contentsAnimator, true, 0);110if (!self->size) {111// direction of the spikes, matches the spikes "type" variable112switch (self->subType) {113case 0:114self->contentsOffset.y = 0x40000;115self->subFlip = FLIP_NONE;116break;117118case 1:119self->contentsOffset.y = -0x40000;120self->subFlip = FLIP_Y;121break;122123case 2:124self->contentsOffset.x = -0x80000;125self->subFlip = FLIP_NONE;126break;127128case 3:129self->contentsOffset.x = 0x80000;130self->subFlip = FLIP_X;131break;132133default: break;134}135}136break;137138case ICE_SPRING:139// Ice Springs (0-2), Normal Springs (2-8)140if (self->subType >= 3)141RSDK.SetSpriteAnimation(Spring->aniFrames, (self->subType - 3), &self->contentsAnimator, true, 0);142else143RSDK.SetSpriteAnimation(IceSpring->aniFrames, self->subType, &self->contentsAnimator, true, 0);144145if (self->size) {146switch (self->subType) {147case 0:148case 3:149case 4:150self->contentsOffset.x = 0;151if (!(self->subFlip & FLIP_Y))152self->contentsOffset.y = 0x80000;153else154self->contentsOffset.y = -0x80000;155break;156157case 1:158case 5:159case 6:160self->contentsOffset.y = 0;161if (!(self->subFlip & FLIP_X))162self->contentsOffset.x = -0x80000;163else164self->contentsOffset.x = 0x80000;165break;166167case 2:168case 7:169case 8:170self->contentsOffset.x = 0;171if (!(self->subFlip & FLIP_Y))172self->contentsOffset.y = -0x10000;173else174self->contentsOffset.y = 0x10000;175break;176177default: break;178}179}180else {181switch (self->subType) {182case 0:183case 3:184case 4:185self->contentsOffset.x = 0;186if (!(self->subFlip & FLIP_Y))187self->contentsOffset.y = 0xC0000;188else189self->contentsOffset.y = -0xC0000;190break;191192case 1:193case 5:194case 6:195self->contentsOffset.y = 0;196if (!(self->subFlip & FLIP_X))197self->contentsOffset.x = -0x100000;198else199self->contentsOffset.x = 0x100000;200break;201202case 2:203case 7:204case 8:205if (!(self->subFlip & FLIP_X))206self->contentsOffset.x = -0x80000;207else208self->contentsOffset.x = 0x80000;209if (!(self->subFlip & FLIP_Y))210self->contentsOffset.y = 0x40000;211else212self->contentsOffset.y = -0x40000;213break;214215default: break;216}217}218break;219220case ICE_ITEMBOX_RINGS:221case ICE_ITEMBOX_BLUESHIELD:222case ICE_ITEMBOX_BUBBLESHIELD:223case ICE_ITEMBOX_FIRESHIELD:224case ICE_ITEMBOX_LIGHTNINGSHIELD:225case ICE_ITEMBOX_INVINCIBILITY:226case ICE_ITEMBOX_SNEAKERS:227case ICE_ITEMBOX_1UP:228case ICE_ITEMBOX_EGGMAN:229case ICE_ITEMBOX_HYPERRING:230case ICE_ITEMBOX_SWAP:231case ICE_ITEMBOX_RANDOM:232case ICE_ITEMBOX_SUPER:233default:234RSDK.SetSpriteAnimation(ItemBox->aniFrames, 0, &self->contentsAnimator, true, 0);235RSDK.SetSpriteAnimation(ItemBox->aniFrames, 2, &self->altContentsAnimator, true,236(self->type > ICE_ITEMBOX_1UP ? 2 : 0) + self->type - 5);237if (self->type != ICE_ITEMBOX_1UP) {238if (globals->gameMode == MODE_COMPETITION) {239if (globals->itemMode == ITEMS_RANDOM) {240self->type = ICE_ITEMBOX_EGGMAN;241self->altContentsAnimator.frameID = 13;242}243else if (globals->itemMode == ITEMS_TELEPORT) {244self->type = ICE_ITEMBOX_SWAP;245self->altContentsAnimator.frameID = 12;246}247}248}249else if (globals->gameMode != MODE_TIMEATTACK) {250switch (RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->characterID) {251default:252case ID_SONIC: break;253254case ID_TAILS: ++self->altContentsAnimator.frameID; break;255case ID_KNUCKLES: self->altContentsAnimator.frameID += 2; break;256#if MANIA_USE_PLUS257case ID_MIGHTY: self->altContentsAnimator.frameID += 8; break;258case ID_RAY: self->altContentsAnimator.frameID += 9; break;259#endif260}261262if (globals->gameMode == MODE_COMPETITION) {263if (globals->itemMode == ITEMS_RANDOM) {264self->type = ICE_ITEMBOX_RANDOM;265self->altContentsAnimator.frameID = 13;266}267else if (globals->itemMode == 2) {268self->type = ICE_ITEMBOX_SWAP;269self->altContentsAnimator.frameID = 12;270}271}272}273else {274self->type = ICE_ITEMBOX_RINGS;275self->altContentsAnimator.frameID = 0;276}277break;278}279280if (self->size == ICE_SIZE_SMALL) {281self->hitboxBlock.left = -16;282self->hitboxBlock.top = -16;283self->hitboxBlock.right = 16;284self->hitboxBlock.bottom = 16;285}286else if (!self->size) {287self->hitboxBlock.left = -24;288self->hitboxBlock.top = -20;289self->hitboxBlock.right = 24;290self->hitboxBlock.bottom = 20;291}292293self->hitboxFallCheck.left = self->hitboxBlock.left - 8;294self->hitboxFallCheck.top = self->hitboxBlock.top;295self->hitboxFallCheck.right = self->hitboxBlock.right + 8;296self->hitboxFallCheck.bottom = self->hitboxBlock.bottom + 8;297298self->hitboxPlayerBlockCheck.left = self->hitboxBlock.left;299self->hitboxPlayerBlockCheck.top = self->hitboxBlock.top - 8;300self->hitboxPlayerBlockCheck.right = self->hitboxBlock.right;301self->hitboxPlayerBlockCheck.bottom = self->hitboxBlock.bottom + 8;302303self->alpha = 0x180;304self->state = Ice_State_IceBlock;305self->stateDraw = Ice_Draw_IceBlock;306}307}308}309310void Ice_StageLoad(void)311{312if (RSDK.CheckSceneFolder("PSZ1")) // PGZ1 doesn't have ice anywhere, likely leftover from an earlier revision313Ice->aniFrames = RSDK.LoadSpriteAnimation("PSZ1/Ice.bin", SCOPE_STAGE);314else if (RSDK.CheckSceneFolder("PSZ2"))315Ice->aniFrames = RSDK.LoadSpriteAnimation("PSZ2/Ice.bin", SCOPE_STAGE);316317Ice->hitboxPlayerBlockInner.left = -15;318Ice->hitboxPlayerBlockInner.top = -24;319Ice->hitboxPlayerBlockInner.right = 15;320Ice->hitboxPlayerBlockInner.bottom = 24;321322Ice->hitboxPlayerBlockOuter.left = -16;323Ice->hitboxPlayerBlockOuter.top = -24;324Ice->hitboxPlayerBlockOuter.right = 16;325Ice->hitboxPlayerBlockOuter.bottom = 24;326327Ice->playerTimers[0] = 0;328Ice->playerTimers[1] = 0;329Ice->playerTimers[2] = 0;330Ice->playerTimers[3] = 0;331332Ice->sfxFreeze = RSDK.GetSfx("PSZ/Freeze.wav");333Ice->sfxLedgeBreak = RSDK.GetSfx("Stage/LedgeBreak.wav");334Ice->sfxWindowShatter = RSDK.GetSfx("Stage/WindowShatter.wav");335Ice->sfxStruggle = RSDK.GetSfx("PSZ/Struggle.wav");336337Zone->timeOverCallback = Ice_TimeOver_CheckFrozen;338Zone_AddVSSwapCallback(Ice_VSSwap_CheckFrozen);339}340341void Ice_VSSwap_CheckFrozen(void)342{343#if MANIA_USE_PLUS344EntityPlayer *player = RSDK_GET_ENTITY(Zone->swapPlayerID, Player);345#else346EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);347#endif348349if (player->state == Ice_PlayerState_Frozen) {350#if MANIA_USE_PLUS351Zone->playerSwapEnabled[Zone->swapPlayerID] = false;352#else353Ice_BreakPlayerBlock(player);354#endif355}356}357358void Ice_FreezePlayer(EntityPlayer *player)359{360RSDK_THIS(Ice);361362if (!Zone->gotTimeOver && player->state != Ice_PlayerState_Frozen && (player->shield != SHIELD_FIRE || player->invincibleTimer > 0)) {363EntityIce *ice = CREATE_ENTITY(Ice, INT_TO_VOID(ICE_CHILD_PLAYER), player->position.x, player->position.y);364ice->playerPtr = player;365366#if MANIA_USE_PLUS367switch (player->characterID) {368case ID_SONIC: ice->animationID = 4 * (player->superState == SUPERSTATE_SUPER) + ICEANI_SONICIDLE; break;369case ID_TAILS: ice->animationID = ICEANI_TAILSIDLE; break;370case ID_KNUCKLES: ice->animationID = ICEANI_KNUXIDLE; break;371case ID_MIGHTY: ice->animationID = ICEANI_MIGHTYIDLE; break;372case ID_RAY: ice->animationID = ICEANI_RAYIDLE; break;373default: break;374}375#else376switch (player->characterID) {377case ID_SONIC: ice->animationID = ICEANI_SONIC; break;378case ID_TAILS: ice->animationID = ICEANI_TAILS; break;379case ID_KNUCKLES: ice->animationID = ICEANI_KNUX; break;380default: break;381}382#endif383384RSDK.SetSpriteAnimation(Ice->aniFrames, ice->animationID, &ice->contentsAnimator, true, 0);385RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_PLAYERGLINT, &ice->altContentsAnimator, true, 0);386ice->alpha = 0x80;387ice->isPermanent = true;388389player->velocity.x >>= 1;390player->groundVel >>= 1;391player->animator.speed = 0;392player->visible = false;393player->nextAirState = StateMachine_None;394player->nextGroundState = StateMachine_None;395player->state = Ice_PlayerState_Frozen;396player->velocity.y = 0;397398RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);399player->abilityPtrs[0] = self;400player->abilityPtrs[1] = ice;401if (!self->collisionMode)402player->position.y += Player_GetHitbox(player)->bottom - Ice->hitboxPlayerBlockOuter.bottom;403404player->blinkTimer = 0;405player->outerbox = &Ice->hitboxPlayerBlockOuter;406player->innerbox = &Ice->hitboxPlayerBlockInner;407player->timer = 0;408player->abilityTimer = 0;409player->spindashCharge = 0;410411RSDK.PlaySfx(Ice->sfxFreeze, false, 255);412}413}414415bool32 Ice_CheckPlayerBlockSmashH(void)416{417RSDK_THIS(Player);418419if (abs(self->skidding) >= 0x50000 && abs(self->pushing) <= abs(self->skidding)) {420self->velocity.x = self->skidding < 0 ? 0x18000 : -0x18000;421422Ice_BreakPlayerBlock(self);423424return true;425}426427return false;428}429430bool32 Ice_CheckPlayerBlockSmashV(void)431{432RSDK_THIS(Player);433434if (abs(self->pushing) >= 0x80000 && abs(self->skidding) <= abs(self->pushing)) {435if (self->pushing > 0 && (self->angle & 0xFF) < 0x20) {436Ice_BreakPlayerBlock(self);437return true;438}439440if (self->pushing && (self->angle + 0x80) < 0x20) {441Ice_BreakPlayerBlock(self);442return true;443}444}445446return false;447}448449void Ice_PlayerState_Frozen(void)450{451RSDK_THIS(Player);452453bool32 onGround = self->onGround;454int32 xVel = self->groundVel;455int32 yVel = self->groundedStore;456457if (!onGround) {458onGround |= self->groundedStore || self->velocity.x;459xVel = self->velocity.x;460yVel = self->velocity.y;461}462463if (!onGround) {464onGround |= abs(self->skidding) < 0x50000 || !Ice_CheckPlayerBlockSmashH();465xVel = self->velocity.x;466yVel = self->velocity.y;467}468469if (onGround) {470if (self->onGround && !self->groundVel) {471if (Ice_CheckPlayerBlockSmashH())472return;473}474475self->skidding = xVel;476477if (!yVel) {478if (Ice_CheckPlayerBlockSmashV())479return;480}481482self->pushing = self->velocity.y;483if (self->shield == SHIELD_FIRE && self->invincibleTimer <= 0) {484self->state = Player_State_Air;485self->velocity.y = -self->jumpStrength >> 1;486self->onGround = false;487RSDK.SetSpriteAnimation(self->aniFrames, ANI_JUMP, &self->animator, true, 0);488489Ice_ShatterGenerator(64, 24, 20, 0, 0, 2);490RSDK.PlaySfx(Ice->sfxWindowShatter, false, 255);491Ice->playerTimers[RSDK.GetEntitySlot(self)] = 30;492493self->skidding = 0;494self->pushing = 0;495self->timer = 0;496self->abilityTimer = 0;497self->spindashCharge = 0;498}499else {500if (!self->invincibleTimer)501self->invincibleTimer = -1;502503if (self->spindashCharge > 0) {504self->spindashCharge--;505}506else if (self->jumpPress) {507self->spindashCharge = 15;508509if (++self->timer > 4) {510self->state = Player_State_Air;511self->velocity.y = -self->jumpStrength >> 1;512self->onGround = false;513RSDK.SetSpriteAnimation(self->aniFrames, ANI_JUMP, &self->animator, true, 0);514Ice_ShatterGenerator(64, 24, 20, 0, 0, 2);515RSDK.PlaySfx(Ice->sfxWindowShatter, false, 255);516Ice->playerTimers[RSDK.GetEntitySlot(self)] = 30;517self->skidding = 0;518self->pushing = 0;519self->timer = 0;520self->abilityTimer = 0;521self->spindashCharge = 0;522}523else {524Ice_ShatterGenerator(8, 24, 20, 0, 0, false);525RSDK.PlaySfx(Ice->sfxStruggle, false, 255);526}527}528}529530if (self->state == Ice_PlayerState_Frozen) {531if (self->onGround) {532int32 rollFric = self->rollingFriction;533self->left = false;534self->right = false;535self->rollingFriction = 0;536Player_HandleRollDeceleration();537538if (!self->groundVel)539self->groundVel += (5000 * RSDK.Sin256(self->angle)) >> 8;540541if (self->camera)542self->camera->disableYOffset = false;543544self->jumpAbilityState = 0;545self->rollingFriction = rollFric;546547if (self->state == Player_State_Ground)548self->state = Ice_PlayerState_Frozen;549}550else {551self->velocity.y += 0x3800;552}553}554}555}556557void Ice_ShatterGenerator(int32 count, int32 sizeX, int32 sizeY, int32 velX, int32 velY, int32 canBreak)558{559RSDK_THIS(Ice);560561if (canBreak > 0)562count >>= 1;563564for (int32 i = 0; i < MAX(0, count); ++i) {565int32 x = self->position.x + (RSDK.Rand(-sizeX, sizeX + 1) << 16);566int32 y = self->position.y + (RSDK.Rand(-sizeY, sizeY + 1) << 16);567EntityIce *ice = CREATE_ENTITY(Ice, INT_TO_VOID(ICE_CHILD_SHARD), x, y);568569ice->velocity.x = velX + (RSDK.Rand(-6, 8) << 15);570ice->velocity.y = velY + (RSDK.Rand(-10, 2) << 15);571ice->direction = RSDK.Rand(0, 4);572ice->blockAnimator.speed = RSDK.Rand(1, 4);573574if (canBreak) {575if (RSDK.Rand(0, 2)) {576RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_PIECE, &ice->blockAnimator, true, 0);577ice->velocity.x = (ice->velocity.x >> 1) + (ice->velocity.x >> 2);578ice->velocity.y = (ice->velocity.y >> 1) + (ice->velocity.y >> 2);579}580}581}582}583584// Like Ice_Shatter, but "shatters" the contents too585void Ice_FullShatter(EntityPlayer *player, int32 velX, int32 velY)586{587RSDK_THIS(Ice);588589if (self->type == ICE_SPIKES || (self->type == ICE_SPRING && self->subType < 3))590self->type = ICE_BLOCK;591592EntityItemBox *itemBox = (EntityItemBox *)Ice_Shatter(self, velX, velY);593if (player && itemBox) {594if (player->sidekick)595player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);596597itemBox->contentsPos.x = itemBox->position.x;598itemBox->contentsPos.y = itemBox->position.y - 0x30000;599ItemBox_Break(itemBox, player);600}601}602603void Ice_BreakPlayerBlock(EntityPlayer *player)604{605RSDK.PlaySfx(Ice->sfxWindowShatter, false, 255);606Ice_ShatterGenerator(64, 24, 20, 0, 0, 2);607Ice->playerTimers[RSDK.GetEntitySlot(player)] = 30;608609player->skidding = 0;610player->pushing = 0;611player->timer = 0;612player->abilityTimer = 0;613player->spindashCharge = 0;614player->visible = true;615if (player->state != Player_State_Death) {616player->outerbox = NULL;617player->innerbox = NULL;618player->state = Player_State_Hurt;619RSDK.SetSpriteAnimation(player->aniFrames, ANI_HURT, &player->animator, true, 0);620621player->velocity.y = -0x38000;622player->onGround = false;623if (player->gravityStrength == 0x1000) {624player->velocity.x >>= 1;625player->velocity.y = -0x1C000;626}627}628}629630EntityItemBox *Ice_Shatter(EntityIce *ice, int32 velX, int32 velY)631{632RSDK_THIS(Ice);633634RSDK.PlaySfx(Ice->sfxWindowShatter, false, 255);635636if (self->blockAnimator.animationID == ICEANI_PILLARBLOCK) {637self->position.y -= 0x370000;638Ice_ShatterGenerator(96, 19, 55, velX, velY, 2);639}640else if (self->size == ICE_SIZE_SMALL) {641Ice_ShatterGenerator(16, 16, 16, velX, velY, 2);642}643else {644Ice_ShatterGenerator(64, 24, 20, velX, velY, 2);645}646647EntityItemBox *itemBox = NULL;648int32 count = 0;649switch (ice->type) {650case ICE_BLOCK: break;651652case ICE_1RING: count = 1;653// [Fallthrough]654case ICE_3RINGS:655if (ice->type == ICE_3RINGS)656count = 3;657// [Fallthrough]658case ICE_5RINGS: {659if (ice->type == ICE_5RINGS)660count = 5;661662int32 angle = 16 * (12 - (count >> 1));663for (int32 i = 0; i < count; ++i) {664EntityRing *ring = CREATE_ENTITY(Ring, INT_TO_VOID(1), ice->position.x, ice->position.y);665ring->velocity.x = velX + 640 * RSDK.Cos256(angle);666ring->velocity.y = velY + 640 * RSDK.Sin256(angle);667ring->position.x += ring->velocity.x * (3 * ice->type - 3);668ring->position.y += ring->velocity.y * (3 * ice->type - 3);669ring->timer = 32;670ring->collisionPlane = 0;671ring->inkEffect = INK_ALPHA;672ring->alpha = 256;673ring->state = Ring_State_Lost;674ring->position.y += (0x50000 * ice->type) - 0x50000;675ring->animator.speed = 512;676ring->stateDraw = Ring_Draw_Normal;677angle += 16;678}679break;680}681682case ICE_SPIKES:683CREATE_ENTITY(Spikes, INT_TO_VOID(self->subType), ice->position.x + self->contentsOffset.x, ice->position.y + self->contentsOffset.y);684break;685686case ICE_SPRING:687if (self->subType >= 3)688CREATE_ENTITY(Spring, INT_TO_VOID((self->subFlip << 8) - 3 + self->subType), ice->position.x + self->contentsOffset.x,689ice->position.y + self->contentsOffset.y);690else691CREATE_ENTITY(IceSpring, INT_TO_VOID(self->subType + (self->subFlip << 8)), ice->position.x + self->contentsOffset.x,692ice->position.y + self->contentsOffset.y);693break;694695default: {696int32 type = ice->type - ICE_ITEMBOX_RINGS;697itemBox = CREATE_ENTITY(ItemBox, INT_TO_VOID(type + (ice->type > ICE_ITEMBOX_1UP ? 2 : 0)), ice->position.x, ice->position.y);698itemBox->velocity.y = -0x18000;699itemBox->state = ItemBox_State_Falling;700break;701}702}703704Ice_UpdateBlockGravity();705destroyEntity(ice);706707return itemBox;708}709710void Ice_TimeOver_CheckFrozen(void)711{712EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);713714if (player->state == Ice_PlayerState_Frozen)715Ice_BreakPlayerBlock(player);716}717718void Ice_UpdateBlockGravity(void)719{720RSDK_THIS(Ice);721722foreach_all(Ice, ice)723{724if (ice != self && ice->state == Ice_State_IceBlock725&& RSDK.CheckObjectCollisionTouchBox(self, &self->hitboxBlock, ice, &ice->hitboxFallCheck)) {726ice->state = Ice_State_StartBlockFall;727}728}729}730731void Ice_State_IceBlock(void)732{733RSDK_THIS(Ice);734735foreach_active(Player, player)736{737bool32 noCollision = true;738int32 playerX = player->position.x;739int32 playerY = player->position.y;740741if (player->state == Ice_PlayerState_Frozen) {742switch (MathHelpers_CheckBoxCollision(self, &self->hitboxPlayerBlockCheck, player, &Ice->hitboxPlayerBlockOuter)) {743default:744case C_NONE:745player->position.x = playerX;746player->position.y = playerY;747748self->position.x -= self->playerMoveOffset.x;749self->position.y -= self->playerMoveOffset.y;750if (Player_CheckCollisionBox(player, self, &self->hitboxBlock) == C_TOP) {751player->position.x += self->playerMoveOffset.x;752player->position.y += self->playerMoveOffset.y;753}754755self->position.x += self->playerMoveOffset.x;756self->position.y += self->playerMoveOffset.y;757noCollision = false;758break;759760case C_TOP:761if (player->velocity.y < 0x40000) {762player->position.x = playerX;763player->position.y = playerY;764765self->position.x -= self->playerMoveOffset.x;766self->position.y -= self->playerMoveOffset.y;767if (Player_CheckCollisionBox(player, self, &self->hitboxBlock) == C_TOP) {768player->position.x += self->playerMoveOffset.x;769player->position.y += self->playerMoveOffset.y;770}771772self->position.x += self->playerMoveOffset.x;773self->position.y += self->playerMoveOffset.y;774noCollision = false;775}776else {777Ice_FullShatter(player, 0, 0);778player->velocity.y = -0x20000;779780foreach_return;781}782break;783784case C_LEFT:785if (player->velocity.x < 0x20000) {786player->position.x = playerX;787player->position.y = playerY;788789self->position.x -= self->playerMoveOffset.x;790self->position.y -= self->playerMoveOffset.y;791if (Player_CheckCollisionBox(player, self, &self->hitboxBlock) == C_TOP) {792player->position.x += self->playerMoveOffset.x;793player->position.y += self->playerMoveOffset.y;794}795796self->position.x += self->playerMoveOffset.x;797self->position.y += self->playerMoveOffset.y;798noCollision = false;799}800else {801Ice_FullShatter(player, player->velocity.x >> 1, 0);802player->position.x = playerX;803player->position.y = playerY;804805foreach_return;806}807break;808809case C_RIGHT:810if (player->velocity.x > -0x20000) {811player->position.x = playerX;812player->position.y = playerY;813814self->position.x -= self->playerMoveOffset.x;815self->position.y -= self->playerMoveOffset.y;816if (Player_CheckCollisionBox(player, self, &self->hitboxBlock) == C_TOP) {817player->position.x += self->playerMoveOffset.x;818player->position.y += self->playerMoveOffset.y;819}820821self->position.x += self->playerMoveOffset.x;822self->position.y += self->playerMoveOffset.y;823noCollision = false;824}825else {826Ice_FullShatter(player, player->velocity.x >> 1, 0);827player->position.x = playerX;828player->position.y = playerY;829830foreach_return;831}832break;833834case C_BOTTOM:835if (player->velocity.y > -0x40000) {836player->position.x = playerX;837player->position.y = playerY;838839self->position.x -= self->playerMoveOffset.x;840self->position.y -= self->playerMoveOffset.y;841if (Player_CheckCollisionBox(player, self, &self->hitboxBlock) == C_TOP) {842player->position.x += self->playerMoveOffset.x;843player->position.y += self->playerMoveOffset.y;844}845846self->position.x += self->playerMoveOffset.x;847self->position.y += self->playerMoveOffset.y;848noCollision = false;849}850else {851Ice_FullShatter(player, 0, player->velocity.y >> 1);852player->position.x = playerX;853player->position.y = playerY;854855foreach_return;856}857break;858}859}860861if (noCollision) {862switch (MathHelpers_CheckBoxCollision(self, &self->hitboxBlock, player, &Ice->hitboxPlayerBlockOuter)) {863default:864case C_NONE:865case C_TOP: break;866867case C_LEFT:868case C_RIGHT:869if (self->knuxSmash && player->characterID == ID_KNUCKLES) {870Ice_Shatter(self, 0, 0);871player->position.x = playerX;872player->position.y = playerY;873foreach_return;874}875else if (player->shield == SHIELD_FIRE && player->invincibleTimer <= 0) {876if (RSDK_GET_ENTITY(Player->playerCount + RSDK.GetEntitySlot(player), Shield)->shieldAnimator.animationID877== SHIELDANI_FIREATTACK) {878if (player->position.x >= self->position.x) {879if (player->velocity.x <= -0x78000) {880Ice_FullShatter(player, player->velocity.x, 0);881player->position.x = playerX;882player->position.y = playerY;883foreach_return;884}885}886else if (player->velocity.x >= 0x78000) {887Ice_FullShatter(player, player->velocity.x, 0);888player->position.x = playerX;889player->position.y = playerY;890foreach_return;891}892}893}894break;895896case C_BOTTOM:897if (self->bottomSmash) {898Ice_Shatter(self, 0, 0);899player->position.x = playerX;900player->position.y = playerY;901foreach_return;902}903break;904}905906player->position.x = playerX;907player->position.y = playerY;908self->position.x -= self->playerMoveOffset.x;909self->position.y -= self->playerMoveOffset.y;910911#if MANIA_USE_PLUS912int32 prevVel = player->velocity.y;913#endif914int32 side = Player_CheckCollisionBox(player, self, &self->hitboxBlock);915if (side) {916if (player->shield == SHIELD_FIRE && player->invincibleTimer <= 0 && !self->glintTimer) {917if (self->blockAnimator.animationID == ICEANI_PILLARBLOCK) {918self->position.y -= 0x370000;919Ice_ShatterGenerator(36, 19, 55, 0, 0, false);920}921else if (self->size == ICE_SIZE_SMALL) {922Ice_ShatterGenerator(6, 19, 17, 0, 0, false);923}924else {925Ice_ShatterGenerator(12, 19, 20, 0, 0, false);926}927928self->blockAnimator.frameID += 2;929self->glintTimer = 15;930RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_LARGEGLINT + self->size, &self->glintAnimator, true, 0);931}932933if (side == C_BOTTOM) {934if (player->onGround && !player->collisionMode && self->playerMoveOffset.y >= 0) {935if (player->shield == SHIELD_FIRE || player->invincibleTimer) {936player->position.x = playerX;937player->position.y = playerY;938Ice_Shatter(self, 0, 0);939foreach_return;940}941player->deathType = PLAYER_DEATH_DIE_USESFX;942}943}944else if (side == C_TOP && player->velocity.y >= 0) {945if (self->blockAnimator.animationID == ICEANI_PILLARBLOCK) {946Player_Hurt(player, self);947}948else {949if ((player->animator.animationID == ANI_JUMP || player->state == Player_State_DropDash) && !player->sidekick) {950Ice_Shatter(self, 0, 0);951player->velocity.y = -0x30000;952player->onGround = false;953954foreach_return;955}956#if MANIA_USE_PLUS957else if (player->state == Player_State_MightyHammerDrop && !player->sidekick) {958Ice_FullShatter(player, 0, player->velocity.y);959player->velocity.y = prevVel - 0x10000;960player->onGround = false;961962foreach_return;963}964#endif965}966967player->position.x += self->playerMoveOffset.x;968player->position.y += self->playerMoveOffset.y;969}970}971972self->position.x += self->playerMoveOffset.x;973self->position.y += self->playerMoveOffset.y;974}975}976977RSDK.ProcessAnimation(&self->glintAnimator);978979if (self->blockAnimator.animationID == ICEANI_PILLARBLOCK) {980if (!RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, self->hitboxBlock.bottom << 16, true)981&& self->state == Ice_State_IceBlock) {982self->state = Ice_State_StartBlockFall;983}984985RSDK.ProcessAnimation(&self->blockAnimator);986987if (--self->glintTimer == 54)988RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_PILLARGLINT, &self->glintAnimator, true, 1);989else if (!self->glintTimer)990Ice_Shatter(self, 0, 0);991}992else {993if (self->glintTimer > 0) {994self->glintTimer--;995996if (!self->glintTimer) {997if (self->type == ICE_SPIKES || (self->type == ICE_SPRING && self->subType < 3))998self->type = ICE_BLOCK;9991000Ice_Shatter(self, 0, 0);1001}1002}1003}1004}10051006void Ice_State_StartBlockFall(void)1007{1008RSDK_THIS(Ice);10091010Ice_UpdateBlockGravity();10111012self->timer = 15;1013self->state = Ice_State_BlockFallDelay;1014self->active = ACTIVE_NORMAL;10151016Ice_State_IceBlock();1017}10181019void Ice_State_BlockFallDelay(void)1020{1021RSDK_THIS(Ice);10221023if (!--self->timer) {1024Ice_UpdateBlockGravity();1025self->state = Ice_State_IceBlockFall;1026}10271028Ice_State_IceBlockFall();1029self->velocity.y = 0;1030}10311032void Ice_State_IceBlockFall(void)1033{1034RSDK_THIS(Ice);10351036self->position.y = self->velocity.y + self->position.y;1037self->playerMoveOffset.y = -(int32)(self->position.y & 0xFFFF0000);1038self->playerMoveOffset.y += (self->velocity.y + self->position.y) & 0xFFFF0000;1039self->velocity.y += 0x3800;10401041if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, self->hitboxBlock.bottom << 16, true)) {1042self->velocity.y = 0;10431044self->state = Ice_State_IceBlock;1045Ice_State_IceBlock();1046}1047else {1048int32 velY = self->velocity.y;1049foreach_all(Ice, ice)1050{1051if (ice != self) {1052if ((ice->stateDraw == Ice_Draw_IceBlock || ice->stateDraw == Ice_Draw_PlayerBlock)1053&& RSDK.CheckObjectCollisionPlatform(ice, &ice->hitboxBlock, self, &self->hitboxBlock, true)) {1054self->velocity.y = 0;10551056if (ice->state == Ice_State_IceBlock) {1057self->active = ACTIVE_BOUNDS;1058self->state = Ice_State_IceBlock;1059}1060}1061}1062}10631064foreach_all(Spikes, spikes)1065{1066if (RSDK.CheckObjectCollisionPlatform(spikes, &spikes->hitbox, self, &self->hitboxBlock, true)) {1067self->velocity.y = 0;1068self->active = ACTIVE_BOUNDS;1069self->state = Ice_State_IceBlock;1070}1071}10721073foreach_all(ItemBox, itemBox)1074{1075if ((itemBox->state == ItemBox_State_Idle || itemBox->state == ItemBox_State_Falling)1076&& RSDK.CheckObjectCollisionPlatform(itemBox, &ItemBox->hitboxItemBox, self, &self->hitboxBlock, true)) {1077self->velocity.y = 0;10781079if (itemBox->onGround) {1080self->active = ACTIVE_BOUNDS;1081self->state = Ice_State_IceBlock;1082}1083}1084}10851086if (!self->velocity.y && velY >= 0x60000) {1087if (ice) {1088if (ice->stateDraw == Ice_Draw_PlayerBlock) {1089Ice_BreakPlayerBlock(ice->playerPtr);1090}1091else {1092Entity *storeEntity = SceneInfo->entity;1093SceneInfo->entity = (Entity *)ice;10941095if (ice->type == ICE_SPIKES || (ice->type == ICE_SPRING && ice->subType < 3))1096ice->type = ICE_BLOCK;10971098Ice_Shatter(ice, 0, 0);10991100SceneInfo->entity = storeEntity;1101}1102}11031104if (self->type == ICE_SPIKES || (self->type == ICE_SPRING && self->subType < 3))1105self->type = ICE_BLOCK;11061107Ice_Shatter(self, 0, 0);1108}11091110Ice_State_IceBlock();1111}1112}11131114void Ice_State_PlayerBlock(void)1115{1116RSDK_THIS(Ice);11171118RSDK.ProcessAnimation(&self->contentsAnimator);1119EntityPlayer *playerPtr = self->playerPtr;11201121if (playerPtr->state == Ice_PlayerState_Frozen) {1122RSDK.ProcessAnimation(&self->altContentsAnimator);11231124#if MANIA_USE_PLUS1125if (self->contentsAnimator.animationID == self->animationID + 3) {1126if (self->contentsAnimator.frameID == self->contentsAnimator.frameCount - 1)1127RSDK.SetSpriteAnimation(Ice->aniFrames, self->animationID, &self->contentsAnimator, false, 0);11281129if (--self->glintTimer <= 0) {1130RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_PLAYERGLINT, &self->altContentsAnimator, true, 0);1131self->glintTimer = 30 * RSDK.Rand(1, 9);1132}11331134self->blockAnimator.frameID = playerPtr->timer;11351136if (playerPtr->spindashCharge) {1137self->contentsOffset.x = RSDK.Rand(-1, 2) << 16;1138self->contentsOffset.y = RSDK.Rand(-1, 2) << 16;1139}1140else {1141self->contentsOffset.x = 0;1142self->contentsOffset.y = 0;1143}11441145self->playerMoveOffset.x = (playerPtr->position.x & 0xFFFF0000) - (self->position.x & 0xFFFF0000);1146self->playerMoveOffset.y = (playerPtr->position.y & 0xFFFF0000) - (self->position.y & 0xFFFF0000);11471148self->position.x = playerPtr->position.x;1149self->position.y = playerPtr->position.y;1150self->drawGroup = playerPtr->drawGroup + 1;1151}1152else {1153if (playerPtr->jumpPress) {1154RSDK.SetSpriteAnimation(Ice->aniFrames, self->animationID + 3, &self->contentsAnimator, false, 0);1155}1156else {1157if (playerPtr->velocity.x >= -0x60000) {1158if (playerPtr->velocity.x <= 0x60000) {1159if (playerPtr->left)1160RSDK.SetSpriteAnimation(Ice->aniFrames, self->animationID + 1, &self->contentsAnimator, false, 0);1161else if (playerPtr->right)1162RSDK.SetSpriteAnimation(Ice->aniFrames, self->animationID + 2, &self->contentsAnimator, false, 0);1163}1164else {1165RSDK.SetSpriteAnimation(Ice->aniFrames, self->animationID + 2, &self->contentsAnimator, false, 0);1166}1167}1168else {1169RSDK.SetSpriteAnimation(Ice->aniFrames, self->animationID + 1, &self->contentsAnimator, false, 0);1170}1171}11721173if (--self->glintTimer <= 0) {1174RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_PLAYERGLINT, &self->altContentsAnimator, true, 0);1175self->glintTimer = 30 * RSDK.Rand(1, 9);1176}11771178self->blockAnimator.frameID = playerPtr->timer;11791180if (playerPtr->spindashCharge) {1181self->contentsOffset.x = RSDK.Rand(-1, 2) << 16;1182self->contentsOffset.y = RSDK.Rand(-1, 2) << 16;1183}1184else {1185self->contentsOffset.x = 0;1186self->contentsOffset.y = 0;1187}11881189self->playerMoveOffset.x = (playerPtr->position.x & 0xFFFF0000) - (self->position.x & 0xFFFF0000);1190self->playerMoveOffset.y = (playerPtr->position.y & 0xFFFF0000) - (self->position.y & 0xFFFF0000);11911192self->position.x = playerPtr->position.x;1193self->position.y = playerPtr->position.y;1194self->drawGroup = playerPtr->drawGroup + 1;1195}1196}1197else {1198if (playerPtr->state != Player_State_FlyToPlayer && playerPtr->state != Player_State_ReturnToPlayer) {1199if (!Player_CheckValidState(playerPtr)) {1200Ice_BreakPlayerBlock(self->playerPtr);1201}1202else {1203playerPtr->outerbox = NULL;1204playerPtr->innerbox = NULL;1205playerPtr->visible = true;1206}1207}12081209destroyEntity(self);1210}1211#else1212if (--self->glintTimer <= 0) {1213RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_PLAYERGLINT, &self->altContentsAnimator, true, 0);1214self->glintTimer = 30 * RSDK.Rand(1, 9);1215}12161217self->blockAnimator.frameID = playerPtr->timer;12181219if (playerPtr->spindashCharge) {1220self->contentsOffset.x = RSDK.Rand(-1, 2) << 16;1221self->contentsOffset.y = RSDK.Rand(-1, 2) << 16;1222}1223else {1224self->contentsOffset.x = 0;1225self->contentsOffset.y = 0;1226}12271228self->playerMoveOffset.x = (playerPtr->position.x & 0xFFFF0000) - (self->position.x & 0xFFFF0000);1229self->playerMoveOffset.y = (playerPtr->position.y & 0xFFFF0000) - (self->position.y & 0xFFFF0000);12301231self->position.x = playerPtr->position.x;1232self->position.y = playerPtr->position.y;1233self->drawGroup = playerPtr->drawGroup + 1;1234}1235else {1236playerPtr->outerbox = NULL;1237playerPtr->innerbox = NULL;1238playerPtr->visible = true;12391240destroyEntity(self);1241}1242#endif12431244foreach_active(Player, player)1245{1246if (player != self->playerPtr && player->stateInput != Player_Input_P2_AI && player->state != Ice_PlayerState_Frozen && player->velocity.y > 01247&& !player->onGround && player->position.y < self->position.y - 0x200000 && Player_CheckBadnikTouch(player, self, &self->hitboxBlock)) {1248if (player->animator.animationID == ANI_JUMP || player->animator.animationID == ANI_DROPDASH) {1249Ice_BreakPlayerBlock(self->playerPtr);1250player->velocity.y = -0x30000;1251player->onGround = false;12521253foreach_break;1254}1255}1256}12571258if (self->timer)1259self->timer--;1260}12611262void Ice_State_Shard(void)1263{1264RSDK_THIS(Ice);12651266RSDK.ProcessAnimation(&self->blockAnimator);12671268self->position.x += self->velocity.x;1269self->position.y += self->velocity.y;1270self->velocity.y += 0x3800;12711272self->visible ^= true;12731274if (!RSDK.CheckOnScreen(self, &self->updateRange))1275destroyEntity(self);1276}12771278void Ice_Draw_IceBlock(void)1279{1280RSDK_THIS(Ice);1281Vector2 drawPos;12821283int32 dirStore = self->direction;12841285drawPos.x = self->position.x + self->contentsOffset.x;1286drawPos.y = self->position.y + self->contentsOffset.y;1287self->direction = self->subFlip;1288RSDK.DrawSprite(&self->contentsAnimator, &drawPos, false);12891290self->direction = dirStore;1291drawPos.y -= 0x30000;1292RSDK.DrawSprite(&self->altContentsAnimator, &drawPos, false);12931294#if MANIA_USE_PLUS1295if (!SceneInfo->inEditor) {1296self->inkEffect = INK_ADD;1297self->blockAnimator.frameID += !self->glintTimer ? 4 : 2;1298RSDK.DrawSprite(&self->blockAnimator, NULL, false);12991300self->blockAnimator.frameID -= !self->glintTimer ? 4 : 2;1301self->inkEffect = INK_NONE;1302}1303#endif13041305RSDK.DrawSprite(&self->blockAnimator, NULL, false);13061307self->inkEffect = INK_ADD;1308RSDK.DrawSprite(&self->glintAnimator, NULL, false);13091310self->inkEffect = INK_NONE;1311}13121313void Ice_Draw_PlayerBlock(void)1314{1315RSDK_THIS(Ice);1316Vector2 drawPos;13171318drawPos.x = self->position.x + self->contentsOffset.x;1319drawPos.y = self->position.y + self->contentsOffset.y;13201321#if MANIA_USE_PLUS1322int32 frame = self->blockAnimator.frameID;1323self->inkEffect = INK_SUB;1324self->blockAnimator.frameID = 5;1325RSDK.DrawSprite(&self->blockAnimator, NULL, false);13261327self->blockAnimator.frameID = frame;1328self->inkEffect = INK_NONE;1329#endif13301331RSDK.DrawSprite(&self->contentsAnimator, &drawPos, false);1332RSDK.DrawSprite(&self->blockAnimator, NULL, false);13331334self->inkEffect = INK_ADD;1335RSDK.DrawSprite(&self->altContentsAnimator, NULL, false);13361337self->inkEffect = INK_NONE;1338}13391340void Ice_Draw_Pillar(void)1341{1342RSDK_THIS(Ice);13431344RSDK.DrawSprite(&self->blockAnimator, NULL, false);13451346self->inkEffect = INK_ADD;1347RSDK.DrawSprite(&self->glintAnimator, NULL, false);13481349self->inkEffect = INK_NONE;1350}13511352void Ice_Draw_Shard(void)1353{1354RSDK_THIS(Ice);13551356RSDK.DrawSprite(&self->blockAnimator, NULL, false);1357}13581359#if GAME_INCLUDE_EDITOR1360void Ice_EditorDraw(void)1361{1362RSDK_THIS(Ice);13631364self->drawFX = FX_FLIP;1365self->drawGroup = Zone->playerDrawGroup[0] + 1;1366self->visible = true;1367self->active = ACTIVE_BOUNDS;1368self->updateRange.x = 0x800000;1369self->updateRange.y = 0x800000;1370self->alpha = 0x180;13711372int32 type = self->type;1373int32 subType = self->subType;1374int32 subFlip = self->subFlip;13751376RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_ICEBLOCK, &self->blockAnimator, true, self->size);1377RSDK.SetSpriteAnimation(-1, 0, &self->altContentsAnimator, true, 0);13781379switch (self->type) {1380case ICE_BLOCK: RSDK.SetSpriteAnimation(-1, ICEANI_ICEBLOCK, &self->contentsAnimator, true, 0); break;1381case ICE_1RING: RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_RINGS, &self->contentsAnimator, true, 0); break;1382case ICE_3RINGS: RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_RINGS, &self->contentsAnimator, true, 1); break;1383case ICE_5RINGS: RSDK.SetSpriteAnimation(Ice->aniFrames, ICEANI_RINGS, &self->contentsAnimator, true, 2); break;13841385case ICE_SPIKES:1386self->subType = self->subType & 3;1387RSDK.SetSpriteAnimation(Spikes->aniFrames, self->subType >> 1, &self->contentsAnimator, true, 0);13881389if (!self->size) {1390// direction of da spikes, matches the spikes "type" variable1391switch (self->subType) {1392case 0:1393self->contentsOffset.y = 0x40000;1394self->subFlip = FLIP_NONE;1395break;13961397case 1:1398self->contentsOffset.y = -0x40000;1399self->subFlip = FLIP_Y;1400break;14011402case 2:1403self->contentsOffset.x = -0x80000;1404self->subFlip = FLIP_NONE;1405break;14061407case 3:1408self->contentsOffset.x = 0x80000;1409self->subFlip = FLIP_X;1410break;14111412default: break;1413}1414}1415break;14161417case ICE_SPRING:1418// Ice Springs (0-2), Normal Springs (2-8)1419if (self->subType >= 3)1420RSDK.SetSpriteAnimation(Spring->aniFrames, (self->subType - 3), &self->contentsAnimator, true, 0);1421else1422RSDK.SetSpriteAnimation(IceSpring->aniFrames, self->subType, &self->contentsAnimator, true, 0);14231424if (self->size) {1425switch (self->subType) {1426case 0:1427case 3:1428case 4:1429self->contentsOffset.x = 0;1430if (!(self->subFlip & FLIP_Y))1431self->contentsOffset.y = 0x80000;1432else1433self->contentsOffset.y = -0x80000;1434break;14351436case 1:1437case 5:1438case 6:1439self->contentsOffset.y = 0;1440if (!(self->subFlip & FLIP_X))1441self->contentsOffset.x = -0x80000;1442else1443self->contentsOffset.x = 0x80000;1444break;14451446case 2:1447case 7:1448case 8:1449self->contentsOffset.x = 0;1450if (!(self->subFlip & FLIP_Y))1451self->contentsOffset.y = -0x10000;1452else1453self->contentsOffset.y = 0x10000;1454break;14551456default: break;1457}1458}1459else {1460switch (self->subType) {1461case 0:1462case 3:1463case 4:1464self->contentsOffset.x = 0;1465if (!(self->subFlip & FLIP_Y))1466self->contentsOffset.y = 0xC0000;1467else1468self->contentsOffset.y = -0xC0000;1469break;14701471case 1:1472case 5:1473case 6:1474self->contentsOffset.y = 0;1475if (!(self->subFlip & FLIP_X))1476self->contentsOffset.x = -0x100000;1477else1478self->contentsOffset.x = 0x100000;1479break;14801481case 2:1482case 7:1483case 8:1484if (!(self->subFlip & FLIP_X))1485self->contentsOffset.x = -0x80000;1486else1487self->contentsOffset.x = 0x80000;1488if (!(self->subFlip & FLIP_Y))1489self->contentsOffset.y = 0x40000;1490else1491self->contentsOffset.y = -0x40000;1492break;14931494default: break;1495}1496}1497break;14981499case ICE_ITEMBOX_RINGS:1500case ICE_ITEMBOX_BLUESHIELD:1501case ICE_ITEMBOX_BUBBLESHIELD:1502case ICE_ITEMBOX_FIRESHIELD:1503case ICE_ITEMBOX_LIGHTNINGSHIELD:1504case ICE_ITEMBOX_INVINCIBILITY:1505case ICE_ITEMBOX_SNEAKERS:1506case ICE_ITEMBOX_1UP:1507case ICE_ITEMBOX_EGGMAN:1508case ICE_ITEMBOX_HYPERRING:1509case ICE_ITEMBOX_SWAP:1510case ICE_ITEMBOX_RANDOM:1511case ICE_ITEMBOX_SUPER:1512default:1513RSDK.SetSpriteAnimation(ItemBox->aniFrames, 0, &self->contentsAnimator, true, 0);1514RSDK.SetSpriteAnimation(ItemBox->aniFrames, 2, &self->altContentsAnimator, true, (self->type > ICE_ITEMBOX_1UP ? 2 : 0) + self->type - 5);15151516if (self->type != ICE_ITEMBOX_1UP) {1517if (globals->gameMode == MODE_COMPETITION) {1518if (globals->itemMode == ITEMS_RANDOM) {1519self->type = ICE_ITEMBOX_EGGMAN;1520self->altContentsAnimator.frameID = 13;1521}1522else if (globals->itemMode == ITEMS_TELEPORT) {1523self->type = ICE_ITEMBOX_SWAP;1524self->altContentsAnimator.frameID = 12;1525}1526}1527}1528else if (globals->gameMode != MODE_TIMEATTACK) {1529switch (RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->characterID) {1530default:1531case ID_SONIC: break;1532case ID_TAILS: ++self->altContentsAnimator.frameID; break;1533case ID_KNUCKLES: self->altContentsAnimator.frameID += 2; break;1534#if MANIA_USE_PLUS1535case ID_MIGHTY: self->altContentsAnimator.frameID += 8; break;1536case ID_RAY: self->altContentsAnimator.frameID += 9; break;1537#endif1538}15391540if (globals->gameMode == MODE_COMPETITION) {1541if (globals->itemMode == ITEMS_RANDOM) {1542self->type = ICE_ITEMBOX_RANDOM;1543self->altContentsAnimator.frameID = 13;1544}1545else if (globals->itemMode == 2) {1546self->type = ICE_ITEMBOX_SWAP;1547self->altContentsAnimator.frameID = 12;1548}1549}1550}1551else {1552self->type = ICE_ITEMBOX_RINGS;1553self->altContentsAnimator.frameID = 0;1554}1555break;1556}15571558Ice_Draw_IceBlock();15591560self->type = type;1561self->subType = subType;1562self->subFlip = subFlip;1563}15641565void Ice_EditorLoad(void)1566{1567if (RSDK.CheckSceneFolder("PSZ1"))1568Ice->aniFrames = RSDK.LoadSpriteAnimation("PSZ1/Ice.bin", SCOPE_STAGE);1569else if (RSDK.CheckSceneFolder("PSZ2"))1570Ice->aniFrames = RSDK.LoadSpriteAnimation("PSZ2/Ice.bin", SCOPE_STAGE);15711572RSDK_ACTIVE_VAR(Ice, size);1573RSDK_ENUM_VAR("Large", ICE_SIZE_LARGE);1574RSDK_ENUM_VAR("Small", ICE_SIZE_SMALL);15751576RSDK_ACTIVE_VAR(Ice, type);1577RSDK_ENUM_VAR("Empty Block", ICE_BLOCK);1578RSDK_ENUM_VAR("1 Ring", ICE_1RING);1579RSDK_ENUM_VAR("3 Rings", ICE_3RINGS);1580RSDK_ENUM_VAR("5 Rings", ICE_5RINGS);1581RSDK_ENUM_VAR("Spikes", ICE_SPIKES);1582RSDK_ENUM_VAR("ItemBox (Rings)", ICE_ITEMBOX_RINGS);1583RSDK_ENUM_VAR("ItemBox (Blue Shield)", ICE_ITEMBOX_BLUESHIELD);1584RSDK_ENUM_VAR("ItemBox (Bubble Shield)", ICE_ITEMBOX_BUBBLESHIELD);1585RSDK_ENUM_VAR("ItemBox (Fire Shield)", ICE_ITEMBOX_FIRESHIELD);1586RSDK_ENUM_VAR("ItemBox (Lightning Shield)", ICE_ITEMBOX_LIGHTNINGSHIELD);1587RSDK_ENUM_VAR("ItemBox (Invincibility)", ICE_ITEMBOX_INVINCIBILITY);1588RSDK_ENUM_VAR("ItemBox (Speed Shoes)", ICE_ITEMBOX_SNEAKERS);1589RSDK_ENUM_VAR("ItemBox (1UP)", ICE_ITEMBOX_1UP);1590RSDK_ENUM_VAR("ItemBox (Eggman)", ICE_ITEMBOX_EGGMAN);1591RSDK_ENUM_VAR("ItemBox (Hyper Ring)", ICE_ITEMBOX_HYPERRING);1592RSDK_ENUM_VAR("ItemBox (Swap)", ICE_ITEMBOX_SWAP);1593RSDK_ENUM_VAR("ItemBox (Random)", ICE_ITEMBOX_SUPER);1594RSDK_ENUM_VAR("ItemBox (Super)", ICE_ITEMBOX_RANDOM);1595RSDK_ENUM_VAR("Spring", ICE_SPRING);15961597RSDK_ACTIVE_VAR(Ice, subFlip);1598RSDK_ENUM_VAR("No Flip", FLIP_NONE);1599RSDK_ENUM_VAR("Flip X", FLIP_X);1600RSDK_ENUM_VAR("Flip Y", FLIP_Y);1601RSDK_ENUM_VAR("Flip XY", FLIP_XY);1602}1603#endif16041605void Ice_Serialize(void)1606{1607RSDK_EDITABLE_VAR(Ice, VAR_UINT8, size);1608RSDK_EDITABLE_VAR(Ice, VAR_UINT8, type);1609RSDK_EDITABLE_VAR(Ice, VAR_UINT8, subType);1610RSDK_EDITABLE_VAR(Ice, VAR_UINT8, subFlip);1611RSDK_EDITABLE_VAR(Ice, VAR_BOOL, bottomSmash);1612RSDK_EDITABLE_VAR(Ice, VAR_BOOL, knuxSmash);1613}161416151616