From KeenWiki
Jump to navigation Jump to search

Licks are small teal beanbag-like enemies in Keen 4. This page covers patches relating to their behavior.

Sprite Type

Licks use type 18, which is used only by them. It does not affect anything.

Keen 4

#Lick sprite type
%patch $112DC $12

Sprite Actions

Lick actions are complex and interesting. Licks are spawned at ground level ready to jump after Keen. While in this state they will loop until they hit solid ground, which causes them to jump.

While falling Licks will loop two falling actions until they land. Near Keen they will flame, a series of actions that eventually lead to being ready to jump again.

$2FC6W #Lick fall 1
$2FE4W #Lick fall 2
$3002W #Lick ready to jump
$3020W #Lick landing/jumping
$303EW #Lick flaming 1
$305CW #Lick flaming 2
$307AW #Lick flaming 3
$3098W #Lick flaming 4
$30B6W #Lick flaming  5
$30D4W #Lick flaming 6
$30F2W #Lick flaming 7
$3110W #Lick done flaming
$312EW #Stunned Lick in air
$314CW #Stunned Lick

Keen 4

#Spawn Lick in-level
%patch $11334 [$3002W] #Ready to jump

#Falling Lick lands
%patch $1147F [$3020W] #Lick land

#Lick flame Keen
%patch $113B9 [$303EW] #Lick flaming

#Lick in air
%patch $31E52 [$2FE4W] #Lick fall
%patch $31EAC [$2FC6W] #Lick fall

#Lick jumping
%patch $31E70 [$3002W] #Ready to jump
%patch $31E8E [$0000W] #Wait

%patch $31ECA [$305CW] #Lick flaming 1
%patch $31EE8 [$307AW] #Lick flaming 2
%patch $31F06 [$3098W] #Lick flaming 3
%patch $31F24 [$30B6W] #Lick flaming 4
%patch $31F42 [$30D4W] #Lick flaming 5
%patch $31F60 [$30F2W] #Lick flaming 6
%patch $31F7E [$3110W] #Lick done flaming
%patch $31F9C [$3002W] #Lick done flaming, ready to jump

#Shot Lick
%patch $1140E [$312EW] #Lick shot

#Stunned Lick
%patch $31FBA [$314CW] #Stunned Lick in air (Stun when landing)
%patch $31FD8 [$0000W] #Do nothing

Sprite Behavior

The way the Lick's behaviors are set up is interesting. The only unique behavior the Lick has is its flaming behavior, which it can only use when it has just landed on the ground. While jumping it uses the same behavior shot sprites do, that is to move through the air under the influence of gravity.

$09DC16C9RL #Move through the air
$10800B42RL #Check for Keen and flame

Keen 4

#Falling Lick
%patch $31E46 $10800B42RL #Landed Lick, can flame Keen
%patch $31E64 $09DC16C9RL #Falling Lick

#Jumping Lick
%patch $31E82 $09DC16C9RL #Falling Lick
%patch $31EA0 $00000000L  #Animate

%patch $31EBE $00000000L  #Animate
%patch $31EDC $00000000L  #Animate
%patch $31EFA $00000000L  #Animate
%patch $31F18 $00000000L  #Animate
%patch $31F36 $00000000L  #Animate
%patch $31F54 $00000000L  #Animate
%patch $31F72 $00000000L  #Animate
%patch $31F90 $00000000L  #Animate

%patch $31FAE $09DC16C9RL #Shot sprite
%patch $31FCC $09DC16C9RL #Shot sprite

Movement code

This is the complete movement code used by Licks. It involves a number of checks to make sure Keen is close before it flames. If it does not flame, its horizontal and vertical speed are altered to make it jump.

The code is quite compact so careful consideration of it is beneficial. The second and third line allow the Lick to change direction and chase Keen. (The $FFFFW and $0000W).) The fourth and fifth line check if Keen is vertically level with Keen (No more than 1 tile above or below the lick, $FF00W-$0100W) If he isn't then a jump is made to the jump code.

The end of the fifth line checks if the lick is facing right ($01), if it is, it performs the 'facing right check' to see if Keen is within attack range. Keen must be between $FFE0W-$0180W (Half a tile left to 1.5 tiles right) of the Lick to be attackable. If not the game skips that check.

The sixth line checks if the lick is facing left ($FF) and if so performs the 'facing right check' (The two checks differ because of the Lick's long flame tongue.) If either of these checks are passed then sound 20 is played and the action is changed to $303EW in lines 7 and 8.

After this is the long jump code; it checks if Keen is further than 3 tiles away in either direction, and if so sets the speeds for a long jump ($05 across $FFE0 up) otherwise a short jump is set ($05 across divided by $02, and $FFF0 up.)

Keen 4

#Lick movement code
%patch $11342 $55 $8B $EC $83 $EC $02 $56 $57 $8B $76 $06 $8B $44 $0A $8B $1E #Check Keen's location
              $D6 $A7 $3B $47 $0A $76 $07 $C7 $44 $0E [$FFFFW]  $EB $05 $C7 $44 #Change H direction to follow him
              $0E [$0001W]  $8B $1E $A7D6W  $8B $47 $0A $2B $44 $0A $8B $F8 $8B
              $47 $0C $2B $44 $0C $89 $46 $FE $81 $7E $FE [$FF00W]  {$7C $40} $81 #Check if Keen <= 1 tile down, if no, go jumping
              $7E $FE [$0100W]  {$7F $39} $83 $7C $0E [$01] {$75 $0B} $83 [$E0FFW]  $7E #Check if Keen <= 1 tile up, if no, go jumping, perform right proximity check
              $06 $81 $FF [$0180W]  {$7C $11} $83 $7C $0E [$FF] {$75 $22} $83 $FF [$20] #Perform left proximity check
              {$7D $1D} $81 $FF [$FE00W] {$7E $17} $B8 [$0020W]  $50 $9A $187409F1RL  #Play sound $20
                  $83 $C4 $02 $C7 $44 $1C [$303EW]  $5F $5E $8B $E5 $5D $CB     #Change to flaming
                                                                          $8B #Jumping code
              $C7 $99 $33 $C2 $2B $C2 $3D [$0300W]  {$7E $15} $8B $44 $0E $B1 [$05] #Check if > 3 tiles from Keen in any direction
              $D3 $E0 $89 $44 $16 $C7 $44 $18 [$FFE0W]  $5F $5E $8B $E5 $5D $CB #If yes, large jump
              $8B $44 $0E $B1 [$05] $D3 $E0 $BB [$02] $00 $99 $F7 $FB $89 $44 $16 #Else small jump
              $C7 $44 $18 [$FFF0W]  $5F $5E $8B $E5 $5D $CB

Lick just harmlessly jumps about

This is a massively stripped down version of the Lick's movement code that results in it harmlessly chasing Keen, always using the long jump after him. Since it cannot flame it cannot hurt Keen (Unless its collision is set to deadly.) and it can be used by any other sprite (E.g. Bounders) without changing what that sprite is.

Keen 4

#Lick movement code less flame checks
%patch $11342 $55 $8B $EC $83 $EC $02 $56 $57 $8B $76 $06 $8B $44 $0A $8B $1E #Check Keen's location
              $D6 $A7 $3B $47 $0A $76 $07 $C7 $44 $0E [$FFFFW]  $EB $05 $C7 $44 #Change H direction to follow him
              $0E [$0001W]  $8B $44 $0E $B1 [$05] $D3 $E0 $89 $44 $16 $C7 $44 $18
              [$FFE0W]  $5F $5E $8B $E5 $5D $CB                                 #Large jump

Lick cannot flame

This quick and dirty patch stops the Lick flaming Keen, but this results in slightly unusual movement when the Lick is very close to the player. The above patch may be preferable in some circumstances. It is not compatible with the above patch.

Keen 4

#Lick doesn't ever flame Keen
%patch $113B6 $EB $03

Seeking Keen

There are three ways in which the Lick seeks Keen. The first is simply to bounce in his direction. The second variable determines how close the Lick can get before switching to more accurate short hops. The final set of variables determine when the Lick will attack Keen. This is divided into three parts. The first is the vertical distance (So the Lick doesn't try and flame Keen while jumping over his head.), the second is the horizontal distance so that the Lick's flame actually hits Keen and the third set of variables is how much 'recoil' the Lick suffers when flaming due to the fact that its flaming sprite is far wider than its jumping sprites.

All values are in 256ths of a pixel, so one pixel is $0100 and one tile is $1000.

Keen seeking

#Head towards Keen
%patch $1135C $FFFF
%patch $11363 $0001W

#How close horizontally to get before using short hops: 
%patch $113C9 $0300W #3 tiles or closer

#Flame Keen if he is this many tiles or closer vertically
%patch $1137D $FF00W #1 tile above
%patch $11384 $0100W #1 tile below
#Max and min distance to flame Keen in:
%patch $11395 $0180W #1.5 tiles right
%patch $113A6 $FF00W #2 tiles left
#Amount to move back when flaming
%patch $11390 $E0 #20 pixels left
%patch $113A1 $20 #20 pixels right

Speed and Jump Height

The Lick's animation motion controls nothing about its speed; all speeds are controlled in code. The two most important are the jump heights for the long and short hops. (See also the above section on when these two different hops are used.) The jump widths are more tricky, the maximum width is $0F and the short hop's value is divided by a second number. (If this is 1 then the hops are the same width.)

Finally the Lick jumps into the air slightly when shot.

Jump height

#Jump heights
%patch $113DA $FFE0W #Long
%patch $113F5 $FFF0W #Short

#Jump widths
%patch $113D1 $05    #Long
%patch $113D1 $05    #Short
%patch $113EA $02     #Short hop length divided by...

#Jump this much when shot
%patch $1141E $10

Animation motion

%patch $31E42 [$0000W $0000W]
%patch $31E9C [$0000W $0000W]

#Ready to jump and in air
%patch $31E60 [$0000W $0000W]
%patch $31E7E [$0000W $0000W]

%patch $31EBA [$0000W $0000W]
%patch $31ED8 [$0000W $0000W]
%patch $31EF6 [$0000W $0000W]
%patch $31F14 [$0000W $0000W]
%patch $31F32 [$0000W $0000W]
%patch $31F50 [$0000W $0000W]
%patch $31F6E [$0000W $0000W]
%patch $31F8C [$0000W $0000W]

%patch $31FAA [$0000W $0000W]
%patch $31FC8 [$0000W $0000W]

Sprite collision

The Lick has, in theory, two different collision codes. The first is for when it is not flaming Keen, when it can be shot but is harmless. The second is for when it is attacking, when it is vulnerable, but also lethal to Keen. However these two collisions are in reality one; these two different collisions are inseparably entwined.

Collision values

When the Lick is harmless it uses its first collision, reacting only to Keen's shots. However when it is dangerous it uses its second collision, which detects if Keen is touching the Lick's flame area before killing him, and also goes tot he first collision to check if Keen is shooting it.

Keen 4

#In air
%patch $31E4A $10800BFDRL #Lick bouncing
%patch $31E68 $10800BFDRL #Lick bouncing

#Landing and ready to jump
%patch $31E86 $10800BFDRL #Lick bouncing
%patch $31EA4 $10800BFDRL #Lick bouncing

%patch $31EC2 $10800C23RL #Lick flaming
%patch $31EE0 $10800C23RL #Lick flaming
%patch $31EFE $10800C23RL #Lick flaming
%patch $31F1C $10800C23RL #Lick flaming
%patch $31F3A $10800C23RL #Lick flaming
%patch $31F58 $10800C23RL #Lick flaming
%patch $31F76 $10800C23RL #Lick flaming
%patch $31F94 $10800C23RL #Lick flaming

%patch $31FB2 $00000000L #No collision (In air)
%patch $31FD0 $00000000L #No collision (On ground)

Collision code

As noted above, the two different Lick collisions are combined. To save space the second 'dangerous to Keen' collision refers to the first when the Lick is shot. This saves the duplication of shot Lick code in the two collisions.

Keen 4

#Lick collision code 1: contains shot Lick code
%patch $113FD $55 $8B $EC $56 $57 $8B $76 $06 $8B $7E $08 $83 $3D [$03] {$75 $12}
              $B8 [$312EW]  $50 $57 $56 $9A $09DC1695RL     $83 $C4 $06 $83 $6C
              $18 $10 $5F $5E $5D $CB

#Lick collision code 2: reacts to Keen and refers to above code
                                      $55 $8B $EC $56 $57 $8B $76 $06 $8B $7E
              $08 $83 $3D [$02] {$75 $31} $83 $7C $0E $01 $75 $0C $8B $1E $A7D6W 
              $8B $47 $0A $3B $44 $0A $77 $12 $83 $7C $0E $FF $75 $22 $8B $1E
              $D6 $A7 $8B $47 $0A $3B $44 $0A $73 $16 $9A $0B8013E9RL     $5F
              $5E $5D $CB $5F $5E $5D $CB $57 $56 $0E $E8 $FF93W  $83 $C4 $04 #Refer to above code here
              $5F $5E $5D $CB

Lick is deadly all the time

This patch makes it so that contact with the Lick or its flame is lethal to Keen, even when the Lick is not flaming. It works by removing the special detection limits in the flaming Lick's collision (That make sure Keen can touch the Lick, but not its flame.) and then making even the 'harmless' Lick use this collision. Removing the last four lines will simply make the Lick deadly all over when it flames Keen.

Keen 4

#Lick is deadly all the time, new collision
%patch $11423 $55 $8B $EC $56 $57 $8B $76 $06 $8B $7E $08 $83 $3D $02 $75 $09 #Check for Keen (Type 2)
              $9A $0B8013E9RL     $5F $5E $5D $CB $83 $3D $03 $75 $12
              $B8 $312EW  $50 $57 $56 $9A $09DC1695RL     $83 $C4 $06 $83 $6C
              $18 $10 $5F $5E $5D $CB

#Bouncing Lick uses this too
%patch $31E4A $10800C23RL #Lick bouncing
%patch $31E68 $10800C23RL #Lick bouncing
%patch $31E86 $10800C23RL #Lick bouncing
%patch $31EA4 $10800C23RL #Lick bouncing


The Lick's animations are quite simple; it has two animations when jumping, another two when falling through the air, and a series of eight when flaming Keen. All of these behave logically, with interesting applications of the animation time. Animation time controls a number of variables, such as how long in total the Lick will spend flaming Keen, or sitting on the ground before jumping again.

Lick animations

%patch $30702 [$01D5W] #Lick Cache start
%patch $3074C [$01E3W] #Lick cache end

#In air
%patch $31E36 $01D9W $01D5W #Fall
%patch $31E40 $000AW        #Reaction speed
%patch $31E54 $01DAW $01D6W #Land
%patch $31E5E $0000W        #Wait to fall

%patch $31E72 $01DBW $01D7W #Fall
%patch $31E7C $0000W        #Wait to jump
%patch $31E90 $01DCW $01D8W #Land
%patch $31E9A $000AW        #Land time (Then sit)

%patch $31EAE $01E0W $01DDW
%patch $31EB8 $0004W        #Animation speed
%patch $31ECC $01E1W $01DEW
%patch $31ED6 $0004W        #Animation speed
%patch $31EEA $01E2W $01DFW
%patch $31EF4 $0004W        #Animation speed
%patch $31F08 $01E1W $01DEW
%patch $31F12 $0004W        #Animation speed
%patch $31F26 $01E0W $01DDW
%patch $31F30 $0004W        #Animation speed
%patch $31F44 $01E1W $01DEW
%patch $31F4E $0004W        #Animation speed

#Lick done flaming
%patch $31F62 $01E2W $01DFW
%patch $31F6C $0004W        #Animation speed
%patch $31F80 $01E1W $01DEW
%patch $31F8A $0004W        #Animation speed

#Stunned in air
%patch $31F9E $01E3W $01E3W
%patch $31FA8 $0000W        #Wait to hit ground

#Stunned on ground
%patch $31FBC $01E3W $01E3W
%patch $31FC6 $0000W        #Animation speed


The Lick makes a sound when flaming, this sound can be blocked.

Keen 4

#Lick flames sound
%patch $113AB [$20]

#Don't play sound when Lick flames
%patch $113AA $EB $0A

Clipping and foreground

The Lick has a foreground variable of 2, putting it in front of Keen at all times, which looks good when it flames him.

Keen 4

#Lick Foreground variable
%patch $112E6 $0002W

Sprite-tile interaction

The Lick has a number of interesting tile collisions, related closely to its behavior since it uses them to jump. The most usual are the ones used when flaming (Just sit.) and when stunned (Hit ground and be stunned.) A custom collision exists for the first falling action as well as the second (the difference is not yet known.) as well as its jump start action and its in air\falling action.

Keen 4

%patch $31E4E $09DC176ERL #Fall 1
%patch $31E6C $10800C71RL #Fall 2
%patch $31E8A $10800C71RL #Starting jump
%patch $31EA8 $09DC176ERL #In air\falling

%patch $31EC6 $09DC176ERL #Flaming
%patch $31EE4 $09DC176ERL #Flaming
%patch $31F02 $09DC176ERL #Flaming
%patch $31F20 $09DC176ERL #Flaming
%patch $31F3E $09DC176ERL #Flaming
%patch $31F5C $09DC176ERL #Flaming
%patch $31F7A $09DC176ERL #Flaming
%patch $31F98 $09DC176ERL #Done flaming

%patch $31FB6 $09DC1913RL #Shot
%patch $31FD4 $09DC1913RL #Stunned

Action type

The Lick's action types can seem complex. When using its first in air action it is type 0 as it is not moving. When using the second action it is type 2, the same as stunned sprites that must move through the air. This is also used when the Lick is starting to jump, but again type 2 is used for the actual jumping. Type 0 is used when flaming as the Lick is sitting still and type 2 is used for both stunned actions as expected.

Keen 4

#In air
%patch $31E3A [$0000W]
%patch $31E94 [$0002W]

%patch $31E58 [$0002W]
%patch $31E76 [$0000W]

%patch $31EB2 [$0000W]
%patch $31ED0 [$0000W]
%patch $31EEE [$0000W]
%patch $31F0C [$0000W]
%patch $31F2A [$0000W]
%patch $31F48 [$0000W]
%patch $31F66 [$0000W]
%patch $31F84 [$0000W]

#Stunned in air
%patch $31FA2 [$0002W]

#Stunned on ground
%patch $31FC0 [$0002W]

Deprotect and stick to ground

The Lick is interesting in that it actually uses the deprotect-animation variable in some of its flaming frames. This is used to improve the look of the flaming Lick. Since it doesn't walk down slopes the Lick does not need to use the stick-to-ground parameter.

Keen 4

#In air
%patch $31E3C [$0000W $0000W]
%patch $31E5A [$0000W $0000W]

%patch $31E78 [$0000W $0000W]
%patch $31E96 [$0000W $0000W]
%patch $31EB4 [$0001W $0000W]
%patch $31ED2 [$0001W $0000W]
%patch $31EF0 [$0001W $0000W]
%patch $31F0E [$0001W $0000W]
%patch $31F2C [$0001W $0000W]
%patch $31F4A [$0001W $0000W]
%patch $31F68 [$0001W $0000W]
%patch $31F86 [$0001W $0000W]

#Stunned in air
%patch $31FA4 [$0000W $0000W]

#Stunned on ground
%patch $31FC2 [$0000W $0000W]

Probability and randomness

The Lick has a 50:50 chance of spawning facing left or right. This has little effect however as it immediately turns to chase Keen.

Keen 4

#Initial movement direction probability
%patch $11300 $80

Sprite spawn code

In the initiation code notice the two difficulty checks (Allowing three difficulty appearances.) and the Lick cache being set ($C7 $06 $CB6DW $0001W.)

The last blue highlighted value is the sprite action the sprite uses as it proceeds to act in-level. $C7 $02 $xxxxW sets the sprite activity $C7 $07 $xxxxW sets the sprite type, $C7 $20 $xxxxW sets the foreground value.

$C7 $47 $0E $xxxxW is the horizontal direction the sprite starts moving in, either $0001W (Facing right), $FFFFW (Facing left) or $0000W (Neither, never used.) $C7 $47 $10 $xxxxW is the vertical direction and works similarly. The Lick has a probability check to determine which way they face this is always 50:50 (Though it needn't be.) and the code responsible for this is $9A $1D02002ARL $3D $0080W

Keen 4

#Location of initiation code
%patch $EE9F [$0240W] #Easy Lick (At $EB30)
%patch $EEE1 [$0236W] #Medium Lick (At $EB26)
%patch $EEE3 [$022CW] #Hard Lick (At $EB1C)

#Lick Initiation code
%patch $EB1C $83 $3E [$7A6CW]  {$03 $7D} $03 $E9 $02D7W  $83 $3E [$7A6CW]  {$02 $7D}
             $03 $E9 $02CDW  $FF $76 $FC $57 $9A {$10800AC8RL}     $83 $C4 $04
             $C7 $06 $CB6DW  $0001W  $E9 $02B8W

#Lick spawn code
%patch $112C8 $55 $8B $EC $33 $C0 $50 $9A $06BD1E11RL     $83 $C4 $02 $8B $1E
              $D8 $A7 $C7 $07 [$0012W]  $C7 $47 $02 [$0001W]  $C7 $47 $20 [$0002W]
              $8B $46 $06 $B1 $08 $D3 $E0 $89 $47 $0A $8B $46 $08 $D3 $E0 $89
              $47 $0C $9A $1D02002ARL     $3D [$0080W]  {$7D} $0B $8B $1E $D8 $A7
              $C7 $47 $0E [$0001W]  $EB $09 $8B $1E $D8 $A7 $C7 $47 $0E [$FFFFW]
              $8B $1E $D8 $A7 $C7 $47 $10 [$0001W]  $9A $1D02002ARL     $BB $0040W
                  $99 $F7 $FB $8B $1E $D8 $A7 $89 $47 $08 $B8 [$3002W]  $50 $53
              $9A $09DC118CRL     $83 $C4 $04 $5D $CB