Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/ERZ/PKingAttack.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: PKingAttack Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectPKingAttack *PKingAttack;
11
12
// NOTE:
13
// This object is likely highly based off LRZ/KingAttack
14
// hence why there's a bunch of "unused" stuff that resembles that object
15
16
void PKingAttack_Update(void)
17
{
18
RSDK_THIS(PKingAttack);
19
20
StateMachine_Run(self->state);
21
}
22
23
void PKingAttack_LateUpdate(void) {}
24
25
void PKingAttack_StaticUpdate(void) {}
26
27
void PKingAttack_Draw(void)
28
{
29
RSDK_THIS(PKingAttack);
30
31
if (self->type == PKINGATTACK_LAUNCHED)
32
RSDK.DrawCircle(self->position.x, self->position.y, 0x20, 0x00, 0xFF, INK_TINT, false);
33
34
RSDK.DrawSprite(&self->animator, NULL, false);
35
}
36
37
void PKingAttack_Create(void *data)
38
{
39
RSDK_THIS(PKingAttack);
40
41
if (!SceneInfo->inEditor) {
42
self->drawGroup = Zone->objectDrawGroup[1];
43
self->type = VOID_TO_INT(data);
44
self->active = ACTIVE_NORMAL;
45
self->updateRange.x = 0x800000;
46
self->updateRange.y = 0x800000;
47
48
switch (self->type) {
49
default: break;
50
case PKINGATTACK_LASER: break;
51
52
case PKINGATTACK_ORBIT:
53
self->drawFX = FX_SCALE;
54
self->visible = true;
55
RSDK.SetSpriteAnimation(PKingAttack->aniFrames, 10, &self->animator, true, RSDK.Rand(0, 6));
56
self->state = PKingAttack_State_OrbitAppear;
57
58
self->hitbox.left = -10;
59
self->hitbox.top = -10;
60
self->hitbox.right = 10;
61
self->hitbox.bottom = 10;
62
break;
63
64
case PKINGATTACK_TRAIL:
65
self->drawGroup = Zone->objectDrawGroup[0];
66
self->visible = true;
67
self->inkEffect = INK_ADD;
68
self->alpha = 0xC0;
69
RSDK.SetSpriteAnimation(PKingAttack->aniFrames, 12, &self->animator, true, 0);
70
self->state = PKingAttack_State_Trail;
71
break;
72
73
case PKINGATTACK_LARGEBULLET: break;
74
case PKINGATTACK_ENERGYLINE: break;
75
76
case PKINGATTACK_SMALLBULLET:
77
self->drawGroup = Zone->objectDrawGroup[0];
78
self->drawFX = FX_ROTATE;
79
self->visible = true;
80
RSDK.SetSpriteAnimation(PKingAttack->aniFrames, 11, &self->animator, true, 0);
81
self->state = PKingAttack_State_SmallBullet;
82
83
self->hitbox.left = -4;
84
self->hitbox.top = -4;
85
self->hitbox.right = 4;
86
self->hitbox.bottom = 4;
87
break;
88
}
89
}
90
}
91
92
void PKingAttack_StageLoad(void)
93
{
94
PKingAttack->aniFrames = RSDK.LoadSpriteAnimation("Phantom/PhantomKing.bin", SCOPE_STAGE);
95
96
PKingAttack->sfxPulse = RSDK.GetSfx("Stage/ElecPulse.wav");
97
}
98
99
void PKingAttack_CheckPlayerCollisions(void)
100
{
101
RSDK_THIS(PKingAttack);
102
103
foreach_active(Player, player)
104
{
105
if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {
106
if (player->superState == SUPERSTATE_SUPER) {
107
if (!player->blinkTimer) {
108
int32 angle = RSDK.ATan2(player->position.x - self->position.x, player->position.y - self->position.y);
109
110
if (self->state == PKingAttack_State_OrbitLaunched) {
111
player->blinkTimer = 120;
112
Ring_LoseRings(player, MIN(player->rings, 8), player->collisionPlane);
113
player->rings -= MIN(player->rings, 8);
114
RSDK.PlaySfx(Player->sfxLoseRings, false, 255);
115
}
116
else {
117
RSDK.PlaySfx(PKingAttack->sfxPulse, false, 255);
118
destroyEntity(self);
119
}
120
121
player->rotation = 0;
122
player->velocity.x = RSDK.Cos256(angle) << 10;
123
player->velocity.y = RSDK.Sin256(angle) << 10;
124
player->groundVel = player->velocity.x;
125
player->state = ERZStart_State_PlayerRebound;
126
}
127
}
128
else {
129
Player_Hurt(player, self);
130
}
131
}
132
}
133
}
134
135
void PKingAttack_State_OrbitAppear(void)
136
{
137
RSDK_THIS(PKingAttack);
138
139
RSDK.ProcessAnimation(&self->animator);
140
141
self->angle = (self->angle + 12) & 0x3FF;
142
143
if (self->scale.x < 0x200) {
144
self->scale.x += 0x20;
145
self->scale.y = self->scale.x;
146
}
147
148
self->velocity.x = self->position.x;
149
self->velocity.y = self->position.y;
150
151
self->position.x = (RSDK.Cos1024(self->angle) << 12) + self->target->position.x;
152
self->position.y = (RSDK.Sin1024(self->angle) << 12) + self->target->position.y;
153
154
self->velocity.x = self->position.x - self->velocity.x;
155
self->velocity.y = self->position.y - self->velocity.y;
156
157
PKingAttack_CheckPlayerCollisions();
158
159
if (++self->timer == 120) {
160
self->timer = 0;
161
self->targetPos.x = self->target->position.x;
162
self->targetPos.y = self->target->position.y;
163
self->state = PKingAttack_State_Orbiting;
164
}
165
}
166
167
void PKingAttack_State_Orbiting(void)
168
{
169
RSDK_THIS(PKingAttack);
170
171
RSDK.ProcessAnimation(&self->animator);
172
173
self->position.x += self->target->position.x - self->targetPos.x;
174
self->position.y += self->target->position.y - self->targetPos.y;
175
176
if (self->position.x <= self->target->position.x) {
177
if (self->position.x < self->target->position.x)
178
self->velocity.x += 0x4000;
179
}
180
else {
181
self->velocity.x -= 0x4000;
182
}
183
184
if (self->position.y <= self->target->position.y) {
185
if (self->position.y < self->target->position.y)
186
self->velocity.y += 0x3800;
187
}
188
else {
189
self->velocity.y -= 0x3800;
190
}
191
192
self->velocity.x = CLAMP(self->velocity.x, -0x50000, 0x50000);
193
self->velocity.y = CLAMP(self->velocity.y, -0x50000, 0x50000);
194
195
self->position.x += self->velocity.x;
196
self->position.y += self->velocity.y;
197
self->targetPos.x = self->target->position.x;
198
self->targetPos.y = self->target->position.y;
199
200
self->angle = (self->angle + 12) & 0x3FF;
201
int32 inc = (384 - self->scale.x - (RSDK.Sin1024(self->angle) >> 3)) >> 3;
202
203
self->scale.x += inc;
204
self->scale.y = self->scale.x;
205
PKingAttack_CheckPlayerCollisions();
206
207
if (self->angle < 0x200)
208
self->drawGroup = Zone->objectDrawGroup[0] - 1;
209
else
210
self->drawGroup = Zone->objectDrawGroup[0];
211
}
212
213
void PKingAttack_State_OrbitLaunched(void)
214
{
215
RSDK_THIS(PKingAttack);
216
217
RSDK.ProcessAnimation(&self->animator);
218
219
++self->timer;
220
if (!(self->timer & 3))
221
CREATE_ENTITY(PKingAttack, INT_TO_VOID(PKINGATTACK_TRAIL), self->position.x, self->position.y);
222
223
if (self->scale.x < 512) {
224
self->scale.x += 0x20;
225
self->scale.y = self->scale.x;
226
}
227
228
self->velocity.x = self->velocity.x + ((self->targetVelocity.x - self->velocity.x) >> 3);
229
self->velocity.y = self->velocity.y + ((self->targetVelocity.y - self->velocity.y) >> 3);
230
self->position.x += self->velocity.x;
231
self->position.y += self->velocity.y;
232
233
PKingAttack_CheckPlayerCollisions();
234
235
if (!RSDK.CheckOnScreen(self, NULL))
236
destroyEntity(self);
237
}
238
239
void PKingAttack_State_Trail(void)
240
{
241
RSDK_THIS(PKingAttack);
242
243
if (self->timer >= 8) {
244
self->alpha -= 8;
245
if (self->alpha <= 0)
246
destroyEntity(self);
247
}
248
else {
249
self->timer++;
250
}
251
}
252
253
void PKingAttack_State_SmallBullet(void)
254
{
255
RSDK_THIS(PKingAttack);
256
257
RSDK.ProcessAnimation(&self->animator);
258
259
self->rotation = (self->rotation + 16) & 0x1FF;
260
self->position.x += self->velocity.x;
261
self->position.y += self->velocity.y;
262
263
PKingAttack_CheckPlayerCollisions();
264
265
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x40000, true)) {
266
self->position.y += 0x40000;
267
destroyEntity(self);
268
}
269
270
if (!RSDK.CheckOnScreen(self, NULL))
271
destroyEntity(self);
272
}
273
274
#if GAME_INCLUDE_EDITOR
275
void PKingAttack_EditorDraw(void)
276
{
277
RSDK_THIS(PKingAttack);
278
279
self->type = PKINGATTACK_ORBIT;
280
self->inkEffect = INK_ADD;
281
self->alpha = 0xC0;
282
RSDK.SetSpriteAnimation(PKingAttack->aniFrames, 12, &self->animator, true, 0);
283
284
PKingAttack_Draw();
285
}
286
287
void PKingAttack_EditorLoad(void) { PKingAttack->aniFrames = RSDK.LoadSpriteAnimation("Phantom/PhantomKing.bin", SCOPE_STAGE); }
288
#endif
289
290
void PKingAttack_Serialize(void) {}
291
292