Add Tera Starstorm move + make Tera Blast displayed type reflect current type due to tera state (#4447)
* Add Tera Starstorm move + make Tera Blast/Tera Starstorm displayed type reflect tera type * Ooops * Curse tests
This commit is contained in:
parent
2648618c04
commit
64b28124fb
@ -351,6 +351,7 @@ enum {
|
||||
EFFECT_LAST_RESPECTS,
|
||||
EFFECT_TIDY_UP,
|
||||
EFFECT_TERA_BLAST,
|
||||
EFFECT_TERA_STARSTORM,
|
||||
NUM_BATTLE_MOVE_EFFECTS,
|
||||
};
|
||||
|
||||
|
||||
@ -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)
|
||||
{
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
mon = &GetSideParty(GetBattlerSide(battler))[gBattlerPartyIndexes[battler]];
|
||||
speciesId = GetMonData(mon, MON_DATA_SPECIES);
|
||||
if (gBattleStruct->tera.playerSelect || IsTerastallized(battler))
|
||||
type = GetBattlerTeraType(battler);
|
||||
}
|
||||
else if (moveInfo->moves[gMoveSelectionCursor[battler]] == MOVE_IVY_CUDGEL)
|
||||
{
|
||||
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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
@ -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);
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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:
|
||||
@ -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)
|
||||
@ -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);
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
},
|
||||
};
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
36
test/battle/move_effect/curse.c
Normal file
36
test/battle/move_effect/curse.c
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user