Merge branch 'RHH/master' into RHH/upcoming
# Conflicts: # include/battle.h
This commit is contained in:
commit
c8b0545d20
7 changed files with 155 additions and 14 deletions
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
## What is the pokeemerald Expansion?
|
## What is the pokeemerald Expansion?
|
||||||
|
|
||||||
The pokeemerald Expansion is a feature branch meant to be integrated into existing Pokémon Emerald hacks based off pret's [pokeemerald](https://github.com/pret/pokeemerald) decompilation project. This is ***NOT*** a standalone romhack, and as such, most features will be unavailable and/or unbalanced if played as is.
|
The pokeemerald Expansion is a decomp hack base project based off pret's [pokeemerald](https://github.com/pret/pokeemerald) decompilation project. It's recommended that any new projects that plan on using it, to clone this repository instead of pret's vanilla repository, as we regurlarly incorporate pret's documentation changes. This is ***NOT*** a standalone romhack, and as such, most features will be unavailable and/or unbalanced if played as is.
|
||||||
|
|
||||||
## What features are included?
|
## What features are included?
|
||||||
- Configuration files that allows you to choose generation-specific behaviors. Full contents here:
|
- ***IMPORTANT*❗❗ Read through these to learn what features you can toggle**:
|
||||||
- [Battle configurations](/include/config/battle.h)
|
- [Battle configurations](/include/config/battle.h)
|
||||||
- [Pokémon configurations](/include/config/pokemon.h)
|
- [Pokémon configurations](/include/config/pokemon.h)
|
||||||
- [Item configurations](/include/config/item.h)
|
- [Item configurations](/include/config/item.h)
|
||||||
|
|
|
@ -713,6 +713,7 @@ BattleScript_EffectAttackUpUserAlly_TryAlly:
|
||||||
BattleScript_EffectAttackUpUserAlly_End:
|
BattleScript_EffectAttackUpUserAlly_End:
|
||||||
goto BattleScript_MoveEnd
|
goto BattleScript_MoveEnd
|
||||||
BattleScript_EffectAttackUpUserAlly_TryAlly_:
|
BattleScript_EffectAttackUpUserAlly_TryAlly_:
|
||||||
|
jumpifability BS_ATTACKER_PARTNER, ABILITY_SOUNDPROOF, BattleScript_EffectAttackUpUserAlly_TryAllyBlocked
|
||||||
setstatchanger STAT_ATK, 1, FALSE
|
setstatchanger STAT_ATK, 1, FALSE
|
||||||
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_EffectAttackUpUserAlly_End
|
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_EffectAttackUpUserAlly_End
|
||||||
jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectAttackUpUserAlly_AllyAnim
|
jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectAttackUpUserAlly_AllyAnim
|
||||||
|
@ -727,6 +728,13 @@ BattleScript_EffectAttackUpUserAlly_AllyAnim:
|
||||||
waitmessage B_WAIT_TIME_LONG
|
waitmessage B_WAIT_TIME_LONG
|
||||||
goto BattleScript_EffectAttackUpUserAlly_End
|
goto BattleScript_EffectAttackUpUserAlly_End
|
||||||
|
|
||||||
|
BattleScript_EffectAttackUpUserAlly_TryAllyBlocked:
|
||||||
|
copybyte sBATTLER, gBattlerTarget
|
||||||
|
call BattleScript_AbilityPopUpTarget
|
||||||
|
printstring STRINGID_PKMNSXBLOCKSY2
|
||||||
|
waitmessage B_WAIT_TIME_LONG
|
||||||
|
goto BattleScript_MoveEnd
|
||||||
|
|
||||||
BattleScript_EffectTeatime::
|
BattleScript_EffectTeatime::
|
||||||
attackcanceler
|
attackcanceler
|
||||||
attackstring
|
attackstring
|
||||||
|
|
|
@ -108,6 +108,8 @@ struct DisableStruct
|
||||||
u8 syrupBombTimer;
|
u8 syrupBombTimer;
|
||||||
u8 syrupBombIsShiny:1;
|
u8 syrupBombIsShiny:1;
|
||||||
u8 steelSurgeDone:1;
|
u8 steelSurgeDone:1;
|
||||||
|
u8 weatherAbilityDone:1;
|
||||||
|
u8 terrainAbilityDone:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ProtectStruct
|
struct ProtectStruct
|
||||||
|
@ -199,8 +201,6 @@ struct SpecialStatus
|
||||||
u8 dancerUsedMove:1;
|
u8 dancerUsedMove:1;
|
||||||
u8 dancerOriginalTarget:3;
|
u8 dancerOriginalTarget:3;
|
||||||
// End of byte
|
// End of byte
|
||||||
u8 weatherAbilityDone:1;
|
|
||||||
u8 terrainAbilityDone:1;
|
|
||||||
u8 emergencyExited:1;
|
u8 emergencyExited:1;
|
||||||
u8 afterYou:1;
|
u8 afterYou:1;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1884,12 +1884,13 @@ u32 GetBattlerAffectionHearts(u32 battler)
|
||||||
return GetMonAffectionHearts(&party[gBattlerPartyIndexes[battler]]);
|
return GetMonAffectionHearts(&party[gBattlerPartyIndexes[battler]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TryToRevertMimicry(void)
|
static void TryToRevertMimicryAndFlags(void)
|
||||||
{
|
{
|
||||||
u32 i;
|
u32 i;
|
||||||
|
|
||||||
for (i = 0; i < gBattlersCount; i++)
|
for (i = 0; i < gBattlersCount; i++)
|
||||||
{
|
{
|
||||||
|
gDisableStructs[i].terrainAbilityDone = FALSE;
|
||||||
if (GetBattlerAbility(i) == ABILITY_MIMICRY)
|
if (GetBattlerAbility(i) == ABILITY_MIMICRY)
|
||||||
RESTORE_BATTLER_TYPE(i);
|
RESTORE_BATTLER_TYPE(i);
|
||||||
}
|
}
|
||||||
|
@ -1942,7 +1943,7 @@ static bool32 EndTurnTerrain(u32 terrainFlag, u32 stringTableId)
|
||||||
if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.terrainTimer == 0)
|
if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.terrainTimer == 0)
|
||||||
{
|
{
|
||||||
gFieldStatuses &= ~terrainFlag;
|
gFieldStatuses &= ~terrainFlag;
|
||||||
TryToRevertMimicry();
|
TryToRevertMimicryAndFlags();
|
||||||
gBattleCommunication[MULTISTRING_CHOOSER] = stringTableId;
|
gBattleCommunication[MULTISTRING_CHOOSER] = stringTableId;
|
||||||
BattleScriptExecute(BattleScript_TerrainEnds);
|
BattleScriptExecute(BattleScript_TerrainEnds);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -2242,6 +2243,8 @@ u8 DoFieldEndTurnEffects(void)
|
||||||
&& --gWishFutureKnock.weatherDuration == 0)
|
&& --gWishFutureKnock.weatherDuration == 0)
|
||||||
{
|
{
|
||||||
gBattleWeather &= ~B_WEATHER_SUN_TEMPORARY;
|
gBattleWeather &= ~B_WEATHER_SUN_TEMPORARY;
|
||||||
|
for (i = 0; i < gBattlersCount; i++)
|
||||||
|
gDisableStructs[i].weatherAbilityDone = FALSE;
|
||||||
gBattlescriptCurrInstr = BattleScript_SunlightFaded;
|
gBattlescriptCurrInstr = BattleScript_SunlightFaded;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -4096,6 +4099,7 @@ static bool32 TryChangeBattleTerrain(u32 battler, u32 statusFlag, u8 *timer)
|
||||||
{
|
{
|
||||||
gFieldStatuses &= ~(STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_GRASSY_TERRAIN | STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_PSYCHIC_TERRAIN);
|
gFieldStatuses &= ~(STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_GRASSY_TERRAIN | STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_PSYCHIC_TERRAIN);
|
||||||
gFieldStatuses |= statusFlag;
|
gFieldStatuses |= statusFlag;
|
||||||
|
gDisableStructs[battler].terrainAbilityDone = FALSE;
|
||||||
|
|
||||||
if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_TERRAIN_EXTENDER)
|
if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_TERRAIN_EXTENDER)
|
||||||
*timer = 8;
|
*timer = 8;
|
||||||
|
@ -6122,10 +6126,11 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ABILITY_PROTOSYNTHESIS:
|
case ABILITY_PROTOSYNTHESIS:
|
||||||
if (!gSpecialStatuses[battler].weatherAbilityDone && IsBattlerWeatherAffected(battler, B_WEATHER_SUN))
|
if (!gDisableStructs[battler].weatherAbilityDone && IsBattlerWeatherAffected(battler, B_WEATHER_SUN))
|
||||||
{
|
{
|
||||||
gSpecialStatuses[battler].weatherAbilityDone = TRUE;
|
gDisableStructs[battler].weatherAbilityDone = TRUE;
|
||||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler));
|
PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler));
|
||||||
|
gBattlerAbility = gBattleScripting.battler = battler;
|
||||||
BattleScriptPushCursorAndCallback(BattleScript_ProtosynthesisActivates);
|
BattleScriptPushCursorAndCallback(BattleScript_ProtosynthesisActivates);
|
||||||
effect++;
|
effect++;
|
||||||
}
|
}
|
||||||
|
@ -6137,9 +6142,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||||
switch (gLastUsedAbility)
|
switch (gLastUsedAbility)
|
||||||
{
|
{
|
||||||
case ABILITY_MIMICRY:
|
case ABILITY_MIMICRY:
|
||||||
if (!gSpecialStatuses[battler].terrainAbilityDone && ChangeTypeBasedOnTerrain(battler))
|
if (!gDisableStructs[battler].terrainAbilityDone && ChangeTypeBasedOnTerrain(battler))
|
||||||
{
|
{
|
||||||
gSpecialStatuses[battler].terrainAbilityDone = TRUE;
|
gDisableStructs[battler].terrainAbilityDone = TRUE;
|
||||||
ChangeTypeBasedOnTerrain(battler);
|
ChangeTypeBasedOnTerrain(battler);
|
||||||
gBattlerAbility = gBattleScripting.battler = battler;
|
gBattlerAbility = gBattleScripting.battler = battler;
|
||||||
BattleScriptPushCursorAndCallback(BattleScript_MimicryActivates_End3);
|
BattleScriptPushCursorAndCallback(BattleScript_MimicryActivates_End3);
|
||||||
|
@ -6147,11 +6152,11 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ABILITY_QUARK_DRIVE:
|
case ABILITY_QUARK_DRIVE:
|
||||||
if (!gSpecialStatuses[battler].terrainAbilityDone && IsBattlerTerrainAffected(battler, STATUS_FIELD_ELECTRIC_TERRAIN))
|
if (!gDisableStructs[battler].terrainAbilityDone && IsBattlerTerrainAffected(battler, STATUS_FIELD_ELECTRIC_TERRAIN))
|
||||||
{
|
{
|
||||||
gSpecialStatuses[battler].terrainAbilityDone = TRUE;
|
gDisableStructs[battler].terrainAbilityDone = TRUE;
|
||||||
gBattlerAbility = gBattleScripting.battler = battler;
|
|
||||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler));
|
PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler));
|
||||||
|
gBattlerAbility = gBattleScripting.battler = battler;
|
||||||
BattleScriptPushCursorAndCallback(BattleScript_QuarkDriveActivates);
|
BattleScriptPushCursorAndCallback(BattleScript_QuarkDriveActivates);
|
||||||
effect++;
|
effect++;
|
||||||
}
|
}
|
||||||
|
@ -6160,7 +6165,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (effect && gLastUsedAbility != 0xFF)
|
if (effect && gLastUsedAbility != 0xFFFF)
|
||||||
RecordAbilityBattle(battler, gLastUsedAbility);
|
RecordAbilityBattle(battler, gLastUsedAbility);
|
||||||
if (effect && caseID <= ABILITYEFFECT_MOVE_END)
|
if (effect && caseID <= ABILITYEFFECT_MOVE_END)
|
||||||
gBattlerAbility = battler;
|
gBattlerAbility = battler;
|
||||||
|
|
|
@ -85,3 +85,50 @@ SINGLE_BATTLE_TEST("Protosynthesis either boosts Defense or Special Defense, not
|
||||||
EXPECT_EQ(damage[0], damage[1]);
|
EXPECT_EQ(damage[0], damage[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Protosynthesis ability pop up activates only once during the duration of sunny day")
|
||||||
|
{
|
||||||
|
u16 turns;
|
||||||
|
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_BELLSPROUT) { Ability(ABILITY_PROTOSYNTHESIS); }
|
||||||
|
OPPONENT(SPECIES_NINETALES) { Ability(ABILITY_DROUGHT); };
|
||||||
|
} WHEN {
|
||||||
|
for (turns = 0; turns < 5; turns++)
|
||||||
|
TURN {}
|
||||||
|
TURN { MOVE(opponent, MOVE_SUNNY_DAY); }
|
||||||
|
} SCENE {
|
||||||
|
ABILITY_POPUP(opponent, ABILITY_DROUGHT);
|
||||||
|
ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS);
|
||||||
|
MESSAGE("The harsh sunlight activated Bellsprout's Protosynthesis!");
|
||||||
|
MESSAGE("Bellsprout's Attack was heightened!");
|
||||||
|
NONE_OF {
|
||||||
|
for (turns = 0; turns < 4; turns++) {
|
||||||
|
ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS);
|
||||||
|
MESSAGE("The harsh sunlight activated Bellsprout's Protosynthesis!");
|
||||||
|
MESSAGE("Bellsprout's Attack was heightened!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, opponent);
|
||||||
|
ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS);
|
||||||
|
MESSAGE("The harsh sunlight activated Bellsprout's Protosynthesis!");
|
||||||
|
MESSAGE("Bellsprout's Attack was heightened!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Protosynthesis activates on switch-in")
|
||||||
|
{
|
||||||
|
KNOWN_FAILING; // Fails because of wrong species
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_BELLSPROUT) { Ability(ABILITY_PROTOSYNTHESIS); }
|
||||||
|
OPPONENT(SPECIES_NINETALES) { Ability(ABILITY_DROUGHT); };
|
||||||
|
} WHEN {
|
||||||
|
TURN { SWITCH(player, 1); }
|
||||||
|
} SCENE {
|
||||||
|
ABILITY_POPUP(opponent, ABILITY_DROUGHT);
|
||||||
|
ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS);
|
||||||
|
MESSAGE("The harsh sunlight activated Bellsprout's Protosynthesis!");
|
||||||
|
MESSAGE("Bellsprout's Attack was heightened!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -85,3 +85,51 @@ SINGLE_BATTLE_TEST("Quark Drive either boosts Defense or Special Defense, not bo
|
||||||
EXPECT_EQ(damage[0], damage[1]);
|
EXPECT_EQ(damage[0], damage[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Quark Drive ability pop up activates only once during the duration of electric terrain")
|
||||||
|
{
|
||||||
|
u16 turns;
|
||||||
|
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_BELLSPROUT) { Ability(ABILITY_QUARK_DRIVE); }
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, MOVE_ELECTRIC_TERRAIN); }
|
||||||
|
for (turns = 0; turns < 4; turns++)
|
||||||
|
TURN {}
|
||||||
|
TURN { MOVE(opponent, MOVE_ELECTRIC_TERRAIN); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, opponent);
|
||||||
|
ABILITY_POPUP(player, ABILITY_QUARK_DRIVE);
|
||||||
|
MESSAGE("The Electric Terrain activated Bellsprout's Quark Drive!");
|
||||||
|
MESSAGE("Bellsprout's Attack was heightened!");
|
||||||
|
NONE_OF {
|
||||||
|
for (turns = 0; turns < 4; turns++) {
|
||||||
|
ABILITY_POPUP(player, ABILITY_QUARK_DRIVE);
|
||||||
|
MESSAGE("The Electric Terrain activated Bellsprout's Quark Drive!");
|
||||||
|
MESSAGE("Bellsprout's Attack was heightened!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, opponent);
|
||||||
|
ABILITY_POPUP(player, ABILITY_QUARK_DRIVE);
|
||||||
|
MESSAGE("The Electric Terrain activated Bellsprout's Quark Drive!");
|
||||||
|
MESSAGE("Bellsprout's Attack was heightened!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Quark Drive activates on switch-in")
|
||||||
|
{
|
||||||
|
KNOWN_FAILING; // Fails because of wrong species
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_BELLSPROUT) { Ability(ABILITY_QUARK_DRIVE); }
|
||||||
|
OPPONENT(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); };
|
||||||
|
} WHEN {
|
||||||
|
TURN { SWITCH(player, 1); }
|
||||||
|
} SCENE {
|
||||||
|
ABILITY_POPUP(opponent, ABILITY_ELECTRIC_SURGE);
|
||||||
|
ABILITY_POPUP(player, ABILITY_QUARK_DRIVE);
|
||||||
|
MESSAGE("The Electric Terrain activated Bellsprout's Quark Drive!");
|
||||||
|
MESSAGE("Bellsprout's Attack was heightened!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -63,3 +63,36 @@ DOUBLE_BATTLE_TEST("Howl raises user's and partner's Attack", s16 damageLeft, s1
|
||||||
EXPECT_MUL_EQ(results[0].damageRight, Q_4_12(1.5), results[1].damageRight);
|
EXPECT_MUL_EQ(results[0].damageRight, Q_4_12(1.5), results[1].damageRight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Howl does not work on partner if it has Soundproof")
|
||||||
|
{
|
||||||
|
s16 damage[2];
|
||||||
|
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Speed(15); }
|
||||||
|
PLAYER(SPECIES_VOLTORB) { Speed(10); Ability(ABILITY_SOUNDPROOF); }
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
|
||||||
|
OPPONENT(SPECIES_WYNAUT) { Speed(1); }
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); }
|
||||||
|
TURN { MOVE(playerLeft, MOVE_HOWL); MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight);
|
||||||
|
HP_BAR(opponentLeft, captureDamage: &damage[0]);
|
||||||
|
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_HOWL, playerLeft);
|
||||||
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
|
||||||
|
MESSAGE("Wobbuffet's Attack rose!");
|
||||||
|
NONE_OF {
|
||||||
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
|
||||||
|
MESSAGE("Wynaut's Attack rose!");
|
||||||
|
}
|
||||||
|
ABILITY_POPUP(playerRight, ABILITY_SOUNDPROOF);
|
||||||
|
MESSAGE("Voltorb's Soundproof blocks Howl!");
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight);
|
||||||
|
HP_BAR(opponentLeft, captureDamage: &damage[1]);
|
||||||
|
} THEN {
|
||||||
|
EXPECT_EQ(damage[0], damage[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue