sticky barb transfer + pickpocket combo, fix CanBattlerGetOrLoseItem

This commit is contained in:
Evan 2020-12-09 10:28:18 -07:00
parent a93a8b2194
commit 34dd11448b
11 changed files with 191 additions and 115 deletions

View File

@ -7700,10 +7700,25 @@ BattleScript_AnnounceAirLockCloudNine::
BattleScript_Pickpocket::
call BattleScript_AbilityPopUp
setmoveeffect MOVE_EFFECT_STEAL_ITEM
jumpifability BS_ATTACKER, ABILITY_STICKY_HOLD, BattleScript_PickpocketPrevented
swapattackerwithtarget
pickpocketsteal
call BattleScript_ItemSteal
swapattackerwithtarget
activateitemeffects BS_TARGET
return
BattleScript_PickpocketPrevented:
pause 0x20
copybyte gBattlerAbility, gBattlerAttacker
call BattleScript_AbilityPopUp
printstring STRINGID_ITEMCANNOTBEREMOVED
waitmessage 0x40
return
BattleScript_StickyBarbTransfer::
playanimation BS_TARGET, B_ANIM_ITEM_STEAL, NULL
printstring STRINGID_STICKYBARBTRANSFER
waitmessage 0x40
removeitem BS_TARGET
return

View File

@ -427,6 +427,12 @@ struct Illusion
struct Pokemon *mon;
};
struct StolenItem
{
u16 originalItem:15;
u16 stolen:1;
};
struct BattleStruct
{
u8 turnEffectsTracker;
@ -541,7 +547,7 @@ struct BattleStruct
u8 sameMoveTurns[MAX_BATTLERS_COUNT]; // For Metronome, number of times the same moves has been SUCCESFULLY used.
u16 moveEffect2; // For Knock Off
u16 changedSpecies[PARTY_SIZE]; // For Zygarde or future forms when multiple mons can change into the same pokemon.
u16 itemStolen[PARTY_SIZE]; //player's team that had items stolen (bit per party member)
struct StolenItem itemStolen[PARTY_SIZE]; //player's team that had items stolen (bit per party member)
};
#define GET_MOVE_TYPE(move, typeArg) \

View File

@ -26,6 +26,7 @@ u32 IsFlowerVeilProtected(u32 battler);
u32 IsLeafGuardProtected(u32 battler);
bool32 IsShieldsDownProtected(u32 battler);
u32 IsAbilityStatusProtected(u32 battler);
void StealTargetItem(u8 battlerStealer, u8 battlerItem);
extern void (* const gBattleScriptingCommandsTable[])(void);
extern const u8 gBattlePalaceNatureToMoveGroupLikelihood[NUM_NATURES][4];

View File

@ -351,5 +351,6 @@ extern const u8 BattleScript_EmergencyExitWildNoPopUp[];
extern const u8 BattleScript_CheekPouchActivates[];
extern const u8 BattleScript_AnnounceAirLockCloudNine[];
extern const u8 BattleScript_Pickpocket[];
extern const u8 BattleScript_StickyBarbTransfer[];
#endif // GUARD_BATTLE_SCRIPTS_H

View File

@ -133,6 +133,8 @@ u8 GetBattleMoveSplit(u32 moveId);
void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast);
bool32 TestSheerForceFlag(u8 battler, u16 move);
void TryRestoreStolenItems(void);
bool8 CanStealItem(u8 battlerId, u16 item);
bool32 CanStealItem(u8 battlerStealing, u8 battlerItem, u16 item);
void TrySaveExchangedItem(u8 battlerId, u16 stolenItem);
bool32 IsPartnerMonFromSameTrainer(u8 battlerId);
#endif // GUARD_BATTLE_UTIL_H

View File

@ -166,7 +166,6 @@
#define VARIOUS_PARALYZE_TYPE_IMMUNITY 100
#define VARIOUS_JUMP_IF_ABSENT 101
#define VARIOUS_MOVEEND_ITEM_EFFECTS 102
#define VARIOUS_PICKPOCKET 103
// Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 0

View File

@ -558,8 +558,10 @@
#define STRINGID_AURABREAKENTERS 554
#define STRINGID_COMATOSEENTERS 555
#define STRINGID_SCREENCLEANERENTERS 556
#define STRINGID_ITEMCANNOTBEREMOVED 557
#define STRINGID_STICKYBARBTRANSFER 558
#define BATTLESTRINGS_COUNT 557
#define BATTLESTRINGS_COUNT 559
//// multichoice message IDs
// switch in ability message

View File

@ -2941,6 +2941,9 @@ static void BattleStartClearSetData(void)
gBattleStruct->arenaLostOpponentMons = 0;
gBattleStruct->mega.triggerSpriteId = 0xFF;
for (i = 0; i < PARTY_SIZE; i++)
gBattleStruct->itemStolen[i].originalItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
}
void SwitchInClearSetData(void)

View File

@ -685,9 +685,13 @@ static const u8 sText_FairyAuraActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}
static const u8 sText_AuraBreakActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} reversed all\nother POKéMON's auras!");
static const u8 sText_ComatoseActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is drowsing!");
static const u8 sText_ScreenCleanerActivates[] = _("All screens on the field were\ncleansed!");
static const u8 sText_ItemCannotBeRemoved[] = _("{B_ATK_NAME_WITH_PREFIX}'s item cannot be removed!");
static const u8 sText_StickyBarbTransfer[] = _("The {B_LAST_ITEM} attached itself to\n{B_ATK_NAME_WITH_PREFIX}!");
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
{
[STRINGID_STICKYBARBTRANSFER - 12] = sText_StickyBarbTransfer,
[STRINGID_ITEMCANNOTBEREMOVED - 12] = sText_ItemCannotBeRemoved,
[STRINGID_STATWASNOTLOWERED - 12] = sText_StatWasNotLowered,
[STRINGID_CLOAKEDINAFREEZINGLIGHT - 12] = sText_CloakedInAFreezingLight,
[STRINGID_DESTINYKNOTACTIVATES - 12] = sText_DestinyKnotActivates,

View File

@ -2369,33 +2369,30 @@ static void CheckSetUnburden(u8 battlerId)
}
}
//slight difference in thief/pickpocket requires this
static void StealTargetItem(void)
{
gLastUsedItem = gBattleStruct->changedItems[gBattlerAttacker] = gBattleMons[gBattlerTarget].item;
gBattleMons[gBattlerTarget].item = 0;
// battlerStealer steals the item of battlerItem
void StealTargetItem(u8 battlerStealer, u8 battlerItem)
{
gLastUsedItem = gBattleMons[battlerItem].item;
gBattleMons[battlerItem].item = 0;
RecordItemEffectBattle(gBattlerTarget, 0);
RecordItemEffectBattle(gBattlerAttacker, ItemId_GetHoldEffect(gLastUsedItem));
//item assignment doesn't happen yet for thief
RecordItemEffectBattle(battlerItem, 0);
RecordItemEffectBattle(battlerStealer, ItemId_GetHoldEffect(gLastUsedItem));
gBattleMons[battlerStealer].item = gLastUsedItem;
CheckSetUnburden(gBattlerTarget);
gBattleResources->flags->flags[gBattlerAttacker] &= ~(RESOURCE_FLAG_UNBURDEN);
CheckSetUnburden(battlerItem);
gBattleResources->flags->flags[battlerStealer] &= ~(RESOURCE_FLAG_UNBURDEN);
gActiveBattler = gBattlerAttacker;
BtlController_EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gLastUsedItem);
MarkBattlerForControllerExec(gBattlerAttacker);
gActiveBattler = battlerStealer;
BtlController_EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gLastUsedItem); // set attacker item
MarkBattlerForControllerExec(battlerStealer);
gActiveBattler = gBattlerTarget;
BtlController_EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gBattleMons[gBattlerTarget].item);
MarkBattlerForControllerExec(gBattlerTarget);
gActiveBattler = battlerItem;
BtlController_EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gBattleMons[battlerItem].item); // remove target item
MarkBattlerForControllerExec(battlerItem);
gBattleStruct->choicedMove[gBattlerTarget] = 0;
gBattleStruct->choicedMove[battlerItem] = 0;
#if B_TRAINERS_KNOCK_OFF_ITEMS == TRUE
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER)
gBattleStruct->itemStolen[gBattlerPartyIndexes[gBattlerTarget]] = gLastUsedItem;
#endif
TrySaveExchangedItem(battlerItem, gLastUsedItem);
}
#define INCREMENT_RESET_RETURN \
@ -2951,7 +2948,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
break;
case MOVE_EFFECT_STEAL_ITEM:
{
if (!CanStealItem(gBattlerAttacker, gBattleMons[gBattlerTarget].item))
if (!CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item))
{
gBattlescriptCurrInstr++;
break;
@ -2966,14 +2963,15 @@ void SetMoveEffect(bool32 primary, u32 certain)
}
else if (gBattleMons[gBattlerAttacker].item != 0
|| gBattleMons[gBattlerTarget].item == ITEM_ENIGMA_BERRY
|| IS_ITEM_MAIL(gBattleMons[gBattlerTarget].item)
|| gBattleMons[gBattlerTarget].item == 0)
{
gBattlescriptCurrInstr++;
}
else
{
StealTargetItem();
StealTargetItem(gBattlerAttacker, gBattlerTarget); //attacker steals target item
gBattleMons[gBattlerAttacker].item = 0; //item assigned later on with thief (see MOVEEND_CHANGED_ITEMS)
gBattleStruct->changedItems[gBattlerAttacker] = gLastUsedItem; // stolen item to be assigned later
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_ItemSteal;
}
@ -5014,29 +5012,33 @@ static void Cmd_moveend(void)
break;
case MOVEEND_PICKPOCKET:
if (IsBattlerAlive(gBattlerAttacker)
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_STICKY_HOLD
&& gBattleMons[gBattlerAttacker].item != ITEM_NONE //attacker must be holding an item
&& !(TestSheerForceFlag(gBattlerAttacker, gCurrentMove)) //pickpocket doesn't activate for sheer force
&& IsMoveMakingContact(gCurrentMove, gBattlerAttacker) //pickpocket requires contact
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) //obviously attack needs to have worked
&& gBattleMons[gBattlerAttacker].item != ITEM_NONE // attacker must be holding an item
&& !(TestSheerForceFlag(gBattlerAttacker, gCurrentMove)) // pickpocket doesn't activate for sheer force
&& IsMoveMakingContact(gCurrentMove, gBattlerAttacker) // pickpocket requires contact
&& !(gMoveResultFlags & 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
SortBattlersBySpeed(battlers, FALSE); // pickpocket activates for fastest mon without item
for (i = 0; i < gBattlersCount; i++)
{
u8 battler = battlers[i];
//attacker is mon who made contact, battler is mon with pickpocket
if (battler != gBattlerAttacker //cannot pickpocket yourself
&& GetBattlerAbility(battler) == ABILITY_PICKPOCKET //'target' must have pickpocket ability
&& BATTLER_DAMAGED(battler) //obviously battler needs to have been damaged as well
&& !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler) //subsitute unaffected
&& IsBattlerAlive(battler) //battler must be alive to pickpocket
&& gBattleMons[battler].item == ITEM_NONE //pickpocketer can't have an item already
&& CanStealItem(battler, gBattleMons[gBattlerAttacker].item)) //cannot steal plates, mega stones, etc
// attacker is mon who made contact, battler is mon with pickpocket
if (battler != gBattlerAttacker // cannot pickpocket yourself
&& GetBattlerAbility(battler) == ABILITY_PICKPOCKET // 'target' must have pickpocket ability
&& BATTLER_DAMAGED(battler) // target needs to have been damaged
&& !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler) // subsitute unaffected
&& IsBattlerAlive(battler) // battler must be alive to pickpocket
&& gBattleMons[battler].item == ITEM_NONE // pickpocketer can't have an item already
&& CanStealItem(battler, gBattlerAttacker, gBattleMons[gBattlerAttacker].item)) // cannot steal plates, mega stones, etc
{
gBattlerTarget = gBattlerAbility = battler;
// battle scripting is super brittle so we shall do the item exchange now (if possible)
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_STICKY_HOLD)
StealTargetItem(gBattlerTarget, gBattlerAttacker); // target takes attacker's item
gEffectBattler = gBattlerAttacker;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_Pickpocket;
gBattlescriptCurrInstr = BattleScript_Pickpocket; // includes sticky hold check to print separate string
effect = TRUE;
break; // pickpocket activates on fastest mon, so exit loop.
}
@ -8322,14 +8324,8 @@ static void Cmd_various(void)
}
return;
case VARIOUS_MOVEEND_ITEM_EFFECTS:
ItemBattleEffects(1, gActiveBattler, FALSE);
break;
case VARIOUS_PICKPOCKET:
{
gBattleScripting.battler = gBattlerAttacker;
StealTargetItem();
gBattleMons[gBattlerAttacker].item = gLastUsedItem;
}
if (ItemBattleEffects(1, gActiveBattler, FALSE))
return;
break;
}
@ -11126,15 +11122,14 @@ static void Cmd_tryswapitems(void) // trick
PREPARE_ITEM_BUFFER(gBattleTextBuff1, *newItemAtk)
PREPARE_ITEM_BUFFER(gBattleTextBuff2, oldItemAtk)
#if B_TRAINERS_KNOCK_OFF_ITEMS
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
if (!(sideAttacker == sideTarget && IsPartnerMonFromSameTrainer(gBattlerAttacker)))
{
// if targeting your own side and you aren't in a multi battle, don't save items as stolen
if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
gBattleStruct->itemStolen[gBattlerPartyIndexes[gBattlerAttacker]] = oldItemAtk;
TrySaveExchangedItem(gBattlerAttacker, oldItemAtk);
if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER)
gBattleStruct->itemStolen[gBattlerPartyIndexes[gBattlerTarget]] = *newItemAtk;
TrySaveExchangedItem(gBattlerTarget, *newItemAtk);
}
#endif
if (oldItemAtk != 0 && *newItemAtk != 0)
gBattleCommunication[MULTISTRING_CHOOSER] = 2; // attacker's item -> <- target's item

View File

@ -5388,18 +5388,6 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
case HOLD_EFFECT_BLACK_SLUDGE:
if (IS_BATTLER_OF_TYPE(battlerId, TYPE_POISON))
goto LEFTOVERS;
case HOLD_EFFECT_STICKY_BARB:
if (!moveTurn)
{
gBattleMoveDamage = gBattleMons[battlerId].maxHP / 8;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
BattleScriptExecute(BattleScript_ItemHurtEnd2);
effect = ITEM_HP_CHANGE;
RecordItemEffectBattle(battlerId, battlerHoldEffect);
PREPARE_ITEM_BUFFER(gBattleTextBuff1, gLastUsedItem);
}
break;
case HOLD_EFFECT_LEFTOVERS:
LEFTOVERS:
if (gBattleMons[battlerId].hp < gBattleMons[battlerId].maxHP && !moveTurn)
@ -5862,6 +5850,22 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
gBattleScripting.statChanger = SET_STATCHANGER(STAT_SPATK, 1, FALSE);
}
break;
case HOLD_EFFECT_STICKY_BARB:
if (TARGET_TURN_DAMAGED
&& (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
&& IsMoveMakingContact(gCurrentMove, gBattlerAttacker)
&& !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battlerId)
&& IsBattlerAlive(gBattlerAttacker)
&& gBattleMons[gBattlerAttacker].item == ITEM_NONE)
{
//no sticky hold checks. item is already known so no CanStealItem checks
gEffectBattler = battlerId; //effect battler = target
StealTargetItem(gBattlerAttacker, gBattlerTarget); //attacker takes target's barb
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_StickyBarbTransfer;
effect = ITEM_EFFECT_OTHER;
}
break;
}
}
break;
@ -5890,6 +5894,18 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
RecordItemEffectBattle(battlerId, battlerHoldEffect);
}
break;
case HOLD_EFFECT_STICKY_BARB: //not an orb per-say, but similar effect, and needs to NOT activate with pickpocket
if (GetBattlerAbility(battlerId) != ABILITY_MAGIC_GUARD)
{
gBattleMoveDamage = gBattleMons[battlerId].maxHP / 8;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
BattleScriptExecute(BattleScript_ItemHurtEnd2);
effect = ITEM_HP_CHANGE;
RecordItemEffectBattle(battlerId, battlerHoldEffect);
PREPARE_ITEM_BUFFER(gBattleTextBuff1, gLastUsedItem);
}
break;
}
if (effect == ITEM_STATUS_CHANGE)
@ -7553,7 +7569,7 @@ s32 GetStealthHazardDamage(u8 hazardType, u8 battlerId)
return dmg;
}
static bool32 IsPartnerMonFromSameTrainer(u8 battlerId)
bool32 IsPartnerMonFromSameTrainer(u8 battlerId)
{
if (GetBattlerSide(battlerId) == B_SIDE_OPPONENT && gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
return FALSE;
@ -7721,25 +7737,37 @@ bool32 DoBattlersShareType(u32 battler1, u32 battler2)
bool32 CanBattlerGetOrLoseItem(u8 battlerId, u16 itemId)
{
u16 species = gBattleMons[battlerId].species;
if (IS_ITEM_MAIL(itemId))
return FALSE;
else if (itemId == ITEM_ENIGMA_BERRY)
u16 holdEffect = ItemId_GetHoldEffect(itemId);
// Mail can be stolen now
if (itemId == ITEM_ENIGMA_BERRY)
return FALSE;
else if (species == SPECIES_KYOGRE && itemId == ITEM_BLUE_ORB)
return FALSE;
else if (species == SPECIES_GROUDON && itemId == ITEM_RED_ORB)
return FALSE;
// Mega stone cannot be lost if pokemon can mega evolve with it or is already mega evolved.
else if (ItemId_GetHoldEffect(itemId) == HOLD_EFFECT_MEGA_STONE
&& ((GetMegaEvolutionSpecies(species, itemId) != SPECIES_NONE) || gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]))
else if (holdEffect == HOLD_EFFECT_MEGA_STONE
&& ((GetMegaEvolutionSpecies(species, itemId) != SPECIES_NONE)
|| gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]))
return FALSE;
#ifdef HOLD_EFFECT_PRIMAL_ORB
// Primal orbs cannot be lost if the species can undergo primal reversion (no need to check if it has since it always does)
else if (holdEffect == HOLD_EFFECT_PRIMAL_ORB
&& ((GetPrimalMegaEvolutionSpecies(species, itemId) != SPECIES_NONE))
#endif
else if (species == SPECIES_GIRATINA && itemId == ITEM_GRISEOUS_ORB)
return FALSE;
else if (species == SPECIES_GENESECT && GetBattlerHoldEffect(battlerId, FALSE) == HOLD_EFFECT_DRIVE)
return FALSE;
else if (species == SPECIES_SILVALLY && GetBattlerHoldEffect(battlerId, FALSE) == HOLD_EFFECT_MEMORY)
return FALSE;
else if (species == SPECIES_ARCEUS && holdEffect == HOLD_EFFECT_PLATE)
return FALSE;
#ifdef HOLD_EFFECT_Z_CRYSTAL
else if (holdEffect == HOLD_EFFECT_Z_CRYSTAL)
return FALSE;
#endif
else
return TRUE;
}
@ -7835,40 +7863,40 @@ u8 GetBattleMoveSplit(u32 moveId)
// useful for effects like pickpocket, eject button, red card, dancer
void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast)
{
int i, j, key, keyBank;
u16 speeds[4] = {0};
int i, j, currSpeed, currBattler;
u16 speeds[4] = {0};
for (i = 0; i < gBattlersCount; i++)
speeds[i] = GetBattlerTotalSpeedStat(battlers[i]);
for (i = 0; i < gBattlersCount; i++)
speeds[i] = GetBattlerTotalSpeedStat(battlers[i]);
for (i = 1; i < gBattlersCount; i++)
{
keyBank = battlers[i];
key = speeds[i];
j = i - 1;
for (i = 1; i < gBattlersCount; i++)
{
currBattler = battlers[i];
currSpeed = speeds[i];
j = i - 1;
if (slowToFast)
{
while (j >= 0 && speeds[j] > key)
{
battlers[j + 1] = battlers[j];
speeds[j + 1] = speeds[j];
j = j - 1;
}
}
else
{
while (j >= 0 && speeds[j] < key)
{
battlers[j + 1] = battlers[j];
speeds[j + 1] = speeds[j];
j = j - 1;
}
}
if (slowToFast)
{
while (j >= 0 && speeds[j] > currSpeed)
{
battlers[j + 1] = battlers[j];
speeds[j + 1] = speeds[j];
j = j - 1;
}
}
else
{
while (j >= 0 && speeds[j] < currSpeed)
{
battlers[j + 1] = battlers[j];
speeds[j + 1] = speeds[j];
j = j - 1;
}
}
battlers[j + 1] = keyBank;
speeds[j + 1] = key;
}
battlers[j + 1] = currBattler;
speeds[j + 1] = currSpeed;
}
}
bool32 TestSheerForceFlag(u8 battler, u16 move)
@ -7886,18 +7914,24 @@ void TryRestoreStolenItems(void)
for (i = 0; i < PARTY_SIZE; i++)
{
stolenItem = gBattleStruct->itemStolen[i];
if (stolenItem != ITEM_NONE && ItemId_GetPocket(stolenItem) != POCKET_BERRIES)
SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &stolenItem); //restore stolen non-berry items
if (gBattleStruct->itemStolen[i].stolen)
{
stolenItem = gBattleStruct->itemStolen[i].originalItem;
if (stolenItem != ITEM_NONE && ItemId_GetPocket(stolenItem) != POCKET_BERRIES)
SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &stolenItem); //restore stolen non-berry items
}
}
}
bool8 CanStealItem(u8 battlerId, u16 item)
bool32 CanStealItem(u8 battlerStealing, u8 battlerItem, u16 item)
{
u8 stealerSide = GetBattlerSide(battlerStealing);
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL)
return FALSE;
if (GetBattlerSide(battlerId) == B_SIDE_OPPONENT
// check if the battler trying to steal should be able to
if (stealerSide == B_SIDE_OPPONENT
&& !(gBattleTypeFlags &
(BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_FRONTIER
@ -7917,11 +7951,25 @@ bool8 CanStealItem(u8 battlerId, u16 item)
| BATTLE_TYPE_LINK
| BATTLE_TYPE_x2000000
| BATTLE_TYPE_SECRET_BASE))
&& (gWishFutureKnock.knockedOffMons[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]))
&& (gWishFutureKnock.knockedOffMons[stealerSide] & gBitTable[gBattlerPartyIndexes[battlerStealing]]))
{
return FALSE;
}
return CanBattlerGetOrLoseItem(battlerId, item);
// check if battler with the item can lose it
return CanBattlerGetOrLoseItem(battlerItem, item);
}
void TrySaveExchangedItem(u8 battlerId, u16 stolenItem)
{
// because BtlController_EmitSetMonData does SetMonData, we need to save the stolen item only if it matches the battler's original
// so, if the player steals an item during battle and has it stolen from it, it will not end the battle with it (naturally)
#if B_TRAINERS_KNOCK_OFF_ITEMS == TRUE
// If regular trainer battle and mon's original item matches what is being stolen, save it to be restored at end of battle
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER
&& !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
&& GetBattlerSide(battlerId) == B_SIDE_PLAYER
&& stolenItem == gBattleStruct->itemStolen[gBattlerPartyIndexes[battlerId]].originalItem)
gBattleStruct->itemStolen[gBattlerPartyIndexes[battlerId]].stolen = TRUE;
#endif
}