mirror of
https://github.com/rh-hideout/pokeemerald-expansion.git
synced 2026-03-21 18:04:50 -05:00
Merge 81d40504ac into 264d99215b
This commit is contained in:
commit
0d1d51d050
|
|
@ -103,9 +103,8 @@
|
|||
setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SET_DATA
|
||||
setvar VAR_0x8005, FRONTIER_DATA_SELECTED_MON_ORDER
|
||||
special CallFrontierUtilFunc @ saves the mon order, so the non-selected mons get restored afterwards
|
||||
setvar VAR_0x8004, SPECIAL_BATTLE_MULTI
|
||||
setvar VAR_0x8005, \type | MULTI_BATTLE_CHOOSE_MONS
|
||||
special DoSpecialTrainerBattle
|
||||
callnative BattleSetup_StartMultiBattle
|
||||
waitstate
|
||||
setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SAVE_PARTY
|
||||
special CallFrontierUtilFunc
|
||||
|
|
@ -132,9 +131,8 @@
|
|||
.endm
|
||||
|
||||
.macro multi_do_fixed type:req
|
||||
setvar VAR_0x8004, SPECIAL_BATTLE_MULTI
|
||||
setvar VAR_0x8005, \type
|
||||
special DoSpecialTrainerBattle
|
||||
callnative BattleSetup_StartMultiBattle
|
||||
waitstate
|
||||
setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SAVE_PARTY
|
||||
special CallFrontierUtilFunc
|
||||
|
|
|
|||
|
|
@ -1599,6 +1599,22 @@
|
|||
@ Starts a wild battle against the Pokemon generated by setwildbattle. Blocks script execution until the battle finishes.
|
||||
.macro dowildbattle
|
||||
.byte SCR_OP_DOWILDBATTLE
|
||||
.byte SPECIAL_WILD_NONE
|
||||
.endm
|
||||
|
||||
.macro startlegendarybattle
|
||||
.byte SCR_OP_DOWILDBATTLE
|
||||
.byte SPECIAL_WILD_LEGENDARY
|
||||
.endm
|
||||
|
||||
.macro startcatchtutorial
|
||||
.byte SCR_OP_DOWILDBATTLE
|
||||
.byte SPECIAL_WILD_CATCH_TUTORIAL
|
||||
.endm
|
||||
|
||||
.macro startghostbattle
|
||||
.byte SCR_OP_DOWILDBATTLE
|
||||
.byte SPECIAL_WILD_GHOST
|
||||
.endm
|
||||
|
||||
@ Sets a relative address to be used by the other vcommands as part of a Mystery Gift script.
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
#include "constants/battle_pike.h"
|
||||
#include "constants/battle_pyramid.h"
|
||||
#include "constants/battle_setup.h"
|
||||
#include "constants/battle_special.h"
|
||||
#include "constants/battle_tent.h"
|
||||
#include "constants/battle_tower.h"
|
||||
#include "constants/berry.h"
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ AncientTomb_EventScript_Registeel::
|
|||
waitmoncry
|
||||
setwildbattle SPECIES_REGISTEEL, 40
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special StartRegiBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
specialvar VAR_RESULT, GetBattleOutcome
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ BirthIsland_Exterior_EventScript_Deoxys::
|
|||
setvar VAR_LAST_TALKED, LOCALID_BIRTH_ISLAND_DEOXYS
|
||||
seteventmon SPECIES_DEOXYS_NORMAL, 30
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special BattleSetup_StartLegendaryBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
specialvar VAR_RESULT, GetBattleOutcome
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ BirthIsland_Exterior_Frlg_EventScript_Deoxys::
|
|||
setvar VAR_LAST_TALKED, LOCALID_BIRTH_ISLAND_DEOXYS
|
||||
seteventmon SPECIES_DEOXYS, 30
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special BattleSetup_StartLegendaryBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
specialvar VAR_RESULT, GetBattleOutcome
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ CeruleanCave_B1F_EventScript_Mewtwo::
|
|||
waitbuttonpress
|
||||
setwildbattle SPECIES_MEWTWO, 70
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special BattleSetup_StartLegendaryBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
specialvar VAR_RESULT, GetBattleOutcome
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ DesertRuins_EventScript_Regirock::
|
|||
waitmoncry
|
||||
setwildbattle SPECIES_REGIROCK, 40
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special StartRegiBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
specialvar VAR_RESULT, GetBattleOutcome
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ FarawayIsland_Interior_EventScript_Mew::
|
|||
waitmoncry
|
||||
seteventmon SPECIES_MEW, 30
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special BattleSetup_StartLegendaryBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
specialvar VAR_RESULT, GetBattleOutcome
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ IslandCave_EventScript_Regice::
|
|||
waitmoncry
|
||||
setwildbattle SPECIES_REGICE, 40
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special StartRegiBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
specialvar VAR_RESULT, GetBattleOutcome
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ MarineCave_End_EventScript_Kyogre::
|
|||
setvar VAR_LAST_TALKED, LOCALID_MARINE_CAVE_KYOGRE
|
||||
setwildbattle SPECIES_KYOGRE, 70
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special BattleSetup_StartLegendaryBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
setvar VAR_TEMP_1, 0
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ MtEmber_Summit_EventScript_Moltres::
|
|||
playbgm MUS_RG_ENCOUNTER_GYM_LEADER, 0
|
||||
waitbuttonpress
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special BattleSetup_StartLegendaryBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
specialvar VAR_RESULT, GetBattleOutcome
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ NavelRock_Base_Frlg_EventScript_Lugia::
|
|||
delay 20
|
||||
seteventmon SPECIES_LUGIA, 70
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special BattleSetup_StartLegendaryBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
specialvar VAR_RESULT, GetBattleOutcome
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ NavelRock_Bottom_EventScript_Lugia::
|
|||
delay 20
|
||||
seteventmon SPECIES_LUGIA, 70
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special BattleSetup_StartLegendaryBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
specialvar VAR_RESULT, GetBattleOutcome
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ NavelRock_Summit_EventScript_HoOh::
|
|||
special RemoveCameraObject
|
||||
seteventmon SPECIES_HO_OH, 70
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special BattleSetup_StartLegendaryBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
setvar VAR_LAST_TALKED, LOCALID_NAVEL_ROCK_HO_OH
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ NavelRock_Top_EventScript_HoOh::
|
|||
special RemoveCameraObject
|
||||
seteventmon SPECIES_HO_OH, 70
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special BattleSetup_StartLegendaryBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
setvar VAR_LAST_TALKED, LOCALID_NAVEL_ROCK_HO_OH
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@ PetalburgCity_EventScript_WallyTutorial::
|
|||
applymovement LOCALID_PLAYER, PetalburgCity_Movement_WallyTutorialPlayer
|
||||
waitmovement 0
|
||||
msgbox Route102_Text_WatchMeCatchPokemon, MSGBOX_DEFAULT
|
||||
special StartWallyTutorialBattle
|
||||
createmon 1, 0, SPECIES_RALTS, 5, gender=MON_MALE
|
||||
startcatchtutorial
|
||||
waitstate
|
||||
msgbox Route102_Text_WallyIDidIt, MSGBOX_DEFAULT
|
||||
applymovement LOCALID_PETALBURG_WALLY, Common_Movement_WalkInPlaceFasterLeft, MAP_PETALBURG_CITY
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ PokemonTower_6F_EventScript_MarowakGhost::
|
|||
lockall
|
||||
textcolor NPC_TEXT_COLOR_MON
|
||||
msgbox PokemonTower_6F_Text_BeGoneIntruders
|
||||
setwildbattle SPECIES_MAROWAK, 30
|
||||
special StartMarowakBattle
|
||||
createmon 1, 0, SPECIES_MAROWAK, 30, gender=MON_FEMALE, nature=NATURE_SERIOUS, hpIv=31, atkIv=31, defIv=31, speedIv=31, spAtkIv=31, spDefIv=31
|
||||
startghostbattle
|
||||
waitstate
|
||||
goto_if_eq VAR_RESULT, FALSE, PokemonTower_6F_EventScript_DefeatedMarowakGhost @ VAR_RESULT set by CB2_EndMarowakBattle
|
||||
applymovement LOCALID_PLAYER, PokemonTower_6F_Movement_ForcePlayerUp
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ PowerPlant_EventScript_Zapdos::
|
|||
playbgm MUS_RG_ENCOUNTER_GYM_LEADER, 0
|
||||
waitbuttonpress
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special BattleSetup_StartLegendaryBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
specialvar VAR_RESULT, GetBattleOutcome
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ SeafoamIslands_B4F_EventScript_Articuno::
|
|||
playbgm MUS_RG_ENCOUNTER_GYM_LEADER, 0
|
||||
waitbuttonpress
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special BattleSetup_StartLegendaryBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
specialvar VAR_RESULT, GetBattleOutcome
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ SkyPillar_Top_EventScript_Rayquaza::
|
|||
waitmoncry
|
||||
setwildbattle SPECIES_RAYQUAZA, 70
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special BattleSetup_StartLegendaryBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
specialvar VAR_RESULT, GetBattleOutcome
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ SouthernIsland_Interior_EventScript_Lati::
|
|||
call_if_eq VAR_ROAMER_POKEMON, 0, SouthernIsland_Interior_EventScript_SetLatiosBattleVars
|
||||
call_if_ne VAR_ROAMER_POKEMON, 0, SouthernIsland_Interior_EventScript_SetLatiasBattleVars
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special BattleSetup_StartLatiBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
specialvar VAR_RESULT, GetBattleOutcome
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ TerraCave_End_EventScript_Groudon::
|
|||
setvar VAR_LAST_TALKED, LOCALID_TERRA_CAVE_GROUDON
|
||||
setwildbattle SPECIES_GROUDON, 70
|
||||
setflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
special BattleSetup_StartLegendaryBattle
|
||||
startlegendarybattle
|
||||
waitstate
|
||||
clearflag FLAG_SYS_CTRL_OBJ_DELETE
|
||||
setvar VAR_TEMP_1, 0
|
||||
|
|
|
|||
|
|
@ -131,14 +131,6 @@ ViridianCity_EventScript_WatchToLearnBasics::
|
|||
release
|
||||
end
|
||||
|
||||
@ Unused. Starts battle after the post battle text, which is odd.
|
||||
ViridianCity_EventScript_TutorialUnused::
|
||||
msgbox ViridianCity_Text_ThatWasEducationalTakeThis
|
||||
special StartOldManTutorialBattle
|
||||
waitstate
|
||||
release
|
||||
end
|
||||
|
||||
ViridianCity_EventScript_TutorialNotReady::
|
||||
msgbox ViridianCity_Text_ThisIsPrivateProperty
|
||||
closemessage
|
||||
|
|
@ -222,7 +214,8 @@ ViridianCity_EventScript_TutorialTriggerRight::
|
|||
ViridianCity_EventScript_DoTutorialBattle::
|
||||
msgbox ViridianCity_Text_ShowYouHowToCatchMons
|
||||
closemessage
|
||||
special StartOldManTutorialBattle
|
||||
createmon 1, 0, SPECIES_WEEDLE, 5, gender=MON_MALE
|
||||
startcatchtutorial
|
||||
waitstate
|
||||
lock
|
||||
faceplayer
|
||||
|
|
|
|||
|
|
@ -362,7 +362,8 @@ Debug_EventScript_Steven_Multi::
|
|||
Debug_EventScript_WallyTutorial::
|
||||
special SavePlayerParty
|
||||
special LoadWallyZigzagoon
|
||||
special StartWallyTutorialBattle
|
||||
createmon 1, 0, SPECIES_RALTS, 5, gender=MON_MALE
|
||||
startcatchtutorial
|
||||
waitstate
|
||||
special LoadPlayerParty
|
||||
release
|
||||
|
|
|
|||
|
|
@ -175,7 +175,6 @@ gSpecials::
|
|||
def_special StartWallClock
|
||||
def_special Special_ViewWallClock
|
||||
def_special ChooseStarter
|
||||
def_special StartWallyTutorialBattle
|
||||
def_special ChangePokemonNickname
|
||||
def_special ChoosePartyMon
|
||||
def_special GetFirstFreePokeblockSlot
|
||||
|
|
@ -328,9 +327,6 @@ gSpecials::
|
|||
def_special IsPokerusInParty
|
||||
def_special SetSootopolisGymCrackedIceMetatiles
|
||||
def_special ShakeCamera
|
||||
def_special StartGroudonKyogreBattle
|
||||
def_special BattleSetup_StartLegendaryBattle
|
||||
def_special StartRegiBattle
|
||||
def_special SetTrainerFacingDirection
|
||||
def_special DoSealedChamberShakingEffect_Short
|
||||
def_special FoundBlackGlasses
|
||||
|
|
@ -340,7 +336,6 @@ gSpecials::
|
|||
def_special ShowContestEntryMonPic
|
||||
def_special HideContestEntryMonPic
|
||||
def_special SetEReaderTrainerGfxId
|
||||
def_special BattleSetup_StartLatiBattle
|
||||
def_special SetRoute119Weather
|
||||
def_special SetRoute123Weather
|
||||
def_special GetContestMultiplayerId
|
||||
|
|
@ -575,7 +570,6 @@ gSpecials::
|
|||
def_special SetFlavorTextFlagFromSpecialVars
|
||||
def_special DisableMsgBoxWalkaway
|
||||
def_special SetWalkingIntoSignVars
|
||||
def_special StartOldManTutorialBattle
|
||||
def_special DaisyMassageServices
|
||||
def_special GetLeadMonFriendship
|
||||
def_special OpenMuseumFossilPic
|
||||
|
|
@ -597,7 +591,6 @@ gSpecials::
|
|||
def_special IsPlayerLeftOfVermilionSailor
|
||||
def_special SetVermilionTrashCans
|
||||
def_special DoSSAnneDepartureCutscene
|
||||
def_special StartMarowakBattle
|
||||
def_special DoesPlayerPartyContainSpecies
|
||||
def_special GetMagikarpSizeRecordInfo
|
||||
def_special CompareMagikarpSize
|
||||
|
|
|
|||
|
|
@ -107,9 +107,7 @@ void RunBattleScriptCommands(void);
|
|||
enum Type GetDynamicMoveType(struct Pokemon *mon, enum Move move, enum BattlerId battler, enum MonState monInBattle);
|
||||
void SetTypeBeforeUsingMove(enum Move move, enum BattlerId battler);
|
||||
bool32 IsWildMonSmart(void);
|
||||
u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer *trainer, bool32 firstTrainer, u32 battleTypeFlags);
|
||||
void ModifyPersonalityForNature(u32 *personality, u32 newNature);
|
||||
u32 GeneratePersonalityForGender(u32 gender, enum Species species);
|
||||
void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMon *partyEntry);
|
||||
bool32 CanPlayerForfeitNormalTrainerBattle(void);
|
||||
bool32 DidPlayerForfeitNormalTrainerBattle(void);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define GUARD_BATTLE_SETUP_H
|
||||
|
||||
#include "battle_transition.h"
|
||||
#include "data.h"
|
||||
#include "gym_leader_rematch.h"
|
||||
|
||||
#define REMATCHES_COUNT 5
|
||||
|
|
@ -50,17 +51,8 @@ extern u16 gPartnerTrainerId;
|
|||
|
||||
#define TRAINER_BATTLE_PARAM gTrainerBattleParameter.params
|
||||
|
||||
void BattleSetup_StartWildBattle(void);
|
||||
void BattleSetup_StartDoubleWildBattle(void);
|
||||
void BattleSetup_StartBattlePikeWildBattle(void);
|
||||
void BattleSetup_StartRoamerBattle(void);
|
||||
void StartWallyTutorialBattle(void);
|
||||
void BattleSetup_StartScriptedWildBattle(void);
|
||||
void BattleSetup_StartScriptedDoubleWildBattle(void);
|
||||
void BattleSetup_StartLatiBattle(void);
|
||||
void BattleSetup_StartLegendaryBattle(void);
|
||||
void StartGroudonKyogreBattle(void);
|
||||
void StartRegiBattle(void);
|
||||
void BattleSetup_StartWildBattle(bool32 isDouble);
|
||||
void DoBattleSetup(bool32 fromScript);
|
||||
enum BattleEnvironments BattleSetup_GetEnvironmentId(void);
|
||||
enum BattleTransition GetWildBattleTransition(void);
|
||||
enum BattleTransition GetTrainerBattleTransition(void);
|
||||
|
|
@ -106,8 +98,6 @@ void ShouldTryGetTrainerScript(void);
|
|||
u16 CountMaxPossibleRematch(u16 trainerId);
|
||||
u16 CountBattledRematchTeams(u16 trainerId);
|
||||
void TrainerBattleLoadArgs(const u8 *data);
|
||||
void TrainerBattleLoadArgsTrainerA(const u8 *data);
|
||||
void TrainerBattleLoadArgsTrainerB(const u8 *data);
|
||||
void TrainerBattleLoadArgsSecondTrainer(const u8 *data);
|
||||
void InitTrainerBattleParameter(void);
|
||||
|
||||
|
|
@ -118,4 +108,6 @@ s32 FirstBattleTrainerIdToRematchTableId(const struct RematchTrainer *table, u16
|
|||
u16 GetRematchTrainerIdFromTable(const struct RematchTrainer *table, u16 firstBattleTrainerId);
|
||||
u8 GetRivalBattleFlags(void);
|
||||
|
||||
void CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer *trainer, bool32 firstTrainer);
|
||||
|
||||
#endif // GUARD_BATTLE_SETUP_H
|
||||
|
|
|
|||
|
|
@ -357,7 +357,7 @@
|
|||
#define B_WILD_NATURAL_ENEMIES TRUE // If set to TRUE, certain wild mon species will attack other species when partnered in double wild battles (eg. Zangoose vs Seviper)
|
||||
#define B_AFFECTION_MECHANICS TRUE // In Gen6+, there's a stat called affection that can trigger different effects in battle. From LGPE onwards, those effects use friendship instead.
|
||||
#define B_TRAINER_CLASS_POKE_BALLS GEN_LATEST // In Gen7+, trainers will use certain types of Poké Balls depending on their trainer class.
|
||||
#define B_TRAINER_MON_RANDOM_ABILITY FALSE // If this is set to TRUE a random legal ability will be generated for a trainer mon
|
||||
#define B_TRAINER_MON_HIDDEN_ABILITY FALSE // If this is set to TRUE, hidden ability can be randomly rolled for trainers/partners who do not have a set ability. If FALSE, it's still random but can't get an hidden ability.
|
||||
#define B_OBEDIENCE_MECHANICS GEN_LATEST // In PLA+ (here Gen8+), obedience restrictions also apply to non-outsider Pokémon, albeit based on their level met rather than actual level
|
||||
#define B_USE_FROSTBITE FALSE // In PLA, Frostbite replaces Freeze. Enabling this flag does the same here. Moves can still be cherry-picked to either Freeze or Frostbite. Freeze-Dry, Secret Power & Tri Attack depend on this config.
|
||||
#define B_TOXIC_REVERSAL GEN_LATEST // In Gen5+, bad poison will change to regular poison at the end of battles.
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ enum BattleSide
|
|||
#define BIT_FLANK 2
|
||||
|
||||
// Battle Type Flags
|
||||
#define BATTLE_TYPE_BASIC_WILD 0
|
||||
#define BATTLE_TYPE_DOUBLE (1 << 0)
|
||||
#define BATTLE_TYPE_LINK (1 << 1)
|
||||
#define BATTLE_TYPE_IS_MASTER (1 << 2) // In not-link battles, it's always set.
|
||||
|
|
@ -118,7 +119,7 @@ enum BattleSide
|
|||
|
||||
#define WILD_DOUBLE_BATTLE ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_TRAINER))))
|
||||
#define RECORDED_WILD_BATTLE ((gBattleTypeFlags & BATTLE_TYPE_RECORDED) && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FRONTIER)))
|
||||
#define BATTLE_TWO_VS_ONE_OPPONENT ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && TRAINER_BATTLE_PARAM.opponentB == 0xFFFF))
|
||||
#define BATTLE_TWO_VS_ONE_OPPONENT ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && TRAINER_BATTLE_PARAM.opponentB == TRAINER_NONE))
|
||||
#define BATTLE_TYPE_HAS_AI (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_ROAMER | BATTLE_TYPE_INGAME_PARTNER)
|
||||
#define BATTLE_TYPE_MORE_THAN_TWO_BATTLERS (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_TWO_OPPONENTS)
|
||||
#define BATTLE_TYPE_PLAYER_HAS_PARTNER (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_TOWER_LINK_MULTI)
|
||||
|
|
|
|||
|
|
@ -13,4 +13,14 @@
|
|||
#define TRAINER_BATTLE_TWO_TRAINERS_NO_INTRO 13
|
||||
#define TRAINER_BATTLE_EARLY_RIVAL 14
|
||||
|
||||
#define MULTI_BATTLE_2_VS_2 0
|
||||
#define MULTI_BATTLE_2_VS_WILD 1
|
||||
#define MULTI_BATTLE_2_VS_1 2
|
||||
#define MULTI_BATTLE_CHOOSE_MONS 0x80
|
||||
|
||||
#define SPECIAL_WILD_NONE 0
|
||||
#define SPECIAL_WILD_LEGENDARY 1
|
||||
#define SPECIAL_WILD_GHOST 2
|
||||
#define SPECIAL_WILD_CATCH_TUTORIAL 3
|
||||
|
||||
#endif // GUARD_CONSTANTS_BATTLE_SETUP_H
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef GUARD_CONSTANTS_BATTLE_SPECIAL_H
|
||||
#define GUARD_CONSTANTS_BATTLE_SPECIAL_H
|
||||
|
||||
// Ids for special multi battle types
|
||||
#define MULTI_BATTLE_2_VS_2 0
|
||||
#define MULTI_BATTLE_2_VS_WILD 1
|
||||
#define MULTI_BATTLE_2_VS_1 2
|
||||
#define MULTI_BATTLE_CHOOSE_MONS 0x80
|
||||
|
||||
#endif // GUARD_CONSTANTS_BATTLE_SPECIAL_H
|
||||
|
|
@ -738,7 +738,6 @@ void CreateBoxMon(struct BoxPokemon *boxMon, enum Species species, u8 level, u32
|
|||
void CreateMonWithIVs(struct Pokemon *mon, enum Species species, u8 level, u32 personality, struct OriginalTrainerId trainerId, u8 fixedIV);
|
||||
void SetBoxMonIVs(struct BoxPokemon *mon, u8 fixedIV);
|
||||
void SetBoxMonPerfectIVs(struct BoxPokemon *mon, u32 numPerfect);
|
||||
void CreateMaleMon(struct Pokemon *mon, enum Species species, u8 level);
|
||||
void CreateMonWithIVsPersonality(struct Pokemon *mon, enum Species species, u8 level, u32 ivs, u32 personality);
|
||||
void CreateBattleTowerMon(struct Pokemon *mon, struct BattleTowerPokemon *src);
|
||||
void CreateBattleTowerMon_HandleLevel(struct Pokemon *mon, struct BattleTowerPokemon *src, bool8 lvl50);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
u32 ScriptGiveMon(enum Species species, u8 level, enum Item item);
|
||||
u8 ScriptGiveEgg(enum Species species);
|
||||
void CreateScriptedWildMon(enum Species species, u8 level, enum Item item);
|
||||
void CreateScriptedDoubleWildMon(enum Species species, u8 level, enum Item item, enum Species species2, u8 level2, enum Item item2);
|
||||
void CreateStaticWildMon(struct Pokemon *mon, enum Species species, u8 level, enum Item item);
|
||||
void ScriptSetMonMoveSlot(u8 monIndex, enum Move move, u8 slot);
|
||||
void ReducePlayerPartyToSelectedMons(void);
|
||||
void HealPlayerParty(void);
|
||||
|
|
|
|||
19
include/trainer_util.h
Normal file
19
include/trainer_util.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef GUARD_TRAINER_UTIL_H
|
||||
#define GUARD_TRAINER_UTIL_H
|
||||
|
||||
struct TrainerGenerator
|
||||
{
|
||||
u8 gender:7;
|
||||
u8 isFrontier:1;
|
||||
u8 name[TRAINER_NAME_LENGTH + 1];
|
||||
u8 trainerClass;
|
||||
struct OriginalTrainerId otID;
|
||||
rng_value_t localRngState;
|
||||
};
|
||||
|
||||
u32 Crc32B(const u8 *data, u32 size);
|
||||
rng_value_t GeneratePartySeed(const struct Trainer *trainer);
|
||||
void GenerateMonFromTrainerMon(struct Pokemon *mon, const struct TrainerMon *trainerMon, struct TrainerGenerator *trainer);
|
||||
u32 GeneratePersonalityForGender(u32 gender, u32 species);
|
||||
|
||||
#endif // GUARD_TRAINER_UTIL_H
|
||||
|
|
@ -58,7 +58,6 @@ u16 GetLocalWildMon(bool8 *isWaterMon);
|
|||
u16 GetLocalWaterMon(void);
|
||||
bool8 UpdateRepelCounter(void);
|
||||
bool8 TryDoDoubleWildBattle(void);
|
||||
bool8 StandardWildEncounter_Debug(void);
|
||||
u32 CalculateChainFishingShinyRolls(void);
|
||||
void CreateWildMon(enum Species species, u8 level);
|
||||
u16 GetCurrentMapWildMonHeaderId(void);
|
||||
|
|
|
|||
26
migration_scripts/1.16/battle_setup_rework.py
Normal file
26
migration_scripts/1.16/battle_setup_rework.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
from itertools import chain
|
||||
|
||||
import glob
|
||||
import os
|
||||
|
||||
replacements = [
|
||||
["special BattleSetup_StartLatiBattle", "startlegendarybattle"],
|
||||
["special StartRegiBattle", "startlegendarybattle"],
|
||||
["special BattleSetup_StartLegendaryBattle", "startlegendarybattle"],
|
||||
]
|
||||
|
||||
if not os.path.exists("Makefile"):
|
||||
print("Please run this script from your root folder.")
|
||||
quit()
|
||||
|
||||
for inc_fname in chain(glob.glob("./data/scripts/*.inc"), glob.glob("./data/maps/*/scripts.inc")):
|
||||
new_lines = []
|
||||
with open(inc_fname, "r") as inc_fp:
|
||||
lines = inc_fp.readlines()
|
||||
for line in lines:
|
||||
for replacement in replacements:
|
||||
line = line.replace(replacement[0], replacement[1])
|
||||
new_lines.append(line)
|
||||
with open(inc_fname, 'w+') as file:
|
||||
for line in new_lines:
|
||||
file.write(line)
|
||||
|
|
@ -315,7 +315,7 @@ void BattleAI_SetupFlags(void)
|
|||
else
|
||||
{
|
||||
gAiThinkingStruct->aiFlags[B_BATTLER_1] = GetAiFlags(TRAINER_BATTLE_PARAM.opponentA, B_BATTLER_1);
|
||||
if ((TRAINER_BATTLE_PARAM.opponentB != 0) && (TRAINER_BATTLE_PARAM.opponentB != 0xFFFF))
|
||||
if (TRAINER_BATTLE_PARAM.opponentB != TRAINER_NONE)
|
||||
gAiThinkingStruct->aiFlags[B_BATTLER_3] = GetAiFlags(TRAINER_BATTLE_PARAM.opponentB, B_BATTLER_3);
|
||||
else
|
||||
gAiThinkingStruct->aiFlags[B_BATTLER_3] = gAiThinkingStruct->aiFlags[B_BATTLER_1];
|
||||
|
|
|
|||
|
|
@ -1407,8 +1407,7 @@ static bool32 HandleEndTurnTrainerBSlides(enum BattlerId battler)
|
|||
if (slide == TRUE)
|
||||
{
|
||||
if ((TRAINER_BATTLE_PARAM.opponentB == TRAINER_BATTLE_PARAM.opponentA)
|
||||
|| (TRAINER_BATTLE_PARAM.opponentB == TRAINER_NONE)
|
||||
|| (TRAINER_BATTLE_PARAM.opponentB == 0xFFFF))
|
||||
|| (TRAINER_BATTLE_PARAM.opponentB == TRAINER_NONE))
|
||||
BattleScriptExecute(BattleScript_TrainerASlideMsgEnd2);
|
||||
else
|
||||
BattleScriptExecute(BattleScript_TrainerBSlideMsgEnd2);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "string_util.h"
|
||||
#include "task.h"
|
||||
#include "text.h"
|
||||
#include "trainer_util.h"
|
||||
#include "constants/abilities.h"
|
||||
#include "constants/battle_frontier.h"
|
||||
#include "constants/battle_frontier_mons.h"
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@
|
|||
#include "test/battle.h"
|
||||
#include "test_runner.h"
|
||||
#include "text.h"
|
||||
#include "trainer_pools.h"
|
||||
#include "trainer_util.h"
|
||||
#include "trig.h"
|
||||
#include "tv.h"
|
||||
#include "util.h"
|
||||
|
|
@ -91,7 +91,6 @@ static void CB2_HandleStartMultiPartnerBattle(void);
|
|||
static void CB2_HandleStartMultiBattle(void);
|
||||
static void CB2_HandleStartBattle(void);
|
||||
static void TryCorrectShedinjaLanguage(struct Pokemon *mon);
|
||||
static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 firstTrainer);
|
||||
static void BattleMainCB1(void);
|
||||
static void CB2_EndLinkBattle(void);
|
||||
static void EndLinkBattleInSteps(void);
|
||||
|
|
@ -128,8 +127,6 @@ static void HandleEndTurn_BattleLost(void);
|
|||
static void HandleEndTurn_RanFromBattle(void);
|
||||
static void HandleEndTurn_MonFled(void);
|
||||
static void HandleEndTurn_FinishBattle(void);
|
||||
static u32 Crc32B (const u8 *data, u32 size);
|
||||
static u32 GeneratePartyHash(const struct Trainer *trainer, u32 i);
|
||||
|
||||
EWRAM_DATA u16 gBattle_BG0_X = 0;
|
||||
EWRAM_DATA u16 gBattle_BG0_Y = 0;
|
||||
|
|
@ -593,18 +590,6 @@ static void CB2_InitBattleInternal(void)
|
|||
else
|
||||
SetMainCallback2(CB2_HandleStartBattle);
|
||||
|
||||
if (!DEBUG_OVERWORLD_MENU || (DEBUG_OVERWORLD_MENU && !gIsDebugBattle))
|
||||
{
|
||||
if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED)))
|
||||
{
|
||||
CreateNPCTrainerParty(&gEnemyParty[0], TRAINER_BATTLE_PARAM.opponentA, TRUE);
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && !BATTLE_TWO_VS_ONE_OPPONENT)
|
||||
CreateNPCTrainerParty(&gEnemyParty[PARTY_SIZE / 2], TRAINER_BATTLE_PARAM.opponentB, FALSE);
|
||||
SetWildMonHeldItem();
|
||||
CalculateEnemyPartyCount();
|
||||
}
|
||||
}
|
||||
|
||||
gMain.inBattle = TRUE;
|
||||
gSaveBlock2Ptr->frontier.disableRecordBattle = FALSE;
|
||||
|
||||
|
|
@ -619,14 +604,16 @@ static void CB2_InitBattleInternal(void)
|
|||
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER))
|
||||
{
|
||||
if (!(gBattleTypeFlags & (BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_PYRAMID | BATTLE_TYPE_PIKE)))
|
||||
SetWildMonHeldItem();
|
||||
TryFormChange(&gEnemyParty[0], FORM_CHANGE_BEGIN_WILD_ENCOUNTER);
|
||||
if (IsDoubleBattle())
|
||||
TryFormChange(&gEnemyParty[1], FORM_CHANGE_BEGIN_WILD_ENCOUNTER);
|
||||
}
|
||||
|
||||
CalculateEnemyPartyCount();
|
||||
#if TESTING
|
||||
gPlayerPartyCount = CalculatePartyCount(gPlayerParty);
|
||||
gEnemyPartyCount = CalculatePartyCount(gEnemyParty);
|
||||
#endif
|
||||
|
||||
gBattleCommunication[MULTIUSE_STATE] = 0;
|
||||
|
|
@ -1848,33 +1835,6 @@ void CB2_QuitRecordedBattle(void)
|
|||
}
|
||||
}
|
||||
|
||||
static u32 Crc32B (const u8 *data, u32 size)
|
||||
{
|
||||
s32 i, j;
|
||||
u32 byte, crc, mask;
|
||||
|
||||
i = 0;
|
||||
crc = 0xFFFFFFFF;
|
||||
for (i = 0; i < size; ++i)
|
||||
{
|
||||
byte = data[i];
|
||||
crc = crc ^ byte;
|
||||
for (j = 7; j >= 0; --j)
|
||||
{
|
||||
mask = -(crc & 1);
|
||||
crc = (crc >> 1) ^ (0xEDB88320 & mask);
|
||||
}
|
||||
}
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
static u32 GeneratePartyHash(const struct Trainer *trainer, u32 i)
|
||||
{
|
||||
const u8 *buffer = (const u8 *) &trainer->party[i];
|
||||
u32 n = sizeof(*trainer->party);
|
||||
return Crc32B(buffer, n);
|
||||
}
|
||||
|
||||
void ModifyPersonalityForNature(u32 *personality, u32 newNature)
|
||||
{
|
||||
u32 nature = GetNatureFromPersonality(*personality);
|
||||
|
|
@ -1888,214 +1848,6 @@ void ModifyPersonalityForNature(u32 *personality, u32 newNature)
|
|||
*personality -= (diff * sign);
|
||||
}
|
||||
|
||||
u32 GeneratePersonalityForGender(u32 gender, enum Species species)
|
||||
{
|
||||
const struct SpeciesInfo *speciesInfo = &gSpeciesInfo[species];
|
||||
if (gender == MON_GENDERLESS)
|
||||
return 0;
|
||||
else if (gender == MON_MALE)
|
||||
return ((255 - speciesInfo->genderRatio) / 2) + speciesInfo->genderRatio;
|
||||
else
|
||||
return speciesInfo->genderRatio / 2;
|
||||
}
|
||||
|
||||
void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMon *partyEntry)
|
||||
{
|
||||
bool32 noMoveSet = TRUE;
|
||||
u32 j;
|
||||
|
||||
for (j = 0; j < MAX_MON_MOVES; ++j)
|
||||
{
|
||||
if (partyEntry->moves[j] != MOVE_NONE)
|
||||
noMoveSet = FALSE;
|
||||
}
|
||||
if (noMoveSet)
|
||||
{
|
||||
GiveMonInitialMoveset(mon);
|
||||
// TODO: Figure out a default strategy when moves are not set, to generate a good moveset
|
||||
return;
|
||||
}
|
||||
|
||||
for (j = 0; j < MAX_MON_MOVES; ++j)
|
||||
{
|
||||
u32 pp = GetMovePP(partyEntry->moves[j]);
|
||||
SetMonData(mon, MON_DATA_MOVE1 + j, &partyEntry->moves[j]);
|
||||
SetMonData(mon, MON_DATA_PP1 + j, &pp);
|
||||
}
|
||||
}
|
||||
|
||||
u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer *trainer, bool32 firstTrainer, u32 battleTypeFlags)
|
||||
{
|
||||
u32 personalityValue;
|
||||
s32 i;
|
||||
u8 monsCount;
|
||||
if (battleTypeFlags & BATTLE_TYPE_TRAINER && !(battleTypeFlags & (BATTLE_TYPE_FRONTIER
|
||||
| BATTLE_TYPE_EREADER_TRAINER
|
||||
| BATTLE_TYPE_TRAINER_HILL)))
|
||||
{
|
||||
if (firstTrainer == TRUE)
|
||||
ZeroEnemyPartyMons();
|
||||
|
||||
if (battleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
|
||||
{
|
||||
if (trainer->partySize > PARTY_SIZE / 2)
|
||||
monsCount = PARTY_SIZE / 2;
|
||||
else
|
||||
monsCount = trainer->partySize;
|
||||
}
|
||||
else
|
||||
{
|
||||
monsCount = trainer->partySize;
|
||||
}
|
||||
|
||||
u32 monIndices[monsCount];
|
||||
DoTrainerPartyPool(trainer, monIndices, monsCount, battleTypeFlags);
|
||||
|
||||
for (i = 0; i < monsCount; i++)
|
||||
{
|
||||
u32 monIndex = monIndices[i];
|
||||
s32 ball = -1;
|
||||
u32 personalityHash = GeneratePartyHash(trainer, i);
|
||||
const struct TrainerMon *partyData = trainer->party;
|
||||
struct OriginalTrainerId otId = OTID_STRUCT_RANDOM_NO_SHINY;
|
||||
u32 abilityNum = 0;
|
||||
|
||||
if (trainer->battleType != TRAINER_BATTLE_TYPE_SINGLES)
|
||||
personalityValue = 0x80;
|
||||
else if (trainer->gender == TRAINER_GENDER_FEMALE)
|
||||
personalityValue = 0x78; // Use personality more likely to result in a female Pokémon
|
||||
else
|
||||
personalityValue = 0x88; // Use personality more likely to result in a male Pokémon
|
||||
|
||||
personalityValue += personalityHash << 8;
|
||||
if (partyData[monIndex].gender == TRAINER_MON_MALE)
|
||||
personalityValue = (personalityValue & 0xFFFFFF00) | GeneratePersonalityForGender(MON_MALE, partyData[monIndex].species);
|
||||
else if (partyData[monIndex].gender == TRAINER_MON_FEMALE)
|
||||
personalityValue = (personalityValue & 0xFFFFFF00) | GeneratePersonalityForGender(MON_FEMALE, partyData[monIndex].species);
|
||||
else if (partyData[monIndex].gender == TRAINER_MON_RANDOM_GENDER)
|
||||
personalityValue = (personalityValue & 0xFFFFFF00) | GeneratePersonalityForGender(Random() & 1 ? MON_MALE : MON_FEMALE, partyData[monIndex].species);
|
||||
ModifyPersonalityForNature(&personalityValue, partyData[monIndex].nature);
|
||||
if (partyData[monIndex].isShiny)
|
||||
{
|
||||
otId.method = OT_ID_PRESET;
|
||||
otId.value = HIHALF(personalityValue) ^ LOHALF(personalityValue);
|
||||
}
|
||||
CreateMon(&party[i], partyData[monIndex].species, partyData[monIndex].lvl, personalityValue, otId);
|
||||
SetMonData(&party[i], MON_DATA_HELD_ITEM, &partyData[monIndex].heldItem);
|
||||
|
||||
CustomTrainerPartyAssignMoves(&party[i], &partyData[monIndex]);
|
||||
SetMonData(&party[i], MON_DATA_IVS, &(partyData[monIndex].iv));
|
||||
if (partyData[monIndex].ev != NULL)
|
||||
{
|
||||
SetMonData(&party[i], MON_DATA_HP_EV, &(partyData[monIndex].ev[0]));
|
||||
SetMonData(&party[i], MON_DATA_ATK_EV, &(partyData[monIndex].ev[1]));
|
||||
SetMonData(&party[i], MON_DATA_DEF_EV, &(partyData[monIndex].ev[2]));
|
||||
SetMonData(&party[i], MON_DATA_SPATK_EV, &(partyData[monIndex].ev[3]));
|
||||
SetMonData(&party[i], MON_DATA_SPDEF_EV, &(partyData[monIndex].ev[4]));
|
||||
SetMonData(&party[i], MON_DATA_SPEED_EV, &(partyData[monIndex].ev[5]));
|
||||
}
|
||||
if (partyData[monIndex].ability != ABILITY_NONE)
|
||||
{
|
||||
const struct SpeciesInfo *speciesInfo = &gSpeciesInfo[partyData[monIndex].species];
|
||||
u32 maxAbilityNum = ARRAY_COUNT(speciesInfo->abilities);
|
||||
for (abilityNum = 0; abilityNum < maxAbilityNum; ++abilityNum)
|
||||
{
|
||||
if (speciesInfo->abilities[abilityNum] == partyData[monIndex].ability)
|
||||
break;
|
||||
}
|
||||
assertf(abilityNum < maxAbilityNum, "illegal ability %S for %S", gAbilitiesInfo[partyData[monIndex].ability].name, speciesInfo->speciesName);
|
||||
}
|
||||
else if (B_TRAINER_MON_RANDOM_ABILITY)
|
||||
{
|
||||
const struct SpeciesInfo *speciesInfo = &gSpeciesInfo[partyData[monIndex].species];
|
||||
abilityNum = personalityHash % 3;
|
||||
while (speciesInfo->abilities[abilityNum] == ABILITY_NONE)
|
||||
{
|
||||
abilityNum--;
|
||||
}
|
||||
}
|
||||
SetMonData(&party[i], MON_DATA_ABILITY_NUM, &abilityNum);
|
||||
SetMonData(&party[i], MON_DATA_FRIENDSHIP, &(partyData[monIndex].friendship));
|
||||
if (partyData[monIndex].ball < POKEBALL_COUNT)
|
||||
{
|
||||
ball = partyData[monIndex].ball;
|
||||
SetMonData(&party[i], MON_DATA_POKEBALL, &ball);
|
||||
}
|
||||
if (partyData[monIndex].nickname != NULL)
|
||||
{
|
||||
SetMonData(&party[i], MON_DATA_NICKNAME, partyData[monIndex].nickname);
|
||||
}
|
||||
if (partyData[monIndex].isShiny)
|
||||
{
|
||||
bool32 data = TRUE;
|
||||
SetMonData(&party[i], MON_DATA_IS_SHINY, &data);
|
||||
}
|
||||
if (partyData[monIndex].dynamaxLevel > 0)
|
||||
{
|
||||
u32 data = partyData[monIndex].dynamaxLevel;
|
||||
if (partyData[monIndex].shouldUseDynamax)
|
||||
gBattleStruct->opponentMonCanDynamax |= 1 << i;
|
||||
SetMonData(&party[i], MON_DATA_DYNAMAX_LEVEL, &data);
|
||||
}
|
||||
if (partyData[monIndex].gigantamaxFactor)
|
||||
{
|
||||
u32 data = partyData[monIndex].gigantamaxFactor;
|
||||
SetMonData(&party[i], MON_DATA_GIGANTAMAX_FACTOR, &data);
|
||||
}
|
||||
if (partyData[monIndex].teraType > 0)
|
||||
{
|
||||
gBattleStruct->opponentMonCanTera |= 1 << i;
|
||||
enum Type data = partyData[monIndex].teraType;
|
||||
SetMonData(&party[i], MON_DATA_TERA_TYPE, &data);
|
||||
}
|
||||
CalculateMonStats(&party[i]);
|
||||
|
||||
if (B_TRAINER_CLASS_POKE_BALLS >= GEN_7 && ball == -1)
|
||||
{
|
||||
ball = gTrainerClasses[trainer->trainerClass].ball ?: ITEM_POKE_BALL;
|
||||
SetMonData(&party[i], MON_DATA_POKEBALL, &ball);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return trainer->partySize;
|
||||
}
|
||||
|
||||
static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 firstTrainer)
|
||||
{
|
||||
u8 retVal;
|
||||
if (trainerNum == TRAINER_SECRET_BASE)
|
||||
return 0;
|
||||
if (GetTrainerStructFromId(trainerNum)->overrideTrainer)
|
||||
{
|
||||
struct Trainer tempTrainer;
|
||||
memcpy(&tempTrainer, GetTrainerStructFromId(trainerNum), sizeof(struct Trainer));
|
||||
const struct Trainer *origTrainer = GetTrainerStructFromId(tempTrainer.overrideTrainer);
|
||||
|
||||
tempTrainer.party = origTrainer->party;
|
||||
|
||||
tempTrainer.poolSize = origTrainer->poolSize;
|
||||
if (tempTrainer.partySize == 0)
|
||||
tempTrainer.partySize = origTrainer->partySize;
|
||||
|
||||
retVal = CreateNPCTrainerPartyFromTrainer(party, (const struct Trainer *)(&tempTrainer), firstTrainer, gBattleTypeFlags);
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = CreateNPCTrainerPartyFromTrainer(party, GetTrainerStructFromId(trainerNum), firstTrainer, gBattleTypeFlags);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void CreateTrainerPartyForPlayer(void)
|
||||
{
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
|
||||
ZeroPlayerPartyMons();
|
||||
gPartnerTrainerId = gSpecialVar_0x8004;
|
||||
CreateNPCTrainerPartyFromTrainer(gPlayerParty, GetTrainerStructFromId(gSpecialVar_0x8004), TRUE, BATTLE_TYPE_TRAINER);
|
||||
}
|
||||
|
||||
void VBlankCB_Battle(void)
|
||||
{
|
||||
// Change gRngSeed every vblank unless the battle could be recorded.
|
||||
|
|
@ -3740,7 +3492,7 @@ static void DoBattleIntro(void)
|
|||
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
|
||||
{
|
||||
statusesOpponentA = GetTrainerStartingStatusFromId(TRAINER_BATTLE_PARAM.opponentA);
|
||||
if (TRAINER_BATTLE_PARAM.opponentB != 0xFFFF)
|
||||
if (TRAINER_BATTLE_PARAM.opponentB != TRAINER_NONE)
|
||||
statusesOpponentB = GetTrainerStartingStatusFromId(TRAINER_BATTLE_PARAM.opponentB);
|
||||
}
|
||||
STARTING_STATUS_DEFINITIONS(UNPACK_STARTING_STATUS_TO_BATTLE);
|
||||
|
|
@ -3847,8 +3599,7 @@ static void TryDoEventsBeforeFirstTurn(void)
|
|||
{
|
||||
// Ensures only trainer A slide is played in single-trainer doubles (B == A / B == TRAINER_NONE) and 2v1 multibattles (B == 0xFFFF)
|
||||
if (!((TRAINER_BATTLE_PARAM.opponentB == TRAINER_BATTLE_PARAM.opponentA)
|
||||
|| (TRAINER_BATTLE_PARAM.opponentB == TRAINER_NONE)
|
||||
|| (TRAINER_BATTLE_PARAM.opponentB == 0xFFFF)))
|
||||
|| (TRAINER_BATTLE_PARAM.opponentB == TRAINER_NONE)))
|
||||
{
|
||||
BattleScriptExecute(BattleScript_TrainerBSlideMsgEnd2);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@
|
|||
#include "data.h"
|
||||
#include "frontier_util.h"
|
||||
#include "difficulty.h"
|
||||
#include "malloc.h"
|
||||
#include "string_util.h"
|
||||
#include "trainer_util.h"
|
||||
#include "text.h"
|
||||
|
||||
#include "constants/abilities.h"
|
||||
|
|
@ -21,15 +23,25 @@ const struct Trainer gBattlePartners[DIFFICULTY_COUNT][PARTNER_COUNT] =
|
|||
|
||||
#define STEVEN_OTID 61226
|
||||
|
||||
static void MakePartnerGenerator(struct TrainerGenerator *trainerGen, const struct Trainer *trainer)
|
||||
{
|
||||
u32 otID;
|
||||
trainerGen->gender = trainer->gender;
|
||||
trainerGen->isFrontier = FALSE;
|
||||
StringCopyN(trainerGen->name, trainer->trainerName, TRAINER_NAME_LENGTH + 1);
|
||||
trainerGen->trainerClass = trainer->trainerClass;
|
||||
otID = Crc32B((const u8 *)trainer, sizeof(struct Trainer));
|
||||
trainerGen->otID = OTID_STRUCT_PRESET(otID);
|
||||
trainerGen->localRngState = LocalRandomSeed(otID);
|
||||
}
|
||||
|
||||
void FillPartnerParty(u16 trainerId)
|
||||
{
|
||||
s32 i, j, k;
|
||||
u32 firstIdPart = 0, secondIdPart = 0, thirdIdPart = 0;
|
||||
u32 ivs, level, personality;
|
||||
s32 i, j;
|
||||
u32 ivs, level;
|
||||
u16 monId;
|
||||
u32 otID;
|
||||
|
||||
u8 trainerName[(PLAYER_NAME_LENGTH * 3) + 1];
|
||||
enum DifficultyLevel difficulty = GetBattlePartnerDifficultyLevel(trainerId);
|
||||
SetFacilityPtrsGetLevel();
|
||||
|
||||
if (trainerId > TRAINER_PARTNER(PARTNER_NONE))
|
||||
|
|
@ -37,85 +49,16 @@ void FillPartnerParty(u16 trainerId)
|
|||
for (i = 0; i < 3; i++)
|
||||
ZeroMonData(&gPlayerParty[i + 3]);
|
||||
|
||||
for (i = 0; i < 3 && i < gBattlePartners[difficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].partySize; i++)
|
||||
const struct Trainer *partner = GetTrainerStructFromId(trainerId);
|
||||
struct TrainerGenerator *partnerGen = AllocZeroed(sizeof(struct TrainerGenerator));
|
||||
MakePartnerGenerator(partnerGen, partner);
|
||||
if (trainerId == TRAINER_PARTNER(PARTNER_STEVEN))
|
||||
partnerGen->otID = OTID_STRUCT_PRESET(STEVEN_OTID);
|
||||
for (i = 0; i < 3 && i < partner->partySize; i++)
|
||||
{
|
||||
const struct TrainerMon *partyData = gBattlePartners[difficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].party;
|
||||
const u8 *partnerName = gBattlePartners[difficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerName;
|
||||
|
||||
for (k = 0; partnerName[k] != EOS && k < 3; k++)
|
||||
{
|
||||
if (k == 0)
|
||||
{
|
||||
firstIdPart = partnerName[k];
|
||||
secondIdPart = partnerName[k];
|
||||
thirdIdPart = partnerName[k];
|
||||
}
|
||||
else if (k == 1)
|
||||
{
|
||||
secondIdPart = partnerName[k];
|
||||
thirdIdPart = partnerName[k];
|
||||
}
|
||||
else if (k == 2)
|
||||
{
|
||||
thirdIdPart = partnerName[k];
|
||||
}
|
||||
}
|
||||
if (trainerId == TRAINER_PARTNER(PARTNER_STEVEN))
|
||||
otID = STEVEN_OTID;
|
||||
else
|
||||
otID = ((firstIdPart % 72) * 1000) + ((secondIdPart % 23) * 10) + (thirdIdPart % 37) % 65536;
|
||||
|
||||
personality = Random32();
|
||||
if (partyData[i].gender == TRAINER_MON_MALE)
|
||||
personality = (personality & 0xFFFFFF00) | GeneratePersonalityForGender(MON_MALE, partyData[i].species);
|
||||
else if (partyData[i].gender == TRAINER_MON_FEMALE)
|
||||
personality = (personality & 0xFFFFFF00) | GeneratePersonalityForGender(MON_FEMALE, partyData[i].species);
|
||||
ModifyPersonalityForNature(&personality, partyData[i].nature);
|
||||
CreateMon(&gPlayerParty[i + 3], partyData[i].species, partyData[i].lvl, personality, OTID_STRUCT_PRESET(otID));
|
||||
j = partyData[i].isShiny;
|
||||
SetMonData(&gPlayerParty[i + 3], MON_DATA_IS_SHINY, &j);
|
||||
SetMonData(&gPlayerParty[i + 3], MON_DATA_HELD_ITEM, &partyData[i].heldItem);
|
||||
CustomTrainerPartyAssignMoves(&gPlayerParty[i + 3], &partyData[i]);
|
||||
|
||||
SetMonData(&gPlayerParty[i + 3], MON_DATA_IVS, &(partyData[i].iv));
|
||||
if (partyData[i].ev != NULL)
|
||||
{
|
||||
SetMonData(&gPlayerParty[i + 3], MON_DATA_HP_EV, &(partyData[i].ev[0]));
|
||||
SetMonData(&gPlayerParty[i + 3], MON_DATA_ATK_EV, &(partyData[i].ev[1]));
|
||||
SetMonData(&gPlayerParty[i + 3], MON_DATA_DEF_EV, &(partyData[i].ev[2]));
|
||||
SetMonData(&gPlayerParty[i + 3], MON_DATA_SPATK_EV, &(partyData[i].ev[3]));
|
||||
SetMonData(&gPlayerParty[i + 3], MON_DATA_SPDEF_EV, &(partyData[i].ev[4]));
|
||||
SetMonData(&gPlayerParty[i + 3], MON_DATA_SPEED_EV, &(partyData[i].ev[5]));
|
||||
}
|
||||
if (partyData[i].ability != ABILITY_NONE)
|
||||
{
|
||||
const struct SpeciesInfo *speciesInfo = &gSpeciesInfo[partyData[i].species];
|
||||
u32 maxAbilities = ARRAY_COUNT(speciesInfo->abilities);
|
||||
for (j = 0; j < maxAbilities; j++)
|
||||
{
|
||||
if (speciesInfo->abilities[j] == partyData[i].ability)
|
||||
break;
|
||||
}
|
||||
if (j < maxAbilities)
|
||||
SetMonData(&gPlayerParty[i + 3], MON_DATA_ABILITY_NUM, &j);
|
||||
}
|
||||
SetMonData(&gPlayerParty[i + 3], MON_DATA_FRIENDSHIP, &(partyData[i].friendship));
|
||||
if (partyData[i].ball < POKEBALL_COUNT)
|
||||
{
|
||||
enum PokeBall ball = partyData[i].ball;
|
||||
SetMonData(&gPlayerParty[i + 3], MON_DATA_POKEBALL, &ball);
|
||||
}
|
||||
if (partyData[i].nickname != NULL)
|
||||
{
|
||||
SetMonData(&gPlayerParty[i + 3], MON_DATA_NICKNAME, partyData[i].nickname);
|
||||
}
|
||||
CalculateMonStats(&gPlayerParty[i + 3]);
|
||||
|
||||
StringCopy(trainerName, gBattlePartners[difficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerName);
|
||||
SetMonData(&gPlayerParty[i + 3], MON_DATA_OT_NAME, trainerName);
|
||||
j = gBattlePartners[difficulty][SanitizeTrainerId(trainerId - TRAINER_PARTNER(PARTNER_NONE))].gender;
|
||||
SetMonData(&gPlayerParty[i + 3], MON_DATA_OT_GENDER, &j);
|
||||
GenerateMonFromTrainerMon(&gPlayerParty[i + 3], &partner->party[i], partnerGen);
|
||||
}
|
||||
Free(partnerGen);
|
||||
}
|
||||
else if (trainerId == TRAINER_EREADER)
|
||||
{
|
||||
|
|
@ -126,7 +69,7 @@ void FillPartnerParty(u16 trainerId)
|
|||
{
|
||||
level = SetFacilityPtrsGetLevel();
|
||||
ivs = GetFrontierTrainerFixedIvs(trainerId);
|
||||
otID = Random32();
|
||||
u32 otID = Random32();
|
||||
for (i = 0; i < FRONTIER_MULTI_PARTY_SIZE; i++)
|
||||
{
|
||||
monId = gSaveBlock2Ptr->frontier.trainerIds[i + 18];
|
||||
|
|
|
|||
|
|
@ -1,50 +1,56 @@
|
|||
#include "global.h"
|
||||
#include "battle.h"
|
||||
#include "load_save.h"
|
||||
#include "battle_setup.h"
|
||||
#include "battle_tower.h"
|
||||
#include "battle_transition.h"
|
||||
#include "data.h"
|
||||
#include "main.h"
|
||||
#include "task.h"
|
||||
#include "safari_zone.h"
|
||||
#include "script.h"
|
||||
#include "event_data.h"
|
||||
#include "metatile_behavior.h"
|
||||
#include "field_player_avatar.h"
|
||||
#include "fieldmap.h"
|
||||
#include "follower_npc.h"
|
||||
#include "random.h"
|
||||
#include "starter_choose.h"
|
||||
#include "script_pokemon_util.h"
|
||||
#include "palette.h"
|
||||
#include "window.h"
|
||||
#include "event_object_movement.h"
|
||||
#include "event_scripts.h"
|
||||
#include "tv.h"
|
||||
#include "trainer_see.h"
|
||||
#include "field_message_box.h"
|
||||
#include "sound.h"
|
||||
#include "strings.h"
|
||||
#include "trainer_hill.h"
|
||||
#include "secret_base.h"
|
||||
#include "string_util.h"
|
||||
#include "overworld.h"
|
||||
#include "field_weather.h"
|
||||
#include "battle_tower.h"
|
||||
#include "gym_leader_rematch.h"
|
||||
#include "battle.h"
|
||||
#include "battle_frontier.h"
|
||||
#include "battle_pike.h"
|
||||
#include "battle_pyramid.h"
|
||||
#include "fldeff.h"
|
||||
#include "fldeff_misc.h"
|
||||
#include "field_control_avatar.h"
|
||||
#include "mirage_tower.h"
|
||||
#include "field_screen_effect.h"
|
||||
#include "data.h"
|
||||
#include "vs_seeker.h"
|
||||
#include "item.h"
|
||||
#include "battle_setup.h"
|
||||
#include "battle_partner.h"
|
||||
#include "battle_tower.h"
|
||||
#include "battle_transition.h"
|
||||
#include "event_data.h"
|
||||
#include "event_object_movement.h"
|
||||
#include "event_scripts.h"
|
||||
#include "fieldmap.h"
|
||||
#include "script.h"
|
||||
#include "field_name_box.h"
|
||||
#include "field_control_avatar.h"
|
||||
#include "field_message_box.h"
|
||||
#include "field_player_avatar.h"
|
||||
#include "field_screen_effect.h"
|
||||
#include "field_weather.h"
|
||||
#include "fishing.h"
|
||||
#include "fldeff.h"
|
||||
#include "fldeff_misc.h"
|
||||
#include "follower_npc.h"
|
||||
#include "gym_leader_rematch.h"
|
||||
#include "item.h"
|
||||
#include "load_save.h"
|
||||
#include "malloc.h"
|
||||
#include "metatile_behavior.h"
|
||||
#include "mirage_tower.h"
|
||||
#include "palette.h"
|
||||
#include "random.h"
|
||||
#include "safari_zone.h"
|
||||
#include "script.h"
|
||||
#include "script_pokemon_util.h"
|
||||
#include "secret_base.h"
|
||||
#include "sound.h"
|
||||
#include "starter_choose.h"
|
||||
#include "strings.h"
|
||||
#include "string_util.h"
|
||||
#include "task.h"
|
||||
#include "trainer_hill.h"
|
||||
#include "trainer_pools.h"
|
||||
#include "trainer_see.h"
|
||||
#include "trainer_util.h"
|
||||
#include "tv.h"
|
||||
#include "overworld.h"
|
||||
|
||||
#include "vs_seeker.h"
|
||||
#include "window.h"
|
||||
|
||||
#include "constants/battle_frontier.h"
|
||||
#include "constants/battle_setup.h"
|
||||
#include "constants/event_objects.h"
|
||||
|
|
@ -54,7 +60,7 @@
|
|||
#include "constants/trainers.h"
|
||||
#include "constants/trainer_hill.h"
|
||||
#include "constants/weather.h"
|
||||
#include "fishing.h"
|
||||
|
||||
|
||||
enum TransitionType
|
||||
{
|
||||
|
|
@ -64,11 +70,13 @@ enum TransitionType
|
|||
TRANSITION_TYPE_WATER,
|
||||
};
|
||||
|
||||
struct TransitionData
|
||||
{
|
||||
enum BattleTransition effect;
|
||||
u16 song;
|
||||
};
|
||||
|
||||
// this file's functions
|
||||
static void DoBattlePikeWildBattle(void);
|
||||
static void DoSafariBattle(void);
|
||||
static void DoGhostBattle(void);
|
||||
static void DoStandardWildBattle(bool32 isDouble);
|
||||
static void CB2_EndWildBattle(void);
|
||||
static void CB2_EndScriptedWildBattle(void);
|
||||
static void CB2_EndMarowakBattle(void);
|
||||
|
|
@ -88,6 +96,9 @@ static void RegisterTrainerInMatchCall(void);
|
|||
static void HandleRematchVarsOnBattleEnd(void);
|
||||
static const u8 *GetIntroSpeechOfApproachingTrainer(void);
|
||||
static const u8 *GetTrainerCantBattleSpeech(void);
|
||||
static void CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 firstTrainer);
|
||||
static void DoTrainerBattle(void);
|
||||
static struct TransitionData GetLegendaryBattleTransition(void);
|
||||
|
||||
EWRAM_DATA TrainerBattleParameter gTrainerBattleParameter = {0};
|
||||
EWRAM_DATA u16 gPartnerTrainerId = 0;
|
||||
|
|
@ -327,305 +338,172 @@ static bool8 CheckSilphScopeInPokemonTower(u16 mapGroup, u16 mapNum)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
void BattleSetup_StartWildBattle(void)
|
||||
{
|
||||
if (GetSafariZoneFlag())
|
||||
DoSafariBattle();
|
||||
else if (CheckSilphScopeInPokemonTower(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum))
|
||||
DoGhostBattle();
|
||||
else
|
||||
DoStandardWildBattle(FALSE);
|
||||
}
|
||||
|
||||
void BattleSetup_StartDoubleWildBattle(void)
|
||||
{
|
||||
DoStandardWildBattle(TRUE);
|
||||
}
|
||||
|
||||
void BattleSetup_StartBattlePikeWildBattle(void)
|
||||
{
|
||||
DoBattlePikeWildBattle();
|
||||
}
|
||||
|
||||
static void DoStandardWildBattle(bool32 isDouble)
|
||||
void BattleSetup_StartWildBattle(bool32 isDouble)
|
||||
{
|
||||
LockPlayerFieldControls();
|
||||
FreezeObjectEvents();
|
||||
StopPlayerAvatar();
|
||||
gMain.savedCallback = CB2_EndWildBattle;
|
||||
gBattleTypeFlags = 0;
|
||||
if (IsNPCFollowerWildBattle())
|
||||
{
|
||||
gBattleTypeFlags |= BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_DOUBLE;
|
||||
}
|
||||
|
||||
if (GetSafariZoneFlag() && !isDouble)
|
||||
gBattleTypeFlags = BATTLE_TYPE_SAFARI;
|
||||
else if (CheckSilphScopeInPokemonTower(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum) && !isDouble)
|
||||
gBattleTypeFlags = BATTLE_TYPE_GHOST;
|
||||
else if (IsNPCFollowerWildBattle())
|
||||
gBattleTypeFlags = BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_DOUBLE;
|
||||
else if (isDouble)
|
||||
gBattleTypeFlags |= BATTLE_TYPE_DOUBLE;
|
||||
gBattleTypeFlags = BATTLE_TYPE_DOUBLE;
|
||||
else
|
||||
gBattleTypeFlags = BATTLE_TYPE_BASIC_WILD;
|
||||
if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE)
|
||||
{
|
||||
VarSet(VAR_TEMP_E, 0);
|
||||
gBattleTypeFlags |= BATTLE_TYPE_PYRAMID;
|
||||
}
|
||||
CreateBattleStartTask(GetWildBattleTransition(), 0);
|
||||
IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
|
||||
IncrementGameStat(GAME_STAT_WILD_BATTLES);
|
||||
IncrementDailyWildBattles();
|
||||
TryUpdateGymLeaderRematchFromWild();
|
||||
DoBattleSetup(FALSE);
|
||||
}
|
||||
|
||||
void DoStandardWildBattle_Debug(void)
|
||||
void BattleSetup_StartMultiBattle(void)
|
||||
{
|
||||
LockPlayerFieldControls();
|
||||
FreezeObjectEvents();
|
||||
StopPlayerAvatar();
|
||||
gMain.savedCallback = CB2_EndWildBattle;
|
||||
gBattleTypeFlags = 0;
|
||||
if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE)
|
||||
if (gSpecialVar_0x8005 & MULTI_BATTLE_2_VS_WILD) // Player + AI against wild mon
|
||||
gBattleTypeFlags = BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER;
|
||||
else if (gSpecialVar_0x8005 & MULTI_BATTLE_2_VS_1) // Player + AI against one trainer
|
||||
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER;
|
||||
else // MULTI_BATTLE_2_VS_2
|
||||
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER;
|
||||
|
||||
if (gSpecialVar_0x8005 & MULTI_BATTLE_CHOOSE_MONS) // Skip mons restoring(done in the script)
|
||||
gBattleScripting.specialTrainerBattleType = 0xFF;
|
||||
|
||||
DoBattleSetup(FALSE);
|
||||
}
|
||||
|
||||
static void IncrementBattleStats()
|
||||
{
|
||||
IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
|
||||
{
|
||||
VarSet(VAR_TEMP_PLAYING_PYRAMID_MUSIC, 0);
|
||||
gBattleTypeFlags |= BATTLE_TYPE_PYRAMID;
|
||||
IncrementGameStat(GAME_STAT_WILD_BATTLES);
|
||||
IncrementDailyWildBattles();
|
||||
TryUpdateGymLeaderRematchFromWild();
|
||||
}
|
||||
else
|
||||
{
|
||||
IncrementGameStat(GAME_STAT_TRAINER_BATTLES);
|
||||
TryUpdateGymLeaderRematchFromTrainer();
|
||||
}
|
||||
CreateBattleStartTask_Debug(GetWildBattleTransition(), 0);
|
||||
//IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
|
||||
//IncrementGameStat(GAME_STAT_WILD_BATTLES);
|
||||
//IncrementDailyWildBattles();
|
||||
//TryUpdateGymLeaderRematchFromWild();
|
||||
}
|
||||
|
||||
void BattleSetup_StartRoamerBattle(void)
|
||||
#define ADD_DEFAULT_SONG(transition) (struct TransitionData){transition, 0}
|
||||
static struct TransitionData GetBattleTransition(void)
|
||||
{
|
||||
LockPlayerFieldControls();
|
||||
FreezeObjectEvents();
|
||||
StopPlayerAvatar();
|
||||
gMain.savedCallback = CB2_EndWildBattle;
|
||||
gBattleTypeFlags = BATTLE_TYPE_ROAMER;
|
||||
CreateBattleStartTask(GetWildBattleTransition(), 0);
|
||||
IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
|
||||
IncrementGameStat(GAME_STAT_WILD_BATTLES);
|
||||
IncrementDailyWildBattles();
|
||||
TryUpdateGymLeaderRematchFromWild();
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_PYRAMID)
|
||||
return ADD_DEFAULT_SONG(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_PYRAMID));
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL)
|
||||
return ADD_DEFAULT_SONG(GetSpecialBattleTransition(B_TRANSITION_GROUP_TRAINER_HILL));
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
|
||||
return ADD_DEFAULT_SONG(GetTrainerBattleTransition());
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_CATCH_TUTORIAL)
|
||||
return (struct TransitionData) {B_TRANSITION_SLICE, 0};
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY)
|
||||
return GetLegendaryBattleTransition();
|
||||
else
|
||||
return ADD_DEFAULT_SONG(GetWildBattleTransition());
|
||||
}
|
||||
|
||||
static void DoSafariBattle(void)
|
||||
static void FillEnnemyParties()
|
||||
{
|
||||
LockPlayerFieldControls();
|
||||
FreezeObjectEvents();
|
||||
StopPlayerAvatar();
|
||||
gMain.savedCallback = CB2_EndSafariBattle;
|
||||
gBattleTypeFlags = BATTLE_TYPE_SAFARI;
|
||||
CreateBattleStartTask(GetWildBattleTransition(), 0);
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_PYRAMID)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
FillFrontierTrainersParties(1);
|
||||
else
|
||||
FillFrontierTrainerParty(1);
|
||||
return;
|
||||
}
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
FillHillTrainersParties();
|
||||
else
|
||||
FillHillTrainerParty();
|
||||
return;
|
||||
}
|
||||
CreateNPCTrainerParty(&gEnemyParty[0], TRAINER_BATTLE_PARAM.opponentA, TRUE);
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && !BATTLE_TWO_VS_ONE_OPPONENT)
|
||||
CreateNPCTrainerParty(&gEnemyParty[PARTY_SIZE / 2], TRAINER_BATTLE_PARAM.opponentB, FALSE);
|
||||
}
|
||||
|
||||
static void DoGhostBattle(void)
|
||||
void DoBattleSetup(bool32 fromScript)
|
||||
{
|
||||
LockPlayerFieldControls();
|
||||
FreezeObjectEvents();
|
||||
StopPlayerAvatar();
|
||||
gMain.savedCallback = CB2_EndWildBattle;
|
||||
gBattleTypeFlags = BATTLE_TYPE_GHOST;
|
||||
CreateBattleStartTask(GetWildBattleTransition(), 0);
|
||||
SetMonData(&gEnemyParty[0], MON_DATA_NICKNAME, gText_Ghost);
|
||||
IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
|
||||
IncrementGameStat(GAME_STAT_WILD_BATTLES);
|
||||
}
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
|
||||
gMain.savedCallback = CB2_EndSafariBattle;
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
|
||||
gMain.savedCallback = CB2_EndTrainerBattle;
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_CATCH_TUTORIAL)
|
||||
gMain.savedCallback = CB2_ReturnToFieldContinueScriptPlayMapMusic;
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_GHOST && fromScript)
|
||||
gMain.savedCallback = CB2_EndMarowakBattle;
|
||||
else if (fromScript)
|
||||
gMain.savedCallback = CB2_EndScriptedWildBattle;
|
||||
else
|
||||
gMain.savedCallback = CB2_EndWildBattle;
|
||||
|
||||
static void DoBattlePikeWildBattle(void)
|
||||
{
|
||||
LockPlayerFieldControls();
|
||||
FreezeObjectEvents();
|
||||
StopPlayerAvatar();
|
||||
gMain.savedCallback = CB2_EndWildBattle;
|
||||
gBattleTypeFlags = BATTLE_TYPE_PIKE;
|
||||
CreateBattleStartTask(GetWildBattleTransition(), 0);
|
||||
IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
|
||||
IncrementGameStat(GAME_STAT_WILD_BATTLES);
|
||||
IncrementDailyWildBattles();
|
||||
TryUpdateGymLeaderRematchFromWild();
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
|
||||
FillEnnemyParties();
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
|
||||
FillPartnerParty(gPartnerTrainerId);
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_GHOST)
|
||||
SetMonData(&gEnemyParty[0], MON_DATA_NICKNAME, gText_Ghost);
|
||||
struct TransitionData transition = GetBattleTransition();
|
||||
CreateBattleStartTask(transition.effect, transition.song);
|
||||
if (!(gBattleTypeFlags & (BATTLE_TYPE_SAFARI | BATTLE_TYPE_CATCH_TUTORIAL)))
|
||||
IncrementBattleStats();
|
||||
}
|
||||
|
||||
static void DoTrainerBattle(void)
|
||||
{
|
||||
CreateNPCTrainerParty(&gEnemyParty[0], TRAINER_BATTLE_PARAM.opponentA, TRUE);
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && !BATTLE_TWO_VS_ONE_OPPONENT)
|
||||
CreateNPCTrainerParty(&gEnemyParty[PARTY_SIZE / 2], TRAINER_BATTLE_PARAM.opponentB, FALSE);
|
||||
CreateBattleStartTask(GetTrainerBattleTransition(), 0);
|
||||
IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
|
||||
IncrementGameStat(GAME_STAT_TRAINER_BATTLES);
|
||||
TryUpdateGymLeaderRematchFromTrainer();
|
||||
}
|
||||
|
||||
static void DoBattlePyramidTrainerHillBattle(void)
|
||||
static struct TransitionData GetLegendaryBattleTransition(void)
|
||||
{
|
||||
if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE)
|
||||
CreateBattleStartTask(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_PYRAMID), 0);
|
||||
else
|
||||
CreateBattleStartTask(GetSpecialBattleTransition(B_TRANSITION_GROUP_TRAINER_HILL), 0);
|
||||
|
||||
IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
|
||||
IncrementGameStat(GAME_STAT_TRAINER_BATTLES);
|
||||
TryUpdateGymLeaderRematchFromTrainer();
|
||||
}
|
||||
|
||||
// Initiates battle where Wally catches Ralts
|
||||
void StartWallyTutorialBattle(void)
|
||||
{
|
||||
CreateMaleMon(&gEnemyParty[0], SPECIES_RALTS, 5);
|
||||
LockPlayerFieldControls();
|
||||
gMain.savedCallback = CB2_ReturnToFieldContinueScriptPlayMapMusic;
|
||||
gBattleTypeFlags = BATTLE_TYPE_CATCH_TUTORIAL;
|
||||
CreateBattleStartTask(B_TRANSITION_SLICE, 0);
|
||||
}
|
||||
|
||||
void StartOldManTutorialBattle(void)
|
||||
{
|
||||
CreateMaleMon(&gEnemyParty[0], SPECIES_WEEDLE, 5);
|
||||
LockPlayerFieldControls();
|
||||
gMain.savedCallback = CB2_ReturnToFieldContinueScriptPlayMapMusic;
|
||||
gBattleTypeFlags = BATTLE_TYPE_CATCH_TUTORIAL;
|
||||
CreateBattleStartTask(B_TRANSITION_SLICE, 0);
|
||||
}
|
||||
|
||||
void BattleSetup_StartScriptedWildBattle(void)
|
||||
{
|
||||
LockPlayerFieldControls();
|
||||
gMain.savedCallback = CB2_EndScriptedWildBattle;
|
||||
gBattleTypeFlags = 0;
|
||||
CreateBattleStartTask(GetWildBattleTransition(), 0);
|
||||
IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
|
||||
IncrementGameStat(GAME_STAT_WILD_BATTLES);
|
||||
IncrementDailyWildBattles();
|
||||
TryUpdateGymLeaderRematchFromWild();
|
||||
}
|
||||
|
||||
void BattleSetup_StartScriptedDoubleWildBattle(void)
|
||||
{
|
||||
LockPlayerFieldControls();
|
||||
gMain.savedCallback = CB2_EndScriptedWildBattle;
|
||||
gBattleTypeFlags = BATTLE_TYPE_DOUBLE;
|
||||
CreateBattleStartTask(GetWildBattleTransition(), 0);
|
||||
IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
|
||||
IncrementGameStat(GAME_STAT_WILD_BATTLES);
|
||||
IncrementDailyWildBattles();
|
||||
TryUpdateGymLeaderRematchFromWild();
|
||||
}
|
||||
|
||||
void StartMarowakBattle(void)
|
||||
{
|
||||
LockPlayerFieldControls();
|
||||
gMain.savedCallback = CB2_EndMarowakBattle;
|
||||
gBattleTypeFlags = BATTLE_TYPE_GHOST;
|
||||
|
||||
if (CheckBagHasItem(ITEM_SILPH_SCOPE, 1))
|
||||
{
|
||||
u32 personality = GetMonPersonality(SPECIES_MAROWAK, MON_FEMALE, NATURE_SERIOUS, RANDOM_UNOWN_LETTER);
|
||||
|
||||
CreateMonWithIVsPersonality(&gEnemyParty[0], SPECIES_MAROWAK, 30, 31, personality);
|
||||
}
|
||||
|
||||
CreateBattleStartTask(GetWildBattleTransition(), 0);
|
||||
SetMonData(&gEnemyParty[0], MON_DATA_NICKNAME, gText_Ghost);
|
||||
IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
|
||||
IncrementGameStat(GAME_STAT_WILD_BATTLES);
|
||||
}
|
||||
|
||||
void BattleSetup_StartLatiBattle(void)
|
||||
{
|
||||
LockPlayerFieldControls();
|
||||
gMain.savedCallback = CB2_EndScriptedWildBattle;
|
||||
gBattleTypeFlags = BATTLE_TYPE_LEGENDARY;
|
||||
CreateBattleStartTask(GetWildBattleTransition(), 0);
|
||||
IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
|
||||
IncrementGameStat(GAME_STAT_WILD_BATTLES);
|
||||
IncrementDailyWildBattles();
|
||||
TryUpdateGymLeaderRematchFromWild();
|
||||
}
|
||||
|
||||
void BattleSetup_StartLegendaryBattle(void)
|
||||
{
|
||||
LockPlayerFieldControls();
|
||||
gMain.savedCallback = CB2_EndScriptedWildBattle;
|
||||
gBattleTypeFlags = BATTLE_TYPE_LEGENDARY;
|
||||
|
||||
switch (GetMonData(&gEnemyParty[0], MON_DATA_SPECIES))
|
||||
{
|
||||
case SPECIES_REGIROCK:
|
||||
return (struct TransitionData) {B_TRANSITION_REGIROCK, MUS_VS_REGI};
|
||||
case SPECIES_REGICE:
|
||||
return (struct TransitionData) {B_TRANSITION_REGICE, MUS_VS_REGI};
|
||||
case SPECIES_REGISTEEL:
|
||||
return (struct TransitionData) {B_TRANSITION_REGISTEEL, MUS_VS_REGI};
|
||||
case SPECIES_GROUDON:
|
||||
case SPECIES_GROUDON_PRIMAL:
|
||||
CreateBattleStartTask(B_TRANSITION_GROUDON, MUS_VS_KYOGRE_GROUDON);
|
||||
break;
|
||||
return (struct TransitionData) {B_TRANSITION_GROUDON, MUS_VS_KYOGRE_GROUDON};
|
||||
case SPECIES_KYOGRE:
|
||||
case SPECIES_KYOGRE_PRIMAL:
|
||||
CreateBattleStartTask(B_TRANSITION_KYOGRE, MUS_VS_KYOGRE_GROUDON);
|
||||
break;
|
||||
return (struct TransitionData) {B_TRANSITION_KYOGRE, MUS_VS_KYOGRE_GROUDON};
|
||||
case SPECIES_RAYQUAZA:
|
||||
case SPECIES_RAYQUAZA_MEGA:
|
||||
CreateBattleStartTask(B_TRANSITION_RAYQUAZA, MUS_VS_RAYQUAZA);
|
||||
break;
|
||||
return (struct TransitionData) {B_TRANSITION_RAYQUAZA, MUS_VS_RAYQUAZA};
|
||||
case SPECIES_DEOXYS_NORMAL:
|
||||
case SPECIES_DEOXYS_ATTACK:
|
||||
case SPECIES_DEOXYS_DEFENSE:
|
||||
case SPECIES_DEOXYS_SPEED:
|
||||
CreateBattleStartTask(B_TRANSITION_BLUR, MUS_RG_VS_DEOXYS);
|
||||
break;
|
||||
case SPECIES_LUGIA:
|
||||
case SPECIES_HO_OH:
|
||||
default:
|
||||
CreateBattleStartTask(B_TRANSITION_BLUR, MUS_RG_VS_LEGEND);
|
||||
break;
|
||||
return (struct TransitionData) {B_TRANSITION_BLUR, MUS_RG_VS_DEOXYS};
|
||||
case SPECIES_MEW:
|
||||
CreateBattleStartTask(B_TRANSITION_GRID_SQUARES, MUS_VS_MEW);
|
||||
break;
|
||||
}
|
||||
|
||||
IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
|
||||
IncrementGameStat(GAME_STAT_WILD_BATTLES);
|
||||
IncrementDailyWildBattles();
|
||||
TryUpdateGymLeaderRematchFromWild();
|
||||
}
|
||||
|
||||
void StartGroudonKyogreBattle(void)
|
||||
{
|
||||
LockPlayerFieldControls();
|
||||
gMain.savedCallback = CB2_EndScriptedWildBattle;
|
||||
gBattleTypeFlags = BATTLE_TYPE_LEGENDARY;
|
||||
|
||||
if (gGameVersion == VERSION_RUBY)
|
||||
CreateBattleStartTask(B_TRANSITION_ANGLED_WIPES, MUS_VS_KYOGRE_GROUDON); // GROUDON
|
||||
else
|
||||
CreateBattleStartTask(B_TRANSITION_RIPPLE, MUS_VS_KYOGRE_GROUDON); // KYOGRE
|
||||
|
||||
IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
|
||||
IncrementGameStat(GAME_STAT_WILD_BATTLES);
|
||||
IncrementDailyWildBattles();
|
||||
TryUpdateGymLeaderRematchFromWild();
|
||||
}
|
||||
|
||||
void StartRegiBattle(void)
|
||||
{
|
||||
enum BattleTransition transitionId;
|
||||
enum Species species;
|
||||
|
||||
LockPlayerFieldControls();
|
||||
gMain.savedCallback = CB2_EndScriptedWildBattle;
|
||||
gBattleTypeFlags = BATTLE_TYPE_LEGENDARY;
|
||||
|
||||
species = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES);
|
||||
switch (species)
|
||||
{
|
||||
case SPECIES_REGIROCK:
|
||||
transitionId = B_TRANSITION_REGIROCK;
|
||||
break;
|
||||
case SPECIES_REGICE:
|
||||
transitionId = B_TRANSITION_REGICE;
|
||||
break;
|
||||
case SPECIES_REGISTEEL:
|
||||
transitionId = B_TRANSITION_REGISTEEL;
|
||||
break;
|
||||
return (struct TransitionData) {B_TRANSITION_GRID_SQUARES, MUS_VS_MEW};
|
||||
case SPECIES_LATIOS:
|
||||
case SPECIES_LATIAS:
|
||||
return (struct TransitionData) {GetWildBattleTransition(), 0};
|
||||
default:
|
||||
transitionId = B_TRANSITION_GRID_SQUARES;
|
||||
break;
|
||||
return (struct TransitionData) {B_TRANSITION_BLUR, MUS_RG_VS_LEGEND};
|
||||
}
|
||||
CreateBattleStartTask(transitionId, MUS_VS_REGI);
|
||||
|
||||
IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
|
||||
IncrementGameStat(GAME_STAT_WILD_BATTLES);
|
||||
IncrementDailyWildBattles();
|
||||
TryUpdateGymLeaderRematchFromWild();
|
||||
}
|
||||
|
||||
static void DowngradeBadPoison(void)
|
||||
|
|
@ -1056,30 +934,6 @@ void TrainerBattleLoadArgs(const u8 *data)
|
|||
sTrainerBattleEndScript = (u8*)data + sizeof(TrainerBattleParameter);
|
||||
}
|
||||
|
||||
void TrainerBattleLoadArgsTrainerA(const u8 *data)
|
||||
{
|
||||
TrainerBattleParameter *temp = (TrainerBattleParameter*)data;
|
||||
|
||||
TRAINER_BATTLE_PARAM.playMusicA = temp->params.playMusicA;
|
||||
TRAINER_BATTLE_PARAM.objEventLocalIdA = temp->params.objEventLocalIdA;
|
||||
TRAINER_BATTLE_PARAM.opponentA = temp->params.opponentA;
|
||||
TRAINER_BATTLE_PARAM.introTextA = temp->params.introTextA;
|
||||
TRAINER_BATTLE_PARAM.defeatTextA = temp->params.defeatTextA;
|
||||
TRAINER_BATTLE_PARAM.battleScriptRetAddrA = temp->params.battleScriptRetAddrA;
|
||||
}
|
||||
|
||||
void TrainerBattleLoadArgsTrainerB(const u8 *data)
|
||||
{
|
||||
TrainerBattleParameter *temp = (TrainerBattleParameter*)data;
|
||||
|
||||
TRAINER_BATTLE_PARAM.playMusicB = temp->params.playMusicB;
|
||||
TRAINER_BATTLE_PARAM.objEventLocalIdB = temp->params.objEventLocalIdB;
|
||||
TRAINER_BATTLE_PARAM.opponentB = temp->params.opponentB;
|
||||
TRAINER_BATTLE_PARAM.introTextB = temp->params.introTextB;
|
||||
TRAINER_BATTLE_PARAM.defeatTextB = temp->params.defeatTextB;
|
||||
TRAINER_BATTLE_PARAM.battleScriptRetAddrB = temp->params.battleScriptRetAddrB;
|
||||
}
|
||||
|
||||
// loads trainer A parameter to trainer B. Used for second trainer in trainer_see.c
|
||||
void TrainerBattleLoadArgsSecondTrainer(const u8 *data)
|
||||
{
|
||||
|
|
@ -1299,25 +1153,12 @@ void ClearTrainerFlag(u16 trainerId)
|
|||
|
||||
void BattleSetup_StartTrainerBattle(void)
|
||||
{
|
||||
gBattleTypeFlags = BATTLE_TYPE_TRAINER;
|
||||
if (gNoOfApproachingTrainers == 2)
|
||||
{
|
||||
if (FollowerNPCIsBattlePartner())
|
||||
gBattleTypeFlags = (BATTLE_TYPE_MULTI | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_TRAINER);
|
||||
else
|
||||
gBattleTypeFlags = (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_TRAINER);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FollowerNPCIsBattlePartner())
|
||||
{
|
||||
gBattleTypeFlags = (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TRAINER);
|
||||
TRAINER_BATTLE_PARAM.opponentB = 0xFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleTypeFlags = (BATTLE_TYPE_TRAINER);
|
||||
}
|
||||
}
|
||||
gBattleTypeFlags |= (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS);
|
||||
|
||||
if (FollowerNPCIsBattlePartner())
|
||||
gBattleTypeFlags |= (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER);
|
||||
|
||||
if (GetTrainerBattleMode() == TRAINER_BATTLE_EARLY_RIVAL && GetRivalBattleFlags() & RIVAL_BATTLE_TUTORIAL)
|
||||
gBattleTypeFlags |= BATTLE_TYPE_FIRST_BATTLE;
|
||||
|
|
@ -1326,33 +1167,11 @@ void BattleSetup_StartTrainerBattle(void)
|
|||
{
|
||||
VarSet(VAR_TEMP_PLAYING_PYRAMID_MUSIC, 0);
|
||||
gBattleTypeFlags |= BATTLE_TYPE_PYRAMID;
|
||||
|
||||
if (gNoOfApproachingTrainers == 2)
|
||||
{
|
||||
FillFrontierTrainersParties(1);
|
||||
ZeroMonData(&gEnemyParty[1]);
|
||||
ZeroMonData(&gEnemyParty[2]);
|
||||
ZeroMonData(&gEnemyParty[4]);
|
||||
ZeroMonData(&gEnemyParty[5]);
|
||||
}
|
||||
else
|
||||
{
|
||||
FillFrontierTrainerParty(1);
|
||||
ZeroMonData(&gEnemyParty[1]);
|
||||
ZeroMonData(&gEnemyParty[2]);
|
||||
}
|
||||
|
||||
MarkApproachingPyramidTrainersAsBattled();
|
||||
}
|
||||
else if (InTrainerHillChallenge())
|
||||
{
|
||||
gBattleTypeFlags |= BATTLE_TYPE_TRAINER_HILL;
|
||||
|
||||
if (gNoOfApproachingTrainers == 2)
|
||||
FillHillTrainersParties();
|
||||
else
|
||||
FillHillTrainerParty();
|
||||
|
||||
SetHillTrainerFlag();
|
||||
}
|
||||
else if (GetTrainerBattleType(TRAINER_BATTLE_PARAM.opponentA) == TRAINER_BATTLE_TYPE_DOUBLES)
|
||||
|
|
@ -1364,12 +1183,8 @@ void BattleSetup_StartTrainerBattle(void)
|
|||
gNoOfApproachingTrainers = 0;
|
||||
sShouldCheckTrainerBScript = FALSE;
|
||||
gWhichTrainerToFaceAfterBattle = 0;
|
||||
gMain.savedCallback = CB2_EndTrainerBattle;
|
||||
|
||||
if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || InTrainerHillChallenge())
|
||||
DoBattlePyramidTrainerHillBattle();
|
||||
else
|
||||
DoTrainerBattle();
|
||||
DoBattleSetup(FALSE);
|
||||
|
||||
ScriptContext_Stop();
|
||||
}
|
||||
|
|
@ -2130,3 +1945,67 @@ void SetMultiTrainerBattle(struct ScriptContext *ctx)
|
|||
TRAINER_BATTLE_PARAM.defeatTextB = (u8*)ScriptReadWord(ctx);
|
||||
gPartnerTrainerId = TRAINER_PARTNER(ScriptReadHalfword(ctx));
|
||||
};
|
||||
|
||||
static void MakeTrainerGenerator(struct TrainerGenerator *trainerGen, const struct Trainer *trainer)
|
||||
{
|
||||
trainerGen->gender = trainer->gender;
|
||||
trainerGen->isFrontier = FALSE;
|
||||
StringCopyN(trainerGen->name, trainer->trainerName, TRAINER_NAME_LENGTH + 1);
|
||||
trainerGen->trainerClass = trainer->trainerClass;
|
||||
trainerGen->otID = OTID_STRUCT_RANDOM_NO_SHINY;
|
||||
trainerGen->localRngState = GeneratePartySeed(trainer);
|
||||
}
|
||||
|
||||
void CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer *trainer, bool32 firstTrainer)
|
||||
{
|
||||
s32 i;
|
||||
u8 monsCount;
|
||||
|
||||
if (firstTrainer == TRUE)
|
||||
ZeroEnemyPartyMons();
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && trainer->partySize > PARTY_SIZE / 2)
|
||||
monsCount = PARTY_SIZE / 2;
|
||||
else
|
||||
monsCount = trainer->partySize;
|
||||
|
||||
u32 monIndices[monsCount];
|
||||
struct TrainerGenerator *trainerGen = AllocZeroed(sizeof(struct TrainerGenerator));
|
||||
MakeTrainerGenerator(trainerGen, trainer);
|
||||
DoTrainerPartyPool(trainer, monIndices, monsCount, gBattleTypeFlags);
|
||||
|
||||
for (i = 0; i < monsCount; i++)
|
||||
{
|
||||
u32 monIndex = monIndices[i];
|
||||
GenerateMonFromTrainerMon(&party[i], &trainer->party[monIndex], trainerGen);
|
||||
}
|
||||
Free(trainerGen);
|
||||
}
|
||||
|
||||
static void CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 firstTrainer)
|
||||
{
|
||||
if (!GetTrainerStructFromId(trainerNum)->overrideTrainer) {
|
||||
CreateNPCTrainerPartyFromTrainer(party, GetTrainerStructFromId(trainerNum), firstTrainer);
|
||||
return;
|
||||
}
|
||||
|
||||
struct Trainer tempTrainer;
|
||||
memcpy(&tempTrainer, GetTrainerStructFromId(trainerNum), sizeof(struct Trainer));
|
||||
const struct Trainer *origTrainer = GetTrainerStructFromId(tempTrainer.overrideTrainer);
|
||||
|
||||
tempTrainer.party = origTrainer->party;
|
||||
|
||||
tempTrainer.poolSize = origTrainer->poolSize;
|
||||
if (tempTrainer.partySize == 0)
|
||||
tempTrainer.partySize = origTrainer->partySize;
|
||||
CreateNPCTrainerPartyFromTrainer(party, (const struct Trainer *)(&tempTrainer), firstTrainer);
|
||||
}
|
||||
|
||||
void CreateTrainerPartyForPlayer(void)
|
||||
{
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
|
||||
ZeroPlayerPartyMons();
|
||||
gPartnerTrainerId = gSpecialVar_0x8004;
|
||||
CreateNPCTrainerPartyFromTrainer(gPlayerParty, GetTrainerStructFromId(gSpecialVar_0x8004), TRUE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
#include "task.h"
|
||||
#include "text.h"
|
||||
#include "constants/battle_frontier.h"
|
||||
#include "constants/battle_special.h"
|
||||
|
||||
static void HandleSpecialTrainerBattleEnd(void);
|
||||
static void Task_StartBattleAfterTransition(u8 taskId);
|
||||
|
|
@ -96,31 +95,8 @@ void DoSpecialTrainerBattle(void)
|
|||
#endif //FREE_BATTLE_TOWER_E_READER
|
||||
break;
|
||||
case SPECIAL_BATTLE_MULTI:
|
||||
if (gSpecialVar_0x8005 & MULTI_BATTLE_2_VS_WILD) // Player + AI against wild mon
|
||||
{
|
||||
gBattleTypeFlags = BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER;
|
||||
}
|
||||
else if (gSpecialVar_0x8005 & MULTI_BATTLE_2_VS_1) // Player + AI against one trainer
|
||||
{
|
||||
TRAINER_BATTLE_PARAM.opponentB = 0xFFFF;
|
||||
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER;
|
||||
}
|
||||
else // MULTI_BATTLE_2_VS_2
|
||||
{
|
||||
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER;
|
||||
}
|
||||
|
||||
FillPartnerParty(gPartnerTrainerId);
|
||||
CreateTask(Task_StartBattleAfterTransition, 1);
|
||||
PlayMapChosenOrBattleBGM(0);
|
||||
if (gSpecialVar_0x8005 & MULTI_BATTLE_2_VS_WILD)
|
||||
BattleTransition_StartOnField(GetWildBattleTransition());
|
||||
else
|
||||
BattleTransition_StartOnField(GetTrainerBattleTransition());
|
||||
|
||||
if (gSpecialVar_0x8005 & MULTI_BATTLE_CHOOSE_MONS) // Skip mons restoring(done in the script)
|
||||
gBattleScripting.specialTrainerBattleType = 0xFF;
|
||||
break;
|
||||
default:
|
||||
errorf("Unknown special battle type %d", gSpecialVar_0x8004);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
11
src/debug.c
11
src/debug.c
|
|
@ -2164,12 +2164,13 @@ static void DebugAction_Trainers_TryBattle(u8 taskId)
|
|||
}
|
||||
gBattleTypeFlags = BATTLE_TYPE_TRAINER;
|
||||
TRAINER_BATTLE_PARAM.opponentA = trainer1Id;
|
||||
TRAINER_BATTLE_PARAM.opponentB = 0xFFFF;
|
||||
TRAINER_BATTLE_PARAM.opponentB = trainer2Id;
|
||||
CreateNPCTrainerPartyFromTrainer(&gEnemyParty[0], GetTrainerStructFromId(trainer1Id), TRUE);
|
||||
if (sDebugMenuListData->data[5] || partnerId != PARTNER_NONE || trainer2Id != TRAINER_NONE)
|
||||
gBattleTypeFlags |= BATTLE_TYPE_DOUBLE;
|
||||
if (trainer2Id != TRAINER_NONE)
|
||||
{
|
||||
TRAINER_BATTLE_PARAM.opponentB = trainer2Id;
|
||||
CreateNPCTrainerPartyFromTrainer(&gEnemyParty[PARTY_SIZE / 2], GetTrainerStructFromId(trainer2Id), FALSE);
|
||||
gBattleTypeFlags |= BATTLE_TYPE_TWO_OPPONENTS;
|
||||
}
|
||||
if (partnerId != PARTNER_NONE)
|
||||
|
|
@ -4898,7 +4899,7 @@ const struct Trainer* GetDebugAiTrainer(void)
|
|||
static void DebugAction_Party_SetParty(u8 taskId)
|
||||
{
|
||||
ZeroPlayerPartyMons();
|
||||
CreateNPCTrainerPartyFromTrainer(gPlayerParty, &sDebugTrainers[DIFFICULTY_NORMAL][DEBUG_TRAINER_PLAYER], TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(gPlayerParty, &sDebugTrainers[DIFFICULTY_NORMAL][DEBUG_TRAINER_PLAYER], TRUE);
|
||||
ScriptContext_Enable();
|
||||
Debug_DestroyMenu_Full(taskId);
|
||||
}
|
||||
|
|
@ -4907,8 +4908,8 @@ static void DebugAction_Party_BattleSingle(u8 taskId)
|
|||
{
|
||||
ZeroPlayerPartyMons();
|
||||
ZeroEnemyPartyMons();
|
||||
CreateNPCTrainerPartyFromTrainer(gPlayerParty, &sDebugTrainers[DIFFICULTY_NORMAL][DEBUG_TRAINER_PLAYER], TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(gEnemyParty, GetDebugAiTrainer(), FALSE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(gPlayerParty, &sDebugTrainers[DIFFICULTY_NORMAL][DEBUG_TRAINER_PLAYER], TRUE);
|
||||
CreateNPCTrainerPartyFromTrainer(gEnemyParty, GetDebugAiTrainer(), FALSE);
|
||||
|
||||
gBattleTypeFlags = BATTLE_TYPE_TRAINER;
|
||||
if (sDebugTrainers[DIFFICULTY_NORMAL][DEBUG_TRAINER_AI].battleType == TRAINER_BATTLE_TYPE_DOUBLES)
|
||||
|
|
|
|||
|
|
@ -1516,14 +1516,6 @@ u32 GetMonPersonality(enum Species species, u8 gender, u8 nature, u8 unownLetter
|
|||
return personality;
|
||||
}
|
||||
|
||||
// This is only used to create Wally's Ralts.
|
||||
void CreateMaleMon(struct Pokemon *mon, enum Species species, u8 level)
|
||||
{
|
||||
u32 personality = GetMonPersonality(species, MON_MALE, NATURE_RANDOM, RANDOM_UNOWN_LETTER);
|
||||
CreateMonWithIVs(mon, species, level, personality, OTID_STRUCT_PLAYER_ID, USE_RANDOM_IVS);
|
||||
GiveMonInitialMoveset(mon);
|
||||
}
|
||||
|
||||
void CreateMonWithIVsPersonality(struct Pokemon *mon, enum Species species, u8 level, u32 ivs, u32 personality)
|
||||
{
|
||||
CreateMon(mon, species, level, personality, OTID_STRUCT_PLAYER_ID);
|
||||
|
|
@ -6081,60 +6073,57 @@ static inline bool32 CanFirstMonBoostHeldItemRarity(void)
|
|||
|
||||
void SetWildMonHeldItem(void)
|
||||
{
|
||||
if (!(gBattleTypeFlags & (BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_TRAINER | BATTLE_TYPE_PYRAMID | BATTLE_TYPE_PIKE)))
|
||||
u16 rnd;
|
||||
enum Species species;
|
||||
u16 count = (WILD_DOUBLE_BATTLE) ? 2 : 1;
|
||||
u16 i;
|
||||
bool32 itemHeldBoost = CanFirstMonBoostHeldItemRarity();
|
||||
u16 chanceNoItem = itemHeldBoost ? 20 : 45;
|
||||
u16 chanceNotRare = itemHeldBoost ? 80 : 95;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
u16 rnd;
|
||||
enum Species species;
|
||||
u16 count = (WILD_DOUBLE_BATTLE) ? 2 : 1;
|
||||
u16 i;
|
||||
bool32 itemHeldBoost = CanFirstMonBoostHeldItemRarity();
|
||||
u16 chanceNoItem = itemHeldBoost ? 20 : 45;
|
||||
u16 chanceNotRare = itemHeldBoost ? 80 : 95;
|
||||
if (GetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM) != ITEM_NONE)
|
||||
continue; // prevent overwriting previously set item
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
rnd = Random() % 100;
|
||||
species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES, 0);
|
||||
if (gMapHeader.mapLayoutId == LAYOUT_ALTERING_CAVE)
|
||||
{
|
||||
if (GetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM) != ITEM_NONE)
|
||||
continue; // prevent overwriting previously set item
|
||||
|
||||
rnd = Random() % 100;
|
||||
species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES, 0);
|
||||
if (gMapHeader.mapLayoutId == LAYOUT_ALTERING_CAVE)
|
||||
s32 alteringCaveId = GetWildMonTableIdInAlteringCave(species);
|
||||
if (alteringCaveId != 0)
|
||||
{
|
||||
s32 alteringCaveId = GetWildMonTableIdInAlteringCave(species);
|
||||
if (alteringCaveId != 0)
|
||||
{
|
||||
// In active Altering Cave, use special item list
|
||||
if (rnd < chanceNotRare)
|
||||
continue;
|
||||
SetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, &sAlteringCaveWildMonHeldItems[alteringCaveId].item);
|
||||
}
|
||||
else
|
||||
{
|
||||
// In inactive Altering Cave, use normal items
|
||||
if (rnd < chanceNoItem)
|
||||
continue;
|
||||
if (rnd < chanceNotRare)
|
||||
SetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, &gSpeciesInfo[species].itemCommon);
|
||||
else
|
||||
SetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, &gSpeciesInfo[species].itemRare);
|
||||
}
|
||||
// In active Altering Cave, use special item list
|
||||
if (rnd < chanceNotRare)
|
||||
continue;
|
||||
SetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, &sAlteringCaveWildMonHeldItems[alteringCaveId].item);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gSpeciesInfo[species].itemCommon == gSpeciesInfo[species].itemRare && gSpeciesInfo[species].itemCommon != ITEM_NONE)
|
||||
{
|
||||
// Both held items are the same, 100% chance to hold item
|
||||
// In inactive Altering Cave, use normal items
|
||||
if (rnd < chanceNoItem)
|
||||
continue;
|
||||
if (rnd < chanceNotRare)
|
||||
SetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, &gSpeciesInfo[species].itemCommon);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rnd < chanceNoItem)
|
||||
continue;
|
||||
if (rnd < chanceNotRare)
|
||||
SetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, &gSpeciesInfo[species].itemCommon);
|
||||
else
|
||||
SetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, &gSpeciesInfo[species].itemRare);
|
||||
}
|
||||
SetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, &gSpeciesInfo[species].itemRare);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gSpeciesInfo[species].itemCommon == gSpeciesInfo[species].itemRare && gSpeciesInfo[species].itemCommon != ITEM_NONE)
|
||||
{
|
||||
// Both held items are the same, 100% chance to hold item
|
||||
SetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, &gSpeciesInfo[species].itemCommon);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rnd < chanceNoItem)
|
||||
continue;
|
||||
if (rnd < chanceNotRare)
|
||||
SetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, &gSpeciesInfo[species].itemCommon);
|
||||
else
|
||||
SetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, &gSpeciesInfo[species].itemRare);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
29
src/scrcmd.c
29
src/scrcmd.c
|
|
@ -62,6 +62,7 @@
|
|||
#include "list_menu.h"
|
||||
#include "malloc.h"
|
||||
#include "battle.h"
|
||||
#include "constants/battle_setup.h"
|
||||
#include "constants/event_objects.h"
|
||||
#include "constants/map_types.h"
|
||||
|
||||
|
|
@ -2524,14 +2525,10 @@ bool8 ScrCmd_setwildbattle(struct ScriptContext *ctx)
|
|||
|
||||
Script_RequestEffects(SCREFF_V1);
|
||||
|
||||
if (species2 == SPECIES_NONE)
|
||||
CreateScriptedWildMon(species, level, item);
|
||||
if (species2 != SPECIES_NONE)
|
||||
{
|
||||
CreateScriptedWildMon(species, level, item);
|
||||
sIsScriptedWildDouble = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateScriptedDoubleWildMon(species, level, item, species2, level2, item2);
|
||||
CreateStaticWildMon(&gEnemyParty[1], species2, level2, item2);
|
||||
sIsScriptedWildDouble = TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -2542,10 +2539,22 @@ bool8 ScrCmd_dowildbattle(struct ScriptContext *ctx)
|
|||
{
|
||||
Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE);
|
||||
|
||||
if (sIsScriptedWildDouble == FALSE)
|
||||
BattleSetup_StartScriptedWildBattle();
|
||||
u8 special = ScriptReadByte(ctx);
|
||||
|
||||
gBattleTypeFlags = BATTLE_TYPE_BASIC_WILD;
|
||||
if (special == SPECIAL_WILD_LEGENDARY)
|
||||
gBattleTypeFlags = BATTLE_TYPE_BASIC_WILD;
|
||||
else if (special == SPECIAL_WILD_GHOST)
|
||||
gBattleTypeFlags = BATTLE_TYPE_GHOST;
|
||||
else if (special == SPECIAL_WILD_CATCH_TUTORIAL)
|
||||
gBattleTypeFlags = BATTLE_TYPE_CATCH_TUTORIAL;
|
||||
else
|
||||
BattleSetup_StartScriptedDoubleWildBattle();
|
||||
assertf(special != SPECIAL_WILD_NONE, "Unkwown value for special wild battle %d", special);
|
||||
|
||||
if (sIsScriptedWildDouble == TRUE)
|
||||
gBattleTypeFlags |= BATTLE_TYPE_DOUBLE;
|
||||
|
||||
DoBattleSetup(TRUE);
|
||||
|
||||
ScriptContext_Stop();
|
||||
|
||||
|
|
|
|||
|
|
@ -113,55 +113,27 @@ bool8 DoesPartyHaveEnigmaBerry(void)
|
|||
return hasItem;
|
||||
}
|
||||
|
||||
void CreateScriptedWildMon(enum Species species, u8 level, enum Item item)
|
||||
void CreateStaticWildMon(struct Pokemon *mon, enum Species species, u8 level, enum Item item)
|
||||
{
|
||||
u8 heldItem[2];
|
||||
|
||||
ZeroEnemyPartyMons();
|
||||
u32 personality = GetMonPersonality(species,
|
||||
GetSynchronizedGender(STATIC_WILDMON_ORIGIN, species),
|
||||
GetSynchronizedNature(STATIC_WILDMON_ORIGIN, species),
|
||||
RANDOM_UNOWN_LETTER);
|
||||
CreateMonWithIVs(&gEnemyParty[0], species, level, personality, OTID_STRUCT_PLAYER_ID, USE_RANDOM_IVS);
|
||||
GiveMonInitialMoveset(&gEnemyParty[0]);
|
||||
CreateMonWithIVs(mon, species, level, personality, OTID_STRUCT_PLAYER_ID, USE_RANDOM_IVS);
|
||||
GiveMonInitialMoveset(mon);
|
||||
if (item)
|
||||
{
|
||||
heldItem[0] = item;
|
||||
heldItem[1] = item >> 8;
|
||||
SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, heldItem);
|
||||
SetMonData(mon, MON_DATA_HELD_ITEM, heldItem);
|
||||
}
|
||||
}
|
||||
void CreateScriptedDoubleWildMon(enum Species species1, u8 level1, enum Item item1, enum Species species2, u8 level2, enum Item item2)
|
||||
|
||||
void CreateScriptedWildMon(enum Species species, u8 level, enum Item item)
|
||||
{
|
||||
u8 heldItem1[2];
|
||||
u8 heldItem2[2];
|
||||
|
||||
ZeroEnemyPartyMons();
|
||||
u32 personality = GetMonPersonality(species1,
|
||||
GetSynchronizedGender(STATIC_WILDMON_ORIGIN, species1),
|
||||
GetSynchronizedNature(STATIC_WILDMON_ORIGIN, species1),
|
||||
RANDOM_UNOWN_LETTER);
|
||||
CreateMonWithIVs(&gEnemyParty[0], species1, level1, personality, OTID_STRUCT_PLAYER_ID, USE_RANDOM_IVS);
|
||||
GiveMonInitialMoveset(&gEnemyParty[0]);
|
||||
if (item1)
|
||||
{
|
||||
heldItem1[0] = item1;
|
||||
heldItem1[1] = item1 >> 8;
|
||||
SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, heldItem1);
|
||||
}
|
||||
|
||||
personality = GetMonPersonality(species2,
|
||||
GetSynchronizedGender(STATIC_WILDMON_ORIGIN, species2),
|
||||
GetSynchronizedNature(STATIC_WILDMON_ORIGIN, species2),
|
||||
RANDOM_UNOWN_LETTER);
|
||||
CreateMonWithIVs(&gEnemyParty[1], species2, level2, personality, OTID_STRUCT_PLAYER_ID, USE_RANDOM_IVS);
|
||||
GiveMonInitialMoveset(&gEnemyParty[1]);
|
||||
if (item2)
|
||||
{
|
||||
heldItem2[0] = item2;
|
||||
heldItem2[1] = item2 >> 8;
|
||||
SetMonData(&gEnemyParty[1], MON_DATA_HELD_ITEM, heldItem2);
|
||||
}
|
||||
CreateStaticWildMon(&gEnemyParty[0], species, level, item);
|
||||
}
|
||||
|
||||
void ScriptSetMonMoveSlot(u8 monIndex, enum Move move, u8 slot)
|
||||
|
|
|
|||
|
|
@ -359,9 +359,8 @@ enum TrainerSlideTargets ShouldDoTrainerSlide(enum BattlerId battler, enum Train
|
|||
return TRAINER_SLIDE_TARGET_NONE;
|
||||
|
||||
// Prevents slides triggering twice in single-trainer doubles (B == A / B == TRAINER_NONE) and 2v1 multibattles (B == 0xFFFF)
|
||||
if (((TRAINER_BATTLE_PARAM.opponentB == TRAINER_BATTLE_PARAM.opponentA)
|
||||
|| (TRAINER_BATTLE_PARAM.opponentB == TRAINER_NONE)
|
||||
|| (TRAINER_BATTLE_PARAM.opponentB == 0xFFFF)))
|
||||
if ((TRAINER_BATTLE_PARAM.opponentB == TRAINER_BATTLE_PARAM.opponentA)
|
||||
|| (TRAINER_BATTLE_PARAM.opponentB == TRAINER_NONE))
|
||||
{
|
||||
MarkTrainerSlideAsPlayed(BATTLE_PARTNER(battler), slideId);
|
||||
}
|
||||
|
|
|
|||
203
src/trainer_util.c
Normal file
203
src/trainer_util.c
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
#include "global.h"
|
||||
#include "main.h"
|
||||
#include "data.h"
|
||||
#include "move.h"
|
||||
#include "random.h"
|
||||
#include "string_util.h"
|
||||
#include "trainer_util.h"
|
||||
#include "text.h"
|
||||
|
||||
#include "constants/pokeball.h"
|
||||
|
||||
u32 Crc32B(const u8 *data, u32 size)
|
||||
{
|
||||
s32 i, j;
|
||||
u32 byte, crc, mask;
|
||||
|
||||
i = 0;
|
||||
crc = 0xFFFFFFFF;
|
||||
for (i = 0; i < size; ++i)
|
||||
{
|
||||
byte = data[i];
|
||||
crc = crc ^ byte;
|
||||
for (j = 7; j >= 0; --j)
|
||||
{
|
||||
mask = -(crc & 1);
|
||||
crc = (crc >> 1) ^ (0xEDB88320 & mask);
|
||||
}
|
||||
}
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
rng_value_t GeneratePartySeed(const struct Trainer *trainer)
|
||||
{
|
||||
u32 seed = Crc32B((const u8 *)trainer, sizeof(struct Trainer)) ^ READ_OTID_FROM_SAVE;
|
||||
return LocalRandomSeed(seed);
|
||||
}
|
||||
|
||||
static void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMon *partyEntry)
|
||||
{
|
||||
bool32 noMoveSet = TRUE;
|
||||
u32 j;
|
||||
|
||||
for (j = 0; j < MAX_MON_MOVES; ++j)
|
||||
{
|
||||
if (partyEntry->moves[j] != MOVE_NONE)
|
||||
noMoveSet = FALSE;
|
||||
}
|
||||
if (noMoveSet)
|
||||
{
|
||||
GiveMonInitialMoveset(mon);
|
||||
// TODO: Figure out a default strategy when moves are not set, to generate a good moveset
|
||||
return;
|
||||
}
|
||||
|
||||
for (j = 0; j < MAX_MON_MOVES; ++j)
|
||||
{
|
||||
u32 pp = GetMovePP(partyEntry->moves[j]);
|
||||
SetMonData(mon, MON_DATA_MOVE1 + j, &partyEntry->moves[j]);
|
||||
SetMonData(mon, MON_DATA_PP1 + j, &pp);
|
||||
}
|
||||
}
|
||||
|
||||
u32 GeneratePersonalityForGender(u32 gender, u32 species)
|
||||
{
|
||||
const struct SpeciesInfo *speciesInfo = &gSpeciesInfo[species];
|
||||
if (gender == MON_MALE)
|
||||
{
|
||||
assertf(speciesInfo->genderRatio < MON_FEMALE, "species %d cannot be male", species);
|
||||
return ((255 - speciesInfo->genderRatio) / 2) + speciesInfo->genderRatio;
|
||||
}
|
||||
if (gender == MON_FEMALE)
|
||||
{
|
||||
assertf(speciesInfo->genderRatio != MON_MALE && speciesInfo->genderRatio != MON_GENDERLESS, "species %d cannot be female", species);
|
||||
return speciesInfo->genderRatio / 2;
|
||||
}
|
||||
if (gender == MON_GENDERLESS)
|
||||
assertf(speciesInfo->genderRatio == MON_GENDERLESS, "species %d cannot be genderless", species);
|
||||
else
|
||||
errorf("GeneratePersonalityForGender called with invalid gender value %d", gender);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const u8 sModuloLUT[25] = {0, 21, 17, 13, 9, 5, 1, 22, 18, 14, 10, 6, 2, 23, 19, 15, 11, 7, 3, 24, 20, 16, 12, 8, 4};
|
||||
|
||||
static void ModifyPersonalityForNature(u32 *personality, s32 newNature)
|
||||
{
|
||||
s32 nature = GetNatureFromPersonality(*personality);
|
||||
s32 diff = abs(newNature - nature);
|
||||
s32 sign = (newNature > nature) ? 1 : -1;
|
||||
if (diff > NUM_NATURES / 2)
|
||||
{
|
||||
diff = NUM_NATURES - diff;
|
||||
sign *= -1;
|
||||
}
|
||||
*personality += (sModuloLUT[diff] * 0x100 * sign);
|
||||
}
|
||||
|
||||
static void SetCorrectAbilityNum(struct Pokemon *mon, u32 species, u32 ability)
|
||||
{
|
||||
const struct SpeciesInfo *speciesInfo = &gSpeciesInfo[species];
|
||||
u32 abilityNum;
|
||||
u32 maxAbilityNum = ARRAY_COUNT(speciesInfo->abilities);
|
||||
for (abilityNum = 0; abilityNum < maxAbilityNum; ++abilityNum)
|
||||
{
|
||||
if (speciesInfo->abilities[abilityNum] == ability)
|
||||
break;
|
||||
}
|
||||
assertf(abilityNum < maxAbilityNum, "illegal ability %S for %S", gAbilitiesInfo[ability].name, speciesInfo->speciesName)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SetMonData(mon, MON_DATA_ABILITY_NUM, &abilityNum);
|
||||
}
|
||||
|
||||
void GenerateMonFromTrainerMon(struct Pokemon *mon, const struct TrainerMon *trainerMon, struct TrainerGenerator *trainer)
|
||||
{
|
||||
u32 data;
|
||||
u32 personality = (LocalRandom32(&trainer->localRngState) & 0xFFFFDF00) + 0x1000;
|
||||
u32 genderValue = 0;
|
||||
if (trainerMon->gender == TRAINER_MON_RANDOM_GENDER)
|
||||
genderValue = LocalRandom32(&trainer->localRngState) & 0x000000FF;
|
||||
else if (trainerMon->gender == TRAINER_MON_MALE)
|
||||
genderValue = GeneratePersonalityForGender(MON_MALE, trainerMon->species);
|
||||
else if (trainerMon->gender == TRAINER_MON_FEMALE)
|
||||
genderValue = GeneratePersonalityForGender(MON_FEMALE, trainerMon->species);
|
||||
else
|
||||
errorf("Unkwown trainer mon gender value %d", trainerMon->gender);
|
||||
personality |= genderValue;
|
||||
ModifyPersonalityForNature(&personality, trainerMon->nature);
|
||||
CreateMon(mon, trainerMon->species, trainerMon->lvl, personality, trainer->otID);
|
||||
if (trainerMon->nickname != NULL)
|
||||
SetMonData(mon, MON_DATA_NICKNAME, trainerMon->nickname);
|
||||
if (trainerMon->ev) //ev in struct TrainerMon are stored in Showdown order not GF order
|
||||
{
|
||||
SetMonData(mon, MON_DATA_HP_EV, &trainerMon->ev[0]);
|
||||
SetMonData(mon, MON_DATA_ATK_EV, &trainerMon->ev[1]);
|
||||
SetMonData(mon, MON_DATA_DEF_EV, &trainerMon->ev[2]);
|
||||
SetMonData(mon, MON_DATA_SPATK_EV, &trainerMon->ev[3]);
|
||||
SetMonData(mon, MON_DATA_SPDEF_EV, &trainerMon->ev[4]);
|
||||
SetMonData(mon, MON_DATA_SPEED_EV, &trainerMon->ev[5]);
|
||||
|
||||
/*
|
||||
for (u32 i = 0; i < NUM_STATS; i++)
|
||||
SetMonData(mon, MON_DATA_HP_EV + i, &trainerMon->ev[i]);
|
||||
*/
|
||||
}
|
||||
|
||||
SetMonData(mon, MON_DATA_IVS, &trainerMon->iv);
|
||||
CustomTrainerPartyAssignMoves(mon, trainerMon);
|
||||
SetMonData(mon, MON_DATA_HELD_ITEM, &trainerMon->heldItem);
|
||||
|
||||
if (trainerMon->ability)
|
||||
{
|
||||
SetCorrectAbilityNum(mon, trainerMon->species, trainerMon->ability);
|
||||
}
|
||||
else if (B_TRAINER_MON_HIDDEN_ABILITY)
|
||||
{
|
||||
do {
|
||||
data = Random() % NUM_ABILITY_SLOTS; // includes hidden abilities
|
||||
} while (GetAbilityBySpecies(trainerMon->species, data) == ABILITY_NONE);
|
||||
SetMonData(mon, MON_DATA_ABILITY_NUM, &data);
|
||||
}
|
||||
|
||||
if (trainerMon->ball < POKEBALL_COUNT)
|
||||
{
|
||||
data = trainerMon->ball;
|
||||
SetMonData(mon, MON_DATA_POKEBALL, &data);
|
||||
}
|
||||
else if (B_TRAINER_CLASS_POKE_BALLS >= GEN_7 && trainer->trainerClass && trainerMon->ball == POKEBALL_COUNT)
|
||||
{
|
||||
data = gTrainerClasses[trainer->trainerClass].ball ?: BALL_POKE;
|
||||
SetMonData(mon, MON_DATA_POKEBALL, &data);
|
||||
}
|
||||
else if (trainerMon->ball > POKEBALL_COUNT)
|
||||
{
|
||||
errorf("Invalid ball for %S in %S's party", GetMonData(mon, MON_DATA_NICKNAME), trainer->name);
|
||||
}
|
||||
|
||||
SetMonData(mon, MON_DATA_FRIENDSHIP, &trainerMon->friendship);
|
||||
|
||||
data = trainerMon->isShiny;
|
||||
SetMonData(mon, MON_DATA_IS_SHINY, &data);
|
||||
if (trainerMon->dynamaxLevel > 0)
|
||||
{
|
||||
data = trainerMon->dynamaxLevel;
|
||||
SetMonData(mon, MON_DATA_DYNAMAX_LEVEL, &data);
|
||||
}
|
||||
if (trainerMon->gigantamaxFactor)
|
||||
{
|
||||
data = trainerMon->gigantamaxFactor;
|
||||
SetMonData(mon, MON_DATA_GIGANTAMAX_FACTOR, &data);
|
||||
}
|
||||
if (trainerMon->teraType)
|
||||
{
|
||||
data = trainerMon->teraType;
|
||||
SetMonData(mon, MON_DATA_TERA_TYPE, &data);
|
||||
}
|
||||
|
||||
CalculateMonStats(mon);
|
||||
SetMonData(mon, MON_DATA_OT_NAME, trainer->name);
|
||||
data = trainer->gender;
|
||||
SetMonData(mon, MON_DATA_OT_GENDER, &data);
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#include "global.h"
|
||||
#include "battle.h"
|
||||
#include "battle_setup.h"
|
||||
#include "battle_pike.h"
|
||||
#include "battle_pyramid.h"
|
||||
|
|
@ -673,7 +674,8 @@ bool8 StandardWildEncounter(u16 curMetatileBehavior, u16 prevMetatileBehavior)
|
|||
else if (!TryGenerateBattlePikeWildMon(TRUE))
|
||||
return FALSE;
|
||||
|
||||
BattleSetup_StartBattlePikeWildBattle();
|
||||
gBattleTypeFlags = BATTLE_TYPE_PIKE;
|
||||
DoBattleSetup(FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
if (gMapHeader.mapLayoutId == LAYOUT_BATTLE_FRONTIER_BATTLE_PYRAMID_FLOOR)
|
||||
|
|
@ -689,7 +691,7 @@ bool8 StandardWildEncounter(u16 curMetatileBehavior, u16 prevMetatileBehavior)
|
|||
return FALSE;
|
||||
|
||||
GenerateBattlePyramidWildMon();
|
||||
BattleSetup_StartWildBattle();
|
||||
BattleSetup_StartWildBattle(FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -712,14 +714,15 @@ bool8 StandardWildEncounter(u16 curMetatileBehavior, u16 prevMetatileBehavior)
|
|||
if (!IsWildLevelAllowedByRepel(roamer->level))
|
||||
return FALSE;
|
||||
|
||||
BattleSetup_StartRoamerBattle();
|
||||
gBattleTypeFlags = BATTLE_TYPE_ROAMER;
|
||||
DoBattleSetup(FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DoMassOutbreakEncounterTest() == TRUE && SetUpMassOutbreakEncounter(WILD_CHECK_REPEL | WILD_CHECK_KEEN_EYE) == TRUE)
|
||||
{
|
||||
BattleSetup_StartWildBattle();
|
||||
BattleSetup_StartWildBattle(FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -731,11 +734,11 @@ bool8 StandardWildEncounter(u16 curMetatileBehavior, u16 prevMetatileBehavior)
|
|||
struct Pokemon mon1 = gEnemyParty[0];
|
||||
TryGenerateWildMon(gWildMonHeaders[headerId].encounterTypes[timeOfDay].landMonsInfo, WILD_AREA_LAND, WILD_CHECK_KEEN_EYE);
|
||||
gEnemyParty[1] = mon1;
|
||||
BattleSetup_StartDoubleWildBattle();
|
||||
BattleSetup_StartWildBattle(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
BattleSetup_StartWildBattle();
|
||||
BattleSetup_StartWildBattle(FALSE);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -763,7 +766,8 @@ bool8 StandardWildEncounter(u16 curMetatileBehavior, u16 prevMetatileBehavior)
|
|||
if (!IsWildLevelAllowedByRepel(roamer->level))
|
||||
return FALSE;
|
||||
|
||||
BattleSetup_StartRoamerBattle();
|
||||
gBattleTypeFlags = BATTLE_TYPE_ROAMER;
|
||||
DoBattleSetup(FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
else // try a regular surfing encounter
|
||||
|
|
@ -776,11 +780,11 @@ bool8 StandardWildEncounter(u16 curMetatileBehavior, u16 prevMetatileBehavior)
|
|||
struct Pokemon mon1 = gEnemyParty[0];
|
||||
TryGenerateWildMon(gWildMonHeaders[headerId].encounterTypes[timeOfDay].waterMonsInfo, WILD_AREA_WATER, WILD_CHECK_KEEN_EYE);
|
||||
gEnemyParty[1] = mon1;
|
||||
BattleSetup_StartDoubleWildBattle();
|
||||
BattleSetup_StartWildBattle(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
BattleSetup_StartWildBattle();
|
||||
BattleSetup_StartWildBattle(FALSE);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -816,11 +820,11 @@ void RockSmashWildEncounter(void)
|
|||
struct Pokemon mon1 = gEnemyParty[0];
|
||||
TryGenerateWildMon(wildPokemonInfo, WILD_AREA_ROCKS, WILD_CHECK_REPEL | WILD_CHECK_KEEN_EYE);
|
||||
gEnemyParty[1] = mon1;
|
||||
BattleSetup_StartDoubleWildBattle();
|
||||
BattleSetup_StartWildBattle(TRUE);
|
||||
gSpecialVar_Result = TRUE;
|
||||
}
|
||||
else {
|
||||
BattleSetup_StartWildBattle();
|
||||
BattleSetup_StartWildBattle(FALSE);
|
||||
gSpecialVar_Result = TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -853,8 +857,8 @@ bool8 SweetScentWildEncounter(void)
|
|||
if (TryGenerateWildMon(gBattlePikeWildMonHeaders[headerId].encounterTypes[timeOfDay].landMonsInfo, WILD_AREA_LAND, 0) != TRUE)
|
||||
return FALSE;
|
||||
|
||||
TryGenerateBattlePikeWildMon(FALSE);
|
||||
BattleSetup_StartBattlePikeWildBattle();
|
||||
gBattleTypeFlags = BATTLE_TYPE_PIKE;
|
||||
DoBattleSetup(FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
if (gMapHeader.mapLayoutId == LAYOUT_BATTLE_FRONTIER_BATTLE_PYRAMID_FLOOR)
|
||||
|
|
@ -866,7 +870,7 @@ bool8 SweetScentWildEncounter(void)
|
|||
return FALSE;
|
||||
|
||||
GenerateBattlePyramidWildMon();
|
||||
BattleSetup_StartWildBattle();
|
||||
BattleSetup_StartWildBattle(FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -881,7 +885,8 @@ bool8 SweetScentWildEncounter(void)
|
|||
|
||||
if (TryStartRoamerEncounter())
|
||||
{
|
||||
BattleSetup_StartRoamerBattle();
|
||||
gBattleTypeFlags = BATTLE_TYPE_ROAMER;
|
||||
DoBattleSetup(FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -890,7 +895,7 @@ bool8 SweetScentWildEncounter(void)
|
|||
else
|
||||
TryGenerateWildMon(gWildMonHeaders[headerId].encounterTypes[timeOfDay].landMonsInfo, WILD_AREA_LAND, 0);
|
||||
|
||||
BattleSetup_StartWildBattle();
|
||||
BattleSetup_StartWildBattle(FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
else if (MetatileBehavior_IsWaterWildEncounter(MapGridGetMetatileBehaviorAt(x, y)) == TRUE)
|
||||
|
|
@ -904,12 +909,13 @@ bool8 SweetScentWildEncounter(void)
|
|||
|
||||
if (TryStartRoamerEncounter())
|
||||
{
|
||||
BattleSetup_StartRoamerBattle();
|
||||
gBattleTypeFlags = BATTLE_TYPE_ROAMER;
|
||||
DoBattleSetup(FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
TryGenerateWildMon(gWildMonHeaders[headerId].encounterTypes[timeOfDay].waterMonsInfo, WILD_AREA_WATER, 0);
|
||||
BattleSetup_StartWildBattle();
|
||||
BattleSetup_StartWildBattle(FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -951,7 +957,7 @@ void FishingWildEncounter(u8 rod)
|
|||
|
||||
IncrementGameStat(GAME_STAT_FISHING_ENCOUNTERS);
|
||||
SetPokemonAnglerSpecies(species);
|
||||
BattleSetup_StartWildBattle();
|
||||
BattleSetup_StartWildBattle(FALSE);
|
||||
}
|
||||
|
||||
u16 GetLocalWildMon(bool8 *isWaterMon)
|
||||
|
|
@ -1189,18 +1195,6 @@ bool8 TryDoDoubleWildBattle(void)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
bool8 StandardWildEncounter_Debug(void)
|
||||
{
|
||||
u32 headerId = GetCurrentMapWildMonHeaderId();
|
||||
enum TimeOfDay timeOfDay = GetTimeOfDayForEncounters(headerId, WILD_AREA_LAND);
|
||||
|
||||
if (TryGenerateWildMon(gWildMonHeaders[headerId].encounterTypes[timeOfDay].landMonsInfo, WILD_AREA_LAND, 0) != TRUE)
|
||||
return FALSE;
|
||||
|
||||
DoStandardWildBattle_Debug();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
u32 ChooseHiddenMonIndex(void)
|
||||
{
|
||||
#ifdef ENCOUNTER_CHANCE_HIDDEN_MONS_TOTAL
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "global.h"
|
||||
#include "test/test.h"
|
||||
#include "battle.h"
|
||||
#include "battle_main.h"
|
||||
#include "battle_setup.h"
|
||||
#include "data.h"
|
||||
#include "malloc.h"
|
||||
#include "random.h"
|
||||
|
|
@ -18,7 +18,7 @@ TEST("CreateNPCTrainerPartyForTrainer generates customized Pokémon")
|
|||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
u32 currTrainer = 3;
|
||||
u8 nickBuffer[20];
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE);
|
||||
EXPECT(IsMonShiny(&testParty[0]));
|
||||
EXPECT(!IsMonShiny(&testParty[1]));
|
||||
|
||||
|
|
@ -94,7 +94,7 @@ TEST("CreateNPCTrainerPartyForTrainer generates different personalities for diff
|
|||
{
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
u32 currTrainer = 3;
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE);
|
||||
EXPECT(testParty[0].box.personality != testParty[1].box.personality);
|
||||
Free(testParty);
|
||||
}
|
||||
|
|
@ -120,7 +120,7 @@ TEST("Trainer Class Balls apply to the entire party")
|
|||
u32 j;
|
||||
u32 currTrainer = 14;
|
||||
const struct Trainer *trainer = GetTrainerStructFromId(currTrainer);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, trainer, TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, trainer, TRUE);
|
||||
for(j = 0; j < 6; j++)
|
||||
{
|
||||
EXPECT(GetMonData(&testParty[j], MON_DATA_POKEBALL, 0) == gTrainerClasses[trainer->trainerClass].ball);
|
||||
|
|
@ -133,7 +133,7 @@ TEST("Difficulty default to Normal if the trainer doesn't have a member for the
|
|||
SetCurrentDifficultyLevel(DIFFICULTY_EASY);
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
u32 currTrainer = 4;
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_MEWTWO);
|
||||
Free(testParty);
|
||||
SetCurrentDifficultyLevel(DIFFICULTY_NORMAL);
|
||||
|
|
@ -144,7 +144,7 @@ TEST("Difficulty changes which party is used for enemy trainer if defined for th
|
|||
SetCurrentDifficultyLevel(DIFFICULTY_EASY);
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
u32 currTrainer = 5;
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_METAPOD);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_LEVEL) == 1);
|
||||
Free(testParty);
|
||||
|
|
@ -156,7 +156,7 @@ TEST("Difficulty changes which party is used for enemy trainer if defined for th
|
|||
SetCurrentDifficultyLevel(DIFFICULTY_HARD);
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
u32 currTrainer = 5;
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_ARCEUS);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_LEVEL) == 99);
|
||||
Free(testParty);
|
||||
|
|
@ -168,7 +168,7 @@ TEST("Difficulty changes which party is used for enemy trainer if defined for th
|
|||
SetCurrentDifficultyLevel(DIFFICULTY_NORMAL);
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
u32 currTrainer = 5;
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_MEWTWO);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_LEVEL) == 50);
|
||||
Free(testParty);
|
||||
|
|
@ -179,7 +179,7 @@ TEST("Difficulty default to Normal if the partner doesn't have a member for the
|
|||
SetCurrentDifficultyLevel(DIFFICULTY_TEST);
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
u32 currTrainer = TRAINER_PARTNER(1);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_METANG);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_LEVEL) == 42);
|
||||
Free(testParty);
|
||||
|
|
@ -191,7 +191,7 @@ TEST("Difficulty changes which party is used for partner if defined for the diff
|
|||
SetCurrentDifficultyLevel(DIFFICULTY_EASY);
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
u32 currTrainer = TRAINER_PARTNER(1);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_METAPOD);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_LEVEL) == 1);
|
||||
Free(testParty);
|
||||
|
|
@ -203,7 +203,7 @@ TEST("Difficulty changes which party is used for partner if defined for the diff
|
|||
SetCurrentDifficultyLevel(DIFFICULTY_HARD);
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
u32 currTrainer = TRAINER_PARTNER(1);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_ARCEUS);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_LEVEL) == 99);
|
||||
Free(testParty);
|
||||
|
|
@ -215,7 +215,7 @@ TEST("Difficulty changes which party is used for partner if defined for the diff
|
|||
SetCurrentDifficultyLevel(DIFFICULTY_NORMAL);
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
u32 currTrainer = TRAINER_PARTNER(1);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_METANG);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_LEVEL) == 42);
|
||||
Free(testParty);
|
||||
|
|
@ -225,7 +225,7 @@ TEST("Trainer Party Pool generates a party from the trainer pool")
|
|||
{
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
u32 currTrainer = 6;
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_EEVEE);
|
||||
Free(testParty);
|
||||
}
|
||||
|
|
@ -234,7 +234,7 @@ TEST("Trainer Party Pool picks a random lead and a random ace if tags exist in t
|
|||
{
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
u32 currTrainer = 7;
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_ARON); // Lead
|
||||
EXPECT(GetMonData(&testParty[1], MON_DATA_SPECIES) == SPECIES_WYNAUT); // Not Lead or Ace
|
||||
EXPECT(GetMonData(&testParty[2], MON_DATA_SPECIES) == SPECIES_EEVEE); // Ace
|
||||
|
|
@ -245,10 +245,12 @@ TEST("Trainer Party Pool picks according to custom rules")
|
|||
{
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
u32 currTrainer = 8;
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE, BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE);
|
||||
gBattleTypeFlags = BATTLE_TYPE_DOUBLE;
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_TORKOAL); // Lead + Weather Setter
|
||||
EXPECT(GetMonData(&testParty[1], MON_DATA_SPECIES) == SPECIES_BULBASAUR); // Lead + Weather Abuser
|
||||
EXPECT(GetMonData(&testParty[2], MON_DATA_SPECIES) == SPECIES_EEVEE); // Anything else
|
||||
gBattleTypeFlags = 0;
|
||||
Free(testParty);
|
||||
}
|
||||
|
||||
|
|
@ -256,7 +258,7 @@ TEST("Trainer Party Pool uses standard party creation if pool is illegal")
|
|||
{
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
u32 currTrainer = 9;
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_WYNAUT);
|
||||
EXPECT(GetMonData(&testParty[1], MON_DATA_SPECIES) == SPECIES_WOBBUFFET);
|
||||
Free(testParty);
|
||||
|
|
@ -266,7 +268,7 @@ TEST("Trainer Party Pool can be pruned before picking")
|
|||
{
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
u32 currTrainer = 10;
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_EEVEE);
|
||||
EXPECT(GetMonData(&testParty[1], MON_DATA_SPECIES) == SPECIES_WYNAUT);
|
||||
Free(testParty);
|
||||
|
|
@ -276,7 +278,7 @@ TEST("Trainer Party Pool can choose which functions to use for picking mons")
|
|||
{
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
u32 currTrainer = 11;
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, GetTrainerStructFromId(currTrainer), TRUE);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_WYNAUT);
|
||||
EXPECT(GetMonData(&testParty[1], MON_DATA_SPECIES) == SPECIES_WOBBUFFET);
|
||||
Free(testParty);
|
||||
|
|
@ -297,7 +299,7 @@ TEST("CreateNPCTrainerPartyForTrainer generates default moves if no moves are sp
|
|||
const struct Trainer *trainer = GetTrainerStructFromId(currTrainer);
|
||||
ASSUME(trainer->party[0].moves[0] == MOVE_NONE);
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, trainer, TRUE, BATTLE_TYPE_TRAINER);
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, trainer, TRUE);
|
||||
EXPECT(GetMonData(&testParty[0], MON_DATA_MOVE1) != MOVE_NONE);
|
||||
Free(testParty);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user