Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/TMZ/SentryBug.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: SentryBug Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectSentryBug *SentryBug;
11
12
void SentryBug_Update(void)
13
{
14
RSDK_THIS(SentryBug);
15
16
RSDK.ProcessAnimation(&self->bugAnimator);
17
18
StateMachine_Run(self->state);
19
StateMachine_Run(self->stateOrbs);
20
}
21
22
void SentryBug_LateUpdate(void) {}
23
24
void SentryBug_StaticUpdate(void) {}
25
26
void SentryBug_Draw(void)
27
{
28
RSDK_THIS(SentryBug);
29
30
if (self->orbsDetached) {
31
RSDK.DrawSprite(&self->bugAnimator, NULL, false);
32
33
if (self->showNet) {
34
RSDK.MatrixScaleXYZ(&self->matTransform, self->netScale >> 4, self->netScale >> 4, self->netScale >> 4);
35
RSDK.MatrixTranslateXYZ(&self->matTransform, self->netPos.x, self->netPos.y, 0, false);
36
RSDK.MatrixRotateXYZ(&self->matWorld, self->netRotation, self->netRotation, 0);
37
RSDK.MatrixMultiply(&self->matWorld, &self->matWorld, &self->matTransform);
38
39
RSDK.Prepare3DScene(SentryBug->sceneIndex);
40
RSDK.AddModelTo3DScene(SentryBug->meshFrames, SentryBug->sceneIndex, S3D_WIREFRAME, &self->matWorld, NULL, self->netColor);
41
42
self->inkEffect = INK_ALPHA;
43
RSDK.Draw3DScene(SentryBug->sceneIndex);
44
self->inkEffect = INK_NONE;
45
}
46
47
for (int32 angle = 0, i = 0; angle < 0xFC; ++i) {
48
self->orbAnimator.frameID = ((angle + self->netRotation + 8) >> 5) & 7;
49
if (self->netColor == 0xF0F000)
50
self->orbAnimator.frameID += 8;
51
52
RSDK.DrawSprite(&self->orbAnimator, &self->orbPositions[i], false);
53
54
angle += 42;
55
}
56
}
57
else {
58
RSDK.DrawSprite(&self->orbAnimator, &self->orbPositions[0], false);
59
RSDK.DrawSprite(&self->orbAnimator, &self->orbPositions[1], false);
60
RSDK.DrawSprite(&self->orbAnimator, &self->orbPositions[2], false);
61
62
RSDK.DrawSprite(&self->bugAnimator, NULL, false);
63
64
RSDK.DrawSprite(&self->orbAnimator, &self->orbPositions[3], false);
65
RSDK.DrawSprite(&self->orbAnimator, &self->orbPositions[4], false);
66
RSDK.DrawSprite(&self->orbAnimator, &self->orbPositions[5], false);
67
}
68
}
69
70
void SentryBug_Create(void *data)
71
{
72
RSDK_THIS(SentryBug);
73
74
self->drawFX = FX_FLIP;
75
if (!SceneInfo->inEditor) {
76
self->active = ACTIVE_BOUNDS;
77
self->updateRange.x = 0x800000;
78
self->updateRange.y = 0x800000;
79
self->visible = true;
80
self->drawGroup = Zone->objectDrawGroup[0];
81
self->amplitude.x >>= 10;
82
self->amplitude.y >>= 10;
83
self->originPos = self->position;
84
self->startPos = self->position;
85
self->netColor = 0xF02000;
86
self->alpha = 0x100;
87
88
if (!self->speed)
89
self->speed = 4;
90
91
if (self->amplitude.x >= 0)
92
RSDK.SetSpriteAnimation(SentryBug->aniFrames, 1, &self->bugAnimator, true, 6);
93
else
94
RSDK.SetSpriteAnimation(SentryBug->aniFrames, 0, &self->bugAnimator, true, 6);
95
96
RSDK.SetSpriteAnimation(SentryBug->aniFrames, 2, &self->orbAnimator, true, 0);
97
98
self->state = SentryBug_State_AwaitPlayer;
99
self->stateOrbs = SentryBug_StateOrbs_Attached;
100
}
101
}
102
103
void SentryBug_StageLoad(void)
104
{
105
if (RSDK.CheckSceneFolder("TMZ1") || RSDK.CheckSceneFolder("TMZ2"))
106
SentryBug->aniFrames = RSDK.LoadSpriteAnimation("TMZ1/SentryBug.bin", SCOPE_STAGE);
107
108
SentryBug->meshFrames = RSDK.LoadMesh("TMZ/OrbNet.bin", SCOPE_STAGE);
109
SentryBug->sceneIndex = RSDK.Create3DScene("View:SentryBug", 512, SCOPE_STAGE);
110
111
SentryBug->hitbox.left = -12;
112
SentryBug->hitbox.top = -12;
113
SentryBug->hitbox.right = 12;
114
SentryBug->hitbox.bottom = 12;
115
116
SentryBug->sfxPon = RSDK.GetSfx("Stage/Pon.wav");
117
SentryBug->sfxSwarm = RSDK.GetSfx("TMZ1/CyberSwarm.wav");
118
119
DEBUGMODE_ADD_OBJ(SentryBug);
120
}
121
122
void SentryBug_DebugSpawn(void)
123
{
124
RSDK_THIS(SentryBug);
125
126
EntitySentryBug *sentryBug = CREATE_ENTITY(SentryBug, NULL, self->position.x, self->position.y);
127
sentryBug->amplitude.x = 0x1200;
128
sentryBug->amplitude.y = 0x400;
129
sentryBug->timer = 60;
130
}
131
132
void SentryBug_DebugDraw(void)
133
{
134
RSDK.SetSpriteAnimation(SentryBug->aniFrames, 0, &DebugMode->animator, true, 0);
135
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
136
}
137
138
void SentryBug_CheckPlayerCollisions(void)
139
{
140
RSDK_THIS(SentryBug);
141
142
foreach_active(Player, player)
143
{
144
if (Player_CheckBadnikTouch(player, self, &SentryBug->hitbox)) {
145
if (Player_CheckBadnikBreak(player, self, true))
146
RSDK.StopSfx(SentryBug->sfxSwarm);
147
}
148
}
149
}
150
151
void SentryBug_SetupOrbDropVelocity(void)
152
{
153
RSDK_THIS(SentryBug);
154
155
Vector2 *velocity = NULL;
156
if (self->bugAnimator.animationID == 1)
157
velocity = (Vector2 *)SentryBug->dropVelR;
158
else
159
velocity = (Vector2 *)SentryBug->dropVelL;
160
161
for (int32 i = 0; i < 6; ++i) {
162
self->orbVelocities[i].x = velocity[i].x;
163
self->orbVelocities[i].y = velocity[i].y;
164
}
165
}
166
167
void SentryBug_StateOrbs_Attached(void)
168
{
169
RSDK_THIS(SentryBug);
170
171
Vector2 *offsets = NULL;
172
if (self->bugAnimator.animationID == 1)
173
offsets = (Vector2 *)&SentryBug->orbOffsets_Attached[12 * self->bugAnimator.frameID];
174
else
175
offsets = (Vector2 *)&SentryBug->orbOffsets_Attached[-12 * self->bugAnimator.frameID + 72];
176
177
for (int32 i = 0; i < 6; ++i) {
178
self->orbPositions[i].x = self->position.x + offsets[i].x;
179
self->orbPositions[i].y = self->position.y + offsets[i].y;
180
}
181
}
182
183
void SentryBug_StateOrbs_Dropped(void)
184
{
185
RSDK_THIS(SentryBug);
186
187
for (int32 i = 0; i < 6; ++i) {
188
self->orbVelocities[i].y += 0x2800;
189
self->orbPositions[i].x += self->orbVelocities[i].x;
190
self->orbPositions[i].y += self->orbVelocities[i].y;
191
}
192
}
193
194
void SentryBug_StateOrbs_BeginNetRotation(void)
195
{
196
RSDK_THIS(SentryBug);
197
198
int32 angle = self->netRotation;
199
for (int32 i = 0; i < 6; ++i) {
200
int32 x = self->netScale * RSDK.Cos256(angle) + self->netPos.x;
201
int32 y = self->netScale * RSDK.Sin256(angle) + self->netPos.y;
202
203
self->orbVelocities[i].x = (x - self->orbPositions[i].x) >> 3;
204
self->orbVelocities[i].y = (y - self->orbPositions[i].y) >> 3;
205
self->orbPositions[i].x += self->orbVelocities[i].x;
206
self->orbPositions[i].y += self->orbVelocities[i].y;
207
angle += 42;
208
}
209
210
self->netRotation += 4;
211
}
212
213
void SentryBug_StateOrbs_RotateAroundNet(void)
214
{
215
RSDK_THIS(SentryBug);
216
217
int32 angle = self->netRotation;
218
for (int32 i = 0; i < 6; ++i) {
219
self->orbPositions[i].x = self->netScale * RSDK.Cos256(angle) + self->netPos.x;
220
self->orbPositions[i].y = self->netScale * RSDK.Sin256(angle) + self->netPos.y;
221
angle += 42;
222
}
223
224
self->netRotation += 4;
225
}
226
227
void SentryBug_StateOrbs_ReturnToSlots(void)
228
{
229
RSDK_THIS(SentryBug);
230
231
Vector2 *offsets = NULL;
232
if (self->bugAnimator.animationID == 1)
233
offsets = (Vector2 *)&SentryBug->orbOffsets_Attached[12 * self->bugAnimator.frameID];
234
else
235
offsets = (Vector2 *)&SentryBug->orbOffsets_Attached[-12 * self->bugAnimator.frameID + 72];
236
237
for (int32 i = 0; i < 6; ++i) {
238
self->orbVelocities[i].x = CLAMP((self->position.x + offsets[i].x - self->orbPositions[i].x) >> 3, -0xC0000, 0xC0000);
239
self->orbVelocities[i].y = CLAMP((self->position.y + offsets[i].y - self->orbPositions[i].y) >> 3, -0xC0000, 0xC0000);
240
241
self->orbPositions[i].x += self->orbVelocities[i].x;
242
self->orbPositions[i].y += self->orbVelocities[i].y;
243
}
244
}
245
246
void SentryBug_State_AwaitPlayer(void)
247
{
248
RSDK_THIS(SentryBug);
249
250
int32 x = self->position.x;
251
252
self->angle = (self->angle + self->speed) & 0x3FF;
253
self->position.x = self->amplitude.x * RSDK.Sin1024(self->angle) + self->originPos.x;
254
self->position.y = self->amplitude.y * RSDK.Sin1024(2 * self->angle) + self->originPos.y;
255
RSDK.SetSpriteAnimation(SentryBug->aniFrames, (x - self->position.x) < 0, &self->bugAnimator, false, 0);
256
257
if (self->timer > 0)
258
self->timer--;
259
260
EntityPlayer *player = Player_GetNearestPlayer();
261
if (player) {
262
if (!self->timer) {
263
int32 rx = (self->position.x - player->position.x) >> 16;
264
int32 ry = (self->position.y - player->position.y) >> 16;
265
266
if (rx * rx + ry * ry < 0x2400) {
267
self->originPos.x = self->position.x;
268
self->originPos.y = self->position.y;
269
self->angle = 0;
270
self->playerPtr = player;
271
self->netScale = 0x6800;
272
self->drawGroup = Zone->objectDrawGroup[1];
273
self->active = ACTIVE_NORMAL;
274
275
RSDK.PlaySfx(SentryBug->sfxPon, false, 255);
276
277
SentryBug_SetupOrbDropVelocity();
278
self->stateOrbs = SentryBug_StateOrbs_Dropped;
279
280
RSDK.PlaySfx(SentryBug->sfxSwarm, false, 255);
281
self->state = SentryBug_State_DropOrbs;
282
}
283
}
284
}
285
286
SentryBug_CheckPlayerCollisions();
287
}
288
289
void SentryBug_State_DropOrbs(void)
290
{
291
RSDK_THIS(SentryBug);
292
293
EntityPlayer *player = self->playerPtr;
294
295
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 4, 10);
296
297
self->netPos.x = player->position.x;
298
self->netPos.y = player->position.y;
299
300
if (++self->timer == 120) {
301
self->timer = 0;
302
self->netScale = 0x6000;
303
self->stateOrbs = SentryBug_StateOrbs_RotateAroundNet;
304
self->showNet = true;
305
self->state = SentryBug_State_NetAppear;
306
}
307
308
if (self->timer == 30) {
309
self->orbsDetached = true;
310
self->stateOrbs = SentryBug_StateOrbs_BeginNetRotation;
311
}
312
313
SentryBug_CheckPlayerCollisions();
314
}
315
316
void SentryBug_State_NetAppear(void)
317
{
318
RSDK_THIS(SentryBug);
319
320
EntityPlayer *player = self->playerPtr;
321
322
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 4, 10);
323
324
self->netPos.x += (player->position.x - self->netPos.x) >> 3;
325
self->netPos.y += (player->position.y - self->netPos.y) >> 3;
326
SentryBug_CheckPlayerCollisions();
327
328
self->alpha = 0xA0 + (RSDK.Sin256(4 * Zone->timer) >> 2);
329
330
if (++self->timer == 60) {
331
self->timer = 0;
332
self->state = SentryBug_State_NetShrink;
333
}
334
}
335
336
void SentryBug_State_NetShrink(void)
337
{
338
RSDK_THIS(SentryBug);
339
340
EntityPlayer *player = self->playerPtr;
341
342
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 4, 10);
343
344
self->netPos.x += (player->position.x - self->netPos.x) >> 3;
345
self->netPos.y += ((player->position.y - self->netPos.y) >> 3);
346
347
int32 rx = (self->netPos.x - self->position.x) >> 16;
348
int32 ry = (self->netPos.y - self->position.y) >> 16;
349
350
self->alpha = 0xA0 + (RSDK.Sin256(4 * Zone->timer) >> 2);
351
352
if (rx * rx + ry * ry <= 0x40000) {
353
if (self->netScale <= 0x1800) {
354
rx = (self->netPos.x - player->position.x) >> 16;
355
ry = (self->netPos.y - player->position.y) >> 16;
356
357
if (rx * rx + ry * ry < 0x200 && Player_CheckValidState(player)) {
358
self->showNet = true;
359
self->alpha = 0x100;
360
self->state = SentryBug_State_NetFlash;
361
self->isPermanent = true;
362
}
363
else {
364
self->orbAnimator.frameID = 0;
365
self->orbsDetached = false;
366
self->stateOrbs = SentryBug_StateOrbs_ReturnToSlots;
367
self->state = SentryBug_State_ReturnToSlots;
368
RSDK.StopSfx(SentryBug->sfxSwarm);
369
}
370
}
371
else {
372
self->netScale -= 0x80;
373
}
374
375
SentryBug_CheckPlayerCollisions();
376
}
377
else {
378
self->orbAnimator.frameID = 0;
379
self->orbsDetached = false;
380
381
self->stateOrbs = SentryBug_StateOrbs_ReturnToSlots;
382
self->state = SentryBug_State_ReturnToSlots;
383
384
RSDK.StopSfx(SentryBug->sfxSwarm);
385
}
386
}
387
388
void SentryBug_State_NetFlash(void)
389
{
390
RSDK_THIS(SentryBug);
391
392
EntityPlayer *player = self->playerPtr;
393
394
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 4, 10);
395
396
self->netPos.x = player->position.x;
397
self->netPos.y = player->position.y;
398
399
player->groundVel >>= 2;
400
player->velocity.x >>= 2;
401
player->velocity.y >>= 2;
402
403
self->netColor = (Zone->timer & 2) ? 0xF0F000 : 0xF02000;
404
405
if (++self->timer == 30) {
406
self->timer = 0;
407
Player_Hurt(player, self);
408
409
self->orbAnimator.frameID = 0;
410
self->netColor = 0xF02000;
411
self->orbsDetached = false;
412
self->stateOrbs = SentryBug_StateOrbs_ReturnToSlots;
413
self->state = SentryBug_State_ReturnToSlots;
414
415
RSDK.StopSfx(SentryBug->sfxSwarm);
416
self->isPermanent = false;
417
}
418
419
SentryBug_CheckPlayerCollisions();
420
}
421
422
void SentryBug_State_ReturnToSlots(void)
423
{
424
RSDK_THIS(SentryBug);
425
426
if (self->alpha > 0)
427
self->alpha -= 0x40;
428
429
self->velocity.x = (self->startPos.x - self->position.x) >> 4;
430
self->velocity.y = (self->startPos.y - self->position.y) >> 4;
431
432
RSDK.SetSpriteAnimation(SentryBug->aniFrames, self->velocity.x > 0, &self->bugAnimator, false, 0);
433
434
self->position.x += self->velocity.x;
435
self->position.y += self->velocity.y;
436
437
if (++self->timer == 60) {
438
self->originPos.x = self->startPos.x;
439
self->originPos.y = self->startPos.y;
440
self->angle = 0;
441
self->timer = 60;
442
self->active = ACTIVE_BOUNDS;
443
self->drawGroup = Zone->objectDrawGroup[0];
444
self->stateOrbs = SentryBug_StateOrbs_Attached;
445
self->state = SentryBug_State_AwaitPlayer;
446
}
447
448
SentryBug_CheckPlayerCollisions();
449
}
450
451
#if GAME_INCLUDE_EDITOR
452
void SentryBug_EditorDraw(void)
453
{
454
RSDK_THIS(SentryBug);
455
456
if (!self->speed)
457
self->speed = 4;
458
459
self->originPos = self->position;
460
self->startPos = self->position;
461
462
if (self->amplitude.x >= 0)
463
RSDK.SetSpriteAnimation(SentryBug->aniFrames, 1, &self->bugAnimator, true, 6);
464
else
465
RSDK.SetSpriteAnimation(SentryBug->aniFrames, 0, &self->bugAnimator, true, 6);
466
467
RSDK.SetSpriteAnimation(SentryBug->aniFrames, 2, &self->orbAnimator, true, 0);
468
469
RSDK.DrawSprite(&self->bugAnimator, NULL, false);
470
}
471
472
void SentryBug_EditorLoad(void) { SentryBug->aniFrames = RSDK.LoadSpriteAnimation("TMZ1/SentryBug.bin", SCOPE_STAGE); }
473
#endif
474
475
void SentryBug_Serialize(void)
476
{
477
RSDK_EDITABLE_VAR(SentryBug, VAR_UINT8, speed);
478
RSDK_EDITABLE_VAR(SentryBug, VAR_VECTOR2, amplitude);
479
}
480
481