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/Enemies/Rexon.txt
1480 views
1
// ----------------------------------
2
// RSDK Project: Sonic 2
3
// Script Description: Rexon Object
4
// Script Author: Christian Whitehead/Simon Thomley
5
// Unpacked by Rubberduckycooly's script unpacker
6
// ----------------------------------
7
8
// ========================
9
// Aliases
10
// ========================
11
12
private alias object.value0 : object.timer
13
14
private alias object.value1 : object.head.magnitude
15
private alias object.value2 : object.head.amplitude
16
private alias object.value3 : object.head.x
17
private alias object.value4 : object.head.y
18
19
// Piece order is desending in height (IE piece 1 is right next to the head, piece 4 is right next to the shell)
20
21
private alias object.value5 : object.piece1.magnitude
22
private alias object.value6 : object.piece1.amplitude
23
private alias object.value7 : object.piece1.x
24
private alias object.value8 : object.piece1.y
25
26
private alias object.value9 : object.piece2.magnitude
27
private alias object.value10 : object.piece2.amplitude
28
private alias object.value11 : object.piece2.x
29
private alias object.value12 : object.piece2.y
30
31
private alias object.value13 : object.piece3.magnitude
32
private alias object.value14 : object.piece3.amplitude
33
private alias object.value15 : object.piece3.x
34
private alias object.value16 : object.piece3.y
35
36
private alias object.value17 : object.piece4.magnitude
37
private alias object.value18 : object.piece4.amplitude
38
private alias object.value19 : object.piece4.x
39
private alias object.value20 : object.piece4.y
40
41
private alias object.value21 : object.head.direction
42
private alias object.value22 : object.piece1.direction
43
private alias object.value23 : object.piece2.direction
44
private alias object.value24 : object.piece3.direction
45
46
private alias object.value25 : object.startPos.x
47
48
// Fragment alias, holds the entityPos of the Rexon it originated from
49
private alias object.value0 : object.parentRexon
50
51
private alias 0 : REXON_AWAITPLAYER
52
private alias 1 : REXON_RISE1
53
private alias 2 : REXON_RISE2
54
private alias 3 : REXON_RISE3
55
private alias 4 : REXON_RISE4
56
private alias 5 : REXON_RISE5
57
private alias 6 : REXON_SHOOT
58
private alias 7 : REXON_SHELL
59
private alias 8 : REXON_FRAGMENT
60
61
// Player Aliases
62
private alias object.xpos : player.xpos
63
64
private alias object.value40 : player.hitboxLeft
65
private alias object.value38 : player.hitboxTop
66
private alias object.value41 : player.hitboxRight
67
private alias object.value39 : player.hitboxBottom
68
69
70
// ========================
71
// Function Declarations
72
// ========================
73
74
reserve function Rexon_Reset
75
reserve function Rexon_DebugDraw
76
reserve function Rexon_DebugSpawn
77
78
79
// ========================
80
// Function Definitions
81
// ========================
82
83
private function Rexon_Reset
84
temp0 = object[arrayPos0].startPos.x
85
temp1 = object[arrayPos0].ypos
86
ResetObjectEntity(object[arrayPos0].entityPos, TypeName[Rexon], 0, temp0, temp1)
87
object[arrayPos0].startPos.x = temp0
88
object[arrayPos0].xvel = -0x2000
89
object[arrayPos0].timer = 128
90
object[arrayPos0].head.amplitude = 368
91
object[arrayPos0].piece1.amplitude = 368
92
object[arrayPos0].piece2.amplitude = 368
93
object[arrayPos0].piece3.amplitude = 368
94
object[arrayPos0].piece4.amplitude = 368
95
end function
96
97
98
private function Rexon_DebugDraw
99
DrawSpriteFX(3, FX_FLIP, object.xpos, object.ypos)
100
end function
101
102
103
private function Rexon_DebugSpawn
104
CreateTempObject(TypeName[Rexon], 0, object.xpos, object.ypos)
105
object[tempObjectPos].startPos.x = object.xpos
106
arrayPos0 = object[tempObjectPos].entityPos
107
108
CallFunction(Rexon_Reset)
109
end function
110
111
112
// ========================
113
// Events
114
// ========================
115
116
event ObjectUpdate
117
switch object.state
118
case REXON_AWAITPLAYER
119
// Swimming around, waiting for the player
120
object.priority = PRIORITY_ACTIVE
121
122
object.xpos += object.xvel
123
object.timer--
124
if object.timer == 0
125
object.timer = 128
126
object.direction ^= FLIP_X
127
FlipSign(object.xvel)
128
end if
129
130
// Check if the player's in range
131
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
132
if object.direction == FLIP_NONE
133
BoxCollisionTest(C_TOUCH, object.entityPos, -160, -256, 96, 256, currentPlayer, -1, -1, 1, 1)
134
else
135
BoxCollisionTest(C_TOUCH, object.entityPos, -96, -256, 160, 256, currentPlayer, -1, -1, 1, 1)
136
end if
137
138
if checkResult == true
139
if player[currentPlayer].xpos > object.xpos
140
object.direction = FLIP_X
141
else
142
object.direction = FLIP_NONE
143
end if
144
object.state++
145
end if
146
next
147
break
148
149
case REXON_RISE1
150
if object.head.magnitude >= 3200
151
object.state++
152
object.head.magnitude = 3200
153
end if
154
155
object.head.magnitude += 640
156
break
157
158
case REXON_RISE2
159
if object.piece1.magnitude >= 3200
160
object.state++
161
object.piece1.magnitude = 3200
162
end if
163
164
object.piece1.magnitude += 640
165
object.head.amplitude += 2
166
break
167
168
case REXON_RISE3
169
if object.piece2.magnitude >= 3200
170
object.state++
171
object.piece2.magnitude = 3200
172
end if
173
174
object.piece2.magnitude += 640
175
object.head.amplitude += 2
176
object.piece1.amplitude += 2
177
break
178
179
case REXON_RISE4
180
if object.piece3.magnitude >= 3200
181
object.state++
182
object.piece3.magnitude = 3200
183
end if
184
185
object.piece3.magnitude += 640
186
object.head.amplitude += 2
187
object.piece1.amplitude += 2
188
object.piece2.amplitude += 2
189
break
190
191
case REXON_RISE5
192
if object.piece4.magnitude >= 2688
193
object.state++
194
object.piece4.magnitude = 2688
195
end if
196
197
object.piece4.magnitude += 640
198
object.head.amplitude += 2
199
object.piece1.amplitude += 2
200
object.piece2.amplitude += 2
201
object.piece3.amplitude += 2
202
break
203
204
case REXON_SHOOT
205
if object.head.direction == FLIP_NONE
206
object.head.amplitude++
207
if object.head.amplitude == 384
208
object.frame = 0 // Close the Rexon's mouth
209
end if
210
211
if object.head.amplitude >= 416
212
object.head.direction = FLIP_X
213
end if
214
else
215
object.head.amplitude--
216
if object.head.amplitude == 368
217
object.frame = 1 // Make the Rexon open wide
218
end if
219
220
if object.head.amplitude <= 352
221
object.head.direction = FLIP_NONE
222
CreateTempObject(TypeName[Rexon Shot], 0, object.head.x, object.head.y)
223
if object.direction == FLIP_NONE
224
object[tempObjectPos].xvel = -0x10000
225
object[tempObjectPos].xpos -= 0x100000
226
else
227
object[tempObjectPos].xvel = 0x10000
228
object[tempObjectPos].xpos += 0x100000
229
end if
230
object[tempObjectPos].yvel = 0x8000
231
object[tempObjectPos].ypos += 0x40000
232
end if
233
end if
234
235
if object.piece1.direction == FLIP_NONE
236
object.piece1.amplitude++
237
if object.piece1.amplitude >= 416
238
object.piece1.direction = FLIP_X
239
end if
240
else
241
object.piece1.amplitude--
242
if object.piece1.amplitude <= 352
243
object.piece1.direction = FLIP_NONE
244
end if
245
end if
246
247
if object.piece2.direction == FLIP_NONE
248
object.piece2.amplitude++
249
if object.piece2.amplitude >= 416
250
object.piece2.direction = FLIP_X
251
end if
252
else
253
object.piece2.amplitude--
254
if object.piece2.amplitude <= 352
255
object.piece2.direction = FLIP_NONE
256
end if
257
end if
258
259
if object.piece3.direction == FLIP_NONE
260
object.piece3.amplitude++
261
if object.piece3.amplitude >= 416
262
object.piece3.direction = FLIP_X
263
end if
264
else
265
object.piece3.amplitude--
266
if object.piece3.amplitude <= 352
267
object.piece3.direction = FLIP_NONE
268
end if
269
end if
270
break
271
272
case REXON_SHELL
273
// Just a lone shell, don't do anything
274
break
275
276
case REXON_FRAGMENT
277
arrayPos0 = object.parentRexon
278
if object[arrayPos0].state != REXON_SHELL
279
// If the Rexon isn't actually defeated, then despawn
280
object.type = TypeName[Blank Object]
281
end if
282
283
object.xpos += object.xvel
284
object.ypos += object.yvel
285
object.yvel += 0x3800
286
287
if object.outOfBounds == true
288
object.type = TypeName[Blank Object]
289
end if
290
break
291
292
end switch
293
294
// Calculate the positions of all body fragments in this (rather lengthy) process
295
296
temp0 = object.xpos
297
if object.direction == FLIP_NONE
298
temp0 -= 0x1C0000
299
else
300
temp0 += 0x1C0000
301
end if
302
303
temp1 = object.ypos
304
temp1 += 0x110000
305
306
temp2 = object.piece4.amplitude
307
temp2 >>= 1
308
if object.direction == FLIP_X
309
temp2 -= 0xC0
310
FlipSign(temp2)
311
temp2 += 0xC0
312
temp2 &= 0xFF
313
end if
314
Cos256(object.piece4.x, temp2)
315
object.piece4.x *= object.piece4.magnitude
316
object.piece4.x += temp0
317
Sin256(object.piece4.y, temp2)
318
object.piece4.y *= object.piece4.magnitude
319
object.piece4.y += temp1
320
321
temp2 = object.piece3.amplitude
322
temp2 >>= 1
323
if object.direction == FLIP_X
324
temp2 -= 0xC0
325
FlipSign(temp2)
326
temp2 += 0xC0
327
temp2 &= 0xFF
328
end if
329
Cos256(object.piece3.x, temp2)
330
object.piece3.x *= object.piece3.magnitude
331
object.piece3.x += object.piece4.x
332
Sin256(object.piece3.y, temp2)
333
object.piece3.y *= object.piece3.magnitude
334
object.piece3.y += object.piece4.y
335
336
temp2 = object.piece2.amplitude
337
temp2 >>= 1
338
if object.direction == FLIP_X
339
temp2 -= 0xC0
340
FlipSign(temp2)
341
temp2 += 0xC0
342
temp2 &= 0xFF
343
end if
344
Cos256(object.piece2.x, temp2)
345
object.piece2.x *= object.piece2.magnitude
346
object.piece2.x += object.piece3.x
347
Sin256(object.piece2.y, temp2)
348
object.piece2.y *= object.piece2.magnitude
349
object.piece2.y += object.piece3.y
350
351
temp2 = object.piece1.amplitude
352
temp2 >>= 1
353
if object.direction == FLIP_X
354
temp2 -= 0xC0
355
FlipSign(temp2)
356
temp2 += 0xC0
357
temp2 &= 0xFF
358
end if
359
Cos256(object.piece1.x, temp2)
360
object.piece1.x *= object.piece1.magnitude
361
object.piece1.x += object.piece2.x
362
Sin256(object.piece1.y, temp2)
363
object.piece1.y *= object.piece1.magnitude
364
object.piece1.y += object.piece2.y
365
366
temp2 = object.head.amplitude
367
temp2 >>= 1
368
if object.direction == FLIP_X
369
temp2 -= 0xC0
370
FlipSign(temp2)
371
temp2 += 0xC0
372
temp2 &= 0xFF
373
end if
374
Cos256(object.head.x, temp2)
375
object.head.x *= object.head.magnitude
376
object.head.x += object.piece1.x
377
Sin256(object.head.y, temp2)
378
object.head.y *= object.head.magnitude
379
object.head.y += object.piece1.y
380
381
if object.state != REXON_FRAGMENT
382
if object.outOfBounds == true
383
temp0 = object.xpos
384
object.xpos = object.startPos.x
385
if object.outOfBounds == true
386
arrayPos0 = object.entityPos
387
CallFunction(Rexon_Reset)
388
else
389
object.xpos = temp0
390
end if
391
end if
392
393
temp6 = object.xpos
394
temp7 = object.ypos
395
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
396
// Provide a shell box for players to stand on
397
BoxCollisionTest(C_SOLID, object.entityPos, -16, -8, 16, 8, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
398
if object.state != REXON_SHELL
399
// Check if the head's been hit
400
object.xpos = object.head.x
401
object.ypos = object.head.y
402
BoxCollisionTest(C_TOUCH, object.entityPos, -8, -8, 8, 8, currentPlayer, player[currentPlayer].hitboxLeft, player[currentPlayer].hitboxTop, player[currentPlayer].hitboxRight, player[currentPlayer].hitboxBottom)
403
if checkResult == true
404
// Create neck fragment pieces to make the Rexon fall apart
405
CreateTempObject(TypeName[Rexon], 0, object.piece1.x, object.piece1.y)
406
object[tempObjectPos].xvel = -0x8000
407
object[tempObjectPos].state = REXON_FRAGMENT
408
object[tempObjectPos].direction = object.direction
409
object[tempObjectPos].parentRexon = object.entityPos
410
411
CreateTempObject(TypeName[Rexon], 0, object.piece2.x, object.piece2.y)
412
object[tempObjectPos].xvel = 0x10000
413
object[tempObjectPos].state = REXON_FRAGMENT
414
object[tempObjectPos].direction = object.direction
415
object[tempObjectPos].parentRexon = object.entityPos
416
417
CreateTempObject(TypeName[Rexon], 0, object.piece3.x, object.piece3.y)
418
object[tempObjectPos].xvel = -0x10000
419
object[tempObjectPos].state = REXON_FRAGMENT
420
object[tempObjectPos].direction = object.direction
421
object[tempObjectPos].parentRexon = object.entityPos
422
423
CreateTempObject(TypeName[Rexon], 0, object.piece4.x, object.piece4.y)
424
object[tempObjectPos].xvel = 0x8000
425
object[tempObjectPos].state = REXON_FRAGMENT
426
object[tempObjectPos].direction = object.direction
427
object[tempObjectPos].parentRexon = object.entityPos
428
429
temp4 = object.startPos.x
430
temp5 = object.direction
431
CallFunction(Player_BadnikBreak)
432
if object.type != TypeName[Rexon]
433
// If the Rexon has been destroyed, turn it back into a Rexon so that its shell platform stays
434
object.type = TypeName[Rexon]
435
object.startPos.x = temp4
436
object.direction = temp5
437
object.priority = PRIORITY_ACTIVE
438
object.state = REXON_SHELL
439
end if
440
end if
441
442
// Check hitboxes for all body parts individually, too
443
object.xpos = object.piece1.x
444
object.ypos = object.piece1.y
445
BoxCollisionTest(C_TOUCH, object.entityPos, -8, -8, 8, 8, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
446
if checkResult == true
447
CallFunction(Player_Hit)
448
end if
449
450
object.xpos = object.piece2.x
451
object.ypos = object.piece2.y
452
BoxCollisionTest(C_TOUCH, object.entityPos, -8, -8, 8, 8, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
453
if checkResult == true
454
CallFunction(Player_Hit)
455
end if
456
457
object.xpos = object.piece3.x
458
object.ypos = object.piece3.y
459
BoxCollisionTest(C_TOUCH, object.entityPos, -8, -8, 8, 8, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
460
if checkResult == true
461
CallFunction(Player_Hit)
462
end if
463
464
object.xpos = object.piece4.x
465
object.ypos = object.piece4.y
466
BoxCollisionTest(C_TOUCH, object.entityPos, -8, -8, 8, 8, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
467
if checkResult == true
468
CallFunction(Player_Hit)
469
end if
470
end if
471
next
472
473
object.xpos = temp6
474
object.ypos = temp7
475
end if
476
end event
477
478
479
event ObjectDraw
480
switch object.state
481
case REXON_RISE1
482
case REXON_RISE2
483
case REXON_RISE3
484
case REXON_RISE4
485
case REXON_RISE5
486
case REXON_SHOOT
487
DrawSpriteFX(2, FX_FLIP, object.piece4.x, object.piece4.y)
488
DrawSpriteFX(2, FX_FLIP, object.piece3.x, object.piece3.y)
489
DrawSpriteFX(2, FX_FLIP, object.piece2.x, object.piece2.y)
490
DrawSpriteFX(2, FX_FLIP, object.piece1.x, object.piece1.y)
491
DrawSpriteFX(object.frame, FX_FLIP, object.head.x, object.head.y)
492
// [Fallthrough to shell drawing]
493
case REXON_AWAITPLAYER
494
case REXON_SHELL
495
DrawSpriteFX(3, FX_FLIP, object.xpos, object.ypos)
496
break
497
498
case REXON_FRAGMENT
499
DrawSpriteFX(2, FX_FLIP, object.xpos, object.ypos)
500
break
501
502
end switch
503
end event
504
505
506
event ObjectStartup
507
CheckCurrentStageFolder("Zone05")
508
if checkResult == true
509
LoadSpriteSheet("HTZ/Objects.gif")
510
511
// Head Frame, Mouth Closed
512
SpriteFrame(-19, -6, 23, 16, 143, 123)
513
514
// Head Frame, Mouth Open
515
SpriteFrame(-19, -6, 23, 16, 45, 55)
516
517
// Neck Frame
518
SpriteFrame(-8, -8, 16, 16, 52, 38)
519
520
// Body Frame
521
SpriteFrame(-16, -8, 32, 16, 91, 105)
522
else
523
LoadSpriteSheet("MBZ/Objects.gif")
524
525
// Duplicate data of HTZ sheet data, appears broken in-game
526
527
// Head Frame, Mouth Closed
528
SpriteFrame(-19, -6, 23, 16, 143, 123)
529
530
// Head Frame, Mouth Open
531
SpriteFrame(-19, -6, 23, 16, 45, 55)
532
533
// Neck Frame
534
SpriteFrame(-8, -8, 16, 16, 52, 38)
535
536
// Body Frame
537
SpriteFrame(-16, -8, 32, 16, 91, 105)
538
end if
539
540
foreach (TypeName[Rexon], arrayPos0, ALL_ENTITIES)
541
object[arrayPos0].startPos.x = object[arrayPos0].xpos
542
CallFunction(Rexon_Reset)
543
next
544
545
SetTableValue(TypeName[Rexon], DebugMode_ObjCount, DebugMode_TypesTable)
546
SetTableValue(Rexon_DebugDraw, DebugMode_ObjCount, DebugMode_DrawTable)
547
SetTableValue(Rexon_DebugSpawn, DebugMode_ObjCount, DebugMode_SpawnTable)
548
DebugMode_ObjCount++
549
end event
550
551
552
// ========================
553
// Editor Events
554
// ========================
555
556
event RSDKDraw
557
object.head.amplitude = 368
558
object.head.magnitude = 3200
559
560
object.piece1.amplitude = 368
561
object.piece1.magnitude = 3200
562
563
object.piece2.amplitude = 368
564
object.piece2.magnitude = 3200
565
566
object.piece3.amplitude = 368
567
object.piece3.magnitude = 3200
568
569
object.piece4.amplitude = 368
570
object.piece4.magnitude = 3200
571
572
temp0 = object.xpos
573
temp0 -= 0x1C0000
574
575
temp1 = object.ypos
576
temp1 += 0x110000
577
578
temp2 = object.piece4.amplitude
579
temp2 >>= 1
580
Cos256(object.piece4.x, temp2)
581
object.piece4.x *= object.piece4.magnitude
582
object.piece4.x += temp0
583
Sin256(object.piece4.y, temp2)
584
object.piece4.y *= object.piece4.magnitude
585
object.piece4.y += temp1
586
587
temp2 = object.piece3.amplitude
588
temp2 >>= 1
589
Cos256(object.piece3.x, temp2)
590
object.piece3.x *= object.piece3.magnitude
591
object.piece3.x += object.piece4.x
592
Sin256(object.piece3.y, temp2)
593
object.piece3.y *= object.piece3.magnitude
594
object.piece3.y += object.piece4.y
595
596
temp2 = object.piece2.amplitude
597
temp2 >>= 1
598
Cos256(object.piece2.x, temp2)
599
object.piece2.x *= object.piece2.magnitude
600
object.piece2.x += object.piece3.x
601
Sin256(object.piece2.y, temp2)
602
object.piece2.y *= object.piece2.magnitude
603
object.piece2.y += object.piece3.y
604
605
temp2 = object.piece1.amplitude
606
temp2 >>= 1
607
Cos256(object.piece1.x, temp2)
608
object.piece1.x *= object.piece1.magnitude
609
object.piece1.x += object.piece2.x
610
Sin256(object.piece1.y, temp2)
611
object.piece1.y *= object.piece1.magnitude
612
object.piece1.y += object.piece2.y
613
614
temp2 = object.head.amplitude
615
temp2 >>= 1
616
Cos256(object.head.x, temp2)
617
object.head.x *= object.head.magnitude
618
object.head.x += object.piece1.x
619
Sin256(object.head.y, temp2)
620
object.head.y *= object.head.magnitude
621
object.head.y += object.piece1.y
622
623
DrawSpriteXY(1, object.piece4.x, object.piece4.y)
624
DrawSpriteXY(1, object.piece3.x, object.piece3.y)
625
DrawSpriteXY(1, object.piece2.x, object.piece2.y)
626
DrawSpriteXY(1, object.piece1.x, object.piece1.y)
627
DrawSpriteXY(0, object.head.x, object.head.y)
628
DrawSpriteXY(2, object.xpos, object.ypos)
629
end event
630
631
632
event RSDKLoad
633
CheckCurrentStageFolder("Zone05")
634
if checkResult == true
635
LoadSpriteSheet("HTZ/Objects.gif")
636
SpriteFrame(-19, -6, 23, 16, 143, 123)
637
SpriteFrame(-8, -8, 16, 16, 52, 38)
638
SpriteFrame(-16, -8, 32, 16, 91, 105)
639
else
640
LoadSpriteSheet("MBZ/Objects.gif")
641
SpriteFrame(-19, -6, 23, 16, 143, 123)
642
SpriteFrame(-8, -8, 16, 16, 52, 38)
643
SpriteFrame(-16, -8, 32, 16, 91, 105)
644
end if
645
646
// Ported Rexons have it set, but new ones don't
647
// While it probably meant something in the original game, in this game it doesn't do anything
648
SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
649
end event
650
651