Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/FBZ/ElectroMagnet.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: ElectroMagnet Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectElectroMagnet *ElectroMagnet;
11
12
void ElectroMagnet_Update(void)
13
{
14
RSDK_THIS(ElectroMagnet);
15
16
StateMachine_Run(self->state);
17
}
18
19
void ElectroMagnet_LateUpdate(void) {}
20
21
void ElectroMagnet_StaticUpdate(void)
22
{
23
if (ElectroMagnet->magnetSfxTimer) {
24
if (!ElectroMagnet->playingMagnetSfx) {
25
RSDK.PlaySfx(ElectroMagnet->sfxMagnet, true, 255);
26
ElectroMagnet->playingMagnetSfx = true;
27
}
28
ElectroMagnet->magnetSfxTimer = 0;
29
}
30
else if (ElectroMagnet->playingMagnetSfx) {
31
RSDK.StopSfx(ElectroMagnet->sfxMagnet);
32
ElectroMagnet->playingMagnetSfx = false;
33
}
34
}
35
36
void ElectroMagnet_Draw(void)
37
{
38
RSDK_THIS(ElectroMagnet);
39
40
if (self->state == ElectroMagnet_State_MagnetActive) {
41
self->animator.frameID = Zone->timer & 3;
42
RSDK.DrawSprite(&self->animator, NULL, false);
43
44
self->animator.frameID = (Zone->timer & 1) + 4;
45
RSDK.DrawSprite(&self->animator, NULL, false);
46
}
47
}
48
49
void ElectroMagnet_Create(void *data)
50
{
51
RSDK_THIS(ElectroMagnet);
52
53
if (!self->interval)
54
self->interval = 600;
55
56
self->active = ACTIVE_BOUNDS;
57
self->updateRange.x = 0x800000;
58
self->visible = !self->invisible;
59
self->updateRange.y = (self->height + 64) << 16;
60
self->drawGroup = Zone->objectDrawGroup[1];
61
62
self->hitboxMagnetRange.left = -64;
63
self->hitboxMagnetRange.top = 0;
64
self->hitboxMagnetRange.right = 64;
65
self->hitboxMagnetRange.bottom = self->height;
66
67
self->hitboxShieldRange.left = -64;
68
self->hitboxShieldRange.top = 0;
69
self->hitboxShieldRange.right = 64;
70
self->hitboxShieldRange.bottom = self->shieldRange;
71
72
RSDK.SetSpriteAnimation(ElectroMagnet->aniFrames, 0, &self->animator, true, 0);
73
self->state = ElectroMagnet_State_AwaitInterval;
74
}
75
76
void ElectroMagnet_StageLoad(void)
77
{
78
ElectroMagnet->active = ACTIVE_ALWAYS;
79
80
if (RSDK.CheckSceneFolder("FBZ"))
81
ElectroMagnet->aniFrames = RSDK.LoadSpriteAnimation("FBZ/ElectroMagnet.bin", SCOPE_STAGE);
82
83
ElectroMagnet->hitboxPlayer.left = -1;
84
ElectroMagnet->hitboxPlayer.top = -1;
85
ElectroMagnet->hitboxPlayer.right = 1;
86
ElectroMagnet->hitboxPlayer.bottom = 1;
87
88
ElectroMagnet->sfxRange.x = 0x800000;
89
ElectroMagnet->sfxRange.y = 0x400000;
90
91
ElectroMagnet->sfxMagnet = RSDK.GetSfx("Stage/Magnet.wav");
92
}
93
94
void ElectroMagnet_State_AwaitInterval(void)
95
{
96
RSDK_THIS(ElectroMagnet);
97
int32 time = (Zone->timer + self->intervalOffset) % self->interval;
98
99
if (time <= self->duration) {
100
self->active = ACTIVE_NORMAL;
101
self->timer = self->duration - time;
102
self->state = ElectroMagnet_State_MagnetActive;
103
}
104
}
105
106
void ElectroMagnet_State_MagnetActive(void)
107
{
108
RSDK_THIS(ElectroMagnet);
109
110
if (self->timer <= 0) {
111
if (self->hitboxShieldRange.top != self->hitboxShieldRange.bottom) {
112
foreach_active(Player, player)
113
{
114
if (RSDK.CheckObjectCollisionTouchBox(player, &ElectroMagnet->hitboxPlayer, self, &self->hitboxShieldRange)
115
&& player->invertGravity) {
116
player->invertGravity = false;
117
player->onGround = false;
118
}
119
}
120
}
121
122
self->active = ACTIVE_BOUNDS;
123
self->state = ElectroMagnet_State_AwaitInterval;
124
}
125
else {
126
self->timer--;
127
128
foreach_all(Blaster, blaster)
129
{
130
if (RSDK.CheckObjectCollisionTouchBox(blaster, &ElectroMagnet->hitboxPlayer, self, &self->hitboxMagnetRange)
131
&& blaster->animator.animationID < 2 && blaster->state != Blaster_State_Init) {
132
blaster->state = Blaster_State_MagnetAttract;
133
blaster->active = ACTIVE_NORMAL;
134
}
135
}
136
137
foreach_all(MagSpikeBall, spikeBall)
138
{
139
if (RSDK.CheckObjectCollisionTouchBox(spikeBall, &ElectroMagnet->hitboxPlayer, self, &self->hitboxMagnetRange)) {
140
spikeBall->direction = FLIP_X;
141
spikeBall->active = ACTIVE_NORMAL;
142
}
143
}
144
145
foreach_all(MagPlatform, platform)
146
{
147
if (RSDK.CheckObjectCollisionTouchBox(platform, &ElectroMagnet->hitboxPlayer, self, &self->hitboxMagnetRange)) {
148
platform->state = MagPlatform_State_Rise;
149
platform->active = ACTIVE_NORMAL;
150
}
151
}
152
153
if (RSDK.CheckOnScreen(self, &ElectroMagnet->sfxRange))
154
++ElectroMagnet->magnetSfxTimer;
155
156
if (self->hitboxShieldRange.top != self->hitboxShieldRange.bottom) {
157
foreach_active(Player, player)
158
{
159
if (RSDK.CheckObjectCollisionTouchBox(player, &ElectroMagnet->hitboxPlayer, self, &self->hitboxShieldRange)) {
160
if (player->state == Player_State_FlyCarried
161
|| (player->characterID == ID_KNUCKLES
162
&& (player->state == Player_State_KnuxWallClimb || player->state == Player_State_KnuxLedgePullUp))) {
163
player->invertGravity = false;
164
}
165
else if (player->shield == SHIELD_LIGHTNING) {
166
if (player->collisionMode != CMODE_ROOF)
167
player->onGround = false;
168
169
player->invertGravity = true;
170
171
if (player->state != Player_State_Transform) {
172
if (player->velocity.y > -0x68000)
173
player->velocity.y -= 2 * player->gravityStrength;
174
175
if (RSDK.ObjectTileCollision(player, player->collisionLayers, CMODE_ROOF, player->collisionPlane, 0, -0x160000, false)) {
176
player->collisionMode = CMODE_ROOF;
177
player->angle = 128;
178
player->onGround = true;
179
player->groundVel = -player->velocity.x;
180
}
181
else {
182
player->state = Player_State_Air;
183
RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);
184
}
185
}
186
}
187
}
188
}
189
}
190
}
191
}
192
193
#if GAME_INCLUDE_EDITOR
194
void ElectroMagnet_EditorDraw(void)
195
{
196
RSDK_THIS(ElectroMagnet);
197
self->alpha = 0xC0;
198
199
self->inkEffect = self->invisible ? INK_ALPHA : INK_NONE;
200
201
self->animator.frameID = 0;
202
RSDK.DrawSprite(&self->animator, NULL, false);
203
204
self->animator.frameID = 4;
205
RSDK.DrawSprite(&self->animator, NULL, false);
206
207
self->inkEffect = INK_NONE;
208
209
self->hitboxMagnetRange.left = -64;
210
self->hitboxMagnetRange.top = 0;
211
self->hitboxMagnetRange.right = 64;
212
self->hitboxMagnetRange.bottom = self->height;
213
214
self->hitboxShieldRange.left = -64;
215
self->hitboxShieldRange.top = 0;
216
self->hitboxShieldRange.right = 64;
217
self->hitboxShieldRange.bottom = self->shieldRange;
218
219
if (showGizmos()) {
220
RSDK_DRAWING_OVERLAY(true);
221
222
DrawHelpers_DrawHitboxOutline(self->position.x, self->position.y, &self->hitboxMagnetRange, FLIP_NONE, 0xFFFF00);
223
DrawHelpers_DrawHitboxOutline(self->position.x, self->position.y, &self->hitboxShieldRange, FLIP_NONE, 0xFF0000);
224
225
RSDK_DRAWING_OVERLAY(false);
226
}
227
}
228
229
void ElectroMagnet_EditorLoad(void) { ElectroMagnet->aniFrames = RSDK.LoadSpriteAnimation("FBZ/ElectroMagnet.bin", SCOPE_STAGE); }
230
#endif
231
232
void ElectroMagnet_Serialize(void)
233
{
234
RSDK_EDITABLE_VAR(ElectroMagnet, VAR_UINT16, interval);
235
RSDK_EDITABLE_VAR(ElectroMagnet, VAR_UINT16, intervalOffset);
236
RSDK_EDITABLE_VAR(ElectroMagnet, VAR_UINT16, duration);
237
RSDK_EDITABLE_VAR(ElectroMagnet, VAR_ENUM, height);
238
RSDK_EDITABLE_VAR(ElectroMagnet, VAR_ENUM, shieldRange);
239
RSDK_EDITABLE_VAR(ElectroMagnet, VAR_BOOL, invisible);
240
}
241
242