mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-12-26 11:44:17 +01:00
commit
004f705607
19
graphics/battle_interface/ability_pop_up.pal
Normal file
19
graphics/battle_interface/ability_pop_up.pal
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
JASC-PAL
|
||||||
|
0100
|
||||||
|
16
|
||||||
|
1 177 91
|
||||||
|
143 129 149
|
||||||
|
103 91 111
|
||||||
|
79 65 85
|
||||||
|
59 31 81
|
||||||
|
103 89 109
|
||||||
|
231 239 245
|
||||||
|
249 253 255
|
||||||
|
0 0 0
|
||||||
|
0 0 0
|
||||||
|
107 115 115
|
||||||
|
74 66 82
|
||||||
|
0 0 0
|
||||||
|
214 214 206
|
||||||
|
132 140 140
|
||||||
|
0 0 0
|
BIN
graphics/battle_interface/last_used_ball_l.png
Normal file
BIN
graphics/battle_interface/last_used_ball_l.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 214 B |
BIN
graphics/battle_interface/last_used_ball_r.png
Normal file
BIN
graphics/battle_interface/last_used_ball_r.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 223 B |
@ -37,6 +37,7 @@
|
|||||||
#define B_ACTION_CANCEL_PARTNER 12 // when choosing an action
|
#define B_ACTION_CANCEL_PARTNER 12 // when choosing an action
|
||||||
#define B_ACTION_NOTHING_FAINTED 13 // when choosing an action
|
#define B_ACTION_NOTHING_FAINTED 13 // when choosing an action
|
||||||
#define B_ACTION_DEBUG 20
|
#define B_ACTION_DEBUG 20
|
||||||
|
#define B_ACTION_THROW_BALL 21 // R to throw last used ball
|
||||||
#define B_ACTION_NONE 0xFF
|
#define B_ACTION_NONE 0xFF
|
||||||
|
|
||||||
#define MAX_TRAINER_ITEMS 4
|
#define MAX_TRAINER_ITEMS 4
|
||||||
@ -602,6 +603,7 @@ struct BattleStruct
|
|||||||
u8 quickClawBattlerId;
|
u8 quickClawBattlerId;
|
||||||
struct StolenItem itemStolen[PARTY_SIZE]; // Player's team that had items stolen (two bytes per party member)
|
struct StolenItem itemStolen[PARTY_SIZE]; // Player's team that had items stolen (two bytes per party member)
|
||||||
u8 blunderPolicy:1; // should blunder policy activate
|
u8 blunderPolicy:1; // should blunder policy activate
|
||||||
|
u8 ballSpriteIds[2]; // item gfx, window gfx
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GET_MOVE_TYPE(move, typeArg) \
|
#define GET_MOVE_TYPE(move, typeArg) \
|
||||||
@ -905,5 +907,6 @@ extern u8 gNumberOfMovesToChoose;
|
|||||||
extern u8 gBattleControllerData[MAX_BATTLERS_COUNT];
|
extern u8 gBattleControllerData[MAX_BATTLERS_COUNT];
|
||||||
extern bool8 gHasFetchedBall;
|
extern bool8 gHasFetchedBall;
|
||||||
extern u8 gLastUsedBall;
|
extern u8 gLastUsedBall;
|
||||||
|
extern u16 gLastThrownBall;
|
||||||
|
|
||||||
#endif // GUARD_BATTLE_H
|
#endif // GUARD_BATTLE_H
|
||||||
|
@ -93,5 +93,9 @@ u8 GetScaledHPFraction(s16 hp, s16 maxhp, u8 scale);
|
|||||||
u8 GetHPBarLevel(s16 hp, s16 maxhp);
|
u8 GetHPBarLevel(s16 hp, s16 maxhp);
|
||||||
void CreateAbilityPopUp(u8 battlerId, u32 ability, bool32 isDoubleBattle);
|
void CreateAbilityPopUp(u8 battlerId, u32 ability, bool32 isDoubleBattle);
|
||||||
void DestroyAbilityPopUp(u8 battlerId);
|
void DestroyAbilityPopUp(u8 battlerId);
|
||||||
|
bool32 CanThrowLastUsedBall(void);
|
||||||
|
void TryHideLastUsedBall(void);
|
||||||
|
void TryRestoreLastUsedBall(void);
|
||||||
|
void TryAddLastUsedBallItemSprites(void);
|
||||||
|
|
||||||
#endif // GUARD_BATTLE_INTERFACE_H
|
#endif // GUARD_BATTLE_INTERFACE_H
|
||||||
|
@ -47,6 +47,7 @@ struct TypePower
|
|||||||
|
|
||||||
extern const struct TypePower gNaturalGiftTable[];
|
extern const struct TypePower gNaturalGiftTable[];
|
||||||
|
|
||||||
|
void HandleAction_ThrowBall(void);
|
||||||
bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move);
|
bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move);
|
||||||
void HandleAction_UseMove(void);
|
void HandleAction_UseMove(void);
|
||||||
void HandleAction_Switch(void);
|
void HandleAction_Switch(void);
|
||||||
|
@ -166,6 +166,10 @@
|
|||||||
// Item Theft Settings
|
// Item Theft Settings
|
||||||
#define B_TRAINERS_KNOCK_OFF_ITEMS TRUE // If TRUE, trainers can steal/swap your items (non-berries are restored after battle). In vanilla games trainers cannot steal items.
|
#define B_TRAINERS_KNOCK_OFF_ITEMS TRUE // If TRUE, trainers can steal/swap your items (non-berries are restored after battle). In vanilla games trainers cannot steal items.
|
||||||
|
|
||||||
|
// Last Used Ball
|
||||||
|
#define B_LAST_USED_BALL TRUE // If TRUE, the "last used ball" feature from Gen 7 will be implemented
|
||||||
|
#define B_LAST_USED_BALL_BUTTON R_BUTTON // If last used ball is implemented, this button (or button combo) will trigger throwing the last used ball.
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
#define B_DOUBLE_WILD_CHANCE 0 // % chance of encountering two Pokémon in a Wild Encounter.
|
#define B_DOUBLE_WILD_CHANCE 0 // % chance of encountering two Pokémon in a Wild Encounter.
|
||||||
#define B_SLEEP_TURNS GEN_7 // In Gen5+, sleep lasts for 1-3 turns instead of 2-5 turns.
|
#define B_SLEEP_TURNS GEN_7 // In Gen5+, sleep lasts for 1-3 turns instead of 2-5 turns.
|
||||||
|
@ -33,5 +33,6 @@ void ItemUseInBattle_EnigmaBerry(u8);
|
|||||||
void Task_UseDigEscapeRopeOnField(u8 taskId);
|
void Task_UseDigEscapeRopeOnField(u8 taskId);
|
||||||
u8 CanUseDigOrEscapeRopeOnCurMap(void);
|
u8 CanUseDigOrEscapeRopeOnCurMap(void);
|
||||||
u8 CheckIfItemIsTMHMOrEvolutionStone(u16 itemId);
|
u8 CheckIfItemIsTMHMOrEvolutionStone(u16 itemId);
|
||||||
|
u32 CanThrowBall(void);
|
||||||
|
|
||||||
#endif // GUARD_ITEM_USE_H
|
#endif // GUARD_ITEM_USE_H
|
||||||
|
@ -249,7 +249,8 @@ static void HandleInputChooseAction(void)
|
|||||||
if (JOY_NEW(A_BUTTON))
|
if (JOY_NEW(A_BUTTON))
|
||||||
{
|
{
|
||||||
PlaySE(SE_SELECT);
|
PlaySE(SE_SELECT);
|
||||||
|
TryHideLastUsedBall();
|
||||||
|
|
||||||
switch (gActionSelectionCursor[gActiveBattler])
|
switch (gActionSelectionCursor[gActiveBattler])
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
@ -336,6 +337,15 @@ static void HandleInputChooseAction(void)
|
|||||||
BtlController_EmitTwoReturnValues(1, B_ACTION_DEBUG, 0);
|
BtlController_EmitTwoReturnValues(1, B_ACTION_DEBUG, 0);
|
||||||
PlayerBufferExecCompleted();
|
PlayerBufferExecCompleted();
|
||||||
}
|
}
|
||||||
|
#if B_LAST_USED_BALL == TRUE
|
||||||
|
else if (JOY_NEW(B_LAST_USED_BALL_BUTTON) && CanThrowLastUsedBall())
|
||||||
|
{
|
||||||
|
PlaySE(SE_SELECT);
|
||||||
|
TryHideLastUsedBall();
|
||||||
|
BtlController_EmitTwoReturnValues(1, B_ACTION_THROW_BALL, 0);
|
||||||
|
PlayerBufferExecCompleted();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UnusedEndBounceEffect(void)
|
static void UnusedEndBounceEffect(void)
|
||||||
@ -372,6 +382,7 @@ static void HandleInputChooseTarget(void)
|
|||||||
else
|
else
|
||||||
BtlController_EmitTwoReturnValues(1, 10, gMoveSelectionCursor[gActiveBattler] | (gMultiUsePlayerCursor << 8));
|
BtlController_EmitTwoReturnValues(1, 10, gMoveSelectionCursor[gActiveBattler] | (gMultiUsePlayerCursor << 8));
|
||||||
EndBounceEffect(gMultiUsePlayerCursor, BOUNCE_HEALTHBOX);
|
EndBounceEffect(gMultiUsePlayerCursor, BOUNCE_HEALTHBOX);
|
||||||
|
TryHideLastUsedBall();
|
||||||
HideMegaTriggerSprite();
|
HideMegaTriggerSprite();
|
||||||
PlayerBufferExecCompleted();
|
PlayerBufferExecCompleted();
|
||||||
}
|
}
|
||||||
@ -514,6 +525,7 @@ static void HandleInputShowTargets(void)
|
|||||||
else
|
else
|
||||||
BtlController_EmitTwoReturnValues(1, 10, gMoveSelectionCursor[gActiveBattler] | (gMultiUsePlayerCursor << 8));
|
BtlController_EmitTwoReturnValues(1, 10, gMoveSelectionCursor[gActiveBattler] | (gMultiUsePlayerCursor << 8));
|
||||||
HideMegaTriggerSprite();
|
HideMegaTriggerSprite();
|
||||||
|
TryHideLastUsedBall();
|
||||||
PlayerBufferExecCompleted();
|
PlayerBufferExecCompleted();
|
||||||
}
|
}
|
||||||
else if (gMain.newKeys & B_BUTTON || gPlayerDpadHoldFrames > 59)
|
else if (gMain.newKeys & B_BUTTON || gPlayerDpadHoldFrames > 59)
|
||||||
@ -606,6 +618,7 @@ static void HandleInputChooseMove(void)
|
|||||||
else
|
else
|
||||||
BtlController_EmitTwoReturnValues(1, 10, gMoveSelectionCursor[gActiveBattler] | (gMultiUsePlayerCursor << 8));
|
BtlController_EmitTwoReturnValues(1, 10, gMoveSelectionCursor[gActiveBattler] | (gMultiUsePlayerCursor << 8));
|
||||||
HideMegaTriggerSprite();
|
HideMegaTriggerSprite();
|
||||||
|
TryHideLastUsedBall();
|
||||||
PlayerBufferExecCompleted();
|
PlayerBufferExecCompleted();
|
||||||
}
|
}
|
||||||
else if (canSelectTarget == 1)
|
else if (canSelectTarget == 1)
|
||||||
@ -2696,6 +2709,7 @@ static void PlayerHandleChooseAction(void)
|
|||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
ActionSelectionDestroyCursorAt(i);
|
ActionSelectionDestroyCursorAt(i);
|
||||||
|
|
||||||
|
TryRestoreLastUsedBall();
|
||||||
ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBattler], 0);
|
ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBattler], 0);
|
||||||
BattleStringExpandPlaceholdersToDisplayedString(gText_WhatWillPkmnDo);
|
BattleStringExpandPlaceholdersToDisplayedString(gText_WhatWillPkmnDo);
|
||||||
BattlePutTextOnWindow(gDisplayedStringBattle, 1);
|
BattlePutTextOnWindow(gDisplayedStringBattle, 1);
|
||||||
|
@ -27,6 +27,10 @@
|
|||||||
#include "constants/battle_config.h"
|
#include "constants/battle_config.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "pokemon_summary_screen.h"
|
#include "pokemon_summary_screen.h"
|
||||||
|
#include "item_icon.h"
|
||||||
|
#include "item_use.h"
|
||||||
|
#include "item.h"
|
||||||
|
#include "constants/items.h"
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{ // Corresponds to gHealthboxElementsGfxTable (and the tables after it) in graphics.c
|
{ // Corresponds to gHealthboxElementsGfxTable (and the tables after it) in graphics.c
|
||||||
@ -196,6 +200,9 @@ static u8 CalcBarFilledPixels(s32 maxValue, s32 oldValue, s32 receivedValue, s32
|
|||||||
static void SpriteCb_AbilityPopUp(struct Sprite *sprite);
|
static void SpriteCb_AbilityPopUp(struct Sprite *sprite);
|
||||||
static void Task_FreeAbilityPopUpGfx(u8 taskId);
|
static void Task_FreeAbilityPopUpGfx(u8 taskId);
|
||||||
|
|
||||||
|
static void SpriteCB_LastUsedBall(struct Sprite *sprite);
|
||||||
|
static void SpriteCB_LastUsedBallWin(struct Sprite *sprite);
|
||||||
|
|
||||||
// const rom data
|
// const rom data
|
||||||
static const struct OamData sUnknown_0832C138 =
|
static const struct OamData sUnknown_0832C138 =
|
||||||
{
|
{
|
||||||
@ -723,6 +730,12 @@ u8 GetMegaIndicatorSpriteId(u32 healthboxSpriteId)
|
|||||||
return gSprites[spriteId].hOther_IndicatorSpriteId;
|
return gSprites[spriteId].hOther_IndicatorSpriteId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void InitLastUsedBallAssets(void)
|
||||||
|
{
|
||||||
|
gBattleStruct->ballSpriteIds[0] = MAX_SPRITES;
|
||||||
|
gBattleStruct->ballSpriteIds[1] = MAX_SPRITES;
|
||||||
|
}
|
||||||
|
|
||||||
u8 CreateBattlerHealthboxSprites(u8 battlerId)
|
u8 CreateBattlerHealthboxSprites(u8 battlerId)
|
||||||
{
|
{
|
||||||
s16 data6 = 0;
|
s16 data6 = 0;
|
||||||
@ -812,6 +825,9 @@ u8 CreateBattlerHealthboxSprites(u8 battlerId)
|
|||||||
gSprites[megaIndicatorSpriteId].invisible = TRUE;
|
gSprites[megaIndicatorSpriteId].invisible = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gBattleStruct->ballSpriteIds[0] = MAX_SPRITES;
|
||||||
|
gBattleStruct->ballSpriteIds[1] = MAX_SPRITES;
|
||||||
|
|
||||||
return healthboxLeftSpriteId;
|
return healthboxLeftSpriteId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3123,3 +3139,200 @@ static void Task_FreeAbilityPopUpGfx(u8 taskId)
|
|||||||
DestroyTask(taskId);
|
DestroyTask(taskId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// last used ball
|
||||||
|
#define LAST_BALL_WINDOW_TAG 0xD721
|
||||||
|
|
||||||
|
static const struct OamData sOamData_LastUsedBall =
|
||||||
|
{
|
||||||
|
.y = 0,
|
||||||
|
.affineMode = 0,
|
||||||
|
.objMode = 0,
|
||||||
|
.mosaic = 0,
|
||||||
|
.bpp = 0,
|
||||||
|
.shape = SPRITE_SHAPE(32x32),
|
||||||
|
.x = 0,
|
||||||
|
.matrixNum = 0,
|
||||||
|
.size = SPRITE_SIZE(32x32),
|
||||||
|
.tileNum = 0,
|
||||||
|
.priority = 1,
|
||||||
|
.paletteNum = 0,
|
||||||
|
.affineParam = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct SpriteTemplate sSpriteTemplate_LastUsedBallWindow =
|
||||||
|
{
|
||||||
|
.tileTag = LAST_BALL_WINDOW_TAG,
|
||||||
|
.paletteTag = ABILITY_POP_UP_TAG,
|
||||||
|
.oam = &sOamData_LastUsedBall,
|
||||||
|
.anims = gDummySpriteAnimTable,
|
||||||
|
.images = NULL,
|
||||||
|
.affineAnims = gDummySpriteAffineAnimTable,
|
||||||
|
.callback = SpriteCB_LastUsedBallWin
|
||||||
|
};
|
||||||
|
|
||||||
|
#if B_LAST_USED_BALL_BUTTON == R_BUTTON
|
||||||
|
static const u8 sLastUsedBallWindowGfx[] = INCBIN_U8("graphics/battle_interface/last_used_ball_r.4bpp");
|
||||||
|
#else
|
||||||
|
static const u8 sLastUsedBallWindowGfx[] = INCBIN_U8("graphics/battle_interface/last_used_ball_l.4bpp");
|
||||||
|
#endif
|
||||||
|
static const struct SpriteSheet sSpriteSheet_LastUsedBallWindow =
|
||||||
|
{
|
||||||
|
sLastUsedBallWindowGfx, sizeof(sLastUsedBallWindowGfx), LAST_BALL_WINDOW_TAG
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LAST_USED_BALL_X_F 15
|
||||||
|
#define LAST_USED_BALL_X_0 -15
|
||||||
|
#define LAST_USED_BALL_Y ((IsDoubleBattle()) ? 78 : 68)
|
||||||
|
|
||||||
|
#define LAST_BALL_WIN_X_F (LAST_USED_BALL_X_F - 1)
|
||||||
|
#define LAST_BALL_WIN_X_0 (LAST_USED_BALL_X_0 - 0)
|
||||||
|
#define LAST_USED_WIN_Y (LAST_USED_BALL_Y - 8)
|
||||||
|
|
||||||
|
#define sHide data[0]
|
||||||
|
|
||||||
|
bool32 CanThrowLastUsedBall(void)
|
||||||
|
{
|
||||||
|
#if B_LAST_USED_BALL == FALSE
|
||||||
|
return FALSE;
|
||||||
|
#else
|
||||||
|
return (!(CanThrowBall() != 0
|
||||||
|
|| (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
|
||||||
|
|| !CheckBagHasItem(gLastThrownBall, 1)));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TryAddLastUsedBallItemSprites(void)
|
||||||
|
{
|
||||||
|
#if B_LAST_USED_BALL == TRUE
|
||||||
|
if (gLastThrownBall == 0
|
||||||
|
|| (gLastThrownBall != 0 && !CheckBagHasItem(gLastThrownBall, 1)))
|
||||||
|
{
|
||||||
|
// we're out of the last used ball, so just set it to the first ball in the bag
|
||||||
|
// we have to compact the bag first bc it is typically only compacted when you open it
|
||||||
|
CompactItemsInBagPocket(&gBagPockets[BALLS_POCKET]);
|
||||||
|
gLastThrownBall = gBagPockets[BALLS_POCKET].itemSlots[0].itemId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CanThrowBall() != 0
|
||||||
|
|| (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
|
||||||
|
|| !CheckBagHasItem(gLastThrownBall, 1))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// ball
|
||||||
|
if (gBattleStruct->ballSpriteIds[0] == MAX_SPRITES)
|
||||||
|
{
|
||||||
|
gBattleStruct->ballSpriteIds[0] = AddItemIconSprite(102, 102, gLastThrownBall);
|
||||||
|
gSprites[gBattleStruct->ballSpriteIds[0]].x = LAST_USED_BALL_X_0;
|
||||||
|
gSprites[gBattleStruct->ballSpriteIds[0]].y = LAST_USED_BALL_Y;
|
||||||
|
gSprites[gBattleStruct->ballSpriteIds[0]].sHide = FALSE; // restore
|
||||||
|
gSprites[gBattleStruct->ballSpriteIds[0]].callback = SpriteCB_LastUsedBall;
|
||||||
|
}
|
||||||
|
|
||||||
|
// window
|
||||||
|
LoadSpritePalette(&sSpritePalette_AbilityPopUp);
|
||||||
|
if (GetSpriteTileStartByTag(LAST_BALL_WINDOW_TAG) == 0xFFFF)
|
||||||
|
LoadSpriteSheet(&sSpriteSheet_LastUsedBallWindow);
|
||||||
|
|
||||||
|
if (gBattleStruct->ballSpriteIds[1] == MAX_SPRITES)
|
||||||
|
{
|
||||||
|
gBattleStruct->ballSpriteIds[1] = CreateSprite(&sSpriteTemplate_LastUsedBallWindow,
|
||||||
|
LAST_BALL_WIN_X_0,
|
||||||
|
LAST_USED_WIN_Y, 5);
|
||||||
|
gSprites[gBattleStruct->ballSpriteIds[0]].sHide = FALSE; // restore
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DestroyLastUsedBallWinGfx(struct Sprite *sprite)
|
||||||
|
{
|
||||||
|
FreeSpriteTilesByTag(LAST_BALL_WINDOW_TAG);
|
||||||
|
FreeSpritePaletteByTag(ABILITY_POP_UP_TAG);
|
||||||
|
DestroySprite(sprite);
|
||||||
|
gBattleStruct->ballSpriteIds[1] = MAX_SPRITES;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DestroyLastUsedBallGfx(struct Sprite *sprite)
|
||||||
|
{
|
||||||
|
FreeSpriteTilesByTag(102);
|
||||||
|
FreeSpritePaletteByTag(102);
|
||||||
|
DestroySprite(sprite);
|
||||||
|
gBattleStruct->ballSpriteIds[0] = MAX_SPRITES;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SpriteCB_LastUsedBallWin(struct Sprite *sprite)
|
||||||
|
{
|
||||||
|
if (sprite->sHide)
|
||||||
|
{
|
||||||
|
if (sprite->x != LAST_BALL_WIN_X_0)
|
||||||
|
sprite->x--;
|
||||||
|
|
||||||
|
if (sprite->x == LAST_BALL_WIN_X_0)
|
||||||
|
DestroyLastUsedBallWinGfx(sprite);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (sprite->x != LAST_BALL_WIN_X_F)
|
||||||
|
sprite->x++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SpriteCB_LastUsedBall(struct Sprite *sprite)
|
||||||
|
{
|
||||||
|
if (sprite->sHide)
|
||||||
|
{
|
||||||
|
if (sprite->x != LAST_USED_BALL_X_0)
|
||||||
|
sprite->x--;
|
||||||
|
|
||||||
|
if (sprite->x == LAST_USED_BALL_X_0)
|
||||||
|
DestroyLastUsedBallGfx(sprite);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (sprite->x != LAST_USED_BALL_X_F)
|
||||||
|
sprite->x++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TryHideOrRestoreLastUsedBall(u8 caseId)
|
||||||
|
{
|
||||||
|
#if B_LAST_USED_BALL == TRUE
|
||||||
|
if (gBattleStruct->ballSpriteIds[0] == MAX_SPRITES)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (caseId)
|
||||||
|
{
|
||||||
|
case 0: // hide
|
||||||
|
if (gBattleStruct->ballSpriteIds[0] != MAX_SPRITES)
|
||||||
|
gSprites[gBattleStruct->ballSpriteIds[0]].sHide = TRUE; // hide
|
||||||
|
if (gBattleStruct->ballSpriteIds[1] != MAX_SPRITES)
|
||||||
|
gSprites[gBattleStruct->ballSpriteIds[1]].sHide = TRUE; // hide
|
||||||
|
break;
|
||||||
|
case 1: // restore
|
||||||
|
if (gBattleStruct->ballSpriteIds[0] != MAX_SPRITES)
|
||||||
|
gSprites[gBattleStruct->ballSpriteIds[0]].sHide = FALSE; // restore
|
||||||
|
if (gBattleStruct->ballSpriteIds[1] != MAX_SPRITES)
|
||||||
|
gSprites[gBattleStruct->ballSpriteIds[1]].sHide = FALSE; // restore
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void TryHideLastUsedBall(void)
|
||||||
|
{
|
||||||
|
#if B_LAST_USED_BALL == TRUE
|
||||||
|
TryHideOrRestoreLastUsedBall(0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void TryRestoreLastUsedBall(void)
|
||||||
|
{
|
||||||
|
#if B_LAST_USED_BALL == TRUE
|
||||||
|
if (gBattleStruct->ballSpriteIds[0] != MAX_SPRITES)
|
||||||
|
TryHideOrRestoreLastUsedBall(1);
|
||||||
|
else
|
||||||
|
TryAddLastUsedBallItemSprites();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -230,6 +230,7 @@ EWRAM_DATA u16 gPartnerSpriteId = 0;
|
|||||||
EWRAM_DATA struct TotemBoost gTotemBoosts[MAX_BATTLERS_COUNT] = {0};
|
EWRAM_DATA struct TotemBoost gTotemBoosts[MAX_BATTLERS_COUNT] = {0};
|
||||||
EWRAM_DATA bool8 gHasFetchedBall = FALSE;
|
EWRAM_DATA bool8 gHasFetchedBall = FALSE;
|
||||||
EWRAM_DATA u8 gLastUsedBall = 0;
|
EWRAM_DATA u8 gLastUsedBall = 0;
|
||||||
|
EWRAM_DATA u16 gLastThrownBall = 0;
|
||||||
|
|
||||||
// IWRAM common vars
|
// IWRAM common vars
|
||||||
void (*gPreBattleCallback1)(void);
|
void (*gPreBattleCallback1)(void);
|
||||||
@ -401,6 +402,7 @@ static void (* const sTurnActionsFuncsTable[])(void) =
|
|||||||
[B_ACTION_TRY_FINISH] = HandleAction_TryFinish,
|
[B_ACTION_TRY_FINISH] = HandleAction_TryFinish,
|
||||||
[B_ACTION_FINISHED] = HandleAction_ActionFinished,
|
[B_ACTION_FINISHED] = HandleAction_ActionFinished,
|
||||||
[B_ACTION_NOTHING_FAINTED] = HandleAction_NothingIsFainted,
|
[B_ACTION_NOTHING_FAINTED] = HandleAction_NothingIsFainted,
|
||||||
|
[B_ACTION_THROW_BALL] = HandleAction_ThrowBall,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void (* const sEndTurnFuncsTable[])(void) =
|
static void (* const sEndTurnFuncsTable[])(void) =
|
||||||
@ -4073,6 +4075,10 @@ static void HandleTurnActionSelectionState(void)
|
|||||||
case B_ACTION_SAFARI_BALL:
|
case B_ACTION_SAFARI_BALL:
|
||||||
gBattleCommunication[gActiveBattler]++;
|
gBattleCommunication[gActiveBattler]++;
|
||||||
break;
|
break;
|
||||||
|
case B_ACTION_THROW_BALL:
|
||||||
|
gBattleStruct->throwingPokeBall = TRUE;
|
||||||
|
gBattleCommunication[gActiveBattler]++;
|
||||||
|
break;
|
||||||
case B_ACTION_SAFARI_POKEBLOCK:
|
case B_ACTION_SAFARI_POKEBLOCK:
|
||||||
if ((gBattleResources->bufferB[gActiveBattler][1] | (gBattleResources->bufferB[gActiveBattler][2] << 8)) != 0)
|
if ((gBattleResources->bufferB[gActiveBattler][1] | (gBattleResources->bufferB[gActiveBattler][2] << 8)) != 0)
|
||||||
{
|
{
|
||||||
@ -4186,6 +4192,13 @@ static void HandleTurnActionSelectionState(void)
|
|||||||
if (gBattleCommunication[ACTIONS_CONFIRMED_COUNT] == gBattlersCount)
|
if (gBattleCommunication[ACTIONS_CONFIRMED_COUNT] == gBattlersCount)
|
||||||
{
|
{
|
||||||
sub_818603C(1);
|
sub_818603C(1);
|
||||||
|
|
||||||
|
if (WILD_DOUBLE_BATTLE && gBattleStruct->throwingPokeBall) {
|
||||||
|
// if we choose to throw a ball with our second mon, skip the action of the first
|
||||||
|
// (if we have chosen throw ball with first, second's is already skipped)
|
||||||
|
gChosenActionByBattler[B_POSITION_PLAYER_LEFT] = B_ACTION_NOTHING_FAINTED;
|
||||||
|
}
|
||||||
|
|
||||||
gBattleMainFunc = SetActionsAndBattlersTurnOrder;
|
gBattleMainFunc = SetActionsAndBattlersTurnOrder;
|
||||||
|
|
||||||
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
|
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
|
||||||
@ -4507,7 +4520,9 @@ static void SetActionsAndBattlersTurnOrder(void)
|
|||||||
{
|
{
|
||||||
for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++)
|
for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++)
|
||||||
{
|
{
|
||||||
if (gChosenActionByBattler[gActiveBattler] == B_ACTION_USE_ITEM || gChosenActionByBattler[gActiveBattler] == B_ACTION_SWITCH)
|
if (gChosenActionByBattler[gActiveBattler] == B_ACTION_USE_ITEM
|
||||||
|
|| gChosenActionByBattler[gActiveBattler] == B_ACTION_SWITCH
|
||||||
|
|| gChosenActionByBattler[gActiveBattler] == B_ACTION_THROW_BALL)
|
||||||
{
|
{
|
||||||
gActionsByTurnOrder[turnOrderId] = gChosenActionByBattler[gActiveBattler];
|
gActionsByTurnOrder[turnOrderId] = gChosenActionByBattler[gActiveBattler];
|
||||||
gBattlerByTurnOrder[turnOrderId] = gActiveBattler;
|
gBattlerByTurnOrder[turnOrderId] = gActiveBattler;
|
||||||
@ -4516,7 +4531,9 @@ static void SetActionsAndBattlersTurnOrder(void)
|
|||||||
}
|
}
|
||||||
for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++)
|
for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++)
|
||||||
{
|
{
|
||||||
if (gChosenActionByBattler[gActiveBattler] != B_ACTION_USE_ITEM && gChosenActionByBattler[gActiveBattler] != B_ACTION_SWITCH)
|
if (gChosenActionByBattler[gActiveBattler] != B_ACTION_USE_ITEM
|
||||||
|
&& gChosenActionByBattler[gActiveBattler] != B_ACTION_SWITCH
|
||||||
|
&& gChosenActionByBattler[gActiveBattler] != B_ACTION_THROW_BALL)
|
||||||
{
|
{
|
||||||
gActionsByTurnOrder[turnOrderId] = gChosenActionByBattler[gActiveBattler];
|
gActionsByTurnOrder[turnOrderId] = gChosenActionByBattler[gActiveBattler];
|
||||||
gBattlerByTurnOrder[turnOrderId] = gActiveBattler;
|
gBattlerByTurnOrder[turnOrderId] = gActiveBattler;
|
||||||
@ -4532,7 +4549,9 @@ static void SetActionsAndBattlersTurnOrder(void)
|
|||||||
if (gActionsByTurnOrder[i] != B_ACTION_USE_ITEM
|
if (gActionsByTurnOrder[i] != B_ACTION_USE_ITEM
|
||||||
&& gActionsByTurnOrder[j] != B_ACTION_USE_ITEM
|
&& gActionsByTurnOrder[j] != B_ACTION_USE_ITEM
|
||||||
&& gActionsByTurnOrder[i] != B_ACTION_SWITCH
|
&& gActionsByTurnOrder[i] != B_ACTION_SWITCH
|
||||||
&& gActionsByTurnOrder[j] != B_ACTION_SWITCH)
|
&& gActionsByTurnOrder[j] != B_ACTION_SWITCH
|
||||||
|
&& gActionsByTurnOrder[i] != B_ACTION_THROW_BALL
|
||||||
|
&& gActionsByTurnOrder[j] != B_ACTION_THROW_BALL)
|
||||||
{
|
{
|
||||||
if (GetWhoStrikesFirst(battler1, battler2, FALSE))
|
if (GetWhoStrikesFirst(battler1, battler2, FALSE))
|
||||||
SwapTurnOrder(i, j);
|
SwapTurnOrder(i, j);
|
||||||
|
@ -12512,7 +12512,8 @@ static void Cmd_handleballthrow(void)
|
|||||||
{
|
{
|
||||||
u32 odds;
|
u32 odds;
|
||||||
u8 catchRate;
|
u8 catchRate;
|
||||||
|
|
||||||
|
gLastThrownBall = gLastUsedItem;
|
||||||
if (gLastUsedItem == ITEM_SAFARI_BALL)
|
if (gLastUsedItem == ITEM_SAFARI_BALL)
|
||||||
catchRate = gBattleStruct->safariCatchFactor * 1275 / 100;
|
catchRate = gBattleStruct->safariCatchFactor * 1275 / 100;
|
||||||
else
|
else
|
||||||
|
@ -756,6 +756,17 @@ void HandleAction_SafariZoneBallThrow(void)
|
|||||||
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
|
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HandleAction_ThrowBall(void)
|
||||||
|
{
|
||||||
|
gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
|
||||||
|
gBattle_BG0_X = 0;
|
||||||
|
gBattle_BG0_Y = 0;
|
||||||
|
gLastUsedItem = gLastThrownBall;
|
||||||
|
RemoveBagItem(gLastUsedItem, 1);
|
||||||
|
gBattlescriptCurrInstr = BattleScript_BallThrow;
|
||||||
|
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
|
||||||
|
}
|
||||||
|
|
||||||
void HandleAction_ThrowPokeblock(void)
|
void HandleAction_ThrowPokeblock(void)
|
||||||
{
|
{
|
||||||
gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
|
gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
|
||||||
|
@ -936,42 +936,46 @@ void ItemUseOutOfBattle_EvolutionStone(u8 taskId)
|
|||||||
SetUpItemUseCallback(taskId);
|
SetUpItemUseCallback(taskId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemUseInBattle_PokeBall(u8 taskId)
|
u32 CanThrowBall(void)
|
||||||
{
|
{
|
||||||
if (IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT))
|
if (IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT))
|
||||||
&& IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT))) // There are two present pokemon.
|
&& IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)))
|
||||||
{
|
{
|
||||||
static const u8 textCantThrowPokeBall[] = _("Cannot throw a ball!\nThere are two pokemon out there!\p");
|
return 1; // There are two present pokemon.
|
||||||
|
|
||||||
if (!InBattlePyramid())
|
|
||||||
DisplayItemMessage(taskId, 1, textCantThrowPokeBall, CloseItemMessage);
|
|
||||||
else
|
|
||||||
DisplayItemMessageInBattlePyramid(taskId, textCantThrowPokeBall, Task_CloseBattlePyramidBagMessage);
|
|
||||||
}
|
}
|
||||||
else if (gBattlerInMenuId == GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT)
|
else if (IsPlayerPartyAndPokemonStorageFull() == TRUE)
|
||||||
&& IsBattlerAlive(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT))) // Attempting to throw a ball with the second pokemon while both are alive.
|
|
||||||
{
|
{
|
||||||
static const u8 textCantThrowPokeBall[] = _("Cannot throw a ball!\p");
|
return 2; // No room for mon
|
||||||
|
|
||||||
if (!InBattlePyramid())
|
|
||||||
DisplayItemMessage(taskId, 1, textCantThrowPokeBall, CloseItemMessage);
|
|
||||||
else
|
|
||||||
DisplayItemMessageInBattlePyramid(taskId, textCantThrowPokeBall, Task_CloseBattlePyramidBagMessage);
|
|
||||||
}
|
}
|
||||||
else if (IsPlayerPartyAndPokemonStorageFull() == FALSE) // have room for mon?
|
|
||||||
|
return 0; // usable
|
||||||
|
}
|
||||||
|
|
||||||
|
static const u8 sText_CantThrowPokeBall_TwoMons[] = _("Cannot throw a ball!\nThere are two pokemon out there!\p");
|
||||||
|
void ItemUseInBattle_PokeBall(u8 taskId)
|
||||||
|
{
|
||||||
|
switch (CanThrowBall())
|
||||||
{
|
{
|
||||||
|
case 0: // usable
|
||||||
|
default:
|
||||||
RemoveBagItem(gSpecialVar_ItemId, 1);
|
RemoveBagItem(gSpecialVar_ItemId, 1);
|
||||||
if (!InBattlePyramid())
|
if (!InBattlePyramid())
|
||||||
Task_FadeAndCloseBagMenu(taskId);
|
Task_FadeAndCloseBagMenu(taskId);
|
||||||
else
|
else
|
||||||
CloseBattlePyramidBag(taskId);
|
CloseBattlePyramidBag(taskId);
|
||||||
}
|
break;
|
||||||
else
|
case 1: // There are two present pokemon.
|
||||||
{
|
if (!InBattlePyramid())
|
||||||
|
DisplayItemMessage(taskId, 1, sText_CantThrowPokeBall_TwoMons, CloseItemMessage);
|
||||||
|
else
|
||||||
|
DisplayItemMessageInBattlePyramid(taskId, sText_CantThrowPokeBall_TwoMons, Task_CloseBattlePyramidBagMessage);
|
||||||
|
break;
|
||||||
|
case 2: // No room for mon
|
||||||
if (!InBattlePyramid())
|
if (!InBattlePyramid())
|
||||||
DisplayItemMessage(taskId, 1, gText_BoxFull, CloseItemMessage);
|
DisplayItemMessage(taskId, 1, gText_BoxFull, CloseItemMessage);
|
||||||
else
|
else
|
||||||
DisplayItemMessageInBattlePyramid(taskId, gText_BoxFull, Task_CloseBattlePyramidBagMessage);
|
DisplayItemMessageInBattlePyramid(taskId, gText_BoxFull, Task_CloseBattlePyramidBagMessage);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include "berry_powder.h"
|
#include "berry_powder.h"
|
||||||
#include "mevent.h"
|
#include "mevent.h"
|
||||||
#include "union_room_chat.h"
|
#include "union_room_chat.h"
|
||||||
|
#include "constants/items.h"
|
||||||
|
|
||||||
extern const u8 EventScript_ResetAllMapFlags[];
|
extern const u8 EventScript_ResetAllMapFlags[];
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user