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/Players/PlayerObject.txt
1479 views
1
// ----------------------------------
2
// RSDK Project: Sonic 2
3
// Script Description: Player Object Object
4
// Script Author: Christian Whitehead/Simon Thomley
5
// Unpacked by Rubberduckycooly's script unpacker
6
// ----------------------------------
7
8
// ========================
9
// Aliases
10
// ========================
11
12
public alias 0x100 : GROUP_PLAYERS
13
public alias arrayPos6 : currentPlayer
14
public alias arrayPos7 : playerCount
15
16
// Gravity
17
public alias 0 : GRAVITY_GROUND
18
public alias 1 : GRAVITY_AIR
19
20
// Priority
21
public alias 0 : PRIORITY_BOUNDS
22
public alias 1 : PRIORITY_ACTIVE
23
public alias 2 : PRIORITY_ALWAYS
24
public alias 3 : PRIORITY_XBOUNDS
25
public alias 4 : PRIORITY_XBOUNDS_DESTROY
26
public alias 5 : PRIORITY_INACTIVE
27
public alias 6 : PRIORITY_BOUNDS_SMALL
28
public alias 7 : PRIORITY_ACTIVE_SMALL
29
30
// Control Modes
31
public alias -1 : CONTROLMODE_NONE
32
public alias 0 : CONTROLMODE_P1
33
public alias 1 : CONTROLMODE_P2
34
public alias 2 : CONTROLMODE_P3 // Although unused by the game normally, RSDKv5U does have support for up to 4 players
35
public alias 3 : CONTROLMODE_P4
36
37
// Camera Styles
38
public alias 0 : CAMERASTYLE_FOLLOW
39
public alias 1 : CAMERASTYLE_EXTENDED
40
public alias 2 : CAMERASTYLE_EXTENDED_OFFSET_L
41
public alias 3 : CAMERASTYLE_EXTENDED_OFFSET_R
42
public alias 4 : CAMERASTYLE_HLOCKED
43
// Origins Only
44
public alias 5 : CAMERASTYLE_FIXED
45
public alias 6 : CAMERASTYLE_STATIC
46
47
// Ink Effects
48
public alias 0 : INK_NONE
49
public alias 1 : INK_BLEND
50
public alias 2 : INK_ALPHA
51
public alias 3 : INK_ADD
52
public alias 4 : INK_SUB
53
54
// Flip Directions
55
public alias 0 : FLIP_NONE
56
public alias 1 : FLIP_X
57
public alias 2 : FLIP_Y
58
public alias 3 : FLIP_XY
59
60
// Collision Sides
61
public alias 0 : CSIDE_FLOOR
62
public alias 1 : CSIDE_LWALL
63
public alias 2 : CSIDE_RWALL
64
public alias 3 : CSIDE_ROOF
65
public alias 4 : CSIDE_LENTITY // Origins only
66
public alias 5 : CSIDE_RENTITY // Origins only
67
68
// Collision Modes
69
public alias 0 : CMODE_FLOOR
70
public alias 1 : CMODE_LWALL
71
public alias 2 : CMODE_ROOF
72
public alias 3 : CMODE_RWALL
73
74
// Collision Directions
75
public alias 0 : COL_NONE
76
public alias 1 : COL_TOP
77
public alias 2 : COL_LEFT
78
public alias 3 : COL_RIGHT
79
public alias 4 : COL_BOTTOM
80
81
// Reserved Object Slot Aliases
82
private alias 0 : SLOT_PLAYER1
83
private alias 1 : SLOT_PLAYER2
84
private alias 11 : SLOT_TITLECARD
85
private alias 30 : SLOT_ACTFINISH
86
87
// Draw Order
88
private alias -1 : DRAWORDER_PLAYER
89
90
// Tile Info ID Aliases
91
private alias 8 : TILEINFO_ANGLEB
92
93
// Player List Pos Aliases
94
// The A at the end of each of these stands for Alias, Origins Plus introduced global variables for player slots but we need to support Standalone too
95
// Also switch cases don't support variables so we have to do this either way
96
public alias 0 : PLAYER_SONIC_A
97
public alias 1 : PLAYER_TAILS_A
98
public alias 2 : PLAYER_KNUCKLES_A
99
public alias 3 : PLAYER_SONIC_TAILS_A
100
public alias 4 : PLAYER_KNUCKLES_TAILS_A
101
public alias 5 : PLAYER_AMY_A
102
public alias 6 : PLAYER_AMY_TAILS_A
103
104
// Shields
105
private alias 0 : SHIELD_NONE
106
private alias 1 : SHIELD_NORMAL
107
private alias 2 : SHIELD_BUBBLE
108
private alias 3 : SHIELD_FIRE
109
private alias 4 : SHIELD_LIGHTNING
110
111
// Shield Types Aliases
112
private alias 0 : SHIELDTYPE_S2
113
private alias 1 : SHIELDTYPE_S3
114
115
// Bubble Shield Aliases
116
private alias 2 : BUBBLESHIELD_BOUNCE_SETUP
117
118
// Fire Shield Aliases
119
private alias 2 : FIRESHIELD_DASH_SETUP
120
121
// Super States
122
private alias 0 : SUPERSTATE_NONE
123
private alias 1 : SUPERSTATE_SUPER
124
private alias 2 : SUPERSTATE_FADEOUT
125
private alias 3 : SUPERSTATE_END
126
127
// Modes
128
private alias 2 : MODE_TIMEATTACK
129
private alias 8 : MISSIONNO_MERCY
130
131
// Global Variable ID Aliases (yeah it's weird, the game uses global variables like an array sometimes, so these aliases are the IDs of those variables)
132
// (these numbers correspond to the variable's position in the GameConfig global variable list)
133
private alias 22 : GLOBAL_PLAYERSCORE
134
private alias 25 : GLOBAL_PLAYERLIVES
135
136
// Tracks
137
private alias 0 : TRACK_STAGE
138
private alias 2 : TRACK_INVINCIBLE
139
private alias 5 : TRACK_GAMEOVER
140
private alias 7 : TRACK_SUPER
141
142
// Stats Aliases
143
private alias StageStatsUsabilityParam1 : stageStat.badnikDestroyCount
144
private alias StageStatsUsabilityParam2 : stageStat.spindashDestroyCount
145
private alias StageStatsUsabilityParam3 : stageStat.buzzerDestroyCount
146
147
// We can't use TypeName aliases for stage objects in global objects, so regular aliases will have to do
148
private alias 54 : TYPE_BUZZER
149
private alias 56 : TYPE_BEE
150
151
// Variables
152
private alias object.type : player.type
153
private alias object.groupID : player.groupID // Normally GROUP_PLAYERS, unless in Debug Mode or some other strange scenario
154
private alias object.entityPos : player.entityPos // Where the player is on the object list - P1 should be 0, P2 should be 1
155
private alias object.state : player.state
156
private alias object.visible : player.visible
157
private alias object.propertyValue : player.character // Individual character type of the object. See the Player List Pos aliases
158
private alias object.xpos : player.xpos // Total world-space position (0x10000 == 1.0)
159
private alias object.ypos : player.ypos
160
private alias object.ixpos : player.ixpos // Screen space position (1 == 1)
161
private alias object.iypos : player.iypos
162
private alias object.lookPosX : player.lookPosX // Camera offset based on this player's position
163
private alias object.lookPosY : player.lookPosY
164
private alias object.xvel : player.xvel // Based on world-space (see above)
165
private alias object.yvel : player.yvel
166
private alias object.speed : player.speed // Based on world-space (see above)
167
private alias object.rotation : player.rotation // 512-based, not 360 degrees
168
private alias object.angle : player.angle // See above
169
private alias object.direction : player.direction
170
private alias object.gravity : player.gravity // GRAVITY_GROUND or GRAVITY_AIR. Not to be confused with player.gravityStrength, see there for more info
171
private alias object.frame : player.frame
172
private alias object.animation : player.animation
173
private alias object.prevAnimation : player.prevAnimation
174
private alias object.animationSpeed : player.animationSpeed
175
private alias object.animationTimer : player.animationTimer
176
private alias object.drawOrder : player.drawOrder // Should always be DRAWORDER_PLAYER, to change draw order use player.sortedDrawOrder instead
177
private alias object.pushing : player.pushing
178
private alias object.controlLock : player.controlLock // Timer for how long control lock is active. Not to be confused with roll jump lock, see the Player_Action_Jump function for that
179
private alias object.controlMode : player.controlMode // See CONTROLMODE_* aliases
180
private alias object.interaction : player.interaction // Will the object interact with other objects?
181
private alias object.scrollTracking : player.scrollTracking // Determines if the camera will track the player's position or just follow it
182
private alias object.collisionMode : player.collisionMode
183
private alias object.collisionLeft : player.collisionLeft
184
private alias object.collisionTop : player.collisionTop
185
private alias object.collisionRight : player.collisionRight
186
private alias object.collisionBottom : player.collisionBottom
187
private alias object.collisionPlane : player.collisionPlane
188
private alias object.floorSensorC : player.floorSensorC
189
private alias object.floorSensorL : player.floorSensorL
190
private alias object.floorSensorR : player.floorSensorR
191
private alias object.floorSensorLC : player.floorSensorLC
192
private alias object.floorSensorRC : player.floorSensorRC
193
private alias object.tileCollisions : player.tileCollisions
194
private alias object.priority : player.priority
195
196
// *Object-wise* input, not to be confused with keyPress[0].X and keyDown[0].X
197
private alias object.jumpPress : player.jumpPress
198
private alias object.jumpHold : player.jumpHold
199
private alias object.up : player.up
200
private alias object.down : player.down
201
private alias object.left : player.left
202
private alias object.right : player.right
203
204
// Object value aliases
205
private alias object.value0 : player.rings
206
private alias object.value1 : player.timer
207
private alias object.value2 : player.abilityTimer // Note: Also used by death/drowning state
208
private alias object.value3 : player.drownTimer // Countdown before player moves to next drown "level"
209
private alias object.value4 : player.drownLevel
210
private alias object.value5 : player.rollAnimationSpeed
211
private alias object.value6 : player.speedShoesTimer
212
private alias object.value7 : player.invincibleTimer
213
private alias object.value8 : player.blinkTimer
214
private alias object.value9 : player.skidSpeed
215
private alias object.value10 : player.animationReserve // Used by springs to store what animation will play after the bounce animation
216
private alias object.value11 : player.scrollDelay // A timer of how long the camera will stay locked for
217
private alias object.value12 : player.tailFrame // One of Tails's tail values, not used by the player itself
218
private alias object.value13 : player.tailAnim // Also one of Tails's tail values
219
private alias object.value14 : player.skidding
220
// value15 is unused
221
private alias object.value16 : player.isSidekick // true if an AI character (P2 in singleplayer), false otherwise (P1, P2 in 2PVS)
222
private alias object.value17 : debugMode.currentSelection
223
private alias object.value18 : player.sortedDrawOrder
224
private alias object.value19 : player.badnikBonus // How many enemies the player has bounced on in a row
225
private alias object.value20 : player.topSpeed
226
private alias object.value21 : player.acceleration
227
private alias object.value22 : player.deceleration
228
private alias object.value23 : player.airAcceleration
229
private alias object.value24 : player.airDeceleration
230
private alias object.value25 : player.gravityStrength // Also used in underwater checks, 0x1000 if underwater, otherwise 0x3800. Not to be confused with player.gravity
231
private alias object.value26 : player.flightVelocity // Used by Tails only
232
private alias object.value27 : player.jumpStrength
233
private alias object.value28 : player.jumpCap
234
private alias object.value29 : player.rollingFriction // Active rolling deceleration - With the player holding the opposite direction
235
private alias object.value30 : player.jumpOffset // Added to the player's position when jumping/rolling. Normally -5 for S&K, and -1 for Tails
236
private alias object.value31 : player.rollingDeceleration // Passive rolling deceleration - Without the player holding the opposite direction
237
private alias object.value32 : player.jumpAbility // Used to store whatever function this player has for its jump ability
238
private alias object.value33 : player.spindashFunction // Used to store whatever function this player has for its spindash ability
239
private alias object.value34 : player.collisionDisabled
240
private alias object.value35 : player.jumpAbilityState
241
private alias object.value36 : player.flyCarryTimer // Tails assist lockout timer
242
private alias object.value37 : player.shield // Current shield the player has, see SHIELD_* constants
243
private alias object.value40 : player.hitboxLeft
244
private alias object.value38 : player.hitboxTop
245
private alias object.value41 : player.hitboxRight
246
private alias object.value39 : player.hitboxBottom
247
private alias object.value42 : player.prevGravity
248
249
// Values used in Origins
250
private alias object.value16 : player.releasingDropDash
251
private alias object.value47 : player.disableGravity // Added in Origins 2.0.1, used after clearing/failing a mission
252
253
// P2 values
254
private alias object.value43 : player.jumpInTimer
255
private alias object.value44 : player.p2InputFunction
256
private alias object.value45 : player.autoJumpTimer
257
private alias object.value46 : player.targetLeaderPos.x
258
private alias object.value47 : player.targetLeaderPos.y
259
260
// Death Event Aliases
261
private alias object.drawOrder : deathEvent.drawOrder
262
private alias object.state : deathEvent.state
263
private alias object.value1 : deathEvent.leftTextPos
264
private alias object.value2 : deathEvent.rightTextPos
265
private alias object.value3 : deathEvent.timer
266
267
// Death Event States
268
private alias 0 : DEATHEVENT_GAMEOVER
269
private alias 1 : DEATHEVENT_TIMEOVER
270
private alias 2 : DEATHEVENT_DEATH
271
private alias 3 : DEATHEVENT_DEATH_TA
272
273
// VSGame Aliases
274
private alias object.state : vsGame.state
275
private alias object.value0 : vsGame.timer
276
277
// VSGame States
278
private alias 2 : VSGAME_FADEOUT
279
private alias 7 : VSGAME_SCREENFADE
280
281
282
// ========================
283
// Function Declarations
284
// ========================
285
286
reserve function Player_ProcessUpdate
287
reserve function Player_State_Static
288
reserve function Player_HandleGroundMovement
289
reserve function Player_HandleAirFriction
290
reserve function Player_HandleAirMovement
291
reserve function Player_HandleOnGround
292
reserve function Player_Action_Jump
293
reserve function Player_Action_Spindash
294
reserve function Player_Action_DblJumpTails
295
reserve function Player_Action_DblJumpKnux
296
reserve function Player_State_Ground
297
reserve function Player_State_Sleeping
298
reserve function Player_State_Air_NoDropDash
299
reserve function Player_State_Air
300
reserve function Player_State_TubeAirRoll
301
reserve function Player_State_Roll
302
reserve function Player_State_RollJump
303
reserve function Player_State_LookUp
304
reserve function Player_State_Crouch
305
reserve function Player_State_Spindash
306
reserve function Player_State_Fly
307
reserve function Player_State_GlideLeft
308
reserve function Player_State_GlideRight
309
reserve function Player_State_GlideDrop
310
reserve function Player_State_GlideSlide
311
reserve function Player_State_Climb
312
reserve function Player_State_LedgePullUp
313
reserve function Player_State_GotHit
314
reserve function Player_State_Hurt
315
reserve function Player_State_Death
316
reserve function Player_State_Drown
317
reserve function Player_State_HangBar // Unused - Leftover from CD
318
reserve function Player_State_TubeRoll
319
reserve function Player_State_Clinging
320
reserve function Player_State_Waterslide
321
reserve function Player_State_Carried
322
reserve function Player_State_ContinueRun
323
reserve function Player_SetDropDashCharge
324
reserve function Player_GetDropDashCharge
325
reserve function Player_HandleDropDash
326
reserve function Player_CheckIfOnScreen
327
reserve function Player_Action_DblJumpAmy
328
reserve function Player_Action_HammerDash
329
reserve function Player_State_HammerDash
330
reserve function Player_SetHammerDashSpeed
331
reserve function Player_HandleAmyHitbox
332
reserve function Player_SetupAttractDemo
333
reserve function Player_ApplyShield
334
reserve function Player_HandleSuperPalette_Sonic
335
reserve function Player_HandleSuperPalette_Tails
336
reserve function Player_HandleSuperPalette_Knux
337
reserve function Player_HandleSuperPalette_Amy
338
reserve function Player_UpdatePhysicsState
339
reserve function Player_HandleSuperForm
340
reserve function Player_CheckHit
341
reserve function Player_BadnikBreak
342
reserve function Player_Hit
343
reserve function Player_FireHit
344
reserve function Player_LightningHit
345
reserve function Player_ProjectileHit
346
reserve function Player_SpikeHit
347
reserve function Player_Kill
348
reserve function Player_HandleRollAnimSpeed
349
reserve function Player_HandleWalkAnimSpeed
350
reserve function Player_HandleRunAnimSpeed
351
reserve function Player_HandleRollDeceleration
352
reserve function Player_State_Transform
353
reserve function Player_TryTransform
354
reserve function Player_State_BubbleBounce
355
reserve function Player_Action_DblJumpSonic
356
reserve function Player_HandleFlyCarry
357
358
359
// ========================
360
// Static Values
361
// ========================
362
363
public value Player_flyCarryLeaderXPos = 0
364
public value Player_flyCarryLeaderYPos = 0
365
public value Player_flyCarryBuddyXPos = 0
366
public value Player_flyCarryBuddyYPos = 0
367
368
public value Player_superState = 0
369
public value Player_superRingLossTimer = 0
370
public value Player_superBlendClr = 0
371
public value Player_superBlendTimer = 0
372
373
public value Player_attractTable = 0
374
public value Player_attractTablePos = 0
375
public value Player_attractTableSize = 0
376
public value Player_attractFrameCount = 0
377
public value Player_attractDuration = 0
378
379
// All these below are unused
380
private value Player_unusedValue1 = 0
381
private value Player_unusedValue2 = 0
382
private value Player_unusedValue3 = 0
383
private value Player_unusedValue4 = 0
384
private value Player_unusedValue5 = 0
385
private value Player_unusedValue6 = 0
386
private value Player_unusedValue7 = 0
387
388
389
// ========================
390
// Tables
391
// ========================
392
393
public table Player_SonicSuperPal
394
0x2020A0, 0x2040C0, 0x4040E0, 0x6060E0
395
0x404080, 0x4060A0, 0x6060E0, 0x8080E0
396
0x606060, 0x6080A0, 0x8080E0, 0xA0A0E0
397
0x808040, 0x80A0A0, 0xA0A0E0, 0xC0C0E0
398
0xA0A040, 0xA0C0A0, 0xC0C0E0, 0xE0E0E0
399
0xC0C040, 0xC0E0A0, 0xE0E0E0, 0xE0E0E0
400
0xE0E040, 0xE0E0A0, 0xE0E0E0, 0xE0E0E0
401
0xE0E060, 0xE0E0E0, 0xE0E0E0, 0xE0E0E0
402
0xE0E080, 0xE0E0E0, 0xE0E0E0, 0xE0E0E0
403
0xE0E060, 0xE0E0C0, 0xE0E0E0, 0xE0E0E0
404
0xE0E040, 0xE0E0A0, 0xE0E0E0, 0xE0E0E0
405
0xE0E020, 0xE0E080, 0xE0E0C0, 0xE0E0E0
406
0xE0E000, 0xE0E060, 0xE0E0A0, 0xE0E0E0
407
0xE0E000, 0xE0E040, 0xE0E080, 0xE0E0C0
408
0xE0E000, 0xE0E060, 0xE0E0A0, 0xE0E0E0
409
0xE0E000, 0xE0E080, 0xE0E0C0, 0xE0E0E0
410
end table
411
412
public table Player_SonicSuperAltPal
413
0x202080, 0x4040A0, 0x6060C0, 0x8080E0
414
0x404060, 0x6060A0, 0x8080E0, 0xA0A0E0
415
0x606040, 0x8080A0, 0xA0A0E0, 0xC0C0E0
416
0x808040, 0xA0A0A0, 0xC0C0E0, 0xE0E0E0
417
0xA0A040, 0xC0C0A0, 0xE0E0E0, 0xE0E0E0
418
0xC0C040, 0xE0E0A0, 0xE0E0E0, 0xE0E0E0
419
0xE0E040, 0xE0E0A0, 0xE0E0E0, 0xE0E0E0
420
0xE0E060, 0xE0E0E0, 0xE0E0E0, 0xE0E0E0
421
0xE0E080, 0xE0E0E0, 0xE0E0E0, 0xE0E0E0
422
0xE0E060, 0xE0E0C0, 0xE0E0E0, 0xE0E0E0
423
0xE0E040, 0xE0E0A0, 0xE0E0E0, 0xE0E0E0
424
0xE0E020, 0xE0E080, 0xE0E0C0, 0xE0E0E0
425
0xE0E000, 0xE0E060, 0xE0E0A0, 0xE0E0E0
426
0xE0E000, 0xE0E040, 0xE0E080, 0xE0E0C0
427
0xE0E000, 0xE0E060, 0xE0E0A0, 0xE0E0E0
428
0xE0E000, 0xE0E080, 0xE0E0C0, 0xE0E0E0
429
end table
430
431
public table Player_TailsSuperPal
432
0x800000, 0xE08000, 0xE0A000, 0xA06040
433
0x800000, 0xE0A020, 0xE0C040, 0xA06040
434
0xA06040, 0xE0C040, 0xE0C080, 0xC06040
435
0xC06040, 0xE0C080, 0xE0E0A0, 0xE08040
436
0xA06040, 0xE0C040, 0xE0C080, 0xC06040
437
0x800000, 0xE0A020, 0xE0C040, 0xA06040
438
end table
439
440
public table Player_TailsSuperAltPal
441
0x800000, 0xE08000, 0xE0A000, 0xA06040
442
0x800000, 0xE0A020, 0xE0C040, 0xA06040
443
0xA06040, 0xE0C040, 0xE0C080, 0xC06040
444
0xC06040, 0xE0C080, 0xE0E0A0, 0xE08040
445
0xA06040, 0xE0C040, 0xE0C080, 0xC06040
446
0x800000, 0xE0A020, 0xE0C040, 0xA06040
447
end table
448
449
public table Player_KnuxSuperPal
450
0x600020, 0xC00020, 0xE04060
451
0x802040, 0xE04060, 0xE060A0
452
0xA04060, 0xE06080, 0xE080C0
453
0xC06080, 0xE080A0, 0xE0A0E0
454
0xE080A0, 0xE0A0C0, 0xE0C0E0
455
0xE0A0C0, 0xE0C0E0, 0xE0E0E0
456
0xE080A0, 0xE0A0C0, 0xE0C0E0
457
0xC06080, 0xE080A0, 0xE0A0E0
458
0xA04060, 0xE06080, 0xE080C0
459
0x802040, 0xE04060, 0xE060A0
460
end table
461
462
public table Player_KnuxSuperAltPal
463
0x600020, 0xC00040, 0xE04080
464
0x802040, 0xE04060, 0xE060A0
465
0xA04060, 0xE06080, 0xE080C0
466
0xC06080, 0xE080A0, 0xE0A0E0
467
0xE080A0, 0xE0A0C0, 0xE0C0E0
468
0xE0A0C0, 0xE0C0E0, 0xE0E0E0
469
0xE080A0, 0xE0A0C0, 0xE0C0E0
470
0xC06080, 0xE080A0, 0xE0A0E0
471
0xA04060, 0xE06080, 0xE080C0
472
0x802040, 0xE04060, 0xE060A0
473
end table
474
475
// Bug Details (yeah we haven't gotten to any actual code yet and there's already an issue):
476
// Amy's base palette is completely missing in both of these tables, causing the game to apply the first super palette when the scene loads instead
477
// This is what causes Amy's fur to be slightly brighter in-game compared to the spritesheets and global palette
478
// Note that if you're looking to fix this, you'll also have to edit the Player_HandleSuperPalette_Amy function to account for the new line
479
480
public table Player_AmySuperPal
481
0xD468B0, 0xFC8CFC, 0xFCD4FC, 0x8C2068, 0xB0448C
482
0xF488D0, 0xFCACFC, 0xFCE4FC, 0xAC4088, 0xD064AC
483
0xF4A8F0, 0xFCCCFC, 0xFCE4FC, 0xCC60A8, 0xF084CC
484
0xF4C8F0, 0xFCECFC, 0xFCE4FC, 0xEC80C8, 0xF0A4EC
485
0xF4E8F0, 0xFCECFC, 0xFCE4FC, 0xECA0E8, 0xF0C4EC
486
0xF4E8F0, 0xFCECFC, 0xFCE4FC, 0xECC0E8, 0xF0E4EC
487
0xF4E8F0, 0xFCECFC, 0xFCE4FC, 0xECA0E8, 0xF0C4EC
488
0xF4C8F0, 0xFCECFC, 0xFCE4FC, 0xEC80C8, 0xF0A4EC
489
0xF4A8F0, 0xFCCCFC, 0xFCE4FC, 0xCC60A8, 0xF084CC
490
0xF488D0, 0xFCACFC, 0xFCE4FC, 0xAC4088, 0xD064AC
491
end table
492
493
public table Player_AmySuperAltPal
494
0xD468B0, 0xFC8CFC, 0xFCD4FC, 0x8C2068, 0xB0448C
495
0xF488D0, 0xFCACFC, 0xFCE4FC, 0xAC4088, 0xD064AC
496
0xF4A8F0, 0xFCCCFC, 0xFCE4FC, 0xCC60A8, 0xF084CC
497
0xF4C8F0, 0xFCECFC, 0xFCE4FC, 0xEC80C8, 0xF0A4EC
498
0xF4E8F0, 0xFCECFC, 0xFCE4FC, 0xECA0E8, 0xF0C4EC
499
0xF4E8F0, 0xFCECFC, 0xFCE4FC, 0xECC0E8, 0xF0E4EC
500
0xF4E8F0, 0xFCECFC, 0xFCE4FC, 0xECA0E8, 0xF0C4EC
501
0xF4C8F0, 0xFCECFC, 0xFCE4FC, 0xEC80C8, 0xF0A4EC
502
0xF4A8F0, 0xFCCCFC, 0xFCE4FC, 0xCC60A8, 0xF084CC
503
0xF488D0, 0xFCACFC, 0xFCE4FC, 0xAC4088, 0xD064AC
504
end table
505
506
// Each line of these physics tables store the values in this order:
507
// Top Speed, Ground Acceleration, Air Acceleration, Air Deleceration, Skid Speed, Rolling Friction, Jump Strength, Jump Cap
508
// Note that Ground Deceleration is not defined here, rather it's set based on Ground Acceleration
509
510
private table Player_SonicPhysicsTable
511
0x60000, 0x0C00, 0x1800, 0x0600, 0x08000, 0x0600, 0x68000, -0x40000 // Normal
512
0x30000, 0x0600, 0x0C00, 0x0300, 0x04000, 0x0300, 0x38000, -0x20000 // Underwater
513
0xA0000, 0x3000, 0x6000, 0x1800, 0x10000, 0x0600, 0x80000, -0x40000 // Super
514
0x50000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0300, 0x38000, -0x20000 // Super + Underwater
515
0xC0000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0600, 0x68000, -0x40000 // Speed Shoes
516
0x60000, 0x0C00, 0x1800, 0x0600, 0x04000, 0x0300, 0x38000, -0x20000 // Speed Shoes + Underwater
517
0xC0000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0600, 0x80000, -0x40000 // Speed Shoes + Super
518
0x60000, 0x0C00, 0x1800, 0x0600, 0x04000, 0x0300, 0x38000, -0x20000 // Speed Shoes + Super + Underwater
519
end table
520
521
private table Player_TailsPhysicsTable
522
0x60000, 0x0C00, 0x1800, 0x0600, 0x08000, 0x0600, 0x68000, -0x40000 // Normal
523
0x30000, 0x0600, 0x0C00, 0x0300, 0x04000, 0x0300, 0x38000, -0x20000 // Underwater
524
0xA0000, 0x3000, 0x6000, 0x1800, 0x10000, 0x0600, 0x80000, -0x40000 // Super
525
0x50000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0300, 0x38000, -0x20000 // Super + Underwater
526
0xC0000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0600, 0x68000, -0x40000 // Speed Shoes
527
0x60000, 0x0C00, 0x1800, 0x0600, 0x04000, 0x0300, 0x38000, -0x20000 // Speed Shoes + Underwater
528
0xC0000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0600, 0x80000, -0x40000 // Speed Shoes + Super
529
0x60000, 0x0C00, 0x1800, 0x0600, 0x04000, 0x0300, 0x38000, -0x20000 // Speed Shoes + Super + Underwater
530
end table
531
532
private table Player_KnuxPhysicsTable
533
0x60000, 0x0C00, 0x1800, 0x0600, 0x08000, 0x0600, 0x60000, -0x40000 // Normal
534
0x30000, 0x0600, 0x0C00, 0x0300, 0x04000, 0x0300, 0x30000, -0x20000 // Underwater
535
0xA0000, 0x3000, 0x6000, 0x1800, 0x10000, 0x0600, 0x60000, -0x40000 // Super
536
0x50000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0300, 0x30000, -0x20000 // Super + Underwater
537
0xC0000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0600, 0x60000, -0x40000 // Speed Shoes
538
0x60000, 0x0C00, 0x1800, 0x0600, 0x04000, 0x0300, 0x30000, -0x20000 // Speed Shoes + Underwater
539
0xC0000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0600, 0x60000, -0x40000 // Speed Shoes + Super
540
0x60000, 0x0C00, 0x1800, 0x0600, 0x08000, 0x0300, 0x30000, -0x20000 // Speed Shoes + Super + Underwater
541
end table
542
543
private table Player_AmyPhysicsTable
544
0x60000, 0x0C00, 0x1800, 0x0600, 0x08000, 0x0600, 0x68000, -0x40000 // Normal
545
0x30000, 0x0600, 0x0C00, 0x0300, 0x04000, 0x0300, 0x38000, -0x20000 // Underwater
546
0xA0000, 0x3000, 0x6000, 0x1800, 0x10000, 0x0600, 0x80000, -0x40000 // Super
547
0x50000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0300, 0x38000, -0x20000 // Super + Underwater
548
0xC0000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0600, 0x68000, -0x40000 // Speed Shoes
549
0x60000, 0x0C00, 0x1800, 0x0600, 0x04000, 0x0300, 0x38000, -0x20000 // Speed Shoes + Underwater
550
0xC0000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0600, 0x80000, -0x40000 // Speed Shoes + Super
551
0x60000, 0x0C00, 0x1800, 0x0600, 0x04000, 0x0300, 0x38000, -0x20000 // Speed Shoes + Super + Underwater
552
end table
553
554
555
// ========================
556
// Function Definitions
557
// ========================
558
559
public function Player_HandleAmyHitbox
560
#platform: USE_ORIGINS
561
// Bug Details: (first line of code in the script and there's already something, huh?)
562
// This checks against P1's character ID, and while that's fine in singleplayer, it fails to account for P2 Amy in VS...
563
// Not that it matters, the Player 2 Object doesn't call this function anyway
564
565
if stage.playerListPos == PLAYER_AMY
566
temp0 = false
567
568
if player[currentPlayer].animation == ANI_HAMMER_JUMP
569
temp0 = true
570
571
player[currentPlayer].hitboxTop = -25
572
player[currentPlayer].hitboxBottom = 25
573
player[currentPlayer].hitboxLeft = -25
574
player[currentPlayer].hitboxRight = 25
575
end if
576
577
if player[currentPlayer].animation == ANI_HAMMER_DASH
578
temp0 = true
579
580
player[currentPlayer].hitboxBottom = 17
581
player[currentPlayer].hitboxTop = -24
582
player[currentPlayer].hitboxLeft = -18
583
player[currentPlayer].hitboxRight = 10
584
585
switch player[currentPlayer].frame
586
case 0
587
case 4
588
player[currentPlayer].hitboxTop = -17
589
player[currentPlayer].hitboxLeft = -10
590
player[currentPlayer].hitboxRight = 23
591
break
592
593
case 1
594
case 5
595
player[currentPlayer].hitboxTop = -17
596
player[currentPlayer].hitboxLeft = -23
597
player[currentPlayer].hitboxRight = 10
598
break
599
600
case 2
601
case 6
602
player[currentPlayer].hitboxTop = -24
603
player[currentPlayer].hitboxLeft = -18
604
player[currentPlayer].hitboxRight = 10
605
break
606
607
case 3
608
case 7
609
player[currentPlayer].hitboxTop = -26
610
player[currentPlayer].hitboxLeft = -10
611
player[currentPlayer].hitboxRight = 25
612
break
613
end switch
614
615
if player[currentPlayer].direction == FACING_LEFT
616
// Swap the left and right values
617
temp1 = player[currentPlayer].hitboxLeft
618
player[currentPlayer].hitboxLeft = player[currentPlayer].hitboxRight
619
player[currentPlayer].hitboxRight = temp1
620
player[currentPlayer].hitboxLeft *= -1
621
player[currentPlayer].hitboxRight *= -1
622
end if
623
end if
624
625
if temp0 == false
626
// Default to regular hitbox
627
player[currentPlayer].hitboxTop = C_BOX
628
player[currentPlayer].hitboxBottom = C_BOX
629
player[currentPlayer].hitboxLeft = C_BOX
630
player[currentPlayer].hitboxRight = C_BOX
631
end if
632
end if
633
#endplatform
634
end function
635
636
637
// Initialize the character object for replay playback
638
public function Player_SetupAttractDemo
639
Player_attractTablePos = 2
640
Player_attractFrameCount = 1
641
642
currentPlayer = SLOT_PLAYER1
643
while currentPlayer < playerCount
644
GetTableValue(player[currentPlayer].xpos, 0, Player_attractTable)
645
GetTableValue(player[currentPlayer].ypos, 1, Player_attractTable)
646
player[currentPlayer].controlMode = CONTROLMODE_NONE
647
player[currentPlayer].up = false
648
player[currentPlayer].down = false
649
player[currentPlayer].left = false
650
player[currentPlayer].right = false
651
player[currentPlayer].jumpPress = false
652
player[currentPlayer].jumpHold = false
653
player[currentPlayer].timer = 0
654
currentPlayer++
655
loop
656
657
camera[0].xpos = player[SLOT_PLAYER1].ixpos
658
camera[0].ypos = player[SLOT_PLAYER1].iypos
659
end function
660
661
662
public function Player_ApplyShield
663
switch player[currentPlayer].shield
664
case SHIELD_NONE
665
ResetObjectEntity(arrayPos0, TypeName[Blank Object], 0, 0, 0)
666
break
667
668
case SHIELD_NORMAL
669
ResetObjectEntity(arrayPos0, blueShieldType, 0, 0, 0)
670
object[arrayPos0].priority = PRIORITY_ACTIVE
671
object[arrayPos0].inkEffect = INK_ALPHA
672
object[arrayPos0].alpha = 0xA0
673
break
674
675
case SHIELD_BUBBLE
676
ResetObjectEntity(arrayPos0, TypeName[Bubble Shield], 0, 0, 0)
677
object[arrayPos0].priority = PRIORITY_ACTIVE
678
break
679
680
case SHIELD_FIRE
681
ResetObjectEntity(arrayPos0, TypeName[Fire Shield], 0, 0, 0)
682
object[arrayPos0].priority = PRIORITY_ACTIVE
683
break
684
685
case SHIELD_LIGHTNING
686
ResetObjectEntity(arrayPos0, TypeName[LightningShield], 0, 0, 0)
687
object[arrayPos0].priority = PRIORITY_ACTIVE
688
break
689
end switch
690
end function
691
692
693
public function Player_HandleSuperPalette_Sonic
694
if Player_superState == SUPERSTATE_SUPER
695
Player_superBlendTimer++
696
if Player_superBlendTimer >= 4
697
Player_superBlendTimer = 0
698
699
Player_superBlendClr += 4
700
if Player_superBlendClr >= 64
701
Player_superBlendClr = 24
702
end if
703
end if
704
else
705
Player_superBlendTimer++
706
if Player_superBlendTimer >= 8
707
Player_superBlendTimer = 0
708
709
Player_superBlendClr -= 4
710
if Player_superBlendClr <= 0
711
Player_superBlendClr = 0
712
Player_superState = SUPERSTATE_NONE
713
end if
714
715
if Player_superBlendClr >= 24
716
Player_superBlendClr = 24
717
end if
718
end if
719
end if
720
721
temp1 = Player_superBlendClr
722
723
GetTableValue(temp0, temp1, Player_SonicSuperPal)
724
SetPaletteEntry(0, 2, temp0)
725
GetTableValue(temp0, temp1, Player_SonicSuperAltPal)
726
SetPaletteEntry(1, 2, temp0)
727
temp1++
728
729
GetTableValue(temp0, temp1, Player_SonicSuperPal)
730
SetPaletteEntry(0, 3, temp0)
731
GetTableValue(temp0, temp1, Player_SonicSuperAltPal)
732
SetPaletteEntry(1, 3, temp0)
733
temp1++
734
735
GetTableValue(temp0, temp1, Player_SonicSuperPal)
736
SetPaletteEntry(0, 4, temp0)
737
GetTableValue(temp0, temp1, Player_SonicSuperAltPal)
738
SetPaletteEntry(1, 4, temp0)
739
temp1++
740
741
GetTableValue(temp0, temp1, Player_SonicSuperPal)
742
SetPaletteEntry(0, 5, temp0)
743
GetTableValue(temp0, temp1, Player_SonicSuperAltPal)
744
SetPaletteEntry(1, 5, temp0)
745
end function
746
747
748
public function Player_HandleSuperPalette_Tails
749
if Player_superState == SUPERSTATE_SUPER
750
Player_superBlendTimer++
751
if Player_superBlendTimer >= 12
752
Player_superBlendTimer = 0
753
754
Player_superBlendClr += 4
755
if Player_superBlendClr >= 24
756
Player_superBlendClr = 0
757
end if
758
end if
759
else
760
if Player_superBlendClr > 12
761
FlipSign(Player_superBlendClr)
762
Player_superBlendClr += 24
763
end if
764
765
Player_superBlendTimer++
766
if Player_superBlendTimer >= 12
767
Player_superBlendTimer = 0
768
769
Player_superBlendClr -= 4
770
if Player_superBlendClr <= 0
771
Player_superBlendClr = 0
772
Player_superState = SUPERSTATE_NONE
773
end if
774
end if
775
end if
776
777
temp1 = Player_superBlendClr
778
779
GetTableValue(temp0, temp1, Player_TailsSuperPal)
780
SetPaletteEntry(0, 13, temp0)
781
GetTableValue(temp0, temp1, Player_TailsSuperAltPal)
782
SetPaletteEntry(1, 13, temp0)
783
temp1++
784
785
GetTableValue(temp0, temp1, Player_TailsSuperPal)
786
SetPaletteEntry(0, 17, temp0)
787
GetTableValue(temp0, temp1, Player_TailsSuperAltPal)
788
SetPaletteEntry(1, 17, temp0)
789
temp1++
790
791
GetTableValue(temp0, temp1, Player_TailsSuperPal)
792
SetPaletteEntry(0, 18, temp0)
793
GetTableValue(temp0, temp1, Player_TailsSuperAltPal)
794
SetPaletteEntry(1, 18, temp0)
795
temp1++
796
797
GetTableValue(temp0, temp1, Player_TailsSuperPal)
798
SetPaletteEntry(0, 16, temp0)
799
GetTableValue(temp0, temp1, Player_TailsSuperAltPal)
800
SetPaletteEntry(1, 16, temp0)
801
end function
802
803
804
public function Player_HandleSuperPalette_Knux
805
if Player_superState == SUPERSTATE_SUPER
806
Player_superBlendTimer++
807
if Player_superBlendTimer >= 12
808
Player_superBlendTimer = 9
809
810
Player_superBlendClr += 3
811
if Player_superBlendClr >= 30
812
Player_superBlendTimer = 0
813
Player_superBlendClr = 0
814
end if
815
end if
816
else
817
if Player_superBlendClr > 15
818
FlipSign(Player_superBlendClr)
819
Player_superBlendClr += 30
820
end if
821
822
Player_superBlendTimer++
823
if Player_superBlendTimer >= 12
824
Player_superBlendTimer = 0
825
826
Player_superBlendClr -= 3
827
if Player_superBlendClr <= 0
828
Player_superBlendClr = 0
829
Player_superState = SUPERSTATE_NONE
830
end if
831
end if
832
end if
833
834
temp1 = Player_superBlendClr
835
836
GetTableValue(temp0, temp1, Player_KnuxSuperPal)
837
SetPaletteEntry(0, 26, temp0)
838
GetTableValue(temp0, temp1, Player_KnuxSuperAltPal)
839
SetPaletteEntry(1, 26, temp0)
840
temp1++
841
842
GetTableValue(temp0, temp1, Player_KnuxSuperPal)
843
SetPaletteEntry(0, 27, temp0)
844
GetTableValue(temp0, temp1, Player_KnuxSuperAltPal)
845
SetPaletteEntry(1, 27, temp0)
846
temp1++
847
848
GetTableValue(temp0, temp1, Player_KnuxSuperPal)
849
SetPaletteEntry(0, 28, temp0)
850
GetTableValue(temp0, temp1, Player_KnuxSuperAltPal)
851
SetPaletteEntry(1, 28, temp0)
852
end function
853
854
855
public function Player_HandleSuperPalette_Amy
856
#platform: USE_ORIGINS
857
if Player_superState == SUPERSTATE_SUPER
858
Player_superBlendTimer++
859
if Player_superBlendTimer >= 12
860
Player_superBlendTimer = 5
861
Player_superBlendClr += 5
862
if Player_superBlendClr >= 50
863
Player_superBlendClr = 0
864
end if
865
end if
866
else
867
if Player_superBlendClr > 15
868
FlipSign(Player_superBlendClr)
869
Player_superBlendClr += 50
870
end if
871
872
Player_superBlendTimer++
873
if Player_superBlendTimer >= 12
874
Player_superBlendTimer = 0
875
Player_superBlendClr -= 5
876
if Player_superBlendClr <= 0
877
Player_superBlendClr = 0
878
Player_superState = SUPERSTATE_NONE
879
end if
880
end if
881
end if
882
883
temp1 = Player_superBlendClr
884
885
GetTableValue(temp0, temp1, Player_AmySuperPal)
886
SetPaletteEntry(0, 54, temp0)
887
GetTableValue(temp0, temp1, Player_AmySuperAltPal)
888
SetPaletteEntry(1, 54, temp0)
889
temp1++
890
891
GetTableValue(temp0, temp1, Player_AmySuperPal)
892
SetPaletteEntry(0, 50, temp0)
893
GetTableValue(temp0, temp1, Player_AmySuperAltPal)
894
SetPaletteEntry(1, 50, temp0)
895
temp1++
896
897
GetTableValue(temp0, temp1, Player_AmySuperPal)
898
SetPaletteEntry(0, 51, temp0)
899
GetTableValue(temp0, temp1, Player_AmySuperAltPal)
900
SetPaletteEntry(1, 51, temp0)
901
temp1++
902
903
GetTableValue(temp0, temp1, Player_AmySuperPal)
904
SetPaletteEntry(0, 52, temp0)
905
GetTableValue(temp0, temp1, Player_AmySuperAltPal)
906
SetPaletteEntry(1, 52, temp0)
907
temp1++
908
909
GetTableValue(temp0, temp1, Player_AmySuperPal)
910
SetPaletteEntry(0, 53, temp0)
911
GetTableValue(temp0, temp1, Player_AmySuperAltPal)
912
SetPaletteEntry(1, 53, temp0)
913
#endplatform
914
end function
915
916
917
public function Player_UpdatePhysicsState
918
// Bug Details:
919
// -> While this works fine in singleplayer and 2013's online multiplayer, this doesn't work as intended in Origins's local 2PVS
920
// Namely, this function here is looking at stage.playerListPos, which is P1's character ID, meaning that P2 will always assume P1's physics
921
// -> This means that, for example, you can have P2 Sonic with Knuckles's jump height, lots of softlocks incoming...
922
923
switch stage.playerListPos
924
case PLAYER_SONIC_A
925
case PLAYER_SONIC_TAILS_A
926
temp0 = Player_SonicPhysicsTable
927
break
928
929
case PLAYER_TAILS_A
930
temp0 = Player_TailsPhysicsTable
931
break
932
933
case PLAYER_KNUCKLES_A
934
temp0 = Player_KnuxPhysicsTable
935
break
936
937
#platform: USE_ORIGINS
938
case PLAYER_AMY_A
939
temp0 = Player_AmyPhysicsTable
940
break
941
#endplatform
942
end switch
943
944
temp1 = 0
945
temp2 = 0
946
if stage.state != STAGE_FROZEN
947
temp3 = player[currentPlayer].ypos
948
temp3 >>= 16
949
CheckGreater(temp3, stage.waterLevel)
950
temp4 = checkResult
951
CheckNotEqual(player[currentPlayer].type, TypeName[Debug Mode])
952
temp4 &= checkResult
953
if temp4 == true
954
SetBit(temp1, 0, true)
955
player[currentPlayer].gravityStrength = 0x1000
956
else
957
player[currentPlayer].gravityStrength = 0x3800
958
end if
959
960
if Player_superState == SUPERSTATE_SUPER
961
#platform: USE_ORIGINS
962
// Tails can no longer be silly :(
963
if player[currentPlayer].isSidekick == false
964
#endplatform
965
SetBit(temp1, 1, true)
966
temp2 = 2
967
#platform: USE_ORIGINS
968
end if
969
#endplatform
970
end if
971
972
if player[currentPlayer].speedShoesTimer > 0
973
SetBit(temp1, 2, true)
974
temp2 = 1
975
end if
976
977
temp1 <<= 3
978
end if
979
980
GetTableValue(player[currentPlayer].topSpeed, temp1, temp0)
981
temp1++
982
GetTableValue(player[currentPlayer].acceleration, temp1, temp0)
983
player[currentPlayer].deceleration = player[currentPlayer].acceleration
984
player[currentPlayer].deceleration >>= temp2
985
temp1++
986
GetTableValue(player[currentPlayer].airAcceleration, temp1, temp0)
987
temp1++
988
GetTableValue(player[currentPlayer].airDeceleration, temp1, temp0)
989
temp1++
990
GetTableValue(player[currentPlayer].skidSpeed, temp1, temp0)
991
temp1++
992
GetTableValue(player[currentPlayer].rollingFriction, temp1, temp0)
993
temp1++
994
GetTableValue(player[currentPlayer].jumpStrength, temp1, temp0)
995
temp1++
996
GetTableValue(player[currentPlayer].jumpCap, temp1, temp0)
997
end function
998
999
1000
public function Player_HandleSuperForm
1001
if Player_superState != SUPERSTATE_NONE
1002
switch stage.playerListPos
1003
case PLAYER_SONIC_A
1004
case PLAYER_SONIC_TAILS_A
1005
CallFunction(Player_HandleSuperPalette_Sonic)
1006
break
1007
1008
case PLAYER_TAILS_A
1009
CallFunction(Player_HandleSuperPalette_Tails)
1010
break
1011
1012
case PLAYER_KNUCKLES_A
1013
CallFunction(Player_HandleSuperPalette_Knux)
1014
break
1015
1016
#platform: USE_ORIGINS
1017
case PLAYER_AMY_A
1018
CallFunction(Player_HandleSuperPalette_Amy)
1019
break
1020
#endplatform
1021
end switch
1022
end if
1023
1024
if Player_superState == SUPERSTATE_SUPER
1025
player.invincibleTimer = 60
1026
Player_superRingLossTimer++
1027
if Player_superRingLossTimer == 60
1028
Player_superRingLossTimer = 0
1029
1030
player.rings--
1031
if player.rings <= 0
1032
player.rings = 0
1033
Player_superState = SUPERSTATE_FADEOUT
1034
end if
1035
end if
1036
end if
1037
1038
if Player_superState == SUPERSTATE_FADEOUT
1039
if stage.playerListPos == PLAYER_SONIC_A
1040
LoadAnimation("Sonic.ani") // Restore the normal Sonic sprites
1041
end if
1042
1043
if music.currentTrack == TRACK_SUPER
1044
PlayMusic(TRACK_STAGE)
1045
end if
1046
1047
player.invincibleTimer = 0
1048
currentPlayer = player.entityPos
1049
if player.state != Player_State_Death
1050
if player.state != Player_State_Drown
1051
arrayPos0 = currentPlayer
1052
arrayPos0 += playerCount
1053
CallFunction(Player_ApplyShield)
1054
end if
1055
end if
1056
1057
Player_superState = SUPERSTATE_END
1058
CallFunction(Player_UpdatePhysicsState)
1059
end if
1060
end function
1061
1062
1063
public function Player_CheckHit
1064
CheckEqual(player[currentPlayer].animation, ANI_JUMPING)
1065
temp0 = checkResult
1066
CheckEqual(player[currentPlayer].animation, ANI_SPINDASH)
1067
temp0 |= checkResult
1068
CheckEqual(player[currentPlayer].animation, ANI_GLIDING)
1069
temp0 |= checkResult
1070
CheckEqual(player[currentPlayer].animation, ANI_GLIDING_STOP)
1071
temp0 |= checkResult
1072
CheckNotEqual(player[currentPlayer].invincibleTimer, 0)
1073
temp0 |= checkResult
1074
1075
#platform: USE_ORIGINS
1076
// Amy's trusty Pico Pico Hammer can bash through anything!
1077
1078
// Bug Details:
1079
// This checks against P1's character ID, and while that's fine in singleplayer, it fails to account for P2 Amy in VS...
1080
// The reason these checks are here is because of AI Tails (These animations' IDs are the same as some of Tails' fly carry animations), though clearly they weren't implemented properly
1081
if stage.playerListPos == PLAYER_AMY
1082
if player[currentPlayer].isSidekick == false
1083
CheckEqual(player[currentPlayer].animation, ANI_HAMMER_JUMP)
1084
temp0 |= checkResult
1085
CheckEqual(player[currentPlayer].animation, ANI_HAMMER_DASH)
1086
temp0 |= checkResult
1087
end if
1088
end if
1089
#endplatform
1090
1091
// Tails can also destroy badniks when flying, but only if the badnik is above him (hitting his tails)
1092
// So check for that, too
1093
CheckEqual(player[currentPlayer].animation, ANI_FLYING)
1094
temp1 = checkResult
1095
CheckEqual(player[currentPlayer].animation, ANI_FLYINGTIRED)
1096
temp1 |= checkResult
1097
CheckEqual(player[currentPlayer].animation, ANI_FLY_LIFT_UP)
1098
temp1 |= checkResult
1099
CheckEqual(player[currentPlayer].animation, ANI_FLY_LIFT_DOWN)
1100
temp1 |= checkResult
1101
CheckEqual(player[currentPlayer].animation, ANI_FLY_LIFT_TIRED)
1102
temp1 |= checkResult
1103
if temp1 == true
1104
CheckGreater(player[currentPlayer].ypos, object.ypos)
1105
temp0 |= checkResult
1106
end if
1107
1108
if temp0 == true
1109
if player[currentPlayer].gravity == GRAVITY_AIR
1110
FlipSign(player[currentPlayer].xvel)
1111
player[currentPlayer].speed = player[currentPlayer].xvel
1112
player[currentPlayer].yvel += player[currentPlayer].gravityStrength
1113
player[currentPlayer].yvel += player[currentPlayer].gravityStrength
1114
FlipSign(player[currentPlayer].yvel)
1115
end if
1116
1117
if player[currentPlayer].animation == ANI_GLIDING
1118
player[currentPlayer].animation = ANI_GLIDING_DROP
1119
player[currentPlayer].state = Player_State_GlideDrop
1120
end if
1121
1122
checkResult = true
1123
else
1124
if player[currentPlayer].state != Player_State_Death
1125
if player[currentPlayer].invincibleTimer == 0
1126
if player[currentPlayer].blinkTimer == 0
1127
player[currentPlayer].state = Player_State_GotHit
1128
if player[currentPlayer].xpos > object.xpos
1129
player[currentPlayer].speed = 0x20000
1130
else
1131
player[currentPlayer].speed = -0x20000
1132
end if
1133
end if
1134
end if
1135
end if
1136
1137
checkResult = false
1138
end if
1139
end function
1140
1141
1142
public function Player_BadnikBreak
1143
CheckEqual(player[currentPlayer].animation, ANI_JUMPING)
1144
temp0 = checkResult
1145
CheckEqual(player[currentPlayer].animation, ANI_SPINDASH)
1146
temp0 |= checkResult
1147
CheckEqual(player[currentPlayer].animation, ANI_GLIDING)
1148
temp0 |= checkResult
1149
CheckEqual(player[currentPlayer].animation, ANI_GLIDING_STOP)
1150
temp0 |= checkResult
1151
CheckNotEqual(player[currentPlayer].invincibleTimer, 0)
1152
temp0 |= checkResult
1153
1154
#platform: USE_ORIGINS
1155
// Amy's trusty Pico Pico Hammer can bash through anything!
1156
1157
// Bug Details:
1158
// This checks against P1's character ID, and while that's fine in singleplayer, it fails to account for P2 Amy in VS...
1159
// The reason these checks are here is because of AI Tails (These animations' IDs are the same as some of Tails' fly carry animations), though clearly they weren't implemented properly
1160
if stage.playerListPos == PLAYER_AMY
1161
if player[currentPlayer].isSidekick == false
1162
CheckEqual(player[currentPlayer].animation, ANI_HAMMER_JUMP)
1163
temp0 |= checkResult
1164
CheckEqual(player[currentPlayer].animation, ANI_HAMMER_DASH)
1165
temp0 |= checkResult
1166
end if
1167
end if
1168
#endplatform
1169
1170
// Tails can also break badniks that are hit his tails while flying, check for that
1171
CheckEqual(player[currentPlayer].animation, ANI_FLYING)
1172
temp1 = checkResult
1173
CheckEqual(player[currentPlayer].animation, ANI_FLYINGTIRED)
1174
temp1 |= checkResult
1175
CheckEqual(player[currentPlayer].animation, ANI_FLY_LIFT_UP)
1176
temp1 |= checkResult
1177
CheckEqual(player[currentPlayer].animation, ANI_FLY_LIFT_DOWN)
1178
temp1 |= checkResult
1179
CheckEqual(player[currentPlayer].animation, ANI_FLY_LIFT_TIRED)
1180
temp1 |= checkResult
1181
if temp1 == true
1182
CheckGreater(player[currentPlayer].ypos, object.ypos)
1183
temp0 |= checkResult
1184
end if
1185
1186
#platform: USE_ORIGINS
1187
if game.playMode == BOOT_PLAYMODE_MISSION
1188
if stage.timeEnabled == false
1189
temp0 = false
1190
end if
1191
end if
1192
#endplatform
1193
1194
if temp0 == true
1195
#platform: USE_ORIGINS
1196
CheckCurrentStageFolder("Zone01") // Emerald Hill Zone
1197
if checkResult == true
1198
CheckEqual(object.type, TYPE_BUZZER)
1199
temp1 = checkResult
1200
CheckEqual(object.type, TYPE_BEE) // I do appreciate the gesture but, why? As-is, Bees are unused in both the main game and missions, were they planning to do something with them?
1201
temp1 |= checkResult
1202
if temp1 == true
1203
stageStat.buzzerDestroyCount++
1204
end if
1205
end if
1206
#endplatform
1207
1208
ResetObjectEntity(object.entityPos, TypeName[Blank Object], 0, object.xpos, object.ypos)
1209
Rand(checkResult, 32)
1210
if checkResult >= 16
1211
CreateTempObject(animalType1, 0, object.xpos, object.ypos)
1212
else
1213
CreateTempObject(animalType2, 0, object.xpos, object.ypos)
1214
end if
1215
object[tempObjectPos].priority = PRIORITY_ACTIVE_SMALL
1216
1217
CreateTempObject(TypeName[Smoke Puff], 0, object.xpos, object.ypos)
1218
object[tempObjectPos].drawOrder = 4
1219
1220
CreateTempObject(TypeName[Object Score], player[currentPlayer].badnikBonus, object.xpos, object.ypos)
1221
object[tempObjectPos].drawOrder = 4
1222
1223
#platform: USE_STANDALONE
1224
PlaySfx(SfxName[Destroy], false)
1225
#endplatform
1226
1227
#platform: USE_ORIGINS
1228
// Bug Details: See above
1229
1230
temp2 = false
1231
1232
if stage.playerListPos == PLAYER_AMY
1233
if player[currentPlayer].isSidekick == false
1234
if player[currentPlayer].animation == ANI_HAMMER_JUMP
1235
temp2 = true
1236
end if
1237
1238
if player[currentPlayer].animation == ANI_HAMMER_DASH
1239
temp2 = true
1240
end if
1241
end if
1242
end if
1243
1244
if temp2 == true
1245
PlaySfx(SfxName[HammerHit], false)
1246
else
1247
PlaySfx(SfxName[Destroy], false)
1248
end if
1249
#endplatform
1250
1251
if player[currentPlayer].yvel > 0
1252
if player[currentPlayer].ypos >= object.ypos
1253
player[currentPlayer].yvel -= 0x10000
1254
else
1255
player[currentPlayer].yvel += player[currentPlayer].gravityStrength
1256
player[currentPlayer].yvel += player[currentPlayer].gravityStrength
1257
FlipSign(player[currentPlayer].yvel)
1258
end if
1259
else
1260
player[currentPlayer].yvel += 0x10000
1261
end if
1262
temp1 = arrayPos0
1263
1264
// global variable "array" (yes, this is actually how its done)
1265
if options.vsMode == false
1266
temp0 = currentPlayer
1267
currentPlayer = SLOT_PLAYER1
1268
arrayPos0 = GLOBAL_PLAYERSCORE
1269
#platform: USE_DECOMP
1270
arrayPos0 = VarName[player.score]
1271
#endplatform
1272
else
1273
arrayPos0 = GLOBAL_PLAYERSCORE
1274
#platform: USE_DECOMP
1275
arrayPos0 = VarName[player.score]
1276
#endplatform
1277
arrayPos0 += currentPlayer
1278
end if
1279
1280
switch player[currentPlayer].badnikBonus
1281
case 0
1282
global[arrayPos0] += 100
1283
break
1284
1285
case 1
1286
global[arrayPos0] += 200
1287
break
1288
1289
case 2
1290
global[arrayPos0] += 500
1291
break
1292
1293
case 3
1294
case 4
1295
case 5
1296
case 6
1297
case 7
1298
case 8
1299
case 9
1300
case 10
1301
case 11
1302
case 12
1303
case 13
1304
case 14
1305
global[arrayPos0] += 1000
1306
break
1307
1308
case 15
1309
global[arrayPos0] += 10000
1310
break
1311
1312
end switch
1313
1314
if player[currentPlayer].badnikBonus < 15
1315
player[currentPlayer].badnikBonus++
1316
end if
1317
1318
if options.vsMode == false
1319
currentPlayer = temp0
1320
end if
1321
arrayPos0 = temp1
1322
1323
#platform: USE_ORIGINS
1324
temp0 = 0
1325
1326
// While it's used in Sonic 1, there aren't any missions in Sonic 2 which utilise this
1327
CheckEqual(player[currentPlayer].state, Player_State_Roll)
1328
temp1 = checkResult
1329
CheckEqual(player[currentPlayer].state, Player_State_RollJump)
1330
temp1 |= checkResult
1331
if temp1 == true
1332
if object.propertyValue == 0
1333
temp0 = KILL_ENEMY_ATTR_SPINDASH
1334
stageStat.spindashDestroyCount++
1335
end if
1336
end if
1337
1338
// Same case for this, too
1339
CheckEqual(player[currentPlayer].state, Player_State_GlideLeft)
1340
temp1 = checkResult
1341
CheckEqual(player[currentPlayer].state, Player_State_GlideRight)
1342
temp1 |= checkResult
1343
if temp1 == true
1344
temp0 = KILL_ENEMY_ATTR_GLIDING
1345
end if
1346
1347
stageStat.badnikDestroyCount++
1348
1349
// This one's used, though
1350
CallNativeFunction2(NotifyCallback, NOTIFY_KILL_ENEMY, temp0)
1351
if game.playMode == BOOT_PLAYMODE_MISSION
1352
if game.missionFunctionNo == MISSIONNO_MERCY
1353
game.forceKillPlayer = true
1354
end if
1355
end if
1356
#endplatform
1357
else
1358
if player[currentPlayer].state != Player_State_Death
1359
if player[currentPlayer].invincibleTimer == 0
1360
if player[currentPlayer].blinkTimer == 0
1361
player[currentPlayer].state = Player_State_GotHit
1362
1363
#platform: USE_ORIGINS
1364
if game.playMode == BOOT_PLAYMODE_MISSION
1365
if game.missionFunctionNo == MISSIONNO_MERCY
1366
game.missionValue = true
1367
end if
1368
end if
1369
#endplatform
1370
1371
if player[currentPlayer].xpos > object.xpos
1372
player[currentPlayer].speed = 0x20000
1373
else
1374
player[currentPlayer].speed = -0x20000
1375
end if
1376
end if
1377
end if
1378
end if
1379
end if
1380
end function
1381
1382
1383
public function Player_Hit
1384
if player[currentPlayer].state != Player_State_Death
1385
arrayPos0 = player[currentPlayer].entityPos
1386
arrayPos0 += playerCount
1387
if player[currentPlayer].invincibleTimer == 0
1388
if player[currentPlayer].blinkTimer == 0
1389
player[currentPlayer].state = Player_State_GotHit
1390
if player[currentPlayer].xpos > object.xpos
1391
player[currentPlayer].speed = 0x20000
1392
else
1393
player[currentPlayer].speed = -0x20000
1394
end if
1395
end if
1396
end if
1397
end if
1398
end function
1399
1400
1401
public function Player_FireHit
1402
if player[currentPlayer].shield != SHIELD_FIRE
1403
if player[currentPlayer].state != Player_State_Death
1404
arrayPos0 = player[currentPlayer].entityPos
1405
arrayPos0 += playerCount
1406
if player[currentPlayer].invincibleTimer == 0
1407
if player[currentPlayer].blinkTimer == 0
1408
player[currentPlayer].state = Player_State_GotHit
1409
if player[currentPlayer].xpos > object.xpos
1410
player[currentPlayer].speed = 0x20000
1411
else
1412
player[currentPlayer].speed = -0x20000
1413
end if
1414
end if
1415
end if
1416
end if
1417
end if
1418
end function
1419
1420
1421
public function Player_LightningHit
1422
if player[currentPlayer].shield != SHIELD_LIGHTNING
1423
if player[currentPlayer].state != Player_State_Death
1424
arrayPos0 = player[currentPlayer].entityPos
1425
arrayPos0 += playerCount
1426
if player[currentPlayer].invincibleTimer == 0
1427
if player[currentPlayer].blinkTimer == 0
1428
player[currentPlayer].state = Player_State_GotHit
1429
if player[currentPlayer].xpos > object.xpos
1430
player[currentPlayer].speed = 0x20000
1431
else
1432
player[currentPlayer].speed = -0x20000
1433
end if
1434
end if
1435
end if
1436
end if
1437
end if
1438
end function
1439
1440
1441
public function Player_ProjectileHit
1442
if player[currentPlayer].shield > SHIELD_NORMAL // Only elemental shields should relfect projectiles
1443
temp0 = player[currentPlayer].xpos
1444
temp0 -= object.xpos
1445
1446
temp1 = player[currentPlayer].ypos
1447
temp1 -= object.ypos
1448
1449
ATan2(temp2, temp0, temp1)
1450
Sin256(temp0, temp2)
1451
Cos256(temp1, temp2)
1452
1453
object.xvel = temp1
1454
object.xvel *= -0x800
1455
object.yvel = temp0
1456
object.yvel *= -0x800
1457
else
1458
if player[currentPlayer].state != Player_State_Death
1459
arrayPos0 = player[currentPlayer].entityPos
1460
arrayPos0 += playerCount
1461
1462
if player[currentPlayer].invincibleTimer == 0
1463
if player[currentPlayer].blinkTimer == 0
1464
player[currentPlayer].state = Player_State_GotHit
1465
1466
if player[currentPlayer].xpos > object.xpos
1467
player[currentPlayer].speed = 0x20000
1468
else
1469
player[currentPlayer].speed = -0x20000
1470
end if
1471
end if
1472
end if
1473
end if
1474
end if
1475
end function
1476
1477
1478
public function Player_SpikeHit
1479
if player[currentPlayer].state != Player_State_Death
1480
arrayPos0 = player[currentPlayer].entityPos
1481
arrayPos0 += playerCount
1482
1483
if player[currentPlayer].invincibleTimer == 0
1484
if player[currentPlayer].state != Player_State_GotHit
1485
if player[currentPlayer].state != Player_State_Hurt
1486
// Check for spike bug and player invulnerability
1487
// Do note though, by default spike bug is disabled in this game and there's no way to turn it on (disregading the Broken Monitor dead code) so only this second blink timer check actually does anything
1488
temp0 = options.spikeBehavior
1489
CheckEqual(player[currentPlayer].blinkTimer, 0)
1490
temp0 |= checkResult
1491
1492
if temp0 == true
1493
if player[currentPlayer].blinkTimer == 0
1494
player[currentPlayer].blinkTimer = 2
1495
end if
1496
1497
player[currentPlayer].state = Player_State_GotHit
1498
if player[currentPlayer].xpos > object.xpos
1499
player[currentPlayer].speed = 0x20000
1500
else
1501
player[currentPlayer].speed = -0x20000
1502
end if
1503
end if
1504
end if
1505
end if
1506
end if
1507
end if
1508
end function
1509
1510
1511
public function Player_Kill
1512
#platform: USE_ORIGINS
1513
// Bug Details:
1514
// This code was added in 2.0.1 to prevent the player from dying after clearing/failing a mission
1515
// However, they used temp0 here, which causes objects that use that variable when updating its position to disappear
1516
// (This bug was fixed in 2.0.0, but now it's back, hooray!)
1517
1518
temp0 = false
1519
if game.playMode == BOOT_PLAYMODE_MISSION
1520
if stage.timeEnabled == false
1521
temp0 = true
1522
end if
1523
end if
1524
1525
if temp0 == false
1526
CallFunction(Player_CheckIfOnScreen)
1527
if checkResult != false
1528
PlaySfx(SfxName[Hurt], false)
1529
end if
1530
#endplatform
1531
1532
#platform: USE_STANDALONE
1533
PlaySfx(SfxName[Hurt], false)
1534
#endplatform
1535
1536
player[currentPlayer].speed = 0
1537
player[currentPlayer].xvel = 0
1538
player[currentPlayer].yvel = -0x68000
1539
player[currentPlayer].state = Player_State_Death
1540
player[currentPlayer].animation = ANI_DYING
1541
player[currentPlayer].tileCollisions = false
1542
player[currentPlayer].interaction = false
1543
player[currentPlayer].blinkTimer = 0
1544
player[currentPlayer].visible = true
1545
#platform: USE_STANDALONE
1546
player[currentPlayer].sortedDrawOrder = 6
1547
#endplatform
1548
#platform: USE_ORIGINS
1549
player[currentPlayer].sortedDrawOrder = 7
1550
#endplatform
1551
1552
if options.vsMode == false
1553
if currentPlayer == 0
1554
// If P1 is the one who died, then freeze everything else
1555
player[currentPlayer].priority = PRIORITY_ALWAYS
1556
if player[1].type == TypeName[Player 2 Object]
1557
player[1].priority = PRIORITY_ALWAYS
1558
end if
1559
1560
camera[0].enabled = false
1561
stage.state = STAGE_FROZEN
1562
end if
1563
else
1564
#platform: USE_STANDALONE
1565
if currentPlayer == camera[0].target
1566
camera[0].enabled = false
1567
end if
1568
#endplatform
1569
1570
#platform: USE_ORIGINS
1571
if currentPlayer == camera[currentPlayer].target
1572
camera[currentPlayer].style = CAMERASTYLE_STATIC
1573
end if
1574
#endplatform
1575
end if
1576
1577
// Move to the shield object slot
1578
arrayPos0 = currentPlayer
1579
arrayPos0 += playerCount
1580
1581
if object[arrayPos0].type == invincibilityType
1582
// This... doesn't actually seem to do anything
1583
object[arrayPos0].propertyValue = 3
1584
end if
1585
1586
// Remove the player's shield
1587
object[arrayPos0].type = TypeName[Blank Object]
1588
player[currentPlayer].shield = SHIELD_NONE
1589
#platform: USE_ORIGINS
1590
else
1591
player[currentPlayer].disableGravity = true
1592
end if
1593
#endplatform
1594
end function
1595
1596
1597
public function Player_ProcessUpdate
1598
if options.attractMode == false
1599
#platform: USE_STANDALONE
1600
if player.controlMode == CONTROLMODE_P1
1601
// No control lock active right now, process player control
1602
1603
// Check if the player's touched the bottom left of the screen
1604
CheckTouchRect(0, 96, screen.xcenter, screen.ysize)
1605
1606
if checkResult > -1
1607
arrayPos0 = checkResult
1608
1609
temp0 = touchscreen[arrayPos0].xpos
1610
temp0 -= saveRAM[39] // Virtual DPad X Pos
1611
1612
temp1 = touchscreen[arrayPos0].ypos
1613
temp1 -= saveRAM[40] // Virtual DPad Y Pos
1614
1615
ATan2(temp2, temp0, temp1)
1616
temp2 += 32
1617
temp2 &= 255
1618
temp2 >>= 6
1619
1620
switch temp2
1621
case 0
1622
keyDown[1].right = true
1623
break
1624
1625
case 1
1626
keyDown[1].down = true
1627
break
1628
1629
case 2
1630
keyDown[1].left = true
1631
break
1632
1633
case 3
1634
keyDown[1].up = true
1635
break
1636
end switch
1637
end if
1638
1639
// And now check if the player's touched the jump button portion of the touch screen
1640
CheckTouchRect(screen.xcenter, 96, screen.xsize, 240)
1641
1642
if checkResult > -1
1643
keyDown[1].buttonA = true
1644
end if
1645
1646
// Update touchJump
1647
// (touchJump is the state of the touchscreen jump button the previous frame, used to differenciate new taps from previous holds)
1648
if touchJump == false
1649
keyPress[1].buttonA |= keyDown[1].buttonA
1650
end if
1651
touchJump = keyDown[1].buttonA
1652
1653
if stage.debugMode == true
1654
// If in Debug Mode, check for the item switcher button too
1655
CheckTouchRect(0, 0, 112, 56)
1656
if checkResult > -1
1657
keyDown[1].buttonB = true
1658
end if
1659
1660
// Update touchDebug too, it's the B button equivalent of touchJump
1661
if touchDebug == false
1662
keyPress[1].buttonB |= keyDown[1].buttonB
1663
end if
1664
touchDebug = keyDown[1].buttonB
1665
end if
1666
1667
// Check for the pause button being pressed as well
1668
CheckTouchRect(240, 0, screen.xsize, 40)
1669
if checkResult > -1
1670
if options.vsMode == false
1671
PlaySfx(SfxName[Menu Back], false)
1672
StopSfx(SfxName[Flying])
1673
StopSfx(SfxName[Tired])
1674
engine.state = 5
1675
end if
1676
end if
1677
1678
if keyPress[0].start == true
1679
if options.vsMode == false
1680
PlaySfx(SfxName[Menu Back], false)
1681
StopSfx(SfxName[Flying])
1682
StopSfx(SfxName[Tired])
1683
engine.state = 5
1684
end if
1685
end if
1686
end if
1687
#endplatform
1688
1689
#platform: USE_ORIGINS
1690
// Origins doesn't have any of that fancy touch stuff to account for, just a single pause button
1691
if keyPress[1].start == true
1692
engine.state = 5
1693
end if
1694
#endplatform
1695
1696
// Call the function for supporting physical gamepads as well
1697
ProcessObjectControl()
1698
1699
if options.vsMode == true
1700
// If in comp mode, send over the player at this point
1701
CallNativeFunction2(SendEntity, 0, false)
1702
end if
1703
else
1704
// No pausing during credits
1705
// (I don't think this actually does anything, though..? Sonic 2 doesn't have in-game credits like Sonic 1 did)
1706
if credits.screen == 0
1707
#platform: USE_STANDALONE
1708
// Allow skipping of the demo by pausing
1709
CheckTouchRect(0, 0, screen.xsize, screen.ysize)
1710
if keyPress[0].start == true
1711
checkResult = 0
1712
end if
1713
1714
if checkResult > -1
1715
if Player_attractDuration > 1
1716
Player_attractDuration = 1
1717
end if
1718
end if
1719
1720
if keyPress[0].start == true
1721
if Player_attractDuration > 1
1722
Player_attractDuration = 1
1723
end if
1724
end if
1725
#endplatform
1726
1727
#platform: USE_ORIGINS
1728
if keyPress[1].start == true
1729
if Player_attractDuration > 1
1730
Player_attractDuration = 1
1731
end if
1732
end if
1733
#endplatform
1734
end if
1735
1736
if player.controlMode == CONTROLMODE_P1
1737
Player_attractFrameCount--
1738
if Player_attractFrameCount < 1
1739
if Player_attractTablePos < Player_attractTableSize
1740
GetTableValue(temp0, Player_attractTablePos, Player_attractTable)
1741
GetBit(player.up, temp0, 0)
1742
GetBit(player.down, temp0, 1)
1743
GetBit(player.left, temp0, 2)
1744
GetBit(player.right, temp0, 3)
1745
GetBit(player.jumpPress, temp0, 4)
1746
GetBit(player.jumpHold, temp0, 5)
1747
Player_attractTablePos++
1748
GetTableValue(Player_attractFrameCount, Player_attractTablePos, Player_attractTable)
1749
Player_attractTablePos++
1750
end if
1751
else
1752
if player.jumpPress == true
1753
player.jumpPress = false
1754
end if
1755
end if
1756
1757
if Player_attractDuration > 0
1758
Player_attractDuration--
1759
if Player_attractDuration < 1
1760
ResetObjectEntity(SLOT_TITLECARD, TypeName[Title Card], 0, 0, 0)
1761
object[SLOT_TITLECARD].state = 8
1762
object[SLOT_TITLECARD].priority = PRIORITY_ACTIVE
1763
object[SLOT_TITLECARD].drawOrder = 6
1764
player.invincibleTimer = 80
1765
camera[0].enabled = false
1766
end if
1767
end if
1768
end if
1769
end if
1770
1771
if player.speedShoesTimer > 0
1772
player.speedShoesTimer--
1773
if player.speedShoesTimer < 1
1774
currentPlayer = player.entityPos
1775
CallFunction(Player_UpdatePhysicsState)
1776
1777
// If any player has speed shoes, keep the sped-up music
1778
temp0 = false
1779
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
1780
temp0 += player[currentPlayer].speedShoesTimer
1781
next
1782
1783
if temp0 == false
1784
if SlowDownMusic != 0
1785
CallFunction(SlowDownMusic)
1786
end if
1787
end if
1788
1789
player.speedShoesTimer = 0
1790
end if
1791
end if
1792
1793
if player.state != Player_State_Hurt
1794
if player.blinkTimer > 0
1795
player.blinkTimer--
1796
1797
GetBit(temp0, player.blinkTimer, 2)
1798
if temp0 == true
1799
player.visible = false
1800
else
1801
player.visible = true
1802
end if
1803
end if
1804
end if
1805
1806
if player.invincibleTimer > 0
1807
player.invincibleTimer--
1808
if player.invincibleTimer == 0
1809
// If any player is invincible, continue playing the invincibility music
1810
temp0 = false
1811
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
1812
temp0 += player[currentPlayer].invincibleTimer
1813
next
1814
1815
if temp0 == false
1816
if music.currentTrack == TRACK_INVINCIBLE
1817
PlayMusic(TRACK_STAGE)
1818
end if
1819
end if
1820
1821
if object[+playerCount].type == invincibilityType
1822
currentPlayer = player.entityPos
1823
arrayPos0 = currentPlayer
1824
arrayPos0 += playerCount
1825
CallFunction(Player_ApplyShield)
1826
end if
1827
end if
1828
end if
1829
1830
if player.state != Player_State_LookUp
1831
if player.state != Player_State_Crouch
1832
// Move the camera back to its normal position
1833
if player.lookPosY > 0
1834
player.lookPosY -= 2
1835
end if
1836
1837
if player.lookPosY < 0
1838
player.lookPosY += 2
1839
end if
1840
end if
1841
end if
1842
1843
// After a spindash release, restore the camera back to normal after a few short moments
1844
if player.scrollDelay > 0
1845
player.scrollDelay--
1846
if player.scrollDelay == 0
1847
currentPlayer = player.entityPos
1848
if player.entityPos == camera[currentPlayer].target
1849
// Restore the camera's state
1850
camera[currentPlayer].style = CAMERASTYLE_FOLLOW
1851
end if
1852
end if
1853
end if
1854
1855
if player.state != Player_State_Fly
1856
if player.flightVelocity != 0
1857
// As a fail-safe, if not flying, enforce that the SFX stop playing as well
1858
StopSfx(SfxName[Flying])
1859
StopSfx(SfxName[Tired])
1860
player.flightVelocity = 0
1861
end if
1862
end if
1863
end function
1864
1865
1866
public function Player_State_Static
1867
checkResult = false
1868
end function
1869
1870
1871
public function Player_HandleRollAnimSpeed
1872
if player.character == PLAYER_TAILS_A
1873
player.rollAnimationSpeed = 120
1874
else
1875
player.rollAnimationSpeed = player.speed
1876
if player.rollAnimationSpeed < 0
1877
FlipSign(player.rollAnimationSpeed)
1878
end if
1879
1880
player.rollAnimationSpeed *= 240
1881
player.rollAnimationSpeed /= 0x60000
1882
player.rollAnimationSpeed += 48
1883
end if
1884
end function
1885
1886
1887
public function Player_HandleWalkAnimSpeed
1888
player.animationSpeed = player.speed
1889
1890
if player.animationSpeed < 0
1891
FlipSign(player.animationSpeed)
1892
end if
1893
1894
player.animationSpeed *= 60
1895
player.animationSpeed /= 0x60000
1896
player.animationSpeed += 20
1897
end function
1898
1899
1900
public function Player_HandleRunAnimSpeed
1901
player.animationSpeed = player.speed
1902
1903
if player.animationSpeed < 0
1904
FlipSign(player.animationSpeed)
1905
end if
1906
1907
player.animationSpeed *= 80
1908
player.animationSpeed /= 0x60000
1909
end function
1910
1911
1912
public function Player_HandleGroundMovement
1913
if player.controlLock > 0
1914
// No moving while the control lock is active, simply just adjust player speed dependong on their angle for right now
1915
player.controlLock--
1916
Sin256(temp0, player.angle)
1917
temp0 *= 0x2000
1918
temp0 >>= 8
1919
player.speed += temp0
1920
else
1921
if player.left == true
1922
temp0 = player.topSpeed
1923
FlipSign(temp0)
1924
if player.speed > temp0
1925
if player.speed > 0
1926
if player.collisionMode == CMODE_FLOOR
1927
if player.speed > 0x40000
1928
player.skidding = 16
1929
end if
1930
end if
1931
1932
if player.speed < player.skidSpeed
1933
player.speed = player.skidSpeed
1934
FlipSign(player.speed)
1935
player.skidding = 0
1936
else
1937
player.speed -= player.skidSpeed
1938
end if
1939
else
1940
player.speed -= player.acceleration
1941
player.skidding = 0
1942
end if
1943
end if
1944
1945
if player.speed <= 0
1946
player.direction = FACING_LEFT
1947
end if
1948
end if
1949
1950
if player.right == true
1951
if player.speed < player.topSpeed
1952
if player.speed < 0
1953
if player.collisionMode == CMODE_FLOOR
1954
if player.speed < -0x40000
1955
player.skidding = 16
1956
end if
1957
end if
1958
1959
temp0 = player.skidSpeed
1960
FlipSign(temp0)
1961
if player.speed > temp0
1962
player.speed = player.skidSpeed
1963
player.skidding = 0
1964
else
1965
player.speed += player.skidSpeed
1966
end if
1967
else
1968
player.speed += player.acceleration
1969
player.skidding = 0
1970
end if
1971
end if
1972
1973
if player.speed >= 0
1974
player.direction = FACING_RIGHT
1975
end if
1976
end if
1977
1978
temp0 = player.left
1979
temp0 |= player.right
1980
if temp0 == false
1981
if player.speed > 0
1982
player.speed -= player.deceleration
1983
if player.speed < 0
1984
player.speed = 0
1985
end if
1986
else
1987
player.speed += player.deceleration
1988
if player.speed > 0
1989
player.speed = 0
1990
end if
1991
end if
1992
1993
if player.speed > 0x2000
1994
Sin256(temp0, player.angle)
1995
temp0 *= 0x2000
1996
temp0 >>= 8
1997
player.speed += temp0
1998
end if
1999
2000
if player.speed < -0x2000
2001
Sin256(temp0, player.angle)
2002
temp0 *= 0x2000
2003
temp0 >>= 8
2004
player.speed += temp0
2005
end if
2006
2007
if player.angle > 192
2008
if player.angle < 228
2009
if player.speed > -0x10000
2010
if player.speed < 0x10000
2011
player.controlLock = 30
2012
end if
2013
end if
2014
end if
2015
end if
2016
2017
if player.angle > 28
2018
if player.angle < 64
2019
if player.speed > -0x10000
2020
if player.speed < 0x10000
2021
player.controlLock = 30
2022
end if
2023
end if
2024
end if
2025
end if
2026
else
2027
Sin256(temp0, player.angle)
2028
temp0 *= 0x2000
2029
temp0 >>= 8
2030
player.speed += temp0
2031
if player.right == true
2032
if player.left == false
2033
if player.angle > 192
2034
if player.angle < 228
2035
if player.speed < 0x28000
2036
if player.speed > -0x20000
2037
player.controlLock = 30
2038
end if
2039
end if
2040
end if
2041
end if
2042
end if
2043
else
2044
if player.left == true
2045
if player.angle > 28
2046
if player.angle < 64
2047
if player.speed > -0x28000
2048
if player.speed < 0x20000
2049
player.controlLock = 30
2050
end if
2051
end if
2052
end if
2053
end if
2054
end if
2055
end if
2056
end if
2057
2058
if options.speedCap == true
2059
// Enforce the speed cap
2060
if player.left == true
2061
temp0 = player.topSpeed
2062
FlipSign(temp0)
2063
if player.speed < temp0
2064
player.speed = temp0
2065
end if
2066
end if
2067
2068
if player.right == true
2069
if player.speed > player.topSpeed
2070
player.speed = player.topSpeed
2071
end if
2072
end if
2073
end if
2074
end if
2075
2076
switch player.collisionMode
2077
case CMODE_LWALL
2078
if player.angle <= 192
2079
if player.speed > -0x20000
2080
if player.speed < 0x20000
2081
player.gravity = GRAVITY_AIR
2082
player.angle = 0
2083
player.collisionMode = CMODE_FLOOR
2084
player.speed = player.xvel
2085
end if
2086
end if
2087
end if
2088
break
2089
2090
case CMODE_ROOF
2091
if player.speed > -0x20000
2092
if player.speed < 0x20000
2093
player.gravity = GRAVITY_AIR
2094
player.angle = 0
2095
player.collisionMode = CMODE_FLOOR
2096
player.speed = player.xvel
2097
end if
2098
end if
2099
break
2100
2101
case CMODE_RWALL
2102
if player.angle >= 64
2103
if player.speed > -0x20000
2104
if player.speed < 0x20000
2105
player.gravity = GRAVITY_AIR
2106
player.angle = 0
2107
player.collisionMode = CMODE_FLOOR
2108
player.speed = player.xvel
2109
end if
2110
end if
2111
end if
2112
break
2113
2114
end switch
2115
end function
2116
2117
2118
public function Player_HandleAirFriction
2119
if player.yvel > -0x40000
2120
if player.yvel < 0
2121
temp0 = player.speed
2122
temp0 >>= 5
2123
player.speed -= temp0
2124
end if
2125
end if
2126
2127
temp0 = player.topSpeed
2128
FlipSign(temp0)
2129
if player.speed > temp0
2130
if player.left == true
2131
player.speed -= player.airAcceleration
2132
player.direction = FACING_LEFT
2133
end if
2134
else
2135
if player.left == true
2136
player.direction = FACING_LEFT
2137
end if
2138
end if
2139
2140
if player.speed < player.topSpeed
2141
if player.right == true
2142
player.speed += player.airAcceleration
2143
player.direction = FACING_RIGHT
2144
end if
2145
else
2146
if player.right == true
2147
player.direction = FACING_RIGHT
2148
end if
2149
end if
2150
2151
if options.airSpeedCap == true
2152
if player.left == true
2153
temp0 = player.topSpeed
2154
FlipSign(temp0)
2155
if player.speed < temp0
2156
player.speed = temp0
2157
end if
2158
end if
2159
2160
if player.right == true
2161
if player.speed > player.topSpeed
2162
player.speed = player.topSpeed
2163
end if
2164
end if
2165
end if
2166
2167
#platform: USE_ORIGINS
2168
if game.playMode == BOOT_PLAYMODE_MISSION
2169
if stage.timeEnabled == false
2170
temp1 = screen.yoffset
2171
temp1 += screen.ysize
2172
temp1 += 40
2173
if player.iypos > temp1
2174
player.iypos = temp1
2175
end if
2176
end if
2177
end if
2178
#endplatform
2179
end function
2180
2181
2182
public function Player_HandleRollDeceleration
2183
if player.right == true
2184
if player.speed < 0
2185
player.speed += player.rollingDeceleration
2186
end if
2187
end if
2188
2189
if player.left == true
2190
if player.speed > 0
2191
player.speed -= player.rollingDeceleration
2192
end if
2193
end if
2194
2195
temp1 = player.speed
2196
if player.speed > 0
2197
player.speed -= player.rollingFriction
2198
Sin256(temp0, player.angle)
2199
if temp0 > 0
2200
Sin256(temp0, player.angle)
2201
temp0 *= 0x5000
2202
else
2203
Sin256(temp0, player.angle)
2204
temp0 *= 0x1400
2205
end if
2206
temp0 >>= 8
2207
player.speed += temp0
2208
if player.speed > 0x120000
2209
player.speed = 0x120000
2210
end if
2211
else
2212
player.speed += player.rollingFriction
2213
2214
Sin256(temp0, player.angle)
2215
if temp0 < 0
2216
Sin256(temp0, player.angle)
2217
temp0 *= 0x5000
2218
else
2219
Sin256(temp0, player.angle)
2220
temp0 *= 0x1400
2221
end if
2222
temp0 >>= 8
2223
2224
player.speed += temp0
2225
if player.speed < -0x120000
2226
player.speed = -0x120000
2227
end if
2228
end if
2229
2230
switch player.collisionMode
2231
case CMODE_FLOOR
2232
case CMODE_ROOF
2233
if temp1 > 0
2234
if player.speed < 0
2235
player.speed = 0
2236
player.state = Player_State_Ground
2237
end if
2238
else
2239
if player.speed > 0
2240
player.speed = 0
2241
player.state = Player_State_Ground
2242
end if
2243
end if
2244
break
2245
2246
case CMODE_LWALL
2247
if player.angle < 193
2248
if temp1 > 0
2249
if player.speed < 0x20000
2250
player.gravity = GRAVITY_AIR
2251
player.xvel = 0
2252
player.speed = 0
2253
end if
2254
end if
2255
end if
2256
break
2257
2258
case CMODE_RWALL
2259
if player.angle > 63
2260
if temp1 < 0
2261
if player.speed > -0x20000
2262
player.gravity = GRAVITY_AIR
2263
player.xvel = 0
2264
player.speed = 0
2265
end if
2266
end if
2267
end if
2268
break
2269
2270
end switch
2271
end function
2272
2273
2274
public function Player_HandleAirMovement
2275
player.scrollTracking = true
2276
2277
#platform: USE_STANDALONE
2278
player.yvel += player.gravityStrength
2279
#endplatform
2280
2281
#platform: USE_ORIGINS
2282
// Bug Details:
2283
// Sonic Team wrapped this in a check, where if you init "Player_Kill" while the stage is finished,
2284
// -> it disables the gravity of the player (in Mission Mode)
2285
// However, this check uses the "currentPlayer" array, and while this is no issue for the other characters,
2286
// -> it used to become one for Tails (as either Tails Object or Player 2 Object)
2287
// This results in various issues in Origins 2.0.1, such as crashes, Tails losing gravity, etc.
2288
// This was fixed (kinda) in Origins 2.0.2, see Tails Object.
2289
2290
if player[currentPlayer].disableGravity == false
2291
player.yvel += player.gravityStrength
2292
end if
2293
#endplatform
2294
2295
if player.yvel < player.jumpCap
2296
if player.jumpHold == false
2297
if player.timer > 0
2298
player.yvel = player.jumpCap
2299
temp0 = player.speed
2300
temp0 >>= 5
2301
player.speed -= temp0
2302
end if
2303
end if
2304
end if
2305
player.xvel = player.speed
2306
2307
if player.rotation < 256
2308
if player.rotation > 0
2309
player.rotation -= 4
2310
else
2311
player.rotation = 0
2312
end if
2313
else
2314
if player.rotation < 512
2315
player.rotation += 4
2316
else
2317
player.rotation = 0
2318
end if
2319
end if
2320
2321
player.collisionMode = CMODE_FLOOR
2322
if player.animation == ANI_JUMPING
2323
player.animationSpeed = player.rollAnimationSpeed
2324
end if
2325
end function
2326
2327
2328
public function Player_HandleOnGround
2329
player.scrollTracking = false
2330
Cos256(temp0, player.angle)
2331
temp0 *= player.speed
2332
temp0 >>= 8
2333
player.xvel = temp0
2334
2335
Sin256(temp0, player.angle)
2336
temp0 *= player.speed
2337
temp0 >>= 8
2338
player.yvel = temp0
2339
end function
2340
2341
2342
public function Player_Action_Jump
2343
// Let's mind our head!!!
2344
temp1 = false
2345
if player.collisionMode == CMODE_FLOOR
2346
temp6 = player.xpos
2347
temp7 = player.ypos
2348
temp0 = player.collisionTop
2349
temp0 -= 2
2350
ObjectTileCollision(CSIDE_ROOF, 0, temp0, player.collisionPlane)
2351
2352
temp1 = checkResult
2353
player.xpos = temp6
2354
player.ypos = temp7
2355
temp0 = player.collisionBottom
2356
if player.animation != ANI_JUMPING
2357
player.iypos -= player.jumpOffset
2358
temp0 += player.jumpOffset
2359
end if
2360
ObjectTileCollision(CSIDE_FLOOR, 0, temp0, player.collisionPlane)
2361
end if
2362
2363
if temp1 == false
2364
player.controlLock = 0
2365
player.gravity = GRAVITY_AIR
2366
temp1 = player.jumpStrength
2367
temp1 += player.gravityStrength
2368
Sin256(player.xvel, player.angle)
2369
player.xvel *= temp1
2370
Cos256(temp0, player.angle)
2371
temp0 *= player.speed
2372
player.xvel += temp0
2373
player.xvel >>= 8
2374
2375
Sin256(player.yvel, player.angle)
2376
player.yvel *= player.speed
2377
Cos256(temp0, player.angle)
2378
temp0 *= temp1
2379
player.yvel -= temp0
2380
player.yvel >>= 8
2381
2382
player.speed = player.xvel
2383
player.scrollTracking = true
2384
player.animation = ANI_JUMPING
2385
player.angle = 0
2386
player.collisionMode = CMODE_FLOOR
2387
player.timer = 1
2388
CallFunction(Player_HandleRollAnimSpeed)
2389
2390
if player.state == Player_State_Roll
2391
player.state = Player_State_RollJump
2392
else
2393
player.state = Player_State_Air
2394
end if
2395
2396
#platform: USE_STANDALONE
2397
PlaySfx(SfxName[Jump], false)
2398
#endplatform
2399
2400
#platform: USE_ORIGINS
2401
// This was introduced in 1.0.4 in order to make P2 Tails's jump SFX less obnoxious when he's off-screen
2402
currentPlayer = player.entityPos
2403
CallFunction(Player_CheckIfOnScreen)
2404
if checkResult != false
2405
PlaySfx(SfxName[Jump], false)
2406
end if
2407
#endplatform
2408
2409
player.collisionDisabled = true
2410
player.jumpAbilityState = 1
2411
end if
2412
2413
#platform: USE_ORIGINS
2414
if game.playMode == BOOT_PLAYMODE_CLASSIC
2415
temp7 = -1
2416
else
2417
temp7 = 0
2418
end if
2419
CallFunction(Player_SetDropDashCharge)
2420
#endplatform
2421
end function
2422
2423
2424
public function Player_Action_Spindash
2425
player.state = Player_State_Spindash
2426
player.animation = ANI_SPINDASH
2427
player.abilityTimer = 0
2428
2429
#platform: USE_ORIGINS
2430
// Don't play the Charge sound effect if using the Drop Dash
2431
CheckEqual(player.releasingDropDash, true)
2432
temp0 = checkResult
2433
CallFunction(Player_GetDropDashCharge)
2434
CheckGreater(20, temp7)
2435
temp0 |= checkResult
2436
if temp0 == true
2437
PlaySfx(SfxName[Charge], false)
2438
end if
2439
#endplatform
2440
2441
#platform: USE_STANDALONE
2442
PlaySfx(SfxName[Charge], false)
2443
#endplatform
2444
2445
CreateTempObject(TypeName[Dust Puff], player.entityPos, player.xpos, player.ypos)
2446
object[tempObjectPos].iypos = player.collisionBottom
2447
object[tempObjectPos].ypos += player.ypos
2448
object[tempObjectPos].frame = 4
2449
object[tempObjectPos].drawOrder = 4
2450
object[tempObjectPos].direction = player.direction
2451
end function
2452
2453
2454
public function Player_State_Transform
2455
player.collisionDisabled = true
2456
2457
player.timer--
2458
if player.timer == 0
2459
#platform: USE_STANDALONE
2460
player.state = Player_State_Air
2461
#endplatform
2462
#platform: USE_ORIGINS
2463
player.state = Player_State_Air_NoDropDash
2464
#endplatform
2465
player.animation = ANI_WALKING
2466
end if
2467
end function
2468
2469
2470
public function Player_TryTransform
2471
if stage.timeEnabled == true
2472
// Move to the shield object slot and spawn a Super Spark there
2473
arrayPos0 = currentPlayer
2474
arrayPos0 += playerCount
2475
ResetObjectEntity(arrayPos0, TypeName[Super Spark], 0, player[SLOT_PLAYER1].xpos, player[SLOT_PLAYER1].ypos)
2476
object[arrayPos0].priority = PRIORITY_ACTIVE
2477
2478
PlaySfx(SfxName[Transform], false)
2479
PlayMusic(TRACK_SUPER)
2480
2481
Player_superState = SUPERSTATE_SUPER
2482
player[currentPlayer].invincibleTimer = 60
2483
player[currentPlayer].blinkTimer = 0
2484
player[currentPlayer].visible = true
2485
2486
CallFunction(Player_UpdatePhysicsState)
2487
if stage.playerListPos == PLAYER_SONIC_A
2488
LoadAnimation("SuperSonic.ani")
2489
end if
2490
2491
player[currentPlayer].state = Player_State_Transform
2492
player[currentPlayer].collisionDisabled = true
2493
player[currentPlayer].animation = ANI_SUPER_TRANSFORM
2494
player[currentPlayer].timer = 24
2495
end if
2496
end function
2497
2498
2499
public function Player_State_BubbleBounce
2500
CallFunction(Player_HandleAirFriction)
2501
CheckNotEqual(player.shield, SHIELD_BUBBLE)
2502
temp0 = checkResult
2503
CheckNotEqual(player.invincibleTimer, 0)
2504
temp0 |= checkResult
2505
CheckEqual(Player_superState, SUPERSTATE_SUPER)
2506
temp0 |= checkResult
2507
2508
if temp0 == true
2509
#platform: USE_STANDALONE
2510
player.state = Player_State_Air
2511
#endplatform
2512
#platform: USE_ORIGINS
2513
player.state = Player_State_Air_NoDropDash
2514
#endplatform
2515
else
2516
if player.gravity == GRAVITY_AIR
2517
CallFunction(Player_HandleAirMovement)
2518
else
2519
player.jumpAbilityState = 1
2520
player.gravity = GRAVITY_AIR
2521
if player.jumpStrength == 0x38000
2522
temp1 = -0x40000
2523
else
2524
temp1 = -0x78000
2525
end if
2526
temp1 += player.gravityStrength
2527
Sin256(player.xvel, player.angle)
2528
player.xvel *= temp1
2529
Cos256(temp0, player.angle)
2530
temp0 *= player.speed
2531
player.xvel += temp0
2532
player.xvel >>= 8
2533
2534
Sin256(player.yvel, player.angle)
2535
player.yvel *= player.speed
2536
Cos256(temp0, player.angle)
2537
temp0 *= temp1
2538
player.yvel = temp0
2539
player.yvel >>= 8
2540
2541
player.speed = player.xvel
2542
player.scrollTracking = true
2543
player.animation = ANI_JUMPING
2544
player.angle = 0
2545
player.collisionMode = CMODE_FLOOR
2546
player.timer = 1
2547
CallFunction(Player_HandleRollAnimSpeed)
2548
#platform: USE_STANDALONE
2549
player.state = Player_State_Air
2550
#endplatform
2551
#platform: USE_ORIGINS
2552
player.state = Player_State_Air_NoDropDash
2553
#endplatform
2554
PlaySfx(SfxName[Bubble Bounce], false)
2555
object[+playerCount].state = 4
2556
end if
2557
end if
2558
end function
2559
2560
2561
public function Player_Action_DblJumpSonic
2562
#platform: USE_ORIGINS
2563
if keyPress[1].buttonY != false
2564
CheckEqual(specialStage.emeralds, 0x7F)
2565
temp0 = checkResult
2566
CheckGreater(player.rings, 49)
2567
temp0 &= checkResult
2568
CheckNotEqual(Player_superState, SUPERSTATE_SUPER)
2569
temp0 &= checkResult
2570
CheckNotEqual(object[SLOT_ACTFINISH].type, TypeName[Act Finish])
2571
temp0 &= checkResult
2572
2573
if temp0 == true
2574
currentPlayer = player.entityPos
2575
CallFunction(Player_TryTransform)
2576
CallNativeFunction4(NotifyCallback, NOTIFY_STATS_CHARA_ACTION, 1, 0, 0)
2577
end if
2578
end if
2579
#endplatform
2580
2581
if player.jumpPress == true
2582
#platform: USE_STANDALONE
2583
CheckEqual(specialStage.emeralds, 0x7F)
2584
temp0 = checkResult
2585
CheckGreater(player.rings, 49)
2586
temp0 &= checkResult
2587
CheckNotEqual(Player_superState, SUPERSTATE_SUPER)
2588
temp0 &= checkResult
2589
CheckNotEqual(object[SLOT_ACTFINISH].type, TypeName[Act Finish])
2590
temp0 &= checkResult
2591
2592
if temp0 == true
2593
currentPlayer = player.entityPos
2594
CallFunction(Player_TryTransform)
2595
else
2596
#endplatform
2597
CheckEqual(player.invincibleTimer, 0)
2598
temp0 = checkResult
2599
CheckNotEqual(Player_superState, SUPERSTATE_SUPER)
2600
temp0 &= checkResult
2601
2602
if temp0 == true
2603
switch player.shield
2604
case SHIELD_NONE
2605
temp0 = options.shieldType
2606
temp0 &= SHIELDTYPE_S3 // (see if it's S2 or S3 shields, ignore whether or not it's set to random)
2607
if temp0 > SHIELDTYPE_S2
2608
PlaySfx(SfxName[Insta Shield], false)
2609
if object[+playerCount].type == TypeName[Blank Object]
2610
currentPlayer = player.entityPos
2611
arrayPos0 = currentPlayer
2612
arrayPos0 += playerCount
2613
ResetObjectEntity(arrayPos0, TypeName[Insta Shield], 0, 0, 0)
2614
object[arrayPos0].priority = PRIORITY_ACTIVE
2615
end if
2616
2617
player.jumpAbilityState = 2
2618
object[+playerCount].state = 1 // (this does nothing btw)
2619
if player.state == Player_State_RollJump
2620
player.state = Player_State_Air
2621
end if
2622
end if
2623
break
2624
2625
case SHIELD_NORMAL
2626
break
2627
2628
case SHIELD_BUBBLE
2629
PlaySfx(SfxName[Bubble Bounce], false)
2630
player.yvel = 0x80000
2631
player.xvel = 0
2632
player.speed = player.xvel
2633
player.jumpAbilityState = 2
2634
player.state = Player_State_BubbleBounce
2635
object[+playerCount].state = BUBBLESHIELD_BOUNCE_SETUP
2636
break
2637
2638
case SHIELD_FIRE
2639
PlaySfx(SfxName[Fire Dash], false)
2640
GetBit(temp0, player.direction, 0)
2641
if temp0 == FLIP_NONE
2642
player.xvel = 0x80000
2643
else
2644
player.xvel = -0x80000
2645
end if
2646
2647
player.speed = player.xvel
2648
player.yvel = 0
2649
player.jumpAbilityState = 2
2650
currentPlayer = player.entityPos
2651
if player.entityPos == camera[currentPlayer].target
2652
player.scrollDelay = 15
2653
camera[currentPlayer].style = CAMERASTYLE_HLOCKED
2654
end if
2655
2656
if player.state == Player_State_RollJump
2657
player.state = Player_State_Air
2658
end if
2659
2660
object[+playerCount].state = FIRESHIELD_DASH_SETUP
2661
object[+playerCount].direction = player.direction
2662
break
2663
2664
case SHIELD_LIGHTNING
2665
PlaySfx(SfxName[Lightning Jump], false)
2666
player.yvel = -0x58000
2667
player.jumpAbilityState = 2
2668
2669
CreateTempObject(TypeName[Lightning Spark], 0, player.xpos, player.ypos)
2670
object[tempObjectPos].xvel = -0x20000
2671
object[tempObjectPos].yvel = -0x20000
2672
2673
CreateTempObject(TypeName[Lightning Spark], 0, player.xpos, player.ypos)
2674
object[tempObjectPos].xvel = 0x20000
2675
object[tempObjectPos].yvel = -0x20000
2676
2677
CreateTempObject(TypeName[Lightning Spark], 0, player.xpos, player.ypos)
2678
object[tempObjectPos].xvel = -0x20000
2679
object[tempObjectPos].yvel = 0x20000
2680
2681
CreateTempObject(TypeName[Lightning Spark], 0, player.xpos, player.ypos)
2682
object[tempObjectPos].xvel = 0x20000
2683
object[tempObjectPos].yvel = 0x20000
2684
2685
if player.state == Player_State_RollJump
2686
player.state = Player_State_Air
2687
end if
2688
break
2689
end switch
2690
end if
2691
#platform: USE_STANDALONE
2692
end if
2693
#endplatform
2694
end if
2695
end function
2696
2697
2698
public function Player_Action_DblJumpTails
2699
#platform: USE_ORIGINS
2700
// Tails can't even transform in Origins normally and yet they updated this anyway... how nice of them!
2701
if keyPress[1].buttonY != false
2702
CheckEqual(specialStage.emeralds, 0x7F)
2703
temp0 = checkResult
2704
CheckGreater(player.rings, 49)
2705
temp0 &= checkResult
2706
CheckNotEqual(Player_superState, SUPERSTATE_SUPER)
2707
temp0 &= checkResult
2708
CheckEqual(options.superTails, true)
2709
temp0 &= checkResult
2710
2711
if temp0 == true
2712
currentPlayer = player.entityPos
2713
CallFunction(Player_TryTransform)
2714
end if
2715
end if
2716
#endplatform
2717
2718
if player.jumpPress == true
2719
#platform: USE_STANDALONE
2720
CheckEqual(specialStage.emeralds, 0x7F)
2721
temp0 = checkResult
2722
CheckGreater(player.rings, 49)
2723
temp0 &= checkResult
2724
CheckNotEqual(Player_superState, SUPERSTATE_SUPER)
2725
temp0 &= checkResult
2726
CheckEqual(options.superTails, true)
2727
temp0 &= checkResult
2728
2729
if temp0 == true
2730
currentPlayer = player.entityPos
2731
CallFunction(Player_TryTransform)
2732
else
2733
#endplatform
2734
#platform: USE_ORIGINS
2735
if player.isSidekick == false
2736
CallNativeFunction4(NotifyCallback, NOTIFY_STATS_CHARA_ACTION, 0, 1, 0)
2737
end if
2738
#endplatform
2739
2740
player.timer = 0
2741
player.state = Player_State_Fly
2742
player.flightVelocity = 0x800
2743
2744
if player.gravityStrength == 0x3800
2745
PlaySfx(SfxName[Flying], true)
2746
player.animation = ANI_FLYING
2747
else
2748
player.animation = ANI_SWIMMING
2749
end if
2750
#platform: USE_STANDALONE
2751
end if
2752
#endplatform
2753
end if
2754
end function
2755
2756
2757
public function Player_Action_DblJumpKnux
2758
#platform: USE_ORIGINS
2759
if keyPress[1].buttonY != false
2760
CheckEqual(specialStage.emeralds, 0x7F)
2761
temp0 = checkResult
2762
CheckGreater(player.rings, 49)
2763
temp0 &= checkResult
2764
CheckNotEqual(Player_superState, SUPERSTATE_SUPER)
2765
temp0 &= checkResult
2766
2767
if temp0 == true
2768
currentPlayer = player.entityPos
2769
CallFunction(Player_TryTransform)
2770
end if
2771
end if
2772
#endplatform
2773
2774
if player.jumpPress == true
2775
#platform: USE_STANDALONE
2776
CheckEqual(specialStage.emeralds, 0x7F)
2777
temp0 = checkResult
2778
CheckGreater(player.rings, 49)
2779
temp0 &= checkResult
2780
CheckNotEqual(Player_superState, SUPERSTATE_SUPER)
2781
temp0 &= checkResult
2782
2783
if temp0 == true
2784
currentPlayer = player.entityPos
2785
CallFunction(Player_TryTransform)
2786
else
2787
#endplatform
2788
#platform: USE_ORIGINS
2789
if player.isSidekick == false // Knuckles is never a sidekick LOL
2790
CallNativeFunction4(NotifyCallback, NOTIFY_STATS_CHARA_ACTION2, 1, 0, 0)
2791
end if
2792
#endplatform
2793
2794
player.speed = 0x40000
2795
if player.yvel < 0
2796
player.yvel = 0
2797
end if
2798
2799
if player.direction == FACING_RIGHT
2800
player.state = Player_State_GlideRight
2801
player.xvel = 0x40000
2802
player.timer = 0
2803
else
2804
player.state = Player_State_GlideLeft
2805
player.xvel = -0x40000
2806
player.timer = 256
2807
end if
2808
2809
player.animation = ANI_GLIDING
2810
player.frame = 2
2811
#platform: USE_STANDALONE
2812
end if
2813
#endplatform
2814
end if
2815
end function
2816
2817
2818
// Handles activating the Drop Dash (Check Player_State_Air or Player_State_RollJump for releasing it)
2819
// Both Sonic and Amy use this function in Origins Plus, how fun!
2820
public function Player_HandleDropDash
2821
#platform: USE_ORIGINS
2822
if player.releasingDropDash == false
2823
CallFunction(Player_GetDropDashCharge)
2824
if temp7 >= 0
2825
if temp7 == 0
2826
if player.jumpPress == true
2827
switch player.character
2828
case PLAYER_SONIC_A
2829
CheckEqual(player.character, PLAYER_SONIC_A) // A bit redundant here, but whatever
2830
temp0 = checkResult
2831
// You can't use the Drop Dash with elemental shields
2832
CheckNotEqual(player.shield, SHIELD_BUBBLE)
2833
temp0 &= checkResult
2834
CheckNotEqual(player.shield, SHIELD_FIRE)
2835
temp0 &= checkResult
2836
CheckNotEqual(player.shield, SHIELD_LIGHTNING)
2837
temp0 &= checkResult
2838
2839
if temp0 == true
2840
temp7 = 1
2841
else
2842
temp7 = -1
2843
end if
2844
break
2845
2846
case PLAYER_AMY_A
2847
// Amy defies all the odds and is able to Drop Dash with any shield
2848
temp7 = 1
2849
break
2850
end switch
2851
end if
2852
else
2853
if player.jumpHold == false
2854
if temp7 >= 20
2855
temp7 = -1
2856
end if
2857
else
2858
temp7++
2859
if temp7 == 20
2860
PlaySfx(SfxName[DropDash], false)
2861
end if
2862
if temp7 >= 20
2863
// Set Sonic to always use the full ball sprite
2864
// This code, when placed here, doesn't work properly. Check ObjectUpdate for the same code in a more proper location
2865
if player.animation == ANI_JUMPING
2866
player.frame = 1
2867
player.animationTimer = 0
2868
player.animationSpeed = 1
2869
end if
2870
end if
2871
end if
2872
end if
2873
2874
CallFunction(Player_SetDropDashCharge)
2875
end if
2876
end if
2877
#endplatform
2878
end function
2879
2880
// Yes, this is actually how Sonic Team programmed this
2881
// Note about these next two functions, player.dropdashCount0 and player.dropdashCount1 are global variables, NOT object values
2882
// Also, the "player.dropdashCount2" and "player.dropdashCount3" values introduced in Origins Plus are unused, this function stayed the same between 1.0.4 and later versions
2883
2884
public function Player_SetDropDashCharge
2885
#platform: USE_ORIGINS
2886
if player.entityPos == SLOT_PLAYER1
2887
player.dropdashCount0 = temp7
2888
else
2889
player.dropdashCount1 = temp7
2890
end if
2891
#endplatform
2892
end function
2893
2894
2895
public function Player_GetDropDashCharge
2896
#platform: USE_ORIGINS
2897
if player.entityPos == SLOT_PLAYER1
2898
temp7 = player.dropdashCount0
2899
else
2900
temp7 = player.dropdashCount1
2901
end if
2902
#endplatform
2903
end function
2904
2905
2906
public function Player_CheckIfOnScreen
2907
#platform: USE_ORIGINS
2908
// This function is new to Origins, it was added in 1.0.4 in order to not make certain SFX play when P2 Tails was far off-screen
2909
// In Origins Plus, the S1 equivalent of this function was updated to fix a bug, but they forgot to fix it here too...
2910
2911
// ...at least they added a check for VS Mode!
2912
if options.vsMode == true
2913
checkResult = true
2914
else
2915
checkResult = false
2916
2917
temp0 = screen.xoffset
2918
temp0 -= 20
2919
if player[currentPlayer].ixpos > temp0
2920
temp0 = screen.xoffset
2921
temp0 += screen.xsize
2922
temp0 += 20
2923
if player[currentPlayer].ixpos < temp0
2924
temp0 = screen.yoffset
2925
temp0 -= 40
2926
if player[currentPlayer].iypos > temp0
2927
temp0 = screen.yoffset
2928
temp0 += screen.ysize
2929
temp0 += 40
2930
if player[currentPlayer].iypos < temp0
2931
checkResult = true
2932
end if
2933
end if
2934
end if
2935
end if
2936
end if
2937
#endplatform
2938
end function
2939
2940
2941
public function Player_State_Ground
2942
if player.animation != ANI_SKIDDING
2943
temp7 = true
2944
else
2945
temp7 = false
2946
end if
2947
2948
CallFunction(Player_HandleGroundMovement)
2949
if player.gravity == GRAVITY_AIR
2950
#platform: USE_STANDALONE
2951
player.state = Player_State_Air
2952
#endplatform
2953
#platform: USE_ORIGINS
2954
player.state = Player_State_Air_NoDropDash
2955
#endplatform
2956
CallFunction(Player_HandleAirMovement)
2957
else
2958
CallFunction(Player_HandleOnGround)
2959
if player.speed == 0
2960
if player.collisionMode == CMODE_FLOOR
2961
switch player.character
2962
case PLAYER_SONIC_A
2963
if Player_superState == SUPERSTATE_SUPER
2964
player.animation = ANI_STOPPED
2965
player.timer = 0
2966
if player.floorSensorC == false
2967
if player.floorSensorR == false
2968
player.animation = ANI_FLAILING1
2969
player.direction = FACING_RIGHT
2970
end if
2971
2972
if player.floorSensorL == false
2973
player.animation = ANI_FLAILING1
2974
player.direction = FACING_LEFT
2975
end if
2976
end if
2977
else
2978
if player.timer < 240
2979
player.animation = ANI_STOPPED
2980
player.timer++
2981
else
2982
player.animation = ANI_WAITING
2983
player.timer++
2984
if player.timer == 0x4B0
2985
player.timer = 0
2986
player.state = Player_State_Sleeping
2987
end if
2988
end if
2989
2990
if player.direction == FACING_RIGHT
2991
if player.floorSensorR == false
2992
if player.floorSensorC == false
2993
player.timer = 0
2994
if player.floorSensorLC == false
2995
player.animation = ANI_FLAILING3
2996
else
2997
player.animation = ANI_FLAILING1
2998
end if
2999
end if
3000
else
3001
if player.floorSensorL == false
3002
if player.floorSensorC == false
3003
player.timer = 0
3004
player.animation = ANI_FLAILING2
3005
end if
3006
end if
3007
end if
3008
else
3009
if player.floorSensorL == false
3010
if player.floorSensorC == false
3011
player.timer = 0
3012
if player.floorSensorRC == false
3013
player.animation = ANI_FLAILING3
3014
else
3015
player.animation = ANI_FLAILING1
3016
end if
3017
end if
3018
else
3019
if player.floorSensorR == false
3020
if player.floorSensorC == false
3021
player.timer = 0
3022
player.animation = ANI_FLAILING2
3023
end if
3024
end if
3025
end if
3026
end if
3027
end if
3028
break
3029
3030
case PLAYER_TAILS_A
3031
if player.timer < 240
3032
player.animation = ANI_STOPPED
3033
player.timer++
3034
else
3035
player.animation = ANI_WAITING
3036
end if
3037
3038
if player.floorSensorC == false
3039
if player.floorSensorR == false
3040
player.timer = 0
3041
player.animation = ANI_FLAILING1
3042
player.direction = FACING_RIGHT
3043
end if
3044
if player.floorSensorL == false
3045
player.timer = 0
3046
player.animation = ANI_FLAILING1
3047
player.direction = FACING_LEFT
3048
end if
3049
end if
3050
break
3051
3052
case PLAYER_KNUCKLES_A
3053
if player.timer < 240
3054
player.animation = ANI_STOPPED
3055
player.timer++
3056
else
3057
#platform: USE_STANDALONE
3058
player.animation = ANI_WAITING
3059
player.timer++
3060
if player.timer == 834
3061
player.timer = 0
3062
player.animation = ANI_STOPPED
3063
end if
3064
#endplatform
3065
3066
#platform: USE_ORIGINS
3067
if player.timer < 570
3068
player.animation = ANI_WAITING
3069
player.timer++
3070
else
3071
player.animation = ANI_BORED
3072
player.timer++
3073
if player.timer == 842
3074
player.timer = 0
3075
player.animation = ANI_STOPPED
3076
end if
3077
end if
3078
#endplatform
3079
end if
3080
3081
if player.floorSensorC == false
3082
if player.floorSensorR == false
3083
player.timer = 0
3084
player.animation = ANI_FLAILING1
3085
if player.direction == FACING_LEFT
3086
player.prevAnimation = ANI_FLAILING1
3087
player.frame = 4
3088
player.animationTimer = 0
3089
player.animationSpeed = 0
3090
end if
3091
player.direction = FACING_RIGHT
3092
end if
3093
3094
if player.floorSensorL == false
3095
player.timer = 0
3096
player.animation = ANI_FLAILING1
3097
if player.direction == FACING_RIGHT
3098
player.prevAnimation = ANI_FLAILING1
3099
player.frame = 4
3100
player.animationTimer = 0
3101
player.animationSpeed = 0
3102
end if
3103
player.direction = FACING_LEFT
3104
end if
3105
end if
3106
break
3107
3108
#platform: USE_ORIGINS
3109
case PLAYER_AMY_A
3110
if player.timer < 240
3111
player.animation = ANI_STOPPED
3112
player.timer++
3113
else
3114
if player.timer < 1107
3115
player.animation = ANI_WAITING
3116
player.timer++
3117
else
3118
player.animation = ANI_BORED
3119
player.timer++
3120
if player.timer >= 1245
3121
// Nothing here LOL
3122
end if
3123
end if
3124
end if
3125
3126
// btw Amy's Flailing1 and Flailing3 animations are the same thing, this whole thing is just copied from Sonic (who *does* have unique flailing1/3 animations)
3127
if player.direction == FACING_RIGHT
3128
if player.floorSensorR == false
3129
if player.floorSensorC == false
3130
player.timer = 0
3131
if player.floorSensorLC == false
3132
player.animation = ANI_FLAILING3
3133
else
3134
player.animation = ANI_FLAILING1
3135
end if
3136
end if
3137
else
3138
if player.floorSensorL == false
3139
if player.floorSensorC == false
3140
player.timer = 0
3141
player.animation = ANI_FLAILING2
3142
end if
3143
end if
3144
end if
3145
else
3146
if player.floorSensorL == false
3147
if player.floorSensorC == false
3148
player.timer = 0
3149
if player.floorSensorRC == false
3150
player.animation = ANI_FLAILING3
3151
else
3152
player.animation = ANI_FLAILING1
3153
end if
3154
end if
3155
else
3156
if player.floorSensorR == false
3157
if player.floorSensorC == false
3158
player.timer = 0
3159
player.animation = ANI_FLAILING2
3160
end if
3161
end if
3162
end if
3163
end if
3164
break
3165
#endplatform
3166
end switch
3167
end if
3168
else
3169
player.timer = 0
3170
if player.speed > 0
3171
if player.speed < 0x5F5C2
3172
player.animation = ANI_WALKING
3173
CallFunction(Player_HandleWalkAnimSpeed)
3174
else
3175
if player.speed > 0x9FFFF
3176
player.animation = ANI_PEELOUT
3177
else
3178
player.animation = ANI_RUNNING
3179
end if
3180
CallFunction(Player_HandleRunAnimSpeed)
3181
end if
3182
else
3183
if player.speed > -0x5F5C2
3184
player.animation = ANI_WALKING
3185
CallFunction(Player_HandleWalkAnimSpeed)
3186
else
3187
if player.speed < -0x9FFFF
3188
player.animation = ANI_PEELOUT
3189
else
3190
player.animation = ANI_RUNNING
3191
end if
3192
CallFunction(Player_HandleRunAnimSpeed)
3193
end if
3194
end if
3195
end if
3196
3197
if player.skidding > 0
3198
if temp7 == true
3199
PlaySfx(SfxName[Skidding], false)
3200
end if
3201
player.animation = ANI_SKIDDING
3202
player.animationSpeed = 0
3203
player.skidding--
3204
if ringTimer == 0
3205
CreateTempObject(TypeName[Dust Puff], 0, player.xpos, player.ypos)
3206
object[tempObjectPos].iypos += player.collisionBottom
3207
object[tempObjectPos].drawOrder = player.sortedDrawOrder
3208
end if
3209
3210
if player.speed > 0
3211
player.direction = FACING_RIGHT
3212
else
3213
player.direction = FACING_LEFT
3214
end if
3215
end if
3216
3217
if player.collisionMode == CMODE_FLOOR
3218
if player.pushing == 2
3219
player.animation = ANI_PUSHING
3220
player.animationSpeed = 0
3221
end if
3222
end if
3223
3224
if player.jumpPress == true
3225
CallFunction(Player_Action_Jump)
3226
else
3227
if player.up == true
3228
if player.speed == 0
3229
if player.animation != ANI_FLAILING1
3230
if player.animation != ANI_FLAILING2
3231
player.state = Player_State_LookUp
3232
player.timer = 0
3233
else
3234
player.up = false
3235
player.down = false
3236
end if
3237
else
3238
player.up = false
3239
player.down = false
3240
end if
3241
end if
3242
end if
3243
3244
if player.down == true
3245
if player.speed == 0
3246
if player.animation != ANI_FLAILING1
3247
if player.animation != ANI_FLAILING2
3248
player.state = Player_State_Crouch
3249
player.timer = 0
3250
else
3251
player.up = false
3252
player.down = false
3253
end if
3254
else
3255
player.up = false
3256
player.down = false
3257
end if
3258
else
3259
if player.left == false
3260
if player.right == false
3261
if player.speed > 0
3262
if player.speed > 0x8800
3263
player.state = Player_State_Roll
3264
player.animation = ANI_JUMPING
3265
if player.prevAnimation != ANI_JUMPING
3266
player.iypos -= player.jumpOffset
3267
end if
3268
3269
player.abilityTimer = 0x400
3270
PlaySfx(SfxName[Rolling], false)
3271
end if
3272
else
3273
if player.speed < -0x8800
3274
player.state = Player_State_Roll
3275
player.animation = ANI_JUMPING
3276
if player.prevAnimation != ANI_JUMPING
3277
player.iypos -= player.jumpOffset
3278
end if
3279
3280
player.abilityTimer = 0x400
3281
PlaySfx(SfxName[Rolling], false)
3282
end if
3283
end if
3284
end if
3285
end if
3286
end if
3287
end if
3288
end if
3289
end if
3290
end function
3291
3292
3293
public function Player_State_Sleeping
3294
if player.gravity == GRAVITY_AIR
3295
#platform: USE_STANDALONE
3296
player.state = Player_State_Air
3297
#endplatform
3298
#platform: USE_ORIGINS
3299
player.state = Player_State_Air_NoDropDash
3300
#endplatform
3301
CallFunction(Player_HandleAirMovement)
3302
else
3303
CallFunction(Player_HandleOnGround)
3304
if player.animation == ANI_CONTINUE_UP
3305
if player.frame == 1
3306
player.state = Player_State_Ground
3307
end if
3308
else
3309
player.animation = ANI_BORED
3310
end if
3311
3312
if player.jumpPress == true
3313
CallFunction(Player_Action_Jump)
3314
else
3315
if player.up == true
3316
player.animation = ANI_CONTINUE_UP
3317
end if
3318
3319
if player.down == true
3320
player.animation = ANI_CONTINUE_UP
3321
end if
3322
3323
if player.left == true
3324
player.animation = ANI_CONTINUE_UP
3325
end if
3326
3327
if player.right == true
3328
player.animation = ANI_CONTINUE_UP
3329
end if
3330
end if
3331
end if
3332
end function
3333
3334
3335
// Prevents the player from using the Drop Dash if they went in midair without jumping
3336
public function Player_State_Air_NoDropDash
3337
#platform: USE_ORIGINS
3338
temp7 = -1
3339
CallFunction(Player_SetDropDashCharge)
3340
player.state = Player_State_Air_NoDropDash
3341
CallFunction(Player_State_Air)
3342
#endplatform
3343
end function
3344
3345
3346
public function Player_State_Air
3347
CallFunction(Player_HandleAirFriction)
3348
3349
if player.gravity == GRAVITY_AIR
3350
CallFunction(Player_HandleAirMovement)
3351
3352
if player.yvel > 0x20000
3353
if player.animation == ANI_FLAILING1
3354
player.animation = ANI_WALKING
3355
end if
3356
3357
if player.animation == ANI_FLAILING2
3358
player.animation = ANI_WALKING
3359
end if
3360
end if
3361
3362
if player.animation == ANI_BOUNCING
3363
if player.yvel >= 0
3364
if player.animationReserve == ANI_STOPPED
3365
player.animationReserve = ANI_WALKING
3366
end if
3367
player.animation = player.animationReserve
3368
end if
3369
end if
3370
3371
if player.animation == ANI_SKIDDING
3372
if player.skidding > 0
3373
player.skidding--
3374
else
3375
player.animation = ANI_WALKING
3376
player.prevAnimation = ANI_WALKING
3377
player.frame = 0
3378
player.animationSpeed = 40
3379
end if
3380
end if
3381
3382
if player.animation == ANI_TWIRL
3383
if player.animationSpeed == 40
3384
if player.frame >= 12
3385
player.animation = ANI_WALKING
3386
player.prevAnimation = ANI_WALKING
3387
player.frame = 0
3388
end if
3389
else
3390
if player.frame >= 24
3391
player.animation = ANI_WALKING
3392
player.prevAnimation = ANI_WALKING
3393
player.frame = 0
3394
player.animationSpeed = 40
3395
end if
3396
end if
3397
end if
3398
3399
if player.animation == ANI_HURT
3400
if player.yvel >= 0
3401
if player.animationReserve == ANI_STOPPED
3402
player.animationReserve = ANI_WALKING
3403
end if
3404
player.animation = player.animationReserve
3405
end if
3406
end if
3407
3408
#platform: USE_STANDALONE
3409
if player.animation == ANI_JUMPING
3410
if player.jumpAbilityState == 1
3411
if player.yvel >= player.jumpCap
3412
CallFunction(player.jumpAbility)
3413
end if
3414
end if
3415
end if
3416
#endplatform
3417
3418
#platform: USE_ORIGINS
3419
if player.yvel >= player.jumpCap
3420
CallFunction(Player_HandleDropDash)
3421
if player.animation == ANI_JUMPING
3422
if player.jumpAbilityState == 1
3423
CallFunction(player.jumpAbility)
3424
end if
3425
end if
3426
end if
3427
#endplatform
3428
else
3429
#platform: USE_STANDALONE
3430
player.state = Player_State_Ground
3431
CallFunction(Player_HandleOnGround)
3432
player.skidding = 0
3433
#endplatform
3434
3435
#platform: USE_ORIGINS
3436
CheckEqual(player.releasingDropDash, false)
3437
temp0 = checkResult
3438
temp1 = 20
3439
temp1 -= 1 // yep
3440
CallFunction(Player_GetDropDashCharge)
3441
CheckGreater(temp7, temp1)
3442
temp0 &= checkResult
3443
3444
if temp0 == true
3445
switch player.character
3446
case PLAYER_SONIC_A
3447
CallFunction(Player_Action_Spindash) // Good ol' Sonic Team programming
3448
break
3449
3450
case PLAYER_AMY_A
3451
CallFunction(Player_Action_HammerDash)
3452
break
3453
end switch
3454
3455
if Player_superState == SUPERSTATE_SUPER
3456
screen.shakeY = 6
3457
end if
3458
else
3459
player.state = Player_State_Ground
3460
CallFunction(Player_HandleOnGround)
3461
player.skidding = 0
3462
end if
3463
#endplatform
3464
end if
3465
end function
3466
3467
public function Player_State_TubeAirRoll
3468
CallFunction(Player_HandleAirFriction)
3469
3470
if player.gravity == GRAVITY_AIR
3471
CallFunction(Player_HandleAirMovement)
3472
else
3473
player.state = Player_State_TubeRoll
3474
CallFunction(Player_HandleOnGround)
3475
player.skidding = 0
3476
end if
3477
3478
player.animation = ANI_JUMPING
3479
end function
3480
3481
3482
public function Player_State_Roll
3483
CallFunction(Player_HandleRollDeceleration)
3484
3485
if player.gravity == GRAVITY_AIR
3486
#platform: USE_STANDALONE
3487
player.state = Player_State_Air
3488
#endplatform
3489
#platform: USE_ORIGINS
3490
player.state = Player_State_Air_NoDropDash
3491
#endplatform
3492
player.timer = 0
3493
CallFunction(Player_HandleAirMovement)
3494
else
3495
CallFunction(Player_HandleRollAnimSpeed)
3496
player.animationSpeed = player.rollAnimationSpeed
3497
CallFunction(Player_HandleOnGround)
3498
if player.jumpPress == true
3499
CallFunction(Player_Action_Jump)
3500
end if
3501
end if
3502
end function
3503
3504
3505
public function Player_State_RollJump
3506
#platform: USE_ORIGINS
3507
// Origins Plus removed Roll Jump Lock! We should still apply it to attract demos so they don't break, though
3508
if options.attractMode == true
3509
#endplatform
3510
player.left = false
3511
player.right = false
3512
#platform: USE_ORIGINS
3513
end if
3514
#endplatform
3515
3516
CallFunction(Player_HandleAirFriction)
3517
3518
if player.gravity == GRAVITY_AIR
3519
#platform: USE_STANDALONE
3520
if player.animation == ANI_JUMPING
3521
if player.jumpAbilityState == 1
3522
if player.yvel >= player.jumpCap
3523
CallFunction(player.jumpAbility)
3524
end if
3525
end if
3526
end if
3527
#endplatform
3528
3529
#platform: USE_ORIGINS
3530
if player.yvel >= player.jumpCap
3531
CallFunction(Player_HandleDropDash)
3532
if player.animation == ANI_JUMPING
3533
if player.jumpAbilityState == 1
3534
CallFunction(player.jumpAbility)
3535
end if
3536
end if
3537
end if
3538
#endplatform
3539
3540
CallFunction(Player_HandleAirMovement)
3541
else
3542
#platform: USE_STANDALONE
3543
player.state = Player_State_Ground
3544
CallFunction(Player_HandleOnGround)
3545
player.skidding = 0
3546
#endplatform
3547
3548
#platform: USE_ORIGINS
3549
CheckEqual(player.releasingDropDash, false)
3550
temp0 = checkResult
3551
temp1 = 20
3552
temp1 -= 1 // yep
3553
CallFunction(Player_GetDropDashCharge)
3554
CheckGreater(temp7, temp1)
3555
temp0 &= checkResult
3556
3557
if temp0 == true
3558
switch player.character
3559
case PLAYER_SONIC_A
3560
CallFunction(Player_Action_Spindash) // Good ol' Sonic Team programming
3561
break
3562
3563
case PLAYER_AMY_A
3564
CallFunction(Player_Action_HammerDash)
3565
break
3566
end switch
3567
3568
if Player_superState == SUPERSTATE_SUPER
3569
screen.shakeY = 6
3570
end if
3571
else
3572
player.state = Player_State_Ground
3573
CallFunction(Player_HandleOnGround)
3574
player.skidding = 0
3575
end if
3576
#endplatform
3577
end if
3578
end function
3579
3580
3581
public function Player_State_LookUp
3582
#platform: USE_ORIGINS
3583
currentPlayer = player.entityPos
3584
#endplatform
3585
3586
if player.up == false
3587
player.state = Player_State_Ground
3588
player.timer = 0
3589
else
3590
if player.timer < 60
3591
player.timer++
3592
else
3593
temp0 = player.ypos
3594
temp0 >>= 16
3595
#platform: USE_STANDALONE
3596
temp0 -= camera[0].ypos
3597
#endplatform
3598
3599
#platform: USE_ORIGINS
3600
temp0 -= camera[currentPlayer].ypos
3601
#endplatform
3602
temp0 -= 112
3603
if player.lookPosY > temp0
3604
player.lookPosY -= 2
3605
end if
3606
end if
3607
3608
player.animation = ANI_LOOKINGUP
3609
if player.gravity == GRAVITY_AIR
3610
#platform: USE_STANDALONE
3611
player.state = Player_State_Air
3612
#endplatform
3613
#platform: USE_ORIGINS
3614
player.state = Player_State_Air_NoDropDash
3615
#endplatform
3616
player.timer = 0
3617
else
3618
if player.jumpPress == true
3619
CallFunction(Player_Action_Jump)
3620
end if
3621
end if
3622
end if
3623
end function
3624
3625
3626
public function Player_State_Crouch
3627
#platform: USE_ORIGINS
3628
currentPlayer = player.entityPos
3629
#endplatform
3630
3631
if player.down == false
3632
player.state = Player_State_Ground
3633
player.timer = 0
3634
else
3635
if player.timer < 60
3636
player.timer++
3637
else
3638
temp0 = player.ypos
3639
temp0 >>= 16
3640
#platform: USE_STANDALONE
3641
temp0 -= camera[0].ypos
3642
#endplatform
3643
3644
#platform: USE_ORIGINS
3645
temp0 -= camera[currentPlayer].ypos
3646
#endplatform
3647
temp0 += 96
3648
if player.lookPosY < temp0
3649
player.lookPosY += 2
3650
end if
3651
end if
3652
3653
player.animation = ANI_LOOKINGDOWN
3654
if player.gravity == GRAVITY_AIR
3655
#platform: USE_STANDALONE
3656
player.state = Player_State_Air
3657
#endplatform
3658
#platform: USE_ORIGINS
3659
player.state = Player_State_Air_NoDropDash
3660
#endplatform
3661
player.timer = 0
3662
else
3663
if player.jumpPress == true
3664
CallFunction(player.spindashFunction)
3665
end if
3666
end if
3667
end if
3668
end function
3669
3670
3671
public function Player_State_Spindash
3672
if player.gravity == GRAVITY_AIR
3673
#platform: USE_STANDALONE
3674
player.state = Player_State_Air
3675
#endplatform
3676
#platform: USE_ORIGINS
3677
player.state = Player_State_Air_NoDropDash
3678
#endplatform
3679
player.speed = 0
3680
end if
3681
3682
if player.jumpPress == true
3683
if player.abilityTimer < 0x90000
3684
player.abilityTimer += 0x20000
3685
else
3686
player.abilityTimer = 0x80000
3687
end if
3688
3689
player.frame = 0
3690
PlaySfx(SfxName[Charge], false)
3691
else
3692
temp0 = player.abilityTimer
3693
temp0 >>= 5
3694
player.abilityTimer -= temp0
3695
end if
3696
3697
#platform: USE_ORIGINS
3698
temp1 = player.down
3699
3700
CheckEqual(player.releasingDropDash, false)
3701
temp2 = checkResult
3702
temp3 = 20
3703
temp3 -= 1 // yep
3704
CallFunction(Player_GetDropDashCharge)
3705
CheckGreater(temp7, temp3)
3706
temp2 &= checkResult
3707
3708
if temp2 == true
3709
temp7 = -1
3710
CallFunction(Player_SetDropDashCharge)
3711
Sin256(temp0, player.angle)
3712
3713
if player.direction == FACING_RIGHT
3714
if temp0 >= 0
3715
temp0 <<= 12
3716
else
3717
temp0 <<= 11
3718
end if
3719
else
3720
if temp0 >= 0
3721
temp0 <<= 11
3722
else
3723
temp0 <<= 12
3724
end if
3725
FlipSign(temp0)
3726
end if
3727
3728
player.abilityTimer = temp0
3729
temp1 = false
3730
end if
3731
3732
if temp1 == false
3733
#endplatform
3734
3735
#platform: USE_STANDALONE
3736
if player.down == false
3737
#endplatform
3738
// Release the spindash!
3739
3740
player.timer = 0
3741
player.state = Player_State_Roll
3742
player.animation = ANI_JUMPING
3743
player.iypos -= player.jumpOffset
3744
3745
currentPlayer = player.entityPos
3746
if player.entityPos == camera[currentPlayer].target
3747
player.scrollDelay = 15
3748
camera[currentPlayer].style = CAMERASTYLE_HLOCKED
3749
end if
3750
3751
temp0 = player.abilityTimer
3752
temp0 >>= 17
3753
temp0 <<= 16
3754
if Player_superState == SUPERSTATE_SUPER
3755
temp0 += 0xB0000
3756
else
3757
temp0 += 0x80000
3758
end if
3759
3760
if player.direction == FACING_RIGHT
3761
player.speed = temp0
3762
else
3763
player.speed = temp0
3764
FlipSign(player.speed)
3765
end if
3766
3767
StopSfx(SfxName[Charge])
3768
PlaySfx(SfxName[Release], false)
3769
CallFunction(Player_HandleOnGround)
3770
end if
3771
end function
3772
3773
3774
public function Player_HandleFlyCarry
3775
if player.flyCarryTimer != 0
3776
player.flyCarryTimer--
3777
end if
3778
3779
temp0 = player.xpos
3780
temp1 = player.ypos
3781
temp1 += 0x1F0000
3782
if player[SLOT_PLAYER1].animation == ANI_JUMPING
3783
temp1 += 0x50000
3784
end if
3785
3786
temp0 -= player[SLOT_PLAYER1].xpos
3787
temp1 -= player[SLOT_PLAYER1].ypos
3788
if player[SLOT_PLAYER1].state != Player_State_Carried
3789
CheckEqual(player[SLOT_PLAYER1].gravity, GRAVITY_GROUND)
3790
temp2 = checkResult
3791
CheckGreater(player.yvel, 0)
3792
temp2 &= checkResult
3793
3794
if temp2 == false
3795
CheckEqual(player[SLOT_PLAYER1].state, Player_State_Ground)
3796
temp2 = checkResult
3797
CheckEqual(player[SLOT_PLAYER1].state, Player_State_Roll)
3798
temp2 |= checkResult
3799
CheckEqual(player[SLOT_PLAYER1].state, Player_State_Air)
3800
temp2 |= checkResult
3801
CheckEqual(player[SLOT_PLAYER1].state, Player_State_RollJump)
3802
temp2 |= checkResult
3803
CheckEqual(player[SLOT_PLAYER1].state, Player_State_LookUp)
3804
temp2 |= checkResult
3805
CheckEqual(player[SLOT_PLAYER1].state, Player_State_Crouch)
3806
temp2 |= checkResult
3807
3808
if temp2 != false
3809
temp2 = temp0
3810
Abs(temp2)
3811
temp3 = temp1
3812
Abs(temp3)
3813
if temp2 <= 0x80000
3814
if temp3 <= 0x80000
3815
if player.flyCarryTimer == 0
3816
if player[SLOT_PLAYER1].down == false
3817
player[SLOT_PLAYER1].animation = ANI_HANGING
3818
player[SLOT_PLAYER1].state = Player_State_Carried
3819
player[SLOT_PLAYER1].xpos += temp0
3820
player[SLOT_PLAYER1].ypos += temp1
3821
PlaySfx(SfxName[Catch], false)
3822
end if
3823
end if
3824
end if
3825
end if
3826
end if
3827
end if
3828
end if
3829
3830
if player[SLOT_PLAYER1].state == Player_State_Carried
3831
temp2 = player.xpos
3832
temp3 = player.ypos
3833
temp6 = player.xvel
3834
temp7 = player.yvel
3835
ProcessObjectMovement()
3836
3837
Player_flyCarryBuddyXPos = player.xpos
3838
Player_flyCarryBuddyYPos = player.ypos
3839
temp4 = player.xpos
3840
temp4 &= 0xFFFF0000
3841
temp5 = player.ypos
3842
temp5 &= 0xFFFF0000
3843
temp5 += 0x1F0000
3844
player.xpos = temp2
3845
player.ypos = temp3
3846
player.xvel = temp6
3847
player.yvel = temp7
3848
3849
stage.entityPos = SLOT_PLAYER1
3850
temp0 = player.xpos
3851
temp0 &= 0xFFFF0000
3852
temp1 = player.ypos
3853
temp1 &= 0xFFFF0000
3854
player.xvel = temp4
3855
player.yvel = temp5
3856
player.xvel -= temp0
3857
player.yvel -= temp1
3858
ProcessObjectMovement()
3859
3860
stage.entityPos = SLOT_PLAYER2
3861
#platform: USE_STANDALONE
3862
player[SLOT_PLAYER1].collisionPlane = player.collisionPlane
3863
#endplatform
3864
#platform: USE_ORIGINS
3865
player.collisionPlane = player[SLOT_PLAYER1].collisionPlane
3866
player.sortedDrawOrder = player[SLOT_PLAYER1].sortedDrawOrder
3867
#endplatform
3868
player[SLOT_PLAYER1].speed = player.speed
3869
player[SLOT_PLAYER1].direction = player.direction
3870
Player_flyCarryLeaderXPos = player[SLOT_PLAYER1].xpos
3871
Player_flyCarryLeaderYPos = player[SLOT_PLAYER1].ypos
3872
temp2 = player[SLOT_PLAYER1].xpos
3873
temp2 &= 0xFFFF0000
3874
temp3 = player[SLOT_PLAYER1].ypos
3875
temp3 &= 0xFFFF0000
3876
CheckNotEqual(temp4, temp2)
3877
temp6 = checkResult
3878
CheckNotEqual(temp5, temp3)
3879
temp6 |= checkResult
3880
if temp6 == true
3881
if player[SLOT_PLAYER1].gravity == GRAVITY_GROUND
3882
player[SLOT_PLAYER1].state = Player_State_Ground
3883
else
3884
#platform: USE_STANDALONE
3885
player[SLOT_PLAYER1].state = Player_State_Air
3886
#endplatform
3887
#platform: USE_ORIGINS
3888
player[SLOT_PLAYER1].state = Player_State_Air_NoDropDash
3889
#endplatform
3890
end if
3891
3892
player.flyCarryTimer = 30
3893
end if
3894
end if
3895
end function
3896
3897
3898
public function Player_State_Carried
3899
if player[1].state != Player_State_Fly
3900
#platform: USE_STANDALONE
3901
player.state = Player_State_Air
3902
#endplatform
3903
#platform: USE_ORIGINS
3904
player.state = Player_State_Air_NoDropDash
3905
#endplatform
3906
end if
3907
3908
temp0 = player[1].xpos
3909
temp0 &= 0xFFFF0000
3910
temp2 = player.xpos
3911
temp2 &= 0xFFFF0000
3912
if player.xpos == Player_flyCarryLeaderXPos
3913
Player_flyCarryBuddyXPos &= 0xFFFF0000
3914
temp1 = temp0
3915
temp1 -= Player_flyCarryBuddyXPos
3916
temp2 += temp1
3917
end if
3918
3919
if temp0 != temp2
3920
if player.gravity == GRAVITY_GROUND
3921
player.state = Player_State_Ground
3922
else
3923
#platform: USE_STANDALONE
3924
player.state = Player_State_Air
3925
#endplatform
3926
#platform: USE_ORIGINS
3927
player.state = Player_State_Air_NoDropDash
3928
#endplatform
3929
end if
3930
end if
3931
3932
if player.gravity == GRAVITY_GROUND
3933
if player.yvel >= 0
3934
player.state = Player_State_Ground
3935
end if
3936
end if
3937
3938
if player.jumpPress != false
3939
if player.down != false
3940
if player.gravityStrength == 0x3800
3941
player.yvel = -0x40000
3942
else
3943
player.yvel = -0x20000
3944
end if
3945
player.state = Player_State_Air
3946
player.animation = ANI_JUMPING
3947
end if
3948
end if
3949
3950
if player.state == Player_State_Carried
3951
player.xvel = 0
3952
player.yvel = 0
3953
player.speed = 0
3954
else
3955
player[1].flyCarryTimer = 30
3956
end if
3957
end function
3958
3959
3960
public function Player_State_Fly
3961
CallFunction(Player_HandleAirFriction)
3962
if player.gravity == GRAVITY_AIR
3963
player.xvel = player.speed
3964
if player.yvel < -0x10000
3965
player.flightVelocity = 0x800
3966
else
3967
if player.yvel < 1
3968
if player.abilityTimer < 60
3969
player.abilityTimer++
3970
else
3971
player.flightVelocity = 0x800
3972
end if
3973
end if
3974
end if
3975
3976
player.yvel += player.flightVelocity
3977
temp0 = stage.curYBoundary1
3978
temp0 += 16
3979
temp0 <<= 16
3980
3981
if player.ypos < temp0
3982
if player.yvel < 0
3983
player.yvel = 0
3984
end if
3985
end if
3986
3987
if options.vsMode == false
3988
CallFunction(Player_HandleFlyCarry)
3989
end if
3990
3991
if player.timer < 480
3992
if player.gravityStrength == 0x3800
3993
if player[SLOT_PLAYER1].state == Player_State_Carried
3994
if player.yvel < 0
3995
player.animation = ANI_FLY_LIFT_UP
3996
player.animationSpeed = 240
3997
else
3998
player.animation = ANI_FLY_LIFT_DOWN
3999
player.animationSpeed = 120
4000
end if
4001
else
4002
player.animation = ANI_FLYING
4003
if player.yvel < 0
4004
player.animationSpeed = 240
4005
else
4006
player.animationSpeed = 120
4007
end if
4008
end if
4009
else
4010
if player[SLOT_PLAYER1].state == Player_State_Carried
4011
player.animation = ANI_SWIM_LIFT
4012
else
4013
player.animation = ANI_SWIMMING
4014
4015
if player.yvel < 0
4016
player.animationSpeed = 60
4017
else
4018
player.animationSpeed = 30
4019
end if
4020
end if
4021
end if
4022
4023
player.timer++
4024
if player.timer == 480
4025
if player.gravityStrength == 0x3800
4026
if player[SLOT_PLAYER1].state == Player_State_Carried
4027
player.animation = ANI_FLY_LIFT_TIRED
4028
else
4029
player.animation = ANI_FLYINGTIRED
4030
end if
4031
player.animationSpeed = 120
4032
4033
StopSfx(SfxName[Flying])
4034
PlaySfx(SfxName[Tired], true)
4035
else
4036
if player[SLOT_PLAYER1].state == Player_State_Carried
4037
player.animation = ANI_SWIM_LIFT
4038
else
4039
player.animation = ANI_SWIMMINGTIRED
4040
end if
4041
end if
4042
else
4043
if player.jumpPress == true
4044
CheckNotEqual(player.gravityStrength, 0x3800)
4045
temp0 = checkResult
4046
CheckEqual(player[SLOT_PLAYER1].state, Player_State_Carried)
4047
temp0 &= checkResult
4048
4049
if temp0 == false
4050
player.flightVelocity = -0x2000
4051
player.abilityTimer = 0
4052
end if
4053
end if
4054
end if
4055
else
4056
if player.gravityStrength == 0x3800
4057
if player[SLOT_PLAYER1].state == Player_State_Carried
4058
player.animation = ANI_FLY_LIFT_TIRED
4059
else
4060
player.animation = ANI_FLYINGTIRED
4061
end if
4062
else
4063
if player[SLOT_PLAYER1].state == Player_State_Carried
4064
player.animation = ANI_SWIM_LIFT
4065
else
4066
player.animation = ANI_SWIMMINGTIRED
4067
end if
4068
end if
4069
end if
4070
else
4071
player.animation = ANI_WALKING
4072
player.state = Player_State_Ground
4073
CallFunction(Player_HandleOnGround)
4074
end if
4075
end function
4076
4077
4078
public function Player_State_GlideLeft
4079
if player.gravity == GRAVITY_AIR
4080
if player.jumpHold == true
4081
if player.timer == 256
4082
if player.speed < 0x180000
4083
player.speed += 0x400
4084
end if
4085
else
4086
if player.speed < 0x40000
4087
player.speed += 0x1000
4088
end if
4089
end if
4090
4091
if player.yvel > 0x8000
4092
player.yvel -= 0x2000
4093
else
4094
player.yvel += 0x2000
4095
end if
4096
4097
if player.timer < 256
4098
player.timer += 4
4099
end if
4100
4101
if player.timer < 170
4102
if player.timer > 86
4103
player.frame = 0
4104
else
4105
if player.timer > 44
4106
player.frame = 1
4107
else
4108
player.frame = 2
4109
end if
4110
end if
4111
else
4112
if player.timer < 212
4113
player.frame = 1
4114
else
4115
player.frame = 2
4116
end if
4117
end if
4118
4119
temp7 = player.xpos
4120
if player.timer < 128
4121
player.direction = FACING_RIGHT
4122
temp0 = false
4123
temp1 = false
4124
else
4125
player.direction = FACING_LEFT
4126
4127
player.xpos = temp7
4128
player.xpos += player.xvel
4129
player.ypos = player.ypos
4130
ObjectTileCollision(CSIDE_RWALL, -12, -2, player.collisionPlane)
4131
4132
temp0 = checkResult
4133
temp2 = player.xpos
4134
player.xpos = temp7
4135
player.xpos += player.xvel
4136
ObjectTileCollision(CSIDE_RWALL, -12, 11, player.collisionPlane)
4137
4138
temp1 = checkResult
4139
temp3 = player.xpos
4140
end if
4141
4142
Cos(player.xvel, player.timer)
4143
player.xvel *= player.speed
4144
player.xvel >>= 9
4145
4146
if player.right == true
4147
player.state = Player_State_GlideRight
4148
end if
4149
4150
player.xpos = temp7
4151
checkResult = temp0
4152
checkResult &= temp1
4153
if checkResult == true
4154
if temp2 == temp3
4155
player.state = Player_State_Climb
4156
player.speed = 0
4157
player.xvel = 0
4158
player.yvel = 0
4159
player.timer = 0
4160
PlaySfx(SfxName[Catch], false)
4161
else
4162
player.timer = 0
4163
player.xvel >>= 2
4164
player.speed = player.xvel
4165
player.animation = ANI_GLIDING_DROP
4166
player.state = Player_State_GlideDrop
4167
end if
4168
else
4169
if temp0 == true
4170
player.timer = 0
4171
player.xvel >>= 2
4172
player.speed = player.xvel
4173
player.animation = ANI_GLIDING_DROP
4174
player.state = Player_State_GlideDrop
4175
end if
4176
end if
4177
else
4178
player.timer = 0
4179
player.xvel >>= 2
4180
player.speed = player.xvel
4181
player.animation = ANI_GLIDING_DROP
4182
player.state = Player_State_GlideDrop
4183
end if
4184
else
4185
if player.collisionMode == CMODE_FLOOR
4186
player.timer = 0
4187
player.state = Player_State_GlideSlide
4188
player.animation = ANI_GLIDING_STOP
4189
player.speed = player.xvel
4190
else
4191
player.state = Player_State_Ground
4192
CallFunction(Player_HandleOnGround)
4193
player.skidding = 0
4194
end if
4195
end if
4196
4197
temp0 = stage.curYBoundary1
4198
temp0 += 16
4199
temp0 <<= 16
4200
if player.ypos < temp0
4201
player.xvel = 0
4202
player.speed = player.xvel
4203
end if
4204
end function
4205
4206
4207
public function Player_State_GlideRight
4208
if player.gravity == GRAVITY_AIR
4209
if player.jumpHold == true
4210
if player.timer == 0
4211
if player.speed < 0x180000
4212
player.speed += 0x400
4213
end if
4214
else
4215
if player.speed < 0x40000
4216
player.speed += 0x1000
4217
end if
4218
end if
4219
4220
if player.yvel > 0x8000
4221
player.yvel -= 0x2000
4222
else
4223
player.yvel += 0x2000
4224
end if
4225
4226
if player.timer > 0
4227
player.timer -= 4
4228
end if
4229
4230
if player.timer < 170
4231
if player.timer > 86
4232
player.frame = 0
4233
else
4234
if player.timer > 44
4235
player.frame = 1
4236
else
4237
player.frame = 2
4238
end if
4239
end if
4240
else
4241
if player.timer < 212
4242
player.frame = 1
4243
else
4244
player.frame = 2
4245
end if
4246
end if
4247
4248
temp7 = player.xpos
4249
if player.timer < 128
4250
player.direction = FACING_RIGHT
4251
4252
player.xpos = temp7
4253
player.xpos += player.xvel
4254
player.ypos = player.ypos
4255
ObjectTileCollision(CSIDE_LWALL, 12, -2, player.collisionPlane)
4256
4257
temp0 = checkResult
4258
temp2 = player.xpos
4259
player.xpos = temp7
4260
player.xpos += player.xvel
4261
ObjectTileCollision(CSIDE_LWALL, 12, 11, player.collisionPlane)
4262
4263
temp1 = checkResult
4264
temp3 = player.xpos
4265
else
4266
player.direction = FACING_LEFT
4267
temp0 = false
4268
temp1 = false
4269
end if
4270
4271
Cos(player.xvel, player.timer)
4272
player.xvel *= player.speed
4273
player.xvel >>= 9
4274
if player.left == true
4275
player.state = Player_State_GlideLeft
4276
end if
4277
4278
player.xpos = temp7
4279
checkResult = temp0
4280
checkResult &= temp1
4281
if checkResult == true
4282
temp2 >>= 1
4283
temp3 >>= 1
4284
if temp2 == temp3
4285
player.state = Player_State_Climb
4286
player.speed = 0
4287
player.xvel = 0
4288
player.yvel = 0
4289
player.timer = 0
4290
PlaySfx(SfxName[Catch], false)
4291
else
4292
player.timer = 0
4293
player.xvel >>= 2
4294
player.speed = player.xvel
4295
player.animation = ANI_GLIDING_DROP
4296
player.state = Player_State_GlideDrop
4297
end if
4298
else
4299
if temp0 == true
4300
player.speed = 0
4301
player.timer = 0
4302
player.xvel >>= 2
4303
player.speed = player.xvel
4304
player.animation = ANI_GLIDING_DROP
4305
player.state = Player_State_GlideDrop
4306
end if
4307
end if
4308
else
4309
player.timer = 0
4310
player.xvel >>= 2
4311
player.speed = player.xvel
4312
player.animation = ANI_GLIDING_DROP
4313
player.state = Player_State_GlideDrop
4314
end if
4315
else
4316
if player.collisionMode == CMODE_FLOOR
4317
player.timer = 0
4318
player.state = Player_State_GlideSlide
4319
player.animation = ANI_GLIDING_STOP
4320
player.speed = player.xvel
4321
else
4322
player.state = Player_State_Ground
4323
CallFunction(Player_HandleOnGround)
4324
player.skidding = 0
4325
end if
4326
end if
4327
4328
temp0 = stage.curYBoundary1
4329
temp0 += 16
4330
temp0 <<= 16
4331
if player.ypos < temp0
4332
player.xvel = 0
4333
player.speed = player.xvel
4334
end if
4335
end function
4336
4337
4338
public function Player_State_GlideDrop
4339
if player.gravity == GRAVITY_AIR
4340
CallFunction(Player_HandleAirFriction)
4341
CallFunction(Player_HandleAirMovement)
4342
else
4343
#platform: USE_ORIGINS
4344
// Origins Plus added performing actions out of this state like in S3&K, neat!
4345
if player.jumpPress == true
4346
player.xvel = 0
4347
player.speed = 0
4348
if player.down == true
4349
CallFunction(player.spindashFunction)
4350
else
4351
CallFunction(Player_Action_Jump)
4352
end if
4353
else
4354
#endplatform
4355
if player.timer == 0
4356
PlaySfx(SfxName[Landing], false)
4357
end if
4358
4359
player.scrollTracking = false
4360
player.speed = 0
4361
player.xvel = 0
4362
player.animation = ANI_LOOKINGDOWN
4363
player.prevAnimation = ANI_LOOKINGDOWN
4364
player.frame = 2
4365
4366
if player.timer < 16
4367
player.timer++
4368
else
4369
player.state = Player_State_Ground
4370
CallFunction(Player_HandleOnGround)
4371
player.skidding = 0
4372
end if
4373
#platform: USE_ORIGINS
4374
end if
4375
#endplatform
4376
end if
4377
end function
4378
4379
4380
public function Player_State_GlideSlide
4381
if player.gravity == GRAVITY_GROUND
4382
if player.speed == 0
4383
#platform: USE_ORIGINS
4384
// Origins Plus added performing actions out of this state like in S3&K, neat!
4385
if player.jumpPress == true
4386
if player.down == true
4387
CallFunction(player.spindashFunction)
4388
else
4389
CallFunction(Player_Action_Jump)
4390
end if
4391
else
4392
#endplatform
4393
player.scrollTracking = false
4394
player.frame = 1
4395
if player.timer < 16
4396
player.timer++
4397
else
4398
player.state = Player_State_Ground
4399
CallFunction(Player_HandleOnGround)
4400
player.skidding = 0
4401
end if
4402
#platform: USE_ORIGINS
4403
end if
4404
#endplatform
4405
else
4406
if ringTimer == 0
4407
CreateTempObject(TypeName[Dust Puff], 0, player.xpos, player.ypos)
4408
object[tempObjectPos].iypos += player.collisionBottom
4409
object[tempObjectPos].drawOrder = player.sortedDrawOrder
4410
4411
if player.timer == 0
4412
PlaySfx(SfxName[Sliding], false)
4413
player.timer = 1
4414
else
4415
player.timer = 0
4416
end if
4417
end if
4418
4419
player.frame = 0
4420
if player.speed > 0
4421
player.speed -= 0x2000
4422
if player.speed < 0
4423
player.speed = 0
4424
player.timer = 0
4425
end if
4426
else
4427
player.speed += 0x2000
4428
if player.speed > 0
4429
player.speed = 0
4430
player.timer = 0
4431
end if
4432
end if
4433
4434
if player.jumpHold == false
4435
player.speed = 0
4436
player.timer = 0
4437
end if
4438
end if
4439
4440
player.xvel = player.speed
4441
else
4442
player.timer = 0
4443
player.animation = ANI_GLIDING_DROP
4444
player.state = Player_State_GlideDrop
4445
end if
4446
end function
4447
4448
4449
public function Player_State_Climb
4450
if player.gravity == GRAVITY_AIR
4451
player.animation = ANI_CLIMBING
4452
if player.up == true
4453
if Player_superState == SUPERSTATE_SUPER
4454
player.yvel = -0x20000
4455
else
4456
player.yvel = -0x10000
4457
end if
4458
temp0 = player.collisionTop
4459
temp0 *= -0x10000
4460
4461
if player.ypos < temp0
4462
player.ypos = temp0
4463
end if
4464
4465
player.timer++
4466
if player.timer == 4
4467
player.timer = 0
4468
player.frame++
4469
player.frame %= 6
4470
end if
4471
else
4472
if player.down == true
4473
if Player_superState == SUPERSTATE_SUPER
4474
player.yvel = 0x20000
4475
else
4476
player.yvel = 0x10000
4477
end if
4478
4479
player.timer++
4480
if player.timer == 4
4481
player.timer = 0
4482
if player.frame < 1
4483
player.frame += 6
4484
end if
4485
4486
player.frame--
4487
end if
4488
else
4489
player.yvel = 0
4490
end if
4491
end if
4492
4493
if player.jumpPress == true
4494
player.animation = ANI_JUMPING
4495
player.state = Player_State_Air
4496
player.timer = 0
4497
PlaySfx(SfxName[Jump], false)
4498
4499
if player.direction == FACING_LEFT
4500
player.xvel = 0x40000
4501
player.speed = 0x40000
4502
player.direction = FACING_RIGHT
4503
else
4504
player.xvel = -0x40000
4505
player.speed = -0x40000
4506
player.direction = FACING_LEFT
4507
end if
4508
4509
player.yvel = -0x40000
4510
if player.gravityStrength != 0x3800
4511
player.xvel >>= 1
4512
player.speed >>= 1
4513
player.yvel >>= 1
4514
end if
4515
else
4516
if player.direction == FACING_RIGHT
4517
temp2 = player.xpos
4518
ObjectTileGrip(CSIDE_LWALL, 10, -10, player.collisionPlane)
4519
4520
temp0 = checkResult
4521
temp3 = player.xpos
4522
player.xpos = temp2
4523
ObjectTileGrip(CSIDE_LWALL, 10, 11, player.collisionPlane)
4524
4525
temp1 = checkResult
4526
if player.xpos > temp3
4527
player.xpos = temp3
4528
end if
4529
else
4530
temp2 = player.xpos
4531
ObjectTileGrip(CSIDE_RWALL, -10, -10, player.collisionPlane)
4532
4533
temp0 = checkResult
4534
temp3 = player.xpos
4535
player.xpos = temp2
4536
ObjectTileGrip(CSIDE_RWALL, -10, 11, player.collisionPlane)
4537
4538
temp1 = checkResult
4539
if player.xpos < temp3
4540
player.xpos = temp3
4541
end if
4542
end if
4543
4544
if temp0 == false
4545
player.xpos = temp2
4546
player.animation = ANI_LEDGEPULLUP
4547
player.yvel = 0
4548
player.timer = 0
4549
player.state = Player_State_LedgePullUp
4550
player.tileCollisions = false
4551
4552
if player.direction == FACING_RIGHT
4553
player.xpos += 0x10000
4554
end if
4555
else
4556
if temp1 == false
4557
player.animation = ANI_GLIDING_DROP
4558
player.prevAnimation = ANI_GLIDING_DROP
4559
player.frame = 2
4560
player.timer = 0
4561
player.state = Player_State_GlideDrop
4562
end if
4563
end if
4564
end if
4565
else
4566
player.animation = ANI_WALKING
4567
player.state = Player_State_Ground
4568
CallFunction(Player_HandleOnGround)
4569
end if
4570
end function
4571
4572
4573
public function Player_State_LedgePullUp
4574
switch player.frame
4575
case 0
4576
if player.timer < 5
4577
ObjectTileGrip(CSIDE_FLOOR, 12, -9, player.collisionPlane)
4578
player.timer++
4579
else
4580
player.timer = 0
4581
player.frame++
4582
4583
if player.direction == FACING_RIGHT
4584
player.xpos += 0x90000
4585
else
4586
player.xpos -= 0x90000
4587
end if
4588
4589
player.ypos -= 0xA0000
4590
end if
4591
break
4592
4593
case 1
4594
if player.timer < 5
4595
player.timer++
4596
else
4597
player.timer = 0
4598
player.frame++
4599
4600
if player.direction == FACING_RIGHT
4601
player.xpos += 0x50000
4602
else
4603
player.xpos -= 0x50000
4604
end if
4605
4606
player.ypos -= 0x20000
4607
end if
4608
break
4609
4610
case 2
4611
if player.timer < 5
4612
player.timer++
4613
else
4614
player.timer = 0
4615
player.animation = ANI_STOPPED
4616
#platform: USE_STANDALONE
4617
player.state = Player_State_Air
4618
#endplatform
4619
#platform: USE_ORIGINS
4620
player.state = Player_State_Air_NoDropDash
4621
#endplatform
4622
player.ypos -= 0xA0000
4623
player.tileCollisions = true
4624
end if
4625
break
4626
4627
end switch
4628
end function
4629
4630
4631
public function Player_State_GotHit
4632
#platform: USE_ORIGINS
4633
temp2 = false
4634
if game.playMode == BOOT_PLAYMODE_MISSION
4635
if game.missionFunctionNo == MISSIONNO_MERCY
4636
if game.missionValue == true
4637
game.missionValue = false
4638
temp2 = true
4639
end if
4640
end if
4641
end if
4642
#endplatform
4643
4644
if player.isSidekick == false
4645
arrayPos0 = player.entityPos
4646
arrayPos0 += playerCount
4647
if player.shield != SHIELD_NONE
4648
temp0 = 1
4649
ResetObjectEntity(arrayPos0, TypeName[Blank Object], 0, 0, 0)
4650
player.shield = SHIELD_NONE
4651
CheckEqual(options.spikeBehavior, 0)
4652
temp1 = checkResult
4653
CheckNotEqual(player.blinkTimer, 0)
4654
temp1 &= checkResult
4655
if temp1 == true
4656
PlaySfx(SfxName[Spike], false)
4657
else
4658
PlaySfx(SfxName[Hurt], false)
4659
end if
4660
else
4661
if player.rings == 0
4662
if player.blinkTimer != 0
4663
PlaySfx(SfxName[Spike], false)
4664
else
4665
PlaySfx(SfxName[Hurt], false)
4666
end if
4667
4668
temp0 = 3
4669
else
4670
PlaySfx(SfxName[Lose Rings], false)
4671
temp0 = 2
4672
end if
4673
end if
4674
else
4675
temp0 = 1
4676
if player.blinkTimer != 0
4677
PlaySfx(SfxName[Spike], false)
4678
else
4679
PlaySfx(SfxName[Hurt], false)
4680
end if
4681
end if
4682
4683
#platform: USE_ORIGINS
4684
if game.playMode == BOOT_PLAYMODE_MISSION
4685
// For the mission "Bodyguard" (Player 2 isn't in any other missions)
4686
if player.type == TypeName[Player 2 Object]
4687
temp0 = 3
4688
game.forceKillPlayer = true
4689
end if
4690
end if
4691
#endplatform
4692
4693
player.visible = true
4694
4695
#platform: USE_ORIGINS
4696
if temp2 != 0
4697
temp0 = 3
4698
end if
4699
#endplatform
4700
4701
switch temp0
4702
default
4703
case 0 // No effect
4704
break
4705
4706
case 1 // Recoil
4707
player.state = Player_State_Hurt
4708
player.animation = ANI_HURT
4709
player.yvel = -0x40000
4710
player.gravity = GRAVITY_AIR
4711
player.scrollTracking = true
4712
player.tileCollisions = true
4713
player.blinkTimer = 120
4714
4715
if player.gravityStrength == 0x1000
4716
player.speed >>= 1
4717
player.yvel >>= 1
4718
end if
4719
break
4720
4721
case 2 // Damage, losing rings
4722
player.state = Player_State_Hurt
4723
player.animation = ANI_HURT
4724
player.yvel = -0x40000
4725
player.gravity = GRAVITY_AIR
4726
player.scrollTracking = true
4727
player.tileCollisions = true
4728
player.blinkTimer = 120
4729
if player.gravityStrength == 0x1000
4730
player.speed >>= 1
4731
player.yvel >>= 1
4732
end if
4733
4734
temp0 = player.rings
4735
if temp0 > 16
4736
temp1 = temp0
4737
temp1 -= 16
4738
temp0 = 16
4739
else
4740
temp1 = 0
4741
end if
4742
4743
if temp1 > 16
4744
temp1 = 16
4745
end if
4746
temp3 = temp1
4747
temp3 >>= 1
4748
temp3 <<= 5
4749
temp2 = 384
4750
temp2 -= temp3
4751
temp3 >>= 4
4752
if temp3 == temp1
4753
temp2 += 16
4754
else
4755
temp2 -= 16
4756
end if
4757
4758
temp3 = 0
4759
while temp3 < temp1
4760
CreateTempObject(TypeName[Lose Ring], player.collisionPlane, player.xpos, player.ypos)
4761
Cos(object[tempObjectPos].xvel, temp2)
4762
Sin(object[tempObjectPos].yvel, temp2)
4763
object[tempObjectPos].xvel <<= 8
4764
object[tempObjectPos].yvel <<= 8
4765
object[tempObjectPos].animationSpeed = 256
4766
object[tempObjectPos].inkEffect = INK_ALPHA
4767
object[tempObjectPos].alpha = 256
4768
temp3++
4769
temp2 += 32
4770
loop
4771
temp3 = temp0
4772
temp3 >>= 1
4773
temp3 <<= 5
4774
temp2 = 384
4775
temp2 -= temp3
4776
temp3 >>= 4
4777
if temp3 == temp0
4778
temp2 += 16
4779
else
4780
temp2 -= 16
4781
end if
4782
4783
temp3 = 0
4784
while temp3 < temp0
4785
CreateTempObject(TypeName[Lose Ring], player.collisionPlane, player.xpos, player.ypos)
4786
Cos(object[tempObjectPos].xvel, temp2)
4787
Sin(object[tempObjectPos].yvel, temp2)
4788
object[tempObjectPos].xvel <<= 9
4789
object[tempObjectPos].yvel <<= 9
4790
object[tempObjectPos].animationSpeed = 256
4791
object[tempObjectPos].inkEffect = INK_ALPHA
4792
object[tempObjectPos].alpha = 256
4793
temp3++
4794
temp2 += 32
4795
loop
4796
player.rings = 0
4797
ringExtraLife = 100
4798
break
4799
4800
case 3 // Death!
4801
#platform: USE_STANDALONE
4802
player.sortedDrawOrder = 6
4803
#endplatform
4804
#platform: USE_ORIGINS
4805
player.sortedDrawOrder = 7
4806
#endplatform
4807
player.speed = 0
4808
player.yvel = -0x70000
4809
player.xvel = 0
4810
player.state = Player_State_Death
4811
player.animation = ANI_DYING
4812
player.tileCollisions = false
4813
player.interaction = false
4814
#platform: USE_ORIGINS
4815
currentPlayer = object.entityPos
4816
#endplatform
4817
#platform: USE_STANDALONE
4818
if player.entityPos == camera[0].target
4819
#endplatform
4820
#platform: USE_ORIGINS
4821
if player.entityPos == camera[currentPlayer].target
4822
#endplatform
4823
player.priority = PRIORITY_ALWAYS
4824
if player[1].type == TypeName[Player 2 Object]
4825
player[1].priority = PRIORITY_ALWAYS
4826
end if
4827
#platform: USE_STANDALONE
4828
camera[0].enabled = false
4829
if options.vsMode == false
4830
stage.state = STAGE_FROZEN
4831
end if
4832
#endplatform
4833
4834
#platform: USE_ORIGINS
4835
if options.vsMode == false
4836
stage.state = STAGE_FROZEN
4837
camera[currentPlayer].enabled = false
4838
else
4839
camera[currentPlayer].style = CAMERASTYLE_STATIC
4840
end if
4841
#endplatform
4842
end if
4843
4844
if object[+playerCount].type == invincibilityType
4845
object[+playerCount].propertyValue = 3
4846
end if
4847
4848
object[+playerCount].type = TypeName[Blank Object]
4849
break
4850
4851
end switch
4852
end function
4853
4854
4855
public function Player_State_Hurt
4856
if player.gravity == GRAVITY_AIR
4857
player.scrollTracking = true
4858
if player.gravityStrength == 0x3800
4859
player.yvel += 0x3000
4860
else
4861
player.yvel += 0xF00
4862
end if
4863
4864
player.xvel = player.speed
4865
else
4866
player.state = Player_State_Ground
4867
player.speed = 0
4868
player.xvel = 0
4869
CallFunction(Player_HandleOnGround)
4870
end if
4871
end function
4872
4873
4874
public function Player_State_Death
4875
if player.entityPos == SLOT_PLAYER1
4876
// If Player 1, then stop all Super activity
4877
if Player_superState == SUPERSTATE_SUPER
4878
Player_superState = SUPERSTATE_FADEOUT
4879
end if
4880
end if
4881
4882
if player.controlMode != CONTROLMODE_NONE
4883
player.yvel = -0x70000
4884
player.controlMode = CONTROLMODE_NONE
4885
end if
4886
4887
if player.blinkTimer != 0
4888
player.blinkTimer = 0
4889
player.visible = true
4890
end if
4891
4892
player.yvel += 0x3800
4893
if player.animation != ANI_BORED
4894
player.animation = ANI_DYING
4895
end if
4896
4897
currentPlayer = player.entityPos
4898
if player.entityPos == camera[currentPlayer].target
4899
temp0 = camera[currentPlayer].ypos
4900
temp0 += 272
4901
temp0 <<= 16
4902
if player.ypos > temp0
4903
player.ypos = temp0
4904
end if
4905
end if
4906
4907
if player.yvel > 0x100000
4908
if player.isSidekick == false
4909
#platform: USE_ORIGINS
4910
CallNativeFunction2(NotifyCallback, NOTIFY_DEATH_EVENT, 0)
4911
#endplatform
4912
4913
// global variable "array" (yes, this is actually how its done)
4914
arrayPos0 = GLOBAL_PLAYERLIVES
4915
#platform: USE_DECOMP
4916
arrayPos0 = VarName[player.lives]
4917
#endplatform
4918
arrayPos0 += player.entityPos
4919
4920
#platform: USE_ORIGINS
4921
if game.coinMode == false
4922
if game.playMode != BOOT_PLAYMODE_MISSION
4923
CheckEqual(game.playMode, BOOT_PLAYMODE_BOSSRUSH)
4924
temp0 = checkResult
4925
CheckEqual(game.oneStageFlag, false)
4926
temp0 |= checkResult
4927
if temp0 != false
4928
global[arrayPos0]--
4929
end if
4930
end if
4931
end if
4932
#endplatform
4933
4934
#platform: USE_STANDALONE
4935
global[arrayPos0]--
4936
#endplatform
4937
4938
if options.vsMode == false
4939
stage.timeEnabled = false
4940
4941
player.type = TypeName[Death Event]
4942
#platform: USE_STANDALONE
4943
deathEvent.drawOrder = 6
4944
deathEvent.leftTextPos = screen.xcenter
4945
deathEvent.leftTextPos -= 264
4946
deathEvent.rightTextPos = screen.xcenter
4947
deathEvent.rightTextPos += 200
4948
#endplatform
4949
#platform: USE_ORIGINS
4950
deathEvent.drawOrder = 7
4951
deathEvent.leftTextPos = screen.xcenter
4952
deathEvent.leftTextPos -= 232
4953
deathEvent.rightTextPos = screen.xcenter
4954
deathEvent.rightTextPos += 232
4955
#endplatform
4956
if options.gameMode == MODE_TIMEATTACK
4957
deathEvent.timer = 0
4958
deathEvent.state = DEATHEVENT_DEATH_TA
4959
else
4960
if global[arrayPos0] == 0 // If the player has no lives left
4961
deathEvent.timer = -2880
4962
deathEvent.state = DEATHEVENT_GAMEOVER
4963
PlayMusic(TRACK_GAMEOVER)
4964
stage.pauseEnabled = false
4965
#platform: USE_ORIGINS
4966
if game.oneStageFlag != false
4967
if game.playMode == BOOT_PLAYMODE_BOSSRUSH
4968
CallNativeFunction4(NotifyCallback, NOTIFY_STAGE_RETRY, 0, stage.listPos, 0)
4969
end if
4970
end if
4971
#endplatform
4972
else
4973
deathEvent.timer = 0
4974
deathEvent.state = DEATHEVENT_DEATH
4975
if stage.timeOver == true
4976
#platform: USE_ORIGINS
4977
if game.oneStageFlag == false
4978
#endplatform
4979
deathEvent.timer = -2880
4980
deathEvent.state = DEATHEVENT_TIMEOVER
4981
PlayMusic(TRACK_GAMEOVER)
4982
stage.pauseEnabled = false
4983
#platform: USE_ORIGINS
4984
end if
4985
#endplatform
4986
end if
4987
end if
4988
end if
4989
else
4990
if global[arrayPos0] == 0 // player.lives
4991
player.type = TypeName[Death Event]
4992
deathEvent.state = DEATHEVENT_GAMEOVER
4993
end if
4994
4995
if stage.timeOver == true
4996
player.type = TypeName[Death Event]
4997
deathEvent.state = DEATHEVENT_TIMEOVER
4998
end if
4999
5000
if player.type == TypeName[Death Event]
5001
#platform: USE_STANDALONE
5002
deathEvent.drawOrder = 6
5003
deathEvent.leftTextPos = screen.xcenter
5004
deathEvent.leftTextPos -= 264
5005
deathEvent.rightTextPos = screen.xcenter
5006
deathEvent.rightTextPos += 200
5007
#endplatform
5008
#platform: USE_ORIGINS
5009
deathEvent.drawOrder = 7
5010
deathEvent.leftTextPos = screen.xcenter
5011
deathEvent.leftTextPos -= 232
5012
deathEvent.rightTextPos = screen.xcenter
5013
deathEvent.rightTextPos += 232
5014
#endplatform
5015
deathEvent.timer = -2880
5016
PlayMusic(TRACK_GAMEOVER)
5017
stage.pauseEnabled = false
5018
else
5019
#platform: USE_STANDALONE
5020
player.state = Player_State_Air
5021
#endplatform
5022
#platform: USE_ORIGINS
5023
player.state = Player_State_Air_NoDropDash
5024
#endplatform
5025
player.rings = 0
5026
player.priority = PRIORITY_ACTIVE
5027
player.gravity = GRAVITY_AIR
5028
player.animation = ANI_HURT
5029
if player.entityPos == SLOT_PLAYER1
5030
player.xpos = vs.restartX1
5031
player.ypos = vs.restartY1
5032
else
5033
player.xpos = vs.restartX2
5034
player.ypos = vs.restartY2
5035
end if
5036
player.direction = FACING_RIGHT
5037
player.tileCollisions = true
5038
player.interaction = true
5039
player.visible = true
5040
#platform: USE_STANDALONE
5041
player.controlMode = CONTROLMODE_P1
5042
#endplatform
5043
#platform: USE_ORIGINS
5044
player.controlMode = currentPlayer
5045
#endplatform
5046
player.scrollTracking = true
5047
player.drawOrder = DRAWORDER_PLAYER
5048
player.sortedDrawOrder = 4
5049
player.collisionPlane = 0
5050
#platform: USE_STANDALONE
5051
if player.entityPos == camera[0].target
5052
CreateTempObject(TypeName[VS Game], 0, player.xpos, player.ypos)
5053
vsGame[tempObjectPos].timer = 384
5054
vsGame[tempObjectPos].state = VSGAME_FADEOUT
5055
camera[0].xpos = player.ixpos
5056
camera[0].ypos = player.iypos
5057
camera[0].enabled = true
5058
end if
5059
#endplatform
5060
#platform: USE_ORIGINS
5061
CreateTempObject(TypeName[VS Game], currentPlayer, player.xpos, player.ypos)
5062
vsGame[tempObjectPos].timer = 384
5063
vsGame[tempObjectPos].state = VSGAME_SCREENFADE
5064
camera[currentPlayer].xpos = player.ixpos
5065
camera[currentPlayer].ypos = player.iypos
5066
camera[currentPlayer].style = CAMERASTYLE_FOLLOW
5067
camera[currentPlayer].enabled = true
5068
#endplatform
5069
end if
5070
end if
5071
end if
5072
end if
5073
end function
5074
5075
5076
public function Player_State_Drown
5077
if player.entityPos == SLOT_PLAYER1
5078
if Player_superState == SUPERSTATE_SUPER
5079
Player_superState = SUPERSTATE_FADEOUT
5080
end if
5081
end if
5082
5083
player.controlMode = CONTROLMODE_NONE
5084
player.yvel += player.gravityStrength
5085
player.animation = ANI_DROWNING
5086
5087
currentPlayer = player.entityPos
5088
if player.entityPos == camera[currentPlayer].target
5089
temp0 = camera[currentPlayer].ypos
5090
temp0 += 272
5091
temp0 <<= 16
5092
if player.ypos > temp0
5093
player.ypos = temp0
5094
end if
5095
end if
5096
5097
if player.yvel > 0x80000
5098
if player.isSidekick == false
5099
#platform: USE_ORIGINS
5100
CallNativeFunction2(NotifyCallback, NOTIFY_DEATH_EVENT, 0)
5101
#endplatform
5102
5103
// global variable "array" (yes, this is actually how its done)
5104
arrayPos0 = GLOBAL_PLAYERLIVES
5105
#platform: USE_DECOMP
5106
arrayPos0 = VarName[player.lives]
5107
#endplatform
5108
arrayPos0 += player.entityPos
5109
5110
#platform: USE_ORIGINS
5111
if global[arrayPos0] > 0
5112
if game.coinMode == false
5113
if game.playMode != BOOT_PLAYMODE_MISSION
5114
CheckEqual(game.playMode, BOOT_PLAYMODE_BOSSRUSH)
5115
temp0 = checkResult
5116
CheckEqual(game.oneStageFlag, false)
5117
temp0 |= checkResult
5118
if temp0 != false
5119
global[arrayPos0]--
5120
end if
5121
end if
5122
end if
5123
end if
5124
#endplatform
5125
5126
#platform: USE_STANDALONE
5127
if global[arrayPos0] > 0
5128
global[arrayPos0]--
5129
end if
5130
#endplatform
5131
5132
if options.vsMode == false
5133
stage.timeEnabled = false
5134
5135
player.type = TypeName[Death Event]
5136
#platform: USE_STANDALONE
5137
deathEvent.drawOrder = 6
5138
deathEvent.leftTextPos = screen.xcenter
5139
deathEvent.leftTextPos -= 264
5140
deathEvent.rightTextPos = screen.xcenter
5141
deathEvent.rightTextPos += 200
5142
#endplatform
5143
#platform: USE_ORIGINS
5144
deathEvent.drawOrder = 7
5145
deathEvent.leftTextPos = screen.xcenter
5146
deathEvent.leftTextPos -= 232
5147
deathEvent.rightTextPos = screen.xcenter
5148
deathEvent.rightTextPos += 232
5149
#endplatform
5150
if options.gameMode == MODE_TIMEATTACK
5151
deathEvent.timer = 0
5152
deathEvent.state = DEATHEVENT_DEATH_TA
5153
else
5154
#platform: USE_STANDALONE
5155
if global[arrayPos0] == 0
5156
#endplatform
5157
#platform: USE_ORIGINS
5158
if player.lives == 0
5159
#endplatform
5160
deathEvent.timer = -2880
5161
deathEvent.state = DEATHEVENT_GAMEOVER
5162
PlayMusic(TRACK_GAMEOVER)
5163
stage.pauseEnabled = false
5164
else
5165
deathEvent.timer = 0
5166
deathEvent.state = DEATHEVENT_DEATH
5167
end if
5168
end if
5169
else
5170
#platform: USE_STANDALONE
5171
player.state = Player_State_Air
5172
#endplatform
5173
#platform: USE_ORIGINS
5174
player.state = Player_State_Air_NoDropDash
5175
#endplatform
5176
player.rings = 0
5177
player.priority = PRIORITY_ACTIVE
5178
player.gravity = GRAVITY_AIR
5179
player.animation = ANI_HURT
5180
if player.entityPos == SLOT_PLAYER1
5181
player.xpos = vs.restartX1
5182
player.ypos = vs.restartY1
5183
else
5184
player.xpos = vs.restartX2
5185
player.ypos = vs.restartY2
5186
end if
5187
5188
player.direction = FACING_RIGHT
5189
player.tileCollisions = true
5190
player.interaction = true
5191
player.visible = true
5192
#platform: USE_STANDALONE
5193
player.controlMode = CONTROLMODE_P1
5194
#endplatform
5195
#platform: USE_ORIGINS
5196
player.controlMode = currentPlayer
5197
#endplatform
5198
player.scrollTracking = true
5199
player.drawOrder = DRAWORDER_PLAYER
5200
player.sortedDrawOrder = 4
5201
player.collisionPlane = 0
5202
#platform: USE_STANDALONE
5203
if player.entityPos == camera[0].target
5204
CreateTempObject(TypeName[VS Game], 0, player.xpos, player.ypos)
5205
vsGame[tempObjectPos].timer = 384
5206
vsGame[tempObjectPos].state = VSGAME_FADEOUT
5207
camera[0].xpos = player.ixpos
5208
camera[0].ypos = player.iypos
5209
camera[0].enabled = true
5210
end if
5211
#endplatform
5212
#platform: USE_ORIGINS
5213
CreateTempObject(TypeName[VS Game], currentPlayer, player.xpos, player.ypos)
5214
vsGame[tempObjectPos].timer = 384
5215
vsGame[tempObjectPos].state = VSGAME_SCREENFADE
5216
camera[currentPlayer].xpos = player.ixpos
5217
camera[currentPlayer].ypos = player.iypos
5218
camera[currentPlayer].style = CAMERASTYLE_FOLLOW
5219
camera[currentPlayer].enabled = true
5220
#endplatform
5221
end if
5222
end if
5223
end if
5224
end function
5225
5226
5227
// Wacky Workbench hanging bar gimmick
5228
// Unused leftover from CD
5229
public function Player_State_HangBar
5230
if player.left == true
5231
player.direction = FACING_LEFT
5232
player.speed = -0x20000
5233
player.animationSpeed = 30
5234
else
5235
if player.right == true
5236
player.direction = FACING_RIGHT
5237
player.speed = 0x20000
5238
player.animationSpeed = 30
5239
else
5240
player.speed = 0
5241
player.animationSpeed = 0
5242
end if
5243
end if
5244
temp1 = player.xpos
5245
temp1 >>= 16
5246
temp2 = player.ypos
5247
temp2 >>= 16
5248
temp2 += player.collisionTop
5249
5250
Get16x16TileInfo(temp0, temp1, temp2, TILEINFO_ANGLEB)
5251
if temp0 != 3 // this is the bar tile flag value
5252
// and even if this function isn't used in Origins they still updated it there lol
5253
#platform: USE_STANDALONE
5254
player.state = Player_State_Air
5255
#endplatform
5256
#platform: USE_ORIGINS
5257
player.state = Player_State_Air_NoDropDash
5258
#endplatform
5259
player.speed = 0
5260
player.animationSpeed = 0
5261
player.yvel = 0
5262
end if
5263
5264
if player.jumpPress == true
5265
player.state = Player_State_Air
5266
player.yvel = 0
5267
player.speed = 0
5268
player.animationSpeed = 0
5269
player.ypos += 0x40000
5270
end if
5271
5272
player.xvel = player.speed
5273
end function
5274
5275
5276
public function Player_State_TubeRoll
5277
#platform: USE_ORIGINS
5278
temp7 = -1
5279
CallFunction(Player_SetDropDashCharge)
5280
#endplatform
5281
5282
if player.gravity == GRAVITY_AIR
5283
player.state = Player_State_TubeAirRoll
5284
player.timer = 0
5285
CallFunction(Player_HandleAirMovement)
5286
else
5287
if player.speed > 0
5288
if player.collisionMode == CMODE_FLOOR
5289
if player.speed < 0x10000
5290
player.speed = 0x40000
5291
end if
5292
end if
5293
else
5294
if player.collisionMode == CMODE_FLOOR
5295
if player.speed > -0x10000
5296
player.speed = -0x40000
5297
end if
5298
end if
5299
end if
5300
5301
if player.right == true
5302
if player.speed < 0
5303
player.speed += player.rollingDeceleration
5304
end if
5305
end if
5306
5307
if player.left == true
5308
if player.speed > 0
5309
player.speed -= player.rollingDeceleration
5310
end if
5311
end if
5312
5313
if player.speed > 0
5314
player.speed -= player.rollingFriction
5315
Sin256(temp0, player.angle)
5316
if temp0 > 0
5317
Sin256(temp0, player.angle)
5318
temp0 *= 0x5000
5319
else
5320
Sin256(temp0, player.angle)
5321
temp0 *= 0x1E00
5322
end if
5323
temp0 >>= 8
5324
5325
player.speed += temp0
5326
else
5327
player.speed += player.rollingFriction
5328
Sin256(temp0, player.angle)
5329
if temp0 < 0
5330
Sin256(temp0, player.angle)
5331
temp0 *= 0x5000
5332
else
5333
Sin256(temp0, player.angle)
5334
temp0 *= 0x1E00
5335
end if
5336
temp0 >>= 8
5337
5338
player.speed += temp0
5339
end if
5340
5341
CallFunction(Player_HandleRollAnimSpeed)
5342
player.animationSpeed = player.rollAnimationSpeed
5343
CallFunction(Player_HandleOnGround)
5344
end if
5345
end function
5346
5347
5348
// Unused state
5349
// WFZ's clinging just uses an identical duplicate of this instead (WFZSetup_State_Clinging) stored within the stage's setup script
5350
public function Player_State_Clinging
5351
player.gravity = GRAVITY_AIR
5352
if player.animation != ANI_CLINGING
5353
player.xvel = 0x80000
5354
player.speed = 0x80000
5355
else
5356
player.xvel = 0
5357
player.speed = 0
5358
end if
5359
5360
if player.up == true
5361
player.ypos -= 0x10000
5362
else
5363
if player.down == true
5364
player.ypos += 0x10000
5365
end if
5366
end if
5367
5368
player.yvel = 0
5369
end function
5370
5371
5372
public function Player_State_Waterslide
5373
if player.gravity == GRAVITY_AIR
5374
#platform: USE_STANDALONE
5375
player.state = Player_State_Air
5376
#endplatform
5377
#platform: USE_ORIGINS
5378
player.state = Player_State_Air_NoDropDash
5379
#endplatform
5380
player.angle = 0
5381
player.collisionMode = CMODE_FLOOR
5382
player.timer = 0
5383
CallFunction(Player_HandleAirMovement)
5384
player.animation = ANI_WATERSLIDE
5385
else
5386
if player.direction == FACING_RIGHT
5387
player.speed = 0xA0000
5388
else
5389
player.speed = -0xA0000
5390
end if
5391
CallFunction(Player_HandleRollAnimSpeed)
5392
player.animation = ANI_WATERSLIDE
5393
5394
CallFunction(Player_HandleOnGround)
5395
if player.jumpPress == true
5396
CallFunction(Player_Action_Jump)
5397
end if
5398
end if
5399
end function
5400
5401
5402
public function Player_State_ContinueRun
5403
if player.speed > 0x10000
5404
player.timer = 0
5405
if player.speed < 0x5F5C2
5406
player.animation = ANI_WALKING
5407
CallFunction(Player_HandleWalkAnimSpeed)
5408
else
5409
if player.speed > 0x9FFFF
5410
player.animation = ANI_PEELOUT
5411
else
5412
player.animation = ANI_RUNNING
5413
end if
5414
5415
CallFunction(Player_HandleRunAnimSpeed)
5416
end if
5417
end if
5418
end function
5419
5420
public function Player_Action_DblJumpAmy
5421
#platform: USE_ORIGINS
5422
if keyPress[1].buttonY != false
5423
CheckEqual(specialStage.emeralds, 0x7F)
5424
temp0 = checkResult
5425
CheckGreater(player.rings, 49)
5426
temp0 &= checkResult
5427
CheckNotEqual(Player_superState, SUPERSTATE_SUPER)
5428
temp0 &= checkResult
5429
5430
if temp0 == true
5431
currentPlayer = player.entityPos
5432
CallFunction(Player_TryTransform)
5433
end if
5434
end if
5435
5436
if player.jumpPress == true
5437
PlaySfx(SfxName[HammerJump], false)
5438
CallNativeFunction4(NotifyCallback, NOTIFY_STATS_CHARA_ACTION2, 0, 1, 0)
5439
5440
// Change the animation without resetting the frame or animation speed
5441
temp0 = player.animationSpeed
5442
temp1 = player.frame
5443
player.animation = ANI_HAMMER_JUMP
5444
ProcessAnimation()
5445
player.animationSpeed = temp0
5446
player.frame = temp1
5447
5448
// No states are set here or anything, instead Amy shares Sonic's Drop Dash code seen in Player_HandleDropDash
5449
end if
5450
#endplatform
5451
end function
5452
5453
5454
public function Player_Action_HammerDash
5455
#platform: USE_ORIGINS
5456
PlaySfx(SfxName[HammerDash], false)
5457
5458
player.state = Player_State_HammerDash
5459
player.animation = ANI_HAMMER_DASH
5460
player.timer = 0
5461
5462
temp7 = -1
5463
CallFunction(Player_SetDropDashCharge)
5464
CallFunction(Player_SetHammerDashSpeed)
5465
#endplatform
5466
end function
5467
5468
5469
public function Player_State_HammerDash
5470
#platform: USE_ORIGINS
5471
if player.right == true
5472
player.direction = FACING_RIGHT
5473
else
5474
if player.left == true
5475
player.direction = FACING_LEFT
5476
end if
5477
end if
5478
5479
temp0 = true
5480
5481
if player.speed != 0
5482
player.timer++
5483
if player.jumpHold == true
5484
if player.timer < 60
5485
CallFunction(Player_SetHammerDashSpeed)
5486
if player.gravity == GRAVITY_AIR
5487
CallFunction(Player_HandleAirMovement)
5488
else
5489
CallFunction(Player_HandleOnGround)
5490
end if
5491
temp0 = false
5492
end if
5493
end if
5494
end if
5495
5496
// If Amy is on a steep enough slope, cancel the move
5497
// (Despite the patch notes for version 2.0.1 claiming this was removed, it's very much still here)
5498
Cos256(temp1, player.angle)
5499
if temp1 <= 0
5500
temp0 = true
5501
end if
5502
5503
if temp0 == true
5504
object.state = Player_State_Ground
5505
end if
5506
#endplatform
5507
end function
5508
5509
5510
public function Player_SetHammerDashSpeed
5511
#platform: USE_ORIGINS
5512
if player.direction == FACING_RIGHT
5513
player.speed = 0x60000
5514
else
5515
// Could they not have just set it to -0x60000?
5516
player.speed = 0
5517
player.speed -= 0x60000
5518
end if
5519
#endplatform
5520
end function
5521
5522
5523
// ========================
5524
// Events
5525
// ========================
5526
5527
event ObjectUpdate
5528
#platform: USE_ORIGINS
5529
currentPlayer = player.entityPos
5530
#endplatform
5531
5532
if stage.debugMode == true
5533
CallFunction(Player_ProcessUpdate)
5534
CheckEqual(options.attractMode, false)
5535
temp0 = checkResult
5536
CheckEqual(keyPress[0].buttonB, true)
5537
temp0 &= checkResult
5538
if temp0 == true
5539
currentPlayer = player.entityPos
5540
player.type = TypeName[Debug Mode]
5541
player.yvel = 0
5542
player.state = Player_State_Static
5543
player.frame = 0
5544
player.rotation = 0
5545
player.interaction = false
5546
player.drawOrder = 4
5547
player.priority = PRIORITY_ACTIVE
5548
player.blinkTimer = 0
5549
player.visible = true
5550
player.abilityTimer = 0
5551
player.drownTimer = 0
5552
player.drownLevel = 0
5553
player.frame = debugMode.currentSelection
5554
camera[currentPlayer].enabled = true
5555
camera[currentPlayer].style = CAMERASTYLE_FOLLOW
5556
player.hitboxLeft = C_BOX
5557
player.hitboxTop = C_BOX
5558
player.hitboxRight = C_BOX
5559
player.hitboxBottom = C_BOX
5560
5561
// This pretty much only happens when the player died, but now that they're entering Debug Mode, everything can be restored again
5562
if stage.state == STAGE_FROZEN
5563
stage.state = STAGE_RUNNING
5564
end if
5565
5566
if player[1].type == TypeName[Player 2 Object]
5567
player[1].priority = PRIORITY_ACTIVE
5568
end if
5569
5570
if object[+playerCount].propertyValue == 3
5571
object[+playerCount].type = invincibilityType
5572
object[+playerCount].propertyValue = 0
5573
end if
5574
else
5575
if player.gravity == GRAVITY_GROUND
5576
player.jumpAbilityState = 0
5577
end if
5578
5579
CallFunction(player.state)
5580
5581
// The Origins folks didn't put the Drop Dash "animation" code here...
5582
5583
currentPlayer = player.entityPos
5584
5585
ProcessAnimation()
5586
5587
if player.entityPos == camera[currentPlayer].target
5588
// Bug Details:
5589
// This check handles the jump offset so the jump ball sprite isn't higher than it's supposed to be relative to the actual player position
5590
// In Origins Plus, Amy has a second animation related to being in a jumpball, but this code doesn't take that into account. Whoops!
5591
if player.animation == ANI_JUMPING
5592
camera[currentPlayer].adjustY = player.jumpOffset
5593
else
5594
if camera[currentPlayer].adjustY == player.jumpOffset
5595
camera[currentPlayer].adjustY = 0
5596
player.iypos += player.jumpOffset
5597
end if
5598
end if
5599
end if
5600
5601
if player.collisionDisabled == false
5602
temp0 = player.prevGravity
5603
player.prevGravity = player.gravity
5604
ProcessObjectMovement()
5605
player.prevGravity ^= GRAVITY_AIR
5606
CheckEqual(player.gravity, GRAVITY_GROUND)
5607
player.prevGravity |= checkResult
5608
player.prevGravity ^= GRAVITY_AIR
5609
5610
if temp0 == GRAVITY_AIR
5611
if player.prevGravity == GRAVITY_GROUND
5612
player.badnikBonus = 0
5613
if player.animation == ANI_JUMPING
5614
if player.down == false
5615
if player.state != Player_State_BubbleBounce
5616
if player.state != Player_State_Roll
5617
if player.state != Player_State_TubeRoll
5618
player.animation = ANI_WALKING
5619
if player.entityPos == camera[currentPlayer].target
5620
camera[currentPlayer].adjustY = 0
5621
end if
5622
5623
player.iypos += player.jumpOffset
5624
end if
5625
end if
5626
end if
5627
end if
5628
end if
5629
end if
5630
end if
5631
else
5632
player.collisionDisabled = false
5633
end if
5634
end if
5635
else
5636
CallFunction(Player_ProcessUpdate)
5637
5638
if player.gravity == GRAVITY_GROUND
5639
player.jumpAbilityState = 0
5640
end if
5641
5642
CallFunction(player.state)
5643
5644
currentPlayer = player.entityPos
5645
5646
#platform: USE_ORIGINS
5647
// Set Sonic to always use the full ball sprite while drop dashing
5648
// Bug Details: This implementation has the side effect of freezing Sonic's/Amy's sprite while on Casino Night's flippers if they landed with a Drop Dash charged
5649
CallFunction(Player_GetDropDashCharge)
5650
if temp7 >= 20
5651
if player.animation == ANI_JUMPING
5652
player.frame = 1
5653
player.animationTimer = 0
5654
player.animationSpeed = 1
5655
end if
5656
end if
5657
#endplatform
5658
5659
ProcessAnimation()
5660
5661
if player.entityPos == camera[currentPlayer].target
5662
// Bug Details: See above
5663
if player.animation == ANI_JUMPING
5664
camera[currentPlayer].adjustY = player.jumpOffset
5665
else
5666
if camera[currentPlayer].adjustY == player.jumpOffset
5667
camera[currentPlayer].adjustY = 0
5668
player.iypos += player.jumpOffset
5669
end if
5670
end if
5671
end if
5672
5673
if player.collisionDisabled == false
5674
temp0 = player.prevGravity
5675
player.prevGravity = player.gravity
5676
ProcessObjectMovement()
5677
player.prevGravity ^= GRAVITY_AIR
5678
CheckEqual(player.gravity, GRAVITY_GROUND)
5679
player.prevGravity |= checkResult
5680
player.prevGravity ^= GRAVITY_AIR
5681
5682
if temp0 == GRAVITY_AIR
5683
if player.prevGravity == GRAVITY_GROUND
5684
player.badnikBonus = 0
5685
if player.animation == ANI_JUMPING
5686
if player.down == false
5687
if player.state != Player_State_BubbleBounce
5688
if player.state != Player_State_Roll
5689
if player.state != Player_State_TubeRoll
5690
player.animation = ANI_WALKING
5691
if player.entityPos == camera[currentPlayer].target
5692
camera[currentPlayer].adjustY = 0
5693
end if
5694
5695
player.iypos += player.jumpOffset
5696
end if
5697
end if
5698
end if
5699
end if
5700
end if
5701
end if
5702
end if
5703
else
5704
player.collisionDisabled = false
5705
end if
5706
end if
5707
5708
CallFunction(Player_HandleSuperForm)
5709
5710
#platform: USE_ORIGINS
5711
if game.playMode == BOOT_PLAYMODE_BOSSRUSH
5712
if game.missionCondition == MISSION_CONDITION_CLEAR
5713
player.invincibleTimer = 80
5714
5715
// Death Egg Zone handles the following itself
5716
CheckCurrentStageFolder("BR9Zone12")
5717
if checkResult == false
5718
CheckEqual(player[SLOT_PLAYER1].state, Player_State_Ground)
5719
temp0 = checkResult
5720
CheckEqual(player[SLOT_PLAYER1].state, Player_State_Static)
5721
temp0 |= checkResult
5722
5723
if temp0 == true
5724
// Prevent the player from moving anymore
5725
// Don't know why we have to specify object slot 0 when this code will only ever run in that slot but ok
5726
player[SLOT_PLAYER1].state = Player_State_Static
5727
player[SLOT_PLAYER1].controlMode = CONTROLMODE_NONE
5728
player[SLOT_PLAYER1].interaction = false
5729
player[SLOT_PLAYER1].up = false
5730
player[SLOT_PLAYER1].down = false
5731
player[SLOT_PLAYER1].left = false
5732
player[SLOT_PLAYER1].right = false
5733
player[SLOT_PLAYER1].jumpHold = false
5734
player[SLOT_PLAYER1].jumpPress = false
5735
player[SLOT_PLAYER1].xvel = 0
5736
player[SLOT_PLAYER1].yvel = 0
5737
player[SLOT_PLAYER1].speed = 0
5738
player[SLOT_PLAYER1].animation = ANI_WAITING
5739
end if
5740
end if
5741
end if
5742
end if
5743
5744
CallFunction(Player_HandleAmyHitbox)
5745
#endplatform
5746
end event
5747
5748
5749
event ObjectDraw
5750
if player.animation != player.prevAnimation
5751
// If the player's animation is different than the one they had last frame, reset all the other animation values too
5752
// Note that the ProcessAnimation function seen in ObjectMain does this too, so this is more of a fail-safe
5753
player.prevAnimation = player.animation
5754
player.frame = 0
5755
player.animationTimer = 0
5756
player.animationSpeed = 0
5757
end if
5758
5759
DrawObjectAnimation()
5760
end event
5761
5762
5763
event ObjectStartup
5764
playerCount = 0
5765
5766
// Do note, the foreach goes order ascending, which is why Origins mission scenes with several Player Objects can still function correctly since
5767
// the last one on the list is used
5768
foreach (TypeName[Player Object], arrayPos0, ALL_ENTITIES)
5769
camera[0].enabled = true
5770
camera[0].style = CAMERASTYLE_FOLLOW
5771
camera[0].target = SLOT_PLAYER1
5772
5773
currentPlayer = SLOT_PLAYER1
5774
5775
#platform: USE_STANDALONE
5776
if stage.playerListPos >= PLAYER_SONIC_TAILS_A // If playing as Sonic & Tails
5777
stage.playerListPos = PLAYER_SONIC_A
5778
stage.player2Enabled = true
5779
end if
5780
#endplatform
5781
5782
#platform: USE_ORIGINS
5783
switch stage.playerListPos
5784
case PLAYER_SONIC_TAILS_A
5785
stage.playerListPos = PLAYER_SONIC
5786
stage.player2Enabled = true
5787
break
5788
5789
case PLAYER_KNUCKLES_TAILS_A
5790
stage.playerListPos = PLAYER_KNUCKLES
5791
stage.player2Enabled = true
5792
break
5793
5794
case PLAYER_AMY_TAILS_A
5795
stage.playerListPos = PLAYER_AMY
5796
stage.player2Enabled = true
5797
break
5798
end switch
5799
#endplatform
5800
5801
ResetObjectEntity(SLOT_PLAYER1, TypeName[Player Object], 0, player[arrayPos0].xpos, player[arrayPos0].ypos)
5802
camera[0].xpos = player[SLOT_PLAYER1].ixpos
5803
camera[0].ypos = player[SLOT_PLAYER1].iypos
5804
5805
player[SLOT_PLAYER1].groupID = GROUP_PLAYERS
5806
player[SLOT_PLAYER1].state = Player_State_Air
5807
player[SLOT_PLAYER1].priority = PRIORITY_ACTIVE
5808
player[SLOT_PLAYER1].drawOrder = DRAWORDER_PLAYER
5809
player[SLOT_PLAYER1].sortedDrawOrder = 4
5810
player[SLOT_PLAYER1].rollingDeceleration = 0x2000
5811
player[SLOT_PLAYER1].spindashFunction = Player_Action_Spindash
5812
player[SLOT_PLAYER1].hitboxLeft = C_BOX
5813
player[SLOT_PLAYER1].hitboxTop = C_BOX
5814
player[SLOT_PLAYER1].hitboxRight = C_BOX
5815
player[SLOT_PLAYER1].hitboxBottom = C_BOX
5816
5817
// Reset things for Super forms
5818
Player_superState = SUPERSTATE_NONE
5819
Player_superRingLossTimer = 0
5820
Player_superBlendClr = 0
5821
Player_superBlendTimer = 0
5822
5823
switch stage.playerListPos
5824
case PLAYER_SONIC_A
5825
LoadAnimation("SuperSonic.ani") // This isn't because you're starting the act as Super Sonic, this is here to load all the necessary sprite sheets
5826
LoadAnimation("Sonic.ani")
5827
CallFunction(Player_HandleSuperPalette_Sonic)
5828
player[SLOT_PLAYER1].character = PLAYER_SONIC_A
5829
player[SLOT_PLAYER1].jumpOffset = -5
5830
player[SLOT_PLAYER1].jumpAbility = Player_Action_DblJumpSonic
5831
ANI_PEELOUT = ANI_RUNNING
5832
break
5833
5834
case PLAYER_TAILS_A
5835
player[SLOT_PLAYER1].type = TypeName[Tails Object]
5836
player[SLOT_PLAYER1].character = PLAYER_TAILS_A
5837
CallFunction(Player_HandleSuperPalette_Tails)
5838
LoadAnimation("Tails.ani")
5839
player[SLOT_PLAYER1].jumpOffset = -1
5840
5841
if options.vsMode == true
5842
options.tailsFlight = true
5843
end if
5844
5845
if options.tailsFlight == true
5846
player[SLOT_PLAYER1].jumpAbility = Player_Action_DblJumpTails
5847
else
5848
player[SLOT_PLAYER1].jumpAbility = Player_State_Static // Not being used as a State here, simply more of a dummy function
5849
end if
5850
5851
stage.player2Enabled = false
5852
break
5853
5854
case PLAYER_KNUCKLES_A
5855
LoadAnimation("Knuckles.ani")
5856
CallFunction(Player_HandleSuperPalette_Knux)
5857
player[SLOT_PLAYER1].character = PLAYER_KNUCKLES_A
5858
player[SLOT_PLAYER1].jumpOffset = -5
5859
player[SLOT_PLAYER1].jumpAbility = Player_Action_DblJumpKnux
5860
ANI_PEELOUT = ANI_RUNNING
5861
5862
// Note this check is actually bugged, this only checks for the last three save slots, ignoring the first one
5863
// Also yes this check is still in Origins LOL
5864
// It only works perchance, as per the bug listed right above
5865
if options.saveSlot > 0
5866
stage.player2Enabled = false
5867
end if
5868
break
5869
5870
#platform: USE_ORIGINS
5871
case PLAYER_AMY_A
5872
LoadAnimation("Amy.ani")
5873
CallFunction(Player_HandleSuperPalette_Amy)
5874
player[SLOT_PLAYER1].character = PLAYER_AMY
5875
player[SLOT_PLAYER1].jumpOffset = -4
5876
player[SLOT_PLAYER1].jumpAbility = Player_Action_DblJumpAmy
5877
ANI_PEELOUT = ANI_RUNNING
5878
break
5879
#endplatform
5880
end switch
5881
5882
if stage.player2Enabled == true
5883
playerCount = 2
5884
else
5885
playerCount = 1
5886
end if
5887
5888
currentPlayer = SLOT_PLAYER1
5889
CallFunction(Player_UpdatePhysicsState)
5890
ResetObjectEntity(arrayPos0, TypeName[Blank Object], 0, 0, 0)
5891
next
5892
end event
5893
5894
5895
// ========================
5896
// Editor Events
5897
// ========================
5898
5899
event RSDKDraw
5900
DrawSprite(0)
5901
end event
5902
5903
5904
event RSDKLoad
5905
LoadSpriteSheet("Players/Sonic1.gif")
5906
SpriteFrame(-16, -19, 27, 39, 1, 1)
5907
5908
// used in-game, but shouldn't be set from the editor
5909
SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
5910
end event
5911
5912