Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/TMZ/BallHog.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: BallHog Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectBallHog *BallHog;
11
12
void BallHog_Update(void)
13
{
14
RSDK_THIS(BallHog);
15
16
StateMachine_Run(self->state);
17
}
18
19
void BallHog_LateUpdate(void) {}
20
21
void BallHog_StaticUpdate(void) {}
22
23
void BallHog_Draw(void)
24
{
25
RSDK_THIS(BallHog);
26
27
RSDK.DrawSprite(&self->animator, NULL, false);
28
}
29
30
void BallHog_Create(void *data)
31
{
32
RSDK_THIS(BallHog);
33
34
self->visible = true;
35
self->drawGroup = Zone->objectDrawGroup[0];
36
self->active = ACTIVE_BOUNDS;
37
self->updateRange.x = 0x800000;
38
self->updateRange.y = 0x800000;
39
40
if (data) {
41
RSDK.SetSpriteAnimation(BallHog->aniFrames, 4, &self->animator, true, 0);
42
self->state = BallHog_State_Bomb;
43
}
44
else {
45
self->startPos = self->position;
46
self->startDir = self->direction;
47
48
if (!self->bombTime)
49
self->bombTime = 6;
50
51
if (!self->numJumps)
52
self->numJumps = 3;
53
54
self->drawFX |= FX_FLIP;
55
self->jumpCount = self->numJumps;
56
self->timer = 20;
57
58
RSDK.SetSpriteAnimation(BallHog->aniFrames, 0, &self->animator, true, 0);
59
60
self->state = BallHog_State_Init;
61
}
62
}
63
64
void BallHog_StageLoad(void)
65
{
66
if (RSDK.CheckSceneFolder("TMZ1") || RSDK.CheckSceneFolder("TMZ2"))
67
BallHog->aniFrames = RSDK.LoadSpriteAnimation("TMZ1/BallHog.bin", SCOPE_STAGE);
68
69
BallHog->hitboxBadnik.left = -12;
70
BallHog->hitboxBadnik.top = -18;
71
BallHog->hitboxBadnik.right = 12;
72
BallHog->hitboxBadnik.bottom = 18;
73
74
BallHog->hitboxBomb.left = -6;
75
BallHog->hitboxBomb.top = -6;
76
BallHog->hitboxBomb.right = 6;
77
BallHog->hitboxBomb.bottom = 6;
78
79
BallHog->sfxExplosion = RSDK.GetSfx("Stage/Explosion.wav");
80
BallHog->sfxArrowHit = RSDK.GetSfx("PSZ/ArrowHit.wav");
81
BallHog->sfxDrop = RSDK.GetSfx("TMZ1/HogDrop.wav");
82
BallHog->sfxJump = RSDK.GetSfx("TMZ1/HogJump.wav");
83
84
DEBUGMODE_ADD_OBJ(BallHog);
85
}
86
87
void BallHog_DebugSpawn(void)
88
{
89
RSDK_THIS(DebugMode);
90
91
CREATE_ENTITY(BallHog, NULL, self->position.x, self->position.y);
92
}
93
94
void BallHog_DebugDraw(void)
95
{
96
RSDK.SetSpriteAnimation(BallHog->aniFrames, 0, &DebugMode->animator, true, 0);
97
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
98
}
99
100
void BallHog_CheckPlayerCollisions(void)
101
{
102
RSDK_THIS(BallHog);
103
104
foreach_active(Player, player)
105
{
106
if (Player_CheckBadnikTouch(player, self, &BallHog->hitboxBadnik))
107
Player_CheckBadnikBreak(player, self, true);
108
}
109
}
110
111
void BallHog_CheckOffScreen(void)
112
{
113
RSDK_THIS(BallHog);
114
115
if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {
116
self->position = self->startPos;
117
self->direction = self->startDir;
118
BallHog_Create(NULL);
119
}
120
}
121
122
void BallHog_State_Init(void)
123
{
124
RSDK_THIS(BallHog);
125
126
self->active = ACTIVE_NORMAL;
127
128
self->state = BallHog_State_Idle;
129
BallHog_State_Idle();
130
}
131
132
void BallHog_State_Idle(void)
133
{
134
RSDK_THIS(BallHog);
135
136
if (!--self->timer) {
137
self->timer = 20;
138
RSDK.SetSpriteAnimation(BallHog->aniFrames, 1, &self->animator, true, 0);
139
self->state = BallHog_State_Jump;
140
}
141
142
RSDK.ProcessAnimation(&self->animator);
143
144
BallHog_CheckPlayerCollisions();
145
BallHog_CheckOffScreen();
146
}
147
148
void BallHog_State_Jump(void)
149
{
150
RSDK_THIS(BallHog);
151
152
if (self->timer) {
153
if (!--self->timer) {
154
RSDK.PlaySfx(BallHog->sfxJump, false, 255);
155
self->velocity.y = -0x203D9;
156
self->position.y -= 0x29999;
157
}
158
}
159
else {
160
self->position.y += self->velocity.y;
161
self->velocity.y += 0x95C0;
162
163
if (self->velocity.y > 0 && RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x140000, 2)) {
164
self->velocity.y = 0;
165
self->timer = 10;
166
RSDK.SetSpriteAnimation(BallHog->aniFrames, 2, &self->animator, true, 0);
167
self->state = BallHog_State_Land;
168
}
169
}
170
171
RSDK.ProcessAnimation(&self->animator);
172
173
BallHog_CheckPlayerCollisions();
174
BallHog_CheckOffScreen();
175
}
176
177
void BallHog_State_Land(void)
178
{
179
RSDK_THIS(BallHog);
180
181
if (!--self->timer) {
182
RSDK.SetSpriteAnimation(BallHog->aniFrames, 0, &self->animator, true, 0);
183
184
if (!--self->jumpCount) {
185
self->timer = 28;
186
self->jumpCount = self->numJumps + 1;
187
self->state = BallHog_State_DropBomb;
188
}
189
else {
190
self->timer = 20;
191
self->state = BallHog_State_Idle;
192
}
193
}
194
195
RSDK.ProcessAnimation(&self->animator);
196
197
BallHog_CheckPlayerCollisions();
198
BallHog_CheckOffScreen();
199
}
200
201
void BallHog_State_DropBomb(void)
202
{
203
RSDK_THIS(BallHog);
204
205
if (--self->timer) {
206
if (self->timer == 8)
207
RSDK.SetSpriteAnimation(BallHog->aniFrames, 3, &self->animator, true, 0);
208
}
209
else {
210
self->timer = 18;
211
RSDK.PlaySfx(BallHog->sfxDrop, false, 0xFF);
212
213
EntityBallHog *bomb = CREATE_ENTITY(BallHog, INT_TO_VOID(true), self->position.x, self->position.y);
214
if (self->direction) {
215
bomb->position.x += 0x40000;
216
bomb->velocity.x = 0x10000;
217
}
218
else {
219
bomb->position.x -= 0x40000;
220
bomb->velocity.x = -0x10000;
221
}
222
223
bomb->position.y += 0xC0000;
224
bomb->timer = 60 * self->bombTime;
225
226
self->state = BallHog_State_Land;
227
}
228
229
RSDK.ProcessAnimation(&self->animator);
230
231
BallHog_CheckPlayerCollisions();
232
BallHog_CheckOffScreen();
233
}
234
235
void BallHog_State_Bomb(void)
236
{
237
RSDK_THIS(BallHog);
238
239
self->position.x += self->velocity.x;
240
self->position.y += self->velocity.y;
241
self->velocity.y += 0x3800;
242
243
if (RSDK.CheckOnScreen(self, &self->updateRange)) {
244
if (self->velocity.y > 0 && RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x80000, 4)) {
245
RSDK.PlaySfx(BallHog->sfxArrowHit, false, 255);
246
int32 storeY = self->position.y;
247
248
self->velocity.y = -0x30000;
249
RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, -0x20000, 0x80000, 8);
250
int32 y1 = self->position.y;
251
252
self->position.y = storeY;
253
RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0x20000, 0x80000, 8);
254
int32 y2 = self->position.y;
255
256
self->position.y = storeY;
257
if (self->velocity.x <= 0 ? y1 < y2 : y2 < y1)
258
self->velocity.x = -self->velocity.x;
259
}
260
261
RSDK.ProcessAnimation(&self->animator);
262
263
bool32 shouldExplode = false;
264
foreach_active(Player, player)
265
{
266
if (Player_CheckCollisionTouch(player, self, &BallHog->hitboxBomb)) {
267
#if MANIA_USE_PLUS
268
if (!Player_CheckMightyUnspin(player, 0x100, 2, &player->uncurlTimer)) {
269
#endif
270
Player_Hurt(player, self);
271
shouldExplode = true;
272
foreach_break;
273
#if MANIA_USE_PLUS
274
}
275
#endif
276
}
277
}
278
279
if (shouldExplode || !--self->timer) {
280
RSDK.PlaySfx(BallHog->sfxExplosion, false, 255);
281
CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_ENEMY), self->position.x, self->position.y)->drawGroup = Zone->objectDrawGroup[1];
282
283
destroyEntity(self);
284
}
285
}
286
else {
287
destroyEntity(self);
288
}
289
}
290
291
#if GAME_INCLUDE_EDITOR
292
void BallHog_EditorDraw(void) { BallHog_Draw(); }
293
294
void BallHog_EditorLoad(void)
295
{
296
BallHog->aniFrames = RSDK.LoadSpriteAnimation("TMZ1/BallHog.bin", SCOPE_STAGE);
297
298
RSDK_ACTIVE_VAR(BallHog, direction);
299
RSDK_ENUM_VAR("Left", FLIP_NONE);
300
RSDK_ENUM_VAR("Right", FLIP_X);
301
}
302
#endif
303
304
void BallHog_Serialize(void)
305
{
306
RSDK_EDITABLE_VAR(BallHog, VAR_UINT8, direction);
307
RSDK_EDITABLE_VAR(BallHog, VAR_UINT8, numJumps);
308
RSDK_EDITABLE_VAR(BallHog, VAR_UINT8, bombTime);
309
}
310
311