Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/GHZ/Fireball.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Fireball Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectFireball *Fireball = NULL;
11
12
void Fireball_Update(void)
13
{
14
RSDK_THIS(Fireball);
15
StateMachine_Run(self->state);
16
}
17
18
void Fireball_LateUpdate(void) {}
19
20
void Fireball_StaticUpdate(void) {}
21
22
void Fireball_Draw(void)
23
{
24
RSDK_THIS(Fireball);
25
StateMachine_Run(self->stateDraw);
26
}
27
28
void Fireball_Create(void *data)
29
{
30
RSDK_THIS(Fireball);
31
32
self->drawFX |= FX_ROTATE | FX_FLIP;
33
self->active = ACTIVE_BOUNDS;
34
self->visible = true;
35
self->updateRange.x = 0x800000;
36
self->updateRange.y = 0x800000;
37
self->drawGroup = Zone->objectDrawGroup[0];
38
RSDK.SetSpriteAnimation(Fireball->aniFrames, 0, &self->animator, true, 0);
39
40
if (!SceneInfo->inEditor)
41
self->interval *= 15;
42
43
if (data) {
44
self->state = (Type_StateMachine)data;
45
self->active = ACTIVE_NORMAL;
46
self->stateDraw = Fireball_Draw_Simple;
47
}
48
else {
49
self->groundVel <<= 7;
50
switch (self->type) {
51
default: break;
52
case FIREBALL_SPAWNER: self->state = Fireball_State_Spawner; break;
53
case FIREBALL_LAUNCHER_STATIC: self->state = Fireball_State_LauncherStatic; break;
54
case FIREBALL_LAUNCHER_GRAVITY: self->state = Fireball_State_LauncherGravity; break;
55
}
56
}
57
}
58
59
void Fireball_StageLoad(void)
60
{
61
if (RSDK.CheckSceneFolder("GHZ"))
62
Fireball->aniFrames = RSDK.LoadSpriteAnimation("GHZ/Fireball.bin", SCOPE_STAGE);
63
64
Fireball->hitboxFireball.left = -6;
65
Fireball->hitboxFireball.top = -6;
66
Fireball->hitboxFireball.right = 6;
67
Fireball->hitboxFireball.bottom = 6;
68
69
Fireball->sfxFireball = RSDK.GetSfx("Stage/Fireball.wav");
70
}
71
72
void Fireball_HandlePlayerInteractions(void)
73
{
74
RSDK_THIS(Fireball);
75
76
foreach_active(Player, player)
77
{
78
if (Player_CheckCollisionTouch(player, self, &Fireball->hitboxFireball)) {
79
Player_ElementHurt(player, self, SHIELD_FIRE);
80
}
81
}
82
}
83
84
void Fireball_State_Spawner(void)
85
{
86
RSDK_THIS(Fireball);
87
88
if (!((Zone->timer + self->intervalOffset) % self->interval)) {
89
EntityFireball *fireball = CREATE_ENTITY(Fireball, Fireball_StateFireball_Spawner, self->position.x, self->position.y);
90
91
fireball->angle = self->rotation;
92
fireball->rotation = self->rotation;
93
94
fireball->groundVel = -self->groundVel;
95
fireball->velocity.x = fireball->groundVel * RSDK.Sin512(0x100 - fireball->angle);
96
fireball->velocity.y = fireball->groundVel * RSDK.Cos512(0x100 - fireball->angle);
97
98
RSDK.PlaySfx(Fireball->sfxFireball, false, 0xFF);
99
}
100
}
101
102
void Fireball_State_LauncherStatic(void)
103
{
104
RSDK_THIS(Fireball);
105
106
if (!((Zone->timer + self->intervalOffset) % self->interval)) {
107
EntityFireball *fireball = CREATE_ENTITY(Fireball, Fireball_StateFireball_LauncherStatic, self->position.x, self->position.y);
108
109
fireball->angle = self->rotation;
110
fireball->rotation = self->rotation;
111
112
fireball->groundVel = -self->groundVel;
113
fireball->velocity.x = fireball->groundVel * RSDK.Sin512(0x100 - fireball->angle);
114
fireball->velocity.y = fireball->groundVel * RSDK.Cos512(0x100 - fireball->angle);
115
116
RSDK.PlaySfx(Fireball->sfxFireball, false, 0xFF);
117
}
118
}
119
120
void Fireball_State_LauncherGravity(void)
121
{
122
RSDK_THIS(Fireball);
123
124
if (!((Zone->timer + self->intervalOffset) % self->interval)) {
125
EntityFireball *fireball = CREATE_ENTITY(Fireball, Fireball_StateFireball_LauncherGravity, self->position.x, self->position.y);
126
127
fireball->angle = self->rotation;
128
fireball->rotation = self->rotation;
129
130
fireball->groundVel = -self->groundVel;
131
fireball->velocity.x = fireball->groundVel * RSDK.Sin512(0x100 - fireball->angle);
132
fireball->velocity.y = fireball->groundVel * RSDK.Cos512(0x100 - fireball->angle);
133
134
RSDK.PlaySfx(Fireball->sfxFireball, false, 255);
135
}
136
}
137
138
void Fireball_StateFireball_Spawner(void)
139
{
140
RSDK_THIS(Fireball);
141
142
self->position.x += self->velocity.x;
143
self->position.y += self->velocity.y;
144
145
self->groundVel += 0x18;
146
self->velocity.x = self->groundVel * RSDK.Sin512(0x100 - self->angle);
147
self->velocity.y = self->groundVel * RSDK.Cos512(0x100 - self->angle);
148
149
if (self->groundVel > 0)
150
self->rotation = self->angle + 0x100;
151
152
if (!RSDK.CheckOnScreen(self, &self->updateRange))
153
destroyEntity(self);
154
155
RSDK.ProcessAnimation(&self->animator);
156
157
Fireball_HandlePlayerInteractions();
158
}
159
160
void Fireball_StateFireball_LauncherStatic(void)
161
{
162
RSDK_THIS(Fireball);
163
164
self->position.x += self->velocity.x;
165
self->position.y += self->velocity.y;
166
167
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, RSDK.Sin512(0x200 - self->rotation) << 10,
168
RSDK.Cos512(0x200 - self->rotation) << 10, true)) {
169
self->state = Fireball_StateFireball_Dissipate;
170
RSDK.SetSpriteAnimation(Fireball->aniFrames, 1, &self->animator, true, 0);
171
}
172
else {
173
if (RSDK.CheckOnScreen(self, &self->updateRange)) {
174
RSDK.ProcessAnimation(&self->animator);
175
Fireball_HandlePlayerInteractions();
176
}
177
else {
178
destroyEntity(self);
179
}
180
}
181
}
182
183
void Fireball_StateFireball_LauncherGravity(void)
184
{
185
RSDK_THIS(Fireball);
186
187
self->rotation = 2 * RSDK.ATan2((self->velocity.x >> 16), (self->velocity.y >> 16)) + 0x180;
188
189
self->position.x += self->velocity.x;
190
self->position.y += self->velocity.y;
191
self->velocity.y += 0x3800;
192
193
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, RSDK.Sin512(0x200 - self->rotation) << 10,
194
RSDK.Cos512(0x200 - self->rotation) << 10, true)) {
195
self->state = Fireball_StateFireball_Dissipate;
196
RSDK.SetSpriteAnimation(Fireball->aniFrames, 1, &self->animator, true, 0);
197
}
198
else {
199
if (RSDK.CheckOnScreen(self, &self->updateRange)) {
200
RSDK.ProcessAnimation(&self->animator);
201
Fireball_HandlePlayerInteractions();
202
}
203
else {
204
destroyEntity(self);
205
}
206
}
207
}
208
209
void Fireball_StateFireball_Dissipate(void)
210
{
211
RSDK_THIS(Fireball);
212
213
RSDK.ProcessAnimation(&self->animator);
214
Fireball_HandlePlayerInteractions();
215
216
if (self->animator.frameID == 2)
217
destroyEntity(self);
218
}
219
220
void Fireball_Draw_Simple(void)
221
{
222
RSDK_THIS(Fireball);
223
224
RSDK.DrawSprite(&self->animator, NULL, false);
225
}
226
227
#if GAME_INCLUDE_EDITOR
228
void Fireball_EditorDraw(void)
229
{
230
RSDK_THIS(Fireball);
231
RSDK.SetSpriteAnimation(Fireball->aniFrames, 0, &self->animator, true, 0);
232
233
Fireball_Draw_Simple();
234
}
235
236
void Fireball_EditorLoad(void)
237
{
238
Fireball->aniFrames = RSDK.LoadSpriteAnimation("GHZ/Fireball.bin", SCOPE_STAGE);
239
240
RSDK_ACTIVE_VAR(Fireball, type);
241
RSDK_ENUM_VAR("Spawner", FIREBALL_SPAWNER);
242
RSDK_ENUM_VAR("Launcher (Static Movement)", FIREBALL_LAUNCHER_STATIC);
243
RSDK_ENUM_VAR("Launcher (Gravity-Applied Movement)", FIREBALL_LAUNCHER_GRAVITY);
244
}
245
#endif
246
247
void Fireball_Serialize(void)
248
{
249
RSDK_EDITABLE_VAR(Fireball, VAR_UINT8, type);
250
RSDK_EDITABLE_VAR(Fireball, VAR_INT32, rotation);
251
RSDK_EDITABLE_VAR(Fireball, VAR_UINT8, interval);
252
RSDK_EDITABLE_VAR(Fireball, VAR_UINT8, intervalOffset);
253
RSDK_EDITABLE_VAR(Fireball, VAR_ENUM, groundVel);
254
}
255
256