Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/MMZ/BuzzSaw.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: BuzzSaw Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectBuzzSaw *BuzzSaw;
11
12
void BuzzSaw_Update(void)
13
{
14
RSDK_THIS(BuzzSaw);
15
16
StateMachine_Run(self->state);
17
}
18
19
void BuzzSaw_LateUpdate(void) {}
20
21
void BuzzSaw_StaticUpdate(void) {}
22
23
void BuzzSaw_Draw(void)
24
{
25
RSDK_THIS(BuzzSaw);
26
27
RSDK.DrawSprite(&self->animator, &self->drawPos, false);
28
}
29
30
void BuzzSaw_Create(void *data)
31
{
32
RSDK_THIS(BuzzSaw);
33
34
self->drawFX = FX_ROTATE;
35
if (self->type == BUZZSAW_ATTACHED)
36
self->rotation = self->angle;
37
else
38
self->inkEffect = INK_ADD;
39
40
if (!SceneInfo->inEditor) {
41
RSDK.SetSpriteAnimation(BuzzSaw->aniFrames, self->type, &self->animator, true, 0);
42
43
self->active = ACTIVE_BOUNDS;
44
self->updateRange.x = (abs(self->speed * self->amplitude.x) + 0x40) << 17;
45
self->updateRange.y = (abs(self->speed * self->amplitude.y) + 0x40) << 17;
46
self->amplitude.x >>= 10;
47
self->amplitude.y >>= 10;
48
self->visible = true;
49
self->drawGroup = Zone->objectDrawGroup[0];
50
self->startPos = self->position;
51
52
if (self->type == BUZZSAW_ATTACHED)
53
self->state = BuzzSaw_State_Attached;
54
else
55
self->state = BuzzSaw_State_Stray_Waiting;
56
}
57
}
58
59
void BuzzSaw_StageLoad(void)
60
{
61
BuzzSaw->aniFrames = RSDK.LoadSpriteAnimation("MMZ/BuzzSaw.bin", SCOPE_STAGE);
62
63
BuzzSaw->unused1.x = 0x200000;
64
BuzzSaw->unused1.y = 0x200000;
65
66
BuzzSaw->hitbox.left = -24;
67
BuzzSaw->hitbox.top = -24;
68
BuzzSaw->hitbox.right = 24;
69
BuzzSaw->hitbox.bottom = 24;
70
71
// ඞ
72
Soundboard_LoadSfx("MMZ/SawSus.wav", true, BuzzSaw_SfxCheck_SawSus, BuzzSaw_SfxUpdate_SawSus);
73
}
74
75
bool32 BuzzSaw_SfxCheck_SawSus(void)
76
{
77
int32 worldX = (ScreenInfo->position.x + ScreenInfo->center.x) << 16;
78
int32 worldY = (ScreenInfo->position.y + ScreenInfo->center.y) << 16;
79
80
int32 count = 0;
81
82
foreach_all(BuzzSaw, saw)
83
{
84
if (MathHelpers_Distance(saw->position.x, saw->position.y, worldX, worldY) <= (640 << 16))
85
count++;
86
}
87
88
return count > 0;
89
}
90
91
void BuzzSaw_SfxUpdate_SawSus(int32 sfx)
92
{
93
int32 dist = 0x7FFF0000;
94
int32 worldX = (ScreenInfo->position.x + ScreenInfo->center.x) << 16;
95
int32 worldY = (ScreenInfo->position.y + ScreenInfo->center.y) << 16;
96
97
foreach_all(BuzzSaw, saw) { dist = MIN(MathHelpers_Distance(saw->position.x, saw->position.y, worldX, worldY), dist); }
98
99
RSDK.SetChannelAttributes(Soundboard->sfxChannel[sfx], 1.0 - (MIN(dist >> 16, 640) / 640.0), 0.0, 1.0);
100
}
101
102
void BuzzSaw_CheckPlayerCollisions(void)
103
{
104
RSDK_THIS(BuzzSaw);
105
106
self->position.x = self->drawPos.x;
107
self->position.y = self->drawPos.y;
108
109
foreach_active(Player, player)
110
{
111
if (Player_CheckCollisionTouch(player, self, &BuzzSaw->hitbox)) {
112
#if MANIA_USE_PLUS
113
if (!Player_CheckMightyUnspin(player, 0x600, false, &player->uncurlTimer))
114
#endif
115
Player_Hurt(player, self);
116
}
117
}
118
119
self->position.x = self->startPos.x;
120
self->position.y = self->startPos.y;
121
}
122
123
void BuzzSaw_State_Attached(void)
124
{
125
RSDK_THIS(BuzzSaw);
126
127
self->drawPos.x = self->startPos.x + self->amplitude.x * RSDK.Sin1024(self->speed * Zone->timer);
128
self->drawPos.y = self->startPos.y + self->amplitude.y * RSDK.Sin1024(self->speed * Zone->timer);
129
130
RSDK.ProcessAnimation(&self->animator);
131
132
BuzzSaw_CheckPlayerCollisions();
133
}
134
135
void BuzzSaw_State_Stray_Waiting(void)
136
{
137
RSDK_THIS(BuzzSaw);
138
139
self->drawPos.x = self->position.x;
140
self->drawPos.y = self->position.y;
141
142
foreach_active(Player, player)
143
{
144
int32 angle = RSDK.ATan2((player->position.x - self->position.x) >> 16, (player->position.y - self->position.y) >> 16);
145
146
int32 rx = (abs(player->position.x - self->position.x) >> 16) * (abs(player->position.x - self->position.x) >> 16);
147
int32 ry = (abs(player->position.y - self->position.y) >> 16) * (abs(player->position.y - self->position.y) >> 16);
148
if (((angle + 0x20 - (self->angle & 0xFF)) & 0xFF) < 0x40 && (uint32)((rx + ry) - 0x4000) < 0x5000) {
149
self->active = ACTIVE_NORMAL;
150
self->velocity.x = 0x600 * RSDK.Cos256(self->angle);
151
self->velocity.y = 0x600 * RSDK.Sin256(self->angle);
152
self->state = BuzzSaw_State_Stray_Released;
153
}
154
}
155
}
156
157
void BuzzSaw_State_Stray_Released(void)
158
{
159
RSDK_THIS(BuzzSaw);
160
161
if (self->alpha < 0x100)
162
self->alpha += 0x10;
163
164
self->drawPos.x += self->velocity.x;
165
self->drawPos.y += self->velocity.y;
166
167
RSDK.ProcessAnimation(&self->animator);
168
169
BuzzSaw_CheckPlayerCollisions();
170
171
self->position.x = self->drawPos.x;
172
self->position.y = self->drawPos.y;
173
174
if (!RSDK.CheckOnScreen(self, &self->updateRange)) {
175
self->position = self->startPos;
176
self->drawPos = self->startPos;
177
self->alpha = 0x00;
178
self->state = BuzzSaw_State_FreeMove_Reset;
179
}
180
181
self->position.x = self->startPos.x;
182
self->position.y = self->startPos.y;
183
}
184
185
void BuzzSaw_State_FreeMove_Reset(void)
186
{
187
RSDK_THIS(BuzzSaw);
188
189
if (!RSDK.CheckOnScreen(self, &self->updateRange)) {
190
self->state = BuzzSaw_State_Stray_Waiting;
191
BuzzSaw_Create(NULL);
192
}
193
}
194
195
#if GAME_INCLUDE_EDITOR
196
void BuzzSaw_EditorDraw(void)
197
{
198
RSDK_THIS(BuzzSaw);
199
200
self->drawFX = FX_ROTATE;
201
self->inkEffect = INK_NONE;
202
self->rotation = 0;
203
204
if (self->type == BUZZSAW_ATTACHED)
205
self->rotation = self->angle;
206
else
207
self->inkEffect = INK_ADD;
208
209
RSDK.SetSpriteAnimation(BuzzSaw->aniFrames, self->type, &self->animator, true, 0);
210
self->active = ACTIVE_BOUNDS;
211
self->updateRange.x = (abs(self->speed * self->amplitude.x) + 0x40) << 17;
212
self->updateRange.y = (abs(self->speed * self->amplitude.y) + 0x40) << 17;
213
self->drawPos = self->position;
214
215
BuzzSaw_Draw();
216
217
if (showGizmos() && self->type == BUZZSAW_ATTACHED) {
218
RSDK_DRAWING_OVERLAY(true);
219
220
Vector2 pos;
221
Vector2 amplitude;
222
amplitude.x = self->amplitude.x >> 10;
223
amplitude.y = self->amplitude.y >> 10;
224
225
self->updateRange.x = (abs(self->speed * self->amplitude.x) + 0x40) << 17;
226
self->updateRange.y = (abs(self->speed * self->amplitude.y) + 0x40) << 17;
227
228
// draw distance previews
229
self->inkEffect = INK_BLEND;
230
self->drawPos.x = amplitude.x * RSDK.Sin1024(0x100) + self->position.x;
231
self->drawPos.y = amplitude.y * RSDK.Sin1024(0x100) + self->position.y;
232
pos = self->drawPos;
233
BuzzSaw_Draw();
234
235
self->drawPos.x = amplitude.x * RSDK.Sin1024(0x300) + self->position.x;
236
self->drawPos.y = amplitude.y * RSDK.Sin1024(0x300) + self->position.y;
237
BuzzSaw_Draw();
238
239
RSDK.DrawLine(pos.x, pos.y, self->drawPos.x, self->drawPos.y, 0x00FF00, 0, INK_NONE, false);
240
241
self->inkEffect = INK_NONE;
242
RSDK_DRAWING_OVERLAY(false);
243
}
244
}
245
246
void BuzzSaw_EditorLoad(void)
247
{
248
BuzzSaw->aniFrames = RSDK.LoadSpriteAnimation("MMZ/BuzzSaw.bin", SCOPE_STAGE);
249
250
RSDK_ACTIVE_VAR(BuzzSaw, type);
251
RSDK_ENUM_VAR("Attached", BUZZSAW_ATTACHED);
252
RSDK_ENUM_VAR("Stray", BUZZSAW_STRAY);
253
}
254
#endif
255
256
void BuzzSaw_Serialize(void)
257
{
258
RSDK_EDITABLE_VAR(BuzzSaw, VAR_ENUM, type);
259
RSDK_EDITABLE_VAR(BuzzSaw, VAR_INT32, angle);
260
RSDK_EDITABLE_VAR(BuzzSaw, VAR_VECTOR2, amplitude);
261
RSDK_EDITABLE_VAR(BuzzSaw, VAR_ENUM, speed);
262
}
263
264