Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/HCZ/Current.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Current Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectCurrent *Current;
11
12
void Current_Update(void)
13
{
14
RSDK_THIS(Current);
15
16
EntityButton *button = self->taggedButton;
17
if (!button || button->activated) {
18
self->activated = true;
19
StateMachine_Run(self->state);
20
}
21
}
22
23
void Current_LateUpdate(void) {}
24
25
void Current_StaticUpdate(void)
26
{
27
if (Water) {
28
int32 offsetH = 0;
29
int32 offsetV = 0;
30
31
foreach_active(Water, water)
32
{
33
if (water->state == Water_State_BigBubble && water->activePlayers) {
34
foreach_active(Current, current)
35
{
36
if (current->planeFilter <= 0 || water->collisionPlane == ((uint8)(current->planeFilter - 1) & 1)) {
37
int32 strength = current->strength << 15;
38
if (MathHelpers_PointInHitbox(current->position.x, current->position.y, water->position.x, water->position.y,
39
current->direction, &current->hitbox)) {
40
if (current->state == Current_State_WaterUp)
41
offsetV -= strength;
42
43
if (current->state == Current_State_WaterDown)
44
offsetV += strength;
45
46
if (current->state == Current_State_WaterLeft)
47
offsetH -= strength;
48
49
if (current->state == Current_State_WaterRight)
50
offsetH += strength;
51
}
52
}
53
}
54
55
if (water->bubbleVelocity.x < offsetH) {
56
water->bubbleVelocity.x += 0x6000;
57
58
if (water->bubbleVelocity.x > offsetH)
59
water->bubbleVelocity.x = offsetH;
60
}
61
62
if (water->bubbleVelocity.x > offsetH) {
63
water->bubbleVelocity.x -= 0x6000;
64
65
if (water->bubbleVelocity.x < offsetH)
66
water->bubbleVelocity.x = offsetH;
67
}
68
69
if (water->bubbleVelocity.y < offsetV) {
70
water->bubbleVelocity.y += 0x6000;
71
72
if (water->bubbleVelocity.y > offsetV)
73
water->bubbleVelocity.y = offsetV;
74
}
75
76
if (water->bubbleVelocity.y > offsetV) {
77
water->bubbleVelocity.y -= 0x6000;
78
79
if (water->bubbleVelocity.y < offsetV)
80
water->bubbleVelocity.y = offsetV;
81
}
82
}
83
}
84
}
85
86
foreach_active(Player, player)
87
{
88
int32 playerID = RSDK.GetEntitySlot(player);
89
90
bool32 active = false;
91
foreach_active(Current, current)
92
{
93
if (current->activated) {
94
if (current->type < CURRENT_W_LEFT) {
95
if ((current->planeFilter <= 0 || player->collisionPlane == ((uint8)(current->planeFilter - 1) & 1))
96
&& (!current->waterOnly || player->underwater)) {
97
if (Player_CheckCollisionTouch(player, current, &current->hitbox)) {
98
Current->activePlayers |= 1 << playerID;
99
active = true;
100
foreach_break;
101
}
102
}
103
}
104
}
105
}
106
107
if (!active)
108
Current->activePlayers &= ~(1 << playerID);
109
}
110
}
111
112
void Current_Draw(void)
113
{
114
RSDK_THIS(Current);
115
116
RSDK.DrawSprite(&self->animator, NULL, false);
117
}
118
119
void Current_Create(void *data)
120
{
121
RSDK_THIS(Current);
122
123
self->drawFX = FX_FLIP;
124
if (!SceneInfo->inEditor) {
125
if (data) {
126
self->active = ACTIVE_NORMAL;
127
self->inkEffect = INK_ADD;
128
self->visible = true;
129
self->updateRange.x = TO_FIXED(512);
130
self->updateRange.y = TO_FIXED(256);
131
132
if (VOID_TO_INT(data) == CURRENT_CHILD_WIND) {
133
self->drawFX = FX_SCALE | FX_FLIP;
134
self->scale.x = 0x400;
135
self->scale.y = 0x100;
136
RSDK.SetSpriteAnimation(Current->aniFrames, 1, &self->animator, true, ZONE_RAND(0, 4));
137
}
138
else {
139
RSDK.SetSpriteAnimation(Water->aniFrames, 5, &self->animator, true, 0);
140
self->alpha = 0x200;
141
}
142
143
self->state = Current_State_Child;
144
}
145
else {
146
self->visible = false;
147
self->updateRange.x = self->size.x >> 1;
148
self->updateRange.y = self->size.y >> 1;
149
self->active = ACTIVE_BOUNDS;
150
151
self->hitbox.left = -(self->size.x >> 17);
152
self->hitbox.right = self->size.x >> 17;
153
self->hitbox.top = -(self->size.y >> 17);
154
self->hitbox.bottom = self->size.y >> 17;
155
156
Current_SetupTagLink();
157
switch (self->type) {
158
case CURRENT_C_LEFT: self->state = Current_State_WaterLeft; break;
159
case CURRENT_C_RIGHT: self->state = Current_State_WaterRight; break;
160
case CURRENT_C_UP: self->state = Current_State_WaterUp; break;
161
case CURRENT_C_DOWN: self->state = Current_State_WaterDown; break;
162
case CURRENT_W_LEFT: self->state = Current_State_PushLeft; break;
163
case CURRENT_W_RIGHT: self->state = Current_State_PushRight; break;
164
case CURRENT_W_UP: self->state = Current_State_PushUp; break;
165
case CURRENT_W_DOWN: self->state = Current_State_PushDown; break;
166
default: break;
167
}
168
}
169
}
170
}
171
172
void Current_StageLoad(void)
173
{
174
if (RSDK.CheckSceneFolder("FBZ"))
175
Current->aniFrames = RSDK.LoadSpriteAnimation("FBZ/Current.bin", SCOPE_STAGE);
176
else
177
Current->aniFrames = RSDK.LoadSpriteAnimation("Global/TicMark.bin", SCOPE_STAGE);
178
179
RSDK.SetSpriteAnimation(Current->aniFrames, 0, &Current->animator, true, 0);
180
181
Current->sfxRush = RSDK.GetSfx("Stage/Rush.wav");
182
}
183
184
void Current_SetupTagLink(void)
185
{
186
RSDK_THIS(Current);
187
188
self->taggedButton = NULL;
189
EntityButton *taggedButton = RSDK_GET_ENTITY(RSDK.GetEntitySlot(self) - 1, Button);
190
191
if (self->buttonTag > 0) {
192
bool32 matchedTag = false;
193
if (Button) {
194
foreach_all(Button, button)
195
{
196
if (button->tag == self->buttonTag) {
197
taggedButton = button;
198
matchedTag = true;
199
foreach_break;
200
}
201
}
202
}
203
204
if (PullChain && !matchedTag) {
205
foreach_all(PullChain, chain)
206
{
207
if (chain->tag == self->buttonTag) {
208
taggedButton = (EntityButton *)chain;
209
matchedTag = true;
210
foreach_break;
211
}
212
}
213
}
214
}
215
216
if (taggedButton) {
217
if ((Button && taggedButton->classID == Button->classID) || (PullChain && taggedButton->classID == PullChain->classID)) {
218
int32 distX = abs(self->position.x - taggedButton->position.x) + TO_FIXED(128);
219
int32 distY = abs(self->position.y - taggedButton->position.y) + TO_FIXED(128);
220
221
if (self->updateRange.x < distX)
222
self->updateRange.x = distX;
223
224
if (self->updateRange.y < distY)
225
self->updateRange.y = distY;
226
227
self->taggedButton = taggedButton;
228
}
229
}
230
}
231
232
Vector2 Current_GetBubbleSpawnPosHorizontal(uint8 right)
233
{
234
RSDK_THIS(Current);
235
236
int32 x = 0;
237
if (right) {
238
x = self->position.x - (self->size.x >> 1) - 0x200000;
239
if ((ScreenInfo->position.x - 64) << 16 > x)
240
x = (ScreenInfo->position.x - 64) << 16;
241
}
242
else {
243
x = (self->size.x >> 1) + self->position.x + 0x200000;
244
if ((ScreenInfo->position.x + 64 + ScreenInfo->size.x) << 16 < x)
245
x = (ScreenInfo->position.x + 64 + ScreenInfo->size.x) << 16;
246
}
247
248
int32 maxY = self->position.y - (self->size.y >> 1) - 0x200000;
249
if ((ScreenInfo->position.y - 64) << 16 > maxY)
250
maxY = (ScreenInfo->position.y - 64) << 16;
251
252
int32 screenY = (ScreenInfo->position.y + 64 + ScreenInfo->size.y) << 16;
253
int32 minY = (self->size.y >> 1) + self->position.y + 0x200000;
254
if (screenY < minY)
255
minY = screenY;
256
257
int32 randMax = (minY - maxY) >> 20;
258
if (!randMax)
259
randMax = 1;
260
261
Vector2 bubblePos;
262
bubblePos.x = x;
263
if (randMax <= 0)
264
bubblePos.y = maxY;
265
else
266
bubblePos.y = maxY + (ZONE_RAND(0, randMax) << 20);
267
return bubblePos;
268
}
269
270
Vector2 Current_GetBubbleSpawnPosVertical(uint8 down)
271
{
272
RSDK_THIS(Current);
273
274
int32 y = 0;
275
if (down) {
276
y = self->position.y - (self->size.y >> 1) - 0x200000;
277
if ((ScreenInfo->position.y - 64) << 16 > y)
278
y = (ScreenInfo->position.y - 64) << 16;
279
}
280
else {
281
y = (self->size.y >> 1) + self->position.y + 0x200000;
282
if ((ScreenInfo->position.y + 64 + ScreenInfo->size.y) << 16 < y)
283
y = (ScreenInfo->position.y + 64 + ScreenInfo->size.y) << 16;
284
}
285
286
int32 maxX = self->position.x - (self->size.x >> 1) - 0x200000;
287
if ((ScreenInfo->position.x - 64) << 16 > maxX)
288
maxX = (ScreenInfo->position.x - 64) << 16;
289
290
int32 screenX = (ScreenInfo->position.x + 64 + ScreenInfo->size.x) << 16;
291
int32 minX = (self->size.x >> 1) + self->position.x + 0x200000;
292
if (screenX < minX)
293
minX = screenX;
294
295
int32 max = (minX - maxX) >> 20;
296
if (!max)
297
max = 1;
298
299
Vector2 bubblePos;
300
if (max <= 0) {
301
bubblePos.x = maxX;
302
bubblePos.y = y;
303
}
304
else {
305
bubblePos.x = maxX + (RSDK.Rand(0, max) << 20);
306
bubblePos.y = y;
307
}
308
return bubblePos;
309
}
310
311
void Current_State_WaterLeft(void)
312
{
313
RSDK_THIS(Current);
314
315
foreach_active(Player, player)
316
{
317
int32 playerID = RSDK.GetEntitySlot(player);
318
319
if ((self->planeFilter <= 0 || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) && (!self->waterOnly || player->underwater)) {
320
321
if (Player_CheckValidState(player)) {
322
if ((1 << playerID) & self->activePlayers) {
323
if (!Player_CheckCollisionTouch(player, self, &self->hitbox) || player->state == Player_State_HoldRespawn) {
324
if (player->state != Player_State_HoldRespawn)
325
player->state = Player_State_Air;
326
327
int32 x = self->position.x + ((self->hitbox.right - 32) << 16);
328
self->activePlayers &= ~(1 << playerID);
329
if (RSDK.CheckSceneFolder("FBZ") && !player->sidekick && self->fbzAchievement && self->playerPositions[playerID].x >= x
330
&& player->position.x < self->position.x) {
331
API_UnlockAchievement(&achievementList[ACH_FBZ]);
332
}
333
self->playerPositions[playerID].x = 0;
334
self->playerPositions[playerID].y = 0;
335
}
336
}
337
else if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {
338
self->playerPositions[playerID].x = player->position.x;
339
self->playerPositions[playerID].y = player->position.y;
340
self->activePlayers |= 1 << playerID;
341
}
342
343
if ((1 << playerID) & self->activePlayers) {
344
bool32 inBubble = false;
345
if (Water)
346
inBubble = Water_GetPlayerBubble(player) != NULL;
347
348
if (player->state != Player_State_Hurt && player->state != Player_State_HoldRespawn) {
349
int32 anim = player->animator.animationID;
350
if (anim != ANI_CLING && anim != ANI_SHAFT_SWING) {
351
player->onGround = false;
352
player->nextGroundState = StateMachine_None;
353
player->nextAirState = StateMachine_None;
354
player->velocity.x = -(self->strength << 15);
355
player->groundVel = player->velocity.x;
356
357
if (!inBubble) {
358
RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);
359
player->tileCollisions = TILECOLLISION_DOWN;
360
player->nextAirState = StateMachine_None;
361
player->nextGroundState = StateMachine_None;
362
player->state = Current_PlayerState_Left;
363
}
364
}
365
366
if (player->up)
367
player->velocity.y = -0x10000;
368
else if (player->down)
369
player->velocity.y = 0x10000;
370
else
371
player->velocity.y = 0;
372
}
373
}
374
}
375
else {
376
self->activePlayers &= ~(1 << playerID);
377
}
378
}
379
}
380
381
if (Water) {
382
if (!(Zone->timer & 7)) {
383
Vector2 pos = Current_GetBubbleSpawnPosHorizontal(false);
384
EntityCurrent *child = CREATE_ENTITY(Current, INT_TO_VOID(CURRENT_CHILD_BUBBLE), pos.x, pos.y);
385
386
child->drawGroup = Zone->objectDrawGroup[1];
387
child->strength = (self->strength + (self->strength >> 3)) >> 1;
388
child->size.x = self->position.x - (self->size.x >> 1) + 0x400000;
389
child->drawGroup = Zone->playerDrawGroup[0];
390
if (child->position.x < (self->position.x + (self->size.x >> 1)))
391
child->alpha = 0xF0;
392
}
393
}
394
}
395
396
void Current_State_WaterRight(void)
397
{
398
RSDK_THIS(Current);
399
400
foreach_active(Player, player)
401
{
402
int32 playerID = RSDK.GetEntitySlot(player);
403
404
if ((self->planeFilter <= 0 || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) && (!self->waterOnly || player->underwater)) {
405
406
if (Player_CheckValidState(player)) {
407
if ((1 << playerID) & self->activePlayers) {
408
if (!Player_CheckCollisionTouch(player, self, &self->hitbox) || player->state == Player_State_HoldRespawn) {
409
if (player->state != Player_State_HoldRespawn)
410
player->state = Player_State_Air;
411
self->activePlayers &= ~(1 << playerID);
412
}
413
}
414
else if (Player_CheckCollisionTouch(player, self, &self->hitbox))
415
self->activePlayers |= 1 << playerID;
416
417
if ((1 << playerID) & self->activePlayers) {
418
bool32 inBubble = false;
419
if (Water)
420
inBubble = Water_GetPlayerBubble(player) != NULL;
421
422
if (player->state != Player_State_Hurt && player->state != Player_State_HoldRespawn) {
423
int32 anim = player->animator.animationID;
424
if (anim != ANI_CLING && anim != ANI_SHAFT_SWING) {
425
player->onGround = false;
426
player->nextGroundState = StateMachine_None;
427
player->nextAirState = StateMachine_None;
428
player->velocity.x = self->strength << 15;
429
player->groundVel = player->velocity.x;
430
if (!inBubble) {
431
RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);
432
player->tileCollisions = TILECOLLISION_DOWN;
433
player->nextAirState = StateMachine_None;
434
player->nextGroundState = StateMachine_None;
435
player->state = Current_PlayerState_Right;
436
}
437
}
438
439
if (player->up)
440
player->velocity.y = -0x10000;
441
else if (player->down)
442
player->velocity.y = 0x10000;
443
else
444
player->velocity.y = 0;
445
}
446
}
447
}
448
else {
449
self->activePlayers &= ~(1 << playerID);
450
}
451
}
452
}
453
454
if (Water) {
455
if (!(Zone->timer & 7)) {
456
Vector2 pos = Current_GetBubbleSpawnPosHorizontal(true);
457
EntityCurrent *child = CREATE_ENTITY(Current, INT_TO_VOID(CURRENT_CHILD_BUBBLE), pos.x, pos.y);
458
459
child->drawGroup = Zone->objectDrawGroup[1];
460
child->strength = (self->strength + (self->strength >> 3)) >> 1;
461
child->size.x = (self->size.x >> 1) + self->position.x - 0x400000;
462
child->type = CURRENT_C_RIGHT;
463
child->drawGroup = Zone->playerDrawGroup[0];
464
if (child->position.x > (self->position.x - (self->size.x >> 1)))
465
child->alpha = 0xF0;
466
}
467
}
468
}
469
470
void Current_State_WaterUp(void)
471
{
472
RSDK_THIS(Current);
473
474
foreach_active(Player, player)
475
{
476
int32 playerID = RSDK.GetEntitySlot(player);
477
478
if ((self->planeFilter <= 0 || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) && (!self->waterOnly || player->underwater)) {
479
480
if (Player_CheckValidState(player)) {
481
if ((1 << playerID) & self->activePlayers) {
482
if (!Player_CheckCollisionTouch(player, self, &self->hitbox) || player->state == Player_State_HoldRespawn) {
483
if (player->state != Player_State_HoldRespawn)
484
player->state = Player_State_Air;
485
self->activePlayers &= ~(1 << playerID);
486
}
487
}
488
else if (Player_CheckCollisionTouch(player, self, &self->hitbox))
489
self->activePlayers |= 1 << playerID;
490
491
if ((1 << playerID) & self->activePlayers) {
492
bool32 inBubble = false;
493
if (Water)
494
inBubble = Water_GetPlayerBubble(player) != NULL;
495
496
if (player->state != Player_State_Hurt && player->state != Player_State_HoldRespawn) {
497
int32 anim = player->animator.animationID;
498
if (anim != ANI_CLING && anim != ANI_SHAFT_SWING) {
499
player->onGround = false;
500
player->nextGroundState = StateMachine_None;
501
player->nextAirState = StateMachine_None;
502
player->velocity.y = -(self->strength << 15);
503
if (!inBubble) {
504
RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);
505
player->tileCollisions = TILECOLLISION_DOWN;
506
player->nextAirState = StateMachine_None;
507
player->nextGroundState = StateMachine_None;
508
player->state = Current_PlayerState_Up;
509
}
510
}
511
512
if (player->left) {
513
player->velocity.x = -0x10000;
514
player->groundVel = -0x10000;
515
}
516
else if (player->right) {
517
player->velocity.x = 0x10000;
518
player->groundVel = 0x10000;
519
}
520
else {
521
player->velocity.x = 0;
522
}
523
}
524
}
525
}
526
else {
527
self->activePlayers &= ~(1 << playerID);
528
}
529
}
530
}
531
532
if (Water) {
533
if (!(Zone->timer & 7)) {
534
Vector2 pos = Current_GetBubbleSpawnPosVertical(false);
535
EntityCurrent *child = CREATE_ENTITY(Current, INT_TO_VOID(CURRENT_CHILD_BUBBLE), pos.x, pos.y);
536
537
child->drawGroup = Zone->objectDrawGroup[1];
538
child->strength = (self->strength + (self->strength >> 3)) >> 1;
539
child->size.y = (self->position.y - (self->size.y >> 1)) + 0x400000;
540
child->type = CURRENT_C_UP;
541
child->drawGroup = Zone->playerDrawGroup[0];
542
if (child->position.y < (self->position.y + (self->size.y >> 1)))
543
child->alpha = 0xF0;
544
}
545
}
546
}
547
548
void Current_State_WaterDown(void)
549
{
550
RSDK_THIS(Current);
551
552
foreach_active(Player, player)
553
{
554
int32 playerID = RSDK.GetEntitySlot(player);
555
556
if ((self->planeFilter <= 0 || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) && (!self->waterOnly || player->underwater)) {
557
558
if (Player_CheckValidState(player)) {
559
if ((1 << playerID) & self->activePlayers) {
560
if (!Player_CheckCollisionTouch(player, self, &self->hitbox) || player->state == Player_State_HoldRespawn) {
561
if (player->state != Player_State_HoldRespawn)
562
player->state = Player_State_Air;
563
564
self->activePlayers &= ~(1 << playerID);
565
}
566
}
567
else if (Player_CheckCollisionTouch(player, self, &self->hitbox))
568
self->activePlayers |= 1 << playerID;
569
570
if ((1 << playerID) & self->activePlayers) {
571
bool32 inBubble = false;
572
if (Water)
573
inBubble = Water_GetPlayerBubble(player) != NULL;
574
575
if (player->state != Player_State_Hurt && player->state != Player_State_HoldRespawn) {
576
int32 anim = player->animator.animationID;
577
if (anim != ANI_CLING && anim != ANI_SHAFT_SWING) {
578
player->onGround = false;
579
player->nextGroundState = StateMachine_None;
580
player->nextAirState = StateMachine_None;
581
player->velocity.y = self->strength << 15;
582
583
if (!inBubble) {
584
RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);
585
player->tileCollisions = TILECOLLISION_DOWN;
586
player->nextAirState = StateMachine_None;
587
player->nextGroundState = StateMachine_None;
588
player->state = Current_PlayerState_Down;
589
}
590
}
591
592
if (player->left) {
593
player->velocity.x = -0x10000;
594
player->groundVel = -0x10000;
595
}
596
else if (player->right) {
597
player->velocity.x = 0x10000;
598
player->groundVel = 0x10000;
599
}
600
else {
601
player->velocity.x = 0;
602
}
603
}
604
}
605
}
606
else {
607
self->activePlayers &= ~(1 << playerID);
608
}
609
}
610
}
611
612
if (Water) {
613
if (!(Zone->timer & 7)) {
614
Vector2 pos = Current_GetBubbleSpawnPosVertical(true);
615
EntityCurrent *child = CREATE_ENTITY(Current, INT_TO_VOID(CURRENT_CHILD_BUBBLE), pos.x, pos.y);
616
617
child->drawGroup = Zone->objectDrawGroup[1];
618
child->strength = (self->strength + (self->strength >> 3)) >> 1;
619
child->size.y = (self->size.y >> 1) + self->position.y - 0x400000;
620
child->type = CURRENT_C_DOWN;
621
child->drawGroup = Zone->playerDrawGroup[0];
622
if (child->position.y > (self->position.y - (self->size.y >> 1)))
623
child->alpha = 0xF0;
624
}
625
}
626
}
627
628
void Current_State_PushLeft(void)
629
{
630
RSDK_THIS(Current);
631
632
foreach_active(Player, player)
633
{
634
if ((self->planeFilter <= 0 || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) && (!self->waterOnly || player->underwater)) {
635
if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {
636
int32 anim = player->animator.animationID;
637
if (anim != ANI_CLING && anim != ANI_SHAFT_SWING)
638
player->position.x += -(self->strength << 15);
639
}
640
}
641
}
642
643
if (!(Zone->timer & 7)) {
644
Vector2 pos = Current_GetBubbleSpawnPosHorizontal(0);
645
EntityCurrent *child = CREATE_ENTITY(Current, INT_TO_VOID(CURRENT_CHILD_WIND), pos.x, pos.y);
646
647
child->drawGroup = Zone->objectDrawGroup[1];
648
child->strength = 4 * self->strength + RSDK.Rand(1 - self->strength, 5);
649
child->size.x = self->position.x - (self->size.x >> 1) + 0x400000;
650
if (child->position.x < (self->position.x + (self->size.x >> 1)))
651
child->alpha = 0xF0;
652
}
653
}
654
655
void Current_State_PushRight(void)
656
{
657
RSDK_THIS(Current);
658
659
foreach_active(Player, player)
660
{
661
if ((self->planeFilter <= 0 || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) && (!self->waterOnly || player->underwater)) {
662
if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {
663
int32 anim = player->animator.animationID;
664
if (anim != ANI_CLING && anim != ANI_SHAFT_SWING)
665
player->position.x += self->strength << 15;
666
}
667
}
668
}
669
}
670
671
void Current_State_PushUp(void)
672
{
673
RSDK_THIS(Current);
674
675
foreach_active(Player, player)
676
{
677
if ((self->planeFilter <= 0 || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) && (!self->waterOnly || player->underwater)) {
678
if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {
679
int32 anim = player->animator.animationID;
680
if (anim != ANI_CLING && anim != ANI_SHAFT_SWING && !player->onGround)
681
player->position.y += -(self->strength << 15);
682
}
683
}
684
}
685
}
686
687
void Current_State_PushDown(void)
688
{
689
RSDK_THIS(Current);
690
691
foreach_active(Player, player)
692
{
693
if ((self->planeFilter <= 0 || player->collisionPlane == ((uint8)(self->planeFilter - 1) & 1)) && (!self->waterOnly || player->underwater)) {
694
if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {
695
int32 anim = player->animator.animationID;
696
if (anim != ANI_CLING && anim != ANI_SHAFT_SWING && !player->onGround)
697
player->position.y += self->strength << 15;
698
}
699
}
700
}
701
}
702
703
void Current_State_Child(void)
704
{
705
RSDK_THIS(Current);
706
RSDK.ProcessAnimation(&self->animator);
707
708
switch (self->type) {
709
case CURRENT_C_LEFT:
710
self->position.x -= self->strength << 17;
711
if (self->position.x < self->size.x) {
712
self->alpha -= 8;
713
}
714
else {
715
if (self->alpha < 0xF0)
716
self->alpha += 8;
717
}
718
break;
719
720
case CURRENT_C_RIGHT:
721
self->position.x += self->strength << 17;
722
if (self->position.x >= self->size.x) {
723
if (self->alpha < 0xF0)
724
self->alpha += 8;
725
}
726
else {
727
self->alpha -= 8;
728
}
729
break;
730
731
case CURRENT_C_UP:
732
self->position.y -= self->strength << 17;
733
if (self->position.y >= self->size.y) {
734
if (self->alpha < 0xF0)
735
self->alpha += 8;
736
}
737
else {
738
self->alpha -= 8;
739
}
740
break;
741
742
case CURRENT_C_DOWN:
743
self->position.y += self->strength << 17;
744
if (self->position.y >= self->size.y) {
745
if (self->alpha < 0xF0)
746
self->alpha += 8;
747
}
748
else {
749
self->alpha -= 8;
750
}
751
break;
752
753
default: break;
754
}
755
756
if ((Water && self->position.y < Water->waterLevel) || !RSDK.CheckOnScreen(self, NULL) || !self->alpha)
757
destroyEntity(self);
758
}
759
760
void Current_PlayerState_Left(void)
761
{
762
RSDK_THIS(Player);
763
764
Hitbox *hitbox = Player_GetHitbox(self);
765
RSDK.ObjectTileCollision(self, self->collisionLayers, CMODE_ROOF, self->collisionPlane, hitbox->left << 16, hitbox->top << 16, true);
766
RSDK.ObjectTileCollision(self, self->collisionLayers, CMODE_FLOOR, self->collisionPlane, hitbox->left << 16, hitbox->bottom << 16, true);
767
}
768
769
void Current_PlayerState_Right(void)
770
{
771
RSDK_THIS(Player);
772
773
Hitbox *hitbox = Player_GetHitbox(self);
774
RSDK.ObjectTileCollision(self, self->collisionLayers, CMODE_ROOF, self->collisionPlane, hitbox->right << 16, hitbox->top << 16, true);
775
RSDK.ObjectTileCollision(self, self->collisionLayers, CMODE_FLOOR, self->collisionPlane, hitbox->right << 16, hitbox->bottom << 16, true);
776
}
777
778
void Current_PlayerState_Up(void)
779
{
780
RSDK_THIS(Player);
781
782
Hitbox *hitbox = Player_GetHitbox(self);
783
RSDK.ObjectTileCollision(self, self->collisionLayers, CMODE_RWALL, self->collisionPlane, hitbox->left << 16, hitbox->top << 16, true);
784
RSDK.ObjectTileCollision(self, self->collisionLayers, CMODE_LWALL, self->collisionPlane, hitbox->right << 16, hitbox->top << 16, true);
785
}
786
787
void Current_PlayerState_Down(void)
788
{
789
RSDK_THIS(Player);
790
791
Hitbox *hitbox = Player_GetHitbox(self);
792
RSDK.ObjectTileCollision(self, self->collisionLayers, CMODE_RWALL, self->collisionPlane, hitbox->left << 16, hitbox->bottom << 16, true);
793
RSDK.ObjectTileCollision(self, self->collisionLayers, CMODE_LWALL, self->collisionPlane, hitbox->right << 16, hitbox->bottom << 16, true);
794
}
795
796
#if GAME_INCLUDE_EDITOR
797
void Current_EditorDraw(void)
798
{
799
RSDK_THIS(Current);
800
801
self->updateRange.x = self->size.x >> 1;
802
self->updateRange.y = self->size.y >> 1;
803
804
RSDK.SetSpriteAnimation(Current->aniFrames, 1, &Current->animator, true, 0);
805
self->direction = FLIP_NONE;
806
807
RSDK.DrawSprite(&Current->animator, NULL, false);
808
809
if (showGizmos()) {
810
RSDK_DRAWING_OVERLAY(true);
811
DrawHelpers_DrawRectOutline(self->position.x, self->position.y, self->size.x, self->size.y, 0xFFFF00);
812
813
RSDK.SetSpriteAnimation(Current->aniFrames, 0, &Current->animator, true, 0);
814
Vector2 drawPos;
815
drawPos.x = self->position.x;
816
drawPos.y = self->position.y;
817
drawPos.x -= self->size.x >> 1;
818
drawPos.y -= self->size.y >> 1;
819
820
self->direction = FLIP_NONE;
821
RSDK.DrawSprite(&Current->animator, &drawPos, false);
822
823
drawPos.x += self->size.x;
824
self->direction = FLIP_X;
825
RSDK.DrawSprite(&Current->animator, &drawPos, false);
826
827
drawPos.y += self->size.y;
828
self->direction = FLIP_XY;
829
RSDK.DrawSprite(&Current->animator, &drawPos, false);
830
831
drawPos.x -= self->size.x;
832
self->direction = FLIP_Y;
833
RSDK.DrawSprite(&Current->animator, &drawPos, false);
834
RSDK_DRAWING_OVERLAY(false);
835
836
Current_SetupTagLink();
837
838
RSDK_DRAWING_OVERLAY(true);
839
if (self->taggedButton) {
840
DrawHelpers_DrawArrow(self->taggedButton->position.x, self->taggedButton->position.y, self->position.x, self->position.y, 0xFFFF00,
841
INK_NONE, 0xFF);
842
}
843
RSDK_DRAWING_OVERLAY(false);
844
}
845
}
846
847
void Current_EditorLoad(void)
848
{
849
Current->aniFrames = RSDK.LoadSpriteAnimation("FBZ/Current.bin", SCOPE_STAGE);
850
RSDK.SetSpriteAnimation(Current->aniFrames, 1, &Current->animator, true, 0);
851
852
RSDK_ACTIVE_VAR(Current, type);
853
RSDK_ENUM_VAR("Current - Left", CURRENT_C_LEFT);
854
RSDK_ENUM_VAR("Current - Right", CURRENT_C_RIGHT);
855
RSDK_ENUM_VAR("Current - Up", CURRENT_C_UP);
856
RSDK_ENUM_VAR("Current - Down", CURRENT_C_DOWN);
857
RSDK_ENUM_VAR("Wind - Left", CURRENT_W_LEFT);
858
RSDK_ENUM_VAR("Wind - Right", CURRENT_W_RIGHT);
859
RSDK_ENUM_VAR("Wind - Up", CURRENT_W_UP);
860
RSDK_ENUM_VAR("Wind - Down", CURRENT_W_DOWN);
861
862
RSDK_ACTIVE_VAR(Current, planeFilter);
863
RSDK_ENUM_VAR("None", PLANEFILTER_NONE);
864
RSDK_ENUM_VAR("AL", PLANEFILTER_AL);
865
RSDK_ENUM_VAR("BL", PLANEFILTER_BL);
866
RSDK_ENUM_VAR("AH", PLANEFILTER_AH);
867
RSDK_ENUM_VAR("BH", PLANEFILTER_BH);
868
}
869
#endif
870
871
void Current_Serialize(void)
872
{
873
RSDK_EDITABLE_VAR(Current, VAR_ENUM, type);
874
RSDK_EDITABLE_VAR(Current, VAR_VECTOR2, size);
875
RSDK_EDITABLE_VAR(Current, VAR_UINT8, strength);
876
RSDK_EDITABLE_VAR(Current, VAR_ENUM, buttonTag);
877
RSDK_EDITABLE_VAR(Current, VAR_ENUM, planeFilter);
878
RSDK_EDITABLE_VAR(Current, VAR_BOOL, waterOnly);
879
RSDK_EDITABLE_VAR(Current, VAR_BOOL, fbzAchievement);
880
}
881
882