From b9cf1fdcfe530c12c5cdefe7d23bd1e29cba677a Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Sat, 29 Sep 2018 18:40:14 +0200 Subject: [PATCH] Psycho Shift, Power Trick, Flame Burst --- asm/macros/battle_script.inc | 13 ++ data/battle_scripts_1.s | 50 +++++++ include/battle_scripts.h | 1 + include/constants/battle.h | 3 +- include/constants/battle_move_effects.h | 3 + include/constants/battle_script_commands.h | 3 + include/constants/battle_string_ids.h | 3 +- src/battle_main.c | 2 + src/battle_message.c | 7 + src/battle_script_commands.c | 148 +++++++++++++++++---- src/data/battle_moves.h | 6 +- 11 files changed, 211 insertions(+), 28 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 3174166085..97a776f3e7 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1522,6 +1522,19 @@ .4byte \ptr .endm + .macro trypsychoshift ptr + various BS_ATTACKER, VARIOUS_PSYCHO_SHIFT + .4byte \ptr + .endm + + .macro curestatus battler + various \battler, VARIOUS_CURE_STATUS + .endm + + .macro powertrick battler + various \battler, VARIOUS_POWER_TRICK + .endm + @ helpful macros .macro setstatchanger stat, stages, down setbyte sSTATCHANGER \stat | \stages << 4 | \down << 7 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index a4948dc898..c36ca54e2e 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -321,6 +321,56 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectHitEnemyHealAlly .4byte BattleScript_EffectSmackDown .4byte BattleScript_EffectSynchronoise + .4byte BattleScript_EffectPsychoShift + .4byte BattleScript_EffectPowerTrick + .4byte BattleScript_EffectFlameBurst + +BattleScript_EffectFlameBurst: + setmoveeffect MOVE_EFFECT_FLAME_BURST | MOVE_EFFECT_AFFECTS_USER + goto BattleScript_EffectHit + +BattleScript_MoveEffectFlameBurst:: + printstring STRINGID_BURSTINGFLAMESHIT + waitmessage 0x40 + healthbarupdate BS_SCRIPTING + datahpupdate BS_SCRIPTING + tryfaintmon BS_SCRIPTING, FALSE, NULL + return + +BattleScript_EffectPowerTrick: + attackcanceler + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + attackstring + ppreduce + powertrick BS_ATTACKER + attackanimation + waitanimation + printstring STRINGID_PKMNSWITCHEDATKANDDEF + waitmessage 0x40 + goto BattleScript_MoveEnd + +BattleScript_EffectPsychoShift: + attackcanceler + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + attackstring + ppreduce + jumpifstatus BS_ATTACKER, STATUS1_ANY, BattleScript_EffectPsychoShiftCanWork + goto BattleScript_ButItFailed +BattleScript_EffectPsychoShiftCanWork: + jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed + jumpifsideaffecting BS_TARGET, SIDE_STATUS_SAFEGUARD, BattleScript_SafeguardProtected + trypsychoshift BattleScript_MoveEnd + attackanimation + waitanimation + printfromtable gStatusConditionsStringIds + waitmessage 0x40 + statusanimation BS_TARGET + updatestatusicon BS_TARGET + curestatus BS_ATTACKER + printstring STRINGID_PKMNSTATUSNORMAL + waitmessage 0x40 + updatestatusicon BS_ATTACKER + goto BattleScript_MoveEnd BattleScript_EffectSynchronoise: attackcanceler diff --git a/include/battle_scripts.h b/include/battle_scripts.h index e96babfb5f..40bebc1c34 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -279,5 +279,6 @@ extern const u8 BattleScript_MoveEffectClearSmog[]; extern const u8 BattleScript_ForceRandomSwitch[]; extern const u8 BattleScript_SideStatusWoreOffReturn[]; extern const u8 BattleScript_MoveEffectSmackDown[]; +extern const u8 BattleScript_MoveEffectFlameBurst[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/constants/battle.h b/include/constants/battle.h index 0e61152450..a0b193e6ad 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -158,6 +158,7 @@ #define STATUS3_AQUA_RING 0x10000000 #define STATUS3_LASER_FOCUS 0x20000000 #define STATUS3_ELECTRIFIED 0x40000000 +#define STATUS3_POWER_TRICK 0x80000000 #define STATUS3_SEMI_INVULNERABLE (STATUS3_UNDERGROUND | STATUS3_ON_AIR | STATUS3_UNDERWATER) // Not really sure what a "hitmarker" is. @@ -315,7 +316,7 @@ #define MOVE_EFFECT_CLEAR_SMOG 0x3A #define MOVE_EFFECT_SP_ATK_TWO_DOWN 0x3B #define MOVE_EFFECT_SMACK_DOWN 0x3C -#define MOVE_EFFECT_NOTHING_3D 0x3D +#define MOVE_EFFECT_FLAME_BURST 0x3D #define MOVE_EFFECT_NOTHING_3E 0x3E #define MOVE_EFFECT_NOTHING_3F 0x3F #define MOVE_EFFECT_AFFECTS_USER 0x40 diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index b2d3788012..63e51f6f04 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -310,5 +310,8 @@ #define EFFECT_HIT_ENEMY_HEAL_ALLY 304 // Pollen Puff #define EFFECT_SMACK_DOWN 305 #define EFFECT_SYNCHRONOISE 306 +#define EFFECT_PSYCHO_SHIFT 307 +#define EFFECT_POWER_TRICK 308 +#define EFFECT_FLAME_BURST 309 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 6f6595e5c8..a9e7f656d3 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -112,6 +112,9 @@ #define VARIOUS_DEFOG 58 #define VARIOUS_JUMP_IF_TARGET_ALLY 59 #define VARIOUS_TRY_SYNCHRONOISE 60 +#define VARIOUS_PSYCHO_SHIFT 61 +#define VARIOUS_CURE_STATUS 62 +#define VARIOUS_POWER_TRICK 63 // atk80, dmg manipulation #define ATK80_DMG_CHANGE_SIGN 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index ba44bdeb1e..667dc13d75 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -508,7 +508,8 @@ #define STRINGID_SEVERELY 505 #define STRINGID_INFESTATION 506 #define STRINGID_NOEFFECTONTARGET 507 +#define STRINGID_BURSTINGFLAMESHIT 508 -#define BATTLESTRINGS_COUNT 519 +#define BATTLESTRINGS_COUNT 521 #endif // GUARD_CONSTANTS_BATTLE_STRING_IDS_H diff --git a/src/battle_main.c b/src/battle_main.c index ba8752f6c2..0f2015bd03 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3143,6 +3143,8 @@ void SwitchInClearSetData(void) gStatuses3[i] |= 0x10; } } + if (gStatuses3[gActiveBattler] & STATUS3_POWER_TRICK) + SWAP(gBattleMons[gActiveBattler].attack, gBattleMons[gActiveBattler].defense, i); } else { diff --git a/src/battle_message.c b/src/battle_message.c index 22a32638a6..2f43cc84b7 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -649,6 +649,7 @@ static const u8 sText_drastically[] = _("drastically "); static const u8 sText_severely[] = _("severely "); static const u8 sText_Infestation[] = _("{B_DEF_NAME_WITH_PREFIX} has been afflicted\nwith an infestation by {B_ATK_NAME_WITH_PREFIX}!"); static const u8 sText_NoEffectOnTarget[] = _("It had no effect\non {B_DEF_NAME_WITH_PREFIX}!"); +static const u8 sText_BurstingFlames[] = _("The bursting flames\nhit {B_SCR_ACTIVE_NAME_WITH_PREFIX}!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { @@ -1149,6 +1150,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = sText_severely, sText_Infestation, sText_NoEffectOnTarget, + sText_BurstingFlames, }; const u16 gTerrainStringIds[] = @@ -1452,6 +1454,11 @@ const u16 gRoomsStringIds[] = STRINGID_EMPTYSTRING3 }; +const u16 gStatusConditionsStringIds[] = +{ + STRINGID_PKMNWASPOISONED, STRINGID_PKMNBADLYPOISONED, STRINGID_PKMNWASBURNED, STRINGID_PKMNWASPARALYZED, STRINGID_PKMNFELLASLEEP +}; + const u8 gText_PkmnIsEvolving[] = _("What?\n{STR_VAR_1} is evolving!"); const u8 gText_CongratsPkmnEvolved[] = _("Congratulations! Your {STR_VAR_1}\nevolved into {STR_VAR_2}!{UNKNOWN_A}\p"); const u8 gText_PkmnStoppedEvolving[] = _("Huh? {STR_VAR_1}\nstopped evolving!\p"); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 3b16de8ba1..9dc47e7d94 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2711,6 +2711,17 @@ void SetMoveEffect(bool8 primary, u8 certain) gBattlescriptCurrInstr = BattleScript_MoveEffectSmackDown; } break; + case MOVE_EFFECT_FLAME_BURST: + if (IsBattlerAlive(BATTLE_PARTNER(gBattlerTarget)) && GetBattlerAbility(BATTLE_PARTNER(gBattlerTarget)) != ABILITY_MAGIC_GUARD) + { + gBattleScripting.battler = BATTLE_PARTNER(gBattlerTarget); + gBattleMoveDamage = gBattleMons[BATTLE_PARTNER(gBattlerTarget)].hp / 16; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_MoveEffectFlameBurst; + } + break; } } } @@ -3261,6 +3272,7 @@ static void atk23_getexp(void) gActiveBattler = gBattleStruct->expGetterBattlerId; if (gBattleBufferB[gActiveBattler][0] == CONTROLLER_TWORETURNVALUES && gBattleBufferB[gActiveBattler][1] == RET_VALUE_LEVELED_UP) { + u16 temp, battlerId = 0xFF; if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && gBattlerPartyIndexes[gActiveBattler] == gBattleStruct->expGetterMonId) HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler); @@ -3276,33 +3288,25 @@ static void atk23_getexp(void) // update battle mon structure after level up if (gBattlerPartyIndexes[0] == gBattleStruct->expGetterMonId && gBattleMons[0].hp) - { - gBattleMons[0].level = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_LEVEL); - gBattleMons[0].hp = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_HP); - gBattleMons[0].maxHP = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_MAX_HP); - gBattleMons[0].attack = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_ATK); - gBattleMons[0].defense = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_DEF); - // Why is this duplicated? - gBattleMons[0].speed = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPEED); - gBattleMons[0].speed = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPEED); + battlerId = 0; + else if (gBattlerPartyIndexes[2] == gBattleStruct->expGetterMonId && gBattleMons[2].hp && (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + battlerId = 2; - gBattleMons[0].spAttack = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPATK); - gBattleMons[0].spDefense = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPDEF); - } - // What is else if? - if (gBattlerPartyIndexes[2] == gBattleStruct->expGetterMonId && gBattleMons[2].hp && (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + if (battlerId != 0xFF) { - gBattleMons[2].level = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_LEVEL); - gBattleMons[2].hp = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_HP); - gBattleMons[2].maxHP = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_MAX_HP); - gBattleMons[2].attack = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_ATK); - gBattleMons[2].defense = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_DEF); - // Duplicated again, but this time there's no Sp Defense - gBattleMons[2].speed = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPEED); - gBattleMons[2].speed = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPEED); + gBattleMons[battlerId].level = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_LEVEL); + gBattleMons[battlerId].hp = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_HP); + gBattleMons[battlerId].maxHP = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_MAX_HP); + gBattleMons[battlerId].attack = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_ATK); + gBattleMons[battlerId].defense = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_DEF); + gBattleMons[battlerId].speed = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPEED); + gBattleMons[battlerId].spAttack = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPATK); + gBattleMons[battlerId].spDefense = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPDEF); - gBattleMons[2].spAttack = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPATK); + if (gStatuses3[battlerId] & STATUS3_POWER_TRICK) + SWAP(gBattleMons[battlerId].attack, gBattleMons[battlerId].defense, temp); } + gBattleScripting.atk23_state = 5; } else @@ -6878,6 +6882,104 @@ static void atk76_various(void) else gBattlescriptCurrInstr += 7; return; + case VARIOUS_PSYCHO_SHIFT: + i = TRUE; + if (gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) + { + if (GetBattlerAbility(gBattlerTarget) == ABILITY_LIMBER) + { + gBattlerAbility = gBattlerTarget; + BattleScriptPush(T1_READ_PTR(gBattlescriptCurrInstr + 3)); + gBattlescriptCurrInstr = BattleScript_PRLZPrevention; + i = FALSE; + } + else if (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_ELECTRIC)) + { + BattleScriptPush(T1_READ_PTR(gBattlescriptCurrInstr + 3)); + gBattlescriptCurrInstr = BattleScript_PRLZPrevention; + i = FALSE; + } + else + { + gBattleCommunication[MULTISTRING_CHOOSER] = 3; + } + } + else if (gBattleMons[gBattlerAttacker].status1 & STATUS1_PSN_ANY) + { + if (GetBattlerAbility(gBattlerTarget) == ABILITY_IMMUNITY) + { + gBattlerAbility = gBattlerTarget; + BattleScriptPush(T1_READ_PTR(gBattlescriptCurrInstr + 3)); + gBattlescriptCurrInstr = BattleScript_PSNPrevention; + i = FALSE; + } + else if (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_POISON) || IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_STEEL)) + { + BattleScriptPush(T1_READ_PTR(gBattlescriptCurrInstr + 3)); + gBattlescriptCurrInstr = BattleScript_PSNPrevention; + i = FALSE; + } + else + { + if (gBattleMons[gBattlerAttacker].status1 & STATUS1_POISON) + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + else + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + } + } + else if (gBattleMons[gBattlerAttacker].status1 & STATUS1_BURN) + { + if (GetBattlerAbility(gBattlerTarget) == ABILITY_WATER_VEIL) + { + gBattlerAbility = gBattlerTarget; + BattleScriptPush(T1_READ_PTR(gBattlescriptCurrInstr + 3)); + gBattlescriptCurrInstr = BattleScript_BRNPrevention; + i = FALSE; + } + else if (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_FIRE)) + { + BattleScriptPush(T1_READ_PTR(gBattlescriptCurrInstr + 3)); + gBattlescriptCurrInstr = BattleScript_BRNPrevention; + i = FALSE; + } + else + { + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + } + } + else if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) + { + if (GetBattlerAbility(gBattlerTarget) == ABILITY_INSOMNIA || GetBattlerAbility(gBattlerTarget) == ABILITY_VITAL_SPIRIT) + { + gBattlerAbility = gBattlerTarget; + // BattleScriptPush(T1_READ_PTR(gBattlescriptCurrInstr + 3)); + // gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + i = FALSE; + } + else + { + gBattleCommunication[MULTISTRING_CHOOSER] = 4; + } + } + + if (i == TRUE) + { + gBattleMons[gBattlerTarget].status1 = gBattleMons[gBattlerAttacker].status1; + gActiveBattler = gBattlerTarget; + BtlController_EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBattler].status1); + MarkBattlerForControllerExec(gActiveBattler); + gBattlescriptCurrInstr += 7; + } + return; + case VARIOUS_CURE_STATUS: + gBattleMons[gActiveBattler].status1 = 0; + BtlController_EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBattler].status1); + MarkBattlerForControllerExec(gActiveBattler); + break; + case VARIOUS_POWER_TRICK: + gStatuses3[gActiveBattler] ^= STATUS3_POWER_TRICK; + SWAP(gBattleMons[gActiveBattler].attack, gBattleMons[gActiveBattler].defense, i); + break; } gBattlescriptCurrInstr += 3; diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index fd25be5de4..e9698a41ba 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -4505,7 +4505,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .split = SPLIT_PHYSICAL, }, { // MOVE_PSYCHO_SHIFT - .effect = EFFECT_PLACEHOLDER, // Needs a custom move effect + .effect = EFFECT_PSYCHO_SHIFT, .power = 0, .type = TYPE_PSYCHIC, .accuracy = 100, @@ -4553,7 +4553,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .split = SPLIT_SPECIAL, }, { // MOVE_POWER_TRICK - .effect = EFFECT_PLACEHOLDER, // Needs a custom move effect + .effect = EFFECT_POWER_TRICK, .power = 0, .type = TYPE_PSYCHIC, .accuracy = 0, @@ -5781,7 +5781,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .split = SPLIT_PHYSICAL, }, { // MOVE_FLAME_BURST - .effect = EFFECT_PLACEHOLDER, // Needs a custom move effect + .effect = EFFECT_FLAME_BURST, .power = 70, .type = TYPE_FIRE, .accuracy = 100,