Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/CPZ/Springboard.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Springboard Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectSpringboard *Springboard;
11
12
void Springboard_Update(void)
13
{
14
RSDK_THIS(Springboard);
15
16
RSDK.ProcessAnimation(&self->animator);
17
18
// bounceDelay is unused, but if it was used, it'd prolly be "if (!--self->bounceDelay) {" around this foreach loop.
19
// source: it was exactly like that in S2 '13
20
foreach_active(Player, playerPtr)
21
{
22
if (playerPtr->velocity.y >= 0 && ((1 << RSDK.GetEntitySlot(playerPtr)) & self->activePlayers)) {
23
int32 pos = CLAMP((playerPtr->position.x - self->position.x + 0x1C0000) >> 17, 0, 28);
24
25
if ((self->direction & FLIP_X))
26
pos = 28 - pos;
27
28
if (pos >= 8) {
29
if (self->animator.frameID == 3)
30
RSDK.SetSpriteAnimation(Springboard->aniFrames, 0, &self->animator, true, 0);
31
32
if (self->animator.frameID == 2) {
33
int32 anim = playerPtr->animator.animationID;
34
if (anim == ANI_WALK || (anim > ANI_AIR_WALK && anim <= ANI_DASH))
35
playerPtr->animationReserve = playerPtr->animator.animationID;
36
else
37
playerPtr->animationReserve = ANI_WALK;
38
39
playerPtr->state = Player_State_Air;
40
playerPtr->onGround = false;
41
playerPtr->tileCollisions = TILECOLLISION_DOWN;
42
RSDK.SetSpriteAnimation(playerPtr->aniFrames, ANI_SPRING_CS, &playerPtr->animator, true, 1);
43
playerPtr->groundVel = playerPtr->velocity.x;
44
playerPtr->velocity.y = Springboard->springPower[MIN(2 * pos - 16, 39)] - playerPtr->gravityStrength - self->force;
45
playerPtr->applyJumpCap = false;
46
47
RSDK.PlaySfx(Springboard->sfxSpring, false, 0xFF);
48
}
49
}
50
}
51
}
52
53
foreach_active(Player, player)
54
{
55
int32 playerID = RSDK.GetEntitySlot(player);
56
57
int32 playerGndVel = player->groundVel;
58
int32 playerVelX = player->velocity.x;
59
int32 springPos = CLAMP((player->position.x - self->position.x + 0x1C0000) >> 17, 0, 27);
60
bool32 bounced = false;
61
62
if (!self->direction) {
63
int32 hitboxTop = 0;
64
65
if (self->animator.frameID <= 2)
66
hitboxTop = Springboard->heightsFlat[springPos];
67
else if (self->animator.frameID == 3)
68
hitboxTop = Springboard->heightsReady[springPos];
69
70
Hitbox hitbox;
71
hitbox.left = -28;
72
hitbox.top = -hitboxTop;
73
hitbox.right = 28;
74
hitbox.bottom = 8;
75
76
uint8 collision = 0;
77
if (!((1 << playerID) & self->activePlayers))
78
bounced = collision = Player_CheckCollisionBox(player, self, &hitbox);
79
else
80
bounced = collision = Player_CheckCollisionPlatform(player, self, &hitbox);
81
82
bounced = collision == C_TOP;
83
switch (collision) {
84
case C_LEFT:
85
player->groundVel = playerGndVel;
86
player->velocity.x = playerVelX;
87
// [Fallthrough]
88
case C_NONE:
89
case C_RIGHT:
90
case C_BOTTOM:
91
if (player->velocity.y >= 0 && ((1 << playerID) & self->activePlayers)) {
92
Hitbox *playerHitbox = Player_GetHitbox(player);
93
player->position.y = self->position.y - (playerHitbox->bottom << 16) - (hitboxTop << 16);
94
95
if (!bounced)
96
bounced = player->position.x > self->position.x;
97
}
98
break;
99
100
case C_TOP:
101
#if MANIA_USE_PLUS
102
if (player->state == Player_State_MightyHammerDrop)
103
player->state = Player_State_Air;
104
#endif
105
break;
106
107
default: break;
108
}
109
110
player->flailing = false;
111
}
112
else if (self->direction == FLIP_X) {
113
int32 pos = abs(springPos - 27);
114
int32 hitboxTop = 0;
115
116
if (self->animator.frameID <= 2)
117
hitboxTop = Springboard->heightsFlat[pos];
118
else if (self->animator.frameID == 3)
119
hitboxTop = Springboard->heightsReady[pos];
120
121
Hitbox hitbox;
122
hitbox.left = -28;
123
hitbox.top = -hitboxTop;
124
hitbox.right = 28;
125
hitbox.bottom = 8;
126
127
uint8 collision = 0;
128
if (!((1 << playerID) & self->activePlayers))
129
collision = Player_CheckCollisionBox(player, self, &hitbox);
130
else
131
collision = Player_CheckCollisionPlatform(player, self, &hitbox);
132
133
bounced = collision == C_TOP;
134
switch (collision) {
135
case C_NONE:
136
case C_LEFT:
137
case C_BOTTOM: break;
138
139
case C_TOP:
140
#if MANIA_USE_PLUS
141
if (player->state == Player_State_MightyHammerDrop) {
142
player->state = Player_State_Air;
143
}
144
#endif
145
break;
146
147
case C_RIGHT:
148
player->groundVel = playerGndVel;
149
player->velocity.x = playerVelX;
150
break;
151
152
default: break;
153
}
154
155
if (player->velocity.y >= 0 && ((1 << playerID) & self->activePlayers)) {
156
Hitbox *playerHitbox = Player_GetHitbox(player);
157
player->position.y = self->position.y - (playerHitbox->bottom << 16) - (hitboxTop << 16);
158
if (!bounced)
159
bounced = player->position.x < self->position.x;
160
}
161
162
player->flailing = false;
163
}
164
165
if (bounced) {
166
self->activePlayers |= (1 << playerID);
167
if (springPos >= 8 && !self->bounceDelay)
168
self->bounceDelay = 6;
169
}
170
else {
171
self->activePlayers &= ~(1 << playerID);
172
}
173
}
174
}
175
176
void Springboard_LateUpdate(void) {}
177
178
void Springboard_StaticUpdate(void) {}
179
180
void Springboard_Draw(void)
181
{
182
RSDK_THIS(Springboard);
183
184
RSDK.DrawSprite(&self->animator, NULL, false);
185
}
186
187
void Springboard_Create(void *data)
188
{
189
RSDK_THIS(Springboard);
190
191
self->visible = true;
192
self->drawGroup = Zone->objectDrawGroup[0];
193
self->drawFX |= FX_FLIP;
194
self->active = ACTIVE_BOUNDS;
195
self->updateRange.x = 0x400000;
196
self->updateRange.y = 0x400000;
197
198
if (!SceneInfo->inEditor) {
199
self->force = (self->force + 8) << 15;
200
RSDK.SetSpriteAnimation(Springboard->aniFrames, 0, &self->animator, true, 3);
201
}
202
}
203
204
void Springboard_StageLoad(void)
205
{
206
Springboard->aniFrames = RSDK.LoadSpriteAnimation("CPZ/Springboard.bin", SCOPE_STAGE);
207
208
Springboard->sfxSpring = RSDK.GetSfx("Global/Spring.wav");
209
210
DEBUGMODE_ADD_OBJ(Springboard);
211
}
212
213
void Springboard_DebugSpawn(void)
214
{
215
RSDK_THIS(DebugMode);
216
217
CREATE_ENTITY(Springboard, NULL, self->position.x, self->position.y);
218
}
219
void Springboard_DebugDraw(void)
220
{
221
RSDK.SetSpriteAnimation(Springboard->aniFrames, 1, &DebugMode->animator, true, 0);
222
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
223
}
224
225
#if GAME_INCLUDE_EDITOR
226
void Springboard_EditorDraw(void)
227
{
228
RSDK_THIS(Springboard);
229
RSDK.SetSpriteAnimation(Springboard->aniFrames, 0, &self->animator, false, 3);
230
231
Springboard_Draw();
232
}
233
234
void Springboard_EditorLoad(void)
235
{
236
Springboard->aniFrames = RSDK.LoadSpriteAnimation("CPZ/Springboard.bin", SCOPE_STAGE);
237
238
RSDK_ACTIVE_VAR(Springboard, direction);
239
RSDK_ENUM_VAR("Right", FLIP_NONE);
240
RSDK_ENUM_VAR("Left", FLIP_X);
241
}
242
#endif
243
244
void Springboard_Serialize(void)
245
{
246
RSDK_EDITABLE_VAR(Springboard, VAR_UINT8, direction);
247
RSDK_EDITABLE_VAR(Springboard, VAR_ENUM, force);
248
}
249
250