Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/HCZ/PullChain.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: PullChain Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectPullChain *PullChain;
11
12
void PullChain_Update(void)
13
{
14
RSDK_THIS(PullChain);
15
16
if (!self->decorMode) {
17
if (self->currentlyActive)
18
self->currentlyActive = false;
19
20
foreach_active(Player, player)
21
{
22
int32 playerID = RSDK.GetEntitySlot(player);
23
24
if (self->grabDelay[playerID] > 0)
25
self->grabDelay[playerID]--;
26
27
if (!player->sidekick) {
28
if (((1 << playerID) & self->activePlayers)) {
29
if (self->chainOffset < 0x100000)
30
self->chainOffset += 0x8000;
31
32
if (self->chainOffset > 0x100000)
33
self->chainOffset = 0x100000;
34
35
if (self->chainOffset == 0x100000) {
36
if (!self->down) {
37
self->currentlyActive = true;
38
self->activated = true;
39
self->toggled = !self->toggled;
40
}
41
42
self->down = true;
43
}
44
}
45
46
self->position.y = self->basePos.y + self->chainOffset;
47
}
48
49
if (!((1 << playerID) & self->activePlayers)) {
50
if (!(self->releasedPlayers & (1 << playerID))) {
51
if (!Current || !((1 << playerID) & Current->activePlayers)) {
52
int32 x = abs(player->position.x - self->position.x) >> 16;
53
int32 y = abs((player->position.y - 0x180000) - self->position.y) >> 16;
54
55
if (MathHelpers_SquareRoot(x * x + y * y) <= 8 && player->state != Player_State_Static
56
&& !self->grabDelay[playerID]) {
57
self->activePlayers |= 1 << playerID;
58
self->releasedPlayers |= 1 << playerID;
59
60
RSDK.PlaySfx(Player->sfxGrab, false, 0xFF);
61
62
if (!player->sidekick)
63
RSDK.PlaySfx(PullChain->sfxPullChain, false, 0xFF);
64
65
RSDK.SetSpriteAnimation(player->aniFrames, ANI_HANG, &player->animator, true, 6);
66
player->nextGroundState = StateMachine_None;
67
player->nextAirState = StateMachine_None;
68
player->velocity.x = 0;
69
player->velocity.y = 0;
70
player->state = Player_State_Static;
71
72
// Reset the dunky code inputs if a proper player grabs it
73
if (!player->sidekick) {
74
for (int32 i = 0; i < 18; ++i) self->cheatCodeInputs[i] = 0;
75
}
76
}
77
}
78
}
79
}
80
81
if ((1 << playerID) & self->activePlayers) {
82
player->position.x = self->position.x;
83
player->position.y = self->position.y + 0x1C0000;
84
85
// R.I.P dunkey mode, you are very missed :(
86
#if GAME_VERSION == VER_100
87
if (!player->sidekick && PullChain_HandleDunkeyCode(player)) {
88
HandLauncher->dunkeyMode = true;
89
RSDK.PlaySfx(Ring->sfxRing, false, 0xFF);
90
}
91
#endif
92
93
if (player->jumpPress || player->animator.animationID != ANI_HANG || player->velocity.x || player->velocity.y) {
94
self->activePlayers &= ~(1 << playerID);
95
if (player->jumpPress) {
96
if (self->chainOffset < 0x100000 && !player->sidekick)
97
RSDK.StopSfx(PullChain->sfxPullChain);
98
99
RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, true, 0);
100
player->velocity.x = 0;
101
player->velocity.y = -0x20000;
102
player->state = Player_State_Air;
103
}
104
105
self->grabDelay[playerID] = 30;
106
}
107
108
if ((1 << playerID) & self->activePlayers)
109
continue;
110
}
111
112
// Make sure we're far enough away before unsetting this
113
// This controls if players can grab the hook
114
if (self->releasedPlayers & (1 << playerID)) {
115
int32 x = abs(player->position.x - self->position.x);
116
int32 y = abs(player->position.y - 0x180000 - self->position.y);
117
if (MathHelpers_SquareRoot((x >> 16) * (x >> 16) + (y >> 16) * (y >> 16)) > 4)
118
self->releasedPlayers &= ~(1 << playerID);
119
}
120
}
121
122
if (!self->activePlayers) {
123
self->down = false;
124
125
if (self->chainOffset > 0)
126
self->chainOffset -= 0x8000;
127
128
if (self->chainOffset < 0)
129
self->chainOffset = 0;
130
}
131
}
132
}
133
134
void PullChain_LateUpdate(void) {}
135
136
void PullChain_StaticUpdate(void) {}
137
138
void PullChain_Draw(void)
139
{
140
RSDK_THIS(PullChain);
141
142
RSDK.DrawSprite(&self->hookAnimator, NULL, false);
143
144
Vector2 drawPos = self->position;
145
for (int32 i = 0; i < self->length; ++i) {
146
RSDK.DrawSprite(&self->chainAnimator, &drawPos, false);
147
drawPos.y -= 0x80000;
148
}
149
150
for (int32 i = 0; i < self->chainOffset; i += 0x80000) {
151
RSDK.DrawSprite(&self->chainAnimator, &drawPos, false);
152
drawPos.y -= 0x80000;
153
}
154
}
155
156
void PullChain_Create(void *data)
157
{
158
RSDK_THIS(PullChain);
159
160
self->active = ACTIVE_BOUNDS;
161
self->drawGroup = self->decorMode ? Zone->objectDrawGroup[0] : Zone->playerDrawGroup[0];
162
self->basePos = self->position;
163
self->visible = true;
164
self->drawFX = FX_FLIP;
165
self->updateRange.x = 0x800000;
166
self->updateRange.y = 0x800000;
167
168
self->hitbox.left = -10;
169
self->hitbox.top = 3;
170
self->hitbox.right = 10;
171
self->hitbox.bottom = 12;
172
173
RSDK.SetSpriteAnimation(PullChain->aniFrames, 0, &self->hookAnimator, true, self->decorMode);
174
RSDK.SetSpriteAnimation(PullChain->aniFrames, 1, &self->chainAnimator, true, self->decorMode);
175
}
176
177
void PullChain_StageLoad(void)
178
{
179
PullChain->aniFrames = RSDK.LoadSpriteAnimation("HCZ/PullChain.bin", SCOPE_STAGE);
180
181
PullChain->sfxPullChain = RSDK.GetSfx("HCZ/PullChain.wav");
182
}
183
184
#if GAME_VERSION == VER_100
185
bool32 PullChain_HandleDunkeyCode(EntityPlayer *player)
186
{
187
RSDK_THIS(PullChain);
188
189
if (HandLauncher->dunkeyMode)
190
return false;
191
192
uint8 buttonMasks = PULLCHAIN_INPUT_NONE;
193
if (player->left)
194
buttonMasks = 1;
195
196
if (player->right)
197
buttonMasks |= 2;
198
199
if (player->up)
200
buttonMasks |= 4;
201
202
if (player->down)
203
buttonMasks |= 8;
204
205
if (buttonMasks == self->codeButtonMasks)
206
return false;
207
208
for (int32 i = 1; i < 18; ++i) self->cheatCodeInputs[i - 1] = self->cheatCodeInputs[i];
209
210
self->cheatCodeInputs[17] = PULLCHAIN_INPUT_NONE;
211
if (player->left)
212
self->cheatCodeInputs[17] = PULLCHAIN_INPUT_LEFT;
213
else if (player->right)
214
self->cheatCodeInputs[17] = PULLCHAIN_INPUT_RIGHT;
215
else if (player->up)
216
self->cheatCodeInputs[17] = PULLCHAIN_INPUT_UP;
217
else if (player->down)
218
self->cheatCodeInputs[17] = PULLCHAIN_INPUT_DOWN;
219
220
bool32 activatedCheatCode = true;
221
for (int32 i = 0; i < 18; ++i) activatedCheatCode &= (self->cheatCodeInputs[i] == PullChain->dunkeyCode[i]);
222
self->codeButtonMasks = buttonMasks;
223
224
return activatedCheatCode;
225
}
226
#endif
227
228
#if GAME_INCLUDE_EDITOR
229
void PullChain_EditorDraw(void)
230
{
231
RSDK_THIS(PullChain);
232
233
self->drawGroup = self->decorMode ? Zone->objectDrawGroup[0] : Zone->playerDrawGroup[0];
234
RSDK.SetSpriteAnimation(PullChain->aniFrames, 0, &self->hookAnimator, true, self->decorMode);
235
RSDK.SetSpriteAnimation(PullChain->aniFrames, 1, &self->chainAnimator, true, self->decorMode);
236
237
PullChain_Draw();
238
}
239
240
void PullChain_EditorLoad(void)
241
{
242
PullChain->aniFrames = RSDK.LoadSpriteAnimation("HCZ/PullChain.bin", SCOPE_STAGE);
243
244
RSDK_ACTIVE_VAR(PullChain, type);
245
RSDK_ENUM_VAR("Normal", PULLCHAIN_NORMAL);
246
}
247
#endif
248
249
void PullChain_Serialize(void)
250
{
251
RSDK_EDITABLE_VAR(PullChain, VAR_ENUM, type);
252
RSDK_EDITABLE_VAR(PullChain, VAR_BOOL, walkOnto);
253
RSDK_EDITABLE_VAR(PullChain, VAR_UINT8, tag);
254
RSDK_EDITABLE_VAR(PullChain, VAR_UINT32, length);
255
RSDK_EDITABLE_VAR(PullChain, VAR_BOOL, decorMode);
256
}
257
258