Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/SPZ/Clapperboard.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Clapperboard Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectClapperboard *Clapperboard;
11
12
void Clapperboard_Update(void)
13
{
14
RSDK_THIS(Clapperboard);
15
16
StateMachine_Run(self->state);
17
18
self->rotation = self->angle >> 1;
19
self->stoodPlayers = 0;
20
StateMachine_Run(self->stateCollide);
21
}
22
23
void Clapperboard_LateUpdate(void) {}
24
25
void Clapperboard_StaticUpdate(void) {}
26
27
void Clapperboard_Draw(void)
28
{
29
RSDK_THIS(Clapperboard);
30
Vector2 drawPos;
31
32
self->drawFX = FX_ROTATE | FX_FLIP;
33
RSDK.DrawSprite(&self->clapperTopAnimator, NULL, false);
34
35
self->drawFX = FX_FLIP;
36
RSDK.DrawSprite(&self->clapperBottomAnimator, NULL, false);
37
38
self->drawFX = FX_NONE;
39
RSDK.DrawSprite(&self->boardAnimator, NULL, false);
40
41
drawPos.x = self->position.x;
42
drawPos.y = self->position.y;
43
if (self->direction == FLIP_X)
44
drawPos.x -= 0x670000;
45
else
46
drawPos.x += 0x10000;
47
self->numbersAnimator.frameID = self->takeID / 100;
48
RSDK.DrawSprite(&self->numbersAnimator, &drawPos, false);
49
50
drawPos.x += 0xD0000;
51
self->numbersAnimator.frameID = (self->takeID / 10) % 10;
52
RSDK.DrawSprite(&self->numbersAnimator, &drawPos, false);
53
54
drawPos.x += 0xD0000;
55
self->numbersAnimator.frameID = self->takeID % 10;
56
RSDK.DrawSprite(&self->numbersAnimator, &drawPos, false);
57
58
drawPos.x += 0x120000;
59
self->numbersAnimator.frameID = SceneInfo->minutes % 10;
60
RSDK.DrawSprite(&self->numbersAnimator, &drawPos, false);
61
62
drawPos.x += 0x120000;
63
self->numbersAnimator.frameID = SceneInfo->seconds / 10;
64
RSDK.DrawSprite(&self->numbersAnimator, &drawPos, false);
65
66
drawPos.x += 0xD0000;
67
self->numbersAnimator.frameID = SceneInfo->seconds % 10;
68
RSDK.DrawSprite(&self->numbersAnimator, &drawPos, false);
69
70
drawPos.x += 0x110000;
71
self->numbersAnimator.frameID = SceneInfo->milliseconds / 10;
72
RSDK.DrawSprite(&self->numbersAnimator, &drawPos, false);
73
}
74
75
void Clapperboard_Create(void *data)
76
{
77
RSDK_THIS(Clapperboard);
78
79
RSDK.SetSpriteAnimation(Clapperboard->aniFrames, 0, &self->clapperTopAnimator, true, 0);
80
RSDK.SetSpriteAnimation(Clapperboard->aniFrames, 0, &self->clapperBottomAnimator, true, 1);
81
RSDK.SetSpriteAnimation(Clapperboard->aniFrames, 0, &self->boardAnimator, true, 2);
82
RSDK.SetSpriteAnimation(Clapperboard->aniFrames, 1, &self->numbersAnimator, true, 0);
83
84
if (!SceneInfo->inEditor) {
85
self->active = ACTIVE_BOUNDS;
86
self->updateRange.x = 0x800000;
87
self->updateRange.y = 0x800000;
88
89
if (self->direction == FLIP_NONE) {
90
self->amplitudeL.x = -0x40000;
91
self->amplitudeR.x = 0x6C0000;
92
self->angle = 0x3C0;
93
self->stateCollide = Clapperboard_Collide_Right;
94
}
95
else {
96
++self->boardAnimator.frameID;
97
self->amplitudeL.x = -0x6C0000;
98
self->amplitudeR.x = 0x40000;
99
self->angle = 0x040;
100
self->stateCollide = Clapperboard_Collide_Left;
101
}
102
103
self->amplitudeL.y = -0x40000;
104
self->amplitudeR.y = -0x40000;
105
self->state = Clapperboard_State_Idle;
106
self->visible = true;
107
self->drawGroup = Zone->objectDrawGroup[0];
108
}
109
}
110
111
void Clapperboard_StageLoad(void)
112
{
113
if (RSDK.CheckSceneFolder("SPZ1"))
114
Clapperboard->aniFrames = RSDK.LoadSpriteAnimation("SPZ1/Clapperboard.bin", SCOPE_STAGE);
115
else
116
Clapperboard->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/Clapperboard.bin", SCOPE_STAGE);
117
118
Clapperboard->sfxWhack = RSDK.GetSfx("Stage/Whack.wav");
119
}
120
121
void Clapperboard_Collide_Left(void)
122
{
123
RSDK_THIS(Clapperboard);
124
125
uint8 negAngle = -(-self->angle >> 2);
126
127
int32 ampL = (self->amplitudeL.y >> 8) * RSDK.Cos256(negAngle) - (self->amplitudeL.x >> 8) * RSDK.Sin256(negAngle);
128
int32 ampR = (self->amplitudeR.y >> 8) * RSDK.Cos256(negAngle) - (self->amplitudeR.x >> 8) * RSDK.Sin256(negAngle);
129
130
self->hitbox.left = ((self->amplitudeL.y >> 8) * RSDK.Sin256(negAngle) + (self->amplitudeL.x >> 8) * RSDK.Cos256(negAngle)) >> 16;
131
self->hitbox.right = ((self->amplitudeR.y >> 8) * RSDK.Sin256(negAngle) + (self->amplitudeR.x >> 8) * RSDK.Cos256(negAngle)) >> 16;
132
133
int32 clapStartPos = self->hitbox.right - self->hitbox.left;
134
self->direction ^= FLIP_X;
135
bool32 clapped = false;
136
137
foreach_active(Player, player)
138
{
139
int32 standPos = self->hitbox.right - CLAMP((player->position.x - self->position.x) >> 16, self->hitbox.left, self->hitbox.right);
140
int32 top = (ampR >> 16) + ((ampR >> 16) - (ampL >> 16)) * standPos / clapStartPos - (self->clapSpeed & 0xFFFF);
141
self->hitbox.top = top;
142
self->hitbox.bottom = top + 24;
143
if (Player_CheckCollisionPlatform(player, self, &self->hitbox)) {
144
#if MANIA_USE_PLUS
145
if (player->state == Player_State_MightyHammerDrop)
146
player->state = Player_State_Air;
147
#endif
148
149
player->position.y += (self->clapSpeed + 2) << 16;
150
if (standPos > (clapStartPos >> 2)) {
151
self->stoodPlayers |= RSDK.GetEntitySlot(player) + 1;
152
if (self->state == Clapperboard_State_ClapReboundL
153
|| (abs(player->groundVel) > 0x80000 && standPos > clapStartPos - (clapStartPos >> 2))) {
154
player->onGround = false;
155
player->state = Player_State_Air;
156
player->velocity.y = -0x40000 - 0x60000 * standPos / clapStartPos;
157
158
int32 anim = player->animator.animationID;
159
if (anim == ANI_WALK || (anim > ANI_AIR_WALK && anim <= ANI_DASH))
160
player->animationReserve = player->animator.animationID;
161
else
162
player->animationReserve = ANI_WALK;
163
164
RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_DIAGONAL, &player->animator, true, 0);
165
RSDK.PlaySfx(Clapperboard->sfxWhack, false, 255);
166
clapped = true;
167
}
168
else {
169
int32 clapSpeed = 16;
170
if (abs(player->groundVel) < 0xA0000)
171
clapSpeed = 16 * standPos / clapStartPos;
172
173
if (clapSpeed > self->clapSpeed)
174
self->clapSpeed = clapSpeed;
175
}
176
}
177
}
178
}
179
180
self->direction ^= FLIP_X;
181
if (clapped)
182
++self->takeID;
183
}
184
185
void Clapperboard_Collide_Right(void)
186
{
187
RSDK_THIS(Clapperboard);
188
189
int32 negAngle = -(-self->angle >> 2);
190
191
int32 ampL = (self->amplitudeL.y >> 8) * RSDK.Cos256(negAngle) - (self->amplitudeL.x >> 8) * RSDK.Sin256(negAngle);
192
int32 ampR = (self->amplitudeR.y >> 8) * RSDK.Cos256(negAngle) - (self->amplitudeR.x >> 8) * RSDK.Sin256(negAngle);
193
194
self->hitbox.left = (((self->amplitudeL.y >> 8) * RSDK.Sin256(negAngle)) + (self->amplitudeL.x >> 8) * RSDK.Cos256(negAngle)) >> 16;
195
self->hitbox.right = (((self->amplitudeR.y >> 8) * RSDK.Sin256(negAngle)) + (self->amplitudeR.x >> 8) * RSDK.Cos256(negAngle)) >> 16;
196
int32 clapStartPos = self->hitbox.right - self->hitbox.left;
197
bool32 clapped = false;
198
199
foreach_active(Player, player)
200
{
201
int32 standPos = CLAMP((player->position.x - self->position.x) >> 16, self->hitbox.left, self->hitbox.right) - self->hitbox.left;
202
int32 top = (ampL >> 16) + ((ampL >> 16) - (ampR >> 16)) * standPos / clapStartPos - (self->clapSpeed & 0xFFFF);
203
self->hitbox.top = top;
204
self->hitbox.bottom = top + 24;
205
206
if (Player_CheckCollisionPlatform(player, self, &self->hitbox)) {
207
#if MANIA_USE_PLUS
208
if (player->state == Player_State_MightyHammerDrop)
209
player->state = Player_State_Air;
210
#endif
211
212
player->position.y += (self->clapSpeed + 2) << 16;
213
if (standPos > clapStartPos >> 2) {
214
self->stoodPlayers |= RSDK.GetEntitySlot(player) + 1;
215
if (self->state == Clapperboard_State_ClapReboundR
216
|| (abs(player->groundVel) > 0x80000 && standPos > clapStartPos - (clapStartPos >> 2))) {
217
player->onGround = false;
218
player->state = Player_State_Air;
219
player->velocity.y = -0x40000 - 0x60000 * standPos / clapStartPos;
220
221
int32 anim = player->animator.animationID;
222
if (anim == ANI_WALK || (anim > ANI_AIR_WALK && anim <= ANI_DASH))
223
player->animationReserve = player->animator.animationID;
224
else
225
player->animationReserve = ANI_WALK;
226
227
RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_DIAGONAL, &player->animator, true, 0);
228
RSDK.PlaySfx(Clapperboard->sfxWhack, false, 0xFF);
229
clapped = true;
230
}
231
else {
232
int32 clapSpeed = 16;
233
if (abs(player->groundVel) < 0xA0000)
234
clapSpeed = 16 * standPos / clapStartPos;
235
236
if (clapSpeed > self->clapSpeed)
237
self->clapSpeed = clapSpeed;
238
}
239
}
240
}
241
}
242
243
if (clapped)
244
++self->takeID;
245
}
246
247
void Clapperboard_State_Idle(void)
248
{
249
RSDK_THIS(Clapperboard);
250
251
if (self->stoodPlayers > 0)
252
self->state = self->direction == FLIP_NONE ? Clapperboard_State_ClappingR : Clapperboard_State_ClappingL;
253
}
254
255
void Clapperboard_State_ClappingL(void)
256
{
257
RSDK_THIS(Clapperboard);
258
259
self->angle -= self->clapSpeed;
260
if (self->angle <= 0x000) {
261
self->angle = 0x000;
262
self->state = Clapperboard_State_ClapReboundL;
263
}
264
}
265
266
void Clapperboard_State_ClapReboundL(void)
267
{
268
RSDK_THIS(Clapperboard);
269
270
self->angle += self->clapSpeed;
271
if (self->angle >= 0x040) {
272
self->angle = 0x040;
273
self->clapSpeed = 0;
274
self->state = Clapperboard_State_Idle;
275
}
276
}
277
278
void Clapperboard_State_ClappingR(void)
279
{
280
RSDK_THIS(Clapperboard);
281
282
self->angle += self->clapSpeed;
283
if (self->angle >= 0x400) {
284
self->angle = 0x400;
285
self->state = Clapperboard_State_ClapReboundR;
286
}
287
}
288
289
void Clapperboard_State_ClapReboundR(void)
290
{
291
RSDK_THIS(Clapperboard);
292
293
self->angle -= self->clapSpeed;
294
if (self->angle <= 0x3C0) {
295
self->angle = 0x3C0;
296
self->clapSpeed = 0;
297
self->state = Clapperboard_State_Idle;
298
}
299
}
300
301
#if GAME_INCLUDE_EDITOR
302
void Clapperboard_EditorDraw(void)
303
{
304
RSDK_THIS(Clapperboard);
305
306
self->boardAnimator.frameID = self->direction == FLIP_NONE ? 2 : 3;
307
308
Clapperboard_Draw();
309
}
310
311
void Clapperboard_EditorLoad(void)
312
{
313
if (RSDK.CheckSceneFolder("SPZ1"))
314
Clapperboard->aniFrames = RSDK.LoadSpriteAnimation("SPZ1/Clapperboard.bin", SCOPE_STAGE);
315
else
316
Clapperboard->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/Clapperboard.bin", SCOPE_STAGE);
317
318
RSDK_ACTIVE_VAR(Clapperboard, direction);
319
RSDK_ENUM_VAR("Right", FLIP_NONE);
320
RSDK_ENUM_VAR("Left", FLIP_X);
321
}
322
#endif
323
324
void Clapperboard_Serialize(void) { RSDK_EDITABLE_VAR(Clapperboard, VAR_UINT8, direction); }
325
326