Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/Unused/WallCrawl.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: WallCrawl Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectWallCrawl *WallCrawl = NULL;
11
12
void WallCrawl_Update(void)
13
{
14
RSDK_THIS(WallCrawl);
15
StateMachine_Run(self->state);
16
}
17
18
void WallCrawl_LateUpdate(void) {}
19
20
void WallCrawl_StaticUpdate(void) {}
21
22
void WallCrawl_Draw(void)
23
{
24
RSDK_THIS(WallCrawl);
25
RSDK.DrawSprite(&self->animator, NULL, false);
26
}
27
28
void WallCrawl_Create(void *data)
29
{
30
RSDK_THIS(WallCrawl);
31
32
self->drawFX |= FX_FLIP;
33
self->startPos.x = self->position.x;
34
self->startPos.y = self->position.y;
35
self->startDir = self->direction;
36
self->visible = true;
37
self->active = ACTIVE_BOUNDS;
38
self->updateRange.x = 0x800000;
39
self->updateRange.y = 0x800000;
40
self->playerPtr = NULL;
41
if (data) {
42
self->drawGroup = Zone->objectDrawGroup[0];
43
RSDK.SetSpriteAnimation(WallCrawl->aniFrames, 3, &self->animator, true, 0);
44
self->state = WallCrawl_State_Projectile;
45
}
46
else {
47
self->drawGroup = Zone->objectDrawGroup[0] + 1;
48
RSDK.SetSpriteAnimation(WallCrawl->aniFrames, 2, &self->animator, true, 0);
49
self->state = WallCrawl_State_Init;
50
}
51
}
52
53
void WallCrawl_StageLoad(void)
54
{
55
WallCrawl->aniFrames = RSDK.LoadSpriteAnimation("Blueprint/WallCrawl.bin", SCOPE_STAGE);
56
57
WallCrawl->hitboxBadnik.left = -14;
58
WallCrawl->hitboxBadnik.top = -14;
59
WallCrawl->hitboxBadnik.right = 14;
60
WallCrawl->hitboxBadnik.bottom = 14;
61
62
WallCrawl->hitboxRange.left = -128;
63
WallCrawl->hitboxRange.top = -128;
64
WallCrawl->hitboxRange.right = 128;
65
WallCrawl->hitboxRange.bottom = 128;
66
67
WallCrawl->hitboxLaser.left = -132;
68
WallCrawl->hitboxLaser.top = 8;
69
WallCrawl->hitboxLaser.right = 132;
70
WallCrawl->hitboxLaser.bottom = -8;
71
72
WallCrawl->hitboxProjectile.left = -24;
73
WallCrawl->hitboxProjectile.top = -1;
74
WallCrawl->hitboxProjectile.right = 24;
75
WallCrawl->hitboxProjectile.bottom = 9;
76
77
DEBUGMODE_ADD_OBJ(WallCrawl);
78
}
79
80
void WallCrawl_DebugSpawn(void)
81
{
82
RSDK_THIS(WallCrawl);
83
EntityWallCrawl *wallCrawl = CREATE_ENTITY(WallCrawl, NULL, self->position.x, self->position.y);
84
wallCrawl->direction = self->direction;
85
wallCrawl->startDir = self->direction;
86
}
87
88
void WallCrawl_DebugDraw(void)
89
{
90
RSDK.SetSpriteAnimation(WallCrawl->aniFrames, 2, &DebugMode->animator, true, 0);
91
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
92
}
93
94
void WallCrawl_HandlePlayerInteractions(void)
95
{
96
RSDK_THIS(WallCrawl);
97
foreach_active(Player, player)
98
{
99
if (!self->timer) {
100
if (Player_CheckCollisionTouch(player, self, &WallCrawl->hitboxRange)) {
101
if (self->playerPtr) {
102
if (abs(player->position.x - self->position.x) < abs(self->playerPtr->position.x - self->position.x))
103
self->playerPtr = player;
104
}
105
else {
106
self->playerPtr = player;
107
}
108
}
109
}
110
if (Player_CheckBadnikTouch(player, self, &WallCrawl->hitboxBadnik))
111
Player_CheckBadnikBreak(player, self, true);
112
}
113
}
114
115
void WallCrawl_CheckOffScreen(void)
116
{
117
RSDK_THIS(WallCrawl);
118
if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {
119
self->position = self->startPos;
120
self->direction = self->startDir;
121
WallCrawl_Create(NULL);
122
}
123
}
124
125
void WallCrawl_State_Init(void)
126
{
127
RSDK_THIS(WallCrawl);
128
129
int32 offsetY = -0xC0000;
130
self->active = ACTIVE_NORMAL;
131
if (self->direction & FLIP_Y)
132
offsetY = 0xC0000;
133
134
int32 offsetX = -0xD0000;
135
if (!(self->direction & FLIP_X))
136
offsetX = 0xC0000;
137
138
RSDK.ObjectTileGrip(self, Zone->collisionLayers, (2 * ((self->direction & FLIP_X) != 0) + 1), 0, offsetX, offsetY, 8);
139
self->state = WallCrawl_State_Moving;
140
WallCrawl_State_Moving();
141
}
142
143
void WallCrawl_State_Moving(void)
144
{
145
RSDK_THIS(WallCrawl);
146
147
if (self->timer)
148
self->timer--;
149
150
EntityPlayer *playerPtr = self->playerPtr;
151
if (playerPtr) {
152
if (Player_CheckCollisionTouch(playerPtr, self, &WallCrawl->hitboxRange)) {
153
if (!Player_CheckCollisionTouch(playerPtr, self, &WallCrawl->hitboxLaser)) {
154
self->animator.speed = 48;
155
if (playerPtr->position.y <= self->position.y) {
156
self->direction &= ~FX_ROTATE;
157
self->velocity.y = -0x10000;
158
}
159
else {
160
self->direction |= FX_ROTATE;
161
self->velocity.y = 0x10000;
162
}
163
}
164
else {
165
int32 offsetX = -0x180000;
166
self->state = WallCrawl_State_Idle;
167
if (!(self->direction & FLIP_X))
168
offsetX = 0x180000;
169
self->idleTimer = 30;
170
CREATE_ENTITY(WallCrawl, INT_TO_VOID(true), self->position.x + offsetX, self->position.y)->direction = self->direction;
171
self->timer = 180;
172
self->playerPtr = NULL;
173
}
174
}
175
else {
176
self->playerPtr = NULL;
177
}
178
}
179
else {
180
self->animator.speed = 24;
181
if (!(self->direction & FLIP_Y))
182
self->velocity.y = -0x8000;
183
else
184
self->velocity.y = 0x8000;
185
}
186
187
self->position.y += self->velocity.y;
188
int32 offsetY = -0xC0000;
189
self->active = ACTIVE_NORMAL;
190
if (self->direction & FLIP_Y)
191
offsetY = 0xC0000;
192
193
int32 offsetX = -0xD0000;
194
if (!(self->direction & FLIP_X))
195
offsetX = 0xC0000;
196
if (!RSDK.ObjectTileGrip(self, Zone->collisionLayers, (2 * ((self->direction & 1) != 0) + 1), 0, offsetX, offsetY, 0)) {
197
self->state = WallCrawl_State_Idle;
198
self->idleTimer = 30;
199
if (self->playerPtr) {
200
self->playerPtr = 0;
201
self->timer = 180;
202
}
203
}
204
RSDK.ProcessAnimation(&self->animator);
205
WallCrawl_HandlePlayerInteractions();
206
WallCrawl_CheckOffScreen();
207
}
208
209
void WallCrawl_State_Idle(void)
210
{
211
RSDK_THIS(WallCrawl);
212
if (!--self->idleTimer) {
213
if (abs(self->velocity.y) == 0x8000)
214
self->direction ^= FLIP_Y;
215
self->state = WallCrawl_State_Moving;
216
WallCrawl_State_Moving();
217
}
218
else {
219
WallCrawl_HandlePlayerInteractions();
220
}
221
WallCrawl_CheckOffScreen();
222
}
223
224
void WallCrawl_State_Projectile(void)
225
{
226
RSDK_THIS(WallCrawl);
227
228
RSDK.ProcessAnimation(&self->animator);
229
if (self->direction & FLIP_X)
230
self->position.x += 0x40000;
231
else
232
self->position.x -= 0x40000;
233
234
foreach_active(Player, player)
235
{
236
if (Player_CheckCollisionTouch(player, self, &WallCrawl->hitboxProjectile)) {
237
Player_Hurt(player, self);
238
}
239
}
240
}
241
242
#if GAME_INCLUDE_EDITOR
243
void WallCrawl_EditorDraw(void)
244
{
245
RSDK_THIS(WallCrawl);
246
RSDK.SetSpriteAnimation(WallCrawl->aniFrames, 2, &self->animator, true, 0);
247
RSDK.DrawSprite(&self->animator, NULL, false);
248
}
249
250
void WallCrawl_EditorLoad(void)
251
{
252
WallCrawl->aniFrames = RSDK.LoadSpriteAnimation("Blueprint/WallCrawl.bin", SCOPE_STAGE);
253
254
RSDK_ACTIVE_VAR(WallCrawl, direction);
255
RSDK_ENUM_VAR("No Flip", FLIP_NONE);
256
RSDK_ENUM_VAR("Flip X", FLIP_X);
257
RSDK_ENUM_VAR("Flip Y", FLIP_Y);
258
RSDK_ENUM_VAR("Flip XY", FLIP_XY);
259
}
260
#endif
261
262
void WallCrawl_Serialize(void) { RSDK_EDITABLE_VAR(WallCrawl, VAR_UINT8, direction); }
263
264