1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
Since Gen 5, the current weather gets displayed during battles on the bottom screen. This tutorial will explain how to do so in Gen 2, more specifically, during move selection. It works by creating a sprite for the weather icon, so you'll also learn how to work with sprite graphics on the Game Boy Color.
## Add the code to display the sprites
Edit [engine/battle/core.asm](../blob/master/engine/battle/core.asm)
```diff
BattleTurn:
...
.skip_iteration
call ParsePlayerAction
+ push af
+ call ClearSprites
+ pop af
jr nz, .loop1
```
```diff
MoveSelectionScreen:
...
.battle_player_moves
call MoveInfoBox
+ call GetWeatherImage
ld a, [wMoveSwapBuffer]
...
.place_textbox_start_over
+ push hl
+ call ClearSprites
+ pop hl
call StdBattleTextbox
```
There's not much to explain here. These changes are just to clear the sprite when we dont need it and to add the call function to the code below.
Add this function to [engine/battle/core.asm](../blob/master/engine/battle/core.asm)
```
GetWeatherImage:
ld a, [wBattleWeather]
and a
ret z
cp WEATHER_RAIN
ld de, RainWeatherImage
lb bc, PAL_BATTLE_OB_BLUE, 4
jr z, .done
cp WEATHER_SUN
ld de, SunWeatherImage
ld b, PAL_BATTLE_OB_YELLOW
jr z, .done
cp WEATHER_SANDSTORM
ld de, SandstormWeatherImage
ld b, PAL_BATTLE_OB_BROWN
jr z, .done
ret
.done
push bc
ld b, BANK(WeatherImages) ; c = 4
ld hl, vTiles0
call Request2bpp
pop bc
ld hl, wVirtualOAMSprite00
ld de, .WeatherImageOAMData
.loop
ld a, [de]
inc de
ld [hli], a
ld a, [de]
inc de
ld [hli], a
dec c
ld a, c
ld [hli], a
ld a, b
ld [hli], a
jr nz, .loop
ret
.WeatherImageOAMData
; positions are backwards since
; we load them in reverse order
db $88, $1c ; y/x - bottom right
db $88, $14 ; y/x - bottom left
db $80, $1c ; y/x - top right
db $80, $14 ; y/x - top left
```
Request2bpp is an important function. It grabs the image from ROM and places it where you want, usually VRAM. The description of it is kind of weird, but basically `b` is the bank that the image resides, `de` is the address that the image resides, `hl` is where you want to copy it to, and `c` is how many tiles to copy.
If you're wanting to make an image a sprite, `wVirtualOAM` is where you want to go. You don't want to write directly to OAM because that would require specific timings that wouldn't be available all of the time. So, you must load the OAM data into `wVirtualOAM`. Every so often, many times per second actually, the game loads whatever is in `wVirtualOAM` into the actual OAM, when those timings I mentioned are available.
OAM data works like this, each sprite is an 8x8 tile just like the background or map tiles, but they can be put anywhere on the screen. Each sprite uses 4 bytes in this order, Y position, X position, Tile number, Attributes. Look [here](http://gbdev.gg8.se/wiki/articles/Video_Display#VRAM_Sprite_Attribute_Table_.28OAM.29) for a better description of the OAM structure.
## Add the graphics
Add these graphics to gfx/battle/weather

```
SECTION "Battle Weather Images", ROMX
INCLUDE "gfx/weather_images.asm"
```
RGBDS will add this section to any free space in a bank unless you add `"Battle WeatherImages"` to [pokecrystal.link](../blob/master/pokecrystal.link).
## Optimize the code
Now, if you plan on not adding any new weather effects or weather icons, optimization is straightforward. Otherwise, there's some tricks you can use to keep the code optimized.
A quick and easy optimzation is to replace the `cp WEATHER_X` in GetWeatherImage to `dec a` like so.
```diff
GetWeatherImage:
ld a, [wBattleWeather]
and a
ret z
- cp WEATHER_RAIN
+ dec a
ld de, RainWeatherImage
lb bc, PAL_BATTLE_OB_BLUE, 4
jr z, .done
- cp WEATHER_SUN
+ dec a
ld de, SunWeatherImage
ld b, PAL_BATTLE_OB_YELLOW
jr z, .done
- cp WEATHER_SANDSTORM
+ dec a
ld de, SandstormWeatherImage
ld b, PAL_BATTLE_OB_BROWN
jr z, .done
ret
```
You can do that because WEATHER_RAIN = 0 + 1, WEATHER_SUN = WEATHER_RAIN + 1, and WEATHER_SANDSTORM = WEATHER_SUN + 1.
That format can be continued to be used if whatever new weather effects equal one more than the last.
## Addendum
Here is a pre-made graphic for Hail made by Bronzeswagger if you decide to add Hail to your hack.

|