Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/HPZ/Redz.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Redz Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectRedz *Redz = NULL;
11
12
void Redz_Update(void)
13
{
14
RSDK_THIS(Redz);
15
RSDK.ProcessAnimation(&self->animator);
16
17
StateMachine_Run(self->state);
18
19
if (self->state != Redz_State_Init && self->state != Redz_Flame_State && self->state != Redz_Flame_Setup) {
20
Redz_CheckPlayerCollisions();
21
if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {
22
self->direction = self->startDir;
23
self->position.x = self->startPos.x;
24
self->position.y = self->startPos.y;
25
Redz_Create(NULL);
26
}
27
}
28
}
29
30
void Redz_LateUpdate(void) {}
31
32
void Redz_StaticUpdate(void) {}
33
34
void Redz_Draw(void)
35
{
36
RSDK_THIS(Redz);
37
RSDK.DrawSprite(&self->animator, NULL, false);
38
}
39
40
void Redz_Create(void *data)
41
{
42
RSDK_THIS(Redz);
43
self->visible = true;
44
self->drawGroup = Zone->objectDrawGroup[0];
45
self->startPos = self->position;
46
self->startDir = self->direction;
47
self->drawFX = FX_FLIP;
48
self->active = ACTIVE_BOUNDS;
49
self->updateRange.x = 0x800000;
50
self->updateRange.y = 0x800000;
51
self->state = Redz_State_Init;
52
}
53
54
void Redz_StageLoad(void)
55
{
56
if (RSDK.CheckSceneFolder("HPZ"))
57
Redz->aniFrames = RSDK.LoadSpriteAnimation("HPZ/Redz.bin", SCOPE_STAGE);
58
59
Redz->hitboxBadnik.left = -16;
60
Redz->hitboxBadnik.top = -16;
61
Redz->hitboxBadnik.right = 16;
62
Redz->hitboxBadnik.bottom = 16;
63
64
Redz->attackbox.left = -64;
65
Redz->attackbox.top = -96;
66
Redz->attackbox.right = 0;
67
Redz->attackbox.bottom = -8;
68
69
Redz->hitboxFlame.left = -7;
70
Redz->hitboxFlame.top = -7;
71
Redz->hitboxFlame.right = 7;
72
Redz->hitboxFlame.bottom = -7;
73
74
Redz->hitboxRange.left = 0;
75
Redz->hitboxRange.top = 0;
76
Redz->hitboxRange.right = 0;
77
Redz->hitboxRange.bottom = 0;
78
79
Redz->sfxFlame = RSDK.GetSfx("Stage/Flame.wav");
80
81
DEBUGMODE_ADD_OBJ(Redz);
82
}
83
84
void Redz_DebugSpawn(void)
85
{
86
RSDK_THIS(DebugMode);
87
88
EntityRedz *redz = CREATE_ENTITY(Redz, NULL, self->position.x, self->position.y);
89
redz->direction = self->direction;
90
redz->startDir = self->direction;
91
}
92
93
void Redz_DebugDraw(void)
94
{
95
RSDK.SetSpriteAnimation(Redz->aniFrames, 0, &DebugMode->animator, true, 0);
96
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
97
}
98
99
void Redz_CheckPlayerCollisions(void)
100
{
101
RSDK_THIS(Redz);
102
foreach_active(Player, player)
103
{
104
if (Player_CheckBadnikTouch(player, self, &Redz->hitboxBadnik))
105
Player_CheckBadnikBreak(player, self, true);
106
}
107
}
108
109
void Redz_State_Init(void)
110
{
111
RSDK_THIS(Redz);
112
113
self->active = ACTIVE_NORMAL;
114
RSDK.SetSpriteAnimation(Redz->aniFrames, 0, &self->animator, true, 0);
115
self->animator.frameID = 0;
116
self->animator.speed = 1;
117
self->state = Redz_State_Walk;
118
self->velocity.x = (2 * (self->direction != FLIP_NONE) - 1) << 15;
119
Redz_State_Walk();
120
}
121
122
void Redz_State_Walk(void)
123
{
124
RSDK_THIS(Redz);
125
126
self->position.x += self->velocity.x;
127
if (!RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, (2 * (self->direction != FLIP_NONE) - 1) << 19, 0x100000, 8)) {
128
self->state = Redz_State_Turn;
129
RSDK.SetSpriteAnimation(Redz->aniFrames, 0, &self->animator, true, 0);
130
self->animator.frameID = 0;
131
self->animator.speed = 0;
132
}
133
134
if (self->attackDelay <= 0) {
135
foreach_active(Player, player)
136
{
137
if (RSDK.CheckObjectCollisionTouchBox(player, &Redz->hitboxRange, self, &Redz->attackbox)) {
138
self->state = Redz_State_PrepareAttack;
139
RSDK.SetSpriteAnimation(Redz->aniFrames, 0, &self->animator, true, 0);
140
self->animator.frameID = 0;
141
self->attackDelay = 60;
142
self->animator.speed = 0;
143
}
144
}
145
}
146
else {
147
self->attackDelay--;
148
}
149
}
150
151
void Redz_State_Turn(void)
152
{
153
RSDK_THIS(Redz);
154
155
if (self->timer < 59) {
156
self->timer++;
157
}
158
else {
159
self->state = Redz_State_Walk;
160
self->timer = 0;
161
RSDK.SetSpriteAnimation(Redz->aniFrames, 0, &self->animator, true, 0);
162
self->animator.frameID = 0;
163
self->animator.speed = 1;
164
self->direction = self->direction == FLIP_NONE;
165
self->velocity.x = -self->velocity.x;
166
}
167
}
168
169
void Redz_State_PrepareAttack(void)
170
{
171
RSDK_THIS(Redz);
172
if (self->timer >= 30) {
173
self->state = Redz_State_Attack;
174
self->timer = 0;
175
RSDK.SetSpriteAnimation(Redz->aniFrames, 1, &self->animator, true, 0);
176
RSDK.PlaySfx(Redz->sfxFlame, false, 255);
177
}
178
else {
179
self->timer++;
180
}
181
}
182
183
void Redz_State_Attack(void)
184
{
185
RSDK_THIS(Redz);
186
if (self->timer >= 90) {
187
self->timer = 0;
188
RSDK.SetSpriteAnimation(Redz->aniFrames, 0, &self->animator, true, 0);
189
self->animator.frameID = 0;
190
self->animator.speed = 1;
191
self->state = Redz_State_Walk;
192
}
193
194
if (!(self->timer & 3)) {
195
EntityRedz *flame = CREATE_ENTITY(Redz, self, self->position.x, self->position.y);
196
flame->state = Redz_Flame_Setup;
197
flame->position.y -= 0x40000;
198
flame->position.x += (2 * (self->direction != FLIP_NONE) - 1) << 19;
199
flame->velocity.x =
200
(2 * (self->direction != FLIP_NONE) - 1) * (RSDK.Cos512(((RSDK.Sin512(8 * (self->timer & 0x3F)) >> 5) - 48) & 0x1FF) << 8);
201
flame->velocity.y = RSDK.Sin512(((RSDK.Sin512(8 * (self->timer & 0x3F)) >> 5) - 48) & 0x1FF) << 8;
202
}
203
++self->timer;
204
}
205
206
void Redz_Flame_Setup(void)
207
{
208
RSDK_THIS(Redz);
209
210
self->active = ACTIVE_NORMAL;
211
RSDK.SetSpriteAnimation(Redz->aniFrames, 2, &self->animator, true, 0);
212
self->animator.frameID = 0;
213
self->state = Redz_Flame_State;
214
self->animator.speed = 1;
215
Redz_Flame_State();
216
}
217
218
void Redz_Flame_State(void)
219
{
220
RSDK_THIS(Redz);
221
self->position.x += self->velocity.x;
222
self->position.y += self->velocity.y;
223
224
foreach_active(Player, player)
225
{
226
if (Player_CheckCollisionTouch(player, self, &Redz->hitboxFlame)) {
227
Player_ElementHurt(player, self, SHIELD_FIRE);
228
}
229
}
230
231
if (++self->timer > 20)
232
destroyEntity(self);
233
}
234
235
#if GAME_INCLUDE_EDITOR
236
void Redz_EditorDraw(void)
237
{
238
RSDK_THIS(Redz);
239
RSDK.SetSpriteAnimation(Redz->aniFrames, 0, &self->animator, true, 0);
240
241
Redz_Draw();
242
}
243
244
void Redz_EditorLoad(void)
245
{
246
Redz->aniFrames = RSDK.LoadSpriteAnimation("HPZ/Redz.bin", SCOPE_STAGE);
247
248
RSDK_ACTIVE_VAR(Redz, direction);
249
RSDK_ENUM_VAR("No Flip", FLIP_NONE);
250
RSDK_ENUM_VAR("Flip X", FLIP_X);
251
}
252
#endif
253
254
void Redz_Serialize(void) { RSDK_EDITABLE_VAR(Redz, VAR_UINT8, direction); }
255
256