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/Shellcracker.txt
1478 views
1
// ----------------------------------
2
// RSDK Project: Sonic 2
3
// Script Description: Shellcracker 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
private alias object.value1 : object.startPos.x
14
private alias object.value2 : object.startPos.y
15
private alias object.value3 : object.armLength
16
private alias object.value4 : object.canExtendArm
17
private alias object.value31 : object.wrapOffset.y
18
19
// States
20
private alias 0 : SHELLCRACKER_MOVING
21
private alias 1 : SHELLCRACKER_PREPAREARMEXTEND
22
private alias 2 : SHELLCRACKER_EXTENDARM
23
private alias 3 : SHELLCRACKER_ARMEXTENDED
24
private alias 4 : SHELLCRACKER_RETRACTARM
25
private alias 5 : SHELLCRACKER_ARMDEBRIS
26
27
// Player Aliases
28
private alias object.value40 : player.hitboxLeft
29
private alias object.value38 : player.hitboxTop
30
private alias object.value41 : player.hitboxRight
31
private alias object.value39 : player.hitboxBottom
32
33
// Path ID Aliases
34
private alias 0 : PATH_A
35
36
37
// ========================
38
// Function Declarations
39
// ========================
40
41
reserve function Shellcracker_Setup
42
reserve function Shellcracker_DebugDraw
43
reserve function Shellcracker_DebugSpawn
44
reserve function Shellcracker_CheckPlayerInRange
45
reserve function Shellcracker_CheckOffScreen
46
47
48
// ========================
49
// Function Definitions
50
// ========================
51
52
private function Shellcracker_Setup
53
if object[arrayPos0].propertyValue == 0
54
object[arrayPos0].direction = FLIP_NONE
55
object[arrayPos0].xvel = 0x4000
56
else
57
object[arrayPos0].direction = FLIP_X
58
object[arrayPos0].xvel = -0x4000
59
end if
60
61
object[arrayPos0].frame = 0
62
object[arrayPos0].timer = 320
63
object[arrayPos0].armLength = 0x140000
64
object[arrayPos0].canExtendArm = false
65
object[arrayPos0].state = SHELLCRACKER_MOVING
66
object[arrayPos0].priority = PRIORITY_BOUNDS
67
end function
68
69
70
private function Shellcracker_DebugDraw
71
DrawSpriteFX(0, FX_FLIP, object.xpos, object.ypos)
72
end function
73
74
75
private function Shellcracker_DebugSpawn
76
CreateTempObject(TypeName[Shellcracker], object.direction, object.xpos, object.ypos)
77
arrayPos0 = object[tempObjectPos].entityPos
78
object[arrayPos0].startPos.x = object.xpos
79
object[arrayPos0].startPos.y = object.ypos
80
CallFunction(Shellcracker_Setup)
81
end function
82
83
84
private function Shellcracker_CheckPlayerInRange
85
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
86
if object.direction == FLIP_NONE
87
BoxCollisionTest(C_TOUCH, object.entityPos, 0, -256, 96, 256, currentPlayer, -1, -1, 1, 1)
88
else
89
BoxCollisionTest(C_TOUCH, object.entityPos, -96, -256, 0, 256, currentPlayer, -1, -1, 1, 1)
90
end if
91
92
if checkResult == true
93
object.timer = 0
94
object.frame = 3
95
object.state = SHELLCRACKER_EXTENDARM
96
end if
97
next
98
end function
99
100
101
private function Shellcracker_CheckOffScreen
102
if object.outOfBounds == true
103
temp0 = object.xpos
104
temp1 = object.ypos
105
106
object.xpos = object.startPos.x
107
object.ypos = object.startPos.y
108
object.ypos += object.wrapOffset.y
109
if object.outOfBounds == true
110
arrayPos0 = object.entityPos
111
CallFunction(Shellcracker_Setup)
112
else
113
object.xpos = temp0
114
object.ypos = temp1
115
end if
116
end if
117
end function
118
119
120
// ========================
121
// Events
122
// ========================
123
124
event ObjectUpdate
125
switch object.state
126
case SHELLCRACKER_MOVING
127
object.priority = PRIORITY_ACTIVE
128
object.xpos += object.xvel
129
130
object.timer--
131
if object.timer == 0
132
object.frame = 0
133
object.animationTimer = 0
134
object.timer = 40
135
object.state = SHELLCRACKER_PREPAREARMEXTEND
136
end if
137
138
ObjectTileGrip(CSIDE_FLOOR, 0, 12, PATH_A)
139
if checkResult == 0
140
object.frame = 0
141
object.animationTimer = 0
142
FlipSign(object.xvel)
143
object.timer = 60
144
object.state = SHELLCRACKER_PREPAREARMEXTEND
145
end if
146
147
object.frame = object.animationTimer
148
object.frame >>= 4
149
object.animationTimer++
150
if object.animationTimer >= 48
151
object.animationTimer = 0
152
end if
153
154
CallFunction(Shellcracker_CheckPlayerInRange)
155
if object.state == SHELLCRACKER_EXTENDARM
156
object.timer = 10
157
object.canExtendArm = true
158
object.frame = 0
159
object.state = SHELLCRACKER_PREPAREARMEXTEND
160
end if
161
162
CallFunction(Shellcracker_CheckOffScreen)
163
break
164
165
case SHELLCRACKER_PREPAREARMEXTEND
166
object.timer--
167
if object.timer == 0
168
object.timer = 320
169
object.state = SHELLCRACKER_MOVING
170
if object.canExtendArm == true
171
object.canExtendArm = false
172
object.timer = 0
173
object.frame = 3
174
object.state = SHELLCRACKER_EXTENDARM
175
else
176
CallFunction(Shellcracker_CheckPlayerInRange)
177
end if
178
end if
179
180
CallFunction(Shellcracker_CheckOffScreen)
181
break
182
183
case SHELLCRACKER_EXTENDARM
184
if object.armLength < 0x480000
185
object.armLength += 0x40000
186
else
187
object.timer = 8
188
object.state = SHELLCRACKER_ARMEXTENDED
189
end if
190
191
CallFunction(Shellcracker_CheckOffScreen)
192
break
193
194
case SHELLCRACKER_ARMEXTENDED
195
object.timer--
196
if object.timer == 0
197
object.state = SHELLCRACKER_RETRACTARM
198
end if
199
200
CallFunction(Shellcracker_CheckOffScreen)
201
break
202
203
case SHELLCRACKER_RETRACTARM
204
if object.armLength > 0x140000
205
object.armLength -= 0x40000
206
else
207
object.frame = 0
208
object.timer = 40
209
object.state = SHELLCRACKER_PREPAREARMEXTEND
210
end if
211
212
CallFunction(Shellcracker_CheckOffScreen)
213
break
214
215
case SHELLCRACKER_ARMDEBRIS
216
arrayPos0 = object.timer
217
if object[arrayPos0].type == TypeName[Shellcracker]
218
object.type = TypeName[Blank Object]
219
end if
220
221
object.xpos += object.xvel
222
object.ypos += object.yvel
223
object.yvel += 0x3800
224
225
temp1 = object.ypos
226
temp1 >>= 16
227
temp1 -= camera[0].ypos
228
Abs(temp1)
229
temp1 -= 32
230
if temp1 >= screen.ycenter
231
object.type = TypeName[Blank Object]
232
end if
233
break
234
235
end switch
236
237
temp6 = object.xpos
238
temp7 = object.ypos
239
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
240
if object.state < SHELLCRACKER_ARMDEBRIS
241
BoxCollisionTest(C_TOUCH, object.entityPos, -16, -8, 16, 8, currentPlayer, player[currentPlayer].hitboxLeft, player[currentPlayer].hitboxTop, player[currentPlayer].hitboxRight, player[currentPlayer].hitboxBottom)
242
if checkResult == true
243
CreateTempObject(TypeName[Shellcracker], 0, object.xpos, object.ypos)
244
object[tempObjectPos].armLength = object.armLength
245
object[tempObjectPos].direction = object.direction
246
object[tempObjectPos].state = SHELLCRACKER_ARMDEBRIS
247
object[tempObjectPos].timer = object.entityPos
248
if object.direction == FLIP_NONE
249
object[tempObjectPos].xvel = 0x40000
250
else
251
object[tempObjectPos].xvel = -0x40000
252
end if
253
254
CallFunction(Player_BadnikBreak)
255
end if
256
257
if object.type == TypeName[Shellcracker]
258
if object.direction == FLIP_NONE
259
object.xpos += object.armLength
260
else
261
object.xpos -= object.armLength
262
end if
263
object.ypos -= 0x80000
264
265
BoxCollisionTest(C_TOUCH, object.entityPos, -10, -7, 10, 7, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
266
if checkResult == true
267
CallFunction(Player_Hit)
268
end if
269
270
object.xpos = temp6
271
object.ypos = temp7
272
end if
273
end if
274
next
275
end event
276
277
278
event ObjectDraw
279
// Draw The Dude:tm:
280
if object.state < SHELLCRACKER_ARMDEBRIS
281
DrawSpriteFX(object.frame, FX_FLIP, object.xpos, object.ypos)
282
end if
283
284
if object.state >= SHELLCRACKER_EXTENDARM
285
temp1 = object.ypos
286
temp1 -= 0x20000
287
temp2 = object.armLength
288
289
// Draw Arm
290
temp7 = 0
291
while temp7 < 7
292
temp0 = object.xpos
293
if object.direction == FLIP_NONE
294
temp0 -= 0xA0000
295
else
296
temp0 += 0xA0000
297
end if
298
299
if temp2 < 0x180000
300
temp2 = 0x180000
301
end if
302
303
if object.direction == FLIP_NONE
304
temp0 += temp2
305
else
306
temp0 -= temp2
307
end if
308
DrawSpriteFX(4, FX_FLIP, temp0, temp1)
309
temp2 -= 0x80000
310
temp7++
311
loop
312
313
// Draw Shell
314
temp0 = object.xpos
315
if object.direction == FLIP_NONE
316
temp0 += object.armLength
317
else
318
temp0 -= object.armLength
319
end if
320
temp1 = object.ypos
321
temp1 -= 0x80000
322
DrawSpriteFX(5, FX_FLIP, temp0, temp1)
323
end if
324
end event
325
326
327
event ObjectStartup
328
CheckCurrentStageFolder("Zone09")
329
if checkResult == true
330
LoadSpriteSheet("MPZ/Objects.gif")
331
SpriteFrame(-24, -19, 56, 31, 199, 30) // ShellCracker (Moving) - Frame 1 - #0
332
SpriteFrame(-24, -19, 56, 31, 199, 62) // ShellCracker (Moving) - Frame 2 - #1
333
SpriteFrame(-24, -19, 56, 31, 199, 94) // ShellCracker (Moving) - Frame 3 - #2
334
SpriteFrame(-24, -12, 47, 24, 208, 126) // ShellCracker (Extending Arm) - #3
335
SpriteFrame(-4, -4, 8, 8, 190, 53) // Arm Node - #4
336
SpriteFrame(-12, -11, 24, 22, 174, 30) // Shell - #5
337
else
338
LoadSpriteSheet("MBZ/Objects.gif")
339
340
// These frame positions are just copied from MPZ's, they don't look quite right with MBZ
341
SpriteFrame(-24, -19, 56, 31, 199, 30) // ShellCracker (Moving) - Frame 1 - #0
342
SpriteFrame(-24, -19, 56, 31, 199, 62) // ShellCracker (Moving) - Frame 2 - #1
343
SpriteFrame(-24, -19, 56, 31, 199, 94) // ShellCracker (Moving) - Frame 3 - #2
344
SpriteFrame(-24, -12, 47, 24, 208, 126) // ShellCracker (Extending Arm) - #3
345
SpriteFrame(-4, -4, 8, 8, 190, 53) // Arm Node - #4
346
SpriteFrame(-12, -11, 24, 22, 174, 30) // Shell - #5
347
end if
348
349
foreach (TypeName[Shellcracker], arrayPos0, ALL_ENTITIES)
350
object[arrayPos0].startPos.x = object[arrayPos0].xpos
351
object[arrayPos0].startPos.y = object[arrayPos0].ypos
352
object[arrayPos0].propertyValue ^= 1
353
CallFunction(Shellcracker_Setup)
354
next
355
SetTableValue(TypeName[Shellcracker], DebugMode_ObjCount, DebugMode_TypesTable)
356
SetTableValue(Shellcracker_DebugDraw, DebugMode_ObjCount, DebugMode_DrawTable)
357
SetTableValue(Shellcracker_DebugSpawn, DebugMode_ObjCount, DebugMode_SpawnTable)
358
DebugMode_ObjCount++
359
end event
360
361
362
// ========================
363
// Editor Events
364
// ========================
365
366
event RSDKEdit
367
if editor.returnVariable == true
368
switch editor.variableID
369
case EDIT_VAR_PROPVAL // property value
370
checkResult = object.propertyValue
371
break
372
373
case 0 // direction
374
checkResult = object.propertyValue
375
break
376
377
end switch
378
else
379
switch editor.variableID
380
case EDIT_VAR_PROPVAL // property value
381
object.propertyValue = editor.variableValue
382
break
383
384
case 0 // direction
385
object.propertyValue = editor.variableValue
386
break
387
388
end switch
389
end if
390
end event
391
392
393
event RSDKDraw
394
object.direction = object.propertyValue
395
object.direction ^= FLIP_X
396
DrawSpriteFX(0, FX_FLIP, object.xpos, object.ypos)
397
end event
398
399
400
event RSDKLoad
401
CheckCurrentStageFolder("Zone09")
402
if checkResult == true
403
LoadSpriteSheet("MPZ/Objects.gif")
404
SpriteFrame(-24, -19, 56, 31, 199, 30)
405
else
406
LoadSpriteSheet("MBZ/Objects.gif")
407
SpriteFrame(-24, -19, 56, 31, 132, 377) // Decomp note - using fixed frame here
408
end if
409
410
AddEditorVariable("direction")
411
SetActiveVariable("direction")
412
AddEnumVariable("Left", 0)
413
AddEnumVariable("Right", 1)
414
end event
415
416