almost full support for link battles mega evolution

This commit is contained in:
DizzyEggg 2018-09-20 11:23:12 +02:00
parent facd838112
commit 602c1322e4
10 changed files with 125 additions and 54 deletions

View File

@ -4610,7 +4610,7 @@ BattleScript_FocusPunchSetUp::
printstring STRINGID_PKMNTIGHTENINGFOCUS
waitmessage 0x40
end2
BattleScript_MegaEvolution::
printstring STRINGID_MEGAEVOREACTING
waitmessage 0x40

View File

@ -601,7 +601,7 @@ struct BattleStruct
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];
u16 speciesThatMegaEvolved[MAX_BATTLERS_COUNT];
u16 playerSpeciesThatMegaEvolved;
u8 megaEvoBattlerId;
bool8 playerMegaEvoSelect;

View File

@ -78,6 +78,8 @@ void UpdateHpTextInHealthbox(u8 healthboxSpriteId, s16 value, u8 maxOrCurrent);
void SwapHpBarsWithHpText(void);
void SetMegaTriggerSpritePal(u8 spriteId, u8 palId);
void CreateMegaTriggerSprite(u8 battlerId, u8 palId);
bool32 IsMegaTriggerSpriteActive(void);
void HideMegaTriggerSprite(void);
void DestroyMegaTriggerSprite(void);
u8 CreatePartyStatusSummarySprites(u8 battler, struct HpAndStatus *partyInfo, u8 arg2, bool8 isBattleStart);
void Task_HidePartyStatusSummary(u8 taskId);

View File

@ -88,6 +88,7 @@ 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);
u16 GetMegaEvolutionSpecies(u16 preEvoSpecies, u16 heldItemId);
bool32 CanMegaEvolve(u8 battlerId);
void UndoMegaEvolution(u8 monId);

View File

@ -391,7 +391,7 @@ static void HandleInputChooseTarget(void)
else
BtlController_EmitTwoReturnValues(1, 10, gMoveSelectionCursor[gActiveBattler] | (gMultiUsePlayerCursor << 8));
EndBounceEffect(gMultiUsePlayerCursor, BOUNCE_HEALTHBOX);
DestroyMegaTriggerSprite();
HideMegaTriggerSprite();
PlayerBufferExecCompleted();
}
else if (gMain.newKeys & B_BUTTON || gPlayerDpadHoldFrames > 59)
@ -548,7 +548,7 @@ static void HandleInputChooseMove(void)
BtlController_EmitTwoReturnValues(1, 10, gMoveSelectionCursor[gActiveBattler] | RET_MEGA_EVOLUTION | (gMultiUsePlayerCursor << 8));
else
BtlController_EmitTwoReturnValues(1, 10, gMoveSelectionCursor[gActiveBattler] | (gMultiUsePlayerCursor << 8));
DestroyMegaTriggerSprite();
HideMegaTriggerSprite();
PlayerBufferExecCompleted();
}
else
@ -570,7 +570,7 @@ static void HandleInputChooseMove(void)
PlaySE(SE_SELECT);
gBattleStruct->playerMegaEvoSelect = FALSE;
BtlController_EmitTwoReturnValues(1, 10, 0xFFFF);
DestroyMegaTriggerSprite();
HideMegaTriggerSprite();
PlayerBufferExecCompleted();
}
else if (gMain.newKeys & DPAD_LEFT)
@ -641,7 +641,7 @@ static void HandleInputChooseMove(void)
}
else if (gMain.newKeys & START_BUTTON)
{
if (gBattleStruct->megaEvoTriggerSpriteId != 0xFF)
if (CanMegaEvolve(gActiveBattler))
{
gBattleStruct->playerMegaEvoSelect ^= 1;
SetMegaTriggerSpritePal(gBattleStruct->megaEvoTriggerSpriteId, gBattleStruct->playerMegaEvoSelect);
@ -2646,10 +2646,12 @@ static void PlayerHandleChooseMove(void)
else
{
InitMoveSelectionsVarsAndStrings();
gBattlerControllerFuncs[gActiveBattler] = HandleChooseMoveAfterDma3;
gBattleStruct->playerMegaEvoSelect = FALSE;
if (!IsMegaTriggerSpriteActive())
gBattleStruct->megaEvoTriggerSpriteId = 0xFF;
if (CanMegaEvolve(gActiveBattler))
CreateMegaTriggerSprite(gActiveBattler, 0);
gBattlerControllerFuncs[gActiveBattler] = HandleChooseMoveAfterDma3;
}
}

View File

@ -589,7 +589,7 @@ static const struct OamData sOamData_MegaTrigger =
.matrixNum = 0,
.size = 2,
.tileNum = 0,
.priority = 1,
.priority = 3,
.paletteNum = 0,
.affineParam = 0,
};
@ -1554,6 +1554,9 @@ void SetMegaTriggerSpritePal(u8 spriteId, u8 palId)
#define MEGA_TRIGGER_POS_X_DIFF 19
#define MEGA_TRIGGER_POS_Y_DIFF 1
#define tBattler data[0]
#define tHide data[1]
void CreateMegaTriggerSprite(u8 battlerId, u8 palId)
{
if (GetSpriteTileStartByTag(TAG_MEGA_TRIGGER_TILE) == 0xFFFF)
@ -1561,21 +1564,55 @@ void CreateMegaTriggerSprite(u8 battlerId, u8 palId)
if (gBattleStruct->megaEvoTriggerSpriteId == 0xFF)
{
gBattleStruct->megaEvoTriggerSpriteId = CreateSprite(&sSpriteTemplate_MegaTrigger,
gSprites[gHealthboxSpriteIds[battlerId]].pos1.x - MEGA_TRIGGER_POS_X_DIFF,
gSprites[gHealthboxSpriteIds[battlerId]].pos1.x,
gSprites[gHealthboxSpriteIds[battlerId]].pos1.y - MEGA_TRIGGER_POS_Y_DIFF, 0);
gSprites[gBattleStruct->megaEvoTriggerSpriteId].data[0] = battlerId;
gSprites[gBattleStruct->megaEvoTriggerSpriteId].tBattler = battlerId;
}
gSprites[gBattleStruct->megaEvoTriggerSpriteId].tHide = FALSE;
SetMegaTriggerSpritePal(gBattleStruct->megaEvoTriggerSpriteId, palId);
}
static void SpriteCb_MegaTrigger(struct Sprite *sprite)
{
sprite->pos1.x = gSprites[gHealthboxSpriteIds[sprite->data[0]]].pos1.x - MEGA_TRIGGER_POS_X_DIFF;
sprite->pos1.y = gSprites[gHealthboxSpriteIds[sprite->data[0]]].pos1.y - MEGA_TRIGGER_POS_Y_DIFF;
if (sprite->tHide)
{
if (sprite->pos1.x != gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos1.x + MEGA_TRIGGER_POS_X_DIFF)
sprite->pos1.x++;
if (sprite->pos2.x != gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos2.x + MEGA_TRIGGER_POS_X_DIFF)
sprite->pos2.x++;
sprite->pos2.x = gSprites[gHealthboxSpriteIds[sprite->data[0]]].pos2.x - MEGA_TRIGGER_POS_X_DIFF;
sprite->pos2.y = gSprites[gHealthboxSpriteIds[sprite->data[0]]].pos2.y - MEGA_TRIGGER_POS_Y_DIFF;
sprite->pos1.y = gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos1.y - MEGA_TRIGGER_POS_Y_DIFF;
sprite->pos2.y = gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos2.y - MEGA_TRIGGER_POS_Y_DIFF;
if (sprite->pos1.x == gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos1.x + MEGA_TRIGGER_POS_X_DIFF
&& sprite->pos2.x == gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos2.x + MEGA_TRIGGER_POS_X_DIFF)
DestroyMegaTriggerSprite();
}
else
{
if (sprite->pos1.x != gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos1.x - MEGA_TRIGGER_POS_X_DIFF)
sprite->pos1.x--;
if (sprite->pos2.x != gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos2.x - MEGA_TRIGGER_POS_X_DIFF)
sprite->pos2.x--;
sprite->pos1.y = gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos1.y - MEGA_TRIGGER_POS_Y_DIFF;
sprite->pos2.y = gSprites[gHealthboxSpriteIds[sprite->tBattler]].pos2.y - MEGA_TRIGGER_POS_Y_DIFF;
}
}
bool32 IsMegaTriggerSpriteActive(void)
{
if (GetSpriteTileStartByTag(TAG_MEGA_TRIGGER_TILE) == 0xFFFF)
return FALSE;
else if (IndexOfSpritePaletteTag(TAG_MEGA_TRIGGER_OFF_PAL) != 0xFF || IndexOfSpritePaletteTag(TAG_MEGA_TRIGGER_ON_PAL) != 0xFF)
return TRUE;
else
return FALSE;
}
void HideMegaTriggerSprite(void)
{
gSprites[gBattleStruct->megaEvoTriggerSpriteId].tHide = TRUE;
}
void DestroyMegaTriggerSprite(void)
@ -1588,6 +1625,9 @@ void DestroyMegaTriggerSprite(void)
gBattleStruct->megaEvoTriggerSpriteId = 0xFF;
}
#undef tBattler
#undef tHide
#define tBattler data[0]
#define tSummaryBarSpriteId data[1]
#define tBallIconSpriteId(n) data[3 + n]

View File

@ -2579,7 +2579,7 @@ static const u8* TryGetStatusString(u8 *src)
StringGetEnd10(text); \
toCpy = text;
static const u8 *BattleStringGetTrainerName(u16 trainerId, u8 *text, u8 multiplierId)
static const u8 *BattleStringGetTrainerName(u16 trainerId, u8 *text, u8 multiplayerId, u8 battlerId)
{
const u8 *toCpy;
@ -2594,7 +2594,11 @@ static const u8 *BattleStringGetTrainerName(u16 trainerId, u8 *text, u8 multipli
}
else if (trainerId == TRAINER_OPPONENT_C00)
{
toCpy = gLinkPlayers[multiplierId ^ BIT_SIDE].name;
toCpy = gLinkPlayers[multiplayerId ^ BIT_SIDE].name;
}
else if (trainerId == TRAINER_LINK_OPPONENT && gBattleTypeFlags & BATTLE_TYPE_LINK && battlerId != 0xFF)
{
toCpy = gLinkPlayers[GetBattlerMultiplayerId(battlerId)].name;
}
else if (trainerId == TRAINER_FRONTIER_BRAIN)
{
@ -2651,13 +2655,13 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst)
u32 dstID = 0; // if they used dstID, why not use srcID as well?
const u8 *toCpy = NULL;
u8 text[30];
u8 multiplayerID;
u8 multiplayerId;
s32 i;
if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
multiplayerID = gUnknown_0203C7B4;
multiplayerId = gUnknown_0203C7B4;
else
multiplayerID = GetMultiplayerId();
multiplayerId = GetMultiplayerId();
while (*src != EOS)
{
@ -2732,25 +2736,25 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst)
toCpy = text;
break;
case B_TXT_LINK_PLAYER_MON1_NAME: // link first player poke name
GetMonData(&gPlayerParty[gBattlerPartyIndexes[gLinkPlayers[multiplayerID].id]],
GetMonData(&gPlayerParty[gBattlerPartyIndexes[gLinkPlayers[multiplayerId].id]],
MON_DATA_NICKNAME, text);
StringGetEnd10(text);
toCpy = text;
break;
case B_TXT_LINK_OPPONENT_MON1_NAME: // link first opponent poke name
GetMonData(&gEnemyParty[gBattlerPartyIndexes[gLinkPlayers[multiplayerID].id ^ 1]],
GetMonData(&gEnemyParty[gBattlerPartyIndexes[gLinkPlayers[multiplayerId].id ^ 1]],
MON_DATA_NICKNAME, text);
StringGetEnd10(text);
toCpy = text;
break;
case B_TXT_LINK_PLAYER_MON2_NAME: // link second player poke name
GetMonData(&gPlayerParty[gBattlerPartyIndexes[gLinkPlayers[multiplayerID].id ^ 2]],
GetMonData(&gPlayerParty[gBattlerPartyIndexes[gLinkPlayers[multiplayerId].id ^ 2]],
MON_DATA_NICKNAME, text);
StringGetEnd10(text);
toCpy = text;
break;
case B_TXT_LINK_OPPONENT_MON2_NAME: // link second opponent poke name
GetMonData(&gEnemyParty[gBattlerPartyIndexes[gLinkPlayers[multiplayerID].id ^ 3]],
GetMonData(&gEnemyParty[gBattlerPartyIndexes[gLinkPlayers[multiplayerId].id ^ 3]],
MON_DATA_NICKNAME, text);
StringGetEnd10(text);
toCpy = text;
@ -2857,19 +2861,19 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst)
toCpy = BattleStringGetTrainerClass(gTrainerBattleOpponent_A);
break;
case B_TXT_TRAINER1_NAME: // trainer1 name
toCpy = BattleStringGetTrainerName(gTrainerBattleOpponent_A, text, multiplayerID);
toCpy = BattleStringGetTrainerName(gTrainerBattleOpponent_A, text, multiplayerId, 0xFF);
break;
case B_TXT_1E: // link player name?
toCpy = gLinkPlayers[multiplayerID].name;
toCpy = gLinkPlayers[multiplayerId].name;
break;
case B_TXT_1F: // link partner name?
toCpy = gLinkPlayers[GetBattlerMultiplayerId(2 ^ gLinkPlayers[multiplayerID].id)].name;
toCpy = gLinkPlayers[GetBattlerMultiplayerId(2 ^ gLinkPlayers[multiplayerId].id)].name;
break;
case B_TXT_20: // link opponent 1 name?
toCpy = gLinkPlayers[GetBattlerMultiplayerId(1 ^ gLinkPlayers[multiplayerID].id)].name;
toCpy = gLinkPlayers[GetBattlerMultiplayerId(1 ^ gLinkPlayers[multiplayerId].id)].name;
break;
case B_TXT_21: // link opponent 2 name?
toCpy = gLinkPlayers[GetBattlerMultiplayerId(3 ^ gLinkPlayers[multiplayerID].id)].name;
toCpy = gLinkPlayers[GetBattlerMultiplayerId(3 ^ gLinkPlayers[multiplayerId].id)].name;
break;
case B_TXT_22: // link scripting active name
toCpy = gLinkPlayers[GetBattlerMultiplayerId(gBattleScripting.battler)].name;
@ -2957,7 +2961,7 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst)
toCpy = BattleStringGetTrainerClass(gTrainerBattleOpponent_B);
break;
case B_TXT_TRAINER2_NAME:
toCpy = BattleStringGetTrainerName(gTrainerBattleOpponent_B, text, multiplayerID);
toCpy = BattleStringGetTrainerName(gTrainerBattleOpponent_B, text, multiplayerId, 0xFF);
break;
case B_TXT_TRAINER2_LOSE_TEXT:
if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
@ -3012,13 +3016,13 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst)
}
break;
case B_POSITION_OPPONENT_LEFT:
toCpy = BattleStringGetTrainerName(gTrainerBattleOpponent_A, text, multiplayerID);
toCpy = BattleStringGetTrainerName(gTrainerBattleOpponent_A, text, multiplayerId, gBattlerAttacker);
break;
case B_POSITION_OPPONENT_RIGHT:
if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
toCpy = BattleStringGetTrainerName(gTrainerBattleOpponent_B, text, multiplayerID);
toCpy = BattleStringGetTrainerName(gTrainerBattleOpponent_B, text, multiplayerId, gBattlerAttacker);
else
toCpy = BattleStringGetTrainerName(gTrainerBattleOpponent_A, text, multiplayerID);
toCpy = BattleStringGetTrainerName(gTrainerBattleOpponent_A, text, multiplayerId, gBattlerAttacker);
break;
}
break;

View File

@ -6594,7 +6594,15 @@ static void atk76_various(void)
mon = &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]];
else
mon = &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]];
gBattleMons[gActiveBattler].species = gBattleStruct->speciesToMegaEvolve[gActiveBattler];
gBattleStruct->speciesThatMegaEvolved[gActiveBattler] = gBattleMons[gActiveBattler].species;
if (GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_LEFT
|| (GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_RIGHT && !(gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER))))
{
gBattleStruct->playerSpeciesThatMegaEvolved = gBattleStruct->speciesThatMegaEvolved[gActiveBattler];
}
gBattleMons[gActiveBattler].species = GetMegaEvolutionSpecies(gBattleStruct->speciesThatMegaEvolved[gActiveBattler], gBattleMons[gActiveBattler].item);
SetMonData(mon, MON_DATA_SPECIES, &gBattleMons[gActiveBattler].species);
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gActiveBattler].species);
@ -6610,10 +6618,13 @@ static void atk76_various(void)
gBattleMons[gActiveBattler].ability = GetMonAbility(mon);
gBattleMons[gActiveBattler].type1 = gBaseStats[gBattleMons[gActiveBattler].species].type1;
gBattleMons[gActiveBattler].type2 = gBaseStats[gBattleMons[gActiveBattler].species].type2;
UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], mon, HEALTHBOX_ALL);
UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], mon, HEALTHBOX_ALL);
gBattleStruct->alreadyMegaEvolved[GetBattlerPosition(gActiveBattler)] = TRUE;
gBattleStruct->megaEvolvedPartyIds[GetBattlerSide(gActiveBattler)] |= gBitTable[gBattlerPartyIndexes[gActiveBattler]];
BtlController_EmitSetMonData(0, REQUEST_ALL_BATTLE, gBitTable[gBattlerPartyIndexes[gActiveBattler]], sizeof(struct BattlePokemon), &gBattleMons[gActiveBattler]);
MarkBattlerForControllerExec(gActiveBattler);
break;
}

View File

@ -5586,10 +5586,23 @@ static bool32 IsPartnerMonFromSameTrainer(u8 battlerId)
return TRUE;
}
bool32 CanMegaEvolve(u8 battlerId)
u16 GetMegaEvolutionSpecies(u16 preEvoSpecies, u16 heldItemId)
{
u32 i;
u16 species, itemId;
for (i = 0; i < EVOS_PER_MON; i++)
{
if (gEvolutionTable[preEvoSpecies][i].method == EVO_MEGA_EVOLUTION
&& gEvolutionTable[preEvoSpecies][i].param == heldItemId)
return gEvolutionTable[preEvoSpecies][i].targetSpecies;
}
return SPECIES_NONE;
}
bool32 CanMegaEvolve(u8 battlerId)
{
u32 itemId, holdEffect;
struct Pokemon *mon;
u8 battlerPosition = GetBattlerPosition(battlerId);
u8 partnerPosition = GetBattlerPosition(BATTLE_PARTNER(battlerId));
@ -5602,27 +5615,23 @@ bool32 CanMegaEvolve(u8 battlerId)
return FALSE;
}
// Check if the pokemon holds an appropriate item,
if (GetBattlerHoldEffect(battlerId, FALSE) != HOLD_EFFECT_MEGA_STONE)
// Check if the pokemon holds an appropriate item.
if (GetBattlerSide(battlerId) == B_SIDE_OPPONENT)
mon = &gEnemyParty[gBattlerPartyIndexes[battlerId]];
else
mon = &gPlayerParty[gBattlerPartyIndexes[battlerId]];
itemId = GetMonData(mon, MON_DATA_HELD_ITEM);
if (itemId != ITEM_ENIGMA_BERRY)
holdEffect = ItemId_GetHoldEffect(itemId);
else
holdEffect = gEnigmaBerries[battlerId].holdEffect;
if (holdEffect != 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;
if (battlerPosition == B_POSITION_PLAYER_LEFT
|| (battlerPosition == B_POSITION_PLAYER_RIGHT && !(gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER))))
gBattleStruct->playerSpeciesThatMegaEvolved = species;
break;
}
}
if (i == EVOS_PER_MON)
if (GetMegaEvolutionSpecies(GetMonData(mon, MON_DATA_SPECIES), itemId) == SPECIES_NONE)
return FALSE;
// All checks passed, the mon CAN mega evolve.

View File

@ -188,6 +188,8 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] =
[SPECIES_SHELGON] = {{EVO_LEVEL, 50, SPECIES_SALAMENCE}},
[SPECIES_BELDUM] = {{EVO_LEVEL, 20, SPECIES_METANG}},
[SPECIES_METANG] = {{EVO_LEVEL, 45, SPECIES_METAGROSS}},
[SPECIES_SKARMORY] = {{EVO_LEVEL, 40, SPECIES_EXPLOUD},
{EVO_MEGA_EVOLUTION, ITEM_MEGA_STONE_TESTING, SPECIES_HO_OH}},
};
#endif //POKEEMERALD_EVOLUTION_H