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
3.1. Modifying the overworld functionality for Headbutting
3.2. Adding the tree item code
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.
3. Headbutting trees for items too!
This may not be for everyone, but it is possible to do the same thing for Headbutting trees. It can be a fun way to distribute other items aside from smashing rocks.
3.1. Modifying the overworld functionality for Headbutting
We're doing the same thing here as rock smash. Let's edit the HeadbuttScript in engine/events/overworld.asm
callasm GetPartyNickname
writetext UseHeadbuttText
reloadmappart
callasm ShakeHeadbuttTree
callasm TreeMonEncounter
- iffalse .no_battle
+ iffalse .try_tree_item
closetext
randomwildmon
startbattle
reloadmapafterbattle
end
+
+.try_tree_item
+ callasm TreeItemEncounter
+ iffalse .no_battle
+ opentext
+ verbosegiveitem ITEM_FROM_MEM
+ closetext
+ end
+
.no_battle
writetext HeadbuttNothingText
waitbutton
closetext
end
3.2. Adding the tree item code
We're going to add this next part right under where we added RockItemEncounter
in engine/events/checkforhiddenitems.asm. For the purposes of this tutorial our list will have all the apricorns, the silver leaf, and the gold leaf. This will make it possible to harvest more apricorns without having to wait 24hrs for the bushes to respawn. Of course you can use any items you want (such as berries), and you can decide how rare or common each item will be.
+TreeItemEncounter:
+ ld hl, .TreeItems
+ 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
+
+.TreeItems:
+ db 1, BLK_APRICORN
+ db 2, PNK_APRICORN
+ db 4, YLW_APRICORN
+ db 6, WHT_APRICORN
+ db 12, RED_APRICORN
+ db 18, BLU_APRICORN
+ db 24, GRN_APRICORN
+ db 24, SILVER_LEAF
+ db 48, GOLD_LEAF
+ db 64, GOLD_LEAF
+ db -1
And that's it! Headbutting trees will have a chance to give the player an item from the list, just like smashing rocks.