mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-11-16 11:37:40 +01:00
Merge branch 'RHH/dev' into RHH/pr/pretmerge_20220909
# Conflicts: # src/battle_interface.c
This commit is contained in:
commit
6b79c7772c
@ -79,6 +79,7 @@ SUPER_RE = A0
|
||||
'?' = AC
|
||||
'.' = AD
|
||||
'-' = AE
|
||||
'_' = AE @ For autogenerating strings based on label names. Not using {UNDERSCORE} on purpose due to how bad it looks.
|
||||
'·' = AF
|
||||
'…' = B0
|
||||
'“' = B1
|
||||
|
@ -24839,15 +24839,15 @@ General_PrimalReversion::
|
||||
jumpargeq 0x1, ITEM_BLUE_ORB, General_PrimalReversion_Alpha
|
||||
General_PrimalReversion_Alpha:
|
||||
loadspritegfx ANIM_TAG_ALPHA_STONE
|
||||
loadspritegfx ANIM_TAG_PRIMAL_PARTICLES
|
||||
loadspritegfx ANIM_TAG_MEGA_PARTICLES
|
||||
loadspritegfx ANIM_TAG_ALPHA_SYMBOL
|
||||
monbg ANIM_ATTACKER
|
||||
setalpha 12, 8
|
||||
loopsewithpan SE_M_MEGA_KICK, SOUND_PAN_ATTACKER, 13, 3
|
||||
createvisualtask AnimTask_BlendColorCycle, 2, 2, 0, 6, 0, 11, RGB(31, 31, 11)
|
||||
call PrimalReversionParticles
|
||||
call PrimalReversionParticles
|
||||
call PrimalReversionParticles
|
||||
call MegaEvolutionParticles
|
||||
call MegaEvolutionParticles
|
||||
call MegaEvolutionParticles
|
||||
waitforvisualfinish
|
||||
playsewithpan SE_M_SOLAR_BEAM, SOUND_PAN_ATTACKER
|
||||
createsprite gAlphaStoneSpriteTemplate, ANIM_ATTACKER, 41, 0, 0, 0, 0
|
||||
@ -24865,15 +24865,15 @@ General_PrimalReversion_Alpha:
|
||||
end
|
||||
General_PrimalReversion_Omega:
|
||||
loadspritegfx ANIM_TAG_OMEGA_STONE
|
||||
loadspritegfx ANIM_TAG_PRIMAL_PARTICLES
|
||||
loadspritegfx ANIM_TAG_MEGA_PARTICLES
|
||||
loadspritegfx ANIM_TAG_OMEGA_SYMBOL
|
||||
monbg ANIM_ATTACKER
|
||||
setalpha 12, 8
|
||||
loopsewithpan SE_M_MEGA_KICK, SOUND_PAN_ATTACKER, 13, 3
|
||||
createvisualtask AnimTask_BlendColorCycle, 2, 2, 0, 6, 0, 11, RGB(31, 31, 11)
|
||||
call PrimalReversionParticles
|
||||
call PrimalReversionParticles
|
||||
call PrimalReversionParticles
|
||||
call MegaEvolutionParticles
|
||||
call MegaEvolutionParticles
|
||||
call MegaEvolutionParticles
|
||||
waitforvisualfinish
|
||||
playsewithpan SE_M_SOLAR_BEAM, SOUND_PAN_ATTACKER
|
||||
createsprite gOmegaStoneSpriteTemplate, ANIM_ATTACKER, 41, 0, 0, 0, 0
|
||||
@ -24889,22 +24889,6 @@ General_PrimalReversion_Omega:
|
||||
clearmonbg ANIM_ATK_PARTNER
|
||||
blendoff
|
||||
end
|
||||
PrimalReversionParticles:
|
||||
createsprite gPrimalParticlesSpriteTemplate, ANIM_ATTACKER, 2, 40, -10, 13
|
||||
delay 3
|
||||
createsprite gPrimalParticlesSpriteTemplate, ANIM_ATTACKER, 2, -35, -10, 13
|
||||
delay 3
|
||||
createsprite gPrimalParticlesSpriteTemplate, ANIM_ATTACKER, 2, 15, -40, 13
|
||||
delay 3
|
||||
createsprite gPrimalParticlesSpriteTemplate, ANIM_ATTACKER, 2, -10, -32, 13
|
||||
delay 3
|
||||
createsprite gPrimalParticlesSpriteTemplate, ANIM_ATTACKER, 2, 25, -20, 13
|
||||
delay 3
|
||||
createsprite gPrimalParticlesSpriteTemplate, ANIM_ATTACKER, 2, -40, -20, 13
|
||||
delay 3
|
||||
createsprite gPrimalParticlesSpriteTemplate, ANIM_ATTACKER, 2, 5, -40, 13
|
||||
delay 3
|
||||
return
|
||||
|
||||
General_AffectionHangedOn::
|
||||
loadspritegfx ANIM_TAG_RED_HEART
|
||||
|
@ -225,6 +225,7 @@ BattleFrontier_BattleFactoryPreBattleRoom_EventScript_CommentOnOpponentType::
|
||||
call_if_eq VAR_0x8005, TYPE_ICE, BattleFrontier_BattleFactoryPreBattleRoom_EventScript_OpponentUsesIce
|
||||
call_if_eq VAR_0x8005, TYPE_DRAGON, BattleFrontier_BattleFactoryPreBattleRoom_EventScript_OpponentUsesDragon
|
||||
call_if_eq VAR_0x8005, TYPE_DARK, BattleFrontier_BattleFactoryPreBattleRoom_EventScript_OpponentUsesDark
|
||||
call_if_eq VAR_0x8005, TYPE_FAIRY, BattleFrontier_BattleFactoryPreBattleRoom_EventScript_OpponentUsesFairy
|
||||
call_if_eq VAR_0x8005, NUMBER_OF_MON_TYPES, BattleFrontier_BattleFactoryPreBattleRoom_EventScript_OpponentHasNoMostCommonType
|
||||
return
|
||||
|
||||
@ -296,6 +297,10 @@ BattleFrontier_BattleFactoryPreBattleRoom_EventScript_OpponentUsesDark::
|
||||
msgbox BattleFrontier_BattleFactoryPreBattleRoom_Text_TrainerSkilledInDarkType, MSGBOX_DEFAULT
|
||||
return
|
||||
|
||||
BattleFrontier_BattleFactoryPreBattleRoom_EventScript_OpponentUsesFairy::
|
||||
msgbox BattleFrontier_BattleFactoryPreBattleRoom_Text_TrainerSkilledInFairyType, MSGBOX_DEFAULT
|
||||
return
|
||||
|
||||
BattleFrontier_BattleFactoryPreBattleRoom_EventScript_OpponentHasNoMostCommonType::
|
||||
msgbox BattleFrontier_BattleFactoryPreBattleRoom_Text_TrainerHasNoClearFavorite, MSGBOX_DEFAULT
|
||||
return
|
||||
@ -559,6 +564,10 @@ BattleFrontier_BattleFactoryPreBattleRoom_Text_TrainerSkilledInDarkType:
|
||||
.string "The TRAINER is apparently skilled\n"
|
||||
.string "in the handling of the DARK type.$"
|
||||
|
||||
BattleFrontier_BattleFactoryPreBattleRoom_Text_TrainerSkilledInFairyType:
|
||||
.string "The TRAINER is apparently skilled\n"
|
||||
.string "in the handling of the FAIRY type.$"
|
||||
|
||||
BattleFrontier_BattleFactoryPreBattleRoom_Text_TrainerSkilledInSteelType:
|
||||
.string "The TRAINER is apparently skilled\n"
|
||||
.string "in the handling of the STEEL type.$"
|
||||
|
19
graphics/battle_anims/backgrounds/windstorm_brew.pal
Normal file
19
graphics/battle_anims/backgrounds/windstorm_brew.pal
Normal file
@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
230 148 98
|
||||
255 255 222
|
||||
230 230 197
|
||||
213 205 172
|
||||
189 180 148
|
||||
172 156 123
|
||||
156 131 106
|
||||
0 0 0
|
||||
0 0 0
|
||||
0 0 0
|
||||
142 204 143
|
||||
123 180 122
|
||||
112 165 99
|
||||
89 130 87
|
||||
67 114 65
|
||||
55 91 56
|
Binary file not shown.
Before Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 510 B |
@ -114,6 +114,7 @@ bool8 HasNoMonsToSwitch(u8 battlerId, u8 r1, u8 r2);
|
||||
u8 TryWeatherFormChange(u8 battlerId);
|
||||
bool32 TryChangeBattleWeather(u8 battler, u32 weatherEnumId, bool32 viaAbility);
|
||||
u8 AbilityBattleEffects(u8 caseID, u8 battlerId, u16 ability, u8 special, u16 moveArg);
|
||||
bool32 IsNeutralizingGasOnField(void);
|
||||
u32 GetBattlerAbility(u8 battlerId);
|
||||
u32 IsAbilityOnSide(u32 battlerId, u32 ability);
|
||||
u32 IsAbilityOnOpposingSide(u32 battlerId, u32 ability);
|
||||
|
@ -56,6 +56,7 @@
|
||||
#define AI_FLAG_STALL (1 << 13) // AI stalls battle and prefers secondary damage/trapping/etc. TODO not finished
|
||||
#define AI_FLAG_SCREENER (1 << 14) // AI prefers screening effects like reflect, mist, etc. TODO unfinished
|
||||
#define AI_FLAG_SMART_SWITCHING (1 << 15) // AI includes a lot more switching checks
|
||||
#define AI_FLAG_ACE_POKEMON (1 << 16) // AI has Ace Pokemon. The last Pokemon in the party will not used until last remaining.
|
||||
|
||||
// 'other' ai logic flags
|
||||
#define AI_FLAG_ROAMING (1 << 29)
|
||||
|
@ -392,9 +392,8 @@
|
||||
#define ANIM_TAG_STONE_PILLAR_MULTI (ANIM_SPRITES_START + 380)
|
||||
#define ANIM_TAG_ALPHA_SYMBOL (ANIM_SPRITES_START + 381)
|
||||
#define ANIM_TAG_OMEGA_SYMBOL (ANIM_SPRITES_START + 382)
|
||||
#define ANIM_TAG_PRIMAL_PARTICLES (ANIM_SPRITES_START + 383)
|
||||
#define ANIM_TAG_STEEL_BEAM (ANIM_SPRITES_START + 384)
|
||||
#define ANIM_TAG_POLTERGEIST (ANIM_SPRITES_START + 385)
|
||||
#define ANIM_TAG_STEEL_BEAM (ANIM_SPRITES_START + 383)
|
||||
#define ANIM_TAG_POLTERGEIST (ANIM_SPRITES_START + 384)
|
||||
|
||||
// battlers
|
||||
#define ANIM_ATTACKER 0
|
||||
|
@ -9631,8 +9631,6 @@ extern const u32 gBattleAnimSpriteGfx_MegaStone[];
|
||||
extern const u32 gBattleAnimSpritePal_MegaStone[];
|
||||
extern const u32 gBattleAnimSpriteGfx_MegaParticles[];
|
||||
extern const u32 gBattleAnimSpritePal_MegaParticles[];
|
||||
extern const u32 gBattleAnimSpriteGfx_PrimalParticles[];
|
||||
extern const u32 gBattleAnimSpritePal_PrimalParticles[];
|
||||
extern const u32 gBattleAnimSpriteGfx_MegaSymbol[];
|
||||
extern const u32 gBattleAnimSpritePal_MegaSymbol[];
|
||||
extern const u32 gBattleAnimSpriteGfx_FlashCannonBall[];
|
||||
@ -10085,9 +10083,6 @@ extern const u16 gSlotMachineReelTimePikachu_Pal[];
|
||||
extern const u32 gBattleAnimBgTilemap_Sandstorm[];
|
||||
extern const u32 gBattleAnimBgImage_Sandstorm[];
|
||||
|
||||
extern const u32 gBattleAnimBgTilemap_Windstorm[];
|
||||
extern const u32 gBattleAnimBgImage_Windstorm[];
|
||||
|
||||
// Pokedex Area Screen
|
||||
extern const u32 gPokedexAreaScreenAreaUnknown_Gfx[];
|
||||
extern const u16 gPokedexAreaScreenAreaUnknown_Pal[];
|
||||
|
@ -409,6 +409,7 @@ extern const u16 gUnionRoomFacilityClasses[];
|
||||
extern const struct SpriteTemplate gBattlerSpriteTemplates[];
|
||||
extern const s8 gNatureStatTable[][5];
|
||||
extern const u16 *const gFormSpeciesIdTables[NUM_SPECIES];
|
||||
extern const u32 sExpCandyExperienceTable[];
|
||||
|
||||
void ZeroBoxMonData(struct BoxPokemon *boxMon);
|
||||
void ZeroMonData(struct Pokemon *mon);
|
||||
|
@ -500,6 +500,7 @@ extern const u8 gText_StopLearningMove2[];
|
||||
extern const u8 gText_MoveNotLearned[];
|
||||
extern const u8 gText_PkmnElevatedToLvVar2[];
|
||||
extern const u8 gText_PkmnGainedExp[];
|
||||
extern const u8 gText_PkmnGainedExpAndElevatedToLvVar3[];
|
||||
extern const u8 gText_RemoveMailBeforeItem[];
|
||||
extern const u8 gText_PkmnHoldingItemCantHoldMail[];
|
||||
extern const u8 gText_MailTransferredFromMailbox[];
|
||||
|
@ -1,10 +1,13 @@
|
||||
#include "global.h"
|
||||
#include "battle.h"
|
||||
#include "constants/battle_ai.h"
|
||||
#include "battle_ai_main.h"
|
||||
#include "battle_ai_util.h"
|
||||
#include "battle_util.h"
|
||||
#include "battle_anim.h"
|
||||
#include "battle_controllers.h"
|
||||
#include "battle_main.h"
|
||||
#include "constants/hold_effects.h"
|
||||
#include "battle_setup.h"
|
||||
#include "data.h"
|
||||
#include "pokemon.h"
|
||||
@ -12,6 +15,7 @@
|
||||
#include "util.h"
|
||||
#include "constants/abilities.h"
|
||||
#include "constants/item_effects.h"
|
||||
#include "constants/battle_move_effects.h"
|
||||
#include "constants/items.h"
|
||||
#include "constants/moves.h"
|
||||
|
||||
@ -19,6 +23,7 @@
|
||||
static bool8 HasSuperEffectiveMoveAgainstOpponents(bool8 noRng);
|
||||
static bool8 FindMonWithFlagsAndSuperEffective(u16 flags, u8 moduloPercent);
|
||||
static bool8 ShouldUseItem(void);
|
||||
static bool32 AiExpectsToFaintPlayer(void);
|
||||
static bool32 AI_ShouldHeal(u32 healAmount);
|
||||
static bool32 AI_OpponentCanFaintAiWithMod(u32 healAmount);
|
||||
|
||||
@ -56,21 +61,6 @@ static bool8 ShouldSwitchIfAllBadMoves(void)
|
||||
}
|
||||
}
|
||||
|
||||
static bool8 ShouldSwitchIfPerishSong(void)
|
||||
{
|
||||
if (gStatuses3[gActiveBattler] & STATUS3_PERISH_SONG
|
||||
&& gDisableStructs[gActiveBattler].perishSongTimer == 0)
|
||||
{
|
||||
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = PARTY_SIZE;
|
||||
BtlController_EmitTwoReturnValues(BUFFER_B, B_ACTION_SWITCH, 0);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static bool8 ShouldSwitchIfWonderGuard(void)
|
||||
{
|
||||
u8 opposingPosition;
|
||||
@ -119,6 +109,9 @@ static bool8 ShouldSwitchIfWonderGuard(void)
|
||||
continue;
|
||||
if (i == gBattlerPartyIndexes[gActiveBattler])
|
||||
continue;
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||
&& i == (CalculateEnemyPartyCount()-1))
|
||||
continue;
|
||||
|
||||
for (opposingBattler = GetBattlerAtPosition(opposingPosition), j = 0; j < MAX_MON_MOVES; j++)
|
||||
{
|
||||
@ -180,7 +173,7 @@ static bool8 FindMonThatAbsorbsOpponentsMove(void)
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
if (AI_GetAbility(gActiveBattler) == absorbingTypeAbility)
|
||||
if (AI_DATA->abilities[gActiveBattler] == absorbingTypeAbility)
|
||||
return FALSE;
|
||||
|
||||
GetAIPartyIndexes(gActiveBattler, &firstId, &lastId);
|
||||
@ -209,6 +202,10 @@ static bool8 FindMonThatAbsorbsOpponentsMove(void)
|
||||
continue;
|
||||
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
||||
continue;
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||
&& i == (CalculateEnemyPartyCount()-1))
|
||||
continue;
|
||||
|
||||
|
||||
species = GetMonData(&party[i], MON_DATA_SPECIES);
|
||||
if (GetMonData(&party[i], MON_DATA_ABILITY_NUM) != 0)
|
||||
@ -228,43 +225,228 @@ static bool8 FindMonThatAbsorbsOpponentsMove(void)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool8 ShouldSwitchIfNaturalCure(void)
|
||||
static bool8 ShouldSwitchIfGameStatePrompt(void)
|
||||
{
|
||||
if (!(gBattleMons[gActiveBattler].status1 & STATUS1_SLEEP))
|
||||
return FALSE;
|
||||
if (AI_GetAbility(gActiveBattler) != ABILITY_NATURAL_CURE)
|
||||
return FALSE;
|
||||
if (gBattleMons[gActiveBattler].hp < gBattleMons[gActiveBattler].maxHP / 2)
|
||||
return FALSE;
|
||||
bool8 switchMon = FALSE;
|
||||
u16 monAbility = AI_DATA->abilities[gActiveBattler];
|
||||
u16 holdEffect = AI_DATA->holdEffects[gActiveBattler];
|
||||
u8 opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(gActiveBattler));
|
||||
u8 opposingBattler = GetBattlerAtPosition(opposingPosition);
|
||||
s32 moduloChance = 4; //25% Chance Default
|
||||
s32 chanceReducer = 1; //No Reduce default. Increase to reduce
|
||||
s32 firstId;
|
||||
s32 lastId;
|
||||
s32 i;
|
||||
struct Pokemon *party;
|
||||
|
||||
if ((gLastLandedMoves[gActiveBattler] == MOVE_NONE
|
||||
|| gLastLandedMoves[gActiveBattler] == MOVE_UNAVAILABLE)
|
||||
&& Random() & 1)
|
||||
|
||||
if (AnyStatIsRaised(gActiveBattler))
|
||||
chanceReducer = 5; // Reduce switchout probability by factor of 5 if setup
|
||||
|
||||
//Perish Song
|
||||
if (gStatuses3[gActiveBattler] & STATUS3_PERISH_SONG
|
||||
&& gDisableStructs[gActiveBattler].perishSongTimer == 0
|
||||
&& monAbility != ABILITY_SOUNDPROOF)
|
||||
switchMon = TRUE;
|
||||
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_SMART_SWITCHING)
|
||||
{
|
||||
//Yawn
|
||||
if (gStatuses3[gActiveBattler] & STATUS3_YAWN
|
||||
&& AI_CanSleep(gActiveBattler, monAbility)
|
||||
&& gBattleMons[gActiveBattler].hp > gBattleMons[gActiveBattler].maxHP / 3)
|
||||
{
|
||||
switchMon = TRUE;
|
||||
|
||||
//Double Battles
|
||||
//Check if partner can prevent sleep
|
||||
if (IsDoubleBattle())
|
||||
{
|
||||
if (IsBattlerAlive(BATTLE_PARTNER(gActiveBattler))
|
||||
&& (GetAIChosenMove(BATTLE_PARTNER(gActiveBattler)) == MOVE_UPROAR)
|
||||
)
|
||||
switchMon = FALSE;
|
||||
|
||||
if (IsBattlerAlive(BATTLE_PARTNER(gActiveBattler))
|
||||
&& (gBattleMoves[AI_DATA->partnerMove].effect == EFFECT_MISTY_TERRAIN
|
||||
|| gBattleMoves[AI_DATA->partnerMove].effect == EFFECT_ELECTRIC_TERRAIN)
|
||||
&& IsBattlerGrounded(gActiveBattler)
|
||||
)
|
||||
switchMon = FALSE;
|
||||
|
||||
if (*(gBattleStruct->AI_monToSwitchIntoId + BATTLE_PARTNER(gActiveBattler)) != PARTY_SIZE) //Partner is switching
|
||||
{
|
||||
GetAIPartyIndexes(gActiveBattler, &firstId, &lastId);
|
||||
|
||||
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
|
||||
party = gPlayerParty;
|
||||
|
||||
for (i = firstId; i < lastId; i++)
|
||||
{
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||
&& i == (CalculateEnemyPartyCount()-1))
|
||||
break;
|
||||
|
||||
//Look for mon in party that is able to be switched into and has ability that sets terrain
|
||||
if (GetMonData(&party[i], MON_DATA_HP) != 0
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_NONE
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_EGG
|
||||
&& i != gBattlerPartyIndexes[gActiveBattler]
|
||||
&& i != gBattlerPartyIndexes[BATTLE_PARTNER(gActiveBattler)]
|
||||
&& IsBattlerGrounded(gActiveBattler)
|
||||
&& (GetMonAbility(&party[i]) == ABILITY_MISTY_SURGE
|
||||
|| GetMonAbility(&party[i]) == ABILITY_ELECTRIC_SURGE)) //Ally has Misty or Electric Surge
|
||||
{
|
||||
*(gBattleStruct->AI_monToSwitchIntoId + BATTLE_PARTNER(gActiveBattler)) = i;
|
||||
BtlController_EmitTwoReturnValues(BUFFER_B, B_ACTION_SWITCH, 0);
|
||||
switchMon = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Check if Active Pokemon can KO opponent instead of switching
|
||||
//Will still fall asleep, but take out opposing Pokemon first
|
||||
if (AiExpectsToFaintPlayer())
|
||||
switchMon = FALSE;
|
||||
|
||||
//Checks to see if active Pokemon can do something against sleep
|
||||
if (monAbility == (ABILITY_NATURAL_CURE | ABILITY_SHED_SKIN | ABILITY_EARLY_BIRD)
|
||||
|| holdEffect == (HOLD_EFFECT_CURE_SLP | HOLD_EFFECT_CURE_STATUS)
|
||||
|| HasMove(gActiveBattler, MOVE_SLEEP_TALK)
|
||||
|| (HasMoveEffect(gActiveBattler, MOVE_SNORE) && AI_GetTypeEffectiveness(MOVE_SNORE, gActiveBattler, opposingBattler) >= UQ_4_12(1.0))
|
||||
|| (IsBattlerGrounded(gActiveBattler)
|
||||
&& (HasMove(gActiveBattler, MOVE_MISTY_TERRAIN) || HasMove(gActiveBattler, MOVE_ELECTRIC_TERRAIN)))
|
||||
)
|
||||
switchMon = FALSE;
|
||||
|
||||
//Check if Active Pokemon evasion boosted and might be able to dodge until awake
|
||||
if (gBattleMons[gActiveBattler].statStages[STAT_EVASION] > (DEFAULT_STAT_STAGE + 3)
|
||||
&& AI_DATA->abilities[opposingBattler] != ABILITY_UNAWARE
|
||||
&& AI_DATA->abilities[opposingBattler] != ABILITY_KEEN_EYE
|
||||
&& !(gBattleMons[gActiveBattler].status2 & STATUS2_FORESIGHT)
|
||||
&& !(gStatuses3[gActiveBattler] & STATUS3_MIRACLE_EYED))
|
||||
switchMon = FALSE;
|
||||
|
||||
}
|
||||
|
||||
//Secondary Damage
|
||||
if (monAbility != ABILITY_MAGIC_GUARD
|
||||
&& !AiExpectsToFaintPlayer())
|
||||
{
|
||||
//Toxic
|
||||
moduloChance = 2; //50%
|
||||
if (((gBattleMons[gActiveBattler].status1 & STATUS1_TOXIC_COUNTER) >= STATUS1_TOXIC_TURN(2))
|
||||
&& gBattleMons[gActiveBattler].hp >= (gBattleMons[gActiveBattler].maxHP / 3)
|
||||
&& (Random() % (moduloChance*chanceReducer)) == 0)
|
||||
switchMon = TRUE;
|
||||
|
||||
//Cursed
|
||||
moduloChance = 2; //50%
|
||||
if (gBattleMons[gActiveBattler].status2 & STATUS2_CURSED
|
||||
&& (Random() % (moduloChance*chanceReducer)) == 0)
|
||||
switchMon = TRUE;
|
||||
|
||||
//Nightmare
|
||||
moduloChance = 3; //33.3%
|
||||
if (gBattleMons[gActiveBattler].status2 & STATUS2_NIGHTMARE
|
||||
&& (Random() % (moduloChance*chanceReducer)) == 0)
|
||||
switchMon = TRUE;
|
||||
|
||||
//Leech Seed
|
||||
moduloChance = 4; //25%
|
||||
if (gStatuses3[gActiveBattler] & STATUS3_LEECHSEED
|
||||
&& (Random() % (moduloChance*chanceReducer)) == 0)
|
||||
switchMon = TRUE;
|
||||
}
|
||||
|
||||
//Infatuation
|
||||
if (gBattleMons[gActiveBattler].status2 & STATUS2_INFATUATION
|
||||
&& !AiExpectsToFaintPlayer())
|
||||
switchMon = TRUE;
|
||||
|
||||
//Todo
|
||||
//Pass Wish Heal
|
||||
|
||||
//Semi-Invulnerable
|
||||
if (gStatuses3[opposingBattler] & STATUS3_SEMI_INVULNERABLE)
|
||||
{
|
||||
if (FindMonThatAbsorbsOpponentsMove()) //If find absorber default to switch
|
||||
switchMon = TRUE;
|
||||
if (!AI_OpponentCanFaintAiWithMod(0)
|
||||
&& AnyStatIsRaised(gActiveBattler))
|
||||
switchMon = FALSE;
|
||||
if (AiExpectsToFaintPlayer()
|
||||
&& !WillAIStrikeFirst()
|
||||
&& !AI_OpponentCanFaintAiWithMod(0))
|
||||
switchMon = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (switchMon)
|
||||
{
|
||||
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = PARTY_SIZE;
|
||||
BtlController_EmitTwoReturnValues(BUFFER_B, B_ACTION_SWITCH, 0);
|
||||
return TRUE;
|
||||
}
|
||||
else if (IS_MOVE_STATUS(gLastLandedMoves[gActiveBattler]) && Random() & 1)
|
||||
else
|
||||
{
|
||||
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = PARTY_SIZE;
|
||||
BtlController_EmitTwoReturnValues(BUFFER_B, B_ACTION_SWITCH, 0);
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static bool8 ShouldSwitchIfAbilityBenefit(void)
|
||||
{
|
||||
s32 monToSwitchId;
|
||||
s32 moduloChance = 4; //25% Chance Default
|
||||
s32 chanceReducer = 1; //No Reduce default. Increase to reduce
|
||||
u8 battlerId = GetBattlerPosition(gActiveBattler);
|
||||
|
||||
if (AnyStatIsRaised(battlerId))
|
||||
chanceReducer = 5; // Reduce switchout probability by factor of 5 if setup
|
||||
|
||||
//Check if ability is blocked
|
||||
if (gStatuses3[gActiveBattler] & STATUS3_GASTRO_ACID
|
||||
||IsNeutralizingGasOnField())
|
||||
return FALSE;
|
||||
|
||||
switch(AI_DATA->abilities[gActiveBattler]) {
|
||||
case ABILITY_NATURAL_CURE:
|
||||
moduloChance = 4; //25%
|
||||
//Attempt to cure bad ailment
|
||||
if (gBattleMons[gActiveBattler].status1 & (STATUS1_SLEEP | STATUS1_FREEZE | STATUS1_TOXIC_POISON)
|
||||
&& GetMostSuitableMonToSwitchInto() != PARTY_SIZE)
|
||||
break;
|
||||
//Attempt to cure lesser ailment
|
||||
if ((gBattleMons[gActiveBattler].status1 & STATUS1_ANY)
|
||||
&& (gBattleMons[gActiveBattler].hp >= gBattleMons[gActiveBattler].maxHP / 2)
|
||||
&& GetMostSuitableMonToSwitchInto() != PARTY_SIZE
|
||||
&& Random() % (moduloChance*chanceReducer) == 0)
|
||||
break;
|
||||
|
||||
return FALSE;
|
||||
|
||||
case ABILITY_REGENERATOR:
|
||||
moduloChance = 2; //50%
|
||||
//Don't switch if ailment
|
||||
if (gBattleMons[gActiveBattler].status1 & STATUS1_ANY)
|
||||
return FALSE;
|
||||
if ((gBattleMons[gActiveBattler].hp <= ((gBattleMons[gActiveBattler].maxHP * 2) / 3))
|
||||
&& GetMostSuitableMonToSwitchInto() != PARTY_SIZE
|
||||
&& Random() % (moduloChance*chanceReducer) == 0)
|
||||
break;
|
||||
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (FindMonWithFlagsAndSuperEffective(MOVE_RESULT_DOESNT_AFFECT_FOE, 1))
|
||||
return TRUE;
|
||||
if (FindMonWithFlagsAndSuperEffective(MOVE_RESULT_NOT_VERY_EFFECTIVE, 1))
|
||||
return TRUE;
|
||||
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = PARTY_SIZE;
|
||||
BtlController_EmitTwoReturnValues(BUFFER_B, B_ACTION_SWITCH, 0);
|
||||
|
||||
if (Random() & 1)
|
||||
{
|
||||
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = PARTY_SIZE;
|
||||
BtlController_EmitTwoReturnValues(BUFFER_B, B_ACTION_SWITCH, 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool8 HasSuperEffectiveMoveAgainstOpponents(bool8 noRng)
|
||||
@ -392,6 +574,10 @@ static bool8 FindMonWithFlagsAndSuperEffective(u16 flags, u8 moduloPercent)
|
||||
continue;
|
||||
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
||||
continue;
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||
&& i == (CalculateEnemyPartyCount()-1))
|
||||
continue;
|
||||
|
||||
|
||||
species = GetMonData(&party[i], MON_DATA_SPECIES);
|
||||
if (GetMonData(&party[i], MON_DATA_ABILITY_NUM) != 0)
|
||||
@ -480,26 +666,42 @@ bool32 ShouldSwitch(void)
|
||||
continue;
|
||||
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
||||
continue;
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||
&& i == (CalculateEnemyPartyCount()-1))
|
||||
continue;
|
||||
|
||||
availableToSwitch++;
|
||||
}
|
||||
|
||||
if (availableToSwitch == 0)
|
||||
return FALSE;
|
||||
if (ShouldSwitchIfAllBadMoves())
|
||||
return TRUE;
|
||||
if (ShouldSwitchIfPerishSong())
|
||||
return TRUE;
|
||||
|
||||
//NOTE: The sequence of the below functions matter! Do not change unless you have carefully considered the outcome.
|
||||
//Since the order is sequencial, and some of these functions prompt switch to specific party members.
|
||||
|
||||
//These Functions can prompt switch to specific party members
|
||||
if (ShouldSwitchIfWonderGuard())
|
||||
return TRUE;
|
||||
if (ShouldSwitchIfGameStatePrompt())
|
||||
return TRUE;
|
||||
if (FindMonThatAbsorbsOpponentsMove())
|
||||
return TRUE;
|
||||
if (ShouldSwitchIfNaturalCure())
|
||||
|
||||
//These Functions can prompt switch to generic pary members
|
||||
if (ShouldSwitchIfAllBadMoves())
|
||||
return TRUE;
|
||||
if (ShouldSwitchIfAbilityBenefit())
|
||||
return TRUE;
|
||||
|
||||
//Removing switch capabilites under specific conditions
|
||||
//These Functions prevent the "FindMonWithFlagsAndSuperEffective" from getting out of hand.
|
||||
if (HasSuperEffectiveMoveAgainstOpponents(FALSE))
|
||||
return FALSE;
|
||||
if (AreStatsRaised())
|
||||
return FALSE;
|
||||
|
||||
//Default Function
|
||||
//Can prompt switch if AI has a pokemon in party that resists current opponent & has super effective move
|
||||
if (FindMonWithFlagsAndSuperEffective(MOVE_RESULT_DOESNT_AFFECT_FOE, 2)
|
||||
|| FindMonWithFlagsAndSuperEffective(MOVE_RESULT_NOT_VERY_EFFECTIVE, 3))
|
||||
return TRUE;
|
||||
@ -542,7 +744,7 @@ void AI_TrySwitchOrUseItem(void)
|
||||
|
||||
GetAIPartyIndexes(gActiveBattler, &firstId, &lastId);
|
||||
|
||||
for (monToSwitchId = firstId; monToSwitchId < lastId; monToSwitchId++)
|
||||
for (monToSwitchId = (lastId-1); monToSwitchId >= firstId; monToSwitchId--)
|
||||
{
|
||||
if (GetMonData(&party[monToSwitchId], MON_DATA_HP) == 0)
|
||||
continue;
|
||||
@ -554,6 +756,9 @@ void AI_TrySwitchOrUseItem(void)
|
||||
continue;
|
||||
if (monToSwitchId == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
||||
continue;
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||
&& monToSwitchId == (CalculateEnemyPartyCount()-1))
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
@ -751,7 +956,9 @@ u8 GetMostSuitableMonToSwitchInto(void)
|
||||
|| gBattlerPartyIndexes[battlerIn2] == i
|
||||
|| i == *(gBattleStruct->monToSwitchIntoId + battlerIn1)
|
||||
|| i == *(gBattleStruct->monToSwitchIntoId + battlerIn2)
|
||||
|| (GetMonAbility(&party[i]) == ABILITY_TRUANT && IsTruantMonVulnerable(gActiveBattler, opposingBattler))) // While not really invalid per say, not really wise to switch into this mon.
|
||||
|| (GetMonAbility(&party[i]) == ABILITY_TRUANT && IsTruantMonVulnerable(gActiveBattler, opposingBattler)) // While not really invalid per say, not really wise to switch into this mon.
|
||||
|| (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||
&& i == (CalculateEnemyPartyCount()-1))) //Save Ace Pokemon for last
|
||||
invalidMons |= gBitTable[i];
|
||||
else
|
||||
aliveCount++;
|
||||
|
@ -1239,17 +1239,6 @@ const struct SpriteTemplate gOmegaStoneSpriteTemplate =
|
||||
.callback = AnimSpriteOnMonPos,
|
||||
};
|
||||
|
||||
const struct SpriteTemplate gPrimalParticlesSpriteTemplate =
|
||||
{
|
||||
.tileTag = ANIM_TAG_PRIMAL_PARTICLES,
|
||||
.paletteTag = ANIM_TAG_PRIMAL_PARTICLES,
|
||||
.oam = &gOamData_AffineNormal_ObjBlend_16x16,
|
||||
.anims = gPowerAbsorptionOrbAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gPowerAbsorptionOrbAffineAnimTable,
|
||||
.callback = AnimPowerAbsorptionOrb,
|
||||
};
|
||||
|
||||
const struct SpriteTemplate gAlphaSymbolSpriteTemplate =
|
||||
{
|
||||
.tileTag = ANIM_TAG_ALPHA_SYMBOL,
|
||||
|
@ -1252,8 +1252,8 @@ void AnimTask_LoadWindstormBackground(u8 taskId)
|
||||
SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y);
|
||||
|
||||
GetBattleAnimBg1Data(&animBg);
|
||||
AnimLoadCompressedBgGfx(animBg.bgId, gBattleAnimBgImage_Windstorm, animBg.tilesOffset);
|
||||
AnimLoadCompressedBgTilemapHandleContest(&animBg, gBattleAnimBgTilemap_Windstorm, 0);
|
||||
AnimLoadCompressedBgGfx(animBg.bgId, gBattleAnimBgImage_Sandstorm, animBg.tilesOffset);
|
||||
AnimLoadCompressedBgTilemapHandleContest(&animBg, gBattleAnimBgTilemap_Sandstorm, 0);
|
||||
LoadCompressedPalette(gBattleAnimSpritePal_Windstorm, animBg.paletteId * 16, 32);
|
||||
|
||||
if (gBattleAnimArgs[0] && GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "battle.h"
|
||||
#include "battle_ai_main.h"
|
||||
#include "battle_ai_util.h"
|
||||
#include "constants/battle_ai.h"
|
||||
#include "battle_anim.h"
|
||||
#include "battle_arena.h"
|
||||
#include "battle_controllers.h"
|
||||
@ -94,6 +95,7 @@ static void OpponentHandleResetActionMoveSelection(void);
|
||||
static void OpponentHandleEndLinkBattle(void);
|
||||
static void OpponentHandleDebugMenu(void);
|
||||
static void OpponentCmdEnd(void);
|
||||
static u8 CountAIAliveNonEggMonsExcept(u8 slotToIgnore);
|
||||
|
||||
static void OpponentBufferRunCommand(void);
|
||||
static void OpponentBufferExecCompleted(void);
|
||||
@ -1668,6 +1670,7 @@ static void OpponentHandleChooseItem(void)
|
||||
static void OpponentHandleChoosePokemon(void)
|
||||
{
|
||||
s32 chosenMonId;
|
||||
s32 pokemonInBattle = 1;
|
||||
|
||||
if (*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) == PARTY_SIZE)
|
||||
{
|
||||
@ -1685,15 +1688,20 @@ static void OpponentHandleChoosePokemon(void)
|
||||
{
|
||||
battler1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
|
||||
battler2 = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
|
||||
pokemonInBattle = 2;
|
||||
|
||||
}
|
||||
|
||||
GetAIPartyIndexes(gActiveBattler, &firstId, &lastId);
|
||||
|
||||
for (chosenMonId = firstId; chosenMonId < lastId; chosenMonId++)
|
||||
for (chosenMonId = (lastId-1); chosenMonId >= firstId; chosenMonId--)
|
||||
{
|
||||
if (GetMonData(&gEnemyParty[chosenMonId], MON_DATA_HP) != 0
|
||||
&& chosenMonId != gBattlerPartyIndexes[battler1]
|
||||
&& chosenMonId != gBattlerPartyIndexes[battler2])
|
||||
&& chosenMonId != gBattlerPartyIndexes[battler2]
|
||||
&& (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||
&& (!(chosenMonId == (CalculateEnemyPartyCount()-1))
|
||||
|| CountAIAliveNonEggMonsExcept(PARTY_SIZE) == pokemonInBattle)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -1712,6 +1720,24 @@ static void OpponentHandleChoosePokemon(void)
|
||||
OpponentBufferExecCompleted();
|
||||
}
|
||||
|
||||
static u8 CountAIAliveNonEggMonsExcept(u8 slotToIgnore)
|
||||
{
|
||||
u16 i, count;
|
||||
|
||||
for (i = 0, count = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
if (i != slotToIgnore
|
||||
&& GetMonData(&gEnemyParty[i], MON_DATA_SPECIES) != SPECIES_NONE
|
||||
&& !GetMonData(&gEnemyParty[i], MON_DATA_IS_EGG)
|
||||
&& GetMonData(&gEnemyParty[i], MON_DATA_HP) != 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void OpponentHandleCmd23(void)
|
||||
{
|
||||
OpponentBufferExecCompleted();
|
||||
|
@ -3123,9 +3123,6 @@ void CreateAbilityPopUp(u8 battlerId, u32 ability, bool32 isDoubleBattle)
|
||||
const s16 (*coords)[2];
|
||||
u8 spriteId1, spriteId2, battlerPosition, taskId;
|
||||
|
||||
|
||||
return;
|
||||
|
||||
if (gBattleScripting.abilityPopupOverwrite != 0)
|
||||
ability = gBattleScripting.abilityPopupOverwrite;
|
||||
|
||||
|
@ -4744,8 +4744,9 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
}
|
||||
break;
|
||||
case ABILITY_INTREPID_SWORD:
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone)
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone && CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
gBattlerAttacker = battler;
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
SET_STATCHANGER(STAT_ATK, 1, FALSE);
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn);
|
||||
@ -4753,8 +4754,9 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
}
|
||||
break;
|
||||
case ABILITY_DAUNTLESS_SHIELD:
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone)
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone && CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
gBattlerAttacker = battler;
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
SET_STATCHANGER(STAT_DEF, 1, FALSE);
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn);
|
||||
|
@ -1448,7 +1448,6 @@ const struct CompressedSpriteSheet gBattleAnimPicTable[] =
|
||||
{gBattleAnimSpriteGfx_StonePillar, 0x1800, ANIM_TAG_STONE_PILLAR_MULTI},
|
||||
{gBattleAnimSpriteGfx_AlphaSymbol, 0x0200, ANIM_TAG_ALPHA_SYMBOL},
|
||||
{gBattleAnimSpriteGfx_OmegaSymbol, 0x0200, ANIM_TAG_OMEGA_SYMBOL},
|
||||
{gBattleAnimSpriteGfx_PrimalParticles, 0x0180, ANIM_TAG_PRIMAL_PARTICLES},
|
||||
{gBattleAnimSpriteGfx_Orbs, 0x0180, ANIM_TAG_STEEL_BEAM},
|
||||
{gBattleAnimSpriteGfx_AuraSphere, 0x200, ANIM_TAG_POLTERGEIST},
|
||||
};
|
||||
@ -1899,7 +1898,6 @@ const struct CompressedSpritePalette gBattleAnimPaletteTable[] =
|
||||
{gBattleAnimSpritePal_StonePillar, ANIM_TAG_STONE_PILLAR_MULTI},
|
||||
{gBattleAnimSpritePal_AlphaSymbol, ANIM_TAG_ALPHA_SYMBOL},
|
||||
{gBattleAnimSpritePal_OmegaSymbol, ANIM_TAG_OMEGA_SYMBOL},
|
||||
{gBattleAnimSpritePal_PrimalParticles, ANIM_TAG_PRIMAL_PARTICLES},
|
||||
{gBattleAnimSpritePal_SteelBeam, ANIM_TAG_STEEL_BEAM},
|
||||
{gBattleAnimSpritePal_Poltergeist, ANIM_TAG_POLTERGEIST},
|
||||
};
|
||||
|
@ -1560,7 +1560,7 @@ const struct Item gItems[] =
|
||||
{
|
||||
.name = _("Lure"),
|
||||
.itemId = ITEM_LURE,
|
||||
.price = 350,
|
||||
.price = 400,
|
||||
.holdEffectParam = 100,
|
||||
.description = sLureDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
@ -1574,7 +1574,7 @@ const struct Item gItems[] =
|
||||
{
|
||||
.name = _("Super Lure"),
|
||||
.itemId = ITEM_SUPER_LURE,
|
||||
.price = 500,
|
||||
.price = 700,
|
||||
.holdEffectParam = 200,
|
||||
.description = sSuperLureDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
@ -1588,7 +1588,7 @@ const struct Item gItems[] =
|
||||
{
|
||||
.name = _("Max Lure"),
|
||||
.itemId = ITEM_MAX_LURE,
|
||||
.price = 700,
|
||||
.price = 900,
|
||||
.holdEffectParam = 250,
|
||||
.description = sMaxLureDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
|
1
src/data/map_group_count.h
Normal file
1
src/data/map_group_count.h
Normal file
@ -0,0 +1 @@
|
||||
static const u8 MAP_GROUP_COUNT[] = {57, 5, 5, 6, 7, 8, 9, 7, 7, 14, 8, 17, 10, 23, 13, 15, 15, 2, 2, 2, 3, 1, 1, 1, 108, 61, 89, 2, 1, 13, 1, 1, 3, 1, 0};
|
@ -885,6 +885,7 @@ static const struct ListMenuItem sTradingBoardTypes[NUMBER_OF_MON_TYPES] = {
|
||||
{ gTypeNames[TYPE_DRAGON], TYPE_DRAGON },
|
||||
{ gTypeNames[TYPE_STEEL], TYPE_STEEL },
|
||||
{ gTypeNames[TYPE_DARK], TYPE_DARK },
|
||||
{ gTypeNames[TYPE_FAIRY], TYPE_FAIRY },
|
||||
{ sText_Exit, NUMBER_OF_MON_TYPES }
|
||||
};
|
||||
|
||||
|
1369
src/debug.c
1369
src/debug.c
File diff suppressed because it is too large
Load Diff
@ -201,6 +201,7 @@ int ProcessPlayerFieldInput(struct FieldInput *input)
|
||||
if (input->input_field_1_2)
|
||||
{
|
||||
PlaySE(SE_WIN_OPEN);
|
||||
FreezeObjectEvents();
|
||||
Debug_ShowMainMenu();
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -42,9 +42,6 @@ const u32 gBattleAnimSpritePal_AlphaSymbol[] = INCBIN_U32("graphics/battle_anims
|
||||
const u32 gBattleAnimSpriteGfx_OmegaSymbol[] = INCBIN_U32("graphics/battle_anims/sprites/omega_symbol.4bpp.lz");
|
||||
const u32 gBattleAnimSpritePal_OmegaSymbol[] = INCBIN_U32("graphics/battle_anims/sprites/omega_symbol.gbapal.lz");
|
||||
|
||||
const u32 gBattleAnimSpriteGfx_PrimalParticles[] = INCBIN_U32("graphics/battle_anims/sprites/primal_particles.4bpp.lz");
|
||||
const u32 gBattleAnimSpritePal_PrimalParticles[] = INCBIN_U32("graphics/battle_anims/sprites/primal_particles.gbapal.lz");
|
||||
|
||||
const u32 gBattleAnimSpriteGfx_FlashCannonBall[] = INCBIN_U32("graphics/battle_anims/sprites/flash_cannon_ball.4bpp.lz");
|
||||
const u32 gBattleAnimSpritePal_FlashCannonBall[] = INCBIN_U32("graphics/battle_anims/sprites/flash_cannon_ball.gbapal.lz");
|
||||
|
||||
@ -1309,8 +1306,6 @@ const u32 gBattleAnimSpritePal_FlyingDirt[] = INCBIN_U32("graphics/battle_anims/
|
||||
const u32 gBattleAnimBgTilemap_Sandstorm[] = INCBIN_U32("graphics/battle_anims/backgrounds/sandstorm_brew.bin.lz");
|
||||
const u32 gBattleAnimBgImage_Sandstorm[] = INCBIN_U32("graphics/battle_anims/backgrounds/sandstorm_brew.4bpp.lz");
|
||||
|
||||
const u32 gBattleAnimBgTilemap_Windstorm[] = INCBIN_U32("graphics/battle_anims/backgrounds/sandstorm_brew.bin.lz");
|
||||
const u32 gBattleAnimBgImage_Windstorm[] = INCBIN_U32("graphics/battle_anims/backgrounds/windstorm_brew.4bpp.lz");
|
||||
const u32 gBattleAnimSpritePal_Windstorm[] = INCBIN_U32("graphics/battle_anims/backgrounds/windstorm_brew.gbapal.lz");
|
||||
|
||||
const u32 gBattleAnimSpriteGfx_MetalSoundWaves[] = INCBIN_U32("graphics/battle_anims/sprites/metal_sound_waves.4bpp.lz");
|
||||
|
@ -5040,7 +5040,8 @@ static void CB2_ShowSummaryScreenToForgetMove(void)
|
||||
|
||||
static void CB2_ReturnToPartyMenuWhileLearningMove(void)
|
||||
{
|
||||
SetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_LEVEL, &sFinalLevel); // to avoid displaying incorrect level
|
||||
if (sFinalLevel != 0)
|
||||
SetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_LEVEL, &sFinalLevel); // to avoid displaying incorrect level
|
||||
InitPartyMenu(PARTY_MENU_TYPE_FIELD, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_MON, TRUE, PARTY_MSG_NONE, Task_ReturnToPartyMenuWhileLearningMove, gPartyMenu.exitCallback);
|
||||
}
|
||||
|
||||
@ -5139,6 +5140,16 @@ static void Task_TryLearningNextMoveAfterText(u8 taskId)
|
||||
Task_TryLearningNextMove(taskId);
|
||||
}
|
||||
|
||||
static void DisplayExpPoints(u8 taskId, TaskFunc task, u8 holdEffectParam)
|
||||
{
|
||||
PlaySE(SE_USE_ITEM);
|
||||
ConvertIntToDecimalStringN(gStringVar2, sExpCandyExperienceTable[holdEffectParam], STR_CONV_MODE_LEFT_ALIGN, 3);
|
||||
StringExpandPlaceholders(gStringVar4, gText_PkmnGainedExp);
|
||||
DisplayPartyMenuMessage(gStringVar4, FALSE);
|
||||
ScheduleBgCopyTilemapToVram(2);
|
||||
gTasks[taskId].func = task;
|
||||
}
|
||||
|
||||
void ItemUseCB_RareCandy(u8 taskId, TaskFunc task)
|
||||
{
|
||||
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
|
||||
@ -5146,6 +5157,7 @@ void ItemUseCB_RareCandy(u8 taskId, TaskFunc task)
|
||||
s16 *arrayPtr = ptr->data;
|
||||
u16 *itemPtr = &gSpecialVar_ItemId;
|
||||
bool8 cannotUseEffect;
|
||||
u8 holdEffectParam = ItemId_GetHoldEffectParam(*itemPtr);
|
||||
sInitialLevel = GetMonData(mon, MON_DATA_LEVEL);
|
||||
|
||||
if (sInitialLevel != MAX_LEVEL)
|
||||
@ -5176,8 +5188,18 @@ void ItemUseCB_RareCandy(u8 taskId, TaskFunc task)
|
||||
if (sFinalLevel > sInitialLevel)
|
||||
{
|
||||
PlayFanfareByFanfareNum(FANFARE_LEVEL_UP);
|
||||
ConvertIntToDecimalStringN(gStringVar2, sFinalLevel, STR_CONV_MODE_LEFT_ALIGN, 3);
|
||||
StringExpandPlaceholders(gStringVar4, gText_PkmnElevatedToLvVar2);
|
||||
if (holdEffectParam == 0) // Rare Candy
|
||||
{
|
||||
ConvertIntToDecimalStringN(gStringVar2, sFinalLevel, STR_CONV_MODE_LEFT_ALIGN, 3);
|
||||
StringExpandPlaceholders(gStringVar4, gText_PkmnElevatedToLvVar2);
|
||||
}
|
||||
else // Exp Candies
|
||||
{
|
||||
ConvertIntToDecimalStringN(gStringVar2, sExpCandyExperienceTable[holdEffectParam - 1], STR_CONV_MODE_LEFT_ALIGN, 6);
|
||||
ConvertIntToDecimalStringN(gStringVar3, sFinalLevel, STR_CONV_MODE_LEFT_ALIGN, 3);
|
||||
StringExpandPlaceholders(gStringVar4, gText_PkmnGainedExpAndElevatedToLvVar3);
|
||||
}
|
||||
|
||||
DisplayPartyMenuMessage(gStringVar4, TRUE);
|
||||
ScheduleBgCopyTilemapToVram(2);
|
||||
gTasks[taskId].func = Task_DisplayLevelUpStatsPg1;
|
||||
@ -5186,6 +5208,7 @@ void ItemUseCB_RareCandy(u8 taskId, TaskFunc task)
|
||||
{
|
||||
PlaySE(SE_USE_ITEM);
|
||||
gPartyMenuUseExitCallback = FALSE;
|
||||
ConvertIntToDecimalStringN(gStringVar2, sExpCandyExperienceTable[holdEffectParam - 1], STR_CONV_MODE_LEFT_ALIGN, 6);
|
||||
StringExpandPlaceholders(gStringVar4, gText_PkmnGainedExp);
|
||||
DisplayPartyMenuMessage(gStringVar4, FALSE);
|
||||
ScheduleBgCopyTilemapToVram(2);
|
||||
@ -5291,11 +5314,14 @@ static void Task_TryLearningNextMove(u8 taskId)
|
||||
switch (result)
|
||||
{
|
||||
case 0: // No moves to learn
|
||||
if (sInitialLevel >= sFinalLevel)
|
||||
PartyMenuTryEvolution(taskId);
|
||||
break;
|
||||
case MON_HAS_MAX_MOVES:
|
||||
DisplayMonNeedsToReplaceMove(taskId);
|
||||
break;
|
||||
case MON_ALREADY_KNOWS_MOVE:
|
||||
gTasks[taskId].func = Task_TryLearningNextMove;
|
||||
return;
|
||||
default:
|
||||
DisplayMonLearnedMove(taskId, result);
|
||||
@ -5304,8 +5330,6 @@ static void Task_TryLearningNextMove(u8 taskId)
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
if (sInitialLevel >= sFinalLevel)
|
||||
PartyMenuTryEvolution(taskId);
|
||||
}
|
||||
|
||||
static void PartyMenuTryEvolution(u8 taskId)
|
||||
@ -5313,6 +5337,10 @@ static void PartyMenuTryEvolution(u8 taskId)
|
||||
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
|
||||
u16 targetSpecies = GetEvolutionTargetSpecies(mon, EVO_MODE_NORMAL, ITEM_NONE, NULL);
|
||||
|
||||
// Resets values to 0 so other means of teaching moves doesn't overwrite levels
|
||||
sInitialLevel = 0;
|
||||
sFinalLevel = 0;
|
||||
|
||||
if (targetSpecies != SPECIES_NONE)
|
||||
{
|
||||
FreePartyPointers();
|
||||
|
@ -5515,7 +5515,7 @@ bool8 ExecuteTableBasedItemEffect(struct Pokemon *mon, u16 item, u8 partyIndex,
|
||||
#endif
|
||||
|
||||
// EXP candies store an index for this table in their holdEffectParam.
|
||||
static const u32 sExpCandyExperienceTable[] = {
|
||||
const u32 sExpCandyExperienceTable[] = {
|
||||
[EXP_100 - 1] = 100,
|
||||
[EXP_800 - 1] = 800,
|
||||
[EXP_3000 - 1] = 3000,
|
||||
@ -5704,20 +5704,26 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
|
||||
&& GetMonData(mon, MON_DATA_LEVEL, NULL) != MAX_LEVEL)
|
||||
{
|
||||
u8 param = ItemId_GetHoldEffectParam(item);
|
||||
dataUnsigned = 0;
|
||||
|
||||
if (param == 0) // Rare Candy
|
||||
{
|
||||
dataUnsigned = gExperienceTables[gBaseStats[GetMonData(mon, MON_DATA_SPECIES, NULL)].growthRate][GetMonData(mon, MON_DATA_LEVEL, NULL) + 1];
|
||||
}
|
||||
else if (param < ARRAY_COUNT(sExpCandyExperienceTable)) // EXP Candies
|
||||
else if (param - 1 < ARRAY_COUNT(sExpCandyExperienceTable)) // EXP Candies
|
||||
{
|
||||
u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL);
|
||||
dataUnsigned = sExpCandyExperienceTable[param - 1] + GetMonData(mon, MON_DATA_EXP, NULL);
|
||||
if (dataUnsigned > gExperienceTables[gBaseStats[species].growthRate][MAX_LEVEL])
|
||||
dataUnsigned = gExperienceTables[gBaseStats[species].growthRate][MAX_LEVEL];
|
||||
}
|
||||
SetMonData(mon, MON_DATA_EXP, &dataUnsigned);
|
||||
CalculateMonStats(mon);
|
||||
retVal = FALSE;
|
||||
|
||||
if (dataUnsigned != 0) // Failsafe
|
||||
{
|
||||
SetMonData(mon, MON_DATA_EXP, &dataUnsigned);
|
||||
CalculateMonStats(mon);
|
||||
retVal = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Cure status
|
||||
|
@ -761,6 +761,7 @@ static bool8 StartMenuDebugCallback(void)
|
||||
HideStartMenuDebug(); // Hide start menu without enabling movement
|
||||
|
||||
#if DEBUG_SYSTEM_ENABLE == TRUE
|
||||
FreezeObjectEvents();
|
||||
Debug_ShowMainMenu();
|
||||
#endif
|
||||
|
||||
|
@ -417,7 +417,8 @@ const u8 gText_PkmnRegainhedHealth[] = _("{STR_VAR_1} regained health.{PAUSE_UNT
|
||||
const u8 gText_PkmnBecameHealthy[] = _("{STR_VAR_1} became healthy.{PAUSE_UNTIL_PRESS}");
|
||||
const u8 gText_MovesPPIncreased[] = _("{STR_VAR_1}'s PP increased.{PAUSE_UNTIL_PRESS}");
|
||||
const u8 gText_PkmnElevatedToLvVar2[] = _("{STR_VAR_1} was elevated to\nLv. {STR_VAR_2}.");
|
||||
const u8 gText_PkmnGainedExp[] = _("{STR_VAR_1} gained Exp. Points!{PAUSE_UNTIL_PRESS}");
|
||||
const u8 gText_PkmnGainedExp[] = _("{STR_VAR_1} gained {STR_VAR_2} Exp. Points!{PAUSE_UNTIL_PRESS}");
|
||||
const u8 gText_PkmnGainedExpAndElevatedToLvVar3[] = _("{STR_VAR_1} gained {STR_VAR_2} Exp. Points\nand was elevated to Lv. {STR_VAR_3}!");
|
||||
const u8 gText_PkmnBaseVar2StatIncreased[] = _("{STR_VAR_1}'s base {STR_VAR_2}\nstat was raised.{PAUSE_UNTIL_PRESS}");
|
||||
const u8 gText_PkmnFriendlyBaseVar2Fell[] = _("{STR_VAR_1} turned friendly.\nThe base {STR_VAR_2} fell!{PAUSE_UNTIL_PRESS}");
|
||||
const u8 gText_PkmnAdoresBaseVar2Fell[] = _("{STR_VAR_1} adores you!\nThe base {STR_VAR_2} fell!{PAUSE_UNTIL_PRESS}");
|
||||
|
@ -386,6 +386,7 @@ string generate_map_constants_text(string groups_filepath, Json groups_data) {
|
||||
char dir_separator = file_dir.back();
|
||||
|
||||
ostringstream text;
|
||||
ostringstream mapCountText;
|
||||
|
||||
text << "#ifndef GUARD_CONSTANTS_MAP_GROUPS_H\n"
|
||||
<< "#define GUARD_CONSTANTS_MAP_GROUPS_H\n\n";
|
||||
@ -424,15 +425,16 @@ string generate_map_constants_text(string groups_filepath, Json groups_data) {
|
||||
}
|
||||
|
||||
text << "#define MAP_GROUPS_COUNT " << group_num << "\n\n";
|
||||
|
||||
text << "// static const u8 MAP_GROUP_COUNT[] = {"; //DEBUG
|
||||
for(int i=0; i<group_num; i++){ //DEBUG
|
||||
text << map_count_vec[i] << ", "; //DEBUG
|
||||
} //DEBUG
|
||||
text << "0};\n\n"; //DEBUG
|
||||
|
||||
text << "#endif // GUARD_CONSTANTS_MAP_GROUPS_H\n";
|
||||
|
||||
char s = file_dir.back();
|
||||
mapCountText << "static const u8 MAP_GROUP_COUNT[] = {"; //DEBUG
|
||||
for(int i=0; i<group_num; i++){ //DEBUG
|
||||
mapCountText << map_count_vec[i] << ", "; //DEBUG
|
||||
} //DEBUG
|
||||
mapCountText << "0};\n"; //DEBUG
|
||||
write_text_file(file_dir + ".." + s + ".." + s + "src" + s + "data" + s + "map_group_count.h", mapCountText.str());
|
||||
|
||||
return text.str();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user