pokeemerald/src/battle_script_commands.c

11022 lines
348 KiB
C
Raw Normal View History

2017-09-04 15:05:11 +02:00
#include "global.h"
#include "battle.h"
2017-09-08 16:46:37 +02:00
#include "battle_move_effects.h"
#include "battle_message.h"
2017-09-28 17:38:07 +02:00
#include "battle_ai_script_commands.h"
#include "battle_scripts.h"
2017-09-08 16:46:37 +02:00
#include "moves.h"
#include "abilities.h"
#include "item.h"
#include "items.h"
#include "hold_effects.h"
#include "util.h"
#include "pokemon.h"
#include "calculate_base_damage.h"
#include "rng.h"
2017-09-20 00:28:00 +02:00
#include "battle_controllers.h"
#include "battle_interface.h"
2017-09-20 00:28:00 +02:00
#include "species.h"
2017-09-20 12:56:45 +02:00
#include "songs.h"
2017-09-22 21:33:49 +02:00
#include "text.h"
#include "sound.h"
2017-09-24 00:29:52 +02:00
#include "pokedex.h"
2017-09-25 00:09:13 +02:00
#include "recorded_battle.h"
#include "window.h"
#include "reshow_battle_screen.h"
#include "main.h"
#include "palette.h"
#include "money.h"
2017-09-26 22:39:59 +02:00
#include "bg.h"
#include "string_util.h"
#include "pokemon_icon.h"
#include "pokemon_item_effects.h"
#include "m4a.h"
2017-09-27 23:43:45 +02:00
#include "mail.h"
2017-09-28 15:34:21 +02:00
#include "event_data.h"
#include "pokemon_storage_system.h"
#include "task.h"
#include "naming_screen.h"
2017-10-07 15:15:47 +02:00
#include "battle_string_ids.h"
// variables
extern u8 gCritMultiplier;
extern s32 gBattleMoveDamage;
extern u32 gStatuses3[BATTLE_BANKS_COUNT];
extern u32 gBattleTypeFlags;
extern struct BattleEnigmaBerry gEnigmaBerries[BATTLE_BANKS_COUNT];
extern struct BattlePokemon gBattleMons[BATTLE_BANKS_COUNT];
extern u8 gActiveBank;
extern u32 gBattleExecBuffer;
extern u8 gNoOfAllBanks;
extern u16 gBattlePartyID[BATTLE_BANKS_COUNT];
2017-10-04 19:25:14 +02:00
extern u8 gBanksByTurnOrder[BATTLE_BANKS_COUNT];
extern u8 gActionsByTurnOrder[BATTLE_BANKS_COUNT];
extern u16 gCurrentMove;
extern u8 gLastUsedAbility;
extern u16 gBattleWeather;
extern u8 gStringBank;
extern u8 gEffectBank;
extern u8 gAbsentBankFlags;
extern u8 gMultiHitCounter;
extern u16 gChosenMovesByBanks[BATTLE_BANKS_COUNT];
extern u16 gSideAffecting[2];
extern u16 gPauseCounterBattle;
extern u16 gPaydayMoney;
extern u16 gRandomTurnNumber;
extern u8 gBattleOutcome;
extern u8 gBattleTerrain;
extern u8 gBankAttacker;
extern u8 gBankTarget;
extern const u8* gBattlescriptCurrInstr;
extern u8 gCurrMovePos;
2017-10-06 00:12:01 +02:00
extern u8 gCurrentActionFuncId;
extern u32 gHitMarker;
extern u8 gBattleMoveFlags;
extern u8 gBattleCommunication[];
extern u16 gUnknown_02024250[4];
extern u16 gUnknown_02024258[4];
2017-09-23 20:13:45 +02:00
extern u16 gUnknown_02024260[4];
extern u8 gUnknown_02024270[4];
extern u8 gStringBank;
extern u16 gDynamicBasePower;
extern u16 gLastUsedItem;
extern u16 gBattleMovePower;
2017-09-20 12:56:45 +02:00
extern s32 gHpDealt;
extern s32 gTakenDmg[BATTLE_BANKS_COUNT];
extern u8 gTakenDmgBanks[BATTLE_BANKS_COUNT];
extern u8 gSentPokesToOpponent[2];
extern u8 gBank1;
extern u16 gExpShareExp;
extern u8 gLeveledUpInBattle;
extern void (*gBattleMainFunc)(void);
extern u8 gPlayerPartyCount;
extern u16 gMoveToLearn;
extern u16 gRandomMove;
extern u8 gBankInMenu;
extern u8 gActionForBanks[BATTLE_BANKS_COUNT];
2017-10-06 00:12:01 +02:00
extern u8 gCurrentTurnActionNumber;
extern u8 gBattleBufferB[BATTLE_BANKS_COUNT][0x200];
extern u16 gLockedMoves[BATTLE_BANKS_COUNT];
2017-09-22 21:33:49 +02:00
extern u16 gPartnerTrainerId;
2017-09-23 20:13:45 +02:00
extern u16 gLastUsedMove;
extern u16 gUnknownMovesUsedByBanks[BATTLE_BANKS_COUNT];
extern u16 gLastUsedMovesByBanks[BATTLE_BANKS_COUNT];
2017-09-25 00:09:13 +02:00
extern u16 gTrainerBattleOpponent_A;
extern u16 gTrainerBattleOpponent_B;
2017-09-27 23:43:45 +02:00
extern u8 gUnknown_020241E9;
2017-09-28 15:34:21 +02:00
extern u16 gBattle_BG1_X;
extern u16 gBattle_BG1_Y;
extern u16 gBattle_BG2_X;
extern u16 gBattle_BG2_Y;
extern u16 gBattle_BG3_X;
2017-09-26 22:39:59 +02:00
extern struct MusicPlayerInfo gMPlay_BGM;
2017-09-25 00:09:13 +02:00
struct TrainerMoney
{
u8 classId;
u8 value;
};
extern const struct BattleMove gBattleMoves[];
extern const struct BaseStats gBaseStats[];
extern const u8 gTypeEffectiveness[336];
2017-09-25 00:09:13 +02:00
extern const struct TrainerMoney gTrainerMoneyTable[];
2017-09-23 20:13:45 +02:00
extern const u8* const gBattleScriptsForMoveEffects[];
// functions
2017-09-22 21:33:49 +02:00
extern void sub_81A5718(u8 bank); // battle frontier 2
2017-09-24 00:29:52 +02:00
extern void sub_81A56B4(void); // battle frontier 2
2017-09-25 00:09:13 +02:00
extern void sub_81BFA38(struct Pokemon* party, u8 monPartyId, u8 monCount, void (*callback)(void), u16 move); // pokemon summary screen
extern u8 sub_81C1B94(void); // pokemon summary screen
extern void IncrementGameStat(u8 statId); // rom_4
2017-09-26 22:39:59 +02:00
extern void sub_81D388C(struct Pokemon* mon, void* statStoreLocation); // pokenav.s
extern void sub_81D3640(u8 arg0, void* statStoreLocation1, void* statStoreLocation2, u8 arg3, u8 arg4, u8 arg5); // pokenav.s
extern void sub_81D3784(u8 arg0, void* statStoreLocation1, u8 arg2, u8 arg3, u8 arg4); // pokenav.s
extern u8* GetMonNickname(struct Pokemon* mon, u8* dst); // party_menu
extern u8 sub_81A5258(u8* arg0); // battle frontier 2
extern void sub_81A5BF8(void); // battle frontier 2
extern void sub_81A5D44(void); // battle frontier 2
extern void sub_81B8E80(u8 bank, u8, u8); // party menu
extern bool8 sub_81B1250(void); // ?
2017-09-28 15:34:21 +02:00
extern bool8 InBattlePike(void);
extern bool8 InBattlePyramid(void);
extern u16 GetBattlePyramidPickupItemId(void);
extern u8 sav1_map_get_light_level(void);
extern u8 sub_813B21C(void);
extern u16 get_unknown_box_id(void);
2017-10-01 18:54:01 +02:00
extern void sub_80356D0(void);
2017-09-25 00:09:13 +02:00
// strings
extern const u8 gText_BattleYesNoChoice[];
// read via orr
#define BSScriptRead32(ptr) ((ptr)[0] | (ptr)[1] << 8 | (ptr)[2] << 16 | (ptr)[3] << 24)
2017-09-28 15:34:21 +02:00
#define BSScriptRead16(ptr) ((ptr)[0] | ((ptr)[1] << 8))
#define BSScriptReadPtr(ptr) ((void *)BSScriptRead32(ptr))
// read via add
#define BS2ScriptRead32(ptr) ((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24))
#define BS2ScriptRead16(ptr) ((ptr)[0] + ((ptr)[1] << 8))
#define BS2ScriptReadPtr(ptr) ((void *)BS2ScriptRead32(ptr))
#define TARGET_PROTECT_AFFECTED ((gProtectStructs[gBankTarget].protected && gBattleMoves[gCurrentMove].flags & FLAG_PROTECT_AFFECTED))
2017-09-23 20:13:45 +02:00
#define TARGET_TURN_DAMAGED (((gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special)))
// this file's functions
2017-09-28 15:34:21 +02:00
static bool8 IsTwoTurnsMove(u16 move);
static void TrySetDestinyBondToHappen(void);
2017-09-28 15:34:21 +02:00
static u8 AttacksThisTurn(u8 bank, u16 move); // Note: returns 1 if it's a charging turn, otherwise 2.
2017-09-20 00:28:00 +02:00
static void CheckWonderGuardAndLevitate(void);
2017-09-28 15:34:21 +02:00
static u8 ChangeStatBuffs(s8 statValue, u8 statId, u8, const u8* BS_ptr);
static bool32 IsMonGettingExpSentOut(void);
static void sub_804F17C(void);
static bool8 sub_804F1CC(void);
static void sub_804F100(void);
static void sub_804F144(void);
static bool8 sub_804F344(void);
static void PutMonIconOnLvlUpBox(void);
static void PutLevelAndGenderOnLvlUpBox(void);
2017-09-28 16:32:23 +02:00
static void SpriteCB_MonIconOnLvlUpBox(struct Sprite* sprite);
2017-09-28 15:34:21 +02:00
static void atk00_attackcanceler(void);
static void atk01_accuracycheck(void);
static void atk02_attackstring(void);
static void atk03_ppreduce(void);
static void atk04_critcalc(void);
static void atk05_damagecalc(void);
2017-09-28 15:34:21 +02:00
static void atk06_typecalc(void);
static void atk07_adjustnormaldamage(void);
static void atk08_adjustnormaldamage2(void);
2017-09-28 15:34:21 +02:00
static void atk09_attackanimation(void);
static void atk0A_waitanimation(void);
static void atk0B_healthbarupdate(void);
static void atk0C_datahpupdate(void);
static void atk0D_critmessage(void);
static void atk0E_effectivenesssound(void);
2017-09-28 15:34:21 +02:00
static void atk0F_resultmessage(void);
static void atk10_printstring(void);
static void atk11_printselectionstring(void);
2017-09-28 15:34:21 +02:00
static void atk12_waitmessage(void);
static void atk13_printfromtable(void);
static void atk14_printselectionstringfromtable(void);
2017-09-28 15:34:21 +02:00
static void atk15_seteffectwithchance(void);
static void atk16_seteffectprimary(void);
static void atk17_seteffectsecondary(void);
static void atk18_clearstatusfromeffect(void);
static void atk19_tryfaintmon(void);
static void atk1A_dofaintanimation(void);
static void atk1B_cleareffectsonfaint(void);
2017-09-28 15:34:21 +02:00
static void atk1C_jumpifstatus(void);
static void atk1D_jumpifstatus2(void);
static void atk1E_jumpifability(void);
static void atk1F_jumpifsideaffecting(void);
static void atk20_jumpifstat(void);
2017-11-26 11:55:17 +01:00
static void atk21_jumpifstatus3condition(void);
2017-09-28 15:34:21 +02:00
static void atk22_jumpiftype(void);
static void atk23_getexp(void);
static void atk24(void);
static void atk25_movevaluescleanup(void);
static void atk26_setmultihit(void);
static void atk27_decrementmultihit(void);
2017-09-28 15:34:21 +02:00
static void atk28_goto(void);
static void atk29_jumpifbyte(void);
static void atk2A_jumpifhalfword(void);
static void atk2B_jumpifword(void);
static void atk2C_jumpifarrayequal(void);
static void atk2D_jumpifarraynotequal(void);
static void atk2E_setbyte(void);
static void atk2F_addbyte(void);
static void atk30_subbyte(void);
static void atk31_copyarray(void);
static void atk32_copyarraywithindex(void);
2017-09-28 15:34:21 +02:00
static void atk33_orbyte(void);
static void atk34_orhalfword(void);
static void atk35_orword(void);
static void atk36_bicbyte(void);
static void atk37_bichalfword(void);
static void atk38_bicword(void);
static void atk39_pause(void);
static void atk3A_waitstate(void);
static void atk3B_healthbar_update(void);
static void atk3C_return(void);
static void atk3D_end(void);
static void atk3E_end2(void);
static void atk3F_end3(void);
static void atk40_jumpifaffectedbyprotect(void);
2017-09-28 15:34:21 +02:00
static void atk41_call(void);
static void atk42_jumpiftype2(void);
static void atk43_jumpifabilitypresent(void);
static void atk44_endselectionscript(void);
2017-09-28 15:34:21 +02:00
static void atk45_playanimation(void);
static void atk46_playanimation2(void);
static void atk47_setgraphicalstatchangevalues(void);
static void atk48_playstatchangeanimation(void);
static void atk49_moveend(void);
static void atk4A_typecalc2(void);
static void atk4B_returnatktoball(void);
static void atk4C_getswitchedmondata(void);
static void atk4D_switchindataupdate(void);
static void atk4E_switchinanim(void);
static void atk4F_jumpifcantswitch(void);
2017-09-28 15:34:21 +02:00
static void atk50_openpartyscreen(void);
static void atk51_switchhandleorder(void);
static void atk52_switchineffects(void);
static void atk53_trainerslidein(void);
static void atk54_playse(void);
static void atk55_fanfare(void);
static void atk56_playfaintcry(void);
2017-09-28 15:34:21 +02:00
static void atk57(void);
static void atk58_returntoball(void);
static void atk59_handlelearnnewmove(void);
2017-09-28 15:34:21 +02:00
static void atk5A_yesnoboxlearnmove(void);
static void atk5B_yesnoboxstoplearningmove(void);
static void atk5C_hitanimation(void);
static void atk5D_getmoneyreward(void);
static void atk5E(void);
static void atk5F(void);
static void atk60_incrementgamestat(void);
static void atk61_drawpartystatussummary(void);
static void atk62(void);
2017-09-28 15:34:21 +02:00
static void atk63_jumptorandomattack(void);
static void atk64_statusanimation(void);
static void atk65_status2animation(void);
static void atk66_chosenstatusanimation(void);
static void atk67_yesnobox(void);
static void atk68_cancelallactions(void);
static void atk69_adjustsetdamage(void);
2017-09-28 15:34:21 +02:00
static void atk6A_removeitem(void);
static void atk6B_atknameinbuff1(void);
static void atk6C_drawlvlupbox(void);
static void atk6D_resetsentmonsvalue(void);
static void atk6E_setatktoplayer0(void);
static void atk6F_makevisible(void);
static void atk70_recordlastability(void);
static void atk71_buffermovetolearn(void);
static void atk72_jumpifplayerran(void);
static void atk73_hpthresholds(void);
static void atk74_hpthresholds2(void);
static void atk75_useitemonopponent(void);
2017-09-28 15:34:21 +02:00
static void atk76_various(void);
static void atk77_setprotectlike(void);
2017-09-28 15:34:21 +02:00
static void atk78_faintifabilitynotdamp(void);
static void atk79_setatkhptozero(void);
static void atk7A_jumpifnexttargetvalid(void);
static void atk7B_tryhealhalfhealth(void);
2017-09-28 15:34:21 +02:00
static void atk7C_trymirrormove(void);
static void atk7D_setrain(void);
2017-09-28 15:34:21 +02:00
static void atk7E_setreflect(void);
static void atk7F_setseeded(void);
static void atk80_manipulatedamage(void);
static void atk81_trysetrest(void);
2017-09-28 15:34:21 +02:00
static void atk82_jumpifnotfirstturn(void);
static void atk83_nop(void);
static void atk84_jumpifcantmakeasleep(void);
2017-09-28 15:34:21 +02:00
static void atk85_stockpile(void);
static void atk86_stockpiletobasedamage(void);
static void atk87_stockpiletohpheal(void);
static void atk88_negativedamage(void);
static void atk89_statbuffchange(void);
static void atk8A_normalisebuffs(void);
static void atk8B_setbide(void);
static void atk8C_confuseifrepeatingattackends(void);
static void atk8D_setmultihitcounter(void);
static void atk8E_initmultihitstring(void);
2017-09-28 15:34:21 +02:00
static void atk8F_forcerandomswitch(void);
static void atk90_tryconversiontypechange(void);
2017-09-28 15:34:21 +02:00
static void atk91_givepaydaymoney(void);
static void atk92_setlightscreen(void);
static void atk93_tryKO(void);
2017-09-28 15:34:21 +02:00
static void atk94_damagetohalftargethp(void);
static void atk95_setsandstorm(void);
static void atk96_weatherdamage(void);
static void atk97_tryinfatuating(void);
static void atk98_updatestatusicon(void);
2017-09-28 15:34:21 +02:00
static void atk99_setmist(void);
static void atk9A_setfocusenergy(void);
2017-09-28 15:34:21 +02:00
static void atk9B_transformdataexecution(void);
static void atk9C_setsubstitute(void);
2017-09-28 15:34:21 +02:00
static void atk9D_mimicattackcopy(void);
static void atk9E_metronome(void);
static void atk9F_dmgtolevel(void);
static void atkA0_psywavedamageeffect(void);
static void atkA1_counterdamagecalculator(void);
static void atkA2_mirrorcoatdamagecalculator(void);
static void atkA3_disablelastusedattack(void);
static void atkA4_trysetencore(void);
2017-09-28 15:34:21 +02:00
static void atkA5_painsplitdmgcalc(void);
static void atkA6_settypetorandomresistance(void);
static void atkA7_setalwayshitflag(void);
static void atkA8_copymovepermanently(void);
2017-11-26 01:19:57 +01:00
static void atkA9_trychoosesleeptalkmove(void);
static void atkAA_setdestinybond(void);
static void atkAB_trysetdestinybondtohappen(void);
2017-09-28 15:34:21 +02:00
static void atkAC_remaininghptopower(void);
static void atkAD_tryspiteppreduce(void);
static void atkAE_healpartystatus(void);
2017-09-28 15:34:21 +02:00
static void atkAF_cursetarget(void);
static void atkB0_trysetspikes(void);
static void atkB1_setforesight(void);
static void atkB2_trysetperishsong(void);
2017-09-28 15:34:21 +02:00
static void atkB3_rolloutdamagecalculation(void);
static void atkB4_jumpifconfusedandstatmaxed(void);
static void atkB5_furycuttercalc(void);
static void atkB6_happinesstodamagecalculation(void);
static void atkB7_presentdamagecalculation(void);
static void atkB8_setsafeguard(void);
2017-09-28 15:34:21 +02:00
static void atkB9_magnitudedamagecalculation(void);
static void atkBA_jumpifnopursuitswitchdmg(void);
static void atkBB_setsunny(void);
static void atkBC_maxattackhalvehp(void);
static void atkBD_copyfoestats(void);
static void atkBE_rapidspinfree(void);
static void atkBF_setdefensecurlbit(void);
2017-09-28 15:34:21 +02:00
static void atkC0_recoverbasedonsunlight(void);
static void atkC1_hiddenpowercalc(void);
static void atkC2_selectfirstvalidtarget(void);
static void atkC3_trysetfutureattack(void);
static void atkC4_trydobeatup(void);
2017-09-28 15:34:21 +02:00
static void atkC5_setsemiinvulnerablebit(void);
static void atkC6_clearsemiinvulnerablebit(void);
static void atkC7_setminimize(void);
static void atkC8_sethail(void);
static void atkC9_jumpifattackandspecialattackcannotfall(void);
static void atkCA_setforcedtarget(void);
static void atkCB_setcharge(void);
static void atkCC_callterrainattack(void);
static void atkCD_cureifburnedparalysedorpoisoned(void);
static void atkCE_settorment(void);
static void atkCF_jumpifnodamage(void);
static void atkD0_settaunt(void);
static void atkD1_trysethelpinghand(void);
static void atkD2_tryswapitems(void);
static void atkD3_trycopyability(void);
static void atkD4_trywish(void);
static void atkD5_trysetroots(void);
2017-09-28 15:34:21 +02:00
static void atkD6_doubledamagedealtifdamaged(void);
static void atkD7_setyawn(void);
static void atkD8_setdamagetohealthdifference(void);
static void atkD9_scaledamagebyhealthratio(void);
static void atkDA_tryswapabilities(void);
static void atkDB_tryimprision(void);
static void atkDC_trysetgrudge(void);
2017-09-28 15:34:21 +02:00
static void atkDD_weightdamagecalculation(void);
static void atkDE_asistattackselect(void);
static void atkDF_trysetmagiccoat(void);
static void atkE0_trysetsnatch(void);
static void atkE1_trygetintimidatetarget(void);
static void atkE2_switchoutabilities(void);
2017-09-28 15:34:21 +02:00
static void atkE3_jumpifhasnohp(void);
static void atkE4_getsecretpowereffect(void);
static void atkE5_pickup(void);
static void atkE6_docastformchangeanimation(void);
static void atkE7_trycastformdatachange(void);
2017-09-28 15:34:21 +02:00
static void atkE8_settypebasedhalvers(void);
static void atkE9_setweatherballtype(void);
static void atkEA_tryrecycleitem(void);
2017-09-28 15:34:21 +02:00
static void atkEB_settypetoterrain(void);
static void atkEC_pursuitrelated(void);
static void atkEF_snatchsetbanks(void);
2017-09-28 15:34:21 +02:00
static void atkEE_removelightscreenreflect(void);
2017-11-26 01:19:57 +01:00
static void atkEF_handleballthrow(void);
static void atkF0_givecaughtmon(void);
static void atkF1_trysetcaughtmondexflags(void);
static void atkF2_displaydexinfo(void);
static void atkF3_trygivecaughtmonnick(void);
2017-09-28 15:34:21 +02:00
static void atkF4_subattackerhpbydmg(void);
static void atkF5_removeattackerstatus1(void);
static void atkF6_finishaction(void);
static void atkF7_finishturn(void);
static void atkF8_trainerslideout(void);
2017-09-04 15:05:11 +02:00
void (* const gBattleScriptingCommandsTable[])(void) =
{
atk00_attackcanceler,
atk01_accuracycheck,
atk02_attackstring,
atk03_ppreduce,
atk04_critcalc,
atk05_damagecalc,
2017-09-04 15:05:11 +02:00
atk06_typecalc,
atk07_adjustnormaldamage,
atk08_adjustnormaldamage2,
2017-09-04 15:05:11 +02:00
atk09_attackanimation,
atk0A_waitanimation,
atk0B_healthbarupdate,
atk0C_datahpupdate,
atk0D_critmessage,
atk0E_effectivenesssound,
2017-09-04 15:05:11 +02:00
atk0F_resultmessage,
atk10_printstring,
atk11_printselectionstring,
2017-09-04 15:05:11 +02:00
atk12_waitmessage,
atk13_printfromtable,
atk14_printselectionstringfromtable,
2017-09-27 23:43:45 +02:00
atk15_seteffectwithchance,
2017-09-04 15:05:11 +02:00
atk16_seteffectprimary,
atk17_seteffectsecondary,
atk18_clearstatusfromeffect,
atk19_tryfaintmon,
atk1A_dofaintanimation,
atk1B_cleareffectsonfaint,
2017-09-04 15:05:11 +02:00
atk1C_jumpifstatus,
atk1D_jumpifstatus2,
atk1E_jumpifability,
atk1F_jumpifsideaffecting,
atk20_jumpifstat,
2017-11-26 11:55:17 +01:00
atk21_jumpifstatus3condition,
2017-09-04 15:05:11 +02:00
atk22_jumpiftype,
atk23_getexp,
atk24,
atk25_movevaluescleanup,
atk26_setmultihit,
atk27_decrementmultihit,
2017-09-04 15:05:11 +02:00
atk28_goto,
atk29_jumpifbyte,
atk2A_jumpifhalfword,
atk2B_jumpifword,
atk2C_jumpifarrayequal,
atk2D_jumpifarraynotequal,
atk2E_setbyte,
atk2F_addbyte,
atk30_subbyte,
atk31_copyarray,
atk32_copyarraywithindex,
2017-09-04 15:05:11 +02:00
atk33_orbyte,
atk34_orhalfword,
atk35_orword,
atk36_bicbyte,
atk37_bichalfword,
atk38_bicword,
atk39_pause,
atk3A_waitstate,
atk3B_healthbar_update,
atk3C_return,
atk3D_end,
atk3E_end2,
atk3F_end3,
atk40_jumpifaffectedbyprotect,
2017-09-04 15:05:11 +02:00
atk41_call,
atk42_jumpiftype2,
atk43_jumpifabilitypresent,
atk44_endselectionscript,
2017-09-04 15:05:11 +02:00
atk45_playanimation,
atk46_playanimation2,
atk47_setgraphicalstatchangevalues,
atk48_playstatchangeanimation,
2017-09-23 20:13:45 +02:00
atk49_moveend,
2017-09-04 15:05:11 +02:00
atk4A_typecalc2,
atk4B_returnatktoball,
atk4C_getswitchedmondata,
atk4D_switchindataupdate,
atk4E_switchinanim,
atk4F_jumpifcantswitch,
2017-09-04 15:05:11 +02:00
atk50_openpartyscreen,
atk51_switchhandleorder,
atk52_switchineffects,
atk53_trainerslidein,
atk54_playse,
atk55_fanfare,
atk56_playfaintcry,
2017-09-04 15:05:11 +02:00
atk57,
atk58_returntoball,
atk59_handlelearnnewmove,
2017-09-25 00:09:13 +02:00
atk5A_yesnoboxlearnmove,
atk5B_yesnoboxstoplearningmove,
2017-09-04 15:05:11 +02:00
atk5C_hitanimation,
atk5D_getmoneyreward,
atk5E,
atk5F,
atk60_incrementgamestat,
atk61_drawpartystatussummary,
atk62,
2017-09-04 15:05:11 +02:00
atk63_jumptorandomattack,
atk64_statusanimation,
atk65_status2animation,
atk66_chosenstatusanimation,
2017-09-25 00:09:13 +02:00
atk67_yesnobox,
atk68_cancelallactions,
atk69_adjustsetdamage,
2017-09-04 15:05:11 +02:00
atk6A_removeitem,
atk6B_atknameinbuff1,
atk6C_drawlvlupbox,
atk6D_resetsentmonsvalue,
atk6E_setatktoplayer0,
atk6F_makevisible,
atk70_recordlastability,
atk71_buffermovetolearn,
atk72_jumpifplayerran,
atk73_hpthresholds,
atk74_hpthresholds2,
atk75_useitemonopponent,
2017-09-04 15:05:11 +02:00
atk76_various,
atk77_setprotectlike,
2017-09-04 15:05:11 +02:00
atk78_faintifabilitynotdamp,
atk79_setatkhptozero,
atk7A_jumpifnexttargetvalid,
atk7B_tryhealhalfhealth,
2017-09-26 22:39:59 +02:00
atk7C_trymirrormove,
atk7D_setrain,
2017-09-04 15:05:11 +02:00
atk7E_setreflect,
atk7F_setseeded,
atk80_manipulatedamage,
atk81_trysetrest,
2017-09-04 15:05:11 +02:00
atk82_jumpifnotfirstturn,
atk83_nop,
atk84_jumpifcantmakeasleep,
2017-09-04 15:05:11 +02:00
atk85_stockpile,
atk86_stockpiletobasedamage,
atk87_stockpiletohpheal,
atk88_negativedamage,
atk89_statbuffchange,
atk8A_normalisebuffs,
atk8B_setbide,
atk8C_confuseifrepeatingattackends,
atk8D_setmultihitcounter,
atk8E_initmultihitstring,
2017-09-04 15:05:11 +02:00
atk8F_forcerandomswitch,
atk90_tryconversiontypechange,
2017-09-04 15:05:11 +02:00
atk91_givepaydaymoney,
atk92_setlightscreen,
atk93_tryKO,
2017-09-26 22:39:59 +02:00
atk94_damagetohalftargethp,
2017-09-04 15:05:11 +02:00
atk95_setsandstorm,
atk96_weatherdamage,
atk97_tryinfatuating,
atk98_updatestatusicon,
2017-09-04 15:05:11 +02:00
atk99_setmist,
atk9A_setfocusenergy,
2017-09-04 15:05:11 +02:00
atk9B_transformdataexecution,
atk9C_setsubstitute,
2017-09-26 22:39:59 +02:00
atk9D_mimicattackcopy,
2017-09-04 15:05:11 +02:00
atk9E_metronome,
atk9F_dmgtolevel,
atkA0_psywavedamageeffect,
atkA1_counterdamagecalculator,
atkA2_mirrorcoatdamagecalculator,
atkA3_disablelastusedattack,
atkA4_trysetencore,
2017-09-04 15:05:11 +02:00
atkA5_painsplitdmgcalc,
atkA6_settypetorandomresistance,
atkA7_setalwayshitflag,
atkA8_copymovepermanently,
2017-11-26 01:19:57 +01:00
atkA9_trychoosesleeptalkmove,
atkAA_setdestinybond,
atkAB_trysetdestinybondtohappen,
2017-09-04 15:05:11 +02:00
atkAC_remaininghptopower,
atkAD_tryspiteppreduce,
atkAE_healpartystatus,
2017-09-04 15:05:11 +02:00
atkAF_cursetarget,
atkB0_trysetspikes,
atkB1_setforesight,
atkB2_trysetperishsong,
2017-09-04 15:05:11 +02:00
atkB3_rolloutdamagecalculation,
atkB4_jumpifconfusedandstatmaxed,
atkB5_furycuttercalc,
atkB6_happinesstodamagecalculation,
atkB7_presentdamagecalculation,
atkB8_setsafeguard,
2017-09-04 15:05:11 +02:00
atkB9_magnitudedamagecalculation,
atkBA_jumpifnopursuitswitchdmg,
atkBB_setsunny,
atkBC_maxattackhalvehp,
atkBD_copyfoestats,
2017-09-27 23:43:45 +02:00
atkBE_rapidspinfree,
atkBF_setdefensecurlbit,
2017-09-04 15:05:11 +02:00
atkC0_recoverbasedonsunlight,
atkC1_hiddenpowercalc,
atkC2_selectfirstvalidtarget,
atkC3_trysetfutureattack,
atkC4_trydobeatup,
2017-09-27 23:43:45 +02:00
atkC5_setsemiinvulnerablebit,
atkC6_clearsemiinvulnerablebit,
2017-09-04 15:05:11 +02:00
atkC7_setminimize,
atkC8_sethail,
atkC9_jumpifattackandspecialattackcannotfall,
atkCA_setforcedtarget,
atkCB_setcharge,
atkCC_callterrainattack,
atkCD_cureifburnedparalysedorpoisoned,
atkCE_settorment,
atkCF_jumpifnodamage,
atkD0_settaunt,
atkD1_trysethelpinghand,
atkD2_tryswapitems,
atkD3_trycopyability,
atkD4_trywish,
atkD5_trysetroots,
2017-09-04 15:05:11 +02:00
atkD6_doubledamagedealtifdamaged,
atkD7_setyawn,
atkD8_setdamagetohealthdifference,
atkD9_scaledamagebyhealthratio,
atkDA_tryswapabilities,
atkDB_tryimprision,
atkDC_trysetgrudge,
2017-09-04 15:05:11 +02:00
atkDD_weightdamagecalculation,
atkDE_asistattackselect,
atkDF_trysetmagiccoat,
atkE0_trysetsnatch,
atkE1_trygetintimidatetarget,
atkE2_switchoutabilities,
2017-09-27 23:43:45 +02:00
atkE3_jumpifhasnohp,
2017-09-04 15:05:11 +02:00
atkE4_getsecretpowereffect,
atkE5_pickup,
atkE6_docastformchangeanimation,
atkE7_trycastformdatachange,
2017-09-04 15:05:11 +02:00
atkE8_settypebasedhalvers,
atkE9_setweatherballtype,
atkEA_tryrecycleitem,
2017-09-04 15:05:11 +02:00
atkEB_settypetoterrain,
atkEC_pursuitrelated,
atkEF_snatchsetbanks,
2017-09-04 15:05:11 +02:00
atkEE_removelightscreenreflect,
2017-11-26 01:19:57 +01:00
atkEF_handleballthrow,
atkF0_givecaughtmon,
atkF1_trysetcaughtmondexflags,
atkF2_displaydexinfo,
atkF3_trygivecaughtmonnick,
2017-09-28 15:34:21 +02:00
atkF4_subattackerhpbydmg,
2017-09-04 15:05:11 +02:00
atkF5_removeattackerstatus1,
atkF6_finishaction,
atkF7_finishturn,
atkF8_trainerslideout
2017-09-04 15:05:11 +02:00
};
struct StatFractions
2017-09-04 15:05:11 +02:00
{
u8 dividend;
u8 divisor;
};
2017-09-28 16:51:24 +02:00
static const struct StatFractions sAccuracyStageRatios[] =
2017-09-04 15:05:11 +02:00
{
{ 33, 100}, // -6
{ 36, 100}, // -5
{ 43, 100}, // -4
{ 50, 100}, // -3
{ 60, 100}, // -2
{ 75, 100}, // -1
{ 1, 1}, // 0
{133, 100}, // +1
{166, 100}, // +2
{ 2, 1}, // +3
{233, 100}, // +4
{133, 50}, // +5
{ 3, 1}, // +6
};
// The chance is 1/N for each stage.
2017-09-28 16:51:24 +02:00
static const u16 sCriticalHitChance[] = {16, 8, 4, 3, 2};
2017-09-04 15:05:11 +02:00
2017-09-28 16:51:24 +02:00
static const u32 sStatusFlagsForMoveEffects[] =
2017-09-04 15:05:11 +02:00
{
0x00000000,
STATUS_SLEEP,
STATUS_POISON,
STATUS_BURN,
STATUS_FREEZE,
STATUS_PARALYSIS,
STATUS_TOXIC_POISON,
STATUS2_CONFUSION,
STATUS2_FLINCHED,
2017-09-04 15:05:11 +02:00
0x00000000,
2017-09-22 21:33:49 +02:00
STATUS2_UPROAR,
2017-09-04 15:05:11 +02:00
0x00000000,
2017-09-22 21:33:49 +02:00
STATUS2_MULTIPLETURNS,
STATUS2_WRAPPED,
2017-09-04 15:05:11 +02:00
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
2017-09-22 21:33:49 +02:00
STATUS2_RECHARGE,
2017-09-04 15:05:11 +02:00
0x00000000,
0x00000000,
2017-09-22 21:33:49 +02:00
STATUS2_ESCAPE_PREVENTION,
STATUS2_NIGHTMARE,
2017-09-04 15:05:11 +02:00
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
2017-09-22 21:33:49 +02:00
STATUS2_LOCK_CONFUSE,
2017-09-04 15:05:11 +02:00
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000
};
2017-09-28 16:51:24 +02:00
static const u8* const sMoveEffectBS_Ptrs[] =
2017-09-26 22:39:59 +02:00
{
BattleScript_MoveEffectSleep, // 0
BattleScript_MoveEffectSleep, // MOVE_EFFECT_SLEEP
BattleScript_MoveEffectPoison, // MOVE_EFFECT_POISON
BattleScript_MoveEffectBurn, // MOVE_EFFECT_BURN
BattleScript_MoveEffectFreeze, // MOVE_EFFECT_FREEZE
BattleScript_MoveEffectParalysis, // MOVE_EFFECT_PARALYSIS
BattleScript_MoveEffectToxic, // MOVE_EFFECT_TOXIC
BattleScript_MoveEffectConfusion, // MOVE_EFFECT_CONFUSION
BattleScript_MoveEffectSleep, // MOVE_EFFECT_FLINCH
BattleScript_MoveEffectSleep, // MOVE_EFFECT_TRI_ATTACK
BattleScript_MoveEffectUproar, // MOVE_EFFECT_UPROAR
BattleScript_MoveEffectPayDay, // MOVE_EFFECT_PAYDAY
BattleScript_MoveEffectSleep, // MOVE_EFFECT_CHARGING
BattleScript_MoveEffectWrap, // MOVE_EFFECT_WRAP
BattleScript_MoveEffectRecoil33, // MOVE_EFFECT_RECOIL_25
BattleScript_MoveEffectSleep, // MOVE_EFFECT_ATK_PLUS_1
BattleScript_MoveEffectSleep, // MOVE_EFFECT_DEF_PLUS_1
BattleScript_MoveEffectSleep, // MOVE_EFFECT_SPD_PLUS_1
BattleScript_MoveEffectSleep, // MOVE_EFFECT_SP_ATK_PLUS_1
BattleScript_MoveEffectSleep, // MOVE_EFFECT_SP_DEF_PLUS_1
BattleScript_MoveEffectSleep, // MOVE_EFFECT_ACC_PLUS_1
BattleScript_MoveEffectSleep, // MOVE_EFFECT_EVS_PLUS_1
BattleScript_MoveEffectSleep, // MOVE_EFFECT_ATK_MINUS_1
BattleScript_MoveEffectSleep, // MOVE_EFFECT_DEF_MINUS_1
BattleScript_MoveEffectSleep, // MOVE_EFFECT_SPD_MINUS_1
BattleScript_MoveEffectSleep, // MOVE_EFFECT_SP_ATK_MINUS_1
BattleScript_MoveEffectSleep, // MOVE_EFFECT_SP_DEF_MINUS_1
BattleScript_MoveEffectSleep, // MOVE_EFFECT_ACC_MINUS_1
BattleScript_MoveEffectSleep, // MOVE_EFFECT_EVS_MINUS_1
BattleScript_MoveEffectSleep, // MOVE_EFFECT_RECHARGE
BattleScript_MoveEffectSleep, // MOVE_EFFECT_RAGE
BattleScript_MoveEffectSleep, // MOVE_EFFECT_STEAL_ITEM
BattleScript_MoveEffectSleep, // MOVE_EFFECT_PREVENT_ESCAPE
BattleScript_MoveEffectSleep, // MOVE_EFFECT_NIGHTMARE
BattleScript_MoveEffectSleep, // MOVE_EFFECT_ALL_STATS_UP
BattleScript_MoveEffectSleep, // MOVE_EFFECT_RAPIDSPIN
BattleScript_MoveEffectSleep, // MOVE_EFFECT_REMOVE_PARALYSIS
BattleScript_MoveEffectSleep, // MOVE_EFFECT_ATK_DEF_DOWN
BattleScript_MoveEffectRecoil33, // MOVE_EFFECT_RECOIL_33_PARALYSIS
};
static const struct WindowTemplate sUnusedWinTemplate = {0, 1, 3, 7, 0xF, 0x1F, 0x3F};
2017-09-28 16:51:24 +02:00
static const u16 sUnknown_0831C2C8[] = INCBIN_U16("graphics/battle_interface/unk_battlebox.gbapal");
static const u8 sUnknown_0831C2E8[] = INCBIN_U8("graphics/battle_interface/unk_battlebox.4bpp.lz");
2017-09-28 16:32:23 +02:00
// unused
static const u8 sRubyLevelUpStatBoxStats[] =
{
MON_DATA_MAX_HP, MON_DATA_SPATK, MON_DATA_ATK,
MON_DATA_SPDEF, MON_DATA_DEF, MON_DATA_SPEED
2017-09-28 16:32:23 +02:00
};
#define MON_ICON_LVLUP_BOX_TAG 0xD75A
2017-09-28 16:51:24 +02:00
static const struct OamData sOamData_MonIconOnLvlUpBox =
2017-09-28 16:32:23 +02:00
{
.y = 0,
.affineMode = 0,
.objMode = 0,
.mosaic = 0,
.bpp = 0,
.shape = 0,
.x = 0,
.matrixNum = 0,
.size = 2,
.tileNum = 0,
.priority = 0,
.paletteNum = 0,
.affineParam = 0,
};
2017-09-28 16:51:24 +02:00
static const struct SpriteTemplate sSpriteTemplate_MonIconOnLvlUpBox =
2017-09-28 16:32:23 +02:00
{
.tileTag = MON_ICON_LVLUP_BOX_TAG,
.paletteTag = MON_ICON_LVLUP_BOX_TAG,
2017-09-28 16:51:24 +02:00
.oam = &sOamData_MonIconOnLvlUpBox,
2017-09-28 16:32:23 +02:00
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCB_MonIconOnLvlUpBox
};
2017-09-28 16:51:24 +02:00
static const u16 sProtectSuccessRates[] = {USHRT_MAX, USHRT_MAX / 2, USHRT_MAX / 4, USHRT_MAX / 8};
2017-09-28 15:34:21 +02:00
#define MIMIC_FORBIDDEN_END 0xFFFE
#define METRONOME_FORBIDDEN_END 0xFFFF
#define ASSIST_FORBIDDEN_END 0xFFFF
2017-09-28 16:51:24 +02:00
static const u16 sMovesForbiddenToCopy[] =
2017-09-28 16:32:23 +02:00
{
MOVE_METRONOME,
MOVE_STRUGGLE,
MOVE_SKETCH,
MOVE_MIMIC,
MIMIC_FORBIDDEN_END,
MOVE_COUNTER,
MOVE_MIRROR_COAT,
MOVE_PROTECT,
MOVE_DETECT,
MOVE_ENDURE,
MOVE_DESTINY_BOND,
MOVE_SLEEP_TALK,
MOVE_THIEF,
MOVE_FOLLOW_ME,
MOVE_SNATCH,
MOVE_HELPING_HAND,
MOVE_COVET,
MOVE_TRICK,
MOVE_FOCUS_PUNCH,
METRONOME_FORBIDDEN_END
};
static const u8 sFlailHpScaleToPowerTable[] =
{
1, 200,
4, 150,
9, 100,
16, 80,
32, 40,
48, 20
};
static const u16 sNaturePowerMoves[] =
{
MOVE_STUN_SPORE,
MOVE_RAZOR_LEAF,
MOVE_EARTHQUAKE,
MOVE_HYDRO_PUMP,
MOVE_SURF,
MOVE_BUBBLE_BEAM,
MOVE_ROCK_SLIDE,
MOVE_SHADOW_BALL,
MOVE_SWIFT,
MOVE_SWIFT
};
// format: min. weight (hectograms), base power
static const u16 sWeightToDamageTable[] =
{
100, 20,
250, 40,
500, 60,
1000, 80,
2000, 100,
0xFFFF, 0xFFFF
};
2017-09-28 16:51:24 +02:00
static const u16 sPickupItems[] =
2017-09-28 16:32:23 +02:00
{
ITEM_POTION,
ITEM_ANTIDOTE,
ITEM_SUPER_POTION,
ITEM_GREAT_BALL,
ITEM_REPEL,
ITEM_ESCAPE_ROPE,
ITEM_X_ATTACK,
ITEM_FULL_HEAL,
ITEM_ULTRA_BALL,
ITEM_HYPER_POTION,
ITEM_RARE_CANDY,
ITEM_PROTEIN,
ITEM_REVIVE,
ITEM_HP_UP,
ITEM_FULL_RESTORE,
ITEM_MAX_REVIVE,
ITEM_PP_UP,
ITEM_MAX_ELIXIR,
};
2017-09-28 16:51:24 +02:00
static const u16 sRarePickupItems[] =
2017-09-28 16:32:23 +02:00
{
ITEM_HYPER_POTION,
ITEM_NUGGET,
ITEM_KINGS_ROCK,
ITEM_FULL_RESTORE,
ITEM_ETHER,
ITEM_WHITE_HERB,
ITEM_TM44,
ITEM_ELIXIR,
ITEM_TM01,
ITEM_LEFTOVERS,
ITEM_TM26,
};
2017-09-28 16:51:24 +02:00
static const u8 sPickupProbabilities[] =
2017-09-28 16:32:23 +02:00
{
30, 40, 50, 60, 70, 80, 90, 94, 98
};
static const u8 sTerrainToType[] =
{
TYPE_GRASS, // tall grass
TYPE_GRASS, // long grass
TYPE_GROUND, // sand
TYPE_WATER, // underwater
TYPE_WATER, // water
TYPE_WATER, // pond water
2017-09-28 16:51:24 +02:00
TYPE_ROCK, // rock
TYPE_ROCK, // cave
2017-09-28 16:32:23 +02:00
TYPE_NORMAL, // building
TYPE_NORMAL, // plain
};
static const u8 sBallCatchBonuses[] =
{
20, 15, 10, 15 // Ultra, Great, Poke, Safari
};
2017-11-04 16:11:13 +01:00
const ALIGNED(4) u8 gUnknown_0831C494[][4] =
{
{0x3d, 0x44, 0x3d, 0x44},
{0x14, 0x2d, 0x54, 0x5c},
{0x46, 0x55, 0x20, 0x5c},
{0x26, 0x45, 0x46, 0x55},
{0x14, 0x5a, 0x46, 0x5c},
{0x1e, 0x32, 0x20, 0x5a},
{0x38, 0x4e, 0x38, 0x4e},
{0x19, 0x28, 0x4b, 0x5a},
{0x45, 0x4b, 0x1c, 0x53},
{0x23, 0x2d, 0x1d, 0x23},
{0x3e, 0x48, 0x1e, 0x32},
{0x3a, 0x5f, 0x58, 0x5e},
{0x22, 0x2d, 0x1d, 0x28},
{0x23, 0x28, 0x23, 0x5f},
{0x38, 0x4e, 0x38, 0x4e},
{0x23, 0x50, 0x22, 0x5e},
{0x2c, 0x5e, 0x22, 0x28},
{0x38, 0x4e, 0x38, 0x4e},
{0x1e, 0x58, 0x1e, 0x58},
{0x1e, 0x2b, 0x1b, 0x21},
{0x28, 0x5a, 0x19, 0x57},
{0x12, 0x58, 0x5a, 0x5f},
{0x58, 0x5e, 0x16, 0x2a},
{0x2a, 0x5c, 0x2a, 0x2f},
{0x38, 0x4e, 0x38, 0x4e}
2017-09-28 16:51:24 +02:00
};
static const u8 sUnknown_0831C4F8[] =
{
0x03, 0x00, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00,
0x01, 0x02, 0x02, 0x00, 0x03, 0x01, 0x03, 0x01,
0x02, 0x03, 0x03, 0x02, 0x01, 0x00, 0x02, 0x02,
0x03, 0x00, 0x00, 0x00
};
2017-09-28 16:32:23 +02:00
2017-09-28 15:34:21 +02:00
static void atk00_attackcanceler(void)
{
s32 i;
2017-10-06 00:12:01 +02:00
if (gBattleOutcome != 0)
{
2017-10-06 00:12:01 +02:00
gCurrentActionFuncId = ACTION_FINISHED;
return;
}
if (gBattleMons[gBankAttacker].hp == 0 && !(gHitMarker & HITMARKER_NO_ATTACKSTRING))
{
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
gBattlescriptCurrInstr = BattleScript_MoveEnd;
return;
}
if (AtkCanceller_UnableToUseMove())
return;
if (AbilityBattleEffects(ABILITYEFFECT_MOVES_BLOCK, gBankTarget, 0, 0, 0))
return;
if (!gBattleMons[gBankAttacker].pp[gCurrMovePos] && gCurrentMove != MOVE_STRUGGLE && !(gHitMarker & 0x800200)
&& !(gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS))
{
gBattlescriptCurrInstr = BattleScript_NoPPForMove;
gBattleMoveFlags |= MOVESTATUS_MISSED;
return;
}
gHitMarker &= ~(HITMARKER_x800000);
if (!(gHitMarker & HITMARKER_OBEYS) && !(gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS))
{
i = IsPokeDisobedient(); // why use the 'i' variable...?
switch (i)
{
case 0:
break;
case 2:
gHitMarker |= HITMARKER_OBEYS;
return;
default:
gBattleMoveFlags |= MOVESTATUS_MISSED;
return;
}
}
gHitMarker |= HITMARKER_OBEYS;
if (gProtectStructs[gBankTarget].bounceMove && gBattleMoves[gCurrentMove].flags & FLAG_MAGICCOAT_AFFECTED)
{
PressurePPLose(gBankAttacker, gBankTarget, MOVE_MAGIC_COAT);
gProtectStructs[gBankTarget].bounceMove = 0;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_MagicCoatBounce;
return;
}
for (i = 0; i < gNoOfAllBanks; i++)
{
2017-10-04 19:25:14 +02:00
if ((gProtectStructs[gBanksByTurnOrder[i]].stealMove) && gBattleMoves[gCurrentMove].flags & FLAG_SNATCH_AFFECTED)
{
2017-10-04 19:25:14 +02:00
PressurePPLose(gBankAttacker, gBanksByTurnOrder[i], MOVE_SNATCH);
gProtectStructs[gBanksByTurnOrder[i]].stealMove = 0;
gBattleScripting.bank = gBanksByTurnOrder[i];
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_SnatchedMove;
return;
}
}
if (gSpecialStatuses[gBankTarget].lightningRodRedirected)
{
gSpecialStatuses[gBankTarget].lightningRodRedirected = 0;
gLastUsedAbility = ABILITY_LIGHTNING_ROD;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_TookAttack;
RecordAbilityBattle(gBankTarget, gLastUsedAbility);
}
else if (TARGET_PROTECT_AFFECTED
&& (gCurrentMove != MOVE_CURSE || (gBattleMons[gBankAttacker].type1 == TYPE_GHOST || gBattleMons[gBankAttacker].type2 == TYPE_GHOST))
&& ((!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS))))
{
CancelMultiTurnMoves(gBankAttacker);
gBattleMoveFlags |= MOVESTATUS_MISSED;
gUnknown_02024250[gBankTarget] = 0;
gUnknown_02024258[gBankTarget] = 0;
gBattleCommunication[6] = 1;
gBattlescriptCurrInstr++;
}
else
{
gBattlescriptCurrInstr++;
}
}
2017-09-28 15:34:21 +02:00
static void JumpIfMoveFailed(u8 adder, u16 move)
{
const void* BS_ptr = gBattlescriptCurrInstr + adder;
if (gBattleMoveFlags & MOVESTATUS_NOEFFECT)
{
gUnknown_02024250[gBankTarget] = 0;
gUnknown_02024258[gBankTarget] = 0;
BS_ptr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
TrySetDestinyBondToHappen();
if (AbilityBattleEffects(ABILITYEFFECT_ABSORBING, gBankTarget, 0, 0, move))
return;
}
gBattlescriptCurrInstr = BS_ptr;
}
static void atk40_jumpifaffectedbyprotect(void)
{
if (TARGET_PROTECT_AFFECTED)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
JumpIfMoveFailed(5, 0);
gBattleCommunication[6] = 1;
}
else
{
gBattlescriptCurrInstr += 5;
}
}
bool8 JumpIfMoveAffectedByProtect(u16 move)
{
bool8 affected = FALSE;
if (TARGET_PROTECT_AFFECTED)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
JumpIfMoveFailed(7, move);
gBattleCommunication[6] = 1;
affected = TRUE;
}
return affected;
}
static bool8 AccuracyCalcHelper(u16 move)
{
if (gStatuses3[gBankTarget] & STATUS3_ALWAYS_HITS && gDisableStructs[gBankTarget].bankWithSureHit == gBankAttacker)
{
JumpIfMoveFailed(7, move);
return TRUE;
}
if (!(gHitMarker & HITMARKER_IGNORE_ON_AIR) && gStatuses3[gBankTarget] & STATUS3_ON_AIR)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
JumpIfMoveFailed(7, move);
return TRUE;
}
gHitMarker &= ~HITMARKER_IGNORE_ON_AIR;
if (!(gHitMarker & HITMARKER_IGNORE_UNDERGROUND) && gStatuses3[gBankTarget] & STATUS3_UNDERGROUND)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
JumpIfMoveFailed(7, move);
return TRUE;
}
gHitMarker &= ~HITMARKER_IGNORE_UNDERGROUND;
if (!(gHitMarker & HITMARKER_IGNORE_UNDERWATER) && gStatuses3[gBankTarget] & STATUS3_UNDERWATER)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
JumpIfMoveFailed(7, move);
return TRUE;
}
gHitMarker &= ~HITMARKER_IGNORE_UNDERWATER;
if ((WEATHER_HAS_EFFECT && (gBattleWeather & WEATHER_RAIN_ANY) && gBattleMoves[move].effect == EFFECT_THUNDER)
|| (gBattleMoves[move].effect == EFFECT_ALWAYS_HIT || gBattleMoves[move].effect == EFFECT_VITAL_THROW))
{
JumpIfMoveFailed(7, move);
return TRUE;
}
return FALSE;
}
2017-09-28 15:34:21 +02:00
static void atk01_accuracycheck(void)
{
u16 move = BS2ScriptRead16(gBattlescriptCurrInstr + 5);
if (move == 0xFFFE || move == 0xFFFF)
{
if (gStatuses3[gBankTarget] & STATUS3_ALWAYS_HITS && move == 0xFFFF && gDisableStructs[gBankTarget].bankWithSureHit == gBankAttacker)
gBattlescriptCurrInstr += 7;
else if (gStatuses3[gBankTarget] & (STATUS3_ON_AIR | STATUS3_UNDERGROUND | STATUS3_UNDERWATER))
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
else if (!JumpIfMoveAffectedByProtect(0))
gBattlescriptCurrInstr += 7;
}
else
{
u8 type, moveAcc, holdEffect, quality;
s8 buff;
u16 calc;
if (move == 0)
move = gCurrentMove;
GET_MOVE_TYPE(move, type);
if (JumpIfMoveAffectedByProtect(move))
return;
if (AccuracyCalcHelper(move))
return;
if (gBattleMons[gBankTarget].status2 & STATUS2_FORESIGHT)
{
u8 acc = gBattleMons[gBankAttacker].statStages[STAT_STAGE_ACC];
buff = acc;
}
else
{
u8 acc = gBattleMons[gBankAttacker].statStages[STAT_STAGE_ACC];
buff = acc + 6 - gBattleMons[gBankTarget].statStages[STAT_STAGE_EVASION];
}
if (buff < 0)
buff = 0;
if (buff > 0xC)
buff = 0xC;
moveAcc = gBattleMoves[move].accuracy;
// check Thunder on sunny weather
if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY && gBattleMoves[move].effect == EFFECT_THUNDER)
moveAcc = 50;
2017-09-28 16:51:24 +02:00
calc = sAccuracyStageRatios[buff].dividend * moveAcc;
calc /= sAccuracyStageRatios[buff].divisor;
if (gBattleMons[gBankAttacker].ability == ABILITY_COMPOUND_EYES)
calc = (calc * 130) / 100; // 1.3 compound eyes boost
if (WEATHER_HAS_EFFECT && gBattleMons[gBankTarget].ability == ABILITY_SAND_VEIL && gBattleWeather & WEATHER_SANDSTORM_ANY)
calc = (calc * 80) / 100; // 1.2 sand veil loss
if (gBattleMons[gBankAttacker].ability == ABILITY_HUSTLE && type < 9)
calc = (calc * 80) / 100; // 1.2 hustle loss
if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY)
{
holdEffect = gEnigmaBerries[gBankTarget].holdEffect;
quality = gEnigmaBerries[gBankTarget].holdEffectParam;
}
else
{
holdEffect = ItemId_GetHoldEffect(gBattleMons[gBankTarget].item);
quality = ItemId_GetHoldEffectParam(gBattleMons[gBankTarget].item);
}
gStringBank = gBankTarget;
if (holdEffect == HOLD_EFFECT_EVASION_UP)
calc = (calc * (100 - quality)) / 100;
// final calculation
if ((Random() % 100 + 1) > calc)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE &&
(gBattleMoves[move].target == MOVE_TARGET_BOTH || gBattleMoves[move].target == MOVE_TARGET_FOES_AND_ALLY))
gBattleCommunication[6] = 2;
else
gBattleCommunication[6] = 0;
2017-09-20 00:28:00 +02:00
CheckWonderGuardAndLevitate();
}
JumpIfMoveFailed(7, move);
}
}
2017-09-28 15:34:21 +02:00
static void atk02_attackstring(void)
{
if (gBattleExecBuffer)
return;
if (!(gHitMarker & (HITMARKER_NO_ATTACKSTRING | HITMARKER_ATTACKSTRING_PRINTED)))
{
2017-10-07 15:15:47 +02:00
PrepareStringBattle(STRINGID_USEDMOVE, gBankAttacker);
gHitMarker |= HITMARKER_ATTACKSTRING_PRINTED;
}
gBattlescriptCurrInstr++;
gBattleCommunication[MSG_DISPLAY] = 0;
}
2017-09-20 00:28:00 +02:00
2017-09-28 15:34:21 +02:00
static void atk03_ppreduce(void)
2017-09-20 00:28:00 +02:00
{
2017-09-27 23:43:45 +02:00
s32 ppToDeduct = 1;
2017-09-20 00:28:00 +02:00
if (gBattleExecBuffer)
return;
if (!gSpecialStatuses[gBankAttacker].flag20)
{
switch (gBattleMoves[gCurrentMove].target)
{
case MOVE_TARGET_FOES_AND_ALLY:
2017-09-27 23:43:45 +02:00
ppToDeduct += AbilityBattleEffects(ABILITYEFFECT_COUNT_ON_FIELD, gBankAttacker, ABILITY_PRESSURE, 0, 0);
2017-09-20 00:28:00 +02:00
break;
case MOVE_TARGET_BOTH:
case MOVE_TARGET_OPPONENTS_FIELD:
2017-09-27 23:43:45 +02:00
ppToDeduct += AbilityBattleEffects(ABILITYEFFECT_COUNT_OTHER_SIDE, gBankAttacker, ABILITY_PRESSURE, 0, 0);
2017-09-20 00:28:00 +02:00
break;
default:
if (gBankAttacker != gBankTarget && gBattleMons[gBankTarget].ability == ABILITY_PRESSURE)
2017-09-27 23:43:45 +02:00
ppToDeduct++;
2017-09-20 00:28:00 +02:00
break;
}
}
if (!(gHitMarker & (HITMARKER_NO_PPDEDUCT | HITMARKER_NO_ATTACKSTRING)) && gBattleMons[gBankAttacker].pp[gCurrMovePos])
{
gProtectStructs[gBankAttacker].notFirstStrike = 1;
2017-09-27 23:43:45 +02:00
if (gBattleMons[gBankAttacker].pp[gCurrMovePos] > ppToDeduct)
gBattleMons[gBankAttacker].pp[gCurrMovePos] -= ppToDeduct;
2017-09-20 00:28:00 +02:00
else
gBattleMons[gBankAttacker].pp[gCurrMovePos] = 0;
if (!(gBattleMons[gBankAttacker].status2 & STATUS2_TRANSFORMED)
&& !((gDisableStructs[gBankAttacker].unk18_b) & gBitTable[gCurrMovePos]))
{
gActiveBank = gBankAttacker;
2017-09-26 22:39:59 +02:00
EmitSetMonData(0, REQUEST_PPMOVE1_BATTLE + gCurrMovePos, 0, 1, &gBattleMons[gBankAttacker].pp[gCurrMovePos]);
2017-09-20 00:28:00 +02:00
MarkBufferBankForExecution(gBankAttacker);
}
}
gHitMarker &= ~(HITMARKER_NO_PPDEDUCT);
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atk04_critcalc(void)
2017-09-20 00:28:00 +02:00
{
u8 holdEffect;
u16 item, critChance;
item = gBattleMons[gBankAttacker].item;
if (item == ITEM_ENIGMA_BERRY)
holdEffect = gEnigmaBerries[gBankAttacker].holdEffect;
else
holdEffect = ItemId_GetHoldEffect(item);
gStringBank = gBankAttacker;
critChance = 2 * ((gBattleMons[gBankAttacker].status2 & STATUS2_FOCUS_ENERGY) != 0)
+ (gBattleMoves[gCurrentMove].effect == EFFECT_HIGH_CRITICAL)
+ (gBattleMoves[gCurrentMove].effect == EFFECT_SKY_ATTACK)
+ (gBattleMoves[gCurrentMove].effect == EFFECT_BLAZE_KICK)
+ (gBattleMoves[gCurrentMove].effect == EFFECT_POISON_TAIL)
+ (holdEffect == HOLD_EFFECT_SCOPE_LENS)
+ 2 * (holdEffect == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[gBankAttacker].species == SPECIES_CHANSEY)
+ 2 * (holdEffect == HOLD_EFFECT_STICK && gBattleMons[gBankAttacker].species == SPECIES_FARFETCHD);
if (critChance > 4)
critChance = 4;
if ((gBattleMons[gBankTarget].ability != ABILITY_BATTLE_ARMOR && gBattleMons[gBankTarget].ability != ABILITY_SHELL_ARMOR)
&& !(gStatuses3[gBankAttacker] & STATUS3_CANT_SCORE_A_CRIT)
&& !(gBattleTypeFlags & (BATTLE_TYPE_WALLY_TUTORIAL | BATTLE_TYPE_FIRST_BATTLE))
2017-09-28 16:51:24 +02:00
&& !(Random() % sCriticalHitChance[critChance]))
2017-09-20 00:28:00 +02:00
gCritMultiplier = 2;
else
gCritMultiplier = 1;
gBattlescriptCurrInstr++;
}
static void atk05_damagecalc(void)
2017-09-20 00:28:00 +02:00
{
u16 sideStatus = gSideAffecting[GET_BANK_SIDE(gBankTarget)];
gBattleMoveDamage = CalculateBaseDamage(&gBattleMons[gBankAttacker], &gBattleMons[gBankTarget], gCurrentMove,
sideStatus, gDynamicBasePower,
gBattleStruct->dynamicMoveType, gBankAttacker, gBankTarget);
gBattleMoveDamage = gBattleMoveDamage * gCritMultiplier * gBattleScripting.dmgMultiplier;
if (gStatuses3[gBankAttacker] & STATUS3_CHARGED_UP && gBattleMoves[gCurrentMove].type == TYPE_ELECTRIC)
gBattleMoveDamage *= 2;
if (gProtectStructs[gBankAttacker].helpingHand)
gBattleMoveDamage = gBattleMoveDamage * 15 / 10;
gBattlescriptCurrInstr++;
}
void AI_CalcDmg(u8 bankAtk, u8 bankDef)
{
u16 sideStatus = gSideAffecting[GET_BANK_SIDE(bankDef)];
gBattleMoveDamage = CalculateBaseDamage(&gBattleMons[bankAtk], &gBattleMons[bankDef], gCurrentMove,
sideStatus, gDynamicBasePower,
gBattleStruct->dynamicMoveType, bankAtk, bankDef);
gDynamicBasePower = 0;
gBattleMoveDamage = gBattleMoveDamage * gCritMultiplier * gBattleScripting.dmgMultiplier;
if (gStatuses3[bankAtk] & STATUS3_CHARGED_UP && gBattleMoves[gCurrentMove].type == TYPE_ELECTRIC)
gBattleMoveDamage *= 2;
if (gProtectStructs[bankAtk].helpingHand)
gBattleMoveDamage = gBattleMoveDamage * 15 / 10;
}
2017-09-28 15:34:21 +02:00
static void ModulateDmgByType(u8 multiplier)
2017-09-20 00:28:00 +02:00
{
gBattleMoveDamage = gBattleMoveDamage * multiplier / 10;
if (gBattleMoveDamage == 0 && multiplier != 0)
gBattleMoveDamage = 1;
switch (multiplier)
{
case TYPE_MUL_NO_EFFECT:
gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED;
gBattleMoveFlags &= ~MOVESTATUS_NOTVERYEFFECTIVE;
gBattleMoveFlags &= ~MOVESTATUS_SUPEREFFECTIVE;
break;
case TYPE_MUL_NOT_EFFECTIVE:
if (gBattleMoves[gCurrentMove].power && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
{
if (gBattleMoveFlags & MOVESTATUS_SUPEREFFECTIVE)
gBattleMoveFlags &= ~MOVESTATUS_SUPEREFFECTIVE;
else
gBattleMoveFlags |= MOVESTATUS_NOTVERYEFFECTIVE;
}
break;
case TYPE_MUL_SUPER_EFFECTIVE:
if (gBattleMoves[gCurrentMove].power && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
{
if (gBattleMoveFlags & MOVESTATUS_NOTVERYEFFECTIVE)
gBattleMoveFlags &= ~MOVESTATUS_NOTVERYEFFECTIVE;
else
gBattleMoveFlags |= MOVESTATUS_SUPEREFFECTIVE;
}
break;
}
}
2017-09-28 15:34:21 +02:00
static void atk06_typecalc(void)
2017-09-20 00:28:00 +02:00
{
s32 i = 0;
u8 moveType;
if (gCurrentMove == MOVE_STRUGGLE)
{
gBattlescriptCurrInstr++;
return;
}
GET_MOVE_TYPE(gCurrentMove, moveType);
// check stab
if (gBattleMons[gBankAttacker].type1 == moveType || gBattleMons[gBankAttacker].type2 == moveType)
{
gBattleMoveDamage = gBattleMoveDamage * 15;
gBattleMoveDamage = gBattleMoveDamage / 10;
}
if (gBattleMons[gBankTarget].ability == ABILITY_LEVITATE && moveType == TYPE_GROUND)
{
gLastUsedAbility = gBattleMons[gBankTarget].ability;
gBattleMoveFlags |= (MOVESTATUS_MISSED | MOVESTATUS_NOTAFFECTED);
gUnknown_02024250[gBankTarget] = 0;
gUnknown_02024258[gBankTarget] = 0;
gBattleCommunication[6] = moveType;
RecordAbilityBattle(gBankTarget, gLastUsedAbility);
}
else
{
while (TYPE_EFFECT_ATK_TYPE(i) != TYPE_ENDTABLE)
2017-09-20 00:28:00 +02:00
{
if (TYPE_EFFECT_ATK_TYPE(i) == TYPE_FORESIGHT)
2017-09-20 00:28:00 +02:00
{
if (gBattleMons[gBankTarget].status2 & STATUS2_FORESIGHT)
break;
i += 3;
continue;
}
else if (TYPE_EFFECT_ATK_TYPE(i) == moveType)
2017-09-20 00:28:00 +02:00
{
// check type1
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBankTarget].type1)
ModulateDmgByType(TYPE_EFFECT_MULTIPLIER(i));
2017-09-20 00:28:00 +02:00
// check type2
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBankTarget].type2 &&
2017-09-20 00:28:00 +02:00
gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2)
ModulateDmgByType(TYPE_EFFECT_MULTIPLIER(i));
2017-09-20 00:28:00 +02:00
}
i += 3;
}
}
if (gBattleMons[gBankTarget].ability == ABILITY_WONDER_GUARD && AttacksThisTurn(gBankAttacker, gCurrentMove) == 2
&& (!(gBattleMoveFlags & MOVESTATUS_SUPEREFFECTIVE) || ((gBattleMoveFlags & (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)) == (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)))
&& gBattleMoves[gCurrentMove].power)
{
gLastUsedAbility = ABILITY_WONDER_GUARD;
gBattleMoveFlags |= MOVESTATUS_MISSED;
gUnknown_02024250[gBankTarget] = 0;
gUnknown_02024258[gBankTarget] = 0;
gBattleCommunication[6] = 3;
RecordAbilityBattle(gBankTarget, gLastUsedAbility);
}
if (gBattleMoveFlags & MOVESTATUS_NOTAFFECTED)
2017-10-06 17:06:45 +02:00
gProtectStructs[gBankAttacker].targetNotAffected = 1;
2017-09-20 00:28:00 +02:00
gBattlescriptCurrInstr++;
}
static void CheckWonderGuardAndLevitate(void)
{
u8 flags = 0;
s32 i = 0;
u8 moveType;
if (gCurrentMove == MOVE_STRUGGLE || !gBattleMoves[gCurrentMove].power)
return;
GET_MOVE_TYPE(gCurrentMove, moveType);
if (gBattleMons[gBankTarget].ability == ABILITY_LEVITATE && moveType == TYPE_GROUND)
{
gLastUsedAbility = ABILITY_LEVITATE;
gBattleCommunication[6] = moveType;
RecordAbilityBattle(gBankTarget, ABILITY_LEVITATE);
return;
}
while (TYPE_EFFECT_ATK_TYPE(i) != TYPE_ENDTABLE)
2017-09-20 00:28:00 +02:00
{
if (TYPE_EFFECT_ATK_TYPE(i) == TYPE_FORESIGHT)
2017-09-20 00:28:00 +02:00
{
if (gBattleMons[gBankTarget].status2 & STATUS2_FORESIGHT)
break;
i += 3;
continue;
}
if (TYPE_EFFECT_ATK_TYPE(i) == moveType)
2017-09-20 00:28:00 +02:00
{
// check no effect
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBankTarget].type1
&& TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_NO_EFFECT)
2017-09-20 00:28:00 +02:00
{
gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED;
2017-10-06 17:06:45 +02:00
gProtectStructs[gBankAttacker].targetNotAffected = 1;
2017-09-20 00:28:00 +02:00
}
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBankTarget].type2 &&
2017-09-20 00:28:00 +02:00
gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2 &&
TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_NO_EFFECT)
2017-09-20 00:28:00 +02:00
{
gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED;
2017-10-06 17:06:45 +02:00
gProtectStructs[gBankAttacker].targetNotAffected = 1;
2017-09-20 00:28:00 +02:00
}
// check super effective
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBankTarget].type1 && TYPE_EFFECT_MULTIPLIER(i) == 20)
2017-09-20 00:28:00 +02:00
flags |= 1;
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBankTarget].type2
2017-09-20 00:28:00 +02:00
&& gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2
&& TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_SUPER_EFFECTIVE)
2017-09-20 00:28:00 +02:00
flags |= 1;
// check not very effective
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBankTarget].type1 && TYPE_EFFECT_MULTIPLIER(i) == 5)
2017-09-20 00:28:00 +02:00
flags |= 2;
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBankTarget].type2
2017-09-20 00:28:00 +02:00
&& gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2
&& TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_NOT_EFFECTIVE)
2017-09-20 00:28:00 +02:00
flags |= 2;
}
i += 3;
}
if (gBattleMons[gBankTarget].ability == ABILITY_WONDER_GUARD && AttacksThisTurn(gBankAttacker, gCurrentMove) == 2)
{
if (((flags & 2) || !(flags & 1)) && gBattleMoves[gCurrentMove].power)
{
gLastUsedAbility = ABILITY_WONDER_GUARD;
gBattleCommunication[6] = 3;
RecordAbilityBattle(gBankTarget, ABILITY_WONDER_GUARD);
}
}
}
2017-09-28 15:34:21 +02:00
static void ModulateDmgByType2(u8 multiplier, u16 move, u8* flags) // same as ModulateDmgByType except different arguments
2017-09-20 00:28:00 +02:00
{
gBattleMoveDamage = gBattleMoveDamage * multiplier / 10;
if (gBattleMoveDamage == 0 && multiplier != 0)
gBattleMoveDamage = 1;
switch (multiplier)
{
case TYPE_MUL_NO_EFFECT:
*flags |= MOVESTATUS_NOTAFFECTED;
*flags &= ~MOVESTATUS_NOTVERYEFFECTIVE;
*flags &= ~MOVESTATUS_SUPEREFFECTIVE;
break;
case TYPE_MUL_NOT_EFFECTIVE:
if (gBattleMoves[move].power && !(*flags & MOVESTATUS_NOEFFECT))
{
if (*flags & MOVESTATUS_SUPEREFFECTIVE)
*flags &= ~MOVESTATUS_SUPEREFFECTIVE;
else
*flags |= MOVESTATUS_NOTVERYEFFECTIVE;
}
break;
case TYPE_MUL_SUPER_EFFECTIVE:
if (gBattleMoves[move].power && !(*flags & MOVESTATUS_NOEFFECT))
{
if (*flags & MOVESTATUS_NOTVERYEFFECTIVE)
*flags &= ~MOVESTATUS_NOTVERYEFFECTIVE;
else
*flags |= MOVESTATUS_SUPEREFFECTIVE;
}
break;
}
}
u8 TypeCalc(u16 move, u8 bankAtk, u8 bankDef)
{
s32 i = 0;
u8 flags = 0;
u8 moveType;
if (move == MOVE_STRUGGLE)
return 0;
moveType = gBattleMoves[move].type;
// check stab
if (gBattleMons[bankAtk].type1 == moveType || gBattleMons[bankAtk].type2 == moveType)
{
gBattleMoveDamage = gBattleMoveDamage * 15;
gBattleMoveDamage = gBattleMoveDamage / 10;
}
if (gBattleMons[bankDef].ability == ABILITY_LEVITATE && moveType == TYPE_GROUND)
{
flags |= (MOVESTATUS_MISSED | MOVESTATUS_NOTAFFECTED);
}
else
{
while (TYPE_EFFECT_ATK_TYPE(i) != TYPE_ENDTABLE)
2017-09-20 00:28:00 +02:00
{
if (TYPE_EFFECT_ATK_TYPE(i) == TYPE_FORESIGHT)
2017-09-20 00:28:00 +02:00
{
if (gBattleMons[bankDef].status2 & STATUS2_FORESIGHT)
break;
i += 3;
continue;
}
else if (TYPE_EFFECT_ATK_TYPE(i) == moveType)
2017-09-20 00:28:00 +02:00
{
// check type1
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[bankDef].type1)
ModulateDmgByType2(TYPE_EFFECT_MULTIPLIER(i), move, &flags);
2017-09-20 00:28:00 +02:00
// check type2
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[bankDef].type2 &&
2017-09-20 00:28:00 +02:00
gBattleMons[bankDef].type1 != gBattleMons[bankDef].type2)
ModulateDmgByType2(TYPE_EFFECT_MULTIPLIER(i), move, &flags);
2017-09-20 00:28:00 +02:00
}
i += 3;
}
}
if (gBattleMons[bankDef].ability == ABILITY_WONDER_GUARD && !(flags & MOVESTATUS_MISSED)
&& AttacksThisTurn(bankAtk, move) == 2
&& (!(flags & MOVESTATUS_SUPEREFFECTIVE) || ((flags & (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)) == (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)))
&& gBattleMoves[move].power)
{
flags |= MOVESTATUS_MISSED;
}
return flags;
}
2017-10-10 18:01:45 +02:00
u8 AI_TypeCalc(u16 move, u16 targetSpecies, u8 targetAbility)
2017-09-20 00:28:00 +02:00
{
s32 i = 0;
u8 flags = 0;
2017-10-10 18:01:45 +02:00
u8 type1 = gBaseStats[targetSpecies].type1, type2 = gBaseStats[targetSpecies].type2;
2017-09-20 00:28:00 +02:00
u8 moveType;
if (move == MOVE_STRUGGLE)
return 0;
moveType = gBattleMoves[move].type;
2017-10-10 18:01:45 +02:00
if (targetAbility == ABILITY_LEVITATE && moveType == TYPE_GROUND)
2017-09-20 00:28:00 +02:00
{
flags = MOVESTATUS_MISSED | MOVESTATUS_NOTAFFECTED;
}
else
{
while (TYPE_EFFECT_ATK_TYPE(i) != TYPE_ENDTABLE)
2017-09-20 00:28:00 +02:00
{
if (TYPE_EFFECT_ATK_TYPE(i) == TYPE_FORESIGHT)
2017-09-20 00:28:00 +02:00
{
i += 3;
continue;
}
if (TYPE_EFFECT_ATK_TYPE(i) == moveType)
2017-09-20 00:28:00 +02:00
{
// check type1
if (TYPE_EFFECT_DEF_TYPE(i) == type1)
ModulateDmgByType2(TYPE_EFFECT_MULTIPLIER(i), move, &flags);
2017-09-20 00:28:00 +02:00
// check type2
if (TYPE_EFFECT_DEF_TYPE(i) == type2 && type1 != type2)
ModulateDmgByType2(TYPE_EFFECT_MULTIPLIER(i), move, &flags);
2017-09-20 00:28:00 +02:00
}
i += 3;
}
}
2017-10-10 18:01:45 +02:00
if (targetAbility == ABILITY_WONDER_GUARD
2017-09-20 00:28:00 +02:00
&& (!(flags & MOVESTATUS_SUPEREFFECTIVE) || ((flags & (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)) == (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)))
&& gBattleMoves[move].power)
flags |= MOVESTATUS_NOTAFFECTED;
return flags;
}
// Multiplies the damage by a random factor between 85% to 100% inclusive
static inline void ApplyRandomDmgMultiplier(void)
{
u16 rand = Random();
u16 randPercent = 100 - (rand % 16);
if (gBattleMoveDamage != 0)
{
gBattleMoveDamage *= randPercent;
gBattleMoveDamage /= 100;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
}
}
2017-09-28 15:34:21 +02:00
static void Unused_ApplyRandomDmgMultiplier(void)
2017-09-20 00:28:00 +02:00
{
ApplyRandomDmgMultiplier();
}
static void atk07_adjustnormaldamage(void)
2017-09-20 00:28:00 +02:00
{
u8 holdEffect, quality;
ApplyRandomDmgMultiplier();
if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY)
{
holdEffect = gEnigmaBerries[gBankTarget].holdEffect, quality = gEnigmaBerries[gBankTarget].holdEffectParam;
}
else
{
holdEffect = ItemId_GetHoldEffect(gBattleMons[gBankTarget].item);
quality = ItemId_GetHoldEffectParam(gBattleMons[gBankTarget].item);
}
gStringBank = gBankTarget;
if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < quality)
{
RecordItemEffectBattle(gBankTarget, holdEffect);
gSpecialStatuses[gBankTarget].focusBanded = 1;
}
if (gBattleMons[gBankTarget].status2 & STATUS2_SUBSTITUTE)
goto END;
if (gBattleMoves[gCurrentMove].effect != EFFECT_FALSE_SWIPE && !gProtectStructs[gBankTarget].endured
&& !gSpecialStatuses[gBankTarget].focusBanded)
goto END;
if (gBattleMons[gBankTarget].hp > gBattleMoveDamage)
goto END;
gBattleMoveDamage = gBattleMons[gBankTarget].hp - 1;
if (gProtectStructs[gBankTarget].endured)
{
gBattleMoveFlags |= MOVESTATUS_ENDURED;
}
else if (gSpecialStatuses[gBankTarget].focusBanded)
{
gBattleMoveFlags |= MOVESTATUS_HUNGON;
gLastUsedItem = gBattleMons[gBankTarget].item;
}
END:
gBattlescriptCurrInstr++;
}
static void atk08_adjustnormaldamage2(void) // The same as 0x7 except it doesn't check for false swipe move effect.
2017-09-20 00:28:00 +02:00
{
u8 holdEffect, quality;
ApplyRandomDmgMultiplier();
if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY)
{
holdEffect = gEnigmaBerries[gBankTarget].holdEffect, quality = gEnigmaBerries[gBankTarget].holdEffectParam;
}
else
{
holdEffect = ItemId_GetHoldEffect(gBattleMons[gBankTarget].item);
quality = ItemId_GetHoldEffectParam(gBattleMons[gBankTarget].item);
}
gStringBank = gBankTarget;
if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < quality)
{
RecordItemEffectBattle(gBankTarget, holdEffect);
gSpecialStatuses[gBankTarget].focusBanded = 1;
}
if (gBattleMons[gBankTarget].status2 & STATUS2_SUBSTITUTE)
goto END;
if (!gProtectStructs[gBankTarget].endured && !gSpecialStatuses[gBankTarget].focusBanded)
goto END;
if (gBattleMons[gBankTarget].hp > gBattleMoveDamage)
goto END;
gBattleMoveDamage = gBattleMons[gBankTarget].hp - 1;
if (gProtectStructs[gBankTarget].endured)
{
gBattleMoveFlags |= MOVESTATUS_ENDURED;
}
else if (gSpecialStatuses[gBankTarget].focusBanded)
{
gBattleMoveFlags |= MOVESTATUS_HUNGON;
gLastUsedItem = gBattleMons[gBankTarget].item;
}
END:
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atk09_attackanimation(void)
2017-09-20 00:28:00 +02:00
{
if (gBattleExecBuffer)
return;
if ((gHitMarker & HITMARKER_NO_ANIMATIONS) && (gCurrentMove != MOVE_TRANSFORM && gCurrentMove != MOVE_SUBSTITUTE))
{
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
2017-09-20 00:28:00 +02:00
gBattlescriptCurrInstr = BattleScript_Pausex20;
gBattleScripting.animTurn++;
gBattleScripting.animTargetsHit++;
}
else
{
if ((gBattleMoves[gCurrentMove].target & MOVE_TARGET_BOTH
|| gBattleMoves[gCurrentMove].target & MOVE_TARGET_FOES_AND_ALLY
|| gBattleMoves[gCurrentMove].target & MOVE_TARGET_DEPENDS)
&& gBattleScripting.animTargetsHit)
{
gBattlescriptCurrInstr++;
return;
}
if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
{
u8 multihit;
gActiveBank = gBankAttacker;
if (gBattleMons[gBankTarget].status2 & STATUS2_SUBSTITUTE)
multihit = gMultiHitCounter;
else if (gMultiHitCounter != 0 && gMultiHitCounter != 1)
{
if (gBattleMons[gBankTarget].hp <= gBattleMoveDamage)
multihit = 1;
else
multihit = gMultiHitCounter;
}
else
multihit = gMultiHitCounter;
EmitMoveAnimation(0, gCurrentMove, gBattleScripting.animTurn, gBattleMovePower, gBattleMoveDamage, gBattleMons[gBankAttacker].friendship, &gDisableStructs[gBankAttacker], multihit);
gBattleScripting.animTurn += 1;
gBattleScripting.animTargetsHit += 1;
MarkBufferBankForExecution(gBankAttacker);
gBattlescriptCurrInstr++;
}
else
{
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
2017-09-20 00:28:00 +02:00
gBattlescriptCurrInstr = BattleScript_Pausex20;
}
}
}
2017-09-28 15:34:21 +02:00
static void atk0A_waitanimation(void)
2017-09-20 00:28:00 +02:00
{
if (gBattleExecBuffer == 0)
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atk0B_healthbarupdate(void)
2017-09-20 00:28:00 +02:00
{
2017-09-20 12:56:45 +02:00
if (gBattleExecBuffer)
return;
if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-20 12:56:45 +02:00
if (gBattleMons[gActiveBank].status2 & STATUS2_SUBSTITUTE && gDisableStructs[gActiveBank].substituteHP && !(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE))
{
2017-10-07 15:15:47 +02:00
PrepareStringBattle(STRINGID_SUBSTITUTEDAMAGED, gActiveBank);
2017-09-20 12:56:45 +02:00
}
else
{
s16 healthValue;
s32 currDmg = gBattleMoveDamage;
s32 maxPossibleDmgValue = 10000; // not present in R/S, ensures that huge damage values don't change sign
if (currDmg <= maxPossibleDmgValue)
healthValue = currDmg;
else
healthValue = maxPossibleDmgValue;
EmitHealthBarUpdate(0, healthValue);
MarkBufferBankForExecution(gActiveBank);
if (GetBankSide(gActiveBank) == SIDE_PLAYER && gBattleMoveDamage > 0)
gBattleResults.unk5_0 = 1;
}
}
gBattlescriptCurrInstr += 2;
}
2017-09-28 15:34:21 +02:00
static void atk0C_datahpupdate(void)
2017-09-20 12:56:45 +02:00
{
u32 moveType;
2017-09-20 00:28:00 +02:00
if (gBattleExecBuffer)
return;
2017-09-20 12:56:45 +02:00
if (gBattleStruct->dynamicMoveType == 0)
moveType = gBattleMoves[gCurrentMove].type;
else if (!(gBattleStruct->dynamicMoveType & 0x40))
moveType = gBattleStruct->dynamicMoveType & 0x3F;
else
moveType = gBattleMoves[gCurrentMove].type;
2017-09-20 00:28:00 +02:00
2017-09-20 12:56:45 +02:00
if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
2017-09-20 00:28:00 +02:00
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-20 12:56:45 +02:00
if (gBattleMons[gActiveBank].status2 & STATUS2_SUBSTITUTE && gDisableStructs[gActiveBank].substituteHP && !(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE))
{
if (gDisableStructs[gActiveBank].substituteHP >= gBattleMoveDamage)
{
if (gSpecialStatuses[gActiveBank].moveturnLostHP == 0)
gSpecialStatuses[gActiveBank].moveturnLostHP = gBattleMoveDamage;
gDisableStructs[gActiveBank].substituteHP -= gBattleMoveDamage;
gHpDealt = gBattleMoveDamage;
}
else
{
if (gSpecialStatuses[gActiveBank].moveturnLostHP == 0)
gSpecialStatuses[gActiveBank].moveturnLostHP = gDisableStructs[gActiveBank].substituteHP;
gHpDealt = gDisableStructs[gActiveBank].substituteHP;
gDisableStructs[gActiveBank].substituteHP = 0;
}
// check substitute fading
if (gDisableStructs[gActiveBank].substituteHP == 0)
{
gBattlescriptCurrInstr += 2;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor();
2017-09-20 12:56:45 +02:00
gBattlescriptCurrInstr = BattleScript_SubstituteFade;
return;
}
}
else
{
gHitMarker &= ~(HITMARKER_IGNORE_SUBSTITUTE);
if (gBattleMoveDamage < 0) // hp goes up
{
gBattleMons[gActiveBank].hp -= gBattleMoveDamage;
if (gBattleMons[gActiveBank].hp > gBattleMons[gActiveBank].maxHP)
gBattleMons[gActiveBank].hp = gBattleMons[gActiveBank].maxHP;
}
else // hp goes down
{
if (gHitMarker & HITMARKER_x20)
{
gHitMarker &= ~(HITMARKER_x20);
}
else
{
gTakenDmg[gActiveBank] += gBattleMoveDamage;
2017-09-28 15:34:21 +02:00
if (gBattlescriptCurrInstr[1] == BS_GET_TARGET)
2017-09-20 12:56:45 +02:00
gTakenDmgBanks[gActiveBank] = gBankAttacker;
else
gTakenDmgBanks[gActiveBank] = gBankTarget;
}
if (gBattleMons[gActiveBank].hp > gBattleMoveDamage)
{
gBattleMons[gActiveBank].hp -= gBattleMoveDamage;
gHpDealt = gBattleMoveDamage;
}
else
{
gHpDealt = gBattleMons[gActiveBank].hp;
gBattleMons[gActiveBank].hp = 0;
}
if (!gSpecialStatuses[gActiveBank].moveturnLostHP && !(gHitMarker & HITMARKER_x100000))
gSpecialStatuses[gActiveBank].moveturnLostHP = gHpDealt;
if (moveType <= 8 && !(gHitMarker & HITMARKER_x100000) && gCurrentMove != MOVE_PAIN_SPLIT)
{
gProtectStructs[gActiveBank].physicalDmg = gHpDealt;
gSpecialStatuses[gActiveBank].moveturnLostHP_physical = gHpDealt;
2017-09-28 15:34:21 +02:00
if (gBattlescriptCurrInstr[1] == BS_GET_TARGET)
2017-09-20 12:56:45 +02:00
{
gProtectStructs[gActiveBank].physicalBank = gBankAttacker;
gSpecialStatuses[gActiveBank].moveturnPhysicalBank = gBankAttacker;
}
else
{
gProtectStructs[gActiveBank].physicalBank = gBankTarget;
gSpecialStatuses[gActiveBank].moveturnPhysicalBank = gBankTarget;
}
}
else if (moveType > 8 && !(gHitMarker & HITMARKER_x100000))
{
gProtectStructs[gActiveBank].specialDmg = gHpDealt;
gSpecialStatuses[gActiveBank].moveturnLostHP_special = gHpDealt;
2017-09-28 15:34:21 +02:00
if (gBattlescriptCurrInstr[1] == BS_GET_TARGET)
2017-09-20 12:56:45 +02:00
{
gProtectStructs[gActiveBank].specialBank = gBankAttacker;
gSpecialStatuses[gActiveBank].moveturnSpecialBank = gBankAttacker;
}
else
{
gProtectStructs[gActiveBank].specialBank = gBankTarget;
gSpecialStatuses[gActiveBank].moveturnSpecialBank = gBankTarget;
}
}
}
gHitMarker &= ~(HITMARKER_x100000);
2017-09-26 22:39:59 +02:00
EmitSetMonData(0, REQUEST_HP_BATTLE, 0, 2, &gBattleMons[gActiveBank].hp);
2017-09-20 12:56:45 +02:00
MarkBufferBankForExecution(gActiveBank);
}
}
else
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-20 12:56:45 +02:00
if (gSpecialStatuses[gActiveBank].moveturnLostHP == 0)
gSpecialStatuses[gActiveBank].moveturnLostHP = 0xFFFF;
}
gBattlescriptCurrInstr += 2;
}
2017-09-28 15:34:21 +02:00
static void atk0D_critmessage(void)
2017-09-20 12:56:45 +02:00
{
if (gBattleExecBuffer == 0)
{
if (gCritMultiplier == 2 && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
{
2017-10-07 15:15:47 +02:00
PrepareStringBattle(STRINGID_CRITICALHIT, gBankAttacker);
2017-09-20 12:56:45 +02:00
gBattleCommunication[MSG_DISPLAY] = 1;
}
gBattlescriptCurrInstr++;
}
}
static void atk0E_effectivenesssound(void)
2017-09-20 12:56:45 +02:00
{
if (gBattleExecBuffer)
return;
gActiveBank = gBankTarget;
if (!(gBattleMoveFlags & MOVESTATUS_MISSED))
{
switch (gBattleMoveFlags & (u8)(~(MOVESTATUS_MISSED)))
{
case MOVESTATUS_SUPEREFFECTIVE:
EmitPlaySE(0, SE_KOUKA_H);
2017-09-20 12:56:45 +02:00
MarkBufferBankForExecution(gActiveBank);
break;
case MOVESTATUS_NOTVERYEFFECTIVE:
EmitPlaySE(0, SE_KOUKA_L);
2017-09-20 12:56:45 +02:00
MarkBufferBankForExecution(gActiveBank);
break;
case MOVESTATUS_NOTAFFECTED:
case MOVESTATUS_FAILED:
// no sound
break;
case MOVESTATUS_ENDURED:
case MOVESTATUS_ONEHITKO:
case MOVESTATUS_HUNGON:
default:
if (gBattleMoveFlags & MOVESTATUS_SUPEREFFECTIVE)
{
EmitPlaySE(0, SE_KOUKA_H);
2017-09-20 12:56:45 +02:00
MarkBufferBankForExecution(gActiveBank);
}
else if (gBattleMoveFlags & MOVESTATUS_NOTVERYEFFECTIVE)
{
EmitPlaySE(0, SE_KOUKA_L);
2017-09-20 12:56:45 +02:00
MarkBufferBankForExecution(gActiveBank);
}
else if (!(gBattleMoveFlags & (MOVESTATUS_NOTAFFECTED | MOVESTATUS_FAILED)))
{
EmitPlaySE(0, SE_KOUKA_M);
2017-09-20 12:56:45 +02:00
MarkBufferBankForExecution(gActiveBank);
}
break;
}
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atk0F_resultmessage(void)
2017-09-20 12:56:45 +02:00
{
u32 stringId = 0;
if (gBattleExecBuffer)
return;
if (gBattleMoveFlags & MOVESTATUS_MISSED && (!(gBattleMoveFlags & MOVESTATUS_NOTAFFECTED) || gBattleCommunication[6] > 2))
{
stringId = gMissStringIds[gBattleCommunication[6]];
gBattleCommunication[MSG_DISPLAY] = 1;
}
else
{
gBattleCommunication[MSG_DISPLAY] = 1;
switch (gBattleMoveFlags & (u8)(~(MOVESTATUS_MISSED)))
{
case MOVESTATUS_SUPEREFFECTIVE:
2017-10-07 15:15:47 +02:00
stringId = STRINGID_SUPEREFFECTIVE;
2017-09-20 12:56:45 +02:00
break;
case MOVESTATUS_NOTVERYEFFECTIVE:
2017-10-07 15:15:47 +02:00
stringId = STRINGID_NOTVERYEFFECTIVE;
2017-09-20 12:56:45 +02:00
break;
case MOVESTATUS_ONEHITKO:
2017-10-07 15:15:47 +02:00
stringId = STRINGID_ONEHITKO;
2017-09-20 12:56:45 +02:00
break;
case MOVESTATUS_ENDURED:
2017-10-07 15:15:47 +02:00
stringId = STRINGID_PKMNENDUREDHIT;
2017-09-20 12:56:45 +02:00
break;
case MOVESTATUS_FAILED:
2017-10-07 15:15:47 +02:00
stringId = STRINGID_BUTITFAILED;
2017-09-20 12:56:45 +02:00
break;
case MOVESTATUS_NOTAFFECTED:
2017-10-07 15:15:47 +02:00
stringId = STRINGID_ITDOESNTAFFECT;
2017-09-20 12:56:45 +02:00
break;
case MOVESTATUS_HUNGON:
gLastUsedItem = gBattleMons[gBankTarget].item;
gStringBank = gBankTarget;
gBattleMoveFlags &= ~(MOVESTATUS_ENDURED | MOVESTATUS_HUNGON);
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor();
2017-09-20 12:56:45 +02:00
gBattlescriptCurrInstr = BattleScript_HangedOnMsg;
return;
default:
if (gBattleMoveFlags & MOVESTATUS_NOTAFFECTED)
{
2017-10-07 15:15:47 +02:00
stringId = STRINGID_ITDOESNTAFFECT;
2017-09-20 12:56:45 +02:00
}
else if (gBattleMoveFlags & MOVESTATUS_ONEHITKO)
{
gBattleMoveFlags &= ~(MOVESTATUS_ONEHITKO);
gBattleMoveFlags &= ~(MOVESTATUS_SUPEREFFECTIVE);
gBattleMoveFlags &= ~(MOVESTATUS_NOTVERYEFFECTIVE);
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor();
2017-09-20 12:56:45 +02:00
gBattlescriptCurrInstr = BattleScript_OneHitKOMsg;
return;
}
else if (gBattleMoveFlags & MOVESTATUS_ENDURED)
{
gBattleMoveFlags &= ~(MOVESTATUS_ENDURED | MOVESTATUS_HUNGON);
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor();
2017-09-20 12:56:45 +02:00
gBattlescriptCurrInstr = BattleScript_EnduredMsg;
return;
}
else if (gBattleMoveFlags & MOVESTATUS_HUNGON)
{
gLastUsedItem = gBattleMons[gBankTarget].item;
gStringBank = gBankTarget;
gBattleMoveFlags &= ~(MOVESTATUS_ENDURED | MOVESTATUS_HUNGON);
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor();
2017-09-20 12:56:45 +02:00
gBattlescriptCurrInstr = BattleScript_HangedOnMsg;
return;
}
else if (gBattleMoveFlags & MOVESTATUS_FAILED)
{
2017-10-07 15:15:47 +02:00
stringId = STRINGID_BUTITFAILED;
2017-09-20 12:56:45 +02:00
}
else
{
gBattleCommunication[MSG_DISPLAY] = 0;
}
}
}
if (stringId)
PrepareStringBattle(stringId, gBankAttacker);
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atk10_printstring(void)
2017-09-20 12:56:45 +02:00
{
if (gBattleExecBuffer == 0)
{
u16 var = BS2ScriptRead16(gBattlescriptCurrInstr + 1);
PrepareStringBattle(var, gBankAttacker);
gBattlescriptCurrInstr += 3;
gBattleCommunication[MSG_DISPLAY] = 1;
2017-09-20 00:28:00 +02:00
}
2017-09-20 12:56:45 +02:00
}
2017-09-20 00:28:00 +02:00
static void atk11_printselectionstring(void)
2017-09-20 12:56:45 +02:00
{
gActiveBank = gBankAttacker;
2017-09-20 00:28:00 +02:00
EmitPrintSelectionString(0, BS2ScriptRead16(gBattlescriptCurrInstr + 1));
2017-09-20 00:28:00 +02:00
MarkBufferBankForExecution(gActiveBank);
2017-09-20 12:56:45 +02:00
gBattlescriptCurrInstr += 3;
gBattleCommunication[MSG_DISPLAY] = 1;
}
2017-09-20 00:28:00 +02:00
2017-09-28 15:34:21 +02:00
static void atk12_waitmessage(void)
2017-09-20 12:56:45 +02:00
{
if (gBattleExecBuffer == 0)
{
if (!gBattleCommunication[MSG_DISPLAY])
{
gBattlescriptCurrInstr += 3;
}
else
{
u16 toWait = BS2ScriptRead16(gBattlescriptCurrInstr + 1);
if (++gPauseCounterBattle >= toWait)
{
gPauseCounterBattle = 0;
gBattlescriptCurrInstr += 3;
gBattleCommunication[MSG_DISPLAY] = 0;
}
}
}
}
2017-09-28 15:34:21 +02:00
static void atk13_printfromtable(void)
2017-09-20 12:56:45 +02:00
{
if (gBattleExecBuffer == 0)
{
2017-09-27 23:43:45 +02:00
const u16 *ptr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
2017-09-20 12:56:45 +02:00
ptr += gBattleCommunication[MULTISTRING_CHOOSER];
2017-09-27 23:43:45 +02:00
PrepareStringBattle(*ptr, gBankAttacker);
2017-09-20 12:56:45 +02:00
gBattlescriptCurrInstr += 5;
gBattleCommunication[MSG_DISPLAY] = 1;
}
}
static void atk14_printselectionstringfromtable(void)
2017-09-20 12:56:45 +02:00
{
if (gBattleExecBuffer == 0)
{
2017-09-27 23:43:45 +02:00
const u16 *ptr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
2017-09-20 12:56:45 +02:00
ptr += gBattleCommunication[MULTISTRING_CHOOSER];
gActiveBank = gBankAttacker;
EmitPrintSelectionString(0, *ptr);
2017-09-20 12:56:45 +02:00
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 5;
gBattleCommunication[MSG_DISPLAY] = 1;
}
}
u8 BankGetTurnOrder(u8 bank)
{
s32 i;
for (i = 0; i < gNoOfAllBanks; i++)
{
2017-10-04 19:25:14 +02:00
if (gBanksByTurnOrder[i] == bank)
2017-09-20 12:56:45 +02:00
break;
}
return i;
2017-09-20 00:28:00 +02:00
}
#define INCREMENT_RESET_RETURN \
{ \
gBattlescriptCurrInstr++; \
gBattleCommunication[MOVE_EFFECT_BYTE] = 0; \
return; \
}
#define RESET_RETURN \
{ \
gBattleCommunication[MOVE_EFFECT_BYTE] = 0; \
return; \
}
void SetMoveEffect(bool8 primary, u8 certain)
{
bool32 statusChanged = FALSE;
u8 affectsUser = 0; // 0x40 otherwise
bool32 noSunCanFreeze = TRUE;
if (gBattleCommunication[MOVE_EFFECT_BYTE] & MOVE_EFFECT_AFFECTS_USER)
{
gEffectBank = gBankAttacker; // bank that effects get applied on
gBattleCommunication[MOVE_EFFECT_BYTE] &= ~(MOVE_EFFECT_AFFECTS_USER);
affectsUser = MOVE_EFFECT_AFFECTS_USER;
gBattleScripting.bank = gBankTarget; // theoretically the attacker
}
else
{
gEffectBank = gBankTarget;
gBattleScripting.bank = gBankAttacker;
}
if (gBattleMons[gEffectBank].ability == ABILITY_SHIELD_DUST && !(gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
&& !primary && gBattleCommunication[MOVE_EFFECT_BYTE] <= 9)
INCREMENT_RESET_RETURN
if (gSideAffecting[GET_BANK_SIDE(gEffectBank)] & SIDE_STATUS_SAFEGUARD && !(gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
&& !primary && gBattleCommunication[MOVE_EFFECT_BYTE] <= 7)
INCREMENT_RESET_RETURN
if (gBattleMons[gEffectBank].hp == 0
&& gBattleCommunication[MOVE_EFFECT_BYTE] != MOVE_EFFECT_PAYDAY
&& gBattleCommunication[MOVE_EFFECT_BYTE] != MOVE_EFFECT_STEAL_ITEM)
INCREMENT_RESET_RETURN
if (gBattleMons[gEffectBank].status2 & STATUS2_SUBSTITUTE && affectsUser != MOVE_EFFECT_AFFECTS_USER)
INCREMENT_RESET_RETURN
if (gBattleCommunication[MOVE_EFFECT_BYTE] <= 6) // status change
{
2017-09-28 16:51:24 +02:00
switch (sStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]])
{
case STATUS_SLEEP:
// check active uproar
if (gBattleMons[gEffectBank].ability != ABILITY_SOUNDPROOF)
{
for (gActiveBank = 0;
gActiveBank < gNoOfAllBanks && !(gBattleMons[gActiveBank].status2 & STATUS2_UPROAR);
gActiveBank++)
{}
}
else
gActiveBank = gNoOfAllBanks;
if (gBattleMons[gEffectBank].status1)
break;
if (gActiveBank != gNoOfAllBanks)
break;
if (gBattleMons[gEffectBank].ability == ABILITY_VITAL_SPIRIT)
break;
if (gBattleMons[gEffectBank].ability == ABILITY_INSOMNIA)
break;
CancelMultiTurnMoves(gEffectBank);
statusChanged = TRUE;
break;
case STATUS_POISON:
if (gBattleMons[gEffectBank].ability == ABILITY_IMMUNITY
2017-09-22 21:33:49 +02:00
&& (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
{
gLastUsedAbility = ABILITY_IMMUNITY;
RecordAbilityBattle(gEffectBank, ABILITY_IMMUNITY);
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_PSNPrevention;
if (gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
{
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
gHitMarker &= ~(HITMARKER_IGNORE_SAFEGUARD);
}
else
{
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
}
RESET_RETURN
}
if ((gBattleMons[gEffectBank].type1 == TYPE_POISON || gBattleMons[gEffectBank].type2 == TYPE_POISON
|| gBattleMons[gEffectBank].type1 == TYPE_STEEL || gBattleMons[gEffectBank].type2 == TYPE_STEEL)
&& (gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
2017-09-22 21:33:49 +02:00
&& (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
{
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_PSNPrevention;
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
RESET_RETURN
}
if (gBattleMons[gEffectBank].type1 == TYPE_POISON)
break;
if (gBattleMons[gEffectBank].type2 == TYPE_POISON)
break;
if (gBattleMons[gEffectBank].type1 == TYPE_STEEL)
break;
if (gBattleMons[gEffectBank].type2 == TYPE_STEEL)
break;
if (gBattleMons[gEffectBank].status1)
break;
if (gBattleMons[gEffectBank].ability == ABILITY_IMMUNITY)
break;
statusChanged = TRUE;
break;
case STATUS_BURN:
if (gBattleMons[gEffectBank].ability == ABILITY_WATER_VEIL
2017-09-22 21:33:49 +02:00
&& (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
{
gLastUsedAbility = ABILITY_WATER_VEIL;
RecordAbilityBattle(gEffectBank, ABILITY_WATER_VEIL);
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_BRNPrevention;
if (gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
{
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
gHitMarker &= ~(HITMARKER_IGNORE_SAFEGUARD);
}
else
{
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
}
RESET_RETURN
}
if ((gBattleMons[gEffectBank].type1 == TYPE_FIRE
|| gBattleMons[gEffectBank].type2 == TYPE_FIRE)
&& (gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
2017-09-22 21:33:49 +02:00
&& (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
{
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_BRNPrevention;
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
RESET_RETURN
}
if (gBattleMons[gEffectBank].type1 == TYPE_FIRE)
break;
if (gBattleMons[gEffectBank].type2 == TYPE_FIRE)
break;
if (gBattleMons[gEffectBank].ability == ABILITY_WATER_VEIL)
break;
if (gBattleMons[gEffectBank].status1)
break;
statusChanged = TRUE;
break;
case STATUS_FREEZE:
if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY)
noSunCanFreeze = FALSE;
if (gBattleMons[gEffectBank].type1 == TYPE_ICE)
break;
if (gBattleMons[gEffectBank].type2 == TYPE_ICE)
break;
if (gBattleMons[gEffectBank].status1)
break;
if (noSunCanFreeze == 0)
break;
if (gBattleMons[gEffectBank].ability == ABILITY_MAGMA_ARMOR)
break;
CancelMultiTurnMoves(gEffectBank);
statusChanged = TRUE;
break;
case STATUS_PARALYSIS:
if (gBattleMons[gEffectBank].ability == ABILITY_LIMBER)
{
2017-09-22 21:33:49 +02:00
if (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)
{
gLastUsedAbility = ABILITY_LIMBER;
RecordAbilityBattle(gEffectBank, ABILITY_LIMBER);
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_PRLZPrevention;
if (gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
{
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
gHitMarker &= ~(HITMARKER_IGNORE_SAFEGUARD);
}
else
{
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
}
RESET_RETURN
}
else
break;
}
if (gBattleMons[gEffectBank].status1)
break;
statusChanged = TRUE;
break;
case STATUS_TOXIC_POISON:
2017-09-22 21:33:49 +02:00
if (gBattleMons[gEffectBank].ability == ABILITY_IMMUNITY && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
{
gLastUsedAbility = ABILITY_IMMUNITY;
RecordAbilityBattle(gEffectBank, ABILITY_IMMUNITY);
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_PSNPrevention;
if (gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
{
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
gHitMarker &= ~(HITMARKER_IGNORE_SAFEGUARD);
}
else
{
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
}
RESET_RETURN
}
if ((gBattleMons[gEffectBank].type1 == TYPE_POISON || gBattleMons[gEffectBank].type2 == TYPE_POISON
|| gBattleMons[gEffectBank].type1 == TYPE_STEEL || gBattleMons[gEffectBank].type2 == TYPE_STEEL)
&& (gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
2017-09-22 21:33:49 +02:00
&& (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
{
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_PSNPrevention;
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
RESET_RETURN
}
if (gBattleMons[gEffectBank].status1)
break;
if (gBattleMons[gEffectBank].type1 != TYPE_POISON
&& gBattleMons[gEffectBank].type2 != TYPE_POISON
&& gBattleMons[gEffectBank].type1 != TYPE_STEEL
&& gBattleMons[gEffectBank].type2 != TYPE_STEEL)
{
if (gBattleMons[gEffectBank].ability == ABILITY_IMMUNITY)
break;
// It's redundant, because at this point we know the status1 value is 0.
gBattleMons[gEffectBank].status1 &= ~(STATUS_TOXIC_POISON);
gBattleMons[gEffectBank].status1 &= ~(STATUS_POISON);
statusChanged = TRUE;
break;
}
else
{
gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED;
}
break;
}
if (statusChanged == TRUE)
{
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
2017-09-28 16:51:24 +02:00
if (sStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]] == STATUS_SLEEP)
gBattleMons[gEffectBank].status1 |= ((Random() & 3) + 2);
else
2017-09-28 16:51:24 +02:00
gBattleMons[gEffectBank].status1 |= sStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]];
2017-09-28 16:51:24 +02:00
gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]];
gActiveBank = gEffectBank;
2017-09-26 22:39:59 +02:00
EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gEffectBank].status1);
MarkBufferBankForExecution(gActiveBank);
if (gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
{
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
gHitMarker &= ~(HITMARKER_IGNORE_SAFEGUARD);
}
else
{
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
}
// for synchronize
if (gBattleCommunication[MOVE_EFFECT_BYTE] == MOVE_EFFECT_POISON
|| gBattleCommunication[MOVE_EFFECT_BYTE] == MOVE_EFFECT_TOXIC
|| gBattleCommunication[MOVE_EFFECT_BYTE] == MOVE_EFFECT_PARALYSIS
|| gBattleCommunication[MOVE_EFFECT_BYTE] == MOVE_EFFECT_BURN)
{
u8* synchronizeEffect = &gBattleStruct->synchronizeMoveEffect;
*synchronizeEffect = gBattleCommunication[MOVE_EFFECT_BYTE];
gHitMarker |= HITMARKER_SYNCHRONISE_EFFECT;
}
return;
}
else if (statusChanged == FALSE)
{
gBattleCommunication[MOVE_EFFECT_BYTE] = 0;
gBattlescriptCurrInstr++;
return;
}
2017-09-22 21:33:49 +02:00
return;
}
else
{
2017-09-28 16:51:24 +02:00
if (gBattleMons[gEffectBank].status2 & sStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]])
{
gBattlescriptCurrInstr++;
}
else
{
u8 side;
2017-09-22 21:33:49 +02:00
switch (gBattleCommunication[MOVE_EFFECT_BYTE])
{
case MOVE_EFFECT_CONFUSION:
if (gBattleMons[gEffectBank].ability == ABILITY_OWN_TEMPO
|| gBattleMons[gEffectBank].status2 & STATUS2_CONFUSION)
{
gBattlescriptCurrInstr++;
}
else
{
gBattleMons[gEffectBank].status2 |= (((Random()) % 0x4)) + 2;
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
2017-09-28 16:51:24 +02:00
gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]];
}
break;
case MOVE_EFFECT_FLINCH:
if (gBattleMons[gEffectBank].ability == ABILITY_INNER_FOCUS)
{
2017-09-22 21:33:49 +02:00
if (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)
{
gLastUsedAbility = ABILITY_INNER_FOCUS;
RecordAbilityBattle(gEffectBank, ABILITY_INNER_FOCUS);
gBattlescriptCurrInstr = BattleScript_FlinchPrevention;
}
else
{
gBattlescriptCurrInstr++;
}
}
else
{
2017-10-06 00:12:01 +02:00
if (BankGetTurnOrder(gEffectBank) > gCurrentTurnActionNumber)
2017-09-28 16:51:24 +02:00
gBattleMons[gEffectBank].status2 |= sStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]];
2017-09-22 21:33:49 +02:00
gBattlescriptCurrInstr++;
}
break;
case MOVE_EFFECT_UPROAR:
2017-09-22 21:33:49 +02:00
if (!(gBattleMons[gEffectBank].status2 & STATUS2_UPROAR))
{
2017-09-22 21:33:49 +02:00
gBattleMons[gEffectBank].status2 |= STATUS2_MULTIPLETURNS;
gLockedMoves[gEffectBank] = gCurrentMove;
gBattleMons[gEffectBank].status2 |= ((Random() & 3) + 2) << 4;
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
2017-09-28 16:51:24 +02:00
gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]];
}
2017-09-22 21:33:49 +02:00
else
{
gBattlescriptCurrInstr++;
}
break;
case MOVE_EFFECT_PAYDAY:
if (GET_BANK_SIDE(gBankAttacker) == SIDE_PLAYER)
{
u16 PayDay = gPaydayMoney;
gPaydayMoney += (gBattleMons[gBankAttacker].level * 5);
if (PayDay > gPaydayMoney)
gPaydayMoney = 0xFFFF;
}
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
2017-09-28 16:51:24 +02:00
gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]];
break;
case MOVE_EFFECT_TRI_ATTACK:
if (gBattleMons[gEffectBank].status1)
{
gBattlescriptCurrInstr++;
}
else
{
gBattleCommunication[MOVE_EFFECT_BYTE] = Random() % 3 + 3;
SetMoveEffect(FALSE, 0);
}
break;
case MOVE_EFFECT_CHARGING:
gBattleMons[gEffectBank].status2 |= STATUS2_MULTIPLETURNS;
gLockedMoves[gEffectBank] = gCurrentMove;
gProtectStructs[gEffectBank].chargingTurn = 1;
gBattlescriptCurrInstr++;
break;
case MOVE_EFFECT_WRAP:
if (gBattleMons[gEffectBank].status2 & STATUS2_WRAPPED)
{
gBattlescriptCurrInstr++;
}
else
{
2017-09-22 21:33:49 +02:00
gBattleMons[gEffectBank].status2 |= ((Random() & 3) + 3) << 0xD;
*(gBattleStruct->wrappedMove + gEffectBank * 2 + 0) = gCurrentMove;
*(gBattleStruct->wrappedMove + gEffectBank * 2 + 1) = gCurrentMove >> 8;
*(gBattleStruct->wrappedBy + gEffectBank) = gBankAttacker;
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
2017-09-28 16:51:24 +02:00
gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]];
2017-09-22 21:33:49 +02:00
for (gBattleCommunication[MULTISTRING_CHOOSER] = 0; ; gBattleCommunication[MULTISTRING_CHOOSER]++)
{
2017-09-22 21:33:49 +02:00
if (gBattleCommunication[MULTISTRING_CHOOSER] > 4)
break;
if (gTrappingMoves[gBattleCommunication[MULTISTRING_CHOOSER]] == gCurrentMove)
break;
}
}
break;
case MOVE_EFFECT_RECOIL_25: // 25% recoil
gBattleMoveDamage = (gHpDealt) / 4;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
2017-09-28 16:51:24 +02:00
gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]];
break;
2017-09-22 21:33:49 +02:00
case MOVE_EFFECT_ATK_PLUS_1:
case MOVE_EFFECT_DEF_PLUS_1:
case MOVE_EFFECT_SPD_PLUS_1:
case MOVE_EFFECT_SP_ATK_PLUS_1:
case MOVE_EFFECT_SP_DEF_PLUS_1:
case MOVE_EFFECT_ACC_PLUS_1:
case MOVE_EFFECT_EVS_PLUS_1:
if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(1),
gBattleCommunication[MOVE_EFFECT_BYTE] - MOVE_EFFECT_ATK_PLUS_1 + 1,
affectsUser, 0))
{
gBattlescriptCurrInstr++;
}
else
{
2017-09-22 21:33:49 +02:00
gBattleScripting.animArg1 = gBattleCommunication[MOVE_EFFECT_BYTE] & ~(MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN);
gBattleScripting.animArg2 = 0;
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_StatUp;
}
break;
2017-09-22 21:33:49 +02:00
case MOVE_EFFECT_ATK_MINUS_1:
case MOVE_EFFECT_DEF_MINUS_1:
case MOVE_EFFECT_SPD_MINUS_1:
case MOVE_EFFECT_SP_ATK_MINUS_1:
case MOVE_EFFECT_SP_DEF_MINUS_1:
case MOVE_EFFECT_ACC_MINUS_1:
case MOVE_EFFECT_EVS_MINUS_1:
if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(1) | STAT_BUFF_NEGATIVE,
gBattleCommunication[MOVE_EFFECT_BYTE] - MOVE_EFFECT_ATK_MINUS_1 + 1,
affectsUser, 0))
{
gBattlescriptCurrInstr++;
}
else
{
2017-09-22 21:33:49 +02:00
gBattleScripting.animArg1 = gBattleCommunication[MOVE_EFFECT_BYTE] & ~(MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN);
gBattleScripting.animArg2 = 0;
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_StatDown;
}
break;
2017-09-22 21:33:49 +02:00
case MOVE_EFFECT_ATK_PLUS_2:
case MOVE_EFFECT_DEF_PLUS_2:
case MOVE_EFFECT_SPD_PLUS_2:
case MOVE_EFFECT_SP_ATK_PLUS_2:
case MOVE_EFFECT_SP_DEF_PLUS_2:
case MOVE_EFFECT_ACC_PLUS_2:
case MOVE_EFFECT_EVS_PLUS_2:
if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(2),
gBattleCommunication[MOVE_EFFECT_BYTE] - MOVE_EFFECT_ATK_PLUS_2 + 1,
affectsUser, 0))
{
gBattlescriptCurrInstr++;
}
else
{
2017-09-22 21:33:49 +02:00
gBattleScripting.animArg1 = gBattleCommunication[MOVE_EFFECT_BYTE] & ~(MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN);
gBattleScripting.animArg2 = 0;
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_StatUp;
}
break;
2017-09-22 21:33:49 +02:00
case MOVE_EFFECT_ATK_MINUS_2:
case MOVE_EFFECT_DEF_MINUS_2:
case MOVE_EFFECT_SPD_MINUS_2:
case MOVE_EFFECT_SP_ATK_MINUS_2:
case MOVE_EFFECT_SP_DEF_MINUS_2:
case MOVE_EFFECT_ACC_MINUS_2:
case MOVE_EFFECT_EVS_MINUS_2:
if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(2) | STAT_BUFF_NEGATIVE,
gBattleCommunication[MOVE_EFFECT_BYTE] - MOVE_EFFECT_ATK_MINUS_2 + 1,
affectsUser, 0))
{
gBattlescriptCurrInstr++;
}
else
{
2017-09-22 21:33:49 +02:00
gBattleScripting.animArg1 = gBattleCommunication[MOVE_EFFECT_BYTE] & ~(MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN);
gBattleScripting.animArg2 = 0;
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_StatDown;
}
break;
case MOVE_EFFECT_RECHARGE:
gBattleMons[gEffectBank].status2 |= STATUS2_RECHARGE;
gDisableStructs[gEffectBank].rechargeCounter = 2;
gLockedMoves[gEffectBank] = gCurrentMove;
gBattlescriptCurrInstr++;
break;
case MOVE_EFFECT_RAGE:
gBattleMons[gBankAttacker].status2 |= STATUS2_RAGE;
gBattlescriptCurrInstr++;
break;
case MOVE_EFFECT_STEAL_ITEM:
{
if (gBattleTypeFlags & BATTLE_TYPE_x4000000)
{
gBattlescriptCurrInstr++;
break;
}
side = GetBankSide(gBankAttacker);
if (GetBankSide(gBankAttacker) == SIDE_OPPONENT
&& !(gBattleTypeFlags &
(BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_LINK
| BATTLE_TYPE_x2000000
| BATTLE_TYPE_SECRET_BASE)))
{
gBattlescriptCurrInstr++;
}
2017-09-22 21:33:49 +02:00
else if (!(gBattleTypeFlags &
(BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_LINK
| BATTLE_TYPE_x2000000
| BATTLE_TYPE_SECRET_BASE))
&& (gWishFutureKnock.knockedOffPokes[side] & gBitTable[gBattlePartyID[gBankAttacker]]))
{
gBattlescriptCurrInstr++;
}
2017-09-22 21:33:49 +02:00
else if (gBattleMons[gBankTarget].item
&& gBattleMons[gBankTarget].ability == ABILITY_STICKY_HOLD)
{
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_NoItemSteal;
gLastUsedAbility = gBattleMons[gBankTarget].ability;
RecordAbilityBattle(gBankTarget, gLastUsedAbility);
}
2017-09-27 23:43:45 +02:00
else if (gBattleMons[gBankAttacker].item != 0
2017-09-22 21:33:49 +02:00
|| gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY
2017-09-27 23:43:45 +02:00
|| IS_ITEM_MAIL(gBattleMons[gBankTarget].item)
2017-09-22 21:33:49 +02:00
|| gBattleMons[gBankTarget].item == 0)
{
gBattlescriptCurrInstr++;
}
2017-09-22 21:33:49 +02:00
else
{
2017-09-27 23:43:45 +02:00
u16* changedItem = &gBattleStruct->changedItems[gBankAttacker];
2017-09-23 20:13:45 +02:00
gLastUsedItem = *changedItem = gBattleMons[gBankTarget].item;
2017-09-22 21:33:49 +02:00
gBattleMons[gBankTarget].item = 0;
2017-09-22 21:33:49 +02:00
gActiveBank = gBankAttacker;
2017-09-26 22:39:59 +02:00
EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gLastUsedItem);
2017-09-22 21:33:49 +02:00
MarkBufferBankForExecution(gBankAttacker);
2017-09-22 21:33:49 +02:00
gActiveBank = gBankTarget;
2017-09-26 22:39:59 +02:00
EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gBattleMons[gBankTarget].item);
2017-09-22 21:33:49 +02:00
MarkBufferBankForExecution(gBankTarget);
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_ItemSteal;
*(u8*)((u8*)(&gBattleStruct->choicedMove[gBankTarget]) + 0) = 0;
*(u8*)((u8*)(&gBattleStruct->choicedMove[gBankTarget]) + 1) = 0;
}
}
break;
case MOVE_EFFECT_PREVENT_ESCAPE:
gBattleMons[gBankTarget].status2 |= STATUS2_ESCAPE_PREVENTION;
gDisableStructs[gBankTarget].bankPreventingEscape = gBankAttacker;
gBattlescriptCurrInstr++;
break;
case MOVE_EFFECT_NIGHTMARE:
gBattleMons[gBankTarget].status2 |= STATUS2_NIGHTMARE;
gBattlescriptCurrInstr++;
break;
case MOVE_EFFECT_ALL_STATS_UP:
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_AllStatsUp;
break;
case MOVE_EFFECT_RAPIDSPIN:
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_RapidSpinAway;
break;
case MOVE_EFFECT_REMOVE_PARALYSIS: // Smelling salts
if (!(gBattleMons[gBankTarget].status1 & STATUS_PARALYSIS))
{
gBattlescriptCurrInstr++;
}
else
{
gBattleMons[gBankTarget].status1 &= ~(STATUS_PARALYSIS);
gActiveBank = gBankTarget;
2017-09-26 22:39:59 +02:00
EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1);
MarkBufferBankForExecution(gActiveBank);
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_TargetPRLZHeal;
}
break;
case MOVE_EFFECT_ATK_DEF_DOWN: // SuperPower
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_AtkDefDown;
break;
case MOVE_EFFECT_RECOIL_33_PARALYSIS: // Volt Tackle
gBattleMoveDamage = gHpDealt / 3;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
2017-09-28 16:51:24 +02:00
gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]];
break;
case MOVE_EFFECT_THRASH:
if (gBattleMons[gEffectBank].status2 & STATUS2_LOCK_CONFUSE)
{
gBattlescriptCurrInstr++;
}
else
{
gBattleMons[gEffectBank].status2 |= STATUS2_MULTIPLETURNS;
gLockedMoves[gEffectBank] = gCurrentMove;
gBattleMons[gEffectBank].status2 |= (((Random() & 1) + 2) << 0xA);
}
break;
case MOVE_EFFECT_KNOCK_OFF:
if (gBattleMons[gEffectBank].ability == ABILITY_STICKY_HOLD)
{
if (gBattleMons[gEffectBank].item == 0)
{
gBattlescriptCurrInstr++;
}
else
{
gLastUsedAbility = ABILITY_STICKY_HOLD;
2017-09-27 23:43:45 +02:00
gBattlescriptCurrInstr = BattleScript_StickyHoldActivates;
RecordAbilityBattle(gEffectBank, ABILITY_STICKY_HOLD);
}
break;
}
2017-09-22 21:33:49 +02:00
if (gBattleMons[gEffectBank].item)
{
side = GetBankSide(gEffectBank);
gLastUsedItem = gBattleMons[gEffectBank].item;
gBattleMons[gEffectBank].item = 0;
gWishFutureKnock.knockedOffPokes[side] |= gBitTable[gBattlePartyID[gEffectBank]];
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_KnockedOff;
*(u8*)((u8*)(&gBattleStruct->choicedMove[gEffectBank]) + 0) = 0;
*(u8*)((u8*)(&gBattleStruct->choicedMove[gEffectBank]) + 1) = 0;
}
2017-09-22 21:33:49 +02:00
else
{
gBattlescriptCurrInstr++;
}
break;
case MOVE_EFFECT_SP_ATK_TWO_DOWN: // Overheat
2017-09-22 21:33:49 +02:00
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_SAtkDown2;
break;
}
}
}
gBattleCommunication[MOVE_EFFECT_BYTE] = 0;
}
2017-09-22 21:33:49 +02:00
2017-09-28 15:34:21 +02:00
static void atk15_seteffectwithchance(void)
2017-09-22 21:33:49 +02:00
{
u32 percentChance;
if (gBattleMons[gBankAttacker].ability == ABILITY_SERENE_GRACE)
percentChance = gBattleMoves[gCurrentMove].secondaryEffectChance * 2;
else
percentChance = gBattleMoves[gCurrentMove].secondaryEffectChance;
if (gBattleCommunication[MOVE_EFFECT_BYTE] & MOVE_EFFECT_CERTAIN
&& !(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
{
gBattleCommunication[MOVE_EFFECT_BYTE] &= ~(MOVE_EFFECT_CERTAIN);
SetMoveEffect(0, MOVE_EFFECT_CERTAIN);
}
else if (Random() % 100 < percentChance
&& gBattleCommunication[MOVE_EFFECT_BYTE]
&& !(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
{
if (percentChance >= 100)
SetMoveEffect(0, MOVE_EFFECT_CERTAIN);
else
SetMoveEffect(0, 0);
}
else
{
gBattlescriptCurrInstr++;
}
gBattleCommunication[MOVE_EFFECT_BYTE] = 0;
gBattleScripting.field_16 = 0;
}
2017-09-28 15:34:21 +02:00
static void atk16_seteffectprimary(void)
2017-09-22 21:33:49 +02:00
{
SetMoveEffect(TRUE, 0);
}
2017-09-28 15:34:21 +02:00
static void atk17_seteffectsecondary(void)
2017-09-22 21:33:49 +02:00
{
SetMoveEffect(FALSE, 0);
}
static void atk18_clearstatusfromeffect(void)
2017-09-22 21:33:49 +02:00
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-22 21:33:49 +02:00
if (gBattleCommunication[MOVE_EFFECT_BYTE] <= MOVE_EFFECT_TOXIC)
2017-09-28 16:51:24 +02:00
gBattleMons[gActiveBank].status1 &= (~sStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]]);
2017-09-22 21:33:49 +02:00
else
2017-09-28 16:51:24 +02:00
gBattleMons[gActiveBank].status2 &= (~sStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]]);
2017-09-22 21:33:49 +02:00
gBattleCommunication[MOVE_EFFECT_BYTE] = 0;
gBattlescriptCurrInstr += 2;
gBattleScripting.field_16 = 0;
}
static void atk19_tryfaintmon(void)
2017-09-22 21:33:49 +02:00
{
const u8 *BS_ptr;
if (gBattlescriptCurrInstr[2] != 0)
{
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
if (gHitMarker & HITMARKER_FAINTED(gActiveBank))
{
BS_ptr = BSScriptReadPtr(gBattlescriptCurrInstr + 3);
BattleScriptPop();
gBattlescriptCurrInstr = BS_ptr;
gSideAffecting[GetBankSide(gActiveBank)] &= ~(SIDE_STATUS_SPIKES_DAMAGED);
}
else
{
gBattlescriptCurrInstr += 7;
}
}
else
{
u8 bank;
if (gBattlescriptCurrInstr[1] == BS_GET_ATTACKER)
{
gActiveBank = gBankAttacker;
bank = gBankTarget;
BS_ptr = BattleScript_FaintAttacker;
}
else
{
gActiveBank = gBankTarget;
bank = gBankAttacker;
BS_ptr = BattleScript_FaintTarget;
}
if (!(gAbsentBankFlags & gBitTable[gActiveBank])
&& gBattleMons[gActiveBank].hp == 0)
{
gHitMarker |= HITMARKER_FAINTED(gActiveBank);
BattleScriptPush(gBattlescriptCurrInstr + 7);
gBattlescriptCurrInstr = BS_ptr;
if (GetBankSide(gActiveBank) == SIDE_PLAYER)
{
gHitMarker |= HITMARKER_x400000;
if (gBattleResults.playerFaintCounter < 0xFF)
gBattleResults.playerFaintCounter++;
AdjustFriendshipOnBattleFaint(gActiveBank);
}
else
{
if (gBattleResults.opponentFaintCounter < 0xFF)
gBattleResults.opponentFaintCounter++;
gBattleResults.lastOpponentSpecies = GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES, NULL);
}
if ((gHitMarker & HITMARKER_DESTINYBOND) && gBattleMons[gBankAttacker].hp != 0)
{
gHitMarker &= ~(HITMARKER_DESTINYBOND);
BattleScriptPush(gBattlescriptCurrInstr);
gBattleMoveDamage = gBattleMons[bank].hp;
gBattlescriptCurrInstr = BattleScript_DestinyBondTakesLife;
}
if ((gStatuses3[gBankTarget] & STATUS3_GRUDGE)
&& !(gHitMarker & HITMARKER_GRUDGE)
&& GetBankSide(gBankAttacker) != GetBankSide(gBankTarget)
&& gBattleMons[gBankAttacker].hp != 0
&& gCurrentMove != MOVE_STRUGGLE)
{
2017-10-06 00:12:01 +02:00
u8 moveIndex = *(gBattleStruct->chosenMovePositions + gBankAttacker);
2017-09-22 21:33:49 +02:00
gBattleMons[gBankAttacker].pp[moveIndex] = 0;
BattleScriptPush(gBattlescriptCurrInstr);
gBattlescriptCurrInstr = BattleScript_GrudgeTakesPp;
gActiveBank = gBankAttacker;
2017-09-26 22:39:59 +02:00
EmitSetMonData(0, moveIndex + REQUEST_PPMOVE1_BATTLE, 0, 1, &gBattleMons[gActiveBank].pp[moveIndex]);
2017-09-22 21:33:49 +02:00
MarkBufferBankForExecution(gActiveBank);
2017-09-25 00:09:13 +02:00
PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleMons[gBankAttacker].moves[moveIndex])
2017-09-22 21:33:49 +02:00
}
}
else
{
gBattlescriptCurrInstr += 7;
}
}
}
static void atk1A_dofaintanimation(void)
2017-09-22 21:33:49 +02:00
{
if (gBattleExecBuffer == 0)
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-22 21:33:49 +02:00
EmitFaintAnimation(0);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 2;
}
}
static void atk1B_cleareffectsonfaint(void)
2017-09-22 21:33:49 +02:00
{
if (gBattleExecBuffer == 0)
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-22 21:33:49 +02:00
if (!(gBattleTypeFlags & BATTLE_TYPE_ARENA) || gBattleMons[gActiveBank].hp == 0)
{
gBattleMons[gActiveBank].status1 = 0;
2017-09-26 22:39:59 +02:00
EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 0x4, &gBattleMons[gActiveBank].status1);
2017-09-22 21:33:49 +02:00
MarkBufferBankForExecution(gActiveBank);
}
2017-10-02 23:32:39 +02:00
FaintClearSetData(); // Effects like attractions, trapping, etc.
2017-09-22 21:33:49 +02:00
gBattlescriptCurrInstr += 2;
}
}
2017-09-28 15:34:21 +02:00
static void atk1C_jumpifstatus(void)
2017-09-22 21:33:49 +02:00
{
2017-09-28 15:34:21 +02:00
u8 bank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-22 21:33:49 +02:00
u32 flags = BS2ScriptRead32(gBattlescriptCurrInstr + 2);
const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 6);
if (gBattleMons[bank].status1 & flags && gBattleMons[bank].hp)
gBattlescriptCurrInstr = jumpPtr;
else
gBattlescriptCurrInstr += 10;
}
2017-09-28 15:34:21 +02:00
static void atk1D_jumpifstatus2(void)
2017-09-22 21:33:49 +02:00
{
2017-09-28 15:34:21 +02:00
u8 bank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-22 21:33:49 +02:00
u32 flags = BS2ScriptRead32(gBattlescriptCurrInstr + 2);
const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 6);
if (gBattleMons[bank].status2 & flags && gBattleMons[bank].hp)
gBattlescriptCurrInstr = jumpPtr;
else
gBattlescriptCurrInstr += 10;
}
2017-09-28 15:34:21 +02:00
static void atk1E_jumpifability(void)
2017-09-22 21:33:49 +02:00
{
u8 bank;
2017-09-28 15:34:21 +02:00
u8 ability = gBattlescriptCurrInstr[2];
2017-09-22 21:33:49 +02:00
const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 3);
2017-09-28 15:34:21 +02:00
if (gBattlescriptCurrInstr[1] == BS_GET_ATTACKER_SIDE)
2017-09-22 21:33:49 +02:00
{
bank = AbilityBattleEffects(ABILITYEFFECT_CHECK_BANK_SIDE, gBankAttacker, ability, 0, 0);
if (bank)
{
gLastUsedAbility = ability;
gBattlescriptCurrInstr = jumpPtr;
RecordAbilityBattle(bank - 1, gLastUsedAbility);
gBattleScripting.field_15 = bank - 1;
}
else
gBattlescriptCurrInstr += 7;
}
2017-09-28 15:34:21 +02:00
else if (gBattlescriptCurrInstr[1] == BS_GET_NOT_ATTACKER_SIDE)
2017-09-22 21:33:49 +02:00
{
bank = AbilityBattleEffects(ABILITYEFFECT_CHECK_OTHER_SIDE, gBankAttacker, ability, 0, 0);
if (bank)
{
gLastUsedAbility = ability;
gBattlescriptCurrInstr = jumpPtr;
RecordAbilityBattle(bank - 1, gLastUsedAbility);
gBattleScripting.field_15 = bank - 1;
}
else
gBattlescriptCurrInstr += 7;
}
else
{
2017-09-28 15:34:21 +02:00
bank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-22 21:33:49 +02:00
if (gBattleMons[bank].ability == ability)
{
gLastUsedAbility = ability;
gBattlescriptCurrInstr = jumpPtr;
RecordAbilityBattle(bank, gLastUsedAbility);
gBattleScripting.field_15 = bank;
}
else
gBattlescriptCurrInstr += 7;
}
}
2017-09-28 15:34:21 +02:00
static void atk1F_jumpifsideaffecting(void)
2017-09-22 21:33:49 +02:00
{
u8 side;
u16 flags;
const u8* jumpPtr;
2017-09-28 15:34:21 +02:00
if (gBattlescriptCurrInstr[1] == BS_GET_ATTACKER)
2017-09-22 21:33:49 +02:00
side = GET_BANK_SIDE(gBankAttacker);
else
side = GET_BANK_SIDE(gBankTarget);
flags = BS2ScriptRead16(gBattlescriptCurrInstr + 2);
jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 4);
if (gSideAffecting[side] & flags)
gBattlescriptCurrInstr = jumpPtr;
else
gBattlescriptCurrInstr += 8;
}
2017-09-28 15:34:21 +02:00
static void atk20_jumpifstat(void)
2017-09-22 21:33:49 +02:00
{
u8 ret = 0;
2017-09-28 15:34:21 +02:00
u8 bank = GetBattleBank(gBattlescriptCurrInstr[1]);
u8 value = gBattleMons[bank].statStages[gBattlescriptCurrInstr[3]];
2017-09-22 21:33:49 +02:00
2017-09-28 15:34:21 +02:00
switch (gBattlescriptCurrInstr[2])
2017-09-22 21:33:49 +02:00
{
case CMP_EQUAL:
2017-09-28 15:34:21 +02:00
if (value == gBattlescriptCurrInstr[4])
2017-09-22 21:33:49 +02:00
ret++;
break;
case CMP_NOT_EQUAL:
2017-09-28 15:34:21 +02:00
if (value != gBattlescriptCurrInstr[4])
2017-09-22 21:33:49 +02:00
ret++;
break;
case CMP_GREATER_THAN:
2017-09-28 15:34:21 +02:00
if (value > gBattlescriptCurrInstr[4])
2017-09-22 21:33:49 +02:00
ret++;
break;
case CMP_LESS_THAN:
2017-09-28 15:34:21 +02:00
if (value < gBattlescriptCurrInstr[4])
2017-09-22 21:33:49 +02:00
ret++;
break;
case CMP_COMMON_BITS:
2017-09-28 15:34:21 +02:00
if (value & gBattlescriptCurrInstr[4])
2017-09-22 21:33:49 +02:00
ret++;
break;
case CMP_NO_COMMON_BITS:
2017-09-28 15:34:21 +02:00
if (!(value & gBattlescriptCurrInstr[4]))
2017-09-22 21:33:49 +02:00
ret++;
break;
}
if (ret)
gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5);
else
gBattlescriptCurrInstr += 9;
}
2017-11-26 11:55:17 +01:00
static void atk21_jumpifstatus3condition(void)
2017-09-22 21:33:49 +02:00
{
u32 flags;
2017-11-26 11:55:17 +01:00
const u8 *jumpPtr;
2017-09-22 21:33:49 +02:00
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-22 21:33:49 +02:00
flags = BS2ScriptRead32(gBattlescriptCurrInstr + 2);
jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 7);
2017-09-28 15:34:21 +02:00
if (gBattlescriptCurrInstr[6])
2017-09-22 21:33:49 +02:00
{
if ((gStatuses3[gActiveBank] & flags) != 0)
gBattlescriptCurrInstr += 11;
else
gBattlescriptCurrInstr = jumpPtr;
}
else
{
if ((gStatuses3[gActiveBank] & flags) != 0)
gBattlescriptCurrInstr = jumpPtr;
else
gBattlescriptCurrInstr += 11;
}
}
2017-09-28 15:34:21 +02:00
static void atk22_jumpiftype(void)
2017-09-22 21:33:49 +02:00
{
2017-09-28 15:34:21 +02:00
u8 bank = GetBattleBank(gBattlescriptCurrInstr[1]);
u8 type = gBattlescriptCurrInstr[2];
2017-09-22 21:33:49 +02:00
const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 3);
if (gBattleMons[bank].type1 == type || gBattleMons[bank].type2 == type)
gBattlescriptCurrInstr = jumpPtr;
else
gBattlescriptCurrInstr += 7;
}
2017-09-28 15:34:21 +02:00
static void atk23_getexp(void)
2017-09-22 21:33:49 +02:00
{
u16 item;
s32 i; // also used as stringId
u8 holdEffect;
s32 sentIn;
s32 viaExpShare = 0;
u16* exp = &gBattleStruct->expValue;
2017-09-28 15:34:21 +02:00
gBank1 = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-22 21:33:49 +02:00
sentIn = gSentPokesToOpponent[(gBank1 & 2) >> 1];
switch (gBattleScripting.atk23_state)
{
case 0: // check if should receive exp at all
if (GetBankSide(gBank1) != SIDE_OPPONENT || (gBattleTypeFlags &
(BATTLE_TYPE_LINK
| BATTLE_TYPE_x2000000
| BATTLE_TYPE_x4000000
| BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_SAFARI
| BATTLE_TYPE_BATTLE_TOWER
| BATTLE_TYPE_EREADER_TRAINER)))
{
gBattleScripting.atk23_state = 6; // goto last case
}
else
{
gBattleScripting.atk23_state++;
gBattleStruct->field_DF |= gBitTable[gBattlePartyID[gBank1]];
}
break;
case 1: // calculate experience points to redistribute
{
u16 calculatedExp;
s32 viaSentIn;
for (viaSentIn = 0, i = 0; i < 6; i++)
{
if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) == SPECIES_NONE || GetMonData(&gPlayerParty[i], MON_DATA_HP) == 0)
continue;
if (gBitTable[i] & sentIn)
viaSentIn++;
item = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
if (item == ITEM_ENIGMA_BERRY)
holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
else
holdEffect = ItemId_GetHoldEffect(item);
if (holdEffect == HOLD_EFFECT_EXP_SHARE)
viaExpShare++;
}
calculatedExp = gBaseStats[gBattleMons[gBank1].species].expYield * gBattleMons[gBank1].level / 7;
if (viaExpShare) // at least one mon is getting exp via exp share
{
*exp = calculatedExp / 2 / viaSentIn;
if (*exp == 0)
*exp = 1;
gExpShareExp = calculatedExp / 2 / viaExpShare;
if (gExpShareExp == 0)
gExpShareExp = 1;
}
else
{
*exp = calculatedExp / viaSentIn;
if (*exp == 0)
*exp = 1;
gExpShareExp = 0;
}
gBattleScripting.atk23_state++;
gBattleStruct->expGetterId = 0;
gBattleStruct->sentInPokes = sentIn;
}
// fall through
case 2: // set exp value to the poke in expgetter_id and print message
if (gBattleExecBuffer == 0)
{
item = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_HELD_ITEM);
if (item == ITEM_ENIGMA_BERRY)
holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
else
holdEffect = ItemId_GetHoldEffect(item);
if (holdEffect != HOLD_EFFECT_EXP_SHARE && !(gBattleStruct->sentInPokes & 1))
{
*(&gBattleStruct->sentInPokes) >>= 1;
gBattleScripting.atk23_state = 5;
gBattleMoveDamage = 0; // used for exp
}
else if (GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_LEVEL) == MAX_MON_LEVEL)
{
*(&gBattleStruct->sentInPokes) >>= 1;
gBattleScripting.atk23_state = 5;
gBattleMoveDamage = 0; // used for exp
}
else
{
// music change in wild battle after fainting a poke
if (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER) && gBattleMons[0].hp && !gBattleStruct->wildVictorySong)
{
2017-11-04 16:11:13 +01:00
BattleStopLowHpSound();
2017-09-22 21:33:49 +02:00
PlayBGM(0x161);
gBattleStruct->wildVictorySong++;
}
if (GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_HP))
{
if (gBattleStruct->sentInPokes & 1)
gBattleMoveDamage = *exp;
else
gBattleMoveDamage = 0;
if (holdEffect == HOLD_EFFECT_EXP_SHARE)
gBattleMoveDamage += gExpShareExp;
if (holdEffect == HOLD_EFFECT_LUCKY_EGG)
gBattleMoveDamage = (gBattleMoveDamage * 150) / 100;
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
gBattleMoveDamage = (gBattleMoveDamage * 150) / 100;
if (IsTradedMon(&gPlayerParty[gBattleStruct->expGetterId]))
{
// check if the pokemon doesn't belong to the player
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gBattleStruct->expGetterId >= 3)
{
i = 0x149;
}
else
{
gBattleMoveDamage = (gBattleMoveDamage * 150) / 100;
i = 0x14A;
}
}
else
{
2017-09-27 23:43:45 +02:00
i = 0x149;
}
2017-09-22 21:33:49 +02:00
// get exp getter bank
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
if (!(gBattlePartyID[2] != gBattleStruct->expGetterId) && !(gAbsentBankFlags & gBitTable[2]))
gBattleStruct->expGetterBank = 2;
else
{
if (!(gAbsentBankFlags & gBitTable[0]))
gBattleStruct->expGetterBank = 0;
else
gBattleStruct->expGetterBank = 2;
}
}
else
gBattleStruct->expGetterBank = 0;
2017-09-25 00:09:13 +02:00
PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBattleStruct->expGetterBank, gBattleStruct->expGetterId)
2017-09-22 21:33:49 +02:00
// buffer 'gained' or 'gained a boosted'
2017-09-25 00:09:13 +02:00
PREPARE_STRING_BUFFER(gBattleTextBuff2, i)
PREPARE_WORD_NUMBER_BUFFER(gBattleTextBuff3, 5, gBattleMoveDamage)
2017-09-22 21:33:49 +02:00
2017-10-07 15:15:47 +02:00
PrepareStringBattle(STRINGID_PKMNGAINEDEXP, gBattleStruct->expGetterBank);
2017-09-22 21:33:49 +02:00
MonGainEVs(&gPlayerParty[gBattleStruct->expGetterId], gBattleMons[gBank1].species);
}
gBattleStruct->sentInPokes >>= 1;
gBattleScripting.atk23_state++;
}
}
break;
case 3: // Set stats and give exp
if (gBattleExecBuffer == 0)
{
gBattleBufferB[gBattleStruct->expGetterBank][0] = 0;
if (GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_HP) && GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_LEVEL) != MAX_MON_LEVEL)
{
BATTLE_LVLUP_STATS->hp = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_MAX_HP);
BATTLE_LVLUP_STATS->atk = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_ATK);
BATTLE_LVLUP_STATS->def = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_DEF);
BATTLE_LVLUP_STATS->spd = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPEED);
2017-09-22 21:33:49 +02:00
BATTLE_LVLUP_STATS->spAtk = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPATK);
BATTLE_LVLUP_STATS->spDef = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPDEF);
gActiveBank = gBattleStruct->expGetterBank;
EmitExpUpdate(0, gBattleStruct->expGetterId, gBattleMoveDamage);
MarkBufferBankForExecution(gActiveBank);
}
gBattleScripting.atk23_state++;
}
break;
case 4: // lvl up if necessary
if (gBattleExecBuffer == 0)
{
gActiveBank = gBattleStruct->expGetterBank;
2017-10-22 18:43:15 +02:00
if (gBattleBufferB[gActiveBank][0] == CONTROLLER_TWORETURNVALUES && gBattleBufferB[gActiveBank][1] == RET_VALUE_LEVELLED_UP)
2017-09-22 21:33:49 +02:00
{
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && gBattlePartyID[gActiveBank] == gBattleStruct->expGetterId)
2017-11-04 16:11:13 +01:00
HandleLowHpMusicChange(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank);
2017-09-22 21:33:49 +02:00
2017-09-25 00:09:13 +02:00
PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gActiveBank, gBattleStruct->expGetterId)
PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff2, 3, GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_LEVEL))
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor();
gLeveledUpInBattle |= gBitTable[gBattleStruct->expGetterId];
gBattlescriptCurrInstr = BattleScript_LevelUp;
gBattleMoveDamage = (gBattleBufferB[gActiveBank][2] | (gBattleBufferB[gActiveBank][3] << 8));
AdjustFriendship(&gPlayerParty[gBattleStruct->expGetterId], 0);
// update battle mon structure after level up
if (gBattlePartyID[0] == gBattleStruct->expGetterId && gBattleMons[0].hp)
{
gBattleMons[0].level = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_LEVEL);
gBattleMons[0].hp = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_HP);
gBattleMons[0].maxHP = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_MAX_HP);
gBattleMons[0].attack = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_ATK);
gBattleMons[0].defense = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_DEF);
// Why is this duplicated?
gBattleMons[0].speed = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPEED);
gBattleMons[0].speed = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPEED);
2017-09-22 21:33:49 +02:00
gBattleMons[0].spAttack = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPATK);
gBattleMons[0].spDefense = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPDEF);
}
// What is else if?
if (gBattlePartyID[2] == gBattleStruct->expGetterId && gBattleMons[2].hp && (gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
{
gBattleMons[2].level = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_LEVEL);
gBattleMons[2].hp = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_HP);
gBattleMons[2].maxHP = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_MAX_HP);
gBattleMons[2].attack = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_ATK);
gBattleMons[2].defense = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_DEF);
// Duplicated again, but this time there's no Sp Defense
gBattleMons[2].speed = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPEED);
gBattleMons[2].speed = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPEED);
2017-09-22 21:33:49 +02:00
gBattleMons[2].spAttack = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPATK);
}
gBattleScripting.atk23_state = 5;
}
else
{
gBattleMoveDamage = 0;
gBattleScripting.atk23_state = 5;
}
}
break;
case 5: // looper increment
if (gBattleMoveDamage) // there is exp to give, goto case 3 that gives exp
gBattleScripting.atk23_state = 3;
else
{
gBattleStruct->expGetterId++;
if (gBattleStruct->expGetterId <= 5)
gBattleScripting.atk23_state = 2; // loop again
else
gBattleScripting.atk23_state = 6; // we're done
}
break;
case 6: // increment instruction
if (gBattleExecBuffer == 0)
{
// not sure why gf clears the item and ability here
gBattleMons[gBank1].item = 0;
gBattleMons[gBank1].ability = 0;
gBattlescriptCurrInstr += 2;
}
break;
}
}
#ifdef NONMATCHING
2017-09-28 15:34:21 +02:00
static void atk24(void)
2017-09-22 21:33:49 +02:00
{
u16 HP_count = 0;
s32 i;
if (gBattleExecBuffer)
return;
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gPartnerTrainerId == STEVEN_PARTNER_ID)
{
for (i = 0; i < 3; i++)
{
if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) && !GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG))
HP_count += GetMonData(&gPlayerParty[i], MON_DATA_HP);
}
}
else
{
for (i = 0; i < 6; i++)
{
if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) && !GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG)
&& (!(gBattleTypeFlags & BATTLE_TYPE_ARENA) || !(gBattleStruct->field_2A0 & gBitTable[i])))
{
HP_count += GetMonData(&gPlayerParty[i], MON_DATA_HP);
}
}
}
if (HP_count == 0)
gBattleOutcome |= BATTLE_LOST;
for (HP_count = 0, i = 0; i < 6; i++)
{
if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES) && !GetMonData(&gEnemyParty[i], MON_DATA_IS_EGG)
&& (!(gBattleTypeFlags & BATTLE_TYPE_ARENA) || !(gBattleStruct->field_2A1 & gBitTable[i])))
{
HP_count += GetMonData(&gEnemyParty[i], MON_DATA_HP);
}
}
if (HP_count == 0)
gBattleOutcome |= BATTLE_WON;
if (gBattleOutcome == 0 && (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)))
{
s32 foundPlayer;
s32 foundOpponent;
// Impossible to decompile loops.
for (foundPlayer = 0, i = 0; i < gNoOfAllBanks; i += 2)
{
if (HITMARKER_UNK(i) & gHitMarker && !gSpecialStatuses[i].flag40)
foundPlayer++;
}
for (foundOpponent = 0, i = 1; i < gNoOfAllBanks; i += 2)
{
if (HITMARKER_UNK(i) & gHitMarker && !gSpecialStatuses[i].flag40)
foundOpponent++;
}
if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
{
if (foundOpponent + foundPlayer > 1)
gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
else
gBattlescriptCurrInstr += 5;
}
else
{
if (foundOpponent != 0 && foundPlayer != 0)
gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
else
gBattlescriptCurrInstr += 5;
}
}
else
{
gBattlescriptCurrInstr += 5;
}
}
#else
__attribute__((naked))
2017-09-28 15:34:21 +02:00
static void atk24(void)
2017-09-22 21:33:49 +02:00
{
asm("\n\
.syntax unified\n\
push {r4-r7,lr}\n\
mov r7, r8\n\
push {r7}\n\
movs r6, 0\n\
ldr r0, =gBattleExecBuffer\n\
ldr r0, [r0]\n\
cmp r0, 0\n\
beq _0804ACE2\n\
b _0804AF22\n\
_0804ACE2:\n\
ldr r0, =gBattleTypeFlags\n\
ldr r0, [r0]\n\
movs r1, 0x80\n\
lsls r1, 15\n\
ands r0, r1\n\
cmp r0, 0\n\
beq _0804AD48\n\
ldr r0, =gPartnerTrainerId\n\
ldrh r1, [r0]\n\
ldr r0, =0x00000c03\n\
cmp r1, r0\n\
bne _0804AD48\n\
movs r5, 0\n\
_0804ACFC:\n\
movs r0, 0x64\n\
adds r1, r5, 0\n\
muls r1, r0\n\
ldr r0, =gPlayerParty\n\
adds r4, r1, r0\n\
adds r0, r4, 0\n\
movs r1, 0xB\n\
bl GetMonData\n\
cmp r0, 0\n\
beq _0804AD2C\n\
adds r0, r4, 0\n\
movs r1, 0x2D\n\
bl GetMonData\n\
cmp r0, 0\n\
bne _0804AD2C\n\
adds r0, r4, 0\n\
movs r1, 0x39\n\
bl GetMonData\n\
adds r0, r6, r0\n\
lsls r0, 16\n\
lsrs r6, r0, 16\n\
_0804AD2C:\n\
adds r5, 0x1\n\
cmp r5, 0x2\n\
ble _0804ACFC\n\
b _0804ADA8\n\
.pool\n\
_0804AD48:\n\
movs r5, 0\n\
_0804AD4A:\n\
movs r0, 0x64\n\
adds r1, r5, 0\n\
muls r1, r0\n\
ldr r0, =gPlayerParty\n\
adds r4, r1, r0\n\
adds r0, r4, 0\n\
movs r1, 0xB\n\
bl GetMonData\n\
cmp r0, 0\n\
beq _0804ADA2\n\
adds r0, r4, 0\n\
movs r1, 0x2D\n\
bl GetMonData\n\
cmp r0, 0\n\
bne _0804ADA2\n\
ldr r0, =gBattleTypeFlags\n\
ldr r0, [r0]\n\
movs r1, 0x80\n\
lsls r1, 11\n\
ands r0, r1\n\
cmp r0, 0\n\
beq _0804AD94\n\
ldr r0, =gBattleStruct\n\
ldr r0, [r0]\n\
movs r1, 0xA8\n\
lsls r1, 2\n\
adds r0, r1\n\
ldrb r1, [r0]\n\
ldr r2, =gBitTable\n\
lsls r0, r5, 2\n\
adds r0, r2\n\
ldr r0, [r0]\n\
ands r1, r0\n\
cmp r1, 0\n\
bne _0804ADA2\n\
_0804AD94:\n\
adds r0, r4, 0\n\
movs r1, 0x39\n\
bl GetMonData\n\
adds r0, r6, r0\n\
lsls r0, 16\n\
lsrs r6, r0, 16\n\
_0804ADA2:\n\
adds r5, 0x1\n\
cmp r5, 0x5\n\
ble _0804AD4A\n\
_0804ADA8:\n\
cmp r6, 0\n\
bne _0804ADB6\n\
ldr r0, =gBattleOutcome\n\
ldrb r1, [r0]\n\
movs r2, 0x2\n\
orrs r1, r2\n\
strb r1, [r0]\n\
_0804ADB6:\n\
movs r6, 0\n\
movs r5, 0\n\
_0804ADBA:\n\
movs r0, 0x64\n\
adds r1, r5, 0\n\
muls r1, r0\n\
ldr r0, =gEnemyParty\n\
adds r4, r1, r0\n\
adds r0, r4, 0\n\
movs r1, 0xB\n\
bl GetMonData\n\
cmp r0, 0\n\
beq _0804AE10\n\
adds r0, r4, 0\n\
movs r1, 0x2D\n\
bl GetMonData\n\
cmp r0, 0\n\
bne _0804AE10\n\
ldr r0, =gBattleTypeFlags\n\
ldr r0, [r0]\n\
movs r1, 0x80\n\
lsls r1, 11\n\
ands r0, r1\n\
cmp r0, 0\n\
beq _0804AE02\n\
ldr r0, =gBattleStruct\n\
ldr r0, [r0]\n\
ldr r1, =0x000002a1\n\
adds r0, r1\n\
ldrb r1, [r0]\n\
ldr r2, =gBitTable\n\
lsls r0, r5, 2\n\
adds r0, r2\n\
ldr r0, [r0]\n\
ands r1, r0\n\
cmp r1, 0\n\
bne _0804AE10\n\
_0804AE02:\n\
adds r0, r4, 0\n\
movs r1, 0x39\n\
bl GetMonData\n\
adds r0, r6, r0\n\
lsls r0, 16\n\
lsrs r6, r0, 16\n\
_0804AE10:\n\
adds r5, 0x1\n\
cmp r5, 0x5\n\
ble _0804ADBA\n\
ldr r2, =gBattleOutcome\n\
cmp r6, 0\n\
bne _0804AE24\n\
ldrb r0, [r2]\n\
movs r1, 0x1\n\
orrs r0, r1\n\
strb r0, [r2]\n\
_0804AE24:\n\
ldrb r0, [r2]\n\
cmp r0, 0\n\
bne _0804AF1A\n\
ldr r0, =gBattleTypeFlags\n\
ldr r1, [r0]\n\
ldr r2, =0x02000002\n\
ands r1, r2\n\
mov r8, r0\n\
cmp r1, 0\n\
beq _0804AF1A\n\
movs r3, 0\n\
movs r5, 0\n\
ldr r0, =gNoOfAllBanks\n\
ldrb r1, [r0]\n\
mov r12, r0\n\
ldr r7, =gBattlescriptCurrInstr\n\
cmp r3, r1\n\
bge _0804AE70\n\
ldr r0, =gHitMarker\n\
movs r6, 0x80\n\
lsls r6, 21\n\
ldr r4, [r0]\n\
adds r2, r1, 0\n\
ldr r1, =gSpecialStatuses\n\
_0804AE54:\n\
adds r0, r6, 0\n\
lsls r0, r5\n\
ands r0, r4\n\
cmp r0, 0\n\
beq _0804AE68\n\
ldrb r0, [r1]\n\
lsls r0, 25\n\
cmp r0, 0\n\
blt _0804AE68\n\
adds r3, 0x1\n\
_0804AE68:\n\
adds r1, 0x28\n\
adds r5, 0x2\n\
cmp r5, r2\n\
blt _0804AE54\n\
_0804AE70:\n\
movs r2, 0\n\
movs r5, 0x1\n\
mov r4, r12\n\
ldrb r1, [r4]\n\
cmp r5, r1\n\
bge _0804AEAA\n\
ldr r0, =gHitMarker\n\
movs r4, 0x80\n\
lsls r4, 21\n\
mov r12, r4\n\
ldr r6, [r0]\n\
ldr r0, =gSpecialStatuses\n\
adds r4, r1, 0\n\
adds r1, r0, 0\n\
adds r1, 0x14\n\
_0804AE8E:\n\
mov r0, r12\n\
lsls r0, r5\n\
ands r0, r6\n\
cmp r0, 0\n\
beq _0804AEA2\n\
ldrb r0, [r1]\n\
lsls r0, 25\n\
cmp r0, 0\n\
blt _0804AEA2\n\
adds r2, 0x1\n\
_0804AEA2:\n\
adds r1, 0x28\n\
adds r5, 0x2\n\
cmp r5, r4\n\
blt _0804AE8E\n\
_0804AEAA:\n\
mov r1, r8\n\
ldr r0, [r1]\n\
movs r1, 0x40\n\
ands r0, r1\n\
cmp r0, 0\n\
beq _0804AEF0\n\
adds r0, r2, r3\n\
cmp r0, 0x1\n\
bgt _0804AEF8\n\
b _0804AF12\n\
.pool\n\
_0804AEF0:\n\
cmp r2, 0\n\
beq _0804AF12\n\
cmp r3, 0\n\
beq _0804AF12\n\
_0804AEF8:\n\
ldr r2, [r7]\n\
ldrb r1, [r2, 0x1]\n\
ldrb r0, [r2, 0x2]\n\
lsls r0, 8\n\
adds r1, r0\n\
ldrb r0, [r2, 0x3]\n\
lsls r0, 16\n\
adds r1, r0\n\
ldrb r0, [r2, 0x4]\n\
lsls r0, 24\n\
adds r1, r0\n\
str r1, [r7]\n\
b _0804AF22\n\
_0804AF12:\n\
ldr r0, [r7]\n\
adds r0, 0x5\n\
str r0, [r7]\n\
b _0804AF22\n\
_0804AF1A:\n\
ldr r1, =gBattlescriptCurrInstr\n\
ldr r0, [r1]\n\
adds r0, 0x5\n\
str r0, [r1]\n\
_0804AF22:\n\
pop {r3}\n\
mov r8, r3\n\
pop {r4-r7}\n\
pop {r0}\n\
bx r0\n\
.pool\n\
.syntax divided");
}
#endif // NONMATCHING
2017-09-28 15:34:21 +02:00
static void MoveValuesCleanUp(void)
2017-09-22 21:33:49 +02:00
{
gBattleMoveFlags = 0;
gBattleScripting.dmgMultiplier = 1;
gCritMultiplier = 1;
gBattleCommunication[MOVE_EFFECT_BYTE] = 0;
gBattleCommunication[6] = 0;
gHitMarker &= ~(HITMARKER_DESTINYBOND);
gHitMarker &= ~(HITMARKER_SYNCHRONISE_EFFECT);
}
static void atk25_movevaluescleanup(void)
2017-09-22 21:33:49 +02:00
{
MoveValuesCleanUp();
gBattlescriptCurrInstr += 1;
}
static void atk26_setmultihit(void)
2017-09-22 21:33:49 +02:00
{
2017-09-28 15:34:21 +02:00
gMultiHitCounter = gBattlescriptCurrInstr[1];
2017-09-22 21:33:49 +02:00
gBattlescriptCurrInstr += 2;
}
static void atk27_decrementmultihit(void)
2017-09-22 21:33:49 +02:00
{
if (--gMultiHitCounter == 0)
gBattlescriptCurrInstr += 5;
else
gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
}
2017-09-28 15:34:21 +02:00
static void atk28_goto(void)
2017-09-22 21:33:49 +02:00
{
gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
}
2017-09-28 15:34:21 +02:00
static void atk29_jumpifbyte(void)
2017-09-22 21:33:49 +02:00
{
2017-09-28 15:34:21 +02:00
u8 caseID = gBattlescriptCurrInstr[1];
2017-09-22 21:33:49 +02:00
const u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 2);
2017-09-28 15:34:21 +02:00
u8 value = gBattlescriptCurrInstr[6];
2017-09-22 21:33:49 +02:00
const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 7);
gBattlescriptCurrInstr += 11;
switch (caseID)
{
case CMP_EQUAL:
if (*memByte == value)
gBattlescriptCurrInstr = jumpPtr;
break;
case CMP_NOT_EQUAL:
if (*memByte != value)
gBattlescriptCurrInstr = jumpPtr;
break;
case CMP_GREATER_THAN:
if (*memByte > value)
gBattlescriptCurrInstr = jumpPtr;
break;
case CMP_LESS_THAN:
if (*memByte < value)
gBattlescriptCurrInstr = jumpPtr;
break;
case CMP_COMMON_BITS:
if (*memByte & value)
gBattlescriptCurrInstr = jumpPtr;
break;
case CMP_NO_COMMON_BITS:
if (!(*memByte & value))
gBattlescriptCurrInstr = jumpPtr;
break;
}
}
2017-09-28 15:34:21 +02:00
static void atk2A_jumpifhalfword(void)
2017-09-22 21:33:49 +02:00
{
2017-09-28 15:34:21 +02:00
u8 caseID = gBattlescriptCurrInstr[1];
2017-09-22 21:33:49 +02:00
const u16* memHword = BS2ScriptReadPtr(gBattlescriptCurrInstr + 2);
u16 value = BS2ScriptRead16(gBattlescriptCurrInstr + 6);
const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 8);
gBattlescriptCurrInstr += 12;
switch (caseID)
{
case CMP_EQUAL:
if (*memHword == value)
gBattlescriptCurrInstr = jumpPtr;
break;
case CMP_NOT_EQUAL:
if (*memHword != value)
gBattlescriptCurrInstr = jumpPtr;
break;
case CMP_GREATER_THAN:
if (*memHword > value)
gBattlescriptCurrInstr = jumpPtr;
break;
case CMP_LESS_THAN:
if (*memHword < value)
gBattlescriptCurrInstr = jumpPtr;
break;
case CMP_COMMON_BITS:
if (*memHword & value)
gBattlescriptCurrInstr = jumpPtr;
break;
case CMP_NO_COMMON_BITS:
if (!(*memHword & value))
gBattlescriptCurrInstr = jumpPtr;
break;
}
}
2017-09-28 15:34:21 +02:00
static void atk2B_jumpifword(void)
2017-09-22 21:33:49 +02:00
{
2017-09-28 15:34:21 +02:00
u8 caseID = gBattlescriptCurrInstr[1];
2017-09-22 21:33:49 +02:00
const u32* memWord = BS2ScriptReadPtr(gBattlescriptCurrInstr + 2);
u32 value = BSScriptRead32(gBattlescriptCurrInstr + 6);
const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 10);
gBattlescriptCurrInstr += 14;
switch (caseID)
{
case CMP_EQUAL:
if (*memWord == value)
gBattlescriptCurrInstr = jumpPtr;
break;
case CMP_NOT_EQUAL:
if (*memWord != value)
gBattlescriptCurrInstr = jumpPtr;
break;
case CMP_GREATER_THAN:
if (*memWord > value)
gBattlescriptCurrInstr = jumpPtr;
break;
case CMP_LESS_THAN:
if (*memWord < value)
gBattlescriptCurrInstr = jumpPtr;
break;
case CMP_COMMON_BITS:
if (*memWord & value)
gBattlescriptCurrInstr = jumpPtr;
break;
case CMP_NO_COMMON_BITS:
if (!(*memWord & value))
gBattlescriptCurrInstr = jumpPtr;
break;
}
}
2017-09-28 15:34:21 +02:00
static void atk2C_jumpifarrayequal(void)
2017-09-22 21:33:49 +02:00
{
const u8* mem1 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
const u8* mem2 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5);
2017-09-28 15:34:21 +02:00
u32 size = gBattlescriptCurrInstr[9];
2017-09-22 21:33:49 +02:00
const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 10);
u8 i;
for (i = 0; i < size; i++)
{
if (*mem1 != *mem2)
{
gBattlescriptCurrInstr += 14;
break;
}
mem1++, mem2++;
}
if (i == size)
gBattlescriptCurrInstr = jumpPtr;
}
2017-09-28 15:34:21 +02:00
static void atk2D_jumpifarraynotequal(void)
2017-09-22 21:33:49 +02:00
{
u8 equalBytes = 0;
const u8* mem1 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
const u8* mem2 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5);
2017-09-28 15:34:21 +02:00
u32 size = gBattlescriptCurrInstr[9];
2017-09-22 21:33:49 +02:00
const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 10);
u8 i;
for (i = 0; i < size; i++)
{
if (*mem1 == *mem2)
{
equalBytes++;
}
mem1++, mem2++;
}
if (equalBytes != size)
gBattlescriptCurrInstr = jumpPtr;
else
gBattlescriptCurrInstr += 14;
}
2017-09-28 15:34:21 +02:00
static void atk2E_setbyte(void)
2017-09-22 21:33:49 +02:00
{
u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
2017-09-28 15:34:21 +02:00
*memByte = gBattlescriptCurrInstr[5];
2017-09-22 21:33:49 +02:00
gBattlescriptCurrInstr += 6;
}
2017-09-28 15:34:21 +02:00
static void atk2F_addbyte(void)
2017-09-22 21:33:49 +02:00
{
u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
2017-09-28 15:34:21 +02:00
*memByte += gBattlescriptCurrInstr[5];
2017-09-22 21:33:49 +02:00
gBattlescriptCurrInstr += 6;
}
2017-09-28 15:34:21 +02:00
static void atk30_subbyte(void)
2017-09-22 21:33:49 +02:00
{
u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
2017-09-28 15:34:21 +02:00
*memByte -= gBattlescriptCurrInstr[5];
2017-09-22 21:33:49 +02:00
gBattlescriptCurrInstr += 6;
}
2017-09-28 15:34:21 +02:00
static void atk31_copyarray(void)
2017-09-22 21:33:49 +02:00
{
u8* dest = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
const u8* src = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5);
2017-09-28 15:34:21 +02:00
s32 size = gBattlescriptCurrInstr[9];
2017-09-22 21:33:49 +02:00
s32 i;
for (i = 0; i < size; i++)
{
dest[i] = src[i];
}
gBattlescriptCurrInstr += 10;
}
static void atk32_copyarraywithindex(void)
2017-09-22 21:33:49 +02:00
{
u8* dest = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
const u8* src = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5);
const u8* index = BS2ScriptReadPtr(gBattlescriptCurrInstr + 9);
2017-09-28 15:34:21 +02:00
s32 size = gBattlescriptCurrInstr[13];
2017-09-22 21:33:49 +02:00
s32 i;
for (i = 0; i < size; i++)
{
dest[i] = src[i + *index];
}
gBattlescriptCurrInstr += 14;
}
2017-09-28 15:34:21 +02:00
static void atk33_orbyte(void)
2017-09-22 21:33:49 +02:00
{
u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
2017-09-28 15:34:21 +02:00
*memByte |= gBattlescriptCurrInstr[5];
2017-09-22 21:33:49 +02:00
gBattlescriptCurrInstr += 6;
}
2017-09-28 15:34:21 +02:00
static void atk34_orhalfword(void)
2017-09-22 21:33:49 +02:00
{
u16* memHword = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
u16 val = BS2ScriptRead16(gBattlescriptCurrInstr + 5);
*memHword |= val;
gBattlescriptCurrInstr += 7;
}
2017-09-28 15:34:21 +02:00
static void atk35_orword(void)
2017-09-22 21:33:49 +02:00
{
u32* memWord = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
u32 val = BS2ScriptRead32(gBattlescriptCurrInstr + 5);
*memWord |= val;
gBattlescriptCurrInstr += 9;
}
2017-09-28 15:34:21 +02:00
static void atk36_bicbyte(void)
2017-09-22 21:33:49 +02:00
{
u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
2017-09-28 15:34:21 +02:00
*memByte &= ~(gBattlescriptCurrInstr[5]);
2017-09-22 21:33:49 +02:00
gBattlescriptCurrInstr += 6;
}
2017-09-28 15:34:21 +02:00
static void atk37_bichalfword(void)
2017-09-22 21:33:49 +02:00
{
u16* memHword = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
u16 val = BS2ScriptRead16(gBattlescriptCurrInstr + 5);
*memHword &= ~val;
gBattlescriptCurrInstr += 7;
}
2017-09-28 15:34:21 +02:00
static void atk38_bicword(void)
2017-09-22 21:33:49 +02:00
{
u32* memWord = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
u32 val = BS2ScriptRead32(gBattlescriptCurrInstr + 5);
*memWord &= ~val;
gBattlescriptCurrInstr += 9;
}
2017-09-28 15:34:21 +02:00
static void atk39_pause(void)
2017-09-22 21:33:49 +02:00
{
if (gBattleExecBuffer == 0)
{
u16 value = BS2ScriptRead16(gBattlescriptCurrInstr + 1);
if (++gPauseCounterBattle >= value)
{
gPauseCounterBattle = 0;
gBattlescriptCurrInstr += 3;
}
}
}
2017-09-28 15:34:21 +02:00
static void atk3A_waitstate(void)
2017-09-22 21:33:49 +02:00
{
if (gBattleExecBuffer == 0)
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atk3B_healthbar_update(void)
2017-09-22 21:33:49 +02:00
{
2017-09-28 15:34:21 +02:00
if (gBattlescriptCurrInstr[1] == BS_GET_TARGET)
2017-09-22 21:33:49 +02:00
gActiveBank = gBankTarget;
else
gActiveBank = gBankAttacker;
EmitHealthBarUpdate(0, gBattleMoveDamage);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 2;
}
2017-09-28 15:34:21 +02:00
static void atk3C_return(void)
2017-09-22 21:33:49 +02:00
{
BattleScriptPop();
}
2017-09-28 15:34:21 +02:00
static void atk3D_end(void)
2017-09-22 21:33:49 +02:00
{
if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
sub_81A5718(gBankAttacker);
gBattleMoveFlags = 0;
gActiveBank = 0;
2017-10-06 00:12:01 +02:00
gCurrentActionFuncId = 0xB;
2017-09-22 21:33:49 +02:00
}
2017-09-28 15:34:21 +02:00
static void atk3E_end2(void)
2017-09-22 21:33:49 +02:00
{
gActiveBank = 0;
2017-10-06 00:12:01 +02:00
gCurrentActionFuncId = 0xB;
2017-09-22 21:33:49 +02:00
}
2017-09-28 15:34:21 +02:00
static void atk3F_end3(void) // pops the main function stack
2017-09-22 21:33:49 +02:00
{
BattleScriptPop();
if (BATTLE_CALLBACKS_STACK->size)
BATTLE_CALLBACKS_STACK->size--;
gBattleMainFunc = BATTLE_CALLBACKS_STACK->function[BATTLE_CALLBACKS_STACK->size];
}
2017-09-28 15:34:21 +02:00
static void atk41_call(void)
2017-09-22 21:33:49 +02:00
{
BattleScriptPush(gBattlescriptCurrInstr + 5);
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
2017-09-28 15:34:21 +02:00
static void atk42_jumpiftype2(void)
2017-09-22 21:33:49 +02:00
{
2017-09-28 15:34:21 +02:00
u8 bank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-22 21:33:49 +02:00
2017-09-28 15:34:21 +02:00
if (gBattlescriptCurrInstr[2] == gBattleMons[bank].type1 || gBattlescriptCurrInstr[2] == gBattleMons[bank].type2)
2017-09-22 21:33:49 +02:00
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 3);
else
gBattlescriptCurrInstr += 7;
}
2017-09-28 15:34:21 +02:00
static void atk43_jumpifabilitypresent(void)
2017-09-22 21:33:49 +02:00
{
2017-09-28 15:34:21 +02:00
if (AbilityBattleEffects(ABILITYEFFECT_CHECK_ON_FIELD, 0, gBattlescriptCurrInstr[1], 0, 0))
2017-09-22 21:33:49 +02:00
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
else
gBattlescriptCurrInstr += 6;
}
static void atk44_endselectionscript(void)
2017-09-22 21:33:49 +02:00
{
2017-10-04 19:25:14 +02:00
*(gBankAttacker + gBattleStruct->selectionScriptFinished) = TRUE;
2017-09-22 21:33:49 +02:00
}
2017-09-28 15:34:21 +02:00
static void atk45_playanimation(void)
2017-09-22 21:33:49 +02:00
{
const u16* argumentPtr;
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-22 21:33:49 +02:00
argumentPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 3);
if (gBattlescriptCurrInstr[2] == B_ANIM_STATS_CHANGE
|| gBattlescriptCurrInstr[2] == B_ANIM_SNATCH_MOVE
|| gBattlescriptCurrInstr[2] == B_ANIM_SUBSTITUTE_FADE)
{
EmitBattleAnimation(0, gBattlescriptCurrInstr[2], *argumentPtr);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 7;
}
else if (gHitMarker & HITMARKER_NO_ANIMATIONS)
{
BattleScriptPush(gBattlescriptCurrInstr + 7);
gBattlescriptCurrInstr = BattleScript_Pausex20;
}
else if (gBattlescriptCurrInstr[2] == B_ANIM_RAIN_CONTINUES
|| gBattlescriptCurrInstr[2] == B_ANIM_SUN_CONTINUES
|| gBattlescriptCurrInstr[2] == B_ANIM_SANDSTORM_CONTINUES
|| gBattlescriptCurrInstr[2] == B_ANIM_HAIL_CONTINUES)
{
EmitBattleAnimation(0, gBattlescriptCurrInstr[2], *argumentPtr);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 7;
}
else if (gStatuses3[gActiveBank] & STATUS3_SEMI_INVULNERABLE)
{
gBattlescriptCurrInstr += 7;
}
else
{
EmitBattleAnimation(0, gBattlescriptCurrInstr[2], *argumentPtr);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 7;
}
}
2017-09-28 15:34:21 +02:00
static void atk46_playanimation2(void) // animation Id is stored in the first pointer
2017-09-22 21:33:49 +02:00
{
const u16* argumentPtr;
const u8* animationIdPtr;
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-22 21:33:49 +02:00
animationIdPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 2);
argumentPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 6);
if (*animationIdPtr == B_ANIM_STATS_CHANGE
|| *animationIdPtr == B_ANIM_SNATCH_MOVE
|| *animationIdPtr == B_ANIM_SUBSTITUTE_FADE)
{
EmitBattleAnimation(0, *animationIdPtr, *argumentPtr);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 10;
}
else if (gHitMarker & HITMARKER_NO_ANIMATIONS)
{
gBattlescriptCurrInstr += 10;
}
else if (*animationIdPtr == B_ANIM_RAIN_CONTINUES
|| *animationIdPtr == B_ANIM_SUN_CONTINUES
|| *animationIdPtr == B_ANIM_SANDSTORM_CONTINUES
|| *animationIdPtr == B_ANIM_HAIL_CONTINUES)
{
EmitBattleAnimation(0, *animationIdPtr, *argumentPtr);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 10;
}
else if (gStatuses3[gActiveBank] & STATUS3_SEMI_INVULNERABLE)
{
gBattlescriptCurrInstr += 10;
}
else
{
EmitBattleAnimation(0, *animationIdPtr, *argumentPtr);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 10;
}
}
2017-09-28 15:34:21 +02:00
static void atk47_setgraphicalstatchangevalues(void)
2017-09-22 21:33:49 +02:00
{
u8 value = 0;
switch (gBattleScripting.statChanger & 0xF0)
{
case 0x10: // +1
value = 0xF;
break;
case 0x20: // +2
value = 0x27;
break;
case 0x90: // -1
value = 0x16;
break;
case 0xA0: // -2
value = 0x2E;
break;
}
gBattleScripting.animArg1 = (gBattleScripting.statChanger & 0xF) + value - 1;
gBattleScripting.animArg2 = 0;
gBattlescriptCurrInstr++;
}
2017-09-23 20:13:45 +02:00
#ifdef NONMATCHING
2017-09-28 15:34:21 +02:00
static void atk48_playstatchangeanimation(void)
2017-09-22 21:33:49 +02:00
{
2017-09-23 00:06:52 +02:00
u32 currStat = 0;
2017-09-22 21:33:49 +02:00
s16 statAnimId = 0;
2017-09-23 00:06:52 +02:00
s16 checkingStatAnimId = 0;
2017-09-22 21:33:49 +02:00
s32 changeableStats = 0;
u32 statsToCheck = 0;
2017-09-23 00:06:52 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
statsToCheck = gBattlescriptCurrInstr[2];
2017-09-22 21:33:49 +02:00
2017-09-23 00:06:52 +02:00
if (gBattlescriptCurrInstr[3] & ATK48_STAT_NEGATIVE) // goes down
2017-09-22 21:33:49 +02:00
{
2017-09-23 00:06:52 +02:00
checkingStatAnimId = (gBattlescriptCurrInstr[3] & ATK48_STAT_BY_TWO) ? 0x2D : 0x15;
while (statsToCheck != 0)
2017-09-22 21:33:49 +02:00
{
2017-09-23 00:06:52 +02:00
if (statsToCheck & 1)
2017-09-22 21:33:49 +02:00
{
2017-09-23 00:06:52 +02:00
if (!(gBattlescriptCurrInstr[3] & ATK48_LOWER_FAIL_CHECK))
2017-09-22 21:33:49 +02:00
{
2017-09-23 00:06:52 +02:00
if (gBattleMons[gActiveBank].statStages[currStat] > 0)
{
statAnimId = checkingStatAnimId;
changeableStats++;
}
2017-09-22 21:33:49 +02:00
}
2017-09-23 00:06:52 +02:00
else if (!gSideTimers[GET_BANK_SIDE(gActiveBank)].mistTimer
&& gBattleMons[gActiveBank].ability != ABILITY_CLEAR_BODY
&& gBattleMons[gActiveBank].ability != ABILITY_WHITE_SMOKE
&& !(gBattleMons[gActiveBank].ability == ABILITY_KEEN_EYE && currStat == STAT_STAGE_ACC)
&& !(gBattleMons[gActiveBank].ability == ABILITY_HYPER_CUTTER && currStat == STAT_STAGE_ATK))
2017-09-22 21:33:49 +02:00
{
2017-09-23 00:06:52 +02:00
if (gBattleMons[gActiveBank].statStages[currStat] > 0)
{
statAnimId = checkingStatAnimId;
changeableStats++;
}
2017-09-22 21:33:49 +02:00
}
}
2017-09-23 00:06:52 +02:00
statsToCheck >>= 1, checkingStatAnimId++, currStat++;
2017-09-22 21:33:49 +02:00
}
if (changeableStats > 1) // more than one stat, so the color is gray
{
2017-09-23 00:06:52 +02:00
if (gBattlescriptCurrInstr[3] & ATK48_STAT_BY_TWO)
2017-09-22 21:33:49 +02:00
statAnimId = 0x3A;
else
statAnimId = 0x39;
}
}
else // goes up
{
2017-09-23 00:06:52 +02:00
checkingStatAnimId = (gBattlescriptCurrInstr[3] & ATK48_STAT_BY_TWO) ? 0x26 : 0xE;
while (statsToCheck != 0)
2017-09-22 21:33:49 +02:00
{
if (statsToCheck & 1 && gBattleMons[gActiveBank].statStages[currStat] < 0xC)
{
statAnimId = checkingStatAnimId;
changeableStats++;
}
2017-09-23 00:06:52 +02:00
statsToCheck >>= 1, checkingStatAnimId += 1, currStat++;
2017-09-22 21:33:49 +02:00
}
if (changeableStats > 1) // more than one stat, so the color is gray
{
2017-09-23 00:06:52 +02:00
if (gBattlescriptCurrInstr[3] & ATK48_STAT_BY_TWO)
2017-09-22 21:33:49 +02:00
statAnimId = 0x38;
else
statAnimId = 0x37;
}
}
2017-09-23 00:06:52 +02:00
if (gBattlescriptCurrInstr[3] & ATK48_BIT_x4 && changeableStats < 2)
2017-09-22 21:33:49 +02:00
{
gBattlescriptCurrInstr += 4;
}
else if (changeableStats != 0 && gBattleScripting.field_1B == 0)
{
EmitBattleAnimation(0, B_ANIM_STATS_CHANGE, statAnimId);
MarkBufferBankForExecution(gActiveBank);
2017-09-23 00:06:52 +02:00
if (gBattlescriptCurrInstr[3] & ATK48_BIT_x4 && changeableStats > 1)
2017-09-22 21:33:49 +02:00
gBattleScripting.field_1B = 1;
gBattlescriptCurrInstr += 4;
}
else
{
gBattlescriptCurrInstr += 4;
}
}
2017-09-23 20:13:45 +02:00
#else
__attribute__((naked))
2017-09-28 15:34:21 +02:00
static void atk48_playstatchangeanimation(void)
2017-09-23 20:13:45 +02:00
{
asm("\n\
.syntax unified\n\
push {r4-r7,lr}\n\
mov r7, r10\n\
mov r6, r9\n\
mov r5, r8\n\
push {r5-r7}\n\
sub sp, 0x4\n\
movs r7, 0\n\
movs r0, 0\n\
mov r8, r0\n\
movs r3, 0\n\
ldr r5, =gBattlescriptCurrInstr\n\
ldr r0, [r5]\n\
ldrb r0, [r0, 0x1]\n\
str r3, [sp]\n\
bl GetBattleBank\n\
ldr r2, =gActiveBank\n\
strb r0, [r2]\n\
ldr r0, [r5]\n\
ldrb r4, [r0, 0x2]\n\
ldrb r1, [r0, 0x3]\n\
movs r0, 0x1\n\
ands r0, r1\n\
ldr r3, [sp]\n\
cmp r0, 0\n\
beq _0804BAEC\n\
movs r0, 0x2\n\
ands r0, r1\n\
movs r1, 0x15\n\
cmp r0, 0\n\
beq _0804BA18\n\
movs r1, 0x2D\n\
_0804BA18:\n\
cmp r4, 0\n\
beq _0804BAC0\n\
movs r0, 0x1\n\
mov r10, r0\n\
ldr r0, =gBattleMons + 0x18\n\
mov r9, r0\n\
lsls r5, r1, 16\n\
_0804BA26:\n\
adds r0, r4, 0\n\
mov r1, r10\n\
ands r0, r1\n\
cmp r0, 0\n\
beq _0804BAB2\n\
ldr r0, =gBattlescriptCurrInstr\n\
ldr r0, [r0]\n\
ldrb r1, [r0, 0x3]\n\
movs r0, 0x8\n\
ands r0, r1\n\
cmp r0, 0\n\
beq _0804BA58\n\
ldr r0, =gActiveBank\n\
ldrb r1, [r0]\n\
movs r0, 0x58\n\
muls r0, r1\n\
adds r0, r7, r0\n\
b _0804BAA0\n\
.pool\n\
_0804BA58:\n\
ldr r6, =gActiveBank\n\
ldrb r0, [r6]\n\
str r3, [sp]\n\
bl GetBankIdentity\n\
mov r1, r10\n\
ands r1, r0\n\
lsls r0, r1, 1\n\
adds r0, r1\n\
lsls r0, 2\n\
ldr r1, =gSideTimers\n\
adds r0, r1\n\
ldrb r0, [r0, 0x4]\n\
ldr r3, [sp]\n\
cmp r0, 0\n\
bne _0804BAB2\n\
ldr r0, =gBattleMons\n\
ldrb r2, [r6]\n\
movs r1, 0x58\n\
muls r2, r1\n\
adds r0, r2, r0\n\
adds r0, 0x20\n\
ldrb r0, [r0]\n\
cmp r0, 0x1D\n\
beq _0804BAB2\n\
cmp r0, 0x49\n\
beq _0804BAB2\n\
cmp r0, 0x33\n\
bne _0804BA96\n\
cmp r7, 0x6\n\
beq _0804BAB2\n\
_0804BA96:\n\
cmp r0, 0x34\n\
bne _0804BA9E\n\
cmp r7, 0x1\n\
beq _0804BAB2\n\
_0804BA9E:\n\
adds r0, r7, r2\n\
_0804BAA0:\n\
add r0, r9\n\
ldrb r0, [r0]\n\
lsls r0, 24\n\
asrs r0, 24\n\
cmp r0, 0\n\
ble _0804BAB2\n\
lsrs r0, r5, 16\n\
mov r8, r0\n\
adds r3, 0x1\n\
_0804BAB2:\n\
lsrs r4, 1\n\
movs r1, 0x80\n\
lsls r1, 9\n\
adds r5, r1\n\
adds r7, 0x1\n\
cmp r4, 0\n\
bne _0804BA26\n\
_0804BAC0:\n\
ldr r0, =gBattlescriptCurrInstr\n\
mov r9, r0\n\
cmp r3, 0x1\n\
ble _0804BB4E\n\
ldr r0, [r0]\n\
ldrb r1, [r0, 0x3]\n\
movs r0, 0x2\n\
ands r0, r1\n\
movs r1, 0x39\n\
mov r8, r1\n\
cmp r0, 0\n\
beq _0804BB4E\n\
movs r0, 0x3A\n\
b _0804BB4C\n\
.pool\n\
_0804BAEC:\n\
movs r0, 0x2\n\
ands r0, r1\n\
movs r1, 0xE\n\
cmp r0, 0\n\
beq _0804BAF8\n\
movs r1, 0x26\n\
_0804BAF8:\n\
mov r9, r5\n\
cmp r4, 0\n\
beq _0804BB34\n\
ldr r6, =gBattleMons + 0x18\n\
adds r5, r2, 0\n\
lsls r2, r1, 16\n\
_0804BB04:\n\
movs r0, 0x1\n\
ands r0, r4\n\
cmp r0, 0\n\
beq _0804BB26\n\
ldrb r1, [r5]\n\
movs r0, 0x58\n\
muls r0, r1\n\
adds r0, r7, r0\n\
adds r0, r6\n\
ldrb r0, [r0]\n\
lsls r0, 24\n\
asrs r0, 24\n\
cmp r0, 0xB\n\
bgt _0804BB26\n\
lsrs r1, r2, 16\n\
mov r8, r1\n\
adds r3, 0x1\n\
_0804BB26:\n\
lsrs r4, 1\n\
movs r0, 0x80\n\
lsls r0, 9\n\
adds r2, r0\n\
adds r7, 0x1\n\
cmp r4, 0\n\
bne _0804BB04\n\
_0804BB34:\n\
cmp r3, 0x1\n\
ble _0804BB4E\n\
mov r1, r9\n\
ldr r0, [r1]\n\
ldrb r1, [r0, 0x3]\n\
movs r0, 0x2\n\
ands r0, r1\n\
movs r1, 0x37\n\
mov r8, r1\n\
cmp r0, 0\n\
beq _0804BB4E\n\
movs r0, 0x38\n\
_0804BB4C:\n\
mov r8, r0\n\
_0804BB4E:\n\
mov r1, r9\n\
ldr r2, [r1]\n\
ldrb r1, [r2, 0x3]\n\
movs r0, 0x4\n\
ands r0, r1\n\
cmp r0, 0\n\
beq _0804BB6C\n\
cmp r3, 0x1\n\
bgt _0804BB6C\n\
adds r0, r2, 0x4\n\
mov r1, r9\n\
b _0804BBBA\n\
.pool\n\
_0804BB6C:\n\
cmp r3, 0\n\
beq _0804BBB4\n\
ldr r4, =gBattleScripting\n\
ldrb r0, [r4, 0x1B]\n\
cmp r0, 0\n\
bne _0804BBB4\n\
movs r0, 0\n\
movs r1, 0x1\n\
mov r2, r8\n\
str r3, [sp]\n\
bl EmitBattleAnimation\n\
ldr r0, =gActiveBank\n\
ldrb r0, [r0]\n\
bl MarkBufferBankForExecution\n\
ldr r0, =gBattlescriptCurrInstr\n\
ldr r0, [r0]\n\
ldrb r1, [r0, 0x3]\n\
movs r0, 0x4\n\
ands r0, r1\n\
ldr r3, [sp]\n\
cmp r0, 0\n\
beq _0804BBA4\n\
cmp r3, 0x1\n\
ble _0804BBA4\n\
movs r0, 0x1\n\
strb r0, [r4, 0x1B]\n\
_0804BBA4:\n\
ldr r1, =gBattlescriptCurrInstr\n\
b _0804BBB6\n\
.pool\n\
_0804BBB4:\n\
mov r1, r9\n\
_0804BBB6:\n\
ldr r0, [r1]\n\
adds r0, 0x4\n\
_0804BBBA:\n\
str r0, [r1]\n\
add sp, 0x4\n\
pop {r3-r5}\n\
mov r8, r3\n\
mov r9, r4\n\
mov r10, r5\n\
pop {r4-r7}\n\
pop {r0}\n\
bx r0\n\
.syntax divided");
}
#endif // NONMATCHING
#define ATK49_LAST_CASE 17
2017-09-28 15:34:21 +02:00
static void atk49_moveend(void)
2017-09-23 20:13:45 +02:00
{
s32 i;
bool32 effect;
u8 moveType;
u8 holdEffectAtk;
u16 *choicedMoveAtk;
u8 arg1, arg2;
u16 lastMove;
effect = FALSE;
if (gLastUsedMove == 0xFFFF)
lastMove = 0;
else
lastMove = gLastUsedMove;
arg1 = gBattlescriptCurrInstr[1];
arg2 = gBattlescriptCurrInstr[2];
if (gBattleMons[gBankAttacker].item == ITEM_ENIGMA_BERRY)
holdEffectAtk = gEnigmaBerries[gBankAttacker].holdEffect;
else
holdEffectAtk = ItemId_GetHoldEffect(gBattleMons[gBankAttacker].item);
choicedMoveAtk = &gBattleStruct->choicedMove[gBankAttacker];
GET_MOVE_TYPE(gCurrentMove, moveType);
do
{
switch (gBattleScripting.atk49_state)
{
case 0: // rage check
if (gBattleMons[gBankTarget].status2 & STATUS2_RAGE
&& gBattleMons[gBankTarget].hp != 0 && gBankAttacker != gBankTarget
&& GetBankSide(gBankAttacker) != GetBankSide(gBankTarget)
&& !(gBattleMoveFlags & MOVESTATUS_NOEFFECT) && TARGET_TURN_DAMAGED
&& gBattleMoves[gCurrentMove].power && gBattleMons[gBankTarget].statStages[STAT_STAGE_ATK] <= 0xB)
{
gBattleMons[gBankTarget].statStages[STAT_STAGE_ATK]++;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_RageIsBuilding;
effect = TRUE;
}
gBattleScripting.atk49_state++;
break;
case 1: // defrosting check
if (gBattleMons[gBankTarget].status1 & STATUS_FREEZE
&& gBattleMons[gBankTarget].hp != 0 && gBankAttacker != gBankTarget
&& gSpecialStatuses[gBankTarget].moveturnLostHP_special
&& !(gBattleMoveFlags & MOVESTATUS_NOEFFECT) && moveType == TYPE_FIRE)
{
gBattleMons[gBankTarget].status1 &= ~(STATUS_FREEZE);
gActiveBank = gBankTarget;
2017-09-26 22:39:59 +02:00
EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gBankTarget].status1);
2017-09-23 20:13:45 +02:00
MarkBufferBankForExecution(gActiveBank);
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_DefrostedViaFireMove;
effect = TRUE;
}
gBattleScripting.atk49_state++;
break;
case 2: // target synchronize
if (AbilityBattleEffects(ABILITYEFFECT_SYNCHRONIZE, gBankTarget, 0, 0, 0))
effect = TRUE;
gBattleScripting.atk49_state++;
break;
case 3: // contact abilities
if (AbilityBattleEffects(ABILITYEFFECT_CONTACT, gBankTarget, 0, 0, 0))
effect = TRUE;
gBattleScripting.atk49_state++;
break;
case 4: // status immunities
if (AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, 0, 0, 0, 0))
effect = TRUE; // it loops through all banks, so we increment after its done with all banks
else
gBattleScripting.atk49_state++;
break;
case 5: // attacker synchronize
if (AbilityBattleEffects(ABILITYEFFECT_ATK_SYNCHRONIZE, gBankAttacker, 0, 0, 0))
effect = TRUE;
gBattleScripting.atk49_state++;
break;
case 6: // update choice band move
if (!(gHitMarker & HITMARKER_OBEYS) || holdEffectAtk != HOLD_EFFECT_CHOICE_BAND
|| gLastUsedMove == MOVE_STRUGGLE || (*choicedMoveAtk != 0 && *choicedMoveAtk != 0xFFFF))
goto LOOP;
if (gLastUsedMove == MOVE_BATON_PASS && !(gBattleMoveFlags & MOVESTATUS_FAILED))
{
gBattleScripting.atk49_state++;
break;
}
*choicedMoveAtk = gLastUsedMove;
LOOP:
{
for (i = 0; i < 4; i++)
{
if (gBattleMons[gBankAttacker].moves[i] == *choicedMoveAtk)
break;
}
if (i == 4)
*choicedMoveAtk = 0;
gBattleScripting.atk49_state++;
}
break;
case 7: // changed held items
for (i = 0; i < gNoOfAllBanks; i++)
{
2017-09-27 23:43:45 +02:00
u16* changedItem = &gBattleStruct->changedItems[i];
2017-09-23 20:13:45 +02:00
if (*changedItem != 0)
{
gBattleMons[i].item = *changedItem;
*changedItem = 0;
}
}
gBattleScripting.atk49_state++;
break;
case 11: // item effects for all banks
if (ItemBattleEffects(3, 0, FALSE))
effect = TRUE;
else
gBattleScripting.atk49_state++;
break;
case 12: // king's rock and shell bell
if (ItemBattleEffects(4, 0, FALSE))
effect = TRUE;
gBattleScripting.atk49_state++;
break;
case 8: // make attacker sprite invisible
if (gStatuses3[gBankAttacker] & (STATUS3_SEMI_INVULNERABLE)
&& gHitMarker & HITMARKER_NO_ANIMATIONS)
{
gActiveBank = gBankAttacker;
EmitSpriteInvisibility(0, TRUE);
MarkBufferBankForExecution(gActiveBank);
gBattleScripting.atk49_state++;
return;
}
gBattleScripting.atk49_state++;
break;
case 9: // make attacker sprite visible
if (gBattleMoveFlags & MOVESTATUS_NOEFFECT
|| !(gStatuses3[gBankAttacker] & (STATUS3_SEMI_INVULNERABLE))
2017-10-06 17:06:45 +02:00
|| WasUnableToUseMove(gBankAttacker))
2017-09-23 20:13:45 +02:00
{
gActiveBank = gBankAttacker;
EmitSpriteInvisibility(0, FALSE);
MarkBufferBankForExecution(gActiveBank);
gStatuses3[gBankAttacker] &= ~(STATUS3_SEMI_INVULNERABLE);
gSpecialStatuses[gBankAttacker].restoredBankSprite = 1;
gBattleScripting.atk49_state++;
return;
}
gBattleScripting.atk49_state++;
break;
case 10: // make target sprite visible
if (!gSpecialStatuses[gBankTarget].restoredBankSprite && gBankTarget < gNoOfAllBanks
&& !(gStatuses3[gBankTarget] & STATUS3_SEMI_INVULNERABLE))
{
gActiveBank = gBankTarget;
EmitSpriteInvisibility(0, FALSE);
MarkBufferBankForExecution(gActiveBank);
gStatuses3[gBankTarget] &= ~(STATUS3_SEMI_INVULNERABLE);
gBattleScripting.atk49_state++;
return;
}
gBattleScripting.atk49_state++;
break;
case 13: // update substitute
for (i = 0; i < gNoOfAllBanks; i++)
{
if (gDisableStructs[i].substituteHP == 0)
gBattleMons[i].status2 &= ~(STATUS2_SUBSTITUTE);
}
gBattleScripting.atk49_state++;
break;
case 14: // This case looks interesting, although I am not certain what it does. Probably fine tunes edge cases.
if (gHitMarker & HITMARKER_PURSUIT_TRAP)
{
gActiveBank = gBankAttacker;
gBankAttacker = gBankTarget;
gBankTarget = gActiveBank;
gHitMarker &= ~(HITMARKER_PURSUIT_TRAP);
}
if (gHitMarker & HITMARKER_ATTACKSTRING_PRINTED)
{
gUnknownMovesUsedByBanks[gBankAttacker] = gLastUsedMove;
}
if (!(gAbsentBankFlags & gBitTable[gBankAttacker])
&& !(gBattleStruct->field_91 & gBitTable[gBankAttacker])
&& gBattleMoves[lastMove].effect != EFFECT_BATON_PASS)
{
if (gHitMarker & HITMARKER_OBEYS)
{
gLastUsedMovesByBanks[gBankAttacker] = gLastUsedMove;
gUnknown_02024260[gBankAttacker] = gCurrentMove;
}
else
{
gLastUsedMovesByBanks[gBankAttacker] = 0xFFFF;
gUnknown_02024260[gBankAttacker] = 0xFFFF;
}
if (!(gHitMarker & HITMARKER_FAINTED(gBankTarget)))
gUnknown_02024270[gBankTarget] = gBankAttacker;
if (gHitMarker & HITMARKER_OBEYS && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
{
if (gLastUsedMove == 0xFFFF)
{
gUnknown_02024250[gBankTarget] = gLastUsedMove;
}
else
{
gUnknown_02024250[gBankTarget] = gCurrentMove;
GET_MOVE_TYPE(gCurrentMove, gUnknown_02024258[gBankTarget]);
}
}
else
{
gUnknown_02024250[gBankTarget] = 0xFFFF;
}
}
gBattleScripting.atk49_state++;
break;
case 15: // mirror move
if (!(gAbsentBankFlags & gBitTable[gBankAttacker]) && !(gBattleStruct->field_91 & gBitTable[gBankAttacker])
&& gBattleMoves[lastMove].flags & FLAG_MIRROR_MOVE_AFFECTED && gHitMarker & HITMARKER_OBEYS
&& gBankAttacker != gBankTarget && !(gHitMarker & HITMARKER_FAINTED(gBankTarget))
&& !(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
{
u8 target, attacker;
*(gBattleStruct->mirrorMoves + gBankTarget * 2 + 0) = gLastUsedMove;
*(gBattleStruct->mirrorMoves + gBankTarget * 2 + 1) = gLastUsedMove >> 8;
target = gBankTarget;
attacker = gBankAttacker;
*(attacker * 2 + target * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0) = gLastUsedMove;
target = gBankTarget;
attacker = gBankAttacker;
*(attacker * 2 + target * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 1) = gLastUsedMove >> 8;
}
gBattleScripting.atk49_state++;
break;
case 16: //
if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) && gBattleTypeFlags & BATTLE_TYPE_DOUBLE
&& !gProtectStructs[gBankAttacker].chargingTurn && gBattleMoves[gCurrentMove].target == MOVE_TARGET_BOTH
&& !(gHitMarker & HITMARKER_NO_ATTACKSTRING))
{
2017-09-26 22:39:59 +02:00
u8 bank = GetBankByIdentity(GetBankIdentity(gBankTarget) ^ BIT_MON);
2017-09-23 20:13:45 +02:00
if (gBattleMons[bank].hp != 0)
{
gBankTarget = bank;
gHitMarker |= HITMARKER_NO_ATTACKSTRING;
gBattleScripting.atk49_state = 0;
MoveValuesCleanUp();
BattleScriptPush(gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect]);
gBattlescriptCurrInstr = BattleScript_82DB87D;
2017-09-23 20:13:45 +02:00
return;
}
else
{
gHitMarker |= HITMARKER_NO_ATTACKSTRING;
}
}
gBattleScripting.atk49_state++;
break;
case ATK49_LAST_CASE:
break;
}
if (arg1 == 1 && effect == FALSE)
gBattleScripting.atk49_state = ATK49_LAST_CASE;
if (arg1 == 2 && arg2 == gBattleScripting.atk49_state)
gBattleScripting.atk49_state = ATK49_LAST_CASE;
} while (gBattleScripting.atk49_state != ATK49_LAST_CASE && effect == FALSE);
if (gBattleScripting.atk49_state == ATK49_LAST_CASE && effect == FALSE)
gBattlescriptCurrInstr += 3;
}
2017-09-28 15:34:21 +02:00
static void atk4A_typecalc2(void)
2017-09-24 00:29:52 +02:00
{
u8 flags = 0;
s32 i = 0;
u8 moveType = gBattleMoves[gCurrentMove].type;
if (gBattleMons[gBankTarget].ability == ABILITY_LEVITATE && moveType == TYPE_GROUND)
{
gLastUsedAbility = gBattleMons[gBankTarget].ability;
gBattleMoveFlags |= (MOVESTATUS_MISSED | MOVESTATUS_NOTAFFECTED);
gUnknown_02024250[gBankTarget] = 0;
gBattleCommunication[6] = moveType;
RecordAbilityBattle(gBankTarget, gLastUsedAbility);
}
else
{
while (TYPE_EFFECT_ATK_TYPE(i) != TYPE_ENDTABLE)
2017-09-24 00:29:52 +02:00
{
if (TYPE_EFFECT_ATK_TYPE(i) == TYPE_FORESIGHT)
2017-09-24 00:29:52 +02:00
{
if (gBattleMons[gBankTarget].status2 & STATUS2_FORESIGHT)
{
break;
}
else
{
i += 3;
continue;
}
}
if (TYPE_EFFECT_ATK_TYPE(i) == moveType)
2017-09-24 00:29:52 +02:00
{
// check type1
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBankTarget].type1)
2017-09-24 00:29:52 +02:00
{
if (TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_NO_EFFECT)
2017-09-24 00:29:52 +02:00
{
gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED;
break;
}
if (TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_NOT_EFFECTIVE)
2017-09-24 00:29:52 +02:00
{
flags |= MOVESTATUS_NOTVERYEFFECTIVE;
}
if (TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_SUPER_EFFECTIVE)
2017-09-24 00:29:52 +02:00
{
flags |= MOVESTATUS_SUPEREFFECTIVE;
}
}
// check type2
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBankTarget].type2)
2017-09-24 00:29:52 +02:00
{
if (gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2
&& TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_NO_EFFECT)
2017-09-24 00:29:52 +02:00
{
gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED;
break;
}
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBankTarget].type2
2017-09-24 00:29:52 +02:00
&& gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2
&& TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_NOT_EFFECTIVE)
2017-09-24 00:29:52 +02:00
{
flags |= MOVESTATUS_NOTVERYEFFECTIVE;
}
if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBankTarget].type2
2017-09-24 00:29:52 +02:00
&& gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2
&& TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_SUPER_EFFECTIVE)
2017-09-24 00:29:52 +02:00
{
flags |= MOVESTATUS_SUPEREFFECTIVE;
}
}
}
i += 3;
}
}
if (gBattleMons[gBankTarget].ability == ABILITY_WONDER_GUARD
&& !(flags & MOVESTATUS_NOEFFECT)
&& AttacksThisTurn(gBankAttacker, gCurrentMove) == 2
&& (!(flags & MOVESTATUS_SUPEREFFECTIVE) || ((flags & (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)) == (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)))
&& gBattleMoves[gCurrentMove].power)
{
gLastUsedAbility = ABILITY_WONDER_GUARD;
gBattleMoveFlags |= MOVESTATUS_MISSED;
gUnknown_02024250[gBankTarget] = 0;
gBattleCommunication[6] = 3;
RecordAbilityBattle(gBankTarget, gLastUsedAbility);
}
if (gBattleMoveFlags & MOVESTATUS_NOTAFFECTED)
2017-10-06 17:06:45 +02:00
gProtectStructs[gBankAttacker].targetNotAffected = 1;
2017-09-24 00:29:52 +02:00
gBattlescriptCurrInstr++;
}
static void atk4B_returnatktoball(void)
2017-09-24 00:29:52 +02:00
{
gActiveBank = gBankAttacker;
if (!(gHitMarker & HITMARKER_FAINTED(gActiveBank)))
{
2017-10-14 11:34:26 +02:00
EmitReturnMonToBall(0, 0);
2017-09-24 00:29:52 +02:00
MarkBufferBankForExecution(gActiveBank);
}
gBattlescriptCurrInstr++;
}
static void atk4C_getswitchedmondata(void)
2017-09-24 00:29:52 +02:00
{
if (gBattleExecBuffer)
return;
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-24 00:29:52 +02:00
2017-11-12 17:06:31 +01:00
gBattlePartyID[gActiveBank] = *(gBattleStruct->monToSwitchIntoId + gActiveBank);
2017-09-24 00:29:52 +02:00
EmitGetMonData(0, REQUEST_ALL_BATTLE, gBitTable[gBattlePartyID[gActiveBank]]);
2017-09-24 00:29:52 +02:00
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 2;
}
static void atk4D_switchindataupdate(void)
2017-09-24 00:29:52 +02:00
{
struct BattlePokemon oldData;
s32 i;
u8 *monData;
if (gBattleExecBuffer)
return;
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-24 00:29:52 +02:00
oldData = gBattleMons[gActiveBank];
monData = (u8*)(&gBattleMons[gActiveBank]);
for (i = 0; i < sizeof(struct BattlePokemon); i++)
{
monData[i] = gBattleBufferB[gActiveBank][4 + i];
}
gBattleMons[gActiveBank].type1 = gBaseStats[gBattleMons[gActiveBank].species].type1;
gBattleMons[gActiveBank].type2 = gBaseStats[gBattleMons[gActiveBank].species].type2;
gBattleMons[gActiveBank].ability = GetAbilityBySpecies(gBattleMons[gActiveBank].species, gBattleMons[gActiveBank].altAbility);
// check knocked off item
i = GetBankSide(gActiveBank);
if (gWishFutureKnock.knockedOffPokes[i] & gBitTable[gBattlePartyID[gActiveBank]])
{
gBattleMons[gActiveBank].item = 0;
}
if (gBattleMoves[gCurrentMove].effect == EFFECT_BATON_PASS)
{
for (i = 0; i < BATTLE_STATS_NO; i++)
2017-09-24 00:29:52 +02:00
{
gBattleMons[gActiveBank].statStages[i] = oldData.statStages[i];
}
gBattleMons[gActiveBank].status2 = oldData.status2;
}
2017-10-02 23:32:39 +02:00
SwitchInClearSetData();
2017-09-24 00:29:52 +02:00
if (gBattleTypeFlags & BATTLE_TYPE_PALACE && gBattleMons[gActiveBank].maxHP / 2 >= gBattleMons[gActiveBank].hp
&& gBattleMons[gActiveBank].hp != 0 && !(gBattleMons[gActiveBank].status1 & STATUS_SLEEP))
{
gBattleStruct->field_92 |= gBitTable[gActiveBank];
}
gBattleScripting.bank = gActiveBank;
PREPARE_MON_NICK_BUFFER(gBattleTextBuff1, gActiveBank, gBattlePartyID[gActiveBank]);
2017-09-24 00:29:52 +02:00
gBattlescriptCurrInstr += 2;
}
static void atk4E_switchinanim(void)
2017-09-24 00:29:52 +02:00
{
if (gBattleExecBuffer)
return;
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-24 00:29:52 +02:00
if (GetBankSide(gActiveBank) == SIDE_OPPONENT
&& !(gBattleTypeFlags & (BATTLE_TYPE_LINK
| BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_x2000000
| BATTLE_TYPE_x4000000
| BATTLE_TYPE_FRONTIER)))
HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBank].species), FLAG_SET_SEEN, gBattleMons[gActiveBank].personality);
gAbsentBankFlags &= ~(gBitTable[gActiveBank]);
EmitSwitchInAnim(0, gBattlePartyID[gActiveBank], gBattlescriptCurrInstr[2]);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 3;
if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
sub_81A56B4();
}
static void atk4F_jumpifcantswitch(void)
2017-09-24 00:29:52 +02:00
{
s32 val = 0;
s32 compareVar = 0;
struct Pokemon *party = NULL;
s32 r7 = 0;
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1] & ~(ATK4F_DONT_CHECK_STATUSES));
if (!(gBattlescriptCurrInstr[1] & ATK4F_DONT_CHECK_STATUSES)
&& ((gBattleMons[gActiveBank].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION))
|| (gStatuses3[gActiveBank] & STATUS3_ROOTED)))
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
}
else if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
{
#ifndef NONMATCHING
asm("":::"r5");
#endif // NONMATCHING
if (GetBankSide(gActiveBank) == SIDE_OPPONENT)
party = gEnemyParty;
else
party = gPlayerParty;
val = 0;
if (2 & gActiveBank)
val = 3;
for (compareVar = val + 3; val < compareVar; val++)
{
if (GetMonData(&party[val], MON_DATA_SPECIES) != SPECIES_NONE
&& !GetMonData(&party[val], MON_DATA_IS_EGG)
&& GetMonData(&party[val], MON_DATA_HP) != 0
&& gBattlePartyID[gActiveBank] != val)
break;
}
if (val == compareVar)
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
else
gBattlescriptCurrInstr += 6;
}
else if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
{
if (gBattleTypeFlags & BATTLE_TYPE_x800000)
{
if (GetBankSide(gActiveBank) == SIDE_PLAYER)
{
party = gPlayerParty;
val = 0;
2017-10-23 16:38:11 +02:00
if (sub_806D82C(GetBankMultiplayerId(gActiveBank)) == TRUE)
2017-09-24 00:29:52 +02:00
val = 3;
}
else
{
party = gEnemyParty;
if (gActiveBank == 1)
val = 0;
else
val = 3;
}
}
else
{
if (GetBankSide(gActiveBank) == SIDE_OPPONENT)
party = gEnemyParty;
else
party = gPlayerParty;
val = 0;
2017-10-23 16:38:11 +02:00
if (sub_806D82C(GetBankMultiplayerId(gActiveBank)) == TRUE)
2017-09-24 00:29:52 +02:00
val = 3;
}
for (compareVar = val + 3; val < compareVar; val++)
{
if (GetMonData(&party[val], MON_DATA_SPECIES) != SPECIES_NONE
&& !GetMonData(&party[val], MON_DATA_IS_EGG)
&& GetMonData(&party[val], MON_DATA_HP) != 0
&& gBattlePartyID[gActiveBank] != val)
break;
}
if (val == compareVar)
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
else
gBattlescriptCurrInstr += 6;
}
else if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && GetBankSide(gActiveBank) == SIDE_OPPONENT)
{
party = gEnemyParty;
val = 0;
if (gActiveBank == 3)
val = 3;
for (compareVar = val + 3; val < compareVar; val++)
{
if (GetMonData(&party[val], MON_DATA_SPECIES) != SPECIES_NONE
&& !GetMonData(&party[val], MON_DATA_IS_EGG)
&& GetMonData(&party[val], MON_DATA_HP) != 0
&& gBattlePartyID[gActiveBank] != val)
break;
}
if (val == compareVar)
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
else
gBattlescriptCurrInstr += 6;
}
else
{
if (GetBankSide(gActiveBank) == SIDE_OPPONENT)
{
2017-09-26 22:39:59 +02:00
r7 = GetBankByIdentity(1);
2017-09-24 00:29:52 +02:00
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
2017-09-26 22:39:59 +02:00
compareVar = GetBankByIdentity(3);
2017-09-24 00:29:52 +02:00
else
compareVar = r7;
party = gEnemyParty;
}
else
{
2017-09-26 22:39:59 +02:00
r7 = GetBankByIdentity(0);
2017-09-24 00:29:52 +02:00
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
2017-09-26 22:39:59 +02:00
compareVar = GetBankByIdentity(2);
2017-09-24 00:29:52 +02:00
else
compareVar = r7;
party = gPlayerParty;
}
for (val = 0; val < 6; val++)
{
if (GetMonData(&party[val], MON_DATA_HP) != 0
&& GetMonData(&party[val], MON_DATA_SPECIES) != SPECIES_NONE
&& !GetMonData(&party[val], MON_DATA_IS_EGG)
&& val != gBattlePartyID[r7] && val != gBattlePartyID[compareVar])
break;
}
if (val == 6)
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
else
gBattlescriptCurrInstr += 6;
}
}
2017-09-28 15:34:21 +02:00
static void sub_804CF10(u8 arg0)
2017-09-24 00:29:52 +02:00
{
*(gBattleStruct->field_58 + gActiveBank) = gBattlePartyID[gActiveBank];
2017-11-12 17:06:31 +01:00
*(gBattleStruct->monToSwitchIntoId + gActiveBank) = 6;
2017-09-24 00:29:52 +02:00
gBattleStruct->field_93 &= ~(gBitTable[gActiveBank]);
EmitChoosePokemon(0, 1, arg0, 0, gBattleStruct->field_60[gActiveBank]);
MarkBufferBankForExecution(gActiveBank);
}
2017-09-25 00:09:13 +02:00
2017-09-28 15:34:21 +02:00
static void atk50_openpartyscreen(void)
2017-09-25 00:09:13 +02:00
{
u32 flags;
u8 hitmarkerFaintBits;
u8 bank;
const u8 *jumpPtr;
bank = 0;
flags = 0;
jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
if (gBattlescriptCurrInstr[1] == 5)
{
if ((gBattleTypeFlags & (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI)) != BATTLE_TYPE_DOUBLE)
{
for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
{
if (gHitMarker & HITMARKER_FAINTED(gActiveBank))
{
if (sub_80423F4(gActiveBank, 6, 6))
{
gAbsentBankFlags |= gBitTable[gActiveBank];
gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
EmitLinkStandbyMsg(0, 2, 0);
MarkBufferBankForExecution(gActiveBank);
}
else if (!gSpecialStatuses[gActiveBank].flag40)
{
sub_804CF10(6);
gSpecialStatuses[gActiveBank].flag40 = 1;
}
}
else
{
EmitLinkStandbyMsg(0, 2, 0);
MarkBufferBankForExecution(gActiveBank);
}
}
}
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
u8 flag40_0, flag40_1, flag40_2, flag40_3;
hitmarkerFaintBits = gHitMarker >> 0x1C;
if (gBitTable[0] & hitmarkerFaintBits)
{
gActiveBank = 0;
if (sub_80423F4(0, 6, 6))
{
gAbsentBankFlags |= gBitTable[gActiveBank];
gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
2017-10-14 11:34:26 +02:00
EmitCmd42(0);
2017-09-25 00:09:13 +02:00
MarkBufferBankForExecution(gActiveBank);
}
else if (!gSpecialStatuses[gActiveBank].flag40)
{
2017-11-12 17:06:31 +01:00
sub_804CF10(gBattleStruct->monToSwitchIntoId[2]);
2017-09-25 00:09:13 +02:00
gSpecialStatuses[gActiveBank].flag40 = 1;
}
else
{
EmitLinkStandbyMsg(0, 2, 0);
MarkBufferBankForExecution(gActiveBank);
flags |= 1;
}
}
if (gBitTable[2] & hitmarkerFaintBits && !(gBitTable[0] & hitmarkerFaintBits))
{
gActiveBank = 2;
if (sub_80423F4(2, 6, 6))
{
gAbsentBankFlags |= gBitTable[gActiveBank];
gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
2017-10-14 11:34:26 +02:00
EmitCmd42(0);
2017-09-25 00:09:13 +02:00
MarkBufferBankForExecution(gActiveBank);
}
else if (!gSpecialStatuses[gActiveBank].flag40)
{
2017-11-12 17:06:31 +01:00
sub_804CF10(gBattleStruct->monToSwitchIntoId[0]);
2017-09-25 00:09:13 +02:00
gSpecialStatuses[gActiveBank].flag40 = 1;
}
else if (!(flags & 1))
{
EmitLinkStandbyMsg(0, 2, 0);
MarkBufferBankForExecution(gActiveBank);
}
}
if (gBitTable[1] & hitmarkerFaintBits)
{
gActiveBank = 1;
if (sub_80423F4(1, 6, 6))
{
gAbsentBankFlags |= gBitTable[gActiveBank];
gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
2017-10-14 11:34:26 +02:00
EmitCmd42(0);
2017-09-25 00:09:13 +02:00
MarkBufferBankForExecution(gActiveBank);
}
else if (!gSpecialStatuses[gActiveBank].flag40)
{
2017-11-12 17:06:31 +01:00
sub_804CF10(gBattleStruct->monToSwitchIntoId[3]);
2017-09-25 00:09:13 +02:00
gSpecialStatuses[gActiveBank].flag40 = 1;
}
else
{
EmitLinkStandbyMsg(0, 2, 0);
MarkBufferBankForExecution(gActiveBank);
flags |= 2;
}
}
if (gBitTable[3] & hitmarkerFaintBits && !(gBitTable[1] & hitmarkerFaintBits))
{
gActiveBank = 3;
if (sub_80423F4(3, 6, 6))
{
gAbsentBankFlags |= gBitTable[gActiveBank];
gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
2017-10-14 11:34:26 +02:00
EmitCmd42(0);
2017-09-25 00:09:13 +02:00
MarkBufferBankForExecution(gActiveBank);
}
else if (!gSpecialStatuses[gActiveBank].flag40)
{
2017-11-12 17:06:31 +01:00
sub_804CF10(gBattleStruct->monToSwitchIntoId[1]);
2017-09-25 00:09:13 +02:00
gSpecialStatuses[gActiveBank].flag40 = 1;
}
else if (!(flags & 2))
{
EmitLinkStandbyMsg(0, 2, 0);
MarkBufferBankForExecution(gActiveBank);
}
}
flag40_0 = gSpecialStatuses[0].flag40;
if (!flag40_0)
{
flag40_2 = gSpecialStatuses[2].flag40;
if (!flag40_2 && hitmarkerFaintBits != 0)
{
if (gAbsentBankFlags & gBitTable[0])
gActiveBank = 2;
else
gActiveBank = 0;
EmitLinkStandbyMsg(0, 2, 0);
MarkBufferBankForExecution(gActiveBank);
}
}
flag40_1 = gSpecialStatuses[1].flag40;
if (!flag40_1)
{
flag40_3 = gSpecialStatuses[3].flag40;
if (!flag40_3 && hitmarkerFaintBits != 0)
{
if (gAbsentBankFlags & gBitTable[1])
gActiveBank = 3;
else
gActiveBank = 1;
EmitLinkStandbyMsg(0, 2, 0);
MarkBufferBankForExecution(gActiveBank);
}
}
}
gBattlescriptCurrInstr += 6;
}
else if (gBattlescriptCurrInstr[1] == 6)
{
if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI))
{
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
hitmarkerFaintBits = gHitMarker >> 0x1C;
if (gBitTable[2] & hitmarkerFaintBits && gBitTable[0] & hitmarkerFaintBits)
{
gActiveBank = 2;
if (sub_80423F4(2, gBattleBufferB[0][1], 6))
{
gAbsentBankFlags |= gBitTable[gActiveBank];
gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
2017-10-14 11:34:26 +02:00
EmitCmd42(0);
2017-09-25 00:09:13 +02:00
MarkBufferBankForExecution(gActiveBank);
}
else if (!gSpecialStatuses[gActiveBank].flag40)
{
2017-11-12 17:06:31 +01:00
sub_804CF10(gBattleStruct->monToSwitchIntoId[0]);
2017-09-25 00:09:13 +02:00
gSpecialStatuses[gActiveBank].flag40 = 1;
}
}
if (gBitTable[3] & hitmarkerFaintBits && hitmarkerFaintBits & gBitTable[1])
{
gActiveBank = 3;
if (sub_80423F4(3, gBattleBufferB[1][1], 6))
{
gAbsentBankFlags |= gBitTable[gActiveBank];
gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
2017-10-14 11:34:26 +02:00
EmitCmd42(0);
2017-09-25 00:09:13 +02:00
MarkBufferBankForExecution(gActiveBank);
}
else if (!gSpecialStatuses[gActiveBank].flag40)
{
2017-11-12 17:06:31 +01:00
sub_804CF10(gBattleStruct->monToSwitchIntoId[1]);
2017-09-25 00:09:13 +02:00
gSpecialStatuses[gActiveBank].flag40 = 1;
}
}
gBattlescriptCurrInstr += 6;
}
else
{
gBattlescriptCurrInstr += 6;
}
}
else
{
gBattlescriptCurrInstr += 6;
}
hitmarkerFaintBits = gHitMarker >> 0x1C;
gBank1 = 0;
while (1)
{
if (gBitTable[gBank1] & hitmarkerFaintBits)
break;
if (gBank1 >= gNoOfAllBanks)
break;
gBank1++;
}
if (gBank1 == gNoOfAllBanks)
gBattlescriptCurrInstr = jumpPtr;
}
else
{
if (gBattlescriptCurrInstr[1] & 0x80)
hitmarkerFaintBits = 0; // used here as the caseId for the EmitChoose function
else
hitmarkerFaintBits = 1;
bank = GetBattleBank(gBattlescriptCurrInstr[1] & ~(0x80));
if (gSpecialStatuses[bank].flag40)
{
gBattlescriptCurrInstr += 6;
}
else if (sub_80423F4(bank, 6, 6))
{
gActiveBank = bank;
gAbsentBankFlags |= gBitTable[gActiveBank];
gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
gBattlescriptCurrInstr = jumpPtr;
}
else
{
gActiveBank = bank;
*(gBattleStruct->field_58 + gActiveBank) = gBattlePartyID[gActiveBank];
2017-11-12 17:06:31 +01:00
*(gBattleStruct->monToSwitchIntoId + gActiveBank) = 6;
2017-09-25 00:09:13 +02:00
gBattleStruct->field_93 &= ~(gBitTable[gActiveBank]);
2017-11-12 17:06:31 +01:00
EmitChoosePokemon(0, hitmarkerFaintBits, *(gBattleStruct->monToSwitchIntoId + (gActiveBank ^ 2)), 0, gBattleStruct->field_60[gActiveBank]);
2017-09-25 00:09:13 +02:00
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 6;
if (GetBankIdentity(gActiveBank) == 0 && gBattleResults.playerSwitchesCounter < 0xFF)
gBattleResults.playerSwitchesCounter++;
if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
{
for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
{
if (gActiveBank != bank)
{
EmitLinkStandbyMsg(0, 2, 0);
MarkBufferBankForExecution(gActiveBank);
}
}
}
else
{
2017-09-26 22:39:59 +02:00
gActiveBank = GetBankByIdentity(GetBankIdentity(bank) ^ BIT_SIDE);
2017-09-25 00:09:13 +02:00
if (gAbsentBankFlags & gBitTable[gActiveBank])
2017-09-26 22:39:59 +02:00
gActiveBank ^= BIT_MON;
2017-09-25 00:09:13 +02:00
EmitLinkStandbyMsg(0, 2, 0);
MarkBufferBankForExecution(gActiveBank);
}
}
}
}
static void atk51_switchhandleorder(void)
2017-09-25 00:09:13 +02:00
{
s32 i;
if (gBattleExecBuffer)
return;
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-25 00:09:13 +02:00
2017-09-28 15:34:21 +02:00
switch (gBattlescriptCurrInstr[2])
2017-09-25 00:09:13 +02:00
{
case 0:
for (i = 0; i < gNoOfAllBanks; i++)
{
if (gBattleBufferB[i][0] == 0x22)
{
2017-11-12 17:06:31 +01:00
*(gBattleStruct->monToSwitchIntoId + i) = gBattleBufferB[i][1];
2017-09-25 00:09:13 +02:00
if (!(gBattleStruct->field_93 & gBitTable[i]))
{
RecordedBattle_SetBankAction(i, gBattleBufferB[i][1]);
gBattleStruct->field_93 |= gBitTable[i];
}
}
}
break;
case 1:
if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI))
sub_803BDA0(gActiveBank);
break;
case 2:
if (!(gBattleStruct->field_93 & gBitTable[gActiveBank]))
{
RecordedBattle_SetBankAction(gActiveBank, gBattleBufferB[gActiveBank][1]);
gBattleStruct->field_93 |= gBitTable[gActiveBank];
}
// fall through
case 3:
gBattleCommunication[0] = gBattleBufferB[gActiveBank][1];
2017-11-12 17:06:31 +01:00
*(gBattleStruct->monToSwitchIntoId + gActiveBank) = gBattleBufferB[gActiveBank][1];
2017-09-25 00:09:13 +02:00
2017-10-04 19:25:14 +02:00
if (gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & BATTLE_TYPE_MULTI)
2017-09-25 00:09:13 +02:00
{
*(gActiveBank * 3 + (u8*)(gBattleStruct->field_60) + 0) &= 0xF;
*(gActiveBank * 3 + (u8*)(gBattleStruct->field_60) + 0) |= (gBattleBufferB[gActiveBank][2] & 0xF0);
*(gActiveBank * 3 + (u8*)(gBattleStruct->field_60) + 1) = gBattleBufferB[gActiveBank][3];
2017-10-04 19:25:14 +02:00
*((gActiveBank ^ BIT_MON) * 3 + (u8*)(gBattleStruct->field_60) + 0) &= (0xF0);
*((gActiveBank ^ BIT_MON) * 3 + (u8*)(gBattleStruct->field_60) + 0) |= (gBattleBufferB[gActiveBank][2] & 0xF0) >> 4;
*((gActiveBank ^ BIT_MON) * 3 + (u8*)(gBattleStruct->field_60) + 2) = gBattleBufferB[gActiveBank][3];
2017-09-25 00:09:13 +02:00
}
else if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
{
2017-11-12 17:06:31 +01:00
sub_80571DC(gActiveBank, *(gBattleStruct->monToSwitchIntoId + gActiveBank));
2017-09-25 00:09:13 +02:00
}
else
{
sub_803BDA0(gActiveBank);
}
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gBankAttacker].species)
PREPARE_MON_NICK_BUFFER(gBattleTextBuff2, gActiveBank, gBattleBufferB[gActiveBank][1])
break;
}
gBattlescriptCurrInstr += 3;
}
static void atk52_switchineffects(void)
2017-09-25 00:09:13 +02:00
{
s32 i;
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-25 00:09:13 +02:00
sub_803FA70(gActiveBank);
gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
gSpecialStatuses[gActiveBank].flag40 = 0;
if (!(gSideAffecting[GetBankSide(gActiveBank)] & SIDE_STATUS_SPIKES_DAMAGED)
&& (gSideAffecting[GetBankSide(gActiveBank)] & SIDE_STATUS_SPIKES)
&& gBattleMons[gActiveBank].type1 != TYPE_FLYING
&& gBattleMons[gActiveBank].type2 != TYPE_FLYING
&& gBattleMons[gActiveBank].ability != ABILITY_LEVITATE)
{
u8 spikesDmg;
gSideAffecting[GetBankSide(gActiveBank)] |= SIDE_STATUS_SPIKES_DAMAGED;
gBattleMons[gActiveBank].status2 &= ~(STATUS2_DESTINY_BOND);
gHitMarker &= ~(HITMARKER_DESTINYBOND);
spikesDmg = (5 - gSideTimers[GetBankSide(gActiveBank)].spikesAmount) * 2;
gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / (spikesDmg);
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattleScripting.bank = gActiveBank;
BattleScriptPushCursor();
if (gBattlescriptCurrInstr[1] == BS_GET_TARGET)
gBattlescriptCurrInstr = BattleScript_SpikesOnTarget;
else if (gBattlescriptCurrInstr[1] == BS_GET_ATTACKER)
gBattlescriptCurrInstr = BattleScript_SpikesOnAttacker;
2017-09-25 00:09:13 +02:00
else
gBattlescriptCurrInstr = BattleScript_SpikesOngBank1;
2017-09-25 00:09:13 +02:00
}
else
{
if (gBattleMons[gActiveBank].ability == ABILITY_TRUANT && !gDisableStructs[gActiveBank].truantUnknownBit)
gDisableStructs[gActiveBank].truantCounter = 1;
gDisableStructs[gActiveBank].truantUnknownBit = 0;
if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, gActiveBank, 0, 0, 0) == 0 &&
ItemBattleEffects(0, gActiveBank, 0) == 0)
{
gSideAffecting[GetBankSide(gActiveBank)] &= ~(SIDE_STATUS_SPIKES_DAMAGED);
for (i = 0; i < gNoOfAllBanks; i++)
{
2017-10-04 19:25:14 +02:00
if (gBanksByTurnOrder[i] == gActiveBank)
gActionsByTurnOrder[i] = ACTION_CANCEL_PARTNER;
2017-09-25 00:09:13 +02:00
}
for (i = 0; i < gNoOfAllBanks; i++)
{
2017-09-27 23:43:45 +02:00
u16* hpOnSwitchout = &gBattleStruct->hpOnSwitchout[GetBankSide(i)];
2017-09-25 00:09:13 +02:00
*hpOnSwitchout = gBattleMons[i].hp;
}
2017-09-28 15:34:21 +02:00
if (gBattlescriptCurrInstr[1] == 5)
2017-09-25 00:09:13 +02:00
{
u32 hitmarkerFaintBits = gHitMarker >> 0x1C;
gBank1++;
while (1)
{
if (hitmarkerFaintBits & gBitTable[gBank1] && !(gAbsentBankFlags & gBitTable[gBank1]))
break;
if (gBank1 >= gNoOfAllBanks)
break;
gBank1++;
}
}
gBattlescriptCurrInstr += 2;
}
}
}
static void atk53_trainerslidein(void)
2017-09-25 00:09:13 +02:00
{
2017-09-26 22:39:59 +02:00
gActiveBank = GetBankByIdentity(gBattlescriptCurrInstr[1]);
2017-09-25 00:09:13 +02:00
EmitTrainerSlide(0);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 2;
}
static void atk54_playse(void)
2017-09-25 00:09:13 +02:00
{
gActiveBank = gBankAttacker;
EmitPlaySE(0, BS2ScriptRead16(gBattlescriptCurrInstr + 1));
2017-09-25 00:09:13 +02:00
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 3;
}
static void atk55_fanfare(void)
2017-09-25 00:09:13 +02:00
{
gActiveBank = gBankAttacker;
2017-10-14 11:34:26 +02:00
EmitPlayFanfareOrBGM(0, BS2ScriptRead16(gBattlescriptCurrInstr + 1), FALSE);
2017-09-25 00:09:13 +02:00
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 3;
}
static void atk56_playfaintcry(void)
2017-09-25 00:09:13 +02:00
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-25 00:09:13 +02:00
EmitFaintingCry(0);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 2;
}
2017-09-28 15:34:21 +02:00
static void atk57(void)
2017-09-25 00:09:13 +02:00
{
gActiveBank = GetBankByIdentity(IDENTITY_PLAYER_MON1);
2017-10-14 11:34:26 +02:00
EmitCmd55(0, gBattleOutcome);
2017-09-25 00:09:13 +02:00
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 1;
}
static void atk58_returntoball(void)
2017-09-25 00:09:13 +02:00
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-10-14 11:34:26 +02:00
EmitReturnMonToBall(0, 1);
2017-09-25 00:09:13 +02:00
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 2;
}
static void atk59_handlelearnnewmove(void)
2017-09-25 00:09:13 +02:00
{
const u8* jumpPtr1 = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
const u8* jumpPtr2 = BSScriptReadPtr(gBattlescriptCurrInstr + 5);
2017-09-28 15:34:21 +02:00
u16 ret = MonTryLearningNewMove(&gPlayerParty[gBattleStruct->expGetterId], gBattlescriptCurrInstr[9]);
2017-09-25 00:09:13 +02:00
while (ret == 0xFFFE)
ret = MonTryLearningNewMove(&gPlayerParty[gBattleStruct->expGetterId], 0);
if (ret == 0)
{
gBattlescriptCurrInstr = jumpPtr2;
}
else if (ret == 0xFFFF)
{
gBattlescriptCurrInstr += 10;
}
else
{
2017-09-26 22:39:59 +02:00
gActiveBank = GetBankByIdentity(0);
2017-09-25 00:09:13 +02:00
if (gBattlePartyID[gActiveBank] == gBattleStruct->expGetterId
&& !(gBattleMons[gActiveBank].status2 & STATUS2_TRANSFORMED))
{
GiveMoveToBattleMon(&gBattleMons[gActiveBank], ret);
}
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
2017-09-26 22:39:59 +02:00
gActiveBank = GetBankByIdentity(2);
2017-09-25 00:09:13 +02:00
if (gBattlePartyID[gActiveBank] == gBattleStruct->expGetterId
&& !(gBattleMons[gActiveBank].status2 & STATUS2_TRANSFORMED))
{
GiveMoveToBattleMon(&gBattleMons[gActiveBank], ret);
}
}
gBattlescriptCurrInstr = jumpPtr1;
}
}
2017-09-28 15:34:21 +02:00
static void atk5A_yesnoboxlearnmove(void)
2017-09-25 00:09:13 +02:00
{
gActiveBank = 0;
switch (gBattleScripting.learnMoveState)
{
case 0:
HandleBattleWindow(0x18, 8, 0x1D, 0xD, 0);
BattleHandleAddTextPrinter(gText_BattleYesNoChoice, 0xC);
2017-09-25 00:09:13 +02:00
gBattleScripting.learnMoveState++;
gBattleCommunication[CURSOR_POSITION] = 0;
BattleCreateYesNoCursorAt(0);
2017-09-25 00:09:13 +02:00
break;
case 1:
if (gMain.newKeys & DPAD_UP && gBattleCommunication[CURSOR_POSITION] != 0)
{
PlaySE(SE_SELECT);
BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]);
2017-09-25 00:09:13 +02:00
gBattleCommunication[CURSOR_POSITION] = 0;
BattleCreateYesNoCursorAt(0);
2017-09-25 00:09:13 +02:00
}
if (gMain.newKeys & DPAD_DOWN && gBattleCommunication[CURSOR_POSITION] == 0)
{
PlaySE(SE_SELECT);
BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]);
2017-09-25 00:09:13 +02:00
gBattleCommunication[CURSOR_POSITION] = 1;
BattleCreateYesNoCursorAt(1);
2017-09-25 00:09:13 +02:00
}
if (gMain.newKeys & A_BUTTON)
{
PlaySE(SE_SELECT);
if (gBattleCommunication[1] == 0)
{
HandleBattleWindow(0x18, 0x8, 0x1D, 0xD, WINDOW_CLEAR);
2017-09-25 00:09:13 +02:00
BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
gBattleScripting.learnMoveState++;
}
else
{
gBattleScripting.learnMoveState = 5;
}
}
else if (gMain.newKeys & B_BUTTON)
{
PlaySE(SE_SELECT);
gBattleScripting.learnMoveState = 5;
}
break;
case 2:
if (!gPaletteFade.active)
{
FreeAllWindowBuffers();
sub_81BFA38(gPlayerParty, gBattleStruct->expGetterId, gPlayerPartyCount - 1, ReshowBattleScreenAfterMenu, gMoveToLearn);
gBattleScripting.learnMoveState++;
}
break;
case 3:
if (!gPaletteFade.active && gMain.callback2 == BattleMainCB2)
{
gBattleScripting.learnMoveState++;
}
break;
case 4:
if (!gPaletteFade.active && gMain.callback2 == BattleMainCB2)
{
u8 movePosition = sub_81C1B94();
if (movePosition == 4)
{
gBattleScripting.learnMoveState = 5;
}
else
{
u16 moveId = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_MOVE1 + movePosition);
if (IsHMMove2(moveId))
{
2017-10-07 15:15:47 +02:00
PrepareStringBattle(STRINGID_HMMOVESCANTBEFORGOTTEN, gActiveBank);
2017-09-25 00:09:13 +02:00
gBattleScripting.learnMoveState = 6;
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
PREPARE_MOVE_BUFFER(gBattleTextBuff2, moveId)
RemoveMonPPBonus(&gPlayerParty[gBattleStruct->expGetterId], movePosition);
SetMonMoveSlot(&gPlayerParty[gBattleStruct->expGetterId], gMoveToLearn, movePosition);
if (gBattlePartyID[0] == gBattleStruct->expGetterId
&& !(gBattleMons[0].status2 & STATUS2_TRANSFORMED)
&& !(gDisableStructs[0].unk18_b & gBitTable[movePosition]))
{
RemoveBattleMonPPBonus(&gBattleMons[0], movePosition);
SetBattleMonMoveSlot(&gBattleMons[0], gMoveToLearn, movePosition);
}
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
&& gBattlePartyID[2] == gBattleStruct->expGetterId
&& !(gBattleMons[2].status2 & STATUS2_TRANSFORMED)
&& !(gDisableStructs[2].unk18_b & gBitTable[movePosition]))
{
RemoveBattleMonPPBonus(&gBattleMons[2], movePosition);
SetBattleMonMoveSlot(&gBattleMons[2], gMoveToLearn, movePosition);
}
}
}
}
break;
case 5:
HandleBattleWindow(0x18, 8, 0x1D, 0xD, WINDOW_CLEAR);
2017-09-25 00:09:13 +02:00
gBattlescriptCurrInstr += 5;
break;
case 6:
if (gBattleExecBuffer == 0)
{
gBattleScripting.learnMoveState = 2;
}
break;
}
}
2017-09-28 15:34:21 +02:00
static void atk5B_yesnoboxstoplearningmove(void)
2017-09-25 00:09:13 +02:00
{
switch (gBattleScripting.learnMoveState)
{
case 0:
HandleBattleWindow(0x18, 8, 0x1D, 0xD, 0);
BattleHandleAddTextPrinter(gText_BattleYesNoChoice, 0xC);
2017-09-25 00:09:13 +02:00
gBattleScripting.learnMoveState++;
gBattleCommunication[CURSOR_POSITION] = 0;
BattleCreateYesNoCursorAt(0);
2017-09-25 00:09:13 +02:00
break;
case 1:
if (gMain.newKeys & DPAD_UP && gBattleCommunication[CURSOR_POSITION] != 0)
{
PlaySE(SE_SELECT);
BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]);
2017-09-25 00:09:13 +02:00
gBattleCommunication[CURSOR_POSITION] = 0;
BattleCreateYesNoCursorAt(0);
2017-09-25 00:09:13 +02:00
}
if (gMain.newKeys & DPAD_DOWN && gBattleCommunication[CURSOR_POSITION] == 0)
{
PlaySE(SE_SELECT);
BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]);
2017-09-25 00:09:13 +02:00
gBattleCommunication[CURSOR_POSITION] = 1;
BattleCreateYesNoCursorAt(1);
2017-09-25 00:09:13 +02:00
}
if (gMain.newKeys & A_BUTTON)
{
PlaySE(SE_SELECT);
if (gBattleCommunication[1] != 0)
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
else
gBattlescriptCurrInstr += 5;
HandleBattleWindow(0x18, 0x8, 0x1D, 0xD, WINDOW_CLEAR);
2017-09-25 00:09:13 +02:00
}
else if (gMain.newKeys & B_BUTTON)
{
PlaySE(SE_SELECT);
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
HandleBattleWindow(0x18, 0x8, 0x1D, 0xD, WINDOW_CLEAR);
2017-09-25 00:09:13 +02:00
}
break;
}
}
2017-09-28 15:34:21 +02:00
static void atk5C_hitanimation(void)
2017-09-25 00:09:13 +02:00
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-25 00:09:13 +02:00
if (gBattleMoveFlags & MOVESTATUS_NOEFFECT)
{
gBattlescriptCurrInstr += 2;
}
else if (!(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE) || !(gBattleMons[gActiveBank].status2 & STATUS2_SUBSTITUTE) || gDisableStructs[gActiveBank].substituteHP == 0)
{
EmitHitAnimation(0);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 2;
}
else
{
gBattlescriptCurrInstr += 2;
}
}
static u32 GetTrainerMoneyToGive(u16 trainerId)
{
u32 i = 0;
u32 lastMonLevel = 0;
u32 moneyReward = 0;
if (trainerId == SECRET_BASE_OPPONENT)
{
moneyReward = 20 * gBattleResources->secretBase->partyLevels[0] * gBattleStruct->moneyMultiplier;
}
else
{
switch (gTrainers[trainerId].partyFlags)
{
case 0:
{
const struct TrainerMonNoItemDefaultMoves *party = gTrainers[trainerId].party.NoItemDefaultMoves;
lastMonLevel = party[gTrainers[trainerId].partySize - 1].lvl;
}
break;
case PARTY_FLAG_CUSTOM_MOVES:
{
const struct TrainerMonNoItemCustomMoves *party = gTrainers[trainerId].party.NoItemCustomMoves;
lastMonLevel = party[gTrainers[trainerId].partySize - 1].lvl;
}
break;
case PARTY_FLAG_HAS_ITEM:
{
const struct TrainerMonItemDefaultMoves *party = gTrainers[trainerId].party.ItemDefaultMoves;
lastMonLevel = party[gTrainers[trainerId].partySize - 1].lvl;
}
break;
case PARTY_FLAG_CUSTOM_MOVES | PARTY_FLAG_HAS_ITEM:
{
const struct TrainerMonItemCustomMoves *party = gTrainers[trainerId].party.ItemCustomMoves;
lastMonLevel = party[gTrainers[trainerId].partySize - 1].lvl;
}
break;
}
for (; gTrainerMoneyTable[i].classId != 0xFF; i++)
{
if (gTrainerMoneyTable[i].classId == gTrainers[trainerId].trainerClass)
break;
}
if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
moneyReward = 4 * lastMonLevel * gBattleStruct->moneyMultiplier * gTrainerMoneyTable[i].value;
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
moneyReward = 4 * lastMonLevel * gBattleStruct->moneyMultiplier * 2 * gTrainerMoneyTable[i].value;
else
moneyReward = 4 * lastMonLevel * gBattleStruct->moneyMultiplier * gTrainerMoneyTable[i].value;
}
return moneyReward;
}
2017-09-28 15:34:21 +02:00
static void atk5D_getmoneyreward(void)
2017-09-25 00:09:13 +02:00
{
u32 moneyReward = GetTrainerMoneyToGive(gTrainerBattleOpponent_A);
if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
moneyReward += GetTrainerMoneyToGive(gTrainerBattleOpponent_B);
AddMoney(&gSaveBlock1Ptr->money, moneyReward);
PREPARE_WORD_NUMBER_BUFFER(gBattleTextBuff1, 5, moneyReward)
gBattlescriptCurrInstr++;
}
static void atk5E(void)
2017-09-25 00:09:13 +02:00
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-25 00:09:13 +02:00
switch (gBattleCommunication[0])
{
case 0:
2017-09-26 22:39:59 +02:00
EmitGetMonData(0, REQUEST_ALL_BATTLE, 0);
2017-09-25 00:09:13 +02:00
MarkBufferBankForExecution(gActiveBank);
gBattleCommunication[0]++;
break;
case 1:
if (gBattleExecBuffer == 0)
{
s32 i;
struct BattlePokemon* bufferPoke = (struct BattlePokemon*) &gBattleBufferB[gActiveBank][4];
for (i = 0; i < 4; i++)
{
gBattleMons[gActiveBank].moves[i] = bufferPoke->moves[i];
gBattleMons[gActiveBank].pp[i] = bufferPoke->pp[i];
}
gBattlescriptCurrInstr += 2;
}
break;
}
}
static void atk5F(void)
2017-09-25 00:09:13 +02:00
{
gActiveBank = gBankAttacker;
gBankAttacker = gBankTarget;
gBankTarget = gActiveBank;
if (gHitMarker & HITMARKER_PURSUIT_TRAP)
gHitMarker &= ~(HITMARKER_PURSUIT_TRAP);
else
gHitMarker |= HITMARKER_PURSUIT_TRAP;
gBattlescriptCurrInstr++;
}
static void atk60_incrementgamestat(void)
2017-09-25 00:09:13 +02:00
{
if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
2017-09-28 15:34:21 +02:00
IncrementGameStat(gBattlescriptCurrInstr[1]);
2017-09-25 00:09:13 +02:00
gBattlescriptCurrInstr += 2;
}
static void atk61_drawpartystatussummary(void)
2017-09-25 00:09:13 +02:00
{
s32 i;
struct Pokemon* party;
struct HpAndStatus hpStatuses[6];
if (gBattleExecBuffer)
return;
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-25 00:09:13 +02:00
if (GetBankSide(gActiveBank) == SIDE_PLAYER)
party = gPlayerParty;
else
party = gEnemyParty;
for (i = 0; i < 6; i++)
{
if (GetMonData(&party[i], MON_DATA_SPECIES2) == SPECIES_NONE
|| GetMonData(&party[i], MON_DATA_SPECIES2) == SPECIES_EGG)
{
hpStatuses[i].hp = 0xFFFF;
hpStatuses[i].status = 0;
}
else
{
hpStatuses[i].hp = GetMonData(&party[i], MON_DATA_HP);
hpStatuses[i].status = GetMonData(&party[i], MON_DATA_STATUS);
}
}
2017-10-02 23:32:39 +02:00
EmitDrawPartyStatusSummary(0, hpStatuses, 1);
2017-09-25 00:09:13 +02:00
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 2;
}
static void atk62(void)
2017-09-25 00:09:13 +02:00
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-25 00:09:13 +02:00
EmitCmd49(0);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 2;
}
2017-09-28 15:34:21 +02:00
static void atk63_jumptorandomattack(void)
2017-09-25 00:09:13 +02:00
{
2017-09-28 15:34:21 +02:00
if (gBattlescriptCurrInstr[1] != 0)
2017-09-25 00:09:13 +02:00
gCurrentMove = gRandomMove;
else
gLastUsedMove = gCurrentMove = gRandomMove;
gBattlescriptCurrInstr = gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect];
}
2017-09-28 15:34:21 +02:00
static void atk64_statusanimation(void)
2017-09-25 00:09:13 +02:00
{
if (gBattleExecBuffer == 0)
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-25 00:09:13 +02:00
if (!(gStatuses3[gActiveBank] & STATUS3_SEMI_INVULNERABLE)
&& gDisableStructs[gActiveBank].substituteHP == 0
&& !(gHitMarker & HITMARKER_NO_ANIMATIONS))
{
EmitStatusAnimation(0, FALSE, gBattleMons[gActiveBank].status1);
MarkBufferBankForExecution(gActiveBank);
}
gBattlescriptCurrInstr += 2;
}
}
2017-09-28 15:34:21 +02:00
static void atk65_status2animation(void)
2017-09-25 00:09:13 +02:00
{
u32 wantedToAnimate;
if (gBattleExecBuffer == 0)
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-25 00:09:13 +02:00
wantedToAnimate = BSScriptRead32(gBattlescriptCurrInstr + 2);
if (!(gStatuses3[gActiveBank] & STATUS3_SEMI_INVULNERABLE)
&& gDisableStructs[gActiveBank].substituteHP == 0
&& !(gHitMarker & HITMARKER_NO_ANIMATIONS))
{
EmitStatusAnimation(0, TRUE, gBattleMons[gActiveBank].status2 & wantedToAnimate);
MarkBufferBankForExecution(gActiveBank);
}
gBattlescriptCurrInstr += 6;
}
}
2017-09-28 15:34:21 +02:00
static void atk66_chosenstatusanimation(void)
2017-09-25 00:09:13 +02:00
{
u32 wantedStatus;
if (gBattleExecBuffer == 0)
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-25 00:09:13 +02:00
wantedStatus = BSScriptRead32(gBattlescriptCurrInstr + 3);
if (!(gStatuses3[gActiveBank] & STATUS3_SEMI_INVULNERABLE)
&& gDisableStructs[gActiveBank].substituteHP == 0
&& !(gHitMarker & HITMARKER_NO_ANIMATIONS))
{
2017-09-28 15:34:21 +02:00
EmitStatusAnimation(0, gBattlescriptCurrInstr[2], wantedStatus);
2017-09-25 00:09:13 +02:00
MarkBufferBankForExecution(gActiveBank);
}
gBattlescriptCurrInstr += 7;
}
}
2017-09-28 15:34:21 +02:00
static void atk67_yesnobox(void)
2017-09-25 00:09:13 +02:00
{
switch (gBattleCommunication[0])
{
case 0:
HandleBattleWindow(0x18, 8, 0x1D, 0xD, 0);
BattleHandleAddTextPrinter(gText_BattleYesNoChoice, 0xC);
2017-09-25 00:09:13 +02:00
gBattleCommunication[0]++;
gBattleCommunication[CURSOR_POSITION] = 0;
BattleCreateYesNoCursorAt(0);
2017-09-25 00:09:13 +02:00
break;
case 1:
if (gMain.newKeys & DPAD_UP && gBattleCommunication[CURSOR_POSITION] != 0)
{
PlaySE(SE_SELECT);
BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]);
2017-09-25 00:09:13 +02:00
gBattleCommunication[CURSOR_POSITION] = 0;
BattleCreateYesNoCursorAt(0);
2017-09-25 00:09:13 +02:00
}
if (gMain.newKeys & DPAD_DOWN && gBattleCommunication[CURSOR_POSITION] == 0)
{
PlaySE(SE_SELECT);
BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]);
2017-09-25 00:09:13 +02:00
gBattleCommunication[CURSOR_POSITION] = 1;
BattleCreateYesNoCursorAt(1);
2017-09-25 00:09:13 +02:00
}
if (gMain.newKeys & B_BUTTON)
{
gBattleCommunication[CURSOR_POSITION] = 1;
PlaySE(SE_SELECT);
HandleBattleWindow(0x18, 8, 0x1D, 0xD, WINDOW_CLEAR);
2017-09-25 00:09:13 +02:00
gBattlescriptCurrInstr++;
}
else if (gMain.newKeys & A_BUTTON)
{
PlaySE(SE_SELECT);
HandleBattleWindow(0x18, 8, 0x1D, 0xD, WINDOW_CLEAR);
2017-09-25 00:09:13 +02:00
gBattlescriptCurrInstr++;
}
break;
}
}
static void atk68_cancelallactions(void)
2017-09-25 00:09:13 +02:00
{
s32 i;
for (i = 0; i < gNoOfAllBanks; i++)
2017-10-04 19:25:14 +02:00
gActionsByTurnOrder[i] = ACTION_CANCEL_PARTNER;
2017-09-25 00:09:13 +02:00
gBattlescriptCurrInstr++;
}
static void atk69_adjustsetdamage(void) // The same as 0x7, except there's no random damage multiplier.
2017-09-25 00:09:13 +02:00
{
u8 holdEffect, quality;
if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY)
{
holdEffect = gEnigmaBerries[gBankTarget].holdEffect, quality = gEnigmaBerries[gBankTarget].holdEffectParam;
}
else
{
holdEffect = ItemId_GetHoldEffect(gBattleMons[gBankTarget].item);
quality = ItemId_GetHoldEffectParam(gBattleMons[gBankTarget].item);
}
gStringBank = gBankTarget;
if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < quality)
{
RecordItemEffectBattle(gBankTarget, holdEffect);
gSpecialStatuses[gBankTarget].focusBanded = 1;
}
if (gBattleMons[gBankTarget].status2 & STATUS2_SUBSTITUTE)
goto END;
if (gBattleMoves[gCurrentMove].effect != EFFECT_FALSE_SWIPE && !gProtectStructs[gBankTarget].endured
&& !gSpecialStatuses[gBankTarget].focusBanded)
goto END;
if (gBattleMons[gBankTarget].hp > gBattleMoveDamage)
goto END;
gBattleMoveDamage = gBattleMons[gBankTarget].hp - 1;
if (gProtectStructs[gBankTarget].endured)
{
gBattleMoveFlags |= MOVESTATUS_ENDURED;
}
else if (gSpecialStatuses[gBankTarget].focusBanded)
{
gBattleMoveFlags |= MOVESTATUS_HUNGON;
gLastUsedItem = gBattleMons[gBankTarget].item;
}
END:
gBattlescriptCurrInstr++;
}
2017-09-26 22:39:59 +02:00
2017-09-28 15:34:21 +02:00
static void atk6A_removeitem(void)
2017-09-26 22:39:59 +02:00
{
u16* usedHeldItem;
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-26 22:39:59 +02:00
2017-09-27 23:43:45 +02:00
usedHeldItem = &gBattleStruct->usedHeldItems[gActiveBank];
2017-09-26 22:39:59 +02:00
*usedHeldItem = gBattleMons[gActiveBank].item;
gBattleMons[gActiveBank].item = 0;
EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gBattleMons[gActiveBank].item);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 2;
}
2017-09-28 15:34:21 +02:00
static void atk6B_atknameinbuff1(void)
2017-09-26 22:39:59 +02:00
{
PREPARE_MON_NICK_BUFFER(gBattleTextBuff1, gBankAttacker, gBattlePartyID[gBankAttacker])
gBattlescriptCurrInstr++;
}
static void atk6C_drawlvlupbox(void)
2017-09-26 22:39:59 +02:00
{
if (gBattleScripting.atk6C_state == 0)
{
if (IsMonGettingExpSentOut())
gBattleScripting.atk6C_state = 3;
else
gBattleScripting.atk6C_state = 1;
}
switch (gBattleScripting.atk6C_state)
{
case 1:
gBattle_BG2_Y = 0x60;
SetBgAttribute(2, BG_CTRL_ATTR_MOSAIC, 0);
ShowBg(2);
sub_804F17C();
gBattleScripting.atk6C_state = 2;
break;
case 2:
if (!sub_804F1CC())
gBattleScripting.atk6C_state = 3;
break;
case 3:
gBattle_BG1_X = 0;
gBattle_BG1_Y = 0x100;
SetBgAttribute(0, BG_CTRL_ATTR_MOSAIC, 1);
SetBgAttribute(1, BG_CTRL_ATTR_MOSAIC, 0);
ShowBg(0);
ShowBg(1);
HandleBattleWindow(0x12, 7, 0x1D, 0x13, WINDOW_x80);
2017-09-26 22:39:59 +02:00
gBattleScripting.atk6C_state = 4;
break;
case 4:
sub_804F100();
PutWindowTilemap(13);
CopyWindowToVram(13, 3);
gBattleScripting.atk6C_state++;
break;
case 5:
case 7:
if (!IsDma3ManagerBusyWithBgCopy())
{
gBattle_BG1_Y = 0;
gBattleScripting.atk6C_state++;
}
break;
case 6:
if (gMain.newKeys != 0)
{
PlaySE(SE_SELECT);
sub_804F144();
CopyWindowToVram(13, 2);
gBattleScripting.atk6C_state++;
}
break;
case 8:
if (gMain.newKeys != 0)
{
PlaySE(SE_SELECT);
HandleBattleWindow(0x12, 7, 0x1D, 0x13, WINDOW_x80 | WINDOW_CLEAR);
2017-09-26 22:39:59 +02:00
gBattleScripting.atk6C_state++;
}
break;
case 9:
if (!sub_804F344())
{
ClearWindowTilemap(14);
CopyWindowToVram(14, 1);
ClearWindowTilemap(13);
CopyWindowToVram(13, 1);
SetBgAttribute(2, BG_CTRL_ATTR_MOSAIC, 2);
ShowBg(2);
gBattleScripting.atk6C_state = 10;
}
break;
case 10:
if (!IsDma3ManagerBusyWithBgCopy())
{
SetBgAttribute(0, BG_CTRL_ATTR_MOSAIC, 0);
SetBgAttribute(1, BG_CTRL_ATTR_MOSAIC, 1);
ShowBg(0);
ShowBg(1);
gBattlescriptCurrInstr++;
}
break;
}
}
2017-09-28 15:34:21 +02:00
static void sub_804F100(void)
2017-09-26 22:39:59 +02:00
{
struct StatsArray currentStats;
sub_81D388C(&gPlayerParty[gBattleStruct->expGetterId], &currentStats);
sub_81D3640(0xD, gBattleResources->statsBeforeLvlUp, &currentStats, 0xE, 0xD, 0xF);
}
2017-09-28 15:34:21 +02:00
static void sub_804F144(void)
2017-09-26 22:39:59 +02:00
{
struct StatsArray currentStats;
sub_81D388C(&gPlayerParty[gBattleStruct->expGetterId], &currentStats);
sub_81D3784(0xD, &currentStats, 0xE, 0xD, 0xF);
}
2017-09-28 15:34:21 +02:00
static void sub_804F17C(void)
2017-09-26 22:39:59 +02:00
{
gBattle_BG2_Y = 0;
gBattle_BG2_X = 0x1A0;
2017-09-28 16:51:24 +02:00
LoadPalette(sUnknown_0831C2C8, 0x60, 0x20);
CopyToWindowPixelBuffer(14, sUnknown_0831C2E8, 0, 0);
2017-09-26 22:39:59 +02:00
PutWindowTilemap(14);
CopyWindowToVram(14, 3);
PutMonIconOnLvlUpBox();
}
2017-09-28 15:34:21 +02:00
static bool8 sub_804F1CC(void)
2017-09-26 22:39:59 +02:00
{
if (IsDma3ManagerBusyWithBgCopy())
return TRUE;
if (gBattle_BG2_X == 0x200)
return FALSE;
if (gBattle_BG2_X == 0x1A0)
PutLevelAndGenderOnLvlUpBox();
gBattle_BG2_X += 8;
if (gBattle_BG2_X >= 0x200)
gBattle_BG2_X = 0x200;
return (gBattle_BG2_X != 0x200);
}
2017-09-28 15:34:21 +02:00
static void PutLevelAndGenderOnLvlUpBox(void)
2017-09-26 22:39:59 +02:00
{
u16 monLevel;
u8 monGender;
struct TextSubPrinter subPrinter;
u8 *txtPtr;
u32 var;
monLevel = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_LEVEL);
monGender = GetMonGender(&gPlayerParty[gBattleStruct->expGetterId]);
GetMonNickname(&gPlayerParty[gBattleStruct->expGetterId], gStringVar4);
subPrinter.current_text_offset = gStringVar4;
subPrinter.windowId = 14;
subPrinter.fontId = 0;
subPrinter.x = 32;
subPrinter.y = 0;
subPrinter.currentX = 32;
subPrinter.currentY = 0;
subPrinter.letterSpacing = 0;
subPrinter.lineSpacing = 0;
subPrinter.fontColor_l = TEXT_COLOR_TRANSPARENT;
subPrinter.fontColor_h = TEXT_COLOR_WHITE;
subPrinter.bgColor = TEXT_COLOR_TRANSPARENT;
subPrinter.shadowColor = TEXT_COLOR_DARK_GREY;
AddTextPrinter(&subPrinter, 0xFF, NULL);
txtPtr = gStringVar4;
gStringVar4[0] = CHAR_SPECIAL_F9;
txtPtr++;
txtPtr[0] = 5;
txtPtr++;
var = (u32)(txtPtr);
txtPtr = ConvertIntToDecimalStringN(txtPtr, monLevel, STR_CONV_MODE_LEFT_ALIGN, 3);
var = (u32)(txtPtr) - var;
txtPtr = StringFill(txtPtr, 0x77, 4 - var);
if (monGender != MON_GENDERLESS)
{
if (monGender == MON_MALE)
{
txtPtr = WriteColorChangeControlCode(txtPtr, 0, 0xC);
txtPtr = WriteColorChangeControlCode(txtPtr, 1, 0xD);
*(txtPtr++) = CHAR_MALE;
}
else
{
txtPtr = WriteColorChangeControlCode(txtPtr, 0, 0xE);
txtPtr = WriteColorChangeControlCode(txtPtr, 1, 0xF);
*(txtPtr++) = CHAR_FEMALE;
}
*(txtPtr++) = EOS;
}
subPrinter.y = 10;
subPrinter.currentY = 10;
AddTextPrinter(&subPrinter, 0xFF, NULL);
CopyWindowToVram(14, 2);
}
2017-09-28 15:34:21 +02:00
static bool8 sub_804F344(void)
2017-09-26 22:39:59 +02:00
{
if (gBattle_BG2_X == 0x1A0)
return FALSE;
if (gBattle_BG2_X - 16 < 0x1A0)
gBattle_BG2_X = 0x1A0;
else
gBattle_BG2_X -= 16;
return (gBattle_BG2_X != 0x1A0);
}
#define sDestroy data0
#define sSavedLvlUpBoxXPosition data1
2017-09-28 15:34:21 +02:00
static void PutMonIconOnLvlUpBox(void)
2017-09-26 22:39:59 +02:00
{
u8 spriteId;
const u16* iconPal;
struct SpriteSheet iconSheet;
struct SpritePalette iconPalSheet;
u16 species = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPECIES);
u32 personality = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_PERSONALITY);
const u8* iconPtr = GetMonIconPtr(species, personality, 1);
iconSheet.data = iconPtr;
iconSheet.size = 0x200;
iconSheet.tag = MON_ICON_LVLUP_BOX_TAG;
iconPal = GetValidMonIconPalettePtr(species);
iconPalSheet.data = iconPal;
iconPalSheet.tag = MON_ICON_LVLUP_BOX_TAG;
LoadSpriteSheet(&iconSheet);
LoadSpritePalette(&iconPalSheet);
2017-09-28 16:51:24 +02:00
spriteId = CreateSprite(&sSpriteTemplate_MonIconOnLvlUpBox, 256, 10, 0);
2017-09-26 22:39:59 +02:00
gSprites[spriteId].sDestroy = FALSE;
gSprites[spriteId].sSavedLvlUpBoxXPosition = gBattle_BG2_X;
}
2017-09-28 16:32:23 +02:00
static void SpriteCB_MonIconOnLvlUpBox(struct Sprite* sprite)
2017-09-26 22:39:59 +02:00
{
sprite->pos2.x = sprite->sSavedLvlUpBoxXPosition - gBattle_BG2_X;
if (sprite->pos2.x != 0)
{
sprite->sDestroy = TRUE;
}
else if (sprite->sDestroy)
{
DestroySprite(sprite);
FreeSpriteTilesByTag(MON_ICON_LVLUP_BOX_TAG);
FreeSpritePaletteByTag(MON_ICON_LVLUP_BOX_TAG);
}
}
#undef sDestroy
#undef sSavedLvlUpBoxXPosition
2017-09-28 15:34:21 +02:00
static bool32 IsMonGettingExpSentOut(void)
2017-09-26 22:39:59 +02:00
{
if (gBattlePartyID[0] == gBattleStruct->expGetterId)
return TRUE;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && gBattlePartyID[2] == gBattleStruct->expGetterId)
return TRUE;
return FALSE;
}
static void atk6D_resetsentmonsvalue(void)
2017-09-26 22:39:59 +02:00
{
ResetSentPokesToOpponentValue();
gBattlescriptCurrInstr++;
}
static void atk6E_setatktoplayer0(void)
2017-09-26 22:39:59 +02:00
{
gBankAttacker = GetBankByIdentity(0);
gBattlescriptCurrInstr++;
}
static void atk6F_makevisible(void)
2017-09-26 22:39:59 +02:00
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-26 22:39:59 +02:00
EmitSpriteInvisibility(0, FALSE);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 2;
}
static void atk70_recordlastability(void)
2017-09-26 22:39:59 +02:00
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-26 22:39:59 +02:00
RecordAbilityBattle(gActiveBank, gLastUsedAbility);
gBattlescriptCurrInstr += 1; // UB: Should be + 2, one byte for command and one byte for bank argument.
}
void BufferMoveToLearnIntoBattleTextBuff2(void)
{
PREPARE_MOVE_BUFFER(gBattleTextBuff2, gMoveToLearn);
}
static void atk71_buffermovetolearn(void)
2017-09-26 22:39:59 +02:00
{
BufferMoveToLearnIntoBattleTextBuff2();
gBattlescriptCurrInstr++;
}
static void atk72_jumpifplayerran(void)
2017-09-26 22:39:59 +02:00
{
2017-10-06 00:12:01 +02:00
if (TryRunFromBattle(gBank1))
2017-09-26 22:39:59 +02:00
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
else
gBattlescriptCurrInstr += 5;
}
static void atk73_hpthresholds(void)
2017-09-26 22:39:59 +02:00
{
u8 opposingBank;
s32 result;
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-26 22:39:59 +02:00
opposingBank = gActiveBank ^ BIT_SIDE;
result = gBattleMons[opposingBank].hp * 100 / gBattleMons[opposingBank].maxHP;
if (result == 0)
result = 1;
if (result > 69 || !gBattleMons[opposingBank].hp)
gBattleStruct->hpScale = 0;
else if (result > 39)
gBattleStruct->hpScale = 1;
else if (result > 9)
gBattleStruct->hpScale = 2;
else
gBattleStruct->hpScale = 3;
}
gBattlescriptCurrInstr += 2;
}
static void atk74_hpthresholds2(void)
2017-09-26 22:39:59 +02:00
{
u8 opposingBank;
s32 result;
u8 hpSwitchout;
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-26 22:39:59 +02:00
opposingBank = gActiveBank ^ BIT_SIDE;
hpSwitchout = *(gBattleStruct->hpOnSwitchout + GetBankSide(opposingBank));
result = (hpSwitchout - gBattleMons[opposingBank].hp) * 100 / hpSwitchout;
if (gBattleMons[opposingBank].hp >= hpSwitchout)
gBattleStruct->hpScale = 0;
else if (result <= 29)
gBattleStruct->hpScale = 1;
else if (result <= 69)
gBattleStruct->hpScale = 2;
else
gBattleStruct->hpScale = 3;
}
gBattlescriptCurrInstr += 2;
}
static void atk75_useitemonopponent(void)
2017-09-26 22:39:59 +02:00
{
gBankInMenu = gBankAttacker;
ExecuteTableBasedItemEffect(&gEnemyParty[gBattlePartyID[gBankAttacker]], gLastUsedItem, gBattlePartyID[gBankAttacker], 0, 1);
gBattlescriptCurrInstr += 1;
}
2017-09-28 15:34:21 +02:00
static void atk76_various(void)
2017-09-26 22:39:59 +02:00
{
u8 side;
s32 i;
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
switch (gBattlescriptCurrInstr[2])
{
case VARIOUS_CANCEL_MULTI_TURN_MOVES:
CancelMultiTurnMoves(gActiveBank);
break;
case VARIOUS_SET_MAGIC_COAT_TARGET:
gBankAttacker = gBankTarget;
side = GetBankSide(gBankAttacker) ^ BIT_SIDE;
2017-09-26 22:39:59 +02:00
if (gSideTimers[side].followmeTimer != 0 && gBattleMons[gSideTimers[side].followmeTarget].hp != 0)
gBankTarget = gSideTimers[side].followmeTarget;
else
gBankTarget = gActiveBank;
break;
case VARIOUS_IS_RUNNING_IMPOSSIBLE:
2017-09-26 22:39:59 +02:00
gBattleCommunication[0] = IsRunningFromBattleImpossible();
break;
case VARIOUS_GET_MOVE_TARGET:
gBankTarget = GetMoveTarget(gCurrentMove, 0);
break;
case 4:
if (gHitMarker & HITMARKER_FAINTED(gActiveBank))
gBattleCommunication[0] = 1;
else
gBattleCommunication[0] = 0;
break;
case VARIOUS_RESET_INTIMIDATE_TRACE_BITS:
gSpecialStatuses[gActiveBank].intimidatedPoke = 0;
gSpecialStatuses[gActiveBank].traced = 0;
break;
case VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP:
if (gBattlePartyID[0] == gBattleStruct->expGetterId || gBattlePartyID[2] == gBattleStruct->expGetterId)
{
u16 *choicedMove;
if (gBattlePartyID[0] == gBattleStruct->expGetterId)
gActiveBank = 0;
else
gActiveBank = 2;
choicedMove = &gBattleStruct->choicedMove[gActiveBank];
for (i = 0; i < 4; i++)
{
if (gBattleMons[gActiveBank].moves[i] == *choicedMove)
break;
}
if (i == 4)
*choicedMove = 0;
}
break;
case 7:
if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_DOUBLE))
&& gBattleTypeFlags & BATTLE_TYPE_TRAINER
&& gBattleMons[0].hp != 0
&& gBattleMons[1].hp != 0)
{
gHitMarker &= ~(HITMARKER_x400000);
}
break;
case 8:
gBattleCommunication[0] = 0;
gBattleScripting.bank = gActiveBank = gBattleCommunication[1];
if (!(gBattleStruct->field_92 & gBitTable[gActiveBank])
&& gBattleMons[gActiveBank].maxHP / 2 >= gBattleMons[gActiveBank].hp
&& gBattleMons[gActiveBank].hp != 0
&& !(gBattleMons[gActiveBank].status1 & STATUS_SLEEP))
{
gBattleStruct->field_92 |= gBitTable[gActiveBank];
gBattleCommunication[0] = 1;
2017-09-28 16:51:24 +02:00
gBattleCommunication[MULTISTRING_CHOOSER] = sUnknown_0831C4F8[GetNatureFromPersonality(gBattleMons[gActiveBank].personality)];
2017-09-26 22:39:59 +02:00
}
break;
case 9:
i = sub_81A5258(gBattleCommunication);
if (i == 0)
return;
gBattleCommunication[1] = i;
break;
case 10:
gBattleMons[1].hp = 0;
gHitMarker |= HITMARKER_FAINTED(1);
gBattleStruct->field_2A1 |= gBitTable[gBattlePartyID[1]];
gDisableStructs[1].truantUnknownBit = 1;
break;
case 11:
gBattleMons[0].hp = 0;
gHitMarker |= HITMARKER_FAINTED(0);
gHitMarker |= HITMARKER_x400000;
gBattleStruct->field_2A0 |= gBitTable[gBattlePartyID[0]];
gDisableStructs[0].truantUnknownBit = 1;
break;
case 12:
gBattleMons[0].hp = 0;
gBattleMons[1].hp = 0;
gHitMarker |= HITMARKER_FAINTED(0);
gHitMarker |= HITMARKER_FAINTED(1);
gHitMarker |= HITMARKER_x400000;
gBattleStruct->field_2A0 |= gBitTable[gBattlePartyID[0]];
gBattleStruct->field_2A1 |= gBitTable[gBattlePartyID[1]];
gDisableStructs[0].truantUnknownBit = 1;
gDisableStructs[1].truantUnknownBit = 1;
break;
case VARIOUS_EMIT_YESNOBOX:
2017-10-22 18:43:15 +02:00
EmitUnknownYesNoBox(0);
2017-09-26 22:39:59 +02:00
MarkBufferBankForExecution(gActiveBank);
break;
case 14:
sub_81A5BF8();
break;
case 15:
sub_81A5D44();
break;
case 16:
BattleStringExpandPlaceholdersToDisplayedString(gRefereeStringsTable[gBattlescriptCurrInstr[1]]);
BattleHandleAddTextPrinter(gDisplayedStringBattle, 0x16);
2017-09-26 22:39:59 +02:00
break;
case 17:
if (IsTextPrinterActive(0x16))
return;
break;
case VARIOUS_WAIT_CRY:
if (!IsCryFinished())
return;
break;
case VARIOUS_RETURN_OPPONENT_MON1:
gActiveBank = 1;
if (gBattleMons[gActiveBank].hp != 0)
{
2017-10-14 11:34:26 +02:00
EmitReturnMonToBall(0, 0);
2017-09-26 22:39:59 +02:00
MarkBufferBankForExecution(gActiveBank);
}
break;
case VARIOUS_RETURN_OPPONENT_MON2:
if (gNoOfAllBanks > 3)
{
gActiveBank = 3;
if (gBattleMons[gActiveBank].hp != 0)
{
2017-10-14 11:34:26 +02:00
EmitReturnMonToBall(0, 0);
2017-09-26 22:39:59 +02:00
MarkBufferBankForExecution(gActiveBank);
}
}
break;
case 21:
m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 0x55);
break;
case 22:
m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 0x100);
break;
case 23:
gBattleStruct->field_2A2 |= gBitTable[gActiveBank];
break;
case 24:
if (sub_805725C(gActiveBank))
return;
break;
case VARIOUS_SET_TELEPORT_OUTCOME:
if (GetBankSide(gActiveBank) == SIDE_PLAYER)
gBattleOutcome = BATTLE_PLAYER_TELEPORTED;
else
gBattleOutcome = BATTLE_OPPONENT_TELEPORTED;
break;
case VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC:
2017-10-14 11:34:26 +02:00
EmitPlayFanfareOrBGM(0, BGM_KACHI1, TRUE);
2017-09-26 22:39:59 +02:00
MarkBufferBankForExecution(gActiveBank);
break;
}
gBattlescriptCurrInstr += 3;
}
static void atk77_setprotectlike(void) // protect and endure
2017-09-26 22:39:59 +02:00
{
bool8 notLastTurn = TRUE;
u16 lastMove = gUnknown_02024260[gBankAttacker];
if (lastMove != MOVE_PROTECT && lastMove != MOVE_DETECT && lastMove != MOVE_ENDURE)
gDisableStructs[gBankAttacker].protectUses = 0;
2017-10-06 00:12:01 +02:00
if (gCurrentTurnActionNumber == (gNoOfAllBanks - 1))
2017-09-26 22:39:59 +02:00
notLastTurn = FALSE;
if (sProtectSuccessRates[gDisableStructs[gBankAttacker].protectUses] >= Random() && notLastTurn)
{
if (gBattleMoves[gCurrentMove].effect == EFFECT_PROTECT)
{
gProtectStructs[gBankAttacker].protected = 1;
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
}
if (gBattleMoves[gCurrentMove].effect == EFFECT_ENDURE)
{
gProtectStructs[gBankAttacker].endured = 1;
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
}
gDisableStructs[gBankAttacker].protectUses++;
}
else
{
gDisableStructs[gBankAttacker].protectUses = 0;
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
gBattleMoveFlags |= MOVESTATUS_MISSED;
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atk78_faintifabilitynotdamp(void)
2017-09-26 22:39:59 +02:00
{
if (gBattleExecBuffer)
return;
for (gBankTarget = 0; gBankTarget < gNoOfAllBanks; gBankTarget++)
{
if (gBattleMons[gBankTarget].ability == ABILITY_DAMP)
break;
}
if (gBankTarget == gNoOfAllBanks)
{
gActiveBank = gBankAttacker;
gBattleMoveDamage = gBattleMons[gActiveBank].hp;
2017-10-22 18:43:15 +02:00
EmitHealthBarUpdate(0, INSTANT_HP_BAR_DROP);
2017-09-26 22:39:59 +02:00
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr++;
for (gBankTarget = 0; gBankTarget < gNoOfAllBanks; gBankTarget++)
{
if (gBankTarget == gBankAttacker)
continue;
if (!(gAbsentBankFlags & gBitTable[gBankTarget]))
break;
}
}
else
{
gLastUsedAbility = ABILITY_DAMP;
RecordAbilityBattle(gBankTarget, gBattleMons[gBankTarget].ability);
gBattlescriptCurrInstr = BattleScript_DampStopsExplosion;
}
}
2017-09-28 15:34:21 +02:00
static void atk79_setatkhptozero(void)
2017-09-26 22:39:59 +02:00
{
if (gBattleExecBuffer)
return;
gActiveBank = gBankAttacker;
gBattleMons[gActiveBank].hp = 0;
EmitSetMonData(0, REQUEST_HP_BATTLE, 0, 2, &gBattleMons[gActiveBank].hp);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr++;
}
static void atk7A_jumpifnexttargetvalid(void)
2017-09-26 22:39:59 +02:00
{
const u8 *jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
2017-09-26 22:39:59 +02:00
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
for (gBankTarget++; ; gBankTarget++)
{
if (gBankTarget == gBankAttacker)
continue;
if (!(gAbsentBankFlags & gBitTable[gBankTarget]))
break;
}
if (gBankTarget >= gNoOfAllBanks)
gBattlescriptCurrInstr += 5;
else
gBattlescriptCurrInstr = jumpPtr;
}
else
{
2017-09-26 22:39:59 +02:00
gBattlescriptCurrInstr += 5;
}
2017-09-26 22:39:59 +02:00
}
static void atk7B_tryhealhalfhealth(void)
2017-09-26 22:39:59 +02:00
{
const u8* failPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
2017-09-28 15:34:21 +02:00
if (gBattlescriptCurrInstr[5] == BS_GET_ATTACKER)
2017-09-26 22:39:59 +02:00
gBankTarget = gBankAttacker;
gBattleMoveDamage = gBattleMons[gBankTarget].maxHP / 2;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattleMoveDamage *= -1;
if (gBattleMons[gBankTarget].hp == gBattleMons[gBankTarget].maxHP)
gBattlescriptCurrInstr = failPtr;
else
gBattlescriptCurrInstr += 6;
}
2017-09-28 15:34:21 +02:00
static void atk7C_trymirrormove(void)
2017-09-26 22:39:59 +02:00
{
s32 validMovesCount;
s32 i;
u16 move;
u16 movesArray[4];
for (i = 0; i < 3; i++)
movesArray[i] = 0;
for (validMovesCount = 0, i = 0; i < gNoOfAllBanks; i++)
{
if (i != gBankAttacker)
{
move = *(i * 2 + gBankAttacker * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0)
| (*(i * 2 + gBankAttacker * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 1) << 8);
if (move != 0 && move != 0xFFFF)
{
movesArray[validMovesCount] = move;
validMovesCount++;
}
}
}
move = *(gBattleStruct->mirrorMoves + gBankAttacker * 2 + 0)
| (*(gBattleStruct->mirrorMoves + gBankAttacker * 2 + 1) << 8);
if (move != 0 && move != 0xFFFF)
{
gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED);
gCurrentMove = move;
gBankTarget = GetMoveTarget(gCurrentMove, 0);
gBattlescriptCurrInstr = gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect];
}
else if (validMovesCount)
{
gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED);
i = Random() % validMovesCount;
gCurrentMove = movesArray[i];
gBankTarget = GetMoveTarget(gCurrentMove, 0);
gBattlescriptCurrInstr = gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect];
}
else
{
gSpecialStatuses[gBankAttacker].flag20 = 1;
gBattlescriptCurrInstr++;
}
}
static void atk7D_setrain(void)
2017-09-26 22:39:59 +02:00
{
if (gBattleWeather & WEATHER_RAIN_ANY)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
}
else
{
gBattleWeather = WEATHER_RAIN_TEMPORARY;
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
gWishFutureKnock.weatherDuration = 5;
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atk7E_setreflect(void)
2017-09-26 22:39:59 +02:00
{
if (gSideAffecting[GET_BANK_SIDE(gBankAttacker)] & SIDE_STATUS_REFLECT)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
}
else
{
gSideAffecting[GET_BANK_SIDE(gBankAttacker)] |= SIDE_STATUS_REFLECT;
gSideTimers[GET_BANK_SIDE(gBankAttacker)].reflectTimer = 5;
gSideTimers[GET_BANK_SIDE(gBankAttacker)].reflectBank = gBankAttacker;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && CountAliveMonsInBattle(BATTLE_ALIVE_ATK_SIDE) == 2)
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
else
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atk7F_setseeded(void)
2017-09-26 22:39:59 +02:00
{
if (gBattleMoveFlags & MOVESTATUS_NOEFFECT || gStatuses3[gBankTarget] & STATUS3_LEECHSEED)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
}
else if (gBattleMons[gBankTarget].type1 == TYPE_GRASS || gBattleMons[gBankTarget].type2 == TYPE_GRASS)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
}
else
{
gStatuses3[gBankTarget] |= gBankAttacker;
gStatuses3[gBankTarget] |= STATUS3_LEECHSEED;
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atk80_manipulatedamage(void)
2017-09-26 22:39:59 +02:00
{
2017-09-28 15:34:21 +02:00
switch (gBattlescriptCurrInstr[1])
2017-09-26 22:39:59 +02:00
{
case ATK80_DMG_CHANGE_SIGN:
gBattleMoveDamage *= -1;
break;
case ATK80_DMG_HALF_BY_TWO_NOT_MORE_THAN_HALF_MAX_HP:
gBattleMoveDamage /= 2;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
if ((gBattleMons[gBankTarget].maxHP / 2) < gBattleMoveDamage)
gBattleMoveDamage = gBattleMons[gBankTarget].maxHP / 2;
break;
case ATK80_DMG_DOUBLED:
gBattleMoveDamage *= 2;
break;
}
gBattlescriptCurrInstr += 2;
}
static void atk81_trysetrest(void)
2017-09-26 22:39:59 +02:00
{
const u8 *failJump = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
2017-09-26 22:39:59 +02:00
gActiveBank = gBankTarget = gBankAttacker;
gBattleMoveDamage = gBattleMons[gBankTarget].maxHP * (-1);
if (gBattleMons[gBankTarget].hp == gBattleMons[gBankTarget].maxHP)
{
gBattlescriptCurrInstr = failJump;
}
else
{
if (gBattleMons[gBankTarget].status1 & ((u8)(~STATUS_SLEEP)))
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
else
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
gBattleMons[gBankTarget].status1 = 3;
EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 5;
}
}
2017-09-28 15:34:21 +02:00
static void atk82_jumpifnotfirstturn(void)
2017-09-26 22:39:59 +02:00
{
const u8* failJump = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
if (gDisableStructs[gBankAttacker].isFirstTurn)
gBattlescriptCurrInstr += 5;
else
gBattlescriptCurrInstr = failJump;
}
2017-09-28 15:34:21 +02:00
static void atk83_nop(void)
2017-09-26 22:39:59 +02:00
{
gBattlescriptCurrInstr++;
}
bool8 UproarWakeUpCheck(u8 bank)
{
s32 i;
for (i = 0; i < gNoOfAllBanks; i++)
{
if (!(gBattleMons[i].status2 & STATUS2_UPROAR) || gBattleMons[bank].ability == ABILITY_SOUNDPROOF)
continue;
gBattleScripting.bank = i;
if (gBankTarget == 0xFF)
gBankTarget = i;
else if (gBankTarget == i)
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
else
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
break;
}
if (i == gNoOfAllBanks)
return FALSE;
else
return TRUE;
}
static void atk84_jumpifcantmakeasleep(void)
2017-09-26 22:39:59 +02:00
{
const u8 *jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
2017-09-26 22:39:59 +02:00
if (UproarWakeUpCheck(gBankTarget))
{
gBattlescriptCurrInstr = jumpPtr;
}
else if (gBattleMons[gBankTarget].ability == ABILITY_INSOMNIA
|| gBattleMons[gBankTarget].ability == ABILITY_VITAL_SPIRIT)
{
gLastUsedAbility = gBattleMons[gBankTarget].ability;
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
gBattlescriptCurrInstr = jumpPtr;
RecordAbilityBattle(gBankTarget, gLastUsedAbility);
}
else
{
gBattlescriptCurrInstr += 5;
}
}
2017-09-28 15:34:21 +02:00
static void atk85_stockpile(void)
2017-09-26 22:39:59 +02:00
{
if (gDisableStructs[gBankAttacker].stockpileCounter == 3)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
}
else
{
gDisableStructs[gBankAttacker].stockpileCounter++;
PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff1, 1, gDisableStructs[gBankAttacker].stockpileCounter)
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atk86_stockpiletobasedamage(void)
2017-09-26 22:39:59 +02:00
{
const u8* jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
if (gDisableStructs[gBankAttacker].stockpileCounter == 0)
{
gBattlescriptCurrInstr = jumpPtr;
}
else
{
if (gBattleCommunication[6] != 1)
{
gBattleMoveDamage = CalculateBaseDamage(&gBattleMons[gBankAttacker], &gBattleMons[gBankTarget], gCurrentMove,
gSideAffecting[GET_BANK_SIDE(gBankTarget)], 0,
0, gBankAttacker, gBankTarget)
* gDisableStructs[gBankAttacker].stockpileCounter;
gBattleScripting.animTurn = gDisableStructs[gBankAttacker].stockpileCounter;
if (gProtectStructs[gBankAttacker].helpingHand)
gBattleMoveDamage = gBattleMoveDamage * 15 / 10;
}
gDisableStructs[gBankAttacker].stockpileCounter = 0;
gBattlescriptCurrInstr += 5;
}
}
2017-09-28 15:34:21 +02:00
static void atk87_stockpiletohpheal(void)
2017-09-26 22:39:59 +02:00
{
const u8* jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
if (gDisableStructs[gBankAttacker].stockpileCounter == 0)
{
gBattlescriptCurrInstr = jumpPtr;
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
}
else if (gBattleMons[gBankAttacker].maxHP == gBattleMons[gBankAttacker].hp)
{
gDisableStructs[gBankAttacker].stockpileCounter = 0;
gBattlescriptCurrInstr = jumpPtr;
gBankTarget = gBankAttacker;
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
}
else
{
gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / (1 << (3 - gDisableStructs[gBankAttacker].stockpileCounter));
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattleMoveDamage *= -1;
gBattleScripting.animTurn = gDisableStructs[gBankAttacker].stockpileCounter;
gDisableStructs[gBankAttacker].stockpileCounter = 0;
gBattlescriptCurrInstr += 5;
gBankTarget = gBankAttacker;
}
}
2017-09-28 15:34:21 +02:00
static void atk88_negativedamage(void)
2017-09-26 22:39:59 +02:00
{
gBattleMoveDamage = -(gHpDealt / 2);
if (gBattleMoveDamage == 0)
gBattleMoveDamage = -1;
gBattlescriptCurrInstr++;
}
2017-11-26 11:55:17 +01:00
static u8 ChangeStatBuffs(s8 statValue, u8 statId, u8 flags, const u8 *BS_ptr)
2017-09-26 22:39:59 +02:00
{
2017-11-26 11:55:17 +01:00
bool8 certain = FALSE;
2017-09-26 22:39:59 +02:00
bool8 notProtectAffected = FALSE;
u32 index;
if (flags & MOVE_EFFECT_AFFECTS_USER)
gActiveBank = gBankAttacker;
else
gActiveBank = gBankTarget;
flags &= ~(MOVE_EFFECT_AFFECTS_USER);
if (flags & MOVE_EFFECT_CERTAIN)
certain++;
flags &= ~(MOVE_EFFECT_CERTAIN);
if (flags & STAT_CHANGE_NOT_PROTECT_AFFECTED)
notProtectAffected++;
flags &= ~(STAT_CHANGE_NOT_PROTECT_AFFECTED);
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId)
if ((statValue << 0x18) < 0) // stat decrease
{
if (gSideTimers[GET_BANK_SIDE(gActiveBank)].mistTimer
&& !certain && gCurrentMove != MOVE_CURSE)
{
if (flags == STAT_CHANGE_BS_PTR)
{
if (gSpecialStatuses[gActiveBank].statLowered)
{
gBattlescriptCurrInstr = BS_ptr;
}
else
{
BattleScriptPush(BS_ptr);
gBattleScripting.bank = gActiveBank;
gBattlescriptCurrInstr = BattleScript_MistProtected;
gSpecialStatuses[gActiveBank].statLowered = 1;
}
}
return STAT_CHANGE_DIDNT_WORK;
}
else if (gCurrentMove != MOVE_CURSE
&& notProtectAffected != TRUE && JumpIfMoveAffectedByProtect(0))
{
gBattlescriptCurrInstr = BattleScript_ButItFailed;
return STAT_CHANGE_DIDNT_WORK;
}
else if ((gBattleMons[gActiveBank].ability == ABILITY_CLEAR_BODY
|| gBattleMons[gActiveBank].ability == ABILITY_WHITE_SMOKE)
&& !certain && gCurrentMove != MOVE_CURSE)
{
if (flags == STAT_CHANGE_BS_PTR)
{
if (gSpecialStatuses[gActiveBank].statLowered)
{
gBattlescriptCurrInstr = BS_ptr;
}
else
{
BattleScriptPush(BS_ptr);
gBattleScripting.bank = gActiveBank;
gBattlescriptCurrInstr = BattleScript_AbilityNoStatLoss;
gLastUsedAbility = gBattleMons[gActiveBank].ability;
RecordAbilityBattle(gActiveBank, gLastUsedAbility);
gSpecialStatuses[gActiveBank].statLowered = 1;
}
}
return STAT_CHANGE_DIDNT_WORK;
}
else if (gBattleMons[gActiveBank].ability == ABILITY_KEEN_EYE
&& !certain && statId == STAT_STAGE_ACC)
{
if (flags == STAT_CHANGE_BS_PTR)
{
BattleScriptPush(BS_ptr);
gBattleScripting.bank = gActiveBank;
gBattlescriptCurrInstr = BattleScript_AbilityNoSpecificStatLoss;
gLastUsedAbility = gBattleMons[gActiveBank].ability;
RecordAbilityBattle(gActiveBank, gLastUsedAbility);
}
return STAT_CHANGE_DIDNT_WORK;
}
else if (gBattleMons[gActiveBank].ability == ABILITY_HYPER_CUTTER
&& !certain && statId == STAT_STAGE_ATK)
{
if (flags == STAT_CHANGE_BS_PTR)
{
BattleScriptPush(BS_ptr);
gBattleScripting.bank = gActiveBank;
gBattlescriptCurrInstr = BattleScript_AbilityNoSpecificStatLoss;
gLastUsedAbility = gBattleMons[gActiveBank].ability;
RecordAbilityBattle(gActiveBank, gLastUsedAbility);
}
return STAT_CHANGE_DIDNT_WORK;
}
else if (gBattleMons[gActiveBank].ability == ABILITY_SHIELD_DUST && flags == 0)
{
return STAT_CHANGE_DIDNT_WORK;
}
else // try to decrease
{
statValue = -GET_STAT_BUFF_VALUE(statValue);
gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN;
index = 1;
if (statValue == -2)
{
gBattleTextBuff2[1] = B_BUFF_STRING;
2017-11-26 11:55:17 +01:00
gBattleTextBuff2[2] = STRINGID_STATHARSHLY;
gBattleTextBuff2[3] = STRINGID_STATHARSHLY >> 8;
2017-09-26 22:39:59 +02:00
index = 4;
}
gBattleTextBuff2[index] = B_BUFF_STRING;
index++;
2017-11-26 11:55:17 +01:00
gBattleTextBuff2[index] = STRINGID_STATFELL;
2017-09-26 22:39:59 +02:00
index++;
2017-11-26 11:55:17 +01:00
gBattleTextBuff2[index] = STRINGID_STATFELL >> 8;
2017-09-26 22:39:59 +02:00
index++;
gBattleTextBuff2[index] = B_BUFF_EOS;
if (gBattleMons[gActiveBank].statStages[statId] == 0)
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
else
gBattleCommunication[MULTISTRING_CHOOSER] = (gBankTarget == gActiveBank);
}
}
else // stat increase
{
statValue = GET_STAT_BUFF_VALUE(statValue);
gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN;
index = 1;
if (statValue == 2)
{
gBattleTextBuff2[1] = B_BUFF_STRING;
2017-11-26 11:55:17 +01:00
gBattleTextBuff2[2] = STRINGID_STATSHARPLY;
gBattleTextBuff2[3] = STRINGID_STATSHARPLY >> 8;
2017-09-26 22:39:59 +02:00
index = 4;
}
gBattleTextBuff2[index] = B_BUFF_STRING;
index++;
2017-11-26 11:55:17 +01:00
gBattleTextBuff2[index] = STRINGID_STATROSE;
2017-09-26 22:39:59 +02:00
index++;
2017-11-26 11:55:17 +01:00
gBattleTextBuff2[index] = STRINGID_STATROSE >> 8;
2017-09-26 22:39:59 +02:00
index++;
gBattleTextBuff2[index] = B_BUFF_EOS;
if (gBattleMons[gActiveBank].statStages[statId] == 0xC)
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
else
gBattleCommunication[MULTISTRING_CHOOSER] = (gBankTarget == gActiveBank);
}
gBattleMons[gActiveBank].statStages[statId] += statValue;
if (gBattleMons[gActiveBank].statStages[statId] < 0)
gBattleMons[gActiveBank].statStages[statId] = 0;
if (gBattleMons[gActiveBank].statStages[statId] > 0xC)
gBattleMons[gActiveBank].statStages[statId] = 0xC;
if (gBattleCommunication[MULTISTRING_CHOOSER] == 2 && flags & STAT_CHANGE_BS_PTR)
gBattleMoveFlags |= MOVESTATUS_MISSED;
if (gBattleCommunication[MULTISTRING_CHOOSER] == 2 && !(flags & STAT_CHANGE_BS_PTR))
return STAT_CHANGE_DIDNT_WORK;
return STAT_CHANGE_WORKED;
}
2017-09-28 15:34:21 +02:00
static void atk89_statbuffchange(void)
2017-09-26 22:39:59 +02:00
{
const u8* jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
2017-09-28 15:34:21 +02:00
if (ChangeStatBuffs(gBattleScripting.statChanger & 0xF0, GET_STAT_BUFF_ID(gBattleScripting.statChanger), gBattlescriptCurrInstr[1], jumpPtr) == STAT_CHANGE_WORKED)
2017-09-26 22:39:59 +02:00
gBattlescriptCurrInstr += 6;
}
2017-09-28 15:34:21 +02:00
static void atk8A_normalisebuffs(void) // haze
2017-09-26 22:39:59 +02:00
{
s32 i, j;
for (i = 0; i < gNoOfAllBanks; i++)
{
for (j = 0; j < BATTLE_STATS_NO; j++)
gBattleMons[i].statStages[j] = 6;
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atk8B_setbide(void)
2017-09-26 22:39:59 +02:00
{
gBattleMons[gBankAttacker].status2 |= STATUS2_MULTIPLETURNS;
gLockedMoves[gBankAttacker] = gCurrentMove;
gTakenDmg[gBankAttacker] = 0;
gBattleMons[gBankAttacker].status2 |= (STATUS2_BIDE - 0x100); // 2 turns
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atk8C_confuseifrepeatingattackends(void)
2017-09-26 22:39:59 +02:00
{
if (!(gBattleMons[gBankAttacker].status2 & STATUS2_LOCK_CONFUSE))
gBattleCommunication[MOVE_EFFECT_BYTE] = (MOVE_EFFECT_THRASH | MOVE_EFFECT_AFFECTS_USER);
gBattlescriptCurrInstr++;
}
static void atk8D_setmultihitcounter(void)
2017-09-26 22:39:59 +02:00
{
2017-09-28 15:34:21 +02:00
if (gBattlescriptCurrInstr[1])
2017-09-26 22:39:59 +02:00
{
2017-09-28 15:34:21 +02:00
gMultiHitCounter = gBattlescriptCurrInstr[1];
2017-09-26 22:39:59 +02:00
}
else
{
gMultiHitCounter = Random() & 3;
if (gMultiHitCounter > 1)
gMultiHitCounter = (Random() & 3) + 2;
else
gMultiHitCounter += 2;
}
gBattlescriptCurrInstr += 2;
}
static void atk8E_initmultihitstring(void)
2017-09-26 22:39:59 +02:00
{
PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0)
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static bool8 sub_8051064(void)
2017-09-26 22:39:59 +02:00
{
if (gBattleMons[gBankAttacker].level >= gBattleMons[gBankTarget].level)
{
*(gBattleStruct->field_58 + gBankTarget) = gBattlePartyID[gBankTarget];
}
else
{
u16 random = Random() & 0xFF;
if ((u32)((random * (gBattleMons[gBankAttacker].level + gBattleMons[gBankTarget].level) >> 8) + 1) <= (gBattleMons[gBankTarget].level / 4))
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
return FALSE;
}
*(gBattleStruct->field_58 + gBankTarget) = gBattlePartyID[gBankTarget];
}
gBattlescriptCurrInstr = BattleScript_82DADD8;
2017-09-26 22:39:59 +02:00
return TRUE;
}
2017-09-28 15:34:21 +02:00
static void atk8F_forcerandomswitch(void)
2017-09-26 22:39:59 +02:00
{
s32 i;
s32 bank1PartyId = 0;
s32 bank2PartyId = 0;
#ifdef NONMATCHING
s32 lastMonId = 0; // + 1
#else
register s32 lastMonId asm("r8") = 0; // + 1
#endif // NONMATCHING
s32 firstMonId = 0;
s32 monsCount = 0;
struct Pokemon* party = NULL;
s32 validMons = 0;
s32 minNeeded = 0;
if ((gBattleTypeFlags & BATTLE_TYPE_TRAINER))
{
if (GetBankSide(gBankTarget) == SIDE_PLAYER)
party = gPlayerParty;
else
party = gEnemyParty;
if ((gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER && gBattleTypeFlags & BATTLE_TYPE_LINK)
|| (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER && gBattleTypeFlags & BATTLE_TYPE_x2000000)
|| (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER))
{
if ((gBankTarget & BIT_MON) != 0)
{
firstMonId = 3;
lastMonId = 6;
}
else
{
firstMonId = 0;
lastMonId = 3;
}
monsCount = 3;
minNeeded = 1;
bank2PartyId = gBattlePartyID[gBankTarget];
bank1PartyId = gBattlePartyID[gBankTarget ^ BIT_MON];
}
else if ((gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_LINK)
|| (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_x2000000))
{
2017-10-23 16:38:11 +02:00
if (sub_806D82C(GetBankMultiplayerId(gBankTarget)) == 1)
2017-09-26 22:39:59 +02:00
{
firstMonId = 3;
lastMonId = 6;
}
else
{
firstMonId = 0;
lastMonId = 3;
}
monsCount = 3;
minNeeded = 1;
bank2PartyId = gBattlePartyID[gBankTarget];
bank1PartyId = gBattlePartyID[gBankTarget ^ BIT_MON];
}
else if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
{
if (GetBankSide(gBankTarget) == SIDE_PLAYER)
{
firstMonId = 0;
lastMonId = 6;
monsCount = 6;
minNeeded = 2; // since there are two opponents, it has to be a double battle
}
else
{
if ((gBankTarget & BIT_MON) != 0)
{
firstMonId = 3;
lastMonId = 6;
}
else
{
firstMonId = 0;
lastMonId = 3;
}
monsCount = 3;
minNeeded = 1;
}
bank2PartyId = gBattlePartyID[gBankTarget];
bank1PartyId = gBattlePartyID[gBankTarget ^ BIT_MON];
}
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
firstMonId = 0;
lastMonId = 6;
monsCount = 6;
minNeeded = 2;
bank2PartyId = gBattlePartyID[gBankTarget];
bank1PartyId = gBattlePartyID[gBankTarget ^ BIT_MON];
}
else
{
firstMonId = 0;
lastMonId = 6;
monsCount = 6;
minNeeded = 1;
bank2PartyId = gBattlePartyID[gBankTarget]; // there is only one pokemon out in single battles
bank1PartyId = gBattlePartyID[gBankTarget];
}
for (i = firstMonId; i < lastMonId; i++)
{
if (GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE
&& !GetMonData(&party[i], MON_DATA_IS_EGG)
&& GetMonData(&party[i], MON_DATA_HP) != 0)
{
validMons++;
}
}
if (validMons <= minNeeded)
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
if (sub_8051064())
{
do
{
i = Random() % monsCount;
i += firstMonId;
}
while (i == bank2PartyId
|| i == bank1PartyId
|| GetMonData(&party[i], MON_DATA_SPECIES) == SPECIES_NONE
|| GetMonData(&party[i], MON_DATA_IS_EGG) == TRUE
|| GetMonData(&party[i], MON_DATA_HP) == 0);
}
2017-11-12 17:06:31 +01:00
*(gBattleStruct->monToSwitchIntoId + gBankTarget) = i;
2017-09-26 22:39:59 +02:00
if (!sub_81B1250())
sub_803BDA0(gBankTarget);
if ((gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER)
|| (gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & BATTLE_TYPE_MULTI)
|| (gBattleTypeFlags & BATTLE_TYPE_x2000000 && gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER)
|| (gBattleTypeFlags & BATTLE_TYPE_x2000000 && gBattleTypeFlags & BATTLE_TYPE_MULTI))
{
sub_81B8E80(gBankTarget, i, 0);
sub_81B8E80(gBankTarget ^ BIT_MON, i, 1);
}
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
sub_80571DC(gBankTarget, i);
}
}
else
{
sub_8051064();
}
}
static void atk90_tryconversiontypechange(void) // randomly changes user's type to one of its moves' type
2017-09-26 22:39:59 +02:00
{
u8 validMoves = 0;
u8 moveChecked;
u8 moveType;
while (validMoves < 4)
{
if (gBattleMons[gBankAttacker].moves[validMoves] == 0)
break;
validMoves++;
}
for (moveChecked = 0; moveChecked < validMoves; moveChecked++)
{
moveType = gBattleMoves[gBattleMons[gBankAttacker].moves[moveChecked]].type;
if (moveType == TYPE_MYSTERY)
{
if (gBattleMons[gBankAttacker].type1 == TYPE_GHOST || gBattleMons[gBankAttacker].type2 == TYPE_GHOST)
moveType = TYPE_GHOST;
else
moveType = TYPE_NORMAL;
}
if (moveType != gBattleMons[gBankAttacker].type1
&& moveType != gBattleMons[gBankAttacker].type2)
{
break;
}
}
if (moveChecked == validMoves)
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
do
{
while ((moveChecked = Random() & 3) >= validMoves);
moveType = gBattleMoves[gBattleMons[gBankAttacker].moves[moveChecked]].type;
if (moveType == TYPE_MYSTERY)
{
if (gBattleMons[gBankAttacker].type1 == TYPE_GHOST || gBattleMons[gBankAttacker].type2 == TYPE_GHOST)
moveType = TYPE_GHOST;
else
moveType = TYPE_NORMAL;
}
}
while (moveType == gBattleMons[gBankAttacker].type1 || moveType == gBattleMons[gBankAttacker].type2);
gBattleMons[gBankAttacker].type1 = moveType;
gBattleMons[gBankAttacker].type2 = moveType;
PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType)
gBattlescriptCurrInstr += 5;
}
}
2017-09-28 15:34:21 +02:00
static void atk91_givepaydaymoney(void)
2017-09-26 22:39:59 +02:00
{
if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)) && gPaydayMoney != 0)
{
u32 bonusMoney = gPaydayMoney * gBattleStruct->moneyMultiplier;
AddMoney(&gSaveBlock1Ptr->money, bonusMoney);
PREPARE_HWORD_NUMBER_BUFFER(gBattleTextBuff1, 5, bonusMoney)
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_PrintPayDayMoneyString;
}
else
{
gBattlescriptCurrInstr++;
}
}
2017-09-28 15:34:21 +02:00
static void atk92_setlightscreen(void)
2017-09-26 22:39:59 +02:00
{
if (gSideAffecting[GET_BANK_SIDE(gBankAttacker)] & SIDE_STATUS_LIGHTSCREEN)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
}
else
{
gSideAffecting[GET_BANK_SIDE(gBankAttacker)] |= SIDE_STATUS_LIGHTSCREEN;
gSideTimers[GET_BANK_SIDE(gBankAttacker)].lightscreenTimer = 5;
gSideTimers[GET_BANK_SIDE(gBankAttacker)].lightscreenBank = gBankAttacker;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && CountAliveMonsInBattle(BATTLE_ALIVE_ATK_SIDE) == 2)
gBattleCommunication[MULTISTRING_CHOOSER] = 4;
else
gBattleCommunication[MULTISTRING_CHOOSER] = 3;
}
gBattlescriptCurrInstr++;
}
static void atk93_tryKO(void)
2017-09-26 22:39:59 +02:00
{
u8 holdEffect, param;
if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY)
{
holdEffect = gEnigmaBerries[gBankTarget].holdEffect;
param = gEnigmaBerries[gBankTarget].holdEffectParam;
}
else
{
holdEffect = ItemId_GetHoldEffect(gBattleMons[gBankTarget].item);
param = ItemId_GetHoldEffectParam(gBattleMons[gBankTarget].item);
}
gStringBank = gBankTarget;
if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < param)
{
RecordItemEffectBattle(gBankTarget, HOLD_EFFECT_FOCUS_BAND);
gSpecialStatuses[gBankTarget].focusBanded = 1;
}
if (gBattleMons[gBankTarget].ability == ABILITY_STURDY)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
gLastUsedAbility = ABILITY_STURDY;
gBattlescriptCurrInstr = BattleScript_SturdyPreventsOHKO;
RecordAbilityBattle(gBankTarget, ABILITY_STURDY);
}
else
{
u16 chance;
if (!(gStatuses3[gBankTarget] & STATUS3_ALWAYS_HITS))
{
chance = gBattleMoves[gCurrentMove].accuracy + (gBattleMons[gBankAttacker].level - gBattleMons[gBankTarget].level);
if (Random() % 100 + 1 < chance && gBattleMons[gBankAttacker].level >= gBattleMons[gBankTarget].level)
chance = TRUE;
else
chance = FALSE;
}
else if (gDisableStructs[gBankTarget].bankWithSureHit == gBankAttacker
&& gBattleMons[gBankAttacker].level >= gBattleMons[gBankTarget].level)
{
chance = TRUE;
}
else
{
chance = gBattleMoves[gCurrentMove].accuracy + (gBattleMons[gBankAttacker].level - gBattleMons[gBankTarget].level);
if (Random() % 100 + 1 < chance && gBattleMons[gBankAttacker].level >= gBattleMons[gBankTarget].level)
chance = TRUE;
else
chance = FALSE;
}
if (chance)
{
if (gProtectStructs[gBankTarget].endured)
{
gBattleMoveDamage = gBattleMons[gBankTarget].hp - 1;
gBattleMoveFlags |= MOVESTATUS_ENDURED;
}
else if (gSpecialStatuses[gBankTarget].focusBanded)
{
gBattleMoveDamage = gBattleMons[gBankTarget].hp - 1;
gBattleMoveFlags |= MOVESTATUS_HUNGON;
gLastUsedItem = gBattleMons[gBankTarget].item;
}
else
{
gBattleMoveDamage = gBattleMons[gBankTarget].hp;
gBattleMoveFlags |= MOVESTATUS_ONEHITKO;
}
gBattlescriptCurrInstr += 5;
}
else
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
if (gBattleMons[gBankAttacker].level >= gBattleMons[gBankTarget].level)
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
else
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
}
2017-09-28 15:34:21 +02:00
static void atk94_damagetohalftargethp(void) // super fang
2017-09-26 22:39:59 +02:00
{
gBattleMoveDamage = gBattleMons[gBankTarget].hp / 2;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atk95_setsandstorm(void)
2017-09-26 22:39:59 +02:00
{
if (gBattleWeather & WEATHER_SANDSTORM_ANY)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
}
else
{
gBattleWeather = WEATHER_SANDSTORM_TEMPORARY;
gBattleCommunication[MULTISTRING_CHOOSER] = 3;
gWishFutureKnock.weatherDuration = 5;
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atk96_weatherdamage(void)
2017-09-26 22:39:59 +02:00
{
if (WEATHER_HAS_EFFECT)
{
if (gBattleWeather & WEATHER_SANDSTORM_ANY)
{
if (gBattleMons[gBankAttacker].type1 != TYPE_ROCK
&& gBattleMons[gBankAttacker].type1 != TYPE_STEEL
&& gBattleMons[gBankAttacker].type1 != TYPE_GROUND
&& gBattleMons[gBankAttacker].type2 != TYPE_ROCK
&& gBattleMons[gBankAttacker].type2 != TYPE_STEEL
&& gBattleMons[gBankAttacker].type2 != TYPE_GROUND
&& gBattleMons[gBankAttacker].ability != ABILITY_SAND_VEIL
&& !(gStatuses3[gBankAttacker] & STATUS3_UNDERGROUND)
&& !(gStatuses3[gBankAttacker] & STATUS3_UNDERWATER))
{
gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 16;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
}
else
{
gBattleMoveDamage = 0;
}
}
if (gBattleWeather & WEATHER_HAIL)
{
if (gBattleMons[gBankAttacker].type1 != TYPE_ICE
&& gBattleMons[gBankAttacker].type2 != TYPE_ICE
&& !(gStatuses3[gBankAttacker] & STATUS3_UNDERGROUND)
&& !(gStatuses3[gBankAttacker] & STATUS3_UNDERWATER))
{
gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 16;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
}
else
{
gBattleMoveDamage = 0;
}
}
}
else
{
gBattleMoveDamage = 0;
}
if (gAbsentBankFlags & gBitTable[gBankAttacker])
gBattleMoveDamage = 0;
gBattlescriptCurrInstr++;
}
static void atk97_tryinfatuating(void)
2017-09-26 22:39:59 +02:00
{
struct Pokemon *monAttacker, *monTarget;
u16 speciesAttacker, speciesTarget;
u32 personalityAttacker, personalityTarget;
if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
monAttacker = &gPlayerParty[gBattlePartyID[gBankAttacker]];
else
monAttacker = &gEnemyParty[gBattlePartyID[gBankAttacker]];
if (GetBankSide(gBankTarget) == SIDE_PLAYER)
monTarget = &gPlayerParty[gBattlePartyID[gBankTarget]];
else
monTarget = &gEnemyParty[gBattlePartyID[gBankTarget]];
speciesAttacker = GetMonData(monAttacker, MON_DATA_SPECIES);
personalityAttacker = GetMonData(monAttacker, MON_DATA_PERSONALITY);
speciesTarget = GetMonData(monTarget, MON_DATA_SPECIES);
personalityTarget = GetMonData(monTarget, MON_DATA_PERSONALITY);
if (gBattleMons[gBankTarget].ability == ABILITY_OBLIVIOUS)
{
gBattlescriptCurrInstr = BattleScript_ObliviousPreventsAttraction;
gLastUsedAbility = ABILITY_OBLIVIOUS;
RecordAbilityBattle(gBankTarget, ABILITY_OBLIVIOUS);
}
else
{
if (GetGenderFromSpeciesAndPersonality(speciesAttacker, personalityAttacker) == GetGenderFromSpeciesAndPersonality(speciesTarget, personalityTarget)
|| gBattleMons[gBankTarget].status2 & STATUS2_INFATUATION
|| GetGenderFromSpeciesAndPersonality(speciesAttacker, personalityAttacker) == MON_GENDERLESS
|| GetGenderFromSpeciesAndPersonality(speciesTarget, personalityTarget) == MON_GENDERLESS)
2017-09-27 23:43:45 +02:00
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
2017-09-26 22:39:59 +02:00
else
{
gBattleMons[gBankTarget].status2 |= STATUS2_INFATUATED_WITH(gBankAttacker);
gBattlescriptCurrInstr += 5;
}
}
}
static void atk98_updatestatusicon(void)
2017-09-26 22:39:59 +02:00
{
if (gBattleExecBuffer)
return;
2017-09-28 15:34:21 +02:00
if (gBattlescriptCurrInstr[1] != BS_ATTACKER_WITH_PARTNER)
2017-09-26 22:39:59 +02:00
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-26 22:39:59 +02:00
EmitStatusIconUpdate(0, gBattleMons[gActiveBank].status1, gBattleMons[gActiveBank].status2);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 2;
}
else
{
gActiveBank = gBankAttacker;
if (!(gAbsentBankFlags & gBitTable[gActiveBank]))
{
EmitStatusIconUpdate(0, gBattleMons[gActiveBank].status1, gBattleMons[gActiveBank].status2);
MarkBufferBankForExecution(gActiveBank);
}
if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
{
gActiveBank = GetBankByIdentity(GetBankIdentity(gBankAttacker) ^ BIT_MON);
if (!(gAbsentBankFlags & gBitTable[gActiveBank]))
{
EmitStatusIconUpdate(0, gBattleMons[gActiveBank].status1, gBattleMons[gActiveBank].status2);
MarkBufferBankForExecution(gActiveBank);
}
}
gBattlescriptCurrInstr += 2;
}
}
2017-09-28 15:34:21 +02:00
static void atk99_setmist(void)
2017-09-26 22:39:59 +02:00
{
if (gSideTimers[GET_BANK_SIDE(gBankAttacker)].mistTimer)
{
gBattleMoveFlags |= MOVESTATUS_FAILED;
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
}
else
{
gSideTimers[GET_BANK_SIDE(gBankAttacker)].mistTimer = 5;
gSideTimers[GET_BANK_SIDE(gBankAttacker)].mistBank = gBankAttacker;
gSideAffecting[GET_BANK_SIDE(gBankAttacker)] |= SIDE_STATUS_MIST;
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
}
gBattlescriptCurrInstr++;
}
static void atk9A_setfocusenergy(void)
2017-09-26 22:39:59 +02:00
{
if (gBattleMons[gBankAttacker].status2 & STATUS2_FOCUS_ENERGY)
{
gBattleMoveFlags |= MOVESTATUS_FAILED;
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
}
else
{
gBattleMons[gBankAttacker].status2 |= STATUS2_FOCUS_ENERGY;
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atk9B_transformdataexecution(void)
2017-09-26 22:39:59 +02:00
{
gLastUsedMove = 0xFFFF;
gBattlescriptCurrInstr++;
if (gBattleMons[gBankTarget].status2 & STATUS2_TRANSFORMED
|| gStatuses3[gBankTarget] & STATUS3_SEMI_INVULNERABLE)
{
gBattleMoveFlags |= MOVESTATUS_FAILED;
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
}
else
{
s32 i;
u8 *battleMonAttacker, *battleMonTarget;
gBattleMons[gBankAttacker].status2 |= STATUS2_TRANSFORMED;
gDisableStructs[gBankAttacker].disabledMove = 0;
gDisableStructs[gBankAttacker].disableTimer1 = 0;
gDisableStructs[gBankAttacker].transformedMonPersonality = gBattleMons[gBankTarget].personality;
2017-09-26 22:39:59 +02:00
gDisableStructs[gBankAttacker].unk18_b = 0;
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gBankTarget].species)
battleMonAttacker = (u8*)(&gBattleMons[gBankAttacker]);
battleMonTarget = (u8*)(&gBattleMons[gBankTarget]);
for (i = 0; i < offsetof(struct BattlePokemon, pp); i++)
battleMonAttacker[i] = battleMonTarget[i];
for (i = 0; i < 4; i++)
{
if (gBattleMoves[gBattleMons[gBankAttacker].moves[i]].pp < 5)
gBattleMons[gBankAttacker].pp[i] = gBattleMoves[gBattleMons[gBankAttacker].moves[i]].pp;
else
gBattleMons[gBankAttacker].pp[i] = 5;
}
gActiveBank = gBankAttacker;
EmitResetActionMoveSelection(0, RESET_MOVE_SELECTION);
MarkBufferBankForExecution(gActiveBank);
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
}
}
static void atk9C_setsubstitute(void)
2017-09-26 22:39:59 +02:00
{
u32 hp = gBattleMons[gBankAttacker].maxHP / 4;
if (gBattleMons[gBankAttacker].maxHP / 4 == 0)
hp = 1;
if (gBattleMons[gBankAttacker].hp <= hp)
{
gBattleMoveDamage = 0;
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
}
else
{
gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 4; // one bit value will only work for pokemon which max hp can go to 1020(which is more than possible in games)
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattleMons[gBankAttacker].status2 |= STATUS2_SUBSTITUTE;
gBattleMons[gBankAttacker].status2 &= ~(STATUS2_WRAPPED);
gDisableStructs[gBankAttacker].substituteHP = gBattleMoveDamage;
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE;
}
gBattlescriptCurrInstr++;
}
static bool8 IsMoveUncopyableByMimic(u16 move)
{
s32 i;
2017-09-28 16:51:24 +02:00
for (i = 0; sMovesForbiddenToCopy[i] != MIMIC_FORBIDDEN_END
&& sMovesForbiddenToCopy[i] != move; i++);
2017-09-26 22:39:59 +02:00
2017-09-28 16:51:24 +02:00
return (sMovesForbiddenToCopy[i] != MIMIC_FORBIDDEN_END);
2017-09-26 22:39:59 +02:00
}
2017-09-28 15:34:21 +02:00
static void atk9D_mimicattackcopy(void)
2017-09-26 22:39:59 +02:00
{
gLastUsedMove = 0xFFFF;
if (IsMoveUncopyableByMimic(gLastUsedMovesByBanks[gBankTarget])
|| gBattleMons[gBankAttacker].status2 & STATUS2_TRANSFORMED
|| gLastUsedMovesByBanks[gBankTarget] == 0
|| gLastUsedMovesByBanks[gBankTarget] == 0xFFFF)
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
s32 i;
for (i = 0; i < 4; i++)
{
if (gBattleMons[gBankAttacker].moves[i] == gLastUsedMovesByBanks[gBankTarget])
break;
}
if (i == 4)
{
gBattleMons[gBankAttacker].moves[gCurrMovePos] = gLastUsedMovesByBanks[gBankTarget];
if (gBattleMoves[gLastUsedMovesByBanks[gBankTarget]].pp < 5)
gBattleMons[gBankAttacker].pp[gCurrMovePos] = gBattleMoves[gLastUsedMovesByBanks[gBankTarget]].pp;
else
gBattleMons[gBankAttacker].pp[gCurrMovePos] = 5;
PREPARE_MOVE_BUFFER(gBattleTextBuff1, gLastUsedMovesByBanks[gBankTarget])
gDisableStructs[gBankAttacker].unk18_b |= gBitTable[gCurrMovePos];
gBattlescriptCurrInstr += 5;
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
}
2017-09-28 15:34:21 +02:00
static void atk9E_metronome(void)
2017-09-26 22:39:59 +02:00
{
while (1)
{
2017-11-11 22:58:23 +01:00
s32 i;
2017-09-26 22:39:59 +02:00
gCurrentMove = (Random() & 0x1FF) + 1;
if (gCurrentMove > LAST_MOVE_INDEX)
continue;
for (i = 0; i < 4; i++); // ?
2017-11-11 22:58:23 +01:00
i = -1;
while (1)
2017-09-26 22:39:59 +02:00
{
2017-11-11 22:58:23 +01:00
i++;
if (sMovesForbiddenToCopy[i] == gCurrentMove)
2017-09-26 22:39:59 +02:00
break;
2017-11-11 22:58:23 +01:00
if (sMovesForbiddenToCopy[i] == METRONOME_FORBIDDEN_END)
2017-09-26 22:39:59 +02:00
break;
}
2017-11-11 22:58:23 +01:00
if (sMovesForbiddenToCopy[i] == METRONOME_FORBIDDEN_END)
{
gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED);
gBattlescriptCurrInstr = gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect];
gBankTarget = GetMoveTarget(gCurrentMove, 0);
return;
}
2017-09-26 22:39:59 +02:00
}
}
2017-09-28 15:34:21 +02:00
static void atk9F_dmgtolevel(void)
2017-09-26 22:39:59 +02:00
{
gBattleMoveDamage = gBattleMons[gBankAttacker].level;
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkA0_psywavedamageeffect(void)
2017-09-26 22:39:59 +02:00
{
s32 randDamage;
while ((randDamage = (Random() & 0xF)) > 10);
randDamage *= 10;
gBattleMoveDamage = gBattleMons[gBankAttacker].level * (randDamage + 50) / 100;
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkA1_counterdamagecalculator(void)
2017-09-26 22:39:59 +02:00
{
u8 sideAttacker = GetBankSide(gBankAttacker);
u8 sideTarget = GetBankSide(gProtectStructs[gBankAttacker].physicalBank);
if (gProtectStructs[gBankAttacker].physicalDmg
&& sideAttacker != sideTarget
&& gBattleMons[gProtectStructs[gBankAttacker].physicalBank].hp)
{
gBattleMoveDamage = gProtectStructs[gBankAttacker].physicalDmg * 2;
if (gSideTimers[sideTarget].followmeTimer && gBattleMons[gSideTimers[sideTarget].followmeTarget].hp)
gBankTarget = gSideTimers[sideTarget].followmeTarget;
else
gBankTarget = gProtectStructs[gBankAttacker].physicalBank;
gBattlescriptCurrInstr += 5;
}
else
{
gSpecialStatuses[gBankAttacker].flag20 = 1;
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
2017-09-28 15:34:21 +02:00
static void atkA2_mirrorcoatdamagecalculator(void) // a copy of atkA1 with the physical -> special field changes
2017-09-26 22:39:59 +02:00
{
u8 sideAttacker = GetBankSide(gBankAttacker);
u8 sideTarget = GetBankSide(gProtectStructs[gBankAttacker].specialBank);
if (gProtectStructs[gBankAttacker].specialDmg && sideAttacker != sideTarget && gBattleMons[gProtectStructs[gBankAttacker].specialBank].hp)
{
gBattleMoveDamage = gProtectStructs[gBankAttacker].specialDmg * 2;
if (gSideTimers[sideTarget].followmeTimer && gBattleMons[gSideTimers[sideTarget].followmeTarget].hp)
gBankTarget = gSideTimers[sideTarget].followmeTarget;
else
gBankTarget = gProtectStructs[gBankAttacker].specialBank;
gBattlescriptCurrInstr += 5;
}
else
{
gSpecialStatuses[gBankAttacker].flag20 = 1;
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
2017-09-28 15:34:21 +02:00
static void atkA3_disablelastusedattack(void)
2017-09-26 22:39:59 +02:00
{
s32 i;
for (i = 0; i < 4; i++)
{
if (gBattleMons[gBankTarget].moves[i] == gLastUsedMovesByBanks[gBankTarget])
break;
}
if (gDisableStructs[gBankTarget].disabledMove == 0
&& i != 4 && gBattleMons[gBankTarget].pp[i] != 0)
{
PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleMons[gBankTarget].moves[i])
gDisableStructs[gBankTarget].disabledMove = gBattleMons[gBankTarget].moves[i];
gDisableStructs[gBankTarget].disableTimer1 = (Random() & 3) + 2;
gDisableStructs[gBankTarget].disableTimer2 = gDisableStructs[gBankTarget].disableTimer1; // used to save the random amount of turns?
gBattlescriptCurrInstr += 5;
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
static void atkA4_trysetencore(void)
2017-09-26 22:39:59 +02:00
{
s32 i;
for (i = 0; i < 4; i++)
{
if (gBattleMons[gBankTarget].moves[i] == gLastUsedMovesByBanks[gBankTarget])
break;
}
if (gLastUsedMovesByBanks[gBankTarget] == MOVE_STRUGGLE
|| gLastUsedMovesByBanks[gBankTarget] == MOVE_ENCORE
|| gLastUsedMovesByBanks[gBankTarget] == MOVE_MIRROR_MOVE)
{
i = 4;
}
if (gDisableStructs[gBankTarget].encoredMove == 0
&& i != 4 && gBattleMons[gBankTarget].pp[i] != 0)
{
gDisableStructs[gBankTarget].encoredMove = gBattleMons[gBankTarget].moves[i];
gDisableStructs[gBankTarget].encoredMovePos = i;
gDisableStructs[gBankTarget].encoreTimer1 = (Random() & 3) + 3;
gDisableStructs[gBankTarget].encoreTimer2 = gDisableStructs[gBankTarget].encoreTimer1;
gBattlescriptCurrInstr += 5;
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
2017-09-28 15:34:21 +02:00
static void atkA5_painsplitdmgcalc(void)
2017-09-26 22:39:59 +02:00
{
if (!(gBattleMons[gBankTarget].status2 & STATUS2_SUBSTITUTE))
{
s32 hpDiff = (gBattleMons[gBankAttacker].hp + gBattleMons[gBankTarget].hp) / 2;
s32 painSplitHp = gBattleMoveDamage = gBattleMons[gBankTarget].hp - hpDiff;
u8* storeLoc = (void*)(&gBattleScripting.painSplitHp);
storeLoc[0] = (painSplitHp);
storeLoc[1] = (painSplitHp & 0x0000FF00) >> 8;
storeLoc[2] = (painSplitHp & 0x00FF0000) >> 16;
storeLoc[3] = (painSplitHp & 0xFF000000) >> 24;
gBattleMoveDamage = gBattleMons[gBankAttacker].hp - hpDiff;
gSpecialStatuses[gBankTarget].moveturnLostHP = 0xFFFF;
gBattlescriptCurrInstr += 5;
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
2017-09-28 15:34:21 +02:00
static void atkA6_settypetorandomresistance(void) // conversion 2
2017-09-26 22:39:59 +02:00
{
if (gUnknown_02024250[gBankAttacker] == 0
|| gUnknown_02024250[gBankAttacker] == 0xFFFF)
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else if (IsTwoTurnsMove(gUnknown_02024250[gBankAttacker])
&& gBattleMons[gUnknown_02024270[gBankAttacker]].status2 & STATUS2_MULTIPLETURNS)
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
s32 i, j, rands;
for (rands = 0; rands < 1000; rands++)
2017-09-26 22:39:59 +02:00
{
while (((i = (Random() & 0x7F)) > sizeof(gTypeEffectiveness) / 3));
2017-09-26 22:39:59 +02:00
i *= 3;
2017-09-26 22:39:59 +02:00
if (TYPE_EFFECT_ATK_TYPE(i) == gUnknown_02024258[gBankAttacker]
&& TYPE_EFFECT_MULTIPLIER(i) <= TYPE_MUL_NOT_EFFECTIVE
&& gBattleMons[gBankAttacker].type1 != TYPE_EFFECT_DEF_TYPE(i)
&& gBattleMons[gBankAttacker].type2 != TYPE_EFFECT_DEF_TYPE(i))
2017-09-26 22:39:59 +02:00
{
gBattleMons[gBankAttacker].type1 = TYPE_EFFECT_DEF_TYPE(i);
gBattleMons[gBankAttacker].type2 = TYPE_EFFECT_DEF_TYPE(i);
2017-09-26 22:39:59 +02:00
PREPARE_TYPE_BUFFER(gBattleTextBuff1, TYPE_EFFECT_DEF_TYPE(i))
2017-09-26 22:39:59 +02:00
gBattlescriptCurrInstr += 5;
return;
}
}
2017-09-26 22:39:59 +02:00
for (j = 0, rands = 0; rands < sizeof(gTypeEffectiveness); j += 3, rands += 3)
2017-09-26 22:39:59 +02:00
{
switch (TYPE_EFFECT_ATK_TYPE(j))
2017-09-26 22:39:59 +02:00
{
case TYPE_ENDTABLE:
case TYPE_FORESIGHT:
break;
default:
if (TYPE_EFFECT_ATK_TYPE(j) == gUnknown_02024258[gBankAttacker]
&& TYPE_EFFECT_MULTIPLIER(j) <= 5
&& gBattleMons[gBankAttacker].type1 != TYPE_EFFECT_DEF_TYPE(i)
&& gBattleMons[gBankAttacker].type2 != TYPE_EFFECT_DEF_TYPE(i))
2017-09-26 22:39:59 +02:00
{
gBattleMons[gBankAttacker].type1 = TYPE_EFFECT_DEF_TYPE(rands);
gBattleMons[gBankAttacker].type2 = TYPE_EFFECT_DEF_TYPE(rands);
2017-09-26 22:39:59 +02:00
PREPARE_TYPE_BUFFER(gBattleTextBuff1, TYPE_EFFECT_DEF_TYPE(rands))
2017-09-26 22:39:59 +02:00
gBattlescriptCurrInstr += 5;
return;
}
break;
2017-09-26 22:39:59 +02:00
}
}
2017-09-26 22:39:59 +02:00
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
2017-09-28 15:34:21 +02:00
static void atkA7_setalwayshitflag(void)
2017-09-26 22:39:59 +02:00
{
gStatuses3[gBankTarget] &= ~(STATUS3_ALWAYS_HITS);
gStatuses3[gBankTarget] |= 0x10;
gDisableStructs[gBankTarget].bankWithSureHit = gBankAttacker;
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkA8_copymovepermanently(void) // sketch
2017-09-26 22:39:59 +02:00
{
gLastUsedMove = 0xFFFF;
if (!(gBattleMons[gBankAttacker].status2 & STATUS2_TRANSFORMED)
&& gUnknownMovesUsedByBanks[gBankTarget] != MOVE_STRUGGLE
&& gUnknownMovesUsedByBanks[gBankTarget] != 0
&& gUnknownMovesUsedByBanks[gBankTarget] != 0xFFFF
&& gUnknownMovesUsedByBanks[gBankTarget] != MOVE_SKETCH)
{
s32 i;
for (i = 0; i < 4; i++)
{
if (gBattleMons[gBankAttacker].moves[i] == MOVE_SKETCH)
continue;
if (gBattleMons[gBankAttacker].moves[i] == gUnknownMovesUsedByBanks[gBankTarget])
break;
}
if (i != 4)
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else // sketch worked
{
struct MovePpInfo movePpData;
gBattleMons[gBankAttacker].moves[gCurrMovePos] = gUnknownMovesUsedByBanks[gBankTarget];
gBattleMons[gBankAttacker].pp[gCurrMovePos] = gBattleMoves[gUnknownMovesUsedByBanks[gBankTarget]].pp;
gActiveBank = gBankAttacker;
for (i = 0; i < 4; i++)
{
movePpData.moves[i] = gBattleMons[gBankAttacker].moves[i];
2017-09-26 22:39:59 +02:00
movePpData.pp[i] = gBattleMons[gBankAttacker].pp[i];
}
movePpData.ppBonuses = gBattleMons[gBankAttacker].ppBonuses;
EmitSetMonData(0, REQUEST_MOVES_PP_BATTLE, 0, sizeof(struct MovePpInfo), &movePpData);
MarkBufferBankForExecution(gActiveBank);
PREPARE_MOVE_BUFFER(gBattleTextBuff1, gUnknownMovesUsedByBanks[gBankTarget])
gBattlescriptCurrInstr += 5;
}
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
2017-09-28 15:34:21 +02:00
static bool8 IsTwoTurnsMove(u16 move)
2017-09-27 23:43:45 +02:00
{
if (gBattleMoves[move].effect == EFFECT_SKULL_BASH
|| gBattleMoves[move].effect == EFFECT_RAZOR_WIND
|| gBattleMoves[move].effect == EFFECT_SKY_ATTACK
|| gBattleMoves[move].effect == EFFECT_SOLARBEAM
|| gBattleMoves[move].effect == EFFECT_SEMI_INVULNERABLE
2017-09-27 23:43:45 +02:00
|| gBattleMoves[move].effect == EFFECT_BIDE)
return TRUE;
else
return FALSE;
}
static bool8 IsInvalidForSleepTalkOrAssist(u16 move)
{
if (move == 0 || move == MOVE_SLEEP_TALK || move == MOVE_ASSIST
|| move == MOVE_MIRROR_MOVE || move == MOVE_METRONOME)
return TRUE;
else
return FALSE;
}
2017-09-28 15:34:21 +02:00
static u8 AttacksThisTurn(u8 bank, u16 move) // Note: returns 1 if it's a charging turn, otherwise 2
2017-09-27 23:43:45 +02:00
{
// first argument is unused
if (gBattleMoves[move].effect == EFFECT_SOLARBEAM
&& (gBattleWeather & WEATHER_SUN_ANY))
return 2;
if (gBattleMoves[move].effect == EFFECT_SKULL_BASH
|| gBattleMoves[move].effect == EFFECT_RAZOR_WIND
|| gBattleMoves[move].effect == EFFECT_SKY_ATTACK
|| gBattleMoves[move].effect == EFFECT_SOLARBEAM
|| gBattleMoves[move].effect == EFFECT_SEMI_INVULNERABLE
2017-09-27 23:43:45 +02:00
|| gBattleMoves[move].effect == EFFECT_BIDE)
{
if ((gHitMarker & HITMARKER_x8000000))
return 1;
}
return 2;
}
2017-11-26 01:19:57 +01:00
static void atkA9_trychoosesleeptalkmove(void)
2017-09-27 23:43:45 +02:00
{
s32 i;
u8 unusableMovesBits = 0;
for (i = 0; i < 4; i++)
{
if (IsInvalidForSleepTalkOrAssist(gBattleMons[gBankAttacker].moves[i])
|| gBattleMons[gBankAttacker].moves[i] == MOVE_FOCUS_PUNCH
|| gBattleMons[gBankAttacker].moves[i] == MOVE_UPROAR
|| IsTwoTurnsMove(gBattleMons[gBankAttacker].moves[i]))
{
unusableMovesBits |= gBitTable[i];
}
}
unusableMovesBits = CheckMoveLimitations(gBankAttacker, unusableMovesBits, ~(MOVE_LIMITATION_PP));
if (unusableMovesBits == 0xF) // all 4 moves cannot be chosen
{
gBattlescriptCurrInstr += 5;
}
else // at least one move can be chosen
{
u32 movePosition;
do
{
movePosition = Random() & 3;
} while ((gBitTable[movePosition] & unusableMovesBits));
gRandomMove = gBattleMons[gBankAttacker].moves[movePosition];
gCurrMovePos = movePosition;
gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED);
gBankTarget = GetMoveTarget(gRandomMove, 0);
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
static void atkAA_setdestinybond(void)
2017-09-27 23:43:45 +02:00
{
gBattleMons[gBankAttacker].status2 |= STATUS2_DESTINY_BOND;
gBattlescriptCurrInstr++;
}
static void TrySetDestinyBondToHappen(void)
2017-09-27 23:43:45 +02:00
{
u8 sideAttacker = GetBankSide(gBankAttacker);
u8 sideTarget = GetBankSide(gBankTarget);
if (gBattleMons[gBankTarget].status2 & STATUS2_DESTINY_BOND
&& sideAttacker != sideTarget
&& !(gHitMarker & HITMARKER_GRUDGE))
{
gHitMarker |= HITMARKER_DESTINYBOND;
}
}
static void atkAB_trysetdestinybondtohappen(void)
2017-09-27 23:43:45 +02:00
{
TrySetDestinyBondToHappen();
2017-09-27 23:43:45 +02:00
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkAC_remaininghptopower(void)
2017-09-27 23:43:45 +02:00
{
s32 i;
s32 hpFraction = GetScaledHPFraction(gBattleMons[gBankAttacker].hp, gBattleMons[gBankAttacker].maxHP, 48);
for (i = 0; i < (s32) sizeof(sFlailHpScaleToPowerTable); i += 2)
{
if (hpFraction <= sFlailHpScaleToPowerTable[i])
break;
}
gDynamicBasePower = sFlailHpScaleToPowerTable[i + 1];
gBattlescriptCurrInstr++;
}
static void atkAD_tryspiteppreduce(void)
2017-09-27 23:43:45 +02:00
{
if (gLastUsedMovesByBanks[gBankTarget] != 0
&& gLastUsedMovesByBanks[gBankTarget] != 0xFFFF)
{
s32 i;
for (i = 0; i < 4; i++)
{
if (gLastUsedMovesByBanks[gBankTarget] == gBattleMons[gBankTarget].moves[i])
break;
}
if (i != 4 && gBattleMons[gBankTarget].pp[i] > 1)
{
s32 ppToDeduct = (Random() & 3) + 2;
if (gBattleMons[gBankTarget].pp[i] < ppToDeduct)
ppToDeduct = gBattleMons[gBankTarget].pp[i];
PREPARE_MOVE_BUFFER(gBattleTextBuff1, gLastUsedMovesByBanks[gBankTarget])
ConvertIntToDecimalStringN(gBattleTextBuff2, ppToDeduct, 0, 1);
PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff2, 1, ppToDeduct)
gBattleMons[gBankTarget].pp[i] -= ppToDeduct;
gActiveBank = gBankTarget;
if (!(gDisableStructs[gActiveBank].unk18_b & gBitTable[i])
&& !(gBattleMons[gActiveBank].status2 & STATUS2_TRANSFORMED))
{
EmitSetMonData(0, REQUEST_PPMOVE1_BATTLE + i, 0, 1, &gBattleMons[gActiveBank].pp[i]);
MarkBufferBankForExecution(gActiveBank);
}
gBattlescriptCurrInstr += 5;
if (gBattleMons[gBankTarget].pp[i] == 0)
CancelMultiTurnMoves(gBankTarget);
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
static void atkAE_healpartystatus(void)
2017-09-27 23:43:45 +02:00
{
u32 zero = 0;
u8 toHeal = 0;
if (gCurrentMove == MOVE_HEAL_BELL)
{
struct Pokemon* party;
s32 i;
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
party = gPlayerParty;
else
party = gEnemyParty;
if (gBattleMons[gBankAttacker].ability != ABILITY_SOUNDPROOF)
{
gBattleMons[gBankAttacker].status1 = 0;
gBattleMons[gBankAttacker].status2 &= ~(STATUS2_NIGHTMARE);
}
else
{
RecordAbilityBattle(gBankAttacker, gBattleMons[gBankAttacker].ability);
gBattleCommunication[MULTISTRING_CHOOSER] |= 1;
}
gActiveBank = gBattleScripting.bank = GetBankByIdentity(GetBankIdentity(gBankAttacker) ^ BIT_MON);
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
&& !(gAbsentBankFlags & gBitTable[gActiveBank]))
{
if (gBattleMons[gActiveBank].ability != ABILITY_SOUNDPROOF)
{
gBattleMons[gActiveBank].status1 = 0;
gBattleMons[gActiveBank].status2 &= ~(STATUS2_NIGHTMARE);
}
else
{
RecordAbilityBattle(gActiveBank, gBattleMons[gActiveBank].ability);
gBattleCommunication[MULTISTRING_CHOOSER] |= 2;
}
}
for (i = 0; i < 6; i++)
{
u16 species = GetMonData(&party[i], MON_DATA_SPECIES2);
u8 abilityBit = GetMonData(&party[i], MON_DATA_ALT_ABILITY);
if (species != 0 && species != SPECIES_EGG)
{
u8 ability;
if (gBattlePartyID[gBankAttacker] == i)
ability = gBattleMons[gBankAttacker].ability;
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
&& gBattlePartyID[gActiveBank] == i
&& !(gAbsentBankFlags & gBitTable[gActiveBank]))
ability = gBattleMons[gActiveBank].ability;
else
ability = GetAbilityBySpecies(species, abilityBit);
if (ability != ABILITY_SOUNDPROOF)
toHeal |= (1 << i);
}
}
}
else // Aromatherapy
{
gBattleCommunication[MULTISTRING_CHOOSER] = 4;
toHeal = 0x3F;
gBattleMons[gBankAttacker].status1 = 0;
gBattleMons[gBankAttacker].status2 &= ~(STATUS2_NIGHTMARE);
gActiveBank = GetBankByIdentity(GetBankIdentity(gBankAttacker) ^ 2);
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
&& !(gAbsentBankFlags & gBitTable[gActiveBank]))
{
gBattleMons[gActiveBank].status1 = 0;
gBattleMons[gActiveBank].status2 &= ~(STATUS2_NIGHTMARE);
}
}
if (toHeal)
{
gActiveBank = gBankAttacker;
EmitSetMonData(0, REQUEST_STATUS_BATTLE, toHeal, 4, &zero);
MarkBufferBankForExecution(gActiveBank);
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkAF_cursetarget(void)
2017-09-27 23:43:45 +02:00
{
if (gBattleMons[gBankTarget].status2 & STATUS2_CURSED)
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
gBattleMons[gBankTarget].status2 |= STATUS2_CURSED;
gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 2;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattlescriptCurrInstr += 5;
}
}
static void atkB0_trysetspikes(void)
2017-09-27 23:43:45 +02:00
{
u8 targetSide = GetBankSide(gBankAttacker) ^ BIT_SIDE;
if (gSideTimers[targetSide].spikesAmount == 3)
{
gSpecialStatuses[gBankAttacker].flag20 = 1;
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
gSideAffecting[targetSide] |= SIDE_STATUS_SPIKES;
gSideTimers[targetSide].spikesAmount++;
gBattlescriptCurrInstr += 5;
}
}
static void atkB1_setforesight(void)
2017-09-27 23:43:45 +02:00
{
gBattleMons[gBankTarget].status2 |= STATUS2_FORESIGHT;
gBattlescriptCurrInstr++;
}
static void atkB2_trysetperishsong(void)
2017-09-27 23:43:45 +02:00
{
s32 i;
s32 notAffectedCount = 0;
for (i = 0; i < gNoOfAllBanks; i++)
{
if (gStatuses3[i] & STATUS3_PERISH_SONG
|| gBattleMons[i].ability == ABILITY_SOUNDPROOF)
{
notAffectedCount++;
}
else
{
gStatuses3[i] |= STATUS3_PERISH_SONG;
2017-11-12 17:11:06 +01:00
gDisableStructs[i].perishSongTimer1 = 3;
gDisableStructs[i].perishSongTimer2 = 3;
2017-09-27 23:43:45 +02:00
}
}
PressurePPLoseOnUsingPerishSong(gBankAttacker);
if (notAffectedCount == gNoOfAllBanks)
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
else
gBattlescriptCurrInstr += 5;
}
2017-09-28 15:34:21 +02:00
static void atkB3_rolloutdamagecalculation(void)
2017-09-27 23:43:45 +02:00
{
if (gBattleMoveFlags & MOVESTATUS_NOEFFECT)
{
CancelMultiTurnMoves(gBankAttacker);
gBattlescriptCurrInstr = BattleScript_MoveMissedPause;
2017-09-27 23:43:45 +02:00
}
else
{
s32 i;
if (!(gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS)) // first hit
{
2017-10-06 17:06:45 +02:00
gDisableStructs[gBankAttacker].rolloutCounter1 = 5;
gDisableStructs[gBankAttacker].rolloutCounter2 = 5;
2017-09-27 23:43:45 +02:00
gBattleMons[gBankAttacker].status2 |= STATUS2_MULTIPLETURNS;
gLockedMoves[gBankAttacker] = gCurrentMove;
}
2017-10-06 17:06:45 +02:00
if (--gDisableStructs[gBankAttacker].rolloutCounter1 == 0) // last hit
2017-09-27 23:43:45 +02:00
{
gBattleMons[gBankAttacker].status2 &= ~(STATUS2_MULTIPLETURNS);
}
gDynamicBasePower = gBattleMoves[gCurrentMove].power;
2017-10-06 17:06:45 +02:00
for (i = 1; i < (5 - gDisableStructs[gBankAttacker].rolloutCounter1); i++)
2017-09-27 23:43:45 +02:00
gDynamicBasePower *= 2;
if (gBattleMons[gBankAttacker].status2 & STATUS2_DEFENSE_CURL)
gDynamicBasePower *= 2;
gBattlescriptCurrInstr++;
}
}
2017-09-28 15:34:21 +02:00
static void atkB4_jumpifconfusedandstatmaxed(void)
2017-09-27 23:43:45 +02:00
{
if (gBattleMons[gBankTarget].status2 & STATUS2_CONFUSION
&& gBattleMons[gBankTarget].statStages[gBattlescriptCurrInstr[1]] == 0xC)
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
else
gBattlescriptCurrInstr += 6;
}
2017-09-28 15:34:21 +02:00
static void atkB5_furycuttercalc(void)
2017-09-27 23:43:45 +02:00
{
if (gBattleMoveFlags & MOVESTATUS_NOEFFECT)
{
gDisableStructs[gBankAttacker].furyCutterCounter = 0;
gBattlescriptCurrInstr = BattleScript_MoveMissedPause;
2017-09-27 23:43:45 +02:00
}
else
{
s32 i;
if (gDisableStructs[gBankAttacker].furyCutterCounter != 5)
gDisableStructs[gBankAttacker].furyCutterCounter++;
gDynamicBasePower = gBattleMoves[gCurrentMove].power;
for (i = 1; i < gDisableStructs[gBankAttacker].furyCutterCounter; i++)
gDynamicBasePower *= 2;
gBattlescriptCurrInstr++;
}
}
2017-09-28 15:34:21 +02:00
static void atkB6_happinesstodamagecalculation(void)
2017-09-27 23:43:45 +02:00
{
if (gBattleMoves[gCurrentMove].effect == EFFECT_RETURN)
gDynamicBasePower = 10 * (gBattleMons[gBankAttacker].friendship) / 25;
else // EFFECT_FRUSTRATION
gDynamicBasePower = 10 * (255 - gBattleMons[gBankAttacker].friendship) / 25;
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkB7_presentdamagecalculation(void)
2017-09-27 23:43:45 +02:00
{
s32 rand = Random() & 0xFF;
if (rand < 102)
gDynamicBasePower = 40;
else if (rand < 178)
gDynamicBasePower = 80;
else if (rand < 204)
gDynamicBasePower = 120;
else
{
gBattleMoveDamage = gBattleMons[gBankTarget].maxHP / 4;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattleMoveDamage *= -1;
}
if (rand < 204)
gBattlescriptCurrInstr = BattleScript_HitFromCritCalc;
2017-09-27 23:43:45 +02:00
else if (gBattleMons[gBankTarget].maxHP == gBattleMons[gBankTarget].hp)
gBattlescriptCurrInstr = BattleScript_AlreadyAtFullHp;
else
{
gBattleMoveFlags &= ~(MOVESTATUS_NOTAFFECTED);
gBattlescriptCurrInstr = BattleScript_PresentHealTarget;
}
}
static void atkB8_setsafeguard(void)
2017-09-27 23:43:45 +02:00
{
if (gSideAffecting[GET_BANK_SIDE(gBankAttacker)] & SIDE_STATUS_SAFEGUARD)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
}
else
{
gSideAffecting[GET_BANK_SIDE(gBankAttacker)] |= SIDE_STATUS_SAFEGUARD;
gSideTimers[GET_BANK_SIDE(gBankAttacker)].safeguardTimer = 5;
gSideTimers[GET_BANK_SIDE(gBankAttacker)].safeguardBank = gBankAttacker;
gBattleCommunication[MULTISTRING_CHOOSER] = 5;
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkB9_magnitudedamagecalculation(void)
2017-09-27 23:43:45 +02:00
{
s32 magnitude = Random() % 100;
if (magnitude < 5)
{
gDynamicBasePower = 10;
magnitude = 4;
}
else if (magnitude < 15)
{
gDynamicBasePower = 30;
magnitude = 5;
}
else if (magnitude < 35)
{
gDynamicBasePower = 50;
magnitude = 6;
}
else if (magnitude < 65)
{
gDynamicBasePower = 70;
magnitude = 7;
}
else if (magnitude < 85)
{
gDynamicBasePower = 90;
magnitude = 8;
}
else if (magnitude < 95)
{
gDynamicBasePower = 110;
magnitude = 9;
}
else
{
gDynamicBasePower = 150;
magnitude = 10;
}
PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff1, 2, magnitude)
for (gBankTarget = 0; gBankTarget < gNoOfAllBanks; gBankTarget++)
{
if (gBankTarget == gBankAttacker)
continue;
if (!(gAbsentBankFlags & gBitTable[gBankTarget])) // a valid target was found
break;
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkBA_jumpifnopursuitswitchdmg(void)
2017-09-27 23:43:45 +02:00
{
if (gMultiHitCounter == 1)
{
if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
gBankTarget = GetBankByIdentity(IDENTITY_OPPONENT_MON1);
else
gBankTarget = GetBankByIdentity(IDENTITY_PLAYER_MON1);
}
else
{
if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
gBankTarget = GetBankByIdentity(IDENTITY_OPPONENT_MON2);
else
gBankTarget = GetBankByIdentity(IDENTITY_PLAYER_MON2);
}
if (gActionForBanks[gBankTarget] == 0
&& gBankAttacker == *(gBattleStruct->moveTarget + gBankTarget)
&& !(gBattleMons[gBankTarget].status1 & (STATUS_SLEEP | STATUS_FREEZE))
&& gBattleMons[gBankAttacker].hp
&& !gDisableStructs[gBankTarget].truantCounter
&& gChosenMovesByBanks[gBankTarget] == MOVE_PURSUIT)
{
s32 i;
for (i = 0; i < gNoOfAllBanks; i++)
{
2017-10-04 19:25:14 +02:00
if (gBanksByTurnOrder[i] == gBankTarget)
gActionsByTurnOrder[i] = 11;
2017-09-27 23:43:45 +02:00
}
gCurrentMove = MOVE_PURSUIT;
2017-10-06 00:12:01 +02:00
gCurrMovePos = gUnknown_020241E9 = *(gBattleStruct->chosenMovePositions + gBankTarget);
2017-09-27 23:43:45 +02:00
gBattlescriptCurrInstr += 5;
gBattleScripting.animTurn = 1;
gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED);
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
2017-09-28 15:34:21 +02:00
static void atkBB_setsunny(void)
2017-09-27 23:43:45 +02:00
{
if (gBattleWeather & WEATHER_SUN_ANY)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
}
else
{
gBattleWeather = WEATHER_SUN_TEMPORARY;
gBattleCommunication[MULTISTRING_CHOOSER] = 4;
gWishFutureKnock.weatherDuration = 5;
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkBC_maxattackhalvehp(void) // belly drum
2017-09-27 23:43:45 +02:00
{
u32 halfHp = gBattleMons[gBankAttacker].maxHP / 2;
if (!(gBattleMons[gBankAttacker].maxHP / 2))
halfHp = 1;
if (gBattleMons[gBankAttacker].statStages[STAT_STAGE_ATK] < 12
&& gBattleMons[gBankAttacker].hp > halfHp)
{
gBattleMons[gBankAttacker].statStages[STAT_STAGE_ATK] = 12;
gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 2;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattlescriptCurrInstr += 5;
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
2017-09-28 15:34:21 +02:00
static void atkBD_copyfoestats(void) // psych up
2017-09-27 23:43:45 +02:00
{
s32 i;
for (i = 0; i < BATTLE_STATS_NO; i++)
{
gBattleMons[gBankAttacker].statStages[i] = gBattleMons[gBankTarget].statStages[i];
}
gBattlescriptCurrInstr += 5; // Has an unused jump ptr(possibly for a failed attempt) parameter.
}
2017-09-28 15:34:21 +02:00
static void atkBE_rapidspinfree(void)
2017-09-27 23:43:45 +02:00
{
if (gBattleMons[gBankAttacker].status2 & STATUS2_WRAPPED)
{
gBattleScripting.bank = gBankTarget;
gBattleMons[gBankAttacker].status2 &= ~(STATUS2_WRAPPED);
gBankTarget = *(gBattleStruct->wrappedBy + gBankAttacker);
gBattleTextBuff1[0] = B_BUFF_PLACEHOLDER_BEGIN;
gBattleTextBuff1[1] = B_BUFF_MOVE;
gBattleTextBuff1[2] = *(gBattleStruct->wrappedMove + gBankAttacker * 2 + 0);
gBattleTextBuff1[3] = *(gBattleStruct->wrappedMove + gBankAttacker * 2 + 1);
gBattleTextBuff1[4] = B_BUFF_EOS;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_WrapFree;
}
else if (gStatuses3[gBankAttacker] & STATUS3_LEECHSEED)
{
gStatuses3[gBankAttacker] &= ~(STATUS3_LEECHSEED);
gStatuses3[gBankAttacker] &= ~(STATUS3_LEECHSEED_BANK);
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_LeechSeedFree;
}
else if (gSideAffecting[GetBankSide(gBankAttacker)] & SIDE_STATUS_SPIKES)
{
gSideAffecting[GetBankSide(gBankAttacker)] &= ~(SIDE_STATUS_SPIKES);
gSideTimers[GetBankSide(gBankAttacker)].spikesAmount = 0;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_SpikesFree;
}
else
{
gBattlescriptCurrInstr++;
}
}
static void atkBF_setdefensecurlbit(void)
2017-09-27 23:43:45 +02:00
{
gBattleMons[gBankAttacker].status2 |= STATUS2_DEFENSE_CURL;
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkC0_recoverbasedonsunlight(void)
2017-09-27 23:43:45 +02:00
{
gBankTarget = gBankAttacker;
if (gBattleMons[gBankAttacker].hp != gBattleMons[gBankAttacker].maxHP)
{
if (gBattleWeather == 0 || !WEATHER_HAS_EFFECT)
gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 2;
else if (gBattleWeather & WEATHER_SUN_ANY)
gBattleMoveDamage = 20 * gBattleMons[gBankAttacker].maxHP / 30;
else // not sunny weather
gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 4;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattleMoveDamage *= -1;
gBattlescriptCurrInstr += 5;
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
#ifdef NONMATCHING
static void atkC1_hiddenpowercalc(void)
2017-09-27 23:43:45 +02:00
{
2017-11-12 00:16:46 +01:00
u32 powerBits = 0;
u32 typeBits = 0;
2017-09-27 23:43:45 +02:00
2017-11-12 00:16:46 +01:00
powerBits |= ((gBattleMons[gBankAttacker].hpIV & 2) >> 1);
powerBits |= ((gBattleMons[gBankAttacker].attackIV & 2) << 0);
powerBits |= ((gBattleMons[gBankAttacker].defenseIV & 2) << 1);
powerBits |= ((gBattleMons[gBankAttacker].speedIV & 2) << 2);
powerBits |= ((gBattleMons[gBankAttacker].spAttackIV & 2) << 3);
powerBits |= ((gBattleMons[gBankAttacker].spDefenseIV & 2) << 4);
2017-09-27 23:43:45 +02:00
2017-11-12 00:16:46 +01:00
typeBits |= ((gBattleMons[gBankAttacker].hpIV & 1) << 0);
typeBits |= ((gBattleMons[gBankAttacker].attackIV & 1) << 1);
typeBits |= ((gBattleMons[gBankAttacker].defenseIV & 1) << 2);
typeBits |= ((gBattleMons[gBankAttacker].speedIV & 1) << 3);
typeBits |= ((gBattleMons[gBankAttacker].spAttackIV & 1) << 4);
typeBits |= ((gBattleMons[gBankAttacker].spDefenseIV & 1) << 5);
2017-09-27 23:43:45 +02:00
gDynamicBasePower = (40 * powerBits) / 63 + 30;
gBattleStruct->dynamicMoveType = (15 * typeBits) / 63 + 1;
if (gBattleStruct->dynamicMoveType > 8)
gBattleStruct->dynamicMoveType++;
gBattleStruct->dynamicMoveType |= 0xC0;
gBattlescriptCurrInstr++;
}
#else
__attribute__((naked))
static void atkC1_hiddenpowercalc(void)
2017-09-27 23:43:45 +02:00
{
asm(".syntax unified\n\
push {r4-r7,lr}\n\
mov r7, r10\n\
mov r6, r9\n\
mov r5, r8\n\
push {r5-r7}\n\
ldr r2, =gBattleMons\n\
ldr r0, =gBankAttacker\n\
ldrb r1, [r0]\n\
movs r0, 0x58\n\
adds r4, r1, 0\n\
muls r4, r0\n\
adds r4, r2\n\
ldrb r0, [r4, 0x14]\n\
mov r10, r0\n\
mov r7, r10\n\
lsls r7, 27\n\
adds r0, r7, 0\n\
lsrs r0, 27\n\
mov r10, r0\n\
movs r1, 0x2\n\
mov r2, r10\n\
ands r2, r1\n\
asrs r2, 1\n\
ldrh r7, [r4, 0x14]\n\
mov r9, r7\n\
mov r0, r9\n\
lsls r0, 22\n\
mov r9, r0\n\
lsrs r3, r0, 27\n\
adds r0, r1, 0\n\
ands r0, r3\n\
orrs r2, r0\n\
ldrb r7, [r4, 0x15]\n\
mov r8, r7\n\
mov r0, r8\n\
lsls r0, 25\n\
mov r8, r0\n\
lsrs r3, r0, 27\n\
adds r0, r1, 0\n\
ands r0, r3\n\
lsls r0, 1\n\
orrs r2, r0\n\
ldr r6, [r4, 0x14]\n\
lsls r6, 12\n\
lsrs r3, r6, 27\n\
adds r0, r1, 0\n\
ands r0, r3\n\
lsls r0, 2\n\
orrs r2, r0\n\
ldrh r5, [r4, 0x16]\n\
lsls r5, 23\n\
lsrs r3, r5, 27\n\
adds r0, r1, 0\n\
ands r0, r3\n\
lsls r0, 3\n\
orrs r2, r0\n\
ldrb r3, [r4, 0x17]\n\
lsls r3, 26\n\
lsrs r0, r3, 27\n\
ands r1, r0\n\
lsls r1, 4\n\
orrs r2, r1\n\
movs r1, 0x1\n\
adds r4, r1, 0\n\
mov r7, r10\n\
ands r4, r7\n\
mov r0, r9\n\
lsrs r0, 27\n\
mov r9, r0\n\
adds r0, r1, 0\n\
mov r7, r9\n\
ands r0, r7\n\
lsls r0, 1\n\
orrs r4, r0\n\
mov r0, r8\n\
lsrs r0, 27\n\
mov r8, r0\n\
adds r0, r1, 0\n\
mov r7, r8\n\
ands r0, r7\n\
lsls r0, 2\n\
orrs r4, r0\n\
lsrs r6, 27\n\
adds r0, r1, 0\n\
ands r0, r6\n\
lsls r0, 3\n\
orrs r4, r0\n\
lsrs r5, 27\n\
adds r0, r1, 0\n\
ands r0, r5\n\
lsls r0, 4\n\
orrs r4, r0\n\
lsrs r3, 27\n\
ands r1, r3\n\
lsls r1, 5\n\
orrs r4, r1\n\
ldr r5, =gDynamicBasePower\n\
lsls r0, r2, 2\n\
adds r0, r2\n\
lsls r0, 3\n\
movs r1, 0x3F\n\
bl __divsi3\n\
adds r0, 0x1E\n\
strh r0, [r5]\n\
ldr r6, =gBattleStruct\n\
ldr r5, [r6]\n\
lsls r0, r4, 4\n\
subs r0, r4\n\
movs r1, 0x3F\n\
bl __divsi3\n\
adds r0, 0x1\n\
strb r0, [r5, 0x13]\n\
ldr r1, [r6]\n\
ldrb r0, [r1, 0x13]\n\
cmp r0, 0x8\n\
bls _080544F0\n\
adds r0, 0x1\n\
strb r0, [r1, 0x13]\n\
_080544F0:\n\
ldr r2, [r6]\n\
ldrb r0, [r2, 0x13]\n\
movs r1, 0xC0\n\
orrs r0, r1\n\
strb r0, [r2, 0x13]\n\
ldr r1, =gBattlescriptCurrInstr\n\
ldr r0, [r1]\n\
adds r0, 0x1\n\
str r0, [r1]\n\
pop {r3-r5}\n\
mov r8, r3\n\
mov r9, r4\n\
mov r10, r5\n\
pop {r4-r7}\n\
pop {r0}\n\
bx r0\n\
.pool\n\
.syntax divided");
}
#endif // NONMATCHING
static void atkC2_selectfirstvalidtarget(void)
2017-09-27 23:43:45 +02:00
{
for (gBankTarget = 0; gBankTarget < gNoOfAllBanks; gBankTarget++)
{
if (gBankTarget == gBankAttacker)
continue;
if (!(gAbsentBankFlags & gBitTable[gBankTarget]))
break;
}
gBattlescriptCurrInstr++;
}
static void atkC3_trysetfutureattack(void)
2017-09-27 23:43:45 +02:00
{
if (gWishFutureKnock.futureSightCounter[gBankTarget] != 0)
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
gSideAffecting[GET_BANK_SIDE(gBankTarget)] |= SIDE_STATUS_FUTUREATTACK;
gWishFutureKnock.futureSightMove[gBankTarget] = gCurrentMove;
gWishFutureKnock.futureSightAttacker[gBankTarget] = gBankAttacker;
gWishFutureKnock.futureSightCounter[gBankTarget] = 3;
gWishFutureKnock.futureSightDmg[gBankTarget] = CalculateBaseDamage(&gBattleMons[gBankAttacker], &gBattleMons[gBankTarget], gCurrentMove,
gSideAffecting[GET_BANK_SIDE(gBankTarget)], 0,
0, gBankAttacker, gBankTarget);
if (gProtectStructs[gBankAttacker].helpingHand)
gWishFutureKnock.futureSightDmg[gBankTarget] = gWishFutureKnock.futureSightDmg[gBankTarget] * 15 / 10;
if (gCurrentMove == MOVE_DOOM_DESIRE)
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
else
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
gBattlescriptCurrInstr += 5;
}
}
static void atkC4_trydobeatup(void)
2017-09-27 23:43:45 +02:00
{
struct Pokemon *party;
2017-09-27 23:43:45 +02:00
if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
party = gPlayerParty;
else
party = gEnemyParty;
if (gBattleMons[gBankTarget].hp == 0)
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
u8 beforeLoop = gBattleCommunication[0];
for (;gBattleCommunication[0] < 6; gBattleCommunication[0]++)
{
if (GetMonData(&party[gBattleCommunication[0]], MON_DATA_HP)
&& GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES2)
&& GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES2) != SPECIES_EGG
&& !GetMonData(&party[gBattleCommunication[0]], MON_DATA_STATUS))
break;
}
if (gBattleCommunication[0] < 6)
{
PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBankAttacker, gBattleCommunication[0])
gBattlescriptCurrInstr += 9;
gBattleMoveDamage = gBaseStats[GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES)].baseAttack;
gBattleMoveDamage *= gBattleMoves[gCurrentMove].power;
gBattleMoveDamage *= (GetMonData(&party[gBattleCommunication[0]], MON_DATA_LEVEL) * 2 / 5 + 2);
gBattleMoveDamage /= gBaseStats[gBattleMons[gBankTarget].species].baseDefense;
gBattleMoveDamage = (gBattleMoveDamage / 50) + 2;
if (gProtectStructs[gBankAttacker].helpingHand)
gBattleMoveDamage = gBattleMoveDamage * 15 / 10;
gBattleCommunication[0]++;
}
else if (beforeLoop != 0)
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
else
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 5);
}
}
2017-09-28 15:34:21 +02:00
static void atkC5_setsemiinvulnerablebit(void)
2017-09-27 23:43:45 +02:00
{
switch (gCurrentMove)
{
case MOVE_FLY:
case MOVE_BOUNCE:
gStatuses3[gBankAttacker] |= STATUS3_ON_AIR;
break;
case MOVE_DIG:
gStatuses3[gBankAttacker] |= STATUS3_UNDERGROUND;
break;
case MOVE_DIVE:
gStatuses3[gBankAttacker] |= STATUS3_UNDERWATER;
break;
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkC6_clearsemiinvulnerablebit(void)
2017-09-27 23:43:45 +02:00
{
switch (gCurrentMove)
{
case MOVE_FLY:
case MOVE_BOUNCE:
gStatuses3[gBankAttacker] &= ~STATUS3_ON_AIR;
break;
case MOVE_DIG:
gStatuses3[gBankAttacker] &= ~STATUS3_UNDERGROUND;
break;
case MOVE_DIVE:
gStatuses3[gBankAttacker] &= ~STATUS3_UNDERWATER;
break;
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkC7_setminimize(void)
2017-09-27 23:43:45 +02:00
{
if (gHitMarker & HITMARKER_OBEYS)
gStatuses3[gBankAttacker] |= STATUS3_MINIMIZED;
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkC8_sethail(void)
2017-09-27 23:43:45 +02:00
{
if (gBattleWeather & WEATHER_HAIL_ANY)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
}
else
{
gBattleWeather = WEATHER_HAIL;
gBattleCommunication[MULTISTRING_CHOOSER] = 5;
gWishFutureKnock.weatherDuration = 5;
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkC9_jumpifattackandspecialattackcannotfall(void) // memento
2017-09-27 23:43:45 +02:00
{
if (gBattleMons[gBankTarget].statStages[STAT_STAGE_ATK] == 0
&& gBattleMons[gBankTarget].statStages[STAT_STAGE_SPATK] == 0
&& gBattleCommunication[6] != 1)
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
gActiveBank = gBankAttacker;
gBattleMoveDamage = gBattleMons[gActiveBank].hp;
2017-10-22 18:43:15 +02:00
EmitHealthBarUpdate(0, INSTANT_HP_BAR_DROP);
2017-09-27 23:43:45 +02:00
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 5;
}
}
2017-09-28 15:34:21 +02:00
static void atkCA_setforcedtarget(void) // follow me
2017-09-27 23:43:45 +02:00
{
gSideTimers[GetBankSide(gBankAttacker)].followmeTimer = 1;
gSideTimers[GetBankSide(gBankAttacker)].followmeTarget = gBankAttacker;
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkCB_setcharge(void)
2017-09-27 23:43:45 +02:00
{
gStatuses3[gBankAttacker] |= STATUS3_CHARGED_UP;
gDisableStructs[gBankAttacker].chargeTimer1 = 2;
gDisableStructs[gBankAttacker].chargeTimer2 = 2;
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkCC_callterrainattack(void) // nature power
2017-09-27 23:43:45 +02:00
{
gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED);
gCurrentMove = sNaturePowerMoves[gBattleTerrain];
gBankTarget = GetMoveTarget(gCurrentMove, 0);
BattleScriptPush(gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect]);
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkCD_cureifburnedparalysedorpoisoned(void) // refresh
2017-09-27 23:43:45 +02:00
{
if (gBattleMons[gBankAttacker].status1 & (STATUS_POISON | STATUS_BURN | STATUS_PARALYSIS | STATUS_TOXIC_POISON))
{
gBattleMons[gBankAttacker].status1 = 0;
gBattlescriptCurrInstr += 5;
gActiveBank = gBankAttacker;
EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1);
MarkBufferBankForExecution(gActiveBank);
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
2017-09-28 15:34:21 +02:00
static void atkCE_settorment(void)
2017-09-27 23:43:45 +02:00
{
if (gBattleMons[gBankTarget].status2 & STATUS2_TORMENT)
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
gBattleMons[gBankTarget].status2 |= STATUS2_TORMENT;
gBattlescriptCurrInstr += 5;
}
}
2017-09-28 15:34:21 +02:00
static void atkCF_jumpifnodamage(void)
2017-09-27 23:43:45 +02:00
{
if (gProtectStructs[gBankAttacker].physicalDmg || gProtectStructs[gBankAttacker].specialDmg)
gBattlescriptCurrInstr += 5;
else
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
2017-09-28 15:34:21 +02:00
static void atkD0_settaunt(void)
2017-09-27 23:43:45 +02:00
{
if (gDisableStructs[gBankTarget].tauntTimer1 == 0)
{
gDisableStructs[gBankTarget].tauntTimer1 = 2;
gDisableStructs[gBankTarget].tauntTimer2 = 2;
gBattlescriptCurrInstr += 5;
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
static void atkD1_trysethelpinghand(void)
2017-09-27 23:43:45 +02:00
{
gBankTarget = GetBankByIdentity(GetBankIdentity(gBankAttacker) ^ BIT_MON);
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
&& !(gAbsentBankFlags & gBitTable[gBankTarget])
&& !gProtectStructs[gBankAttacker].helpingHand
&& !gProtectStructs[gBankTarget].helpingHand)
{
gProtectStructs[gBankTarget].helpingHand = 1;
gBattlescriptCurrInstr += 5;
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
static void atkD2_tryswapitems(void) // trick
2017-09-27 23:43:45 +02:00
{
// opponent can't swap items with player in regular battles
if (gBattleTypeFlags & BATTLE_TYPE_x4000000
|| (GetBankSide(gBankAttacker) == SIDE_OPPONENT
&& !(gBattleTypeFlags & (BATTLE_TYPE_LINK
| BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_SECRET_BASE
| BATTLE_TYPE_x2000000))))
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
u8 sideAttacker = GetBankSide(gBankAttacker);
u8 sideTarget = GetBankSide(gBankTarget);
// 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
| BATTLE_TYPE_SECRET_BASE
| BATTLE_TYPE_x2000000))
&& (gWishFutureKnock.knockedOffPokes[sideAttacker] & gBitTable[gBattlePartyID[gBankAttacker]]
|| gWishFutureKnock.knockedOffPokes[sideTarget] & gBitTable[gBattlePartyID[gBankTarget]]))
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
// can't swap if two pokemon don't have an item
// or if either of them is an enigma berry or a mail
else if ((gBattleMons[gBankAttacker].item == 0 && gBattleMons[gBankTarget].item == 0)
|| gBattleMons[gBankAttacker].item == ITEM_ENIGMA_BERRY
|| gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY
|| IS_ITEM_MAIL(gBattleMons[gBankAttacker].item)
|| IS_ITEM_MAIL(gBattleMons[gBankTarget].item))
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
// check if ability prevents swapping
else if (gBattleMons[gBankTarget].ability == ABILITY_STICKY_HOLD)
{
gBattlescriptCurrInstr = BattleScript_StickyHoldActivates;
gLastUsedAbility = gBattleMons[gBankTarget].ability;
RecordAbilityBattle(gBankTarget, gLastUsedAbility);
}
// took a while, but all checks passed and items can be safely swapped
else
{
u16 oldItemAtk, *newItemAtk;
newItemAtk = &gBattleStruct->changedItems[gBankAttacker];
oldItemAtk = gBattleMons[gBankAttacker].item;
*newItemAtk = gBattleMons[gBankTarget].item;
gBattleMons[gBankAttacker].item = 0;
gBattleMons[gBankTarget].item = oldItemAtk;
gActiveBank = gBankAttacker;
EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, newItemAtk);
MarkBufferBankForExecution(gBankAttacker);
gActiveBank = gBankTarget;
EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gBattleMons[gBankTarget].item);
MarkBufferBankForExecution(gBankTarget);
*(u8*)((u8*)(&gBattleStruct->choicedMove[gBankTarget]) + 0) = 0;
*(u8*)((u8*)(&gBattleStruct->choicedMove[gBankTarget]) + 1) = 0;
*(u8*)((u8*)(&gBattleStruct->choicedMove[gBankAttacker]) + 0) = 0;
*(u8*)((u8*)(&gBattleStruct->choicedMove[gBankAttacker]) + 1) = 0;
gBattlescriptCurrInstr += 5;
PREPARE_ITEM_BUFFER(gBattleTextBuff1, *newItemAtk)
PREPARE_ITEM_BUFFER(gBattleTextBuff2, oldItemAtk)
if (oldItemAtk != 0 && *newItemAtk != 0)
gBattleCommunication[MULTISTRING_CHOOSER] = 2; // attacker's item -> <- target's item
else if (oldItemAtk == 0 && *newItemAtk != 0)
gBattleCommunication[MULTISTRING_CHOOSER] = 0; // nothing -> <- target's item
else
gBattleCommunication[MULTISTRING_CHOOSER] = 1; // attacker's item -> <- nothing
}
}
}
static void atkD3_trycopyability(void) // role play
2017-09-27 23:43:45 +02:00
{
if (gBattleMons[gBankTarget].ability != 0
&& gBattleMons[gBankTarget].ability != ABILITY_WONDER_GUARD)
{
gBattleMons[gBankAttacker].ability = gBattleMons[gBankTarget].ability;
gLastUsedAbility = gBattleMons[gBankTarget].ability;
gBattlescriptCurrInstr += 5;
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
static void atkD4_trywish(void)
2017-09-27 23:43:45 +02:00
{
2017-09-28 15:34:21 +02:00
switch (gBattlescriptCurrInstr[1])
2017-09-27 23:43:45 +02:00
{
case 0: // use wish
if (gWishFutureKnock.wishCounter[gBankAttacker] == 0)
{
gWishFutureKnock.wishCounter[gBankAttacker] = 2;
gWishFutureKnock.wishUserID[gBankAttacker] = gBattlePartyID[gBankAttacker];
gBattlescriptCurrInstr += 6;
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
}
break;
case 1: // heal effect
PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBankTarget, gWishFutureKnock.wishUserID[gBankTarget])
gBattleMoveDamage = gBattleMons[gBankTarget].maxHP / 2;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattleMoveDamage *= -1;
if (gBattleMons[gBankTarget].hp == gBattleMons[gBankTarget].maxHP)
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
else
gBattlescriptCurrInstr += 6;
break;
}
}
static void atkD5_trysetroots(void) // ingrain
2017-09-27 23:43:45 +02:00
{
if (gStatuses3[gBankAttacker] & STATUS3_ROOTED)
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
gStatuses3[gBankAttacker] |= STATUS3_ROOTED;
gBattlescriptCurrInstr += 5;
}
}
2017-09-28 15:34:21 +02:00
static void atkD6_doubledamagedealtifdamaged(void)
2017-09-27 23:43:45 +02:00
{
if ((gProtectStructs[gBankAttacker].physicalDmg
&& gProtectStructs[gBankAttacker].physicalBank == gBankTarget)
|| (gProtectStructs[gBankAttacker].specialDmg
&& gProtectStructs[gBankAttacker].specialBank == gBankTarget))
{
gBattleScripting.dmgMultiplier = 2;
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkD7_setyawn(void)
2017-09-27 23:43:45 +02:00
{
if (gStatuses3[gBankTarget] & STATUS3_YAWN
|| gBattleMons[gBankTarget].status1 & STATUS_ANY)
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
gStatuses3[gBankTarget] |= 0x1000;
gBattlescriptCurrInstr += 5;
}
}
2017-09-28 15:34:21 +02:00
static void atkD8_setdamagetohealthdifference(void)
2017-09-27 23:43:45 +02:00
{
if (gBattleMons[gBankTarget].hp <= gBattleMons[gBankAttacker].hp)
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
gBattleMoveDamage = gBattleMons[gBankTarget].hp - gBattleMons[gBankAttacker].hp;
gBattlescriptCurrInstr += 5;
}
}
2017-09-28 15:34:21 +02:00
static void atkD9_scaledamagebyhealthratio(void)
2017-09-27 23:43:45 +02:00
{
if (gDynamicBasePower == 0)
{
u8 power = gBattleMoves[gCurrentMove].power;
gDynamicBasePower = gBattleMons[gBankAttacker].hp * power / gBattleMons[gBankAttacker].maxHP;
if (gDynamicBasePower == 0)
gDynamicBasePower = 1;
}
gBattlescriptCurrInstr++;
}
static void atkDA_tryswapabilities(void) // skill swap
2017-09-27 23:43:45 +02:00
{
if ((gBattleMons[gBankAttacker].ability == 0
&& gBattleMons[gBankTarget].ability == 0)
|| gBattleMons[gBankAttacker].ability == ABILITY_WONDER_GUARD
|| gBattleMons[gBankTarget].ability == ABILITY_WONDER_GUARD
|| gBattleMoveFlags & MOVESTATUS_NOEFFECT)
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
u8 abilityAtk = gBattleMons[gBankAttacker].ability;
gBattleMons[gBankAttacker].ability = gBattleMons[gBankTarget].ability;
gBattleMons[gBankTarget].ability = abilityAtk;
gBattlescriptCurrInstr += 5;
}
}
static void atkDB_tryimprision(void)
2017-09-27 23:43:45 +02:00
{
if ((gStatuses3[gBankAttacker] & STATUS3_IMPRISONED_OTHERS))
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
u8 bank, sideAttacker;
sideAttacker = GetBankSide(gBankAttacker);
PressurePPLoseOnUsingImprision(gBankAttacker);
for (bank = 0; bank < gNoOfAllBanks; bank++)
{
if (sideAttacker != GetBankSide(bank))
{
s32 attackerMoveId;
for (attackerMoveId = 0; attackerMoveId < 4; attackerMoveId++)
{
s32 i;
for (i = 0; i < 4; i++)
{
if (gBattleMons[gBankAttacker].moves[attackerMoveId] == gBattleMons[bank].moves[i]
&& gBattleMons[gBankAttacker].moves[attackerMoveId] != MOVE_NONE)
break;
}
if (i != 4)
break;
}
if (attackerMoveId != 4)
{
gStatuses3[gBankAttacker] |= STATUS3_IMPRISONED_OTHERS;
gBattlescriptCurrInstr += 5;
break;
}
}
}
if (bank == gNoOfAllBanks) // In Generation 3 games, Imprison fails if the user doesn't share any moves with any of the foes
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
static void atkDC_trysetgrudge(void)
2017-09-27 23:43:45 +02:00
{
if (gStatuses3[gBankAttacker] & STATUS3_GRUDGE)
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
gStatuses3[gBankAttacker] |= STATUS3_GRUDGE;
gBattlescriptCurrInstr += 5;
}
}
2017-09-28 15:34:21 +02:00
static void atkDD_weightdamagecalculation(void)
2017-09-27 23:43:45 +02:00
{
s32 i;
for (i = 0; sWeightToDamageTable[i] != 0xFFFF; i += 2)
{
if (sWeightToDamageTable[i] > GetPokedexHeightWeight(SpeciesToNationalPokedexNum(gBattleMons[gBankTarget].species), 1))
break;
}
if (sWeightToDamageTable[i] != 0xFFFF)
gDynamicBasePower = sWeightToDamageTable[i + 1];
else
gDynamicBasePower = 120;
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkDE_asistattackselect(void)
2017-09-27 23:43:45 +02:00
{
s32 chooseableMovesNo = 0;
struct Pokemon* party;
s32 monId, moveId;
u16* movesArray = gBattleStruct->assistPossibleMoves;
if (GET_BANK_SIDE(gBankAttacker) != SIDE_PLAYER)
party = gEnemyParty;
else
party = gPlayerParty;
for (monId = 0; monId < 6; monId++)
{
if (monId == gBattlePartyID[gBankAttacker])
continue;
if (GetMonData(&party[monId], MON_DATA_SPECIES2) == SPECIES_NONE)
continue;
if (GetMonData(&party[monId], MON_DATA_SPECIES2) == SPECIES_EGG)
continue;
for (moveId = 0; moveId < 4; moveId++)
{
s32 i = 0;
u16 move = GetMonData(&party[monId], MON_DATA_MOVE1 + moveId);
if (IsInvalidForSleepTalkOrAssist(move))
continue;
2017-09-28 16:51:24 +02:00
for (; sMovesForbiddenToCopy[i] != ASSIST_FORBIDDEN_END && move != sMovesForbiddenToCopy[i]; i++);
2017-09-27 23:43:45 +02:00
2017-09-28 16:51:24 +02:00
if (sMovesForbiddenToCopy[i] != ASSIST_FORBIDDEN_END)
2017-09-27 23:43:45 +02:00
continue;
if (move == MOVE_NONE)
continue;
movesArray[chooseableMovesNo] = move;
chooseableMovesNo++;
}
}
if (chooseableMovesNo)
{
gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED);
gRandomMove = movesArray[((Random() & 0xFF) * chooseableMovesNo) >> 8];
gBankTarget = GetMoveTarget(gRandomMove, 0);
gBattlescriptCurrInstr += 5;
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
static void atkDF_trysetmagiccoat(void)
2017-09-27 23:43:45 +02:00
{
gBankTarget = gBankAttacker;
gSpecialStatuses[gBankAttacker].flag20 = 1;
2017-10-06 00:12:01 +02:00
if (gCurrentTurnActionNumber == gNoOfAllBanks - 1) // moves last turn
2017-09-27 23:43:45 +02:00
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
gProtectStructs[gBankAttacker].bounceMove = 1;
gBattlescriptCurrInstr += 5;
}
}
static void atkE0_trysetsnatch(void) // snatch
2017-09-27 23:43:45 +02:00
{
gSpecialStatuses[gBankAttacker].flag20 = 1;
2017-10-06 00:12:01 +02:00
if (gCurrentTurnActionNumber == gNoOfAllBanks - 1) // moves last turn
2017-09-27 23:43:45 +02:00
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
gProtectStructs[gBankAttacker].stealMove = 1;
gBattlescriptCurrInstr += 5;
}
}
static void atkE1_trygetintimidatetarget(void)
2017-09-27 23:43:45 +02:00
{
u8 side;
gBattleScripting.bank = gBattleStruct->intimidateBank;
side = GetBankSide(gBattleScripting.bank);
PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gBattleMons[gBattleScripting.bank].ability)
for (;gBankTarget < gNoOfAllBanks; gBankTarget++)
{
if (GetBankSide(gBankTarget) == side)
continue;
if (!(gAbsentBankFlags & gBitTable[gBankTarget]))
break;
}
if (gBankTarget >= gNoOfAllBanks)
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
else
gBattlescriptCurrInstr += 5;
}
static void atkE2_switchoutabilities(void)
2017-09-27 23:43:45 +02:00
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-27 23:43:45 +02:00
switch (gBattleMons[gActiveBank].ability)
{
case ABILITY_NATURAL_CURE:
gBattleMons[gActiveBank].status1 = 0;
EmitSetMonData(0, REQUEST_STATUS_BATTLE, gBitTable[*(gBattleStruct->field_58 + gActiveBank)], 4, &gBattleMons[gActiveBank].status1);
MarkBufferBankForExecution(gActiveBank);
break;
}
gBattlescriptCurrInstr += 2;
}
2017-09-28 15:34:21 +02:00
static void atkE3_jumpifhasnohp(void)
2017-09-27 23:43:45 +02:00
{
2017-09-28 15:34:21 +02:00
gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
2017-09-27 23:43:45 +02:00
if (gBattleMons[gActiveBank].hp == 0)
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
else
gBattlescriptCurrInstr += 6;
}
2017-09-28 15:34:21 +02:00
static void atkE4_getsecretpowereffect(void)
2017-09-27 23:43:45 +02:00
{
switch (gBattleTerrain)
{
case BATTLE_TERRAIN_GRASS:
gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_POISON;
break;
case BATTLE_TERRAIN_LONG_GRASS:
gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_SLEEP;
break;
case BATTLE_TERRAIN_SAND:
gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_ACC_MINUS_1;
break;
case BATTLE_TERRAIN_UNDERWATER:
gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_DEF_MINUS_1;
break;
case BATTLE_TERRAIN_WATER:
gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_ATK_MINUS_1;
break;
case BATTLE_TERRAIN_POND:
gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_SPD_MINUS_1;
break;
case BATTLE_TERRAIN_ROCK:
gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_CONFUSION;
break;
case BATTLE_TERRAIN_CAVE:
gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_FLINCH;
break;
default:
gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_PARALYSIS;
break;
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkE5_pickup(void)
2017-09-27 23:43:45 +02:00
{
if (!InBattlePike())
{
s32 i;
u16 species, heldItem;
u8 ability;
if (InBattlePyramid())
{
for (i = 0; i < 6; i++)
{
species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2);
heldItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
if (GetMonData(&gPlayerParty[i], MON_DATA_ALT_ABILITY))
ability = gBaseStats[species].ability2;
else
ability = gBaseStats[species].ability1;
if (ability == ABILITY_PICKUP
&& species != 0
&& species != SPECIES_EGG
&& heldItem == ITEM_NONE
&& (Random() % 10) == 0)
{
heldItem = GetBattlePyramidPickupItemId();
SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &heldItem);
}
}
}
else
{
for (i = 0; i < 6; i++)
{
species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2);
heldItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
if (GetMonData(&gPlayerParty[i], MON_DATA_ALT_ABILITY))
ability = gBaseStats[species].ability2;
else
ability = gBaseStats[species].ability1;
if (ability == ABILITY_PICKUP
&& species != 0
&& species != SPECIES_EGG
&& heldItem == ITEM_NONE
&& (Random() % 10) == 0)
{
s32 j;
s32 rand = Random() % 100;
u8 lvlDivBy10 = (GetMonData(&gPlayerParty[i], MON_DATA_LEVEL) - 1) / 10;
if (lvlDivBy10 > 9)
lvlDivBy10 = 9;
for (j = 0; j < 9; j++)
{
2017-09-28 16:51:24 +02:00
if (sPickupProbabilities[j] > rand)
2017-09-27 23:43:45 +02:00
{
2017-09-28 16:51:24 +02:00
SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &sPickupItems[lvlDivBy10 + j]);
2017-09-27 23:43:45 +02:00
break;
}
else if (rand == 99 || rand == 98)
{
2017-09-28 16:51:24 +02:00
SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &sRarePickupItems[lvlDivBy10 + (99 - rand)]);
2017-09-27 23:43:45 +02:00
break;
}
}
}
}
}
}
gBattlescriptCurrInstr++;
}
2017-09-28 15:34:21 +02:00
static void atkE6_docastformchangeanimation(void)
2017-09-28 15:34:21 +02:00
{
gActiveBank = gBattleScripting.bank;
if (gBattleMons[gActiveBank].status2 & STATUS2_SUBSTITUTE)
*(&gBattleStruct->formToChangeInto) |= 0x80;
EmitBattleAnimation(0, B_ANIM_CASTFORM_CHANGE, gBattleStruct->formToChangeInto);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr++;
}
static void atkE7_trycastformdatachange(void)
2017-09-28 15:34:21 +02:00
{
u8 form;
gBattlescriptCurrInstr++;
form = CastformDataTypeChange(gBattleScripting.bank);
if (form)
{
BattleScriptPushCursorAndCallback(BattleScript_CastformChange);
*(&gBattleStruct->formToChangeInto) = form - 1;
}
}
static void atkE8_settypebasedhalvers(void) // water and mud sport
{
bool8 worked = FALSE;
if (gBattleMoves[gCurrentMove].effect == EFFECT_MUD_SPORT)
{
if (!(gStatuses3[gBankAttacker] & STATUS3_MUDSPORT))
{
gStatuses3[gBankAttacker] |= STATUS3_MUDSPORT;
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
worked = TRUE;
}
}
else // water sport
{
if (!(gStatuses3[gBankAttacker] & STATUS3_WATERSPORT))
{
gStatuses3[gBankAttacker] |= STATUS3_WATERSPORT;
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
worked = TRUE;
}
}
if (worked)
gBattlescriptCurrInstr += 5;
else
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
static void atkE9_setweatherballtype(void)
{
if (WEATHER_HAS_EFFECT)
{
if (gBattleWeather & WEATHER_ANY)
gBattleScripting.dmgMultiplier = 2;
if (gBattleWeather & WEATHER_RAIN_ANY)
*(&gBattleStruct->dynamicMoveType) = TYPE_WATER | 0x80;
else if (gBattleWeather & WEATHER_SANDSTORM_ANY)
*(&gBattleStruct->dynamicMoveType) = TYPE_ROCK | 0x80;
else if (gBattleWeather & WEATHER_SUN_ANY)
*(&gBattleStruct->dynamicMoveType) = TYPE_FIRE | 0x80;
else if (gBattleWeather & WEATHER_HAIL_ANY)
*(&gBattleStruct->dynamicMoveType) = TYPE_ICE | 0x80;
else
*(&gBattleStruct->dynamicMoveType) = TYPE_NORMAL | 0x80;
}
gBattlescriptCurrInstr++;
}
static void atkEA_tryrecycleitem(void)
2017-09-28 15:34:21 +02:00
{
u16 *usedHeldItem;
gActiveBank = gBankAttacker;
usedHeldItem = &gBattleStruct->usedHeldItems[gActiveBank];
if (*usedHeldItem != 0 && gBattleMons[gActiveBank].item == 0)
{
gLastUsedItem = *usedHeldItem;
*usedHeldItem = 0;
gBattleMons[gActiveBank].item = gLastUsedItem;
EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gBattleMons[gActiveBank].item);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 5;
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
static void atkEB_settypetoterrain(void)
{
if (gBattleMons[gBankAttacker].type1 != sTerrainToType[gBattleTerrain]
&& gBattleMons[gBankAttacker].type2 != sTerrainToType[gBattleTerrain])
{
gBattleMons[gBankAttacker].type1 = sTerrainToType[gBattleTerrain];
gBattleMons[gBankAttacker].type2 = sTerrainToType[gBattleTerrain];
PREPARE_TYPE_BUFFER(gBattleTextBuff1, sTerrainToType[gBattleTerrain])
gBattlescriptCurrInstr += 5;
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
static void atkEC_pursuitrelated(void)
2017-09-28 15:34:21 +02:00
{
gActiveBank = GetBankByIdentity(GetBankIdentity(gBankAttacker) ^ BIT_MON);
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
&& !(gAbsentBankFlags & gBitTable[gActiveBank])
&& gActionForBanks[gActiveBank] == 0
&& gChosenMovesByBanks[gActiveBank] == MOVE_PURSUIT)
{
2017-10-04 19:25:14 +02:00
gActionsByTurnOrder[gActiveBank] = 11;
2017-09-28 15:34:21 +02:00
gCurrentMove = MOVE_PURSUIT;
gBattlescriptCurrInstr += 5;
gBattleScripting.animTurn = 1;
gBattleScripting.field_20 = gBankAttacker;
gBankAttacker = gActiveBank;
}
else
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
}
static void atkEF_snatchsetbanks(void)
2017-09-28 15:34:21 +02:00
{
gEffectBank = gBankAttacker;
if (gBankAttacker == gBankTarget)
gBankAttacker = gBankTarget = gBattleScripting.bank;
else
gBankTarget = gBattleScripting.bank;
gBattleScripting.bank = gEffectBank;
gBattlescriptCurrInstr++;
}
static void atkEE_removelightscreenreflect(void) // brick break
{
u8 opposingSide = GetBankSide(gBankAttacker) ^ BIT_SIDE;
if (gSideTimers[opposingSide].reflectTimer || gSideTimers[opposingSide].lightscreenTimer)
{
gSideAffecting[opposingSide] &= ~(SIDE_STATUS_REFLECT);
gSideAffecting[opposingSide] &= ~(SIDE_STATUS_LIGHTSCREEN);
gSideTimers[opposingSide].reflectTimer = 0;
gSideTimers[opposingSide].lightscreenTimer = 0;
gBattleScripting.animTurn = 1;
gBattleScripting.animTargetsHit = 1;
}
else
{
gBattleScripting.animTurn = 0;
gBattleScripting.animTargetsHit = 0;
}
gBattlescriptCurrInstr++;
}
2017-11-26 01:19:57 +01:00
static void atkEF_handleballthrow(void)
2017-09-28 15:34:21 +02:00
{
u8 ballMultiplier = 0;
if (gBattleExecBuffer)
return;
gActiveBank = gBankAttacker;
gBankTarget = gBankAttacker ^ BIT_SIDE;
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
{
2017-10-22 18:43:15 +02:00
EmitBallThrowAnim(0, BALL_TRAINER_BLOCK);
2017-09-28 15:34:21 +02:00
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr = BattleScript_TrainerBallBlock;
}
else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL)
{
2017-10-22 18:43:15 +02:00
EmitBallThrowAnim(0, BALL_3_SHAKES_SUCCESS);
2017-09-28 15:34:21 +02:00
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr = BattleScript_WallyBallThrow;
}
else
{
u32 odds;
u8 catchRate;
if (gLastUsedItem == ITEM_SAFARI_BALL)
catchRate = gBattleStruct->field_7C * 1275 / 100;
else
catchRate = gBaseStats[gBattleMons[gBankTarget].species].catchRate;
if (gLastUsedItem > ITEM_SAFARI_BALL)
{
switch (gLastUsedItem)
{
case ITEM_NET_BALL:
if (gBattleMons[gBankTarget].type1 == TYPE_WATER
|| gBattleMons[gBankTarget].type2 == TYPE_WATER
|| gBattleMons[gBankTarget].type1 == TYPE_BUG
|| gBattleMons[gBankTarget].type2 == TYPE_BUG)
ballMultiplier = 30;
else
ballMultiplier = 10;
break;
case ITEM_DIVE_BALL:
if (sav1_map_get_light_level() == 5)
ballMultiplier = 35;
else
ballMultiplier = 10;
break;
case ITEM_NEST_BALL:
2017-09-28 19:34:13 +02:00
if (gBattleMons[gBankTarget].level < 40)
2017-09-28 15:34:21 +02:00
{
ballMultiplier = 40 - gBattleMons[gBankTarget].level;
if (ballMultiplier <= 9)
ballMultiplier = 10;
}
else
{
ballMultiplier = 10;
}
break;
case ITEM_REPEAT_BALL:
if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gBankTarget].species), FLAG_GET_CAUGHT))
ballMultiplier = 30;
else
ballMultiplier = 10;
break;
case ITEM_TIMER_BALL:
ballMultiplier = gBattleResults.battleTurnCounter + 10;
if (ballMultiplier > 40)
ballMultiplier = 40;
break;
case ITEM_LUXURY_BALL:
case ITEM_PREMIER_BALL:
ballMultiplier = 10;
break;
}
}
else
ballMultiplier = sBallCatchBonuses[gLastUsedItem - 2];
odds = (catchRate * ballMultiplier / 10)
* (gBattleMons[gBankTarget].maxHP * 3 - gBattleMons[gBankTarget].hp * 2)
/ (3 * gBattleMons[gBankTarget].maxHP);
if (gBattleMons[gBankTarget].status1 & (STATUS_SLEEP | STATUS_FREEZE))
odds *= 2;
if (gBattleMons[gBankTarget].status1 & (STATUS_POISON | STATUS_BURN | STATUS_PARALYSIS | STATUS_TOXIC_POISON))
odds = (odds * 15) / 10;
if (gLastUsedItem != ITEM_SAFARI_BALL)
{
if (gLastUsedItem == ITEM_MASTER_BALL)
{
Decompile TV (#80) * ClearTVShowData * special_0x44 * DoTVShow (nonmatching because align) * DoTVShowBravoTrainerPokemonProfile * Update field names * DoTVShowBravoTrainerBattleTower * Renaming of struct fields * sub_80EBFF4 and UpdateTVScreensOnMap * SetTVMetatilesOnMap * Power buttons for the TV screens on the map * special_0x45 * sub_80EC18C * special_0x4a * ResetGabbyAndTy * GabbyAndTyBeforeInterview * GabbyAndTyAfterInterview * Through IsTVShowInSearchOfTrainersAiring * GabbyAndTyGetLastQuote * GabbyAndTyGetLastBattleTrivia * GabbyAndTySetScriptVarsToFieldObjectLocalIds * InterviewAfter; use TVShow as a precursor for making the individual show structs anonymous * Make TV structs anonymous within the union * Move the TV union to its own subheader * Move TV show enums to the global.tv.h subheader * Funcion renaming * Apply static attributes where able * PutPokemonTodayCaughtOnAir * sub_80EC8A4 * PutPokemonTodayFailedOnTheAir * sub_80EC9E8, sub_80ECA10 * sub_80ECA38 * sub_80ECB00 * Put3CheersForPokeblocksOnTheAir * PutFanClubSpecialOnTheAir * ContestLiveUpdates_BeforeInterview * Other before-interview Contest Live Updates functions * ContestLiveUpdates_BeforeInterview_5 * InterviewAfter_BravoTrainerPokemonProfile * BravoTrainerPokemonProfile_BeforeInterview1 * BravoTrainerPokemonProfile_BeforeInterview2 * Disassemble TV data * Decompile TV data * InterviewAfter_BravoTrainerBattleTowerProfile * SaveRecordedItemPurchasesForTVShow * PutNameRaterShowOnTheAir * StartMassOutbreak * PutLilycoveContestLadyShowOnTheAir * InterviewAfter_FanClubLetter * Rip TV strings * InterviewAfter_RecentHappenings * InterviewAfter_PkmnFanClubOpinions * sub_80ED718 * EndMassOutbreak * sub_80ED888 * sub_80ED8B4 * UpdateMassOutbreakTimeLeft * sub_80ED950 * PutFishingAdviceShowOnTheAir * through sub_80EDA80 * ewram and common syms are now fetched from the object files * BSS symbols are taken from the tv.o file * through sub_80EDC60 * sub_80EDCE8 * sub_80EDD78 * through sub_80EDE84 * nomatching sub_80EDE98 * sub_80EDFB4 * sub_80EE104 * sub_80EE104 * sub_80EE184 * sub_80EE2CC * sub_80EE35C * sub_80EE44C * sub_80EE4DC * sub_80EE5A4 * sub_80EE69C * sub_80EE72C * sub_80EE7C0 * sub_80EE818 * sub_80EE8C8 * sub_80EEA70 * sub_80EEB98 * sub_80EEBF4 * through sub_80EED60 * Functions relating to Pokemon News * sub_80EEF6C * GetPriceReduction * IsPriceDiscounted * sub_80EF120 * through sub_80EF370 * sub_80EF40C * HasMixableShowAlreadyBeenSpawnedWithPlayerID * TV_SortPurchasesByQuantity * FindActiveBroadcastByShowType_SetScriptResult * InterviewBefore * through sub_80EF88C * through sub_80EF93C * through sub_80EFA24 * through TV_BernoulliTrial * sub_80EFB58 * sub_80EFBA4 * sub_80EFBDC * through sub_80EFD98 * ChangePokemonNickname * ChangeBoxPokemonNickname * sub_80EFF9C * through player_id_to_dword * CheckForBigMovieOrEmergencyNewsOnTV * GetMomOrDadStringForTVMessage * sub_80F01E8 * sub_80F0358 * sub_80F049C * TV record mixing functions * sub_80F06D0 * sub_80F0708 nonmatching * through sub_80F0B24 * sub_80F0B64 * through sub_80F0C04 * sub_80F0C7C * sub_80F0D60 * sub_80F0E58 * sub_80F0E84 * through sub_80F0F24 * sub_80F0F64 * sub_80F1208 * sub_80F1254 * sub_80F1290 * sub_80F12A4 * sub_80F14F8 * DoTVShowTodaysSmartShopper * DoTVShowTheNameRaterShow * DoTVShowPokemonTodaySuccessfulCapture * DoTVShowPokemonTodayFailedCapture * DoTVShowPokemonFanClubLetter * DoTVShowRecentHappenings * DoTVShowPokemonFanClubOpinions * DoTVShowPokemonNewsMassOutbreak * DoTVShowPokemonContestLiveUpdates * DoTVShowPokemonBattleUpdate * DoTVShow3CheersForPokeblocks * DoTVShowInSearchOfTrainers * Label GabbyAndTyData fields; remove ddump comments from data/text/tv.inc * DoTVShowPokemonAngler * DoTVShowTheWorldOfMasters; update RAM symbols and field names * Decorate static functions * DoTVShowTodaysRivalTrainer; region map enums * TVDewfordTrendWatcherNetworkTextGroup * DoTVShowHoennTreasureInvestigators * DoTVShowFindThatGamer * DoTVShowBreakingNewsTV * DoTVShowSecretBaseVisit * DoTVShowPokemonLotterWinnerFlashReport * DoTVShowThePokemonBattleSeminar * DoTVShowTrainerFanClubSpecial, DoTVShowTrainerFanClub * DoTVShowSpotTheCuties * DoTVShowPokemonNewsBattleFrontier * DoTVShowWhatsNo1InHoennToday * Helpers for DoTVShowSecretBaseSecrets * DoTVShowSecretBaseSecrets * DoTVShowSafariFanClub * Finish decompilation of tv.s * Some renaming * Rename text group pointers * revoke statis; pokenews enums * Labels are number one * Label all TV struct fields * Make data/text/tv.inc more readable * Split data/text/tv.inc * Rename pokenews text pointers * Frontier Symbol constants; indicate static rodata objects with 's' prefix * Fix leading spaces/tabs F*** CLion sometimes * Fix inconsequential warning
2017-10-13 17:09:36 +02:00
gBattleResults.usedMasterBall = TRUE;
2017-09-28 15:34:21 +02:00
}
else
{
if (gBattleResults.catchAttempts[gLastUsedItem - ITEM_ULTRA_BALL] < 0xFF)
gBattleResults.catchAttempts[gLastUsedItem - ITEM_ULTRA_BALL]++;
}
}
if (odds > 254) // mon caught
{
2017-10-22 18:43:15 +02:00
EmitBallThrowAnim(0, BALL_3_SHAKES_SUCCESS);
2017-09-28 15:34:21 +02:00
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr = BattleScript_SuccessBallThrow;
SetMonData(&gEnemyParty[gBattlePartyID[gBankTarget]], MON_DATA_POKEBALL, &gLastUsedItem);
if (CalculatePlayerPartyCount() == 6)
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
else
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
}
else // mon may be caught, calculate shakes
{
u8 shakes;
odds = Sqrt(Sqrt(16711680 / odds));
odds = 1048560 / odds;
for (shakes = 0; shakes < 4 && Random() < odds; shakes++);
if (gLastUsedItem == ITEM_MASTER_BALL)
shakes = BALL_3_SHAKES_SUCCESS; // why calculate the shakes before that check?
2017-10-22 18:43:15 +02:00
EmitBallThrowAnim(0, shakes);
2017-09-28 15:34:21 +02:00
MarkBufferBankForExecution(gActiveBank);
if (shakes == BALL_3_SHAKES_SUCCESS) // mon caught, copy of the code above
{
gBattlescriptCurrInstr = BattleScript_SuccessBallThrow;
SetMonData(&gEnemyParty[gBattlePartyID[gBankTarget]], MON_DATA_POKEBALL, &gLastUsedItem);
if (CalculatePlayerPartyCount() == 6)
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
else
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
}
else // not caught
{
gBattleCommunication[MULTISTRING_CHOOSER] = shakes;
gBattlescriptCurrInstr = BattleScript_ShakeBallThrow;
}
}
}
}
static void atkF0_givecaughtmon(void)
2017-09-28 15:34:21 +02:00
{
if (GiveMonToPlayer(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]]) != MON_GIVEN_TO_PARTY)
{
if (!sub_813B21C())
{
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_STORAGE_UNKNOWN)));
GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_NICKNAME, gStringVar2);
}
else
{
StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_STORAGE_UNKNOWN)));
GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_NICKNAME, gStringVar2);
StringCopy(gStringVar3, GetBoxNamePtr(get_unknown_box_id()));
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
}
2017-11-08 22:20:10 +01:00
if (FlagGet(FLAG_SYS_PC_LANETTE))
2017-09-28 15:34:21 +02:00
gBattleCommunication[MULTISTRING_CHOOSER]++;
}
gBattleResults.caughtMonSpecies = GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_SPECIES, NULL);
GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_NICKNAME, gBattleResults.caughtMonNick);
gBattleResults.caughtMonBall = GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_POKEBALL, NULL);
gBattlescriptCurrInstr++;
}
static void atkF1_trysetcaughtmondexflags(void)
2017-09-28 15:34:21 +02:00
{
u16 species = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, NULL);
u32 personality = GetMonData(&gEnemyParty[0], MON_DATA_PERSONALITY, NULL);
if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(species), FLAG_GET_CAUGHT))
{
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
HandleSetPokedexFlag(SpeciesToNationalPokedexNum(species), FLAG_SET_CAUGHT, personality);
gBattlescriptCurrInstr += 5;
}
}
static void atkF2_displaydexinfo(void)
2017-09-28 15:34:21 +02:00
{
u16 species = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, NULL);
switch (gBattleCommunication[0])
{
case 0:
BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
gBattleCommunication[0]++;
break;
case 1:
if (!gPaletteFade.active)
{
FreeAllWindowBuffers();
gBattleCommunication[TASK_ID] = CreateDexDisplayMonDataTask(SpeciesToNationalPokedexNum(species),
gBattleMons[gBankTarget].otId,
gBattleMons[gBankTarget].personality);
gBattleCommunication[0]++;
}
break;
case 2:
if (!gPaletteFade.active
&& gMain.callback2 == BattleMainCB2
&& !gTasks[gBattleCommunication[TASK_ID]].isActive)
{
SetVBlankCallback(VBlankCB_Battle);
gBattleCommunication[0]++;
}
break;
case 3:
2017-10-01 18:54:01 +02:00
sub_80356D0();
2017-10-01 01:12:42 +02:00
LoadBattleTextboxAndBackground();
2017-09-28 15:34:21 +02:00
gBattle_BG3_X = 0x100;
gBattleCommunication[0]++;
break;
case 4:
if (!IsDma3ManagerBusyWithBgCopy())
{
BeginNormalPaletteFade(0xFFFF, 0, 0x10, 0, 0);
ShowBg(0);
ShowBg(3);
gBattleCommunication[0]++;
}
break;
case 5:
if (!gPaletteFade.active)
gBattlescriptCurrInstr++;
break;
}
}
void HandleBattleWindow(u8 xStart, u8 yStart, u8 xEnd, u8 yEnd, u8 flags)
2017-09-28 15:34:21 +02:00
{
s32 destY, destX;
u16 var = 0;
for (destY = yStart; destY <= yEnd; destY++)
{
for (destX = xStart; destX <= xEnd; destX++)
{
if (destY == yStart)
{
if (destX == xStart)
var = 0x1022;
else if (destX == xEnd)
var = 0x1024;
else
var = 0x1023;
}
else if (destY == yEnd)
{
if (destX == xStart)
var = 0x1028;
else if (destX == xEnd)
var = 0x102A;
else
var = 0x1029;
}
else
{
if (destX == xStart)
var = 0x1025;
else if (destX == xEnd)
var = 0x1027;
else
var = 0x1026;
}
if (flags & WINDOW_CLEAR)
2017-09-28 15:34:21 +02:00
var = 0;
if (flags & WINDOW_x80)
2017-09-28 15:34:21 +02:00
CopyToBgTilemapBufferRect_ChangePalette(1, &var, destX, destY, 1, 1, 0x11);
else
CopyToBgTilemapBufferRect_ChangePalette(0, &var, destX, destY, 1, 1, 0x11);
}
}
}
void BattleCreateYesNoCursorAt(u8 cursorPosition)
2017-09-28 15:34:21 +02:00
{
u16 src[2];
src[0] = 1;
src[1] = 2;
CopyToBgTilemapBufferRect_ChangePalette(0, src, 0x19, 9 + (2 * cursorPosition), 1, 2, 0x11);
CopyBgTilemapBufferToVram(0);
}
void BattleDestroyYesNoCursorAt(u8 cursorPosition)
2017-09-28 15:34:21 +02:00
{
u16 src[2];
src[0] = 0x1016;
src[1] = 0x1016;
CopyToBgTilemapBufferRect_ChangePalette(0, src, 0x19, 9 + (2 * cursorPosition), 1, 2, 0x11);
CopyBgTilemapBufferToVram(0);
}
static void atkF3_trygivecaughtmonnick(void)
2017-09-28 15:34:21 +02:00
{
switch (gBattleCommunication[MULTIUSE_STATE])
{
case 0:
HandleBattleWindow(0x18, 8, 0x1D, 0xD, 0);
BattleHandleAddTextPrinter(gText_BattleYesNoChoice, 0xC);
2017-09-28 15:34:21 +02:00
gBattleCommunication[MULTIUSE_STATE]++;
gBattleCommunication[CURSOR_POSITION] = 0;
BattleCreateYesNoCursorAt(0);
2017-09-28 15:34:21 +02:00
break;
case 1:
if (gMain.newKeys & DPAD_UP && gBattleCommunication[CURSOR_POSITION] != 0)
{
PlaySE(SE_SELECT);
BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]);
2017-09-28 15:34:21 +02:00
gBattleCommunication[CURSOR_POSITION] = 0;
BattleCreateYesNoCursorAt(0);
2017-09-28 15:34:21 +02:00
}
if (gMain.newKeys & DPAD_DOWN && gBattleCommunication[CURSOR_POSITION] == 0)
{
PlaySE(SE_SELECT);
BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]);
2017-09-28 15:34:21 +02:00
gBattleCommunication[CURSOR_POSITION] = 1;
BattleCreateYesNoCursorAt(1);
2017-09-28 15:34:21 +02:00
}
if (gMain.newKeys & A_BUTTON)
{
PlaySE(SE_SELECT);
if (gBattleCommunication[CURSOR_POSITION] == 0)
{
gBattleCommunication[MULTIUSE_STATE]++;
BeginFastPaletteFade(3);
}
else
{
gBattleCommunication[MULTIUSE_STATE] = 4;
}
}
else if (gMain.newKeys & B_BUTTON)
{
PlaySE(SE_SELECT);
gBattleCommunication[MULTIUSE_STATE] = 4;
}
break;
case 2:
if (!gPaletteFade.active)
{
GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_NICKNAME, gBattleStruct->caughtMonNick);
FreeAllWindowBuffers();
DoNamingScreen(NAMING_SCREEN_CAUGHT_MON, gBattleStruct->caughtMonNick,
GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_SPECIES),
GetMonGender(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]]),
GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_PERSONALITY, NULL),
BattleMainCB2);
gBattleCommunication[MULTIUSE_STATE]++;
}
break;
case 3:
if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active )
{
SetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_NICKNAME, gBattleStruct->caughtMonNick);
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
break;
case 4:
if (CalculatePlayerPartyCount() == 6)
gBattlescriptCurrInstr += 5;
else
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
break;
}
}
static void atkF4_subattackerhpbydmg(void)
{
gBattleMons[gBankAttacker].hp -= gBattleMoveDamage;
gBattlescriptCurrInstr++;
}
static void atkF5_removeattackerstatus1(void)
{
gBattleMons[gBankAttacker].status1 = 0;
gBattlescriptCurrInstr++;
}
static void atkF6_finishaction(void)
2017-09-28 15:34:21 +02:00
{
2017-10-06 00:12:01 +02:00
gCurrentActionFuncId = ACTION_FINISHED;
2017-09-28 15:34:21 +02:00
}
static void atkF7_finishturn(void)
2017-09-28 15:34:21 +02:00
{
2017-10-06 00:12:01 +02:00
gCurrentActionFuncId = ACTION_FINISHED;
gCurrentTurnActionNumber = gNoOfAllBanks;
2017-09-28 15:34:21 +02:00
}
static void atkF8_trainerslideout(void)
2017-09-28 15:34:21 +02:00
{
gActiveBank = GetBankByIdentity(gBattlescriptCurrInstr[1]);
EmitTrainerSlideBack(0);
MarkBufferBankForExecution(gActiveBank);
gBattlescriptCurrInstr += 2;
}