Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-1-Sonic-2-2013-Script-Decompilation
Path: blob/master/Sonic 1/Scripts/MZ/Eggman.txt
1482 views
1
// ----------------------------------
2
// RSDK Project: Sonic 1
3
// Script Description: Eggman Object
4
// Script Author: Christian Whitehead/Simon Thomley
5
// Unpacked by Rubberduckycooly's script unpacker
6
// ----------------------------------
7
8
// Using MZEggman as a prefix here because there's like 12 "Eggman" objects in the game so its less confusing this way
9
10
// ========================
11
// Aliases
12
// ========================
13
14
private alias object.value0 : object.timer
15
private alias object.value1 : object.health
16
private alias object.value2 : object.invincibilityTimer
17
private alias object.value3 : object.flameAnim
18
private alias object.value4 : object.flameAnimTimer
19
private alias object.value5 : object.boundsL
20
private alias object.value6 : object.boundsR
21
private alias object.value7 : object.divePos.y
22
private alias object.value8 : object.originPos.y
23
private alias object.value9 : object.fireballDropDelay
24
private alias object.value10 : object.dontRandomizeNextDrop
25
private alias object.value11 : object.nextState
26
private alias object.value12 : object.hitDelay
27
28
// Eggman States
29
private alias 0 : MZEGGMAN_AWAITPLAYER
30
private alias 1 : MZEGGMAN_ENTEREGGMAN
31
private alias 2 : MZEGGMAN_TAUNT
32
private alias 3 : MZEGGMAN_MOVE_L
33
private alias 4 : MZEGGMAN_DROPFIREBALL_L
34
private alias 5 : MZEGGMAN_DROPPEDFIREBALL_L
35
private alias 6 : MZEGGMAN_MOVE_R
36
private alias 7 : MZEGGMAN_DROPFIREBALL_R
37
private alias 8 : MZEGGMAN_DROPPEDFIREBALL_R
38
private alias 9 : MZEGGMAN_EXPLODE
39
private alias 10 : MZEGGMAN_DEFEATFALL
40
private alias 11 : MZEGGMAN_DEFEATRISE
41
private alias 12 : MZEGGMAN_FLEE
42
private alias 13 : MZEGGMAN_ESCAPE
43
private alias 14 : MZEGGMAN_HITFREEZE
44
45
// Eggman Animations
46
private alias 0 : MZEGGANI_INVISIBLE
47
private alias 1 : MZEGGANI_IDLE
48
private alias 2 : MZEGGANI_LAUGH
49
private alias 3 : MZEGGANI_LAUGH_LOOP
50
private alias 4 : MZEGGANI_HIT
51
private alias 5 : MZEGGANI_DEFEATED
52
private alias 6 : MZEGGANI_TOASTED
53
private alias 7 : MZEGGANI_PANIC
54
55
// Flame Animations
56
private alias 0 : FLAME_INACTIVE
57
private alias 1 : FLAME_ACTIVE
58
private alias 2 : FLAME_EXPLODE
59
60
// Marker aliases
61
private alias object.xpos : marker.xpos
62
private alias object.ypos : marker.ypos
63
private alias object.ixpos : marker.ixpos
64
private alias object.iypos : marker.iypos
65
66
// Fireball aliases
67
private alias object.value2 : fireball.fireballDir
68
private alias object.value3 : fireball.finalY
69
private alias 1 : FIREBALL_MOVE_GRAVITY
70
71
// Player Aliases
72
private alias object.xpos : player.xpos
73
private alias object.xvel : player.xvel
74
private alias object.speed : player.speed
75
private alias object.animation : player.animation
76
private alias object.collisionRight : player.collisionRight
77
private alias object.value40 : player.hitboxLeft
78
private alias object.value38 : player.hitboxTop
79
private alias object.value41 : player.hitboxRight
80
private alias object.value39 : player.hitboxBottom
81
private alias object.value18 : player.sortedDrawOrder
82
83
// Music Events
84
private alias 26 : SLOT_MUSICEVENT_BOSS
85
86
private alias 0 : MUSICEVENT_FADETOBOSS
87
private alias 1 : MUSICEVENT_FADETOSTAGE
88
private alias 2 : MUSICEVENT_TRANSITION
89
90
91
// ========================
92
// Function Declarations
93
// ========================
94
95
reserve function MZEggman_Oscillate
96
reserve function MZEggman_HandleFireballErupt
97
98
99
// ========================
100
// Aliases
101
// ========================
102
103
private function MZEggman_Oscillate
104
Sin256(object.ypos, object.angle)
105
object.ypos <<= 10
106
object.ypos += object.originPos.y
107
object.angle += 2
108
object.angle &= 0xFF
109
end function
110
111
112
private function MZEggman_HandleFireballErupt
113
if object.fireballDropDelay > 0
114
object.fireballDropDelay--
115
else
116
Rand(temp0, 112)
117
temp0 -= 56
118
temp0 <<= 16
119
temp0 += marker[+1].xpos
120
temp1 = marker[+1].ypos
121
temp1 += 0x200000
122
CreateTempObject(TypeName[Fireball], 0, temp0, temp1)
123
object[tempObjectPos].state = FIREBALL_MOVE_GRAVITY
124
object[tempObjectPos].xvel = 0
125
object[tempObjectPos].yvel = -0x40000
126
fireball[tempObjectPos].finalY = temp1
127
fireball[tempObjectPos].fireballDir = 2
128
PlaySfx(SfxName[Small Fireball], false)
129
130
if object.dontRandomizeNextDrop == false
131
Rand(temp0, 3)
132
if temp0 == 2
133
object.fireballDropDelay = 70
134
object.dontRandomizeNextDrop = true
135
else
136
object.fireballDropDelay = 140
137
end if
138
else
139
object.dontRandomizeNextDrop = false
140
object.fireballDropDelay = 140
141
end if
142
end if
143
end function
144
145
146
// ========================
147
// Events
148
// ========================
149
150
event ObjectUpdate
151
switch object.state
152
case MZEGGMAN_AWAITPLAYER
153
temp0 = marker[+1].ixpos
154
temp0 += screen.xcenter
155
stage.newXBoundary2 = temp0
156
157
temp0 -= screen.xsize
158
stage.newXBoundary1 = temp0
159
160
temp0 = stage.curYBoundary2
161
temp0 -= screen.ysize
162
stage.newYBoundary1 = temp0
163
164
if player[0].xpos > marker[+1].xpos
165
object.divePos.y = marker[+1].ypos
166
object.divePos.y -= 0x900000
167
object.originPos.y = marker[+1].ypos
168
object.originPos.y -= 0x900000
169
170
temp0 = 0x700000
171
temp0 *= screen.xcenter
172
temp0 /= 160
173
object.speed = 0x20000
174
object.speed *= screen.xcenter
175
object.speed /= 160
176
177
object.boundsL = marker[+1].xpos
178
object.boundsL -= temp0
179
object.boundsR = marker[+1].xpos
180
object.boundsR += temp0
181
182
object.xvel = -0x10000
183
object.flameAnim = FLAME_ACTIVE
184
object.fireballDropDelay = 120
185
ResetObjectEntity(SLOT_MUSICEVENT_BOSS, TypeName[Music Event], MUSICEVENT_FADETOBOSS, 0, 0)
186
object[SLOT_MUSICEVENT_BOSS].priority = PRIORITY_ACTIVE
187
object.drawOrder = 4
188
player[0].sortedDrawOrder = 5
189
if object[1].type == TypeName[Player 2 Object]
190
player[1].sortedDrawOrder = 5
191
end if
192
object.state++
193
end if
194
break
195
196
case MZEGGMAN_ENTEREGGMAN
197
object.xpos += object.xvel
198
if object.xpos <= object.boundsR
199
object.xpos = object.boundsR
200
object.flameAnim = FLAME_INACTIVE
201
object.state++
202
end if
203
CallFunction(MZEggman_Oscillate)
204
break
205
206
case MZEGGMAN_TAUNT
207
CallFunction(MZEggman_Oscillate)
208
209
object.timer++
210
if object.timer == 16
211
object.timer = 0
212
object.xvel = object.speed
213
FlipSign(object.xvel)
214
object.yvel = 0x10000
215
object.flameAnim = FLAME_ACTIVE
216
object.state++
217
end if
218
break
219
220
case MZEGGMAN_MOVE_L
221
object.yvel -= 0x400
222
object.xpos += object.xvel
223
object.ypos += object.yvel
224
225
if object.xpos <= object.boundsL
226
object.xpos = object.boundsL
227
object.flameAnim = FLAME_INACTIVE
228
object.state++
229
end if
230
CallFunction(MZEggman_HandleFireballErupt)
231
break
232
233
case MZEGGMAN_DROPFIREBALL_L
234
object.yvel -= 0x400
235
object.ypos += object.yvel
236
237
if object.ypos <= object.divePos.y
238
object.ypos = object.divePos.y
239
object.direction = FACING_LEFT
240
object.animation = MZEGGANI_LAUGH_LOOP
241
object.animationTimer = 0
242
CreateTempObject(TypeName[Boss Fireball], 0, object.xpos, object.ypos)
243
object[tempObjectPos].ypos += 0x140000
244
object.state++
245
end if
246
CallFunction(MZEggman_HandleFireballErupt)
247
break
248
249
case MZEGGMAN_DROPPEDFIREBALL_L
250
object.timer++
251
if object.timer == 80
252
object.timer = 0
253
object.xvel = object.speed
254
object.yvel = 0x10000
255
object.animation = MZEGGANI_IDLE
256
object.flameAnim = FLAME_ACTIVE
257
object.state++
258
end if
259
260
CallFunction(MZEggman_HandleFireballErupt)
261
break
262
263
case MZEGGMAN_MOVE_R
264
object.yvel -= 0x400
265
object.xpos += object.xvel
266
object.ypos += object.yvel
267
268
if object.xpos >= object.boundsR
269
object.xpos = object.boundsR
270
object.flameAnim = FLAME_INACTIVE
271
object.state++
272
end if
273
CallFunction(MZEggman_HandleFireballErupt)
274
break
275
276
case MZEGGMAN_DROPFIREBALL_R
277
object.yvel -= 0x400
278
object.ypos += object.yvel
279
280
if object.ypos <= object.divePos.y
281
object.ypos = object.divePos.y
282
object.direction = FACING_RIGHT
283
object.animation = MZEGGANI_LAUGH_LOOP
284
object.animationTimer = 0
285
CreateTempObject(TypeName[Boss Fireball], 0, object.xpos, object.ypos)
286
object[tempObjectPos].ypos += 0x140000
287
object.state++
288
end if
289
CallFunction(MZEggman_HandleFireballErupt)
290
break
291
292
case MZEGGMAN_DROPPEDFIREBALL_R
293
object.timer++
294
if object.timer == 80
295
object.timer = 0
296
object.xvel = object.speed
297
FlipSign(object.xvel)
298
object.yvel = 0x10000
299
object.animation = MZEGGANI_IDLE
300
object.flameAnim = FLAME_INACTIVE
301
object.state = MZEGGMAN_MOVE_L
302
end if
303
304
CallFunction(MZEggman_HandleFireballErupt)
305
break
306
307
case MZEGGMAN_EXPLODE
308
object.timer++
309
temp0 = object.timer
310
temp0 &= 7
311
if temp0 == 4
312
Rand(temp0, 64)
313
temp0 -= 32
314
temp0 <<= 16
315
temp0 += object.xpos
316
Rand(temp1, 48)
317
temp1 -= 24
318
temp1 <<= 16
319
temp1 += object.ypos
320
CreateTempObject(TypeName[Explosion], 0, temp0, temp1)
321
PlaySfx(SfxName[Explosion], false)
322
end if
323
324
if object.timer == 180
325
object.animation = MZEGGANI_TOASTED
326
object.animationTimer = 0
327
object.timer = 0
328
object.direction = FACING_LEFT
329
ResetObjectEntity(SLOT_MUSICEVENT_BOSS, TypeName[Music Event], MUSICEVENT_FADETOSTAGE, 0, 0)
330
object[SLOT_MUSICEVENT_BOSS].priority = PRIORITY_ACTIVE
331
object.state++
332
end if
333
break
334
335
case MZEGGMAN_DEFEATFALL
336
object.ypos += object.yvel
337
object.yvel += 0x1800
338
339
object.timer++
340
if object.timer == 32
341
object.yvel = 0
342
object.timer = 0
343
object.state++
344
end if
345
break
346
347
case MZEGGMAN_DEFEATRISE
348
if object.timer < 40
349
object.ypos += object.yvel
350
object.yvel -= 0x800
351
object.timer++
352
else
353
object.timer = 0
354
object.yvel = 0
355
object.angle = 0
356
object.originPos.y = object.ypos
357
object.state++
358
end if
359
break
360
361
case MZEGGMAN_FLEE
362
CallFunction(MZEggman_Oscillate)
363
364
if object.timer < 8
365
object.timer++
366
else
367
object.timer = 0
368
object.animation = MZEGGANI_PANIC
369
object.animationTimer = 0
370
object.flameAnim = FLAME_EXPLODE
371
object.flameAnimTimer = 0
372
object.priority = PRIORITY_ACTIVE
373
temp0 = tileLayer[0].xsize
374
temp0 <<= 7
375
stage.newXBoundary2 = temp0
376
object.state++
377
end if
378
break
379
380
case MZEGGMAN_ESCAPE
381
CallFunction(MZEggman_Oscillate)
382
object.xpos += 0x40000
383
object.originPos.y -= 0x4000
384
if object.outOfBounds == true
385
object.type = TypeName[Blank Object]
386
object.priority = PRIORITY_BOUNDS
387
end if
388
break
389
390
case MZEGGMAN_HITFREEZE
391
object.hitDelay++
392
if object.hitDelay == 16
393
object.hitDelay = 0
394
object.state = object.nextState
395
end if
396
break
397
398
end switch
399
400
if object.health != 0
401
if object.invincibilityTimer > 0
402
object.invincibilityTimer--
403
end if
404
405
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
406
if object.invincibilityTimer == 0
407
CheckEqual(player[currentPlayer].animation, ANI_HURT)
408
temp0 = checkResult
409
CheckEqual(player[currentPlayer].animation, ANI_DYING)
410
temp0 |= checkResult
411
CheckEqual(player[currentPlayer].animation, ANI_DROWNING)
412
temp0 |= checkResult
413
if temp0 != false
414
if object.animation != MZEGGANI_LAUGH
415
object.animation = MZEGGANI_LAUGH
416
object.animationTimer = 0
417
end if
418
end if
419
420
#platform: USE_STANDALONE
421
BoxCollisionTest(C_TOUCH, object.entityPos, -20, -16, 20, 16, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
422
#endplatform
423
#platform: USE_ORIGINS
424
BoxCollisionTest(C_TOUCH, object.entityPos, -20, -16, 20, 16, currentPlayer, player[currentPlayer].hitboxLeft, player[currentPlayer].hitboxTop, player[currentPlayer].hitboxRight, player[currentPlayer].hitboxBottom)
425
#endplatform
426
if checkResult == true
427
CallFunction(Player_CheckHit)
428
if object.state > MZEGGMAN_TAUNT
429
if object.state != MZEGGMAN_HITFREEZE
430
object.nextState = object.state
431
object.state = MZEGGMAN_HITFREEZE
432
end if
433
end if
434
435
if checkResult == true
436
object.health--
437
if object.health == 0
438
#platform: USE_ORIGINS
439
CallNativeFunction2(NotifyCallback, NOTIFY_KILL_BOSS, 0)
440
CallNativeFunction2(NotifyCallback, NOTIFY_BOSS_END, true)
441
#endplatform
442
player.score += 1000
443
object.drawOrder = 3
444
object.animation = MZEGGANI_DEFEATED
445
object.animationTimer = 0
446
object.flameAnim = FLAME_INACTIVE
447
object.timer = 0
448
object.yvel = 0
449
object.state = MZEGGMAN_EXPLODE
450
else
451
object.animation = MZEGGANI_HIT
452
object.animationTimer = 0
453
object.invincibilityTimer = 32
454
PlaySfx(SfxName[Boss Hit], false)
455
end if
456
end if
457
end if
458
end if
459
next
460
end if
461
462
// Handle Right Bounds
463
if object.state < MZEGGMAN_ESCAPE
464
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
465
temp0 = player[currentPlayer].collisionRight
466
temp0 <<= 16
467
temp0 += player[currentPlayer].xpos
468
temp1 = stage.curXBoundary2
469
temp1 <<= 16
470
if temp0 > temp1
471
player[currentPlayer].xvel = 0
472
player[currentPlayer].speed = 0
473
player[currentPlayer].xpos = temp1
474
temp0 = player[currentPlayer].collisionRight
475
temp0 <<= 16
476
player[currentPlayer].xpos -= temp0
477
end if
478
next
479
end if
480
end event
481
482
483
event ObjectDraw
484
switch object.animation
485
default
486
case MZEGGANI_INVISIBLE
487
break
488
489
case MZEGGANI_IDLE
490
temp0 = object.animationTimer
491
temp0 /= 6
492
object.animationTimer++
493
object.animationTimer %= 12
494
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
495
break
496
497
case MZEGGANI_LAUGH
498
temp0 = object.animationTimer
499
temp0 %= 10
500
temp0 /= 5
501
temp0 += 9
502
object.animationTimer++
503
if object.animationTimer == 50
504
object.animationTimer = 0
505
if player[0].animation != ANI_DYING
506
object.animation = MZEGGANI_IDLE
507
end if
508
end if
509
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
510
break
511
512
case MZEGGANI_LAUGH_LOOP
513
temp0 = object.animationTimer
514
temp0 /= 5
515
temp0 += 9
516
object.animationTimer++
517
object.animationTimer %= 10
518
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
519
break
520
521
case MZEGGANI_HIT
522
temp0 = object.animationTimer
523
temp0 &= 1
524
temp0 += 2
525
object.animationTimer++
526
if object.animationTimer == 30
527
object.animationTimer = 0
528
object.animation = MZEGGANI_IDLE
529
end if
530
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
531
break
532
533
case MZEGGANI_DEFEATED
534
temp0 = object.animationTimer
535
temp0 >>= 5
536
temp0 += 4
537
object.animationTimer++
538
object.animationTimer &= 63
539
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
540
break
541
542
case MZEGGANI_TOASTED
543
DrawSpriteFX(6, FX_FLIP, object.xpos, object.ypos)
544
break
545
546
case MZEGGANI_PANIC
547
temp0 = object.animationTimer
548
temp0 >>= 2
549
temp0 += 7
550
object.animationTimer++
551
object.animationTimer %= 7
552
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
553
break
554
555
end switch
556
557
switch object.flameAnim
558
default
559
case FLAME_INACTIVE
560
break
561
562
case FLAME_ACTIVE
563
temp0 = object.flameAnimTimer
564
temp0 >>= 2
565
temp0 += 11
566
object.flameAnimTimer++
567
object.flameAnimTimer &= 7
568
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
569
break
570
571
case FLAME_EXPLODE
572
temp0 = object.flameAnimTimer
573
temp0 /= 3
574
temp0 += 11
575
object.flameAnimTimer++
576
if object.flameAnimTimer > 21
577
object.flameAnimTimer = 18
578
end if
579
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
580
break
581
582
end switch
583
584
DrawSpriteFX(19, FX_FLIP, object.xpos, object.ypos)
585
end event
586
587
588
event ObjectStartup
589
LoadSpriteSheet("Global/Eggman.gif")
590
591
SpriteFrame(-28, -32, 64, 56, 1, 1)
592
SpriteFrame(-28, -32, 64, 56, 66, 1)
593
SpriteFrame(-28, -32, 64, 56, 131, 1)
594
SpriteFrame(-28, -32, 64, 56, 1, 58)
595
SpriteFrame(-28, -32, 64, 56, 1, 1)
596
SpriteFrame(-28, -32, 64, 56, 1, 58)
597
SpriteFrame(-28, -32, 64, 56, 66, 58)
598
SpriteFrame(-28, -32, 64, 56, 131, 58)
599
SpriteFrame(-28, -32, 64, 56, 66, 1)
600
SpriteFrame(-28, -32, 64, 56, 1, 115)
601
SpriteFrame(-28, -32, 64, 56, 66, 115)
602
SpriteFrame(34, 1, 10, 9, 196, 2)
603
SpriteFrame(33, 0, 15, 11, 196, 12)
604
SpriteFrame(34, -1, 22, 14, 213, 1)
605
SpriteFrame(34, -8, 32, 26, 213, 16)
606
SpriteFrame(34, -1, 22, 14, 213, 1)
607
SpriteFrame(34, -8, 32, 26, 213, 16)
608
SpriteFrame(34, 1, 10, 9, 196, 2)
609
SpriteFrame(33, 0, 15, 11, 196, 12)
610
SpriteFrame(-8, 16, 16, 16, 238, 43)
611
612
// Set up values for every Eggman object
613
foreach (TypeName[Eggman], arrayPos0, ALL_ENTITIES)
614
object[arrayPos0].animation = MZEGGANI_IDLE
615
#platform: USE_STANDALONE
616
object[arrayPos0].health = 8
617
#endplatform
618
#platform: USE_ORIGINS
619
if game.bossOneLife == false
620
object[arrayPos0].health = 8
621
else
622
object[arrayPos0].health = 1
623
end if
624
#endplatform
625
next
626
627
if stage.actNum == 3
628
if screen.xsize == 320
629
// Change the boss arena to match the original game's version
630
SetTileLayerEntry(348, 0, 50, 5)
631
SetTileLayerEntry(349, 0, 51, 5)
632
end if
633
end if
634
end event
635
636
637
// ========================
638
// Editor Events
639
// ========================
640
641
event RSDKDraw
642
DrawSprite(0)
643
DrawSprite(19)
644
end event
645
646
647
event RSDKLoad
648
LoadSpriteSheet("Global/Eggman.gif")
649
SpriteFrame(-28, -32, 64, 56, 1, 1)
650
SpriteFrame(-28, -32, 64, 56, 66, 1)
651
SpriteFrame(-28, -32, 64, 56, 131, 1)
652
SpriteFrame(-28, -32, 64, 56, 1, 58)
653
SpriteFrame(-28, -32, 64, 56, 1, 1)
654
SpriteFrame(-28, -32, 64, 56, 1, 58)
655
SpriteFrame(-28, -32, 64, 56, 66, 58)
656
SpriteFrame(-28, -32, 64, 56, 131, 58)
657
SpriteFrame(-28, -32, 64, 56, 66, 1)
658
SpriteFrame(-28, -32, 64, 56, 1, 115)
659
SpriteFrame(-28, -32, 64, 56, 66, 115)
660
SpriteFrame(34, 1, 10, 9, 196, 2)
661
SpriteFrame(33, 0, 15, 11, 196, 12)
662
SpriteFrame(34, -1, 22, 14, 213, 1)
663
SpriteFrame(34, -8, 32, 26, 213, 16)
664
SpriteFrame(34, -1, 22, 14, 213, 1)
665
SpriteFrame(34, -8, 32, 26, 213, 16)
666
SpriteFrame(34, 1, 10, 9, 196, 2)
667
SpriteFrame(33, 0, 15, 11, 196, 12)
668
SpriteFrame(-8, 16, 16, 16, 238, 43)
669
670
SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
671
end event
672
673