mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-11-16 11:37:40 +01:00
Implement double wild battle functionality
This commit is contained in:
parent
ef11706dc7
commit
67384c08be
@ -399,6 +399,7 @@ B_BUFF3 = FD 34
|
||||
B_ATK_TRAINER_NAME = FD 35
|
||||
B_ATK_TRAINER_CLASS = FD 36
|
||||
B_ATK_TEAM = FD 37
|
||||
B_DEF_NAME = FD 38
|
||||
|
||||
@ indicates the end of a town/city name (before " TOWN" or " CITY")
|
||||
NAME_END = FC 00
|
||||
|
@ -581,6 +581,7 @@ struct BattleStruct
|
||||
u32 debugAIFlags;
|
||||
bool8 notfirstTimeAIFlags;
|
||||
u8 activeAbilityPopUps; // as bits for each battler
|
||||
bool8 throwingPokeBall;
|
||||
struct MegaEvolutionData mega;
|
||||
};
|
||||
|
||||
|
@ -60,6 +60,7 @@
|
||||
#define B_TXT_ATK_TRAINER_NAME 0x35
|
||||
#define B_TXT_ATK_TRAINER_CLASS 0x36
|
||||
#define B_TXT_ATK_TEAM 0x37
|
||||
#define B_TXT_DEF_NAME 0x38
|
||||
|
||||
// for B_TXT_BUFF1, B_TXT_BUFF2 and B_TXT_BUFF3
|
||||
|
||||
|
@ -2452,7 +2452,7 @@ static void PlayerHandleSuccessBallThrowAnim(void)
|
||||
{
|
||||
gBattleSpritesDataPtr->animationData->ballThrowCaseId = BALL_3_SHAKES_SUCCESS;
|
||||
gDoingBattleAnim = TRUE;
|
||||
InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), B_ANIM_BALL_THROW);
|
||||
InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, gBattlerTarget, B_ANIM_BALL_THROW);
|
||||
gBattlerControllerFuncs[gActiveBattler] = CompleteOnSpecialAnimDone;
|
||||
}
|
||||
|
||||
@ -2462,7 +2462,7 @@ static void PlayerHandleBallThrowAnim(void)
|
||||
|
||||
gBattleSpritesDataPtr->animationData->ballThrowCaseId = ballThrowCaseId;
|
||||
gDoingBattleAnim = TRUE;
|
||||
InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), B_ANIM_BALL_THROW);
|
||||
InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, gBattlerTarget, B_ANIM_BALL_THROW);
|
||||
gBattlerControllerFuncs[gActiveBattler] = CompleteOnSpecialAnimDone;
|
||||
}
|
||||
|
||||
|
@ -4063,6 +4063,19 @@ u8 IsRunningFromBattleImpossible(void)
|
||||
|
||||
gPotentialItemEffectBattler = gActiveBattler;
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE) // Cannot ever run from saving Birch's battle.
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
|
||||
return 1;
|
||||
}
|
||||
if (GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_RIGHT
|
||||
&& gBattleTypeFlags & BATTLE_TYPE_DOUBLE
|
||||
&& !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_LINK))) // The second pokemon cannot run from a double wild battle.
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (holdEffect == HOLD_EFFECT_CAN_ALWAYS_RUN)
|
||||
return 0;
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_LINK)
|
||||
@ -4107,11 +4120,6 @@ u8 IsRunningFromBattleImpossible(void)
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
|
||||
return 1;
|
||||
}
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4197,6 +4205,13 @@ static void HandleTurnActionSelectionState(void)
|
||||
gChosenActionByBattler[gActiveBattler] = B_ACTION_USE_MOVE;
|
||||
gBattleCommunication[gActiveBattler] = STATE_WAIT_ACTION_CONFIRMED_STANDBY;
|
||||
}
|
||||
else if (position == B_POSITION_PLAYER_RIGHT
|
||||
&& (gBattleStruct->throwingPokeBall || gChosenActionByBattler[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)] == B_ACTION_RUN))
|
||||
{
|
||||
gBattleStruct->throwingPokeBall = FALSE;
|
||||
gChosenActionByBattler[gActiveBattler] = B_ACTION_NOTHING_FAINTED; // Not fainted, but it cannot move, because of the throwing ball.
|
||||
gBattleCommunication[gActiveBattler] = STATE_WAIT_ACTION_CONFIRMED_STANDBY;
|
||||
}
|
||||
else
|
||||
{
|
||||
BtlController_EmitChooseAction(0, gChosenActionByBattler[0], gBattleBufferB[0][1] | (gBattleBufferB[0][2] << 8));
|
||||
@ -4454,6 +4469,8 @@ static void HandleTurnActionSelectionState(void)
|
||||
else
|
||||
{
|
||||
gLastUsedItem = (gBattleBufferB[gActiveBattler][1] | (gBattleBufferB[gActiveBattler][2] << 8));
|
||||
if (ItemId_GetPocket(gLastUsedItem) == POCKET_POKE_BALLS)
|
||||
gBattleStruct->throwingPokeBall = TRUE;
|
||||
gBattleCommunication[gActiveBattler]++;
|
||||
}
|
||||
break;
|
||||
@ -5804,25 +5821,26 @@ bool8 TryRunFromBattle(u8 battler)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
|
||||
u8 runningFromBattler = BATTLE_OPPOSITE(battler);
|
||||
if (!IsBattlerAlive(runningFromBattler))
|
||||
runningFromBattler |= BIT_FLANK;
|
||||
|
||||
if (InBattlePyramid())
|
||||
{
|
||||
if (InBattlePyramid())
|
||||
{
|
||||
pyramidMultiplier = sub_81A9E28();
|
||||
speedVar = (gBattleMons[battler].speed * pyramidMultiplier) / (gBattleMons[BATTLE_OPPOSITE(battler)].speed) + (gBattleStruct->runTries * 30);
|
||||
if (speedVar > (Random() & 0xFF))
|
||||
effect++;
|
||||
}
|
||||
else if (gBattleMons[battler].speed < gBattleMons[BATTLE_OPPOSITE(battler)].speed)
|
||||
{
|
||||
speedVar = (gBattleMons[battler].speed * 128) / (gBattleMons[BATTLE_OPPOSITE(battler)].speed) + (gBattleStruct->runTries * 30);
|
||||
if (speedVar > (Random() & 0xFF))
|
||||
effect++;
|
||||
}
|
||||
else // same speed or faster
|
||||
{
|
||||
pyramidMultiplier = sub_81A9E28();
|
||||
speedVar = (gBattleMons[battler].speed * pyramidMultiplier) / (gBattleMons[runningFromBattler].speed) + (gBattleStruct->runTries * 30);
|
||||
if (speedVar > (Random() & 0xFF))
|
||||
effect++;
|
||||
}
|
||||
}
|
||||
else if (gBattleMons[battler].speed < gBattleMons[runningFromBattler].speed)
|
||||
{
|
||||
speedVar = (gBattleMons[battler].speed * 128) / (gBattleMons[runningFromBattler].speed) + (gBattleStruct->runTries * 30);
|
||||
if (speedVar > (Random() & 0xFF))
|
||||
effect++;
|
||||
}
|
||||
else // same speed or faster
|
||||
{
|
||||
effect++;
|
||||
}
|
||||
|
||||
gBattleStruct->runTries++;
|
||||
|
@ -477,13 +477,13 @@ static const u8 sText_PkmnBrokeFree[] = _("Oh, no!\nThe POKéMON broke free!");
|
||||
static const u8 sText_ItAppearedCaught[] = _("Aww!\nIt appeared to be caught!");
|
||||
static const u8 sText_AarghAlmostHadIt[] = _("Aargh!\nAlmost had it!");
|
||||
static const u8 sText_ShootSoClose[] = _("Shoot!\nIt was so close, too!");
|
||||
static const u8 sText_GotchaPkmnCaught[] = _("Gotcha!\n{B_OPPONENT_MON1_NAME} was caught!{UNKNOWN_A}{PLAY_BGM MUS_KACHI22}\p");
|
||||
static const u8 sText_GotchaPkmnCaught2[] = _("Gotcha!\n{B_OPPONENT_MON1_NAME} was caught!{UNKNOWN_A}{PLAY_BGM MUS_KACHI22}{PAUSE 127}");
|
||||
static const u8 sText_GiveNicknameCaptured[] = _("Give a nickname to the\ncaptured {B_OPPONENT_MON1_NAME}?");
|
||||
static const u8 sText_PkmnSentToPC[] = _("{B_OPPONENT_MON1_NAME} was sent to\n{B_PC_CREATOR_NAME} PC.");
|
||||
static const u8 sText_GotchaPkmnCaught[] = _("Gotcha!\n{B_DEF_NAME} was caught!{UNKNOWN_A}{PLAY_BGM MUS_KACHI22}\p");
|
||||
static const u8 sText_GotchaPkmnCaught2[] = _("Gotcha!\n{B_DEF_NAME} was caught!{UNKNOWN_A}{PLAY_BGM MUS_KACHI22}{PAUSE 127}");
|
||||
static const u8 sText_GiveNicknameCaptured[] = _("Give a nickname to the\ncaptured {B_DEF_NAME}?");
|
||||
static const u8 sText_PkmnSentToPC[] = _("{B_DEF_NAME} was sent to\n{B_PC_CREATOR_NAME} PC.");
|
||||
static const u8 sText_Someones[] = _("someone’s");
|
||||
static const u8 sText_Lanettes[] = _("LANETTE’s");
|
||||
static const u8 sText_PkmnDataAddedToDex[] = _("{B_OPPONENT_MON1_NAME}’s data was\nadded to the POKéDEX.\p");
|
||||
static const u8 sText_PkmnDataAddedToDex[] = _("{B_DEF_NAME}’s data was\nadded to the POKéDEX.\p");
|
||||
static const u8 sText_ItIsRaining[] = _("It is raining.");
|
||||
static const u8 sText_SandstormIsRaging[] = _("A sandstorm is raging.");
|
||||
static const u8 sText_BoxIsFull[] = _("The BOX is full!\nYou can’t catch any more!\p");
|
||||
@ -2858,6 +2858,15 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst)
|
||||
case B_TXT_DEF_NAME_WITH_PREFIX: // target name with prefix
|
||||
HANDLE_NICKNAME_STRING_CASE(gBattlerTarget, gBattlerPartyIndexes[gBattlerTarget])
|
||||
break;
|
||||
case B_TXT_DEF_NAME: // target name
|
||||
if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER)
|
||||
GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_NICKNAME, text);
|
||||
else
|
||||
GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_NICKNAME, text);
|
||||
|
||||
StringGetEnd10(text);
|
||||
toCpy = text;
|
||||
break;
|
||||
case B_TXT_EFF_NAME_WITH_PREFIX: // effect battlerId name with prefix
|
||||
HANDLE_NICKNAME_STRING_CASE(gEffectBattler, gBattlerPartyIndexes[gEffectBattler])
|
||||
break;
|
||||
|
@ -10480,6 +10480,14 @@ static void atkEE_removelightscreenreflect(void) // brick break
|
||||
gBattlescriptCurrInstr++;
|
||||
}
|
||||
|
||||
static u8 GetCatchingBattler(void)
|
||||
{
|
||||
if (IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)))
|
||||
return GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
|
||||
else
|
||||
return GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
|
||||
}
|
||||
|
||||
static void atkEF_handleballthrow(void)
|
||||
{
|
||||
u8 ballMultiplier = 0;
|
||||
@ -10488,9 +10496,7 @@ static void atkEF_handleballthrow(void)
|
||||
return;
|
||||
|
||||
gActiveBattler = gBattlerAttacker;
|
||||
gBattlerTarget = gBattlerAttacker ^ BIT_SIDE;
|
||||
if (!IsBattlerAlive(gBattlerTarget))
|
||||
gBattlerTarget ^= BIT_FLANK;
|
||||
gBattlerTarget = GetCatchingBattler();
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
|
||||
{
|
||||
@ -10632,18 +10638,18 @@ static void atkEF_handleballthrow(void)
|
||||
|
||||
static void atkF0_givecaughtmon(void)
|
||||
{
|
||||
if (GiveMonToPlayer(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]]) != MON_GIVEN_TO_PARTY)
|
||||
if (GiveMonToPlayer(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]]) != MON_GIVEN_TO_PARTY)
|
||||
{
|
||||
if (!sub_813B21C())
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
|
||||
StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_STORAGE_UNKNOWN)));
|
||||
GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_NICKNAME, gStringVar2);
|
||||
GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_NICKNAME, gStringVar2);
|
||||
}
|
||||
else
|
||||
{
|
||||
StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_STORAGE_UNKNOWN)));
|
||||
GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_NICKNAME, gStringVar2);
|
||||
GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_NICKNAME, gStringVar2);
|
||||
StringCopy(gStringVar3, GetBoxNamePtr(get_unknown_box_id()));
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
|
||||
}
|
||||
@ -10652,17 +10658,17 @@ static void atkF0_givecaughtmon(void)
|
||||
gBattleCommunication[MULTISTRING_CHOOSER]++;
|
||||
}
|
||||
|
||||
gBattleResults.caughtMonSpecies = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_SPECIES, NULL);
|
||||
GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_NICKNAME, gBattleResults.caughtMonNick);
|
||||
gBattleResults.caughtMonBall = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, NULL);
|
||||
gBattleResults.caughtMonSpecies = GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_SPECIES, NULL);
|
||||
GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_NICKNAME, gBattleResults.caughtMonNick);
|
||||
gBattleResults.caughtMonBall = GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_POKEBALL, NULL);
|
||||
|
||||
gBattlescriptCurrInstr++;
|
||||
}
|
||||
|
||||
static void atkF1_trysetcaughtmondexflags(void)
|
||||
{
|
||||
u16 species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_SPECIES, NULL);
|
||||
u32 personality = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_PERSONALITY, NULL);
|
||||
u16 species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_SPECIES, NULL);
|
||||
u32 personality = GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_PERSONALITY, NULL);
|
||||
|
||||
if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(species), FLAG_GET_CAUGHT))
|
||||
{
|
||||
@ -10677,7 +10683,7 @@ static void atkF1_trysetcaughtmondexflags(void)
|
||||
|
||||
static void atkF2_displaydexinfo(void)
|
||||
{
|
||||
u16 species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_SPECIES, NULL);
|
||||
u16 species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_SPECIES, NULL);
|
||||
|
||||
switch (gBattleCommunication[0])
|
||||
{
|
||||
@ -10690,8 +10696,8 @@ static void atkF2_displaydexinfo(void)
|
||||
{
|
||||
FreeAllWindowBuffers();
|
||||
gBattleCommunication[TASK_ID] = CreateDexDisplayMonDataTask(SpeciesToNationalPokedexNum(species),
|
||||
gBattleMons[gBattlerTarget].otId,
|
||||
gBattleMons[gBattlerTarget].personality);
|
||||
gBattleMons[GetCatchingBattler()].otId,
|
||||
gBattleMons[GetCatchingBattler()].personality);
|
||||
gBattleCommunication[0]++;
|
||||
}
|
||||
break;
|
||||
|
@ -941,6 +941,15 @@ void ItemUseInBattle_PokeBall(u8 taskId)
|
||||
else
|
||||
DisplayItemMessageInBattlePyramid(taskId, textCantThrowPokeBall, sub_81C6714);
|
||||
}
|
||||
else if (gBattlerInMenuId == GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT)) // Attempting to throw a ball with the second pokemon.
|
||||
{
|
||||
u8 textCantThrowPokeBall[] = _("Cannot throw a ball!\p");
|
||||
|
||||
if (!InBattlePyramid())
|
||||
DisplayItemMessage(taskId, 1, textCantThrowPokeBall, bag_menu_inits_lists_menu);
|
||||
else
|
||||
DisplayItemMessageInBattlePyramid(taskId, textCantThrowPokeBall, sub_81C6714);
|
||||
}
|
||||
else if (IsPlayerPartyAndPokemonStorageFull() == FALSE) // have room for mon?
|
||||
{
|
||||
RemoveBagItem(gSpecialVar_ItemId, 1);
|
||||
|
Loading…
Reference in New Issue
Block a user