Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/TMZ/GymBar.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: GymBar Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectGymBar *GymBar;
11
12
void GymBar_Update(void) { GymBar_HandlePlayerInteractions(); }
13
14
void GymBar_LateUpdate(void) {}
15
16
void GymBar_StaticUpdate(void) {}
17
18
void GymBar_Draw(void)
19
{
20
RSDK_THIS(GymBar);
21
22
Vector2 drawPos = self->position;
23
if (self->type != GYMBAR_HORIZONTAL) {
24
drawPos.y = self->position.y - (self->size << 18);
25
self->animator.frameID = 0;
26
RSDK.DrawSprite(&self->animator, &drawPos, false);
27
28
self->animator.frameID = 1;
29
for (int32 i = 0; i < self->size; ++i) {
30
RSDK.DrawSprite(&self->animator, &drawPos, false);
31
drawPos.y += 0x80000;
32
}
33
}
34
else {
35
drawPos.x = self->position.x - (self->size << 18);
36
self->animator.frameID = 0;
37
RSDK.DrawSprite(&self->animator, &drawPos, false);
38
39
self->animator.frameID = 1;
40
for (int32 i = 0; i < self->size; ++i) {
41
RSDK.DrawSprite(&self->animator, &drawPos, false);
42
drawPos.x += 0x80000;
43
}
44
}
45
46
self->animator.frameID = 2;
47
RSDK.DrawSprite(&self->animator, &drawPos, false);
48
}
49
50
void GymBar_Create(void *data)
51
{
52
RSDK_THIS(GymBar);
53
54
self->drawFX = FX_FLIP;
55
self->visible = true;
56
self->drawGroup = Zone->objectDrawGroup[0];
57
self->active = ACTIVE_BOUNDS;
58
self->updateRange.x = 0x400000;
59
self->updateRange.y = 0x400000;
60
61
if (self->type == GYMBAR_HORIZONTAL) {
62
self->updateRange.x = (self->size << 18) + 0x400000;
63
64
self->hitbox.left = -4 * self->size;
65
self->hitbox.top = 0;
66
self->hitbox.right = 4 * self->size - 8;
67
self->hitbox.bottom = 8;
68
69
self->maxX = self->position.x - (self->size << 18) + 0x50000;
70
self->minX = (self->size << 18) + self->position.x - 0xC0000;
71
}
72
else {
73
self->updateRange.y = (self->size + 16) << 18;
74
75
self->hitbox.left = 0;
76
self->hitbox.top = (8 - (self->size << 2));
77
self->hitbox.right = 0;
78
self->hitbox.bottom = (self->size << 2) - 16;
79
}
80
81
RSDK.SetSpriteAnimation(GymBar->aniFrames, self->type, &self->animator, true, 0);
82
}
83
84
void GymBar_StageLoad(void)
85
{
86
if (RSDK.CheckSceneFolder("TMZ1") || RSDK.CheckSceneFolder("TMZ2"))
87
GymBar->aniFrames = RSDK.LoadSpriteAnimation("TMZ1/GymBar.bin", SCOPE_STAGE);
88
89
GymBar->sfxBumper = RSDK.GetSfx("Stage/Bumper3.wav");
90
91
DEBUGMODE_ADD_OBJ(GymBar);
92
}
93
94
void GymBar_DebugSpawn(void)
95
{
96
RSDK_THIS(GymBar);
97
98
CREATE_ENTITY(GymBar, NULL, self->position.x, self->position.y);
99
}
100
101
void GymBar_DebugDraw(void)
102
{
103
RSDK.SetSpriteAnimation(GymBar->aniFrames, 0, &DebugMode->animator, true, 0);
104
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
105
}
106
107
void GymBar_HandlePlayerInteractions(void)
108
{
109
RSDK_THIS(GymBar);
110
111
foreach_active(Player, player)
112
{
113
int32 playerID = RSDK.GetEntitySlot(player);
114
if (player->animator.animationID != ANI_HURT && player->state != Player_State_FlyCarried) {
115
if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {
116
if (!self->playerTimers[playerID]) {
117
player->onGround = false;
118
if (self->type != GYMBAR_HORIZONTAL) {
119
if (abs(player->velocity.x) >= 0x40000) {
120
player->position.x = self->position.x;
121
player->direction = FLIP_NONE;
122
if (player->velocity.x <= 0)
123
RSDK.SetSpriteAnimation(player->aniFrames, ANI_POLE_SWING_H, &player->animator, false, 2);
124
else
125
RSDK.SetSpriteAnimation(player->aniFrames, ANI_POLE_SWING_H, &player->animator, false, 9);
126
player->animator.speed = 0xE0 + ((abs(player->velocity.x) - 0x40000) >> 12);
127
player->abilityValues[0] = 0;
128
player->abilityValues[1] = player->animator.frameID;
129
player->abilityValues[2] = player->velocity.x;
130
player->state = GymBar_PlayerState_SwingH;
131
}
132
}
133
else {
134
player->rotation = 0;
135
player->position.x = CLAMP(player->position.x, self->maxX, self->minX);
136
player->position.y = self->position.y;
137
138
if (abs(player->velocity.y) < 0x40000 || self->noSwing) {
139
RSDK.SetSpriteAnimation(player->aniFrames, ANI_POLE_SWING_V, &player->animator, false, 0);
140
player->animator.speed = 0;
141
player->abilityPtrs[0] = self;
142
player->state = GymBar_PlayerState_Hang;
143
}
144
else {
145
if (player->velocity.y <= 0)
146
RSDK.SetSpriteAnimation(player->aniFrames, ANI_POLE_SWING_V, &player->animator, false, 2);
147
else
148
RSDK.SetSpriteAnimation(player->aniFrames, ANI_POLE_SWING_V, &player->animator, false, 9);
149
player->animator.speed = 0x100 + ((abs(player->velocity.y) - 0x40000) >> 12);
150
player->abilityValues[0] = 0;
151
player->abilityValues[1] = player->animator.frameID;
152
player->abilityValues[2] = player->velocity.y;
153
player->state = GymBar_PlayerState_SwingV;
154
}
155
}
156
157
if (player->state == GymBar_PlayerState_Hang || player->state == GymBar_PlayerState_SwingH
158
|| player->state == GymBar_PlayerState_SwingV) {
159
self->playerTimers[playerID] = 16;
160
RSDK.PlaySfx(Player->sfxGrab, false, 0xFF);
161
player->nextAirState = StateMachine_None;
162
player->nextGroundState = StateMachine_None;
163
player->velocity.x = 0;
164
player->velocity.y = 0;
165
player->groundVel = 0;
166
player->applyJumpCap = false;
167
}
168
}
169
}
170
else {
171
if (self->playerTimers[playerID])
172
self->playerTimers[playerID]--;
173
}
174
}
175
}
176
}
177
178
void GymBar_HandleSwingJump(void)
179
{
180
RSDK_THIS(Player);
181
182
if (!self->down)
183
self->velocity.y = -0x50000;
184
185
RSDK.SetSpriteAnimation(self->aniFrames, ANI_JUMP, &self->animator, false, 0);
186
187
if (self->characterID == ID_TAILS)
188
self->animator.speed = 120;
189
else
190
self->animator.speed = ((abs(self->groundVel) * 0xF0) / 0x60000) + 0x30;
191
192
if (self->animator.speed > 0xF0)
193
self->animator.speed = 0xF0;
194
195
self->applyJumpCap = true;
196
self->jumpAbilityState = 1;
197
self->abilityPtrs[0] = NULL;
198
self->abilityValues[0] = 0;
199
self->abilityValues[1] = 0;
200
self->abilityValues[2] = 0;
201
202
self->state = Player_State_Air;
203
}
204
205
void GymBar_PlayerState_SwingV(void)
206
{
207
RSDK_THIS(Player);
208
209
if (self->jumpPress)
210
GymBar_HandleSwingJump();
211
212
int32 frame = self->abilityValues[2] <= 0 ? 4 : 11;
213
214
if (self->animator.frameID == frame && self->abilityValues[1] != frame)
215
++self->abilityValues[0];
216
217
self->abilityValues[1] = self->animator.frameID;
218
if (self->abilityValues[0] >= 2) {
219
if (self->abilityValues[2] <= 0)
220
RSDK.SetSpriteAnimation(self->aniFrames, ANI_SPRING_DIAGONAL, &self->animator, false, 0);
221
else
222
RSDK.SetSpriteAnimation(self->aniFrames, ANI_WALK, &self->animator, false, 0);
223
224
self->velocity.y =
225
self->abilityValues[2] + (self->abilityValues[2] >> ((abs(self->abilityValues[2]) >> 18) + (abs(self->abilityValues[2]) >> 20)));
226
self->abilityPtrs[0] = NULL;
227
self->abilityValues[0] = 0;
228
self->abilityValues[1] = 0;
229
self->abilityValues[2] = 0;
230
231
self->state = Player_State_Air;
232
}
233
}
234
235
void GymBar_PlayerState_Hang(void)
236
{
237
RSDK_THIS(Player);
238
239
EntityGymBar *gymbar = self->abilityPtrs[0];
240
if (self->left) {
241
if (self->position.x > gymbar->maxX)
242
self->position.x -= 0x10000;
243
244
RSDK.SetSpriteAnimation(self->aniFrames, ANI_SHIMMY_MOVE, &self->animator, false, 0);
245
self->direction = FLIP_X;
246
}
247
else if (self->right) {
248
if (self->position.x < gymbar->minX)
249
self->position.x += 0x10000;
250
251
RSDK.SetSpriteAnimation(self->aniFrames, ANI_SHIMMY_MOVE, &self->animator, false, 0);
252
self->direction = FLIP_NONE;
253
}
254
else {
255
RSDK.SetSpriteAnimation(self->aniFrames, ANI_SHIMMY_IDLE, &self->animator, false, 0);
256
}
257
258
if (self->jumpPress)
259
GymBar_HandleSwingJump();
260
}
261
262
void GymBar_PlayerState_SwingH(void)
263
{
264
RSDK_THIS(Player);
265
266
if (self->jumpPress)
267
GymBar_HandleSwingJump();
268
269
int32 frame = self->abilityValues[2] <= 0 ? 4 : 11;
270
271
if (self->animator.frameID == frame && self->abilityValues[1] != frame)
272
++self->abilityValues[0];
273
274
self->abilityValues[1] = self->animator.frameID;
275
if (self->abilityValues[0] >= 2) {
276
RSDK.SetSpriteAnimation(self->aniFrames, ANI_WALK, &self->animator, false, 0);
277
278
self->velocity.x = self->abilityValues[2] + (self->abilityValues[2] >> (abs(self->abilityValues[2]) >> 18));
279
self->groundVel = self->velocity.x;
280
self->direction = abs(self->velocity.x >> 31);
281
282
self->abilityPtrs[0] = NULL;
283
self->abilityValues[0] = 0;
284
self->abilityValues[1] = 0;
285
self->abilityValues[2] = 0;
286
287
self->state = Player_State_Air;
288
}
289
}
290
291
#if GAME_INCLUDE_EDITOR
292
void GymBar_EditorDraw(void)
293
{
294
RSDK_THIS(GymBar);
295
296
if (self->type == GYMBAR_HORIZONTAL) {
297
self->updateRange.x = (self->size << 18) + 0x400000;
298
self->maxX = self->position.x - (self->size << 18) + 0x50000;
299
self->minX = (self->size << 18) + self->position.x - 0xC0000;
300
}
301
else {
302
self->updateRange.y = (self->size + 16) << 18;
303
}
304
305
RSDK.SetSpriteAnimation(GymBar->aniFrames, self->type, &self->animator, true, 0);
306
307
GymBar_Draw();
308
}
309
310
void GymBar_EditorLoad(void)
311
{
312
GymBar->aniFrames = RSDK.LoadSpriteAnimation("TMZ1/GymBar.bin", SCOPE_STAGE);
313
314
RSDK_ACTIVE_VAR(GymBar, type);
315
RSDK_ENUM_VAR("Horizontal", GYMBAR_HORIZONTAL);
316
RSDK_ENUM_VAR("Vertical", GYMBAR_VERTICAL);
317
}
318
#endif
319
320
void GymBar_Serialize(void)
321
{
322
RSDK_EDITABLE_VAR(GymBar, VAR_ENUM, type);
323
RSDK_EDITABLE_VAR(GymBar, VAR_ENUM, size);
324
RSDK_EDITABLE_VAR(GymBar, VAR_BOOL, noSwing);
325
}
326
327