Patch:Schoolfish
Schoolfish are harmless creatures in Keen 4 who chase keen in the Well of Wishes. They are useful in that they can act as decoys to stop Keen being eaten or attacked. It is linked to the Dopefish.
Sprite Type
Schoolfish uses sprite type 22 which is used only by Schoolfish and doesn't affect anything else. The Schoolfish's sprite type is reset when the Dopefish eats it.
Keen 4
#Schoolfish sprite type
%patch $123FD $01 #Dead Schoolfish (After Dopefish eats it)
%patch $124DB $16 #Schoolfish
Sprite Actions
The Schoolfish has three actions; two of them very similar, in that they seek Keen, and one used for when the Schoolfish is eaten. As such their behavior is remarkably simple, after being placed in a level; it swims indefinitely. When the fish is eaten it is changed into an eaten fish and then vanishes. This ties it to the Dopefish.
Actions: $3764W #Schoolfish 1 $3782W #Schoolfish 2 $3692W #Dead Schoolfish
Keen 4
#Fish placed in-level
%patch $12508 [$3764W] #Spawn Schoolfish
#Swimming fish
%patch $325F0 [$3782W] #Schoolfish 1
%patch $3260E [$3764W] #Schoolfish 2 [Go to 1
#Eaten fish
%patch $123E1 [$3692W] #Schoolfish eaten -Die
%patch $3251E [$0000W] #Dead Schoolfish -Disappear
Sprite Behavior
Schoolfish has only one behavior, the 'Seek Keen ' behavior. This can be used by any sprite since it does not involve sprite transformation. (Using it will not turn another sprite into a Schoolfish.)
Behaviors: $11A20AF6RL #Seek Keen
Keen 4
#Swimming
%patch $325E4 $11A20AF6RL #Seek Keen
%patch $32602 $11A20AF6RL #Seek Keen
#Dead
%patch $32512 $00000000L #Nothing
Behavior code
This is the behavior code for the Schoolfish. There are three checks performed (In brown.) The first checks to see if Keen is horizontally level with the fish, and if so, skips the horizontal movement stuff. The second checks if Keen is right or left of the fish and the third checks whether he is above or below it.
The checks define which speed and direction (In blue) are set; the first two directions are horizontal, the second two vertical. The first speed ($000AW) is horizontal (In either direction) and the second and third vertical. (Upwards first, then downwards.) Notice that this patch contains, and thus will overwrite a few patches found on this page. (Including the speed patches in the next section.)
Keen 4
#Schoolfish behavior code
%patch $12516 $55 $8B $EC $56 $8B $76 $06 $83 $7C $3E {$00 $75 $18} $8B $44 $0A #If Keen is level with fish, skip l\r stuff
$8B $1E $A7D6W $3B $47 {$0A $73 $07} $C7 $44 $0E [$0001W] $EB $05 #Check for Keen h, set h direction
$C7 $44 $0E [$FFFFW] $B8 [$000AW] $50 $FF $74 $0E $56 $9A #Set h speed = $A
$09DC149FRL $83 $C4 $06 $8B $44 $0C $8B $1E $A7D6W $3B $47 {$0C $73} #Check for Keen v
{$14} $B8 [$000AW] $50 $B8 [$0001W] $50 $56 $9A $09DC1517RL $83 #Set v speed and direction
$C4 $06 $5E $5D $CB $B8 [$000AW] $50 $B8 [$FFFFW] $50 $56 $9A
$09DC1517RL $83 $C4 $06 $5E $5D $CB
Compact code
This code is a slightly more compact version of the Schoolfish's behavior. This is done by rearranging the vertical speed checks and calls.
Keen 4
#Compact Schoolfish behavior code
%patch $12516 $55 $8B $EC $56 $8B $76 $06 $83 $7C $3E {$00 $75 $18} $8B $44 $0A #If Keen is level with fish, skip l\r stuff
$8B $1E $A7D6W $3B $47 {$0A $73 $07} $C7 $44 $0E [$0001W] $EB $05 #Check for Keen h, set h direction
$C7 $44 $0E [$FFFFW] $B8 [$000AW] $50 $FF $74 $0E $56 $9A #Set h speed = $A
$09DC149FRL $83 $C4 $06 $B8 [$000AW] $50 $8B $44 $0C $8B $1E $A7D6W #Set speed, check for Keen v
$3B $47 {$0C $73} $05 $B8 [$0001W] $EB $03 $B8 [$FFFFW] $50 $56 $9A #Set v direction
$09DC1517RL $83 $C4 $06 $5E $5D $CB
Seeking Keen
The Schoolfish seeks Keen in two dimensions, both horizontal and vertical. To make the Schoolfish flee Keen all four values must be reversed.
Keen seeking
#Schoolfish seek Keen
%patch $12532 $0001W #Seek Keen left
%patch $12539 $FFFFW #Seek Keen right
%patch $1255C $0001W #Seek Keen up
%patch $12570 $FFFFW #Seek Keen down
Swim Speed
Schoolfish have no animation motion, but they do swim smoothly, their floating speeds and magnitude are completely separate and depend on their swimming behavior code (See above.) As noted there are three speeds, up, down and horizontal (Left and right.
Animation motion
#Dead
%patch $3250E [$0000W $0000W]
#Swimming
%patch $325E0 [$0000W $0000W]
%patch $325FE [$0000W $0000W]
Swim speeds
#Swimming speeds
%patch $12558 [$000AW] #Speed up
%patch $1256C [$000AW] #Speed down
%patch $1253C [$000AW] #Speed left/right
Schoolfish turn instantly
By default Schoolfish need to accelerate\decelerate to change direction, something appropriate to an aquatic environment, but not always desirable. This patch makes the Schoolfish change direction and speed instantly, though its motion can become choppy. Speed is controlled by tweaking the speed and animation speed in the second section, Reversing the $FFFFW and $0001W values in the first section will make the Schoolfish run away from Keen.
The third section is optional; with it the Schoolfish behaves very erratically, a unique type of movement that may be useful, without it the patch works far more conventionally.
This patch is incompatible with other speed patches and Keens seeking patches for the Schoolfish, as it rewrites the Schoolfish's behavior code.
Keen 4
#Schoolfish turns instantly
%patch $12516 $55 $8B $EC $56 $8B $76 $06 $83 $7C $3E $00 $75 $18 $8B $44 $0A
$8B $1E $A7D6W $3B $47 $0A $73 $07 $C7 $44 $0E [$0001W] $EB $05
$C7 $44 $0E [$FFFFW] $8B $44 $0C $8B $1E $A7D6W $3B $47 $0C $73
$07 $C7 $44 $10 [$0001W] $EB $05 $C7 $44 $10 [$FFFFW] $5E $5D $CB
#Swimming
%patch $325E0 [$0040W $0040W] #Speed 1
%patch $325DE [$0008W] #Animation speed
%patch $325FE [$0040W $0040W] #Speed 2
%patch $325FC [$0008W] #Animation speed
#Insanity variables
%patch $325D8 [$0001W]
%patch $325F6 [$0001W]
Sprite Collision
The Schoolfish's collision is simple; they don't have one by default.
Collision values
Schoolfish have no collision. This means, technically nothing can affect them, instead, when a Dopefish touches them, the Dopefish itself reacts and eats them.
Keen 4 collision values
#Swimming
%patch $325E8 $00000000L #No collision
%patch $32606 $00000000L #No collision
#Eaten
%patch $32516 $00000000L #No collision
Animations
Schoolfishs' animations are simple enough, they cycles through two frames. The dead Schoolfish uses the same animation frames as the first swimming action.
Keen 4
#Cache
%patch $306FA [$01A5W] #Schoolfish Cache start
%patch $30744 [$01A8W] #Schoolfish cache end
#Dead Schoolfish
%patch $32502 $01A5W $01A7W
%patch $3250C $0000W
#Schoolfish swim
%patch $325D4 $01A5W $01A7W
%patch $325DE $0014W #Animation speed
%patch $325F2 $01A6W $01A8W
%patch $325FC $0014W #Animation speed
Clipping and foreground
The Schoolfish has a clipping value of 2, common for swimming sprites, which keeps it solidly out of all blocking tiles, including sloped tiles. Patching this can result in a 'fullcliptowalls' error. It has a foreground value of 0, keeping it firmly behind more important sprites and tiles. When the Schoolfish is eaten its clipping is removed. (This affects other sprites too.)
Keen 4 clipping
#Schoolfish clipping
%patch $124E5 $0002W
#Eaten Schoolfish clipping
%patch $12402 $0000W
Keen 4 foreground
#Schoolfish Foreground variable
%patch $1259D $0000W
Sprite-tile interaction
Schoolfish use the 'fish' tile interaction, used by both the Schoolfish and Dopefish. It is quite simple, it keeps them out of walls and sloped tiles.
Keen 4
#Swimming
%patch $325EC $11A20A3CRL
%patch $3260A $11A20A3CRL
#Dead
%patch $3251A $09DC176ERL
Action type
Schoolfish uses type 3 for its actions, allowing it to move smoothly, and a value of 2 when eaten, allowing it to sit and wait to vanish.
Keen 4
#Eaten Schoolfish
%patch $32606 [$0002W]
#Swimming
%patch $325D8 [$0003W]
%patch $325F6 [$0003W]
Deprotect and stick to ground
As Schoolfish doesn't need to move up or down hills they have a value of zero for all their frames.
Keen 4
#Swimming
%patch $325DA [$0000W $0000W]
%patch $325F8 [$0000W $0000W]
#Dead
%patch $32508 [$0000W $0000W]
Sprite spawn code
In the initiation code notice the Schoolfish cache being set ($C7 $06 $CB65W $0001W.)
In the spawning code the last blue highlighted value is the sprite action the sprite uses as it proceeds to act in-level. $C7 $06 $xxxxW sets the clipping, $C7 $07 $xxxxW sets the sprite type, $C7 $20 $xxxxW sets the foreground value. Finally $D3 $E0 $05 $xxxx is how far down (Or more usually up) the sprite is spawned from where it is placed. This is necessary for sprites that walk on the ground as they can only be placed in the level at multiples of 16 pixels high while their actual height can be anything.
A special thing to note is $C7 $02 $0001W which sets the Schoolfish's sprite activity to 1 which means it stops 'working' when offscreen.
Keen 4
#Location of initiation code
%patch $EEA3 [$027EW] #Schoolfish (At $EB6E)
#Schoolfish Initiation code
%patch $EB6E $FF $76 $FC $57 $9A {$11A20AA7RL} $83 $C4 $04 $C7 $06 $CB65W
$0001W $E9 $027AW
#Schoolfish spawn code
%patch $124C7 $55 $8B $EC $33 $C0 $50 $9A $06BD1E11RL $83 $C4 $02 $8B $1E
$D8 $A7 $C7 $07 [$0016W] $C7 $47 $02 [$0001W] $C7 $47 $06 [$0002W] #Sprite type = 22, activity = 1, clipping = 2
$C7 $47 $20 [$0000W] $8B $46 $06 $B1 $08 $D3 $E0 $89 $47 $0A $8B #Fore = 0
$46 $08 $D3 $E0 $89 $47 $0C $B8 [$0001W] $89 $47 $0E $89 $47 $10
$B8 [$3764W] $50 $53 $9A $09DC118CRL $83 $C4 $04 $5D $CB