Merge branch 'master' of https://github.com/rh-hideout/pokeemerald-expansion into rh-hideout-master
This commit is contained in:
commit
f7e45ca2b3
@ -421,8 +421,8 @@ B_TRAINER1_NAME_WITH_CLASS = FD 42
|
||||
B_TRAINER2_NAME_WITH_CLASS = FD 43
|
||||
B_PARTNER_NAME_WITH_CLASS = FD 44
|
||||
B_ATK_TRAINER_NAME_WITH_CLASS = FD 45
|
||||
B_SCR_TEAM1 = FD 46
|
||||
B_SCR_TEAM2 = FD 47
|
||||
B_EFF_TEAM1 = FD 46
|
||||
B_EFF_TEAM2 = FD 47
|
||||
|
||||
@ indicates the end of a town/city name (before " TOWN" or " CITY")
|
||||
NAME_END = FC 00
|
||||
|
||||
@ -2856,12 +2856,6 @@ BattleScript_MoveMissed::
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectDarkVoid::
|
||||
.if B_DARK_VOID_FAIL >= GEN_7
|
||||
jumpifspecies BS_ATTACKER, SPECIES_DARKRAI, BattleScript_EffectNonVolatileStatus
|
||||
goto BattleScript_PokemonCantUseTheMove
|
||||
.endif
|
||||
|
||||
BattleScript_TerrainPreventsEnd2::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
printfromtable gTerrainPreventsStringIds
|
||||
@ -4683,6 +4677,11 @@ BattleScript_FlatterTryConfuse::
|
||||
seteffectprimary MOVE_EFFECT_CONFUSION
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectDarkVoid::
|
||||
.if B_DARK_VOID_FAIL >= GEN_7
|
||||
jumpifspecies BS_ATTACKER, SPECIES_DARKRAI, BattleScript_EffectNonVolatileStatus
|
||||
goto BattleScript_PokemonCantUseTheMove
|
||||
.endif
|
||||
BattleScript_EffectNonVolatileStatus::
|
||||
attackcanceler
|
||||
attackstring
|
||||
@ -6764,51 +6763,40 @@ BattleScript_UltraBurst::
|
||||
end3
|
||||
|
||||
BattleScript_GulpMissileFormChange::
|
||||
call BattleScript_AttackerFormChange
|
||||
call BattleScript_BattlerFormChange
|
||||
goto BattleScript_FromTwoTurnMovesSecondTurnRet
|
||||
|
||||
BattleScript_AttackerFormChange::
|
||||
BattleScript_BattlerFormChange::
|
||||
pause 5
|
||||
copybyte gBattlerAbility, gBattlerAttacker
|
||||
call BattleScript_AbilityPopUp
|
||||
call BattleScript_AbilityPopUpScripting
|
||||
flushtextbox
|
||||
BattleScript_AttackerFormChangeNoPopup::
|
||||
handleformchange BS_ATTACKER, 0
|
||||
handleformchange BS_ATTACKER, 1
|
||||
playanimation BS_ATTACKER, B_ANIM_FORM_CHANGE
|
||||
BattleScript_BattlerFormChangeNoPopup:
|
||||
handleformchange BS_SCRIPTING, 0
|
||||
handleformchange BS_SCRIPTING, 1
|
||||
playanimation BS_SCRIPTING, B_ANIM_FORM_CHANGE
|
||||
waitanimation
|
||||
handleformchange BS_ATTACKER, 2
|
||||
handleformchange BS_SCRIPTING, 2
|
||||
return
|
||||
|
||||
BattleScript_AttackerFormChangeEnd3::
|
||||
call BattleScript_AttackerFormChange
|
||||
BattleScript_BattlerFormChangeEnd3::
|
||||
call BattleScript_BattlerFormChange
|
||||
end3
|
||||
|
||||
BattleScript_AttackerFormChangeEnd3NoPopup::
|
||||
call BattleScript_AttackerFormChangeNoPopup
|
||||
BattleScript_BattlerFormChangeEnd3NoPopup::
|
||||
call BattleScript_BattlerFormChangeNoPopup
|
||||
end3
|
||||
|
||||
BattleScript_AttackerFormChangeWithString::
|
||||
BattleScript_BattlerFormChangeWithStringEnd3::
|
||||
pause 5
|
||||
copybyte gBattlerAbility, gBattlerAttacker
|
||||
call BattleScript_AbilityPopUp
|
||||
call BattleScript_AbilityPopUpScripting
|
||||
flushtextbox
|
||||
BattleScript_AttackerFormChangeWithStringNoPopup::
|
||||
handleformchange BS_ATTACKER, 0
|
||||
handleformchange BS_ATTACKER, 1
|
||||
playanimation BS_ATTACKER, B_ANIM_FORM_CHANGE
|
||||
handleformchange BS_SCRIPTING, 0
|
||||
handleformchange BS_SCRIPTING, 1
|
||||
playanimation BS_SCRIPTING, B_ANIM_FORM_CHANGE
|
||||
waitanimation
|
||||
handleformchange BS_ATTACKER, 2
|
||||
handleformchange BS_SCRIPTING, 2
|
||||
printstring STRINGID_PKMNTRANSFORMED
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
return
|
||||
|
||||
BattleScript_AttackerFormChangeWithStringEnd3::
|
||||
call BattleScript_AttackerFormChangeWithString
|
||||
end3
|
||||
|
||||
BattleScript_AttackerFormChangeWithStringEnd3NoPopup::
|
||||
call BattleScript_AttackerFormChangeWithStringNoPopup
|
||||
end3
|
||||
|
||||
BattleScript_AttackerFormChangeMoveEffect::
|
||||
@ -6874,19 +6862,6 @@ BattleScript_TargetFormChangeWithStringNoPopup::
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
return
|
||||
|
||||
BattleScript_BattlerFormChangeWithStringEnd3::
|
||||
pause 5
|
||||
call BattleScript_AbilityPopUpScripting
|
||||
flushtextbox
|
||||
handleformchange BS_SCRIPTING, 0
|
||||
handleformchange BS_SCRIPTING, 1
|
||||
playanimation BS_SCRIPTING, B_ANIM_FORM_CHANGE, NULL
|
||||
waitanimation
|
||||
handleformchange BS_SCRIPTING, 2
|
||||
printstring STRINGID_PKMNTRANSFORMED
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
end3
|
||||
|
||||
BattleScript_IllusionOffAndTerastallization::
|
||||
call BattleScript_IllusionOff
|
||||
goto BattleScript_Terastallization
|
||||
@ -6913,7 +6888,7 @@ BattleScript_CottonDownActivates::
|
||||
swapattackerwithtarget
|
||||
setbyte gBattlerTarget, 0
|
||||
BattleScript_CottonDownLoop:
|
||||
jumpiffainted BS_TARGET, TRUE, BattleScript_CottonDownLoopIncrement
|
||||
jumpifabsent BS_TARGET, BattleScript_CottonDownLoopIncrement
|
||||
setstatchanger STAT_SPEED, 1, TRUE
|
||||
jumpifbyteequal gBattlerTarget, gEffectBattler, BattleScript_CottonDownLoopIncrement
|
||||
statbuffchange STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_CottonDownLoopIncrement
|
||||
@ -7621,11 +7596,7 @@ BattleScript_TryIntimidateHoldEffectsRet:
|
||||
|
||||
BattleScript_IntimidateActivates::
|
||||
savetarget
|
||||
.if B_ABILITY_POP_UP == TRUE
|
||||
showabilitypopup BS_ATTACKER
|
||||
pause B_WAIT_TIME_LONG
|
||||
destroyabilitypopup
|
||||
.endif
|
||||
call BattleScript_AbilityPopUp
|
||||
setbyte gBattlerTarget, 0
|
||||
BattleScript_IntimidateLoop:
|
||||
jumpifbyteequal gBattlerTarget, gBattlerAttacker, BattleScript_IntimidateLoopIncrement
|
||||
@ -7656,6 +7627,7 @@ BattleScript_IntimidateLoopIncrement:
|
||||
copybyte sBATTLER, gBattlerAttacker
|
||||
destroyabilitypopup
|
||||
restoretarget
|
||||
restoreattacker
|
||||
pause B_WAIT_TIME_MED
|
||||
tryintimidateejectpack
|
||||
end3
|
||||
@ -7690,11 +7662,7 @@ BattleScript_IntimidateInReverse::
|
||||
|
||||
BattleScript_SupersweetSyrupActivates::
|
||||
savetarget
|
||||
.if B_ABILITY_POP_UP == TRUE
|
||||
showabilitypopup BS_ATTACKER
|
||||
pause B_WAIT_TIME_LONG
|
||||
destroyabilitypopup
|
||||
.endif
|
||||
call BattleScript_AbilityPopUp
|
||||
printstring STRINGID_SUPERSWEETAROMAWAFTS
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
setbyte gBattlerTarget, 0
|
||||
@ -7722,6 +7690,7 @@ BattleScript_SupersweetSyrupLoopIncrement:
|
||||
copybyte sBATTLER, gBattlerAttacker
|
||||
destroyabilitypopup
|
||||
restoretarget
|
||||
restoreattacker
|
||||
pause B_WAIT_TIME_MED
|
||||
tryintimidateejectpack
|
||||
end3
|
||||
@ -7878,8 +7847,8 @@ BattleScript_HospitalityActivates::
|
||||
printstring STRINGID_HOSPITALITYRESTORATION
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE
|
||||
healthbarupdate BS_TARGET
|
||||
datahpupdate BS_TARGET
|
||||
healthbarupdate BS_EFFECT_BATTLER
|
||||
datahpupdate BS_EFFECT_BATTLER
|
||||
end3
|
||||
|
||||
BattleScript_AttackWeakenedByStrongWinds::
|
||||
@ -8346,6 +8315,7 @@ BattleScript_FellStingerRaisesAtkEnd:
|
||||
|
||||
BattleScript_AttackerAbilityStatRaiseEnd3::
|
||||
call BattleScript_AttackerAbilityStatRaise
|
||||
restoreattacker
|
||||
end3
|
||||
|
||||
BattleScript_SwitchInAbilityMsg::
|
||||
@ -8396,6 +8366,8 @@ BattleScript_ImposterActivates::
|
||||
waitanimation
|
||||
printstring STRINGID_IMPOSTERTRANSFORM
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
restoreattacker
|
||||
restoretarget
|
||||
end3
|
||||
|
||||
BattleScript_HurtAttacker:
|
||||
@ -9496,6 +9468,7 @@ BattleScript_PastelVeilLoopIncrement:
|
||||
setallytonexttarget BattleScript_PastelVeil_TryCurePoison
|
||||
goto BattleScript_PastelVeilEnd
|
||||
BattleScript_PastelVeilEnd:
|
||||
restoretarget
|
||||
end3
|
||||
|
||||
BattleScript_NeutralizingGasExits::
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 786 B After Width: | Height: | Size: 907 B |
@ -588,7 +588,8 @@ struct BattlerState
|
||||
u32 pursuitTarget:1;
|
||||
u32 stompingTantrumTimer:2;
|
||||
u32 canPickupItem:1;
|
||||
u32 padding:16;
|
||||
u32 itemCanBeKnockedOff:1;
|
||||
u32 padding:15;
|
||||
// End of Word
|
||||
};
|
||||
|
||||
|
||||
@ -84,8 +84,8 @@
|
||||
#define B_TXT_TRAINER2_NAME_WITH_CLASS 0x43
|
||||
#define B_TXT_PARTNER_NAME_WITH_CLASS 0x44
|
||||
#define B_TXT_ATK_TRAINER_NAME_WITH_CLASS 0x45
|
||||
#define B_TXT_SCR_TEAM1 0x46
|
||||
#define B_TXT_SCR_TEAM2 0x47
|
||||
#define B_TXT_EFF_TEAM1 0x46
|
||||
#define B_TXT_EFF_TEAM2 0x47
|
||||
|
||||
#define B_BUFF_STRING 0
|
||||
#define B_BUFF_NUMBER 1
|
||||
|
||||
@ -374,10 +374,10 @@ extern const u8 BattleScript_IllusionOffEnd3[];
|
||||
extern const u8 BattleScript_IllusionOffAndTerastallization[];
|
||||
extern const u8 BattleScript_DancerActivates[];
|
||||
extern const u8 BattleScript_AftermathDmg[];
|
||||
extern const u8 BattleScript_AttackerFormChange[];
|
||||
extern const u8 BattleScript_AttackerFormChangeEnd3[];
|
||||
extern const u8 BattleScript_BattlerFormChange[];
|
||||
extern const u8 BattleScript_BattlerFormChangeEnd3[];
|
||||
extern const u8 BattleScript_AttackerFormChangeWithString[];
|
||||
extern const u8 BattleScript_AttackerFormChangeWithStringEnd3[];
|
||||
extern const u8 BattleScript_BattlerFormChangeWithStringEnd3[];
|
||||
extern const u8 BattleScript_TargetFormChange[];
|
||||
extern const u8 BattleScript_AnticipationActivates[];
|
||||
extern const u8 BattleScript_SlowStartEnds[];
|
||||
@ -449,7 +449,7 @@ extern const u8 BattleScript_WanderingSpiritActivates[];
|
||||
extern const u8 BattleScript_MirrorArmorReflect[];
|
||||
extern const u8 BattleScript_GooeyActivates[];
|
||||
extern const u8 BattleScript_PastelVeilActivates[];
|
||||
extern const u8 BattleScript_AttackerFormChangeEnd3NoPopup[];
|
||||
extern const u8 BattleScript_BattlerFormChangeEnd3NoPopup[];
|
||||
extern const u8 BattleScript_AttackerFormChangeWithStringEnd3NoPopup[];
|
||||
extern const u8 BattleScript_AttackerFormChangeMoveEffect[];
|
||||
extern const u8 BattleScript_BothCanNoLongerEscape[];
|
||||
|
||||
@ -297,7 +297,7 @@ bool32 TryClearIllusion(u32 battler, u32 caseID);
|
||||
u32 GetIllusionMonSpecies(u32 battler);
|
||||
struct Pokemon *GetIllusionMonPtr(u32 battler);
|
||||
void ClearIllusionMon(u32 battler);
|
||||
u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon);
|
||||
u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon, u32 battler);
|
||||
bool32 SetIllusionMon(struct Pokemon *mon, u32 battler);
|
||||
bool32 ShouldGetStatBadgeBoost(u16 flagId, u32 battler);
|
||||
u32 GetBattleMoveCategory(u32 move);
|
||||
|
||||
@ -363,7 +363,6 @@ enum MoveEffects
|
||||
MOVE_EFFECT_REMOVE_ARG_TYPE,
|
||||
MOVE_EFFECT_RECHARGE,
|
||||
MOVE_EFFECT_RAGE,
|
||||
MOVE_EFFECT_STEAL_ITEM,
|
||||
MOVE_EFFECT_PREVENT_ESCAPE,
|
||||
MOVE_EFFECT_NIGHTMARE,
|
||||
MOVE_EFFECT_ALL_STATS_UP,
|
||||
@ -399,8 +398,6 @@ enum MoveEffects
|
||||
MOVE_EFFECT_TRAP_BOTH,
|
||||
MOVE_EFFECT_ROUND,
|
||||
MOVE_EFFECT_DIRE_CLAW,
|
||||
MOVE_EFFECT_STEALTH_ROCK,
|
||||
MOVE_EFFECT_SPIKES,
|
||||
MOVE_EFFECT_SYRUP_BOMB,
|
||||
MOVE_EFFECT_FLORAL_HEALING,
|
||||
MOVE_EFFECT_SECRET_POWER,
|
||||
@ -414,6 +411,11 @@ enum MoveEffects
|
||||
MOVE_EFFECT_LIGHT_SCREEN,
|
||||
MOVE_EFFECT_SALT_CURE,
|
||||
MOVE_EFFECT_EERIE_SPELL,
|
||||
|
||||
// Max move effects happen earlier in the execution chain.
|
||||
// For example stealth rock from G-Max Stonesurge is set up before abilities but from Stone Axe after.
|
||||
// Stone Axe can also fail to set up rocks if user faints where as Stonesurge will always go up.
|
||||
// This means we need to be careful if we want to re-use those effects for (new) vanilla moves
|
||||
MOVE_EFFECT_RAISE_TEAM_ATTACK,
|
||||
MOVE_EFFECT_RAISE_TEAM_DEFENSE,
|
||||
MOVE_EFFECT_RAISE_TEAM_SPEED,
|
||||
@ -455,11 +457,14 @@ enum MoveEffects
|
||||
MOVE_EFFECT_LOWER_EVASIVENESS_SIDE,
|
||||
MOVE_EFFECT_AROMATHERAPY,
|
||||
MOVE_EFFECT_CONFUSE_SIDE,
|
||||
MOVE_EFFECT_STEELSURGE,
|
||||
MOVE_EFFECT_STEELSURGE, // Steel type rocks
|
||||
MOVE_EFFECT_STEALTH_ROCK, // Max Move rocks, not to be confused for rocks set up from Ceasless Edge (same but differ in execution order)
|
||||
MOVE_EFFECT_TORMENT_SIDE,
|
||||
MOVE_EFFECT_LOWER_SPEED_2_SIDE,
|
||||
MOVE_EFFECT_FIRE_SPIN_SIDE,
|
||||
MOVE_EFFECT_FIXED_POWER,
|
||||
// Max move effects end. They can be used for (custom) normal moves.
|
||||
|
||||
NUM_MOVE_EFFECTS
|
||||
};
|
||||
|
||||
|
||||
@ -155,6 +155,7 @@ enum BattleMoveEffects
|
||||
EFFECT_BRICK_BREAK,
|
||||
EFFECT_YAWN,
|
||||
EFFECT_KNOCK_OFF,
|
||||
EFFECT_STEAL_ITEM,
|
||||
EFFECT_ENDEAVOR,
|
||||
EFFECT_POWER_BASED_ON_USER_HP,
|
||||
EFFECT_SKILL_SWAP,
|
||||
@ -351,6 +352,8 @@ enum BattleMoveEffects
|
||||
EFFECT_SMACK_DOWN,
|
||||
EFFECT_ICE_SPINNER, // Removes terrain unless attacker is removed from field either by fainting or ejected out
|
||||
EFFECT_STEEL_ROLLER, // Will fail if there is no terrain up but removes it regardless if attacker is removed from field or not
|
||||
EFFECT_STONE_AXE, // Not to be confused with MOVE_EFFECT_STEALTH_ROCK. They have two different activation timings.
|
||||
EFFECT_CEASELESS_EDGE, // Same applies to spikes
|
||||
NUM_BATTLE_MOVE_EFFECTS,
|
||||
};
|
||||
|
||||
|
||||
@ -260,7 +260,6 @@ enum MoveEndEffects
|
||||
MOVEEND_ATTACKER_VISIBLE,
|
||||
MOVEEND_TARGET_VISIBLE,
|
||||
MOVEEND_ITEM_EFFECTS_TARGET,
|
||||
MOVEEND_FIRST_MOVE_BLOCK,
|
||||
MOVEEND_ITEM_EFFECTS_ALL,
|
||||
MOVEEND_SYMBIOSIS,
|
||||
MOVEEND_KINGSROCK, // These item effects will occur each strike of a multi-hit move
|
||||
@ -271,7 +270,7 @@ enum MoveEndEffects
|
||||
MOVEEND_DEFROST,
|
||||
MOVEEND_NEXT_TARGET, // Everything up until here is handled for each strike of a spread move
|
||||
MOVEEND_MULTIHIT_MOVE,
|
||||
MOVEEND_SECOND_MOVE_BLOCK,
|
||||
MOVEEND_MOVE_BLOCK,
|
||||
MOVEEND_ITEM_EFFECTS_ATTACKER,
|
||||
MOVEEND_ABILITY_BLOCK,
|
||||
MOVEEND_SHEER_FORCE, // If move is Sheer Force affected, skip until Opportunist
|
||||
|
||||
@ -290,7 +290,7 @@ void BattleAI_SetupAIData(u8 defaultScoreMoves, u32 battler)
|
||||
{
|
||||
if (moveLimitations & (1u << moveIndex))
|
||||
SET_SCORE(battler, moveIndex, 0);
|
||||
if (defaultScoreMoves & 1)
|
||||
else if (defaultScoreMoves & 1)
|
||||
SET_SCORE(battler, moveIndex, AI_SCORE_DEFAULT);
|
||||
else
|
||||
SET_SCORE(battler, moveIndex, 0);
|
||||
@ -2769,7 +2769,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
break;
|
||||
case EFFECT_MAGNET_RISE:
|
||||
if (gFieldStatuses & STATUS_FIELD_GRAVITY
|
||||
|| gDisableStructs[battlerAtk].magnetRiseTimer != 0
|
||||
|| gDisableStructs[battlerAtk].magnetRiseTimer > gBattleTurnCounter
|
||||
|| aiData->holdEffects[battlerAtk] == HOLD_EFFECT_IRON_BALL
|
||||
|| gStatuses3[battlerAtk] & (STATUS3_ROOTED | STATUS3_MAGNET_RISE | STATUS3_SMACKED_DOWN)
|
||||
|| !IsBattlerGrounded(battlerAtk))
|
||||
@ -5117,6 +5117,69 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EFFECT_STEAL_ITEM:
|
||||
{
|
||||
bool32 canSteal = FALSE;
|
||||
|
||||
if (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE)
|
||||
canSteal = TRUE;
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER || IsOnPlayerSide(battlerAtk))
|
||||
canSteal = TRUE;
|
||||
|
||||
if (canSteal && aiData->items[battlerAtk] == ITEM_NONE
|
||||
&& aiData->items[battlerDef] != ITEM_NONE
|
||||
&& CanBattlerGetOrLoseItem(battlerDef, aiData->items[battlerDef])
|
||||
&& CanBattlerGetOrLoseItem(battlerAtk, aiData->items[battlerDef])
|
||||
&& !HasMoveWithEffect(battlerAtk, EFFECT_ACROBATICS)
|
||||
&& aiData->abilities[battlerDef] != ABILITY_STICKY_HOLD)
|
||||
{
|
||||
switch (aiData->holdEffects[battlerDef])
|
||||
{
|
||||
case HOLD_EFFECT_NONE:
|
||||
break;
|
||||
case HOLD_EFFECT_CHOICE_BAND:
|
||||
case HOLD_EFFECT_CHOICE_SCARF:
|
||||
case HOLD_EFFECT_CHOICE_SPECS:
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case HOLD_EFFECT_TOXIC_ORB:
|
||||
if (ShouldPoison(battlerAtk, battlerAtk))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case HOLD_EFFECT_FLAME_ORB:
|
||||
if (ShouldBurn(battlerAtk, battlerAtk, aiData->abilities[battlerAtk]))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case HOLD_EFFECT_BLACK_SLUDGE:
|
||||
if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case HOLD_EFFECT_IRON_BALL:
|
||||
if (HasMoveWithEffect(battlerAtk, EFFECT_FLING))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case HOLD_EFFECT_LAGGING_TAIL:
|
||||
case HOLD_EFFECT_STICKY_BARB:
|
||||
break;
|
||||
default:
|
||||
ADJUST_SCORE(WEAK_EFFECT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EFFECT_STONE_AXE:
|
||||
case EFFECT_CEASELESS_EDGE:
|
||||
if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData));
|
||||
{
|
||||
if (gDisableStructs[battlerAtk].isFirstTurn)
|
||||
ADJUST_SCORE(BEST_EFFECT);
|
||||
else
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
} // move effect checks
|
||||
@ -5256,68 +5319,6 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
else if (GetItemPocket(aiData->items[battlerDef]) == POCKET_BERRIES || aiData->holdEffects[battlerDef] == HOLD_EFFECT_GEMS)
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case MOVE_EFFECT_STEAL_ITEM:
|
||||
{
|
||||
bool32 canSteal = FALSE;
|
||||
|
||||
if (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE)
|
||||
canSteal = TRUE;
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER || IsOnPlayerSide(battlerAtk))
|
||||
canSteal = TRUE;
|
||||
|
||||
if (canSteal && aiData->items[battlerAtk] == ITEM_NONE
|
||||
&& aiData->items[battlerDef] != ITEM_NONE
|
||||
&& CanBattlerGetOrLoseItem(battlerDef, aiData->items[battlerDef])
|
||||
&& CanBattlerGetOrLoseItem(battlerAtk, aiData->items[battlerDef])
|
||||
&& !HasMoveWithEffect(battlerAtk, EFFECT_ACROBATICS)
|
||||
&& aiData->abilities[battlerDef] != ABILITY_STICKY_HOLD)
|
||||
{
|
||||
switch (aiData->holdEffects[battlerDef])
|
||||
{
|
||||
case HOLD_EFFECT_NONE:
|
||||
break;
|
||||
case HOLD_EFFECT_CHOICE_BAND:
|
||||
case HOLD_EFFECT_CHOICE_SCARF:
|
||||
case HOLD_EFFECT_CHOICE_SPECS:
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case HOLD_EFFECT_TOXIC_ORB:
|
||||
if (ShouldPoison(battlerAtk, battlerAtk))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case HOLD_EFFECT_FLAME_ORB:
|
||||
if (ShouldBurn(battlerAtk, battlerAtk, aiData->abilities[battlerAtk]))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case HOLD_EFFECT_BLACK_SLUDGE:
|
||||
if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case HOLD_EFFECT_IRON_BALL:
|
||||
if (HasMoveWithEffect(battlerAtk, EFFECT_FLING))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case HOLD_EFFECT_LAGGING_TAIL:
|
||||
case HOLD_EFFECT_STICKY_BARB:
|
||||
break;
|
||||
default:
|
||||
ADJUST_SCORE(WEAK_EFFECT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_STEALTH_ROCK:
|
||||
case MOVE_EFFECT_SPIKES:
|
||||
if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData));
|
||||
{
|
||||
if (gDisableStructs[battlerAtk].isFirstTurn)
|
||||
ADJUST_SCORE(BEST_EFFECT);
|
||||
else
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_FEINT:
|
||||
if (GetMoveEffect(predictedMove) == EFFECT_PROTECT)
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
@ -5375,7 +5376,6 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
|
||||
// Effects that are encouraged on the first turn of battle
|
||||
static s32 AI_ForceSetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
{
|
||||
u8 i;
|
||||
if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)
|
||||
|| gBattleResults.battleTurnCounter != 0)
|
||||
return score;
|
||||
@ -5473,27 +5473,10 @@ static s32 AI_ForceSetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32
|
||||
case EFFECT_CHILLY_RECEPTION:
|
||||
case EFFECT_GEOMANCY:
|
||||
case EFFECT_VICTORY_DANCE:
|
||||
case EFFECT_CEASELESS_EDGE:
|
||||
case EFFECT_STONE_AXE:
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case EFFECT_HIT:
|
||||
{
|
||||
// TEMPORARY - should applied to all moves regardless of EFFECT
|
||||
// Consider move effects
|
||||
u32 additionalEffectCount = GetMoveAdditionalEffectCount(move);
|
||||
for (i = 0; i < additionalEffectCount; i++)
|
||||
{
|
||||
const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i);
|
||||
switch (additionalEffect->moveEffect)
|
||||
{
|
||||
case MOVE_EFFECT_STEALTH_ROCK:
|
||||
case MOVE_EFFECT_SPIKES:
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -160,10 +160,12 @@ static inline bool32 SetSwitchinAndSwitch(u32 battler, u32 switchinId)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool32 AI_DoesChoiceItemBlockMove(u32 battler, u32 move)
|
||||
static bool32 AI_DoesChoiceEffectBlockMove(u32 battler, u32 move)
|
||||
{
|
||||
// Choice locked into something else
|
||||
if (gAiLogicData->lastUsedMove[battler] != MOVE_NONE && gAiLogicData->lastUsedMove[battler] != move && HOLD_EFFECT_CHOICE(GetBattlerHoldEffect(battler, FALSE)) && IsBattlerItemEnabled(battler))
|
||||
if (gAiLogicData->lastUsedMove[battler] != MOVE_NONE && gAiLogicData->lastUsedMove[battler] != move
|
||||
&& ((HOLD_EFFECT_CHOICE(GetBattlerHoldEffect(battler, FALSE)) && IsBattlerItemEnabled(battler))
|
||||
|| gBattleMons[battler].ability == ABILITY_GORILLA_TACTICS))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
@ -225,12 +227,12 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
|
||||
if (!IsBattleMoveStatus(aiMove))
|
||||
{
|
||||
// Check if mon has a super effective move
|
||||
if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0) && !AI_DoesChoiceItemBlockMove(battler, aiMove))
|
||||
if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0) && !AI_DoesChoiceEffectBlockMove(battler, aiMove))
|
||||
hasSuperEffectiveMove = TRUE;
|
||||
|
||||
// Get maximum damage mon can deal
|
||||
damageDealt = AI_GetDamage(battler, opposingBattler, i, AI_ATTACKING, gAiLogicData);
|
||||
if (damageDealt > maxDamageDealt && !AI_DoesChoiceItemBlockMove(battler, aiMove))
|
||||
if (damageDealt > maxDamageDealt && !AI_DoesChoiceEffectBlockMove(battler, aiMove))
|
||||
{
|
||||
maxDamageDealt = damageDealt;
|
||||
aiBestMove = aiMove;
|
||||
@ -259,13 +261,10 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
|
||||
if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH)
|
||||
{
|
||||
damageTaken = AI_GetDamage(opposingBattler, battler, i, AI_DEFENDING, gAiLogicData);
|
||||
if (playerMove == gBattleStruct->choicedMove[opposingBattler]) // If player is choiced, only care about the choice locked move
|
||||
if (damageTaken > maxDamageTaken && !AI_DoesChoiceEffectBlockMove(opposingBattler, playerMove))
|
||||
{
|
||||
return maxDamageTaken = damageTaken;
|
||||
break;
|
||||
}
|
||||
if (damageTaken > maxDamageTaken)
|
||||
maxDamageTaken = damageTaken;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,7 +278,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
|
||||
}
|
||||
|
||||
// Check if current mon can 1v1 in spite of bad matchup, and don't switch out if it can
|
||||
if (hitsToKoPlayer < hitsToKoAI || (hitsToKoPlayer == hitsToKoAI && AI_IsFaster(battler, opposingBattler, aiBestMove)))
|
||||
if ((hitsToKoPlayer != 0 && (hitsToKoPlayer < hitsToKoAI || hitsToKoAI == 0)) || (hitsToKoPlayer == hitsToKoAI && AI_IsFaster(battler, opposingBattler, aiBestMove)))
|
||||
return FALSE;
|
||||
|
||||
// If we don't have any other viable options, don't switch out
|
||||
@ -483,7 +482,7 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler)
|
||||
// Only check damage if it's a damaging move
|
||||
if (!IsBattleMoveStatus(aiMove))
|
||||
{
|
||||
if (!AI_DoesChoiceItemBlockMove(battler, aiMove) && AI_GetDamage(battler, opposingBattler, i, AI_ATTACKING, gAiLogicData) > gBattleMons[opposingBattler].hp)
|
||||
if (!AI_DoesChoiceEffectBlockMove(battler, aiMove) && AI_GetDamage(battler, opposingBattler, i, AI_ATTACKING, gAiLogicData) > gBattleMons[opposingBattler].hp)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@ -802,7 +801,7 @@ static bool32 CanUseSuperEffectiveMoveAgainstOpponents(u32 battler)
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
move = gBattleMons[battler].moves[i];
|
||||
if (move == MOVE_NONE || AI_DoesChoiceItemBlockMove(battler, move))
|
||||
if (move == MOVE_NONE || AI_DoesChoiceEffectBlockMove(battler, move))
|
||||
continue;
|
||||
|
||||
if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
@ -821,7 +820,7 @@ static bool32 CanUseSuperEffectiveMoveAgainstOpponents(u32 battler)
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
move = gBattleMons[battler].moves[i];
|
||||
if (move == MOVE_NONE || AI_DoesChoiceItemBlockMove(battler, move))
|
||||
if (move == MOVE_NONE || AI_DoesChoiceEffectBlockMove(battler, move))
|
||||
continue;
|
||||
|
||||
if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
@ -1803,7 +1802,7 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler)
|
||||
|
||||
// No damage being dealt
|
||||
if ((damageTaken + statusDamage + recurringDamage <= recurringHealing) || damageTaken + statusDamage + recurringDamage == 0)
|
||||
return startingHP;
|
||||
return hitsToKO;
|
||||
|
||||
// Mon fainted to hazards
|
||||
if (startingHP == 0)
|
||||
@ -2010,6 +2009,18 @@ static inline bool32 IsFreeSwitch(enum SwitchType switchType, u32 battlerSwitchi
|
||||
|
||||
static inline bool32 CanSwitchinWin1v1(u32 hitsToKOAI, u32 hitsToKOPlayer, bool32 isSwitchinFirst, bool32 isFreeSwitch)
|
||||
{
|
||||
// Player's best move deals 0 damage
|
||||
if (hitsToKOAI == 0 && hitsToKOPlayer > 0)
|
||||
return TRUE;
|
||||
|
||||
// AI's best move deals 0 damage
|
||||
if (hitsToKOPlayer == 0 && hitsToKOAI > 0)
|
||||
return FALSE;
|
||||
|
||||
// Neither mon can damage the other
|
||||
if (hitsToKOPlayer == 0 && hitsToKOAI == 0)
|
||||
return FALSE;
|
||||
|
||||
// Free switch, need to outspeed or take 1 extra hit
|
||||
if (isFreeSwitch)
|
||||
{
|
||||
@ -2026,7 +2037,7 @@ static inline bool32 CanSwitchinWin1v1(u32 hitsToKOAI, u32 hitsToKOPlayer, bool3
|
||||
// Everything runs in the same loop to minimize computation time. This makes it harder to read, but hopefully the comments can guide you!
|
||||
static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, u32 battler, u32 opposingBattler, u32 battlerIn1, u32 battlerIn2, enum SwitchType switchType)
|
||||
{
|
||||
int revengeKillerId = PARTY_SIZE, slowRevengeKillerId = PARTY_SIZE, fastThreatenId = PARTY_SIZE, slowThreatenId = PARTY_SIZE, damageMonId = PARTY_SIZE;
|
||||
int revengeKillerId = PARTY_SIZE, slowRevengeKillerId = PARTY_SIZE, fastThreatenId = PARTY_SIZE, slowThreatenId = PARTY_SIZE, damageMonId = PARTY_SIZE, generic1v1MonId = PARTY_SIZE;
|
||||
int batonPassId = PARTY_SIZE, typeMatchupId = PARTY_SIZE, typeMatchupEffectiveId = PARTY_SIZE, defensiveMonId = PARTY_SIZE, aceMonId = PARTY_SIZE, trapperId = PARTY_SIZE;
|
||||
int i, j, aliveCount = 0, bits = 0, aceMonCount = 0;
|
||||
s32 defensiveMonHitKOThreshold = 3; // 3HKO threshold that candidate defensive mons must exceed
|
||||
@ -2071,9 +2082,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
|
||||
for (j = 0; j < MAX_MON_MOVES; j++)
|
||||
{
|
||||
aiMove = gAiLogicData->switchinCandidate.battleMon.moves[j];
|
||||
|
||||
if (aiMove != MOVE_NONE && !IsBattleMoveStatus(aiMove))
|
||||
damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, AI_ATTACKING);
|
||||
damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, AI_ATTACKING);
|
||||
|
||||
// Offensive switchin decisions are based on which whether switchin moves first and whether it can win a 1v1
|
||||
isSwitchinFirst = AI_WhoStrikesFirstPartyMon(battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, aiMove);
|
||||
@ -2104,6 +2113,9 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
|
||||
defensiveMonId = i;
|
||||
}
|
||||
|
||||
if (canSwitchinWin1v1)
|
||||
generic1v1MonId = i;
|
||||
|
||||
// Check for mon with resistance and super effective move for best type matchup mon with effective move
|
||||
if (aiMove != MOVE_NONE && !IsBattleMoveStatus(aiMove))
|
||||
{
|
||||
@ -2182,6 +2194,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
|
||||
else if (typeMatchupEffectiveId != PARTY_SIZE) return typeMatchupEffectiveId;
|
||||
else if (typeMatchupId != PARTY_SIZE) return typeMatchupId;
|
||||
else if (batonPassId != PARTY_SIZE) return batonPassId;
|
||||
else if (generic1v1MonId != PARTY_SIZE) return generic1v1MonId;
|
||||
else if (damageMonId != PARTY_SIZE) return damageMonId;
|
||||
}
|
||||
else
|
||||
@ -2192,6 +2205,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
|
||||
else if (typeMatchupId != PARTY_SIZE) return typeMatchupId;
|
||||
else if (defensiveMonId != PARTY_SIZE) return defensiveMonId;
|
||||
else if (batonPassId != PARTY_SIZE) return batonPassId;
|
||||
else if (generic1v1MonId != PARTY_SIZE) return generic1v1MonId;
|
||||
}
|
||||
// If ace mon is the last available Pokemon and U-Turn/Volt Switch or Eject Pack/Button was used - switch to the mon.
|
||||
if (aceMonId != PARTY_SIZE && CountUsablePartyMons(battler) <= aceMonCount
|
||||
|
||||
@ -4141,13 +4141,41 @@ bool32 IsRecycleEncouragedItem(u32 item)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, enum StatChange statId, bool32 considerContrary)
|
||||
static u32 GetStatBeingChanged(enum StatChange statChange)
|
||||
{
|
||||
switch(statChange)
|
||||
{
|
||||
case STAT_CHANGE_ATK:
|
||||
case STAT_CHANGE_ATK_2:
|
||||
return STAT_ATK;
|
||||
case STAT_CHANGE_DEF:
|
||||
case STAT_CHANGE_DEF_2:
|
||||
return STAT_DEF;
|
||||
case STAT_CHANGE_SPEED:
|
||||
case STAT_CHANGE_SPEED_2:
|
||||
return STAT_SPEED;
|
||||
case STAT_CHANGE_SPATK:
|
||||
case STAT_CHANGE_SPATK_2:
|
||||
return STAT_SPATK;
|
||||
case STAT_CHANGE_SPDEF:
|
||||
case STAT_CHANGE_SPDEF_2:
|
||||
return STAT_SPDEF;
|
||||
case STAT_CHANGE_ACC:
|
||||
return STAT_ACC;
|
||||
case STAT_CHANGE_EVASION:
|
||||
return STAT_EVASION;
|
||||
}
|
||||
return 0; // STAT_HP, should never be getting changed
|
||||
}
|
||||
|
||||
static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, enum StatChange statChange, bool32 considerContrary)
|
||||
{
|
||||
enum AIScore tempScore = NO_INCREASE;
|
||||
u32 noOfHitsToFaint = NoOfHitsForTargetToFaintAI(battlerDef, battlerAtk);
|
||||
u32 aiIsFaster = AI_IsFaster(battlerAtk, battlerDef, TRUE);
|
||||
u32 shouldSetUp = ((noOfHitsToFaint >= 2 && aiIsFaster) || (noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS);
|
||||
u32 i;
|
||||
u32 statId = GetStatBeingChanged(statChange);
|
||||
|
||||
if (considerContrary && gAiLogicData->abilities[battlerAtk] == ABILITY_CONTRARY)
|
||||
return NO_INCREASE;
|
||||
@ -4206,7 +4234,7 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef,
|
||||
tempScore += WEAK_EFFECT;
|
||||
}
|
||||
|
||||
switch (statId)
|
||||
switch (statChange)
|
||||
{
|
||||
case STAT_CHANGE_ATK:
|
||||
if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL) && shouldSetUp)
|
||||
@ -4269,7 +4297,7 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef,
|
||||
}
|
||||
break;
|
||||
case STAT_CHANGE_ACC:
|
||||
if (gBattleMons[battlerAtk].statStages[STAT_ACC] <= 3) // Increase only if necessary
|
||||
if (gBattleMons[battlerAtk].statStages[statId] <= 3) // Increase only if necessary
|
||||
tempScore += DECENT_EFFECT;
|
||||
break;
|
||||
case STAT_CHANGE_EVASION:
|
||||
@ -4283,14 +4311,14 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef,
|
||||
return tempScore;
|
||||
}
|
||||
|
||||
u32 IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, enum StatChange statId)
|
||||
u32 IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, enum StatChange statChange)
|
||||
{
|
||||
return IncreaseStatUpScoreInternal(battlerAtk, battlerDef, statId, TRUE);
|
||||
return IncreaseStatUpScoreInternal(battlerAtk, battlerDef, statChange, TRUE);
|
||||
}
|
||||
|
||||
u32 IncreaseStatUpScoreContrary(u32 battlerAtk, u32 battlerDef, enum StatChange statId)
|
||||
u32 IncreaseStatUpScoreContrary(u32 battlerAtk, u32 battlerDef, enum StatChange statChange)
|
||||
{
|
||||
return IncreaseStatUpScoreInternal(battlerAtk, battlerDef, statId, FALSE);
|
||||
return IncreaseStatUpScoreInternal(battlerAtk, battlerDef, statChange, FALSE);
|
||||
}
|
||||
|
||||
void IncreasePoisonScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score)
|
||||
|
||||
@ -1652,7 +1652,7 @@ static u32 GetBattlerMonData(u32 battler, struct Pokemon *party, u32 monId, u8 *
|
||||
u32 side = GetBattlerSide(battler);
|
||||
u32 partyIndex = gBattlerPartyIndexes[battler];
|
||||
if (TestRunner_Battle_GetForcedAbility(side, partyIndex))
|
||||
gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex);
|
||||
gBattleMons[battler].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
@ -2172,9 +2172,7 @@ void StartSendOutAnim(u32 battler, bool32 dontClearTransform, bool32 dontClearSu
|
||||
|
||||
ClearTemporarySpeciesSpriteData(battler, dontClearTransform, dontClearSubstituteBit);
|
||||
gBattlerPartyIndexes[battler] = gBattleResources->bufferA[battler][1];
|
||||
species = GetIllusionMonSpecies(battler);
|
||||
if (species == SPECIES_NONE)
|
||||
species = GetMonData(mon, MON_DATA_SPECIES);
|
||||
species = GetBattlerVisualSpecies(battler);
|
||||
gBattleControllerData[battler] = CreateInvisibleSpriteWithCallback(SpriteCB_WaitForBattlerBallReleaseAnim);
|
||||
// Load sprite for opponent only, player sprite is expected to be already loaded.
|
||||
if (!IsOnPlayerSide(battler))
|
||||
@ -2490,7 +2488,7 @@ void BtlController_HandleSetRawMonData(u32 battler)
|
||||
void BtlController_HandleLoadMonSprite(u32 battler, void (*controllerCallback)(u32 battler))
|
||||
{
|
||||
struct Pokemon *mon = GetBattlerMon(battler);
|
||||
u16 species = GetMonData(mon, MON_DATA_SPECIES);
|
||||
u16 species = GetBattlerVisualSpecies(battler);
|
||||
|
||||
BattleLoadMonSpriteGfx(mon, battler);
|
||||
SetMultiuseSpriteTemplateToPokemon(species, GetBattlerPosition(battler));
|
||||
@ -3153,7 +3151,7 @@ void TrySetBattlerShadowSpriteCallback(u32 battler)
|
||||
if (gSprites[gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteIdPrimary].callback == SpriteCallbackDummy
|
||||
&& (B_ENEMY_MON_SHADOW_STYLE <= GEN_3 || P_GBA_STYLE_SPECIES_GFX == TRUE
|
||||
|| gSprites[gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteIdSecondary].callback == SpriteCallbackDummy))
|
||||
SetBattlerShadowSpriteCallback(battler, GetMonData(GetBattlerMon(battler), MON_DATA_SPECIES));
|
||||
SetBattlerShadowSpriteCallback(battler, GetBattlerVisualSpecies(battler));
|
||||
}
|
||||
|
||||
bool32 TryShinyAnimAfterMonAnimUtil(u32 battler)
|
||||
@ -3256,7 +3254,7 @@ bool32 SwitchIn_TryShinyAnimUtil(u32 battler)
|
||||
DestroySprite(&gSprites[gBattleControllerData[battler]]);
|
||||
|
||||
if (GetBattlerSide(battler) == B_SIDE_OPPONENT)
|
||||
SetBattlerShadowSpriteCallback(battler, GetMonData(GetBattlerMon(battler), MON_DATA_SPECIES));
|
||||
SetBattlerShadowSpriteCallback(battler, GetBattlerVisualSpecies(battler));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -490,10 +490,16 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler)
|
||||
gBattleStruct->eventBlockCounter++;
|
||||
break;
|
||||
case FIRST_EVENT_BLOCK_GRASSY_TERRAIN_HEAL:
|
||||
if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && IsBattlerAlive(battler) && !IsBattlerAtMaxHp(battler) && IsBattlerGrounded(battler))
|
||||
if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN
|
||||
&& IsBattlerAlive(battler)
|
||||
&& !IsBattlerAtMaxHp(battler)
|
||||
&& !(gStatuses3[battler] & (STATUS3_SEMI_INVULNERABLE | STATUS3_HEAL_BLOCK))
|
||||
&& IsBattlerGrounded(battler))
|
||||
{
|
||||
gBattlerAttacker = battler;
|
||||
gBattleStruct->moveDamage[battler] = -(GetNonDynamaxMaxHP(battler) / 16);
|
||||
if (gBattleStruct->moveDamage[battler] == 0)
|
||||
gBattleStruct->moveDamage[battler] = -1;
|
||||
BattleScriptExecute(BattleScript_GrassyTerrainHeals);
|
||||
effect = TRUE;
|
||||
}
|
||||
|
||||
@ -1168,7 +1168,7 @@ void CreateEnemyShadowSprite(u32 battler)
|
||||
{
|
||||
if (B_ENEMY_MON_SHADOW_STYLE >= GEN_4 && P_GBA_STYLE_SPECIES_GFX == FALSE)
|
||||
{
|
||||
u16 species = SanitizeSpeciesId(gBattleMons[battler].species);
|
||||
u16 species = GetBattlerVisualSpecies(battler);
|
||||
u8 size = gSpeciesInfo[species].enemyShadowSize;
|
||||
|
||||
gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteIdPrimary = CreateSprite(&gSpriteTemplate_EnemyShadow,
|
||||
@ -1282,7 +1282,7 @@ void SpriteCB_EnemyShadow(struct Sprite *shadowSprite)
|
||||
}
|
||||
else if (B_ENEMY_MON_SHADOW_STYLE >= GEN_4 && P_GBA_STYLE_SPECIES_GFX == FALSE)
|
||||
{
|
||||
u16 species = SanitizeSpeciesId(gBattleMons[battler].species);
|
||||
u16 species = GetBattlerVisualSpecies(battler);
|
||||
xOffset = gSpeciesInfo[species].enemyShadowXOffset + (shadowSprite->tSpriteSide == SPRITE_SIDE_LEFT ? -16 : 16);
|
||||
yOffset = gSpeciesInfo[species].enemyShadowYOffset + 16;
|
||||
size = gSpeciesInfo[species].enemyShadowSize;
|
||||
|
||||
@ -3263,7 +3263,7 @@ void SwitchInClearSetData(u32 battler)
|
||||
u32 side = GetBattlerSide(battler);
|
||||
u32 partyIndex = gBattlerPartyIndexes[battler];
|
||||
if (TestRunner_Battle_GetForcedAbility(side, partyIndex))
|
||||
gBattleMons[i].ability = gDisableStructs[i].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex);
|
||||
gBattleMons[i].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex);
|
||||
}
|
||||
#endif // TESTING
|
||||
|
||||
@ -3474,7 +3474,7 @@ static void DoBattleIntro(void)
|
||||
u32 side = GetBattlerSide(battler);
|
||||
u32 partyIndex = gBattlerPartyIndexes[battler];
|
||||
if (TestRunner_Battle_GetForcedAbility(side, partyIndex))
|
||||
gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex);
|
||||
gBattleMons[battler].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -3770,7 +3770,7 @@ static void TryDoEventsBeforeFirstTurn(void)
|
||||
u32 side = GetBattlerSide(i);
|
||||
u32 partyIndex = gBattlerPartyIndexes[i];
|
||||
if (TestRunner_Battle_GetForcedAbility(side, partyIndex))
|
||||
gBattleMons[i].ability = gDisableStructs[i].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex);
|
||||
gBattleMons[i].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex);
|
||||
}
|
||||
}
|
||||
#endif // TESTING
|
||||
|
||||
@ -319,7 +319,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] =
|
||||
[STRINGID_PKMNENDUREDHIT] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n挺住了攻击!"),
|
||||
[STRINGID_MAGNITUDESTRENGTH] = COMPOUND_STRING("震级{B_BUFF1}!"),
|
||||
[STRINGID_PKMNCUTHPMAXEDATTACK] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n削减了体力并释放了全部力量!"),
|
||||
[STRINGID_PKMNCOPIEDSTATCHANGES] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}复制了\n{B_DEF_NAME_WITH_PREFIX2}的能力变化!"),
|
||||
[STRINGID_PKMNCOPIEDSTATCHANGES] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}复制了\n{B_DEF_NAME_WITH_PREFIX2}的能力变化!"),
|
||||
[STRINGID_PKMNGOTFREE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}摆脱了\n{B_DEF_NAME_WITH_PREFIX2}的{B_BUFF1}!"), //not in gen 5+, generic rapid spin?
|
||||
[STRINGID_PKMNSHEDLEECHSEED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}摆脱了\n寄生种子的束缚!"), //not in gen 5+, generic rapid spin?
|
||||
[STRINGID_PKMNBLEWAWAYSPIKES] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n吹飞了撒菱!"), //not in gen 5+, generic rapid spin?
|
||||
@ -629,13 +629,13 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] =
|
||||
[STRINGID_ICEBODYHPGAIN] = COMPOUND_STRING("因为{B_ATK_ABILITY},\n{B_ATK_NAME_WITH_PREFIX}回复了少许HP。"), //don't think this message is displayed anymore
|
||||
[STRINGID_SNOWWARNINGHAIL] = COMPOUND_STRING("开始下冰雹了!"),
|
||||
[STRINGID_FRISKACTIVATES] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}察觉到了\n{B_DEF_NAME_WITH_PREFIX2}的{B_LAST_ITEM}!"),
|
||||
[STRINGID_UNNERVEENTERS] = COMPOUND_STRING("{B_DEF_TEAM1}因太紧张\n而无法食用树果!"),
|
||||
[STRINGID_UNNERVEENTERS] = COMPOUND_STRING("{B_EFF_TEAM1}因太紧张\n而无法食用树果!"),
|
||||
[STRINGID_HARVESTBERRY] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n收获了{B_LAST_ITEM}!"),
|
||||
[STRINGID_MAGICBOUNCEACTIVATES] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}\n将{B_ATK_NAME_WITH_PREFIX2}反射了回去!"),
|
||||
[STRINGID_PROTEANTYPECHANGE] = COMPOUND_STRING("因为{B_ATK_ABILITY},\n{B_ATK_NAME_WITH_PREFIX}变成了{B_BUFF1}属性!"),
|
||||
[STRINGID_SYMBIOSISITEMPASS] = COMPOUND_STRING("因{B_LAST_ABILITY},{B_SCR_NAME_WITH_PREFIX}\n将{B_LAST_ITEM}传给了{B_EFF_NAME_WITH_PREFIX2}!"),
|
||||
[STRINGID_STEALTHROCKDMG] = COMPOUND_STRING("尖锐的岩石扎进了\n{B_SCR_NAME_WITH_PREFIX2}的体内!"),
|
||||
[STRINGID_TOXICSPIKESABSORBED] = COMPOUND_STRING("{B_SCR_TEAM2}脚下的\n毒菱消失不见了!"),
|
||||
[STRINGID_TOXICSPIKESABSORBED] = COMPOUND_STRING("{B_EFF_TEAM2}脚下的\n毒菱消失不见了!"),
|
||||
[STRINGID_TOXICSPIKESPOISONED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}中毒了!"),
|
||||
[STRINGID_TOXICSPIKESBADLYPOISONED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}中剧毒了!"),
|
||||
[STRINGID_STICKYWEBSWITCHIN] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}\n被黏黏网粘住了!"),
|
||||
@ -857,7 +857,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] =
|
||||
[STRINGID_SWAMPENVELOPEDSIDE] = COMPOUND_STRING("在{B_DEF_TEAM2}周围\n延伸出了湿地!"),
|
||||
[STRINGID_THESWAMPDISAPPEARED] = COMPOUND_STRING("{B_ATK_TEAM2}周围的湿地\n消失不见了!"),
|
||||
[STRINGID_PKMNTELLCHILLINGRECEPTIONJOKE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}说出了冷笑话!"),
|
||||
[STRINGID_HOSPITALITYRESTORATION] = COMPOUND_STRING("{B_ATK_PARTNER_NAME}喝光了\n{B_ATK_NAME_WITH_PREFIX2}泡的茶!"),
|
||||
[STRINGID_HOSPITALITYRESTORATION] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX}喝光了\n{B_SCR_NAME_WITH_PREFIX2}泡的茶!"),
|
||||
[STRINGID_ELECTROSHOTCHARGING] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}吸收了电力!"),
|
||||
[STRINGID_ITEMWASUSEDUP] = COMPOUND_STRING("{B_LAST_ITEM}已完成使命,\n消失了……"),
|
||||
[STRINGID_ATTACKERLOSTITSTYPE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}失去了\n{B_BUFF1}属性!"),
|
||||
@ -1205,7 +1205,8 @@ const u16 gGotBurnedStringIds[] =
|
||||
|
||||
const u16 gGotFrostbiteStringIds[] =
|
||||
{
|
||||
[B_MSG_STATUSED] = STRINGID_PKMNGOTFROSTBITE
|
||||
[B_MSG_STATUSED] = STRINGID_PKMNGOTFROSTBITE,
|
||||
[B_MSG_STATUSED_BY_ABILITY] = STRINGID_PKMNGOTFROSTBITE,
|
||||
};
|
||||
|
||||
const u16 gFrostbiteHealedStringIds[] =
|
||||
@ -3110,14 +3111,14 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize)
|
||||
else
|
||||
toCpy = sText_Opposing2;
|
||||
break;
|
||||
case B_TXT_SCR_TEAM1:
|
||||
if (IsOnPlayerSide(gBattleScripting.battler))
|
||||
case B_TXT_EFF_TEAM1:
|
||||
if (IsOnPlayerSide(gEffectBattler))
|
||||
toCpy = sText_Your1;
|
||||
else
|
||||
toCpy = sText_Opposing1;
|
||||
break;
|
||||
case B_TXT_SCR_TEAM2:
|
||||
if (IsOnPlayerSide(gBattleScripting.battler))
|
||||
case B_TXT_EFF_TEAM2:
|
||||
if (IsOnPlayerSide(gEffectBattler))
|
||||
toCpy = sText_Your2;
|
||||
else
|
||||
toCpy = sText_Opposing2;
|
||||
@ -3184,7 +3185,7 @@ static void IllusionNickHack(u32 battler, u32 partyId, u8 *dst)
|
||||
else
|
||||
partnerMon = mon;
|
||||
|
||||
id = GetIllusionMonPartyId(gEnemyParty, mon, partnerMon);
|
||||
id = GetIllusionMonPartyId(gEnemyParty, mon, partnerMon, battler);
|
||||
}
|
||||
|
||||
if (id != PARTY_SIZE)
|
||||
|
||||
@ -964,8 +964,6 @@ static const u16 sProtectSuccessRates[] = {USHRT_MAX, USHRT_MAX / 2, USHRT_MAX /
|
||||
|
||||
static const u16 sFinalStrikeOnlyEffects[] =
|
||||
{
|
||||
MOVE_EFFECT_BUG_BITE,
|
||||
MOVE_EFFECT_STEAL_ITEM,
|
||||
MOVE_EFFECT_REMOVE_ARG_TYPE,
|
||||
MOVE_EFFECT_REMOVE_STATUS,
|
||||
MOVE_EFFECT_RECOIL_HP_25,
|
||||
@ -2749,6 +2747,14 @@ static void Cmd_datahpupdate(void)
|
||||
&& GetMoveCategory(gCurrentMove) != DAMAGE_CATEGORY_STATUS
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget))
|
||||
gBattleStruct->timesGotHit[GetBattlerSide(gBattlerTarget)][gBattlerPartyIndexes[gBattlerTarget]]++;
|
||||
|
||||
if (GetMoveEffect(gCurrentMove) == EFFECT_KNOCK_OFF
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& gBattleMons[gBattlerTarget].item != 0
|
||||
&& !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove)
|
||||
&& CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerTarget].item)
|
||||
&& !NoAliveMonsForEitherParty())
|
||||
gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = TRUE;
|
||||
}
|
||||
|
||||
TryRestoreDamageAfterCheekPouch(battler);
|
||||
@ -3132,7 +3138,7 @@ void StealTargetItem(u8 battlerStealer, u8 battlerItem)
|
||||
|
||||
if (B_STEAL_WILD_ITEMS >= GEN_9
|
||||
&& !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE))
|
||||
&& MoveHasAdditionalEffect(gCurrentMove, MOVE_EFFECT_STEAL_ITEM)
|
||||
&& GetMoveEffect(gCurrentMove) == EFFECT_STEAL_ITEM
|
||||
&& battlerStealer == gBattlerAttacker) // ensure that Pickpocket isn't activating this
|
||||
{
|
||||
AddBagItem(gLastUsedItem, 1);
|
||||
@ -3289,10 +3295,8 @@ void SetMoveEffect(bool32 primary, bool32 certain)
|
||||
switch (gBattleScripting.moveEffect) // Set move effects which happen later on
|
||||
{
|
||||
case MOVE_EFFECT_STEALTH_ROCK:
|
||||
case MOVE_EFFECT_SPIKES:
|
||||
case MOVE_EFFECT_PAYDAY:
|
||||
case MOVE_EFFECT_BUG_BITE:
|
||||
case MOVE_EFFECT_STEAL_ITEM:
|
||||
activateAfterFaint = TRUE;
|
||||
break;
|
||||
}
|
||||
@ -3470,6 +3474,26 @@ void SetMoveEffect(bool32 primary, bool32 certain)
|
||||
}
|
||||
gBattlescriptCurrInstr++;
|
||||
break;
|
||||
case MOVE_EFFECT_BUG_BITE:
|
||||
if (GetBattlerHoldEffect(gEffectBattler, TRUE) == HOLD_EFFECT_JABOCA_BERRY)
|
||||
{
|
||||
// jaboca berry triggers instead of being stolen
|
||||
gBattlescriptCurrInstr++;
|
||||
}
|
||||
else if (GetItemPocket(gBattleMons[gEffectBattler].item) == POCKET_BERRIES
|
||||
&& battlerAbility != ABILITY_STICKY_HOLD)
|
||||
{
|
||||
// target loses their berry
|
||||
gLastUsedItem = gBattleMons[gEffectBattler].item;
|
||||
gBattleMons[gEffectBattler].item = 0;
|
||||
CheckSetUnburden(gEffectBattler);
|
||||
|
||||
BtlController_EmitSetMonData(gEffectBattler, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gEffectBattler].item), &gBattleMons[gEffectBattler].item);
|
||||
MarkBattlerForControllerExec(gEffectBattler);
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEffectBugBite;
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_TRI_ATTACK:
|
||||
if (gBattleMons[gEffectBattler].status1)
|
||||
{
|
||||
@ -3638,35 +3662,6 @@ void SetMoveEffect(bool32 primary, bool32 certain)
|
||||
gBattleMons[gBattlerAttacker].status2 |= STATUS2_RAGE;
|
||||
gBattlescriptCurrInstr++;
|
||||
break;
|
||||
case MOVE_EFFECT_STEAL_ITEM:
|
||||
if (!CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item)
|
||||
|| gBattleMons[gBattlerAttacker].item != ITEM_NONE
|
||||
|| gBattleMons[gBattlerTarget].item == ITEM_NONE)
|
||||
{
|
||||
gBattlescriptCurrInstr++;
|
||||
}
|
||||
else if (GetBattlerAbility(gBattlerTarget) == ABILITY_STICKY_HOLD)
|
||||
{
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_NoItemSteal;
|
||||
|
||||
gLastUsedAbility = gBattleMons[gBattlerTarget].ability;
|
||||
RecordAbilityBattle(gBattlerTarget, gLastUsedAbility);
|
||||
}
|
||||
else
|
||||
{
|
||||
StealTargetItem(gBattlerAttacker, gBattlerTarget); // Attacker steals target item
|
||||
|
||||
if (!(B_STEAL_WILD_ITEMS >= GEN_9
|
||||
&& !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE))))
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].item = ITEM_NONE; // Item assigned later on with thief (see MOVEEND_CHANGED_ITEMS)
|
||||
gBattleStruct->changedItems[gBattlerAttacker] = gLastUsedItem; // Stolen item to be assigned later
|
||||
}
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_ItemSteal;
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_PREVENT_ESCAPE:
|
||||
gBattleMons[gBattlerTarget].status2 |= STATUS2_ESCAPE_PREVENTION;
|
||||
gDisableStructs[gBattlerTarget].battlerPreventingEscape = gBattlerAttacker;
|
||||
@ -3802,26 +3797,6 @@ void SetMoveEffect(bool32 primary, bool32 certain)
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEffectIncinerate;
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_BUG_BITE:
|
||||
if (GetBattlerHoldEffect(gEffectBattler, TRUE) == HOLD_EFFECT_JABOCA_BERRY)
|
||||
{
|
||||
// jaboca berry triggers instead of being stolen
|
||||
gBattlescriptCurrInstr++;
|
||||
}
|
||||
else if (GetItemPocket(gBattleMons[gEffectBattler].item) == POCKET_BERRIES
|
||||
&& battlerAbility != ABILITY_STICKY_HOLD)
|
||||
{
|
||||
// target loses their berry
|
||||
gLastUsedItem = gBattleMons[gEffectBattler].item;
|
||||
gBattleMons[gEffectBattler].item = 0;
|
||||
CheckSetUnburden(gEffectBattler);
|
||||
|
||||
BtlController_EmitSetMonData(gEffectBattler, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gEffectBattler].item), &gBattleMons[gEffectBattler].item);
|
||||
MarkBattlerForControllerExec(gEffectBattler);
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEffectBugBite;
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_TRAP_BOTH:
|
||||
if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_ESCAPE_PREVENTION) && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_ESCAPE_PREVENTION))
|
||||
{
|
||||
@ -3877,18 +3852,6 @@ void SetMoveEffect(bool32 primary, bool32 certain)
|
||||
gBattlescriptCurrInstr = BattleScript_StealthRockActivates;
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_SPIKES:
|
||||
if (gSideTimers[GetBattlerSide(gEffectBattler)].spikesAmount < 3)
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SPIKESSCATTERED;
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
|
||||
if (gBattleStruct->isSkyBattle)
|
||||
gBattlescriptCurrInstr++;
|
||||
else
|
||||
gBattlescriptCurrInstr = BattleScript_SpikesActivates;
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_SYRUP_BOMB:
|
||||
if (!(gStatuses4[gEffectBattler] & STATUS4_SYRUP_BOMB))
|
||||
{
|
||||
@ -6073,47 +6036,6 @@ static void Cmd_playstatchangeanimation(void)
|
||||
}
|
||||
}
|
||||
|
||||
static bool32 TryKnockOffBattleScript(u32 battlerDef)
|
||||
{
|
||||
if (gBattleMons[battlerDef].item != 0
|
||||
&& CanBattlerGetOrLoseItem(battlerDef, gBattleMons[battlerDef].item)
|
||||
&& !NoAliveMonsForEitherParty())
|
||||
{
|
||||
if (GetBattlerAbility(battlerDef) == ABILITY_STICKY_HOLD && IsBattlerAlive(battlerDef))
|
||||
{
|
||||
gBattlerAbility = battlerDef;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_StickyHoldActivates;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 side = GetBattlerSide(battlerDef);
|
||||
|
||||
gLastUsedItem = gBattleMons[battlerDef].item;
|
||||
gBattleMons[battlerDef].item = 0;
|
||||
if (gBattleMons[battlerDef].ability != ABILITY_GORILLA_TACTICS)
|
||||
gBattleStruct->choicedMove[battlerDef] = 0;
|
||||
CheckSetUnburden(battlerDef);
|
||||
|
||||
// In Gen 5+, Knock Off removes the target's item rather than rendering it unusable.
|
||||
if (B_KNOCK_OFF_REMOVAL >= GEN_5)
|
||||
{
|
||||
BtlController_EmitSetMonData(battlerDef, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[battlerDef].item), &gBattleMons[battlerDef].item);
|
||||
MarkBattlerForControllerExec(battlerDef);
|
||||
}
|
||||
else
|
||||
{
|
||||
gWishFutureKnock.knockedOffMons[side] |= 1u << gBattlerPartyIndexes[battlerDef];
|
||||
}
|
||||
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_KnockedOff;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline bool32 TryTriggerSymbiosis(u32 battler, u32 ally)
|
||||
{
|
||||
return GetBattlerAbility(ally) == ABILITY_SYMBIOSIS
|
||||
@ -6323,6 +6245,233 @@ static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move
|
||||
return effect;
|
||||
}
|
||||
|
||||
static bool32 HandleMoveEndMoveBlock(u32 moveEffect)
|
||||
{
|
||||
if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
return FALSE;
|
||||
|
||||
u32 effect = FALSE;
|
||||
switch (moveEffect)
|
||||
{
|
||||
case EFFECT_KNOCK_OFF:
|
||||
if (gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff && IsBattlerAlive(gBattlerAttacker))
|
||||
{
|
||||
u32 side = GetBattlerSide(gBattlerTarget);
|
||||
gLastUsedItem = gBattleMons[gBattlerTarget].item;
|
||||
gBattleMons[gBattlerTarget].item = 0;
|
||||
if (gBattleMons[gBattlerTarget].ability != ABILITY_GORILLA_TACTICS)
|
||||
gBattleStruct->choicedMove[gBattlerTarget] = 0;
|
||||
CheckSetUnburden(gBattlerTarget);
|
||||
|
||||
// In Gen 5+, Knock Off removes the target's item rather than rendering it unusable.
|
||||
if (B_KNOCK_OFF_REMOVAL >= GEN_5)
|
||||
{
|
||||
BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].item), &gBattleMons[gBattlerTarget].item);
|
||||
MarkBattlerForControllerExec(gBattlerTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
gWishFutureKnock.knockedOffMons[side] |= 1u << gBattlerPartyIndexes[gBattlerTarget];
|
||||
}
|
||||
|
||||
gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = FALSE;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_KnockedOff;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_STEAL_ITEM:
|
||||
if (!CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item)
|
||||
|| gBattleMons[gBattlerAttacker].item != ITEM_NONE
|
||||
|| gBattleMons[gBattlerTarget].item == ITEM_NONE
|
||||
|| !IsBattlerAlive(gBattlerAttacker)
|
||||
|| !IsBattlerTurnDamaged(gBattlerTarget))
|
||||
{
|
||||
effect = FALSE;
|
||||
}
|
||||
else if (GetBattlerAbility(gBattlerTarget) == ABILITY_STICKY_HOLD)
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_NoItemSteal;
|
||||
|
||||
gLastUsedAbility = gBattleMons[gBattlerTarget].ability;
|
||||
RecordAbilityBattle(gBattlerTarget, gLastUsedAbility);
|
||||
effect = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
StealTargetItem(gBattlerAttacker, gBattlerTarget); // Attacker steals target item
|
||||
|
||||
if (!(B_STEAL_WILD_ITEMS >= GEN_9
|
||||
&& !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE))))
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].item = ITEM_NONE; // Item assigned later on with thief (see MOVEEND_CHANGED_ITEMS)
|
||||
gBattleStruct->changedItems[gBattlerAttacker] = gLastUsedItem; // Stolen item to be assigned later
|
||||
}
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_ItemSteal;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_HIT_SWITCH_TARGET:
|
||||
if (IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& IsBattlerAlive(gBattlerTarget)
|
||||
&& IsBattlerAlive(gBattlerAttacker)
|
||||
&& !(gStatuses3[BATTLE_PARTNER(gBattlerTarget)] & STATUS3_COMMANDER))
|
||||
{
|
||||
u32 targetAbility = GetBattlerAbility(gBattlerTarget);
|
||||
if (targetAbility == ABILITY_GUARD_DOG)
|
||||
return FALSE;
|
||||
|
||||
BattleScriptPushCursor();
|
||||
if (targetAbility == ABILITY_SUCTION_CUPS)
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_AbilityPreventsPhasingOutRet;
|
||||
}
|
||||
else if (gStatuses3[gBattlerTarget] & STATUS3_ROOTED)
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_PrintMonIsRootedRet;
|
||||
}
|
||||
else if (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_HitSwitchTargetDynamaxed;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleScripting.switchCase = B_SWITCH_HIT;
|
||||
gBattlescriptCurrInstr = BattleScript_TryHitSwitchTarget;
|
||||
}
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_SMACK_DOWN:
|
||||
if (!IsBattlerGrounded(gBattlerTarget)
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& IsBattlerAlive(gBattlerTarget)
|
||||
&& !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove))
|
||||
{
|
||||
gStatuses3[gBattlerTarget] |= STATUS3_SMACKED_DOWN;
|
||||
gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR);
|
||||
BattleScriptPush(gBattlescriptCurrInstr);
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEffectSmackDown;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_RECOIL_IF_MISS:
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& (!IsBattlerTurnDamaged(gBattlerTarget) || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)
|
||||
&& !gBattleStruct->noTargetPresent)
|
||||
{
|
||||
if (B_RECOIL_IF_MISS_DMG >= GEN_5 || (B_CRASH_IF_TARGET_IMMUNE == GEN_4 && gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_DOESNT_AFFECT_FOE))
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2;
|
||||
else if (B_RECOIL_IF_MISS_DMG == GEN_4 && (GetNonDynamaxMaxHP(gBattlerTarget) / 2) < gBattleStruct->moveDamage[gBattlerTarget])
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerTarget) / 2;
|
||||
else // Fallback if B_RECOIL_IF_MISS_DMG is set to gen3 or lower.
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerTarget) / 2;
|
||||
|
||||
if (gBattleStruct->moveDamage[gBattlerAttacker] == 0)
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = 1;
|
||||
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_RecoilIfMiss;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_RECOIL:
|
||||
if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker))
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = max(1, gBattleScripting.savedDmg * max(1, GetMoveRecoil(gCurrentMove)) / 100);
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_EXPLOSION:
|
||||
if (!IsAbilityOnField(ABILITY_DAMP))
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = 0;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_FaintAttackerForExplosion;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_MAX_HP_50_RECOIL:
|
||||
case EFFECT_MIND_BLOWN:
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_FAILED)
|
||||
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD)
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_MaxHp50Recoil;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_CHLOROBLAST:
|
||||
if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker))
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_RAPID_SPIN:
|
||||
if (IsBattlerTurnDamaged(gBattlerTarget))
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_RapidSpinAway;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_FELL_STINGER:
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& !IsBattlerAlive(gBattlerTarget)
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& !NoAliveMonsForEitherParty()
|
||||
&& CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
SET_STATCHANGER(STAT_ATK, GetGenConfig(GEN_CONFIG_FELL_STINGER_STAT_RAISE) >= GEN_7 ? 3 : 2, FALSE);
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK);
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_FellStingerRaisesStat;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_STONE_AXE:
|
||||
if (!(gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_STEALTH_ROCK) && IsBattlerAlive(gBattlerAttacker))
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_POINTEDSTONESFLOAT;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_StealthRockActivates;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_CEASELESS_EDGE:
|
||||
if (gSideTimers[GetBattlerSide(gBattlerTarget)].spikesAmount < 3 && IsBattlerAlive(gBattlerAttacker))
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SPIKESSCATTERED;
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
if (gBattleStruct->isSkyBattle)
|
||||
{
|
||||
effect = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_SpikesActivates;
|
||||
effect = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
effect = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
static void Cmd_moveend(void)
|
||||
{
|
||||
CMD_ARGS(u8 endMode, u8 endState);
|
||||
@ -6587,72 +6736,6 @@ static void Cmd_moveend(void)
|
||||
}
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_FIRST_MOVE_BLOCK:
|
||||
if ((gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT && IsBattlerAlive(gBattlerTarget))
|
||||
|| gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT
|
||||
|| gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
{
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (moveEffect)
|
||||
{
|
||||
case EFFECT_KNOCK_OFF:
|
||||
if (!DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove))
|
||||
effect = TryKnockOffBattleScript(gBattlerTarget);
|
||||
break;
|
||||
case EFFECT_HIT_SWITCH_TARGET:
|
||||
if (IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& IsBattlerAlive(gBattlerTarget)
|
||||
&& IsBattlerAlive(gBattlerAttacker)
|
||||
&& !(gStatuses3[BATTLE_PARTNER(gBattlerTarget)] & STATUS3_COMMANDER))
|
||||
{
|
||||
u32 targetAbility = GetBattlerAbility(gBattlerTarget);
|
||||
if (targetAbility == ABILITY_GUARD_DOG)
|
||||
{
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
}
|
||||
|
||||
effect = TRUE;
|
||||
BattleScriptPushCursor();
|
||||
if (targetAbility == ABILITY_SUCTION_CUPS)
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_AbilityPreventsPhasingOutRet;
|
||||
}
|
||||
else if (gStatuses3[gBattlerTarget] & STATUS3_ROOTED)
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_PrintMonIsRootedRet;
|
||||
}
|
||||
else if (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_HitSwitchTargetDynamaxed;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleScripting.switchCase = B_SWITCH_HIT;
|
||||
gBattlescriptCurrInstr = BattleScript_TryHitSwitchTarget;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EFFECT_SMACK_DOWN:
|
||||
if (!IsBattlerGrounded(gBattlerTarget)
|
||||
&& IsBattlerAlive(gBattlerTarget)
|
||||
&& !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove))
|
||||
{
|
||||
gStatuses3[gBattlerTarget] |= STATUS3_SMACKED_DOWN;
|
||||
gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR);
|
||||
effect = TRUE;
|
||||
BattleScriptPush(gBattlescriptCurrInstr);
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEffectSmackDown;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_ITEM_EFFECTS_ALL: // item effects for all battlers
|
||||
if (ItemBattleEffects(ITEMEFFECT_MOVE_END, 0, FALSE))
|
||||
effect = TRUE;
|
||||
@ -6992,99 +7075,8 @@ static void Cmd_moveend(void)
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
}
|
||||
case MOVEEND_SECOND_MOVE_BLOCK:
|
||||
if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
{
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (moveEffect)
|
||||
{
|
||||
case EFFECT_RECOIL_IF_MISS:
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& (!IsBattlerTurnDamaged(gBattlerTarget) || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)
|
||||
&& !gBattleStruct->noTargetPresent)
|
||||
{
|
||||
if (B_RECOIL_IF_MISS_DMG >= GEN_5 || (B_CRASH_IF_TARGET_IMMUNE == GEN_4 && gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_DOESNT_AFFECT_FOE))
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2;
|
||||
else if (B_RECOIL_IF_MISS_DMG == GEN_4 && (GetNonDynamaxMaxHP(gBattlerTarget) / 2) < gBattleStruct->moveDamage[gBattlerTarget])
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerTarget) / 2;
|
||||
else // Fallback if B_RECOIL_IF_MISS_DMG is set to gen3 or lower.
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerTarget) / 2;
|
||||
|
||||
if (gBattleStruct->moveDamage[gBattlerAttacker] == 0)
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = 1;
|
||||
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_RecoilIfMiss;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_RECOIL:
|
||||
if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker))
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = max(1, gBattleStruct->moveDamage[gBattlerTarget] * max(1, GetMoveRecoil(gCurrentMove)) / 100);
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_EXPLOSION:
|
||||
if (!IsAbilityOnField(ABILITY_DAMP))
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = 0;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_FaintAttackerForExplosion;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_MAX_HP_50_RECOIL:
|
||||
case EFFECT_MIND_BLOWN:
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_FAILED)
|
||||
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD)
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_MaxHp50Recoil;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_CHLOROBLAST:
|
||||
if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker))
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_RAPID_SPIN:
|
||||
if (IsBattlerTurnDamaged(gBattlerTarget))
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_RapidSpinAway;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_FELL_STINGER:
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& !IsBattlerAlive(gBattlerTarget)
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& !NoAliveMonsForEitherParty()
|
||||
&& CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
SET_STATCHANGER(STAT_ATK, GetGenConfig(GEN_CONFIG_FELL_STINGER_STAT_RAISE) >= GEN_7 ? 3 : 2, FALSE);
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK);
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_FellStingerRaisesStat;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case MOVEEND_MOVE_BLOCK:
|
||||
effect = HandleMoveEndMoveBlock(moveEffect);
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_ITEM_EFFECTS_ATTACKER:
|
||||
@ -7378,7 +7370,9 @@ static void Cmd_moveend(void)
|
||||
switch (moveEffect)
|
||||
{
|
||||
case EFFECT_ICE_SPINNER:
|
||||
if (IsBattlerAlive(gBattlerAttacker) && IsBattlerTurnDamaged(gBattlerTarget))
|
||||
if (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY
|
||||
&& IsBattlerAlive(gBattlerAttacker)
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget))
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_RemoveTerrain;
|
||||
@ -8331,7 +8325,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler)
|
||||
{
|
||||
gSideStatuses[GetBattlerSide(battler)] &= ~SIDE_STATUS_TOXIC_SPIKES;
|
||||
gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount = 0;
|
||||
gBattleScripting.battler = battler;
|
||||
gEffectBattler = battler;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_ToxicSpikesAbsorbed;
|
||||
}
|
||||
@ -17883,9 +17877,14 @@ void BS_TryGulpMissile(void)
|
||||
&& (gCurrentMove == MOVE_DIVE)
|
||||
&& (GetBattlerAbility(gBattlerAttacker) == ABILITY_GULP_MISSILE)
|
||||
&& TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT))
|
||||
{
|
||||
gBattleScripting.battler = gBattlerAttacker;
|
||||
gBattlescriptCurrInstr = BattleScript_GulpMissileFormChange;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
}
|
||||
|
||||
void BS_TryActivateGulpMissile(void)
|
||||
|
||||
@ -839,10 +839,6 @@ static void AddMovePoints(u8 caseId, u16 arg1, u8 arg2, u8 arg3)
|
||||
const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i);
|
||||
switch (additionalEffect->moveEffect)
|
||||
{
|
||||
case MOVE_EFFECT_STEAL_ITEM:
|
||||
if ((additionalEffect->chance == 100 || additionalEffect->chance == 0))
|
||||
baseFromEffect += 3;
|
||||
break;
|
||||
case MOVE_EFFECT_THRASH:
|
||||
if (additionalEffect->self == TRUE)
|
||||
baseFromEffect += 3;
|
||||
|
||||
@ -1821,7 +1821,8 @@ static inline bool32 TryFormChangeBeforeMove(void)
|
||||
return FALSE;
|
||||
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_AttackerFormChange;
|
||||
gBattleScripting.battler = gBattlerAttacker;
|
||||
gBattlescriptCurrInstr = BattleScript_BattlerFormChange;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -3515,6 +3516,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
&& gBattleStruct->illusion[diagonalBattler].state != ILLUSION_ON
|
||||
&& !(gStatuses3[diagonalBattler] & STATUS3_SEMI_INVULNERABLE_NO_COMMANDER))
|
||||
{
|
||||
SaveBattlerAttacker(gBattlerAttacker);
|
||||
SaveBattlerTarget(gBattlerTarget);
|
||||
gBattlerAttacker = battler;
|
||||
gBattlerTarget = diagonalBattler;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_ImposterActivates);
|
||||
@ -3562,7 +3565,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
case ABILITY_UNNERVE:
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone && !gDisableStructs[battler].unnerveActivated)
|
||||
{
|
||||
gBattlerTarget = GetOppositeBattler(battler);
|
||||
gEffectBattler = GetOppositeBattler(battler);
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_UNNERVE;
|
||||
gDisableStructs[battler].unnerveActivated = TRUE;
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
@ -3574,7 +3577,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
case ABILITY_AS_ONE_SHADOW_RIDER:
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone && !gDisableStructs[battler].unnerveActivated)
|
||||
{
|
||||
gBattlerTarget = GetOppositeBattler(battler);
|
||||
gEffectBattler = GetOppositeBattler(battler);
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_ASONE;
|
||||
gDisableStructs[battler].unnerveActivated = TRUE;
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
@ -3596,6 +3599,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
case ABILITY_PASTEL_VEIL:
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone)
|
||||
{
|
||||
SaveBattlerTarget(gBattlerTarget);
|
||||
gBattlerTarget = battler;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_PASTEL_VEIL;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_PastelVeilActivates);
|
||||
@ -3635,7 +3639,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone)
|
||||
{
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
gBattleScripting.battler = battler;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_FriskActivates); // Try activate
|
||||
effect++;
|
||||
}
|
||||
@ -3680,6 +3683,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
SET_STATCHANGER(statId, 1, FALSE);
|
||||
SaveBattlerAttacker(gBattlerAttacker);
|
||||
gBattlerAttacker = battler;
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId);
|
||||
BattleScriptPushCursorAndCallback(BattleScript_AttackerAbilityStatRaiseEnd3);
|
||||
@ -3830,6 +3834,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
case ABILITY_INTIMIDATE:
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone)
|
||||
{
|
||||
SaveBattlerAttacker(gBattlerAttacker);
|
||||
gBattlerAttacker = battler;
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
SET_STATCHANGER(STAT_ATK, 1, TRUE);
|
||||
@ -3841,6 +3846,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone
|
||||
&& !gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].supersweetSyrup)
|
||||
{
|
||||
SaveBattlerAttacker(gBattlerAttacker);
|
||||
gBattlerAttacker = battler;
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].supersweetSyrup = TRUE;
|
||||
@ -3865,6 +3871,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
BattleScriptPushCursorAndCallback(BattleScript_ActivateTeraformZero);
|
||||
effect++;
|
||||
}
|
||||
break;
|
||||
case ABILITY_SCHOOLING:
|
||||
if (gBattleMons[battler].level < 20)
|
||||
break;
|
||||
@ -3873,8 +3880,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
case ABILITY_SHIELDS_DOWN:
|
||||
if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_HP_PERCENT))
|
||||
{
|
||||
gBattlerAttacker = battler;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3);
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeEnd3);
|
||||
effect++;
|
||||
}
|
||||
break;
|
||||
@ -4002,10 +4008,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
&& CountBattlerStatIncreases(BATTLE_PARTNER(battler), FALSE))
|
||||
{
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
gBattlerAttacker = gBattlerAbility = battler;
|
||||
for (i = 0; i < NUM_BATTLE_STATS; i++)
|
||||
gBattleMons[battler].statStages[i] = gBattleMons[BATTLE_PARTNER(battler)].statStages[i];
|
||||
gBattleScripting.battler = BATTLE_PARTNER(battler);
|
||||
gEffectBattler = BATTLE_PARTNER(battler);
|
||||
BattleScriptPushCursorAndCallback(BattleScript_CostarActivates);
|
||||
effect++;
|
||||
}
|
||||
@ -4033,8 +4038,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
&& gBattleMons[partner].hp < gBattleMons[partner].maxHP
|
||||
&& IsBattlerAlive(partner))
|
||||
{
|
||||
gBattlerTarget = partner;
|
||||
gBattlerAttacker = battler;
|
||||
gEffectBattler = partner;
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
gBattleStruct->moveDamage[partner] = (GetNonDynamaxMaxHP(partner) / 4) * -1;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_HospitalityActivates);
|
||||
@ -4074,10 +4078,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
&& gBattleMons[battler].species == SPECIES_TERAPAGOS_NORMAL
|
||||
&& TryBattleFormChange(battler, FORM_CHANGE_BATTLE_SWITCH))
|
||||
{
|
||||
gBattlerAttacker = battler;
|
||||
gBattleScripting.abilityPopupOverwrite = gLastUsedAbility = ABILITY_TERA_SHIFT;
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeWithStringEnd3);
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3);
|
||||
effect++;
|
||||
}
|
||||
break;
|
||||
@ -4296,8 +4299,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
case ABILITY_SHIELDS_DOWN:
|
||||
if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_HP_PERCENT))
|
||||
{
|
||||
gBattlerAttacker = battler;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3);
|
||||
gBattleScripting.battler = battler;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeEnd3);
|
||||
effect++;
|
||||
}
|
||||
break;
|
||||
@ -4328,8 +4331,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
&& GetActiveGimmick(battler) != GIMMICK_TERA
|
||||
&& TryBattleFormChange(battler, FORM_CHANGE_BATTLE_TURN_END))
|
||||
{
|
||||
gBattlerAttacker = battler;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3NoPopup);
|
||||
gBattleScripting.battler = battler;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeEnd3NoPopup);
|
||||
effect++;
|
||||
}
|
||||
break;
|
||||
@ -4354,6 +4357,16 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
case ABILITYEFFECT_MOVE_END: // Think contact abilities.
|
||||
switch (gLastUsedAbility)
|
||||
{
|
||||
case ABILITY_STICKY_HOLD:
|
||||
if (gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff && IsBattlerAlive(gBattlerTarget))
|
||||
{
|
||||
gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = FALSE;
|
||||
gBattlerAbility = gBattlerTarget;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_StickyHoldActivates;
|
||||
effect++;
|
||||
}
|
||||
break;
|
||||
case ABILITY_JUSTIFIED:
|
||||
if (!(gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_NO_EFFECT)
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
@ -4969,8 +4982,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
&& ((gCurrentMove == MOVE_SURF && IsBattlerTurnDamaged(gBattlerTarget)) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER)
|
||||
&& TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT))
|
||||
{
|
||||
gBattleScripting.battler = gBattlerAttacker;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_AttackerFormChange;
|
||||
gBattlescriptCurrInstr = BattleScript_BattlerFormChange;
|
||||
effect++;
|
||||
}
|
||||
break;
|
||||
@ -7045,6 +7059,12 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn)
|
||||
case ITEMEFFECT_MOVE_END:
|
||||
for (battler = 0; battler < gBattlersCount; battler++)
|
||||
{
|
||||
// If item can be knocked off berry activation will be blocked, but not other items
|
||||
if (gBattleStruct->battlerState[battler].itemCanBeKnockedOff
|
||||
&& (GetItemPocket(gBattleMons[battler].item) == POCKET_BERRIES
|
||||
|| GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_RESTORE_HP))
|
||||
continue;
|
||||
|
||||
gLastUsedItem = gBattleMons[battler].item;
|
||||
effect = ItemEffectMoveEnd(battler, GetBattlerHoldEffect(battler, TRUE));
|
||||
if (effect)
|
||||
@ -10373,11 +10393,29 @@ u32 GetIllusionMonSpecies(u32 battler)
|
||||
return SPECIES_NONE;
|
||||
}
|
||||
|
||||
u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon)
|
||||
u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon, u32 battler)
|
||||
{
|
||||
s32 id;
|
||||
s32 partyEnd=6;
|
||||
s32 partyStart=0;
|
||||
|
||||
// Adjust party search range for Multibattles and Player vs two-trainers
|
||||
if((GetBattlerSide(battler) == B_SIDE_PLAYER && (gBattleTypeFlags & BATTLE_TYPE_MULTI))
|
||||
|| (GetBattlerSide(battler) == B_SIDE_OPPONENT && (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)))
|
||||
{
|
||||
if((GetBattlerPosition(battler) == B_POSITION_PLAYER_LEFT) || (GetBattlerPosition(battler) == B_POSITION_OPPONENT_LEFT))
|
||||
{
|
||||
partyEnd = 3;
|
||||
partyStart = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
partyEnd = 6;
|
||||
partyStart = 3;
|
||||
}
|
||||
}
|
||||
|
||||
// Find last alive non-egg pokemon.
|
||||
for (id = PARTY_SIZE - 1; id >= 0; id--)
|
||||
for (s32 id = partyEnd - 1; id >= partyStart; id--)
|
||||
{
|
||||
if (GetMonData(&party[id], MON_DATA_SANITY_HAS_SPECIES)
|
||||
&& GetMonData(&party[id], MON_DATA_HP)
|
||||
@ -10411,7 +10449,7 @@ bool32 SetIllusionMon(struct Pokemon *mon, u32 battler)
|
||||
else
|
||||
partnerMon = mon;
|
||||
|
||||
id = GetIllusionMonPartyId(party, mon, partnerMon);
|
||||
id = GetIllusionMonPartyId(party, mon, partnerMon, battler);
|
||||
if (id != PARTY_SIZE)
|
||||
{
|
||||
gBattleStruct->illusion[battler].state = ILLUSION_ON;
|
||||
|
||||
@ -992,6 +992,12 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
|
||||
.battleTvScore = 2,
|
||||
},
|
||||
|
||||
[EFFECT_STEAL_ITEM] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectHit,
|
||||
.battleTvScore = 3,
|
||||
},
|
||||
|
||||
[EFFECT_ENDEAVOR] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectEndeavor,
|
||||
@ -2230,4 +2236,16 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
|
||||
.battleScript = BattleScript_EffectSteelRoller,
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
|
||||
[EFFECT_STONE_AXE] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectHit,
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
|
||||
[EFFECT_CEASELESS_EDGE] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectHit,
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
};
|
||||
|
||||
@ -4419,7 +4419,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.description = COMPOUND_STRING(
|
||||
"攻击时盗取道具。当自己\n"
|
||||
"携带道具时,不会去盗取。"),
|
||||
.effect = EFFECT_HIT,
|
||||
.effect = EFFECT_STEAL_ITEM,
|
||||
.power = B_UPDATED_MOVE_DATA >= GEN_6 ? 60 : 40,
|
||||
.type = TYPE_DARK,
|
||||
.accuracy = 100,
|
||||
@ -4428,9 +4428,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.priority = 0,
|
||||
.category = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.makesContact = TRUE,
|
||||
.additionalEffects = ADDITIONAL_EFFECTS({
|
||||
.moveEffect = MOVE_EFFECT_STEAL_ITEM,
|
||||
}),
|
||||
.ignoresKingsRock = (B_UPDATED_MOVE_FLAGS == GEN_3 || B_UPDATED_MOVE_FLAGS == GEN_4),
|
||||
.meFirstBanned = TRUE,
|
||||
.metronomeBanned = TRUE,
|
||||
@ -8931,7 +8928,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.description = COMPOUND_STRING(
|
||||
"边撒娇边靠近对手攻击,\n"
|
||||
"还能夺取对手携带的道具。"),
|
||||
.effect = EFFECT_HIT,
|
||||
.effect = EFFECT_STEAL_ITEM,
|
||||
.power = B_UPDATED_MOVE_DATA >= GEN_5 ? 60 : 40,
|
||||
.type = TYPE_NORMAL,
|
||||
.accuracy = 100,
|
||||
@ -8944,9 +8941,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.metronomeBanned = TRUE,
|
||||
.copycatBanned = TRUE,
|
||||
.assistBanned = TRUE,
|
||||
.additionalEffects = ADDITIONAL_EFFECTS({
|
||||
.moveEffect = MOVE_EFFECT_STEAL_ITEM,
|
||||
}),
|
||||
.contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES,
|
||||
.contestCategory = CONTEST_CATEGORY_CUTE,
|
||||
.contestComboStarterId = 0,
|
||||
@ -19061,7 +19055,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.description = COMPOUND_STRING(
|
||||
"用岩石之斧攻击。散落的\n"
|
||||
"岩石碎片会飘浮在对手周围。"),
|
||||
.effect = EFFECT_HIT,
|
||||
.effect = EFFECT_STONE_AXE,
|
||||
.power = 65,
|
||||
.type = TYPE_ROCK,
|
||||
.accuracy = 90,
|
||||
@ -19072,8 +19066,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.makesContact = TRUE,
|
||||
.slicingMove = TRUE,
|
||||
.additionalEffects = ADDITIONAL_EFFECTS({
|
||||
.moveEffect = MOVE_EFFECT_STEALTH_ROCK,
|
||||
.chance = 100,
|
||||
.sheerForceBoost = SHEER_FORCE_BOOST,
|
||||
}),
|
||||
.battleAnimScript = gBattleAnimMove_StoneAxe,
|
||||
},
|
||||
@ -19387,7 +19380,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.description = COMPOUND_STRING(
|
||||
"用贝壳之剑攻击。散落碎片\n"
|
||||
"会散落在对手脚下成为撒菱。"),
|
||||
.effect = EFFECT_HIT,
|
||||
.effect = EFFECT_CEASELESS_EDGE,
|
||||
.power = 65,
|
||||
.type = TYPE_DARK,
|
||||
.accuracy = 90,
|
||||
@ -19398,8 +19391,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.makesContact = TRUE,
|
||||
.slicingMove = TRUE,
|
||||
.additionalEffects = ADDITIONAL_EFFECTS({
|
||||
.moveEffect = MOVE_EFFECT_SPIKES,
|
||||
.chance = 100,
|
||||
.sheerForceBoost = SHEER_FORCE_BOOST,
|
||||
}),
|
||||
.battleAnimScript = gBattleAnimMove_CeaselessEdge,
|
||||
},
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(MoveIsAffectedBySheerForce(MOVE_ELECTRO_SHOT) == TRUE);
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
SINGLE_BATTLE_TEST("Sticky Hold prevents item theft")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_THIEF, MOVE_EFFECT_STEAL_ITEM));
|
||||
ASSUME(GetMoveEffect(MOVE_THIEF) == EFFECT_STEAL_ITEM);
|
||||
PLAYER(SPECIES_URSALUNA) { Item(ITEM_NONE); }
|
||||
OPPONENT(SPECIES_GASTRODON) { Ability(ABILITY_STICKY_HOLD); Item(ITEM_LIFE_ORB); }
|
||||
} WHEN {
|
||||
|
||||
@ -881,3 +881,16 @@ AI_SINGLE_BATTLE_TEST("Move scoring comparison properly awards bonus point to be
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_WATER_SPOUT); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI will stop setting up at +4")
|
||||
{
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT);
|
||||
PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_CELEBRATE); }
|
||||
OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_TACKLE, MOVE_IRON_DEFENSE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_IRON_DEFENSE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_IRON_DEFENSE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_TACKLE); }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1255,3 +1255,16 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI won't send out defensive mon
|
||||
TURN { MOVE(player, MOVE_WATER_PULSE); EXPECT_MOVE(opponent, MOVE_BULLDOZE); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI considers 0 hits to KO as losing a 1v1")
|
||||
{
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT);
|
||||
PLAYER(SPECIES_JOLTEON) { Level(100); Ability(ABILITY_VOLT_ABSORB); Moves(MOVE_TACKLE); }
|
||||
OPPONENT(SPECIES_ZIGZAGOON) { Level(1); HP(1); Moves(MOVE_TACKLE); }
|
||||
OPPONENT(SPECIES_TANGELA) { Level(100); Moves(MOVE_THUNDERBOLT); }
|
||||
OPPONENT(SPECIES_TANGELA) { Level(100); Moves(MOVE_GIGA_DRAIN); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_TACKLE); EXPECT_SEND_OUT(opponent, 2); }
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,17 +102,14 @@ SINGLE_BATTLE_TEST("Air Balloon pops before it can be stolen with Magician")
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Air Balloon pops before it can be stolen with Thief or Covet")
|
||||
SINGLE_BATTLE_TEST("Air Balloon pops before it can be stolen by Thief")
|
||||
{
|
||||
u32 move;
|
||||
PARAMETRIZE { move = MOVE_THIEF; }
|
||||
PARAMETRIZE { move = MOVE_COVET; }
|
||||
GIVEN {
|
||||
ASSUME(MoveHasAdditionalEffect(move, MOVE_EFFECT_STEAL_ITEM) == TRUE);
|
||||
ASSUME(GetMoveEffect(MOVE_THIEF) == EFFECT_STEAL_ITEM);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_AIR_BALLOON); };
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, move); }
|
||||
TURN { MOVE(opponent, MOVE_THIEF); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet floats in the air with its Air Balloon!");
|
||||
MESSAGE("Wobbuffet's Air Balloon popped!");
|
||||
|
||||
@ -170,7 +170,7 @@ SINGLE_BATTLE_TEST("Red Card does not activate if stolen by a move")
|
||||
bool32 activate;
|
||||
PARAMETRIZE { item = ITEM_NONE; activate = FALSE; }
|
||||
PARAMETRIZE { item = ITEM_POTION; activate = TRUE; }
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_THIEF, MOVE_EFFECT_STEAL_ITEM) == TRUE);
|
||||
ASSUME(GetMoveEffect(MOVE_THIEF) == EFFECT_STEAL_ITEM);
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); }
|
||||
|
||||
@ -132,23 +132,22 @@ SINGLE_BATTLE_TEST("White Herb wont have time to activate if it is knocked off o
|
||||
PARAMETRIZE { move = MOVE_KNOCK_OFF; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_THIEF, MOVE_EFFECT_STEAL_ITEM) == TRUE);
|
||||
ASSUME(GetMoveEffect(MOVE_KNOCK_OFF) == EFFECT_KNOCK_OFF);
|
||||
ASSUME(GetMoveEffect(MOVE_THIEF) == EFFECT_STEAL_ITEM);
|
||||
PLAYER(SPECIES_SLUGMA) { Ability(ABILITY_WEAK_ARMOR); Item(ITEM_WHITE_HERB); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, move); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
|
||||
if (move == MOVE_THIEF) {
|
||||
MESSAGE("The opposing Wobbuffet stole Slugma's White Herb!");
|
||||
}
|
||||
ABILITY_POPUP(player, ABILITY_WEAK_ARMOR);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||
MESSAGE("Slugma's Weak Armor lowered its Defense!");
|
||||
MESSAGE("Slugma's Weak Armor raised its Speed!");
|
||||
if (move == MOVE_KNOCK_OFF) {
|
||||
MESSAGE("The opposing Wobbuffet knocked off Slugma's White Herb!");
|
||||
} else if (move == MOVE_THIEF) {
|
||||
MESSAGE("The opposing Wobbuffet stole Slugma's White Herb!");
|
||||
}
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_CEASELESS_EDGE, MOVE_EFFECT_SPIKES) == TRUE);
|
||||
ASSUME(GetMoveEffect(MOVE_CEASELESS_EDGE) == EFFECT_CEASELESS_EDGE);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Ceaseless Edge sets up hazards after hitting the target")
|
||||
@ -62,3 +62,19 @@ SINGLE_BATTLE_TEST("Ceaseless Edge can set up to 3 layers of Spikes")
|
||||
MESSAGE("The opposing Wynaut was hurt by the spikes!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Ceaseless Edge fails to set up hazards if user faints")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_ROCKY_HELMET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CEASELESS_EDGE); SEND_OUT(player, 1); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CEASELESS_EDGE, player);
|
||||
HP_BAR(player);
|
||||
MESSAGE("Wobbuffet was hurt by the opposing Wobbuffet's Rocky Helmet!");
|
||||
NOT MESSAGE("Spikes were scattered on the ground all around the opposing team!");
|
||||
}
|
||||
}
|
||||
@ -43,7 +43,7 @@ DOUBLE_BATTLE_TEST("Dragon Tail switches the target with a random non-battler, n
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Dragon Tail does not fail if no replacements")
|
||||
SINGLE_BATTLE_TEST("Dragon Tail fails if no replacements")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
@ -56,7 +56,7 @@ SINGLE_BATTLE_TEST("Dragon Tail does not fail if no replacements")
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Dragon Tail does not fail if replacements fainted")
|
||||
SINGLE_BATTLE_TEST("Dragon Tail fails if replacements fainted")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
|
||||
@ -96,7 +96,10 @@ SINGLE_BATTLE_TEST("Ice Spinner doesn't fail if there is no terrain on the field
|
||||
TURN { MOVE(player, MOVE_ICE_SPINNER); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ICE_SPINNER, player);
|
||||
NOT MESSAGE("But it failed!");
|
||||
NONE_OF {
|
||||
MESSAGE("But it failed!");
|
||||
MESSAGE("Mist swirled around the battlefield!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -99,6 +99,22 @@ SINGLE_BATTLE_TEST("Knock Off does not remove items through Substitute")
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Knock Off does not remove items through Substitute even if it breaks it")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { MaxHP(4); HP(4); Item(ITEM_LEFTOVERS); };
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_KNOCK_OFF); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_KNOCK_OFF, player);
|
||||
MESSAGE("The opposing Wobbuffet's substitute faded!");
|
||||
NOT { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_KNOCKOFF); }
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_LEFTOVERS);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Knock Off does not remove items through Protect")
|
||||
{
|
||||
GIVEN {
|
||||
@ -229,18 +245,6 @@ DOUBLE_BATTLE_TEST("Knock Off does not trigger the opposing ally's Symbiosis")
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Knock Off doesn't knock off items from Pokemon behind substitutes")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_POKE_BALL); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_KNOCK_OFF); }
|
||||
} SCENE {
|
||||
NOT MESSAGE("Wobbuffet knocked off the opposing Wobbuffet's Poké Ball!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Knock Off does knock off Mega Stones from Pokemon that don't actually use them")
|
||||
{
|
||||
GIVEN {
|
||||
@ -360,3 +364,33 @@ SINGLE_BATTLE_TEST("Knock Off doesn't knock off begin-battle form-change hold it
|
||||
NOT MESSAGE("Wobbuffet knocked off the opposing Zamazenta's Rusted Shield!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Knock Off does not activate if user faints")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_ROCKY_HELMET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_KNOCK_OFF); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_KNOCK_OFF, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
|
||||
MESSAGE("Wobbuffet was hurt by the opposing Wobbuffet's Rocky Helmet!");
|
||||
MESSAGE("Wobbuffet fainted!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_ROCKY_HELMET);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Knock Off doesn't remove item if it's prevented by Sticky Hold")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_MUK) { MaxHP(100); HP(51); Item(ITEM_ORAN_BERRY); Ability(ABILITY_STICKY_HOLD); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_KNOCK_OFF); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponent, ABILITY_STICKY_HOLD);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
|
||||
}
|
||||
}
|
||||
|
||||
94
test/battle/move_effect/stone_axe.c
Normal file
94
test/battle/move_effect/stone_axe.c
Normal file
@ -0,0 +1,94 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(GetMoveEffect(MOVE_STONE_AXE) == EFFECT_STONE_AXE);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Stone Axe sets up hazards after hitting the target")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_STONE_AXE); }
|
||||
TURN { SWITCH(opponent, 1); }
|
||||
} SCENE {
|
||||
s32 maxHP = GetMonData(&OPPONENT_PARTY[1], MON_DATA_MAX_HP);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player);
|
||||
HP_BAR(opponent);
|
||||
MESSAGE("Pointed stones float in the air around the opposing team!");
|
||||
MESSAGE("2 sent out Wobbuffet!");
|
||||
HP_BAR(opponent, damage: maxHP / 8);
|
||||
MESSAGE("Pointed stones dug into the opposing Wobbuffet!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Stone Axe can set up pointed stones only once")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_STONE_AXE); }
|
||||
TURN { MOVE(player, MOVE_STONE_AXE); }
|
||||
TURN { MOVE(player, MOVE_STONE_AXE); }
|
||||
TURN { MOVE(player, MOVE_STONE_AXE); }
|
||||
TURN { SWITCH(opponent, 1); }
|
||||
} SCENE {
|
||||
s32 maxHP = GetMonData(&OPPONENT_PARTY[1], MON_DATA_MAX_HP);
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player);
|
||||
HP_BAR(opponent);
|
||||
MESSAGE("Pointed stones float in the air around the opposing team!");
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player);
|
||||
HP_BAR(opponent);
|
||||
NOT MESSAGE("Pointed stones float in the air around the opposing team!");
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player);
|
||||
HP_BAR(opponent);
|
||||
NOT MESSAGE("Pointed stones float in the air around the opposing team!");
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player);
|
||||
HP_BAR(opponent);
|
||||
NOT MESSAGE("Pointed stones float in the air around the opposing team!");
|
||||
|
||||
MESSAGE("2 sent out Wynaut!");
|
||||
HP_BAR(opponent, damage: maxHP / 8);
|
||||
MESSAGE("Pointed stones dug into the opposing Wynaut!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Stone Axe sets up hazards after any ability activation")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_SKARMORY) { Ability(ABILITY_WEAK_ARMOR); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_STONE_AXE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player);
|
||||
ABILITY_POPUP(opponent, ABILITY_WEAK_ARMOR);
|
||||
MESSAGE("Pointed stones float in the air around the opposing team!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Stone Axe fails to set up hazards if user faints")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_ROCKY_HELMET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_STONE_AXE); SEND_OUT(player, 1); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player);
|
||||
HP_BAR(player);
|
||||
MESSAGE("Wobbuffet was hurt by the opposing Wobbuffet's Rocky Helmet!");
|
||||
NOT MESSAGE("Pointed stones float in the air around the opposing team!");
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_PAY_DAY, MOVE_EFFECT_PAYDAY));
|
||||
ASSUME(MoveHasAdditionalEffectWithChance(MOVE_PAY_DAY, MOVE_EFFECT_PAYDAY, 0) == TRUE);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pay Day Scatters coins around after it hits - singles")
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_THIEF, MOVE_EFFECT_STEAL_ITEM) == TRUE);
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_COVET, MOVE_EFFECT_STEAL_ITEM) == TRUE);
|
||||
ASSUME(GetMoveEffect(MOVE_THIEF == EFFECT_STEAL_ITEM));
|
||||
ASSUME(GetMoveEffect(MOVE_COVET == EFFECT_STEAL_ITEM));
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Thief and Covet steal target's held item")
|
||||
@ -127,3 +127,41 @@ WILD_BATTLE_TEST("Thief and Covet steal target's held item and it's added to Bag
|
||||
EXPECT_EQ(opponent->item, ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Thief and Covet can't steal target's held item if user faints before")
|
||||
{
|
||||
u32 move;
|
||||
PARAMETRIZE { move = MOVE_THIEF; }
|
||||
PARAMETRIZE { move = MOVE_COVET; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); };
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_ROCKY_HELMET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, move); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, move, player);
|
||||
HP_BAR(opponent);
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_STEAL, opponent);
|
||||
} THEN {
|
||||
EXPECT_EQ(player->item, ITEM_NONE);
|
||||
EXPECT_EQ(opponent->item, ITEM_ROCKY_HELMET);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Thief and Covet: Berry activation happens before the item can be stolen")
|
||||
{
|
||||
u32 move;
|
||||
PARAMETRIZE { move = MOVE_THIEF; }
|
||||
PARAMETRIZE { move = MOVE_COVET; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { MaxHP(200); HP(101); Item(ITEM_ORAN_BERRY); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, move); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, move, player);
|
||||
HP_BAR(opponent);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_STEAL, opponent);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,63 +3,19 @@
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_STONE_AXE, MOVE_EFFECT_STEALTH_ROCK) == TRUE);
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_STONESURGE, MOVE_EFFECT_STEALTH_ROCK));
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Stone Axe sets up hazards after hitting the target")
|
||||
SINGLE_BATTLE_TEST("Steath Rock: Rock from G-Max Stonesurge are set up before any ability activation")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_DREDNAW) { GigantamaxFactor(TRUE); }
|
||||
OPPONENT(SPECIES_SKARMORY) { Ability(ABILITY_WEAK_ARMOR); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_STONE_AXE); }
|
||||
TURN { SWITCH(opponent, 1); }
|
||||
TURN { MOVE(player, MOVE_WATERFALL, gimmick: GIMMICK_DYNAMAX); }
|
||||
} SCENE {
|
||||
s32 maxHP = GetMonData(&OPPONENT_PARTY[1], MON_DATA_MAX_HP);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player);
|
||||
HP_BAR(opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_G_MAX_STONESURGE, player);
|
||||
MESSAGE("Pointed stones float in the air around the opposing team!");
|
||||
MESSAGE("2 sent out Wobbuffet!");
|
||||
HP_BAR(opponent, damage: maxHP / 8);
|
||||
MESSAGE("Pointed stones dug into the opposing Wobbuffet!");
|
||||
ABILITY_POPUP(opponent, ABILITY_WEAK_ARMOR);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Stone Axe can set up pointed stones only once")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_STONE_AXE); }
|
||||
TURN { MOVE(player, MOVE_STONE_AXE); }
|
||||
TURN { MOVE(player, MOVE_STONE_AXE); }
|
||||
TURN { MOVE(player, MOVE_STONE_AXE); }
|
||||
TURN { SWITCH(opponent, 1); }
|
||||
} SCENE {
|
||||
s32 maxHP = GetMonData(&OPPONENT_PARTY[1], MON_DATA_MAX_HP);
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player);
|
||||
HP_BAR(opponent);
|
||||
MESSAGE("Pointed stones float in the air around the opposing team!");
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player);
|
||||
HP_BAR(opponent);
|
||||
NOT MESSAGE("Pointed stones float in the air around the opposing team!");
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player);
|
||||
HP_BAR(opponent);
|
||||
NOT MESSAGE("Pointed stones float in the air around the opposing team!");
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player);
|
||||
HP_BAR(opponent);
|
||||
NOT MESSAGE("Pointed stones float in the air around the opposing team!");
|
||||
|
||||
MESSAGE("2 sent out Wynaut!");
|
||||
HP_BAR(opponent, damage: maxHP / 8);
|
||||
MESSAGE("Pointed stones dug into the opposing Wynaut!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_MAKE_IT_RAIN, MOVE_EFFECT_PAYDAY));
|
||||
ASSUME(MoveHasAdditionalEffectWithChance(MOVE_MAKE_IT_RAIN, MOVE_EFFECT_PAYDAY, 0) == TRUE);
|
||||
ASSUME(MoveHasAdditionalEffectSelf(MOVE_MAKE_IT_RAIN, MOVE_EFFECT_SP_ATK_MINUS_1));
|
||||
}
|
||||
|
||||
|
||||
@ -102,3 +102,23 @@ SINGLE_BATTLE_TEST("Recoil: Flare Blitz is absorbed by Flash Fire and no recoil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Recoil: The correct amount of recoil damage is dealt after targets recovery berry proc")
|
||||
{
|
||||
s16 directDamage;
|
||||
s16 recoilDamage;
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveRecoil(MOVE_TAKE_DOWN) == 25);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { MaxHP(100); HP(51); Item(ITEM_SITRUS_BERRY); };
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_TAKE_DOWN); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TAKE_DOWN, player);
|
||||
HP_BAR(opponent, captureDamage: &directDamage);
|
||||
HP_BAR(player, captureDamage: &recoilDamage);
|
||||
} THEN {
|
||||
EXPECT_MUL_EQ(directDamage, UQ_4_12(0.25), recoilDamage);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user