To the Sonic chase the enemies, we must use some RAM's value, so you can set and check if Sonic is chasing an object.
To the Sonic auto-chase the object, you need to create a jump (to skip pieces of code, as the check of button pessed), that every frame, calculate and execute the Homing Attack, if Sonic is chasing some object.
And in our case, we will create a counter to the chase have a time limit.
Note: Our counter's flag (RAM's address) is the same of our Homing Attack's flag.
Below these lines:
Because the next time that we calculate the Homing Attack (after the jump), we need to know the object's x and y position that Sonic is chasing - we need know which object the Sonic is chasing, to obtain the object's x and y position.
Now, below the HA_Move, add this code of four lines, which i will explain line by line:
The 1st line - Loads the RAM address of the object that Sonic is chasing, you need load the object's address in RAM to variable a1, in order to can make "the calculation of distance", which is the code below:
The 2nd line - Subtracts 1 of frames counter, so that when get 0, Sonic stop chasing the object, this explains the 3rd and 4th line of the code:
Now we need to make the jump, below Sonic_Homingattack add these two lines:
BUGS AND OTHER CODE MODIFICATIONS
Everything down from here and the Step 5, 6 and 7 is bug corrections and others modifications.
Bug: "Auto Homing Attack" after any jump
After doing all these modifications, if you compiled, you may have noticed an error after use the Homing Attack:
After any of these events, if you try jump, Sonic makes the Homing Attack,
or in case of monitor, enemy and boss, the Sonic is stopped for a time in air until the Homing Attack's time is over.
Why?
Because the Homing Attack is enabled (not was reset or set to 0)
The variable that determines whether the Homing Attack is activated is this below:
How to: Fix the bug when "touch the ground"
Search for Sonic_ResetOnFloor (values that are reset when Sonic touches the ground) and you will see this:
How to: Fix the bug when "destroy a monitor"
If you will do "bounce Sonic upwards in Homing Attack", this will be fixed in Step 6, but if you do not want this, continue normally.
Search for Touch_Monitor (the code that says what should happen if Sonic touches a monitor) and you'll find this:
How to: Fix the bug when "destroy a enemy"
If you will do "bounce Sonic upwards in Homing Attack", this will be fixed in Step 6, but if you do not want this, continue normally.
Search for Touch_KillEnemy (the code that says what should happen if Sonic destroy a enemy) and you'll find this:
How to: Fix the bug when "collect a giant ring"
When you collect a giant ring with the Homing Attack, the variable that shows whether Sonic is chasing someone is not reset, after you play a special stage, you can see that it's the same bug as in the previous three items:
How to fix?
Search for Obj4B_Collect (subroutine that shows what must happen when Sonic get a giant ring) and below these lines:
To the Sonic auto-chase the object, you need to create a jump (to skip pieces of code, as the check of button pessed), that every frame, calculate and execute the Homing Attack, if Sonic is chasing some object.
And in our case, we will create a counter to the chase have a time limit.
Note: Our counter's flag (RAM's address) is the same of our Homing Attack's flag.
Below these lines:
- Code:
cmp.l #16384,d1 ; is distance of Sonic, greater than or equal 128 pixels of the object? (128^2=16384 // $80^2=$4000)
bge.s HA_nextobject ; if yes, don't execute the homing attack
- Code:
move.b #30,($FFFFFFD1).w ; number of frames Sonic can chasing the object
move.l a1,($FFFFFFD2).w ; save the object address that Sonic is chasing
Because the next time that we calculate the Homing Attack (after the jump), we need to know the object's x and y position that Sonic is chasing - we need know which object the Sonic is chasing, to obtain the object's x and y position.
Now, below the HA_Move, add this code of four lines, which i will explain line by line:
- Code:
movea.l ($FFFFFFD2).w,a1 ; load the object address that Sonic is chasing
subi.b #1,($FFFFFFD1).w ; sub 1 of frames counter
tst.b ($FFFFFFD1).w ; the time to the Sonic chasing some object is over?
beq.w Sonic_HA_rts ; if yes, don't make the Homing Attack
The 1st line - Loads the RAM address of the object that Sonic is chasing, you need load the object's address in RAM to variable a1, in order to can make "the calculation of distance", which is the code below:
- Code:
; Recalculating the distance between the Sonic and the object (d1 = x distance / d2 = y distance)
move.w 8(a1),d1 ; move the object x-position to d1
move.w $C(a1),d2 ; move the object y-position to d2
sub.w 8(a0),d1 ; sub sonic x-position of object x-position
sub.w $C(a0),d2 ; sub sonic y-position of object y-position
The 2nd line - Subtracts 1 of frames counter, so that when get 0, Sonic stop chasing the object, this explains the 3rd and 4th line of the code:
- Code:
tst.b ($FFFFFFD1).w ; the time to the Sonic chasing some object is over?
beq.w Sonic_HA_rts ; if yes, don't make the Homing Attack
Now we need to make the jump, below Sonic_Homingattack add these two lines:
- Code:
tst.b ($FFFFFFD1).w ; is Sonic chasing some object?
bne.w HA_Move ; if yes, chase him
BUGS AND OTHER CODE MODIFICATIONS
Everything down from here and the Step 5, 6 and 7 is bug corrections and others modifications.
Bug: "Auto Homing Attack" after any jump
After doing all these modifications, if you compiled, you may have noticed an error after use the Homing Attack:
- touch the ground
- destroy a monitor (if you will do "bounce Sonic upwards in Homing Attack", fix it in Step 6)
- destroy a enemy (if you will do "bounce Sonic upwards in Homing Attack", fix it in Step 6)
- collect a giant ring
- hit a boss (this will be fixed in Step 5)
After any of these events, if you try jump, Sonic makes the Homing Attack,
or in case of monitor, enemy and boss, the Sonic is stopped for a time in air until the Homing Attack's time is over.
Why?
Because the Homing Attack is enabled (not was reset or set to 0)
The variable that determines whether the Homing Attack is activated is this below:
- Code:
$FFFFFFD1 ; number of frames Sonic can chasing the object
How to: Fix the bug when "touch the ground"
Search for Sonic_ResetOnFloor (values that are reset when Sonic touches the ground) and you will see this:
- Code:
Sonic_ResetOnFloor: ; XREF: PlatformObject; et al
btst #4,$22(a0)
beq.s loc_137AE
nop
nop
nop
loc_137AE:
bclr #5,$22(a0)
bclr #1,$22(a0)
bclr #4,$22(a0)
btst #2,$22(a0)
beq.s loc_137E4
bclr #2,$22(a0)
move.b #$13,$16(a0)
move.b #9,$17(a0)
move.b #0,$1C(a0) ; use running/walking animation
subq.w #5,$C(a0)
loc_137E4:
move.b #0,$3C(a0)
move.w #0,($FFFFF7D0).w
rts
; End of function Sonic_ResetOnFloor
- Code:
clr.b ($FFFFFFD1).w ; cancel the Homing Attack, clearing the number of frames Sonic can chasing the object
How to: Fix the bug when "destroy a monitor"
If you will do "bounce Sonic upwards in Homing Attack", this will be fixed in Step 6, but if you do not want this, continue normally.
Search for Touch_Monitor (the code that says what should happen if Sonic touches a monitor) and you'll find this:
- Code:
Touch_Monitor:
tst.w $12(a0) ; is Sonic moving upwards?
bpl.s loc_1AF1E ; if not, branch
move.w $C(a0),d0
subi.w #$10,d0
cmp.w $C(a1),d0
bcs.s locret_1AF2E
neg.w $12(a0) ; reverse Sonic's y-motion
move.w #-$180,$12(a1)
tst.b $25(a1)
bne.s locret_1AF2E
addq.b #4,$25(a1) ; advance the monitor's routine counter
rts
; ===========================================================================
loc_1AF1E:
cmpi.b #2,$1C(a0) ; is Sonic rolling/jumping?
bne.s locret_1AF2E
neg.w $12(a0) ; reverse Sonic's y-motion
addq.b #2,$24(a1) ; advance the monitor's routine counter
locret_1AF2E:
rts
- Code:
cmpi.b #2,$1C(a0) ; is Sonic rolling/jumping?
bne.s locret_1AF2E
- Code:
clr.b ($FFFFFFD1).w ; cancel the Homing Attack, clearing the number of frames Sonic can chasing the object
How to: Fix the bug when "destroy a enemy"
If you will do "bounce Sonic upwards in Homing Attack", this will be fixed in Step 6, but if you do not want this, continue normally.
Search for Touch_KillEnemy (the code that says what should happen if Sonic destroy a enemy) and you'll find this:
- Code:
Touch_KillEnemy:
bset #7,$22(a1)
moveq #0,d0
move.w ($FFFFF7D0).w,d0
addq.w #2,($FFFFF7D0).w ; add 2 to item bonus counter
cmpi.w #6,d0
bcs.s loc_1AF82
moveq #6,d0
loc_1AF82:
move.w d0,$3E(a1)
move.w Enemy_Points(pc,d0.w),d0
cmpi.w #$20,($FFFFF7D0).w ; have 16 enemies been destroyed?
bcs.s loc_1AF9C ; if not, branch
move.w #1000,d0 ; fix bonus to 10000
move.w #$A,$3E(a1)
loc_1AF9C:
bsr.w AddPoints
move.b #$27,0(a1) ; change object to points
move.b #0,$24(a1)
tst.w $12(a0)
bmi.s loc_1AFC2
move.w $C(a0),d0
cmp.w $C(a1),d0
bcc.s loc_1AFCA
neg.w $12(a0)
rts
- Code:
loc_1AF9C:
bsr.w AddPoints
- Code:
clr.b ($FFFFFFD1).w ; cancel the Homing Attack, clearing the number of frames Sonic can chasing the object
How to: Fix the bug when "collect a giant ring"
When you collect a giant ring with the Homing Attack, the variable that shows whether Sonic is chasing someone is not reset, after you play a special stage, you can see that it's the same bug as in the previous three items:
- touch the ground
- destroy a monitor
- destroy a enemy
How to fix?
Search for Obj4B_Collect (subroutine that shows what must happen when Sonic get a giant ring) and below these lines:
- Code:
Obj4B_Collect: ; XREF: Obj4B_Index
subq.b #2,$24(a0)
move.b #0,$20(a0)
bsr.w SingleObjLoad
bne.w Obj4B_PlaySnd
- Code:
clr.b ($FFFFFFD1).w ; cancel the Homing Attack, clearing the number of frames Sonic can chasing the object