From bfb697c8f15a4d0d5a47b095e9c24c304e4ca3db Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Mon, 17 Jun 2024 23:24:23 +0200 Subject: [PATCH] even more reordering --- src/battle_util.c | 461 +++++++++++++++++++++++----------------------- 1 file changed, 231 insertions(+), 230 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index de2601323..eda4be73a 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1238,6 +1238,24 @@ u8 GetImprisonedMovesCount(u8 battlerId, u16 move) return imprisonedMoves; } +u32 GetBattlerAffectionHearts(u32 battler) +{ + u8 side = GetBattlerSide(battler); + struct Pokemon *party = GetSideParty(side); + u16 species = GetMonData(&party[gBattlerPartyIndexes[battler]], MON_DATA_SPECIES); + + if (side != B_SIDE_PLAYER) + return AFFECTION_NO_HEARTS; + else if (gSpeciesInfo[species].isMegaEvolution + || (gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER + | BATTLE_TYPE_BATTLE_TOWER + | BATTLE_TYPE_RECORDED_LINK + | BATTLE_TYPE_LINK))) + return AFFECTION_NO_HEARTS; + + return GetMonAffectionHearts(&party[gBattlerPartyIndexes[battler]]); +} + static void TryToRevertMimicryAndFlags(void) { u32 i; @@ -3385,6 +3403,62 @@ bool32 HasNoMonsToSwitch(u32 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2 } } +static const u16 sWeatherFlagsInfo[][3] = +{ + [ENUM_WEATHER_RAIN] = {B_WEATHER_RAIN_TEMPORARY, B_WEATHER_RAIN_PERMANENT, HOLD_EFFECT_DAMP_ROCK}, + [ENUM_WEATHER_RAIN_PRIMAL] = {B_WEATHER_RAIN_PRIMAL, B_WEATHER_RAIN_PRIMAL, HOLD_EFFECT_DAMP_ROCK}, + [ENUM_WEATHER_SUN] = {B_WEATHER_SUN_TEMPORARY, B_WEATHER_SUN_PERMANENT, HOLD_EFFECT_HEAT_ROCK}, + [ENUM_WEATHER_SUN_PRIMAL] = {B_WEATHER_SUN_PRIMAL, B_WEATHER_SUN_PRIMAL, HOLD_EFFECT_HEAT_ROCK}, + [ENUM_WEATHER_SANDSTORM] = {B_WEATHER_SANDSTORM_TEMPORARY, B_WEATHER_SANDSTORM_PERMANENT, HOLD_EFFECT_SMOOTH_ROCK}, + [ENUM_WEATHER_HAIL] = {B_WEATHER_HAIL_TEMPORARY, B_WEATHER_HAIL_PERMANENT, HOLD_EFFECT_ICY_ROCK}, + [ENUM_WEATHER_STRONG_WINDS] = {B_WEATHER_STRONG_WINDS, B_WEATHER_STRONG_WINDS, HOLD_EFFECT_NONE}, + [ENUM_WEATHER_SNOW] = {B_WEATHER_SNOW_TEMPORARY, B_WEATHER_SNOW_PERMANENT, HOLD_EFFECT_ICY_ROCK}, +}; + +static void ShouldChangeFormInWeather(u32 battler) +{ + int i; + int side = GetBattlerSide(battler); + struct Pokemon *party = GetSideParty(side); + + for (i = 0; i < PARTY_SIZE; i++) + { + if (GetMonData(&party[i], MON_DATA_SPECIES) == SPECIES_EISCUE_NOICE_FACE) + gBattleStruct->allowedToChangeFormInWeather[i][side] = TRUE; + else + gBattleStruct->allowedToChangeFormInWeather[i][side] = FALSE; + } +} + +bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility) +{ + u16 battlerAbility = GetBattlerAbility(battler); + if (gBattleWeather & B_WEATHER_PRIMAL_ANY + && battlerAbility != ABILITY_DESOLATE_LAND + && battlerAbility != ABILITY_PRIMORDIAL_SEA + && battlerAbility != ABILITY_DELTA_STREAM) + { + return FALSE; + } + else if (B_ABILITY_WEATHER < GEN_6 && viaAbility && !(gBattleWeather & sWeatherFlagsInfo[weatherEnumId][1])) + { + gBattleWeather = (sWeatherFlagsInfo[weatherEnumId][0] | sWeatherFlagsInfo[weatherEnumId][1]); + ShouldChangeFormInWeather(battler); + return TRUE; + } + else if (!(gBattleWeather & (sWeatherFlagsInfo[weatherEnumId][0] | sWeatherFlagsInfo[weatherEnumId][1]))) + { + gBattleWeather = (sWeatherFlagsInfo[weatherEnumId][0]); + if (GetBattlerHoldEffect(battler, TRUE) == sWeatherFlagsInfo[weatherEnumId][2]) + gWishFutureKnock.weatherDuration = 8; + else + gWishFutureKnock.weatherDuration = 5; + ShouldChangeFormInWeather(battler); + return TRUE; + } + return FALSE; +} + static bool32 TryChangeBattleTerrain(u32 battler, u32 statusFlag, u8 *timer) { if ((!(gFieldStatuses & statusFlag) && (!gBattleStruct->isSkyBattle))) @@ -6059,6 +6133,30 @@ static u8 DamagedStatBoostBerryEffect(u32 battler, u8 statId, u8 category) return 0; } +u8 TryHandleSeed(u32 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 execute) +{ + if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + BufferStatChange(battler, statId, STRINGID_STATROSE); + gLastUsedItem = itemId; // For surge abilities + gEffectBattler = gBattleScripting.battler = battler; + SET_STATCHANGER(statId, 1, FALSE); + gBattleScripting.animArg1 = 14 + statId; + gBattleScripting.animArg2 = 0; + if (execute) + { + BattleScriptExecute(BattleScript_BerryStatRaiseEnd2); + } + else + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet; + } + return ITEM_STATS_CHANGE; + } + return 0; +} + static u32 ItemRestorePp(u32 battler, u32 itemId, bool32 execute) { struct Pokemon *party = GetBattlerParty(battler); @@ -7615,6 +7713,123 @@ static bool32 IsBattlerModernFatefulEncounter(u8 battlerId) return GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_MODERN_FATEFUL_ENCOUNTER, NULL); } +u8 IsMonDisobedient(void) +{ + s32 rnd; + s32 calc; + u8 obedienceLevel = 0; + + if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK)) + return 0; + if (BattlerHasAi(gBattlerAttacker)) + return 0; + if ((gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_POKEDUDE))) + return 0; + if (GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT) + return 0; // TODO: might not be reached? remove? + + if (IsBattlerModernFatefulEncounter(gBattlerAttacker)) // only false if illegal Mew or Deoxys + { + if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) + return 0; + if (!IsOtherTrainer(gBattleMons[gBattlerAttacker].otId, gBattleMons[gBattlerAttacker].otName)) + return 0; + if (FlagGet(FLAG_BADGE08_GET)) + return 0; + + obedienceLevel = 10; + + if (FlagGet(FLAG_BADGE02_GET)) + obedienceLevel = 30; + if (FlagGet(FLAG_BADGE04_GET)) + obedienceLevel = 50; + if (FlagGet(FLAG_BADGE06_GET)) + obedienceLevel = 70; + } + + if (gBattleMons[gBattlerAttacker].level <= obedienceLevel) + return 0; + rnd = (Random() & 255); + calc = (gBattleMons[gBattlerAttacker].level + obedienceLevel) * rnd >> 8; + if (calc < obedienceLevel) + return 0; + + // is not obedient + if (gCurrentMove == MOVE_RAGE) + gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_RAGE; + if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP && (gCurrentMove == MOVE_SNORE || gCurrentMove == MOVE_SLEEP_TALK)) + { + gBattlescriptCurrInstr = BattleScript_IgnoresWhileAsleep; + return 1; + } + + rnd = (Random() & 255); + calc = (gBattleMons[gBattlerAttacker].level + obedienceLevel) * rnd >> 8; + if (calc < obedienceLevel && gCurrentMove != MOVE_FOCUS_PUNCH) // Additional check for focus punch in FR + { + calc = CheckMoveLimitations(gBattlerAttacker, gBitTable[gCurrMovePos], MOVE_LIMITATIONS_ALL); + if (calc == 0xF) // all moves cannot be used + { + // Randomly select, then print a disobedient string + // B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE + gBattleCommunication[MULTISTRING_CHOOSER] = Random() & (NUM_LOAF_STRINGS - 1); + gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAroundMsg; + return 1; + } + else // use a random move + { + do + { + gCurrMovePos = gChosenMovePos = Random() & (MAX_MON_MOVES - 1); + } while (gBitTable[gCurrMovePos] & calc); + + gCalledMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos]; + gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove; + gBattlerTarget = GetMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); + gHitMarker |= HITMARKER_DISOBEDIENT_MOVE; + return 2; + } + } + else + { + obedienceLevel = gBattleMons[gBattlerAttacker].level - obedienceLevel; + + calc = (Random() & 255); + if (calc < obedienceLevel && !(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY) && gBattleMons[gBattlerAttacker].ability != ABILITY_VITAL_SPIRIT && gBattleMons[gBattlerAttacker].ability != ABILITY_INSOMNIA) + { + // try putting asleep + int i; + for (i = 0; i < gBattlersCount; i++) + { + if (gBattleMons[i].status2 & STATUS2_UPROAR) + break; + } + if (i == gBattlersCount) + { + gBattlescriptCurrInstr = BattleScript_IgnoresAndFallsAsleep; + return 1; + } + } + calc -= obedienceLevel; + if (calc < obedienceLevel) + { + gBattleMoveDamage = CalculateMoveDamage(MOVE_NONE, gBattlerAttacker, gBattlerAttacker, TYPE_MYSTERY, 40, FALSE, FALSE, TRUE); + gBattlerTarget = gBattlerAttacker; + gBattlescriptCurrInstr = BattleScript_IgnoresAndHitsItself; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + return 2; + } + else + { + // Randomly select, then print a disobedient string + // B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE + gBattleCommunication[MULTISTRING_CHOOSER] = Random() & (NUM_LOAF_STRINGS - 1); + gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAroundMsg; + return 1; + } + } +} + bool32 TryPrimalReversion(u32 battler) { if (GetBattlerHoldEffect(battler, FALSE) == HOLD_EFFECT_PRIMAL_ORB @@ -7874,6 +8089,22 @@ bool32 CanBattlerEscape(u32 battler) // no ability check return TRUE; } +static u32 GetBattlerItemHoldEffectParam(u32 battler, u32 item) +{ + if (item == ITEM_ENIGMA_BERRY_E_READER) + return gEnigmaBerries[battler].holdEffectParam; + else + return ItemId_GetHoldEffectParam(item); +} + +u32 GetBattlerHoldEffectParam(u32 battler) +{ + if (gBattleMons[battler].item == ITEM_ENIGMA_BERRY_E_READER) + return gEnigmaBerries[battler].holdEffectParam; + else + return ItemId_GetHoldEffectParam(gBattleMons[battler].item); +} + bool32 IsMoveMakingContact(u32 move, u32 battlerAtk) { u32 atkHoldEffect = GetBattlerHoldEffect(battlerAtk, TRUE); @@ -10019,236 +10250,6 @@ bool32 CanUltraBurst(u32 battler) return FALSE; } -u32 GetBattlerHoldEffectParam(u32 battler) -{ - if (gBattleMons[battler].item == ITEM_ENIGMA_BERRY_E_READER) - return gEnigmaBerries[battler].holdEffectParam; - else - return ItemId_GetHoldEffectParam(gBattleMons[battler].item); -} -u8 IsMonDisobedient(void) -{ - s32 rnd; - s32 calc; - u8 obedienceLevel = 0; - - if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK)) - return 0; - if (BattlerHasAi(gBattlerAttacker)) - return 0; - if ((gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_POKEDUDE))) - return 0; - if (GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT) - return 0; // TODO: might not be reached? remove? - - if (IsBattlerModernFatefulEncounter(gBattlerAttacker)) // only false if illegal Mew or Deoxys - { - if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) - return 0; - if (!IsOtherTrainer(gBattleMons[gBattlerAttacker].otId, gBattleMons[gBattlerAttacker].otName)) - return 0; - if (FlagGet(FLAG_BADGE08_GET)) - return 0; - - obedienceLevel = 10; - - if (FlagGet(FLAG_BADGE02_GET)) - obedienceLevel = 30; - if (FlagGet(FLAG_BADGE04_GET)) - obedienceLevel = 50; - if (FlagGet(FLAG_BADGE06_GET)) - obedienceLevel = 70; - } - - if (gBattleMons[gBattlerAttacker].level <= obedienceLevel) - return 0; - rnd = (Random() & 255); - calc = (gBattleMons[gBattlerAttacker].level + obedienceLevel) * rnd >> 8; - if (calc < obedienceLevel) - return 0; - - // is not obedient - if (gCurrentMove == MOVE_RAGE) - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_RAGE; - if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP && (gCurrentMove == MOVE_SNORE || gCurrentMove == MOVE_SLEEP_TALK)) - { - gBattlescriptCurrInstr = BattleScript_IgnoresWhileAsleep; - return 1; - } - - rnd = (Random() & 255); - calc = (gBattleMons[gBattlerAttacker].level + obedienceLevel) * rnd >> 8; - if (calc < obedienceLevel && gCurrentMove != MOVE_FOCUS_PUNCH) // Additional check for focus punch in FR - { - calc = CheckMoveLimitations(gBattlerAttacker, gBitTable[gCurrMovePos], MOVE_LIMITATIONS_ALL); - if (calc == 0xF) // all moves cannot be used - { - // Randomly select, then print a disobedient string - // B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE - gBattleCommunication[MULTISTRING_CHOOSER] = Random() & (NUM_LOAF_STRINGS - 1); - gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAroundMsg; - return 1; - } - else // use a random move - { - do - { - gCurrMovePos = gChosenMovePos = Random() & (MAX_MON_MOVES - 1); - } while (gBitTable[gCurrMovePos] & calc); - - gCalledMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos]; - gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove; - gBattlerTarget = GetMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); - gHitMarker |= HITMARKER_DISOBEDIENT_MOVE; - return 2; - } - } - else - { - obedienceLevel = gBattleMons[gBattlerAttacker].level - obedienceLevel; - - calc = (Random() & 255); - if (calc < obedienceLevel && !(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY) && gBattleMons[gBattlerAttacker].ability != ABILITY_VITAL_SPIRIT && gBattleMons[gBattlerAttacker].ability != ABILITY_INSOMNIA) - { - // try putting asleep - int i; - for (i = 0; i < gBattlersCount; i++) - { - if (gBattleMons[i].status2 & STATUS2_UPROAR) - break; - } - if (i == gBattlersCount) - { - gBattlescriptCurrInstr = BattleScript_IgnoresAndFallsAsleep; - return 1; - } - } - calc -= obedienceLevel; - if (calc < obedienceLevel) - { - gBattleMoveDamage = CalculateMoveDamage(MOVE_NONE, gBattlerAttacker, gBattlerAttacker, TYPE_MYSTERY, 40, FALSE, FALSE, TRUE); - gBattlerTarget = gBattlerAttacker; - gBattlescriptCurrInstr = BattleScript_IgnoresAndHitsItself; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return 2; - } - else - { - // Randomly select, then print a disobedient string - // B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE - gBattleCommunication[MULTISTRING_CHOOSER] = Random() & (NUM_LOAF_STRINGS - 1); - gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAroundMsg; - return 1; - } - } -} - -u32 GetBattlerAffectionHearts(u32 battler) -{ - u8 side = GetBattlerSide(battler); - struct Pokemon *party = GetSideParty(side); - u16 species = GetMonData(&party[gBattlerPartyIndexes[battler]], MON_DATA_SPECIES); - - if (side != B_SIDE_PLAYER) - return AFFECTION_NO_HEARTS; - else if (gSpeciesInfo[species].isMegaEvolution - || (gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER - | BATTLE_TYPE_BATTLE_TOWER - | BATTLE_TYPE_RECORDED_LINK - | BATTLE_TYPE_LINK))) - return AFFECTION_NO_HEARTS; - - return GetMonAffectionHearts(&party[gBattlerPartyIndexes[battler]]); -} - -static const u16 sWeatherFlagsInfo[][3] = -{ - [ENUM_WEATHER_RAIN] = {B_WEATHER_RAIN_TEMPORARY, B_WEATHER_RAIN_PERMANENT, HOLD_EFFECT_DAMP_ROCK}, - [ENUM_WEATHER_RAIN_PRIMAL] = {B_WEATHER_RAIN_PRIMAL, B_WEATHER_RAIN_PRIMAL, HOLD_EFFECT_DAMP_ROCK}, - [ENUM_WEATHER_SUN] = {B_WEATHER_SUN_TEMPORARY, B_WEATHER_SUN_PERMANENT, HOLD_EFFECT_HEAT_ROCK}, - [ENUM_WEATHER_SUN_PRIMAL] = {B_WEATHER_SUN_PRIMAL, B_WEATHER_SUN_PRIMAL, HOLD_EFFECT_HEAT_ROCK}, - [ENUM_WEATHER_SANDSTORM] = {B_WEATHER_SANDSTORM_TEMPORARY, B_WEATHER_SANDSTORM_PERMANENT, HOLD_EFFECT_SMOOTH_ROCK}, - [ENUM_WEATHER_HAIL] = {B_WEATHER_HAIL_TEMPORARY, B_WEATHER_HAIL_PERMANENT, HOLD_EFFECT_ICY_ROCK}, - [ENUM_WEATHER_STRONG_WINDS] = {B_WEATHER_STRONG_WINDS, B_WEATHER_STRONG_WINDS, HOLD_EFFECT_NONE}, - [ENUM_WEATHER_SNOW] = {B_WEATHER_SNOW_TEMPORARY, B_WEATHER_SNOW_PERMANENT, HOLD_EFFECT_ICY_ROCK}, -}; - -static void ShouldChangeFormInWeather(u32 battler) -{ - int i; - int side = GetBattlerSide(battler); - struct Pokemon *party = GetSideParty(side); - - for (i = 0; i < PARTY_SIZE; i++) - { - if (GetMonData(&party[i], MON_DATA_SPECIES) == SPECIES_EISCUE_NOICE_FACE) - gBattleStruct->allowedToChangeFormInWeather[i][side] = TRUE; - else - gBattleStruct->allowedToChangeFormInWeather[i][side] = FALSE; - } -} - -bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility) -{ - u16 battlerAbility = GetBattlerAbility(battler); - if (gBattleWeather & B_WEATHER_PRIMAL_ANY - && battlerAbility != ABILITY_DESOLATE_LAND - && battlerAbility != ABILITY_PRIMORDIAL_SEA - && battlerAbility != ABILITY_DELTA_STREAM) - { - return FALSE; - } - else if (B_ABILITY_WEATHER < GEN_6 && viaAbility && !(gBattleWeather & sWeatherFlagsInfo[weatherEnumId][1])) - { - gBattleWeather = (sWeatherFlagsInfo[weatherEnumId][0] | sWeatherFlagsInfo[weatherEnumId][1]); - ShouldChangeFormInWeather(battler); - return TRUE; - } - else if (!(gBattleWeather & (sWeatherFlagsInfo[weatherEnumId][0] | sWeatherFlagsInfo[weatherEnumId][1]))) - { - gBattleWeather = (sWeatherFlagsInfo[weatherEnumId][0]); - if (GetBattlerHoldEffect(battler, TRUE) == sWeatherFlagsInfo[weatherEnumId][2]) - gWishFutureKnock.weatherDuration = 8; - else - gWishFutureKnock.weatherDuration = 5; - ShouldChangeFormInWeather(battler); - return TRUE; - } - return FALSE; -} - -u8 TryHandleSeed(u32 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 execute) -{ - if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)) - { - BufferStatChange(battler, statId, STRINGID_STATROSE); - gLastUsedItem = itemId; // For surge abilities - gEffectBattler = gBattleScripting.battler = battler; - SET_STATCHANGER(statId, 1, FALSE); - gBattleScripting.animArg1 = 14 + statId; - gBattleScripting.animArg2 = 0; - if (execute) - { - BattleScriptExecute(BattleScript_BerryStatRaiseEnd2); - } - else - { - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet; - } - return ITEM_STATS_CHANGE; - } - return 0; -} - -static u32 GetBattlerItemHoldEffectParam(u32 battler, u32 item) -{ - if (item == ITEM_ENIGMA_BERRY_E_READER) - return gEnigmaBerries[battler].holdEffectParam; - else - return ItemId_GetHoldEffectParam(item); -} - bool32 IsBattlerMegaEvolved(u32 battler) { // While Transform does copy stats and visuals, it shouldn't be counted as true Mega Evolution.