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/Ring.txt
1480 views
1
// ----------------------------------
2
// RSDK Project: Sonic 2
3
// Script Description: Ring 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.value1 : object.targetPlayer
13
14
private alias 0 : RING_IDLE
15
private alias 1 : RING_ATTRACTED
16
17
// Player Aliases
18
private alias object.state : player.state
19
private alias object.xpos : player.xpos
20
private alias object.ypos : player.ypos
21
private alias object.value0 : player.rings
22
private alias object.value16 : player.isSidekick
23
private alias object.value18 : player.currentPlane
24
private alias object.value37 : player.shield
25
26
private alias 4 : SHIELD_LIGHTNING
27
28
// Game Modes
29
private alias 2 : MODE_TIMEATTACK
30
31
// Music Events
32
private alias 25 : SLOT_MUSICEVENT_CHANGE
33
34
private alias 2 : MUSICEVENT_TRANSITION
35
36
37
// ========================
38
// Function Declarations
39
// ========================
40
41
reserve function Ring_DebugDraw
42
reserve function Ring_DebugSpawn
43
44
45
// ========================
46
// Function Definitions
47
// ========================
48
49
private function Ring_DebugDraw
50
DrawSprite(0)
51
end function
52
53
54
private function Ring_DebugSpawn
55
CreateTempObject(TypeName[Ring], 0, object.xpos, object.ypos)
56
object[tempObjectPos].drawOrder = 4
57
end function
58
59
60
// ========================
61
// Events
62
// ========================
63
64
event ObjectUpdate
65
// Bug Details:
66
// - The loop doesn't check to see if the ring's been obtained already, so
67
// if two players touch the ring at the same time, then the ring will count twice
68
// - (The CNZ ring properly checks for that.. so why doesn't the normal version have the fix?..)
69
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
70
71
// Bug Details:
72
// -> While this top check works fine in singleplayer, as well as 2013's online VS, this doesn't work quite as fairly in Origins's local 2PVS
73
// It puts P2 at a direct disadvantage, since it blocks them from picking up any rings while P1 is recoiling
74
// On the other hand, however, P1 can still pick up rings even when P2 is recoiling
75
CheckEqual(player[0].state, Player_State_Hurt)
76
temp0 = checkResult
77
78
CheckEqual(player[currentPlayer].state, Player_State_Hurt)
79
temp0 = checkResult
80
CheckEqual(player[currentPlayer].state, Player_State_GotHit)
81
temp0 |= checkResult
82
83
if temp0 == false
84
// All checks passed, see if the player is touching the ring
85
86
BoxCollisionTest(C_TOUCH, object.entityPos, -8, -8, 8, 8, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
87
if checkResult == true
88
// Player is touching ring - collect it
89
90
// Turn this object into a sparkle
91
object.type = TypeName[Ring Sparkle]
92
93
// Set this object to the same drawOrder as the player
94
object.drawOrder = player[currentPlayer].currentPlane
95
96
// Add it to the player's ring count
97
if player[currentPlayer].isSidekick == true
98
// P2 Tails in normal gameplay (not VS)
99
// So add it to P1's ring count
100
player[0].rings++
101
if player[0].rings > 999
102
player[0].rings = 999
103
end if
104
else
105
// Either P2 in VS or P1 in any mode
106
// In any case, give the ring to the player that collected it
107
player[currentPlayer].rings++
108
if player[currentPlayer].rings > 999
109
player[currentPlayer].rings = 999
110
end if
111
end if
112
113
// Check if the player should get an extra life
114
// (Always checking against P1? Doesn't look like P2 can get an extra life with rings in VS..)
115
if player[0].rings >= ringExtraLife
116
// Not in time attack?
117
if options.gameMode != MODE_TIMEATTACK
118
// Give the player an extra life/coin and play the music
119
#platform: USE_ORIGINS
120
if game.coinMode == false
121
player.lives++
122
else
123
CallNativeFunction2(NotifyCallback, NOTIFY_ADD_COIN, 1)
124
end if
125
#endplatform
126
#platform: USE_STANDALONE
127
player.lives++
128
#endplatform
129
PlaySfx(SfxName[Life], false)
130
PauseMusic()
131
ResetObjectEntity(SLOT_MUSICEVENT_CHANGE, TypeName[Music Event], MUSICEVENT_TRANSITION, 0, 0)
132
object[SLOT_MUSICEVENT_CHANGE].priority = PRIORITY_ACTIVE
133
end if
134
135
ringExtraLife += 100
136
if ringExtraLife > 300
137
ringExtraLife = 1000
138
end if
139
end if
140
141
if options.vsMode == true
142
if vs.playerID == 0 // Player 1 on the server side
143
if currentPlayer == 0 // Player 1 on the client's side
144
vs.totalRings1P++
145
else
146
vs.totalRings2P++
147
end if
148
else
149
if currentPlayer == 1 // Player 2 on the client's side
150
vs.totalRings1P++
151
else
152
vs.totalRings2P++
153
end if
154
end if
155
end if
156
157
// Play the ring sound
158
if ringPan == 0
159
PlaySfx(SfxName[Ring L], false)
160
SetSfxAttributes(SfxName[Ring L], -1, -100)
161
ringPan = 1
162
else
163
PlaySfx(SfxName[Ring R], false)
164
SetSfxAttributes(SfxName[Ring R], -1, 100)
165
ringPan = 0
166
end if
167
else
168
// Check if the ring should get attracted
169
if object.state == RING_IDLE
170
if player[currentPlayer].shield == SHIELD_LIGHTNING
171
BoxCollisionTest(C_TOUCH, object.entityPos, -64, -64, 64, 64, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
172
if checkResult == true
173
// Make the ring attracted to the player
174
object.state = RING_ATTRACTED
175
object.targetPlayer = currentPlayer
176
end if
177
end if
178
end if
179
end if
180
end if
181
next
182
183
if object.state == RING_ATTRACTED
184
arrayPos0 = object.targetPlayer
185
186
if player[arrayPos0].shield != SHIELD_LIGHTNING
187
// If the player lost their shield, then make this ring dropped
188
object.type = TypeName[Lose Ring]
189
object.animationSpeed = 128
190
object.alpha = 256
191
else
192
arrayPos0 = object.targetPlayer
193
194
// Move closer to the player
195
if object.xpos > player[arrayPos0].xpos
196
if object.xvel > 0
197
object.xvel -= 0xC000
198
else
199
object.xvel -= 0x3000
200
end if
201
else
202
if object.xvel < 0
203
object.xvel += 0xC000
204
else
205
object.xvel += 0x3000
206
end if
207
end if
208
209
if object.ypos > player[arrayPos0].ypos
210
if object.yvel > 0
211
object.yvel -= 0xC000
212
else
213
object.yvel -= 0x3000
214
end if
215
else
216
if object.yvel < 0
217
object.yvel += 0xC000
218
else
219
object.yvel += 0x3000
220
end if
221
end if
222
223
object.xpos += object.xvel
224
object.ypos += object.yvel
225
end if
226
end if
227
end event
228
229
230
event ObjectDraw
231
// All rings use the same frame
232
// (Animation is handled by Stage Setup object)
233
DrawSprite(ringFrame)
234
end event
235
236
237
event ObjectStartup
238
LoadSpriteSheet("Global/Items.gif")
239
240
// (Doesn't mean much, but this is one of the few times in v4 scripts that a code is between LoadSpriteSheet and SpriteFrames)
241
foreach (TypeName[Ring], arrayPos0, ALL_ENTITIES)
242
object[arrayPos0].drawOrder = 4
243
next
244
245
// Ring frames
246
SpriteFrame(-8, -8, 16, 16, 1, 1)
247
SpriteFrame(-8, -8, 16, 16, 1, 18)
248
SpriteFrame(-8, -8, 16, 16, 1, 35)
249
SpriteFrame(-8, -8, 16, 16, 1, 52)
250
SpriteFrame(-8, -8, 16, 16, 1, 69)
251
SpriteFrame(-8, -8, 16, 16, 1, 86)
252
SpriteFrame(-8, -8, 16, 16, 1, 103)
253
SpriteFrame(-8, -8, 16, 16, 1, 120)
254
255
// Add the Ring to the debug mode object list
256
SetTableValue(TypeName[Ring], DebugMode_ObjCount, DebugMode_TypesTable)
257
SetTableValue(Ring_DebugDraw, DebugMode_ObjCount, DebugMode_DrawTable)
258
SetTableValue(Ring_DebugSpawn, DebugMode_ObjCount, DebugMode_SpawnTable)
259
DebugMode_ObjCount++
260
end event
261
262
263
// ========================
264
// Editor Events
265
// ========================
266
267
event RSDKEdit
268
if editor.returnVariable == true
269
switch editor.variableID
270
case EDIT_VAR_PROPVAL // property value
271
checkResult = object.propertyValue
272
break
273
274
case 0 // type
275
checkResult = object.propertyValue
276
break
277
278
end switch
279
else
280
switch editor.variableID
281
case EDIT_VAR_PROPVAL // property value
282
object.propertyValue = editor.variableValue
283
break
284
285
case 0 // type
286
object.propertyValue = editor.variableValue
287
break
288
289
end switch
290
end if
291
end event
292
293
294
event RSDKDraw
295
DrawSprite(0)
296
end event
297
298
299
event RSDKLoad
300
LoadSpriteSheet("Global/Items.gif")
301
SpriteFrame(-8, -8, 16, 16, 1, 1)
302
303
AddEditorVariable("type")
304
SetActiveVariable("type")
305
AddEnumVariable("Normal", 0)
306
//AddEnumVariable("Not required by Sonic for perfect bonus", 1) // The score tally system seems to be a bit broken, so while it looks like this is how it was *supposed* to be, this is effectively useless
307
AddEnumVariable("Not required by all characters for perfect bonus", 2)
308
end event
309
310