Merge branch '_RHH/upcoming' into _RHH/pr/upcoming/lighting-expansion-v2
4
Makefile
@ -427,7 +427,9 @@ $(OBJ_DIR)/sym_common.ld: sym_common.txt $(C_OBJS) $(wildcard common_syms/*.txt)
|
||||
$(OBJ_DIR)/sym_ewram.ld: sym_ewram.txt
|
||||
$(RAMSCRGEN) ewram_data $< ENGLISH > $@
|
||||
|
||||
TEACHABLE_DEPS := $(shell find data/ -type f -name '*.inc') $(INCLUDE_DIRS)/constants/tms_hms.h $(C_SUBDIR)/pokemon.c
|
||||
MOVES_JSON_DIR := $(TOOLS_DIR)/learnset_helpers/porymoves_files
|
||||
TEACHABLE_DEPS := $(shell find data/ -type f -name '*.inc') $(INCLUDE_DIRS)/constants/tms_hms.h $(C_SUBDIR)/pokemon.c $(wildcard $(MOVES_JSON_DIR)/*.json)
|
||||
|
||||
$(DATA_SRC_SUBDIR)/pokemon/teachable_learnsets.h: $(TEACHABLE_DEPS)
|
||||
python3 $(TOOLS_DIR)/learnset_helpers/teachable.py
|
||||
|
||||
|
||||
@ -1823,7 +1823,7 @@
|
||||
.4byte \text
|
||||
.endm
|
||||
|
||||
@ Equivalent to fadescreen but copies gPlttBufferUnfaded to gDecompressionBuffer on the fade out
|
||||
@ Equivalent to fadescreen but copies gPlttBufferUnfaded to an allocated buffer on the fade out
|
||||
@ and the reverse on the fade in, in effect saving gPlttBufferUnfaded to restore it.
|
||||
@ If nowait set, does not wait for the fade to complete
|
||||
.macro fadescreenswapbuffers mode:req, nowait=0
|
||||
@ -2473,6 +2473,11 @@
|
||||
callnative Script_SetDifficulty, requests_effects=1
|
||||
.byte \difficulty
|
||||
.endm
|
||||
|
||||
.macro forcesave
|
||||
callnative Script_ForceSaveGame
|
||||
waitstate
|
||||
.endm
|
||||
|
||||
@ Makes the trainer unable to see the player if executed.
|
||||
@ This is a no-op if the player interacts with the trainer.
|
||||
|
||||
@ -270,6 +270,11 @@ Debug_ShowExpansionVersion::
|
||||
Debug_ExpansionVersion:
|
||||
.string "pokeemerald-expansion {STR_VAR_1}$"
|
||||
|
||||
Debug_EventScript_Steven_Multi::
|
||||
call MossdeepCity_SpaceCenter_2F_EventScript_ChoosePartyForMultiBattle
|
||||
release
|
||||
end
|
||||
|
||||
Debug_BerryPestsDisabled::
|
||||
msgbox DebugText_BerryPestsDisabled, MSGBOX_DEFAULT
|
||||
release
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
- [v1.7.x](tutorials/how_to_new_pokemon_1_7_0.md)
|
||||
- [v1.6.x](tutorials/how_to_new_pokemon_1_6_0.md)
|
||||
- [How to use the Testing System](tutorials/how_to_testing_system.md)
|
||||
- [How to add new Trainer Slides](tutorials/how_to_new_trainer_slide.md)
|
||||
- [Day/Night System FAQ](tutorials/dns.md)
|
||||
- [Changelog](./CHANGELOG.md)
|
||||
- [1.10.x]()
|
||||
|
||||
@ -29,12 +29,14 @@ This section lists all of expansion’s AI Flags and briefly describes the effec
|
||||
|
||||
## Composite AI Flags
|
||||
|
||||
Expansion has two "composite" AI flags, `AI_FLAG_BASIC_TRAINER` and `AI_FLAG_SMART_TRAINER`. This means that these flags have no unique functionality themselves, and can instead be thought of as groups of other flags that are all enabled when this flag is enabled. The idea behind these flags is that if you don't care to manage the detailed behaviour of a particular trainer, you can use these as a baseline instead, and expansion will keep them updated for you.
|
||||
Expansion has a few "composite" AI flags. This means that these flags have no unique functionality themselves, and can instead be thought of as groups of other flags that are all enabled when this flag is enabled. The idea behind these flags is that if you don't care to manage the detailed behaviour of a particular trainer, you can use these as a baseline instead, and expansion will keep them updated for you.
|
||||
|
||||
`AI_FLAG_BASIC_TRAINER` is expansion's version of generic, normal AI behaviour. It includes `AI_FLAG_CHECK_BAD_MOVE` (don't use bad moves), `AI_FLAG_TRY_TO_FAINT` (faint the player where possible), and `AI_FLAG_CHECK_VIABILITY` (choose the most effective move to use in the current context). Trainers with this flag will still be smarter than they are in vanilla as there have been dramatic improvements made to move selection, but not incredibly so. Trainers with this flag should feel like normal trainers. In general we recommend these three flags be used in all cases, unless you specifically want a trainer who makes obvious mistakes in battle.
|
||||
|
||||
`AI_FLAG_SMART_TRAINER` is expansion's version of a "smart AI". It includes everything in `AI_FLAG_BASIC_TRAINER` along with `AI_FLAG_SMART_SWITCHING` (make smart decisions about when to switch), `AI_FLAG_SMART_MON_CHOICES` (make smart decisions about what mon to send in after a switch / KO), and `AI_FLAG_OMNISCIENT` (awareness of what moves, items, and abilities the player's mons have to better inform decisions). Expansion will keep this updated to represent the most objectively intelligent behaviour our flags are capable of producing.
|
||||
|
||||
`AI_FLAG_PREDICTION` will enable all of the prediction flags at once, so the AI can perform as well as possible. It is best paired with the flags in `AI_FLAG_SMART_TRAINER` for optimal behaviour. This currently includes `AI_FLAG_PREDICT_SWITCH` and `AI_FLAG_PREDICT_INCOMING_MON`, but will likely be expanded in the future.
|
||||
|
||||
Expansion has LOADS of flags, which will be covered in the rest of this guide. If you don't want to engage with detailed trainer AI tuning though, you can just use these two composite flags, and trust that expansion will keep their contents updated to always represent the most standard and the smartest behaviour we can.
|
||||
|
||||
## `AI_FLAG_CHECK_BAD_MOVE`
|
||||
@ -171,3 +173,9 @@ AI will predict the player's ability based to its aiRating. Without this flag th
|
||||
|
||||
## `AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE`
|
||||
AI will add score to its highest damaging move, regardless of accuracy or secondary effects. Replaces deprecated `AI_FLAG_PREFER_STRONGEST_MOVE`.
|
||||
|
||||
## `AI_FLAG_PREDICT_SWITCH`
|
||||
AI will determine whether it would switch out in the player's situation or not, and predict the player to switch accordingly. In any case where the AI would consider switching, it will assume the player will switch. This is modulated by a 50% failure rate, so the behaviour is non-deterministic and can change from turn to turn to emulate the inconsistency in human predictions. This behaviour is improved significantly by using `AI_FLAG_SMART_SWITCHING` and `AI_FLAG_SMART_MON_CHOICES` as they improve the AI's ability to determine good situations to switch, and also by `AI_FLAG_OMNISCIENT` so the AI can use all its knowledge of the player's team to make the decision.
|
||||
|
||||
## `AI_FLAG_PREDICT_INCOMING_MON`
|
||||
This flag requires `AI_FLAG_PREDICT_SWITCH` to function. If the AI predicts that the player will switch, this flag allows the AI to run its move scoring calculation against the Pokémon it expects the player to switch into, instead of the Pokémon that it expects to switch out.
|
||||
|
||||
@ -169,8 +169,6 @@ Each move can have up to 15 additional effects, allowing you to construct monstr
|
||||
.moveEffect = MOVE_EFFECT_ALL_STATS_UP,
|
||||
.chance = 40,
|
||||
.self = TRUE,
|
||||
},{
|
||||
.moveEffect = MOVE_EFFECT_RAPID_SPIN,
|
||||
},{
|
||||
.moveEffect = MOVE_EFFECT_DEF_MINUS_2,
|
||||
.chance = 50,
|
||||
|
||||
205
docs/tutorials/how_to_new_trainer_slide.md
Normal file
@ -0,0 +1,205 @@
|
||||
# Adding New Trainer Slides
|
||||
## Define Slides Per Trainer
|
||||
|
||||
We are going to add a Trainer Slide to Wally's first Victory Road battle, before he Mega Evolves his Gallade. This battle takes place outside a Battle Facility, so `sTrainerSlides` must be edited.
|
||||
|
||||
### `src/trainer_slide.c`
|
||||
```diff
|
||||
+ const u8 gText_ThatsTheWay[] = _("That's the way, Gallade! Go!{PAUSE_UNTIL_PRESS}");
|
||||
|
||||
static const u8* const sTrainerSlides[DIFFICULTY_COUNT][TRAINERS_COUNT][TRAINER_SLIDE_COUNT] =
|
||||
{
|
||||
[DIFFICULTY_NORMAL] =
|
||||
{
|
||||
+ [TRAINER_WALLY_VR_1] = // use the Trainer's Id from include/constants/opponents.h
|
||||
+ {
|
||||
+ [TRAINER_SLIDE_MEGA_EVOLUTION] = COMPOUND_STRING("That's the way, Gallade! Go!{PAUSE_UNTIL_PRESS}"), // find the id for the slide to be used.
|
||||
+ //[TRAINER_SLIDE_MEGA_EVOLUTION] = gText_ThatsTheWay, // You can use globals or COMPOUND_STRING to define text here.
|
||||
+ }
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
If we were to edit a Trainer that appears in a Battle Facility, `sFrontierTrainerSlides` would be edited instead. Here, we'll give Anabel a line before she uses a Z-Move.
|
||||
|
||||
### `src/trainer_slide.c`
|
||||
```diff
|
||||
static const u8* const sFrontierTrainerSlides[DIFFICULTY_COUNT][FRONTIER_TRAINERS_COUNT][TRAINER_SLIDE_COUNT] =
|
||||
{
|
||||
[DIFFICULTY_NORMAL] =
|
||||
{
|
||||
+ [TRAINER_ANABEL] =
|
||||
+ {
|
||||
+ [TRAINER_SLIDE_Z_MOVE] = COMPOUND_STRING("Victory...is ours!"), //{PAUSE_UNTIL_PRESS} is omitted, so the battle will continue as soon as the next is finished printing.
|
||||
+ }
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## Add New Slides
|
||||
* [Example Commit](<https://github.com/rh-hideout/pokeemerald-expansion/commit/d6424688007cbd923c861cfd35272e5ebfaa4016>)
|
||||
* [Patch](<https://github.com/rh-hideout/pokeemerald-expansion/commit/d6424688007cbd923c861cfd35272e5ebfaa4016.patch>)
|
||||
* [Diff](<https://github.com/rh-hideout/pokeemerald-expansion/commit/d6424688007cbd923c861cfd35272e5ebfaa4016.diff>)
|
||||
|
||||
### `include/constants/trainer_slide.h`
|
||||
```diff
|
||||
enum TrainerSlideType
|
||||
{
|
||||
TRAINER_SLIDE_BEFORE_FIRST_TURN,
|
||||
TRAINER_SLIDE_PLAYER_LANDS_FIRST_CRITICAL_HIT,
|
||||
+ TRAINER_SLIDE_ENEMY_LANDS_FIRST_CRITICAL_HIT, // Each Trainer Slide has a unqiue id.
|
||||
TRAINER_SLIDE_PLAYER_LANDS_FIRST_SUPER_EFFECTIVE_HIT,
|
||||
TRAINER_SLIDE_PLAYER_LANDS_FIRST_STAB_MOVE,
|
||||
TRAINER_SLIDE_PLAYER_LANDS_FIRST_DOWN,
|
||||
TRAINER_SLIDE_ENEMY_MON_UNAFFECTED,
|
||||
TRAINER_SLIDE_LAST_SWITCHIN,
|
||||
TRAINER_SLIDE_LAST_HALF_HP,
|
||||
TRAINER_SLIDE_LAST_LOW_HP,
|
||||
TRAINER_SLIDE_MEGA_EVOLUTION,
|
||||
TRAINER_SLIDE_Z_MOVE,
|
||||
TRAINER_SLIDE_DYNAMAX,
|
||||
TRAINER_SLIDE_COUNT,
|
||||
};
|
||||
```
|
||||
|
||||
Each Trainer Slide has a unique id and needs to be added to this list.
|
||||
|
||||
### `include/trainer_slide.h`
|
||||
|
||||
If your new Trainer Slide needs to check for beforen initalized, a function is declared here to be used externally. Critical hits are used to initalize this Trainer Slide but the slide doesn't play instantly, so we will create an function to initialize it.
|
||||
|
||||
```diff
|
||||
void SetTrainerSlideMessage(enum DifficultyLevel, u32, u32);
|
||||
void TryInitalizeFirstSTABMoveTrainerSlide(u32, u32, u32);
|
||||
void TryInitalizeTrainerSlidePlayerLandsFirstCriticalHit(u32);
|
||||
+ void TryInitalizeTrainerSlideEnemyLandsFirstCriticalHit(u32);
|
||||
void TryInitalizeTrainerSlidePlayerLandsFirstSuperEffectiveHit(u32);
|
||||
void TryInitalizeTrainerSlideEnemyMonUnaffected(u32);
|
||||
bool32 IsTrainerSlideInitialized(enum TrainerSlideType);
|
||||
```
|
||||
### `src/trainer_slide.c`
|
||||
|
||||
```diff
|
||||
return IsTrainerSlideInitialized(slideId);
|
||||
}
|
||||
|
||||
+static bool32 ShouldRunTrainerSlideEnemyLandsFirstCriticalHit(enum TrainerSlideType slideId)
|
||||
+{
|
||||
+ return IsTrainerSlideInitialized(slideId);
|
||||
+}
|
||||
+
|
||||
static bool32 ShouldRunTrainerSlidePlayerLandsFirstSuperEffectiveHit(u32 battler, enum TrainerSlideType slideId)
|
||||
{
|
||||
if (!IsTrainerSlideInitialized(slideId))
|
||||
```
|
||||
|
||||
```diff
|
||||
case TRAINER_SLIDE_PLAYER_LANDS_FIRST_CRITICAL_HIT:
|
||||
shouldRun = ShouldRunTrainerSlidePlayerLandsFirstCriticalHit(slideId);
|
||||
break;
|
||||
+ case TRAINER_SLIDE_ENEMY_LANDS_FIRST_CRITICAL_HIT:
|
||||
+ shouldRun = ShouldRunTrainerSlideEnemyLandsFirstCriticalHit(slideId);
|
||||
+ break;
|
||||
case TRAINER_SLIDE_PLAYER_LANDS_FIRST_SUPER_EFFECTIVE_HIT:
|
||||
shouldRun = ShouldRunTrainerSlidePlayerLandsFirstSuperEffectiveHit(battler, slideId);
|
||||
break;
|
||||
```
|
||||
|
||||
The function that determines if a Slide should play has different function for most Slides. We need to check if this Slide was initialized by a critical hit previously, so a function is created here. This function and the Id and then added to the switch statement in `ShouldDoTrainerSlide`.
|
||||
|
||||
```diff
|
||||
InitalizeTrainerSlide(slideId);
|
||||
}
|
||||
|
||||
+void TryInitalizeTrainerSlideEnemyLandsFirstCriticalHit(u32 target)
|
||||
+{
|
||||
+ enum TrainerSlideType slideId = TRAINER_SLIDE_ENEMY_LANDS_FIRST_CRITICAL_HIT;
|
||||
+
|
||||
+ if (IsSlideInitalizedOrPlayed(slideId))
|
||||
+ return;
|
||||
+
|
||||
+ if (GetBattlerSide(target) == B_SIDE_OPPONENT)
|
||||
+ return;
|
||||
+
|
||||
+ InitalizeTrainerSlide(slideId);
|
||||
+}
|
||||
+
|
||||
```
|
||||
|
||||
The function to check if this slide SHOULD be initalized is added to the bottom of this file.
|
||||
|
||||
### `src/battle_main.c`
|
||||
|
||||
```diff
|
||||
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
|
||||
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_PLAYER_LANDS_FIRST_CRITICAL_HIT)))
|
||||
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
|
||||
+ else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_ENEMY_LANDS_FIRST_CRITICAL_HIT)))
|
||||
+ BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
|
||||
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_PLAYER_LANDS_FIRST_SUPER_EFFECTIVE_HIT)))
|
||||
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
|
||||
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_PLAYER_LANDS_FIRST_STAB_MOVE)))
|
||||
diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c
|
||||
```
|
||||
|
||||
In `BattleTurnPassed`, most Trainer Slides are checked to see if they should run, so our new call is added here.
|
||||
|
||||
### `src/battle_script_commands.c`
|
||||
|
||||
```diff
|
||||
{
|
||||
PrepareStringBattle(STRINGID_CRITICALHIT, gBattlerAttacker);
|
||||
|
||||
+ TryInitalizeTrainerSlideEnemyLandsFirstCriticalHit(gBattlerTarget);
|
||||
TryInitalizeTrainerSlidePlayerLandsFirstCriticalHit(gBattlerTarget);
|
||||
|
||||
gBattleCommunication[MSG_DISPLAY] = 1;
|
||||
```
|
||||
|
||||
The actual usage of `TryInitalizeTrainerSlideEnemyLandsFirstCriticalHit` is added and is checked whenever a critical hit is scored.
|
||||
|
||||
### `test/battle/trainer_slides.c`
|
||||
```diff
|
||||
}
|
||||
}
|
||||
|
||||
+SINGLE_BATTLE_TEST("Trainer Slide: Enemy Lands First Critical Hit")
|
||||
+{
|
||||
+ gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_ENEMY_LANDS_FIRST_CRITICAL_HIT;
|
||||
+
|
||||
+ GIVEN {
|
||||
+ ASSUME(GetMoveEffect(MOVE_LASER_FOCUS) == EFFECT_LASER_FOCUS);
|
||||
+ PLAYER(SPECIES_WOBBUFFET);
|
||||
+ OPPONENT(SPECIES_WOBBUFFET);
|
||||
+ } WHEN {
|
||||
+ TURN { MOVE(opponent, MOVE_LASER_FOCUS); }
|
||||
+ TURN { MOVE(opponent, MOVE_TACKLE); }
|
||||
+ } SCENE {
|
||||
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_LASER_FOCUS, opponent);
|
||||
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
|
||||
+ MESSAGE("A critical hit!");
|
||||
+ MESSAGE("This message plays after the enemy lands their first critical hit.{PAUSE_UNTIL_PRESS}");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
SINGLE_BATTLE_TEST("Trainer Slide: Player Lands First STAB Hit")
|
||||
{
|
||||
gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_PLAYER_LANDS_FIRST_STAB_MOVE;
|
||||
diff --git a/test/battle/trainer_slides.h b/test/battle/trainer_slides.h
|
||||
```
|
||||
|
||||
### `test/battle/trainer_slides.h`
|
||||
```diff
|
||||
|
||||
[TRAINER_SLIDE_PLAYER_LANDS_FIRST_CRITICAL_HIT] = COMPOUND_STRING("This message plays after the player lands their first critical hit.{PAUSE_UNTIL_PRESS}"),
|
||||
},
|
||||
+ [TRAINER_SLIDE_ENEMY_LANDS_FIRST_CRITICAL_HIT] =
|
||||
+ {
|
||||
+ [TRAINER_SLIDE_ENEMY_LANDS_FIRST_CRITICAL_HIT] = COMPOUND_STRING("This message plays after the enemy lands their first critical hit.{PAUSE_UNTIL_PRESS}"),
|
||||
+ },
|
||||
[TRAINER_SLIDE_PLAYER_LANDS_FIRST_SUPER_EFFECTIVE_HIT] =
|
||||
{
|
||||
[TRAINER_SLIDE_PLAYER_LANDS_FIRST_SUPER_EFFECTIVE_HIT] = COMPOUND_STRING("This message plays after the player lands their first super effective hit.{PAUSE_UNTIL_PRESS}"),
|
||||
```
|
||||
|
||||
Tests are added to make sure the new Trainer Slide works. A test is added to the c file, and the trainer to run the entry in the test is added to `sTestTrainerSlides`.
|
||||
BIN
graphics/pokemon/clodsire/anim_front.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 539 B After Width: | Height: | Size: 813 B |
|
Before Width: | Height: | Size: 698 B |
@ -1,19 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
152 208 160
|
||||
64 60 48
|
||||
128 108 96
|
||||
153 211 165
|
||||
248 141 165
|
||||
176 90 105
|
||||
105 54 57
|
||||
184 160 162
|
||||
152 122 126
|
||||
86 71 72
|
||||
128 109 102
|
||||
96 80 72
|
||||
48 40 32
|
||||
69 60 50
|
||||
51 41 36
|
||||
46 39 36
|
||||
16 16 16
|
||||
184 160 160
|
||||
208 208 208
|
||||
40 36 32
|
||||
152 120 120
|
||||
80 68 72
|
||||
104 52 56
|
||||
176 88 104
|
||||
248 140 160
|
||||
0 0 0
|
||||
0 0 0
|
||||
215 189 217
|
||||
152 116 156
|
||||
91 67 108
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
152 208 160
|
||||
74 67 90
|
||||
127 116 143
|
||||
107 97 124
|
||||
46 40 44
|
||||
16 16 16
|
||||
153 211 165
|
||||
248 141 142
|
||||
176 94 90
|
||||
105 62 54
|
||||
160 158 197
|
||||
205 180 170
|
||||
40 36 32
|
||||
127 127 157
|
||||
87 85 112
|
||||
104 52 56
|
||||
176 88 104
|
||||
248 140 160
|
||||
0 0 0
|
||||
0 0 0
|
||||
127 116 143
|
||||
107 97 124
|
||||
74 67 90
|
||||
49 43 62
|
||||
46 40 44
|
||||
16 16 16
|
||||
230 209 181
|
||||
201 159 123
|
||||
99 63 59
|
||||
|
||||
|
Before Width: | Height: | Size: 591 B After Width: | Height: | Size: 949 B |
|
Before Width: | Height: | Size: 783 B After Width: | Height: | Size: 653 B |
BIN
graphics/summary_screen/iv_ev_tiles.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
@ -19,6 +19,7 @@
|
||||
#include "battle_gimmick.h"
|
||||
#include "move.h"
|
||||
#include "random.h" // for rng_value_t
|
||||
#include "trainer_slide.h"
|
||||
|
||||
// Helper for accessing command arguments and advancing gBattlescriptCurrInstr.
|
||||
//
|
||||
@ -68,6 +69,7 @@
|
||||
|
||||
#define BATTLE_BUFFER_LINK_SIZE 0x1000
|
||||
|
||||
// Cleared each time a mon leaves the field, either by switching out or fainting
|
||||
struct DisableStruct
|
||||
{
|
||||
u32 transformedMonPersonality;
|
||||
@ -354,7 +356,7 @@ struct AiLogicData
|
||||
u8 monToSwitchInId[MAX_BATTLERS_COUNT]; // ID of the mon to switch in.
|
||||
u8 mostSuitableMonId[MAX_BATTLERS_COUNT]; // Stores result of GetMostSuitableMonToSwitchInto, which decides which generic mon the AI would switch into if they decide to switch. This can be overruled by specific mons found in ShouldSwitch; the final resulting mon is stored in AI_monToSwitchIntoId.
|
||||
struct SwitchinCandidate switchinCandidate; // Struct used for deciding which mon to switch to in battle_ai_switch_items.c
|
||||
u8 weatherHasEffect:1; // The same as WEATHER_HAS_EFFECT. Stored here, so it's called only once.
|
||||
u8 weatherHasEffect:1; // The same as HasWeatherEffect(). Stored here, so it's called only once.
|
||||
u8 ejectButtonSwitch:1; // Tracks whether current switch out was from Eject Button
|
||||
u8 ejectPackSwitch:1; // Tracks whether current switch out was from Eject Pack
|
||||
u8 predictingSwitch:1; // Determines whether AI will use predictions this turn or not
|
||||
@ -793,16 +795,6 @@ struct BattleStruct
|
||||
u8 bonusCritStages[MAX_BATTLERS_COUNT]; // G-Max Chi Strike boosts crit stages of allies.
|
||||
u8 itemPartyIndex[MAX_BATTLERS_COUNT];
|
||||
u8 itemMoveIndex[MAX_BATTLERS_COUNT];
|
||||
u8 trainerSlideFirstCriticalHitMsgState:2;
|
||||
u8 trainerSlideFirstSuperEffectiveHitMsgState:2;
|
||||
u8 trainerSlideFirstSTABMoveMsgState:2;
|
||||
u8 trainerSlidePlayerMonUnaffectedMsgState:2;
|
||||
u8 trainerSlideHalfHpMsgDone:1;
|
||||
u8 trainerSlideMegaEvolutionMsgDone:1;
|
||||
u8 trainerSlideZMoveMsgDone:1;
|
||||
u8 trainerSlideBeforeFirstTurnMsgDone:1;
|
||||
u8 trainerSlideDynamaxMsgDone:1;
|
||||
u8 trainerSlideLowHpMsgDone:1;
|
||||
u8 pledgeMove:1;
|
||||
u8 isSkyBattle:1;
|
||||
u32 aiDelayTimer; // Counts number of frames AI takes to choose an action.
|
||||
@ -841,6 +833,8 @@ struct BattleStruct
|
||||
u8 printedStrongWindsWeakenedAttack:1;
|
||||
u8 numSpreadTargets:2;
|
||||
u8 padding3:2;
|
||||
struct MessageStatus slideMessageStatus;
|
||||
u8 trainerSlideSpriteIds[MAX_BATTLERS_COUNT];
|
||||
};
|
||||
|
||||
// The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider,
|
||||
|
||||
@ -80,6 +80,7 @@ bool32 IsAbilityOfRating(u32 ability, s8 rating);
|
||||
bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability);
|
||||
bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u32 move);
|
||||
bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove);
|
||||
u32 AI_GetBattlerAbility(u32 battler);
|
||||
|
||||
// stat stage checks
|
||||
bool32 AnyStatIsRaised(u32 battlerId);
|
||||
@ -146,6 +147,7 @@ bool32 IsStatRaisingEffect(u32 effect);
|
||||
bool32 IsStatLoweringEffect(u32 effect);
|
||||
bool32 IsSelfStatLoweringEffect(u32 effect);
|
||||
bool32 IsSwitchOutEffect(u32 effect);
|
||||
bool32 IsChaseEffect(u32 effect);
|
||||
bool32 IsAttackBoostMoveEffect(u32 effect);
|
||||
bool32 IsUngroundingEffect(u32 effect);
|
||||
bool32 IsSemiInvulnerable(u32 battlerDef, u32 move);
|
||||
|
||||
@ -319,6 +319,7 @@ void SetControllerToRecordedPlayer(u32 battler);
|
||||
|
||||
// opponent controller
|
||||
void SetControllerToOpponent(u32 battler);
|
||||
void OpponentHandleTrainerSlide(u32 battler);
|
||||
|
||||
// player partner controller
|
||||
void Controller_PlayerPartnerShowIntroHealthbox(u32 battler); // Also used by the link partner.
|
||||
|
||||
@ -245,35 +245,18 @@ struct BattleMsgData
|
||||
u8 textBuffs[3][TEXT_BUFF_ARRAY_COUNT];
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
TRAINER_SLIDE_LAST_SWITCHIN,
|
||||
TRAINER_SLIDE_LAST_LOW_HP,
|
||||
TRAINER_SLIDE_FIRST_DOWN,
|
||||
TRAINER_SLIDE_LAST_HALF_HP,
|
||||
TRAINER_SLIDE_FIRST_CRITICAL_HIT,
|
||||
TRAINER_SLIDE_FIRST_SUPER_EFFECTIVE_HIT,
|
||||
TRAINER_SLIDE_FIRST_STAB_MOVE,
|
||||
TRAINER_SLIDE_PLAYER_MON_UNAFFECTED,
|
||||
TRAINER_SLIDE_MEGA_EVOLUTION,
|
||||
TRAINER_SLIDE_Z_MOVE,
|
||||
TRAINER_SLIDE_BEFORE_FIRST_TURN,
|
||||
TRAINER_SLIDE_DYNAMAX,
|
||||
};
|
||||
|
||||
void BufferStringBattle(u16 stringID, u32 battler);
|
||||
u32 BattleStringExpandPlaceholdersToDisplayedString(const u8 *src);
|
||||
u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize);
|
||||
void BattlePutTextOnWindow(const u8 *text, u8 windowId);
|
||||
void SetPpNumbersPaletteInMoveSelection(u32 battler);
|
||||
u8 GetCurrentPpToMaxPpState(u8 currentPp, u8 maxPp);
|
||||
u32 ShouldDoTrainerSlide(u32 battler, u32 which); // return 1 for TrainerA, 2 forTrainerB
|
||||
void ExpandBattleTextBuffPlaceholders(const u8 *src, u8 *dst);
|
||||
|
||||
extern struct BattleMsgData *gBattleMsgDataPtr;
|
||||
|
||||
extern const u8 *const gBattleStringsTable[];
|
||||
extern const u8 *const gStatNamesTable[];
|
||||
extern const u8 *const gStatNamesTable[NUM_BATTLE_STATS];
|
||||
extern const u8 *const gPokeblockWasTooXStringTable[];
|
||||
extern const u8 *const gRefereeStringsTable[];
|
||||
extern const u8 *const gRoundsStringTable[];
|
||||
|
||||
@ -67,7 +67,7 @@ enum {
|
||||
#define ABILITYEFFECT_WATER_SPORT 253 // Only used if B_SPORT_TURNS >= GEN_6
|
||||
|
||||
// For the first argument of ItemBattleEffects, to deteremine which block of item effects to try
|
||||
enum ItemEffect
|
||||
enum ItemCaseId
|
||||
{
|
||||
ITEMEFFECT_NONE,
|
||||
ITEMEFFECT_ON_SWITCH_IN,
|
||||
@ -82,7 +82,15 @@ enum ItemEffect
|
||||
ITEMEFFECT_STATS_CHANGED, // For White Herb and Eject Pack
|
||||
};
|
||||
|
||||
#define WEATHER_HAS_EFFECT ((!IsAbilityOnField(ABILITY_CLOUD_NINE) && !IsAbilityOnField(ABILITY_AIR_LOCK)))
|
||||
enum ItemEffect
|
||||
{
|
||||
ITEM_NO_EFFECT,
|
||||
ITEM_STATUS_CHANGE,
|
||||
ITEM_EFFECT_OTHER,
|
||||
ITEM_PP_CHANGE,
|
||||
ITEM_HP_CHANGE,
|
||||
ITEM_STATS_CHANGE,
|
||||
};
|
||||
|
||||
#define IS_WHOLE_SIDE_ALIVE(battler) ((IsBattlerAlive(battler) && IsBattlerAlive(BATTLE_PARTNER(battler))))
|
||||
#define IS_ALIVE_AND_PRESENT(battler) (IsBattlerAlive(battler) && IsBattlerSpritePresent(battler))
|
||||
@ -157,6 +165,7 @@ struct DamageCalculationData
|
||||
u32 updateFlags:1;
|
||||
u32 padding:2;
|
||||
};
|
||||
STATIC_ASSERT(sizeof(struct DamageCalculationData) <= 4, StructExceedsFourBytes);
|
||||
|
||||
enum SleepClauseBlock
|
||||
{
|
||||
@ -224,7 +233,7 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move);
|
||||
bool32 CanBattlerEscape(u32 battler); // no ability check
|
||||
void BattleScriptExecute(const u8 *BS_ptr);
|
||||
void BattleScriptPushCursorAndCallback(const u8 *BS_ptr);
|
||||
u32 ItemBattleEffects(enum ItemEffect, u32 battler, bool32 moveTurn);
|
||||
u32 ItemBattleEffects(enum ItemCaseId, u32 battler, bool32 moveTurn);
|
||||
void ClearVariousBattlerFlags(u32 battler);
|
||||
void HandleAction_RunBattleScript(void);
|
||||
u32 SetRandomTarget(u32 battler);
|
||||
@ -282,7 +291,7 @@ void TryRestoreHeldItems(void);
|
||||
bool32 CanStealItem(u32 battlerStealing, u32 battlerItem, u16 item);
|
||||
void TrySaveExchangedItem(u32 battler, u16 stolenItem);
|
||||
bool32 IsPartnerMonFromSameTrainer(u32 battler);
|
||||
u32 TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum ItemEffect caseID);
|
||||
enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum ItemCaseId caseID);
|
||||
bool32 IsBattlerAffectedByHazards(u32 battler, bool32 toxicSpikes);
|
||||
void SortBattlersBySpeed(u8 *battlers, bool32 slowToFast);
|
||||
bool32 CompareStat(u32 battler, u8 statId, u8 cmpTo, u8 cmpKind);
|
||||
@ -343,5 +352,6 @@ u32 NumAffectedSpreadMoveTargets(void);
|
||||
bool32 IsPursuitTargetSet(void);
|
||||
void ClearPursuitValuesIfSet(u32 battler);
|
||||
void ClearPursuitValues(void);
|
||||
bool32 HasWeatherEffect(void);
|
||||
|
||||
#endif // GUARD_BATTLE_UTIL_H
|
||||
|
||||
@ -80,7 +80,8 @@ u8 Unused_AdjustBgMosaic(u8 val, u32 mode);
|
||||
void SetBgTilemapBuffer(u32 bg, void *tilemap);
|
||||
void UnsetBgTilemapBuffer(u32 bg);
|
||||
void *GetBgTilemapBuffer(u32 bg);
|
||||
void CopyToBgTilemapBuffer(u32 bg, const void *src, u16 mode, u16 destOffset);
|
||||
void CopyToBgTilemapBuffer(u32 bg, const void *src, u32 mode, u32 destOffset);
|
||||
void DecompressAndCopyToBgTilemapBuffer(u32 bg, const u32 *src, u32 mode, u32 destOffset);
|
||||
void CopyBgTilemapBufferToVram(u32 bg);
|
||||
void CopyToBgTilemapBufferRect(u32 bg, const void *src, u8 destX, u8 destY, u8 width, u8 height);
|
||||
void CopyToBgTilemapBufferRect_ChangePalette(u32 bg, const void *src, u8 destX, u8 destY, u8 rectWidth, u8 rectHeight, u8 palette);
|
||||
|
||||
@ -297,8 +297,7 @@
|
||||
#define B_SHOW_TYPES SHOW_TYPES_NEVER // When defined as SHOW_TYPES_ALWAYS, after selecting "Fight" in battle, the types of all Pokemon are revealed. Whe defined as SHOW_TYPES_OWN, types are only revealed if the player owns the mon in question.
|
||||
|
||||
// Pokémon battle sprite settings
|
||||
#define B_ENEMY_MON_SHADOW_STYLE GEN_3 // In Gen4+, all enemy Pokemon will have a shadow drawn beneath them.
|
||||
// Currently Gen4+ shadows don't properly work with Trainerslides
|
||||
#define B_ENEMY_MON_SHADOW_STYLE GEN_LATEST // In Gen4+, all enemy Pokemon will have a shadow drawn beneath them.
|
||||
|
||||
// Battle UI settings
|
||||
#define B_MOVE_REARRANGEMENT_IN_BATTLE GEN_LATEST // In Gen 4+ move slots cannot be rearranged in battle
|
||||
|
||||
@ -117,4 +117,7 @@
|
||||
#define OW_UNION_DISABLE_CHECK FALSE // When TRUE, the nurse does not inform the player if there is a trainer waiting in the Union Room. This speeds up the loading of the Pokémon Center.
|
||||
#define OW_FLAG_MOVE_UNION_ROOM_CHECK 0 // If this flag is set, the game will only check if players are in the Union Room while healing Pokémon, and not when players enter the Pokémon Center. This speeds up the loading of the Pokémon Center. This is ignored if OW_UNION_DISABLE_CHECK is TRUE.
|
||||
|
||||
// Berry Blender
|
||||
#define BERRY_BLENDER_THROW_ALL_BERRIES_AT_ONCE TRUE // This is a small little addition, that basically speeds up the animation where all players' berries are thrown into the blender. Self-explanatory I hope!
|
||||
|
||||
#endif // GUARD_CONFIG_OVERWORLD_H
|
||||
|
||||
@ -60,18 +60,15 @@
|
||||
#define P_ONLY_OBTAINABLE_SHINIES FALSE // If TRUE, Pokémon encountered in the Battle Pyramid won't be shiny.
|
||||
#define P_NO_SHINIES_WITHOUT_POKEBALLS FALSE // If TRUE, Pokémon encountered when the player is out of Poké Balls won't be shiny
|
||||
#define P_SHOW_DYNAMIC_TYPES FALSE // If TRUE, all moves with dynamic type changes will be reflected as their current type in battle/summary screens instead of just select ones like in vanilla.
|
||||
#define P_SUMMARY_SCREEN_MOVE_RELEARNER TRUE // If TRUE, shows an option for Pokémon to relearn moves on the summary screen moves page.
|
||||
#define P_SUMMARY_MOVE_RELEARNER_FULL_PP TRUE // If TRUE, the move relearner in the summary screen restores relearned moves' PP to full.
|
||||
#define P_SUMMARY_SCREEN_RENAME TRUE // If TRUE, an option to change Pokémon nicknames replaces the cancel prompt on the summary screen info page.
|
||||
|
||||
// Learnset helper toggles
|
||||
#define P_LEARNSET_HELPER_TEACHABLE TRUE // If TRUE, teachable_learnsets.h will be populated by tools/learnset_helpers/teachable.py using the included JSON files based on available TMs and tutors.
|
||||
#define P_LEARNSET_HELPER_TEACHABLE TRUE // If TRUE, teachable_learnsets.h will be populated by tools/learnset_helpers/teachable.py using the included JSON files based on available TMs and tutors.
|
||||
|
||||
// Flag settings
|
||||
// To use the following features in scripting, replace the 0s with the flag ID you're assigning it to.
|
||||
// Eg: Replace with FLAG_UNUSED_0x264 so you can use that flag to toggle the feature.
|
||||
#define P_FLAG_FORCE_SHINY 0 // If this flag is set, all wild and gift Pokémon will forced into being Shiny.
|
||||
#define P_FLAG_FORCE_NO_SHINY 0 // If this flag is set, all wild and gift Pokémon will forced into NOT being Shiny.
|
||||
#define P_FLAG_FORCE_SHINY 0 // If this flag is set, all wild and gift Pokémon will forced into being Shiny.
|
||||
#define P_FLAG_FORCE_NO_SHINY 0 // If this flag is set, all wild and gift Pokémon will forced into NOT being Shiny.
|
||||
|
||||
// Go here if you want to disable specific families of Pokémon.
|
||||
#include "config/species_enabled.h"
|
||||
|
||||
30
include/config/summary_screen.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef GUARD_CONFIG_SUMMARY_SCREEN_H
|
||||
#define GUARD_CONFIG_SUMMARY_SCREEN_H
|
||||
|
||||
// Settings
|
||||
#define P_SUMMARY_SCREEN_MOVE_RELEARNER TRUE // If TRUE, shows an option for Pokémon to relearn moves on the summary screen moves page.
|
||||
#define P_SUMMARY_MOVE_RELEARNER_FULL_PP TRUE // If TRUE, the move relearner in the summary screen restores relearned moves' PP to full.
|
||||
#define P_SUMMARY_SCREEN_RENAME TRUE // If TRUE, an option to change Pokémon nicknames replaces the cancel prompt on the summary screen info page.
|
||||
#define P_SUMMARY_SCREEN_IV_EV_INFO FALSE // If TRUE, will allow player to cycle through the Stats, IVs, and EVs in the summary screen skills page.
|
||||
#define P_SUMMARY_SCREEN_IV_EV_BOX_ONLY FALSE // If TRUE, will allow player to cycle through the Stats, IVs, and EVs in the summary screen skills page, but only in the PC storage box.
|
||||
#define P_SUMMARY_SCREEN_IV_EV_TILESET FALSE // If TRUE, loads an alternate tileset to allow changing the "STATS" label in the summary screen skills page. Note: if it's still loading the alternate tileset after changing this and recompiling, you may need a `make clean` before compilation.
|
||||
#define P_SUMMARY_SCREEN_IV_EV_VALUES FALSE // If TRUE, will show the actual IV value instead of the letter grade.
|
||||
/*
|
||||
LETTER GRADE GUIDE:
|
||||
|
||||
F = 0
|
||||
D = 1 - 15
|
||||
C = 16 - 25
|
||||
B = 26 - 29
|
||||
A = 30
|
||||
S = 31
|
||||
|
||||
Info taken from https://bulbapedia.bulbagarden.net/wiki/Stats_judge.
|
||||
*/
|
||||
#define P_SUMMARY_SCREEN_IV_ONLY FALSE // If TRUE, will only show IV info in the summary screen.
|
||||
#define P_SUMMARY_SCREEN_EV_ONLY FALSE // If TRUE, will only show EV info in the summary screen.
|
||||
|
||||
// Flags
|
||||
#define P_FLAG_SUMMARY_SCREEN_IV_EV_INFO 0 // If this flag is set, will allow player to cycle through the Stats, IVs, and EVs in the summary screen skills page. Note: if P_SUMMARY_SCREEN_IV_EV_INFO is TRUE, this flag does nothing.
|
||||
|
||||
#endif // GUARD_CONFIG_SUMMARY_SCREEN_H
|
||||
@ -364,61 +364,60 @@ enum BattleWeather
|
||||
#define MOVE_EFFECT_PREVENT_ESCAPE 33
|
||||
#define MOVE_EFFECT_NIGHTMARE 34
|
||||
#define MOVE_EFFECT_ALL_STATS_UP 35
|
||||
#define MOVE_EFFECT_RAPID_SPIN 36
|
||||
#define MOVE_EFFECT_REMOVE_STATUS 37
|
||||
#define MOVE_EFFECT_ATK_DEF_DOWN 38
|
||||
#define MOVE_EFFECT_ATK_PLUS_2 39
|
||||
#define MOVE_EFFECT_DEF_PLUS_2 40
|
||||
#define MOVE_EFFECT_SPD_PLUS_2 41
|
||||
#define MOVE_EFFECT_SP_ATK_PLUS_2 42
|
||||
#define MOVE_EFFECT_SP_DEF_PLUS_2 43
|
||||
#define MOVE_EFFECT_ACC_PLUS_2 44
|
||||
#define MOVE_EFFECT_EVS_PLUS_2 45
|
||||
#define MOVE_EFFECT_ATK_MINUS_2 46
|
||||
#define MOVE_EFFECT_DEF_MINUS_2 47
|
||||
#define MOVE_EFFECT_SPD_MINUS_2 48
|
||||
#define MOVE_EFFECT_SP_ATK_MINUS_2 49
|
||||
#define MOVE_EFFECT_SP_DEF_MINUS_2 50
|
||||
#define MOVE_EFFECT_ACC_MINUS_2 51
|
||||
#define MOVE_EFFECT_EVS_MINUS_2 52
|
||||
#define MOVE_EFFECT_SCALE_SHOT 53
|
||||
#define MOVE_EFFECT_THRASH 54
|
||||
#define MOVE_EFFECT_KNOCK_OFF 55
|
||||
#define MOVE_EFFECT_DEF_SPDEF_DOWN 56
|
||||
#define MOVE_EFFECT_CLEAR_SMOG 57
|
||||
#define MOVE_EFFECT_SMACK_DOWN 58
|
||||
#define MOVE_EFFECT_FLAME_BURST 59
|
||||
#define MOVE_EFFECT_FEINT 60
|
||||
#define MOVE_EFFECT_SPECTRAL_THIEF 61
|
||||
#define MOVE_EFFECT_V_CREATE 62
|
||||
#define MOVE_EFFECT_HAPPY_HOUR 63
|
||||
#define MOVE_EFFECT_CORE_ENFORCER 64
|
||||
#define MOVE_EFFECT_THROAT_CHOP 65
|
||||
#define MOVE_EFFECT_INCINERATE 66
|
||||
#define MOVE_EFFECT_BUG_BITE 67
|
||||
#define MOVE_EFFECT_RECOIL_HP_25 68
|
||||
#define MOVE_EFFECT_TRAP_BOTH 69
|
||||
#define MOVE_EFFECT_ROUND 70
|
||||
#define MOVE_EFFECT_STOCKPILE_WORE_OFF 71
|
||||
#define MOVE_EFFECT_DIRE_CLAW 72
|
||||
#define MOVE_EFFECT_STEALTH_ROCK 73
|
||||
#define MOVE_EFFECT_SPIKES 74
|
||||
#define MOVE_EFFECT_SYRUP_BOMB 75
|
||||
#define MOVE_EFFECT_FLORAL_HEALING 76
|
||||
#define MOVE_EFFECT_SECRET_POWER 77
|
||||
#define MOVE_EFFECT_PSYCHIC_NOISE 78
|
||||
#define MOVE_EFFECT_TERA_BLAST 79
|
||||
#define MOVE_EFFECT_ORDER_UP 80
|
||||
#define MOVE_EFFECT_ION_DELUGE 81
|
||||
#define MOVE_EFFECT_AROMATHERAPY 82 // No functionality yet
|
||||
#define MOVE_EFFECT_HAZE 83
|
||||
#define MOVE_EFFECT_LEECH_SEED 84
|
||||
#define MOVE_EFFECT_REFLECT 85
|
||||
#define MOVE_EFFECT_LIGHT_SCREEN 86
|
||||
#define MOVE_EFFECT_SALT_CURE 87
|
||||
#define MOVE_EFFECT_EERIE_SPELL 88
|
||||
#define MOVE_EFFECT_REMOVE_STATUS 36
|
||||
#define MOVE_EFFECT_ATK_DEF_DOWN 37
|
||||
#define MOVE_EFFECT_ATK_PLUS_2 38
|
||||
#define MOVE_EFFECT_DEF_PLUS_2 39
|
||||
#define MOVE_EFFECT_SPD_PLUS_2 40
|
||||
#define MOVE_EFFECT_SP_ATK_PLUS_2 41
|
||||
#define MOVE_EFFECT_SP_DEF_PLUS_2 42
|
||||
#define MOVE_EFFECT_ACC_PLUS_2 43
|
||||
#define MOVE_EFFECT_EVS_PLUS_2 44
|
||||
#define MOVE_EFFECT_ATK_MINUS_2 45
|
||||
#define MOVE_EFFECT_DEF_MINUS_2 46
|
||||
#define MOVE_EFFECT_SPD_MINUS_2 47
|
||||
#define MOVE_EFFECT_SP_ATK_MINUS_2 48
|
||||
#define MOVE_EFFECT_SP_DEF_MINUS_2 49
|
||||
#define MOVE_EFFECT_ACC_MINUS_2 50
|
||||
#define MOVE_EFFECT_EVS_MINUS_2 51
|
||||
#define MOVE_EFFECT_SCALE_SHOT 52
|
||||
#define MOVE_EFFECT_THRASH 53
|
||||
#define MOVE_EFFECT_KNOCK_OFF 54
|
||||
#define MOVE_EFFECT_DEF_SPDEF_DOWN 55
|
||||
#define MOVE_EFFECT_CLEAR_SMOG 56
|
||||
#define MOVE_EFFECT_SMACK_DOWN 57
|
||||
#define MOVE_EFFECT_FLAME_BURST 58
|
||||
#define MOVE_EFFECT_FEINT 59
|
||||
#define MOVE_EFFECT_SPECTRAL_THIEF 60
|
||||
#define MOVE_EFFECT_V_CREATE 61
|
||||
#define MOVE_EFFECT_HAPPY_HOUR 62
|
||||
#define MOVE_EFFECT_CORE_ENFORCER 63
|
||||
#define MOVE_EFFECT_THROAT_CHOP 64
|
||||
#define MOVE_EFFECT_INCINERATE 65
|
||||
#define MOVE_EFFECT_BUG_BITE 66
|
||||
#define MOVE_EFFECT_RECOIL_HP_25 67
|
||||
#define MOVE_EFFECT_TRAP_BOTH 68
|
||||
#define MOVE_EFFECT_ROUND 69
|
||||
#define MOVE_EFFECT_STOCKPILE_WORE_OFF 70
|
||||
#define MOVE_EFFECT_DIRE_CLAW 71
|
||||
#define MOVE_EFFECT_STEALTH_ROCK 72
|
||||
#define MOVE_EFFECT_SPIKES 73
|
||||
#define MOVE_EFFECT_SYRUP_BOMB 74
|
||||
#define MOVE_EFFECT_FLORAL_HEALING 75
|
||||
#define MOVE_EFFECT_SECRET_POWER 76
|
||||
#define MOVE_EFFECT_PSYCHIC_NOISE 77
|
||||
#define MOVE_EFFECT_TERA_BLAST 78
|
||||
#define MOVE_EFFECT_ORDER_UP 79
|
||||
#define MOVE_EFFECT_ION_DELUGE 80
|
||||
#define MOVE_EFFECT_AROMATHERAPY 81 // No functionality yet
|
||||
#define MOVE_EFFECT_HAZE 82
|
||||
#define MOVE_EFFECT_LEECH_SEED 83
|
||||
#define MOVE_EFFECT_REFLECT 84
|
||||
#define MOVE_EFFECT_LIGHT_SCREEN 85
|
||||
#define MOVE_EFFECT_SALT_CURE 86
|
||||
#define MOVE_EFFECT_EERIE_SPELL 87
|
||||
|
||||
#define NUM_MOVE_EFFECTS 89
|
||||
#define NUM_MOVE_EFFECTS 88
|
||||
|
||||
#define MOVE_EFFECT_AFFECTS_USER 0x2000
|
||||
#define MOVE_EFFECT_CERTAIN 0x4000
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
#define AI_FLAG_CHECK_BAD_MOVE (1 << 0) // AI will avoid using moves that are likely to fail or be ineffective in the current situation.
|
||||
#define AI_FLAG_TRY_TO_FAINT (1 << 1) // AI will prioritize KOing the player's mon if able.
|
||||
#define AI_FLAG_CHECK_VIABILITY (1 << 2) // AI damaging moves and move effects to determine the best available move in the current situation.
|
||||
#define AI_FLAG_FORCE_SETUP_FIRST_TURN (1 << 3) // AI will prioritize using setup moves on the first turn at the expensve of all else. AI_FLAG_CHECK_VIABILITY will instead do this when the AI determines it makes sense.
|
||||
#define AI_FLAG_FORCE_SETUP_FIRST_TURN (1 << 3) // AI will prioritize using setup moves on the first turn at the expensve of all else. AI_FLAG_CHECK_VIABILITY will instead do this when the AI determines it makes sense.
|
||||
#define AI_FLAG_RISKY (1 << 4) // AI will generally behave more recklessly, prioritizing damage over accuracy, explosions, etc.
|
||||
#define AI_FLAG_TRY_TO_2HKO (1 << 5) // AI adds score bonus to any move the AI has that either OHKOs or 2HKOs the player.
|
||||
#define AI_FLAG_PREFER_BATON_PASS (1 << 6) // AI prefers raising its own stats and setting for / using Baton Pass.
|
||||
@ -52,12 +52,14 @@
|
||||
#define AI_FLAG_WEIGH_ABILITY_PREDICTION (1 << 21) // AI will predict player's ability based on aiRating
|
||||
#define AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE (1 << 22) // AI adds score to highest damage move regardless of accuracy or secondary effect
|
||||
#define AI_FLAG_PREDICT_SWITCH (1 << 23) // AI will predict the player's switches and switchins based on how it would handle the situation. Recommend using AI_FLAG_OMNISCIENT
|
||||
#define AI_FLAG_PREDICT_INCOMING_MON (1 << 24) // AI will score against the predicting incoming mon if it predicts the player to switch. Requires AI_FLAG_PREDICT_SWITCH
|
||||
|
||||
#define AI_FLAG_COUNT 24
|
||||
#define AI_FLAG_COUNT 25
|
||||
|
||||
// The following options are enough to have a basic/smart trainer. Any other addtion could make the trainer worse/better depending on the flag
|
||||
#define AI_FLAG_BASIC_TRAINER (AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY)
|
||||
#define AI_FLAG_SMART_TRAINER (AI_FLAG_BASIC_TRAINER | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_WEIGH_ABILITY_PREDICTION)
|
||||
#define AI_FLAG_PREDICTION (AI_FLAG_PREDICT_SWITCH | AI_FLAG_PREDICT_INCOMING_MON)
|
||||
|
||||
// 'other' ai logic flags
|
||||
#define AI_FLAG_DYNAMIC_FUNC (1 << 28) // Create custom AI functions for specific battles via "setdynamicaifunc" cmd
|
||||
|
||||
@ -351,6 +351,7 @@ enum {
|
||||
EFFECT_GUARDIAN_OF_ALOLA,
|
||||
EFFECT_SHELL_SIDE_ARM,
|
||||
EFFECT_ORDER_UP,
|
||||
EFFECT_RAPID_SPIN,
|
||||
NUM_BATTLE_MOVE_EFFECTS,
|
||||
};
|
||||
|
||||
|
||||
@ -284,6 +284,7 @@ enum MoveEndEffects
|
||||
MOVEEND_MULTIHIT_MOVE,
|
||||
MOVEEND_DEFROST,
|
||||
MOVEEND_RECOIL,
|
||||
MOVEEND_RAPID_SPIN,
|
||||
MOVEEND_ITEM_EFFECTS_ATTACKER,
|
||||
MOVEEND_MAGICIAN, // Occurs after final multi-hit strike, and after other items/abilities would activate
|
||||
MOVEEND_RED_CARD, // Red Card triggers before Eject Pack
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#include "config/pokemon.h"
|
||||
#include "config/overworld.h"
|
||||
#include "config/dexnav.h"
|
||||
#include "config/summary_screen.h"
|
||||
|
||||
// Invalid Versions show as "----------" in Gen 4 and Gen 5's summary screen.
|
||||
// In Gens 6 and 7, invalid versions instead show "a distant land" in the summary screen.
|
||||
|
||||
42
include/constants/trainer_slide.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef GUARD_CONSTANTS_TRAINER_SLIDE_H
|
||||
#define GUARD_CONSTANTS_TRAINER_SLIDE_H
|
||||
|
||||
enum ComparisonOperators
|
||||
{
|
||||
LESS_THAN,
|
||||
EQUAL,
|
||||
GREATER_THAN,
|
||||
LESS_THAN_OR_EQUAL,
|
||||
GREATER_THAN_OR_EQUAL,
|
||||
NOT_EQUAL,
|
||||
};
|
||||
|
||||
enum TrainerSlideType
|
||||
{
|
||||
TRAINER_SLIDE_BEFORE_FIRST_TURN,
|
||||
TRAINER_SLIDE_PLAYER_LANDS_FIRST_CRITICAL_HIT,
|
||||
TRAINER_SLIDE_ENEMY_LANDS_FIRST_CRITICAL_HIT,
|
||||
TRAINER_SLIDE_PLAYER_LANDS_FIRST_SUPER_EFFECTIVE_HIT,
|
||||
TRAINER_SLIDE_PLAYER_LANDS_FIRST_STAB_MOVE,
|
||||
TRAINER_SLIDE_PLAYER_LANDS_FIRST_DOWN,
|
||||
TRAINER_SLIDE_ENEMY_MON_UNAFFECTED,
|
||||
TRAINER_SLIDE_LAST_SWITCHIN,
|
||||
TRAINER_SLIDE_LAST_HALF_HP,
|
||||
TRAINER_SLIDE_LAST_LOW_HP,
|
||||
TRAINER_SLIDE_MEGA_EVOLUTION,
|
||||
TRAINER_SLIDE_Z_MOVE,
|
||||
TRAINER_SLIDE_DYNAMAX,
|
||||
TRAINER_SLIDE_COUNT,
|
||||
};
|
||||
|
||||
#define TRAINER_SLIDES_PER_ARRAY 8
|
||||
#define TRAINER_SLIDE_ARRAY_SIZE ((TRAINER_SLIDE_COUNT + TRAINER_SLIDES_PER_ARRAY - 1) / TRAINER_SLIDES_PER_ARRAY)
|
||||
|
||||
enum TrainerSlideTargets
|
||||
{
|
||||
TRAINER_SLIDE_TARGET_NONE,
|
||||
TRAINER_SLIDE_TARGET_TRAINER_A,
|
||||
TRAINER_SLIDE_TARGET_TRAINER_B,
|
||||
};
|
||||
|
||||
#endif // GUARD_CONSTANTS_TRAINER_SLIDE_H
|
||||
@ -3,20 +3,20 @@
|
||||
|
||||
#include "sprite.h"
|
||||
|
||||
extern u8 ALIGNED(4) gDecompressionBuffer[0x4000];
|
||||
#define MAX_DECOMPRESSION_BUFFER_SIZE 0x4000
|
||||
|
||||
void LZDecompressWram(const u32 *src, void *dest);
|
||||
void LZDecompressVram(const u32 *src, void *dest);
|
||||
|
||||
u32 IsLZ77Data(const void *ptr, u32 minSize, u32 maxSize);
|
||||
|
||||
u16 LoadCompressedSpriteSheet(const struct CompressedSpriteSheet *src);
|
||||
u16 LoadCompressedSpriteSheetByTemplate(const struct SpriteTemplate *template, s32 offset);
|
||||
void LoadCompressedSpriteSheetOverrideBuffer(const struct CompressedSpriteSheet *src, void *buffer);
|
||||
u32 LoadCompressedSpriteSheet(const struct CompressedSpriteSheet *src);
|
||||
u32 LoadCompressedSpriteSheetByTemplate(const struct SpriteTemplate *template, s32 offset);
|
||||
u32 LoadCompressedSpriteSheetOverrideBuffer(const struct CompressedSpriteSheet *src, void *buffer);
|
||||
bool8 LoadCompressedSpriteSheetUsingHeap(const struct CompressedSpriteSheet *src);
|
||||
|
||||
void LoadCompressedSpritePalette(const struct CompressedSpritePalette *src);
|
||||
void LoadCompressedSpritePaletteWithTag(const u32 *pal, u16 tag);
|
||||
u32 LoadCompressedSpritePalette(const struct CompressedSpritePalette *src);
|
||||
u32 LoadCompressedSpritePaletteWithTag(const u32 *pal, u16 tag);
|
||||
void LoadCompressedSpritePaletteOverrideBuffer(const struct CompressedSpritePalette *src, void *buffer);
|
||||
bool8 LoadCompressedSpritePaletteUsingHeap(const struct CompressedSpritePalette *src);
|
||||
|
||||
|
||||
@ -48,4 +48,6 @@ extern u16 gSpecialVar_MonBoxId;
|
||||
extern u16 gSpecialVar_MonBoxPos;
|
||||
extern u16 gSpecialVar_Unused_0x8014;
|
||||
|
||||
extern const u16 gBadgeFlags[NUM_BADGES];
|
||||
|
||||
#endif // GUARD_EVENT_DATA_H
|
||||
|
||||
@ -1,6 +1,23 @@
|
||||
#ifndef GUARD_HALL_OF_FAME_H
|
||||
#define GUARD_HALL_OF_FAME_H
|
||||
|
||||
struct HallofFameMon
|
||||
{
|
||||
u32 tid;
|
||||
u32 personality;
|
||||
u16 isShiny:1;
|
||||
u16 species:15;
|
||||
u8 lvl;
|
||||
u8 nickname[POKEMON_NAME_LENGTH];
|
||||
};
|
||||
|
||||
struct HallofFameTeam
|
||||
{
|
||||
struct HallofFameMon mon[PARTY_SIZE];
|
||||
};
|
||||
|
||||
extern struct HallofFameTeam *gHoFSaveBuffer;
|
||||
|
||||
void CB2_DoHallOfFameScreen(void);
|
||||
void CB2_DoHallOfFameScreenDontSaveData(void);
|
||||
void CB2_DoHallOfFamePC(void);
|
||||
|
||||
@ -17,9 +17,19 @@ void RemoveBagItemIconSprite(u8 id);
|
||||
void CreateItemMenuSwapLine(void);
|
||||
void SetItemMenuSwapLineInvisibility(bool8 invisible);
|
||||
void UpdateItemMenuSwapLinePos(u8 y);
|
||||
u8 CreateBerryTagSprite(u8 id, s16 x, s16 y);
|
||||
void FreeBerryTagSpritePalette(void);
|
||||
u8 CreateSpinningBerrySprite(u8 berryId, u8 x, u8 y, bool8 startAffine);
|
||||
|
||||
// Note: Because of removing gDecompressionBuffer and allowing to create more than one berry sprite at a time, the memory for gfx is allocated dynamically.
|
||||
// For CreateBerryTagSprite and CreateSpinningBerrySprite, the allocated ptr is stored in two last data fields(data[6], data[7]), so make sure to NOT put anything in there!
|
||||
// The corresponding code has already been edited in berry_tag_screen.c and berry_blender.c
|
||||
#define BERRY_ICON_GFX_PTR_DATA_ID 6
|
||||
u32 CreateBerryTagSprite(u32 id, s32 x, s32 y);
|
||||
u32 CreateSpinningBerrySprite(u32 berryId, s32 x, s32 y, bool32 startAffine);
|
||||
// Needs to always call either of these after creating a Berry Icon sprite, because it frees allocated memory!
|
||||
void DestroyBerryIconSprite(u32 spriteId, u32 berryId, bool32 freePal);
|
||||
void DestroyBerryIconSpritePtr(struct Sprite *sprite, u32 berryId, bool32 freePal);
|
||||
|
||||
void FreeBerryIconSpritePalette(u32 berryId); // Unused atm, because it's also handled by DestroyBerryIconSprite. Leaving it as it is, because it may still be useful in some custom cases.
|
||||
|
||||
u8 CreateBerryFlavorCircleSprite(s16 x);
|
||||
|
||||
#endif // GUARD_ITEM_MENU_ICONS_H
|
||||
|
||||
@ -81,6 +81,7 @@ struct MysteryGiftClient
|
||||
void * msg;
|
||||
struct MysteryGiftLink link;
|
||||
bool32 isWonderNews;
|
||||
ALIGNED(4) u8 bufferScript[MG_LINK_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
void MysteryGiftClient_Create(bool32 isWonderNews);
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#define GUARD_POKEMON_SUMMARY_SCREEN_H
|
||||
|
||||
#include "main.h"
|
||||
#include "config/summary_screen.h"
|
||||
|
||||
extern u8 gLastViewedMonIndex;
|
||||
|
||||
@ -40,4 +41,11 @@ enum PokemonSummaryScreenPage
|
||||
PSS_PAGE_COUNT,
|
||||
};
|
||||
|
||||
enum PokemonSummarySkillsMode
|
||||
{
|
||||
SUMMARY_SKILLS_MODE_STATS,
|
||||
SUMMARY_SKILLS_MODE_IVS,
|
||||
SUMMARY_SKILLS_MODE_EVS,
|
||||
};
|
||||
|
||||
#endif // GUARD_POKEMON_SUMMARY_SCREEN_H
|
||||
|
||||
@ -318,11 +318,11 @@ u16 GetSpriteTileTagByTileStart(u16 start);
|
||||
void RequestSpriteSheetCopy(const struct SpriteSheet *sheet);
|
||||
u16 LoadSpriteSheetDeferred(const struct SpriteSheet *sheet);
|
||||
void FreeAllSpritePalettes(void);
|
||||
u8 LoadSpritePalette(const struct SpritePalette *palette);
|
||||
u32 LoadSpritePalette(const struct SpritePalette *palette);
|
||||
u8 LoadSpritePaletteInSlot(const struct SpritePalette *palette, u8 paletteNum);
|
||||
void LoadSpritePalettes(const struct SpritePalette *palettes);
|
||||
u8 AllocSpritePalette(u16 tag);
|
||||
u8 IndexOfSpritePaletteTag(u16 tag);
|
||||
u32 AllocSpritePalette(u16 tag);
|
||||
u32 IndexOfSpritePaletteTag(u16 tag);
|
||||
u16 GetSpritePaletteTagByPaletteNum(u8 paletteNum);
|
||||
void FreeSpritePaletteByTag(u16 tag);
|
||||
void SetSubspriteTables(struct Sprite *sprite, const struct SubspriteTable *subspriteTables);
|
||||
|
||||
25
include/trainer_slide.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef GUARD_TRAINER_SLIDE_H
|
||||
#define GUARD_TRAINER_SLIDE_H
|
||||
|
||||
#include "constants/trainer_slide.h"
|
||||
|
||||
|
||||
struct MessageStatus
|
||||
{
|
||||
u8 messageInitalized[TRAINER_SLIDE_ARRAY_SIZE];
|
||||
u8 messagePlayed[TRAINER_SLIDE_ARRAY_SIZE];
|
||||
};
|
||||
|
||||
void SetTrainerSlideMessage(enum DifficultyLevel difficulty, u32 trainerId, u32 slideId);
|
||||
enum TrainerSlideTargets ShouldDoTrainerSlide(u32 battler, enum TrainerSlideType slideId);
|
||||
void TryInitalizeFirstSTABMoveTrainerSlide(u32 battlerDef, u32 battlerAtk, u32 moveType);
|
||||
void TryInitalizeTrainerSlidePlayerLandsFirstCriticalHit(u32 target);
|
||||
void TryInitalizeTrainerSlideEnemyLandsFirstCriticalHit(u32 target);
|
||||
void TryInitalizeTrainerSlidePlayerLandsFirstSuperEffectiveHit(u32 target);
|
||||
void TryInitalizeTrainerSlideEnemyMonUnaffected(u32 target);
|
||||
bool32 IsTrainerSlideInitialized(enum TrainerSlideType slideId);
|
||||
bool32 IsTrainerSlidePlayed(enum TrainerSlideType slideId);
|
||||
void InitalizeTrainerSlide(enum TrainerSlideType slideId);
|
||||
void MarkTrainerSlideAsPlayed(enum TrainerSlideType slideId);
|
||||
|
||||
#endif // GUARD_TRAINER_SLIDE_H
|
||||
@ -35,6 +35,7 @@
|
||||
static u32 ChooseMoveOrAction_Singles(u32 battlerAi);
|
||||
static u32 ChooseMoveOrAction_Doubles(u32 battlerAi);
|
||||
static inline void BattleAI_DoAIProcessing(struct AI_ThinkingStruct *aiThink, u32 battlerAi, u32 battlerDef);
|
||||
static inline void BattleAI_DoAIProcessing_PredictedSwitchin(struct AI_ThinkingStruct *aiThink, struct AiLogicData *aiData, u32 battlerAi, u32 battlerDef);
|
||||
static bool32 IsPinchBerryItemEffect(u32 holdEffect);
|
||||
|
||||
// ewram
|
||||
@ -183,6 +184,10 @@ static u32 GetAiFlags(u16 trainerId)
|
||||
if (flags & AI_FLAG_SMART_SWITCHING)
|
||||
flags |= AI_FLAG_SMART_MON_CHOICES;
|
||||
|
||||
// Automatically includes AI_FLAG_PREDICT_SWITCH if AI_FLAG_PREDICT_INCOMING_MON is being used
|
||||
if (flags & AI_FLAG_PREDICT_INCOMING_MON)
|
||||
flags |= AI_FLAG_PREDICT_SWITCH;
|
||||
|
||||
if (sDynamicAiFunc != NULL)
|
||||
flags |= AI_FLAG_DYNAMIC_FUNC;
|
||||
|
||||
@ -407,14 +412,35 @@ static u32 Ai_SetMoveAccuracy(struct AiLogicData *aiData, u32 battlerAtk, u32 ba
|
||||
return accuracy;
|
||||
}
|
||||
|
||||
static void CalcBattlerAiMovesData(struct AiLogicData *aiData, u32 battlerAtk, u32 battlerDef, u32 weather)
|
||||
{
|
||||
u32 moveIndex, move;
|
||||
u32 rollType = GetDmgRollType(battlerAtk);
|
||||
u16 *moves = GetMovesArray(battlerAtk);
|
||||
|
||||
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
|
||||
{
|
||||
struct SimulatedDamage dmg = {0};
|
||||
u8 effectiveness = AI_EFFECTIVENESS_x0;
|
||||
move = moves[moveIndex];
|
||||
|
||||
if (move != MOVE_NONE
|
||||
&& move != MOVE_UNAVAILABLE
|
||||
//&& !IsBattleMoveStatus(move) /* we want to get effectiveness and accuracy of status moves */
|
||||
&& !(aiData->moveLimitations[battlerAtk] & (1u << moveIndex)))
|
||||
{
|
||||
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, TRUE, weather, rollType);
|
||||
aiData->moveAccuracy[battlerAtk][battlerDef][moveIndex] = Ai_SetMoveAccuracy(aiData, battlerAtk, battlerDef, move);
|
||||
}
|
||||
aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex] = dmg;
|
||||
aiData->effectiveness[battlerAtk][battlerDef][moveIndex] = effectiveness;
|
||||
}
|
||||
}
|
||||
|
||||
static void SetBattlerAiMovesData(struct AiLogicData *aiData, u32 battlerAtk, u32 battlersCount, u32 weather)
|
||||
{
|
||||
u16 *moves;
|
||||
u32 battlerDef, moveIndex, move;
|
||||
u32 rollType = GetDmgRollType(battlerAtk);
|
||||
u32 battlerDef;
|
||||
SaveBattlerData(battlerAtk);
|
||||
moves = GetMovesArray(battlerAtk);
|
||||
|
||||
SetBattlerData(battlerAtk);
|
||||
|
||||
// Simulate dmg for both ai controlled mons and for player controlled mons.
|
||||
@ -425,23 +451,7 @@ static void SetBattlerAiMovesData(struct AiLogicData *aiData, u32 battlerAtk, u3
|
||||
|
||||
SaveBattlerData(battlerDef);
|
||||
SetBattlerData(battlerDef);
|
||||
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
|
||||
{
|
||||
struct SimulatedDamage dmg = {0};
|
||||
u8 effectiveness = AI_EFFECTIVENESS_x0;
|
||||
move = moves[moveIndex];
|
||||
|
||||
if (move != MOVE_NONE
|
||||
&& move != MOVE_UNAVAILABLE
|
||||
//&& !IsBattleMoveStatus(move) /* we want to get effectiveness and accuracy of status moves */
|
||||
&& !(aiData->moveLimitations[battlerAtk] & (1u << moveIndex)))
|
||||
{
|
||||
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, TRUE, weather, rollType);
|
||||
aiData->moveAccuracy[battlerAtk][battlerDef][moveIndex] = Ai_SetMoveAccuracy(aiData, battlerAtk, battlerDef, move);
|
||||
}
|
||||
aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex] = dmg;
|
||||
aiData->effectiveness[battlerAtk][battlerDef][moveIndex] = effectiveness;
|
||||
}
|
||||
CalcBattlerAiMovesData(aiData, battlerAtk, battlerDef, weather);
|
||||
RestoreBattlerData(battlerDef);
|
||||
}
|
||||
RestoreBattlerData(battlerAtk);
|
||||
@ -458,7 +468,7 @@ void SetAiLogicDataForTurn(struct AiLogicData *aiData)
|
||||
// Set delay timer to count how long it takes for AI to choose action/move
|
||||
gBattleStruct->aiDelayTimer = gMain.vblankCounter1;
|
||||
|
||||
aiData->weatherHasEffect = WEATHER_HAS_EFFECT;
|
||||
aiData->weatherHasEffect = HasWeatherEffect();
|
||||
weather = AI_GetWeather(aiData);
|
||||
|
||||
// get/assume all battler data and simulate AI damage
|
||||
@ -496,7 +506,10 @@ static u32 ChooseMoveOrAction_Singles(u32 battlerAi)
|
||||
{
|
||||
if (flags & 1)
|
||||
{
|
||||
BattleAI_DoAIProcessing(AI_THINKING_STRUCT, battlerAi, gBattlerTarget);
|
||||
if (IsBattlerPredictedToSwitch(gBattlerTarget) && (AI_THINKING_STRUCT->aiFlags[battlerAi] & AI_FLAG_PREDICT_INCOMING_MON))
|
||||
BattleAI_DoAIProcessing_PredictedSwitchin(AI_THINKING_STRUCT, AI_DATA, battlerAi, gBattlerTarget);
|
||||
else
|
||||
BattleAI_DoAIProcessing(AI_THINKING_STRUCT, battlerAi, gBattlerTarget);
|
||||
}
|
||||
flags >>= 1;
|
||||
AI_THINKING_STRUCT->aiLogicId++;
|
||||
@ -576,7 +589,10 @@ static u32 ChooseMoveOrAction_Doubles(u32 battlerAi)
|
||||
{
|
||||
if (flags & 1)
|
||||
{
|
||||
BattleAI_DoAIProcessing(AI_THINKING_STRUCT, battlerAi, gBattlerTarget);
|
||||
if (IsBattlerPredictedToSwitch(gBattlerTarget) && (AI_THINKING_STRUCT->aiFlags[battlerAi] & AI_FLAG_PREDICT_INCOMING_MON))
|
||||
BattleAI_DoAIProcessing_PredictedSwitchin(AI_THINKING_STRUCT, AI_DATA, battlerAi, gBattlerTarget);
|
||||
else
|
||||
BattleAI_DoAIProcessing(AI_THINKING_STRUCT, battlerAi, gBattlerTarget);
|
||||
}
|
||||
flags >>= 1;
|
||||
AI_THINKING_STRUCT->aiLogicId++;
|
||||
@ -703,6 +719,116 @@ static inline void BattleAI_DoAIProcessing(struct AI_ThinkingStruct *aiThink, u3
|
||||
aiThink->movesetIndex = 0;
|
||||
}
|
||||
|
||||
void BattleAI_DoAIProcessing_PredictedSwitchin(struct AI_ThinkingStruct *aiThink, struct AiLogicData *aiData, u32 battlerAtk, u32 battlerDef)
|
||||
{
|
||||
struct BattlePokemon switchoutCandidate = gBattleMons[battlerDef];
|
||||
struct SimulatedDamage simulatedDamageSwitchout[4];
|
||||
u8 effectivenessSwitchout[4];
|
||||
u8 moveAccuracySwitchout[4];
|
||||
|
||||
struct BattlePokemon switchinCandidate;
|
||||
struct SimulatedDamage simulatedDamageSwitchin[4];
|
||||
u8 effectivenessSwitchin[4];
|
||||
u8 moveAccuracySwitchin[4];
|
||||
|
||||
struct Pokemon *party = GetBattlerParty(battlerDef);
|
||||
struct BattlePokemon *savedBattleMons = AllocSaveBattleMons();
|
||||
u32 moveIndex;
|
||||
|
||||
// Store battler moves data to save time over recalculating it
|
||||
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
|
||||
{
|
||||
simulatedDamageSwitchout[moveIndex] = aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex];
|
||||
effectivenessSwitchout[moveIndex] = aiData->effectiveness[battlerAtk][battlerDef][moveIndex];
|
||||
moveAccuracySwitchout[moveIndex] = aiData->moveAccuracy[battlerAtk][battlerDef][moveIndex];
|
||||
}
|
||||
|
||||
// Get battler and move data for predicted switchin
|
||||
PokemonToBattleMon(&party[aiData->mostSuitableMonId[battlerDef]], &switchinCandidate);
|
||||
gBattleMons[battlerDef] = switchinCandidate;
|
||||
SetBattlerAiData(battlerDef, aiData);
|
||||
CalcBattlerAiMovesData(aiData, battlerAtk, battlerDef, AI_GetWeather(aiData));
|
||||
|
||||
// Regular processing with new battler
|
||||
do
|
||||
{
|
||||
if (gBattleMons[battlerAtk].pp[aiThink->movesetIndex] == 0)
|
||||
aiThink->moveConsidered = MOVE_NONE;
|
||||
else
|
||||
aiThink->moveConsidered = gBattleMons[battlerAtk].moves[aiThink->movesetIndex];
|
||||
|
||||
// There is no point in calculating scores for all 3 battlers(2 opponents + 1 ally) with certain moves.
|
||||
if (aiThink->moveConsidered != MOVE_NONE
|
||||
&& aiThink->score[aiThink->movesetIndex] > 0
|
||||
&& ShouldConsiderMoveForBattler(battlerAtk, battlerDef, aiThink->moveConsidered))
|
||||
{
|
||||
if (IsChaseEffect(gMovesInfo[aiThink->moveConsidered].effect))
|
||||
{
|
||||
// Save new switchin data
|
||||
simulatedDamageSwitchin[aiThink->movesetIndex] = aiData->simulatedDmg[battlerAtk][battlerDef][aiThink->movesetIndex];
|
||||
effectivenessSwitchin[aiThink->movesetIndex] = aiData->effectiveness[battlerAtk][battlerDef][aiThink->movesetIndex];
|
||||
moveAccuracySwitchin[aiThink->movesetIndex] = aiData->moveAccuracy[battlerAtk][battlerDef][aiThink->movesetIndex];
|
||||
|
||||
// Restore old switchout data
|
||||
gBattleMons[battlerDef] = switchoutCandidate;
|
||||
SetBattlerAiData(battlerDef, aiData);
|
||||
aiData->simulatedDmg[battlerAtk][battlerDef][aiThink->movesetIndex] = simulatedDamageSwitchout[aiThink->movesetIndex];
|
||||
aiData->effectiveness[battlerAtk][battlerDef][aiThink->movesetIndex] = effectivenessSwitchout[aiThink->movesetIndex];
|
||||
aiData->moveAccuracy[battlerAtk][battlerDef][aiThink->movesetIndex] = moveAccuracySwitchout[aiThink->movesetIndex];
|
||||
|
||||
if (aiThink->aiLogicId < ARRAY_COUNT(sBattleAiFuncTable)
|
||||
&& sBattleAiFuncTable[aiThink->aiLogicId] != NULL)
|
||||
{
|
||||
// Call AI function
|
||||
aiThink->score[aiThink->movesetIndex] =
|
||||
sBattleAiFuncTable[aiThink->aiLogicId](battlerAtk,
|
||||
battlerDef,
|
||||
aiThink->moveConsidered,
|
||||
aiThink->score[aiThink->movesetIndex]);
|
||||
}
|
||||
|
||||
// Restore new switchin data
|
||||
gBattleMons[battlerDef] = switchinCandidate;
|
||||
SetBattlerAiData(battlerDef, aiData);
|
||||
aiData->simulatedDmg[battlerAtk][battlerDef][aiThink->movesetIndex] = simulatedDamageSwitchin[aiThink->movesetIndex];
|
||||
aiData->effectiveness[battlerAtk][battlerDef][aiThink->movesetIndex] = effectivenessSwitchin[aiThink->movesetIndex];
|
||||
aiData->moveAccuracy[battlerAtk][battlerDef][aiThink->movesetIndex] = moveAccuracySwitchin[aiThink->movesetIndex];
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (aiThink->aiLogicId < ARRAY_COUNT(sBattleAiFuncTable)
|
||||
&& sBattleAiFuncTable[aiThink->aiLogicId] != NULL)
|
||||
{
|
||||
// Call AI function
|
||||
aiThink->score[aiThink->movesetIndex] =
|
||||
sBattleAiFuncTable[aiThink->aiLogicId](battlerAtk,
|
||||
battlerDef,
|
||||
aiThink->moveConsidered,
|
||||
aiThink->score[aiThink->movesetIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aiThink->score[aiThink->movesetIndex] = 0;
|
||||
}
|
||||
aiThink->movesetIndex++;
|
||||
} while (aiThink->movesetIndex < MAX_MON_MOVES && !(aiThink->aiAction & AI_ACTION_DO_NOT_ATTACK));
|
||||
|
||||
aiThink->movesetIndex = 0;
|
||||
|
||||
// Restore original battler data and moves
|
||||
FreeRestoreBattleMons(savedBattleMons);
|
||||
SetBattlerAiData(battlerDef, aiData);
|
||||
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
|
||||
{
|
||||
aiData->simulatedDmg[battlerAtk][battlerDef][moveIndex] = simulatedDamageSwitchout[moveIndex];
|
||||
aiData->effectiveness[battlerAtk][battlerDef][moveIndex] = effectivenessSwitchout[moveIndex];
|
||||
aiData->moveAccuracy[battlerAtk][battlerDef][moveIndex] = moveAccuracySwitchout[moveIndex];
|
||||
}
|
||||
}
|
||||
|
||||
// AI Score Functions
|
||||
// AI_FLAG_CHECK_BAD_MOVE - decreases move scores
|
||||
static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
@ -1707,7 +1833,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
|| !IsBattlerAlive(BATTLE_PARTNER(battlerAtk))
|
||||
|| PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)
|
||||
|| (aiData->partnerMove != MOVE_NONE && IsBattleMoveStatus(aiData->partnerMove))
|
||||
|| *(gBattleStruct->monToSwitchIntoId + BATTLE_PARTNER(battlerAtk)) != PARTY_SIZE) //Partner is switching out.
|
||||
|| gBattleStruct->monToSwitchIntoId[BATTLE_PARTNER(battlerAtk)] != PARTY_SIZE) //Partner is switching out.
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_TRICK:
|
||||
@ -2965,7 +3091,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
case EFFECT_ENTRAINMENT:
|
||||
if (partnerHasBadAbility && IsAbilityOfRating(aiData->abilities[battlerAtk], 0))
|
||||
{
|
||||
RETURN_SCORE_PLUS(WEAK_EFFECT);
|
||||
RETURN_SCORE_PLUS(DECENT_EFFECT);
|
||||
}
|
||||
break;
|
||||
case EFFECT_SOAK:
|
||||
@ -3516,7 +3642,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
case EFFECT_LEECH_SEED:
|
||||
if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS)
|
||||
|| gStatuses3[battlerDef] & STATUS3_LEECHSEED
|
||||
|| HasMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_RAPID_SPIN)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_RAPID_SPIN)
|
||||
|| aiData->abilities[battlerDef] == ABILITY_LIQUID_OOZE
|
||||
|| aiData->abilities[battlerDef] == ABILITY_MAGIC_GUARD)
|
||||
break;
|
||||
@ -4072,9 +4198,13 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
case EFFECT_ENTRAINMENT:
|
||||
if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX)
|
||||
break;
|
||||
else if ((IsAbilityOfRating(aiData->abilities[battlerDef], 5) || gAbilitiesInfo[aiData->abilities[battlerAtk]].aiRating <= 0)
|
||||
&& (aiData->abilities[battlerDef] != aiData->abilities[battlerAtk] && !(gStatuses3[battlerDef] & STATUS3_GASTRO_ACID)))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
if (aiData->abilities[battlerDef] != aiData->abilities[battlerAtk] && !(gStatuses3[battlerDef] & STATUS3_GASTRO_ACID))
|
||||
{
|
||||
if (gAbilitiesInfo[aiData->abilities[battlerAtk]].aiRating <= 0)
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
else if (IsAbilityOfRating(aiData->abilities[battlerDef], 5) && gAbilitiesInfo[aiData->abilities[battlerAtk]].aiRating <= 3)
|
||||
ADJUST_SCORE(WEAK_EFFECT);
|
||||
}
|
||||
break;
|
||||
case EFFECT_IMPRISON:
|
||||
if (predictedMove != MOVE_NONE && HasMove(battlerAtk, predictedMove))
|
||||
@ -4431,6 +4561,12 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
|| gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & STATUS1_ANY)
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
break;
|
||||
case EFFECT_RAPID_SPIN:
|
||||
if ((gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerAtk) != 0)
|
||||
|| (gStatuses3[battlerAtk] & STATUS3_LEECHSEED || gBattleMons[battlerAtk].status2 & STATUS2_WRAPPED))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
break;
|
||||
|
||||
} // move effect checks
|
||||
|
||||
u32 additionalEffectCount = GetMoveAdditionalEffectCount(move);
|
||||
@ -4475,11 +4611,6 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
case MOVE_EFFECT_EVS_PLUS_2:
|
||||
ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_EVASION));
|
||||
break;
|
||||
case MOVE_EFFECT_RAPID_SPIN:
|
||||
if ((gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerAtk) != 0)
|
||||
|| (gStatuses3[battlerAtk] & STATUS3_LEECHSEED || gBattleMons[battlerAtk].status2 & STATUS2_WRAPPED))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -4674,7 +4805,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_WRAP:
|
||||
if (!HasMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_RAPID_SPIN) && ShouldTrap(battlerAtk, battlerDef, move))
|
||||
if (!HasMoveEffect(battlerDef, EFFECT_RAPID_SPIN) && ShouldTrap(battlerAtk, battlerDef, move))
|
||||
ADJUST_SCORE(BEST_EFFECT);
|
||||
break;
|
||||
case MOVE_EFFECT_SALT_CURE:
|
||||
@ -5284,10 +5415,16 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
switch (moveEffect)
|
||||
{
|
||||
case EFFECT_PURSUIT:
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
{
|
||||
u32 hitsToKO = GetNoOfHitsToKOBattler(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex);
|
||||
if (hitsToKO == 2)
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
else if (hitsToKO == 1)
|
||||
ADJUST_SCORE(BEST_EFFECT);
|
||||
// else if (IsPredictedToUsePursuitableMove(battlerDef, battlerAtk) && !MoveWouldHitFirst(move, battlerAtk, battlerDef)) //Pursuit against fast U-Turn
|
||||
// ADJUST_SCORE(GOOD_EFFECT);
|
||||
break;
|
||||
}
|
||||
|
||||
case EFFECT_FOCUS_PUNCH:
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
@ -5338,6 +5475,10 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
if (opposingHazardFlags != 0)
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
break;
|
||||
case EFFECT_RAPID_SPIN:
|
||||
if (aiHazardFlags != 0)
|
||||
ADJUST_SCORE(BEST_EFFECT);
|
||||
break;
|
||||
case EFFECT_DEFOG:
|
||||
if (aiHazardFlags != 0)
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
@ -5393,10 +5534,6 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
case MOVE_EFFECT_WRAP:
|
||||
ADJUST_SCORE(-GOOD_EFFECT);
|
||||
break;
|
||||
case MOVE_EFFECT_RAPID_SPIN:
|
||||
if (aiHazardFlags != 0)
|
||||
ADJUST_SCORE(BEST_EFFECT);
|
||||
break;
|
||||
case MOVE_EFFECT_FEINT:
|
||||
ADJUST_SCORE(-BEST_EFFECT);
|
||||
break;
|
||||
|
||||
@ -197,7 +197,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
|
||||
&& gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 4)))
|
||||
{
|
||||
// 50% chance to stay in regardless
|
||||
if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, 50) || AI_DATA->aiSwitchPredictionInProgress)
|
||||
if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, 50) && !AI_DATA->aiSwitchPredictionInProgress)
|
||||
return FALSE;
|
||||
|
||||
// Switch mon out
|
||||
@ -217,7 +217,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
|
||||
return FALSE;
|
||||
|
||||
// 50% chance to stay in regardless
|
||||
if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, 50) || AI_DATA->aiSwitchPredictionInProgress)
|
||||
if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, 50) && !AI_DATA->aiSwitchPredictionInProgress)
|
||||
return FALSE;
|
||||
|
||||
// Switch mon out
|
||||
@ -482,7 +482,7 @@ static bool32 ShouldSwitchIfTrapperInParty(u32 battler)
|
||||
|
||||
monAbility = GetMonAbility(&party[i]);
|
||||
|
||||
if (CanAbilityTrapOpponent(monAbility, opposingBattler))
|
||||
if (CanAbilityTrapOpponent(monAbility, opposingBattler) || (CanAbilityTrapOpponent(AI_GetBattlerAbility(opposingBattler), opposingBattler) && monAbility == ABILITY_TRACE))
|
||||
{
|
||||
// If mon in slot i is the most suitable switchin candidate, then it's a trapper than wins 1v1
|
||||
if (i == AI_DATA->mostSuitableMonId[battler])
|
||||
@ -825,7 +825,7 @@ static bool32 CanMonSurviveHazardSwitchin(u32 battler)
|
||||
{
|
||||
aiMove = GetMonData(&party[i], MON_DATA_MOVE1 + j, NULL);
|
||||
u32 aiEffect = GetMoveEffect(aiMove);
|
||||
if (MoveHasAdditionalEffectSelf(aiMove, MOVE_EFFECT_RAPID_SPIN)
|
||||
if (aiEffect == EFFECT_RAPID_SPIN
|
||||
|| (B_DEFOG_EFFECT_CLEARING >= GEN_6 && aiEffect == EFFECT_DEFOG)
|
||||
|| aiEffect == EFFECT_TIDY_UP)
|
||||
{
|
||||
@ -1120,7 +1120,7 @@ void AI_TrySwitchOrUseItem(u32 battler)
|
||||
gBattleStruct->AI_monToSwitchIntoId[battler] = monToSwitchId;
|
||||
}
|
||||
|
||||
*(gBattleStruct->monToSwitchIntoId + battler) = gBattleStruct->AI_monToSwitchIntoId[battler];
|
||||
gBattleStruct->monToSwitchIntoId[battler] = gBattleStruct->AI_monToSwitchIntoId[battler];
|
||||
AI_DATA->monToSwitchInId[battler] = gBattleStruct->AI_monToSwitchIntoId[battler];
|
||||
return;
|
||||
}
|
||||
@ -1342,7 +1342,7 @@ static s32 GetSwitchinWeatherImpact(void)
|
||||
s32 weatherImpact = 0, maxHP = AI_DATA->switchinCandidate.battleMon.maxHP, ability = AI_DATA->switchinCandidate.battleMon.ability;
|
||||
u32 holdEffect = ItemId_GetHoldEffect(AI_DATA->switchinCandidate.battleMon.item);
|
||||
|
||||
if (WEATHER_HAS_EFFECT)
|
||||
if (HasWeatherEffect())
|
||||
{
|
||||
// Damage
|
||||
if (holdEffect != HOLD_EFFECT_SAFETY_GOGGLES && ability != ABILITY_MAGIC_GUARD && ability != ABILITY_OVERCOAT)
|
||||
@ -1915,7 +1915,8 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
|
||||
}
|
||||
|
||||
// If mon can trap
|
||||
if (CanAbilityTrapOpponent(AI_DATA->switchinCandidate.battleMon.ability, opposingBattler)
|
||||
if ((CanAbilityTrapOpponent(AI_DATA->switchinCandidate.battleMon.ability, opposingBattler)
|
||||
|| (CanAbilityTrapOpponent(AI_GetBattlerAbility(opposingBattler), opposingBattler) && AI_DATA->switchinCandidate.battleMon.ability == ABILITY_TRACE))
|
||||
&& CountUsablePartyMons(opposingBattler) > 0
|
||||
&& canSwitchinWin1v1)
|
||||
trapperId = i;
|
||||
@ -1984,8 +1985,8 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd)
|
||||
s32 lastId = 0; // + 1
|
||||
struct Pokemon *party;
|
||||
|
||||
if (*(gBattleStruct->monToSwitchIntoId + battler) != PARTY_SIZE)
|
||||
return *(gBattleStruct->monToSwitchIntoId + battler);
|
||||
if (gBattleStruct->monToSwitchIntoId[battler] != PARTY_SIZE)
|
||||
return gBattleStruct->monToSwitchIntoId[battler];
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
|
||||
return gBattlerPartyIndexes[battler] + 1;
|
||||
|
||||
|
||||
@ -2396,6 +2396,18 @@ bool32 IsSwitchOutEffect(u32 effect)
|
||||
}
|
||||
}
|
||||
|
||||
bool32 IsChaseEffect(u32 effect)
|
||||
{
|
||||
// Effects that hit switching out mons like Pursuit
|
||||
switch (effect)
|
||||
{
|
||||
case EFFECT_PURSUIT:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool32 IsMoveSleepClauseTrigger(u32 move)
|
||||
{
|
||||
u32 i, effect = GetMoveEffect(move);
|
||||
@ -4111,7 +4123,7 @@ bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData
|
||||
{
|
||||
if (aiData->abilities[battlerDef] == ABILITY_MAGIC_BOUNCE
|
||||
|| CountUsablePartyMons(battlerDef) == 0
|
||||
|| HasMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_RAPID_SPIN)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_RAPID_SPIN)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_DEFOG))
|
||||
return FALSE;
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include "gpu_regs.h"
|
||||
#include "graphics.h"
|
||||
#include "main.h"
|
||||
#include "malloc.h"
|
||||
#include "m4a.h"
|
||||
#include "palette.h"
|
||||
#include "pokemon.h"
|
||||
@ -1570,17 +1571,15 @@ void LoadMoveBg(u16 bgId)
|
||||
{
|
||||
if (IsContest())
|
||||
{
|
||||
void *decompressionBuffer = Alloc(0x800);
|
||||
const u32 *tilemap = gBattleAnimBackgroundTable[bgId].tilemap;
|
||||
void *dmaSrc;
|
||||
void *dmaDest;
|
||||
|
||||
LZDecompressWram(tilemap, gDecompressionBuffer);
|
||||
RelocateBattleBgPal(GetBattleBgPaletteNum(), (void *)gDecompressionBuffer, 0x100, FALSE);
|
||||
dmaSrc = gDecompressionBuffer;
|
||||
dmaDest = (void *)BG_SCREEN_ADDR(26);
|
||||
DmaCopy32(3, dmaSrc, dmaDest, 0x800);
|
||||
LZDecompressWram(tilemap, decompressionBuffer);
|
||||
RelocateBattleBgPal(GetBattleBgPaletteNum(), decompressionBuffer, 0x100, FALSE);
|
||||
DmaCopy32(3, decompressionBuffer, (void *)BG_SCREEN_ADDR(26), 0x800);
|
||||
LZDecompressVram(gBattleAnimBackgroundTable[bgId].image, (void *)BG_SCREEN_ADDR(4));
|
||||
LoadCompressedPalette(gBattleAnimBackgroundTable[bgId].palette, BG_PLTT_ID(GetBattleBgPaletteNum()), PLTT_SIZE_4BPP);
|
||||
Free(decompressionBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -43,7 +43,6 @@
|
||||
static void OpponentHandleLoadMonSprite(u32 battler);
|
||||
static void OpponentHandleSwitchInAnim(u32 battler);
|
||||
static void OpponentHandleDrawTrainerPic(u32 battler);
|
||||
static void OpponentHandleTrainerSlide(u32 battler);
|
||||
static void OpponentHandleTrainerSlideBack(u32 battler);
|
||||
static void OpponentHandleMoveAnimation(u32 battler);
|
||||
static void OpponentHandlePrintString(u32 battler);
|
||||
@ -504,7 +503,7 @@ static void OpponentHandleDrawTrainerPic(u32 battler)
|
||||
BtlController_HandleDrawTrainerPic(battler, trainerPicId, TRUE, xPos, 40, -1);
|
||||
}
|
||||
|
||||
static void OpponentHandleTrainerSlide(u32 battler)
|
||||
void OpponentHandleTrainerSlide(u32 battler)
|
||||
{
|
||||
u32 trainerPicId = OpponentGetTrainerPicId(battler);
|
||||
BtlController_HandleTrainerSlide(battler, trainerPicId);
|
||||
|
||||
@ -2043,7 +2043,7 @@ static void PlayerHandleChooseAction(u32 battler)
|
||||
if (B_SHOW_PARTNER_TARGET && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && IsBattlerAlive(B_POSITION_PLAYER_RIGHT))
|
||||
{
|
||||
StringCopy(gStringVar1, COMPOUND_STRING("Partner will use:\n"));
|
||||
u32 move = gBattleMons[B_POSITION_PLAYER_RIGHT].moves[*(gBattleStruct->chosenMovePositions + B_POSITION_PLAYER_RIGHT)];
|
||||
u32 move = gBattleMons[B_POSITION_PLAYER_RIGHT].moves[gBattleStruct->chosenMovePositions[B_POSITION_PLAYER_RIGHT]];
|
||||
StringAppend(gStringVar1, GetMoveName(move));
|
||||
u32 moveTarget = GetBattlerMoveTargetType(B_POSITION_PLAYER_RIGHT, move);
|
||||
if (moveTarget == MOVE_TARGET_SELECTED)
|
||||
@ -2107,7 +2107,7 @@ void HandleChooseMoveAfterDma3(u32 battler)
|
||||
|
||||
static void PlayerChooseMoveInBattlePalace(u32 battler)
|
||||
{
|
||||
if (--*(gBattleStruct->arenaMindPoints + battler) == 0)
|
||||
if (--gBattleStruct->arenaMindPoints[battler] == 0)
|
||||
{
|
||||
gBattlePalaceMoveSelectionRngValue = gRngValue;
|
||||
BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, ChooseMoveAndTargetInBattlePalace(battler));
|
||||
@ -2119,7 +2119,7 @@ void PlayerHandleChooseMove(u32 battler)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
|
||||
{
|
||||
*(gBattleStruct->arenaMindPoints + battler) = 8;
|
||||
gBattleStruct->arenaMindPoints[battler] = 8;
|
||||
gBattlerControllerFuncs[battler] = PlayerChooseMoveInBattlePalace;
|
||||
}
|
||||
else
|
||||
|
||||
@ -405,7 +405,7 @@ static void PlayerPartnerHandleChoosePokemon(u32 battler)
|
||||
}
|
||||
}
|
||||
}
|
||||
*(gBattleStruct->monToSwitchIntoId + battler) = chosenMonId;
|
||||
gBattleStruct->monToSwitchIntoId[battler] = chosenMonId;
|
||||
}
|
||||
else // Mon to switch out has been already chosen.
|
||||
{
|
||||
|
||||
@ -64,7 +64,7 @@ static void (*const sRecordedOpponentBufferCommands[CONTROLLER_CMDS_COUNT])(u32
|
||||
[CONTROLLER_SWITCHINANIM] = RecordedOpponentHandleSwitchInAnim,
|
||||
[CONTROLLER_RETURNMONTOBALL] = BtlController_HandleReturnMonToBall,
|
||||
[CONTROLLER_DRAWTRAINERPIC] = RecordedOpponentHandleDrawTrainerPic,
|
||||
[CONTROLLER_TRAINERSLIDE] = BtlController_Empty,
|
||||
[CONTROLLER_TRAINERSLIDE] = OpponentHandleTrainerSlide,
|
||||
[CONTROLLER_TRAINERSLIDEBACK] = RecordedOpponentHandleTrainerSlideBack,
|
||||
[CONTROLLER_FAINTANIMATION] = BtlController_HandleFaintAnimation,
|
||||
[CONTROLLER_PALETTEFADE] = BtlController_Empty,
|
||||
@ -484,9 +484,9 @@ static void RecordedOpponentHandleChooseItem(u32 battler)
|
||||
|
||||
static void RecordedOpponentHandleChoosePokemon(u32 battler)
|
||||
{
|
||||
*(gBattleStruct->monToSwitchIntoId + battler) = RecordedBattle_GetBattlerAction(RECORDED_PARTY_INDEX, battler);
|
||||
gBattleStruct->monToSwitchIntoId[battler] = RecordedBattle_GetBattlerAction(RECORDED_PARTY_INDEX, battler);
|
||||
gSelectedMonPartyId = gBattleStruct->monToSwitchIntoId[battler]; // Revival Blessing
|
||||
BtlController_EmitChosenMonReturnValue(battler, BUFFER_B, *(gBattleStruct->monToSwitchIntoId + battler), NULL);
|
||||
BtlController_EmitChosenMonReturnValue(battler, BUFFER_B, gBattleStruct->monToSwitchIntoId[battler], NULL);
|
||||
RecordedOpponentBufferExecCompleted(battler);
|
||||
}
|
||||
|
||||
|
||||
@ -477,9 +477,9 @@ static void RecordedPlayerHandleChooseItem(u32 battler)
|
||||
|
||||
static void RecordedPlayerHandleChoosePokemon(u32 battler)
|
||||
{
|
||||
*(gBattleStruct->monToSwitchIntoId + battler) = RecordedBattle_GetBattlerAction(RECORDED_PARTY_INDEX, battler);
|
||||
gBattleStruct->monToSwitchIntoId[battler] = RecordedBattle_GetBattlerAction(RECORDED_PARTY_INDEX, battler);
|
||||
gSelectedMonPartyId = gBattleStruct->monToSwitchIntoId[battler]; // Revival Blessing
|
||||
BtlController_EmitChosenMonReturnValue(battler, BUFFER_B, *(gBattleStruct->monToSwitchIntoId + battler), NULL);
|
||||
BtlController_EmitChosenMonReturnValue(battler, BUFFER_B, gBattleStruct->monToSwitchIntoId[battler], NULL);
|
||||
RecordedPlayerBufferExecCompleted(battler);
|
||||
}
|
||||
|
||||
|
||||
@ -1077,7 +1077,7 @@ void BtlController_EmitMoveAnimation(u32 battler, u32 bufferId, u16 move, u8 tur
|
||||
gBattleResources->transferBuffer[9] = (dmg & 0xFF000000) >> 24;
|
||||
gBattleResources->transferBuffer[10] = friendship;
|
||||
gBattleResources->transferBuffer[11] = multihit;
|
||||
if (WEATHER_HAS_EFFECT)
|
||||
if (HasWeatherEffect())
|
||||
{
|
||||
gBattleResources->transferBuffer[12] = gBattleWeather;
|
||||
gBattleResources->transferBuffer[13] = (gBattleWeather & 0xFF00) >> 8;
|
||||
@ -2223,12 +2223,12 @@ static void Controller_DoMoveAnimation(u32 battler)
|
||||
|
||||
static void Controller_HandleTrainerSlideBack(u32 battler)
|
||||
{
|
||||
if (gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy)
|
||||
if (gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].callback == SpriteCallbackDummy)
|
||||
{
|
||||
if (GetBattlerSide(battler) == B_SIDE_OPPONENT)
|
||||
FreeTrainerFrontPicPalette(gSprites[gBattlerSpriteIds[battler]].oam.affineParam);
|
||||
FreeSpriteOamMatrix(&gSprites[gBattlerSpriteIds[battler]]);
|
||||
DestroySprite(&gSprites[gBattlerSpriteIds[battler]]);
|
||||
FreeTrainerFrontPicPalette(gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.affineParam);
|
||||
FreeSpriteOamMatrix(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]]);
|
||||
DestroySprite(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]]);
|
||||
BattleControllerComplete(battler);
|
||||
}
|
||||
}
|
||||
@ -2270,7 +2270,7 @@ static void Controller_WaitForStatusAnimation(u32 battler)
|
||||
|
||||
static void Controller_WaitForTrainerPic(u32 battler)
|
||||
{
|
||||
if (gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy)
|
||||
if (gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].callback == SpriteCallbackDummy)
|
||||
BattleControllerComplete(battler);
|
||||
}
|
||||
|
||||
@ -2460,18 +2460,18 @@ void BtlController_HandleDrawTrainerPic(u32 battler, u32 trainerPicId, bool32 is
|
||||
if (GetBattlerSide(battler) == B_SIDE_OPPONENT) // Always the front sprite for the opponent.
|
||||
{
|
||||
DecompressTrainerFrontPic(trainerPicId, battler);
|
||||
SetMultiuseSpriteTemplateToTrainerBack(trainerPicId, GetBattlerPosition(battler));
|
||||
SetMultiuseSpriteTemplateToTrainerFront(trainerPicId, GetBattlerPosition(battler));
|
||||
if (subpriority == -1)
|
||||
subpriority = GetBattlerSpriteSubpriority(battler);
|
||||
gBattlerSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate,
|
||||
gBattleStruct->trainerSlideSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate,
|
||||
xPos,
|
||||
yPos,
|
||||
subpriority);
|
||||
|
||||
gSprites[gBattlerSpriteIds[battler]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerSprites[trainerPicId].palette.tag);
|
||||
gSprites[gBattlerSpriteIds[battler]].x2 = -DISPLAY_WIDTH;
|
||||
gSprites[gBattlerSpriteIds[battler]].sSpeedX = 2;
|
||||
gSprites[gBattlerSpriteIds[battler]].oam.affineParam = trainerPicId;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerSprites[trainerPicId].palette.tag);
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].x2 = -DISPLAY_WIDTH;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].sSpeedX = 2;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.affineParam = trainerPicId;
|
||||
}
|
||||
else // Player's side
|
||||
{
|
||||
@ -2481,15 +2481,15 @@ void BtlController_HandleDrawTrainerPic(u32 battler, u32 trainerPicId, bool32 is
|
||||
SetMultiuseSpriteTemplateToTrainerFront(trainerPicId, GetBattlerPosition(battler));
|
||||
if (subpriority == -1)
|
||||
subpriority = GetBattlerSpriteSubpriority(battler);
|
||||
gBattlerSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate,
|
||||
gBattleStruct->trainerSlideSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate,
|
||||
xPos,
|
||||
yPos,
|
||||
subpriority);
|
||||
|
||||
gSprites[gBattlerSpriteIds[battler]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerSprites[trainerPicId].palette.tag);
|
||||
gSprites[gBattlerSpriteIds[battler]].oam.affineMode = ST_OAM_AFFINE_OFF;
|
||||
gSprites[gBattlerSpriteIds[battler]].hFlip = 1;
|
||||
gSprites[gBattlerSpriteIds[battler]].y2 = 48;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerSprites[trainerPicId].palette.tag);
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.affineMode = ST_OAM_AFFINE_OFF;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].hFlip = 1;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].y2 = 48;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2497,20 +2497,20 @@ void BtlController_HandleDrawTrainerPic(u32 battler, u32 trainerPicId, bool32 is
|
||||
SetMultiuseSpriteTemplateToTrainerBack(trainerPicId, GetBattlerPosition(battler));
|
||||
if (subpriority == -1)
|
||||
subpriority = GetBattlerSpriteSubpriority(battler);
|
||||
gBattlerSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate,
|
||||
gBattleStruct->trainerSlideSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate,
|
||||
xPos,
|
||||
yPos,
|
||||
subpriority);
|
||||
|
||||
gSprites[gBattlerSpriteIds[battler]].oam.paletteNum = battler;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = battler;
|
||||
}
|
||||
gSprites[gBattlerSpriteIds[battler]].x2 = DISPLAY_WIDTH;
|
||||
gSprites[gBattlerSpriteIds[battler]].sSpeedX = -2;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].x2 = DISPLAY_WIDTH;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].sSpeedX = -2;
|
||||
}
|
||||
if (B_FAST_INTRO_NO_SLIDE || gTestRunnerHeadless)
|
||||
gSprites[gBattlerSpriteIds[battler]].callback = SpriteCB_TrainerSpawn;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].callback = SpriteCB_TrainerSpawn;
|
||||
else
|
||||
gSprites[gBattlerSpriteIds[battler]].callback = SpriteCB_TrainerSlideIn;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].callback = SpriteCB_TrainerSlideIn;
|
||||
|
||||
gBattlerControllerFuncs[battler] = Controller_WaitForTrainerPic;
|
||||
}
|
||||
@ -2521,26 +2521,26 @@ void BtlController_HandleTrainerSlide(u32 battler, u32 trainerPicId)
|
||||
{
|
||||
DecompressTrainerBackPic(trainerPicId, battler);
|
||||
SetMultiuseSpriteTemplateToTrainerBack(trainerPicId, GetBattlerPosition(battler));
|
||||
gBattlerSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate,
|
||||
gBattleStruct->trainerSlideSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate,
|
||||
80,
|
||||
(8 - gTrainerBacksprites[trainerPicId].coordinates.size) * 4 + 80,
|
||||
30);
|
||||
gSprites[gBattlerSpriteIds[battler]].oam.paletteNum = battler;
|
||||
gSprites[gBattlerSpriteIds[battler]].x2 = -96;
|
||||
gSprites[gBattlerSpriteIds[battler]].sSpeedX = 2;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = battler;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].x2 = -96;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].sSpeedX = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
DecompressTrainerFrontPic(trainerPicId, battler);
|
||||
SetMultiuseSpriteTemplateToTrainerBack(trainerPicId, GetBattlerPosition(battler));
|
||||
gBattlerSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate, 176, 40, 30);
|
||||
gSprites[gBattlerSpriteIds[battler]].oam.affineParam = trainerPicId;
|
||||
gSprites[gBattlerSpriteIds[battler]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerSprites[trainerPicId].palette.tag);
|
||||
gSprites[gBattlerSpriteIds[battler]].x2 = 96;
|
||||
gSprites[gBattlerSpriteIds[battler]].x += 32;
|
||||
gSprites[gBattlerSpriteIds[battler]].sSpeedX = -2;
|
||||
SetMultiuseSpriteTemplateToTrainerFront(trainerPicId, GetBattlerPosition(battler));
|
||||
gBattleStruct->trainerSlideSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate, 176, 40, 0);
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.affineParam = trainerPicId;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerSprites[trainerPicId].palette.tag);
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].x2 = 96;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].x += 32;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].sSpeedX = -2;
|
||||
}
|
||||
gSprites[gBattlerSpriteIds[battler]].callback = SpriteCB_TrainerSlideIn;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].callback = SpriteCB_TrainerSlideIn;
|
||||
|
||||
gBattlerControllerFuncs[battler] = Controller_WaitForTrainerPic;
|
||||
}
|
||||
@ -2551,14 +2551,14 @@ void BtlController_HandleTrainerSlideBack(u32 battler, s16 data0, bool32 startAn
|
||||
{
|
||||
u32 side = GetBattlerSide(battler);
|
||||
|
||||
SetSpritePrimaryCoordsFromSecondaryCoords(&gSprites[gBattlerSpriteIds[battler]]);
|
||||
gSprites[gBattlerSpriteIds[battler]].data[0] = data0;
|
||||
gSprites[gBattlerSpriteIds[battler]].data[2] = (side == B_SIDE_PLAYER) ? -40 : 280;
|
||||
gSprites[gBattlerSpriteIds[battler]].data[4] = gSprites[gBattlerSpriteIds[battler]].y;
|
||||
gSprites[gBattlerSpriteIds[battler]].callback = StartAnimLinearTranslation;
|
||||
StoreSpriteCallbackInData6(&gSprites[gBattlerSpriteIds[battler]], SpriteCallbackDummy);
|
||||
SetSpritePrimaryCoordsFromSecondaryCoords(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]]);
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].data[0] = data0;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].data[2] = (side == B_SIDE_PLAYER) ? -40 : 280;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].data[4] = gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].y;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].callback = StartAnimLinearTranslation;
|
||||
StoreSpriteCallbackInData6(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]], SpriteCallbackDummy);
|
||||
if (startAnim)
|
||||
StartSpriteAnim(&gSprites[gBattlerSpriteIds[battler]], 1);
|
||||
StartSpriteAnim(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]], 1);
|
||||
gBattlerControllerFuncs[battler] = Controller_HandleTrainerSlideBack;
|
||||
}
|
||||
|
||||
@ -2828,34 +2828,34 @@ void BtlController_HandleIntroTrainerBallThrow(u32 battler, u16 tagTrainerPal, c
|
||||
u8 paletteNum, taskId;
|
||||
u32 side = GetBattlerSide(battler);
|
||||
|
||||
SetSpritePrimaryCoordsFromSecondaryCoords(&gSprites[gBattlerSpriteIds[battler]]);
|
||||
SetSpritePrimaryCoordsFromSecondaryCoords(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]]);
|
||||
if (side == B_SIDE_PLAYER)
|
||||
{
|
||||
gSprites[gBattlerSpriteIds[battler]].data[0] = 50;
|
||||
gSprites[gBattlerSpriteIds[battler]].data[2] = -40;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].data[0] = 50;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].data[2] = -40;
|
||||
}
|
||||
else
|
||||
{
|
||||
gSprites[gBattlerSpriteIds[battler]].data[0] = 35;
|
||||
gSprites[gBattlerSpriteIds[battler]].data[2] = 280;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].data[0] = 35;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].data[2] = 280;
|
||||
}
|
||||
|
||||
gSprites[gBattlerSpriteIds[battler]].data[4] = gSprites[gBattlerSpriteIds[battler]].y;
|
||||
gSprites[gBattlerSpriteIds[battler]].callback = StartAnimLinearTranslation;
|
||||
gSprites[gBattlerSpriteIds[battler]].sBattlerId = battler;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].data[4] = gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].y;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].callback = StartAnimLinearTranslation;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].sBattlerId = battler;
|
||||
|
||||
if (side == B_SIDE_PLAYER)
|
||||
{
|
||||
StoreSpriteCallbackInData6(&gSprites[gBattlerSpriteIds[battler]], SpriteCB_FreePlayerSpriteLoadMonSprite);
|
||||
StartSpriteAnim(&gSprites[gBattlerSpriteIds[battler]], ShouldDoSlideInAnim() ? 2 : 1);
|
||||
StoreSpriteCallbackInData6(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]], SpriteCB_FreePlayerSpriteLoadMonSprite);
|
||||
StartSpriteAnim(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]], ShouldDoSlideInAnim() ? 2 : 1);
|
||||
|
||||
paletteNum = AllocSpritePalette(tagTrainerPal);
|
||||
LoadCompressedPalette(trainerPal, OBJ_PLTT_ID(paletteNum), PLTT_SIZE_4BPP);
|
||||
gSprites[gBattlerSpriteIds[battler]].oam.paletteNum = paletteNum;
|
||||
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = paletteNum;
|
||||
}
|
||||
else
|
||||
{
|
||||
StoreSpriteCallbackInData6(&gSprites[gBattlerSpriteIds[battler]], SpriteCB_FreeOpponentSprite);
|
||||
StoreSpriteCallbackInData6(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]], SpriteCB_FreeOpponentSprite);
|
||||
}
|
||||
|
||||
taskId = CreateTask(Task_StartSendOutAnim, 5);
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include "constants/battle_anim.h"
|
||||
#include "battle_interface.h"
|
||||
#include "main.h"
|
||||
#include "menu.h"
|
||||
#include "dma3.h"
|
||||
#include "malloc.h"
|
||||
#include "graphics.h"
|
||||
@ -655,9 +656,10 @@ void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battler)
|
||||
else
|
||||
lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personalityValue);
|
||||
|
||||
LZDecompressWram(lzPaletteData, gDecompressionBuffer);
|
||||
LoadPalette(gDecompressionBuffer, paletteOffset, PLTT_SIZE_4BPP);
|
||||
LoadPalette(gDecompressionBuffer, BG_PLTT_ID(8) + BG_PLTT_ID(battler), PLTT_SIZE_4BPP);
|
||||
void *buffer = malloc_and_decompress(lzPaletteData, NULL);
|
||||
LoadPalette(buffer, paletteOffset, PLTT_SIZE_4BPP);
|
||||
LoadPalette(buffer, BG_PLTT_ID(8) + BG_PLTT_ID(battler), PLTT_SIZE_4BPP);
|
||||
Free(buffer);
|
||||
|
||||
// transform's pink color
|
||||
if (gBattleSpritesDataPtr->battlerData[battler].transformSpecies != SPECIES_NONE)
|
||||
@ -975,8 +977,9 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo
|
||||
DmaCopy32(3, src, dst, MON_PIC_SIZE);
|
||||
paletteOffset = OBJ_PLTT_ID(battlerAtk);
|
||||
lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(targetSpecies, isShiny, personalityValue);
|
||||
LZDecompressWram(lzPaletteData, gDecompressionBuffer);
|
||||
LoadPalette(gDecompressionBuffer, paletteOffset, PLTT_SIZE_4BPP);
|
||||
void *buffer = malloc_and_decompress(lzPaletteData, NULL);
|
||||
LoadPalette(buffer, paletteOffset, PLTT_SIZE_4BPP);
|
||||
Free(buffer);
|
||||
|
||||
if (!megaEvo)
|
||||
{
|
||||
|
||||
@ -70,6 +70,7 @@
|
||||
#include "constants/party_menu.h"
|
||||
#include "constants/rgb.h"
|
||||
#include "constants/songs.h"
|
||||
#include "constants/trainer_slide.h"
|
||||
#include "constants/trainers.h"
|
||||
#include "constants/weather.h"
|
||||
#include "cable_club.h"
|
||||
@ -121,8 +122,6 @@ static void HandleEndTurn_BattleLost(void);
|
||||
static void HandleEndTurn_RanFromBattle(void);
|
||||
static void HandleEndTurn_MonFled(void);
|
||||
static void HandleEndTurn_FinishBattle(void);
|
||||
static void SpriteCB_UnusedBattleInit(struct Sprite *sprite);
|
||||
static void SpriteCB_UnusedBattleInit_Main(struct Sprite *sprite);
|
||||
static u32 Crc32B (const u8 *data, u32 size);
|
||||
static u32 GeneratePartyHash(const struct Trainer *trainer, u32 i);
|
||||
static s32 Factorial(s32);
|
||||
@ -255,17 +254,6 @@ static const struct ScanlineEffectParams sIntroScanlineParams32Bit =
|
||||
®_BG3HOFS, SCANLINE_EFFECT_DMACNT_32BIT, 1
|
||||
};
|
||||
|
||||
const struct SpriteTemplate gUnusedBattleInitSprite =
|
||||
{
|
||||
.tileTag = 0,
|
||||
.paletteTag = 0,
|
||||
.oam = &gDummyOamData,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCB_UnusedBattleInit,
|
||||
};
|
||||
|
||||
static const u8 sText_ShedinjaJpnName[] = _("ヌケニン"); // Nukenin
|
||||
|
||||
const struct OamData gOamData_BattleSpriteOpponentSide =
|
||||
@ -1788,60 +1776,6 @@ void CB2_QuitRecordedBattle(void)
|
||||
}
|
||||
}
|
||||
|
||||
#define sState data[0]
|
||||
#define sDelay data[4]
|
||||
|
||||
static void SpriteCB_UnusedBattleInit(struct Sprite *sprite)
|
||||
{
|
||||
sprite->sState = 0;
|
||||
sprite->callback = SpriteCB_UnusedBattleInit_Main;
|
||||
}
|
||||
|
||||
static void SpriteCB_UnusedBattleInit_Main(struct Sprite *sprite)
|
||||
{
|
||||
u16 *arr = (u16 *)gDecompressionBuffer;
|
||||
|
||||
switch (sprite->sState)
|
||||
{
|
||||
case 0:
|
||||
sprite->sState++;
|
||||
sprite->data[1] = 0;
|
||||
sprite->data[2] = 0x281;
|
||||
sprite->data[3] = 0;
|
||||
sprite->sDelay = 1;
|
||||
// fall through
|
||||
case 1:
|
||||
sprite->sDelay--;
|
||||
if (sprite->sDelay == 0)
|
||||
{
|
||||
s32 i;
|
||||
s32 r2;
|
||||
s32 r0;
|
||||
|
||||
sprite->sDelay = 2;
|
||||
r2 = sprite->data[1] + sprite->data[3] * 32;
|
||||
r0 = sprite->data[2] - sprite->data[3] * 32;
|
||||
for (i = 0; i < 29; i += 2)
|
||||
{
|
||||
arr[r2 + i] = 0x3D;
|
||||
arr[r0 + i] = 0x3D;
|
||||
}
|
||||
sprite->data[3]++;
|
||||
if (sprite->data[3] == 21)
|
||||
{
|
||||
sprite->sState++;
|
||||
sprite->data[1] = 32;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
sprite->data[1]--;
|
||||
if (sprite->data[1] == 20)
|
||||
SetMainCallback2(CB2_InitBattle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 Crc32B (const u8 *data, u32 size)
|
||||
{
|
||||
s32 i, j;
|
||||
@ -3198,9 +3132,9 @@ void SwitchInClearSetData(u32 battler)
|
||||
{
|
||||
if (gBattleMons[i].status2 & STATUS2_INFATUATED_WITH(battler))
|
||||
gBattleMons[i].status2 &= ~STATUS2_INFATUATED_WITH(battler);
|
||||
if ((gBattleMons[i].status2 & STATUS2_WRAPPED) && *(gBattleStruct->wrappedBy + i) == battler)
|
||||
if ((gBattleMons[i].status2 & STATUS2_WRAPPED) && gBattleStruct->wrappedBy[i] == battler)
|
||||
gBattleMons[i].status2 &= ~STATUS2_WRAPPED;
|
||||
if ((gStatuses4[i] & STATUS4_SYRUP_BOMB) && *(gBattleStruct->stickySyrupdBy + i) == battler)
|
||||
if ((gStatuses4[i] & STATUS4_SYRUP_BOMB) && gBattleStruct->stickySyrupdBy[i] == battler)
|
||||
gStatuses4[i] &= ~STATUS4_SYRUP_BOMB;
|
||||
}
|
||||
|
||||
@ -3313,9 +3247,9 @@ const u8* FaintClearSetData(u32 battler)
|
||||
gBattleMons[i].status2 &= ~STATUS2_ESCAPE_PREVENTION;
|
||||
if (gBattleMons[i].status2 & STATUS2_INFATUATED_WITH(battler))
|
||||
gBattleMons[i].status2 &= ~STATUS2_INFATUATED_WITH(battler);
|
||||
if ((gBattleMons[i].status2 & STATUS2_WRAPPED) && *(gBattleStruct->wrappedBy + i) == battler)
|
||||
if ((gBattleMons[i].status2 & STATUS2_WRAPPED) && gBattleStruct->wrappedBy[i] == battler)
|
||||
gBattleMons[i].status2 &= ~STATUS2_WRAPPED;
|
||||
if ((gStatuses4[i] & STATUS4_SYRUP_BOMB) && *(gBattleStruct->stickySyrupdBy + i) == battler)
|
||||
if ((gStatuses4[i] & STATUS4_SYRUP_BOMB) && gBattleStruct->stickySyrupdBy[i] == battler)
|
||||
gStatuses4[i] &= ~STATUS4_SYRUP_BOMB;
|
||||
}
|
||||
|
||||
@ -3931,7 +3865,7 @@ static void TryDoEventsBeforeFirstTurn(void)
|
||||
case FIRST_TURN_EVENTS_END:
|
||||
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
|
||||
{
|
||||
*(gBattleStruct->monToSwitchIntoId + i) = PARTY_SIZE;
|
||||
gBattleStruct->monToSwitchIntoId[i] = PARTY_SIZE;
|
||||
gChosenActionByBattler[i] = B_ACTION_NONE;
|
||||
gChosenMoveByBattler[i] = MOVE_NONE;
|
||||
gBattleStruct->battlerState[i].absentBattlerFlags = gAbsentBattlerFlags & (1u << i);
|
||||
@ -4052,10 +3986,15 @@ void BattleTurnPassed(void)
|
||||
gChosenActionByBattler[i] = B_ACTION_NONE;
|
||||
gChosenMoveByBattler[i] = MOVE_NONE;
|
||||
gBattleStruct->battlerState[i].absentBattlerFlags = gAbsentBattlerFlags & (1u << i);
|
||||
gBattleStruct->monToSwitchIntoId[i] = PARTY_SIZE;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
|
||||
*(gBattleStruct->monToSwitchIntoId + i) = PARTY_SIZE;
|
||||
for (i = 0; i < NUM_BATTLE_SIDES; i++)
|
||||
{
|
||||
if (gSideTimers[i].retaliateTimer > 0)
|
||||
gSideTimers[i].retaliateTimer--;
|
||||
|
||||
}
|
||||
|
||||
BattlePutTextOnWindow(gText_EmptyString3, B_WIN_MSG);
|
||||
AssignUsableGimmicks();
|
||||
@ -4063,11 +4002,6 @@ void BattleTurnPassed(void)
|
||||
SetAiLogicDataForTurn(AI_DATA); // get assumed abilities, hold effects, etc of all battlers
|
||||
gBattleMainFunc = HandleTurnActionSelectionState;
|
||||
|
||||
if (gSideTimers[B_SIDE_PLAYER].retaliateTimer > 0)
|
||||
gSideTimers[B_SIDE_PLAYER].retaliateTimer--;
|
||||
if (gSideTimers[B_SIDE_OPPONENT].retaliateTimer > 0)
|
||||
gSideTimers[B_SIDE_OPPONENT].retaliateTimer--;
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
|
||||
BattleScriptExecute(BattleScript_PalacePrintFlavorText);
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_ARENA && gBattleStruct->arenaTurnCounter == 0)
|
||||
@ -4076,13 +4010,15 @@ void BattleTurnPassed(void)
|
||||
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
|
||||
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_LAST_HALF_HP)))
|
||||
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
|
||||
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_FIRST_CRITICAL_HIT)))
|
||||
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_PLAYER_LANDS_FIRST_CRITICAL_HIT)))
|
||||
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
|
||||
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_FIRST_SUPER_EFFECTIVE_HIT)))
|
||||
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_ENEMY_LANDS_FIRST_CRITICAL_HIT)))
|
||||
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
|
||||
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_FIRST_STAB_MOVE)))
|
||||
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_PLAYER_LANDS_FIRST_SUPER_EFFECTIVE_HIT)))
|
||||
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
|
||||
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_PLAYER_MON_UNAFFECTED)))
|
||||
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_PLAYER_LANDS_FIRST_STAB_MOVE)))
|
||||
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
|
||||
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_ENEMY_MON_UNAFFECTED)))
|
||||
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
|
||||
}
|
||||
|
||||
@ -4168,7 +4104,7 @@ void SwitchPartyOrder(u32 battler)
|
||||
gBattlePartyCurrentOrder[i] = *(battler * 3 + i + (u8 *)(gBattleStruct->battlerPartyOrders));
|
||||
|
||||
partyId1 = GetPartyIdFromBattlePartyId(gBattlerPartyIndexes[battler]);
|
||||
partyId2 = GetPartyIdFromBattlePartyId(*(gBattleStruct->monToSwitchIntoId + battler));
|
||||
partyId2 = GetPartyIdFromBattlePartyId(gBattleStruct->monToSwitchIntoId[battler]);
|
||||
SwitchPartyMonSlots(partyId1, partyId2);
|
||||
|
||||
if (IsDoubleBattle())
|
||||
@ -4204,11 +4140,6 @@ enum
|
||||
void SetupAISwitchingData(u32 battler, bool32 isAiRisky)
|
||||
{
|
||||
s32 opposingBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler)));
|
||||
|
||||
// AI's data
|
||||
AI_DATA->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, isAiRisky);
|
||||
if (ShouldSwitch(battler))
|
||||
AI_DATA->shouldSwitch |= (1u << battler);
|
||||
|
||||
// AI's predicting data
|
||||
if ((AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_PREDICT_SWITCH))
|
||||
@ -4219,10 +4150,15 @@ void SetupAISwitchingData(u32 battler, bool32 isAiRisky)
|
||||
if (ShouldSwitch(opposingBattler))
|
||||
AI_DATA->shouldSwitch |= (1u << opposingBattler);
|
||||
AI_DATA->aiSwitchPredictionInProgress = FALSE;
|
||||
|
||||
|
||||
// Determine whether AI will use predictions this turn
|
||||
AI_DATA->predictingSwitch = RandomPercentage(RNG_AI_PREDICT_SWITCH, 50);
|
||||
}
|
||||
|
||||
// AI's data
|
||||
AI_DATA->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, isAiRisky);
|
||||
if (ShouldSwitch(battler))
|
||||
AI_DATA->shouldSwitch |= (1u << battler);
|
||||
}
|
||||
|
||||
static void HandleTurnActionSelectionState(void)
|
||||
@ -4257,7 +4193,7 @@ static void HandleTurnActionSelectionState(void)
|
||||
}
|
||||
// fallthrough
|
||||
case STATE_BEFORE_ACTION_CHOSEN: // Choose an action.
|
||||
*(gBattleStruct->monToSwitchIntoId + battler) = PARTY_SIZE;
|
||||
gBattleStruct->monToSwitchIntoId[battler] = PARTY_SIZE;
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_MULTI
|
||||
|| (position & BIT_FLANK) == B_FLANK_LEFT
|
||||
|| gBattleStruct->battlerState[GetBattlerAtPosition(BATTLE_PARTNER(position))].absentBattlerFlags
|
||||
@ -4310,15 +4246,15 @@ static void HandleTurnActionSelectionState(void)
|
||||
if (AreAllMovesUnusable(battler))
|
||||
{
|
||||
gBattleCommunication[battler] = STATE_SELECTION_SCRIPT;
|
||||
*(gBattleStruct->selectionScriptFinished + battler) = FALSE;
|
||||
*(gBattleStruct->stateIdAfterSelScript + battler) = STATE_WAIT_ACTION_CONFIRMED_STANDBY;
|
||||
*(gBattleStruct->moveTarget + battler) = gBattleResources->bufferB[battler][3];
|
||||
gBattleStruct->selectionScriptFinished[battler] = FALSE;
|
||||
gBattleStruct->stateIdAfterSelScript[battler] = STATE_WAIT_ACTION_CONFIRMED_STANDBY;
|
||||
gBattleStruct->moveTarget[battler] = gBattleResources->bufferB[battler][3];
|
||||
return;
|
||||
}
|
||||
else if (gDisableStructs[battler].encoredMove != 0)
|
||||
{
|
||||
gChosenMoveByBattler[battler] = gDisableStructs[battler].encoredMove;
|
||||
*(gBattleStruct->chosenMovePositions + battler) = gDisableStructs[battler].encoredMovePos;
|
||||
gBattleStruct->chosenMovePositions[battler] = gDisableStructs[battler].encoredMovePos;
|
||||
gBattleCommunication[battler] = STATE_WAIT_ACTION_CONFIRMED_STANDBY;
|
||||
return;
|
||||
}
|
||||
@ -4352,8 +4288,8 @@ static void HandleTurnActionSelectionState(void)
|
||||
RecordedBattle_ClearBattlerAction(battler, 1);
|
||||
gSelectionBattleScripts[battler] = BattleScript_ActionSelectionItemsCantBeUsed;
|
||||
gBattleCommunication[battler] = STATE_SELECTION_SCRIPT;
|
||||
*(gBattleStruct->selectionScriptFinished + battler) = FALSE;
|
||||
*(gBattleStruct->stateIdAfterSelScript + battler) = STATE_BEFORE_ACTION_CHOSEN;
|
||||
gBattleStruct->selectionScriptFinished[battler] = FALSE;
|
||||
gBattleStruct->stateIdAfterSelScript[battler] = STATE_BEFORE_ACTION_CHOSEN;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4368,8 +4304,8 @@ static void HandleTurnActionSelectionState(void)
|
||||
RecordedBattle_ClearBattlerAction(battler, 1);
|
||||
gSelectionBattleScripts[battler] = BattleScript_ActionSelectionItemsCantBeUsed;
|
||||
gBattleCommunication[battler] = STATE_SELECTION_SCRIPT;
|
||||
*(gBattleStruct->selectionScriptFinished + battler) = FALSE;
|
||||
*(gBattleStruct->stateIdAfterSelScript + battler) = STATE_BEFORE_ACTION_CHOSEN;
|
||||
gBattleStruct->selectionScriptFinished[battler] = FALSE;
|
||||
gBattleStruct->stateIdAfterSelScript[battler] = STATE_BEFORE_ACTION_CHOSEN;
|
||||
return;
|
||||
}
|
||||
else
|
||||
@ -4379,7 +4315,7 @@ static void HandleTurnActionSelectionState(void)
|
||||
}
|
||||
break;
|
||||
case B_ACTION_SWITCH:
|
||||
*(gBattleStruct->battlerPartyIndexes + battler) = gBattlerPartyIndexes[battler];
|
||||
gBattleStruct->battlerPartyIndexes[battler] = gBattlerPartyIndexes[battler];
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_ARENA
|
||||
|| !CanBattlerEscape(battler))
|
||||
{
|
||||
@ -4393,9 +4329,9 @@ static void HandleTurnActionSelectionState(void)
|
||||
else
|
||||
{
|
||||
if (battler == 2 && gChosenActionByBattler[0] == B_ACTION_SWITCH)
|
||||
BtlController_EmitChoosePokemon(battler, BUFFER_A, PARTY_ACTION_CHOOSE_MON, *(gBattleStruct->monToSwitchIntoId + 0), ABILITY_NONE, gBattleStruct->battlerPartyOrders[battler]);
|
||||
BtlController_EmitChoosePokemon(battler, BUFFER_A, PARTY_ACTION_CHOOSE_MON, gBattleStruct->monToSwitchIntoId[0], ABILITY_NONE, gBattleStruct->battlerPartyOrders[battler]);
|
||||
else if (battler == 3 && gChosenActionByBattler[1] == B_ACTION_SWITCH)
|
||||
BtlController_EmitChoosePokemon(battler, BUFFER_A, PARTY_ACTION_CHOOSE_MON, *(gBattleStruct->monToSwitchIntoId + 1), ABILITY_NONE, gBattleStruct->battlerPartyOrders[battler]);
|
||||
BtlController_EmitChoosePokemon(battler, BUFFER_A, PARTY_ACTION_CHOOSE_MON, gBattleStruct->monToSwitchIntoId[1], ABILITY_NONE, gBattleStruct->battlerPartyOrders[battler]);
|
||||
else
|
||||
BtlController_EmitChoosePokemon(battler, BUFFER_A, PARTY_ACTION_CHOOSE_MON, PARTY_SIZE, ABILITY_NONE, gBattleStruct->battlerPartyOrders[battler]);
|
||||
}
|
||||
@ -4406,8 +4342,8 @@ static void HandleTurnActionSelectionState(void)
|
||||
{
|
||||
gSelectionBattleScripts[battler] = BattleScript_PrintFullBox;
|
||||
gBattleCommunication[battler] = STATE_SELECTION_SCRIPT;
|
||||
*(gBattleStruct->selectionScriptFinished + battler) = FALSE;
|
||||
*(gBattleStruct->stateIdAfterSelScript + battler) = STATE_BEFORE_ACTION_CHOSEN;
|
||||
gBattleStruct->selectionScriptFinished[battler] = FALSE;
|
||||
gBattleStruct->stateIdAfterSelScript[battler] = STATE_BEFORE_ACTION_CHOSEN;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@ -4467,8 +4403,8 @@ static void HandleTurnActionSelectionState(void)
|
||||
{
|
||||
gSelectionBattleScripts[battler] = BattleScript_AskIfWantsToForfeitMatch;
|
||||
gBattleCommunication[battler] = STATE_SELECTION_SCRIPT_MAY_RUN;
|
||||
*(gBattleStruct->selectionScriptFinished + battler) = FALSE;
|
||||
*(gBattleStruct->stateIdAfterSelScript + battler) = STATE_BEFORE_ACTION_CHOSEN;
|
||||
gBattleStruct->selectionScriptFinished[battler] = FALSE;
|
||||
gBattleStruct->stateIdAfterSelScript[battler] = STATE_BEFORE_ACTION_CHOSEN;
|
||||
return;
|
||||
}
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER
|
||||
@ -4484,8 +4420,8 @@ static void HandleTurnActionSelectionState(void)
|
||||
{
|
||||
gSelectionBattleScripts[battler] = BattleScript_PrintCantEscapeFromBattle;
|
||||
gBattleCommunication[battler] = STATE_SELECTION_SCRIPT;
|
||||
*(gBattleStruct->selectionScriptFinished + battler) = FALSE;
|
||||
*(gBattleStruct->stateIdAfterSelScript + battler) = STATE_BEFORE_ACTION_CHOSEN;
|
||||
gBattleStruct->selectionScriptFinished[battler] = FALSE;
|
||||
gBattleStruct->stateIdAfterSelScript[battler] = STATE_BEFORE_ACTION_CHOSEN;
|
||||
return;
|
||||
}
|
||||
else
|
||||
@ -4526,9 +4462,9 @@ static void HandleTurnActionSelectionState(void)
|
||||
{
|
||||
RecordedBattle_ClearBattlerAction(battler, 1);
|
||||
gBattleCommunication[battler] = STATE_SELECTION_SCRIPT;
|
||||
*(gBattleStruct->selectionScriptFinished + battler) = FALSE;
|
||||
gBattleStruct->selectionScriptFinished[battler] = FALSE;
|
||||
gBattleResources->bufferB[battler][1] = B_ACTION_USE_MOVE;
|
||||
*(gBattleStruct->stateIdAfterSelScript + battler) = STATE_WAIT_ACTION_CHOSEN;
|
||||
gBattleStruct->stateIdAfterSelScript[battler] = STATE_WAIT_ACTION_CHOSEN;
|
||||
return;
|
||||
}
|
||||
else
|
||||
@ -4657,9 +4593,9 @@ static void HandleTurnActionSelectionState(void)
|
||||
}
|
||||
break;
|
||||
case STATE_SELECTION_SCRIPT:
|
||||
if (*(gBattleStruct->selectionScriptFinished + battler))
|
||||
if (gBattleStruct->selectionScriptFinished[battler])
|
||||
{
|
||||
gBattleCommunication[battler] = *(gBattleStruct->stateIdAfterSelScript + battler);
|
||||
gBattleCommunication[battler] = gBattleStruct->stateIdAfterSelScript[battler];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4679,7 +4615,7 @@ static void HandleTurnActionSelectionState(void)
|
||||
}
|
||||
break;
|
||||
case STATE_SELECTION_SCRIPT_MAY_RUN:
|
||||
if (*(gBattleStruct->selectionScriptFinished + battler))
|
||||
if (gBattleStruct->selectionScriptFinished[battler])
|
||||
{
|
||||
if (gBattleResources->bufferB[battler][1] == B_ACTION_NOTHING_FAINTED)
|
||||
{
|
||||
@ -4690,7 +4626,7 @@ static void HandleTurnActionSelectionState(void)
|
||||
else
|
||||
{
|
||||
RecordedBattle_ClearBattlerAction(battler, 1);
|
||||
gBattleCommunication[battler] = *(gBattleStruct->stateIdAfterSelScript + battler);
|
||||
gBattleCommunication[battler] = gBattleStruct->stateIdAfterSelScript[battler];
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -4732,7 +4668,7 @@ static void HandleTurnActionSelectionState(void)
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (gChosenActionByBattler[i] == B_ACTION_SWITCH)
|
||||
SwitchPartyOrderInGameMulti(i, *(gBattleStruct->monToSwitchIntoId + i));
|
||||
SwitchPartyOrderInGameMulti(i, gBattleStruct->monToSwitchIntoId[battler]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4785,7 +4721,7 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, u32 holdEffect)
|
||||
u32 speed = gBattleMons[battler].speed;
|
||||
|
||||
// weather abilities
|
||||
if (WEATHER_HAS_EFFECT)
|
||||
if (HasWeatherEffect())
|
||||
{
|
||||
if (ability == ABILITY_SWIFT_SWIM && holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA && gBattleWeather & B_WEATHER_RAIN)
|
||||
speed *= 2;
|
||||
@ -4804,7 +4740,7 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, u32 holdEffect)
|
||||
speed *= 2;
|
||||
else if (ability == ABILITY_SLOW_START && gDisableStructs[battler].slowStartTimer != 0)
|
||||
speed /= 2;
|
||||
else if (ability == ABILITY_PROTOSYNTHESIS && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && ((gBattleWeather & B_WEATHER_SUN && WEATHER_HAS_EFFECT) || gDisableStructs[battler].boosterEnergyActivates))
|
||||
else if (ability == ABILITY_PROTOSYNTHESIS && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && ((gBattleWeather & B_WEATHER_SUN && HasWeatherEffect()) || gDisableStructs[battler].boosterEnergyActivates))
|
||||
speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed;
|
||||
else if (ability == ABILITY_QUARK_DRIVE && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battler].boosterEnergyActivates))
|
||||
speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed;
|
||||
@ -4862,7 +4798,7 @@ s8 GetChosenMovePriority(u32 battler)
|
||||
if (gProtectStructs[battler].noValidMoves)
|
||||
move = MOVE_STRUGGLE;
|
||||
else
|
||||
move = gBattleMons[battler].moves[*(gBattleStruct->chosenMovePositions + battler)];
|
||||
move = gBattleMons[battler].moves[gBattleStruct->chosenMovePositions[battler]];
|
||||
|
||||
return GetBattleMovePriority(battler, move);
|
||||
}
|
||||
@ -5911,7 +5847,7 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, u8 *ateBoost)
|
||||
switch (moveEffect)
|
||||
{
|
||||
case EFFECT_WEATHER_BALL:
|
||||
if (gMain.inBattle && WEATHER_HAS_EFFECT)
|
||||
if (gMain.inBattle && HasWeatherEffect())
|
||||
{
|
||||
if (gBattleWeather & B_WEATHER_RAIN && holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA)
|
||||
return TYPE_WATER;
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
#include "test_runner.h"
|
||||
#include "text.h"
|
||||
#include "trainer_hill.h"
|
||||
#include "trainer_slide.h"
|
||||
#include "window.h"
|
||||
#include "line_break.h"
|
||||
#include "constants/abilities.h"
|
||||
@ -137,9 +138,14 @@ static const u8 sText_Evasiveness[] = _("evasiveness");
|
||||
|
||||
const u8 *const gStatNamesTable[NUM_BATTLE_STATS] =
|
||||
{
|
||||
sText_HP, sText_Attack, sText_Defense,
|
||||
sText_Speed, sText_SpAttack, sText_SpDefense,
|
||||
sText_Accuracy, sText_Evasiveness
|
||||
[STAT_HP] = sText_HP,
|
||||
[STAT_ATK] = sText_Attack,
|
||||
[STAT_DEF] = sText_Defense,
|
||||
[STAT_SPEED] = sText_Speed,
|
||||
[STAT_SPATK] = sText_SpAttack,
|
||||
[STAT_SPDEF] = sText_SpDefense,
|
||||
[STAT_ACC] = sText_Accuracy,
|
||||
[STAT_EVASION] = sText_Evasiveness,
|
||||
};
|
||||
const u8 *const gPokeblockWasTooXStringTable[FLAVOR_COUNT] =
|
||||
{
|
||||
@ -3541,252 +3547,3 @@ u8 GetCurrentPpToMaxPpState(u8 currentPp, u8 maxPp)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct TrainerSlide
|
||||
{
|
||||
u16 trainerId;
|
||||
bool8 isFrontierTrainer;
|
||||
const u8 *msgLastSwitchIn;
|
||||
const u8 *msgLastLowHp;
|
||||
const u8 *msgFirstDown;
|
||||
const u8 *msgLastHalfHp;
|
||||
const u8 *msgFirstCriticalHit;
|
||||
const u8 *msgFirstSuperEffectiveHit;
|
||||
const u8 *msgFirstSTABMove;
|
||||
const u8 *msgPlayerMonUnaffected;
|
||||
const u8 *msgMegaEvolution;
|
||||
const u8 *msgZMove;
|
||||
const u8 *msgBeforeFirstTurn;
|
||||
const u8 *msgDynamax;
|
||||
};
|
||||
|
||||
static const struct TrainerSlide sTrainerSlides[DIFFICULTY_COUNT][TRAINERS_COUNT] =
|
||||
{
|
||||
[DIFFICULTY_NORMAL] =
|
||||
{
|
||||
/* Put any trainer slide-in messages inside this array.
|
||||
Example:
|
||||
{
|
||||
.trainerId = TRAINER_WALLY_VR_2,
|
||||
.isFrontierTrainer = FALSE,
|
||||
.msgLastSwitchIn = sText_AarghAlmostHadIt,
|
||||
.msgLastLowHp = sText_BoxIsFull,
|
||||
.msgFirstDown = sText_123Poof,
|
||||
.msgLastHalfHp = sText_ShootSoClose,
|
||||
.msgFirstCriticalHit = sText_CriticalHit,
|
||||
.msgFirstSuperEffectiveHit = sText_SuperEffective,
|
||||
.msgFirstSTABMove = sText_ABoosted,
|
||||
.msgPlayerMonUnaffected = sText_ButNoEffect,
|
||||
.msgMegaEvolution = sText_PowderExplodes,
|
||||
.msgZMove = sText_Electromagnetism,
|
||||
.msgBeforeFirstTurn = sText_GravityIntensified,
|
||||
.msgDynamax = sText_TargetWokeUp,
|
||||
},
|
||||
},
|
||||
[DIFFICULTY_EASY] =
|
||||
{
|
||||
},
|
||||
[DIFFICULTY_HARD] =
|
||||
{
|
||||
*/
|
||||
},
|
||||
};
|
||||
|
||||
static u32 GetEnemyMonCount(u32 firstId, u32 lastId, bool32 onlyAlive)
|
||||
{
|
||||
u32 i, count = 0;
|
||||
|
||||
for (i = firstId; i < lastId; i++)
|
||||
{
|
||||
u32 species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES_OR_EGG, NULL);
|
||||
if (species != SPECIES_NONE
|
||||
&& species != SPECIES_EGG
|
||||
&& (!onlyAlive || GetMonData(&gEnemyParty[i], MON_DATA_HP, NULL)))
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
LESS_THAN,
|
||||
EQUAL,
|
||||
GREATER_THAN,
|
||||
LESS_THAN_OR_EQUAL,
|
||||
GREATER_THAN_OR_EQUAL,
|
||||
NOT_EQUAL,
|
||||
};
|
||||
|
||||
u32 BattlerHPPercentage(u32 battler, u32 operation, u32 threshold)
|
||||
{
|
||||
switch (operation)
|
||||
{
|
||||
case LESS_THAN:
|
||||
return gBattleMons[battler].hp < (gBattleMons[battler].maxHP / threshold);
|
||||
case EQUAL:
|
||||
return gBattleMons[battler].hp == (gBattleMons[battler].maxHP / threshold);
|
||||
case GREATER_THAN:
|
||||
return gBattleMons[battler].hp > (gBattleMons[battler].maxHP / threshold);
|
||||
case LESS_THAN_OR_EQUAL:
|
||||
return gBattleMons[battler].hp <= (gBattleMons[battler].maxHP / threshold);
|
||||
case GREATER_THAN_OR_EQUAL:
|
||||
return gBattleMons[battler].hp >= (gBattleMons[battler].maxHP / threshold);
|
||||
case NOT_EQUAL:
|
||||
default:
|
||||
return gBattleMons[battler].hp != (gBattleMons[battler].maxHP / threshold);
|
||||
}
|
||||
}
|
||||
|
||||
u32 ShouldDoTrainerSlide(u32 battler, u32 which)
|
||||
{
|
||||
u32 i, firstId, lastId, trainerId, retValue = 1;
|
||||
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER) || GetBattlerSide(battler) != B_SIDE_OPPONENT)
|
||||
return 0;
|
||||
|
||||
// Two opponents support.
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
|
||||
{
|
||||
if (gBattlerPartyIndexes[battler] >= 3)
|
||||
{
|
||||
firstId = 3, lastId = PARTY_SIZE;
|
||||
trainerId = gTrainerBattleOpponent_B;
|
||||
retValue = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
firstId = 0, lastId = 3;
|
||||
trainerId = gTrainerBattleOpponent_A;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
firstId = 0, lastId = PARTY_SIZE;
|
||||
trainerId = gTrainerBattleOpponent_A;
|
||||
}
|
||||
|
||||
enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(trainerId);
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(sTrainerSlides); i++)
|
||||
{
|
||||
if (trainerId == sTrainerSlides[difficulty]->trainerId
|
||||
&& (((gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && sTrainerSlides[difficulty]->isFrontierTrainer)
|
||||
|| (!(gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && !sTrainerSlides[difficulty]->isFrontierTrainer)))
|
||||
{
|
||||
gBattleScripting.battler = battler;
|
||||
switch (which)
|
||||
{
|
||||
case TRAINER_SLIDE_LAST_SWITCHIN:
|
||||
if (sTrainerSlides[difficulty]->msgLastSwitchIn != NULL && !CanBattlerSwitch(battler))
|
||||
{
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgLastSwitchIn;
|
||||
return retValue;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_LAST_LOW_HP:
|
||||
if (sTrainerSlides[difficulty]->msgLastLowHp != NULL
|
||||
&& GetEnemyMonCount(firstId, lastId, TRUE) == 1
|
||||
&& BattlerHPPercentage(battler, LESS_THAN_OR_EQUAL, 4)
|
||||
&& !gBattleStruct->trainerSlideLowHpMsgDone)
|
||||
{
|
||||
gBattleStruct->trainerSlideLowHpMsgDone = TRUE;
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgLastLowHp;
|
||||
return retValue;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_FIRST_DOWN:
|
||||
if (sTrainerSlides[difficulty]->msgFirstDown != NULL && GetEnemyMonCount(firstId, lastId, TRUE) == GetEnemyMonCount(firstId, lastId, FALSE) - 1)
|
||||
{
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgFirstDown;
|
||||
return retValue;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_LAST_HALF_HP:
|
||||
if (sTrainerSlides[difficulty]->msgLastHalfHp != NULL
|
||||
&& GetEnemyMonCount(firstId, lastId, TRUE) == GetEnemyMonCount(firstId, lastId, FALSE) - 1
|
||||
&& BattlerHPPercentage(battler, LESS_THAN_OR_EQUAL, 2) && BattlerHPPercentage(battler, GREATER_THAN, 4)
|
||||
&& !gBattleStruct->trainerSlideHalfHpMsgDone)
|
||||
{
|
||||
gBattleStruct->trainerSlideHalfHpMsgDone = TRUE;
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgLastHalfHp;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_FIRST_CRITICAL_HIT:
|
||||
if (sTrainerSlides[difficulty]->msgFirstCriticalHit != NULL && gBattleStruct->trainerSlideFirstCriticalHitMsgState == 1)
|
||||
{
|
||||
gBattleStruct->trainerSlideFirstCriticalHitMsgState = 2;
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgFirstCriticalHit;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_FIRST_SUPER_EFFECTIVE_HIT:
|
||||
if (sTrainerSlides[difficulty]->msgFirstSuperEffectiveHit != NULL
|
||||
&& gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState == 1
|
||||
&& gBattleMons[battler].hp)
|
||||
{
|
||||
gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState = 2;
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgFirstSuperEffectiveHit;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_FIRST_STAB_MOVE:
|
||||
if (sTrainerSlides[difficulty]->msgFirstSTABMove != NULL
|
||||
&& gBattleStruct->trainerSlideFirstSTABMoveMsgState == 1
|
||||
&& GetEnemyMonCount(firstId, lastId, TRUE) == GetEnemyMonCount(firstId, lastId, FALSE))
|
||||
{
|
||||
gBattleStruct->trainerSlideFirstSTABMoveMsgState = 2;
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgFirstSTABMove;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_PLAYER_MON_UNAFFECTED:
|
||||
if (sTrainerSlides[difficulty]->msgPlayerMonUnaffected != NULL
|
||||
&& gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState == 1
|
||||
&& GetEnemyMonCount(firstId, lastId, TRUE) == GetEnemyMonCount(firstId, lastId, FALSE))
|
||||
{
|
||||
gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState = 2;
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgPlayerMonUnaffected;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_MEGA_EVOLUTION:
|
||||
if (sTrainerSlides[difficulty]->msgMegaEvolution != NULL && !gBattleStruct->trainerSlideMegaEvolutionMsgDone)
|
||||
{
|
||||
gBattleStruct->trainerSlideMegaEvolutionMsgDone = TRUE;
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgMegaEvolution;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_Z_MOVE:
|
||||
if (sTrainerSlides[difficulty]->msgZMove != NULL && !gBattleStruct->trainerSlideZMoveMsgDone)
|
||||
{
|
||||
gBattleStruct->trainerSlideZMoveMsgDone = TRUE;
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgZMove;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_BEFORE_FIRST_TURN:
|
||||
if (sTrainerSlides[difficulty]->msgBeforeFirstTurn != NULL && !gBattleStruct->trainerSlideBeforeFirstTurnMsgDone)
|
||||
{
|
||||
gBattleStruct->trainerSlideBeforeFirstTurnMsgDone = TRUE;
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgBeforeFirstTurn;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_DYNAMAX:
|
||||
if (sTrainerSlides[difficulty]->msgDynamax != NULL && !gBattleStruct->trainerSlideDynamaxMsgDone)
|
||||
{
|
||||
gBattleStruct->trainerSlideDynamaxMsgDone = TRUE;
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgDynamax;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -61,6 +61,7 @@
|
||||
#include "constants/party_menu.h"
|
||||
#include "constants/rgb.h"
|
||||
#include "constants/songs.h"
|
||||
#include "constants/trainer_slide.h"
|
||||
#include "constants/trainers.h"
|
||||
#include "battle_util.h"
|
||||
#include "constants/pokemon.h"
|
||||
@ -299,11 +300,6 @@ static const u16 sTrappingMoves[NUM_TRAPPING_MOVES] =
|
||||
MOVE_THUNDER_CAGE
|
||||
};
|
||||
|
||||
static const u16 sBadgeFlags[8] = {
|
||||
FLAG_BADGE01_GET, FLAG_BADGE02_GET, FLAG_BADGE03_GET, FLAG_BADGE04_GET,
|
||||
FLAG_BADGE05_GET, FLAG_BADGE06_GET, FLAG_BADGE07_GET, FLAG_BADGE08_GET,
|
||||
};
|
||||
|
||||
static const u16 sWhiteOutBadgeMoney[9] = { 8, 16, 24, 36, 48, 64, 80, 100, 120 };
|
||||
|
||||
#define STAT_CHANGE_WORKED 0
|
||||
@ -1450,7 +1446,7 @@ static bool32 AccuracyCalcHelper(u32 move, u32 battler)
|
||||
effect = TRUE;
|
||||
}
|
||||
|
||||
if (WEATHER_HAS_EFFECT)
|
||||
if (HasWeatherEffect())
|
||||
{
|
||||
if ((moveEffect == EFFECT_THUNDER || moveEffect == EFFECT_RAIN_ALWAYS_HIT)
|
||||
&& IsBattlerWeatherAffected(battler, B_WEATHER_RAIN))
|
||||
@ -1539,11 +1535,11 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u
|
||||
switch (defAbility)
|
||||
{
|
||||
case ABILITY_SAND_VEIL:
|
||||
if (WEATHER_HAS_EFFECT && gBattleWeather & B_WEATHER_SANDSTORM)
|
||||
if (HasWeatherEffect() && gBattleWeather & B_WEATHER_SANDSTORM)
|
||||
calc = (calc * 80) / 100; // 1.2 sand veil loss
|
||||
break;
|
||||
case ABILITY_SNOW_CLOAK:
|
||||
if (WEATHER_HAS_EFFECT && (gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW)))
|
||||
if (HasWeatherEffect() && (gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW)))
|
||||
calc = (calc * 80) / 100; // 1.2 snow cloak loss
|
||||
break;
|
||||
case ABILITY_TANGLED_FEET:
|
||||
@ -1595,7 +1591,7 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u
|
||||
if (B_AFFECTION_MECHANICS == TRUE && GetBattlerAffectionHearts(battlerDef) == AFFECTION_FIVE_HEARTS)
|
||||
calc = (calc * 90) / 100;
|
||||
|
||||
if (WEATHER_HAS_EFFECT && gBattleWeather & B_WEATHER_FOG)
|
||||
if (HasWeatherEffect() && gBattleWeather & B_WEATHER_FOG)
|
||||
calc = (calc * 60) / 100; // modified by 3/5
|
||||
|
||||
return calc;
|
||||
@ -2307,7 +2303,7 @@ static u32 UpdateEffectivenessResultFlagsForDoubleSpreadMoves(u32 resultFlags)
|
||||
|
||||
static inline bool32 TryStrongWindsWeakenAttack(u32 battlerDef, u32 moveType)
|
||||
{
|
||||
if (gBattleWeather & B_WEATHER_STRONG_WINDS && WEATHER_HAS_EFFECT)
|
||||
if (gBattleWeather & B_WEATHER_STRONG_WINDS && HasWeatherEffect())
|
||||
{
|
||||
if (GetMoveCategory(gCurrentMove) != DAMAGE_CATEGORY_STATUS
|
||||
&& IS_BATTLER_OF_TYPE(battlerDef, TYPE_FLYING)
|
||||
@ -2702,9 +2698,8 @@ static void Cmd_critmessage(void)
|
||||
{
|
||||
PrepareStringBattle(STRINGID_CRITICALHIT, gBattlerAttacker);
|
||||
|
||||
// Signal for the trainer slide-in system.
|
||||
if (GetBattlerSide(gBattlerTarget) != B_SIDE_PLAYER && gBattleStruct->trainerSlideFirstCriticalHitMsgState != 2)
|
||||
gBattleStruct->trainerSlideFirstCriticalHitMsgState = 1;
|
||||
TryInitalizeTrainerSlideEnemyLandsFirstCriticalHit(gBattlerTarget);
|
||||
TryInitalizeTrainerSlidePlayerLandsFirstCriticalHit(gBattlerTarget);
|
||||
|
||||
gBattleCommunication[MSG_DISPLAY] = 1;
|
||||
}
|
||||
@ -2850,11 +2845,8 @@ static void Cmd_resultmessage(void)
|
||||
{
|
||||
stringId = STRINGID_SUPEREFFECTIVE;
|
||||
}
|
||||
if (stringId) // Signal for the trainer slide-in system
|
||||
{
|
||||
if (GetBattlerSide(gBattlerTarget) != B_SIDE_PLAYER && gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState != 2)
|
||||
gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState = 1;
|
||||
}
|
||||
if (stringId == STRINGID_SUPEREFFECTIVE || stringId == STRINGID_SUPEREFFECTIVETWOFOES)
|
||||
TryInitalizeTrainerSlidePlayerLandsFirstSuperEffectiveHit(gBattlerTarget);
|
||||
break;
|
||||
case MOVE_RESULT_NOT_VERY_EFFECTIVE:
|
||||
if (IsDoubleSpreadMove())
|
||||
@ -3796,10 +3788,6 @@ void SetMoveEffect(bool32 primary, bool32 certain)
|
||||
gBattlescriptCurrInstr = BattleScript_AllStatsUp;
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_RAPID_SPIN:
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_RapidSpinAway;
|
||||
break;
|
||||
case MOVE_EFFECT_ATK_DEF_DOWN: // SuperPower
|
||||
if (!NoAliveMonsForEitherParty())
|
||||
{
|
||||
@ -4507,7 +4495,7 @@ static void Cmd_tryfaintmon(void)
|
||||
&& IsBattlerAlive(gBattlerAttacker)
|
||||
&& gCurrentMove != MOVE_STRUGGLE)
|
||||
{
|
||||
u8 moveIndex = *(gBattleStruct->chosenMovePositions + gBattlerAttacker);
|
||||
u8 moveIndex = gBattleStruct->chosenMovePositions[gBattlerAttacker];
|
||||
|
||||
gBattleMons[gBattlerAttacker].pp[moveIndex] = 0;
|
||||
BattleScriptPush(gBattlescriptCurrInstr);
|
||||
@ -6139,6 +6127,17 @@ static void Cmd_moveend(void)
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
}
|
||||
case MOVEEND_RAPID_SPIN:
|
||||
if (gMovesInfo[gCurrentMove].effect == EFFECT_RAPID_SPIN
|
||||
&& !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget))
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_RapidSpinAway;
|
||||
effect = TRUE;
|
||||
}
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_ITEM_EFFECTS_ATTACKER:
|
||||
if (ItemBattleEffects(ITEMEFFECT_MOVE_END, gBattlerAttacker, FALSE))
|
||||
effect = TRUE;
|
||||
@ -6950,9 +6949,9 @@ static void Cmd_moveend(void)
|
||||
break;
|
||||
case MOVEEND_CLEAR_BITS: // Clear/Set bits for things like using a move for all targets and all hits.
|
||||
if (gSpecialStatuses[gBattlerAttacker].instructedChosenTarget)
|
||||
*(gBattleStruct->moveTarget + gBattlerAttacker) = gSpecialStatuses[gBattlerAttacker].instructedChosenTarget & 0x3;
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = gSpecialStatuses[gBattlerAttacker].instructedChosenTarget & 0x3;
|
||||
if (gSpecialStatuses[gBattlerAttacker].dancerOriginalTarget)
|
||||
*(gBattleStruct->moveTarget + gBattlerAttacker) = gSpecialStatuses[gBattlerAttacker].dancerOriginalTarget & 0x3;
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = gSpecialStatuses[gBattlerAttacker].dancerOriginalTarget & 0x3;
|
||||
|
||||
if (B_RAMPAGE_CANCELLING >= GEN_5
|
||||
&& MoveHasAdditionalEffectSelf(gCurrentMove, MOVE_EFFECT_THRASH) // If we're rampaging
|
||||
@ -7027,7 +7026,7 @@ static void Cmd_moveend(void)
|
||||
if (SetTargetToNextPursuiter(gBattlerTarget))
|
||||
{
|
||||
ChangeOrderTargetAfterAttacker();
|
||||
*(gBattleStruct->moveTarget + gBattlerTarget) = storedTarget;
|
||||
gBattleStruct->moveTarget[gBattlerTarget] = storedTarget;
|
||||
gBattlerTarget = storedTarget;
|
||||
}
|
||||
else if (IsBattlerAlive(gBattlerTarget))
|
||||
@ -7037,7 +7036,7 @@ static void Cmd_moveend(void)
|
||||
gBattlescriptCurrInstr = BattleScript_MoveSwitchOpenPartyScreen;
|
||||
else
|
||||
gBattlescriptCurrInstr = BattleScript_DoSwitchOut;
|
||||
*(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = gBattleStruct->pursuitStoredSwitch;
|
||||
gBattleStruct->monToSwitchIntoId[gBattlerTarget] = gBattleStruct->pursuitStoredSwitch;
|
||||
ClearPursuitValues();
|
||||
effect = TRUE;
|
||||
}
|
||||
@ -7562,11 +7561,11 @@ static void Cmd_openpartyscreen(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
*(gBattleStruct->battlerPartyIndexes + battler) = gBattlerPartyIndexes[battler];
|
||||
*(gBattleStruct->monToSwitchIntoId + battler) = PARTY_SIZE;
|
||||
gBattleStruct->battlerPartyIndexes[battler] = gBattlerPartyIndexes[battler];
|
||||
gBattleStruct->monToSwitchIntoId[battler] = PARTY_SIZE;
|
||||
gBattleStruct->field_93 &= ~(1u << battler);
|
||||
|
||||
BtlController_EmitChoosePokemon(battler, BUFFER_A, hitmarkerFaintBits, *(gBattleStruct->monToSwitchIntoId + BATTLE_PARTNER(battler)), ABILITY_NONE, gBattleStruct->battlerPartyOrders[battler]);
|
||||
BtlController_EmitChoosePokemon(battler, BUFFER_A, hitmarkerFaintBits, gBattleStruct->monToSwitchIntoId[BATTLE_PARTNER(battler)], ABILITY_NONE, gBattleStruct->battlerPartyOrders[battler]);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
@ -7619,7 +7618,7 @@ static void Cmd_switchhandleorder(void)
|
||||
{
|
||||
if (gBattleResources->bufferB[i][0] == CONTROLLER_CHOSENMONRETURNVALUE)
|
||||
{
|
||||
*(gBattleStruct->monToSwitchIntoId + i) = gBattleResources->bufferB[i][1];
|
||||
gBattleStruct->monToSwitchIntoId[i] = gBattleResources->bufferB[i][1];
|
||||
if (!(gBattleStruct->field_93 & (1u << i)))
|
||||
{
|
||||
RecordedBattle_SetBattlerAction(i, gBattleResources->bufferB[i][1]);
|
||||
@ -7641,7 +7640,7 @@ static void Cmd_switchhandleorder(void)
|
||||
// fall through
|
||||
case 3:
|
||||
gBattleCommunication[0] = gBattleResources->bufferB[battler][1];
|
||||
*(gBattleStruct->monToSwitchIntoId + battler) = gBattleResources->bufferB[battler][1];
|
||||
gBattleStruct->monToSwitchIntoId[battler] = gBattleResources->bufferB[battler][1];
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & BATTLE_TYPE_MULTI)
|
||||
{
|
||||
@ -7655,7 +7654,7 @@ static void Cmd_switchhandleorder(void)
|
||||
}
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
|
||||
{
|
||||
SwitchPartyOrderInGameMulti(battler, *(gBattleStruct->monToSwitchIntoId + battler));
|
||||
SwitchPartyOrderInGameMulti(battler, gBattleStruct->monToSwitchIntoId[battler]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -7692,7 +7691,7 @@ bool32 DoSwitchInAbilities(u32 battler)
|
||||
{
|
||||
return (TryPrimalReversion(battler)
|
||||
|| AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0)
|
||||
|| (gBattleWeather & B_WEATHER_ANY && WEATHER_HAS_EFFECT && AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0))
|
||||
|| (gBattleWeather & B_WEATHER_ANY && HasWeatherEffect() && AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0))
|
||||
|| (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY && AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, 0, 0, 0)));
|
||||
}
|
||||
|
||||
@ -8319,9 +8318,9 @@ static void Cmd_getmoneyreward(void)
|
||||
sPartyLevel = GetMonData(&gPlayerParty[i], MON_DATA_LEVEL);
|
||||
}
|
||||
}
|
||||
for (count = 0, i = 0; i < ARRAY_COUNT(sBadgeFlags); i++)
|
||||
for (count = 0, i = 0; i < ARRAY_COUNT(gBadgeFlags); i++)
|
||||
{
|
||||
if (FlagGet(sBadgeFlags[i]) == TRUE)
|
||||
if (FlagGet(gBadgeFlags[i]) == TRUE)
|
||||
++count;
|
||||
}
|
||||
money = sWhiteOutBadgeMoney[count] * sPartyLevel;
|
||||
@ -9054,7 +9053,7 @@ static void Cmd_hpthresholds2(void)
|
||||
{
|
||||
u32 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
u32 opposingBattler = BATTLE_OPPOSITE(battler);
|
||||
u8 hpSwitchout = *(gBattleStruct->hpOnSwitchout + GetBattlerSide(opposingBattler));
|
||||
u8 hpSwitchout = gBattleStruct->hpOnSwitchout[GetBattlerSide(opposingBattler)];
|
||||
s32 result = (hpSwitchout - gBattleMons[opposingBattler].hp) * 100 / hpSwitchout;
|
||||
|
||||
if (gBattleMons[opposingBattler].hp >= hpSwitchout)
|
||||
@ -10504,7 +10503,7 @@ static void Cmd_various(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
gSpecialStatuses[gBattlerTarget].instructedChosenTarget = *(gBattleStruct->moveTarget + gBattlerTarget) | 0x4;
|
||||
gSpecialStatuses[gBattlerTarget].instructedChosenTarget = gBattleStruct->moveTarget[gBattlerTarget] | 0x4;
|
||||
gCalledMove = move;
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
@ -10696,7 +10695,7 @@ static void Cmd_various(void)
|
||||
case VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF:
|
||||
{
|
||||
VARIOUS_ARGS();
|
||||
if ((i = ShouldDoTrainerSlide(battler, TRAINER_SLIDE_FIRST_DOWN)))
|
||||
if ((i = ShouldDoTrainerSlide(battler, TRAINER_SLIDE_PLAYER_LANDS_FIRST_DOWN)))
|
||||
{
|
||||
gBattleScripting.battler = battler;
|
||||
BattleScriptPush(cmd->nextInstr);
|
||||
@ -10721,7 +10720,7 @@ static void Cmd_various(void)
|
||||
{
|
||||
VARIOUS_ARGS();
|
||||
if (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_AURORA_VEIL
|
||||
|| !(WEATHER_HAS_EFFECT && gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW)))
|
||||
|| !(HasWeatherEffect() && gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW)))
|
||||
{
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
|
||||
@ -10828,25 +10827,25 @@ static void Cmd_various(void)
|
||||
VARIOUS_ARGS(const u8 *failInstr);
|
||||
if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_SEEDS)
|
||||
{
|
||||
u8 effect = 0;
|
||||
enum ItemEffect effect = ITEM_NO_EFFECT;
|
||||
u16 item = gBattleMons[battler].item;
|
||||
switch (GetBattlerHoldEffectParam(battler))
|
||||
{
|
||||
case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN:
|
||||
effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE);
|
||||
effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, item, ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN);
|
||||
break;
|
||||
case HOLD_EFFECT_PARAM_GRASSY_TERRAIN:
|
||||
effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE);
|
||||
effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, item, ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN);
|
||||
break;
|
||||
case HOLD_EFFECT_PARAM_MISTY_TERRAIN:
|
||||
effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE);
|
||||
effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN);
|
||||
break;
|
||||
case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN:
|
||||
effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE);
|
||||
effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN);
|
||||
break;
|
||||
}
|
||||
|
||||
if (effect)
|
||||
if (effect != ITEM_NO_EFFECT)
|
||||
return;
|
||||
}
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
@ -12488,10 +12487,10 @@ static void Cmd_forcerandomswitch(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
*(gBattleStruct->battlerPartyIndexes + gBattlerTarget) = gBattlerPartyIndexes[gBattlerTarget];
|
||||
gBattleStruct->battlerPartyIndexes[gBattlerTarget] = gBattlerPartyIndexes[gBattlerTarget];
|
||||
gBattlescriptCurrInstr = BattleScript_RoarSuccessSwitch;
|
||||
gBattleStruct->battlerState[gBattlerTarget].forcedSwitch = TRUE;
|
||||
*(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = validMons[RandomUniform(RNG_FORCE_RANDOM_SWITCH, 0, validMonsCount - 1)];
|
||||
gBattleStruct->monToSwitchIntoId[gBattlerTarget] = validMons[RandomUniform(RNG_FORCE_RANDOM_SWITCH, 0, validMonsCount - 1)];
|
||||
|
||||
if (!IsMultiBattle())
|
||||
SwitchPartyOrder(gBattlerTarget);
|
||||
@ -14004,7 +14003,7 @@ static bool32 SetTargetToNextPursuiter(u32 battlerDef)
|
||||
&& IsBattlerAlive(battlerDef)
|
||||
&& IsBattlerAlive(battler)
|
||||
&& GetBattlerSide(battler) != GetBattlerSide(battlerDef)
|
||||
&& (B_PURSUIT_TARGET >= GEN_4 || *(gBattleStruct->moveTarget + battler) == battlerDef)
|
||||
&& (B_PURSUIT_TARGET >= GEN_4 || gBattleStruct->moveTarget[battler] == battlerDef)
|
||||
&& !IsGimmickSelected(battler, GIMMICK_Z_MOVE)
|
||||
&& !IsGimmickSelected(battler, GIMMICK_DYNAMAX)
|
||||
&& GetActiveGimmick(battler) != GIMMICK_DYNAMAX)
|
||||
@ -14028,7 +14027,7 @@ static void Cmd_jumpifnopursuitswitchdmg(void)
|
||||
gBattleStruct->battlerState[gBattlerAttacker].pursuitTarget = TRUE;
|
||||
gBattleStruct->pursuitSwitchByMove = gActionsByTurnOrder[gCurrentTurnActionNumber] == B_ACTION_USE_MOVE;
|
||||
gBattleStruct->pursuitStoredSwitch = gBattleStruct->monToSwitchIntoId[gBattlerAttacker];
|
||||
*(gBattleStruct->moveTarget + gBattlerTarget) = gBattlerAttacker;
|
||||
gBattleStruct->moveTarget[gBattlerTarget] = gBattlerAttacker;
|
||||
gBattlerTarget = savedTarget;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
@ -14091,7 +14090,7 @@ static void Cmd_rapidspinfree(void)
|
||||
{
|
||||
gBattleScripting.battler = gBattlerTarget;
|
||||
gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_WRAPPED;
|
||||
gBattlerTarget = *(gBattleStruct->wrappedBy + gBattlerAttacker);
|
||||
gBattlerTarget = gBattleStruct->wrappedBy[gBattlerAttacker];
|
||||
PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->wrappedMove[gBattlerAttacker]);
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_WrapFree;
|
||||
@ -14161,14 +14160,14 @@ static void Cmd_recoverbasedonsunlight(void)
|
||||
{
|
||||
if (gCurrentMove == MOVE_SHORE_UP)
|
||||
{
|
||||
if (WEATHER_HAS_EFFECT && gBattleWeather & B_WEATHER_SANDSTORM)
|
||||
if (HasWeatherEffect() && gBattleWeather & B_WEATHER_SANDSTORM)
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = 20 * GetNonDynamaxMaxHP(gBattlerAttacker) / 30;
|
||||
else
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(gBattleWeather & B_WEATHER_ANY) || !WEATHER_HAS_EFFECT || GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_UTILITY_UMBRELLA)
|
||||
if (!(gBattleWeather & B_WEATHER_ANY) || !HasWeatherEffect() || GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_UTILITY_UMBRELLA)
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2;
|
||||
else if (gBattleWeather & B_WEATHER_SUN)
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = 20 * GetNonDynamaxMaxHP(gBattlerAttacker) / 30;
|
||||
@ -14417,7 +14416,6 @@ static void Cmd_setcharge(void)
|
||||
gDisableStructs[battler].chargeTimer = 2;
|
||||
else
|
||||
gDisableStructs[battler].chargeTimer = 0;
|
||||
gBattlescriptCurrInstr++;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
@ -15084,7 +15082,7 @@ static void Cmd_switchoutabilities(void)
|
||||
|
||||
gBattleMons[battler].status1 = 0;
|
||||
BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE,
|
||||
1u << *(gBattleStruct->battlerPartyIndexes + battler),
|
||||
1u << gBattleStruct->battlerPartyIndexes[battler],
|
||||
sizeof(gBattleMons[battler].status1),
|
||||
&gBattleMons[battler].status1);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
@ -15096,7 +15094,7 @@ static void Cmd_switchoutabilities(void)
|
||||
if (regenerate > gBattleMons[battler].maxHP)
|
||||
regenerate = gBattleMons[battler].maxHP;
|
||||
BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_HP_BATTLE,
|
||||
1u << *(gBattleStruct->battlerPartyIndexes + battler),
|
||||
1u << gBattleStruct->battlerPartyIndexes[battler],
|
||||
sizeof(regenerate),
|
||||
®enerate);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
|
||||
@ -360,12 +360,6 @@ const struct RematchTrainer gRematchTable[REMATCH_TABLE_ENTRIES] =
|
||||
[REMATCH_WALLACE] = REMATCH(TRAINER_WALLACE, TRAINER_WALLACE, TRAINER_WALLACE, TRAINER_WALLACE, TRAINER_WALLACE, EVER_GRANDE_CITY),
|
||||
};
|
||||
|
||||
static const u16 sBadgeFlags[NUM_BADGES] =
|
||||
{
|
||||
FLAG_BADGE01_GET, FLAG_BADGE02_GET, FLAG_BADGE03_GET, FLAG_BADGE04_GET,
|
||||
FLAG_BADGE05_GET, FLAG_BADGE06_GET, FLAG_BADGE07_GET, FLAG_BADGE08_GET,
|
||||
};
|
||||
|
||||
#define tState data[0]
|
||||
#define tTransition data[1]
|
||||
|
||||
@ -1920,9 +1914,9 @@ static bool32 HasAtLeastFiveBadges(void)
|
||||
{
|
||||
s32 i, count;
|
||||
|
||||
for (count = 0, i = 0; i < ARRAY_COUNT(sBadgeFlags); i++)
|
||||
for (count = 0, i = 0; i < ARRAY_COUNT(gBadgeFlags); i++)
|
||||
{
|
||||
if (FlagGet(sBadgeFlags[i]) == TRUE)
|
||||
if (FlagGet(gBadgeFlags[i]) == TRUE)
|
||||
{
|
||||
if (++count >= 5)
|
||||
return TRUE;
|
||||
|
||||
@ -2527,13 +2527,13 @@ static void Mugshots_CreateTrainerPics(struct Task *task)
|
||||
task->tOpponentSpriteId = CreateTrainerSprite(trainerPicId,
|
||||
gTrainerSprites[trainerPicId].mugshotCoords.x - 32,
|
||||
gTrainerSprites[trainerPicId].mugshotCoords.y + 42,
|
||||
0, gDecompressionBuffer);
|
||||
0, NULL);
|
||||
gReservedSpritePaletteCount = 12;
|
||||
|
||||
task->tPlayerSpriteId = CreateTrainerSprite(PlayerGenderToFrontTrainerPicId(gSaveBlock2Ptr->playerGender),
|
||||
DISPLAY_WIDTH + 32,
|
||||
106,
|
||||
0, gDecompressionBuffer);
|
||||
0, NULL);
|
||||
|
||||
opponentSprite = &gSprites[task->tOpponentSpriteId];
|
||||
playerSprite = &gSprites[task->tPlayerSpriteId];
|
||||
|
||||
@ -934,7 +934,7 @@ static void AddMovePoints(u8 caseId, u16 arg1, u8 arg2, u8 arg3)
|
||||
// Various cases to add/remove points
|
||||
if (GetMoveRecoil(arg2) > 0)
|
||||
baseFromEffect++; // Recoil moves
|
||||
if (MoveHasAdditionalEffect(arg2, MOVE_EFFECT_RAPID_SPIN))
|
||||
if (gMovesInfo[arg2].effect == EFFECT_RAPID_SPIN)
|
||||
baseFromEffect++;
|
||||
if (MoveHasAdditionalEffect(arg2, MOVE_EFFECT_SP_ATK_MINUS_2) || MoveHasAdditionalEffect(arg2, MOVE_EFFECT_ATK_DEF_DOWN))
|
||||
baseFromEffect += 2; // Overheat, Superpower, etc.
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include "task.h"
|
||||
#include "test_runner.h"
|
||||
#include "trig.h"
|
||||
#include "trainer_slide.h"
|
||||
#include "window.h"
|
||||
#include "battle_message.h"
|
||||
#include "battle_ai_main.h"
|
||||
@ -253,7 +254,7 @@ void HandleAction_UseMove(void)
|
||||
gBattleScripting.savedDmg = 0;
|
||||
gBattleCommunication[MISS_TYPE] = 0;
|
||||
gBattleScripting.savedMoveEffect = 0;
|
||||
gCurrMovePos = gChosenMovePos = *(gBattleStruct->chosenMovePositions + gBattlerAttacker);
|
||||
gCurrMovePos = gChosenMovePos = gBattleStruct->chosenMovePositions[gBattlerAttacker];
|
||||
|
||||
// choose move
|
||||
if (gProtectStructs[gBattlerAttacker].noValidMoves)
|
||||
@ -261,7 +262,7 @@ void HandleAction_UseMove(void)
|
||||
gProtectStructs[gBattlerAttacker].noValidMoves = FALSE;
|
||||
gCurrentMove = gChosenMove = MOVE_STRUGGLE;
|
||||
gHitMarker |= HITMARKER_NO_PPDEDUCT;
|
||||
*(gBattleStruct->moveTarget + gBattlerAttacker) = GetBattleMoveTarget(MOVE_STRUGGLE, NO_TARGET_OVERRIDE);
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(MOVE_STRUGGLE, NO_TARGET_OVERRIDE);
|
||||
}
|
||||
else if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS || gBattleMons[gBattlerAttacker].status2 & STATUS2_RECHARGE)
|
||||
{
|
||||
@ -273,7 +274,7 @@ void HandleAction_UseMove(void)
|
||||
{
|
||||
gCurrentMove = gChosenMove = gDisableStructs[gBattlerAttacker].encoredMove;
|
||||
gCurrMovePos = gChosenMovePos = gDisableStructs[gBattlerAttacker].encoredMovePos;
|
||||
*(gBattleStruct->moveTarget + gBattlerAttacker) = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE);
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE);
|
||||
}
|
||||
// check if the encored move wasn't overwritten
|
||||
else if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].encoredMove != MOVE_NONE
|
||||
@ -284,12 +285,12 @@ void HandleAction_UseMove(void)
|
||||
gDisableStructs[gBattlerAttacker].encoredMove = MOVE_NONE;
|
||||
gDisableStructs[gBattlerAttacker].encoredMovePos = 0;
|
||||
gDisableStructs[gBattlerAttacker].encoreTimer = 0;
|
||||
*(gBattleStruct->moveTarget + gBattlerAttacker) = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE);
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE);
|
||||
}
|
||||
else if (gBattleMons[gBattlerAttacker].moves[gCurrMovePos] != gChosenMoveByBattler[gBattlerAttacker])
|
||||
{
|
||||
gCurrentMove = gChosenMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos];
|
||||
*(gBattleStruct->moveTarget + gBattlerAttacker) = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE);
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -335,7 +336,7 @@ void HandleAction_UseMove(void)
|
||||
}
|
||||
else if (IsDoubleBattle()
|
||||
&& gSideTimers[side].followmeTimer == 0
|
||||
&& !gBattleStruct->battlerState[*(gBattleStruct->moveTarget + gBattlerAttacker)].pursuitTarget
|
||||
&& !gBattleStruct->battlerState[gBattleStruct->moveTarget[gBattlerAttacker]].pursuitTarget
|
||||
&& (!IsBattleMoveStatus(gCurrentMove) || (moveTarget != MOVE_TARGET_USER && moveTarget != MOVE_TARGET_ALL_BATTLERS))
|
||||
&& ((ability != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC)
|
||||
|| (ability != ABILITY_STORM_DRAIN && moveType == TYPE_WATER)))
|
||||
@ -376,7 +377,7 @@ void HandleAction_UseMove(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlerTarget = *(gBattleStruct->moveTarget + gBattlerAttacker);
|
||||
gBattlerTarget = gBattleStruct->moveTarget[gBattlerAttacker];
|
||||
}
|
||||
|
||||
if (!IsBattlerAlive(gBattlerTarget) && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget))
|
||||
@ -426,7 +427,7 @@ void HandleAction_UseMove(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlerTarget = *(gBattleStruct->moveTarget + gBattlerAttacker);
|
||||
gBattlerTarget = gBattleStruct->moveTarget[gBattlerAttacker];
|
||||
if (!IsBattlerAlive(gBattlerTarget)
|
||||
&& moveTarget != MOVE_TARGET_OPPONENTS_FIELD
|
||||
&& (GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget)))
|
||||
@ -486,7 +487,7 @@ void HandleAction_Switch(void)
|
||||
gActionSelectionCursor[gBattlerAttacker] = 0;
|
||||
gMoveSelectionCursor[gBattlerAttacker] = 0;
|
||||
|
||||
PREPARE_MON_NICK_BUFFER(gBattleTextBuff1, gBattlerAttacker, *(gBattleStruct->battlerPartyIndexes + gBattlerAttacker))
|
||||
PREPARE_MON_NICK_BUFFER(gBattleTextBuff1, gBattlerAttacker, gBattleStruct->battlerPartyIndexes[gBattlerAttacker]);
|
||||
|
||||
gBattleScripting.battler = gBattlerAttacker;
|
||||
gBattlescriptCurrInstr = BattleScript_ActionSwitch;
|
||||
@ -788,7 +789,7 @@ void HandleAction_ActionFinished(void)
|
||||
{
|
||||
u32 i, j, moveType;
|
||||
bool32 afterYouActive = gSpecialStatuses[gBattlerByTurnOrder[gCurrentTurnActionNumber + 1]].afterYou;
|
||||
*(gBattleStruct->monToSwitchIntoId + gBattlerByTurnOrder[gCurrentTurnActionNumber]) = gSelectedMonPartyId = PARTY_SIZE;
|
||||
gBattleStruct->monToSwitchIntoId[gBattlerByTurnOrder[gCurrentTurnActionNumber]] = gSelectedMonPartyId = PARTY_SIZE;
|
||||
gCurrentTurnActionNumber++;
|
||||
gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber];
|
||||
SpecialStatusesClear();
|
||||
@ -1132,11 +1133,8 @@ void PrepareStringBattle(u16 stringId, u32 battler)
|
||||
SET_STATCHANGER(STAT_SPEED, 1, FALSE);
|
||||
}
|
||||
|
||||
// Signal for the trainer slide-in system.
|
||||
if ((stringId == STRINGID_ITDOESNTAFFECT || stringId == STRINGID_PKMNWASNTAFFECTED || stringId == STRINGID_PKMNUNAFFECTED)
|
||||
&& GetBattlerSide(gBattlerTarget) == B_SIDE_OPPONENT
|
||||
&& gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState != 2)
|
||||
gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState = 1;
|
||||
if ((stringId == STRINGID_ITDOESNTAFFECT || stringId == STRINGID_PKMNWASNTAFFECTED || stringId == STRINGID_PKMNUNAFFECTED))
|
||||
TryInitalizeTrainerSlideEnemyMonUnaffected(gBattlerTarget);
|
||||
|
||||
BtlController_EmitPrintString(battler, BUFFER_A, stringId);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
@ -2242,7 +2240,7 @@ u8 DoBattlerEndTurnEffects(void)
|
||||
{
|
||||
case ENDTURN_WEATHER_DAMAGE:
|
||||
ability = GetBattlerAbility(battler);
|
||||
if (!IsBattlerAlive(battler) || !WEATHER_HAS_EFFECT || ability == ABILITY_MAGIC_GUARD)
|
||||
if (!IsBattlerAlive(battler) || !HasWeatherEffect() || ability == ABILITY_MAGIC_GUARD)
|
||||
{
|
||||
gBattleStruct->turnEffectsTracker++;
|
||||
break;
|
||||
@ -3553,7 +3551,7 @@ static void CancellerStanceChangeTwo(u32 *effect)
|
||||
|
||||
static void CancellerWeatherPrimal(u32 *effect)
|
||||
{
|
||||
if (WEATHER_HAS_EFFECT && GetMovePower(gCurrentMove) > 0)
|
||||
if (HasWeatherEffect() && GetMovePower(gCurrentMove) > 0)
|
||||
{
|
||||
u32 moveType = GetBattleMoveType(gCurrentMove);
|
||||
if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL))
|
||||
@ -3901,7 +3899,7 @@ bool32 HasNoMonsToSwitch(u32 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2
|
||||
{
|
||||
if (IsValidForBattle(&party[i])
|
||||
&& i != partyIdBattlerOn1 && i != partyIdBattlerOn2
|
||||
&& i != *(gBattleStruct->monToSwitchIntoId + flankId) && i != playerId[gBattleStruct->monToSwitchIntoId])
|
||||
&& i != gBattleStruct->monToSwitchIntoId[flankId] && i != playerId[gBattleStruct->monToSwitchIntoId])
|
||||
break;
|
||||
}
|
||||
return (i == PARTY_SIZE);
|
||||
@ -3923,7 +3921,7 @@ bool32 HasNoMonsToSwitch(u32 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2
|
||||
{
|
||||
if (IsValidForBattle(&party[i])
|
||||
&& i != partyIdBattlerOn1 && i != partyIdBattlerOn2
|
||||
&& i != *(gBattleStruct->monToSwitchIntoId + flankId) && i != playerId[gBattleStruct->monToSwitchIntoId])
|
||||
&& i != gBattleStruct->monToSwitchIntoId[flankId] && i != playerId[gBattleStruct->monToSwitchIntoId])
|
||||
break;
|
||||
}
|
||||
return (i == PARTY_SIZE);
|
||||
@ -4012,7 +4010,7 @@ bool32 HasNoMonsToSwitch(u32 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2
|
||||
{
|
||||
if (IsValidForBattle(&party[i])
|
||||
&& i != partyIdBattlerOn1 && i != partyIdBattlerOn2
|
||||
&& i != *(gBattleStruct->monToSwitchIntoId + flankId) && i != playerId[gBattleStruct->monToSwitchIntoId])
|
||||
&& i != gBattleStruct->monToSwitchIntoId[flankId] && i != playerId[gBattleStruct->monToSwitchIntoId])
|
||||
break;
|
||||
}
|
||||
return (i == PARTY_SIZE);
|
||||
@ -4893,7 +4891,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
BattleScriptPushCursorAndCallback(BattleScript_DrizzleActivates);
|
||||
effect++;
|
||||
}
|
||||
else if (gBattleWeather & B_WEATHER_PRIMAL_ANY && WEATHER_HAS_EFFECT && !gSpecialStatuses[battler].switchInAbilityDone)
|
||||
else if (gBattleWeather & B_WEATHER_PRIMAL_ANY && HasWeatherEffect() && !gSpecialStatuses[battler].switchInAbilityDone)
|
||||
{
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BlockedByPrimalWeatherEnd3);
|
||||
@ -4906,7 +4904,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
BattleScriptPushCursorAndCallback(BattleScript_SandstreamActivates);
|
||||
effect++;
|
||||
}
|
||||
else if (gBattleWeather & B_WEATHER_PRIMAL_ANY && WEATHER_HAS_EFFECT && !gSpecialStatuses[battler].switchInAbilityDone)
|
||||
else if (gBattleWeather & B_WEATHER_PRIMAL_ANY && HasWeatherEffect() && !gSpecialStatuses[battler].switchInAbilityDone)
|
||||
{
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BlockedByPrimalWeatherEnd3);
|
||||
@ -4919,7 +4917,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
BattleScriptPushCursorAndCallback(BattleScript_DroughtActivates);
|
||||
effect++;
|
||||
}
|
||||
else if (gBattleWeather & B_WEATHER_PRIMAL_ANY && WEATHER_HAS_EFFECT && !gSpecialStatuses[battler].switchInAbilityDone)
|
||||
else if (gBattleWeather & B_WEATHER_PRIMAL_ANY && HasWeatherEffect() && !gSpecialStatuses[battler].switchInAbilityDone)
|
||||
{
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BlockedByPrimalWeatherEnd3);
|
||||
@ -4937,7 +4935,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
BattleScriptPushCursorAndCallback(BattleScript_SnowWarningActivatesHail);
|
||||
effect++;
|
||||
}
|
||||
else if (gBattleWeather & B_WEATHER_PRIMAL_ANY && WEATHER_HAS_EFFECT && !gSpecialStatuses[battler].switchInAbilityDone)
|
||||
else if (gBattleWeather & B_WEATHER_PRIMAL_ANY && HasWeatherEffect() && !gSpecialStatuses[battler].switchInAbilityDone)
|
||||
{
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BlockedByPrimalWeatherEnd3);
|
||||
@ -6070,9 +6068,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (MoveResultHasEffect(gBattlerTarget)
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& !(gBattleWeather & B_WEATHER_SANDSTORM && WEATHER_HAS_EFFECT))
|
||||
&& !(gBattleWeather & B_WEATHER_SANDSTORM && HasWeatherEffect()))
|
||||
{
|
||||
if (gBattleWeather & B_WEATHER_PRIMAL_ANY && WEATHER_HAS_EFFECT)
|
||||
if (gBattleWeather & B_WEATHER_PRIMAL_ANY && HasWeatherEffect())
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_BlockedByPrimalWeatherRet;
|
||||
@ -6298,7 +6296,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
{
|
||||
// Set bit and save Dancer mon's original target
|
||||
gSpecialStatuses[battler].dancerUsedMove = TRUE;
|
||||
gSpecialStatuses[battler].dancerOriginalTarget = *(gBattleStruct->moveTarget + battler) | 0x4;
|
||||
gSpecialStatuses[battler].dancerOriginalTarget = gBattleStruct->moveTarget[battler] | 0x4;
|
||||
gBattleStruct->atkCancellerTracker = 0;
|
||||
gBattlerAttacker = gBattlerAbility = battler;
|
||||
gCalledMove = gCurrentMove;
|
||||
@ -6533,7 +6531,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
case ABILITY_FLOWER_GIFT:
|
||||
if ((IsBattlerWeatherAffected(battler, gBattleWeather)
|
||||
|| gBattleWeather == B_WEATHER_NONE
|
||||
|| !WEATHER_HAS_EFFECT) // Air Lock active
|
||||
|| !HasWeatherEffect()) // Air Lock active
|
||||
&& TryBattleFormChange(battler, FORM_CHANGE_BATTLE_WEATHER))
|
||||
{
|
||||
gBattleScripting.battler = battler;
|
||||
@ -6565,7 +6563,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
}
|
||||
case ABILITY_PROTOSYNTHESIS:
|
||||
if (!gDisableStructs[battler].weatherAbilityDone
|
||||
&& (gBattleWeather & B_WEATHER_SUN) && WEATHER_HAS_EFFECT
|
||||
&& (gBattleWeather & B_WEATHER_SUN) && HasWeatherEffect()
|
||||
&& !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)
|
||||
&& !gDisableStructs[battler].boosterEnergyActivates)
|
||||
{
|
||||
@ -6787,16 +6785,6 @@ void BattleScriptPushCursorAndCallback(const u8 *BS_ptr)
|
||||
gBattleMainFunc = RunBattleScriptCommands;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
ITEM_NO_EFFECT,
|
||||
ITEM_STATUS_CHANGE,
|
||||
ITEM_EFFECT_OTHER,
|
||||
ITEM_PP_CHANGE,
|
||||
ITEM_HP_CHANGE,
|
||||
ITEM_STATS_CHANGE,
|
||||
};
|
||||
|
||||
bool32 IsBattlerTerrainAffected(u32 battler, u32 terrainFlag)
|
||||
{
|
||||
if (!(gFieldStatuses & terrainFlag))
|
||||
@ -6935,7 +6923,7 @@ bool32 HasEnoughHpToEatBerry(u32 battler, u32 hpFraction, u32 itemId)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static u32 HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, enum ItemEffect caseID)
|
||||
static enum ItemEffect HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, enum ItemCaseId caseID)
|
||||
{
|
||||
if (HasEnoughHpToEatBerry(battler, (B_CONFUSE_BERRIES_HEAL >= GEN_7 ? 4 : 2), itemId)
|
||||
&& (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)))
|
||||
@ -6971,10 +6959,10 @@ static u32 HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, enum ItemEffe
|
||||
|
||||
return ITEM_HP_CHANGE;
|
||||
}
|
||||
return 0;
|
||||
return ITEM_NO_EFFECT;
|
||||
}
|
||||
|
||||
static u32 StatRaiseBerry(u32 battler, u32 itemId, u32 statId, enum ItemEffect caseID)
|
||||
static enum ItemEffect StatRaiseBerry(u32 battler, u32 itemId, u32 statId, enum ItemCaseId caseID)
|
||||
{
|
||||
if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN) && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, itemId), itemId))
|
||||
{
|
||||
@ -7002,7 +6990,7 @@ static u32 StatRaiseBerry(u32 battler, u32 itemId, u32 statId, enum ItemEffect c
|
||||
return ITEM_NO_EFFECT;
|
||||
}
|
||||
|
||||
static u32 RandomStatRaiseBerry(u32 battler, u32 itemId, enum ItemEffect caseID)
|
||||
static enum ItemEffect RandomStatRaiseBerry(u32 battler, u32 itemId, enum ItemCaseId caseID)
|
||||
{
|
||||
s32 i;
|
||||
u16 stringId;
|
||||
@ -7050,10 +7038,10 @@ static u32 RandomStatRaiseBerry(u32 battler, u32 itemId, enum ItemEffect caseID)
|
||||
|
||||
return ITEM_STATS_CHANGE;
|
||||
}
|
||||
return 0;
|
||||
return ITEM_NO_EFFECT;
|
||||
}
|
||||
|
||||
static u32 TrySetMicleBerry(u32 battler, u32 itemId, enum ItemEffect caseID)
|
||||
static enum ItemEffect TrySetMicleBerry(u32 battler, u32 itemId, enum ItemCaseId caseID)
|
||||
{
|
||||
if (HasEnoughHpToEatBerry(battler, 4, itemId))
|
||||
{
|
||||
@ -7069,10 +7057,10 @@ static u32 TrySetMicleBerry(u32 battler, u32 itemId, enum ItemEffect caseID)
|
||||
}
|
||||
return ITEM_EFFECT_OTHER;
|
||||
}
|
||||
return 0;
|
||||
return ITEM_NO_EFFECT;
|
||||
}
|
||||
|
||||
static u8 TrySetEnigmaBerry(u32 battler)
|
||||
static enum ItemEffect TrySetEnigmaBerry(u32 battler)
|
||||
{
|
||||
if (IsBattlerAlive(battler)
|
||||
&& !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove)
|
||||
@ -7089,10 +7077,10 @@ static u8 TrySetEnigmaBerry(u32 battler)
|
||||
gBattlescriptCurrInstr = BattleScript_ItemHealHP_RemoveItemRet;
|
||||
return ITEM_HP_CHANGE;
|
||||
}
|
||||
return 0;
|
||||
return ITEM_NO_EFFECT;
|
||||
}
|
||||
|
||||
static u8 DamagedStatBoostBerryEffect(u32 battler, u8 statId, u8 category)
|
||||
static enum ItemEffect DamagedStatBoostBerryEffect(u32 battler, u8 statId, u8 category)
|
||||
{
|
||||
if (IsBattlerAlive(battler)
|
||||
&& CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)
|
||||
@ -7118,10 +7106,10 @@ static u8 DamagedStatBoostBerryEffect(u32 battler, u8 statId, u8 category)
|
||||
gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet;
|
||||
return ITEM_STATS_CHANGE;
|
||||
}
|
||||
return 0;
|
||||
return ITEM_NO_EFFECT;
|
||||
}
|
||||
|
||||
u32 TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum ItemEffect caseID)
|
||||
enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum ItemCaseId caseID)
|
||||
{
|
||||
if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
@ -7131,7 +7119,7 @@ u32 TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum Ite
|
||||
SET_STATCHANGER(statId, 1, FALSE);
|
||||
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL)
|
||||
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN)
|
||||
{
|
||||
BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
|
||||
}
|
||||
@ -7142,10 +7130,33 @@ u32 TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum Ite
|
||||
}
|
||||
return ITEM_STATS_CHANGE;
|
||||
}
|
||||
return 0;
|
||||
return ITEM_NO_EFFECT;
|
||||
}
|
||||
|
||||
static u32 ItemRestorePp(u32 battler, u32 itemId, enum ItemEffect caseID)
|
||||
static enum ItemEffect TryEjectPack(u32 battler, enum ItemCaseId caseID)
|
||||
{
|
||||
if (gProtectStructs[battler].statFell
|
||||
&& !gProtectStructs[battler].disableEjectPack
|
||||
&& CountUsablePartyMons(battler) > 0
|
||||
&& !(gCurrentMove == MOVE_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker))) // Does not activate if attacker used Parting Shot and can switch out
|
||||
{
|
||||
gProtectStructs[battler].statFell = FALSE;
|
||||
gBattleScripting.battler = battler;
|
||||
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN)
|
||||
{
|
||||
BattleScriptExecute(BattleScript_EjectPackActivate_End2);
|
||||
}
|
||||
else
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_EjectPackActivate_Ret;
|
||||
}
|
||||
return ITEM_STATS_CHANGE;
|
||||
}
|
||||
return ITEM_NO_EFFECT;
|
||||
}
|
||||
|
||||
static u32 ItemRestorePp(u32 battler, u32 itemId, enum ItemCaseId caseID)
|
||||
{
|
||||
struct Pokemon *party = GetBattlerParty(battler);
|
||||
struct Pokemon *mon = &party[gBattlerPartyIndexes[battler]];
|
||||
@ -7192,7 +7203,7 @@ static u32 ItemRestorePp(u32 battler, u32 itemId, enum ItemEffect caseID)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 ItemHealHp(u32 battler, u32 itemId, enum ItemEffect caseID, bool32 percentHeal)
|
||||
static u32 ItemHealHp(u32 battler, u32 itemId, enum ItemCaseId caseID, bool32 percentHeal)
|
||||
{
|
||||
if (!(gBattleScripting.overrideBerryRequirements && gBattleMons[battler].hp == gBattleMons[battler].maxHP)
|
||||
&& (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))
|
||||
@ -7288,7 +7299,7 @@ static bool32 GetMentalHerbEffect(u32 battler)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 TryConsumeMirrorHerb(u32 battler, enum ItemEffect caseID)
|
||||
static u32 TryConsumeMirrorHerb(u32 battler, enum ItemCaseId caseID)
|
||||
{
|
||||
u32 effect = 0;
|
||||
|
||||
@ -7313,12 +7324,12 @@ static u32 TryConsumeMirrorHerb(u32 battler, enum ItemEffect caseID)
|
||||
return effect;
|
||||
}
|
||||
|
||||
static inline u32 TryBoosterEnergy(u32 battler, enum ItemEffect caseID)
|
||||
static inline u32 TryBoosterEnergy(u32 battler, enum ItemCaseId caseID)
|
||||
{
|
||||
if (gDisableStructs[battler].boosterEnergyActivates || gBattleMons[battler].status2 & STATUS2_TRANSFORMED)
|
||||
return ITEM_NO_EFFECT;
|
||||
|
||||
if (((GetBattlerAbility(battler) == ABILITY_PROTOSYNTHESIS) && !((gBattleWeather & B_WEATHER_SUN) && WEATHER_HAS_EFFECT))
|
||||
if (((GetBattlerAbility(battler) == ABILITY_PROTOSYNTHESIS) && !((gBattleWeather & B_WEATHER_SUN) && HasWeatherEffect()))
|
||||
|| ((GetBattlerAbility(battler) == ABILITY_QUARK_DRIVE) && !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN)))
|
||||
{
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler));
|
||||
@ -7579,7 +7590,7 @@ static u8 ItemEffectMoveEnd(u32 battler, u16 holdEffect)
|
||||
return effect;
|
||||
}
|
||||
|
||||
static inline bool32 TryCureStatus(u32 battler, enum ItemEffect caseId)
|
||||
static inline bool32 TryCureStatus(u32 battler, enum ItemCaseId caseId)
|
||||
{
|
||||
u32 effect = ITEM_NO_EFFECT;
|
||||
u32 string = 0;
|
||||
@ -7639,10 +7650,10 @@ static inline bool32 TryCureStatus(u32 battler, enum ItemEffect caseId)
|
||||
return effect;
|
||||
}
|
||||
|
||||
u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
|
||||
u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn)
|
||||
{
|
||||
u32 moveType = 0;
|
||||
u32 effect = ITEM_NO_EFFECT;
|
||||
enum ItemEffect effect = ITEM_NO_EFFECT;
|
||||
u32 battlerHoldEffect = 0, atkHoldEffect = 0;
|
||||
u32 atkHoldEffectParam = 0;
|
||||
u32 atkItem = 0;
|
||||
@ -7840,24 +7851,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
|
||||
}
|
||||
break;
|
||||
case HOLD_EFFECT_EJECT_PACK:
|
||||
if (gProtectStructs[battler].statFell
|
||||
&& gProtectStructs[battler].disableEjectPack == 0
|
||||
&& CountUsablePartyMons(battler) > 0
|
||||
&& !(gCurrentMove == MOVE_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker))) // Does not activate if attacker used Parting Shot and can switch out
|
||||
{
|
||||
gProtectStructs[battler].statFell = FALSE;
|
||||
gBattleScripting.battler = battler;
|
||||
effect = ITEM_STATS_CHANGE;
|
||||
if (moveTurn)
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_EjectPackActivate_Ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
BattleScriptExecute(BattleScript_EjectPackActivate_End2);
|
||||
}
|
||||
}
|
||||
effect = TryEjectPack(battler, caseID);
|
||||
break;
|
||||
case HOLD_EFFECT_BERSERK_GENE:
|
||||
BufferStatChange(battler, STAT_ATK, STRINGID_STATROSE);
|
||||
@ -7885,12 +7879,10 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
|
||||
{
|
||||
gSpecialStatuses[battler].switchInItemDone = TRUE;
|
||||
gBattlerAttacker = gPotentialItemEffectBattler = gBattleScripting.battler = battler;
|
||||
switch (effect)
|
||||
if (effect == ITEM_STATUS_CHANGE)
|
||||
{
|
||||
case ITEM_STATUS_CHANGE:
|
||||
BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8102,12 +8094,10 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
|
||||
if (effect != 0)
|
||||
{
|
||||
gBattlerAttacker = gPotentialItemEffectBattler = gBattleScripting.battler = battler;
|
||||
switch (effect)
|
||||
if (effect == ITEM_STATUS_CHANGE)
|
||||
{
|
||||
case ITEM_STATUS_CHANGE:
|
||||
BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8466,16 +8456,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
|
||||
}
|
||||
break;
|
||||
case HOLD_EFFECT_EJECT_PACK:
|
||||
if (gProtectStructs[battler].statFell
|
||||
&& gProtectStructs[battler].disableEjectPack == 0
|
||||
&& CountUsablePartyMons(battler) > 0)
|
||||
{
|
||||
gBattleScripting.battler = battler;
|
||||
gPotentialItemEffectBattler = battler;
|
||||
effect = ITEM_STATS_CHANGE;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_EjectPackActivates;
|
||||
}
|
||||
effect = TryEjectPack(battler, ITEMEFFECT_ON_SWITCH_IN);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -8611,7 +8592,7 @@ u32 GetBattleMoveTarget(u16 move, u8 setTarget)
|
||||
break;
|
||||
}
|
||||
|
||||
*(gBattleStruct->moveTarget + gBattlerAttacker) = targetBattler;
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = targetBattler;
|
||||
|
||||
return targetBattler;
|
||||
}
|
||||
@ -9574,7 +9555,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageCalculationData *
|
||||
case ABILITY_PROTOSYNTHESIS:
|
||||
{
|
||||
u8 defHighestStat = GetHighestStatId(battlerDef);
|
||||
if (((weather & B_WEATHER_SUN && WEATHER_HAS_EFFECT) || gDisableStructs[battlerDef].boosterEnergyActivates)
|
||||
if (((weather & B_WEATHER_SUN && HasWeatherEffect()) || gDisableStructs[battlerDef].boosterEnergyActivates)
|
||||
&& ((IsBattleMovePhysical(move) && defHighestStat == STAT_DEF) || (IsBattleMoveSpecial(move) && defHighestStat == STAT_SPDEF))
|
||||
&& !(gBattleMons[battlerDef].status2 & STATUS2_TRANSFORMED))
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(0.7));
|
||||
@ -9856,7 +9837,7 @@ static inline u32 CalcAttackStat(struct DamageCalculationData *damageCalcData, u
|
||||
if (!(gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED))
|
||||
{
|
||||
u32 atkHighestStat = GetHighestStatId(battlerAtk);
|
||||
if (((weather & B_WEATHER_SUN) && WEATHER_HAS_EFFECT) || gDisableStructs[battlerAtk].boosterEnergyActivates)
|
||||
if (((weather & B_WEATHER_SUN) && HasWeatherEffect()) || gDisableStructs[battlerAtk].boosterEnergyActivates)
|
||||
{
|
||||
if ((IsBattleMovePhysical(move) && atkHighestStat == STAT_ATK) || (IsBattleMoveSpecial(move) && atkHighestStat == STAT_SPATK))
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(1.3));
|
||||
@ -9875,7 +9856,7 @@ static inline u32 CalcAttackStat(struct DamageCalculationData *damageCalcData, u
|
||||
}
|
||||
break;
|
||||
case ABILITY_ORICHALCUM_PULSE:
|
||||
if ((weather & B_WEATHER_SUN) && WEATHER_HAS_EFFECT && IsBattleMovePhysical(move))
|
||||
if ((weather & B_WEATHER_SUN) && HasWeatherEffect() && IsBattleMovePhysical(move))
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(1.3333));
|
||||
break;
|
||||
case ABILITY_HADRON_ENGINE:
|
||||
@ -10570,7 +10551,7 @@ static inline s32 DoFutureSightAttackDamageCalc(struct DamageCalculationData *da
|
||||
|
||||
static u32 GetWeather(void)
|
||||
{
|
||||
if (gBattleWeather == B_WEATHER_NONE || !WEATHER_HAS_EFFECT)
|
||||
if (gBattleWeather == B_WEATHER_NONE || !HasWeatherEffect())
|
||||
return B_WEATHER_NONE;
|
||||
else
|
||||
return gBattleWeather;
|
||||
@ -10643,7 +10624,7 @@ static inline void MulByTypeEffectiveness(uq4_12_t *modifier, u32 move, u32 move
|
||||
mod = UQ_4_12(2.0);
|
||||
|
||||
// B_WEATHER_STRONG_WINDS weakens Super Effective moves against Flying-type Pokémon
|
||||
if (gBattleWeather & B_WEATHER_STRONG_WINDS && WEATHER_HAS_EFFECT)
|
||||
if (gBattleWeather & B_WEATHER_STRONG_WINDS && HasWeatherEffect())
|
||||
{
|
||||
if (defType == TYPE_FLYING && mod >= UQ_4_12(2.0))
|
||||
mod = UQ_4_12(1.0);
|
||||
@ -10758,9 +10739,8 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(u32 move, u32 mov
|
||||
}
|
||||
}
|
||||
|
||||
// Signal for the trainer slide-in system.
|
||||
if (GetBattlerSide(battlerDef) != B_SIDE_PLAYER && modifier && gBattleStruct->trainerSlideFirstSTABMoveMsgState != 2)
|
||||
gBattleStruct->trainerSlideFirstSTABMoveMsgState = 1;
|
||||
if (recordAbilities)
|
||||
TryInitalizeFirstSTABMoveTrainerSlide(battlerDef, battlerAtk, moveType);
|
||||
|
||||
return modifier;
|
||||
}
|
||||
@ -11124,13 +11104,13 @@ u16 GetBattleFormChangeTargetSpecies(u32 battler, u16 method)
|
||||
targetSpecies = formChanges[i].targetSpecies;
|
||||
}
|
||||
// We need to revert the weather form if the field is under Air Lock, too.
|
||||
else if (!WEATHER_HAS_EFFECT && formChanges[i].param1 == B_WEATHER_NONE)
|
||||
else if (!HasWeatherEffect() && formChanges[i].param1 == B_WEATHER_NONE)
|
||||
{
|
||||
targetSpecies = formChanges[i].targetSpecies;
|
||||
}
|
||||
// Otherwise, just check for a match between the weather and the form change table.
|
||||
// Added a check for whether the weather is in effect to prevent end-of-turn soft locks with Cloud Nine / Air Lock
|
||||
else if (((gBattleWeather & formChanges[i].param1) && WEATHER_HAS_EFFECT)
|
||||
else if (((gBattleWeather & formChanges[i].param1) && HasWeatherEffect())
|
||||
|| (gBattleWeather == B_WEATHER_NONE && formChanges[i].param1 == B_WEATHER_NONE))
|
||||
{
|
||||
targetSpecies = formChanges[i].targetSpecies;
|
||||
@ -11753,7 +11733,7 @@ bool32 PickupHasValidTarget(u32 battler)
|
||||
|
||||
bool32 IsBattlerWeatherAffected(u32 battler, u32 weatherFlags)
|
||||
{
|
||||
if (gBattleWeather & weatherFlags && WEATHER_HAS_EFFECT)
|
||||
if (gBattleWeather & weatherFlags && HasWeatherEffect())
|
||||
{
|
||||
// given weather is active -> check if its sun, rain against utility umbrella ( since only 1 weather can be active at once)
|
||||
if (gBattleWeather & (B_WEATHER_SUN | B_WEATHER_RAIN) && GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_UTILITY_UMBRELLA)
|
||||
@ -12302,3 +12282,10 @@ void ClearPursuitValuesIfSet(u32 battler)
|
||||
if (gBattleStruct->battlerState[battler].pursuitTarget)
|
||||
ClearPursuitValues();
|
||||
}
|
||||
|
||||
bool32 HasWeatherEffect(void)
|
||||
{
|
||||
if (IsAbilityOnField(ABILITY_CLOUD_NINE) || IsAbilityOnField(ABILITY_AIR_LOCK))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1126,68 +1126,84 @@ static void CB2_LoadBerryBlender(void)
|
||||
UpdatePaletteFade();
|
||||
}
|
||||
|
||||
#define sTargetY data[0]
|
||||
#define sX data[1]
|
||||
#define sY data[2]
|
||||
#define sBounceSpeed data[3]
|
||||
#define sYUpSpeed data[4]
|
||||
#define sBounces data[5]
|
||||
#define sXSpeed data[6]
|
||||
#define sYDownSpeed data[7]
|
||||
// Because of changing how Berry sprites are generated, we have to leave data[6] and data[7] untouched as it has an allocated memory ptr for berry's gfx.
|
||||
struct BerrySpriteData
|
||||
{
|
||||
s16 sTargetY; // data0
|
||||
s16 sX; // data1
|
||||
s16 sY; // data2
|
||||
|
||||
s8 sBounceSpeed; // data3
|
||||
u8 berryId; // data3
|
||||
|
||||
s8 sYUpSpeed; // data4
|
||||
s8 sBounces; // data4
|
||||
|
||||
s8 sXSpeed; // data5
|
||||
s8 sYDownSpeed; // data5
|
||||
};
|
||||
|
||||
static inline struct BerrySpriteData *GetBerrySpriteDataAsStructPtr(struct Sprite *sprite)
|
||||
{
|
||||
return (void *)(&sprite->data[0]);
|
||||
}
|
||||
|
||||
// For throwing berries into the machine
|
||||
static void SpriteCB_Berry(struct Sprite *sprite)
|
||||
{
|
||||
sprite->sX += sprite->sXSpeed;
|
||||
sprite->sY -= sprite->sYUpSpeed;
|
||||
sprite->sY += sprite->sYDownSpeed;
|
||||
sprite->sTargetY += sprite->sYDownSpeed;
|
||||
sprite->sYUpSpeed--;
|
||||
struct BerrySpriteData *spriteData = GetBerrySpriteDataAsStructPtr(sprite);
|
||||
|
||||
if (sprite->sTargetY < sprite->sY)
|
||||
spriteData->sX += spriteData->sXSpeed;
|
||||
spriteData->sY -= spriteData->sYUpSpeed;
|
||||
spriteData->sY += spriteData->sYDownSpeed;
|
||||
spriteData->sTargetY += spriteData->sYDownSpeed;
|
||||
spriteData->sYUpSpeed--;
|
||||
|
||||
if (spriteData->sTargetY < spriteData->sY)
|
||||
{
|
||||
sprite->sBounceSpeed = sprite->sYUpSpeed = sprite->sBounceSpeed - 1;
|
||||
spriteData->sBounceSpeed = spriteData->sYUpSpeed = spriteData->sBounceSpeed - 1;
|
||||
|
||||
if (++sprite->sBounces > 3)
|
||||
DestroySprite(sprite);
|
||||
if (++spriteData->sBounces > 3)
|
||||
{
|
||||
DestroyBerryIconSpritePtr(sprite, spriteData->berryId, TRUE);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlaySE(SE_BALL_TRAY_EXIT);
|
||||
}
|
||||
}
|
||||
sprite->x = sprite->sX;
|
||||
sprite->y = sprite->sY;
|
||||
sprite->x = spriteData->sX;
|
||||
sprite->y = spriteData->sY;
|
||||
}
|
||||
|
||||
static void SetBerrySpriteData(struct Sprite *sprite, s16 x, s16 y, s16 bounceSpeed, s16 xSpeed, s16 ySpeed)
|
||||
static void SetBerrySpriteData(struct Sprite *sprite, s32 x, s32 y, s32 bounceSpeed, s32 xSpeed, s32 ySpeed, u32 berryId)
|
||||
{
|
||||
sprite->sTargetY = y;
|
||||
sprite->sX = x;
|
||||
sprite->sY = y;
|
||||
sprite->sBounceSpeed = bounceSpeed;
|
||||
sprite->sYUpSpeed = 10;
|
||||
sprite->sBounces = 0;
|
||||
sprite->sXSpeed = xSpeed;
|
||||
sprite->sYDownSpeed = ySpeed;
|
||||
struct BerrySpriteData *spriteData = GetBerrySpriteDataAsStructPtr(sprite);
|
||||
|
||||
spriteData->sTargetY = y;
|
||||
spriteData->sX = x;
|
||||
spriteData->sY = y;
|
||||
spriteData->sBounceSpeed = bounceSpeed;
|
||||
spriteData->sYUpSpeed = 10;
|
||||
spriteData->sBounces = 0;
|
||||
spriteData->sXSpeed = xSpeed;
|
||||
spriteData->sYDownSpeed = ySpeed;
|
||||
spriteData->berryId = berryId;
|
||||
sprite->callback = SpriteCB_Berry;
|
||||
}
|
||||
|
||||
#undef sTargetY
|
||||
#undef sX
|
||||
#undef sY
|
||||
#undef sBounceSpeed
|
||||
#undef sYUpSpeed
|
||||
#undef sBounces
|
||||
#undef sXSpeed
|
||||
#undef sYDownSpeed
|
||||
|
||||
static void CreateBerrySprite(u16 itemId, u8 playerId)
|
||||
static void CreateBerrySprite(u32 itemId, u32 playerId)
|
||||
{
|
||||
u8 spriteId = CreateSpinningBerrySprite(ITEM_TO_BERRY(itemId) - 1, 0, 80, playerId & 1);
|
||||
u32 berryId = ITEM_TO_BERRY(itemId) - 1;
|
||||
u32 spriteId = CreateSpinningBerrySprite(berryId, 0, 80, playerId & 1);
|
||||
SetBerrySpriteData(&gSprites[spriteId],
|
||||
sBerrySpriteData[playerId][0],
|
||||
sBerrySpriteData[playerId][1],
|
||||
sBerrySpriteData[playerId][2],
|
||||
sBerrySpriteData[playerId][3],
|
||||
sBerrySpriteData[playerId][4]);
|
||||
sBerrySpriteData[playerId][4],
|
||||
berryId);
|
||||
}
|
||||
|
||||
static void ConvertItemToBlenderBerry(struct BlenderBerry* berry, u16 itemId)
|
||||
@ -1676,13 +1692,14 @@ static void CB2_StartBlenderLocal(void)
|
||||
u32 playerId = sPlayerIdMap[sBerryBlender->numPlayers - 2][i];
|
||||
if (sBerryBlender->playerToThrowBerry == playerId)
|
||||
{
|
||||
CreateBerrySprite(sBerryBlender->chosenItemId[sBerryBlender->playerToThrowBerry], i);
|
||||
break;
|
||||
CreateBerrySprite(sBerryBlender->chosenItemId[sBerryBlender->playerToThrowBerry++], i);
|
||||
// If we're throwing all at once, continue the loop. If not, break out of the loop(vanilla behavior).
|
||||
if (!BERRY_BLENDER_THROW_ALL_BERRIES_AT_ONCE)
|
||||
break;
|
||||
}
|
||||
}
|
||||
sBerryBlender->framesToWait = 0;
|
||||
sBerryBlender->mainState++;
|
||||
sBerryBlender->playerToThrowBerry++;
|
||||
break;
|
||||
case 12:
|
||||
if (++sBerryBlender->framesToWait > 60)
|
||||
|
||||
10
src/berry_crush.c
Executable file → Normal file
@ -1941,12 +1941,10 @@ static void DrawPlayerNameWindows(struct BerryCrushGame *game)
|
||||
// Each player name window border uses a color that corresponds to a slot of the crusher lid
|
||||
static void CopyPlayerNameWindowGfxToBg(struct BerryCrushGame *game)
|
||||
{
|
||||
u8 i = 0;
|
||||
u8 *windowGfx;
|
||||
s32 i;
|
||||
u8 *windowGfx = malloc_and_decompress(gBerryCrush_TextWindows_Tilemap, NULL);
|
||||
|
||||
LZ77UnCompWram(gBerryCrush_TextWindows_Tilemap, gDecompressionBuffer);
|
||||
|
||||
for (windowGfx = gDecompressionBuffer; i < game->playerCount; i++)
|
||||
for (i = 0; i < game->playerCount; i++)
|
||||
{
|
||||
CopyToBgTilemapBufferRect(
|
||||
3,
|
||||
@ -1958,6 +1956,8 @@ static void CopyPlayerNameWindowGfxToBg(struct BerryCrushGame *game)
|
||||
);
|
||||
}
|
||||
CopyBgTilemapBufferToVram(3);
|
||||
|
||||
Free(windowGfx);
|
||||
}
|
||||
|
||||
static void CreateGameSprites(struct BerryCrushGame *game)
|
||||
|
||||
@ -43,6 +43,7 @@ struct BerryTagScreenStruct
|
||||
{
|
||||
u16 tilemapBuffers[3][0x400];
|
||||
u16 berryId;
|
||||
u16 currentSpriteBerryId;
|
||||
u8 berrySpriteId;
|
||||
u8 flavorCircleIds[FLAVOR_COUNT];
|
||||
u16 gfxState;
|
||||
@ -466,13 +467,13 @@ static void PrintBerryDescription2(void)
|
||||
|
||||
static void CreateBerrySprite(void)
|
||||
{
|
||||
sBerryTag->berrySpriteId = CreateBerryTagSprite(sBerryTag->berryId - 1, 56, 64);
|
||||
sBerryTag->currentSpriteBerryId = sBerryTag->berryId - 1;
|
||||
sBerryTag->berrySpriteId = CreateBerryTagSprite(sBerryTag->currentSpriteBerryId, 56, 64);
|
||||
}
|
||||
|
||||
static void DestroyBerrySprite(void)
|
||||
{
|
||||
DestroySprite(&gSprites[sBerryTag->berrySpriteId]);
|
||||
FreeBerryTagSpritePalette();
|
||||
DestroyBerryIconSprite(sBerryTag->berrySpriteId, sBerryTag->currentSpriteBerryId, TRUE);
|
||||
}
|
||||
|
||||
static void CreateFlavorCircleSprites(void)
|
||||
|
||||
12
src/bg.c
@ -3,6 +3,8 @@
|
||||
#include "bg.h"
|
||||
#include "dma3.h"
|
||||
#include "gpu_regs.h"
|
||||
#include "malloc.h"
|
||||
#include "menu.h"
|
||||
|
||||
#define DISPCNT_ALL_BG_AND_MODE_BITS (DISPCNT_BG_ALL_ON | 0x7)
|
||||
|
||||
@ -865,7 +867,7 @@ void *GetBgTilemapBuffer(u32 bg)
|
||||
return sGpuBgConfigs2[bg].tilemap;
|
||||
}
|
||||
|
||||
void CopyToBgTilemapBuffer(u32 bg, const void *src, u16 mode, u16 destOffset)
|
||||
void CopyToBgTilemapBuffer(u32 bg, const void *src, u32 mode, u32 destOffset)
|
||||
{
|
||||
if (!IsInvalidBg(bg) && !IsTileMapOutsideWram(bg))
|
||||
{
|
||||
@ -876,6 +878,14 @@ void CopyToBgTilemapBuffer(u32 bg, const void *src, u16 mode, u16 destOffset)
|
||||
}
|
||||
}
|
||||
|
||||
void DecompressAndCopyToBgTilemapBuffer(u32 bg, const u32 *src, u32 mode, u32 destOffset)
|
||||
{
|
||||
void *buffer = malloc_and_decompress(src, NULL);
|
||||
|
||||
CopyToBgTilemapBuffer(bg, buffer, mode, destOffset);
|
||||
Free(buffer);
|
||||
}
|
||||
|
||||
void CopyBgTilemapBufferToVram(u32 bg)
|
||||
{
|
||||
u16 sizeToLoad;
|
||||
|
||||
@ -21,8 +21,7 @@ static void Task_LinkContest_InitFlags(u8);
|
||||
|
||||
bool32 LinkContest_SendBlock(void *src, u16 size)
|
||||
{
|
||||
memcpy(gDecompressionBuffer, src, size);
|
||||
if (SendBlock(BitmaskAllOtherLinkPlayers(), gDecompressionBuffer, size))
|
||||
if (SendBlock(BitmaskAllOtherLinkPlayers(), src, size))
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
@ -270,16 +270,6 @@ static const union AnimCmd *const sAnims_Rival[] =
|
||||
sAnim_Rival_Still,
|
||||
};
|
||||
|
||||
#define MONBG_OFFSET (MON_PIC_SIZE * 3)
|
||||
static const struct SpriteSheet sSpriteSheet_MonBg[] = {
|
||||
{ gDecompressionBuffer, MONBG_OFFSET, TAG_MON_BG },
|
||||
{},
|
||||
};
|
||||
static const struct SpritePalette sSpritePalette_MonBg[] = {
|
||||
{ (const u16 *)&gDecompressionBuffer[MONBG_OFFSET], TAG_MON_BG },
|
||||
{},
|
||||
};
|
||||
|
||||
static const struct OamData sOamData_MonBg =
|
||||
{
|
||||
.y = DISPLAY_HEIGHT,
|
||||
@ -529,6 +519,8 @@ static void Task_ReadyShowMons(u8 taskId)
|
||||
}
|
||||
}
|
||||
|
||||
#define MONBG_OFFSET (MON_PIC_SIZE * 3)
|
||||
|
||||
static void Task_LoadShowMons(u8 taskId)
|
||||
{
|
||||
switch (gMain.state)
|
||||
@ -536,8 +528,11 @@ static void Task_LoadShowMons(u8 taskId)
|
||||
default:
|
||||
case 0:
|
||||
{
|
||||
u16 i;
|
||||
s32 i;
|
||||
u16 *temp;
|
||||
u8 *buffer = Alloc(MONBG_OFFSET + PLTT_SIZEOF(16));
|
||||
struct SpriteSheet bgSheet = { buffer, MONBG_OFFSET, TAG_MON_BG };
|
||||
struct SpritePalette bgPalette = { (u16 *) &buffer[MONBG_OFFSET], TAG_MON_BG };
|
||||
|
||||
ResetSpriteData();
|
||||
ResetAllPicSprites();
|
||||
@ -548,20 +543,22 @@ static void Task_LoadShowMons(u8 taskId)
|
||||
LoadPalette(gBirchBagGrass_Pal + 1, BG_PLTT_ID(0) + 1, PLTT_SIZEOF(2 * 16 - 1));
|
||||
|
||||
for (i = 0; i < MON_PIC_SIZE; i++)
|
||||
gDecompressionBuffer[i] = 0x11;
|
||||
for (i = 0; i < MON_PIC_SIZE; i++)
|
||||
(gDecompressionBuffer + MON_PIC_SIZE)[i] = 0x22;
|
||||
for (i = 0; i < MON_PIC_SIZE; i++)
|
||||
(gDecompressionBuffer + MON_PIC_SIZE * 2)[i] = 0x33;
|
||||
{
|
||||
buffer[i] = 0x11;
|
||||
(buffer + MON_PIC_SIZE)[i] = 0x22;
|
||||
(buffer + MON_PIC_SIZE * 2)[i] = 0x33;
|
||||
}
|
||||
|
||||
temp = (u16 *)(&gDecompressionBuffer[MONBG_OFFSET]);
|
||||
temp = (u16 *)(&buffer[MONBG_OFFSET]);
|
||||
temp[0] = RGB_BLACK;
|
||||
temp[1] = RGB(31, 31, 20); // light yellow
|
||||
temp[2] = RGB(31, 20, 20); // light red
|
||||
temp[3] = RGB(20, 20, 31); // light blue
|
||||
|
||||
LoadSpriteSheet(sSpriteSheet_MonBg);
|
||||
LoadSpritePalette(sSpritePalette_MonBg);
|
||||
LoadSpriteSheet(&bgSheet);
|
||||
LoadSpritePalette(&bgPalette);
|
||||
|
||||
Free(buffer);
|
||||
|
||||
gMain.state++;
|
||||
break;
|
||||
|
||||
@ -2240,4 +2240,10 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
|
||||
.battleScript = BattleScript_EffectHit,
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
|
||||
[EFFECT_RAPID_SPIN] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectHit,
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
};
|
||||
|
||||
@ -7696,7 +7696,7 @@ const u32 gObjectEventPic_Substitute[] = INCBIN_COMP("graphics/pokemon/question_
|
||||
#endif //OW_PKMN_OBJECTS_SHARE_PALETTES
|
||||
#endif //OW_POKEMON_OBJECT_EVENTS
|
||||
|
||||
const u32 gMonFrontPic_Clodsire[] = INCBIN_U32("graphics/pokemon/clodsire/front.4bpp.lz");
|
||||
const u32 gMonFrontPic_Clodsire[] = INCBIN_U32("graphics/pokemon/clodsire/anim_front.4bpp.lz");
|
||||
const u32 gMonPalette_Clodsire[] = INCBIN_U32("graphics/pokemon/clodsire/normal.gbapal.lz");
|
||||
const u32 gMonBackPic_Clodsire[] = INCBIN_U32("graphics/pokemon/clodsire/back.4bpp.lz");
|
||||
const u32 gMonShinyPalette_Clodsire[] = INCBIN_U32("graphics/pokemon/clodsire/shiny.gbapal.lz");
|
||||
|
||||
@ -5806,7 +5806,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
|
||||
.description = COMPOUND_STRING(
|
||||
"Spins the body at high\n"
|
||||
"speed to strike the foe."),
|
||||
.effect = EFFECT_HIT,
|
||||
.effect = EFFECT_RAPID_SPIN,
|
||||
.power = B_UPDATED_MOVE_DATA >= GEN_8 ? 50 : 20,
|
||||
.type = TYPE_NORMAL,
|
||||
.accuracy = 100,
|
||||
@ -5815,12 +5815,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
|
||||
.priority = 0,
|
||||
.category = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.makesContact = TRUE,
|
||||
.additionalEffects = ADDITIONAL_EFFECTS({
|
||||
.moveEffect = MOVE_EFFECT_RAPID_SPIN,
|
||||
.self = TRUE,
|
||||
}
|
||||
.additionalEffects = ADDITIONAL_EFFECTS(
|
||||
#if B_SPEED_BUFFING_RAPID_SPIN >= GEN_8
|
||||
,{
|
||||
{
|
||||
.moveEffect = MOVE_EFFECT_SPD_PLUS_1,
|
||||
.self = TRUE,
|
||||
.chance = 100,
|
||||
@ -19571,7 +19568,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
|
||||
.description = COMPOUND_STRING(
|
||||
"Erases trap moves and Leech\n"
|
||||
"Seed. Poisons adjacent foes."),
|
||||
.effect = EFFECT_HIT,
|
||||
.effect = EFFECT_RAPID_SPIN,
|
||||
.power = 30,
|
||||
.type = TYPE_POISON,
|
||||
.accuracy = 100,
|
||||
@ -19580,10 +19577,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
|
||||
.priority = 0,
|
||||
.category = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.makesContact = TRUE,
|
||||
.additionalEffects = ADDITIONAL_EFFECTS({
|
||||
.moveEffect = MOVE_EFFECT_RAPID_SPIN,
|
||||
.self = TRUE,
|
||||
},
|
||||
.additionalEffects = ADDITIONAL_EFFECTS(
|
||||
{
|
||||
.moveEffect = MOVE_EFFECT_POISON,
|
||||
.chance = 100,
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
#include "constants/abilities.h"
|
||||
#include "species_info/shared_dex_text.h"
|
||||
#include "species_info/shared_front_pic_anims.h"
|
||||
|
||||
// Macros for ease of use.
|
||||
|
||||
#define EVOLUTION(...) (const struct Evolution[]) { __VA_ARGS__, { EVOLUTIONS_END }, }
|
||||
|
||||
#define ANIM_FRAMES(...) (const union AnimCmd *const[]) { sAnim_GeneralFrame0, (const union AnimCmd[]) { __VA_ARGS__ ANIMCMD_END, }, }
|
||||
|
||||
#if P_FOOTPRINTS
|
||||
#define FOOTPRINT(sprite) .footprint = gMonFootprint_## sprite,
|
||||
#else
|
||||
@ -42,77 +45,41 @@
|
||||
#define OVERWORLD_PAL_FEMALE(...)
|
||||
#endif //OW_PKMN_OBJECTS_SHARE_PALETTES == FALSE
|
||||
|
||||
#define OVERWORLD(picTable, _size, shadow, _tracks, ...) \
|
||||
.overworldData = { \
|
||||
.tileTag = TAG_NONE, \
|
||||
.paletteTag = OBJ_EVENT_PAL_TAG_DYNAMIC, \
|
||||
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, \
|
||||
.size = (_size == SIZE_32x32 ? 512 : 2048), \
|
||||
.width = (_size == SIZE_32x32 ? 32 : 64), \
|
||||
.height = (_size == SIZE_32x32 ? 32 : 64), \
|
||||
.paletteSlot = PALSLOT_NPC_1, \
|
||||
.shadowSize = shadow, \
|
||||
.inanimate = FALSE, \
|
||||
.compressed = COMP, \
|
||||
.tracks = _tracks, \
|
||||
.oam = (_size == SIZE_32x32 ? &gObjectEventBaseOam_32x32 : &gObjectEventBaseOam_64x64), \
|
||||
.subspriteTables = (_size == SIZE_32x32 ? sOamTables_32x32 : sOamTables_64x64), \
|
||||
.anims = sAnimTable_Following, \
|
||||
.images = picTable, \
|
||||
.affineAnims = gDummySpriteAffineAnimTable, \
|
||||
}, \
|
||||
OVERWORLD_PAL(__VA_ARGS__)
|
||||
#define OVERWORLD_DATA(objEventPic, _size, shadow, _tracks, _anims) \
|
||||
{ \
|
||||
.tileTag = TAG_NONE, \
|
||||
.paletteTag = OBJ_EVENT_PAL_TAG_DYNAMIC, \
|
||||
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, \
|
||||
.size = (_size == SIZE_32x32 ? 512 : 2048), \
|
||||
.width = (_size == SIZE_32x32 ? 32 : 64), \
|
||||
.height = (_size == SIZE_32x32 ? 32 : 64), \
|
||||
.paletteSlot = PALSLOT_NPC_1, \
|
||||
.shadowSize = shadow, \
|
||||
.inanimate = FALSE, \
|
||||
.compressed = COMP, \
|
||||
.tracks = _tracks, \
|
||||
.oam = (_size == SIZE_32x32 ? &gObjectEventBaseOam_32x32 : &gObjectEventBaseOam_64x64), \
|
||||
.subspriteTables = (_size == SIZE_32x32 ? sOamTables_32x32 : sOamTables_64x64), \
|
||||
.anims = _anims, \
|
||||
.images = (const struct SpriteFrameImage[]) { overworld_ascending_frames(objEventPic, SIZE_32x32 ? 4 : 8, SIZE_32x32 ? 4 : 8), }, \
|
||||
.affineAnims = gDummySpriteAffineAnimTable, \
|
||||
}
|
||||
|
||||
#define OVERWORLD_SET_ANIM(picTable, _size, shadow, _tracks, _anims, ...) \
|
||||
.overworldData = { \
|
||||
.tileTag = TAG_NONE, \
|
||||
.paletteTag = OBJ_EVENT_PAL_TAG_DYNAMIC, \
|
||||
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, \
|
||||
.size = (_size == SIZE_32x32 ? 512 : 2048), \
|
||||
.width = (_size == SIZE_32x32 ? 32 : 64), \
|
||||
.height = (_size == SIZE_32x32 ? 32 : 64), \
|
||||
.paletteSlot = PALSLOT_NPC_1, \
|
||||
.shadowSize = shadow, \
|
||||
.inanimate = FALSE, \
|
||||
.compressed = COMP, \
|
||||
.tracks = _tracks, \
|
||||
.oam = (_size == SIZE_32x32 ? &gObjectEventBaseOam_32x32 : &gObjectEventBaseOam_64x64), \
|
||||
.subspriteTables = (_size == SIZE_32x32 ? sOamTables_32x32 : sOamTables_64x64), \
|
||||
.anims = _anims, \
|
||||
.images = picTable, \
|
||||
.affineAnims = gDummySpriteAffineAnimTable, \
|
||||
}, \
|
||||
#define OVERWORLD(objEventPic, _size, shadow, _tracks, _anims, ...) \
|
||||
.overworldData = OVERWORLD_DATA(objEventPic, _size, shadow, _tracks, _anims), \
|
||||
OVERWORLD_PAL(__VA_ARGS__)
|
||||
|
||||
#if P_GENDER_DIFFERENCES
|
||||
#define OVERWORLD_FEMALE(picTable, _size, shadow, _tracks, ...) \
|
||||
.overworldDataFemale = { \
|
||||
.tileTag = TAG_NONE, \
|
||||
.paletteTag = OBJ_EVENT_PAL_TAG_DYNAMIC, \
|
||||
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE, \
|
||||
.size = (_size == SIZE_32x32 ? 512 : 2048), \
|
||||
.width = (_size == SIZE_32x32 ? 32 : 64), \
|
||||
.height = (_size == SIZE_32x32 ? 32 : 64), \
|
||||
.paletteSlot = PALSLOT_NPC_1, \
|
||||
.shadowSize = shadow, \
|
||||
.inanimate = FALSE, \
|
||||
.compressed = COMP, \
|
||||
.tracks = _tracks, \
|
||||
.oam = (_size == SIZE_32x32 ? &gObjectEventBaseOam_32x32 : &gObjectEventBaseOam_64x64), \
|
||||
.subspriteTables = (_size == SIZE_32x32 ? sOamTables_32x32 : sOamTables_64x64), \
|
||||
.anims = sAnimTable_Following, \
|
||||
.images = picTable, \
|
||||
.affineAnims = gDummySpriteAffineAnimTable, \
|
||||
}, \
|
||||
#define OVERWORLD_FEMALE(objEventPic, _size, shadow, _tracks, _anims, ...) \
|
||||
.overworldDataFemale = OVERWORLD_DATA(objEventPic, _size, shadow, _tracks, _anims), \
|
||||
OVERWORLD_PAL_FEMALE(__VA_ARGS__)
|
||||
#else
|
||||
#define OVERWORLD_FEMALE(picTable, _size, shadow, _tracks, ...)
|
||||
#define OVERWORLD_FEMALE(...)
|
||||
#endif //P_GENDER_DIFFERENCES
|
||||
|
||||
#else
|
||||
#define OVERWORLD(picTable, _size, shadow, _tracks, ...)
|
||||
#define OVERWORLD_SET_ANIM(picTable, _size, shadow, _tracks, _anims, ...)
|
||||
#define OVERWORLD_FEMALE(picTable, _size, shadow, _tracks, ...)
|
||||
#define OVERWORLD(...)
|
||||
#define OVERWORLD_FEMALE(...)
|
||||
#define OVERWORLD_PAL(...)
|
||||
#define OVERWORLD_PAL_FEMALE(...)
|
||||
#endif //OW_POKEMON_OBJECT_EVENTS
|
||||
@ -145,7 +112,7 @@ const struct SpeciesInfo gSpeciesInfo[] =
|
||||
.frontPic = gMonFrontPic_CircledQuestionMark,
|
||||
.frontPicSize = MON_COORDS_SIZE(40, 40),
|
||||
.frontPicYOffset = 12,
|
||||
.frontAnimFrames = sAnims_None,
|
||||
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
|
||||
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
|
||||
.backPic = gMonBackPic_CircledQuestionMark,
|
||||
.backPicSize = MON_COORDS_SIZE(40, 40),
|
||||
@ -172,7 +139,7 @@ const struct SpeciesInfo gSpeciesInfo[] =
|
||||
.oam = &gObjectEventBaseOam_32x32,
|
||||
.subspriteTables = sOamTables_32x32,
|
||||
.anims = sAnimTable_Following,
|
||||
.images = sPicTable_Substitute,
|
||||
.images = (const struct SpriteFrameImage[]) { overworld_ascending_frames(gObjectEventPic_Substitute, 4, 4), },
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
},
|
||||
#endif
|
||||
|
||||
448
src/data/pokemon/species_info/shared_front_pic_anims.h
Normal file
@ -0,0 +1,448 @@
|
||||
static const union AnimCmd *const sAnims_SingleFramePlaceHolder[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 1),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
|
||||
static const union AnimCmd *const sAnims_TwoFramePlaceHolder[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 30),
|
||||
ANIMCMD_FRAME(1, 30),
|
||||
ANIMCMD_FRAME(0, 1),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
|
||||
#if P_FAMILY_BURMY
|
||||
static const union AnimCmd *const sAnims_Burmy[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(1, 32),
|
||||
ANIMCMD_FRAME(0, 20),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
|
||||
static const union AnimCmd *const sAnims_Wormadam[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 10),
|
||||
ANIMCMD_FRAME(1, 10),
|
||||
ANIMCMD_FRAME(0, 10),
|
||||
ANIMCMD_FRAME(1, 10),
|
||||
ANIMCMD_FRAME(0, 10),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
|
||||
static const union AnimCmd *const sAnims_Mothim[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 4),
|
||||
ANIMCMD_FRAME(1, 4),
|
||||
ANIMCMD_FRAME(0, 6),
|
||||
ANIMCMD_FRAME(1, 6),
|
||||
ANIMCMD_FRAME(0, 5),
|
||||
ANIMCMD_FRAME(1, 5),
|
||||
ANIMCMD_FRAME(0, 25),
|
||||
ANIMCMD_FRAME(1, 6),
|
||||
ANIMCMD_FRAME(0, 6),
|
||||
ANIMCMD_FRAME(1, 4),
|
||||
ANIMCMD_FRAME(0, 4),
|
||||
ANIMCMD_FRAME(1, 5),
|
||||
ANIMCMD_FRAME(0, 5),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_BURMY
|
||||
|
||||
#if P_FAMILY_SHELLOS
|
||||
static const union AnimCmd *const sAnims_Shellos[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 1),
|
||||
ANIMCMD_FRAME(1, 36),
|
||||
ANIMCMD_FRAME(0, 10),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
|
||||
static const union AnimCmd *const sAnims_Gastrodon[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(1, 15),
|
||||
ANIMCMD_FRAME(0, 15),
|
||||
ANIMCMD_FRAME(1, 15),
|
||||
ANIMCMD_FRAME(0, 15),
|
||||
ANIMCMD_FRAME(1, 15),
|
||||
ANIMCMD_FRAME(0, 15),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_SHELLOS
|
||||
|
||||
#if P_FAMILY_ARCEUS
|
||||
static const union AnimCmd *const sAnims_Arceus[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 12),
|
||||
ANIMCMD_FRAME(1, 45),
|
||||
ANIMCMD_FRAME(0, 15),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_ARCEUS
|
||||
|
||||
#if P_FAMILY_BASCULIN
|
||||
static const union AnimCmd *const sAnims_Basculin[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(1, 8),
|
||||
ANIMCMD_FRAME(0, 8),
|
||||
ANIMCMD_FRAME(1, 8),
|
||||
ANIMCMD_FRAME(0, 15),
|
||||
ANIMCMD_FRAME(1, 20),
|
||||
ANIMCMD_FRAME(0, 10),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_BASCULIN
|
||||
|
||||
#if P_FAMILY_DEERLING
|
||||
static const union AnimCmd *const sAnims_Deerling[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(1, 15),
|
||||
ANIMCMD_FRAME(0, 15),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
|
||||
static const union AnimCmd *const sAnims_Sawsbuck[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 20),
|
||||
ANIMCMD_FRAME(1, 10),
|
||||
ANIMCMD_FRAME(0, 10),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_DEERLING
|
||||
|
||||
#if P_FAMILY_GENESECT
|
||||
static const union AnimCmd *const sAnims_Genesect[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(1, 5),
|
||||
ANIMCMD_FRAME(0, 5),
|
||||
ANIMCMD_FRAME(1, 25),
|
||||
ANIMCMD_FRAME(0, 5),
|
||||
ANIMCMD_FRAME(1, 5),
|
||||
ANIMCMD_FRAME(0, 5),
|
||||
ANIMCMD_FRAME(1, 5),
|
||||
ANIMCMD_FRAME(0, 5),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_GENESECT
|
||||
|
||||
#if P_FAMILY_FROAKIE
|
||||
static const union AnimCmd *const sAnims_Greninja[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(1, 32),
|
||||
ANIMCMD_FRAME(0, 20),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_GRENINJA
|
||||
|
||||
#if P_FAMILY_SCATTERBUG
|
||||
static const union AnimCmd *const sAnims_Scatterbug[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 5),
|
||||
ANIMCMD_FRAME(1, 10),
|
||||
ANIMCMD_FRAME(0, 10),
|
||||
ANIMCMD_FRAME(1, 35),
|
||||
ANIMCMD_FRAME(0, 5),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
|
||||
static const union AnimCmd *const sAnims_Spewpa[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 18),
|
||||
ANIMCMD_FRAME(1, 18),
|
||||
ANIMCMD_FRAME(0, 18),
|
||||
ANIMCMD_FRAME(1, 18),
|
||||
ANIMCMD_FRAME(0, 10),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
|
||||
static const union AnimCmd *const sAnims_Vivillon[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 15),
|
||||
ANIMCMD_FRAME(1, 15),
|
||||
ANIMCMD_FRAME(0, 15),
|
||||
ANIMCMD_FRAME(1, 15),
|
||||
ANIMCMD_FRAME(0, 15),
|
||||
ANIMCMD_FRAME(1, 15),
|
||||
ANIMCMD_FRAME(0, 50),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_SCATTERBUG
|
||||
|
||||
#if P_FAMILY_FLABEBE
|
||||
static const union AnimCmd *const sAnims_Flabebe[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(1, 27),
|
||||
ANIMCMD_FRAME(0, 20),
|
||||
ANIMCMD_FRAME(1, 23),
|
||||
ANIMCMD_FRAME(0, 5),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
|
||||
static const union AnimCmd *const sAnims_Floette[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 25),
|
||||
ANIMCMD_FRAME(1, 50),
|
||||
ANIMCMD_FRAME(0, 5),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
|
||||
static const union AnimCmd *const sAnims_Florges[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(1, 45),
|
||||
ANIMCMD_FRAME(0, 5),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_FLABEBE
|
||||
|
||||
#if P_FAMILY_FURFROU
|
||||
static const union AnimCmd *const sAnims_Furfrou[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 27),
|
||||
ANIMCMD_FRAME(1, 6),
|
||||
ANIMCMD_FRAME(0, 6),
|
||||
ANIMCMD_FRAME(1, 6),
|
||||
ANIMCMD_FRAME(0, 1),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_FURFROU
|
||||
|
||||
#if P_FAMILY_ESPURR
|
||||
static const union AnimCmd *const sAnims_Meowstic[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 12),
|
||||
ANIMCMD_FRAME(1, 45),
|
||||
ANIMCMD_FRAME(0, 15),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_MEOWSTIC
|
||||
|
||||
#if P_FAMILY_PUMPKABOO
|
||||
static const union AnimCmd *const sAnims_Pumpkaboo[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(1, 12),
|
||||
ANIMCMD_FRAME(0, 12),
|
||||
ANIMCMD_FRAME(1, 12),
|
||||
ANIMCMD_FRAME(0, 30),
|
||||
ANIMCMD_FRAME(1, 12),
|
||||
ANIMCMD_FRAME(0, 12),
|
||||
ANIMCMD_FRAME(1, 12),
|
||||
ANIMCMD_FRAME(0, 15),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
|
||||
static const union AnimCmd *const sAnims_Gourgeist[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 15),
|
||||
ANIMCMD_FRAME(1, 15),
|
||||
ANIMCMD_FRAME(0, 5),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_PUMPKABOO
|
||||
|
||||
#if P_FAMILY_XERNEAS
|
||||
static const union AnimCmd *const sAnims_Xerneas[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 12),
|
||||
ANIMCMD_FRAME(1, 45),
|
||||
ANIMCMD_FRAME(0, 15),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_XERNEAS
|
||||
|
||||
#if P_FAMILY_ZYGARDE
|
||||
static const union AnimCmd *const sAnims_Zygarde50[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 10),
|
||||
ANIMCMD_FRAME(1, 25),
|
||||
ANIMCMD_FRAME(0, 30),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
|
||||
static const union AnimCmd *const sAnims_Zygarde10[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 20),
|
||||
ANIMCMD_FRAME(1, 10),
|
||||
ANIMCMD_FRAME(0, 10),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_ZYGARDE
|
||||
|
||||
#if P_FAMILY_GRUBBIN
|
||||
static const union AnimCmd *const sAnims_Vikavolt[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 1),
|
||||
ANIMCMD_FRAME(1, 15),
|
||||
ANIMCMD_FRAME(0, 1),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_GRUBBIN
|
||||
|
||||
#if P_FAMILY_CUTIEFLY
|
||||
static const union AnimCmd *const sAnims_Ribombee[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(1, 8),
|
||||
ANIMCMD_FRAME(0, 8),
|
||||
ANIMCMD_FRAME(1, 8),
|
||||
ANIMCMD_FRAME(0, 8),
|
||||
ANIMCMD_FRAME(1, 8),
|
||||
ANIMCMD_FRAME(0, 8),
|
||||
ANIMCMD_FRAME(1, 8),
|
||||
ANIMCMD_FRAME(0, 8),
|
||||
ANIMCMD_FRAME(1, 8),
|
||||
ANIMCMD_FRAME(0, 8),
|
||||
ANIMCMD_FRAME(1, 8),
|
||||
ANIMCMD_FRAME(0, 8),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_CUTIEFLY
|
||||
|
||||
#if P_FAMILY_ROCKRUFF
|
||||
static const union AnimCmd *const sAnims_Rockruff[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(1, 9),
|
||||
ANIMCMD_FRAME(0, 8),
|
||||
ANIMCMD_FRAME(1, 8),
|
||||
ANIMCMD_FRAME(0, 5),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_ROCKRUFF
|
||||
|
||||
#if P_FAMILY_DEWPIDER
|
||||
static const union AnimCmd *const sAnims_Araquanid[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 1),
|
||||
ANIMCMD_FRAME(1, 45),
|
||||
ANIMCMD_FRAME(0, 1),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_DEWPIDER
|
||||
|
||||
#if P_FAMILY_SALANDIT
|
||||
static const union AnimCmd *const sAnims_Salazzle[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 10),
|
||||
ANIMCMD_FRAME(1, 30),
|
||||
ANIMCMD_FRAME(0, 1),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_SALANDIT
|
||||
|
||||
#if P_FAMILY_TOGEDEMARU
|
||||
static const union AnimCmd *const sAnims_Togedemaru[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(1, 30),
|
||||
ANIMCMD_FRAME(0, 5),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_TOGEDEMARU
|
||||
|
||||
#if P_FAMILY_JANGMO_O
|
||||
static const union AnimCmd *const sAnims_Kommo_O[] =
|
||||
{
|
||||
sAnim_GeneralFrame0,
|
||||
(const union AnimCmd[]) {
|
||||
ANIMCMD_FRAME(0, 10),
|
||||
ANIMCMD_FRAME(1, 20),
|
||||
ANIMCMD_FRAME(0, 20),
|
||||
ANIMCMD_FRAME(1, 20),
|
||||
ANIMCMD_FRAME(0, 1),
|
||||
ANIMCMD_END,
|
||||
},
|
||||
};
|
||||
#endif //P_FAMILY_JANGMO_O
|
||||
1199
src/debug.c
@ -5,8 +5,7 @@
|
||||
#include "pokemon.h"
|
||||
#include "pokemon_sprite_visualizer.h"
|
||||
#include "text.h"
|
||||
|
||||
EWRAM_DATA ALIGNED(4) u8 gDecompressionBuffer[0x4000] = {0};
|
||||
#include "menu.h"
|
||||
|
||||
void LZDecompressWram(const u32 *src, void *dest)
|
||||
{
|
||||
@ -40,66 +39,69 @@ u32 IsLZ77Data(const void *ptr, u32 minSize, u32 maxSize)
|
||||
return 0;
|
||||
}
|
||||
|
||||
u16 LoadCompressedSpriteSheet(const struct CompressedSpriteSheet *src)
|
||||
static inline u32 DoLoadCompressedSpriteSheet(const struct CompressedSpriteSheet *src, void *buffer)
|
||||
{
|
||||
struct SpriteSheet dest;
|
||||
|
||||
LZ77UnCompWram(src->data, gDecompressionBuffer);
|
||||
dest.data = gDecompressionBuffer;
|
||||
dest.data = buffer;
|
||||
dest.size = src->size;
|
||||
dest.tag = src->tag;
|
||||
return LoadSpriteSheet(&dest);
|
||||
}
|
||||
|
||||
u32 LoadCompressedSpriteSheet(const struct CompressedSpriteSheet *src)
|
||||
{
|
||||
void *buffer = malloc_and_decompress(src->data, NULL);
|
||||
u32 ret = DoLoadCompressedSpriteSheet(src, buffer);
|
||||
Free(buffer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 LoadCompressedSpriteSheetOverrideBuffer(const struct CompressedSpriteSheet *src, void *buffer)
|
||||
{
|
||||
LZDecompressWram(src->data, buffer);
|
||||
return DoLoadCompressedSpriteSheet(src, buffer);
|
||||
}
|
||||
|
||||
// This can be used for either compressed or uncompressed sprite sheets
|
||||
u16 LoadCompressedSpriteSheetByTemplate(const struct SpriteTemplate *template, s32 offset)
|
||||
u32 LoadCompressedSpriteSheetByTemplate(const struct SpriteTemplate *template, s32 offset)
|
||||
{
|
||||
struct SpriteTemplate myTemplate;
|
||||
struct SpriteFrameImage myImage;
|
||||
u32 size;
|
||||
|
||||
// Check for LZ77 header and read uncompressed size, or fallback if not compressed (zero size)
|
||||
if ((size = IsLZ77Data(template->images->data, TILE_SIZE_4BPP, sizeof(gDecompressionBuffer))) == 0)
|
||||
if ((size = IsLZ77Data(template->images->data, TILE_SIZE_4BPP, MAX_DECOMPRESSION_BUFFER_SIZE)) == 0)
|
||||
return LoadSpriteSheetByTemplateWithOffset(template, 0, offset);
|
||||
|
||||
LZ77UnCompWram(template->images->data, gDecompressionBuffer);
|
||||
myImage.data = gDecompressionBuffer;
|
||||
void *buffer = malloc_and_decompress(template->images->data, NULL);
|
||||
myImage.data = buffer;
|
||||
myImage.size = size + offset;
|
||||
myTemplate.images = &myImage;
|
||||
myTemplate.tileTag = template->tileTag;
|
||||
|
||||
return LoadSpriteSheetByTemplateWithOffset(&myTemplate, 0, offset);
|
||||
u32 ret = LoadSpriteSheetByTemplateWithOffset(&myTemplate, 0, offset);
|
||||
Free(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LoadCompressedSpriteSheetOverrideBuffer(const struct CompressedSpriteSheet *src, void *buffer)
|
||||
u32 LoadCompressedSpritePalette(const struct CompressedSpritePalette *src)
|
||||
{
|
||||
struct SpriteSheet dest;
|
||||
return LoadCompressedSpritePaletteWithTag(src->data, src->tag);
|
||||
}
|
||||
|
||||
u32 LoadCompressedSpritePaletteWithTag(const u32 *pal, u16 tag)
|
||||
{
|
||||
u32 index;
|
||||
struct SpritePalette dest;
|
||||
void *buffer = malloc_and_decompress(pal, NULL);
|
||||
|
||||
LZ77UnCompWram(src->data, buffer);
|
||||
dest.data = buffer;
|
||||
dest.size = src->size;
|
||||
dest.tag = src->tag;
|
||||
LoadSpriteSheet(&dest);
|
||||
}
|
||||
|
||||
void LoadCompressedSpritePalette(const struct CompressedSpritePalette *src)
|
||||
{
|
||||
struct SpritePalette dest;
|
||||
|
||||
LZ77UnCompWram(src->data, gDecompressionBuffer);
|
||||
dest.data = (void *) gDecompressionBuffer;
|
||||
dest.tag = src->tag;
|
||||
LoadSpritePalette(&dest);
|
||||
}
|
||||
|
||||
void LoadCompressedSpritePaletteWithTag(const u32 *pal, u16 tag)
|
||||
{
|
||||
struct SpritePalette dest;
|
||||
|
||||
LZ77UnCompWram(pal, gDecompressionBuffer);
|
||||
dest.data = (void *) gDecompressionBuffer;
|
||||
dest.tag = tag;
|
||||
LoadSpritePalette(&dest);
|
||||
index = LoadSpritePalette(&dest);
|
||||
Free(buffer);
|
||||
return index;
|
||||
}
|
||||
|
||||
void LoadCompressedSpritePaletteOverrideBuffer(const struct CompressedSpritePalette *src, void *buffer)
|
||||
|
||||
@ -18,17 +18,10 @@
|
||||
struct EReaderTaskData
|
||||
{
|
||||
u16 timer;
|
||||
u16 unused1;
|
||||
u16 unused2;
|
||||
u16 unused3;
|
||||
u8 state;
|
||||
u8 textState;
|
||||
u8 unused4;
|
||||
u8 unused5;
|
||||
u8 unused6;
|
||||
u8 unused7;
|
||||
u8 status;
|
||||
u8 *unusedBuffer;
|
||||
u8 *buffer;
|
||||
};
|
||||
|
||||
struct EReaderData
|
||||
@ -98,7 +91,6 @@ static u8 EReader_Transfer(struct EReaderData *eReader)
|
||||
|
||||
static void OpenEReaderLink(void)
|
||||
{
|
||||
memset(gDecompressionBuffer, 0, 0x2000);
|
||||
gLinkType = LINKTYPE_EREADER_EM;
|
||||
OpenLink();
|
||||
SetSuppressLinkErrorMessage(TRUE);
|
||||
@ -251,16 +243,9 @@ void CreateEReaderTask(void)
|
||||
data = (struct EReaderTaskData *)gTasks[taskId].data;
|
||||
data->state = 0;
|
||||
data->textState = 0;
|
||||
data->unused4 = 0;
|
||||
data->unused5 = 0;
|
||||
data->unused6 = 0;
|
||||
data->unused7 = 0;
|
||||
data->timer = 0;
|
||||
data->unused1 = 0;
|
||||
data->unused2 = 0;
|
||||
data->unused3 = 0;
|
||||
data->status = 0;
|
||||
data->unusedBuffer = AllocZeroed(CLIENT_MAX_MSG_SIZE);
|
||||
data->buffer = AllocZeroed(0x2000);
|
||||
}
|
||||
|
||||
static void ResetTimer(u16 *timer)
|
||||
@ -471,7 +456,7 @@ static void Task_EReader(u8 taskId)
|
||||
}
|
||||
break;
|
||||
case ER_STATE_VALIDATE_CARD:
|
||||
data->status = ValidateTrainerHillData((struct EReaderTrainerHillSet *)gDecompressionBuffer);
|
||||
data->status = ValidateTrainerHillData((struct EReaderTrainerHillSet *)data->buffer);
|
||||
SetCloseLinkCallbackAndType(data->status);
|
||||
data->state = ER_STATE_WAIT_DISCONNECT;
|
||||
break;
|
||||
@ -485,7 +470,7 @@ static void Task_EReader(u8 taskId)
|
||||
}
|
||||
break;
|
||||
case ER_STATE_SAVE:
|
||||
if (TryWriteTrainerHill((struct EReaderTrainerHillSet *)&gDecompressionBuffer))
|
||||
if (TryWriteTrainerHill((struct EReaderTrainerHillSet *)data->buffer))
|
||||
{
|
||||
MG_AddMessageTextPrinter(gJPText_ConnectionComplete);
|
||||
ResetTimer(&data->timer);
|
||||
@ -525,7 +510,7 @@ static void Task_EReader(u8 taskId)
|
||||
data->state = ER_STATE_START;
|
||||
break;
|
||||
case ER_STATE_END:
|
||||
Free(data->unusedBuffer);
|
||||
Free(data->buffer);
|
||||
DestroyTask(taskId);
|
||||
SetMainCallback2(MainCB_FreeAllBuffersAndReturnToInitTitleScreen);
|
||||
break;
|
||||
|
||||
@ -29,6 +29,18 @@ EWRAM_DATA static u8 sSpecialFlags[SPECIAL_FLAGS_SIZE] = {0};
|
||||
|
||||
extern u16 *const gSpecialVars[];
|
||||
|
||||
const u16 gBadgeFlags[NUM_BADGES] =
|
||||
{
|
||||
FLAG_BADGE01_GET,
|
||||
FLAG_BADGE02_GET,
|
||||
FLAG_BADGE03_GET,
|
||||
FLAG_BADGE04_GET,
|
||||
FLAG_BADGE05_GET,
|
||||
FLAG_BADGE06_GET,
|
||||
FLAG_BADGE07_GET,
|
||||
FLAG_BADGE08_GET,
|
||||
};
|
||||
|
||||
void InitEventData(void)
|
||||
{
|
||||
memset(gSaveBlock1Ptr->flags, 0, sizeof(gSaveBlock1Ptr->flags));
|
||||
|
||||
@ -2086,15 +2086,19 @@ static u8 LoadDynamicFollowerPalette(u16 species, u8 form, bool32 shiny)
|
||||
spritePalette.data = gSpeciesInfo[species].overworldPalette;
|
||||
}
|
||||
|
||||
|
||||
// Check if pal data must be decompressed
|
||||
if (IsLZ77Data(spritePalette.data, PLTT_SIZE_4BPP, PLTT_SIZE_4BPP))
|
||||
{
|
||||
// IsLZ77Data guarantees word-alignment, so casting this is safe
|
||||
LZ77UnCompWram((u32*)spritePalette.data, gDecompressionBuffer);
|
||||
spritePalette.data = (void*)gDecompressionBuffer;
|
||||
struct CompressedSpritePalette compSpritePalette;
|
||||
|
||||
compSpritePalette.data = (const void *) spritePalette.data;
|
||||
compSpritePalette.tag = spritePalette.tag;
|
||||
paletteNum = LoadCompressedSpritePalette(&compSpritePalette);
|
||||
}
|
||||
else
|
||||
{
|
||||
paletteNum = LoadSpritePalette(&spritePalette);
|
||||
}
|
||||
paletteNum = LoadSpritePalette(&spritePalette);
|
||||
}
|
||||
else
|
||||
#endif //OW_POKEMON_OBJECT_EVENTS == TRUE && OW_PKMN_OBJECTS_SHARE_PALETTES == FALSE
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include "fldeff.h"
|
||||
#include "gpu_regs.h"
|
||||
#include "main.h"
|
||||
#include "malloc.h"
|
||||
#include "mirage_tower.h"
|
||||
#include "menu.h"
|
||||
#include "metatile_behavior.h"
|
||||
@ -897,8 +898,20 @@ bool8 FieldEffectActiveListContains(u8 id)
|
||||
u8 CreateTrainerSprite(u8 trainerSpriteID, s16 x, s16 y, u8 subpriority, u8 *buffer)
|
||||
{
|
||||
struct SpriteTemplate spriteTemplate;
|
||||
bool32 alloced = FALSE;
|
||||
|
||||
// Allocate memory for buffer
|
||||
if (buffer == NULL)
|
||||
{
|
||||
buffer = Alloc(TRAINER_PIC_SIZE + PLTT_SIZEOF(16));
|
||||
alloced = TRUE;
|
||||
}
|
||||
|
||||
LoadCompressedSpritePaletteOverrideBuffer(&gTrainerSprites[trainerSpriteID].palette, buffer);
|
||||
LoadCompressedSpriteSheetOverrideBuffer(&gTrainerSprites[trainerSpriteID].frontPic, buffer);
|
||||
if (alloced)
|
||||
Free(buffer);
|
||||
|
||||
spriteTemplate.tileTag = gTrainerSprites[trainerSpriteID].frontPic.tag;
|
||||
spriteTemplate.paletteTag = gTrainerSprites[trainerSpriteID].palette.tag;
|
||||
spriteTemplate.oam = &sOam_64x64;
|
||||
@ -3946,7 +3959,7 @@ static void Task_MoveDeoxysRock(u8 taskId)
|
||||
u8 FldEff_CaveDust(void)
|
||||
{
|
||||
u8 spriteId;
|
||||
|
||||
|
||||
SetSpritePosToOffsetMapCoords((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8);
|
||||
spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[FLDEFFOBJ_CAVE_DUST], gFieldEffectArguments[0], gFieldEffectArguments[1], 0xFF);
|
||||
if (spriteId != MAX_SPRITES)
|
||||
@ -3954,7 +3967,7 @@ u8 FldEff_CaveDust(void)
|
||||
gSprites[spriteId].coordOffsetEnabled = TRUE;
|
||||
gSprites[spriteId].data[0] = 22;
|
||||
}
|
||||
|
||||
|
||||
return spriteId;
|
||||
}
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "field_screen_effect.h"
|
||||
#include "field_weather.h"
|
||||
#include "fldeff.h"
|
||||
#include "malloc.h"
|
||||
#include "mirage_tower.h"
|
||||
#include "palette.h"
|
||||
#include "party_menu.h"
|
||||
@ -15,6 +16,7 @@
|
||||
#include "sprite.h"
|
||||
#include "task.h"
|
||||
#include "wild_encounter.h"
|
||||
#include "util.h"
|
||||
#include "constants/field_effects.h"
|
||||
#include "constants/rgb.h"
|
||||
#include "constants/songs.h"
|
||||
@ -47,20 +49,40 @@ bool8 FldEff_SweetScent(void)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#define tPalBuffer1 data[1]
|
||||
#define tPalBuffer2 data[2]
|
||||
|
||||
void StartSweetScentFieldEffect(void)
|
||||
{
|
||||
u8 taskId;
|
||||
void *palBuffer;
|
||||
u32 taskId;
|
||||
u32 palettes = ~(1 << (gSprites[GetPlayerAvatarSpriteId()].oam.paletteNum + 16) | (1 << 13) | (1 << 14) | (1 << 15));
|
||||
|
||||
PlaySE(SE_M_SWEET_SCENT);
|
||||
CpuFastCopy(gPlttBufferUnfaded, gDecompressionBuffer, PLTT_SIZE);
|
||||
palBuffer = Alloc(PLTT_SIZE);
|
||||
CpuFastCopy(gPlttBufferUnfaded, palBuffer, PLTT_SIZE);
|
||||
CpuFastCopy(gPlttBufferFaded, gPlttBufferUnfaded, PLTT_SIZE);
|
||||
BeginNormalPaletteFade(palettes, 4, 0, 8, RGB_RED);
|
||||
taskId = CreateTask(TrySweetScentEncounter, 0);
|
||||
gTasks[taskId].data[0] = 0;
|
||||
StoreWordInTwoHalfwords((u16 *)&gTasks[taskId].tPalBuffer1, (u32) palBuffer);
|
||||
FieldEffectActiveListRemove(FLDEFF_SWEET_SCENT);
|
||||
}
|
||||
|
||||
static void *GetPalBufferPtr(u32 taskId)
|
||||
{
|
||||
u32 palBuffer;
|
||||
|
||||
LoadWordFromTwoHalfwords((u16 *)&gTasks[taskId].tPalBuffer1, &palBuffer);
|
||||
return (void *) palBuffer;
|
||||
}
|
||||
|
||||
static void FreeDestroyTask(u32 taskId)
|
||||
{
|
||||
Free(GetPalBufferPtr(taskId));
|
||||
DestroyTask(taskId);
|
||||
}
|
||||
|
||||
static void TrySweetScentEncounter(u8 taskId)
|
||||
{
|
||||
if (!gPaletteFade.active)
|
||||
@ -72,7 +94,7 @@ static void TrySweetScentEncounter(u8 taskId)
|
||||
gTasks[taskId].data[0] = 0;
|
||||
if (SweetScentWildEncounter() == TRUE)
|
||||
{
|
||||
DestroyTask(taskId);
|
||||
FreeDestroyTask(taskId);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -92,9 +114,12 @@ static void FailSweetScentEncounter(u8 taskId)
|
||||
{
|
||||
if (!gPaletteFade.active)
|
||||
{
|
||||
CpuFastCopy(gDecompressionBuffer, gPlttBufferUnfaded, PLTT_SIZE);
|
||||
CpuFastCopy(GetPalBufferPtr(taskId), gPlttBufferUnfaded, PLTT_SIZE);
|
||||
SetWeatherPalStateIdle();
|
||||
ScriptContext_SetupScript(EventScript_FailSweetScent);
|
||||
DestroyTask(taskId);
|
||||
FreeDestroyTask(taskId);
|
||||
}
|
||||
}
|
||||
|
||||
#undef tPalBuffer1
|
||||
#undef tPalBuffer2
|
||||
|
||||
@ -1683,7 +1683,11 @@ const u32 gMoveTypes_Pal[] = INCBIN_U32("graphics/types/move_types.gbapal.lz");
|
||||
const u32 gSummaryMoveSelect_Gfx[] = INCBIN_U32("graphics/summary_screen/move_select.4bpp.lz");
|
||||
const u32 gSummaryMoveSelect_Pal[] = INCBIN_U32("graphics/summary_screen/move_select.gbapal.lz");
|
||||
|
||||
#if P_SUMMARY_SCREEN_IV_EV_TILESET
|
||||
const u32 gSummaryScreen_Gfx[] = INCBIN_U32("graphics/summary_screen/iv_ev_tiles.4bpp.lz");
|
||||
#else
|
||||
const u32 gSummaryScreen_Gfx[] = INCBIN_U32("graphics/summary_screen/tiles.4bpp.lz");
|
||||
#endif // P_SUMMARY_SCREEN_IV_EV_TILESET
|
||||
const u32 gSummaryScreen_Pal[] = INCBIN_U32("graphics/summary_screen/tiles.gbapal.lz");
|
||||
const u32 gSummaryPage_Info_Tilemap[] = INCBIN_U32("graphics/summary_screen/page_info.bin.lz");
|
||||
const u32 gSummaryPage_Skills_Tilemap[] = INCBIN_U32("graphics/summary_screen/page_skills.bin.lz");
|
||||
|
||||
@ -38,21 +38,6 @@
|
||||
#define HALL_OF_FAME_MAX_TEAMS 30
|
||||
#define TAG_CONFETTI 1001
|
||||
|
||||
struct HallofFameMon
|
||||
{
|
||||
u32 tid;
|
||||
u32 personality;
|
||||
u16 isShiny:1;
|
||||
u16 species:15;
|
||||
u8 lvl;
|
||||
u8 nickname[POKEMON_NAME_LENGTH];
|
||||
};
|
||||
|
||||
struct HallofFameTeam
|
||||
{
|
||||
struct HallofFameMon mon[PARTY_SIZE];
|
||||
};
|
||||
|
||||
STATIC_ASSERT(sizeof(struct HallofFameTeam) * HALL_OF_FAME_MAX_TEAMS <= SECTOR_DATA_SIZE * NUM_HOF_SECTORS, HallOfFameFreeSpace);
|
||||
|
||||
struct HofGfx
|
||||
@ -66,6 +51,7 @@ struct HofGfx
|
||||
static EWRAM_DATA u32 sHofFadePalettes = 0;
|
||||
static EWRAM_DATA struct HallofFameTeam *sHofMonPtr = NULL;
|
||||
static EWRAM_DATA struct HofGfx *sHofGfxPtr = NULL;
|
||||
EWRAM_DATA struct HallofFameTeam *gHoFSaveBuffer = NULL;
|
||||
|
||||
static void ClearVramOamPltt_LoadHofPal(void);
|
||||
static void LoadHofGfx(void);
|
||||
@ -416,13 +402,19 @@ static bool8 InitHallOfFameScreen(void)
|
||||
#define tPlayerSpriteID data[4]
|
||||
#define tMonSpriteId(i) data[i + 5]
|
||||
|
||||
static void AllocateHoFTeams(void)
|
||||
{
|
||||
sHofMonPtr = AllocZeroed(sizeof(*sHofMonPtr));
|
||||
gHoFSaveBuffer = Alloc(SECTOR_SIZE * NUM_HOF_SECTORS);
|
||||
}
|
||||
|
||||
void CB2_DoHallOfFameScreen(void)
|
||||
{
|
||||
if (!InitHallOfFameScreen())
|
||||
{
|
||||
u8 taskId = CreateTask(Task_Hof_InitMonData, 0);
|
||||
gTasks[taskId].tDontSaveData = FALSE;
|
||||
sHofMonPtr = AllocZeroed(sizeof(*sHofMonPtr));
|
||||
AllocateHoFTeams();
|
||||
}
|
||||
}
|
||||
|
||||
@ -432,7 +424,7 @@ void CB2_DoHallOfFameScreenDontSaveData(void)
|
||||
{
|
||||
u8 taskId = CreateTask(Task_Hof_InitMonData, 0);
|
||||
gTasks[taskId].tDontSaveData = TRUE;
|
||||
sHofMonPtr = AllocZeroed(sizeof(*sHofMonPtr));
|
||||
AllocateHoFTeams();
|
||||
}
|
||||
}
|
||||
|
||||
@ -486,16 +478,16 @@ static void Task_Hof_InitMonData(u8 taskId)
|
||||
static void Task_Hof_InitTeamSaveData(u8 taskId)
|
||||
{
|
||||
u16 i;
|
||||
struct HallofFameTeam *lastSavedTeam = (struct HallofFameTeam *)(gDecompressionBuffer);
|
||||
struct HallofFameTeam *lastSavedTeam = gHoFSaveBuffer;
|
||||
|
||||
if (!gHasHallOfFameRecords)
|
||||
{
|
||||
memset(gDecompressionBuffer, 0, SECTOR_SIZE * NUM_HOF_SECTORS);
|
||||
memset(gHoFSaveBuffer, 0, SECTOR_SIZE * NUM_HOF_SECTORS);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LoadGameSave(SAVE_HALL_OF_FAME) != SAVE_STATUS_OK)
|
||||
memset(gDecompressionBuffer, 0, SECTOR_SIZE * NUM_HOF_SECTORS);
|
||||
memset(gHoFSaveBuffer, 0, SECTOR_SIZE * NUM_HOF_SECTORS);
|
||||
}
|
||||
|
||||
for (i = 0; i < HALL_OF_FAME_MAX_TEAMS; i++, lastSavedTeam++)
|
||||
@ -505,8 +497,8 @@ static void Task_Hof_InitTeamSaveData(u8 taskId)
|
||||
}
|
||||
if (i >= HALL_OF_FAME_MAX_TEAMS)
|
||||
{
|
||||
struct HallofFameTeam *afterTeam = (struct HallofFameTeam *)(gDecompressionBuffer);
|
||||
struct HallofFameTeam *beforeTeam = (struct HallofFameTeam *)(gDecompressionBuffer);
|
||||
struct HallofFameTeam *afterTeam = gHoFSaveBuffer;
|
||||
struct HallofFameTeam *beforeTeam = gHoFSaveBuffer;
|
||||
afterTeam++;
|
||||
for (i = 0; i < HALL_OF_FAME_MAX_TEAMS - 1; i++, beforeTeam++, afterTeam++)
|
||||
{
|
||||
@ -522,6 +514,13 @@ static void Task_Hof_InitTeamSaveData(u8 taskId)
|
||||
gTasks[taskId].func = Task_Hof_TrySaveData;
|
||||
}
|
||||
|
||||
static void FreeAllHoFMem(void)
|
||||
{
|
||||
TRY_FREE_AND_SET_NULL(sHofGfxPtr);
|
||||
TRY_FREE_AND_SET_NULL(sHofMonPtr);
|
||||
TRY_FREE_AND_SET_NULL(gHoFSaveBuffer);
|
||||
}
|
||||
|
||||
static void Task_Hof_TrySaveData(u8 taskId)
|
||||
{
|
||||
gGameContinueCallback = CB2_DoHallOfFameScreenDontSaveData;
|
||||
@ -531,8 +530,7 @@ static void Task_Hof_TrySaveData(u8 taskId)
|
||||
UnsetBgTilemapBuffer(3);
|
||||
FreeAllWindowBuffers();
|
||||
|
||||
TRY_FREE_AND_SET_NULL(sHofGfxPtr);
|
||||
TRY_FREE_AND_SET_NULL(sHofMonPtr);
|
||||
FreeAllHoFMem();
|
||||
|
||||
DestroyTask(taskId);
|
||||
}
|
||||
@ -772,10 +770,7 @@ static void Task_Hof_HandleExit(u8 taskId)
|
||||
UnsetBgTilemapBuffer(3);
|
||||
ResetBgsAndClearDma3BusyFlags(0);
|
||||
DestroyTask(taskId);
|
||||
|
||||
TRY_FREE_AND_SET_NULL(sHofGfxPtr);
|
||||
TRY_FREE_AND_SET_NULL(sHofMonPtr);
|
||||
|
||||
FreeAllHoFMem();
|
||||
StartCredits();
|
||||
}
|
||||
}
|
||||
@ -807,6 +802,7 @@ void CB2_DoHallOfFamePC(void)
|
||||
SetVBlankCallback(NULL);
|
||||
ClearVramOamPltt_LoadHofPal();
|
||||
sHofGfxPtr = AllocZeroed(sizeof(*sHofGfxPtr));
|
||||
AllocateHoFTeams();
|
||||
gMain.state = 1;
|
||||
break;
|
||||
case 1:
|
||||
@ -823,7 +819,7 @@ void CB2_DoHallOfFamePC(void)
|
||||
case 3:
|
||||
if (!LoadHofBgs())
|
||||
{
|
||||
struct HallofFameTeam *fameTeam = (struct HallofFameTeam *)(gDecompressionBuffer);
|
||||
struct HallofFameTeam *fameTeam = gHoFSaveBuffer;
|
||||
fameTeam->mon[0] = sDummyFameMon;
|
||||
ComputerScreenOpenEffect(0, 0, 0);
|
||||
SetVBlankCallback(VBlankCB_HallOfFame);
|
||||
@ -852,7 +848,6 @@ void CB2_DoHallOfFamePC(void)
|
||||
gTasks[taskId].tMonSpriteId(i) = SPRITE_NONE;
|
||||
}
|
||||
|
||||
sHofMonPtr = AllocZeroed(SECTOR_SIZE * NUM_HOF_SECTORS);
|
||||
SetMainCallback2(CB2_HallOfFame);
|
||||
}
|
||||
break;
|
||||
@ -871,8 +866,7 @@ static void Task_HofPC_CopySaveData(u8 taskId)
|
||||
u16 i;
|
||||
struct HallofFameTeam *savedTeams;
|
||||
|
||||
CpuCopy16(gDecompressionBuffer, sHofMonPtr, SECTOR_SIZE * NUM_HOF_SECTORS);
|
||||
savedTeams = sHofMonPtr;
|
||||
savedTeams = gHoFSaveBuffer;
|
||||
for (i = 0; i < HALL_OF_FAME_MAX_TEAMS; i++, savedTeams++)
|
||||
{
|
||||
if (savedTeams->mon[0].species == SPECIES_NONE)
|
||||
@ -892,7 +886,7 @@ static void Task_HofPC_CopySaveData(u8 taskId)
|
||||
|
||||
static void Task_HofPC_DrawSpritesPrintText(u8 taskId)
|
||||
{
|
||||
struct HallofFameTeam *savedTeams = sHofMonPtr;
|
||||
struct HallofFameTeam *savedTeams = gHoFSaveBuffer;
|
||||
struct HallofFameMon* currMon;
|
||||
u16 i;
|
||||
|
||||
@ -958,7 +952,7 @@ static void Task_HofPC_DrawSpritesPrintText(u8 taskId)
|
||||
|
||||
static void Task_HofPC_PrintMonInfo(u8 taskId)
|
||||
{
|
||||
struct HallofFameTeam *savedTeams = sHofMonPtr;
|
||||
struct HallofFameTeam *savedTeams = gHoFSaveBuffer;
|
||||
struct HallofFameMon* currMon;
|
||||
u16 i;
|
||||
u16 currMonID;
|
||||
@ -1047,7 +1041,7 @@ static void Task_HofPC_HandlePaletteOnExit(u8 taskId)
|
||||
struct HallofFameTeam *fameTeam;
|
||||
|
||||
CpuCopy16(gPlttBufferFaded, gPlttBufferUnfaded, PLTT_SIZE);
|
||||
fameTeam = (struct HallofFameTeam *)(gDecompressionBuffer);
|
||||
fameTeam = gHoFSaveBuffer;
|
||||
fameTeam->mon[0] = sDummyFameMon;
|
||||
ComputerScreenCloseEffect(0, 0, 0);
|
||||
gTasks[taskId].func = Task_HofPC_HandleExit;
|
||||
@ -1057,7 +1051,7 @@ static void Task_HofPC_HandleExit(u8 taskId)
|
||||
{
|
||||
if (!IsComputerScreenCloseEffectActive())
|
||||
{
|
||||
u8 i;
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
@ -1079,8 +1073,7 @@ static void Task_HofPC_HandleExit(u8 taskId)
|
||||
ResetBgsAndClearDma3BusyFlags(0);
|
||||
DestroyTask(taskId);
|
||||
|
||||
TRY_FREE_AND_SET_NULL(sHofGfxPtr);
|
||||
TRY_FREE_AND_SET_NULL(sHofMonPtr);
|
||||
FreeAllHoFMem();
|
||||
|
||||
ReturnFromHallOfFamePC();
|
||||
}
|
||||
|
||||
@ -6,9 +6,12 @@
|
||||
#include "item_menu.h"
|
||||
#include "item_icon.h"
|
||||
#include "item_menu_icons.h"
|
||||
#include "malloc.h"
|
||||
#include "menu_helpers.h"
|
||||
#include "menu.h"
|
||||
#include "sprite.h"
|
||||
#include "window.h"
|
||||
#include "util.h"
|
||||
#include "constants/items.h"
|
||||
|
||||
enum {
|
||||
@ -269,18 +272,13 @@ static const union AnimCmd *const sBerryPicSpriteAnimTable[] =
|
||||
sAnim_BerryPic
|
||||
};
|
||||
|
||||
static const struct SpriteFrameImage sBerryPicSpriteImageTable[] =
|
||||
{
|
||||
{&gDecompressionBuffer[0], 0x800},
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sBerryPicSpriteTemplate =
|
||||
{
|
||||
.tileTag = TAG_NONE,
|
||||
.paletteTag = TAG_BERRY_PIC_PAL,
|
||||
.oam = &sBerryPicOamData,
|
||||
.anims = sBerryPicSpriteAnimTable,
|
||||
.images = sBerryPicSpriteImageTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCallbackDummy,
|
||||
};
|
||||
@ -319,7 +317,7 @@ static const struct SpriteTemplate sBerryPicRotatingSpriteTemplate =
|
||||
.paletteTag = TAG_BERRY_PIC_PAL,
|
||||
.oam = &sBerryPicRotatingOamData,
|
||||
.anims = sBerryPicSpriteAnimTable,
|
||||
.images = sBerryPicSpriteImageTable,
|
||||
.images = NULL,
|
||||
.affineAnims = sBerryPicRotatingAnimCmds,
|
||||
.callback = SpriteCallbackDummy,
|
||||
};
|
||||
@ -640,47 +638,83 @@ static void ArrangeBerryGfx(void *src, void *dest)
|
||||
}
|
||||
}
|
||||
|
||||
static void LoadBerryGfx(u8 berryId)
|
||||
#define BERRY_SPRITE_SIZE ((64*64)/2) // 0x800
|
||||
|
||||
struct BerryDynamicGfx
|
||||
{
|
||||
ALIGNED(4) u8 gfx[BERRY_SPRITE_SIZE];
|
||||
struct SpriteFrameImage images[1];
|
||||
};
|
||||
|
||||
static struct BerryDynamicGfx *LoadBerryGfx(u8 berryId)
|
||||
{
|
||||
struct CompressedSpritePalette pal;
|
||||
|
||||
if (berryId == ITEM_TO_BERRY(ITEM_ENIGMA_BERRY_E_READER) - 1 && IsEnigmaBerryValid())
|
||||
{
|
||||
// unknown empty if statement
|
||||
}
|
||||
|
||||
pal.data = sBerryPicTable[berryId].pal;
|
||||
pal.tag = TAG_BERRY_PIC_PAL;
|
||||
pal.tag = TAG_BERRY_PIC_PAL + berryId;
|
||||
LoadCompressedSpritePalette(&pal);
|
||||
LZDecompressWram(sBerryPicTable[berryId].tiles, &gDecompressionBuffer[0x1000]);
|
||||
ArrangeBerryGfx(&gDecompressionBuffer[0x1000], &gDecompressionBuffer[0]);
|
||||
struct BerryDynamicGfx *gfxAlloced = Alloc(sizeof(struct BerryDynamicGfx));
|
||||
void *buffer = malloc_and_decompress(sBerryPicTable[berryId].tiles, NULL);
|
||||
ArrangeBerryGfx(buffer, gfxAlloced->gfx);
|
||||
Free(buffer);
|
||||
|
||||
return gfxAlloced;
|
||||
}
|
||||
|
||||
u8 CreateBerryTagSprite(u8 id, s16 x, s16 y)
|
||||
static u32 CreateBerrySprite(const struct SpriteTemplate *sprTemplate, u32 berryId, s32 x, s32 y)
|
||||
{
|
||||
LoadBerryGfx(id);
|
||||
return CreateSprite(&sBerryPicSpriteTemplate, x, y, 0);
|
||||
u32 spriteId;
|
||||
struct BerryDynamicGfx *dynamicGfx = LoadBerryGfx(berryId);
|
||||
struct SpriteTemplate newSprTemplate = *sprTemplate;
|
||||
|
||||
newSprTemplate.paletteTag += berryId;
|
||||
newSprTemplate.images = dynamicGfx->images;
|
||||
|
||||
dynamicGfx->images[0].data = dynamicGfx->gfx;
|
||||
dynamicGfx->images[0].size = BERRY_SPRITE_SIZE;
|
||||
dynamicGfx->images[0].relativeFrames = FALSE;
|
||||
|
||||
spriteId = CreateSprite(&newSprTemplate, x, y, 0);
|
||||
StoreWordInTwoHalfwords((u16 *) &gSprites[spriteId].data[BERRY_ICON_GFX_PTR_DATA_ID], (u32) dynamicGfx);
|
||||
return spriteId;
|
||||
}
|
||||
|
||||
void FreeBerryTagSpritePalette(void)
|
||||
u32 CreateBerryTagSprite(u32 id, s32 x, s32 y)
|
||||
{
|
||||
FreeSpritePaletteByTag(TAG_BERRY_PIC_PAL);
|
||||
return CreateBerrySprite(&sBerryPicSpriteTemplate, id, x, y);
|
||||
}
|
||||
|
||||
// For throwing berries into the Berry Blender
|
||||
u8 CreateSpinningBerrySprite(u8 berryId, u8 x, u8 y, bool8 startAffine)
|
||||
u32 CreateSpinningBerrySprite(u32 berryId, s32 x, s32 y, bool32 startAffine)
|
||||
{
|
||||
u8 spriteId;
|
||||
|
||||
FreeSpritePaletteByTag(TAG_BERRY_PIC_PAL);
|
||||
LoadBerryGfx(berryId);
|
||||
spriteId = CreateSprite(&sBerryPicRotatingSpriteTemplate, x, y, 0);
|
||||
if (startAffine == TRUE)
|
||||
u32 spriteId = CreateBerrySprite(&sBerryPicRotatingSpriteTemplate, berryId, x, y);
|
||||
if (startAffine)
|
||||
StartSpriteAffineAnim(&gSprites[spriteId], 1);
|
||||
|
||||
return spriteId;
|
||||
}
|
||||
|
||||
void DestroyBerryIconSprite(u32 spriteId, u32 berryId, bool32 freePal)
|
||||
{
|
||||
DestroyBerryIconSpritePtr(&gSprites[spriteId], berryId, freePal);
|
||||
}
|
||||
|
||||
void DestroyBerryIconSpritePtr(struct Sprite *sprite, u32 berryId, bool32 freePal)
|
||||
{
|
||||
u32 gfxBuffer;
|
||||
|
||||
LoadWordFromTwoHalfwords((u16 *) &sprite->data[BERRY_ICON_GFX_PTR_DATA_ID], &gfxBuffer);
|
||||
Free((void *)gfxBuffer);
|
||||
DestroySprite(sprite);
|
||||
if (freePal)
|
||||
FreeBerryIconSpritePalette(berryId);
|
||||
}
|
||||
|
||||
void FreeBerryIconSpritePalette(u32 berryId)
|
||||
{
|
||||
FreeSpritePaletteByTag(TAG_BERRY_PIC_PAL + berryId);
|
||||
}
|
||||
|
||||
u8 CreateBerryFlavorCircleSprite(s16 x)
|
||||
{
|
||||
return CreateSprite(&sBerryCheckCircleSpriteTemplate, x, 116, 0);
|
||||
|
||||
11
src/link.c
@ -555,18 +555,11 @@ static void ProcessRecvCmds(u8 unused)
|
||||
{
|
||||
if (sBlockRecv[i].size > BLOCK_BUFFER_SIZE)
|
||||
{
|
||||
u16 *buffer;
|
||||
u16 j;
|
||||
|
||||
buffer = (u16 *)gDecompressionBuffer;
|
||||
for (j = 0; j < CMD_LENGTH - 1; j++)
|
||||
{
|
||||
buffer[(sBlockRecv[i].pos / 2) + j] = gRecvCmds[i][j + 1];
|
||||
}
|
||||
// Too large block was sent.
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 j;
|
||||
u32 j;
|
||||
|
||||
for (j = 0; j < CMD_LENGTH - 1; j++)
|
||||
{
|
||||
|
||||
@ -1915,12 +1915,12 @@ static void AddBirchSpeechObjects(u8 taskId)
|
||||
gSprites[lotadSpriteId].oam.priority = 0;
|
||||
gSprites[lotadSpriteId].invisible = TRUE;
|
||||
gTasks[taskId].tLotadSpriteId = lotadSpriteId;
|
||||
brendanSpriteId = CreateTrainerSprite(FacilityClassToPicIndex(FACILITY_CLASS_BRENDAN), 120, 60, 0, &gDecompressionBuffer[0]);
|
||||
brendanSpriteId = CreateTrainerSprite(FacilityClassToPicIndex(FACILITY_CLASS_BRENDAN), 120, 60, 0, NULL);
|
||||
gSprites[brendanSpriteId].callback = SpriteCB_Null;
|
||||
gSprites[brendanSpriteId].invisible = TRUE;
|
||||
gSprites[brendanSpriteId].oam.priority = 0;
|
||||
gTasks[taskId].tBrendanSpriteId = brendanSpriteId;
|
||||
maySpriteId = CreateTrainerSprite(FacilityClassToPicIndex(FACILITY_CLASS_MAY), 120, 60, 0, &gDecompressionBuffer[TRAINER_PIC_SIZE]);
|
||||
maySpriteId = CreateTrainerSprite(FacilityClassToPicIndex(FACILITY_CLASS_MAY), 120, 60, 0, NULL);
|
||||
gSprites[maySpriteId].callback = SpriteCB_Null;
|
||||
gSprites[maySpriteId].invisible = TRUE;
|
||||
gSprites[maySpriteId].oam.priority = 0;
|
||||
|
||||
@ -1839,25 +1839,13 @@ static void PopulateBattleFrontierStreak(int matchCallId, u8 *destStr)
|
||||
ConvertIntToDecimalStringN(destStr, sBattleFrontierStreakInfo.streak, STR_CONV_MODE_LEFT_ALIGN, i);
|
||||
}
|
||||
|
||||
static const u16 sBadgeFlags[NUM_BADGES] =
|
||||
{
|
||||
FLAG_BADGE01_GET,
|
||||
FLAG_BADGE02_GET,
|
||||
FLAG_BADGE03_GET,
|
||||
FLAG_BADGE04_GET,
|
||||
FLAG_BADGE05_GET,
|
||||
FLAG_BADGE06_GET,
|
||||
FLAG_BADGE07_GET,
|
||||
FLAG_BADGE08_GET,
|
||||
};
|
||||
|
||||
static int GetNumOwnedBadges(void)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < NUM_BADGES; i++)
|
||||
{
|
||||
if (!FlagGet(sBadgeFlags[i]))
|
||||
if (!FlagGet(gBadgeFlags[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -1943,7 +1943,12 @@ void task_free_buf_after_copying_tile_data_to_vram(u8 taskId)
|
||||
|
||||
void *malloc_and_decompress(const void *src, u32 *size)
|
||||
{
|
||||
u32 sizeLocal; // If size is passed as NULL, because we don't care about knowing the size
|
||||
void *ptr;
|
||||
|
||||
if (size == NULL)
|
||||
size = &sizeLocal;
|
||||
|
||||
u8 *sizeAsBytes = (u8 *)size;
|
||||
u8 *srcAsBytes = (u8 *)src;
|
||||
|
||||
|
||||
@ -255,10 +255,14 @@ static void CB2_MysteryEventMenu(void)
|
||||
case 11:
|
||||
if (gReceivedRemoteLinkPlayers == 0)
|
||||
{
|
||||
// No clue what is going on here, and from where gDecompressionBuffer gets actually populated with mystery event script.
|
||||
/*
|
||||
u16 status = RunMysteryEventScript(gDecompressionBuffer);
|
||||
CpuFill32(0, gDecompressionBuffer, 0x7D4);
|
||||
|
||||
if (!GetEventLoadMessage(gStringVar4, status))
|
||||
TrySavingData(SAVE_NORMAL);
|
||||
*/
|
||||
gMain.state++;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -238,7 +238,7 @@ static u32 Client_Run(struct MysteryGiftClient * client)
|
||||
#endif //FREE_BATTLE_TOWER_E_READER
|
||||
break;
|
||||
case CLI_RUN_BUFFER_SCRIPT:
|
||||
memcpy(gDecompressionBuffer, client->recvBuffer, MG_LINK_BUFFER_SIZE);
|
||||
memcpy(client->bufferScript, client->recvBuffer, MG_LINK_BUFFER_SIZE);
|
||||
client->funcId = FUNC_RUN_BUFFER;
|
||||
client->funcState = 0;
|
||||
break;
|
||||
@ -279,7 +279,7 @@ static u32 Client_RunMysteryEventScript(struct MysteryGiftClient * client)
|
||||
static u32 Client_RunBufferScript(struct MysteryGiftClient * client)
|
||||
{
|
||||
// exec arbitrary code
|
||||
u32 (*func)(u32 *, struct SaveBlock2 *, struct SaveBlock1 *) = (void *)gDecompressionBuffer;
|
||||
u32 (*func)(u32 *, struct SaveBlock2 *, struct SaveBlock1 *) = (void *)client->bufferScript;
|
||||
if (func(&client->param, gSaveBlock2Ptr, gSaveBlock1Ptr) == 1)
|
||||
{
|
||||
client->funcId = FUNC_RUN;
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
#include "palette.h"
|
||||
#include "util.h"
|
||||
#include "decompress.h"
|
||||
#include "malloc.h"
|
||||
#include "menu.h"
|
||||
#include "gpu_regs.h"
|
||||
#include "task.h"
|
||||
#include "constants/rgb.h"
|
||||
@ -42,9 +44,9 @@ static const u8 sRoundedDownGrayscaleMap[] = {
|
||||
|
||||
void LoadCompressedPalette(const u32 *src, u32 offset, u32 size)
|
||||
{
|
||||
LZDecompressWram(src, gDecompressionBuffer);
|
||||
CpuCopy16(gDecompressionBuffer, &gPlttBufferUnfaded[offset], size);
|
||||
CpuCopy16(gDecompressionBuffer, &gPlttBufferFaded[offset], size);
|
||||
void *buffer = malloc_and_decompress(src, NULL);
|
||||
LoadPalette(buffer, offset, size);
|
||||
Free(buffer);
|
||||
}
|
||||
|
||||
void LoadPalette(const void *src, u32 offset, u32 size)
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
#include "recorded_battle.h"
|
||||
#include "rtc.h"
|
||||
#include "sound.h"
|
||||
#include "sprite.h"
|
||||
#include "string_util.h"
|
||||
#include "strings.h"
|
||||
#include "task.h"
|
||||
@ -676,7 +677,6 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
|
||||
};
|
||||
|
||||
#include "data/graphics/pokemon.h"
|
||||
#include "data/pokemon_graphics/front_pic_anims.h"
|
||||
|
||||
#include "data/pokemon/trainer_class_lookups.h"
|
||||
#include "data/pokemon/experience_tables.h"
|
||||
@ -706,7 +706,6 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
|
||||
#include "data/pokemon/form_species_tables.h"
|
||||
#include "data/pokemon/form_change_tables.h"
|
||||
#include "data/pokemon/form_change_table_pointers.h"
|
||||
#include "data/object_events/object_event_pic_tables_followers.h"
|
||||
|
||||
#include "data/pokemon/species_info.h"
|
||||
|
||||
|
||||
@ -743,10 +743,11 @@ static void BattleLoadOpponentMonSpriteGfxCustom(u16 species, bool8 isFemale, bo
|
||||
{
|
||||
const u32 *lzPaletteData = GetMonSpritePalFromSpecies(species, isShiny, isFemale);
|
||||
u16 paletteOffset = OBJ_PLTT_ID(battlerId);
|
||||
void *buffer = malloc_and_decompress(lzPaletteData, NULL);
|
||||
|
||||
LZDecompressWram(lzPaletteData, gDecompressionBuffer);
|
||||
LoadPalette(gDecompressionBuffer, paletteOffset, PLTT_SIZE_4BPP);
|
||||
LoadPalette(gDecompressionBuffer, BG_PLTT_ID(8) + BG_PLTT_ID(battlerId), PLTT_SIZE_4BPP);
|
||||
LoadPalette(buffer, paletteOffset, PLTT_SIZE_4BPP);
|
||||
LoadPalette(buffer, BG_PLTT_ID(8) + BG_PLTT_ID(battlerId), PLTT_SIZE_4BPP);
|
||||
Free(buffer);
|
||||
}
|
||||
|
||||
static void SetConstSpriteValues(struct PokemonSpriteVisualizer *data)
|
||||
|
||||
@ -59,9 +59,9 @@
|
||||
#define PSS_LABEL_WINDOW_CONTEST_MOVES_TITLE 3
|
||||
|
||||
// Button control text (upper right)
|
||||
#define PSS_LABEL_WINDOW_PROMPT_CANCEL 4 // Also handles the "rename" prompt if P_SUMMARY_SCREEN_RENAME is true
|
||||
#define PSS_LABEL_WINDOW_PROMPT_INFO 5
|
||||
#define PSS_LABEL_WINDOW_PROMPT_SWITCH 6
|
||||
#define PSS_LABEL_WINDOW_PROMPT_UTILITY 4 // Handles "Switch", "Info", and "Cancel" prompts. Also handles the "Rename" and "IVs"/"EVs"/"STATS" prompts if P_SUMMARY_SCREEN_RENAME and P_SUMMARY_SCREEN_IV_EV_INFO are true, respectively
|
||||
#define PSS_LABEL_WINDOW_PROMPT_INFO 5 // unused
|
||||
#define PSS_LABEL_WINDOW_PROMPT_SWITCH 6 // unused
|
||||
#define PSS_LABEL_WINDOW_UNUSED1 7
|
||||
|
||||
// Info screen
|
||||
@ -169,6 +169,7 @@ static EWRAM_DATA struct PokemonSummaryScreenData
|
||||
} summary;
|
||||
u16 bgTilemapBuffers[PSS_PAGE_COUNT][2][0x400];
|
||||
u8 mode;
|
||||
u8 skillsPageMode;
|
||||
bool8 isBoxMon;
|
||||
u8 curMonIndex;
|
||||
u8 maxMonIndex;
|
||||
@ -317,9 +318,22 @@ static void KeepMoveSelectorVisible(u8);
|
||||
static void SummaryScreen_DestroyAnimDelayTask(void);
|
||||
static bool32 ShouldShowMoveRelearner(void);
|
||||
static bool32 ShouldShowRename(void);
|
||||
static void ShowCancelOrRenamePrompt(void);
|
||||
static bool32 ShouldShowIvEvPrompt(void);
|
||||
static void BufferLeftColumnIvEvStats(void);
|
||||
static void CB2_ReturnToSummaryScreenFromNamingScreen(void);
|
||||
static void CB2_PssChangePokemonNickname(void);
|
||||
static void ShowUtilityPrompt(s16 mode);
|
||||
static void ShowMonSkillsInfo(u8 taskId, s16 mode);
|
||||
static void WriteToStatsTilemapBuffer(u32 length, u32 block, u32 statsCoordX, u32 statsCoordY);
|
||||
void ExtractMonSkillStatsData(struct Pokemon *mon, struct PokeSummary *sum);
|
||||
void ExtractMonSkillIvData(struct Pokemon *mon, struct PokeSummary *sum);
|
||||
void ExtractMonSkillEvData(struct Pokemon *mon, struct PokeSummary *sum);
|
||||
static void PrintTextOnWindow(u8 windowId, const u8 *string, u8 x, u8 y, u8 lineSpacing, u8 colorId);
|
||||
static void PrintTextOnWindowWithFont(u8 windowId, const u8 *string, u8 x, u8 y, u8 lineSpacing, u8 colorId, u32 fontId);
|
||||
static const u8 *GetLetterGrade(u32 stat);
|
||||
static u8 AddWindowFromTemplateList(const struct WindowTemplate *template, u8 templateId);
|
||||
static u8 IncrementSkillsStatsMode(u8 mode);
|
||||
static void ClearStatLabel(u32 length, u32 statsCoordX, u32 statsCoordY);
|
||||
|
||||
static const struct BgTemplate sBgTemplates[] =
|
||||
{
|
||||
@ -427,7 +441,7 @@ static const struct WindowTemplate sSummaryTemplate[] =
|
||||
.paletteNum = 6,
|
||||
.baseBlock = 67,
|
||||
},
|
||||
[PSS_LABEL_WINDOW_PROMPT_CANCEL] = {
|
||||
[PSS_LABEL_WINDOW_PROMPT_UTILITY] = {
|
||||
.bg = 0,
|
||||
.tilemapLeft = 22,
|
||||
.tilemapTop = 0,
|
||||
@ -731,6 +745,7 @@ static void (*const sTextPrinterTasks[])(u8 taskId) =
|
||||
static const u8 sMemoNatureTextColor[] = _("{COLOR LIGHT_RED}{SHADOW GREEN}");
|
||||
static const u8 sMemoMiscTextColor[] = _("{COLOR WHITE}{SHADOW DARK_GRAY}"); // This is also affected by palettes, apparently
|
||||
static const u8 sStatsLeftColumnLayout[] = _("{DYNAMIC 0}/{DYNAMIC 1}\n{DYNAMIC 2}\n{DYNAMIC 3}");
|
||||
static const u8 sStatsLeftIVEVColumnLayout[] = _("{DYNAMIC 0}\n{DYNAMIC 1}\n{DYNAMIC 2}");
|
||||
static const u8 sStatsRightColumnLayout[] = _("{DYNAMIC 0}\n{DYNAMIC 1}\n{DYNAMIC 2}");
|
||||
static const u8 sMovesPPLayout[] = _("{PP}{DYNAMIC 0}/{DYNAMIC 1}");
|
||||
|
||||
@ -1504,30 +1519,7 @@ static bool8 ExtractMonDataToSummaryStruct(struct Pokemon *mon)
|
||||
sum->ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES);
|
||||
break;
|
||||
case 2:
|
||||
if (sMonSummaryScreen->monList.mons == gPlayerParty || sMonSummaryScreen->mode == SUMMARY_MODE_BOX || sMonSummaryScreen->handleDeoxys == TRUE)
|
||||
{
|
||||
sum->nature = GetNature(mon);
|
||||
sum->mintNature = GetMonData(mon, MON_DATA_HIDDEN_NATURE);
|
||||
sum->currentHP = GetMonData(mon, MON_DATA_HP);
|
||||
sum->maxHP = GetMonData(mon, MON_DATA_MAX_HP);
|
||||
sum->atk = GetMonData(mon, MON_DATA_ATK);
|
||||
sum->def = GetMonData(mon, MON_DATA_DEF);
|
||||
sum->spatk = GetMonData(mon, MON_DATA_SPATK);
|
||||
sum->spdef = GetMonData(mon, MON_DATA_SPDEF);
|
||||
sum->speed = GetMonData(mon, MON_DATA_SPEED);
|
||||
}
|
||||
else
|
||||
{
|
||||
sum->nature = GetNature(mon);
|
||||
sum->mintNature = GetMonData(mon, MON_DATA_HIDDEN_NATURE);
|
||||
sum->currentHP = GetMonData(mon, MON_DATA_HP);
|
||||
sum->maxHP = GetMonData(mon, MON_DATA_MAX_HP);
|
||||
sum->atk = GetMonData(mon, MON_DATA_ATK2);
|
||||
sum->def = GetMonData(mon, MON_DATA_DEF2);
|
||||
sum->spatk = GetMonData(mon, MON_DATA_SPATK2);
|
||||
sum->spdef = GetMonData(mon, MON_DATA_SPDEF2);
|
||||
sum->speed = GetMonData(mon, MON_DATA_SPEED2);
|
||||
}
|
||||
ExtractMonSkillStatsData(mon, sum);
|
||||
break;
|
||||
case 3:
|
||||
GetMonData(mon, MON_DATA_OT_NAME, sum->OTName);
|
||||
@ -1640,6 +1632,58 @@ static void CloseSummaryScreen(u8 taskId)
|
||||
}
|
||||
}
|
||||
|
||||
// Update skills page tilemap
|
||||
static void ChangeStatLabel(s16 mode)
|
||||
{
|
||||
if (!P_SUMMARY_SCREEN_IV_EV_TILESET)
|
||||
return;
|
||||
|
||||
u32 statsBlock = 169;
|
||||
u32 ivsBlock = 221;
|
||||
u32 evsBlock = 218;
|
||||
|
||||
u32 statsCoordX = 44;
|
||||
u32 statsCoordY = 102;
|
||||
|
||||
u32 statsLength = 3;
|
||||
u32 ivEvLength = 2;
|
||||
|
||||
ClearStatLabel(statsLength, statsCoordX, statsCoordY);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case SUMMARY_SKILLS_MODE_STATS:
|
||||
WriteToStatsTilemapBuffer(statsLength, statsBlock, statsCoordX, statsCoordY);
|
||||
break;
|
||||
case SUMMARY_SKILLS_MODE_IVS:
|
||||
WriteToStatsTilemapBuffer(ivEvLength, ivsBlock, statsCoordX, statsCoordY);
|
||||
break;
|
||||
case SUMMARY_SKILLS_MODE_EVS:
|
||||
WriteToStatsTilemapBuffer(ivEvLength, evsBlock, statsCoordX, statsCoordY);
|
||||
break;
|
||||
}
|
||||
CopyBgTilemapBufferToVram(1);
|
||||
}
|
||||
|
||||
static void WriteToStatsTilemapBuffer(u32 length, u32 block, u32 statsCoordX, u32 statsCoordY)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i <= length; i++)
|
||||
FillBgTilemapBufferRect(1, block + i, statsCoordX + i, statsCoordY, 1, 1, 2);
|
||||
}
|
||||
|
||||
static void ClearStatLabel(u32 length, u32 statsCoordX, u32 statsCoordY)
|
||||
{
|
||||
u32 blankStatsBlock = 1241;
|
||||
|
||||
u32 i;
|
||||
u32 blankOffset = 3;
|
||||
|
||||
for (i = 0; i <= length; i++)
|
||||
FillBgTilemapBufferRect(1, blankStatsBlock, statsCoordX + blankOffset + i, statsCoordY, 1, 1, 2);
|
||||
}
|
||||
|
||||
static void Task_HandleInput(u8 taskId)
|
||||
{
|
||||
if (MenuHelpers_ShouldWaitForLinkRecv() != TRUE && !gPaletteFade.active)
|
||||
@ -1676,12 +1720,21 @@ static void Task_HandleInput(u8 taskId)
|
||||
PlaySE(SE_SELECT);
|
||||
BeginCloseSummaryScreen(taskId);
|
||||
}
|
||||
else // Contest or Battle Moves
|
||||
else if (sMonSummaryScreen->currPageIndex == PSS_PAGE_BATTLE_MOVES
|
||||
|| sMonSummaryScreen->currPageIndex == PSS_PAGE_CONTEST_MOVES)
|
||||
{
|
||||
PlaySE(SE_SELECT);
|
||||
SwitchToMoveSelection(taskId);
|
||||
}
|
||||
}
|
||||
if (sMonSummaryScreen->currPageIndex == PSS_PAGE_SKILLS)
|
||||
{
|
||||
if (ShouldShowIvEvPrompt())
|
||||
{
|
||||
ShowMonSkillsInfo(taskId, IncrementSkillsStatsMode(sMonSummaryScreen->skillsPageMode));
|
||||
PlaySE(SE_SELECT);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (JOY_NEW(B_BUTTON))
|
||||
{
|
||||
@ -1710,6 +1763,125 @@ static void Task_HandleInput(u8 taskId)
|
||||
}
|
||||
}
|
||||
|
||||
static u8 IncrementSkillsStatsMode(u8 mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case SUMMARY_SKILLS_MODE_STATS:
|
||||
if (P_SUMMARY_SCREEN_EV_ONLY)
|
||||
{
|
||||
sMonSummaryScreen->skillsPageMode = SUMMARY_SKILLS_MODE_EVS;
|
||||
return SUMMARY_SKILLS_MODE_EVS;
|
||||
}
|
||||
else
|
||||
{
|
||||
sMonSummaryScreen->skillsPageMode = SUMMARY_SKILLS_MODE_IVS;
|
||||
return SUMMARY_SKILLS_MODE_IVS;
|
||||
}
|
||||
|
||||
case SUMMARY_SKILLS_MODE_IVS:
|
||||
if (P_SUMMARY_SCREEN_IV_ONLY)
|
||||
{
|
||||
sMonSummaryScreen->skillsPageMode = SUMMARY_SKILLS_MODE_STATS;
|
||||
return SUMMARY_SKILLS_MODE_STATS;
|
||||
}
|
||||
else
|
||||
{
|
||||
sMonSummaryScreen->skillsPageMode = SUMMARY_SKILLS_MODE_EVS;
|
||||
return SUMMARY_SKILLS_MODE_EVS;
|
||||
}
|
||||
case SUMMARY_SKILLS_MODE_EVS:
|
||||
default:
|
||||
sMonSummaryScreen->skillsPageMode = SUMMARY_SKILLS_MODE_STATS;
|
||||
return SUMMARY_SKILLS_MODE_STATS;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void ShowMonSkillsInfo(u8 taskId, s16 mode)
|
||||
{
|
||||
struct PokeSummary *sum = &sMonSummaryScreen->summary;
|
||||
struct Pokemon *mon = &sMonSummaryScreen->currentMon;
|
||||
|
||||
FillWindowPixelBuffer(sMonSummaryScreen->windowIds[PSS_DATA_WINDOW_SKILLS_STATS_LEFT], 0);
|
||||
FillWindowPixelBuffer(sMonSummaryScreen->windowIds[PSS_DATA_WINDOW_SKILLS_STATS_RIGHT], 0);
|
||||
|
||||
if (sMonSummaryScreen->currPageIndex == PSS_PAGE_SKILLS)
|
||||
{
|
||||
ChangeStatLabel(mode);
|
||||
ShowUtilityPrompt(mode);
|
||||
}
|
||||
|
||||
if (mode == SUMMARY_SKILLS_MODE_STATS)
|
||||
{
|
||||
ExtractMonSkillStatsData(mon, sum);
|
||||
BufferLeftColumnStats();
|
||||
}
|
||||
else if (mode == SUMMARY_SKILLS_MODE_IVS)
|
||||
{
|
||||
ExtractMonSkillIvData(mon, sum);
|
||||
BufferLeftColumnIvEvStats();
|
||||
}
|
||||
else if (mode == SUMMARY_SKILLS_MODE_EVS)
|
||||
{
|
||||
ExtractMonSkillEvData(mon, sum);
|
||||
BufferLeftColumnIvEvStats();
|
||||
}
|
||||
|
||||
PrintLeftColumnStats();
|
||||
BufferRightColumnStats();
|
||||
PrintRightColumnStats();
|
||||
gTasks[taskId].func = Task_HandleInput;
|
||||
}
|
||||
|
||||
void ExtractMonSkillStatsData(struct Pokemon *mon, struct PokeSummary *sum)
|
||||
{
|
||||
if (sMonSummaryScreen->monList.mons == gPlayerParty || sMonSummaryScreen->mode == SUMMARY_MODE_BOX || sMonSummaryScreen->handleDeoxys == TRUE)
|
||||
{
|
||||
sum->nature = GetNature(mon);
|
||||
sum->mintNature = GetMonData(mon, MON_DATA_HIDDEN_NATURE);
|
||||
sum->currentHP = GetMonData(mon, MON_DATA_HP);
|
||||
sum->maxHP = GetMonData(mon, MON_DATA_MAX_HP);
|
||||
sum->atk = GetMonData(mon, MON_DATA_ATK);
|
||||
sum->def = GetMonData(mon, MON_DATA_DEF);
|
||||
sum->spatk = GetMonData(mon, MON_DATA_SPATK);
|
||||
sum->spdef = GetMonData(mon, MON_DATA_SPDEF);
|
||||
sum->speed = GetMonData(mon, MON_DATA_SPEED);
|
||||
}
|
||||
else
|
||||
{
|
||||
sum->nature = GetNature(mon);
|
||||
sum->mintNature = GetMonData(mon, MON_DATA_HIDDEN_NATURE);
|
||||
sum->currentHP = GetMonData(mon, MON_DATA_HP);
|
||||
sum->maxHP = GetMonData(mon, MON_DATA_MAX_HP);
|
||||
sum->atk = GetMonData(mon, MON_DATA_ATK2);
|
||||
sum->def = GetMonData(mon, MON_DATA_DEF2);
|
||||
sum->spatk = GetMonData(mon, MON_DATA_SPATK2);
|
||||
sum->spdef = GetMonData(mon, MON_DATA_SPDEF2);
|
||||
sum->speed = GetMonData(mon, MON_DATA_SPEED2);
|
||||
}
|
||||
}
|
||||
|
||||
void ExtractMonSkillIvData(struct Pokemon *mon, struct PokeSummary *sum)
|
||||
{
|
||||
sum->currentHP = GetMonData(mon, MON_DATA_HP_IV);
|
||||
sum->atk = GetMonData(mon, MON_DATA_ATK_IV);
|
||||
sum->def = GetMonData(mon, MON_DATA_DEF_IV);
|
||||
sum->spatk = GetMonData(mon, MON_DATA_SPATK_IV);
|
||||
sum->spdef = GetMonData(mon, MON_DATA_SPDEF_IV);
|
||||
sum->speed = GetMonData(mon, MON_DATA_SPEED_IV);
|
||||
}
|
||||
|
||||
void ExtractMonSkillEvData(struct Pokemon *mon, struct PokeSummary *sum)
|
||||
{
|
||||
sum->currentHP = GetMonData(mon, MON_DATA_HP_EV);
|
||||
sum->atk = GetMonData(mon, MON_DATA_ATK_EV);
|
||||
sum->def = GetMonData(mon, MON_DATA_DEF_EV);
|
||||
sum->spatk = GetMonData(mon, MON_DATA_SPATK_EV);
|
||||
sum->spdef = GetMonData(mon, MON_DATA_SPDEF_EV);
|
||||
sum->speed = GetMonData(mon, MON_DATA_SPEED_EV);
|
||||
}
|
||||
|
||||
static void ChangeSummaryPokemon(u8 taskId, s8 delta)
|
||||
{
|
||||
s8 monId;
|
||||
@ -1781,6 +1953,13 @@ static void Task_ChangeSummaryMon(u8 taskId)
|
||||
sMonSummaryScreen->switchCounter = 0;
|
||||
break;
|
||||
case 4:
|
||||
if (P_SUMMARY_SCREEN_RENAME && sMonSummaryScreen->currPageIndex == PSS_PAGE_INFO)
|
||||
ShowUtilityPrompt(SUMMARY_MODE_NORMAL);
|
||||
if (ShouldShowIvEvPrompt() && sMonSummaryScreen->currPageIndex == PSS_PAGE_SKILLS)
|
||||
{
|
||||
sMonSummaryScreen->skillsPageMode = SUMMARY_SKILLS_MODE_STATS;
|
||||
ChangeStatLabel(SUMMARY_SKILLS_MODE_STATS);
|
||||
}
|
||||
if (ExtractMonDataToSummaryStruct(&sMonSummaryScreen->currentMon) == FALSE)
|
||||
{
|
||||
return;
|
||||
@ -1826,12 +2005,6 @@ static void Task_ChangeSummaryMon(u8 taskId)
|
||||
case 11:
|
||||
PrintPageSpecificText(sMonSummaryScreen->currPageIndex);
|
||||
LimitEggSummaryPageDisplay();
|
||||
if (P_SUMMARY_SCREEN_RENAME && sMonSummaryScreen->currPageIndex == PSS_PAGE_INFO)
|
||||
{
|
||||
FillWindowPixelBuffer(PSS_LABEL_WINDOW_PROMPT_CANCEL, PIXEL_FILL(0));
|
||||
ShowCancelOrRenamePrompt();
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_CANCEL);
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
gSprites[sMonSummaryScreen->spriteIds[SPRITE_ARR_ID_MON]].data[2] = 0;
|
||||
@ -1934,6 +2107,24 @@ static void ChangePage(u8 taskId, s8 delta)
|
||||
SetTaskFuncWithFollowupFunc(taskId, PssScrollLeft, gTasks[taskId].func);
|
||||
CreateTextPrinterTask(sMonSummaryScreen->currPageIndex);
|
||||
HidePageSpecificSprites();
|
||||
|
||||
if (sMonSummaryScreen->currPageIndex == PSS_PAGE_SKILLS
|
||||
|| (sMonSummaryScreen->currPageIndex + delta) == PSS_PAGE_SKILLS)
|
||||
{
|
||||
struct Pokemon *mon = &sMonSummaryScreen->currentMon;
|
||||
|
||||
if (sMonSummaryScreen->skillsPageMode != SUMMARY_SKILLS_MODE_STATS)
|
||||
sMonSummaryScreen->skillsPageMode = SUMMARY_SKILLS_MODE_STATS;
|
||||
|
||||
ShowUtilityPrompt(sMonSummaryScreen->skillsPageMode);
|
||||
ExtractMonSkillStatsData(mon, summary);
|
||||
BufferLeftColumnStats();
|
||||
BufferRightColumnStats();
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowUtilityPrompt(SUMMARY_MODE_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
static void PssScrollRight(u8 taskId) // Scroll right
|
||||
@ -1982,6 +2173,9 @@ static void PssScrollRightEnd(u8 taskId) // display right
|
||||
static void PssScrollLeft(u8 taskId) // Scroll left
|
||||
{
|
||||
s16 *data = gTasks[taskId].data;
|
||||
// to fix a specific lag in writing to the stat label
|
||||
if (sMonSummaryScreen->currPageIndex == PSS_PAGE_SKILLS)
|
||||
ChangeStatLabel(SUMMARY_SKILLS_MODE_STATS);
|
||||
if (data[0] == 0)
|
||||
{
|
||||
if (sMonSummaryScreen->bgDisplayOrder == 0)
|
||||
@ -2045,13 +2239,19 @@ static void SwitchToMoveSelection(u8 taskId)
|
||||
ClearWindowTilemap(PSS_LABEL_WINDOW_POKEMON_SKILLS_STATUS);
|
||||
HandlePowerAccTilemap(9, -3);
|
||||
HandleAppealJamTilemap(9, -3, move);
|
||||
|
||||
if (!sMonSummaryScreen->lockMovesFlag)
|
||||
{
|
||||
ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_INFO);
|
||||
if (ShouldShowMoveRelearner())
|
||||
ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN);
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_SWITCH);
|
||||
|
||||
ShowUtilityPrompt(SUMMARY_MODE_SELECT_MOVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowUtilityPrompt(SUMMARY_MODE_NORMAL);
|
||||
}
|
||||
|
||||
TilemapFiveMovesDisplay(sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_BATTLE_MOVES][0], 3, FALSE);
|
||||
TilemapFiveMovesDisplay(sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_CONTEST_MOVES][0], 1, FALSE);
|
||||
PrintMoveDetails(move);
|
||||
@ -2083,14 +2283,16 @@ static void Task_HandleInput_MoveSelect(u8 taskId)
|
||||
else if (JOY_NEW(A_BUTTON))
|
||||
{
|
||||
if (sMonSummaryScreen->lockMovesFlag == TRUE
|
||||
|| (sMonSummaryScreen->newMove == MOVE_NONE && sMonSummaryScreen->firstMoveIndex == MAX_MON_MOVES))
|
||||
|| (sMonSummaryScreen->newMove == MOVE_NONE && sMonSummaryScreen->firstMoveIndex == MAX_MON_MOVES))
|
||||
{
|
||||
PlaySE(SE_SELECT);
|
||||
ShowUtilityPrompt(SUMMARY_MODE_NORMAL);
|
||||
CloseMoveSelectMode(taskId);
|
||||
}
|
||||
else if (HasMoreThanOneMove() == TRUE)
|
||||
{
|
||||
PlaySE(SE_SELECT);
|
||||
ShowUtilityPrompt(SUMMARY_MODE_SELECT_MOVE);
|
||||
SwitchToMovePositionSwitchMode(taskId);
|
||||
}
|
||||
else
|
||||
@ -2178,10 +2380,10 @@ static void ChangeSelectedMove(s16 *taskData, s8 direction, u8 *moveIndexPtr)
|
||||
static void CloseMoveSelectMode(u8 taskId)
|
||||
{
|
||||
DestroyMoveSelectorSprites(SPRITE_ARR_ID_MOVE_SELECTOR1);
|
||||
ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_SWITCH);
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_INFO);
|
||||
if (ShouldShowMoveRelearner())
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN);
|
||||
|
||||
ShowUtilityPrompt(SUMMARY_MODE_NORMAL);
|
||||
PrintMoveDetails(0);
|
||||
TilemapFiveMovesDisplay(sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_BATTLE_MOVES][0], 3, TRUE);
|
||||
TilemapFiveMovesDisplay(sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_CONTEST_MOVES][0], 1, TRUE);
|
||||
@ -2999,8 +3201,6 @@ static void PrintAOrBButtonIcon(u8 windowId, bool8 bButton, u32 x)
|
||||
|
||||
static void PrintPageNamesAndStats(void)
|
||||
{
|
||||
int stringXPos;
|
||||
int iconXPos;
|
||||
int statsXPos;
|
||||
|
||||
PrintTextOnWindow(PSS_LABEL_WINDOW_POKEMON_INFO_TITLE, gText_PkmnInfo, 2, 1, 0, 1);
|
||||
@ -3008,21 +3208,7 @@ static void PrintPageNamesAndStats(void)
|
||||
PrintTextOnWindow(PSS_LABEL_WINDOW_BATTLE_MOVES_TITLE, gText_BattleMoves, 2, 1, 0, 1);
|
||||
PrintTextOnWindow(PSS_LABEL_WINDOW_CONTEST_MOVES_TITLE, gText_ContestMoves, 2, 1, 0, 1);
|
||||
|
||||
ShowCancelOrRenamePrompt();
|
||||
|
||||
stringXPos = GetStringRightAlignXOffset(FONT_NORMAL, gText_Info, 62);
|
||||
iconXPos = stringXPos - 16;
|
||||
if (iconXPos < 0)
|
||||
iconXPos = 0;
|
||||
PrintAOrBButtonIcon(PSS_LABEL_WINDOW_PROMPT_INFO, FALSE, iconXPos);
|
||||
PrintTextOnWindow(PSS_LABEL_WINDOW_PROMPT_INFO, gText_Info, stringXPos, 1, 0, 0);
|
||||
|
||||
stringXPos = GetStringRightAlignXOffset(FONT_NORMAL, gText_Switch, 62);
|
||||
iconXPos = stringXPos - 16;
|
||||
if (iconXPos < 0)
|
||||
iconXPos = 0;
|
||||
PrintAOrBButtonIcon(PSS_LABEL_WINDOW_PROMPT_SWITCH, FALSE, iconXPos);
|
||||
PrintTextOnWindow(PSS_LABEL_WINDOW_PROMPT_SWITCH, gText_Switch, stringXPos, 1, 0, 0);
|
||||
ShowUtilityPrompt(SUMMARY_MODE_NORMAL);
|
||||
|
||||
PrintTextOnWindow(PSS_LABEL_WINDOW_POKEMON_INFO_RENTAL, gText_RentalPkmn, 0, 1, 0, 1);
|
||||
PrintTextOnWindow(PSS_LABEL_WINDOW_POKEMON_INFO_TYPE, gText_TypeSlash, 0, 1, 0, 0);
|
||||
@ -3061,7 +3247,7 @@ static void PutPageWindowTilemaps(u8 page)
|
||||
{
|
||||
case PSS_PAGE_INFO:
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_POKEMON_INFO_TITLE);
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_CANCEL);
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_UTILITY);
|
||||
if (InBattleFactory() == TRUE || InSlateportBattleTent() == TRUE)
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_POKEMON_INFO_RENTAL);
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_POKEMON_INFO_TYPE);
|
||||
@ -3071,9 +3257,12 @@ static void PutPageWindowTilemaps(u8 page)
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_POKEMON_SKILLS_STATS_LEFT);
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_POKEMON_SKILLS_STATS_RIGHT);
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_POKEMON_SKILLS_EXP);
|
||||
if (ShouldShowIvEvPrompt())
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_UTILITY);
|
||||
break;
|
||||
case PSS_PAGE_BATTLE_MOVES:
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_BATTLE_MOVES_TITLE);
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_UTILITY);
|
||||
if (sMonSummaryScreen->mode == SUMMARY_MODE_SELECT_MOVE)
|
||||
{
|
||||
if (sMonSummaryScreen->newMove != MOVE_NONE || sMonSummaryScreen->firstMoveIndex != MAX_MON_MOVES)
|
||||
@ -3081,13 +3270,13 @@ static void PutPageWindowTilemaps(u8 page)
|
||||
}
|
||||
else
|
||||
{
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_INFO);
|
||||
if (ShouldShowMoveRelearner())
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN);
|
||||
}
|
||||
break;
|
||||
case PSS_PAGE_CONTEST_MOVES:
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_CONTEST_MOVES_TITLE);
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_UTILITY);
|
||||
if (sMonSummaryScreen->mode == SUMMARY_MODE_SELECT_MOVE)
|
||||
{
|
||||
if (sMonSummaryScreen->newMove != MOVE_NONE || sMonSummaryScreen->firstMoveIndex != MAX_MON_MOVES)
|
||||
@ -3095,7 +3284,6 @@ static void PutPageWindowTilemaps(u8 page)
|
||||
}
|
||||
else
|
||||
{
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_INFO);
|
||||
if (ShouldShowMoveRelearner())
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN);
|
||||
}
|
||||
@ -3115,7 +3303,7 @@ static void ClearPageWindowTilemaps(u8 page)
|
||||
switch (page)
|
||||
{
|
||||
case PSS_PAGE_INFO:
|
||||
ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_CANCEL);
|
||||
ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_UTILITY);
|
||||
if (InBattleFactory() == TRUE || InSlateportBattleTent() == TRUE)
|
||||
ClearWindowTilemap(PSS_LABEL_WINDOW_POKEMON_INFO_RENTAL);
|
||||
ClearWindowTilemap(PSS_LABEL_WINDOW_POKEMON_INFO_TYPE);
|
||||
@ -3124,6 +3312,8 @@ static void ClearPageWindowTilemaps(u8 page)
|
||||
ClearWindowTilemap(PSS_LABEL_WINDOW_POKEMON_SKILLS_STATS_LEFT);
|
||||
ClearWindowTilemap(PSS_LABEL_WINDOW_POKEMON_SKILLS_STATS_RIGHT);
|
||||
ClearWindowTilemap(PSS_LABEL_WINDOW_POKEMON_SKILLS_EXP);
|
||||
if (ShouldShowIvEvPrompt())
|
||||
ClearPageWindowTilemaps(PSS_LABEL_WINDOW_PROMPT_UTILITY);
|
||||
break;
|
||||
case PSS_PAGE_BATTLE_MOVES:
|
||||
if (sMonSummaryScreen->mode == SUMMARY_MODE_SELECT_MOVE)
|
||||
@ -3136,7 +3326,6 @@ static void ClearPageWindowTilemaps(u8 page)
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_INFO);
|
||||
if (ShouldShowMoveRelearner())
|
||||
ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN);
|
||||
}
|
||||
@ -3149,7 +3338,6 @@ static void ClearPageWindowTilemaps(u8 page)
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_INFO);
|
||||
if (ShouldShowMoveRelearner())
|
||||
ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN);
|
||||
}
|
||||
@ -3477,6 +3665,8 @@ static void PrintSkillsPageText(void)
|
||||
{
|
||||
PrintHeldItemName();
|
||||
PrintRibbonCount();
|
||||
if(ShouldShowIvEvPrompt())
|
||||
ShowUtilityPrompt(SUMMARY_SKILLS_MODE_STATS);
|
||||
BufferLeftColumnStats();
|
||||
PrintLeftColumnStats();
|
||||
BufferRightColumnStats();
|
||||
@ -3497,21 +3687,24 @@ static void Task_PrintSkillsPage(u8 taskId)
|
||||
PrintRibbonCount();
|
||||
break;
|
||||
case 3:
|
||||
BufferLeftColumnStats();
|
||||
ChangeStatLabel(SUMMARY_SKILLS_MODE_STATS);
|
||||
break;
|
||||
case 4:
|
||||
PrintLeftColumnStats();
|
||||
BufferLeftColumnStats();
|
||||
break;
|
||||
case 5:
|
||||
BufferRightColumnStats();
|
||||
PrintLeftColumnStats();
|
||||
break;
|
||||
case 6:
|
||||
PrintRightColumnStats();
|
||||
BufferRightColumnStats();
|
||||
break;
|
||||
case 7:
|
||||
PrintExpPointsNextLevel();
|
||||
PrintRightColumnStats();
|
||||
break;
|
||||
case 8:
|
||||
PrintExpPointsNextLevel();
|
||||
break;
|
||||
case 9:
|
||||
DestroyTask(taskId);
|
||||
return;
|
||||
}
|
||||
@ -3581,10 +3774,38 @@ static void BufferStat(u8 *dst, u8 statIndex, u32 stat, u32 strId, u32 n)
|
||||
else
|
||||
txtPtr = StringCopy(dst, sTextNatureNeutral);
|
||||
|
||||
ConvertIntToDecimalStringN(txtPtr, stat, STR_CONV_MODE_RIGHT_ALIGN, n);
|
||||
if (!P_SUMMARY_SCREEN_IV_EV_VALUES
|
||||
&& sMonSummaryScreen->skillsPageMode == SUMMARY_SKILLS_MODE_IVS)
|
||||
StringAppend(dst, GetLetterGrade(stat));
|
||||
else
|
||||
ConvertIntToDecimalStringN(txtPtr, stat, STR_CONV_MODE_RIGHT_ALIGN, n);
|
||||
|
||||
DynamicPlaceholderTextUtil_SetPlaceholderPtr(strId, dst);
|
||||
}
|
||||
|
||||
static const u8 *GetLetterGrade(u32 stat)
|
||||
{
|
||||
static const u8 gText_GradeF[] = _("F");
|
||||
static const u8 gText_GradeD[] = _("D");
|
||||
static const u8 gText_GradeC[] = _("C");
|
||||
static const u8 gText_GradeB[] = _("B");
|
||||
static const u8 gText_GradeA[] = _("A");
|
||||
static const u8 gText_GradeS[] = _("S");
|
||||
|
||||
if (stat > 0 && stat <= 15)
|
||||
return gText_GradeD;
|
||||
else if (stat > 15 && stat <= 25)
|
||||
return gText_GradeC;
|
||||
else if (stat > 26 && stat <= 29)
|
||||
return gText_GradeB;
|
||||
else if (stat == 30)
|
||||
return gText_GradeA;
|
||||
else if (stat == 31)
|
||||
return gText_GradeS;
|
||||
else
|
||||
return gText_GradeF;
|
||||
}
|
||||
|
||||
static void BufferLeftColumnStats(void)
|
||||
{
|
||||
u8 *currentHPString = Alloc(20);
|
||||
@ -3593,10 +3814,12 @@ static void BufferLeftColumnStats(void)
|
||||
u8 *defenseString = Alloc(20);
|
||||
|
||||
DynamicPlaceholderTextUtil_Reset();
|
||||
BufferStat(currentHPString, 0, sMonSummaryScreen->summary.currentHP, 0, 3);
|
||||
BufferStat(maxHPString, 0, sMonSummaryScreen->summary.maxHP, 1, 3);
|
||||
|
||||
BufferStat(currentHPString, STAT_HP, sMonSummaryScreen->summary.currentHP, 0, 3);
|
||||
BufferStat(maxHPString, STAT_HP, sMonSummaryScreen->summary.maxHP, 1, 3);
|
||||
BufferStat(attackString, STAT_ATK, sMonSummaryScreen->summary.atk, 2, 7);
|
||||
BufferStat(defenseString, STAT_DEF, sMonSummaryScreen->summary.def, 3, 7);
|
||||
|
||||
DynamicPlaceholderTextUtil_ExpandPlaceholders(gStringVar4, sStatsLeftColumnLayout);
|
||||
|
||||
Free(currentHPString);
|
||||
@ -3605,23 +3828,58 @@ static void BufferLeftColumnStats(void)
|
||||
Free(defenseString);
|
||||
}
|
||||
|
||||
static void BufferLeftColumnIvEvStats(void)
|
||||
{
|
||||
u8 *hpIvEvString = Alloc(20);
|
||||
u8 *attackIvEvString = Alloc(20);
|
||||
u8 *defenseIvEvString = Alloc(20);
|
||||
|
||||
DynamicPlaceholderTextUtil_Reset();
|
||||
|
||||
BufferStat(hpIvEvString, STAT_HP, sMonSummaryScreen->summary.currentHP, 0, 7);
|
||||
BufferStat(attackIvEvString, STAT_ATK, sMonSummaryScreen->summary.atk, 1, 7);
|
||||
BufferStat(defenseIvEvString, STAT_DEF, sMonSummaryScreen->summary.def, 2, 7);
|
||||
|
||||
DynamicPlaceholderTextUtil_ExpandPlaceholders(gStringVar4, sStatsLeftIVEVColumnLayout);
|
||||
|
||||
Free(hpIvEvString);
|
||||
Free(attackIvEvString);
|
||||
Free(defenseIvEvString);
|
||||
}
|
||||
|
||||
static void PrintLeftColumnStats(void)
|
||||
{
|
||||
PrintTextOnWindow(AddWindowFromTemplateList(sPageSkillsTemplate, PSS_DATA_WINDOW_SKILLS_STATS_LEFT), gStringVar4, 4, 1, 0, 0);
|
||||
int x;
|
||||
|
||||
if (sMonSummaryScreen->skillsPageMode == SUMMARY_SKILLS_MODE_IVS && !P_SUMMARY_SCREEN_IV_EV_VALUES)
|
||||
x = GetStringRightAlignXOffset(FONT_NORMAL, gStringVar4, 46);
|
||||
else
|
||||
x = 4;
|
||||
|
||||
PrintTextOnWindow(AddWindowFromTemplateList(sPageSkillsTemplate, PSS_DATA_WINDOW_SKILLS_STATS_LEFT), gStringVar4, x, 1, 0, 0);
|
||||
}
|
||||
|
||||
static void BufferRightColumnStats(void)
|
||||
{
|
||||
DynamicPlaceholderTextUtil_Reset();
|
||||
|
||||
BufferStat(gStringVar1, STAT_SPATK, sMonSummaryScreen->summary.spatk, 0, 3);
|
||||
BufferStat(gStringVar2, STAT_SPDEF, sMonSummaryScreen->summary.spdef, 1, 3);
|
||||
BufferStat(gStringVar3, STAT_SPEED, sMonSummaryScreen->summary.speed, 2, 3);
|
||||
|
||||
DynamicPlaceholderTextUtil_ExpandPlaceholders(gStringVar4, sStatsRightColumnLayout);
|
||||
}
|
||||
|
||||
static void PrintRightColumnStats(void)
|
||||
{
|
||||
PrintTextOnWindow(AddWindowFromTemplateList(sPageSkillsTemplate, PSS_DATA_WINDOW_SKILLS_STATS_RIGHT), gStringVar4, 2, 1, 0, 0);
|
||||
int x;
|
||||
|
||||
if (sMonSummaryScreen->skillsPageMode == SUMMARY_SKILLS_MODE_IVS && !P_SUMMARY_SCREEN_IV_EV_VALUES)
|
||||
x = GetStringRightAlignXOffset(FONT_NORMAL, gStringVar4, 20);
|
||||
else
|
||||
x = 2;
|
||||
|
||||
PrintTextOnWindow(AddWindowFromTemplateList(sPageSkillsTemplate, PSS_DATA_WINDOW_SKILLS_STATS_RIGHT), gStringVar4, x, 1, 0, 0);
|
||||
}
|
||||
|
||||
static void PrintExpPointsNextLevel(void)
|
||||
@ -3651,7 +3909,6 @@ static void PrintBattleMoves(void)
|
||||
PrintMoveNameAndPP(1);
|
||||
PrintMoveNameAndPP(2);
|
||||
PrintMoveNameAndPP(3);
|
||||
|
||||
if (sMonSummaryScreen->mode == SUMMARY_MODE_SELECT_MOVE)
|
||||
{
|
||||
PrintNewMoveDetailsOrCancelText();
|
||||
@ -4385,6 +4642,7 @@ static inline bool32 ShouldShowMoveRelearner(void)
|
||||
{
|
||||
return (P_SUMMARY_SCREEN_MOVE_RELEARNER
|
||||
&& !sMonSummaryScreen->lockMovesFlag
|
||||
&& !sMonSummaryScreen->isBoxMon
|
||||
&& sMonSummaryScreen->mode != SUMMARY_MODE_BOX
|
||||
&& sMonSummaryScreen->mode != SUMMARY_MODE_BOX_CURSOR
|
||||
&& sMonSummaryScreen->relearnableMovesNum > 0
|
||||
@ -4397,6 +4655,7 @@ static inline bool32 ShouldShowRename(void)
|
||||
return (P_SUMMARY_SCREEN_RENAME
|
||||
&& !sMonSummaryScreen->lockMovesFlag
|
||||
&& !sMonSummaryScreen->summary.isEgg
|
||||
&& !sMonSummaryScreen->isBoxMon
|
||||
&& sMonSummaryScreen->mode != SUMMARY_MODE_BOX
|
||||
&& sMonSummaryScreen->mode != SUMMARY_MODE_BOX_CURSOR
|
||||
&& !InBattleFactory()
|
||||
@ -4404,17 +4663,84 @@ static inline bool32 ShouldShowRename(void)
|
||||
&& GetPlayerIDAsU32() == sMonSummaryScreen->summary.OTID);
|
||||
}
|
||||
|
||||
static void ShowCancelOrRenamePrompt(void)
|
||||
static inline bool32 ShouldShowIvEvPrompt(void)
|
||||
{
|
||||
const u8 *promptText = ShouldShowRename() ? gText_Rename : gText_Cancel2;
|
||||
if (P_SUMMARY_SCREEN_IV_EV_BOX_ONLY)
|
||||
{
|
||||
return (P_SUMMARY_SCREEN_IV_EV_INFO || FlagGet(P_FLAG_SUMMARY_SCREEN_IV_EV_INFO))
|
||||
&& (sMonSummaryScreen->mode == SUMMARY_MODE_BOX|| sMonSummaryScreen->mode == SUMMARY_MODE_BOX_CURSOR);
|
||||
}
|
||||
else if (!P_SUMMARY_SCREEN_IV_EV_BOX_ONLY)
|
||||
{
|
||||
return (P_SUMMARY_SCREEN_IV_EV_INFO || FlagGet(P_FLAG_SUMMARY_SCREEN_IV_EV_INFO));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline void ShowUtilityPrompt(s16 mode)
|
||||
{
|
||||
const u8* promptText = NULL;
|
||||
const u8* gText_SkillPageIvs = COMPOUND_STRING("IVs");
|
||||
const u8* gText_SkillPageEvs = COMPOUND_STRING("EVs");
|
||||
const u8* gText_SkillPageStats = COMPOUND_STRING("STATS");
|
||||
|
||||
if (sMonSummaryScreen->currPageIndex == PSS_PAGE_INFO)
|
||||
{
|
||||
if (ShouldShowRename())
|
||||
promptText = gText_Rename;
|
||||
else
|
||||
promptText = gText_Cancel2;
|
||||
}
|
||||
else if (sMonSummaryScreen->currPageIndex == PSS_PAGE_SKILLS)
|
||||
{
|
||||
if (ShouldShowIvEvPrompt())
|
||||
{
|
||||
if (mode == SUMMARY_SKILLS_MODE_STATS)
|
||||
{
|
||||
if (P_SUMMARY_SCREEN_EV_ONLY)
|
||||
promptText = gText_SkillPageEvs;
|
||||
else
|
||||
promptText = gText_SkillPageIvs;
|
||||
}
|
||||
else if (mode == SUMMARY_SKILLS_MODE_IVS)
|
||||
{
|
||||
if (P_SUMMARY_SCREEN_IV_ONLY)
|
||||
promptText = gText_SkillPageStats;
|
||||
else
|
||||
promptText = gText_SkillPageEvs;
|
||||
}
|
||||
else if (mode == SUMMARY_SKILLS_MODE_EVS)
|
||||
{
|
||||
promptText = gText_SkillPageStats;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sMonSummaryScreen->currPageIndex == PSS_PAGE_BATTLE_MOVES
|
||||
|| sMonSummaryScreen->currPageIndex == PSS_PAGE_CONTEST_MOVES)
|
||||
{
|
||||
if (mode == SUMMARY_MODE_SELECT_MOVE && !sMonSummaryScreen->lockMovesFlag)
|
||||
promptText = gText_Switch;
|
||||
else
|
||||
promptText = gText_Info;
|
||||
}
|
||||
|
||||
if (promptText == NULL)
|
||||
{
|
||||
ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_UTILITY);
|
||||
FillWindowPixelBuffer(PSS_LABEL_WINDOW_PROMPT_UTILITY, PIXEL_FILL(0));
|
||||
return;
|
||||
}
|
||||
|
||||
FillWindowPixelBuffer(PSS_LABEL_WINDOW_PROMPT_UTILITY, PIXEL_FILL(0));
|
||||
PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_UTILITY);
|
||||
|
||||
int stringXPos = GetStringRightAlignXOffset(FONT_NORMAL, promptText, 62);
|
||||
int iconXPos = stringXPos - 16;
|
||||
if (iconXPos < 0)
|
||||
iconXPos = 0;
|
||||
|
||||
PrintAOrBButtonIcon(PSS_LABEL_WINDOW_PROMPT_CANCEL, FALSE, iconXPos);
|
||||
PrintTextOnWindow(PSS_LABEL_WINDOW_PROMPT_CANCEL, promptText, stringXPos, 1, 0, 0);
|
||||
PrintAOrBButtonIcon(PSS_LABEL_WINDOW_PROMPT_UTILITY, FALSE, iconXPos);
|
||||
PrintTextOnWindow(PSS_LABEL_WINDOW_PROMPT_UTILITY, promptText, stringXPos, 1, 0, 0);
|
||||
}
|
||||
|
||||
static void CB2_ReturnToSummaryScreenFromNamingScreen(void)
|
||||
|
||||
@ -17,14 +17,15 @@ struct Pokenav_MainMenu
|
||||
{
|
||||
void (*loopTask)(u32);
|
||||
u32 (*isLoopTaskActiveFunc)(void);
|
||||
u32 unused;
|
||||
u32 currentTaskId;
|
||||
u32 helpBarWindowId;
|
||||
u32 palettes;
|
||||
struct Sprite *spinningPokenav;
|
||||
struct Sprite *leftHeaderSprites[2];
|
||||
struct Sprite *submenuLeftHeaderSprites[2];
|
||||
u8 tilemapBuffer[BG_SCREEN_SIZE];
|
||||
ALIGNED(4) u8 tilemapBuffer[BG_SCREEN_SIZE];
|
||||
ALIGNED(4) u8 leftHeaderMenuBuffer[0x1000];
|
||||
ALIGNED(4) u8 leftHeaderSubMenuBuffer[0x1000];
|
||||
};
|
||||
|
||||
// This struct uses a 32bit tag, and doesn't have a size field.
|
||||
@ -378,13 +379,11 @@ void SetActiveMenuLoopTasks(void *createLoopTask, void *isLoopTaskActive) // Fix
|
||||
struct Pokenav_MainMenu *menu = GetSubstructPtr(POKENAV_SUBSTRUCT_MAIN_MENU);
|
||||
menu->loopTask = createLoopTask;
|
||||
menu->isLoopTaskActiveFunc = isLoopTaskActive;
|
||||
menu->unused = 0;
|
||||
}
|
||||
|
||||
void RunMainMenuLoopedTask(u32 state)
|
||||
{
|
||||
struct Pokenav_MainMenu *menu = GetSubstructPtr(POKENAV_SUBSTRUCT_MAIN_MENU);
|
||||
menu->unused = 0;
|
||||
menu->loopTask(state);
|
||||
}
|
||||
|
||||
@ -686,8 +685,8 @@ static void LoadLeftHeaderGfxForMenu(u32 menuGfxId)
|
||||
tag = sMenuLeftHeaderSpriteSheets[menuGfxId].tag;
|
||||
size = GetDecompressedDataSize(sMenuLeftHeaderSpriteSheets[menuGfxId].data);
|
||||
LoadPalette(&gPokenavLeftHeader_Pal[tag * 16], OBJ_PLTT_ID(IndexOfSpritePaletteTag(1)), PLTT_SIZE_4BPP);
|
||||
LZ77UnCompWram(sMenuLeftHeaderSpriteSheets[menuGfxId].data, gDecompressionBuffer);
|
||||
RequestDma3Copy(gDecompressionBuffer, (void *)OBJ_VRAM0 + (GetSpriteTileStartByTag(2) * 32), size, 1);
|
||||
LZDecompressWram(sMenuLeftHeaderSpriteSheets[menuGfxId].data, menu->leftHeaderMenuBuffer);
|
||||
RequestDma3Copy(menu->leftHeaderMenuBuffer, (void *)OBJ_VRAM0 + (GetSpriteTileStartByTag(2) * 32), size, 1);
|
||||
menu->leftHeaderSprites[1]->oam.tileNum = GetSpriteTileStartByTag(2) + sMenuLeftHeaderSpriteSheets[menuGfxId].size;
|
||||
|
||||
if (menuGfxId == POKENAV_GFX_MAP_MENU_ZOOMED_OUT || menuGfxId == POKENAV_GFX_MAP_MENU_ZOOMED_IN)
|
||||
@ -698,16 +697,18 @@ static void LoadLeftHeaderGfxForMenu(u32 menuGfxId)
|
||||
|
||||
static void LoadLeftHeaderGfxForSubMenu(u32 menuGfxId)
|
||||
{
|
||||
struct Pokenav_MainMenu *menu;
|
||||
u32 size, tag;
|
||||
|
||||
if (menuGfxId >= POKENAV_GFX_MENUS_END - POKENAV_GFX_SUBMENUS_START)
|
||||
return;
|
||||
|
||||
menu = GetSubstructPtr(POKENAV_SUBSTRUCT_MAIN_MENU);
|
||||
tag = sPokenavSubMenuLeftHeaderSpriteSheets[menuGfxId].tag;
|
||||
size = GetDecompressedDataSize(sPokenavSubMenuLeftHeaderSpriteSheets[menuGfxId].data);
|
||||
LoadPalette(&gPokenavLeftHeader_Pal[tag * 16], OBJ_PLTT_ID(IndexOfSpritePaletteTag(2)), PLTT_SIZE_4BPP);
|
||||
LZ77UnCompWram(sPokenavSubMenuLeftHeaderSpriteSheets[menuGfxId].data, &gDecompressionBuffer[0x1000]);
|
||||
RequestDma3Copy(&gDecompressionBuffer[0x1000], (void *)OBJ_VRAM0 + 0x800 + (GetSpriteTileStartByTag(2) * 32), size, 1);
|
||||
LZDecompressWram(sPokenavSubMenuLeftHeaderSpriteSheets[menuGfxId].data, menu->leftHeaderSubMenuBuffer);
|
||||
RequestDma3Copy(menu->leftHeaderSubMenuBuffer, (void *)OBJ_VRAM0 + 0x800 + (GetSpriteTileStartByTag(2) * 32), size, 1);
|
||||
}
|
||||
|
||||
void ShowLeftHeaderGfx(u32 menuGfxId, bool32 isMain, bool32 isOnRightSide)
|
||||
|
||||