mirror of
https://github.com/pret/pokefirered.git
synced 2026-05-23 06:06:12 -05:00
fixed bug with type3 not being intialized leading to wrong type calculations
removed unused functions
This commit is contained in:
parent
15e04f6f97
commit
963be8c077
|
|
@ -94,5 +94,8 @@ s8 GetChosenMovePriority(u32 battlerId);
|
|||
u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, u32 holdEffect);
|
||||
u32 GetBattlerTotalSpeedStat(u32 battler);
|
||||
void SpecialStatusesClear(void);
|
||||
s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, u32 ability1, u32 ability2,
|
||||
u32 holdEffectBattler1, u32 holdEffectBattler2, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2);
|
||||
s32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves);
|
||||
|
||||
#endif // GUARD_BATTLE_MAIN_H
|
||||
|
|
|
|||
|
|
@ -668,7 +668,6 @@ void SetMonMoveSlot(struct Pokemon *mon, u16 move, u8 slot);
|
|||
void SetBattleMonMoveSlot(struct BattlePokemon *mon, u16 move, u8 slot);
|
||||
u16 MonTryLearningNewMove(struct Pokemon *mon, bool8 firstMove);
|
||||
void DeleteFirstMoveAndGiveMoveToMon(struct Pokemon *mon, u16 move);
|
||||
s32 CalculateBaseDamageOld(struct BattlePokemon *attacker, struct BattlePokemon *defender, u32 move, u32 sideStatus, u16 powerOverride, u8 typeOverride, u8 battlerIdAtk, u8 battlerIdDef);
|
||||
u32 GetMonAffectionHearts(struct Pokemon *pokemon);
|
||||
u8 CountAliveMonsInBattle(u8 caseId, u32 battler);
|
||||
|
||||
|
|
|
|||
|
|
@ -1102,7 +1102,7 @@ static void Cmd_if_not_equal_(void) // Same as if_not_equal.
|
|||
|
||||
static void Cmd_if_would_go_first(void)
|
||||
{
|
||||
if (GetWhoStrikesFirst(gBattlerAttacker, gBattlerTarget, TRUE) == sAIScriptPtr[1])
|
||||
if ((GetWhichBattlerFaster(gBattlerAttacker, gBattlerTarget, TRUE) == 1) == sAIScriptPtr[1])
|
||||
sAIScriptPtr = T1_READ_PTR(sAIScriptPtr + 2);
|
||||
else
|
||||
sAIScriptPtr += 6;
|
||||
|
|
@ -1110,7 +1110,7 @@ static void Cmd_if_would_go_first(void)
|
|||
|
||||
static void Cmd_if_would_not_go_first(void)
|
||||
{
|
||||
if (GetWhoStrikesFirst(gBattlerAttacker, gBattlerTarget, TRUE) != sAIScriptPtr[1])
|
||||
if ((GetWhichBattlerFaster(gBattlerAttacker, gBattlerTarget, TRUE) == 1) != sAIScriptPtr[1])
|
||||
sAIScriptPtr = T1_READ_PTR(sAIScriptPtr + 2);
|
||||
else
|
||||
sAIScriptPtr += 6;
|
||||
|
|
|
|||
|
|
@ -2692,6 +2692,7 @@ static void BattleIntroDrawTrainersOrMonsSprites(void)
|
|||
|
||||
gBattleMons[gActiveBattler].type1 = gSpeciesInfo[gBattleMons[gActiveBattler].species].types[0];
|
||||
gBattleMons[gActiveBattler].type2 = gSpeciesInfo[gBattleMons[gActiveBattler].species].types[1];
|
||||
gBattleMons[gActiveBattler].type3 = TYPE_MYSTERY;
|
||||
gBattleMons[gActiveBattler].ability = GetAbilityBySpecies(gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].abilityNum);
|
||||
hpOnSwitchout = &gBattleStruct->hpOnSwitchout[GetBattlerSide(gActiveBattler)];
|
||||
*hpOnSwitchout = gBattleMons[gActiveBattler].hp;
|
||||
|
|
@ -2900,13 +2901,6 @@ static void BattleIntroRecordMonsToDex(void)
|
|||
}
|
||||
}
|
||||
|
||||
// not used
|
||||
static void Unused_AutoProgressToIntro(void)
|
||||
{
|
||||
if (gBattleControllerExecFlags == 0)
|
||||
gBattleMainFunc = BattleIntroPrintPlayerSendsOut;
|
||||
}
|
||||
|
||||
static void BattleIntroPrintPlayerSendsOut(void)
|
||||
{
|
||||
if (gBattleControllerExecFlags == 0)
|
||||
|
|
@ -2944,28 +2938,6 @@ static void BattleIntroPlayerSendsOutMonAnimation(void)
|
|||
gBattleMainFunc = TryDoEventsBeforeFirstTurn;
|
||||
}
|
||||
|
||||
// Unused
|
||||
static void BattleIntroSwitchInPlayerMons(void)
|
||||
{
|
||||
if (gBattleControllerExecFlags == 0)
|
||||
{
|
||||
for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++)
|
||||
{
|
||||
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
|
||||
{
|
||||
BtlController_EmitSwitchInAnim(BUFFER_A, gBattlerPartyIndexes[gActiveBattler], FALSE);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
}
|
||||
}
|
||||
|
||||
gBattleStruct->switchInAbilitiesCounter = 0;
|
||||
gBattleStruct->switchInItemsCounter = 0;
|
||||
gBattleStruct->overworldWeatherDone = FALSE;
|
||||
|
||||
gBattleMainFunc = TryDoEventsBeforeFirstTurn;
|
||||
}
|
||||
}
|
||||
|
||||
static void TryDoEventsBeforeFirstTurn(void)
|
||||
{
|
||||
s32 i, j;
|
||||
|
|
@ -2980,7 +2952,7 @@ static void TryDoEventsBeforeFirstTurn(void)
|
|||
gBattlerByTurnOrder[i] = i;
|
||||
for (i = 0; i < gBattlersCount - 1; i++)
|
||||
for (j = i + 1; j < gBattlersCount; j++)
|
||||
if (GetWhoStrikesFirst(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], TRUE) != 0)
|
||||
if ((GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], TRUE) == 1) != 0)
|
||||
SwapTurnOrder(i, j);
|
||||
}
|
||||
if (!gBattleStruct->overworldWeatherDone
|
||||
|
|
@ -3504,138 +3476,95 @@ void SwapTurnOrder(u8 id1, u8 id2)
|
|||
SWAP(gBattlerByTurnOrder[id1], gBattlerByTurnOrder[id2], temp);
|
||||
}
|
||||
|
||||
u8 GetWhoStrikesFirst(u8 battler1, u8 battler2, bool8 ignoreChosenMoves)
|
||||
// Function for AI with variables provided as arguments to speed the computation time
|
||||
s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, u32 ability1, u32 ability2,
|
||||
u32 holdEffectBattler1, u32 holdEffectBattler2, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2)
|
||||
{
|
||||
u8 strikesFirst = 0;
|
||||
u8 speedMultiplierBattler1 = 0, speedMultiplierBattler2 = 0;
|
||||
u32 speedBattler1 = 0, speedBattler2 = 0;
|
||||
u8 holdEffect = 0;
|
||||
u8 holdEffectParam = 0;
|
||||
u16 moveBattler1 = 0, moveBattler2 = 0;
|
||||
u32 strikesFirst = 0;
|
||||
|
||||
if (WEATHER_HAS_EFFECT)
|
||||
if (priority1 == priority2)
|
||||
{
|
||||
if ((gBattleMons[battler1].ability == ABILITY_SWIFT_SWIM && gBattleWeather & B_WEATHER_RAIN)
|
||||
|| (gBattleMons[battler1].ability == ABILITY_CHLOROPHYLL && gBattleWeather & B_WEATHER_SUN))
|
||||
speedMultiplierBattler1 = 2;
|
||||
else
|
||||
speedMultiplierBattler1 = 1;
|
||||
if ((gBattleMons[battler2].ability == ABILITY_SWIFT_SWIM && gBattleWeather & B_WEATHER_RAIN)
|
||||
|| (gBattleMons[battler2].ability == ABILITY_CHLOROPHYLL && gBattleWeather & B_WEATHER_SUN))
|
||||
speedMultiplierBattler2 = 2;
|
||||
else
|
||||
speedMultiplierBattler2 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
speedMultiplierBattler1 = 1;
|
||||
speedMultiplierBattler2 = 1;
|
||||
}
|
||||
// QUICK CLAW / CUSTAP - always first
|
||||
// LAGGING TAIL - always last
|
||||
// STALL - always last
|
||||
|
||||
speedBattler1 = (gBattleMons[battler1].speed * speedMultiplierBattler1)
|
||||
* (gStatStageRatios[gBattleMons[battler1].statStages[STAT_SPEED]][0])
|
||||
/ (gStatStageRatios[gBattleMons[battler1].statStages[STAT_SPEED]][1]);
|
||||
|
||||
if (gBattleMons[battler1].item == ITEM_ENIGMA_BERRY)
|
||||
{
|
||||
holdEffect = gEnigmaBerries[battler1].holdEffect;
|
||||
holdEffectParam = gEnigmaBerries[battler1].holdEffectParam;
|
||||
}
|
||||
else
|
||||
{
|
||||
holdEffect = ItemId_GetHoldEffect(gBattleMons[battler1].item);
|
||||
holdEffectParam = ItemId_GetHoldEffectParam(gBattleMons[battler1].item);
|
||||
}
|
||||
// badge boost
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_LINK)
|
||||
&& FlagGet(FLAG_BADGE03_GET)
|
||||
&& GetBattlerSide(battler1) == B_SIDE_PLAYER)
|
||||
speedBattler1 = (speedBattler1 * 110) / 100;
|
||||
if (holdEffect == HOLD_EFFECT_MACHO_BRACE)
|
||||
speedBattler1 /= 2;
|
||||
if (gBattleMons[battler1].status1 & STATUS1_PARALYSIS)
|
||||
speedBattler1 /= 4;
|
||||
if (holdEffect == HOLD_EFFECT_QUICK_CLAW && gRandomTurnNumber < (0xFFFF * holdEffectParam) / 100)
|
||||
speedBattler1 = UINT_MAX;
|
||||
// check second battlerId's speed
|
||||
speedBattler2 = (gBattleMons[battler2].speed * speedMultiplierBattler2)
|
||||
* (gStatStageRatios[gBattleMons[battler2].statStages[STAT_SPEED]][0])
|
||||
/ (gStatStageRatios[gBattleMons[battler2].statStages[STAT_SPEED]][1]);
|
||||
if (gBattleMons[battler2].item == ITEM_ENIGMA_BERRY)
|
||||
{
|
||||
holdEffect = gEnigmaBerries[battler2].holdEffect;
|
||||
holdEffectParam = gEnigmaBerries[battler2].holdEffectParam;
|
||||
}
|
||||
else
|
||||
{
|
||||
holdEffect = ItemId_GetHoldEffect(gBattleMons[battler2].item);
|
||||
holdEffectParam = ItemId_GetHoldEffectParam(gBattleMons[battler2].item);
|
||||
}
|
||||
// badge boost
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_LINK)
|
||||
&& FlagGet(FLAG_BADGE03_GET)
|
||||
&& GetBattlerSide(battler2) == B_SIDE_PLAYER)
|
||||
speedBattler2 = (speedBattler2 * 110) / 100;
|
||||
if (holdEffect == HOLD_EFFECT_MACHO_BRACE)
|
||||
speedBattler2 /= 2;
|
||||
if (gBattleMons[battler2].status1 & STATUS1_PARALYSIS)
|
||||
speedBattler2 /= 4;
|
||||
if (holdEffect == HOLD_EFFECT_QUICK_CLAW && gRandomTurnNumber < (0xFFFF * holdEffectParam) / 100)
|
||||
speedBattler2 = UINT_MAX;
|
||||
if (ignoreChosenMoves)
|
||||
{
|
||||
moveBattler1 = MOVE_NONE;
|
||||
moveBattler2 = MOVE_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gChosenActionByBattler[battler1] == B_ACTION_USE_MOVE)
|
||||
{
|
||||
if (gProtectStructs[battler1].noValidMoves)
|
||||
moveBattler1 = MOVE_STRUGGLE;
|
||||
else
|
||||
moveBattler1 = gBattleMons[battler1].moves[*(gBattleStruct->chosenMovePositions + battler1)];
|
||||
}
|
||||
if (gProtectStructs[battler1].quickDraw && !gProtectStructs[battler2].quickDraw)
|
||||
strikesFirst = 1;
|
||||
else if (!gProtectStructs[battler1].quickDraw && gProtectStructs[battler2].quickDraw)
|
||||
strikesFirst = -1;
|
||||
else if (gProtectStructs[battler1].usedCustapBerry && !gProtectStructs[battler2].usedCustapBerry)
|
||||
strikesFirst = 1;
|
||||
else if (gProtectStructs[battler2].usedCustapBerry && !gProtectStructs[battler1].usedCustapBerry)
|
||||
strikesFirst = -1;
|
||||
else if (holdEffectBattler1 == HOLD_EFFECT_LAGGING_TAIL && holdEffectBattler2 != HOLD_EFFECT_LAGGING_TAIL)
|
||||
strikesFirst = -1;
|
||||
else if (holdEffectBattler2 == HOLD_EFFECT_LAGGING_TAIL && holdEffectBattler1 != HOLD_EFFECT_LAGGING_TAIL)
|
||||
strikesFirst = 1;
|
||||
else if (ability1 == ABILITY_STALL && ability2 != ABILITY_STALL)
|
||||
strikesFirst = -1;
|
||||
else if (ability2 == ABILITY_STALL && ability1 != ABILITY_STALL)
|
||||
strikesFirst = 1;
|
||||
else if (ability1 == ABILITY_MYCELIUM_MIGHT && ability2 != ABILITY_MYCELIUM_MIGHT && IS_MOVE_STATUS(gChosenMoveByBattler[battler1]))
|
||||
strikesFirst = -1;
|
||||
else if (ability2 == ABILITY_MYCELIUM_MIGHT && ability1 != ABILITY_MYCELIUM_MIGHT && IS_MOVE_STATUS(gChosenMoveByBattler[battler2]))
|
||||
strikesFirst = 1;
|
||||
else
|
||||
moveBattler1 = MOVE_NONE;
|
||||
if (gChosenActionByBattler[battler2] == B_ACTION_USE_MOVE)
|
||||
{
|
||||
if (gProtectStructs[battler2].noValidMoves)
|
||||
moveBattler2 = MOVE_STRUGGLE;
|
||||
else
|
||||
moveBattler2 = gBattleMons[battler2].moves[*(gBattleStruct->chosenMovePositions + battler2)];
|
||||
}
|
||||
else
|
||||
moveBattler2 = MOVE_NONE;
|
||||
}
|
||||
// both move priorities are different than 0
|
||||
if (gMovesInfo[moveBattler1].priority != 0 || gMovesInfo[moveBattler2].priority != 0)
|
||||
{
|
||||
// both priorities are the same
|
||||
if (gMovesInfo[moveBattler1].priority == gMovesInfo[moveBattler2].priority)
|
||||
{
|
||||
if (speedBattler1 == speedBattler2 && Random() & 1)
|
||||
strikesFirst = 2; // same speeds, same priorities
|
||||
{
|
||||
strikesFirst = 0; // same speeds, same priorities
|
||||
}
|
||||
else if (speedBattler1 < speedBattler2)
|
||||
strikesFirst = 1; // battler2 has more speed
|
||||
// else battler1 has more speed
|
||||
{
|
||||
// battler2 has more speed
|
||||
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM)
|
||||
strikesFirst = 1;
|
||||
else
|
||||
strikesFirst = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// battler1 has more speed
|
||||
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM)
|
||||
strikesFirst = -1;
|
||||
else
|
||||
strikesFirst = 1;
|
||||
}
|
||||
}
|
||||
else if (gMovesInfo[moveBattler1].priority < gMovesInfo[moveBattler2].priority)
|
||||
strikesFirst = 1; // battler2's move has greater priority
|
||||
// else battler1's move has greater priority
|
||||
}
|
||||
// both priorities are equal to 0
|
||||
else if (priority1 < priority2)
|
||||
{
|
||||
strikesFirst = -1; // battler2's move has greater priority
|
||||
}
|
||||
else
|
||||
{
|
||||
if (speedBattler1 == speedBattler2 && Random() & 1)
|
||||
strikesFirst = 2; // same speeds, same priorities
|
||||
else if (speedBattler1 < speedBattler2)
|
||||
strikesFirst = 1; // battler2 has more speed
|
||||
// else battler1 has more speed
|
||||
strikesFirst = 1; // battler1's move has greater priority
|
||||
}
|
||||
return strikesFirst;
|
||||
}
|
||||
|
||||
s32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves)
|
||||
{
|
||||
s32 priority1 = 0, priority2 = 0;
|
||||
u32 ability1 = GetBattlerAbility(battler1);
|
||||
u32 speedBattler1 = GetBattlerTotalSpeedStat(battler1);
|
||||
u32 holdEffectBattler1 = GetBattlerHoldEffect(battler1, TRUE);
|
||||
u32 speedBattler2 = GetBattlerTotalSpeedStat(battler2);
|
||||
u32 holdEffectBattler2 = GetBattlerHoldEffect(battler2, TRUE);
|
||||
u32 ability2 = GetBattlerAbility(battler2);
|
||||
|
||||
if (!ignoreChosenMoves)
|
||||
{
|
||||
if (gChosenActionByBattler[battler1] == B_ACTION_USE_MOVE)
|
||||
priority1 = GetChosenMovePriority(battler1);
|
||||
if (gChosenActionByBattler[battler2] == B_ACTION_USE_MOVE)
|
||||
priority2 = GetChosenMovePriority(battler2);
|
||||
}
|
||||
|
||||
return GetWhichBattlerFasterArgs(battler1, battler2, ignoreChosenMoves, ability1, ability2,
|
||||
holdEffectBattler1, holdEffectBattler2, speedBattler1, speedBattler2, priority1, priority2);
|
||||
}
|
||||
|
||||
static void SetActionsAndBattlersTurnOrder(void)
|
||||
{
|
||||
s32 turnOrderId = 0;
|
||||
|
|
@ -3717,7 +3646,7 @@ static void SetActionsAndBattlersTurnOrder(void)
|
|||
&& gActionsByTurnOrder[j] != B_ACTION_USE_ITEM
|
||||
&& gActionsByTurnOrder[i] != B_ACTION_SWITCH
|
||||
&& gActionsByTurnOrder[j] != B_ACTION_SWITCH)
|
||||
if (GetWhoStrikesFirst(battler1, battler2, FALSE))
|
||||
if (GetWhichBattlerFaster(battler1, battler2, FALSE) == 1)
|
||||
SwapTurnOrder(i, j);
|
||||
}
|
||||
}
|
||||
|
|
@ -4613,15 +4542,18 @@ static void HandleAction_NothingIsFainted(void)
|
|||
|
||||
static void HandleAction_ActionFinished(void)
|
||||
{
|
||||
++gCurrentTurnActionNumber;
|
||||
u32 i, j;
|
||||
bool32 afterYouActive = gSpecialStatuses[gBattlerByTurnOrder[gCurrentTurnActionNumber + 1]].afterYou;
|
||||
*(gBattleStruct->monToSwitchIntoId + gBattlerByTurnOrder[gCurrentTurnActionNumber]) = gSelectedMonPartyId = PARTY_SIZE;
|
||||
gCurrentTurnActionNumber++;
|
||||
gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber];
|
||||
SpecialStatusesClear();
|
||||
gHitMarker &= ~(HITMARKER_DESTINYBOND | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_ATTACKSTRING_PRINTED
|
||||
| HITMARKER_NO_PPDEDUCT | HITMARKER_STATUS_ABILITY_EFFECT | HITMARKER_IGNORE_ON_AIR
|
||||
| HITMARKER_IGNORE_UNDERGROUND | HITMARKER_IGNORE_UNDERWATER | HITMARKER_PASSIVE_DAMAGE
|
||||
| HITMARKER_NO_PPDEDUCT | HITMARKER_STATUS_ABILITY_EFFECT | HITMARKER_PASSIVE_DAMAGE
|
||||
| HITMARKER_OBEYS | HITMARKER_WAKE_UP_CLEAR | HITMARKER_SYNCHRONISE_EFFECT
|
||||
| HITMARKER_CHARGING | HITMARKER_NEVER_SET);
|
||||
gCurrentMove = MOVE_NONE;
|
||||
| HITMARKER_CHARGING | HITMARKER_NEVER_SET | HITMARKER_IGNORE_DISGUISE);
|
||||
|
||||
gCurrentMove = 0;
|
||||
gBattleMoveDamage = 0;
|
||||
gMoveResultFlags = 0;
|
||||
gBattleScripting.animTurn = 0;
|
||||
|
|
@ -4629,12 +4561,43 @@ static void HandleAction_ActionFinished(void)
|
|||
gLastLandedMoves[gBattlerAttacker] = 0;
|
||||
gLastHitByType[gBattlerAttacker] = 0;
|
||||
gBattleStruct->dynamicMoveType = 0;
|
||||
gDynamicBasePower = 0;
|
||||
gBattleScripting.moveendState = 0;
|
||||
gBattleCommunication[MOVE_EFFECT_BYTE] = 0;
|
||||
gBattleCommunication[ACTIONS_CONFIRMED_COUNT] = 0;
|
||||
gBattleCommunication[3] = 0;
|
||||
gBattleCommunication[4] = 0;
|
||||
gBattleScripting.multihitMoveEffect = 0;
|
||||
gBattleResources->battleScriptsStack->size = 0;
|
||||
gBattleStruct->dynamax.usingMaxMove[gBattlerAttacker] = 0;
|
||||
|
||||
if (B_RECALC_TURN_AFTER_ACTIONS >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove)
|
||||
{
|
||||
// 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
|
||||
for (i = gCurrentTurnActionNumber; i < gBattlersCount - 1; i++)
|
||||
{
|
||||
for (j = i + 1; j < gBattlersCount; j++)
|
||||
{
|
||||
u32 battler1 = gBattlerByTurnOrder[i];
|
||||
u32 battler2 = gBattlerByTurnOrder[j];
|
||||
|
||||
if (gProtectStructs[battler1].quash || gProtectStructs[battler2].quash
|
||||
|| gProtectStructs[battler1].shellTrap || gProtectStructs[battler2].shellTrap)
|
||||
continue;
|
||||
|
||||
// We recalculate order only for action of the same priority. If any action other than switch/move has been taken, they should
|
||||
// have been executed before. The only recalculation needed is for moves/switch. Mega evolution is handled in src/battle_main.c/TryChangeOrder
|
||||
if((gActionsByTurnOrder[i] == B_ACTION_USE_MOVE && gActionsByTurnOrder[j] == B_ACTION_USE_MOVE))
|
||||
{
|
||||
if (GetWhichBattlerFaster(battler1, battler2, FALSE) == -1)
|
||||
SwapTurnOrder(i, j);
|
||||
}
|
||||
else if ((gActionsByTurnOrder[i] == B_ACTION_SWITCH && gActionsByTurnOrder[j] == B_ACTION_SWITCH))
|
||||
{
|
||||
if (GetWhichBattlerFaster(battler1, battler2, TRUE) == -1) // If the actions chosen are switching, we recalc order but ignoring the moves
|
||||
SwapTurnOrder(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s8 GetMovePriority(u32 battler, u16 move)
|
||||
|
|
|
|||
|
|
@ -321,7 +321,6 @@ static const u16 sWhiteOutBadgeMoney[9] = { 8, 16, 24, 36, 48, 64, 80, 100, 120
|
|||
|
||||
static void TrySetDestinyBondToHappen(void);
|
||||
static u8 AttacksThisTurn(u8 battlerId, u16 move); // Note: returns 1 if it's a charging turn, otherwise 2.
|
||||
static void CheckWonderGuardAndLevitate(void);
|
||||
static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr);
|
||||
static void InitLevelUpBanner(void);
|
||||
static bool8 SlideInLevelUpBanner(void);
|
||||
|
|
@ -1977,16 +1976,14 @@ static void Cmd_damagecalc(void)
|
|||
void AI_CalcDmg(u8 attacker, u8 defender)
|
||||
{
|
||||
u32 sideStatus = gSideStatuses[GET_BATTLER_SIDE(defender)];
|
||||
gBattleMoveDamage = CalculateBaseDamageOld(&gBattleMons[attacker], &gBattleMons[defender], gCurrentMove,
|
||||
sideStatus, gDynamicBasePower,
|
||||
gBattleStruct->dynamicMoveType, attacker, defender);
|
||||
gDynamicBasePower = 0;
|
||||
gBattleMoveDamage = gBattleMoveDamage * gCritMultiplier * gBattleScripting.dmgMultiplier;
|
||||
u8 moveType;
|
||||
s32 critChance;
|
||||
|
||||
if (gStatuses3[attacker] & STATUS3_CHARGED_UP && gMovesInfo[gCurrentMove].type == TYPE_ELECTRIC)
|
||||
gBattleMoveDamage *= 2;
|
||||
if (gProtectStructs[attacker].helpingHand)
|
||||
gBattleMoveDamage = gBattleMoveDamage * 15 / 10;
|
||||
GET_MOVE_TYPE(gCurrentMove, moveType);
|
||||
critChance = CalcCritChanceStage(attacker, defender, gCurrentMove, TRUE);
|
||||
gIsCriticalHit = RandomWeighted(RNG_CRITICAL_HIT, sCriticalHitChance[critChance] - 1, 1);
|
||||
gBattleMoveDamage = CalculateMoveDamage(gCurrentMove, attacker, defender, moveType, 0, gIsCriticalHit, TRUE, TRUE);
|
||||
CalcTypeEffectivenessMultiplier(gCurrentMove, moveType, gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget), TRUE);
|
||||
}
|
||||
|
||||
static void ModulateDmgByType(u8 multiplier)
|
||||
|
|
@ -2035,81 +2032,6 @@ static void Cmd_typecalc(void)
|
|||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
static void CheckWonderGuardAndLevitate(void)
|
||||
{
|
||||
u8 flags = 0;
|
||||
s32 i = 0;
|
||||
u8 moveType;
|
||||
|
||||
if (gCurrentMove == MOVE_STRUGGLE || !gMovesInfo[gCurrentMove].power)
|
||||
return;
|
||||
|
||||
GET_MOVE_TYPE(gCurrentMove, moveType);
|
||||
|
||||
if (gBattleMons[gBattlerTarget].ability == ABILITY_LEVITATE && moveType == TYPE_GROUND)
|
||||
{
|
||||
gLastUsedAbility = ABILITY_LEVITATE;
|
||||
gBattleCommunication[MISS_TYPE] = B_MSG_GROUND_MISS;
|
||||
RecordAbilityBattle(gBattlerTarget, ABILITY_LEVITATE);
|
||||
return;
|
||||
}
|
||||
|
||||
while (TYPE_EFFECT_ATK_TYPE(i) != TYPE_ENDTABLE)
|
||||
{
|
||||
if (TYPE_EFFECT_ATK_TYPE(i) == TYPE_FORESIGHT)
|
||||
{
|
||||
if (gBattleMons[gBattlerTarget].status2 & STATUS2_FORESIGHT)
|
||||
break;
|
||||
i += 3;
|
||||
continue;
|
||||
}
|
||||
if (TYPE_EFFECT_ATK_TYPE(i) == moveType)
|
||||
{
|
||||
// check no effect
|
||||
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBattlerTarget].type1
|
||||
&& TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_NO_EFFECT)
|
||||
{
|
||||
gMoveResultFlags |= MOVE_RESULT_DOESNT_AFFECT_FOE;
|
||||
gProtectStructs[gBattlerAttacker].targetNotAffected = 1;
|
||||
}
|
||||
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBattlerTarget].type2 &&
|
||||
gBattleMons[gBattlerTarget].type1 != gBattleMons[gBattlerTarget].type2 &&
|
||||
TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_NO_EFFECT)
|
||||
{
|
||||
gMoveResultFlags |= MOVE_RESULT_DOESNT_AFFECT_FOE;
|
||||
gProtectStructs[gBattlerAttacker].targetNotAffected = 1;
|
||||
}
|
||||
|
||||
// check super effective
|
||||
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBattlerTarget].type1 && TYPE_EFFECT_MULTIPLIER(i) == 20)
|
||||
flags |= 1;
|
||||
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBattlerTarget].type2
|
||||
&& gBattleMons[gBattlerTarget].type1 != gBattleMons[gBattlerTarget].type2
|
||||
&& TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_SUPER_EFFECTIVE)
|
||||
flags |= 1;
|
||||
|
||||
// check not very effective
|
||||
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBattlerTarget].type1 && TYPE_EFFECT_MULTIPLIER(i) == 5)
|
||||
flags |= 2;
|
||||
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBattlerTarget].type2
|
||||
&& gBattleMons[gBattlerTarget].type1 != gBattleMons[gBattlerTarget].type2
|
||||
&& TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_NOT_EFFECTIVE)
|
||||
flags |= 2;
|
||||
}
|
||||
i += 3;
|
||||
}
|
||||
|
||||
if (gBattleMons[gBattlerTarget].ability == ABILITY_WONDER_GUARD && AttacksThisTurn(gBattlerAttacker, gCurrentMove) == 2)
|
||||
{
|
||||
if (((flags & 2) || !(flags & 1)) && gMovesInfo[gCurrentMove].power)
|
||||
{
|
||||
gLastUsedAbility = ABILITY_WONDER_GUARD;
|
||||
gBattleCommunication[MISS_TYPE] = B_MSG_AVOIDED_DMG;
|
||||
RecordAbilityBattle(gBattlerTarget, ABILITY_WONDER_GUARD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Same as ModulateDmgByType except different arguments
|
||||
static void ModulateDmgByType2(u8 multiplier, u16 move, u8 *flags)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -34,14 +34,6 @@
|
|||
#define BATTLE_HISTORY (gBattleResources->battleHistory)
|
||||
|
||||
|
||||
#define SOUND_MOVES_END 0xFFFF
|
||||
|
||||
static const u16 sSoundMovesTable[] =
|
||||
{
|
||||
MOVE_GROWL, MOVE_ROAR, MOVE_SING, MOVE_SUPERSONIC, MOVE_SCREECH, MOVE_SNORE,
|
||||
MOVE_UPROAR, MOVE_METAL_SOUND, MOVE_GRASS_WHISTLE, MOVE_HYPER_VOICE, SOUND_MOVES_END
|
||||
};
|
||||
|
||||
static bool32 TryRemoveScreens(u32 battler);
|
||||
static bool32 IsUnnerveAbilityOnOpposingSide(u32 battler);
|
||||
static u32 GetFlingPowerFromItemId(u32 itemId);
|
||||
|
|
@ -542,7 +534,7 @@ u8 DoFieldEndTurnEffects(void)
|
|||
s32 j;
|
||||
for (j = i + 1; j < gBattlersCount; j++)
|
||||
{
|
||||
if (GetWhoStrikesFirst(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], FALSE))
|
||||
if (GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], FALSE) == 1)
|
||||
SwapTurnOrder(i, j);
|
||||
}
|
||||
}
|
||||
|
|
@ -8387,6 +8379,7 @@ static inline void MulByTypeEffectiveness(uq4_12_t *modifier, u32 move, u32 move
|
|||
{
|
||||
uq4_12_t mod = GetTypeModifier(moveType, defType);
|
||||
u32 abilityAtk = GetBattlerAbility(battlerAtk);
|
||||
DebugPrintfLevel(MGBA_LOG_ERROR, "MulByTypeEffectiveness: mod = %d, moveType=%d, defType=%d", mod, moveType, defType);
|
||||
|
||||
if (mod == UQ_4_12(0.0) && GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_RING_TARGET)
|
||||
{
|
||||
|
|
@ -8591,12 +8584,18 @@ u8 GetBattlerType(u32 battler, u8 typeIndex)
|
|||
if (gBattleResources->flags->flags[battler] & RESOURCE_FLAG_ROOST)
|
||||
{
|
||||
if (types[0] == TYPE_FLYING && types[1] == TYPE_FLYING)
|
||||
{
|
||||
DebugPrintfLevel(MGBA_LOG_ERROR, "GetBattlerType: roost1, typeIndex=%d, type=%d", typeIndex, B_ROOST_PURE_FLYING >= GEN_5 ? TYPE_NORMAL : TYPE_MYSTERY);
|
||||
return B_ROOST_PURE_FLYING >= GEN_5 ? TYPE_NORMAL : TYPE_MYSTERY;
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugPrintfLevel(MGBA_LOG_ERROR, "GetBattlerType: roost1, typeIndex=%d, type=%d", typeIndex, types[typeIndex] == TYPE_FLYING ? TYPE_MYSTERY : types[typeIndex]);
|
||||
return types[typeIndex] == TYPE_FLYING ? TYPE_MYSTERY : types[typeIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DebugPrintfLevel(MGBA_LOG_ERROR, "GetBattlerType: typeIndex=%d, type=%d", typeIndex, types[typeIndex]);
|
||||
return types[typeIndex];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8273,17 +8273,17 @@
|
|||
{
|
||||
"min_level": 3,
|
||||
"max_level": 3,
|
||||
"species": "SPECIES_CASTFORM"
|
||||
"species": "SPECIES_MIMIKYU"
|
||||
},
|
||||
{
|
||||
"min_level": 3,
|
||||
"max_level": 3,
|
||||
"species": "SPECIES_CASTFORM"
|
||||
"species": "SPECIES_MIMIKYU"
|
||||
},
|
||||
{
|
||||
"min_level": 2,
|
||||
"max_level": 2,
|
||||
"species": "SPECIES_CASTFORM"
|
||||
"species": "SPECIES_MIMIKYU"
|
||||
},
|
||||
{
|
||||
"min_level": 2,
|
||||
|
|
|
|||
277
src/pokemon.c
277
src/pokemon.c
|
|
@ -1803,283 +1803,6 @@ static void DeleteFirstMoveAndGiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 mo
|
|||
SetBoxMonData(boxMon, MON_DATA_PP_BONUSES, &ppBonuses);
|
||||
}
|
||||
|
||||
#define APPLY_STAT_MOD(var, mon, stat, statIndex) \
|
||||
{ \
|
||||
(var) = (stat) * (gStatStageRatios)[(mon)->statStages[(statIndex)]][0]; \
|
||||
(var) /= (gStatStageRatios)[(mon)->statStages[(statIndex)]][1]; \
|
||||
}
|
||||
|
||||
// Own function in pokeemerald
|
||||
#define ShouldGetStatBadgeBoost(flag, battler)\
|
||||
(!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_EREADER_TRAINER)) && FlagGet(flag) && GetBattlerSide(battler) == B_SIDE_PLAYER)
|
||||
|
||||
|
||||
s32 CalculateBaseDamageOld(struct BattlePokemon *attacker, struct BattlePokemon *defender, u32 move, u32 sideStatus, u16 powerOverride, u8 typeOverride, u8 battlerIdAtk, u8 battlerIdDef)
|
||||
{
|
||||
u32 i;
|
||||
s32 damage = 0;
|
||||
s32 damageHelper;
|
||||
u8 type;
|
||||
u16 attack, defense;
|
||||
u16 spAttack, spDefense;
|
||||
u8 defenderHoldEffect;
|
||||
u8 defenderHoldEffectParam;
|
||||
u8 attackerHoldEffect;
|
||||
u8 attackerHoldEffectParam;
|
||||
|
||||
if (!powerOverride)
|
||||
gBattleMovePower = gMovesInfo[move].power;
|
||||
else
|
||||
gBattleMovePower = powerOverride;
|
||||
|
||||
if (!typeOverride)
|
||||
type = gMovesInfo[move].type;
|
||||
else
|
||||
type = typeOverride & DYNAMIC_TYPE_MASK;
|
||||
|
||||
attack = attacker->attack;
|
||||
defense = defender->defense;
|
||||
spAttack = attacker->spAttack;
|
||||
spDefense = defender->spDefense;
|
||||
|
||||
// Get attacker hold item info
|
||||
if (attacker->item == ITEM_ENIGMA_BERRY)
|
||||
{
|
||||
attackerHoldEffect = gEnigmaBerries[battlerIdAtk].holdEffect;
|
||||
attackerHoldEffectParam = gEnigmaBerries[battlerIdAtk].holdEffectParam;
|
||||
}
|
||||
else
|
||||
{
|
||||
attackerHoldEffect = ItemId_GetHoldEffect(attacker->item);
|
||||
attackerHoldEffectParam = ItemId_GetHoldEffectParam(attacker->item);
|
||||
}
|
||||
|
||||
// Get defender hold item info
|
||||
if (defender->item == ITEM_ENIGMA_BERRY)
|
||||
{
|
||||
defenderHoldEffect = gEnigmaBerries[battlerIdDef].holdEffect;
|
||||
defenderHoldEffectParam = gEnigmaBerries[battlerIdDef].holdEffectParam;
|
||||
}
|
||||
else
|
||||
{
|
||||
defenderHoldEffect = ItemId_GetHoldEffect(defender->item);
|
||||
defenderHoldEffectParam = ItemId_GetHoldEffectParam(defender->item);
|
||||
}
|
||||
|
||||
if (attacker->ability == ABILITY_HUGE_POWER || attacker->ability == ABILITY_PURE_POWER)
|
||||
attack *= 2;
|
||||
|
||||
if (ShouldGetStatBadgeBoost(FLAG_BADGE01_GET, battlerIdAtk))
|
||||
attack = (110 * attack) / 100;
|
||||
if (ShouldGetStatBadgeBoost(FLAG_BADGE05_GET, battlerIdDef))
|
||||
defense = (110 * defense) / 100;
|
||||
if (ShouldGetStatBadgeBoost(FLAG_BADGE07_GET, battlerIdAtk))
|
||||
spAttack = (110 * spAttack) / 100;
|
||||
if (ShouldGetStatBadgeBoost(FLAG_BADGE07_GET, battlerIdDef))
|
||||
spDefense = (110 * spDefense) / 100;
|
||||
|
||||
// Apply type-bonus hold item
|
||||
for (i = 0; i < ARRAY_COUNT(sHoldEffectToType); i++)
|
||||
{
|
||||
if (attackerHoldEffect == sHoldEffectToType[i][0]
|
||||
&& type == sHoldEffectToType[i][1])
|
||||
{
|
||||
if (IS_TYPE_PHYSICAL(type))
|
||||
attack = (attack * (attackerHoldEffectParam + 100)) / 100;
|
||||
else
|
||||
spAttack = (spAttack * (attackerHoldEffectParam + 100)) / 100;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply boosts from hold items
|
||||
if (attackerHoldEffect == HOLD_EFFECT_CHOICE_BAND)
|
||||
attack = (150 * attack) / 100;
|
||||
if (attackerHoldEffect == HOLD_EFFECT_SOUL_DEW && !(gBattleTypeFlags & (BATTLE_TYPE_BATTLE_TOWER)) && (attacker->species == SPECIES_LATIAS || attacker->species == SPECIES_LATIOS))
|
||||
spAttack = (150 * spAttack) / 100;
|
||||
if (defenderHoldEffect == HOLD_EFFECT_SOUL_DEW && !(gBattleTypeFlags & (BATTLE_TYPE_BATTLE_TOWER)) && (defender->species == SPECIES_LATIAS || defender->species == SPECIES_LATIOS))
|
||||
spDefense = (150 * spDefense) / 100;
|
||||
if (attackerHoldEffect == HOLD_EFFECT_DEEP_SEA_TOOTH && attacker->species == SPECIES_CLAMPERL)
|
||||
spAttack *= 2;
|
||||
if (defenderHoldEffect == HOLD_EFFECT_DEEP_SEA_SCALE && defender->species == SPECIES_CLAMPERL)
|
||||
spDefense *= 2;
|
||||
if (attackerHoldEffect == HOLD_EFFECT_LIGHT_BALL && attacker->species == SPECIES_PIKACHU)
|
||||
spAttack *= 2;
|
||||
if (defenderHoldEffect == HOLD_EFFECT_METAL_POWDER && defender->species == SPECIES_DITTO)
|
||||
defense *= 2;
|
||||
if (attackerHoldEffect == HOLD_EFFECT_THICK_CLUB && (attacker->species == SPECIES_CUBONE || attacker->species == SPECIES_MAROWAK))
|
||||
attack *= 2;
|
||||
if (defender->ability == ABILITY_THICK_FAT && (type == TYPE_FIRE || type == TYPE_ICE))
|
||||
spAttack /= 2;
|
||||
if (attacker->ability == ABILITY_HUSTLE)
|
||||
attack = (150 * attack) / 100;
|
||||
if (attacker->ability == ABILITY_PLUS && ABILITY_ON_FIELD2(ABILITY_MINUS))
|
||||
spAttack = (150 * spAttack) / 100;
|
||||
if (attacker->ability == ABILITY_MINUS && ABILITY_ON_FIELD2(ABILITY_PLUS))
|
||||
spAttack = (150 * spAttack) / 100;
|
||||
if (attacker->ability == ABILITY_GUTS && attacker->status1)
|
||||
attack = (150 * attack) / 100;
|
||||
if (defender->ability == ABILITY_MARVEL_SCALE && defender->status1)
|
||||
defense = (150 * defense) / 100;
|
||||
if (type == TYPE_ELECTRIC && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, ABILITYEFFECT_MUD_SPORT, 0))
|
||||
gBattleMovePower /= 2;
|
||||
if (type == TYPE_FIRE && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, ABILITYEFFECT_WATER_SPORT, 0))
|
||||
gBattleMovePower /= 2;
|
||||
if (type == TYPE_GRASS && attacker->ability == ABILITY_OVERGROW && attacker->hp <= (attacker->maxHP / 3))
|
||||
gBattleMovePower = (150 * gBattleMovePower) / 100;
|
||||
if (type == TYPE_FIRE && attacker->ability == ABILITY_BLAZE && attacker->hp <= (attacker->maxHP / 3))
|
||||
gBattleMovePower = (150 * gBattleMovePower) / 100;
|
||||
if (type == TYPE_WATER && attacker->ability == ABILITY_TORRENT && attacker->hp <= (attacker->maxHP / 3))
|
||||
gBattleMovePower = (150 * gBattleMovePower) / 100;
|
||||
if (type == TYPE_BUG && attacker->ability == ABILITY_SWARM && attacker->hp <= (attacker->maxHP / 3))
|
||||
gBattleMovePower = (150 * gBattleMovePower) / 100;
|
||||
|
||||
// Self-destruct / Explosion cut defense in half
|
||||
if (gMovesInfo[gCurrentMove].effect == EFFECT_EXPLOSION)
|
||||
defense /= 2;
|
||||
|
||||
if (IS_TYPE_PHYSICAL(type))
|
||||
{
|
||||
if (gCritMultiplier == 2)
|
||||
{
|
||||
// Critical hit, if attacker has lost attack stat stages then ignore stat drop
|
||||
if (attacker->statStages[STAT_ATK] > DEFAULT_STAT_STAGE)
|
||||
APPLY_STAT_MOD(damage, attacker, attack, STAT_ATK)
|
||||
else
|
||||
damage = attack;
|
||||
}
|
||||
else
|
||||
APPLY_STAT_MOD(damage, attacker, attack, STAT_ATK)
|
||||
|
||||
damage = damage * gBattleMovePower;
|
||||
damage *= (2 * attacker->level / 5 + 2);
|
||||
|
||||
if (gCritMultiplier == 2)
|
||||
{
|
||||
// Critical hit, if defender has gained defense stat stages then ignore stat increase
|
||||
if (defender->statStages[STAT_DEF] < DEFAULT_STAT_STAGE)
|
||||
APPLY_STAT_MOD(damageHelper, defender, defense, STAT_DEF)
|
||||
else
|
||||
damageHelper = defense;
|
||||
}
|
||||
else
|
||||
APPLY_STAT_MOD(damageHelper, defender, defense, STAT_DEF)
|
||||
|
||||
damage = damage / damageHelper;
|
||||
damage /= 50;
|
||||
|
||||
// Burn cuts attack in half
|
||||
if ((attacker->status1 & STATUS1_BURN) && attacker->ability != ABILITY_GUTS)
|
||||
damage /= 2;
|
||||
|
||||
// Apply Reflect
|
||||
if ((sideStatus & SIDE_STATUS_REFLECT) && gCritMultiplier == 1)
|
||||
{
|
||||
if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerTarget) == 2)
|
||||
damage = 2 * (damage / 3);
|
||||
else
|
||||
damage /= 2;
|
||||
}
|
||||
|
||||
// Moves hitting both targets do half damage in double battles
|
||||
if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gMovesInfo[move].target == MOVE_TARGET_BOTH && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerTarget) == 2)
|
||||
damage /= 2;
|
||||
|
||||
// Moves always do at least 1 damage.
|
||||
if (damage == 0)
|
||||
damage = 1;
|
||||
}
|
||||
|
||||
if (type == TYPE_MYSTERY)
|
||||
damage = 0; // is ??? type. does 0 damage.
|
||||
|
||||
if (IS_TYPE_SPECIAL(type))
|
||||
{
|
||||
if (gCritMultiplier == 2)
|
||||
{
|
||||
// Critical hit, if attacker has lost sp. attack stat stages then ignore stat drop
|
||||
if (attacker->statStages[STAT_SPATK] > DEFAULT_STAT_STAGE)
|
||||
APPLY_STAT_MOD(damage, attacker, spAttack, STAT_SPATK)
|
||||
else
|
||||
damage = spAttack;
|
||||
}
|
||||
else
|
||||
APPLY_STAT_MOD(damage, attacker, spAttack, STAT_SPATK)
|
||||
|
||||
damage = damage * gBattleMovePower;
|
||||
damage *= (2 * attacker->level / 5 + 2);
|
||||
|
||||
if (gCritMultiplier == 2)
|
||||
{
|
||||
// Critical hit, if defender has gained sp. defense stat stages then ignore stat increase
|
||||
if (defender->statStages[STAT_SPDEF] < DEFAULT_STAT_STAGE)
|
||||
APPLY_STAT_MOD(damageHelper, defender, spDefense, STAT_SPDEF)
|
||||
else
|
||||
damageHelper = spDefense;
|
||||
}
|
||||
else
|
||||
APPLY_STAT_MOD(damageHelper, defender, spDefense, STAT_SPDEF)
|
||||
|
||||
damage = (damage / damageHelper);
|
||||
damage /= 50;
|
||||
|
||||
// Apply Lightscreen
|
||||
if ((sideStatus & SIDE_STATUS_LIGHTSCREEN) && gCritMultiplier == 1)
|
||||
{
|
||||
if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerTarget) == 2)
|
||||
damage = 2 * (damage / 3);
|
||||
else
|
||||
damage /= 2;
|
||||
}
|
||||
|
||||
// Moves hitting both targets do half damage in double battles
|
||||
if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gMovesInfo[move].target == MOVE_TARGET_BOTH && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerTarget) == 2)
|
||||
damage /= 2;
|
||||
|
||||
// Are effects of weather negated with cloud nine or air lock
|
||||
if (WEATHER_HAS_EFFECT2)
|
||||
{
|
||||
// Rain weakens Fire, boosts Water
|
||||
if (gBattleWeather & B_WEATHER_RAIN_TEMPORARY)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TYPE_FIRE:
|
||||
damage /= 2;
|
||||
break;
|
||||
case TYPE_WATER:
|
||||
damage = (15 * damage) / 10;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Any weather except sun weakens solar beam
|
||||
if ((gBattleWeather & (B_WEATHER_RAIN | B_WEATHER_SANDSTORM | B_WEATHER_HAIL_TEMPORARY)) && gCurrentMove == MOVE_SOLAR_BEAM)
|
||||
damage /= 2;
|
||||
|
||||
// Sun boosts Fire, weakens Water
|
||||
if (gBattleWeather & B_WEATHER_SUN)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TYPE_FIRE:
|
||||
damage = (15 * damage) / 10;
|
||||
break;
|
||||
case TYPE_WATER:
|
||||
damage /= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Flash fire triggered
|
||||
if ((gBattleResources->flags->flags[battlerIdAtk] & RESOURCE_FLAG_FLASH_FIRE) && type == TYPE_FIRE)
|
||||
damage = (15 * damage) / 10;
|
||||
}
|
||||
|
||||
return damage + 2;
|
||||
}
|
||||
|
||||
u8 CountAliveMonsInBattle(u8 caseId, u32 battler)
|
||||
{
|
||||
s32 i;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user