Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/UFO/UFO_Player.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: UFO_Player Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectUFO_Player *UFO_Player;
11
12
void UFO_Player_Update(void)
13
{
14
RSDK_THIS(UFO_Player);
15
16
StateMachine_Run(self->stateInput);
17
StateMachine_Run(self->state);
18
19
RSDK.ProcessAnimation(&self->animator);
20
if (UFO_Setup->timedOut)
21
self->groundVel -= self->groundVel >> 5;
22
}
23
24
void UFO_Player_LateUpdate(void)
25
{
26
RSDK_THIS(UFO_Player);
27
Matrix *mat = &UFO_Camera->matWorld;
28
29
int32 x = self->position.x >> 16;
30
int32 y = self->height >> 16;
31
int32 z = self->position.y >> 16;
32
33
self->zdepth = mat->values[2][3] + mat->values[2][0] * x + mat->values[2][1] * y + mat->values[2][2] * z;
34
}
35
36
void UFO_Player_StaticUpdate(void) {}
37
38
void UFO_Player_Draw(void)
39
{
40
RSDK_THIS(UFO_Player);
41
42
if (self->zdepth >= 1) {
43
RSDK.Prepare3DScene(UFO_Player->sceneIndex);
44
45
int32 anim = self->animator.animationID;
46
if (anim == 2 || anim == 3) {
47
RSDK.MatrixTranslateXYZ(&self->matTransform, self->position.x, self->height + 0x100000, self->position.y, true);
48
49
RSDK.MatrixRotateX(&self->matRotate, self->angleX);
50
RSDK.MatrixRotateY(&self->matWorld, self->angle + (self->angleZ >> 5));
51
52
RSDK.MatrixMultiply(&self->matNormal, &self->matRotate, &self->matWorld);
53
RSDK.MatrixMultiply(&self->matWorld, &self->matNormal, &self->matTransform);
54
RSDK.MatrixMultiply(&self->matWorld, &self->matWorld, &UFO_Camera->matWorld);
55
RSDK.MatrixMultiply(&self->matNormal, &self->matNormal, &UFO_Camera->matView);
56
57
RSDK.AddModelTo3DScene(self->animator.animationID, UFO_Player->sceneIndex, S3D_SOLIDCOLOR_SHADED_BLENDED_SCREEN, &self->matWorld,
58
&self->matNormal, 0xFFFFFF);
59
}
60
else {
61
RSDK.MatrixTranslateXYZ(&self->matTransform, self->position.x, self->height, self->position.y, true);
62
63
RSDK.MatrixRotateZ(&self->matRotate, self->angleZ >> 5);
64
RSDK.MatrixRotateY(&self->matWorld, self->angle + (self->angleZ >> (6 - (uint8)(UFO_Setup->machLevel))));
65
66
RSDK.MatrixMultiply(&self->matNormal, &self->matRotate, &self->matWorld);
67
RSDK.MatrixMultiply(&self->matWorld, &self->matNormal, &self->matTransform);
68
RSDK.MatrixMultiply(&self->matWorld, &self->matWorld, &UFO_Camera->matWorld);
69
RSDK.MatrixRotateXYZ(&self->matNormal, 0, self->angle, 0);
70
RSDK.MatrixMultiply(&self->matNormal, &self->matNormal, &UFO_Camera->matView);
71
72
RSDK.AddMeshFrameTo3DScene(self->animator.animationID, UFO_Player->sceneIndex, &self->animator, S3D_SOLIDCOLOR_SHADED_BLENDED_SCREEN,
73
&self->matWorld, &self->matNormal, 0xFFFFFF);
74
}
75
76
RSDK.Draw3DScene(UFO_Player->sceneIndex);
77
}
78
}
79
80
void UFO_Player_Create(void *data)
81
{
82
RSDK_THIS(UFO_Player);
83
84
if (!SceneInfo->inEditor) {
85
self->active = ACTIVE_NORMAL;
86
self->visible = true;
87
self->updateRange.x = 0x800000;
88
self->updateRange.y = 0x800000;
89
self->drawFX = FX_FLIP;
90
self->drawGroup = 4;
91
92
if (!self->machQuota1)
93
self->machQuota1 = 32;
94
95
if (!self->machQuota2)
96
self->machQuota2 = 32;
97
98
if (!self->machQuota3)
99
self->machQuota3 = 32;
100
101
if (self->startingRings > 0)
102
UFO_Setup->rings = self->startingRings;
103
104
UFO_Setup->machQuotas[0] = self->machQuota1;
105
UFO_Setup->machQuotas[1] = self->machQuota2;
106
UFO_Setup->machQuotas[2] = self->machQuota3;
107
self->angle = 0x200;
108
self->onGround = true;
109
110
UFO_Player_ChangeMachState();
111
self->stateInput = UFO_Player_Input_P1;
112
self->controllerID = INPUT_NONE;
113
self->state = UFO_Player_State_Run;
114
115
RSDK.SetModelAnimation(UFO_Player->jogModel, &self->animator, 128, 0, true, 0);
116
}
117
}
118
119
void UFO_Player_StageLoad(void)
120
{
121
if (globals->playerID == ID_NONE)
122
globals->playerID = ID_DEFAULT_PLAYER;
123
124
switch (GET_CHARACTER_ID(1)) {
125
default:
126
case ID_SONIC:
127
UFO_Player->jogModel = RSDK.LoadMesh("Special/SonicJog.bin", SCOPE_STAGE);
128
UFO_Player->dashModel = RSDK.LoadMesh("Special/SonicDash.bin", SCOPE_STAGE);
129
UFO_Player->jumpModel = RSDK.LoadMesh("Special/SonicJump.bin", SCOPE_STAGE);
130
UFO_Player->ballModel = RSDK.LoadMesh("Special/SonicBall.bin", SCOPE_STAGE);
131
UFO_Player->tumbleModel = RSDK.LoadMesh("Special/SonicTumble.bin", SCOPE_STAGE);
132
break;
133
134
case ID_TAILS:
135
UFO_Player->jogModel = RSDK.LoadMesh("Special/TailsJog.bin", SCOPE_STAGE);
136
UFO_Player->dashModel = RSDK.LoadMesh("Special/TailsDash.bin", SCOPE_STAGE);
137
UFO_Player->jumpModel = RSDK.LoadMesh("Special/TailsJump.bin", SCOPE_STAGE);
138
UFO_Player->ballModel = RSDK.LoadMesh("Special/TailsBall.bin", SCOPE_STAGE);
139
UFO_Player->tumbleModel = RSDK.LoadMesh("Special/TailsTumble.bin", SCOPE_STAGE);
140
break;
141
142
case ID_KNUCKLES:
143
UFO_Player->jogModel = RSDK.LoadMesh("Special/KnuxJog.bin", SCOPE_STAGE);
144
UFO_Player->dashModel = RSDK.LoadMesh("Special/KnuxDash.bin", SCOPE_STAGE);
145
UFO_Player->jumpModel = RSDK.LoadMesh("Special/KnuxJump.bin", SCOPE_STAGE);
146
UFO_Player->ballModel = RSDK.LoadMesh("Special/KnuxBall.bin", SCOPE_STAGE);
147
UFO_Player->tumbleModel = RSDK.LoadMesh("Special/KnuxTumble.bin", SCOPE_STAGE);
148
break;
149
150
#if MANIA_USE_PLUS
151
case ID_MIGHTY:
152
UFO_Player->jogModel = RSDK.LoadMesh("Special/MightyJog.bin", SCOPE_STAGE);
153
UFO_Player->dashModel = RSDK.LoadMesh("Special/MightyDash.bin", SCOPE_STAGE);
154
UFO_Player->jumpModel = RSDK.LoadMesh("Special/MightyJump.bin", SCOPE_STAGE);
155
UFO_Player->ballModel = RSDK.LoadMesh("Special/MightyBall.bin", SCOPE_STAGE);
156
UFO_Player->tumbleModel = RSDK.LoadMesh("Special/MightyTumble.bin", SCOPE_STAGE);
157
break;
158
159
case ID_RAY:
160
UFO_Player->jogModel = RSDK.LoadMesh("Special/RayJog.bin", SCOPE_STAGE);
161
UFO_Player->dashModel = RSDK.LoadMesh("Special/RayDash.bin", SCOPE_STAGE);
162
UFO_Player->jumpModel = RSDK.LoadMesh("Special/RayJump.bin", SCOPE_STAGE);
163
UFO_Player->ballModel = RSDK.LoadMesh("Special/RayBall.bin", SCOPE_STAGE);
164
UFO_Player->tumbleModel = RSDK.LoadMesh("Special/RayTumble.bin", SCOPE_STAGE);
165
break;
166
#endif
167
}
168
169
UFO_Player->sceneIndex = RSDK.Create3DScene("View:Special", 4096, SCOPE_STAGE);
170
171
RSDK.SetDiffuseColor(UFO_Player->sceneIndex, 0xA0, 0xA0, 0xA0);
172
RSDK.SetDiffuseIntensity(UFO_Player->sceneIndex, 8, 8, 8);
173
RSDK.SetSpecularIntensity(UFO_Player->sceneIndex, 15, 15, 15);
174
175
foreach_all(UFO_Player, player)
176
{
177
EntityUFO_Player *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, UFO_Player);
178
RSDK.CopyEntity(player1, player, true);
179
}
180
181
UFO_Player->sfxJump = RSDK.GetSfx("Global/Jump.wav");
182
UFO_Player->sfxCharge = RSDK.GetSfx("Global/Charge.wav");
183
UFO_Player->sfxRelease = RSDK.GetSfx("Global/Release.wav");
184
UFO_Player->sfxLoseRings = RSDK.GetSfx("Global/LoseRings.wav");
185
UFO_Player->sfxDrop = RSDK.GetSfx("Stage/Drop.wav");
186
UFO_Player->sfxBumper = RSDK.GetSfx("Stage/Bumper.wav");
187
UFO_Player->sfxSpring = RSDK.GetSfx("Global/Spring.wav");
188
UFO_Player->sfxSkid = RSDK.GetSfx("Special/Skid.wav");
189
UFO_Player->sfxGrittyGround = RSDK.GetSfx("Special/GrittyGround.wav");
190
191
EntityUFO_Player *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, UFO_Player);
192
RSDK.ClearCameras();
193
RSDK.AddCamera(&player1->position, 0x100000, 0x100000, true);
194
}
195
196
void UFO_Player_Input_P1(void)
197
{
198
RSDK_THIS(UFO_Player);
199
200
if (self->controllerID < PLAYER_COUNT) {
201
RSDKControllerState *controller = &ControllerInfo[self->controllerID];
202
RSDKAnalogState *stick = &AnalogStickInfoL[self->controllerID];
203
204
self->up = controller->keyUp.down;
205
self->down = controller->keyDown.down;
206
self->left = controller->keyLeft.down;
207
self->right = controller->keyRight.down;
208
209
self->up |= stick->keyUp.down;
210
self->down |= stick->keyDown.down;
211
self->left |= stick->keyLeft.down;
212
self->right |= stick->keyRight.down;
213
214
#if MANIA_USE_PLUS
215
self->up |= stick->vDelta > 0.3;
216
self->down |= stick->vDelta < -0.3;
217
self->left |= stick->hDelta < -0.3;
218
self->right |= stick->hDelta > 0.3;
219
#else
220
self->up |= stick->vDeltaL > 0.3;
221
self->down |= stick->vDeltaL < -0.3;
222
self->left |= stick->hDeltaL < -0.3;
223
self->right |= stick->hDeltaL > 0.3;
224
#endif
225
226
if (self->left && self->right) {
227
self->left = false;
228
self->right = false;
229
}
230
231
self->jumpPress = controller->keyA.press || controller->keyB.press || controller->keyC.press || controller->keyX.press;
232
self->jumpHold = controller->keyA.down || controller->keyB.down || controller->keyC.down || controller->keyX.down;
233
234
if ((controller->keyStart.press || Unknown_pausePress) && SceneInfo->state == ENGINESTATE_REGULAR) {
235
EntityPauseMenu *pauseMenu = RSDK_GET_ENTITY(SLOT_PAUSEMENU, PauseMenu);
236
if (!pauseMenu->classID) {
237
RSDK.ResetEntitySlot(SLOT_PAUSEMENU, PauseMenu->classID, NULL);
238
pauseMenu->triggerPlayer = RSDK.GetEntitySlot(self);
239
pauseMenu->disableRestart = true;
240
}
241
}
242
}
243
}
244
245
void UFO_Player_ChangeMachState(void)
246
{
247
RSDK_THIS(UFO_Player);
248
249
switch (UFO_Setup->machLevel) {
250
default: break;
251
252
case 0:
253
UFO_Player->maxSpeed = 0x70000;
254
self->velDivisor = 16;
255
self->angleVel = 128;
256
break;
257
258
case 1:
259
UFO_Player->maxSpeed = 0xA0000;
260
self->velDivisor = 18;
261
self->angleVel = 144;
262
break;
263
264
case 2:
265
UFO_Player->maxSpeed = 0xE0000;
266
self->velDivisor = 20;
267
self->angleVel = 160;
268
break;
269
}
270
}
271
272
void UFO_Player_HandleBumperTiles(void)
273
{
274
RSDK_THIS(UFO_Player);
275
276
int32 bumpDirMasks = 0;
277
278
uint16 tile = RSDK.GetTile(UFO_Setup->playFieldLayer, (self->position.x - 0x80000) >> 20, (self->position.y - 0x80000) >> 20);
279
if (RSDK.GetTileFlags(tile, 0) == UFO_TFLAGS_BUMPER)
280
bumpDirMasks = 0b0001;
281
282
tile = RSDK.GetTile(UFO_Setup->playFieldLayer, (self->position.x + 0x80000) >> 20, (self->position.y - 0x80000) >> 20);
283
if (RSDK.GetTileFlags(tile, 0) == UFO_TFLAGS_BUMPER)
284
bumpDirMasks |= 0b0010;
285
286
tile = RSDK.GetTile(UFO_Setup->playFieldLayer, (self->position.x - 0x80000) >> 20, (self->position.y + 0x80000) >> 20);
287
if (RSDK.GetTileFlags(tile, 0) == UFO_TFLAGS_BUMPER)
288
bumpDirMasks |= 0b0100;
289
290
tile = RSDK.GetTile(UFO_Setup->playFieldLayer, (self->position.x + 0x80000) >> 20, (self->position.y + 0x80000) >> 20);
291
if (RSDK.GetTileFlags(tile, 0) == UFO_TFLAGS_BUMPER)
292
bumpDirMasks |= 0b1000;
293
294
if (bumpDirMasks) {
295
if (!self->bumperTimer)
296
RSDK.PlaySfx(UFO_Player->sfxBumper, false, 0xFF);
297
298
self->bumperTimer = 16;
299
switch (bumpDirMasks) {
300
default:
301
case 0b0000: break;
302
303
case 0b0001:
304
case 0b0110:
305
case 0b0111:
306
self->velocity.y = 0x40000;
307
self->velocity.x = 0x40000;
308
break;
309
310
case 0b0010:
311
case 0b1001:
312
case 0b1011:
313
self->velocity.x = -0x40000;
314
self->velocity.y = 0x40000;
315
break;
316
317
case 0b0011: self->velocity.y = 0x40000; break;
318
319
case 0b0100:
320
case 0b1101:
321
self->velocity.y = -0x40000;
322
self->velocity.x = 0x40000;
323
break;
324
325
case 0b0101: self->velocity.x = 0x40000; break;
326
327
case 0b1000:
328
case 0b1110:
329
case 0b1111:
330
self->velocity.x = -0x40000;
331
self->velocity.y = -0x40000;
332
break;
333
334
case 0b1010: self->velocity.x = -0x40000; break;
335
case 0b1100: self->velocity.y = -0x40000; break;
336
}
337
}
338
}
339
340
void UFO_Player_HandleSpeedUp(void)
341
{
342
RSDK_THIS(UFO_Player);
343
344
uint16 tile = RSDK.GetTile(UFO_Setup->playFieldLayer, self->position.x >> 20, self->position.y >> 20);
345
if (tile == (uint16)-1) {
346
if (++self->courseOutTimer >= 2) {
347
self->interaction = 0;
348
self->timer = 0;
349
self->state = UFO_Player_State_CourseOut;
350
self->camera->state = UFO_Camera_State_CourseOut;
351
352
if (!UFO_Setup->timedOut)
353
RSDK.PlaySfx(UFO_Player->sfxDrop, false, 0xFF);
354
355
return;
356
}
357
}
358
else {
359
self->courseOutTimer = 0;
360
}
361
362
if (self->bumperTimer <= 0) {
363
if (RSDK.GetTileFlags(tile, 0) == UFO_TFLAGS_GRITTYGROUND) {
364
if (self->groundVel > UFO_Player->maxSpeed - (UFO_Player->maxSpeed >> 2))
365
self->groundVel = self->groundVel - (self->groundVel >> 5);
366
367
if (!(UFO_Setup->timer & 3)) {
368
CREATE_ENTITY(UFO_Dust, NULL, self->position.x, self->position.y);
369
RSDK.PlaySfx(UFO_Player->sfxGrittyGround, false, 255);
370
}
371
}
372
else {
373
if (self->groundVel > UFO_Player->maxSpeed) {
374
self->groundVel -= 0x4000;
375
376
if (self->groundVel < UFO_Player->maxSpeed)
377
self->groundVel = UFO_Player->maxSpeed;
378
}
379
else if (self->groundVel < UFO_Player->maxSpeed) {
380
self->groundVel += 0x4000;
381
382
if (self->groundVel > UFO_Player->maxSpeed)
383
self->groundVel = UFO_Player->maxSpeed;
384
}
385
}
386
}
387
}
388
389
void UFO_Player_State_Run(void)
390
{
391
RSDK_THIS(UFO_Player);
392
393
int32 turnSpeed = UFO_Player->maxSpeed - 0x87000;
394
395
if (self->right) {
396
if (self->angleZ < (turnSpeed >> 11) + 1280)
397
self->angleZ += (turnSpeed >> 14) + self->angleVel;
398
}
399
else if (self->left) {
400
if (self->angleZ > -1280 - (turnSpeed >> 11))
401
self->angleZ -= self->angleVel - (turnSpeed >> 14);
402
}
403
else {
404
self->angleZ -= self->angleZ >> 2;
405
}
406
407
if (self->angleZ <= 0)
408
self->angle -= -self->angleZ >> 8;
409
else
410
self->angle += self->angleZ >> 8;
411
412
self->angle &= 0x3FF;
413
414
if (abs(self->angleZ) <= 1280 || UFO_Setup->machLevel <= 1) {
415
self->skidTimer = 0;
416
}
417
else {
418
if (self->skidTimer >= 16) {
419
if (!(UFO_Setup->timer & 3))
420
CREATE_ENTITY(UFO_Dust, NULL, self->position.x, self->position.y);
421
422
if (!(UFO_Setup->timer & 7))
423
RSDK.PlaySfx(UFO_Player->sfxSkid, false, 255);
424
}
425
else {
426
self->skidTimer++;
427
}
428
}
429
430
if (self->bumperTimer >= 1) {
431
self->bumperTimer--;
432
UFO_Player_HandleSpeedUp();
433
}
434
else {
435
UFO_Player_HandleSpeedUp();
436
437
int32 x = (self->groundVel >> 10) * RSDK.Sin1024(self->angle);
438
int32 y = (self->groundVel >> 10) * RSDK.Cos1024(self->angle);
439
440
self->velocity.x += (x - self->velocity.x) / self->velDivisor;
441
self->velocity.y += (-y - self->velocity.y) / self->velDivisor;
442
}
443
444
self->position.x += self->velocity.x;
445
self->position.y += self->velocity.y;
446
447
if (self->jumpPress && self->state != UFO_Player_State_CourseOut) {
448
self->gravityStrength = 0x50000;
449
self->onGround = false;
450
self->state = UFO_Player_State_Jump;
451
452
RSDK.SetModelAnimation(UFO_Player->jumpModel, &self->animator, 128, 0, true, 0);
453
RSDK.PlaySfx(UFO_Player->sfxJump, false, 0xFF);
454
455
UFO_Player_HandleBumperTiles();
456
}
457
else {
458
if (self->groundVel <= 0xC0000) {
459
RSDK.SetModelAnimation(UFO_Player->jogModel, &self->animator, 128, 0, 0, 0);
460
self->animator.speed = (self->groundVel >> 12) + 48;
461
}
462
else {
463
RSDK.SetModelAnimation(UFO_Player->dashModel, &self->animator, 160, 0, 0, 0);
464
}
465
466
UFO_Player_HandleBumperTiles();
467
}
468
}
469
470
void UFO_Player_State_Jump(void)
471
{
472
RSDK_THIS(UFO_Player);
473
474
int32 turnSpeed = UFO_Player->maxSpeed - 0x60000;
475
476
int32 speed = 0;
477
if (self->right) {
478
speed = (turnSpeed >> 20) + 12;
479
480
if (self->angleZ < 1280 + (turnSpeed >> 10))
481
self->angleZ += (self->angleVel >> 1) + (turnSpeed >> 14);
482
}
483
else if (self->left) {
484
speed = -12 - (turnSpeed >> 20);
485
486
if (self->angleZ > -1280 - (turnSpeed >> 10))
487
self->angleZ -= (self->angleVel >> 1) - (turnSpeed >> 14);
488
}
489
else {
490
speed = 0;
491
492
self->angleZ -= self->angleZ >> 4;
493
}
494
495
if (self->angleZ <= 0)
496
self->angle -= -self->angleZ >> 8;
497
else
498
self->angle += self->angleZ >> 8;
499
500
self->angle &= 0x3FF;
501
502
self->velocity.x -= self->velocity.x >> 8;
503
self->velocity.y -= self->velocity.y >> 8;
504
self->velocity.x += speed * RSDK.Cos1024(self->angle);
505
self->velocity.y += speed * RSDK.Sin1024(self->angle);
506
507
self->position.x += self->velocity.x;
508
self->position.y += self->velocity.y;
509
self->gravityStrength += -0x3800 - (turnSpeed >> 7);
510
511
self->height += self->gravityStrength;
512
self->angleX = (self->angleX - (UFO_Player->maxSpeed >> 13)) & 0x3FF;
513
514
self->animator.animationID = (self->angleX & 0x100) ? UFO_Player->ballModel : UFO_Player->jumpModel;
515
516
if (self->height < 0 && self->gravityStrength <= 0) {
517
self->courseOutTimer = 4;
518
self->height = 0;
519
self->onGround = true;
520
self->state = UFO_Player_State_Run;
521
self->angleZ -= (self->angleZ >> 1);
522
}
523
524
UFO_Player_HandleBumperTiles();
525
}
526
527
void UFO_Player_State_Springboard(void)
528
{
529
RSDK_THIS(UFO_Player);
530
531
int32 tilt = 0;
532
if (self->right)
533
tilt = 8;
534
else if (self->left)
535
tilt = -8;
536
537
self->velocity.x -= self->velocity.x >> 8;
538
self->velocity.y -= self->velocity.y >> 8;
539
540
self->velocity.x += tilt * RSDK.Cos1024(self->angle);
541
self->velocity.y += tilt * RSDK.Sin1024(self->angle);
542
543
self->position.x += self->velocity.x;
544
self->position.y += self->velocity.y;
545
546
self->gravityStrength -= 0x5000;
547
self->height += self->gravityStrength;
548
549
self->angleX = (self->angleX - (UFO_Player->maxSpeed >> 13)) & 0x3FF;
550
551
self->animator.animationID = (self->angleX & 0x100) ? UFO_Player->ballModel : UFO_Player->jumpModel;
552
553
if (self->height < 0) {
554
self->courseOutTimer = 4;
555
self->height = 0;
556
self->onGround = true;
557
self->state = UFO_Player_State_Run;
558
self->angleZ -= (self->angleZ >> 1);
559
}
560
561
UFO_Player_HandleBumperTiles();
562
}
563
564
void UFO_Player_State_Trip(void)
565
{
566
RSDK_THIS(UFO_Player);
567
568
self->position.x += self->velocity.x;
569
self->position.y += self->velocity.y;
570
571
self->velocity.x -= self->velocity.x >> 8;
572
self->velocity.y -= self->velocity.y >> 8;
573
574
if (!self->onGround) {
575
self->gravityStrength -= 0x3800;
576
self->height += self->gravityStrength;
577
578
if (self->height < 0) {
579
self->height = 0;
580
self->onGround = true;
581
}
582
}
583
584
UFO_Player_HandleBumperTiles();
585
586
if (++self->timer > 32) {
587
self->timer = 0;
588
589
if (self->onGround)
590
self->state = UFO_Player_State_Run;
591
else
592
self->state = UFO_Player_State_Jump;
593
}
594
}
595
596
void UFO_Player_State_CourseOut(void)
597
{
598
RSDK_THIS(UFO_Player);
599
600
self->velocity.x -= (self->velocity.x >> 5);
601
self->velocity.y -= (self->velocity.y >> 5);
602
self->gravityStrength -= 0x800;
603
604
self->position.x += self->velocity.x;
605
self->position.y += self->velocity.y;
606
self->height += self->gravityStrength;
607
608
if (self->height < 0)
609
self->drawGroup = 2;
610
611
if (RSDK_GET_ENTITY(SLOT_UFO_SETUP, UFO_Setup)->state == UFO_Setup_State_HandleRingDrain) {
612
++self->timer;
613
614
if (self->timer == 120) {
615
UFO_Setup_Finish_Fail();
616
}
617
else if (self->timer == 16) {
618
if (!UFO_Setup->timedOut) {
619
UFO_Setup->timedOut = true;
620
CREATE_ENTITY(UFO_Message, INT_TO_VOID(UFO_MESSAGE_COURSEOUT), self->position.x, self->position.y);
621
}
622
}
623
}
624
}
625
626
void UFO_Player_State_UFOCaught_Charge(void)
627
{
628
RSDK_THIS(UFO_Player);
629
630
++self->timer;
631
632
self->velocity.x -= (self->velocity.x >> 4);
633
self->velocity.y -= (self->velocity.y >> 4);
634
635
self->position.x += self->velocity.x;
636
self->position.y += self->velocity.y;
637
638
self->angleX = (self->angleX - (UFO_Player->maxSpeed >> 13)) & 0x3FF;
639
640
if (self->timer == 2) {
641
RSDK.SetModelAnimation(UFO_Player->jumpModel, &self->animator, 128, 0, true, 0);
642
RSDK.PlaySfx(UFO_Player->sfxCharge, false, 255);
643
}
644
645
if (self->timer >= 30) {
646
self->timer = 0;
647
self->camera->state = UFO_Camera_State_UFOCaught;
648
self->state = UFO_Player_State_UFOCaught_Released;
649
650
self->velocity.x = (self->circuitPtr->position.x - self->position.x) >> 4;
651
self->velocity.y = (self->circuitPtr->position.y - self->position.y) >> 4;
652
self->gravityStrength = (self->circuitPtr->height - self->height + 0x200000) >> 4;
653
654
RSDK.PlaySfx(UFO_Player->sfxRelease, false, 255);
655
}
656
}
657
658
void UFO_Player_State_UFOCaught_Released(void)
659
{
660
RSDK_THIS(UFO_Player);
661
662
self->gravityStrength -= 0x80;
663
664
self->position.x += self->velocity.x;
665
self->position.y += self->velocity.y;
666
self->height += self->gravityStrength;
667
668
++self->timer;
669
670
self->angleX = (self->angleX - (UFO_Player->maxSpeed >> 13)) & 0x3FF;
671
672
if (self->timer == 16)
673
UFO_Setup_Finish_Win();
674
}
675
676
#if GAME_INCLUDE_EDITOR
677
void UFO_Player_EditorDraw(void)
678
{
679
RSDK_THIS(UFO_Player);
680
681
RSDK.SetSpriteAnimation(UFO_Player->aniFrames, 0, &self->animator, true, 7);
682
683
RSDK.DrawSprite(&self->animator, NULL, false);
684
}
685
686
void UFO_Player_EditorLoad(void) { UFO_Player->aniFrames = RSDK.LoadSpriteAnimation("Editor/PlayerIcons.bin", SCOPE_STAGE); }
687
#endif
688
689
void UFO_Player_Serialize(void)
690
{
691
RSDK_EDITABLE_VAR(UFO_Player, VAR_ENUM, machQuota1);
692
RSDK_EDITABLE_VAR(UFO_Player, VAR_ENUM, machQuota2);
693
RSDK_EDITABLE_VAR(UFO_Player, VAR_ENUM, machQuota3);
694
RSDK_EDITABLE_VAR(UFO_Player, VAR_ENUM, startingRings);
695
}
696
697