Stick and Lucky Punch are sad in gen 2
Stick (renamed to Leek in newer gens) and Lucky Punch are held items that apply their effects exclusively to Farfetch'd and Chansey respectively.
Their effect is to raise by 2 the critical stage, an hidden statistic that determines the likelihood of a Pokémon to perform a critical hit.
However, in generation 2, they have a slightly different effect: they set the critical stage to 2 and ignore all other effects.
This is never beneficial, and it's in fact detrimental most of the time. The Scope item combined with a move with high critical ratio reaches crit stage 3 and stage 4 can be reached with Focus Energy or Dire Hit: in all those cases the crit stage will be 2 with a Stick or a Lucky Punch.
The code
Let's take a look at the code in the disassembly to see how critical hits are determined in generation 2.
The code that interests us is under the label BattleCommand_Critical in engine/battle/effect_commands.asm.
Let's comment it piece by piece:
BattleCommand_Critical:
; Determine whether this attack's hit will be critical.
We start by setting wCriticalHit to 0, meaning that by default the current attack is not a critical.
xor a
ld [wCriticalHit], a
Then we check if the current move has a base power greater than 0 (which would mean it's an attacking move): if not the attack can't be a critical and we return.
ld a, BATTLE_VARS_MOVE_POWER
call GetBattleVar
and a
ret z
Next we do the usual turn check with hBattleTurn and we load the address to the held item in hl and the Pokémon species in a.
ldh a, [hBattleTurn]
and a
ld hl, wEnemyMonItem
ld a, [wEnemyMonSpecies]
jr nz, .Item
ld hl, wBattleMonItem
ld a, [wBattleMonSpecies]
Now that we have the values we need we can start checking for any bonuses, but first we set c, which contains our critical stage, to 0.
.Item:
ld c, 0
First we check if the current Pokémon is Chansey. If it's not we skip directly to the Farfetch'd check, if it is we check if the current item is Lucky Punch.
If the item is not the Lucky Punch we skip over the Farfetch'd check and directly to Focus Energy (which is correct, as we have already established that the Pokémon is Chansey), if it is we load 2 in c and immediately skip to the tally, which determines the crit chance based on c, skipping everything in between.
cp CHANSEY
jr nz, .Farfetchd
ld a, [hl]
cp LUCKY_PUNCH
jr nz, .FocusEnergy
; +2 critical level
ld c, 2
jr .Tally
Farfetch'd's (that was fun to write) check works the same as Chansey's just with different values for the species and item.
.Farfetchd:
cp FARFETCH_D
jr nz, .FocusEnergy
ld a, [hl]
cp STICK
jr nz, .FocusEnergy
; +2 critical level
ld c, 2
jr .Tally
The Focus Energy check raises c by 1 if Focus Energy is active, but this time it doesn't skip anything.
.FocusEnergy:
ld a, BATTLE_VARS_SUBSTATUS4
call GetBattleVar
bit SUBSTATUS_FOCUS_ENERGY, a
jr z, .CheckCritical
; +1 critical level
inc c
The next check is for the move: if the current move is in the list at data/moves/critical_hit_moves.asm the critical stage is raised by 2.
.CheckCritical:
ld a, BATTLE_VARS_MOVE_ANIM
call GetBattleVar
ld de, 1
ld hl, CriticalHitMoves
push bc
call IsInArray
pop bc
jr nc, .ScopeLens
; +2 critical level
inc c
inc c
Once again we check the user item, if it's a Scope Lens we raise the stage by 1. Note that here we jump to the tally if the item is not a Scope Lens, but this time no code is skipped, because this is the last check.
.ScopeLens:
push bc
call GetUserItem
ld a, b
cp HELD_CRITICAL_UP ; Increased critical chance. Only Scope Lens has this.
pop bc
jr nz, .Tally
; +1 critical level
inc c
All the code between the Farfetch'd check and this point is skipped completely if Stick's or Lucky Punch's effects are active.
Now it's time to determine the probability: the table is at data/battle/critical_hit_chances.asm: we simply add c bytes to the CriticalHitChances address, obtaining the address of the byte that encodes the probability out of 255.
.Tally:
ld hl, CriticalHitChances
ld b, 0
add hl, bc
call BattleRandom
cp [hl]
ret nc
ld a, 1
ld [wCriticalHit], a
ret
Speculation and fix
I'm not sure why these items are coded like this, it might be an oversight: maybe they moved some code around or they added the other checks later in development and forgot to update the jrs.
Maybe it was intended, it's hard to know with no information.
Fixing this is really simple, you just need to update the jrs to go to the Focus Energy check instead of to the tally, like this:
cp CHANSEY
jr nz, .Farfetchd
ld a, [hl]
cp LUCKY_PUNCH
jr nz, .FocusEnergy
; +2 critical level
ld c, 2
- jr .Tally
+ jr .FocusEnergy
.Farfetchd:
cp FARFETCH_D
jr nz, .FocusEnergy
ld a, [hl]
cp STICK
jr nz, .FocusEnergy
; +2 critical level
ld c, 2
- jr .Tally
Conclusion
If you decide to use Chansey or Farfetch'd in generation 2, use these items only if you plan to not use moves with high critical ratio, if you do (and are fine with farming Mystery Gift) the Scope Lens has a better effect.