From 1a94d27fe683a373c3ffc028c201d4fc7bb74abd Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Wed, 15 Jul 2020 17:21:12 +0200 Subject: [PATCH] Emergency Exit --- asm/macros/battle_ai_script.inc | 10 +++++++ data/battle_ai_scripts.s | 31 +++++++++++++++++++- data/battle_anim_scripts.s | 8 ++++++ data/battle_scripts_1.s | 33 ++++++++++++++++++++++ include/battle.h | 21 ++++---------- include/battle_scripts.h | 4 +++ include/constants/battle.h | 11 ++++++++ include/constants/battle_anim.h | 3 +- include/constants/battle_script_commands.h | 5 ++-- src/battle_ai_script_commands.c | 18 ++++++++++++ src/battle_anim_utility_funcs.c | 9 ++++++ src/battle_script_commands.c | 31 ++++++++++++++++++-- src/battle_util.c | 17 +++++++++++ 13 files changed, 180 insertions(+), 21 deletions(-) diff --git a/asm/macros/battle_ai_script.inc b/asm/macros/battle_ai_script.inc index 7fa775ef3..5b6d3b6db 100644 --- a/asm/macros/battle_ai_script.inc +++ b/asm/macros/battle_ai_script.inc @@ -668,6 +668,16 @@ .byte 0x75 .endm + .macro get_considered_move_target + .byte 0x76 + .endm + + .macro compare_speeds battler1:req, battler2:req + .byte 0x77 + .byte \battler1 + .byte \battler2 + .endm + @ useful script macros .macro if_has_physical_move battler:req, ptr:req if_has_move_with_split \battler, SPLIT_PHYSICAL, \ptr diff --git a/data/battle_ai_scripts.s b/data/battle_ai_scripts.s index 86b12d249..5398a6c3d 100644 --- a/data/battle_ai_scripts.s +++ b/data/battle_ai_scripts.s @@ -3610,10 +3610,39 @@ AI_ConsiderAllyChosenMove: if_equal 0, AI_ConsiderAllyChosenMoveRet get_move_effect_from_result if_equal EFFECT_HELPING_HAND, AI_PartnerChoseHelpingHand - if_equal EFFECT_PERISH_SONG, AI_PartnerChosePerishSong + if_equal EFFECT_PERISH_SONG, AI_PartnerChosePerishSong + if_equal EFFECT_ALWAYS_CRIT, AI_PartnerChoseAlwaysCrit AI_ConsiderAllyChosenMoveRet: end +@ Ally decided to use Frost Breath on us. we must have Anger Point as our ability +AI_PartnerChoseAlwaysCrit: + if_no_ability AI_USER, ABILITY_ANGER_POINT, AI_PartnerChoseAlwaysCritEnd + @frost breath user should be faster + compare_speeds AI_USER, AI_USER_PARTNER + if_not_equal 1, AI_PartnerChoseAlwaysCritEnd + get_considered_move_effect + if_in_hwords sEffectsAtkRaise, Score_Minus3 + @encourage moves hitting multiple opponents + get_considered_move_power + if_equal 0, AI_PartnerChoseAlwaysCritEnd + get_considered_move_target + if_equal MOVE_TARGET_BOTH, Score_Plus3 + if_equal MOVE_TARGET_FOES_AND_ALLY, Score_Plus3 +AI_PartnerChoseAlwaysCritEnd: + end + +.align 1 +sEffectsAtkRaise: + .2byte EFFECT_ATTACK_ACCURACY_UP + .2byte EFFECT_ATTACK_UP + .2byte EFFECT_ATTACK_UP_2 + .2byte EFFECT_DRAGON_DANCE + .2byte EFFECT_COIL + .2byte EFFECT_BELLY_DRUM + .2byte EFFECT_BULK_UP + .2byte -1 + AI_PartnerChoseHelpingHand: @ Do not use a status move if you know your move's power will be boosted get_considered_move_power diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index b2dddb17b..111790923 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -776,6 +776,7 @@ gBattleAnims_General:: .4byte General_TerrainPsychic .4byte General_IllusionOff .4byte General_FormChange + .4byte General_SlideOffScreen .align 2 gBattleAnims_Special:: @@ -24310,6 +24311,13 @@ General_FormChange: waitforvisualfinish clearmonbg ANIM_ATTACKER end + +General_SlideOffScreen: + createvisualtask AnimTask_SlideOffScreen, 5, ANIM_TARGET, +3 + waitforvisualfinish + createvisualtask AnimTask_SetInvisible, 1, ANIM_TARGET, TRUE + waitforvisualfinish + end General_MegaEvolution: loadspritegfx ANIM_TAG_MEGA_STONE diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 87f2f4bd8..b2e6f6012 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6553,6 +6553,39 @@ BattleScript_MoodyLower: waitmessage 0x40 BattleScript_MoodyEnd: end3 + +BattleScript_EmergencyExit:: + pause 0x5 + call BattleScript_AbilityPopUp + pause 0x40 +BattleScript_EmergencyExitNoPopUp:: + playanimation BS_TARGET, B_ANIM_SLIDE_OFFSCREEN, NULL + waitanimation + openpartyscreen BS_TARGET, BattleScript_EmergencyExitRet + switchoutabilities BS_TARGET + waitstate + switchhandleorder BS_TARGET, 2 + returntoball BS_TARGET + getswitchedmondata BS_TARGET + switchindataupdate BS_TARGET + hpthresholds BS_TARGET + printstring STRINGID_SWITCHINMON + switchinanim BS_TARGET, TRUE + waitstate + switchineffects BS_TARGET +BattleScript_EmergencyExitRet: + return + +BattleScript_EmergencyExitWild:: + pause 0x5 + call BattleScript_AbilityPopUp + pause 0x40 +BattleScript_EmergencyExitWildNoPopUp:: + playanimation BS_TARGET, B_ANIM_SLIDE_OFFSCREEN, NULL + waitanimation + setoutcomeonteleport BS_TARGET + finishaction + return BattleScript_TraceActivates:: pause 0x20 diff --git a/include/battle.h b/include/battle.h index 8d3acf954..a36f2aead 100644 --- a/include/battle.h +++ b/include/battle.h @@ -51,16 +51,6 @@ #define MSG_DISPLAY 0x7 #define BATTLE_COMMUNICATION_ENTRIES_COUNT 0x8 -#define MOVE_TARGET_SELECTED 0x0 -#define MOVE_TARGET_DEPENDS 0x1 -#define MOVE_TARGET_USER_OR_SELECTED 0x2 -#define MOVE_TARGET_RANDOM 0x4 -#define MOVE_TARGET_BOTH 0x8 -#define MOVE_TARGET_USER 0x10 -#define MOVE_TARGET_FOES_AND_ALLY 0x20 -#define MOVE_TARGET_OPPONENTS_FIELD 0x40 -#define MOVE_TARGET_ALLY 0x80 - #define BATTLE_BUFFER_LINK_SIZE 0x1000 struct ResourceFlags @@ -68,11 +58,12 @@ struct ResourceFlags u32 flags[4]; }; -#define RESOURCE_FLAG_FLASH_FIRE 0x1 -#define RESOURCE_FLAG_ROOST 0x2 -#define RESOURCE_FLAG_UNBURDEN 0x4 -#define RESOURCE_FLAG_INTIMIDATED 0x8 -#define RESOURCE_FLAG_TRACED 0x10 +#define RESOURCE_FLAG_FLASH_FIRE 0x1 +#define RESOURCE_FLAG_ROOST 0x2 +#define RESOURCE_FLAG_UNBURDEN 0x4 +#define RESOURCE_FLAG_INTIMIDATED 0x8 +#define RESOURCE_FLAG_TRACED 0x10 +#define RESOURCE_FLAG_EMERGENCY_EXIT 0x20 struct DisableStruct { diff --git a/include/battle_scripts.h b/include/battle_scripts.h index af407d05e..4ad35f108 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -343,5 +343,9 @@ extern const u8 BattleScript_FriskActivates[]; extern const u8 BattleScript_FriskMsg[]; extern const u8 BattleScript_FriskMsgWithPopup[]; extern const u8 BattleScript_MoodyActivates[]; +extern const u8 BattleScript_EmergencyExit[]; +extern const u8 BattleScript_EmergencyExitNoPopUp[]; +extern const u8 BattleScript_EmergencyExitWild[]; +extern const u8 BattleScript_EmergencyExitWildNoPopUp[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/constants/battle.h b/include/constants/battle.h index 97e64a269..d4f2c90b7 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -346,4 +346,15 @@ #define BATTLE_TERRAIN_BUILDING 8 #define BATTLE_TERRAIN_PLAIN 9 +// Move targets +#define MOVE_TARGET_SELECTED 0x0 +#define MOVE_TARGET_DEPENDS 0x1 +#define MOVE_TARGET_USER_OR_SELECTED 0x2 +#define MOVE_TARGET_RANDOM 0x4 +#define MOVE_TARGET_BOTH 0x8 +#define MOVE_TARGET_USER 0x10 +#define MOVE_TARGET_FOES_AND_ALLY 0x20 +#define MOVE_TARGET_OPPONENTS_FIELD 0x40 +#define MOVE_TARGET_ALLY 0x80 + #endif // GUARD_CONSTANTS_BATTLE_H diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index b93cf65ca..4224b2daf 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -347,7 +347,7 @@ #define ANIM_TAG_STEAM_ERUPTION (ANIM_SPRITES_START + 335) #define ANIM_TAG_CONFIDE (ANIM_SPRITES_START + 336) #define ANIM_TAG_VERTICAL_HEX (ANIM_SPRITES_START + 337) -#define ANIM_TAG_UNAVAILABLE_1 (ANIM_SPRITES_START + 338) //0x2862.. supposedly used elsewhere? +#define ANIM_TAG_UNAVAILABLE_1 (ANIM_SPRITES_START + 338) //0x2862.. supposedly used elsewhere? #define ANIM_TAG_UNAVAILABLE_2 (ANIM_SPRITES_START + 339) #define ANIM_TAG_POWER_TRICK (ANIM_SPRITES_START + 340) #define ANIM_TAG_CHAIN_LINK (ANIM_SPRITES_START + 341) @@ -524,6 +524,7 @@ #define B_ANIM_TERRAIN_PSYCHIC 0x1B #define B_ANIM_ILLUSION_OFF 0x1C #define B_ANIM_FORM_CHANGE 0x1D +#define B_ANIM_SLIDE_OFFSCREEN 0x1E // for Emergency Exit // special animations table #define B_ANIM_LVL_UP 0x0 diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 7173b17db..afc6eb0e8 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -211,8 +211,9 @@ #define MOVEEND_NEXT_TARGET 20 #define MOVEEND_LIFE_ORB 21 #define MOVEEND_DANCER 22 -#define MOVEEND_CLEAR_BITS 23 -#define MOVEEND_COUNT 24 +#define MOVEEND_EMERGENCY_EXIT 23 +#define MOVEEND_CLEAR_BITS 24 +#define MOVEEND_COUNT 25 // stat flags for Cmd_playstatchangeanimation #define BIT_HP 0x1 diff --git a/src/battle_ai_script_commands.c b/src/battle_ai_script_commands.c index 3593868d6..7e081c764 100644 --- a/src/battle_ai_script_commands.c +++ b/src/battle_ai_script_commands.c @@ -176,6 +176,8 @@ static void Cmd_get_best_dmg_hp_percent(void); static void Cmd_get_curr_dmg_hp_percent(void); static void Cmd_get_move_split_from_result(void); static void Cmd_get_considered_move_split(void); +static void Cmd_get_considered_move_target(void); +static void Cmd_compare_speeds(void); // ewram EWRAM_DATA const u8 *gAIScriptPtr = NULL; @@ -304,6 +306,8 @@ static const BattleAICmdFunc sBattleAICmdTable[] = Cmd_get_curr_dmg_hp_percent, // 0x73 Cmd_get_move_split_from_result, // 0x74 Cmd_get_considered_move_split, // 0x75 + Cmd_get_considered_move_target, // 0x76 + Cmd_compare_speeds, // 0x77 }; static const u16 sDiscouragedPowerfulMoveEffects[] = @@ -2808,3 +2812,17 @@ static void Cmd_get_considered_move_split(void) AI_THINKING_STRUCT->funcResult = gBattleMoves[AI_THINKING_STRUCT->moveConsidered].split; gAIScriptPtr += 1; } + +static void Cmd_get_considered_move_target(void) +{ + AI_THINKING_STRUCT->funcResult = gBattleMoves[AI_THINKING_STRUCT->moveConsidered].target; + gAIScriptPtr += 1; +} + +static void Cmd_compare_speeds(void) +{ + u8 battler1 = BattleAI_GetWantedBattler(gAIScriptPtr[1]); + u8 battler2 = BattleAI_GetWantedBattler(gAIScriptPtr[2]); + AI_THINKING_STRUCT->funcResult = GetWhoStrikesFirst(battler1, battler2, TRUE); + gAIScriptPtr += 3; +} diff --git a/src/battle_anim_utility_funcs.c b/src/battle_anim_utility_funcs.c index afcb82186..5afa17634 100644 --- a/src/battle_anim_utility_funcs.c +++ b/src/battle_anim_utility_funcs.c @@ -1079,3 +1079,12 @@ void AnimTask_CanBattlerSwitch(u8 taskId) gBattleAnimArgs[ARG_RET_ID] = CanBattlerSwitch(GetAnimBattlerId(gBattleAnimArgs[0])); DestroyAnimVisualTask(taskId); } + +void AnimTask_SetInvisible(u8 taskId) +{ + u32 battlerId = GetAnimBattlerId(gBattleAnimArgs[0]); + u32 spriteId = gBattlerSpriteIds[battlerId]; + + gSprites[spriteId].invisible = gBattleSpritesDataPtr->battlerData[battlerId].invisible = gBattleAnimArgs[1]; + DestroyAnimVisualTask(taskId); +} diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index f4d60f51f..962a7fdc6 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -4830,6 +4830,33 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; + case MOVEEND_EMERGENCY_EXIT: // Special case, because moves hitting multiple opponents stop after switching out + for (i = 0; i < gBattlersCount; i++) + { + if (gBattleResources->flags->flags[i] & RESOURCE_FLAG_EMERGENCY_EXIT) + { + gBattleResources->flags->flags[i] &= ~(RESOURCE_FLAG_EMERGENCY_EXIT); + gBattlerTarget = gBattlerAbility = i; + BattleScriptPushCursor(); + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER || GetBattlerSide(i) == B_SIDE_PLAYER) + { + if (B_ABILITY_POP_UP >= GEN_6) + gBattlescriptCurrInstr = BattleScript_EmergencyExit; + else + gBattlescriptCurrInstr = BattleScript_EmergencyExitNoPopUp; + } + else + { + if (B_ABILITY_POP_UP >= GEN_6) + gBattlescriptCurrInstr = BattleScript_EmergencyExitWild; + else + gBattlescriptCurrInstr = BattleScript_EmergencyExitWildNoPopUp; + } + return; + } + } + gBattleScripting.moveendState++; + break; case MOVEEND_CLEAR_BITS: // Clear/Set bits for things like using a move for all targets and all hits. if (gSpecialStatuses[gBattlerAttacker].instructedChosenTarget) *(gBattleStruct->moveTarget + gBattlerAttacker) = gSpecialStatuses[gBattlerAttacker].instructedChosenTarget & 0x3; @@ -11701,7 +11728,7 @@ static void Cmd_handleballthrow(void) { if (IsCriticalCapture()) gBattleSpritesDataPtr->animationData->criticalCaptureSuccess = 1; - + gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem); if (CalculatePlayerPartyCount() == PARTY_SIZE) @@ -11715,7 +11742,7 @@ static void Cmd_handleballthrow(void) gBattleCommunication[MULTISTRING_CHOOSER] = shakes + 3; else gBattleCommunication[MULTISTRING_CHOOSER] = shakes; - + gBattlescriptCurrInstr = BattleScript_ShakeBallThrow; } } diff --git a/src/battle_util.c b/src/battle_util.c index 9a734065d..48057afa0 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3557,6 +3557,23 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA effect++; } break; + case ABILITY_EMERGENCY_EXIT: + case ABILITY_WIMP_OUT: + if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && TARGET_TURN_DAMAGED + && IsBattlerAlive(battler) + // Had more than half of hp before, now has less + && gBattleStruct->hpBefore[battler] > gBattleMons[battler].maxHP / 2 + && gBattleMons[battler].hp < gBattleMons[battler].maxHP / 2 + && (gMultiHitCounter == 0 || gMultiHitCounter == 1) + && !(GetBattlerAbility(gBattlerAttacker) == ABILITY_SHEER_FORCE && gBattleMoves[gCurrentMove].flags & FLAG_SHEER_FORCE_BOOST) + && (CanBattlerSwitch(battler) || !(gBattleTypeFlags & BATTLE_TYPE_TRAINER)) + && !(gBattleTypeFlags & BATTLE_TYPE_ARENA)) + { + gBattleResources->flags->flags[battler] |= RESOURCE_FLAG_EMERGENCY_EXIT; + effect++; + } + break; case ABILITY_WEAK_ARMOR: if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && TARGET_TURN_DAMAGED