mirror of
https://github.com/rh-hideout/pokeemerald-expansion.git
synced 2026-04-26 02:14:22 -05:00
Move adjustdamage to the damage calc (#8948)
This commit is contained in:
parent
7b4eb6ce40
commit
922db5ce4a
|
|
@ -30,10 +30,6 @@
|
|||
.byte B_SCR_OP_TYPECALC
|
||||
.endm
|
||||
|
||||
.macro adjustdamage
|
||||
.byte B_SCR_OP_ADJUSTDAMAGE
|
||||
.endm
|
||||
|
||||
.macro multihitresultmessage
|
||||
.byte B_SCR_OP_MULTIHITRESULTMESSAGE
|
||||
.endm
|
||||
|
|
@ -1339,6 +1335,10 @@
|
|||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
.macro unused_1
|
||||
.byte B_SCR_UNUSED_1
|
||||
.endm
|
||||
|
||||
.macro callnative func:req
|
||||
.byte B_SCR_OP_CALLNATIVE
|
||||
.4byte \func
|
||||
|
|
|
|||
|
|
@ -563,7 +563,6 @@ BattleScript_EffectFling::
|
|||
printstring STRINGID_PKMNFLUNG
|
||||
waitmessage B_WAIT_TIME_SHORT
|
||||
damagecalc
|
||||
adjustdamage
|
||||
removeitem BS_ATTACKER
|
||||
attackanimation
|
||||
waitanimation
|
||||
|
|
@ -2230,7 +2229,6 @@ BattleScript_HitFromAccCheck::
|
|||
setpreattackadditionaleffect
|
||||
BattleScript_HitFromDamageCalc::
|
||||
damagecalc
|
||||
adjustdamage
|
||||
BattleScript_HitFromAtkAnimation::
|
||||
call BattleScript_Hit_RetFromAtkAnimation
|
||||
BattleScript_MoveEnd::
|
||||
|
|
@ -2242,7 +2240,6 @@ BattleScript_EffectHit_Ret::
|
|||
BattleScript_EffectHit_RetFromAccCheck::
|
||||
accuracycheck BattleScript_MoveMissedPause
|
||||
damagecalc
|
||||
adjustdamage
|
||||
BattleScript_Hit_RetFromAtkAnimation::
|
||||
attackanimation
|
||||
waitanimation
|
||||
|
|
@ -3588,7 +3585,6 @@ BattleScript_EffectSpitUp::
|
|||
jumpifbyte CMP_EQUAL, cMISS_TYPE, B_MSG_PROTECTED, BattleScript_SpitUpFailProtect
|
||||
accuracycheck BattleScript_MoveMissedPause
|
||||
damagecalc
|
||||
adjustdamage
|
||||
stockpiletobasedamage
|
||||
call BattleScript_Hit_RetFromAtkAnimation
|
||||
removestockpilecounters
|
||||
|
|
@ -4671,7 +4667,6 @@ BattleScript_BideAttack::
|
|||
typecalc
|
||||
clearmoveresultflags MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_NOT_VERY_EFFECTIVE
|
||||
copybidedmg
|
||||
adjustdamage
|
||||
setbyte sB_ANIM_TURN, 1
|
||||
attackanimation
|
||||
waitanimation
|
||||
|
|
@ -5095,7 +5090,6 @@ BattleScript_MonTookFutureAttack::
|
|||
jumpifmovehadnoeffect BattleScript_FutureAttackEnd
|
||||
accuracycheck BattleScript_MoveMissedPause
|
||||
damagecalc
|
||||
adjustdamage
|
||||
jumpifmovehadnoeffect BattleScript_DoFutureAttackResult
|
||||
jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_FUTURE_SIGHT, BattleScript_FutureHitAnimDoomDesire
|
||||
playanimation BS_ATTACKER, B_ANIM_FUTURE_SIGHT_HIT
|
||||
|
|
@ -5809,7 +5803,6 @@ BattleScript_MoveUsedIsConfused::
|
|||
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, FALSE, BattleScript_MoveUsedIsConfusedRet
|
||||
BattleScript_DoSelfConfusionDmg::
|
||||
cancelmultiturnmoves
|
||||
adjustdamage
|
||||
printstring STRINGID_ITHURTCONFUSION
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
effectivenesssound
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ enum BattleScriptOpcode
|
|||
B_SCR_OP_CRITCALC,
|
||||
B_SCR_OP_DAMAGECALC,
|
||||
B_SCR_OP_TYPECALC,
|
||||
B_SCR_OP_ADJUSTDAMAGE,
|
||||
B_SCR_OP_MULTIHITRESULTMESSAGE,
|
||||
B_SCR_OP_ATTACKANIMATION,
|
||||
B_SCR_OP_WAITANIMATION,
|
||||
|
|
@ -258,6 +257,11 @@ enum BattleScriptOpcode
|
|||
B_SCR_OP_JUMPIFCAPTIVATEAFFECTED,
|
||||
B_SCR_OP_SETNONVOLATILESTATUS,
|
||||
B_SCR_OP_TRYOVERWRITEABILITY,
|
||||
|
||||
// Expansion users, please don't use any of the unused commands.
|
||||
// They are reserved for expansion usage.
|
||||
// Use callnatives instead.
|
||||
B_SCR_OP_UNUSED_1,
|
||||
B_SCR_OP_CALLNATIVE,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -340,7 +340,6 @@ static void Cmd_printselectionstringfromtable(void);
|
|||
static void Cmd_critcalc(void);
|
||||
static void Cmd_damagecalc(void);
|
||||
static void Cmd_typecalc(void);
|
||||
static void Cmd_adjustdamage(void);
|
||||
static void Cmd_multihitresultmessage(void);
|
||||
static void Cmd_attackanimation(void);
|
||||
static void Cmd_waitanimation(void);
|
||||
|
|
@ -588,6 +587,7 @@ static void Cmd_averagestats(void);
|
|||
static void Cmd_jumpifcaptivateaffected(void);
|
||||
static void Cmd_setnonvolatilestatus(void);
|
||||
static void Cmd_tryoverwriteability(void);
|
||||
static void Cmd_unused_1(void);
|
||||
static void Cmd_callnative(void);
|
||||
|
||||
void (*const gBattleScriptingCommandsTable[])(void) =
|
||||
|
|
@ -599,7 +599,6 @@ void (*const gBattleScriptingCommandsTable[])(void) =
|
|||
[B_SCR_OP_CRITCALC] = Cmd_critcalc,
|
||||
[B_SCR_OP_DAMAGECALC] = Cmd_damagecalc,
|
||||
[B_SCR_OP_TYPECALC] = Cmd_typecalc,
|
||||
[B_SCR_OP_ADJUSTDAMAGE] = Cmd_adjustdamage,
|
||||
[B_SCR_OP_MULTIHITRESULTMESSAGE] = Cmd_multihitresultmessage,
|
||||
[B_SCR_OP_ATTACKANIMATION] = Cmd_attackanimation,
|
||||
[B_SCR_OP_WAITANIMATION] = Cmd_waitanimation,
|
||||
|
|
@ -847,6 +846,7 @@ void (*const gBattleScriptingCommandsTable[])(void) =
|
|||
[B_SCR_OP_JUMPIFCAPTIVATEAFFECTED] = Cmd_jumpifcaptivateaffected,
|
||||
[B_SCR_OP_SETNONVOLATILESTATUS] = Cmd_setnonvolatilestatus,
|
||||
[B_SCR_OP_TRYOVERWRITEABILITY] = Cmd_tryoverwriteability,
|
||||
[B_SCR_OP_UNUSED_1] = Cmd_unused_1,
|
||||
[B_SCR_OP_CALLNATIVE] = Cmd_callnative,
|
||||
};
|
||||
|
||||
|
|
@ -1277,7 +1277,8 @@ static void Cmd_damagecalc(void)
|
|||
{
|
||||
CMD_ARGS();
|
||||
|
||||
if (gBattleStruct->calculatedDamageDone)
|
||||
// Test if unableToUseMove check is needed
|
||||
if (gBattleStruct->calculatedDamageDone || gBattleStruct->unableToUseMove)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
return;
|
||||
|
|
@ -1295,8 +1296,7 @@ static void Cmd_damagecalc(void)
|
|||
|
||||
if (IsSpreadMove(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove)))
|
||||
{
|
||||
u32 battlerDef;
|
||||
for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++)
|
||||
for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++)
|
||||
{
|
||||
if (IsBattlerInvalidForSpreadMove(gBattlerAttacker, battlerDef))
|
||||
continue;
|
||||
|
|
@ -1304,6 +1304,7 @@ static void Cmd_damagecalc(void)
|
|||
ctx.battlerDef = battlerDef;
|
||||
CalculateAndSetMoveDamage(&ctx);
|
||||
}
|
||||
gBattleStruct->calculatedDamageDone = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1312,6 +1313,14 @@ static void Cmd_damagecalc(void)
|
|||
}
|
||||
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
|
||||
if (gSpecialStatuses[gBattlerAttacker].gemBoost
|
||||
&& gBattleMons[gBattlerAttacker].item
|
||||
&& IsAnyTargetAffected())
|
||||
{
|
||||
BattleScriptCall(BattleScript_GemActivates);
|
||||
gLastUsedItem = gBattleMons[gBattlerAttacker].item;
|
||||
}
|
||||
}
|
||||
|
||||
static void Cmd_typecalc(void)
|
||||
|
|
@ -1334,120 +1343,6 @@ static void Cmd_typecalc(void)
|
|||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
static void Cmd_adjustdamage(void)
|
||||
{
|
||||
CMD_ARGS();
|
||||
|
||||
enum HoldEffect holdEffect;
|
||||
u8 param;
|
||||
u32 battlerDef;
|
||||
u32 rand = Random() % 100;
|
||||
u32 affectionScore;
|
||||
enum BattleMoveEffects moveEffect = GetMoveEffect(gCurrentMove);
|
||||
bool32 calcSpreadMoveDamage = IsSpreadMove(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove));
|
||||
u32 enduredHit = 0;
|
||||
|
||||
for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++)
|
||||
{
|
||||
if (gBattleStruct->calculatedDamageDone)
|
||||
break;
|
||||
|
||||
if (!calcSpreadMoveDamage && battlerDef != gBattlerTarget)
|
||||
continue;
|
||||
|
||||
if (IsBattlerInvalidForSpreadMove(gBattlerAttacker, battlerDef))
|
||||
continue;
|
||||
|
||||
if (DoesSubstituteBlockMove(gBattlerAttacker, battlerDef, gCurrentMove))
|
||||
continue;
|
||||
|
||||
if (DoesDisguiseBlockMove(battlerDef, gCurrentMove))
|
||||
continue;
|
||||
|
||||
if (GetBattlerAbility(battlerDef) == ABILITY_ICE_FACE && IsBattleMovePhysical(gCurrentMove) && gBattleMons[battlerDef].species == SPECIES_EISCUE)
|
||||
{
|
||||
// Damage deals typeless 0 HP.
|
||||
gBattleStruct->moveResultFlags[battlerDef] &= ~(MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_NOT_VERY_EFFECTIVE);
|
||||
gBattleStruct->moveDamage[battlerDef] = 0;
|
||||
RecordAbilityBattle(battlerDef, ABILITY_ICE_FACE);
|
||||
gBattleMons[battlerDef].volatiles.triggerIceFace = TRUE;
|
||||
// Form change will be done after attack animation in Cmd_resultmessage.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gBattleMons[battlerDef].hp > gBattleStruct->moveDamage[battlerDef])
|
||||
continue;
|
||||
|
||||
holdEffect = GetBattlerHoldEffect(battlerDef);
|
||||
param = GetBattlerHoldEffectParam(battlerDef);
|
||||
affectionScore = GetBattlerAffectionHearts(battlerDef);
|
||||
|
||||
gPotentialItemEffectBattler = battlerDef;
|
||||
|
||||
if (moveEffect == EFFECT_FALSE_SWIPE)
|
||||
{
|
||||
enduredHit |= 1u << battlerDef;
|
||||
}
|
||||
else if (gBattleMons[battlerDef].volatiles.endured)
|
||||
{
|
||||
enduredHit |= 1u << battlerDef;
|
||||
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED;
|
||||
}
|
||||
else if (holdEffect == HOLD_EFFECT_FOCUS_BAND && rand < param)
|
||||
{
|
||||
enduredHit |= 1u << battlerDef;
|
||||
RecordItemEffectBattle(battlerDef, holdEffect);
|
||||
gLastUsedItem = gBattleMons[battlerDef].item;
|
||||
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_HUNG_ON;
|
||||
}
|
||||
else if (GetConfig(CONFIG_STURDY) >= GEN_5 && GetBattlerAbility(battlerDef) == ABILITY_STURDY && IsBattlerAtMaxHp(battlerDef))
|
||||
{
|
||||
enduredHit |= 1u << battlerDef;
|
||||
RecordAbilityBattle(battlerDef, ABILITY_STURDY);
|
||||
gLastUsedAbility = ABILITY_STURDY;
|
||||
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_STURDIED;
|
||||
}
|
||||
else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && IsBattlerAtMaxHp(battlerDef))
|
||||
{
|
||||
enduredHit |= 1u << battlerDef;
|
||||
RecordItemEffectBattle(battlerDef, holdEffect);
|
||||
gLastUsedItem = gBattleMons[battlerDef].item;
|
||||
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_HUNG_ON;
|
||||
}
|
||||
else if (B_AFFECTION_MECHANICS == TRUE && IsOnPlayerSide(battlerDef) && affectionScore >= AFFECTION_THREE_HEARTS)
|
||||
{
|
||||
if ((affectionScore == AFFECTION_FIVE_HEARTS && rand < 20)
|
||||
|| (affectionScore == AFFECTION_FOUR_HEARTS && rand < 15)
|
||||
|| (affectionScore == AFFECTION_THREE_HEARTS && rand < 10))
|
||||
{
|
||||
enduredHit |= 1u << battlerDef;
|
||||
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED_AFFECTION;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle reducing the dmg to 1 hp.
|
||||
if (enduredHit & 1u << battlerDef)
|
||||
{
|
||||
gBattleStruct->moveDamage[battlerDef] = gBattleMons[battlerDef].hp - 1;
|
||||
gProtectStructs[battlerDef].assuranceDoubled = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (calcSpreadMoveDamage)
|
||||
gBattleStruct->calculatedDamageDone = TRUE;
|
||||
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
|
||||
if (gSpecialStatuses[gBattlerAttacker].gemBoost
|
||||
&& !IsBattlerUnaffectedByMove(gBattlerTarget)
|
||||
&& !gBattleStruct->unableToUseMove
|
||||
&& gBattleMons[gBattlerAttacker].item)
|
||||
{
|
||||
BattleScriptCall(BattleScript_GemActivates);
|
||||
gLastUsedItem = gBattleMons[gBattlerAttacker].item;
|
||||
}
|
||||
}
|
||||
|
||||
static void Cmd_multihitresultmessage(void)
|
||||
{
|
||||
CMD_ARGS();
|
||||
|
|
@ -1731,9 +1626,7 @@ static void DoublesHPBarReduction(void)
|
|||
for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++)
|
||||
{
|
||||
if (IsBattlerUnaffectedByMove(battlerDef)
|
||||
|| gBattleStruct->moveDamage[battlerDef] == 0
|
||||
|| DoesSubstituteBlockMove(gBattlerAttacker, battlerDef, gCurrentMove)
|
||||
|| DoesDisguiseBlockMove(battlerDef, gCurrentMove))
|
||||
|| gBattleStruct->moveDamage[battlerDef] == 0)
|
||||
continue;
|
||||
|
||||
s32 dmgUpdate = min(gBattleStruct->moveDamage[battlerDef], 10000);
|
||||
|
|
@ -11833,6 +11726,10 @@ static void Cmd_tryoverwriteability(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void Cmd_unused_1(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void Cmd_callnative(void)
|
||||
{
|
||||
CMD_ARGS(void (*func)(void));
|
||||
|
|
|
|||
|
|
@ -2381,6 +2381,7 @@ static enum MoveCanceler CancelerConfused(struct BattleContext *ctx)
|
|||
dmgCtx.updateFlags = TRUE;
|
||||
dmgCtx.isSelfInflicted = TRUE;
|
||||
dmgCtx.fixedBasePower = 40;
|
||||
gBattlerTarget = gBattlerAttacker;
|
||||
gBattleStruct->passiveHpUpdate[ctx->battlerAtk] = CalculateMoveDamage(&dmgCtx);
|
||||
gBattlescriptCurrInstr = BattleScript_MoveUsedIsConfused;
|
||||
return MOVE_STEP_FAILURE;
|
||||
|
|
@ -9737,20 +9738,15 @@ s32 CalcCritChanceStageGen1(struct BattleContext *ctx)
|
|||
if (critChance > 255)
|
||||
critChance = 255;
|
||||
|
||||
// Prevented crits
|
||||
if (gSideStatuses[ctx->battlerDef] & SIDE_STATUS_LUCKY_CHANT)
|
||||
critChance = CRITICAL_HIT_BLOCKED;
|
||||
else if (ctx->abilityDef == ABILITY_BATTLE_ARMOR || ctx->abilityDef == ABILITY_SHELL_ARMOR)
|
||||
if (ctx->abilityDef == ABILITY_BATTLE_ARMOR || ctx->abilityDef == ABILITY_SHELL_ARMOR)
|
||||
{
|
||||
if (ctx->updateFlags)
|
||||
RecordAbilityBattle(ctx->battlerDef, ctx->abilityDef);
|
||||
critChance = CRITICAL_HIT_BLOCKED;
|
||||
}
|
||||
|
||||
// Guaranteed crits
|
||||
else if (gBattleMons[ctx->battlerAtk].volatiles.laserFocus
|
||||
|| MoveAlwaysCrits(ctx->move)
|
||||
|| (ctx->abilityAtk == ABILITY_MERCILESS && gBattleMons[ctx->battlerDef].status1 & STATUS1_PSN_ANY))
|
||||
|| MoveAlwaysCrits(ctx->move)
|
||||
|| (ctx->abilityAtk == ABILITY_MERCILESS && gBattleMons[ctx->battlerDef].status1 & STATUS1_PSN_ANY))
|
||||
{
|
||||
critChance = CRITICAL_HIT_ALWAYS;
|
||||
}
|
||||
|
|
@ -9760,6 +9756,14 @@ s32 CalcCritChanceStageGen1(struct BattleContext *ctx)
|
|||
|
||||
static bool32 IsCriticalHit(struct BattleContext *ctx)
|
||||
{
|
||||
|
||||
if (gBattleTypeFlags & (BATTLE_TYPE_WALLY_TUTORIAL | BATTLE_TYPE_FIRST_BATTLE))
|
||||
return FALSE;
|
||||
if (ctx->isSelfInflicted)
|
||||
return FALSE;
|
||||
if (gSideStatuses[ctx->battlerDef] & SIDE_STATUS_LUCKY_CHANT)
|
||||
return FALSE;
|
||||
|
||||
bool32 isCrit = FALSE;
|
||||
s32 critChance = 0;
|
||||
|
||||
|
|
@ -9768,21 +9772,16 @@ static bool32 IsCriticalHit(struct BattleContext *ctx)
|
|||
else
|
||||
critChance = CalcCritChanceStage(ctx);
|
||||
|
||||
if (gBattleTypeFlags & (BATTLE_TYPE_WALLY_TUTORIAL | BATTLE_TYPE_FIRST_BATTLE))
|
||||
if (critChance == CRITICAL_HIT_BLOCKED)
|
||||
isCrit = FALSE;
|
||||
else if (critChance == -1)
|
||||
isCrit = FALSE;
|
||||
else if (critChance == -2)
|
||||
else if (critChance == CRITICAL_HIT_ALWAYS)
|
||||
isCrit = TRUE;
|
||||
else if (GetConfig(CONFIG_CRIT_CHANCE) == GEN_1)
|
||||
isCrit = RandomChance(RNG_CRITICAL_HIT, critChance, 256);
|
||||
else if (GetConfig(CONFIG_CRIT_CHANCE) == GEN_2)
|
||||
isCrit = RandomChance(RNG_CRITICAL_HIT, GetCriticalHitOdds(critChance), 256);
|
||||
else
|
||||
{
|
||||
if (GetConfig(CONFIG_CRIT_CHANCE) == GEN_1)
|
||||
isCrit = RandomChance(RNG_CRITICAL_HIT, critChance, 256);
|
||||
else if (GetConfig(CONFIG_CRIT_CHANCE) == GEN_2)
|
||||
isCrit = RandomChance(RNG_CRITICAL_HIT, GetCriticalHitOdds(critChance), 256);
|
||||
else
|
||||
isCrit = RandomChance(RNG_CRITICAL_HIT, 1, GetCriticalHitOdds(critChance));
|
||||
}
|
||||
isCrit = RandomChance(RNG_CRITICAL_HIT, 1, GetCriticalHitOdds(critChance));
|
||||
|
||||
// Counter for IF_CRITICAL_HITS_GE evolution condition.
|
||||
if (isCrit && IsOnPlayerSide(ctx->battlerAtk)
|
||||
|
|
@ -9793,21 +9792,95 @@ static bool32 IsCriticalHit(struct BattleContext *ctx)
|
|||
return isCrit;
|
||||
}
|
||||
|
||||
s32 GetAdjustedDamage(struct BattleContext *ctx, s32 damage)
|
||||
{
|
||||
if (DoesSubstituteBlockMove(ctx->battlerAtk, ctx->battlerDef, ctx->move)
|
||||
|| DoesDisguiseBlockMove(ctx->battlerDef, ctx->move))
|
||||
return damage; // No damage will be dealt
|
||||
|
||||
if (ctx->abilityDef == ABILITY_ICE_FACE && IsBattleMovePhysical(ctx->move) && gBattleMons[ctx->battlerDef].species == SPECIES_EISCUE)
|
||||
{
|
||||
gBattleStruct->moveResultFlags[ctx->battlerDef] &= ~(MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_NOT_VERY_EFFECTIVE);
|
||||
RecordAbilityBattle(ctx->battlerDef, ABILITY_ICE_FACE);
|
||||
gBattleMons[ctx->battlerDef].volatiles.triggerIceFace = TRUE; // Form change will be done after attack animation in Cmd_resultmessage.
|
||||
return 0; // Typeless damage 0 HP.
|
||||
}
|
||||
|
||||
if (gBattleMons[ctx->battlerDef].hp > damage)
|
||||
return damage;
|
||||
|
||||
bool32 enduredHit = FALSE;
|
||||
u32 rand = Random() % 100;
|
||||
u32 affectionScore = GetBattlerAffectionHearts(ctx->battlerDef);
|
||||
|
||||
if (GetMoveEffect(ctx->move) == EFFECT_FALSE_SWIPE)
|
||||
{
|
||||
enduredHit = TRUE;
|
||||
}
|
||||
else if (gBattleMons[ctx->battlerDef].volatiles.endured)
|
||||
{
|
||||
enduredHit = TRUE;
|
||||
gBattleStruct->moveResultFlags[ctx->battlerDef] |= MOVE_RESULT_FOE_ENDURED;
|
||||
}
|
||||
else if (ctx->holdEffectDef == HOLD_EFFECT_FOCUS_BAND && rand < GetBattlerHoldEffectParam(ctx->battlerDef))
|
||||
{
|
||||
enduredHit = TRUE;
|
||||
RecordItemEffectBattle(ctx->battlerDef, ctx->holdEffectDef);
|
||||
gLastUsedItem = gBattleMons[ctx->battlerDef].item;
|
||||
gBattleStruct->moveResultFlags[ctx->battlerDef] |= MOVE_RESULT_FOE_HUNG_ON;
|
||||
}
|
||||
else if (GetConfig(CONFIG_STURDY) >= GEN_5 && ctx->abilityDef == ABILITY_STURDY && IsBattlerAtMaxHp(ctx->battlerDef))
|
||||
{
|
||||
enduredHit = TRUE;
|
||||
RecordAbilityBattle(ctx->battlerDef, ABILITY_STURDY);
|
||||
gLastUsedAbility = ABILITY_STURDY;
|
||||
gBattleStruct->moveResultFlags[ctx->battlerDef] |= MOVE_RESULT_STURDIED;
|
||||
}
|
||||
else if (ctx->holdEffectDef == HOLD_EFFECT_FOCUS_SASH && IsBattlerAtMaxHp(ctx->battlerDef))
|
||||
{
|
||||
enduredHit = TRUE;
|
||||
RecordItemEffectBattle(ctx->battlerDef, ctx->holdEffectDef);
|
||||
gLastUsedItem = gBattleMons[ctx->battlerDef].item;
|
||||
gBattleStruct->moveResultFlags[ctx->battlerDef] |= MOVE_RESULT_FOE_HUNG_ON;
|
||||
}
|
||||
else if (B_AFFECTION_MECHANICS == TRUE && IsOnPlayerSide(ctx->battlerDef) && affectionScore >= AFFECTION_THREE_HEARTS)
|
||||
{
|
||||
if ((affectionScore == AFFECTION_FIVE_HEARTS && rand < 20)
|
||||
|| (affectionScore == AFFECTION_FOUR_HEARTS && rand < 15)
|
||||
|| (affectionScore == AFFECTION_THREE_HEARTS && rand < 10))
|
||||
{
|
||||
enduredHit = TRUE;
|
||||
gBattleStruct->moveResultFlags[ctx->battlerDef] |= MOVE_RESULT_FOE_ENDURED_AFFECTION;
|
||||
}
|
||||
}
|
||||
|
||||
if (enduredHit)
|
||||
{
|
||||
damage = gBattleMons[ctx->battlerDef].hp - 1; // Reduce damage to 1 hp.
|
||||
gProtectStructs[ctx->battlerDef].assuranceDoubled = TRUE;
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
s32 CalculateMoveDamage(struct BattleContext *ctx)
|
||||
{
|
||||
s32 damage = 0;
|
||||
|
||||
ctx->abilityAtk = GetBattlerAbility(ctx->battlerAtk);
|
||||
ctx->abilityDef = GetBattlerAbility(ctx->battlerDef);
|
||||
ctx->holdEffectAtk = GetBattlerHoldEffect(ctx->battlerAtk);
|
||||
ctx->holdEffectDef = GetBattlerHoldEffect(ctx->battlerDef);
|
||||
|
||||
ctx->typeEffectivenessModifier = CalcTypeEffectivenessMultiplier(ctx);
|
||||
if (!ctx->isSelfInflicted)
|
||||
ctx->isCrit = IsCriticalHit(ctx);
|
||||
ctx->isCrit = IsCriticalHit(ctx);
|
||||
|
||||
if (IsFutureSightAttackerInParty(ctx->battlerAtk, ctx->battlerDef, ctx->move))
|
||||
return DoFutureSightAttackDamageCalc(ctx);
|
||||
damage = DoFutureSightAttackDamageCalc(ctx);
|
||||
else
|
||||
damage = DoMoveDamageCalc(ctx);
|
||||
|
||||
return DoMoveDamageCalc(ctx);
|
||||
return GetAdjustedDamage(ctx, damage);
|
||||
}
|
||||
|
||||
// for AI so that typeEffectivenessModifier, weather, abilities and holdEffects are calculated only once
|
||||
|
|
|
|||
|
|
@ -52,3 +52,34 @@ SINGLE_BATTLE_TEST("Confusion self hit does not consume Gems")
|
|||
MESSAGE("It hurt itself in its confusion!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Confusion damage activates Focus Sash")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetItemHoldEffect(ITEM_FOCUS_SASH) == HOLD_EFFECT_FOCUS_SASH);
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(1); Item(ITEM_FOCUS_SASH); }
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_CONFUSE_RAY); MOVE(player, MOVE_POUND); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, opponent);
|
||||
HP_BAR(player); // Confusion damage
|
||||
MESSAGE("Wobbuffet hung on using its Focus Sash!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Confusion damage Breaks Ice Face")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_EISCUE) { Ability(ABILITY_ICE_FACE); }
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_CONFUSE_RAY); MOVE(player, MOVE_FAIRY_WIND); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, opponent);
|
||||
HP_BAR(player); // Confusion damage
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player);
|
||||
} THEN {
|
||||
EXPECT_EQ(player->species, SPECIES_EISCUE_NOICE);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user