changed all ability variables to u16 or larger

added ability capsule and ability patch functionality
removed unused ribbons to free space in pokemonsubstruct3 for hidden ability
This commit is contained in:
cawtds 2024-04-26 22:09:46 +02:00
parent 1e892f14fe
commit d17698ee8f
30 changed files with 311 additions and 84 deletions

View File

@ -150,7 +150,7 @@
.macro jumpifability param0:req, ability:req, ptr:req
.byte 0x1e
.byte \param0
.byte \ability
.2byte \ability
.4byte \ptr
.endm
@ -372,7 +372,7 @@
.macro jumpifabilitypresent ability:req, ptr:req
.byte 0x43
.byte \ability
.2byte \ability
.4byte \ptr
.endm

View File

@ -92,12 +92,8 @@ ViridianCity_Mart_Items::
.2byte ITEM_FIRE_STONE
.2byte ITEM_ICE_STONE
.2byte ITEM_BLACK_AUGURITE
.2byte ITEM_POMEG_BERRY
.2byte ITEM_KELPSY_BERRY
.2byte ITEM_QUALOT_BERRY
.2byte ITEM_HONDEW_BERRY
.2byte ITEM_GREPA_BERRY
.2byte ITEM_TAMATO_BERRY
.2byte ITEM_ABILITY_CAPSULE
.2byte ITEM_ABILITY_PATCH
.2byte ITEM_NONE
release
end

View File

@ -296,7 +296,7 @@ struct UsedMoves
struct BattleHistory
{
/*0x00*/ u16 usedMoves[2][8]; // 0xFFFF means move not used (confuse self hit, etc)
/*0x20*/ u8 abilities[MAX_BATTLERS_COUNT / 2];
/*0x20*/ u16 abilities[MAX_BATTLERS_COUNT / 2];
/*0x22*/ u8 itemEffects[MAX_BATTLERS_COUNT / 2];
/*0x24*/ u16 trainerItems[MAX_BATTLERS_COUNT];
/*0x2C*/ u8 itemsNo;
@ -426,7 +426,7 @@ struct BattleStruct
u8 simulatedInputState[4]; // used by Oak/Old Man/Pokedude controllers
u8 lastTakenMove[MAX_BATTLERS_COUNT * 2 * 2]; // ask gamefreak why they declared it that way
u16 hpOnSwitchout[2];
u8 abilityPreventingSwitchout;
u16 abilityPreventingSwitchout;
u8 hpScale;
u16 savedBattleTypeFlags;
void (*savedCallback)(void);
@ -656,7 +656,7 @@ extern u16 gChosenMove;
extern u16 gCalledMove;
extern u8 gCritMultiplier;
extern u16 gBattleWeather;
extern u8 gLastUsedAbility;
extern u16 gLastUsedAbility;
extern u8 gBattlerInMenuId;
extern u8 gPotentialItemEffectBattler;
extern u8 gBattlersCount;

View File

@ -12,7 +12,7 @@ void BattleAI_HandleItemUseBeforeAISetup(void);
void BattleAI_SetupAIData(void);
u8 BattleAI_ChooseMoveOrAction(void);
void ClearBankMoveHistory(u8 bank);
void RecordAbilityBattle(u8 bank, u8 abilityId);
void RecordAbilityBattle(u8 bank, u16 abilityId);
void ClearBankAbilityHistory(u8 bank);
void RecordItemEffectBattle(u8 bank, u8 itemEffect);
void ClearBankItemEffectHistory(u8 bank);

View File

@ -224,7 +224,7 @@ void BtlController_EmitPrintSelectionString(u8 bufferId, u16 stringId);
void BtlController_EmitChooseAction(u8 bufferId, u8 action, u16 itemId);
void BtlController_EmitChooseMove(u8 bufferId, bool8 isDoubleBattle, bool8 NoPpNumber, struct ChooseMoveStruct *movePpData);
void BtlController_EmitChooseItem(u8 bufferId, u8 *arg1);
void BtlController_EmitChoosePokemon(u8 bufferId, u8 caseId, u8 arg2, u8 abilityId, u8 *arg4);
void BtlController_EmitChoosePokemon(u8 bufferId, u8 caseId, u8 arg2, u16 abilityId, u8 *arg4);
void BtlController_EmitHealthBarUpdate(u8 bufferId, u16 hpValue);
void BtlController_EmitExpUpdate(u8 bufferId, u8 partyId, u16 expPoints);
void BtlController_EmitStatusIconUpdate(u8 bufferId, u32 status1, u32 status2);

View File

@ -198,13 +198,13 @@ struct BattleMsgData
u16 currentMove;
u16 originallyUsedMove;
u16 lastItem;
u8 lastAbility;
u16 lastAbility;
u8 scrActive;
u8 bakScriptPartyIdx;
u8 hpScale;
u8 itemEffectBattler;
u8 moveType;
u8 abilities[4];
u16 abilities[4];
u8 textBuffs[3][0x10];
};

View File

@ -9,7 +9,7 @@
void AI_CalcDmg(u8 attacker, u8 defender);
u8 TypeCalc(u16 move, u8 attacker, u8 defender);
u8 AI_TypeCalc(u16 move, u16 targetSpecies, u8 targetAbility);
u8 AI_TypeCalc(u16 move, u16 targetSpecies, u16 targetAbility);
u8 GetBattlerTurnOrderNum(u8 battlerId);
void SetMoveEffect(bool8 primary, u8 certain);
bool32 IsMonGettingExpSentOut(void);

View File

@ -85,7 +85,7 @@ void TryClearRageStatuses(void);
u8 AtkCanceller_UnableToUseMove(void);
bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2);
u8 CastformDataTypeChange(u8 battler);
u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveArg);
u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 moveArg);
void BattleScriptExecute(const u8 *BS_ptr);
void BattleScriptPushCursorAndCallback(const u8 *BS_ptr);
u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn);

View File

@ -81,16 +81,16 @@
#define MON_DATA_NATIONAL_RIBBON 76
#define MON_DATA_EARTH_RIBBON 77
#define MON_DATA_WORLD_RIBBON 78
#define MON_DATA_UNUSED_RIBBONS 79
#define MON_DATA_MODERN_FATEFUL_ENCOUNTER 80
#define MON_DATA_KNOWN_MOVES 81
#define MON_DATA_RIBBON_COUNT 82
#define MON_DATA_RIBBONS 83
#define MON_DATA_ATK2 84
#define MON_DATA_DEF2 85
#define MON_DATA_SPEED2 86
#define MON_DATA_SPATK2 87
#define MON_DATA_SPDEF2 88
// #define MON_DATA_UNUSED_RIBBONS 79
#define MON_DATA_MODERN_FATEFUL_ENCOUNTER 79
#define MON_DATA_KNOWN_MOVES 80
#define MON_DATA_RIBBON_COUNT 81
#define MON_DATA_RIBBONS 82
#define MON_DATA_ATK2 83
#define MON_DATA_DEF2 84
#define MON_DATA_SPEED2 85
#define MON_DATA_SPATK2 86
#define MON_DATA_SPDEF2 87
// Pokemon types
#define TYPE_NONE 255

View File

@ -7,6 +7,8 @@ void Task_ItemUse_CloseMessageBoxAndReturnToField_VsSeeker(u8);
void Task_UseDigEscapeRopeOnField(u8 taskId);
void ItemUse_SetQuestLogEvent(u8, struct Pokemon *, u16, u16);
void ItemUseOutOfBattle_AbilityCapsule(u8);
void ItemUseOutOfBattle_AbilityPatch(u8);
void ItemUseOutOfBattle_BerryPouch(u8 taskId);
void ItemUseOutOfBattle_Bike(u8 taskId);
void ItemUseOutOfBattle_BlackWhiteFlute(u8 taskId);
@ -34,7 +36,6 @@ void ItemUseOutOfBattle_TownMap(u8 taskId);
void ItemUseOutOfBattle_VsSeeker(u8 taskId);
void ItemUseOutOfBattle_CannotUse(u8 taskId);
void ItemUseInBattle_BagMenu(u8 taskId);
// void ItemUseInBattle_BerryPouch(u8 taskId);
void ItemUseInBattle_PartyMenu(u8 taskId);
void ItemUseInBattle_PartyMenuChooseMove(u8 taskId);
u8 CanUseEscapeRopeOnCurrMap(void);

View File

@ -51,6 +51,8 @@ bool8 FieldCallback_PrepareFadeInFromMenu(void);
void CB2_ReturnToPartyMenuFromFlyMap(void);
void SetUsedFlyQuestLogEvent(const u8 *healLocCtrlData);
void CB2_ShowPartyMenuForItemUse(void);
void ItemUseCB_AbilityCapsule(u8 taskId, TaskFunc task);
void ItemUseCB_AbilityPatch(u8 taskId, TaskFunc task);
void ItemUseCB_BattleScript(u8 taskId, TaskFunc task);
void ItemUseCB_Medicine(u8 taskId, TaskFunc func);
void ItemUseCB_ReduceEV(u8 taskId, TaskFunc task);

View File

@ -58,7 +58,7 @@ struct PokemonSubstruct3
/* 0x05 */ u32 spAttackIV:5;
/* 0x06 */ u32 spDefenseIV:5;
/* 0x07 */ u32 isEgg:1;
/* 0x07 */ u32 abilityNum:1;
/* 0x07 */ u32 abilityNum:2;
/* 0x08 */ u32 coolRibbon:3; // Stores the highest contest rank achieved in the Cool category.
/* 0x08 */ u32 beautyRibbon:3; // Stores the highest contest rank achieved in the Beauty category.
@ -77,7 +77,7 @@ struct PokemonSubstruct3
/* 0x0B */ u32 nationalRibbon:1; // Given to purified Shadow Pokémon in Colosseum/XD.
/* 0x0B */ u32 earthRibbon:1; // Given to teams that have beaten Mt. Battle's 100-battle challenge in Colosseum/XD.
/* 0x0B */ u32 worldRibbon:1; // Distributed during Pokémon Festa '04 and '05 to tournament winners.
/* 0x0B */ u32 unusedRibbons:4; // Discarded in Gen 4.
/* 0x0B */ u32 unusedRibbons:3; // Discarded in Gen 4.
// The functionality of this bit changed in FRLG:
// In RS, this bit does nothing, is never set, & is accidentally unset when hatching Eggs.
@ -187,9 +187,9 @@ struct BattlePokemon
/*0x16*/ u32 spAttackIV:5;
/*0x17*/ u32 spDefenseIV:5;
/*0x17*/ u32 isEgg:1;
/*0x17*/ u32 abilityNum:1;
/*0x17*/ u32 abilityNum:2;
/*0x18*/ s8 statStages[NUM_BATTLE_STATS];
/*0x20*/ u8 ability;
/*0x20*/ u16 ability;
/*0x21*/ u8 type1;
/*0x22*/ u8 type2;
/*0x23*/ u8 unknown;
@ -440,8 +440,8 @@ u8 GiveMonToPlayer(struct Pokemon *mon);
u8 CalculatePlayerPartyCount(void);
u8 CalculateEnemyPartyCount(void);
u8 GetMonsStateToDoubles(void);
u8 GetAbilityBySpecies(u16 species, bool8 abilityNum);
u8 GetMonAbility(struct Pokemon *mon);
u16 GetAbilityBySpecies(u16 species, bool8 abilityNum);
u16 GetMonAbility(struct Pokemon *mon);
u8 GetSecretBaseTrainerPicIndex(void);
u8 GetSecretBaseTrainerNameIndex(void);
bool8 IsPlayerPartyAndPokemonStorageFull(void);

View File

@ -482,7 +482,7 @@ static void ClearBattlerMoveHistory(u8 battlerId)
BATTLE_HISTORY->usedMoves[battlerId / 2][i] = MOVE_NONE;
}
void RecordAbilityBattle(u8 battlerId, u8 abilityId)
void RecordAbilityBattle(u8 battlerId, u16 abilityId)
{
if (GetBattlerSide(battlerId) == 0)
BATTLE_HISTORY->abilities[GET_BATTLER_SIDE(battlerId)] = abilityId;
@ -1152,7 +1152,7 @@ static void Cmd_get_ability(void)
{
u16 side = GET_BATTLER_SIDE(battlerId);
if (BATTLE_HISTORY->abilities[side] != 0)
if (BATTLE_HISTORY->abilities[side] != ABILITY_NONE)
{
AI_THINKING_STRUCT->funcResult = BATTLE_HISTORY->abilities[side];
sAIScriptPtr += 2;

View File

@ -83,7 +83,7 @@ static bool8 ShouldSwitchIfWonderGuard(void)
static bool8 FindMonThatAbsorbsOpponentsMove(void)
{
u8 battlerIn1, battlerIn2;
u8 absorbingTypeAbility;
u16 absorbingTypeAbility;
s32 i;
if ((HasSuperEffectiveMoveAgainstOpponents(TRUE) && Random() % 3)
@ -118,7 +118,7 @@ static bool8 FindMonThatAbsorbsOpponentsMove(void)
for (i = 0; i < PARTY_SIZE; ++i)
{
u16 species;
u8 monAbility;
u16 monAbility;
if ((GetMonData(&gEnemyParty[i], MON_DATA_HP) == 0)
|| (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES_OR_EGG) == SPECIES_NONE)
@ -263,7 +263,7 @@ static bool8 FindMonWithFlagsAndSuperEffective(u8 flags, u8 moduloPercent)
for (i = 0; i < PARTY_SIZE; ++i)
{
u16 species;
u8 monAbility;
u16 monAbility;
if ((GetMonData(&gEnemyParty[i], MON_DATA_HP) == 0)
|| (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES_OR_EGG) == SPECIES_NONE)

View File

@ -1888,7 +1888,7 @@ static void OakOldManHandleChoosePokemon(void)
gTasks[gBattleControllerData[gActiveBattler]].data[0] = gBattleBufferA[gActiveBattler][1] & 0xF;
*(&gBattleStruct->battlerPreventingSwitchout) = gBattleBufferA[gActiveBattler][1] >> 4;
*(&gBattleStruct->playerPartyIdx) = gBattleBufferA[gActiveBattler][2];
*(&gBattleStruct->abilityPreventingSwitchout) = gBattleBufferA[gActiveBattler][3];
*(&gBattleStruct->abilityPreventingSwitchout) = (gBattleBufferA[gActiveBattler][3] & 0xFF) | (gBattleBufferA[gActiveBattler][7] << 8);
for (i = 0; i < 3; ++i)
gBattlePartyCurrentOrder[i] = gBattleBufferA[gActiveBattler][4 + i];
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK);

View File

@ -2466,7 +2466,7 @@ static void PlayerHandleChoosePokemon(void)
gTasks[gBattleControllerData[gActiveBattler]].data[0] = gBattleBufferA[gActiveBattler][1] & 0xF;
*(&gBattleStruct->battlerPreventingSwitchout) = gBattleBufferA[gActiveBattler][1] >> 4;
*(&gBattleStruct->playerPartyIdx) = gBattleBufferA[gActiveBattler][2];
*(&gBattleStruct->abilityPreventingSwitchout) = gBattleBufferA[gActiveBattler][3];
*(&gBattleStruct->abilityPreventingSwitchout) = (gBattleBufferA[gActiveBattler][3] & 0xFF) | (gBattleBufferA[gActiveBattler][7] << 8);
for (i = 0; i < 3; ++i)
gBattlePartyCurrentOrder[i] = gBattleBufferA[gActiveBattler][4 + i];
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK);

View File

@ -1624,7 +1624,7 @@ static void PokedudeHandleChoosePokemon(void)
gTasks[gBattleControllerData[gActiveBattler]].data[0] = gBattleBufferA[gActiveBattler][1] & 0xF;
*(&gBattleStruct->battlerPreventingSwitchout) = gBattleBufferA[gActiveBattler][1] >> 4;
*(&gBattleStruct->playerPartyIdx) = gBattleBufferA[gActiveBattler][2];
*(&gBattleStruct->abilityPreventingSwitchout) = gBattleBufferA[gActiveBattler][3];
*(&gBattleStruct->abilityPreventingSwitchout) = (gBattleBufferA[gActiveBattler][3] & 0xFF) | (gBattleBufferA[gActiveBattler][7] << 8);
for (i = 0; i < 3; ++i)
gBattlePartyCurrentOrder[i] = gBattleBufferA[gActiveBattler][4 + i];
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK);

View File

@ -872,14 +872,15 @@ void BtlController_EmitChooseItem(u8 bufferId, u8 *battlePartyOrder)
PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4);
}
void BtlController_EmitChoosePokemon(u8 bufferId, u8 caseId, u8 slotId, u8 abilityId, u8 *data)
void BtlController_EmitChoosePokemon(u8 bufferId, u8 caseId, u8 slotId, u16 abilityId, u8 *data)
{
s32 i;
sBattleBuffersTransferData[0] = CONTROLLER_CHOOSEPOKEMON;
sBattleBuffersTransferData[1] = caseId;
sBattleBuffersTransferData[2] = slotId;
sBattleBuffersTransferData[3] = abilityId;
sBattleBuffersTransferData[3] = abilityId & 0xFF;
sBattleBuffersTransferData[7] = (abilityId >> 8) & 0xFF;
for (i = 0; i < 3; i++)
sBattleBuffersTransferData[4 + i] = data[i];
PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 8); // Only 7 bytes were written.

View File

@ -159,7 +159,7 @@ EWRAM_DATA s32 gBattleMoveDamage = 0;
EWRAM_DATA s32 gHpDealt = 0;
EWRAM_DATA s32 gTakenDmg[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA u16 gLastUsedItem = 0;
EWRAM_DATA u8 gLastUsedAbility = 0;
EWRAM_DATA u16 gLastUsedAbility = 0;
EWRAM_DATA u8 gBattlerAttacker = 0;
EWRAM_DATA u8 gBattlerTarget = 0;
EWRAM_DATA u8 gBattlerFainted = 0;

View File

@ -35,7 +35,7 @@ struct BattleWindowText
u8 shadowColor;
};
static EWRAM_DATA u8 sBattlerAbilities[MAX_BATTLERS_COUNT] = {};
static EWRAM_DATA u16 sBattlerAbilities[MAX_BATTLERS_COUNT] = {};
static EWRAM_DATA struct BattleMsgData *sBattleMsgDataPtr = NULL;
static void ChooseMoveUsedParticle(u8 *textPtr);

View File

@ -1552,7 +1552,7 @@ u8 TypeCalc(u16 move, u8 attacker, u8 defender)
return flags;
}
u8 AI_TypeCalc(u16 move, u16 targetSpecies, u8 targetAbility)
u8 AI_TypeCalc(u16 move, u16 targetSpecies, u16 targetAbility)
{
s32 i = 0;
u8 flags = 0;
@ -3022,48 +3022,49 @@ static void Cmd_jumpifstatus2(void)
static void Cmd_jumpifability(void)
{
u8 battlerId;
u8 ability = gBattlescriptCurrInstr[2];
const u8 *jumpPtr = T2_READ_PTR(gBattlescriptCurrInstr + 3);
CMD_ARGS(u8 battler, u16 ability, const u8 *jumpInstr);
u32 battlerId;
bool32 hasAbility = FALSE;
u32 ability = cmd->ability;
if (gBattlescriptCurrInstr[1] == BS_ATTACKER_SIDE)
if (cmd->battler == BS_ATTACKER_SIDE)
{
battlerId = AbilityBattleEffects(ABILITYEFFECT_CHECK_BATTLER_SIDE, gBattlerAttacker, ability, 0, 0);
if (battlerId)
{
gLastUsedAbility = ability;
gBattlescriptCurrInstr = jumpPtr;
gBattlescriptCurrInstr = cmd->jumpInstr;
RecordAbilityBattle(battlerId - 1, gLastUsedAbility);
gBattleScripting.battlerWithAbility = battlerId - 1;
}
else
gBattlescriptCurrInstr += 7;
gBattlescriptCurrInstr = cmd->nextInstr;
}
else if (gBattlescriptCurrInstr[1] == BS_NOT_ATTACKER_SIDE)
else if (cmd->battler == BS_NOT_ATTACKER_SIDE)
{
battlerId = AbilityBattleEffects(ABILITYEFFECT_CHECK_OTHER_SIDE, gBattlerAttacker, ability, 0, 0);
if (battlerId)
{
gLastUsedAbility = ability;
gBattlescriptCurrInstr = jumpPtr;
gBattlescriptCurrInstr = cmd->jumpInstr;
RecordAbilityBattle(battlerId - 1, gLastUsedAbility);
gBattleScripting.battlerWithAbility = battlerId - 1;
}
else
gBattlescriptCurrInstr += 7;
gBattlescriptCurrInstr = cmd->nextInstr;
}
else
{
battlerId = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]);
battlerId = GetBattlerForBattleScript(cmd->battler);
if (gBattleMons[battlerId].ability == ability)
{
gLastUsedAbility = ability;
gBattlescriptCurrInstr = jumpPtr;
gBattlescriptCurrInstr = cmd->jumpInstr;
RecordAbilityBattle(battlerId, gLastUsedAbility);
gBattleScripting.battlerWithAbility = battlerId;
}
else
gBattlescriptCurrInstr += 7;
gBattlescriptCurrInstr = cmd->nextInstr;
}
}
@ -3889,10 +3890,13 @@ static void Cmd_jumpiftype2(void)
static void Cmd_jumpifabilitypresent(void)
{
if (AbilityBattleEffects(ABILITYEFFECT_CHECK_ON_FIELD, 0, gBattlescriptCurrInstr[1], 0, 0))
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2);
CMD_ARGS(u16 ability, const u8 *jumpInstr);
u16 ability = cmd->ability;
if (AbilityBattleEffects(ABILITYEFFECT_CHECK_ON_FIELD, 0, ability, 0, 0))
gBattlescriptCurrInstr = cmd->jumpInstr;
else
gBattlescriptCurrInstr += 6;
gBattlescriptCurrInstr = cmd->nextInstr;
}
static void Cmd_endselectionscript(void)
@ -8108,7 +8112,7 @@ static void Cmd_healpartystatus(void)
if (species != SPECIES_NONE && species != SPECIES_EGG)
{
u8 ability;
u16 ability;
if (gBattlerPartyIndexes[gBattlerAttacker] == i)
ability = gBattleMons[gBattlerAttacker].ability;
@ -9070,7 +9074,7 @@ static void Cmd_tryswapabilities(void)
}
else
{
u8 abilityAtk = gBattleMons[gBattlerAttacker].ability;
u16 abilityAtk = gBattleMons[gBattlerAttacker].ability;
gBattleMons[gBattlerAttacker].ability = gBattleMons[gBattlerTarget].ability;
gBattleMons[gBattlerTarget].ability = abilityAtk;

View File

@ -1643,7 +1643,7 @@ u8 CastformDataTypeChange(u8 battler)
return formChange;
}
u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveArg)
u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 moveArg)
{
u8 effect = 0;
struct Pokemon *pokeAtk;

View File

@ -1357,7 +1357,7 @@ const struct Item gItems[] =
"mon's ability."),
.pocket = POCKET_ITEMS,
.type = ITEM_TYPE_PARTY_MENU,
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
.fieldUseFunc = ItemUseOutOfBattle_AbilityCapsule,
},
[ITEM_ABILITY_PATCH] =
@ -1372,7 +1372,7 @@ const struct Item gItems[] =
"a rare ability."),
.pocket = POCKET_ITEMS,
.type = ITEM_TYPE_PARTY_MENU,
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
.fieldUseFunc = ItemUseOutOfBattle_AbilityPatch,
},
// Mints
@ -9363,7 +9363,7 @@ const struct Item gItems[] =
[ITEM_TM10] =
{
.name = _("TM10"),
.price = 2,
.price = 10000,
.description = COMPOUND_STRING(
"The attack power\n"
"varies among\n"

View File

@ -560,7 +560,7 @@ static void CreateShedinja(u16 preEvoSpecies, struct Pokemon* mon)
for (i = MON_DATA_COOL_RIBBON; i < MON_DATA_COOL_RIBBON + CONTEST_CATEGORIES_COUNT; i++)
SetMonData(&gPlayerParty[gPlayerPartyCount], i, &data);
for (i = MON_DATA_CHAMPION_RIBBON; i <= MON_DATA_UNUSED_RIBBONS; i++)
for (i = MON_DATA_CHAMPION_RIBBON; i <= MON_DATA_WORLD_RIBBON; i++)
SetMonData(&gPlayerParty[gPlayerPartyCount], i, &data);
SetMonData(&gPlayerParty[gPlayerPartyCount], MON_DATA_STATUS, &data);

View File

@ -178,6 +178,18 @@ static void Task_ItemUseWaitForFade(u8 taskId)
}
}
void ItemUseOutOfBattle_AbilityCapsule(u8 taskId)
{
gItemUseCB = ItemUseCB_AbilityCapsule;
SetUpItemUseCallback(taskId);
}
void ItemUseOutOfBattle_AbilityPatch(u8 taskId)
{
gItemUseCB = ItemUseCB_AbilityPatch;
SetUpItemUseCallback(taskId);
}
void ItemUseOutOfBattle_Mail(u8 taskId)
{
ItemMenu_SetExitCallback(CB2_CheckMail);

View File

@ -125,7 +125,7 @@ void NewGameInitData(void)
ClearPokedexFlags();
InitEventData();
ResetFameChecker();
SetMoney(&gSaveBlock1Ptr->money, 3000);
SetMoney(&gSaveBlock1Ptr->money, 900000); // change back to 3000
ResetGameStats();
ClearPlayerLinkBattleRecords();
InitHeracrossSizeRecord();

View File

@ -4428,6 +4428,209 @@ static bool8 IsItemFlute(u16 item)
return FALSE;
}
#define tState data[0]
#define tSpecies data[1]
#define tAbilityNum data[2]
#define tMonId data[3]
#define tOldFunc 4
void Task_AbilityCapsule(u8 taskId)
{
static const u8 askText[] = _("Would you like to change {STR_VAR_1}'s\nability to {STR_VAR_2}?");
static const u8 doneText[] = _("{STR_VAR_1}'s ability became\n{STR_VAR_2}!{PAUSE_UNTIL_PRESS}");
s16 *data = gTasks[taskId].data;
DebugPrintfLevel(MGBA_LOG_ERROR, "species: %s", gSpeciesInfo[tSpecies].speciesName);
DebugPrintfLevel(MGBA_LOG_ERROR, "ability1: %s", gAbilityNames[gSpeciesInfo[tSpecies].abilities[0]]);
DebugPrintfLevel(MGBA_LOG_ERROR, "ability2: %s", gAbilityNames[gSpeciesInfo[tSpecies].abilities[1]]);
DebugPrintfLevel(MGBA_LOG_ERROR, "ability3: %s", gAbilityNames[gSpeciesInfo[tSpecies].abilities[2]]);
switch (tState)
{
case 0:
// Can't use.
if (gSpeciesInfo[tSpecies].abilities[0] == gSpeciesInfo[tSpecies].abilities[1]
|| gSpeciesInfo[tSpecies].abilities[1] == ABILITY_NONE
|| tAbilityNum > 1
|| !tSpecies)
{
gPartyMenuUseExitCallback = FALSE;
PlaySE(SE_SELECT);
DisplayPartyMenuMessage(gText_WontHaveEffect, 1);
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = Task_ClosePartyMenuAfterText;
return;
}
gPartyMenuUseExitCallback = TRUE;
GetMonNickname(&gPlayerParty[tMonId], gStringVar1);
StringCopy(gStringVar2, gAbilityNames[GetAbilityBySpecies(tSpecies, tAbilityNum)]);
StringExpandPlaceholders(gStringVar4, askText);
PlaySE(SE_SELECT);
DisplayPartyMenuMessage(gStringVar4, 1);
ScheduleBgCopyTilemapToVram(2);
tState++;
break;
case 1:
if (!IsPartyMenuTextPrinterActive())
{
PartyMenuDisplayYesNoMenu();
tState++;
}
break;
case 2:
switch (Menu_ProcessInputNoWrapClearOnChoose())
{
case 0:
tState++;
break;
case 1:
case MENU_B_PRESSED:
gPartyMenuUseExitCallback = FALSE;
PlaySE(SE_SELECT);
ScheduleBgCopyTilemapToVram(2);
// Don't exit party selections screen, return to choosing a mon.
ClearStdWindowAndFrameToTransparent(6, 0);
ClearWindowTilemap(6);
DisplayPartyMenuStdMessage(5);
gTasks[taskId].func = (void *)GetWordTaskArg(taskId, tOldFunc);
return;
}
break;
case 3:
PlaySE(SE_USE_ITEM);
StringExpandPlaceholders(gStringVar4, doneText);
DisplayPartyMenuMessage(gStringVar4, 1);
ScheduleBgCopyTilemapToVram(2);
tState++;
break;
case 4:
if (!IsPartyMenuTextPrinterActive())
tState++;
break;
case 5:
SetMonData(&gPlayerParty[tMonId], MON_DATA_ABILITY_NUM, &tAbilityNum);
RemoveBagItem(gSpecialVar_ItemId, 1);
gTasks[taskId].func = Task_ClosePartyMenu;
break;
}
}
void ItemUseCB_AbilityCapsule(u8 taskId, TaskFunc task)
{
s16 *data = gTasks[taskId].data;
tState = 0;
tMonId = gPartyMenu.slotId;
tSpecies = GetMonData(&gPlayerParty[tMonId], MON_DATA_SPECIES, NULL);
tAbilityNum = GetMonData(&gPlayerParty[tMonId], MON_DATA_ABILITY_NUM, NULL) ^ 1;
SetWordTaskArg(taskId, tOldFunc, (uintptr_t)(gTasks[taskId].func));
gTasks[taskId].func = Task_AbilityCapsule;
}
void Task_AbilityPatch(u8 taskId)
{
static const u8 askText[] = _("Would you like to change {STR_VAR_1}'s\nability to {STR_VAR_2}?");
static const u8 doneText[] = _("{STR_VAR_1}'s ability became\n{STR_VAR_2}!{PAUSE_UNTIL_PRESS}");
s16 *data = gTasks[taskId].data;
DebugPrintfLevel(MGBA_LOG_ERROR, "species: %S", gSpeciesInfo[tSpecies].speciesName);
DebugPrintfLevel(MGBA_LOG_ERROR, "ability1: %S", gAbilityNames[gSpeciesInfo[tSpecies].abilities[0]]);
DebugPrintfLevel(MGBA_LOG_ERROR, "ability2: %S", gAbilityNames[gSpeciesInfo[tSpecies].abilities[1]]);
DebugPrintfLevel(MGBA_LOG_ERROR, "ability3: %S", gAbilityNames[gSpeciesInfo[tSpecies].abilities[2]]);
switch (tState)
{
case 0:
// Can't use.
if (gSpeciesInfo[tSpecies].abilities[tAbilityNum] == 0
|| !tSpecies
)
{
gPartyMenuUseExitCallback = FALSE;
PlaySE(SE_SELECT);
DisplayPartyMenuMessage(gText_WontHaveEffect, 1);
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = Task_ClosePartyMenuAfterText;
return;
}
gPartyMenuUseExitCallback = TRUE;
GetMonNickname(&gPlayerParty[tMonId], gStringVar1);
DebugPrintfLevel(MGBA_LOG_ERROR, "tAbilityNum: %d", tAbilityNum);
DebugPrintfLevel(MGBA_LOG_ERROR, "abilityName: %S", gAbilityNames[GetAbilityBySpecies(tSpecies, tAbilityNum)]);
StringCopy(gStringVar2, gAbilityNames[GetAbilityBySpecies(tSpecies, tAbilityNum)]);
StringExpandPlaceholders(gStringVar4, askText);
PlaySE(SE_SELECT);
DisplayPartyMenuMessage(gStringVar4, 1);
ScheduleBgCopyTilemapToVram(2);
tState++;
break;
case 1:
if (!IsPartyMenuTextPrinterActive())
{
PartyMenuDisplayYesNoMenu();
tState++;
}
break;
case 2:
switch (Menu_ProcessInputNoWrapClearOnChoose())
{
case 0:
tState++;
break;
case 1:
case MENU_B_PRESSED:
gPartyMenuUseExitCallback = FALSE;
PlaySE(SE_SELECT);
ScheduleBgCopyTilemapToVram(2);
// Don't exit party selections screen, return to choosing a mon.
ClearStdWindowAndFrameToTransparent(6, 0);
ClearWindowTilemap(6);
DisplayPartyMenuStdMessage(5);
gTasks[taskId].func = (void *)GetWordTaskArg(taskId, tOldFunc);
return;
}
break;
case 3:
PlaySE(SE_USE_ITEM);
StringExpandPlaceholders(gStringVar4, doneText);
DisplayPartyMenuMessage(gStringVar4, 1);
ScheduleBgCopyTilemapToVram(2);
tState++;
break;
case 4:
if (!IsPartyMenuTextPrinterActive())
tState++;
break;
case 5:
SetMonData(&gPlayerParty[tMonId], MON_DATA_ABILITY_NUM, &tAbilityNum);
RemoveBagItem(gSpecialVar_ItemId, 1);
gTasks[taskId].func = Task_ClosePartyMenu;
break;
}
}
void ItemUseCB_AbilityPatch(u8 taskId, TaskFunc task)
{
s16 *data = gTasks[taskId].data;
tState = 0;
tMonId = gPartyMenu.slotId;
tSpecies = GetMonData(&gPlayerParty[tMonId], MON_DATA_SPECIES, NULL);
if (GetMonData(&gPlayerParty[tMonId], MON_DATA_ABILITY_NUM, NULL) == 2)
tAbilityNum = 0;
else
tAbilityNum = 2;
SetWordTaskArg(taskId, tOldFunc, (uintptr_t)(gTasks[taskId].func));
gTasks[taskId].func = Task_AbilityPatch;
}
#undef tState
#undef tSpecies
#undef tAbilityNum
#undef tMonId
#undef tOldFunc
static bool32 CannotUsePartyBattleItem(u16 itemId, struct Pokemon* mon)
{
u8 i;

View File

@ -2240,9 +2240,6 @@ u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data)
case MON_DATA_WORLD_RIBBON:
retVal = substruct3->worldRibbon;
break;
case MON_DATA_UNUSED_RIBBONS:
retVal = substruct3->unusedRibbons;
break;
case MON_DATA_MODERN_FATEFUL_ENCOUNTER:
retVal = substruct3->modernFatefulEncounter;
break;
@ -2394,7 +2391,6 @@ void SetMonData(struct Pokemon *mon, s32 field, const void *dataArg)
case MON_DATA_NATIONAL_RIBBON:
case MON_DATA_EARTH_RIBBON:
case MON_DATA_WORLD_RIBBON:
case MON_DATA_UNUSED_RIBBONS:
case MON_DATA_MODERN_FATEFUL_ENCOUNTER:
case MON_DATA_KNOWN_MOVES:
case MON_DATA_RIBBON_COUNT:
@ -2648,9 +2644,6 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg)
case MON_DATA_WORLD_RIBBON:
SET8(substruct3->worldRibbon);
break;
case MON_DATA_UNUSED_RIBBONS:
SET8(substruct3->unusedRibbons);
break;
case MON_DATA_MODERN_FATEFUL_ENCOUNTER:
SET8(substruct3->modernFatefulEncounter);
break;
@ -2790,17 +2783,32 @@ u8 GetMonsStateToDoubles(void)
return (aliveCount > 1) ? PLAYER_HAS_TWO_USABLE_MONS : PLAYER_HAS_ONE_USABLE_MON;
}
u8 GetAbilityBySpecies(u16 species, bool8 abilityNum)
u16 GetAbilityBySpecies(u16 species, bool8 abilityNum)
{
if (abilityNum)
gLastUsedAbility = gSpeciesInfo[species].abilities[1];
int i;
if (abilityNum < NUM_ABILITY_SLOTS)
gLastUsedAbility = gSpeciesInfo[species].abilities[abilityNum];
else
gLastUsedAbility = gSpeciesInfo[species].abilities[0];
gLastUsedAbility = ABILITY_NONE;
if (abilityNum >= NUM_NORMAL_ABILITY_SLOTS) // if abilityNum is empty hidden ability, look for other hidden abilities
{
for (i = NUM_NORMAL_ABILITY_SLOTS; i < NUM_ABILITY_SLOTS && gLastUsedAbility == ABILITY_NONE; i++)
{
gLastUsedAbility = gSpeciesInfo[species].abilities[i];
}
}
for (i = 0; i < NUM_ABILITY_SLOTS && gLastUsedAbility == ABILITY_NONE; i++) // look for any non-empty ability
{
gLastUsedAbility = gSpeciesInfo[species].abilities[i];
}
return gLastUsedAbility;
}
u8 GetMonAbility(struct Pokemon *mon)
u16 GetMonAbility(struct Pokemon *mon)
{
u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL);
u8 abilityNum = GetMonData(mon, MON_DATA_ABILITY_NUM, NULL);

View File

@ -2759,7 +2759,7 @@ static void CheckPartnersMonForRibbons(void)
{
u8 numRibbons = 0;
u8 i;
for (i = 0; i < (MON_DATA_UNUSED_RIBBONS - MON_DATA_CHAMPION_RIBBON); i++)
for (i = 0; i < (MON_DATA_WORLD_RIBBON - MON_DATA_CHAMPION_RIBBON); i++)
numRibbons += GetMonData(&gEnemyParty[gSelectedTradeMonPositions[TRADE_PARTNER] % PARTY_SIZE], MON_DATA_CHAMPION_RIBBON + i);
if (numRibbons != 0)

View File

@ -336,7 +336,7 @@ static u8 GetAbilityEncounterRateModType(void)
sWildEncounterData.abilityEffect = 0;
if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG))
{
u8 ability = GetMonAbility(&gPlayerParty[0]);
u16 ability = GetMonAbility(&gPlayerParty[0]);
if (ability == ABILITY_STENCH)
sWildEncounterData.abilityEffect = 1;
else if (ability == ABILITY_ILLUMINATE)