opponent trainer theft config option. Clean up code a bit

This commit is contained in:
Evan 2020-11-13 11:00:44 -07:00
parent 64bcac4589
commit 435f928aa4
7 changed files with 71 additions and 105 deletions

View File

@ -1756,13 +1756,13 @@
.4byte \ptr
.endm
.macro activateitemeffects battler:req
various \battler, VARIOUS_MOVEEND_ITEM_EFFECTS
.endm
.macro activateitemeffects battler:req
various \battler, VARIOUS_MOVEEND_ITEM_EFFECTS
.endm
.macro pickpocketsteal
various 0, VARIOUS_PICKPOCKET
.endm
.macro pickpocketsteal
various 0, VARIOUS_PICKPOCKET
.endm
@ helpful macros
.macro setstatchanger stat:req, stages:req, down:req

View File

@ -541,6 +541,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)
};
#define GET_MOVE_TYPE(move, typeArg) \

View File

@ -132,6 +132,6 @@ bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 battlerId);
u8 GetBattleMoveSplit(u32 moveId);
void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast);
bool32 TestSheerForceFlag(u8 battler, u16 move);
bool32 ItemCanBeStolen(u16 item, u8 battlerId);
void TryRestoreStolenItems(void);
#endif // GUARD_BATTLE_UTIL_H

View File

@ -132,6 +132,7 @@
#define B_SLEEP_TURNS GEN_6 // In Gen5+, sleep lasts for 1-3 turns instead of 2-5 turns.
#define B_PARALYZE_ELECTRIC GEN_6 // In Gen6+, Electric type Pokémon can't be paralyzed.
#define B_POWDER_GRASS GEN_6 // In Gen6+, Grass type Pokémon are immune to powder and spore moves.
#define B_TRAINERS_STEAL_ITEMS TRUE // If TRUE, trainer with thief/pickpocket will temporarily steal your items
// Animation Settings
#define B_NEW_SWORD_PARTICLE TRUE // If set to TRUE, it updates Swords Dance's particle.

View File

@ -4819,6 +4819,10 @@ static void HandleEndTurn_FinishBattle(void)
sub_8186444();
BeginFastPaletteFade(3);
FadeOutMapMusic(5);
#if B_TRAINERS_STEAL_ITEMS
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
TryRestoreStolenItems();
#endif
for (i = 0; i < PARTY_SIZE; i++)
{
UndoMegaEvolution(i);

View File

@ -2369,6 +2369,35 @@ 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;
RecordItemEffectBattle(gBattlerTarget, 0);
RecordItemEffectBattle(gBattlerAttacker, ItemId_GetHoldEffect(gLastUsedItem));
//item assignment doesn't happen yet for thief
CheckSetUnburden(gBattlerTarget);
gBattleResources->flags->flags[gBattlerAttacker] &= ~(RESOURCE_FLAG_UNBURDEN);
gActiveBattler = gBattlerAttacker;
BtlController_EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gLastUsedItem);
MarkBattlerForControllerExec(gBattlerAttacker);
gActiveBattler = gBattlerTarget;
BtlController_EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gBattleMons[gBattlerTarget].item);
MarkBattlerForControllerExec(gBattlerTarget);
gBattleStruct->choicedMove[gBattlerTarget] = 0;
#if B_TRAINERS_STEAL_ITEMS
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER)
gBattleStruct->itemStolen[gBattlerPartyIndexes[gBattlerTarget]] = gLastUsedItem;
#endif
}
#define INCREMENT_RESET_RETURN \
{ \
gBattlescriptCurrInstr++; \
@ -2922,7 +2951,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
break;
case MOVE_EFFECT_STEAL_ITEM:
{
if (!ItemCanBeStolen(gBattleMons[gBattlerTarget].item, gBattlerAttacker))
if (!CanBattlerGetOrLoseItem(gBattlerAttacker, gBattleMons[gBattlerTarget].item))
{
gBattlescriptCurrInstr++;
break;
@ -2944,28 +2973,9 @@ void SetMoveEffect(bool32 primary, u32 certain)
}
else
{
gLastUsedItem = gBattleStruct->changedItems[gBattlerAttacker] = gBattleMons[gBattlerTarget].item;
gBattleMons[gBattlerTarget].item = 0;
RecordItemEffectBattle(gBattlerTarget, 0);
RecordItemEffectBattle(gBattlerAttacker, ItemId_GetHoldEffect(gLastUsedItem));
//item assignment doesn't happen yet
CheckSetUnburden(gBattlerTarget);
gBattleResources->flags->flags[gBattlerAttacker] &= ~(RESOURCE_FLAG_UNBURDEN);
gActiveBattler = gBattlerAttacker;
BtlController_EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gLastUsedItem);
MarkBattlerForControllerExec(gBattlerAttacker);
gActiveBattler = gBattlerTarget;
BtlController_EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gBattleMons[gBattlerTarget].item);
MarkBattlerForControllerExec(gBattlerTarget);
StealTargetItem();
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_ItemSteal;
gBattleStruct->choicedMove[gBattlerTarget] = 0;
}
}
@ -5022,7 +5032,7 @@ static void Cmd_moveend(void)
&& !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler) //subsitute unaffected
&& IsBattlerAlive(battler) //battler must be alive to be pickpocketed
&& gBattleMons[battler].item == ITEM_NONE //pickpocketer can't have an item already
&& ItemCanBeStolen(gBattleMons[gBattlerAttacker].item, battler)) //cannot steal plates, mega stones, etc
&& CanBattlerGetOrLoseItem(battler, gBattleMons[gBattlerAttacker].item)) //cannot steal plates, mega stones, etc
{
gBattlerTarget = gBattlerAbility = battler;
BattleScriptPushCursor();
@ -8316,28 +8326,9 @@ static void Cmd_various(void)
break;
case VARIOUS_PICKPOCKET:
{
// different from MOVE_EFFECT_STEAL_ITEM in that it immediately assigns the stolen item to the 'attacker'
gEffectBattler = gBattlerTarget;
gBattleScripting.battler = gBattlerAttacker;
gLastUsedItem = gBattleMons[gEffectBattler].item;
gBattleMons[gEffectBattler].item = 0;
StealTargetItem();
gBattleMons[gBattlerAttacker].item = gLastUsedItem;
RecordItemEffectBattle(gBattlerTarget, 0);
RecordItemEffectBattle(gBattlerAttacker, ItemId_GetHoldEffect(gLastUsedItem));
CheckSetUnburden(gEffectBattler); //Give target Unburden boost
gBattleResources->flags->flags[gBattlerTarget] &= ~(RESOURCE_FLAG_UNBURDEN); //remove attacker boost
gActiveBattler = gBattlerAttacker;
BtlController_EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gLastUsedItem);
MarkBattlerForControllerExec(gActiveBattler);
gActiveBattler = gEffectBattler;
BtlController_EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gBattleMons[gActiveBattler].item);
MarkBattlerForControllerExec(gActiveBattler);
gBattleStruct->choicedMove[gEffectBattler] = 0;
}
break;
}
@ -11066,7 +11057,11 @@ static void Cmd_tryswapitems(void) // trick
| BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_SECRET_BASE
| BATTLE_TYPE_x2000000))))
| BATTLE_TYPE_x2000000
#if B_TRAINERS_STEAL_ITEMS
| BATTLE_TYPE_TRAINER
#endif
))))
{
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
}
@ -11131,6 +11126,16 @@ static void Cmd_tryswapitems(void) // trick
PREPARE_ITEM_BUFFER(gBattleTextBuff1, *newItemAtk)
PREPARE_ITEM_BUFFER(gBattleTextBuff2, oldItemAtk)
#if B_TRAINERS_STEAL_ITEMS
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
{
if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
gBattleStruct->itemStolen[gBattlerPartyIndexes[gBattlerAttacker]] = oldItemAtk;
if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER)
gBattleStruct->itemStolen[gBattlerPartyIndexes[gBattlerTarget]] = *newItemAtk;
}
#endif
if (oldItemAtk != 0 && *newItemAtk != 0)
gBattleCommunication[MULTISTRING_CHOOSER] = 2; // attacker's item -> <- target's item
else if (oldItemAtk == 0 && *newItemAtk != 0)

View File

@ -7793,61 +7793,16 @@ bool32 TestSheerForceFlag(u8 battler, u16 move)
return FALSE;
}
bool32 ItemCanBeStolen(u16 item, u8 battlerId)
void TryRestoreStolenItems(void)
{
u8 effect = ItemId_GetHoldEffect(item);
u32 i;
u16 stolenItem = ITEM_NONE;
if (item == ITEM_ENIGMA_BERRY)
return FALSE;
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL)
return FALSE;
if (GetBattlerSide(battlerId) == B_SIDE_OPPONENT
&& !(gBattleTypeFlags &
(BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_LINK
| BATTLE_TYPE_x2000000
| BATTLE_TYPE_SECRET_BASE)))
for (i = 0; i < PARTY_SIZE; i++)
{
return FALSE;
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
}
else if (!(gBattleTypeFlags &
(BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_LINK
| BATTLE_TYPE_x2000000
| BATTLE_TYPE_SECRET_BASE))
&& (gWishFutureKnock.knockedOffMons[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]))
{
return FALSE;
}
if (IS_ITEM_MAIL(item))
return FALSE;
switch (effect)
{
case HOLD_EFFECT_MEGA_STONE:
#ifdef HOLD_EFFECT_MEMORY
case HOLD_EFFECT_MEMORY:
#endif
#ifdef HOLD_EFFECT_Z_CRYSTAL
case HOLD_EFFECT_Z_CRYSTAL:
#endif
#ifdef HOLD_EFFECT_DRIVE
case HOLD_EFFECT_DRIVE:
#endif
#ifdef HOLD_EFFECT_GEMS
case HOLD_EFFECT_GEMS:
#endif
#ifdef HOLD_EFFECT_GRISEOUS_ORB
case HOLD_EFFECT_GRISEOUS_ORB:
#endif
return FALSE;
}
return TRUE;
}