Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/LRZ/Iwamodoki.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Iwamodoki Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectIwamodoki *Iwamodoki;
11
12
void Iwamodoki_Update(void)
13
{
14
RSDK_THIS(Iwamodoki);
15
16
if (LRZConvItem && self->lrzConvPhys) {
17
self->preMovePos.x = self->position.x;
18
self->preMovePos.y = self->position.y;
19
self->moveOffset = LRZConvItem_HandleLRZConvPhys(self);
20
}
21
else {
22
self->preMovePos.x = self->position.x;
23
self->preMovePos.y = self->position.y;
24
self->moveOffset.x = 0;
25
self->moveOffset.y = 0;
26
}
27
28
self->postMovePos.x = self->position.x;
29
self->postMovePos.y = self->position.y;
30
31
StateMachine_Run(self->state);
32
}
33
34
void Iwamodoki_LateUpdate(void) {}
35
36
void Iwamodoki_StaticUpdate(void) {}
37
38
void Iwamodoki_Draw(void)
39
{
40
RSDK_THIS(Iwamodoki);
41
42
RSDK.DrawSprite(&self->animator, NULL, false);
43
}
44
45
void Iwamodoki_Create(void *data)
46
{
47
RSDK_THIS(Iwamodoki);
48
49
self->drawFX |= FX_FLIP;
50
self->startPos = self->position;
51
self->startDir = self->direction;
52
self->visible = true;
53
self->active = ACTIVE_BOUNDS;
54
self->updateRange.x = 0x800000;
55
self->updateRange.y = 0x800000;
56
self->drawGroup = Zone->objectDrawGroup[0];
57
58
if (data) {
59
self->active = ACTIVE_NORMAL;
60
RSDK.SetSpriteAnimation(Iwamodoki->aniFrames, VOID_TO_INT(data) + 2, &self->animator, true, 0);
61
self->state = Iwamodoki_State_Debris;
62
}
63
else {
64
RSDK.SetSpriteAnimation(Iwamodoki->aniFrames, 0, &self->animator, true, 0);
65
self->state = Iwamodoki_State_Init;
66
}
67
}
68
69
void Iwamodoki_StageLoad(void)
70
{
71
if (RSDK.CheckSceneFolder("LRZ1"))
72
Iwamodoki->aniFrames = RSDK.LoadSpriteAnimation("LRZ1/Iwamodoki.bin", SCOPE_STAGE);
73
else if (RSDK.CheckSceneFolder("LRZ2") || RSDK.CheckSceneFolder("LRZ3"))
74
Iwamodoki->aniFrames = RSDK.LoadSpriteAnimation("LRZ2/Iwamodoki.bin", SCOPE_STAGE);
75
76
Iwamodoki->hitboxBadnik.left = -12;
77
Iwamodoki->hitboxBadnik.top = -11;
78
Iwamodoki->hitboxBadnik.right = 12;
79
Iwamodoki->hitboxBadnik.bottom = 11;
80
81
Iwamodoki->hitboxRange.left = -64;
82
Iwamodoki->hitboxRange.top = -64;
83
Iwamodoki->hitboxRange.right = 64;
84
Iwamodoki->hitboxRange.bottom = 64;
85
86
Iwamodoki->hitboxProjectile.left = -4;
87
Iwamodoki->hitboxProjectile.top = -4;
88
Iwamodoki->hitboxProjectile.right = 4;
89
Iwamodoki->hitboxProjectile.bottom = 4;
90
91
DEBUGMODE_ADD_OBJ(Iwamodoki);
92
}
93
94
void Iwamodoki_DebugSpawn(void)
95
{
96
RSDK_THIS(DebugMode);
97
98
CREATE_ENTITY(Iwamodoki, NULL, self->position.x, self->position.y);
99
}
100
101
void Iwamodoki_DebugDraw(void)
102
{
103
RSDK.SetSpriteAnimation(Iwamodoki->aniFrames, 2, &DebugMode->animator, true, 0);
104
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
105
}
106
107
void Iwamodoki_HandlePlayerCollisions(void)
108
{
109
RSDK_THIS(Iwamodoki);
110
111
self->position.x = self->preMovePos.x;
112
self->position.y = self->preMovePos.y;
113
114
foreach_active(Player, player)
115
{
116
if (Player_CheckCollisionBox(player, self, &Iwamodoki->hitboxBadnik) == C_TOP) {
117
player->position.x += self->moveOffset.x;
118
player->position.y += self->moveOffset.y;
119
}
120
}
121
122
self->position.x = self->postMovePos.x;
123
self->position.y = self->postMovePos.y;
124
}
125
126
void Iwamodoki_CheckOffScreen(void)
127
{
128
RSDK_THIS(Iwamodoki);
129
130
if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {
131
self->position = self->startPos;
132
self->direction = self->startDir;
133
Iwamodoki_Create(NULL);
134
}
135
}
136
137
void Iwamodoki_State_Init(void)
138
{
139
RSDK_THIS(Iwamodoki);
140
141
self->active = ACTIVE_NORMAL;
142
self->velocity.x = -0x10000;
143
144
self->state = Iwamodoki_State_AwaitPlayer;
145
Iwamodoki_State_AwaitPlayer();
146
}
147
148
void Iwamodoki_State_AwaitPlayer(void)
149
{
150
RSDK_THIS(Iwamodoki);
151
152
foreach_active(Player, player)
153
{
154
if (Player_CheckCollisionTouch(player, self, &Iwamodoki->hitboxRange)) {
155
self->state = Iwamodoki_State_Appear;
156
}
157
}
158
159
Iwamodoki_HandlePlayerCollisions();
160
Iwamodoki_CheckOffScreen();
161
}
162
163
void Iwamodoki_State_Appear(void)
164
{
165
RSDK_THIS(Iwamodoki);
166
167
RSDK.ProcessAnimation(&self->animator);
168
169
if (self->animator.frameID == 6) {
170
RSDK.SetSpriteAnimation(Iwamodoki->aniFrames, 1, &self->animator, true, 0);
171
self->chargeCount = 15;
172
self->timer = 15;
173
self->state = Iwamodoki_State_Charging;
174
}
175
176
Iwamodoki_HandlePlayerCollisions();
177
Iwamodoki_CheckOffScreen();
178
}
179
180
void Iwamodoki_State_Charging(void)
181
{
182
RSDK_THIS(Iwamodoki);
183
184
RSDK.ProcessAnimation(&self->animator);
185
186
if (!--self->timer) {
187
if (!--self->chargeCount) {
188
// Explode Anim
189
self->timer = 32;
190
RSDK.SetSpriteAnimation(Iwamodoki->aniFrames, 2, &self->animator, true, 0);
191
self->state = Iwamodoki_State_Explode;
192
}
193
else {
194
// Charging Anim
195
RSDK.SetSpriteAnimation(Iwamodoki->aniFrames, 1, &self->animator, true, 0);
196
self->timer = self->chargeCount;
197
}
198
}
199
200
Iwamodoki_HandlePlayerCollisions();
201
Iwamodoki_CheckOffScreen();
202
}
203
204
void Iwamodoki_State_Explode(void)
205
{
206
RSDK_THIS(Iwamodoki);
207
208
RSDK.ProcessAnimation(&self->animator);
209
210
if (!--self->timer) {
211
CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_ENEMY), self->position.x, self->position.y)->drawGroup = Zone->objectDrawGroup[1];
212
213
if (self->onScreen == 1)
214
RSDK.PlaySfx(Explosion->sfxDestroy, false, 255);
215
216
EntityIwamodoki *debris = CREATE_ENTITY(Iwamodoki, INT_TO_VOID(1), self->position.x, self->position.y);
217
debris->velocity.x = -0x20000;
218
debris->velocity.y = -0x40000;
219
220
debris = CREATE_ENTITY(Iwamodoki, INT_TO_VOID(1), self->position.x, self->position.y);
221
debris->velocity.x = 0x20000;
222
debris->velocity.y = -0x40000;
223
224
debris = CREATE_ENTITY(Iwamodoki, INT_TO_VOID(2), self->position.x, self->position.y);
225
debris->velocity.x = -0x40000;
226
debris->velocity.y = -0x20000;
227
228
debris = CREATE_ENTITY(Iwamodoki, INT_TO_VOID(2), self->position.x, self->position.y);
229
debris->velocity.x = 0x40000;
230
debris->velocity.y = -0x20000;
231
232
destroyEntity(self);
233
}
234
else {
235
Iwamodoki_HandlePlayerCollisions();
236
Iwamodoki_CheckOffScreen();
237
}
238
}
239
240
void Iwamodoki_State_Debris(void)
241
{
242
RSDK_THIS(Iwamodoki);
243
244
RSDK.ProcessAnimation(&self->animator);
245
246
self->position.x += self->velocity.x;
247
self->position.y += self->velocity.y;
248
self->velocity.y += 0x3800;
249
250
foreach_active(Player, player)
251
{
252
if (Player_CheckCollisionTouch(player, self, &Iwamodoki->hitboxProjectile)) {
253
Player_ProjectileHurt(player, self);
254
}
255
}
256
257
if (!RSDK.CheckOnScreen(self, NULL))
258
destroyEntity(self);
259
}
260
261
#if GAME_INCLUDE_EDITOR
262
void Iwamodoki_EditorDraw(void) { Iwamodoki_Draw(); }
263
264
void Iwamodoki_EditorLoad(void)
265
{
266
if (RSDK.CheckSceneFolder("LRZ1"))
267
Iwamodoki->aniFrames = RSDK.LoadSpriteAnimation("LRZ1/Iwamodoki.bin", SCOPE_STAGE);
268
else if (RSDK.CheckSceneFolder("LRZ2") || RSDK.CheckSceneFolder("LRZ3"))
269
Iwamodoki->aniFrames = RSDK.LoadSpriteAnimation("LRZ2/Iwamodoki.bin", SCOPE_STAGE);
270
271
RSDK_ACTIVE_VAR(Iwamodoki, direction);
272
RSDK_ENUM_VAR("No Flip", FLIP_NONE);
273
RSDK_ENUM_VAR("Flip X", FLIP_X);
274
RSDK_ENUM_VAR("Flip Y", FLIP_Y);
275
RSDK_ENUM_VAR("Flip XY", FLIP_XY);
276
}
277
#endif
278
279
void Iwamodoki_Serialize(void)
280
{
281
RSDK_EDITABLE_VAR(Iwamodoki, VAR_UINT8, direction);
282
RSDK_EDITABLE_VAR(Iwamodoki, VAR_BOOL, lrzConvPhys);
283
}
284
285