Merge branch '_RHH/master' into _RHH/upcoming

This commit is contained in:
Eduardo Quezada 2024-12-04 18:55:56 -03:00
commit a92350fb53
20 changed files with 535 additions and 233 deletions

View File

@ -17,7 +17,8 @@
## **People who collaborated with me in this PR**
<!-- Please credit everyone else that contributed to this PR, be it code and/or assets. -->
<!-- Use their GitHub tag if they have one. -->
<!-- Use their GitHub tag if they have one (or add "@/" at the start if they don't). Be sure to start the line using @ so the automatic changelog can properly detect the collaborators. -->
<!-- Eg.: "@Lunos for sprites, @/Masuda for support" -->
<!-- If it doesn't apply, feel free to remove this section. -->
## Feature(s) this PR does NOT handle:

View File

@ -466,6 +466,7 @@ FONT_SMALL_NARROW = FC 06 08
FONT_NARROWER = FC 06 0A
FONT_SMALL_NARROWER = FC 06 0B
FONT_SHORT_NARROW = FC 06 0C
FONT_SHORT_NARROWER = FC 06 0D
@ colors

View File

@ -10080,6 +10080,10 @@ BattleScript_BerserkGeneRet_End:
end3
BattleScript_BoosterEnergyEnd2::
call BattleScript_BoosterEnergyRet
end2
BattleScript_BoosterEnergyRet::
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1
call BattleScript_AbilityPopUpScripting
printstring STRINGID_BOOSTERENERGYACTIVATES
@ -10087,7 +10091,7 @@ BattleScript_BoosterEnergyEnd2::
printstring STRINGID_STATWASHEIGHTENED
waitmessage B_WAIT_TIME_MED
removeitem BS_SCRIPTING
end2
return
BattleScript_EffectSnow::
attackcanceler

View File

@ -447,3 +447,122 @@ Debug_EventScript_EWRAMCounters::
Debug_EventScript_EWRAMCounters_Text::
.string "Follower Steps: {STR_VAR_1}.\n"
.string "Fishing Chain: {STR_VAR_2}.$"
Debug_EventScript_FontTest_Text_1::
.string "{FONT_SHORT_NARROWER}" @ Edit this to test your font
.string "Angel Adept Blind Bodice Clique\n"
.string "Coast Dunce Docile Enact Eosin\l"
.string "Furlong Focal Gnome Gondola Human\l"
.string "Hoist Inlet Iodine Justin Jocose\l"
.string "Knoll Koala Linden Loads Milliner\l"
.string "Modal Number Nodule Onset Oddball\l"
.string "Pneumo Poncho Quanta Qophs Rhone\l"
.string "Roman Snout Sodium Tundra Tocsin\l"
.string "Uncle Udder Vulcan Vocal Whale\l"
.string "Woman Xmas Xenon Yunnan Young\l"
.string "Zloty Zodiac.$"
Debug_EventScript_FontTest_Text_2::
.string "{FONT_SHORT_NARROWER}" @ Edit this to test your font
.string "Angel angel adept for the nuance loads\n"
.string "of the arena cocoa and quaalude. Blind\l"
.string "blind bodice for the submit oboe of the\l"
.string "club snob and abbot. Clique clique\l"
.string "coast for the pouch loco of the franc\l"
.string "assoc and accede. Dunce dunce docile\l"
.string "for the loudness mastodon of the\l"
.string "loud statehood and huddle.$"
Debug_EventScript_FontTest_Text_3::
.string "{FONT_SHORT_NARROWER}" @ Edit this to test your font
.string "Enact enact eosin for the quench coed\n"
.string "of the pique canoe and bleep. Furlong\l"
.string "furlong focal for the genuflect\l"
.string "profound of the motif aloof and offers.\l"
.string "Gnome gnome gondola for the impugn\l"
.string "logos of the unplug analog and smuggle.\l"
.string "Human human hoist for the buddhist\l"
.string "alcohol of the riyadh caliph and\l"
.string "bathhouse.$"
Debug_EventScript_FontTest_Text_4::
.string "{FONT_SHORT_NARROWER}" @ Edit this to test your font
.string "Inlet inlet iodine for the quince\n"
.string "champion of the ennui scampi and shiite.\l"
.string "Justin justin jocose for the djibouti\l"
.string "sojourn of the oranj raj and hajjis.\l"
.string "Knoll knoll koala for the banknote\l"
.string "lookout of the dybbuk outlook and\l"
.string "trekked. Linden linden loads for the\l"
.string "ulna monolog of the consul menthol and\l"
.string "shallot.$"
Debug_EventScript_FontTest_Text_5::
.string "{FONT_SHORT_NARROWER}" @ Edit this to test your font
.string "Milliner milliner modal for the alumna\n"
.string "solomon of the album custom and summon.\l"
.string "Number number nodule for the unmade\l"
.string "economic of the shotgun bison and\l"
.string "tunnel. Onset onset oddball for the\l"
.string "abandon podium of the antiquo tempo\l"
.string "and moonlit. Pneumo pneumo poncho for\l"
.string "the dauphin opossum of the holdup\l"
.string "bishop and supplies.$"
Debug_EventScript_FontTest_Text_6::
.string "{FONT_SHORT_NARROWER}" @ Edit this to test your font
.string "Quanta quanta qophs for the inquest\n"
.string "sheqel of the cinq coq and suqqu. Rhone\l"
.string "rhone roman for the burnt porous of the\l"
.string "lemur clamor and carrot. Snout snout\l"
.string "sodium for the ensnare bosom of the\l"
.string "genus pathos and missing. Tundra\l"
.string "tundra tocsin for the nutmeg isotope\l"
.string "of the peasant ingot and ottoman.$"
Debug_EventScript_FontTest_Text_7::
.string "{FONT_SHORT_NARROWER}" @ Edit this to test your font
.string "Uncle uncle udder for the dunes cloud\n"
.string "of the hindu thou and continuum. Vulcan\l"
.string "vulcan vocal for the alluvial ovoid of\l"
.string "the yugoslav chekhov and revved. Whale\l"
.string "whale woman for the meanwhile blowout\l"
.string "of the forepaw meadow and glowworm.\l"
.string "Xmas xmas xenon for the bauxite\l"
.string "doxology of the tableaux equinox and\l"
.string "exxon.$"
Debug_EventScript_FontTest_Text_8::
.string "{FONT_SHORT_NARROWER}" @ Edit this to test your font
.string "Yunnan yunnan young for the dynamo\n"
.string "coyote of the obloquy employ and\l"
.string "sayyid. Zloty zloty zodiac for the gizmo\l"
.string "ozone of the franz laissez and buzzing.$"
Debug_PrintFontTest::
msgbox Debug_EventScript_FontTest_Text_1, MSGBOX_DEFAULT
msgbox Debug_EventScript_FontTest_Text_2, MSGBOX_DEFAULT
msgbox Debug_EventScript_FontTest_Text_3, MSGBOX_DEFAULT
msgbox Debug_EventScript_FontTest_Text_4, MSGBOX_DEFAULT
msgbox Debug_EventScript_FontTest_Text_5, MSGBOX_DEFAULT
msgbox Debug_EventScript_FontTest_Text_6, MSGBOX_DEFAULT
msgbox Debug_EventScript_FontTest_Text_7, MSGBOX_DEFAULT
msgbox Debug_EventScript_FontTest_Text_8, MSGBOX_DEFAULT
releaseall
end
Debug_EventScript_FontTest::
lockall
goto Debug_PrintFontTest
@ goto_if_eq VAR_RESULT, 0, Debug_NoPokemon
@ dynmultipush Debug_EventScript_InflictStatus1_Text_Single, 0
@ dynmultipush Debug_EventScript_InflictStatus1_Text_PartyWide, 1
@ dynmultipush Debug_EventScript_InflictStatus1_Text_Close, 2
@ dynmultistack 0, 0, FALSE, 3 FALSE, 0, NULL
@ switch VAR_RESULT
@ case 0, Debug_EventScript_InflictStatus1_Single
@ case 1, Debug_EventScript_InflictStatus1_Party
@ case 2, Debug_EventScript_InflictStatus1_Close
@Debug_EventScript_InflictStatus1_Close:
@ releaseall
@ end

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -248,6 +248,9 @@ $(FONTGFXDIR)/small_narrower.latfont: $(FONTGFXDIR)/latin_small_narrower.png
$(FONTGFXDIR)/short_narrow.latfont: $(FONTGFXDIR)/latin_short_narrow.png
$(GFX) $< $@
$(FONTGFXDIR)/short_narrower.latfont: $(FONTGFXDIR)/latin_short_narrower.png
$(GFX) $< $@
$(FONTGFXDIR)/small.hwjpnfont: $(FONTGFXDIR)/japanese_small.png
$(GFX) $< $@

View File

@ -517,6 +517,7 @@ extern const u8 BattleScript_AromaVeilProtectsRet[];
extern const u8 BattleScript_LowerAtkSpAtk[];
extern const u8 BattleScript_Terastallization[];
extern const u8 BattleScript_BoosterEnergyEnd2[];
extern const u8 BattleScript_BoosterEnergyRet[];
extern const u8 BattleScript_TeraShellDistortingTypeMatchups[];
extern const u8 BattleScript_TeraFormChange[];
extern const u8 BattleScript_SleepClausePreventsEnd[];

View File

@ -65,16 +65,20 @@ enum {
#define ABILITYEFFECT_WATER_SPORT 253 // Only used if B_SPORT_TURNS >= GEN_6
// For the first argument of ItemBattleEffects, to deteremine which block of item effects to try
#define ITEMEFFECT_ON_SWITCH_IN 0
#define ITEMEFFECT_NORMAL 1
#define ITEMEFFECT_DUMMY 2 // Unused, empty
#define ITEMEFFECT_MOVE_END 3
#define ITEMEFFECT_KINGSROCK 4
#define ITEMEFFECT_TARGET 5
#define ITEMEFFECT_ORBS 6
#define ITEMEFFECT_LIFEORB_SHELLBELL 7
#define ITEMEFFECT_USE_LAST_ITEM 8 // move end effects for just the battler, not whole field
#define ITEMEFFECT_STATS_CHANGED 9 // For White Herb and Eject Pack
enum ItemEffect
{
ITEMEFFECT_NONE,
ITEMEFFECT_ON_SWITCH_IN,
ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN,
ITEMEFFECT_NORMAL,
ITEMEFFECT_MOVE_END,
ITEMEFFECT_KINGSROCK,
ITEMEFFECT_TARGET,
ITEMEFFECT_ORBS,
ITEMEFFECT_LIFEORB_SHELLBELL,
ITEMEFFECT_USE_LAST_ITEM, // move end effects for just the battler, not whole field
ITEMEFFECT_STATS_CHANGED, // For White Herb and Eject Pack
};
#define WEATHER_HAS_EFFECT ((!IsAbilityOnField(ABILITY_CLOUD_NINE) && !IsAbilityOnField(ABILITY_AIR_LOCK)))
@ -215,7 +219,7 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move);
bool32 CanBattlerEscape(u32 battler); // no ability check
void BattleScriptExecute(const u8 *BS_ptr);
void BattleScriptPushCursorAndCallback(const u8 *BS_ptr);
u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn);
u32 ItemBattleEffects(enum ItemEffect, u32 battler, bool32 moveTurn);
void ClearVariousBattlerFlags(u32 battler);
void HandleAction_RunBattleScript(void);
u32 SetRandomTarget(u32 battler);
@ -272,7 +276,7 @@ void TryRestoreHeldItems(void);
bool32 CanStealItem(u32 battlerStealing, u32 battlerItem, u16 item);
void TrySaveExchangedItem(u32 battler, u16 stolenItem);
bool32 IsPartnerMonFromSameTrainer(u32 battler);
u8 TryHandleSeed(u32 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 execute);
u32 TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum ItemEffect caseID);
bool32 IsBattlerAffectedByHazards(u32 battler, bool32 toxicSpikes);
void SortBattlersBySpeed(u8 *battlers, bool32 slowToFast);
bool32 CompareStat(u32 battler, u8 statId, u8 cmpTo, u8 cmpKind);

View File

@ -21,5 +21,7 @@ extern const u8 gFontSmallNarrowerLatinGlyphWidths[];
extern const u16 gFontSmallNarrowerLatinGlyphs[];
extern const u8 gFontShortNarrowLatinGlyphWidths[];
extern const u16 gFontShortNarrowLatinGlyphs[];
extern const u8 gFontShortNarrowerLatinGlyphWidths[];
extern const u16 gFontShortNarrowerLatinGlyphs[];
#endif // GUARD_FONTS_H

View File

@ -21,6 +21,7 @@ enum {
FONT_NARROWER,
FONT_SMALL_NARROWER,
FONT_SHORT_NARROW,
FONT_SHORT_NARROWER,
};
// Return values for font functions

View File

@ -3903,7 +3903,7 @@ static void TryDoEventsBeforeFirstTurn(void)
case FIRST_TURN_EVENTS_ITEM_EFFECTS:
while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest
{
if (ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++], FALSE))
if (ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN, gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++], FALSE))
return;
}
gBattleStruct->switchInBattlerCounter = 0;

View File

@ -10728,16 +10728,16 @@ static void Cmd_various(void)
switch (GetBattlerHoldEffectParam(battler))
{
case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, item, FALSE);
effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE);
break;
case HOLD_EFFECT_PARAM_GRASSY_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, item, FALSE);
effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE);
break;
case HOLD_EFFECT_PARAM_MISTY_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, item, FALSE);
effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE);
break;
case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, item, FALSE);
effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE);
break;
}

View File

@ -6860,7 +6860,7 @@ bool32 HasEnoughHpToEatBerry(u32 battler, u32 hpFraction, u32 itemId)
return FALSE;
}
static u8 HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, bool32 end2)
static u32 HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, enum ItemEffect caseID)
{
if (HasEnoughHpToEatBerry(battler, (B_CONFUSE_BERRIES_HEAL >= GEN_7 ? 4 : 2), itemId)
&& (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)))
@ -6878,7 +6878,7 @@ static u8 HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, bool32 end2)
gBattlerAbility = battler;
}
gBattleScripting.battler = battler;
if (end2)
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL)
{
if (GetFlavorRelationByPersonality(gBattleMons[battler].personality, flavorId) < 0)
BattleScriptExecute(BattleScript_BerryConfuseHealEnd2);
@ -6899,7 +6899,7 @@ static u8 HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, bool32 end2)
return 0;
}
static u8 StatRaiseBerry(u32 battler, u32 itemId, u32 statId, bool32 end2)
static u32 StatRaiseBerry(u32 battler, u32 itemId, u32 statId, enum ItemEffect caseID)
{
if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN) && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, itemId), itemId))
{
@ -6913,7 +6913,7 @@ static u8 StatRaiseBerry(u32 battler, u32 itemId, u32 statId, bool32 end2)
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId;
gBattleScripting.animArg2 = 0;
if (end2)
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL)
{
BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
}
@ -6924,10 +6924,10 @@ static u8 StatRaiseBerry(u32 battler, u32 itemId, u32 statId, bool32 end2)
}
return ITEM_STATS_CHANGE;
}
return 0;
return ITEM_NO_EFFECT;
}
static u8 RandomStatRaiseBerry(u32 battler, u32 itemId, bool32 end2)
static u32 RandomStatRaiseBerry(u32 battler, u32 itemId, enum ItemEffect caseID)
{
s32 i;
u16 stringId;
@ -6963,7 +6963,7 @@ static u8 RandomStatRaiseBerry(u32 battler, u32 itemId, bool32 end2)
gBattleScripting.animArg1 = STAT_ANIM_PLUS2 + i + 1;
gBattleScripting.animArg2 = 0;
if (end2)
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL)
{
BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
}
@ -6978,12 +6978,12 @@ static u8 RandomStatRaiseBerry(u32 battler, u32 itemId, bool32 end2)
return 0;
}
static u8 TrySetMicleBerry(u32 battler, u32 itemId, bool32 end2)
static u32 TrySetMicleBerry(u32 battler, u32 itemId, enum ItemEffect caseID)
{
if (HasEnoughHpToEatBerry(battler, 4, itemId))
{
gBattleStruct->usedMicleBerry |= 1u << battler;
if (end2)
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL)
{
BattleScriptExecute(BattleScript_MicleBerryActivateEnd2);
}
@ -7046,7 +7046,7 @@ static u8 DamagedStatBoostBerryEffect(u32 battler, u8 statId, u8 category)
return 0;
}
u8 TryHandleSeed(u32 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 execute)
u32 TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum ItemEffect caseID)
{
if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
{
@ -7056,7 +7056,7 @@ u8 TryHandleSeed(u32 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 exe
SET_STATCHANGER(statId, 1, FALSE);
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId;
gBattleScripting.animArg2 = 0;
if (execute)
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL)
{
BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
}
@ -7070,7 +7070,7 @@ u8 TryHandleSeed(u32 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 exe
return 0;
}
static u32 ItemRestorePp(u32 battler, u32 itemId, bool32 execute)
static u32 ItemRestorePp(u32 battler, u32 itemId, enum ItemEffect caseID)
{
struct Pokemon *party = GetBattlerParty(battler);
struct Pokemon *mon = &party[gBattlerPartyIndexes[battler]];
@ -7098,7 +7098,7 @@ static u32 ItemRestorePp(u32 battler, u32 itemId, bool32 execute)
PREPARE_MOVE_BUFFER(gBattleTextBuff1, move);
if (execute)
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL)
{
BattleScriptExecute(BattleScript_BerryPPHealEnd2);
}
@ -7117,7 +7117,7 @@ static u32 ItemRestorePp(u32 battler, u32 itemId, bool32 execute)
return 0;
}
static u8 ItemHealHp(u32 battler, u32 itemId, bool32 end2, bool32 percentHeal)
static u32 ItemHealHp(u32 battler, u32 itemId, enum ItemEffect caseID, bool32 percentHeal)
{
if (!(gBattleScripting.overrideBerryRequirements && gBattleMons[battler].hp == gBattleMons[battler].maxHP)
&& (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))
@ -7133,7 +7133,7 @@ static u8 ItemHealHp(u32 battler, u32 itemId, bool32 end2, bool32 percentHeal)
gBattleStruct->moveDamage[battler] *= 2;
gBattlerAbility = battler; // in SWSH, berry juice shows ability pop up but has no effect. This is mimicked here
if (end2)
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL)
{
BattleScriptExecute(BattleScript_ItemHealHP_RemoveItemEnd2);
}
@ -7214,9 +7214,9 @@ static bool32 GetMentalHerbEffect(u32 battler)
return ret;
}
static u8 TryConsumeMirrorHerb(u32 battler, bool32 execute)
static u32 TryConsumeMirrorHerb(u32 battler, enum ItemEffect caseID)
{
u8 effect = 0;
u32 effect = 0;
if (gProtectStructs[battler].eatMirrorHerb)
{
@ -7225,7 +7225,7 @@ static u8 TryConsumeMirrorHerb(u32 battler, bool32 execute)
gBattleScripting.battler = battler;
gProtectStructs[battler].eatMirrorHerb = 0;
ChooseStatBoostAnimation(battler);
if (execute)
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL)
{
BattleScriptExecute(BattleScript_MirrorHerbCopyStatChangeEnd2);
}
@ -7239,7 +7239,7 @@ static u8 TryConsumeMirrorHerb(u32 battler, bool32 execute)
return effect;
}
static inline u32 TryBoosterEnergy(u32 battler)
static inline u32 TryBoosterEnergy(u32 battler, enum ItemEffect caseID)
{
if (gBattleStruct->boosterEnergyActivates & (1u << battler) || gBattleMons[battler].status2 & STATUS2_TRANSFORMED)
return ITEM_NO_EFFECT;
@ -7250,7 +7250,15 @@ static inline u32 TryBoosterEnergy(u32 battler)
PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler));
gBattlerAbility = gBattleScripting.battler = battler;
gBattleStruct->boosterEnergyActivates |= 1u << battler;
BattleScriptExecute(BattleScript_BoosterEnergyEnd2);
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL)
{
BattleScriptExecute(BattleScript_BoosterEnergyEnd2);
}
else
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_BoosterEnergyRet;
}
return ITEM_EFFECT_OTHER;
}
@ -7285,59 +7293,59 @@ static u8 ItemEffectMoveEnd(u32 battler, u16 holdEffect)
{
case HOLD_EFFECT_MICLE_BERRY:
if (B_HP_BERRIES >= GEN_4)
effect = TrySetMicleBerry(battler, gLastUsedItem, FALSE);
effect = TrySetMicleBerry(battler, gLastUsedItem, ITEMEFFECT_NONE);
break;
case HOLD_EFFECT_RESTORE_HP:
if (B_HP_BERRIES >= GEN_4)
effect = ItemHealHp(battler, gLastUsedItem, FALSE, FALSE);
effect = ItemHealHp(battler, gLastUsedItem, ITEMEFFECT_NONE, FALSE);
break;
case HOLD_EFFECT_RESTORE_PCT_HP:
if (B_BERRIES_INSTANT >= GEN_4)
effect = ItemHealHp(battler, gLastUsedItem, FALSE, TRUE);
effect = ItemHealHp(battler, gLastUsedItem, ITEMEFFECT_NONE, TRUE);
break;
case HOLD_EFFECT_RESTORE_PP:
if (B_BERRIES_INSTANT >= GEN_4)
effect = ItemRestorePp(battler, gLastUsedItem, FALSE);
effect = ItemRestorePp(battler, gLastUsedItem, ITEMEFFECT_NONE);
break;
case HOLD_EFFECT_CONFUSE_SPICY:
if (B_BERRIES_INSTANT >= GEN_4)
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SPICY, FALSE);
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SPICY, ITEMEFFECT_NONE);
break;
case HOLD_EFFECT_CONFUSE_DRY:
if (B_BERRIES_INSTANT >= GEN_4)
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_DRY, FALSE);
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_DRY, ITEMEFFECT_NONE);
break;
case HOLD_EFFECT_CONFUSE_SWEET:
if (B_BERRIES_INSTANT >= GEN_4)
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SWEET, FALSE);
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SWEET, ITEMEFFECT_NONE);
break;
case HOLD_EFFECT_CONFUSE_BITTER:
if (B_BERRIES_INSTANT >= GEN_4)
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_BITTER, FALSE);
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_BITTER, ITEMEFFECT_NONE);
break;
case HOLD_EFFECT_CONFUSE_SOUR:
if (B_BERRIES_INSTANT >= GEN_4)
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SOUR, FALSE);
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SOUR, ITEMEFFECT_NONE);
break;
case HOLD_EFFECT_ATTACK_UP:
if (B_BERRIES_INSTANT >= GEN_4)
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_ATK, FALSE);
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_ATK, ITEMEFFECT_NONE);
break;
case HOLD_EFFECT_DEFENSE_UP:
if (B_BERRIES_INSTANT >= GEN_4)
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_DEF, FALSE);
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_DEF, ITEMEFFECT_NONE);
break;
case HOLD_EFFECT_SPEED_UP:
if (B_BERRIES_INSTANT >= GEN_4)
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPEED, FALSE);
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPEED, ITEMEFFECT_NONE);
break;
case HOLD_EFFECT_SP_ATTACK_UP:
if (B_BERRIES_INSTANT >= GEN_4)
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPATK, FALSE);
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPATK, ITEMEFFECT_NONE);
break;
case HOLD_EFFECT_SP_DEFENSE_UP:
if (B_BERRIES_INSTANT >= GEN_4)
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, FALSE);
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, ITEMEFFECT_NONE);
break;
case HOLD_EFFECT_ENIGMA_BERRY: // consume and heal if hit by super effective move
if (B_BERRIES_INSTANT >= GEN_4)
@ -7353,7 +7361,7 @@ static u8 ItemEffectMoveEnd(u32 battler, u16 holdEffect)
break;
case HOLD_EFFECT_RANDOM_STAT_UP:
if (B_BERRIES_INSTANT >= GEN_4)
effect = RandomStatRaiseBerry(battler, gLastUsedItem, FALSE);
effect = RandomStatRaiseBerry(battler, gLastUsedItem, ITEMEFFECT_NONE);
break;
case HOLD_EFFECT_CURE_PAR:
if (gBattleMons[battler].status1 & STATUS1_PARALYSIS && !UnnerveOn(battler, gLastUsedItem))
@ -7490,20 +7498,80 @@ static u8 ItemEffectMoveEnd(u32 battler, u16 holdEffect)
effect = ITEM_STATS_CHANGE;
break;
case HOLD_EFFECT_MIRROR_HERB:
effect = TryConsumeMirrorHerb(battler, FALSE);
effect = TryConsumeMirrorHerb(battler, ITEMEFFECT_NONE);
break;
}
return effect;
}
u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
static inline bool32 TryCureStatus(u32 battler, enum ItemEffect caseId)
{
int i = 0, moveType;
u8 effect = ITEM_NO_EFFECT;
u32 battlerHoldEffect = 0, atkHoldEffect;
u8 atkHoldEffectParam;
u16 atkItem;
u32 effect = ITEM_NO_EFFECT;
u32 string = 0;
if ((gBattleMons[battler].status1 & STATUS1_ANY || gBattleMons[battler].status2 & STATUS2_CONFUSION) && !UnnerveOn(battler, gLastUsedItem))
{
if (gBattleMons[battler].status1 & STATUS1_PSN_ANY)
{
StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn);
string++;
}
if (gBattleMons[battler].status1 & STATUS1_SLEEP)
{
gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE;
StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn);
string++;
TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]);
}
if (gBattleMons[battler].status1 & STATUS1_PARALYSIS)
{
StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn);
string++;
}
if (gBattleMons[battler].status1 & STATUS1_BURN)
{
StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn);
string++;
}
if (gBattleMons[battler].status1 & STATUS1_FREEZE || gBattleMons[battler].status1 & STATUS1_FROSTBITE)
{
StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn);
string++;
}
if (gBattleMons[battler].status2 & STATUS2_CONFUSION)
{
StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn);
string++;
}
if (string <= 1)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_PROBLEM;
else
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_NORMALIZED_STATUS;
gBattleMons[battler].status1 = 0;
RemoveConfusionStatus(battler);
if (caseId == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseId == ITEMEFFECT_NORMAL)
{
BattleScriptExecute(BattleScript_BerryCureChosenStatusEnd2);
}
else
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_BerryCureChosenStatusRet;
}
effect = ITEM_STATUS_CHANGE;
}
return effect;
}
u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
{
u32 moveType = 0;
u32 effect = ITEM_NO_EFFECT;
u32 battlerHoldEffect = 0, atkHoldEffect = 0;
u32 atkHoldEffectParam = 0;
u32 atkItem = 0;
if (caseID != ITEMEFFECT_USE_LAST_ITEM)
{
@ -7517,7 +7585,10 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
switch (caseID)
{
case ITEMEFFECT_NONE:
break;
case ITEMEFFECT_ON_SWITCH_IN:
case ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN:
if (!gSpecialStatuses[battler].switchInItemDone)
{
switch (battlerHoldEffect)
@ -7539,43 +7610,43 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
break;
case HOLD_EFFECT_CONFUSE_SPICY:
if (B_BERRIES_INSTANT >= GEN_4)
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SPICY, TRUE);
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SPICY, caseID);
break;
case HOLD_EFFECT_CONFUSE_DRY:
if (B_BERRIES_INSTANT >= GEN_4)
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_DRY, TRUE);
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_DRY, caseID);
break;
case HOLD_EFFECT_CONFUSE_SWEET:
if (B_BERRIES_INSTANT >= GEN_4)
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SWEET, TRUE);
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SWEET, caseID);
break;
case HOLD_EFFECT_CONFUSE_BITTER:
if (B_BERRIES_INSTANT >= GEN_4)
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_BITTER, TRUE);
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_BITTER, caseID);
break;
case HOLD_EFFECT_CONFUSE_SOUR:
if (B_BERRIES_INSTANT >= GEN_4)
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SOUR, TRUE);
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SOUR, caseID);
break;
case HOLD_EFFECT_ATTACK_UP:
if (B_BERRIES_INSTANT >= GEN_4)
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_ATK, TRUE);
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_ATK, caseID);
break;
case HOLD_EFFECT_DEFENSE_UP:
if (B_BERRIES_INSTANT >= GEN_4)
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_DEF, TRUE);
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_DEF, caseID);
break;
case HOLD_EFFECT_SPEED_UP:
if (B_BERRIES_INSTANT >= GEN_4)
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPEED, TRUE);
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPEED, caseID);
break;
case HOLD_EFFECT_SP_ATTACK_UP:
if (B_BERRIES_INSTANT >= GEN_4)
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPATK, TRUE);
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPATK, caseID);
break;
case HOLD_EFFECT_SP_DEFENSE_UP:
if (B_BERRIES_INSTANT >= GEN_4)
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, TRUE);
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, caseID);
break;
case HOLD_EFFECT_CRITICAL_UP:
if (B_BERRIES_INSTANT >= GEN_4
@ -7590,7 +7661,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
break;
case HOLD_EFFECT_RANDOM_STAT_UP:
if (B_BERRIES_INSTANT >= GEN_4)
effect = RandomStatRaiseBerry(battler, gLastUsedItem, TRUE);
effect = RandomStatRaiseBerry(battler, gLastUsedItem, caseID);
break;
case HOLD_EFFECT_CURE_PAR:
if (B_BERRIES_INSTANT >= GEN_4
@ -7653,60 +7724,16 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
}
break;
case HOLD_EFFECT_CURE_STATUS:
if (B_BERRIES_INSTANT >= GEN_4
&& (gBattleMons[battler].status1 & STATUS1_ANY || gBattleMons[battler].status2 & STATUS2_CONFUSION)
&& !UnnerveOn(battler, gLastUsedItem))
{
i = 0;
if (gBattleMons[battler].status1 & STATUS1_PSN_ANY)
{
StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn);
i++;
}
if (gBattleMons[battler].status1 & STATUS1_SLEEP)
{
gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE;
StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn);
i++;
TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]);
}
if (gBattleMons[battler].status1 & STATUS1_PARALYSIS)
{
StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn);
i++;
}
if (gBattleMons[battler].status1 & STATUS1_BURN)
{
StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn);
i++;
}
if (gBattleMons[battler].status1 & STATUS1_FREEZE || gBattleMons[battler].status1 & STATUS1_FROSTBITE)
{
StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn);
i++;
}
if (gBattleMons[battler].status2 & STATUS2_CONFUSION)
{
StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn);
i++;
}
if (i <= 1)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_PROBLEM;
else
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_NORMALIZED_STATUS;
gBattleMons[battler].status1 = 0;
RemoveConfusionStatus(battler);
BattleScriptExecute(BattleScript_BerryCureChosenStatusEnd2);
effect = ITEM_STATUS_CHANGE;
}
if (B_BERRIES_INSTANT >= GEN_4)
effect = TryCureStatus(battler, caseID);
break;
case HOLD_EFFECT_RESTORE_HP:
if (B_BERRIES_INSTANT >= GEN_4)
effect = ItemHealHp(battler, gLastUsedItem, TRUE, FALSE);
effect = ItemHealHp(battler, gLastUsedItem, caseID, FALSE);
break;
case HOLD_EFFECT_RESTORE_PCT_HP:
if (B_BERRIES_INSTANT >= GEN_4)
effect = ItemHealHp(battler, gLastUsedItem, TRUE, TRUE);
effect = ItemHealHp(battler, gLastUsedItem, caseID, TRUE);
break;
case HOLD_EFFECT_AIR_BALLOON:
effect = ITEM_EFFECT_OTHER;
@ -7725,16 +7752,16 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
switch (GetBattlerHoldEffectParam(battler))
{
case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, gLastUsedItem, TRUE);
effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, gLastUsedItem, caseID);
break;
case HOLD_EFFECT_PARAM_GRASSY_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, gLastUsedItem, TRUE);
effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, gLastUsedItem, caseID);
break;
case HOLD_EFFECT_PARAM_MISTY_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, gLastUsedItem, TRUE);
effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, gLastUsedItem, caseID);
break;
case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, gLastUsedItem, TRUE);
effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, gLastUsedItem, caseID);
break;
}
break;
@ -7774,10 +7801,10 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
effect = ITEM_STATS_CHANGE;
break;
case HOLD_EFFECT_MIRROR_HERB:
effect = TryConsumeMirrorHerb(battler, TRUE);
effect = TryConsumeMirrorHerb(battler, caseID);
break;
case HOLD_EFFECT_BOOSTER_ENERGY:
effect = TryBoosterEnergy(battler);
effect = TryBoosterEnergy(battler, caseID);
break;
}
if (effect != 0)
@ -7801,15 +7828,15 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
{
case HOLD_EFFECT_RESTORE_HP:
if (!moveTurn)
effect = ItemHealHp(battler, gLastUsedItem, TRUE, FALSE);
effect = ItemHealHp(battler, gLastUsedItem, caseID, FALSE);
break;
case HOLD_EFFECT_RESTORE_PCT_HP:
if (!moveTurn)
effect = ItemHealHp(battler, gLastUsedItem, TRUE, TRUE);
effect = ItemHealHp(battler, gLastUsedItem, caseID, TRUE);
break;
case HOLD_EFFECT_RESTORE_PP:
if (!moveTurn)
effect = ItemRestorePp(battler, gLastUsedItem, TRUE);
effect = ItemRestorePp(battler, gLastUsedItem, caseID);
break;
case HOLD_EFFECT_RESTORE_STATS:
effect = RestoreWhiteHerbStats(battler);
@ -7851,43 +7878,43 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
break;
case HOLD_EFFECT_CONFUSE_SPICY:
if (!moveTurn)
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SPICY, TRUE);
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SPICY, caseID);
break;
case HOLD_EFFECT_CONFUSE_DRY:
if (!moveTurn)
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_DRY, TRUE);
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_DRY, caseID);
break;
case HOLD_EFFECT_CONFUSE_SWEET:
if (!moveTurn)
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SWEET, TRUE);
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SWEET, caseID);
break;
case HOLD_EFFECT_CONFUSE_BITTER:
if (!moveTurn)
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_BITTER, TRUE);
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_BITTER, caseID);
break;
case HOLD_EFFECT_CONFUSE_SOUR:
if (!moveTurn)
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SOUR, TRUE);
effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SOUR, caseID);
break;
case HOLD_EFFECT_ATTACK_UP:
if (!moveTurn)
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_ATK, TRUE);
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_ATK, caseID);
break;
case HOLD_EFFECT_DEFENSE_UP:
if (!moveTurn)
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_DEF, TRUE);
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_DEF, caseID);
break;
case HOLD_EFFECT_SPEED_UP:
if (!moveTurn)
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPEED, TRUE);
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPEED, caseID);
break;
case HOLD_EFFECT_SP_ATTACK_UP:
if (!moveTurn)
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPATK, TRUE);
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPATK, caseID);
break;
case HOLD_EFFECT_SP_DEFENSE_UP:
if (!moveTurn)
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, TRUE);
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, caseID);
break;
case HOLD_EFFECT_CRITICAL_UP:
if (!moveTurn && !(gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY)
@ -7901,7 +7928,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
break;
case HOLD_EFFECT_RANDOM_STAT_UP:
if (!moveTurn)
effect = RandomStatRaiseBerry(battler, gLastUsedItem, TRUE);
effect = RandomStatRaiseBerry(battler, gLastUsedItem, caseID);
break;
case HOLD_EFFECT_CURE_PAR:
if (gBattleMons[battler].status1 & STATUS1_PARALYSIS && !UnnerveOn(battler, gLastUsedItem))
@ -7960,50 +7987,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
}
break;
case HOLD_EFFECT_CURE_STATUS:
if ((gBattleMons[battler].status1 & STATUS1_ANY || gBattleMons[battler].status2 & STATUS2_CONFUSION) && !UnnerveOn(battler, gLastUsedItem))
{
i = 0;
if (gBattleMons[battler].status1 & STATUS1_PSN_ANY)
{
StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn);
i++;
}
if (gBattleMons[battler].status1 & STATUS1_SLEEP)
{
gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE;
StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn);
i++;
TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]);
}
if (gBattleMons[battler].status1 & STATUS1_PARALYSIS)
{
StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn);
i++;
}
if (gBattleMons[battler].status1 & STATUS1_BURN)
{
StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn);
i++;
}
if (gBattleMons[battler].status1 & STATUS1_FREEZE || gBattleMons[battler].status1 & STATUS1_FROSTBITE)
{
StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn);
i++;
}
if (gBattleMons[battler].status2 & STATUS2_CONFUSION)
{
StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn);
i++;
}
if (i <= 1)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_PROBLEM;
else
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_NORMALIZED_STATUS;
gBattleMons[battler].status1 = 0;
RemoveConfusionStatus(battler);
BattleScriptExecute(BattleScript_BerryCureChosenStatusEnd2);
effect = ITEM_STATUS_CHANGE;
}
effect = TryCureStatus(battler, caseID);
break;
case HOLD_EFFECT_MENTAL_HERB:
if (GetMentalHerbEffect(battler))
@ -8016,7 +8000,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
break;
case HOLD_EFFECT_MICLE_BERRY:
if (!moveTurn)
effect = TrySetMicleBerry(battler, gLastUsedItem, TRUE);
effect = TrySetMicleBerry(battler, gLastUsedItem, caseID);
break;
case HOLD_EFFECT_BERSERK_GENE:
BufferStatChange(battler, STAT_ATK, STRINGID_STATROSE);
@ -8034,10 +8018,10 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
effect = ITEM_STATS_CHANGE;
break;
case HOLD_EFFECT_MIRROR_HERB:
effect = TryConsumeMirrorHerb(battler, TRUE);
effect = TryConsumeMirrorHerb(battler, caseID);
break;
case HOLD_EFFECT_BOOSTER_ENERGY:
effect = TryBoosterEnergy(battler);
effect = TryBoosterEnergy(battler, caseID);
break;
}

View File

@ -89,6 +89,7 @@ enum UtilDebugMenu
DEBUG_UTIL_MENU_ITEM_SAVEBLOCK,
DEBUG_UTIL_MENU_ITEM_ROM_SPACE,
DEBUG_UTIL_MENU_ITEM_WEATHER,
DEBUG_UTIL_MENU_ITEM_FONT_TEST,
DEBUG_UTIL_MENU_ITEM_CHECKWALLCLOCK,
DEBUG_UTIL_MENU_ITEM_SETWALLCLOCK,
DEBUG_UTIL_MENU_ITEM_WATCHCREDITS,
@ -365,6 +366,7 @@ static void DebugAction_Util_CheckSaveBlock(u8 taskId);
static void DebugAction_Util_CheckROMSpace(u8 taskId);
static void DebugAction_Util_Weather(u8 taskId);
static void DebugAction_Util_Weather_SelectId(u8 taskId);
static void DebugAction_Util_FontTest(u8 taskId);
static void DebugAction_Util_CheckWallClock(u8 taskId);
static void DebugAction_Util_SetWallClock(u8 taskId);
static void DebugAction_Util_WatchCredits(u8 taskId);
@ -453,6 +455,7 @@ static void DebugAction_BerryFunctions_Weeds(u8 taskId);
extern const u8 Debug_FlagsNotSetOverworldConfigMessage[];
extern const u8 Debug_FlagsNotSetBattleConfigMessage[];
extern const u8 Debug_FlagsAndVarNotSetBattleConfigMessage[];
extern const u8 Debug_EventScript_FontTest[];
extern const u8 Debug_EventScript_CheckEVs[];
extern const u8 Debug_EventScript_CheckIVs[];
extern const u8 Debug_EventScript_InflictStatus1[];
@ -525,6 +528,7 @@ static const u8 sDebugText_Util_SaveBlockSpace[] = _("Save Block space
static const u8 sDebugText_Util_ROMSpace[] = _("ROM space…{CLEAR_TO 110}{RIGHT_ARROW}");
static const u8 sDebugText_Util_Weather[] = _("Set weather…{CLEAR_TO 110}{RIGHT_ARROW}");
static const u8 sDebugText_Util_Weather_ID[] = _("Weather ID: {STR_VAR_3}\n{STR_VAR_1}\n{STR_VAR_2}");
static const u8 sDebugText_Util_FontTest[] = _("Font Test…{CLEAR_TO 110}{RIGHT_ARROW}");
static const u8 sDebugText_Util_CheckWallClock[] = _("Check wall clock…{CLEAR_TO 110}{RIGHT_ARROW}");
static const u8 sDebugText_Util_SetWallClock[] = _("Set wall clock…{CLEAR_TO 110}{RIGHT_ARROW}");
static const u8 sDebugText_Util_WatchCredits[] = _("Watch credits…{CLEAR_TO 110}{RIGHT_ARROW}");
@ -714,6 +718,7 @@ static const struct ListMenuItem sDebugMenu_Items_Utilities[] =
[DEBUG_UTIL_MENU_ITEM_SAVEBLOCK] = {sDebugText_Util_SaveBlockSpace, DEBUG_UTIL_MENU_ITEM_SAVEBLOCK},
[DEBUG_UTIL_MENU_ITEM_ROM_SPACE] = {sDebugText_Util_ROMSpace, DEBUG_UTIL_MENU_ITEM_ROM_SPACE},
[DEBUG_UTIL_MENU_ITEM_WEATHER] = {sDebugText_Util_Weather, DEBUG_UTIL_MENU_ITEM_WEATHER},
[DEBUG_UTIL_MENU_ITEM_FONT_TEST] = {sDebugText_Util_FontTest, DEBUG_UTIL_MENU_ITEM_FONT_TEST},
[DEBUG_UTIL_MENU_ITEM_CHECKWALLCLOCK] = {sDebugText_Util_CheckWallClock, DEBUG_UTIL_MENU_ITEM_CHECKWALLCLOCK},
[DEBUG_UTIL_MENU_ITEM_SETWALLCLOCK] = {sDebugText_Util_SetWallClock, DEBUG_UTIL_MENU_ITEM_SETWALLCLOCK},
[DEBUG_UTIL_MENU_ITEM_WATCHCREDITS] = {sDebugText_Util_WatchCredits, DEBUG_UTIL_MENU_ITEM_WATCHCREDITS},
@ -884,6 +889,7 @@ static void (*const sDebugMenu_Actions_Utilities[])(u8) =
[DEBUG_UTIL_MENU_ITEM_SAVEBLOCK] = DebugAction_Util_CheckSaveBlock,
[DEBUG_UTIL_MENU_ITEM_ROM_SPACE] = DebugAction_Util_CheckROMSpace,
[DEBUG_UTIL_MENU_ITEM_WEATHER] = DebugAction_Util_Weather,
[DEBUG_UTIL_MENU_ITEM_FONT_TEST] = DebugAction_Util_FontTest,
[DEBUG_UTIL_MENU_ITEM_CHECKWALLCLOCK] = DebugAction_Util_CheckWallClock,
[DEBUG_UTIL_MENU_ITEM_SETWALLCLOCK] = DebugAction_Util_SetWallClock,
[DEBUG_UTIL_MENU_ITEM_WATCHCREDITS] = DebugAction_Util_WatchCredits,
@ -2294,6 +2300,11 @@ static void DebugAction_Util_Weather_SelectId(u8 taskId)
}
}
static void DebugAction_Util_FontTest(u8 taskId)
{
Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_FontTest);
}
static void DebugAction_Util_CheckWallClock(u8 taskId)
{
Debug_DestroyMenu_Full_Script(taskId, PlayersHouse_2F_EventScript_CheckWallClock);

View File

@ -288,6 +288,42 @@ ALIGNED(4) const u8 gFontShortNarrowLatinGlyphWidths[] = {
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 3,
};
ALIGNED(4) const u16 gFontShortNarrowerLatinGlyphs[] = INCBIN_U16("graphics/fonts/short_narrower.latfont");
ALIGNED(4) const u8 gFontShortNarrowerLatinGlyphWidths[] = {
1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4,
8, 4, 4, 4, 5, 5, 4, 4, 3, 4, 4, 4, 4, 4, 4, 3,
4, 4, 4, 4, 4, 6, 4, 4, 4, 5, 4, 5, 8, 6, 6, 3,
3, 3, 3, 3, 8, 8, 3, 5, 5, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5, 5, 4, 8, 8, 8, 7, 8, 8, 4, 4, 6, 4, 4, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4,
3, 3, 3, 3, 3, 3, 3, 5, 3, 7, 7, 7, 7, 0, 0, 3,
4, 5, 6, 7, 4, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 3, 5, 3,
5, 5, 5, 3, 3, 5, 5, 6, 3, 6, 6, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4,
4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4,
2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8,
4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3,
10, 10, 10, 10, 8, 8, 10, 8, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 3,
};
ALIGNED(4) const u16 gFontSmallJapaneseGlyphs[] = INCBIN_U16("graphics/fonts/small.hwjpnfont");
ALIGNED(4) const u16 gFontNormalJapaneseGlyphs[] = INCBIN_U16("graphics/fonts/normal.hwjpnfont");

View File

@ -26,6 +26,7 @@ static u16 FontFunc_SmallNarrow(struct TextPrinter *);
static u16 FontFunc_Narrower(struct TextPrinter *);
static u16 FontFunc_SmallNarrower(struct TextPrinter *);
static u16 FontFunc_ShortNarrow(struct TextPrinter *);
static u16 FontFunc_ShortNarrower(struct TextPrinter *);
static void DecompressGlyph_Small(u16, bool32);
static void DecompressGlyph_Normal(u16, bool32);
static void DecompressGlyph_Short(u16, bool32);
@ -35,6 +36,7 @@ static void DecompressGlyph_Bold(u16);
static void DecompressGlyph_Narrower(u16, bool32);
static void DecompressGlyph_SmallNarrower(u16, bool32);
static void DecompressGlyph_ShortNarrow(u16, bool32);
static void DecompressGlyph_ShortNarrower(u16, bool32);
static u32 GetGlyphWidth_Small(u16, bool32);
static u32 GetGlyphWidth_Normal(u16, bool32);
static u32 GetGlyphWidth_Short(u16, bool32);
@ -43,6 +45,7 @@ static u32 GetGlyphWidth_SmallNarrow(u16, bool32);
static u32 GetGlyphWidth_Narrower(u16, bool32);
static u32 GetGlyphWidth_SmallNarrower(u16, bool32);
static u32 GetGlyphWidth_ShortNarrow(u16, bool32);
static u32 GetGlyphWidth_ShortNarrower(u16, bool32);
static EWRAM_DATA struct TextPrinter sTempTextPrinter = {0};
static EWRAM_DATA struct TextPrinter sTextPrinters[WINDOWS_MAX] = {0};
@ -102,6 +105,7 @@ static const struct GlyphWidthFunc sGlyphWidthFuncs[] =
{ FONT_NARROWER, GetGlyphWidth_Narrower },
{ FONT_SMALL_NARROWER, GetGlyphWidth_SmallNarrower },
{ FONT_SHORT_NARROW, GetGlyphWidth_ShortNarrow },
{ FONT_SHORT_NARROWER, GetGlyphWidth_ShortNarrower },
};
struct
@ -260,6 +264,16 @@ static const struct FontInfo sFontInfos[] =
.bgColor = 1,
.shadowColor = 3,
},
[FONT_SHORT_NARROWER] = {
.fontFunction = FontFunc_ShortNarrower,
.maxLetterWidth = 5,
.maxLetterHeight = 14,
.letterSpacing = 0,
.lineSpacing = 0,
.fgColor = 2,
.bgColor = 1,
.shadowColor = 3,
},
};
static const u8 sMenuCursorDimensions[][2] =
@ -277,6 +291,7 @@ static const u8 sMenuCursorDimensions[][2] =
[FONT_NARROWER] = { 8, 15 },
[FONT_SMALL_NARROWER] = { 8, 8 },
[FONT_SHORT_NARROW] = { 8, 14 },
[FONT_SHORT_NARROWER] = { 8, 14 },
};
static const u16 sFontBoldJapaneseGlyphs[] = INCBIN_U16("graphics/fonts/bold.hwjpnfont");
@ -850,6 +865,18 @@ static u16 FontFunc_ShortNarrow(struct TextPrinter *textPrinter)
return RenderText(textPrinter);
}
static u16 FontFunc_ShortNarrower(struct TextPrinter *textPrinter)
{
struct TextPrinterSubStruct *subStruct = (struct TextPrinterSubStruct *)(&textPrinter->subStructFields);
if (subStruct->hasFontIdBeenSet == FALSE)
{
subStruct->fontId = FONT_SHORT_NARROWER;
subStruct->hasFontIdBeenSet = TRUE;
}
return RenderText(textPrinter);
}
void TextPrinterInitDownArrowCounters(struct TextPrinter *textPrinter)
{
struct TextPrinterSubStruct *subStruct = (struct TextPrinterSubStruct *)(&textPrinter->subStructFields);
@ -1238,6 +1265,9 @@ static u16 RenderText(struct TextPrinter *textPrinter)
case FONT_SHORT_NARROW:
DecompressGlyph_ShortNarrow(currChar, textPrinter->japanese);
break;
case FONT_SHORT_NARROWER:
DecompressGlyph_ShortNarrower(currChar, textPrinter->japanese);
break;
case FONT_BRAILLE:
break;
}
@ -2161,6 +2191,50 @@ static u32 GetGlyphWidth_ShortNarrow(u16 glyphId, bool32 isJapanese)
return gFontShortNarrowLatinGlyphWidths[glyphId];
}
static void DecompressGlyph_ShortNarrower(u16 glyphId, bool32 isJapanese)
{
const u16 *glyphs;
if (isJapanese == TRUE)
{
glyphs = gFontShortJapaneseGlyphs + (0x100 * (glyphId >> 0x3)) + (0x10 * (glyphId & 0x7));
DecompressGlyphTile(glyphs, gCurGlyph.gfxBufferTop);
DecompressGlyphTile(glyphs + 0x8, gCurGlyph.gfxBufferTop + 8);
DecompressGlyphTile(glyphs + 0x80, gCurGlyph.gfxBufferBottom); // gCurGlyph + 0x20
DecompressGlyphTile(glyphs + 0x88, gCurGlyph.gfxBufferBottom + 8); // gCurGlyph + 0x60
gCurGlyph.width = gFontShortJapaneseGlyphWidths[glyphId];
gCurGlyph.height = 14;
}
else
{
glyphs = gFontShortNarrowerLatinGlyphs + (0x20 * glyphId);
gCurGlyph.width = gFontShortNarrowerLatinGlyphWidths[glyphId];
if (gCurGlyph.width <= 8)
{
DecompressGlyphTile(glyphs, gCurGlyph.gfxBufferTop);
DecompressGlyphTile(glyphs + 0x10, gCurGlyph.gfxBufferBottom);
}
else
{
DecompressGlyphTile(glyphs, gCurGlyph.gfxBufferTop);
DecompressGlyphTile(glyphs + 0x8, gCurGlyph.gfxBufferTop + 8);
DecompressGlyphTile(glyphs + 0x10, gCurGlyph.gfxBufferBottom);
DecompressGlyphTile(glyphs + 0x18, gCurGlyph.gfxBufferBottom + 8);
}
gCurGlyph.height = 14;
}
}
static u32 GetGlyphWidth_ShortNarrower(u16 glyphId, bool32 isJapanese)
{
if (isJapanese == TRUE)
return gFontShortJapaneseGlyphWidths[glyphId];
else
return gFontShortNarrowerLatinGlyphWidths[glyphId];
}
static const s8 sNarrowerFontIds[] =
{
[FONT_SMALL] = FONT_SMALL_NARROW,
@ -2175,7 +2249,8 @@ static const s8 sNarrowerFontIds[] =
[FONT_BOLD] = -1,
[FONT_NARROWER] = -1,
[FONT_SMALL_NARROWER] = -1,
[FONT_SHORT_NARROW] = -1,
[FONT_SHORT_NARROW] = FONT_SHORT_NARROWER,
[FONT_SHORT_NARROWER] = -1,
};
// If the narrowest font ID doesn't fit the text, we still return that

View File

@ -209,3 +209,28 @@ SINGLE_BATTLE_TEST("Booster Energy can't be tricked if a Paradox species is invo
MESSAGE("But it failed!");
}
}
DOUBLE_BATTLE_TEST("Booster Energy triggers correctly for all battlers if multiple fainted the previous turn")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_CATERPIE) { HP(1); }
PLAYER(SPECIES_GOUGING_FIRE) { Item(ITEM_BOOSTER_ENERGY); }
PLAYER(SPECIES_IRON_MOTH) { Item(ITEM_BOOSTER_ENERGY); }
OPPONENT(SPECIES_CATERPIE) { HP(1); }
OPPONENT(SPECIES_CATERPIE) { HP(1); }
OPPONENT(SPECIES_FLUTTER_MANE) { Item(ITEM_BOOSTER_ENERGY); }
OPPONENT(SPECIES_CATERPIE);
} WHEN {
TURN { MOVE(playerLeft, MOVE_EXPLOSION);
SEND_OUT(opponentRight, 3);
SEND_OUT(opponentLeft, 2);
SEND_OUT(playerRight, 3);
SEND_OUT(playerLeft, 2); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, playerLeft);
ABILITY_POPUP(playerLeft, ABILITY_PROTOSYNTHESIS);
ABILITY_POPUP(playerRight, ABILITY_QUARK_DRIVE);
ABILITY_POPUP(opponentLeft, ABILITY_PROTOSYNTHESIS);
}
}

View File

@ -265,3 +265,30 @@ SINGLE_BATTLE_TEST("Player Pokemon can be further poisoned with Toxic spikes aft
STATUS_ICON(player, poison: TRUE);
}
}
DOUBLE_BATTLE_TEST("Lum Berry correctly cures all battlers if multiple fainted the previous turn")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_CATERPIE) { HP(1); }
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LUM_BERRY); Status1(STATUS1_BURN); }
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LUM_BERRY); Status1(STATUS1_POISON); }
OPPONENT(SPECIES_CATERPIE) { HP(1); }
OPPONENT(SPECIES_CATERPIE) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LUM_BERRY); Status1(STATUS1_PARALYSIS); }
OPPONENT(SPECIES_CATERPIE);
} WHEN {
TURN { MOVE(playerLeft, MOVE_EXPLOSION);
SEND_OUT(opponentRight, 3);
SEND_OUT(opponentLeft, 2);
SEND_OUT(playerRight, 3);
SEND_OUT(playerLeft, 2); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, playerLeft);
} THEN {
EXPECT_EQ(playerLeft->status1, STATUS1_NONE);
EXPECT_EQ(playerRight->status1, STATUS1_NONE);
EXPECT_EQ(opponentLeft->status1, STATUS1_NONE);
}
}

View File

@ -251,51 +251,6 @@ static bool set_parse_error(struct Parser *p, struct SourceLocation location, co
return false;
}
static bool show_parse_error(struct Parser *p)
{
// Print error message.
int n = fprintf(stderr, "%s:%d: ", p->source->path, p->error_location.line);
fprintf(stderr, "error: %s\n", p->error);
// Seek to the line.
int line, begin, end;
for (line = 1, begin = 0; begin < p->source->buffer_n; begin++)
{
if (p->error_location.line == line)
break;
if (p->source->buffer[begin] == '\n')
line++;
}
for (end = begin; end < p->source->buffer_n; end++)
{
if (p->source->buffer[end] == '\n')
break;
}
// Print the source line.
fprintf(stderr, "%s:%d: %.*s\n", p->source->path, p->error_location.line, end - begin, &p->source->buffer[begin]);
// Print caret pointing at the column.
fprintf(stderr, "%*s", n, "");
for (int column = 1; column < p->error_location.column && begin + column < end; column++)
{
unsigned char c = p->source->buffer[begin + column];
fputc(c == '\t' ? c : ' ', stderr);
}
fprintf(stderr, "^\n");
p->error = NULL;
p->fatal_error = true;
return false;
}
static bool set_show_parse_error(struct Parser *p, struct SourceLocation location, const char *error)
{
set_parse_error(p, location, error);
return show_parse_error(p);
}
__attribute__((warn_unused_result))
static bool peek_char(struct Parser *p, unsigned char *c)
{
@ -618,6 +573,59 @@ static bool match_move_identifier(struct Parser *p, struct Token *t)
return true;
}
static bool show_parse_error(struct Parser *p)
{
// Print error message.
int n = fprintf(stderr, "%s:%d: ", p->source->path, p->error_location.line);
fprintf(stderr, "error: %s\n", p->error);
struct Parser p_ = {
.source = p->source,
.location = { .line = 1, .column = 1 },
.offset = 0,
};
for (;;) {
if (p->error_location.line == p_.location.line)
break;
if (!match_empty_line(&p_))
skip_line(&p_);
if (match_eof(&p_))
assert(false);
}
int begin = p_.offset;
int end;
for (end = begin; end < p->source->buffer_n; end++)
{
if (p->source->buffer[end] == '\n')
break;
}
// Print the source line.
fprintf(stderr, "%s:%d: %.*s\n", p->source->path, p->error_location.line, end - begin, &p->source->buffer[begin]);
// Print caret pointing at the column.
fprintf(stderr, "%*s", n, "");
for (int column = 1; column < p->error_location.column && begin + column < end; column++)
{
unsigned char c = p->source->buffer[begin + column];
fputc(c == '\t' ? c : ' ', stderr);
}
fprintf(stderr, "^\n");
p->error = NULL;
p->fatal_error = true;
return false;
}
static bool set_show_parse_error(struct Parser *p, struct SourceLocation location, const char *error)
{
set_parse_error(p, location, error);
return show_parse_error(p);
}
__attribute__((warn_unused_result))
static bool parse_section(struct Parser *p, struct Token *section)
{