Path: blob/master/SonicMania/Objects/CPZ/ChemicalPool.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: ChemicalPool Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectChemicalPool *ChemicalPool;1011void ChemicalPool_Update(void)12{13RSDK_THIS(ChemicalPool);1415if (self->timer > 0)16self->timer--;1718self->offsetY = self->position.y - self->updateRange.y;1920StateMachine_Run(self->state);21}2223void ChemicalPool_LateUpdate(void) {}2425void ChemicalPool_StaticUpdate(void) {}2627void ChemicalPool_Draw(void)28{29RSDK_THIS(ChemicalPool);3031RSDKScreenInfo *screen = &ScreenInfo[SceneInfo->currentScreenID];3233int32 screenX = self->position.x - (screen->position.x << 16);34int32 screenY = screen->position.y << 16;3536Vector2 verts[4];37Vector2 *vertices = self->vertices;38for (int32 i = 0; i < self->tileSizeX; ++i) {39verts[0].x = vertices[0].x + screenX;40verts[0].y = vertices[0].y - screenY;41verts[1].x = vertices[2].x + screenX;42verts[1].y = vertices[2].y - screenY;43verts[2].x = vertices[3].x + screenX;44verts[2].y = vertices[3].y - screenY;45verts[3].x = vertices[1].x + screenX;46verts[3].y = vertices[1].y - screenY;4748color *surfaceColors = NULL;49if (self->timer >= 1)50surfaceColors = ChemicalPool->surfaceColorsFlash;51else52surfaceColors = self->surfaceColors;53RSDK.DrawBlendedFace(verts, surfaceColors, 4, 0xC0, INK_NONE);5455verts[0].x = verts[3].x;56verts[0].y = verts[3].y;57verts[1].x = verts[2].x;58verts[1].y = verts[2].y;59verts[2].y = self->position.y + self->updateRange.y - screenY;60verts[3].y = self->position.y + self->updateRange.y - screenY;61if (self->timer >= 1)62RSDK.DrawFace(verts, 4, 0xE0, 0xE0, 0xE0, 0xC0, INK_ALPHA);63else64RSDK.DrawFace(verts, 4, self->r, self->g, self->b, 0xC0, INK_ALPHA);6566vertices += 2;67}6869if (self->type > CHEMICALPOOL_BLUE) { // da reflection70int32 x = ((self->position.x - self->updateRange.x) >> 16) - screen->position.x;71int32 y = ((self->position.y - self->updateRange.y) >> 16) - screen->position.y;72RSDK.SetClipBounds(SceneInfo->currentScreenID, x, y, x + (self->size.x >> 16), y + (self->size.y >> 16));7374Vector2 drawPos;75drawPos.x = self->position.x - ((self->position.x - (screen->position.x << 16) - (ScreenInfo->center.x << 16)) >> 1);7677int32 offset = CLAMP(0x800000 - self->size.y, 0, 0x400000);78drawPos.y = offset + self->position.y + self->maxDeform - ((self->position.y - (screen->center.y << 16) - (screen->position.y << 16)) >> 4);79RSDK.DrawSprite(&self->animator, &drawPos, false);8081RSDK.SetClipBounds(SceneInfo->currentScreenID, 0, 0, screen->size.x, screen->size.y);82}83}8485void ChemicalPool_Create(void *data)86{87RSDK_THIS(ChemicalPool);8889if (!SceneInfo->inEditor) {90self->inkEffect = INK_ADD;91self->visible = true;92self->alpha = 0xFF;93self->active = ACTIVE_BOUNDS;94self->drawGroup = Zone->objectDrawGroup[1] - 2;95self->updateRange.x = self->size.x >> 1;96self->updateRange.y = self->size.y >> 1;97self->tileSizeX = self->size.x >> 20;9899Vector2 *vertices = self->vertices;100for (int32 i = 0; i < 0x2100000; i += 0x100000) {101int32 x = i - (self->size.x >> 1);102vertices[0].x = x;103vertices[1].x = x;104105int32 y = self->position.y - (self->size.y >> 1);106vertices[0].y = y;107vertices[1].y = y + 0x80000;108109vertices += 2;110}111112self->leftEdge = (self->position.x - (self->size.x >> 1)) >> 20;113self->rightEdge = (self->position.x + (self->size.x >> 1)) >> 20;114self->impactPower = 0x80;115self->impactPowerSides = 0x99;116self->r = 0x00;117self->g = 0x08;118self->b = 0xC0;119120self->hitbox.left = -(self->size.x >> 17);121self->hitbox.top = (self->type == CHEMICALPOOL_BLUE ? 6 : 0) - (self->size.y >> 17);122self->hitbox.right = -self->hitbox.left;123self->hitbox.bottom = -self->hitbox.bottom;124125ChemicalPool_SetupColors();126127self->timer = 0;128129RSDK.SetSpriteAnimation(ChemicalPool->aniFrames, 0, &self->animator, true, 0);130}131}132133void ChemicalPool_StageLoad(void)134{135ChemicalPool->aniFrames = RSDK.LoadSpriteAnimation("CPZ/ChemPool.bin", SCOPE_STAGE);136137ChemicalPool->sfxChemYellow = RSDK.GetSfx("CPZ/ChemYellow.wav");138ChemicalPool->sfxChemRed = RSDK.GetSfx("CPZ/ChemRed.wav");139ChemicalPool->sfxChemChange = RSDK.GetSfx("CPZ/ChemChange.wav");140}141142void ChemicalPool_ChangeState(EntityChemicalPool *chemPool, int32 newType, int32 newR, int32 newG, int32 newB)143{144chemPool->r = chemPool->r + ((newR - chemPool->r) >> 2);145chemPool->b = chemPool->b + ((newB - chemPool->b) >> 2);146chemPool->g = chemPool->g + ((newG - chemPool->g) >> 2);147chemPool->surfaceColors[2] = (chemPool->r << 16) | (chemPool->g << 8) | chemPool->b;148chemPool->surfaceColors[3] = (chemPool->r << 16) | (chemPool->g << 8) | chemPool->b;149150uint32 change = abs(newR - chemPool->r) + abs(newG - chemPool->g) + abs(newB - chemPool->b) - 1;151if (change < 0x1F && chemPool->state != ChemicalPool_State_Changing) {152chemPool->type = newType;153chemPool->timer = 4;154chemPool->state = ChemicalPool_State_Changing;155RSDK.PlaySfx(ChemicalPool->sfxChemChange, false, 255);156}157}158159void ChemicalPool_ProcessDeformations(void)160{161RSDK_THIS(ChemicalPool);162163for (int32 i = self->leftEdge; i < self->rightEdge; ++i) {164int32 deform = ChemicalPool->surfaceDeformation[i];165ChemicalPool->impactTable[i] += (-deform >> 5) - (ChemicalPool->impactTable[i] >> 3);166ChemicalPool->deformTable[i] = ChemicalPool->impactTable[i] + ChemicalPool->surfaceDeformation[i];167}168169for (int32 i = self->leftEdge; i < self->rightEdge; ++i) {170int32 prev = MAX(i - 1, self->leftEdge);171int32 next = MIN(i + 1, self->rightEdge);172173ChemicalPool->surfaceDeformation[i] = (self->impactPower * ChemicalPool->deformTable[i] >> 8)174+ (self->impactPowerSides * (ChemicalPool->deformTable[prev] + ChemicalPool->deformTable[next]) >> 9);175}176177self->maxDeform = 0;178int32 id = self->leftEdge;179Vector2 *vertices = self->vertices;180for (int32 i = 0; i <= self->tileSizeX; ++i) {181if (ChemicalPool->surfaceDeformation[id] > self->maxDeform)182self->maxDeform = ChemicalPool->surfaceDeformation[id];183vertices[0].y = ChemicalPool->surfaceDeformation[id] + self->offsetY;184185int32 deform = 2 * ChemicalPool->surfaceDeformation[id] + 0x80000;186if (deform < ChemicalPool->surfaceDeformation[id])187deform = ChemicalPool->surfaceDeformation[id] + 0x10000;188vertices[1].y = deform + self->offsetY;189190++id;191vertices += 2;192}193}194195void ChemicalPool_SetDeform(int32 impactX, int32 impactVelocity)196{197int32 bounceX = (impactX + 0x80000) >> 20;198199foreach_active(ChemicalPool, chemPool)200{201if (bounceX > chemPool->leftEdge && bounceX < chemPool->rightEdge) {202int32 prev = MAX(bounceX - 1, chemPool->leftEdge + 1);203int32 next = MIN(bounceX + 2, chemPool->rightEdge);204205for (int32 i = 0; i < next - prev; ++i) ChemicalPool->impactTable[prev + i] += impactVelocity;206207foreach_break;208}209}210}211212void ChemicalPool_SpawnDebris(int32 x, int32 y)213{214RSDK_THIS(ChemicalPool);215216for (int32 i = 0; i < 6; ++i) {217EntityDebris *debris = CREATE_ENTITY(Debris, NULL, x + ZONE_RAND(-0x80000, 0x80000), y + ZONE_RAND(0x40000, 0x140000));218debris->state = Debris_State_Fall;219debris->gravityStrength = 0x3800;220debris->velocity.x = ZONE_RAND(0, 0x20000);221if (debris->position.x < x)222debris->velocity.x = -debris->velocity.x;223debris->velocity.y = ZONE_RAND(-0x40000, -0x10000);224debris->drawGroup = Zone->objectDrawGroup[1];225RSDK.SetSpriteAnimation(Reagent->aniFrames, self->type + 1, &debris->animator, true, ZONE_RAND(0, 2));226}227}228229void ChemicalPool_SetupColors(void)230{231RSDK_THIS(ChemicalPool);232233switch (self->type) {234case CHEMICALPOOL_BLUE:235default:236self->surfaceColors[0] = 0x0060E0;237self->surfaceColors[1] = 0x0060E0;238self->surfaceColors[2] = 0x0008C0;239self->surfaceColors[3] = 0x0008C0;240self->r = 0x00;241self->g = 0x08;242self->b = 0xC0;243self->state = ChemicalPool_State_HarmfulBlue;244self->timer = 3;245break;246247case CHEMICALPOOL_GREEN:248self->surfaceColors[0] = 0x20E020;249self->surfaceColors[1] = 0x20E020;250self->surfaceColors[2] = 0x189000;251self->surfaceColors[3] = 0x189000;252self->r = 0x18;253self->g = 0x90;254self->b = 0x00;255self->state = ChemicalPool_State_Green;256self->timer = 3;257break;258259case CHEMICALPOOL_CYAN:260self->surfaceColors[0] = 0x00B8F0;261self->surfaceColors[1] = 0x00B8F0;262self->surfaceColors[2] = 0x0080B0;263self->surfaceColors[3] = 0x0080B0;264self->r = 0x00;265self->g = 0x80;266self->b = 0xB0;267self->state = ChemicalPool_State_Cyan;268self->timer = 3;269break;270}271}272273void ChemicalPool_State_HarmfulBlue(void)274{275RSDK_THIS(ChemicalPool);276ChemicalPool_ProcessDeformations();277int32 topStore = self->hitbox.top;278279foreach_active(Player, player)280{281if (player->velocity.y >= 0 && Player_CheckCollisionBox(player, self, &self->hitbox)) {282ChemicalPool_SetDeform(player->position.x, (player->velocity.y >> 4) + 0x1000);283if (player->shield != SHIELD_BUBBLE) {284if (player->state != Player_State_Hurt && player->state != Player_State_Death && player->state != Player_State_Drown285&& !player->invincibleTimer && player->blinkTimer <= 0) {286if (player->position.x > self->position.x)287player->velocity.x = 0x20000;288else289player->velocity.x = -0x20000;290Player_Hit(player);291}292}293294if (player->velocity.y < 0 && player->velocity.y > -0x40000)295player->velocity.y = -0x40000;296}297}298299self->hitbox.top = topStore;300if (!(Zone->timer & 3)) {301EntityChemBubble *bubble = CREATE_ENTITY(ChemBubble, NULL, self->position.x + RSDK.Rand(-self->updateRange.x, self->updateRange.x),302self->position.y + self->updateRange.y);303bubble->parent = self;304}305}306307void ChemicalPool_State_Green(void)308{309RSDK_THIS(ChemicalPool);310311ChemicalPool_ProcessDeformations();312313foreach_active(Player, player)314{315if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {316ChemicalPool_SetDeform(player->position.x, player->velocity.y >> 1);317ChemicalPool_SpawnDebris(player->position.x, player->position.y);318319if (player->state != Player_State_DropDash)320player->state = Player_State_Air;321322int32 anim = player->animator.animationID;323if (anim != ANI_JUMP && anim != ANI_JOG && anim != ANI_RUN && anim != ANI_DASH)324player->animator.animationID = ANI_WALK;325326player->onGround = false;327player->applyJumpCap = false;328player->velocity.y = -0x140000;329330RSDK.PlaySfx(ChemicalPool->sfxChemRed, false, 255);331}332}333}334335void ChemicalPool_State_Cyan(void)336{337RSDK_THIS(ChemicalPool);338339ChemicalPool_ProcessDeformations();340341foreach_active(Player, player)342{343if (player->velocity.y >= 0) {344if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {345ChemicalPool_SetDeform(player->position.x, player->velocity.y >> 1);346ChemicalPool_SpawnDebris(player->position.x, player->position.y);347348if (player->state != Player_State_DropDash)349player->state = Player_State_Air;350351int32 anim = player->animator.animationID;352if (anim != ANI_JUMP && anim != ANI_JOG && anim != ANI_RUN && anim != ANI_DASH)353player->animator.animationID = ANI_WALK;354355if ((-0x10000 - player->velocity.y) > -0x80000)356player->velocity.y = -0x10000 - player->velocity.y;357else358player->velocity.y = -0x80000;359360player->onGround = false;361player->applyJumpCap = false;362RSDK.PlaySfx(ChemicalPool->sfxChemYellow, false, 255);363}364}365}366}367368void ChemicalPool_State_Changing(void)369{370RSDK_THIS(ChemicalPool);371372ChemicalPool_ProcessDeformations();373374if (++self->changeTimer == 16) {375foreach_active(ChemBubble, bubble)376{377if (abs(bubble->position.x - self->position.x) <= self->updateRange.x) {378if (abs(bubble->position.y - self->position.y) <= self->updateRange.y)379destroyEntity(bubble);380}381}382383self->changeTimer = 0;384ChemicalPool_SetupColors();385self->active = ACTIVE_BOUNDS;386}387}388389#if GAME_INCLUDE_EDITOR390void ChemicalPool_EditorDraw(void)391{392RSDK_THIS(ChemicalPool);393394self->updateRange.x = self->size.x >> 1;395self->updateRange.y = self->size.y >> 1;396397Vector2 drawPos;398drawPos.x = self->position.x - (self->size.x >> 1);399drawPos.y = self->position.y - (self->size.y >> 1);400ChemicalPool_SetupColors();401RSDK.DrawRect(drawPos.x, drawPos.y, self->size.x, self->size.y, (self->r << 16) | (self->g << 8) | (self->b << 0), 0xC0, INK_ALPHA, false);402403DrawHelpers_DrawRectOutline(self->position.x, self->position.y, self->size.x, self->size.y, 0xFFFF00);404}405406void ChemicalPool_EditorLoad(void)407{408RSDK_ACTIVE_VAR(ChemicalPool, type);409RSDK_ENUM_VAR("Blue", CHEMICALPOOL_BLUE);410RSDK_ENUM_VAR("Green", CHEMICALPOOL_GREEN);411RSDK_ENUM_VAR("Cyan", CHEMICALPOOL_CYAN);412}413#endif414415void ChemicalPool_Serialize(void)416{417RSDK_EDITABLE_VAR(ChemicalPool, VAR_ENUM, type);418RSDK_EDITABLE_VAR(ChemicalPool, VAR_VECTOR2, size);419}420421422