mirror of
https://github.com/rh-hideout/pokeemerald-expansion.git
synced 2026-04-25 16:28:25 -05:00
Stockpile / WishFutureKnock / Order up clean up (#8528)
This commit is contained in:
parent
42d968ebfb
commit
4d69a7274f
|
|
@ -746,9 +746,8 @@
|
|||
.4byte \jumpInstr
|
||||
.endm
|
||||
|
||||
.macro stockpile id:req
|
||||
.macro stockpile
|
||||
.byte 0x85
|
||||
.byte \id
|
||||
.endm
|
||||
|
||||
.macro stockpiletobasedamage
|
||||
|
|
|
|||
|
|
@ -3741,17 +3741,16 @@ BattleScript_NotAffectedAbilityPopUp::
|
|||
|
||||
BattleScript_EffectStockpile::
|
||||
attackcanceler
|
||||
stockpile 0
|
||||
stockpile
|
||||
attackanimation
|
||||
waitanimation
|
||||
printstring STRINGID_PKMNSTOCKPILED
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
.if B_STOCKPILE_RAISES_DEFS < GEN_4
|
||||
goto BattleScript_EffectStockpileEnd
|
||||
goto BattleScript_MoveEnd
|
||||
.endif
|
||||
jumpifmovehadnoeffect BattleScript_EffectStockpileEnd
|
||||
jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_DEF, MAX_STAT_STAGE, BattleScript_EffectStockpileDef
|
||||
jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPDEF, MAX_STAT_STAGE, BattleScript_EffectStockpileEnd
|
||||
jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPDEF, MAX_STAT_STAGE, BattleScript_MoveEnd
|
||||
BattleScript_EffectStockpileDef:
|
||||
setstatchanger STAT_DEF, 1, FALSE
|
||||
statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectStockpileSpDef, BIT_SPDEF
|
||||
|
|
@ -3760,12 +3759,10 @@ BattleScript_EffectStockpileDef:
|
|||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_EffectStockpileSpDef::
|
||||
setstatchanger STAT_SPDEF, 1, FALSE
|
||||
statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectStockpileEnd
|
||||
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectStockpileEnd
|
||||
statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_MoveEnd
|
||||
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_MoveEnd
|
||||
printfromtable gStatUpStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_EffectStockpileEnd:
|
||||
stockpile 1
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_MoveEffectStockpileWoreOff::
|
||||
|
|
|
|||
|
|
@ -183,18 +183,6 @@ struct FieldTimer
|
|||
u16 fairyLockTimer;
|
||||
};
|
||||
|
||||
struct WishFutureKnock
|
||||
{
|
||||
u16 futureSightCounter[MAX_BATTLERS_COUNT];
|
||||
u8 futureSightBattlerIndex[MAX_BATTLERS_COUNT];
|
||||
u8 futureSightPartyIndex[MAX_BATTLERS_COUNT];
|
||||
u16 futureSightMove[MAX_BATTLERS_COUNT];
|
||||
u16 wishCounter[MAX_BATTLERS_COUNT];
|
||||
u8 wishPartyId[MAX_BATTLERS_COUNT];
|
||||
u8 weatherDuration;
|
||||
u8 knockedOffMons[NUM_BATTLE_SIDES]; // Each battler is represented by a bit.
|
||||
};
|
||||
|
||||
struct AI_SavedBattleMon
|
||||
{
|
||||
enum Ability ability;
|
||||
|
|
@ -443,7 +431,8 @@ struct LinkBattlerHeader
|
|||
struct BattleEnigmaBerry battleEnigmaBerry;
|
||||
};
|
||||
|
||||
enum IllusionState {
|
||||
enum IllusionState
|
||||
{
|
||||
ILLUSION_NOT_SET,
|
||||
ILLUSION_OFF,
|
||||
ILLUSION_ON
|
||||
|
|
@ -493,6 +482,20 @@ struct BattleVideo {
|
|||
rng_value_t rngSeed;
|
||||
};
|
||||
|
||||
struct Wish
|
||||
{
|
||||
u16 counter[MAX_BATTLERS_COUNT];
|
||||
u8 partyId[MAX_BATTLERS_COUNT];
|
||||
};
|
||||
|
||||
struct FutureSight
|
||||
{
|
||||
u16 move;
|
||||
u16 counter:10;
|
||||
u16 battlerIndex:3;
|
||||
u16 partyIndex:3;
|
||||
};
|
||||
|
||||
struct BattlerState
|
||||
{
|
||||
u8 targetsDone[MAX_BATTLERS_COUNT];
|
||||
|
|
@ -534,7 +537,8 @@ struct PartyState
|
|||
u32 timesGotHit:5;
|
||||
u32 changedSpecies:11; // For forms when multiple mons can change into the same pokemon.
|
||||
u32 sentOut:1;
|
||||
u32 padding:9;
|
||||
u32 knockedOffItem;
|
||||
u32 padding:8;
|
||||
u16 usedHeldItem;
|
||||
};
|
||||
|
||||
|
|
@ -562,9 +566,12 @@ struct BattleStruct
|
|||
struct BattlerState battlerState[MAX_BATTLERS_COUNT];
|
||||
struct PartyState partyState[NUM_BATTLE_SIDES][PARTY_SIZE];
|
||||
struct EventStates eventState;
|
||||
struct FutureSight futureSight[MAX_BATTLERS_COUNT];
|
||||
struct Wish wish;
|
||||
u16 moveTarget[MAX_BATTLERS_COUNT];
|
||||
u32 expShareExpValue;
|
||||
u32 expValue;
|
||||
u8 weatherDuration;
|
||||
u8 expGettersOrder[PARTY_SIZE]; // First battlers which were sent out, then via exp-share
|
||||
u8 expGetterMonId;
|
||||
u8 expOrderId:3;
|
||||
|
|
@ -1016,7 +1023,6 @@ extern u8 gBattleOutcome;
|
|||
extern struct ProtectStruct gProtectStructs[MAX_BATTLERS_COUNT];
|
||||
extern struct SpecialStatus gSpecialStatuses[MAX_BATTLERS_COUNT];
|
||||
extern u16 gBattleWeather;
|
||||
extern struct WishFutureKnock gWishFutureKnock;
|
||||
extern u16 gIntroSlideFlags;
|
||||
extern u8 gSentPokesToOpponent[2];
|
||||
extern struct BattleEnigmaBerry gEnigmaBerries[MAX_BATTLERS_COUNT];
|
||||
|
|
|
|||
|
|
@ -335,7 +335,6 @@ enum __attribute__((packed)) BattleMoveEffects
|
|||
EFFECT_TERA_STARSTORM,
|
||||
EFFECT_DRAGON_DARTS,
|
||||
EFFECT_SHELL_SIDE_ARM,
|
||||
EFFECT_ORDER_UP,
|
||||
EFFECT_RAPID_SPIN,
|
||||
EFFECT_SPECTRAL_THIEF,
|
||||
EFFECT_RECOIL,
|
||||
|
|
|
|||
|
|
@ -2116,8 +2116,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_FUTURE_SIGHT:
|
||||
if (gWishFutureKnock.futureSightCounter[LEFT_FOE(battlerAtk)] > 0
|
||||
|| gWishFutureKnock.futureSightCounter[RIGHT_FOE(battlerAtk)] > 0)
|
||||
if (gBattleStruct->futureSight[LEFT_FOE(battlerAtk)].counter > 0
|
||||
|| gBattleStruct->futureSight[RIGHT_FOE(battlerAtk)].counter > 0)
|
||||
ADJUST_SCORE(-12);
|
||||
else
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
|
|
@ -2585,7 +2585,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_WISH:
|
||||
if (gWishFutureKnock.wishCounter[battlerAtk] > 0)
|
||||
if (gBattleStruct->wish.counter[battlerAtk] > 0)
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_ASSIST:
|
||||
|
|
@ -4617,7 +4617,7 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, stru
|
|||
|| HasUsableWhileAsleepMove(battlerAtk)
|
||||
|| aiData->abilities[battlerAtk] == ABILITY_SHED_SKIN
|
||||
|| aiData->abilities[battlerAtk] == ABILITY_EARLY_BIRD
|
||||
|| (AI_GetWeather() & B_WEATHER_RAIN && gWishFutureKnock.weatherDuration != 1 && aiData->abilities[battlerAtk] == ABILITY_HYDRATION && aiData->holdEffects[battlerAtk] != HOLD_EFFECT_UTILITY_UMBRELLA))
|
||||
|| (AI_GetWeather() & B_WEATHER_RAIN && gBattleStruct->weatherDuration != 1 && aiData->abilities[battlerAtk] == ABILITY_HYDRATION && aiData->holdEffects[battlerAtk] != HOLD_EFFECT_UTILITY_UMBRELLA))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -64,15 +64,15 @@ static u32 GetWishHealAmountForBattler(u32 battler)
|
|||
{
|
||||
u32 wishHeal = 0;
|
||||
|
||||
if (gWishFutureKnock.wishCounter[battler] == 0)
|
||||
if (gBattleStruct->wish.counter[battler] == 0)
|
||||
return wishHeal;
|
||||
|
||||
if (B_WISH_HP_SOURCE >= GEN_5)
|
||||
{
|
||||
if (IsOnPlayerSide(battler))
|
||||
wishHeal = GetMonData(&gPlayerParty[gWishFutureKnock.wishPartyId[battler]], MON_DATA_MAX_HP) / 2;
|
||||
wishHeal = GetMonData(&gPlayerParty[gBattleStruct->wish.partyId[battler]], MON_DATA_MAX_HP) / 2;
|
||||
else
|
||||
wishHeal = GetMonData(&gEnemyParty[gWishFutureKnock.wishPartyId[battler]], MON_DATA_MAX_HP) / 2;
|
||||
wishHeal = GetMonData(&gEnemyParty[gBattleStruct->wish.partyId[battler]], MON_DATA_MAX_HP) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -108,11 +108,11 @@ static void GetIncomingHealInfo(u32 battler, struct IncomingHealInfo *healInfo)
|
|||
}
|
||||
|
||||
// Wish heals at end of turn
|
||||
if (gWishFutureKnock.wishCounter[battler] > 0)
|
||||
if (gBattleStruct->wish.counter[battler] > 0)
|
||||
{
|
||||
healInfo->hasHealing = TRUE;
|
||||
healInfo->healEndOfTurn = TRUE;
|
||||
healInfo->wishCounter = gWishFutureKnock.wishCounter[battler];
|
||||
healInfo->wishCounter = gBattleStruct->wish.counter[battler];
|
||||
healInfo->healAmount = GetWishHealAmountForBattler(battler);
|
||||
}
|
||||
}
|
||||
|
|
@ -1758,7 +1758,7 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler, const struct Incomi
|
|||
u32 statusDamage = GetSwitchinStatusDamage(battler);
|
||||
u32 hitsToKO = 0;
|
||||
u16 maxHP = gBattleMons[battler].maxHP, item = gAiLogicData->items[battler], heldItemEffect = GetItemHoldEffect(item);
|
||||
u8 weatherDuration = gWishFutureKnock.weatherDuration, holdEffectParam = GetItemHoldEffectParam(item);
|
||||
u8 weatherDuration = gBattleStruct->weatherDuration, holdEffectParam = GetItemHoldEffectParam(item);
|
||||
u32 opposingBattler = GetOppositeBattler(battler);
|
||||
enum Ability opposingAbility = gAiLogicData->abilities[opposingBattler], ability = gAiLogicData->abilities[battler];
|
||||
bool32 usedSingleUseHealingItem = FALSE, opponentCanBreakMold = IsMoldBreakerTypeAbility(opposingBattler, opposingAbility);
|
||||
|
|
|
|||
|
|
@ -6601,34 +6601,34 @@ static void TrySwapWishBattlerIds(u32 battlerAtk, u32 battlerPartner)
|
|||
u32 i, temp;
|
||||
|
||||
// if used future sight on opposing side, properly track who used it
|
||||
if (gWishFutureKnock.futureSightCounter[LEFT_FOE(battlerAtk)] > 0
|
||||
|| gWishFutureKnock.futureSightCounter[RIGHT_FOE(battlerAtk)] > 0)
|
||||
if (gBattleStruct->futureSight[LEFT_FOE(battlerAtk)].counter > 0
|
||||
|| gBattleStruct->futureSight[RIGHT_FOE(battlerAtk)].counter > 0)
|
||||
{
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (IsBattlerAlly(i, battlerAtk))
|
||||
continue; // only on opposing side
|
||||
|
||||
if (gWishFutureKnock.futureSightBattlerIndex[i] == battlerAtk)
|
||||
if (gBattleStruct->futureSight[i].battlerIndex == battlerAtk)
|
||||
{
|
||||
// if target was attacked with future sight from us, now they'll be the partner slot
|
||||
gWishFutureKnock.futureSightBattlerIndex[i] = battlerPartner;
|
||||
gWishFutureKnock.futureSightPartyIndex[i] = gBattlerPartyIndexes[battlerPartner];
|
||||
gBattleStruct->futureSight[i].battlerIndex = battlerPartner;
|
||||
gBattleStruct->futureSight[i].partyIndex = gBattlerPartyIndexes[battlerPartner];
|
||||
break;
|
||||
}
|
||||
else if (gWishFutureKnock.futureSightBattlerIndex[i] == battlerPartner)
|
||||
else if (gBattleStruct->futureSight[i].battlerIndex == battlerPartner)
|
||||
{
|
||||
gWishFutureKnock.futureSightBattlerIndex[i] = battlerAtk;
|
||||
gWishFutureKnock.futureSightPartyIndex[i] = gBattlerPartyIndexes[battlerAtk];
|
||||
gBattleStruct->futureSight[i].battlerIndex = battlerAtk;
|
||||
gBattleStruct->futureSight[i].partyIndex = gBattlerPartyIndexes[battlerAtk];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// swap wish party indices
|
||||
if (gWishFutureKnock.wishCounter[battlerAtk] > 0
|
||||
|| gWishFutureKnock.wishCounter[battlerPartner] > 0)
|
||||
SWAP(gWishFutureKnock.wishPartyId[battlerAtk], gWishFutureKnock.wishPartyId[battlerPartner], temp);
|
||||
if (gBattleStruct->wish.counter[battlerAtk] > 0
|
||||
|| gBattleStruct->wish.counter[battlerPartner] > 0)
|
||||
SWAP(gBattleStruct->wish.partyId[battlerAtk], gBattleStruct->wish.partyId[battlerPartner], temp);
|
||||
}
|
||||
|
||||
static void TrySwapAttractBattlerIds(u32 battlerAtk, u32 battlerPartner)
|
||||
|
|
|
|||
|
|
@ -229,21 +229,22 @@ static bool32 HandleEndTurnFutureSight(u32 battler)
|
|||
|
||||
gBattleStruct->eventState.endTurnBattler++;
|
||||
|
||||
if (gWishFutureKnock.futureSightCounter[battler] > 0 && --gWishFutureKnock.futureSightCounter[battler] == 0)
|
||||
if (gBattleStruct->futureSight[battler].counter > 0
|
||||
&& --gBattleStruct->futureSight[battler].counter == 0)
|
||||
{
|
||||
if (!IsBattlerAlive(battler))
|
||||
return effect;
|
||||
|
||||
if (gWishFutureKnock.futureSightMove[battler] == MOVE_FUTURE_SIGHT)
|
||||
if (gBattleStruct->futureSight[battler].move == MOVE_FUTURE_SIGHT)
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FUTURE_SIGHT;
|
||||
else
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DOOM_DESIRE;
|
||||
|
||||
PREPARE_MOVE_BUFFER(gBattleTextBuff1, gWishFutureKnock.futureSightMove[battler]);
|
||||
PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->futureSight[battler].move);
|
||||
|
||||
gBattlerTarget = battler;
|
||||
gBattlerAttacker = gWishFutureKnock.futureSightBattlerIndex[battler];
|
||||
gCurrentMove = gWishFutureKnock.futureSightMove[battler];
|
||||
gBattlerAttacker = gBattleStruct->futureSight[battler].battlerIndex;
|
||||
gCurrentMove = gBattleStruct->futureSight[battler].move;
|
||||
|
||||
if (!IsFutureSightAttackerInParty(gBattlerAttacker, gBattlerTarget, gCurrentMove))
|
||||
SetTypeBeforeUsingMove(gCurrentMove, gBattlerAttacker);
|
||||
|
|
@ -261,15 +262,13 @@ static bool32 HandleEndTurnWish(u32 battler)
|
|||
|
||||
gBattleStruct->eventState.endTurnBattler++;
|
||||
|
||||
if (gWishFutureKnock.wishCounter[battler] > 0 && --gWishFutureKnock.wishCounter[battler] == 0 && IsBattlerAlive(battler))
|
||||
if (gBattleStruct->wish.counter[battler] > 0 && --gBattleStruct->wish.counter[battler] == 0 && IsBattlerAlive(battler))
|
||||
{
|
||||
s32 wishHeal = 0;
|
||||
gBattlerTarget = battler;
|
||||
PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, battler, gWishFutureKnock.wishPartyId[battler])
|
||||
PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, battler, gBattleStruct->wish.partyId[battler])
|
||||
if (GetConfig(CONFIG_WISH_HP_SOURCE) >= GEN_5)
|
||||
{
|
||||
wishHeal = GetMonData(&GetBattlerParty(battler)[gWishFutureKnock.wishPartyId[battler]], MON_DATA_MAX_HP) / 2;
|
||||
}
|
||||
wishHeal = GetMonData(&GetBattlerParty(battler)[gBattleStruct->wish.partyId[battler]], MON_DATA_MAX_HP) / 2;
|
||||
else
|
||||
wishHeal = GetNonDynamaxMaxHP(battler) / 2;
|
||||
|
||||
|
|
|
|||
|
|
@ -202,7 +202,6 @@ EWRAM_DATA u8 gBattleOutcome = 0;
|
|||
EWRAM_DATA struct ProtectStruct gProtectStructs[MAX_BATTLERS_COUNT] = {0};
|
||||
EWRAM_DATA struct SpecialStatus gSpecialStatuses[MAX_BATTLERS_COUNT] = {0};
|
||||
EWRAM_DATA u16 gBattleWeather = 0;
|
||||
EWRAM_DATA struct WishFutureKnock gWishFutureKnock = {0};
|
||||
EWRAM_DATA u16 gIntroSlideFlags = 0;
|
||||
EWRAM_DATA u8 gSentPokesToOpponent[2] = {0};
|
||||
EWRAM_DATA struct BattleEnigmaBerry gEnigmaBerries[MAX_BATTLERS_COUNT] = {0};
|
||||
|
|
@ -3021,7 +3020,6 @@ static void BattleStartClearSetData(void)
|
|||
memset(&gFieldTimers, 0, sizeof(gFieldTimers));
|
||||
memset(&gSideStatuses, 0, sizeof(gSideStatuses));
|
||||
memset(&gSideTimers, 0, sizeof(gSideTimers));
|
||||
memset(&gWishFutureKnock, 0, sizeof(gWishFutureKnock));
|
||||
memset(&gBattleResults, 0, sizeof(gBattleResults));
|
||||
ClearSetBScriptingStruct();
|
||||
|
||||
|
|
|
|||
|
|
@ -2873,7 +2873,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, c
|
|||
moveEffect = MOVE_EFFECT_NONE;
|
||||
else if (!primary
|
||||
&& TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove)
|
||||
&& !(GetMoveEffect(gCurrentMove) == EFFECT_ORDER_UP && gBattleStruct->battlerState[gBattlerAttacker].commanderSpecies != SPECIES_NONE))
|
||||
&& !(moveEffect == MOVE_EFFECT_ORDER_UP && gBattleStruct->battlerState[gBattlerAttacker].commanderSpecies != SPECIES_NONE))
|
||||
moveEffect = MOVE_EFFECT_NONE;
|
||||
else if (!IsBattlerAlive(gEffectBattler) && !activateAfterFaint)
|
||||
moveEffect = MOVE_EFFECT_NONE;
|
||||
|
|
@ -5469,7 +5469,7 @@ static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move
|
|||
&& i != battlerAtk
|
||||
&& IsBattlerTurnDamaged(i)
|
||||
&& CanStealItem(battlerAtk, i, gBattleMons[i].item)
|
||||
&& !(gWishFutureKnock.knockedOffMons[GetBattlerSide(i)] & (1u << gBattlerPartyIndexes[i]))
|
||||
&& !GetBattlerPartyState(i)->knockedOffItem
|
||||
&& !DoesSubstituteBlockMove(battlerAtk, i, move)
|
||||
&& (GetBattlerAbility(i) != ABILITY_STICKY_HOLD || !IsBattlerAlive(i)))
|
||||
{
|
||||
|
|
@ -5648,7 +5648,7 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect)
|
|||
}
|
||||
else
|
||||
{
|
||||
gWishFutureKnock.knockedOffMons[side] |= 1u << gBattlerPartyIndexes[gBattlerTarget];
|
||||
GetBattlerPartyState(gBattlerTarget)->knockedOffItem = TRUE;
|
||||
}
|
||||
|
||||
BattleScriptCall(BattleScript_KnockedOff);
|
||||
|
|
@ -6781,10 +6781,10 @@ static void Cmd_moveend(void)
|
|||
break;
|
||||
case MOVEEND_PICKPOCKET:
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& gBattleMons[gBattlerAttacker].item != ITEM_NONE // Attacker must be holding an item
|
||||
&& !(gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerAttacker)] & (1u << gBattlerPartyIndexes[gBattlerAttacker])) // But not knocked off
|
||||
&& IsMoveMakingContact(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), gCurrentMove) // Pickpocket requires contact
|
||||
&& !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) // Obviously attack needs to have worked
|
||||
&& gBattleMons[gBattlerAttacker].item != ITEM_NONE // Attacker must be holding an item
|
||||
&& !GetBattlerPartyState(gBattlerAttacker)->knockedOffItem // But not knocked off
|
||||
&& IsMoveMakingContact(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), gCurrentMove) // Pickpocket requires contact
|
||||
&& !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) // Obviously attack needs to have worked
|
||||
{
|
||||
u8 battlers[4] = {0, 1, 2, 3};
|
||||
SortBattlersBySpeed(battlers, FALSE); // Pickpocket activates for fastest mon without item
|
||||
|
|
@ -7137,9 +7137,7 @@ static void Cmd_switchindataupdate(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
// check knocked off item
|
||||
i = GetBattlerSide(battler);
|
||||
if (gWishFutureKnock.knockedOffMons[i] & (1u << gBattlerPartyIndexes[battler]))
|
||||
if (GetBattlerPartyState(battler)->knockedOffItem)
|
||||
{
|
||||
gBattleMons[battler].item = ITEM_NONE;
|
||||
}
|
||||
|
|
@ -8849,7 +8847,7 @@ bool32 CanUseLastResort(u8 battler)
|
|||
|
||||
static void RemoveAllWeather(void)
|
||||
{
|
||||
gWishFutureKnock.weatherDuration = 0;
|
||||
gBattleStruct->weatherDuration = 0;
|
||||
|
||||
if (gBattleWeather & B_WEATHER_RAIN)
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_END_RAIN;
|
||||
|
|
@ -9559,25 +9557,31 @@ static void Cmd_jumpifuproarwakes(void)
|
|||
|
||||
static void Cmd_stockpile(void)
|
||||
{
|
||||
CMD_ARGS(u8 id);
|
||||
CMD_ARGS();
|
||||
|
||||
switch (cmd->id)
|
||||
gBattleMons[gBattlerAttacker].volatiles.stockpileCounter++;
|
||||
|
||||
if (B_STOCKPILE_RAISES_DEFS >= GEN_4)
|
||||
{
|
||||
case 0:
|
||||
gBattleMons[gBattlerAttacker].volatiles.stockpileCounter++;
|
||||
gBattleMons[gBattlerAttacker].volatiles.stockpileBeforeDef = gBattleMons[gBattlerAttacker].statStages[STAT_DEF];
|
||||
gBattleMons[gBattlerAttacker].volatiles.stockpileBeforeSpDef = gBattleMons[gBattlerAttacker].statStages[STAT_SPDEF];
|
||||
PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff1, 1, gBattleMons[gBattlerAttacker].volatiles.stockpileCounter);
|
||||
break;
|
||||
case 1: // Save def/sp def stats.
|
||||
if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT))
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].volatiles.stockpileDef += gBattleMons[gBattlerAttacker].statStages[STAT_DEF] - gBattleMons[gBattlerAttacker].volatiles.stockpileBeforeDef;
|
||||
gBattleMons[gBattlerAttacker].volatiles.stockpileSpDef += gBattleMons[gBattlerAttacker].statStages[STAT_SPDEF] - gBattleMons[gBattlerAttacker].volatiles.stockpileBeforeSpDef;
|
||||
}
|
||||
break;
|
||||
if (ChangeStatBuffs(
|
||||
gBattlerAttacker,
|
||||
SET_STAT_BUFF_VALUE(1),
|
||||
STAT_DEF,
|
||||
STAT_CHANGE_ONLY_CHECKING,
|
||||
0, 0) != STAT_CHANGE_DIDNT_WORK)
|
||||
gBattleMons[gBattlerAttacker].volatiles.stockpileDef++;
|
||||
|
||||
if (ChangeStatBuffs(
|
||||
gBattlerAttacker,
|
||||
SET_STAT_BUFF_VALUE(1),
|
||||
STAT_SPDEF,
|
||||
STAT_CHANGE_ONLY_CHECKING,
|
||||
0, 0) != STAT_CHANGE_DIDNT_WORK)
|
||||
gBattleMons[gBattlerAttacker].volatiles.stockpileSpDef++;
|
||||
|
||||
}
|
||||
|
||||
PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff1, 1, gBattleMons[gBattlerAttacker].volatiles.stockpileCounter);
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
|
|
@ -11910,10 +11914,10 @@ static void Cmd_setfutureattack(void)
|
|||
{
|
||||
CMD_ARGS();
|
||||
|
||||
gWishFutureKnock.futureSightMove[gBattlerTarget] = gCurrentMove;
|
||||
gWishFutureKnock.futureSightBattlerIndex[gBattlerTarget] = gBattlerAttacker;
|
||||
gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] = gBattlerPartyIndexes[gBattlerAttacker];
|
||||
gWishFutureKnock.futureSightCounter[gBattlerTarget] = 3;
|
||||
gBattleStruct->futureSight[gBattlerTarget].move = gCurrentMove;
|
||||
gBattleStruct->futureSight[gBattlerTarget].battlerIndex = gBattlerAttacker;
|
||||
gBattleStruct->futureSight[gBattlerTarget].partyIndex = gBattlerPartyIndexes[gBattlerAttacker];
|
||||
gBattleStruct->futureSight[gBattlerTarget].counter = 3;
|
||||
|
||||
if (gCurrentMove == MOVE_DOOM_DESIRE)
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DOOM_DESIRE;
|
||||
|
|
@ -12178,17 +12182,13 @@ static void Cmd_tryswapitems(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
u8 sideAttacker = GetBattlerSide(gBattlerAttacker);
|
||||
u8 sideTarget = GetBattlerSide(gBattlerTarget);
|
||||
|
||||
// You can't swap items if they were knocked off in regular battles
|
||||
if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK
|
||||
| BATTLE_TYPE_EREADER_TRAINER
|
||||
| BATTLE_TYPE_FRONTIER
|
||||
| BATTLE_TYPE_SECRET_BASE
|
||||
| BATTLE_TYPE_RECORDED_LINK))
|
||||
&& (gWishFutureKnock.knockedOffMons[sideAttacker] & (1u << gBattlerPartyIndexes[gBattlerAttacker])
|
||||
|| gWishFutureKnock.knockedOffMons[sideTarget] & (1u << gBattlerPartyIndexes[gBattlerTarget])))
|
||||
&& (GetBattlerPartyState(gBattlerAttacker)->knockedOffItem || GetBattlerPartyState(gBattlerTarget)->knockedOffItem))
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
|
|
@ -12244,7 +12244,7 @@ static void Cmd_tryswapitems(void)
|
|||
PREPARE_ITEM_BUFFER(gBattleTextBuff1, *newItemAtk)
|
||||
PREPARE_ITEM_BUFFER(gBattleTextBuff2, oldItemAtk)
|
||||
|
||||
if (!(sideAttacker == sideTarget && IsPartnerMonFromSameTrainer(gBattlerAttacker)))
|
||||
if (!(IsBattlerAlly(gBattlerAttacker, gBattlerTarget) && IsPartnerMonFromSameTrainer(gBattlerAttacker)))
|
||||
{
|
||||
// if targeting your own side and you aren't in a multi battle, don't save items as stolen
|
||||
if (IsOnPlayerSide(gBattlerAttacker))
|
||||
|
|
@ -12325,10 +12325,10 @@ static void Cmd_trywish(void)
|
|||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
else if (gWishFutureKnock.wishCounter[gBattlerAttacker] == 0)
|
||||
else if (gBattleStruct->wish.counter[gBattlerAttacker] == 0)
|
||||
{
|
||||
gWishFutureKnock.wishCounter[gBattlerAttacker] = 2;
|
||||
gWishFutureKnock.wishPartyId[gBattlerAttacker] = gBattlerPartyIndexes[gBattlerAttacker];
|
||||
gBattleStruct->wish.counter[gBattlerAttacker] = 2;
|
||||
gBattleStruct->wish.partyId[gBattlerAttacker] = gBattlerPartyIndexes[gBattlerAttacker];
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
else
|
||||
|
|
@ -16902,7 +16902,7 @@ void BS_TryBestow(void)
|
|||
|| !CanBattlerGetOrLoseItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerAttacker].item)
|
||||
|| !CanBattlerGetOrLoseItem(gBattlerTarget, gBattlerAttacker, gBattleMons[gBattlerAttacker].item)
|
||||
|| GetBattlerAbility(gBattlerAttacker) == ABILITY_STICKY_HOLD
|
||||
|| gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerTarget)] & (1u << gBattlerPartyIndexes[gBattlerTarget]))
|
||||
|| GetBattlerPartyState(gBattlerTarget)->knockedOffItem)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ bool32 EndOrContinueWeather(void)
|
|||
if (currBattleWeather == 0xFF)
|
||||
return FALSE;
|
||||
|
||||
if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0)
|
||||
if (gBattleStruct->weatherDuration > 0 && --gBattleStruct->weatherDuration == 0)
|
||||
{
|
||||
gBattleWeather = B_WEATHER_NONE;
|
||||
for (u32 battler = 0; battler < gBattlersCount; battler++)
|
||||
|
|
@ -2737,7 +2737,7 @@ static enum MoveCanceler CancelerMoveFailure(struct BattleContext *ctx)
|
|||
battleScript = BattleScript_ButItFailed;
|
||||
break;
|
||||
case EFFECT_FUTURE_SIGHT:
|
||||
if (gWishFutureKnock.futureSightCounter[ctx->battlerDef] > 0)
|
||||
if (gBattleStruct->futureSight[ctx->battlerDef].counter > 0)
|
||||
battleScript = BattleScript_ButItFailed;
|
||||
break;
|
||||
case EFFECT_LAST_RESORT:
|
||||
|
|
@ -3305,11 +3305,11 @@ bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, u32 ability)
|
|||
u32 rock = sBattleWeatherInfo[battleWeatherId].rock;
|
||||
gBattleWeather = sBattleWeatherInfo[battleWeatherId].flag;
|
||||
if (gBattleWeather & B_WEATHER_PRIMAL_ANY)
|
||||
gWishFutureKnock.weatherDuration = 0;
|
||||
gBattleStruct->weatherDuration = 0;
|
||||
else if (rock != 0 && GetBattlerHoldEffect(battler) == rock)
|
||||
gWishFutureKnock.weatherDuration = 8;
|
||||
gBattleStruct->weatherDuration = 8;
|
||||
else
|
||||
gWishFutureKnock.weatherDuration = 5;
|
||||
gBattleStruct->weatherDuration = 5;
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
gBattleMons[i].volatiles.weatherAbilityDone = FALSE;
|
||||
|
|
@ -8848,7 +8848,7 @@ static inline s32 DoFutureSightAttackDamageCalcVars(struct BattleContext *ctx)
|
|||
enum Type moveType = ctx->moveType;
|
||||
|
||||
struct Pokemon *party = GetBattlerParty(battlerAtk);
|
||||
struct Pokemon *partyMon = &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]];
|
||||
struct Pokemon *partyMon = &party[gBattleStruct->futureSight[battlerDef].partyIndex];
|
||||
u32 partyMonLevel = GetMonData(partyMon, MON_DATA_LEVEL, NULL);
|
||||
u32 partyMonSpecies = GetMonData(partyMon, MON_DATA_SPECIES, NULL);
|
||||
gBattleMovePower = GetMovePower(move);
|
||||
|
|
@ -8898,11 +8898,11 @@ bool32 IsFutureSightAttackerInParty(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
struct Pokemon *party = GetBattlerParty(battlerAtk);
|
||||
if (IsDoubleBattle())
|
||||
{
|
||||
return &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[gBattlerPartyIndexes[battlerAtk]]
|
||||
&& &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[gBattlerPartyIndexes[BATTLE_PARTNER(battlerAtk)]];
|
||||
return &party[gBattleStruct->futureSight[battlerDef].partyIndex] != &party[gBattlerPartyIndexes[battlerAtk]]
|
||||
&& &party[gBattleStruct->futureSight[battlerDef].partyIndex] != &party[gBattlerPartyIndexes[BATTLE_PARTNER(battlerAtk)]];
|
||||
}
|
||||
|
||||
return &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[gBattlerPartyIndexes[battlerAtk]];
|
||||
return &party[gBattleStruct->futureSight[battlerDef].partyIndex] != &party[gBattlerPartyIndexes[battlerAtk]];
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -8965,7 +8965,7 @@ s32 CalcCritChanceStage(struct BattleContext *ctx)
|
|||
{
|
||||
s32 critChance = 0;
|
||||
|
||||
if (gSideStatuses[ctx->battlerDef] & SIDE_STATUS_LUCKY_CHANT)
|
||||
if (gSideStatuses[GetBattlerSide(ctx->battlerDef)] & SIDE_STATUS_LUCKY_CHANT)
|
||||
{
|
||||
critChance = CRITICAL_HIT_BLOCKED;
|
||||
}
|
||||
|
|
@ -10302,7 +10302,7 @@ bool32 CanStealItem(u32 battlerStealing, u32 battlerItem, u16 item)
|
|||
| BATTLE_TYPE_LINK
|
||||
| BATTLE_TYPE_RECORDED_LINK
|
||||
| BATTLE_TYPE_SECRET_BASE))
|
||||
&& (gWishFutureKnock.knockedOffMons[stealerSide] & (1u << gBattlerPartyIndexes[battlerStealing])))
|
||||
&& GetBattlerPartyState(battlerStealing)->knockedOffItem)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2251,12 +2251,6 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
|
|||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
|
||||
[EFFECT_ORDER_UP] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectHit,
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
|
||||
[EFFECT_RAPID_SPIN] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectHit,
|
||||
|
|
|
|||
|
|
@ -19956,7 +19956,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
|||
.description = COMPOUND_STRING(
|
||||
"Boosts a user's stats\n"
|
||||
"depending on Tatsugiri."),
|
||||
.effect = EFFECT_ORDER_UP,
|
||||
.effect = EFFECT_HIT,
|
||||
.power = 80,
|
||||
.type = TYPE_DRAGON,
|
||||
.accuracy = 100,
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Present", s16 damage)
|
|||
} WHEN {
|
||||
//Test will fail if present heals because the hp change would be 0
|
||||
//so we want a damaging version of present
|
||||
TURN { MOVE(player, MOVE_PRESENT, WITH_RNG(RNG_PRESENT, 1)); }
|
||||
TURN { MOVE(player, MOVE_PRESENT, WITH_RNG(RNG_PRESENT, 1)); }
|
||||
} SCENE {
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
|
|
@ -969,7 +969,7 @@ DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to
|
|||
{
|
||||
s16 damage1, damage2;
|
||||
u32 move = 0;
|
||||
for (u32 j = MOVE_HONE_CLAWS; j < MOVES_COUNT_GEN5; j++)
|
||||
for (u32 j = MOVE_HONE_CLAWS + 12; j < MOVES_COUNT_GEN5; j++)
|
||||
{
|
||||
if (GetMoveCategory(j) != DAMAGE_CATEGORY_STATUS && !IgnoreMoveForSheerForceBoost(j))
|
||||
PARAMETRIZE { move = j; }
|
||||
|
|
|
|||
|
|
@ -34,6 +34,28 @@ SINGLE_BATTLE_TEST("Stockpile's count can go up only to 3")
|
|||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Stockpile's def and spDef stat increases aren't incremented by other stat stage changes")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_STOCKPILE); }
|
||||
TURN { MOVE(player, MOVE_COSMIC_POWER); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STOCKPILE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_COSMIC_POWER, player);
|
||||
} THEN {
|
||||
EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 2);
|
||||
EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 2);
|
||||
|
||||
u32 stockpileDef = gBattleMons[0].volatiles.stockpileDef;
|
||||
u32 stockpileSpDef = gBattleMons[0].volatiles.stockpileSpDef;
|
||||
EXPECT_EQ(stockpileDef, 1);
|
||||
EXPECT_EQ(stockpileSpDef, 1);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Spit Up and Swallow don't work if used without Stockpile")
|
||||
{
|
||||
u32 move;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user