2017-12-01 21:25:13 +01:00
|
|
|
#include "global.h"
|
|
|
|
#include "battle_setup.h"
|
2018-11-13 14:19:04 +00:00
|
|
|
#include "event_data.h"
|
2018-06-11 08:34:19 -05:00
|
|
|
#include "event_object_movement.h"
|
2018-11-13 14:19:04 +00:00
|
|
|
#include "field_effect.h"
|
2017-12-18 23:26:44 +01:00
|
|
|
#include "field_player_avatar.h"
|
2018-11-13 14:19:04 +00:00
|
|
|
#include "pokemon.h"
|
2017-12-18 23:26:44 +01:00
|
|
|
#include "script.h"
|
|
|
|
#include "script_movement.h"
|
2018-11-13 14:19:04 +00:00
|
|
|
#include "sprite.h"
|
|
|
|
#include "task.h"
|
|
|
|
#include "trainer_see.h"
|
2019-01-13 20:50:08 +01:00
|
|
|
#include "trainer_hill.h"
|
2018-11-13 14:19:04 +00:00
|
|
|
#include "util.h"
|
2018-11-18 17:52:22 +01:00
|
|
|
#include "battle_pyramid.h"
|
2019-01-20 10:11:45 -06:00
|
|
|
#include "constants/battle_setup.h"
|
2019-11-01 03:41:55 -04:00
|
|
|
#include "constants/event_objects.h"
|
2019-11-21 14:03:35 -05:00
|
|
|
#include "constants/event_object_movement.h"
|
2018-11-13 14:19:04 +00:00
|
|
|
#include "constants/field_effects.h"
|
2020-04-21 15:53:48 -04:00
|
|
|
#include "constants/trainer_types.h"
|
2017-12-01 21:25:13 +01:00
|
|
|
|
|
|
|
// this file's functions
|
2019-11-20 22:55:44 -05:00
|
|
|
static u8 CheckTrainer(u8 objectEventId);
|
|
|
|
static u8 GetTrainerApproachDistance(struct ObjectEvent *trainerObj);
|
|
|
|
static u8 CheckPathBetweenTrainerAndPlayer(struct ObjectEvent *trainerObj, u8 approachDistance, u8 direction);
|
2021-01-26 04:41:13 -05:00
|
|
|
static void InitTrainerApproachTask(struct ObjectEvent *trainerObj, u8 range);
|
2017-12-19 17:18:44 +01:00
|
|
|
static void Task_RunTrainerSeeFuncList(u8 taskId);
|
2021-01-26 04:41:13 -05:00
|
|
|
static void Task_EndTrainerApproach(u8 taskId);
|
2017-12-19 17:18:44 +01:00
|
|
|
static void SetIconSpriteData(struct Sprite *sprite, u16 fldEffId, u8 spriteAnimNum);
|
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
static u8 GetTrainerApproachDistanceSouth(struct ObjectEvent *trainerObj, s16 range, s16 x, s16 y);
|
|
|
|
static u8 GetTrainerApproachDistanceNorth(struct ObjectEvent *trainerObj, s16 range, s16 x, s16 y);
|
|
|
|
static u8 GetTrainerApproachDistanceWest(struct ObjectEvent *trainerObj, s16 range, s16 x, s16 y);
|
|
|
|
static u8 GetTrainerApproachDistanceEast(struct ObjectEvent *trainerObj, s16 range, s16 x, s16 y);
|
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
static bool8 TrainerSeeIdle(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj);
|
2019-11-20 22:55:44 -05:00
|
|
|
static bool8 TrainerExclamationMark(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj);
|
|
|
|
static bool8 WaitTrainerExclamationMark(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj);
|
|
|
|
static bool8 TrainerMoveToPlayer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj);
|
|
|
|
static bool8 PlayerFaceApproachingTrainer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj);
|
|
|
|
static bool8 WaitPlayerFaceApproachingTrainer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj);
|
|
|
|
static bool8 RevealDisguisedTrainer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj);
|
|
|
|
static bool8 WaitRevealDisguisedTrainer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj);
|
2021-02-14 19:25:23 +00:00
|
|
|
static bool8 RevealBuriedTrainer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj);
|
|
|
|
static bool8 PopOutOfAshBuriedTrainer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj);
|
|
|
|
static bool8 JumpInPlaceBuriedTrainer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj);
|
|
|
|
static bool8 WaitRevealBuriedTrainer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj);
|
2017-12-19 17:18:44 +01:00
|
|
|
|
|
|
|
static void SpriteCB_TrainerIcons(struct Sprite *sprite);
|
2017-12-18 19:35:50 +01:00
|
|
|
|
2017-12-19 17:33:07 +01:00
|
|
|
// IWRAM common
|
2019-11-01 03:41:55 -04:00
|
|
|
u16 gWhichTrainerToFaceAfterBattle;
|
|
|
|
u8 gPostBattleMovementScript[4];
|
2017-12-19 17:33:07 +01:00
|
|
|
struct ApproachingTrainer gApproachingTrainers[2];
|
|
|
|
u8 gNoOfApproachingTrainers;
|
2019-11-01 03:41:55 -04:00
|
|
|
bool8 gTrainerApproachedPlayer;
|
2017-12-19 17:33:07 +01:00
|
|
|
|
|
|
|
// EWRAM
|
|
|
|
EWRAM_DATA u8 gApproachingTrainerId = 0;
|
|
|
|
|
2017-12-18 19:35:50 +01:00
|
|
|
// const rom data
|
2022-01-14 12:29:30 -05:00
|
|
|
static const u8 sEmotion_ExclamationMarkGfx[] = INCBIN_U8("graphics/field_effects/pics/emotion_exclamation.4bpp");
|
|
|
|
static const u8 sEmotion_QuestionMarkGfx[] = INCBIN_U8("graphics/field_effects/pics/emotion_question.4bpp");
|
|
|
|
static const u8 sEmotion_HeartGfx[] = INCBIN_U8("graphics/field_effects/pics/emotion_heart.4bpp");
|
2017-12-18 19:35:50 +01:00
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
static u8 (*const sDirectionalApproachDistanceFuncs[])(struct ObjectEvent *trainerObj, s16 range, s16 x, s16 y) =
|
2017-12-18 19:35:50 +01:00
|
|
|
{
|
|
|
|
GetTrainerApproachDistanceSouth,
|
|
|
|
GetTrainerApproachDistanceNorth,
|
|
|
|
GetTrainerApproachDistanceWest,
|
|
|
|
GetTrainerApproachDistanceEast,
|
|
|
|
};
|
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
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,
|
2021-02-14 19:25:23 +00:00
|
|
|
TRSEE_REVEAL_BURIED,
|
|
|
|
TRSEE_BURIED_POP_OUT,
|
|
|
|
TRSEE_BURIED_JUMP,
|
|
|
|
TRSEE_REVEAL_BURIED_WAIT,
|
2021-01-26 04:41:13 -05:00
|
|
|
};
|
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
static bool8 (*const sTrainerSeeFuncList[])(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj) =
|
2017-12-18 19:35:50 +01:00
|
|
|
{
|
2021-01-26 04:41:13 -05:00
|
|
|
[TRSEE_NONE] = TrainerSeeIdle,
|
|
|
|
[TRSEE_EXCLAMATION] = TrainerExclamationMark,
|
|
|
|
[TRSEE_EXCLAMATION_WAIT] = WaitTrainerExclamationMark,
|
|
|
|
[TRSEE_MOVE_TO_PLAYER] = TrainerMoveToPlayer,
|
|
|
|
[TRSEE_PLAYER_FACE] = PlayerFaceApproachingTrainer,
|
|
|
|
[TRSEE_PLAYER_FACE_WAIT] = WaitPlayerFaceApproachingTrainer,
|
|
|
|
[TRSEE_REVEAL_DISGUISE] = RevealDisguisedTrainer,
|
|
|
|
[TRSEE_REVEAL_DISGUISE_WAIT] = WaitRevealDisguisedTrainer,
|
2021-02-14 19:25:23 +00:00
|
|
|
[TRSEE_REVEAL_BURIED] = RevealBuriedTrainer,
|
|
|
|
[TRSEE_BURIED_POP_OUT] = PopOutOfAshBuriedTrainer,
|
|
|
|
[TRSEE_BURIED_JUMP] = JumpInPlaceBuriedTrainer,
|
|
|
|
[TRSEE_REVEAL_BURIED_WAIT] = WaitRevealBuriedTrainer,
|
2017-12-18 19:35:50 +01:00
|
|
|
};
|
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
static bool8 (*const sTrainerSeeFuncList2[])(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj) =
|
2017-12-18 19:35:50 +01:00
|
|
|
{
|
2021-02-14 19:25:23 +00:00
|
|
|
RevealBuriedTrainer,
|
|
|
|
PopOutOfAshBuriedTrainer,
|
|
|
|
JumpInPlaceBuriedTrainer,
|
|
|
|
WaitRevealBuriedTrainer,
|
2017-12-18 19:35:50 +01:00
|
|
|
};
|
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
static const struct OamData sOamData_Icons =
|
2017-12-18 19:35:50 +01:00
|
|
|
{
|
|
|
|
.y = 0,
|
2019-12-04 15:25:13 -05:00
|
|
|
.affineMode = ST_OAM_AFFINE_OFF,
|
|
|
|
.objMode = ST_OAM_OBJ_NORMAL,
|
2022-07-29 21:27:39 -04:00
|
|
|
.mosaic = FALSE,
|
2019-12-04 15:25:13 -05:00
|
|
|
.bpp = ST_OAM_4BPP,
|
2019-03-11 03:12:15 -04:00
|
|
|
.shape = SPRITE_SHAPE(16x16),
|
2017-12-18 19:35:50 +01:00
|
|
|
.x = 0,
|
|
|
|
.matrixNum = 0,
|
2019-03-11 03:12:15 -04:00
|
|
|
.size = SPRITE_SIZE(16x16),
|
2017-12-18 19:35:50 +01:00
|
|
|
.tileNum = 0,
|
|
|
|
.priority = 1,
|
|
|
|
.paletteNum = 0,
|
|
|
|
.affineParam = 0,
|
|
|
|
};
|
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
static const struct SpriteFrameImage sSpriteImageTable_ExclamationQuestionMark[] =
|
2017-12-18 19:35:50 +01:00
|
|
|
{
|
2019-03-11 03:12:15 -04:00
|
|
|
{
|
|
|
|
.data = sEmotion_ExclamationMarkGfx,
|
|
|
|
.size = 0x80
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.data = sEmotion_QuestionMarkGfx,
|
|
|
|
.size = 0x80
|
|
|
|
}
|
2017-12-18 19:35:50 +01:00
|
|
|
};
|
2017-12-01 21:25:13 +01:00
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
static const struct SpriteFrameImage sSpriteImageTable_HeartIcon[] =
|
2017-12-18 19:35:50 +01:00
|
|
|
{
|
2019-03-11 03:12:15 -04:00
|
|
|
{
|
|
|
|
.data = sEmotion_HeartGfx,
|
|
|
|
.size = 0x80
|
|
|
|
}
|
2017-12-18 19:35:50 +01:00
|
|
|
};
|
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
static const union AnimCmd sSpriteAnim_Icons1[] =
|
2017-12-18 19:35:50 +01:00
|
|
|
{
|
|
|
|
ANIMCMD_FRAME(0, 60),
|
|
|
|
ANIMCMD_END
|
|
|
|
};
|
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
static const union AnimCmd sSpriteAnim_Icons2[] =
|
2017-12-18 19:35:50 +01:00
|
|
|
{
|
|
|
|
ANIMCMD_FRAME(1, 60),
|
|
|
|
ANIMCMD_END
|
|
|
|
};
|
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
static const union AnimCmd *const sSpriteAnimTable_Icons[] =
|
2017-12-18 19:35:50 +01:00
|
|
|
{
|
2017-12-19 17:18:44 +01:00
|
|
|
sSpriteAnim_Icons1,
|
|
|
|
sSpriteAnim_Icons2
|
2017-12-18 19:35:50 +01:00
|
|
|
};
|
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
static const struct SpriteTemplate sSpriteTemplate_ExclamationQuestionMark =
|
2017-12-18 19:35:50 +01:00
|
|
|
{
|
2021-09-14 13:14:14 -04:00
|
|
|
.tileTag = TAG_NONE,
|
|
|
|
.paletteTag = TAG_NONE,
|
2017-12-19 17:18:44 +01:00
|
|
|
.oam = &sOamData_Icons,
|
|
|
|
.anims = sSpriteAnimTable_Icons,
|
|
|
|
.images = sSpriteImageTable_ExclamationQuestionMark,
|
2017-12-18 19:35:50 +01:00
|
|
|
.affineAnims = gDummySpriteAffineAnimTable,
|
2017-12-19 17:18:44 +01:00
|
|
|
.callback = SpriteCB_TrainerIcons
|
2017-12-18 19:35:50 +01:00
|
|
|
};
|
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
static const struct SpriteTemplate sSpriteTemplate_HeartIcon =
|
2017-12-18 19:35:50 +01:00
|
|
|
{
|
2021-09-14 13:14:14 -04:00
|
|
|
.tileTag = TAG_NONE,
|
2021-02-22 15:35:09 +00:00
|
|
|
.paletteTag = FLDEFF_PAL_TAG_GENERAL_0,
|
2017-12-19 17:18:44 +01:00
|
|
|
.oam = &sOamData_Icons,
|
|
|
|
.anims = sSpriteAnimTable_Icons,
|
|
|
|
.images = sSpriteImageTable_HeartIcon,
|
2017-12-18 19:35:50 +01:00
|
|
|
.affineAnims = gDummySpriteAffineAnimTable,
|
2017-12-19 17:18:44 +01:00
|
|
|
.callback = SpriteCB_TrainerIcons
|
2017-12-18 19:35:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
// code
|
2017-12-01 21:25:13 +01:00
|
|
|
bool8 CheckForTrainersWantingBattle(void)
|
|
|
|
{
|
|
|
|
u8 i;
|
|
|
|
|
2022-09-05 11:04:21 +02:00
|
|
|
if (FlagGet(OW_FLAG_NO_TRAINER_SEE))
|
2022-08-29 19:36:44 +02:00
|
|
|
return FALSE;
|
Implementation if Pyredrid and AsparagusEduardo debug menu plus huge rewrite and tons of additions
V2: Fly, Warp, Flags, Vars, give items, give pkm 2 versions
Improved cheats, reworked the vars system
vars function now starts at VARS_START and end VARS_END
Figured out how to display FieldMessages, reimplemented CheckSafeBlock, cleanup
DebugAction_DestroyExtraWindow instead of multiple, renamed text variables
cleanup + pokemon simple
give pokemon complex nearly done
Complex pkm works, items now with icons
if statement cleanup
alter build tools to include maps per map group
Warp functionallity
added hex value to flags and vars
cleanup
Credits
2020-09-26 00:51:02 +02:00
|
|
|
|
2017-12-01 21:25:13 +01:00
|
|
|
gNoOfApproachingTrainers = 0;
|
|
|
|
gApproachingTrainerId = 0;
|
|
|
|
|
2019-11-20 23:12:51 -05:00
|
|
|
for (i = 0; i < OBJECT_EVENTS_COUNT; i++)
|
2017-12-01 21:25:13 +01:00
|
|
|
{
|
2020-04-21 15:53:48 -04:00
|
|
|
u8 numTrainers;
|
2017-12-01 21:25:13 +01:00
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
if (!gObjectEvents[i].active)
|
2017-12-01 21:25:13 +01:00
|
|
|
continue;
|
2020-04-21 15:53:48 -04:00
|
|
|
if (gObjectEvents[i].trainerType != TRAINER_TYPE_NORMAL && gObjectEvents[i].trainerType != TRAINER_TYPE_BURIED)
|
2017-12-01 21:25:13 +01:00
|
|
|
continue;
|
|
|
|
|
2020-04-21 15:53:48 -04:00
|
|
|
numTrainers = CheckTrainer(i);
|
|
|
|
if (numTrainers == 2)
|
|
|
|
break;
|
2017-12-01 21:25:13 +01:00
|
|
|
|
2020-04-21 15:53:48 -04:00
|
|
|
if (numTrainers == 0)
|
2017-12-01 21:25:13 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (gNoOfApproachingTrainers > 1)
|
|
|
|
break;
|
|
|
|
if (GetMonsStateToDoubles_2() != 0) // one trainer found and cant have a double battle
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gNoOfApproachingTrainers == 1)
|
|
|
|
{
|
|
|
|
ResetTrainerOpponentIds();
|
2019-11-20 22:55:44 -05:00
|
|
|
ConfigureAndSetUpOneTrainerBattle(gApproachingTrainers[gNoOfApproachingTrainers - 1].objectEventId,
|
2017-12-01 21:25:13 +01:00
|
|
|
gApproachingTrainers[gNoOfApproachingTrainers - 1].trainerScriptPtr);
|
2019-11-01 03:41:55 -04:00
|
|
|
gTrainerApproachedPlayer = TRUE;
|
2017-12-01 21:25:13 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else if (gNoOfApproachingTrainers == 2)
|
|
|
|
{
|
|
|
|
ResetTrainerOpponentIds();
|
|
|
|
for (i = 0; i < gNoOfApproachingTrainers; i++, gApproachingTrainerId++)
|
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
ConfigureTwoTrainersBattle(gApproachingTrainers[i].objectEventId,
|
2017-12-01 21:25:13 +01:00
|
|
|
gApproachingTrainers[i].trainerScriptPtr);
|
|
|
|
}
|
|
|
|
SetUpTwoTrainersBattle();
|
|
|
|
gApproachingTrainerId = 0;
|
2019-11-01 03:41:55 -04:00
|
|
|
gTrainerApproachedPlayer = TRUE;
|
2017-12-01 21:25:13 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-11-01 03:41:55 -04:00
|
|
|
gTrainerApproachedPlayer = FALSE;
|
2017-12-01 21:25:13 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
2017-12-18 19:35:50 +01:00
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
static u8 CheckTrainer(u8 objectEventId)
|
2017-12-18 19:35:50 +01:00
|
|
|
{
|
|
|
|
const u8 *scriptPtr;
|
2021-01-26 04:41:13 -05:00
|
|
|
u8 numTrainers = 1;
|
2017-12-18 19:35:50 +01:00
|
|
|
u8 approachDistance;
|
|
|
|
|
|
|
|
if (InTrainerHill() == TRUE)
|
2019-08-04 15:35:35 -04:00
|
|
|
scriptPtr = GetTrainerHillTrainerScript();
|
2017-12-18 19:35:50 +01:00
|
|
|
else
|
2019-11-20 22:55:44 -05:00
|
|
|
scriptPtr = GetObjectEventScriptPointerByObjectEventId(objectEventId);
|
2017-12-18 19:35:50 +01:00
|
|
|
|
|
|
|
if (InBattlePyramid())
|
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
if (GetBattlePyramidTrainerFlag(objectEventId))
|
2017-12-18 19:35:50 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (InTrainerHill() == TRUE)
|
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
if (GetHillTrainerFlag(objectEventId))
|
2017-12-18 19:35:50 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (GetTrainerFlagFromScriptPointer(scriptPtr))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
approachDistance = GetTrainerApproachDistance(&gObjectEvents[objectEventId]);
|
2017-12-18 19:35:50 +01:00
|
|
|
|
|
|
|
if (approachDistance != 0)
|
|
|
|
{
|
|
|
|
if (scriptPtr[1] == TRAINER_BATTLE_DOUBLE
|
|
|
|
|| scriptPtr[1] == TRAINER_BATTLE_REMATCH_DOUBLE
|
|
|
|
|| scriptPtr[1] == TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE)
|
|
|
|
{
|
|
|
|
if (GetMonsStateToDoubles_2() != 0)
|
|
|
|
return 0;
|
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
numTrainers = 2;
|
2017-12-18 19:35:50 +01:00
|
|
|
}
|
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
gApproachingTrainers[gNoOfApproachingTrainers].objectEventId = objectEventId;
|
2017-12-18 19:35:50 +01:00
|
|
|
gApproachingTrainers[gNoOfApproachingTrainers].trainerScriptPtr = scriptPtr;
|
|
|
|
gApproachingTrainers[gNoOfApproachingTrainers].radius = approachDistance;
|
2021-01-26 04:41:13 -05:00
|
|
|
InitTrainerApproachTask(&gObjectEvents[objectEventId], approachDistance - 1);
|
2017-12-18 19:35:50 +01:00
|
|
|
gNoOfApproachingTrainers++;
|
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
return numTrainers;
|
2017-12-18 19:35:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
static u8 GetTrainerApproachDistance(struct ObjectEvent *trainerObj)
|
2017-12-18 19:35:50 +01:00
|
|
|
{
|
|
|
|
s16 x, y;
|
|
|
|
u8 i;
|
|
|
|
u8 approachDistance;
|
|
|
|
|
|
|
|
PlayerGetDestCoords(&x, &y);
|
2020-04-21 15:53:48 -04:00
|
|
|
if (trainerObj->trainerType == TRAINER_TYPE_NORMAL) // can only see in one direction
|
2017-12-18 19:35:50 +01:00
|
|
|
{
|
2018-06-11 09:19:17 -05:00
|
|
|
approachDistance = sDirectionalApproachDistanceFuncs[trainerObj->facingDirection - 1](trainerObj, trainerObj->trainerRange_berryTreeId, x, y);
|
|
|
|
return CheckPathBetweenTrainerAndPlayer(trainerObj, approachDistance, trainerObj->facingDirection);
|
2017-12-18 19:35:50 +01:00
|
|
|
}
|
2020-04-21 15:53:48 -04:00
|
|
|
else // TRAINER_TYPE_SEE_ALL_DIRECTIONS, TRAINER_TYPE_BURIED
|
2017-12-18 19:35:50 +01:00
|
|
|
{
|
2020-04-21 15:53:48 -04:00
|
|
|
for (i = 0; i < ARRAY_COUNT(sDirectionalApproachDistanceFuncs); i++)
|
2017-12-18 19:35:50 +01:00
|
|
|
{
|
|
|
|
approachDistance = sDirectionalApproachDistanceFuncs[i](trainerObj, trainerObj->trainerRange_berryTreeId, x, y);
|
2017-12-18 23:26:44 +01:00
|
|
|
if (CheckPathBetweenTrainerAndPlayer(trainerObj, approachDistance, i + 1)) // directions are 1-4 instead of 0-3. south north west east
|
2017-12-18 19:35:50 +01:00
|
|
|
return approachDistance;
|
|
|
|
}
|
|
|
|
}
|
2017-12-18 23:26:44 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns how far south the player is from trainer. 0 if out of trainer's sight.
|
2019-11-20 22:55:44 -05:00
|
|
|
static u8 GetTrainerApproachDistanceSouth(struct ObjectEvent *trainerObj, s16 range, s16 x, s16 y)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2018-06-11 09:19:17 -05:00
|
|
|
if (trainerObj->currentCoords.x == x
|
|
|
|
&& y > trainerObj->currentCoords.y
|
|
|
|
&& y <= trainerObj->currentCoords.y + range)
|
|
|
|
return (y - trainerObj->currentCoords.y);
|
2017-12-18 23:26:44 +01:00
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns how far north the player is from trainer. 0 if out of trainer's sight.
|
2019-11-20 22:55:44 -05:00
|
|
|
static u8 GetTrainerApproachDistanceNorth(struct ObjectEvent *trainerObj, s16 range, s16 x, s16 y)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2018-06-11 09:19:17 -05:00
|
|
|
if (trainerObj->currentCoords.x == x
|
|
|
|
&& y < trainerObj->currentCoords.y
|
|
|
|
&& y >= trainerObj->currentCoords.y - range)
|
|
|
|
return (trainerObj->currentCoords.y - y);
|
2017-12-18 23:26:44 +01:00
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns how far west the player is from trainer. 0 if out of trainer's sight.
|
2019-11-20 22:55:44 -05:00
|
|
|
static u8 GetTrainerApproachDistanceWest(struct ObjectEvent *trainerObj, s16 range, s16 x, s16 y)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2018-06-11 09:19:17 -05:00
|
|
|
if (trainerObj->currentCoords.y == y
|
|
|
|
&& x < trainerObj->currentCoords.x
|
|
|
|
&& x >= trainerObj->currentCoords.x - range)
|
|
|
|
return (trainerObj->currentCoords.x - x);
|
2017-12-18 23:26:44 +01:00
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns how far east the player is from trainer. 0 if out of trainer's sight.
|
2019-11-20 22:55:44 -05:00
|
|
|
static u8 GetTrainerApproachDistanceEast(struct ObjectEvent *trainerObj, s16 range, s16 x, s16 y)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2018-06-11 09:19:17 -05:00
|
|
|
if (trainerObj->currentCoords.y == y
|
|
|
|
&& x > trainerObj->currentCoords.x
|
|
|
|
&& x <= trainerObj->currentCoords.x + range)
|
|
|
|
return (x - trainerObj->currentCoords.x);
|
2017-12-18 23:26:44 +01:00
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
static u8 CheckPathBetweenTrainerAndPlayer(struct ObjectEvent *trainerObj, u8 approachDistance, u8 direction)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
|
|
|
s16 x, y;
|
2021-01-26 04:41:13 -05:00
|
|
|
u8 rangeX, rangeY;
|
2017-12-18 23:26:44 +01:00
|
|
|
u8 i;
|
|
|
|
u8 collision;
|
|
|
|
|
|
|
|
if (approachDistance == 0)
|
|
|
|
return 0;
|
|
|
|
|
2018-06-11 09:19:17 -05:00
|
|
|
x = trainerObj->currentCoords.x;
|
|
|
|
y = trainerObj->currentCoords.y;
|
2017-12-18 23:26:44 +01:00
|
|
|
|
|
|
|
MoveCoords(direction, &x, &y);
|
|
|
|
for (i = 0; i < approachDistance - 1; i++, MoveCoords(direction, &x, &y))
|
|
|
|
{
|
2022-01-29 21:13:46 -05:00
|
|
|
// Check for collisions on approach, ignoring the "out of range" collision for regular movement
|
2018-06-13 17:51:26 -05:00
|
|
|
collision = GetCollisionFlagsAtCoords(trainerObj, x, y, direction);
|
2022-01-29 21:13:46 -05:00
|
|
|
if (collision != 0 && (collision & ~(1 << (COLLISION_OUTSIDE_RANGE - 1))))
|
2017-12-18 23:26:44 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
rangeX = trainerObj->rangeX;
|
|
|
|
rangeY = trainerObj->rangeY;
|
2020-09-17 18:24:11 -04:00
|
|
|
trainerObj->rangeX = 0;
|
|
|
|
trainerObj->rangeY = 0;
|
2017-12-18 23:26:44 +01:00
|
|
|
|
2018-06-13 17:51:26 -05:00
|
|
|
collision = GetCollisionAtCoords(trainerObj, x, y, direction);
|
2017-12-18 23:26:44 +01:00
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
trainerObj->rangeX = rangeX;
|
|
|
|
trainerObj->rangeY = rangeY;
|
|
|
|
if (collision == COLLISION_OBJECT_EVENT)
|
2017-12-18 23:26:44 +01:00
|
|
|
return approachDistance;
|
|
|
|
|
2017-12-18 19:35:50 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2017-12-18 23:26:44 +01:00
|
|
|
|
|
|
|
#define tFuncId data[0]
|
|
|
|
#define tTrainerRange data[3]
|
2017-12-19 17:18:44 +01:00
|
|
|
#define tOutOfAshSpriteId data[4]
|
2019-11-20 22:55:44 -05:00
|
|
|
#define tTrainerObjectEventId data[7]
|
2017-12-18 23:26:44 +01:00
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
static void InitTrainerApproachTask(struct ObjectEvent *trainerObj, u8 range)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
|
|
|
struct Task *task;
|
|
|
|
|
|
|
|
gApproachingTrainers[gNoOfApproachingTrainers].taskId = CreateTask(Task_RunTrainerSeeFuncList, 0x50);
|
|
|
|
task = &gTasks[gApproachingTrainers[gNoOfApproachingTrainers].taskId];
|
|
|
|
task->tTrainerRange = range;
|
2019-11-20 22:55:44 -05:00
|
|
|
task->tTrainerObjectEventId = gApproachingTrainers[gNoOfApproachingTrainers].objectEventId;
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
static void StartTrainerApproach(TaskFunc followupFunc)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
|
|
|
u8 taskId;
|
|
|
|
TaskFunc taskFunc;
|
|
|
|
|
|
|
|
if (gApproachingTrainerId == 0)
|
|
|
|
taskId = gApproachingTrainers[0].taskId;
|
|
|
|
else
|
|
|
|
taskId = gApproachingTrainers[1].taskId;
|
|
|
|
|
|
|
|
taskFunc = Task_RunTrainerSeeFuncList;
|
|
|
|
SetTaskFuncWithFollowupFunc(taskId, taskFunc, followupFunc);
|
2021-01-26 04:41:13 -05:00
|
|
|
gTasks[taskId].tFuncId = TRSEE_EXCLAMATION;
|
2017-12-18 23:26:44 +01:00
|
|
|
taskFunc(taskId);
|
|
|
|
}
|
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
static void Task_RunTrainerSeeFuncList(u8 taskId)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
|
|
|
struct Task *task = &gTasks[taskId];
|
2019-11-20 22:55:44 -05:00
|
|
|
struct ObjectEvent *trainerObj = &gObjectEvents[task->tTrainerObjectEventId];
|
2017-12-18 23:26:44 +01:00
|
|
|
|
|
|
|
if (!trainerObj->active)
|
|
|
|
{
|
|
|
|
SwitchTaskToFollowupFunc(taskId);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-12-19 17:18:44 +01:00
|
|
|
while (sTrainerSeeFuncList[task->tFuncId](taskId, task, trainerObj));
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
static bool8 TrainerSeeIdle(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
// TRSEE_EXCLAMATION
|
2019-11-20 22:55:44 -05:00
|
|
|
static bool8 TrainerExclamationMark(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
|
|
|
u8 direction;
|
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
ObjectEventGetLocalIdAndMap(trainerObj, &gFieldEffectArguments[0], &gFieldEffectArguments[1], &gFieldEffectArguments[2]);
|
2018-06-13 17:51:26 -05:00
|
|
|
FieldEffectStart(FLDEFF_EXCLAMATION_MARK_ICON);
|
|
|
|
direction = GetFaceDirectionMovementAction(trainerObj->facingDirection);
|
2019-11-20 22:55:44 -05:00
|
|
|
ObjectEventSetHeldMovement(trainerObj, direction);
|
2021-01-26 04:41:13 -05:00
|
|
|
task->tFuncId++; // TRSEE_EXCLAMATION_WAIT
|
2017-12-18 23:26:44 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
// TRSEE_EXCLAMATION_WAIT
|
2019-11-20 22:55:44 -05:00
|
|
|
static bool8 WaitTrainerExclamationMark(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2018-06-13 17:51:26 -05:00
|
|
|
if (FieldEffectActiveListContains(FLDEFF_EXCLAMATION_MARK_ICON))
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-01-26 04:41:13 -05:00
|
|
|
task->tFuncId++; // TRSEE_MOVE_TO_PLAYER
|
2019-01-20 10:11:45 -06:00
|
|
|
if (trainerObj->movementType == MOVEMENT_TYPE_TREE_DISGUISE || trainerObj->movementType == MOVEMENT_TYPE_MOUNTAIN_DISGUISE)
|
2021-01-26 04:41:13 -05:00
|
|
|
task->tFuncId = TRSEE_REVEAL_DISGUISE;
|
2021-02-14 19:25:23 +00:00
|
|
|
if (trainerObj->movementType == MOVEMENT_TYPE_BURIED)
|
|
|
|
task->tFuncId = TRSEE_REVEAL_BURIED;
|
2017-12-18 23:26:44 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
// TRSEE_MOVE_TO_PLAYER
|
2019-11-20 22:55:44 -05:00
|
|
|
static bool8 TrainerMoveToPlayer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
if (!ObjectEventIsMovementOverridden(trainerObj) || ObjectEventClearHeldMovementIfFinished(trainerObj))
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2017-12-19 17:18:44 +01:00
|
|
|
if (task->tTrainerRange)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
ObjectEventSetHeldMovement(trainerObj, GetWalkNormalMovementAction(trainerObj->facingDirection));
|
2017-12-19 17:18:44 +01:00
|
|
|
task->tTrainerRange--;
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
ObjectEventSetHeldMovement(trainerObj, MOVEMENT_ACTION_FACE_PLAYER);
|
2021-01-26 04:41:13 -05:00
|
|
|
task->tFuncId++; // TRSEE_PLAYER_FACE
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
// TRSEE_PLAYER_FACE
|
2019-11-20 22:55:44 -05:00
|
|
|
static bool8 PlayerFaceApproachingTrainer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
struct ObjectEvent *playerObj;
|
2017-12-18 23:26:44 +01:00
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
if (ObjectEventIsMovementOverridden(trainerObj) && !ObjectEventClearHeldMovementIfFinished(trainerObj))
|
2017-12-18 23:26:44 +01:00
|
|
|
return FALSE;
|
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
// Set trainer's movement type so they stop and remain facing that direction
|
2018-06-13 17:51:26 -05:00
|
|
|
SetTrainerMovementType(trainerObj, GetTrainerFacingDirectionMovementType(trainerObj->facingDirection));
|
2019-11-20 22:55:44 -05:00
|
|
|
TryOverrideTemplateCoordsForObjectEvent(trainerObj, GetTrainerFacingDirectionMovementType(trainerObj->facingDirection));
|
|
|
|
OverrideTemplateCoordsForObjectEvent(trainerObj);
|
2017-12-18 23:26:44 +01:00
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
playerObj = &gObjectEvents[gPlayerAvatar.objectEventId];
|
|
|
|
if (ObjectEventIsMovementOverridden(playerObj) && !ObjectEventClearHeldMovementIfFinished(playerObj))
|
2017-12-18 23:26:44 +01:00
|
|
|
return FALSE;
|
|
|
|
|
2021-10-27 01:27:20 +08:00
|
|
|
CancelPlayerForcedMovement();
|
2019-11-20 22:55:44 -05:00
|
|
|
ObjectEventSetHeldMovement(&gObjectEvents[gPlayerAvatar.objectEventId], GetFaceDirectionMovementAction(GetOppositeDirection(trainerObj->facingDirection)));
|
2021-01-26 04:41:13 -05:00
|
|
|
task->tFuncId++; // TRSEE_PLAYER_FACE_WAIT
|
2017-12-18 23:26:44 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
// TRSEE_PLAYER_FACE_WAIT
|
2019-11-20 22:55:44 -05:00
|
|
|
static bool8 WaitPlayerFaceApproachingTrainer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
struct ObjectEvent *playerObj = &gObjectEvents[gPlayerAvatar.objectEventId];
|
2017-12-18 23:26:44 +01:00
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
if (!ObjectEventIsMovementOverridden(playerObj)
|
|
|
|
|| ObjectEventClearHeldMovementIfFinished(playerObj))
|
2017-12-18 23:26:44 +01:00
|
|
|
SwitchTaskToFollowupFunc(taskId);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
// TRSEE_REVEAL_DISGUISE
|
2019-11-20 22:55:44 -05:00
|
|
|
static bool8 RevealDisguisedTrainer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
if (!ObjectEventIsMovementOverridden(trainerObj)
|
|
|
|
|| ObjectEventClearHeldMovementIfFinished(trainerObj))
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
ObjectEventSetHeldMovement(trainerObj, MOVEMENT_ACTION_REVEAL_TRAINER);
|
2021-01-26 04:41:13 -05:00
|
|
|
task->tFuncId++; // TRSEE_REVEAL_DISGUISE_WAIT
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
// TRSEE_REVEAL_DISGUISE_WAIT
|
2019-11-20 22:55:44 -05:00
|
|
|
static bool8 WaitRevealDisguisedTrainer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
if (ObjectEventClearHeldMovementIfFinished(trainerObj))
|
2021-01-26 04:41:13 -05:00
|
|
|
task->tFuncId = TRSEE_MOVE_TO_PLAYER;
|
2017-12-18 23:26:44 +01:00
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2021-02-14 19:25:23 +00:00
|
|
|
// TRSEE_REVEAL_BURIED
|
|
|
|
static bool8 RevealBuriedTrainer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
if (!ObjectEventIsMovementOverridden(trainerObj)
|
|
|
|
|| ObjectEventClearHeldMovementIfFinished(trainerObj))
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
ObjectEventSetHeldMovement(trainerObj, MOVEMENT_ACTION_FACE_PLAYER);
|
2017-12-19 17:18:44 +01:00
|
|
|
task->tFuncId++;
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2021-02-14 19:25:23 +00:00
|
|
|
// TRSEE_BURIED_POP_OUT
|
|
|
|
static bool8 PopOutOfAshBuriedTrainer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
if (ObjectEventCheckHeldMovementStatus(trainerObj))
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2018-06-11 09:19:17 -05:00
|
|
|
gFieldEffectArguments[0] = trainerObj->currentCoords.x;
|
|
|
|
gFieldEffectArguments[1] = trainerObj->currentCoords.y;
|
2017-12-18 23:26:44 +01:00
|
|
|
gFieldEffectArguments[2] = gSprites[trainerObj->spriteId].subpriority - 1;
|
|
|
|
gFieldEffectArguments[3] = 2;
|
2020-06-24 16:27:00 -04:00
|
|
|
task->tOutOfAshSpriteId = FieldEffectStart(FLDEFF_ASH_PUFF);
|
2017-12-19 17:18:44 +01:00
|
|
|
task->tFuncId++;
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2021-02-14 19:25:23 +00:00
|
|
|
// TRSEE_BURIED_JUMP
|
|
|
|
static bool8 JumpInPlaceBuriedTrainer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
|
|
|
struct Sprite *sprite;
|
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
if (gSprites[task->tOutOfAshSpriteId].animCmdIndex == 2)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2018-06-11 09:19:17 -05:00
|
|
|
trainerObj->fixedPriority = 0;
|
|
|
|
trainerObj->triggerGroundEffectsOnMove = 1;
|
2017-12-18 23:26:44 +01:00
|
|
|
|
|
|
|
sprite = &gSprites[trainerObj->spriteId];
|
|
|
|
sprite->oam.priority = 2;
|
2019-11-20 22:55:44 -05:00
|
|
|
ObjectEventClearHeldMovementIfFinished(trainerObj);
|
|
|
|
ObjectEventSetHeldMovement(trainerObj, GetJumpInPlaceMovementAction(trainerObj->facingDirection));
|
2017-12-19 17:18:44 +01:00
|
|
|
task->tFuncId++;
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2021-02-14 19:25:23 +00:00
|
|
|
// TRSEE_REVEAL_BURIED_WAIT
|
|
|
|
static bool8 WaitRevealBuriedTrainer(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2020-06-24 16:27:00 -04:00
|
|
|
if (!FieldEffectActiveListContains(FLDEFF_ASH_PUFF))
|
2021-01-26 04:41:13 -05:00
|
|
|
task->tFuncId = TRSEE_MOVE_TO_PLAYER;
|
2017-12-18 23:26:44 +01:00
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
#undef tTrainerRange
|
|
|
|
#undef tOutOfAshSpriteId
|
2019-11-20 22:55:44 -05:00
|
|
|
#undef tTrainerObjectEventId
|
2017-12-19 17:18:44 +01:00
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
#define tObjEvent data[1]
|
|
|
|
|
2021-02-14 19:25:23 +00:00
|
|
|
static void Task_SetBuriedTrainerMovement(u8 taskId)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
|
|
|
struct Task *task = &gTasks[taskId];
|
2019-11-20 22:55:44 -05:00
|
|
|
struct ObjectEvent *objEvent;
|
2017-12-18 23:26:44 +01:00
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
LoadWordFromTwoHalfwords(&task->tObjEvent, (u32 *)&objEvent);
|
2017-12-18 23:26:44 +01:00
|
|
|
if (!task->data[7])
|
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
ObjectEventClearHeldMovement(objEvent);
|
2017-12-18 23:26:44 +01:00
|
|
|
task->data[7]++;
|
|
|
|
}
|
2021-01-26 04:41:13 -05:00
|
|
|
sTrainerSeeFuncList2[task->tFuncId](taskId, task, objEvent);
|
|
|
|
if (task->tFuncId == ((int)ARRAY_COUNT(sTrainerSeeFuncList2) - 1) && !FieldEffectActiveListContains(FLDEFF_ASH_PUFF))
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
SetTrainerMovementType(objEvent, GetTrainerFacingDirectionMovementType(objEvent->facingDirection));
|
|
|
|
TryOverrideTemplateCoordsForObjectEvent(objEvent, GetTrainerFacingDirectionMovementType(objEvent->facingDirection));
|
2017-12-18 23:26:44 +01:00
|
|
|
DestroyTask(taskId);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
objEvent->heldMovementFinished = 0;
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-14 19:25:23 +00:00
|
|
|
// Called when a buried Trainer has the reveal_trainer movement applied, from direct interaction
|
|
|
|
void SetBuriedTrainerMovement(struct ObjectEvent *objEvent)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2021-02-14 19:25:23 +00:00
|
|
|
StoreWordInTwoHalfwords(&gTasks[CreateTask(Task_SetBuriedTrainerMovement, 0)].tObjEvent, (u32)objEvent);
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
void DoTrainerApproach(void)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2021-01-26 04:41:13 -05:00
|
|
|
StartTrainerApproach(Task_EndTrainerApproach);
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
|
2021-01-26 04:41:13 -05:00
|
|
|
static void Task_EndTrainerApproach(u8 taskId)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
|
|
|
DestroyTask(taskId);
|
2022-08-15 15:18:12 -04:00
|
|
|
ScriptContext_Enable();
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
|
2018-12-07 23:50:56 +01:00
|
|
|
void TryPrepareSecondApproachingTrainer(void)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
|
|
|
if (gNoOfApproachingTrainers == 2)
|
|
|
|
{
|
|
|
|
if (gApproachingTrainerId == 0)
|
|
|
|
{
|
|
|
|
gApproachingTrainerId++;
|
2018-12-07 23:50:56 +01:00
|
|
|
gSpecialVar_Result = TRUE;
|
2019-11-20 22:55:44 -05:00
|
|
|
UnfreezeObjectEvents();
|
|
|
|
FreezeObjectEventsExceptOne(gApproachingTrainers[1].objectEventId);
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gApproachingTrainerId = 0;
|
2018-12-07 23:50:56 +01:00
|
|
|
gSpecialVar_Result = FALSE;
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-12-07 23:50:56 +01:00
|
|
|
gSpecialVar_Result = FALSE;
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
#define sLocalId data[0]
|
|
|
|
#define sMapNum data[1]
|
|
|
|
#define sMapGroup data[2]
|
|
|
|
#define sData3 data[3]
|
|
|
|
#define sData4 data[4]
|
|
|
|
#define sFldEffId data[7]
|
|
|
|
|
2018-06-13 17:51:26 -05:00
|
|
|
u8 FldEff_ExclamationMarkIcon(void)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2017-12-19 17:18:44 +01:00
|
|
|
u8 spriteId = CreateSpriteAtEnd(&sSpriteTemplate_ExclamationQuestionMark, 0, 0, 0x53);
|
2017-12-18 23:26:44 +01:00
|
|
|
|
|
|
|
if (spriteId != MAX_SPRITES)
|
2018-06-13 17:51:26 -05:00
|
|
|
SetIconSpriteData(&gSprites[spriteId], FLDEFF_EXCLAMATION_MARK_ICON, 0);
|
2017-12-18 23:26:44 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-06-13 17:51:26 -05:00
|
|
|
u8 FldEff_QuestionMarkIcon(void)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2017-12-19 17:18:44 +01:00
|
|
|
u8 spriteId = CreateSpriteAtEnd(&sSpriteTemplate_ExclamationQuestionMark, 0, 0, 0x52);
|
2017-12-18 23:26:44 +01:00
|
|
|
|
|
|
|
if (spriteId != MAX_SPRITES)
|
2018-06-13 17:51:26 -05:00
|
|
|
SetIconSpriteData(&gSprites[spriteId], FLDEFF_QUESTION_MARK_ICON, 1);
|
2017-12-18 23:26:44 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 FldEff_HeartIcon(void)
|
|
|
|
{
|
2017-12-19 17:18:44 +01:00
|
|
|
u8 spriteId = CreateSpriteAtEnd(&sSpriteTemplate_HeartIcon, 0, 0, 0x52);
|
2017-12-18 23:26:44 +01:00
|
|
|
|
|
|
|
if (spriteId != MAX_SPRITES)
|
|
|
|
{
|
|
|
|
struct Sprite *sprite = &gSprites[spriteId];
|
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
SetIconSpriteData(sprite, FLDEFF_HEART_ICON, 0);
|
2017-12-18 23:26:44 +01:00
|
|
|
sprite->oam.paletteNum = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
static void SetIconSpriteData(struct Sprite *sprite, u16 fldEffId, u8 spriteAnimNum)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
|
|
|
sprite->oam.priority = 1;
|
|
|
|
sprite->coordOffsetEnabled = 1;
|
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
sprite->sLocalId = gFieldEffectArguments[0];
|
|
|
|
sprite->sMapNum = gFieldEffectArguments[1];
|
|
|
|
sprite->sMapGroup = gFieldEffectArguments[2];
|
|
|
|
sprite->sData3 = -5;
|
|
|
|
sprite->sFldEffId = fldEffId;
|
2017-12-18 23:26:44 +01:00
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
StartSpriteAnim(sprite, spriteAnimNum);
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
static void SpriteCB_TrainerIcons(struct Sprite *sprite)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
u8 objEventId;
|
2017-12-18 23:26:44 +01:00
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
if (TryGetObjectEventIdByLocalIdAndMap(sprite->sLocalId, sprite->sMapNum, sprite->sMapGroup, &objEventId)
|
2017-12-18 23:26:44 +01:00
|
|
|
|| sprite->animEnded)
|
|
|
|
{
|
2017-12-19 17:18:44 +01:00
|
|
|
FieldEffectStop(sprite, sprite->sFldEffId);
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
struct Sprite *objEventSprite = &gSprites[gObjectEvents[objEventId].spriteId];
|
2017-12-19 17:18:44 +01:00
|
|
|
sprite->sData4 += sprite->sData3;
|
2021-07-07 09:11:52 -04:00
|
|
|
sprite->x = objEventSprite->x;
|
|
|
|
sprite->y = objEventSprite->y - 16;
|
|
|
|
sprite->x2 = objEventSprite->x2;
|
|
|
|
sprite->y2 = objEventSprite->y2 + sprite->sData4;
|
2017-12-19 17:18:44 +01:00
|
|
|
if (sprite->sData4)
|
|
|
|
sprite->sData3++;
|
2017-12-18 23:26:44 +01:00
|
|
|
else
|
2017-12-19 17:18:44 +01:00
|
|
|
sprite->sData3 = 0;
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-19 17:18:44 +01:00
|
|
|
#undef sLocalId
|
|
|
|
#undef sMapNum
|
|
|
|
#undef sMapGroup
|
|
|
|
#undef sData3
|
|
|
|
#undef sData4
|
|
|
|
#undef sFldEffId
|
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
u8 GetCurrentApproachingTrainerObjectEventId(void)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
|
|
|
if (gApproachingTrainerId == 0)
|
2019-11-20 22:55:44 -05:00
|
|
|
return gApproachingTrainers[0].objectEventId;
|
2017-12-18 23:26:44 +01:00
|
|
|
else
|
2019-11-20 22:55:44 -05:00
|
|
|
return gApproachingTrainers[1].objectEventId;
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
u8 GetChosenApproachingTrainerObjectEventId(u8 arrayId)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
|
|
|
if (arrayId >= ARRAY_COUNT(gApproachingTrainers))
|
|
|
|
return 0;
|
|
|
|
else if (arrayId == 0)
|
2019-11-20 22:55:44 -05:00
|
|
|
return gApproachingTrainers[0].objectEventId;
|
2017-12-18 23:26:44 +01:00
|
|
|
else
|
2019-11-20 22:55:44 -05:00
|
|
|
return gApproachingTrainers[1].objectEventId;
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
|
2019-11-01 03:41:55 -04:00
|
|
|
void PlayerFaceTrainerAfterBattle(void)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
struct ObjectEvent *objEvent;
|
2017-12-18 23:26:44 +01:00
|
|
|
|
2019-11-01 03:41:55 -04:00
|
|
|
if (gTrainerApproachedPlayer == TRUE)
|
2017-12-18 23:26:44 +01:00
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
objEvent = &gObjectEvents[gApproachingTrainers[gWhichTrainerToFaceAfterBattle].objectEventId];
|
|
|
|
gPostBattleMovementScript[0] = GetFaceDirectionMovementAction(GetOppositeDirection(objEvent->facingDirection));
|
2019-11-01 03:41:55 -04:00
|
|
|
gPostBattleMovementScript[1] = MOVEMENT_ACTION_STEP_END;
|
2019-11-20 23:12:51 -05:00
|
|
|
ScriptMovement_StartObjectMovementScript(OBJ_EVENT_ID_PLAYER, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, gPostBattleMovementScript);
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-11-20 22:55:44 -05:00
|
|
|
objEvent = &gObjectEvents[gPlayerAvatar.objectEventId];
|
|
|
|
gPostBattleMovementScript[0] = GetFaceDirectionMovementAction(objEvent->facingDirection);
|
2019-11-01 03:41:55 -04:00
|
|
|
gPostBattleMovementScript[1] = MOVEMENT_ACTION_STEP_END;
|
2019-11-20 23:12:51 -05:00
|
|
|
ScriptMovement_StartObjectMovementScript(OBJ_EVENT_ID_PLAYER, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, gPostBattleMovementScript);
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|
|
|
|
|
2019-11-20 23:12:51 -05:00
|
|
|
SetMovingNpcId(OBJ_EVENT_ID_PLAYER);
|
2017-12-18 23:26:44 +01:00
|
|
|
}
|