Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/AIZ/MonkeyDude.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: MonkeyDude Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectMonkeyDude *MonkeyDude;
11
12
void MonkeyDude_Update(void)
13
{
14
RSDK_THIS(MonkeyDude);
15
StateMachine_Run(self->state);
16
#if !MANIA_USE_PLUS
17
for (self->armNodeID = 0; self->armNodeID < MonkeyDude_ArmJointCount; ++self->armNodeID) {
18
StateMachine_Run(self->armStates[self->armNodeID]);
19
}
20
#endif
21
}
22
23
void MonkeyDude_LateUpdate(void) {}
24
25
void MonkeyDude_StaticUpdate(void) {}
26
27
void MonkeyDude_Draw(void)
28
{
29
RSDK_THIS(MonkeyDude);
30
#if MANIA_USE_PLUS
31
if (self->state == MonkeyDude_State_Coconut) {
32
RSDK.DrawSprite(&self->bodyAnimator, NULL, false);
33
}
34
else {
35
#endif
36
Vector2 drawPos;
37
38
if (!self->direction)
39
drawPos.x = self->position.x - 0xD0000;
40
else
41
drawPos.x = self->position.x + 0xD0000;
42
43
if (!self->bodyAnimator.frameID)
44
drawPos.y = self->position.y + -0x20000;
45
else
46
drawPos.y = self->position.y + -0x40000;
47
RSDK.DrawSprite(&MonkeyDude->armAnimator, &drawPos, false);
48
49
for (self->armNodeID = 0; self->armNodeID < MonkeyDude_ArmJointCount; ++self->armNodeID) {
50
if (self->direction)
51
drawPos.x += RSDK.Sin256(self->armAngles[self->armNodeID]) << 11;
52
else
53
drawPos.x -= RSDK.Sin256(self->armAngles[self->armNodeID]) << 11;
54
55
drawPos.y += RSDK.Cos256(self->armAngles[self->armNodeID]) << 11;
56
57
Animator *animator = NULL;
58
if (self->armNodeID == MonkeyDude_ArmJointCount - 1) {
59
if (self->throwCount >= 4)
60
animator = &self->handAnimator;
61
else
62
animator = &MonkeyDude->coconutAnimator;
63
}
64
else {
65
animator = &MonkeyDude->armAnimator;
66
}
67
RSDK.DrawSprite(animator, &drawPos, false);
68
}
69
70
RSDK.DrawSprite(&self->bodyAnimator, NULL, false);
71
72
drawPos.x = self->position.x;
73
drawPos.y = self->armY;
74
RSDK.DrawSprite(&MonkeyDude->tailAnimator, &drawPos, false);
75
#if MANIA_USE_PLUS
76
}
77
#endif
78
}
79
80
void MonkeyDude_Create(void *data)
81
{
82
RSDK_THIS(MonkeyDude);
83
self->visible = true;
84
self->drawGroup = Zone->objectDrawGroup[0];
85
self->drawFX |= FX_FLIP;
86
self->startPos = self->position;
87
self->startDir = self->direction;
88
self->active = ACTIVE_BOUNDS;
89
self->updateRange.x = 0x800000;
90
self->updateRange.y = 0x800000;
91
92
#if MANIA_USE_PLUS
93
if (!self->nummoves)
94
self->nummoves = 3;
95
96
if (data) {
97
RSDK.SetSpriteAnimation(MonkeyDude->aniFrames, 4, &self->bodyAnimator, true, 0);
98
self->state = MonkeyDude_State_Coconut;
99
}
100
else {
101
#endif
102
RSDK.SetSpriteAnimation(MonkeyDude->aniFrames, 0, &self->bodyAnimator, true, 0);
103
RSDK.SetSpriteAnimation(MonkeyDude->aniFrames, 3, &self->handAnimator, true, 0);
104
self->state = MonkeyDude_State_Init;
105
#if MANIA_USE_PLUS
106
}
107
#endif
108
}
109
110
void MonkeyDude_StageLoad(void)
111
{
112
#if MANIA_USE_PLUS
113
MonkeyDude->aniFrames = RSDK.LoadSpriteAnimation("AIZ/MonkeyDude.bin", SCOPE_STAGE);
114
115
MonkeyDude->hitboxBadnik.left = -10;
116
MonkeyDude->hitboxBadnik.top = -21;
117
MonkeyDude->hitboxBadnik.right = 7;
118
MonkeyDude->hitboxBadnik.bottom = 4;
119
120
MonkeyDude->hitboxCoconut.left = -4;
121
MonkeyDude->hitboxCoconut.top = -4;
122
MonkeyDude->hitboxCoconut.right = 4;
123
MonkeyDude->hitboxCoconut.bottom = 4;
124
#else
125
MonkeyDude->aniFrames = RSDK.LoadSpriteAnimation("Blueprint/MonkeyDude.bin", SCOPE_STAGE);
126
127
// strange hitbox, doesn't match either one above lol
128
MonkeyDude->hitboxBadnik.left = -8;
129
MonkeyDude->hitboxBadnik.top = -8;
130
MonkeyDude->hitboxBadnik.right = 8;
131
MonkeyDude->hitboxBadnik.bottom = 8;
132
#endif
133
134
RSDK.SetSpriteAnimation(MonkeyDude->aniFrames, 2, &MonkeyDude->armAnimator, true, 0);
135
RSDK.SetSpriteAnimation(MonkeyDude->aniFrames, 1, &MonkeyDude->tailAnimator, true, 0);
136
RSDK.SetSpriteAnimation(MonkeyDude->aniFrames, 4, &MonkeyDude->coconutAnimator, true, 0);
137
138
#if MANIA_USE_PLUS
139
MonkeyDude->sfxDrop = RSDK.GetSfx("Stage/Drop.wav");
140
#endif
141
142
DEBUGMODE_ADD_OBJ(MonkeyDude);
143
}
144
145
void MonkeyDude_DebugDraw(void)
146
{
147
#if MANIA_USE_PLUS
148
RSDK_THIS(MonkeyDude);
149
150
RSDK.SetSpriteAnimation(MonkeyDude->aniFrames, 0, &self->bodyAnimator, true, 0);
151
RSDK.DrawSprite(&self->bodyAnimator, NULL, false);
152
#endif
153
}
154
155
void MonkeyDude_DebugSpawn(void)
156
{
157
#if MANIA_USE_PLUS
158
RSDK_THIS(MonkeyDude);
159
160
EntityMonkeyDude *monkeyDude = CREATE_ENTITY(MonkeyDude, NULL, self->position.x, self->position.y);
161
monkeyDude->direction = self->direction;
162
monkeyDude->startDir = self->direction;
163
#endif
164
}
165
166
void MonkeyDude_State_Init(void)
167
{
168
RSDK_THIS(MonkeyDude);
169
self->armY = self->position.y;
170
self->active = ACTIVE_NORMAL;
171
self->velocity.y = 0x10000;
172
self->moveCount = 1;
173
self->timer = 1;
174
self->angleVel = 4;
175
self->activeArmNodes = 0;
176
self->throwCount = 0;
177
self->state = MonkeyDude_State_Laugh;
178
#if MANIA_USE_PLUS
179
RSDK.ProcessAnimation(&self->bodyAnimator);
180
#else
181
self->bodyAnimator.frameID = (self->coconutFrame++ >> 3) & 1;
182
#endif
183
if (--self->timer <= 0) {
184
self->coconutFrame = 0;
185
self->timer = 8;
186
self->state = MonkeyDude_State_MoveArm;
187
}
188
#if MANIA_USE_PLUS
189
MonkeyDude_HandleStates();
190
#endif
191
192
int32 delay = 0;
193
for (int32 i = 0; i < MonkeyDude_ArmJointCount; ++i) {
194
self->armAngles[i] = 0;
195
self->armTimers[i] = delay;
196
self->armStates[i] = MonkeyDude_StateBody_ArmRaise;
197
198
delay += 24 / (MonkeyDude_ArmJointCount - 1);
199
}
200
}
201
202
void MonkeyDude_HandleBodyPart(void)
203
{
204
RSDK_THIS(MonkeyDude);
205
self->armTimers[self->armNodeID] = self->armNodeID;
206
switch (self->throwCount) {
207
case 0:
208
case 4:
209
self->angleVel = 4;
210
self->armTimers[self->armNodeID] *= 4;
211
self->armMoveDir[self->armNodeID] ^= 1;
212
213
if (!self->armNodeID) {
214
self->currentAngle = self->armAngles[0];
215
if (self->armMoveDir[0]) {
216
self->currentAngle -= RSDK.Rand(0, 96);
217
if (self->currentAngle < 32)
218
self->currentAngle = 32;
219
}
220
else {
221
self->currentAngle += RSDK.Rand(0, 96);
222
if (self->currentAngle > 128)
223
self->currentAngle = 128;
224
}
225
}
226
if (self->armNodeID == MonkeyDude_ArmJointCount - 1)
227
self->activeArmNodes = 0;
228
break;
229
230
case 1:
231
self->angleVel = 5;
232
self->armTimers[self->armNodeID] *= 2;
233
self->currentAngle = 176;
234
self->armMoveDir[self->armNodeID] = 0;
235
if (self->armNodeID == MonkeyDude_ArmJointCount - 1) {
236
++self->throwCount;
237
self->activeArmNodes = 0;
238
}
239
break;
240
241
case 2:
242
self->armTimers[self->armNodeID] *= 2;
243
self->currentAngle = 96;
244
self->armMoveDir[self->armNodeID] = 1;
245
if (self->armNodeID == MonkeyDude_ArmJointCount - 1) {
246
++self->throwCount;
247
self->activeArmNodes = 0;
248
}
249
break;
250
}
251
252
if (self->armNodeID == MonkeyDude_ArmJointCount - 1)
253
self->activeArmNodes = 0;
254
}
255
256
#if MANIA_USE_PLUS
257
void MonkeyDude_HandleStates(void)
258
{
259
RSDK_THIS(MonkeyDude);
260
foreach_active(Player, player)
261
{
262
if (Player_CheckBadnikTouch(player, self, &MonkeyDude->hitboxBadnik))
263
Player_CheckBadnikBreak(player, self, true);
264
}
265
266
if (self->classID) {
267
if (self->throwCount) {
268
if (self->throwCount == 3 && self->armAngles[MonkeyDude_ArmJointCount - 1] <= 164) {
269
int32 spawnX = self->position.x + 0xD0000;
270
if (!self->direction)
271
spawnX = self->position.x - 0xD0000;
272
int32 spawnY = self->position.y;
273
274
for (int32 i = 0; i < MonkeyDude_ArmJointCount; ++i) {
275
if (self->direction)
276
spawnX += RSDK.Sin256(self->armAngles[i]) << 11;
277
else
278
spawnX -= RSDK.Sin256(self->armAngles[i]) << 11;
279
spawnY += (RSDK.Cos256(self->armAngles[i]) << 11);
280
}
281
282
EntityMonkeyDude *coconut = CREATE_ENTITY(MonkeyDude, INT_TO_VOID(1), spawnX, spawnY);
283
if (!self->direction)
284
coconut->velocity.x = -0x20000;
285
else
286
coconut->velocity.x = 0x20000;
287
coconut->velocity.y = -0x40000;
288
coconut->direction = self->direction;
289
RSDK.PlaySfx(MonkeyDude->sfxDrop, false, 0xFF);
290
++self->throwCount;
291
}
292
}
293
else {
294
EntityPlayer *target = Player_GetNearestPlayer();
295
if (!self->direction) {
296
if (target->position.x < self->position.x) {
297
if (abs(self->position.x - target->position.x) <= 0x800000) {
298
if (target->position.y > self->position.y - 0x200000 && target->position.y - self->position.y <= 0x800000
299
&& self->onScreen == 1) {
300
self->throwCount = 1;
301
self->currentAngle = self->armAngles[0];
302
}
303
}
304
}
305
}
306
}
307
308
for (self->armNodeID = 0; self->armNodeID < MonkeyDude_ArmJointCount; ++self->armNodeID) {
309
StateMachine_Run(self->armStates[self->armNodeID]);
310
}
311
312
if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {
313
self->position = self->startPos;
314
self->direction = self->startDir;
315
MonkeyDude_Create(NULL);
316
}
317
}
318
}
319
#endif
320
321
void MonkeyDude_State_Laugh(void)
322
{
323
RSDK_THIS(MonkeyDude);
324
#if MANIA_USE_PLUS
325
RSDK.ProcessAnimation(&self->bodyAnimator);
326
#else
327
self->bodyAnimator.frameID = (self->coconutFrame++ >> 3) & 1;
328
#endif
329
if (--self->timer <= 0) {
330
self->coconutFrame = 0;
331
self->timer = 8;
332
self->state = MonkeyDude_State_MoveArm;
333
}
334
#if MANIA_USE_PLUS
335
MonkeyDude_HandleStates();
336
#endif
337
}
338
339
void MonkeyDude_State_MoveArm(void)
340
{
341
RSDK_THIS(MonkeyDude);
342
self->armY += self->velocity.y;
343
self->bodyAnimator.frameID = 0;
344
if (--self->timer <= 0) {
345
self->timer = 8;
346
self->state = MonkeyDude_State_MoveBody;
347
}
348
#if MANIA_USE_PLUS
349
MonkeyDude_HandleStates();
350
#endif
351
}
352
353
void MonkeyDude_State_MoveBody(void)
354
{
355
RSDK_THIS(MonkeyDude);
356
self->position.y += self->velocity.y;
357
if (--self->timer <= 0) {
358
if (--self->moveCount > 0) {
359
self->timer = 8;
360
self->state = MonkeyDude_State_MoveArm;
361
}
362
else {
363
self->timer = 60;
364
self->velocity.y = -self->velocity.y;
365
self->moveCount = self->nummoves;
366
self->state = MonkeyDude_State_Laugh;
367
}
368
}
369
#if MANIA_USE_PLUS
370
MonkeyDude_HandleStates();
371
#endif
372
}
373
374
void MonkeyDude_StateBody_ArmRaise(void)
375
{
376
RSDK_THIS(MonkeyDude);
377
if (self->activeArmNodes == ((1 << MonkeyDude_ArmJointCount) - 1)) {
378
self->armStates[self->armNodeID] = MonkeyDude_StateBody_Throw;
379
MonkeyDude_HandleBodyPart();
380
}
381
382
if (self->armTimers[self->armNodeID]) {
383
self->armTimers[self->armNodeID]--;
384
}
385
else if (self->armAngles[self->armNodeID] >= 128) {
386
self->activeArmNodes |= (1 << self->armNodeID);
387
}
388
else {
389
self->armAngles[self->armNodeID] += self->angleVel;
390
}
391
}
392
393
void MonkeyDude_StateBody_Throw(void)
394
{
395
RSDK_THIS(MonkeyDude);
396
if (self->activeArmNodes == ((1 << MonkeyDude_ArmJointCount) - 1))
397
MonkeyDude_HandleBodyPart();
398
399
if (self->armTimers[self->armNodeID]) {
400
self->armTimers[self->armNodeID]--;
401
}
402
else {
403
if (self->armMoveDir[self->armNodeID]) {
404
if (self->armAngles[self->armNodeID] <= self->currentAngle) {
405
self->activeArmNodes |= (1 << self->armNodeID);
406
}
407
else {
408
self->armAngles[self->armNodeID] -= self->angleVel;
409
}
410
}
411
else {
412
if (self->armAngles[self->armNodeID] >= self->currentAngle) {
413
self->activeArmNodes |= (1 << self->armNodeID);
414
}
415
else {
416
self->armAngles[self->armNodeID] += self->angleVel;
417
}
418
}
419
}
420
}
421
422
#if MANIA_USE_PLUS
423
void MonkeyDude_State_Coconut(void)
424
{
425
RSDK_THIS(MonkeyDude);
426
427
self->position.x += self->velocity.x;
428
self->position.y += self->velocity.y;
429
self->velocity.y += 0x3800;
430
431
if (RSDK.CheckOnScreen(self, NULL)) {
432
RSDK.ProcessAnimation(&self->bodyAnimator);
433
foreach_active(Player, player)
434
{
435
if (Player_CheckCollisionTouch(player, self, &MonkeyDude->hitboxCoconut))
436
Player_ProjectileHurt(player, self);
437
}
438
}
439
else {
440
destroyEntity(self);
441
}
442
}
443
#endif
444
445
#if GAME_INCLUDE_EDITOR
446
void MonkeyDude_EditorDraw(void) { MonkeyDude_Draw(); }
447
448
void MonkeyDude_EditorLoad(void)
449
{
450
#if MANIA_USE_PLUS
451
MonkeyDude->aniFrames = RSDK.LoadSpriteAnimation("AIZ/MonkeyDude.bin", SCOPE_STAGE);
452
#else
453
MonkeyDude->aniFrames = RSDK.LoadSpriteAnimation("Blueprint/MonkeyDude.bin", SCOPE_STAGE);
454
#endif
455
}
456
#endif
457
458
void MonkeyDude_Serialize(void) { RSDK_EDITABLE_VAR(MonkeyDude, VAR_ENUM, nummoves); }
459
460