mirror of
https://github.com/pret/pokeheartgold.git
synced 2026-05-15 15:40:13 -05:00
6407 lines
219 KiB
C
6407 lines
219 KiB
C
#include "battle/battle_command.h"
|
|
|
|
#include "global.h"
|
|
|
|
#include "constants/abilities.h"
|
|
#include "constants/battle.h"
|
|
#include "constants/battle_script.h"
|
|
#include "constants/battle_subscript.h"
|
|
#include "constants/items.h"
|
|
#include "constants/message_tags.h"
|
|
#include "constants/move_effects.h"
|
|
#include "constants/moves.h"
|
|
#include "constants/opcode.h"
|
|
#include "constants/pokemon.h"
|
|
#include "constants/sndseq.h"
|
|
|
|
#include "battle/battle_controller.h"
|
|
#include "battle/battle_controller_player.h"
|
|
#include "battle/overlay_12_0224E4FC.h"
|
|
#include "msgdata/msg/msg_0197.h"
|
|
|
|
#include "assert.h"
|
|
#include "item.h"
|
|
#include "palette.h"
|
|
#include "party.h"
|
|
#include "pokemon.h"
|
|
#include "pokemon_mood.h"
|
|
#include "render_window.h"
|
|
#include "sound.h"
|
|
#include "sound_chatot.h"
|
|
#include "sys_task_api.h"
|
|
#include "system.h"
|
|
#include "text.h"
|
|
#include "touchscreen.h"
|
|
#include "unk_02005D10.h"
|
|
#include "unk_0208805C.h"
|
|
|
|
int BattleScriptReadWord(BattleContext *ctx);
|
|
static void BattleScriptIncrementPointer(BattleContext *ctx, int adrs);
|
|
static void BattleScriptJump(BattleContext *ctx, NarcId narcId, int adrs);
|
|
static void BattleScriptGotoSubscript(BattleContext *ctx, NarcId narcId, int adrs);
|
|
static void *BattleScriptGetVarPointer(BattleSystem *bsys, BattleContext *ctx, int var);
|
|
|
|
u8 GetBattlerIDBySide(BattleSystem *bsys, BattleContext *ctx, u32 a2);
|
|
|
|
extern BtlCmdFunc sBattleScriptCommandTable[];
|
|
|
|
BOOL RunBattleScript(BattleSystem *bsys, BattleContext *ctx) {
|
|
BOOL ret;
|
|
|
|
do {
|
|
ret = sBattleScriptCommandTable[ctx->battleScriptBuffer[ctx->scriptSeqNo]](bsys, ctx);
|
|
} while (ctx->battleContinueFlag == 0 && (BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_LINK) == 0);
|
|
|
|
ctx->battleContinueFlag = 0;
|
|
|
|
return ret;
|
|
}
|
|
|
|
BOOL BtlCmd_PlayEncounterAnimation(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
BattleController_EmitPlayEncounterAnimation(bsys, FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_SetPokemonEncounter(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
int battlersMax = BattleSystem_GetMaxBattlers(bsys);
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
switch (BattleScriptReadWord(ctx)) {
|
|
default:
|
|
case BATTLER_CATEGORY_ALL:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
BattleController_EmitPokemonEncounter(bsys, battlerId);
|
|
BattleSystem_SetPokedexSeen(bsys, battlerId);
|
|
}
|
|
break;
|
|
case BATTLER_CATEGORY_PLAYER:
|
|
break;
|
|
case BATTLER_CATEGORY_ENEMY: {
|
|
OpponentData *opponentData;
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 & 1) {
|
|
BattleController_EmitPokemonEncounter(bsys, battlerId);
|
|
BattleSystem_SetPokedexSeen(bsys, battlerId);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PokemonSlideIn(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
int battlersMax = BattleSystem_GetMaxBattlers(bsys);
|
|
|
|
OpponentData *opponentData;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
switch (BattleScriptReadWord(ctx)) {
|
|
default:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
BattleController_EmitPokemonSlideIn(bsys, battlerId);
|
|
BattleSystem_SetPokedexSeen(bsys, battlerId);
|
|
}
|
|
break;
|
|
case BATTLER_CATEGORY_PLAYER:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (!(opponentData->unk195 & 1)) {
|
|
BattleController_EmitPokemonSlideIn(bsys, battlerId);
|
|
BattleSystem_SetPokedexSeen(bsys, battlerId);
|
|
}
|
|
}
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, BATTLER_ENEMY);
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, BATTLER_ENEMY2);
|
|
break;
|
|
case BATTLER_CATEGORY_ENEMY:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 & 1) {
|
|
BattleSystem_ClearExperienceEarnFlags(ctx, battlerId);
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, battlerId);
|
|
BattleController_EmitPokemonSlideIn(bsys, battlerId);
|
|
BattleSystem_SetPokedexSeen(bsys, battlerId);
|
|
}
|
|
}
|
|
break;
|
|
case BATTLER_CATEGORY_ATTACKER:
|
|
opponentData = BattleSystem_GetOpponentData(bsys, ctx->battlerIdAttacker);
|
|
if (!(opponentData->unk195 & 1)) {
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, BATTLER_ENEMY);
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, BATTLER_ENEMY2);
|
|
} else {
|
|
BattleSystem_ClearExperienceEarnFlags(ctx, ctx->battlerIdAttacker);
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, ctx->battlerIdAttacker);
|
|
}
|
|
BattleSystem_SetPokedexSeen(bsys, ctx->battlerIdAttacker);
|
|
BattleController_EmitPokemonSlideIn(bsys, ctx->battlerIdAttacker);
|
|
break;
|
|
case BATTLER_CATEGORY_DEFENDER:
|
|
opponentData = BattleSystem_GetOpponentData(bsys, ctx->battlerIdTarget);
|
|
if (!(opponentData->unk195 & 1)) {
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, BATTLER_ENEMY);
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, BATTLER_ENEMY2);
|
|
} else {
|
|
BattleSystem_ClearExperienceEarnFlags(ctx, ctx->battlerIdTarget);
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, ctx->battlerIdTarget);
|
|
}
|
|
BattleSystem_SetPokedexSeen(bsys, ctx->battlerIdTarget);
|
|
BattleController_EmitPokemonSlideIn(bsys, ctx->battlerIdTarget);
|
|
break;
|
|
case BATTLER_CATEGORY_SWITCHED_MON:
|
|
opponentData = BattleSystem_GetOpponentData(bsys, ctx->battlerIdSwitch);
|
|
if (!(opponentData->unk195 & 1)) {
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, BATTLER_ENEMY);
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, BATTLER_ENEMY2);
|
|
} else {
|
|
BattleSystem_ClearExperienceEarnFlags(ctx, ctx->battlerIdSwitch);
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, ctx->battlerIdSwitch);
|
|
}
|
|
BattleSystem_SetPokedexSeen(bsys, ctx->battlerIdSwitch);
|
|
BattleController_EmitPokemonSlideIn(bsys, ctx->battlerIdSwitch);
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PokemonSendOut(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
int battlersMax = BattleSystem_GetMaxBattlers(bsys);
|
|
|
|
OpponentData *opponentData;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
switch (BattleScriptReadWord(ctx)) {
|
|
default:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
BattleController_EmitPokemonSendOut(bsys, battlerId, 0, 0);
|
|
BattleSystem_SetPokedexSeen(bsys, battlerId);
|
|
}
|
|
break;
|
|
case 3:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (!(opponentData->unk195 & 1)) {
|
|
BattleController_EmitPokemonSendOut(bsys, battlerId, 0, 0);
|
|
BattleSystem_SetPokedexSeen(bsys, battlerId);
|
|
}
|
|
}
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, BATTLER_ENEMY);
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, BATTLER_ENEMY2);
|
|
break;
|
|
case 4:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 & 1) {
|
|
BattleSystem_ClearExperienceEarnFlags(ctx, battlerId);
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, battlerId);
|
|
BattleController_EmitPokemonSendOut(bsys, battlerId, 0, 0);
|
|
BattleSystem_SetPokedexSeen(bsys, battlerId);
|
|
}
|
|
}
|
|
break;
|
|
case 1:
|
|
opponentData = BattleSystem_GetOpponentData(bsys, ctx->battlerIdAttacker);
|
|
if (!(opponentData->unk195 & 1)) {
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, BATTLER_ENEMY);
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, BATTLER_ENEMY2);
|
|
} else {
|
|
BattleSystem_ClearExperienceEarnFlags(ctx, ctx->battlerIdAttacker);
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, ctx->battlerIdAttacker);
|
|
}
|
|
BattleSystem_SetPokedexSeen(bsys, ctx->battlerIdAttacker);
|
|
BattleController_EmitPokemonSendOut(bsys, ctx->battlerIdAttacker, 0, 0);
|
|
break;
|
|
case 2:
|
|
opponentData = BattleSystem_GetOpponentData(bsys, ctx->battlerIdTarget);
|
|
if (!(opponentData->unk195 & 1)) {
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, BATTLER_ENEMY);
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, BATTLER_ENEMY2);
|
|
} else {
|
|
BattleSystem_ClearExperienceEarnFlags(ctx, ctx->battlerIdTarget);
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, ctx->battlerIdTarget);
|
|
}
|
|
BattleSystem_SetPokedexSeen(bsys, ctx->battlerIdTarget);
|
|
BattleController_EmitPokemonSendOut(bsys, ctx->battlerIdTarget, 0, 0);
|
|
break;
|
|
case 6:
|
|
opponentData = BattleSystem_GetOpponentData(bsys, ctx->battlerIdSwitch);
|
|
if (!(opponentData->unk195 & 1)) {
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, BATTLER_ENEMY);
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, BATTLER_ENEMY2);
|
|
} else {
|
|
BattleSystem_ClearExperienceEarnFlags(ctx, ctx->battlerIdSwitch);
|
|
BattleSystem_SetExperienceEarnFlags(bsys, ctx, ctx->battlerIdSwitch);
|
|
}
|
|
BattleSystem_SetPokedexSeen(bsys, ctx->battlerIdSwitch);
|
|
BattleController_EmitPokemonSendOut(bsys, ctx->battlerIdSwitch, 0, 0);
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_RecallPokemon(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
int battlersMax = BattleSystem_GetMaxBattlers(bsys);
|
|
OpponentData *opponentData;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
int side = BattleScriptReadWord(ctx);
|
|
|
|
switch (side) {
|
|
case BATTLER_CATEGORY_ALL:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
BattleController_EmitRecallPokemon(bsys, ctx, battlerId);
|
|
}
|
|
break;
|
|
case BATTLER_CATEGORY_PLAYER:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if ((opponentData->unk195 & 1) == 0) {
|
|
BattleController_EmitRecallPokemon(bsys, ctx, battlerId);
|
|
}
|
|
}
|
|
break;
|
|
case BATTLER_CATEGORY_ENEMY:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 & 1 && !(ctx->switchInFlag & MaskOfFlagNo(battlerId))) {
|
|
BattleController_EmitRecallPokemon(bsys, ctx, battlerId);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
BattleController_EmitRecallPokemon(bsys, ctx, GetBattlerIDBySide(bsys, ctx, side));
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_DeletePokemon(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u32 battlerId = GetBattlerIDBySide(bsys, ctx, BattleScriptReadWord(ctx));
|
|
BattleController_EmitDeletePokemon(bsys, battlerId);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_SetTrainerEncounter(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
int battlersMax = BattleSystem_GetMaxBattlers(bsys);
|
|
OpponentData *opponentData;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
switch (BattleScriptReadWord(ctx)) {
|
|
case 0:
|
|
default:
|
|
if (BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_TAG) {
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 != 4) {
|
|
BattleController_EmitTrainerEncounter(bsys, battlerId);
|
|
}
|
|
}
|
|
} else {
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
if ((BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_MULTI) == 0 && (BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_DOUBLES) && (battlerId > 1)) {
|
|
break;
|
|
}
|
|
BattleController_EmitTrainerEncounter(bsys, battlerId);
|
|
}
|
|
}
|
|
break;
|
|
case 3:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (!(opponentData->unk195 & 1)) {
|
|
BattleController_EmitTrainerEncounter(bsys, battlerId);
|
|
if ((BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_MULTI) == 0 && (BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_DOUBLES)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 4:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 & 1) {
|
|
BattleController_EmitTrainerEncounter(bsys, battlerId);
|
|
if ((BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_MULTI) == 0 && (BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_TAG) == 0 && (BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_DOUBLES)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_ThrowPokeball(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
int battlersMax = BattleSystem_GetMaxBattlers(bsys);
|
|
OpponentData *opponentData;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u32 unkB = BattleScriptReadWord(ctx);
|
|
u32 unkC = BattleScriptReadWord(ctx);
|
|
|
|
switch (unkB) {
|
|
case 0:
|
|
default:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
if ((BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_MULTI) == 0 && (BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_DOUBLES) && (battlerId > 1)) {
|
|
break;
|
|
}
|
|
BattleController_EmitThrowPokeball(bsys, battlerId, unkC);
|
|
}
|
|
break;
|
|
case 3:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (!(opponentData->unk195 & 1)) {
|
|
BattleController_EmitThrowPokeball(bsys, battlerId, unkC);
|
|
if ((BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_MULTI) == 0 && (BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_DOUBLES)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 4:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 & 1) {
|
|
BattleController_EmitThrowPokeball(bsys, battlerId, unkC);
|
|
if ((BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_MULTI) == 0 && (BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_TAG) == 0 && (BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_DOUBLES)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
ctx->battleContinueFlag = 1;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TrainerSlideOut(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
int battlersMax = BattleSystem_GetMaxBattlers(bsys);
|
|
OpponentData *opponentData;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u32 unkB = BattleScriptReadWord(ctx);
|
|
|
|
switch (unkB) {
|
|
case 0:
|
|
default:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
if ((BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_MULTI) == 0 && (BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_DOUBLES) && (battlerId > 1)) {
|
|
break;
|
|
}
|
|
BattleController_EmitTrainerSlideOut(bsys, battlerId);
|
|
}
|
|
break;
|
|
case 3:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (!(opponentData->unk195 & 1)) {
|
|
BattleController_EmitTrainerSlideOut(bsys, battlerId);
|
|
if ((BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_MULTI) == 0 && (BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_DOUBLES)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 4:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 & 1) {
|
|
BattleController_EmitTrainerSlideOut(bsys, battlerId);
|
|
if ((BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_MULTI) == 0 && (BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_TAG) == 0 && (BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_DOUBLES)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 9:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 == 0 || opponentData->unk195 == 2) {
|
|
BattleController_EmitTrainerSlideOut(bsys, battlerId);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case 10:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 == 1 || opponentData->unk195 == 3) {
|
|
BattleController_EmitTrainerSlideOut(bsys, battlerId);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case 11:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 == 4) {
|
|
BattleController_EmitTrainerSlideOut(bsys, battlerId);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case 12:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 == 5) {
|
|
BattleController_EmitTrainerSlideOut(bsys, battlerId);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TrainerSlideIn(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
int battlersMax = BattleSystem_GetMaxBattlers(bsys);
|
|
OpponentData *opponentData;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u32 side = BattleScriptReadWord(ctx);
|
|
u32 index = BattleScriptReadWord(ctx);
|
|
|
|
switch (side) {
|
|
case BATTLER_CATEGORY_ALL:
|
|
default:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
if ((BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_DOUBLES) && (battlerId > 1)) {
|
|
break;
|
|
}
|
|
BattleController_EmitTrainerSlideIn(bsys, battlerId, index);
|
|
}
|
|
break;
|
|
case BATTLER_CATEGORY_PLAYER:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (!(opponentData->unk195 & 1)) {
|
|
BattleController_EmitTrainerSlideIn(bsys, battlerId, index);
|
|
if (BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_DOUBLES) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case BATTLER_CATEGORY_ENEMY:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 & 1) {
|
|
BattleController_EmitTrainerSlideIn(bsys, battlerId, index);
|
|
if (BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_DOUBLES) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case BATTLER_CATEGORY_PLAYER_SLOT_1:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 == 0 || opponentData->unk195 == 2) {
|
|
BattleController_EmitTrainerSlideIn(bsys, battlerId, index);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case BATTLER_CATEGORY_ENEMY_SLOT_1:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 == 1 || opponentData->unk195 == 3) {
|
|
BattleController_EmitTrainerSlideIn(bsys, battlerId, index);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case BATTLER_CATEGORY_PLAYER_SLOT_2:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 == 4) {
|
|
BattleController_EmitTrainerSlideIn(bsys, battlerId, index);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case BATTLER_CATEGORY_ENEMY_SLOT_2:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 == 5) {
|
|
BattleController_EmitTrainerSlideIn(bsys, battlerId, index);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_BackgroundSlideIn(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
int battlersMax = BattleSystem_GetMaxBattlers(bsys);
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
BattleController_EmitBackgroundSlideIn(bsys, battlerId);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_HealthbarSlideIn(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
int battlersMax = BattleSystem_GetMaxBattlers(bsys);
|
|
OpponentData *opponentData;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
int side = BattleScriptReadWord(ctx);
|
|
|
|
switch (side) {
|
|
case BATTLER_CATEGORY_ALL:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
BattleController_EmitHealthbarSlideIn(bsys, ctx, battlerId, 0);
|
|
}
|
|
break;
|
|
case BATTLER_CATEGORY_PLAYER:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if ((opponentData->unk195 & 1) == 0) {
|
|
BattleController_EmitHealthbarSlideIn(bsys, ctx, battlerId, 0);
|
|
}
|
|
}
|
|
break;
|
|
case BATTLER_CATEGORY_ENEMY:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 & 1) {
|
|
BattleController_EmitHealthbarSlideIn(bsys, ctx, battlerId, 0);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
BattleController_EmitHealthbarSlideIn(bsys, ctx, GetBattlerIDBySide(bsys, ctx, side), 0);
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_HealthbarSlideInDelay(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
int battlersMax = BattleSystem_GetMaxBattlers(bsys);
|
|
OpponentData *opponentData;
|
|
u8 delay;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
int side = BattleScriptReadWord(ctx);
|
|
|
|
delay = 0;
|
|
|
|
switch (side) {
|
|
case BATTLER_CATEGORY_ALL:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
BattleController_EmitHealthbarSlideIn(bsys, ctx, battlerId, 0);
|
|
}
|
|
break;
|
|
case BATTLER_CATEGORY_PLAYER:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if ((opponentData->unk195 & 1) == 0) {
|
|
BattleController_EmitHealthbarSlideIn(bsys, ctx, battlerId, delay);
|
|
delay += 4;
|
|
}
|
|
}
|
|
break;
|
|
case BATTLER_CATEGORY_ENEMY:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 & 1) {
|
|
BattleController_EmitHealthbarSlideIn(bsys, ctx, battlerId, delay);
|
|
delay += 4;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
BattleController_EmitHealthbarSlideIn(bsys, ctx, GetBattlerIDBySide(bsys, ctx, side), 0);
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_HealthbarSlideOut(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
int battlersMax = BattleSystem_GetMaxBattlers(bsys);
|
|
OpponentData *opponentData;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
int side = BattleScriptReadWord(ctx);
|
|
|
|
switch (side) {
|
|
case BATTLER_CATEGORY_ALL:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
BattleController_EmitHealthbarSlideOut(bsys, battlerId);
|
|
}
|
|
break;
|
|
case BATTLER_CATEGORY_PLAYER:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if ((opponentData->unk195 & 1) == 0 && (ctx->switchInFlag & MaskOfFlagNo(battlerId)) == 0) {
|
|
BattleController_EmitHealthbarSlideOut(bsys, battlerId);
|
|
}
|
|
}
|
|
break;
|
|
case BATTLER_CATEGORY_ENEMY:
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 & 1) {
|
|
BattleController_EmitHealthbarSlideOut(bsys, battlerId);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
BattleController_EmitHealthbarSlideOut(bsys, GetBattlerIDBySide(bsys, ctx, side));
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_Wait(BattleSystem *bsys, BattleContext *ctx) {
|
|
if (Link_QueueNotEmpty(ctx)) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
} else {
|
|
Link_CheckTimeout(ctx);
|
|
}
|
|
|
|
ctx->battleContinueFlag = 1;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void DamageCalcDefault(BattleSystem *bsys, BattleContext *ctx) {
|
|
int type;
|
|
|
|
if (GetBattlerAbility(ctx, ctx->battlerIdAttacker) == ABILITY_NORMALIZE) {
|
|
type = TYPE_NORMAL;
|
|
} else if (ctx->moveType) {
|
|
type = ctx->moveType;
|
|
} else {
|
|
type = ctx->trainerAIData.moveData[ctx->moveNoCur].type;
|
|
}
|
|
|
|
ctx->damage = CalcMoveDamage(bsys, ctx, ctx->moveNoCur, ctx->fieldSideConditionFlags[BattleSystem_GetFieldSide(bsys, ctx->battlerIdTarget)], ctx->fieldCondition, ctx->movePower, type, ctx->battlerIdAttacker, ctx->battlerIdTarget, ctx->criticalMultiplier);
|
|
|
|
ctx->damage *= ctx->criticalMultiplier;
|
|
|
|
if (GetBattlerHeldItemEffect(ctx, ctx->battlerIdAttacker) == HOLD_EFFECT_HP_DRAIN_ON_ATK) {
|
|
ctx->damage = ctx->damage * (100 + GetHeldItemModifier(ctx, ctx->battlerIdAttacker, 0)) / 100;
|
|
}
|
|
|
|
if (GetBattlerHeldItemEffect(ctx, ctx->battlerIdAttacker) == HOLD_EFFECT_BOOST_REPEATED) {
|
|
ctx->damage = ctx->damage * (10 + ctx->battleMons[ctx->battlerIdAttacker].unk88.metronomeTurns) / 10;
|
|
}
|
|
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].unk88.meFirstFlag) {
|
|
if (ctx->meFirstTotal == ctx->battleMons[ctx->battlerIdAttacker].unk88.meFirstCount) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.meFirstCount--;
|
|
}
|
|
if ((ctx->meFirstTotal - ctx->battleMons[ctx->battlerIdAttacker].unk88.meFirstCount) < 2) {
|
|
ctx->damage = ctx->damage * 15 / 10;
|
|
} else {
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.meFirstFlag = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL BtlCmd_CalcDamage(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
DamageCalcDefault(bsys, ctx);
|
|
ctx->damage = ApplyDamageRange(bsys, ctx, ctx->damage);
|
|
ctx->damage *= -1;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CalcDamageRaw(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
DamageCalcDefault(bsys, ctx);
|
|
ctx->damage *= -1;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PrintAttackMessage(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
if (!(ctx->battleStatus & BATTLE_STATUS_NO_ATTACK_MESSAGE)) {
|
|
BattleController_EmitPrintAttackMessage(bsys, ctx);
|
|
}
|
|
|
|
ctx->battleStatus |= BATTLE_STATUS_NO_ATTACK_MESSAGE;
|
|
ctx->battleStatus2 |= BATTLE_STATUS2_DISPLAY_ATTACK_MESSAGE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PrintMessage(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleMessageData msgdata;
|
|
BattleMessage msg;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
InitBattleMsgData(ctx, &msgdata);
|
|
InitBattleMsg(bsys, ctx, &msgdata, &msg);
|
|
BattleController_EmitPrintMessage(bsys, ctx, &msg);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PrintGlobalMessage(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleMessageData msgdata;
|
|
BattleMessage msg;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
InitBattleMsgData(ctx, &msgdata);
|
|
InitBattleMsg(bsys, ctx, &msgdata, &msg);
|
|
|
|
msg.tag |= 128;
|
|
|
|
BattleController_EmitPrintMessage(bsys, ctx, &msg);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PrintBufferedMessage(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
BattleController_EmitPrintMessage(bsys, ctx, &ctx->buffMsg);
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_BufferMessage(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleMessageData msgdata;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
InitBattleMsgData(ctx, &msgdata);
|
|
InitBattleMsg(bsys, ctx, &msgdata, &ctx->buffMsg);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_BufferLocalMessage(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleMessageData msgdata;
|
|
BattleMessage msg;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u32 side = BattleScriptReadWord(ctx);
|
|
|
|
InitBattleMsgData(ctx, &msgdata);
|
|
InitBattleMsg(bsys, ctx, &msgdata, &msg);
|
|
|
|
msg.tag |= 64;
|
|
msg.battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
BattleController_EmitPrintMessage(bsys, ctx, &msg);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PlayMoveAnimation(BattleSystem *bsys, BattleContext *ctx) {
|
|
u16 move;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
u32 battler = BattleScriptReadWord(ctx);
|
|
|
|
if (battler == BATTLER_NONE) {
|
|
move = ctx->moveTemp;
|
|
} else {
|
|
move = ctx->moveNoCur;
|
|
}
|
|
|
|
if ((!(ctx->battleStatus & BATTLE_STATUS_MOVE_ANIMATIONS_OFF) && BattleSystem_AreBattleAnimationsOn(bsys) == TRUE) || move == MOVE_TRANSFORM) {
|
|
ctx->battleStatus |= BATTLE_STATUS_MOVE_ANIMATIONS_OFF;
|
|
BattleController_SetMoveAnimation(bsys, ctx, move);
|
|
}
|
|
|
|
if (!BattleSystem_AreBattleAnimationsOn(bsys)) {
|
|
BattleScriptGotoSubscript(ctx, NARC_a_0_0_1, BATTLE_SUBSCRIPT_WAIT_MOVE_ANIMATION);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PlayMoveAnimationOnMons(BattleSystem *bsys, BattleContext *ctx) {
|
|
u16 move;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
u32 battler = BattleScriptReadWord(ctx);
|
|
u32 attackerSide = BattleScriptReadWord(ctx);
|
|
u32 defenderSide = BattleScriptReadWord(ctx);
|
|
|
|
if (battler == BATTLER_NONE) {
|
|
move = ctx->moveTemp;
|
|
} else {
|
|
move = ctx->moveNoCur;
|
|
}
|
|
|
|
u32 attacker = GetBattlerIDBySide(bsys, ctx, attackerSide);
|
|
u32 defender = GetBattlerIDBySide(bsys, ctx, defenderSide);
|
|
|
|
if ((!(ctx->battleStatus & BATTLE_STATUS_MOVE_ANIMATIONS_OFF) && BattleSystem_AreBattleAnimationsOn(bsys) == TRUE) || move == MOVE_TRANSFORM) {
|
|
ctx->battleStatus |= BATTLE_STATUS_MOVE_ANIMATIONS_OFF;
|
|
ov12_0226343C(bsys, ctx, move, attacker, defender);
|
|
}
|
|
|
|
if (!BattleSystem_AreBattleAnimationsOn(bsys)) {
|
|
BattleScriptGotoSubscript(ctx, NARC_a_0_0_1, BATTLE_SUBSCRIPT_WAIT_MOVE_ANIMATION);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_FlickerMon(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u32 side = BattleScriptReadWord(ctx);
|
|
|
|
BattleController_EmitMonFlicker(bsys, GetBattlerIDBySide(bsys, ctx, side), ctx->moveStatusFlag);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_UpdateHealthbarValue(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u8 battlerId = GetBattlerIDBySide(bsys, ctx, BattleScriptReadWord(ctx));
|
|
|
|
if ((ctx->battleMons[battlerId].hp + ctx->hpCalc) <= 0) {
|
|
ctx->hitDamage = ctx->battleMons[battlerId].hp * -1;
|
|
} else {
|
|
ctx->hitDamage = ctx->hpCalc;
|
|
}
|
|
|
|
if (ctx->hitDamage < 0) {
|
|
ctx->totalDamage[battlerId] += (-1 * ctx->hitDamage);
|
|
}
|
|
|
|
ctx->battleMons[battlerId].hp += ctx->hpCalc;
|
|
|
|
if (ctx->battleMons[battlerId].hp < 0) {
|
|
ctx->battleMons[battlerId].hp = 0;
|
|
} else if (ctx->battleMons[battlerId].hp > ctx->battleMons[battlerId].maxHp) {
|
|
ctx->battleMons[battlerId].hp = ctx->battleMons[battlerId].maxHp;
|
|
}
|
|
|
|
CopyBattleMonToPartyMon(bsys, ctx, battlerId);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_UpdateHealthbar(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
BattleController_EmitHealthbarUpdate(bsys, ctx, GetBattlerIDBySide(bsys, ctx, BattleScriptReadWord(ctx)));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryFaintMon(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u32 battlerId = GetBattlerIDBySide(bsys, ctx, BattleScriptReadWord(ctx));
|
|
|
|
if (ctx->battleMons[battlerId].hp == 0) {
|
|
ctx->battlerIdFainted = battlerId;
|
|
ctx->battleStatus |= MaskOfFlagNo(battlerId) << BATTLE_STATUS_FAINTED_SHIFT;
|
|
ctx->totalTimesFainted[battlerId]++;
|
|
UpdateFrienshipFainted(bsys, ctx, battlerId);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PlayFaintAnimation(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
BattleController_EmitPlayFaintAnimation(bsys, ctx, ctx->battlerIdFainted);
|
|
|
|
ctx->battleStatus &= (MaskOfFlagNo(ctx->battlerIdFainted) << BATTLE_STATUS_FAINTED_SHIFT) ^ -1;
|
|
ctx->battleStatus2 |= MaskOfFlagNo(ctx->battlerIdFainted) << BATTLE_STATUS2_EXP_GAIN_SHIFT;
|
|
ctx->playerActions[ctx->battlerIdFainted].command = CONTROLLER_COMMAND_40;
|
|
|
|
InitFaintedWork(bsys, ctx, ctx->battlerIdFainted);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_WaitButtonABTime(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int waitFrames = BattleScriptReadWord(ctx);
|
|
int waitIncrement;
|
|
|
|
if (!(BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_LINK)) {
|
|
if (gSystem.newKeys & 0xC03 || System_GetTouchNew()) {
|
|
// TODO: Rename variable in struct
|
|
ctx->unk_F0 = waitFrames;
|
|
}
|
|
}
|
|
|
|
if (bsys->battleType & BATTLE_TYPE_LINK && !(bsys->battleSpecial & BATTLE_SPECIAL_RECORDING)) {
|
|
waitIncrement = 2;
|
|
} else {
|
|
waitIncrement = 1;
|
|
}
|
|
|
|
if (waitFrames > ctx->unk_F0) {
|
|
BattleScriptIncrementPointer(ctx, -2);
|
|
ctx->unk_F0 += waitIncrement;
|
|
} else {
|
|
ctx->unk_F0 = 0;
|
|
}
|
|
|
|
ctx->battleContinueFlag = 1;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PlaySound(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u32 side = BattleScriptReadWord(ctx);
|
|
u32 sound = BattleScriptReadWord(ctx);
|
|
|
|
BattleController_EmitPlaySE(bsys, ctx, sound, GetBattlerIDBySide(bsys, ctx, side));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CompareVarToValue(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u32 opcode = BattleScriptReadWord(ctx);
|
|
u32 varId = BattleScriptReadWord(ctx);
|
|
int cmp = BattleScriptReadWord(ctx);
|
|
u32 adrs = BattleScriptReadWord(ctx);
|
|
|
|
int *var = BattleScriptGetVarPointer(bsys, ctx, varId);
|
|
|
|
switch (opcode) {
|
|
case OPCODE_EQU:
|
|
if (*var != cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case OPCODE_NEQ:
|
|
if (*var == cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case OPCODE_GT:
|
|
if (*var <= cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case OPCODE_LTE:
|
|
if (*var > cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case OPCODE_FLAG_SET:
|
|
if (!(*var & cmp)) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case OPCODE_FLAG_NOT:
|
|
if (*var & cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case OPCODE_AND:
|
|
if ((*var & cmp) != cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (adrs) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CompareMonDataToValue(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u32 opcode = BattleScriptReadWord(ctx);
|
|
u32 side = BattleScriptReadWord(ctx);
|
|
u32 varId = BattleScriptReadWord(ctx);
|
|
int cmp = BattleScriptReadWord(ctx);
|
|
u32 adrs = BattleScriptReadWord(ctx);
|
|
|
|
int var = GetBattlerVar(ctx, GetBattlerIDBySide(bsys, ctx, side), varId, NULL);
|
|
|
|
switch (opcode) {
|
|
case 0:
|
|
if (var != cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 1:
|
|
if (var == cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (var <= cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 3:
|
|
if (var > cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 4:
|
|
if (!(var & cmp)) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 5:
|
|
if (var & cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 6:
|
|
if ((var & cmp) != cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (adrs) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_FadeOutBattle(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
BattleController_EmitFadeOutBattle(bsys, ctx);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_GoToSubscript(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
BattleScriptJump(ctx, NARC_a_0_0_1, BattleScriptReadWord(ctx));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_GoToEffectScript(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
BattleScriptJump(ctx, NARC_a_0_3_0, ctx->trainerAIData.moveData[ctx->moveNoCur].effect);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_GoToMoveScript(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u32 unkA = BattleScriptReadWord(ctx);
|
|
|
|
ctx->battleStatus &= ~BATTLE_STATUS_NO_ATTACK_MESSAGE;
|
|
ctx->battleStatus &= ~BATTLE_STATUS_MOVE_ANIMATIONS_OFF;
|
|
|
|
ctx->moveNoCur = ctx->moveTemp;
|
|
|
|
if (unkA == 0) {
|
|
ctx->battlerIdTarget = ov12_022506D4(bsys, ctx, ctx->battlerIdAttacker, (u16)ctx->moveTemp, 1, 0);
|
|
ov12_02250A18(bsys, ctx, ctx->battlerIdAttacker, ctx->moveTemp);
|
|
ctx->playerActions[ctx->battlerIdAttacker].unk4 = ctx->battlerIdTarget;
|
|
}
|
|
|
|
if (ctx->battlerIdTarget == BATTLER_NONE) {
|
|
ctx->commandNext = CONTROLLER_COMMAND_39;
|
|
BattleScriptJump(ctx, NARC_a_0_0_1, BATTLE_SUBSCRIPT_NO_TARGET);
|
|
} else {
|
|
BattleScriptJump(ctx, NARC_a_0_0_0, ctx->moveNoCur);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CalcCrit(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
if ((BattleSystem_GetBattleType(bsys) & BATTLE_TYPE_TUTORIAL) || (BattleSystem_GetBattleSpecial(bsys) & BATTLE_SPECIAL_FIRST_RIVAL)) {
|
|
ctx->criticalMultiplier = 1;
|
|
} else {
|
|
ctx->criticalMultiplier = TryCriticalHit(bsys, ctx, ctx->battlerIdAttacker, ctx->battlerIdTarget, ctx->criticalCnt, ov12_022581D4(bsys, ctx, 0, ctx->battlerIdTarget));
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CalcExpGain(BattleSystem *bsys, BattleContext *ctx) {
|
|
int adrs;
|
|
u32 battleType = BattleSystem_GetBattleType(bsys);
|
|
OpponentData *opponentData = BattleSystem_GetOpponentData(bsys, ctx->battlerIdFainted);
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
adrs = BattleScriptReadWord(ctx);
|
|
|
|
if ((opponentData->unk195 & 1) && !(battleType & (BATTLE_TYPE_LINK | BATTLE_TYPE_SAFARI | BATTLE_TYPE_FRONTIER | BATTLE_TYPE_PAL_PARK))) {
|
|
int expMonsCnt = 0;
|
|
int expShareMonsCnt = 0;
|
|
u16 totalExp;
|
|
u16 itemNo;
|
|
Pokemon *mon;
|
|
for (int i = 0; i < Party_GetCount(BattleSystem_GetParty(bsys, 0)); i++) {
|
|
mon = BattleSystem_GetPartyMon(bsys, 0, i);
|
|
if (GetMonData(mon, MON_DATA_SPECIES, 0) && GetMonData(mon, MON_DATA_HP, 0)) {
|
|
if (ctx->unk_A4[(ctx->battlerIdFainted >> 1) & 1] & MaskOfFlagNo(i)) {
|
|
expMonsCnt++;
|
|
}
|
|
itemNo = GetMonData(mon, MON_DATA_HELD_ITEM, 0);
|
|
if (GetItemVar(ctx, itemNo, ITEM_VAR_HOLD_EFFECT) == HOLD_EFFECT_EXP_SHARE) {
|
|
expShareMonsCnt++;
|
|
}
|
|
}
|
|
}
|
|
totalExp = GetMonBaseStat(ctx->battleMons[ctx->battlerIdFainted].species, BASE_EXP_YIELD);
|
|
totalExp = (totalExp * ctx->battleMons[ctx->battlerIdFainted].level) / 7;
|
|
if (expShareMonsCnt) {
|
|
ctx->gainedExp = (totalExp / 2) / expMonsCnt;
|
|
if (ctx->gainedExp == 0) {
|
|
ctx->gainedExp = 1;
|
|
}
|
|
ctx->partyGainedExp = (totalExp / 2) / expShareMonsCnt;
|
|
if (ctx->partyGainedExp == 0) {
|
|
ctx->partyGainedExp = 1;
|
|
}
|
|
} else {
|
|
ctx->gainedExp = totalExp / expMonsCnt;
|
|
if (ctx->gainedExp == 0) {
|
|
ctx->gainedExp = 1;
|
|
}
|
|
ctx->partyGainedExp = 0;
|
|
}
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void Task_GetExp(SysTask *task, void *data);
|
|
|
|
BOOL BtlCmd_StartGetExpTask(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
ctx->getterWork = AllocFromHeap(HEAP_ID_BATTLE, sizeof(GetterWork));
|
|
|
|
ctx->getterWork->bsys = bsys;
|
|
ctx->getterWork->ctx = ctx;
|
|
ctx->getterWork->state = 0;
|
|
ctx->getterWork->unk30[6] = 0;
|
|
|
|
SysTask_CreateOnMainQueue(Task_GetExp, ctx->getterWork, 0);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_WaitGetExpTask(BattleSystem *bsys, BattleContext *ctx) {
|
|
if (ctx->getterWork == NULL) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
}
|
|
|
|
ctx->battleContinueFlag = 1;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_WaitGetExpTaskLoop(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
BattleScriptReadWord(ctx);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_ShowParty(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId, unkA, unkB;
|
|
int maxBattlers = BattleSystem_GetMaxBattlers(bsys);
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
unkB = 0;
|
|
|
|
for (battlerId = 0; battlerId < maxBattlers; battlerId++) {
|
|
if (ctx->unk_13C[battlerId] & 1) {
|
|
unkB |= MaskOfFlagNo(battlerId);
|
|
BattleController_EmitShowMonList(bsys, ctx, battlerId, 1, 0, 6);
|
|
}
|
|
}
|
|
|
|
for (battlerId = 0; battlerId < maxBattlers; battlerId++) {
|
|
if (BattleSystem_GetBattleType(bsys) == (BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLES | BATTLE_TYPE_LINK)) {
|
|
unkA = BattleSystem_GetBattlerIdPartner(bsys, battlerId);
|
|
if (!(unkB & MaskOfFlagNo(battlerId)) && !(unkB & MaskOfFlagNo(unkA))) {
|
|
unkB |= MaskOfFlagNo(battlerId);
|
|
BattleController_EmitShowWaitMessage(bsys, battlerId);
|
|
}
|
|
} else {
|
|
if (!(unkB & MaskOfFlagNo(battlerId))) {
|
|
BattleController_EmitShowWaitMessage(bsys, battlerId);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (battlerId = 0; battlerId < maxBattlers; battlerId++) {
|
|
if (ctx->unk_13C[battlerId] & 1) {
|
|
ctx->battlerIdSwitch = battlerId;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_WaitMonSelection(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
|
|
int maxBattlers = BattleSystem_GetMaxBattlers(bsys);
|
|
int switchCnt = 0;
|
|
|
|
for (battlerId = 0; battlerId < maxBattlers; battlerId++) {
|
|
if (ctx->unk_13C[battlerId] & 1) {
|
|
switchCnt++;
|
|
}
|
|
}
|
|
|
|
for (battlerId = 0; battlerId < maxBattlers; battlerId++) {
|
|
if ((ctx->unk_13C[battlerId] & 1) && BattleBuffer_GetNext(ctx, battlerId)) {
|
|
ctx->unk_21A0[battlerId] = ctx->battleBuffer[battlerId][0] - 1;
|
|
switchCnt--;
|
|
if (!(ctx->battleStatus2 & (MaskOfFlagNo(battlerId) << BATTLE_STATUS_FAINTED_SHIFT))) {
|
|
ctx->battleStatus2 |= (MaskOfFlagNo(battlerId) << BATTLE_STATUS_FAINTED_SHIFT);
|
|
BattleController_EmitShowWaitMessage(bsys, battlerId);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (switchCnt == 0) {
|
|
for (battlerId = 0; battlerId < maxBattlers; battlerId++) {
|
|
if ((ctx->unk_13C[battlerId] & 1) && BattleBuffer_GetNext(ctx, battlerId)) {
|
|
ov12_0223BDDC(bsys, battlerId, ctx->battleBuffer[battlerId][0]);
|
|
}
|
|
}
|
|
ctx->battleStatus2 &= 0xf0ffffff;
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
}
|
|
|
|
ctx->battleContinueFlag = 1;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_SwitchAndUpdateMon(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
|
|
int battlerId;
|
|
|
|
switch (side) {
|
|
case BATTLER_CATEGORY_ATTACKER:
|
|
battlerId = ctx->battlerIdAttacker;
|
|
break;
|
|
case BATTLER_CATEGORY_SWITCHED_MON:
|
|
battlerId = ctx->battlerIdSwitch;
|
|
break;
|
|
case BATTLER_CATEGORY_FORCED_OUT:
|
|
battlerId = ctx->battlerIdTarget;
|
|
break;
|
|
}
|
|
|
|
ctx->unk_13C[battlerId] &= ~1;
|
|
ctx->switchInFlag &= (MaskOfFlagNo(battlerId) ^ ~0);
|
|
ctx->selectedMonIndex[battlerId] = ctx->unk_21A0[battlerId];
|
|
ctx->unk_21A0[battlerId] = 6;
|
|
|
|
BattleSystem_GetBattleMon(bsys, ctx, battlerId, ctx->selectedMonIndex[battlerId]);
|
|
ov12_02256F78(bsys, ctx, battlerId, ctx->selectedMonIndex[battlerId]);
|
|
|
|
ctx->hpTemp = ctx->battleMons[1].hp;
|
|
|
|
InitSwitchWork(bsys, ctx, battlerId);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_GoToIfAnySwitches(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
int maxBattlers = BattleSystem_GetMaxBattlers(bsys);
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u32 adrs = BattleScriptReadWord(ctx);
|
|
|
|
for (battlerId = 0; battlerId < maxBattlers; battlerId++) {
|
|
if (ctx->unk_13C[battlerId] & 1) {
|
|
ctx->battlerIdSwitch = battlerId;
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void Task_GetPokemon(SysTask *task, void *data);
|
|
|
|
BOOL BtlCmd_StartCatchMonTask(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int unkA = BattleScriptReadWord(ctx);
|
|
|
|
ctx->getterWork = (GetterWork *)AllocFromHeap(HEAP_ID_BATTLE, sizeof(GetterWork));
|
|
ctx->getterWork->bsys = bsys;
|
|
ctx->getterWork->ctx = ctx;
|
|
ctx->getterWork->state = 0;
|
|
ctx->getterWork->unk24 = unkA;
|
|
ctx->getterWork->unk2C = ItemToBallId(ctx->itemTemp);
|
|
|
|
SysTask_CreateOnMainQueue(Task_GetPokemon, ctx->getterWork, 0);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_WaitCatchMonTask(BattleSystem *bsys, BattleContext *ctx) {
|
|
if (ctx->getterWork == NULL) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
}
|
|
|
|
ctx->battleContinueFlag = 1;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_SetMultiHit(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int cnt = BattleScriptReadWord(ctx);
|
|
int checkMultiHit = BattleScriptReadWord(ctx);
|
|
|
|
if (ctx->multiHitCountTemp == 0) {
|
|
if (cnt == 0) {
|
|
if (GetBattlerAbility(ctx, ctx->battlerIdAttacker) == ABILITY_SKILL_LINK) {
|
|
cnt = 5;
|
|
} else if ((cnt = BattleSystem_Random(bsys) & 3) < 2) {
|
|
cnt += 2;
|
|
} else {
|
|
cnt = (BattleSystem_Random(bsys) & 3) + 2;
|
|
}
|
|
}
|
|
ctx->multiHitCount = cnt;
|
|
ctx->multiHitCountTemp = cnt;
|
|
ctx->checkMultiHit = checkMultiHit;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_UpdateVar(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int opcode = BattleScriptReadWord(ctx);
|
|
int varId = BattleScriptReadWord(ctx);
|
|
int val = BattleScriptReadWord(ctx);
|
|
|
|
int *var = BattleScriptGetVarPointer(bsys, ctx, varId);
|
|
|
|
switch (opcode) {
|
|
case OPCODE_SET:
|
|
*var = val;
|
|
break;
|
|
case OPCODE_ADD:
|
|
*var += val;
|
|
break;
|
|
case OPCODE_SUB:
|
|
*var -= val;
|
|
break;
|
|
case OPCODE_FLAG_ON:
|
|
*var |= val;
|
|
break;
|
|
case OPCODE_FLAG_OFF:
|
|
*var &= (val ^ ~0);
|
|
break;
|
|
case OPCODE_MUL:
|
|
*var *= val;
|
|
break;
|
|
case OPCODE_DIV:
|
|
*var /= val;
|
|
break;
|
|
case OPCODE_LEFT_SHIFT:
|
|
*var <<= val;
|
|
break;
|
|
case OPCODE_RIGHT_SHIFT: {
|
|
u32 uvar = *var;
|
|
*var = uvar >> val;
|
|
break;
|
|
}
|
|
case OPCODE_FLAG_INDEX:
|
|
*var = MaskOfFlagNo(val);
|
|
break;
|
|
case OPCODE_GET:
|
|
GF_ASSERT(FALSE);
|
|
break;
|
|
case OPCODE_SUB_TO_ZERO:
|
|
*var -= val;
|
|
if (*var < 0) {
|
|
*var = 0;
|
|
}
|
|
break;
|
|
case OPCODE_BITWISE_XOR:
|
|
*var ^= val;
|
|
break;
|
|
case OPCODE_BITWISE_AND:
|
|
*var &= val;
|
|
break;
|
|
default:
|
|
GF_ASSERT(FALSE);
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_ChangeStatStage(BattleSystem *bsys, BattleContext *ctx) {
|
|
int change, stat;
|
|
BattleMon *mon = &ctx->battleMons[ctx->battlerIdStatChange];
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int unkA = BattleScriptReadWord(ctx);
|
|
int unkB = BattleScriptReadWord(ctx);
|
|
int unkC = BattleScriptReadWord(ctx);
|
|
|
|
int unkD = 0;
|
|
|
|
ctx->battleStatus &= ~BATTLE_STATUS_FAIL_STAT_STAGE_CHANGE;
|
|
|
|
if (ctx->statChangeParam >= 46) {
|
|
stat = ctx->statChangeParam - 46;
|
|
change = -2;
|
|
ctx->tempData = 13;
|
|
} else if (ctx->statChangeParam >= 39) {
|
|
stat = ctx->statChangeParam - 39;
|
|
change = 2;
|
|
ctx->tempData = 12;
|
|
} else if (ctx->statChangeParam >= 22) {
|
|
stat = ctx->statChangeParam - 22;
|
|
change = -1;
|
|
ctx->tempData = 13;
|
|
} else {
|
|
stat = ctx->statChangeParam - 15;
|
|
change = 1;
|
|
ctx->tempData = 12;
|
|
}
|
|
|
|
if (change > 0) { // Stat Increase
|
|
if (mon->statChanges[stat + 1] == 12) {
|
|
ctx->battleStatus |= BATTLE_STATUS_FAIL_STAT_STAGE_CHANGE;
|
|
if (ctx->statChangeType == 3 || ctx->statChangeType == 2) {
|
|
BattleScriptIncrementPointer(ctx, unkB);
|
|
} else {
|
|
ctx->buffMsg.id = msg_0197_00142; //{0}'s {1} won't go any higher!
|
|
ctx->buffMsg.tag = TAG_NICKNAME_STAT;
|
|
ctx->buffMsg.param[0] = CreateNicknameTag(ctx, ctx->battlerIdStatChange);
|
|
ctx->buffMsg.param[1] = stat + 1;
|
|
BattleScriptIncrementPointer(ctx, unkA);
|
|
}
|
|
} else {
|
|
if (ctx->statChangeType == 3) {
|
|
ctx->buffMsg.id = msg_0197_00622; //{0}'s {1} raised its {2}
|
|
ctx->buffMsg.tag = TAG_NICKNAME_ABILITY_STAT;
|
|
ctx->buffMsg.param[0] = CreateNicknameTag(ctx, ctx->battlerIdStatChange);
|
|
ctx->buffMsg.param[1] = ctx->battleMons[ctx->battlerIdStatChange].ability;
|
|
ctx->buffMsg.param[2] = stat + 1;
|
|
} else if (ctx->statChangeType == 5) {
|
|
ctx->buffMsg.id = msg_0197_00756; // The {1} raised {0}'s {2}
|
|
ctx->buffMsg.tag = TAG_NICKNAME_ITEM_STAT;
|
|
ctx->buffMsg.param[0] = CreateNicknameTag(ctx, ctx->battlerIdStatChange);
|
|
ctx->buffMsg.param[1] = ctx->itemTemp;
|
|
ctx->buffMsg.param[2] = stat + 1;
|
|
} else {
|
|
ctx->buffMsg.id = (change == 1) ? msg_0197_00750 : msg_0197_00753; //{0}'s {1} (sharply) rose!
|
|
ctx->buffMsg.tag = TAG_NICKNAME_STAT;
|
|
ctx->buffMsg.param[0] = CreateNicknameTag(ctx, ctx->battlerIdStatChange);
|
|
ctx->buffMsg.param[1] = stat + 1;
|
|
}
|
|
mon->statChanges[stat + 1] += change;
|
|
if (mon->statChanges[stat + 1] > 12) {
|
|
mon->statChanges[stat + 1] = 12;
|
|
}
|
|
}
|
|
} else { // Stat Decrease
|
|
if (!(ctx->statChangeFlag & (1 << 27))) {
|
|
if (ctx->battlerIdAttacker != ctx->battlerIdStatChange) {
|
|
// Mist
|
|
if (ctx->fieldSideConditionData[BattleSystem_GetFieldSide(bsys, ctx->battlerIdStatChange)].mistTurns) {
|
|
ctx->buffMsg.id = msg_0197_00273; // {0} is protected by Mist!
|
|
ctx->buffMsg.tag = TAG_NICKNAME;
|
|
ctx->buffMsg.param[0] = CreateNicknameTag(ctx, ctx->battlerIdStatChange);
|
|
unkD = 1;
|
|
} else if (CheckBattlerAbilityIfNotIgnored(ctx, ctx->battlerIdAttacker, ctx->battlerIdStatChange, ABILITY_CLEAR_BODY) == TRUE || CheckBattlerAbilityIfNotIgnored(ctx, ctx->battlerIdAttacker, ctx->battlerIdStatChange, ABILITY_WHITE_SMOKE) == TRUE) {
|
|
if (ctx->statChangeType == 3) {
|
|
ctx->buffMsg.id = msg_0197_00727; //{0}'s {1} suppressed {2}'s {3}
|
|
ctx->buffMsg.tag = TAG_NICKNAME_ABILITY_NICKNAME_ABILITY;
|
|
ctx->buffMsg.param[0] = CreateNicknameTag(ctx, ctx->battlerIdStatChange);
|
|
ctx->buffMsg.param[1] = ctx->battleMons[ctx->battlerIdStatChange].ability;
|
|
ctx->buffMsg.param[2] = CreateNicknameTag(ctx, ctx->battlerIdAttacker);
|
|
ctx->buffMsg.param[3] = ctx->battleMons[ctx->battlerIdAttacker].ability;
|
|
} else {
|
|
ctx->buffMsg.id = msg_0197_00669; //{0}'s {1} prevents stat loss!
|
|
ctx->buffMsg.tag = TAG_NICKNAME_ABILITY;
|
|
ctx->buffMsg.param[0] = CreateNicknameTag(ctx, ctx->battlerIdStatChange);
|
|
ctx->buffMsg.param[1] = ctx->battleMons[ctx->battlerIdStatChange].ability;
|
|
}
|
|
unkD = TRUE;
|
|
} else if ((CheckBattlerAbilityIfNotIgnored(ctx, ctx->battlerIdAttacker, ctx->battlerIdStatChange, ABILITY_KEEN_EYE) == TRUE && (1 + stat) == 6) || (CheckBattlerAbilityIfNotIgnored(ctx, ctx->battlerIdAttacker, ctx->battlerIdStatChange, ABILITY_HYPER_CUTTER) == TRUE && (1 + stat) == 1)) {
|
|
if (ctx->statChangeType == 3) {
|
|
ctx->buffMsg.id = msg_0197_00727; //{0}'s {1} suppressed {2}'s {3}
|
|
ctx->buffMsg.tag = TAG_NICKNAME_ABILITY_NICKNAME_ABILITY;
|
|
ctx->buffMsg.param[0] = CreateNicknameTag(ctx, ctx->battlerIdStatChange);
|
|
ctx->buffMsg.param[1] = ctx->battleMons[ctx->battlerIdStatChange].ability;
|
|
ctx->buffMsg.param[2] = CreateNicknameTag(ctx, ctx->battlerIdAttacker);
|
|
ctx->buffMsg.param[3] = ctx->battleMons[ctx->battlerIdAttacker].ability;
|
|
} else {
|
|
ctx->buffMsg.id = msg_0197_00704; //{0}'s {1} prvents {2} loss!
|
|
ctx->buffMsg.tag = TAG_NICKNAME_ABILITY_STAT;
|
|
ctx->buffMsg.param[0] = CreateNicknameTag(ctx, ctx->battlerIdStatChange);
|
|
ctx->buffMsg.param[1] = ctx->battleMons[ctx->battlerIdStatChange].ability;
|
|
ctx->buffMsg.param[2] = stat + 1;
|
|
}
|
|
unkD = TRUE;
|
|
} else if (mon->statChanges[1 + stat] == 0) {
|
|
ctx->battleStatus |= BATTLE_STATUS_FAIL_STAT_STAGE_CHANGE;
|
|
if (ctx->statChangeType == 2 || ctx->statChangeType == 3) {
|
|
BattleScriptIncrementPointer(ctx, unkB);
|
|
return FALSE;
|
|
} else {
|
|
ctx->buffMsg.id = msg_0197_00145; //{0}'s {1} won't go lower!
|
|
ctx->buffMsg.tag = TAG_NICKNAME_STAT;
|
|
ctx->buffMsg.param[0] = CreateNicknameTag(ctx, ctx->battlerIdStatChange);
|
|
ctx->buffMsg.param[1] = stat + 1;
|
|
BattleScriptIncrementPointer(ctx, unkA);
|
|
return FALSE;
|
|
}
|
|
} else if (CheckBattlerAbilityIfNotIgnored(ctx, ctx->battlerIdAttacker, ctx->battlerIdStatChange, ABILITY_SHIELD_DUST) == TRUE && ctx->statChangeType == 2) {
|
|
unkD = 1;
|
|
} else if (ctx->battleMons[ctx->battlerIdStatChange].status2 & STATUS2_SUBSTITUTE) {
|
|
unkD = 2;
|
|
}
|
|
} else if (mon->statChanges[1 + stat] == 0) {
|
|
ctx->battleStatus |= BATTLE_STATUS_FAIL_STAT_STAGE_CHANGE;
|
|
if (ctx->statChangeType == 2 || ctx->statChangeType == 3) {
|
|
BattleScriptIncrementPointer(ctx, unkB);
|
|
return FALSE;
|
|
} else {
|
|
ctx->buffMsg.id = msg_0197_00145; //{0}'s {1} won't go lower!
|
|
ctx->buffMsg.tag = TAG_NICKNAME_STAT;
|
|
ctx->buffMsg.param[0] = CreateNicknameTag(ctx, ctx->battlerIdStatChange);
|
|
ctx->buffMsg.param[1] = stat + 1;
|
|
BattleScriptIncrementPointer(ctx, unkA);
|
|
return FALSE;
|
|
}
|
|
}
|
|
if (unkD == 2 && ctx->statChangeType == 1) {
|
|
BattleScriptIncrementPointer(ctx, unkC);
|
|
return FALSE;
|
|
} else if (unkD && ctx->statChangeType == 2) {
|
|
BattleScriptIncrementPointer(ctx, unkB);
|
|
return FALSE;
|
|
} else if (unkD) {
|
|
BattleScriptIncrementPointer(ctx, unkA);
|
|
return FALSE;
|
|
}
|
|
}
|
|
if (ctx->statChangeType == 3) {
|
|
ctx->buffMsg.id = msg_0197_00662; //{0}'s {1} cuts {2}'s {3}
|
|
ctx->buffMsg.tag = TAG_NICKNAME_ABILITY_NICKNAME_STAT;
|
|
ctx->buffMsg.param[0] = CreateNicknameTag(ctx, ctx->battlerIdAttacker);
|
|
ctx->buffMsg.param[1] = ctx->battleMons[ctx->battlerIdAttacker].ability;
|
|
ctx->buffMsg.param[2] = CreateNicknameTag(ctx, ctx->battlerIdStatChange);
|
|
ctx->buffMsg.param[3] = stat + 1;
|
|
} else {
|
|
ctx->buffMsg.id = (change == -1) ? msg_0197_00762 : msg_0197_00765; //{0}'s {1} (harsly) fell!
|
|
ctx->buffMsg.tag = TAG_NICKNAME_STAT;
|
|
ctx->buffMsg.param[0] = CreateNicknameTag(ctx, ctx->battlerIdStatChange);
|
|
ctx->buffMsg.param[1] = stat + 1;
|
|
}
|
|
mon->statChanges[stat + 1] += change;
|
|
if (mon->statChanges[stat + 1] < 0) {
|
|
mon->statChanges[stat + 1] = 0;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// TODO: Move to above of file once defined as static
|
|
void BattlerSetAbility(BattleContext *ctx, u8 a1, u8 a2);
|
|
|
|
BOOL BtlCmd_UpdateMonData(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int opcode = BattleScriptReadWord(ctx);
|
|
int side = BattleScriptReadWord(ctx);
|
|
int varId = BattleScriptReadWord(ctx);
|
|
int val = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
int var = GetBattlerVar(ctx, battlerId, varId, NULL);
|
|
|
|
switch (opcode) {
|
|
case 7:
|
|
var = val;
|
|
break;
|
|
case 8:
|
|
var += val;
|
|
break;
|
|
case 9:
|
|
var -= val;
|
|
break;
|
|
case 10:
|
|
var |= val;
|
|
break;
|
|
case 11:
|
|
var &= (val ^ ~0);
|
|
break;
|
|
case 12:
|
|
var *= val;
|
|
break;
|
|
case 13:
|
|
var /= val;
|
|
break;
|
|
case 14:
|
|
var <<= val;
|
|
break;
|
|
case 15: {
|
|
u32 uvar = var;
|
|
var = uvar >> val;
|
|
break;
|
|
}
|
|
case 16:
|
|
var = MaskOfFlagNo(val);
|
|
break;
|
|
case 17:
|
|
GF_ASSERT(FALSE);
|
|
break;
|
|
case 18:
|
|
var -= val;
|
|
if (var < 0) {
|
|
var = 0;
|
|
}
|
|
break;
|
|
case 19:
|
|
var ^= val;
|
|
break;
|
|
case 20:
|
|
var &= val;
|
|
break;
|
|
default:
|
|
GF_ASSERT(FALSE);
|
|
break;
|
|
}
|
|
|
|
if (varId == BMON_DATA_ABILITY) {
|
|
BattlerSetAbility(ctx, battlerId, var);
|
|
}
|
|
|
|
SetBattlerVar(ctx, battlerId, varId, &var);
|
|
CopyBattleMonToPartyMon(bsys, ctx, battlerId);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_ClearVolatileStatus(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int var = BattleScriptReadWord(ctx);
|
|
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
ctx->unk_218C[battlerId] |= var;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_ToggleVanish(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int unkA = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
BattleController_EmitToggleVanish(bsys, battlerId, unkA);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckAbility(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int unkA = BattleScriptReadWord(ctx);
|
|
int side = BattleScriptReadWord(ctx);
|
|
int ability = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (side == BATTLER_CATEGORY_ALL) {
|
|
int maxBattlers = BattleSystem_GetMaxBattlers(bsys);
|
|
|
|
for (battlerId = 0; battlerId < maxBattlers; battlerId++) {
|
|
if (unkA == 0) {
|
|
if (GetBattlerAbility(ctx, battlerId) == ability) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
ctx->battlerIdAbility = battlerId;
|
|
break;
|
|
}
|
|
} else if (GetBattlerAbility(ctx, battlerId) == ability) {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
if (unkA == 0) {
|
|
if (GetBattlerAbility(ctx, battlerId) == ability) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
ctx->battlerIdAbility = battlerId;
|
|
}
|
|
} else if (GetBattlerAbility(ctx, battlerId) != ability) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
ctx->battlerIdAbility = battlerId;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_Random(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int modulo = BattleScriptReadWord(ctx);
|
|
modulo += 1;
|
|
|
|
int x0 = BattleScriptReadWord(ctx);
|
|
|
|
ctx->calcTemp = BattleSystem_Random(bsys) % modulo + x0;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_UpdateVar2(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int opcode = BattleScriptReadWord(ctx);
|
|
int varId = BattleScriptReadWord(ctx);
|
|
int valId = BattleScriptReadWord(ctx);
|
|
|
|
int *var = BattleScriptGetVarPointer(bsys, ctx, varId);
|
|
int *val = BattleScriptGetVarPointer(bsys, ctx, valId);
|
|
|
|
switch (opcode) {
|
|
case 7:
|
|
*var = *val;
|
|
break;
|
|
case 8:
|
|
*var += *val;
|
|
break;
|
|
case 9:
|
|
*var -= *val;
|
|
break;
|
|
case 10:
|
|
*var |= *val;
|
|
break;
|
|
case 11:
|
|
*var &= (*val ^ ~0);
|
|
break;
|
|
case 12:
|
|
*var *= *val;
|
|
break;
|
|
case 13:
|
|
*var /= *val;
|
|
break;
|
|
case 14:
|
|
*var <<= *val;
|
|
break;
|
|
case 15: {
|
|
u32 uvar = *var;
|
|
*var = uvar >> *val;
|
|
break;
|
|
}
|
|
case 16:
|
|
*var = MaskOfFlagNo(*val);
|
|
break;
|
|
case 17:
|
|
*val = *var;
|
|
break;
|
|
case 18:
|
|
*var -= *val;
|
|
if (*var < 0) {
|
|
*var = 0;
|
|
}
|
|
break;
|
|
case 19:
|
|
*var ^= *val;
|
|
break;
|
|
case 20:
|
|
*var &= *val;
|
|
break;
|
|
default:
|
|
GF_ASSERT(FALSE);
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_UpdateMonDataFromVar(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int opcode = BattleScriptReadWord(ctx);
|
|
int side = BattleScriptReadWord(ctx);
|
|
int varId = BattleScriptReadWord(ctx);
|
|
int valId = BattleScriptReadWord(ctx);
|
|
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
int var = GetBattlerVar(ctx, battlerId, varId, NULL);
|
|
int *val = BattleScriptGetVarPointer(bsys, ctx, valId);
|
|
|
|
switch (opcode) {
|
|
case 7:
|
|
var = *val;
|
|
break;
|
|
case 8:
|
|
var += *val;
|
|
break;
|
|
case 9:
|
|
var -= *val;
|
|
break;
|
|
case 10:
|
|
var |= *val;
|
|
break;
|
|
case 11:
|
|
var &= (*val ^ ~0);
|
|
break;
|
|
case 12:
|
|
var *= *val;
|
|
break;
|
|
case 13:
|
|
var /= *val;
|
|
break;
|
|
case 14:
|
|
var <<= *val;
|
|
break;
|
|
case 15: {
|
|
u32 uvar = var;
|
|
var = uvar >> *val;
|
|
break;
|
|
}
|
|
case 16:
|
|
var = MaskOfFlagNo(*val);
|
|
break;
|
|
case 17:
|
|
*val = var;
|
|
break;
|
|
case 18:
|
|
var -= *val;
|
|
if (var < 0) {
|
|
var = 0;
|
|
}
|
|
break;
|
|
case 19:
|
|
var ^= *val;
|
|
break;
|
|
case 20:
|
|
var &= *val;
|
|
break;
|
|
default:
|
|
GF_ASSERT(FALSE);
|
|
break;
|
|
}
|
|
|
|
if (opcode != 17) {
|
|
if (varId == BMON_DATA_ABILITY) {
|
|
BattlerSetAbility(ctx, battlerId, var);
|
|
}
|
|
SetBattlerVar(ctx, battlerId, varId, &var);
|
|
CopyBattleMonToPartyMon(bsys, ctx, battlerId);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_Goto(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
BattleScriptIncrementPointer(ctx, BattleScriptReadWord(ctx));
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_Call(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
BattleScriptGotoSubscript(ctx, NARC_a_0_0_1, BattleScriptReadWord(ctx));
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CallFromVar(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
int *var = BattleScriptGetVarPointer(bsys, ctx, BattleScriptReadWord(ctx));
|
|
BattleScriptGotoSubscript(ctx, NARC_a_0_0_1, *var);
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_SetMirrorMove(BattleSystem *bsys, BattleContext *ctx) {
|
|
int move = 0;
|
|
int battleType = BattleSystem_GetBattleType(bsys);
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
if (ctx->moveNoCopied[ctx->battlerIdAttacker]) {
|
|
move = ctx->moveNoCopied[ctx->battlerIdAttacker];
|
|
} else if (battleType & BATTLE_TYPE_DOUBLES) {
|
|
move = ctx->moveNoCopiedHit[ctx->battlerIdAttacker][0] + ctx->moveNoCopiedHit[ctx->battlerIdAttacker][1] + ctx->moveNoCopiedHit[ctx->battlerIdAttacker][2] + ctx->moveNoCopiedHit[ctx->battlerIdAttacker][3];
|
|
if (move) {
|
|
do {
|
|
move = ctx->moveNoCopiedHit[ctx->battlerIdAttacker][BattleSystem_Random(bsys) % 4];
|
|
} while (!move);
|
|
}
|
|
}
|
|
if (move && IsMoveEncored(ctx, move) == TRUE) {
|
|
ctx->battleStatus &= ~BATTLE_STATUS_NO_ATTACK_MESSAGE;
|
|
ctx->battleStatus &= ~BATTLE_STATUS_MOVE_ANIMATIONS_OFF;
|
|
ctx->moveNoCur = move;
|
|
ctx->battlerIdTarget = ov12_022506D4(bsys, ctx, ctx->battlerIdAttacker, move, 1, 0);
|
|
if (ctx->battlerIdTarget == BATTLER_NONE) {
|
|
ctx->commandNext = CONTROLLER_COMMAND_39;
|
|
BattleScriptJump(ctx, NARC_a_0_0_1, BATTLE_SUBSCRIPT_NO_TARGET);
|
|
} else {
|
|
ctx->playerActions[ctx->battlerIdAttacker].unk4 = ctx->battlerIdTarget;
|
|
BattleScriptJump(ctx, NARC_a_0_0_0, move);
|
|
}
|
|
} else {
|
|
ctx->selfTurnData[ctx->battlerIdAttacker].ignorePressure = 1;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_ResetAllStatChanges(BattleSystem *bsys, BattleContext *ctx) {
|
|
int stat, battlerId;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int battlersMax = BattleSystem_GetMaxBattlers(bsys);
|
|
|
|
for (battlerId = 0; battlerId < battlersMax; battlerId++) {
|
|
for (stat = 0; stat < 8; stat++) {
|
|
ctx->battleMons[battlerId].statChanges[stat] = 6;
|
|
}
|
|
ctx->battleMons[battlerId].status2 &= ~STATUS2_FOCUS_ENERGY;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_LockMoveChoice(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
LockBattlerIntoCurrentMove(bsys, ctx, GetBattlerIDBySide(bsys, ctx, BattleScriptReadWord(ctx)));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_UnlockMoveChoice(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
UnlockBattlerOutOfCurrentMove(bsys, ctx, GetBattlerIDBySide(bsys, ctx, BattleScriptReadWord(ctx)));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_SetHealthbarStatus(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int status = BattleScriptReadWord(ctx);
|
|
|
|
BattleController_EmitHealthbarStatus(bsys, GetBattlerIDBySide(bsys, ctx, side), status);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PrintTrainerMessage(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int msg = BattleScriptReadWord(ctx);
|
|
|
|
BattleController_EmitPrintTrainerMessage(bsys, GetBattlerIDBySide(bsys, ctx, side), msg);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern u16 sPrizeMoneyTbl[0x81][2];
|
|
|
|
u32 CalcPrizeMoney(BattleSystem *bsys, BattleContext *ctx, int trainerIndex) {
|
|
int i;
|
|
TRPOKE *trPoke;
|
|
u32 prizeMoney;
|
|
u8 level = 0;
|
|
u8 trainerClass;
|
|
Trainer trainer;
|
|
|
|
trPoke = AllocFromHeap(HEAP_ID_BATTLE, sizeof(TRPOKE) * 6);
|
|
|
|
TrainerData_ReadTrData(bsys->trainerId[trainerIndex], &trainer);
|
|
TrainerData_ReadTrPoke(bsys->trainerId[trainerIndex], trPoke);
|
|
|
|
switch (trainer.data.trainerType) {
|
|
default:
|
|
case 0: {
|
|
TRPOKE_NOITEM_DFLTMOVES *pokeDef = (TRPOKE_NOITEM_DFLTMOVES *)trPoke;
|
|
level = pokeDef[trainer.data.npoke - 1].level;
|
|
break;
|
|
}
|
|
case 1: {
|
|
TRPOKE_NOITEM_CUSTMOVES *pokeCust = (TRPOKE_NOITEM_CUSTMOVES *)trPoke;
|
|
level = pokeCust[trainer.data.npoke - 1].level;
|
|
break;
|
|
}
|
|
case 2: {
|
|
TRPOKE_ITEM_DFLTMOVES *pokeItem = (TRPOKE_ITEM_DFLTMOVES *)trPoke;
|
|
level = pokeItem[trainer.data.npoke - 1].level;
|
|
break;
|
|
}
|
|
case 3: {
|
|
TRPOKE_ITEM_CUSTMOVES *pokeCustItem = (TRPOKE_ITEM_CUSTMOVES *)trPoke;
|
|
level = pokeCustItem[trainer.data.npoke - 1].level;
|
|
break;
|
|
}
|
|
}
|
|
|
|
i = 0;
|
|
trainerClass = trainer.data.trainerClass;
|
|
|
|
do {
|
|
if (trainerClass != sPrizeMoneyTbl[i][0]) {
|
|
i++;
|
|
if (i < (int)NELEMS(sPrizeMoneyTbl)) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (i >= (int)NELEMS(sPrizeMoneyTbl)) {
|
|
GF_ASSERT(FALSE);
|
|
}
|
|
if (i >= (int)NELEMS(sPrizeMoneyTbl)) {
|
|
i = 2;
|
|
}
|
|
if (bsys->battleType & BATTLE_TYPE_TAG || bsys->battleType == (BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLES | BATTLE_TYPE_MULTI | BATTLE_TYPE_AI)) {
|
|
prizeMoney = level * 4 * ctx->prizeMoneyValue * sPrizeMoneyTbl[i][1];
|
|
break;
|
|
} else if (bsys->battleType & BATTLE_TYPE_DOUBLES) {
|
|
prizeMoney = level * 4 * ctx->prizeMoneyValue * 2 * sPrizeMoneyTbl[i][1];
|
|
break;
|
|
} else {
|
|
prizeMoney = level * 4 * ctx->prizeMoneyValue * sPrizeMoneyTbl[i][1];
|
|
break;
|
|
}
|
|
|
|
} while (TRUE);
|
|
|
|
FreeToHeap(trPoke);
|
|
|
|
return prizeMoney;
|
|
}
|
|
|
|
BOOL BtlCmd_PayPrizeMoney(BattleSystem *bsys, BattleContext *ctx) {
|
|
u32 prizeMoney;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
if (bsys->battleOutcomeFlag == 1) {
|
|
prizeMoney = CalcPrizeMoney(bsys, ctx, 1);
|
|
if (bsys->battleType & BATTLE_TYPE_TAG || bsys->battleType == (BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLES | BATTLE_TYPE_MULTI | BATTLE_TYPE_AI)) {
|
|
prizeMoney += CalcPrizeMoney(bsys, ctx, 3);
|
|
}
|
|
PlayerProfile_AddMoney(BattleSystem_GetPlayerProfile(bsys, 0), prizeMoney);
|
|
} else {
|
|
prizeMoney = CalcMoneyLoss(bsys->trainerParty[0], bsys->playerProfile[0]);
|
|
PlayerProfile_SubMoney(BattleSystem_GetPlayerProfile(bsys, 0), prizeMoney);
|
|
}
|
|
|
|
if (prizeMoney) {
|
|
ctx->msgTemp = prizeMoney;
|
|
} else {
|
|
ctx->msgTemp = 0;
|
|
}
|
|
|
|
ctx->tempData = bsys->unk2474_1;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PlayBattleAnimation(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int status = BattleScriptReadWord(ctx);
|
|
|
|
if (BattleSystem_AreBattleAnimationsOn(bsys) == TRUE || status == 15 || status == 16 || status == 25 || status == 26) {
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
if (CheckStatusEffectsSubstitute(ctx, battlerId, status) == TRUE) {
|
|
BattleController_EmitSetStatus2Effect(bsys, ctx, battlerId, status);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PlayBattleAnimationOnMons(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int sideA = BattleScriptReadWord(ctx);
|
|
int sideB = BattleScriptReadWord(ctx);
|
|
int status = BattleScriptReadWord(ctx);
|
|
|
|
if (BattleSystem_AreBattleAnimationsOn(bsys) == TRUE || status == 15 || status == 16 || status == 26 || status == 25) {
|
|
int battlerIdA = GetBattlerIDBySide(bsys, ctx, sideA);
|
|
int battlerIdB = GetBattlerIDBySide(bsys, ctx, sideB);
|
|
if (CheckStatusEffectsSubstitute(ctx, battlerIdA, status) == TRUE && CheckStatusEffectsSubstitute(ctx, battlerIdB, status) == TRUE) {
|
|
BattleController_EmitCopyStatus2Effect(bsys, ctx, battlerIdA, battlerIdB, status);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PlayBattleAnimationFromVar(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int status = BattleScriptReadWord(ctx);
|
|
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
int *data = BattleScriptGetVarPointer(bsys, ctx, status);
|
|
|
|
if (BattleSystem_AreBattleAnimationsOn(bsys) == TRUE || status == 15 || status == 16 || *data == 25 || *data == 26) {
|
|
if (CheckStatusEffectsSubstitute(ctx, battlerId, *data) == TRUE) {
|
|
BattleController_EmitSetStatus2Effect(bsys, ctx, battlerId, *data);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PrintRecallMessage(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, BattleScriptReadWord(ctx));
|
|
|
|
BattleController_EmitPrintReturnMessage(bsys, ctx, battlerId, ctx->selectedMonIndex[battlerId]);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PrintSendOutMessage(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, BattleScriptReadWord(ctx));
|
|
|
|
BattleController_EmitPrintSendOutMessage(bsys, ctx, battlerId, ctx->selectedMonIndex[battlerId]);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PrintEncounterMessage(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
BattleController_EmitPrintEncounterMessage(bsys, ctx, GetBattlerIDBySide(bsys, ctx, BattleScriptReadWord(ctx)));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PrintFirstSendOutMessage(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
BattleController_EmitPrintFirstSendOutMessage(bsys, ctx, GetBattlerIDBySide(bsys, ctx, BattleScriptReadWord(ctx)));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PrintBufferedTrainerMessage(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
BattleController_EmitPrintTrainerMessage(bsys, GetBattlerIDBySide(bsys, ctx, BattleScriptReadWord(ctx)), ctx->msgTemp);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryConversion(BattleSystem *bsys, BattleContext *ctx) {
|
|
int i, cnt, moveType;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (GetBattlerAbility(ctx, ctx->battlerIdAttacker) == ABILITY_MULTITYPE) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
return FALSE;
|
|
}
|
|
|
|
for (cnt = 0; cnt < MAX_MON_MOVES; cnt++) {
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].moves[cnt] == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < cnt; i++) {
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].moves[i] != MOVE_CONVERSION) {
|
|
moveType = ctx->trainerAIData.moveData[ctx->battleMons[ctx->battlerIdAttacker].moves[i]].type;
|
|
if (moveType == TYPE_MYSTERY) {
|
|
if (GetBattlerVar(ctx, ctx->battlerIdAttacker, BMON_DATA_TYPE_1, NULL) == TYPE_GHOST || GetBattlerVar(ctx, ctx->battlerIdAttacker, BMON_DATA_TYPE_2, NULL) == TYPE_GHOST) {
|
|
moveType = TYPE_GHOST;
|
|
} else {
|
|
moveType = TYPE_NORMAL;
|
|
}
|
|
}
|
|
if (GetBattlerVar(ctx, ctx->battlerIdAttacker, BMON_DATA_TYPE_1, NULL) != moveType && GetBattlerVar(ctx, ctx->battlerIdAttacker, BMON_DATA_TYPE_2, NULL) != moveType) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (i == cnt) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else {
|
|
do {
|
|
do {
|
|
i = BattleSystem_Random(bsys) % cnt;
|
|
} while (ctx->battleMons[ctx->battlerIdAttacker].moves[i] == MOVE_CONVERSION);
|
|
moveType = ctx->trainerAIData.moveData[ctx->battleMons[ctx->battlerIdAttacker].moves[i]].type;
|
|
if (moveType == TYPE_MYSTERY) {
|
|
if (GetBattlerVar(ctx, ctx->battlerIdAttacker, BMON_DATA_TYPE_1, NULL) == TYPE_GHOST || GetBattlerVar(ctx, ctx->battlerIdAttacker, BMON_DATA_TYPE_2, NULL) == TYPE_GHOST) {
|
|
moveType = TYPE_GHOST;
|
|
} else {
|
|
moveType = TYPE_NORMAL;
|
|
}
|
|
}
|
|
} while (GetBattlerVar(ctx, ctx->battlerIdAttacker, BMON_DATA_TYPE_1, NULL) == moveType || GetBattlerVar(ctx, ctx->battlerIdAttacker, BMON_DATA_TYPE_2, NULL) == moveType);
|
|
ctx->battleMons[ctx->battlerIdAttacker].type1 = moveType;
|
|
ctx->battleMons[ctx->battlerIdAttacker].type2 = moveType;
|
|
ctx->msgTemp = moveType;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CompareVarToVar(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int opcode = BattleScriptReadWord(ctx);
|
|
int varNo = BattleScriptReadWord(ctx);
|
|
int cmpNo = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
u32 *var = BattleScriptGetVarPointer(bsys, ctx, varNo);
|
|
u32 *cmp = BattleScriptGetVarPointer(bsys, ctx, cmpNo);
|
|
|
|
switch (opcode) {
|
|
case 0:
|
|
if (*var != *cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 1:
|
|
if (*var == *cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (*var <= *cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 3:
|
|
if (*var > *cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 4:
|
|
if ((*var & *cmp) == 0) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 5:
|
|
if (*var & *cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 6:
|
|
if ((*var & *cmp) != *cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (adrs) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CompareMonDataToVar(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int opcode = BattleScriptReadWord(ctx);
|
|
int side = BattleScriptReadWord(ctx);
|
|
int varNo = BattleScriptReadWord(ctx);
|
|
int cmpNo = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
u32 var = GetBattlerVar(ctx, GetBattlerIDBySide(bsys, ctx, side), varNo, NULL);
|
|
u32 *cmp = BattleScriptGetVarPointer(bsys, ctx, cmpNo);
|
|
|
|
switch (opcode) {
|
|
case 0:
|
|
if (var != *cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 1:
|
|
if (var == *cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (var <= *cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 3:
|
|
if (var > *cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 4:
|
|
if ((var & *cmp) == 0) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 5:
|
|
if (var & *cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
case 6:
|
|
if ((var & *cmp) != *cmp) {
|
|
adrs = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (adrs) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_AddPayDayMoney(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
ctx->msgTemp = ctx->unk_14C * ctx->prizeMoneyValue;
|
|
|
|
if (ctx->msgTemp > 0xFFFF) {
|
|
ctx->msgTemp = 0xFFFF;
|
|
}
|
|
|
|
PlayerProfile_AddMoney(BattleSystem_GetPlayerProfile(bsys, 0), ctx->msgTemp);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryLightScreen(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int unkA = BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker);
|
|
|
|
if (ctx->fieldSideConditionFlags[unkA] & SIDE_CONDITION_LIGHT_SCREEN) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
ctx->moveStatusFlag |= 64;
|
|
} else {
|
|
ctx->fieldSideConditionFlags[unkA] |= SIDE_CONDITION_LIGHT_SCREEN;
|
|
ctx->fieldSideConditionData[unkA].lightScreenTurns = 5;
|
|
ctx->fieldSideConditionData[unkA].lightScreenBattler = ctx->battlerIdAttacker;
|
|
if (GetBattlerHeldItemEffect(ctx, ctx->battlerIdAttacker) == HOLD_EFFECT_EXTEND_SCREENS) {
|
|
ctx->fieldSideConditionData[unkA].lightScreenTurns += GetHeldItemModifier(ctx, ctx->battlerIdAttacker, 0);
|
|
}
|
|
ctx->buffMsg.tag = TAG_MOVE_SIDE;
|
|
ctx->buffMsg.param[0] = ctx->moveNoCur;
|
|
ctx->buffMsg.param[1] = ctx->battlerIdAttacker;
|
|
if (GetMonsHitCount(bsys, ctx, 1, ctx->battlerIdAttacker) == 2) {
|
|
ctx->buffMsg.id = msg_0197_00192; //{0} raised your team's special defence slightly!
|
|
} else {
|
|
ctx->buffMsg.id = msg_0197_00190; //{0} raised your team's special defence!
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryReflect(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int unkA = BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker);
|
|
|
|
if (ctx->fieldSideConditionFlags[unkA] & SIDE_CONDITION_REFLECT) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
ctx->moveStatusFlag |= 64;
|
|
} else {
|
|
ctx->fieldSideConditionFlags[unkA] |= SIDE_CONDITION_REFLECT;
|
|
ctx->fieldSideConditionData[unkA].reflectTurns = 5;
|
|
ctx->fieldSideConditionData[unkA].reflectBattler = ctx->battlerIdAttacker;
|
|
if (GetBattlerHeldItemEffect(ctx, ctx->battlerIdAttacker) == HOLD_EFFECT_EXTEND_SCREENS) {
|
|
ctx->fieldSideConditionData[unkA].reflectTurns += GetHeldItemModifier(ctx, ctx->battlerIdAttacker, 0);
|
|
}
|
|
ctx->buffMsg.tag = TAG_MOVE_SIDE;
|
|
ctx->buffMsg.param[0] = ctx->moveNoCur;
|
|
ctx->buffMsg.param[1] = ctx->battlerIdAttacker;
|
|
if (GetMonsHitCount(bsys, ctx, 1, ctx->battlerIdAttacker) == 2) {
|
|
ctx->buffMsg.id = msg_0197_00196;
|
|
} else {
|
|
ctx->buffMsg.id = msg_0197_00194;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryMist(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int unkA = BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker);
|
|
|
|
if (ctx->fieldSideConditionFlags[unkA] & SIDE_CONDITION_MIST) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
ctx->moveStatusFlag |= 64;
|
|
} else {
|
|
ctx->fieldSideConditionFlags[unkA] |= SIDE_CONDITION_MIST;
|
|
ctx->fieldSideConditionData[unkA].mistTurns = 5;
|
|
ctx->fieldSideConditionData[unkA].mistBattler = ctx->battlerIdAttacker;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryOHKOMove(BattleSystem *bsys, BattleContext *ctx) {
|
|
u16 hitChance;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
ctx->battleStatus |= BATTLE_STATUS_FLAT_HIT_RATE;
|
|
|
|
if (CheckBattlerAbilityIfNotIgnored(ctx, ctx->battlerIdAttacker, ctx->battlerIdTarget, ABILITY_STURDY) == TRUE) {
|
|
ctx->moveStatusFlag |= MOVE_STATUS_STURDY;
|
|
} else {
|
|
if (!(ctx->battleMons[ctx->battlerIdTarget].moveEffectFlags & MOVE_EFFECT_FLAG_LOCK_ON) && GetBattlerAbility(ctx, ctx->battlerIdAttacker) != ABILITY_NO_GUARD && GetBattlerAbility(ctx, ctx->battlerIdTarget) != ABILITY_NO_GUARD) {
|
|
hitChance = ctx->battleMons[ctx->battlerIdAttacker].level - ctx->battleMons[ctx->battlerIdTarget].level + ctx->trainerAIData.moveData[ctx->moveNoCur].accuracy;
|
|
if ((BattleSystem_Random(bsys) % 100) < hitChance && (ctx->battleMons[ctx->battlerIdAttacker].level >= ctx->battleMons[ctx->battlerIdTarget].level)) {
|
|
hitChance = 1;
|
|
} else {
|
|
hitChance = 0;
|
|
}
|
|
} else {
|
|
if ((((ctx->battleMons[ctx->battlerIdTarget].unk88.battlerIdLockOn == ctx->battlerIdAttacker) && (ctx->battleMons[ctx->battlerIdTarget].moveEffectFlags & MOVE_EFFECT_FLAG_LOCK_ON)) || GetBattlerAbility(ctx, ctx->battlerIdAttacker) == ABILITY_NO_GUARD || GetBattlerAbility(ctx, ctx->battlerIdTarget) == ABILITY_NO_GUARD) && ctx->battleMons[ctx->battlerIdAttacker].level >= ctx->battleMons[ctx->battlerIdTarget].level) {
|
|
hitChance = 1;
|
|
} else {
|
|
hitChance = ctx->battleMons[ctx->battlerIdAttacker].level - ctx->battleMons[ctx->battlerIdTarget].level + ctx->trainerAIData.moveData[ctx->moveNoCur].accuracy;
|
|
if ((BattleSystem_Random(bsys) % 100) < hitChance && ctx->battleMons[ctx->battlerIdAttacker].level >= ctx->battleMons[ctx->battlerIdTarget].level) {
|
|
hitChance = 1;
|
|
} else {
|
|
hitChance = 0;
|
|
}
|
|
}
|
|
ctx->moveStatusFlag |= 1 << 10;
|
|
}
|
|
|
|
if (hitChance) {
|
|
ctx->damage = -ctx->battleMons[ctx->battlerIdTarget].hp;
|
|
ctx->moveStatusFlag |= 1 << 5;
|
|
} else if (ctx->battleMons[ctx->battlerIdAttacker].level >= ctx->battleMons[ctx->battlerIdTarget].level) {
|
|
ctx->moveStatusFlag |= 1;
|
|
} else {
|
|
ctx->moveStatusFlag |= 1 << 12;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_DivideVarByValue(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int varNo = BattleScriptReadWord(ctx);
|
|
int denom = BattleScriptReadWord(ctx);
|
|
|
|
int *data = BattleScriptGetVarPointer(bsys, ctx, varNo);
|
|
|
|
*data = DamageDivide(*data, denom);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_DivideVarByVar(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int varNo = BattleScriptReadWord(ctx);
|
|
int denomNo = BattleScriptReadWord(ctx);
|
|
|
|
int *data = BattleScriptGetVarPointer(bsys, ctx, varNo);
|
|
int *denom = BattleScriptGetVarPointer(bsys, ctx, denomNo);
|
|
|
|
int sign;
|
|
|
|
if (*data < 0) {
|
|
sign = -1;
|
|
} else {
|
|
sign = 1;
|
|
}
|
|
|
|
*data /= *denom;
|
|
|
|
if (*data == 0) {
|
|
*data = sign;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryMimic(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if ((!CheckLegalMimicMove(ctx->moveNoBattlerPrev[ctx->battlerIdTarget])) || (ctx->battleMons[ctx->battlerIdAttacker].status2 & STATUS2_TRANSFORM) || (ctx->battleMons[ctx->battlerIdTarget].status2 & STATUS2_SUBSTITUTE) || ctx->moveNoBattlerPrev[ctx->battlerIdTarget] == 0) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else {
|
|
int moveIndex = 0;
|
|
int mimicIndex = -1;
|
|
|
|
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) {
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].moves[moveIndex] == ctx->moveNoBattlerPrev[ctx->battlerIdTarget]) {
|
|
break;
|
|
}
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].moves[moveIndex] == MOVE_MIMIC && mimicIndex == -1) {
|
|
mimicIndex = moveIndex;
|
|
}
|
|
}
|
|
|
|
if (moveIndex == MAX_MON_MOVES) {
|
|
ctx->moveTemp = ctx->moveNoBattlerPrev[ctx->battlerIdTarget];
|
|
ctx->battleMons[ctx->battlerIdAttacker].moves[mimicIndex] = ctx->moveTemp;
|
|
if (ctx->trainerAIData.moveData[ctx->moveTemp].pp < 5) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].movePPCur[mimicIndex] = ctx->trainerAIData.moveData[ctx->moveTemp].pp;
|
|
} else {
|
|
ctx->battleMons[ctx->battlerIdAttacker].movePPCur[mimicIndex] = 5;
|
|
}
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.mimicedMoveIndex |= MaskOfFlagNo(mimicIndex);
|
|
|
|
if (ctx->moveTemp == MOVE_LAST_RESORT) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.lastResortCount = 0;
|
|
}
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_Metronome(BattleSystem *bsys, BattleContext *ctx) {
|
|
int metronomeIndex;
|
|
u16 moveNo;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
while (TRUE) {
|
|
moveNo = (BattleSystem_Random(bsys) % 0x1d3) + 1;
|
|
|
|
for (metronomeIndex = 0; metronomeIndex < MAX_MON_MOVES; metronomeIndex++) {
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].moves[metronomeIndex] == moveNo) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (metronomeIndex != MAX_MON_MOVES) {
|
|
continue;
|
|
}
|
|
|
|
if (CheckLegalMetronomeMove(bsys, ctx, ctx->battlerIdAttacker, moveNo) == FALSE) {
|
|
continue;
|
|
}
|
|
|
|
ctx->moveTemp = moveNo;
|
|
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryDisable(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int disabledMoveIndex = BattleMon_GetMoveIndex(&ctx->battleMons[ctx->battlerIdTarget], ctx->moveNoBattlerPrev[ctx->battlerIdTarget]);
|
|
|
|
if ((ctx->battleMons[ctx->battlerIdTarget].unk88.disabledMove == 0) && disabledMoveIndex != 4 && ctx->battleMons[ctx->battlerIdTarget].movePPCur[disabledMoveIndex] && ctx->moveNoBattlerPrev[ctx->battlerIdTarget]) {
|
|
ctx->moveTemp = ctx->moveNoBattlerPrev[ctx->battlerIdTarget];
|
|
ctx->battleMons[ctx->battlerIdTarget].unk88.disabledMove = ctx->moveTemp;
|
|
ctx->battleMons[ctx->battlerIdTarget].unk88.disabledTurns = BattleSystem_Random(bsys) % 4 + 3;
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_Counter(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int battlerId = ctx->turnData[ctx->battlerIdAttacker].battlerIdPhysicalDamage;
|
|
|
|
int sideA = BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker);
|
|
int sideB = BattleSystem_GetFieldSide(bsys, battlerId);
|
|
|
|
if (ctx->turnData[ctx->battlerIdAttacker].physicalDamage[battlerId] && sideA != sideB && ctx->battleMons[battlerId].hp) {
|
|
ctx->damage = ctx->turnData[ctx->battlerIdAttacker].physicalDamage[battlerId] * 2;
|
|
if (ctx->fieldSideConditionData[sideB].followMeFlag && ctx->battleMons[ctx->fieldSideConditionData[sideB].battlerIdFollowMe].hp) {
|
|
ctx->battlerIdTarget = ctx->fieldSideConditionData[sideB].battlerIdFollowMe;
|
|
} else {
|
|
ctx->battlerIdTarget = battlerId;
|
|
}
|
|
if (ctx->battleMons[ctx->battlerIdTarget].hp == 0) {
|
|
ctx->battlerIdTarget = Battler_GetRandomOpposingBattlerId(bsys, ctx, ctx->battlerIdAttacker);
|
|
if (ctx->battleMons[ctx->battlerIdTarget].hp == 0) {
|
|
ctx->commandNext = CONTROLLER_COMMAND_39;
|
|
BattleScriptJump(ctx, NARC_a_0_0_1, BATTLE_SUBSCRIPT_NO_TARGET);
|
|
}
|
|
}
|
|
CheckIgnorePressure(ctx, ctx->battlerIdAttacker, ctx->battlerIdTarget);
|
|
} else {
|
|
ctx->selfTurnData[ctx->battlerIdAttacker].ignorePressure = 1;
|
|
ctx->moveStatusFlag |= MOVE_STATUS_FAILED;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_MirrorCoat(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int battlerId = ctx->turnData[ctx->battlerIdAttacker].battlerIdSpecialDamage;
|
|
|
|
int sideA = BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker);
|
|
int sideB = BattleSystem_GetFieldSide(bsys, battlerId);
|
|
|
|
if (ctx->turnData[ctx->battlerIdAttacker].specialDamage[battlerId] && sideA != sideB && ctx->battleMons[battlerId].hp) {
|
|
ctx->damage = ctx->turnData[ctx->battlerIdAttacker].specialDamage[battlerId] * 2;
|
|
if (ctx->fieldSideConditionData[sideB].followMeFlag && ctx->battleMons[ctx->fieldSideConditionData[sideB].battlerIdFollowMe].hp) {
|
|
ctx->battlerIdTarget = ctx->fieldSideConditionData[sideB].battlerIdFollowMe;
|
|
} else {
|
|
ctx->battlerIdTarget = battlerId;
|
|
}
|
|
if (ctx->battleMons[ctx->battlerIdTarget].hp == 0) {
|
|
ctx->battlerIdTarget = Battler_GetRandomOpposingBattlerId(bsys, ctx, ctx->battlerIdAttacker);
|
|
if (ctx->battleMons[ctx->battlerIdTarget].hp == 0) {
|
|
ctx->commandNext = CONTROLLER_COMMAND_39;
|
|
BattleScriptJump(ctx, NARC_a_0_0_1, BATTLE_SUBSCRIPT_NO_TARGET);
|
|
}
|
|
}
|
|
CheckIgnorePressure(ctx, ctx->battlerIdAttacker, ctx->battlerIdTarget);
|
|
} else {
|
|
ctx->selfTurnData[ctx->battlerIdAttacker].ignorePressure = 1;
|
|
ctx->moveStatusFlag |= MOVE_STATUS_FAILED;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryEncore(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int encoredMoveIndex = BattleMon_GetMoveIndex(&ctx->battleMons[ctx->battlerIdTarget], ctx->moveNoBattlerPrev[ctx->battlerIdTarget]);
|
|
|
|
if (IsMoveEncored(ctx, ctx->moveNoBattlerPrev[ctx->battlerIdTarget]) == FALSE) {
|
|
encoredMoveIndex = MAX_MON_MOVES;
|
|
}
|
|
|
|
if (ctx->battleMons[ctx->battlerIdTarget].unk88.encoredMove == 0 && encoredMoveIndex != MAX_MON_MOVES && ctx->battleMons[ctx->battlerIdTarget].movePPCur[encoredMoveIndex] && ctx->moveNoBattlerPrev[ctx->battlerIdTarget]) {
|
|
ctx->moveTemp = ctx->moveNoBattlerPrev[ctx->battlerIdTarget];
|
|
ctx->battleMons[ctx->battlerIdTarget].unk88.encoredMove = ctx->moveTemp;
|
|
ctx->battleMons[ctx->battlerIdTarget].unk88.encoredMoveIndex = encoredMoveIndex;
|
|
ctx->battleMons[ctx->battlerIdTarget].unk88.encoredTurns = BattleSystem_Random(bsys) % 5 + 3;
|
|
} else {
|
|
ctx->moveStatusFlag |= 64;
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryConversion2(BattleSystem *bsys, BattleContext *ctx) {
|
|
int i, moveType;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (GetBattlerAbility(ctx, ctx->battlerIdAttacker) == ABILITY_MULTITYPE) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
return FALSE;
|
|
}
|
|
|
|
if (ctx->conversion2Move[ctx->battlerIdAttacker] && (ctx->conversion2BattlerId[ctx->battlerIdAttacker] != 255)) {
|
|
if (BattleCtx_IsIdenticalToCurrentMove(ctx, ctx->conversion2Move[ctx->battlerIdAttacker]) && (ctx->battleMons[ctx->conversion2BattlerId[ctx->battlerIdAttacker]].status2 & STATUS2_LOCKED_INTO_MOVE)) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
return FALSE;
|
|
} else {
|
|
u8 typeMove, typeMon, val;
|
|
moveType = ctx->conversion2Type[ctx->battlerIdAttacker];
|
|
|
|
for (i = 0; i < 1000; i++) {
|
|
GetTypeEffectivnessData(bsys, 0xffff, &typeMove, &typeMon, &val);
|
|
if (typeMove == moveType && val <= 5 && GetBattlerVar(ctx, ctx->battlerIdAttacker, BMON_DATA_TYPE_1, NULL) != typeMon && GetBattlerVar(ctx, ctx->battlerIdAttacker, BMON_DATA_TYPE_2, NULL) != typeMon) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].type1 = typeMon;
|
|
ctx->battleMons[ctx->battlerIdAttacker].type2 = typeMon;
|
|
ctx->msgTemp = typeMon;
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
i = 0;
|
|
while (GetTypeEffectivnessData(bsys, i, &typeMove, &typeMon, &val) == TRUE) {
|
|
if (typeMove == moveType && val <= 5 && GetBattlerVar(ctx, ctx->battlerIdAttacker, BMON_DATA_TYPE_1, NULL) != typeMon && GetBattlerVar(ctx, ctx->battlerIdAttacker, BMON_DATA_TYPE_2, NULL) != typeMon) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].type1 = typeMon;
|
|
ctx->battleMons[ctx->battlerIdAttacker].type2 = typeMon;
|
|
ctx->msgTemp = typeMon;
|
|
return FALSE;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TrySketch(BattleSystem *bsys, BattleContext *ctx) {
|
|
int moveIndex;
|
|
int sketchIndex = -1;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].status2 & STATUS2_TRANSFORM || ctx->moveNoSketch[ctx->battlerIdTarget] == MOVE_STRUGGLE || ctx->moveNoSketch[ctx->battlerIdTarget] == MOVE_SKETCH || ctx->moveNoSketch[ctx->battlerIdTarget] == MOVE_CHATTER || ctx->moveNoSketch[ctx->battlerIdTarget] == 0) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else {
|
|
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) {
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].moves[moveIndex] != MOVE_SKETCH && ctx->battleMons[ctx->battlerIdAttacker].moves[moveIndex] == ctx->moveNoSketch[ctx->battlerIdTarget]) {
|
|
break;
|
|
}
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].moves[moveIndex] == MOVE_SKETCH && sketchIndex == -1) {
|
|
sketchIndex = moveIndex;
|
|
}
|
|
}
|
|
if (moveIndex == MAX_MON_MOVES) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].moves[sketchIndex] = ctx->moveNoSketch[ctx->battlerIdTarget];
|
|
ctx->battleMons[ctx->battlerIdAttacker].movePPCur[sketchIndex] = ctx->trainerAIData.moveData[ctx->moveNoSketch[ctx->battlerIdTarget]].pp;
|
|
BattleController_EmitBattleMonToPartyMonCopy(bsys, ctx, ctx->battlerIdAttacker);
|
|
ctx->moveTemp = ctx->moveNoSketch[ctx->battlerIdTarget];
|
|
if (ctx->moveTemp == MOVE_LAST_RESORT) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.lastResortCount = 0;
|
|
}
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TrySleepTalk(BattleSystem *bsys, BattleContext *ctx) {
|
|
int moveIndex, nonSelectableMoves;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
nonSelectableMoves = 0;
|
|
|
|
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) {
|
|
if (CheckMoveCallsOtherMove(ctx->battleMons[ctx->battlerIdAttacker].moves[moveIndex]) || ctx->battleMons[ctx->battlerIdAttacker].moves[moveIndex] == MOVE_FOCUS_PUNCH || ctx->battleMons[ctx->battlerIdAttacker].moves[moveIndex] == MOVE_UPROAR || ctx->battleMons[ctx->battlerIdAttacker].moves[moveIndex] == MOVE_CHATTER || BattleCtx_IsIdenticalToCurrentMove(ctx, ctx->battleMons[ctx->battlerIdAttacker].moves[moveIndex])) {
|
|
nonSelectableMoves |= MaskOfFlagNo(moveIndex);
|
|
}
|
|
}
|
|
|
|
nonSelectableMoves = StruggleCheck(bsys, ctx, ctx->battlerIdAttacker, nonSelectableMoves, ~2);
|
|
|
|
if (nonSelectableMoves == 15) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else {
|
|
do {
|
|
moveIndex = BattleSystem_Random(bsys) % 4;
|
|
} while (MaskOfFlagNo(moveIndex) & nonSelectableMoves);
|
|
ctx->moveTemp = ctx->battleMons[ctx->battlerIdAttacker].moves[moveIndex];
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern u8 sFlailDamageTable[6][2];
|
|
|
|
BOOL BtlCmd_CalcFlailPower(BattleSystem *bsys, BattleContext *ctx) {
|
|
int i;
|
|
int hpBarPixels;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
hpBarPixels = CalculateHpBarPixelsLength(ctx->battleMons[ctx->battlerIdAttacker].hp, ctx->battleMons[ctx->battlerIdAttacker].maxHp, 64);
|
|
for (i = 0; i < sizeof(sFlailDamageTable) / sizeof(sFlailDamageTable[0]); i++) {
|
|
if (hpBarPixels <= sFlailDamageTable[i][0]) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
ctx->movePower = sFlailDamageTable[i][1];
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TrySpite(BattleSystem *bsys, BattleContext *ctx) {
|
|
int moveIndex, ppLoss;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (ctx->moveNoBattlerPrev[ctx->battlerIdTarget]) {
|
|
moveIndex = BattleMon_GetMoveIndex(&ctx->battleMons[ctx->battlerIdTarget], ctx->moveNoBattlerPrev[ctx->battlerIdTarget]);
|
|
if (moveIndex == MAX_MON_MOVES || ctx->battleMons[ctx->battlerIdTarget].movePPCur[moveIndex] == 0) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else {
|
|
ppLoss = 4;
|
|
if (ctx->battleMons[ctx->battlerIdTarget].movePPCur[moveIndex] < ppLoss) {
|
|
ppLoss = ctx->battleMons[ctx->battlerIdTarget].movePPCur[moveIndex];
|
|
}
|
|
ctx->moveTemp = ctx->moveNoBattlerPrev[ctx->battlerIdTarget];
|
|
ctx->msgTemp = ppLoss;
|
|
ctx->battleMons[ctx->battlerIdTarget].movePPCur[moveIndex] -= ppLoss;
|
|
CopyBattleMonToPartyMon(bsys, ctx, ctx->battlerIdTarget);
|
|
}
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryPartyStatusRefresh(BattleSystem *bsys, BattleContext *ctx) {
|
|
u32 battleType = BattleSystem_GetBattleType(bsys);
|
|
int battlerId;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
ctx->calcTemp = 0;
|
|
|
|
if (ctx->moveNoCur == MOVE_HEAL_BELL) {
|
|
ctx->moveTemp = ctx->moveNoCur;
|
|
if (GetBattlerAbility(ctx, ctx->battlerIdAttacker) != ABILITY_SOUNDPROOF) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].status = STATUS_NONE;
|
|
ctx->battleMons[ctx->battlerIdAttacker].status2 &= ~STATUS2_NIGHTMARE;
|
|
} else {
|
|
ctx->calcTemp |= 5;
|
|
}
|
|
|
|
if (battleType & BATTLE_TYPE_DOUBLES) {
|
|
battlerId = GetBattlerIDBySide(bsys, ctx, BATTLER_CATEGORY_ATTACKER_PARTNER);
|
|
if (!(ctx->switchInFlag & MaskOfFlagNo(battlerId))) {
|
|
if (!CheckBattlerAbilityIfNotIgnored(ctx, ctx->battlerIdAttacker, battlerId, ABILITY_SOUNDPROOF)) {
|
|
ctx->battleMons[battlerId].status = STATUS_NONE;
|
|
ctx->battleMons[battlerId].status2 &= ~STATUS2_NIGHTMARE;
|
|
} else {
|
|
ctx->battlerIdTemp = battlerId;
|
|
ctx->calcTemp |= 10;
|
|
}
|
|
}
|
|
} else {
|
|
ctx->calcTemp |= 8;
|
|
}
|
|
} else { // aromatherapy
|
|
ctx->battleMons[ctx->battlerIdAttacker].status = STATUS_NONE;
|
|
ctx->battleMons[ctx->battlerIdAttacker].status2 &= ~STATUS2_NIGHTMARE;
|
|
if (battleType & BATTLE_TYPE_DOUBLES) {
|
|
battlerId = GetBattlerIDBySide(bsys, ctx, BATTLER_CATEGORY_ATTACKER_PARTNER);
|
|
if (!(ctx->switchInFlag & MaskOfFlagNo(battlerId))) {
|
|
ctx->battleMons[battlerId].status = STATUS_NONE;
|
|
ctx->battleMons[battlerId].status2 &= ~STATUS2_NIGHTMARE;
|
|
}
|
|
} else {
|
|
ctx->calcTemp |= 8;
|
|
}
|
|
}
|
|
|
|
BattleControl_EmitPartyStatusHeal(bsys, ctx, ctx->battlerIdAttacker, ctx->moveNoCur);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryStealItem(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs1 = BattleScriptReadWord(ctx);
|
|
int adrs2 = BattleScriptReadWord(ctx);
|
|
|
|
u32 battleType = BattleSystem_GetBattleType(bsys);
|
|
int fieldSide = BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker);
|
|
|
|
if (BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker) && !(battleType & (BATTLE_TYPE_LINK | BATTLE_TYPE_FRONTIER))) {
|
|
BattleScriptIncrementPointer(ctx, adrs1);
|
|
} else if (ctx->fieldSideConditionData[fieldSide].battlerBitKnockedOffItem & MaskOfFlagNo(ctx->selectedMonIndex[ctx->battlerIdAttacker])) {
|
|
BattleScriptIncrementPointer(ctx, adrs1);
|
|
} else if (GetBattlerAbility(ctx, ctx->battlerIdAttacker) == ABILITY_MULTITYPE || GetBattlerAbility(ctx, ctx->battlerIdTarget) == ABILITY_MULTITYPE) {
|
|
BattleScriptIncrementPointer(ctx, adrs1);
|
|
} else if (ctx->battleMons[ctx->battlerIdTarget].item == ITEM_GRISEOUS_ORB) {
|
|
BattleScriptIncrementPointer(ctx, adrs1);
|
|
} else if (ctx->battleMons[ctx->battlerIdTarget].unk88.custapBerryFlag || ctx->battleMons[ctx->battlerIdTarget].unk88.quickClawFlag) {
|
|
BattleScriptIncrementPointer(ctx, adrs1);
|
|
} else {
|
|
if (ctx->battleMons[ctx->battlerIdTarget].item && CheckBattlerAbilityIfNotIgnored(ctx, ctx->battlerIdAttacker, ctx->battlerIdTarget, ABILITY_STICKY_HOLD) == TRUE) {
|
|
BattleScriptIncrementPointer(ctx, adrs2);
|
|
} else if (ctx->battleMons[ctx->battlerIdAttacker].item || CanStealHeldItem(bsys, ctx, ctx->battlerIdTarget) == FALSE) {
|
|
BattleScriptIncrementPointer(ctx, adrs1);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern u16 sProtectSuccessChance[4];
|
|
|
|
BOOL BtlCmd_TryProtection(BattleSystem *bsys, BattleContext *ctx) {
|
|
int flag;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (ctx->moveNoProtect[ctx->battlerIdAttacker] != MOVE_PROTECT && ctx->moveNoProtect[ctx->battlerIdAttacker] != MOVE_DETECT && ctx->moveNoProtect[ctx->battlerIdAttacker] != MOVE_ENDURE) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.protectSuccessTurns = 0;
|
|
}
|
|
|
|
if (ctx->battlersOnField == 1) {
|
|
flag = FALSE;
|
|
} else {
|
|
flag = TRUE;
|
|
}
|
|
|
|
if (sProtectSuccessChance[ctx->battleMons[ctx->battlerIdAttacker].unk88.protectSuccessTurns] >= (u32)BattleSystem_Random(bsys) && flag) {
|
|
if (ctx->trainerAIData.moveData[ctx->moveNoCur].effect == MOVE_EFFECT_PROTECT) {
|
|
ctx->turnData[ctx->battlerIdAttacker].protectFlag = TRUE;
|
|
ctx->buffMsg.id = msg_0197_00282;
|
|
}
|
|
if (ctx->trainerAIData.moveData[ctx->moveNoCur].effect == MOVE_EFFECT_SURVIVE_WITH_1_HP) {
|
|
ctx->turnData[ctx->battlerIdAttacker].endureFlag = TRUE;
|
|
ctx->buffMsg.id = msg_0197_00442;
|
|
}
|
|
ctx->buffMsg.tag = TAG_NICKNAME;
|
|
ctx->buffMsg.param[0] = CreateNicknameTag(ctx, ctx->battlerIdAttacker);
|
|
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].unk88.protectSuccessTurns < NELEMS(sProtectSuccessChance) - 1) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.protectSuccessTurns++;
|
|
}
|
|
|
|
} else {
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.protectSuccessTurns = 0;
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TrySubstitute(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int subHp = DamageDivide(ctx->battleMons[ctx->battlerIdAttacker].maxHp, 4);
|
|
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].hp <= subHp) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else {
|
|
ctx->hpCalc = -subHp;
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.substituteHp = subHp;
|
|
ctx->battleMons[ctx->battlerIdAttacker].status2 &= ~STATUS2_BIND;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryWhirlwind(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
u32 battleType = BattleSystem_GetBattleType(bsys);
|
|
|
|
if (battleType & BATTLE_TYPE_TRAINER) {
|
|
Party *party;
|
|
Pokemon *mon;
|
|
int partySize;
|
|
int cnt = 0;
|
|
int cntMax;
|
|
int index0, indexEnd, monIndex, maxRand;
|
|
int monIndexA, monIndexB;
|
|
|
|
party = BattleSystem_GetParty(bsys, ctx->battlerIdTarget);
|
|
partySize = BattleSystem_GetPartySize(bsys, ctx->battlerIdTarget);
|
|
|
|
if (battleType & BATTLE_TYPE_MULTI || battleType & BATTLE_TYPE_TAG && BattleSystem_GetFieldSide(bsys, ctx->battlerIdTarget)) {
|
|
index0 = 0;
|
|
indexEnd = partySize;
|
|
maxRand = partySize;
|
|
cntMax = 1;
|
|
monIndexA = ctx->selectedMonIndex[ctx->battlerIdTarget];
|
|
monIndexB = ctx->selectedMonIndex[ctx->battlerIdTarget];
|
|
} else if (battleType & BATTLE_TYPE_DOUBLES) {
|
|
index0 = 0;
|
|
indexEnd = partySize;
|
|
maxRand = partySize;
|
|
cntMax = 2;
|
|
monIndexA = ctx->selectedMonIndex[ctx->battlerIdTarget];
|
|
monIndexB = ctx->selectedMonIndex[BattleSystem_GetBattlerIdPartner(bsys, ctx->battlerIdTarget)];
|
|
} else {
|
|
index0 = 0;
|
|
indexEnd = partySize;
|
|
maxRand = partySize;
|
|
cntMax = 1;
|
|
monIndexA = ctx->selectedMonIndex[ctx->battlerIdTarget];
|
|
monIndexB = ctx->selectedMonIndex[ctx->battlerIdTarget];
|
|
}
|
|
|
|
for (monIndex = index0; monIndex < indexEnd; monIndex++) {
|
|
mon = Party_GetMonByIndex(party, monIndex);
|
|
if (GetMonData(mon, MON_DATA_SPECIES, 0) != SPECIES_NONE
|
|
&& !GetMonData(mon, MON_DATA_IS_EGG, 0)
|
|
&& GetMonData(mon, MON_DATA_HP, 0) != 0) {
|
|
cnt++;
|
|
}
|
|
}
|
|
|
|
if (cnt <= cntMax) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else if (WhirlwindCheck(bsys, ctx)) {
|
|
do {
|
|
do {
|
|
monIndex = (BattleSystem_Random(bsys) % maxRand);
|
|
monIndex += index0;
|
|
} while (monIndex == monIndexA || monIndex == monIndexB);
|
|
mon = Party_GetMonByIndex(party, monIndex);
|
|
} while (GetMonData(mon, MON_DATA_SPECIES, 0) == SPECIES_NONE
|
|
|| GetMonData(mon, MON_DATA_IS_EGG, 0) == TRUE
|
|
|| GetMonData(mon, MON_DATA_HP, 0) == 0);
|
|
ctx->unk_21A0[ctx->battlerIdTarget] = monIndex;
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
} else if (WhirlwindCheck(bsys, ctx) == FALSE) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_Transform(BattleSystem *bsys, BattleContext *ctx) {
|
|
u32 i;
|
|
u8 *src, *dest;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
ctx->battleMons[ctx->battlerIdAttacker].status2 |= STATUS2_TRANSFORM;
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.disabledMove = 0;
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.disabledTurns = 0;
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.transformPersonality = ctx->battleMons[ctx->battlerIdTarget].personality;
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.transformGender = ctx->battleMons[ctx->battlerIdTarget].gender;
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.mimicedMoveIndex = 0;
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.lastResortCount = 0;
|
|
|
|
src = (u8 *)&ctx->battleMons[ctx->battlerIdAttacker];
|
|
dest = (u8 *)&ctx->battleMons[ctx->battlerIdTarget];
|
|
|
|
for (i = 0; i < 40; i++) {
|
|
src[i] = dest[i];
|
|
}
|
|
|
|
ctx->battleMons[ctx->battlerIdAttacker].sendOutFlag = 0;
|
|
ctx->battleMons[ctx->battlerIdAttacker].intimidateFlag = 0;
|
|
ctx->battleMons[ctx->battlerIdAttacker].traceFlag = 0;
|
|
ctx->battleMons[ctx->battlerIdAttacker].downloadFlag = 0;
|
|
ctx->battleMons[ctx->battlerIdAttacker].anticipationFlag = 0;
|
|
ctx->battleMons[ctx->battlerIdAttacker].forewarnFlag = 0;
|
|
ctx->battleMons[ctx->battlerIdAttacker].friskFlag = 0;
|
|
ctx->battleMons[ctx->battlerIdAttacker].moldBreakerFlag = 0;
|
|
ctx->battleMons[ctx->battlerIdAttacker].pressureFlag = 0;
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.truantFlag = ctx->totalTurns & 1;
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.slowStartTurns = ctx->totalTurns + 1;
|
|
ctx->battleMons[ctx->battlerIdAttacker].slowStartFlag = 0;
|
|
ctx->battleMons[ctx->battlerIdAttacker].slowStartEnded = 0;
|
|
|
|
for (i = 0; (int)i < MAX_MON_MOVES; i++) {
|
|
if (ctx->trainerAIData.moveData[ctx->battleMons[ctx->battlerIdAttacker].moves[i]].pp < 5) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].movePPCur[i] = ctx->trainerAIData.moveData[ctx->battleMons[ctx->battlerIdAttacker].moves[i]].pp;
|
|
} else {
|
|
ctx->battleMons[ctx->battlerIdAttacker].movePPCur[i] = 5;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TrySpikes(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int fieldSide = BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker) ^ 1;
|
|
|
|
if (ctx->fieldSideConditionData[fieldSide].spikesLayers == 3) {
|
|
ctx->selfTurnData[ctx->battlerIdAttacker].ignorePressure = 1;
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else {
|
|
ctx->fieldSideConditionFlags[fieldSide] |= SIDE_CONDITION_SPIKES;
|
|
ctx->fieldSideConditionData[fieldSide].spikesLayers++;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckSpikes(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
int fieldSide = BattleSystem_GetFieldSide(bsys, battlerId);
|
|
|
|
if (ctx->fieldSideConditionData[fieldSide].spikesLayers && ctx->battleMons[battlerId].hp) {
|
|
ctx->hpCalc = (5 - ctx->fieldSideConditionData[fieldSide].spikesLayers) * 2;
|
|
ctx->hpCalc = DamageDivide(ctx->battleMons[battlerId].maxHp * -1, ctx->hpCalc);
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryPerishSong(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
int maxBattlers = BattleSystem_GetMaxBattlers(bsys);
|
|
|
|
ctx->calcTemp = maxBattlers;
|
|
|
|
int cnt = 0;
|
|
|
|
for (battlerId = 0; battlerId < maxBattlers; battlerId++) {
|
|
if (ctx->battleMons[battlerId].moveEffectFlags & MOVE_EFFECT_FLAG_PERISH_SONG || ctx->battleMons[battlerId].hp == 0 || CheckBattlerAbilityIfNotIgnored(ctx, ctx->battlerIdAttacker, battlerId, ABILITY_SOUNDPROOF) == TRUE) {
|
|
cnt++;
|
|
} else {
|
|
ctx->battleMons[battlerId].moveEffectFlags |= MOVE_EFFECT_FLAG_PERISH_SONG;
|
|
ctx->battleMons[battlerId].unk88.perishSongTurns = 3;
|
|
}
|
|
}
|
|
if (cnt == maxBattlers) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_GetTurnOrderBySpeed(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u32 *unkPtr = BattleScriptGetVarPointer(bsys, ctx, BattleScriptReadWord(ctx));
|
|
|
|
*unkPtr = ctx->turnOrder[ctx->unk_3104];
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_GoToIfValidMon(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u32 varId = BattleScriptReadWord(ctx);
|
|
u32 adrs = BattleScriptReadWord(ctx);
|
|
u32 *battlerId = BattleScriptGetVarPointer(bsys, ctx, varId);
|
|
|
|
if (*battlerId < BattleSystem_GetMaxBattlers(bsys)) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_EndOfTurnWeatherEffect(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u32 battlerId = GetBattlerIDBySide(bsys, ctx, BattleScriptReadWord(ctx));
|
|
|
|
ctx->tempData = 0;
|
|
ctx->hpCalc = 0;
|
|
|
|
u32 type1 = GetBattlerVar(ctx, battlerId, BMON_DATA_TYPE_1, NULL);
|
|
u32 type2 = GetBattlerVar(ctx, battlerId, BMON_DATA_TYPE_2, NULL);
|
|
|
|
if (CheckAbilityActive(bsys, ctx, CHECK_ABILITY_ALL_HP, 0, ABILITY_CLOUD_NINE) == 0 && CheckAbilityActive(bsys, ctx, CHECK_ABILITY_ALL_HP, 0, ABILITY_AIR_LOCK) == 0) {
|
|
if (ctx->fieldCondition & FIELD_CONDITION_SANDSTORM_ALL) {
|
|
if (type1 != TYPE_ROCK && type2 != TYPE_ROCK && type1 != TYPE_STEEL && type2 != TYPE_STEEL && type1 != TYPE_GROUND && type2 != TYPE_GROUND && ctx->battleMons[battlerId].hp && GetBattlerAbility(ctx, battlerId) != ABILITY_SAND_VEIL && !(ctx->battleMons[battlerId].moveEffectFlags & 0x40080)) {
|
|
ctx->moveTemp = MOVE_SANDSTORM;
|
|
ctx->hpCalc = DamageDivide(ctx->battleMons[battlerId].maxHp * -1, 16);
|
|
}
|
|
}
|
|
if (ctx->fieldCondition & FIELD_CONDITION_SUN_ALL) {
|
|
if (ctx->battleMons[battlerId].hp && !(ctx->battleMons[battlerId].moveEffectFlags & 0x40080)) {
|
|
if (GetBattlerAbility(ctx, battlerId) == ABILITY_DRY_SKIN || GetBattlerAbility(ctx, battlerId) == ABILITY_SOLAR_POWER) {
|
|
ctx->hpCalc = DamageDivide(ctx->battleMons[battlerId].maxHp * -1, 8);
|
|
}
|
|
if (GetBattlerAbility(ctx, battlerId) == ABILITY_SOLAR_POWER) {
|
|
ctx->tempData = 2;
|
|
}
|
|
}
|
|
}
|
|
if (ctx->fieldCondition & FIELD_CONDITION_HAIL_ALL) {
|
|
if (ctx->battleMons[battlerId].hp && !(ctx->battleMons[battlerId].moveEffectFlags & 0x40080)) {
|
|
if (GetBattlerAbility(ctx, battlerId) == ABILITY_ICE_BODY) {
|
|
if (ctx->battleMons[battlerId].hp < ctx->battleMons[battlerId].maxHp) {
|
|
ctx->hpCalc = DamageDivide(ctx->battleMons[battlerId].maxHp, 16);
|
|
}
|
|
} else if (type1 != TYPE_ICE && type2 != TYPE_ICE && GetBattlerAbility(ctx, battlerId) != ABILITY_SNOW_CLOAK) {
|
|
ctx->moveTemp = MOVE_HAIL;
|
|
ctx->hpCalc = DamageDivide(ctx->battleMons[battlerId].maxHp * -1, 16);
|
|
}
|
|
}
|
|
}
|
|
if (ctx->fieldCondition & FIELD_CONDITION_RAIN_ALL) {
|
|
if (ctx->battleMons[battlerId].hp && ctx->battleMons[battlerId].hp < ctx->battleMons[battlerId].maxHp && GetBattlerAbility(ctx, battlerId) == ABILITY_RAIN_DISH) {
|
|
ctx->hpCalc = DamageDivide(ctx->battleMons[battlerId].maxHp, 16);
|
|
}
|
|
if (ctx->battleMons[battlerId].hp && ctx->battleMons[battlerId].hp < ctx->battleMons[battlerId].maxHp && GetBattlerAbility(ctx, battlerId) == ABILITY_DRY_SKIN) {
|
|
ctx->hpCalc = DamageDivide(ctx->battleMons[battlerId].maxHp, 8);
|
|
}
|
|
if (ctx->battleMons[battlerId].hp && (u8)ctx->battleMons[battlerId].status && GetBattlerAbility(ctx, battlerId) == ABILITY_HYDRATION) {
|
|
if (ctx->battleMons[battlerId].status & STATUS_SLEEP) {
|
|
ctx->msgTemp = 0;
|
|
} else if (ctx->battleMons[battlerId].status & STATUS_POISON_ALL) {
|
|
ctx->msgTemp = 1;
|
|
} else if (ctx->battleMons[battlerId].status & STATUS_BURN) {
|
|
ctx->msgTemp = 2;
|
|
} else if (ctx->battleMons[battlerId].status & STATUS_PARALYSIS) {
|
|
ctx->msgTemp = 3;
|
|
} else {
|
|
ctx->msgTemp = 4;
|
|
}
|
|
ctx->tempData = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CalcRolloutPower(BattleSystem *bsys, BattleContext *ctx) {
|
|
int i, j;
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
ctx->selfTurnData[ctx->battlerIdAttacker].rolloutCount = ctx->battleMons[ctx->battlerIdAttacker].unk88.rolloutCount;
|
|
|
|
if (!(ctx->battleMons[ctx->battlerIdAttacker].status2 & STATUS2_LOCKED_INTO_MOVE)) {
|
|
LockBattlerIntoCurrentMove(bsys, ctx, ctx->battlerIdAttacker);
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.rolloutCount = 5;
|
|
}
|
|
|
|
if (--ctx->battleMons[ctx->battlerIdAttacker].unk88.rolloutCount == 0) {
|
|
UnlockBattlerOutOfCurrentMove(bsys, ctx, ctx->battlerIdAttacker);
|
|
}
|
|
|
|
ctx->movePower = ctx->trainerAIData.moveData[ctx->moveNoCur].power;
|
|
|
|
j = 5 - ctx->battleMons[ctx->battlerIdAttacker].unk88.rolloutCount;
|
|
|
|
for (i = 1; i < j; i++) {
|
|
ctx->movePower *= 2;
|
|
}
|
|
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].status2 & STATUS2_DEFENSE_CURL) {
|
|
ctx->movePower *= 2;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CalcFuryCutterPower(BattleSystem *bsys, BattleContext *ctx) {
|
|
int i;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].unk88.furyCutterCount < 5) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.furyCutterCount++;
|
|
}
|
|
|
|
ctx->movePower = ctx->trainerAIData.moveData[ctx->moveNoCur].power;
|
|
|
|
for (i = 1; i < ctx->battleMons[ctx->battlerIdAttacker].unk88.furyCutterCount; i++) {
|
|
ctx->movePower *= 2;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryAttract(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (ctx->battleMons[ctx->battlerIdTemp].gender == ctx->battleMons[ctx->battlerIdStatChange].gender || ctx->battleMons[ctx->battlerIdStatChange].status2 & STATUS2_ATTRACT || ctx->battleMons[ctx->battlerIdTemp].gender == 2 || ctx->battleMons[ctx->battlerIdStatChange].gender == 2) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else {
|
|
ctx->battleMons[ctx->battlerIdStatChange].status2 |= MaskOfFlagNo(ctx->battlerIdTemp) << 16;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TrySafeguard(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
int fieldSide = BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker);
|
|
|
|
if (ctx->fieldSideConditionFlags[fieldSide] & SIDE_CONDITION_SAFEGUARD) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
ctx->moveStatusFlag |= 64;
|
|
} else {
|
|
ctx->fieldSideConditionFlags[fieldSide] |= SIDE_CONDITION_SAFEGUARD;
|
|
ctx->fieldSideConditionData[fieldSide].safeguardTurns = 5;
|
|
ctx->fieldSideConditionData[fieldSide].safeguardBattler = ctx->battlerIdAttacker;
|
|
ctx->buffMsg.tag = TAG_NONE_SIDE;
|
|
ctx->buffMsg.param[0] = ctx->battlerIdAttacker;
|
|
ctx->buffMsg.id = msg_0197_00198;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_Present(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
int rand = (u8)BattleSystem_Random(bsys);
|
|
|
|
if (rand < 102) {
|
|
ctx->movePower = 40;
|
|
} else if (rand < 178) {
|
|
ctx->movePower = 80;
|
|
} else if (rand < 204) {
|
|
ctx->movePower = 120;
|
|
} else {
|
|
ctx->hpCalc = DamageDivide(ctx->battleMons[ctx->battlerIdTarget].maxHp, 4);
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CalcMagnitudePower(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
if (ctx->magnitude == 0) {
|
|
ctx->magnitude = BattleSystem_Random(bsys) % 100;
|
|
if (ctx->magnitude < 5) {
|
|
ctx->movePower = 10;
|
|
ctx->magnitude = 4;
|
|
} else if (ctx->magnitude < 15) {
|
|
ctx->movePower = 30;
|
|
ctx->magnitude = 5;
|
|
} else if (ctx->magnitude < 35) {
|
|
ctx->movePower = 50;
|
|
ctx->magnitude = 6;
|
|
} else if (ctx->magnitude < 65) {
|
|
ctx->movePower = 70;
|
|
ctx->magnitude = 7;
|
|
} else if (ctx->magnitude < 85) {
|
|
ctx->movePower = 90;
|
|
ctx->magnitude = 8;
|
|
} else if (ctx->magnitude < 95) {
|
|
ctx->movePower = 110;
|
|
ctx->magnitude = 9;
|
|
} else {
|
|
ctx->movePower = 150;
|
|
ctx->magnitude = 10;
|
|
}
|
|
}
|
|
|
|
ctx->msgTemp = ctx->magnitude;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryReplaceFaintedMon(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int flag = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
if (!CanSwitchMon(bsys, ctx, battlerId)) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else if (flag == 1) {
|
|
ctx->unk_13C[battlerId] |= 1;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_RapidSpin(BattleSystem *bsys, BattleContext *ctx) {
|
|
int side = BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker);
|
|
|
|
// Binding Moves
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].status2 & STATUS2_BIND) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].status2 &= ~STATUS2_BIND;
|
|
ctx->battlerIdTemp = ctx->battleMons[ctx->battlerIdAttacker].unk88.battlerIdBinding;
|
|
ctx->moveTemp = ctx->battleMons[ctx->battlerIdAttacker].unk88.bindingMove;
|
|
BattleScriptGotoSubscript(ctx, NARC_a_0_0_1, BATTLE_SUBSCRIPT_BREAK_BIND_EFFECT);
|
|
return FALSE;
|
|
}
|
|
|
|
// Leech Seed
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].moveEffectFlags & MOVE_EFFECT_FLAG_LEECH_SEED) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].moveEffectFlags &= ~MOVE_EFFECT_FLAG_LEECH_SEED;
|
|
ctx->battleMons[ctx->battlerIdAttacker].moveEffectFlags &= ~3;
|
|
ctx->moveTemp = 73;
|
|
BattleScriptGotoSubscript(ctx, NARC_a_0_0_1, BATTLE_SUBSCRIPT_BLOW_AWAY_HAZARDS);
|
|
return FALSE;
|
|
}
|
|
|
|
// Spikes
|
|
if (ctx->fieldSideConditionData[side].spikesLayers) {
|
|
ctx->fieldSideConditionFlags[side] &= ~SIDE_CONDITION_SPIKES;
|
|
ctx->fieldSideConditionData[side].spikesLayers = 0;
|
|
ctx->moveTemp = MOVE_SPIKES;
|
|
BattleScriptGotoSubscript(ctx, NARC_a_0_0_1, BATTLE_SUBSCRIPT_BLOW_AWAY_HAZARDS);
|
|
return FALSE;
|
|
}
|
|
|
|
// Toxic Spikes
|
|
if (ctx->fieldSideConditionData[side].toxicSpikesLayers) {
|
|
ctx->fieldSideConditionFlags[side] &= ~SIDE_CONDITION_TOXIC_SPIKES;
|
|
ctx->fieldSideConditionData[side].toxicSpikesLayers = 0;
|
|
ctx->moveTemp = MOVE_TOXIC_SPIKES;
|
|
BattleScriptGotoSubscript(ctx, NARC_a_0_0_1, BATTLE_SUBSCRIPT_BLOW_AWAY_HAZARDS);
|
|
return FALSE;
|
|
}
|
|
|
|
// Stealth Rocks
|
|
if (ctx->fieldSideConditionFlags[side] & SIDE_CONDITION_STEALTH_ROCKS) {
|
|
ctx->fieldSideConditionFlags[side] &= ~SIDE_CONDITION_STEALTH_ROCKS;
|
|
ctx->moveTemp = MOVE_STEALTH_ROCK;
|
|
BattleScriptGotoSubscript(ctx, NARC_a_0_0_1, BATTLE_SUBSCRIPT_BLOW_AWAY_HAZARDS);
|
|
return FALSE;
|
|
}
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_WeatherHPRecovery(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
if (!(ctx->fieldCondition & FIELD_CONDITION_WEATHER) || CheckAbilityActive(bsys, ctx, CHECK_ABILITY_ALL_HP, 0, ABILITY_CLOUD_NINE) || CheckAbilityActive(bsys, ctx, CHECK_ABILITY_ALL_HP, 0, ABILITY_AIR_LOCK)) {
|
|
ctx->hpCalc = ctx->battleMons[ctx->battlerIdAttacker].maxHp / 2;
|
|
} else if (ctx->fieldCondition & FIELD_CONDITION_SUN_ALL) {
|
|
ctx->hpCalc = DamageDivide(ctx->battleMons[ctx->battlerIdAttacker].maxHp * 20, 30);
|
|
} else {
|
|
ctx->hpCalc = DamageDivide(ctx->battleMons[ctx->battlerIdAttacker].maxHp, 4);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CalcHiddenPowerParams(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
ctx->movePower = ((ctx->battleMons[ctx->battlerIdAttacker].hpIV & 2) >> 1) | (ctx->battleMons[ctx->battlerIdAttacker].atkIV & 2) | ((ctx->battleMons[ctx->battlerIdAttacker].defIV & 2) << 1) | ((ctx->battleMons[ctx->battlerIdAttacker].speedIV & 2) << 2) | ((ctx->battleMons[ctx->battlerIdAttacker].spAtkIV & 2) << 3) | ((ctx->battleMons[ctx->battlerIdAttacker].spDefIV & 2) << 4);
|
|
ctx->moveType = (ctx->battleMons[ctx->battlerIdAttacker].hpIV & 1) | ((ctx->battleMons[ctx->battlerIdAttacker].atkIV & 1) << 1) | ((ctx->battleMons[ctx->battlerIdAttacker].defIV & 1) << 2) | ((ctx->battleMons[ctx->battlerIdAttacker].speedIV & 1) << 3) | ((ctx->battleMons[ctx->battlerIdAttacker].spAtkIV & 1) << 4) | ((ctx->battleMons[ctx->battlerIdAttacker].spDefIV & 1) << 5);
|
|
|
|
ctx->movePower = ctx->movePower * 40 / 63 + 30;
|
|
ctx->moveType = ctx->moveType * 15 / 63 + 1;
|
|
|
|
if (ctx->moveType >= TYPE_MYSTERY) {
|
|
ctx->moveType++;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CopyStatStages(BattleSystem *bsys, BattleContext *ctx) {
|
|
int stat;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
for (stat = 0; stat < 8; stat++) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].statChanges[stat] = ctx->battleMons[ctx->battlerIdTarget].statChanges[stat];
|
|
}
|
|
|
|
ctx->battleMons[ctx->battlerIdAttacker].status2 |= (ctx->battleMons[ctx->battlerIdTarget].status2 & STATUS2_FOCUS_ENERGY);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryFutureSight(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (ctx->fieldConditionData.futureSightTurns[ctx->battlerIdTarget] == 0) {
|
|
int side = BattleSystem_GetFieldSide(bsys, ctx->battlerIdTarget);
|
|
ctx->fieldSideConditionFlags[side] |= SIDE_CONDITION_FUTURE_SIGHT;
|
|
ctx->fieldConditionData.futureSightTurns[ctx->battlerIdTarget] = 3;
|
|
ctx->fieldConditionData.futureSightMoveNo[ctx->battlerIdTarget] = ctx->moveNoCur;
|
|
ctx->fieldConditionData.battlerIdFutureSight[ctx->battlerIdTarget] = ctx->battlerIdAttacker;
|
|
int damage = CalcMoveDamage(bsys, ctx, ctx->moveNoCur, ctx->fieldSideConditionFlags[side], ctx->fieldCondition, 0, 0, ctx->battlerIdAttacker, ctx->battlerIdTarget, 1) * -1;
|
|
ctx->fieldConditionData.futureSightDamage[ctx->battlerIdTarget] = ApplyDamageRange(bsys, ctx, damage);
|
|
if (ctx->turnData[ctx->battlerIdAttacker].helpingHandFlag) {
|
|
ctx->fieldConditionData.futureSightDamage[ctx->battlerIdTarget] = ctx->fieldConditionData.futureSightDamage[ctx->battlerIdTarget] * 15 / 10;
|
|
}
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckMoveHit(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int sideAttacker = BattleScriptReadWord(ctx);
|
|
int sideTarget = BattleScriptReadWord(ctx);
|
|
int move = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int battlerIdAttacker = GetBattlerIDBySide(bsys, ctx, sideAttacker);
|
|
int battlerIdTarget = GetBattlerIDBySide(bsys, ctx, sideTarget);
|
|
int moveMsgNo = GetMoveMessageNo(ctx, move);
|
|
|
|
BattleSystem_CheckMoveHitEffect(bsys, ctx, battlerIdAttacker, battlerIdTarget, moveMsgNo);
|
|
|
|
if (ctx->moveStatusFlag & 0x1fd849) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryTeleport(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u32 adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (CantEscape(bsys, ctx, ctx->battlerIdAttacker, NULL)) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_BeatUp(BattleSystem *bsys, BattleContext *ctx) {
|
|
int species;
|
|
int form;
|
|
int level;
|
|
Pokemon *mon;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int monCnt = BattleSystem_GetPartySize(bsys, ctx->battlerIdAttacker);
|
|
|
|
if (ctx->multiHitCountTemp == 0) {
|
|
ctx->multiHitCountTemp = 2;
|
|
ctx->checkMultiHit = 253;
|
|
ctx->beatUpCount = 0;
|
|
|
|
while (TRUE) {
|
|
mon = BattleSystem_GetPartyMon(bsys, ctx->battlerIdAttacker, ctx->beatUpCount);
|
|
if (ctx->beatUpCount == ctx->selectedMonIndex[ctx->battlerIdAttacker]
|
|
|| (GetMonData(mon, MON_DATA_HP, 0) != 0
|
|
&& GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0) != SPECIES_NONE
|
|
&& GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0) != SPECIES_EGG
|
|
&& GetMonData(mon, MON_DATA_STATUS, 0) == STATUS_NONE)) {
|
|
break;
|
|
}
|
|
ctx->beatUpCount++;
|
|
}
|
|
}
|
|
|
|
mon = BattleSystem_GetPartyMon(bsys, ctx->battlerIdAttacker, ctx->beatUpCount);
|
|
species = GetMonData(mon, MON_DATA_SPECIES, 0);
|
|
form = GetMonData(mon, MON_DATA_FORM, 0);
|
|
level = GetMonData(mon, MON_DATA_LEVEL, 0);
|
|
|
|
ctx->damage = GetMonBaseStat_HandleAlternateForm(species, form, BASE_ATK);
|
|
ctx->damage *= ctx->trainerAIData.moveData[ctx->moveNoCur].power;
|
|
ctx->damage *= (level * 2 / 5 + 2);
|
|
ctx->damage /= (u32)GetMonBaseStat_HandleAlternateForm(ctx->battleMons[ctx->battlerIdTarget].species, ctx->battleMons[ctx->battlerIdTarget].form, BASE_DEF);
|
|
ctx->damage /= 50;
|
|
ctx->damage += 2;
|
|
ctx->damage *= ctx->criticalMultiplier;
|
|
if (ctx->turnData[ctx->battlerIdAttacker].helpingHandFlag) {
|
|
ctx->damage = ctx->damage * 15 / 10;
|
|
}
|
|
ctx->damage = ApplyDamageRange(bsys, ctx, ctx->damage);
|
|
ctx->damage *= -1;
|
|
|
|
ctx->buffMsg.id = msg_0197_00481;
|
|
ctx->buffMsg.tag = TAG_NICKNAME;
|
|
ctx->buffMsg.param[0] = (ctx->battlerIdAttacker | (ctx->beatUpCount << 8));
|
|
|
|
ctx->beatUpCount++;
|
|
ctx->multiHitCount = 2;
|
|
|
|
if (ctx->beatUpCount < monCnt) {
|
|
while (TRUE) {
|
|
mon = BattleSystem_GetPartyMon(bsys, ctx->battlerIdAttacker, ctx->beatUpCount);
|
|
if (ctx->beatUpCount == ctx->selectedMonIndex[ctx->battlerIdAttacker]
|
|
|| (GetMonData(mon, MON_DATA_HP, 0) != 0
|
|
&& GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0) != SPECIES_NONE
|
|
&& GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0) != SPECIES_EGG
|
|
&& GetMonData(mon, MON_DATA_STATUS, 0) == STATUS_NONE)) {
|
|
break;
|
|
}
|
|
ctx->beatUpCount++;
|
|
if (ctx->beatUpCount >= monCnt) {
|
|
ctx->multiHitCount = 1;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
ctx->multiHitCount = 1;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_FollowMe(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker);
|
|
ctx->fieldSideConditionData[side].followMeFlag = TRUE;
|
|
ctx->fieldSideConditionData[side].battlerIdFollowMe = ctx->battlerIdAttacker;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryHelpingHand(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
u32 battleType = BattleSystem_GetBattleType(bsys);
|
|
|
|
if (battleType & BATTLE_TYPE_DOUBLES) {
|
|
battlerId = GetBattlerIDBySide(bsys, ctx, 16);
|
|
if ((ctx->switchInFlag & MaskOfFlagNo(battlerId)) == 0 && ctx->playerActions[battlerId].command != CONTROLLER_COMMAND_40 && ctx->battleMons[battlerId].hp && !ctx->turnData[ctx->battlerIdAttacker].helpingHandFlag && !ctx->turnData[battlerId].helpingHandFlag) {
|
|
ctx->battlerIdTemp = battlerId;
|
|
ctx->turnData[battlerId].helpingHandFlag = TRUE;
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TrySwapItems(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrsA = BattleScriptReadWord(ctx);
|
|
int adrsB = BattleScriptReadWord(ctx);
|
|
|
|
u32 battleType = BattleSystem_GetBattleType(bsys);
|
|
int sideAttacker = BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker);
|
|
int sideTarget = BattleSystem_GetFieldSide(bsys, ctx->battlerIdTarget);
|
|
|
|
if (BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker) && (battleType & (BATTLE_TYPE_LINK | BATTLE_TYPE_FRONTIER)) == 0) {
|
|
BattleScriptIncrementPointer(ctx, adrsA);
|
|
} else if ((ctx->fieldSideConditionData[sideAttacker].battlerBitKnockedOffItem & MaskOfFlagNo(ctx->selectedMonIndex[ctx->battlerIdAttacker])) || (ctx->fieldSideConditionData[sideTarget].battlerBitKnockedOffItem & MaskOfFlagNo(ctx->selectedMonIndex[ctx->battlerIdTarget]))) {
|
|
BattleScriptIncrementPointer(ctx, adrsA);
|
|
} else if ((ctx->battleMons[ctx->battlerIdAttacker].item == 0 && ctx->battleMons[ctx->battlerIdTarget].item == 0) || !CanTrickHeldItem(ctx, ctx->battlerIdAttacker) || !CanTrickHeldItem(ctx, ctx->battlerIdTarget)) {
|
|
BattleScriptIncrementPointer(ctx, adrsA);
|
|
} else if (CheckBattlerAbilityIfNotIgnored(ctx, ctx->battlerIdAttacker, ctx->battlerIdTarget, ABILITY_STICKY_HOLD) == TRUE) {
|
|
BattleScriptIncrementPointer(ctx, adrsB);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryWish(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (ctx->fieldConditionData.wishTurns[ctx->battlerIdAttacker]) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else {
|
|
ctx->fieldConditionData.wishTurns[ctx->battlerIdAttacker] = 2;
|
|
ctx->fieldConditionData.wishTarget[ctx->battlerIdAttacker] = ctx->selectedMonIndex[ctx->battlerIdAttacker];
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryAssist(BattleSystem *bsys, BattleContext *ctx) {
|
|
u32 unkA;
|
|
u16 avaliableMoves[6 * 4];
|
|
u16 move;
|
|
int i, j, monCnt, moveCnt;
|
|
Pokemon *mon;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
unkA = BattleScriptReadWord(ctx);
|
|
|
|
moveCnt = 0;
|
|
monCnt = BattleSystem_GetPartySize(bsys, ctx->battlerIdAttacker);
|
|
|
|
for (i = 0; i < monCnt; i++) {
|
|
if (i != ctx->selectedMonIndex[ctx->battlerIdAttacker]) {
|
|
mon = BattleSystem_GetPartyMon(bsys, ctx->battlerIdAttacker, i);
|
|
if (GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0) != SPECIES_NONE
|
|
&& GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0) != SPECIES_EGG) {
|
|
for (j = 0; j < MAX_MON_MOVES; j++) {
|
|
move = GetMonData(mon, MON_DATA_MOVE1 + j, 0);
|
|
if (CheckMoveCallsOtherMove(move) == FALSE && CheckLegalMetronomeMove(bsys, ctx, ctx->battlerIdAttacker, move) == TRUE) {
|
|
avaliableMoves[moveCnt] = move;
|
|
moveCnt++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (moveCnt) {
|
|
ctx->moveTemp = avaliableMoves[BattleSystem_Random(bsys) % moveCnt];
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, unkA);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TrySetMagicCoat(BattleSystem *bsys, BattleContext *ctx) {
|
|
int i;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
u32 unkA = BattleScriptReadWord(ctx);
|
|
|
|
for (i = 0; i < BattleSystem_GetMaxBattlers(bsys); i++) {}
|
|
|
|
if (ctx->battlersOnField == 1) {
|
|
BattleScriptIncrementPointer(ctx, unkA);
|
|
} else {
|
|
ctx->turnData[ctx->battlerIdAttacker].magicCoatFlag = 1;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_MagicCoat(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker);
|
|
int battlerId = ctx->battlerIdAttacker;
|
|
ctx->battlerIdMagicCoat = battlerId;
|
|
ctx->battlerIdAttacker = ctx->battlerIdTarget;
|
|
|
|
if (ctx->fieldSideConditionData[side].followMeFlag && ctx->battleMons[ctx->fieldSideConditionData[side].battlerIdFollowMe].hp) {
|
|
ctx->battlerIdTarget = ctx->fieldSideConditionData[side].battlerIdFollowMe;
|
|
} else if (ctx->trainerAIData.moveData[ctx->moveNoCur].range == RANGE_ADJACENT_OPPONENTS || ctx->trainerAIData.moveData[ctx->moveNoCur].range == RANGE_ALL_ADJACENT) {
|
|
ctx->battlerIdTarget = battlerId;
|
|
} else {
|
|
side = ov12_022506D4(bsys, ctx, ctx->battlerIdAttacker, (u16)ctx->moveNoCur, 1, 0);
|
|
if (ctx->selfTurnData[side].lightningRodFlag || ctx->selfTurnData[side].stormDrainFlag) {
|
|
ctx->battlerIdTarget = side;
|
|
} else {
|
|
ctx->battlerIdTarget = battlerId;
|
|
}
|
|
}
|
|
|
|
ctx->battleStatus2 |= BATTLE_STATUS2_MAGIC_COAT;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CalcRevengeDamageMul(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
if ((ctx->turnData[ctx->battlerIdAttacker].physicalDamage[ctx->battlerIdTarget] && ctx->turnData[ctx->battlerIdAttacker].battlerBitPhysicalDamage & MaskOfFlagNo(ctx->battlerIdTarget)) || (ctx->turnData[ctx->battlerIdAttacker].specialDamage[ctx->battlerIdTarget] && ctx->turnData[ctx->battlerIdAttacker].battlerBitSpecialDamage & MaskOfFlagNo(ctx->battlerIdTarget))) {
|
|
ctx->unk_2158 = 20;
|
|
} else {
|
|
ctx->unk_2158 = 10;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryBreakScreens(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
int side = BattleSystem_GetFieldSide(bsys, ctx->battlerIdTarget);
|
|
|
|
if ((ctx->fieldSideConditionFlags[side] & SIDE_CONDITION_REFLECT) || (ctx->fieldSideConditionFlags[side] & SIDE_CONDITION_LIGHT_SCREEN)) {
|
|
ctx->fieldSideConditionFlags[side] &= ~SIDE_CONDITION_REFLECT;
|
|
ctx->fieldSideConditionFlags[side] &= ~SIDE_CONDITION_LIGHT_SCREEN;
|
|
ctx->fieldSideConditionData[side].reflectTurns = 0;
|
|
ctx->fieldSideConditionData[side].lightScreenTurns = 0;
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryYawn(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
u32 adrs = BattleScriptReadWord(ctx);
|
|
if (ctx->battleMons[ctx->battlerIdTarget].moveEffectFlags & MOVE_EFFECT_FLAG_YAWN) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else {
|
|
ctx->battleMons[ctx->battlerIdTarget].moveEffectFlags |= (2 << MOVE_EFFECT_FLAG_YAWN_SHIFT);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryKnockOff(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
int side = BattleSystem_GetFieldSide(bsys, ctx->battlerIdTarget);
|
|
|
|
if (ctx->battleMons[ctx->battlerIdTarget].item && CheckBattlerAbilityIfNotIgnored(ctx, ctx->battlerIdAttacker, ctx->battlerIdTarget, ABILITY_STICKY_HOLD) == TRUE) {
|
|
ctx->buffMsg.id = msg_0197_00714;
|
|
ctx->buffMsg.tag = TAG_NICKNAME_ABILITY_MOVE;
|
|
ctx->buffMsg.param[0] = CreateNicknameTag(ctx, ctx->battlerIdTarget);
|
|
ctx->buffMsg.param[1] = ctx->battleMons[ctx->battlerIdTarget].ability;
|
|
ctx->buffMsg.param[2] = ctx->moveNoCur;
|
|
} else if (ctx->battleMons[ctx->battlerIdTarget].item) {
|
|
ctx->buffMsg.id = msg_0197_00552;
|
|
ctx->buffMsg.tag = TAG_NICKNAME_NICKNAME_ITEM;
|
|
ctx->buffMsg.param[0] = CreateNicknameTag(ctx, ctx->battlerIdAttacker);
|
|
ctx->buffMsg.param[1] = CreateNicknameTag(ctx, ctx->battlerIdTarget);
|
|
ctx->buffMsg.param[2] = ctx->battleMons[ctx->battlerIdTarget].item;
|
|
ctx->battleMons[ctx->battlerIdTarget].item = 0;
|
|
ctx->fieldSideConditionData[side].battlerBitKnockedOffItem |= MaskOfFlagNo(ctx->selectedMonIndex[ctx->battlerIdTarget]);
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CalcHPFalloffPower(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
if (ctx->movePower == 0) {
|
|
ctx->movePower = ctx->trainerAIData.moveData[ctx->moveNoCur].power * ctx->battleMons[ctx->battlerIdAttacker].hp / ctx->battleMons[ctx->battlerIdAttacker].maxHp;
|
|
if (ctx->movePower == 0) {
|
|
ctx->movePower = 1;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryImprison(BattleSystem *bsys, BattleContext *ctx) {
|
|
int adrs, side, i, j, battlerId, maxBattlers, battlerIdA, battlerIdB;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
adrs = BattleScriptReadWord(ctx);
|
|
|
|
battlerIdA = ov12_0223ABB8(bsys, ctx->battlerIdAttacker, 0);
|
|
battlerIdB = ov12_0223ABB8(bsys, ctx->battlerIdAttacker, 2);
|
|
|
|
ctx->battleMons[battlerIdA].moveEffectFlags |= MOVE_EFFECT_FLAG_IMPRISON;
|
|
ctx->battleMons[battlerIdB].moveEffectFlags |= MOVE_EFFECT_FLAG_IMPRISON;
|
|
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].moveEffectFlags & MOVE_EFFECT_FLAG_IMPRISON_USER) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else {
|
|
side = BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker);
|
|
maxBattlers = BattleSystem_GetMaxBattlers(bsys);
|
|
for (battlerId = 0; battlerId < maxBattlers; battlerId++) {
|
|
if (side != BattleSystem_GetFieldSide(bsys, battlerId)) {
|
|
for (i = 0; i < MAX_MON_MOVES; i++) {
|
|
for (j = 0; j < MAX_MON_MOVES; j++) {
|
|
if ((ctx->battleMons[ctx->battlerIdAttacker].moves[i] == ctx->battleMons[battlerId].moves[j]) && ctx->battleMons[ctx->battlerIdAttacker].moves[i] && ctx->battleMons[battlerId].moves[j]) {
|
|
break;
|
|
}
|
|
}
|
|
if (j != MAX_MON_MOVES) {
|
|
break;
|
|
}
|
|
}
|
|
if (j != MAX_MON_MOVES) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (battlerId == maxBattlers) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else {
|
|
ctx->battleMons[ctx->battlerIdAttacker].moveEffectFlags |= MOVE_EFFECT_FLAG_IMPRISON_USER;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryGrudge(BattleSystem *bsys, BattleContext *ctx) {
|
|
int pos;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
BattleSystem_GetFieldSide(bsys, ctx->battlerIdTarget);
|
|
|
|
if (ctx->battleMons[ctx->battlerIdFainted].moveEffectFlags & MOVE_EFFECT_FLAG_GRUDGE && BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker) != BattleSystem_GetFieldSide(bsys, ctx->battlerIdFainted) && ctx->battleMons[ctx->battlerIdAttacker].hp && ctx->moveNoTemp != MOVE_STRUGGLE) {
|
|
pos = ctx->movePos[ctx->battlerIdAttacker];
|
|
ctx->battleMons[ctx->battlerIdAttacker].movePPCur[pos] = 0;
|
|
ctx->moveTemp = ctx->battleMons[ctx->battlerIdAttacker].moves[pos];
|
|
CopyBattleMonToPartyMon(bsys, ctx, ctx->battlerIdAttacker);
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TrySnatch(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
u32 maxBattlers;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
maxBattlers = 0;
|
|
for (battlerId = 0; battlerId < BattleSystem_GetMaxBattlers(bsys); battlerId++) {
|
|
if (ctx->battleMons[battlerId].hp) {
|
|
maxBattlers++;
|
|
}
|
|
}
|
|
|
|
if (ctx->battlersOnField == 1) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else {
|
|
ctx->turnData[ctx->battlerIdAttacker].snatchFlag = TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern u16 sLowKickDamageTable[6][2];
|
|
|
|
BOOL BtlCmd_CalcWeightBasedPower(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int cnt = 0;
|
|
int weight = ctx->battleMons[ctx->battlerIdTarget].weight;
|
|
|
|
do {
|
|
if (sLowKickDamageTable[cnt][0] >= weight) {
|
|
break;
|
|
}
|
|
cnt++;
|
|
} while (sLowKickDamageTable[cnt][0] != 0xffff);
|
|
|
|
if (sLowKickDamageTable[cnt][0] != 0xffff) {
|
|
ctx->movePower = sLowKickDamageTable[cnt][1];
|
|
} else {
|
|
ctx->movePower = 120;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CalcWeatherBallParams(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
if (!CheckAbilityActive(bsys, ctx, CHECK_ABILITY_ALL_HP, 0, ABILITY_CLOUD_NINE) && !CheckAbilityActive(bsys, ctx, CHECK_ABILITY_ALL_HP, 0, ABILITY_AIR_LOCK)) {
|
|
if (ctx->fieldCondition & FIELD_CONDITION_WEATHER) {
|
|
ctx->movePower = ctx->trainerAIData.moveData[ctx->moveNoCur].power * 2;
|
|
if (ctx->fieldCondition & FIELD_CONDITION_RAIN_ALL) {
|
|
ctx->moveType = TYPE_WATER;
|
|
}
|
|
if (ctx->fieldCondition & FIELD_CONDITION_SANDSTORM_ALL) {
|
|
ctx->moveType = TYPE_ROCK;
|
|
}
|
|
if (ctx->fieldCondition & FIELD_CONDITION_SUN_ALL) {
|
|
ctx->moveType = TYPE_FIRE;
|
|
}
|
|
if (ctx->fieldCondition & FIELD_CONDITION_HAIL_ALL) {
|
|
ctx->moveType = TYPE_ICE;
|
|
}
|
|
} else {
|
|
ctx->movePower = ctx->trainerAIData.moveData[ctx->moveNoCur].power;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryPursuit(BattleSystem *bsys, BattleContext *ctx) {
|
|
int adrs, battlerId, maxBattlers, moveNo, moveIndex;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
adrs = BattleScriptReadWord(ctx);
|
|
maxBattlers = BattleSystem_GetMaxBattlers(bsys);
|
|
|
|
for (battlerId = 0; battlerId < maxBattlers; battlerId++) {
|
|
if (ctx->playerActions[battlerId].command != CONTROLLER_COMMAND_40 && ctx->battleMons[battlerId].hp && !(ctx->battleMons[battlerId].status & 39) && !CheckTruant(ctx, battlerId) && BattleSystem_GetFieldSide(bsys, battlerId) != BattleSystem_GetFieldSide(bsys, ctx->battlerIdSwitch)) {
|
|
if (ctx->battleMons[battlerId].unk88.encoredMove && ctx->battleMons[battlerId].unk88.encoredMove == ctx->battleMons[battlerId].moves[ctx->battleMons[battlerId].unk88.encoredMoveIndex]) {
|
|
moveNo = ctx->battleMons[battlerId].unk88.encoredMove;
|
|
} else {
|
|
moveNo = GetBattlerSelectedMove(ctx, battlerId);
|
|
}
|
|
if (moveNo) {
|
|
moveIndex = BattleMon_GetMoveIndex(&ctx->battleMons[battlerId], moveNo);
|
|
if (ctx->trainerAIData.moveData[moveNo].effect == MOVE_EFFECT_HIT_BEFORE_SWITCH && ctx->battleMons[battlerId].movePPCur[moveIndex]) {
|
|
ctx->battleMons[battlerId].movePPCur[moveIndex]--;
|
|
if (GetBattlerAbility(ctx, ctx->battlerIdSwitch) == ABILITY_PRESSURE && ctx->battleMons[battlerId].movePPCur[moveIndex]) {
|
|
ctx->battleMons[battlerId].movePPCur[moveIndex]--;
|
|
}
|
|
ov12_02252D14(bsys, ctx);
|
|
ctx->battlerIdAttacker = battlerId;
|
|
ctx->battlerIdTarget = ctx->battlerIdSwitch;
|
|
ctx->unk_2158 = 20;
|
|
ctx->moveNoCur = moveNo;
|
|
ctx->moveNoBattlerPrev[battlerId] = moveNo;
|
|
ctx->playerActions[battlerId].command = CONTROLLER_COMMAND_40;
|
|
CopyBattleMonToPartyMon(bsys, ctx, battlerId);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (battlerId == maxBattlers) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else {
|
|
int itemEffect = GetBattlerHeldItemEffect(ctx, ctx->battlerIdAttacker);
|
|
GetHeldItemModifier(ctx, ctx->battlerIdAttacker, 0);
|
|
|
|
if (itemEffect == HOLD_EFFECT_CHOICE_ATK || itemEffect == HOLD_EFFECT_CHOICE_SPEED || itemEffect == HOLD_EFFECT_CHOICE_SPATK) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.moveNoChoice = moveNo;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_ApplyTypeEffectiveness(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
ctx->damage = ov12_02251D28(bsys, ctx, ctx->moveNoCur, ctx->moveType, ctx->battlerIdAttacker, ctx->battlerIdTarget, ctx->damage, &ctx->moveStatusFlag);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_IfTurnFlag(BattleSystem *bsys, BattleContext *ctx) {
|
|
int ret = FALSE;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int flag = BattleScriptReadWord(ctx);
|
|
int val = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
switch (flag) {
|
|
case 0:
|
|
if (ctx->turnData[battlerId].struggleFlag == val) {
|
|
ret = TRUE;
|
|
}
|
|
break;
|
|
case 1:
|
|
if (ctx->turnData[battlerId].unk0_1 == val) {
|
|
ret = TRUE;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (ctx->turnData[battlerId].protectFlag == val) {
|
|
ret = TRUE;
|
|
}
|
|
break;
|
|
case 3:
|
|
if (ctx->turnData[battlerId].helpingHandFlag == val) {
|
|
ret = TRUE;
|
|
}
|
|
break;
|
|
case 4:
|
|
if (ctx->turnData[battlerId].magicCoatFlag == val) {
|
|
ret = TRUE;
|
|
}
|
|
break;
|
|
case 5:
|
|
if (ctx->turnData[battlerId].snatchFlag == val) {
|
|
ret = TRUE;
|
|
}
|
|
break;
|
|
case 6:
|
|
if (ctx->turnData[battlerId].roostFlag == val) {
|
|
ret = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (ret) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_SetTurnFlag(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int flag = BattleScriptReadWord(ctx);
|
|
int val = BattleScriptReadWord(ctx);
|
|
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
switch (flag) {
|
|
case 0:
|
|
ctx->turnData[battlerId].struggleFlag = val;
|
|
break;
|
|
case 1:
|
|
ctx->turnData[battlerId].unk0_1 = val;
|
|
break;
|
|
case 2:
|
|
ctx->turnData[battlerId].protectFlag = val;
|
|
break;
|
|
case 3:
|
|
ctx->turnData[battlerId].helpingHandFlag = val;
|
|
break;
|
|
case 4:
|
|
ctx->turnData[battlerId].magicCoatFlag = val;
|
|
break;
|
|
case 5:
|
|
ctx->turnData[battlerId].snatchFlag = val;
|
|
break;
|
|
case 6:
|
|
ctx->turnData[battlerId].roostFlag = val;
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CalcGyroBallPower(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
ctx->movePower = 1 + 25 * ctx->effectiveSpeed[ctx->battlerIdTarget] / ctx->effectiveSpeed[ctx->battlerIdAttacker];
|
|
|
|
if (ctx->movePower > 150) {
|
|
ctx->movePower = 150;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryMetalBurst(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int sideA = BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker);
|
|
int sideB = BattleSystem_GetFieldSide(bsys, ctx->turnData[ctx->battlerIdAttacker].unk38);
|
|
|
|
if (ctx->turnData[ctx->battlerIdAttacker].unk34 && sideA != sideB && ctx->battleMons[ctx->turnData[ctx->battlerIdAttacker].unk38].hp) {
|
|
ctx->damage = ctx->turnData[ctx->battlerIdAttacker].unk34 * 15 / 10;
|
|
if (ctx->fieldSideConditionData[sideB].followMeFlag && ctx->battleMons[ctx->fieldSideConditionData[sideB].battlerIdFollowMe].hp) {
|
|
ctx->battlerIdTarget = ctx->fieldSideConditionData[sideB].battlerIdFollowMe;
|
|
} else {
|
|
ctx->battlerIdTarget = ctx->turnData[ctx->battlerIdAttacker].unk38;
|
|
}
|
|
if (ctx->battleMons[ctx->battlerIdTarget].hp == 0) {
|
|
ctx->battlerIdTarget = Battler_GetRandomOpposingBattlerId(bsys, ctx, ctx->battlerIdAttacker);
|
|
if (ctx->battleMons[ctx->battlerIdTarget].hp == 0) {
|
|
ctx->commandNext = CONTROLLER_COMMAND_39;
|
|
BattleScriptJump(ctx, NARC_a_0_0_1, BATTLE_SUBSCRIPT_NO_TARGET);
|
|
}
|
|
}
|
|
CheckIgnorePressure(ctx, ctx->battlerIdAttacker, ctx->battlerIdTarget);
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CalcPaybackPower(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
if (ctx->playerActions[ctx->battlerIdTarget].command == CONTROLLER_COMMAND_40) {
|
|
ctx->movePower = ctx->trainerAIData.moveData[ctx->moveNoCur].power * 2;
|
|
} else {
|
|
ctx->movePower = ctx->trainerAIData.moveData[ctx->moveNoCur].power;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern u8 sTrumpCardPowerTable[];
|
|
|
|
BOOL BtlCmd_CalcTrumpCardPower(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u8 pp = ctx->battleMons[ctx->battlerIdAttacker].movePPCur[ctx->movePos[ctx->battlerIdAttacker]];
|
|
|
|
if (pp > 4) {
|
|
pp = 4;
|
|
}
|
|
|
|
ctx->movePower = sTrumpCardPowerTable[pp];
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CalcWringOutPower(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
ctx->movePower = 1 + (120 * ctx->battleMons[ctx->battlerIdTarget].hp) / ctx->battleMons[ctx->battlerIdTarget].maxHp;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryMeFirst(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
u16 move;
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (ctx->battleMons[ctx->battlerIdTarget].unk88.encoredMove && ctx->battleMons[ctx->battlerIdTarget].unk88.encoredMove == ctx->battleMons[ctx->battlerIdTarget].moves[ctx->battleMons[ctx->battlerIdTarget].unk88.encoredMoveIndex]) {
|
|
move = ctx->battleMons[ctx->battlerIdTarget].unk88.encoredMove;
|
|
} else {
|
|
move = GetBattlerSelectedMove(ctx, ctx->battlerIdTarget);
|
|
}
|
|
|
|
if (ctx->playerActions[ctx->battlerIdTarget].command != CONTROLLER_COMMAND_40 && ctx->turnData[ctx->battlerIdTarget].struggleFlag == 0 && CheckLegalMeFirstMove(ctx, move) == TRUE && ctx->trainerAIData.moveData[move].power) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.meFirstFlag = TRUE;
|
|
ctx->battleMons[ctx->battlerIdAttacker].unk88.meFirstCount = ctx->meFirstTotal;
|
|
ctx->moveTemp = move;
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryCopycat(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (CheckMoveCallsOtherMove(ctx->moveNoPrev) == FALSE && ctx->moveNoPrev && CheckLegalMetronomeMove(bsys, ctx, ctx->battlerIdAttacker, ctx->moveNoPrev) == TRUE) {
|
|
ctx->moveTemp = ctx->moveNoPrev;
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CalcPunishmentPower(BattleSystem *bsys, BattleContext *ctx) {
|
|
int stat, cnt;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
cnt = 0;
|
|
for (stat = 0; stat < 8; stat++) {
|
|
if (ctx->battleMons[ctx->battlerIdTarget].statChanges[stat] > 6) {
|
|
cnt += ctx->battleMons[ctx->battlerIdTarget].statChanges[stat] - 6;
|
|
}
|
|
}
|
|
|
|
ctx->movePower = 60 + 20 * cnt;
|
|
|
|
if (ctx->movePower > 200) {
|
|
ctx->movePower = 200;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TrySuckerPunch(BattleSystem *bsys, BattleContext *ctx) {
|
|
int move;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (ctx->battleMons[ctx->battlerIdTarget].unk88.encoredMove && ctx->battleMons[ctx->battlerIdTarget].unk88.encoredMove == ctx->battleMons[ctx->battlerIdTarget].moves[ctx->battleMons[ctx->battlerIdTarget].unk88.encoredMoveIndex]) {
|
|
move = ctx->battleMons[ctx->battlerIdTarget].unk88.encoredMove;
|
|
} else {
|
|
move = GetBattlerSelectedMove(ctx, ctx->battlerIdTarget);
|
|
}
|
|
|
|
if (ctx->playerActions[ctx->battlerIdTarget].command == CONTROLLER_COMMAND_40 || (ctx->trainerAIData.moveData[move].power == 0 && !ctx->turnData[ctx->battlerIdTarget].struggleFlag)) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckSideCondition(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int unkB = BattleScriptReadWord(ctx);
|
|
int flag = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int fieldSide = BattleSystem_GetFieldSide(bsys, GetBattlerIDBySide(bsys, ctx, side));
|
|
|
|
int var;
|
|
|
|
switch (unkB) {
|
|
case 0:
|
|
case 1:
|
|
switch (flag) {
|
|
case 0:
|
|
var = ctx->fieldSideConditionData[fieldSide].reflectTurns;
|
|
break;
|
|
case 1:
|
|
var = ctx->fieldSideConditionData[fieldSide].lightScreenTurns;
|
|
break;
|
|
case 2:
|
|
var = ctx->fieldSideConditionData[fieldSide].mistTurns;
|
|
break;
|
|
case 3:
|
|
var = ctx->fieldSideConditionData[fieldSide].safeguardTurns;
|
|
break;
|
|
case 4:
|
|
var = ctx->fieldSideConditionData[fieldSide].spikesLayers;
|
|
break;
|
|
case 5:
|
|
var = ctx->fieldSideConditionData[fieldSide].toxicSpikesLayers;
|
|
break;
|
|
}
|
|
break;
|
|
case 2:
|
|
switch (flag) {
|
|
case 0:
|
|
ctx->fieldSideConditionData[fieldSide].reflectTurns = 0;
|
|
ctx->fieldSideConditionFlags[fieldSide] &= ~1;
|
|
break;
|
|
case 1:
|
|
ctx->fieldSideConditionData[fieldSide].lightScreenTurns = 0;
|
|
ctx->fieldSideConditionFlags[fieldSide] &= ~2;
|
|
break;
|
|
case 2:
|
|
ctx->fieldSideConditionData[fieldSide].mistTurns = 0;
|
|
ctx->fieldSideConditionFlags[fieldSide] &= ~64;
|
|
break;
|
|
case 3:
|
|
ctx->fieldSideConditionData[fieldSide].safeguardTurns = 0;
|
|
ctx->fieldSideConditionFlags[fieldSide] &= ~8;
|
|
break;
|
|
case 4:
|
|
ctx->fieldSideConditionData[fieldSide].spikesLayers = 0;
|
|
ctx->fieldSideConditionFlags[fieldSide] &= ~4;
|
|
break;
|
|
case 5:
|
|
ctx->fieldSideConditionData[fieldSide].toxicSpikesLayers = 0;
|
|
ctx->fieldSideConditionFlags[fieldSide] &= ~(1 << 10);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (unkB == 0 && !var) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
if (unkB == 1 && var) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryFeint(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (!ctx->turnData[ctx->battlerIdTarget].protectFlag) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryPyschoShift(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (ctx->battleMons[ctx->battlerIdTarget].status || ctx->battleMons[ctx->battlerIdTarget].status2 & STATUS2_SUBSTITUTE || !ctx->battleMons[ctx->battlerIdAttacker].status) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryLastResort(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int cnt = GetBattlerLearnedMoveCount(bsys, ctx, ctx->battlerIdAttacker);
|
|
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].unk88.lastResortCount < cnt - 1 || cnt < 2) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryToxicSpikes(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int side = BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker) ^ 1;
|
|
|
|
if (ctx->fieldSideConditionData[side].toxicSpikesLayers == 2) {
|
|
ctx->selfTurnData[ctx->battlerIdAttacker].ignorePressure = TRUE;
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else {
|
|
ctx->fieldSideConditionFlags[side] |= (1 << 10);
|
|
ctx->fieldSideConditionData[side].toxicSpikesLayers++;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckToxicSpikes(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
int fieldSide = BattleSystem_GetFieldSide(bsys, battlerId);
|
|
|
|
if (ctx->fieldSideConditionData[fieldSide].toxicSpikesLayers) {
|
|
ctx->calcTemp = ctx->fieldSideConditionData[fieldSide].toxicSpikesLayers;
|
|
ctx->statChangeType = 6;
|
|
ctx->battlerIdStatChange = battlerId;
|
|
if (GetBattlerVar(ctx, ctx->battlerIdSwitch, BMON_DATA_TYPE_1, NULL) == TYPE_POISON || GetBattlerVar(ctx, ctx->battlerIdSwitch, BMON_DATA_TYPE_2, NULL) == TYPE_POISON) {
|
|
ctx->fieldSideConditionFlags[fieldSide] &= ~(1 << 10);
|
|
ctx->fieldSideConditionData[fieldSide].toxicSpikesLayers = 0;
|
|
ctx->calcTemp = 0;
|
|
}
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckIgnorableAbility(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int flag = BattleScriptReadWord(ctx);
|
|
int side = BattleScriptReadWord(ctx);
|
|
int ability = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (side == 0) {
|
|
int index;
|
|
int maxBattlers = BattleSystem_GetMaxBattlers(bsys);
|
|
|
|
for (index = 0; index < maxBattlers; index++) {
|
|
battlerId = ctx->turnOrder[index];
|
|
if (flag == 0) {
|
|
if (CheckBattlerAbilityIfNotIgnored(ctx, ctx->battlerIdAttacker, battlerId, ability) == TRUE && ctx->battleMons[battlerId].hp) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
ctx->battlerIdAbility = battlerId;
|
|
break;
|
|
}
|
|
} else if (!CheckBattlerAbilityIfNotIgnored(ctx, ctx->battlerIdAttacker, battlerId, ability) || !ctx->battleMons[battlerId].hp) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
ctx->battlerIdAbility = battlerId;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
if (flag == 0) {
|
|
if (CheckBattlerAbilityIfNotIgnored(ctx, ctx->battlerIdAttacker, battlerId, ability) == TRUE && ctx->battleMons[battlerId].hp) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
ctx->battlerIdAbility = battlerId;
|
|
}
|
|
} else if (!CheckBattlerAbilityIfNotIgnored(ctx, ctx->battlerIdAttacker, battlerId, ability) || !ctx->battleMons[battlerId].hp) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
ctx->battlerIdAbility = battlerId;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_IfSameSide(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int sideA = BattleScriptReadWord(ctx);
|
|
int sideB = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int battlerIdA = GetBattlerIDBySide(bsys, ctx, sideA);
|
|
int battlerIdB = GetBattlerIDBySide(bsys, ctx, sideB);
|
|
|
|
if (BattleSystem_GetFieldSide(bsys, battlerIdA) == BattleSystem_GetFieldSide(bsys, battlerIdB)) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern const u16 sPickupTable1[18];
|
|
extern const u16 sPickupTable2[11];
|
|
extern const u8 sPickupWeightTable[9];
|
|
extern const u8 sHoneyGatherChanceTable[10];
|
|
|
|
BOOL BtlCmd_GenerateEndOfBattleItem(BattleSystem *bsys, BattleContext *ctx) {
|
|
int rnd, i, j, k;
|
|
u16 species, item;
|
|
u8 ability, lvl;
|
|
Pokemon *mon;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
for (i = 0; i < BattleSystem_GetPartySize(bsys, 0); i++) {
|
|
mon = BattleSystem_GetPartyMon(bsys, 0, i);
|
|
species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0);
|
|
item = GetMonData(mon, MON_DATA_HELD_ITEM, 0);
|
|
ability = GetMonData(mon, MON_DATA_ABILITY, 0);
|
|
if (ability == ABILITY_PICKUP
|
|
&& species != SPECIES_NONE
|
|
&& species != SPECIES_EGG
|
|
&& item == ITEM_NONE
|
|
&& !(BattleSystem_Random(bsys) % 10)) {
|
|
rnd = BattleSystem_Random(bsys) % 100;
|
|
lvl = (GetMonData(mon, MON_DATA_LEVEL, 0) - 1) / 10;
|
|
if (lvl >= 10) {
|
|
lvl = 9;
|
|
}
|
|
for (j = 0; j < 9; j++) {
|
|
if (sPickupWeightTable[j] > rnd) {
|
|
SetMonData(mon, MON_DATA_HELD_ITEM, &sPickupTable1[lvl + j]);
|
|
break;
|
|
} else if (rnd >= 98 && rnd <= 99) {
|
|
SetMonData(mon, MON_DATA_HELD_ITEM, &sPickupTable2[lvl + (99 - rnd)]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (ability == ABILITY_HONEY_GATHER
|
|
&& species != SPECIES_NONE
|
|
&& species != SPECIES_EGG
|
|
&& item == ITEM_NONE) {
|
|
j = 0;
|
|
k = 10;
|
|
lvl = GetMonData(mon, MON_DATA_LEVEL, 0);
|
|
while (lvl > k) {
|
|
j++;
|
|
k += 10;
|
|
}
|
|
|
|
GF_ASSERT(j < 10);
|
|
|
|
if ((BattleSystem_Random(bsys) % 100) < sHoneyGatherChanceTable[j]) {
|
|
j = ITEM_HONEY;
|
|
SetMonData(mon, MON_DATA_HELD_ITEM, &j);
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TrickRoom(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
ctx->selfTurnData[ctx->battlerIdAttacker].trickRoomFlag = TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_IfMovedThisTurn(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
if (ov12_0225561C(ctx, battlerId) == TRUE) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckItemHoldEffect(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int flag = BattleScriptReadWord(ctx);
|
|
int side = BattleScriptReadWord(ctx);
|
|
int itemEffect = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
if (flag == 0) {
|
|
if (GetBattlerHeldItemEffect(ctx, battlerId) == itemEffect) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
} else if (GetBattlerHeldItemEffect(ctx, battlerId) != itemEffect) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_GetItemHoldEffect(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int varId = BattleScriptReadWord(ctx);
|
|
int *holdEffect = BattleScriptGetVarPointer(bsys, ctx, varId);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
u16 item = GetBattlerHeldItem(ctx, battlerId);
|
|
*holdEffect = GetItemVar(ctx, item, ITEM_VAR_HOLD_EFFECT);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_GetItemEffectParam(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int varId = BattleScriptReadWord(ctx);
|
|
int *var = BattleScriptGetVarPointer(bsys, ctx, varId);
|
|
u16 item = GetBattlerHeldItem(ctx, GetBattlerIDBySide(bsys, ctx, side));
|
|
*var = GetItemVar(ctx, item, ITEM_VAR_MODIFIER);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern const u8 sCamouflageTypeTable[13];
|
|
|
|
BOOL BtlCmd_TryCamouflage(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (GetBattlerAbility(ctx, ctx->battlerIdAttacker) == ABILITY_MULTITYPE) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
return FALSE;
|
|
}
|
|
|
|
Terrain terrain = BattleSystem_GetTerrainId(bsys);
|
|
if (terrain > TERRAIN_OTHERS) {
|
|
terrain = TERRAIN_OTHERS;
|
|
}
|
|
int type = sCamouflageTypeTable[terrain];
|
|
|
|
if (GetBattlerVar(ctx, ctx->battlerIdAttacker, BMON_DATA_TYPE_1, NULL) != type && GetBattlerVar(ctx, ctx->battlerIdAttacker, BMON_DATA_TYPE_2, NULL) != type) {
|
|
ctx->battleMons[ctx->battlerIdAttacker].type1 = type;
|
|
ctx->battleMons[ctx->battlerIdAttacker].type2 = type;
|
|
ctx->msgTemp = type;
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern u16 sNaturePowerMoveTable[];
|
|
|
|
BOOL BtlCmd_GetTerrainMove(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int terrain = BattleSystem_GetTerrainId(bsys);
|
|
if (terrain > 12) {
|
|
terrain = 12;
|
|
}
|
|
ctx->moveTemp = sNaturePowerMoveTable[terrain];
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern u32 sSecretPowerEffectTable[];
|
|
|
|
BOOL BtlCmd_GetTerrainSecondaryEffect(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int terrain = BattleSystem_GetTerrainId(bsys);
|
|
if (terrain > 12) {
|
|
terrain = 12;
|
|
}
|
|
ctx->unk_2174 = sSecretPowerEffectTable[terrain];
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CalcNaturalGiftParams(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
int power = GetNaturalGiftPower(ctx, ctx->battlerIdAttacker);
|
|
|
|
if (power) {
|
|
ctx->movePower = power;
|
|
ctx->moveType = GetNaturalGiftType(ctx, ctx->battlerIdAttacker);
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryPluck(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs1 = BattleScriptReadWord(ctx);
|
|
int adrs2 = BattleScriptReadWord(ctx);
|
|
|
|
if (ctx->battleMons[ctx->battlerIdTarget].item && CheckBattlerAbilityIfNotIgnored(ctx, ctx->battlerIdAttacker, ctx->battlerIdTarget, ABILITY_STICKY_HOLD) == TRUE) {
|
|
BattleScriptIncrementPointer(ctx, adrs1);
|
|
} else if ((ctx->battleMons[ctx->battlerIdTarget].item && ctx->battleMons[ctx->battlerIdTarget].unk88.custapBerryFlag) || TryEatOpponentBerry(bsys, ctx, ctx->battlerIdTarget) != TRUE) {
|
|
BattleScriptIncrementPointer(ctx, adrs2);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryFling(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (TryFling(bsys, ctx, ctx->battlerIdAttacker) != TRUE) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_YesNoMenu(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
BattleController_EmitDrawYesNoBox(bsys, ctx, 0, 0, BattleScriptReadWord(ctx), 0, 0);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_WaitYesNoResult(BattleSystem *bsys, BattleContext *ctx) {
|
|
u8 selection = BattleBuffer_GetNext(ctx, 0);
|
|
|
|
if (selection) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrsYes = BattleScriptReadWord(ctx);
|
|
int adrsNo = BattleScriptReadWord(ctx);
|
|
|
|
if (selection == 255) {
|
|
BattleScriptIncrementPointer(ctx, adrsNo);
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrsYes);
|
|
}
|
|
|
|
ov12_0223BDDC(bsys, 0, selection);
|
|
}
|
|
|
|
ctx->battleContinueFlag = TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_ChoosePokemonMenu(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleSystem_GetMaxBattlers(bsys);
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
BattleController_EmitShowMonList(bsys, ctx, 0, 0, 0, 6);
|
|
ctx->battlerIdSwitch = 0;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_WaitPokemonMenuResult(BattleSystem *bsys, BattleContext *ctx) {
|
|
u8 selection = BattleBuffer_GetNext(ctx, 0);
|
|
|
|
if (selection) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (selection == 255) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
} else {
|
|
ctx->unk_21A0[0] = selection - 1;
|
|
}
|
|
}
|
|
|
|
ctx->battleContinueFlag = TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_SetLinkBattleResult(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
if (BattleSystem_GetBattleType(bsys) & 4) {
|
|
BattleController_EmitSetBattleResults(bsys);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckStealthRock(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
int fieldSide = BattleSystem_GetFieldSide(bsys, battlerId);
|
|
int type1 = GetBattlerVar(ctx, battlerId, BMON_DATA_TYPE_1, NULL);
|
|
int type2 = GetBattlerVar(ctx, battlerId, BMON_DATA_TYPE_2, NULL);
|
|
|
|
if (ctx->fieldSideConditionFlags[fieldSide] & 128 && ctx->battleMons[battlerId].hp) {
|
|
switch (CalculateTypeEffectiveness(TYPE_ROCK, type1, type2)) {
|
|
case 160:
|
|
ctx->hpCalc = 2;
|
|
break;
|
|
case 80:
|
|
ctx->hpCalc = 4;
|
|
break;
|
|
case 40:
|
|
ctx->hpCalc = 8;
|
|
break;
|
|
case 20:
|
|
ctx->hpCalc = 16;
|
|
break;
|
|
case 10:
|
|
ctx->hpCalc = 32;
|
|
break;
|
|
case 0:
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
return FALSE;
|
|
default:
|
|
GF_ASSERT(FALSE);
|
|
break;
|
|
}
|
|
ctx->hpCalc = DamageDivide(ctx->battleMons[battlerId].maxHp * -1, ctx->hpCalc);
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckEffectActivation(BattleSystem *bsys, BattleContext *ctx) {
|
|
u16 effectChance;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (GetBattlerAbility(ctx, ctx->battlerIdAttacker) == ABILITY_SERENE_GRACE) {
|
|
effectChance = ctx->trainerAIData.moveData[ctx->moveNoCur].effectChance * 2;
|
|
} else {
|
|
effectChance = ctx->trainerAIData.moveData[ctx->moveNoCur].effectChance;
|
|
}
|
|
|
|
GF_ASSERT(effectChance != 0);
|
|
|
|
if ((BattleSystem_Random(bsys) % 100) < effectChance && ctx->battleMons[ctx->battlerIdStatChange].hp) {
|
|
return FALSE;
|
|
}
|
|
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckChatterActivation(BattleSystem *bsys, BattleContext *ctx) {
|
|
u16 effectChance;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int param;
|
|
|
|
if (ctx->battleMons[ctx->battlerIdAttacker].species == SPECIES_CHATOT && ctx->battleMons[ctx->battlerIdTarget].hp && !(ctx->battleMons[ctx->battlerIdAttacker].status2 & (1 << 21))) {
|
|
if ((BattleSystem_GetBattleSpecial(bsys) & BATTLE_SPECIAL_RECORDING) == FALSE) {
|
|
param = sub_02006EFC(BattleSystem_GetChatotVoice(bsys, ctx->battlerIdAttacker));
|
|
} else {
|
|
param = BattleSystem_GetChatotVoiceParam(bsys, ctx->battlerIdAttacker);
|
|
}
|
|
|
|
switch (param) {
|
|
default:
|
|
case 0:
|
|
effectChance = 0;
|
|
break;
|
|
case 1:
|
|
effectChance = 10;
|
|
break;
|
|
case 2:
|
|
effectChance = 30;
|
|
break;
|
|
}
|
|
if ((BattleSystem_Random(bsys) % 100) > effectChance) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_GetCurrentMoveData(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
ctx->calcTemp = GetMoveTblAttr(&ctx->trainerAIData.moveData[ctx->moveNoCur], (MoveAttr)BattleScriptReadWord(ctx));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_SetMosaic(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int param = BattleScriptReadWord(ctx);
|
|
int delay = BattleScriptReadWord(ctx);
|
|
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
BattleController_EmitPlayMosaicAnimation(bsys, battlerId, param, delay);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_ChangeForm(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
BattleController_EmitChangeForm(bsys, battlerId);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_SetBattleBackground(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
BattleController_EmitSetBattleBackground(bsys, 0);
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_UseBagItem(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
BattleSystem_RecoverStatus(bsys, battlerId, ctx->selectedMonIndex[battlerId], 0, ctx->itemTemp);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryEscape(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
if (BattleTryRun(bsys, ctx, battlerId)) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_ShowBattleStartPartyGauge(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
BattleController_EmitInitStartBallGauge(bsys, battlerId);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_HideBattleStartPartyGauge(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
BattleController_EmitDeleteStartBallGauge(bsys, battlerId);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_ShowPartyGauge(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
BattleController_EmitInitBallGauge(bsys, battlerId);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_HidePartyGauge(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
BattleController_EmitDeleteBallGauge(bsys, battlerId);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_LoadPartyGaugeGraphics(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
BattleController_EmitLoadBallGfx(bsys);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_FreePartyGaugeGraphics(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
BattleController_EmitDeleteBallGfx(bsys);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_IncrementGameStat(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int flag = BattleScriptReadWord(ctx);
|
|
int id = BattleScriptReadWord(ctx);
|
|
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
BattleController_EmitIncrementGameStat(bsys, battlerId, flag, id);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_RestoreSprite(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
ov12_02263F8C(bsys, ctx, battlerId);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TriggerAbilityOnHit(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
if (CheckAbilityEffectOnHit(bsys, ctx, &ctx->tempData) == FALSE) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_SpriteToOAM(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
OpponentData *opponentData;
|
|
int maxBattlers = BattleSystem_GetMaxBattlers(bsys);
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
|
|
switch (side) {
|
|
case 3:
|
|
for (battlerId = 0; battlerId < maxBattlers; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (!(opponentData->unk195 & 1)) {
|
|
ov12_02264038(bsys, battlerId);
|
|
}
|
|
}
|
|
break;
|
|
case 4:
|
|
for (battlerId = 0; battlerId < maxBattlers; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 & 1) {
|
|
ov12_02264038(bsys, battlerId);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
ov12_02264038(bsys, battlerId);
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_OAMToSprite(BattleSystem *bsys, BattleContext *ctx) {
|
|
int battlerId;
|
|
OpponentData *opponentData;
|
|
int maxBattlers = BattleSystem_GetMaxBattlers(bsys);
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
|
|
switch (side) {
|
|
case 3:
|
|
for (battlerId = 0; battlerId < maxBattlers; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (!(opponentData->unk195 & 1)) {
|
|
ov12_02264054(bsys, battlerId);
|
|
}
|
|
}
|
|
break;
|
|
case 4:
|
|
for (battlerId = 0; battlerId < maxBattlers; battlerId++) {
|
|
opponentData = BattleSystem_GetOpponentData(bsys, battlerId);
|
|
if (opponentData->unk195 & 1) {
|
|
ov12_02264054(bsys, battlerId);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
ov12_02264054(bsys, battlerId);
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckWhiteout(BattleSystem *bsys, BattleContext *ctx) {
|
|
int i;
|
|
int adrs;
|
|
int battlerId;
|
|
int partyHp = 0;
|
|
|
|
Pokemon *mon;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
adrs = BattleScriptReadWord(ctx);
|
|
|
|
int battleType = BattleSystem_GetBattleType(bsys);
|
|
battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
if (battleType & BATTLE_TYPE_MULTI || (battleType & BATTLE_TYPE_TAG && BattleSystem_GetFieldSide(bsys, battlerId))) {
|
|
Party *party1 = BattleSystem_GetParty(bsys, battlerId);
|
|
Party *party2 = BattleSystem_GetParty(bsys, BattleSystem_GetBattlerIdPartner(bsys, battlerId));
|
|
|
|
BattleSystem_GetOpponentData(bsys, battlerId);
|
|
|
|
for (i = 0; i < Party_GetCount(party1); i++) {
|
|
mon = Party_GetMonByIndex(party1, i);
|
|
if (GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0) != SPECIES_NONE
|
|
&& GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0) != SPECIES_EGG) {
|
|
partyHp += GetMonData(mon, MON_DATA_HP, 0);
|
|
}
|
|
}
|
|
|
|
if ((battleType == 75 || battleType == 74) && BattleSystem_GetFieldSide(bsys, battlerId) == 0 && ov12_0223AB0C(bsys, battlerId) == 2) {
|
|
|
|
} else {
|
|
for (i = 0; i < Party_GetCount(party2); i++) {
|
|
mon = Party_GetMonByIndex(party2, i);
|
|
if (GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0) != SPECIES_NONE
|
|
&& GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0) != SPECIES_EGG) {
|
|
partyHp += GetMonData(mon, MON_DATA_HP, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (partyHp == 0) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
} else {
|
|
Party *party = BattleSystem_GetParty(bsys, battlerId);
|
|
|
|
BattleSystem_GetOpponentData(bsys, battlerId);
|
|
|
|
for (i = 0; i < Party_GetCount(party); i++) {
|
|
mon = Party_GetMonByIndex(party, i);
|
|
if (GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0) != SPECIES_NONE
|
|
&& GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0) != SPECIES_EGG) {
|
|
partyHp += GetMonData(mon, MON_DATA_HP, 0);
|
|
}
|
|
}
|
|
|
|
if (partyHp == 0) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_BoostRandomStatBy2(BattleSystem *bsys, BattleContext *ctx) {
|
|
int i, cnt;
|
|
int statChanges[8];
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
cnt = 0;
|
|
for (i = 1; i < 8; i++) {
|
|
if (ctx->battleMons[ctx->battlerIdTarget].statChanges[i] < 12) {
|
|
statChanges[cnt++] = i - 1;
|
|
}
|
|
}
|
|
|
|
if (cnt) {
|
|
ctx->unk_2170 = 39 + statChanges[BattleSystem_Random(bsys) % cnt];
|
|
ctx->unk_2170 |= (1 << 31);
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_RemoveItem(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
ctx->recycleItem[battlerId] = ctx->battleMons[battlerId].item;
|
|
|
|
ctx->battleMons[battlerId].item = 0;
|
|
|
|
CopyBattleMonToPartyMon(bsys, ctx, battlerId);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryRecycle(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (ctx->recycleItem[ctx->battlerIdAttacker]) {
|
|
ctx->itemTemp = ctx->recycleItem[ctx->battlerIdAttacker];
|
|
ctx->recycleItem[ctx->battlerIdAttacker] = 0;
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckItemHoldEffectOnHit(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
if (!CheckItemEffectOnHit(bsys, ctx, &ctx->tempData)) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PrintBattleResultMessage(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
BattleController_EmitPrintResultMessage(bsys);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PrintEscapeMessage(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
BattleController_EmitRunAwayMessage(bsys, ctx);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PrintForfeitMessage(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
BattleController_EmitForefitMessage(bsys);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckHoldOnWith1HP(BattleSystem *bsys, BattleContext *ctx) {
|
|
BOOL flag = FALSE;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
int itemEffect = GetBattlerHeldItemEffect(ctx, battlerId);
|
|
int activationChance = GetHeldItemModifier(ctx, battlerId, 0);
|
|
|
|
if (itemEffect == HOLD_EFFECT_MAYBE_ENDURE && (BattleSystem_Random(bsys) % 100) < activationChance) {
|
|
flag = TRUE;
|
|
}
|
|
if (itemEffect == HOLD_EFFECT_ENDURE && ctx->battleMons[battlerId].hp == ctx->battleMons[battlerId].maxHp) {
|
|
flag = TRUE;
|
|
}
|
|
|
|
if (flag && (ctx->battleMons[battlerId].hp + ctx->hpCalc) <= 0) {
|
|
ctx->hpCalc = (ctx->battleMons[battlerId].hp - 1) * -1;
|
|
ctx->moveStatusFlag |= 256;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_TryRestoreStatusOnSwitch(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
if (ctx->battleMons[battlerId].hp && ctx->selectedMonIndex[battlerId] != 6) {
|
|
Pokemon *mon = BattleSystem_GetPartyMon(bsys, battlerId, ctx->selectedMonIndex[battlerId]);
|
|
int ability = GetMonData(mon, MON_DATA_ABILITY, NULL);
|
|
int status = GetMonData(mon, MON_DATA_STATUS, NULL);
|
|
if (ctx->battleMons[battlerId].ability != ABILITY_NATURAL_CURE && !CheckStatusHealSwitch(ctx, ability, status)) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckSubstitute(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
if (ctx->battleMons[battlerId].status2 & (1 << 24) || ctx->selfTurnData[battlerId].unk14 & 8) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckIgnoreWeather(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (!CheckAbilityActive(bsys, ctx, CHECK_ABILITY_ALL_HP, 0, ABILITY_CLOUD_NINE) && !CheckAbilityActive(bsys, ctx, CHECK_ABILITY_ALL_HP, 0, ABILITY_AIR_LOCK)) {
|
|
|
|
} else {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_SetRandomTarget(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
ctx->battlerIdTarget = Battler_GetRandomOpposingBattlerId(bsys, ctx, battlerId);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckItemHoldEffectOnUTurn(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (!CheckItemEffectOnUTurn(bsys, ctx, &ctx->tempData)) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_RefreshSprite(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
BattleController_EmitSwapToSubstituteSprite(bsys, ctx, battlerId);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PlayMoveHitSound(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
BattleController_EmitPlayMoveSE(bsys, ctx, battlerId);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_PlayBGM(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int song = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
BattleController_EmitPlaySong(bsys, battlerId, song);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckSafariGameDone(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (!(BattleSystem_GetPartySize(bsys, 0) != 6 || PCStorage_FindFirstBoxWithEmptySlot(bsys->storage) != 18)) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_WaitTime(BattleSystem *bsys, BattleContext *ctx) {
|
|
int tSpeed;
|
|
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int wait = BattleScriptReadWord(ctx);
|
|
|
|
if ((bsys->battleType & BATTLE_TYPE_LINK) && !(bsys->battleSpecial & BATTLE_SPECIAL_RECORDING)) {
|
|
tSpeed = 2;
|
|
} else {
|
|
tSpeed = 1;
|
|
}
|
|
|
|
if (wait > ctx->unk_F0) {
|
|
BattleScriptIncrementPointer(ctx, -2);
|
|
ctx->unk_F0 += tSpeed;
|
|
} else {
|
|
ctx->unk_F0 = 0;
|
|
}
|
|
|
|
ctx->battleContinueFlag = TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_CheckCurMoveIsType(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int type = BattleScriptReadWord(ctx);
|
|
int adrs = BattleScriptReadWord(ctx);
|
|
|
|
if (ctx->trainerAIData.moveData[ctx->moveNoCur].type == type) {
|
|
BattleScriptIncrementPointer(ctx, adrs);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_LoadArchivedMonData(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int species = BattleScriptReadWord(ctx);
|
|
int form = BattleScriptReadWord(ctx);
|
|
int stat = BattleScriptReadWord(ctx);
|
|
|
|
int *formPtr = BattleScriptGetVarPointer(bsys, ctx, form);
|
|
|
|
ctx->calcTemp = GetMonBaseStat_HandleAlternateForm(species, *formPtr, stat);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_RefreshMonData(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
BattleSystem_ReloadMonData(bsys, ctx, battlerId, ctx->selectedMonIndex[battlerId]);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_222(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int side = BattleScriptReadWord(ctx);
|
|
int msgIndex = BattleScriptReadWord(ctx);
|
|
|
|
int battlerId = GetBattlerIDBySide(bsys, ctx, side);
|
|
|
|
if (TrainerMessageWithIdPairExists(BattleSystem_GetTrainerIndex(bsys, battlerId), msgIndex, HEAP_ID_BATTLE)) {
|
|
ctx->msgTemp = msgIndex;
|
|
} else {
|
|
ctx->msgTemp = 0;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_223(BattleSystem *bsys, BattleContext *ctx) {
|
|
BattleScriptIncrementPointer(ctx, 1);
|
|
|
|
int a2 = BattleScriptReadWord(ctx);
|
|
|
|
ov12_022645C8(bsys, ctx, a2 & 1);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BtlCmd_EndScript(BattleSystem *bsys, BattleContext *ctx) {
|
|
ctx->battleContinueFlag = TRUE;
|
|
|
|
return ov12_0224EC74(ctx);
|
|
}
|
|
|
|
int BattleScriptReadWord(BattleContext *ctx) {
|
|
int data = ctx->battleScriptBuffer[ctx->scriptSeqNo];
|
|
|
|
ctx->scriptSeqNo++;
|
|
|
|
return data;
|
|
}
|
|
|
|
static void BattleScriptIncrementPointer(BattleContext *ctx, int adrs) {
|
|
ctx->scriptSeqNo += adrs;
|
|
}
|
|
|
|
static void BattleScriptJump(BattleContext *ctx, NarcId narcId, int adrs) {
|
|
ReadBattleScriptFromNarc(ctx, narcId, adrs);
|
|
}
|
|
|
|
static void BattleScriptGotoSubscript(BattleContext *ctx, NarcId narcId, int adrs) {
|
|
ov12_0224EBDC(ctx, narcId, adrs);
|
|
}
|
|
|
|
static void *BattleScriptGetVarPointer(BattleSystem *bsys, BattleContext *ctx, int var) {
|
|
switch (var) {
|
|
case BSCRIPT_VAR_BATTLE_TYPE:
|
|
return &bsys->battleType;
|
|
case BSCRIPT_VAR_CRITICAL_BOOSTS:
|
|
return &ctx->criticalCnt;
|
|
case BSCRIPT_VAR_SIDE_EFFECT_FLAGS_DIRECT:
|
|
return &ctx->unk_2170;
|
|
case BSCRIPT_VAR_SIDE_EFFECT_FLAGS_INDIRECT:
|
|
return &ctx->unk_2174;
|
|
case BSCRIPT_VAR_SIDE_EFFECT_FLAGS_ABILITY:
|
|
return &ctx->unk_2178;
|
|
case BSCRIPT_VAR_SIDE_EFFECT_TYPE:
|
|
return &ctx->statChangeType;
|
|
case BSCRIPT_VAR_BATTLE_STATUS:
|
|
return &ctx->battleStatus;
|
|
case BSCRIPT_VAR_FIELD_CONDITION:
|
|
return &ctx->fieldCondition;
|
|
case BSCRIPT_VAR_POWER_MULTI:
|
|
return &ctx->unk_2158;
|
|
case BSCRIPT_VAR_CALC_TEMP:
|
|
return &ctx->calcTemp;
|
|
case BSCRIPT_VAR_MOVE_STATUS_FLAGS:
|
|
return &ctx->moveStatusFlag;
|
|
case BSCRIPT_VAR_SIDE_CONDITION_ATTACKER:
|
|
return &ctx->fieldSideConditionFlags[BattleSystem_GetFieldSide(bsys, ctx->battlerIdAttacker)];
|
|
case BSCRIPT_VAR_SIDE_CONDITION_TARGET:
|
|
return &ctx->fieldSideConditionFlags[BattleSystem_GetFieldSide(bsys, ctx->battlerIdTarget)];
|
|
case BSCRIPT_VAR_SIDE_CONDITION_STAT_CHANGE:
|
|
return &ctx->fieldSideConditionFlags[BattleSystem_GetFieldSide(bsys, ctx->battlerIdStatChange)];
|
|
case BSCRIPT_VAR_DAMAGE:
|
|
return &ctx->damage;
|
|
case BSCRIPT_VAR_BATTLER_ATTACKER:
|
|
return &ctx->battlerIdAttacker;
|
|
case BSCRIPT_VAR_BATTLER_TARGET:
|
|
return &ctx->battlerIdTarget;
|
|
case BSCRIPT_VAR_BATTLER_STAT_CHANGE:
|
|
return &ctx->battlerIdStatChange;
|
|
case BSCRIPT_VAR_BATTLER_FAINTED:
|
|
return &ctx->battlerIdFainted;
|
|
case BSCRIPT_VAR_BATTLER_SWITCH:
|
|
return &ctx->battlerIdSwitch;
|
|
case BSCRIPT_VAR_MSG_BATTLER_TEMP:
|
|
return &ctx->battlerIdTemp;
|
|
case BSCRIPT_VAR_ATTACKER_STORED_DAMAGE:
|
|
return &ctx->unk_30E4[ctx->battlerIdAttacker];
|
|
case BSCRIPT_VAR_MESSAGE:
|
|
return &ctx->msgTemp;
|
|
case BSCRIPT_VAR_PAY_DAY_COUNT:
|
|
return &ctx->unk_14C;
|
|
case BSCRIPT_VAR_MOVE_NO_CUR:
|
|
return &ctx->moveNoCur;
|
|
case BSCRIPT_VAR_TOTAL_TURNS:
|
|
return &ctx->totalTurns;
|
|
case BSCRIPT_VAR_MSG_ATTACKER:
|
|
return &ctx->battlerIdLeechSeedRecv;
|
|
case BSCRIPT_VAR_MSG_DEFENDER:
|
|
return &ctx->battlerIdLeechSeeded;
|
|
case BSCRIPT_VAR_MOVE_NO_TEMP:
|
|
return &ctx->moveNoTemp;
|
|
case BSCRIPT_VAR_LAST_BATTLER_ID:
|
|
return &ctx->unk_98;
|
|
case BSCRIPT_VAR_MOVE_POWER:
|
|
return &ctx->movePower;
|
|
case BSCRIPT_VAR_AFTER_MOVE_MESSAGE_TYPE:
|
|
return &ctx->unk_38;
|
|
case BSCRIPT_VAR_HP_CALC:
|
|
return &ctx->hpCalc;
|
|
case BSCRIPT_VAR_BATTLE_OUTCOME:
|
|
return &bsys->battleOutcomeFlag;
|
|
case BSCRIPT_VAR_SIDE_EFFECT_PARAM:
|
|
return &ctx->statChangeParam;
|
|
case BSCRIPT_VAR_MSG_MOVE_TEMP:
|
|
return &ctx->moveTemp;
|
|
case BSCRIPT_VAR_MSG_ITEM_TEMP:
|
|
return &ctx->itemTemp;
|
|
case BSCRIPT_VAR_MSG_ABILITY_TEMP:
|
|
return &ctx->abilityTemp;
|
|
case BSCRIPT_VAR_WEATHER_TURNS:
|
|
return &ctx->fieldConditionData.weatherTurns;
|
|
case BSCRIPT_VAR_BATTLER_SPEED_TEMP:
|
|
return &ctx->unk_3104;
|
|
case BSCRIPT_VAR_MULTI_HIT_LOOP:
|
|
return &ctx->unk_2180;
|
|
case BSCRIPT_VAR_PHYSICAL_DAMAGE:
|
|
return &ctx->turnData[ctx->battlerIdAttacker].battlerBitPhysicalDamage;
|
|
case BSCRIPT_VAR_SPECIAL_DAMAGE:
|
|
return &ctx->turnData[ctx->battlerIdAttacker].battlerBitSpecialDamage;
|
|
case BSCRIPT_VAR_TEMP_DATA:
|
|
return &ctx->tempData;
|
|
case BSCRIPT_VAR_CRIT_MULTIPLIER:
|
|
return &ctx->criticalMultiplier;
|
|
case BSCRIPT_VAR_ATTACKER_LAST_DAMAGE_TAKEN:
|
|
return &ctx->turnData[ctx->battlerIdAttacker].unk34;
|
|
case BSCRIPT_VAR_DEFENDER_LAST_DAMAGE_TAKEN:
|
|
return &ctx->turnData[ctx->battlerIdTarget].unk34;
|
|
case BSCRIPT_VAR_ATTACKER_SELF_TURN_STATUS_FLAGS:
|
|
return &ctx->selfTurnData[ctx->battlerIdAttacker].unk14;
|
|
case BSCRIPT_VAR_DEFENDER_SELF_TURN_STATUS_FLAGS:
|
|
return &ctx->selfTurnData[ctx->battlerIdTarget].unk14;
|
|
case BSCRIPT_VAR_SIDE_EFFECT_MON_SELF_TURN_STATUS_FLAGS:
|
|
return &ctx->selfTurnData[ctx->battlerIdStatChange].unk14;
|
|
case BSCRIPT_VAR_FLING_DATA:
|
|
return &ctx->flingData;
|
|
case BSCRIPT_VAR_FLING_SCRIPT:
|
|
return &ctx->flingScript;
|
|
case BSCRIPT_VAR_BATTLE_SYS_STATUS:
|
|
return &bsys->battleSpecial;
|
|
case BSCRIPT_VAR_ATTACKER_LOCKED_MOVE:
|
|
return &ctx->moveNoLockedInto[ctx->battlerIdAttacker];
|
|
case BSCRIPT_VAR_HIT_DAMAGE:
|
|
return &ctx->hitDamage;
|
|
case BSCRIPT_VAR_SAFARI_BALL_CNT:
|
|
return &bsys->safariBallCnt;
|
|
case BSCRIPT_VAR_SWITCHED_MON_TEMP:
|
|
return &ctx->battlerIdSwitchTemp;
|
|
case BSCRIPT_VAR_MOVE_TYPE:
|
|
return &ctx->moveType;
|
|
case BSCRIPT_VAR_MOVE_EFFECT_CHANCE:
|
|
return &ctx->unk_2164;
|
|
case BSCRIPT_VAR_REGULATION_FLAG:
|
|
return &bsys->unk241C;
|
|
case BSCRIPT_VAR_BATTLE_STATUS_2:
|
|
return &ctx->battleStatus2;
|
|
case BSCRIPT_VAR_TURN_ORDER_COUNTER:
|
|
return &ctx->executionIndex;
|
|
case BSCRIPT_VAR_MAX_BATTLERS:
|
|
return &bsys->maxBattlers;
|
|
case BSCRIPT_VAR_BATTLER_ATTACKER_TEMP:
|
|
return &ctx->battlerIdAttackerTemp;
|
|
case BSCRIPT_VAR_BATTLER_TARGET_TEMP:
|
|
return &ctx->battlerIdTargetTemp;
|
|
case BSCRIPT_VAR_PHYSICAL_DAMAGE_TAKEN:
|
|
return &ctx->selfTurnData[ctx->battlerIdTarget].physicalDamage;
|
|
case BSCRIPT_VAR_MSG_BATTLER_TEMP_ASSURANCE_DAMAGE_MASK:
|
|
return &ctx->turnData[ctx->battlerIdTemp].unk3C;
|
|
case BSCRIPT_VAR_DEFENDER_ASSURANCE_DAMAGE_MASK:
|
|
return &ctx->turnData[ctx->battlerIdTarget].unk3C;
|
|
case BSCRIPT_VAR_ATTACKER_SHELL_BELL_DAMAGE_DEALT:
|
|
return &ctx->selfTurnData[ctx->battlerIdAttacker].shellBellDamage;
|
|
case BSCRIPT_VAR_WAITING_BATTLERS:
|
|
return &ctx->battlersOnField;
|
|
case BSCRIPT_VAR_70:
|
|
return &bsys->unk2478;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
enum {
|
|
STATE_GET_EXP_START = 0,
|
|
STATE_GET_EXP_WAIT_MESSAGE_PRINT,
|
|
STATE_GET_EXP_WAIT_MESSAGE_DELAY,
|
|
STATE_GET_EXP_GAUGE,
|
|
STATE_GET_EXP_WAIT_GAUGE,
|
|
STATE_GET_EXP_CHECK_LEVEL_UP,
|
|
STATE_GET_EXP_WAIT_LEVEL_UP_EFFECT,
|
|
STATE_GET_EXP_WAIT_LEVEL_UP_MESSAGE_PRINT,
|
|
STATE_GET_EXP_LEVEL_UP_SUMMARY_LOAD_ICON,
|
|
STATE_GET_EXP_LEVEL_UP_SUMMARY_INIT,
|
|
STATE_GET_EXP_LEVEL_UP_SUMMARY_PRINT_DIFF,
|
|
STATE_GET_EXP_LEVEL_UP_SUMMARY_PRINT_DIFF_WAIT,
|
|
STATE_GET_EXP_LEVEL_UP_SUMMARY_PRINT_TRUE,
|
|
STATE_GET_EXP_LEVEL_UP_SUMMARY_PRINT_TRUE_WAIT,
|
|
STATE_GET_EXP_LEVEL_UP_CLEAR,
|
|
STATE_GET_EXP_CHECK_LEARN_MOVE,
|
|
STATE_GET_EXP_WANTS_TO_LEARN_MOVE_PRINT,
|
|
STATE_GET_EXP_WANTS_TO_LEARN_MOVE_PRINT_WAIT,
|
|
STATE_GET_EXP_CANT_LEARN_MORE_MOVES_PRINT,
|
|
STATE_GET_EXP_CANT_LEARN_MORE_MOVES_PRINT_WAIT,
|
|
STATE_GET_EXP_MAKE_IT_FORGET_PROMPT,
|
|
STATE_GET_EXP_MAKE_IT_FORGET_ANSWER,
|
|
STATE_GET_EXP_MAKE_IT_FORGET_WAIT,
|
|
STATE_GET_EXP_MAKE_IT_FORGET_INPUT_TAKEN,
|
|
STATE_GET_EXP_ONE_TWO_POOF,
|
|
STATE_GET_EXP_ONE_TWO_POOF_WAIT,
|
|
STATE_GET_EXP_FORGOT_HOW_TO_USE,
|
|
STATE_GET_EXP_FORGOT_HOW_TO_USE_WAIT,
|
|
STATE_GET_EXP_AND_DOTDOTDOT,
|
|
STATE_GET_EXP_AND_DOTDOTDOT_WAIT,
|
|
STATE_GET_EXP_LEARNED_MOVE,
|
|
STATE_GET_EXP_MAKE_IT_FORGET_CANCELLED,
|
|
STATE_GET_EXP_MAKE_IT_FORGET_CANCELLED_WAIT,
|
|
STATE_GET_EXP_GIVE_UP_LEARNING_PROMPT,
|
|
STATE_GET_EXP_GIVE_UP_LEARNING_ANSWER,
|
|
STATE_GET_EXP_GIVE_UP_LEARNING_WAIT,
|
|
STATE_GET_EXP_LEARNED_MOVE_WAIT,
|
|
STATE_GET_EXP_CHECK_DONE,
|
|
STATE_GET_EXP_DONE,
|
|
};
|
|
|
|
// Note: these structs are needed to match *only as long as the data is in the assembly*
|
|
// when the data gets decompiled, they should be embeded in the function as arrays
|
|
typedef struct TempStatsStruct {
|
|
u32 stats[6];
|
|
} TempStatsStruct;
|
|
|
|
extern TempStatsStruct ov12_0226C354;
|
|
extern TempStatsStruct ov12_0226C36C;
|
|
extern TempStatsStruct ov12_0226C384;
|
|
extern TempStatsStruct ov12_0226C33C;
|
|
|
|
static void Task_GetExp(SysTask *task, void *inData) {
|
|
int i;
|
|
int slot;
|
|
GetterWork *data = inData;
|
|
Pokemon *mon;
|
|
BattleMessage msg;
|
|
int side;
|
|
int expBattler;
|
|
MsgData *msgLoader;
|
|
u32 battleType;
|
|
u16 item;
|
|
int itemEffect;
|
|
|
|
msgLoader = BattleSystem_GetMessageData(data->bsys);
|
|
battleType = BattleSystem_GetBattleType(data->bsys);
|
|
side = (data->ctx->battlerIdFainted >> 1) & 1; // Get side of fainted mon (left or right)
|
|
expBattler = 0;
|
|
|
|
// Figure out which mon we're working on
|
|
for (slot = data->unk30[6]; slot < BattleSystem_GetPartySize(data->bsys, expBattler); slot++) {
|
|
mon = BattleSystem_GetPartyMon(data->bsys, expBattler, slot);
|
|
item = GetMonData(mon, MON_DATA_HELD_ITEM, NULL);
|
|
itemEffect = GetItemAttr(item, ITEM_VAR_HOLD_EFFECT, HEAP_ID_BATTLE);
|
|
|
|
if (itemEffect == HOLD_EFFECT_EXP_SHARE || (data->ctx->unk_A4[side] & MaskOfFlagNo(slot))) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (slot == BattleSystem_GetPartySize(data->bsys, expBattler)) {
|
|
data->state = STATE_GET_EXP_DONE;
|
|
} else if ((battleType & BATTLE_TYPE_DOUBLES)
|
|
&& !(battleType & BATTLE_TYPE_AI)
|
|
&& data->ctx->selectedMonIndex[BATTLER_PLAYER2] == slot) {
|
|
expBattler = 2;
|
|
}
|
|
|
|
switch (data->state) {
|
|
case STATE_GET_EXP_START:
|
|
item = GetMonData(mon, MON_DATA_HELD_ITEM, NULL);
|
|
itemEffect = GetItemAttr(item, ITEM_VAR_HOLD_EFFECT, HEAP_ID_BATTLE);
|
|
|
|
// Declare victory if all wild mons have been defeated
|
|
if (!(battleType & BATTLE_TYPE_TRAINER)
|
|
&& data->ctx->battleMons[BATTLER_ENEMY].hp
|
|
+ data->ctx->battleMons[BATTLER_ENEMY2].hp
|
|
== 0
|
|
&& GetMonData(mon, MON_DATA_HP, NULL)
|
|
&& !data->ctx->unk_3144) {
|
|
PlayBGM(SEQ_GS_WIN2);
|
|
data->ctx->unk_3144 = TRUE;
|
|
BattleSystem_SetCriticalHpMusicFlag(data->bsys, CRITICAL_MUSIC_OFF);
|
|
}
|
|
|
|
u32 totalExp = 0;
|
|
msg.id = msg_0197_00001; // "{0} gained {1} Exp. Points!"
|
|
|
|
if (GetMonData(mon, MON_DATA_HP, NULL) && GetMonData(mon, MON_DATA_LEVEL, NULL) != 100) {
|
|
if (data->ctx->unk_A4[side] & MaskOfFlagNo(slot)) {
|
|
totalExp = data->ctx->gainedExp;
|
|
}
|
|
|
|
if (itemEffect == HOLD_EFFECT_EXP_SHARE) {
|
|
totalExp += data->ctx->partyGainedExp;
|
|
}
|
|
|
|
if (itemEffect == HOLD_EFFECT_EXP_UP) {
|
|
totalExp = totalExp * 150 / 100;
|
|
}
|
|
|
|
if (battleType & BATTLE_TYPE_TRAINER) {
|
|
totalExp = totalExp * 150 / 100;
|
|
}
|
|
|
|
if (!ov12_022568B0(data->bsys, mon)) {
|
|
if (GetMonData(mon, MON_DATA_GAME_LANGUAGE, NULL) != gGameLanguage) {
|
|
totalExp = totalExp * 170 / 100;
|
|
} else {
|
|
totalExp = totalExp * 150 / 100;
|
|
}
|
|
|
|
msg.id = msg_0197_00002; // "{0} gained a boosted {1} Exp. Points!"
|
|
}
|
|
|
|
u32 newExp = GetMonData(mon, MON_DATA_EXPERIENCE, NULL);
|
|
data->unk30[3] = newExp - GetMonBaseExperienceAtCurrentLevel(mon);
|
|
newExp += totalExp;
|
|
|
|
if (slot == data->ctx->selectedMonIndex[expBattler]) {
|
|
data->ctx->battleMons[expBattler].exp = newExp;
|
|
}
|
|
|
|
SetMonData(mon, MON_DATA_EXPERIENCE, &newExp);
|
|
ov12_022463E8(BattleSystem_GetParty(data->bsys, expBattler),
|
|
slot,
|
|
data->ctx->battleMons[data->ctx->battlerIdFainted].species,
|
|
data->ctx->battleMons[data->ctx->battlerIdFainted].form);
|
|
}
|
|
|
|
if (totalExp) {
|
|
msg.tag = TAG_NICKNAME_NUM;
|
|
msg.param[0] = expBattler | (slot << 8);
|
|
msg.param[1] = totalExp;
|
|
data->unk30[0] = BattleSystem_PrintBattleMessage(data->bsys, msgLoader, &msg, BattleSystem_GetTextFrameDelay(data->bsys));
|
|
data->unk30[1] = 7;
|
|
data->state++;
|
|
} else {
|
|
data->state = STATE_GET_EXP_CHECK_DONE;
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_GET_EXP_WAIT_MESSAGE_PRINT:
|
|
if (!TextPrinterCheckActive(data->unk30[0])) {
|
|
data->state++;
|
|
}
|
|
break;
|
|
|
|
case STATE_GET_EXP_WAIT_MESSAGE_DELAY:
|
|
if (--data->unk30[1] == 0) {
|
|
data->state++;
|
|
}
|
|
break;
|
|
|
|
case STATE_GET_EXP_GAUGE:
|
|
// Only animate the gauge for an active battler
|
|
if (slot == data->ctx->selectedMonIndex[expBattler]) {
|
|
ov12_02263564(data->bsys, data->ctx, expBattler, data->unk30[3]);
|
|
data->unk30[3] = 0;
|
|
data->state++;
|
|
} else {
|
|
data->state = STATE_GET_EXP_CHECK_LEVEL_UP;
|
|
}
|
|
break;
|
|
|
|
case STATE_GET_EXP_WAIT_GAUGE:
|
|
if (Link_QueueNotEmpty(data->ctx)) {
|
|
data->state++;
|
|
}
|
|
break;
|
|
|
|
case STATE_GET_EXP_CHECK_LEVEL_UP:
|
|
if (Pokemon_TryLevelUp(mon)) {
|
|
// Only play the special level-up animation for an active battler
|
|
if (data->ctx->selectedMonIndex[expBattler] == slot) {
|
|
BattleController_EmitSetStatus2Effect(data->bsys, data->ctx, expBattler, 8);
|
|
ov12_0226399C(data->bsys, expBattler);
|
|
}
|
|
|
|
data->state = STATE_GET_EXP_WAIT_LEVEL_UP_EFFECT;
|
|
} else {
|
|
data->state = STATE_GET_EXP_CHECK_DONE;
|
|
}
|
|
break;
|
|
|
|
case STATE_GET_EXP_WAIT_LEVEL_UP_EFFECT:
|
|
if (Link_QueueNotEmpty(data->ctx)) {
|
|
TempStatsStruct stats = ov12_0226C354;
|
|
int level = GetMonData(mon, MON_DATA_LEVEL, NULL);
|
|
// Cache the stats from the previous level for later
|
|
data->ctx->prevLevelStats = AllocFromHeap(HEAP_ID_BATTLE, sizeof(PokemonStats));
|
|
PokemonStats *oldStats = data->ctx->prevLevelStats;
|
|
for (i = 0; i < NUM_STATS; i++) {
|
|
oldStats->stats[i] = GetMonData(mon, stats.stats[i], NULL);
|
|
}
|
|
|
|
MonApplyFriendshipMod(mon, MON_MOOD_MODIFIER_LEVEL_UP_IN_BATTLE, BattleSystem_GetLocation(data->bsys));
|
|
ApplyMonMoodModifier(mon, 0);
|
|
CalcMonStats(mon);
|
|
|
|
if (data->ctx->selectedMonIndex[expBattler] == slot) {
|
|
BattleSystem_ReloadMonData(data->bsys, data->ctx, expBattler, data->ctx->selectedMonIndex[expBattler]);
|
|
}
|
|
|
|
data->ctx->levelUpMons |= MaskOfFlagNo(slot);
|
|
ov12_02263A1C(data->bsys, data->ctx, expBattler);
|
|
|
|
msg.id = msg_0197_00003; // "{0} grew to Lv. {1}!"
|
|
msg.tag = TAG_NICKNAME_NUM;
|
|
msg.param[0] = expBattler | (slot << 8);
|
|
msg.param[1] = level;
|
|
data->unk30[0] = BattleSystem_PrintBattleMessage(data->bsys, msgLoader, &msg, BattleSystem_GetTextFrameDelay(data->bsys));
|
|
data->state = STATE_GET_EXP_WAIT_LEVEL_UP_MESSAGE_PRINT;
|
|
}
|
|
break;
|
|
|
|
case STATE_GET_EXP_WAIT_LEVEL_UP_MESSAGE_PRINT:
|
|
if (TextPrinterCheckActive(data->unk30[0]) == 0) {
|
|
data->state = STATE_GET_EXP_LEVEL_UP_SUMMARY_LOAD_ICON;
|
|
data->unk30[2] = 0;
|
|
}
|
|
break;
|
|
|
|
case STATE_GET_EXP_LEVEL_UP_SUMMARY_LOAD_ICON:
|
|
// Load the Pokemon's Party icon if they are not the active battler
|
|
if (data->ctx->selectedMonIndex[expBattler] != slot) {
|
|
ov12_02248228(data->bsys, data, mon);
|
|
}
|
|
|
|
data->state = STATE_GET_EXP_LEVEL_UP_SUMMARY_INIT;
|
|
break;
|
|
|
|
case STATE_GET_EXP_LEVEL_UP_SUMMARY_INIT: {
|
|
BgConfig *bgConfig = BattleSystem_GetBgConfig(data->bsys);
|
|
Window *window = BattleSystem_GetWindow(data->bsys, 1);
|
|
PaletteData *palette = BattleSystem_GetPaletteData(data->bsys);
|
|
|
|
G2_SetBG0Priority(2);
|
|
SetBgPriority(GF_BG_LYR_MAIN_1, 1);
|
|
SetBgPriority(GF_BG_LYR_MAIN_2, 0);
|
|
|
|
ov12_0223C224(data->bsys, 1);
|
|
|
|
sub_0200E398(bgConfig, 2, 1, 0, HEAP_ID_BATTLE);
|
|
PaletteData_LoadNarc(palette, NARC_a_0_3_8, sub_0200E3D8(), HEAP_ID_BATTLE, PLTTBUF_MAIN_BG, 0x20, 8 * 0x10);
|
|
AddWindowParameterized(bgConfig, window, GF_BG_LYR_MAIN_2, 0x11, 0x7, 14, 12, 11, 9 + 1);
|
|
FillWindowPixelBuffer(window, 0xFF);
|
|
DrawFrameAndWindow1(window, FALSE, 1, 8);
|
|
|
|
data->state = STATE_GET_EXP_LEVEL_UP_SUMMARY_PRINT_DIFF;
|
|
break;
|
|
}
|
|
case STATE_GET_EXP_LEVEL_UP_SUMMARY_PRINT_DIFF: {
|
|
TempStatsStruct stats = ov12_0226C36C;
|
|
TempStatsStruct monData = ov12_0226C384;
|
|
|
|
Window *window = BattleSystem_GetWindow(data->bsys, 1);
|
|
PokemonStats *oldStats = data->ctx->prevLevelStats;
|
|
|
|
for (i = 0; i < NUM_STATS; i++) {
|
|
msg.id = msg_0197_00947; // stat name
|
|
msg.tag = TAG_STAT;
|
|
msg.param[0] = stats.stats[i];
|
|
|
|
ov12_0223C4E8(data->bsys, window, msgLoader, &msg, 0, 16 * i, 0, 0, 0);
|
|
|
|
msg.id = msg_0197_00948; // "+{0}"
|
|
msg.tag = TAG_NUMBERS;
|
|
msg.param[0] = GetMonData(mon, monData.stats[i], NULL) - oldStats->stats[i];
|
|
msg.numDigits = 2;
|
|
|
|
ov12_0223C4E8(data->bsys, window, msgLoader, &msg, 80, 16 * i, 0, 0, 0);
|
|
}
|
|
|
|
data->state = STATE_GET_EXP_LEVEL_UP_SUMMARY_PRINT_DIFF_WAIT;
|
|
break;
|
|
}
|
|
case STATE_GET_EXP_LEVEL_UP_SUMMARY_PRINT_TRUE: {
|
|
TempStatsStruct monData = ov12_0226C33C;
|
|
Window *window = BattleSystem_GetWindow(data->bsys, 1);
|
|
|
|
FillWindowPixelRect(window, 0xF, 80, 0, 36, 96); // clear out the diff section (keep the printed stat names)
|
|
|
|
for (i = 0; i < NUM_STATS; i++) {
|
|
msg.id = msg_0197_00949; // just a number
|
|
msg.tag = TAG_NUMBERS;
|
|
msg.param[0] = GetMonData(mon, monData.stats[i], NULL);
|
|
msg.numDigits = 3;
|
|
|
|
ov12_0223C4E8(data->bsys, window, msgLoader, &msg, 72, 16 * i, 0x2, 36, 0);
|
|
}
|
|
|
|
data->state = STATE_GET_EXP_LEVEL_UP_SUMMARY_PRINT_TRUE_WAIT;
|
|
break;
|
|
}
|
|
case STATE_GET_EXP_LEVEL_UP_SUMMARY_PRINT_DIFF_WAIT:
|
|
case STATE_GET_EXP_LEVEL_UP_SUMMARY_PRINT_TRUE_WAIT:
|
|
if ((gSystem.newKeys & (PAD_BUTTON_A | PAD_BUTTON_B | PAD_BUTTON_X | PAD_BUTTON_Y)) || System_GetTouchNew()) {
|
|
PlaySE(SEQ_SE_DP_SELECT);
|
|
data->state++;
|
|
}
|
|
break;
|
|
|
|
case STATE_GET_EXP_LEVEL_UP_CLEAR: {
|
|
Window *window = BattleSystem_GetWindow(data->bsys, 1);
|
|
|
|
sub_0200E5D4(window, 0);
|
|
RemoveWindow(window);
|
|
|
|
G2_SetBG0Priority(1);
|
|
SetBgPriority(GF_BG_LYR_MAIN_1, 0);
|
|
SetBgPriority(GF_BG_LYR_MAIN_2, 1);
|
|
|
|
ov12_0223C224(data->bsys, 0);
|
|
|
|
if (data->ctx->selectedMonIndex[expBattler] != slot) {
|
|
ov12_022484D4(data->bsys, data);
|
|
}
|
|
|
|
FreeToHeap(data->ctx->prevLevelStats);
|
|
data->state = STATE_GET_EXP_CHECK_LEARN_MOVE;
|
|
break;
|
|
}
|
|
|
|
case STATE_GET_EXP_CHECK_LEARN_MOVE: {
|
|
u16 move;
|
|
BgConfig *bgConfig = BattleSystem_GetBgConfig(data->bsys); // unused, but must be kept to match
|
|
|
|
switch (MonTryLearnMoveOnLevelUp(mon, &data->unk30[2], &move)) {
|
|
case 0:
|
|
data->state = STATE_GET_EXP_GAUGE;
|
|
break;
|
|
case 0xFFFE:
|
|
break;
|
|
case 0xFFFF:
|
|
data->unk30[4] = move;
|
|
data->state = STATE_GET_EXP_WANTS_TO_LEARN_MOVE_PRINT;
|
|
break;
|
|
default:
|
|
if (data->ctx->selectedMonIndex[expBattler] == slot) {
|
|
BattleSystem_ReloadMonData(data->bsys, data->ctx, expBattler, data->ctx->selectedMonIndex[expBattler]);
|
|
}
|
|
|
|
msg.id = msg_0197_00004; // "{0} learned {1}!"
|
|
msg.tag = TAG_NICKNAME_MOVE;
|
|
msg.param[0] = expBattler | (slot << 8);
|
|
msg.param[1] = move;
|
|
data->unk30[0] = BattleSystem_PrintBattleMessage(data->bsys, msgLoader, &msg, BattleSystem_GetTextFrameDelay(data->bsys));
|
|
data->state = STATE_GET_EXP_LEARNED_MOVE_WAIT;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case STATE_GET_EXP_WANTS_TO_LEARN_MOVE_PRINT:
|
|
msg.id = msg_0197_01178; // "{0} wants to learn the move {1}."
|
|
msg.tag = TAG_NICKNAME_MOVE;
|
|
msg.param[0] = expBattler | (slot << 8);
|
|
msg.param[1] = data->unk30[4];
|
|
data->unk30[0] = BattleSystem_PrintBattleMessage(data->bsys, msgLoader, &msg, BattleSystem_GetTextFrameDelay(data->bsys));
|
|
data->state++;
|
|
break;
|
|
|
|
case STATE_GET_EXP_CANT_LEARN_MORE_MOVES_PRINT:
|
|
msg.id = msg_0197_01179; // "But {0} can't learn more than four moves."
|
|
msg.tag = TAG_NICKNAME;
|
|
msg.param[0] = expBattler | (slot << 8);
|
|
data->unk30[0] = BattleSystem_PrintBattleMessage(data->bsys, msgLoader, &msg, BattleSystem_GetTextFrameDelay(data->bsys));
|
|
data->state++;
|
|
break;
|
|
|
|
case STATE_GET_EXP_WANTS_TO_LEARN_MOVE_PRINT_WAIT:
|
|
case STATE_GET_EXP_CANT_LEARN_MORE_MOVES_PRINT_WAIT:
|
|
case STATE_GET_EXP_ONE_TWO_POOF_WAIT:
|
|
case STATE_GET_EXP_FORGOT_HOW_TO_USE_WAIT:
|
|
case STATE_GET_EXP_AND_DOTDOTDOT_WAIT:
|
|
case STATE_GET_EXP_MAKE_IT_FORGET_CANCELLED_WAIT:
|
|
if (!TextPrinterCheckActive(data->unk30[0])) {
|
|
data->state++;
|
|
}
|
|
break;
|
|
|
|
case STATE_GET_EXP_MAKE_IT_FORGET_PROMPT:
|
|
// "Make it forget another move?"
|
|
BattleController_EmitDrawYesNoBox(data->bsys, data->ctx, expBattler, msg_0197_01180, 1, 0, 0);
|
|
data->state++;
|
|
break;
|
|
|
|
case STATE_GET_EXP_MAKE_IT_FORGET_ANSWER:
|
|
if (BattleBuffer_GetNext(data->ctx, expBattler)) {
|
|
if (BattleBuffer_GetNext(data->ctx, expBattler) == 0xFF) { // TODO: could use a const
|
|
data->state = STATE_GET_EXP_MAKE_IT_FORGET_CANCELLED;
|
|
} else {
|
|
msg.id = msg_0197_01183; // "Which move should be forgotten?"
|
|
msg.tag = TAG_NONE;
|
|
data->unk30[0] = BattleSystem_PrintBattleMessage(data->bsys, msgLoader, &msg, BattleSystem_GetTextFrameDelay(data->bsys));
|
|
data->state = STATE_GET_EXP_MAKE_IT_FORGET_WAIT;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case STATE_GET_EXP_MAKE_IT_FORGET_WAIT:
|
|
if (!TextPrinterCheckActive(data->unk30[0])) {
|
|
ov12_02263D14(data->bsys, expBattler, data->unk30[4], slot);
|
|
data->state++;
|
|
}
|
|
break;
|
|
|
|
case STATE_GET_EXP_MAKE_IT_FORGET_INPUT_TAKEN:
|
|
if (BattleBuffer_GetNext(data->ctx, expBattler) == 0xFF) {
|
|
data->state = STATE_GET_EXP_MAKE_IT_FORGET_CANCELLED;
|
|
} else if (BattleBuffer_GetNext(data->ctx, expBattler)) {
|
|
data->unk30[5] = data->ctx->battleBuffer[expBattler][0] - 1;
|
|
data->state = STATE_GET_EXP_ONE_TWO_POOF;
|
|
}
|
|
break;
|
|
|
|
case STATE_GET_EXP_MAKE_IT_FORGET_CANCELLED:
|
|
msg.id = msg_0197_01184; // "Well, then..."
|
|
msg.tag = TAG_NONE;
|
|
data->unk30[0] = BattleSystem_PrintBattleMessage(data->bsys, msgLoader, &msg, BattleSystem_GetTextFrameDelay(data->bsys));
|
|
data->state++;
|
|
break;
|
|
|
|
case STATE_GET_EXP_GIVE_UP_LEARNING_PROMPT:
|
|
// "Should this Pokémon give up on learning this new move?"
|
|
BattleController_EmitDrawYesNoBox(data->bsys, data->ctx, expBattler, msg_0197_01185, 2, data->unk30[4], 0);
|
|
data->state++;
|
|
break;
|
|
|
|
case STATE_GET_EXP_GIVE_UP_LEARNING_ANSWER:
|
|
if (BattleBuffer_GetNext(data->ctx, expBattler)) {
|
|
if (BattleBuffer_GetNext(data->ctx, expBattler) == 0xFF) {
|
|
data->state = STATE_GET_EXP_WANTS_TO_LEARN_MOVE_PRINT;
|
|
} else {
|
|
msg.id = msg_0197_01188; // "{0} did not learn {1}."
|
|
msg.tag = TAG_NICKNAME_MOVE;
|
|
msg.param[0] = expBattler | (slot << 8);
|
|
msg.param[1] = data->unk30[4];
|
|
data->unk30[0] = BattleSystem_PrintBattleMessage(data->bsys, msgLoader, &msg, BattleSystem_GetTextFrameDelay(data->bsys));
|
|
data->state = 35;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case STATE_GET_EXP_GIVE_UP_LEARNING_WAIT:
|
|
if (!TextPrinterCheckActive(data->unk30[0])) {
|
|
// Check for another move to learn
|
|
data->state = STATE_GET_EXP_CHECK_LEARN_MOVE;
|
|
}
|
|
break;
|
|
|
|
case STATE_GET_EXP_ONE_TWO_POOF:
|
|
msg.id = msg_0197_01189; // "1, 2, and... ... Poof!"
|
|
msg.tag = 0;
|
|
data->unk30[0] = BattleSystem_PrintBattleMessage(data->bsys, msgLoader, &msg, BattleSystem_GetTextFrameDelay(data->bsys));
|
|
data->state++;
|
|
break;
|
|
|
|
case STATE_GET_EXP_FORGOT_HOW_TO_USE:
|
|
msg.id = msg_0197_01190; // "{0} forgot how to use {1}."
|
|
msg.tag = TAG_NICKNAME_MOVE;
|
|
msg.param[0] = expBattler | (slot << 8);
|
|
msg.param[1] = GetMonData(mon, MON_DATA_MOVE1 + data->unk30[5], NULL);
|
|
data->unk30[0] = BattleSystem_PrintBattleMessage(data->bsys, msgLoader, &msg, BattleSystem_GetTextFrameDelay(data->bsys));
|
|
data->state++;
|
|
break;
|
|
|
|
case STATE_GET_EXP_AND_DOTDOTDOT:
|
|
msg.id = msg_0197_01191; // "And..."
|
|
msg.tag = TAG_NONE;
|
|
data->unk30[0] = BattleSystem_PrintBattleMessage(data->bsys, msgLoader, &msg, BattleSystem_GetTextFrameDelay(data->bsys));
|
|
data->state++;
|
|
break;
|
|
|
|
case STATE_GET_EXP_LEARNED_MOVE:
|
|
msg.id = msg_0197_01192; // "{0} learned {1}!"
|
|
msg.tag = TAG_NICKNAME_MOVE;
|
|
msg.param[0] = expBattler | (slot << 8);
|
|
msg.param[1] = data->unk30[4];
|
|
data->unk30[0] = BattleSystem_PrintBattleMessage(data->bsys, msgLoader, &msg, BattleSystem_GetTextFrameDelay(data->bsys));
|
|
|
|
i = 0;
|
|
SetMonData(mon, MON_DATA_MOVE1PPUP + data->unk30[5], &i);
|
|
MonSetMoveInSlot(mon, data->unk30[4], data->unk30[5]);
|
|
|
|
if (data->ctx->selectedMonIndex[expBattler] == slot) {
|
|
BattleSystem_ReloadMonData(data->bsys, data->ctx, expBattler, data->ctx->selectedMonIndex[expBattler]);
|
|
}
|
|
|
|
data->state = STATE_GET_EXP_LEARNED_MOVE_WAIT;
|
|
break;
|
|
|
|
case STATE_GET_EXP_LEARNED_MOVE_WAIT:
|
|
if (!TextPrinterCheckActive(data->unk30[0])) {
|
|
// Check for another move to learn
|
|
data->state = STATE_GET_EXP_CHECK_LEARN_MOVE;
|
|
}
|
|
break;
|
|
|
|
case STATE_GET_EXP_CHECK_DONE:
|
|
data->ctx->unk_A4[side] &= (MaskOfFlagNo(slot) ^ 0xFFFFFFFF); // this mon is done
|
|
data->unk30[6] = slot + 1;
|
|
data->state = STATE_GET_EXP_START; // go back to the top and get the next mon
|
|
break;
|
|
|
|
case STATE_GET_EXP_DONE:
|
|
data->ctx->getterWork = NULL;
|
|
FreeToHeap(inData);
|
|
SysTask_Destroy(task);
|
|
break;
|
|
}
|
|
}
|