Merge branch 'RHH/upcoming' into RHH/pr/feature/formBattleChange
# Conflicts: # src/data/pokemon/form_change_table_pointers.h # src/data/pokemon/form_change_tables.h
@ -420,6 +420,29 @@ gBattleScriptsForMoveEffects::
|
||||
.4byte BattleScript_EffectShellTrap @ EFFECT_SHELL_TRAP
|
||||
.4byte BattleScript_EffectHit @ EFFECT_PSYBLADE
|
||||
.4byte BattleScript_EffectHit @ EFFECT_HYDRO_STEAM
|
||||
.4byte BattleScript_EffectHitSetEntryHazard @ EFFECT_HIT_SET_ENTRY_HAZARD
|
||||
.4byte BattleScript_EffectDireClaw @ EFFECT_DIRE_CLAW
|
||||
.4byte BattleScript_EffectBarbBarrage @ EFFECT_BARB_BARRAGE
|
||||
|
||||
BattleScript_StealthRockActivates::
|
||||
setstealthrock BattleScript_MoveEnd
|
||||
printfromtable gDmgHazardsStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectDireClaw::
|
||||
setmoveeffect MOVE_EFFECT_DIRE_CLAW
|
||||
goto BattleScript_EffectHit
|
||||
|
||||
BattleScript_EffectHitSetEntryHazard::
|
||||
argumenttomoveeffect
|
||||
goto BattleScript_EffectHit
|
||||
|
||||
BattleScript_SpikesActivates::
|
||||
trysetspikes BattleScript_MoveEnd
|
||||
printfromtable gDmgHazardsStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectAttackUpUserAlly:
|
||||
jumpifnoally BS_ATTACKER, BattleScript_EffectAttackUp
|
||||
@ -3372,6 +3395,7 @@ BattleScript_CantMakeAsleep::
|
||||
orhalfword gMoveResultFlags, MOVE_RESULT_FAILED
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectBarbBarrage:
|
||||
BattleScript_EffectPoisonHit:
|
||||
setmoveeffect MOVE_EFFECT_POISON
|
||||
goto BattleScript_EffectHit
|
||||
@ -8627,6 +8651,7 @@ BattleScript_IntimidateActivates::
|
||||
BattleScript_IntimidateLoop:
|
||||
jumpifbyteequal gBattlerTarget, gBattlerAttacker, BattleScript_IntimidateLoopIncrement
|
||||
jumpiftargetally BattleScript_IntimidateLoopIncrement
|
||||
jumpifabsent BS_TARGET, BattleScript_IntimidateLoopIncrement
|
||||
jumpifstatus2 BS_TARGET, STATUS2_SUBSTITUTE, BattleScript_IntimidateLoopIncrement
|
||||
jumpifholdeffect BS_TARGET, HOLD_EFFECT_CLEAR_AMULET, BattleScript_IntimidatePrevented_Item
|
||||
jumpifability BS_TARGET, ABILITY_CLEAR_BODY, BattleScript_IntimidatePrevented
|
||||
@ -8654,6 +8679,7 @@ BattleScript_IntimidateLoopIncrement:
|
||||
addbyte gBattlerTarget, 1
|
||||
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_IntimidateLoop
|
||||
BattleScript_IntimidateEnd:
|
||||
copybyte sBATTLER, gBattlerAttacker
|
||||
destroyabilitypopup
|
||||
pause B_WAIT_TIME_MED
|
||||
end3
|
||||
|
19
graphics/items/icon_palettes/ability_shield.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
255 255 255
|
||||
248 200 240
|
||||
224 176 232
|
||||
200 144 224
|
||||
240 224 248
|
||||
176 120 216
|
||||
77 146 186
|
||||
105 179 221
|
||||
238 246 246
|
||||
222 222 222
|
||||
197 197 197
|
||||
161 161 161
|
||||
48 48 48
|
||||
255 255 255
|
||||
0 0 0
|
19
graphics/items/icon_palettes/adamant_crystal.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
255 255 255
|
||||
184 208 248
|
||||
168 200 248
|
||||
81 123 173
|
||||
128 168 216
|
||||
200 232 248
|
||||
224 248 248
|
||||
248 248 248
|
||||
104 104 104
|
||||
48 48 48
|
||||
255 255 255
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
19
graphics/items/icon_palettes/auspicious_armor.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
255 255 255
|
||||
160 144 32
|
||||
192 176 56
|
||||
224 208 88
|
||||
128 112 32
|
||||
72 56 24
|
||||
224 80 80
|
||||
176 88 88
|
||||
120 72 72
|
||||
48 48 48
|
||||
255 255 255
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
19
graphics/items/icon_palettes/big_bamboo_shoot.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
0 0 0
|
||||
189 202 71
|
||||
121 168 43
|
||||
120 167 42
|
||||
163 126 74
|
||||
116 101 78
|
||||
79 66 46
|
||||
115 77 43
|
||||
180 133 94
|
||||
233 176 96
|
||||
241 241 193
|
||||
183 170 147
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
19
graphics/items/icon_palettes/booster_energy.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
111 45 22
|
||||
0 0 0
|
||||
190 91 13
|
||||
255 139 1
|
||||
255 255 255
|
||||
255 231 10
|
||||
251 42 6
|
||||
154 157 151
|
||||
193 161 19
|
||||
234 238 234
|
||||
122 111 115
|
||||
74 67 68
|
||||
90 185 248
|
||||
78 86 255
|
||||
111 52 255
|
19
graphics/items/icon_palettes/covert_cloak.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
0 0 0
|
||||
54 52 72
|
||||
101 120 143
|
||||
103 139 163
|
||||
84 105 130
|
||||
74 75 101
|
||||
90 108 136
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
19
graphics/items/icon_palettes/gimmighoul_coin.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
180 124 35
|
||||
115 66 13
|
||||
255 249 234
|
||||
224 159 27
|
||||
255 226 121
|
||||
255 200 59
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
19
graphics/items/icon_palettes/griseous_core.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
255 255 255
|
||||
206 181 41
|
||||
222 198 57
|
||||
247 231 140
|
||||
156 132 33
|
||||
189 156 41
|
||||
123 99 33
|
||||
49 49 49
|
||||
255 255 255
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
19
graphics/items/icon_palettes/leaders_crest.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
0 0 0
|
||||
188 143 70
|
||||
131 85 43
|
||||
186 181 176
|
||||
80 74 71
|
||||
239 185 78
|
||||
138 128 128
|
||||
220 217 215
|
||||
250 225 159
|
||||
246 205 93
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
19
graphics/items/icon_palettes/loaded_dice.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
48 52 78
|
||||
127 216 17
|
||||
0 0 0
|
||||
192 240 140
|
||||
128 217 18
|
||||
90 137 46
|
||||
129 218 19
|
||||
88 135 48
|
||||
107 182 17
|
||||
128 217 18
|
||||
93 144 44
|
||||
89 136 47
|
||||
255 255 255
|
||||
127 216 19
|
||||
48 38 64
|
19
graphics/items/icon_palettes/lustrous_globe.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
255 255 255
|
||||
248 216 232
|
||||
198 159 217
|
||||
210 171 229
|
||||
224 192 240
|
||||
210 192 240
|
||||
160 192 232
|
||||
144 200 232
|
||||
160 216 240
|
||||
128 216 224
|
||||
208 240 240
|
||||
248 240 240
|
||||
248 248 248
|
||||
80 80 80
|
||||
48 48 48
|
19
graphics/items/icon_palettes/malicious_armor.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
255 255 255
|
||||
66 66 99
|
||||
90 90 132
|
||||
115 115 156
|
||||
90 115 230
|
||||
132 140 181
|
||||
125 147 246
|
||||
48 48 48
|
||||
255 255 255
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
19
graphics/items/icon_palettes/mirror_herb.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
0 0 0
|
||||
39 194 168
|
||||
124 228 211
|
||||
19 101 84
|
||||
187 228 77
|
||||
238 250 169
|
||||
234 244 124
|
||||
24 152 108
|
||||
126 106 28
|
||||
173 171 15
|
||||
43 138 128
|
||||
127 175 55
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
19
graphics/items/icon_palettes/punching_glove.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
255 255 255
|
||||
255 212 0
|
||||
200 56 32
|
||||
248 64 48
|
||||
232 232 232
|
||||
48 48 48
|
||||
255 255 255
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
19
graphics/items/icon_palettes/scroll_of_darkness.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
0 0 0
|
||||
130 116 116
|
||||
86 86 86
|
||||
54 41 49
|
||||
104 78 86
|
||||
56 56 56
|
||||
141 105 41
|
||||
223 191 65
|
||||
242 241 242
|
||||
184 172 179
|
||||
186 140 57
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
19
graphics/items/icon_palettes/scroll_of_waters.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
0 0 0
|
||||
118 109 109
|
||||
143 130 127
|
||||
101 77 83
|
||||
73 68 68
|
||||
122 108 104
|
||||
141 105 41
|
||||
223 191 65
|
||||
242 241 242
|
||||
184 172 179
|
||||
186 140 57
|
||||
102 78 84
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
19
graphics/items/icon_palettes/tera_orb.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
0 0 0
|
||||
81 41 75
|
||||
98 61 92
|
||||
66 72 65
|
||||
51 4 43
|
||||
201 185 199
|
||||
110 86 106
|
||||
84 73 92
|
||||
32 41 34
|
||||
255 255 255
|
||||
71 50 92
|
||||
64 71 94
|
||||
139 165 201
|
||||
183 191 209
|
||||
0 0 0
|
19
graphics/items/icon_palettes/tiny_bamboo_shoot.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
0 0 0
|
||||
111 167 43
|
||||
179 192 68
|
||||
107 144 66
|
||||
84 116 48
|
||||
68 93 37
|
||||
124 137 52
|
||||
168 87 80
|
||||
168 116 111
|
||||
241 241 193
|
||||
168 87 80
|
||||
183 170 147
|
||||
121 52 57
|
||||
0 0 0
|
||||
0 0 0
|
BIN
graphics/items/icons/ability_shield.png
Normal file
After Width: | Height: | Size: 692 B |
BIN
graphics/items/icons/adamant_crystal.png
Normal file
After Width: | Height: | Size: 735 B |
BIN
graphics/items/icons/auspicious_armor.png
Normal file
After Width: | Height: | Size: 710 B |
BIN
graphics/items/icons/big_bamboo_shoot.png
Normal file
After Width: | Height: | Size: 300 B |
BIN
graphics/items/icons/booster_energy.png
Normal file
After Width: | Height: | Size: 309 B |
BIN
graphics/items/icons/covert_cloak.png
Normal file
After Width: | Height: | Size: 308 B |
BIN
graphics/items/icons/gimmighoul_coin.png
Normal file
After Width: | Height: | Size: 270 B |
BIN
graphics/items/icons/griseous_core.png
Normal file
After Width: | Height: | Size: 724 B |
BIN
graphics/items/icons/leaders_crest.png
Normal file
After Width: | Height: | Size: 276 B |
BIN
graphics/items/icons/loaded_dice.png
Normal file
After Width: | Height: | Size: 307 B |
BIN
graphics/items/icons/lustrous_globe.png
Normal file
After Width: | Height: | Size: 750 B |
BIN
graphics/items/icons/malicious_armor.png
Normal file
After Width: | Height: | Size: 690 B |
BIN
graphics/items/icons/mirror_herb.png
Normal file
After Width: | Height: | Size: 331 B |
BIN
graphics/items/icons/punching_glove.png
Normal file
After Width: | Height: | Size: 682 B |
BIN
graphics/items/icons/scroll_of_darkness.png
Normal file
After Width: | Height: | Size: 264 B |
BIN
graphics/items/icons/scroll_of_waters.png
Normal file
After Width: | Height: | Size: 264 B |
BIN
graphics/items/icons/tera_orb.png
Normal file
After Width: | Height: | Size: 327 B |
BIN
graphics/items/icons/tiny_bamboo_shoot.png
Normal file
After Width: | Height: | Size: 249 B |
@ -529,7 +529,6 @@ struct BattleStruct
|
||||
u8 wildVictorySong;
|
||||
u8 dynamicMoveType;
|
||||
u8 wrappedBy[MAX_BATTLERS_COUNT];
|
||||
u16 assistPossibleMoves[PARTY_SIZE * MAX_MON_MOVES]; // Each of mons can know max 4 moves.
|
||||
u8 focusPunchBattlerId;
|
||||
u8 battlerPreventingSwitchout;
|
||||
u8 moneyMultiplier:6;
|
||||
|
@ -1,6 +1,9 @@
|
||||
#ifndef GUARD_BATTLE_MAIN_H
|
||||
#define GUARD_BATTLE_MAIN_H
|
||||
|
||||
#include "pokemon.h"
|
||||
#include "data.h"
|
||||
|
||||
struct TrainerMoney
|
||||
{
|
||||
u8 classId;
|
||||
@ -66,6 +69,7 @@ bool8 TryRunFromBattle(u8 battlerId);
|
||||
void SpecialStatusesClear(void);
|
||||
void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk);
|
||||
bool32 IsWildMonSmart(void);
|
||||
u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer *trainer, bool32 firstTrainer, u32 battleTypeFlags);
|
||||
|
||||
extern struct MultiPartnerMenuPokemon gMultiPartnerParty[MULTI_PARTY_SIZE];
|
||||
|
||||
|
@ -459,6 +459,8 @@ extern const u8 BattleScript_LunarDanceActivates[];
|
||||
extern const u8 BattleScript_ShellTrapSetUp[];
|
||||
extern const u8 BattleScript_CouldntFullyProtect[];
|
||||
extern const u8 BattleScript_MoveEffectStockpileWoreOff[];
|
||||
extern const u8 BattleScript_StealthRockActivates[];
|
||||
extern const u8 BattleScript_SpikesActivates[];
|
||||
|
||||
// zmoves
|
||||
extern const u8 BattleScript_ZMoveActivateDamaging[];
|
||||
|
@ -7,7 +7,8 @@
|
||||
#define I_KEY_ESCAPE_ROPE GEN_LATEST // In Gen8, Escape Rope became a Key Item. Keep in mind, this will make it free to buy in marts.
|
||||
#define I_HEALTH_RECOVERY GEN_LATEST // In Gen7+, certain healing items recover a different amount of HP than they used to.
|
||||
#define I_SITRUS_BERRY_HEAL GEN_LATEST // In Gen4+, Sitrus Berry was changed from healing 30 HP to healing 25% of Max HP.
|
||||
#define I_VITAMIN_EV_CAP GEN_LATEST // In Gen8, the Vitamins no longer have a cap of 100 EV per stat.
|
||||
#define I_VITAMIN_EV_CAP GEN_LATEST // In Gen8+, the Vitamins no longer have a cap of 100 EV per stat.
|
||||
#define I_GRISEOUS_ORB_FORM_CHANGE GEN_LATEST // In Gen9+, the Griseous Orb no longer changes Giratina's form when held.
|
||||
|
||||
// Repel/Lure config
|
||||
// These two settings are both independent and complementary.
|
||||
|
@ -372,9 +372,12 @@
|
||||
#define MOVE_EFFECT_TRAP_BOTH 70
|
||||
#define MOVE_EFFECT_DOUBLE_SHOCK 71
|
||||
#define MOVE_EFFECT_ROUND 72
|
||||
#define MOVE_EFFECT_STOCKPILE_WORE_OFF 74
|
||||
#define MOVE_EFFECT_STOCKPILE_WORE_OFF 73
|
||||
#define MOVE_EFFECT_DIRE_CLAW 74
|
||||
#define MOVE_EFFECT_STEALTH_ROCK 75
|
||||
#define MOVE_EFFECT_SPIKES 76
|
||||
|
||||
#define NUM_MOVE_EFFECTS 75
|
||||
#define NUM_MOVE_EFFECTS 77
|
||||
|
||||
#define MOVE_EFFECT_AFFECTS_USER 0x4000
|
||||
#define MOVE_EFFECT_CERTAIN 0x8000
|
||||
|
@ -401,7 +401,10 @@
|
||||
#define EFFECT_SHELL_TRAP 395
|
||||
#define EFFECT_PSYBLADE 396
|
||||
#define EFFECT_HYDRO_STEAM 397
|
||||
#define EFFECT_HIT_SET_ENTRY_HAZARD 398
|
||||
#define EFFECT_DIRE_CLAW 399
|
||||
#define EFFECT_BARB_BARRAGE 400
|
||||
|
||||
#define NUM_BATTLE_MOVE_EFFECTS 398
|
||||
#define NUM_BATTLE_MOVE_EFFECTS 401
|
||||
|
||||
#endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H
|
||||
|
@ -933,4 +933,10 @@
|
||||
#define B_MSG_Z_STAT_UP 5
|
||||
#define B_MSG_Z_HP_TRAP 6
|
||||
|
||||
// gDmgHazardsStringIds
|
||||
#define B_MSG_PKMNHURTBYSPIKES 0
|
||||
#define B_MSG_STEALTHROCKDMG 1
|
||||
#define B_MSG_POINTEDSTONESFLOAT 2
|
||||
#define B_MSG_SPIKESSCATTERED 3
|
||||
|
||||
#endif // GUARD_CONSTANTS_BATTLE_STRING_IDS_H
|
||||
|
@ -159,6 +159,7 @@
|
||||
#define HOLD_EFFECT_PUNCHING_GLOVE 178
|
||||
#define HOLD_EFFECT_COVERT_CLOAK 179
|
||||
#define HOLD_EFFECT_LOADED_DICE 180
|
||||
#define HOLD_EFFECT_BOOSTER_ENERGY 181 // Not implemented.
|
||||
|
||||
#define HOLD_EFFECT_CHOICE(holdEffect)((holdEffect == HOLD_EFFECT_CHOICE_BAND || holdEffect == HOLD_EFFECT_CHOICE_SCARF || holdEffect == HOLD_EFFECT_CHOICE_SPECS))
|
||||
|
||||
|
@ -928,13 +928,48 @@
|
||||
#define ITEM_RUBY 756
|
||||
#define ITEM_SAPPHIRE 757
|
||||
|
||||
// GEN IX ITEMS
|
||||
#define ITEM_ABILITY_SHIELD 758
|
||||
#define ITEM_CLEAR_AMULET 759
|
||||
#define ITEM_PUNCHING_GLOVE 760
|
||||
#define ITEM_COVERT_CLOAK 761
|
||||
#define ITEM_LOADED_DICE 762
|
||||
#define ITEM_AUSPICIOUS_ARMOR 763
|
||||
#define ITEM_BOOSTER_ENERGY 764
|
||||
#define ITEM_BIG_BAMBOO_SHOOT 765
|
||||
#define ITEM_GIMMIGHOUL_COIN 766
|
||||
#define ITEM_LEADERS_CREST 767
|
||||
#define ITEM_MALICIOUS_ARMOR 768
|
||||
#define ITEM_MIRROR_HERB 769
|
||||
#define ITEM_SCROLL_OF_DARKNESS 770
|
||||
#define ITEM_SCROLL_OF_WATERS 771
|
||||
#define ITEM_TERA_ORB 772
|
||||
#define ITEM_TINY_BAMBOO_SHOOT 773
|
||||
|
||||
#define ITEMS_COUNT 763
|
||||
#define ITEM_BUG_TERA_SHARD 774
|
||||
#define ITEM_DARK_TERA_SHARD 775
|
||||
#define ITEM_DRAGON_TERA_SHARD 776
|
||||
#define ITEM_ELECTRIC_TERA_SHARD 777
|
||||
#define ITEM_FAIRY_TERA_SHARD 778
|
||||
#define ITEM_FIGHTING_TERA_SHARD 779
|
||||
#define ITEM_FIRE_TERA_SHARD 780
|
||||
#define ITEM_FLYING_TERA_SHARD 781
|
||||
#define ITEM_GHOST_TERA_SHARD 782
|
||||
#define ITEM_GRASS_TERA_SHARD 783
|
||||
#define ITEM_GROUND_TERA_SHARD 784
|
||||
#define ITEM_ICE_TERA_SHARD 785
|
||||
#define ITEM_NORMAL_TERA_SHARD 786
|
||||
#define ITEM_POISON_TERA_SHARD 787
|
||||
#define ITEM_PSYCHIC_TERA_SHARD 788
|
||||
#define ITEM_ROCK_TERA_SHARD 789
|
||||
#define ITEM_STEEL_TERA_SHARD 790
|
||||
#define ITEM_WATER_TERA_SHARD 791
|
||||
|
||||
#define ITEM_ADAMANT_CRYSTAL 792
|
||||
#define ITEM_GRISEOUS_CORE 793
|
||||
#define ITEM_LUSTROUS_GLOBE 794
|
||||
|
||||
#define ITEMS_COUNT 795
|
||||
#define ITEM_FIELD_ARROW ITEMS_COUNT
|
||||
|
||||
// A special item id associated with "Cancel"/"Exit" etc. in a list of items or decorations
|
||||
@ -1001,7 +1036,4 @@
|
||||
#define ITEM_B_USE_MEDICINE 1
|
||||
#define ITEM_B_USE_OTHER 2
|
||||
|
||||
// Check if the item is one that can be used on a Pokemon.
|
||||
#define ITEM_HAS_EFFECT(item) ((item) >= ITEM_POTION && (item) <= LAST_BERRY_INDEX)
|
||||
|
||||
#endif // GUARD_CONSTANTS_ITEMS_H
|
||||
|
@ -376,5 +376,10 @@
|
||||
// Pokémon.
|
||||
#define F_TRAINER_PARTY_CUSTOM_MOVESET (1 << 0)
|
||||
#define F_TRAINER_PARTY_HELD_ITEM (1 << 1)
|
||||
#define F_TRAINER_PARTY_EVERYTHING_CUSTOMIZED (1 << 3)
|
||||
|
||||
// Trainer party defines
|
||||
#define TRAINER_MON_MALE 1
|
||||
#define TRAINER_MON_FEMALE 2
|
||||
|
||||
#endif // GUARD_TRAINERS_H
|
||||
|
@ -31,6 +31,26 @@ struct MonCoords
|
||||
#define MON_COORDS_SIZE(width, height)(DIV_ROUND_UP(width, 8) << 4 | DIV_ROUND_UP(height, 8))
|
||||
#define GET_MON_COORDS_WIDTH(size)((size >> 4) * 8)
|
||||
#define GET_MON_COORDS_HEIGHT(size)((size & 0xF) * 8)
|
||||
#define TRAINER_PARTY_IVS(hp, atk, def, speed, spatk, spdef) (hp | (atk << 5) | (def << 10) | (speed << 15) | (spatk << 20) | (spdef << 25))
|
||||
#define TRAINER_PARTY_EVS(hp, atk, def, speed, spatk, spdef) ((const u8[6]){hp,atk,def,spatk,spdef,speed})
|
||||
#define TRAINER_PARTY_NATURE(nature) (nature+1)
|
||||
|
||||
struct TrainerMonCustomized
|
||||
{
|
||||
const u8 *nickname;
|
||||
const u8 *ev;
|
||||
u32 iv;
|
||||
u16 moves[4];
|
||||
u16 species;
|
||||
u16 heldItem;
|
||||
u16 ability;
|
||||
u8 lvl;
|
||||
u8 ball;
|
||||
u8 friendship;
|
||||
u8 nature : 5;
|
||||
bool8 gender : 2;
|
||||
bool8 isShiny : 1;
|
||||
};
|
||||
|
||||
struct TrainerMonNoItemDefaultMoves
|
||||
{
|
||||
@ -68,6 +88,7 @@ struct TrainerMonItemCustomMoves
|
||||
#define NO_ITEM_CUSTOM_MOVES(party) { .NoItemCustomMoves = party }, .partySize = ARRAY_COUNT(party), .partyFlags = F_TRAINER_PARTY_CUSTOM_MOVESET
|
||||
#define ITEM_DEFAULT_MOVES(party) { .ItemDefaultMoves = party }, .partySize = ARRAY_COUNT(party), .partyFlags = F_TRAINER_PARTY_HELD_ITEM
|
||||
#define ITEM_CUSTOM_MOVES(party) { .ItemCustomMoves = party }, .partySize = ARRAY_COUNT(party), .partyFlags = F_TRAINER_PARTY_CUSTOM_MOVESET | F_TRAINER_PARTY_HELD_ITEM
|
||||
#define EVERYTHING_CUSTOMIZED(party) { .EverythingCustomized = party}, .partySize = ARRAY_COUNT(party), .partyFlags = F_TRAINER_PARTY_EVERYTHING_CUSTOMIZED
|
||||
|
||||
union TrainerMonPtr
|
||||
{
|
||||
@ -75,20 +96,21 @@ union TrainerMonPtr
|
||||
const struct TrainerMonNoItemCustomMoves *NoItemCustomMoves;
|
||||
const struct TrainerMonItemDefaultMoves *ItemDefaultMoves;
|
||||
const struct TrainerMonItemCustomMoves *ItemCustomMoves;
|
||||
const struct TrainerMonCustomized *EverythingCustomized;
|
||||
};
|
||||
|
||||
struct Trainer
|
||||
{
|
||||
/*0x00*/ u8 partyFlags;
|
||||
/*0x01*/ u8 trainerClass;
|
||||
/*0x02*/ u8 encounterMusic_gender; // last bit is gender
|
||||
/*0x03*/ u8 trainerPic;
|
||||
/*0x04*/ u8 trainerName[TRAINER_NAME_LENGTH + 1];
|
||||
/*0x10*/ u16 items[MAX_TRAINER_ITEMS];
|
||||
/*0x18*/ bool8 doubleBattle;
|
||||
/*0x1C*/ u32 aiFlags;
|
||||
/*0x20*/ u8 partySize;
|
||||
/*0x24*/ union TrainerMonPtr party;
|
||||
/*0x00*/ u32 aiFlags;
|
||||
/*0x04*/ union TrainerMonPtr party;
|
||||
/*0x08*/ u16 items[MAX_TRAINER_ITEMS];
|
||||
/*0x10*/ u8 trainerClass;
|
||||
/*0x11*/ u8 encounterMusic_gender; // last bit is gender
|
||||
/*0x12*/ u8 trainerPic;
|
||||
/*0x13*/ u8 trainerName[TRAINER_NAME_LENGTH + 1];
|
||||
/*0x1E*/ bool8 doubleBattle:1;
|
||||
u8 partyFlags:7;
|
||||
/*0x1F*/ u8 partySize;
|
||||
};
|
||||
|
||||
#define TRAINER_ENCOUNTER_MUSIC(trainer)((gTrainers[trainer].encounterMusic_gender & 0x7F))
|
||||
|
@ -147,6 +147,9 @@
|
||||
#define CAT(a, b) CAT_(a, b)
|
||||
#define CAT_(a, b) a ## b
|
||||
|
||||
// Converts a string to a compound literal, essentially making it a pointer to const u8
|
||||
#define COMPOUND_STRING(str) (const u8[]) _(str)
|
||||
|
||||
// This produces an error at compile-time if expr is zero.
|
||||
// It looks like file.c:line: size of array `id' is negative
|
||||
#define STATIC_ASSERT(expr, id) typedef char id[(expr) ? 1 : -1];
|
||||
|
@ -8834,6 +8834,45 @@ extern const u32 gItemIcon_Gem[];
|
||||
extern const u32 gItemIconPalette_Ruby[];
|
||||
extern const u32 gItemIconPalette_Sapphire[];
|
||||
|
||||
// GEN IX ITEMS
|
||||
extern const u32 gItemIcon_AbilityShield[];
|
||||
extern const u32 gItemIconPalette_AbilityShield[];
|
||||
extern const u32 gItemIcon_AuspiciousArmor[];
|
||||
extern const u32 gItemIconPalette_AuspiciousArmor[];
|
||||
extern const u32 gItemIcon_BigBambooShoot[];
|
||||
extern const u32 gItemIconPalette_BigBambooShoot[];
|
||||
extern const u32 gItemIcon_BoosterEnergy[];
|
||||
extern const u32 gItemIconPalette_BoosterEnergy[];
|
||||
extern const u32 gItemIcon_CovertCloak[];
|
||||
extern const u32 gItemIconPalette_CovertCloak[];
|
||||
extern const u32 gItemIcon_GimmighoulCoin[];
|
||||
extern const u32 gItemIconPalette_GimmighoulCoin[];
|
||||
extern const u32 gItemIcon_LeadersCrest[];
|
||||
extern const u32 gItemIconPalette_LeadersCrest[];
|
||||
extern const u32 gItemIcon_LoadedDice[];
|
||||
extern const u32 gItemIconPalette_LoadedDice[];
|
||||
extern const u32 gItemIcon_MaliciousArmor[];
|
||||
extern const u32 gItemIconPalette_MaliciousArmor[];
|
||||
extern const u32 gItemIcon_MirrorHerb[];
|
||||
extern const u32 gItemIconPalette_MirrorHerb[];
|
||||
extern const u32 gItemIcon_PunchingGlove[];
|
||||
extern const u32 gItemIconPalette_PunchingGlove[];
|
||||
extern const u32 gItemIcon_ScrollOfDarkness[];
|
||||
extern const u32 gItemIconPalette_ScrollOfDarkness[];
|
||||
extern const u32 gItemIcon_ScrollOfWaters[];
|
||||
extern const u32 gItemIconPalette_ScrollOfWaters[];
|
||||
extern const u32 gItemIcon_TeraOrb[];
|
||||
extern const u32 gItemIconPalette_TeraOrb[];
|
||||
extern const u32 gItemIcon_TinyBambooShoot[];
|
||||
extern const u32 gItemIconPalette_TinyBambooShoot[];
|
||||
|
||||
extern const u32 gItemIcon_AdamantCrystal[];
|
||||
extern const u32 gItemIconPalette_AdamantCrystal[];
|
||||
extern const u32 gItemIcon_GriseousCore[];
|
||||
extern const u32 gItemIconPalette_GriseousCore[];
|
||||
extern const u32 gItemIcon_LustrousGlobe[];
|
||||
extern const u32 gItemIconPalette_LustrousGlobe[];
|
||||
|
||||
extern const u32 gItemIcon_ReturnToFieldArrow[];
|
||||
extern const u32 gItemIconPalette_ReturnToFieldArrow[];
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define GUARD_POKEMON_H
|
||||
|
||||
#include "sprite.h"
|
||||
#include "constants/items.h"
|
||||
#include "constants/region_map_sections.h"
|
||||
#include "constants/map_groups.h"
|
||||
|
||||
@ -401,7 +402,7 @@ extern const struct BattleMove gBattleMoves[];
|
||||
extern const u8 gFacilityClassToPicIndex[];
|
||||
extern const u8 gFacilityClassToTrainerClass[];
|
||||
extern const struct SpeciesInfo gSpeciesInfo[];
|
||||
extern const u8 *const gItemEffectTable[];
|
||||
extern const u8 *const gItemEffectTable[ITEMS_COUNT];
|
||||
extern const u32 gExperienceTables[][MAX_LEVEL + 1];
|
||||
extern const struct LevelUpMove *const gLevelUpLearnsets[];
|
||||
extern const u16 *const gTeachableLearnsets[];
|
||||
|
@ -20,4 +20,67 @@ u16 Random2(void);
|
||||
void SeedRng(u16 seed);
|
||||
void SeedRng2(u16 seed);
|
||||
|
||||
/* Structured random number generator.
|
||||
* Instead of the caller converting bits from Random() to a meaningful
|
||||
* value, the caller provides metadata that is used to return the
|
||||
* meaningful value directly. This allows code to interpret the random
|
||||
* call, for example, battle tests know what the domain of a random call
|
||||
* is, and can exhaustively test it.
|
||||
*
|
||||
* RandomTag identifies the purpose of the value.
|
||||
*
|
||||
* RandomUniform(tag, lo, hi) returns a number from lo to hi inclusive.
|
||||
*
|
||||
* RandomPercentage(tag, t) returns FALSE with probability (1-t)/100,
|
||||
* and TRUE with probability t/100.
|
||||
*
|
||||
* RandomWeighted(tag, w0, w1, ... wN) returns a number from 0 to N
|
||||
* inclusive. The return value is proportional to the weights, e.g.
|
||||
* RandomWeighted(..., 1, 1) returns 50% 0s and 50% 1s.
|
||||
* RandomWeighted(..., 2, 1) returns 2/3 0s and 1/3 1s. */
|
||||
|
||||
enum RandomTag
|
||||
{
|
||||
RNG_NONE,
|
||||
RNG_ACCURACY,
|
||||
RNG_CONFUSION,
|
||||
RNG_CRITICAL_HIT,
|
||||
RNG_CUTE_CHARM,
|
||||
RNG_DAMAGE_MODIFIER,
|
||||
RNG_FLAME_BODY,
|
||||
RNG_FORCE_RANDOM_SWITCH,
|
||||
RNG_FROZEN,
|
||||
RNG_HOLD_EFFECT_FLINCH,
|
||||
RNG_INFATUATION,
|
||||
RNG_PARALYSIS,
|
||||
RNG_POISON_POINT,
|
||||
RNG_RAMPAGE_TURNS,
|
||||
RNG_SECONDARY_EFFECT,
|
||||
RNG_SLEEP_TURNS,
|
||||
RNG_SPEED_TIE,
|
||||
RNG_STATIC,
|
||||
RNG_STENCH,
|
||||
};
|
||||
|
||||
#define RandomWeighted(tag, ...) \
|
||||
({ \
|
||||
const u8 weights[] = { __VA_ARGS__ }; \
|
||||
u32 sum, i; \
|
||||
for (i = 0, sum = 0; i < ARRAY_COUNT(weights); i++) \
|
||||
sum += weights[i]; \
|
||||
RandomWeightedArray(tag, sum, ARRAY_COUNT(weights), weights); \
|
||||
})
|
||||
|
||||
#define RandomPercentage(tag, t) \
|
||||
({ \
|
||||
const u8 weights[] = { 100 - t, t }; \
|
||||
RandomWeightedArray(tag, 100, ARRAY_COUNT(weights), weights); \
|
||||
})
|
||||
|
||||
u32 RandomUniform(enum RandomTag, u32 lo, u32 hi);
|
||||
u32 RandomWeightedArray(enum RandomTag, u32 sum, u32 n, const u8 *weights);
|
||||
|
||||
u32 RandomUniformDefault(enum RandomTag, u32 lo, u32 hi);
|
||||
u32 RandomWeightedArrayDefault(enum RandomTag, u32 sum, u32 n, const u8 *weights);
|
||||
|
||||
#endif // GUARD_RANDOM_H
|
||||
|
@ -3473,6 +3473,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
break;
|
||||
case EFFECT_TOXIC:
|
||||
case EFFECT_POISON:
|
||||
case EFFECT_BARB_BARRAGE:
|
||||
IncreasePoisonScore(battlerAtk, battlerDef, move, &score);
|
||||
break;
|
||||
case EFFECT_LIGHT_SCREEN:
|
||||
@ -3864,6 +3865,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
break;
|
||||
|
||||
case EFFECT_SPIKES:
|
||||
case EFFECT_HIT_SET_ENTRY_HAZARD:
|
||||
case EFFECT_STEALTH_ROCK:
|
||||
case EFFECT_STICKY_WEB:
|
||||
case EFFECT_TOXIC_SPIKES:
|
||||
@ -4898,6 +4900,7 @@ static s16 AI_SetupFirstTurn(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
case EFFECT_HAIL:
|
||||
case EFFECT_GEOMANCY:
|
||||
case EFFECT_VICTORY_DANCE:
|
||||
case EFFECT_HIT_SET_ENTRY_HAZARD:
|
||||
score += 2;
|
||||
break;
|
||||
default:
|
||||
|
@ -1085,13 +1085,13 @@ static bool8 ShouldUseItem(void)
|
||||
item = gBattleResources->battleHistory->trainerItems[i];
|
||||
if (item == ITEM_NONE)
|
||||
continue;
|
||||
if (gItemEffectTable[item - ITEM_POTION] == NULL)
|
||||
if (gItemEffectTable[item] == NULL)
|
||||
continue;
|
||||
|
||||
if (item == ITEM_ENIGMA_BERRY_E_READER)
|
||||
itemEffects = gSaveBlock1Ptr->enigmaBerry.itemEffect;
|
||||
else
|
||||
itemEffects = gItemEffectTable[item - ITEM_POTION];
|
||||
itemEffects = gItemEffectTable[item];
|
||||
|
||||
*(gBattleStruct->AI_itemType + gActiveBattler / 2) = GetAI_ItemType(item, itemEffects);
|
||||
|
||||
|
@ -118,6 +118,10 @@ static void HandleEndTurn_FinishBattle(void);
|
||||
static void SpriteCB_UnusedBattleInit(struct Sprite *sprite);
|
||||
static void SpriteCB_UnusedBattleInit_Main(struct Sprite *sprite);
|
||||
static void TrySpecialEvolution(void);
|
||||
static u32 Crc32B (const u8 *data, u32 size);
|
||||
static u32 GeneratePartyHash(const struct Trainer *trainer, u32 i);
|
||||
static void ModifyPersonalityForNature(u32 *personality, u32 newNature);
|
||||
static u32 GeneratePersonalityForGender(u32 gender, u32 species);
|
||||
|
||||
EWRAM_DATA u16 gBattle_BG0_X = 0;
|
||||
EWRAM_DATA u16 gBattle_BG0_Y = 0;
|
||||
@ -1857,72 +1861,129 @@ static void SpriteCB_UnusedBattleInit_Main(struct Sprite *sprite)
|
||||
}
|
||||
}
|
||||
|
||||
static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 firstTrainer)
|
||||
static u32 Crc32B (const u8 *data, u32 size)
|
||||
{
|
||||
s32 i, j;
|
||||
u32 byte, crc, mask;
|
||||
|
||||
i = 0;
|
||||
crc = 0xFFFFFFFF;
|
||||
for (i = 0; i < size; ++i)
|
||||
{
|
||||
byte = data[i];
|
||||
crc = crc ^ byte;
|
||||
for (j = 7; j >= 0; --j)
|
||||
{
|
||||
mask = -(crc & 1);
|
||||
crc = (crc >> 1) ^ (0xEDB88320 & mask);
|
||||
}
|
||||
}
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
static u32 GeneratePartyHash(const struct Trainer *trainer, u32 i)
|
||||
{
|
||||
const u8 *buffer;
|
||||
u32 n;
|
||||
if (trainer->partyFlags == 0)
|
||||
{
|
||||
buffer = (const u8 *) &trainer->party.NoItemDefaultMoves[i];
|
||||
n = sizeof(*trainer->party.NoItemDefaultMoves);
|
||||
}
|
||||
else if (trainer->partyFlags == F_TRAINER_PARTY_CUSTOM_MOVESET)
|
||||
{
|
||||
buffer = (const u8 *) &trainer->party.NoItemCustomMoves[i];
|
||||
n = sizeof(*trainer->party.NoItemCustomMoves);
|
||||
}
|
||||
else if (trainer->partyFlags == F_TRAINER_PARTY_HELD_ITEM)
|
||||
{
|
||||
buffer = (const u8 *) &trainer->party.ItemDefaultMoves[i];
|
||||
n = sizeof(*trainer->party.ItemDefaultMoves);
|
||||
}
|
||||
else if (trainer->partyFlags == (F_TRAINER_PARTY_HELD_ITEM | F_TRAINER_PARTY_CUSTOM_MOVESET))
|
||||
{
|
||||
buffer = (const u8 *) &trainer->party.ItemCustomMoves[i];
|
||||
n = sizeof(*trainer->party.ItemCustomMoves);
|
||||
}
|
||||
else if (trainer->partyFlags == F_TRAINER_PARTY_EVERYTHING_CUSTOMIZED)
|
||||
{
|
||||
buffer = (const u8 *) &trainer->party.EverythingCustomized[i];
|
||||
n = sizeof(*trainer->party.EverythingCustomized);
|
||||
}
|
||||
return Crc32B(buffer, n);
|
||||
}
|
||||
|
||||
static void ModifyPersonalityForNature(u32 *personality, u32 newNature)
|
||||
{
|
||||
u32 nature = GetNatureFromPersonality(*personality);
|
||||
s32 diff = abs(nature - newNature);
|
||||
s32 sign = (nature > newNature) ? 1 : -1;
|
||||
if (diff > NUM_NATURES / 2)
|
||||
{
|
||||
diff = NUM_NATURES - diff;
|
||||
sign *= -1;
|
||||
}
|
||||
*personality -= (diff * sign);
|
||||
}
|
||||
|
||||
static u32 GeneratePersonalityForGender(u32 gender, u32 species)
|
||||
{
|
||||
const struct SpeciesInfo *speciesInfo = &gSpeciesInfo[species];
|
||||
if (gender == MON_MALE)
|
||||
return ((255 - speciesInfo->genderRatio) / 2) + speciesInfo->genderRatio;
|
||||
else
|
||||
return speciesInfo->genderRatio / 2;
|
||||
}
|
||||
|
||||
u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer *trainer, bool32 firstTrainer, u32 battleTypeFlags)
|
||||
{
|
||||
u32 nameHash = 0;
|
||||
u32 personalityValue;
|
||||
u8 fixedIV;
|
||||
s32 i, j;
|
||||
u8 monsCount;
|
||||
u16 ball;
|
||||
|
||||
if (trainerNum == TRAINER_SECRET_BASE)
|
||||
return 0;
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && !(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER
|
||||
s32 ball = -1;
|
||||
if (battleTypeFlags & BATTLE_TYPE_TRAINER && !(battleTypeFlags & (BATTLE_TYPE_FRONTIER
|
||||
| BATTLE_TYPE_EREADER_TRAINER
|
||||
| BATTLE_TYPE_TRAINER_HILL)))
|
||||
{
|
||||
if (firstTrainer == TRUE)
|
||||
ZeroEnemyPartyMons();
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
|
||||
if (battleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
|
||||
{
|
||||
if (gTrainers[trainerNum].partySize > PARTY_SIZE / 2)
|
||||
if (trainer->partySize > PARTY_SIZE / 2)
|
||||
monsCount = PARTY_SIZE / 2;
|
||||
else
|
||||
monsCount = gTrainers[trainerNum].partySize;
|
||||
monsCount = trainer->partySize;
|
||||
}
|
||||
else
|
||||
{
|
||||
monsCount = gTrainers[trainerNum].partySize;
|
||||
monsCount = trainer->partySize;
|
||||
}
|
||||
|
||||
for (i = 0; i < monsCount; i++)
|
||||
{
|
||||
|
||||
if (gTrainers[trainerNum].doubleBattle == TRUE)
|
||||
u32 personalityHash = GeneratePartyHash(trainer, i);
|
||||
if (trainer->doubleBattle == TRUE)
|
||||
personalityValue = 0x80;
|
||||
else if (gTrainers[trainerNum].encounterMusic_gender & F_TRAINER_FEMALE)
|
||||
else if (trainer->encounterMusic_gender & F_TRAINER_FEMALE)
|
||||
personalityValue = 0x78; // Use personality more likely to result in a female Pokémon
|
||||
else
|
||||
personalityValue = 0x88; // Use personality more likely to result in a male Pokémon
|
||||
|
||||
for (j = 0; gTrainers[trainerNum].trainerName[j] != EOS; j++)
|
||||
nameHash += gTrainers[trainerNum].trainerName[j];
|
||||
|
||||
switch (gTrainers[trainerNum].partyFlags)
|
||||
personalityValue += personalityHash << 8;
|
||||
switch (trainer->partyFlags)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
const struct TrainerMonNoItemDefaultMoves *partyData = gTrainers[trainerNum].party.NoItemDefaultMoves;
|
||||
|
||||
for (j = 0; gSpeciesNames[partyData[i].species][j] != EOS; j++)
|
||||
nameHash += gSpeciesNames[partyData[i].species][j];
|
||||
|
||||
personalityValue += nameHash << 8;
|
||||
const struct TrainerMonNoItemDefaultMoves *partyData = trainer->party.NoItemDefaultMoves;
|
||||
fixedIV = partyData[i].iv * MAX_PER_STAT_IVS / 255;
|
||||
CreateMon(&party[i], partyData[i].species, partyData[i].lvl, fixedIV, TRUE, personalityValue, OT_ID_RANDOM_NO_SHINY, 0);
|
||||
break;
|
||||
}
|
||||
case F_TRAINER_PARTY_CUSTOM_MOVESET:
|
||||
{
|
||||
const struct TrainerMonNoItemCustomMoves *partyData = gTrainers[trainerNum].party.NoItemCustomMoves;
|
||||
|
||||
for (j = 0; gSpeciesNames[partyData[i].species][j] != EOS; j++)
|
||||
nameHash += gSpeciesNames[partyData[i].species][j];
|
||||
|
||||
personalityValue += nameHash << 8;
|
||||
const struct TrainerMonNoItemCustomMoves *partyData = trainer->party.NoItemCustomMoves;
|
||||
fixedIV = partyData[i].iv * MAX_PER_STAT_IVS / 255;
|
||||
CreateMon(&party[i], partyData[i].species, partyData[i].lvl, fixedIV, TRUE, personalityValue, OT_ID_RANDOM_NO_SHINY, 0);
|
||||
|
||||
@ -1935,12 +1996,7 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir
|
||||
}
|
||||
case F_TRAINER_PARTY_HELD_ITEM:
|
||||
{
|
||||
const struct TrainerMonItemDefaultMoves *partyData = gTrainers[trainerNum].party.ItemDefaultMoves;
|
||||
|
||||
for (j = 0; gSpeciesNames[partyData[i].species][j] != EOS; j++)
|
||||
nameHash += gSpeciesNames[partyData[i].species][j];
|
||||
|
||||
personalityValue += nameHash << 8;
|
||||
const struct TrainerMonItemDefaultMoves *partyData = trainer->party.ItemDefaultMoves;
|
||||
fixedIV = partyData[i].iv * MAX_PER_STAT_IVS / 255;
|
||||
CreateMon(&party[i], partyData[i].species, partyData[i].lvl, fixedIV, TRUE, personalityValue, OT_ID_RANDOM_NO_SHINY, 0);
|
||||
|
||||
@ -1949,12 +2005,7 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir
|
||||
}
|
||||
case F_TRAINER_PARTY_CUSTOM_MOVESET | F_TRAINER_PARTY_HELD_ITEM:
|
||||
{
|
||||
const struct TrainerMonItemCustomMoves *partyData = gTrainers[trainerNum].party.ItemCustomMoves;
|
||||
|
||||
for (j = 0; gSpeciesNames[partyData[i].species][j] != EOS; j++)
|
||||
nameHash += gSpeciesNames[partyData[i].species][j];
|
||||
|
||||
personalityValue += nameHash << 8;
|
||||
const struct TrainerMonItemCustomMoves *partyData = trainer->party.ItemCustomMoves;
|
||||
fixedIV = partyData[i].iv * MAX_PER_STAT_IVS / 255;
|
||||
CreateMon(&party[i], partyData[i].species, partyData[i].lvl, fixedIV, TRUE, personalityValue, OT_ID_RANDOM_NO_SHINY, 0);
|
||||
|
||||
@ -1967,18 +2018,88 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir
|
||||
}
|
||||
break;
|
||||
}
|
||||
case F_TRAINER_PARTY_EVERYTHING_CUSTOMIZED:
|
||||
{
|
||||
const struct TrainerMonCustomized *partyData = trainer->party.EverythingCustomized;
|
||||
u32 otIdType = OT_ID_RANDOM_NO_SHINY;
|
||||
u32 fixedOtId = 0;
|
||||
if (partyData[i].gender == TRAINER_MON_MALE)
|
||||
personalityValue = (personalityValue & 0xFFFFFF00) | GeneratePersonalityForGender(MON_MALE, partyData[i].species);
|
||||
else if (partyData[i].gender == TRAINER_MON_FEMALE)
|
||||
personalityValue = (personalityValue & 0xFFFFFF00) | GeneratePersonalityForGender(MON_FEMALE, partyData[i].species);
|
||||
if (partyData[i].nature != 0)
|
||||
ModifyPersonalityForNature(&personalityValue, partyData[i].nature - 1);
|
||||
if (partyData[i].isShiny)
|
||||
{
|
||||
otIdType = OT_ID_PRESET;
|
||||
fixedOtId = HIHALF(personalityValue) ^ LOHALF(personalityValue);
|
||||
}
|
||||
CreateMon(&party[i], partyData[i].species, partyData[i].lvl, 0, TRUE, personalityValue, otIdType, fixedOtId);
|
||||
SetMonData(&party[i], MON_DATA_HELD_ITEM, &partyData[i].heldItem);
|
||||
|
||||
// TODO: Figure out a default strategy when moves are not set, to generate a good moveset
|
||||
for (j = 0; j < MAX_MON_MOVES; ++j)
|
||||
{
|
||||
SetMonData(&party[i], MON_DATA_MOVE1 + j, &partyData[i].moves[j]);
|
||||
SetMonData(&party[i], MON_DATA_PP1 + j, &gBattleMoves[partyData[i].moves[j]].pp);
|
||||
}
|
||||
SetMonData(&party[i], MON_DATA_IVS, &(partyData[i].iv));
|
||||
if (partyData[i].ev != NULL)
|
||||
{
|
||||
SetMonData(&party[i], MON_DATA_HP_EV, &(partyData[i].ev[0]));
|
||||
SetMonData(&party[i], MON_DATA_ATK_EV, &(partyData[i].ev[1]));
|
||||
SetMonData(&party[i], MON_DATA_DEF_EV, &(partyData[i].ev[2]));
|
||||
SetMonData(&party[i], MON_DATA_SPATK_EV, &(partyData[i].ev[3]));
|
||||
SetMonData(&party[i], MON_DATA_SPDEF_EV, &(partyData[i].ev[4]));
|
||||
SetMonData(&party[i], MON_DATA_SPEED_EV, &(partyData[i].ev[5]));
|
||||
}
|
||||
if (partyData[i].ability != ABILITY_NONE)
|
||||
{
|
||||
const struct SpeciesInfo *speciesInfo = &gSpeciesInfo[partyData[i].species];
|
||||
u32 maxAbilities = ARRAY_COUNT(speciesInfo->abilities);
|
||||
for (j = 0; j < maxAbilities; ++j)
|
||||
{
|
||||
if (speciesInfo->abilities[j] == partyData[i].ability)
|
||||
break;
|
||||
}
|
||||
if (j < maxAbilities)
|
||||
SetMonData(&party[i], MON_DATA_ABILITY_NUM, &j);
|
||||
}
|
||||
SetMonData(&party[i], MON_DATA_FRIENDSHIP, &(partyData[i].friendship));
|
||||
if (partyData[i].ball != ITEM_NONE)
|
||||
{
|
||||
ball = partyData[i].ball;
|
||||
SetMonData(&party[i], MON_DATA_POKEBALL, &ball);
|
||||
}
|
||||
if (partyData[i].nickname != NULL)
|
||||
{
|
||||
SetMonData(&party[i], MON_DATA_NICKNAME, partyData[i].nickname);
|
||||
}
|
||||
CalculateMonStats(&party[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#if B_TRAINER_CLASS_POKE_BALLS >= GEN_7
|
||||
ball = (sTrainerBallTable[gTrainers[trainerNum].trainerClass]) ? sTrainerBallTable[gTrainers[trainerNum].trainerClass] : ITEM_POKE_BALL;
|
||||
if (ball == -1)
|
||||
{
|
||||
ball = (sTrainerBallTable[trainer->trainerClass]) ? sTrainerBallTable[trainer->trainerClass] : ITEM_POKE_BALL;
|
||||
SetMonData(&party[i], MON_DATA_POKEBALL, &ball);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
gBattleTypeFlags |= gTrainers[trainerNum].doubleBattle;
|
||||
}
|
||||
|
||||
return gTrainers[trainerNum].partySize;
|
||||
return trainer->partySize;
|
||||
}
|
||||
|
||||
static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 firstTrainer)
|
||||
{
|
||||
u8 retVal;
|
||||
if (trainerNum == TRAINER_SECRET_BASE)
|
||||
return 0;
|
||||
retVal = CreateNPCTrainerPartyFromTrainer(party, &gTrainers[trainerNum], firstTrainer, gBattleTypeFlags);
|
||||
|
||||
gBattleTypeFlags |= gTrainers[trainerNum].doubleBattle;
|
||||
}
|
||||
|
||||
void VBlankCB_Battle(void)
|
||||
|
@ -209,7 +209,7 @@ static const u8 sText_PkmnFellIntoNightmare[] = _("{B_DEF_NAME_WITH_PREFIX} fell
|
||||
static const u8 sText_PkmnLockedInNightmare[] = _("{B_ATK_NAME_WITH_PREFIX} is locked\nin a NIGHTMARE!");
|
||||
static const u8 sText_PkmnLaidCurse[] = _("{B_ATK_NAME_WITH_PREFIX} cut its own HP and\nlaid a CURSE on {B_DEF_NAME_WITH_PREFIX}!");
|
||||
static const u8 sText_PkmnAfflictedByCurse[] = _("{B_ATK_NAME_WITH_PREFIX} is afflicted\nby the CURSE!");
|
||||
static const u8 sText_SpikesScattered[] = _("Spikes were scattered all around\nthe opponent's side!");
|
||||
static const u8 sText_SpikesScattered[] = _("Spikes were scattered all around\n{B_DEF_TEAM2} team!");
|
||||
static const u8 sText_PkmnHurtBySpikes[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is hurt\nby spikes!");
|
||||
static const u8 sText_PkmnIdentified[] = _("{B_ATK_NAME_WITH_PREFIX} identified\n{B_DEF_NAME_WITH_PREFIX}!");
|
||||
static const u8 sText_PkmnPerishCountFell[] = _("{B_ATK_NAME_WITH_PREFIX}'s PERISH count\nfell to {B_BUFF1}!");
|
||||
@ -1475,7 +1475,10 @@ const u16 gHealingWishStringIds[] =
|
||||
|
||||
const u16 gDmgHazardsStringIds[] =
|
||||
{
|
||||
STRINGID_PKMNHURTBYSPIKES, STRINGID_STEALTHROCKDMG
|
||||
[B_MSG_PKMNHURTBYSPIKES] = STRINGID_PKMNHURTBYSPIKES,
|
||||
[B_MSG_STEALTHROCKDMG] = STRINGID_STEALTHROCKDMG,
|
||||
[B_MSG_POINTEDSTONESFLOAT] = STRINGID_POINTEDSTONESFLOAT,
|
||||
[B_MSG_SPIKESSCATTERED] = STRINGID_SPIKESSCATTERED
|
||||
};
|
||||
|
||||
const u16 gSwitchInAbilityStringIds[] =
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "main.h"
|
||||
#include "palette.h"
|
||||
#include "money.h"
|
||||
#include "malloc.h"
|
||||
#include "bg.h"
|
||||
#include "string_util.h"
|
||||
#include "pokemon_icon.h"
|
||||
@ -1917,15 +1918,25 @@ static void Cmd_accuracycheck(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 accuracy;
|
||||
|
||||
GET_MOVE_TYPE(move, type);
|
||||
if (JumpIfMoveAffectedByProtect(move))
|
||||
return;
|
||||
if (AccuracyCalcHelper(move))
|
||||
return;
|
||||
|
||||
// final calculation
|
||||
if ((Random() % 100 + 1) > GetTotalAccuracy(gBattlerAttacker, gBattlerTarget, move, GetBattlerAbility(gBattlerAttacker), GetBattlerAbility(gBattlerTarget),
|
||||
GetBattlerHoldEffect(gBattlerAttacker, TRUE), GetBattlerHoldEffect(gBattlerTarget, TRUE)))
|
||||
accuracy = GetTotalAccuracy(
|
||||
gBattlerAttacker,
|
||||
gBattlerTarget,
|
||||
move,
|
||||
GetBattlerAbility(gBattlerAttacker),
|
||||
GetBattlerAbility(gBattlerTarget),
|
||||
GetBattlerHoldEffect(gBattlerAttacker, TRUE),
|
||||
GetBattlerHoldEffect(gBattlerTarget, TRUE)
|
||||
);
|
||||
|
||||
if (!RandomPercentage(RNG_ACCURACY, accuracy))
|
||||
{
|
||||
gMoveResultFlags |= MOVE_RESULT_MISSED;
|
||||
if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_BLUNDER_POLICY)
|
||||
@ -2104,10 +2115,8 @@ static void Cmd_critcalc(void)
|
||||
gIsCriticalHit = FALSE;
|
||||
else if (critChance == -2)
|
||||
gIsCriticalHit = TRUE;
|
||||
else if (Random() % sCriticalHitChance[critChance] == 0)
|
||||
gIsCriticalHit = TRUE;
|
||||
else
|
||||
gIsCriticalHit = FALSE;
|
||||
gIsCriticalHit = RandomWeighted(RNG_CRITICAL_HIT, sCriticalHitChance[critChance] - 1, 1);
|
||||
|
||||
// Counter for EVO_CRITICAL_HITS.
|
||||
partySlot = gBattlerPartyIndexes[gBattlerAttacker];
|
||||
@ -2885,6 +2894,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
|
||||
bool32 mirrorArmorReflected = (GetBattlerAbility(gBattlerTarget) == ABILITY_MIRROR_ARMOR);
|
||||
u32 flags = 0;
|
||||
u16 battlerAbility;
|
||||
bool8 activateAfterFaint = FALSE;
|
||||
|
||||
if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT
|
||||
&& gBattleMons[gBattlerTarget].hp != 0
|
||||
@ -2903,6 +2913,13 @@ void SetMoveEffect(bool32 primary, u32 certain)
|
||||
gBattleStruct->moveEffect2 = gBattleScripting.moveEffect;
|
||||
gBattlescriptCurrInstr++;
|
||||
return;
|
||||
case MOVE_EFFECT_STEALTH_ROCK:
|
||||
case MOVE_EFFECT_SPIKES:
|
||||
case MOVE_EFFECT_PAYDAY:
|
||||
case MOVE_EFFECT_STEAL_ITEM:
|
||||
case MOVE_EFFECT_BUG_BITE:
|
||||
activateAfterFaint = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (gBattleScripting.moveEffect & MOVE_EFFECT_AFFECTS_USER)
|
||||
@ -2943,10 +2960,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
|
||||
if (TestSheerForceFlag(gBattlerAttacker, gCurrentMove) && affectsUser != MOVE_EFFECT_AFFECTS_USER)
|
||||
INCREMENT_RESET_RETURN
|
||||
|
||||
if (gBattleMons[gEffectBattler].hp == 0
|
||||
&& gBattleScripting.moveEffect != MOVE_EFFECT_PAYDAY
|
||||
&& gBattleScripting.moveEffect != MOVE_EFFECT_STEAL_ITEM
|
||||
&& gBattleScripting.moveEffect != MOVE_EFFECT_BUG_BITE)
|
||||
if (gBattleMons[gEffectBattler].hp == 0 && !activateAfterFaint)
|
||||
INCREMENT_RESET_RETURN
|
||||
|
||||
if (DoesSubstituteBlockMove(gBattlerAttacker, gEffectBattler, gCurrentMove) && affectsUser != MOVE_EFFECT_AFFECTS_USER)
|
||||
@ -3153,9 +3167,9 @@ void SetMoveEffect(bool32 primary, u32 certain)
|
||||
|
||||
if (sStatusFlagsForMoveEffects[gBattleScripting.moveEffect] == STATUS1_SLEEP)
|
||||
#if B_SLEEP_TURNS >= GEN_5
|
||||
gBattleMons[gEffectBattler].status1 |= ((Random() % 3) + 2);
|
||||
gBattleMons[gEffectBattler].status1 |= STATUS1_SLEEP_TURN(1 + RandomUniform(RNG_SLEEP_TURNS, 1, 3));
|
||||
#else
|
||||
gBattleMons[gEffectBattler].status1 |= ((Random() % 4) + 3);
|
||||
gBattleMons[gEffectBattler].status1 |= STATUS1_SLEEP_TURN(1 + RandomUniform(RNG_SLEEP_TURNS, 2, 5));
|
||||
#endif
|
||||
else
|
||||
gBattleMons[gEffectBattler].status1 |= sStatusFlagsForMoveEffects[gBattleScripting.moveEffect];
|
||||
@ -3558,7 +3572,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
|
||||
{
|
||||
gBattleMons[gEffectBattler].status2 |= STATUS2_MULTIPLETURNS;
|
||||
gLockedMoves[gEffectBattler] = gCurrentMove;
|
||||
gBattleMons[gEffectBattler].status2 |= STATUS2_LOCK_CONFUSE_TURN((Random() & 1) + 2); // thrash for 2-3 turns
|
||||
gBattleMons[gEffectBattler].status2 |= STATUS2_LOCK_CONFUSE_TURN(RandomUniform(RNG_RAMPAGE_TURNS, 2, 3));
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_SP_ATK_TWO_DOWN: // Overheat
|
||||
@ -3761,6 +3775,30 @@ void SetMoveEffect(bool32 primary, u32 certain)
|
||||
TryUpdateRoundTurnOrder(); // If another Pokémon uses Round before the user this turn, the user will use Round directly after it
|
||||
gBattlescriptCurrInstr++;
|
||||
break;
|
||||
case MOVE_EFFECT_DIRE_CLAW:
|
||||
if (!gBattleMons[gEffectBattler].status1)
|
||||
{
|
||||
static const u8 sDireClawEffects[] = { MOVE_EFFECT_POISON, MOVE_EFFECT_PARALYSIS, MOVE_EFFECT_SLEEP };
|
||||
gBattleScripting.moveEffect = sDireClawEffects[Random() % ARRAY_COUNT(sDireClawEffects)];
|
||||
SetMoveEffect(TRUE, 0);
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_STEALTH_ROCK:
|
||||
if (!(gSideStatuses[GetBattlerSide(gEffectBattler)] & SIDE_STATUS_STEALTH_ROCK))
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_POINTEDSTONESFLOAT;
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_StealthRockActivates;
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_SPIKES:
|
||||
if (gSideTimers[GetBattlerSide(gEffectBattler)].spikesAmount < 3)
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SPIKESSCATTERED;
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_SpikesActivates;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3779,25 +3817,28 @@ static void Cmd_seteffectwithchance(void)
|
||||
else
|
||||
percentChance = gBattleMoves[gCurrentMove].secondaryEffectChance;
|
||||
|
||||
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
|
||||
&& gBattleScripting.moveEffect)
|
||||
{
|
||||
if (gBattleScripting.moveEffect & MOVE_EFFECT_CERTAIN
|
||||
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
|
||||
|| percentChance >= 100)
|
||||
{
|
||||
gBattleScripting.moveEffect &= ~MOVE_EFFECT_CERTAIN;
|
||||
SetMoveEffect(FALSE, MOVE_EFFECT_CERTAIN);
|
||||
}
|
||||
else if (Random() % 100 < percentChance
|
||||
&& gBattleScripting.moveEffect
|
||||
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
|
||||
else if (RandomPercentage(RNG_SECONDARY_EFFECT, percentChance))
|
||||
{
|
||||
if (percentChance >= 100)
|
||||
SetMoveEffect(FALSE, MOVE_EFFECT_CERTAIN);
|
||||
else
|
||||
SetMoveEffect(FALSE, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
gBattleScripting.moveEffect = 0;
|
||||
gBattleScripting.multihitMoveEffect = 0;
|
||||
@ -5322,6 +5363,7 @@ static bool32 TryKnockOffBattleScript(u32 battlerDef)
|
||||
|
||||
gLastUsedItem = gBattleMons[battlerDef].item;
|
||||
gBattleMons[battlerDef].item = 0;
|
||||
if (gBattleMons[battlerDef].ability != ABILITY_GORILLA_TACTICS)
|
||||
gBattleStruct->choicedMove[battlerDef] = 0;
|
||||
gWishFutureKnock.knockedOffMons[side] |= gBitTable[gBattlerPartyIndexes[battlerDef]];
|
||||
CheckSetUnburden(battlerDef);
|
||||
@ -6965,9 +7007,9 @@ bool32 ShouldPostponeSwitchInAbilities(u32 battlerId)
|
||||
// Checks for double battle, so abilities like Intimidate wait until all battlers are switched-in before activating.
|
||||
if (IsDoubleBattle())
|
||||
{
|
||||
if (aliveOpposing1 && !aliveOpposing2 && !HasNoMonsToSwitch(BATTLE_OPPOSITE(battlerId), PARTY_SIZE, PARTY_SIZE))
|
||||
if (aliveOpposing1 && !aliveOpposing2 && !HasNoMonsToSwitch(BATTLE_PARTNER(BATTLE_OPPOSITE(battlerId)), PARTY_SIZE, PARTY_SIZE))
|
||||
return TRUE;
|
||||
if (!aliveOpposing1 && aliveOpposing2 && !HasNoMonsToSwitch(BATTLE_PARTNER(BATTLE_OPPOSITE(battlerId)), PARTY_SIZE, PARTY_SIZE))
|
||||
if (!aliveOpposing1 && aliveOpposing2 && !HasNoMonsToSwitch(BATTLE_OPPOSITE(battlerId), PARTY_SIZE, PARTY_SIZE))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -7028,7 +7070,7 @@ static void Cmd_switchineffects(void)
|
||||
gBattleMoveDamage = 1;
|
||||
|
||||
gSideStatuses[GetBattlerSide(gActiveBattler)] |= SIDE_STATUS_SPIKES_DAMAGED;
|
||||
SetDmgHazardsBattlescript(gActiveBattler, 0);
|
||||
SetDmgHazardsBattlescript(gActiveBattler, B_MSG_PKMNHURTBYSPIKES);
|
||||
}
|
||||
else if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_STEALTH_ROCK_DAMAGED)
|
||||
&& (gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_STEALTH_ROCK)
|
||||
@ -7039,7 +7081,7 @@ static void Cmd_switchineffects(void)
|
||||
gBattleMoveDamage = GetStealthHazardDamage(gBattleMoves[MOVE_STEALTH_ROCK].type, gActiveBattler);
|
||||
|
||||
if (gBattleMoveDamage != 0)
|
||||
SetDmgHazardsBattlescript(gActiveBattler, 1);
|
||||
SetDmgHazardsBattlescript(gActiveBattler, B_MSG_STEALTHROCKDMG);
|
||||
}
|
||||
else if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_TOXIC_SPIKES_DAMAGED)
|
||||
&& (gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_TOXIC_SPIKES)
|
||||
@ -7484,6 +7526,12 @@ static u32 GetTrainerMoneyToGive(u16 trainerId)
|
||||
lastMonLevel = party[gTrainers[trainerId].partySize - 1].lvl;
|
||||
}
|
||||
break;
|
||||
case F_TRAINER_PARTY_EVERYTHING_CUSTOMIZED:
|
||||
{
|
||||
const struct TrainerMonCustomized *party = gTrainers[trainerId].party.EverythingCustomized;
|
||||
lastMonLevel = party[gTrainers[trainerId].partySize - 1].lvl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
for (; gTrainerMoneyTable[i].classId != 0xFF; i++)
|
||||
@ -12276,7 +12324,7 @@ static void Cmd_forcerandomswitch(void)
|
||||
*(gBattleStruct->battlerPartyIndexes + gBattlerTarget) = gBattlerPartyIndexes[gBattlerTarget];
|
||||
gBattlescriptCurrInstr = BattleScript_RoarSuccessSwitch;
|
||||
gBattleStruct->forcedSwitch |= gBitTable[gBattlerTarget];
|
||||
*(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = validMons[Random() % validMonsCount];
|
||||
*(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = validMons[RandomUniform(RNG_FORCE_RANDOM_SWITCH, 0, validMonsCount - 1)];
|
||||
|
||||
if (!IsMultiBattle())
|
||||
SwitchPartyOrder(gBattlerTarget);
|
||||
@ -12483,7 +12531,7 @@ static void Cmd_tryKO(void)
|
||||
if (gCurrentMove == MOVE_SHEER_COLD && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_ICE))
|
||||
odds -= 10;
|
||||
#endif
|
||||
if (Random() % 100 + 1 < odds && gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level)
|
||||
if (RandomPercentage(RNG_ACCURACY, odds) && gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level)
|
||||
lands = TRUE;
|
||||
}
|
||||
|
||||
@ -14699,8 +14747,10 @@ static void Cmd_assistattackselect(void)
|
||||
s32 chooseableMovesNo = 0;
|
||||
struct Pokemon *party;
|
||||
s32 monId, moveId;
|
||||
u16 *validMoves = gBattleStruct->assistPossibleMoves;
|
||||
u16 *validMoves = Alloc(sizeof(u16) * PARTY_SIZE * MAX_MON_MOVES);
|
||||
|
||||
if (validMoves != NULL)
|
||||
{
|
||||
if (GET_BATTLER_SIDE(gBattlerAttacker) != B_SIDE_PLAYER)
|
||||
party = gEnemyParty;
|
||||
else
|
||||
@ -14717,20 +14767,20 @@ static void Cmd_assistattackselect(void)
|
||||
|
||||
for (moveId = 0; moveId < MAX_MON_MOVES; moveId++)
|
||||
{
|
||||
s32 i = 0;
|
||||
u16 move = GetMonData(&party[monId], MON_DATA_MOVE1 + moveId);
|
||||
|
||||
if (sForbiddenMoves[move] & FORBIDDEN_ASSIST)
|
||||
continue;
|
||||
|
||||
validMoves[chooseableMovesNo] = move;
|
||||
chooseableMovesNo++;
|
||||
validMoves[chooseableMovesNo++] = move;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (chooseableMovesNo)
|
||||
{
|
||||
gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED;
|
||||
gCalledMove = validMoves[((Random() & 0xFF) * chooseableMovesNo) >> 8];
|
||||
gCalledMove = validMoves[Random() % chooseableMovesNo];
|
||||
gBattlerTarget = GetMoveTarget(gCalledMove, NO_TARGET_OVERRIDE);
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
@ -14738,6 +14788,8 @@ static void Cmd_assistattackselect(void)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
|
||||
TRY_FREE_AND_SET_NULL(validMoves);
|
||||
}
|
||||
|
||||
static void Cmd_trysetmagiccoat(void)
|
||||
|
@ -798,6 +798,14 @@ static u8 GetSumOfEnemyPartyLevel(u16 opponentId, u8 numMons)
|
||||
sum += party[i].lvl;
|
||||
}
|
||||
break;
|
||||
case F_TRAINER_PARTY_EVERYTHING_CUSTOMIZED:
|
||||
{
|
||||
const struct TrainerMonCustomized *party;
|
||||
party = gTrainers[opponentId].party.EverythingCustomized;
|
||||
for (i = 0; i < count; i++)
|
||||
sum += party[i].lvl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return sum;
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "field_message_box.h"
|
||||
#include "tv.h"
|
||||
#include "battle_factory.h"
|
||||
#include "constants/abilities.h"
|
||||
#include "constants/apprentice.h"
|
||||
#include "constants/battle_dome.h"
|
||||
#include "constants/battle_frontier.h"
|
||||
@ -3007,6 +3008,7 @@ static void FillPartnerParty(u16 trainerId)
|
||||
u16 monId;
|
||||
u32 otID;
|
||||
u8 trainerName[(PLAYER_NAME_LENGTH * 3) + 1];
|
||||
s32 ball = -1;
|
||||
SetFacilityPtrsGetLevel();
|
||||
|
||||
if (trainerId == TRAINER_STEVEN_PARTNER)
|
||||
@ -3098,6 +3100,53 @@ static void FillPartnerParty(u16 trainerId)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case F_TRAINER_PARTY_EVERYTHING_CUSTOMIZED:
|
||||
{
|
||||
const struct TrainerMonCustomized *partyData = gTrainers[trainerId - TRAINER_CUSTOM_PARTNER].party.EverythingCustomized;
|
||||
|
||||
CreateMon(&gPlayerParty[i], partyData[i].species, partyData[i].lvl, 0, TRUE, j, TRUE, otID);
|
||||
SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &partyData[i].heldItem);
|
||||
|
||||
// TODO: Figure out a default strategy when moves are not set, to generate a good moveset
|
||||
for (j = 0; j < MAX_MON_MOVES; ++j)
|
||||
{
|
||||
SetMonData(&gPlayerParty[i], MON_DATA_MOVE1 + j, &partyData[i].moves[j]);
|
||||
SetMonData(&gPlayerParty[i], MON_DATA_PP1 + j, &gBattleMoves[partyData[i].moves[j]].pp);
|
||||
}
|
||||
SetMonData(&gPlayerParty[i], MON_DATA_IVS, &(partyData[i].iv));
|
||||
if (partyData[i].ev != NULL)
|
||||
{
|
||||
SetMonData(&gPlayerParty[i], MON_DATA_HP_EV, &(partyData[i].ev[0]));
|
||||
SetMonData(&gPlayerParty[i], MON_DATA_ATK_EV, &(partyData[i].ev[1]));
|
||||
SetMonData(&gPlayerParty[i], MON_DATA_DEF_EV, &(partyData[i].ev[2]));
|
||||
SetMonData(&gPlayerParty[i], MON_DATA_SPATK_EV, &(partyData[i].ev[3]));
|
||||
SetMonData(&gPlayerParty[i], MON_DATA_SPDEF_EV, &(partyData[i].ev[4]));
|
||||
SetMonData(&gPlayerParty[i], MON_DATA_SPEED_EV, &(partyData[i].ev[5]));
|
||||
}
|
||||
if (partyData[i].ability != ABILITY_NONE)
|
||||
{
|
||||
const struct SpeciesInfo *speciesInfo = &gSpeciesInfo[partyData[i].species];
|
||||
u32 maxAbilities = ARRAY_COUNT(speciesInfo->abilities);
|
||||
for (j = 0; j < maxAbilities; ++j)
|
||||
{
|
||||
if (speciesInfo->abilities[j] == partyData[i].ability)
|
||||
break;
|
||||
}
|
||||
if (j < maxAbilities)
|
||||
SetMonData(&gPlayerParty[i], MON_DATA_ABILITY_NUM, &j);
|
||||
}
|
||||
SetMonData(&gPlayerParty[i], MON_DATA_FRIENDSHIP, &(partyData[i].friendship));
|
||||
if (partyData[i].ball != ITEM_NONE)
|
||||
{
|
||||
ball = partyData[i].ball;
|
||||
SetMonData(&gPlayerParty[i], MON_DATA_POKEBALL, &ball);
|
||||
}
|
||||
if (partyData[i].nickname != NULL)
|
||||
{
|
||||
SetMonData(&gPlayerParty[i], MON_DATA_NICKNAME, partyData[i].nickname);
|
||||
}
|
||||
CalculateMonStats(&gPlayerParty[i]);
|
||||
}
|
||||
}
|
||||
|
||||
StringCopy(trainerName, gTrainers[trainerId - TRAINER_CUSTOM_PARTNER].trainerName);
|
||||
|
@ -2127,15 +2127,22 @@ enum
|
||||
ENDTURN_FIELD_COUNT,
|
||||
};
|
||||
|
||||
static bool32 TryEndTerrain(u32 terrainFlag, u32 stringTableId)
|
||||
static bool32 EndTurnTerrain(u32 terrainFlag, u32 stringTableId)
|
||||
{
|
||||
if (gFieldStatuses & terrainFlag
|
||||
&& (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.terrainTimer == 0))
|
||||
if (gFieldStatuses & terrainFlag)
|
||||
{
|
||||
if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.terrainTimer == 0)
|
||||
{
|
||||
gFieldStatuses &= ~terrainFlag;
|
||||
TryToRevertMimicry();
|
||||
if (!(terrainFlag & STATUS_FIELD_GRASSY_TERRAIN))
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = stringTableId;
|
||||
BattleScriptExecute(BattleScript_TerrainEnds);
|
||||
}
|
||||
}
|
||||
if (terrainFlag & STATUS_FIELD_GRASSY_TERRAIN)
|
||||
BattleScriptExecute(BattleScript_GrassyTerrainHeals);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
@ -2492,19 +2499,19 @@ u8 DoFieldEndTurnEffects(void)
|
||||
gBattleStruct->turnCountersTracker++;
|
||||
break;
|
||||
case ENDTURN_ELECTRIC_TERRAIN:
|
||||
effect = TryEndTerrain(STATUS_FIELD_ELECTRIC_TERRAIN, B_MSG_TERRAINENDS_ELECTRIC);
|
||||
effect = EndTurnTerrain(STATUS_FIELD_ELECTRIC_TERRAIN, B_MSG_TERRAINENDS_ELECTRIC);
|
||||
gBattleStruct->turnCountersTracker++;
|
||||
break;
|
||||
case ENDTURN_MISTY_TERRAIN:
|
||||
effect = TryEndTerrain(STATUS_FIELD_MISTY_TERRAIN, B_MSG_TERRAINENDS_MISTY);
|
||||
effect = EndTurnTerrain(STATUS_FIELD_MISTY_TERRAIN, B_MSG_TERRAINENDS_MISTY);
|
||||
gBattleStruct->turnCountersTracker++;
|
||||
break;
|
||||
case ENDTURN_GRASSY_TERRAIN:
|
||||
effect = TryEndTerrain(STATUS_FIELD_GRASSY_TERRAIN, B_MSG_TERRAINENDS_GRASS);
|
||||
effect = EndTurnTerrain(STATUS_FIELD_GRASSY_TERRAIN, B_MSG_TERRAINENDS_GRASS);
|
||||
gBattleStruct->turnCountersTracker++;
|
||||
break;
|
||||
case ENDTURN_PSYCHIC_TERRAIN:
|
||||
effect = TryEndTerrain(STATUS_FIELD_PSYCHIC_TERRAIN, B_MSG_TERRAINENDS_PSYCHIC);
|
||||
effect = EndTurnTerrain(STATUS_FIELD_PSYCHIC_TERRAIN, B_MSG_TERRAINENDS_PSYCHIC);
|
||||
gBattleStruct->turnCountersTracker++;
|
||||
break;
|
||||
case ENDTURN_WATER_SPORT:
|
||||
@ -3479,7 +3486,7 @@ u8 AtkCanceller_UnableToUseMove(void)
|
||||
case CANCELLER_FROZEN: // check being frozen
|
||||
if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE && !(gBattleMoves[gCurrentMove].flags & FLAG_THAW_USER))
|
||||
{
|
||||
if (Random() % 5)
|
||||
if (!RandomPercentage(RNG_FROZEN, 20))
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_MoveUsedIsFrozen;
|
||||
gHitMarker |= HITMARKER_NO_ATTACKSTRING;
|
||||
@ -3597,9 +3604,9 @@ u8 AtkCanceller_UnableToUseMove(void)
|
||||
{
|
||||
// confusion dmg
|
||||
#if B_CONFUSION_SELF_DMG_CHANCE >= GEN_7
|
||||
if (Random() % 3 == 0)
|
||||
if (RandomWeighted(RNG_CONFUSION, 2, 1))
|
||||
#else
|
||||
if (Random() % 2 == 0)
|
||||
if (RandomWeighted(RNG_CONFUSION, 1, 1))
|
||||
#endif
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = TRUE;
|
||||
@ -3625,7 +3632,7 @@ u8 AtkCanceller_UnableToUseMove(void)
|
||||
gBattleStruct->atkCancellerTracker++;
|
||||
break;
|
||||
case CANCELLER_PARALYSED: // paralysis
|
||||
if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) && (Random() % 4) == 0)
|
||||
if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) && !RandomPercentage(RNG_PARALYSIS, 75))
|
||||
{
|
||||
gProtectStructs[gBattlerAttacker].prlzImmobility = TRUE;
|
||||
// This is removed in FRLG and Emerald for some reason
|
||||
@ -3640,7 +3647,7 @@ u8 AtkCanceller_UnableToUseMove(void)
|
||||
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION)
|
||||
{
|
||||
gBattleScripting.battler = CountTrailingZeroBits((gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) >> 0x10);
|
||||
if (Random() & 1)
|
||||
if (!RandomPercentage(RNG_INFATUATION, 50))
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
}
|
||||
@ -5588,7 +5595,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& CanBePoisoned(gBattlerTarget, gBattlerAttacker)
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker)
|
||||
&& (Random() % 3) == 0)
|
||||
&& RandomWeighted(RNG_POISON_POINT, 2, 1))
|
||||
{
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_POISON;
|
||||
PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility);
|
||||
@ -5606,7 +5613,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& CanBeParalyzed(gBattlerAttacker)
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker)
|
||||
&& (Random() % 3) == 0)
|
||||
&& RandomWeighted(RNG_STATIC, 2, 1))
|
||||
{
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_PARALYSIS;
|
||||
BattleScriptPushCursor();
|
||||
@ -5622,7 +5629,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
&& (IsMoveMakingContact(move, gBattlerAttacker))
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& CanBeBurned(gBattlerAttacker)
|
||||
&& (Random() % 3) == 0)
|
||||
&& RandomWeighted(RNG_FLAME_BODY, 2, 1))
|
||||
{
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_BURN;
|
||||
BattleScriptPushCursor();
|
||||
@ -5638,7 +5645,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
&& (IsMoveMakingContact(move, gBattlerAttacker))
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& gBattleMons[gBattlerTarget].hp != 0
|
||||
&& (Random() % 3) == 0
|
||||
&& RandomWeighted(RNG_CUTE_CHARM, 2, 1)
|
||||
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_OBLIVIOUS
|
||||
&& !IsAbilityOnSide(gBattlerAttacker, ABILITY_AROMA_VEIL)
|
||||
&& GetGenderFromSpeciesAndPersonality(speciesAtk, pidAtk) != GetGenderFromSpeciesAndPersonality(speciesDef, pidDef)
|
||||
@ -5856,7 +5863,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
|
||||
&& gBattleMons[gBattlerTarget].hp != 0
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& (Random() % 10) == 0
|
||||
&& RandomWeighted(RNG_STENCH, 9, 1)
|
||||
&& !IS_MOVE_STATUS(move)
|
||||
&& !sMovesNotAffectedByStench[gCurrentMove])
|
||||
{
|
||||
@ -6487,8 +6494,8 @@ bool32 CanBeFrozen(u8 battlerId)
|
||||
|
||||
bool32 CanBeConfused(u8 battlerId)
|
||||
{
|
||||
if (GetBattlerAbility(gEffectBattler) == ABILITY_OWN_TEMPO
|
||||
|| gBattleMons[gEffectBattler].status2 & STATUS2_CONFUSION
|
||||
if (GetBattlerAbility(battlerId) == ABILITY_OWN_TEMPO
|
||||
|| gBattleMons[battlerId].status2 & STATUS2_CONFUSION
|
||||
|| IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
@ -7576,7 +7583,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
|
||||
if (gBattleMoveDamage != 0 // Need to have done damage
|
||||
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& (Random() % 100) < atkHoldEffectParam
|
||||
&& RandomPercentage(RNG_HOLD_EFFECT_FLINCH, atkHoldEffectParam)
|
||||
&& gBattleMoves[gCurrentMove].flags & FLAG_KINGS_ROCK_AFFECTED
|
||||
&& gBattleMons[gBattlerTarget].hp)
|
||||
{
|
||||
@ -8135,7 +8142,7 @@ u32 GetBattlerHoldEffect(u8 battlerId, bool32 checkNegating)
|
||||
return gBattleStruct->debugHoldEffects[battlerId];
|
||||
else
|
||||
#endif
|
||||
if (gBattleMons[battlerId].item == ITEM_ENIGMA_BERRY)
|
||||
if (gBattleMons[battlerId].item == ITEM_ENIGMA_BERRY_E_READER)
|
||||
return gEnigmaBerries[battlerId].holdEffect;
|
||||
else
|
||||
return ItemId_GetHoldEffect(gBattleMons[battlerId].item);
|
||||
@ -8144,7 +8151,7 @@ u32 GetBattlerHoldEffect(u8 battlerId, bool32 checkNegating)
|
||||
//
|
||||
static u32 GetBattlerItemHoldEffectParam(u8 battlerId, u16 item)
|
||||
{
|
||||
if (item == ITEM_ENIGMA_BERRY)
|
||||
if (item == ITEM_ENIGMA_BERRY_E_READER)
|
||||
return gEnigmaBerries[battlerId].holdEffectParam;
|
||||
else
|
||||
return ItemId_GetHoldEffectParam(item);
|
||||
@ -8152,7 +8159,7 @@ static u32 GetBattlerItemHoldEffectParam(u8 battlerId, u16 item)
|
||||
|
||||
u32 GetBattlerHoldEffectParam(u8 battlerId)
|
||||
{
|
||||
if (gBattleMons[battlerId].item == ITEM_ENIGMA_BERRY)
|
||||
if (gBattleMons[battlerId].item == ITEM_ENIGMA_BERRY_E_READER)
|
||||
return gEnigmaBerries[battlerId].holdEffectParam;
|
||||
else
|
||||
return ItemId_GetHoldEffectParam(gBattleMons[battlerId].item);
|
||||
@ -9057,6 +9064,7 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe
|
||||
if (gBattleMons[battlerDef].hp <= (gBattleMons[battlerDef].maxHP / 2))
|
||||
MulModifier(&modifier, UQ_4_12(2.0));
|
||||
break;
|
||||
case EFFECT_BARB_BARRAGE:
|
||||
case EFFECT_VENOSHOCK:
|
||||
if (gBattleMons[battlerDef].status1 & STATUS1_PSN_ANY)
|
||||
MulModifier(&modifier, UQ_4_12(2.0));
|
||||
@ -9694,7 +9702,7 @@ static s32 DoMoveDamageCalc(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType,
|
||||
// Add a random factor.
|
||||
if (randomFactor)
|
||||
{
|
||||
dmg *= 100 - (Random() % 16);
|
||||
dmg *= 100 - RandomUniform(RNG_DAMAGE_MODIFIER, 0, 15);
|
||||
dmg /= 100;
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,7 @@ bool32 IsViableZMove(u8 battlerId, u16 move)
|
||||
holdEffect = gBattleStruct->debugHoldEffects[battlerId];
|
||||
else
|
||||
#endif
|
||||
if (item == ITEM_ENIGMA_BERRY)
|
||||
if (item == ITEM_ENIGMA_BERRY_E_READER)
|
||||
return FALSE; // HoldEffect = gEnigmaBerries[battlerId].holdEffect;
|
||||
else
|
||||
holdEffect = ItemId_GetHoldEffect(item);
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "battle.h"
|
||||
#include "data.h"
|
||||
#include "graphics.h"
|
||||
#include "constants/abilities.h"
|
||||
#include "constants/items.h"
|
||||
#include "constants/moves.h"
|
||||
#include "constants/trainers.h"
|
||||
|
@ -12452,11 +12452,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] =
|
||||
#else
|
||||
.power = 60,
|
||||
#endif
|
||||
.effect = EFFECT_PLACEHOLDER, // EFFECT_DIRE_CLAW,
|
||||
.effect = EFFECT_DIRE_CLAW,
|
||||
.type = TYPE_POISON,
|
||||
.accuracy = 100,
|
||||
.pp = 15,
|
||||
.secondaryEffectChance = 0,
|
||||
.secondaryEffectChance = 50,
|
||||
.target = MOVE_TARGET_SELECTED,
|
||||
.priority = 0,
|
||||
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST,
|
||||
@ -12496,17 +12496,18 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] =
|
||||
|
||||
[MOVE_STONE_AXE] =
|
||||
{
|
||||
.effect = EFFECT_PLACEHOLDER, // EFFECT_STONE_AXE,
|
||||
.effect = EFFECT_HIT_SET_ENTRY_HAZARD,
|
||||
.power = 65,
|
||||
.type = TYPE_ROCK,
|
||||
.accuracy = 90,
|
||||
.pp = 15,
|
||||
.secondaryEffectChance = 0,
|
||||
.target = MOVE_TARGET_USER,
|
||||
.secondaryEffectChance = 100,
|
||||
.target = MOVE_TARGET_SELECTED,
|
||||
.priority = 0,
|
||||
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST | FLAG_SLICING_MOVE,
|
||||
.split = SPLIT_PHYSICAL,
|
||||
.zMoveEffect = Z_EFFECT_NONE,
|
||||
.argument = MOVE_EFFECT_STEALTH_ROCK,
|
||||
},
|
||||
|
||||
[MOVE_SPRINGTIDE_STORM] =
|
||||
@ -12651,12 +12652,16 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] =
|
||||
|
||||
[MOVE_BARB_BARRAGE] =
|
||||
{
|
||||
.effect = EFFECT_PLACEHOLDER, // EFFECT_BARB_BARRAGE,
|
||||
.effect = EFFECT_BARB_BARRAGE,
|
||||
.power = 60,
|
||||
.type = TYPE_POISON,
|
||||
.accuracy = 100,
|
||||
#if B_UPDATED_MOVE_DATA >= GEN_9
|
||||
.pp = 10,
|
||||
#else
|
||||
.pp = 15,
|
||||
.secondaryEffectChance = 0,
|
||||
#endif
|
||||
.secondaryEffectChance = 50,
|
||||
.target = MOVE_TARGET_SELECTED,
|
||||
.priority = 0,
|
||||
.flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST,
|
||||
@ -12753,17 +12758,18 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] =
|
||||
|
||||
[MOVE_CEASELESS_EDGE] =
|
||||
{
|
||||
.effect = EFFECT_PLACEHOLDER, // EFFECT_CEASELESS_EDGE,
|
||||
.effect = EFFECT_HIT_SET_ENTRY_HAZARD,
|
||||
.power = 65,
|
||||
.type = TYPE_DARK,
|
||||
.accuracy = 90,
|
||||
.pp = 15,
|
||||
.secondaryEffectChance = 0,
|
||||
.secondaryEffectChance = 100,
|
||||
.target = MOVE_TARGET_SELECTED,
|
||||
.priority = 0,
|
||||
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST | FLAG_SLICING_MOVE,
|
||||
.split = SPLIT_PHYSICAL,
|
||||
.zMoveEffect = Z_EFFECT_NONE,
|
||||
.argument = MOVE_EFFECT_SPIKES,
|
||||
},
|
||||
|
||||
[MOVE_BLEAKWIND_STORM] =
|
||||
|
@ -1931,17 +1931,61 @@ const u32 gItemIconPalette_Ruby[] = INCBIN_U32("graphics/items/icon_palettes/rub
|
||||
|
||||
const u32 gItemIconPalette_Sapphire[] = INCBIN_U32("graphics/items/icon_palettes/sapphire.gbapal.lz");
|
||||
|
||||
//const u32 gItemIcon_AbilityShield[] = INCBIN_U32("graphics/items/icons/ability_shield.4bpp.lz");
|
||||
//const u32 gItemIconPalette_AbilityShield[] = INCBIN_U32("graphics/items/icon_palettes/ability_shield.gbapal.lz");
|
||||
const u32 gItemIcon_AbilityShield[] = INCBIN_U32("graphics/items/icons/ability_shield.4bpp.lz");
|
||||
const u32 gItemIconPalette_AbilityShield[] = INCBIN_U32("graphics/items/icon_palettes/ability_shield.gbapal.lz");
|
||||
|
||||
//const u32 gItemIcon_ClearAmulet[] = INCBIN_U32("graphics/items/icons/clear_amulet.4bpp.lz");
|
||||
//const u32 gItemIconPalette_ClearAmulet[] = INCBIN_U32("graphics/items/icon_palettes/clear_amulet.gbapal.lz");
|
||||
|
||||
//const u32 gItemIcon_PunchingGlove[] = INCBIN_U32("graphics/items/icons/punching_glove.4bpp.lz");
|
||||
//const u32 gItemIconPalette_PunchingGlove[] = INCBIN_U32("graphics/items/icon_palettes/punching_glove.gbapal.lz");
|
||||
const u32 gItemIcon_PunchingGlove[] = INCBIN_U32("graphics/items/icons/punching_glove.4bpp.lz");
|
||||
const u32 gItemIconPalette_PunchingGlove[] = INCBIN_U32("graphics/items/icon_palettes/punching_glove.gbapal.lz");
|
||||
|
||||
//const u32 gItemIcon_CovertCloak[] = INCBIN_U32("graphics/items/icons/covert_cloak.4bpp.lz");
|
||||
//const u32 gItemIconPalette_CovertCloak[] = INCBIN_U32("graphics/items/icon_palettes/covert_cloak.gbapal.lz");
|
||||
const u32 gItemIcon_CovertCloak[] = INCBIN_U32("graphics/items/icons/covert_cloak.4bpp.lz");
|
||||
const u32 gItemIconPalette_CovertCloak[] = INCBIN_U32("graphics/items/icon_palettes/covert_cloak.gbapal.lz");
|
||||
|
||||
//const u32 gItemIcon_LoadedDice[] = INCBIN_U32("graphics/items/icons/loaded_dice.4bpp.lz");
|
||||
//const u32 gItemIconPalette_LoadedDice[] = INCBIN_U32("graphics/items/icon_palettes/loaded_dice.gbapal.lz");
|
||||
const u32 gItemIcon_LoadedDice[] = INCBIN_U32("graphics/items/icons/loaded_dice.4bpp.lz");
|
||||
const u32 gItemIconPalette_LoadedDice[] = INCBIN_U32("graphics/items/icon_palettes/loaded_dice.gbapal.lz");
|
||||
|
||||
const u32 gItemIcon_AuspiciousArmor[] = INCBIN_U32("graphics/items/icons/auspicious_armor.4bpp.lz");
|
||||
const u32 gItemIconPalette_AuspiciousArmor[] = INCBIN_U32("graphics/items/icon_palettes/auspicious_armor.gbapal.lz");
|
||||
|
||||
const u32 gItemIcon_BigBambooShoot[] = INCBIN_U32("graphics/items/icons/big_bamboo_shoot.4bpp.lz");
|
||||
const u32 gItemIconPalette_BigBambooShoot[] = INCBIN_U32("graphics/items/icon_palettes/big_bamboo_shoot.gbapal.lz");
|
||||
|
||||
const u32 gItemIcon_BoosterEnergy[] = INCBIN_U32("graphics/items/icons/booster_energy.4bpp.lz");
|
||||
const u32 gItemIconPalette_BoosterEnergy[] = INCBIN_U32("graphics/items/icon_palettes/booster_energy.gbapal.lz");
|
||||
|
||||
const u32 gItemIcon_GimmighoulCoin[] = INCBIN_U32("graphics/items/icons/gimmighoul_coin.4bpp.lz");
|
||||
const u32 gItemIconPalette_GimmighoulCoin[] = INCBIN_U32("graphics/items/icon_palettes/gimmighoul_coin.gbapal.lz");
|
||||
|
||||
const u32 gItemIcon_LeadersCrest[] = INCBIN_U32("graphics/items/icons/leaders_crest.4bpp.lz");
|
||||
const u32 gItemIconPalette_LeadersCrest[] = INCBIN_U32("graphics/items/icon_palettes/leaders_crest.gbapal.lz");
|
||||
|
||||
const u32 gItemIcon_MaliciousArmor[] = INCBIN_U32("graphics/items/icons/malicious_armor.4bpp.lz");
|
||||
const u32 gItemIconPalette_MaliciousArmor[] = INCBIN_U32("graphics/items/icon_palettes/malicious_armor.gbapal.lz");
|
||||
|
||||
const u32 gItemIcon_MirrorHerb[] = INCBIN_U32("graphics/items/icons/mirror_herb.4bpp.lz");
|
||||
const u32 gItemIconPalette_MirrorHerb[] = INCBIN_U32("graphics/items/icon_palettes/mirror_herb.gbapal.lz");
|
||||
|
||||
const u32 gItemIcon_ScrollOfDarkness[] = INCBIN_U32("graphics/items/icons/scroll_of_darkness.4bpp.lz");
|
||||
const u32 gItemIconPalette_ScrollOfDarkness[] = INCBIN_U32("graphics/items/icon_palettes/scroll_of_darkness.gbapal.lz");
|
||||
|
||||
const u32 gItemIcon_ScrollOfWaters[] = INCBIN_U32("graphics/items/icons/scroll_of_waters.4bpp.lz");
|
||||
const u32 gItemIconPalette_ScrollOfWaters[] = INCBIN_U32("graphics/items/icon_palettes/scroll_of_waters.gbapal.lz");
|
||||
|
||||
const u32 gItemIcon_TeraOrb[] = INCBIN_U32("graphics/items/icons/tera_orb.4bpp.lz");
|
||||
const u32 gItemIconPalette_TeraOrb[] = INCBIN_U32("graphics/items/icon_palettes/tera_orb.gbapal.lz");
|
||||
|
||||
const u32 gItemIcon_TinyBambooShoot[] = INCBIN_U32("graphics/items/icons/tiny_bamboo_shoot.4bpp.lz");
|
||||
const u32 gItemIconPalette_TinyBambooShoot[] = INCBIN_U32("graphics/items/icon_palettes/tiny_bamboo_shoot.gbapal.lz");
|
||||
|
||||
// Tera Shards here
|
||||
|
||||
const u32 gItemIcon_AdamantCrystal[] = INCBIN_U32("graphics/items/icons/adamant_crystal.4bpp.lz");
|
||||
const u32 gItemIconPalette_AdamantCrystal[] = INCBIN_U32("graphics/items/icon_palettes/adamant_crystal.gbapal.lz");
|
||||
|
||||
const u32 gItemIcon_GriseousCore[] = INCBIN_U32("graphics/items/icons/griseous_core.4bpp.lz");
|
||||
const u32 gItemIconPalette_GriseousCore[] = INCBIN_U32("graphics/items/icon_palettes/griseous_core.gbapal.lz");
|
||||
|
||||
const u32 gItemIcon_LustrousGlobe[] = INCBIN_U32("graphics/items/icons/lustrous_globe.4bpp.lz");
|
||||
const u32 gItemIconPalette_LustrousGlobe[] = INCBIN_U32("graphics/items/icon_palettes/lustrous_globe.gbapal.lz");
|
||||
|
@ -803,11 +803,43 @@ const u32 *const gItemIconTable[ITEMS_COUNT + 1][2] =
|
||||
[ITEM_TEA] = {gItemIcon_Tea, gItemIconPalette_Tea},
|
||||
[ITEM_RUBY] = {gItemIcon_Gem, gItemIconPalette_Ruby},
|
||||
[ITEM_SAPPHIRE] = {gItemIcon_Gem, gItemIconPalette_Sapphire},
|
||||
[ITEM_ABILITY_SHIELD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_AbilityShield, gItemIconPalette_AbilityShield},
|
||||
[ITEM_ABILITY_SHIELD] = {gItemIcon_AbilityShield, gItemIconPalette_AbilityShield},
|
||||
[ITEM_CLEAR_AMULET] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_ClearAmulet, gItemIconPalette_ClearAmulet},
|
||||
[ITEM_PUNCHING_GLOVE] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_PunchingGlove, gItemIconPalette_PunchingGlove},
|
||||
[ITEM_COVERT_CLOAK] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_CovertCloak, gItemIconPalette_CovertCloak},
|
||||
[ITEM_LOADED_DICE] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_LoadedDice, gItemIconPalette_LoadedDice},
|
||||
[ITEM_PUNCHING_GLOVE] = {gItemIcon_PunchingGlove, gItemIconPalette_PunchingGlove},
|
||||
[ITEM_COVERT_CLOAK] = {gItemIcon_CovertCloak, gItemIconPalette_CovertCloak},
|
||||
[ITEM_LOADED_DICE] = {gItemIcon_LoadedDice, gItemIconPalette_LoadedDice},
|
||||
[ITEM_AUSPICIOUS_ARMOR] = {gItemIcon_AuspiciousArmor, gItemIconPalette_AuspiciousArmor},
|
||||
[ITEM_BOOSTER_ENERGY] = {gItemIcon_BoosterEnergy, gItemIconPalette_BoosterEnergy},
|
||||
[ITEM_BIG_BAMBOO_SHOOT] = {gItemIcon_BigBambooShoot, gItemIconPalette_BigBambooShoot},
|
||||
[ITEM_GIMMIGHOUL_COIN] = {gItemIcon_GimmighoulCoin, gItemIconPalette_GimmighoulCoin},
|
||||
[ITEM_LEADERS_CREST] = {gItemIcon_LeadersCrest, gItemIconPalette_LeadersCrest},
|
||||
[ITEM_MALICIOUS_ARMOR] = {gItemIcon_MaliciousArmor, gItemIconPalette_MaliciousArmor},
|
||||
[ITEM_MIRROR_HERB] = {gItemIcon_MirrorHerb, gItemIconPalette_MirrorHerb},
|
||||
[ITEM_SCROLL_OF_DARKNESS] = {gItemIcon_ScrollOfDarkness, gItemIconPalette_ScrollOfDarkness},
|
||||
[ITEM_SCROLL_OF_WATERS] = {gItemIcon_ScrollOfWaters, gItemIconPalette_ScrollOfWaters},
|
||||
[ITEM_TERA_ORB] = {gItemIcon_TeraOrb, gItemIconPalette_TeraOrb},
|
||||
[ITEM_TINY_BAMBOO_SHOOT] = {gItemIcon_TinyBambooShoot, gItemIconPalette_TinyBambooShoot},
|
||||
[ITEM_BUG_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_BugTeraShard, gItemIconPalette_BugTeraShard},
|
||||
[ITEM_DARK_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_DarkTeraShard, gItemIconPalette_DarkTeraShard},
|
||||
[ITEM_DRAGON_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_DragonTeraShard, gItemIconPalette_DragonTeraShard},
|
||||
[ITEM_ELECTRIC_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_ElectricTeraShard, gItemIconPalette_ElectricTeraShard},
|
||||
[ITEM_FAIRY_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_FairyTeraShard, gItemIconPalette_FairyTeraShard},
|
||||
[ITEM_FIGHTING_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_FightingTeraShard, gItemIconPalette_FightingTeraShard},
|
||||
[ITEM_FIRE_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_FireTeraShard, gItemIconPalette_FireTeraShard},
|
||||
[ITEM_FLYING_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_FlyingTeraShard, gItemIconPalette_FlyingTeraShard},
|
||||
[ITEM_GHOST_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_GhostTeraShard, gItemIconPalette_GhostTeraShard},
|
||||
[ITEM_GRASS_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_GrassTeraShard, gItemIconPalette_GrassTeraShard},
|
||||
[ITEM_GROUND_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_GroundTeraShard, gItemIconPalette_GroundTeraShard},
|
||||
[ITEM_ICE_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_IceTeraShard, gItemIconPalette_IceTeraShard},
|
||||
[ITEM_NORMAL_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_NormalTeraShard, gItemIconPalette_NormalTeraShard},
|
||||
[ITEM_POISON_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_PoisonTeraShard, gItemIconPalette_PoisonTeraShard},
|
||||
[ITEM_PSYCHIC_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_PsychicTeraShard, gItemIconPalette_PsychicTeraShard},
|
||||
[ITEM_ROCK_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_RockTeraShard, gItemIconPalette_RockTeraShard},
|
||||
[ITEM_STEEL_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_SteelTeraShard, gItemIconPalette_SteelTeraShard},
|
||||
[ITEM_WATER_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_WaterTeraShard, gItemIconPalette_WaterTeraShard},
|
||||
[ITEM_ADAMANT_CRYSTAL] = {gItemIcon_AdamantCrystal, gItemIconPalette_AdamantCrystal},
|
||||
[ITEM_GRISEOUS_CORE] = {gItemIcon_GriseousCore, gItemIconPalette_GriseousCore},
|
||||
[ITEM_LUSTROUS_GLOBE] = {gItemIcon_LustrousGlobe, gItemIconPalette_LustrousGlobe},
|
||||
// Return to field arrow
|
||||
[ITEMS_COUNT] = {gItemIcon_ReturnToFieldArrow, gItemIconPalette_ReturnToFieldArrow},
|
||||
};
|
||||
|
367
src/data/items.h
@ -9896,7 +9896,6 @@ const struct Item gItems[] =
|
||||
|
||||
[ITEM_LOADED_DICE] =
|
||||
{
|
||||
//YellwApricorn
|
||||
.name = _("Loaded Dice"),
|
||||
.itemId = ITEM_LOADED_DICE,
|
||||
.price = 20000,
|
||||
@ -9907,4 +9906,370 @@ const struct Item gItems[] =
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
.flingPower = 30,
|
||||
},
|
||||
|
||||
[ITEM_AUSPICIOUS_ARMOR] =
|
||||
{
|
||||
.name = _("AuspciousArmr"),
|
||||
.itemId = ITEM_AUSPICIOUS_ARMOR,
|
||||
.price = 3000,
|
||||
.description = sAuspiciousArmorDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_PARTY_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_EvolutionStone,
|
||||
.flingPower = 30,
|
||||
},
|
||||
|
||||
[ITEM_BOOSTER_ENERGY] =
|
||||
{
|
||||
.name = _("BoosterEnergy"),
|
||||
.itemId = ITEM_BOOSTER_ENERGY,
|
||||
.price = 0,
|
||||
.holdEffect = HOLD_EFFECT_BOOSTER_ENERGY,
|
||||
.description = sBoosterEnergyDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
.flingPower = 30,
|
||||
},
|
||||
|
||||
[ITEM_BIG_BAMBOO_SHOOT] =
|
||||
{
|
||||
.name = _("BigBmbooShoot"),
|
||||
.itemId = ITEM_BIG_BAMBOO_SHOOT,
|
||||
.price = 3000,
|
||||
.description = sBigBambooShootDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
.flingPower = 30,
|
||||
},
|
||||
|
||||
[ITEM_GIMMIGHOUL_COIN] =
|
||||
{
|
||||
.name = _("GimighoulCoin"),
|
||||
.itemId = ITEM_GIMMIGHOUL_COIN,
|
||||
.price = 400,
|
||||
.description = sGimmighoulCoinDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_LEADERS_CREST] =
|
||||
{
|
||||
.name = _("Leader'sCrest"),
|
||||
.itemId = ITEM_LEADERS_CREST,
|
||||
.price = 3000,
|
||||
.description = sLeadersCrestDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_MALICIOUS_ARMOR] =
|
||||
{
|
||||
.name = _("MaliciousArmr"),
|
||||
.itemId = ITEM_MALICIOUS_ARMOR,
|
||||
.price = 3000,
|
||||
.description = sMaliciousArmorDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_PARTY_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_EvolutionStone,
|
||||
.flingPower = 30,
|
||||
},
|
||||
|
||||
[ITEM_MIRROR_HERB] =
|
||||
{
|
||||
.name = _("Mirror Herb"),
|
||||
.itemId = ITEM_MIRROR_HERB,
|
||||
.price = 30000,
|
||||
.holdEffect = HOLD_EFFECT_MIRROR_HERB,
|
||||
.description = sMirrorHerbDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
.flingPower = 30,
|
||||
},
|
||||
|
||||
[ITEM_SCROLL_OF_DARKNESS] =
|
||||
{
|
||||
.name = _("ScrllOfDrknss"),
|
||||
.itemId = ITEM_SCROLL_OF_DARKNESS,
|
||||
.price = 0,
|
||||
.description = sScrollOfDarknessDesc,
|
||||
.importance = 1,
|
||||
.pocket = POCKET_KEY_ITEMS,
|
||||
.type = ITEM_USE_PARTY_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_EvolutionStone,
|
||||
},
|
||||
|
||||
[ITEM_SCROLL_OF_WATERS] =
|
||||
{
|
||||
.name = _("ScrollOfWatrs"),
|
||||
.itemId = ITEM_SCROLL_OF_WATERS,
|
||||
.price = 0,
|
||||
.description = sScrollOfWatersDesc,
|
||||
.importance = 1,
|
||||
.pocket = POCKET_KEY_ITEMS,
|
||||
.type = ITEM_USE_PARTY_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_EvolutionStone,
|
||||
},
|
||||
|
||||
[ITEM_TERA_ORB] =
|
||||
{
|
||||
.name = _("Tera Orb"),
|
||||
.itemId = ITEM_TERA_ORB,
|
||||
.price = 0,
|
||||
.description = sTeraOrbDesc,
|
||||
.importance = 1,
|
||||
.pocket = POCKET_KEY_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_TINY_BAMBOO_SHOOT] =
|
||||
{
|
||||
.name = _("TinyBmbooShot"),
|
||||
.itemId = ITEM_TINY_BAMBOO_SHOOT,
|
||||
.price = 750,
|
||||
.description = sTinyBambooShootDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
.flingPower = 30,
|
||||
},
|
||||
|
||||
[ITEM_BUG_TERA_SHARD] =
|
||||
{
|
||||
.name = _("Bug TeraShard"),
|
||||
.itemId = ITEM_BUG_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_DARK_TERA_SHARD] =
|
||||
{
|
||||
.name = _("DarkTeraShard"),
|
||||
.itemId = ITEM_DARK_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_DRAGON_TERA_SHARD] =
|
||||
{
|
||||
.name = _("DragnTeraShrd"),
|
||||
.itemId = ITEM_DRAGON_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_ELECTRIC_TERA_SHARD] =
|
||||
{
|
||||
.name = _("EltrcTeraShrd"),
|
||||
.itemId = ITEM_ELECTRIC_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_FAIRY_TERA_SHARD] =
|
||||
{
|
||||
.name = _("FairyTeraShrd"),
|
||||
.itemId = ITEM_FAIRY_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_FIGHTING_TERA_SHARD] =
|
||||
{
|
||||
.name = _("FghtngTerShrd"),
|
||||
.itemId = ITEM_FIGHTING_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_FIRE_TERA_SHARD] =
|
||||
{
|
||||
.name = _("FireTeraShard"),
|
||||
.itemId = ITEM_FIRE_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_FLYING_TERA_SHARD] =
|
||||
{
|
||||
.name = _("FlyngTeraShrd"),
|
||||
.itemId = ITEM_FLYING_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_GHOST_TERA_SHARD] =
|
||||
{
|
||||
.name = _("GhostTeraShrd"),
|
||||
.itemId = ITEM_GHOST_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_GRASS_TERA_SHARD] =
|
||||
{
|
||||
.name = _("GrassTeraShrd"),
|
||||
.itemId = ITEM_GRASS_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_GROUND_TERA_SHARD] =
|
||||
{
|
||||
.name = _("GrondTeraShrd"),
|
||||
.itemId = ITEM_GROUND_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_ICE_TERA_SHARD] =
|
||||
{
|
||||
.name = _("Ice TeraShard"),
|
||||
.itemId = ITEM_ICE_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_NORMAL_TERA_SHARD] =
|
||||
{
|
||||
.name = _("NormlTeraShrd"),
|
||||
.itemId = ITEM_NORMAL_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_POISON_TERA_SHARD] =
|
||||
{
|
||||
.name = _("PoisnTeraShrd"),
|
||||
.itemId = ITEM_POISON_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_PSYCHIC_TERA_SHARD] =
|
||||
{
|
||||
.name = _("PschcTeraShrd"),
|
||||
.itemId = ITEM_PSYCHIC_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_ROCK_TERA_SHARD] =
|
||||
{
|
||||
.name = _("RockTeraShard"),
|
||||
.itemId = ITEM_ROCK_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_STEEL_TERA_SHARD] =
|
||||
{
|
||||
.name = _("SteelTeraShrd"),
|
||||
.itemId = ITEM_STEEL_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_WATER_TERA_SHARD] =
|
||||
{
|
||||
.name = _("WaterTeraShrd"),
|
||||
.itemId = ITEM_WATER_TERA_SHARD,
|
||||
.price = 0,
|
||||
.description = sTeraShardDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
},
|
||||
|
||||
[ITEM_ADAMANT_CRYSTAL] =
|
||||
{
|
||||
.name = _("AdamantCrystl"),
|
||||
.itemId = ITEM_ADAMANT_CRYSTAL,
|
||||
.price = 0,
|
||||
.description = sAdamantCrystalDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
.flingPower = 60,
|
||||
},
|
||||
|
||||
[ITEM_GRISEOUS_CORE] =
|
||||
{
|
||||
.name = _("Griseous Core"),
|
||||
.itemId = ITEM_GRISEOUS_CORE,
|
||||
.price = 0,
|
||||
.description = sGriseousCoreDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
.flingPower = 60,
|
||||
},
|
||||
|
||||
[ITEM_LUSTROUS_GLOBE] =
|
||||
{
|
||||
.name = _("LustrousGlobe"),
|
||||
.itemId = ITEM_LUSTROUS_GLOBE,
|
||||
.price = 0,
|
||||
.description = sLustrousGlobeDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
|
||||
.flingPower = 60,
|
||||
},
|
||||
};
|
||||
|
@ -491,7 +491,9 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] =
|
||||
[SPECIES_DREEPY] = {{EVO_LEVEL, 50, SPECIES_DRAKLOAK}},
|
||||
[SPECIES_DRAKLOAK] = {{EVO_LEVEL, 60, SPECIES_DRAGAPULT}},
|
||||
[SPECIES_KUBFU] = {{EVO_DARK_SCROLL, 0, SPECIES_URSHIFU},
|
||||
{EVO_WATER_SCROLL, 0, SPECIES_URSHIFU_RAPID_STRIKE_STYLE}},
|
||||
{EVO_ITEM, ITEM_SCROLL_OF_DARKNESS, SPECIES_URSHIFU},
|
||||
{EVO_WATER_SCROLL, 0, SPECIES_URSHIFU_RAPID_STRIKE_STYLE},
|
||||
{EVO_ITEM, ITEM_SCROLL_OF_WATERS, SPECIES_URSHIFU_RAPID_STRIKE_STYLE}},
|
||||
#endif
|
||||
[SPECIES_RATTATA_ALOLAN] = {{EVO_LEVEL_NIGHT, 20, SPECIES_RATICATE_ALOLAN}},
|
||||
[SPECIES_SANDSHREW_ALOLAN] = {{EVO_ITEM, ITEM_ICE_STONE, SPECIES_SANDSLASH_ALOLAN}},
|
||||
|
@ -98,6 +98,10 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] =
|
||||
[SPECIES_ABOMASNOW_MEGA] = sAbomasnowFormChangeTable,
|
||||
[SPECIES_GALLADE] = sGalladeFormChangeTable,
|
||||
[SPECIES_GALLADE_MEGA] = sGalladeFormChangeTable,
|
||||
[SPECIES_DIALGA] = sDialgaFormChangeTable,
|
||||
[SPECIES_DIALGA_ORIGIN] = sDialgaFormChangeTable,
|
||||
[SPECIES_PALKIA] = sPalkiaFormChangeTable,
|
||||
[SPECIES_PALKIA_ORIGIN] = sPalkiaFormChangeTable,
|
||||
[SPECIES_GIRATINA] = sGiratinaFormChangeTable,
|
||||
[SPECIES_GIRATINA_ORIGIN] = sGiratinaFormChangeTable,
|
||||
[SPECIES_SHAYMIN] = sShayminFormChangeTable,
|
||||
|
@ -243,9 +243,24 @@ static const struct FormChange sGalladeFormChangeTable[] = {
|
||||
{FORM_CHANGE_TERMINATOR},
|
||||
};
|
||||
|
||||
static const struct FormChange sDialgaFormChangeTable[] = {
|
||||
{FORM_CHANGE_ITEM_HOLD, SPECIES_DIALGA, ITEM_NONE},
|
||||
{FORM_CHANGE_ITEM_HOLD, SPECIES_DIALGA_ORIGIN, ITEM_ADAMANT_CRYSTAL},
|
||||
{FORM_CHANGE_TERMINATOR},
|
||||
};
|
||||
|
||||
static const struct FormChange sPalkiaFormChangeTable[] = {
|
||||
{FORM_CHANGE_ITEM_HOLD, SPECIES_PALKIA, ITEM_NONE},
|
||||
{FORM_CHANGE_ITEM_HOLD, SPECIES_PALKIA_ORIGIN, ITEM_LUSTROUS_GLOBE},
|
||||
{FORM_CHANGE_TERMINATOR},
|
||||
};
|
||||
|
||||
static const struct FormChange sGiratinaFormChangeTable[] = {
|
||||
{FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA, ITEM_NONE},
|
||||
#if I_GRISEOUS_ORB_FORM_CHANGE < GEN_9
|
||||
{FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA_ORIGIN, ITEM_GRISEOUS_ORB},
|
||||
#endif
|
||||
{FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA_ORIGIN, ITEM_GRISEOUS_CORE},
|
||||
{FORM_CHANGE_TERMINATOR},
|
||||
};
|
||||
|
||||
|
@ -447,128 +447,132 @@ const u8 gItemEffect_TamatoBerry[10] = {
|
||||
EV_BERRY_FRIENDSHIP_CHANGE,
|
||||
};
|
||||
|
||||
const u8 *const gItemEffectTable[] =
|
||||
const u8 *const gItemEffectTable[ITEMS_COUNT] =
|
||||
{
|
||||
// Medicine
|
||||
[ITEM_POTION - ITEM_POTION] = gItemEffect_Potion,
|
||||
[ITEM_SUPER_POTION - ITEM_POTION] = gItemEffect_SuperPotion,
|
||||
[ITEM_HYPER_POTION - ITEM_POTION] = gItemEffect_HyperPotion,
|
||||
[ITEM_MAX_POTION - ITEM_POTION] = gItemEffect_MaxPotion,
|
||||
[ITEM_FULL_RESTORE - ITEM_POTION] = gItemEffect_FullRestore,
|
||||
[ITEM_REVIVE - ITEM_POTION] = gItemEffect_Revive,
|
||||
[ITEM_MAX_REVIVE - ITEM_POTION] = gItemEffect_MaxRevive,
|
||||
[ITEM_FRESH_WATER - ITEM_POTION] = gItemEffect_FreshWater,
|
||||
[ITEM_SODA_POP - ITEM_POTION] = gItemEffect_SodaPop,
|
||||
[ITEM_LEMONADE - ITEM_POTION] = gItemEffect_Lemonade,
|
||||
[ITEM_MOOMOO_MILK - ITEM_POTION] = gItemEffect_MoomooMilk,
|
||||
[ITEM_ENERGY_POWDER - ITEM_POTION] = gItemEffect_EnergyPowder,
|
||||
[ITEM_ENERGY_ROOT - ITEM_POTION] = gItemEffect_EnergyRoot,
|
||||
[ITEM_HEAL_POWDER - ITEM_POTION] = gItemEffect_HealPowder,
|
||||
[ITEM_REVIVAL_HERB - ITEM_POTION] = gItemEffect_RevivalHerb,
|
||||
[ITEM_ANTIDOTE - ITEM_POTION] = gItemEffect_Antidote,
|
||||
[ITEM_PARALYZE_HEAL - ITEM_POTION] = gItemEffect_ParalyzeHeal,
|
||||
[ITEM_BURN_HEAL - ITEM_POTION] = gItemEffect_BurnHeal,
|
||||
[ITEM_ICE_HEAL - ITEM_POTION] = gItemEffect_IceHeal,
|
||||
[ITEM_AWAKENING - ITEM_POTION] = gItemEffect_Awakening,
|
||||
[ITEM_FULL_HEAL - ITEM_POTION] = gItemEffect_FullHeal,
|
||||
[ITEM_ETHER - ITEM_POTION] = gItemEffect_Ether,
|
||||
[ITEM_MAX_ETHER - ITEM_POTION] = gItemEffect_MaxEther,
|
||||
[ITEM_ELIXIR - ITEM_POTION] = gItemEffect_Elixir,
|
||||
[ITEM_MAX_ELIXIR - ITEM_POTION] = gItemEffect_MaxElixir,
|
||||
[ITEM_BERRY_JUICE - ITEM_POTION] = gItemEffect_BerryJuice,
|
||||
[ITEM_SACRED_ASH - ITEM_POTION] = gItemEffect_SacredAsh,
|
||||
[ITEM_SWEET_HEART - ITEM_POTION] = gItemEffect_Potion,
|
||||
[ITEM_MAX_HONEY - ITEM_POTION] = gItemEffect_MaxRevive,
|
||||
[ITEM_POTION] = gItemEffect_Potion,
|
||||
[ITEM_SUPER_POTION] = gItemEffect_SuperPotion,
|
||||
[ITEM_HYPER_POTION] = gItemEffect_HyperPotion,
|
||||
[ITEM_MAX_POTION] = gItemEffect_MaxPotion,
|
||||
[ITEM_FULL_RESTORE] = gItemEffect_FullRestore,
|
||||
[ITEM_REVIVE] = gItemEffect_Revive,
|
||||
[ITEM_MAX_REVIVE] = gItemEffect_MaxRevive,
|
||||
[ITEM_FRESH_WATER] = gItemEffect_FreshWater,
|
||||
[ITEM_SODA_POP] = gItemEffect_SodaPop,
|
||||
[ITEM_LEMONADE] = gItemEffect_Lemonade,
|
||||
[ITEM_MOOMOO_MILK] = gItemEffect_MoomooMilk,
|
||||
[ITEM_ENERGY_POWDER] = gItemEffect_EnergyPowder,
|
||||
[ITEM_ENERGY_ROOT] = gItemEffect_EnergyRoot,
|
||||
[ITEM_HEAL_POWDER] = gItemEffect_HealPowder,
|
||||
[ITEM_REVIVAL_HERB] = gItemEffect_RevivalHerb,
|
||||
[ITEM_ANTIDOTE] = gItemEffect_Antidote,
|
||||
[ITEM_PARALYZE_HEAL] = gItemEffect_ParalyzeHeal,
|
||||
[ITEM_BURN_HEAL] = gItemEffect_BurnHeal,
|
||||
[ITEM_ICE_HEAL] = gItemEffect_IceHeal,
|
||||
[ITEM_AWAKENING] = gItemEffect_Awakening,
|
||||
[ITEM_FULL_HEAL] = gItemEffect_FullHeal,
|
||||
[ITEM_ETHER] = gItemEffect_Ether,
|
||||
[ITEM_MAX_ETHER] = gItemEffect_MaxEther,
|
||||
[ITEM_ELIXIR] = gItemEffect_Elixir,
|
||||
[ITEM_MAX_ELIXIR] = gItemEffect_MaxElixir,
|
||||
[ITEM_BERRY_JUICE] = gItemEffect_BerryJuice,
|
||||
[ITEM_SACRED_ASH] = gItemEffect_SacredAsh,
|
||||
[ITEM_SWEET_HEART] = gItemEffect_Potion,
|
||||
[ITEM_MAX_HONEY] = gItemEffect_MaxRevive,
|
||||
|
||||
// Regional Specialties
|
||||
[ITEM_PEWTER_CRUNCHIES - ITEM_POTION] = gItemEffect_FullHeal,
|
||||
[ITEM_RAGE_CANDY_BAR - ITEM_POTION] = gItemEffect_FullHeal,
|
||||
[ITEM_LAVA_COOKIE - ITEM_POTION] = gItemEffect_FullHeal,
|
||||
[ITEM_OLD_GATEAU - ITEM_POTION] = gItemEffect_FullHeal,
|
||||
[ITEM_CASTELIACONE - ITEM_POTION] = gItemEffect_FullHeal,
|
||||
[ITEM_LUMIOSE_GALETTE - ITEM_POTION] = gItemEffect_FullHeal,
|
||||
[ITEM_SHALOUR_SABLE - ITEM_POTION] = gItemEffect_FullHeal,
|
||||
[ITEM_BIG_MALASADA - ITEM_POTION] = gItemEffect_FullHeal,
|
||||
[ITEM_PEWTER_CRUNCHIES] = gItemEffect_FullHeal,
|
||||
[ITEM_RAGE_CANDY_BAR] = gItemEffect_FullHeal,
|
||||
[ITEM_LAVA_COOKIE] = gItemEffect_FullHeal,
|
||||
[ITEM_OLD_GATEAU] = gItemEffect_FullHeal,
|
||||
[ITEM_CASTELIACONE] = gItemEffect_FullHeal,
|
||||
[ITEM_LUMIOSE_GALETTE] = gItemEffect_FullHeal,
|
||||
[ITEM_SHALOUR_SABLE] = gItemEffect_FullHeal,
|
||||
[ITEM_BIG_MALASADA] = gItemEffect_FullHeal,
|
||||
|
||||
// Vitamins
|
||||
[ITEM_HP_UP - ITEM_POTION] = gItemEffect_HPUp,
|
||||
[ITEM_PROTEIN - ITEM_POTION] = gItemEffect_Protein,
|
||||
[ITEM_IRON - ITEM_POTION] = gItemEffect_Iron,
|
||||
[ITEM_CALCIUM - ITEM_POTION] = gItemEffect_Calcium,
|
||||
[ITEM_ZINC - ITEM_POTION] = gItemEffect_Zinc,
|
||||
[ITEM_CARBOS - ITEM_POTION] = gItemEffect_Carbos,
|
||||
[ITEM_PP_UP - ITEM_POTION] = gItemEffect_PPUp,
|
||||
[ITEM_PP_MAX - ITEM_POTION] = gItemEffect_PPMax,
|
||||
[ITEM_HP_UP] = gItemEffect_HPUp,
|
||||
[ITEM_PROTEIN] = gItemEffect_Protein,
|
||||
[ITEM_IRON] = gItemEffect_Iron,
|
||||
[ITEM_CALCIUM] = gItemEffect_Calcium,
|
||||
[ITEM_ZINC] = gItemEffect_Zinc,
|
||||
[ITEM_CARBOS] = gItemEffect_Carbos,
|
||||
[ITEM_PP_UP] = gItemEffect_PPUp,
|
||||
[ITEM_PP_MAX] = gItemEffect_PPMax,
|
||||
|
||||
// EV Feathers
|
||||
[ITEM_HEALTH_FEATHER - ITEM_POTION] = gItemEffect_HpFeather,
|
||||
[ITEM_MUSCLE_FEATHER - ITEM_POTION] = gItemEffect_AtkFeather,
|
||||
[ITEM_RESIST_FEATHER - ITEM_POTION] = gItemEffect_DefFeather,
|
||||
[ITEM_GENIUS_FEATHER - ITEM_POTION] = gItemEffect_SpatkFeather,
|
||||
[ITEM_CLEVER_FEATHER - ITEM_POTION] = gItemEffect_SpdefFeather,
|
||||
[ITEM_SWIFT_FEATHER - ITEM_POTION] = gItemEffect_SpeedFeather,
|
||||
[ITEM_HEALTH_FEATHER] = gItemEffect_HpFeather,
|
||||
[ITEM_MUSCLE_FEATHER] = gItemEffect_AtkFeather,
|
||||
[ITEM_RESIST_FEATHER] = gItemEffect_DefFeather,
|
||||
[ITEM_GENIUS_FEATHER] = gItemEffect_SpatkFeather,
|
||||
[ITEM_CLEVER_FEATHER] = gItemEffect_SpdefFeather,
|
||||
[ITEM_SWIFT_FEATHER] = gItemEffect_SpeedFeather,
|
||||
|
||||
// Candy
|
||||
[ITEM_RARE_CANDY - ITEM_POTION] = gItemEffect_RareCandy,
|
||||
[ITEM_EXP_CANDY_XS - ITEM_POTION] = gItemEffect_RareCandy,
|
||||
[ITEM_EXP_CANDY_S - ITEM_POTION] = gItemEffect_RareCandy,
|
||||
[ITEM_EXP_CANDY_M - ITEM_POTION] = gItemEffect_RareCandy,
|
||||
[ITEM_EXP_CANDY_L - ITEM_POTION] = gItemEffect_RareCandy,
|
||||
[ITEM_EXP_CANDY_XL - ITEM_POTION] = gItemEffect_RareCandy,
|
||||
//[ITEM_DYNAMAX_CANDY - ITEM_POTION] = gItemEffect_DynamaxCandy, // Todo
|
||||
[ITEM_RARE_CANDY] = gItemEffect_RareCandy,
|
||||
[ITEM_EXP_CANDY_XS] = gItemEffect_RareCandy,
|
||||
[ITEM_EXP_CANDY_S] = gItemEffect_RareCandy,
|
||||
[ITEM_EXP_CANDY_M] = gItemEffect_RareCandy,
|
||||
[ITEM_EXP_CANDY_L] = gItemEffect_RareCandy,
|
||||
[ITEM_EXP_CANDY_XL] = gItemEffect_RareCandy,
|
||||
//[ITEM_DYNAMAX_CANDY] = gItemEffect_DynamaxCandy, // Todo
|
||||
|
||||
// Medicinal Flutes
|
||||
[ITEM_BLUE_FLUTE - ITEM_POTION] = gItemEffect_BlueFlute,
|
||||
[ITEM_YELLOW_FLUTE - ITEM_POTION] = gItemEffect_YellowFlute,
|
||||
[ITEM_RED_FLUTE - ITEM_POTION] = gItemEffect_RedFlute,
|
||||
[ITEM_BLUE_FLUTE] = gItemEffect_BlueFlute,
|
||||
[ITEM_YELLOW_FLUTE] = gItemEffect_YellowFlute,
|
||||
[ITEM_RED_FLUTE] = gItemEffect_RedFlute,
|
||||
|
||||
// X Items
|
||||
[ITEM_X_ATTACK - ITEM_POTION] = gItemEffect_XAttack,
|
||||
[ITEM_X_DEFENSE - ITEM_POTION] = gItemEffect_XDefense,
|
||||
[ITEM_X_SPEED - ITEM_POTION] = gItemEffect_XSpeed,
|
||||
[ITEM_X_ACCURACY - ITEM_POTION] = gItemEffect_XAccuracy,
|
||||
[ITEM_X_SP_ATK - ITEM_POTION] = gItemEffect_XSpecialAttack,
|
||||
[ITEM_X_SP_DEF - ITEM_POTION] = gItemEffect_XSpecialDefense,
|
||||
[ITEM_X_ATTACK] = gItemEffect_XAttack,
|
||||
[ITEM_X_DEFENSE] = gItemEffect_XDefense,
|
||||
[ITEM_X_SPEED] = gItemEffect_XSpeed,
|
||||
[ITEM_X_ACCURACY] = gItemEffect_XAccuracy,
|
||||
[ITEM_X_SP_ATK] = gItemEffect_XSpecialAttack,
|
||||
[ITEM_X_SP_DEF] = gItemEffect_XSpecialDefense,
|
||||
|
||||
[ITEM_DIRE_HIT - ITEM_POTION] = gItemEffect_DireHit,
|
||||
[ITEM_GUARD_SPEC - ITEM_POTION] = gItemEffect_GuardSpec,
|
||||
[ITEM_DIRE_HIT] = gItemEffect_DireHit,
|
||||
[ITEM_GUARD_SPEC] = gItemEffect_GuardSpec,
|
||||
|
||||
//[ITEM_MAX_MUSHROOMS - ITEM_POTION] = gItemEffect_MaxMushrooms, // Todo
|
||||
//[ITEM_MAX_MUSHROOMS] = gItemEffect_MaxMushrooms, // Todo
|
||||
|
||||
// Evolution Items
|
||||
[ITEM_FIRE_STONE - ITEM_POTION] = gItemEffect_EvoItem,
|
||||
[ITEM_WATER_STONE - ITEM_POTION] = gItemEffect_EvoItem,
|
||||
[ITEM_THUNDER_STONE - ITEM_POTION] = gItemEffect_EvoItem,
|
||||
[ITEM_LEAF_STONE - ITEM_POTION] = gItemEffect_EvoItem,
|
||||
[ITEM_ICE_STONE - ITEM_POTION] = gItemEffect_EvoItem,
|
||||
[ITEM_SUN_STONE - ITEM_POTION] = gItemEffect_EvoItem,
|
||||
[ITEM_MOON_STONE - ITEM_POTION] = gItemEffect_EvoItem,
|
||||
[ITEM_SHINY_STONE - ITEM_POTION] = gItemEffect_EvoItem,
|
||||
[ITEM_DUSK_STONE - ITEM_POTION] = gItemEffect_EvoItem,
|
||||
[ITEM_DAWN_STONE - ITEM_POTION] = gItemEffect_EvoItem,
|
||||
[ITEM_SWEET_APPLE - ITEM_POTION] = gItemEffect_EvoItem,
|
||||
[ITEM_TART_APPLE - ITEM_POTION] = gItemEffect_EvoItem,
|
||||
[ITEM_CRACKED_POT - ITEM_POTION] = gItemEffect_EvoItem,
|
||||
[ITEM_CHIPPED_POT - ITEM_POTION] = gItemEffect_EvoItem,
|
||||
[ITEM_GALARICA_CUFF - ITEM_POTION] = gItemEffect_EvoItem,
|
||||
[ITEM_GALARICA_WREATH - ITEM_POTION] = gItemEffect_EvoItem,
|
||||
[ITEM_FIRE_STONE] = gItemEffect_EvoItem,
|
||||
[ITEM_WATER_STONE] = gItemEffect_EvoItem,
|
||||
[ITEM_THUNDER_STONE] = gItemEffect_EvoItem,
|
||||
[ITEM_LEAF_STONE] = gItemEffect_EvoItem,
|
||||
[ITEM_ICE_STONE] = gItemEffect_EvoItem,
|
||||
[ITEM_SUN_STONE] = gItemEffect_EvoItem,
|
||||
[ITEM_MOON_STONE] = gItemEffect_EvoItem,
|
||||
[ITEM_SHINY_STONE] = gItemEffect_EvoItem,
|
||||
[ITEM_DUSK_STONE] = gItemEffect_EvoItem,
|
||||
[ITEM_DAWN_STONE] = gItemEffect_EvoItem,
|
||||
[ITEM_SWEET_APPLE] = gItemEffect_EvoItem,
|
||||
[ITEM_TART_APPLE] = gItemEffect_EvoItem,
|
||||
[ITEM_CRACKED_POT] = gItemEffect_EvoItem,
|
||||
[ITEM_CHIPPED_POT] = gItemEffect_EvoItem,
|
||||
[ITEM_GALARICA_CUFF] = gItemEffect_EvoItem,
|
||||
[ITEM_GALARICA_WREATH] = gItemEffect_EvoItem,
|
||||
[ITEM_AUSPICIOUS_ARMOR] = gItemEffect_EvoItem,
|
||||
[ITEM_MALICIOUS_ARMOR] = gItemEffect_EvoItem,
|
||||
[ITEM_SCROLL_OF_DARKNESS] = gItemEffect_EvoItem,
|
||||
[ITEM_SCROLL_OF_WATERS] = gItemEffect_EvoItem,
|
||||
|
||||
// Berries
|
||||
[ITEM_CHERI_BERRY - ITEM_POTION] = gItemEffect_CheriBerry,
|
||||
[ITEM_CHESTO_BERRY - ITEM_POTION] = gItemEffect_ChestoBerry,
|
||||
[ITEM_PECHA_BERRY - ITEM_POTION] = gItemEffect_PechaBerry,
|
||||
[ITEM_RAWST_BERRY - ITEM_POTION] = gItemEffect_RawstBerry,
|
||||
[ITEM_ASPEAR_BERRY - ITEM_POTION] = gItemEffect_AspearBerry,
|
||||
[ITEM_LEPPA_BERRY - ITEM_POTION] = gItemEffect_LeppaBerry,
|
||||
[ITEM_ORAN_BERRY - ITEM_POTION] = gItemEffect_OranBerry,
|
||||
[ITEM_PERSIM_BERRY - ITEM_POTION] = gItemEffect_PersimBerry,
|
||||
[ITEM_LUM_BERRY - ITEM_POTION] = gItemEffect_FullHeal,
|
||||
[ITEM_SITRUS_BERRY - ITEM_POTION] = gItemEffect_SitrusBerry,
|
||||
[ITEM_POMEG_BERRY - ITEM_POTION] = gItemEffect_PomegBerry,
|
||||
[ITEM_KELPSY_BERRY - ITEM_POTION] = gItemEffect_KelpsyBerry,
|
||||
[ITEM_QUALOT_BERRY - ITEM_POTION] = gItemEffect_QualotBerry,
|
||||
[ITEM_HONDEW_BERRY - ITEM_POTION] = gItemEffect_HondewBerry,
|
||||
[ITEM_GREPA_BERRY - ITEM_POTION] = gItemEffect_GrepaBerry,
|
||||
[ITEM_TAMATO_BERRY - ITEM_POTION] = gItemEffect_TamatoBerry,
|
||||
[LAST_BERRY_INDEX - ITEM_POTION] = NULL,
|
||||
[ITEM_CHERI_BERRY] = gItemEffect_CheriBerry,
|
||||
[ITEM_CHESTO_BERRY] = gItemEffect_ChestoBerry,
|
||||
[ITEM_PECHA_BERRY] = gItemEffect_PechaBerry,
|
||||
[ITEM_RAWST_BERRY] = gItemEffect_RawstBerry,
|
||||
[ITEM_ASPEAR_BERRY] = gItemEffect_AspearBerry,
|
||||
[ITEM_LEPPA_BERRY] = gItemEffect_LeppaBerry,
|
||||
[ITEM_ORAN_BERRY] = gItemEffect_OranBerry,
|
||||
[ITEM_PERSIM_BERRY] = gItemEffect_PersimBerry,
|
||||
[ITEM_LUM_BERRY] = gItemEffect_FullHeal,
|
||||
[ITEM_SITRUS_BERRY] = gItemEffect_SitrusBerry,
|
||||
[ITEM_POMEG_BERRY] = gItemEffect_PomegBerry,
|
||||
[ITEM_KELPSY_BERRY] = gItemEffect_KelpsyBerry,
|
||||
[ITEM_QUALOT_BERRY] = gItemEffect_QualotBerry,
|
||||
[ITEM_HONDEW_BERRY] = gItemEffect_HondewBerry,
|
||||
[ITEM_GREPA_BERRY] = gItemEffect_GrepaBerry,
|
||||
[ITEM_TAMATO_BERRY] = gItemEffect_TamatoBerry,
|
||||
[LAST_BERRY_INDEX] = NULL,
|
||||
};
|
||||
|
@ -3817,3 +3817,78 @@ static const u8 sLoadedDiceDesc[] = _(
|
||||
"Rolls high numbers.\n"
|
||||
"Multihit strikes\n"
|
||||
"hit more times.");
|
||||
|
||||
static const u8 sAuspiciousArmorDesc[] = _(
|
||||
"Armor inhabited by\n"
|
||||
"auspicious wishes.\n"
|
||||
"Causes evolution.");
|
||||
|
||||
static const u8 sBoosterEnergyDesc[] = _(
|
||||
"Encapsuled energy\n"
|
||||
"ups Pokémon with\n"
|
||||
"certain Abilities.");
|
||||
|
||||
static const u8 sBigBambooShootDesc[] = _(
|
||||
"A large and rare\n"
|
||||
"bamboo shoot. Best\n"
|
||||
"sold to gourmands.");
|
||||
|
||||
static const u8 sGimmighoulCoinDesc[] = _(
|
||||
"Gimmighoul hoard\n"
|
||||
"and treasure these\n"
|
||||
"curious coins.");
|
||||
|
||||
static const u8 sLeadersCrestDesc[] = _(
|
||||
"A shard of an old\n"
|
||||
"blade of some sort.\n"
|
||||
"Held by Bisharp.");
|
||||
|
||||
static const u8 sMaliciousArmorDesc[] = _(
|
||||
"Armor inhabited by\n"
|
||||
"malicious will.\n"
|
||||
"Causes evolution.");
|
||||
|
||||
static const u8 sMirrorHerbDesc[] = _(
|
||||
"Mirrors an enemy's\n"
|
||||
"stat increases\n"
|
||||
"but only once.");
|
||||
|
||||
static const u8 sScrollOfDarknessDesc[] = _(
|
||||
"A peculiar scroll\n"
|
||||
"with secrets of\n"
|
||||
"the dark path.");
|
||||
|
||||
static const u8 sScrollOfWatersDesc[] = _(
|
||||
"A peculiar scroll\n"
|
||||
"with secrets of\n"
|
||||
"the water path.");
|
||||
|
||||
static const u8 sTeraOrbDesc[] = _(
|
||||
"Energy charges can\n"
|
||||
"be used to cause\n"
|
||||
"Terastallization.");
|
||||
|
||||
static const u8 sTinyBambooShootDesc[] = _(
|
||||
"A small and rare\n"
|
||||
"bamboo shoot. Best\n"
|
||||
"sold to gourmands.");
|
||||
|
||||
static const u8 sTeraShardDesc[] = _(
|
||||
"These shards may\n"
|
||||
"form when a Tera\n"
|
||||
"Pokémon faints.");
|
||||
|
||||
static const u8 sAdamantCrystalDesc[] = _(
|
||||
"A large, glowing gem\n"
|
||||
"that lets Dialga\n"
|
||||
"change form.");
|
||||
|
||||
static const u8 sGriseousCoreDesc[] = _(
|
||||
"A large, glowing gem\n"
|
||||
"that lets Giratina\n"
|
||||
"change form.");
|
||||
|
||||
static const u8 sLustrousGlobeDesc[] = _(
|
||||
"A large, glowing gem\n"
|
||||
"that lets Palkia\n"
|
||||
"change form.");
|
||||
|
@ -1812,6 +1812,9 @@ static void PopulateSpeciesFromTrainerParty(int matchCallId, u8 *destStr)
|
||||
case F_TRAINER_PARTY_CUSTOM_MOVESET | F_TRAINER_PARTY_HELD_ITEM:
|
||||
speciesName = gSpeciesNames[party.ItemCustomMoves[monId].species];
|
||||
break;
|
||||
case F_TRAINER_PARTY_EVERYTHING_CUSTOMIZED:
|
||||
speciesName = gSpeciesNames[party.EverythingCustomized[monId].species];
|
||||
break;
|
||||
}
|
||||
|
||||
StringCopy(destStr, speciesName);
|
||||
|
@ -4288,7 +4288,10 @@ static bool8 IsHPRecoveryItem(u16 item)
|
||||
if (item == ITEM_ENIGMA_BERRY_E_READER)
|
||||
effect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
|
||||
else
|
||||
effect = gItemEffectTable[item - ITEM_POTION];
|
||||
effect = gItemEffectTable[item];
|
||||
|
||||
if (effect == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (effect[4] & ITEM4_HEAL_HP)
|
||||
return TRUE;
|
||||
@ -4799,9 +4802,9 @@ void ItemUseCB_PPRecovery(u8 taskId, TaskFunc task)
|
||||
if (item == ITEM_ENIGMA_BERRY_E_READER)
|
||||
effect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
|
||||
else
|
||||
effect = gItemEffectTable[item - ITEM_POTION];
|
||||
effect = gItemEffectTable[item];
|
||||
|
||||
if (!(effect[4] & ITEM4_HEAL_PP_ONE))
|
||||
if (effect == NULL || !(effect[4] & ITEM4_HEAL_PP_ONE))
|
||||
{
|
||||
gPartyMenu.data1 = 0;
|
||||
TryUsePPItem(taskId);
|
||||
@ -5514,6 +5517,7 @@ void ItemUseCB_EvolutionStone(u8 taskId, TaskFunc task)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ItemId_GetPocket(gSpecialVar_ItemId) != POCKET_KEY_ITEMS)
|
||||
RemoveBagItem(gSpecialVar_ItemId, 1);
|
||||
FreePartyPointers();
|
||||
}
|
||||
@ -5674,14 +5678,14 @@ u8 GetItemEffectType(u16 item)
|
||||
const u8 *itemEffect;
|
||||
u32 statusCure;
|
||||
|
||||
if (!ITEM_HAS_EFFECT(item))
|
||||
return ITEM_EFFECT_NONE;
|
||||
|
||||
// Read the item's effect properties.
|
||||
if (item == ITEM_ENIGMA_BERRY_E_READER)
|
||||
itemEffect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
|
||||
else
|
||||
itemEffect = gItemEffectTable[item - ITEM_POTION];
|
||||
itemEffect = gItemEffectTable[item];
|
||||
|
||||
if (itemEffect == NULL)
|
||||
return ITEM_EFFECT_NONE;
|
||||
|
||||
if ((itemEffect[0] & ITEM0_DIRE_HIT) || itemEffect[1] || (itemEffect[3] & ITEM3_GUARD_SPEC))
|
||||
return ITEM_EFFECT_X_ITEM;
|
||||
|
@ -5783,9 +5783,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
|
||||
}
|
||||
|
||||
// Skip using the item if it won't do anything
|
||||
if (!ITEM_HAS_EFFECT(item))
|
||||
return TRUE;
|
||||
if (gItemEffectTable[item - ITEM_POTION] == NULL && item != ITEM_ENIGMA_BERRY_E_READER)
|
||||
if (gItemEffectTable[item] == NULL && item != ITEM_ENIGMA_BERRY_E_READER)
|
||||
return TRUE;
|
||||
|
||||
// Get item effect
|
||||
@ -5798,7 +5796,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
|
||||
}
|
||||
else
|
||||
{
|
||||
itemEffect = gItemEffectTable[item - ITEM_POTION];
|
||||
itemEffect = gItemEffectTable[item];
|
||||
}
|
||||
|
||||
// Do item effect
|
||||
@ -6352,9 +6350,9 @@ u8 GetItemEffectParamOffset(u16 itemId, u8 effectByte, u8 effectBit)
|
||||
|
||||
offset = ITEM_EFFECT_ARG_START;
|
||||
|
||||
temp = gItemEffectTable[itemId - ITEM_POTION];
|
||||
temp = gItemEffectTable[itemId];
|
||||
|
||||
if (!temp && itemId != ITEM_ENIGMA_BERRY_E_READER)
|
||||
if (temp != NULL && !temp && itemId != ITEM_ENIGMA_BERRY_E_READER)
|
||||
return 0;
|
||||
|
||||
if (itemId == ITEM_ENIGMA_BERRY_E_READER)
|
||||
@ -6482,7 +6480,7 @@ u8 *UseStatIncreaseItem(u16 itemId)
|
||||
}
|
||||
else
|
||||
{
|
||||
itemEffect = gItemEffectTable[itemId - ITEM_POTION];
|
||||
itemEffect = gItemEffectTable[itemId];
|
||||
}
|
||||
|
||||
gPotentialItemEffectBattler = gBattlerInMenuId;
|
||||
@ -6556,7 +6554,7 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 mode, u16 evolutionItem, s
|
||||
partnerSpecies = GetMonData(tradePartner, MON_DATA_SPECIES, 0);
|
||||
partnerHeldItem = GetMonData(tradePartner, MON_DATA_HELD_ITEM, 0);
|
||||
|
||||
if (partnerHeldItem == ITEM_ENIGMA_BERRY)
|
||||
if (partnerHeldItem == ITEM_ENIGMA_BERRY_E_READER)
|
||||
partnerHoldEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
|
||||
else
|
||||
partnerHoldEffect = ItemId_GetHoldEffect(partnerHeldItem);
|
||||
@ -7226,7 +7224,7 @@ void MonGainEVs(struct Pokemon *mon, u16 defeatedSpecies)
|
||||
u8 bonus;
|
||||
|
||||
heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0);
|
||||
if (heldItem == ITEM_ENIGMA_BERRY)
|
||||
if (heldItem == ITEM_ENIGMA_BERRY_E_READER)
|
||||
{
|
||||
if (gMain.inBattle)
|
||||
holdEffect = gEnigmaBerries[0].holdEffect;
|
||||
|
24
src/random.c
@ -31,3 +31,27 @@ u16 Random2(void)
|
||||
gRng2Value = ISO_RANDOMIZE1(gRng2Value);
|
||||
return gRng2Value >> 16;
|
||||
}
|
||||
|
||||
__attribute__((weak, alias("RandomUniformDefault")))
|
||||
u32 RandomUniform(enum RandomTag tag, u32 lo, u32 hi);
|
||||
|
||||
__attribute__((weak, alias("RandomWeightedArrayDefault")))
|
||||
u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights);
|
||||
|
||||
u32 RandomUniformDefault(enum RandomTag tag, u32 lo, u32 hi)
|
||||
{
|
||||
return lo + (((hi - lo) * Random()) >> 16);
|
||||
}
|
||||
|
||||
u32 RandomWeightedArrayDefault(enum RandomTag tag, u32 sum, u32 n, const u8 *weights)
|
||||
{
|
||||
s32 i, targetSum;
|
||||
targetSum = (sum * Random()) >> 16;
|
||||
for (i = 0; i < n - 1; i++)
|
||||
{
|
||||
targetSum -= weights[i];
|
||||
if (targetSum < 0)
|
||||
return i;
|
||||
}
|
||||
return n - 1;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
SINGLE_BATTLE_TEST("Compound Eyes raises accuracy")
|
||||
{
|
||||
PASSES_RANDOMLY(91, 100);
|
||||
PASSES_RANDOMLY(91, 100, RNG_ACCURACY);
|
||||
GIVEN {
|
||||
ASSUME(gBattleMoves[MOVE_THUNDER].accuracy == 70);
|
||||
PLAYER(SPECIES_BUTTERFREE) { Ability(ABILITY_COMPOUND_EYES); };
|
||||
@ -21,12 +21,11 @@ SINGLE_BATTLE_TEST("Compound Eyes raises accuracy")
|
||||
// than we expect.
|
||||
SINGLE_BATTLE_TEST("Compound Eyes does not affect OHKO moves")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
PASSES_RANDOMLY(30, 100);
|
||||
PASSES_RANDOMLY(30, 100, RNG_ACCURACY);
|
||||
GIVEN {
|
||||
ASSUME(gBattleMoves[MOVE_FISSURE].accuracy == 30);
|
||||
ASSUME(gBattleMoves[MOVE_FISSURE].effect == EFFECT_OHKO);
|
||||
PLAYER(SPECIES_BUTTERFREE) { Ability(ABILITY_TINTED_LENS); };
|
||||
PLAYER(SPECIES_BUTTERFREE) { Ability(ABILITY_COMPOUND_EYES); };
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_FISSURE); }
|
||||
|
@ -1,9 +1,6 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
|
||||
// TODO: Currently PASSES_RANDOMLY is incapable of testing Cute Charm
|
||||
// because it only activates 33% of the time, but we only want to
|
||||
// measure the 50% of the time that the infatuation prevents our move.
|
||||
SINGLE_BATTLE_TEST("Cute Charm inflicts infatuation on contact")
|
||||
{
|
||||
u32 move;
|
||||
|
@ -98,7 +98,6 @@ DOUBLE_BATTLE_TEST("Intimidate doesn't activate on an empty field in a double ba
|
||||
|
||||
SINGLE_BATTLE_TEST("Intimidate and Eject Button force the opponent to Attack")
|
||||
{
|
||||
KNOWN_FAILING; // Issue #2837
|
||||
GIVEN {
|
||||
ASSUME(gItems[ITEM_EJECT_BUTTON].holdEffect == HOLD_EFFECT_EJECT_BUTTON);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
@ -123,3 +122,40 @@ SINGLE_BATTLE_TEST("Intimidate and Eject Button force the opponent to Attack")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Intimidate activates on an empty slot")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_CROAGUNK);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
PLAYER(SPECIES_HITMONTOP) { Ability(ABILITY_INTIMIDATE); };
|
||||
OPPONENT(SPECIES_RALTS);
|
||||
OPPONENT(SPECIES_AZURILL);
|
||||
} WHEN {
|
||||
TURN {
|
||||
SWITCH(playerLeft, 2);
|
||||
MOVE(playerRight, MOVE_GUNK_SHOT, target: opponentLeft);
|
||||
MOVE(opponentRight, MOVE_SPLASH);
|
||||
}
|
||||
TURN {
|
||||
SWITCH(playerLeft, 3);
|
||||
MOVE(playerRight, MOVE_SPLASH);
|
||||
}
|
||||
|
||||
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet, that's enough! Come back!");
|
||||
MESSAGE("Go! Wynaut!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_GUNK_SHOT, playerRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, opponentRight);
|
||||
MESSAGE("Wynaut, that's enough! Come back!");
|
||||
MESSAGE("Go! Hitmontop!");
|
||||
ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE);
|
||||
NONE_OF {
|
||||
MESSAGE("Hitmontop's Intimidate cuts Foe Ralts's attack!");
|
||||
}
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
|
||||
MESSAGE("Hitmontop's Intimidate cuts Foe Azurill's attack!");
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ SINGLE_BATTLE_TEST("Sand Veil prevents damage from sandstorm")
|
||||
|
||||
SINGLE_BATTLE_TEST("Sand Veil reduces accuracy during sandstorm")
|
||||
{
|
||||
PASSES_RANDOMLY(4,5);
|
||||
PASSES_RANDOMLY(4, 5, RNG_ACCURACY);
|
||||
GIVEN {
|
||||
ASSUME(gBattleMoves[MOVE_POUND].accuracy == 100);
|
||||
PLAYER(SPECIES_SANDSHREW) { Ability(ABILITY_SAND_VEIL); };
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
SINGLE_BATTLE_TEST("Stench has a 10% chance to flinch")
|
||||
{
|
||||
PASSES_RANDOMLY(1,10);
|
||||
PASSES_RANDOMLY(1, 10, RNG_STENCH);
|
||||
GIVEN {
|
||||
ASSUME(gBattleMoves[MOVE_TACKLE].power > 0);
|
||||
PLAYER(SPECIES_GRIMER) { Ability(ABILITY_STENCH); };
|
||||
@ -17,7 +17,8 @@ SINGLE_BATTLE_TEST("Stench has a 10% chance to flinch")
|
||||
|
||||
SINGLE_BATTLE_TEST("Stench does not stack with King's Rock")
|
||||
{
|
||||
PASSES_RANDOMLY(1,10);
|
||||
KNOWN_FAILING;
|
||||
PASSES_RANDOMLY(1, 10, RNG_STENCH);
|
||||
GIVEN {
|
||||
ASSUME(gItems[ITEM_KINGS_ROCK].holdEffect == HOLD_EFFECT_FLINCH);
|
||||
ASSUME(gBattleMoves[MOVE_TACKLE].power > 0);
|
||||
|
@ -8,7 +8,7 @@ ASSUMPTIONS
|
||||
|
||||
SINGLE_BATTLE_TEST("Red Card switches the attacker with a random non-fainted replacement")
|
||||
{
|
||||
PASSES_RANDOMLY(1, 2);
|
||||
PASSES_RANDOMLY(1, 2, RNG_FORCE_RANDOM_SWITCH);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
@ -27,7 +27,7 @@ SINGLE_BATTLE_TEST("Red Card switches the attacker with a random non-fainted rep
|
||||
|
||||
DOUBLE_BATTLE_TEST("Red Card switches the target with a random non-battler, non-fainted replacement")
|
||||
{
|
||||
PASSES_RANDOMLY(1, 2);
|
||||
PASSES_RANDOMLY(1, 2, RNG_FORCE_RANDOM_SWITCH);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); }
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
|
26
test/move.c
@ -10,7 +10,7 @@ SINGLE_BATTLE_TEST("Accuracy controls the proportion of misses")
|
||||
PARAMETRIZE { move = MOVE_RAZOR_LEAF; }
|
||||
PARAMETRIZE { move = MOVE_SCRATCH; }
|
||||
ASSUME(0 < gBattleMoves[move].accuracy && gBattleMoves[move].accuracy <= 100);
|
||||
PASSES_RANDOMLY(gBattleMoves[move].accuracy, 100);
|
||||
PASSES_RANDOMLY(gBattleMoves[move].accuracy, 100, RNG_ACCURACY);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
@ -27,10 +27,9 @@ SINGLE_BATTLE_TEST("Secondary Effect Chance controls the proportion of secondary
|
||||
PARAMETRIZE { move = MOVE_THUNDER_SHOCK; }
|
||||
PARAMETRIZE { move = MOVE_DISCHARGE; }
|
||||
PARAMETRIZE { move = MOVE_NUZZLE; }
|
||||
ASSUME(gBattleMoves[move].accuracy == 100);
|
||||
ASSUME(gBattleMoves[move].effect == EFFECT_PARALYZE_HIT);
|
||||
ASSUME(0 < gBattleMoves[move].secondaryEffectChance && gBattleMoves[move].secondaryEffectChance <= 100);
|
||||
PASSES_RANDOMLY(gBattleMoves[move].secondaryEffectChance, 100);
|
||||
PASSES_RANDOMLY(gBattleMoves[move].secondaryEffectChance, 100, RNG_SECONDARY_EFFECT);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
@ -70,6 +69,7 @@ SINGLE_BATTLE_TEST("Turn order is determined by speed if priority ties")
|
||||
|
||||
SINGLE_BATTLE_TEST("Turn order is determined randomly if priority and speed tie")
|
||||
{
|
||||
KNOWN_FAILING; // The algorithm is significantly biased.
|
||||
PASSES_RANDOMLY(1, 2);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(1); }
|
||||
@ -85,15 +85,29 @@ SINGLE_BATTLE_TEST("Turn order is determined randomly if priority and speed tie"
|
||||
SINGLE_BATTLE_TEST("Critical hits occur at a 1/24 rate")
|
||||
{
|
||||
ASSUME(B_CRIT_CHANCE >= GEN_7);
|
||||
ASSUME(gBattleMoves[MOVE_SCRATCH].accuracy == 100);
|
||||
PASSES_RANDOMLY(100 / 24, 100);
|
||||
PASSES_RANDOMLY(1, 24, RNG_CRITICAL_HIT);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
MESSAGE("It's a critical hit!");
|
||||
MESSAGE("A critical hit!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Slash's critical hits occur at a 1/8 rate")
|
||||
{
|
||||
ASSUME(B_CRIT_CHANCE >= GEN_7);
|
||||
ASSUME(gBattleMoves[MOVE_SLASH].flags & FLAG_HIGH_CRIT);
|
||||
PASSES_RANDOMLY(1, 8, RNG_CRITICAL_HIT);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SLASH); }
|
||||
} SCENE {
|
||||
MESSAGE("A critical hit!");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ ASSUMPTIONS
|
||||
SINGLE_BATTLE_TEST("Sand Attack lowers Accuracy")
|
||||
{
|
||||
ASSUME(gBattleMoves[MOVE_SCRATCH].accuracy == 100);
|
||||
PASSES_RANDOMLY(gBattleMoves[MOVE_SCRATCH].accuracy * 3 / 4, 100);
|
||||
PASSES_RANDOMLY(gBattleMoves[MOVE_SCRATCH].accuracy * 3 / 4, 100, RNG_ACCURACY);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
22
test/move_effect_assist.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(gBattleMoves[MOVE_ASSIST].effect == EFFECT_ASSIST);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Assist fails if there are no valid moves to choose from")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) {Moves(MOVE_ASSIST, MOVE_CELEBRATE, MOVE_METRONOME, MOVE_ME_FIRST); }
|
||||
PLAYER(SPECIES_WOBBUFFET) {Moves(MOVE_ASSIST, MOVE_ENDURE, MOVE_DRAGON_TAIL, MOVE_SPOTLIGHT); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ASSIST); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet used Assist!");
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_ASSIST, player);
|
||||
MESSAGE("But it failed!");
|
||||
}
|
||||
}
|
43
test/move_effect_barb_barrage.c
Normal file
@ -0,0 +1,43 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
//ASSUME(gBattleMoves[MOVE_BARB_BARRAGE].effect == EFFECT_BARB_BARRAGE);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Barb Barrage inflicts poison")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_BARB_BARRAGE); }
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BARB_BARRAGE, player);
|
||||
HP_BAR(opponent);
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent);
|
||||
STATUS_ICON(opponent, poison: TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Barb Barrage's power doubles if the target is poisoned/badly poisoned", s16 damage)
|
||||
{
|
||||
u32 status1;
|
||||
PARAMETRIZE { status1 = 0; }
|
||||
PARAMETRIZE { status1 = STATUS1_POISON; }
|
||||
PARAMETRIZE { status1 = STATUS1_TOXIC_POISON; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) {Status1(status1);}
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_BARB_BARRAGE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BARB_BARRAGE, player);
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage);
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[2].damage);
|
||||
}
|
||||
}
|
@ -327,7 +327,6 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Aurora Veil from p
|
||||
|
||||
DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes everything it can")
|
||||
{
|
||||
bool32 defogTurn = FALSE;
|
||||
GIVEN {
|
||||
ASSUME(gBattleMoves[MOVE_HAIL].effect == EFFECT_HAIL);
|
||||
ASSUME(gSpeciesInfo[SPECIES_GLALIE].types[0] == TYPE_ICE);
|
||||
@ -343,13 +342,10 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes everything it can"
|
||||
TURN { MOVE(playerLeft, MOVE_STICKY_WEB); MOVE(playerRight, MOVE_SPIKES); MOVE(opponentLeft, MOVE_STICKY_WEB); MOVE(opponentRight, MOVE_SPIKES); }
|
||||
TURN { SWITCH(playerLeft, 2); SWITCH(playerRight, 3); SWITCH(opponentLeft, 2); SWITCH(opponentRight, 3);}
|
||||
TURN { MOVE(playerLeft, MOVE_TOXIC_SPIKES); MOVE(playerRight, MOVE_STEALTH_ROCK); MOVE(opponentLeft, MOVE_TOXIC_SPIKES); MOVE(opponentRight, MOVE_STEALTH_ROCK); }
|
||||
TURN { MOVE(playerLeft, MOVE_HAIL); MOVE(playerRight, MOVE_AURORA_VEIL); MOVE(opponentLeft, MOVE_AURORA_VEIL); MOVE(opponentRight, MOVE_STEALTH_ROCK); }
|
||||
TURN { MOVE(playerLeft, MOVE_REFLECT); MOVE(playerRight, MOVE_LIGHT_SCREEN); MOVE(opponentLeft, MOVE_REFLECT); MOVE(opponentRight, MOVE_LIGHT_SCREEN); }
|
||||
TURN { MOVE(playerLeft, MOVE_MIST); MOVE(playerRight, MOVE_SAFEGUARD); MOVE(opponentLeft, MOVE_MIST); MOVE(opponentRight, MOVE_SAFEGUARD); }
|
||||
TURN { defogTurn = TRUE ; MOVE(opponentRight, MOVE_DEFOG, target:playerLeft);}
|
||||
TURN { MOVE(playerLeft, MOVE_HAIL); MOVE(playerRight, MOVE_AURORA_VEIL); MOVE(opponentLeft, MOVE_AURORA_VEIL); MOVE(opponentRight, MOVE_LIGHT_SCREEN); }
|
||||
TURN { MOVE(playerLeft, MOVE_REFLECT); MOVE(playerRight, MOVE_LIGHT_SCREEN); MOVE(opponentLeft, MOVE_REFLECT); MOVE(opponentRight, MOVE_SAFEGUARD); }
|
||||
TURN { MOVE(playerLeft, MOVE_MIST); MOVE(playerRight, MOVE_SAFEGUARD); MOVE(opponentLeft, MOVE_MIST); MOVE(opponentRight, MOVE_DEFOG, target: playerLeft); }
|
||||
} SCENE {
|
||||
if (defogTurn == TRUE)
|
||||
{
|
||||
MESSAGE("Foe Glalie used Defog!");
|
||||
MESSAGE("Glalie is protected by MIST!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFOG, opponentRight);
|
||||
@ -371,5 +367,4 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes everything it can"
|
||||
MESSAGE("The poison spikes disappeared from the ground around the opposing team!");
|
||||
MESSAGE("The sticky web has disappeared from the ground around the opposing team!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
138
test/move_effect_dire_claw.c
Normal file
@ -0,0 +1,138 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(gBattleMoves[MOVE_DIRE_CLAW].effect == EFFECT_DIRE_CLAW);
|
||||
}
|
||||
|
||||
// found by brute-force
|
||||
#define RNG_SLEEP 0xcb0
|
||||
#define RNG_POISON 0x2BE
|
||||
#define RNG_PARALYSIS 5
|
||||
|
||||
SINGLE_BATTLE_TEST("Dire Claw can inflict poison, paralysis or sleep")
|
||||
{
|
||||
u8 statusAnim;
|
||||
u32 rng;
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = RNG_POISON; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = RNG_SLEEP; }
|
||||
GIVEN {
|
||||
RNGSeed(rng);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_DIRE_CLAW); }
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_DIRE_CLAW, player);
|
||||
HP_BAR(opponent);
|
||||
ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent);
|
||||
if (statusAnim == B_ANIM_STATUS_PRZ) {
|
||||
STATUS_ICON(opponent, paralysis: TRUE);
|
||||
}
|
||||
else if (statusAnim == B_ANIM_STATUS_SLP) {
|
||||
STATUS_ICON(opponent, sleep: TRUE);
|
||||
}
|
||||
else if (statusAnim == B_ANIM_STATUS_PSN) {
|
||||
STATUS_ICON(opponent, poison: TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze poison/electric types respectively")
|
||||
{
|
||||
u8 statusAnim;
|
||||
u16 species;
|
||||
u32 rng;
|
||||
#if B_PARALYZE_ELECTRIC >= GEN_6
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_RAICHU; }
|
||||
#endif // B_PARALYZE_ELECTRIC
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = RNG_POISON; species = SPECIES_ARBOK;}
|
||||
GIVEN {
|
||||
RNGSeed(rng);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(species);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_DIRE_CLAW); }
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_DIRE_CLAW, player);
|
||||
HP_BAR(opponent);
|
||||
NOT ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent);
|
||||
if (statusAnim == B_ANIM_STATUS_PRZ) {
|
||||
NOT STATUS_ICON(opponent, paralysis: TRUE);
|
||||
}
|
||||
else if (statusAnim == B_ANIM_STATUS_PSN) {
|
||||
NOT STATUS_ICON(opponent, poison: TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze/cause to fall asleep pokemon with abilities preventing respective statuses")
|
||||
{
|
||||
u8 statusAnim;
|
||||
u16 species, ability;
|
||||
u32 rng;
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_RAICHU; ability = ABILITY_LIGHTNING_ROD; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_JOLTEON; ability = ABILITY_VOLT_ABSORB; }
|
||||
#if P_GEN_4_POKEMON == TRUE
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_ELECTIVIRE; ability = ABILITY_MOTOR_DRIVE; }
|
||||
#endif // P_GEN_4_POKEMON
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = RNG_POISON; species = SPECIES_ZANGOOSE; ability = ABILITY_IMMUNITY; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = RNG_SLEEP; species = SPECIES_VIGOROTH; ability = ABILITY_VITAL_SPIRIT; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = RNG_SLEEP; species = SPECIES_HYPNO; ability = ABILITY_INSOMNIA; }
|
||||
|
||||
GIVEN {
|
||||
RNGSeed(rng);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(species) {Ability(ability);}
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_DIRE_CLAW); }
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_DIRE_CLAW, player);
|
||||
HP_BAR(opponent);
|
||||
NOT ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent);
|
||||
if (statusAnim == B_ANIM_STATUS_PRZ) {
|
||||
NOT STATUS_ICON(opponent, paralysis: TRUE);
|
||||
}
|
||||
else if (statusAnim == B_ANIM_STATUS_SLP) {
|
||||
NOT STATUS_ICON(opponent, sleep: TRUE);
|
||||
}
|
||||
else if (statusAnim == B_ANIM_STATUS_PSN) {
|
||||
NOT STATUS_ICON(opponent, poison: TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze/cause to fall asleep a mon which is already statused")
|
||||
{
|
||||
u8 statusAnim;
|
||||
u32 rng;
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = RNG_POISON; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = RNG_SLEEP; }
|
||||
GIVEN {
|
||||
RNGSeed(rng);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) {Status1(STATUS1_BURN);}
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_DIRE_CLAW); }
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_DIRE_CLAW, player);
|
||||
HP_BAR(opponent);
|
||||
NOT ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent);
|
||||
if (statusAnim == B_ANIM_STATUS_PRZ) {
|
||||
NOT STATUS_ICON(opponent, paralysis: TRUE);
|
||||
}
|
||||
else if (statusAnim == B_ANIM_STATUS_SLP) {
|
||||
NOT STATUS_ICON(opponent, sleep: TRUE);
|
||||
}
|
||||
else if (statusAnim == B_ANIM_STATUS_PSN) {
|
||||
NOT STATUS_ICON(opponent, poison: TRUE);
|
||||
}
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ ASSUMPTIONS
|
||||
SINGLE_BATTLE_TEST("Double Team raises Evasion")
|
||||
{
|
||||
ASSUME(gBattleMoves[MOVE_SCRATCH].accuracy == 100);
|
||||
PASSES_RANDOMLY(gBattleMoves[MOVE_SCRATCH].accuracy * 3 / 4, 100);
|
||||
PASSES_RANDOMLY(gBattleMoves[MOVE_SCRATCH].accuracy * 3 / 4, 100, RNG_ACCURACY);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
117
test/move_effect_hit_set_entry_hazardss.c
Normal file
@ -0,0 +1,117 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(gBattleMoves[MOVE_STONE_AXE].effect == EFFECT_HIT_SET_ENTRY_HAZARD);
|
||||
ASSUME(gBattleMoves[MOVE_CEASELESS_EDGE].effect == EFFECT_HIT_SET_ENTRY_HAZARD);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Stone Axe / Ceaseless Edge set up hazards after hitting the target")
|
||||
{
|
||||
u16 move;
|
||||
PARAMETRIZE {move = MOVE_STONE_AXE; }
|
||||
PARAMETRIZE {move = MOVE_CEASELESS_EDGE; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, move); }
|
||||
TURN { SWITCH(opponent, 1); }
|
||||
} SCENE {
|
||||
s32 maxHP = GetMonData(&OPPONENT_PARTY[1], MON_DATA_MAX_HP);
|
||||
ANIMATION(ANIM_TYPE_MOVE, move, player);
|
||||
HP_BAR(opponent);
|
||||
if (move == MOVE_CEASELESS_EDGE) {
|
||||
MESSAGE("Spikes were scattered all around the opposing team!");
|
||||
}
|
||||
else {
|
||||
MESSAGE("Pointed stones float in the air around the opposing team!");
|
||||
}
|
||||
MESSAGE("2 sent out Wobbuffet!");
|
||||
if (move == MOVE_CEASELESS_EDGE) {
|
||||
HP_BAR(opponent, damage: maxHP / 8);
|
||||
MESSAGE("Foe Wobbuffet is hurt by spikes!");
|
||||
}
|
||||
else {
|
||||
HP_BAR(opponent, damage: maxHP / 8);
|
||||
MESSAGE("Pointed stones dug into Foe Wobbuffet!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Ceaseless Edge can set up to 3 layers of Spikes")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CEASELESS_EDGE); }
|
||||
TURN { MOVE(player, MOVE_CEASELESS_EDGE); }
|
||||
TURN { MOVE(player, MOVE_CEASELESS_EDGE); }
|
||||
TURN { MOVE(player, MOVE_CEASELESS_EDGE); }
|
||||
TURN { SWITCH(opponent, 1); }
|
||||
} SCENE {
|
||||
s32 maxHP = GetMonData(&OPPONENT_PARTY[1], MON_DATA_MAX_HP);
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CEASELESS_EDGE, player);
|
||||
HP_BAR(opponent);
|
||||
MESSAGE("Spikes were scattered all around the opposing team!");
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CEASELESS_EDGE, player);
|
||||
HP_BAR(opponent);
|
||||
MESSAGE("Spikes were scattered all around the opposing team!");
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CEASELESS_EDGE, player);
|
||||
HP_BAR(opponent);
|
||||
MESSAGE("Spikes were scattered all around the opposing team!");
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CEASELESS_EDGE, player);
|
||||
HP_BAR(opponent);
|
||||
NOT MESSAGE("Spikes were scattered all around the opposing team!");
|
||||
|
||||
MESSAGE("2 sent out Wynaut!");
|
||||
HP_BAR(opponent, damage: maxHP / 4);
|
||||
MESSAGE("Foe Wynaut is hurt by spikes!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Stone Axe can set up pointed stones only once")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_STONE_AXE); }
|
||||
TURN { MOVE(player, MOVE_STONE_AXE); }
|
||||
TURN { MOVE(player, MOVE_STONE_AXE); }
|
||||
TURN { MOVE(player, MOVE_STONE_AXE); }
|
||||
TURN { SWITCH(opponent, 1); }
|
||||
} SCENE {
|
||||
s32 maxHP = GetMonData(&OPPONENT_PARTY[1], MON_DATA_MAX_HP);
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player);
|
||||
HP_BAR(opponent);
|
||||
MESSAGE("Pointed stones float in the air around the opposing team!");
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player);
|
||||
HP_BAR(opponent);
|
||||
NOT MESSAGE("Pointed stones float in the air around the opposing team!");
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player);
|
||||
HP_BAR(opponent);
|
||||
NOT MESSAGE("Pointed stones float in the air around the opposing team!");
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player);
|
||||
HP_BAR(opponent);
|
||||
NOT MESSAGE("Pointed stones float in the air around the opposing team!");
|
||||
|
||||
MESSAGE("2 sent out Wynaut!");
|
||||
HP_BAR(opponent, damage: maxHP / 8);
|
||||
MESSAGE("Pointed stones dug into Foe Wynaut!");
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,7 @@ ASSUMPTIONS
|
||||
|
||||
SINGLE_BATTLE_TEST("Dragon Tail switches the target with a random non-fainted replacement")
|
||||
{
|
||||
KNOWN_FAILING; // Only 18/50. Waiting for an improved PASSES_RANDOMLY.
|
||||
PASSES_RANDOMLY(90 * 1, 100 * 2);
|
||||
PASSES_RANDOMLY(1, 2, RNG_FORCE_RANDOM_SWITCH);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
@ -27,7 +26,7 @@ SINGLE_BATTLE_TEST("Dragon Tail switches the target with a random non-fainted re
|
||||
|
||||
DOUBLE_BATTLE_TEST("Dragon Tail switches the target with a random non-battler, non-fainted replacement")
|
||||
{
|
||||
PASSES_RANDOMLY(90 * 1, 100 * 2);
|
||||
PASSES_RANDOMLY(1, 2, RNG_FORCE_RANDOM_SWITCH);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
|
@ -8,7 +8,7 @@ ASSUMPTIONS
|
||||
|
||||
SINGLE_BATTLE_TEST("Thrash lasts for 2 or 3 turns")
|
||||
{
|
||||
PASSES_RANDOMLY(1, 2);
|
||||
PASSES_RANDOMLY(1, 2, RNG_RAMPAGE_TURNS);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
@ -26,7 +26,6 @@ SINGLE_BATTLE_TEST("Thrash lasts for 2 or 3 turns")
|
||||
SINGLE_BATTLE_TEST("Thrash confuses the user after it finishes")
|
||||
{
|
||||
GIVEN {
|
||||
RNGSeed(0x00000000);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
@ -45,7 +44,6 @@ SINGLE_BATTLE_TEST("Thrash does not confuse the user if it is canceled on turn 1
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(B_RAMPAGE_CANCELLING >= GEN_5);
|
||||
RNGSeed(0x00000000);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
@ -61,7 +59,6 @@ SINGLE_BATTLE_TEST("Thrash does not confuse the user if it is canceled on turn 2
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(B_RAMPAGE_CANCELLING >= GEN_5);
|
||||
RNGSeed(0x00000000);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
@ -78,7 +75,6 @@ SINGLE_BATTLE_TEST("Thrash confuses the user if it is canceled on turn 3 of 3")
|
||||
KNOWN_FAILING;
|
||||
GIVEN {
|
||||
ASSUME(B_RAMPAGE_CANCELLING >= GEN_5);
|
||||
RNGSeed(0x00000000);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
|
@ -8,7 +8,7 @@ ASSUMPTIONS
|
||||
|
||||
SINGLE_BATTLE_TEST("Roar switches the target with a random non-fainted replacement")
|
||||
{
|
||||
PASSES_RANDOMLY(1, 2);
|
||||
PASSES_RANDOMLY(1, 2, RNG_FORCE_RANDOM_SWITCH);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
@ -25,7 +25,7 @@ SINGLE_BATTLE_TEST("Roar switches the target with a random non-fainted replaceme
|
||||
|
||||
DOUBLE_BATTLE_TEST("Roar switches the target with a random non-battler, non-fainted replacement")
|
||||
{
|
||||
PASSES_RANDOMLY(1, 2);
|
||||
PASSES_RANDOMLY(1, 2, RNG_FORCE_RANDOM_SWITCH);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
|
@ -6,16 +6,33 @@ ASSUMPTIONS
|
||||
ASSUME(gBattleMoves[MOVE_HYPNOSIS].effect == EFFECT_SLEEP);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Hypnosis inflicts sleep")
|
||||
SINGLE_BATTLE_TEST("Hypnosis inflicts 1-3 turns of sleep")
|
||||
{
|
||||
u32 turns, count;
|
||||
ASSUME(B_SLEEP_TURNS >= GEN_5);
|
||||
PARAMETRIZE { turns = 1; }
|
||||
PARAMETRIZE { turns = 2; }
|
||||
PARAMETRIZE { turns = 3; }
|
||||
PASSES_RANDOMLY(1, 3, RNG_SLEEP_TURNS);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_HYPNOSIS); }
|
||||
TURN { MOVE(player, MOVE_HYPNOSIS); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
for (count = 0; count < turns; ++count)
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPNOSIS, player);
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent);
|
||||
MESSAGE("Foe Wobbuffet fell asleep!");
|
||||
STATUS_ICON(opponent, sleep: TRUE);
|
||||
for (count = 0; count < turns; ++count)
|
||||
{
|
||||
if (count < turns - 1)
|
||||
MESSAGE("Foe Wobbuffet is fast asleep.");
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent);
|
||||
}
|
||||
MESSAGE("Foe Wobbuffet woke up!");
|
||||
STATUS_ICON(opponent, none: TRUE);
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ SINGLE_BATTLE_TEST("Spikes damage on switch in")
|
||||
s32 maxHP = GetMonData(&OPPONENT_PARTY[1], MON_DATA_MAX_HP);
|
||||
for (count = 0; count < layers; ++count) {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKES, player);
|
||||
MESSAGE("Spikes were scattered all around the opponent's side!");
|
||||
MESSAGE("Spikes were scattered all around the opposing team!");
|
||||
}
|
||||
MESSAGE("2 sent out Wynaut!");
|
||||
HP_BAR(opponent, damage: maxHP / divisor);
|
||||
@ -51,11 +51,11 @@ SINGLE_BATTLE_TEST("Spikes fails after 3 layers")
|
||||
} SCENE {
|
||||
s32 maxHP = GetMonData(&OPPONENT_PARTY[1], MON_DATA_MAX_HP);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKES, player);
|
||||
MESSAGE("Spikes were scattered all around the opponent's side!");
|
||||
MESSAGE("Spikes were scattered all around the opposing team!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKES, player);
|
||||
MESSAGE("Spikes were scattered all around the opponent's side!");
|
||||
MESSAGE("Spikes were scattered all around the opposing team!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKES, player);
|
||||
MESSAGE("Spikes were scattered all around the opponent's side!");
|
||||
MESSAGE("Spikes were scattered all around the opposing team!");
|
||||
MESSAGE("Wobbuffet used Spikes!");
|
||||
MESSAGE("But it failed!");
|
||||
MESSAGE("2 sent out Wynaut!");
|
||||
|
144
test/move_effect_tri_attack.c
Normal file
@ -0,0 +1,144 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(gBattleMoves[MOVE_TRI_ATTACK].effect == EFFECT_TRI_ATTACK);
|
||||
}
|
||||
|
||||
// found by brute-force
|
||||
#define RNG_PARALYSIS 0xcb0
|
||||
#define RNG_BURN 0x2BE
|
||||
#define RNG_FREEZE 5
|
||||
|
||||
SINGLE_BATTLE_TEST("Tri Attack can inflict paralysis, burn or freeze")
|
||||
{
|
||||
u8 statusAnim;
|
||||
u32 rng;
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = RNG_BURN; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = RNG_FREEZE; }
|
||||
GIVEN {
|
||||
RNGSeed(rng);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_TRI_ATTACK); }
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TRI_ATTACK, player);
|
||||
HP_BAR(opponent);
|
||||
ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent);
|
||||
if (statusAnim == B_ANIM_STATUS_BRN) {
|
||||
STATUS_ICON(opponent, burn: TRUE);
|
||||
}
|
||||
else if (statusAnim == B_ANIM_STATUS_FRZ) {
|
||||
STATUS_ICON(opponent, freeze: TRUE);
|
||||
}
|
||||
else if (statusAnim == B_ANIM_STATUS_PRZ) {
|
||||
STATUS_ICON(opponent, paralysis: TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze electric/fire/ice types respectively")
|
||||
{
|
||||
u8 statusAnim;
|
||||
u16 species;
|
||||
u32 rng;
|
||||
#if B_PARALYZE_ELECTRIC >= GEN_6
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_RAICHU;}
|
||||
#endif // B_PARALYZE_ELECTRIC
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = RNG_BURN; species = SPECIES_ARCANINE; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = RNG_FREEZE; species = SPECIES_GLALIE; }
|
||||
GIVEN {
|
||||
RNGSeed(rng);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(species);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_TRI_ATTACK); }
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TRI_ATTACK, player);
|
||||
HP_BAR(opponent);
|
||||
NOT ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent);
|
||||
if (statusAnim == B_ANIM_STATUS_BRN) {
|
||||
NOT STATUS_ICON(opponent, burn: TRUE);
|
||||
}
|
||||
else if (statusAnim == B_ANIM_STATUS_FRZ) {
|
||||
NOT STATUS_ICON(opponent, freeze: TRUE);
|
||||
}
|
||||
else if (statusAnim == B_ANIM_STATUS_PRZ) {
|
||||
NOT STATUS_ICON(opponent, paralysis: TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze pokemon with abilities preventing respective statuses")
|
||||
{
|
||||
u8 statusAnim;
|
||||
u16 species, ability;
|
||||
u32 rng;
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_RAICHU; ability = ABILITY_LIGHTNING_ROD; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_JOLTEON; ability = ABILITY_VOLT_ABSORB; }
|
||||
#if P_GEN_4_POKEMON == TRUE
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_ELECTIVIRE; ability = ABILITY_MOTOR_DRIVE; }
|
||||
#endif // P_GEN_4_POKEMON
|
||||
#if P_GEN_7_POKEMON == TRUE
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = RNG_BURN; species = SPECIES_DEWPIDER; ability = ABILITY_WATER_BUBBLE; }
|
||||
#endif // P_GEN_7_POKEMON
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = RNG_BURN; species = SPECIES_SEAKING; ability = ABILITY_WATER_VEIL; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = RNG_FREEZE; species = SPECIES_CAMERUPT; ability = ABILITY_MAGMA_ARMOR; }
|
||||
|
||||
GIVEN {
|
||||
RNGSeed(rng);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(species) {Ability(ability);}
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_TRI_ATTACK); }
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TRI_ATTACK, player);
|
||||
HP_BAR(opponent);
|
||||
NOT ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent);
|
||||
if (statusAnim == B_ANIM_STATUS_BRN) {
|
||||
NOT STATUS_ICON(opponent, burn: TRUE);
|
||||
}
|
||||
else if (statusAnim == B_ANIM_STATUS_FRZ) {
|
||||
NOT STATUS_ICON(opponent, freeze: TRUE);
|
||||
}
|
||||
else if (statusAnim == B_ANIM_STATUS_PRZ) {
|
||||
NOT STATUS_ICON(opponent, paralysis: TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze a mon which is already statused")
|
||||
{
|
||||
u8 statusAnim;
|
||||
u32 rng;
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = RNG_BURN; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = RNG_FREEZE; }
|
||||
GIVEN {
|
||||
RNGSeed(rng);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) {Status1(STATUS1_SLEEP);}
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_TRI_ATTACK); }
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TRI_ATTACK, player);
|
||||
HP_BAR(opponent);
|
||||
NOT ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent);
|
||||
if (statusAnim == B_ANIM_STATUS_BRN) {
|
||||
NOT STATUS_ICON(opponent, burn: TRUE);
|
||||
}
|
||||
else if (statusAnim == B_ANIM_STATUS_FRZ) {
|
||||
NOT STATUS_ICON(opponent, freeze: TRUE);
|
||||
}
|
||||
else if (statusAnim == B_ANIM_STATUS_PRZ) {
|
||||
NOT STATUS_ICON(opponent, paralysis: TRUE);
|
||||
}
|
||||
}
|
||||
}
|
27
test/move_effect_venoshock.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(gBattleMoves[MOVE_VENOSHOCK].effect == EFFECT_VENOSHOCK);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Venoshock's power doubles if the target is poisoned/badly poisoned", s16 damage)
|
||||
{
|
||||
u32 status1;
|
||||
PARAMETRIZE { status1 = 0; }
|
||||
PARAMETRIZE { status1 = STATUS1_POISON; }
|
||||
PARAMETRIZE { status1 = STATUS1_TOXIC_POISON; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) {Status1(status1);}
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_VENOSHOCK); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_VENOSHOCK, player);
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage);
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[2].damage);
|
||||
}
|
||||
}
|
81
test/random.c
Normal file
@ -0,0 +1,81 @@
|
||||
#include "global.h"
|
||||
#include "test.h"
|
||||
#include "random.h"
|
||||
|
||||
TEST("RandomUniform generates lo..hi")
|
||||
{
|
||||
u32 lo, hi, i;
|
||||
PARAMETRIZE { lo = 0; hi = 1; }
|
||||
PARAMETRIZE { lo = 0; hi = 2; }
|
||||
PARAMETRIZE { lo = 0; hi = 3; }
|
||||
PARAMETRIZE { lo = 2; hi = 4; }
|
||||
for (i = 0; i < 1024; i++)
|
||||
{
|
||||
u32 r = RandomUniformDefault(RNG_NONE, lo, hi);
|
||||
EXPECT(lo <= r && r <= hi);
|
||||
}
|
||||
}
|
||||
|
||||
TEST("RandomWeighted generates 0..n-1")
|
||||
{
|
||||
u32 n, sum, i;
|
||||
static const u8 ws[8] = { 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
PARAMETRIZE { n = 1; }
|
||||
PARAMETRIZE { n = 2; }
|
||||
PARAMETRIZE { n = 3; }
|
||||
PARAMETRIZE { n = 4; }
|
||||
ASSUME(n <= ARRAY_COUNT(ws));
|
||||
for (i = 0, sum = 0; i < n; i++)
|
||||
sum += ws[i];
|
||||
for (i = 0; i < 1024; i++)
|
||||
{
|
||||
u32 r = RandomWeightedArrayDefault(RNG_NONE, sum, n, ws);
|
||||
EXPECT(0 <= r && r < n);
|
||||
}
|
||||
}
|
||||
|
||||
TEST("RandomUniform generates uniform distribution")
|
||||
{
|
||||
u32 i, error;
|
||||
u16 distribution[4];
|
||||
|
||||
memset(distribution, 0, sizeof(distribution));
|
||||
for (i = 0; i < 4096; i++)
|
||||
{
|
||||
u32 r = RandomUniformDefault(RNG_NONE, 0, ARRAY_COUNT(distribution));
|
||||
EXPECT(0 <= r && r < ARRAY_COUNT(distribution));
|
||||
distribution[r]++;
|
||||
}
|
||||
|
||||
error = 0;
|
||||
for (i = 0; i < ARRAY_COUNT(distribution); i++)
|
||||
error += abs(UQ_4_12(0.25) - distribution[i]);
|
||||
|
||||
EXPECT_LT(error, UQ_4_12(0.025));
|
||||
}
|
||||
|
||||
TEST("RandomWeighted generates distribution in proportion to the weights")
|
||||
{
|
||||
u32 i, sum, error;
|
||||
static const u8 ws[4] = { 1, 2, 2, 3 };
|
||||
u16 distribution[ARRAY_COUNT(ws)];
|
||||
|
||||
for (i = 0, sum = 0; i < ARRAY_COUNT(ws); i++)
|
||||
sum += ws[i];
|
||||
|
||||
memset(distribution, 0, sizeof(distribution));
|
||||
for (i = 0; i < 4096; i++)
|
||||
{
|
||||
u32 r = RandomWeightedArrayDefault(RNG_NONE, sum, ARRAY_COUNT(ws), ws);
|
||||
EXPECT(0 <= r && r < ARRAY_COUNT(ws));
|
||||
distribution[r]++;
|
||||
}
|
||||
|
||||
error = 0;
|
||||
error += abs(UQ_4_12(0.125) - distribution[0]);
|
||||
error += abs(UQ_4_12(0.250) - distribution[1]);
|
||||
error += abs(UQ_4_12(0.250) - distribution[2]);
|
||||
error += abs(UQ_4_12(0.375) - distribution[3]);
|
||||
|
||||
EXPECT_LT(error, UQ_4_12(0.025));
|
||||
}
|
@ -72,7 +72,7 @@ SINGLE_BATTLE_TEST("Burn reduces attack by 50%", s16 damage)
|
||||
|
||||
SINGLE_BATTLE_TEST("Freeze has a 20% chance of being thawed")
|
||||
{
|
||||
PASSES_RANDOMLY(20, 100);
|
||||
PASSES_RANDOMLY(20, 100, RNG_FROZEN);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
@ -90,9 +90,8 @@ SINGLE_BATTLE_TEST("Freeze is thawed by opponent's Fire-type attacks")
|
||||
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_EMBER); }
|
||||
TURN { MOVE(opponent, MOVE_EMBER); MOVE(player, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet is frozen solid!");
|
||||
MESSAGE("Foe Wobbuffet used Ember!");
|
||||
MESSAGE("Wobbuffet was defrosted!");
|
||||
STATUS_ICON(player, none: TRUE);
|
||||
@ -145,7 +144,7 @@ SINGLE_BATTLE_TEST("Paralysis reduces speed by 50%")
|
||||
|
||||
SINGLE_BATTLE_TEST("Paralysis has a 25% chance of skipping the turn")
|
||||
{
|
||||
PASSES_RANDOMLY(25, 100);
|
||||
PASSES_RANDOMLY(25, 100, RNG_PARALYSIS);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_PARALYSIS); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
19
test/terrain_grassy.c
Normal file
@ -0,0 +1,19 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Grassy Terrain recovers 1/16th HP at end of turn")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { MaxHP(100); HP(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_GRASSY_TERRAIN); }
|
||||
} SCENE {
|
||||
s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP);
|
||||
MESSAGE("Wobbuffet is healed by the grassy terrain!");
|
||||
HP_BAR(player, damage: -maxHP / 16);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Grassy Terrain increases power of Grass-type moves by 30/50 percent")
|
||||
TO_DO_BATTLE_TEST("Grassy Terrain decreases power of Earthquake, Magnitude and Bulldoze by 50 percent")
|
30
test/test.h
@ -13,6 +13,7 @@ enum TestResult
|
||||
TEST_RESULT_INVALID,
|
||||
TEST_RESULT_ERROR,
|
||||
TEST_RESULT_TIMEOUT,
|
||||
TEST_RESULT_TODO,
|
||||
};
|
||||
|
||||
struct TestRunner
|
||||
@ -53,6 +54,16 @@ extern const u8 gTestRunnerI;
|
||||
extern const char gTestRunnerArgv[256];
|
||||
|
||||
extern const struct TestRunner gAssumptionsRunner;
|
||||
|
||||
struct FunctionTestRunnerState
|
||||
{
|
||||
u8 parameters;
|
||||
u8 runParameter;
|
||||
};
|
||||
|
||||
extern const struct TestRunner gFunctionTestRunner;
|
||||
extern struct FunctionTestRunnerState *gFunctionTestRunnerState;
|
||||
|
||||
extern struct TestRunnerState gTestRunnerState;
|
||||
|
||||
void CB2_TestRunner(void);
|
||||
@ -62,6 +73,17 @@ void Test_ExitWithResult(enum TestResult, const char *fmt, ...);
|
||||
|
||||
s32 MgbaPrintf_(const char *fmt, ...);
|
||||
|
||||
#define TEST(_name) \
|
||||
static void CAT(Test, __LINE__)(void); \
|
||||
__attribute__((section(".tests"))) static const struct Test CAT(sTest, __LINE__) = \
|
||||
{ \
|
||||
.name = _name, \
|
||||
.filename = __FILE__, \
|
||||
.runner = &gFunctionTestRunner, \
|
||||
.data = (void *)CAT(Test, __LINE__), \
|
||||
}; \
|
||||
static void CAT(Test, __LINE__)(void)
|
||||
|
||||
#define ASSUMPTIONS \
|
||||
static void Assumptions(void); \
|
||||
__attribute__((section(".tests"))) static const struct Test sAssumptions = \
|
||||
@ -138,4 +160,12 @@ s32 MgbaPrintf_(const char *fmt, ...);
|
||||
#define KNOWN_FAILING \
|
||||
Test_ExpectedResult(TEST_RESULT_FAIL)
|
||||
|
||||
#define PARAMETRIZE if (gFunctionTestRunnerState->parameters++ == gFunctionTestRunnerState->runParameter)
|
||||
|
||||
#define TO_DO \
|
||||
Test_ExpectedResult(TEST_RESULT_TODO)
|
||||
|
||||
#define EXPECT_TO_DO \
|
||||
Test_ExitWithResult(TEST_RESULT_TODO, "%s:%d: EXPECT_TO_DO", gTestRunnerState.test->filename, __LINE__)
|
||||
|
||||
#endif
|
||||
|