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/CPZ/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 CPZEggman 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.oscillationAngle
17
private alias object.value4 : object.timer
18
private alias object.value5 : object.flameAnim
19
private alias object.value6 : object.flameAnimTimer
20
private alias object.value7 : object.health
21
private alias object.value8 : object.invincibilityTimer
22
private alias object.value9 : object.exploding
23
private alias object.value10 : object.nonStopBopCount
24
25
// Eggman States
26
private alias 0 : CPZEGGMAN_AWAITPLAYER
27
private alias 1 : CPZEGGMAN_BOSSFIGHT
28
private alias 2 : CPZEGGMAN_EXPLODE
29
private alias 3 : CPZEGGMAN_DEFEATFALL
30
private alias 4 : CPZEGGMAN_DEFEATRISE
31
private alias 5 : CPZEGGMAN_FLEE
32
private alias 6 : CPZEGGMAN_ESCAPE
33
34
// Eggman Animations
35
private alias 0 : CPZEGGANI_INVISIBLE
36
private alias 1 : CPZEGGANI_IDLE
37
private alias 2 : CPZEGGANI_LAUGH
38
private alias 3 : CPZEGGANI_HIT
39
private alias 4 : CPZEGGANI_DEFEATED
40
private alias 5 : CPZEGGANI_TOASTED
41
private alias 6 : CPZEGGANI_PANIC
42
43
// Flame Animations
44
private alias 0 : FLAME_INACTIVE
45
private alias 1 : FLAME_ACTIVE
46
private alias 2 : FLAME_EXPLODE
47
48
// Dropper Aliases
49
private alias object.value4 : chemicalDropper.boundsL
50
private alias object.value5 : chemicalDropper.boundsR
51
52
// Dropper States
53
private alias 4 : CHEMICALDROPPER_DESTROYED
54
55
// Music Events
56
private alias 26 : SLOT_MUSICEVENT_BOSS
57
58
private alias 0 : MUSICEVENT_FADETOBOSS
59
private alias 1 : MUSICEVENT_FADETOSTAGE
60
61
// Player Aliases
62
private alias object.xpos : player.xpos
63
private alias object.xvel : player.xvel
64
private alias object.speed : player.speed
65
private alias object.animation : player.animation
66
private alias object.gravity : player.gravity
67
private alias object.collisionRight : player.collisionRight
68
private alias object.value40 : player.hitboxLeft
69
private alias object.value38 : player.hitboxTop
70
private alias object.value41 : player.hitboxRight
71
private alias object.value39 : player.hitboxBottom
72
73
// Achievement Aliases
74
private alias 5 : ACHIEVEMENT_BOBNONSTOP
75
76
77
// ========================
78
// Function Declarations
79
// ========================
80
81
reserve function CPZEggman_Oscillate
82
83
84
// ========================
85
// Tables
86
// ========================
87
88
private table CPZEggman_flameAnimFrameTable
89
7, 8, 8, 7, 7, 16
90
end table
91
92
93
// ========================
94
// Function Definitions
95
// ========================
96
97
private function CPZEggman_Oscillate
98
object.ypos = object.originPos.y
99
Sin256(temp0, object.oscillationAngle)
100
temp0 <<= 10
101
object.ypos += temp0
102
object.oscillationAngle += 2
103
object.oscillationAngle &= 255
104
end function
105
106
107
// ========================
108
// Events
109
// ========================
110
111
event ObjectUpdate
112
switch object.state
113
case CPZEGGMAN_AWAITPLAYER
114
temp0 = object.ixpos
115
temp0 -= screen.xcenter
116
stage.newXBoundary1 = temp0
117
temp0 = object.ixpos
118
temp0 += screen.xcenter
119
stage.newXBoundary2 = temp0
120
if player[0].xpos > object.xpos
121
object.animation = CPZEGGANI_IDLE
122
ResetObjectEntity(SLOT_MUSICEVENT_BOSS, TypeName[Music Event], MUSICEVENT_FADETOBOSS, 0, 0)
123
object[SLOT_MUSICEVENT_BOSS].priority = PRIORITY_ACTIVE
124
object.originPos.y = object.ypos
125
object[+1].type = TypeName[Chemical Dropper]
126
chemicalDropper[+1].boundsL = object.xpos
127
chemicalDropper[+1].boundsL -= 0x700000
128
chemicalDropper[+1].boundsR = object.xpos
129
chemicalDropper[+1].boundsR += 0x700000
130
temp0 = screen.xcenter
131
temp0 += 256
132
temp0 <<= 16
133
object.xpos += temp0
134
object[+1].xpos = object.xpos
135
object[+1].ypos = object.ypos
136
object[+1].originPos.x = object.xpos
137
object[+1].originPos.y = object.ypos
138
object[+1].priority = PRIORITY_ACTIVE
139
object.flameAnim = FLAME_ACTIVE
140
141
#platform: USE_STANDALONE
142
object.health = 8
143
#endplatform
144
#platform: USE_ORIGINS
145
if game.bossOneLife == false
146
object.health = 8
147
else
148
object.health = 1
149
end if
150
#endplatform
151
152
object.priority = PRIORITY_ACTIVE
153
object.state++
154
end if
155
break
156
157
case CPZEGGMAN_BOSSFIGHT
158
break
159
160
case CPZEGGMAN_EXPLODE
161
object.timer++
162
if object.timer == 180
163
object.timer = 0
164
object.animation = CPZEGGANI_TOASTED
165
object.exploding = false
166
object.state++
167
ResetObjectEntity(SLOT_MUSICEVENT_BOSS, TypeName[Music Event], MUSICEVENT_FADETOSTAGE, 0, 0)
168
object[SLOT_MUSICEVENT_BOSS].priority = PRIORITY_ACTIVE
169
temp0 = tileLayer[0].xsize
170
temp0 <<= 7
171
stage.newXBoundary2 = temp0
172
end if
173
break
174
175
case CPZEGGMAN_DEFEATFALL
176
object.ypos += object.yvel
177
object.yvel += 0x1800
178
object.timer++
179
if object.timer == 38
180
object.yvel = 0
181
object.timer = 0
182
object.animationTimer = 0
183
object.state++
184
end if
185
break
186
187
case CPZEGGMAN_DEFEATRISE
188
if object.timer < 48
189
object.ypos += object.yvel
190
object.yvel -= 0x800
191
object.timer++
192
else
193
object.timer = 0
194
object.yvel = 0
195
object.originPos.y = object.ypos
196
object.state++
197
end if
198
break
199
200
case CPZEGGMAN_FLEE
201
object.ypos = object.originPos.y
202
CallFunction(CPZEggman_Oscillate)
203
204
if object.timer < 8
205
object.timer++
206
else
207
object.timer = 0
208
object.animation = CPZEGGANI_PANIC
209
object.animationTimer = 0
210
object.flameAnim = FLAME_EXPLODE
211
object.flameAnimTimer = 0
212
object.direction = FLIP_X
213
object.priority = PRIORITY_ACTIVE
214
temp0 = tileLayer[0].xsize
215
temp0 <<= 7
216
stage.newXBoundary2 = temp0
217
object.state++
218
end if
219
break
220
221
case CPZEGGMAN_ESCAPE
222
object.xpos += 0x40000
223
object.originPos.y -= 0x4000
224
CallFunction(CPZEggman_Oscillate)
225
if object.outOfBounds == true
226
object.type = TypeName[Blank Object]
227
object.priority = PRIORITY_BOUNDS
228
end if
229
break
230
231
end switch
232
233
// If P1's touched the floor, then reset the Bop Non-Stop count for the Achievement
234
if player[0].gravity == GRAVITY_GROUND
235
object.nonStopBopCount = 0
236
end if
237
238
if object.health != 0
239
if object.invincibilityTimer > 0
240
object.invincibilityTimer--
241
GetBit(temp0, object.invincibilityTimer, 0)
242
if temp0 == true
243
SetPaletteEntry(0, 192, 0xE0E0E0)
244
else
245
SetPaletteEntry(0, 192, 0x000000)
246
end if
247
end if
248
249
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
250
if object.invincibilityTimer == 0
251
CheckEqual(player[currentPlayer].animation, ANI_HURT)
252
temp0 = checkResult
253
CheckEqual(player[currentPlayer].animation, ANI_DYING)
254
temp0 |= checkResult
255
CheckEqual(player[currentPlayer].animation, ANI_DROWNING)
256
temp0 |= checkResult
257
if temp0 != false
258
if object.animation != CPZEGGANI_LAUGH
259
object.animation = CPZEGGANI_LAUGH
260
object.animationTimer = 0
261
end if
262
end if
263
264
BoxCollisionTest(C_TOUCH, object.entityPos, -24, -24, 24, 22, currentPlayer, player[currentPlayer].hitboxLeft, player[currentPlayer].hitboxTop, player[currentPlayer].hitboxRight, player[currentPlayer].hitboxBottom)
265
if checkResult == true
266
CallFunction(Player_CheckHit)
267
if checkResult == true
268
object.health--
269
if object.health == 0
270
#platform: USE_ORIGINS
271
CallNativeFunction2(NotifyCallback, NOTIFY_KILL_BOSS, 0)
272
CallNativeFunction2(NotifyCallback, NOTIFY_BOSS_END, 1)
273
#endplatform
274
275
player.score += 1000
276
object.animation = CPZEGGANI_DEFEATED
277
object.animationTimer = 0
278
object.flameAnim = FLAME_INACTIVE
279
object.exploding = true
280
object.originPos.y = object.ypos
281
object.oscillationAngle = object[+1].oscillationAngle
282
object.state++
283
object[+1].state = CHEMICALDROPPER_DESTROYED
284
285
if object.nonStopBopCount >= 7
286
if stage.debugMode == false
287
// Grant the "Bob Non-stop" Achievement
288
CallNativeFunction2(SetAchievement, ACHIEVEMENT_BOBNONSTOP, 100)
289
end if
290
end if
291
else
292
object.animation = CPZEGGANI_HIT
293
object.animationTimer = 0
294
object.invincibilityTimer = 32
295
PlaySfx(SfxName[Boss Hit], false)
296
if currentPlayer == 0
297
if player[0].gravity == GRAVITY_AIR
298
object.nonStopBopCount++
299
end if
300
end if
301
end if
302
end if
303
end if
304
end if
305
next
306
end if
307
308
// Enforce the R Boundary
309
if object.state != CPZEGGMAN_ESCAPE
310
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
311
temp0 = player[currentPlayer].collisionRight
312
temp0 <<= 16
313
temp0 += player[currentPlayer].xpos
314
temp1 = stage.curXBoundary2
315
temp1 <<= 16
316
if temp0 > temp1
317
player[currentPlayer].xvel = 0
318
player[currentPlayer].speed = 0
319
player[currentPlayer].xpos = temp1
320
temp0 = player[currentPlayer].collisionRight
321
temp0 <<= 16
322
player[currentPlayer].xpos -= temp0
323
end if
324
next
325
end if
326
327
if object.exploding == true
328
temp0 = oscillation
329
temp0 &= 7
330
if temp0 == 0
331
Rand(temp0, 48)
332
temp0 -= 24
333
temp0 <<= 16
334
temp0 += object.xpos
335
Rand(temp1, 48)
336
temp1 -= 24
337
temp1 <<= 16
338
temp1 += object.ypos
339
CreateTempObject(TypeName[Explosion], 0, temp0, temp1)
340
object[tempObjectPos].drawOrder = 5
341
PlaySfx(SfxName[Explosion], false)
342
end if
343
end if
344
end event
345
346
347
event ObjectDraw
348
if object.animation != CPZEGGANI_INVISIBLE
349
DrawSpriteFX(6, FX_FLIP, object.xpos, object.ypos)
350
end if
351
352
switch object.animation
353
case CPZEGGANI_IDLE
354
temp0 = object.animationTimer
355
temp0 >>= 3
356
object.animationTimer++
357
object.animationTimer &= 15
358
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
359
break
360
361
case CPZEGGANI_LAUGH
362
temp0 = object.animationTimer
363
temp0 &= 15
364
temp0 >>= 3
365
temp0 += 2
366
object.animationTimer++
367
if object.animationTimer == 50
368
object.animationTimer = 0
369
if player[0].animation != ANI_DYING
370
object.animation = CPZEGGANI_IDLE
371
end if
372
end if
373
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
374
break
375
376
case CPZEGGANI_HIT
377
temp0 = object.animationTimer
378
temp0 &= 1
379
temp0 += 2
380
object.animationTimer++
381
if object.animationTimer == 50
382
object.animationTimer = 0
383
object.animation = CPZEGGANI_IDLE
384
end if
385
DrawSpriteFX(4, FX_FLIP, object.xpos, object.ypos)
386
break
387
388
case CPZEGGANI_DEFEATED
389
temp0 = object.animationTimer
390
temp0 >>= 5
391
temp0 += 4
392
temp0 %= 5
393
object.animationTimer++
394
object.animationTimer &= 63
395
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
396
break
397
398
case CPZEGGANI_TOASTED
399
DrawSpriteFX(5, FX_FLIP, object.xpos, object.ypos)
400
break
401
402
case CPZEGGANI_PANIC
403
temp0 = object.animationTimer
404
temp0 >>= 3
405
object.animationTimer++
406
object.animationTimer &= 15
407
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
408
409
temp0 = object.animationTimer
410
temp0 >>= 2
411
temp0 &= 1
412
if temp0 == 1
413
DrawSpriteFX(15, FX_FLIP, object.xpos, object.ypos)
414
end if
415
break
416
417
end switch
418
419
switch object.flameAnim
420
default
421
case FLAME_INACTIVE
422
break
423
424
case FLAME_ACTIVE
425
GetTableValue(temp0, object.flameAnimTimer, CPZEggman_flameAnimFrameTable)
426
object.flameAnimTimer++
427
if object.flameAnimTimer == 6
428
object.flameAnimTimer = 0
429
end if
430
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
431
break
432
433
case FLAME_EXPLODE
434
temp0 = object.flameAnimTimer
435
temp0 /= 3
436
temp0 += 9
437
object.flameAnimTimer++
438
if object.flameAnimTimer >= 18
439
object.flameAnimTimer = 0
440
temp0 = 7
441
object.flameAnim = FLAME_ACTIVE
442
end if
443
DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)
444
break
445
446
end switch
447
end event
448
449
450
event ObjectStartup
451
CheckCurrentStageFolder("Zone02")
452
if checkResult == true
453
LoadSpriteSheet("Global/EggMobile.gif")
454
455
// 0->5 - Eggman Frames
456
SpriteFrame(-28, -28, 60, 20, 5, 1)
457
SpriteFrame(-28, -28, 60, 20, 66, 1)
458
SpriteFrame(-28, -28, 60, 20, 5, 22)
459
SpriteFrame(-28, -28, 60, 20, 66, 22)
460
SpriteFrame(-28, -28, 60, 20, 5, 43)
461
SpriteFrame(-28, -28, 60, 20, 66, 43)
462
463
// 6 - Eggmobile Body Frame
464
SpriteFrame(-32, -8, 64, 29, 1, 64)
465
466
// 7->9 - Thruster Frames
467
SpriteFrame(31, 4, 12, 8, 66, 65)
468
SpriteFrame(30, 2, 14, 12, 66, 74)
469
SpriteFrame(31, -2, 22, 14, 66, 87)
470
471
// 10->14 - Explosion Flame Frames
472
SpriteFrame(31, -9, 32, 26, 94, 64)
473
SpriteFrame(31, -2, 22, 14, 66, 87)
474
SpriteFrame(31, -9, 32, 26, 94, 64)
475
SpriteFrame(31, 4, 12, 8, 66, 65)
476
SpriteFrame(30, 2, 14, 12, 66, 74)
477
478
// 15 - Sweat Frame
479
SpriteFrame(-3, -28, 11, 8, 79, 65)
480
481
// 16 - Blank Frame
482
SpriteFrame(0, 0, 0, 0, 7, 2)
483
484
if options.vsMode == true
485
foreach (TypeName[Eggman], arrayPos0, ALL_ENTITIES)
486
object[arrayPos0].type = TypeName[Blank Object]
487
next
488
end if
489
else
490
LoadSpriteSheet("MBZ/Objects.gif")
491
492
// 0->5 - Eggman Frames
493
SpriteFrame(-28, -28, 60, 20, 1, 1)
494
SpriteFrame(-28, -28, 60, 20, 62, 1)
495
SpriteFrame(-28, -28, 60, 20, 1, 22)
496
SpriteFrame(-28, -28, 60, 20, 62, 22)
497
SpriteFrame(-28, -28, 60, 20, 1, 43)
498
SpriteFrame(-28, -28, 60, 20, 62, 43)
499
500
// 6 - Eggmobile Body Frame
501
SpriteFrame(-32, -8, 64, 29, 415, 170)
502
503
// 7->9 - Thruster Frames
504
SpriteFrame(31, 4, 12, 8, 57, 90)
505
SpriteFrame(30, 2, 14, 12, 57, 99)
506
SpriteFrame(31, -2, 22, 14, 34, 97)
507
508
// 10->14 - Explosion Flame Frames
509
SpriteFrame(31, -9, 32, 26, 72, 86)
510
SpriteFrame(31, -2, 22, 14, 34, 97)
511
SpriteFrame(31, -9, 32, 26, 72, 86)
512
SpriteFrame(31, 4, 12, 8, 57, 90)
513
SpriteFrame(30, 2, 14, 12, 57, 99)
514
515
// 15 - Sweat Frame
516
SpriteFrame(-3, -28, 11, 8, 45, 88)
517
518
// 16 - Blank Frame
519
SpriteFrame(0, 0, 0, 0, 7, 2)
520
end if
521
end event
522
523
524
// ========================
525
// Editor Events
526
// ========================
527
528
event RSDKDraw
529
DrawSprite(1)
530
DrawSprite(0)
531
532
if editor.showGizmos == true
533
editor.drawingOverlay = true
534
535
// Draw lines connecting the whole network of boss objects
536
DrawArrow(object.xpos, object.ypos, object[+1].xpos, object[+1].ypos, 0, 255, 0) // Chemical Dropper
537
538
// Draw arena bounds
539
temp0 = 212; temp1 = 113; temp2 = 212; temp3 = 128;
540
CallFunction(EditorHelpers_DrawHitbox)
541
542
// Draw Robotnik's movement bounds
543
temp0 = object.xpos
544
temp0 -= 0x700000
545
546
temp1 = object.xpos
547
temp1 += 0x700000
548
549
DrawLine(temp0, object.ypos, temp1, object.ypos, 0, 255, 0)
550
551
editor.drawingOverlay = false
552
end if
553
end event
554
555
556
event RSDKLoad
557
CheckCurrentStageFolder("Zone02")
558
if checkResult == true
559
LoadSpriteSheet("Global/EggMobile.gif")
560
561
// 0 - Eggman Frame
562
SpriteFrame(-28, -28, 60, 20, 5, 1)
563
564
// 1 - Eggmobile Body Frame
565
SpriteFrame(-32, -8, 64, 29, 1, 64)
566
else
567
LoadSpriteSheet("MBZ/Objects.gif")
568
569
// 0 - Eggman Frame
570
SpriteFrame(-28, -28, 60, 20, 1, 1)
571
572
// 1 - Eggmobile Body Frame
573
SpriteFrame(-32, -8, 64, 29, 415, 170)
574
end if
575
576
SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
577
end event
578
579