Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-1-Sonic-2-2013-Script-Decompilation
Path: blob/master/Sonic 2/Scripts/EHZ/Eggman.txt
1482 views
1
// ----------------------------------
2
// RSDK Project: Sonic 2
3
// Script Description: Eggman Object
4
// Script Author: Christian Whitehead/Simon Thomley
5
// Unpacked by Rubberduckycooly's script unpacker
6
// ----------------------------------
7
8
// Using EHZEggman as a prefix here because there's like 12 "Eggman" objects in the game so it's less confusing this way
9
10
// ========================
11
// Aliases
12
// ========================
13
14
private alias object.value0 : object.timer
15
private alias object.value2 : object.exploding
16
private alias object.value3 : object.heliAnim
17
private alias object.value4 : object.heliAnimTimer
18
private alias object.value6 : object.heliSfxTimer
19
private alias object.value8 : object.health
20
private alias object.value9 : object.invincibilityTimer
21
private alias object.value10 : object.didHitPlayer
22
23
// Eggman States
24
private alias 0 : EHZEGGMAN_AWAITPLAYER
25
private alias 1 : EHZEGGMAN_FLYIN
26
private alias 2 : EHZEGGMAN_ENTERCAR
27
private alias 3 : EHZEGGMAN_STARTCAR
28
private alias 4 : EHZEGGMAN_INCAR
29
private alias 5 : EHZEGGMAN_EXPLODE
30
private alias 6 : EHZEGGMAN_EXITCAR
31
private alias 7 : EHZEGGMAN_FLEE
32
private alias 8 : EHZEGGMAN_ESCAPE
33
34
// Eggman Animations
35
private alias 0 : EHZEGGANI_INVISIBLE
36
private alias 1 : EHZEGGANI_IDLE
37
private alias 2 : EHZEGGANI_LAUGH
38
private alias 3 : EHZEGGANI_HIT
39
private alias 4 : EHZEGGANI_DEFEATED
40
private alias 5 : EHZEGGANI_TOASTED
41
private alias 6 : EHZEGGANI_PANIC
42
43
// Eggman Heli Animations
44
private alias 0 : HELIANI_ACTIVE
45
private alias 1 : HELIANI_ENTERCAR
46
private alias 2 : HELIANI_RETRACTING
47
private alias 3 : HELIANI_NONE
48
private alias 4 : HELIANI_EXTENDING
49
private alias 5 : HELIANI_EXITCAR
50
51
// Car Wheel Aliases
52
private alias object.value0 : eggmanWheel.timer
53
private alias object.value1 : eggmanWheel.xOffset
54
private alias object.value2 : eggmanWheel.parent
55
56
// Car Aliases
57
private alias object.value1 : eggmanCar.drawPos.y
58
private alias object.value2 : eggmanCar.boundsL
59
private alias object.value3 : eggmanCar.boundsR
60
61
// Car Drill States
62
private alias 0 : EHZEGGMANDRILL_ATTATCHED
63
private alias 2 : EHZEGGMANDRILL_FIRED
64
65
// Player Aliases
66
private alias object.xpos : player.xpos
67
private alias object.xvel : player.xvel
68
private alias object.speed : player.speed
69
private alias object.animation : player.animation
70
private alias object.collisionRight : player.collisionRight
71
72
private alias object.value40 : player.hitboxLeft
73
private alias object.value38 : player.hitboxTop
74
private alias object.value41 : player.hitboxRight
75
private alias object.value39 : player.hitboxBottom
76
77
// Music Events
78
private alias 26 : SLOT_MUSICEVENT_BOSS
79
80
private alias 0 : MUSICEVENT_FADETOBOSS
81
private alias 1 : MUSICEVENT_FADETOSTAGE
82
83
84
// ========================
85
// Function Declarations
86
// ========================
87
88
reserve function EHZEggman_PlayHeliSfx
89
90
91
// ========================
92
// Function Definitions
93
// ========================
94
95
private function EHZEggman_PlayHeliSfx
96
if object.heliSfxTimer == 0
97
PlaySfx(SfxName[Helicopter], false)
98
end if
99
object.heliSfxTimer++
100
object.heliSfxTimer &= 31
101
end function
102
103
104
// ========================
105
// Events
106
// ========================
107
108
event ObjectUpdate
109
switch object.state
110
case EHZEGGMAN_AWAITPLAYER
111
temp0 = object.ixpos
112
temp0 -= 200
113
stage.newXBoundary1 = temp0
114
115
temp0 = object.ixpos
116
temp0 += 200
117
stage.newXBoundary2 = temp0
118
119
if player[0].xpos > object.xpos
120
object.animation = EHZEGGANI_IDLE
121
ResetObjectEntity(SLOT_MUSICEVENT_BOSS, TypeName[Music Event], MUSICEVENT_FADETOBOSS, 0, 0)
122
object[SLOT_MUSICEVENT_BOSS].priority = PRIORITY_ACTIVE
123
124
// The Car!!!!
125
object[+1].type = TypeName[Eggman Car]
126
object[+1].xpos = object.xpos
127
object[+1].xpos += 0x1590000
128
object[+1].ypos = object.ypos
129
eggmanCar[+1].boundsL = object.xpos
130
eggmanCar[+1].boundsL -= 0x1180000
131
temp0 = object.ixpos
132
temp0 -= 200
133
temp0 += screen.xcenter
134
if camera[0].xpos < temp0
135
temp0 -= camera[0].xpos
136
temp0 <<= 16
137
eggmanCar[+1].boundsL -= temp0
138
end if
139
140
eggmanCar[+1].boundsR = object.xpos
141
eggmanCar[+1].boundsR += 0x1500000
142
object[+1].priority = PRIORITY_ACTIVE
143
144
// Drrrrrill
145
object[+2].type = TypeName[Eggman Drill]
146
object[+2].priority = PRIORITY_ACTIVE
147
148
// Back Wheel
149
object[-1].type = TypeName[Eggman Wheel]
150
eggmanWheel[-1].xOffset = -0x2C0000
151
eggmanWheel[-1].parent = object[+1].entityPos
152
object[-1].priority = PRIORITY_ACTIVE
153
154
// Front Wheel 1
155
object[+3].type = TypeName[Eggman Wheel]
156
eggmanWheel[+3].xOffset = -0xC0000
157
eggmanWheel[+3].parent = object[+1].entityPos
158
object[+3].priority = PRIORITY_ACTIVE
159
160
// Front Wheel 2
161
object[+4].type = TypeName[Eggman Wheel]
162
eggmanWheel[+4].xOffset = 0x1C0000
163
eggmanWheel[+4].parent = object[+1].entityPos
164
object[+4].priority = PRIORITY_ACTIVE
165
166
object.xpos += 0x1580000
167
object.ypos -= 0x13F0000
168
object.priority = PRIORITY_ACTIVE
169
object.state++
170
end if
171
break
172
173
case EHZEGGMAN_FLYIN
174
CallFunction(EHZEggman_PlayHeliSfx)
175
object.xpos -= 0x10000
176
object.ypos += 0x10000
177
object.timer++
178
if object.timer == 320
179
object.heliAnim = HELIANI_ENTERCAR
180
object.heliAnimTimer = 0
181
object.timer = 0
182
object.state++
183
end if
184
break
185
186
case EHZEGGMAN_ENTERCAR
187
break
188
189
case EHZEGGMAN_STARTCAR
190
object.timer++
191
if object.timer == 24
192
object.timer = 0
193
194
#platform: USE_STANDALONE
195
object.health = 8
196
#endplatform
197
#platform: USE_ORIGINS
198
if game.bossOneLife == false
199
object.health = 8
200
else
201
object.health = 1
202
end if
203
#endplatform
204
205
object.state++
206
object[+1].xvel = -0x20000
207
object[+1].state++
208
end if
209
break
210
211
case EHZEGGMAN_INCAR
212
break
213
214
case EHZEGGMAN_EXPLODE
215
object.timer++
216
if object.timer == 180
217
object.timer = 0
218
object.heliAnim = HELIANI_EXTENDING
219
object.animation = EHZEGGANI_TOASTED
220
object.exploding = false
221
object.state++
222
ResetObjectEntity(SLOT_MUSICEVENT_BOSS, TypeName[Music Event], MUSICEVENT_FADETOSTAGE, 0, 0)
223
object[SLOT_MUSICEVENT_BOSS].priority = PRIORITY_ACTIVE
224
temp0 = tileLayer[0].xsize
225
temp0 <<= 7
226
stage.newXBoundary2 = temp0
227
end if
228
break
229
230
case EHZEGGMAN_EXITCAR
231
break
232
233
case EHZEGGMAN_FLEE
234
CallFunction(EHZEggman_PlayHeliSfx)
235
object.ypos -= 0x10000
236
237
object.timer++
238
if object.timer == 96
239
object.timer = 0
240
object.direction = FLIP_X
241
object.animation = EHZEGGANI_PANIC
242
object.state++
243
end if
244
break
245
246
case EHZEGGMAN_ESCAPE
247
if object.outOfBounds == false
248
CallFunction(EHZEggman_PlayHeliSfx)
249
end if
250
object.xpos += 0x60000
251
252
temp0 = stage.newXBoundary2
253
temp0 += 128
254
temp0 <<= 16
255
if object.xpos >= temp0
256
object.type = TypeName[Blank Object]
257
end if
258
break
259
260
end switch
261
262
if object.health != 0
263
if object.invincibilityTimer > 0
264
object.invincibilityTimer--
265
GetBit(temp0, object.invincibilityTimer, 0)
266
if temp0 == true // Palette flashing when hit
267
SetPaletteEntry(0, 192, 0xE0E0E0)
268
else
269
SetPaletteEntry(0, 192, 0x000000)
270
end if
271
end if
272
273
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
274
if object.invincibilityTimer == 0 // Invulnerable?
275
CheckEqual(player[currentPlayer].animation, ANI_HURT)
276
temp0 = checkResult
277
CheckEqual(player[currentPlayer].animation, ANI_DYING)
278
temp0 |= checkResult
279
CheckEqual(player[currentPlayer].animation, ANI_DROWNING)
280
temp0 |= checkResult
281
if temp0 != false
282
if object.animation != EHZEGGANI_LAUGH
283
object.animation = EHZEGGANI_LAUGH
284
object.animationTimer = 0
285
end if
286
287
if currentPlayer == 0
288
object.didHitPlayer = true
289
end if
290
end if
291
292
BoxCollisionTest(C_TOUCH, object.entityPos, -24, -24, 24, 24, currentPlayer, player[currentPlayer].hitboxLeft, player[currentPlayer].hitboxTop, player[currentPlayer].hitboxRight, player[currentPlayer].hitboxBottom)
293
if checkResult == true
294
CallFunction(Player_CheckHit)
295
if checkResult == true
296
object.health--
297
if object.health == 0
298
#platform: USE_ORIGINS
299
CallNativeFunction2(NotifyCallback, NOTIFY_KILL_BOSS, 0)
300
CallNativeFunction2(NotifyCallback, NOTIFY_BOSS_END, 1)
301
#endplatform
302
303
player.score += 1000
304
object.animation = EHZEGGANI_DEFEATED
305
object.animationTimer = 0
306
object.exploding = true
307
object.state++
308
309
// The Car!!!!
310
object[+1].state++
311
object[+1].yvel = -0x18000
312
object[+1].ypos = eggmanCar[+1].drawPos.y
313
314
if object[+2].state == EHZEGGMANDRILL_ATTATCHED
315
object[+2].state = EHZEGGMANDRILL_FIRED
316
if object.direction == FLIP_NONE
317
object[+2].xvel = -0x30000
318
else
319
object[+2].xvel = 0x30000
320
end if
321
end if
322
else
323
object.animation = EHZEGGANI_HIT
324
object.animationTimer = 0
325
object.invincibilityTimer = 32
326
PlaySfx(SfxName[Boss Hit], false)
327
end if
328
end if
329
end if
330
end if
331
next
332
end if
333
334
// R Boundary
335
if object.state != EHZEGGMAN_ESCAPE
336
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
337
temp0 = player[currentPlayer].collisionRight
338
temp0 <<= 16
339
temp0 += player[currentPlayer].xpos
340
temp1 = stage.curXBoundary2
341
temp1 <<= 16
342
if temp0 > temp1
343
player[currentPlayer].xvel = 0
344
player[currentPlayer].speed = 0
345
player[currentPlayer].xpos = temp1
346
temp0 = player[currentPlayer].collisionRight
347
temp0 <<= 16
348
player[currentPlayer].xpos -= temp0
349
end if
350
next
351
end if
352
353
if object.exploding == true
354
temp0 = oscillation
355
temp0 &= 7
356
if temp0 == 0
357
Rand(temp0, 96)
358
temp0 -= 48
359
temp0 <<= 16
360
temp0 += object.xpos
361
362
Rand(temp1, 48)
363
temp1 -= 24
364
temp1 <<= 16
365
temp1 += object.ypos
366
367
CreateTempObject(TypeName[Explosion], 0, temp0, temp1)
368
object[tempObjectPos].drawOrder = 5
369
PlaySfx(SfxName[Explosion], false)
370
end if
371
end if
372
end event
373
374
375
event ObjectDraw
376
if object.animation != EHZEGGANI_INVISIBLE
377
switch object.heliAnim
378
case HELIANI_ACTIVE
379
temp0 = object.heliAnimTimer
380
temp0 >>= 1
381
temp0 += 12
382
383
object.heliAnimTimer++
384
object.heliAnimTimer &= 3
385
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
386
break
387
388
case HELIANI_ENTERCAR
389
temp0 = object.heliAnimTimer
390
temp0 /= 6
391
temp0 += 8
392
393
object.heliAnimTimer++
394
if object.heliAnimTimer == 24
395
object.heliAnimTimer = 0
396
object.heliAnim = HELIANI_RETRACTING
397
end if
398
399
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
400
break
401
402
case HELIANI_RETRACTING
403
temp0 = object.heliAnimTimer
404
temp0 <<= 16
405
temp0 += object.ypos
406
DrawSpriteFX(7, FX_FLIP, object.xpos, temp0)
407
408
object.heliAnimTimer++
409
if object.heliAnimTimer == 12
410
object.state++
411
object.heliAnim = HELIANI_NONE
412
end if
413
break
414
415
case HELIANI_NONE
416
break
417
418
case HELIANI_EXTENDING
419
object.heliAnimTimer--
420
if object.heliAnimTimer > 0
421
temp0 = object.heliAnimTimer
422
else
423
temp0 = 0
424
end if
425
426
temp0 <<= 16
427
temp0 += object.ypos
428
DrawSpriteFX(7, FX_FLIP, object.xpos, temp0)
429
430
if object.heliAnimTimer == -12
431
object.heliAnimTimer = 24
432
object.heliAnim = HELIANI_EXITCAR
433
end if
434
break
435
436
case HELIANI_EXITCAR
437
object.heliAnimTimer--
438
439
temp0 = object.heliAnimTimer
440
temp0 /= 6
441
temp0 += 8
442
443
if object.heliAnimTimer == 0
444
object.heliAnim = HELIANI_ACTIVE
445
object.state++
446
end if
447
448
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
449
break
450
451
end switch
452
453
DrawSpriteFX(6, FX_FLIP, object.xpos, object.ypos)
454
end if
455
456
switch object.animation
457
default
458
case EHZEGGANI_INVISIBLE
459
break
460
461
case EHZEGGANI_IDLE
462
temp0 = object.animationTimer
463
temp0 >>= 3
464
object.animationTimer++
465
object.animationTimer &= 15
466
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
467
break
468
469
case EHZEGGANI_LAUGH
470
temp0 = object.animationTimer
471
temp0 &= 15
472
temp0 >>= 3
473
temp0 += 2
474
475
object.animationTimer++
476
if object.animationTimer == 50
477
object.animationTimer = 0
478
if player[0].animation != ANI_DYING
479
object.animation = EHZEGGANI_IDLE
480
end if
481
end if
482
483
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
484
break
485
486
case EHZEGGANI_HIT
487
temp0 = object.animationTimer
488
temp0 &= 1
489
temp0 += 2
490
491
object.animationTimer++
492
if object.animationTimer == 50
493
object.animationTimer = 0
494
object.animation = EHZEGGANI_IDLE
495
end if
496
497
DrawSpriteFX(4, FX_FLIP, object.xpos, object.ypos)
498
break
499
500
case EHZEGGANI_DEFEATED
501
temp0 = object.animationTimer
502
temp0 >>= 5
503
temp0 += 4
504
temp0 %= 5
505
506
object.animationTimer++
507
object.animationTimer &= 63
508
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
509
break
510
511
case EHZEGGANI_TOASTED
512
DrawSpriteFX(5, FX_FLIP, object.xpos, object.ypos)
513
break
514
515
case EHZEGGANI_PANIC
516
temp0 = object.animationTimer
517
temp0 >>= 3
518
519
object.animationTimer++
520
object.animationTimer &= 15
521
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
522
523
temp0 = object.animationTimer
524
temp0 >>= 2
525
temp0 &= 1
526
if temp0 == 1
527
DrawSpriteFX(14, FX_FLIP, object.xpos, object.ypos)
528
end if
529
break
530
531
end switch
532
end event
533
534
535
event ObjectStartup
536
// Check if in EHZ
537
CheckCurrentStageFolder("Zone01")
538
if checkResult == true
539
// Load EHZ stuff
540
LoadSpriteSheet("EHZ/Objects.gif")
541
542
// Eggman Frames
543
SpriteFrame(-28, -28, 60, 20, 70, 155)
544
SpriteFrame(-28, -28, 60, 20, 131, 155)
545
SpriteFrame(-28, -28, 60, 20, 70, 176)
546
SpriteFrame(-28, -28, 60, 20, 131, 176)
547
SpriteFrame(-28, -28, 60, 20, 70, 197)
548
SpriteFrame(-28, -28, 60, 20, 131, 197)
549
550
// Eggmobile Body Frame
551
SpriteFrame(-32, -8, 64, 29, 0, 209)
552
553
// Boss Helicopter Frames
554
SpriteFrame(2, -40, 16, 16, 65, 239)
555
SpriteFrame(-62, -40, 144, 16, 1, 239)
556
SpriteFrame(-46, -40, 112, 16, 17, 239)
557
SpriteFrame(-30, -40, 80, 16, 33, 239)
558
SpriteFrame(-14, -40, 48, 16, 49, 239)
559
SpriteFrame(2, -40, 80, 16, 65, 222)
560
SpriteFrame(-62, -40, 79, 16, 1, 239)
561
562
// Sweat Frame
563
SpriteFrame(-3, -28, 11, 8, 27, 53)
564
565
// Erase the boss in VS mode
566
if options.vsMode == true
567
foreach (TypeName[Eggman], arrayPos0, ALL_ENTITIES)
568
object[arrayPos0].type = TypeName[Blank Object]
569
next
570
end if
571
else
572
LoadSpriteSheet("MBZ/Objects.gif")
573
574
// Eggman Frames
575
SpriteFrame(-28, -28, 60, 20, 1, 1)
576
SpriteFrame(-28, -28, 60, 20, 62, 1)
577
SpriteFrame(-28, -28, 60, 20, 1, 22)
578
SpriteFrame(-28, -28, 60, 20, 62, 22)
579
SpriteFrame(-28, -28, 60, 20, 1, 43)
580
SpriteFrame(-28, -28, 60, 20, 62, 43)
581
582
// Eggmobile Body Frame
583
SpriteFrame(-32, -8, 64, 29, 415, 170)
584
585
// Boss Helicopter Frames
586
SpriteFrame(2, -40, 16, 16, 169, 91)
587
SpriteFrame(-62, -40, 144, 16, 105, 91)
588
SpriteFrame(-46, -40, 112, 16, 121, 91)
589
SpriteFrame(-30, -40, 80, 16, 137, 91)
590
SpriteFrame(-14, -40, 48, 16, 153, 91)
591
SpriteFrame(2, -40, 80, 16, 42, 64)
592
SpriteFrame(-62, -40, 79, 16, 105, 91)
593
594
// Sweat Frame
595
SpriteFrame(-3, -28, 11, 8, 45, 88)
596
597
// No need to erase the boss in VS mode when in MBZ since it should never even be active there anyway
598
end if
599
end event
600
601
602
// ========================
603
// Editor Events
604
// ========================
605
606
event RSDKDraw
607
DrawSprite(0)
608
DrawSprite(1)
609
610
if editor.showGizmos == true
611
editor.drawingOverlay = true
612
613
// Draw lines connecting the whole network of boss objects
614
DrawArrow(object.xpos, object.ypos, object[-1].xpos, object[-1].ypos, 255, 255, 0) // Back Wheel
615
DrawArrow(object.xpos, object.ypos, object[+1].xpos, object[+1].ypos, 255, 255, 0) // Car
616
DrawArrow(object.xpos, object.ypos, object[+2].xpos, object[+2].ypos, 255, 255, 0) // Drill
617
DrawArrow(object.xpos, object.ypos, object[+3].xpos, object[+3].ypos, 255, 255, 0) // Front Wheel 1
618
DrawArrow(object.xpos, object.ypos, object[+4].xpos, object[+4].ypos, 255, 255, 0) // Front Wheel 2
619
620
// Draw arena bounds
621
// Left bounds depends on screen size, this is a rough estimation
622
temp0 = 224; temp1 = 208; temp2 = 200; temp3 = 32;
623
CallFunction(EditorHelpers_DrawHitbox)
624
625
editor.drawingOverlay = false
626
end if
627
end event
628
629
630
event RSDKLoad
631
CheckCurrentStageFolder("Zone01")
632
if checkResult == true
633
LoadSpriteSheet("EHZ/Objects.gif")
634
SpriteFrame(-28, -28, 60, 20, 70, 155)
635
SpriteFrame(-32, -8, 64, 29, 0, 209)
636
else
637
LoadSpriteSheet("MBZ/Objects.gif")
638
SpriteFrame(-28, -28, 60, 20, 1, 1)
639
SpriteFrame(-32, -8, 64, 29, 415, 170)
640
end if
641
642
SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
643
end event
644
645