Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/HCZ/HCZSetup.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: HCZSetup Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectHCZSetup *HCZSetup;
11
12
void HCZSetup_Update(void) {}
13
14
void HCZSetup_LateUpdate(void) {}
15
16
void HCZSetup_StaticUpdate(void)
17
{
18
if (!(Zone->timer & 3)) {
19
++HCZSetup->background2Layer->deformationOffsetW;
20
21
// Handle Animating the BG candle & waterline tiles
22
if (!(Zone->timer & 3)) {
23
HCZSetup->bgCandlesAniTileFrame += 0x10;
24
HCZSetup->bgCandlesAniTileFrame &= 0x3F;
25
RSDK.DrawAniTiles(HCZSetup->bgCandlesAniTiles, 386, 0, HCZSetup->bgCandlesAniTileFrame, 64, 16);
26
27
HCZSetup->waterlineAniTileFrame += 0x20;
28
HCZSetup->waterlineAniTileFrame &= 0x1FF;
29
RSDK.DrawAniTiles(HCZSetup->waterlineAniTiles, 820, HCZSetup->waterlineAniTileFrame, 0, 32, 96);
30
RSDK.DrawAniTiles(HCZSetup->waterlineAniTiles, 857, HCZSetup->waterlineAniTileFrame, 96, 32, 128);
31
RSDK.RotatePalette(0, 176, 182, true);
32
}
33
}
34
35
// Handle Animating the pendulum tiles
36
int32 *durations = HCZSetup->pendulumAniTileDurations;
37
int32 duration1 = 0;
38
int32 duration2 = 0;
39
40
for (int32 i = 0; i < 7; ++i) {
41
duration1 += durations[0];
42
duration2 += durations[1];
43
durations += 2;
44
}
45
46
int32 pendulumTimer = Zone->timer % (duration2 + duration1);
47
int32 pendulumAniTileFrame = 0;
48
49
while (pendulumTimer >= HCZSetup->pendulumAniTileDurations[pendulumAniTileFrame]) {
50
pendulumTimer -= HCZSetup->pendulumAniTileDurations[pendulumAniTileFrame++];
51
}
52
53
if (!pendulumTimer)
54
RSDK.DrawAniTiles(HCZSetup->pendulumAniTiles, 874, 0, 16 * pendulumAniTileFrame, 32, 16);
55
56
if (!(Zone->timer & 1)) {
57
for (int32 layerID = Zone->fgLayer[0]; layerID <= Zone->fgLayer[1]; ++layerID) RSDK.GetTileLayer(layerID)->deformationOffsetW++;
58
}
59
60
#if MANIA_USE_PLUS
61
if (HCZSetup->waterslidingPlayerCount) {
62
if (HCZSetup->playingWaterfallLoop) {
63
if (!(HCZSetup->waterfallLoopTimer & 0x1F)) {
64
RSDK.StopSfx(HCZSetup->sfxWaterfall);
65
RSDK.PlaySfx(HCZSetup->sfxWaterfallLoop, false, 0xFF);
66
}
67
}
68
else {
69
HCZSetup->waterfallLoopTimer = 0;
70
HCZSetup->playingWaterfallLoop = true;
71
RSDK.PlaySfx(HCZSetup->sfxWaterfall, false, 0xFF);
72
}
73
++HCZSetup->waterfallLoopTimer;
74
}
75
else {
76
HCZSetup->playingWaterfallLoop = false;
77
}
78
79
HCZSetup->waterslidingPlayerCount = 0;
80
foreach_active(Player, player)
81
{
82
RSDK.GetEntitySlot(player);
83
if (player->state != Player_State_Static) {
84
Hitbox *hitbox = Player_GetHitbox(player);
85
uint16 tile =
86
RSDK.GetTile(Zone->fgLayer[1], player->position.x >> 20, ((hitbox->bottom << 16) + player->position.y - 0x10000) >> 20) & 0x3FF;
87
88
if (((tile >= 226 && tile <= 244) || (tile >= 880 && tile <= 888)) && player->collisionPlane == 1) {
89
if (player->state != Player_State_BubbleBounce && player->state != Player_State_MightyHammerDrop) {
90
if (player->onGround) {
91
if (player->state != Player_State_WaterSlide) {
92
player->interaction = true;
93
player->tileCollisions = TILECOLLISION_DOWN;
94
player->position.y += player->jumpOffset;
95
player->nextGroundState = StateMachine_None;
96
player->state = Player_State_WaterSlide;
97
}
98
99
if (player->onGround)
100
++HCZSetup->waterslidingPlayerCount;
101
}
102
else if (player->animator.animationID == ANI_FLUME)
103
++HCZSetup->waterslidingPlayerCount;
104
}
105
}
106
}
107
}
108
#endif
109
}
110
111
void HCZSetup_Draw(void) {}
112
113
void HCZSetup_Create(void *data) {}
114
115
void HCZSetup_StageLoad(void)
116
{
117
HCZSetup->bgCandlesAniTiles = RSDK.LoadSpriteSheet("HCZ/AniTiles.gif", SCOPE_STAGE);
118
HCZSetup->waterlineAniTiles = RSDK.LoadSpriteSheet("HCZ/AniTiles2.gif", SCOPE_STAGE);
119
HCZSetup->pendulumAniTiles = RSDK.LoadSpriteSheet("HCZ/AniTiles3.gif", SCOPE_STAGE);
120
121
HCZSetup->background2Layer = RSDK.GetTileLayer(1);
122
// Add some deformations to background 2
123
for (int32 i = 0; i < 0x200; i += 0x10) {
124
int32 deformation = RSDK.Rand(0, 4);
125
126
int32 *deformDataW = &HCZSetup->background2Layer->deformationDataW[CLAMP(i, 0, 0x200)];
127
128
int32 angle = 0;
129
for (int32 d = 0; d < 0x10; ++d) {
130
*deformDataW = deformation * RSDK.Sin1024(angle) >> 10;
131
angle += 0x40;
132
}
133
134
memcpy(&HCZSetup->background2Layer->deformationDataW[0x200], &HCZSetup->background2Layer->deformationDataW[0], 0x200 * sizeof(int32));
135
}
136
137
// if Act 2, Setup the waterline effect
138
if (Zone->actID == 1)
139
HCZSetup->background2Layer->scanlineCallback = HCZSetup_Scanline_WaterLine;
140
141
// All Layers between FG Low & FG High get foreground water deformation applied
142
for (int32 layerID = Zone->fgLayer[0]; layerID <= Zone->fgLayer[1]; ++layerID) {
143
TileLayer *layer = RSDK.GetTileLayer(layerID);
144
int32 *deformDataW = layer->deformationDataW;
145
146
// HCZ FG underwater deformation values
147
for (int32 i = 0; i < 4; ++i) {
148
deformDataW[0] = 1;
149
deformDataW[1] = 1;
150
deformDataW[2] = 2;
151
deformDataW[3] = 2;
152
deformDataW[4] = 3;
153
deformDataW[5] = 3;
154
deformDataW[6] = 3;
155
deformDataW[7] = 3;
156
deformDataW[8] = 2;
157
deformDataW[9] = 2;
158
deformDataW[10] = 1;
159
deformDataW[11] = 1;
160
161
deformDataW[128] = 1;
162
deformDataW[129] = 1;
163
deformDataW[130] = 2;
164
deformDataW[131] = 2;
165
deformDataW[132] = 3;
166
deformDataW[133] = 3;
167
deformDataW[134] = 3;
168
deformDataW[135] = 3;
169
deformDataW[136] = 2;
170
deformDataW[137] = 2;
171
deformDataW[138] = 1;
172
deformDataW[139] = 1;
173
174
deformDataW[160] = -1;
175
deformDataW[161] = -1;
176
deformDataW[162] = -2;
177
deformDataW[163] = -2;
178
deformDataW[164] = -3;
179
deformDataW[165] = -3;
180
deformDataW[166] = -3;
181
deformDataW[167] = -3;
182
deformDataW[168] = -2;
183
deformDataW[169] = -2;
184
deformDataW[170] = -1;
185
deformDataW[171] = -1;
186
187
deformDataW += 0x100;
188
}
189
}
190
191
Animals->animalTypes[0] = ANIMAL_POCKY;
192
Animals->animalTypes[1] = ANIMAL_ROCKY;
193
194
RSDK.SetDrawGroupProperties(0, false, Water_DrawHook_ApplyWaterPalette);
195
RSDK.SetDrawGroupProperties(Zone->hudDrawGroup, false, Water_DrawHook_RemoveWaterPalette);
196
197
Water->waterPalette = 1;
198
199
if (Zone->actID) {
200
if (!CutsceneRules_CheckStageReload())
201
CutsceneRules_CheckPlayerPos(TO_FIXED(176), TO_FIXED(1424), TO_FIXED(608), TO_FIXED(1664));
202
203
Zone->cameraBoundsL[0] = 168;
204
Zone->cameraBoundsL[1] = 168;
205
Zone->cameraBoundsL[2] = 168;
206
Zone->cameraBoundsL[3] = 168;
207
208
if (isMainGameMode() && globals->atlEnabled && !CutsceneRules_CheckStageReload())
209
Zone_ReloadStoredEntities(TO_FIXED(388), TO_FIXED(1696), true);
210
211
Zone->stageFinishCallback = HCZSetup_StageFinish_EndAct2;
212
}
213
else if (isMainGameMode() && CutsceneRules_IsAct1()) {
214
Zone->shouldRecoverPlayers = true;
215
Zone->stageFinishCallback = HCZSetup_StageFinish_EndAct1;
216
}
217
218
#if MANIA_USE_PLUS
219
if (SceneInfo->filter & FILTER_ENCORE) {
220
RSDK.LoadPalette(0, "EncoreHCZ.act", 0b0000000011111111);
221
RSDK.LoadPalette(1, "EncoreHCZw.act", 0b0000000011111111);
222
}
223
224
HCZSetup->sfxWaterfall = RSDK.GetSfx("Stage/Waterfall.wav");
225
HCZSetup->sfxWaterfallLoop = RSDK.GetSfx("Stage/Waterfall2.wav");
226
#endif
227
}
228
229
void HCZSetup_Scanline_WaterLine(ScanlineInfo *scanlines)
230
{
231
RSDK.ProcessParallax(HCZSetup->background2Layer);
232
233
RSDKScreenInfo *screen = &ScreenInfo[SceneInfo->currentScreenID];
234
int32 screenY = 0x210 - (screen->position.y >> 2);
235
int32 waterLevel = FROM_FIXED(Water->waterLevel) - screen->position.y;
236
237
int32 scanlineHeight = MAX(0x10000, 0x640000 / MAX(1, abs(screenY - waterLevel)));
238
239
screenY = CLAMP(screenY, 0, screen->size.y);
240
waterLevel = CLAMP(waterLevel, 0, screen->size.y);
241
242
ScanlineInfo *scanlinePtr = &scanlines[screenY];
243
244
// scanlinePtr->position.x handles the horizontal scroll that gives water the parallax effect
245
// scanlinePtr->position.y handles the cool "water line" effect
246
247
// if above OR below, if it's equal, the water covers it all anyways
248
if (screenY > waterLevel) { // below the waterline
249
int32 scanlineY = 1232 << 16; // bottom most tile of the water tiles
250
for (int32 i = 0; i < screenY - waterLevel; ++i) {
251
// 852 = (top most tile of the below water tiles)
252
scanlinePtr->position.x = ((((852 << 16) - 0xC000 * (scanlineY >> 16)) / 100 + 0x10000) * screen->position.x) & 0x1FFFFFF;
253
scanlinePtr->position.y = scanlineY;
254
scanlineY -= scanlineHeight;
255
--scanlinePtr;
256
}
257
}
258
else if (screenY < waterLevel) { // above the waterline
259
int32 scanlineY = 1036 << 16; // top most tile of the water tiles
260
for (int32 i = 0; i < waterLevel - screenY; ++i) {
261
// 1132 = bottom most tile of the above water tiles
262
int32 distance = 1132 - (scanlineY >> 16);
263
scanlinePtr->position.x = (((-0xC000 * distance) / 100 + 0x10000) * screen->position.x) & 0x1FFFFFF;
264
scanlinePtr->position.y = scanlineY;
265
scanlineY += scanlineHeight;
266
++scanlinePtr;
267
}
268
}
269
}
270
271
void HCZSetup_StageFinish_EndAct1(void)
272
{
273
Zone_StoreEntities((Zone->cameraBoundsL[0] + ScreenInfo->center.x) << 16, Zone->cameraBoundsB[0] << 16);
274
RSDK.LoadScene();
275
}
276
277
void HCZSetup_StageFinish_EndAct2(void)
278
{
279
if (globals->gameMode == MODE_MANIA && CHECK_CHARACTER_ID(ID_KNUCKLES, 1))
280
RSDK.SetScene("Cutscenes", "Mirage Saloon K Intro");
281
282
Zone_StartFadeOut(10, 0x000000);
283
}
284
285
#if GAME_INCLUDE_EDITOR
286
void HCZSetup_EditorDraw(void) {}
287
288
void HCZSetup_EditorLoad(void) {}
289
#endif
290
291
void HCZSetup_Serialize(void) {}
292
293