Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/UFO/UFO_Ring.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: UFO_Ring Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectUFO_Ring *UFO_Ring;
11
12
void UFO_Ring_Update(void)
13
{
14
RSDK_THIS(UFO_Ring);
15
StateMachine_Run(self->state);
16
}
17
18
void UFO_Ring_LateUpdate(void)
19
{
20
RSDK_THIS(UFO_Ring);
21
22
int32 x = self->position.x >> 8;
23
int32 y = self->height >> 8;
24
int32 z = self->position.y >> 8;
25
26
Matrix *m = &UFO_Camera->matWorld;
27
28
self->worldX = m->values[0][3] + (y * m->values[0][1] >> 8) + (z * m->values[0][2] >> 8) + (x * m->values[0][0] >> 8);
29
self->worldY = m->values[1][3] + (y * m->values[1][1] >> 8) + (z * m->values[1][2] >> 8) + (x * m->values[1][0] >> 8);
30
self->zdepth = m->values[2][3] + (y * m->values[2][1] >> 8) + (z * m->values[2][2] >> 8) + (x * m->values[2][0] >> 8);
31
}
32
33
void UFO_Ring_StaticUpdate(void) {}
34
35
void UFO_Ring_Draw(void)
36
{
37
RSDK_THIS(UFO_Ring);
38
39
if (self->zdepth >= 0x100) {
40
self->direction = self->animator.frameID > 8;
41
42
Vector2 drawPos;
43
drawPos.x = (ScreenInfo->center.x + (self->worldX << 8) / self->zdepth) << 16;
44
drawPos.y = (ScreenInfo->center.y - (self->worldY << 8) / self->zdepth) << 16;
45
46
self->scale.x = 0x1000000 / self->zdepth;
47
self->scale.y = 0x1000000 / self->zdepth;
48
if (self->state == UFO_Ring_State_NormalRing)
49
self->animator.frameID = UFO_Setup->ringFrame;
50
51
RSDK.DrawSprite(&self->animator, &drawPos, true);
52
}
53
}
54
55
void UFO_Ring_Create(void *data)
56
{
57
RSDK_THIS(UFO_Ring);
58
59
if (!SceneInfo->inEditor) {
60
self->visible = true;
61
self->drawFX = FX_FLIP | FX_SCALE;
62
self->drawGroup = 4;
63
self->active = ACTIVE_RBOUNDS;
64
self->updateRange.x = 0x400;
65
self->updateRange.y = 0x400;
66
67
if (!self->height)
68
self->height = 12;
69
self->height <<= 16;
70
71
self->state = UFO_Ring_State_NormalRing;
72
73
RSDK.SetSpriteAnimation(UFO_Ring->aniFrames, 1, &self->animator, true, 0);
74
}
75
}
76
77
void UFO_Ring_StageLoad(void)
78
{
79
UFO_Ring->aniFrames = RSDK.LoadSpriteAnimation("Global/Ring.bin", SCOPE_STAGE);
80
81
UFO_Ring->sfxRing = RSDK.GetSfx("Global/Ring.wav");
82
}
83
84
void UFO_Ring_PlayRingSfx(void)
85
{
86
if (UFO_Setup->rings < 999)
87
UFO_Setup->rings++;
88
89
if (UFO_Setup->ringPan) {
90
int32 channel = RSDK.PlaySfx(UFO_Ring->sfxRing, false, 0xFF);
91
RSDK.SetChannelAttributes(channel, 1.0, -1.0, 1.0);
92
UFO_Setup->ringPan = 0;
93
}
94
else {
95
int32 channel = RSDK.PlaySfx(UFO_Ring->sfxRing, false, 0xFF);
96
RSDK.SetChannelAttributes(channel, 1.0, 1.0, 1.0);
97
UFO_Setup->ringPan = 1;
98
}
99
}
100
101
void UFO_Ring_LoseRings(EntityUFO_Player *player)
102
{
103
int32 ringCount = CLAMP(UFO_Setup->rings, 0, 10);
104
105
UFO_Setup->rings -= 10;
106
if (UFO_Setup->rings < 0)
107
UFO_Setup->rings = 0;
108
109
for (int32 r = 0; r < ringCount; ++r) {
110
EntityUFO_Ring *ring = CREATE_ENTITY(UFO_Ring, NULL, player->position.x, player->position.y);
111
112
ring->height = player->height + 0x80000;
113
ring->velocity.x = player->velocity.x + RSDK.Rand(-0x40000, 0x40000);
114
ring->velocity.y = player->velocity.y + RSDK.Rand(-0x40000, 0x40000);
115
ring->bounceVelocity = RSDK.Rand(0x40000, 0x60000);
116
ring->inkEffect = INK_ALPHA;
117
ring->alpha = 0x200;
118
ring->animator.speed = 0x100;
119
ring->state = UFO_Ring_State_LoseRing;
120
}
121
}
122
123
void UFO_Ring_State_NormalRing(void)
124
{
125
RSDK_THIS(UFO_Ring);
126
127
foreach_active(UFO_Player, player)
128
{
129
int32 rx = (self->position.x - player->position.x) >> 16;
130
int32 ry = (self->height - player->height - 0xA0000) >> 16;
131
int32 rz = (self->position.y - player->position.y) >> 16;
132
133
if (rx * rx + ry * ry + rz * rz < UFO_Player->maxSpeed >> 9) {
134
RSDK.SetSpriteAnimation(UFO_Ring->aniFrames, 2, &self->animator, true, 4);
135
++self->drawGroup;
136
self->state = UFO_Ring_State_Sparkle;
137
UFO_Ring_PlayRingSfx();
138
}
139
}
140
}
141
142
void UFO_Ring_State_Sparkle(void)
143
{
144
RSDK_THIS(UFO_Ring);
145
146
RSDK.ProcessAnimation(&self->animator);
147
148
if (self->animator.frameID == self->animator.frameCount - 1)
149
destroyEntity(self);
150
}
151
152
void UFO_Ring_State_LoseRing(void)
153
{
154
RSDK_THIS(UFO_Ring);
155
156
RSDK.ProcessAnimation(&self->animator);
157
158
self->position.x += self->velocity.x;
159
self->position.y += self->velocity.y;
160
self->bounceVelocity -= 0x3800;
161
162
self->height += self->bounceVelocity;
163
if (self->height < 0xC0000 && self->bounceVelocity < 0) {
164
self->height = 0xC0000;
165
self->bounceVelocity = -(self->bounceVelocity >> 1);
166
}
167
168
if (self->animator.speed > 0x40)
169
self->animator.speed--;
170
171
self->alpha -= 4;
172
if (!self->alpha)
173
destroyEntity(self);
174
}
175
176
#if GAME_INCLUDE_EDITOR
177
void UFO_Ring_EditorDraw(void)
178
{
179
RSDK_THIS(UFO_Ring);
180
181
RSDK.SetSpriteAnimation(UFO_Ring->aniFrames, 0, &self->animator, true, 0);
182
RSDK.DrawSprite(&self->animator, NULL, false);
183
}
184
185
void UFO_Ring_EditorLoad(void) { UFO_Ring->aniFrames = RSDK.LoadSpriteAnimation("Global/Ring.bin", SCOPE_STAGE); }
186
#endif
187
188
void UFO_Ring_Serialize(void) { RSDK_EDITABLE_VAR(UFO_Ring, VAR_ENUM, height); }
189
190