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/Global/BrokenMonitor.txt
1480 views
1
// ----------------------------------
2
// RSDK Project: Sonic 2
3
// Script Description: Broken Monitor 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.contentsPos.y
13
private alias object.value1 : object.timer
14
private alias object.value3 : object.rewardPlayer
15
private alias object.value4 : object.drawIndex
16
17
// Monitor type aliases
18
private alias 0 : MONITOR_BLANK
19
private alias 1 : MONITOR_RINGS
20
private alias 2 : MONITOR_SHIELD_BLUE
21
private alias 3 : MONITOR_INVINCIBILITY
22
private alias 4 : MONITOR_SPEEDSHOES
23
private alias 5 : MONITOR_1UP_SONIC // In Origins with game.coinMode set to true, these give coins instead
24
private alias 6 : MONITOR_1UP_TAILS
25
private alias 7 : MONITOR_1UP_KNUX
26
private alias 8 : MONITOR_SUPER
27
private alias 9 : MONITOR_SHIELD_BUBBLE
28
private alias 10 : MONITOR_SHIELD_FIRE
29
private alias 11 : MONITOR_SHIELD_LIGHTNING
30
private alias 12 : MONITOR_EGGMAN
31
private alias 13 : MONITOR_TELEPORT
32
private alias 14 : MONITOR_RANDOM
33
private alias 14 : MONITOR_DEBUG_SPIKES // This is strange... spikes shouldn't be here... yet is is.
34
private alias 15 : MONITOR_DEBUG_SHIELD
35
private alias 16 : MONITOR_DEBUG_EMERALDS
36
private alias 17 : MONITOR_1UP_AMY // Origins exclusive
37
38
// Monitor states
39
private alias 0 : MONITOR_STATE_RISE
40
private alias 1 : MONITOR_STATE_FADE
41
private alias 2 : MONITOR_STATE_IDLE
42
43
// VSGame States
44
private alias 1 : VSGAME_TELEPORT
45
46
// Player aliases
47
private alias object.type : player.type
48
private alias object.xpos : player.xpos
49
private alias object.ypos : player.ypos
50
private alias object.speed : player.speed
51
private alias object.value0 : player.rings
52
private alias object.value3 : player.drownTimer
53
private alias object.value4 : player.drownLevel
54
private alias object.value6 : player.speedShoesTimer
55
private alias object.value7 : player.invincibleTimer
56
private alias object.value16 : player.isSidekick
57
private alias object.value37 : player.shield
58
59
// Shields
60
private alias 0 : SHIELD_NONE
61
private alias 1 : SHIELD_NORMAL
62
private alias 2 : SHIELD_BUBBLE
63
private alias 3 : SHIELD_FIRE
64
private alias 4 : SHIELD_LIGHTNING
65
66
// Super States
67
private alias 1 : SUPERSTATE_SUPER
68
69
// Shield Type Aliases
70
private alias 3 : SHIELDTYPE_RAND_S3
71
72
// Game Modes
73
private alias 2 : MODE_TIMEATTACK
74
75
// Music Events
76
private alias 25 : SLOT_MUSICEVENT_CHANGE
77
78
private alias 2 : MUSICEVENT_TRANSITION
79
80
// Tracks
81
private alias 2 : TRACK_INVINCIBLE
82
83
// Global Variable ID Aliases
84
private alias 25 : GLOBAL_PLAYERLIVES
85
86
87
// ========================
88
// Function Declarations
89
// ========================
90
91
reserve function BrokenMonitor_Blank
92
93
94
// ========================
95
// Static Values
96
// ========================
97
98
public value BrokenMonitor_ResetDrownMusic = 0
99
100
101
// ========================
102
// Function Definitions
103
// ========================
104
105
private function BrokenMonitor_Blank
106
// Do nothing!
107
end function
108
109
110
// ========================
111
// Events
112
// ========================
113
114
event ObjectUpdate
115
switch object.state
116
case MONITOR_STATE_RISE
117
if object.timer < 0
118
object.contentsPos.y += object.timer
119
object.timer += 0x1800
120
else
121
object.timer = 0
122
end if
123
124
if object.timer == 0
125
object.state = MONITOR_STATE_FADE
126
object.inkEffect = INK_ALPHA
127
currentPlayer = object.rewardPlayer
128
switch object.propertyValue
129
case MONITOR_BLANK
130
break
131
132
case MONITOR_RINGS
133
player[currentPlayer].rings += 10
134
if ringPan == 0
135
PlaySfx(SfxName[Ring L], false)
136
SetSfxAttributes(SfxName[Ring L], -1, -100)
137
ringPan = 1
138
else
139
PlaySfx(SfxName[Ring R], false)
140
SetSfxAttributes(SfxName[Ring R], -1, 100)
141
ringPan = 0
142
end if
143
144
if player[currentPlayer].rings > 999
145
player[currentPlayer].rings = 999
146
end if
147
148
if player[0].rings >= ringExtraLife
149
if options.gameMode != MODE_TIMEATTACK
150
// this one doesn't have 2P global array code, it's just like this
151
#platform: USE_ORIGINS
152
if game.coinMode == false
153
player.lives++
154
else
155
CallNativeFunction2(NotifyCallback, NOTIFY_ADD_COIN, 1)
156
end if
157
#endplatform
158
#platform: USE_STANDALONE
159
player.lives++
160
#endplatform
161
PlaySfx(SfxName[Life], false)
162
PauseMusic()
163
ResetObjectEntity(SLOT_MUSICEVENT_CHANGE, TypeName[Music Event], MUSICEVENT_TRANSITION, 0, 0)
164
object[SLOT_MUSICEVENT_CHANGE].priority = PRIORITY_ACTIVE
165
end if
166
167
ringExtraLife += 100
168
if ringExtraLife > 300
169
ringExtraLife = 1000
170
end if
171
end if
172
break
173
174
case MONITOR_SHIELD_BLUE
175
PlaySfx(SfxName[Blue Shield], false)
176
arrayPos0 = playerCount
177
arrayPos0 += currentPlayer
178
player[currentPlayer].shield = SHIELD_NORMAL
179
180
if Player_superState != SUPERSTATE_SUPER
181
if object[arrayPos0].type != invincibilityType
182
CallFunction(Player_ApplyShield)
183
end if
184
end if
185
break
186
187
case MONITOR_INVINCIBILITY
188
if Player_superState != SUPERSTATE_SUPER
189
arrayPos0 = playerCount
190
arrayPos0 += currentPlayer
191
ResetObjectEntity(arrayPos0, invincibilityType, 0, player[currentPlayer].xpos, player[currentPlayer].ypos)
192
object[arrayPos0].priority = PRIORITY_ACTIVE
193
player[currentPlayer].invincibleTimer = 1260
194
PlayMusic(TRACK_INVINCIBLE)
195
end if
196
break
197
198
case MONITOR_SPEEDSHOES
199
if SpeedUpMusic != 0
200
if player[currentPlayer].speedShoesTimer == 0
201
CallFunction(SpeedUpMusic)
202
end if
203
end if
204
205
player[currentPlayer].speedShoesTimer = 1320
206
CallFunction(Player_UpdatePhysicsState)
207
break
208
209
case MONITOR_1UP_SONIC
210
case MONITOR_1UP_TAILS
211
case MONITOR_1UP_KNUX
212
#platform: USE_ORIGINS
213
case MONITOR_1UP_AMY
214
if game.coinMode == false
215
#endplatform
216
// global variable "array" (yes, this is actually how its done)
217
arrayPos0 = GLOBAL_PLAYERLIVES
218
#platform: USE_DECOMP
219
arrayPos0 = VarName[player.lives]
220
#endplatform
221
if player[currentPlayer].isSidekick == false
222
arrayPos0 += currentPlayer
223
end if
224
225
global[arrayPos0]++
226
#platform: USE_ORIGINS
227
else
228
CallNativeFunction2(NotifyCallback, NOTIFY_ADD_COIN, 1)
229
end if
230
#endplatform
231
232
PlaySfx(SfxName[Life], false)
233
PauseMusic()
234
ResetObjectEntity(SLOT_MUSICEVENT_CHANGE, TypeName[Music Event], MUSICEVENT_TRANSITION, 0, 0)
235
object[SLOT_MUSICEVENT_CHANGE].priority = PRIORITY_ACTIVE
236
break
237
238
case MONITOR_SUPER
239
currentPlayer = 0
240
player[0].rings += 50
241
if Player_superState != SUPERSTATE_SUPER
242
object.type = player[0].type
243
CallFunction(Player_TryTransform)
244
object.type = TypeName[Broken Monitor]
245
else
246
if ringPan == 0
247
PlaySfx(SfxName[Ring L], false)
248
SetSfxAttributes(SfxName[Ring L], -1, -100)
249
ringPan = 1
250
else
251
PlaySfx(SfxName[Ring R], false)
252
SetSfxAttributes(SfxName[Ring R], -1, 100)
253
ringPan = 0
254
end if
255
end if
256
257
if player[0].rings > 999
258
player[0].rings = 999
259
end if
260
261
if player[0].rings >= ringExtraLife
262
if options.gameMode != MODE_TIMEATTACK
263
// this one doesn't have 2P code, it's just like this since the code only gives rings to P1 anyway
264
#platform: USE_ORIGINS
265
if game.coinMode == false
266
player.lives++
267
else
268
CallNativeFunction2(NotifyCallback, NOTIFY_ADD_COIN, 1)
269
end if
270
#endplatform
271
#platform: USE_STANDALONE
272
player.lives++
273
#endplatform
274
275
PlaySfx(SfxName[Life], false)
276
PauseMusic()
277
ResetObjectEntity(SLOT_MUSICEVENT_CHANGE, TypeName[Music Event], MUSICEVENT_TRANSITION, 0, 0)
278
object[SLOT_MUSICEVENT_CHANGE].priority = PRIORITY_ACTIVE
279
end if
280
281
ringExtraLife += 100
282
if ringExtraLife > 300
283
ringExtraLife = 1000
284
end if
285
end if
286
break
287
288
case MONITOR_SHIELD_BUBBLE
289
PlaySfx(SfxName[Bubble Shield], false)
290
arrayPos0 = playerCount
291
arrayPos0 += currentPlayer
292
player[currentPlayer].shield = SHIELD_BUBBLE
293
294
if Player_superState != SUPERSTATE_SUPER
295
if object[arrayPos0].type != invincibilityType
296
CallFunction(Player_ApplyShield)
297
end if
298
end if
299
300
if player[currentPlayer].drownLevel >= 3
301
player[currentPlayer].drownTimer = 0
302
player[currentPlayer].drownLevel = 0
303
CallFunction(BrokenMonitor_ResetDrownMusic)
304
end if
305
break
306
307
case MONITOR_SHIELD_FIRE
308
PlaySfx(SfxName[Fire Shield], false)
309
arrayPos0 = playerCount
310
arrayPos0 += currentPlayer
311
player[currentPlayer].shield = SHIELD_FIRE
312
313
if Player_superState != SUPERSTATE_SUPER
314
if object[arrayPos0].type != invincibilityType
315
CallFunction(Player_ApplyShield)
316
end if
317
end if
318
break
319
320
case MONITOR_SHIELD_LIGHTNING
321
PlaySfx(SfxName[Lightning Shield], false)
322
arrayPos0 = playerCount
323
arrayPos0 += currentPlayer
324
player[currentPlayer].shield = SHIELD_LIGHTNING
325
326
if Player_superState != SUPERSTATE_SUPER
327
if object[arrayPos0].type != invincibilityType
328
CallFunction(Player_ApplyShield)
329
end if
330
end if
331
break
332
333
case MONITOR_EGGMAN
334
CallFunction(Player_Hit)
335
break
336
337
case MONITOR_TELEPORT
338
CreateTempObject(TypeName[VS Game], 0, object.xpos, object.ypos)
339
object[tempObjectPos].state = VSGAME_TELEPORT
340
PlaySfx(SfxName[Teleport], false)
341
break
342
343
case MONITOR_DEBUG_SPIKES
344
// Leftover from S1, this code should never hit at all since MONITOR_DEBUG_SPIKES is the same ID as MONITOR_RANDOM and
345
// random monitors get replaced on startup
346
347
PlaySfx(SfxName[Spike], false)
348
options.spikeBehavior ^= true
349
break
350
351
case MONITOR_DEBUG_SHIELD
352
PlaySfx(SfxName[Blue Shield], false)
353
options.shieldType++
354
options.shieldType &= SHIELDTYPE_RAND_S3
355
arrayPos0 = playerCount
356
currentPlayer = 0
357
CallFunction(Player_ApplyShield)
358
break
359
360
case MONITOR_DEBUG_EMERALDS
361
// Toggle emerald state - give the player all emeralds if they don't have them already but give them none if they have all
362
if specialStage.emeralds == 0x7F
363
specialStage.emeralds = 0
364
else
365
specialStage.emeralds = 0x7F
366
end if
367
PlaySfx(SfxName[Transform], false)
368
break
369
end switch
370
end if
371
break
372
373
case MONITOR_STATE_FADE
374
object.timer++
375
if object.timer == 30
376
object.timer = 0
377
object.state = MONITOR_STATE_IDLE
378
object.propertyValue = MONITOR_BLANK
379
if object.priority != PRIORITY_XBOUNDS_DESTROY
380
object.priority = PRIORITY_BOUNDS
381
end if
382
else
383
if object.timer > 14
384
object.alpha -= 16
385
end if
386
end if
387
break
388
389
case MONITOR_STATE_IDLE
390
break
391
end switch
392
#platform: USE_ORIGINS
393
object.drawIndex = 0 // Added in Origins, prevents flickering issues in 2PVS Splitscreen.
394
#endplatform
395
end event
396
397
398
event ObjectDraw
399
if object.drawIndex == 0
400
// Draw the monitor box on the normal layer
401
DrawSprite(0)
402
AddDrawListEntityRef(5, object.entityPos)
403
else
404
// Draw the effect icon on the higher draw layer
405
if object.propertyValue > 0
406
DrawSpriteFX(object.propertyValue, FX_INK, object.xpos, object.contentsPos.y)
407
end if
408
end if
409
410
object.drawIndex ^= 1
411
end event
412
413
414
event ObjectStartup
415
LoadSpriteSheet("Global/Items.gif")
416
SpriteFrame(-16, 0, 32, 16, 18, 34) // 0 - Broken Monitor Frame
417
418
SpriteFrame(-8, -9, 16, 14, 18, 66) // 1 - MONITOR_RINGS
419
SpriteFrame(-8, -9, 16, 14, 35, 66) // 2 - MONITOR_SHIELD_BLUE
420
SpriteFrame(-8, -9, 16, 14, 18, 81) // 3 - MONITOR_INVINCIBILITY
421
SpriteFrame(-8, -9, 16, 14, 35, 81) // 4 - MONITOR_SPEEDSHOES
422
423
// Amy's monitor icon is at the end of the list
424
#platform: USE_ORIGINS
425
if game.coinMode == false
426
#endplatform
427
// Player lives icons
428
SpriteFrame(-8, -9, 16, 14, 18, 96) // 5 - MONITOR_1UP_SONIC
429
SpriteFrame(-8, -9, 16, 14, 35, 96) // 6 - MONITOR_1UP_TAILS
430
SpriteFrame(-8, -9, 16, 14, 18, 111) // 7 - MONITOR_1UP_KNUX
431
#platform: USE_ORIGINS
432
else
433
SpriteFrame(-8, -9, 16, 14, 35, 186) // 5 - MONITOR_1UP_SONIC (Coin)
434
SpriteFrame(-8, -9, 16, 14, 35, 186) // 6 - MONITOR_1UP_TAILS (Coin but again)
435
SpriteFrame(-8, -9, 16, 14, 35, 186) // 7 - MONITOR_1UP_KNUX (Coin but yet again)
436
end if
437
#endplatform
438
439
SpriteFrame(-8, -9, 16, 14, 35, 111) // 8 - MONITOR_SUPER
440
SpriteFrame(-8, -9, 16, 14, 18, 141) // 9 - MONITOR_SHIELD_BUBBLE
441
SpriteFrame(-8, -9, 16, 14, 35, 126) // 10 - MONITOR_SHIELD_FIRE
442
SpriteFrame(-8, -9, 16, 14, 18, 126) // 11 - MONITOR_SHIELD_LIGHTNING
443
SpriteFrame(-8, -9, 16, 14, 35, 141) // 12 - MONITOR_EGGMAN
444
SpriteFrame(-8, -9, 16, 14, 18, 156) // 13 - MONITOR_TELEPORT
445
SpriteFrame(-8, -9, 16, 14, 35, 156) // 14 - MONITOR_RANDOM
446
SpriteFrame(-8, -9, 16, 14, 18, 171) // 15 - MONITOR_DEBUG_SHIELD
447
SpriteFrame(-8, -9, 16, 14, 35, 171) // 16 - MONITOR_DEBUG_EMERALDS
448
#platform: USE_ORIGINS
449
if game.coinMode == false
450
SpriteFrame(-8, -9, 16, 14, 18, 201) // 17 - MONITOR_1UP_AMY
451
else
452
SpriteFrame(-8, -9, 16, 14, 35, 186) // 17 - MONITOR_1UP_AMY (The long awaited return of Coin)
453
end if
454
#endplatform
455
456
// (The Spring Icon is unused, and so is the Mania monitor added in Origins)
457
458
// By default, assume there isn't any water in the stage and assign a dummy function for resetting drown music
459
// (In stages with water, that stage's [Water] object will set the function itself instead)
460
BrokenMonitor_ResetDrownMusic = BrokenMonitor_Blank
461
end event
462
463
464
// ========================
465
// Editor Events
466
// ========================
467
468
event RSDKDraw
469
DrawSprite(0)
470
end event
471
472
473
event RSDKLoad
474
LoadSpriteSheet("Global/Items.gif")
475
SpriteFrame(-16, 0, 32, 16, 18, 34)
476
477
SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
478
end event
479
480