Introduces BattlerState struct for the Battle Engine (#5954)
This commit is contained in:
parent
21bc5cfd30
commit
6e5f40d506
@ -137,6 +137,7 @@ struct DisableStruct
|
||||
u8 terrainAbilityDone:1;
|
||||
u8 usedProteanLibero:1;
|
||||
u16 overwrittenAbility; // abilities overwritten during battle (keep separate from battle history in case of switching)
|
||||
u8 boosterEnergyActivates:1;
|
||||
};
|
||||
|
||||
struct ProtectStruct
|
||||
@ -235,6 +236,8 @@ struct SpecialStatus
|
||||
u8 teraShellAbilityDone:1;
|
||||
u8 criticalHit:1;
|
||||
// End of byte
|
||||
u8 enduredDamage:1;
|
||||
u8 padding:7;
|
||||
};
|
||||
|
||||
struct SideTimer
|
||||
@ -621,8 +624,32 @@ enum BattleIntroStates
|
||||
BATTLE_INTRO_STATE_SET_DEX_AND_BATTLE_VARS
|
||||
};
|
||||
|
||||
struct BattlerState
|
||||
{
|
||||
u8 targetsDone[MAX_BATTLERS_COUNT];
|
||||
|
||||
u32 commandingDondozo:1;
|
||||
u32 absentBattlerFlags:1;
|
||||
u32 focusPunchBattlers:1;
|
||||
u32 multipleSwitchInBattlers:1;
|
||||
u32 alreadyStatusedMoveAttempt:1; // For example when using Thunder Wave on an already paralyzed Pokémon.
|
||||
u32 activeAbilityPopUps:1;
|
||||
u32 lastMoveFailed:1; // For Stomping Tantrum
|
||||
u32 forcedSwitch:1;
|
||||
u32 storedHealingWish:1;
|
||||
u32 storedLunarDance:1;
|
||||
u32 usedEjectItem:1;
|
||||
u32 sleepClauseEffectExempt:1; // Stores whether effect should be exempt from triggering Sleep Clause (Effect Spore)
|
||||
u32 usedMicleBerry:1;
|
||||
u32 pursuitTarget:1;
|
||||
u32 padding:17;
|
||||
// End of Word
|
||||
};
|
||||
|
||||
// Cleared at the beginning of the battle. Fields need to be cleared when needed manually otherwise.
|
||||
struct BattleStruct
|
||||
{
|
||||
struct BattlerState battlerState[MAX_BATTLERS_COUNT];
|
||||
u8 turnEffectsTracker;
|
||||
u8 turnEffectsBattlerId;
|
||||
u8 turnCountersTracker;
|
||||
@ -640,7 +667,6 @@ struct BattleStruct
|
||||
u8 wildVictorySong;
|
||||
u8 dynamicMoveType;
|
||||
u8 wrappedBy[MAX_BATTLERS_COUNT];
|
||||
u8 focusPunchBattlers; // as bits
|
||||
u8 battlerPreventingSwitchout;
|
||||
u8 moneyMultiplier:6;
|
||||
u8 moneyMultiplierItem:1;
|
||||
@ -681,9 +707,9 @@ struct BattleStruct
|
||||
u8 hpScale;
|
||||
u16 synchronizeMoveEffect;
|
||||
u8 anyMonHasTransformed:1; // Only used in battle_tv.c
|
||||
u8 multipleSwitchInBattlers:4; // One bit per battler
|
||||
u8 multipleSwitchInState:2;
|
||||
u8 multipleSwitchInCursor:3;
|
||||
u8 padding1:2;
|
||||
u8 multipleSwitchInSortedBattlers[MAX_BATTLERS_COUNT];
|
||||
void (*savedCallback)(void);
|
||||
u16 usedHeldItems[PARTY_SIZE][NUM_BATTLE_SIDES]; // For each party member and side. For harvest, recycle
|
||||
@ -720,7 +746,6 @@ struct BattleStruct
|
||||
u16 arenaStartHp[2];
|
||||
u8 arenaLostPlayerMons; // Bits for party member, lost as in referee's decision, not by fainting.
|
||||
u8 arenaLostOpponentMons;
|
||||
u8 alreadyStatusedMoveAttempt; // As bits for battlers; For example when using Thunder Wave on an already paralyzed Pokémon.
|
||||
u8 debugBattler;
|
||||
u8 magnitudeBasePower;
|
||||
u8 presentBasePower;
|
||||
@ -730,7 +755,6 @@ struct BattleStruct
|
||||
u8 savedTargetCount:4;
|
||||
u8 savedAttackerCount:4;
|
||||
bool8 ateBoost[MAX_BATTLERS_COUNT];
|
||||
u8 activeAbilityPopUps; // as bits for each battler
|
||||
u8 abilityPopUpSpriteIds[MAX_BATTLERS_COUNT][2]; // two per battler
|
||||
struct ZMoveData zmove;
|
||||
struct DynamaxData dynamax;
|
||||
@ -739,7 +763,6 @@ struct BattleStruct
|
||||
enum BattleIntroStates introState:8;
|
||||
u8 ateBerry[2]; // array id determined by side, each party pokemon as bit
|
||||
u8 stolenStats[NUM_BATTLE_STATS]; // hp byte is used for which stats to raise, other inform about by how many stages
|
||||
u8 lastMoveFailed; // as bits for each battler, for the sake of Stomping Tantrum
|
||||
u8 lastMoveTarget[MAX_BATTLERS_COUNT]; // The last target on which each mon used a move, for the sake of Instruct
|
||||
u16 tracedAbility[MAX_BATTLERS_COUNT];
|
||||
u16 hpBefore[MAX_BATTLERS_COUNT]; // Hp of battlers before using a move. For Berserk and Anger Shell.
|
||||
@ -754,8 +777,6 @@ struct BattleStruct
|
||||
u16 changedSpecies[NUM_BATTLE_SIDES][PARTY_SIZE]; // For forms when multiple mons can change into the same pokemon.
|
||||
u8 quickClawBattlerId;
|
||||
struct LostItem itemLost[NUM_BATTLE_SIDES][PARTY_SIZE]; // Pokemon that had items consumed or stolen (two bytes per party member per side)
|
||||
u8 forcedSwitch:4; // For each battler
|
||||
u8 additionalEffectsCounter:4; // A counter for the additionalEffects applied by the current move in Cmd_setadditionaleffects
|
||||
u8 blunderPolicy:1; // should blunder policy activate
|
||||
u8 swapDamageCategory:1; // Photon Geyser, Shell Side Arm, Light That Burns the Sky
|
||||
u8 bouncedMoveIsUsed:1;
|
||||
@ -773,10 +794,7 @@ struct BattleStruct
|
||||
u8 hitSwitchTargetFailed:1;
|
||||
u8 effectsBeforeUsingMoveDone:1; // Mega Evo and Focus Punch/Shell Trap effects.
|
||||
u8 spriteIgnore0Hp:1;
|
||||
u8 targetsDone[MAX_BATTLERS_COUNT]; // Each battler as a bit.
|
||||
u8 battleBondTransformed[NUM_BATTLE_SIDES]; // Bitfield for each party.
|
||||
u8 storedHealingWish:4; // Each battler as a bit.
|
||||
u8 storedLunarDance:4; // Each battler as a bit.
|
||||
u8 bonusCritStages[MAX_BATTLERS_COUNT]; // G-Max Chi Strike boosts crit stages of allies.
|
||||
u8 itemPartyIndex[MAX_BATTLERS_COUNT];
|
||||
u8 itemMoveIndex[MAX_BATTLERS_COUNT];
|
||||
@ -795,7 +813,6 @@ struct BattleStruct
|
||||
u32 aiDelayTimer; // Counts number of frames AI takes to choose an action.
|
||||
u32 aiDelayFrames; // Number of frames it took to choose an action.
|
||||
u8 timesGotHit[NUM_BATTLE_SIDES][PARTY_SIZE];
|
||||
u8 enduredDamage;
|
||||
u8 transformZeroToHero[NUM_BATTLE_SIDES];
|
||||
u8 stickySyrupdBy[MAX_BATTLERS_COUNT];
|
||||
u8 intrepidSwordBoost[NUM_BATTLE_SIDES];
|
||||
@ -806,18 +823,13 @@ struct BattleStruct
|
||||
u8 quickDrawRandom[MAX_BATTLERS_COUNT];
|
||||
u8 shellSideArmCategory[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT];
|
||||
u8 speedTieBreaks; // MAX_BATTLERS_COUNT! values.
|
||||
u8 boosterEnergyActivates;
|
||||
u8 categoryOverride; // for Z-Moves and Max Moves
|
||||
u8 commandingDondozo;
|
||||
u16 commanderActive[MAX_BATTLERS_COUNT];
|
||||
u32 stellarBoostFlags[NUM_BATTLE_SIDES]; // stored as a bitfield of flags for all types for each side
|
||||
u8 redCardActivates:1;
|
||||
u8 padding1:7;
|
||||
u8 usedEjectItem;
|
||||
u8 monCausingSleepClause[NUM_BATTLE_SIDES]; // Stores which pokemon on a given side is causing Sleep Clause to be active as the mon's index in the party
|
||||
u8 sleepClauseEffectExempt:4; // Stores whether effect should be exempt from triggering Sleep Clause (Effect Spore)
|
||||
u8 usedMicleBerry:4;
|
||||
u8 pursuitTarget:4; // Each battler as a bit.
|
||||
u8 additionalEffectsCounter:4; // A counter for the additionalEffects applied by the current move in Cmd_setadditionaleffects
|
||||
u8 redCardActivates:1;
|
||||
u8 padding2:2; // padding in the middle so pursuit fields are together
|
||||
u8 pursuitSwitchByMove:1;
|
||||
u8 pursuitStoredSwitch; // Stored id for the Pursuit target's switch
|
||||
s32 battlerExpReward;
|
||||
@ -833,7 +845,7 @@ struct BattleStruct
|
||||
u8 calculatedSpreadMoveAccuracy:1;
|
||||
u8 printedStrongWindsWeakenedAttack:1;
|
||||
u8 numSpreadTargets:2;
|
||||
u8 padding2:2;
|
||||
u8 padding3:2;
|
||||
};
|
||||
|
||||
// The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider,
|
||||
@ -1190,7 +1202,7 @@ static inline bool32 IsBattlerTurnDamaged(u32 battler)
|
||||
{
|
||||
return gSpecialStatuses[battler].physicalDmg != 0
|
||||
|| gSpecialStatuses[battler].specialDmg != 0
|
||||
|| gBattleStruct->enduredDamage & (1u << battler);
|
||||
|| gSpecialStatuses[battler].enduredDamage;
|
||||
}
|
||||
|
||||
static inline bool32 IsBattlerAtMaxHp(u32 battler)
|
||||
|
||||
@ -339,5 +339,8 @@ void ClearDamageCalcResults(void);
|
||||
u32 DoesDestinyBondFail(u32 battler);
|
||||
bool32 IsMoveEffectBlockedByTarget(u32 ability);
|
||||
u32 NumAffectedSpreadMoveTargets(void);
|
||||
bool32 IsPursuitTargetSet(void);
|
||||
void ClearPursuitValuesIfSet(u32 battler);
|
||||
void ClearPursuitValues(void);
|
||||
|
||||
#endif // GUARD_BATTLE_UTIL_H
|
||||
|
||||
@ -734,7 +734,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
if (IsTwoTurnNotSemiInvulnerableMove(battlerAtk, move) && CanTargetFaintAi(battlerDef, battlerAtk))
|
||||
RETURN_SCORE_MINUS(10);
|
||||
|
||||
if (gBattleStruct->commandingDondozo & (1u << battlerDef))
|
||||
if (gBattleStruct->battlerState[battlerDef].commandingDondozo)
|
||||
RETURN_SCORE_MINUS(20);
|
||||
|
||||
// check if negates type
|
||||
|
||||
@ -40,11 +40,11 @@ static void InitializeSwitchinCandidate(struct Pokemon *mon)
|
||||
static bool32 IsAceMon(u32 battler, u32 monPartyId)
|
||||
{
|
||||
if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_ACE_POKEMON
|
||||
&& !(gBattleStruct->forcedSwitch & (1u << battler))
|
||||
&& !gBattleStruct->battlerState[battler].forcedSwitch
|
||||
&& monPartyId == CalculateEnemyPartyCountInSide(battler)-1)
|
||||
return TRUE;
|
||||
if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_DOUBLE_ACE_POKEMON
|
||||
&& !(gBattleStruct->forcedSwitch & (1u << battler))
|
||||
&& !gBattleStruct->battlerState[battler].forcedSwitch
|
||||
&& (monPartyId == CalculateEnemyPartyCount()-1 || monPartyId == CalculateEnemyPartyCount()-2))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
|
||||
@ -430,7 +430,7 @@ bool32 IsDamageMoveUnusable(u32 battlerAtk, u32 battlerDef, u32 move, u32 moveTy
|
||||
if (battlerDef == BATTLE_PARTNER(battlerAtk))
|
||||
battlerDefAbility = aiData->abilities[battlerDef];
|
||||
|
||||
if (gBattleStruct->commandingDondozo & (1u << battlerDef))
|
||||
if (gBattleStruct->battlerState[battlerDef].commandingDondozo)
|
||||
return TRUE;
|
||||
|
||||
if (CanAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[battlerDef]))
|
||||
@ -1511,7 +1511,7 @@ bool32 IsSemiInvulnerable(u32 battlerDef, u32 move)
|
||||
{
|
||||
if (gStatuses3[battlerDef] & STATUS3_PHANTOM_FORCE)
|
||||
return TRUE;
|
||||
else if (gBattleStruct->commandingDondozo & (1u << battlerDef))
|
||||
else if (gBattleStruct->battlerState[battlerDef].commandingDondozo)
|
||||
return TRUE;
|
||||
else if (!MoveDamagesAirborne(move) && gStatuses3[battlerDef] & STATUS3_ON_AIR)
|
||||
return TRUE;
|
||||
|
||||
@ -386,10 +386,9 @@ void BattleArena_AddSkillPoints(u8 battler)
|
||||
|
||||
if (gHitMarker & HITMARKER_OBEYS)
|
||||
{
|
||||
u8 *failedMoveBits = &gBattleStruct->alreadyStatusedMoveAttempt;
|
||||
if (*failedMoveBits & (1u << battler))
|
||||
if (gBattleStruct->battlerState[battler].alreadyStatusedMoveAttempt)
|
||||
{
|
||||
*failedMoveBits &= ~((1u << battler));
|
||||
gBattleStruct->battlerState[battler].alreadyStatusedMoveAttempt = FALSE;
|
||||
skillPoints[battler] -= 2;
|
||||
}
|
||||
else if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)
|
||||
|
||||
@ -2695,6 +2695,17 @@ static void RestoreOverwrittenPixels(u8 *tiles)
|
||||
Free(buffer);
|
||||
}
|
||||
|
||||
static inline bool32 IsAnyAbilityPopUpActive(void)
|
||||
{
|
||||
for (u32 battler = 0; battler < gBattlersCount; battler++)
|
||||
{
|
||||
if (gBattleStruct->battlerState[battler].activeAbilityPopUps)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void CreateAbilityPopUp(u8 battlerId, u32 ability, bool32 isDoubleBattle)
|
||||
{
|
||||
const s16 (*coords)[2];
|
||||
@ -2713,12 +2724,13 @@ void CreateAbilityPopUp(u8 battlerId, u32 ability, bool32 isDoubleBattle)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gBattleStruct->activeAbilityPopUps)
|
||||
if (!IsAnyAbilityPopUpActive())
|
||||
{
|
||||
LoadSpriteSheet(&sSpriteSheet_AbilityPopUp);
|
||||
LoadSpritePalette(&sSpritePalette_AbilityPopUp);
|
||||
}
|
||||
gBattleStruct->activeAbilityPopUps |= 1u << battlerId;
|
||||
|
||||
gBattleStruct->battlerState[battlerId].activeAbilityPopUps = TRUE;
|
||||
battlerPosition = GetBattlerPosition(battlerId);
|
||||
|
||||
if (isDoubleBattle)
|
||||
@ -2809,7 +2821,7 @@ static void SpriteCb_AbilityPopUp(struct Sprite *sprite)
|
||||
||(sprite->tRightToLeft && (sprite->x -= 4) <= sprite->tOriginalX - ABILITY_POP_UP_POS_X_SLIDE)
|
||||
)
|
||||
{
|
||||
gBattleStruct->activeAbilityPopUps &= ~(1u << sprite->tBattlerId);
|
||||
gBattleStruct->battlerState[sprite->tBattlerId].activeAbilityPopUps = FALSE;
|
||||
DestroySprite(sprite);
|
||||
}
|
||||
}
|
||||
@ -2823,7 +2835,7 @@ static void SpriteCb_AbilityPopUp(struct Sprite *sprite)
|
||||
|
||||
void DestroyAbilityPopUp(u8 battlerId)
|
||||
{
|
||||
if (gBattleStruct->activeAbilityPopUps & (1u << battlerId))
|
||||
if (gBattleStruct->battlerState[battlerId].activeAbilityPopUps)
|
||||
{
|
||||
gSprites[gBattleStruct->abilityPopUpSpriteIds[battlerId][0]].tFrames = 0;
|
||||
gSprites[gBattleStruct->abilityPopUpSpriteIds[battlerId][1]].tFrames = 0;
|
||||
@ -2835,7 +2847,7 @@ static void Task_FreeAbilityPopUpGfx(u8 taskId)
|
||||
{
|
||||
if (!gSprites[gTasks[taskId].tSpriteId1].inUse
|
||||
&& !gSprites[gTasks[taskId].tSpriteId2].inUse
|
||||
&& !gBattleStruct->activeAbilityPopUps)
|
||||
&& !IsAnyAbilityPopUpActive())
|
||||
{
|
||||
FreeSpriteTilesByTag(ABILITY_POP_UP_TAG);
|
||||
FreeSpritePaletteByTag(ABILITY_POP_UP_TAG);
|
||||
|
||||
@ -3133,10 +3133,8 @@ static void BattleStartClearSetData(void)
|
||||
|
||||
gBattleStruct->swapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky
|
||||
gBattleStruct->categoryOverride = FALSE; // used for Z-Moves and Max Moves
|
||||
gBattleStruct->pursuitTarget = 0;
|
||||
gBattleStruct->pursuitSwitchByMove = FALSE;
|
||||
gBattleStruct->pursuitStoredSwitch = 0;
|
||||
|
||||
ClearPursuitValues();
|
||||
gSelectedMonPartyId = PARTY_SIZE; // Revival Blessing
|
||||
gCategoryIconSpriteId = 0xFF;
|
||||
|
||||
@ -3243,17 +3241,11 @@ void SwitchInClearSetData(u32 battler)
|
||||
gBattleStruct->lastTakenMoveFrom[battler][1] = 0;
|
||||
gBattleStruct->lastTakenMoveFrom[battler][2] = 0;
|
||||
gBattleStruct->lastTakenMoveFrom[battler][3] = 0;
|
||||
gBattleStruct->lastMoveFailed &= ~(1u << battler);
|
||||
gBattleStruct->battlerState[battler].lastMoveFailed = FALSE;
|
||||
gBattleStruct->palaceFlags &= ~(1u << battler);
|
||||
gBattleStruct->boosterEnergyActivates &= ~(1u << battler);
|
||||
gBattleStruct->canPickupItem &= ~(1u << battler);
|
||||
|
||||
if (gBattleStruct->pursuitTarget & (1u << battler))
|
||||
{
|
||||
gBattleStruct->pursuitTarget = 0;
|
||||
gBattleStruct->pursuitSwitchByMove = FALSE;
|
||||
gBattleStruct->pursuitStoredSwitch = 0;
|
||||
}
|
||||
ClearPursuitValuesIfSet(battler);
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(gSideTimers); i++)
|
||||
{
|
||||
@ -3278,7 +3270,7 @@ void SwitchInClearSetData(u32 battler)
|
||||
// Reset damage to prevent things like red card activating if the switched-in mon is holding it
|
||||
gSpecialStatuses[battler].physicalDmg = 0;
|
||||
gSpecialStatuses[battler].specialDmg = 0;
|
||||
gBattleStruct->enduredDamage &= ~(1u << battler);
|
||||
gSpecialStatuses[battler].enduredDamage = FALSE;
|
||||
|
||||
// Reset Eject Button / Eject Pack switch detection
|
||||
AI_DATA->ejectButtonSwitch = FALSE;
|
||||
@ -3383,16 +3375,9 @@ const u8* FaintClearSetData(u32 battler)
|
||||
gBattleStruct->lastTakenMoveFrom[battler][1] = 0;
|
||||
gBattleStruct->lastTakenMoveFrom[battler][2] = 0;
|
||||
gBattleStruct->lastTakenMoveFrom[battler][3] = 0;
|
||||
|
||||
if (gBattleStruct->pursuitTarget & (1u << battler))
|
||||
{
|
||||
gBattleStruct->pursuitTarget = 0;
|
||||
gBattleStruct->pursuitSwitchByMove = FALSE;
|
||||
gBattleStruct->pursuitStoredSwitch = 0;
|
||||
}
|
||||
|
||||
gBattleStruct->palaceFlags &= ~(1u << battler);
|
||||
gBattleStruct->boosterEnergyActivates &= ~(1u << battler);
|
||||
|
||||
ClearPursuitValuesIfSet(battler);
|
||||
|
||||
if (gBattleStruct->commanderActive[battler] != SPECIES_NONE)
|
||||
{
|
||||
@ -3953,10 +3938,10 @@ static void TryDoEventsBeforeFirstTurn(void)
|
||||
*(gBattleStruct->monToSwitchIntoId + i) = PARTY_SIZE;
|
||||
gChosenActionByBattler[i] = B_ACTION_NONE;
|
||||
gChosenMoveByBattler[i] = MOVE_NONE;
|
||||
gBattleStruct->battlerState[i].absentBattlerFlags = gAbsentBattlerFlags & (1u << i);
|
||||
}
|
||||
TurnValuesCleanUp(FALSE);
|
||||
SpecialStatusesClear();
|
||||
*(&gBattleStruct->absentBattlerFlags) = gAbsentBattlerFlags;
|
||||
BattlePutTextOnWindow(gText_EmptyString3, B_WIN_MSG);
|
||||
AssignUsableGimmicks();
|
||||
gBattleMainFunc = HandleTurnActionSelectionState;
|
||||
@ -4070,12 +4055,12 @@ void BattleTurnPassed(void)
|
||||
{
|
||||
gChosenActionByBattler[i] = B_ACTION_NONE;
|
||||
gChosenMoveByBattler[i] = MOVE_NONE;
|
||||
gBattleStruct->battlerState[i].absentBattlerFlags = gAbsentBattlerFlags & (1u << i);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
|
||||
*(gBattleStruct->monToSwitchIntoId + i) = PARTY_SIZE;
|
||||
|
||||
*(&gBattleStruct->absentBattlerFlags) = gAbsentBattlerFlags;
|
||||
BattlePutTextOnWindow(gText_EmptyString3, B_WIN_MSG);
|
||||
AssignUsableGimmicks();
|
||||
SetShellSideArmCategory();
|
||||
@ -4259,10 +4244,10 @@ static void HandleTurnActionSelectionState(void)
|
||||
*(gBattleStruct->monToSwitchIntoId + battler) = PARTY_SIZE;
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_MULTI
|
||||
|| (position & BIT_FLANK) == B_FLANK_LEFT
|
||||
|| gBattleStruct->absentBattlerFlags & (1u << GetBattlerAtPosition(BATTLE_PARTNER(position)))
|
||||
|| gBattleStruct->battlerState[GetBattlerAtPosition(BATTLE_PARTNER(position))].absentBattlerFlags
|
||||
|| gBattleCommunication[GetBattlerAtPosition(BATTLE_PARTNER(position))] == STATE_WAIT_ACTION_CONFIRMED)
|
||||
{
|
||||
if ((gBattleStruct->absentBattlerFlags & (1u << battler)) || (gBattleStruct->commandingDondozo & (1u << battler)))
|
||||
if (gBattleStruct->battlerState[battler].absentBattlerFlags || gBattleStruct->battlerState[battler].commandingDondozo)
|
||||
{
|
||||
gChosenActionByBattler[battler] = B_ACTION_NOTHING_FAINTED;
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI))
|
||||
@ -4637,7 +4622,7 @@ static void HandleTurnActionSelectionState(void)
|
||||
|
||||
if (((gBattleTypeFlags & BATTLE_TYPE_MULTI) || !IsDoubleBattle())
|
||||
|| (position & BIT_FLANK) != B_FLANK_LEFT
|
||||
|| (*(&gBattleStruct->absentBattlerFlags) & (1u << GetBattlerAtPosition(BATTLE_PARTNER(position)))))
|
||||
|| gBattleStruct->battlerState[GetBattlerAtPosition(BATTLE_PARTNER(position))].absentBattlerFlags)
|
||||
{
|
||||
BtlController_EmitLinkStandbyMsg(battler, BUFFER_A, LINK_STANDBY_MSG_STOP_BOUNCE, i);
|
||||
}
|
||||
@ -4803,9 +4788,9 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, u32 holdEffect)
|
||||
speed *= 2;
|
||||
else if (ability == ABILITY_SLOW_START && gDisableStructs[battler].slowStartTimer != 0)
|
||||
speed /= 2;
|
||||
else if (ability == ABILITY_PROTOSYNTHESIS && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && ((gBattleWeather & B_WEATHER_SUN && WEATHER_HAS_EFFECT) || gBattleStruct->boosterEnergyActivates & (1u << battler)))
|
||||
else if (ability == ABILITY_PROTOSYNTHESIS && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && ((gBattleWeather & B_WEATHER_SUN && WEATHER_HAS_EFFECT) || gDisableStructs[battler].boosterEnergyActivates))
|
||||
speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed;
|
||||
else if (ability == ABILITY_QUARK_DRIVE && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gBattleStruct->boosterEnergyActivates & (1u << battler)))
|
||||
else if (ability == ABILITY_QUARK_DRIVE && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battler].boosterEnergyActivates))
|
||||
speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed;
|
||||
|
||||
// stat stages
|
||||
@ -5186,9 +5171,10 @@ static void TurnValuesCleanUp(bool8 var0)
|
||||
gBattleMons[i].status2 &= ~STATUS2_SUBSTITUTE;
|
||||
|
||||
if (!(gStatuses3[i] & STATUS3_COMMANDER))
|
||||
gBattleStruct->commandingDondozo &= ~(1u << i);
|
||||
gBattleStruct->battlerState[i].commandingDondozo = FALSE;
|
||||
|
||||
gSpecialStatuses[i].parentalBondState = PARENTAL_BOND_OFF;
|
||||
gBattleStruct->battlerState[i].usedEjectItem = FALSE;
|
||||
}
|
||||
|
||||
gSideStatuses[B_SIDE_PLAYER] &= ~(SIDE_STATUS_QUICK_GUARD | SIDE_STATUS_WIDE_GUARD | SIDE_STATUS_CRAFTY_SHIELD | SIDE_STATUS_MAT_BLOCK);
|
||||
@ -5196,11 +5182,8 @@ static void TurnValuesCleanUp(bool8 var0)
|
||||
gSideTimers[B_SIDE_PLAYER].followmeTimer = 0;
|
||||
gSideTimers[B_SIDE_OPPONENT].followmeTimer = 0;
|
||||
|
||||
gBattleStruct->usedEjectItem = 0;
|
||||
gBattleStruct->pursuitTarget = 0;
|
||||
gBattleStruct->pursuitSwitchByMove = FALSE;
|
||||
gBattleStruct->pursuitStoredSwitch = 0;
|
||||
gBattleStruct->pledgeMove = FALSE; // combined pledge move may not have been used due to a canceller
|
||||
ClearPursuitValues();
|
||||
ClearDamageCalcResults();
|
||||
}
|
||||
|
||||
@ -5264,12 +5247,12 @@ static bool32 TryDoMoveEffectsBeforeMoves(void)
|
||||
SortBattlersBySpeed(battlers, FALSE);
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (!(gBattleStruct->focusPunchBattlers & (1u << battlers[i]))
|
||||
if (!gBattleStruct->battlerState[battlers[i]].focusPunchBattlers
|
||||
&& !(gBattleMons[battlers[i]].status1 & STATUS1_SLEEP)
|
||||
&& !(gDisableStructs[battlers[i]].truantCounter)
|
||||
&& !(gProtectStructs[battlers[i]].noValidMoves))
|
||||
{
|
||||
gBattleStruct->focusPunchBattlers |= 1u << battlers[i];
|
||||
gBattleStruct->battlerState[battlers[i]].focusPunchBattlers = TRUE;
|
||||
gBattlerAttacker = battlers[i];
|
||||
switch (GetMoveEffect(gChosenMoveByBattler[gBattlerAttacker]))
|
||||
{
|
||||
@ -5390,9 +5373,9 @@ static void CheckChangingTurnOrderEffects(void)
|
||||
gCurrentActionFuncId = gActionsByTurnOrder[0];
|
||||
gBattleStruct->dynamicMoveType = 0;
|
||||
gBattleStruct->effectsBeforeUsingMoveDone = FALSE;
|
||||
gBattleStruct->focusPunchBattlers = 0;
|
||||
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
|
||||
{
|
||||
gBattleStruct->battlerState[i].focusPunchBattlers = FALSE;
|
||||
gBattleStruct->ateBoost[i] = FALSE;
|
||||
gSpecialStatuses[i].gemBoost = FALSE;
|
||||
}
|
||||
@ -5412,7 +5395,7 @@ static void RunTurnActionsFunctions(void)
|
||||
// Mega Evolve / Focus Punch-like moves after switching, items, running, but before using a move.
|
||||
if (gCurrentActionFuncId == B_ACTION_USE_MOVE && !gBattleStruct->effectsBeforeUsingMoveDone)
|
||||
{
|
||||
if (!gBattleStruct->pursuitTarget)
|
||||
if (!IsPursuitTargetSet())
|
||||
{
|
||||
if (TryDoGimmicksBeforeMoves())
|
||||
return;
|
||||
@ -5690,7 +5673,7 @@ static void FreeResetData_ReturnToOvOrDoEvolutions(void)
|
||||
IncrementDexNavChain();
|
||||
else
|
||||
gSaveBlock3Ptr->dexNavChain = 0;
|
||||
|
||||
|
||||
gDexNavBattle = FALSE;
|
||||
ResetSpriteData();
|
||||
if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK
|
||||
|
||||
@ -1166,9 +1166,9 @@ static void Cmd_attackcanceler(void)
|
||||
|
||||
s32 i;
|
||||
|
||||
if (gBattleStruct->usedEjectItem & (1u << gBattlerAttacker))
|
||||
if (gBattleStruct->battlerState[gBattlerAttacker].usedEjectItem)
|
||||
{
|
||||
gBattleStruct->usedEjectItem = 0;
|
||||
gBattleStruct->battlerState[gBattlerAttacker].usedEjectItem = FALSE;
|
||||
gCurrentActionFuncId = B_ACTION_TRY_FINISH;
|
||||
return;
|
||||
}
|
||||
@ -1432,7 +1432,7 @@ static bool32 AccuracyCalcHelper(u32 move, u32 battler)
|
||||
{
|
||||
effect = TRUE;
|
||||
}
|
||||
else if (gBattleStruct->pursuitTarget & (1u << battler))
|
||||
else if (gBattleStruct->battlerState[battler].pursuitTarget)
|
||||
{
|
||||
effect = TRUE;
|
||||
}
|
||||
@ -1581,7 +1581,7 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u
|
||||
break;
|
||||
}
|
||||
|
||||
if (gBattleStruct->usedMicleBerry & 1u << battlerAtk)
|
||||
if (gBattleStruct->battlerState[battlerAtk].usedMicleBerry)
|
||||
{
|
||||
if (atkAbility == ABILITY_RIPEN)
|
||||
calc = (calc * 140) / 100; // ripen gives 40% acc boost
|
||||
@ -2128,7 +2128,7 @@ static void Cmd_adjustdamage(void)
|
||||
|
||||
if (DoesDisguiseBlockMove(battlerDef, gCurrentMove))
|
||||
{
|
||||
gBattleStruct->enduredDamage |= 1u << battlerDef;
|
||||
gSpecialStatuses[battlerDef].enduredDamage = TRUE;
|
||||
continue;
|
||||
}
|
||||
if (GetBattlerAbility(battlerDef) == ABILITY_ICE_FACE && IsBattleMovePhysical(gCurrentMove) && gBattleMons[battlerDef].species == SPECIES_EISCUE)
|
||||
@ -2182,7 +2182,7 @@ static void Cmd_adjustdamage(void)
|
||||
|
||||
// Handle reducing the dmg to 1 hp.
|
||||
gBattleStruct->moveDamage[battlerDef] = gBattleMons[battlerDef].hp - 1;
|
||||
gBattleStruct->enduredDamage |= 1u << battlerDef;
|
||||
gSpecialStatuses[battlerDef].enduredDamage = TRUE;
|
||||
|
||||
if (gProtectStructs[battlerDef].endured)
|
||||
{
|
||||
@ -3209,7 +3209,7 @@ void SetMoveEffect(bool32 primary, bool32 certain)
|
||||
|
||||
if (i != gBattlersCount)
|
||||
break;
|
||||
if (!CanBeSlept(gEffectBattler, GetBattlerAbility(gEffectBattler), BLOCKED_BY_SLEEP_CLAUSE) && !(gBattleStruct->sleepClauseEffectExempt & (1u << gEffectBattler)))
|
||||
if (!CanBeSlept(gEffectBattler, GetBattlerAbility(gEffectBattler), BLOCKED_BY_SLEEP_CLAUSE) && !gBattleStruct->battlerState[gEffectBattler].sleepClauseEffectExempt)
|
||||
break;
|
||||
|
||||
cancelMultiTurnMovesResult = CancelMultiTurnMoves(gEffectBattler);
|
||||
@ -5895,7 +5895,7 @@ static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent)
|
||||
if (battler != gBattlerAttacker
|
||||
&& !(excludeCurrent && battler == gBattlerTarget)
|
||||
&& IsBattlerAlive(battler)
|
||||
&& !(gBattleStruct->targetsDone[gBattlerAttacker] & (1u << battler))
|
||||
&& !gBattleStruct->battlerState[gBattlerAttacker].targetsDone[battler]
|
||||
&& (GetBattlerSide(battler) != GetBattlerSide(gBattlerAttacker) || moveTarget == MOVE_TARGET_FOES_AND_ALLY))
|
||||
break;
|
||||
}
|
||||
@ -6396,9 +6396,9 @@ static void Cmd_moveend(void)
|
||||
if ((gBattleStruct->moveResultFlags[gBattlerTarget] & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE))
|
||||
|| (gBattleMons[gBattlerAttacker].status2 & (STATUS2_FLINCHED))
|
||||
|| gProtectStructs[gBattlerAttacker].prlzImmobility)
|
||||
gBattleStruct->lastMoveFailed |= 1u << gBattlerAttacker;
|
||||
gBattleStruct->battlerState[gBattlerAttacker].lastMoveFailed = TRUE;
|
||||
else
|
||||
gBattleStruct->lastMoveFailed &= ~(1u << gBattlerAttacker);
|
||||
gBattleStruct->battlerState[gBattlerAttacker].lastMoveFailed = FALSE;
|
||||
|
||||
// Set ShellTrap to activate after the attacker's turn if target was hit by a physical move.
|
||||
if (GetMoveEffect(gChosenMoveByBattler[gBattlerTarget]) == EFFECT_SHELL_TRAP
|
||||
@ -6436,7 +6436,7 @@ static void Cmd_moveend(void)
|
||||
}
|
||||
u32 originalEffect = GetMoveEffect(originallyUsedMove);
|
||||
if (!(gAbsentBattlerFlags & (1u << gBattlerAttacker))
|
||||
&& !(gBattleStruct->absentBattlerFlags & (1u << gBattlerAttacker))
|
||||
&& !gBattleStruct->battlerState[gBattlerAttacker].absentBattlerFlags
|
||||
&& originalEffect != EFFECT_BATON_PASS && originalEffect != EFFECT_HEALING_WISH)
|
||||
{
|
||||
if (gHitMarker & HITMARKER_OBEYS)
|
||||
@ -6480,7 +6480,7 @@ static void Cmd_moveend(void)
|
||||
break;
|
||||
case MOVEEND_MIRROR_MOVE: // mirror move
|
||||
if (!(gAbsentBattlerFlags & (1u << gBattlerAttacker))
|
||||
&& !(gBattleStruct->absentBattlerFlags & (1u << gBattlerAttacker))
|
||||
&& !gBattleStruct->battlerState[gBattlerAttacker].absentBattlerFlags
|
||||
&& !IsMoveMirrorMoveBanned(originallyUsedMove)
|
||||
&& gHitMarker & HITMARKER_OBEYS
|
||||
&& gBattlerAttacker != gBattlerTarget
|
||||
@ -6500,7 +6500,7 @@ static void Cmd_moveend(void)
|
||||
&& MoveResultHasEffect(gBattlerTarget))
|
||||
gProtectStructs[gBattlerAttacker].targetAffected = TRUE;
|
||||
|
||||
gBattleStruct->targetsDone[gBattlerAttacker] |= 1u << gBattlerTarget;
|
||||
gBattleStruct->battlerState[gBattlerAttacker].targetsDone[gBattlerTarget] = TRUE;
|
||||
if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
&& IsDoubleBattle()
|
||||
&& !gProtectStructs[gBattlerAttacker].chargingTurn
|
||||
@ -6531,9 +6531,9 @@ static void Cmd_moveend(void)
|
||||
u8 originalBounceTarget = gBattlerAttacker;
|
||||
gBattleStruct->bouncedMoveIsUsed = FALSE;
|
||||
gBattlerAttacker = gBattleStruct->attackerBeforeBounce;
|
||||
gBattleStruct->targetsDone[gBattlerAttacker] |= 1u << originalBounceTarget;
|
||||
gBattleStruct->targetsDone[originalBounceTarget] = 0;
|
||||
|
||||
gBattleStruct->battlerState[gBattlerAttacker].targetsDone[originalBounceTarget] = TRUE;
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
gBattleStruct->battlerState[originalBounceTarget].targetsDone[i] = FALSE;
|
||||
nextTarget = GetNextTarget(moveTarget, FALSE);
|
||||
if (nextTarget != MAX_BATTLERS_COUNT)
|
||||
{
|
||||
@ -6703,7 +6703,7 @@ static void Cmd_moveend(void)
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEnd; // Prevent user switch-in selection
|
||||
effect = TRUE;
|
||||
BattleScriptPushCursor();
|
||||
gBattleStruct->usedEjectItem |= 1u << battler;
|
||||
gBattleStruct->battlerState[battler].usedEjectItem = TRUE;
|
||||
if (ejectButtonBattlers & (1u << battler))
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_EjectButtonActivates;
|
||||
@ -6972,7 +6972,6 @@ static void Cmd_moveend(void)
|
||||
DebugPrintfLevel(MGBA_LOG_WARN, "savedTargetCount is greater than 0! More calls to SaveBattlerTarget than RestoreBattlerTarget!");
|
||||
// #endif
|
||||
}
|
||||
gBattleStruct->targetsDone[gBattlerAttacker] = 0;
|
||||
gProtectStructs[gBattlerAttacker].targetAffected = FALSE;
|
||||
gProtectStructs[gBattlerAttacker].shellTrap = FALSE;
|
||||
gBattleStruct->ateBoost[gBattlerAttacker] = FALSE;
|
||||
@ -6988,12 +6987,11 @@ static void Cmd_moveend(void)
|
||||
gBattleStruct->categoryOverride = FALSE;
|
||||
gBattleStruct->bouncedMoveIsUsed = FALSE;
|
||||
gBattleStruct->snatchedMoveIsUsed = FALSE;
|
||||
gBattleStruct->enduredDamage = 0;
|
||||
gBattleStruct->additionalEffectsCounter = 0;
|
||||
gBattleStruct->poisonPuppeteerConfusion = FALSE;
|
||||
gBattleStruct->fickleBeamBoosted = FALSE;
|
||||
gBattleStruct->redCardActivates = FALSE;
|
||||
gBattleStruct->usedMicleBerry &= ~(1u << gBattlerAttacker);
|
||||
gBattleStruct->battlerState[gBattlerAttacker].usedMicleBerry = FALSE;
|
||||
if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
gBattleStruct->pledgeMove = FALSE;
|
||||
if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE)
|
||||
@ -7005,6 +7003,8 @@ static void Cmd_moveend(void)
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
gBattleStruct->battlerState[gBattlerAttacker].targetsDone[i] = FALSE;
|
||||
|
||||
if (gBattleStruct->commanderActive[i] != SPECIES_NONE && !IsBattlerAlive(i))
|
||||
{
|
||||
u32 partner = BATTLE_PARTNER(i);
|
||||
@ -7017,7 +7017,7 @@ static void Cmd_moveend(void)
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_PURSUIT_NEXT_ACTION:
|
||||
if (gBattleStruct->pursuitTarget & (1u << gBattlerTarget))
|
||||
if (gBattleStruct->battlerState[gBattlerTarget].pursuitTarget)
|
||||
{
|
||||
u32 storedTarget = gBattlerTarget;
|
||||
if (SetTargetToNextPursuiter(gBattlerTarget))
|
||||
@ -7034,9 +7034,7 @@ static void Cmd_moveend(void)
|
||||
else
|
||||
gBattlescriptCurrInstr = BattleScript_DoSwitchOut;
|
||||
*(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = gBattleStruct->pursuitStoredSwitch;
|
||||
gBattleStruct->pursuitTarget = 0;
|
||||
gBattleStruct->pursuitSwitchByMove = FALSE;
|
||||
gBattleStruct->pursuitStoredSwitch = 0;
|
||||
ClearPursuitValues();
|
||||
effect = TRUE;
|
||||
}
|
||||
}
|
||||
@ -7719,20 +7717,20 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler)
|
||||
}
|
||||
// Healing Wish activates before hazards.
|
||||
// Starting from Gen8 - it heals only pokemon which can be healed. In gens 5,6,7 the effect activates anyways.
|
||||
else if (((gBattleStruct->storedHealingWish & (1u << battler)) || (gBattleStruct->storedLunarDance & (1u << battler)))
|
||||
else if ((gBattleStruct->battlerState[battler].storedHealingWish || gBattleStruct->battlerState[battler].storedLunarDance)
|
||||
&& (gBattleMons[battler].hp != gBattleMons[battler].maxHP || gBattleMons[battler].status1 != 0 || B_HEALING_WISH_SWITCH < GEN_8))
|
||||
{
|
||||
if (gBattleStruct->storedHealingWish & (1u << battler))
|
||||
if (gBattleStruct->battlerState[battler].storedHealingWish)
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_HealingWishActivates;
|
||||
gBattleStruct->storedHealingWish &= ~(1u << battler);
|
||||
gBattleStruct->battlerState[battler].storedHealingWish = FALSE;
|
||||
}
|
||||
else // Lunar Dance
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_LunarDanceActivates;
|
||||
gBattleStruct->storedLunarDance &= ~(1u << battler);
|
||||
gBattleStruct->battlerState[battler].storedLunarDance = FALSE;
|
||||
}
|
||||
}
|
||||
else if (!(gDisableStructs[battler].spikesDone)
|
||||
@ -7881,7 +7879,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler)
|
||||
gBattleStruct->hpOnSwitchout[GetBattlerSide(i)] = gBattleMons[i].hp;
|
||||
}
|
||||
|
||||
gBattleStruct->forcedSwitch &= ~(1u << battler);
|
||||
gBattleStruct->battlerState[battler].forcedSwitch = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -7897,7 +7895,7 @@ static void Cmd_switchineffects(void)
|
||||
{
|
||||
// Multiple mons fainted and are being switched-in. Their abilities/hazards will play according to speed ties.
|
||||
case BS_FAINTED_MULTIPLE_1: // Saves the battlers.
|
||||
gBattleStruct->multipleSwitchInBattlers |= 1 << battler;
|
||||
gBattleStruct->battlerState[battler].multipleSwitchInBattlers = TRUE;
|
||||
UpdateSentMonFlags(battler);
|
||||
|
||||
// Increment fainted battler.
|
||||
@ -7926,14 +7924,16 @@ static void Cmd_switchineffects(void)
|
||||
for (; gBattleStruct->multipleSwitchInCursor < gBattlersCount; gBattleStruct->multipleSwitchInCursor++)
|
||||
{
|
||||
gBattlerFainted = gBattleStruct->multipleSwitchInSortedBattlers[gBattleStruct->multipleSwitchInCursor];
|
||||
if (gBattleStruct->multipleSwitchInBattlers & (1 << (gBattlerFainted)))
|
||||
if (gBattleStruct->battlerState[gBattlerFainted].multipleSwitchInBattlers)
|
||||
{
|
||||
if (DoSwitchInEffectsForBattler(gBattlerFainted))
|
||||
return;
|
||||
}
|
||||
}
|
||||
// All battlers done, end
|
||||
gBattleStruct->multipleSwitchInBattlers = 0;
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
gBattleStruct->battlerState[i].multipleSwitchInBattlers = FALSE;
|
||||
|
||||
gBattleStruct->multipleSwitchInState = 0;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
@ -10048,7 +10048,7 @@ static void Cmd_various(void)
|
||||
case VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT:
|
||||
{
|
||||
VARIOUS_ARGS();
|
||||
gBattleStruct->alreadyStatusedMoveAttempt |= 1u << battler;
|
||||
gBattleStruct->battlerState[battler].alreadyStatusedMoveAttempt = TRUE;
|
||||
break;
|
||||
}
|
||||
case VARIOUS_PALACE_TRY_ESCAPE_STATUS:
|
||||
@ -12486,7 +12486,7 @@ static void Cmd_forcerandomswitch(void)
|
||||
{
|
||||
*(gBattleStruct->battlerPartyIndexes + gBattlerTarget) = gBattlerPartyIndexes[gBattlerTarget];
|
||||
gBattlescriptCurrInstr = BattleScript_RoarSuccessSwitch;
|
||||
gBattleStruct->forcedSwitch |= 1u << gBattlerTarget;
|
||||
gBattleStruct->battlerState[gBattlerTarget].forcedSwitch = TRUE;
|
||||
*(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = validMons[RandomUniform(RNG_FORCE_RANDOM_SWITCH, 0, validMonsCount - 1)];
|
||||
|
||||
if (!IsMultiBattle())
|
||||
@ -14021,7 +14021,7 @@ static void Cmd_jumpifnopursuitswitchdmg(void)
|
||||
if (SetTargetToNextPursuiter(gBattlerAttacker))
|
||||
{
|
||||
ChangeOrderTargetAfterAttacker();
|
||||
gBattleStruct->pursuitTarget = 1u << gBattlerAttacker;
|
||||
gBattleStruct->battlerState[gBattlerAttacker].pursuitTarget = TRUE;
|
||||
gBattleStruct->pursuitSwitchByMove = gActionsByTurnOrder[gCurrentTurnActionNumber] == B_ACTION_USE_MOVE;
|
||||
gBattleStruct->pursuitStoredSwitch = gBattleStruct->monToSwitchIntoId[gBattlerAttacker];
|
||||
*(gBattleStruct->moveTarget + gBattlerTarget) = gBattlerAttacker;
|
||||
@ -17619,11 +17619,11 @@ void BS_JumpIfSleepClause(void)
|
||||
// Can freely sleep own partner
|
||||
if (IsDoubleBattle() && IsSleepClauseEnabled() && GetBattlerSide(gBattlerAttacker) == GetBattlerSide(gBattlerTarget))
|
||||
{
|
||||
gBattleStruct->sleepClauseEffectExempt |= (1u << gBattlerTarget);
|
||||
gBattleStruct->battlerState[gBattlerTarget].sleepClauseEffectExempt = TRUE;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
return;
|
||||
}
|
||||
gBattleStruct->sleepClauseEffectExempt &= ~(1u << gBattlerTarget);
|
||||
gBattleStruct->battlerState[gBattlerTarget].sleepClauseEffectExempt = FALSE;
|
||||
// Can't sleep if clause is active otherwise
|
||||
if (IsSleepClauseActiveForSide(GetBattlerSide(gBattlerTarget)))
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
@ -17795,9 +17795,9 @@ void BS_StoreHealingWish(void)
|
||||
|
||||
u32 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
if (gCurrentMove == MOVE_LUNAR_DANCE)
|
||||
gBattleStruct->storedLunarDance |= 1u << battler;
|
||||
gBattleStruct->battlerState[battler].storedLunarDance = TRUE;
|
||||
else
|
||||
gBattleStruct->storedHealingWish |= 1u << battler;
|
||||
gBattleStruct->battlerState[battler].storedHealingWish = TRUE;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
|
||||
@ -223,7 +223,7 @@ bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move)
|
||||
|| ability == ABILITY_PROPELLER_TAIL || ability == ABILITY_STALWART)
|
||||
return FALSE;
|
||||
|
||||
if (effect == EFFECT_PURSUIT && gBattleStruct->pursuitTarget)
|
||||
if (effect == EFFECT_PURSUIT && IsPursuitTargetSet())
|
||||
return FALSE;
|
||||
|
||||
if (gSideTimers[defSide].followmePowder && !IsAffectedByPowder(battlerAtk, ability, GetBattlerHoldEffect(battlerAtk, TRUE)))
|
||||
@ -239,8 +239,8 @@ void HandleAction_UseMove(void)
|
||||
u16 moveTarget;
|
||||
|
||||
gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
|
||||
if (gBattleStruct->absentBattlerFlags & (1u << gBattlerAttacker)
|
||||
|| gBattleStruct->commandingDondozo & (1u << gBattlerAttacker)
|
||||
if (gBattleStruct->battlerState[gBattlerAttacker].absentBattlerFlags
|
||||
|| gBattleStruct->battlerState[gBattlerAttacker].commandingDondozo
|
||||
|| !IsBattlerAlive(gBattlerAttacker))
|
||||
{
|
||||
gCurrentActionFuncId = B_ACTION_FINISHED;
|
||||
@ -334,7 +334,7 @@ void HandleAction_UseMove(void)
|
||||
}
|
||||
else if (IsDoubleBattle()
|
||||
&& gSideTimers[side].followmeTimer == 0
|
||||
&& !(gBattleStruct->pursuitTarget & (1u << *(gBattleStruct->moveTarget + gBattlerAttacker)))
|
||||
&& !gBattleStruct->battlerState[*(gBattleStruct->moveTarget + gBattlerAttacker)].pursuitTarget
|
||||
&& (!IsBattleMoveStatus(gCurrentMove) || (moveTarget != MOVE_TARGET_USER && moveTarget != MOVE_TARGET_ALL_BATTLERS))
|
||||
&& ((GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC)
|
||||
|| (GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_STORM_DRAIN && moveType == TYPE_WATER)))
|
||||
@ -815,7 +815,7 @@ void HandleAction_ActionFinished(void)
|
||||
gBattleScripting.multihitMoveEffect = 0;
|
||||
gBattleResources->battleScriptsStack->size = 0;
|
||||
|
||||
if (B_RECALC_TURN_AFTER_ACTIONS >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove && !gBattleStruct->pursuitTarget)
|
||||
if (B_RECALC_TURN_AFTER_ACTIONS >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove && !IsPursuitTargetSet())
|
||||
{
|
||||
// i starts at `gCurrentTurnActionNumber` because we don't want to recalculate turn order for mon that have already
|
||||
// taken action. It's been previously increased, which we want in order to not recalculate the turn of the mon that just finished its action
|
||||
@ -3280,7 +3280,7 @@ static void CancellerObedience(u32 *effect)
|
||||
break;
|
||||
case DISOBEYS_FALL_ASLEEP:
|
||||
if (IsSleepClauseEnabled())
|
||||
gBattleStruct->sleepClauseEffectExempt |= (1u << gBattlerAttacker);
|
||||
gBattleStruct->battlerState[gBattlerAttacker].sleepClauseEffectExempt = TRUE;
|
||||
gBattlescriptCurrInstr = BattleScript_IgnoresAndFallsAsleep;
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED;
|
||||
break;
|
||||
@ -5244,7 +5244,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
SaveBattlerAttacker(gBattlerAttacker);
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
gBattlerAttacker = partner;
|
||||
gBattleStruct->commandingDondozo |= 1u << battler;
|
||||
gBattleStruct->battlerState[battler].commandingDondozo = TRUE;
|
||||
gBattleStruct->commanderActive[partner] = gBattleMons[battler].species;
|
||||
gStatuses3[battler] |= STATUS3_COMMANDER;
|
||||
if (gBattleMons[battler].status2 & STATUS2_CONFUSION
|
||||
@ -5930,7 +5930,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker))
|
||||
{
|
||||
if (IsSleepClauseEnabled())
|
||||
gBattleStruct->sleepClauseEffectExempt |= (1u << gBattlerAttacker);
|
||||
gBattleStruct->battlerState[gBattlerAttacker].sleepClauseEffectExempt = TRUE;
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_SLEEP;
|
||||
PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility);
|
||||
BattleScriptPushCursor();
|
||||
@ -6556,7 +6556,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (!gDisableStructs[battler].weatherAbilityDone
|
||||
&& (gBattleWeather & B_WEATHER_SUN) && WEATHER_HAS_EFFECT
|
||||
&& !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)
|
||||
&& !(gBattleStruct->boosterEnergyActivates & (1u << battler)))
|
||||
&& !gDisableStructs[battler].boosterEnergyActivates)
|
||||
{
|
||||
gDisableStructs[battler].weatherAbilityDone = TRUE;
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler));
|
||||
@ -6585,7 +6585,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (!gDisableStructs[battler].terrainAbilityDone
|
||||
&& gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN
|
||||
&& !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)
|
||||
&& !(gBattleStruct->boosterEnergyActivates & (1u << battler)))
|
||||
&& !gDisableStructs[battler].boosterEnergyActivates)
|
||||
{
|
||||
gDisableStructs[battler].terrainAbilityDone = TRUE;
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler));
|
||||
@ -7046,7 +7046,7 @@ static u32 TrySetMicleBerry(u32 battler, u32 itemId, enum ItemEffect caseID)
|
||||
{
|
||||
if (HasEnoughHpToEatBerry(battler, 4, itemId))
|
||||
{
|
||||
gBattleStruct->usedMicleBerry |= 1u << battler;
|
||||
gBattleStruct->battlerState[battler].usedMicleBerry = TRUE;
|
||||
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL)
|
||||
{
|
||||
BattleScriptExecute(BattleScript_MicleBerryActivateEnd2);
|
||||
@ -7305,7 +7305,7 @@ static u32 TryConsumeMirrorHerb(u32 battler, enum ItemEffect caseID)
|
||||
|
||||
static inline u32 TryBoosterEnergy(u32 battler, enum ItemEffect caseID)
|
||||
{
|
||||
if (gBattleStruct->boosterEnergyActivates & (1u << battler) || gBattleMons[battler].status2 & STATUS2_TRANSFORMED)
|
||||
if (gDisableStructs[battler].boosterEnergyActivates || gBattleMons[battler].status2 & STATUS2_TRANSFORMED)
|
||||
return ITEM_NO_EFFECT;
|
||||
|
||||
if (((GetBattlerAbility(battler) == ABILITY_PROTOSYNTHESIS) && !((gBattleWeather & B_WEATHER_SUN) && WEATHER_HAS_EFFECT))
|
||||
@ -7313,7 +7313,7 @@ static inline u32 TryBoosterEnergy(u32 battler, enum ItemEffect caseID)
|
||||
{
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler));
|
||||
gBattlerAbility = gBattleScripting.battler = battler;
|
||||
gBattleStruct->boosterEnergyActivates |= 1u << battler;
|
||||
gDisableStructs[battler].boosterEnergyActivates = TRUE;
|
||||
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL)
|
||||
{
|
||||
BattleScriptExecute(BattleScript_BoosterEnergyEnd2);
|
||||
@ -9133,7 +9133,7 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData
|
||||
basePower *= 2;
|
||||
break;
|
||||
case EFFECT_PURSUIT:
|
||||
if (gBattleStruct->pursuitTarget & (1u << battlerDef))
|
||||
if (gBattleStruct->battlerState[battlerDef].pursuitTarget)
|
||||
basePower *= 2;
|
||||
break;
|
||||
case EFFECT_NATURAL_GIFT:
|
||||
@ -9362,7 +9362,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageCalculationData *
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(0.5));
|
||||
break;
|
||||
case EFFECT_STOMPING_TANTRUM:
|
||||
if (gBattleStruct->lastMoveFailed & (1u << battlerAtk))
|
||||
if (gBattleStruct->battlerState[battlerAtk].lastMoveFailed)
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(2.0));
|
||||
break;
|
||||
case EFFECT_MAGNITUDE:
|
||||
@ -9550,7 +9550,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageCalculationData *
|
||||
case ABILITY_PROTOSYNTHESIS:
|
||||
{
|
||||
u8 defHighestStat = GetHighestStatId(battlerDef);
|
||||
if (((weather & B_WEATHER_SUN && WEATHER_HAS_EFFECT) || gBattleStruct->boosterEnergyActivates & (1u << battlerDef))
|
||||
if (((weather & B_WEATHER_SUN && WEATHER_HAS_EFFECT) || gDisableStructs[battlerDef].boosterEnergyActivates)
|
||||
&& ((IsBattleMovePhysical(move) && defHighestStat == STAT_DEF) || (IsBattleMoveSpecial(move) && defHighestStat == STAT_SPDEF))
|
||||
&& !(gBattleMons[battlerDef].status2 & STATUS2_TRANSFORMED))
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(0.7));
|
||||
@ -9559,7 +9559,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageCalculationData *
|
||||
case ABILITY_QUARK_DRIVE:
|
||||
{
|
||||
u8 defHighestStat = GetHighestStatId(battlerDef);
|
||||
if ((gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gBattleStruct->boosterEnergyActivates & (1u << battlerDef))
|
||||
if ((gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battlerDef].boosterEnergyActivates)
|
||||
&& ((IsBattleMovePhysical(move) && defHighestStat == STAT_DEF) || (IsBattleMoveSpecial(move) && defHighestStat == STAT_SPDEF))
|
||||
&& !(gBattleMons[battlerDef].status2 & STATUS2_TRANSFORMED))
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(0.7));
|
||||
@ -9829,7 +9829,7 @@ static inline u32 CalcAttackStat(struct DamageCalculationData *damageCalcData, u
|
||||
if (!(gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED))
|
||||
{
|
||||
u32 atkHighestStat = GetHighestStatId(battlerAtk);
|
||||
if (((weather & B_WEATHER_SUN) && WEATHER_HAS_EFFECT) || gBattleStruct->boosterEnergyActivates & (1u << battlerAtk))
|
||||
if (((weather & B_WEATHER_SUN) && WEATHER_HAS_EFFECT) || gDisableStructs[battlerAtk].boosterEnergyActivates)
|
||||
{
|
||||
if ((IsBattleMovePhysical(move) && atkHighestStat == STAT_ATK) || (IsBattleMoveSpecial(move) && atkHighestStat == STAT_SPATK))
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(1.3));
|
||||
@ -9840,7 +9840,7 @@ static inline u32 CalcAttackStat(struct DamageCalculationData *damageCalcData, u
|
||||
if (!(gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED))
|
||||
{
|
||||
u32 atkHighestStat = GetHighestStatId(battlerAtk);
|
||||
if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gBattleStruct->boosterEnergyActivates & (1u << battlerAtk))
|
||||
if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battlerAtk].boosterEnergyActivates)
|
||||
{
|
||||
if ((IsBattleMovePhysical(move) && atkHighestStat == STAT_ATK) || (IsBattleMoveSpecial(move) && atkHighestStat == STAT_SPATK))
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(1.3));
|
||||
@ -12147,9 +12147,9 @@ u32 GetBattleMoveType(u32 move)
|
||||
|
||||
void TryActivateSleepClause(u32 battler, u32 indexInParty)
|
||||
{
|
||||
if (gBattleStruct->sleepClauseEffectExempt & (1u << battler))
|
||||
if (gBattleStruct->battlerState[battler].sleepClauseEffectExempt)
|
||||
{
|
||||
gBattleStruct->sleepClauseEffectExempt &= ~(1u << battler);
|
||||
gBattleStruct->battlerState[battler].sleepClauseEffectExempt = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -12205,7 +12205,7 @@ bool32 DoesDestinyBondFail(u32 battler)
|
||||
{
|
||||
if (B_DESTINY_BOND_FAIL >= GEN_7
|
||||
&& GetMoveEffect(gLastResultingMoves[battler]) == EFFECT_DESTINY_BOND
|
||||
&& !(gBattleStruct->lastMoveFailed & (1u << battler)))
|
||||
&& !gBattleStruct->battlerState[battler].lastMoveFailed)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
@ -12243,3 +12243,27 @@ u32 NumAffectedSpreadMoveTargets(void)
|
||||
|
||||
return targetCount;
|
||||
}
|
||||
|
||||
bool32 IsPursuitTargetSet(void)
|
||||
{
|
||||
for (u32 battler = 0; battler < gBattlersCount; battler++)
|
||||
{
|
||||
if (gBattleStruct->battlerState[battler].pursuitTarget)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void ClearPursuitValues(void)
|
||||
{
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
gBattleStruct->battlerState[i].pursuitTarget = FALSE;
|
||||
gBattleStruct->pursuitSwitchByMove = FALSE;
|
||||
gBattleStruct->pursuitStoredSwitch = 0;
|
||||
}
|
||||
|
||||
void ClearPursuitValuesIfSet(u32 battler)
|
||||
{
|
||||
if (gBattleStruct->battlerState[battler].pursuitTarget)
|
||||
ClearPursuitValues();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user