mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2025-01-28 22:33:53 +01:00
add additional item theft check
This commit is contained in:
parent
a0b9ece980
commit
5bdf266000
@ -548,7 +548,7 @@ struct BattleStruct
|
|||||||
u8 sameMoveTurns[MAX_BATTLERS_COUNT]; // For Metronome, number of times the same moves has been SUCCESFULLY used.
|
u8 sameMoveTurns[MAX_BATTLERS_COUNT]; // For Metronome, number of times the same moves has been SUCCESFULLY used.
|
||||||
u16 moveEffect2; // For Knock Off
|
u16 moveEffect2; // For Knock Off
|
||||||
u16 changedSpecies[PARTY_SIZE]; // For Zygarde or future forms when multiple mons can change into the same pokemon.
|
u16 changedSpecies[PARTY_SIZE]; // For Zygarde or future forms when multiple mons can change into the same pokemon.
|
||||||
struct StolenItem 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 (byte per party member)
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GET_MOVE_TYPE(move, typeArg) \
|
#define GET_MOVE_TYPE(move, typeArg) \
|
||||||
|
@ -141,13 +141,16 @@
|
|||||||
#define B_CRITICAL_CAPTURE TRUE // If set to TRUE, Critical Capture will be enabled.
|
#define B_CRITICAL_CAPTURE TRUE // If set to TRUE, Critical Capture will be enabled.
|
||||||
#define B_CATCHING_CHARM_BOOST 20 // % boost in Critical Capture odds if player has the Catching Charm.
|
#define B_CATCHING_CHARM_BOOST 20 // % boost in Critical Capture odds if player has the Catching Charm.
|
||||||
|
|
||||||
|
// Item Theft Settings
|
||||||
|
#define B_TRAINERS_KNOCK_OFF_ITEMS TRUE // If TRUE, trainers can steal/swap your items (non-berries are restored after battle). In vanilla games trainers cannot steal items.
|
||||||
|
#define B_KEEP_STOLEN_TRAINER_ITEMS GEN_5 // In Gen5+, you do not keep items stolen from trainers. Wild Pokemon still always have their items permanently stolen.
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
#define B_DOUBLE_WILD_CHANCE 0 // % chance of encountering two Pokémon in a Wild Encounter.
|
#define B_DOUBLE_WILD_CHANCE 0 // % chance of encountering two Pokémon in a Wild Encounter.
|
||||||
#define B_SLEEP_TURNS GEN_6 // In Gen5+, sleep lasts for 1-3 turns instead of 2-5 turns.
|
#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_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_POWDER_GRASS GEN_6 // In Gen6+, Grass-type Pokémon are immune to powder and spore moves.
|
||||||
#define B_STEEL_RESISTANCES GEN_6 // In Gen6+, Steel-type Pokémon are no longer resistant to Dark and Ghost moves.
|
#define B_STEEL_RESISTANCES GEN_6 // In Gen6+, Steel-type Pokémon are no longer resistant to Dark and Ghost moves.
|
||||||
#define B_TRAINERS_KNOCK_OFF_ITEMS TRUE // If TRUE, trainers can steal/swap your items (non-berries are restored after battle). In vanilla games trainers cannot steal items.
|
|
||||||
|
|
||||||
// Animation Settings
|
// Animation Settings
|
||||||
#define B_NEW_SWORD_PARTICLE TRUE // If set to TRUE, it updates Swords Dance's particle.
|
#define B_NEW_SWORD_PARTICLE TRUE // If set to TRUE, it updates Swords Dance's particle.
|
||||||
|
@ -2969,9 +2969,9 @@ void SetMoveEffect(bool32 primary, u32 certain)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
StealTargetItem(gBattlerAttacker, gBattlerTarget); //attacker steals target item
|
StealTargetItem(gBattlerAttacker, gBattlerTarget); // Attacker steals target item
|
||||||
gBattleMons[gBattlerAttacker].item = 0; //item assigned later on with thief (see MOVEEND_CHANGED_ITEMS)
|
gBattleMons[gBattlerAttacker].item = 0; // Item assigned later on with thief (see MOVEEND_CHANGED_ITEMS)
|
||||||
gBattleStruct->changedItems[gBattlerAttacker] = gLastUsedItem; // stolen item to be assigned later
|
gBattleStruct->changedItems[gBattlerAttacker] = gLastUsedItem; // Stolen item to be assigned later
|
||||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||||
gBattlescriptCurrInstr = BattleScript_ItemSteal;
|
gBattlescriptCurrInstr = BattleScript_ItemSteal;
|
||||||
}
|
}
|
||||||
@ -5012,35 +5012,35 @@ static void Cmd_moveend(void)
|
|||||||
break;
|
break;
|
||||||
case MOVEEND_PICKPOCKET:
|
case MOVEEND_PICKPOCKET:
|
||||||
if (IsBattlerAlive(gBattlerAttacker)
|
if (IsBattlerAlive(gBattlerAttacker)
|
||||||
&& gBattleMons[gBattlerAttacker].item != ITEM_NONE // attacker must be holding an item
|
&& gBattleMons[gBattlerAttacker].item != ITEM_NONE // Attacker must be holding an item
|
||||||
&& !(TestSheerForceFlag(gBattlerAttacker, gCurrentMove)) // pickpocket doesn't activate for sheer force
|
&& !(TestSheerForceFlag(gBattlerAttacker, gCurrentMove)) // Pickpocket doesn't activate for sheer force
|
||||||
&& IsMoveMakingContact(gCurrentMove, gBattlerAttacker) // pickpocket requires contact
|
&& IsMoveMakingContact(gCurrentMove, gBattlerAttacker) // Pickpocket requires contact
|
||||||
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) // obviously attack needs to have worked
|
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) // Obviously attack needs to have worked
|
||||||
{
|
{
|
||||||
u8 battlers[4] = {0, 1, 2, 3};
|
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++)
|
for (i = 0; i < gBattlersCount; i++)
|
||||||
{
|
{
|
||||||
u8 battler = battlers[i];
|
u8 battler = battlers[i];
|
||||||
// attacker is mon who made contact, battler is mon with pickpocket
|
// Attacker is mon who made contact, battler is mon with pickpocket
|
||||||
if (battler != gBattlerAttacker // cannot pickpocket yourself
|
if (battler != gBattlerAttacker // Cannot pickpocket yourself
|
||||||
&& GetBattlerAbility(battler) == ABILITY_PICKPOCKET // 'target' must have pickpocket ability
|
&& GetBattlerAbility(battler) == ABILITY_PICKPOCKET // Target must have pickpocket ability
|
||||||
&& BATTLER_DAMAGED(battler) // target needs to have been damaged
|
&& BATTLER_DAMAGED(battler) // Target needs to have been damaged
|
||||||
&& !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler) // subsitute unaffected
|
&& !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler) // Subsitute unaffected
|
||||||
&& IsBattlerAlive(battler) // battler must be alive to pickpocket
|
&& IsBattlerAlive(battler) // Battler must be alive to pickpocket
|
||||||
&& gBattleMons[battler].item == ITEM_NONE // pickpocketer can't have an item already
|
&& gBattleMons[battler].item == ITEM_NONE // Pickpocketer can't have an item already
|
||||||
&& CanStealItem(battler, gBattlerAttacker, gBattleMons[gBattlerAttacker].item)) // cannot steal plates, mega stones, etc
|
&& CanStealItem(battler, gBattlerAttacker, gBattleMons[gBattlerAttacker].item)) // Cannot steal plates, mega stones, etc
|
||||||
{
|
{
|
||||||
gBattlerTarget = gBattlerAbility = battler;
|
gBattlerTarget = gBattlerAbility = battler;
|
||||||
// battle scripting is super brittle so we shall do the item exchange now (if possible)
|
// Battle scripting is super brittle so we shall do the item exchange now (if possible)
|
||||||
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_STICKY_HOLD)
|
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_STICKY_HOLD)
|
||||||
StealTargetItem(gBattlerTarget, gBattlerAttacker); // target takes attacker's item
|
StealTargetItem(gBattlerTarget, gBattlerAttacker); // Target takes attacker's item
|
||||||
|
|
||||||
gEffectBattler = gBattlerAttacker;
|
gEffectBattler = gBattlerAttacker;
|
||||||
BattleScriptPushCursor();
|
BattleScriptPushCursor();
|
||||||
gBattlescriptCurrInstr = BattleScript_Pickpocket; // includes sticky hold check to print separate string
|
gBattlescriptCurrInstr = BattleScript_Pickpocket; // Includes sticky hold check to print separate string
|
||||||
effect = TRUE;
|
effect = TRUE;
|
||||||
break; // pickpocket activates on fastest mon, so exit loop.
|
break; // Pickpocket activates on fastest mon, so exit loop.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5858,9 +5858,9 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
|
|||||||
&& IsBattlerAlive(gBattlerAttacker)
|
&& IsBattlerAlive(gBattlerAttacker)
|
||||||
&& gBattleMons[gBattlerAttacker].item == ITEM_NONE)
|
&& gBattleMons[gBattlerAttacker].item == ITEM_NONE)
|
||||||
{
|
{
|
||||||
//no sticky hold checks. item is already known so no CanStealItem checks
|
// No sticky hold checks. item is already known so no CanStealItem checks
|
||||||
gEffectBattler = battlerId; //effect battler = target
|
gEffectBattler = battlerId; // gEffectBattler = target
|
||||||
StealTargetItem(gBattlerAttacker, gBattlerTarget); //attacker takes target's barb
|
StealTargetItem(gBattlerAttacker, gBattlerTarget); // Attacker takes target's barb
|
||||||
BattleScriptPushCursor();
|
BattleScriptPushCursor();
|
||||||
gBattlescriptCurrInstr = BattleScript_StickyBarbTransfer;
|
gBattlescriptCurrInstr = BattleScript_StickyBarbTransfer;
|
||||||
effect = ITEM_EFFECT_OTHER;
|
effect = ITEM_EFFECT_OTHER;
|
||||||
@ -5894,7 +5894,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
|
|||||||
RecordItemEffectBattle(battlerId, battlerHoldEffect);
|
RecordItemEffectBattle(battlerId, battlerHoldEffect);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HOLD_EFFECT_STICKY_BARB: //not an orb per-say, but similar effect, and needs to NOT activate with pickpocket
|
case HOLD_EFFECT_STICKY_BARB: // Not an orb per se, but similar effect, and needs to NOT activate with pickpocket
|
||||||
if (GetBattlerAbility(battlerId) != ABILITY_MAGIC_GUARD)
|
if (GetBattlerAbility(battlerId) != ABILITY_MAGIC_GUARD)
|
||||||
{
|
{
|
||||||
gBattleMoveDamage = gBattleMons[battlerId].maxHP / 8;
|
gBattleMoveDamage = gBattleMons[battlerId].maxHP / 8;
|
||||||
@ -7859,8 +7859,8 @@ u8 GetBattleMoveSplit(u32 moveId)
|
|||||||
return SPLIT_SPECIAL;
|
return SPLIT_SPECIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort an array of battlers by speed
|
// Sort an array of battlers by speed
|
||||||
// useful for effects like pickpocket, eject button, red card, dancer
|
// Useful for effects like pickpocket, eject button, red card, dancer
|
||||||
void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast)
|
void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast)
|
||||||
{
|
{
|
||||||
int i, j, currSpeed, currBattler;
|
int i, j, currSpeed, currBattler;
|
||||||
@ -7918,7 +7918,7 @@ void TryRestoreStolenItems(void)
|
|||||||
{
|
{
|
||||||
stolenItem = gBattleStruct->itemStolen[i].originalItem;
|
stolenItem = gBattleStruct->itemStolen[i].originalItem;
|
||||||
if (stolenItem != ITEM_NONE && ItemId_GetPocket(stolenItem) != POCKET_BERRIES)
|
if (stolenItem != ITEM_NONE && ItemId_GetPocket(stolenItem) != POCKET_BERRIES)
|
||||||
SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &stolenItem); //restore stolen non-berry items
|
SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &stolenItem); // Restore stolen non-berry items
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7930,7 +7930,7 @@ bool32 CanStealItem(u8 battlerStealing, u8 battlerItem, u16 item)
|
|||||||
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL)
|
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
// check if the battler trying to steal should be able to
|
// Check if the battler trying to steal should be able to
|
||||||
if (stealerSide == B_SIDE_OPPONENT
|
if (stealerSide == B_SIDE_OPPONENT
|
||||||
&& !(gBattleTypeFlags &
|
&& !(gBattleTypeFlags &
|
||||||
(BATTLE_TYPE_EREADER_TRAINER
|
(BATTLE_TYPE_EREADER_TRAINER
|
||||||
@ -7956,14 +7956,17 @@ bool32 CanStealItem(u8 battlerStealing, u8 battlerItem, u16 item)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if battler with the item can lose it
|
if (!CanBattlerGetOrLoseItem(battlerItem, item) // Battler with item cannot have it stolen
|
||||||
return CanBattlerGetOrLoseItem(battlerItem, item);
|
||!CanBattlerGetOrLoseItem(battlerStealing, item)) // Stealer cannot take the item
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrySaveExchangedItem(u8 battlerId, u16 stolenItem)
|
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
|
// 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)
|
// 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 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 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
|
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER
|
||||||
|
Loading…
x
Reference in New Issue
Block a user