Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/SPZ/RockemSockem.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: RockemSockem Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectRockemSockem *RockemSockem;
11
12
void RockemSockem_Update(void)
13
{
14
RSDK_THIS(RockemSockem);
15
16
RSDK.ProcessAnimation(&self->ballAnimator);
17
18
if (self->bounceTimer > 0) {
19
if (!--self->bounceTimer)
20
RSDK.SetSpriteAnimation(RockemSockem->aniFrames, 2, &self->ballAnimator, true, self->ballAnimator.frameID);
21
}
22
23
if (self->reboundTimer > 0) {
24
if (!--self->reboundTimer) {
25
self->position.x = self->startPos.x;
26
self->position.y = self->startPos.y;
27
self->velocity.x = 0;
28
self->velocity.y = 0;
29
self->active = ACTIVE_BOUNDS;
30
}
31
}
32
33
self->position.x += self->velocity.x;
34
self->position.y += self->velocity.y;
35
self->velocity.x = self->velocity.x + ((self->startPos.x - self->position.x) >> 6) - (self->velocity.x >> 4);
36
self->velocity.y = self->velocity.y + ((self->startPos.y - self->position.y) >> 6) - (self->velocity.y >> 4);
37
38
foreach_active(Player, player)
39
{
40
if (Player_CheckBadnikTouch(player, self, &RockemSockem->hitbox)) {
41
int32 vel = abs(player->velocity.x) <= abs(player->velocity.y) ? abs(player->velocity.y) : abs(player->velocity.x);
42
43
int32 angle = RSDK.ATan2((player->position.x - self->position.x) / 3, player->position.y - self->position.y);
44
int32 distX = abs(self->position.x - self->startPos.x);
45
int32 distY = abs(self->position.y - self->startPos.y);
46
self->reboundTimer = 120;
47
48
int32 dx = (distX >> 16) * (distX >> 16);
49
int32 dy = (distY >> 16) * (distY >> 16);
50
51
if (dx + dy < 0x100 && !self->bounceTimer) {
52
if ((angle - 0x20) & 0xC0) {
53
self->velocity.x -= vel * RSDK.Cos256(angle) >> 8;
54
self->velocity.y -= vel * RSDK.Sin256(angle) >> 8;
55
}
56
else {
57
self->velocity.x -= vel * RSDK.Cos256(angle) >> 9;
58
self->velocity.y -= 0x2000;
59
}
60
61
self->velocity.x = CLAMP(self->velocity.x, -0x40000, 0x40000);
62
player->velocity.x -= player->velocity.x >> 4;
63
if (player->velocity.y <= 0)
64
player->velocity.y -= player->velocity.y >> 5;
65
else
66
player->velocity.y -= player->velocity.y >> 4;
67
68
self->active = ACTIVE_NORMAL;
69
}
70
else if (player->velocity.y < 0) {
71
self->active = ACTIVE_NORMAL;
72
}
73
else {
74
int32 angleVal = ((angle - 0x20) >> 6) & 3;
75
76
int32 anim = player->animator.animationID;
77
switch (angleVal) {
78
default:
79
case 0:
80
player->velocity.x = ((RSDK.Cos256(angle) << 9) + player->velocity.x) >> 1;
81
player->velocity.y = -(abs(RSDK.Sin256(angle)) * 0x400);
82
83
if (anim != ANI_JUMP && anim != ANI_JOG && anim != ANI_RUN && anim != ANI_DASH)
84
player->animator.animationID = ANI_WALK;
85
break;
86
87
case 1:
88
player->velocity.x = (0x500 * RSDK.Cos256(angle) + player->velocity.x) >> 1;
89
player->velocity.y = -(abs(RSDK.Sin256(angle)) * 0x500);
90
91
RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_CS, &player->animator, false, 0);
92
break;
93
94
case 2:
95
player->velocity.x = (0x700 * RSDK.Cos256(angle) + player->velocity.x) >> 1;
96
player->velocity.y = -(abs(RSDK.Sin256(angle)) * 0x700);
97
98
RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_CS, &player->animator, false, 0);
99
break;
100
101
case 3: break;
102
}
103
104
if (self->ballAnimator.animationID != 3)
105
RSDK.PlaySfx(RockemSockem->sfxRockemSockem, false, 0xFF);
106
107
// Bug Details:
108
// this one's actually the opposite of normal, since its fixed in release builds
109
// but if you comment out this Player_State_Air line and glide into the rockem sockem as knux
110
// you'll get the funny anim bug they showed off at SDCC 2017
111
player->state = Player_State_Air;
112
player->onGround = false;
113
RSDK.SetSpriteAnimation(RockemSockem->aniFrames, 3, &self->ballAnimator, true, self->ballAnimator.frameID);
114
self->bounceTimer = 16;
115
self->active = ACTIVE_NORMAL;
116
}
117
}
118
}
119
120
if (self->position.y > self->drawPos.y - 0xE0000) {
121
self->position.y = self->drawPos.y - 0xE0000;
122
self->bounceTimer = 16;
123
}
124
125
self->angleVel = 0;
126
if (abs(self->startPos.x - self->position.x) > 0x10000)
127
self->angleVel = (self->startPos.x - self->position.x) >> 17;
128
129
RockemSockem_HandleJointPositions();
130
}
131
132
void RockemSockem_LateUpdate(void) {}
133
134
void RockemSockem_StaticUpdate(void) {}
135
136
void RockemSockem_Draw(void)
137
{
138
RSDK_THIS(RockemSockem);
139
140
for (int32 i = 0; i < ROCKEMSOCKEM_COIL_COUNT; ++i) {
141
self->rotation = self->jointRotations[i];
142
RSDK.DrawSprite(&self->jointAnimator, &self->jointPositions[i], false);
143
}
144
145
RSDK.DrawSprite(&self->baseAnimator, &self->drawPos, false);
146
147
if (self->ballAnimator.frameID > 9)
148
self->direction = FLIP_X;
149
RSDK.DrawSprite(&self->ballAnimator, NULL, false);
150
151
self->direction = FLIP_NONE;
152
}
153
154
void RockemSockem_Create(void *data)
155
{
156
RSDK_THIS(RockemSockem);
157
158
RSDK.SetSpriteAnimation(RockemSockem->aniFrames, 0, &self->baseAnimator, true, 0);
159
RSDK.SetSpriteAnimation(RockemSockem->aniFrames, 1, &self->jointAnimator, true, 0);
160
RSDK.SetSpriteAnimation(RockemSockem->aniFrames, 2, &self->ballAnimator, true, 0);
161
162
if (!SceneInfo->inEditor) {
163
self->drawPos = self->position;
164
self->position.y -= (0xE0000 + (0x50000 * ROCKEMSOCKEM_COIL_COUNT));
165
self->startPos = self->position;
166
self->angle = 0x80;
167
self->active = ACTIVE_BOUNDS;
168
self->updateRange.x = 0x800000;
169
self->updateRange.y = 0x800000;
170
self->visible = true;
171
self->drawGroup = Zone->objectDrawGroup[0];
172
self->drawFX = FX_ROTATE | FX_FLIP;
173
}
174
}
175
176
void RockemSockem_StageLoad(void)
177
{
178
if (RSDK.CheckSceneFolder("SPZ1"))
179
RockemSockem->aniFrames = RSDK.LoadSpriteAnimation("SPZ1/RockemSockem.bin", SCOPE_STAGE);
180
else
181
RockemSockem->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/RockemSockem.bin", SCOPE_STAGE);
182
183
RockemSockem->hitbox.left = -16;
184
RockemSockem->hitbox.top = -14;
185
RockemSockem->hitbox.right = 16;
186
RockemSockem->hitbox.bottom = 14;
187
188
RockemSockem->sfxRockemSockem = RSDK.GetSfx("Stage/RockemSockem.wav");
189
}
190
191
void RockemSockem_HandleJointPositions(void)
192
{
193
RSDK_THIS(RockemSockem);
194
195
int32 x = (RSDK.Sin256(self->angle) << 11) + self->drawPos.x;
196
int32 y = (RSDK.Cos256(self->angle) << 11) + self->drawPos.y;
197
198
int32 ang = RSDK.ATan2(y - self->position.y, (RSDK.Sin256(self->angle) << 11) + self->drawPos.x - self->position.x);
199
int32 posX = (0xC00 * RSDK.Sin256(ang) + self->position.x) & 0xFFFF0000;
200
int32 posY = (0xC00 * RSDK.Cos256(ang) + self->position.y) & 0xFFFF0000;
201
202
int32 angle = self->angle;
203
x >>= 16;
204
y >>= 16;
205
posX >>= 16;
206
posY >>= 16;
207
208
self->jointRotations[0] = 2 * (640 - angle);
209
self->jointPositions[0].x = 0x10002 * x;
210
self->jointPositions[0].y = 0x10002 * y;
211
212
angle += self->angleVel;
213
self->jointRotations[1] = 2 * (640 - angle);
214
self->jointPositions[1].x = 0x2AAB * (x + posX + 4 * x);
215
self->jointPositions[1].y = 0x2AAB * (y + posY + 4 * y);
216
217
angle += self->angleVel;
218
self->jointRotations[2] = 2 * (640 - angle);
219
self->jointPositions[2].x = 0x5556 * (posX + 2 * x);
220
self->jointPositions[2].y = 0x5556 * (posY + 2 * y);
221
222
angle += self->angleVel;
223
self->jointRotations[3] = 2 * (640 - angle);
224
self->jointPositions[3].x = 0x8001 * (x + posX);
225
self->jointPositions[3].y = 0x8001 * (y + posY);
226
227
angle += self->angleVel;
228
self->jointRotations[4] = 2 * (640 - angle);
229
self->jointPositions[4].x = 0x5556 * (x + 2 * posX);
230
self->jointPositions[4].y = 0x5556 * (y + 2 * posY);
231
232
angle -= self->angleVel;
233
self->jointRotations[5] = 2 * (640 - angle);
234
self->jointPositions[5].x = 0x2AAB * (posX + x + 4 * posX);
235
self->jointPositions[5].y = 0x2AAB * (posY + y + 4 * posY);
236
}
237
238
#if GAME_INCLUDE_EDITOR
239
void RockemSockem_EditorDraw(void)
240
{
241
RSDK_THIS(RockemSockem);
242
243
self->drawPos = self->position;
244
self->position.y -= (0xE0000 + (0x50000 * ROCKEMSOCKEM_COIL_COUNT));
245
self->startPos = self->position;
246
self->angle = 0x80;
247
self->active = ACTIVE_BOUNDS;
248
self->updateRange.x = 0x800000;
249
self->updateRange.y = 0x800000;
250
self->visible = true;
251
self->drawGroup = Zone->objectDrawGroup[0];
252
self->drawFX = FX_ROTATE | FX_FLIP;
253
254
self->angleVel = 0;
255
if (abs(self->startPos.x - self->position.x) > 0x10000)
256
self->angleVel = (self->startPos.x - self->position.x) >> 17;
257
258
RockemSockem_HandleJointPositions();
259
260
RockemSockem_Draw();
261
}
262
263
void RockemSockem_EditorLoad(void)
264
{
265
if (RSDK.CheckSceneFolder("SPZ1"))
266
RockemSockem->aniFrames = RSDK.LoadSpriteAnimation("SPZ1/RockemSockem.bin", SCOPE_STAGE);
267
else
268
RockemSockem->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/RockemSockem.bin", SCOPE_STAGE);
269
}
270
#endif
271
272
void RockemSockem_Serialize(void) {}
273