Fix order of messages in gen6 exp share (#3339)

Co-authored-by: Eduardo Quezada D'Ottone <eduardo602002@gmail.com>
This commit is contained in:
DizzyEggg 2023-09-24 22:07:56 +02:00 committed by GitHub
parent b77dec1234
commit 996bc6ba24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 129 additions and 106 deletions

View File

@ -536,7 +536,15 @@ struct BattleStruct
u8 turnCountersTracker; u8 turnCountersTracker;
u16 wrappedMove[MAX_BATTLERS_COUNT]; u16 wrappedMove[MAX_BATTLERS_COUNT];
u16 moveTarget[MAX_BATTLERS_COUNT]; u16 moveTarget[MAX_BATTLERS_COUNT];
u32 expShareExpValue;
u32 expValue;
u8 expGettersOrder[PARTY_SIZE]; // First battlers which were sent out, then via exp-share
u8 expGetterMonId; u8 expGetterMonId;
u8 expOrderId:3;
u8 expGetterBattlerId:2;
u8 teamGotExpMsgPrinted:1; // The 'Rest of your team got msg' has been printed.
u8 givenExpMons; // Bits for enemy party's pokemon that gave exp to player's party.
u8 expSentInMons; // As bits for player party mons - not including exp share mons.
u8 wildVictorySong; u8 wildVictorySong;
u8 dynamicMoveType; u8 dynamicMoveType;
u8 wrappedBy[MAX_BATTLERS_COUNT]; u8 wrappedBy[MAX_BATTLERS_COUNT];
@ -549,9 +557,7 @@ struct BattleStruct
u8 switchInAbilitiesCounter; u8 switchInAbilitiesCounter;
u8 faintedActionsState; u8 faintedActionsState;
u8 faintedActionsBattlerId; u8 faintedActionsBattlerId;
u32 expValue;
u8 scriptPartyIdx; // for printing the nickname u8 scriptPartyIdx; // for printing the nickname
u8 sentInPokes;
bool8 selectionScriptFinished[MAX_BATTLERS_COUNT]; bool8 selectionScriptFinished[MAX_BATTLERS_COUNT];
u8 battlerPartyIndexes[MAX_BATTLERS_COUNT]; u8 battlerPartyIndexes[MAX_BATTLERS_COUNT];
u8 monToSwitchIntoId[MAX_BATTLERS_COUNT]; u8 monToSwitchIntoId[MAX_BATTLERS_COUNT];
@ -569,7 +575,6 @@ struct BattleStruct
u8 stateIdAfterSelScript[MAX_BATTLERS_COUNT]; u8 stateIdAfterSelScript[MAX_BATTLERS_COUNT];
u8 prevSelectedPartySlot; u8 prevSelectedPartySlot;
u8 stringMoveType; u8 stringMoveType;
u8 expGetterBattlerId;
u8 absentBattlerFlags; u8 absentBattlerFlags;
u8 palaceFlags; // First 4 bits are "is <= 50% HP and not asleep" for each battler, last 4 bits are selected moves to pass to AI u8 palaceFlags; // First 4 bits are "is <= 50% HP and not asleep" for each battler, last 4 bits are selected moves to pass to AI
u8 field_93; // related to choosing pokemon? u8 field_93; // related to choosing pokemon?
@ -592,7 +597,6 @@ struct BattleStruct
u8 switchInItemsCounter; u8 switchInItemsCounter;
u8 arenaTurnCounter; u8 arenaTurnCounter;
u8 turnSideTracker; u8 turnSideTracker;
u8 givenExpMons; // Bits for enemy party's pokemon that gave exp to player's party.
u16 lastTakenMoveFrom[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT]; // a 2-D array [target][attacker] u16 lastTakenMoveFrom[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT]; // a 2-D array [target][attacker]
union { union {
struct LinkBattlerHeader linkBattlerHeader; struct LinkBattlerHeader linkBattlerHeader;
@ -975,7 +979,6 @@ extern u16 gBattleWeather;
extern struct WishFutureKnock gWishFutureKnock; extern struct WishFutureKnock gWishFutureKnock;
extern u16 gIntroSlideFlags; extern u16 gIntroSlideFlags;
extern u8 gSentPokesToOpponent[2]; extern u8 gSentPokesToOpponent[2];
extern u16 gExpShareExp;
extern struct BattleEnigmaBerry gEnigmaBerries[MAX_BATTLERS_COUNT]; extern struct BattleEnigmaBerry gEnigmaBerries[MAX_BATTLERS_COUNT];
extern struct BattleScripting gBattleScripting; extern struct BattleScripting gBattleScripting;
extern struct BattleStruct *gBattleStruct; extern struct BattleStruct *gBattleStruct;

View File

@ -212,7 +212,6 @@ EWRAM_DATA u16 gBattleWeather = 0;
EWRAM_DATA struct WishFutureKnock gWishFutureKnock = {0}; EWRAM_DATA struct WishFutureKnock gWishFutureKnock = {0};
EWRAM_DATA u16 gIntroSlideFlags = 0; EWRAM_DATA u16 gIntroSlideFlags = 0;
EWRAM_DATA u8 gSentPokesToOpponent[2] = {0}; EWRAM_DATA u8 gSentPokesToOpponent[2] = {0};
EWRAM_DATA u16 gExpShareExp = 0;
EWRAM_DATA struct BattleEnigmaBerry gEnigmaBerries[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA struct BattleEnigmaBerry gEnigmaBerries[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA struct BattleScripting gBattleScripting = {0}; EWRAM_DATA struct BattleScripting gBattleScripting = {0};
EWRAM_DATA struct BattleStruct *gBattleStruct = NULL; EWRAM_DATA struct BattleStruct *gBattleStruct = NULL;

View File

@ -4023,19 +4023,28 @@ static void Cmd_jumpbasedontype(void)
FEATURE_FLAG_ASSERT(I_EXP_SHARE_FLAG, YouNeedToSetTheExpShareFlagToAnUnusedFlag); FEATURE_FLAG_ASSERT(I_EXP_SHARE_FLAG, YouNeedToSetTheExpShareFlagToAnUnusedFlag);
static u32 GetMonHoldEffect(struct Pokemon *mon)
{
u32 holdEffect;
u32 item = GetMonData(mon, MON_DATA_HELD_ITEM);
if (item == ITEM_ENIGMA_BERRY_E_READER)
holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
else
holdEffect = ItemId_GetHoldEffect(item);
return holdEffect;
}
static void Cmd_getexp(void) static void Cmd_getexp(void)
{ {
CMD_ARGS(u8 battler); CMD_ARGS(u8 battler);
u16 item; u32 holdEffect;
s32 i; // also used as stringId s32 i; // also used as stringId
u8 holdEffect; u8 *expMonId = &gBattleStruct->expGetterMonId;
s32 sentIn;
s32 viaExpShare = 0;
u32 *exp = &gBattleStruct->expValue;
gBattlerFainted = GetBattlerForBattleScript(cmd->battler); gBattlerFainted = GetBattlerForBattleScript(cmd->battler);
sentIn = gSentPokesToOpponent[(gBattlerFainted & 2) >> 1];
switch (gBattleScripting.getexpState) switch (gBattleScripting.getexpState)
{ {
@ -4061,26 +4070,42 @@ static void Cmd_getexp(void)
break; break;
case 1: // calculate experience points to redistribute case 1: // calculate experience points to redistribute
{ {
u32 calculatedExp; u32 orderId = 0;
s32 viaSentIn; u32 calculatedExp = 0;
u32 *exp = &gBattleStruct->expValue;
u32 sentInBits = gSentPokesToOpponent[(gBattlerFainted & 2) >> 1];
u32 expShareBits = 0;
s32 viaSentIn = 0;
s32 viaExpShare = 0;
for (viaSentIn = 0, i = 0; i < PARTY_SIZE; i++) for (i = 0; i < PARTY_SIZE; i++)
{ {
if (!IsValidForBattle(&gPlayerParty[i])) if (!IsValidForBattle(&gPlayerParty[i]))
continue; continue;
if (gBitTable[i] & sentIn) if (gBitTable[i] & sentInBits)
viaSentIn++; viaSentIn++;
item = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM); holdEffect = GetMonHoldEffect(&gPlayerParty[i]);
if (item == ITEM_ENIGMA_BERRY_E_READER)
holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
else
holdEffect = ItemId_GetHoldEffect(item);
if (holdEffect == HOLD_EFFECT_EXP_SHARE || IsGen6ExpShareEnabled()) if (holdEffect == HOLD_EFFECT_EXP_SHARE || IsGen6ExpShareEnabled())
{
expShareBits |= gBitTable[i];
viaExpShare++; viaExpShare++;
}
} }
// Get order of mons getting exp: 1. all mons via sent in, 2. all mons via exp share
for (i = 0; i < PARTY_SIZE; i++)
{
if (gBitTable[i] & sentInBits)
gBattleStruct->expGettersOrder[orderId++] = i;
}
for (i = 0; i < PARTY_SIZE; i++)
{
if (!(gBitTable[i] & sentInBits) && gBitTable[i] & expShareBits)
gBattleStruct->expGettersOrder[orderId++] = i;
}
if (orderId < PARTY_SIZE)
gBattleStruct->expGettersOrder[orderId] = PARTY_SIZE;
#if (B_SCALED_EXP >= GEN_5) && (B_SCALED_EXP != GEN_6) #if (B_SCALED_EXP >= GEN_5) && (B_SCALED_EXP != GEN_6)
calculatedExp = gSpeciesInfo[gBattleMons[gBattlerFainted].species].expYield * gBattleMons[gBattlerFainted].level / 5; calculatedExp = gSpeciesInfo[gBattleMons[gBattlerFainted].species].expYield * gBattleMons[gBattlerFainted].level / 5;
#else #else
@ -4097,54 +4122,49 @@ static void Cmd_getexp(void)
if (*exp == 0) if (*exp == 0)
*exp = 1; *exp = 1;
gExpShareExp = calculatedExp / 2 / viaExpShare; gBattleStruct->expShareExpValue = calculatedExp / 2 / viaExpShare;
if (gExpShareExp == 0) if (gBattleStruct->expShareExpValue == 0)
gExpShareExp = 1; gBattleStruct->expShareExpValue = 1;
} }
else else
{ {
*exp = SAFE_DIV(calculatedExp, viaSentIn); *exp = SAFE_DIV(calculatedExp, viaSentIn);
if (*exp == 0) if (*exp == 0)
*exp = 1; *exp = 1;
gExpShareExp = 0; gBattleStruct->expShareExpValue = 0;
} }
#else #else
*exp = calculatedExp; *exp = calculatedExp;
gExpShareExp = calculatedExp / 2; gBattleStruct->expShareExpValue = calculatedExp / 2;
if (gExpShareExp == 0) if (gBattleStruct->expShareExpValue == 0)
gExpShareExp = 1; gBattleStruct->expShareExpValue = 1;
#endif #endif
gBattleScripting.getexpState++; gBattleScripting.getexpState++;
gBattleStruct->expGetterMonId = 0; gBattleStruct->expOrderId = 0;
gBattleStruct->sentInPokes = sentIn; *expMonId = gBattleStruct->expGettersOrder[0];
gBattleStruct->expSentInMons = sentInBits;
} }
// fall through // fall through
case 2: // set exp value to the poke in expgetter_id and print message case 2: // set exp value to the poke in expgetter_id and print message
if (gBattleControllerExecFlags == 0) if (gBattleControllerExecFlags == 0)
{ {
item = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_HELD_ITEM); bool32 wasSentOut = ((gBattleStruct->expSentInMons & gBitTable[*expMonId]) != 0);
holdEffect = GetMonHoldEffect(&gPlayerParty[*expMonId]);
if (item == ITEM_ENIGMA_BERRY_E_READER) if ((holdEffect != HOLD_EFFECT_EXP_SHARE && !wasSentOut && !IsGen6ExpShareEnabled())
holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect; || GetMonData(&gPlayerParty[*expMonId], MON_DATA_SPECIES_OR_EGG) == SPECIES_EGG)
else
holdEffect = ItemId_GetHoldEffect(item);
if ((holdEffect != HOLD_EFFECT_EXP_SHARE && !(gBattleStruct->sentInPokes & 1) && !IsGen6ExpShareEnabled())
|| GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPECIES_OR_EGG) == SPECIES_EGG)
{ {
*(&gBattleStruct->sentInPokes) >>= 1;
gBattleScripting.getexpState = 5; gBattleScripting.getexpState = 5;
gBattleMoveDamage = 0; // used for exp gBattleMoveDamage = 0; // used for exp
} }
else if ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gBattleStruct->expGetterMonId >= 3) else if ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && *expMonId >= 3)
|| GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_LEVEL) == MAX_LEVEL) || GetMonData(&gPlayerParty[*expMonId], MON_DATA_LEVEL) == MAX_LEVEL)
{ {
*(&gBattleStruct->sentInPokes) >>= 1;
gBattleScripting.getexpState = 5; gBattleScripting.getexpState = 5;
gBattleMoveDamage = 0; // used for exp gBattleMoveDamage = 0; // used for exp
#if B_MAX_LEVEL_EV_GAINS >= GEN_5 #if B_MAX_LEVEL_EV_GAINS >= GEN_5
MonGainEVs(&gPlayerParty[gBattleStruct->expGetterMonId], gBattleMons[gBattlerFainted].species); MonGainEVs(&gPlayerParty[*expMonId], gBattleMons[gBattlerFainted].species);
#endif #endif
} }
else else
@ -4161,10 +4181,10 @@ static void Cmd_getexp(void)
gBattleStruct->wildVictorySong++; gBattleStruct->wildVictorySong++;
} }
if (IsValidForBattle(&gPlayerParty[gBattleStruct->expGetterMonId])) if (IsValidForBattle(&gPlayerParty[*expMonId]))
{ {
if (gBattleStruct->sentInPokes & 1) if (wasSentOut)
gBattleMoveDamage = *exp; gBattleMoveDamage = gBattleStruct->expValue;
else else
gBattleMoveDamage = 0; gBattleMoveDamage = 0;
@ -4174,14 +4194,16 @@ static void Cmd_getexp(void)
&& gBattleMoveDamage == 0 && gBattleMoveDamage == 0
#endif #endif
) )
gBattleMoveDamage += gExpShareExp; {
gBattleMoveDamage += gBattleStruct->expShareExpValue;
}
ApplyExperienceMultipliers(&gBattleMoveDamage, gBattleStruct->expGetterMonId, gBattlerFainted); ApplyExperienceMultipliers(&gBattleMoveDamage, *expMonId, gBattlerFainted);
if (IsTradedMon(&gPlayerParty[gBattleStruct->expGetterMonId])) if (IsTradedMon(&gPlayerParty[*expMonId]))
{ {
// check if the pokemon doesn't belong to the player // check if the pokemon doesn't belong to the player
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gBattleStruct->expGetterMonId >= 3) if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && *expMonId >= 3)
i = STRINGID_EMPTYSTRING4; i = STRINGID_EMPTYSTRING4;
else else
i = STRINGID_ABOOSTED; i = STRINGID_ABOOSTED;
@ -4194,7 +4216,7 @@ static void Cmd_getexp(void)
// get exp getter battler // get exp getter battler
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{ {
if (gBattlerPartyIndexes[2] == gBattleStruct->expGetterMonId && !(gAbsentBattlerFlags & gBitTable[2])) if (gBattlerPartyIndexes[2] == *expMonId && !(gAbsentBattlerFlags & gBitTable[2]))
gBattleStruct->expGetterBattlerId = 2; gBattleStruct->expGetterBattlerId = 2;
else else
{ {
@ -4209,24 +4231,24 @@ static void Cmd_getexp(void)
gBattleStruct->expGetterBattlerId = 0; gBattleStruct->expGetterBattlerId = 0;
} }
PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBattleStruct->expGetterBattlerId, gBattleStruct->expGetterMonId); PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBattleStruct->expGetterBattlerId, *expMonId);
// buffer 'gained' or 'gained a boosted' // buffer 'gained' or 'gained a boosted'
PREPARE_STRING_BUFFER(gBattleTextBuff2, i); PREPARE_STRING_BUFFER(gBattleTextBuff2, i);
PREPARE_WORD_NUMBER_BUFFER(gBattleTextBuff3, 6, gBattleMoveDamage); PREPARE_WORD_NUMBER_BUFFER(gBattleTextBuff3, 6, gBattleMoveDamage);
if (gBattleStruct->sentInPokes & 1) if (wasSentOut || holdEffect == HOLD_EFFECT_EXP_SHARE)
{ {
PrepareStringBattle(STRINGID_PKMNGAINEDEXP, gBattleStruct->expGetterBattlerId); PrepareStringBattle(STRINGID_PKMNGAINEDEXP, gBattleStruct->expGetterBattlerId);
} }
else if (!IsValidForBattle(&gPlayerParty[gBattleStruct->expGetterMonId+1])) else if (IsGen6ExpShareEnabled() && !gBattleStruct->teamGotExpMsgPrinted) // Print 'the rest of your team got exp' message once, when all of the sent-in mons were given experience
{ {
gLastUsedItem = ITEM_EXP_SHARE; gLastUsedItem = ITEM_EXP_SHARE;
PrepareStringBattle(STRINGID_TEAMGAINEDEXP, 0); PrepareStringBattle(STRINGID_TEAMGAINEDEXP, gBattleStruct->expGetterBattlerId);
gBattleStruct->teamGotExpMsgPrinted = TRUE;
} }
MonGainEVs(&gPlayerParty[gBattleStruct->expGetterMonId], gBattleMons[gBattlerFainted].species); MonGainEVs(&gPlayerParty[*expMonId], gBattleMons[gBattlerFainted].species);
} }
gBattleStruct->sentInPokes >>= 1;
gBattleScripting.getexpState++; gBattleScripting.getexpState++;
} }
} }
@ -4235,16 +4257,16 @@ static void Cmd_getexp(void)
if (gBattleControllerExecFlags == 0) if (gBattleControllerExecFlags == 0)
{ {
gBattleResources->bufferB[gBattleStruct->expGetterBattlerId][0] = 0; gBattleResources->bufferB[gBattleStruct->expGetterBattlerId][0] = 0;
if (GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_HP) && GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_LEVEL) != MAX_LEVEL) if (GetMonData(&gPlayerParty[*expMonId], MON_DATA_HP) && GetMonData(&gPlayerParty[*expMonId], MON_DATA_LEVEL) != MAX_LEVEL)
{ {
gBattleResources->beforeLvlUp->stats[STAT_HP] = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_MAX_HP); gBattleResources->beforeLvlUp->stats[STAT_HP] = GetMonData(&gPlayerParty[*expMonId], MON_DATA_MAX_HP);
gBattleResources->beforeLvlUp->stats[STAT_ATK] = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_ATK); gBattleResources->beforeLvlUp->stats[STAT_ATK] = GetMonData(&gPlayerParty[*expMonId], MON_DATA_ATK);
gBattleResources->beforeLvlUp->stats[STAT_DEF] = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_DEF); gBattleResources->beforeLvlUp->stats[STAT_DEF] = GetMonData(&gPlayerParty[*expMonId], MON_DATA_DEF);
gBattleResources->beforeLvlUp->stats[STAT_SPEED] = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPEED); gBattleResources->beforeLvlUp->stats[STAT_SPEED] = GetMonData(&gPlayerParty[*expMonId], MON_DATA_SPEED);
gBattleResources->beforeLvlUp->stats[STAT_SPATK] = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPATK); gBattleResources->beforeLvlUp->stats[STAT_SPATK] = GetMonData(&gPlayerParty[*expMonId], MON_DATA_SPATK);
gBattleResources->beforeLvlUp->stats[STAT_SPDEF] = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPDEF); gBattleResources->beforeLvlUp->stats[STAT_SPDEF] = GetMonData(&gPlayerParty[*expMonId], MON_DATA_SPDEF);
BtlController_EmitExpUpdate(gBattleStruct->expGetterBattlerId, BUFFER_A, gBattleStruct->expGetterMonId, gBattleMoveDamage); BtlController_EmitExpUpdate(gBattleStruct->expGetterBattlerId, BUFFER_A, *expMonId, gBattleMoveDamage);
MarkBattlerForControllerExec(gBattleStruct->expGetterBattlerId); MarkBattlerForControllerExec(gBattleStruct->expGetterBattlerId);
} }
gBattleScripting.getexpState++; gBattleScripting.getexpState++;
@ -4257,27 +4279,27 @@ static void Cmd_getexp(void)
if (gBattleResources->bufferB[expBattler][0] == CONTROLLER_TWORETURNVALUES && gBattleResources->bufferB[expBattler][1] == RET_VALUE_LEVELED_UP) if (gBattleResources->bufferB[expBattler][0] == CONTROLLER_TWORETURNVALUES && gBattleResources->bufferB[expBattler][1] == RET_VALUE_LEVELED_UP)
{ {
u16 temp, battler = 0xFF; u16 temp, battler = 0xFF;
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && gBattlerPartyIndexes[expBattler] == gBattleStruct->expGetterMonId) if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && gBattlerPartyIndexes[expBattler] == *expMonId)
HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[expBattler]], expBattler); HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[expBattler]], expBattler);
PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, expBattler, gBattleStruct->expGetterMonId); PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, expBattler, *expMonId);
PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff2, 3, GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_LEVEL)); PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff2, 3, GetMonData(&gPlayerParty[*expMonId], MON_DATA_LEVEL));
BattleScriptPushCursor(); BattleScriptPushCursor();
gLeveledUpInBattle |= gBitTable[gBattleStruct->expGetterMonId]; gLeveledUpInBattle |= gBitTable[*expMonId];
gBattlescriptCurrInstr = BattleScript_LevelUp; gBattlescriptCurrInstr = BattleScript_LevelUp;
gBattleMoveDamage = T1_READ_32(&gBattleResources->bufferB[expBattler][2]); gBattleMoveDamage = T1_READ_32(&gBattleResources->bufferB[expBattler][2]);
AdjustFriendship(&gPlayerParty[gBattleStruct->expGetterMonId], FRIENDSHIP_EVENT_GROW_LEVEL); AdjustFriendship(&gPlayerParty[*expMonId], FRIENDSHIP_EVENT_GROW_LEVEL);
// update battle mon structure after level up // update battle mon structure after level up
if (gBattlerPartyIndexes[0] == gBattleStruct->expGetterMonId && gBattleMons[0].hp) if (gBattlerPartyIndexes[0] == *expMonId && gBattleMons[0].hp)
battler = 0; battler = 0;
else if (gBattlerPartyIndexes[2] == gBattleStruct->expGetterMonId && gBattleMons[2].hp && (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) else if (gBattlerPartyIndexes[2] == *expMonId && gBattleMons[2].hp && (gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
battler = 2; battler = 2;
if (battler != 0xFF) if (battler != 0xFF)
{ {
CopyMonLevelAndBaseStatsToBattleMon(battler, &gPlayerParty[gBattleStruct->expGetterMonId]); CopyMonLevelAndBaseStatsToBattleMon(battler, &gPlayerParty[*expMonId]);
if (gStatuses3[battler] & STATUS3_POWER_TRICK) if (gStatuses3[battler] & STATUS3_POWER_TRICK)
SWAP(gBattleMons[battler].attack, gBattleMons[battler].defense, temp); SWAP(gBattleMons[battler].attack, gBattleMons[battler].defense, temp);
} }
@ -4298,17 +4320,24 @@ static void Cmd_getexp(void)
} }
else else
{ {
gBattleStruct->expGetterMonId++; if ((++gBattleStruct->expOrderId) < PARTY_SIZE)
if (gBattleStruct->expGetterMonId < PARTY_SIZE) {
gBattleScripting.getexpState = 2; // loop again *expMonId = gBattleStruct->expGettersOrder[gBattleStruct->expOrderId];
else if (*expMonId < PARTY_SIZE)
gBattleScripting.getexpState = 6; // we're done {
gBattleScripting.getexpState = 2; // loop again
break;
}
}
gBattleScripting.getexpState = 6; // we're done
} }
break; break;
case 6: // increment instruction case 6: // increment instruction
if (gBattleControllerExecFlags == 0) if (gBattleControllerExecFlags == 0)
{ {
// not sure why gf clears the item and ability here // not sure why gf clears the item and ability here
gBattleStruct->expOrderId = 0;
gBattleStruct->teamGotExpMsgPrinted = FALSE;
gBattleMons[gBattlerFainted].item = ITEM_NONE; gBattleMons[gBattlerFainted].item = ITEM_NONE;
gBattleMons[gBattlerFainted].ability = ABILITY_NONE; gBattleMons[gBattlerFainted].ability = ABILITY_NONE;
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
@ -7044,9 +7073,10 @@ static void Cmd_handlelearnnewmove(void)
{ {
CMD_ARGS(const u8 *learnedMovePtr, const u8 *nothingToLearnPtr, bool8 isFirstMove); CMD_ARGS(const u8 *learnedMovePtr, const u8 *nothingToLearnPtr, bool8 isFirstMove);
u16 learnMove = MonTryLearningNewMove(&gPlayerParty[gBattleStruct->expGetterMonId], cmd->isFirstMove); u32 monId = gBattleStruct->expGetterMonId;
u16 learnMove = MonTryLearningNewMove(&gPlayerParty[monId], cmd->isFirstMove);
while (learnMove == MON_ALREADY_KNOWS_MOVE) while (learnMove == MON_ALREADY_KNOWS_MOVE)
learnMove = MonTryLearningNewMove(&gPlayerParty[gBattleStruct->expGetterMonId], FALSE); learnMove = MonTryLearningNewMove(&gPlayerParty[monId], FALSE);
if (learnMove == MOVE_NONE) if (learnMove == MOVE_NONE)
{ {
@ -7060,7 +7090,7 @@ static void Cmd_handlelearnnewmove(void)
{ {
u32 battler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); u32 battler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
if (gBattlerPartyIndexes[battler] == gBattleStruct->expGetterMonId if (gBattlerPartyIndexes[battler] == monId
&& !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED))
{ {
GiveMoveToBattleMon(&gBattleMons[battler], learnMove); GiveMoveToBattleMon(&gBattleMons[battler], learnMove);
@ -7068,7 +7098,7 @@ static void Cmd_handlelearnnewmove(void)
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{ {
battler = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); battler = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
if (gBattlerPartyIndexes[battler] == gBattleStruct->expGetterMonId if (gBattlerPartyIndexes[battler] == monId
&& !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED))
{ {
GiveMoveToBattleMon(&gBattleMons[battler], learnMove); GiveMoveToBattleMon(&gBattleMons[battler], learnMove);
@ -7834,15 +7864,14 @@ static bool8 SlideInLevelUpBanner(void)
static void DrawLevelUpBannerText(void) static void DrawLevelUpBannerText(void)
{ {
u16 monLevel;
u8 monGender;
struct TextPrinterTemplate printerTemplate; struct TextPrinterTemplate printerTemplate;
u8 *txtPtr; u8 *txtPtr;
u32 var; u32 var;
monLevel = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_LEVEL); struct Pokemon *mon = &gPlayerParty[gBattleStruct->expGetterMonId];
monGender = GetMonGender(&gPlayerParty[gBattleStruct->expGetterMonId]); u32 monLevel = GetMonData(mon, MON_DATA_LEVEL);
GetMonNickname(&gPlayerParty[gBattleStruct->expGetterMonId], gStringVar4); u8 monGender = GetMonGender(mon);
GetMonNickname(mon, gStringVar4);
printerTemplate.currentChar = gStringVar4; printerTemplate.currentChar = gStringVar4;
printerTemplate.windowId = B_WIN_LEVEL_UP_BANNER; printerTemplate.windowId = B_WIN_LEVEL_UP_BANNER;
@ -7912,20 +7941,18 @@ static bool8 SlideOutLevelUpBanner(void)
static void PutMonIconOnLvlUpBanner(void) static void PutMonIconOnLvlUpBanner(void)
{ {
u8 spriteId; u8 spriteId;
const u16 *iconPal;
struct SpriteSheet iconSheet; struct SpriteSheet iconSheet;
struct SpritePalette iconPalSheet; struct SpritePalette iconPalSheet;
u16 species = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPECIES); struct Pokemon *mon = &gPlayerParty[gBattleStruct->expGetterMonId];
u32 personality = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_PERSONALITY); u32 species = GetMonData(mon, MON_DATA_SPECIES);
u32 personality = GetMonData(mon, MON_DATA_PERSONALITY);
const u8 *iconPtr = GetMonIconPtr(species, personality); iconSheet.data = GetMonIconPtr(species, personality);
iconSheet.data = iconPtr;
iconSheet.size = 0x200; iconSheet.size = 0x200;
iconSheet.tag = TAG_LVLUP_BANNER_MON_ICON; iconSheet.tag = TAG_LVLUP_BANNER_MON_ICON;
iconPal = GetValidMonIconPalettePtr(species); iconPalSheet.data = GetValidMonIconPalettePtr(species);
iconPalSheet.data = iconPal;
iconPalSheet.tag = TAG_LVLUP_BANNER_MON_ICON; iconPalSheet.tag = TAG_LVLUP_BANNER_MON_ICON;
LoadSpriteSheet(&iconSheet); LoadSpriteSheet(&iconSheet);
@ -12439,7 +12466,7 @@ static void Cmd_transformdataexecution(void)
{ {
s32 i; s32 i;
u8 *battleMonAttacker, *battleMonTarget; u8 *battleMonAttacker, *battleMonTarget;
gBattleMons[gBattlerAttacker].status2 |= STATUS2_TRANSFORMED; gBattleMons[gBattlerAttacker].status2 |= STATUS2_TRANSFORMED;
gDisableStructs[gBattlerAttacker].disabledMove = MOVE_NONE; gDisableStructs[gBattlerAttacker].disabledMove = MOVE_NONE;
gDisableStructs[gBattlerAttacker].disableTimer = 0; gDisableStructs[gBattlerAttacker].disableTimer = 0;
@ -12464,11 +12491,11 @@ static void Cmd_transformdataexecution(void)
else else
gBattleMons[gBattlerAttacker].pp[i] = 5; gBattleMons[gBattlerAttacker].pp[i] = 5;
} }
// update AI knowledge // update AI knowledge
RecordAllMoves(gBattlerAttacker); RecordAllMoves(gBattlerAttacker);
RecordAbilityBattle(gBattlerAttacker, gBattleMons[gBattlerAttacker].ability); RecordAbilityBattle(gBattlerAttacker, gBattleMons[gBattlerAttacker].ability);
BtlController_EmitResetActionMoveSelection(gBattlerAttacker, BUFFER_A, RESET_MOVE_SELECTION); BtlController_EmitResetActionMoveSelection(gBattlerAttacker, BUFFER_A, RESET_MOVE_SELECTION);
MarkBattlerForControllerExec(gBattlerAttacker); MarkBattlerForControllerExec(gBattlerAttacker);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TRANSFORMED; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TRANSFORMED;
@ -16023,13 +16050,7 @@ u8 GetFirstFaintedPartyIndex(u8 battler)
void ApplyExperienceMultipliers(s32 *expAmount, u8 expGetterMonId, u8 faintedBattler) void ApplyExperienceMultipliers(s32 *expAmount, u8 expGetterMonId, u8 faintedBattler)
{ {
u16 item = GetMonData(&gPlayerParty[expGetterMonId], MON_DATA_HELD_ITEM); u32 holdEffect = GetMonHoldEffect(&gPlayerParty[expGetterMonId]);
u8 holdEffect;
if (item == ITEM_ENIGMA_BERRY_E_READER)
holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
else
holdEffect = ItemId_GetHoldEffect(item);
if (IsTradedMon(&gPlayerParty[expGetterMonId])) if (IsTradedMon(&gPlayerParty[expGetterMonId]))
*expAmount = (*expAmount * 150) / 100; *expAmount = (*expAmount * 150) / 100;