terastal mechanically integrated
BIN
graphics/battle_interface/bug_indicator.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
graphics/battle_interface/dark_indicator.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
graphics/battle_interface/dragon_indicator.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
graphics/battle_interface/electric_indicator.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
graphics/battle_interface/fairy_indicator.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
graphics/battle_interface/fighting_indicator.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
graphics/battle_interface/fire_indicator.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
graphics/battle_interface/flying_indicator.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
graphics/battle_interface/ghost_indicator.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
graphics/battle_interface/grass_indicator.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
graphics/battle_interface/ground_indicator.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
graphics/battle_interface/ice_indicator.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
graphics/battle_interface/normal_indicator.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
graphics/battle_interface/poison_indicator.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
graphics/battle_interface/psychic_indicator.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
graphics/battle_interface/rock_indicator.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
graphics/battle_interface/steel_indicator.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
graphics/battle_interface/stellar_indicator.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
19
graphics/battle_interface/tera_indicator.pal
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
0 0 0
|
||||
98 83 124
|
||||
207 63 109
|
||||
83 105 175
|
||||
80 144 216
|
||||
216 208 179
|
||||
254 115 121
|
||||
148 155 163
|
||||
99 188 91
|
||||
147 192 47
|
||||
255 156 85
|
||||
199 182 140
|
||||
113 206 198
|
||||
117 206 192
|
||||
245 210 55
|
||||
255 255 255
|
||||
BIN
graphics/battle_interface/tera_trigger.png
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
graphics/battle_interface/water_indicator.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
|
|
@ -14,7 +14,7 @@
|
|||
#include "pokeball.h"
|
||||
// #include "battle_debug.h"
|
||||
#include "battle_dynamax.h"
|
||||
// #include "battle_terastal.h"
|
||||
#include "battle_terastal.h"
|
||||
#include "random.h" // for rng_value_t
|
||||
|
||||
// Helper for accessing command arguments and advancing gBattlescriptCurrInstr.
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ enum {
|
|||
#define RET_MEGA_EVOLUTION (1 << 7)
|
||||
#define RET_ULTRA_BURST (1 << 6)
|
||||
#define RET_DYNAMAX (1 << 5)
|
||||
#define RET_TERASTAL (1 << 4)
|
||||
|
||||
struct UnusedControllerStruct
|
||||
{
|
||||
|
|
|
|||
|
|
@ -60,12 +60,36 @@ enum
|
|||
#define TAG_DYNAMAX_TRIGGER_TILE 0xD77D
|
||||
#define TAG_DYNAMAX_INDICATOR_TILE 0xD77E
|
||||
|
||||
#define TAG_NORMAL_INDICATOR_TILE 0xD77F
|
||||
#define TAG_FIGHTING_INDICATOR_TILE 0xD780
|
||||
#define TAG_FLYING_INDICATOR_TILE 0xD781
|
||||
#define TAG_POISON_INDICATOR_TILE 0xD782
|
||||
#define TAG_GROUND_INDICATOR_TILE 0xD783
|
||||
#define TAG_ROCK_INDICATOR_TILE 0xD784
|
||||
#define TAG_BUG_INDICATOR_TILE 0xD785
|
||||
#define TAG_GHOST_INDICATOR_TILE 0xD786
|
||||
#define TAG_STEEL_INDICATOR_TILE 0xD787
|
||||
// empty spot for TYPE_MYSTERY
|
||||
#define TAG_FIRE_INDICATOR_TILE 0xD789
|
||||
#define TAG_WATER_INDICATOR_TILE 0xD78A
|
||||
#define TAG_GRASS_INDICATOR_TILE 0xD78B
|
||||
#define TAG_ELECTRIC_INDICATOR_TILE 0xD78C
|
||||
#define TAG_PSYCHIC_INDICATOR_TILE 0xD78D
|
||||
#define TAG_ICE_INDICATOR_TILE 0xD78E
|
||||
#define TAG_DRAGON_INDICATOR_TILE 0xD78F
|
||||
#define TAG_DARK_INDICATOR_TILE 0xD790
|
||||
#define TAG_FAIRY_INDICATOR_TILE 0xD791
|
||||
#define TAG_STELLAR_INDICATOR_TILE 0xD792
|
||||
#define TAG_TERA_TRIGGER_TILE 0xD793
|
||||
|
||||
#define TAG_MEGA_TRIGGER_PAL 0xD777
|
||||
#define TAG_MEGA_INDICATOR_PAL 0xD778
|
||||
#define TAG_MISC_INDICATOR_PAL 0xD779 // Alpha, Omega, and Dynamax indicators use the same palette as each of them only uses 4 different colors.
|
||||
#define TAG_ZMOVE_TRIGGER_PAL 0xD77B
|
||||
#define TAG_BURST_TRIGGER_PAL 0xD77C
|
||||
#define TAG_DYNAMAX_TRIGGER_PAL 0xD77D
|
||||
#define TAG_TERA_INDICATOR_PAL 0xD77E
|
||||
#define TAG_TERA_TRIGGER_PAL 0xD77F
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
@ -94,6 +118,7 @@ void DestoryHealthboxSprite(u8 healthboxSpriteId);
|
|||
void DummyBattleInterfaceFunc(u8 healthboxSpriteId, bool8 isDoubleBattleBankOnly);
|
||||
void UpdateOamPriorityInAllHealthboxes(u8 priority);
|
||||
void InitBattlerHealthboxCoords(u8 battlerId);
|
||||
void GetBattlerHealthboxCoords(u8 battler, s16 *x, s16 *y);
|
||||
void UpdateHpTextInHealthbox(u32 healthboxSpriteId, u32 maxOrCurrent, s16 currHp, s16 maxHp);
|
||||
void SwapHpBarsWithHpText(void);
|
||||
u8 CreatePartyStatusSummarySprites(u8 battlerId, struct HpAndStatus *partyInfo, u8 isSwitchingMons, bool8 isBattleStart);
|
||||
|
|
|
|||
|
|
@ -810,6 +810,8 @@ extern const u8 BattleScript_IllusionOff[];
|
|||
extern const u8 BattleScript_DancerActivates[];
|
||||
extern const u8 BattleScript_AttackerFormChange[];
|
||||
extern const u8 BattleScript_AttackerFormChangeEnd3[];
|
||||
extern const u8 BattleScript_AttackerFormChangeWithString[];
|
||||
extern const u8 BattleScript_AttackerFormChangeWithStringEnd3[];
|
||||
extern const u8 BattleScript_TargetFormChange[];
|
||||
extern const u8 BattleScript_AnticipationActivates[];
|
||||
extern const u8 BattleScript_SlowStartEnds[];
|
||||
|
|
@ -827,6 +829,7 @@ extern const u8 BattleScript_CheekPouchActivates[];
|
|||
extern const u8 BattleScript_TotemVar[];
|
||||
extern const u8 BattleScript_TotemFlaredToLife[];
|
||||
extern const u8 BattleScript_AnnounceAirLockCloudNine[];
|
||||
extern const u8 BattleScript_ActivateTeraformZero[];
|
||||
extern const u8 BattleScript_BattlerAbilityStatRaiseOnSwitchIn[];
|
||||
extern const u8 BattleScript_CottonDownActivates[];
|
||||
extern const u8 BattleScript_BallFetch[];
|
||||
|
|
@ -880,6 +883,7 @@ extern const u8 BattleScript_PastelVeilActivates[];
|
|||
extern const u8 BattleScript_MimicryActivatesEnd3[];
|
||||
extern const u8 BattleScript_ApplyMimicry[];
|
||||
extern const u8 BattleScript_AttackerFormChangeEnd3NoPopup[];
|
||||
extern const u8 BattleScript_AttackerFormChangeWithStringEnd3NoPopup[];
|
||||
extern const u8 BattleScript_AttackerFormChangeMoveEffect[];
|
||||
extern const u8 BattleScript_BothCanNoLongerEscape[];
|
||||
extern const u8 BattleScript_OctolockEndTurn[];
|
||||
|
|
|
|||
31
include/battle_terastal.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef GUARD_BATTLE_TERASTAL_H
|
||||
#define GUARD_BATTLE_TERASTAL_H
|
||||
|
||||
void PrepareBattlerForTera(u32 battler);
|
||||
void ApplyBattlerVisualsForTeraAnim(u32 battler);
|
||||
bool32 CanTerastallize(u32 battler);
|
||||
u32 GetBattlerTeraType(u32 battler);
|
||||
bool32 IsTerastallized(u32 battler);
|
||||
void ExpendTypeStellarBoost(u32 battler, u32 type);
|
||||
bool32 IsTypeStellarBoosted(u32 battler, u32 type);
|
||||
uq4_12_t GetTeraMultiplier(u32 battler, u32 type);
|
||||
|
||||
u16 GetTeraTypeRGB(u32 type);
|
||||
|
||||
void ChangeTeraTriggerSprite(u8 spriteId, u8 animId);
|
||||
void CreateTeraTriggerSprite(u8 battler, u8 palId);
|
||||
bool32 IsTeraTriggerSpriteActive(void);
|
||||
void HideTeraTriggerSprite(void);
|
||||
void DestroyTeraTriggerSprite(void);
|
||||
|
||||
void TeraIndicator_LoadSpriteGfx(void);
|
||||
bool32 TeraIndicator_ShouldBeInvisible(u32 battler);
|
||||
u8 TeraIndicator_GetSpriteId(u32 healthboxSpriteId);
|
||||
void TeraIndicator_SetVisibilities(u32 healthboxId, bool32 invisible);
|
||||
void TeraIndicator_UpdateOamPriorities(u32 healthboxId, u32 oamPriority);
|
||||
void TeraIndicator_UpdateLevel(u32 healthboxId, u32 level);
|
||||
void TeraIndicator_CreateSprite(u32 battler, u32 healthboxSpriteId);
|
||||
void TeraIndicator_DestroySprite(u32 healthboxSpriteId);
|
||||
void TeraIndicator_UpdateType(u32 battler, u32 healthboxSpriteId);
|
||||
|
||||
#endif
|
||||
|
|
@ -24,6 +24,8 @@
|
|||
// param2: time of day to check, optional.
|
||||
// - DAY if Form change that activates in the daytime.
|
||||
// - NIGHT if Form change that activates at nighttime.
|
||||
// - 0 if irrelevant, but param3 is necessary.
|
||||
// param3: illegal statuses to have, optional.
|
||||
#define FORM_CHANGE_ITEM_USE 2
|
||||
|
||||
// TODO: Form change that activates when the Pokémon learns or forgets the move.
|
||||
|
|
@ -61,7 +63,7 @@
|
|||
#define FORM_CHANGE_END_BATTLE_TERRAIN 8
|
||||
|
||||
// Form change that activates when the Pokémon is switched out in battle.
|
||||
// - No parameters.
|
||||
// param1: ability to check, optional
|
||||
#define FORM_CHANGE_BATTLE_SWITCH 9
|
||||
|
||||
// Form change that activates when the Pokémon's HP % passes a certain threshold.
|
||||
|
|
@ -121,6 +123,10 @@
|
|||
#define FORM_CHANGE_STATUS 20
|
||||
|
||||
// Form change that activates after move is used. Currently only used for activating Gulp Missile.
|
||||
#define FORM_CHANGE_HIT_BY_MOVE 21
|
||||
#define FORM_CHANGE_HIT_BY_MOVE 21
|
||||
|
||||
// Form change that activates when terastallized as as a specific type
|
||||
// param1: tera type
|
||||
#define FORM_CHANGE_BATTLE_TERASTALLIZATION 22
|
||||
|
||||
#endif // GUARD_CONSTANTS_FORM_CHANGE_TYPES_H
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "battle_controllers.h"
|
||||
#include "battle_setup.h"
|
||||
#include "battle_z_move.h"
|
||||
// #include "battle_terastal.h"
|
||||
#include "battle_terastal.h"
|
||||
#include "data.h"
|
||||
// #include "debug.h"
|
||||
#include "event_data.h"
|
||||
|
|
@ -403,7 +403,7 @@ static void SetBattlerAiGimmickData(u32 battler, struct AiLogicData *aiData)
|
|||
if (party != NULL)
|
||||
{
|
||||
aiData->shouldDynamax[battler] = CanDynamax(battler) && (party[isSecondTrainer ? gBattlerPartyIndexes[battler] - MULTI_PARTY_SIZE : gBattlerPartyIndexes[battler]].shouldDynamax);
|
||||
aiData->shouldTerastal[battler] = FALSE; // TODO: Tera CanTerastallize(battler) && (party[isSecondTrainer ? gBattlerPartyIndexes[battler] - MULTI_PARTY_SIZE : gBattlerPartyIndexes[battler]].shouldTerastal);
|
||||
aiData->shouldTerastal[battler] = CanTerastallize(battler) && (party[isSecondTrainer ? gBattlerPartyIndexes[battler] - MULTI_PARTY_SIZE : gBattlerPartyIndexes[battler]].shouldTerastal);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2440,11 +2440,11 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
switch (move)
|
||||
{
|
||||
case MOVE_TRICK_OR_TREAT:
|
||||
if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GHOST) || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove) /* || IsTerastallized(battlerDef) */) // TODO: Tera
|
||||
if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GHOST) || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove) || IsTerastallized(battlerDef))
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case MOVE_FORESTS_CURSE:
|
||||
if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS) || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove) /* || IsTerastallized(battlerDef) */) // TODO: Tera
|
||||
if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS) || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove) || IsTerastallized(battlerDef))
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
}
|
||||
|
|
@ -3006,7 +3006,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
case EFFECT_SOAK:
|
||||
if (atkPartnerAbility == ABILITY_WONDER_GUARD
|
||||
&& IS_BATTLER_OF_TYPE(battlerAtkPartner, TYPE_WATER)
|
||||
/* && !IsTerastallized(battlerAtkPartner) */) // TODO: Tera
|
||||
&& !IsTerastallized(battlerAtkPartner))
|
||||
{
|
||||
RETURN_SCORE_PLUS(WEAK_EFFECT);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -774,36 +774,42 @@ void UpdateOamPriorityInAllHealthboxes(u8 priority)
|
|||
}
|
||||
}
|
||||
|
||||
void InitBattlerHealthboxCoords(u8 battler)
|
||||
void GetBattlerHealthboxCoords(u8 battler, s16 *x, s16 *y)
|
||||
{
|
||||
s16 x = 0, y = 0;
|
||||
*x = 0, *y = 0;
|
||||
|
||||
if (!WhichBattleCoords(battler))
|
||||
{
|
||||
if (GetBattlerSide(battler) != B_SIDE_PLAYER)
|
||||
x = 44, y = 30;
|
||||
*x = 44, *y = 30;
|
||||
else
|
||||
x = 158, y = 88;
|
||||
*x = 158, *y = 88;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (GetBattlerPosition(battler))
|
||||
{
|
||||
case B_POSITION_PLAYER_LEFT:
|
||||
x = 159, y = 75;
|
||||
*x = 159, *y = 75;
|
||||
break;
|
||||
case B_POSITION_PLAYER_RIGHT:
|
||||
x = 171, y = 100;
|
||||
*x = 171, *y = 100;
|
||||
break;
|
||||
case B_POSITION_OPPONENT_LEFT:
|
||||
x = 44, y = 19;
|
||||
*x = 44, *y = 19;
|
||||
break;
|
||||
case B_POSITION_OPPONENT_RIGHT:
|
||||
x = 32, y = 44;
|
||||
*x = 32, *y = 44;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InitBattlerHealthboxCoords(u8 battler)
|
||||
{
|
||||
s16 x, y;
|
||||
|
||||
GetBattlerHealthboxCoords(battler, &x, &y);
|
||||
UpdateSpritePos(gHealthboxSpriteIds[battler], x, y);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1175,7 +1175,7 @@ bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType)
|
|||
&& (gBattleMons[battler].type1 != moveType || gBattleMons[battler].type2 != moveType
|
||||
|| (gBattleMons[battler].type3 != moveType && gBattleMons[battler].type3 != TYPE_MYSTERY))
|
||||
&& move != MOVE_STRUGGLE
|
||||
/* && !IsTerastallized(battler) */) // TODO: Tera
|
||||
&& !IsTerastallized(battler))
|
||||
{
|
||||
SET_BATTLER_TYPE(battler, moveType);
|
||||
return TRUE;
|
||||
|
|
@ -1183,19 +1183,18 @@ bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
// TODO: Tera
|
||||
// bool32 ShouldTeraShellDistortTypeMatchups(u32 move, u32 battlerDef)
|
||||
// {
|
||||
// if (!(gBattleStruct->distortedTypeMatchups & gBitTable[battlerDef])
|
||||
// && GetBattlerAbility(battlerDef) == ABILITY_TERA_SHELL
|
||||
// && gBattleMons[battlerDef].species == SPECIES_TERAPAGOS_TERASTAL
|
||||
// && !IS_MOVE_STATUS(move)
|
||||
// && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
|
||||
// && gBattleMons[battlerDef].hp == gBattleMons[battlerDef].maxHP)
|
||||
// return TRUE;
|
||||
bool32 ShouldTeraShellDistortTypeMatchups(u32 move, u32 battlerDef)
|
||||
{
|
||||
if (!(gBattleStruct->distortedTypeMatchups & gBitTable[battlerDef])
|
||||
&& GetBattlerAbility(battlerDef) == ABILITY_TERA_SHELL
|
||||
&& gBattleMons[battlerDef].species == SPECIES_TERAPAGOS_TERASTAL
|
||||
&& !IS_MOVE_STATUS(move)
|
||||
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
|
||||
&& gBattleMons[battlerDef].hp == gBattleMons[battlerDef].maxHP)
|
||||
return TRUE;
|
||||
|
||||
// return FALSE;
|
||||
// }
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 IsMoveNotAllowedInSkyBattles(u32 move)
|
||||
{
|
||||
|
|
@ -1874,14 +1873,13 @@ static void Cmd_ppreduce(void)
|
|||
gHitMarker &= ~HITMARKER_NO_PPDEDUCT;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
|
||||
// TODO: Tera
|
||||
// if (ShouldTeraShellDistortTypeMatchups(gCurrentMove, gBattlerTarget))
|
||||
// {
|
||||
// gBattleStruct->distortedTypeMatchups |= gBitTable[gBattlerTarget];
|
||||
// gBattlerAbility = gBattlerTarget;
|
||||
// BattleScriptPushCursor();
|
||||
// gBattlescriptCurrInstr = BattleScript_TeraShellDistortingTypeMatchups;
|
||||
// }
|
||||
if (ShouldTeraShellDistortTypeMatchups(gCurrentMove, gBattlerTarget))
|
||||
{
|
||||
gBattleStruct->distortedTypeMatchups |= gBitTable[gBattlerTarget];
|
||||
gBattlerAbility = gBattlerTarget;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_TeraShellDistortingTypeMatchups;
|
||||
}
|
||||
}
|
||||
|
||||
// The chance is 1/N for each stage.
|
||||
|
|
@ -3829,16 +3827,15 @@ void SetMoveEffect(bool32 primary, bool32 certain)
|
|||
gBattlescriptCurrInstr = BattleScript_EffectPsychicNoise;
|
||||
}
|
||||
break;
|
||||
// TODO: Tera
|
||||
// case MOVE_EFFECT_TERA_BLAST:
|
||||
// if (IsTerastallized(gEffectBattler)
|
||||
// && GetBattlerTeraType(gEffectBattler) == TYPE_STELLAR
|
||||
// && !NoAliveMonsForEitherParty())
|
||||
// {
|
||||
// BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
// gBattlescriptCurrInstr = BattleScript_LowerAtkSpAtk;
|
||||
// }
|
||||
// break;
|
||||
case MOVE_EFFECT_TERA_BLAST:
|
||||
if (IsTerastallized(gEffectBattler)
|
||||
&& GetBattlerTeraType(gEffectBattler) == TYPE_STELLAR
|
||||
&& !NoAliveMonsForEitherParty())
|
||||
{
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_LowerAtkSpAtk;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9669,7 +9666,7 @@ static void Cmd_various(void)
|
|||
VARIOUS_ARGS(const u8 *failInstr);
|
||||
if ((GetBattlerType(gBattlerTarget, 0, FALSE) == gMovesInfo[gCurrentMove].type
|
||||
&& GetBattlerType(gBattlerTarget, 1, FALSE) == gMovesInfo[gCurrentMove].type)
|
||||
/* || IsTerastallized(gBattlerTarget) */) // TODO: Tera
|
||||
|| IsTerastallized(gBattlerTarget))
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
|
|
@ -10002,7 +9999,7 @@ static void Cmd_various(void)
|
|||
case VARIOUS_TRY_THIRD_TYPE:
|
||||
{
|
||||
VARIOUS_ARGS(const u8 *failInstr);
|
||||
if (IS_BATTLER_OF_TYPE(battler, gMovesInfo[gCurrentMove].argument)/* || IsTerastallized(battler) */) // TODO: Tera
|
||||
if (IS_BATTLER_OF_TYPE(battler, gMovesInfo[gCurrentMove].argument) || IsTerastallized(battler))
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
|
|
@ -12111,12 +12108,11 @@ static void Cmd_tryconversiontypechange(void)
|
|||
u8 moveChecked = 0;
|
||||
u8 moveType = 0;
|
||||
|
||||
// TODO: Tera
|
||||
// if (IsTerastallized(gBattlerAttacker))
|
||||
// {
|
||||
// gBattlescriptCurrInstr = cmd->failInstr;
|
||||
// return;
|
||||
// }
|
||||
if (IsTerastallized(gBattlerAttacker))
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (B_UPDATED_CONVERSION >= GEN_6)
|
||||
{
|
||||
|
|
@ -12889,15 +12885,14 @@ static void Cmd_settypetorandomresistance(void)
|
|||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
// TODO: Tera
|
||||
// else if (IsTerastallized(gBattlerAttacker))
|
||||
// {
|
||||
// gBattlescriptCurrInstr = cmd->failInstr;
|
||||
// }
|
||||
// else if (gLastHitByType[gBattlerAttacker] == TYPE_STELLAR)
|
||||
// {
|
||||
// gBattlescriptCurrInstr = cmd->failInstr;
|
||||
// }
|
||||
else if (IsTerastallized(gBattlerAttacker))
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
else if (gLastHitByType[gBattlerAttacker] == TYPE_STELLAR)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 i, resistTypes = 0;
|
||||
|
|
@ -14848,7 +14843,7 @@ static void Cmd_settypetoterrain(void)
|
|||
break;
|
||||
}
|
||||
|
||||
if (!IS_BATTLER_OF_TYPE(gBattlerAttacker, terrainType) /* && !IsTerastallized(gBattlerAttacker) */) // TODO: Tera
|
||||
if (!IS_BATTLER_OF_TYPE(gBattlerAttacker, terrainType) && !IsTerastallized(gBattlerAttacker))
|
||||
{
|
||||
SET_BATTLER_TYPE(gBattlerAttacker, terrainType);
|
||||
PREPARE_TYPE_BUFFER(gBattleTextBuff1, terrainType);
|
||||
|
|
@ -16479,11 +16474,10 @@ void BS_TryReflectType(void)
|
|||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
// TODO: Tera
|
||||
// else if (IsTerastallized(gBattlerAttacker))
|
||||
// {
|
||||
// gBattlescriptCurrInstr = cmd->failInstr;
|
||||
// }
|
||||
else if (IsTerastallized(gBattlerAttacker))
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
else if (IS_BATTLER_TYPELESS(gBattlerTarget))
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
|
|
@ -16848,9 +16842,8 @@ void BS_AllySwitchFailChance(void)
|
|||
void BS_SetPhotonGeyserCategory(void)
|
||||
{
|
||||
NATIVE_ARGS();
|
||||
// TODO: Tera
|
||||
// if (!((gMovesInfo[gCurrentMove].effect == EFFECT_TERA_BLAST && !IsTerastallized(gBattlerAttacker))
|
||||
// || (gMovesInfo[gCurrentMove].effect == EFFECT_TERA_STARSTORM && !(IsTerastallized(gBattlerAttacker) && gBattleMons[gBattlerAttacker].species == SPECIES_TERAPAGOS_STELLAR))))
|
||||
if (!((gMovesInfo[gCurrentMove].effect == EFFECT_TERA_BLAST && !IsTerastallized(gBattlerAttacker))
|
||||
|| (gMovesInfo[gCurrentMove].effect == EFFECT_TERA_STARSTORM && !(IsTerastallized(gBattlerAttacker) && gBattleMons[gBattlerAttacker].species == SPECIES_TERAPAGOS_STELLAR))))
|
||||
gBattleStruct->swapDamageCategory = (GetCategoryBasedOnStats(gBattlerAttacker) == DAMAGE_CATEGORY_PHYSICAL);
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
|
@ -17047,8 +17040,7 @@ void BS_RemoveWeather(void)
|
|||
void BS_ApplyTerastallization(void)
|
||||
{
|
||||
NATIVE_ARGS();
|
||||
// TODO: Tera
|
||||
// ApplyBattlerVisualsForTeraAnim(gBattlerAttacker);
|
||||
ApplyBattlerVisualsForTeraAnim(gBattlerAttacker);
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
|
|
|
|||
775
src/battle_terastal.c
Normal file
|
|
@ -0,0 +1,775 @@
|
|||
#include "global.h"
|
||||
#include "battle.h"
|
||||
#include "battle_anim.h"
|
||||
#include "battle_controllers.h"
|
||||
#include "battle_interface.h"
|
||||
#include "battle_terastal.h"
|
||||
#include "event_data.h"
|
||||
#include "item.h"
|
||||
#include "palette.h"
|
||||
#include "pokemon.h"
|
||||
#include "safari_zone.h"
|
||||
#include "sprite.h"
|
||||
#include "util.h"
|
||||
#include "constants/abilities.h"
|
||||
#include "constants/hold_effects.h"
|
||||
#include "constants/rgb.h"
|
||||
|
||||
// Sets flags and variables upon a battler's Terastallization.
|
||||
void PrepareBattlerForTera(u32 battler)
|
||||
{
|
||||
u32 side = GetBattlerSide(battler);
|
||||
u32 index = gBattlerPartyIndexes[battler];
|
||||
|
||||
// Update TeraData fields.
|
||||
gBattleStruct->tera.isTerastallized[side] |= gBitTable[index];
|
||||
gBattleStruct->tera.alreadyTerastallized[battler] = TRUE;
|
||||
|
||||
// Remove Tera Orb charge.
|
||||
if (B_FLAG_TERA_ORB_CHARGED != 0
|
||||
&& (B_FLAG_TERA_ORB_NO_COST == 0 || !FlagGet(B_FLAG_TERA_ORB_NO_COST))
|
||||
&& side == B_SIDE_PLAYER
|
||||
&& !(gBattleTypeFlags & BATTLE_TYPE_DOUBLE && !IsPartnerMonFromSameTrainer(battler)))
|
||||
{
|
||||
FlagClear(B_FLAG_TERA_ORB_CHARGED);
|
||||
}
|
||||
}
|
||||
|
||||
// Applies palette blend and enables UI indicator after animation has played
|
||||
void ApplyBattlerVisualsForTeraAnim(u32 battler)
|
||||
{
|
||||
struct Pokemon *party = GetBattlerParty(battler);
|
||||
u32 index = gBattlerPartyIndexes[battler];
|
||||
|
||||
// Show indicator and do palette blend.
|
||||
UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], &party[index], HEALTHBOX_ALL);
|
||||
BlendPalette(OBJ_PLTT_ID(battler), 16, 8, GetTeraTypeRGB(GetBattlerTeraType(battler)));
|
||||
CpuCopy32(gPlttBufferFaded + OBJ_PLTT_ID(battler), gPlttBufferUnfaded + OBJ_PLTT_ID(battler), PLTT_SIZEOF(16));
|
||||
|
||||
// We apply the animation behind a white screen, so restore the blended color here to avoid a pop
|
||||
BlendPalette(OBJ_PLTT_ID(battler), 16, 16, RGB_WHITEALPHA);
|
||||
}
|
||||
|
||||
// Returns whether a battler can Terastallize.
|
||||
bool32 CanTerastallize(u32 battler)
|
||||
{
|
||||
u32 holdEffect = GetBattlerHoldEffect(battler, FALSE);
|
||||
|
||||
// Check if Player has Tera Orb and has charge.
|
||||
if (!CheckBagHasItem(ITEM_TERA_ORB, 1)
|
||||
|| !((B_FLAG_TERA_ORB_NO_COST != 0 && FlagGet(B_FLAG_TERA_ORB_NO_COST))
|
||||
|| (B_FLAG_TERA_ORB_CHARGED != 0 && FlagGet(B_FLAG_TERA_ORB_CHARGED)
|
||||
&& ((battler == B_POSITION_PLAYER_LEFT || (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) && battler == B_POSITION_PLAYER_RIGHT))))))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Check if Trainer has already Terastallized.
|
||||
if (gBattleStruct->tera.alreadyTerastallized[battler])
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
|
||||
&& IsPartnerMonFromSameTrainer(battler)
|
||||
&& (gBattleStruct->tera.alreadyTerastallized[BATTLE_PARTNER(battler)]
|
||||
|| (gBattleStruct->tera.toTera & gBitTable[BATTLE_PARTNER(battler)])))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Check if battler is holding a Z-Crystal or Mega Stone.
|
||||
if (holdEffect == HOLD_EFFECT_Z_CRYSTAL || holdEffect == HOLD_EFFECT_MEGA_STONE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Every check passed!
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Returns a battler's Tera type.
|
||||
u32 GetBattlerTeraType(u32 battler)
|
||||
{
|
||||
return GetMonData(&GetBattlerParty(battler)[gBattlerPartyIndexes[battler]], MON_DATA_TERA_TYPE);
|
||||
}
|
||||
|
||||
// Returns whether a battler is terastallized.
|
||||
bool32 IsTerastallized(u32 battler)
|
||||
{
|
||||
return gBattleStruct->tera.isTerastallized[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]];
|
||||
}
|
||||
|
||||
|
||||
// Uses up a type's Stellar boost.
|
||||
void ExpendTypeStellarBoost(u32 battler, u32 type)
|
||||
{
|
||||
if (type < 32) // avoid OOB access
|
||||
gBattleStruct->tera.stellarBoostFlags[GetBattlerSide(battler)] |= gBitTable[type];
|
||||
}
|
||||
|
||||
// Checks whether a type's Stellar boost has been expended.
|
||||
bool32 IsTypeStellarBoosted(u32 battler, u32 type)
|
||||
{
|
||||
if (type < 32) // avoid OOB access
|
||||
return !(gBattleStruct->tera.stellarBoostFlags[GetBattlerSide(battler)] & gBitTable[type]);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Returns the STAB power multiplier to use when Terastallized.
|
||||
// Power multipliers from Smogon Research thread.
|
||||
uq4_12_t GetTeraMultiplier(u32 battler, u32 type)
|
||||
{
|
||||
u32 teraType = GetBattlerTeraType(battler);
|
||||
bool32 hasAdaptability = (GetBattlerAbility(battler) == ABILITY_ADAPTABILITY);
|
||||
|
||||
// Safety check.
|
||||
if (!IsTerastallized(battler))
|
||||
return UQ_4_12(1.0);
|
||||
|
||||
// Stellar-type checks.
|
||||
if (teraType == TYPE_STELLAR)
|
||||
{
|
||||
bool32 shouldBoost = IsTypeStellarBoosted(battler, type);
|
||||
if (IS_BATTLER_OF_BASE_TYPE(battler, type))
|
||||
{
|
||||
if (shouldBoost)
|
||||
return UQ_4_12(2.0);
|
||||
else
|
||||
return UQ_4_12(1.5);
|
||||
}
|
||||
else if (shouldBoost)
|
||||
return UQ_4_12(1.2);
|
||||
else
|
||||
return UQ_4_12(1.0);
|
||||
}
|
||||
// Base and Tera type.
|
||||
if (type == teraType && IS_BATTLER_OF_BASE_TYPE(battler, type))
|
||||
{
|
||||
if (hasAdaptability)
|
||||
return UQ_4_12(2.25);
|
||||
else
|
||||
return UQ_4_12(2.0);
|
||||
}
|
||||
// Base or Tera type only.
|
||||
else if ((type == teraType && !IS_BATTLER_OF_BASE_TYPE(battler, type))
|
||||
|| (type != teraType && IS_BATTLER_OF_BASE_TYPE(battler, type)))
|
||||
{
|
||||
if (hasAdaptability)
|
||||
return UQ_4_12(2.0);
|
||||
else
|
||||
return UQ_4_12(1.5);
|
||||
}
|
||||
// Neither base or Tera type.
|
||||
else
|
||||
{
|
||||
return UQ_4_12(1.0);
|
||||
}
|
||||
}
|
||||
|
||||
u16 GetTeraTypeRGB(u32 type)
|
||||
{
|
||||
return gTypesInfo[type].teraTypeRGBValue;
|
||||
}
|
||||
|
||||
// TERASTAL TRIGGER:
|
||||
static const u8 ALIGNED(4) sTeraTriggerGfx[] = INCBIN_U8("graphics/battle_interface/tera_trigger.4bpp");
|
||||
static const u16 sTeraTriggerPal[] = INCBIN_U16("graphics/battle_interface/tera_trigger.gbapal");
|
||||
|
||||
static const struct SpriteSheet sSpriteSheet_TeraTrigger =
|
||||
{
|
||||
sTeraTriggerGfx, sizeof(sTeraTriggerGfx), TAG_TERA_TRIGGER_TILE
|
||||
};
|
||||
static const struct SpritePalette sSpritePalette_TeraTrigger =
|
||||
{
|
||||
sTeraTriggerPal, TAG_TERA_TRIGGER_PAL
|
||||
};
|
||||
|
||||
static const struct OamData sOamData_TeraTrigger =
|
||||
{
|
||||
.y = 0,
|
||||
.affineMode = 0,
|
||||
.objMode = 0,
|
||||
.mosaic = 0,
|
||||
.bpp = 0,
|
||||
.shape = ST_OAM_SQUARE,
|
||||
.x = 0,
|
||||
.matrixNum = 0,
|
||||
.size = 2,
|
||||
.tileNum = 0,
|
||||
.priority = 1,
|
||||
.paletteNum = 0,
|
||||
.affineParam = 0,
|
||||
};
|
||||
|
||||
static const union AnimCmd sSpriteAnim_TeraTriggerOff[] =
|
||||
{
|
||||
ANIMCMD_FRAME(0, 0),
|
||||
ANIMCMD_END
|
||||
};
|
||||
|
||||
static const union AnimCmd sSpriteAnim_TeraTriggerOn[] =
|
||||
{
|
||||
ANIMCMD_FRAME(16, 0),
|
||||
ANIMCMD_END
|
||||
};
|
||||
|
||||
static const union AnimCmd *const sSpriteAnimTable_TeraTrigger[] =
|
||||
{
|
||||
sSpriteAnim_TeraTriggerOff,
|
||||
sSpriteAnim_TeraTriggerOn,
|
||||
};
|
||||
|
||||
static void SpriteCb_TeraTrigger(struct Sprite *sprite);
|
||||
static const struct SpriteTemplate sSpriteTemplate_TeraTrigger =
|
||||
{
|
||||
.tileTag = TAG_TERA_TRIGGER_TILE,
|
||||
.paletteTag = TAG_TERA_TRIGGER_PAL,
|
||||
.oam = &sOamData_TeraTrigger,
|
||||
.anims = sSpriteAnimTable_TeraTrigger,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraTrigger
|
||||
};
|
||||
|
||||
// Tera Evolution Trigger icon functions.
|
||||
void ChangeTeraTriggerSprite(u8 spriteId, u8 animId)
|
||||
{
|
||||
StartSpriteAnim(&gSprites[spriteId], animId);
|
||||
}
|
||||
|
||||
#define SINGLES_TERA_TRIGGER_POS_X_OPTIMAL (30)
|
||||
#define SINGLES_TERA_TRIGGER_POS_X_PRIORITY (31)
|
||||
#define SINGLES_TERA_TRIGGER_POS_X_SLIDE (15)
|
||||
#define SINGLES_TERA_TRIGGER_POS_Y_DIFF (-11)
|
||||
|
||||
#define DOUBLES_TERA_TRIGGER_POS_X_OPTIMAL (30)
|
||||
#define DOUBLES_TERA_TRIGGER_POS_X_PRIORITY (31)
|
||||
#define DOUBLES_TERA_TRIGGER_POS_X_SLIDE (15)
|
||||
#define DOUBLES_TERA_TRIGGER_POS_Y_DIFF (-4)
|
||||
|
||||
#define tBattler data[0]
|
||||
#define tHide data[1]
|
||||
|
||||
void CreateTeraTriggerSprite(u8 battler, u8 palId)
|
||||
{
|
||||
LoadSpritePalette(&sSpritePalette_TeraTrigger);
|
||||
if (GetSpriteTileStartByTag(TAG_TERA_TRIGGER_TILE) == 0xFFFF)
|
||||
{
|
||||
LoadSpriteSheet(&sSpriteSheet_TeraTrigger);
|
||||
}
|
||||
if (gBattleStruct->tera.triggerSpriteId == 0xFF)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
gBattleStruct->tera.triggerSpriteId = CreateSprite(&sSpriteTemplate_TeraTrigger,
|
||||
gSprites[gHealthboxSpriteIds[battler]].x - DOUBLES_TERA_TRIGGER_POS_X_SLIDE,
|
||||
gSprites[gHealthboxSpriteIds[battler]].y - DOUBLES_TERA_TRIGGER_POS_Y_DIFF, 0);
|
||||
else
|
||||
gBattleStruct->tera.triggerSpriteId = CreateSprite(&sSpriteTemplate_TeraTrigger,
|
||||
gSprites[gHealthboxSpriteIds[battler]].x - SINGLES_TERA_TRIGGER_POS_X_SLIDE,
|
||||
gSprites[gHealthboxSpriteIds[battler]].y - SINGLES_TERA_TRIGGER_POS_Y_DIFF, 0);
|
||||
}
|
||||
gSprites[gBattleStruct->tera.triggerSpriteId].tBattler = battler;
|
||||
gSprites[gBattleStruct->tera.triggerSpriteId].tHide = FALSE;
|
||||
|
||||
ChangeTeraTriggerSprite(gBattleStruct->tera.triggerSpriteId, palId);
|
||||
}
|
||||
|
||||
static void SpriteCb_TeraTrigger(struct Sprite *sprite)
|
||||
{
|
||||
s32 xSlide, xPriority, xOptimal;
|
||||
s32 yDiff;
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
{
|
||||
xSlide = DOUBLES_TERA_TRIGGER_POS_X_SLIDE;
|
||||
xPriority = DOUBLES_TERA_TRIGGER_POS_X_PRIORITY;
|
||||
xOptimal = DOUBLES_TERA_TRIGGER_POS_X_OPTIMAL;
|
||||
yDiff = DOUBLES_TERA_TRIGGER_POS_Y_DIFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
xSlide = SINGLES_TERA_TRIGGER_POS_X_SLIDE;
|
||||
xPriority = SINGLES_TERA_TRIGGER_POS_X_PRIORITY;
|
||||
xOptimal = SINGLES_TERA_TRIGGER_POS_X_OPTIMAL;
|
||||
yDiff = SINGLES_TERA_TRIGGER_POS_Y_DIFF;
|
||||
}
|
||||
|
||||
if (sprite->tHide)
|
||||
{
|
||||
if (sprite->x != gSprites[gHealthboxSpriteIds[sprite->tBattler]].x - xSlide)
|
||||
sprite->x++;
|
||||
|
||||
if (sprite->x >= gSprites[gHealthboxSpriteIds[sprite->tBattler]].x - xPriority)
|
||||
sprite->oam.priority = 2;
|
||||
else
|
||||
sprite->oam.priority = 1;
|
||||
|
||||
sprite->y = gSprites[gHealthboxSpriteIds[sprite->tBattler]].y - yDiff;
|
||||
sprite->y2 = gSprites[gHealthboxSpriteIds[sprite->tBattler]].y2 - yDiff;
|
||||
if (sprite->x == gSprites[gHealthboxSpriteIds[sprite->tBattler]].x - xSlide)
|
||||
DestroyTeraTriggerSprite();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sprite->x != gSprites[gHealthboxSpriteIds[sprite->tBattler]].x - xOptimal)
|
||||
sprite->x--;
|
||||
|
||||
if (sprite->x >= gSprites[gHealthboxSpriteIds[sprite->tBattler]].x - xPriority)
|
||||
sprite->oam.priority = 2;
|
||||
else
|
||||
sprite->oam.priority = 1;
|
||||
|
||||
sprite->y = gSprites[gHealthboxSpriteIds[sprite->tBattler]].y - yDiff;
|
||||
sprite->y2 = gSprites[gHealthboxSpriteIds[sprite->tBattler]].y2 - yDiff;
|
||||
}
|
||||
}
|
||||
|
||||
bool32 IsTeraTriggerSpriteActive(void)
|
||||
{
|
||||
if (GetSpriteTileStartByTag(TAG_TERA_TRIGGER_TILE) == 0xFFFF)
|
||||
return FALSE;
|
||||
else if (IndexOfSpritePaletteTag(TAG_TERA_TRIGGER_PAL) != 0xFF)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void HideTeraTriggerSprite(void)
|
||||
{
|
||||
if (gBattleStruct->tera.triggerSpriteId != 0xFF)
|
||||
{
|
||||
ChangeTeraTriggerSprite(gBattleStruct->tera.triggerSpriteId, 0);
|
||||
gSprites[gBattleStruct->tera.triggerSpriteId].tHide = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyTeraTriggerSprite(void)
|
||||
{
|
||||
FreeSpritePaletteByTag(TAG_TERA_TRIGGER_PAL);
|
||||
FreeSpriteTilesByTag(TAG_TERA_TRIGGER_TILE);
|
||||
if (gBattleStruct->tera.triggerSpriteId != 0xFF)
|
||||
DestroySprite(&gSprites[gBattleStruct->tera.triggerSpriteId]);
|
||||
gBattleStruct->tera.triggerSpriteId = 0xFF;
|
||||
}
|
||||
|
||||
#undef tBattler
|
||||
#undef tHide
|
||||
|
||||
// TERA INDICATOR:
|
||||
static const u16 sTeraIndicatorPal[] = INCBIN_U16("graphics/battle_interface/tera_indicator.gbapal");
|
||||
static const u8 ALIGNED(4) sNormalIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/normal_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sFightingIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/fighting_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sFlyingIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/flying_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sPoisonIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/poison_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sGroundIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/ground_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sRockIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/rock_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sBugIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/bug_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sGhostIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/ghost_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sSteelIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/steel_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sFireIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/fire_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sWaterIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/water_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sGrassIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/grass_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sElectricIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/electric_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sPsychicIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/psychic_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sIceIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/ice_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sDragonIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/dragon_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sDarkIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/dark_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sFairyIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/fairy_indicator.4bpp");
|
||||
static const u8 ALIGNED(4) sStellarIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/stellar_indicator.4bpp");
|
||||
|
||||
static void SpriteCb_TeraIndicator(struct Sprite *sprite);
|
||||
static const s8 sIndicatorPositions[][2] =
|
||||
{
|
||||
[B_POSITION_PLAYER_LEFT] = {53, -9},
|
||||
[B_POSITION_OPPONENT_LEFT] = {44, -9},
|
||||
[B_POSITION_PLAYER_RIGHT] = {52, -9},
|
||||
[B_POSITION_OPPONENT_RIGHT] = {44, -9},
|
||||
};
|
||||
|
||||
static const struct SpritePalette sSpritePalette_TeraIndicator =
|
||||
{
|
||||
sTeraIndicatorPal, TAG_TERA_INDICATOR_PAL
|
||||
};
|
||||
|
||||
static const struct OamData sOamData_TeraIndicator =
|
||||
{
|
||||
.shape = SPRITE_SHAPE(16x16),
|
||||
.size = SPRITE_SIZE(16x16),
|
||||
.priority = 1,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_NormalIndicator =
|
||||
{
|
||||
.tileTag = TAG_NORMAL_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_FightingIndicator =
|
||||
{
|
||||
.tileTag = TAG_FIGHTING_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_FlyingIndicator =
|
||||
{
|
||||
.tileTag = TAG_FLYING_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_PoisonIndicator =
|
||||
{
|
||||
.tileTag = TAG_POISON_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_GroundIndicator =
|
||||
{
|
||||
.tileTag = TAG_GROUND_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_RockIndicator =
|
||||
{
|
||||
.tileTag = TAG_ROCK_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_BugIndicator =
|
||||
{
|
||||
.tileTag = TAG_BUG_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_GhostIndicator =
|
||||
{
|
||||
.tileTag = TAG_GHOST_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_SteelIndicator =
|
||||
{
|
||||
.tileTag = TAG_STEEL_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_FireIndicator =
|
||||
{
|
||||
.tileTag = TAG_FIRE_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_WaterIndicator =
|
||||
{
|
||||
.tileTag = TAG_WATER_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_GrassIndicator =
|
||||
{
|
||||
.tileTag = TAG_GRASS_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_ElectricIndicator =
|
||||
{
|
||||
.tileTag = TAG_ELECTRIC_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_PsychicIndicator =
|
||||
{
|
||||
.tileTag = TAG_PSYCHIC_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_IceIndicator =
|
||||
{
|
||||
.tileTag = TAG_ICE_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_DragonIndicator =
|
||||
{
|
||||
.tileTag = TAG_DRAGON_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_DarkIndicator =
|
||||
{
|
||||
.tileTag = TAG_DARK_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_FairyIndicator =
|
||||
{
|
||||
.tileTag = TAG_FAIRY_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate sSpriteTemplate_StellarIndicator =
|
||||
{
|
||||
.tileTag = TAG_STELLAR_INDICATOR_TILE,
|
||||
.paletteTag = TAG_TERA_INDICATOR_PAL,
|
||||
.oam = &sOamData_TeraIndicator,
|
||||
.anims = gDummySpriteAnimTable,
|
||||
.images = NULL,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCb_TeraIndicator,
|
||||
};
|
||||
|
||||
static const struct SpriteSheet sTeraIndicatorSpriteSheets[NUMBER_OF_MON_TYPES + 1] =
|
||||
{
|
||||
{sNormalIndicatorGfx, sizeof(sNormalIndicatorGfx), TAG_NORMAL_INDICATOR_TILE}, // TYPE_NONE
|
||||
{sNormalIndicatorGfx, sizeof(sNormalIndicatorGfx), TAG_NORMAL_INDICATOR_TILE},
|
||||
{sFightingIndicatorGfx, sizeof(sFightingIndicatorGfx), TAG_FIGHTING_INDICATOR_TILE},
|
||||
{sFlyingIndicatorGfx, sizeof(sFlyingIndicatorGfx), TAG_FLYING_INDICATOR_TILE},
|
||||
{sPoisonIndicatorGfx, sizeof(sPoisonIndicatorGfx), TAG_POISON_INDICATOR_TILE},
|
||||
{sGroundIndicatorGfx, sizeof(sGroundIndicatorGfx), TAG_GROUND_INDICATOR_TILE},
|
||||
{sRockIndicatorGfx, sizeof(sRockIndicatorGfx), TAG_ROCK_INDICATOR_TILE},
|
||||
{sBugIndicatorGfx, sizeof(sBugIndicatorGfx), TAG_BUG_INDICATOR_TILE},
|
||||
{sGhostIndicatorGfx, sizeof(sGhostIndicatorGfx), TAG_GHOST_INDICATOR_TILE},
|
||||
{sSteelIndicatorGfx, sizeof(sSteelIndicatorGfx), TAG_STEEL_INDICATOR_TILE},
|
||||
{sNormalIndicatorGfx, sizeof(sNormalIndicatorGfx), TAG_NORMAL_INDICATOR_TILE}, // TYPE_MYSTERY
|
||||
{sFireIndicatorGfx, sizeof(sFireIndicatorGfx), TAG_FIRE_INDICATOR_TILE},
|
||||
{sWaterIndicatorGfx, sizeof(sWaterIndicatorGfx), TAG_WATER_INDICATOR_TILE},
|
||||
{sGrassIndicatorGfx, sizeof(sGrassIndicatorGfx), TAG_GRASS_INDICATOR_TILE},
|
||||
{sElectricIndicatorGfx, sizeof(sElectricIndicatorGfx), TAG_ELECTRIC_INDICATOR_TILE},
|
||||
{sPsychicIndicatorGfx, sizeof(sPsychicIndicatorGfx), TAG_PSYCHIC_INDICATOR_TILE},
|
||||
{sIceIndicatorGfx, sizeof(sIceIndicatorGfx), TAG_ICE_INDICATOR_TILE},
|
||||
{sDragonIndicatorGfx, sizeof(sDragonIndicatorGfx), TAG_DRAGON_INDICATOR_TILE},
|
||||
{sDarkIndicatorGfx, sizeof(sDarkIndicatorGfx), TAG_DARK_INDICATOR_TILE},
|
||||
{sFairyIndicatorGfx, sizeof(sFairyIndicatorGfx), TAG_FAIRY_INDICATOR_TILE},
|
||||
{sStellarIndicatorGfx, sizeof(sStellarIndicatorGfx), TAG_STELLAR_INDICATOR_TILE},
|
||||
{0}
|
||||
};
|
||||
|
||||
static const struct SpriteTemplate * const sTeraIndicatorSpriteTemplates[NUMBER_OF_MON_TYPES] =
|
||||
{
|
||||
[TYPE_NONE] = &sSpriteTemplate_NormalIndicator, // just in case
|
||||
[TYPE_NORMAL] = &sSpriteTemplate_NormalIndicator,
|
||||
[TYPE_FIGHTING] = &sSpriteTemplate_FightingIndicator,
|
||||
[TYPE_FLYING] = &sSpriteTemplate_FlyingIndicator,
|
||||
[TYPE_POISON] = &sSpriteTemplate_PoisonIndicator,
|
||||
[TYPE_GROUND] = &sSpriteTemplate_GroundIndicator,
|
||||
[TYPE_ROCK] = &sSpriteTemplate_RockIndicator,
|
||||
[TYPE_BUG] = &sSpriteTemplate_BugIndicator,
|
||||
[TYPE_GHOST] = &sSpriteTemplate_GhostIndicator,
|
||||
[TYPE_STEEL] = &sSpriteTemplate_SteelIndicator,
|
||||
[TYPE_MYSTERY] = &sSpriteTemplate_NormalIndicator, // just in case
|
||||
[TYPE_FIRE] = &sSpriteTemplate_FireIndicator,
|
||||
[TYPE_WATER] = &sSpriteTemplate_WaterIndicator,
|
||||
[TYPE_GRASS] = &sSpriteTemplate_GrassIndicator,
|
||||
[TYPE_ELECTRIC] = &sSpriteTemplate_ElectricIndicator,
|
||||
[TYPE_PSYCHIC] = &sSpriteTemplate_PsychicIndicator,
|
||||
[TYPE_ICE] = &sSpriteTemplate_IceIndicator,
|
||||
[TYPE_DRAGON] = &sSpriteTemplate_DragonIndicator,
|
||||
[TYPE_DARK] = &sSpriteTemplate_DarkIndicator,
|
||||
[TYPE_FAIRY] = &sSpriteTemplate_FairyIndicator,
|
||||
[TYPE_STELLAR] = &sSpriteTemplate_StellarIndicator,
|
||||
};
|
||||
|
||||
// for sprite data fields
|
||||
#define tBattler data[0]
|
||||
#define tType data[1] // Indicator type: tera
|
||||
#define tPosX data[2]
|
||||
#define tLevelXDelta data[3] // X position depends whether level has 3, 2 or 1 digit
|
||||
|
||||
// data fields for healthboxMain
|
||||
// oam.affineParam holds healthboxRight spriteId
|
||||
#define hMain_TeraIndicatorId data[3]
|
||||
#define hMain_HealthBarSpriteId data[5]
|
||||
#define hMain_Battler data[6]
|
||||
#define hMain_Data7 data[7]
|
||||
|
||||
// data fields for healthboxRight
|
||||
#define hOther_HealthBoxSpriteId data[5]
|
||||
|
||||
// data fields for healthbar
|
||||
#define hBar_HealthBoxSpriteId data[5]
|
||||
|
||||
void TeraIndicator_LoadSpriteGfx(void)
|
||||
{
|
||||
LoadSpriteSheets(sTeraIndicatorSpriteSheets);
|
||||
LoadSpritePalette(&sSpritePalette_TeraIndicator);
|
||||
}
|
||||
|
||||
bool32 TeraIndicator_ShouldBeInvisible(u32 battler)
|
||||
{
|
||||
return !IsTerastallized(battler);
|
||||
}
|
||||
|
||||
u8 TeraIndicator_GetSpriteId(u32 healthboxSpriteId)
|
||||
{
|
||||
return gBattleStruct->tera.indicatorSpriteId[gSprites[healthboxSpriteId].hMain_Battler];
|
||||
}
|
||||
|
||||
void TeraIndicator_SetVisibilities(u32 healthboxId, bool32 invisible)
|
||||
{
|
||||
u8 spriteId = TeraIndicator_GetSpriteId(healthboxId);
|
||||
u32 battler = gSprites[healthboxId].hMain_Battler;
|
||||
|
||||
if (GetSafariZoneFlag())
|
||||
return;
|
||||
|
||||
if (invisible == TRUE)
|
||||
gSprites[spriteId].invisible = TRUE;
|
||||
else // Try visible.
|
||||
gSprites[spriteId].invisible = TeraIndicator_ShouldBeInvisible(battler);
|
||||
}
|
||||
|
||||
void TeraIndicator_UpdateOamPriorities(u32 healthboxId, u32 oamPriority)
|
||||
{
|
||||
u8 spriteId = TeraIndicator_GetSpriteId(healthboxId);
|
||||
gSprites[spriteId].oam.priority = oamPriority;
|
||||
}
|
||||
|
||||
void TeraIndicator_UpdateLevel(u32 healthboxId, u32 level)
|
||||
{
|
||||
s16 xDelta = 0;
|
||||
u8 spriteId = TeraIndicator_GetSpriteId(healthboxId);
|
||||
|
||||
if (level >= 100)
|
||||
xDelta -= 4;
|
||||
else if (level < 10)
|
||||
xDelta += 5;
|
||||
|
||||
gSprites[spriteId].tLevelXDelta = xDelta;
|
||||
}
|
||||
|
||||
void TeraIndicator_CreateSprite(u32 battler, u32 healthboxSpriteId)
|
||||
{
|
||||
u32 position;
|
||||
u8 spriteId;
|
||||
s16 xHealthbox = 0, y = 0;
|
||||
s32 x = 0;
|
||||
u32 type = GetBattlerTeraType(battler);
|
||||
|
||||
position = GetBattlerPosition(battler);
|
||||
GetBattlerHealthboxCoords(battler, &xHealthbox, &y);
|
||||
|
||||
x = sIndicatorPositions[position][0];
|
||||
y += sIndicatorPositions[position][1];
|
||||
|
||||
spriteId = gBattleStruct->tera.indicatorSpriteId[battler] = CreateSpriteAtEnd(sTeraIndicatorSpriteTemplates[type], 0, y, 0);
|
||||
gSprites[spriteId].tBattler = battler;
|
||||
gSprites[spriteId].tPosX = x;
|
||||
gSprites[spriteId].invisible = TRUE;
|
||||
}
|
||||
|
||||
void TeraIndicator_DestroySprite(u32 healthboxSpriteId)
|
||||
{
|
||||
u8 spriteId = TeraIndicator_GetSpriteId(healthboxSpriteId);
|
||||
DestroySprite(&gSprites[spriteId]);
|
||||
}
|
||||
|
||||
void TeraIndicator_UpdateType(u32 battler, u32 healthboxSpriteId)
|
||||
{
|
||||
TeraIndicator_DestroySprite(healthboxSpriteId);
|
||||
TeraIndicator_CreateSprite(battler, healthboxSpriteId);
|
||||
}
|
||||
|
||||
static void SpriteCb_TeraIndicator(struct Sprite *sprite)
|
||||
{
|
||||
u32 battler = sprite->tBattler;
|
||||
|
||||
sprite->x = gSprites[gHealthboxSpriteIds[battler]].x + sprite->tPosX + sprite->tLevelXDelta;
|
||||
sprite->x2 = gSprites[gHealthboxSpriteIds[battler]].x2;
|
||||
sprite->y2 = gSprites[gHealthboxSpriteIds[battler]].y2;
|
||||
}
|
||||
|
||||
#undef tBattler
|
||||
#undef tType
|
||||
#undef tPosX
|
||||
#undef tLevelXDelta
|
||||
|
|
@ -650,7 +650,7 @@ void HandleAction_NothingIsFainted(void)
|
|||
|
||||
void HandleAction_ActionFinished(void)
|
||||
{
|
||||
u32 i, j/* , moveType */;
|
||||
u32 i, j, moveType;
|
||||
bool32 afterYouActive = gSpecialStatuses[gBattlerByTurnOrder[gCurrentTurnActionNumber + 1]].afterYou;
|
||||
*(gBattleStruct->monToSwitchIntoId + gBattlerByTurnOrder[gCurrentTurnActionNumber]) = gSelectedMonPartyId = PARTY_SIZE;
|
||||
gCurrentTurnActionNumber++;
|
||||
|
|
@ -661,16 +661,15 @@ void HandleAction_ActionFinished(void)
|
|||
| HITMARKER_OBEYS | HITMARKER_WAKE_UP_CLEAR | HITMARKER_SYNCHRONISE_EFFECT
|
||||
| HITMARKER_CHARGING | HITMARKER_NEVER_SET | HITMARKER_IGNORE_DISGUISE);
|
||||
|
||||
// TODO: Tera
|
||||
// check if Stellar type boost should be used up
|
||||
// GET_MOVE_TYPE(gCurrentMove, moveType);
|
||||
// if (IsTerastallized(gBattlerAttacker)
|
||||
// && GetBattlerTeraType(gBattlerAttacker) == TYPE_STELLAR
|
||||
// && gMovesInfo[gCurrentMove].category != DAMAGE_CATEGORY_STATUS
|
||||
// && IsTypeStellarBoosted(gBattlerAttacker, moveType))
|
||||
// {
|
||||
// ExpendTypeStellarBoost(gBattlerAttacker, moveType);
|
||||
// }
|
||||
GET_MOVE_TYPE(gCurrentMove, moveType);
|
||||
if (IsTerastallized(gBattlerAttacker)
|
||||
&& GetBattlerTeraType(gBattlerAttacker) == TYPE_STELLAR
|
||||
&& gMovesInfo[gCurrentMove].category != DAMAGE_CATEGORY_STATUS
|
||||
&& IsTypeStellarBoosted(gBattlerAttacker, moveType))
|
||||
{
|
||||
ExpendTypeStellarBoost(gBattlerAttacker, moveType);
|
||||
}
|
||||
|
||||
gCurrentMove = 0;
|
||||
gBattleMoveDamage = 0;
|
||||
|
|
@ -1202,7 +1201,7 @@ bool32 IsBelchPreventingMove(u32 battler, u32 move)
|
|||
u32 TrySetCantSelectMoveBattleScript(u32 battler)
|
||||
{
|
||||
u32 limitations = 0;
|
||||
u8 moveId = gBattleResources->bufferB[battler][2] & ~(RET_MEGA_EVOLUTION | RET_ULTRA_BURST | RET_DYNAMAX/* | RET_TERASTAL */); // TODO: Tera
|
||||
u8 moveId = gBattleResources->bufferB[battler][2] & ~(RET_MEGA_EVOLUTION | RET_ULTRA_BURST | RET_DYNAMAX | RET_TERASTAL);
|
||||
u32 move = gBattleMons[battler].moves[moveId];
|
||||
u32 holdEffect = GetBattlerHoldEffect(battler, TRUE);
|
||||
u16 *choicedMove = &gBattleStruct->choicedMove[battler];
|
||||
|
|
@ -4427,15 +4426,14 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
|||
effect++;
|
||||
}
|
||||
break;
|
||||
// TODO: Tera
|
||||
// case ABILITY_TERAFORM_ZERO:
|
||||
// if (!gSpecialStatuses[battler].switchInAbilityDone
|
||||
// && gBattleMons[battler].species == SPECIES_TERAPAGOS_STELLAR)
|
||||
// {
|
||||
// gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
// BattleScriptPushCursorAndCallback(BattleScript_ActivateTeraformZero);
|
||||
// effect++;
|
||||
// }
|
||||
case ABILITY_TERAFORM_ZERO:
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone
|
||||
&& gBattleMons[battler].species == SPECIES_TERAPAGOS_STELLAR)
|
||||
{
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_ActivateTeraformZero);
|
||||
effect++;
|
||||
}
|
||||
case ABILITY_SCHOOLING:
|
||||
if (gBattleMons[battler].level < 20)
|
||||
break;
|
||||
|
|
@ -4627,19 +4625,18 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
|||
effect++;
|
||||
}
|
||||
break;
|
||||
// TODO: Tera
|
||||
// case ABILITY_TERA_SHIFT:
|
||||
// if (!gSpecialStatuses[battler].switchInAbilityDone
|
||||
// && gBattleMons[battler].species == SPECIES_TERAPAGOS_NORMAL
|
||||
// && TryBattleFormChange(battler, FORM_CHANGE_BATTLE_SWITCH))
|
||||
// {
|
||||
// gBattlerAttacker = battler;
|
||||
// gBattleScripting.abilityPopupOverwrite = gLastUsedAbility = ABILITY_TERA_SHIFT;
|
||||
// gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
// BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeWithStringEnd3);
|
||||
// effect++;
|
||||
// }
|
||||
// break;
|
||||
case ABILITY_TERA_SHIFT:
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone
|
||||
&& gBattleMons[battler].species == SPECIES_TERAPAGOS_NORMAL
|
||||
&& TryBattleFormChange(battler, FORM_CHANGE_BATTLE_SWITCH))
|
||||
{
|
||||
gBattlerAttacker = battler;
|
||||
gBattleScripting.abilityPopupOverwrite = gLastUsedAbility = ABILITY_TERA_SHIFT;
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeWithStringEnd3);
|
||||
effect++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ABILITYEFFECT_ENDTURN:
|
||||
|
|
@ -8718,11 +8715,10 @@ static inline u32 CalcMoveBasePower(u32 move, u32 battlerAtk, u32 battlerDef, u3
|
|||
if (RandomPercentage(RNG_FICKLE_BEAM, 30))
|
||||
basePower *= 2;
|
||||
break;
|
||||
// TODO: Tera
|
||||
// case EFFECT_TERA_BLAST:
|
||||
// if (IsTerastallized(battlerAtk) && GetBattlerTeraType(battlerAtk) == TYPE_STELLAR)
|
||||
// basePower = 100;
|
||||
// break;
|
||||
case EFFECT_TERA_BLAST:
|
||||
if (IsTerastallized(battlerAtk) && GetBattlerTeraType(battlerAtk) == TYPE_STELLAR)
|
||||
basePower = 100;
|
||||
break;
|
||||
case EFFECT_LAST_RESPECTS:
|
||||
basePower += (basePower * min(100, GetBattlerSideFaintCounter(battlerAtk)));
|
||||
break;
|
||||
|
|
@ -9091,18 +9087,17 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32
|
|||
break;
|
||||
}
|
||||
|
||||
// TODO: Tera
|
||||
// Terastallization boosts weak, non-priority, non-multi hit moves after modifiers to 60 BP.
|
||||
// if (IsTerastallized(battlerAtk)
|
||||
// && (moveType == GetBattlerTeraType(battlerAtk)
|
||||
// || (GetBattlerTeraType(battlerAtk) == TYPE_STELLAR && IsTypeStellarBoosted(battlerAtk, moveType)))
|
||||
// && uq4_12_multiply_by_int_half_down(modifier, basePower) < 60
|
||||
// && gMovesInfo[move].strikeCount < 2
|
||||
// && gMovesInfo[move].effect != EFFECT_MULTI_HIT
|
||||
// && gMovesInfo[move].priority == 0)
|
||||
// {
|
||||
// return 60;
|
||||
// }
|
||||
if (IsTerastallized(battlerAtk)
|
||||
&& (moveType == GetBattlerTeraType(battlerAtk)
|
||||
|| (GetBattlerTeraType(battlerAtk) == TYPE_STELLAR && IsTypeStellarBoosted(battlerAtk, moveType)))
|
||||
&& uq4_12_multiply_by_int_half_down(modifier, basePower) < 60
|
||||
&& gMovesInfo[move].strikeCount < 2
|
||||
&& gMovesInfo[move].effect != EFFECT_MULTI_HIT
|
||||
&& gMovesInfo[move].priority == 0)
|
||||
{
|
||||
return 60;
|
||||
}
|
||||
|
||||
return uq4_12_multiply_by_int_half_down(modifier, basePower);
|
||||
}
|
||||
|
|
@ -9806,10 +9801,9 @@ static inline s32 DoMoveDamageCalcVars(u32 move, u32 battlerAtk, u32 battlerDef,
|
|||
dmg /= 100;
|
||||
}
|
||||
|
||||
// TODO: Tera
|
||||
// if (IsTerastallized(battlerAtk))
|
||||
// DAMAGE_APPLY_MODIFIER(GetTeraMultiplier(battlerAtk, moveType));
|
||||
// else
|
||||
if (IsTerastallized(battlerAtk))
|
||||
DAMAGE_APPLY_MODIFIER(GetTeraMultiplier(battlerAtk, moveType));
|
||||
else
|
||||
DAMAGE_APPLY_MODIFIER(GetSameTypeAttackBonusModifier(battlerAtk, moveType, move, abilityAtk));
|
||||
DAMAGE_APPLY_MODIFIER(typeEffectivenessModifier);
|
||||
DAMAGE_APPLY_MODIFIER(GetBurnOrFrostBiteModifier(battlerAtk, move, abilityAtk));
|
||||
|
|
@ -9965,7 +9959,7 @@ static inline void MulByTypeEffectiveness(uq4_12_t *modifier, u32 move, u32 move
|
|||
mod = UQ_4_12(2.0);
|
||||
if (moveType == TYPE_GROUND && defType == TYPE_FLYING && IsBattlerGrounded(battlerDef) && mod == UQ_4_12(0.0))
|
||||
mod = UQ_4_12(1.0);
|
||||
if (FALSE/* moveType == TYPE_STELLAR && IsTerastallized(battlerDef) */) // TODO: Tera
|
||||
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
|
||||
|
|
@ -9975,7 +9969,7 @@ static inline void MulByTypeEffectiveness(uq4_12_t *modifier, u32 move, u32 move
|
|||
mod = UQ_4_12(1.0);
|
||||
}
|
||||
|
||||
if (gBattleStruct->distortedTypeMatchups & gBitTable[battlerDef] /* || (gBattleStruct->aiCalcInProgress && ShouldTeraShellDistortTypeMatchups(move, battlerDef)) */) // TODO: Tera
|
||||
if (gBattleStruct->distortedTypeMatchups & gBitTable[battlerDef] || (gBattleStruct->aiCalcInProgress && ShouldTeraShellDistortTypeMatchups(move, battlerDef)))
|
||||
{
|
||||
mod = UQ_4_12(0.5);
|
||||
if (recordAbilities)
|
||||
|
|
@ -10409,14 +10403,13 @@ bool32 IsBattlerUltraBursted(u32 battler)
|
|||
return (gSpeciesInfo[gBattleMons[battler].species].isUltraBurst);
|
||||
}
|
||||
|
||||
// TODO: Tera
|
||||
// bool32 IsBattlerInTeraForm(u32 battler)
|
||||
// {
|
||||
// // While Transform does copy stats and visuals, it shouldn't be counted as a true Tera Form.
|
||||
// if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED)
|
||||
// return FALSE;
|
||||
// return (gSpeciesInfo[gBattleMons[battler].species].isTeraForm);
|
||||
// }
|
||||
bool32 IsBattlerInTeraForm(u32 battler)
|
||||
{
|
||||
// While Transform does copy stats and visuals, it shouldn't be counted as a true Tera Form.
|
||||
if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED)
|
||||
return FALSE;
|
||||
return (gSpeciesInfo[gBattleMons[battler].species].isTeraForm);
|
||||
}
|
||||
|
||||
// Returns SPECIES_NONE if no form change is possible
|
||||
u16 GetBattleFormChangeTargetSpecies(u32 battler, u16 method)
|
||||
|
|
@ -10508,11 +10501,10 @@ u16 GetBattleFormChangeTargetSpecies(u32 battler, u16 method)
|
|||
if (gBattleMons[battler].status1 & formChanges[i].param1)
|
||||
targetSpecies = formChanges[i].targetSpecies;
|
||||
break;
|
||||
// TODO: Tera
|
||||
// case FORM_CHANGE_BATTLE_TERASTALLIZATION:
|
||||
// if (GetBattlerTeraType(battler) == formChanges[i].param1)
|
||||
// targetSpecies = formChanges[i].targetSpecies;
|
||||
// break;
|
||||
case FORM_CHANGE_BATTLE_TERASTALLIZATION:
|
||||
if (GetBattlerTeraType(battler) == formChanges[i].param1)
|
||||
targetSpecies = formChanges[i].targetSpecies;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10528,7 +10520,7 @@ bool32 CanBattlerFormChange(u32 battler, u16 method)
|
|||
&& B_TRANSFORM_FORM_CHANGES >= GEN_5)
|
||||
return FALSE;
|
||||
// Mega Evolved and Ultra Bursted Pokémon should always revert to normal upon fainting or ending the battle.
|
||||
if ((IsBattlerMegaEvolved(battler) || IsBattlerUltraBursted(battler)/* || IsBattlerInTeraForm(battler) */) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_END_BATTLE)) // TODO: Tera
|
||||
if ((IsBattlerMegaEvolved(battler) || IsBattlerUltraBursted(battler) || IsBattlerInTeraForm(battler)) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_END_BATTLE))
|
||||
return TRUE;
|
||||
else if (IsBattlerPrimalReverted(battler) && (method == FORM_CHANGE_END_BATTLE))
|
||||
return TRUE;
|
||||
|
|
@ -10568,7 +10560,7 @@ bool32 TryBattleFormChange(u32 battler, u16 method)
|
|||
bool32 restoreSpecies = FALSE;
|
||||
|
||||
// Mega Evolved and Ultra Bursted Pokémon should always revert to normal upon fainting or ending the battle, so no need to add it to the form change tables.
|
||||
if ((IsBattlerMegaEvolved(battler) || IsBattlerUltraBursted(battler) /* || IsBattlerInTeraForm(battler) */) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_END_BATTLE)) // TODO: Tera
|
||||
if ((IsBattlerMegaEvolved(battler) || IsBattlerUltraBursted(battler) || IsBattlerInTeraForm(battler)) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_END_BATTLE))
|
||||
restoreSpecies = TRUE;
|
||||
|
||||
// Unlike Megas, Primal Reversion isn't canceled on fainting.
|
||||
|
|
@ -11347,22 +11339,21 @@ bool8 IsMonBannedFromSkyBattles(u16 species)
|
|||
|
||||
u8 GetBattlerType(u32 battler, u8 typeIndex, bool32 ignoreTera)
|
||||
{
|
||||
// u32 teraType = GetBattlerTeraType(battler); // TODO: Tera
|
||||
u32 teraType = GetBattlerTeraType(battler);
|
||||
u16 types[3] = {0};
|
||||
types[0] = gBattleMons[battler].type1;
|
||||
types[1] = gBattleMons[battler].type2;
|
||||
types[2] = gBattleMons[battler].type3;
|
||||
|
||||
// Handle Terastallization
|
||||
// TODO: Tera
|
||||
// if (IsTerastallized(battler) && teraType != TYPE_STELLAR && !ignoreTera)
|
||||
// return GetBattlerTeraType(battler);
|
||||
if (IsTerastallized(battler) && teraType != TYPE_STELLAR && !ignoreTera)
|
||||
return GetBattlerTeraType(battler);
|
||||
|
||||
// Handle Roost's Flying-type suppression
|
||||
if (typeIndex == 0 || typeIndex == 1)
|
||||
{
|
||||
if (gBattleResources->flags->flags[battler] & RESOURCE_FLAG_ROOST
|
||||
/* && !IsTerastallized(battler) */) // TODO: Tera
|
||||
&& !IsTerastallized(battler))
|
||||
{
|
||||
if (types[0] == TYPE_FLYING && types[1] == TYPE_FLYING)
|
||||
return B_ROOST_PURE_FLYING >= GEN_5 ? TYPE_NORMAL : TYPE_MYSTERY;
|
||||
|
|
@ -11377,9 +11368,8 @@ u8 GetBattlerType(u32 battler, u8 typeIndex, bool32 ignoreTera)
|
|||
void RemoveBattlerType(u32 battler, u8 type)
|
||||
{
|
||||
u32 i;
|
||||
// TODO: Tera
|
||||
// if (IsTerastallized(battler)) // don't remove type if Terastallized
|
||||
// return;
|
||||
if (IsTerastallized(battler)) // don't remove type if Terastallized
|
||||
return;
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (*(u8 *)(&gBattleMons[battler].type1 + i) == type)
|
||||
|
|
|
|||