Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/OOZ/Octus.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Octus Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectOctus *Octus;
11
12
void Octus_Update(void)
13
{
14
RSDK_THIS(Octus);
15
16
StateMachine_Run(self->state);
17
}
18
19
void Octus_LateUpdate(void) {}
20
21
void Octus_StaticUpdate(void) {}
22
23
void Octus_Draw(void)
24
{
25
RSDK_THIS(Octus);
26
27
RSDK.DrawSprite(&self->animator, NULL, false);
28
}
29
30
void Octus_Create(void *data)
31
{
32
RSDK_THIS(Octus);
33
34
self->visible = true;
35
self->drawGroup = Zone->objectDrawGroup[0];
36
self->drawFX |= FX_FLIP;
37
self->startPos = self->position;
38
self->startDir = self->direction;
39
self->timer = 128;
40
self->unused1 = 0;
41
self->unused2 = 0;
42
43
if (data) {
44
self->inkEffect = INK_ADD;
45
self->alpha = 0xC0;
46
self->active = ACTIVE_NORMAL;
47
self->updateRange.x = 0x200000;
48
self->updateRange.y = 0x200000;
49
RSDK.SetSpriteAnimation(Octus->aniFrames, 3, &self->animator, true, 0);
50
self->state = Octus_State_Shot;
51
}
52
else {
53
self->active = ACTIVE_BOUNDS;
54
self->updateRange.x = 0x800000;
55
self->updateRange.y = 0x800000;
56
RSDK.SetSpriteAnimation(Octus->aniFrames, 0, &self->animator, true, 0);
57
self->state = Octus_State_Init;
58
self->alpha = 0xC0;
59
}
60
}
61
62
void Octus_StageLoad(void)
63
{
64
if (RSDK.CheckSceneFolder("OOZ1") || RSDK.CheckSceneFolder("OOZ2"))
65
Octus->aniFrames = RSDK.LoadSpriteAnimation("OOZ/Octus.bin", SCOPE_STAGE);
66
67
Octus->hitboxBadnik.left = -16;
68
Octus->hitboxBadnik.top = -12;
69
Octus->hitboxBadnik.right = 16;
70
Octus->hitboxBadnik.bottom = 12;
71
72
Octus->hitboxRange.left = -128;
73
Octus->hitboxRange.top = -512;
74
Octus->hitboxRange.right = 128;
75
Octus->hitboxRange.bottom = 512;
76
77
Octus->hitboxProjectile.left = -4;
78
Octus->hitboxProjectile.top = -4;
79
Octus->hitboxProjectile.right = 4;
80
Octus->hitboxProjectile.bottom = 4;
81
82
Octus->sfxShot = RSDK.GetSfx("Stage/Shot.wav");
83
84
DEBUGMODE_ADD_OBJ(Octus);
85
}
86
87
void Octus_DebugSpawn(void)
88
{
89
RSDK_THIS(Octus);
90
91
EntityOctus *octus = CREATE_ENTITY(Octus, NULL, self->position.x, self->position.y);
92
octus->direction = self->direction;
93
octus->startDir = self->direction;
94
}
95
96
void Octus_DebugDraw(void)
97
{
98
RSDK.SetSpriteAnimation(Octus->aniFrames, 0, &DebugMode->animator, true, 0);
99
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
100
}
101
102
void Octus_CheckPlayerCollisions(void)
103
{
104
RSDK_THIS(Octus);
105
106
foreach_active(Player, player)
107
{
108
if (Player_CheckBadnikTouch(player, self, &Octus->hitboxBadnik))
109
Player_CheckBadnikBreak(player, self, true);
110
}
111
}
112
113
void Octus_CheckOffScreen(void)
114
{
115
RSDK_THIS(Octus);
116
117
if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {
118
self->position = self->startPos;
119
self->direction = self->startDir;
120
Octus_Create(NULL);
121
}
122
}
123
124
void Octus_State_Init(void)
125
{
126
RSDK_THIS(Octus);
127
128
self->active = ACTIVE_NORMAL;
129
130
self->state = Octus_State_CheckPlayerInRange;
131
Octus_State_CheckPlayerInRange();
132
}
133
134
void Octus_State_CheckPlayerInRange(void)
135
{
136
RSDK_THIS(Octus);
137
138
RSDK.ProcessAnimation(&self->animator);
139
140
foreach_active(Player, player)
141
{
142
if (Player_CheckCollisionTouch(player, self, &Octus->hitboxRange)) {
143
self->timer = 32;
144
RSDK.SetSpriteAnimation(Octus->aniFrames, 1, &self->animator, true, 0);
145
self->state = Octus_State_JumpDelay;
146
foreach_break;
147
}
148
}
149
150
Octus_CheckPlayerCollisions();
151
Octus_CheckOffScreen();
152
}
153
154
void Octus_State_JumpDelay(void)
155
{
156
RSDK_THIS(Octus);
157
158
RSDK.ProcessAnimation(&self->animator);
159
160
if (--self->timer <= 0) {
161
self->velocity.y = -0x20000;
162
self->state = Octus_State_Jump;
163
}
164
165
Octus_CheckPlayerCollisions();
166
Octus_CheckOffScreen();
167
}
168
169
void Octus_State_Jump(void)
170
{
171
RSDK_THIS(Octus);
172
173
RSDK.ProcessAnimation(&self->animator);
174
175
self->position.y += self->velocity.y;
176
self->velocity.y += 0x1000;
177
178
if (self->velocity.y >= 0) {
179
self->timer = 60;
180
RSDK.SetSpriteAnimation(Octus->aniFrames, 2, &self->animator, true, 0);
181
self->state = Octus_State_Shoot;
182
}
183
184
Octus_CheckPlayerCollisions();
185
Octus_CheckOffScreen();
186
}
187
188
void Octus_State_Shoot(void)
189
{
190
RSDK_THIS(Octus);
191
192
RSDK.ProcessAnimation(&self->animator);
193
194
if (--self->timer == 51) {
195
EntityOctus *shot = CREATE_ENTITY(Octus, INT_TO_VOID(true), self->position.x, self->position.y);
196
if (self->direction) {
197
shot->position.x += 0xE0000;
198
shot->velocity.x = 0x20000;
199
}
200
else {
201
shot->position.x -= 0xE0000;
202
shot->velocity.x = -0x20000;
203
}
204
205
RSDK.PlaySfx(Octus->sfxShot, false, 255);
206
}
207
else if (self->timer <= 0) {
208
self->state = Octus_State_Fall;
209
}
210
211
Octus_CheckPlayerCollisions();
212
Octus_CheckOffScreen();
213
}
214
215
void Octus_State_Fall(void)
216
{
217
RSDK_THIS(Octus);
218
219
RSDK.ProcessAnimation(&self->animator);
220
221
self->position.y += self->velocity.y;
222
self->velocity.y += 0x1000;
223
224
if (RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0xD0000, 1)) {
225
self->velocity.y = 0;
226
RSDK.SetSpriteAnimation(Octus->aniFrames, 0, &self->animator, true, 0);
227
self->state = Octus_State_CheckPlayerInRange;
228
}
229
230
Octus_CheckPlayerCollisions();
231
Octus_CheckOffScreen();
232
}
233
234
void Octus_State_Shot(void)
235
{
236
RSDK_THIS(Octus);
237
238
self->position.x += self->velocity.x;
239
self->position.y += self->velocity.y;
240
241
if (RSDK.CheckOnScreen(self, NULL)) {
242
RSDK.ProcessAnimation(&self->animator);
243
foreach_active(Player, player)
244
{
245
if (Player_CheckCollisionTouch(player, self, &Octus->hitboxProjectile))
246
Player_ProjectileHurt(player, self);
247
}
248
}
249
else {
250
destroyEntity(self);
251
}
252
}
253
254
#if GAME_INCLUDE_EDITOR
255
void Octus_EditorDraw(void) { Octus_Draw(); }
256
257
void Octus_EditorLoad(void)
258
{
259
Octus->aniFrames = RSDK.LoadSpriteAnimation("OOZ/Octus.bin", SCOPE_STAGE);
260
261
RSDK_ACTIVE_VAR(Octus, direction);
262
RSDK_ENUM_VAR("Left", FLIP_NONE);
263
RSDK_ENUM_VAR("Right", FLIP_X);
264
}
265
#endif
266
267
void Octus_Serialize(void) { RSDK_EDITABLE_VAR(Octus, VAR_UINT8, direction); }
268
269