Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/AIZ/SchrodingersCapsule.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: SchrodingersCapsule Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
#if MANIA_USE_PLUS
11
ObjectSchrodingersCapsule *SchrodingersCapsule;
12
13
void SchrodingersCapsule_Update(void)
14
{
15
RSDK_THIS(SchrodingersCapsule);
16
StateMachine_Run(self->state);
17
18
if (self->mainAnimator.frameID != 1) {
19
bool32 stoodSolid = false;
20
foreach_active(Player, player)
21
{
22
if (Player_CheckCollisionBox(player, self, &self->hitboxSolid) == C_TOP)
23
stoodSolid = true;
24
25
if (self->state == SchrodingersCapsule_State_HandleBounds) {
26
if (Player_CheckCollisionBox(player, self, &self->hitboxButton) == C_TOP) {
27
self->buttonPos = 0x80000;
28
player->velocity.x = 0;
29
player->groundVel = 0;
30
CutsceneSeq_LockPlayerControl(player);
31
stoodSolid = false;
32
player->state = Player_State_Ground;
33
player->stateInput = StateMachine_None;
34
self->active = ACTIVE_NORMAL;
35
self->state = SchrodingersCapsule_State_Activated;
36
}
37
else {
38
if (Player_CheckCollisionTouch(player, self, &self->hitboxButtonTrigger)) {
39
Hitbox *playerHitbox = Player_GetHitbox(player);
40
self->buttonPos = ((playerHitbox->bottom + 48) << 16) - self->position.y + player->position.y;
41
if (self->buttonPos <= 0x80000) {
42
if (self->buttonPos < 0)
43
self->buttonPos = 0;
44
self->buttonPos &= 0xFFFF0000;
45
}
46
else {
47
self->buttonPos = 0x80000;
48
self->buttonPos &= 0xFFFF0000;
49
}
50
}
51
else {
52
if (self->buttonPos > 0)
53
self->buttonPos -= 0x10000;
54
}
55
56
if (stoodSolid) {
57
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
58
if (ruby->velocity.y > 0)
59
ruby->velocity.y = -ruby->velocity.y;
60
ruby->state = EncoreIntro_PhantomRuby_CapsuleRiseUp;
61
}
62
}
63
}
64
else {
65
stoodSolid = false;
66
Player_CheckCollisionBox(player, self, &self->hitboxButton);
67
}
68
}
69
}
70
}
71
72
void SchrodingersCapsule_LateUpdate(void) {}
73
74
void SchrodingersCapsule_StaticUpdate(void) {}
75
76
void SchrodingersCapsule_Draw(void)
77
{
78
RSDK_THIS(SchrodingersCapsule);
79
Vector2 drawPos;
80
81
if (!self->mainAnimator.frameID) {
82
drawPos = self->position;
83
drawPos.y += self->buttonPos;
84
RSDK.DrawSprite(&self->buttonAnimator, &drawPos, false);
85
86
self->mainAnimator.frameID = 2;
87
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
88
89
if ((Zone->timer & 8)) {
90
self->mainAnimator.frameID = 3;
91
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
92
}
93
94
drawPos = self->position;
95
drawPos.x += 0xE0000;
96
RSDK.DrawSprite(&self->mightyAnimator, &drawPos, false);
97
98
drawPos.x -= 0x1C0000;
99
RSDK.DrawSprite(&self->rayAnimator, &drawPos, false);
100
101
self->mainAnimator.frameID = 0;
102
}
103
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
104
105
if (!self->mainAnimator.frameID) {
106
self->inkEffect = INK_ADD;
107
self->alpha = 0x80;
108
RSDK.DrawSprite(&self->glassAnimator, NULL, false);
109
110
self->inkEffect = INK_NONE;
111
}
112
}
113
114
void SchrodingersCapsule_Create(void *data)
115
{
116
RSDK_THIS(SchrodingersCapsule);
117
self->drawFX = FX_FLIP;
118
if (!SceneInfo->inEditor) {
119
RSDK.SetSpriteAnimation(SchrodingersCapsule->aniFrames, 0, &self->mainAnimator, true, 0);
120
RSDK.SetSpriteAnimation(SchrodingersCapsule->aniFrames, 1, &self->buttonAnimator, true, 0);
121
RSDK.SetSpriteAnimation(SchrodingersCapsule->aniFrames, 2, &self->glassAnimator, true, 0);
122
RSDK.SetSpriteAnimation(SchrodingersCapsule->aniFrames, 3, &self->mightyAnimator, true, 0);
123
RSDK.SetSpriteAnimation(SchrodingersCapsule->aniFrames, 4, &self->rayAnimator, true, 0);
124
125
self->hitboxSolid.left = -40;
126
self->hitboxSolid.top = -40;
127
self->hitboxSolid.right = 40;
128
self->hitboxSolid.bottom = 40;
129
130
self->hitboxButton.left = -16;
131
self->hitboxButton.top = -44;
132
self->hitboxButton.right = 16;
133
self->hitboxButton.bottom = -30;
134
135
self->hitboxButtonTrigger.left = -15;
136
self->hitboxButtonTrigger.top = -60;
137
self->hitboxButtonTrigger.right = 15;
138
self->hitboxButtonTrigger.bottom = -30;
139
140
self->state = SchrodingersCapsule_State_Init;
141
self->active = ACTIVE_BOUNDS;
142
self->updateRange.x = 0x800000;
143
self->updateRange.y = 0x800000;
144
self->visible = true;
145
self->drawGroup = Zone->objectDrawGroup[0];
146
}
147
}
148
149
void SchrodingersCapsule_StageLoad(void)
150
{
151
SchrodingersCapsule->aniFrames = RSDK.LoadSpriteAnimation("AIZ/SchrodingersCapsule.bin", SCOPE_STAGE);
152
153
SchrodingersCapsule->sfxExplosion2 = RSDK.GetSfx("Stage/Explosion2.wav");
154
SchrodingersCapsule->sfxExplosion3 = RSDK.GetSfx("Stage/Explosion3.wav");
155
}
156
157
void SchrodingersCapsule_State_Init(void)
158
{
159
RSDK_THIS(SchrodingersCapsule);
160
161
self->state = SchrodingersCapsule_State_HandleBounds;
162
}
163
164
void SchrodingersCapsule_State_HandleBounds(void)
165
{
166
RSDK_THIS(SchrodingersCapsule);
167
168
RSDK.ProcessAnimation(&self->glassAnimator);
169
RSDK.ProcessAnimation(&self->mightyAnimator);
170
RSDK.ProcessAnimation(&self->rayAnimator);
171
172
for (int32 p = 0; p < Player->playerCount; ++p) {
173
EntityPlayer *player = RSDK_GET_ENTITY(p, Player);
174
if (!player->sidekick) {
175
if (abs(self->position.x - player->position.x) < 0x1000000) {
176
if (abs(self->position.y - player->position.y) < 0x1000000 && self->position.x - (Zone->cameraBoundsR[p] << 16) < 0x1000000) {
177
Zone->playerBoundActiveL[p] = true;
178
Zone->playerBoundActiveR[p] = true;
179
Zone->cameraBoundsL[p] = (self->position.x >> 16) - ScreenInfo[p].center.x;
180
Zone->cameraBoundsR[p] = (self->position.x >> 16) + ScreenInfo[p].center.x;
181
}
182
}
183
}
184
}
185
}
186
187
void SchrodingersCapsule_State_Activated(void)
188
{
189
RSDK_THIS(SchrodingersCapsule);
190
RSDK.ProcessAnimation(&self->glassAnimator);
191
RSDK.ProcessAnimation(&self->mightyAnimator);
192
RSDK.ProcessAnimation(&self->rayAnimator);
193
RSDK.SetSpriteAnimation(-1, 0, &self->glassAnimator, true, 0);
194
self->state = SchrodingersCapsule_State_Explode;
195
SceneInfo->timeEnabled = false;
196
}
197
198
void SchrodingersCapsule_State_Explode(void)
199
{
200
RSDK_THIS(SchrodingersCapsule);
201
RSDK.ProcessAnimation(&self->glassAnimator);
202
RSDK.ProcessAnimation(&self->mightyAnimator);
203
RSDK.ProcessAnimation(&self->rayAnimator);
204
if (!(self->timer % 3)) {
205
EntityExplosion *explosion = CREATE_ENTITY(Explosion, INT_TO_VOID((2 * (RSDK.Rand(0, 256) > 192) + EXPLOSION_ENEMY)),
206
(RSDK.Rand(-24, 24) << 16) + self->position.x, (RSDK.Rand(-24, 24) << 16) + self->position.y);
207
explosion->drawGroup = Zone->objectDrawGroup[1];
208
209
RSDK.PlaySfx(SchrodingersCapsule->sfxExplosion2, false, 0xFF);
210
}
211
212
if (++self->timer == 60) {
213
self->timer = 0;
214
self->state = StateMachine_None;
215
self->mainAnimator.frameID = 1;
216
RSDK.SetSpriteAnimation(-1, -1, &self->mightyAnimator, true, 0);
217
RSDK.SetSpriteAnimation(-1, -1, &self->rayAnimator, true, 0);
218
219
EntityPlayer *buddy1 = RSDK_GET_ENTITY(SLOT_PLAYER3, Player);
220
memset(buddy1, 0, sizeof(EntityBase)); // not in the original, clears the entity slot incase of something like a shield is still active
221
buddy1->classID = Player->classID;
222
Player_ChangeCharacter(buddy1, ID_MIGHTY);
223
buddy1->position.x = self->position.x + TO_FIXED(14);
224
buddy1->position.y = self->position.y;
225
buddy1->playerID = RSDK.GetEntitySlot(buddy1);
226
buddy1->active = ACTIVE_NORMAL;
227
buddy1->tileCollisions = TILECOLLISION_DOWN;
228
buddy1->interaction = true;
229
buddy1->visible = true;
230
buddy1->controllerID = buddy1->playerID + 1;
231
buddy1->drawGroup = Zone->playerDrawGroup[0];
232
buddy1->scale.x = 0x200;
233
buddy1->scale.y = 0x200;
234
buddy1->state = Player_State_Ground;
235
buddy1->collisionLayers = Zone->collisionLayers;
236
buddy1->drawFX = FX_ROTATE | FX_FLIP;
237
buddy1->velocity.x = 0x1C000;
238
buddy1->velocity.y = -0x40000;
239
buddy1->direction = FLIP_X;
240
RSDK.SetSpriteAnimation(buddy1->aniFrames, ANI_HURT, &buddy1->animator, true, 0);
241
242
EntityPlayer *buddy2 = RSDK_GET_ENTITY(SLOT_PLAYER4, Player);
243
memset(buddy2, 0, sizeof(EntityBase)); // like above, but for safety :]
244
buddy2->classID = Player->classID;
245
Player_ChangeCharacter(buddy2, ID_RAY);
246
buddy2->position.x = self->position.x - TO_FIXED(14);
247
buddy2->position.y = self->position.y;
248
buddy2->playerID = RSDK.GetEntitySlot(buddy2);
249
buddy2->active = ACTIVE_NORMAL;
250
buddy2->tileCollisions = TILECOLLISION_DOWN;
251
buddy2->interaction = true;
252
buddy2->visible = true;
253
buddy2->controllerID = buddy2->playerID + 1;
254
buddy2->drawGroup = Zone->playerDrawGroup[0];
255
buddy2->scale.x = 0x200;
256
buddy2->scale.y = 0x200;
257
buddy2->state = Player_State_Ground;
258
buddy2->collisionLayers = Zone->collisionLayers;
259
buddy2->drawFX = FX_ROTATE | FX_FLIP;
260
buddy2->velocity.x = -0x24000;
261
buddy2->velocity.y = -0x40000;
262
RSDK.SetSpriteAnimation(buddy2->aniFrames, ANI_HURT, &buddy2->animator, true, 0);
263
264
Music_FadeOut(0.025);
265
RSDK.PlaySfx(SchrodingersCapsule->sfxExplosion3, false, 0xFF);
266
267
EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
268
player->position.x = self->position.x;
269
Player_ChangeCharacter(player, player->characterID);
270
RSDK.SetSpriteAnimation(player->aniFrames, ANI_HURT, &player->animator, true, 0);
271
player->velocity.x = 0;
272
player->velocity.y = 0;
273
player->groundVel = 0;
274
player->stateInput = StateMachine_None;
275
player->left = false;
276
player->right = false;
277
player->jumpPress = false;
278
player->jumpHold = false;
279
280
EntityCamera *camera = RSDK_GET_ENTITY(SLOT_CAMERA1, Camera);
281
camera->position.x += 0x100000;
282
283
self->timer = 0;
284
self->state = SchrodingersCapsule_State_SetupActClear;
285
286
EntityFXFade *fade = CREATE_ENTITY(FXFade, INT_TO_VOID(0xF0F0F0), self->position.x, self->position.y);
287
fade->speedIn = 256;
288
fade->speedOut = 32;
289
}
290
}
291
292
void SchrodingersCapsule_State_SetupActClear(void)
293
{
294
RSDK_THIS(SchrodingersCapsule);
295
if (++self->timer == 90) {
296
self->timer = 0;
297
self->state = StateMachine_None;
298
299
EntityPlayer *buddy1 = RSDK_GET_ENTITY(SLOT_PLAYER3, Player);
300
buddy1->state = Player_State_Victory;
301
RSDK.SetSpriteAnimation(buddy1->aniFrames, ANI_VICTORY, &buddy1->animator, true, 0);
302
303
EntityPlayer *buddy2 = RSDK_GET_ENTITY(SLOT_PLAYER4, Player);
304
buddy2->state = Player_State_Victory;
305
RSDK.SetSpriteAnimation(buddy2->aniFrames, ANI_VICTORY, &buddy2->animator, true, 0);
306
307
ActClear->displayedActID = 1;
308
ActClear->forceNoSave = true;
309
Music_PlayTrack(TRACK_ACTCLEAR);
310
RSDK.ResetEntitySlot(SLOT_ACTCLEAR, ActClear->classID, NULL);
311
}
312
}
313
314
#if GAME_INCLUDE_EDITOR
315
void SchrodingersCapsule_EditorDraw(void)
316
{
317
RSDK_THIS(SchrodingersCapsule);
318
319
RSDK.SetSpriteAnimation(SchrodingersCapsule->aniFrames, 0, &self->mainAnimator, true, 0);
320
RSDK.SetSpriteAnimation(SchrodingersCapsule->aniFrames, 1, &self->buttonAnimator, true, 0);
321
RSDK.SetSpriteAnimation(SchrodingersCapsule->aniFrames, 2, &self->glassAnimator, true, 0);
322
RSDK.SetSpriteAnimation(SchrodingersCapsule->aniFrames, 3, &self->mightyAnimator, true, 0);
323
RSDK.SetSpriteAnimation(SchrodingersCapsule->aniFrames, 4, &self->rayAnimator, true, 0);
324
325
SchrodingersCapsule_Draw();
326
}
327
328
void SchrodingersCapsule_EditorLoad(void) { SchrodingersCapsule->aniFrames = RSDK.LoadSpriteAnimation("AIZ/SchrodingersCapsule.bin", SCOPE_STAGE); }
329
#endif
330
331
void SchrodingersCapsule_Serialize(void) {}
332
#endif
333
334