mirror of
https://github.com/rh-hideout/pokeemerald-expansion.git
synced 2026-03-21 18:04:50 -05:00
Trainerbattle Type Differentiation (#6424)
Co-authored-by: CallmeEchoo <callmeechoo@github.com> Co-authored-by: Your Name <you@example.com>
This commit is contained in:
parent
25623fbade
commit
29f83ea5e0
|
|
@ -98,14 +98,13 @@
|
||||||
waitstate
|
waitstate
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro multi_do type:req, partnerId:req
|
.macro multi_do type:req
|
||||||
special ReducePlayerPartyToSelectedMons
|
special ReducePlayerPartyToSelectedMons
|
||||||
setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SET_DATA
|
setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SET_DATA
|
||||||
setvar VAR_0x8005, FRONTIER_DATA_SELECTED_MON_ORDER
|
setvar VAR_0x8005, FRONTIER_DATA_SELECTED_MON_ORDER
|
||||||
special CallFrontierUtilFunc @ saves the mon order, so the non-selected mons get restored afterwards
|
special CallFrontierUtilFunc @ saves the mon order, so the non-selected mons get restored afterwards
|
||||||
setvar VAR_0x8004, SPECIAL_BATTLE_MULTI
|
setvar VAR_0x8004, SPECIAL_BATTLE_MULTI
|
||||||
setvar VAR_0x8005, \type | MULTI_BATTLE_CHOOSE_MONS
|
setvar VAR_0x8005, \type | MULTI_BATTLE_CHOOSE_MONS
|
||||||
setvar VAR_0x8006, \partnerId
|
|
||||||
special DoSpecialTrainerBattle
|
special DoSpecialTrainerBattle
|
||||||
waitstate
|
waitstate
|
||||||
setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SAVE_PARTY
|
setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SAVE_PARTY
|
||||||
|
|
@ -115,26 +114,26 @@
|
||||||
|
|
||||||
.macro multi_2_vs_2 trainer1Id:req, trainer1LoseText:req, trainer2Id:req, trainer2LoseText:req, partnerId:req
|
.macro multi_2_vs_2 trainer1Id:req, trainer1LoseText:req, trainer2Id:req, trainer2LoseText:req, partnerId:req
|
||||||
special SavePlayerParty
|
special SavePlayerParty
|
||||||
trainerbattle TRAINER_BATTLE_SET_TRAINERS_FOR_MULTI_BATTLE, OBJ_ID_NONE, \trainer1Id, NULL, \trainer1LoseText, NULL, OBJ_ID_NONE, \trainer2Id, NULL, \trainer2LoseText, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE
|
setmultitrainerbattle \trainer1Id, \trainer1LoseText, \trainer2Id, \trainer2LoseText, \partnerId
|
||||||
multi_do MULTI_BATTLE_2_VS_2, \partnerId
|
multi_do MULTI_BATTLE_2_VS_2
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro multi_2_vs_1 trainer1Id:req, trainer1LoseText:req, partnerId:req
|
.macro multi_2_vs_1 trainer1Id:req, trainer1LoseText:req, partnerId:req
|
||||||
special SavePlayerParty
|
special SavePlayerParty
|
||||||
trainerbattle TRAINER_BATTLE_SET_TRAINERS_FOR_MULTI_BATTLE, OBJ_ID_NONE, \trainer1Id, NULL, \trainer1LoseText, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE
|
setmultitrainerbattle \trainer1Id, \trainer1LoseText, TRAINER_NONE, NULL, \partnerId
|
||||||
multi_do MULTI_BATTLE_2_VS_1, \partnerId
|
multi_do MULTI_BATTLE_2_VS_1
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
@ Wild mons need to be assigned to gEnemyParty 0 and 3 slots, other slots need to be cleared out.
|
@ Wild mons need to be assigned to gEnemyParty 0 and 3 slots, other slots need to be cleared out.
|
||||||
.macro multi_wild partnerId:req
|
.macro multi_wild partnerId:req
|
||||||
special SavePlayerParty
|
special SavePlayerParty
|
||||||
multi_do MULTI_BATTLE_2_VS_WILD, \partnerId
|
setmultitrainerbattle TRAINER_NONE, NULL, TRAINER_NONE, NULL, \partnerId
|
||||||
|
multi_do MULTI_BATTLE_2_VS_WILD
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro multi_do_fixed type:req, partnerId:req
|
.macro multi_do_fixed type:req
|
||||||
setvar VAR_0x8004, SPECIAL_BATTLE_MULTI
|
setvar VAR_0x8004, SPECIAL_BATTLE_MULTI
|
||||||
setvar VAR_0x8005, \type
|
setvar VAR_0x8005, \type
|
||||||
setvar VAR_0x8006, \partnerId
|
|
||||||
special DoSpecialTrainerBattle
|
special DoSpecialTrainerBattle
|
||||||
waitstate
|
waitstate
|
||||||
setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SAVE_PARTY
|
setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SAVE_PARTY
|
||||||
|
|
@ -144,18 +143,19 @@
|
||||||
|
|
||||||
.macro multi_fixed_2_vs_2 trainer1Id:req, trainer1LoseText:req, trainer2Id:req, trainer2LoseText:req, partnerId:req
|
.macro multi_fixed_2_vs_2 trainer1Id:req, trainer1LoseText:req, trainer2Id:req, trainer2LoseText:req, partnerId:req
|
||||||
special SavePlayerParty
|
special SavePlayerParty
|
||||||
trainerbattle TRAINER_BATTLE_SET_TRAINERS_FOR_MULTI_BATTLE, OBJ_ID_NONE, \trainer1Id, NULL, \trainer1LoseText, NULL, OBJ_ID_NONE, \trainer2Id, NULL, \trainer2LoseText, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE
|
setmultitrainerbattle \trainer1Id, \trainer1LoseText, \trainer2Id, \trainer2LoseText, \partnerId
|
||||||
multi_do_fixed MULTI_BATTLE_2_VS_2, \partnerId
|
multi_do_fixed MULTI_BATTLE_2_VS_2
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro multi_fixed_2_vs_1 trainer1Id:req, trainer1LoseText:req, partnerId:req
|
.macro multi_fixed_2_vs_1 trainer1Id:req, trainer1LoseText:req, partnerId:req
|
||||||
special SavePlayerParty
|
special SavePlayerParty
|
||||||
trainerbattle TRAINER_BATTLE_SET_TRAINERS_FOR_MULTI_BATTLE, OBJ_ID_NONE, \trainer1Id, NULL, \trainer1LoseText, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE
|
setmultitrainerbattle \trainer1Id, \trainer1LoseText, TRAINER_NONE, NULL, \partnerId
|
||||||
multi_do_fixed MULTI_BATTLE_2_VS_1, \partnerId
|
multi_do_fixed MULTI_BATTLE_2_VS_1
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
@ Wild mons need to be assigned to gEnemyParty 0 and 3 slots, other slots need to be cleared out.
|
@ Wild mons need to be assigned to gEnemyParty 0 and 3 slots, other slots need to be cleared out.
|
||||||
.macro multi_fixed_wild partnerId:req
|
.macro multi_fixed_wild partnerId:req
|
||||||
special SavePlayerParty
|
special SavePlayerParty
|
||||||
multi_do_fixed MULTI_BATTLE_2_VS_WILD, \partnerId
|
setmultitrainerbattle TRAINER_NONE, NULL, TRAINER_NONE, NULL, \partnerId
|
||||||
|
multi_do_fixed MULTI_BATTLE_2_VS_WILD
|
||||||
.endm
|
.endm
|
||||||
|
|
|
||||||
|
|
@ -2599,6 +2599,27 @@
|
||||||
cant_see_if 5
|
cant_see_if 5
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
.macro setmultitrainerbattle trainer_a:req, lose_text_a:req, trainer_b:req, lose_text_b:req, partnerId:req
|
||||||
|
callnative SetMultiTrainerBattle
|
||||||
|
.2byte \trainer_a
|
||||||
|
.4byte \lose_text_a
|
||||||
|
.2byte \trainer_b
|
||||||
|
.4byte \lose_text_b
|
||||||
|
.2byte \partnerId
|
||||||
|
.endm
|
||||||
|
|
||||||
|
@ facility version of `trainerbattle` macro. Used in Battle Pyramid and Trainer Hill
|
||||||
|
.macro facilitytrainerbattle facility:req
|
||||||
|
callnative FacilityTrainerBattle
|
||||||
|
.byte \facility
|
||||||
|
.endm
|
||||||
|
|
||||||
|
@ immediately starts a battle of the given facility
|
||||||
|
.macro dofacilitytrainerbattle facility:req
|
||||||
|
callnative DoFacilityTrainerBattle
|
||||||
|
.byte \facility
|
||||||
|
.endm
|
||||||
|
|
||||||
@ Follower NPCs
|
@ Follower NPCs
|
||||||
|
|
||||||
@ Sets an existing NPC up to follow the player.
|
@ Sets an existing NPC up to follow the player.
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include "constants/battle_pike.h"
|
#include "constants/battle_pike.h"
|
||||||
#include "constants/battle_pyramid.h"
|
#include "constants/battle_pyramid.h"
|
||||||
#include "constants/battle_setup.h"
|
#include "constants/battle_setup.h"
|
||||||
|
#include "constants/battle_special.h"
|
||||||
#include "constants/battle_tent.h"
|
#include "constants/battle_tent.h"
|
||||||
#include "constants/battle_tower.h"
|
#include "constants/battle_tower.h"
|
||||||
#include "constants/berry.h"
|
#include "constants/berry.h"
|
||||||
|
|
|
||||||
|
|
@ -364,9 +364,7 @@ BattleFrontier_BattleArenaBattleRoom_EventScript_DoArenaBattle::
|
||||||
setvar VAR_TEMP_2, 0
|
setvar VAR_TEMP_2, 0
|
||||||
frontier_set FRONTIER_DATA_RECORD_DISABLED, FALSE
|
frontier_set FRONTIER_DATA_RECORD_DISABLED, FALSE
|
||||||
special HealPlayerParty
|
special HealPlayerParty
|
||||||
setvar VAR_0x8004, SPECIAL_BATTLE_ARENA
|
dofacilitytrainerbattle FACILITY_BATTLE_ARENA
|
||||||
setvar VAR_0x8005, 0
|
|
||||||
special DoSpecialTrainerBattle
|
|
||||||
waitstate
|
waitstate
|
||||||
frontier_restorehelditems
|
frontier_restorehelditems
|
||||||
special HealPlayerParty
|
special HealPlayerParty
|
||||||
|
|
|
||||||
|
|
@ -445,10 +445,8 @@ BattleFrontier_BattleDomeBattleRoom_EventScript_TuckerDraw::
|
||||||
BattleFrontier_BattleDomeBattleRoom_EventScript_DoDomeBattle::
|
BattleFrontier_BattleDomeBattleRoom_EventScript_DoDomeBattle::
|
||||||
frontier_set FRONTIER_DATA_RECORD_DISABLED, FALSE
|
frontier_set FRONTIER_DATA_RECORD_DISABLED, FALSE
|
||||||
special HealPlayerParty
|
special HealPlayerParty
|
||||||
setvar VAR_0x8004, SPECIAL_BATTLE_DOME
|
|
||||||
setvar VAR_0x8005, 0
|
|
||||||
setvar VAR_TEMP_9, 1
|
setvar VAR_TEMP_9, 1
|
||||||
special DoSpecialTrainerBattle
|
dofacilitytrainerbattle FACILITY_BATTLE_DOME
|
||||||
waitstate
|
waitstate
|
||||||
setvar VAR_TEMP_9, 0
|
setvar VAR_TEMP_9, 0
|
||||||
dome_restorehelditems
|
dome_restorehelditems
|
||||||
|
|
|
||||||
|
|
@ -80,9 +80,7 @@ BattleFrontier_BattleFactoryBattleRoom_EventScript_BattleOpponent::
|
||||||
closemessage
|
closemessage
|
||||||
frontier_set FRONTIER_DATA_RECORD_DISABLED, FALSE
|
frontier_set FRONTIER_DATA_RECORD_DISABLED, FALSE
|
||||||
special HealPlayerParty
|
special HealPlayerParty
|
||||||
setvar VAR_0x8004, SPECIAL_BATTLE_FACTORY
|
dofacilitytrainerbattle FRONTIER_FACILITY_FACTORY
|
||||||
setvar VAR_0x8005, 0
|
|
||||||
special DoSpecialTrainerBattle
|
|
||||||
waitstate
|
waitstate
|
||||||
switch VAR_RESULT
|
switch VAR_RESULT
|
||||||
case 1, BattleFrontier_BattleFactoryBattleRoom_EventScript_DefeatedOpponent
|
case 1, BattleFrontier_BattleFactoryBattleRoom_EventScript_DefeatedOpponent
|
||||||
|
|
@ -171,9 +169,7 @@ BattleFrontier_BattleFactoryBattleRoom_EventScript_DoNolandBattle::
|
||||||
closemessage
|
closemessage
|
||||||
frontier_set FRONTIER_DATA_RECORD_DISABLED, FALSE
|
frontier_set FRONTIER_DATA_RECORD_DISABLED, FALSE
|
||||||
special HealPlayerParty
|
special HealPlayerParty
|
||||||
setvar VAR_0x8004, SPECIAL_BATTLE_FACTORY
|
dofacilitytrainerbattle FACILITY_BATTLE_FACTORY
|
||||||
setvar VAR_0x8005, 0
|
|
||||||
special DoSpecialTrainerBattle
|
|
||||||
waitstate
|
waitstate
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -274,9 +274,7 @@ BattleFrontier_BattlePalaceBattleRoom_EventScript_DoPalaceBattle::
|
||||||
setvar VAR_TEMP_2, 0
|
setvar VAR_TEMP_2, 0
|
||||||
frontier_set FRONTIER_DATA_RECORD_DISABLED, FALSE
|
frontier_set FRONTIER_DATA_RECORD_DISABLED, FALSE
|
||||||
special HealPlayerParty
|
special HealPlayerParty
|
||||||
setvar VAR_0x8004, SPECIAL_BATTLE_PALACE
|
dofacilitytrainerbattle FACILITY_BATTLE_PALACE
|
||||||
setvar VAR_0x8005, 0
|
|
||||||
special DoSpecialTrainerBattle
|
|
||||||
waitstate
|
waitstate
|
||||||
frontier_restorehelditems
|
frontier_restorehelditems
|
||||||
special HealPlayerParty
|
special HealPlayerParty
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,7 @@ BattleFrontier_BattlePikeRoomNormal_EventScript_EnterSingleBattleRoom::
|
||||||
waitmessage
|
waitmessage
|
||||||
closemessage
|
closemessage
|
||||||
releaseall
|
releaseall
|
||||||
setvar VAR_0x8004, SPECIAL_BATTLE_PIKE_SINGLE
|
dofacilitytrainerbattle FACILITY_BATTLE_PIKE_SINGLE
|
||||||
setvar VAR_0x8005, 0
|
|
||||||
special DoSpecialTrainerBattle
|
|
||||||
waitstate
|
waitstate
|
||||||
switch VAR_RESULT
|
switch VAR_RESULT
|
||||||
case 1, BattleFrontier_BattlePikeRoomNormal_EventScript_WonSingleBattle
|
case 1, BattleFrontier_BattlePikeRoomNormal_EventScript_WonSingleBattle
|
||||||
|
|
@ -61,9 +59,7 @@ BattleFrontier_BattlePikeRoomNormal_EventScript_EnterHardBattleRoom::
|
||||||
waitmessage
|
waitmessage
|
||||||
closemessage
|
closemessage
|
||||||
releaseall
|
releaseall
|
||||||
setvar VAR_0x8004, SPECIAL_BATTLE_PIKE_SINGLE
|
dofacilitytrainerbattle FACILITY_BATTLE_PIKE_SINGLE
|
||||||
setvar VAR_0x8005, 0
|
|
||||||
special DoSpecialTrainerBattle
|
|
||||||
waitstate
|
waitstate
|
||||||
switch VAR_RESULT
|
switch VAR_RESULT
|
||||||
case 1, BattleFrontier_BattlePikeRoomNormal_EventScript_WonHardBattle
|
case 1, BattleFrontier_BattlePikeRoomNormal_EventScript_WonHardBattle
|
||||||
|
|
@ -252,9 +248,7 @@ BattleFrontier_BattlePikeRoomNormal_EventScript_EnterDoubleBattleRoom::
|
||||||
pike_gettrainerintro 1
|
pike_gettrainerintro 1
|
||||||
msgbox gStringVar4, MSGBOX_DEFAULT
|
msgbox gStringVar4, MSGBOX_DEFAULT
|
||||||
closemessage
|
closemessage
|
||||||
setvar VAR_0x8004, SPECIAL_BATTLE_PIKE_DOUBLE
|
dofacilitytrainerbattle FACILITY_BATTLE_PIKE_DOUBLE
|
||||||
setvar VAR_0x8005, 0
|
|
||||||
special DoSpecialTrainerBattle
|
|
||||||
waitstate
|
waitstate
|
||||||
switch VAR_RESULT
|
switch VAR_RESULT
|
||||||
case 1, BattleFrontier_BattlePikeRoomNormal_EventScript_WonDoubleBattle
|
case 1, BattleFrontier_BattlePikeRoomNormal_EventScript_WonDoubleBattle
|
||||||
|
|
@ -380,9 +374,7 @@ BattleFrontier_BattlePikeRoomNormal_EventScript_DoPikeQueenBattle::
|
||||||
closemessage
|
closemessage
|
||||||
applymovement LOCALID_PLAYER, BattleFrontier_BattlePikeRoomNormal_Movement_PlayerWalkUp2
|
applymovement LOCALID_PLAYER, BattleFrontier_BattlePikeRoomNormal_Movement_PlayerWalkUp2
|
||||||
waitmovement 0
|
waitmovement 0
|
||||||
setvar VAR_0x8004, SPECIAL_BATTLE_PIKE_SINGLE
|
dofacilitytrainerbattle FACILITY_BATTLE_PIKE_SINGLE
|
||||||
setvar VAR_0x8005, 0
|
|
||||||
special DoSpecialTrainerBattle
|
|
||||||
waitstate
|
waitstate
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ BattlePyramid_WarpToTop::
|
||||||
|
|
||||||
@ TRAINER_PHILLIP is used as a placeholder
|
@ TRAINER_PHILLIP is used as a placeholder
|
||||||
BattlePyramid_TrainerBattle::
|
BattlePyramid_TrainerBattle::
|
||||||
trainerbattle TRAINER_BATTLE_HILL, LOCALID_NONE, TRAINER_PHILLIP, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText, NULL, LOCALID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE
|
facilitytrainerbattle FACILITY_BATTLE_PYRAMID
|
||||||
pyramid_showhint
|
pyramid_showhint
|
||||||
waitmessage
|
waitmessage
|
||||||
waitbuttonpress
|
waitbuttonpress
|
||||||
|
|
|
||||||
|
|
@ -180,9 +180,7 @@ BattleFrontier_BattlePyramidTop_EventScript_DefeatedBrandonGold::
|
||||||
|
|
||||||
BattleFrontier_BattlePyramidTop_EventScript_DoBrandonBattle::
|
BattleFrontier_BattlePyramidTop_EventScript_DoBrandonBattle::
|
||||||
closemessage
|
closemessage
|
||||||
setvar VAR_0x8004, SPECIAL_BATTLE_PYRAMID
|
dofacilitytrainerbattle FACILITY_BATTLE_PYRAMID
|
||||||
setvar VAR_0x8005, 0
|
|
||||||
special DoSpecialTrainerBattle
|
|
||||||
waitstate
|
waitstate
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -296,9 +296,7 @@ BattleFrontier_BattleTowerBattleRoom_EventScript_DoTowerBattle::
|
||||||
setvar VAR_TEMP_2, 0
|
setvar VAR_TEMP_2, 0
|
||||||
frontier_set FRONTIER_DATA_RECORD_DISABLED, FALSE
|
frontier_set FRONTIER_DATA_RECORD_DISABLED, FALSE
|
||||||
special HealPlayerParty
|
special HealPlayerParty
|
||||||
setvar VAR_0x8004, SPECIAL_BATTLE_TOWER
|
dofacilitytrainerbattle FACILITY_BATTLE_TOWER
|
||||||
setvar VAR_0x8005, 0
|
|
||||||
special DoSpecialTrainerBattle
|
|
||||||
waitstate
|
waitstate
|
||||||
copyvar VAR_0x8004, VAR_FRONTIER_BATTLE_MODE
|
copyvar VAR_0x8004, VAR_FRONTIER_BATTLE_MODE
|
||||||
goto_if_eq VAR_0x8004, FRONTIER_MODE_LINK_MULTIS, BattleFrontier_BattleTowerBattleRoom_EventScript_EndTowerBattle
|
goto_if_eq VAR_0x8004, FRONTIER_MODE_LINK_MULTIS, BattleFrontier_BattleTowerBattleRoom_EventScript_EndTowerBattle
|
||||||
|
|
|
||||||
|
|
@ -57,9 +57,7 @@ SlateportCity_BattleTentBattleRoom_EventScript_EnterRoom::
|
||||||
waitmessage
|
waitmessage
|
||||||
closemessage
|
closemessage
|
||||||
special HealPlayerParty
|
special HealPlayerParty
|
||||||
setvar VAR_0x8004, SPECIAL_BATTLE_FACTORY
|
dofacilitytrainerbattle FACILITY_BATTLE_PYRAMID
|
||||||
setvar VAR_0x8005, 0
|
|
||||||
special DoSpecialTrainerBattle
|
|
||||||
waitstate
|
waitstate
|
||||||
switch VAR_RESULT
|
switch VAR_RESULT
|
||||||
case 1, SlateportCity_BattleTentBattleRoom_EventScript_DefeatedOpponent
|
case 1, SlateportCity_BattleTentBattleRoom_EventScript_DefeatedOpponent
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ TrainerHill_1F_Movement_SetInvisible::
|
||||||
|
|
||||||
@ TRAINER_PHILLIP is an actual Trainer on the SS Tidal, but is used as a placeholder here
|
@ TRAINER_PHILLIP is an actual Trainer on the SS Tidal, but is used as a placeholder here
|
||||||
TrainerHill_EventScript_TrainerBattle::
|
TrainerHill_EventScript_TrainerBattle::
|
||||||
trainerbattle TRAINER_BATTLE_HILL, LOCALID_NONE, TRAINER_PHILLIP, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText, NULL, LOCALID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE
|
facilitytrainerbattle FACILITY_BATTLE_TRAINER_HILL
|
||||||
trainerhill_postbattletext
|
trainerhill_postbattletext
|
||||||
waitmessage
|
waitmessage
|
||||||
waitbuttonpress
|
waitbuttonpress
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef GUARD_BATTLE_DOME_H
|
#ifndef GUARD_BATTLE_DOME_H
|
||||||
#define GUARD_BATTLE_DOME_H
|
#define GUARD_BATTLE_DOME_H
|
||||||
|
|
||||||
|
#include "constants/battle_dome.h"
|
||||||
|
|
||||||
int GetDomeTrainerSelectedMons(u16 tournamentTrainerId);
|
int GetDomeTrainerSelectedMons(u16 tournamentTrainerId);
|
||||||
int TrainerIdToDomeTournamentId(u16 trainerId);
|
int TrainerIdToDomeTournamentId(u16 trainerId);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,5 +8,6 @@ void FillFactoryBrainParty(void);
|
||||||
u8 GetNumPastRentalsRank(u8 battleMode, u8 lvlMode);
|
u8 GetNumPastRentalsRank(u8 battleMode, u8 lvlMode);
|
||||||
u64 GetAiScriptsInBattleFactory(void);
|
u64 GetAiScriptsInBattleFactory(void);
|
||||||
void SetMonMoveAvoidReturn(struct Pokemon *mon, u16 moveArg, u8 moveSlot);
|
void SetMonMoveAvoidReturn(struct Pokemon *mon, u16 moveArg, u8 moveSlot);
|
||||||
|
void FillFactoryTrainerParty(void);
|
||||||
|
|
||||||
#endif // GUARD_BATTLE_FACTORY_H
|
#endif // GUARD_BATTLE_FACTORY_H
|
||||||
|
|
|
||||||
32
include/battle_frontier.h
Normal file
32
include/battle_frontier.h
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef GUARD_BATTLE_FRONTIER_H
|
||||||
|
#define GUARD_BATTLE_FRONTIER_H
|
||||||
|
|
||||||
|
#include "data.h"
|
||||||
|
#include "script.h"
|
||||||
|
|
||||||
|
struct BattleFrontierTrainer
|
||||||
|
{
|
||||||
|
u8 facilityClass;
|
||||||
|
u8 filler1[3];
|
||||||
|
u8 trainerName[PLAYER_NAME_LENGTH + 1];
|
||||||
|
u16 speechBefore[EASY_CHAT_BATTLE_WORDS_COUNT];
|
||||||
|
u16 speechWin[EASY_CHAT_BATTLE_WORDS_COUNT];
|
||||||
|
u16 speechLose[EASY_CHAT_BATTLE_WORDS_COUNT];
|
||||||
|
const u16 *monSet;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Temporary storage for monIds of the opponent team
|
||||||
|
// during team generation in battle factory and similar facilities.
|
||||||
|
extern u16 gFrontierTempParty[MAX_FRONTIER_PARTY_SIZE];
|
||||||
|
|
||||||
|
extern const struct BattleFrontierTrainer *gFacilityTrainers;
|
||||||
|
extern const struct TrainerMon *gFacilityTrainerMons;
|
||||||
|
extern const struct BattleFrontierTrainer gBattleFrontierTrainers[];
|
||||||
|
extern const struct TrainerMon gBattleFrontierMons[];
|
||||||
|
|
||||||
|
void DoFacilityTrainerBattle(struct ScriptContext *ctx);
|
||||||
|
void FillFrontierTrainerParty(u8 monsCount);
|
||||||
|
void FillFrontierTrainersParties(u8 monsCount);
|
||||||
|
void CreateFacilityMon(const struct TrainerMon *fmon, u16 level, u8 fixedIV, u32 otID, u32 flags, struct Pokemon *dst);
|
||||||
|
|
||||||
|
#endif // GUARD_BATTLE_FRONTIER_H
|
||||||
11
include/battle_partner.h
Normal file
11
include/battle_partner.h
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef BATTLE_PARTNER_H
|
||||||
|
#define BATTLE_PARTNER_H
|
||||||
|
|
||||||
|
#include "difficulty.h"
|
||||||
|
#include "constants/battle_partner.h"
|
||||||
|
|
||||||
|
extern const struct Trainer gBattlePartners[DIFFICULTY_COUNT][PARTNER_COUNT];
|
||||||
|
|
||||||
|
void FillPartnerParty(u16 trainerId);
|
||||||
|
|
||||||
|
#endif // BATTLE_PARTNER_H
|
||||||
|
|
@ -42,7 +42,6 @@ typedef union PACKED TrainerBattleParameter
|
||||||
u8 data[sizeof(struct _TrainerBattleParameter)];
|
u8 data[sizeof(struct _TrainerBattleParameter)];
|
||||||
} TrainerBattleParameter;
|
} TrainerBattleParameter;
|
||||||
|
|
||||||
|
|
||||||
extern const struct RematchTrainer gRematchTable[REMATCH_TABLE_ENTRIES];
|
extern const struct RematchTrainer gRematchTable[REMATCH_TABLE_ENTRIES];
|
||||||
|
|
||||||
extern TrainerBattleParameter gTrainerBattleParameter;
|
extern TrainerBattleParameter gTrainerBattleParameter;
|
||||||
|
|
@ -70,6 +69,7 @@ void ResetTrainerOpponentIds(void);
|
||||||
void SetMapVarsToTrainerA(void);
|
void SetMapVarsToTrainerA(void);
|
||||||
void SetMapVarsToTrainerB(void);
|
void SetMapVarsToTrainerB(void);
|
||||||
const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data);
|
const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data);
|
||||||
|
const u8* BattleSetup_ConfigureFacilityTrainerBattle(u8 facility, const u8* scriptEndPtr);
|
||||||
void ConfigureAndSetUpOneTrainerBattle(u8 trainerObjEventId, const u8 *trainerScript);
|
void ConfigureAndSetUpOneTrainerBattle(u8 trainerObjEventId, const u8 *trainerScript);
|
||||||
void ConfigureTwoTrainersBattle(u8 trainerObjEventId, const u8 *trainerScript);
|
void ConfigureTwoTrainersBattle(u8 trainerObjEventId, const u8 *trainerScript);
|
||||||
void SetUpTwoTrainersBattle(void);
|
void SetUpTwoTrainersBattle(void);
|
||||||
|
|
@ -107,6 +107,7 @@ void TrainerBattleLoadArgs(const u8 *data);
|
||||||
void TrainerBattleLoadArgsTrainerA(const u8 *data);
|
void TrainerBattleLoadArgsTrainerA(const u8 *data);
|
||||||
void TrainerBattleLoadArgsTrainerB(const u8 *data);
|
void TrainerBattleLoadArgsTrainerB(const u8 *data);
|
||||||
void TrainerBattleLoadArgsSecondTrainer(const u8 *data);
|
void TrainerBattleLoadArgsSecondTrainer(const u8 *data);
|
||||||
|
void InitTrainerBattleParameter(void);
|
||||||
|
|
||||||
void DoStandardWildBattle_Debug(void);
|
void DoStandardWildBattle_Debug(void);
|
||||||
void BattleSetup_StartTrainerBattle_Debug(void);
|
void BattleSetup_StartTrainerBattle_Debug(void);
|
||||||
|
|
|
||||||
13
include/battle_special.h
Normal file
13
include/battle_special.h
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef GUARD_BATTLE_SPECIAL_H
|
||||||
|
#define GUARD_BATTLE_SPECIAL_H
|
||||||
|
|
||||||
|
void DoSpecialTrainerBattle(void);
|
||||||
|
void SetEReaderTrainerGfxId(void);
|
||||||
|
u8 GetEreaderTrainerFrontSpriteId(void);
|
||||||
|
enum TrainerClassID GetEreaderTrainerClassId(void);
|
||||||
|
void GetEreaderTrainerName(u8 *dst);
|
||||||
|
void ValidateEReaderTrainer(void);
|
||||||
|
void ClearEReaderTrainer(struct BattleTowerEReaderTrainer *ereaderTrainer);
|
||||||
|
void CopyEReaderTrainerGreeting(void);
|
||||||
|
|
||||||
|
#endif // GUARD_BATTLE_SPECIAL_H
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#define GUARD_BATTLE_TOWER_H
|
#define GUARD_BATTLE_TOWER_H
|
||||||
|
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
|
#include "battle_frontier.h"
|
||||||
|
|
||||||
struct RSBattleTowerRecord
|
struct RSBattleTowerRecord
|
||||||
{
|
{
|
||||||
|
|
@ -15,68 +16,27 @@ struct RSBattleTowerRecord
|
||||||
/*0xA0*/ u32 checksum;
|
/*0xA0*/ u32 checksum;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BattleFrontierTrainer
|
|
||||||
{
|
|
||||||
u8 facilityClass;
|
|
||||||
u8 filler1[3];
|
|
||||||
u8 trainerName[PLAYER_NAME_LENGTH + 1];
|
|
||||||
u16 speechBefore[EASY_CHAT_BATTLE_WORDS_COUNT];
|
|
||||||
u16 speechWin[EASY_CHAT_BATTLE_WORDS_COUNT];
|
|
||||||
u16 speechLose[EASY_CHAT_BATTLE_WORDS_COUNT];
|
|
||||||
const u16 *monSet;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const u8 gTowerMaleFacilityClasses[30];
|
extern const u8 gTowerMaleFacilityClasses[30];
|
||||||
extern const u16 gTowerMaleTrainerGfxIds[30];
|
extern const u16 gTowerMaleTrainerGfxIds[30];
|
||||||
extern const u8 gTowerFemaleFacilityClasses[20];
|
extern const u8 gTowerFemaleFacilityClasses[20];
|
||||||
extern const u16 gTowerFemaleTrainerGfxIds[20];
|
extern const u16 gTowerFemaleTrainerGfxIds[20];
|
||||||
extern const struct TrainerMon gBattleFrontierMons[];
|
|
||||||
extern const struct BattleFrontierTrainer gBattleFrontierTrainers[];
|
|
||||||
extern const struct TrainerMon gSlateportBattleTentMons[];
|
extern const struct TrainerMon gSlateportBattleTentMons[];
|
||||||
extern const struct BattleFrontierTrainer gSlateportBattleTentTrainers[];
|
extern const struct BattleFrontierTrainer gSlateportBattleTentTrainers[];
|
||||||
|
|
||||||
// Temporary storage for monIds of the opponent team
|
|
||||||
// during team generation in battle factory and similar facilities.
|
|
||||||
extern u16 gFrontierTempParty[];
|
|
||||||
|
|
||||||
extern const struct BattleFrontierTrainer *gFacilityTrainers;
|
|
||||||
extern const struct TrainerMon *gFacilityTrainerMons;
|
|
||||||
|
|
||||||
void CallBattleTowerFunc(void);
|
void CallBattleTowerFunc(void);
|
||||||
u16 GetRandomScaledFrontierTrainerId(u8 challengeNum, u8 battleNum);
|
|
||||||
void SetBattleFacilityTrainerGfxId(u16 trainerId, u8 tempVarId);
|
|
||||||
void SetEReaderTrainerGfxId(void);
|
|
||||||
u16 GetBattleFacilityTrainerGfxId(u16 trainerId);
|
|
||||||
void PutNewBattleTowerRecord(struct EmeraldBattleTowerRecord *newRecordEm);
|
void PutNewBattleTowerRecord(struct EmeraldBattleTowerRecord *newRecordEm);
|
||||||
u8 GetFrontierTrainerFrontSpriteId(u16 trainerId);
|
|
||||||
enum TrainerClassID GetFrontierOpponentClass(u16 trainerId);
|
|
||||||
void GetFrontierTrainerName(u8 *dst, u16 trainerId);
|
|
||||||
void FillFrontierTrainerParty(u8 monsCount);
|
|
||||||
void FillFrontierTrainersParties(u8 monsCount);
|
|
||||||
u16 GetRandomFrontierMonFromSet(u16 trainerId);
|
|
||||||
void FrontierSpeechToString(const u16 *words);
|
|
||||||
void DoSpecialTrainerBattle(void);
|
|
||||||
void CalcEmeraldBattleTowerChecksum(struct EmeraldBattleTowerRecord *record);
|
void CalcEmeraldBattleTowerChecksum(struct EmeraldBattleTowerRecord *record);
|
||||||
void CalcRubyBattleTowerChecksum(struct RSBattleTowerRecord *record);
|
void CalcRubyBattleTowerChecksum(struct RSBattleTowerRecord *record);
|
||||||
u16 GetCurrentBattleTowerWinStreak(u8 lvlMode, u8 battleMode);
|
u16 GetCurrentBattleTowerWinStreak(u8 lvlMode, u8 battleMode);
|
||||||
u8 GetEreaderTrainerFrontSpriteId(void);
|
|
||||||
enum TrainerClassID GetEreaderTrainerClassId(void);
|
|
||||||
void GetEreaderTrainerName(u8 *dst);
|
|
||||||
void ValidateEReaderTrainer(void);
|
|
||||||
void ClearEReaderTrainer(struct BattleTowerEReaderTrainer *ereaderTrainer);
|
|
||||||
void CopyEReaderTrainerGreeting(void);
|
|
||||||
void TryHideBattleTowerReporter(void);
|
void TryHideBattleTowerReporter(void);
|
||||||
bool32 RubyBattleTowerRecordToEmerald(struct RSBattleTowerRecord *src, struct EmeraldBattleTowerRecord *dst);
|
bool32 RubyBattleTowerRecordToEmerald(struct RSBattleTowerRecord *src, struct EmeraldBattleTowerRecord *dst);
|
||||||
bool32 EmeraldBattleTowerRecordToRuby(struct EmeraldBattleTowerRecord *src, struct RSBattleTowerRecord *dst);
|
bool32 EmeraldBattleTowerRecordToRuby(struct EmeraldBattleTowerRecord *src, struct RSBattleTowerRecord *dst);
|
||||||
void CalcApprenticeChecksum(struct Apprentice *apprentice);
|
void CalcApprenticeChecksum(struct Apprentice *apprentice);
|
||||||
void GetBattleTowerTrainerLanguage(u8 *dst, u16 trainerId);
|
void GetBattleTowerTrainerLanguage(u8 *dst, u16 trainerId);
|
||||||
u8 SetFacilityPtrsGetLevel(void);
|
u8 SetTentPtrsGetLevel(void);
|
||||||
u8 GetFrontierEnemyMonLevel(u8 lvlMode);
|
|
||||||
s32 GetHighestLevelInPlayerParty(void);
|
|
||||||
u16 FacilityClassToGraphicsId(u8 facilityClass);
|
|
||||||
bool32 ValidateBattleTowerRecord(u8 recordId); // unused
|
bool32 ValidateBattleTowerRecord(u8 recordId); // unused
|
||||||
void TrySetLinkBattleTowerEnemyPartyLevel(void);
|
void TrySetLinkBattleTowerEnemyPartyLevel(void);
|
||||||
void CreateFacilityMon(const struct TrainerMon *fmon, u16 level, u8 fixedIV, u32 otID, u32 flags, struct Pokemon *dst);
|
void FillTentTrainerParty(u8 monsCount);
|
||||||
void FillPartnerParty(u16 trainerId);
|
|
||||||
|
|
||||||
#endif //GUARD_BATTLE_TOWER_H
|
#endif //GUARD_BATTLE_TOWER_H
|
||||||
|
|
|
||||||
|
|
@ -33,17 +33,20 @@
|
||||||
#define CHALLENGE_STATUS_LOST 4
|
#define CHALLENGE_STATUS_LOST 4
|
||||||
|
|
||||||
// Special trainer battles.
|
// Special trainer battles.
|
||||||
#define SPECIAL_BATTLE_TOWER 0
|
|
||||||
#define SPECIAL_BATTLE_SECRET_BASE 1
|
#define SPECIAL_BATTLE_SECRET_BASE 1
|
||||||
#define SPECIAL_BATTLE_EREADER 2
|
#define SPECIAL_BATTLE_EREADER 2
|
||||||
#define SPECIAL_BATTLE_DOME 3
|
#define SPECIAL_BATTLE_MULTI 3
|
||||||
#define SPECIAL_BATTLE_PALACE 4
|
|
||||||
#define SPECIAL_BATTLE_ARENA 5
|
// Facility trainer Battles
|
||||||
#define SPECIAL_BATTLE_FACTORY 6
|
#define FACILITY_BATTLE_TOWER 0
|
||||||
#define SPECIAL_BATTLE_PIKE_SINGLE 7
|
#define FACILITY_BATTLE_DOME 1
|
||||||
#define SPECIAL_BATTLE_PIKE_DOUBLE 8
|
#define FACILITY_BATTLE_PALACE 2
|
||||||
#define SPECIAL_BATTLE_PYRAMID 9
|
#define FACILITY_BATTLE_ARENA 3
|
||||||
#define SPECIAL_BATTLE_MULTI 10
|
#define FACILITY_BATTLE_FACTORY 4
|
||||||
|
#define FACILITY_BATTLE_PIKE_SINGLE 5
|
||||||
|
#define FACILITY_BATTLE_PIKE_DOUBLE 6
|
||||||
|
#define FACILITY_BATTLE_PYRAMID 7
|
||||||
|
#define FACILITY_BATTLE_TRAINER_HILL 8
|
||||||
|
|
||||||
#define MAX_BATTLE_FRONTIER_POINTS 9999
|
#define MAX_BATTLE_FRONTIER_POINTS 9999
|
||||||
#define MAX_STREAK 9999
|
#define MAX_STREAK 9999
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,6 @@
|
||||||
#define TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE 6
|
#define TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE 6
|
||||||
#define TRAINER_BATTLE_REMATCH_DOUBLE 7
|
#define TRAINER_BATTLE_REMATCH_DOUBLE 7
|
||||||
#define TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC 8
|
#define TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC 8
|
||||||
#define TRAINER_BATTLE_PYRAMID 9
|
|
||||||
#define TRAINER_BATTLE_SET_TRAINERS_FOR_MULTI_BATTLE 10
|
|
||||||
#define TRAINER_BATTLE_HILL 12
|
|
||||||
#define TRAINER_BATTLE_TWO_TRAINERS_NO_INTRO 13
|
#define TRAINER_BATTLE_TWO_TRAINERS_NO_INTRO 13
|
||||||
|
|
||||||
#endif // GUARD_CONSTANTS_BATTLE_SETUP_H
|
#endif // GUARD_CONSTANTS_BATTLE_SETUP_H
|
||||||
|
|
|
||||||
10
include/constants/battle_special.h
Normal file
10
include/constants/battle_special.h
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#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
|
||||||
|
|
@ -38,10 +38,4 @@
|
||||||
#define BATTLE_TOWER_LINKSTAT_MEMBER_RETIRE 2
|
#define BATTLE_TOWER_LINKSTAT_MEMBER_RETIRE 2
|
||||||
#define BATTLE_TOWER_LINKSTAT_LEADER_RETIRE 3
|
#define BATTLE_TOWER_LINKSTAT_LEADER_RETIRE 3
|
||||||
|
|
||||||
// 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_TOWER_H
|
#endif //GUARD_CONSTANTS_BATTLE_TOWER_H
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,21 @@ u8 GetFrontierBrainMonNature(u8 monId);
|
||||||
u8 GetFrontierBrainMonEvs(u8 monId, u8 evStatId);
|
u8 GetFrontierBrainMonEvs(u8 monId, u8 evStatId);
|
||||||
s32 GetFronterBrainSymbol(void);
|
s32 GetFronterBrainSymbol(void);
|
||||||
void ClearEnemyPartyAfterChallenge(void);
|
void ClearEnemyPartyAfterChallenge(void);
|
||||||
|
bool8 IsFrontierTrainerFemale(u16 trainerId);
|
||||||
|
u8 GetFrontierTrainerFixedIvs(u16 trainerId);
|
||||||
|
u16 GetRandomScaledFrontierTrainerId(u8 challengeNum, u8 battleNum);
|
||||||
|
void SetBattleFacilityTrainerGfxId(u16 trainerId, u8 tempVarId);
|
||||||
|
u16 GetBattleFacilityTrainerGfxId(u16 trainerId);
|
||||||
|
u8 GetFrontierTrainerFrontSpriteId(u16 trainerId);
|
||||||
|
enum TrainerClassID GetFrontierOpponentClass(u16 trainerId);
|
||||||
|
u8 GetFrontierTrainerFacilityClass(u16 trainerId);
|
||||||
|
void GetFrontierTrainerName(u8 *dst, u16 trainerId);
|
||||||
|
u16 GetRandomFrontierMonFromSet(u16 trainerId);
|
||||||
|
void FrontierSpeechToString(const u16 *words);
|
||||||
|
u8 SetFacilityPtrsGetLevel(void);
|
||||||
|
u8 GetFrontierEnemyMonLevel(u8 lvlMode);
|
||||||
|
s32 GetHighestLevelInPlayerParty(void);
|
||||||
|
u16 FacilityClassToGraphicsId(u8 facilityClass);
|
||||||
void ShowBattleFrontierCaughtBannedSpecies(void);
|
void ShowBattleFrontierCaughtBannedSpecies(void);
|
||||||
|
|
||||||
#endif // GUARD_FRONTIER_UTIL_H
|
#endif // GUARD_FRONTIER_UTIL_H
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "event_data.h"
|
#include "event_data.h"
|
||||||
#include "event_object_movement.h"
|
#include "event_object_movement.h"
|
||||||
|
#include "frontier_util.h"
|
||||||
#include "field_player_avatar.h"
|
#include "field_player_avatar.h"
|
||||||
#include "international_string_util.h"
|
#include "international_string_util.h"
|
||||||
#include "item.h"
|
#include "item.h"
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include "battle_tv.h"
|
#include "battle_tv.h"
|
||||||
#include "bg.h"
|
#include "bg.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
|
#include "frontier_util.h"
|
||||||
#include "link.h"
|
#include "link.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "m4a.h"
|
#include "m4a.h"
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include "battle_tv.h"
|
#include "battle_tv.h"
|
||||||
#include "bg.h"
|
#include "bg.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
|
#include "frontier_util.h"
|
||||||
#include "link.h"
|
#include "link.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "m4a.h"
|
#include "m4a.h"
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
#include "battle_message.h"
|
#include "battle_message.h"
|
||||||
#include "battle_interface.h"
|
#include "battle_interface.h"
|
||||||
#include "battle_setup.h"
|
#include "battle_setup.h"
|
||||||
#include "battle_tower.h"
|
#include "battle_special.h"
|
||||||
#include "battle_tv.h"
|
#include "battle_tv.h"
|
||||||
#include "battle_z_move.h"
|
#include "battle_z_move.h"
|
||||||
#include "bg.h"
|
#include "bg.h"
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include "battle_z_move.h"
|
#include "battle_z_move.h"
|
||||||
#include "bg.h"
|
#include "bg.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
|
#include "frontier_util.h"
|
||||||
#include "item_use.h"
|
#include "item_use.h"
|
||||||
#include "link.h"
|
#include "link.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include "battle_tv.h"
|
#include "battle_tv.h"
|
||||||
#include "bg.h"
|
#include "bg.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
|
#include "frontier_util.h"
|
||||||
#include "item_menu.h"
|
#include "item_menu.h"
|
||||||
#include "item_use.h"
|
#include "item_use.h"
|
||||||
#include "link.h"
|
#include "link.h"
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include "battle_z_move.h"
|
#include "battle_z_move.h"
|
||||||
#include "bg.h"
|
#include "bg.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
|
#include "frontier_util.h"
|
||||||
#include "item_use.h"
|
#include "item_use.h"
|
||||||
#include "link.h"
|
#include "link.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
|
||||||
|
|
@ -848,3 +848,81 @@ void SetMonMoveAvoidReturn(struct Pokemon *mon, u16 moveArg, u8 moveSlot)
|
||||||
move = MOVE_FRUSTRATION;
|
move = MOVE_FRUSTRATION;
|
||||||
SetMonMoveSlot(mon, move, moveSlot);
|
SetMonMoveSlot(mon, move, moveSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void FillFactoryFrontierTrainerParty(u16 trainerId, u8 firstMonId)
|
||||||
|
{
|
||||||
|
u8 i;
|
||||||
|
u8 level;
|
||||||
|
u8 fixedIV;
|
||||||
|
u32 otID;
|
||||||
|
|
||||||
|
if (trainerId < FRONTIER_TRAINERS_COUNT)
|
||||||
|
{
|
||||||
|
// By mistake Battle Tower's Level 50 challenge number is used to determine the IVs for Battle Factory.
|
||||||
|
#ifdef BUGFIX
|
||||||
|
u8 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
|
||||||
|
u8 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
|
||||||
|
u8 challengeNum = gSaveBlock2Ptr->frontier.factoryWinStreaks[battleMode][lvlMode] / FRONTIER_STAGES_PER_CHALLENGE;
|
||||||
|
#else
|
||||||
|
u8 UNUSED lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
|
||||||
|
u8 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
|
||||||
|
u8 challengeNum = gSaveBlock2Ptr->frontier.towerWinStreaks[battleMode][FRONTIER_LVL_50] / FRONTIER_STAGES_PER_CHALLENGE;
|
||||||
|
#endif
|
||||||
|
if (gSaveBlock2Ptr->frontier.curChallengeBattleNum < FRONTIER_STAGES_PER_CHALLENGE - 1)
|
||||||
|
fixedIV = GetFactoryMonFixedIV(challengeNum, FALSE);
|
||||||
|
else
|
||||||
|
fixedIV = GetFactoryMonFixedIV(challengeNum, TRUE); // Last trainer in challenge uses higher IVs
|
||||||
|
}
|
||||||
|
else if (trainerId == TRAINER_EREADER)
|
||||||
|
{
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
for (i = firstMonId; i < firstMonId + FRONTIER_PARTY_SIZE; i++)
|
||||||
|
CreateBattleTowerMon(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.ereaderTrainer.party[i - firstMonId]);
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (trainerId == TRAINER_FRONTIER_BRAIN)
|
||||||
|
{
|
||||||
|
FillFactoryBrainParty();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fixedIV = MAX_PER_STAT_IVS;
|
||||||
|
}
|
||||||
|
|
||||||
|
level = SetFacilityPtrsGetLevel();
|
||||||
|
otID = T1_READ_32(gSaveBlock2Ptr->playerTrainerId);
|
||||||
|
for (i = 0; i < FRONTIER_PARTY_SIZE; i++)
|
||||||
|
{
|
||||||
|
u16 monId = gFrontierTempParty[i];
|
||||||
|
CreateFacilityMon(&gFacilityTrainerMons[monId],
|
||||||
|
level, fixedIV, otID, FLAG_FRONTIER_MON_FACTORY,
|
||||||
|
&gEnemyParty[firstMonId + i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FillFactoryTentTrainerParty(u16 trainerId, u8 firstMonId)
|
||||||
|
{
|
||||||
|
u8 i;
|
||||||
|
u8 level = TENT_MIN_LEVEL;
|
||||||
|
u8 fixedIV = 0;
|
||||||
|
u32 otID = T1_READ_32(gSaveBlock2Ptr->playerTrainerId);
|
||||||
|
|
||||||
|
for (i = 0; i < FRONTIER_PARTY_SIZE; i++)
|
||||||
|
{
|
||||||
|
u16 monId = gFrontierTempParty[i];
|
||||||
|
CreateFacilityMon(&gFacilityTrainerMons[monId],
|
||||||
|
level, fixedIV, otID, 0,
|
||||||
|
&gEnemyParty[firstMonId + i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FillFactoryTrainerParty(void)
|
||||||
|
{
|
||||||
|
ZeroEnemyPartyMons();
|
||||||
|
if (gSaveBlock2Ptr->frontier.lvlMode != FRONTIER_LVL_TENT)
|
||||||
|
FillFactoryFrontierTrainerParty(TRAINER_BATTLE_PARAM.opponentA, 0);
|
||||||
|
else
|
||||||
|
FillFactoryTentTrainerParty(TRAINER_BATTLE_PARAM.opponentA, 0);
|
||||||
|
}
|
||||||
|
|
|
||||||
395
src/battle_frontier.c
Normal file
395
src/battle_frontier.c
Normal file
|
|
@ -0,0 +1,395 @@
|
||||||
|
#include "global.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "battle.h"
|
||||||
|
#include "battle_main.h"
|
||||||
|
#include "battle_frontier.h"
|
||||||
|
#include "battle_setup.h"
|
||||||
|
#include "battle_dome.h"
|
||||||
|
#include "battle_factory.h"
|
||||||
|
#include "battle_partner.h"
|
||||||
|
#include "battle_tower.h"
|
||||||
|
#include "battle_transition.h"
|
||||||
|
#include "event_data.h"
|
||||||
|
#include "frontier_util.h"
|
||||||
|
#include "overworld.h"
|
||||||
|
#include "script.h"
|
||||||
|
#include "string_util.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "text.h"
|
||||||
|
#include "constants/abilities.h"
|
||||||
|
#include "constants/battle_frontier.h"
|
||||||
|
#include "constants/battle_frontier_mons.h"
|
||||||
|
|
||||||
|
static void FillTrainerParty(u16 trainerId, u8 firstMonId, u8 monCount);
|
||||||
|
|
||||||
|
// EWRAM vars.
|
||||||
|
EWRAM_DATA const struct BattleFrontierTrainer *gFacilityTrainers = NULL;
|
||||||
|
EWRAM_DATA const struct TrainerMon *gFacilityTrainerMons = NULL;
|
||||||
|
|
||||||
|
// IWRAM common
|
||||||
|
COMMON_DATA u16 gFrontierTempParty[MAX_FRONTIER_PARTY_SIZE] = {0};
|
||||||
|
|
||||||
|
static void HandleFacilityTrainerBattleEnd(void)
|
||||||
|
{
|
||||||
|
u8 facility = gBattleScripting.specialTrainerBattleType;
|
||||||
|
switch (facility)
|
||||||
|
{
|
||||||
|
case FACILITY_BATTLE_TOWER:
|
||||||
|
case FACILITY_BATTLE_DOME:
|
||||||
|
case FACILITY_BATTLE_PALACE:
|
||||||
|
case FACILITY_BATTLE_ARENA:
|
||||||
|
case FACILITY_BATTLE_FACTORY:
|
||||||
|
case FACILITY_BATTLE_PIKE_SINGLE:
|
||||||
|
case FACILITY_BATTLE_PIKE_DOUBLE:
|
||||||
|
case FACILITY_BATTLE_PYRAMID:
|
||||||
|
if (gSaveBlock2Ptr->frontier.battlesCount < 0xFFFFFF)
|
||||||
|
{
|
||||||
|
gSaveBlock2Ptr->frontier.battlesCount++;
|
||||||
|
if (gSaveBlock2Ptr->frontier.battlesCount % 20 == 0)
|
||||||
|
UpdateGymLeaderRematch();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gSaveBlock2Ptr->frontier.battlesCount = 0xFFFFFF;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FACILITY_BATTLE_TRAINER_HILL:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Task_StartBattleAfterTransition(u8 taskId)
|
||||||
|
{
|
||||||
|
if (IsBattleTransitionDone() == TRUE)
|
||||||
|
{
|
||||||
|
gMain.savedCallback = HandleFacilityTrainerBattleEnd;
|
||||||
|
SetMainCallback2(CB2_InitBattle);
|
||||||
|
DestroyTask(taskId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DoFacilityTrainerBattleInternal(u8 facility)
|
||||||
|
{
|
||||||
|
gBattleScripting.specialTrainerBattleType = facility;
|
||||||
|
|
||||||
|
switch (facility)
|
||||||
|
{
|
||||||
|
case FACILITY_BATTLE_TOWER:
|
||||||
|
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_BATTLE_TOWER;
|
||||||
|
switch (VarGet(VAR_FRONTIER_BATTLE_MODE))
|
||||||
|
{
|
||||||
|
case FRONTIER_MODE_SINGLES:
|
||||||
|
FillFrontierTrainerParty(FRONTIER_PARTY_SIZE);
|
||||||
|
break;
|
||||||
|
case FRONTIER_MODE_DOUBLES:
|
||||||
|
FillFrontierTrainerParty(FRONTIER_DOUBLES_PARTY_SIZE);
|
||||||
|
gBattleTypeFlags |= BATTLE_TYPE_DOUBLE;
|
||||||
|
break;
|
||||||
|
case FRONTIER_MODE_MULTIS:
|
||||||
|
FillFrontierTrainersParties(FRONTIER_MULTI_PARTY_SIZE);
|
||||||
|
gPartnerTrainerId = gSaveBlock2Ptr->frontier.trainerIds[17];
|
||||||
|
FillPartnerParty(gPartnerTrainerId);
|
||||||
|
gBattleTypeFlags |= BATTLE_TYPE_DOUBLE | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS;
|
||||||
|
break;
|
||||||
|
case FRONTIER_MODE_LINK_MULTIS:
|
||||||
|
gBattleTypeFlags |= BATTLE_TYPE_DOUBLE | BATTLE_TYPE_LINK | BATTLE_TYPE_MULTI | BATTLE_TYPE_TOWER_LINK_MULTI;
|
||||||
|
FillFrontierTrainersParties(FRONTIER_MULTI_PARTY_SIZE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
||||||
|
PlayMapChosenOrBattleBGM(0);
|
||||||
|
BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_TOWER));
|
||||||
|
break;
|
||||||
|
case FACILITY_BATTLE_DOME:
|
||||||
|
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOME;
|
||||||
|
if (VarGet(VAR_FRONTIER_BATTLE_MODE) == FRONTIER_MODE_DOUBLES)
|
||||||
|
gBattleTypeFlags |= BATTLE_TYPE_DOUBLE;
|
||||||
|
if (TRAINER_BATTLE_PARAM.opponentA == TRAINER_FRONTIER_BRAIN)
|
||||||
|
FillFrontierTrainerParty(DOME_BATTLE_PARTY_SIZE);
|
||||||
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
||||||
|
CreateTask_PlayMapChosenOrBattleBGM(0);
|
||||||
|
BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_DOME));
|
||||||
|
break;
|
||||||
|
case FACILITY_BATTLE_PALACE:
|
||||||
|
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE;
|
||||||
|
if (VarGet(VAR_FRONTIER_BATTLE_MODE) == FRONTIER_MODE_DOUBLES)
|
||||||
|
gBattleTypeFlags |= BATTLE_TYPE_DOUBLE;
|
||||||
|
if (gSaveBlock2Ptr->frontier.lvlMode != FRONTIER_LVL_TENT)
|
||||||
|
FillFrontierTrainerParty(FRONTIER_PARTY_SIZE);
|
||||||
|
else
|
||||||
|
FillTentTrainerParty(FRONTIER_PARTY_SIZE);
|
||||||
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
||||||
|
PlayMapChosenOrBattleBGM(0);
|
||||||
|
BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_PALACE));
|
||||||
|
break;
|
||||||
|
case FACILITY_BATTLE_ARENA:
|
||||||
|
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_ARENA;
|
||||||
|
if (gSaveBlock2Ptr->frontier.lvlMode != FRONTIER_LVL_TENT)
|
||||||
|
FillFrontierTrainerParty(FRONTIER_PARTY_SIZE);
|
||||||
|
else
|
||||||
|
FillTentTrainerParty(FRONTIER_PARTY_SIZE);
|
||||||
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
||||||
|
PlayMapChosenOrBattleBGM(0);
|
||||||
|
BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_ARENA));
|
||||||
|
break;
|
||||||
|
case FACILITY_BATTLE_FACTORY:
|
||||||
|
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_FACTORY;
|
||||||
|
if (VarGet(VAR_FRONTIER_BATTLE_MODE) == FRONTIER_MODE_DOUBLES)
|
||||||
|
gBattleTypeFlags |= BATTLE_TYPE_DOUBLE;
|
||||||
|
FillFactoryTrainerParty();
|
||||||
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
||||||
|
PlayMapChosenOrBattleBGM(0);
|
||||||
|
BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_FACTORY));
|
||||||
|
break;
|
||||||
|
case FACILITY_BATTLE_PIKE_SINGLE:
|
||||||
|
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_BATTLE_TOWER;
|
||||||
|
FillFrontierTrainerParty(FRONTIER_PARTY_SIZE);
|
||||||
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
||||||
|
PlayMapChosenOrBattleBGM(0);
|
||||||
|
BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_PIKE));
|
||||||
|
break;
|
||||||
|
case FACILITY_BATTLE_PIKE_DOUBLE:
|
||||||
|
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS;
|
||||||
|
FillFrontierTrainersParties(1);
|
||||||
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
||||||
|
PlayMapChosenOrBattleBGM(0);
|
||||||
|
BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_PIKE));
|
||||||
|
break;
|
||||||
|
case FACILITY_BATTLE_PYRAMID:
|
||||||
|
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_PYRAMID;
|
||||||
|
FillFrontierTrainerParty(FRONTIER_PARTY_SIZE);
|
||||||
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
||||||
|
PlayMapChosenOrBattleBGM(0);
|
||||||
|
BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_PYRAMID));
|
||||||
|
break;
|
||||||
|
case FACILITY_BATTLE_TRAINER_HILL:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoFacilityTrainerBattle(struct ScriptContext *ctx)
|
||||||
|
{
|
||||||
|
u8 facility = ScriptReadByte(ctx);
|
||||||
|
|
||||||
|
DoFacilityTrainerBattleInternal(facility);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FacilityTrainerBattle(struct ScriptContext *ctx)
|
||||||
|
{
|
||||||
|
InitTrainerBattleParameter();
|
||||||
|
|
||||||
|
u8 facility = ScriptReadByte(ctx);
|
||||||
|
ctx->scriptPtr = BattleSetup_ConfigureFacilityTrainerBattle(facility, ctx->scriptPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FillFrontierTrainerParty(u8 monsCount)
|
||||||
|
{
|
||||||
|
ZeroEnemyPartyMons();
|
||||||
|
FillTrainerParty(TRAINER_BATTLE_PARAM.opponentA, 0, monsCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FillFrontierTrainersParties(u8 monsCount)
|
||||||
|
{
|
||||||
|
ZeroEnemyPartyMons();
|
||||||
|
FillTrainerParty(TRAINER_BATTLE_PARAM.opponentA, 0, monsCount);
|
||||||
|
FillTrainerParty(TRAINER_BATTLE_PARAM.opponentB, 3, monsCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FillTrainerParty(u16 trainerId, u8 firstMonId, u8 monCount)
|
||||||
|
{
|
||||||
|
s32 i, j;
|
||||||
|
u16 chosenMonIndices[MAX_FRONTIER_PARTY_SIZE];
|
||||||
|
u8 level = SetFacilityPtrsGetLevel();
|
||||||
|
u8 fixedIV = 0;
|
||||||
|
u8 bfMonCount;
|
||||||
|
const u16 *monSet = NULL;
|
||||||
|
u32 otID = 0;
|
||||||
|
|
||||||
|
if (trainerId < FRONTIER_TRAINERS_COUNT)
|
||||||
|
{
|
||||||
|
// Normal battle frontier trainer.
|
||||||
|
fixedIV = GetFrontierTrainerFixedIvs(trainerId);
|
||||||
|
monSet = gFacilityTrainers[TRAINER_BATTLE_PARAM.opponentA].monSet;
|
||||||
|
}
|
||||||
|
else if (trainerId == TRAINER_EREADER)
|
||||||
|
{
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
for (i = firstMonId; i < firstMonId + FRONTIER_PARTY_SIZE; i++)
|
||||||
|
CreateBattleTowerMon(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.ereaderTrainer.party[i - firstMonId]);
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (trainerId == TRAINER_FRONTIER_BRAIN)
|
||||||
|
{
|
||||||
|
CreateFrontierBrainPokemon();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
||||||
|
{
|
||||||
|
// Record mixed player.
|
||||||
|
for (j = 0, i = firstMonId; i < firstMonId + monCount; j++, i++)
|
||||||
|
{
|
||||||
|
if (gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].party[j].species != SPECIES_NONE
|
||||||
|
&& gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].party[j].level <= level)
|
||||||
|
{
|
||||||
|
CreateBattleTowerMon_HandleLevel(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].party[j], FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Apprentice.
|
||||||
|
for (i = firstMonId; i < firstMonId + FRONTIER_PARTY_SIZE; i++)
|
||||||
|
CreateApprenticeMon(&gEnemyParty[i], &gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE], i - firstMonId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regular battle frontier trainer.
|
||||||
|
// Attempt to fill the trainer's party with random Pokémon until 3 have been
|
||||||
|
// successfully chosen. The trainer's party may not have duplicate Pokémon species
|
||||||
|
// or duplicate held items.
|
||||||
|
for (bfMonCount = 0; monSet[bfMonCount] != 0xFFFF; bfMonCount++)
|
||||||
|
;
|
||||||
|
i = 0;
|
||||||
|
otID = Random32();
|
||||||
|
while (i != monCount)
|
||||||
|
{
|
||||||
|
u16 monId = monSet[Random() % bfMonCount];
|
||||||
|
|
||||||
|
// "High tier" Pokémon are only allowed on open level mode
|
||||||
|
// 20 is not a possible value for level here
|
||||||
|
if ((level == FRONTIER_MAX_LEVEL_50 || level == 20) && monId > FRONTIER_MONS_HIGH_TIER)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Ensure this Pokémon species isn't a duplicate.
|
||||||
|
for (j = 0; j < i + firstMonId; j++)
|
||||||
|
{
|
||||||
|
if (GetMonData(&gEnemyParty[j], MON_DATA_SPECIES, NULL) == gFacilityTrainerMons[monId].species)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j != i + firstMonId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Ensure this Pokemon's held item isn't a duplicate.
|
||||||
|
for (j = 0; j < i + firstMonId; j++)
|
||||||
|
{
|
||||||
|
if (GetMonData(&gEnemyParty[j], MON_DATA_HELD_ITEM, NULL) != ITEM_NONE
|
||||||
|
&& GetMonData(&gEnemyParty[j], MON_DATA_HELD_ITEM, NULL) == gFacilityTrainerMons[monId].heldItem)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j != i + firstMonId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Ensure this exact Pokémon index isn't a duplicate. This check doesn't seem necessary
|
||||||
|
// because the species and held items were already checked directly above.
|
||||||
|
for (j = 0; j < i; j++)
|
||||||
|
{
|
||||||
|
if (chosenMonIndices[j] == monId)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j != i)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
chosenMonIndices[i] = monId;
|
||||||
|
|
||||||
|
// Place the chosen Pokémon into the trainer's party.
|
||||||
|
CreateFacilityMon(&gFacilityTrainerMons[monId], level, fixedIV, otID, 0, &gEnemyParty[i + firstMonId]);
|
||||||
|
|
||||||
|
// The Pokémon was successfully added to the trainer's party, so it's safe to move on to
|
||||||
|
// the next party slot.
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateFacilityMon(const struct TrainerMon *fmon, u16 level, u8 fixedIV, u32 otID, u32 flags, struct Pokemon *dst)
|
||||||
|
{
|
||||||
|
u8 ball = (fmon->ball == 0xFF) ? Random() % POKEBALL_COUNT : fmon->ball;
|
||||||
|
u16 move;
|
||||||
|
u32 personality = 0, ability, friendship, j;
|
||||||
|
|
||||||
|
if (fmon->gender == TRAINER_MON_MALE)
|
||||||
|
{
|
||||||
|
personality = GeneratePersonalityForGender(MON_MALE, fmon->species);
|
||||||
|
}
|
||||||
|
else if (fmon->gender == TRAINER_MON_FEMALE)
|
||||||
|
{
|
||||||
|
personality = GeneratePersonalityForGender(MON_FEMALE, fmon->species);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModifyPersonalityForNature(&personality, fmon->nature);
|
||||||
|
CreateMon(dst, fmon->species, level, fixedIV, TRUE, personality, otID, OT_ID_PRESET);
|
||||||
|
|
||||||
|
friendship = MAX_FRIENDSHIP;
|
||||||
|
// Give the chosen Pokémon its specified moves.
|
||||||
|
for (j = 0; j < MAX_MON_MOVES; j++)
|
||||||
|
{
|
||||||
|
move = fmon->moves[j];
|
||||||
|
if (flags & FLAG_FRONTIER_MON_FACTORY && move == MOVE_RETURN)
|
||||||
|
move = MOVE_FRUSTRATION;
|
||||||
|
|
||||||
|
SetMonMoveSlot(dst, move, j);
|
||||||
|
if (GetMoveEffect(move) == EFFECT_FRUSTRATION)
|
||||||
|
friendship = 0; // Frustration is more powerful the lower the pokemon's friendship is.
|
||||||
|
}
|
||||||
|
|
||||||
|
SetMonData(dst, MON_DATA_FRIENDSHIP, &friendship);
|
||||||
|
SetMonData(dst, MON_DATA_HELD_ITEM, &fmon->heldItem);
|
||||||
|
|
||||||
|
// try to set ability. Otherwise, random of non-hidden as per vanilla
|
||||||
|
if (fmon->ability != ABILITY_NONE)
|
||||||
|
{
|
||||||
|
const struct SpeciesInfo *speciesInfo = &gSpeciesInfo[fmon->species];
|
||||||
|
u32 maxAbilities = ARRAY_COUNT(speciesInfo->abilities);
|
||||||
|
for (ability = 0; ability < maxAbilities; ++ability)
|
||||||
|
{
|
||||||
|
if (speciesInfo->abilities[ability] == fmon->ability)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ability >= maxAbilities)
|
||||||
|
ability = 0;
|
||||||
|
SetMonData(dst, MON_DATA_ABILITY_NUM, &ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fmon->ev != NULL)
|
||||||
|
{
|
||||||
|
SetMonData(dst, MON_DATA_HP_EV, &(fmon->ev[0]));
|
||||||
|
SetMonData(dst, MON_DATA_ATK_EV, &(fmon->ev[1]));
|
||||||
|
SetMonData(dst, MON_DATA_DEF_EV, &(fmon->ev[2]));
|
||||||
|
SetMonData(dst, MON_DATA_SPATK_EV, &(fmon->ev[3]));
|
||||||
|
SetMonData(dst, MON_DATA_SPDEF_EV, &(fmon->ev[4]));
|
||||||
|
SetMonData(dst, MON_DATA_SPEED_EV, &(fmon->ev[5]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fmon->iv)
|
||||||
|
SetMonData(dst, MON_DATA_IVS, &(fmon->iv));
|
||||||
|
|
||||||
|
if (fmon->isShiny)
|
||||||
|
{
|
||||||
|
u32 data = TRUE;
|
||||||
|
SetMonData(dst, MON_DATA_IS_SHINY, &data);
|
||||||
|
}
|
||||||
|
if (fmon->dynamaxLevel > 0)
|
||||||
|
{
|
||||||
|
u32 data = fmon->dynamaxLevel;
|
||||||
|
SetMonData(dst, MON_DATA_DYNAMAX_LEVEL, &data);
|
||||||
|
}
|
||||||
|
if (fmon->gigantamaxFactor)
|
||||||
|
{
|
||||||
|
u32 data = fmon->gigantamaxFactor;
|
||||||
|
SetMonData(dst, MON_DATA_GIGANTAMAX_FACTOR, &data);
|
||||||
|
}
|
||||||
|
if (fmon->teraType)
|
||||||
|
{
|
||||||
|
u32 data = fmon->teraType;
|
||||||
|
SetMonData(dst, MON_DATA_TERA_TYPE, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SetMonData(dst, MON_DATA_POKEBALL, &ball);
|
||||||
|
CalculateMonStats(dst);
|
||||||
|
}
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include "dma3.h"
|
#include "dma3.h"
|
||||||
#include "event_data.h"
|
#include "event_data.h"
|
||||||
#include "evolution_scene.h"
|
#include "evolution_scene.h"
|
||||||
|
#include "frontier_util.h"
|
||||||
#include "field_weather.h"
|
#include "field_weather.h"
|
||||||
#include "follower_npc.h"
|
#include "follower_npc.h"
|
||||||
#include "graphics.h"
|
#include "graphics.h"
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
#include "battle_controllers.h"
|
#include "battle_controllers.h"
|
||||||
#include "battle_message.h"
|
#include "battle_message.h"
|
||||||
#include "battle_setup.h"
|
#include "battle_setup.h"
|
||||||
#include "battle_tower.h"
|
#include "battle_special.h"
|
||||||
#include "battle_z_move.h"
|
#include "battle_z_move.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "event_data.h"
|
#include "event_data.h"
|
||||||
|
|
|
||||||
178
src/battle_partner.c
Normal file
178
src/battle_partner.c
Normal file
|
|
@ -0,0 +1,178 @@
|
||||||
|
#include "global.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "battle.h"
|
||||||
|
#include "battle_partner.h"
|
||||||
|
#include "battle_frontier.h"
|
||||||
|
#include "data.h"
|
||||||
|
#include "frontier_util.h"
|
||||||
|
#include "difficulty.h"
|
||||||
|
#include "string_util.h"
|
||||||
|
#include "text.h"
|
||||||
|
|
||||||
|
#include "constants/abilities.h"
|
||||||
|
#include "constants/battle_ai.h"
|
||||||
|
|
||||||
|
#include "data/partner_parties.h"
|
||||||
|
const struct Trainer gBattlePartners[DIFFICULTY_COUNT][PARTNER_COUNT] =
|
||||||
|
{
|
||||||
|
#include "data/battle_partners.h"
|
||||||
|
};
|
||||||
|
|
||||||
|
#define STEVEN_OTID 61226
|
||||||
|
|
||||||
|
void FillPartnerParty(u16 trainerId)
|
||||||
|
{
|
||||||
|
s32 i, j, k;
|
||||||
|
u32 firstIdPart = 0, secondIdPart = 0, thirdIdPart = 0;
|
||||||
|
u32 ivs, level, personality;
|
||||||
|
u16 monId;
|
||||||
|
u32 otID;
|
||||||
|
u8 trainerName[(PLAYER_NAME_LENGTH * 3) + 1];
|
||||||
|
s32 ball = -1;
|
||||||
|
enum DifficultyLevel difficulty = GetBattlePartnerDifficultyLevel(trainerId);
|
||||||
|
SetFacilityPtrsGetLevel();
|
||||||
|
|
||||||
|
if (trainerId > TRAINER_PARTNER(PARTNER_NONE))
|
||||||
|
{
|
||||||
|
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 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, 0, TRUE, personality, OT_ID_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 != ITEM_NONE)
|
||||||
|
{
|
||||||
|
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))].encounterMusic_gender >> 7;
|
||||||
|
SetMonData(&gPlayerParty[i + 3], MON_DATA_OT_GENDER, &j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (trainerId == TRAINER_EREADER)
|
||||||
|
{
|
||||||
|
// Scrapped, lol.
|
||||||
|
trainerName[0] = gGameLanguage;
|
||||||
|
}
|
||||||
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
||||||
|
{
|
||||||
|
level = SetFacilityPtrsGetLevel();
|
||||||
|
ivs = GetFrontierTrainerFixedIvs(trainerId);
|
||||||
|
otID = Random32();
|
||||||
|
for (i = 0; i < FRONTIER_MULTI_PARTY_SIZE; i++)
|
||||||
|
{
|
||||||
|
monId = gSaveBlock2Ptr->frontier.trainerIds[i + 18];
|
||||||
|
CreateFacilityMon(&gFacilityTrainerMons[monId], level, ivs, otID, 0, &gPlayerParty[MULTI_PARTY_SIZE + i]);
|
||||||
|
for (j = 0; j < PLAYER_NAME_LENGTH + 1; j++)
|
||||||
|
trainerName[j] = gFacilityTrainers[trainerId].trainerName[j];
|
||||||
|
SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_OT_NAME, &trainerName);
|
||||||
|
j = IsFrontierTrainerFemale(trainerId);
|
||||||
|
SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_OT_GENDER, &j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
||||||
|
{
|
||||||
|
trainerId -= TRAINER_RECORD_MIXING_FRIEND;
|
||||||
|
for (i = 0; i < FRONTIER_MULTI_PARTY_SIZE; i++)
|
||||||
|
{
|
||||||
|
struct EmeraldBattleTowerRecord *record = &gSaveBlock2Ptr->frontier.towerRecords[trainerId];
|
||||||
|
struct BattleTowerPokemon monData = record->party[gSaveBlock2Ptr->frontier.trainerIds[18 + i]];
|
||||||
|
StringCopy(trainerName, record->name);
|
||||||
|
if (record->language == LANGUAGE_JAPANESE)
|
||||||
|
{
|
||||||
|
if (monData.nickname[0] != EXT_CTRL_CODE_BEGIN || monData.nickname[1] != EXT_CTRL_CODE_JPN)
|
||||||
|
{
|
||||||
|
monData.nickname[5] = EOS;
|
||||||
|
ConvertInternationalString(monData.nickname, LANGUAGE_JAPANESE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (monData.nickname[0] == EXT_CTRL_CODE_BEGIN && monData.nickname[1] == EXT_CTRL_CODE_JPN)
|
||||||
|
trainerName[5] = EOS;
|
||||||
|
}
|
||||||
|
CreateBattleTowerMon_HandleLevel(&gPlayerParty[MULTI_PARTY_SIZE + i], &monData, TRUE);
|
||||||
|
SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_OT_NAME, trainerName);
|
||||||
|
j = IsFrontierTrainerFemale(trainerId + TRAINER_RECORD_MIXING_FRIEND);
|
||||||
|
SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_OT_GENDER, &j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
trainerId -= TRAINER_RECORD_MIXING_APPRENTICE;
|
||||||
|
for (i = 0; i < FRONTIER_MULTI_PARTY_SIZE; i++)
|
||||||
|
{
|
||||||
|
CreateApprenticeMon(&gPlayerParty[MULTI_PARTY_SIZE + i], &gSaveBlock2Ptr->apprentices[trainerId], gSaveBlock2Ptr->frontier.trainerIds[18 + i]);
|
||||||
|
j = IsFrontierTrainerFemale(trainerId + TRAINER_RECORD_MIXING_APPRENTICE);
|
||||||
|
SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_OT_GENDER, &j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
#include "field_weather.h"
|
#include "field_weather.h"
|
||||||
#include "battle_tower.h"
|
#include "battle_tower.h"
|
||||||
#include "gym_leader_rematch.h"
|
#include "gym_leader_rematch.h"
|
||||||
|
#include "battle_frontier.h"
|
||||||
#include "battle_pike.h"
|
#include "battle_pike.h"
|
||||||
#include "battle_pyramid.h"
|
#include "battle_pyramid.h"
|
||||||
#include "fldeff.h"
|
#include "fldeff.h"
|
||||||
|
|
@ -42,6 +43,7 @@
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "vs_seeker.h"
|
#include "vs_seeker.h"
|
||||||
#include "item.h"
|
#include "item.h"
|
||||||
|
#include "script.h"
|
||||||
#include "field_name_box.h"
|
#include "field_name_box.h"
|
||||||
#include "constants/battle_frontier.h"
|
#include "constants/battle_frontier.h"
|
||||||
#include "constants/battle_setup.h"
|
#include "constants/battle_setup.h"
|
||||||
|
|
@ -958,7 +960,7 @@ void ResetTrainerOpponentIds(void)
|
||||||
TRAINER_BATTLE_PARAM.opponentB = 0;
|
TRAINER_BATTLE_PARAM.opponentB = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void InitTrainerBattleVariables(void)
|
void InitTrainerBattleParameter(void)
|
||||||
{
|
{
|
||||||
memset(gTrainerBattleParameter.data, 0, sizeof(TrainerBattleParameter));
|
memset(gTrainerBattleParameter.data, 0, sizeof(TrainerBattleParameter));
|
||||||
sTrainerBattleEndScript = NULL;
|
sTrainerBattleEndScript = NULL;
|
||||||
|
|
@ -966,7 +968,7 @@ static void InitTrainerBattleVariables(void)
|
||||||
|
|
||||||
void TrainerBattleLoadArgs(const u8 *data)
|
void TrainerBattleLoadArgs(const u8 *data)
|
||||||
{
|
{
|
||||||
InitTrainerBattleVariables();
|
InitTrainerBattleParameter();
|
||||||
memcpy(gTrainerBattleParameter.data, data, sizeof(TrainerBattleParameter));
|
memcpy(gTrainerBattleParameter.data, data, sizeof(TrainerBattleParameter));
|
||||||
sTrainerBattleEndScript = (u8*)data + sizeof(TrainerBattleParameter);
|
sTrainerBattleEndScript = (u8*)data + sizeof(TrainerBattleParameter);
|
||||||
}
|
}
|
||||||
|
|
@ -1059,30 +1061,6 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data)
|
||||||
TRAINER_BATTLE_PARAM.opponentA = GetRematchTrainerId(TRAINER_BATTLE_PARAM.opponentA);
|
TRAINER_BATTLE_PARAM.opponentA = GetRematchTrainerId(TRAINER_BATTLE_PARAM.opponentA);
|
||||||
return EventScript_TryDoRematchBattle;
|
return EventScript_TryDoRematchBattle;
|
||||||
#endif //FREE_MATCH_CALL
|
#endif //FREE_MATCH_CALL
|
||||||
case TRAINER_BATTLE_PYRAMID:
|
|
||||||
if (gApproachingTrainerId == 0)
|
|
||||||
{
|
|
||||||
SetMapVarsToTrainerA();
|
|
||||||
TRAINER_BATTLE_PARAM.opponentA = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TRAINER_BATTLE_PARAM.opponentB = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked);
|
|
||||||
}
|
|
||||||
return EventScript_TryDoNormalTrainerBattle;
|
|
||||||
case TRAINER_BATTLE_SET_TRAINERS_FOR_MULTI_BATTLE:
|
|
||||||
return sTrainerBattleEndScript;
|
|
||||||
case TRAINER_BATTLE_HILL:
|
|
||||||
if (gApproachingTrainerId == 0)
|
|
||||||
{
|
|
||||||
SetMapVarsToTrainerA();
|
|
||||||
TRAINER_BATTLE_PARAM.opponentA = LocalIdToHillTrainerId(gSpecialVar_LastTalked);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TRAINER_BATTLE_PARAM.opponentB = LocalIdToHillTrainerId(gSpecialVar_LastTalked);
|
|
||||||
}
|
|
||||||
return EventScript_TryDoNormalTrainerBattle;
|
|
||||||
case TRAINER_BATTLE_TWO_TRAINERS_NO_INTRO:
|
case TRAINER_BATTLE_TWO_TRAINERS_NO_INTRO:
|
||||||
gNoOfApproachingTrainers = 2; // set TWO_OPPONENTS gBattleTypeFlags
|
gNoOfApproachingTrainers = 2; // set TWO_OPPONENTS gBattleTypeFlags
|
||||||
gApproachingTrainerId = 1; // prevent trainer approach
|
gApproachingTrainerId = 1; // prevent trainer approach
|
||||||
|
|
@ -1096,6 +1074,39 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const u8* BattleSetup_ConfigureFacilityTrainerBattle(u8 facility, const u8* scriptEndPtr)
|
||||||
|
{
|
||||||
|
sTrainerBattleEndScript = (u8*)scriptEndPtr;
|
||||||
|
|
||||||
|
switch (facility)
|
||||||
|
{
|
||||||
|
case FACILITY_BATTLE_PYRAMID:
|
||||||
|
if (gApproachingTrainerId == 0)
|
||||||
|
{
|
||||||
|
SetMapVarsToTrainerA();
|
||||||
|
TRAINER_BATTLE_PARAM.opponentA = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRAINER_BATTLE_PARAM.opponentB = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked);
|
||||||
|
}
|
||||||
|
return EventScript_TryDoNormalTrainerBattle;
|
||||||
|
case FACILITY_BATTLE_TRAINER_HILL:
|
||||||
|
if (gApproachingTrainerId == 0)
|
||||||
|
{
|
||||||
|
SetMapVarsToTrainerA();
|
||||||
|
TRAINER_BATTLE_PARAM.opponentA = LocalIdToHillTrainerId(gSpecialVar_LastTalked);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRAINER_BATTLE_PARAM.opponentB = LocalIdToHillTrainerId(gSpecialVar_LastTalked);
|
||||||
|
}
|
||||||
|
return EventScript_TryDoNormalTrainerBattle;
|
||||||
|
default:
|
||||||
|
return sTrainerBattleEndScript;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ConfigureAndSetUpOneTrainerBattle(u8 trainerObjEventId, const u8 *trainerScript)
|
void ConfigureAndSetUpOneTrainerBattle(u8 trainerObjEventId, const u8 *trainerScript)
|
||||||
{
|
{
|
||||||
gSelectedObjectEvent = trainerObjEventId;
|
gSelectedObjectEvent = trainerObjEventId;
|
||||||
|
|
@ -1960,3 +1971,15 @@ u16 CountBattledRematchTeams(u16 trainerId)
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetMultiTrainerBattle(struct ScriptContext *ctx)
|
||||||
|
{
|
||||||
|
InitTrainerBattleParameter();
|
||||||
|
|
||||||
|
TRAINER_BATTLE_PARAM.opponentA = ScriptReadHalfword(ctx);
|
||||||
|
TRAINER_BATTLE_PARAM.defeatTextA = (u8*)ScriptReadWord(ctx);
|
||||||
|
TRAINER_BATTLE_PARAM.opponentB = ScriptReadHalfword(ctx);
|
||||||
|
TRAINER_BATTLE_PARAM.defeatTextB = (u8*)ScriptReadWord(ctx);
|
||||||
|
gPartnerTrainerId = TRAINER_PARTNER(ScriptReadHalfword(ctx));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
||||||
277
src/battle_special.c
Normal file
277
src/battle_special.c
Normal file
|
|
@ -0,0 +1,277 @@
|
||||||
|
#include "global.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "battle_special.h"
|
||||||
|
#include "battle.h"
|
||||||
|
#include "battle_frontier.h"
|
||||||
|
#include "battle_partner.h"
|
||||||
|
#include "battle_setup.h"
|
||||||
|
#include "battle_tower.h"
|
||||||
|
#include "battle_transition.h"
|
||||||
|
#include "event_data.h"
|
||||||
|
#include "frontier_util.h"
|
||||||
|
#include "new_game.h"
|
||||||
|
#include "overworld.h"
|
||||||
|
#include "recorded_battle.h"
|
||||||
|
#include "string_util.h"
|
||||||
|
#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);
|
||||||
|
static void UNUSED FillEReaderTrainerWithPlayerData(void);
|
||||||
|
static void CopyEReaderTrainerFarewellMessage(void);
|
||||||
|
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
static void SetEReaderTrainerChecksum(struct BattleTowerEReaderTrainer *ereaderTrainer);
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
|
||||||
|
static void HandleSpecialTrainerBattleEnd(void)
|
||||||
|
{
|
||||||
|
s32 i;
|
||||||
|
|
||||||
|
RecordedBattle_SaveBattleOutcome();
|
||||||
|
switch (gBattleScripting.specialTrainerBattleType)
|
||||||
|
{
|
||||||
|
case SPECIAL_BATTLE_SECRET_BASE:
|
||||||
|
for (i = 0; i < PARTY_SIZE; i++)
|
||||||
|
{
|
||||||
|
u16 itemBefore = GetMonData(&gSaveBlock1Ptr->playerParty[i], MON_DATA_HELD_ITEM);
|
||||||
|
SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &itemBefore);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SPECIAL_BATTLE_EREADER:
|
||||||
|
CopyEReaderTrainerFarewellMessage();
|
||||||
|
break;
|
||||||
|
case SPECIAL_BATTLE_MULTI:
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES))
|
||||||
|
gSaveBlock1Ptr->playerParty[i] = gPlayerParty[i];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Task_StartBattleAfterTransition(u8 taskId)
|
||||||
|
{
|
||||||
|
if (IsBattleTransitionDone() == TRUE)
|
||||||
|
{
|
||||||
|
gMain.savedCallback = HandleSpecialTrainerBattleEnd;
|
||||||
|
SetMainCallback2(CB2_InitBattle);
|
||||||
|
DestroyTask(taskId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoSpecialTrainerBattle(void)
|
||||||
|
{
|
||||||
|
s32 i;
|
||||||
|
|
||||||
|
gBattleScripting.specialTrainerBattleType = gSpecialVar_0x8004;
|
||||||
|
switch (gSpecialVar_0x8004)
|
||||||
|
{
|
||||||
|
case SPECIAL_BATTLE_SECRET_BASE:
|
||||||
|
for (i = 0; i < PARTY_SIZE; i++)
|
||||||
|
{
|
||||||
|
u16 itemBefore = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
|
||||||
|
SetMonData(&gSaveBlock1Ptr->playerParty[i], MON_DATA_HELD_ITEM, &itemBefore);
|
||||||
|
}
|
||||||
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
||||||
|
PlayMapChosenOrBattleBGM(0);
|
||||||
|
BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_SECRET_BASE));
|
||||||
|
break;
|
||||||
|
case SPECIAL_BATTLE_EREADER:
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
ZeroEnemyPartyMons();
|
||||||
|
for (i = 0; i < (int)ARRAY_COUNT(gSaveBlock2Ptr->frontier.ereaderTrainer.party); i++)
|
||||||
|
CreateBattleTowerMon(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.ereaderTrainer.party[i]);
|
||||||
|
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_EREADER_TRAINER;
|
||||||
|
TRAINER_BATTLE_PARAM.opponentA = 0;
|
||||||
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
||||||
|
PlayMapChosenOrBattleBGM(0);
|
||||||
|
BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_E_READER));
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetEReaderTrainerGfxId(void)
|
||||||
|
{
|
||||||
|
SetBattleFacilityTrainerGfxId(TRAINER_EREADER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a leftover debugging function that is used to populate the E-Reader
|
||||||
|
// trainer with the player's current data.
|
||||||
|
static void UNUSED FillEReaderTrainerWithPlayerData(void)
|
||||||
|
{
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
struct BattleTowerEReaderTrainer *ereaderTrainer = &gSaveBlock2Ptr->frontier.ereaderTrainer;
|
||||||
|
s32 i, j;
|
||||||
|
|
||||||
|
if (gSaveBlock2Ptr->playerGender != MALE)
|
||||||
|
{
|
||||||
|
ereaderTrainer->facilityClass = gTowerFemaleFacilityClasses[(gSaveBlock2Ptr->playerTrainerId[0] + gSaveBlock2Ptr->playerTrainerId[1]
|
||||||
|
+ gSaveBlock2Ptr->playerTrainerId[2] + gSaveBlock2Ptr->playerTrainerId[3]) % ARRAY_COUNT(gTowerFemaleFacilityClasses)];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ereaderTrainer->facilityClass = gTowerMaleFacilityClasses[(gSaveBlock2Ptr->playerTrainerId[0] + gSaveBlock2Ptr->playerTrainerId[1]
|
||||||
|
+ gSaveBlock2Ptr->playerTrainerId[2] + gSaveBlock2Ptr->playerTrainerId[3]) % ARRAY_COUNT(gTowerMaleFacilityClasses)];
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyTrainerId(ereaderTrainer->trainerId, gSaveBlock2Ptr->playerTrainerId);
|
||||||
|
StringCopy_PlayerName(ereaderTrainer->name, gSaveBlock2Ptr->playerName);
|
||||||
|
|
||||||
|
ereaderTrainer->winStreak = 1;
|
||||||
|
|
||||||
|
j = 7;
|
||||||
|
for (i = 0; i < EASY_CHAT_BATTLE_WORDS_COUNT; i++)
|
||||||
|
{
|
||||||
|
ereaderTrainer->greeting[i] = gSaveBlock1Ptr->easyChatBattleStart[i];
|
||||||
|
ereaderTrainer->farewellPlayerLost[i] = j;
|
||||||
|
ereaderTrainer->farewellPlayerWon[i] = j + 6;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < (int)ARRAY_COUNT(ereaderTrainer->party); i++)
|
||||||
|
ConvertPokemonToBattleTowerPokemon(&gPlayerParty[i], &ereaderTrainer->party[i]);
|
||||||
|
|
||||||
|
SetEReaderTrainerChecksum(ereaderTrainer);
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 GetEreaderTrainerFrontSpriteId(void)
|
||||||
|
{
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
return gFacilityClassToPicIndex[gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass];
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TrainerClassID GetEreaderTrainerClassId(void)
|
||||||
|
{
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
return gFacilityClassToTrainerClass[gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass];
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetEreaderTrainerName(u8 *dst)
|
||||||
|
{
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
s32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
dst[i] = gSaveBlock2Ptr->frontier.ereaderTrainer.name[i];
|
||||||
|
|
||||||
|
dst[i] = EOS;
|
||||||
|
#else
|
||||||
|
dst[0] = EOS;
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if the saved E-Reader trainer is valid.
|
||||||
|
void ValidateEReaderTrainer(void)
|
||||||
|
{
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
u32 i;
|
||||||
|
u32 checksum;
|
||||||
|
struct BattleTowerEReaderTrainer *ereaderTrainer;
|
||||||
|
|
||||||
|
gSpecialVar_Result = FALSE;
|
||||||
|
ereaderTrainer = &gSaveBlock2Ptr->frontier.ereaderTrainer;
|
||||||
|
|
||||||
|
checksum = 0;
|
||||||
|
for (i = 0; i < (sizeof(struct BattleTowerEReaderTrainer) - 4) / 4; i++) // - 4, because of the last field being the checksum itself.
|
||||||
|
checksum |= ((u32 *)ereaderTrainer)[i];
|
||||||
|
|
||||||
|
if (checksum == 0)
|
||||||
|
{
|
||||||
|
gSpecialVar_Result = TRUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
checksum = 0;
|
||||||
|
for (i = 0; i < (sizeof(struct BattleTowerEReaderTrainer) - 4) / 4; i++) // - 4, because of the last field being the checksum itself.
|
||||||
|
checksum += ((u32 *)ereaderTrainer)[i];
|
||||||
|
|
||||||
|
if (gSaveBlock2Ptr->frontier.ereaderTrainer.checksum != checksum)
|
||||||
|
{
|
||||||
|
ClearEReaderTrainer(&gSaveBlock2Ptr->frontier.ereaderTrainer);
|
||||||
|
gSpecialVar_Result = TRUE;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
gSpecialVar_Result = FALSE;
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
}
|
||||||
|
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
static void SetEReaderTrainerChecksum(struct BattleTowerEReaderTrainer *ereaderTrainer)
|
||||||
|
{
|
||||||
|
s32 i;
|
||||||
|
|
||||||
|
ereaderTrainer->checksum = 0;
|
||||||
|
for (i = 0; i < (sizeof(struct BattleTowerEReaderTrainer) - 4) / 4; i++) // - 4, because of the last field being the checksum itself.
|
||||||
|
ereaderTrainer->checksum += ((u32 *)ereaderTrainer)[i];
|
||||||
|
}
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
|
||||||
|
void ClearEReaderTrainer(struct BattleTowerEReaderTrainer *ereaderTrainer)
|
||||||
|
{
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < (sizeof(struct BattleTowerEReaderTrainer)) / 4; i++)
|
||||||
|
((u32 *)ereaderTrainer)[i] = 0;
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
}
|
||||||
|
|
||||||
|
void CopyEReaderTrainerGreeting(void)
|
||||||
|
{
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
FrontierSpeechToString(gSaveBlock2Ptr->frontier.ereaderTrainer.greeting);
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CopyEReaderTrainerFarewellMessage(void)
|
||||||
|
{
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
if (gBattleOutcome == B_OUTCOME_DREW)
|
||||||
|
gStringVar4[0] = EOS;
|
||||||
|
else if (gBattleOutcome == B_OUTCOME_WON)
|
||||||
|
FrontierSpeechToString(gSaveBlock2Ptr->frontier.ereaderTrainer.farewellPlayerWon);
|
||||||
|
else
|
||||||
|
FrontierSpeechToString(gSaveBlock2Ptr->frontier.ereaderTrainer.farewellPlayerLost);
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
}
|
||||||
1456
src/battle_tower.c
1456
src/battle_tower.c
File diff suppressed because it is too large
Load Diff
|
|
@ -2,7 +2,7 @@
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "malloc.h"
|
#include "malloc.h"
|
||||||
#include "battle.h"
|
#include "battle.h"
|
||||||
#include "battle_tower.h"
|
#include "battle_special.h"
|
||||||
#include "cable_club.h"
|
#include "cable_club.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "decoration.h"
|
#include "decoration.h"
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include "follower_npc.h"
|
#include "follower_npc.h"
|
||||||
#include "follower_npc_alternate_sprites.h"
|
#include "follower_npc_alternate_sprites.h"
|
||||||
#include "battle.h"
|
#include "battle.h"
|
||||||
|
#include "battle_partner.h"
|
||||||
#include "battle_setup.h"
|
#include "battle_setup.h"
|
||||||
#include "battle_tower.h"
|
#include "battle_tower.h"
|
||||||
#include "bike.h"
|
#include "bike.h"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "frontier_util.h"
|
#include "frontier_util.h"
|
||||||
|
#include "easy_chat.h"
|
||||||
#include "event_data.h"
|
#include "event_data.h"
|
||||||
#include "battle_setup.h"
|
#include "battle_setup.h"
|
||||||
#include "overworld.h"
|
#include "overworld.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
|
#include "battle_frontier.h"
|
||||||
|
#include "battle_special.h"
|
||||||
#include "battle_tower.h"
|
#include "battle_tower.h"
|
||||||
#include "field_specials.h"
|
#include "field_specials.h"
|
||||||
#include "battle.h"
|
#include "battle.h"
|
||||||
|
|
@ -29,6 +32,7 @@
|
||||||
#include "load_save.h"
|
#include "load_save.h"
|
||||||
#include "battle_dome.h"
|
#include "battle_dome.h"
|
||||||
#include "constants/battle_frontier.h"
|
#include "constants/battle_frontier.h"
|
||||||
|
#include "constants/battle_frontier_mons.h"
|
||||||
#include "constants/battle_move_effects.h"
|
#include "constants/battle_move_effects.h"
|
||||||
#include "constants/battle_pike.h"
|
#include "constants/battle_pike.h"
|
||||||
#include "constants/frontier_util.h"
|
#include "constants/frontier_util.h"
|
||||||
|
|
@ -788,6 +792,31 @@ static const u8 *const sHallFacilityToRecordsText[] =
|
||||||
[RANKING_HALL_TOWER_LINK] = gText_FrontierFacilityWinStreak,
|
[RANKING_HALL_TOWER_LINK] = gText_FrontierFacilityWinStreak,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Trainer ID ranges for possible frontier trainers to encounter on particular challenges
|
||||||
|
// Trainers are scaled by difficulty, so higher trainer IDs have better teams
|
||||||
|
static const u16 sFrontierTrainerIdRanges[][2] =
|
||||||
|
{
|
||||||
|
{FRONTIER_TRAINER_BRADY, FRONTIER_TRAINER_JILL}, // 0 - 99
|
||||||
|
{FRONTIER_TRAINER_TREVIN, FRONTIER_TRAINER_CHLOE}, // 80 - 119
|
||||||
|
{FRONTIER_TRAINER_ERIK, FRONTIER_TRAINER_SOFIA}, // 100 - 139
|
||||||
|
{FRONTIER_TRAINER_NORTON, FRONTIER_TRAINER_JAZLYN}, // 120 - 159
|
||||||
|
{FRONTIER_TRAINER_BRADEN, FRONTIER_TRAINER_ALISON}, // 140 - 179
|
||||||
|
{FRONTIER_TRAINER_ZACHERY, FRONTIER_TRAINER_LAMAR}, // 160 - 199
|
||||||
|
{FRONTIER_TRAINER_HANK, FRONTIER_TRAINER_TESS}, // 180 - 219
|
||||||
|
{FRONTIER_TRAINER_JAXON, FRONTIER_TRAINER_GRETEL}, // 200 - 299
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u16 sFrontierTrainerIdRangesHard[][2] =
|
||||||
|
{
|
||||||
|
{FRONTIER_TRAINER_ERIK, FRONTIER_TRAINER_CHLOE}, // 100 - 119
|
||||||
|
{FRONTIER_TRAINER_NORTON, FRONTIER_TRAINER_SOFIA}, // 120 - 139
|
||||||
|
{FRONTIER_TRAINER_BRADEN, FRONTIER_TRAINER_JAZLYN}, // 140 - 159
|
||||||
|
{FRONTIER_TRAINER_ZACHERY, FRONTIER_TRAINER_ALISON}, // 160 - 179
|
||||||
|
{FRONTIER_TRAINER_HANK, FRONTIER_TRAINER_LAMAR}, // 180 - 199
|
||||||
|
{FRONTIER_TRAINER_JAXON, FRONTIER_TRAINER_TESS}, // 200 - 219
|
||||||
|
{FRONTIER_TRAINER_LEON, FRONTIER_TRAINER_RAUL}, // 220 - 239
|
||||||
|
{FRONTIER_TRAINER_JAXON, FRONTIER_TRAINER_GRETEL}, // 200 - 299
|
||||||
|
};
|
||||||
|
|
||||||
#define BANNED_SPECIES_SHOWN 6
|
#define BANNED_SPECIES_SHOWN 6
|
||||||
|
|
||||||
|
|
@ -2715,6 +2744,602 @@ void ClearEnemyPartyAfterChallenge()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool8 IsFrontierTrainerFemale(u16 trainerId)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
u8 facilityClass;
|
||||||
|
|
||||||
|
SetFacilityPtrsGetLevel();
|
||||||
|
if (trainerId == TRAINER_EREADER)
|
||||||
|
{
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
facilityClass = gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass;
|
||||||
|
#else
|
||||||
|
facilityClass = 0;
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
}
|
||||||
|
else if (trainerId == TRAINER_FRONTIER_BRAIN)
|
||||||
|
{
|
||||||
|
return IsFrontierBrainFemale();
|
||||||
|
}
|
||||||
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
||||||
|
{
|
||||||
|
facilityClass = gFacilityTrainers[trainerId].facilityClass;
|
||||||
|
}
|
||||||
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
||||||
|
{
|
||||||
|
facilityClass = gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
facilityClass = gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search female classes.
|
||||||
|
for (i = 0; i < ARRAY_COUNT(gTowerFemaleFacilityClasses); i++)
|
||||||
|
{
|
||||||
|
if (gTowerFemaleFacilityClasses[i] == facilityClass)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i != ARRAY_COUNT(gTowerFemaleFacilityClasses))
|
||||||
|
return TRUE;
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frontier Trainer parties are roughly scaled in difficulty with higher trainer IDs, so scale IVs as well
|
||||||
|
// Duplicated in Battle Dome as GetDomeTrainerMonIvs
|
||||||
|
u8 GetFrontierTrainerFixedIvs(u16 trainerId)
|
||||||
|
{
|
||||||
|
u8 fixedIv;
|
||||||
|
|
||||||
|
if (trainerId <= FRONTIER_TRAINER_JILL) // 0 - 99
|
||||||
|
fixedIv = 3;
|
||||||
|
else if (trainerId <= FRONTIER_TRAINER_CHLOE) // 100 - 119
|
||||||
|
fixedIv = 6;
|
||||||
|
else if (trainerId <= FRONTIER_TRAINER_SOFIA) // 120 - 139
|
||||||
|
fixedIv = 9;
|
||||||
|
else if (trainerId <= FRONTIER_TRAINER_JAZLYN) // 140 - 159
|
||||||
|
fixedIv = 12;
|
||||||
|
else if (trainerId <= FRONTIER_TRAINER_ALISON) // 160 - 179
|
||||||
|
fixedIv = 15;
|
||||||
|
else if (trainerId <= FRONTIER_TRAINER_LAMAR) // 180 - 199
|
||||||
|
fixedIv = 18;
|
||||||
|
else if (trainerId <= FRONTIER_TRAINER_TESS) // 200 - 219
|
||||||
|
fixedIv = 21;
|
||||||
|
else // 220+ (- 299)
|
||||||
|
fixedIv = MAX_PER_STAT_IVS;
|
||||||
|
|
||||||
|
return fixedIv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
u16 GetRandomScaledFrontierTrainerId(u8 challengeNum, u8 battleNum)
|
||||||
|
{
|
||||||
|
u16 trainerId;
|
||||||
|
|
||||||
|
if (challengeNum <= 7)
|
||||||
|
{
|
||||||
|
if (battleNum == FRONTIER_STAGES_PER_CHALLENGE - 1)
|
||||||
|
{
|
||||||
|
// The last battle in each challenge has a jump in difficulty, pulls from a table with higher ranges
|
||||||
|
trainerId = (sFrontierTrainerIdRangesHard[challengeNum][1] - sFrontierTrainerIdRangesHard[challengeNum][0]) + 1;
|
||||||
|
trainerId = sFrontierTrainerIdRangesHard[challengeNum][0] + (Random() % trainerId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
trainerId = (sFrontierTrainerIdRanges[challengeNum][1] - sFrontierTrainerIdRanges[challengeNum][0]) + 1;
|
||||||
|
trainerId = sFrontierTrainerIdRanges[challengeNum][0] + (Random() % trainerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// After challenge 7, trainer IDs always come from the last, hardest range, which is the same for both trainer ID tables
|
||||||
|
trainerId = (sFrontierTrainerIdRanges[7][1] - sFrontierTrainerIdRanges[7][0]) + 1;
|
||||||
|
trainerId = sFrontierTrainerIdRanges[7][0] + (Random() % trainerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return trainerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void UNUSED GetRandomScaledFrontierTrainerIdRange(u8 challengeNum, u8 battleNum, u16 *trainerIdPtr, u8 *rangePtr)
|
||||||
|
{
|
||||||
|
u16 trainerId, range;
|
||||||
|
|
||||||
|
if (challengeNum <= 7)
|
||||||
|
{
|
||||||
|
if (battleNum == FRONTIER_STAGES_PER_CHALLENGE - 1)
|
||||||
|
{
|
||||||
|
// The last battle in each challenge has a jump in difficulty, pulls from a table with higher ranges
|
||||||
|
range = (sFrontierTrainerIdRangesHard[challengeNum][1] - sFrontierTrainerIdRangesHard[challengeNum][0]) + 1;
|
||||||
|
trainerId = sFrontierTrainerIdRangesHard[challengeNum][0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
range = (sFrontierTrainerIdRanges[challengeNum][1] - sFrontierTrainerIdRanges[challengeNum][0]) + 1;
|
||||||
|
trainerId = sFrontierTrainerIdRanges[challengeNum][0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// After challenge 7, trainer IDs always come from the last, hardest range, which is the same for both trainer ID tables
|
||||||
|
range = (sFrontierTrainerIdRanges[7][1] - sFrontierTrainerIdRanges[7][0]) + 1;
|
||||||
|
trainerId = sFrontierTrainerIdRanges[7][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
*trainerIdPtr = trainerId;
|
||||||
|
*rangePtr = range;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetBattleFacilityTrainerGfxId(u16 trainerId, u8 tempVarId)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
u8 facilityClass;
|
||||||
|
u8 trainerObjectGfxId;
|
||||||
|
|
||||||
|
SetFacilityPtrsGetLevel();
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
if (trainerId == TRAINER_EREADER)
|
||||||
|
{
|
||||||
|
facilityClass = gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass;
|
||||||
|
}
|
||||||
|
else if (trainerId == TRAINER_FRONTIER_BRAIN)
|
||||||
|
#else
|
||||||
|
if (trainerId == TRAINER_FRONTIER_BRAIN)
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
{
|
||||||
|
SetFrontierBrainObjEventGfx_2();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
||||||
|
{
|
||||||
|
facilityClass = gFacilityTrainers[trainerId].facilityClass;
|
||||||
|
}
|
||||||
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
||||||
|
{
|
||||||
|
facilityClass = gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
facilityClass = gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search male classes.
|
||||||
|
for (i = 0; i < ARRAY_COUNT(gTowerMaleFacilityClasses); i++)
|
||||||
|
{
|
||||||
|
if (gTowerMaleFacilityClasses[i] == facilityClass)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i != ARRAY_COUNT(gTowerMaleFacilityClasses))
|
||||||
|
{
|
||||||
|
trainerObjectGfxId = gTowerMaleTrainerGfxIds[i];
|
||||||
|
switch (tempVarId)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
VarSet(VAR_OBJ_GFX_ID_0, trainerObjectGfxId);
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
VarSet(VAR_OBJ_GFX_ID_1, trainerObjectGfxId);
|
||||||
|
return;
|
||||||
|
case 15:
|
||||||
|
VarSet(VAR_OBJ_GFX_ID_E, trainerObjectGfxId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search female classes.
|
||||||
|
for (i = 0; i < ARRAY_COUNT(gTowerFemaleFacilityClasses); i++)
|
||||||
|
{
|
||||||
|
if (gTowerFemaleFacilityClasses[i] == facilityClass)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i != ARRAY_COUNT(gTowerFemaleFacilityClasses))
|
||||||
|
{
|
||||||
|
trainerObjectGfxId = gTowerFemaleTrainerGfxIds[i];
|
||||||
|
switch (tempVarId)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
VarSet(VAR_OBJ_GFX_ID_0, trainerObjectGfxId);
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
VarSet(VAR_OBJ_GFX_ID_1, trainerObjectGfxId);
|
||||||
|
return;
|
||||||
|
case 15:
|
||||||
|
VarSet(VAR_OBJ_GFX_ID_E, trainerObjectGfxId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (tempVarId)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
VarSet(VAR_OBJ_GFX_ID_0, OBJ_EVENT_GFX_BOY_1);
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
VarSet(VAR_OBJ_GFX_ID_1, OBJ_EVENT_GFX_BOY_1);
|
||||||
|
return;
|
||||||
|
case 15:
|
||||||
|
VarSet(VAR_OBJ_GFX_ID_E, OBJ_EVENT_GFX_BOY_1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 GetBattleFacilityTrainerGfxId(u16 trainerId)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
u8 facilityClass;
|
||||||
|
u16 trainerObjectGfxId;
|
||||||
|
|
||||||
|
SetFacilityPtrsGetLevel();
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
if (trainerId == TRAINER_EREADER)
|
||||||
|
{
|
||||||
|
facilityClass = gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass;
|
||||||
|
}
|
||||||
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
||||||
|
#else
|
||||||
|
if (trainerId < FRONTIER_TRAINERS_COUNT)
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
{
|
||||||
|
facilityClass = gFacilityTrainers[trainerId].facilityClass;
|
||||||
|
}
|
||||||
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
||||||
|
{
|
||||||
|
facilityClass = gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
facilityClass = gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search male classes.
|
||||||
|
for (i = 0; i < ARRAY_COUNT(gTowerMaleFacilityClasses); i++)
|
||||||
|
{
|
||||||
|
if (gTowerMaleFacilityClasses[i] == facilityClass)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i != ARRAY_COUNT(gTowerMaleFacilityClasses))
|
||||||
|
{
|
||||||
|
trainerObjectGfxId = gTowerMaleTrainerGfxIds[i];
|
||||||
|
return trainerObjectGfxId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search female classes.
|
||||||
|
for (i = 0; i < ARRAY_COUNT(gTowerFemaleFacilityClasses); i++)
|
||||||
|
{
|
||||||
|
if (gTowerFemaleFacilityClasses[i] == facilityClass)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i != ARRAY_COUNT(gTowerFemaleFacilityClasses))
|
||||||
|
{
|
||||||
|
trainerObjectGfxId = gTowerFemaleTrainerGfxIds[i];
|
||||||
|
return trainerObjectGfxId;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return OBJ_EVENT_GFX_BOY_1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 GetFrontierTrainerFrontSpriteId(u16 trainerId)
|
||||||
|
{
|
||||||
|
SetFacilityPtrsGetLevel();
|
||||||
|
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
if (trainerId == TRAINER_EREADER)
|
||||||
|
{
|
||||||
|
return gFacilityClassToPicIndex[gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass];
|
||||||
|
}
|
||||||
|
else if (trainerId == TRAINER_FRONTIER_BRAIN)
|
||||||
|
#else
|
||||||
|
if (trainerId == TRAINER_FRONTIER_BRAIN)
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
{
|
||||||
|
return GetFrontierBrainTrainerPicIndex();
|
||||||
|
}
|
||||||
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
||||||
|
{
|
||||||
|
return gFacilityClassToPicIndex[gFacilityTrainers[trainerId].facilityClass];
|
||||||
|
}
|
||||||
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
||||||
|
{
|
||||||
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
||||||
|
return gFacilityClassToPicIndex[GetRecordedBattleRecordMixFriendClass()];
|
||||||
|
else
|
||||||
|
return gFacilityClassToPicIndex[gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
||||||
|
return gFacilityClassToPicIndex[gApprentices[GetRecordedBattleApprenticeId()].facilityClass];
|
||||||
|
else
|
||||||
|
return gFacilityClassToPicIndex[gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TrainerClassID GetFrontierOpponentClass(u16 trainerId)
|
||||||
|
{
|
||||||
|
u8 trainerClass = 0;
|
||||||
|
enum DifficultyLevel difficulty = GetBattlePartnerDifficultyLevel(trainerId);
|
||||||
|
SetFacilityPtrsGetLevel();
|
||||||
|
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
if (trainerId == TRAINER_EREADER)
|
||||||
|
{
|
||||||
|
trainerClass = gFacilityClassToTrainerClass[gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass];
|
||||||
|
}
|
||||||
|
else if (trainerId == TRAINER_FRONTIER_BRAIN)
|
||||||
|
#else
|
||||||
|
if (trainerId == TRAINER_FRONTIER_BRAIN)
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
{
|
||||||
|
return GetFrontierBrainTrainerClass();
|
||||||
|
}
|
||||||
|
else if (trainerId > TRAINER_PARTNER(PARTNER_NONE))
|
||||||
|
{
|
||||||
|
trainerClass = gBattlePartners[difficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerClass;
|
||||||
|
}
|
||||||
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
||||||
|
{
|
||||||
|
trainerClass = gFacilityClassToTrainerClass[gFacilityTrainers[trainerId].facilityClass];
|
||||||
|
}
|
||||||
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
||||||
|
{
|
||||||
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
||||||
|
{
|
||||||
|
trainerClass = gFacilityClassToTrainerClass[GetRecordedBattleRecordMixFriendClass()];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
trainerClass = gFacilityClassToTrainerClass[gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
||||||
|
{
|
||||||
|
trainerClass = gFacilityClassToTrainerClass[gApprentices[GetRecordedBattleApprenticeId()].facilityClass];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
trainerClass = gFacilityClassToTrainerClass[gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return trainerClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 GetFrontierTrainerFacilityClass(u16 trainerId)
|
||||||
|
{
|
||||||
|
u8 facilityClass;
|
||||||
|
SetFacilityPtrsGetLevel();
|
||||||
|
|
||||||
|
if (trainerId == TRAINER_EREADER)
|
||||||
|
{
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
facilityClass = gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass;
|
||||||
|
#else
|
||||||
|
facilityClass = 0;
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
}
|
||||||
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
||||||
|
{
|
||||||
|
facilityClass = gFacilityTrainers[trainerId].facilityClass;
|
||||||
|
}
|
||||||
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
||||||
|
{
|
||||||
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
||||||
|
facilityClass = GetRecordedBattleRecordMixFriendClass();
|
||||||
|
else
|
||||||
|
facilityClass = gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
||||||
|
facilityClass = gApprentices[GetRecordedBattleApprenticeId()].facilityClass;
|
||||||
|
else
|
||||||
|
facilityClass = gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
return facilityClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetFrontierTrainerName(u8 *dst, u16 trainerId)
|
||||||
|
{
|
||||||
|
s32 i = 0;
|
||||||
|
enum DifficultyLevel difficulty = GetBattlePartnerDifficultyLevel(trainerId);
|
||||||
|
SetFacilityPtrsGetLevel();
|
||||||
|
|
||||||
|
if (trainerId == TRAINER_EREADER)
|
||||||
|
{
|
||||||
|
#if FREE_BATTLE_TOWER_E_READER == FALSE
|
||||||
|
for (i = 0; i < PLAYER_NAME_LENGTH; i++)
|
||||||
|
dst[i] = gSaveBlock2Ptr->frontier.ereaderTrainer.name[i];
|
||||||
|
#endif //FREE_BATTLE_TOWER_E_READER
|
||||||
|
}
|
||||||
|
else if (trainerId == TRAINER_FRONTIER_BRAIN)
|
||||||
|
{
|
||||||
|
CopyFrontierBrainTrainerName(dst);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (trainerId > TRAINER_PARTNER(PARTNER_NONE))
|
||||||
|
{
|
||||||
|
for (i = 0; gBattlePartners[difficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerName[i] != EOS; i++)
|
||||||
|
dst[i] = gBattlePartners[difficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerName[i];
|
||||||
|
}
|
||||||
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
||||||
|
{
|
||||||
|
for (i = 0; i < PLAYER_NAME_LENGTH; i++)
|
||||||
|
dst[i] = gFacilityTrainers[trainerId].trainerName[i];
|
||||||
|
}
|
||||||
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
||||||
|
{
|
||||||
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
||||||
|
{
|
||||||
|
GetRecordedBattleRecordMixFriendName(dst);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct EmeraldBattleTowerRecord *record = &gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND];
|
||||||
|
TVShowConvertInternationalString(dst, record->name, record->language);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u8 id, language;
|
||||||
|
|
||||||
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
||||||
|
{
|
||||||
|
id = GetRecordedBattleApprenticeId();
|
||||||
|
language = GetRecordedBattleApprenticeLanguage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct Apprentice *apprentice = &gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE];
|
||||||
|
id = apprentice->id;
|
||||||
|
language = apprentice->language;
|
||||||
|
}
|
||||||
|
TVShowConvertInternationalString(dst, GetApprenticeNameInLanguage(id, language), language);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst[i] = EOS;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 GetRandomFrontierMonFromSet(u16 trainerId)
|
||||||
|
{
|
||||||
|
u8 level = SetFacilityPtrsGetLevel();
|
||||||
|
const u16 *monSet = gFacilityTrainers[trainerId].monSet;
|
||||||
|
u8 numMons = 0;
|
||||||
|
u32 monId = monSet[numMons];
|
||||||
|
|
||||||
|
while (monId != 0xFFFF)
|
||||||
|
{
|
||||||
|
numMons++;
|
||||||
|
monId = monSet[numMons];
|
||||||
|
if (monId == 0xFFFF)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// "High tier" Pokémon are only allowed on open level mode
|
||||||
|
// 20 is not a possible value for level here
|
||||||
|
monId = monSet[Random() % numMons];
|
||||||
|
} while((level == FRONTIER_MAX_LEVEL_50 || level == 20) && monId > FRONTIER_MONS_HIGH_TIER);
|
||||||
|
|
||||||
|
return monId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontierSpeechToString(const u16 *words)
|
||||||
|
{
|
||||||
|
ConvertEasyChatWordsToString(gStringVar4, words, 3, 2);
|
||||||
|
if (GetStringWidth(FONT_NORMAL, gStringVar4, -1) > 204u)
|
||||||
|
{
|
||||||
|
s32 i = 0;
|
||||||
|
|
||||||
|
ConvertEasyChatWordsToString(gStringVar4, words, 2, 3);
|
||||||
|
while (gStringVar4[i++] != CHAR_NEWLINE)
|
||||||
|
;
|
||||||
|
while (gStringVar4[i] != CHAR_NEWLINE)
|
||||||
|
i++;
|
||||||
|
|
||||||
|
gStringVar4[i] = CHAR_PROMPT_SCROLL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 SetFacilityPtrsGetLevel(void)
|
||||||
|
{
|
||||||
|
if (gSaveBlock2Ptr->frontier.lvlMode == FRONTIER_LVL_TENT)
|
||||||
|
{
|
||||||
|
return SetTentPtrsGetLevel();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gFacilityTrainers = gBattleFrontierTrainers;
|
||||||
|
gFacilityTrainerMons = gBattleFrontierMons;
|
||||||
|
return GetFrontierEnemyMonLevel(gSaveBlock2Ptr->frontier.lvlMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 GetFrontierEnemyMonLevel(u8 lvlMode)
|
||||||
|
{
|
||||||
|
u8 level;
|
||||||
|
|
||||||
|
switch (lvlMode)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case FRONTIER_LVL_50:
|
||||||
|
level = FRONTIER_MAX_LEVEL_50;
|
||||||
|
break;
|
||||||
|
case FRONTIER_LVL_OPEN:
|
||||||
|
level = GetHighestLevelInPlayerParty();
|
||||||
|
if (level < FRONTIER_MIN_LEVEL_OPEN)
|
||||||
|
level = FRONTIER_MIN_LEVEL_OPEN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 GetHighestLevelInPlayerParty(void)
|
||||||
|
{
|
||||||
|
s32 highestLevel = 0;
|
||||||
|
s32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < PARTY_SIZE; i++)
|
||||||
|
{
|
||||||
|
if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL)
|
||||||
|
&& GetMonData(&gPlayerParty[i], MON_DATA_SPECIES_OR_EGG, NULL) != SPECIES_EGG)
|
||||||
|
{
|
||||||
|
s32 level = GetMonData(&gPlayerParty[i], MON_DATA_LEVEL, NULL);
|
||||||
|
if (level > highestLevel)
|
||||||
|
highestLevel = level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return highestLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 FacilityClassToGraphicsId(u8 facilityClass)
|
||||||
|
{
|
||||||
|
u16 trainerObjectGfxId;
|
||||||
|
u8 i;
|
||||||
|
|
||||||
|
// Search male classes.
|
||||||
|
for (i = 0; i < ARRAY_COUNT(gTowerMaleFacilityClasses); i++)
|
||||||
|
{
|
||||||
|
if (gTowerMaleFacilityClasses[i] == facilityClass)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i != ARRAY_COUNT(gTowerMaleFacilityClasses))
|
||||||
|
{
|
||||||
|
trainerObjectGfxId = gTowerMaleTrainerGfxIds[i];
|
||||||
|
return trainerObjectGfxId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search female classes.
|
||||||
|
for (i = 0; i < ARRAY_COUNT(gTowerFemaleFacilityClasses); i++)
|
||||||
|
{
|
||||||
|
if (gTowerFemaleFacilityClasses[i] == facilityClass)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i != ARRAY_COUNT(gTowerFemaleFacilityClasses))
|
||||||
|
{
|
||||||
|
trainerObjectGfxId = gTowerFemaleTrainerGfxIds[i];
|
||||||
|
return trainerObjectGfxId;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return OBJ_EVENT_GFX_BOY_1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define tWindowId data[0]
|
#define tWindowId data[0]
|
||||||
#define tMenuTaskId data[1]
|
#define tMenuTaskId data[1]
|
||||||
#define tArrowTaskId data[2]
|
#define tArrowTaskId data[2]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "berry.h"
|
#include "berry.h"
|
||||||
#include "battle_tower.h"
|
#include "battle_special.h"
|
||||||
#include "easy_chat.h"
|
#include "easy_chat.h"
|
||||||
#include "event_data.h"
|
#include "event_data.h"
|
||||||
#include "mail.h"
|
#include "mail.h"
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
#include "event_data.h"
|
#include "event_data.h"
|
||||||
#include "easy_chat.h"
|
#include "easy_chat.h"
|
||||||
#include "script.h"
|
#include "script.h"
|
||||||
#include "battle_tower.h"
|
#include "battle_special.h"
|
||||||
#include "wonder_news.h"
|
#include "wonder_news.h"
|
||||||
#include "string_util.h"
|
#include "string_util.h"
|
||||||
#include "new_game.h"
|
#include "new_game.h"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#include "decompress.h"
|
#include "decompress.h"
|
||||||
#include "overworld.h"
|
#include "overworld.h"
|
||||||
#include "script.h"
|
#include "script.h"
|
||||||
#include "battle_tower.h"
|
#include "battle_special.h"
|
||||||
#include "mystery_gift.h"
|
#include "mystery_gift.h"
|
||||||
#include "mystery_event_script.h"
|
#include "mystery_event_script.h"
|
||||||
#include "mystery_gift_client.h"
|
#include "mystery_gift_client.h"
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include "battle_tower.h"
|
#include "battle_tower.h"
|
||||||
#include "battle_z_move.h"
|
#include "battle_z_move.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
|
#include "frontier_util.h"
|
||||||
#include "daycare.h"
|
#include "daycare.h"
|
||||||
#include "dexnav.h"
|
#include "dexnav.h"
|
||||||
#include "event_data.h"
|
#include "event_data.h"
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include "ereader_helpers.h"
|
#include "ereader_helpers.h"
|
||||||
#include "event_data.h"
|
#include "event_data.h"
|
||||||
#include "event_scripts.h"
|
#include "event_scripts.h"
|
||||||
|
#include "frontier_util.h"
|
||||||
#include "fieldmap.h"
|
#include "fieldmap.h"
|
||||||
#include "field_message_box.h"
|
#include "field_message_box.h"
|
||||||
#include "international_string_util.h"
|
#include "international_string_util.h"
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
#include "trainer_hill.h"
|
#include "trainer_hill.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "battle_pyramid.h"
|
#include "battle_pyramid.h"
|
||||||
|
#include "constants/battle_frontier.h"
|
||||||
#include "constants/battle_setup.h"
|
#include "constants/battle_setup.h"
|
||||||
#include "constants/event_objects.h"
|
#include "constants/event_objects.h"
|
||||||
#include "constants/event_object_movement.h"
|
#include "constants/event_object_movement.h"
|
||||||
|
|
@ -420,6 +421,33 @@ bool8 CheckForTrainersWantingBattle(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (InBattlePyramid_() || InTrainerHillChallenge())
|
||||||
|
{
|
||||||
|
u8 facility = InBattlePyramid_() ? FACILITY_BATTLE_PYRAMID : FACILITY_BATTLE_TRAINER_HILL;
|
||||||
|
|
||||||
|
if (gNoOfApproachingTrainers > 0)
|
||||||
|
{
|
||||||
|
ResetTrainerOpponentIds();
|
||||||
|
InitTrainerBattleParameter();
|
||||||
|
|
||||||
|
gSelectedObjectEvent = gApproachingTrainers[0].objectEventId;
|
||||||
|
gSpecialVar_LastTalked = gObjectEvents[gApproachingTrainers[0].objectEventId].localId;
|
||||||
|
BattleSetup_ConfigureFacilityTrainerBattle(facility, gApproachingTrainers[0].trainerScriptPtr + 2);
|
||||||
|
if (gNoOfApproachingTrainers > 1)
|
||||||
|
{
|
||||||
|
gApproachingTrainerId++;
|
||||||
|
gSelectedObjectEvent = gApproachingTrainers[1].objectEventId;
|
||||||
|
gSpecialVar_LastTalked = gObjectEvents[gApproachingTrainers[1].objectEventId].localId;
|
||||||
|
BattleSetup_ConfigureFacilityTrainerBattle(facility, gApproachingTrainers[0].trainerScriptPtr + 2);
|
||||||
|
gApproachingTrainerId = 0;
|
||||||
|
}
|
||||||
|
ScriptContext_SetupScript(EventScript_StartTrainerApproach);
|
||||||
|
LockPlayerFieldControls();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (gNoOfApproachingTrainers == 1)
|
if (gNoOfApproachingTrainers == 1)
|
||||||
{
|
{
|
||||||
ResetTrainerOpponentIds();
|
ResetTrainerOpponentIds();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user