mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2025-01-18 01:14:19 +01:00
Merge pull request #1932 from BuffelSaft/gen_8_moves_batch2
Gen 8 moves batch + Beak Blast
This commit is contained in:
commit
f0d74b60ff
@ -1968,6 +1968,14 @@
|
||||
various \battler, VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM
|
||||
.endm
|
||||
|
||||
.macro setbeakblast battler:req
|
||||
various \battler, VARIOUS_SET_BEAK_BLAST
|
||||
.endm
|
||||
|
||||
.macro swapsidestatuses
|
||||
various BS_ATTACKER, VARIOUS_SWAP_SIDE_STATUSES
|
||||
.endm
|
||||
|
||||
@ helpful macros
|
||||
.macro setstatchanger stat:req, stages:req, down:req
|
||||
setbyte sSTATCHANGER, \stat | \stages << 3 | \down << 7
|
||||
|
@ -829,6 +829,8 @@ gBattleAnims_General::
|
||||
.4byte General_StrongWinds @ B_ANIM_STRONG_WINDS
|
||||
.4byte General_PrimalReversion @ B_ANIM_PRIMAL_REVERSION
|
||||
.4byte General_AquaRingHeal @ B_ANIM_AQUA_RING_HEAL
|
||||
.4byte General_BeakBlastSetUp @ B_ANIM_BEAK_BLAST_SETUP
|
||||
.4byte General_ShellTrapSetUp @ B_ANIM_SHELL_TRAP_SETUP
|
||||
|
||||
.align 2
|
||||
gBattleAnims_Special::
|
||||
@ -11735,7 +11737,7 @@ Move_INSTRUCT::
|
||||
blendoff
|
||||
end
|
||||
|
||||
Move_BEAK_BLAST::
|
||||
General_BeakBlastSetUp:
|
||||
loadspritegfx ANIM_TAG_SMALL_EMBER @Fire
|
||||
playsewithpan SE_M_DRAGON_RAGE, SOUND_PAN_ATTACKER
|
||||
delay 0x3
|
||||
@ -11743,7 +11745,7 @@ Move_BEAK_BLAST::
|
||||
launchtemplate gFireSpiralOutwardSpriteTemplate 0x3 0x4 0x0 0x0 0x38 0x0
|
||||
waitforvisualfinish
|
||||
end
|
||||
BeakBlastUnleash:
|
||||
Move_BEAK_BLAST::
|
||||
loadspritegfx ANIM_TAG_IMPACT
|
||||
launchtask AnimTask_BlendBattleAnimPal 0xA 0x5 ANIM_PAL_ATK 0x2 0x0 0x9 0x1F
|
||||
waitforvisualfinish
|
||||
@ -11892,8 +11894,7 @@ Move_AURORA_VEIL::
|
||||
blendoff
|
||||
end
|
||||
|
||||
Move_SHELL_TRAP::
|
||||
ShellTrapChargeUp:
|
||||
General_ShellTrapSetUp:
|
||||
loadspritegfx ANIM_TAG_SMALL_EMBER
|
||||
loadspritegfx ANIM_TAG_IMPACT
|
||||
monbg ANIM_TARGET
|
||||
@ -11910,6 +11911,7 @@ ShellTrapChargeUp:
|
||||
clearmonbg ANIM_TARGET
|
||||
blendoff
|
||||
end
|
||||
Move_SHELL_TRAP::
|
||||
ShellTrapUnleash:
|
||||
loadspritegfx ANIM_TAG_IMPACT @pound
|
||||
loadspritegfx ANIM_TAG_SMALL_RED_EYE @red
|
||||
@ -13605,8 +13607,8 @@ Move_DRUM_BEATING::
|
||||
blendoff
|
||||
end
|
||||
|
||||
Move_SNAP_TRAP::
|
||||
end @ to do:
|
||||
Move_SNAP_TRAP:: @ placeholder
|
||||
goto Move_BITE
|
||||
|
||||
Move_PYRO_BALL::
|
||||
loadspritegfx ANIM_TAG_FLAT_ROCK
|
||||
@ -24214,6 +24216,7 @@ General_TurnTrap:
|
||||
jumpargeq 0, TRAP_ANIM_SAND_TOMB, Status_SandTomb
|
||||
jumpargeq 0, TRAP_ANIM_MAGMA_STORM, Status_MagmaStorm
|
||||
jumpargeq 0, TRAP_ANIM_INFESTATION, Status_Infestation
|
||||
jumpargeq 0, TRAP_ANIM_SNAP_TRAP, Status_Snap_Trap
|
||||
goto Status_BindWrap
|
||||
Status_BindWrap:
|
||||
loadspritegfx ANIM_TAG_TENDRILS
|
||||
@ -24300,6 +24303,9 @@ Status_Clamp:
|
||||
waitforvisualfinish
|
||||
end
|
||||
|
||||
Status_Snap_Trap: @ placeholder
|
||||
goto Move_BITE
|
||||
|
||||
Status_SandTomb:
|
||||
loadspritegfx ANIM_TAG_MUD_SAND
|
||||
createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 0, 4, 2, 0, 7, RGB(19, 17, 0)
|
||||
|
@ -404,6 +404,119 @@ gBattleScriptsForMoveEffects::
|
||||
.4byte BattleScript_EffectClangorousSoul @ EFFECT_CLANGOROUS_SOUL
|
||||
.4byte BattleScript_EffectHit @ EFFECT_BOLT_BEAK
|
||||
.4byte BattleScript_EffectSkyDrop @ EFFECT_SKY_DROP
|
||||
.4byte BattleScript_EffectHit @ EFFECT_EXPANDING_FORCE
|
||||
.4byte BattleScript_EffectScaleShot @ EFFECT_SCALE_SHOT
|
||||
.4byte BattleScript_EffectMeteorBeam @ EFFECT_METEOR_BEAM
|
||||
.4byte BattleScript_EffectHit @ EFFECT_RISING_VOLTAGE
|
||||
.4byte BattleScript_EffectHit @ EFFECT_BEAK_BLAST
|
||||
.4byte BattleScript_EffectCourtChange @ EFFECT_COURT_CHANGE
|
||||
|
||||
BattleScript_EffectCourtChange::
|
||||
attackcanceler
|
||||
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
|
||||
attackstring
|
||||
ppreduce
|
||||
swapsidestatuses
|
||||
attackanimation
|
||||
waitanimation
|
||||
printstring STRINGID_COURTCHANGE
|
||||
waitmessage 0x40
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_BeakBlastSetUp::
|
||||
setbeakblast BS_ATTACKER
|
||||
printstring STRINGID_EMPTYSTRING3
|
||||
waitmessage 0x1
|
||||
playanimation BS_ATTACKER, B_ANIM_BEAK_BLAST_SETUP, NULL
|
||||
printstring STRINGID_HEATUPBEAK
|
||||
waitmessage 0x40
|
||||
end2
|
||||
|
||||
BattleScript_BeakBlastBurn::
|
||||
setbyte cMULTISTRING_CHOOSER, 0
|
||||
copybyte gEffectBattler, gBattlerAttacker
|
||||
call BattleScript_MoveEffectBurn
|
||||
return
|
||||
|
||||
BattleScript_EffectMeteorBeam::
|
||||
@ DecideTurn
|
||||
jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_TwoTurnMovesSecondTurn
|
||||
jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING, BattleScript_TwoTurnMovesSecondTurn
|
||||
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_METEOR_BEAM
|
||||
call BattleScript_FirstChargingTurnMeteorBeam
|
||||
jumpifnoholdeffect BS_ATTACKER, HOLD_EFFECT_POWER_HERB, BattleScript_MoveEnd
|
||||
call BattleScript_PowerHerbActivation
|
||||
goto BattleScript_TwoTurnMovesSecondTurn
|
||||
|
||||
BattleScript_FirstChargingTurnMeteorBeam::
|
||||
attackcanceler
|
||||
printstring STRINGID_EMPTYSTRING3
|
||||
ppreduce
|
||||
attackanimation
|
||||
waitanimation
|
||||
orword gHitMarker, HITMARKER_CHARGING
|
||||
setmoveeffect MOVE_EFFECT_CHARGING | MOVE_EFFECT_AFFECTS_USER
|
||||
seteffectprimary
|
||||
copybyte cMULTISTRING_CHOOSER, sTWOTURN_STRINGID
|
||||
printfromtable gFirstTurnOfTwoStringIds
|
||||
waitmessage 0x40
|
||||
setmoveeffect MOVE_EFFECT_SP_ATK_PLUS_1 | MOVE_EFFECT_AFFECTS_USER
|
||||
seteffectsecondary
|
||||
return
|
||||
|
||||
BattleScript_EffectScaleShot::
|
||||
attackcanceler
|
||||
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
|
||||
attackstring
|
||||
ppreduce
|
||||
setmultihitcounter 0x0
|
||||
initmultihitstring
|
||||
sethword sMULTIHIT_EFFECT, 0x0
|
||||
BattleScript_ScaleShotLoop::
|
||||
jumpifhasnohp BS_ATTACKER, BattleScript_ScaleShotEnd
|
||||
jumpifhasnohp BS_TARGET, BattleScript_ScaleShotPrintStrings
|
||||
jumpifhalfword CMP_EQUAL, gChosenMove, MOVE_SLEEP_TALK, BattleScript_ScaleShotDoMultiHit
|
||||
jumpifstatus BS_ATTACKER, STATUS1_SLEEP, BattleScript_ScaleShotPrintStrings
|
||||
BattleScript_ScaleShotDoMultiHit::
|
||||
movevaluescleanup
|
||||
copyhword sMOVE_EFFECT, sMULTIHIT_EFFECT
|
||||
critcalc
|
||||
damagecalc
|
||||
jumpifmovehadnoeffect BattleScript_ScaleShotMultiHitNoMoreHits
|
||||
adjustdamage
|
||||
attackanimation
|
||||
waitanimation
|
||||
effectivenesssound
|
||||
hitanimation BS_TARGET
|
||||
waitstate
|
||||
healthbarupdate BS_TARGET
|
||||
datahpupdate BS_TARGET
|
||||
critmessage
|
||||
waitmessage 0x40
|
||||
multihitresultmessage
|
||||
printstring STRINGID_EMPTYSTRING3
|
||||
waitmessage 0x1
|
||||
addbyte sMULTIHIT_STRING + 4, 0x1
|
||||
moveendto MOVEEND_NEXT_TARGET
|
||||
jumpifbyte CMP_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_FOE_ENDURED, BattleScript_ScaleShotPrintStrings
|
||||
decrementmultihit BattleScript_ScaleShotLoop
|
||||
goto BattleScript_ScaleShotPrintStrings
|
||||
BattleScript_ScaleShotMultiHitNoMoreHits::
|
||||
pause 0x20
|
||||
BattleScript_ScaleShotPrintStrings::
|
||||
resultmessage
|
||||
waitmessage 0x40
|
||||
jumpifmovehadnoeffect BattleScript_ScaleShotEnd
|
||||
copyarray gBattleTextBuff1, sMULTIHIT_STRING, 0x6
|
||||
printstring STRINGID_HITXTIMES
|
||||
waitmessage 0x40
|
||||
BattleScript_ScaleShotEnd::
|
||||
setmoveeffect MOVE_EFFECT_SCALE_SHOT | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN
|
||||
seteffectwithchance
|
||||
tryfaintmon BS_TARGET
|
||||
moveendcase MOVEEND_SYNCHRONIZE_TARGET
|
||||
moveendfrom MOVEEND_STATUS_IMMUNITY_ABILITIES
|
||||
end
|
||||
|
||||
BattleScript_EffectSkyDrop:
|
||||
jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_SkyDropTurn2
|
||||
@ -6760,6 +6873,7 @@ BattleScript_ToxicSpikesPoisoned::
|
||||
BattleScript_StickyWebOnSwitchIn::
|
||||
savetarget
|
||||
copybyte gBattlerTarget, sBATTLER
|
||||
setbyte sSTICKY_WEB_STAT_DROP, 1
|
||||
printstring STRINGID_STICKYWEBSWITCHIN
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
jumpifability BS_TARGET, ABILITY_MIRROR_ARMOR, BattleScript_MirrorArmorReflectStickyWeb
|
||||
@ -7168,6 +7282,26 @@ BattleScript_DefSpDefDownTrySpDef::
|
||||
BattleScript_DefSpDefDownRet::
|
||||
return
|
||||
|
||||
BattleScript_DefDownSpeedUp::
|
||||
jumpifstat BS_ATTACKER, CMP_GREATER_THAN, STAT_DEF, MIN_STAT_STAGE, BattleScript_DefDownSpeedUpTryDef
|
||||
jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_DefDownSpeedUpRet
|
||||
BattleScript_DefDownSpeedUpTryDef::
|
||||
playstatchangeanimation BS_ATTACKER, BIT_DEF, STAT_CHANGE_NEGATIVE | STAT_CHANGE_CANT_PREVENT
|
||||
setstatchanger STAT_DEF, 1, TRUE
|
||||
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR | MOVE_EFFECT_CERTAIN, BattleScript_DefDownSpeedUpTrySpeed
|
||||
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_DefDownSpeedUpTrySpeed
|
||||
printfromtable gStatDownStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_DefDownSpeedUpTrySpeed:
|
||||
playstatchangeanimation BS_ATTACKER, BIT_SPEED, 0
|
||||
setstatchanger STAT_SPEED, 1, FALSE
|
||||
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR | MOVE_EFFECT_CERTAIN, BattleScript_DefDownSpeedUpRet
|
||||
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_DefDownSpeedUpRet
|
||||
printfromtable gStatUpStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_DefDownSpeedUpRet::
|
||||
return
|
||||
|
||||
BattleScript_KnockedOff::
|
||||
playanimation BS_TARGET, B_ANIM_ITEM_KNOCKOFF
|
||||
printstring STRINGID_PKMNKNOCKEDOFF
|
||||
|
@ -141,10 +141,12 @@ struct ProtectStruct
|
||||
u32 usedMicleBerry:1;
|
||||
u32 usedCustapBerry:1; // also quick claw
|
||||
u32 touchedProtectLike:1;
|
||||
u32 disableEjectPack:1;
|
||||
u32 statFell:1;
|
||||
u32 pranksterElevated:1;
|
||||
u32 quickDraw:1;
|
||||
// End of 32-bit bitfield
|
||||
u16 disableEjectPack:1;
|
||||
u16 statFell:1;
|
||||
u16 pranksterElevated:1;
|
||||
u16 quickDraw:1;
|
||||
u16 beakBlastCharge:1;
|
||||
u32 physicalDmg;
|
||||
u32 specialDmg;
|
||||
u8 physicalBattlerId;
|
||||
@ -194,19 +196,21 @@ struct SideTimer
|
||||
u8 mistBattlerId;
|
||||
u8 safeguardTimer;
|
||||
u8 safeguardBattlerId;
|
||||
u8 followmeTimer;
|
||||
u8 followmeTarget:3;
|
||||
u8 followmePowder:1; // Rage powder, does not affect grass type pokemon.
|
||||
u8 spikesAmount;
|
||||
u8 toxicSpikesAmount;
|
||||
u8 stealthRockAmount;
|
||||
u8 stickyWebAmount;
|
||||
u8 stickyWebBattlerSide; // Used for Court Change
|
||||
u8 auroraVeilTimer;
|
||||
u8 auroraVeilBattlerId;
|
||||
u8 tailwindTimer;
|
||||
u8 tailwindBattlerId;
|
||||
u8 luckyChantTimer;
|
||||
u8 luckyChantBattlerId;
|
||||
// Timers below this point are not swapped by Court Change
|
||||
u8 followmeTimer;
|
||||
u8 followmeTarget:3;
|
||||
u8 followmePowder:1; // Rage powder, does not affect grass type pokemon.
|
||||
u8 retaliateTimer;
|
||||
};
|
||||
|
||||
@ -699,6 +703,7 @@ struct BattleScripting
|
||||
u16 abilityPopupOverwrite;
|
||||
u8 switchCase; // Special switching conditions, eg. red card
|
||||
u8 overrideBerryRequirements;
|
||||
u8 stickyWebStatDrop; // To prevent Defiant activating on a Court Change'd Sticky Web
|
||||
};
|
||||
|
||||
struct BattleSpriteInfo
|
||||
|
@ -60,6 +60,7 @@ bool32 IsAbilityOfRating(u16 ability, s8 rating);
|
||||
s8 GetAbilityRating(u16 ability);
|
||||
bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability);
|
||||
bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u16 move);
|
||||
u32 AI_GetBattlerMoveTargetType(u8 battlerId, u16 move);
|
||||
|
||||
// stat stage checks
|
||||
bool32 AnyStatIsRaised(u8 battlerId);
|
||||
|
@ -416,5 +416,8 @@ extern const u8 BattleScript_BothCanNoLongerEscape[];
|
||||
extern const u8 BattleScript_OctolockEndTurn[];
|
||||
extern const u8 BattleScript_NeutralizingGasExits[];
|
||||
extern const u8 BattleScript_MagicianActivates[];
|
||||
extern const u8 BattleScript_BeakBlastSetUp[];
|
||||
extern const u8 BattleScript_BeakBlastBurn[];
|
||||
extern const u8 BattleScript_DefDownSpeedUp[];
|
||||
|
||||
#endif // GUARD_BATTLE_SCRIPTS_H
|
||||
|
@ -170,7 +170,7 @@ bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags);
|
||||
void TryToApplyMimicry(u8 battlerId, bool8 various);
|
||||
void TryToRevertMimicry(void);
|
||||
void RestoreBattlerOriginalTypes(u8 battlerId);
|
||||
|
||||
u32 GetBattlerMoveTargetType(u8 battlerId, u16 move);
|
||||
// Ability checks
|
||||
bool32 IsRolePlayBannedAbilityAtk(u16 ability);
|
||||
bool32 IsRolePlayBannedAbility(u16 ability);
|
||||
|
@ -363,8 +363,9 @@
|
||||
#define MOVE_EFFECT_RELIC_SONG 0x47
|
||||
#define MOVE_EFFECT_TRAP_BOTH 0x48
|
||||
#define MOVE_EFFECT_SKY_DROP 0x49
|
||||
#define MOVE_EFFECT_SCALE_SHOT 0x4A
|
||||
|
||||
#define NUM_MOVE_EFFECTS 0x50
|
||||
#define NUM_MOVE_EFFECTS 0x4B
|
||||
|
||||
#define MOVE_EFFECT_AFFECTS_USER 0x4000
|
||||
#define MOVE_EFFECT_CERTAIN 0x8000
|
||||
|
@ -532,6 +532,8 @@
|
||||
#define B_ANIM_STRONG_WINDS 30
|
||||
#define B_ANIM_PRIMAL_REVERSION 31
|
||||
#define B_ANIM_AQUA_RING_HEAL 32
|
||||
#define B_ANIM_BEAK_BLAST_SETUP 33
|
||||
#define B_ANIM_SHELL_TRAP_SETUP 34
|
||||
|
||||
// special animations table (gBattleAnims_Special)
|
||||
#define B_ANIM_LVL_UP 0
|
||||
@ -570,6 +572,7 @@
|
||||
#define TRAP_ANIM_SAND_TOMB 4
|
||||
#define TRAP_ANIM_MAGMA_STORM 5
|
||||
#define TRAP_ANIM_INFESTATION 6
|
||||
#define TRAP_ANIM_SNAP_TRAP 7
|
||||
|
||||
// Weather defines for battle animation scripts.
|
||||
#define ANIM_WEATHER_NONE 0
|
||||
|
@ -387,7 +387,13 @@
|
||||
#define EFFECT_CLANGOROUS_SOUL 381
|
||||
#define EFFECT_BOLT_BEAK 382
|
||||
#define EFFECT_SKY_DROP 383
|
||||
#define EFFECT_EXPANDING_FORCE 384
|
||||
#define EFFECT_SCALE_SHOT 385
|
||||
#define EFFECT_METEOR_BEAM 386
|
||||
#define EFFECT_RISING_VOLTAGE 387
|
||||
#define EFFECT_BEAK_BLAST 388
|
||||
#define EFFECT_COURT_CHANGE 389
|
||||
|
||||
#define NUM_BATTLE_MOVE_EFFECTS 384
|
||||
#define NUM_BATTLE_MOVE_EFFECTS 390
|
||||
|
||||
#endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H
|
||||
|
@ -39,6 +39,7 @@
|
||||
#define sABILITY_OVERWRITE (gBattleScripting + 0x34) // abilityPopupOverwrite
|
||||
#define sSWITCH_CASE (gBattleScripting + 0x36) // switchCase
|
||||
#define sBERRY_OVERRIDE (gBattleScripting + 0x37) // overrideBerryRequirements
|
||||
#define sSTICKY_WEB_STAT_DROP (gBattleScripting + 0x38) // stickyWebStatDrop
|
||||
|
||||
// Array entries for battle communication
|
||||
#define MULTIUSE_STATE 0
|
||||
@ -238,6 +239,8 @@
|
||||
#define VARIOUS_SAVE_BATTLER_ITEM 148
|
||||
#define VARIOUS_RESTORE_BATTLER_ITEM 149
|
||||
#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 150
|
||||
#define VARIOUS_SET_BEAK_BLAST 151
|
||||
#define VARIOUS_SWAP_SIDE_STATUSES 152
|
||||
|
||||
// Cmd_manipulatedamage
|
||||
#define DMG_CHANGE_SIGN 0
|
||||
|
@ -609,8 +609,12 @@
|
||||
#define STRINGID_NEUTRALIZINGGASOVER 607
|
||||
#define STRINGID_TARGETTOOHEAVY 608
|
||||
#define STRINGID_PKMNTOOKTARGETHIGH 609
|
||||
#define STRINGID_PKMNINSNAPTRAP 610
|
||||
#define STRINGID_METEORBEAMCHARGING 611
|
||||
#define STRINGID_HEATUPBEAK 612
|
||||
#define STRINGID_COURTCHANGE 613
|
||||
|
||||
#define BATTLESTRINGS_COUNT 610
|
||||
#define BATTLESTRINGS_COUNT 614
|
||||
|
||||
// This is the string id that gBattleStringsTable starts with.
|
||||
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,
|
||||
@ -667,6 +671,7 @@
|
||||
#define B_MSG_TURN1_GEOMANCY 9
|
||||
#define B_MSG_TURN1_FREEZE_SHOCK 10
|
||||
#define B_MSG_TURN1_SKY_DROP 11
|
||||
#define B_MSG_TURN1_METEOR_BEAM 12
|
||||
|
||||
// gMoveWeatherChangeStringIds
|
||||
#define B_MSG_STARTED_RAIN 0
|
||||
|
@ -550,7 +550,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
u8 atkPriority = GetMovePriority(battlerAtk, move);
|
||||
u16 moveEffect = gBattleMoves[move].effect;
|
||||
s32 moveType;
|
||||
u16 moveTarget = gBattleMoves[move].target;
|
||||
u16 moveTarget = AI_GetBattlerMoveTargetType(battlerAtk, move);
|
||||
u16 accuracy = AI_GetMoveAccuracy(battlerAtk, battlerDef, AI_DATA->atkAbility, AI_DATA->defAbility, AI_DATA->atkHoldEffect, AI_DATA->defHoldEffect, move);
|
||||
u8 effectiveness = AI_GetMoveEffectiveness(move, battlerAtk, battlerDef);
|
||||
bool32 isDoubleBattle = IsValidDoubleBattle(battlerAtk);
|
||||
@ -566,7 +566,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
GET_MOVE_TYPE(move, moveType);
|
||||
|
||||
// check non-user target
|
||||
if (!(gBattleMoves[move].target & MOVE_TARGET_USER))
|
||||
if (!(moveTarget & MOVE_TARGET_USER))
|
||||
{
|
||||
// handle negative checks on non-user target
|
||||
// check powder moves
|
||||
@ -2371,7 +2371,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gBattleMoves[instructedMove].target & (MOVE_TARGET_SELECTED
|
||||
if (AI_GetBattlerMoveTargetType(battlerDef, instructedMove) & (MOVE_TARGET_SELECTED
|
||||
| MOVE_TARGET_DEPENDS
|
||||
| MOVE_TARGET_RANDOM
|
||||
| MOVE_TARGET_BOTH
|
||||
@ -2568,7 +2568,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
// move data
|
||||
u8 moveType = gBattleMoves[move].type;
|
||||
u16 effect = gBattleMoves[move].effect;
|
||||
u16 target = gBattleMoves[move].target;
|
||||
u16 moveTarget = AI_GetBattlerMoveTargetType(battlerAtk, move);
|
||||
// ally data
|
||||
u8 battlerAtkPartner = AI_DATA->battlerAtkPartner;
|
||||
u16 atkPartnerAbility = AI_DATA->atkPartnerAbility;
|
||||
@ -2607,7 +2607,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
if (IsAttackBoostMoveEffect(effect))
|
||||
score -= 3;
|
||||
// encourage moves hitting multiple opponents
|
||||
if (!IS_MOVE_STATUS(move) && (gBattleMoves[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)))
|
||||
if (!IS_MOVE_STATUS(move) && (moveTarget & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)))
|
||||
score += 3;
|
||||
}
|
||||
}
|
||||
@ -2675,7 +2675,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
if (GetMoveDamageResult(move) == MOVE_POWER_OTHER)
|
||||
{
|
||||
// partner ability checks
|
||||
if (!partnerProtecting && gBattleMoves[move].target != MOVE_TARGET_BOTH && !DoesBattlerIgnoreAbilityChecks(AI_DATA->atkAbility, move))
|
||||
if (!partnerProtecting && moveTarget != MOVE_TARGET_BOTH && !DoesBattlerIgnoreAbilityChecks(AI_DATA->atkAbility, move))
|
||||
{
|
||||
switch (atkPartnerAbility)
|
||||
{
|
||||
@ -2875,7 +2875,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
|
||||
if (instructedMove != MOVE_NONE
|
||||
&& !IS_MOVE_STATUS(instructedMove)
|
||||
&& gBattleMoves[instructedMove].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) // Use instruct on multi-target moves
|
||||
&& (AI_GetBattlerMoveTargetType(battlerAtkPartner, instructedMove) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) // Use instruct on multi-target moves
|
||||
{
|
||||
RETURN_SCORE_PLUS(1);
|
||||
}
|
||||
@ -3698,24 +3698,24 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score);
|
||||
break;
|
||||
case MOVE_WIDE_GUARD:
|
||||
if (predictedMove != MOVE_NONE && gBattleMoves[predictedMove].target & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH))
|
||||
if (predictedMove != MOVE_NONE && AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH))
|
||||
{
|
||||
ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score);
|
||||
}
|
||||
else if (isDoubleBattle && gBattleMoves[AI_DATA->partnerMove].target & MOVE_TARGET_FOES_AND_ALLY)
|
||||
else if (isDoubleBattle && AI_GetBattlerMoveTargetType(AI_DATA->battlerAtkPartner, AI_DATA->partnerMove) & MOVE_TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
if (AI_DATA->atkAbility != ABILITY_TELEPATHY)
|
||||
ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score);
|
||||
}
|
||||
break;
|
||||
case MOVE_CRAFTY_SHIELD:
|
||||
if (predictedMove != MOVE_NONE && IS_MOVE_STATUS(predictedMove) && !(gBattleMoves[predictedMove].target & MOVE_TARGET_USER))
|
||||
if (predictedMove != MOVE_NONE && IS_MOVE_STATUS(predictedMove) && !(AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER))
|
||||
ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score);
|
||||
break;
|
||||
|
||||
case MOVE_MAT_BLOCK:
|
||||
if (gDisableStructs[battlerAtk].isFirstTurn && predictedMove != MOVE_NONE
|
||||
&& !IS_MOVE_STATUS(predictedMove) && !(gBattleMoves[predictedMove].target & MOVE_TARGET_USER))
|
||||
&& !IS_MOVE_STATUS(predictedMove) && !(AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER))
|
||||
ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score);
|
||||
break;
|
||||
case MOVE_KINGS_SHIELD:
|
||||
@ -4160,7 +4160,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
score += 10;
|
||||
break;
|
||||
case EFFECT_MAGIC_COAT:
|
||||
if (IS_MOVE_STATUS(predictedMove) && gBattleMoves[predictedMove].target & (MOVE_TARGET_SELECTED | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH))
|
||||
if (IS_MOVE_STATUS(predictedMove) && AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_SELECTED | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH))
|
||||
score += 3;
|
||||
break;
|
||||
case EFFECT_RECYCLE:
|
||||
|
@ -1251,6 +1251,16 @@ bool32 AI_WeatherHasEffect(void)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
u32 AI_GetBattlerMoveTargetType(u8 battlerId, u16 move)
|
||||
{
|
||||
u32 target;
|
||||
|
||||
if (gBattleMoves[move].effect == EFFECT_EXPANDING_FORCE && AI_IsTerrainAffected(battlerId, STATUS_FIELD_PSYCHIC_TERRAIN))
|
||||
return MOVE_TARGET_BOTH;
|
||||
else
|
||||
return gBattleMoves[move].target;
|
||||
}
|
||||
|
||||
bool32 IsAromaVeilProtectedMove(u16 move)
|
||||
{
|
||||
u32 i;
|
||||
@ -1919,9 +1929,8 @@ bool32 HasMoveWithLowAccuracy(u8 battlerAtk, u8 battlerDef, u8 accCheck, bool32
|
||||
if (ignoreStatus && IS_MOVE_STATUS(moves[i]))
|
||||
continue;
|
||||
else if ((!IS_MOVE_STATUS(moves[i]) && gBattleMoves[moves[i]].accuracy == 0)
|
||||
|| gBattleMoves[moves[i]].target & (MOVE_TARGET_USER | MOVE_TARGET_OPPONENTS_FIELD))
|
||||
|| AI_GetBattlerMoveTargetType(battlerAtk, moves[i]) & (MOVE_TARGET_USER | MOVE_TARGET_OPPONENTS_FIELD))
|
||||
continue;
|
||||
|
||||
if (AI_GetMoveAccuracy(battlerAtk, battlerDef, atkAbility, defAbility, atkHoldEffect, defHoldEffect, moves[i]) <= accCheck)
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ void DoMoveAnim(u16 move)
|
||||
gBattleAnimAttacker = gBattlerAttacker;
|
||||
gBattleAnimTarget = gBattlerTarget;
|
||||
// Make sure the anim target of moves hitting everyone is at the opposite side.
|
||||
if (gBattleMoves[move].target & MOVE_TARGET_FOES_AND_ALLY && IsDoubleBattle())
|
||||
if (GetBattlerMoveTargetType(gBattlerAttacker, move) & MOVE_TARGET_FOES_AND_ALLY && IsDoubleBattle())
|
||||
{
|
||||
while (GET_BATTLER_SIDE(gBattleAnimAttacker) == GET_BATTLER_SIDE(gBattleAnimTarget))
|
||||
{
|
||||
|
@ -2500,6 +2500,8 @@ void AnimTask_GetTrappedMoveAnimId(u8 taskId)
|
||||
gBattleAnimArgs[0] = TRAP_ANIM_MAGMA_STORM;
|
||||
else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_INFESTATION)
|
||||
gBattleAnimArgs[0] = TRAP_ANIM_INFESTATION;
|
||||
else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_SNAP_TRAP)
|
||||
gBattleAnimArgs[0] = TRAP_ANIM_SNAP_TRAP;
|
||||
else
|
||||
gBattleAnimArgs[0] = TRAP_ANIM_BIND;
|
||||
|
||||
|
@ -1584,9 +1584,9 @@ static void OpponentHandleChooseMove(void)
|
||||
BtlController_EmitTwoReturnValues(BUFFER_B, 15, gBattlerTarget);
|
||||
break;
|
||||
default:
|
||||
if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER))
|
||||
if (GetBattlerMoveTargetType(gActiveBattler, moveInfo->moves[chosenMoveId]) & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER))
|
||||
gBattlerTarget = gActiveBattler;
|
||||
if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & MOVE_TARGET_BOTH)
|
||||
if (GetBattlerMoveTargetType(gActiveBattler, moveInfo->moves[chosenMoveId]) & MOVE_TARGET_BOTH)
|
||||
{
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
|
||||
if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
|
||||
@ -1611,7 +1611,7 @@ static void OpponentHandleChooseMove(void)
|
||||
move = moveInfo->moves[chosenMoveId];
|
||||
} while (move == MOVE_NONE);
|
||||
|
||||
if (gBattleMoves[move].target & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER))
|
||||
if (GetBattlerMoveTargetType(gActiveBattler, move) & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER))
|
||||
BtlController_EmitTwoReturnValues(BUFFER_B, 10, (chosenMoveId) | (gActiveBattler << 8));
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
{
|
||||
|
@ -357,6 +357,7 @@ static void HandleInputChooseTarget(void)
|
||||
s32 i;
|
||||
static const u8 identities[MAX_BATTLERS_COUNT] = {B_POSITION_PLAYER_LEFT, B_POSITION_PLAYER_RIGHT, B_POSITION_OPPONENT_RIGHT, B_POSITION_OPPONENT_LEFT};
|
||||
u16 move = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_MOVE1 + gMoveSelectionCursor[gActiveBattler]);
|
||||
u16 moveTarget = GetBattlerMoveTargetType(gActiveBattler, move);
|
||||
|
||||
DoBounceEffect(gMultiUsePlayerCursor, BOUNCE_HEALTHBOX, 15, 1);
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
@ -397,7 +398,7 @@ static void HandleInputChooseTarget(void)
|
||||
PlaySE(SE_SELECT);
|
||||
gSprites[gBattlerSpriteIds[gMultiUsePlayerCursor]].callback = SpriteCb_HideAsMoveTarget;
|
||||
|
||||
if (gBattleMoves[move].target == (MOVE_TARGET_USER | MOVE_TARGET_ALLY))
|
||||
if (moveTarget == (MOVE_TARGET_USER | MOVE_TARGET_ALLY))
|
||||
{
|
||||
gMultiUsePlayerCursor ^= BIT_FLANK;
|
||||
}
|
||||
@ -426,7 +427,7 @@ static void HandleInputChooseTarget(void)
|
||||
case B_POSITION_PLAYER_RIGHT:
|
||||
if (gActiveBattler != gMultiUsePlayerCursor)
|
||||
i++;
|
||||
else if (gBattleMoves[move].target & MOVE_TARGET_USER_OR_SELECTED)
|
||||
else if (moveTarget & MOVE_TARGET_USER_OR_SELECTED)
|
||||
i++;
|
||||
break;
|
||||
case B_POSITION_OPPONENT_LEFT:
|
||||
@ -446,7 +447,7 @@ static void HandleInputChooseTarget(void)
|
||||
PlaySE(SE_SELECT);
|
||||
gSprites[gBattlerSpriteIds[gMultiUsePlayerCursor]].callback = SpriteCb_HideAsMoveTarget;
|
||||
|
||||
if (gBattleMoves[move].target == (MOVE_TARGET_USER | MOVE_TARGET_ALLY))
|
||||
if (moveTarget == (MOVE_TARGET_USER | MOVE_TARGET_ALLY))
|
||||
{
|
||||
gMultiUsePlayerCursor ^= BIT_FLANK;
|
||||
}
|
||||
@ -475,7 +476,7 @@ static void HandleInputChooseTarget(void)
|
||||
case B_POSITION_PLAYER_RIGHT:
|
||||
if (gActiveBattler != gMultiUsePlayerCursor)
|
||||
i++;
|
||||
else if (gBattleMoves[move].target & MOVE_TARGET_USER_OR_SELECTED)
|
||||
else if (moveTarget & MOVE_TARGET_USER_OR_SELECTED)
|
||||
i++;
|
||||
break;
|
||||
case B_POSITION_OPPONENT_LEFT:
|
||||
@ -608,7 +609,7 @@ static void HandleInputChooseMove(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
moveTarget = gBattleMoves[moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]].target;
|
||||
moveTarget = GetBattlerMoveTargetType(gActiveBattler, moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]);
|
||||
}
|
||||
|
||||
if (moveTarget & MOVE_TARGET_USER)
|
||||
|
@ -34,7 +34,7 @@ extern const struct CompressedSpriteSheet gSpriteSheet_EnemyShadow;
|
||||
extern const struct SpriteTemplate gSpriteTemplate_EnemyShadow;
|
||||
|
||||
// this file's functions
|
||||
static u8 GetBattlePalaceMoveGroup(u16 move);
|
||||
static u8 GetBattlePalaceMoveGroup(u8 battlerId, u16 move);
|
||||
static u16 GetBattlePalaceTarget(void);
|
||||
static void SpriteCB_TrainerSlideVertical(struct Sprite *sprite);
|
||||
static bool8 ShouldAnimBeDoneRegardlessOfSubstitute(u8 animId);
|
||||
@ -151,7 +151,7 @@ u16 ChooseMoveAndTargetInBattlePalace(void)
|
||||
{
|
||||
if (moveInfo->moves[i] == MOVE_NONE)
|
||||
break;
|
||||
if (selectedGroup == GetBattlePalaceMoveGroup(moveInfo->moves[i]) && moveInfo->currentPp[i] != 0)
|
||||
if (selectedGroup == GetBattlePalaceMoveGroup(gActiveBattler, moveInfo->moves[i]) && moveInfo->currentPp[i] != 0)
|
||||
selectedMoves |= gBitTable[i];
|
||||
}
|
||||
|
||||
@ -177,11 +177,11 @@ u16 ChooseMoveAndTargetInBattlePalace(void)
|
||||
{
|
||||
// validMoveFlags is used here as a bitfield for which moves can be used for each move group type
|
||||
// first 4 bits are for attack (1 for each move), then 4 bits for defense, and 4 for support
|
||||
if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_ATTACK && !(gBitTable[i] & unusableMovesBits))
|
||||
if (GetBattlePalaceMoveGroup(gActiveBattler, moveInfo->moves[i]) == PALACE_MOVE_GROUP_ATTACK && !(gBitTable[i] & unusableMovesBits))
|
||||
validMoveFlags += (1 << 0);
|
||||
if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_DEFENSE && !(gBitTable[i] & unusableMovesBits))
|
||||
if (GetBattlePalaceMoveGroup(gActiveBattler, moveInfo->moves[i]) == PALACE_MOVE_GROUP_DEFENSE && !(gBitTable[i] & unusableMovesBits))
|
||||
validMoveFlags += (1 << 4);
|
||||
if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_SUPPORT && !(gBitTable[i] & unusableMovesBits))
|
||||
if (GetBattlePalaceMoveGroup(gActiveBattler, moveInfo->moves[i]) == PALACE_MOVE_GROUP_SUPPORT && !(gBitTable[i] & unusableMovesBits))
|
||||
validMoveFlags += (1 << 8);
|
||||
}
|
||||
|
||||
@ -218,7 +218,7 @@ u16 ChooseMoveAndTargetInBattlePalace(void)
|
||||
do
|
||||
{
|
||||
i = Random() % MAX_MON_MOVES;
|
||||
if (!(gBitTable[i] & unusableMovesBits) && validMoveGroup == GetBattlePalaceMoveGroup(moveInfo->moves[i]))
|
||||
if (!(gBitTable[i] & unusableMovesBits) && validMoveGroup == GetBattlePalaceMoveGroup(gActiveBattler, moveInfo->moves[i]))
|
||||
chosenMoveId = i;
|
||||
} while (chosenMoveId == -1);
|
||||
}
|
||||
@ -247,7 +247,7 @@ u16 ChooseMoveAndTargetInBattlePalace(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
moveTarget = gBattleMoves[moveInfo->moves[chosenMoveId]].target;
|
||||
moveTarget = GetBattlerMoveTargetType(gActiveBattler, moveInfo->moves[chosenMoveId]);
|
||||
}
|
||||
|
||||
if (moveTarget & MOVE_TARGET_USER)
|
||||
@ -269,9 +269,9 @@ u16 ChooseMoveAndTargetInBattlePalace(void)
|
||||
#undef numValidMoveGroups
|
||||
#undef validMoveGroup
|
||||
|
||||
static u8 GetBattlePalaceMoveGroup(u16 move)
|
||||
static u8 GetBattlePalaceMoveGroup(u8 battlerId, u16 move)
|
||||
{
|
||||
switch (gBattleMoves[move].target)
|
||||
switch (GetBattlerMoveTargetType(battlerId, move))
|
||||
{
|
||||
case MOVE_TARGET_SELECTED:
|
||||
case MOVE_TARGET_USER_OR_SELECTED:
|
||||
|
@ -4820,13 +4820,19 @@ static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void)
|
||||
{
|
||||
gActiveBattler = gBattlerAttacker = gBattleStruct->focusPunchBattlerId;
|
||||
gBattleStruct->focusPunchBattlerId++;
|
||||
if (gChosenMoveByBattler[gActiveBattler] == MOVE_FOCUS_PUNCH
|
||||
&& !(gBattleMons[gActiveBattler].status1 & STATUS1_SLEEP)
|
||||
if (!(gBattleMons[gActiveBattler].status1 & STATUS1_SLEEP)
|
||||
&& !(gDisableStructs[gBattlerAttacker].truantCounter)
|
||||
&& !(gProtectStructs[gActiveBattler].noValidMoves))
|
||||
{
|
||||
BattleScriptExecute(BattleScript_FocusPunchSetUp);
|
||||
return;
|
||||
switch(gChosenMoveByBattler[gActiveBattler])
|
||||
{
|
||||
case MOVE_FOCUS_PUNCH:
|
||||
BattleScriptExecute(BattleScript_FocusPunchSetUp);
|
||||
return;
|
||||
case MOVE_BEAK_BLAST:
|
||||
BattleScriptExecute(BattleScript_BeakBlastSetUp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -144,6 +144,7 @@ static const u8 sText_PkmnDugHole[] = _("{B_ATK_NAME_WITH_PREFIX} dug a hole!");
|
||||
static const u8 sText_PkmnHidUnderwater[] = _("{B_ATK_NAME_WITH_PREFIX} hid\nunderwater!");
|
||||
static const u8 sText_PkmnSprangUp[] = _("{B_ATK_NAME_WITH_PREFIX} sprang up!");
|
||||
static const u8 sText_PkmnSqueezedByBind[] = _("{B_DEF_NAME_WITH_PREFIX} was squeezed by\n{B_ATK_NAME_WITH_PREFIX}'s BIND!");
|
||||
static const u8 sText_PkmnInSnapTrap[] = _("{B_DEF_NAME_WITH_PREFIX} got trapped\nby a snap trap!");
|
||||
static const u8 sText_PkmnTrappedInVortex[] = _("{B_DEF_NAME_WITH_PREFIX} was trapped\nin the vortex!");
|
||||
static const u8 sText_PkmnTrappedBySandTomb[] = _("{B_DEF_NAME_WITH_PREFIX} was trapped\nby SAND TOMB!");
|
||||
static const u8 sText_PkmnWrappedBy[] = _("{B_DEF_NAME_WITH_PREFIX} was WRAPPED by\n{B_ATK_NAME_WITH_PREFIX}!");
|
||||
@ -734,9 +735,16 @@ static const u8 sText_NeutralizingGasEnters[] = _("Neutralizing Gas filled the a
|
||||
static const u8 sText_NeutralizingGasOver[] = _("The effects of Neutralizing\nGas wore off!");
|
||||
static const u8 sText_PkmnTookTargetHigh[] = _("{B_ATK_NAME_WITH_PREFIX} took {B_DEF_NAME_WITH_PREFIX}\ninto the air!");
|
||||
static const u8 sText_TargetTooHeavy[] = _("But the target\nwas too heavy!");
|
||||
static const u8 sText_MeteorBeamCharging[] = _("{B_ATK_NAME_WITH_PREFIX} is overflowing\nwith space energy!");
|
||||
static const u8 sText_HeatingUpBeak[] = _("{B_ATK_NAME_WITH_PREFIX} started\nheating up its beak!");
|
||||
static const u8 sText_CourtChange[] = _("{B_ATK_NAME_WITH_PREFIX} swapped the battle\neffects affecting each side!");
|
||||
|
||||
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
|
||||
{
|
||||
[STRINGID_COURTCHANGE - BATTLESTRINGS_TABLE_START] = sText_CourtChange,
|
||||
[STRINGID_HEATUPBEAK - BATTLESTRINGS_TABLE_START] = sText_HeatingUpBeak,
|
||||
[STRINGID_METEORBEAMCHARGING - BATTLESTRINGS_TABLE_START] = sText_MeteorBeamCharging,
|
||||
[STRINGID_PKMNINSNAPTRAP - BATTLESTRINGS_TABLE_START] = sText_PkmnInSnapTrap,
|
||||
[STRINGID_NEUTRALIZINGGASOVER - BATTLESTRINGS_TABLE_START] = sText_NeutralizingGasOver,
|
||||
[STRINGID_NEUTRALIZINGGASENTERS - BATTLESTRINGS_TABLE_START] = sText_NeutralizingGasEnters,
|
||||
[STRINGID_BATTLERTYPECHANGEDTO - BATTLESTRINGS_TABLE_START] = sText_BattlerTypeChangedTo,
|
||||
@ -1550,6 +1558,7 @@ const u16 gFirstTurnOfTwoStringIds[] =
|
||||
[B_MSG_TURN1_GEOMANCY] = STRINGID_PKNMABSORBINGPOWER,
|
||||
[B_MSG_TURN1_FREEZE_SHOCK] = STRINGID_CLOAKEDINAFREEZINGLIGHT,
|
||||
[B_MSG_TURN1_SKY_DROP] = STRINGID_PKMNTOOKTARGETHIGH,
|
||||
[B_MSG_TURN1_METEOR_BEAM] = STRINGID_METEORBEAMCHARGING,
|
||||
};
|
||||
|
||||
// Index copied from move's index in sTrappingMoves
|
||||
@ -1563,6 +1572,7 @@ const u16 gWrappedStringIds[] =
|
||||
STRINGID_PKMNTRAPPEDBYSANDTOMB, // MOVE_SAND_TOMB
|
||||
STRINGID_TRAPPEDBYSWIRLINGMAGMA, // MOVE_MAGMA_STORM
|
||||
STRINGID_INFESTATION, // MOVE_INFESTATION
|
||||
STRINGID_PKMNINSNAPTRAP, // MOVE_SNAPTRAP
|
||||
};
|
||||
|
||||
const u16 gMistUsedStringIds[] =
|
||||
|
@ -281,7 +281,7 @@ static const s32 sExperienceScalingFactors[] =
|
||||
|
||||
static const u16 sTrappingMoves[] =
|
||||
{
|
||||
MOVE_BIND, MOVE_WRAP, MOVE_FIRE_SPIN, MOVE_CLAMP, MOVE_WHIRLPOOL, MOVE_SAND_TOMB, MOVE_MAGMA_STORM, MOVE_INFESTATION, 0xFFFF
|
||||
MOVE_BIND, MOVE_WRAP, MOVE_FIRE_SPIN, MOVE_CLAMP, MOVE_WHIRLPOOL, MOVE_SAND_TOMB, MOVE_MAGMA_STORM, MOVE_INFESTATION, MOVE_SNAP_TRAP, 0xFFFF
|
||||
};
|
||||
|
||||
#define STAT_CHANGE_WORKED 0
|
||||
@ -1296,12 +1296,12 @@ static const u8 sBattlePalaceNatureToFlavorTextId[NUM_NATURES] =
|
||||
[NATURE_QUIRKY] = B_MSG_EAGER_FOR_MORE,
|
||||
};
|
||||
|
||||
static bool32 NoTargetPresent(u32 move)
|
||||
static bool32 NoTargetPresent(u8 battlerId, u32 move)
|
||||
{
|
||||
if (!IsBattlerAlive(gBattlerTarget))
|
||||
gBattlerTarget = GetMoveTarget(move, NO_TARGET_OVERRIDE);
|
||||
|
||||
switch (gBattleMoves[move].target)
|
||||
switch (GetBattlerMoveTargetType(battlerId, move))
|
||||
{
|
||||
case MOVE_TARGET_SELECTED:
|
||||
case MOVE_TARGET_DEPENDS:
|
||||
@ -1446,7 +1446,7 @@ static void Cmd_attackcanceler(void)
|
||||
}
|
||||
|
||||
gHitMarker |= HITMARKER_OBEYS;
|
||||
if (NoTargetPresent(gCurrentMove) && (!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)))
|
||||
if (NoTargetPresent(gBattlerAttacker, gCurrentMove) && (!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)))
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_ButItFailedAtkStringPpReduce;
|
||||
if (!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))
|
||||
@ -1530,6 +1530,11 @@ static void Cmd_attackcanceler(void)
|
||||
gBattleCommunication[MISS_TYPE] = B_MSG_PROTECTED;
|
||||
gBattlescriptCurrInstr++;
|
||||
}
|
||||
else if (gProtectStructs[gBattlerTarget].beakBlastCharge && IsMoveMakingContact(gCurrentMove, gBattlerAttacker))
|
||||
{
|
||||
gProtectStructs[gBattlerAttacker].touchedProtectLike = TRUE;
|
||||
gBattlescriptCurrInstr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlescriptCurrInstr++;
|
||||
@ -1724,6 +1729,7 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
static void Cmd_accuracycheck(void)
|
||||
{
|
||||
u16 type, move = T2_READ_16(gBattlescriptCurrInstr + 5);
|
||||
u16 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, move);
|
||||
|
||||
if (move == ACC_CURR_MOVE)
|
||||
move = gCurrentMove;
|
||||
@ -1753,7 +1759,7 @@ static void Cmd_accuracycheck(void)
|
||||
gBattleStruct->blunderPolicy = TRUE; // Only activates from missing through acc/evasion checks
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE &&
|
||||
(gBattleMoves[move].target == MOVE_TARGET_BOTH || gBattleMoves[move].target == MOVE_TARGET_FOES_AND_ALLY))
|
||||
(moveTarget == MOVE_TARGET_BOTH || moveTarget == MOVE_TARGET_FOES_AND_ALLY))
|
||||
gBattleCommunication[MISS_TYPE] = B_MSG_AVOIDED_ATK;
|
||||
else
|
||||
gBattleCommunication[MISS_TYPE] = B_MSG_MISSED;
|
||||
@ -1787,7 +1793,7 @@ static void Cmd_ppreduce(void)
|
||||
|
||||
if (!gSpecialStatuses[gBattlerAttacker].ppNotAffectedByPressure)
|
||||
{
|
||||
switch (gBattleMoves[gCurrentMove].target)
|
||||
switch (GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove))
|
||||
{
|
||||
case MOVE_TARGET_FOES_AND_ALLY:
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
@ -2087,6 +2093,8 @@ static void Cmd_multihitresultmessage(void)
|
||||
|
||||
static void Cmd_attackanimation(void)
|
||||
{
|
||||
u16 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
|
||||
|
||||
if (gBattleControllerExecFlags)
|
||||
return;
|
||||
|
||||
@ -2103,9 +2111,9 @@ static void Cmd_attackanimation(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((gBattleMoves[gCurrentMove].target & MOVE_TARGET_BOTH
|
||||
|| gBattleMoves[gCurrentMove].target & MOVE_TARGET_FOES_AND_ALLY
|
||||
|| gBattleMoves[gCurrentMove].target & MOVE_TARGET_DEPENDS)
|
||||
if ((moveTarget & MOVE_TARGET_BOTH
|
||||
|| moveTarget & MOVE_TARGET_FOES_AND_ALLY
|
||||
|| moveTarget & MOVE_TARGET_DEPENDS)
|
||||
&& gBattleScripting.animTargetsHit)
|
||||
{
|
||||
gBattlescriptCurrInstr++;
|
||||
@ -3159,7 +3167,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
|
||||
| BATTLE_TYPE_LINK
|
||||
| BATTLE_TYPE_RECORDED_LINK
|
||||
| BATTLE_TYPE_SECRET_BASE))
|
||||
&& (gWishFutureKnock.knockedOffMons[side] & gBitTable[gBattlerPartyIndexes[gBattlerAttacker]]))
|
||||
&& (gWishFutureKnock.knockedOffMons[side] & gBitTable[gBattlerPartyIndexes[gBattlerAttacker]]))
|
||||
{
|
||||
gBattlescriptCurrInstr++;
|
||||
}
|
||||
@ -3495,6 +3503,13 @@ void SetMoveEffect(bool32 primary, u32 certain)
|
||||
gBattleMons[gBattlerTarget].status2 |= STATUS2_ESCAPE_PREVENTION;
|
||||
gBattleMons[gBattlerAttacker].status2 |= STATUS2_ESCAPE_PREVENTION;
|
||||
break;
|
||||
case MOVE_EFFECT_SCALE_SHOT:
|
||||
if (!NoAliveMonsForEitherParty())
|
||||
{
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_DefDownSpeedUp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5014,7 +5029,7 @@ static void Cmd_moveend(void)
|
||||
}
|
||||
else if (gProtectStructs[gBattlerTarget].obstructed && gCurrentMove != MOVE_SUCKER_PUNCH)
|
||||
{
|
||||
gProtectStructs[gBattlerAttacker].touchedProtectLike = 0;
|
||||
gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE;
|
||||
i = gBattlerAttacker;
|
||||
gBattlerAttacker = gBattlerTarget;
|
||||
gBattlerTarget = i; // gBattlerTarget and gBattlerAttacker are swapped in order to activate Defiant, if applicable
|
||||
@ -5023,6 +5038,17 @@ static void Cmd_moveend(void)
|
||||
gBattlescriptCurrInstr = BattleScript_KingsShieldEffect;
|
||||
effect = 1;
|
||||
}
|
||||
// Not strictly a protect effect, but works the same way
|
||||
else if (gProtectStructs[gBattlerTarget].beakBlastCharge
|
||||
&& CanBeBurned(gBattlerAttacker)
|
||||
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
|
||||
{
|
||||
gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE;
|
||||
gBattleMons[gBattlerAttacker].status1 = STATUS1_BURN;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_BeakBlastBurn;
|
||||
effect = 1;
|
||||
}
|
||||
}
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
@ -5318,6 +5344,8 @@ static void Cmd_moveend(void)
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_NEXT_TARGET: // For moves hitting two opposing Pokemon.
|
||||
{
|
||||
u16 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
|
||||
// Set a flag if move hits either target (for throat spray that can't check damage)
|
||||
if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
|
||||
@ -5326,12 +5354,13 @@ static void Cmd_moveend(void)
|
||||
if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
&& gBattleTypeFlags & BATTLE_TYPE_DOUBLE
|
||||
&& !gProtectStructs[gBattlerAttacker].chargingTurn
|
||||
&& (gBattleMoves[gCurrentMove].target == MOVE_TARGET_BOTH || gBattleMoves[gCurrentMove].target == MOVE_TARGET_FOES_AND_ALLY)
|
||||
&& (moveTarget == MOVE_TARGET_BOTH
|
||||
|| moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
&& !(gHitMarker & HITMARKER_NO_ATTACKSTRING))
|
||||
{
|
||||
u8 battlerId;
|
||||
|
||||
if (gBattleMoves[gCurrentMove].target == MOVE_TARGET_FOES_AND_ALLY)
|
||||
if (moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
gHitMarker |= HITMARKER_NO_PPDEDUCT;
|
||||
for (battlerId = gBattlerTarget + 1; battlerId < gBattlersCount; battlerId++)
|
||||
@ -5367,6 +5396,7 @@ static void Cmd_moveend(void)
|
||||
RecordLastUsedMoveBy(gBattlerAttacker, gCurrentMove);
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
}
|
||||
case MOVEEND_EJECT_BUTTON:
|
||||
if (gCurrentMove != MOVE_DRAGON_TAIL
|
||||
&& gCurrentMove != MOVE_CIRCLE_THROW
|
||||
@ -7621,6 +7651,66 @@ static bool32 IsRototillerAffected(u32 battlerId)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define COURTCHANGE_SWAP(status, structField, temp) \
|
||||
{ \
|
||||
temp = gSideStatuses[B_SIDE_PLAYER]; \
|
||||
if (gSideStatuses[B_SIDE_OPPONENT] & status) \
|
||||
gSideStatuses[B_SIDE_PLAYER] |= status; \
|
||||
else \
|
||||
gSideStatuses[B_SIDE_PLAYER] &= ~(status); \
|
||||
if (temp & status) \
|
||||
gSideStatuses[B_SIDE_OPPONENT] |= status; \
|
||||
else \
|
||||
gSideStatuses[B_SIDE_OPPONENT] &= ~(status); \
|
||||
SWAP(sideTimerPlayer->structField, sideTimerOpp->structField, temp);\
|
||||
} \
|
||||
|
||||
#define UPDATE_COURTCHANGED_BATTLER(structField)\
|
||||
{ \
|
||||
sideTimerPlayer->structField ^= BIT_SIDE; \
|
||||
sideTimerOpp->structField ^= BIT_SIDE; \
|
||||
} \
|
||||
|
||||
static bool32 CourtChangeSwapSideStatuses(void)
|
||||
{
|
||||
struct SideTimer *sideTimerPlayer = &gSideTimers[B_SIDE_PLAYER];
|
||||
struct SideTimer *sideTimerOpp = &gSideTimers[B_SIDE_OPPONENT];
|
||||
u32 temp;
|
||||
|
||||
// TODO: add Pledge-related effects
|
||||
// TODO: add Gigantamax-related effects
|
||||
|
||||
// Swap timers and statuses
|
||||
COURTCHANGE_SWAP(SIDE_STATUS_REFLECT, reflectTimer, temp)
|
||||
COURTCHANGE_SWAP(SIDE_STATUS_LIGHTSCREEN, lightscreenTimer, temp)
|
||||
COURTCHANGE_SWAP(SIDE_STATUS_MIST, mistTimer, temp);
|
||||
COURTCHANGE_SWAP(SIDE_STATUS_SAFEGUARD, safeguardTimer, temp);
|
||||
COURTCHANGE_SWAP(SIDE_STATUS_AURORA_VEIL, auroraVeilTimer, temp);
|
||||
COURTCHANGE_SWAP(SIDE_STATUS_TAILWIND, tailwindTimer, temp);
|
||||
// Lucky Chant doesn't exist in gen 8, but seems like it should be affected by Court Change
|
||||
COURTCHANGE_SWAP(SIDE_STATUS_LUCKY_CHANT, luckyChantTimer, temp);
|
||||
COURTCHANGE_SWAP(SIDE_STATUS_SPIKES, spikesAmount, temp);
|
||||
COURTCHANGE_SWAP(SIDE_STATUS_STEALTH_ROCK, stealthRockAmount, temp);
|
||||
COURTCHANGE_SWAP(SIDE_STATUS_TOXIC_SPIKES, toxicSpikesAmount, temp);
|
||||
COURTCHANGE_SWAP(SIDE_STATUS_STICKY_WEB, stickyWebAmount, temp);
|
||||
|
||||
// Change battler IDs of swapped effects. Needed for the correct string when they expire
|
||||
// E.g. "Foe's Reflect wore off!"
|
||||
UPDATE_COURTCHANGED_BATTLER(reflectBattlerId);
|
||||
UPDATE_COURTCHANGED_BATTLER(lightscreenBattlerId);
|
||||
UPDATE_COURTCHANGED_BATTLER(mistBattlerId);
|
||||
UPDATE_COURTCHANGED_BATTLER(safeguardBattlerId);
|
||||
UPDATE_COURTCHANGED_BATTLER(auroraVeilBattlerId);
|
||||
UPDATE_COURTCHANGED_BATTLER(tailwindBattlerId);
|
||||
UPDATE_COURTCHANGED_BATTLER(luckyChantBattlerId);
|
||||
|
||||
// For Mirror Armor only
|
||||
gBattleStruct->stickyWebUser = gBattlerAttacker;
|
||||
|
||||
// Track which side originally set the Sticky Web
|
||||
SWAP(sideTimerPlayer->stickyWebBattlerSide, sideTimerOpp->stickyWebBattlerSide, temp);
|
||||
}
|
||||
|
||||
static void Cmd_various(void)
|
||||
{
|
||||
struct Pokemon *mon;
|
||||
@ -8322,6 +8412,7 @@ static void Cmd_various(void)
|
||||
case MOVE_MIRROR_COAT:
|
||||
case MOVE_METAL_BURST:
|
||||
case MOVE_ME_FIRST:
|
||||
case MOVE_BEAK_BLAST:
|
||||
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
|
||||
break;
|
||||
default:
|
||||
@ -9474,6 +9565,12 @@ static void Cmd_various(void)
|
||||
case VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM:
|
||||
gBattleMons[gActiveBattler].item = gLastUsedItem;
|
||||
break;
|
||||
case VARIOUS_SET_BEAK_BLAST:
|
||||
gProtectStructs[gBattlerAttacker].beakBlastCharge = TRUE;
|
||||
break;
|
||||
case VARIOUS_SWAP_SIDE_STATUSES:
|
||||
CourtChangeSwapSideStatuses();
|
||||
break;
|
||||
} // End of switch (gBattlescriptCurrInstr[2])
|
||||
|
||||
gBattlescriptCurrInstr += 3;
|
||||
@ -9618,7 +9715,7 @@ static void Cmd_jumpifnexttargetvalid(void)
|
||||
|
||||
for (gBattlerTarget++; gBattlerTarget < gBattlersCount; gBattlerTarget++)
|
||||
{
|
||||
if (gBattlerTarget == gBattlerAttacker && !(gBattleMoves[gCurrentMove].target & MOVE_TARGET_USER))
|
||||
if (gBattlerTarget == gBattlerAttacker && !(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER))
|
||||
continue;
|
||||
if (IsBattlerAlive(gBattlerTarget))
|
||||
break;
|
||||
@ -11429,7 +11526,8 @@ static bool8 IsTwoTurnsMove(u16 move)
|
||||
|| gBattleMoves[move].effect == EFFECT_TWO_TURNS_ATTACK
|
||||
|| gBattleMoves[move].effect == EFFECT_SOLAR_BEAM
|
||||
|| gBattleMoves[move].effect == EFFECT_SEMI_INVULNERABLE
|
||||
|| gBattleMoves[move].effect == EFFECT_BIDE)
|
||||
|| gBattleMoves[move].effect == EFFECT_BIDE
|
||||
|| gBattleMoves[move].effect == EFFECT_METEOR_BEAM)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
@ -12123,6 +12221,7 @@ static void Cmd_recoverbasedonsunlight(void)
|
||||
static void Cmd_setstickyweb(void)
|
||||
{
|
||||
u8 targetSide = GetBattlerSide(gBattlerTarget);
|
||||
|
||||
if (gSideStatuses[targetSide] & SIDE_STATUS_STICKY_WEB)
|
||||
{
|
||||
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
|
||||
@ -12130,6 +12229,7 @@ static void Cmd_setstickyweb(void)
|
||||
else
|
||||
{
|
||||
gSideStatuses[targetSide] |= SIDE_STATUS_STICKY_WEB;
|
||||
gSideTimers[targetSide].stickyWebBattlerSide = GetBattlerSide(gBattlerAttacker); // For Court Change/Defiant - set this to the user's side
|
||||
gSideTimers[targetSide].stickyWebAmount = 1;
|
||||
gBattleStruct->stickyWebUser = gBattlerAttacker; // For Mirror Armor
|
||||
gBattlescriptCurrInstr += 5;
|
||||
@ -12140,7 +12240,7 @@ static void Cmd_selectfirstvalidtarget(void)
|
||||
{
|
||||
for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++)
|
||||
{
|
||||
if (gBattlerTarget == gBattlerAttacker && !(gBattleMoves[gCurrentMove].target & MOVE_TARGET_USER))
|
||||
if (gBattlerTarget == gBattlerAttacker && !(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER))
|
||||
continue;
|
||||
if (IsBattlerAlive(gBattlerTarget))
|
||||
break;
|
||||
@ -12441,7 +12541,7 @@ static void Cmd_tryswapitems(void) // trick
|
||||
u8 sideAttacker = GetBattlerSide(gBattlerAttacker);
|
||||
u8 sideTarget = GetBattlerSide(gBattlerTarget);
|
||||
|
||||
// you can't swap items if they were knocked off in regular battles
|
||||
// You can't swap items if they were knocked off in regular battles
|
||||
if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK
|
||||
| BATTLE_TYPE_EREADER_TRAINER
|
||||
| BATTLE_TYPE_FRONTIER
|
||||
|
@ -238,6 +238,7 @@ bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move)
|
||||
void HandleAction_UseMove(void)
|
||||
{
|
||||
u32 i, side, moveType, var = 4;
|
||||
u16 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
|
||||
|
||||
gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
|
||||
if (gBattleStruct->absentBattlerFlags & gBitTable[gBattlerAttacker] || !IsBattlerAlive(gBattlerAttacker))
|
||||
@ -310,14 +311,14 @@ void HandleAction_UseMove(void)
|
||||
// choose target
|
||||
side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE;
|
||||
if (IsAffectedByFollowMe(gBattlerAttacker, side, gCurrentMove)
|
||||
&& gBattleMoves[gCurrentMove].target == MOVE_TARGET_SELECTED
|
||||
&& moveTarget == MOVE_TARGET_SELECTED
|
||||
&& GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gSideTimers[side].followmeTarget))
|
||||
{
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = gBattlerTarget = gSideTimers[side].followmeTarget; // follow me moxie fix
|
||||
}
|
||||
else if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
&& gSideTimers[side].followmeTimer == 0
|
||||
&& (gBattleMoves[gCurrentMove].power != 0 || gBattleMoves[gCurrentMove].target != MOVE_TARGET_USER)
|
||||
&& (gBattleMoves[gCurrentMove].power != 0 || moveTarget != MOVE_TARGET_USER)
|
||||
&& ((GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC)
|
||||
|| (GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_STORM_DRAIN && moveType == TYPE_WATER)))
|
||||
{
|
||||
@ -338,7 +339,7 @@ void HandleAction_UseMove(void)
|
||||
}
|
||||
if (var == 4)
|
||||
{
|
||||
if (gBattleMoves[gChosenMove].target & MOVE_TARGET_RANDOM)
|
||||
if (moveTarget & MOVE_TARGET_RANDOM)
|
||||
{
|
||||
if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
|
||||
{
|
||||
@ -355,7 +356,7 @@ void HandleAction_UseMove(void)
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
|
||||
}
|
||||
}
|
||||
else if (gBattleMoves[gChosenMove].target & MOVE_TARGET_FOES_AND_ALLY)
|
||||
else if (moveTarget & MOVE_TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++)
|
||||
{
|
||||
@ -399,7 +400,7 @@ void HandleAction_UseMove(void)
|
||||
}
|
||||
}
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
|
||||
&& gBattleMoves[gChosenMove].target & MOVE_TARGET_RANDOM)
|
||||
&& moveTarget & MOVE_TARGET_RANDOM)
|
||||
{
|
||||
if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
|
||||
{
|
||||
@ -422,7 +423,7 @@ void HandleAction_UseMove(void)
|
||||
gBattlerTarget = GetBattlerAtPosition(GetBattlerPosition(gBattlerTarget) ^ BIT_FLANK);
|
||||
}
|
||||
}
|
||||
else if (gBattleMoves[gChosenMove].target == MOVE_TARGET_ALLY)
|
||||
else if (moveTarget == MOVE_TARGET_ALLY)
|
||||
{
|
||||
if (IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker)))
|
||||
gBattlerTarget = BATTLE_PARTNER(gBattlerAttacker);
|
||||
@ -430,7 +431,7 @@ void HandleAction_UseMove(void)
|
||||
gBattlerTarget = gBattlerAttacker;
|
||||
}
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
|
||||
&& gBattleMoves[gChosenMove].target == MOVE_TARGET_FOES_AND_ALLY)
|
||||
&& moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++)
|
||||
{
|
||||
@ -1547,6 +1548,7 @@ bool8 WasUnableToUseMove(u8 battler)
|
||||
|
||||
void PrepareStringBattle(u16 stringId, u8 battler)
|
||||
{
|
||||
u32 targetSide = GetBattlerSide(gBattlerTarget);
|
||||
u16 battlerAbility = GetBattlerAbility(battler);
|
||||
u16 targetAbility = GetBattlerAbility(gBattlerTarget);
|
||||
// Support for Contrary ability.
|
||||
@ -1567,8 +1569,10 @@ void PrepareStringBattle(u16 stringId, u8 battler)
|
||||
&& ((targetAbility == ABILITY_DEFIANT && CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
|| (targetAbility == ABILITY_COMPETITIVE && CompareStat(gBattlerTarget, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)))
|
||||
&& gSpecialStatuses[gBattlerTarget].changedStatsBattlerId != BATTLE_PARTNER(gBattlerTarget)
|
||||
&& gSpecialStatuses[gBattlerTarget].changedStatsBattlerId != gBattlerTarget)
|
||||
&& ((gSpecialStatuses[gBattlerTarget].changedStatsBattlerId != gBattlerTarget) || gBattleScripting.stickyWebStatDrop == 1)
|
||||
&& !(gBattleScripting.stickyWebStatDrop == 1 && gSideTimers[targetSide].stickyWebBattlerSide == targetSide)) // Sticky Web must have been set by the foe
|
||||
{
|
||||
gBattleScripting.stickyWebStatDrop = 0;
|
||||
gBattlerAbility = gBattlerTarget;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_DefiantActivates;
|
||||
@ -4808,7 +4812,10 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
}
|
||||
break;
|
||||
case ABILITYEFFECT_MOVES_BLOCK: // 2
|
||||
if ((gLastUsedAbility == ABILITY_SOUNDPROOF && gBattleMoves[move].flags & FLAG_SOUND && !(gBattleMoves[move].target & MOVE_TARGET_USER))
|
||||
{
|
||||
u16 moveTarget = GetBattlerMoveTargetType(battler, move);
|
||||
|
||||
if ((gLastUsedAbility == ABILITY_SOUNDPROOF && gBattleMoves[move].flags & FLAG_SOUND && !(moveTarget & MOVE_TARGET_USER))
|
||||
|| (gLastUsedAbility == ABILITY_BULLETPROOF && gBattleMoves[move].flags & FLAG_BALLISTIC))
|
||||
{
|
||||
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)
|
||||
@ -4831,14 +4838,14 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
else if (BlocksPrankster(move, gBattlerAttacker, gBattlerTarget, TRUE)
|
||||
&& !(IS_MOVE_STATUS(move) && GetBattlerAbility(gBattlerTarget) == ABILITY_MAGIC_BOUNCE))
|
||||
{
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(gBattleMoves[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)))
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(moveTarget & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)))
|
||||
CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected
|
||||
gBattleScripting.battler = gBattlerAbility = gBattlerTarget;
|
||||
gBattlescriptCurrInstr = BattleScript_DarkTypePreventsPrankster;
|
||||
effect = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ABILITYEFFECT_ABSORBING: // 3
|
||||
if (move != MOVE_NONE)
|
||||
{
|
||||
@ -7424,7 +7431,7 @@ u32 GetMoveTarget(u16 move, u8 setTarget)
|
||||
if (setTarget != NO_TARGET_OVERRIDE)
|
||||
moveTarget = setTarget - 1;
|
||||
else
|
||||
moveTarget = gBattleMoves[move].target;
|
||||
moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, move);
|
||||
|
||||
// Special cases
|
||||
if (move == MOVE_CURSE && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST))
|
||||
@ -7697,7 +7704,7 @@ bool32 IsBattlerProtected(u8 battlerId, u16 move)
|
||||
else if (gProtectStructs[battlerId].protected)
|
||||
return TRUE;
|
||||
else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_WIDE_GUARD
|
||||
&& gBattleMoves[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))
|
||||
&& GetBattlerMoveTargetType(gBattlerAttacker, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))
|
||||
return TRUE;
|
||||
else if (gProtectStructs[battlerId].banefulBunkered)
|
||||
return TRUE;
|
||||
@ -7823,7 +7830,7 @@ u32 CountBattlerStatIncreases(u8 battlerId, bool32 countEvasionAcc)
|
||||
|
||||
u32 GetMoveTargetCount(u16 move, u8 battlerAtk, u8 battlerDef)
|
||||
{
|
||||
switch (gBattleMoves[move].target)
|
||||
switch (GetBattlerMoveTargetType(gBattlerAttacker, move))
|
||||
{
|
||||
case MOVE_TARGET_BOTH:
|
||||
return IsBattlerAlive(battlerDef)
|
||||
@ -8162,9 +8169,17 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef)
|
||||
&& IsBattlerGrounded(gBattlerAttacker))
|
||||
basePower *= 2;
|
||||
break;
|
||||
case EFFECT_EXPANDING_FORCE:
|
||||
if (IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_PSYCHIC_TERRAIN))
|
||||
MulModifier(&basePower, UQ_4_12(1.5));
|
||||
break;
|
||||
case EFFECT_RISING_VOLTAGE:
|
||||
if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN))
|
||||
basePower *= 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// move-specific base power changes
|
||||
// Move-specific base power changes
|
||||
switch (move)
|
||||
{
|
||||
case MOVE_WATER_SHURIKEN:
|
||||
@ -10004,7 +10019,7 @@ bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 chec
|
||||
return FALSE;
|
||||
if (GetBattlerSide(battlerPrankster) == GetBattlerSide(battlerDef))
|
||||
return FALSE;
|
||||
if (checkTarget && (gBattleMoves[move].target & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS)))
|
||||
if (checkTarget && (GetBattlerMoveTargetType(battlerPrankster, move) & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS)))
|
||||
return FALSE;
|
||||
if (!IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK))
|
||||
return FALSE;
|
||||
@ -10036,3 +10051,16 @@ bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags)
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Gets move target before redirection effects etc. are applied
|
||||
// Possible return values are defined in battle.h following MOVE_TARGET_SELECTED
|
||||
u32 GetBattlerMoveTargetType(u8 battlerId, u16 move)
|
||||
{
|
||||
u32 target;
|
||||
|
||||
if (gBattleMoves[move].effect == EFFECT_EXPANDING_FORCE
|
||||
&& IsBattlerTerrainAffected(battlerId, STATUS_FIELD_PSYCHIC_TERRAIN))
|
||||
return MOVE_TARGET_BOTH;
|
||||
else
|
||||
return gBattleMoves[move].target;
|
||||
}
|
||||
|
@ -5388,7 +5388,7 @@ static void SetBattleTargetSpritePosition(void)
|
||||
|
||||
static void SetMoveTargetPosition(u16 move)
|
||||
{
|
||||
switch (gBattleMoves[move].target)
|
||||
switch (GetBattlerMoveTargetType(gBattlerAttacker, move))
|
||||
{
|
||||
case MOVE_TARGET_USER_OR_SELECTED:
|
||||
case MOVE_TARGET_USER:
|
||||
|
@ -10142,7 +10142,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
|
||||
|
||||
[MOVE_BEAK_BLAST] =
|
||||
{
|
||||
.effect = EFFECT_PLACEHOLDER,
|
||||
.effect = EFFECT_BEAK_BLAST,
|
||||
.power = 100,
|
||||
.type = TYPE_FLYING,
|
||||
.accuracy = 100,
|
||||
@ -10212,13 +10212,13 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
|
||||
|
||||
[MOVE_SHELL_TRAP] =
|
||||
{
|
||||
.effect = EFFECT_PLACEHOLDER,
|
||||
.effect = EFFECT_PLACEHOLDER, // EFFECT_SHELL_TRAP,
|
||||
.power = 150,
|
||||
.type = TYPE_FIRE,
|
||||
.accuracy = 100,
|
||||
.pp = 5,
|
||||
.secondaryEffectChance = 0,
|
||||
.target = MOVE_TARGET_SELECTED,
|
||||
.target = MOVE_TARGET_BOTH,
|
||||
.priority = -3,
|
||||
.flags = FLAG_PROTECT_AFFECTED | FLAG_KINGS_ROCK_AFFECTED,
|
||||
.split = SPLIT_SPECIAL,
|
||||
@ -10913,7 +10913,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
|
||||
|
||||
[MOVE_COURT_CHANGE] =
|
||||
{
|
||||
.effect = EFFECT_PLACEHOLDER, //TODO
|
||||
.effect = EFFECT_COURT_CHANGE,
|
||||
.power = 0,
|
||||
.type = TYPE_NORMAL,
|
||||
.accuracy = 100,
|
||||
@ -10983,7 +10983,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
|
||||
|
||||
[MOVE_SNAP_TRAP] =
|
||||
{
|
||||
.effect = EFFECT_TRAP, //TODO: add case/effect
|
||||
.effect = EFFECT_TRAP,
|
||||
.power = 35,
|
||||
.type = TYPE_GRASS,
|
||||
.accuracy = 100,
|
||||
@ -11235,7 +11235,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
|
||||
|
||||
[MOVE_EXPANDING_FORCE] =
|
||||
{
|
||||
.effect = EFFECT_PLACEHOLDER, //TODO
|
||||
.effect = EFFECT_EXPANDING_FORCE,
|
||||
.power = 80,
|
||||
.type = TYPE_PSYCHIC,
|
||||
.accuracy = 100,
|
||||
@ -11263,12 +11263,12 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
|
||||
|
||||
[MOVE_SCALE_SHOT] =
|
||||
{
|
||||
.effect = EFFECT_PLACEHOLDER, //TODO (EFFECT_MULTI_HIT + ABILITY_WEAK_ARMOR,
|
||||
.effect = EFFECT_SCALE_SHOT,
|
||||
.power = 25,
|
||||
.type = TYPE_DRAGON,
|
||||
.accuracy = 90,
|
||||
.pp = 20,
|
||||
.secondaryEffectChance = 0,
|
||||
.secondaryEffectChance = 100,
|
||||
.target = MOVE_TARGET_SELECTED,
|
||||
.priority = 0,
|
||||
.flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED,
|
||||
@ -11277,7 +11277,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
|
||||
|
||||
[MOVE_METEOR_BEAM] =
|
||||
{
|
||||
.effect = EFFECT_PLACEHOLDER, //TODO
|
||||
.effect = EFFECT_METEOR_BEAM,
|
||||
.power = 120,
|
||||
.type = TYPE_ROCK,
|
||||
.accuracy = 90,
|
||||
@ -11333,7 +11333,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
|
||||
|
||||
[MOVE_RISING_VOLTAGE] =
|
||||
{
|
||||
.effect = EFFECT_PLACEHOLDER, //TODO
|
||||
.effect = EFFECT_RISING_VOLTAGE,
|
||||
.power = 70,
|
||||
.type = TYPE_ELECTRIC,
|
||||
.accuracy = 100,
|
||||
@ -11417,7 +11417,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
|
||||
|
||||
[MOVE_CORROSIVE_GAS] =
|
||||
{
|
||||
.effect = EFFECT_PLACEHOLDER, //TODO
|
||||
.effect = EFFECT_PLACEHOLDER, // EFFECT_CORROSIVE_GAS, TODO
|
||||
.power = 0,
|
||||
.type = TYPE_POISON,
|
||||
.accuracy = 100,
|
||||
|
Loading…
x
Reference in New Issue
Block a user