mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-12-27 20:24:18 +01:00
Mega Evolution support is mostly done.
This commit is contained in:
parent
33b6ec8c0a
commit
55f21c1776
@ -1473,6 +1473,10 @@
|
||||
.4byte \ptr
|
||||
.endm
|
||||
|
||||
.macro handlemegaevo battler
|
||||
various \battler, VARIOUS_HANDLE_MEGA_EVO
|
||||
.endm
|
||||
|
||||
@ helpful macros
|
||||
.macro setstatchanger stat, stages, down
|
||||
setbyte sSTATCHANGER \stat | \stages << 4 | \down << 7
|
||||
|
@ -672,6 +672,7 @@ gBattleAnims_VariousTable:: @ 82C9320
|
||||
.4byte Anim_Table_x14
|
||||
.4byte Status_Ingrain
|
||||
.4byte Anim_WishHeal
|
||||
.4byte General_MegaEvolution
|
||||
|
||||
.align 2
|
||||
gBattleAnims_Special:: @ 82C937C
|
||||
@ -12055,6 +12056,9 @@ Anim_WishHeal:
|
||||
createsprite gUnknown_08597274, 0x2, 1, 3, 10, 0, 0
|
||||
end
|
||||
|
||||
General_MegaEvolution:
|
||||
end
|
||||
|
||||
AnimScript_82D85A3:
|
||||
createvisualtask sub_8172E9C, 0x2
|
||||
jumpargeq 0x7, 0x1, AnimScript_82D85B4
|
||||
|
@ -4611,6 +4611,16 @@ BattleScript_FocusPunchSetUp::
|
||||
waitmessage 0x40
|
||||
end2
|
||||
|
||||
BattleScript_MegaEvolution::
|
||||
printstring STRINGID_MEGAEVOREACTING
|
||||
waitmessage 0x40
|
||||
playanimation BS_ATTACKER, B_ANIM_MEGA_EVOLUTION, NULL
|
||||
waitanimation
|
||||
handlemegaevo BS_ATTACKER
|
||||
printstring STRINGID_MEGAEVOEVOLVED
|
||||
waitmessage 0x40
|
||||
end2
|
||||
|
||||
BattleScript_MoveUsedIsAsleep::
|
||||
printstring STRINGID_PKMNFASTASLEEP
|
||||
waitmessage 0x40
|
||||
|
@ -598,6 +598,11 @@ struct BattleStruct
|
||||
bool8 ateBoost[MAX_BATTLERS_COUNT];
|
||||
u32 debugAIFlags;
|
||||
bool8 notfirstTimeAIFlags;
|
||||
u8 toMegaEvolve; // As flags using gBitTable.
|
||||
u8 megaEvolvedPartyIds[2]; // As flags using gBitTable;
|
||||
bool8 alreadyMegaEvolved[4]; // Array id is used for mon position.
|
||||
u16 speciesToMegaEvolve[MAX_BATTLERS_COUNT];
|
||||
u8 megaEvoBattlerId;
|
||||
};
|
||||
|
||||
#define GET_MOVE_TYPE(move, typeArg) \
|
||||
|
@ -84,6 +84,7 @@ enum
|
||||
|
||||
// Special return values in gBattleBufferB from Battle Controller functions.
|
||||
#define RET_VALUE_LEVELED_UP 11
|
||||
#define RET_MEGA_EVOLUTION 0x80
|
||||
|
||||
struct UnusedControllerStruct
|
||||
{
|
||||
|
@ -271,5 +271,6 @@ extern const u8 BattleScript_SelectingNotAllowedMoveHealBlockInPalace[];
|
||||
extern const u8 BattleScript_ToxicSpikesFree[];
|
||||
extern const u8 BattleScript_StickyWebFree[];
|
||||
extern const u8 BattleScript_StealthRockFree[];
|
||||
extern const u8 BattleScript_MegaEvolution[];
|
||||
|
||||
#endif // GUARD_BATTLE_SCRIPTS_H
|
||||
|
@ -88,5 +88,6 @@ u16 CalcTypeEffectivenessMultiplier(u16 move, u8 moveType, u8 battlerAtk, u8 bat
|
||||
u16 CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u8 abilityDef);
|
||||
u16 GetTypeModifier(u8 atkType, u8 defType);
|
||||
s32 GetStealthHazardDamage(u8 hazardType, u8 battlerId);
|
||||
bool32 CanMegaEvolve(u8 battlerId);
|
||||
|
||||
#endif // GUARD_BATTLE_UTIL_H
|
||||
|
@ -60,6 +60,7 @@
|
||||
#define B_ANIM_x14 0x14
|
||||
#define B_ANIM_INGRAIN_HEAL 0x15
|
||||
#define B_ANIM_WISH_HEAL 0x16
|
||||
#define B_ANIM_MEGA_EVOLUTION 0x17
|
||||
|
||||
// special animations table
|
||||
#define B_ANIM_LVL_UP 0x0
|
||||
|
@ -99,6 +99,7 @@
|
||||
#define VARIOUS_TRY_ELECTRIFY 48
|
||||
#define VARIOUS_TRY_REFLECT_TYPE 49
|
||||
#define VARIOUS_TRY_SOAK 50
|
||||
#define VARIOUS_HANDLE_MEGA_EVO 51
|
||||
|
||||
// atk80, dmg manipulation
|
||||
#define ATK80_DMG_CHANGE_SIGN 0
|
||||
|
@ -502,6 +502,8 @@
|
||||
#define STRINGID_TERRAINBECOMESELECTRIC 499
|
||||
#define STRINGID_TERRAINBECOMESPSYCHIC 500
|
||||
#define STRINGID_TARGETELECTRIFIED 501
|
||||
#define STRINGID_MEGAEVOREACTING 502
|
||||
#define STRINGID_MEGAEVOEVOLVED 503
|
||||
|
||||
#define BATTLESTRINGS_COUNT 516
|
||||
|
||||
|
@ -109,6 +109,7 @@
|
||||
|
||||
// Gen6 hold effects
|
||||
#define HOLD_EFFECT_FAIRY_POWER 130
|
||||
#define HOLD_EFFECT_MEGA_STONE 131
|
||||
|
||||
// Gen7 hold effects
|
||||
#define HOLD_EFFECT_PROTECTIVE_PADS 150
|
||||
|
@ -239,7 +239,7 @@
|
||||
#define ITEM_METAL_POWDER 223
|
||||
#define ITEM_THICK_CLUB 224
|
||||
#define ITEM_STICK 225
|
||||
#define ITEM_0E2 226
|
||||
#define ITEM_MEGA_STONE_TESTING 226
|
||||
#define ITEM_0E3 227
|
||||
#define ITEM_0E4 228
|
||||
#define ITEM_0E5 229
|
||||
|
@ -422,6 +422,8 @@ enum
|
||||
#define EVO_LEVEL_SHEDINJA 0x000e // Pokémon reaches the specified level (special value for Shedinja)
|
||||
#define EVO_BEAUTY 0x000f // Pokémon levels up with beauty ≥ specified value
|
||||
|
||||
#define EVO_MEGA_EVOLUTION 0xffff // Not an actual evolution, used to temporarily mega evolve in battle.
|
||||
|
||||
struct Evolution
|
||||
{
|
||||
u16 method;
|
||||
|
@ -1548,16 +1548,15 @@ static void OpponentHandleChooseMove(void)
|
||||
|
||||
if (gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_ROAMER))
|
||||
{
|
||||
|
||||
BattleAI_SetupAIData(0xF);
|
||||
chosenMoveId = BattleAI_ChooseMoveOrAction();
|
||||
|
||||
switch (chosenMoveId)
|
||||
{
|
||||
case 5:
|
||||
case AI_CHOICE_WATCH:
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_SAFARI_WATCH_CAREFULLY, 0);
|
||||
break;
|
||||
case 4:
|
||||
case AI_CHOICE_FLEE:
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_RUN, 0);
|
||||
break;
|
||||
case 6:
|
||||
@ -1572,6 +1571,9 @@ static void OpponentHandleChooseMove(void)
|
||||
if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
|
||||
}
|
||||
if (CanMegaEvolve(gActiveBattler)) // If opponent can mega evolve, do it.
|
||||
BtlController_EmitTwoReturnValues(1, 10 | RET_MEGA_EVOLUTION, (chosenMoveId) | (gBattlerTarget << 8));
|
||||
else
|
||||
BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (gBattlerTarget << 8));
|
||||
break;
|
||||
}
|
||||
|
@ -166,6 +166,7 @@ static void SetActionsAndBattlersTurnOrder(void);
|
||||
static void sub_803CDF8(void);
|
||||
static bool8 AllAtActionConfirmed(void);
|
||||
static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void);
|
||||
static void CheckMegaEvolutionBeforeTurn(void);
|
||||
static void FreeResetData_ReturnToOvOrDoEvolutions(void);
|
||||
static void ReturnFromBattleToOverworld(void);
|
||||
static void TryEvolvePokemon(void);
|
||||
@ -4375,9 +4376,12 @@ static void HandleTurnActionSelectionState(void)
|
||||
case STATE_WAIT_ACTION_CASE_CHOSEN:
|
||||
if (!(gBattleControllerExecFlags & ((gBitTable[gActiveBattler]) | (0xF0000000) | (gBitTable[gActiveBattler] << 4) | (gBitTable[gActiveBattler] << 8) | (gBitTable[gActiveBattler] << 0xC))))
|
||||
{
|
||||
bool32 shouldMegaEvolve;
|
||||
switch (gChosenActionByBattler[gActiveBattler])
|
||||
{
|
||||
case B_ACTION_USE_MOVE:
|
||||
shouldMegaEvolve = gBattleBufferB[gActiveBattler][1] & RET_MEGA_EVOLUTION;
|
||||
gBattleBufferB[gActiveBattler][1] &= ~(RET_MEGA_EVOLUTION);
|
||||
switch (gBattleBufferB[gActiveBattler][1])
|
||||
{
|
||||
case 3:
|
||||
@ -4419,6 +4423,8 @@ static void HandleTurnActionSelectionState(void)
|
||||
*(gBattleStruct->chosenMovePositions + gActiveBattler) = gBattleBufferB[gActiveBattler][2];
|
||||
gChosenMoveByBattler[gActiveBattler] = gBattleMons[gActiveBattler].moves[*(gBattleStruct->chosenMovePositions + gActiveBattler)];
|
||||
*(gBattleStruct->moveTarget + gActiveBattler) = gBattleBufferB[gActiveBattler][3];
|
||||
if (shouldMegaEvolve)
|
||||
gBattleStruct->toMegaEvolve |= gBitTable[gActiveBattler];
|
||||
gBattleCommunication[gActiveBattler]++;
|
||||
}
|
||||
break;
|
||||
@ -4844,8 +4850,8 @@ static void SetActionsAndBattlersTurnOrder(void)
|
||||
turnOrderId++;
|
||||
}
|
||||
}
|
||||
gBattleMainFunc = CheckFocusPunch_ClearVarsBeforeTurnStarts;
|
||||
gBattleStruct->focusPunchBattlerId = 0;
|
||||
gBattleMainFunc = CheckMegaEvolutionBeforeTurn;
|
||||
gBattleStruct->megaEvoBattlerId = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
@ -4886,8 +4892,8 @@ static void SetActionsAndBattlersTurnOrder(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
gBattleMainFunc = CheckFocusPunch_ClearVarsBeforeTurnStarts;
|
||||
gBattleStruct->focusPunchBattlerId = 0;
|
||||
gBattleMainFunc = CheckMegaEvolutionBeforeTurn;
|
||||
gBattleStruct->megaEvoBattlerId = 0;
|
||||
}
|
||||
|
||||
static void TurnValuesCleanUp(bool8 var0)
|
||||
@ -4939,6 +4945,29 @@ static void SpecialStatusesClear(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void CheckMegaEvolutionBeforeTurn(void)
|
||||
{
|
||||
if (!(gHitMarker & HITMARKER_RUN))
|
||||
{
|
||||
while (gBattleStruct->megaEvoBattlerId < gBattlersCount)
|
||||
{
|
||||
gActiveBattler = gBattlerAttacker = gBattleStruct->megaEvoBattlerId;
|
||||
gBattleStruct->megaEvoBattlerId++;
|
||||
if (gBattleStruct->toMegaEvolve & gBitTable[gActiveBattler]
|
||||
&& !(gProtectStructs[gActiveBattler].noValidMoves))
|
||||
{
|
||||
gBattleStruct->toMegaEvolve &= ~(gBitTable[gActiveBattler]);
|
||||
gLastUsedItem = gBattleMons[gActiveBattler].item;
|
||||
BattleScriptExecute(BattleScript_MegaEvolution);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gBattleMainFunc = CheckFocusPunch_ClearVarsBeforeTurnStarts;
|
||||
gBattleStruct->focusPunchBattlerId = 0;
|
||||
}
|
||||
|
||||
static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void)
|
||||
{
|
||||
u32 i;
|
||||
|
@ -631,8 +631,6 @@ static const u8 sText_NotDoneYet[] = _("This move effect is not done yet!\p");
|
||||
static const u8 sText_PkmnBlewAwayToxicSpikes[] = _("{B_ATK_NAME_WITH_PREFIX} blew away\nTOXIC SPIKES!");
|
||||
static const u8 sText_PkmnBlewAwayStickyWeb[] = _("{B_ATK_NAME_WITH_PREFIX} blew away\nSTICKY WEB!");
|
||||
static const u8 sText_PkmnBlewAwayStealthRock[] = _("{B_ATK_NAME_WITH_PREFIX} blew away\nSTEALTH ROCK!");
|
||||
|
||||
// To do.
|
||||
static const u8 sText_StickyWebUsed[] = _("A sticky web spreads out on the\nground around your team!");
|
||||
static const u8 sText_QuashSuccess[] = _("The opposing {B_ATK_NAME_WITH_PREFIX}’s move was postponed!");
|
||||
static const u8 sText_IonDelugeOn[] = _("A deluge of ions showers\nthe battlefield!");
|
||||
@ -642,12 +640,11 @@ static const u8 sText_TerrainBecomesGrassy[] = _("Grass grew to cover\nthe battl
|
||||
static const u8 sText_TerrainBecomesElectric[] = _("An electric current runs across\nthe battlefield!");
|
||||
static const u8 sText_TerrainBecomesPsychic[] = _("The battlefield got weird!");
|
||||
static const u8 sText_TargetElectrified[] = _("The opposing {B_ATK_NAME_WITH_PREFIX}’s moves\nhave been electrified!");
|
||||
|
||||
// New selection strings, they must end with "\p".
|
||||
// Use {B_LAST_ITEM} and {B_CURRENT_MOVE}.
|
||||
static const u8 sText_AssaultVestDoesntAllow[] = _("The effects of the {B_LAST_ITEM} prevent status\nmoves from being used!\p");
|
||||
static const u8 sText_GravityPreventsUsage[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} can’t use {B_CURRENT_MOVE}\nbecause of gravity!\p");
|
||||
static const u8 sText_HealBlockPreventsUsage[] = _("The opposing {B_ATK_NAME_WITH_PREFIX} was\nprevented from healing!\p");
|
||||
static const u8 sText_MegaEvoReacting[] = _("{B_ATK_NAME_WITH_PREFIX}’s {B_LAST_ITEM} is reacting\nto {B_ATK_TRAINER_NAME}’s Mega Ring!");
|
||||
static const u8 sText_MegaEvoEvolved[] = _("{B_ATK_NAME_WITH_PREFIX} has Mega\nEvolved into Mega {B_BUFF1}!");
|
||||
|
||||
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
|
||||
{
|
||||
@ -1142,6 +1139,8 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
|
||||
sText_TerrainBecomesElectric,
|
||||
sText_TerrainBecomesPsychic,
|
||||
sText_TargetElectrified,
|
||||
sText_MegaEvoReacting,
|
||||
sText_MegaEvoEvolved,
|
||||
};
|
||||
|
||||
const u16 gTerrainStringIds[] =
|
||||
|
@ -6119,6 +6119,7 @@ static void HandleTerrainMove(u32 moveEffect)
|
||||
|
||||
static void atk76_various(void)
|
||||
{
|
||||
struct Pokemon *mon;
|
||||
u8 side;
|
||||
s32 i, j;
|
||||
u8 data[10];
|
||||
@ -6588,6 +6589,28 @@ static void atk76_various(void)
|
||||
gBattlescriptCurrInstr += 7;
|
||||
}
|
||||
return;
|
||||
case VARIOUS_HANDLE_MEGA_EVO:
|
||||
if (GetBattlerSide(gActiveBattler) == B_SIDE_OPPONENT)
|
||||
mon = &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]];
|
||||
else
|
||||
mon = &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]];
|
||||
gBattleMons[gActiveBattler].species = gBattleStruct->speciesToMegaEvolve[gActiveBattler];
|
||||
SetMonData(mon, MON_DATA_SPECIES, &gBattleMons[gActiveBattler].species);
|
||||
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gActiveBattler].species);
|
||||
|
||||
CalculateMonStats(mon);
|
||||
gBattleMons[gActiveBattler].hp = GetMonData(mon, MON_DATA_HP);
|
||||
gBattleMons[gActiveBattler].maxHP = GetMonData(mon, MON_DATA_MAX_HP);
|
||||
gBattleMons[gActiveBattler].attack = GetMonData(mon, MON_DATA_ATK);
|
||||
gBattleMons[gActiveBattler].defense = GetMonData(mon, MON_DATA_DEF);
|
||||
gBattleMons[gActiveBattler].speed = GetMonData(mon, MON_DATA_SPEED);
|
||||
gBattleMons[gActiveBattler].spAttack = GetMonData(mon, MON_DATA_SPATK);
|
||||
gBattleMons[gActiveBattler].spDefense = GetMonData(mon, MON_DATA_SPDEF);
|
||||
UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], mon, HEALTHBOX_ALL);
|
||||
|
||||
gBattleStruct->alreadyMegaEvolved[GetBattlerPosition(gActiveBattler)] = TRUE;
|
||||
gBattleStruct->megaEvolvedPartyIds[GetBattlerSide(gActiveBattler)] |= gBitTable[gBattlerPartyIndexes[gActiveBattler]];
|
||||
break;
|
||||
}
|
||||
|
||||
gBattlescriptCurrInstr += 3;
|
||||
|
@ -5572,3 +5572,60 @@ s32 GetStealthHazardDamage(u8 hazardType, u8 battlerId)
|
||||
|
||||
return dmg;
|
||||
}
|
||||
|
||||
static bool32 IsPartnerMonFromSameTrainer(u8 battlerId)
|
||||
{
|
||||
if (GetBattlerSide(battlerId) == B_SIDE_OPPONENT && gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
|
||||
return FALSE;
|
||||
else if (GetBattlerSide(battlerId) == B_SIDE_PLAYER && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
|
||||
return FALSE;
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
|
||||
return FALSE;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 CanMegaEvolve(u8 battlerId)
|
||||
{
|
||||
u32 i;
|
||||
u16 species, itemId;
|
||||
u8 battlerPosition = GetBattlerPosition(battlerId);
|
||||
u8 partnerPosition = GetBattlerPosition(BATTLE_PARTNER(battlerId));
|
||||
|
||||
// Check if trainer already mega evolved a pokemon.
|
||||
if (gBattleStruct->alreadyMegaEvolved[battlerPosition])
|
||||
return FALSE;
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
{
|
||||
if (IsPartnerMonFromSameTrainer(battlerId) && gBattleStruct->alreadyMegaEvolved[partnerPosition])
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gBattleStruct->alreadyMegaEvolved[partnerPosition])
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Check if the pokemon holds an appropriate item,
|
||||
if (GetBattlerHoldEffect(battlerId, FALSE) != HOLD_EFFECT_MEGA_STONE)
|
||||
return FALSE;
|
||||
|
||||
// Check if there is an entry in the evolution table.
|
||||
species = gBattleMons[battlerId].species;
|
||||
itemId = gBattleMons[battlerId].item;
|
||||
for (i = 0; i < EVOS_PER_MON; i++)
|
||||
{
|
||||
if (gEvolutionTable[species][i].method == EVO_MEGA_EVOLUTION
|
||||
&& gEvolutionTable[species][i].param == itemId)
|
||||
{
|
||||
gBattleStruct->speciesToMegaEvolve[battlerId] = gEvolutionTable[species][i].targetSpecies;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == EVOS_PER_MON)
|
||||
return FALSE;
|
||||
|
||||
// All checks passed, the mon CAN mega evolve.
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -3649,10 +3649,10 @@ const struct Item gItems[] =
|
||||
.secondaryId = 0,
|
||||
},
|
||||
{
|
||||
.name = _("????????"),
|
||||
.itemId = ITEM_NONE,
|
||||
.name = _("Mega Stone"),
|
||||
.itemId = ITEM_MEGA_STONE_TESTING,
|
||||
.price = 0,
|
||||
.holdEffect = HOLD_EFFECT_NONE,
|
||||
.holdEffect = HOLD_EFFECT_MEGA_STONE,
|
||||
.holdEffectParam = 0,
|
||||
.description = gDummyItemDescription,
|
||||
.importance = 0,
|
||||
|
@ -173,7 +173,8 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] =
|
||||
[SPECIES_VIGOROTH] = {{EVO_LEVEL, 36, SPECIES_SLAKING}},
|
||||
[SPECIES_GULPIN] = {{EVO_LEVEL, 26, SPECIES_SWALOT}},
|
||||
[SPECIES_WHISMUR] = {{EVO_LEVEL, 20, SPECIES_LOUDRED}},
|
||||
[SPECIES_LOUDRED] = {{EVO_LEVEL, 40, SPECIES_EXPLOUD}},
|
||||
[SPECIES_LOUDRED] = {{EVO_LEVEL, 40, SPECIES_EXPLOUD},
|
||||
{EVO_MEGA_EVOLUTION, ITEM_MEGA_STONE_TESTING, SPECIES_HO_OH}},
|
||||
[SPECIES_CLAMPERL] = {{EVO_TRADE_ITEM, ITEM_DEEP_SEA_TOOTH, SPECIES_HUNTAIL},
|
||||
{EVO_TRADE_ITEM, ITEM_DEEP_SEA_SCALE, SPECIES_GOREBYSS}},
|
||||
[SPECIES_SHUPPET] = {{EVO_LEVEL, 37, SPECIES_BANETTE}},
|
||||
|
Loading…
Reference in New Issue
Block a user