Skip to content

Commit

Permalink
Add Tera Starstorm move + make Tera Blast displayed type reflect curr…
Browse files Browse the repository at this point in the history
…ent type due to tera state (#4447)

* Add Tera Starstorm move + make Tera Blast/Tera Starstorm displayed type reflect tera type

* Ooops

* Curse tests
  • Loading branch information
kittenchilly committed Apr 27, 2024
1 parent 2648618 commit 64b2812
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 48 deletions.
1 change: 1 addition & 0 deletions include/constants/battle_move_effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ enum {
EFFECT_LAST_RESPECTS,
EFFECT_TIDY_UP,
EFFECT_TERA_BLAST,
EFFECT_TERA_STARSTORM,
NUM_BATTLE_MOVE_EFFECTS,
};

Expand Down
37 changes: 18 additions & 19 deletions src/battle_controller_player.c
Original file line number Diff line number Diff line change
Expand Up @@ -693,17 +693,8 @@ static void HandleInputChooseMove(u32 battler)
if (JOY_NEW(A_BUTTON))
{
PlaySE(SE_SELECT);
if (moveInfo->moves[gMoveSelectionCursor[battler]] == MOVE_CURSE)
{
if (moveInfo->monType1 != TYPE_GHOST && moveInfo->monType2 != TYPE_GHOST && moveInfo->monType3 != TYPE_GHOST)
moveTarget = MOVE_TARGET_USER;
else
moveTarget = MOVE_TARGET_SELECTED;
}
else
{
moveTarget = GetBattlerMoveTargetType(battler, moveInfo->moves[gMoveSelectionCursor[battler]]);
}

moveTarget = GetBattlerMoveTargetType(battler, moveInfo->moves[gMoveSelectionCursor[battler]]);

if (gBattleStruct->zmove.viewing)
{
Expand Down Expand Up @@ -931,6 +922,7 @@ static void HandleInputChooseMove(u32 battler)
{
gBattleStruct->tera.playerSelect ^= 1;
ChangeTeraTriggerSprite(gBattleStruct->tera.triggerSpriteId, gBattleStruct->tera.playerSelect);
MoveSelectionDisplayMoveType(battler); // For Tera Blast / Tera Starstorm
PlaySE(SE_SELECT);
}
}
Expand Down Expand Up @@ -1748,25 +1740,32 @@ static void MoveSelectionDisplayMoveType(u32 battler)
u8 *txtPtr, *end;
u8 type;
u32 speciesId;
struct Pokemon *mon;
struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct *)(&gBattleResources->bufferA[battler][4]);

txtPtr = StringCopy(gDisplayedStringBattle, gText_MoveInterfaceType);

if (moveInfo->moves[gMoveSelectionCursor[battler]] == MOVE_IVY_CUDGEL)
type = gMovesInfo[moveInfo->moves[gMoveSelectionCursor[battler]]].type;

if (moveInfo->moves[gMoveSelectionCursor[battler]] == MOVE_TERA_BLAST)
{
if (gBattleStruct->tera.playerSelect || IsTerastallized(battler))
type = GetBattlerTeraType(battler);
}
else if (moveInfo->moves[gMoveSelectionCursor[battler]] == MOVE_IVY_CUDGEL)
{
mon = &GetSideParty(GetBattlerSide(battler))[gBattlerPartyIndexes[battler]];
speciesId = GetMonData(mon, MON_DATA_SPECIES);
speciesId = gBattleMons[battler].species;

if (speciesId == SPECIES_OGERPON_WELLSPRING_MASK || speciesId == SPECIES_OGERPON_WELLSPRING_MASK_TERA
|| speciesId == SPECIES_OGERPON_HEARTHFLAME_MASK || speciesId == SPECIES_OGERPON_HEARTHFLAME_MASK_TERA
|| speciesId == SPECIES_OGERPON_CORNERSTONE_MASK || speciesId == SPECIES_OGERPON_CORNERSTONE_MASK_TERA)
type = gBattleMons[battler].type2;
else
type = gMovesInfo[MOVE_IVY_CUDGEL].type;
}
else
type = gMovesInfo[moveInfo->moves[gMoveSelectionCursor[battler]]].type;
else if (moveInfo->moves[gMoveSelectionCursor[battler]] == MOVE_TERA_STARSTORM)
{
if (gBattleMons[battler].species == SPECIES_TERAPAGOS_STELLAR
|| (gBattleStruct->tera.playerSelect && gBattleMons[battler].species == SPECIES_TERAPAGOS_TERASTAL))
type = TYPE_STELLAR;
}

end = StringCopy(txtPtr, gTypesInfo[type].name);
PrependFontIdToFit(txtPtr, end, FONT_NORMAL, WindowWidthPx(B_WIN_MOVE_TYPE) - 25);
Expand Down
12 changes: 1 addition & 11 deletions src/battle_gfx_sfx_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,17 +263,7 @@ u16 ChooseMoveAndTargetInBattlePalace(u32 battler)
}
}

if (moveInfo->moves[chosenMoveId] == MOVE_CURSE)
{
if (moveInfo->monType1 != TYPE_GHOST && moveInfo->monType2 != TYPE_GHOST && moveInfo->monType3 != TYPE_GHOST)
moveTarget = MOVE_TARGET_USER;
else
moveTarget = MOVE_TARGET_SELECTED;
}
else
{
moveTarget = GetBattlerMoveTargetType(battler, moveInfo->moves[chosenMoveId]);
}
moveTarget = GetBattlerMoveTargetType(battler, moveInfo->moves[chosenMoveId]);

if (moveTarget & MOVE_TARGET_USER)
chosenMoveId |= (battler << 8);
Expand Down
7 changes: 6 additions & 1 deletion src/battle_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5341,7 +5341,7 @@ static void PopulateArrayWithBattlers(u8 *battlers)
static bool32 TryDoGimmicksBeforeMoves(void)
{
if (!(gHitMarker & HITMARKER_RUN)
&& (gBattleStruct->mega.toEvolve || gBattleStruct->burst.toBurst
&& (gBattleStruct->mega.toEvolve || gBattleStruct->burst.toBurst
|| gBattleStruct->dynamax.toDynamax || gBattleStruct->tera.toTera))
{
u32 i, battler;
Expand Down Expand Up @@ -6072,6 +6072,10 @@ void SetTypeBeforeUsingMove(u32 move, u32 battlerAtk)
{
gBattleStruct->dynamicMoveType = GetBattlerTeraType(battlerAtk) | F_DYNAMIC_TYPE_SET;
}
else if (gMovesInfo[move].effect == EFFECT_TERA_STARSTORM && gBattleMons[battlerAtk].species == SPECIES_TERAPAGOS_STELLAR)
{
gBattleStruct->dynamicMoveType = TYPE_STELLAR | F_DYNAMIC_TYPE_SET;
}

attackerAbility = GetBattlerAbility(battlerAtk);

Expand All @@ -6081,6 +6085,7 @@ void SetTypeBeforeUsingMove(u32 move, u32 battlerAtk)
&& gMovesInfo[move].effect != EFFECT_CHANGE_TYPE_ON_ITEM
&& gMovesInfo[move].effect != EFFECT_NATURAL_GIFT
&& !(gMovesInfo[move].effect == EFFECT_TERA_BLAST && IsTerastallized(battlerAtk))
&& !(gMovesInfo[move].effect == EFFECT_TERA_STARSTORM && gBattleMons[battlerAtk].species == SPECIES_TERAPAGOS_STELLAR)
&& ((attackerAbility == ABILITY_PIXILATE && (ateType = TYPE_FAIRY))
|| (attackerAbility == ABILITY_REFRIGERATE && (ateType = TYPE_ICE))
|| (attackerAbility == ABILITY_AERILATE && (ateType = TYPE_FLYING))
Expand Down
3 changes: 2 additions & 1 deletion src/battle_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -16735,7 +16735,8 @@ void BS_AllySwitchFailChance(void)
void BS_SetPhotonGeyserCategory(void)
{
NATIVE_ARGS();
if (!(gMovesInfo[gCurrentMove].effect == EFFECT_TERA_BLAST && !IsTerastallized(gBattlerAttacker)))
if (!(gMovesInfo[gCurrentMove].effect == EFFECT_TERA_BLAST && !IsTerastallized(gBattlerAttacker))
&& !(gMovesInfo[gCurrentMove].effect == EFFECT_TERA_STARSTORM && gBattleMons[gBattlerAttacker].species != SPECIES_TERAPAGOS_STELLAR))
gBattleStruct->swapDamageCategory = (GetCategoryBasedOnStats(gBattlerAttacker) == DAMAGE_CATEGORY_PHYSICAL);
gBattlescriptCurrInstr = cmd->nextInstr;
}
Expand Down
24 changes: 12 additions & 12 deletions src/battle_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -8043,10 +8043,6 @@ u32 GetMoveTarget(u16 move, u8 setTarget)
else
moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, move);

// Special cases
if (move == MOVE_CURSE && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST))
moveTarget = MOVE_TARGET_USER;

switch (moveTarget)
{
case MOVE_TARGET_SELECTED:
Expand Down Expand Up @@ -10104,6 +10100,8 @@ static inline void MulByTypeEffectiveness(uq4_12_t *modifier, u32 move, u32 move
mod = UQ_4_12(1.0);
if (moveType == TYPE_FIRE && gDisableStructs[battlerDef].tarShot)
mod = UQ_4_12(2.0);
if (moveType == TYPE_STELLAR && IsTerastallized(battlerDef))
mod = UQ_4_12(2.0);

// B_WEATHER_STRONG_WINDS weakens Super Effective moves against Flying-type Pokémon
if (gBattleWeather & B_WEATHER_STRONG_WINDS && WEATHER_HAS_EFFECT)
Expand Down Expand Up @@ -10220,16 +10218,12 @@ uq4_12_t CalcTypeEffectivenessMultiplier(u32 move, u32 moveType, u32 battlerAtk,
{
uq4_12_t modifier = UQ_4_12(1.0);

if (move != MOVE_STRUGGLE && moveType != TYPE_MYSTERY && moveType != TYPE_STELLAR)
if (move != MOVE_STRUGGLE && moveType != TYPE_MYSTERY)
{
modifier = CalcTypeEffectivenessMultiplierInternal(move, moveType, battlerAtk, battlerDef, recordAbilities, modifier, defAbility);
if (gMovesInfo[move].effect == EFFECT_TWO_TYPED_MOVE)
modifier = CalcTypeEffectivenessMultiplierInternal(move, gMovesInfo[move].argument, battlerAtk, battlerDef, recordAbilities, modifier, defAbility);
}
else if (moveType == TYPE_STELLAR)
{
modifier = IsTerastallized(battlerDef) ? UQ_4_12(2.0) : UQ_4_12(1.0);
}

if (recordAbilities)
UpdateMoveResultFlags(modifier);
Expand Down Expand Up @@ -11173,11 +11167,17 @@ bool32 IsBattlerWeatherAffected(u32 battler, u32 weatherFlags)
// Possible return values are defined in battle.h following MOVE_TARGET_SELECTED
u32 GetBattlerMoveTargetType(u32 battler, u32 move)
{
if (gMovesInfo[move].effect == EFFECT_EXPANDING_FORCE
if (move == MOVE_CURSE
&& !IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
return MOVE_TARGET_USER;
else if (gMovesInfo[move].effect == EFFECT_EXPANDING_FORCE
&& IsBattlerTerrainAffected(battler, STATUS_FIELD_PSYCHIC_TERRAIN))
return MOVE_TARGET_BOTH;
else
return gMovesInfo[move].target;
else if (gMovesInfo[move].effect == EFFECT_TERA_STARSTORM
&& gBattleMons[battler].species == SPECIES_TERAPAGOS_STELLAR)
return MOVE_TARGET_BOTH;

return gMovesInfo[move].target;
}

bool32 CanTargetBattler(u32 battlerAtk, u32 battlerDef, u16 move)
Expand Down
6 changes: 6 additions & 0 deletions src/data/battle_move_effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -2236,4 +2236,10 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
.battleScript = BattleScript_EffectPhotonGeyser,
.battleTvScore = 0, // TODO: Assign points
},

[EFFECT_TERA_STARSTORM] =
{
.battleScript = BattleScript_EffectPhotonGeyser,
.battleTvScore = 0, // TODO: Assign points
},
};
6 changes: 3 additions & 3 deletions src/data/moves_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -19563,12 +19563,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.description = COMPOUND_STRING(
"Damages all opponents if user is\n"
"Stellar form Terapagos."),
.effect = EFFECT_PLACEHOLDER, //EFFECT_TERA_STARSTORM
.effect = EFFECT_TERA_STARSTORM,
.power = 120,
.type = TYPE_NORMAL, // Stellar type if used by Terapagos-Stellar
.type = TYPE_NORMAL,
.accuracy = 100,
.pp = 5,
.target = MOVE_TARGET_SELECTED, // MOVE_TARGET_BOTH if used by Terapagos-Stellar
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_SPECIAL,
.assistBanned = TRUE,
Expand Down
2 changes: 1 addition & 1 deletion src/data/pokemon/form_species_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -2169,7 +2169,7 @@ static const u16 sOgerponFormSpeciesIdTable[] = {
static const u16 sTerapagosFormSpeciesIdTable[] = {
SPECIES_TERAPAGOS_NORMAL,
SPECIES_TERAPAGOS_TERASTAL,
#if P_TERA_FORMS
#if P_TERA_FORMS
SPECIES_TERAPAGOS_STELLAR,
#endif
FORM_SPECIES_END,
Expand Down
36 changes: 36 additions & 0 deletions test/battle/move_effect/curse.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "global.h"
#include "test/battle.h"

ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_CURSE].effect == EFFECT_CURSE);
}

SINGLE_BATTLE_TEST("Curse lowers Speed, raises Attack, and raises Defense when used by non-Ghost-types")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_CURSE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_CURSE, player);
MESSAGE("Wobbuffet's Speed fell!");
MESSAGE("Wobbuffet's Attack rose!");
MESSAGE("Wobbuffet's Defense rose!");
}
}

SINGLE_BATTLE_TEST("Curse cuts the user's HP in half when used by Ghost-types")
{
GIVEN {
PLAYER(SPECIES_MISDREAVUS);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_CURSE); }
} SCENE {
s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CURSE, player);
HP_BAR(player, hp: maxHP / 2);
}
}

0 comments on commit 64b2812

Please sign in to comment.