diff --git a/include/config/battle.h b/include/config/battle.h index 915766647..6dea72b40 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -184,6 +184,7 @@ #define B_WILD_NATURAL_ENEMIES TRUE // If set to TRUE, certain wild mon species will attack other species when partnered in double wild battles (eg. Zangoose vs Seviper) #define B_AFFECTION_MECHANICS FALSE // In Gen6+, there's a stat called affection that can trigger different effects in battle. From LGPE onwards, those effects use friendship instead. #define B_TRAINER_CLASS_POKE_BALLS GEN_LATEST // In Gen7+, trainers will use certain types of Poké Balls depending on their trainer class. +#define B_OBEDIENCE_MECHANICS GEN_LATEST // In PLA+ (here Gen8+), obedience restrictions also apply to non-outsider Pokémon, albeit based on their level met rather than actual level // Animation Settings #define B_NEW_SWORD_PARTICLE FALSE // If set to TRUE, it updates Swords Dance's particle. diff --git a/include/pokemon.h b/include/pokemon.h index f70fda91a..d04d44bbb 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -291,6 +291,7 @@ struct BattlePokemon /*0x4D*/ u32 status1; /*0x51*/ u32 status2; /*0x55*/ u32 otId; + /*0x59*/ u8 metLevel; }; struct SpeciesInfo diff --git a/src/battle_controller_link_opponent.c b/src/battle_controller_link_opponent.c index e95b13944..97fc21df9 100644 --- a/src/battle_controller_link_opponent.c +++ b/src/battle_controller_link_opponent.c @@ -595,6 +595,7 @@ static u32 CopyLinkOpponentMonData(u8 monId, u8 *dst) battleMon.spDefense = GetMonData(&gEnemyParty[monId], MON_DATA_SPDEF); battleMon.abilityNum = GetMonData(&gEnemyParty[monId], MON_DATA_ABILITY_NUM); battleMon.otId = GetMonData(&gEnemyParty[monId], MON_DATA_OT_ID); + battleMon.metLevel = GetMonData(&gEnemyParty[monId], MON_DATA_MET_LEVEL); GetMonData(&gEnemyParty[monId], MON_DATA_NICKNAME, nickname); StringCopy_Nickname(battleMon.nickname, nickname); GetMonData(&gEnemyParty[monId], MON_DATA_OT_NAME, battleMon.otName); diff --git a/src/battle_controller_link_partner.c b/src/battle_controller_link_partner.c index da1599a90..d90acd11e 100644 --- a/src/battle_controller_link_partner.c +++ b/src/battle_controller_link_partner.c @@ -489,6 +489,7 @@ static u32 CopyLinkPartnerMonData(u8 monId, u8 *dst) battleMon.spDefense = GetMonData(&gPlayerParty[monId], MON_DATA_SPDEF); battleMon.abilityNum = GetMonData(&gPlayerParty[monId], MON_DATA_ABILITY_NUM); battleMon.otId = GetMonData(&gPlayerParty[monId], MON_DATA_OT_ID); + battleMon.metLevel = GetMonData(&gPlayerParty[monId], MON_DATA_MET_LEVEL); GetMonData(&gPlayerParty[monId], MON_DATA_NICKNAME, nickname); StringCopy_Nickname(battleMon.nickname, nickname); GetMonData(&gPlayerParty[monId], MON_DATA_OT_NAME, battleMon.otName); diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 3e168828d..b6044491b 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -612,6 +612,7 @@ static u32 GetOpponentMonData(u8 monId, u8 *dst) battleMon.spDefense = GetMonData(&gEnemyParty[monId], MON_DATA_SPDEF); battleMon.abilityNum = GetMonData(&gEnemyParty[monId], MON_DATA_ABILITY_NUM); battleMon.otId = GetMonData(&gEnemyParty[monId], MON_DATA_OT_ID); + battleMon.metLevel = GetMonData(&gEnemyParty[monId], MON_DATA_MET_LEVEL); GetMonData(&gEnemyParty[monId], MON_DATA_NICKNAME, nickname); StringCopy_Nickname(battleMon.nickname, nickname); GetMonData(&gEnemyParty[monId], MON_DATA_OT_NAME, battleMon.otName); diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index d2d0cecd8..aab5ad04e 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -1866,6 +1866,7 @@ static u32 CopyPlayerMonData(u8 monId, u8 *dst) battleMon.spDefense = GetMonData(&gPlayerParty[monId], MON_DATA_SPDEF); battleMon.abilityNum = GetMonData(&gPlayerParty[monId], MON_DATA_ABILITY_NUM); battleMon.otId = GetMonData(&gPlayerParty[monId], MON_DATA_OT_ID); + battleMon.metLevel = GetMonData(&gPlayerParty[monId], MON_DATA_MET_LEVEL); GetMonData(&gPlayerParty[monId], MON_DATA_NICKNAME, nickname); StringCopy_Nickname(battleMon.nickname, nickname); GetMonData(&gPlayerParty[monId], MON_DATA_OT_NAME, battleMon.otName); diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index 712f1562d..d17aeaa93 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -675,6 +675,7 @@ static u32 CopyPlayerPartnerMonData(u8 monId, u8 *dst) battleMon.spDefense = GetMonData(&gPlayerParty[monId], MON_DATA_SPDEF); battleMon.abilityNum = GetMonData(&gPlayerParty[monId], MON_DATA_ABILITY_NUM); battleMon.otId = GetMonData(&gPlayerParty[monId], MON_DATA_OT_ID); + battleMon.metLevel = GetMonData(&gPlayerParty[monId], MON_DATA_MET_LEVEL); GetMonData(&gPlayerParty[monId], MON_DATA_NICKNAME, nickname); StringCopy_Nickname(battleMon.nickname, nickname); GetMonData(&gPlayerParty[monId], MON_DATA_OT_NAME, battleMon.otName); diff --git a/src/battle_controller_recorded_opponent.c b/src/battle_controller_recorded_opponent.c index 9f3631a37..f1243ee2b 100644 --- a/src/battle_controller_recorded_opponent.c +++ b/src/battle_controller_recorded_opponent.c @@ -581,6 +581,7 @@ static u32 CopyRecordedOpponentMonData(u8 monId, u8 *dst) battleMon.spDefense = GetMonData(&gEnemyParty[monId], MON_DATA_SPDEF); battleMon.abilityNum = GetMonData(&gEnemyParty[monId], MON_DATA_ABILITY_NUM); battleMon.otId = GetMonData(&gEnemyParty[monId], MON_DATA_OT_ID); + battleMon.metLevel = GetMonData(&gEnemyParty[monId], MON_DATA_MET_LEVEL); GetMonData(&gEnemyParty[monId], MON_DATA_NICKNAME, nickname); StringCopy_Nickname(battleMon.nickname, nickname); GetMonData(&gEnemyParty[monId], MON_DATA_OT_NAME, battleMon.otName); diff --git a/src/battle_controller_recorded_player.c b/src/battle_controller_recorded_player.c index ecc8e09de..f2e1fc295 100644 --- a/src/battle_controller_recorded_player.c +++ b/src/battle_controller_recorded_player.c @@ -562,6 +562,7 @@ static u32 CopyRecordedPlayerMonData(u8 monId, u8 *dst) battleMon.spDefense = GetMonData(&gPlayerParty[monId], MON_DATA_SPDEF); battleMon.abilityNum = GetMonData(&gPlayerParty[monId], MON_DATA_ABILITY_NUM); battleMon.otId = GetMonData(&gPlayerParty[monId], MON_DATA_OT_ID); + battleMon.metLevel = GetMonData(&gPlayerParty[monId], MON_DATA_MET_LEVEL); GetMonData(&gPlayerParty[monId], MON_DATA_NICKNAME, nickname); StringCopy_Nickname(battleMon.nickname, nickname); GetMonData(&gPlayerParty[monId], MON_DATA_OT_NAME, battleMon.otName); diff --git a/src/battle_controller_wally.c b/src/battle_controller_wally.c index 4f4f2eb6f..da4b8754e 100644 --- a/src/battle_controller_wally.c +++ b/src/battle_controller_wally.c @@ -491,6 +491,7 @@ static u32 CopyWallyMonData(u8 monId, u8 *dst) battleMon.spDefense = GetMonData(&gPlayerParty[monId], MON_DATA_SPDEF); battleMon.abilityNum = GetMonData(&gPlayerParty[monId], MON_DATA_ABILITY_NUM); battleMon.otId = GetMonData(&gPlayerParty[monId], MON_DATA_OT_ID); + battleMon.metLevel = GetMonData(&gPlayerParty[monId], MON_DATA_MET_LEVEL); GetMonData(&gPlayerParty[monId], MON_DATA_NICKNAME, nickname); StringCopy_Nickname(battleMon.nickname, nickname); GetMonData(&gPlayerParty[monId], MON_DATA_OT_NAME, battleMon.otName); diff --git a/src/battle_util.c b/src/battle_util.c index b9b57f4eb..11f733e13 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8018,6 +8018,7 @@ u8 IsMonDisobedient(void) s32 rnd; s32 calc; u8 obedienceLevel = 0; + u8 levelReferenced; if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK)) return 0; @@ -8032,8 +8033,10 @@ u8 IsMonDisobedient(void) return 0; if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) return 0; + #if B_OBEDIENCE_MECHANICS < GEN_8 if (!IsOtherTrainer(gBattleMons[gBattlerAttacker].otId, gBattleMons[gBattlerAttacker].otName)) return 0; + #endif if (FlagGet(FLAG_BADGE08_GET)) return 0; @@ -8047,10 +8050,19 @@ u8 IsMonDisobedient(void) obedienceLevel = 70; } +#if B_OBEDIENCE_MECHANICS >= GEN_8 + if (!IsOtherTrainer(gBattleMons[gBattlerAttacker].otId, gBattleMons[gBattlerAttacker].otName)) + levelReferenced = gBattleMons[gBattlerAttacker].metLevel; + else +#else if (gBattleMons[gBattlerAttacker].level <= obedienceLevel) +#endif + levelReferenced = gBattleMons[gBattlerAttacker].level; + + if (levelReferenced <= obedienceLevel) return 0; rnd = (Random() & 255); - calc = (gBattleMons[gBattlerAttacker].level + obedienceLevel) * rnd >> 8; + calc = (levelReferenced + obedienceLevel) * rnd >> 8; if (calc < obedienceLevel) return 0; @@ -8064,7 +8076,7 @@ u8 IsMonDisobedient(void) } rnd = (Random() & 255); - calc = (gBattleMons[gBattlerAttacker].level + obedienceLevel) * rnd >> 8; + calc = (levelReferenced + obedienceLevel) * rnd >> 8; if (calc < obedienceLevel) { calc = CheckMoveLimitations(gBattlerAttacker, gBitTable[gCurrMovePos], MOVE_LIMITATIONS_ALL); @@ -8092,7 +8104,7 @@ u8 IsMonDisobedient(void) } else { - obedienceLevel = gBattleMons[gBattlerAttacker].level - obedienceLevel; + obedienceLevel = levelReferenced - obedienceLevel; calc = (Random() & 255); if (calc < obedienceLevel && CanSleep(gBattlerAttacker))