diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 055edbbce..8a8e12e9a 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1570,6 +1570,11 @@ .macro setauroraveil battler various \battler, VARIOUS_SET_AURORA_VEIL .endm + + .macro trysetthirdtype battler, ptr + various \battler, VARIOUS_TRY_THIRD_TYPE + .4byte \ptr + .endm @ helpful macros .macro setstatchanger stat, stages, down diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 37b4433eb..3a4df269d 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -334,6 +334,19 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectDefenseUp2Hit .4byte BattleScript_EffectRevelationDance .4byte BattleScript_EffectAuroraVeil + .4byte BattleScript_EffectThirdType + +BattleScript_EffectThirdType: + attackcanceler + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + attackstring + ppreduce + trysetthirdtype BS_TARGET, BattleScript_ButItFailed + attackanimation + waitanimation + printstring STRINGID_THIRDTYPEADDED + waitmessage 0x40 + goto BattleScript_MoveEnd BattleScript_EffectDefenseUp2Hit: setmoveeffect MOVE_EFFECT_DEF_PLUS_2 | MOVE_EFFECT_AFFECTS_USER diff --git a/include/battle.h b/include/battle.h index f6c804519..3aab577ab 100644 --- a/include/battle.h +++ b/include/battle.h @@ -603,11 +603,12 @@ struct BattleStruct #define BATTLER_MAX_HP(battlerId)(gBattleMons[battlerId].hp == gBattleMons[battlerId].maxHP) #define TARGET_TURN_DAMAGED ((gSpecialStatuses[gBattlerTarget].physicalDmg != 0 || gSpecialStatuses[gBattlerTarget].specialDmg != 0)) -#define IS_BATTLER_OF_TYPE(battlerId, type)((gBattleMons[battlerId].type1 == type || gBattleMons[battlerId].type2 == type)) -#define SET_BATTLER_TYPE(battlerId, type) \ -{ \ - gBattleMons[battlerId].type1 = type; \ - gBattleMons[battlerId].type2 = type; \ +#define IS_BATTLER_OF_TYPE(battlerId, type)((gBattleMons[battlerId].type1 == type || gBattleMons[battlerId].type2 == type || gBattleMons[battlerId].type3 == type)) +#define SET_BATTLER_TYPE(battlerId, type) \ +{ \ + gBattleMons[battlerId].type1 = type; \ + gBattleMons[battlerId].type2 = type; \ + gBattleMons[battlerId].type3 = TYPE_MYSTERY; \ } #define GET_STAT_BUFF_ID(n)((n & 0xF)) // first four bits 0x1, 0x2, 0x4, 0x8 diff --git a/include/battle_controllers.h b/include/battle_controllers.h index b60dfb469..dae1dd8f0 100644 --- a/include/battle_controllers.h +++ b/include/battle_controllers.h @@ -111,6 +111,7 @@ struct ChooseMoveStruct u16 species; u8 monType1; u8 monType2; + u8 monType3; struct MegaEvolutionData mega; }; diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index d8cf1e6ad..6b956aed7 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -322,5 +322,6 @@ #define EFFECT_DEFENSE_UP2_HIT 316 #define EFFECT_REVELATION_DANCE 317 #define EFFECT_AURORA_VEIL 318 +#define EFFECT_THIRD_TYPE 319 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index f32622f0d..c4ba51f13 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -131,6 +131,7 @@ #define VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF 69 #define VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON 70 #define VARIOUS_SET_AURORA_VEIL 71 +#define VARIOUS_TRY_THIRD_TYPE 72 // 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 fa8c359b2..3205a3037 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -511,6 +511,7 @@ #define STRINGID_NOEFFECTONTARGET 507 #define STRINGID_BURSTINGFLAMESHIT 508 #define STRINGID_BESTOWITEMGIVING 509 +#define STRINGID_THIRDTYPEADDED 510 #define BATTLESTRINGS_COUNT 521 diff --git a/include/pokemon.h b/include/pokemon.h index ba5802c77..e0b44775e 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -316,7 +316,7 @@ struct BattlePokemon /*0x20*/ u8 ability; /*0x21*/ u8 type1; /*0x22*/ u8 type2; - /*0x23*/ u8 unknown; + /*0x23*/ u8 type3; /*0x24*/ u8 pp[4]; /*0x28*/ u16 hp; /*0x2A*/ u8 level; diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 49d5d5cfe..7a0da96e5 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -506,7 +506,7 @@ static void HandleInputChooseMove(void) PlaySE(SE_SELECT); if (moveInfo->moves[gMoveSelectionCursor[gActiveBattler]] == MOVE_CURSE) { - if (moveInfo->monType1 != TYPE_GHOST && moveInfo->monType2 != TYPE_GHOST) + if (moveInfo->monType1 != TYPE_GHOST && moveInfo->monType2 != TYPE_GHOST && moveInfo->monType3 != TYPE_GHOST) moveTarget = MOVE_TARGET_USER; else moveTarget = MOVE_TARGET_SELECTED; diff --git a/src/battle_debug.c b/src/battle_debug.c index 91d597d46..d7e5cd393 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -854,7 +854,7 @@ static void CreateSecondaryListMenu(struct BattleDebugMenu *data) itemsCount = 1; break; case LIST_ITEM_TYPES: - itemsCount = 2; + itemsCount = 3; break; case LIST_ITEM_MOVES: case LIST_ITEM_PP: @@ -972,7 +972,7 @@ static void PrintSecondaryEntries(struct BattleDebugMenu *data) AddTextPrinter(&printer, 0, NULL); break; case LIST_ITEM_TYPES: - for (i = 0; i < 2; i++) + for (i = 0; i < 3; i++) { u8 *types = &gBattleMons[data->battlerId].type1; diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 3acc97d06..7ad886bdd 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -221,7 +221,7 @@ u16 ChooseMoveAndTargetInBattlePalace(void) if (moveInfo->moves[chosenMoveId] == MOVE_CURSE) { - if (moveInfo->monType1 != TYPE_GHOST && moveInfo->monType2 != TYPE_GHOST) + if (moveInfo->monType1 != TYPE_GHOST && moveInfo->monType2 != TYPE_GHOST && moveInfo->monType3 != TYPE_GHOST) var1 = MOVE_TARGET_USER; else var1 = MOVE_TARGET_SELECTED; diff --git a/src/battle_main.c b/src/battle_main.c index 3d10ac40d..1c2538c1a 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3319,6 +3319,7 @@ void FaintClearSetData(void) gBattleMons[gActiveBattler].type1 = gBaseStats[gBattleMons[gActiveBattler].species].type1; gBattleMons[gActiveBattler].type2 = gBaseStats[gBattleMons[gActiveBattler].species].type2; + gBattleMons[gActiveBattler].type3 = TYPE_MYSTERY; ClearBattlerMoveHistory(gActiveBattler); ClearBattlerAbilityHistory(gActiveBattler); @@ -3389,6 +3390,7 @@ static void BattleIntroDrawTrainersOrMonsSprites(void) gBattleMons[gActiveBattler].type1 = gBaseStats[gBattleMons[gActiveBattler].species].type1; gBattleMons[gActiveBattler].type2 = gBaseStats[gBattleMons[gActiveBattler].species].type2; + gBattleMons[gActiveBattler].type3 = TYPE_MYSTERY; gBattleMons[gActiveBattler].ability = GetAbilityBySpecies(gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].altAbility); hpOnSwitchout = &gBattleStruct->hpOnSwitchout[GetBattlerSide(gActiveBattler)]; *hpOnSwitchout = gBattleMons[gActiveBattler].hp; @@ -4256,6 +4258,7 @@ static void HandleTurnActionSelectionState(void) moveInfo.species = gBattleMons[gActiveBattler].species; moveInfo.monType1 = gBattleMons[gActiveBattler].type1; moveInfo.monType2 = gBattleMons[gActiveBattler].type2; + moveInfo.monType3 = gBattleMons[gActiveBattler].type3; for (i = 0; i < 4; i++) { @@ -5426,6 +5429,8 @@ void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk) gBattleStruct->dynamicMoveType = gBattleMons[battlerAtk].type1 | 0x80; else if (gBattleMons[battlerAtk].type2 != TYPE_MYSTERY) gBattleStruct->dynamicMoveType = gBattleMons[battlerAtk].type2 | 0x80; + else if (gBattleMons[battlerAtk].type3 != TYPE_MYSTERY) + gBattleStruct->dynamicMoveType = gBattleMons[battlerAtk].type3 | 0x80; } attackerAbility = GetBattlerAbility(battlerAtk); diff --git a/src/battle_message.c b/src/battle_message.c index 590bbabc9..e5ba3d30b 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -648,6 +648,7 @@ static const u8 sText_Infestation[] = _("{B_DEF_NAME_WITH_PREFIX} has been affli 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}!"); static const u8 sText_BestowItemGiving[] = _("{B_DEF_NAME_WITH_PREFIX} received {B_LAST_ITEM}\nfrom {B_ATK_NAME_WITH_PREFIX}!"); +static const u8 sText_ThirdTypeAdded[] = _("{B_BUFF1} type was added to\n{B_DEF_NAME_WITH_PREFIX}!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { @@ -1150,6 +1151,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = sText_NoEffectOnTarget, sText_BurstingFlames, sText_BestowItemGiving, + sText_ThirdTypeAdded, }; const u16 gTerrainStringIds[] = diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d632677f0..39af970da 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7127,6 +7127,18 @@ static void atk76_various(void) gBattleCommunication[MULTISTRING_CHOOSER] = 5; } break; + case VARIOUS_TRY_THIRD_TYPE: + if (IS_BATTLER_OF_TYPE(gActiveBattler, gBattleMoves[gCurrentMove].argument)) + { + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + } + else + { + gBattleMons[gActiveBattler].type3 = gBattleMoves[gCurrentMove].argument; + PREPARE_TYPE_BUFFER(gBattleTextBuff1, gBattleMoves[gCurrentMove].argument); + gBattlescriptCurrInstr += 7; + } + return; } gBattlescriptCurrInstr += 3; diff --git a/src/battle_util.c b/src/battle_util.c index 49da1613e..7dffd85f3 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5483,6 +5483,9 @@ static u16 CalcTypeEffectivenessMultiplierInternal(u16 move, u8 moveType, u8 bat MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, gBattleMons[battlerDef].type1, atkAbility); if (gBattleMons[battlerDef].type2 != gBattleMons[battlerDef].type1) MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, gBattleMons[battlerDef].type2, atkAbility); + if (gBattleMons[battlerDef].type3 != TYPE_MYSTERY && gBattleMons[battlerDef].type3 != gBattleMons[battlerDef].type2 + && gBattleMons[battlerDef].type3 != gBattleMons[battlerDef].type1) + MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, gBattleMons[battlerDef].type3, atkAbility); if (moveType == TYPE_GROUND && !IsBattlerGrounded(battlerDef)) { diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 936d2e76c..aa023a921 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -6817,7 +6817,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .split = SPLIT_PHYSICAL, }, { // MOVE_TRICK_OR_TREAT - .effect = EFFECT_PLACEHOLDER, // Needs a custom move effect + .effect = EFFECT_THIRD_TYPE, .power = 0, .type = TYPE_GHOST, .accuracy = 100, @@ -6827,6 +6827,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .priority = 0, .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED, .split = SPLIT_STATUS, + .argument = TYPE_GHOST, }, { // MOVE_NOBLE_ROAR .effect = EFFECT_NOBLE_ROAR, @@ -6865,7 +6866,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .split = SPLIT_SPECIAL, }, { // MOVE_FOREST_S_CURSE - .effect = EFFECT_PLACEHOLDER, // Needs a custom move effect + .effect = EFFECT_THIRD_TYPE, .power = 0, .type = TYPE_GRASS, .accuracy = 100, @@ -6875,6 +6876,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .priority = 0, .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED, .split = SPLIT_STATUS, + .argument = TYPE_GRASS, }, { // MOVE_PETAL_BLIZZARD .effect = EFFECT_HIT,