From KeenWiki
Jump to navigation Jump to search

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.

$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.)

$11A20AF6RL #Seek Keen 

Keen 4

%patch $325E4 $11A20AF6RL #Seek Keen 
%patch $32602 $11A20AF6RL #Seek Keen

%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

%patch $3250E [$0000W $0000W]

%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

%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

%patch $325E8 $00000000L #No collision
%patch $32606 $00000000L #No collision

%patch $32516 $00000000L #No collision


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

%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

%patch $325EC $11A20A3CRL
%patch $3260A $11A20A3CRL

%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]

%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

%patch $325DA [$0000W $0000W]
%patch $325F8 [$0000W $0000W]

%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