Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/SPZ/Letterboard.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Letterboard Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectLetterboard *Letterboard;
11
12
void Letterboard_Update(void)
13
{
14
RSDK_THIS(Letterboard);
15
16
StateMachine_Run(self->state);
17
}
18
19
void Letterboard_LateUpdate(void) {}
20
21
void Letterboard_StaticUpdate(void) {}
22
23
void Letterboard_Draw(void)
24
{
25
RSDK_THIS(Letterboard);
26
27
self->scale.x = abs(RSDK.Cos512(self->angle));
28
RSDK.DrawSprite(RSDK.Cos512(self->angle) >= 0 ? &self->animatorBack : &self->animatorFront, NULL, false);
29
}
30
31
void Letterboard_Create(void *data)
32
{
33
RSDK_THIS(Letterboard);
34
35
if (!SceneInfo->inEditor) {
36
RSDK.SetSpriteAnimation(Letterboard->aniFrames, 0, &self->animatorBack, true, 0);
37
RSDK.SetSpriteAnimation(Letterboard->aniFrames, 1, &self->animatorFront, true, 0);
38
39
if (self->controller) {
40
self->state = Letterboard_State_Controller;
41
}
42
else if (self->letterID) {
43
self->state = Letterboard_State_CheckPlayerSpin;
44
self->animatorFront.frameID = self->letterID - 1;
45
}
46
47
self->scale.x = 0x200;
48
self->scale.y = 0x200;
49
self->active = ACTIVE_BOUNDS;
50
self->updateRange.x = 0x400000;
51
self->updateRange.y = 0x400000;
52
self->visible = true;
53
self->drawGroup = Zone->objectDrawGroup[0];
54
}
55
}
56
57
void Letterboard_StageLoad(void)
58
{
59
Letterboard->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/Letterboard.bin", SCOPE_STAGE);
60
61
Letterboard->hitboxBoard.left = -12;
62
Letterboard->hitboxBoard.top = -12;
63
Letterboard->hitboxBoard.right = 12;
64
Letterboard->hitboxBoard.bottom = 12;
65
66
Letterboard->sfxLetterTurn = RSDK.GetSfx("Stage/LetterTurn.wav");
67
Letterboard->sfxWin = RSDK.GetSfx("Stage/Win.wav");
68
}
69
70
void Letterboard_State_Controller(void)
71
{
72
RSDK_THIS(Letterboard);
73
74
self->active = ACTIVE_BOUNDS;
75
76
bool32 revealedAll = true;
77
int32 slot = SceneInfo->entitySlot + 1;
78
79
for (int32 i = 0; i < self->letterID; ++i) {
80
EntityLetterboard *letterboard = RSDK_GET_ENTITY(slot + i, Letterboard);
81
if (letterboard->state)
82
revealedAll = false;
83
84
if (letterboard->state == Letterboard_State_Spun)
85
self->active = ACTIVE_NORMAL;
86
}
87
88
if (revealedAll) {
89
RSDK.PlaySfx(Letterboard->sfxWin, false, 0xFF);
90
91
self->active = ACTIVE_BOUNDS;
92
self->state = StateMachine_None;
93
if (globals->gameMode != MODE_COMPETITION)
94
Player_GiveScore(RSDK_GET_ENTITY(SLOT_PLAYER1, Player), 100 * self->letterID);
95
}
96
}
97
98
void Letterboard_State_CheckPlayerSpin(void)
99
{
100
RSDK_THIS(Letterboard);
101
102
foreach_active(Player, player)
103
{
104
self->spinSpeed = (abs(player->velocity.x) + abs(player->velocity.y)) >> 14;
105
if (self->spinSpeed > 0) {
106
if (Player_CheckCollisionTouch(player, self, &Letterboard->hitboxBoard)) {
107
self->drawFX = FX_SCALE;
108
self->state = Letterboard_State_Spun;
109
if (self->spinSpeed > 16)
110
self->spinSpeed = 16;
111
if (self->spinSpeed < 8)
112
self->spinSpeed = 8;
113
114
self->timer = 2;
115
int32 slot = SceneInfo->entitySlot;
116
117
EntityLetterboard *letterboard = self;
118
while (slot >= 0) {
119
letterboard = RSDK_GET_ENTITY(slot--, Letterboard);
120
if (letterboard->state == Letterboard_State_Controller)
121
break;
122
}
123
124
letterboard->active = ACTIVE_NORMAL;
125
self->active = ACTIVE_NORMAL;
126
RSDK.PlaySfx(Letterboard->sfxLetterTurn, false, 255);
127
foreach_break;
128
}
129
}
130
}
131
}
132
133
void Letterboard_State_Spun(void)
134
{
135
RSDK_THIS(Letterboard);
136
137
int32 prevAngle = self->angle;
138
self->angle = (self->angle + self->spinSpeed) & 0x1FF;
139
if (self->angle >= 0x100 && prevAngle < 0x100 && --self->timer <= 0) {
140
self->active = ACTIVE_BOUNDS;
141
self->angle = 0x100;
142
self->state = StateMachine_None;
143
}
144
}
145
146
#if GAME_INCLUDE_EDITOR
147
void Letterboard_EditorDraw(void)
148
{
149
RSDK_THIS(Letterboard);
150
151
RSDK.SetSpriteAnimation(Letterboard->aniFrames, 0, &self->animatorBack, true, 0);
152
RSDK.SetSpriteAnimation(Letterboard->aniFrames, 1, &self->animatorFront, true, 0);
153
154
if (!self->controller && self->letterID) {
155
self->animatorFront.frameID = self->letterID - 1;
156
RSDK.DrawSprite(&self->animatorFront, NULL, false);
157
}
158
else {
159
RSDK.DrawSprite(&self->animatorBack, NULL, false);
160
}
161
162
if (self->controller && showGizmos()) {
163
RSDK_DRAWING_OVERLAY(true);
164
165
int32 slot = SceneInfo->entitySlot + 1;
166
for (int32 i = 0; i < self->letterID; ++i) {
167
EntityLetterboard *letterboard = RSDK_GET_ENTITY(slot + i, Letterboard);
168
169
if (letterboard) {
170
DrawHelpers_DrawArrow(self->position.x, self->position.y, letterboard->position.x, letterboard->position.y, 0xFFFF00, INK_NONE, 0xFF);
171
}
172
}
173
174
RSDK_DRAWING_OVERLAY(false);
175
}
176
}
177
178
void Letterboard_EditorLoad(void) { Letterboard->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/Letterboard.bin", SCOPE_STAGE); }
179
#endif
180
181
void Letterboard_Serialize(void)
182
{
183
RSDK_EDITABLE_VAR(Letterboard, VAR_BOOL, controller);
184
RSDK_EDITABLE_VAR(Letterboard, VAR_UINT8, letterID);
185
}
186
187