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