Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/AIZ/Rhinobot.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Rhinobot Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
#if MANIA_USE_PLUS
11
ObjectRhinobot *Rhinobot;
12
13
void Rhinobot_Update(void)
14
{
15
RSDK_THIS(Rhinobot);
16
StateMachine_Run(self->state);
17
}
18
19
void Rhinobot_LateUpdate(void) {}
20
21
void Rhinobot_StaticUpdate(void) {}
22
23
void Rhinobot_Draw(void)
24
{
25
RSDK_THIS(Rhinobot);
26
if (self->drawDust) {
27
Vector2 drawPos;
28
drawPos.x = self->position.x;
29
drawPos.y = self->position.y;
30
if (self->state == Rhinobot_State_Moving) {
31
if (!self->moveDir)
32
drawPos.x -= 0xD0000;
33
else
34
drawPos.x += 0xD0000;
35
}
36
RSDK.DrawSprite(&self->dustAnimator, &drawPos, false);
37
}
38
RSDK.DrawSprite(&self->bodyAnimator, NULL, false);
39
}
40
41
void Rhinobot_Create(void *data)
42
{
43
RSDK_THIS(Rhinobot);
44
self->visible = true;
45
self->drawFX |= FX_FLIP;
46
self->drawGroup = Zone->objectDrawGroup[0];
47
self->startPos = self->position;
48
self->startDir = self->direction;
49
self->active = ACTIVE_BOUNDS;
50
self->updateRange.x = 0x800000;
51
self->updateRange.y = 0x800000;
52
RSDK.SetSpriteAnimation(Rhinobot->aniFrames, 0, &self->bodyAnimator, true, 0);
53
RSDK.SetSpriteAnimation(Rhinobot->aniFrames, 2, &self->dustAnimator, true, 0);
54
self->state = Rhinobot_State_Init;
55
}
56
57
void Rhinobot_StageLoad(void)
58
{
59
if (RSDK.CheckSceneFolder("AIZ"))
60
Rhinobot->aniFrames = RSDK.LoadSpriteAnimation("AIZ/Rhinobot.bin", SCOPE_STAGE);
61
62
Rhinobot->hitboxBadnik.left = -14;
63
Rhinobot->hitboxBadnik.top = -9;
64
Rhinobot->hitboxBadnik.right = 23;
65
Rhinobot->hitboxBadnik.bottom = 15;
66
67
Rhinobot->sfxHuff = RSDK.GetSfx("Stage/Huff.wav");
68
69
DEBUGMODE_ADD_OBJ(Rhinobot);
70
}
71
72
void Rhinobot_DebugSpawn(void)
73
{
74
RSDK_THIS(DebugMode);
75
76
CREATE_ENTITY(Rhinobot, NULL, self->position.x, self->position.y);
77
}
78
79
void Rhinobot_DebugDraw(void)
80
{
81
RSDK.SetSpriteAnimation(Rhinobot->aniFrames, 0, &DebugMode->animator, true, 0);
82
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
83
}
84
85
bool32 Rhinobot_CheckTileCollisions(void)
86
{
87
RSDK_THIS(Rhinobot);
88
89
if (self->moveDir) {
90
if (!RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0x40000, 0xF0000, 8)) {
91
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_LWALL, 0, 0x100000, 0, false))
92
return false;
93
if (RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0xF0000, 8))
94
return false;
95
self->state = Rhinobot_State_Fall;
96
}
97
}
98
else if (!RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, -0x40000, 0xF0000, 8)) {
99
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_RWALL, 0, -0x100000, 0, false))
100
return false;
101
if (RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0xF0000, 8))
102
return false;
103
self->state = Rhinobot_State_Fall;
104
}
105
106
return true;
107
}
108
109
void Rhinobot_CheckPlayerCollisions(void)
110
{
111
RSDK_THIS(Rhinobot);
112
113
foreach_active(Player, player)
114
{
115
if (Player_CheckBadnikTouch(player, self, &Rhinobot->hitboxBadnik))
116
Player_CheckBadnikBreak(player, self, true);
117
}
118
}
119
120
void Rhinobot_CheckOffScreen(void)
121
{
122
RSDK_THIS(Rhinobot);
123
124
if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {
125
self->position = self->startPos;
126
self->direction = self->startDir;
127
Rhinobot_Create(NULL);
128
}
129
}
130
131
void Rhinobot_Delay_Charge(void)
132
{
133
RSDK_THIS(Rhinobot);
134
135
self->drawDust = false;
136
if (!self->moveDir)
137
self->velocity.x = -0x40000;
138
else
139
self->velocity.x = 0x40000;
140
141
self->state = Rhinobot_State_Skidding;
142
self->stateDelay = Rhinobot_Delay_Skidding;
143
}
144
145
void Rhinobot_Delay_Skidding(void)
146
{
147
RSDK_THIS(Rhinobot);
148
149
RSDK.SetSpriteAnimation(Rhinobot->aniFrames, 1, &self->bodyAnimator, true, 0);
150
self->skidDir ^= FLIP_X;
151
self->acceleration = -self->acceleration;
152
self->topSpeed = -self->topSpeed;
153
self->stateDelay = Rhinobot_Delay_SkidFinish;
154
}
155
156
void Rhinobot_Delay_SkidFinish(void)
157
{
158
RSDK_THIS(Rhinobot);
159
160
self->moveDir ^= FLIP_X;
161
self->direction ^= FLIP_X;
162
self->drawDust = false;
163
RSDK.SetSpriteAnimation(Rhinobot->aniFrames, 0, &self->bodyAnimator, true, 0);
164
self->stateDelay = Rhinobot_Delay_Skidding;
165
}
166
167
void Rhinobot_State_Init(void)
168
{
169
RSDK_THIS(Rhinobot);
170
171
self->active = ACTIVE_NORMAL;
172
self->stateDelay = Rhinobot_Delay_Skidding;
173
self->moveDir = self->startDir;
174
self->skidDir = self->startDir;
175
176
if (self->direction == FLIP_NONE) {
177
self->acceleration = -0x1000;
178
self->topSpeed = -0x30000;
179
}
180
else {
181
self->acceleration = 0x1000;
182
self->topSpeed = 0x30000;
183
}
184
185
self->state = Rhinobot_State_Moving;
186
Rhinobot_State_Moving();
187
}
188
189
void Rhinobot_State_Moving(void)
190
{
191
RSDK_THIS(Rhinobot);
192
193
EntityPlayer *player = Player_GetNearestPlayer();
194
195
bool32 isRevingUp = false;
196
if (abs(player->position.y - self->position.y) <= 0x200000) {
197
if (abs(player->position.x - self->position.x) <= 0x600000) {
198
if (self->skidDir == self->moveDir && (player->position.x > self->position.x) == self->skidDir) {
199
self->state = Rhinobot_State_Idle;
200
self->velocity.x = 0;
201
self->timer = 32;
202
self->stateDelay = Rhinobot_Delay_Charge;
203
self->drawDust = true;
204
if (self->onScreen)
205
RSDK.PlaySfx(Rhinobot->sfxHuff, false, 255);
206
isRevingUp = true;
207
}
208
}
209
}
210
211
if (!isRevingUp) {
212
if (Rhinobot_CheckTileCollisions()) {
213
if (self->state == Rhinobot_State_Moving) {
214
self->velocity.x += self->acceleration;
215
self->position.x += self->velocity.x;
216
217
if (!self->velocity.x || (self->skidDir && self->velocity.x >= self->topSpeed)
218
|| (!self->skidDir && self->velocity.x <= self->topSpeed)) {
219
#if RETRO_USE_MOD_LOADER
220
StateMachine_Run(self->stateDelay);
221
#else
222
self->stateDelay();
223
#endif
224
}
225
}
226
}
227
else {
228
self->velocity.x = 0;
229
self->skidDir = self->moveDir ^ FLIP_X;
230
self->moveDir ^= FLIP_X;
231
self->direction ^= FLIP_X;
232
self->drawDust = false;
233
RSDK.SetSpriteAnimation(Rhinobot->aniFrames, 0, &self->bodyAnimator, true, 0);
234
self->stateDelay = Rhinobot_Delay_Skidding;
235
}
236
237
if (((self->moveDir && !self->skidDir && self->velocity.x < 0x28000) || (!self->moveDir && self->skidDir && self->velocity.x > -0x28000))
238
&& !self->drawDust) {
239
self->drawDust = true;
240
if (self->onScreen)
241
RSDK.PlaySfx(Rhinobot->sfxHuff, false, 0xFF);
242
}
243
}
244
245
RSDK.ProcessAnimation(&self->bodyAnimator);
246
RSDK.ProcessAnimation(&self->dustAnimator);
247
248
Rhinobot_CheckPlayerCollisions();
249
Rhinobot_CheckOffScreen();
250
}
251
252
void Rhinobot_State_Skidding(void)
253
{
254
RSDK_THIS(Rhinobot);
255
256
self->position.x += self->velocity.x;
257
258
if (!Rhinobot_CheckTileCollisions()) {
259
self->velocity.x = 0;
260
self->skidDir = self->moveDir ^ FLIP_X;
261
self->moveDir ^= FLIP_X;
262
self->direction ^= FLIP_X;
263
self->drawDust = false;
264
RSDK.SetSpriteAnimation(Rhinobot->aniFrames, 0, &self->bodyAnimator, true, 0);
265
self->stateDelay = Rhinobot_Delay_Skidding;
266
self->state = Rhinobot_State_Moving;
267
}
268
269
RSDK.ProcessAnimation(&self->bodyAnimator);
270
RSDK.ProcessAnimation(&self->dustAnimator);
271
272
Rhinobot_CheckPlayerCollisions();
273
Rhinobot_CheckOffScreen();
274
}
275
276
void Rhinobot_State_Idle(void)
277
{
278
RSDK_THIS(Rhinobot);
279
280
RSDK.ProcessAnimation(&self->dustAnimator);
281
282
if (--self->timer <= 0) {
283
#if RETRO_USE_MOD_LOADER
284
StateMachine_Run(self->stateDelay);
285
#else
286
self->stateDelay();
287
#endif
288
}
289
290
Rhinobot_CheckPlayerCollisions();
291
Rhinobot_CheckOffScreen();
292
}
293
294
void Rhinobot_State_Fall(void)
295
{
296
RSDK_THIS(Rhinobot);
297
298
RSDK.ProcessAnimation(&self->dustAnimator);
299
300
self->position.x += self->velocity.x;
301
self->position.y += self->velocity.y;
302
self->velocity.y += 0x3800;
303
304
if (RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x100000, 8)) {
305
self->velocity.y = 0;
306
RSDK.SetSpriteAnimation(Rhinobot->aniFrames, 0, &self->bodyAnimator, true, 0);
307
self->drawDust = true;
308
if (self->onScreen)
309
RSDK.PlaySfx(Rhinobot->sfxHuff, false, 255);
310
self->state = Rhinobot_State_Moving;
311
Rhinobot_State_Moving();
312
}
313
else {
314
Rhinobot_CheckPlayerCollisions();
315
Rhinobot_CheckOffScreen();
316
}
317
}
318
319
#if GAME_INCLUDE_EDITOR
320
void Rhinobot_EditorDraw(void) { Rhinobot_Draw(); }
321
322
void Rhinobot_EditorLoad(void) { Rhinobot->aniFrames = RSDK.LoadSpriteAnimation("AIZ/Rhinobot.bin", SCOPE_STAGE); }
323
#endif
324
325
void Rhinobot_Serialize(void) {}
326
#endif
327
328