Smashing rocks has a chance to contain items - pret/pokecrystal GitHub Wiki
In HGSS, XY and ORAS, it is possible to use Rock Smash and instead of encountering a Pokémon (or nothing...), you could also find an item from a small table of potential item drops.
This tutorial will go over how to achieve that functionality in pokecrystal. (This feature was adapted from Polished Crystal: huge thanks to Rangi!)
Contents
1. Modifying the overworld functionality
First, we must edit the RockSmashScript
within engine/events/overworld.asm:
callasm RockMonEncounter
readmem wTempWildMonSpecies
- iffalse .done
+ iffalse .no_battle
randomwildmon
startbattle
reloadmapafterbattle
-.done
end
+.no_battle
+ callasm RockItemEncounter
+ iffalse .no_item
+ opentext
+ verbosegiveitem ITEM_FROM_MEM
+ closetext
+.no_item
+ end
These changes stop the RockSmashScript
from ending if it doesn't find a Pokémon, jumping to .no_battle
in that case, and then calling RockItemEncounter
to determine whether or not an item will be found under the rock. If no item is selected, the script will jump to .no_item
, ending the script and giving the player nothing.
But RockItemEncounter
has yet to be defined, so these changes on their own will not work.
2. Adding the rock item code
We have to define RockItemEncounter
, and a suitable place to put it would be in engine/events/checkforhiddenitems.asm at the bottom of the script:
.GetFarByte:
ld a, [wBuffer1]
call GetFarByte
inc hl
ret
+
+RockItemEncounter:
+ ld hl, .RockItems
+ call Random
+.loop
+ sub [hl]
+ jr c, .ok
+ inc hl
+ inc hl
+ jr .loop
+
+.ok
+ ld a, [hli]
+ inc a
+ jr z, .done
+ ld a, [hli]
+.done
+ ld [wScriptVar], a
+ ret
+
+.RockItems:
+ db 1, MAX_REVIVE
+ db 2, THICK_CLUB
+ db 4, NUGGET
+ db 6, STAR_PIECE
+ db 12, BIG_PEARL
+ db 18, ETHER
+ db 24, HARD_STONE
+ db 24, SOFT_SAND
+ db 48, PEARL
+ db 64, BRICK_PIECE
+ db -1
For starters, RockItemEncounter
will load the .RockItems
table into hl
, and then call Random
, which will load a random byte (i.e., a value between 0 and 255) in a
. With this random value generated, it performs comparisons against the probabilities encoded in the .RockItems
table, picking an item with the listed odds (out of 256: in the example, there's a 1 in 256 chance of getting a Max Revive, and a 64 in 256 (or 1 in 4) chance of getting a Brick Piece).
Since the probabilities in the table add up to less than 256, the db -1
line at the end indicates the end of the table. If this line is reached, the function will load a 0 (which represents NO_ITEM
), indicating that the rocks didn't contain an item. If this is the case, the iffalse .no_item
line in the script will skip giving an item to the player. Otherwise, the selected item, which will have already been loaded into the script variable (wScriptVar
) by the function, will be awarded to the player by the script.
And there you have it, the player can now find items within smashed rocks! You can add your own items and chances by editing the .RockItems
table in checkhiddenitems.asm
, or even add something more complex like the Fossils/Old Amber from RBY.
Note that the probabilities can only add up to 256 or less. (If they add up to 256 exactly, the final db -1
is not needed, but it can be left in place just in case.) If they add up to more than 256, the last entries in the table will be inaccessible.