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/LZ/Eggman.txt
1483 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 LZEggman 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.originPos.x
15
private alias object.value1 : object.originPos.y
16
private alias object.value2 : object.defeated
17
private alias object.value3 : object.oscillateAngle.y
18
private alias object.value4 : object.oscillateAngle.x
19
private alias object.value5 : object.timer
20
private alias object.value6 : object.flameAnim
21
private alias object.value7 : object.flameAnimTimer
22
private alias object.value8 : object.health
23
private alias object.value9 : object.invincibilityTimer
24
private alias object.value10 : object.gotHit
25
26
// Eggman States
27
private alias 0 : LZEGGMAN_AWAITPLAYER
28
private alias 1 : LZEGGMAN_NODE1
29
private alias 2 : LZEGGMAN_NODE2
30
private alias 3 : LZEGGMAN_NODE3
31
private alias 4 : LZEGGMAN_NODE4
32
private alias 5 : LZEGGMAN_LASTNODE
33
private alias 6 : LZEGGMAN_REACHEDEND
34
private alias 7 : LZEGGMAN_ESCAPE
35
36
// Eggman Animations
37
private alias 0 : LZEGGANI_INVISIBLE
38
private alias 1 : LZEGGANI_IDLE
39
private alias 2 : LZEGGANI_LAUGH
40
private alias 3 : LZEGGANI_HIT
41
private alias 4 : LZEGGANI_DEFEATED
42
private alias 5 : LZEGGANI_TOASTED
43
private alias 6 : LZEGGANI_PANIC
44
45
// Flame Animations
46
private alias 0 : FLAME_INACTIVE
47
private alias 1 : FLAME_ACTIVE
48
private alias 2 : FLAME_EXPLODE
49
50
// Music Events
51
private alias 26 : SLOT_MUSICEVENT_BOSS
52
53
private alias 0 : MUSICEVENT_FADETOBOSS
54
private alias 1 : MUSICEVENT_FADETOSTAGE
55
private alias 2 : MUSICEVENT_TRANSITION
56
57
// Player Aliases
58
private alias object.xpos : player.xpos
59
private alias object.ypos : player.ypos
60
private alias object.xvel : player.xvel
61
private alias object.speed : player.speed
62
private alias object.animation : player.animation
63
private alias object.value40 : player.hitboxLeft
64
private alias object.value38 : player.hitboxTop
65
private alias object.value41 : player.hitboxRight
66
private alias object.value39 : player.hitboxBottom
67
68
// Achievement Aliases
69
private alias 6 : ACHIEVEMENT_FLAWLESSPURSUIT
70
71
72
// ========================
73
// Function Declarations
74
// ========================
75
76
reserve function LZEggman_Oscillate
77
reserve function LZEggman_HandleMovement
78
79
80
// ========================
81
// Tables
82
// ========================
83
84
private table LZEggman_nodePositionTable[10]
85
86
87
// ========================
88
// Function Definitions
89
// ========================
90
91
private function LZEggman_Oscillate
92
Sin256(temp0, object.oscillateAngle.y)
93
temp0 <<= 10
94
object.ypos += temp0
95
96
object.oscillateAngle.y += 2
97
object.oscillateAngle.y &= 0xFF
98
end function
99
100
101
private function LZEggman_HandleMovement
102
object.originPos.x += object.xvel
103
object.originPos.y += object.yvel
104
105
object.xpos = object.originPos.x
106
object.ypos = object.originPos.y
107
end function
108
109
110
// ========================
111
// Events
112
// ========================
113
114
event ObjectUpdate
115
#platform: USE_ORIGINS
116
// cool stuff
117
CallNativeFunction2(NotifyCallback, NOTIFY_DEBUGPRINT, object.state)
118
#endplatform
119
120
switch object.state
121
case LZEGGMAN_AWAITPLAYER
122
GetTableValue(temp0, 0, LZEggman_nodePositionTable)
123
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
124
if player[currentPlayer].xpos >= temp0
125
object.xvel = 0x6000
126
object.yvel = -0x18000
127
object.originPos.y = object.ypos
128
object.oscillateAngle.y = 0
129
object.state++
130
object.priority = PRIORITY_ACTIVE
131
ResetObjectEntity(SLOT_MUSICEVENT_BOSS, TypeName[Music Event], MUSICEVENT_FADETOBOSS, 0, 0)
132
object[SLOT_MUSICEVENT_BOSS].priority = PRIORITY_ACTIVE
133
end if
134
next
135
CallFunction(LZEggman_HandleMovement)
136
137
if object.state == LZEGGMAN_AWAITPLAYER
138
CallFunction(LZEggman_Oscillate)
139
end if
140
break
141
142
case LZEGGMAN_NODE1
143
temp1 = -2
144
145
GetTableValue(temp0, 1, LZEggman_nodePositionTable)
146
if object.originPos.x >= temp0
147
object.originPos.x = temp0
148
object.xvel = 0
149
temp1++
150
end if
151
152
GetTableValue(temp0, 2, LZEggman_nodePositionTable)
153
if object.originPos.y <= temp0
154
object.originPos.y = temp0
155
object.yvel = 0
156
temp1++
157
end if
158
159
if temp1 == 0
160
object.xvel = 0x14000
161
object.yvel = -0x20000
162
object.state++
163
end if
164
CallFunction(LZEggman_HandleMovement)
165
break
166
167
case LZEGGMAN_NODE2
168
temp1 = -2
169
170
GetTableValue(temp0, 3, LZEggman_nodePositionTable)
171
if object.originPos.x >= temp0
172
object.originPos.x = temp0
173
object.xvel = 0
174
temp1++
175
end if
176
177
GetTableValue(temp0, 4, LZEggman_nodePositionTable)
178
if object.originPos.y <= temp0
179
object.originPos.y = temp0
180
object.yvel = 0
181
temp1++
182
end if
183
184
if temp1 == 0
185
object.yvel = -0x18000
186
object.state++
187
end if
188
189
CallFunction(LZEggman_HandleMovement)
190
break
191
192
case LZEGGMAN_NODE3
193
GetTableValue(temp0, 5, LZEggman_nodePositionTable)
194
if object.originPos.y <= temp0
195
object.originPos.y = temp0
196
if object.defeated == false
197
object.xvel = 0x14000
198
object.yvel--
199
else
200
object.xvel = 0x28000
201
object.yvel--
202
end if
203
object.direction = FLIP_X
204
object.originPos.x = object.xpos
205
object.state++
206
CallFunction(LZEggman_HandleMovement)
207
else
208
object.oscillateAngle.x += 2
209
object.oscillateAngle.x &= 0xFF
210
Cos256(temp0, object.oscillateAngle.x)
211
if temp0 > 0
212
object.direction = FLIP_X
213
else
214
object.direction = FLIP_NONE
215
end if
216
Sin256(object.xpos, object.oscillateAngle.x)
217
object.xpos <<= 12
218
object.xpos += object.originPos.x
219
220
temp0 = object.yvel
221
temp1 = 0x7FFFFFFF
222
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
223
if player[currentPlayer].ypos < temp1
224
temp1 = player[currentPlayer].ypos
225
end if
226
next
227
228
temp1 -= object.originPos.y
229
if temp1 >= 0
230
temp1 -= 0x480000
231
if temp1 >= 0
232
temp0 >>= 1
233
temp1 -= 0x280000
234
if temp1 >= 0
235
temp0 >>= 1
236
temp1 -= 0x280000
237
if temp1 >= 0
238
temp0 = 0
239
end if
240
end if
241
end if
242
end if
243
244
if object.defeated == true
245
temp0 <<= 1
246
end if
247
248
if temp0 == 0
249
object.ypos = object.originPos.y
250
CallFunction(LZEggman_Oscillate)
251
else
252
object.originPos.y = object.ypos
253
object.oscillateAngle.y = 0
254
object.originPos.y += temp0
255
object.ypos = object.originPos.y
256
end if
257
end if
258
break
259
260
case LZEGGMAN_NODE4
261
temp1 = -2
262
263
GetTableValue(temp0, 6, LZEggman_nodePositionTable)
264
if object.originPos.x >= temp0
265
object.originPos.x = temp0
266
object.xvel = 0
267
temp1++
268
end if
269
270
GetTableValue(temp0, 7, LZEggman_nodePositionTable)
271
if object.originPos.y <= temp0
272
object.originPos.y = temp0
273
object.yvel = 0
274
temp1++
275
end if
276
277
if temp1 == 0
278
if object.defeated == false
279
object.direction = FLIP_NONE
280
end if
281
object.oscillateAngle.y = 0
282
object.state++
283
end if
284
285
CallFunction(LZEggman_HandleMovement)
286
break
287
288
case LZEGGMAN_LASTNODE
289
temp2 = 0
290
if object.defeated == false
291
// Check if player excaped to the top
292
GetTableValue(temp0, 8, LZEggman_nodePositionTable)
293
GetTableValue(temp1, 9, LZEggman_nodePositionTable)
294
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
295
if player[currentPlayer].xpos >= temp0
296
if player[currentPlayer].ypos <= temp1
297
temp2 = true
298
object.timer = 50
299
object.animation = LZEGGANI_DEFEATED
300
object.animationTimer = 32
301
end if
302
end if
303
next
304
else
305
temp2 = true
306
object.timer = 1
307
end if
308
309
if temp2 == true
310
ResetObjectEntity(SLOT_MUSICEVENT_BOSS, TypeName[Music Event], MUSICEVENT_FADETOSTAGE, 0, 0)
311
object[SLOT_MUSICEVENT_BOSS].priority = PRIORITY_ACTIVE
312
object.state++
313
end if
314
315
CallFunction(LZEggman_HandleMovement)
316
CallFunction(LZEggman_Oscillate)
317
break
318
319
case LZEGGMAN_REACHEDEND
320
object.timer--
321
if object.timer == 0
322
object.timer = 0
323
object.xvel = 0x40000
324
object.yvel = -0x4000
325
object.priority = PRIORITY_ACTIVE
326
object.animation = LZEGGANI_PANIC
327
object.animationTimer = 0
328
object.flameAnim = FLAME_EXPLODE
329
object.originPos.y = object.ypos
330
object.state++
331
if stage.debugMode == false
332
if object.gotHit == false
333
// Grant the "Flawless Pursuit" Achievement
334
CallNativeFunction2(SetAchievement, ACHIEVEMENT_FLAWLESSPURSUIT, 100)
335
end if
336
end if
337
#platform: USE_ORIGINS
338
CallNativeFunction2(NotifyCallback, NOTIFY_KILL_BOSS, 0)
339
CallNativeFunction2(NotifyCallback, NOTIFY_BOSS_END, true)
340
#endplatform
341
else
342
if object.timer == 24
343
object.animation = LZEGGANI_IDLE
344
object.animationTimer = 0
345
object.direction = FLIP_X
346
end if
347
end if
348
349
CallFunction(LZEggman_HandleMovement)
350
351
if object.state == LZEGGMAN_REACHEDEND
352
CallFunction(LZEggman_Oscillate)
353
end if
354
break
355
356
case LZEGGMAN_ESCAPE
357
if object.outOfBounds == true
358
ResetObjectEntity(object.entityPos, TypeName[Blank Object], 0, 0, 0)
359
object.defeated = false
360
else
361
CallFunction(LZEggman_HandleMovement)
362
end if
363
break
364
365
end switch
366
367
if object.health != 0
368
if object.invincibilityTimer > 0
369
object.invincibilityTimer--
370
end if
371
372
// Check interaction with players
373
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
374
if object.invincibilityTimer == 0
375
376
// CHeck if the player is in one of the following animations
377
CheckEqual(player[currentPlayer].animation, ANI_HURT)
378
temp0 = checkResult
379
CheckEqual(player[currentPlayer].animation, ANI_DYING)
380
temp0 |= checkResult
381
CheckEqual(player[currentPlayer].animation, ANI_DROWNING)
382
temp0 |= checkResult
383
384
if temp0 != 0
385
// Player is in one of those animations, start laughing at them
386
if object.animation != LZEGGANI_LAUGH
387
object.animation = LZEGGANI_LAUGH
388
object.animationTimer = 0
389
end if
390
391
if currentPlayer == 0
392
object.gotHit = true
393
end if
394
end if
395
396
// Check player collision
397
#platform: USE_STANDALONE
398
BoxCollisionTest(C_TOUCH, object.entityPos, -20, -16, 20, 16, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
399
#endplatform
400
#platform: USE_ORIGINS
401
BoxCollisionTest(C_TOUCH, object.entityPos, -20, -16, 20, 16, currentPlayer, player[currentPlayer].hitboxLeft, player[currentPlayer].hitboxTop, player[currentPlayer].hitboxRight, player[currentPlayer].hitboxBottom)
402
#endplatform
403
if checkResult == true
404
405
// See if the player should be hit or is attacking
406
CallFunction(Player_CheckHit)
407
408
if checkResult == true
409
object.health--
410
if object.health == 0
411
#platform: USE_ORIGINS
412
CallNativeFunction2(NotifyCallback, NOTIFY_KILL_BOSS, 0)
413
CallNativeFunction2(NotifyCallback, NOTIFY_BOSS_END, 1)
414
#endplatform
415
// Final hit, increase score and start exploding
416
player.score += 1000
417
object.animation = LZEGGANI_DEFEATED
418
object.animationTimer = 0
419
object.defeated = true
420
else
421
// Simply got hit, do the hit stuff
422
object.animation = LZEGGANI_HIT
423
object.animationTimer = 0
424
object.invincibilityTimer = 32
425
PlaySfx(SfxName[Boss Hit], false)
426
end if
427
end if
428
end if
429
end if
430
next
431
end if
432
433
if object.defeated == true
434
temp0 = oscillation
435
temp0 &= 7
436
if temp0 == 0
437
Rand(temp0, 96)
438
temp0 -= 48
439
temp0 <<= 16
440
temp0 += object.xpos
441
Rand(temp1, 48)
442
temp1 -= 24
443
temp1 <<= 16
444
temp1 += object.ypos
445
CreateTempObject(TypeName[Explosion], 0, temp0, temp1)
446
PlaySfx(SfxName[Explosion], false)
447
end if
448
end if
449
end event
450
451
452
event ObjectDraw
453
switch object.animation
454
default
455
case LZEGGANI_INVISIBLE
456
break
457
458
case LZEGGANI_IDLE
459
temp0 = object.animationTimer
460
temp0 /= 6
461
object.animationTimer++
462
object.animationTimer %= 12
463
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
464
break
465
466
case LZEGGANI_LAUGH
467
temp0 = object.animationTimer
468
temp0 %= 10
469
temp0 /= 5
470
temp0 += 9
471
object.animationTimer++
472
if object.animationTimer == 50
473
object.animationTimer = 0
474
if player[0].animation != ANI_DYING
475
object.animation = LZEGGANI_IDLE
476
end if
477
end if
478
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
479
break
480
481
case LZEGGANI_HIT
482
temp0 = object.animationTimer
483
temp0 &= 1
484
temp0 += 2
485
object.animationTimer++
486
if object.animationTimer == 30
487
object.animationTimer = 0
488
object.animation = LZEGGANI_IDLE
489
end if
490
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
491
break
492
493
case LZEGGANI_DEFEATED
494
temp0 = object.animationTimer
495
temp0 >>= 5
496
temp0 += 4
497
object.animationTimer++
498
object.animationTimer &= 63
499
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
500
break
501
502
case LZEGGANI_TOASTED
503
DrawSpriteFX(6, FX_FLIP, object.xpos, object.ypos)
504
break
505
506
case LZEGGANI_PANIC
507
temp0 = object.animationTimer
508
temp0 >>= 2
509
temp0 += 7
510
object.animationTimer++
511
object.animationTimer %= 7
512
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
513
break
514
515
end switch
516
517
switch object.flameAnim
518
default
519
case FLAME_INACTIVE
520
break
521
522
case FLAME_ACTIVE
523
temp0 = object.flameAnimTimer
524
temp0 >>= 2
525
temp0 += 11
526
object.flameAnimTimer++
527
object.flameAnimTimer &= 7
528
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
529
break
530
531
case FLAME_EXPLODE
532
temp0 = object.flameAnimTimer
533
temp0 /= 3
534
temp0 += 11
535
object.flameAnimTimer++
536
if object.flameAnimTimer > 21
537
object.flameAnimTimer = 18
538
end if
539
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
540
break
541
542
end switch
543
end event
544
545
546
event ObjectStartup
547
LoadSpriteSheet("Global/Eggman.gif")
548
549
// Eggman frames
550
SpriteFrame(-28, -32, 64, 56, 1, 1)
551
SpriteFrame(-28, -32, 64, 56, 66, 1)
552
SpriteFrame(-28, -32, 64, 56, 131, 1)
553
SpriteFrame(-28, -32, 64, 56, 1, 58)
554
SpriteFrame(-28, -32, 64, 56, 1, 1)
555
SpriteFrame(-28, -32, 64, 56, 1, 58)
556
SpriteFrame(-28, -32, 64, 56, 66, 58)
557
SpriteFrame(-28, -32, 64, 56, 131, 58)
558
SpriteFrame(-28, -32, 64, 56, 66, 1)
559
SpriteFrame(-28, -32, 64, 56, 1, 115)
560
SpriteFrame(-28, -32, 64, 56, 66, 115)
561
SpriteFrame(34, 1, 10, 9, 196, 2)
562
SpriteFrame(33, 0, 15, 11, 196, 12)
563
SpriteFrame(34, -1, 22, 14, 213, 1)
564
SpriteFrame(34, -8, 32, 26, 213, 16)
565
SpriteFrame(34, -1, 22, 14, 213, 1)
566
SpriteFrame(34, -8, 32, 26, 213, 16)
567
SpriteFrame(34, 1, 10, 9, 196, 2)
568
SpriteFrame(33, 0, 15, 11, 196, 12)
569
570
// Setup values
571
foreach (TypeName[Eggman], arrayPos0, ALL_ENTITIES)
572
573
// Set position points for changing behaviours
574
// (Think of how he turns after reaching a certain point, etc.)
575
576
// First Node (X only)
577
temp0 = -0x700000
578
temp0 += object[arrayPos0].xpos
579
SetTableValue(temp0, 0, LZEggman_nodePositionTable)
580
581
// Node 1 (X & Y)
582
temp0 = 0x380000
583
temp0 += object[arrayPos0].xpos
584
SetTableValue(temp0, 1, LZEggman_nodePositionTable)
585
586
temp0 = -0xC00000
587
temp0 += object[arrayPos0].ypos
588
SetTableValue(temp0, 2, LZEggman_nodePositionTable)
589
590
// Node 2 (X & Y)
591
temp0 = 0x600000
592
temp0 += object[arrayPos0].xpos
593
SetTableValue(temp0, 3, LZEggman_nodePositionTable)
594
595
temp0 = -0x1000000
596
temp0 += object[arrayPos0].ypos
597
SetTableValue(temp0, 4, LZEggman_nodePositionTable)
598
599
// Node 3 (Y only)
600
temp0 = -0x4C00000
601
temp0 += object[arrayPos0].ypos
602
SetTableValue(temp0, 5, LZEggman_nodePositionTable)
603
604
// Node 4 (X & Y)
605
temp0 = 0x13C0000
606
temp0 += object[arrayPos0].xpos
607
SetTableValue(temp0, 6, LZEggman_nodePositionTable)
608
609
temp0 = -0x5000000
610
temp0 += object[arrayPos0].ypos
611
SetTableValue(temp0, 7, LZEggman_nodePositionTable)
612
613
// Last Node (X & Y)
614
temp0 = 0xB80000
615
temp0 += object[arrayPos0].xpos
616
SetTableValue(temp0, 8, LZEggman_nodePositionTable)
617
618
temp0 = -0x4D00000
619
temp0 += object[arrayPos0].ypos
620
SetTableValue(temp0, 9, LZEggman_nodePositionTable)
621
622
// Store the starting position
623
object[arrayPos0].originPos.x = object[arrayPos0].xpos
624
object[arrayPos0].originPos.y = object[arrayPos0].ypos
625
626
// Make it in the first animation state
627
object[arrayPos0].animation = LZEGGANI_IDLE
628
629
#platform: USE_ORIGINS
630
if game.bossOneLife == false
631
// It takes 8 hits to drown this egg
632
object[arrayPos0].health = 8
633
else
634
// It takes 2 hits now?
635
// Normally this cheat only makes it 1, wonder what's up with that...
636
object[arrayPos0].health = 2
637
end if
638
#endplatform
639
640
#platform: USE_STANDALONE
641
// It takes 8 hits to drown this egg
642
object[arrayPos0].health = 8
643
#endplatform
644
next
645
646
end event
647
648
649
// ========================
650
// Editor Events
651
// ========================
652
653
event RSDKDraw
654
DrawSprite(0)
655
656
if editor.showGizmos == true
657
editor.drawingOverlay = true
658
659
// TODO: draw node path, that'd be cool
660
661
editor.drawingOverlay = false
662
end if
663
end event
664
665
666
event RSDKLoad
667
LoadSpriteSheet("Global/Eggman.gif")
668
SpriteFrame(-28, -32, 64, 56, 1, 1)
669
670
SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
671
end event
672
673