Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/SPZ/MicDrop.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: MicDrop Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectMicDrop *MicDrop;
11
12
void MicDrop_Update(void)
13
{
14
RSDK_THIS(MicDrop);
15
16
StateMachine_Run(self->state);
17
}
18
19
void MicDrop_LateUpdate(void) {}
20
21
void MicDrop_StaticUpdate(void) {}
22
23
void MicDrop_Draw(void)
24
{
25
RSDK_THIS(MicDrop);
26
27
SpriteFrame *frame = RSDK.GetFrame(MicDrop->aniFrames, 1, self->wireAnimator.frameID);
28
SpriteFrame *otherFrame = RSDK.GetFrame(MicDrop->aniFrames, 1, self->wireAnimator.frameID + 4);
29
30
if (self->wireAnimator.frameID == 3) {
31
RSDK.DrawLine(self->startPos.x, self->startPos.y, self->position.x, self->position.y, 0x081828, 0, INK_NONE, false);
32
RSDK.DrawLine(self->startPos.x - 0x10000, self->startPos.y, self->position.x - 0x10000, self->position.y, 0x204078, 0, INK_NONE, false);
33
}
34
else {
35
int32 distance = (self->position.y - self->startPos.y) >> 16;
36
if (distance > 58) {
37
frame->height = otherFrame->height;
38
frame->pivotY = otherFrame->pivotY;
39
frame->sprY = otherFrame->sprY;
40
RSDK.DrawLine(self->startPos.x, self->startPos.y, self->position.x, self->position.y - (58 << 16), 0x081828, 0, INK_NONE, false);
41
RSDK.DrawLine(self->startPos.x - 0x10000, self->startPos.y, self->position.x - 0x10000, self->position.y - (58 << 16), 0x204078, 0,
42
INK_NONE, false);
43
}
44
else {
45
frame->height = distance + 2;
46
frame->pivotY = 1 - distance;
47
frame->sprY = otherFrame->sprY - distance + 58;
48
}
49
}
50
51
RSDK.DrawSprite(&self->wireAnimator, NULL, false);
52
RSDK.DrawSprite(&self->bodyAnimator, NULL, false);
53
}
54
55
void MicDrop_Create(void *data)
56
{
57
RSDK_THIS(MicDrop);
58
59
self->visible = true;
60
self->drawGroup = Zone->objectDrawGroup[0];
61
self->startPos = self->position;
62
self->active = ACTIVE_BOUNDS;
63
self->updateRange.x = 0x800000;
64
self->updateRange.y = 0x800000;
65
self->drawFX = FX_ROTATE | FX_FLIP;
66
67
RSDK.SetSpriteAnimation(MicDrop->aniFrames, 0, &self->bodyAnimator, true, 0);
68
RSDK.SetSpriteAnimation(MicDrop->aniFrames, 1, &self->wireAnimator, true, 0);
69
self->state = MicDrop_State_Init;
70
}
71
72
void MicDrop_StageLoad(void)
73
{
74
if (RSDK.CheckSceneFolder("SPZ1"))
75
MicDrop->aniFrames = RSDK.LoadSpriteAnimation("SPZ1/MicDrop.bin", SCOPE_STAGE);
76
else
77
MicDrop->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/MicDrop.bin", SCOPE_STAGE);
78
79
MicDrop->hitboxBadnik.left = -12;
80
MicDrop->hitboxBadnik.top = -15;
81
MicDrop->hitboxBadnik.right = 12;
82
MicDrop->hitboxBadnik.bottom = 15;
83
84
MicDrop->hitboxRange.left = -128;
85
MicDrop->hitboxRange.top = 0;
86
MicDrop->hitboxRange.right = 128;
87
MicDrop->hitboxRange.bottom = 256;
88
89
DEBUGMODE_ADD_OBJ(MicDrop);
90
91
MicDrop->sfxElectrify = RSDK.GetSfx("Stage/Electrify.wav");
92
}
93
94
void MicDrop_DebugSpawn(void)
95
{
96
RSDK_THIS(DebugMode);
97
98
EntityMicDrop *micDrop = CREATE_ENTITY(MicDrop, NULL, self->position.x, self->position.y);
99
micDrop->distance = 128;
100
}
101
102
void MicDrop_DebugDraw(void)
103
{
104
RSDK.SetSpriteAnimation(MicDrop->aniFrames, 0, &DebugMode->animator, true, 0);
105
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
106
}
107
108
void MicDrop_CheckPlayerCollisions(void)
109
{
110
RSDK_THIS(MicDrop);
111
112
int32 storeX = self->position.x;
113
int32 storeY = self->position.y;
114
115
self->position.x = (((self->radius + 25) * RSDK.Cos512(self->angle + 128)) << 7) + self->startPos.x;
116
self->position.y = (((self->radius + 25) * RSDK.Sin512(self->angle + 128)) << 7) + self->startPos.y;
117
118
foreach_active(Player, player)
119
{
120
if (Player_CheckBadnikTouch(player, self, &MicDrop->hitboxBadnik)) {
121
if (self->bodyAnimator.animationID != 3 || player->shield == SHIELD_LIGHTNING || player->invincibleTimer || player->blinkTimer)
122
Player_CheckBadnikBreak(player, self, true);
123
else
124
Player_Hurt(player, self);
125
}
126
}
127
128
self->position.x = storeX;
129
self->position.y = storeY;
130
}
131
132
void MicDrop_CheckOffScreen(void)
133
{
134
RSDK_THIS(MicDrop);
135
136
if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {
137
self->position.x = self->startPos.x;
138
self->position.y = self->startPos.y;
139
MicDrop_Create(NULL);
140
}
141
}
142
143
void MicDrop_State_Init(void)
144
{
145
RSDK_THIS(MicDrop);
146
147
self->active = ACTIVE_NORMAL;
148
self->velocity.y = 0;
149
self->direction = FLIP_NONE;
150
self->timer = 0;
151
self->swingPos = 0;
152
self->angle = 0;
153
self->rotation = 0;
154
155
self->state = MicDrop_State_CheckForPlayer;
156
MicDrop_State_CheckForPlayer();
157
}
158
159
void MicDrop_State_CheckForPlayer(void)
160
{
161
RSDK_THIS(MicDrop);
162
163
foreach_active(Player, player)
164
{
165
if (Player_CheckCollisionTouch(player, self, &MicDrop->hitboxRange))
166
self->state = MicDrop_State_DropDown;
167
}
168
169
MicDrop_CheckPlayerCollisions();
170
}
171
172
void MicDrop_State_DropDown(void)
173
{
174
RSDK_THIS(MicDrop);
175
176
self->position.y += self->velocity.y;
177
self->velocity.y += 0x3800;
178
179
self->radius = (self->position.y - self->startPos.y) >> 16;
180
if (self->radius >= 0x20000)
181
self->bodyAnimator.frameID = 3;
182
183
if (self->radius >= self->distance) {
184
self->radius = self->distance;
185
self->position.y = self->startPos.y + (self->distance << 16);
186
self->bodyAnimator.frameID = 4;
187
self->state = MicDrop_State_DropRecoil;
188
}
189
190
MicDrop_CheckPlayerCollisions();
191
}
192
193
void MicDrop_State_DropRecoil(void)
194
{
195
RSDK_THIS(MicDrop);
196
197
switch (++self->timer) {
198
case 2:
199
self->wireAnimator.frameID = 1;
200
self->bodyAnimator.frameID = 5;
201
break;
202
203
case 4:
204
self->wireAnimator.frameID = 2;
205
self->bodyAnimator.frameID = 1;
206
break;
207
208
case 6:
209
self->wireAnimator.frameID = 3;
210
self->bodyAnimator.frameID = 0;
211
212
self->timer = 0;
213
self->state = MicDrop_State_Idle;
214
break;
215
}
216
217
MicDrop_CheckPlayerCollisions();
218
MicDrop_CheckOffScreen();
219
}
220
221
void MicDrop_State_Idle(void)
222
{
223
RSDK_THIS(MicDrop);
224
225
if (++self->timer >= 30) {
226
self->swingSpeed = 64;
227
self->swingVel = 4;
228
self->state = MicDrop_State_Swinging;
229
}
230
231
MicDrop_CheckPlayerCollisions();
232
MicDrop_CheckOffScreen();
233
}
234
235
void MicDrop_State_Swinging(void)
236
{
237
RSDK_THIS(MicDrop);
238
239
self->swingPos += self->swingSpeed;
240
if (self->swingPos < 0) {
241
self->swingVel = 1;
242
self->swingPos -= self->swingSpeed;
243
self->swingSpeed >>= 1;
244
245
self->state = MicDrop_State_Electrify;
246
MicDrop_State_Electrify();
247
}
248
else {
249
self->rotation = self->swingPos >> 4;
250
self->angle = self->rotation >> 2;
251
self->swingSpeed -= self->swingVel;
252
self->position.x = self->startPos.x + (self->radius << 7) * RSDK.Cos512(self->angle + 0x80);
253
self->position.y = self->startPos.y + (self->radius << 7) * RSDK.Sin512(self->angle + 0x80);
254
255
MicDrop_CheckPlayerCollisions();
256
MicDrop_CheckOffScreen();
257
}
258
}
259
260
void MicDrop_State_Electrify(void)
261
{
262
RSDK_THIS(MicDrop);
263
264
self->swingPos += self->swingSpeed;
265
self->angle = self->swingPos >> 4;
266
self->rotation = self->angle;
267
if (self->angle >= 0)
268
self->swingSpeed -= self->swingVel;
269
else
270
self->swingSpeed += self->swingVel;
271
272
self->position.x = self->startPos.x + (self->radius << 7) * RSDK.Cos512(self->angle + 0x80);
273
self->position.y = self->startPos.y + (self->radius << 7) * RSDK.Sin512(self->angle + 0x80);
274
275
switch (++self->timer) {
276
case 60: RSDK.SetSpriteAnimation(MicDrop->aniFrames, 2, &self->bodyAnimator, true, 0); break;
277
278
case 90:
279
RSDK.PlaySfx(MicDrop->sfxElectrify, false, 0xFF);
280
RSDK.SetSpriteAnimation(MicDrop->aniFrames, 3, &self->bodyAnimator, true, 0);
281
break;
282
283
case 120:
284
self->timer = 0;
285
RSDK.SetSpriteAnimation(MicDrop->aniFrames, 0, &self->bodyAnimator, true, 0);
286
break;
287
}
288
289
if (self->timer >= 60)
290
RSDK.ProcessAnimation(&self->bodyAnimator);
291
292
MicDrop_CheckPlayerCollisions();
293
MicDrop_CheckOffScreen();
294
}
295
296
#if GAME_INCLUDE_EDITOR
297
void MicDrop_EditorDraw(void)
298
{
299
RSDK_THIS(MicDrop);
300
301
self->startPos.y = self->position.y;
302
self->position.y = self->startPos.y + (self->distance << 16);
303
304
MicDrop_Draw();
305
306
self->position.y = self->startPos.y;
307
}
308
309
void MicDrop_EditorLoad(void)
310
{
311
if (RSDK.CheckSceneFolder("SPZ1"))
312
MicDrop->aniFrames = RSDK.LoadSpriteAnimation("SPZ1/MicDrop.bin", SCOPE_STAGE);
313
else
314
MicDrop->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/MicDrop.bin", SCOPE_STAGE);
315
}
316
#endif
317
318
void MicDrop_Serialize(void) { RSDK_EDITABLE_VAR(MicDrop, VAR_UINT16, distance); }
319
320