mirror of
https://github.com/pret/pokefirered.git
synced 2026-09-30 12:59:43 -05:00
added trainer see double battle and more overworld configs
This commit is contained in:
@@ -1741,6 +1741,17 @@
|
||||
.2byte \quantity
|
||||
.endm
|
||||
|
||||
@ Sets the selected object to the id of the currently approaching trainer.
|
||||
.macro selectapproachingtrainer
|
||||
.byte 0xd5
|
||||
.endm
|
||||
|
||||
@ Freezes all objects immediately except the player and the approaching trainers.
|
||||
@ The player and trainers are frozen once their movement is finished.
|
||||
.macro lockfortrainer
|
||||
.byte 0xd6
|
||||
.endm
|
||||
|
||||
.macro _dynmultichoice left:req, top:req, ignoreBPress:req, maxBeforeScroll:req, shouldSort:req, initialSelected:req, callbacks:req argv:vararg
|
||||
.byte 0xe3
|
||||
.2byte \left
|
||||
|
||||
@@ -23,12 +23,23 @@
|
||||
.align 2
|
||||
|
||||
BattleScript_LocalTrainerBattleWon::
|
||||
jumpifbattletype BATTLE_TYPE_TWO_OPPONENTS, BattleScript_LocalTwoTrainersDefeated
|
||||
printstring STRINGID_PLAYERDEFEATEDTRAINER1
|
||||
goto BattleScript_LocalBattleWonLoseTexts
|
||||
BattleScript_LocalTwoTrainersDefeated::
|
||||
printstring STRINGID_TWOENEMIESDEFEATED
|
||||
BattleScript_LocalBattleWonLoseTexts::
|
||||
trainerslidein BS_ATTACKER
|
||||
waitstate
|
||||
printstring STRINGID_TRAINER1LOSETEXT
|
||||
getmoneyreward
|
||||
jumpifnotbattletype BATTLE_TYPE_TWO_OPPONENTS, BattleScript_LocalTrainerBattleWonGotMoney
|
||||
trainerslideout B_POSITION_OPPONENT_LEFT
|
||||
waitstate
|
||||
trainerslidein BS_FAINTED
|
||||
waitstate
|
||||
printstring STRINGID_TRAINER2LOSETEXT
|
||||
BattleScript_LocalTrainerBattleWonGotMoney::
|
||||
getmoneyreward
|
||||
printstring STRINGID_PLAYERGOTMONEY
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_PayDayMoneyAndPickUpItems::
|
||||
|
||||
@@ -886,10 +886,6 @@ Text_GiveNicknameToReceivedMon::
|
||||
.string "Want to give a nickname to the\n"
|
||||
.string "{STR_VAR_2} you received?$"
|
||||
|
||||
gText_PkmnFainted3::
|
||||
.string "{STR_VAR_1} fainted…\p"
|
||||
.string "$"
|
||||
|
||||
Text_WelcomeWantToHealPkmn::
|
||||
.string "Welcome to our POKéMON CENTER!\p"
|
||||
.string "Would you like me to heal your\n"
|
||||
|
||||
@@ -214,6 +214,8 @@ gScriptCmdTable::
|
||||
.4byte ScrCmd_setmonmetlocation @ 0xd2
|
||||
.4byte ScrCmd_getbraillestringwidth @ 0xd3
|
||||
.4byte ScrCmd_bufferitemnameplural @ 0xd4
|
||||
.4byte ScrCmd_selectapproachingtrainer @ 0xd5
|
||||
.4byte ScrCmd_lockfortrainer @ 0xd6
|
||||
|
||||
gScriptCmdTableEnd::
|
||||
.4byte ScrCmd_nop
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
EventScript_DoTrainerBattleFromApproach::
|
||||
lock
|
||||
selectapproachingtrainer
|
||||
lockfortrainer
|
||||
EventScript_TrainerApproach::
|
||||
special PlayTrainerEncounterMusic
|
||||
special EndTrainerApproach
|
||||
waitstate
|
||||
goto EventScript_DoTrainerBattle
|
||||
goto EventScript_ShowTrainerIntroMsg
|
||||
|
||||
EventScript_TryDoNormalTrainerBattle::
|
||||
lock
|
||||
@@ -16,7 +18,7 @@ EventScript_TryDoNormalTrainerBattle::
|
||||
goto_if_ne VAR_RESULT, FALSE, EventScript_NoTrainerBattle
|
||||
special PlayTrainerEncounterMusic
|
||||
special SetUpTrainerMovement
|
||||
goto EventScript_DoTrainerBattle
|
||||
goto EventScript_ShowTrainerIntroMsg
|
||||
|
||||
EventScript_NoTrainerBattle::
|
||||
gotopostbattlescript
|
||||
@@ -31,7 +33,7 @@ EventScript_TryDoDoubleTrainerBattle::
|
||||
goto_if_ne VAR_RESULT, PLAYER_HAS_TWO_USABLE_MONS, EventScript_NotEnoughMonsForDoubleBattle
|
||||
special PlayTrainerEncounterMusic
|
||||
special SetUpTrainerMovement
|
||||
goto EventScript_DoTrainerBattle
|
||||
goto EventScript_ShowTrainerIntroMsg
|
||||
|
||||
EventScript_NotEnoughMonsForDoubleBattle::
|
||||
special ShowTrainerCantBattleSpeech
|
||||
@@ -112,10 +114,15 @@ Movement_RevealTrainer::
|
||||
reveal_trainer
|
||||
step_end
|
||||
|
||||
EventScript_DoTrainerBattle::
|
||||
EventScript_ShowTrainerIntroMsg::
|
||||
special ShowTrainerIntroSpeech
|
||||
waitmessage
|
||||
waitbuttonpress
|
||||
special TryPrepareSecondApproachingTrainer
|
||||
goto_if_eq VAR_RESULT, TRUE, EventScript_TrainerApproach
|
||||
goto EventScript_DoTrainerBattle
|
||||
|
||||
EventScript_DoTrainerBattle::
|
||||
goto_if_questlog EventScript_EndQuestLogBattle
|
||||
dotrainerbattle
|
||||
specialvar VAR_RESULT, GetTrainerBattleMode
|
||||
|
||||
@@ -456,4 +456,5 @@ gSpecials::
|
||||
def_special GetSprayId
|
||||
def_special GetLastUsedSprayType
|
||||
def_special TrySkyBattle
|
||||
def_special TryPrepareSecondApproachingTrainer
|
||||
gSpecialsEnd::
|
||||
|
||||
@@ -995,8 +995,6 @@ extern u8 gBattleOutcome;
|
||||
extern u16 gLastUsedItem;
|
||||
extern u32 gBattleTypeFlags;
|
||||
extern struct MonSpritesGfx *gMonSpritesGfxPtr;
|
||||
extern u16 gTrainerBattleOpponent_A;
|
||||
extern u16 gTrainerBattleOpponent_B;
|
||||
extern u16 gMoveToLearn;
|
||||
extern u16 gBattleMovePower;
|
||||
extern struct BattleEnigmaBerry gEnigmaBerries[MAX_BATTLERS_COUNT];
|
||||
|
||||
@@ -266,7 +266,7 @@ void BattleControllerComplete(u32 battler); // Can be used for all the controlle
|
||||
void BtlController_Empty(u32 battler); // Empty command, does nothing, only completes the execution.
|
||||
void BtlController_TerminatorNop(u32 battler); // Dummy function at the end of the table.
|
||||
void BattleControllerDummy(u32 battler);
|
||||
void StartSendOutAnim(u32 battler, bool32 dontClearSubstituteBit);
|
||||
void StartSendOutAnim(u32 battler, bool32 dontClearSubstituteBit, bool32 doSlideIn);
|
||||
void Controller_WaitForString(u32 battler);
|
||||
|
||||
// handlers
|
||||
|
||||
@@ -38,15 +38,11 @@ enum
|
||||
#define TAG_HEALTHBOX_PALS_1 55049
|
||||
#define TAG_HEALTHBOX_PALS_2 55050
|
||||
#define TAG_HEALTHBOX_SAFARI_TILE 55051
|
||||
#define TAG_PARTY_SUMMARY_BAR_PLAYER_TILE 55052
|
||||
#define TAG_PARTY_SUMMARY_BAR_OPPONENT_TILE 55053
|
||||
#define TAG_PARTY_SUMMARY_BAR_TILE 55052
|
||||
|
||||
#define TAG_PARTY_SUMMARY_BAR_PLAYER_PAL 55056
|
||||
#define TAG_PARTY_SUMMARY_BAR_OPPONENT_PAL 55057
|
||||
#define TAG_PARTY_SUMMARY_BALL_PLAYER_PAL 55058
|
||||
#define TAG_PARTY_SUMMARY_BALL_OPPONENT_PAL 55059
|
||||
#define TAG_PARTY_SUMMARY_BALL_PLAYER_TILE 55060
|
||||
#define TAG_PARTY_SUMMARY_BALL_OPPONENT_TILE 55061
|
||||
#define TAG_PARTY_SUMMARY_BAR_PAL 55056
|
||||
#define TAG_PARTY_SUMMARY_BALL_PAL 55058
|
||||
#define TAG_PARTY_SUMMARY_BALL_TILE 55060
|
||||
|
||||
#define TAG_HEALTHBOX_PAL TAG_HEALTHBOX_PLAYER1_TILE
|
||||
#define TAG_HEALTHBAR_PAL TAG_HEALTHBAR_PLAYER1_TILE
|
||||
|
||||
@@ -92,6 +92,7 @@ void SpriteCB_FaintSlideAnim(struct Sprite *sprite);
|
||||
void DoBounceEffect(u8 battler, u8 which, s8 delta, s8 amplitude);
|
||||
void EndBounceEffect(u8 battler, u8 which);
|
||||
void SpriteCB_PlayerMonFromBall(struct Sprite *sprite);
|
||||
void SpriteCB_PlayerMonSlideIn(struct Sprite *sprite);
|
||||
void SpriteCB_PlayerThrowInit(struct Sprite *sprite);
|
||||
void UpdatePlayerPosInThrowAnim(struct Sprite *sprite);
|
||||
void BeginBattleIntroDummy(void);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#ifndef GUARD_BATTLE_SETUP_H
|
||||
#define GUARD_BATTLE_SETUP_H
|
||||
|
||||
#include "global.h"
|
||||
|
||||
extern u16 gTrainerBattleOpponent_A;
|
||||
extern u16 gTrainerBattleOpponent_B;
|
||||
extern u16 gPartnerTrainerId;
|
||||
|
||||
void StartWildBattle(void);
|
||||
@@ -17,8 +17,11 @@ void StartGroudonKyogreBattle(void);
|
||||
void StartRegiBattle(void);
|
||||
u8 BattleSetup_GetTerrainId(void);
|
||||
u8 BattleSetup_GetBattleTowerBattleTransition(void);
|
||||
void ResetTrainerOpponentIds(void);
|
||||
const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data);
|
||||
void ConfigureAndSetUpOneTrainerBattle(u8 trainerEventObjId, const u8 *trainerScript);
|
||||
void ConfigureTwoTrainersBattle(u8 trainerObjEventId, const u8 *trainerScript);
|
||||
void SetUpTwoTrainersBattle(void);
|
||||
bool32 GetTrainerFlagFromScriptPointer(const u8 *data);
|
||||
void SetUpTrainerMovement(void);
|
||||
u8 GetTrainerBattleMode(void);
|
||||
@@ -27,7 +30,7 @@ void SetBattledTrainerFlag(void);
|
||||
bool8 HasTrainerBeenFought(u16 trainerId);
|
||||
void SetTrainerFlag(u16 trainerId);
|
||||
void ClearTrainerFlag(u16 trainerId);
|
||||
void StartTrainerBattle(void);
|
||||
void BattleSetup_StartTrainerBattle(void);
|
||||
void StartRematchBattle(void);
|
||||
void ShowTrainerIntroSpeech(void);
|
||||
const u8 *BattleSetup_GetScriptAddrAfterBattle(void);
|
||||
@@ -35,6 +38,7 @@ const u8 *BattleSetup_GetTrainerPostBattleScript(void);
|
||||
void ShowTrainerCantBattleSpeech(void);
|
||||
void PlayTrainerEncounterMusic(void);
|
||||
const u8 *GetTrainerALoseText(void);
|
||||
const u8 *GetTrainerBLoseText(void);
|
||||
const u8 *GetTrainerWonSpeech(void);
|
||||
void BattleSetup_StartTrainerBattle_Debug(void);
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ extern const u16 gBattleTowerBannedSpecies[];
|
||||
|
||||
void ClearEReaderTrainer(struct BattleTowerEReaderTrainer *);
|
||||
void ValidateEReaderTrainer(void);
|
||||
u8 GetBattleTowerTrainerFrontSpriteId(void);
|
||||
u8 GetBattleTowerTrainerFrontSpriteId(u16 trainerId);
|
||||
u8 GetEreaderTrainerFrontSpriteId(void);
|
||||
void CopyEReaderTrainerName5(u8 *dest);
|
||||
void GetBattleTowerTrainerName(u8 *text);
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
// Other settings
|
||||
#define OW_POISON_DAMAGE GEN_LATEST // In Gen4, Pokémon no longer faint from Poison in the overworld. In Gen5+, they no longer take damage at all.
|
||||
#define OW_TIMES_OF_DAY GEN_LATEST // Different generations have the times of day change at different times.
|
||||
#define OW_DOUBLE_APPROACH_WITH_ONE_MON FALSE // If enabled, you can be spotted by two trainers at the same time even if you only have one eligible Pokémon in your party.
|
||||
#define OW_HIDE_REPEAT_MAP_POPUP FALSE // If enabled, map popups will not appear if entering a map with the same Map Section Id as the last.
|
||||
|
||||
@@ -44,7 +43,7 @@
|
||||
// (You should not use 48x48 sprites/tables for compressed gfx)
|
||||
// 16x32, 32x32, 64x64 etc are fine
|
||||
// Follower Pokémon
|
||||
#define OW_FOLLOWERS_ENABLED TRUE // Enables follower Pokémon, HGSS style. Requires OW_POKEMON_OBJECT_EVENTS.
|
||||
#define OW_FOLLOWERS_ENABLED FALSE // Enables follower Pokémon, HGSS style. Requires OW_POKEMON_OBJECT_EVENTS. Note that additional scripting may be required for them to be fully supported!
|
||||
#define OW_FOLLOWERS_BOBBING TRUE // If true, follower pokemon will bob up and down during their idle & walking animations
|
||||
#define OW_FOLLOWERS_POKEBALLS TRUE // Followers will emerge from the pokeball they are stored in, instead of a normal pokeball
|
||||
|
||||
@@ -59,9 +58,18 @@
|
||||
#define OW_STORM_DRAIN GEN_LATEST // In Gen8+, if a Pokémon with Storm Drain is leading the party, there is a 50% chance to encounter a Water-type Pokémon.
|
||||
#define OW_FLASH_FIRE GEN_LATEST // In Gen8+, if a Pokémon with Flash Fire is leading the party, there is a 50% chance to encounter a Fire-type Pokémon.
|
||||
|
||||
// These generational defines only make a distinction for OW_ALTERED_TIME_RATIO
|
||||
#define GEN_8_PLA GEN_LATEST + 2
|
||||
|
||||
//Time
|
||||
#define OW_TIMES_OF_DAY GEN_LATEST // Different generations have the times of day change at different times.
|
||||
#define OW_USE_FAKE_RTC FALSE // When TRUE, seconds on the in-game clock will only advance once every 60 playTimeVBlanks (every 60 frames).
|
||||
#define OW_ALTERED_TIME_RATIO GEN_LATEST // In GEN_8_PLA, the time in game moves forward 60 seconds for every second in the RTC. In GEN_9, it is 20 seconds. This has no effect if OW_USE_FAKE_RTC is FALSE.
|
||||
|
||||
// Overworld flags
|
||||
// To use the following features in scripting, replace the 0s with the flag ID you're assigning it to.
|
||||
// Eg: Replace with FLAG_UNUSED_0x264 so you can use that flag to toggle the feature.
|
||||
#define OW_FLAG_PAUSE_TIME 0 // If this flag is set and OW_USE_FAKE_RTC is enabled, seconds on the in-game clock will not advance.
|
||||
#define OW_FLAG_NO_ENCOUNTER 0 // If this flag is set, wild encounters will be disabled.
|
||||
#define OW_FLAG_NO_TRAINER_SEE 0 // If this flag is set, trainers will not battle the player unless they're talked to.
|
||||
#define OW_FLAG_NO_COLLISION 0 // If this flag is set, the player will be able to walk over tiles with collision. Mainly intended for debugging purposes.
|
||||
@@ -82,8 +90,11 @@
|
||||
#define OW_POPUP_BW_COLOR_WHITE 1 // White pop-up from W2
|
||||
|
||||
// Configuration
|
||||
#define OW_POPUP_BW_COLOR OW_POPUP_BW_COLOR_BLACK // B2W2 use different colors for their map pop-ups.
|
||||
#define OW_POPUP_BW_COLOR OW_POPUP_BW_COLOR_BLACK // B2W2 use different colors for their map pop-ups.
|
||||
#define OW_POPUP_BW_TIME_MODE OW_POPUP_BW_TIME_NONE // Determines what type of time is shown.
|
||||
#define OW_POPUP_BW_ALPHA_BLEND FALSE // Enables alpha blending/transparency for the pop-ups. Mainly intended to be used with the black color option.
|
||||
|
||||
// Pokémon Center
|
||||
#define OW_IGNORE_EGGS_ON_HEAL GEN_LATEST // In Gen 4+, the nurse in the Pokémon Center does not heal Eggs on healing machine.
|
||||
|
||||
#endif // GUARD_CONFIG_OVERWORLD_H
|
||||
|
||||
@@ -7,8 +7,9 @@ bool8 IsFreezePlayerFinished(void);
|
||||
void FreezeObjects_WaitForPlayer(void);
|
||||
bool8 IsFreezeSelectedObjectAndPlayerFinished(void);
|
||||
void FreezeObjects_WaitForPlayerAndSelected(void);
|
||||
void FreezeForApproachingTrainers(void);
|
||||
void ClearPlayerHeldMovementAndUnfreezeObjectEvents(void);
|
||||
bool8 walkrun_is_standing_still(void);
|
||||
bool8 IsPlayerStandingStill(void);
|
||||
void UnionRoom_UnlockPlayerAndChatPartner(void);
|
||||
|
||||
#endif // GUARD_EVENT_OBJECT_LOCK_H
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#ifndef GUARD_EVENT_OBJECT_MOVEMENT_H
|
||||
#define GUARD_EVENT_OBJECT_MOVEMENT_H
|
||||
|
||||
#if OW_POKEMON_OBJECT_EVENTS == FALSE && OW_FOLLOWERS_ENABLED == TRUE
|
||||
#error "OW_POKEMON_OBJECT_EVENTS needs to be TRUE in order for OW_FOLLOWERS_ENABLED to work."
|
||||
#endif
|
||||
|
||||
// Palette slots for overworld NPCs.
|
||||
// The same standard set of palettes for overworld objects are normally always loaded at the same
|
||||
// time while walking around the overworld. The only exceptions are the palettes for the player and
|
||||
@@ -108,7 +112,7 @@ struct ObjectEvent *GetFollowerObject(void);
|
||||
u8 CreateVirtualObject(u16 graphicsId, u8 virtualObjId, s16 x, s16 y, u8 elevation, u8 direction);
|
||||
u8 CreateObjectGraphicsSprite(u16 graphicsId, SpriteCallback callback, s16 x, s16 y, u8 subpriority);
|
||||
u8 TrySpawnObjectEvent(u8 localId, u8 mapNum, u8 mapGroup);
|
||||
int SpawnSpecialObjectEventParameterized(u16 graphicsId, u8 movementBehavior, u8 localId, s16 x, s16 y, u8 elevation);
|
||||
u32 SpawnSpecialObjectEventParameterized(u16 graphicsId, u8 movementBehavior, u8 localId, s16 x, s16 y, u8 elevation);
|
||||
u8 SpawnSpecialObjectEvent(struct ObjectEventTemplate *);
|
||||
void CameraObjectReset1(void);
|
||||
void CameraObjectReset2(void);
|
||||
@@ -178,6 +182,7 @@ void FreezeObjectEvents(void);
|
||||
bool8 FreezeObjectEvent(struct ObjectEvent *);
|
||||
void UnfreezeObjectEvent(struct ObjectEvent *);
|
||||
void FreezeObjectEventsExceptOne(u8 objEventId);
|
||||
void FreezeObjectEventsExceptTwo(u8 objectEventId1, u8 objectEventId2);
|
||||
void SetVirtualObjectGraphics(u8 virtualObjId, u16 graphicsId);
|
||||
void SetVirtualObjectInvisibility(u8 virtualObjId, bool32 invisible);
|
||||
bool32 IsVirtualObjectInvisible(u8 virtualObjId);
|
||||
|
||||
@@ -50,6 +50,7 @@ extern const struct SpriteTemplate gBallSpriteTemplates[];
|
||||
|
||||
#define POKEBALL_PLAYER_SENDOUT 0xFF
|
||||
#define POKEBALL_OPPONENT_SENDOUT 0xFE
|
||||
#define POKEBALL_PLAYER_SLIDEIN 0xFD
|
||||
|
||||
u8 DoPokeballSendOutAnimation(u32 battler, s16 pan, u8 kindOfThrow);
|
||||
void CreatePokeballSpriteToReleaseMon(u8 monSpriteId, u8 monPalNum, u8 x, u8 y, u8 oamPriority, u8 subpriortiy, u8 delay, u32 fadePalettes);
|
||||
|
||||
@@ -762,6 +762,7 @@ u8 GiveMonToPlayer(struct Pokemon *mon);
|
||||
u8 CalculatePlayerPartyCount(void);
|
||||
u8 CalculateEnemyPartyCount(void);
|
||||
u8 GetMonsStateToDoubles(void);
|
||||
u8 GetMonsStateToDoubles_2(void);
|
||||
u16 GetAbilityBySpecies(u16 species, u8 abilityNum);
|
||||
u16 GetMonAbility(struct Pokemon *mon);
|
||||
u8 GetSecretBaseTrainerPicIndex(void);
|
||||
|
||||
@@ -64,7 +64,6 @@ void RecordedBattle_ClearBattlerAction(u8 battlerId, u8 bytesToClear);
|
||||
u8 RecordedBattle_GetBattlerAction(u32 actionType, u8 battlerId);
|
||||
u8 RecordedBattle_BufferNewBattlerData(u8 *dst);
|
||||
void RecordedBattle_RecordAllBattlerData(u8 *data);
|
||||
bool32 MoveRecordedBattleToSaveData(void);
|
||||
void SetPartiesFromRecordedSave(struct RecordedBattleSave *src);
|
||||
void SetVariablesForRecordedBattle(struct RecordedBattleSave *);
|
||||
void RecordedBattle_SaveParties(void);
|
||||
|
||||
@@ -72,6 +72,9 @@ bool8 CanWalkAwayToCancelMsgBox(void);
|
||||
void SetWalkingIntoSignVars(void);
|
||||
bool8 IsMsgBoxWalkawayDisabled(void);
|
||||
|
||||
// srccmd.h
|
||||
void SetMovingNpcId(u16 npcId);
|
||||
|
||||
extern const u8 *gRamScriptRetAddr;
|
||||
extern u8 gWalkAwayFromSignInhibitTimer;
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ extern const u8 gText_RegisteredDataDeleted[];
|
||||
extern const u8 gText_Confirm3[];
|
||||
extern const u8 gText_Cancel4[];
|
||||
extern const u8 gText_IsThisTheCorrectTime[];
|
||||
extern const u8 gText_PkmnFainted3[];
|
||||
extern const u8 gText_PkmnFainted_FldPsn[];
|
||||
extern const u8 gText_Coins[];
|
||||
extern const u8 gText_EggNickname[];
|
||||
extern const u8 gText_MenuPokemon[];
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
#ifndef GUARD_TRAINER_SEE_H
|
||||
#define GUARD_TRAINER_SEE_H
|
||||
|
||||
#include "global.h"
|
||||
struct ApproachingTrainer
|
||||
{
|
||||
u8 objectEventId;
|
||||
u8 radius; // plus 1
|
||||
const u8 *trainerScriptPtr;
|
||||
u8 taskId;
|
||||
};
|
||||
|
||||
extern u16 gWhichTrainerToFaceAfterBattle;
|
||||
extern struct ApproachingTrainer gApproachingTrainers[2];
|
||||
extern u8 gNoOfApproachingTrainers;
|
||||
extern bool8 gTrainerApproachedPlayer;
|
||||
extern u8 gApproachingTrainerId;
|
||||
|
||||
bool8 CheckForTrainersWantingBattle(void);
|
||||
void MovementAction_RevealTrainer_RunTrainerSeeFuncList(struct ObjectEvent *var);
|
||||
@@ -13,5 +22,8 @@ u8 FldEff_DoubleExclMarkIcon(void);
|
||||
u8 FldEff_XIcon(void);
|
||||
u8 FldEff_SmileyFaceIcon(void);
|
||||
u8 FldEff_QuestionMarkIcon(void);
|
||||
u8 GetCurrentApproachingTrainerObjectEventId(void);
|
||||
u8 GetChosenApproachingTrainerObjectEventId(u8 arrayId);
|
||||
void TryPrepareSecondApproachingTrainer(void);
|
||||
|
||||
#endif //GUARD_TRAINER_SEE_H
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "battle_anim.h"
|
||||
#include "battle_bg.h"
|
||||
#include "battle_message.h"
|
||||
#include "battle_setup.h"
|
||||
#include "battle_terrain.h"
|
||||
#include "decompress.h"
|
||||
#include "graphics.h"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "battle_controllers.h"
|
||||
#include "battle_interface.h"
|
||||
#include "battle_message.h"
|
||||
#include "battle_setup.h"
|
||||
#include "gflib.h"
|
||||
#include "data.h"
|
||||
#include "link.h"
|
||||
|
||||
@@ -8,14 +8,15 @@
|
||||
#include "random.h"
|
||||
#include "battle.h"
|
||||
#include "battle_ai_main.h"
|
||||
#include "battle_ai_switch_items.h"
|
||||
#include "battle_ai_util.h"
|
||||
#include "battle_anim.h"
|
||||
#include "battle_controllers.h"
|
||||
#include "battle_message.h"
|
||||
#include "battle_interface.h"
|
||||
#include "battle_tower.h"
|
||||
#include "battle_gfx_sfx_util.h"
|
||||
#include "battle_ai_switch_items.h"
|
||||
#include "battle_interface.h"
|
||||
#include "battle_message.h"
|
||||
#include "battle_setup.h"
|
||||
#include "battle_tower.h"
|
||||
#include "battle_z_move.h"
|
||||
#include "link.h"
|
||||
#include "party_menu.h"
|
||||
@@ -136,32 +137,60 @@ static void Intro_DelayAndEnd(u32 battler)
|
||||
|
||||
static void Intro_WaitForShinyAnimAndHealthbox(u32 battler)
|
||||
{
|
||||
bool8 var = FALSE;
|
||||
bool8 healthboxAnimDone = FALSE;
|
||||
bool8 twoMons;
|
||||
|
||||
if (!IsDoubleBattle() || ((IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI))))
|
||||
twoMons = TwoOpponentIntroMons(battler);
|
||||
if (!twoMons || ((twoMons && (gBattleTypeFlags & BATTLE_TYPE_MULTI) && !BATTLE_TWO_VS_ONE_OPPONENT) || (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)))
|
||||
{
|
||||
if (gSprites[gHealthboxSpriteIds[battler]].callback == SpriteCallbackDummy)
|
||||
var = TRUE;
|
||||
healthboxAnimDone = TRUE;
|
||||
twoMons = FALSE;
|
||||
}
|
||||
else if (gSprites[gHealthboxSpriteIds[battler]].callback == SpriteCallbackDummy
|
||||
&& gSprites[gHealthboxSpriteIds[BATTLE_PARTNER(battler)]].callback == gSprites[gHealthboxSpriteIds[battler]].callback)
|
||||
else
|
||||
{
|
||||
var = TRUE;
|
||||
if (gSprites[gHealthboxSpriteIds[battler]].callback == SpriteCallbackDummy
|
||||
&& gSprites[gHealthboxSpriteIds[BATTLE_PARTNER(battler)]].callback == SpriteCallbackDummy)
|
||||
healthboxAnimDone = TRUE;
|
||||
twoMons = TRUE;
|
||||
}
|
||||
if (IsCryPlayingOrClearCrySongs())
|
||||
var = FALSE;
|
||||
if (var && gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim && gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].finishedShinyMonAnim)
|
||||
|
||||
if (healthboxAnimDone)
|
||||
{
|
||||
gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim = FALSE;
|
||||
gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE;
|
||||
gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].triedShinyMonAnim = FALSE;
|
||||
gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].finishedShinyMonAnim = FALSE;
|
||||
FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS);
|
||||
FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS);
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
|
||||
m4aMPlayContinue(&gMPlayInfo_BGM);
|
||||
if (twoMons == TRUE)
|
||||
{
|
||||
if (gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim
|
||||
&& gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].finishedShinyMonAnim)
|
||||
{
|
||||
gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim = FALSE;
|
||||
gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE;
|
||||
gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].triedShinyMonAnim = FALSE;
|
||||
gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].finishedShinyMonAnim = FALSE;
|
||||
FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS);
|
||||
FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else if (gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim)
|
||||
{
|
||||
if (GetBattlerPosition(battler) == 3)
|
||||
{
|
||||
if (!gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].triedShinyMonAnim
|
||||
&& !gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].finishedShinyMonAnim)
|
||||
{
|
||||
FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS);
|
||||
FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim = FALSE;
|
||||
gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE;
|
||||
}
|
||||
else
|
||||
m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 256);
|
||||
return;
|
||||
|
||||
gBattleSpritesDataPtr->healthBoxesData[battler].introEndDelay = 3;
|
||||
gBattlerControllerFuncs[battler] = Intro_DelayAndEnd;
|
||||
}
|
||||
@@ -169,30 +198,93 @@ static void Intro_WaitForShinyAnimAndHealthbox(u32 battler)
|
||||
|
||||
static void Intro_TryShinyAnimShowHealthbox(u32 battler)
|
||||
{
|
||||
if (!gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim && !gBattleSpritesDataPtr->healthBoxesData[battler].ballAnimActive)
|
||||
bool32 bgmRestored = FALSE;
|
||||
bool32 battlerAnimsDone = FALSE;
|
||||
bool32 twoMons;
|
||||
|
||||
if (!gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim
|
||||
&& !gBattleSpritesDataPtr->healthBoxesData[battler].ballAnimActive
|
||||
&& !gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim)
|
||||
TryShinyAnimation(battler, &gEnemyParty[gBattlerPartyIndexes[battler]]);
|
||||
if (!gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].triedShinyMonAnim && !gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].ballAnimActive)
|
||||
|
||||
twoMons = TwoOpponentIntroMons(battler);
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
|
||||
&& (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) || BATTLE_TWO_VS_ONE_OPPONENT)
|
||||
&& twoMons
|
||||
&& !gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].triedShinyMonAnim
|
||||
&& !gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].ballAnimActive
|
||||
&& !gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].finishedShinyMonAnim)
|
||||
TryShinyAnimation(BATTLE_PARTNER(battler), &gEnemyParty[gBattlerPartyIndexes[BATTLE_PARTNER(battler)]]);
|
||||
|
||||
if (!gBattleSpritesDataPtr->healthBoxesData[battler].ballAnimActive && !gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].ballAnimActive)
|
||||
{
|
||||
if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI))
|
||||
if (!gBattleSpritesDataPtr->healthBoxesData[battler].healthboxSlideInStarted)
|
||||
{
|
||||
if (twoMons && (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) || BATTLE_TWO_VS_ONE_OPPONENT))
|
||||
{
|
||||
UpdateHealthboxAttribute(gHealthboxSpriteIds[BATTLE_PARTNER(battler)], &gEnemyParty[gBattlerPartyIndexes[BATTLE_PARTNER(battler)]], HEALTHBOX_ALL);
|
||||
StartHealthboxSlideIn(BATTLE_PARTNER(battler));
|
||||
SetHealthboxSpriteVisible(gHealthboxSpriteIds[BATTLE_PARTNER(battler)]);
|
||||
}
|
||||
UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], &gEnemyParty[gBattlerPartyIndexes[battler]], HEALTHBOX_ALL);
|
||||
StartHealthboxSlideIn(battler);
|
||||
SetHealthboxSpriteVisible(gHealthboxSpriteIds[battler]);
|
||||
}
|
||||
gBattleSpritesDataPtr->healthBoxesData[battler].healthboxSlideInStarted = TRUE;
|
||||
}
|
||||
|
||||
if (!gBattleSpritesDataPtr->healthBoxesData[battler].waitForCry
|
||||
&& gBattleSpritesDataPtr->healthBoxesData[battler].healthboxSlideInStarted
|
||||
&& !gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].waitForCry
|
||||
&& !IsCryPlayingOrClearCrySongs())
|
||||
{
|
||||
if (!gBattleSpritesDataPtr->healthBoxesData[battler].bgmRestored)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_LINK)
|
||||
{
|
||||
if (GetBattlerPosition(battler) == 1)
|
||||
m4aMPlayContinue(&gMPlayInfo_BGM);
|
||||
}
|
||||
else
|
||||
m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x100);
|
||||
}
|
||||
gBattleSpritesDataPtr->healthBoxesData[battler].bgmRestored = TRUE;
|
||||
bgmRestored = TRUE;
|
||||
}
|
||||
|
||||
if (!twoMons || (twoMons && gBattleTypeFlags & BATTLE_TYPE_MULTI && !BATTLE_TWO_VS_ONE_OPPONENT))
|
||||
{
|
||||
if (gSprites[gBattleControllerData[battler]].callback == SpriteCallbackDummy
|
||||
&& gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy)
|
||||
{
|
||||
battlerAnimsDone = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gSprites[gBattleControllerData[battler]].callback == SpriteCallbackDummy
|
||||
&& gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy
|
||||
&& gSprites[gBattleControllerData[BATTLE_PARTNER(battler)]].callback == SpriteCallbackDummy
|
||||
&& gSprites[gBattlerSpriteIds[BATTLE_PARTNER(battler)]].callback == SpriteCallbackDummy)
|
||||
{
|
||||
battlerAnimsDone = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (bgmRestored && battlerAnimsDone)
|
||||
{
|
||||
if (twoMons && (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) || BATTLE_TWO_VS_ONE_OPPONENT))
|
||||
{
|
||||
DestroySprite(&gSprites[gBattleControllerData[BATTLE_PARTNER(battler)]]);
|
||||
UpdateHealthboxAttribute(gHealthboxSpriteIds[BATTLE_PARTNER(battler)],
|
||||
&gEnemyParty[gBattlerPartyIndexes[BATTLE_PARTNER(battler)]],
|
||||
HEALTHBOX_ALL);
|
||||
StartHealthboxSlideIn(BATTLE_PARTNER(battler));
|
||||
SetHealthboxSpriteVisible(gHealthboxSpriteIds[BATTLE_PARTNER(battler)]);
|
||||
SetBattlerShadowSpriteCallback(BATTLE_PARTNER(battler), GetMonData(&gEnemyParty[gBattlerPartyIndexes[BATTLE_PARTNER(battler)]], MON_DATA_SPECIES));
|
||||
}
|
||||
|
||||
DestroySprite(&gSprites[gBattleControllerData[battler]]);
|
||||
UpdateHealthboxAttribute(gHealthboxSpriteIds[battler],
|
||||
&gEnemyParty[gBattlerPartyIndexes[battler]],
|
||||
HEALTHBOX_ALL);
|
||||
StartHealthboxSlideIn(battler);
|
||||
SetHealthboxSpriteVisible(gHealthboxSpriteIds[battler]);
|
||||
SetBattlerShadowSpriteCallback(battler, GetMonData(&gEnemyParty[gBattlerPartyIndexes[battler]], MON_DATA_SPECIES));
|
||||
gBattleSpritesDataPtr->animationData->introAnimActive = FALSE;
|
||||
gBattleSpritesDataPtr->healthBoxesData[battler].bgmRestored = FALSE;
|
||||
gBattleSpritesDataPtr->healthBoxesData[battler].healthboxSlideInStarted = FALSE;
|
||||
|
||||
gBattlerControllerFuncs[battler] = Intro_WaitForShinyAnimAndHealthbox;
|
||||
}
|
||||
}
|
||||
@@ -298,11 +390,30 @@ static u32 OpponentGetTrainerPicId(u32 battlerId) // TODO: trainer refactoring
|
||||
u32 trainerPicId;
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER)
|
||||
trainerPicId = GetBattleTowerTrainerFrontSpriteId();
|
||||
{
|
||||
if (gBattleTypeFlags & (BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_TOWER_LINK_MULTI))
|
||||
{
|
||||
if (battlerId == 1)
|
||||
trainerPicId = GetBattleTowerTrainerFrontSpriteId(gTrainerBattleOpponent_A);
|
||||
else
|
||||
trainerPicId = GetBattleTowerTrainerFrontSpriteId(gTrainerBattleOpponent_B);
|
||||
}
|
||||
else
|
||||
{
|
||||
trainerPicId = GetBattleTowerTrainerFrontSpriteId(gTrainerBattleOpponent_A);
|
||||
}
|
||||
}
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_TOWER)
|
||||
trainerPicId = GetTrainerTowerTrainerFrontSpriteId();
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_EREADER_TRAINER)
|
||||
trainerPicId = GetEreaderTrainerFrontSpriteId();
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
|
||||
{
|
||||
if (battlerId != 1)
|
||||
trainerPicId = GetTrainerPicFromId(gTrainerBattleOpponent_B);
|
||||
else
|
||||
trainerPicId = GetTrainerPicFromId(gTrainerBattleOpponent_A);
|
||||
}
|
||||
else
|
||||
trainerPicId = GetTrainerPicFromId(gTrainerBattleOpponent_A);
|
||||
|
||||
@@ -336,7 +447,7 @@ static void OpponentHandleTrainerSlide(u32 battler)
|
||||
}
|
||||
|
||||
static void OpponentHandleTrainerSlideBack(u32 battler)
|
||||
{
|
||||
{
|
||||
BtlController_HandleTrainerSlideBack(battler, 35, FALSE);
|
||||
}
|
||||
|
||||
|
||||
@@ -396,7 +396,10 @@ static void RecordedOpponentHandleDrawTrainerPic(u32 battler)
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER)
|
||||
{
|
||||
trainerPicId = GetBattleTowerTrainerFrontSpriteId();
|
||||
if (battler == B_POSITION_OPPONENT_LEFT)
|
||||
trainerPicId = GetBattleTowerTrainerFrontSpriteId(gTrainerBattleOpponent_A);
|
||||
else
|
||||
trainerPicId = GetBattleTowerTrainerFrontSpriteId(gTrainerBattleOpponent_B);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
#include "battle_controllers.h"
|
||||
#include "battle_interface.h"
|
||||
#include "battle_message.h"
|
||||
#include "battle_setup.h"
|
||||
#include "cable_club.h"
|
||||
#include "event_object_movement.h"
|
||||
#include "link.h"
|
||||
#include "link_rfu.h"
|
||||
#include "palette.h"
|
||||
@@ -19,9 +21,9 @@
|
||||
#include "test_runner.h"
|
||||
#include "text.h"
|
||||
#include "util.h"
|
||||
#include "constants/abilities.h"
|
||||
#include "constants/songs.h"
|
||||
#include "constants/sound.h"
|
||||
#include "constants/abilities.h"
|
||||
|
||||
static EWRAM_DATA u8 sLinkSendTaskId = 0;
|
||||
static EWRAM_DATA u8 sLinkReceiveTaskId = 0;
|
||||
@@ -1834,7 +1836,22 @@ static void SetBattlerMonData(u32 battler, struct Pokemon *party, u32 monId)
|
||||
HandleLowHpMusicChange(&party[gBattlerPartyIndexes[battler]], battler);
|
||||
}
|
||||
|
||||
void StartSendOutAnim(u32 battler, bool32 dontClearSubstituteBit)
|
||||
// In normal singles, if follower pokemon is out, have it slide in instead of being thrown
|
||||
static bool8 ShouldDoSlideInAnim(void)
|
||||
{
|
||||
struct ObjectEvent *followerObj = GetFollowerObject();
|
||||
if (!followerObj || followerObj->invisible)
|
||||
return FALSE;
|
||||
if (gBattleTypeFlags & (
|
||||
BATTLE_TYPE_LINK | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_FRONTIER | BATTLE_TYPE_FIRST_BATTLE |
|
||||
BATTLE_TYPE_SAFARI | BATTLE_TYPE_OLD_MAN_TUTORIAL | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TWO_OPPONENTS |
|
||||
BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_RECORDED | BATTLE_TYPE_POKEDUDE | BATTLE_TYPE_TRAINER_TOWER)
|
||||
)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void StartSendOutAnim(u32 battler, bool32 dontClearSubstituteBit, bool32 doSlideIn)
|
||||
{
|
||||
u16 species;
|
||||
u32 side = GetBattlerSide(battler);
|
||||
@@ -1865,7 +1882,7 @@ void StartSendOutAnim(u32 battler, bool32 dontClearSubstituteBit)
|
||||
|
||||
gSprites[gBattleControllerData[battler]].data[1] = gBattlerSpriteIds[battler];
|
||||
gSprites[gBattleControllerData[battler]].data[2] = battler;
|
||||
gSprites[gBattleControllerData[battler]].data[0] = DoPokeballSendOutAnimation(battler, 0, (side == B_SIDE_OPPONENT) ? POKEBALL_OPPONENT_SENDOUT : POKEBALL_PLAYER_SENDOUT);
|
||||
gSprites[gBattleControllerData[battler]].data[0] = DoPokeballSendOutAnimation(battler, 0, (side == B_SIDE_OPPONENT) ? POKEBALL_OPPONENT_SENDOUT : (doSlideIn ? POKEBALL_PLAYER_SLIDEIN : POKEBALL_PLAYER_SENDOUT));
|
||||
}
|
||||
|
||||
static void FreeMonSprite(u32 battler)
|
||||
@@ -2213,7 +2230,7 @@ void BtlController_HandleSwitchInAnim(u32 battler, bool32 isPlayerSide, void (*c
|
||||
gBattlerPartyIndexes[battler] = gBattleResources->bufferA[battler][1];
|
||||
if (isPlayerSide)
|
||||
BattleLoadMonSpriteGfx(&gPlayerParty[gBattlerPartyIndexes[battler]], battler);
|
||||
StartSendOutAnim(battler, gBattleResources->bufferA[battler][2]);
|
||||
StartSendOutAnim(battler, gBattleResources->bufferA[battler][2], FALSE);
|
||||
gBattlerControllerFuncs[battler] = controllerCallback;
|
||||
}
|
||||
|
||||
@@ -2719,17 +2736,17 @@ static void Task_StartSendOutAnim(u8 taskId)
|
||||
if (TwoMonsAtSendOut(battler))
|
||||
{
|
||||
gBattleResources->bufferA[battler][1] = gBattlerPartyIndexes[battler];
|
||||
StartSendOutAnim(battler, FALSE);
|
||||
StartSendOutAnim(battler, FALSE, ShouldDoSlideInAnim());
|
||||
|
||||
battlerPartner = BATTLE_PARTNER(battler);
|
||||
gBattleResources->bufferA[battlerPartner][1] = gBattlerPartyIndexes[battlerPartner];
|
||||
BattleLoadMonSpriteGfx(&gPlayerParty[gBattlerPartyIndexes[battlerPartner]], battlerPartner);
|
||||
StartSendOutAnim(battlerPartner, FALSE);
|
||||
StartSendOutAnim(battlerPartner, FALSE, ShouldDoSlideInAnim());
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleResources->bufferA[battler][1] = gBattlerPartyIndexes[battler];
|
||||
StartSendOutAnim(battler, FALSE);
|
||||
StartSendOutAnim(battler, FALSE, ShouldDoSlideInAnim());
|
||||
}
|
||||
gBattlerControllerFuncs[battler] = (void*)(GetWordTaskArg(taskId, tControllerFunc_1));
|
||||
DestroyTask(taskId);
|
||||
|
||||
@@ -697,8 +697,7 @@ void CB2_BattleDebugMenu(void)
|
||||
break;
|
||||
case 3:
|
||||
LoadPalette(sBgColor, 0, 2);
|
||||
// LoadPalette(GetOverworldTextboxPalettePtr(), 0xf0, 16); // TODO: debug
|
||||
LoadPalette(GetTextWindowPalette(2), 0xC0, 0x20);
|
||||
LoadPalette(GetTextWindowPalette(2), 0xf0, 16);
|
||||
gMain.state++;
|
||||
break;
|
||||
case 4:
|
||||
@@ -1213,6 +1212,7 @@ static void Task_DebugMenuProcessInput(u8 taskId)
|
||||
{
|
||||
data->currentSecondaryListItemId = listItemId;
|
||||
data->modifyWindowId = AddWindow(&sModifyWindowTemplate);
|
||||
ClearStdWindowAndFrameToTransparent(data->modifyWindowId, TRUE); // FRLG change: fixes number background
|
||||
PutWindowTilemap(data->modifyWindowId);
|
||||
CopyWindowToVram(data->modifyWindowId, COPYWIN_FULL);
|
||||
SetUpModifyArrows(data);
|
||||
|
||||
@@ -367,24 +367,30 @@ static const struct SubspriteTable sStatusSummaryBar_SubspriteTable_Exit[] = {
|
||||
|
||||
static const u16 sBattleInterface_Unused[] = INCBIN_U16("graphics/battle_interface/unused.4bpp");
|
||||
|
||||
static const struct CompressedSpriteSheet sPartySummaryBarSpriteSheets[] = {
|
||||
{gBattleInterface_PartySummaryBar_Gfx, 16 * TILE_SIZE_4BPP, TAG_PARTY_SUMMARY_BAR_PLAYER_TILE},
|
||||
{gBattleInterface_PartySummaryBar_Gfx, 16 * TILE_SIZE_4BPP, TAG_PARTY_SUMMARY_BAR_OPPONENT_TILE}
|
||||
static const struct CompressedSpriteSheet sStatusSummaryBarSpriteSheet =
|
||||
{
|
||||
.data = gBattleInterface_PartySummaryBar_Gfx,
|
||||
.size = 16 * TILE_SIZE_4BPP,
|
||||
.tag = TAG_PARTY_SUMMARY_BAR_TILE,
|
||||
};
|
||||
|
||||
static const struct SpritePalette sPartySummaryBarSpritePals[] = {
|
||||
{gBattleInterface_Healthbox_Pal, TAG_PARTY_SUMMARY_BAR_PLAYER_PAL},
|
||||
{gBattleInterface_Healthbox_Pal, TAG_PARTY_SUMMARY_BAR_OPPONENT_PAL}
|
||||
static const struct SpritePalette sPartySummaryBarSpritePals =
|
||||
{
|
||||
.data = gBattleInterface_Healthbox_Pal,
|
||||
.tag = TAG_PARTY_SUMMARY_BAR_PAL,
|
||||
};
|
||||
|
||||
static const struct SpritePalette sPartySummaryBallSpritePals[] = {
|
||||
{gBattleInterface_Healthbar_Pal, TAG_PARTY_SUMMARY_BALL_PLAYER_PAL},
|
||||
{gBattleInterface_Healthbar_Pal, TAG_PARTY_SUMMARY_BALL_OPPONENT_PAL}
|
||||
static const struct SpritePalette sPartySummaryBallSpritePals =
|
||||
{
|
||||
.data = gBattleInterface_Healthbar_Pal,
|
||||
.tag = TAG_PARTY_SUMMARY_BALL_PAL,
|
||||
};
|
||||
|
||||
static const struct SpriteSheet sPartySummaryBallSpriteSheets[] = {
|
||||
{gBattleInterface_Gfx + B_INTERFACE_GFX_BALL_PARTY_SUMMARY, 4 * TILE_SIZE_4BPP, TAG_PARTY_SUMMARY_BALL_PLAYER_TILE},
|
||||
{gBattleInterface_Gfx + B_INTERFACE_GFX_BALL_PARTY_SUMMARY, 4 * TILE_SIZE_4BPP, TAG_PARTY_SUMMARY_BALL_OPPONENT_TILE}
|
||||
static const struct SpriteSheet sPartySummaryBallSpriteSheets =
|
||||
{
|
||||
.data = gBattleInterface_Gfx + B_INTERFACE_GFX_BALL_PARTY_SUMMARY,
|
||||
.size = 4 * TILE_SIZE_4BPP,
|
||||
.tag = TAG_PARTY_SUMMARY_BALL_TILE,
|
||||
};
|
||||
|
||||
// Unused
|
||||
@@ -402,15 +408,15 @@ static const struct OamData sOamData_PartySummaryBall = {
|
||||
|
||||
static const struct SpriteTemplate sPartySummaryBarSpriteTemplates[] = {
|
||||
{
|
||||
.tileTag = TAG_PARTY_SUMMARY_BAR_PLAYER_TILE,
|
||||
.paletteTag = TAG_PARTY_SUMMARY_BAR_PLAYER_PAL,
|
||||
.tileTag = TAG_PARTY_SUMMARY_BAR_TILE,
|
||||
.paletteTag = TAG_PARTY_SUMMARY_BAR_PAL,
|
||||
.oam = &sOamData_Healthbox,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCB_PartySummaryBar
|
||||
}, {
|
||||
.tileTag = TAG_PARTY_SUMMARY_BAR_OPPONENT_TILE,
|
||||
.paletteTag = TAG_PARTY_SUMMARY_BAR_OPPONENT_PAL,
|
||||
.tileTag = TAG_PARTY_SUMMARY_BAR_TILE,
|
||||
.paletteTag = TAG_PARTY_SUMMARY_BAR_PAL,
|
||||
.oam = &sOamData_Healthbox,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
@@ -420,15 +426,15 @@ static const struct SpriteTemplate sPartySummaryBarSpriteTemplates[] = {
|
||||
|
||||
static const struct SpriteTemplate sPartySummaryBallSpriteTemplates[] = {
|
||||
{
|
||||
.tileTag = TAG_PARTY_SUMMARY_BALL_PLAYER_TILE,
|
||||
.paletteTag = TAG_PARTY_SUMMARY_BALL_PLAYER_PAL,
|
||||
.tileTag = TAG_PARTY_SUMMARY_BALL_TILE,
|
||||
.paletteTag = TAG_PARTY_SUMMARY_BALL_PAL,
|
||||
.oam = &sOamData_PartySummaryBall,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCB_PartySummaryBall_OnBattleStart
|
||||
}, {
|
||||
.tileTag = TAG_PARTY_SUMMARY_BALL_OPPONENT_TILE,
|
||||
.paletteTag = TAG_PARTY_SUMMARY_BALL_OPPONENT_PAL,
|
||||
.tileTag = TAG_PARTY_SUMMARY_BALL_TILE,
|
||||
.paletteTag = TAG_PARTY_SUMMARY_BALL_PAL,
|
||||
.oam = &sOamData_PartySummaryBall,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
@@ -1125,10 +1131,10 @@ u8 CreatePartyStatusSummarySprites(u8 battlerId, struct HpAndStatus *partyInfo,
|
||||
nValidMons++;
|
||||
}
|
||||
|
||||
LoadCompressedSpriteSheetUsingHeap(&sPartySummaryBarSpriteSheets[isOpponent]);
|
||||
LoadSpriteSheet(&sPartySummaryBallSpriteSheets[isOpponent]);
|
||||
LoadSpritePalette(&sPartySummaryBarSpritePals[isOpponent]);
|
||||
LoadSpritePalette(&sPartySummaryBallSpritePals[isOpponent]);
|
||||
LoadCompressedSpriteSheetUsingHeap(&sStatusSummaryBarSpriteSheet);
|
||||
LoadSpriteSheet(&sPartySummaryBallSpriteSheets);
|
||||
LoadSpritePalette(&sPartySummaryBarSpritePals);
|
||||
LoadSpritePalette(&sPartySummaryBallSpritePals);
|
||||
|
||||
summaryBarSpriteId = CreateSprite(&sPartySummaryBarSpriteTemplates[isOpponent], x, y, 10);
|
||||
SetSubspriteTables(&gSprites[summaryBarSpriteId], sStatusSummaryBar_SubspriteTable_Enter);
|
||||
|
||||
@@ -90,6 +90,9 @@ s32 GetAnimBgAttribute(u8 bgId, u8 attributeId)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define tState data[0]
|
||||
#define tTerrain data[1]
|
||||
|
||||
void HandleIntroSlide(u8 terrain)
|
||||
{
|
||||
u8 taskId;
|
||||
@@ -107,8 +110,9 @@ void HandleIntroSlide(u8 terrain)
|
||||
{
|
||||
taskId = CreateTask(sBattleIntroSlideFuncs[terrain], 0);
|
||||
}
|
||||
gTasks[taskId].data[0] = 0;
|
||||
gTasks[taskId].data[1] = terrain;
|
||||
|
||||
gTasks[taskId].tState = 0;
|
||||
gTasks[taskId].tTerrain = terrain;
|
||||
gTasks[taskId].data[2] = 0;
|
||||
gTasks[taskId].data[3] = 0;
|
||||
gTasks[taskId].data[4] = 0;
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "constants/moves.h"
|
||||
#include "constants/pokemon.h"
|
||||
#include "constants/songs.h"
|
||||
#include "constants/sound.h"
|
||||
#include "constants/trainers.h"
|
||||
|
||||
static void HandleEndTurn_ContinueBattle(void);
|
||||
@@ -2145,6 +2146,37 @@ void SpriteCB_PlayerMonFromBall(struct Sprite *sprite)
|
||||
BattleAnimateBackSprite(sprite, sprite->sSpeciesId);
|
||||
}
|
||||
|
||||
void SpriteCB_PlayerMonSlideIn(struct Sprite *sprite)
|
||||
{
|
||||
if (sprite->data[3] == 0)
|
||||
{
|
||||
PlaySE(SE_BALL_TRAY_ENTER);
|
||||
sprite->data[3]++;
|
||||
}
|
||||
else if (sprite->data[3] == 1)
|
||||
{
|
||||
if (sprite->animEnded)
|
||||
return;
|
||||
sprite->data[4] = sprite->x;
|
||||
sprite->x = -33;
|
||||
sprite->invisible = FALSE;
|
||||
sprite->data[3]++;
|
||||
}
|
||||
else if (sprite->data[3] < 27)
|
||||
{
|
||||
sprite->x += 4;
|
||||
sprite->data[3]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite->data[3] = 0;
|
||||
sprite->x = sprite->data[4];
|
||||
sprite->data[4] = 0;
|
||||
sprite->callback = SpriteCB_PlayerMonFromBall;
|
||||
PlayCry_ByMode(sprite->sSpeciesId, -25, CRY_MODE_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteCB_PlayerThrowInit(struct Sprite *sprite)
|
||||
{
|
||||
StartSpriteAnim(sprite, 1);
|
||||
|
||||
@@ -3178,12 +3178,22 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst)
|
||||
}
|
||||
break;
|
||||
case B_TXT_TRAINER2_LOSE_TEXT:
|
||||
GetTrainerTowerOpponentLoseText(gStringVar4, 1);
|
||||
toCpy = gStringVar4;
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_TOWER)
|
||||
{
|
||||
GetTrainerTowerOpponentLoseText(gStringVar4, 1);
|
||||
toCpy = gStringVar4;
|
||||
}
|
||||
else
|
||||
{
|
||||
toCpy = GetTrainerBLoseText();
|
||||
}
|
||||
break;
|
||||
case B_TXT_TRAINER2_WIN_TEXT:
|
||||
GetTrainerTowerOpponentWinText(gStringVar4, 1);
|
||||
toCpy = gStringVar4;
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_TOWER)
|
||||
{
|
||||
GetTrainerTowerOpponentWinText(gStringVar4, 1);
|
||||
toCpy = gStringVar4;
|
||||
}
|
||||
break;
|
||||
case B_TXT_26: // ?
|
||||
HANDLE_NICKNAME_STRING_CASE(gBattleScripting.battler)
|
||||
@@ -3240,7 +3250,8 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst)
|
||||
// TODO: implement partner trainers?
|
||||
// if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
|
||||
// toCpy = gTrainerClasses[GetFrontierOpponentClass(gPartnerTrainerId)].name;
|
||||
toCpy = gTrainerClasses[TRAINER_CLASS_NONE].name;
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
|
||||
toCpy = gTrainerClasses[gPartnerTrainerId].name;
|
||||
break;
|
||||
case B_POSITION_OPPONENT_LEFT:
|
||||
toCpy = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_A);
|
||||
@@ -3267,7 +3278,6 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst)
|
||||
break;
|
||||
case B_TXT_DEF_NAME: // target name
|
||||
HANDLE_NICKNAME_STRING_CASE(gBattlerTarget)
|
||||
// GetBattlerNick(gBattlerTarget, text);
|
||||
toCpy = text;
|
||||
break;
|
||||
case B_TXT_DEF_TEAM1:
|
||||
@@ -3284,12 +3294,15 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst)
|
||||
break;
|
||||
}
|
||||
|
||||
// missing if (toCpy != NULL) check
|
||||
while (*toCpy != EOS)
|
||||
if (toCpy != NULL)
|
||||
{
|
||||
dst[dstId++] = *toCpy;
|
||||
toCpy++;
|
||||
while (*toCpy != EOS)
|
||||
{
|
||||
dst[dstId++] = *toCpy;
|
||||
toCpy++;
|
||||
}
|
||||
}
|
||||
|
||||
if (*src == B_TXT_TRAINER1_LOSE_TEXT || *src == B_TXT_TRAINER1_WIN_TEXT
|
||||
|| *src == B_TXT_TRAINER2_LOSE_TEXT || *src == B_TXT_TRAINER2_WIN_TEXT)
|
||||
{
|
||||
|
||||
@@ -77,11 +77,14 @@ EWRAM_DATA u16 gTrainerBattleOpponent_B = 0;
|
||||
EWRAM_DATA u16 gPartnerTrainerId = 0;
|
||||
static EWRAM_DATA u16 sTrainerObjectEventLocalId = 0;
|
||||
static EWRAM_DATA u8 *sTrainerAIntroSpeech = NULL;
|
||||
EWRAM_DATA static u8 *sTrainerBIntroSpeech = NULL;
|
||||
static EWRAM_DATA u8 *sTrainerADefeatSpeech = NULL;
|
||||
EWRAM_DATA static u8 *sTrainerBDefeatSpeech = NULL;
|
||||
static EWRAM_DATA u8 *sTrainerVictorySpeech = NULL;
|
||||
static EWRAM_DATA u8 *sTrainerCannotBattleSpeech = NULL;
|
||||
static EWRAM_DATA u8 *sTrainerBattleEndScript = NULL;
|
||||
static EWRAM_DATA u8 *sTrainerABattleScriptRetAddr = NULL;
|
||||
EWRAM_DATA static u8 *sTrainerBBattleScriptRetAddr = NULL;
|
||||
static EWRAM_DATA u16 sRivalBattleFlags = 0;
|
||||
EWRAM_DATA static bool8 sShouldCheckTrainerBScript = FALSE;
|
||||
EWRAM_DATA static u8 sNoOfPossibleTrainerRetScripts = 0;
|
||||
@@ -182,6 +185,49 @@ static const struct TrainerBattleParameter sContinueScriptDoubleBattleParams[] =
|
||||
{&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR},
|
||||
};
|
||||
|
||||
static const struct TrainerBattleParameter sTrainerBOrdinaryBattleParams[] =
|
||||
{
|
||||
{&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT},
|
||||
{&gTrainerBattleOpponent_B, TRAINER_PARAM_LOAD_VAL_16BIT},
|
||||
{&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT},
|
||||
{&sTrainerBIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
|
||||
{&sTrainerBDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
|
||||
{&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
|
||||
{&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
|
||||
{&sTrainerBBattleScriptRetAddr, TRAINER_PARAM_CLEAR_VAL_32BIT},
|
||||
{&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR},
|
||||
};
|
||||
|
||||
static const struct TrainerBattleParameter sTrainerBContinueScriptBattleParams[] =
|
||||
{
|
||||
{&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT},
|
||||
{&gTrainerBattleOpponent_B, TRAINER_PARAM_LOAD_VAL_16BIT},
|
||||
{&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT},
|
||||
{&sTrainerBIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
|
||||
{&sTrainerBDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
|
||||
{&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
|
||||
{&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
|
||||
{&sTrainerBBattleScriptRetAddr, TRAINER_PARAM_LOAD_VAL_32BIT},
|
||||
{&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR},
|
||||
};
|
||||
|
||||
// two trainers, each with a defeat speech
|
||||
static const struct TrainerBattleParameter sTrainerTwoTrainerBattleParams[] =
|
||||
{
|
||||
{&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT},
|
||||
{&sTrainerObjectEventLocalId, TRAINER_PARAM_CLEAR_VAL_16BIT},
|
||||
{&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT},
|
||||
{&sTrainerAIntroSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
|
||||
{&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
|
||||
{&gTrainerBattleOpponent_B, TRAINER_PARAM_LOAD_VAL_16BIT},
|
||||
{&sTrainerBIntroSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
|
||||
{&sTrainerBDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
|
||||
{&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
|
||||
{&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
|
||||
{&sTrainerBBattleScriptRetAddr, TRAINER_PARAM_CLEAR_VAL_32BIT},
|
||||
{&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR},
|
||||
};
|
||||
|
||||
|
||||
#define tState data[0]
|
||||
#define tTransition data[1]
|
||||
@@ -705,6 +751,11 @@ static u16 GetTrainerAFlag(void)
|
||||
return TRAINER_FLAGS_START + gTrainerBattleOpponent_A;
|
||||
}
|
||||
|
||||
static u16 GetTrainerBFlag(void)
|
||||
{
|
||||
return TRAINER_FLAGS_START + gTrainerBattleOpponent_B;
|
||||
}
|
||||
|
||||
static bool32 IsPlayerDefeated(u32 battleOutcome)
|
||||
{
|
||||
switch (battleOutcome)
|
||||
@@ -723,17 +774,33 @@ static bool32 IsPlayerDefeated(u32 battleOutcome)
|
||||
}
|
||||
}
|
||||
|
||||
void ResetTrainerOpponentIds(void)
|
||||
{
|
||||
gTrainerBattleOpponent_A = 0;
|
||||
gTrainerBattleOpponent_B = 0;
|
||||
}
|
||||
|
||||
static void InitTrainerBattleVariables(void)
|
||||
{
|
||||
sTrainerBattleMode = 0;
|
||||
gTrainerBattleOpponent_A = 0;
|
||||
|
||||
if (gApproachingTrainerId == 0)
|
||||
{
|
||||
sTrainerAIntroSpeech = NULL;
|
||||
sTrainerADefeatSpeech = NULL;
|
||||
sTrainerABattleScriptRetAddr = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
sTrainerBIntroSpeech = NULL;
|
||||
sTrainerBDefeatSpeech = NULL;
|
||||
sTrainerBBattleScriptRetAddr = NULL;
|
||||
}
|
||||
|
||||
sTrainerObjectEventLocalId = 0;
|
||||
sTrainerAIntroSpeech = NULL;
|
||||
sTrainerADefeatSpeech = NULL;
|
||||
sTrainerVictorySpeech = NULL;
|
||||
sTrainerCannotBattleSpeech = NULL;
|
||||
sTrainerBattleEndScript = NULL;
|
||||
sTrainerABattleScriptRetAddr = NULL;
|
||||
sRivalBattleFlags = 0;
|
||||
}
|
||||
|
||||
@@ -840,8 +907,15 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data)
|
||||
TrainerBattleLoadArgs(sEarlyRivalBattleParams, data);
|
||||
return EventScript_DoNoIntroTrainerBattle;
|
||||
default:
|
||||
TrainerBattleLoadArgs(sOrdinaryBattleParams, data);
|
||||
SetMapVarsToTrainer();
|
||||
if (gApproachingTrainerId == 0)
|
||||
{
|
||||
TrainerBattleLoadArgs(sOrdinaryBattleParams, data);
|
||||
SetMapVarsToTrainer();
|
||||
}
|
||||
else
|
||||
{
|
||||
TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data);
|
||||
}
|
||||
return EventScript_TryDoNormalTrainerBattle;
|
||||
}
|
||||
}
|
||||
@@ -855,6 +929,19 @@ void ConfigureAndSetUpOneTrainerBattle(u8 trainerEventObjId, const u8 *trainerSc
|
||||
LockPlayerFieldControls();
|
||||
}
|
||||
|
||||
void ConfigureTwoTrainersBattle(u8 trainerObjEventId, const u8 *trainerScript)
|
||||
{
|
||||
gSelectedObjectEvent = trainerObjEventId;
|
||||
gSpecialVar_LastTalked = gObjectEvents[trainerObjEventId].localId;
|
||||
BattleSetup_ConfigureTrainerBattle(trainerScript + 1);
|
||||
}
|
||||
|
||||
void SetUpTwoTrainersBattle(void)
|
||||
{
|
||||
ScriptContext_SetupScript(EventScript_DoTrainerBattleFromApproach);
|
||||
LockPlayerFieldControls();
|
||||
}
|
||||
|
||||
bool32 GetTrainerFlagFromScriptPointer(const u8 *data)
|
||||
{
|
||||
u32 flag = TrainerBattleLoadArg16(data + 2);
|
||||
@@ -886,6 +973,8 @@ u16 Script_HasTrainerBeenFought(void)
|
||||
|
||||
void SetBattledTrainerFlag(void)
|
||||
{
|
||||
if (gTrainerBattleOpponent_B != 0)
|
||||
FlagSet(GetTrainerBFlag());
|
||||
FlagSet(GetTrainerAFlag());
|
||||
}
|
||||
|
||||
@@ -910,6 +999,9 @@ void BattleSetup_StartTrainerBattle(void)
|
||||
gBattleTypeFlags = (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_TRAINER);
|
||||
else
|
||||
gBattleTypeFlags = (BATTLE_TYPE_TRAINER);
|
||||
|
||||
if (GetTrainerBattleMode() == TRAINER_BATTLE_EARLY_RIVAL && GetRivalBattleFlags() & RIVAL_BATTLE_TUTORIAL)
|
||||
gBattleTypeFlags |= BATTLE_TYPE_FIRST_BATTLE;
|
||||
|
||||
sNoOfPossibleTrainerRetScripts = gNoOfApproachingTrainers;
|
||||
gNoOfApproachingTrainers = 0;
|
||||
@@ -935,16 +1027,6 @@ void BattleSetup_StartTrainerBattle_Debug(void)
|
||||
ScriptContext_Stop();
|
||||
}
|
||||
|
||||
void StartTrainerBattle(void)
|
||||
{
|
||||
gBattleTypeFlags = BATTLE_TYPE_TRAINER;
|
||||
if (GetTrainerBattleMode() == TRAINER_BATTLE_EARLY_RIVAL && GetRivalBattleFlags() & RIVAL_BATTLE_TUTORIAL)
|
||||
gBattleTypeFlags |= BATTLE_TYPE_FIRST_BATTLE;
|
||||
gMain.savedCallback = CB2_EndTrainerBattle;
|
||||
DoTrainerBattle();
|
||||
ScriptContext_Stop();
|
||||
}
|
||||
|
||||
static void SaveChangesToPlayerParty(void)
|
||||
{
|
||||
u8 i = 0, j = 0;
|
||||
@@ -1078,13 +1160,19 @@ void ShowTrainerCantBattleSpeech(void)
|
||||
|
||||
void PlayTrainerEncounterMusic(void)
|
||||
{
|
||||
u16 trainerId;
|
||||
u16 music;
|
||||
|
||||
if (gApproachingTrainerId == 0)
|
||||
trainerId = gTrainerBattleOpponent_A;
|
||||
else
|
||||
trainerId = gTrainerBattleOpponent_B;
|
||||
|
||||
if (!QL_IS_PLAYBACK_STATE
|
||||
&& sTrainerBattleMode != TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC
|
||||
&& sTrainerBattleMode != TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC)
|
||||
{
|
||||
switch (GetTrainerEncounterMusicId(gTrainerBattleOpponent_A))
|
||||
switch (GetTrainerEncounterMusicId(trainerId))
|
||||
{
|
||||
case TRAINER_ENCOUNTER_MUSIC_FEMALE:
|
||||
case TRAINER_ENCOUNTER_MUSIC_GIRL:
|
||||
@@ -1119,7 +1207,10 @@ static const u8 *ReturnEmptyStringIfNull(const u8 *string)
|
||||
|
||||
static const u8 *GetIntroSpeechOfApproachingTrainer(void)
|
||||
{
|
||||
return ReturnEmptyStringIfNull(sTrainerAIntroSpeech);
|
||||
if (gApproachingTrainerId == 0)
|
||||
return ReturnEmptyStringIfNull(sTrainerAIntroSpeech);
|
||||
else
|
||||
return ReturnEmptyStringIfNull(sTrainerBIntroSpeech);
|
||||
}
|
||||
|
||||
const u8 *GetTrainerALoseText(void)
|
||||
@@ -1130,6 +1221,12 @@ const u8 *GetTrainerALoseText(void)
|
||||
return gStringVar4;
|
||||
}
|
||||
|
||||
const u8 *GetTrainerBLoseText(void)
|
||||
{
|
||||
StringExpandPlaceholders(gStringVar4, ReturnEmptyStringIfNull(sTrainerBDefeatSpeech));
|
||||
return gStringVar4;
|
||||
}
|
||||
|
||||
const u8 *GetTrainerWonSpeech(void)
|
||||
{
|
||||
StringExpandPlaceholders(gStringVar4, ReturnEmptyStringIfNull(sTrainerVictorySpeech));
|
||||
|
||||
@@ -404,20 +404,19 @@ void SetEReaderTrainerGfxId(void)
|
||||
SetBattleTowerTrainerGfxId(BATTLE_TOWER_EREADER_TRAINER_ID);
|
||||
}
|
||||
|
||||
u8 GetBattleTowerTrainerFrontSpriteId(void)
|
||||
u8 GetBattleTowerTrainerFrontSpriteId(u16 trainerId)
|
||||
{
|
||||
if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId == BATTLE_TOWER_EREADER_TRAINER_ID)
|
||||
if (trainerId == BATTLE_TOWER_EREADER_TRAINER_ID)
|
||||
{
|
||||
return gFacilityClassToPicIndex[gSaveBlock2Ptr->battleTower.ereaderTrainer.trainerClass];
|
||||
}
|
||||
else if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
|
||||
else if (trainerId < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
|
||||
{
|
||||
// TODO: fix?
|
||||
return gFacilityClassToPicIndex[sBattleTowerTrainers[gSaveBlock2Ptr->battleTower.battleTowerTrainerId].trainerClass];
|
||||
return gFacilityClassToPicIndex[sBattleTowerTrainers[trainerId].trainerClass];
|
||||
}
|
||||
else
|
||||
{
|
||||
return gFacilityClassToPicIndex[gSaveBlock2Ptr->battleTower.records[gSaveBlock2Ptr->battleTower.battleTowerTrainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].trainerClass];
|
||||
return gFacilityClassToPicIndex[gSaveBlock2Ptr->battleTower.records[trainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].trainerClass];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -252,12 +252,10 @@ bool8 RS_IsRunningDisallowed(u8 r0)
|
||||
|
||||
bool32 IsRunningDisallowed(u8 metatileBehavior)
|
||||
{
|
||||
if (!gMapHeader.allowRunning)
|
||||
return TRUE;
|
||||
if (MetatileBehaviorForbidsBiking(metatileBehavior) != TRUE)
|
||||
return FALSE;
|
||||
else
|
||||
if ((OW_RUNNING_INDOORS == GEN_3 && !gMapHeader.allowRunning) || MetatileBehaviorForbidsBiking(metatileBehavior) == TRUE)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool8 MetatileBehaviorForbidsBiking(u8 metatileBehavior)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "gflib.h"
|
||||
#include "battle.h"
|
||||
#include "battle_records.h"
|
||||
#include "battle_setup.h"
|
||||
#include "cable_club.h"
|
||||
#include "event_data.h"
|
||||
#include "event_scripts.h"
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
#include "global.h"
|
||||
#include "task.h"
|
||||
#include "field_player_avatar.h"
|
||||
#include "event_object_movement.h"
|
||||
#include "script_movement.h"
|
||||
#include "event_data.h"
|
||||
#include "event_object_movement.h"
|
||||
#include "field_player_avatar.h"
|
||||
#include "script_movement.h"
|
||||
#include "task.h"
|
||||
#include "trainer_see.h"
|
||||
#include "constants/event_objects.h"
|
||||
|
||||
bool8 walkrun_is_standing_still(void)
|
||||
bool8 IsPlayerStandingStill(void)
|
||||
{
|
||||
if (gPlayerAvatar.tileTransitionState == 1)
|
||||
if (gPlayerAvatar.tileTransitionState == T_TILE_TRANSITION)
|
||||
return FALSE;
|
||||
else
|
||||
return TRUE;
|
||||
@@ -16,7 +17,7 @@ bool8 walkrun_is_standing_still(void)
|
||||
|
||||
void Task_WaitPlayerStopMoving(u8 taskId)
|
||||
{
|
||||
if (walkrun_is_standing_still())
|
||||
if (IsPlayerStandingStill())
|
||||
{
|
||||
HandleEnforcedLookDirectionOnPlayerStopMoving();
|
||||
DestroyTask(taskId);
|
||||
@@ -44,7 +45,7 @@ void Task_WaitPlayerAndTargetNPCStopMoving(u8 taskId)
|
||||
{
|
||||
struct Task *task = &gTasks[taskId];
|
||||
|
||||
if (task->data[0] == 0 && walkrun_is_standing_still() == TRUE)
|
||||
if (task->data[0] == 0 && IsPlayerStandingStill() == TRUE)
|
||||
{
|
||||
HandleEnforcedLookDirectionOnPlayerStopMoving();
|
||||
task->data[0] = 1;
|
||||
@@ -112,3 +113,78 @@ void Script_ClearHeldMovement(void)
|
||||
{
|
||||
ObjectEventClearHeldMovementIfActive(&gObjectEvents[gSelectedObjectEvent]);
|
||||
}
|
||||
|
||||
#define tPlayerFrozen data[0]
|
||||
#define tObjectFrozen data[1]
|
||||
#define tObjectId data[2]
|
||||
|
||||
// Freeze designated object and player once their movement is finished
|
||||
static void Task_FreezeObjectAndPlayer(u8 taskId)
|
||||
{
|
||||
struct Task *task = &gTasks[taskId];
|
||||
u8 objectEventId = task->tObjectId;
|
||||
|
||||
if (!task->tPlayerFrozen && IsPlayerStandingStill() == TRUE)
|
||||
{
|
||||
HandleEnforcedLookDirectionOnPlayerStopMoving();
|
||||
task->tPlayerFrozen = TRUE;
|
||||
}
|
||||
if (!task->tObjectFrozen && !gObjectEvents[objectEventId].singleMovementActive)
|
||||
{
|
||||
FreezeObjectEvent(&gObjectEvents[objectEventId]);
|
||||
task->tObjectFrozen = TRUE;
|
||||
}
|
||||
if (task->tPlayerFrozen && task->tObjectFrozen)
|
||||
DestroyTask(taskId);
|
||||
}
|
||||
|
||||
// Freeze all objects immediately except the player and the approaching trainers.
|
||||
// The approaching trainers and player are frozen once their movement is finished
|
||||
void FreezeForApproachingTrainers(void)
|
||||
{
|
||||
u8 trainerObjectId1, trainerObjectId2, taskId;
|
||||
struct ObjectEvent *followerObj = GetFollowerObject();
|
||||
trainerObjectId1 = GetChosenApproachingTrainerObjectEventId(0);
|
||||
|
||||
if (gNoOfApproachingTrainers == 2)
|
||||
{
|
||||
// Get second trainer, freeze all other objects
|
||||
trainerObjectId2 = GetChosenApproachingTrainerObjectEventId(1);
|
||||
FreezeObjectEventsExceptTwo(trainerObjectId1, trainerObjectId2);
|
||||
|
||||
// Start task to freeze trainer 1 (and player) after movement
|
||||
taskId = CreateTask(Task_FreezeObjectAndPlayer, 80);
|
||||
gTasks[taskId].tObjectId = trainerObjectId1;
|
||||
if (!gObjectEvents[trainerObjectId1].singleMovementActive)
|
||||
{
|
||||
FreezeObjectEvent(&gObjectEvents[trainerObjectId1]);
|
||||
gTasks[taskId].tObjectFrozen = TRUE;
|
||||
}
|
||||
|
||||
// Start task to freeze trainer 2 after movement
|
||||
taskId = CreateTask(Task_FreezeObjectAndPlayer, 81);
|
||||
gTasks[taskId].tObjectId = trainerObjectId2;
|
||||
if (!gObjectEvents[trainerObjectId2].singleMovementActive)
|
||||
{
|
||||
FreezeObjectEvent(&gObjectEvents[trainerObjectId2]);
|
||||
gTasks[taskId].tObjectFrozen = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FreezeObjectEventsExceptOne(trainerObjectId1);
|
||||
taskId = CreateTask(Task_FreezeObjectAndPlayer, 80);
|
||||
gTasks[taskId].tObjectId = trainerObjectId1;
|
||||
if (!gObjectEvents[trainerObjectId1].singleMovementActive)
|
||||
{
|
||||
FreezeObjectEvent(&gObjectEvents[trainerObjectId1]);
|
||||
gTasks[taskId].tObjectFrozen = TRUE;
|
||||
}
|
||||
}
|
||||
if (followerObj) // Unfreeze follower so it can move behind player
|
||||
UnfreezeObjectEvent(followerObj);
|
||||
}
|
||||
|
||||
#undef tPlayerFrozen
|
||||
#undef tObjectFrozen
|
||||
#undef tObjectId
|
||||
|
||||
@@ -1828,7 +1828,7 @@ u8 SpawnSpecialObjectEvent(struct ObjectEventTemplate *objectEventTemplate)
|
||||
return TrySpawnObjectEventTemplate(objectEventTemplate, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, cameraX, cameraY);
|
||||
}
|
||||
|
||||
int SpawnSpecialObjectEventParameterized(u16 graphicsId, u8 movementBehavior, u8 localId, s16 x, s16 y, u8 elevation)
|
||||
u32 SpawnSpecialObjectEventParameterized(u16 graphicsId, u8 movementBehavior, u8 localId, s16 x, s16 y, u8 elevation)
|
||||
{
|
||||
struct ObjectEventTemplate objectEventTemplate;
|
||||
|
||||
@@ -10281,6 +10281,19 @@ void FreezeObjectEventsExceptOne(u8 noFreeze)
|
||||
}
|
||||
}
|
||||
|
||||
// Used to freeze other objects except two trainers approaching for battle
|
||||
void FreezeObjectEventsExceptTwo(u8 objectEventId1, u8 objectEventId2)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
for(i = 0; i < OBJECT_EVENTS_COUNT; i++)
|
||||
{
|
||||
if(i != objectEventId1 && i != objectEventId2 &&
|
||||
gObjectEvents[i].active && i != gPlayerAvatar.objectEventId)
|
||||
FreezeObjectEvent(&gObjectEvents[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void UnfreezeObjectEvent(struct ObjectEvent *objectEvent)
|
||||
{
|
||||
if (objectEvent->active && objectEvent->frozen)
|
||||
|
||||
@@ -351,7 +351,7 @@ static void Task_ExitDoor(u8 taskId)
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
if (FieldFadeTransitionBackgroundEffectIsFinished() && walkrun_is_standing_still() && !FieldIsDoorAnimationRunning() && !FuncIsActiveTask(Task_BarnDoorWipe))
|
||||
if (FieldFadeTransitionBackgroundEffectIsFinished() && IsPlayerStandingStill() && !FieldIsDoorAnimationRunning() && !FuncIsActiveTask(Task_BarnDoorWipe))
|
||||
{
|
||||
ObjectEventClearHeldMovementIfFinished(&gObjectEvents[GetObjectEventIdByLocalIdAndMap(OBJ_EVENT_ID_PLAYER, 0, 0)]);
|
||||
task->data[0] = 4;
|
||||
@@ -367,7 +367,7 @@ static void Task_ExitDoor(u8 taskId)
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (walkrun_is_standing_still())
|
||||
if (IsPlayerStandingStill())
|
||||
{
|
||||
task->data[1] = FieldAnimateDoorClose(*x, *y);
|
||||
ObjectEventClearHeldMovementIfFinished(&gObjectEvents[GetObjectEventIdByLocalIdAndMap(OBJ_EVENT_ID_PLAYER, 0, 0)]);
|
||||
@@ -409,7 +409,7 @@ static void Task_ExitNonAnimDoor(u8 taskId)
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (walkrun_is_standing_still())
|
||||
if (IsPlayerStandingStill())
|
||||
{
|
||||
task->data[0] = 3;
|
||||
}
|
||||
@@ -747,7 +747,7 @@ static void Task_DoorWarp(u8 taskId)
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (walkrun_is_standing_still())
|
||||
if (IsPlayerStandingStill())
|
||||
{
|
||||
task->data[1] = FieldAnimateDoorClose(*xp, *yp - 1);
|
||||
ObjectEventClearHeldMovementIfFinished(&gObjectEvents[GetObjectEventIdByLocalIdAndMap(OBJ_EVENT_ID_PLAYER, 0, 0)]);
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
#include "event_data.h"
|
||||
#include "fldeff.h"
|
||||
#include "party_menu.h"
|
||||
#include "pokemon.h"
|
||||
#include "field_poison.h"
|
||||
#include "constants/battle.h"
|
||||
#include "constants/form_change_types.h"
|
||||
|
||||
static bool32 IsMonValidSpecies(struct Pokemon *pokemon)
|
||||
{
|
||||
@@ -33,7 +35,8 @@ static void FaintFromFieldPoison(u8 partyIdx)
|
||||
{
|
||||
struct Pokemon *pokemon = gPlayerParty + partyIdx;
|
||||
u32 status = STATUS1_NONE;
|
||||
AdjustFriendship(pokemon, FRIENDSHIP_EVENT_FAINT_OUTSIDE_BATTLE);
|
||||
if (OW_POISON_DAMAGE < GEN_4)
|
||||
AdjustFriendship(pokemon, FRIENDSHIP_EVENT_FAINT_OUTSIDE_BATTLE);
|
||||
SetMonData(pokemon, MON_DATA_STATUS, &status);
|
||||
GetMonData(pokemon, MON_DATA_NICKNAME, gStringVar1);
|
||||
StringGet_Nickname(gStringVar1);
|
||||
@@ -42,7 +45,7 @@ static void FaintFromFieldPoison(u8 partyIdx)
|
||||
static bool32 MonFaintedFromPoison(u8 partyIdx)
|
||||
{
|
||||
struct Pokemon *pokemon = gPlayerParty + partyIdx;
|
||||
if (IsMonValidSpecies(pokemon) && !GetMonData(pokemon, MON_DATA_HP) && GetAilmentFromStatus(GetMonData(pokemon, MON_DATA_STATUS)) == AILMENT_PSN)
|
||||
if (IsMonValidSpecies(pokemon) && GetMonData(pokemon, MON_DATA_HP) == ((OW_POISON_DAMAGE < GEN_4) ? 0 : 1) && GetAilmentFromStatus(GetMonData(pokemon, MON_DATA_STATUS)) == AILMENT_PSN)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
@@ -61,7 +64,7 @@ static void Task_TryFieldPoisonWhiteOut(u8 taskId)
|
||||
if (MonFaintedFromPoison(tPartyId))
|
||||
{
|
||||
FaintFromFieldPoison(tPartyId);
|
||||
ShowFieldMessage(gText_PkmnFainted3);
|
||||
ShowFieldMessage(gText_PkmnFainted_FldPsn);
|
||||
tState++;
|
||||
return;
|
||||
}
|
||||
@@ -101,9 +104,16 @@ s32 DoPoisonFieldEffect(void)
|
||||
{
|
||||
if (GetMonData(pokemon, MON_DATA_SANITY_HAS_SPECIES) && GetAilmentFromStatus(GetMonData(pokemon, MON_DATA_STATUS)) == AILMENT_PSN)
|
||||
{
|
||||
// Apply poison damage
|
||||
hp = GetMonData(pokemon, MON_DATA_HP);
|
||||
if (hp == 0 || --hp == 0)
|
||||
if (OW_POISON_DAMAGE < GEN_4 && (hp == 0 || --hp == 0))
|
||||
{
|
||||
TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_FAINT);
|
||||
numFainted++;
|
||||
}
|
||||
else if (OW_POISON_DAMAGE >= GEN_4 && (hp == 1 || --hp == 1))
|
||||
numFainted++;
|
||||
|
||||
SetMonData(pokemon, MON_DATA_HP, &hp);
|
||||
numPoisoned++;
|
||||
}
|
||||
|
||||
@@ -355,7 +355,7 @@ void AnimatePcTurnOff()
|
||||
|
||||
void SpawnCameraObject(void)
|
||||
{
|
||||
u8 objectEventId = SpawnSpecialObjectEventParameterized(OBJ_EVENT_GFX_YOUNGSTER, 8, OBJ_EVENT_ID_CAMERA, gSaveBlock1Ptr->pos.x + MAP_OFFSET, gSaveBlock1Ptr->pos.y + MAP_OFFSET, 3);
|
||||
u32 objectEventId = SpawnSpecialObjectEventParameterized(OBJ_EVENT_GFX_YOUNGSTER, 8, OBJ_EVENT_ID_CAMERA, gSaveBlock1Ptr->pos.x + MAP_OFFSET, gSaveBlock1Ptr->pos.y + MAP_OFFSET, 3);
|
||||
gObjectEvents[objectEventId].invisible = TRUE;
|
||||
CameraObjectSetFollowedObjectId(gObjectEvents[objectEventId].spriteId);
|
||||
}
|
||||
|
||||
@@ -546,13 +546,8 @@ u8 DoPokeballSendOutAnimation(u32 battler, s16 pan, u8 kindOfThrow)
|
||||
|
||||
static void Task_DoPokeballSendOutAnim(u8 taskId)
|
||||
{
|
||||
u16 throwCaseId;
|
||||
u8 battlerId;
|
||||
u16 itemId, ballId;
|
||||
u8 ballSpriteId;
|
||||
bool8 notSendOut = FALSE;
|
||||
s16 x, y;
|
||||
u32 gender;
|
||||
u32 throwCaseId, battlerId, ballId, ballSpriteId;
|
||||
bool32 notSendOut = FALSE;
|
||||
u32 throwXoffset = (B_ENEMY_THROW_BALLS >= GEN_6) ? 24 : 0;
|
||||
s32 throwYoffset = (B_ENEMY_THROW_BALLS >= GEN_6) ? -16 : 24;
|
||||
|
||||
@@ -564,20 +559,8 @@ static void Task_DoPokeballSendOutAnim(u8 taskId)
|
||||
|
||||
throwCaseId = gTasks[taskId].tThrowId;
|
||||
battlerId = gTasks[taskId].tBattler;
|
||||
|
||||
if (GetBattlerSide(battlerId) != B_SIDE_PLAYER)
|
||||
itemId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_POKEBALL);
|
||||
else
|
||||
itemId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_POKEBALL);
|
||||
|
||||
ballId = ItemIdToBallId(itemId);
|
||||
ballId = ItemIdToBallId(GetBattlerPokeballItemId(battlerId));
|
||||
LoadBallGfx(ballId);
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_LINK)
|
||||
gender = gLinkPlayers[GetBattlerMultiplayerId(battlerId)].gender;
|
||||
else
|
||||
gender = gSaveBlock2Ptr->playerGender;
|
||||
|
||||
ballSpriteId = CreateSprite(&gBallSpriteTemplates[ballId], 32, 80, 29);
|
||||
gSprites[ballSpriteId].data[0] = 0x80;
|
||||
gSprites[ballSpriteId].data[1] = 0;
|
||||
@@ -585,22 +568,15 @@ static void Task_DoPokeballSendOutAnim(u8 taskId)
|
||||
|
||||
switch (throwCaseId)
|
||||
{
|
||||
case POKEBALL_PLAYER_SENDOUT:
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_POKEDUDE)
|
||||
{
|
||||
x = 32;
|
||||
y = 64;
|
||||
}
|
||||
else
|
||||
{
|
||||
gender = !!gender; // something unknown got optimized out
|
||||
x = 48;
|
||||
y = 70;
|
||||
}
|
||||
|
||||
case POKEBALL_PLAYER_SLIDEIN: // don't actually send out, trigger the slide-in animation
|
||||
gBattlerTarget = battlerId;
|
||||
gSprites[ballSpriteId].x = x;
|
||||
gSprites[ballSpriteId].y = y;
|
||||
gSprites[ballSpriteId].callback = HandleBallAnimEnd;
|
||||
gSprites[ballSpriteId].invisible = TRUE;
|
||||
break;
|
||||
case POKEBALL_PLAYER_SENDOUT:
|
||||
gBattlerTarget = battlerId;
|
||||
gSprites[ballSpriteId].x = (gBattleTypeFlags & BATTLE_TYPE_POKEDUDE) ? 32 : 48;
|
||||
gSprites[ballSpriteId].y = (gBattleTypeFlags & BATTLE_TYPE_POKEDUDE) ? 64 : 70;
|
||||
gSprites[ballSpriteId].callback = SpriteCB_MonSendOut_1;
|
||||
DoPokeballSendOutSoundEffect(battlerId);
|
||||
break;
|
||||
@@ -1085,6 +1061,13 @@ static void HandleBallAnimEnd(struct Sprite *sprite)
|
||||
bool8 affineAnimEnded = FALSE;
|
||||
u8 battlerId = sprite->sBattler;
|
||||
|
||||
if (sprite->data[7] == POKEBALL_PLAYER_SLIDEIN)
|
||||
{
|
||||
gSprites[gBattlerSpriteIds[sprite->sBattler]].callback = SpriteCB_PlayerMonSlideIn;
|
||||
AnimateSprite(&gSprites[gBattlerSpriteIds[sprite->sBattler]]);
|
||||
gSprites[gBattlerSpriteIds[sprite->sBattler]].data[1] = 0x1000;
|
||||
}
|
||||
|
||||
gSprites[gBattlerSpriteIds[battlerId]].invisible = FALSE;
|
||||
if (sprite->animEnded)
|
||||
sprite->invisible = TRUE;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "data.h"
|
||||
#include "battle.h"
|
||||
#include "battle_anim.h"
|
||||
#include "battle_setup.h"
|
||||
#include "item.h"
|
||||
#include "event_data.h"
|
||||
#include "util.h"
|
||||
@@ -3255,22 +3256,45 @@ u8 GetMonsStateToDoubles(void)
|
||||
s32 i;
|
||||
CalculatePlayerPartyCount();
|
||||
|
||||
if (OW_DOUBLE_APPROACH_WITH_ONE_MON)
|
||||
return PLAYER_HAS_TWO_USABLE_MONS;
|
||||
|
||||
if (gPlayerPartyCount == 1)
|
||||
return gPlayerPartyCount; // PLAYER_HAS_ONE_MON
|
||||
|
||||
for (i = 0; i < gPlayerPartyCount; i++)
|
||||
{
|
||||
// FRLG changed the order of these checks, but there's no point to doing that
|
||||
// because of the requirement of all 3 of these checks.
|
||||
if (GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0
|
||||
&& GetMonData(&gPlayerParty[i], MON_DATA_SPECIES_OR_EGG, NULL) != SPECIES_NONE
|
||||
&& GetMonData(&gPlayerParty[i], MON_DATA_SPECIES_OR_EGG, NULL) != SPECIES_EGG)
|
||||
if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES_OR_EGG, NULL) != SPECIES_EGG
|
||||
&& GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0
|
||||
&& GetMonData(&gPlayerParty[i], MON_DATA_SPECIES_OR_EGG, NULL) != SPECIES_NONE)
|
||||
aliveCount++;
|
||||
}
|
||||
|
||||
return (aliveCount > 1) ? PLAYER_HAS_TWO_USABLE_MONS : PLAYER_HAS_ONE_USABLE_MON;
|
||||
}
|
||||
|
||||
u8 GetMonsStateToDoubles_2(void)
|
||||
{
|
||||
s32 aliveCount = 0;
|
||||
s32 i;
|
||||
|
||||
if (OW_DOUBLE_APPROACH_WITH_ONE_MON)
|
||||
return PLAYER_HAS_TWO_USABLE_MONS;
|
||||
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
u32 species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES_OR_EGG, NULL);
|
||||
if (species != SPECIES_EGG && species != SPECIES_NONE
|
||||
&& GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0)
|
||||
aliveCount++;
|
||||
}
|
||||
|
||||
if (aliveCount == 1)
|
||||
return PLAYER_HAS_ONE_MON; // may have more than one, but only one is alive
|
||||
|
||||
return (aliveCount > 1) ? PLAYER_HAS_TWO_USABLE_MONS : PLAYER_HAS_ONE_USABLE_MON;
|
||||
}
|
||||
|
||||
u16 GetAbilityBySpecies(u16 species, u8 abilityNum)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "gflib.h"
|
||||
#include "battle.h"
|
||||
#include "battle_anim.h"
|
||||
#include "battle_setup.h"
|
||||
#include "link.h"
|
||||
#include "overworld.h"
|
||||
#include "quest_log.h"
|
||||
|
||||
31
src/scrcmd.c
31
src/scrcmd.c
@@ -23,6 +23,7 @@
|
||||
#include "field_message_box.h"
|
||||
#include "new_menu_helpers.h"
|
||||
#include "script_menu.h"
|
||||
#include "trainer_see.h"
|
||||
#include "data.h"
|
||||
#include "field_specials.h"
|
||||
#include "constants/items.h"
|
||||
@@ -1887,7 +1888,7 @@ bool8 ScrCmd_trainerbattle(struct ScriptContext * ctx)
|
||||
|
||||
bool8 ScrCmd_dotrainerbattle(struct ScriptContext * ctx)
|
||||
{
|
||||
StartTrainerBattle();
|
||||
BattleSetup_StartTrainerBattle();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -2235,6 +2236,29 @@ bool8 ScrCmd_normalmsg(struct ScriptContext * ctx)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool8 ScrCmd_selectapproachingtrainer(struct ScriptContext *ctx)
|
||||
{
|
||||
gSelectedObjectEvent = GetCurrentApproachingTrainerObjectEventId();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool8 ScrCmd_lockfortrainer(struct ScriptContext *ctx)
|
||||
{
|
||||
if (IsUpdateLinkStateCBActive())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gObjectEvents[gSelectedObjectEvent].active)
|
||||
{
|
||||
FreezeForApproachingTrainers();
|
||||
SetupNativeScript(ctx, IsFreezePlayerFinished);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// This command will set a Pokémon's modernFatefulEncounter bit; there is no similar command to clear it.
|
||||
bool8 ScrCmd_setmonmodernfatefulencounter(struct ScriptContext * ctx)
|
||||
{
|
||||
@@ -2262,3 +2286,8 @@ bool8 ScrCmd_setmonmetlocation(struct ScriptContext * ctx)
|
||||
SetMonData(&gPlayerParty[partyIndex], MON_DATA_MET_LOCATION, &location);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void SetMovingNpcId(u16 npcId)
|
||||
{
|
||||
sMovingNpcId = npcId;
|
||||
}
|
||||
|
||||
@@ -318,6 +318,11 @@ const u8 gText_PkmnGainedExp[] = _("{STR_VAR_1} gained {STR_VAR_2} Exp. Points!{
|
||||
const u8 gText_PkmnGainedExpAndElevatedToLvVar3[] = _("{STR_VAR_1} gained {STR_VAR_2} Exp. Points\nand was elevated to Lv. {STR_VAR_3}!");
|
||||
const u8 gText_PkmnSnappedOutOfConfusion[] = _("{STR_VAR_1} snapped out of its\nconfusion.{PAUSE_UNTIL_PRESS}");
|
||||
const u8 gText_PkmnGotOverInfatuation[] = _("{STR_VAR_1} got over its\ninfatuation.{PAUSE_UNTIL_PRESS}");
|
||||
#if OW_POISON_DAMAGE < GEN_4
|
||||
const u8 gText_PkmnFainted_FldPsn[] = _("{STR_VAR_1} fainted…\p\n");
|
||||
#else
|
||||
const u8 gText_PkmnFainted_FldPsn[] = _("{STR_VAR_1} survived the poisoning.\nThe poison faded away!\p");
|
||||
#endif
|
||||
const u8 gText_OnlyPkmnForBattle[] = _("That's your only\nPOKéMON for battle.");
|
||||
ALIGNED(4) const u8 gText_PkmnCantBeTradedNow[] = _("That POKéMON can't be traded\nnow.");
|
||||
ALIGNED(4) const u8 gText_EggCantBeTradedNow[] = _("An EGG can't be traded now.");
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#include "global.h"
|
||||
#include "battle_setup.h"
|
||||
#include "event_data.h"
|
||||
#include "event_object_movement.h"
|
||||
#include "field_effect.h"
|
||||
#include "field_player_avatar.h"
|
||||
#include "quest_log.h"
|
||||
#include "script.h"
|
||||
#include "script_movement.h"
|
||||
#include "task.h"
|
||||
#include "trainer_see.h"
|
||||
#include "util.h"
|
||||
#include "constants/battle_setup.h"
|
||||
#include "constants/event_object_movement.h"
|
||||
@@ -13,9 +16,9 @@
|
||||
#include "constants/trainer_types.h"
|
||||
|
||||
typedef u8 (*TrainerApproachFunc)(struct ObjectEvent *, s16, s16, s16);
|
||||
typedef bool8 (*TrainerSeeFunc)(u8, struct Task *, struct ObjectEvent *);
|
||||
typedef bool32 (*TrainerSeeFunc)(u8, struct Task *, struct ObjectEvent *);
|
||||
|
||||
static bool8 CheckTrainer(u8 trainerObjId);
|
||||
static u32 CheckTrainer(u8 trainerObjId);
|
||||
static u8 GetTrainerApproachDistance(struct ObjectEvent * trainerObj);
|
||||
static u8 GetTrainerApproachDistanceSouth(struct ObjectEvent * trainerObj, s16 range, s16 x, s16 y);
|
||||
static u8 GetTrainerApproachDistanceNorth(struct ObjectEvent * trainerObj, s16 range, s16 x, s16 y);
|
||||
@@ -24,21 +27,21 @@ static u8 GetTrainerApproachDistanceEast(struct ObjectEvent * trainerObj, s16 ra
|
||||
static u8 CheckPathBetweenTrainerAndPlayer(struct ObjectEvent * trainerObj, u8 approachDistance, u8 facingDirection);
|
||||
static void TrainerApproachPlayer(struct ObjectEvent * trainerObj, u8 approachDistance);
|
||||
static void Task_RunTrainerSeeFuncList(u8 taskId);
|
||||
static bool8 TrainerSeeFunc_Dummy(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool8 TrainerSeeFunc_StartExclMark(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool8 TrainerSeeFunc_WaitExclMark(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool8 TrainerSeeFunc_TrainerApproach(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool8 TrainerSeeFunc_PrepareToEngage(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool8 TrainerSeeFunc_End(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool8 TrainerSeeFunc_BeginRemoveDisguise(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool8 TrainerSeeFunc_WaitRemoveDisguise(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool8 TrainerSeeFunc_TrainerInAshFacesPlayer(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool8 TrainerSeeFunc_BeginJumpOutOfAsh(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool8 TrainerSeeFunc_WaitJumpOutOfAsh(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool8 TrainerSeeFunc_EndJumpOutOfAsh(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool8 TrainerSeeFunc_OffscreenAboveTrainerCreateCameraObj(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool8 TrainerSeeFunc_OffscreenAboveTrainerCameraObjMoveUp(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool8 TrainerSeeFunc_OffscreenAboveTrainerCameraObjMoveDown(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool32 TrainerSeeFunc_Dummy(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool32 TrainerSeeFunc_StartExclMark(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool32 TrainerSeeFunc_WaitExclMark(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool32 TrainerSeeFunc_TrainerApproach(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool32 TrainerSeeFunc_PrepareToEngage(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool32 TrainerSeeFunc_End(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool32 TrainerSeeFunc_BeginRemoveDisguise(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool32 TrainerSeeFunc_WaitRemoveDisguise(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool32 TrainerSeeFunc_TrainerInAshFacesPlayer(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool32 TrainerSeeFunc_BeginJumpOutOfAsh(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool32 TrainerSeeFunc_WaitJumpOutOfAsh(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool32 TrainerSeeFunc_EndJumpOutOfAsh(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool32 TrainerSeeFunc_OffscreenAboveTrainerCreateCameraObj(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool32 TrainerSeeFunc_OffscreenAboveTrainerCameraObjMoveUp(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static bool32 TrainerSeeFunc_OffscreenAboveTrainerCameraObjMoveDown(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj);
|
||||
static void Task_DestroyTrainerApproachTask(u8 taskId);
|
||||
static void SpriteCB_TrainerIcons(struct Sprite *sprite);
|
||||
static void SetIconSpriteData(struct Sprite *sprite, u16 fldEffId, u8 spriteAnimNum);
|
||||
@@ -46,6 +49,11 @@ static void SetIconSpriteData(struct Sprite *sprite, u16 fldEffId, u8 spriteAnim
|
||||
// IWRAM common
|
||||
u16 gWhichTrainerToFaceAfterBattle;
|
||||
u8 gNoOfApproachingTrainers;
|
||||
struct ApproachingTrainer gApproachingTrainers[2];
|
||||
bool8 gTrainerApproachedPlayer;
|
||||
|
||||
// EWRAM
|
||||
EWRAM_DATA u8 gApproachingTrainerId = 0;
|
||||
|
||||
static const u16 sGfx_Emoticons[] = INCBIN_U16("graphics/misc/emoticons.4bpp");
|
||||
static const u8 sEmotion_Gfx[] = INCBIN_U8("graphics/misc/emotes.4bpp");
|
||||
@@ -62,25 +70,43 @@ static const TrainerApproachFunc sDirectionalApproachDistanceFuncs[] = {
|
||||
GetTrainerApproachDistanceEast
|
||||
};
|
||||
|
||||
enum {
|
||||
TRSEE_NONE,
|
||||
TRSEE_EXCLAMATION,
|
||||
TRSEE_EXCLAMATION_WAIT,
|
||||
TRSEE_MOVE_TO_PLAYER,
|
||||
TRSEE_PLAYER_FACE,
|
||||
TRSEE_PLAYER_FACE_WAIT,
|
||||
TRSEE_REVEAL_DISGUISE,
|
||||
TRSEE_REVEAL_DISGUISE_WAIT,
|
||||
TRSEE_REVEAL_BURIED,
|
||||
TRSEE_BURIED_POP_OUT,
|
||||
TRSEE_BURIED_JUMP,
|
||||
TRSEE_REVEAL_BURIED_WAIT,
|
||||
TRSEE_OFFSCREEN_CREATE_CAMERA,
|
||||
TRSEE_OFFSCREEN_MOVE_CAMERA_UP,
|
||||
TRSEE_OFFSCREEN_MOVE_CAMERA_DOWN,
|
||||
};
|
||||
|
||||
// bool8 func(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
// Returns TRUE to run the next func immediately
|
||||
// Returns FALSE to delay the next func to the next frame
|
||||
static const TrainerSeeFunc sTrainerSeeFuncList[] = {
|
||||
TrainerSeeFunc_Dummy,
|
||||
TrainerSeeFunc_StartExclMark,
|
||||
TrainerSeeFunc_WaitExclMark,
|
||||
TrainerSeeFunc_TrainerApproach,
|
||||
TrainerSeeFunc_PrepareToEngage,
|
||||
TrainerSeeFunc_End,
|
||||
TrainerSeeFunc_BeginRemoveDisguise,
|
||||
TrainerSeeFunc_WaitRemoveDisguise,
|
||||
TrainerSeeFunc_TrainerInAshFacesPlayer,
|
||||
TrainerSeeFunc_BeginJumpOutOfAsh,
|
||||
TrainerSeeFunc_WaitJumpOutOfAsh,
|
||||
TrainerSeeFunc_EndJumpOutOfAsh,
|
||||
TrainerSeeFunc_OffscreenAboveTrainerCreateCameraObj,
|
||||
TrainerSeeFunc_OffscreenAboveTrainerCameraObjMoveUp,
|
||||
TrainerSeeFunc_OffscreenAboveTrainerCameraObjMoveDown
|
||||
[TRSEE_NONE] = TrainerSeeFunc_Dummy,
|
||||
[TRSEE_EXCLAMATION] = TrainerSeeFunc_StartExclMark,
|
||||
[TRSEE_EXCLAMATION_WAIT] = TrainerSeeFunc_WaitExclMark,
|
||||
[TRSEE_MOVE_TO_PLAYER] = TrainerSeeFunc_TrainerApproach,
|
||||
[TRSEE_PLAYER_FACE] = TrainerSeeFunc_PrepareToEngage,
|
||||
[TRSEE_PLAYER_FACE_WAIT] = TrainerSeeFunc_End,
|
||||
[TRSEE_REVEAL_DISGUISE] = TrainerSeeFunc_BeginRemoveDisguise,
|
||||
[TRSEE_REVEAL_DISGUISE_WAIT] = TrainerSeeFunc_WaitRemoveDisguise,
|
||||
[TRSEE_REVEAL_BURIED] = TrainerSeeFunc_TrainerInAshFacesPlayer,
|
||||
[TRSEE_BURIED_POP_OUT] = TrainerSeeFunc_BeginJumpOutOfAsh,
|
||||
[TRSEE_BURIED_JUMP] = TrainerSeeFunc_WaitJumpOutOfAsh,
|
||||
[TRSEE_REVEAL_BURIED_WAIT] = TrainerSeeFunc_EndJumpOutOfAsh,
|
||||
[TRSEE_OFFSCREEN_CREATE_CAMERA] = TrainerSeeFunc_OffscreenAboveTrainerCreateCameraObj,
|
||||
[TRSEE_OFFSCREEN_MOVE_CAMERA_UP] = TrainerSeeFunc_OffscreenAboveTrainerCameraObjMoveUp,
|
||||
[TRSEE_OFFSCREEN_MOVE_CAMERA_DOWN] = TrainerSeeFunc_OffscreenAboveTrainerCameraObjMoveDown,
|
||||
};
|
||||
|
||||
static const TrainerSeeFunc sTrainerSeeFuncList2[] = {
|
||||
@@ -96,33 +122,87 @@ bool8 CheckForTrainersWantingBattle(void)
|
||||
if (QL_IsTrainerSightDisabled() == TRUE)
|
||||
return FALSE;
|
||||
|
||||
if (FlagGet(OW_FLAG_NO_TRAINER_SEE))
|
||||
return FALSE;
|
||||
|
||||
gNoOfApproachingTrainers = 0;
|
||||
gApproachingTrainerId = 0;
|
||||
|
||||
for (i = 0; i < OBJECT_EVENTS_COUNT; i++)
|
||||
{
|
||||
if (gObjectEvents[i].active
|
||||
&& (gObjectEvents[i].trainerType == TRAINER_TYPE_NORMAL
|
||||
|| gObjectEvents[i].trainerType == TRAINER_TYPE_BURIED)
|
||||
&& CheckTrainer(i))
|
||||
return TRUE;
|
||||
u8 numTrainers;
|
||||
|
||||
if (!gObjectEvents[i].active)
|
||||
continue;
|
||||
if (gObjectEvents[i].trainerType != TRAINER_TYPE_NORMAL && gObjectEvents[i].trainerType != TRAINER_TYPE_BURIED)
|
||||
continue;
|
||||
|
||||
numTrainers = CheckTrainer(i);
|
||||
if (numTrainers == 2)
|
||||
break;
|
||||
|
||||
if (numTrainers == 0)
|
||||
continue;
|
||||
|
||||
if (gNoOfApproachingTrainers > 1)
|
||||
break;
|
||||
if (GetMonsStateToDoubles_2() != PLAYER_HAS_TWO_USABLE_MONS) // one trainer found and cant have a double battle
|
||||
break;
|
||||
}
|
||||
|
||||
if (gNoOfApproachingTrainers == 1)
|
||||
{
|
||||
ResetTrainerOpponentIds();
|
||||
ConfigureAndSetUpOneTrainerBattle(gApproachingTrainers[gNoOfApproachingTrainers - 1].objectEventId,
|
||||
gApproachingTrainers[gNoOfApproachingTrainers - 1].trainerScriptPtr);
|
||||
gTrainerApproachedPlayer = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
else if (gNoOfApproachingTrainers == 2)
|
||||
{
|
||||
ResetTrainerOpponentIds();
|
||||
for (i = 0; i < gNoOfApproachingTrainers; i++, gApproachingTrainerId++)
|
||||
{
|
||||
ConfigureTwoTrainersBattle(gApproachingTrainers[i].objectEventId,
|
||||
gApproachingTrainers[i].trainerScriptPtr);
|
||||
}
|
||||
SetUpTwoTrainersBattle();
|
||||
gApproachingTrainerId = 0;
|
||||
gTrainerApproachedPlayer = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gTrainerApproachedPlayer = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool8 CheckTrainer(u8 trainerObjId)
|
||||
static u32 CheckTrainer(u8 trainerObjId)
|
||||
{
|
||||
const u8 *script = GetObjectEventScriptPointerByObjectEventId(trainerObjId);
|
||||
u8 approachDistance;
|
||||
u32 numTrainers = 1;
|
||||
u32 approachDistance;
|
||||
if (GetTrainerFlagFromScriptPointer(script))
|
||||
return FALSE;
|
||||
approachDistance = GetTrainerApproachDistance(&gObjectEvents[trainerObjId]);
|
||||
if (approachDistance != 0)
|
||||
{
|
||||
if (script[1] == TRAINER_BATTLE_DOUBLE && GetMonsStateToDoubles())
|
||||
return FALSE;
|
||||
ConfigureAndSetUpOneTrainerBattle(trainerObjId, script);
|
||||
{
|
||||
if (GetMonsStateToDoubles_2() != PLAYER_HAS_TWO_USABLE_MONS)
|
||||
return 0;
|
||||
numTrainers = 2;
|
||||
}
|
||||
|
||||
gApproachingTrainers[gNoOfApproachingTrainers].objectEventId = trainerObjId;
|
||||
gApproachingTrainers[gNoOfApproachingTrainers].trainerScriptPtr = script;
|
||||
gApproachingTrainers[gNoOfApproachingTrainers].radius = approachDistance;
|
||||
TrainerApproachPlayer(&gObjectEvents[trainerObjId], approachDistance - 1);
|
||||
return TRUE;
|
||||
gNoOfApproachingTrainers++;
|
||||
return numTrainers;
|
||||
}
|
||||
return FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 GetTrainerApproachDistance(struct ObjectEvent *trainerObj)
|
||||
@@ -238,38 +318,41 @@ static u8 CheckPathBetweenTrainerAndPlayer(struct ObjectEvent *trainerObj, u8 ap
|
||||
}
|
||||
|
||||
#define tFuncId data[0]
|
||||
#define tTrainerObjHi data[1]
|
||||
#define tTrainerObjLo data[2]
|
||||
#define tTrainerRange data[3]
|
||||
#define tOutOfAshSpriteId data[4]
|
||||
#define tData5 data[5]
|
||||
|
||||
#define TaskGetTrainerObj(dest, task) do { \
|
||||
(dest) = (struct ObjectEvent *)(((task)->tTrainerObjHi << 16) | ((u16)(task)->tTrainerObjLo)); \
|
||||
} while (0)
|
||||
#define tTrainerObjectEventId data[7]
|
||||
|
||||
static void TrainerApproachPlayer(struct ObjectEvent * trainerObj, u8 approachDistance)
|
||||
{
|
||||
u8 taskId = CreateTask(Task_RunTrainerSeeFuncList, 80);
|
||||
struct Task *task = &gTasks[taskId];
|
||||
task->tTrainerObjHi = ((uintptr_t)trainerObj) >> 16;
|
||||
task->tTrainerObjLo = (uintptr_t)trainerObj;
|
||||
struct Task *task;
|
||||
|
||||
gApproachingTrainers[gNoOfApproachingTrainers].taskId = CreateTask(Task_RunTrainerSeeFuncList, 80);
|
||||
task = &gTasks[gApproachingTrainers[gNoOfApproachingTrainers].taskId];
|
||||
task->tTrainerRange = approachDistance;
|
||||
task->tTrainerObjectEventId = gApproachingTrainers[gNoOfApproachingTrainers].objectEventId;
|
||||
}
|
||||
|
||||
static void StartTrainerApproachWithFollowupTask(TaskFunc taskFunc)
|
||||
static void StartTrainerApproachWithFollowupTask(TaskFunc followupFunc)
|
||||
{
|
||||
u8 taskId = FindTaskIdByFunc(Task_RunTrainerSeeFuncList);
|
||||
SetTaskFuncWithFollowupFunc(taskId, Task_RunTrainerSeeFuncList, taskFunc);
|
||||
u8 taskId;
|
||||
TaskFunc taskFunc;
|
||||
|
||||
if (gApproachingTrainerId == 0)
|
||||
taskId = gApproachingTrainers[0].taskId;
|
||||
else
|
||||
taskId = gApproachingTrainers[1].taskId;
|
||||
|
||||
taskFunc = Task_RunTrainerSeeFuncList;
|
||||
SetTaskFuncWithFollowupFunc(taskId, taskFunc, followupFunc);
|
||||
gTasks[taskId].tFuncId = 1;
|
||||
Task_RunTrainerSeeFuncList(taskId);
|
||||
taskFunc(taskId);
|
||||
}
|
||||
|
||||
static void Task_RunTrainerSeeFuncList(u8 taskId)
|
||||
{
|
||||
struct Task *task = &gTasks[taskId];
|
||||
struct ObjectEvent * trainerObj;
|
||||
TaskGetTrainerObj(trainerObj, task);
|
||||
struct ObjectEvent *trainerObj = &gObjectEvents[task->tTrainerObjectEventId];
|
||||
|
||||
if (!trainerObj->active)
|
||||
{
|
||||
@@ -277,19 +360,18 @@ static void Task_RunTrainerSeeFuncList(u8 taskId)
|
||||
}
|
||||
else
|
||||
{
|
||||
while (sTrainerSeeFuncList[task->tFuncId](taskId, task, trainerObj))
|
||||
;
|
||||
while (sTrainerSeeFuncList[task->tFuncId](taskId, task, trainerObj));
|
||||
}
|
||||
}
|
||||
|
||||
// TrainerSeeFuncs
|
||||
|
||||
static bool8 TrainerSeeFunc_Dummy(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
static bool32 TrainerSeeFunc_Dummy(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool8 TrainerSeeFunc_StartExclMark(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
static bool32 TrainerSeeFunc_StartExclMark(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
{
|
||||
u8 action;
|
||||
// FRLG introduces trainers who can see the player from offscreen above.
|
||||
@@ -309,7 +391,7 @@ static bool8 TrainerSeeFunc_StartExclMark(u8 taskId, struct Task *task, struct O
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool8 TrainerSeeFunc_WaitExclMark(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
static bool32 TrainerSeeFunc_WaitExclMark(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
{
|
||||
if (FieldEffectActiveListContains(FLDEFF_EXCLAMATION_MARK_ICON))
|
||||
{
|
||||
@@ -326,7 +408,7 @@ static bool8 TrainerSeeFunc_WaitExclMark(u8 taskId, struct Task *task, struct Ob
|
||||
}
|
||||
}
|
||||
|
||||
static bool8 TrainerSeeFunc_TrainerApproach(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
static bool32 TrainerSeeFunc_TrainerApproach(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
{
|
||||
if (!ObjectEventIsMovementOverridden(trainerObj) || ObjectEventClearHeldMovementIfFinished(trainerObj))
|
||||
{
|
||||
@@ -344,7 +426,7 @@ static bool8 TrainerSeeFunc_TrainerApproach(u8 taskId, struct Task *task, struct
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool8 TrainerSeeFunc_PrepareToEngage(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
static bool32 TrainerSeeFunc_PrepareToEngage(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
{
|
||||
struct ObjectEvent *playerObj;
|
||||
|
||||
@@ -360,13 +442,12 @@ static bool8 TrainerSeeFunc_PrepareToEngage(u8 taskId, struct Task *task, struct
|
||||
return FALSE;
|
||||
|
||||
CancelPlayerForcedMovement();
|
||||
// Uncomment to have player turn to face their opponent
|
||||
// ObjectEventSetHeldMovement(&gObjectEvents[gPlayerAvatar.objectEventId], GetFaceDirectionMovementAction(GetOppositeDirection(trainerObj->facingDirection)));
|
||||
ObjectEventSetHeldMovement(&gObjectEvents[gPlayerAvatar.objectEventId], GetFaceDirectionMovementAction(GetOppositeDirection(trainerObj->facingDirection)));
|
||||
task->tFuncId++;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool8 TrainerSeeFunc_End(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
static bool32 TrainerSeeFunc_End(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
{
|
||||
struct ObjectEvent *playerObj = &gObjectEvents[gPlayerAvatar.objectEventId];
|
||||
|
||||
@@ -377,7 +458,7 @@ static bool8 TrainerSeeFunc_End(u8 taskId, struct Task *task, struct ObjectEvent
|
||||
}
|
||||
|
||||
// Jumps here if disguised. Not used in FRLG.
|
||||
static bool8 TrainerSeeFunc_BeginRemoveDisguise(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
static bool32 TrainerSeeFunc_BeginRemoveDisguise(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
{
|
||||
if (!ObjectEventIsMovementOverridden(trainerObj)
|
||||
|| ObjectEventClearHeldMovementIfFinished(trainerObj))
|
||||
@@ -388,7 +469,7 @@ static bool8 TrainerSeeFunc_BeginRemoveDisguise(u8 taskId, struct Task *task, st
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool8 TrainerSeeFunc_WaitRemoveDisguise(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
static bool32 TrainerSeeFunc_WaitRemoveDisguise(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
{
|
||||
if (ObjectEventClearHeldMovementIfFinished(trainerObj))
|
||||
task->tFuncId = 3;
|
||||
@@ -397,7 +478,7 @@ static bool8 TrainerSeeFunc_WaitRemoveDisguise(u8 taskId, struct Task *task, str
|
||||
}
|
||||
|
||||
// Jump here if buried in ash. Not used in FRLG.
|
||||
static bool8 TrainerSeeFunc_TrainerInAshFacesPlayer(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
static bool32 TrainerSeeFunc_TrainerInAshFacesPlayer(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
{
|
||||
if (!ObjectEventIsMovementOverridden(trainerObj)
|
||||
|| ObjectEventClearHeldMovementIfFinished(trainerObj))
|
||||
@@ -408,7 +489,7 @@ static bool8 TrainerSeeFunc_TrainerInAshFacesPlayer(u8 taskId, struct Task *task
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool8 TrainerSeeFunc_BeginJumpOutOfAsh(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
static bool32 TrainerSeeFunc_BeginJumpOutOfAsh(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
{
|
||||
if (ObjectEventCheckHeldMovementStatus(trainerObj))
|
||||
{
|
||||
@@ -422,7 +503,7 @@ static bool8 TrainerSeeFunc_BeginJumpOutOfAsh(u8 taskId, struct Task *task, stru
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool8 TrainerSeeFunc_WaitJumpOutOfAsh(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
static bool32 TrainerSeeFunc_WaitJumpOutOfAsh(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
{
|
||||
struct Sprite *sprite;
|
||||
|
||||
@@ -441,7 +522,7 @@ static bool8 TrainerSeeFunc_WaitJumpOutOfAsh(u8 taskId, struct Task *task, struc
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool8 TrainerSeeFunc_EndJumpOutOfAsh(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
||||
static bool32 TrainerSeeFunc_EndJumpOutOfAsh(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
||||
{
|
||||
if (!FieldEffectActiveListContains(FLDEFF_POP_OUT_OF_ASH))
|
||||
task->tFuncId = 3;
|
||||
@@ -450,9 +531,9 @@ static bool8 TrainerSeeFunc_EndJumpOutOfAsh(u8 taskId, struct Task *task, struct
|
||||
}
|
||||
|
||||
// FRLG exclusive: Scroll the camera up to reveal an offscreen above trainer
|
||||
static bool8 TrainerSeeFunc_OffscreenAboveTrainerCreateCameraObj(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
||||
static bool32 TrainerSeeFunc_OffscreenAboveTrainerCreateCameraObj(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
||||
{
|
||||
int specialObjectId;
|
||||
u32 specialObjectId;
|
||||
task->tData5 = 0;
|
||||
specialObjectId = SpawnSpecialObjectEventParameterized(OBJ_EVENT_GFX_YOUNGSTER, 7, OBJ_EVENT_ID_CAMERA, gSaveBlock1Ptr->pos.x + 7, gSaveBlock1Ptr->pos.y + 7, 3);
|
||||
gObjectEvents[specialObjectId].invisible = TRUE;
|
||||
@@ -461,7 +542,7 @@ static bool8 TrainerSeeFunc_OffscreenAboveTrainerCreateCameraObj(u8 taskId, stru
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool8 TrainerSeeFunc_OffscreenAboveTrainerCameraObjMoveUp(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
||||
static bool32 TrainerSeeFunc_OffscreenAboveTrainerCameraObjMoveUp(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
||||
{
|
||||
u8 specialObjectId;
|
||||
TryGetObjectEventIdByLocalIdAndMap(OBJ_EVENT_ID_CAMERA, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &specialObjectId);
|
||||
@@ -484,7 +565,7 @@ static bool8 TrainerSeeFunc_OffscreenAboveTrainerCameraObjMoveUp(u8 taskId, stru
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool8 TrainerSeeFunc_OffscreenAboveTrainerCameraObjMoveDown(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
static bool32 TrainerSeeFunc_OffscreenAboveTrainerCameraObjMoveDown(u8 taskId, struct Task *task, struct ObjectEvent * trainerObj)
|
||||
{
|
||||
u8 specialObjectId;
|
||||
TryGetObjectEventIdByLocalIdAndMap(OBJ_EVENT_ID_CAMERA, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &specialObjectId);
|
||||
@@ -921,3 +1002,44 @@ static void SpriteCB_TrainerIcons(struct Sprite *sprite)
|
||||
#undef sData3
|
||||
#undef sData4
|
||||
#undef sFldEffId
|
||||
|
||||
u8 GetCurrentApproachingTrainerObjectEventId(void)
|
||||
{
|
||||
if (gApproachingTrainerId == 0)
|
||||
return gApproachingTrainers[0].objectEventId;
|
||||
else
|
||||
return gApproachingTrainers[1].objectEventId;
|
||||
}
|
||||
|
||||
u8 GetChosenApproachingTrainerObjectEventId(u8 arrayId)
|
||||
{
|
||||
if (arrayId >= ARRAY_COUNT(gApproachingTrainers))
|
||||
return 0;
|
||||
else if (arrayId == 0)
|
||||
return gApproachingTrainers[0].objectEventId;
|
||||
else
|
||||
return gApproachingTrainers[1].objectEventId;
|
||||
}
|
||||
|
||||
void TryPrepareSecondApproachingTrainer(void)
|
||||
{
|
||||
if (gNoOfApproachingTrainers == 2)
|
||||
{
|
||||
if (gApproachingTrainerId == 0)
|
||||
{
|
||||
gApproachingTrainerId++;
|
||||
gSpecialVar_Result = TRUE;
|
||||
UnfreezeObjectEvents();
|
||||
FreezeObjectEventsExceptOne(gApproachingTrainers[1].objectEventId);
|
||||
}
|
||||
else
|
||||
{
|
||||
gApproachingTrainerId = 0;
|
||||
gSpecialVar_Result = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gSpecialVar_Result = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "global.h"
|
||||
#include "gflib.h"
|
||||
#include "battle.h"
|
||||
#include "battle_setup.h"
|
||||
#include "link.h"
|
||||
#include "menu.h"
|
||||
#include "new_menu_helpers.h"
|
||||
|
||||
@@ -603,7 +603,7 @@ static void Task_ResetObjectsRematchWantedState(u8 taskId)
|
||||
struct Task *task = &gTasks[taskId];
|
||||
u8 i;
|
||||
|
||||
if (task->data[0] == 0 && walkrun_is_standing_still() == TRUE)
|
||||
if (task->data[0] == 0 && IsPlayerStandingStill() == TRUE)
|
||||
{
|
||||
HandleEnforcedLookDirectionOnPlayerStopMoving();
|
||||
task->data[0] = 1;
|
||||
|
||||
Reference in New Issue
Block a user