Difference between revisions of "Create Insta-kill and High Jump Monitors"
From Sonic Retro
Scarred Sun (talk | contribs) |
m (Text replacement - "\[\[Category:SCHG How-tos.*" to "") |
||
(7 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
− | This tutorial/how-to will show | + | This tutorial/how-to will show you how to make two types of monitors, which are an insta-kill ("R"), and hi-jump monitor. The former will always kill Sonic (even if he has a shield, or is invicible or super), while the latter will cause Sonic to jump extra high for a certain time period. For this guide, I will be using the 2007 Xenowhirl Sonic 2 Discode (without the extra split). Let's begin! |
− | Firstly, in the s2.asm file, | + | Firstly, in the s2.asm file, go to the label "robotnik_monitor". Underneath that label, you should see this: |
− | < | + | <pre> |
robotnik_monitor: | robotnik_monitor: | ||
addq.w #1,(a2) | addq.w #1,(a2) | ||
bra.w Touch_ChkHurt2 | bra.w Touch_ChkHurt2 | ||
− | </ | + | </pre> |
Change it to this: | Change it to this: | ||
− | < | + | <pre> |
robotnik_monitor: ;** Credits to Hayate | robotnik_monitor: ;** Credits to Hayate | ||
− | addq.w | + | addq.w #1,(a2) |
− | movea.l | + | movea.l a0,a1 |
− | lea | + | lea ($FFFFB000).w,a0 |
− | jsr | + | jsr (KillCharacter).l |
− | movea.l | + | movea.l a1,a0 |
rts | rts | ||
− | </ | + | </pre> |
− | Now, | + | Now, the hi-jump monitor is a little bit more difficult to make. For my purposes, instead of making a new monitor subtype, we will enable the hi-jump effect everytime a Tails 1up monitor is hit. Since this monitor does not do anything in 1 player mode, it is perfect for our purposes. In order for this effect to take place, we will have to make a new flag for the timing, and this flag will be called "hijump_time" |
− | First, we will | + | First, we will define our new flag. Near the beginning of the s2.asm file, you will find a list of variable definitions. (For newer disasms, this is in s2.constants.asm). Search for the following code, and add the flag, as shown: |
− | < | + | <pre> |
; conventions specific to sonic/tails (Obj01, Obj02, and ObjDB): | ; conventions specific to sonic/tails (Obj01, Obj02, and ObjDB): | ||
; note: $1F, $20, and $21 are unused and available | ; note: $1F, $20, and $21 are unused and available | ||
inertia = $14 ; and $15 ; directionless representation of speed... not updated in the air | inertia = $14 ; and $15 ; directionless representation of speed... not updated in the air | ||
+ | hijump_time = $1F ; <-- This guy right here is our new flag. | ||
flip_angle = $27 ; angle about the x=0 axis (360 degrees = 256) (twist/tumble) | flip_angle = $27 ; angle about the x=0 axis (360 degrees = 256) (twist/tumble) | ||
air_left = $28 | air_left = $28 | ||
Line 50: | Line 51: | ||
layer = $3E ; collision plane, track switching... | layer = $3E ; collision plane, track switching... | ||
layer_plus = $3F ; always same as layer+1 ?? used for collision somehow | layer_plus = $3F ; always same as layer+1 ?? used for collision somehow | ||
− | + | </pre> | |
− | |||
Afterwards, goto the label "tails_1up". Underneath there, you should see this: | Afterwards, goto the label "tails_1up". Underneath there, you should see this: | ||
− | < | + | <pre> |
tails_1up: | tails_1up: | ||
− | |||
addq.w #1,($FFFFFEF6).w | addq.w #1,($FFFFFEF6).w | ||
addq.b #1,(Life_count_2P).w | addq.b #1,(Life_count_2P).w | ||
Line 63: | Line 62: | ||
move.w #$98,d0 | move.w #$98,d0 | ||
jmp (PlayMusic).l ; Play extra life music | jmp (PlayMusic).l ; Play extra life music | ||
− | </ | + | </pre> |
Replace it with this: | Replace it with this: | ||
− | < | + | <pre> |
tails_1up: ;** | tails_1up: ;** | ||
addq.w #1,(a2) | addq.w #1,(a2) | ||
Line 73: | Line 72: | ||
move.w #$4B0,hijump_time(a1) | move.w #$4B0,hijump_time(a1) | ||
rts | rts | ||
− | </ | + | </pre> |
− | What that will do | + | What that will do is initialize a timer once the monitor is hit. You can modify the "move.w" value to any value you would like the timer to last. Lastly, in order to actually cause Sonic to jump higher, we need to modify some code for when Sonic jumps. A little ways under the label "Sonic_Jump", you should see the following code: |
− | < | + | <pre> |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
move.w #$680,d2 | move.w #$680,d2 | ||
tst.b (Super_Sonic_flag).w | tst.b (Super_Sonic_flag).w | ||
Line 96: | Line 85: | ||
beq.s + | beq.s + | ||
move.w #$380,d2 ; set lower jump speed if under | move.w #$380,d2 ; set lower jump speed if under | ||
− | + | </pre> | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | </ | ||
Change it to this: | Change it to this: | ||
− | < | + | <pre> |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
move.w #$680,d2 ;*** | move.w #$680,d2 ;*** | ||
tst.b (Super_Sonic_flag).w ;*** | tst.b (Super_Sonic_flag).w ;*** | ||
Line 150: | Line 102: | ||
beq.s + ;** | beq.s + ;** | ||
move.w #$1000,d2 ;sethigher jump speed if hit | move.w #$1000,d2 ;sethigher jump speed if hit | ||
− | + | </pre> | |
− | + | ||
− | + | You have now created a hi-jump monitor! You can change the value at the "move.w" after the ** to any other value to set how high Sonic will jump under the influence of the high jump monitor. | |
− | + | ||
− | + | ===EXTRA NOTE=== | |
− | + | (Addition by [[ThomasSpeedrunner]]) | |
− | + | You may notice a bug that comes with the hi-jump monitor: once you hit it, the ability is kept for the rest of the level. So, to fix this, we must add a check. Find this bit of code: | |
− | + | <pre> | |
− | + | ; loc_1A10C: | |
− | + | Obj01_ChkShoes: ; Checks if Speed Shoes have expired and disables them if they have. | |
− | + | btst #2,status_secondary(a0) | |
− | + | beq.s Obj01_ExitChk | |
− | + | tst.w speedshoes_time(a0) | |
− | + | beq.s Obj01_ExitChk | |
− | move. | + | subq.w #1,speedshoes_time(a0) |
− | + | bne.s Obj01_ExitChk | |
− | move.w #$ | + | move.w #$600,(Sonic_top_speed).w |
− | + | move.w #$C,(Sonic_acceleration).w | |
− | move. | + | move.w #$80,(Sonic_deceleration).w |
− | move. | + | tst.b (Super_Sonic_flag).w |
− | + | beq.s Obj01_RmvSpeed | |
− | + | move.w #$A00,(Sonic_top_speed).w | |
− | + | move.w #$30,(Sonic_acceleration).w | |
− | + | move.w #$100,(Sonic_deceleration).w | |
− | + | ; loc_1A14A: | |
− | + | Obj01_RmvSpeed: | |
− | + | bclr #2,status_secondary(a0) | |
− | </ | + | move.w #MusID_SlowDown,d0 ; Slow down tempo |
+ | jmp (PlayMusic).l | ||
+ | </pre> | ||
+ | Change it to this: | ||
+ | <pre> | ||
+ | ; loc_1A10C: | ||
+ | Obj01_ChkShoes: ; Checks if Speed Shoes have expired and disables them if they have. | ||
+ | btst #2,status_secondary(a0) | ||
+ | beq.s Obj01_ChkHighJump | ||
+ | tst.w speedshoes_time(a0) | ||
+ | beq.s Obj01_ChkHighJump | ||
+ | subq.w #1,speedshoes_time(a0) | ||
+ | bne.s Obj01_ChkHighJump | ||
+ | move.w #$600,(Sonic_top_speed).w | ||
+ | move.w #$C,(Sonic_acceleration).w | ||
+ | move.w #$80,(Sonic_deceleration).w | ||
+ | tst.b (Super_Sonic_flag).w | ||
+ | beq.s Obj01_RmvSpeed | ||
+ | move.w #$A00,(Sonic_top_speed).w | ||
+ | move.w #$30,(Sonic_acceleration).w | ||
+ | move.w #$100,(Sonic_deceleration).w | ||
+ | ; loc_1A14A: | ||
+ | Obj01_RmvSpeed: | ||
+ | bclr #2,status_secondary(a0) | ||
+ | move.w #MusID_SlowDown,d0 ; Slow down tempo | ||
+ | jmp (PlayMusic).l | ||
+ | </pre> | ||
+ | Now right below it, put in this: | ||
+ | <pre> | ||
+ | Obj01_ChkHighJump: ; Checks if High Jump has expired and diasbles it if it has. | ||
+ | btst #3,status_secondary(a0) | ||
+ | beq.s Obj01_ExitChk | ||
+ | tst.w hijump_time(a0) | ||
+ | beq.s Obj01_ExitChk | ||
+ | subq.w #1,hijump_time(a0) | ||
+ | bne.s Obj01_ExitChk | ||
+ | move.w #$680,d2 | ||
+ | tst.b (Super_Sonic_flag).w | ||
+ | beq.s Obj01_RmvHiJump | ||
+ | move.w #$800,d2 | ||
+ | Obj01_RmvHiJump: | ||
+ | bclr #3,status_secondary(a0) | ||
+ | </pre> | ||
+ | That fixes the infinite time bug. Now the hi-jump effect should wear off when it's supposed to! | ||
− | |||
{{S2Howtos}} | {{S2Howtos}} | ||
− | + | |{{PAGENAME}}]] |
Latest revision as of 11:11, 25 August 2018
This tutorial/how-to will show you how to make two types of monitors, which are an insta-kill ("R"), and hi-jump monitor. The former will always kill Sonic (even if he has a shield, or is invicible or super), while the latter will cause Sonic to jump extra high for a certain time period. For this guide, I will be using the 2007 Xenowhirl Sonic 2 Discode (without the extra split). Let's begin!
Firstly, in the s2.asm file, go to the label "robotnik_monitor". Underneath that label, you should see this:
robotnik_monitor: addq.w #1,(a2) bra.w Touch_ChkHurt2
Change it to this:
robotnik_monitor: ;** Credits to Hayate addq.w #1,(a2) movea.l a0,a1 lea ($FFFFB000).w,a0 jsr (KillCharacter).l movea.l a1,a0 rts
Now, the hi-jump monitor is a little bit more difficult to make. For my purposes, instead of making a new monitor subtype, we will enable the hi-jump effect everytime a Tails 1up monitor is hit. Since this monitor does not do anything in 1 player mode, it is perfect for our purposes. In order for this effect to take place, we will have to make a new flag for the timing, and this flag will be called "hijump_time"
First, we will define our new flag. Near the beginning of the s2.asm file, you will find a list of variable definitions. (For newer disasms, this is in s2.constants.asm). Search for the following code, and add the flag, as shown:
; conventions specific to sonic/tails (Obj01, Obj02, and ObjDB): ; note: $1F, $20, and $21 are unused and available inertia = $14 ; and $15 ; directionless representation of speed... not updated in the air hijump_time = $1F ; <-- This guy right here is our new flag. flip_angle = $27 ; angle about the x=0 axis (360 degrees = 256) (twist/tumble) air_left = $28 flip_turned = $29 ; 0 for normal, 1 to invert flipping (it's a 180 degree rotation about the axis of Sonic's spine, so he stays in the same position but looks turned around) obj_control = $2A ; 0 for normal, 1 for hanging or for resting on a flipper, $81 for going through CNZ/OOZ/MTZ tubes or stopped in CNZ cages or stoppers or flying if Tails status_secondary = $2B flips_remaining = $2C ; number of flip revolutions remaining flip_speed = $2D ; number of flip revolutions per frame / 256 move_lock = $2E ; and $2F ; horizontal control lock, counts down to 0 invulnerable_time = $30 ; and $31 ; time remaining until you stop blinking invincibility_time = $32 ; and $33 ; remaining speedshoes_time = $34 ; and $35 ; remaining next_tilt = $36 ; angle on ground in front of sprite tilt = $37 ; angle on ground stick_to_convex = $38 ; 0 for normal, 1 to make Sonic stick to convex surfaces like the rotating discs in Sonic 1 and 3 (unused in Sonic 2 but fully functional) spindash_flag = $39 ; 0 for normal, 1 for charging a spindash or forced rolling spindash_counter = $3A ; and $3B jumping = $3C interact = $3D ; RAM address of the last object Sonic stood on, minus $FFFFB000 and divided by $40 layer = $3E ; collision plane, track switching... layer_plus = $3F ; always same as layer+1 ?? used for collision somehow
Afterwards, goto the label "tails_1up". Underneath there, you should see this:
tails_1up: addq.w #1,($FFFFFEF6).w addq.b #1,(Life_count_2P).w addq.b #1,(Update_HUD_lives_2P).w move.w #$98,d0 jmp (PlayMusic).l ; Play extra life music
Replace it with this:
tails_1up: ;** addq.w #1,(a2) bset #3,status_secondary(a1) move.w #$4B0,hijump_time(a1) rts
What that will do is initialize a timer once the monitor is hit. You can modify the "move.w" value to any value you would like the timer to last. Lastly, in order to actually cause Sonic to jump higher, we need to modify some code for when Sonic jumps. A little ways under the label "Sonic_Jump", you should see the following code:
move.w #$680,d2 tst.b (Super_Sonic_flag).w beq.s + move.w #$800,d2 ; set higher jump speed if super + btst #6,status(a0) ; Test if underwater beq.s + move.w #$380,d2 ; set lower jump speed if under
Change it to this:
move.w #$680,d2 ;*** tst.b (Super_Sonic_flag).w ;*** beq.s + ;*** move.w #$800,d2 ; set higher jump speed if super + btst #6,status(a0) ; Test if underwater beq.s + move.w #$380,d2 ; set lower jump speed if under + btst #3,status_secondary(a0);**test if high jump monitor was hit beq.s + ;** move.w #$1000,d2 ;sethigher jump speed if hit
You have now created a hi-jump monitor! You can change the value at the "move.w" after the ** to any other value to set how high Sonic will jump under the influence of the high jump monitor.
EXTRA NOTE
(Addition by ThomasSpeedrunner) You may notice a bug that comes with the hi-jump monitor: once you hit it, the ability is kept for the rest of the level. So, to fix this, we must add a check. Find this bit of code:
; loc_1A10C: Obj01_ChkShoes: ; Checks if Speed Shoes have expired and disables them if they have. btst #2,status_secondary(a0) beq.s Obj01_ExitChk tst.w speedshoes_time(a0) beq.s Obj01_ExitChk subq.w #1,speedshoes_time(a0) bne.s Obj01_ExitChk move.w #$600,(Sonic_top_speed).w move.w #$C,(Sonic_acceleration).w move.w #$80,(Sonic_deceleration).w tst.b (Super_Sonic_flag).w beq.s Obj01_RmvSpeed move.w #$A00,(Sonic_top_speed).w move.w #$30,(Sonic_acceleration).w move.w #$100,(Sonic_deceleration).w ; loc_1A14A: Obj01_RmvSpeed: bclr #2,status_secondary(a0) move.w #MusID_SlowDown,d0 ; Slow down tempo jmp (PlayMusic).l
Change it to this:
; loc_1A10C: Obj01_ChkShoes: ; Checks if Speed Shoes have expired and disables them if they have. btst #2,status_secondary(a0) beq.s Obj01_ChkHighJump tst.w speedshoes_time(a0) beq.s Obj01_ChkHighJump subq.w #1,speedshoes_time(a0) bne.s Obj01_ChkHighJump move.w #$600,(Sonic_top_speed).w move.w #$C,(Sonic_acceleration).w move.w #$80,(Sonic_deceleration).w tst.b (Super_Sonic_flag).w beq.s Obj01_RmvSpeed move.w #$A00,(Sonic_top_speed).w move.w #$30,(Sonic_acceleration).w move.w #$100,(Sonic_deceleration).w ; loc_1A14A: Obj01_RmvSpeed: bclr #2,status_secondary(a0) move.w #MusID_SlowDown,d0 ; Slow down tempo jmp (PlayMusic).l
Now right below it, put in this:
Obj01_ChkHighJump: ; Checks if High Jump has expired and diasbles it if it has. btst #3,status_secondary(a0) beq.s Obj01_ExitChk tst.w hijump_time(a0) beq.s Obj01_ExitChk subq.w #1,hijump_time(a0) bne.s Obj01_ExitChk move.w #$680,d2 tst.b (Super_Sonic_flag).w beq.s Obj01_RmvHiJump move.w #$800,d2 Obj01_RmvHiJump: bclr #3,status_secondary(a0)
That fixes the infinite time bug. Now the hi-jump effect should wear off when it's supposed to!
|Create Insta-kill and High Jump Monitors]]