Merge branch 'battle_engine' of https://github.com/rh-hideout/pokeemerald-expansion into mimicry

This commit is contained in:
LOuroboros 2021-11-03 20:42:26 -03:00
commit f6628e301f
9 changed files with 93 additions and 18 deletions

View File

@ -1839,6 +1839,10 @@
various BS_ATTACKER, VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER various BS_ATTACKER, VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER
.endm .endm
.macro setattackertostickywebuser
various BS_TARGET, VARIOUS_SET_ATTACKER_STICKY_WEB_USER
.endm
.macro getrototillertargets ptr:req .macro getrototillertargets ptr:req
various BS_ATTACKER, VARIOUS_GET_ROTOTILLER_TARGETS various BS_ATTACKER, VARIOUS_GET_ROTOTILLER_TARGETS
.4byte \ptr .4byte \ptr

View File

@ -2906,6 +2906,34 @@ BattleScript_StatDownPrintString::
BattleScript_StatDownEnd:: BattleScript_StatDownEnd::
goto BattleScript_MoveEnd goto BattleScript_MoveEnd
BattleScript_MirrorArmorReflect::
pause B_WAIT_TIME_SHORT
call BattleScript_AbilityPopUp
jumpifsubstituteblocks BattleScript_AbilityNoSpecificStatLoss
BattleScript_MirrorArmorReflectStatLoss:
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_NOT_PROTECT_AFFECTED | STAT_BUFF_ALLOW_PTR, BattleScript_MirrorArmorReflectEnd
jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_MirrorArmorReflectAnim
goto BattleScript_MirrorArmorReflectWontFall
BattleScript_MirrorArmorReflectAnim:
setgraphicalstatchangevalues
playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
BattleScript_MirrorArmorReflectPrintString:
printfromtable gStatDownStringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_MirrorArmorReflectEnd:
return
BattleScript_MirrorArmorReflectWontFall:
copybyte gBattlerTarget, gBattlerAttacker @ STRINGID_STATSWONTDECREASE uses target
goto BattleScript_MirrorArmorReflectPrintString
@ gBattlerTarget is battler with Mirror Armor
BattleScript_MirrorArmorReflectStickyWeb:
call BattleScript_AbilityPopUp
setattackertostickywebuser
jumpifbyteequal gBattlerAttacker, gBattlerTarget, BattleScript_StickyWebOnSwitchInEnd @ Sticky web user not on field -> no stat loss
goto BattleScript_MirrorArmorReflectStatLoss
BattleScript_StatDown:: BattleScript_StatDown::
playanimation BS_EFFECT_BATTLER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 playanimation BS_EFFECT_BATTLER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
printfromtable gStatDownStringIds printfromtable gStatDownStringIds
@ -6381,6 +6409,7 @@ BattleScript_StickyWebOnSwitchIn::
copybyte gBattlerTarget, sBATTLER copybyte gBattlerTarget, sBATTLER
printstring STRINGID_STICKYWEBSWITCHIN printstring STRINGID_STICKYWEBSWITCHIN
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
jumpifability BS_TARGET, ABILITY_MIRROR_ARMOR, BattleScript_MirrorArmorReflectStickyWeb
statbuffchange STAT_BUFF_ALLOW_PTR, BattleScript_StickyWebOnSwitchInEnd statbuffchange STAT_BUFF_ALLOW_PTR, BattleScript_StickyWebOnSwitchInEnd
jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_StickyWebOnSwitchInStatAnim jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_StickyWebOnSwitchInStatAnim
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_StickyWebOnSwitchInEnd jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_StickyWebOnSwitchInEnd
@ -7955,6 +7984,7 @@ BattleScript_GrassyTerrainHealEnd:
BattleScript_AbilityNoSpecificStatLoss:: BattleScript_AbilityNoSpecificStatLoss::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp
BattleScript_AbilityNoSpecificStatLossPrint:
printstring STRINGID_PKMNSXPREVENTSYLOSS printstring STRINGID_PKMNSXPREVENTSYLOSS
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY
@ -8235,6 +8265,13 @@ BattleScript_CuteCharmActivates::
call BattleScript_TryDestinyKnotTarget call BattleScript_TryDestinyKnotTarget
return return
BattleScript_GooeyActivates::
waitstate
call BattleScript_AbilityPopUp
swapattackerwithtarget @ for defiant, mirror armor
seteffectsecondary
return
BattleScript_AbilityStatusEffect:: BattleScript_AbilityStatusEffect::
waitstate waitstate
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp

View File

@ -612,6 +612,7 @@ struct BattleStruct
struct StolenItem itemStolen[PARTY_SIZE]; // Player's team that had items stolen (two bytes per party member) struct StolenItem itemStolen[PARTY_SIZE]; // Player's team that had items stolen (two bytes per party member)
u8 blunderPolicy:1; // should blunder policy activate u8 blunderPolicy:1; // should blunder policy activate
u8 ballSpriteIds[2]; // item gfx, window gfx u8 ballSpriteIds[2]; // item gfx, window gfx
u8 stickyWebUser;
}; };
#define GET_MOVE_TYPE(move, typeArg) \ #define GET_MOVE_TYPE(move, typeArg) \

View File

@ -404,6 +404,8 @@ extern const u8 BattleScript_PrimalReversion[];
extern const u8 BattleScript_HyperspaceFuryRemoveProtect[]; extern const u8 BattleScript_HyperspaceFuryRemoveProtect[];
extern const u8 BattleScript_SelectingNotAllowedMoveGorillaTactics[]; extern const u8 BattleScript_SelectingNotAllowedMoveGorillaTactics[];
extern const u8 BattleScript_WanderingSpiritActivates[]; extern const u8 BattleScript_WanderingSpiritActivates[];
extern const u8 BattleScript_MirrorArmorReflect[];
extern const u8 BattleScript_GooeyActivates[];
extern const u8 BattleScript_MimicryActivatesEnd3[]; extern const u8 BattleScript_MimicryActivatesEnd3[];
extern const u8 BattleScript_ApplyMimicry[]; extern const u8 BattleScript_ApplyMimicry[];

View File

@ -197,7 +197,8 @@
#define VARIOUS_UPDATE_ABILITY_POPUP 124 #define VARIOUS_UPDATE_ABILITY_POPUP 124
#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 125 #define VARIOUS_JUMP_IF_WEATHER_AFFECTED 125
#define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 126 #define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 126
#define VARIOUS_TRY_TO_APPLY_MIMICRY 127 #define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 127
#define VARIOUS_TRY_TO_APPLY_MIMICRY 128
// Cmd_manipulatedamage // Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 0 #define DMG_CHANGE_SIGN 0

View File

@ -559,7 +559,7 @@ static const struct BgTemplate sBgTemplates[] =
}, },
{ {
.bg = 1, .bg = 1,
.charBaseIndex = 10, .charBaseIndex = 2,
.mapBaseIndex = 20, .mapBaseIndex = 20,
.screenSize = 0, .screenSize = 0,
.paletteMode = 0, .paletteMode = 0,

View File

@ -2933,6 +2933,8 @@ static void BattleStartClearSetData(void)
gBattleStruct->mega.triggerSpriteId = 0xFF; gBattleStruct->mega.triggerSpriteId = 0xFF;
gBattleStruct->stickyWebUser = 0xFF;
for (i = 0; i < PARTY_SIZE; i++) for (i = 0; i < PARTY_SIZE; i++)
{ {
gBattleStruct->usedHeldItems[i][0] = 0; gBattleStruct->usedHeldItems[i][0] = 0;
@ -3031,6 +3033,9 @@ void SwitchInClearSetData(void)
gBattleStruct->lastMoveFailed &= ~(gBitTable[gActiveBattler]); gBattleStruct->lastMoveFailed &= ~(gBitTable[gActiveBattler]);
gBattleStruct->palaceFlags &= ~(gBitTable[gActiveBattler]); gBattleStruct->palaceFlags &= ~(gBitTable[gActiveBattler]);
if (gActiveBattler == gBattleStruct->stickyWebUser)
gBattleStruct->stickyWebUser = 0xFF; // Switched into sticky web user slot so reset it
for (i = 0; i < gBattlersCount; i++) for (i = 0; i < gBattlersCount; i++)
{ {
if (i != gActiveBattler && GetBattlerSide(i) != GetBattlerSide(gActiveBattler)) if (i != gActiveBattler && GetBattlerSide(i) != GetBattlerSide(gActiveBattler))
@ -3128,6 +3133,9 @@ void FaintClearSetData(void)
gBattleStruct->palaceFlags &= ~(gBitTable[gActiveBattler]); gBattleStruct->palaceFlags &= ~(gBitTable[gActiveBattler]);
if (gActiveBattler == gBattleStruct->stickyWebUser)
gBattleStruct->stickyWebUser = 0xFF; // User of sticky web fainted, so reset the stored battler ID
for (i = 0; i < gBattlersCount; i++) for (i = 0; i < gBattlersCount; i++)
{ {
if (i != gActiveBattler && GetBattlerSide(i) != GetBattlerSide(gActiveBattler)) if (i != gActiveBattler && GetBattlerSide(i) != GetBattlerSide(gActiveBattler))

View File

@ -2586,6 +2586,8 @@ void SetMoveEffect(bool32 primary, u32 certain)
{ {
s32 i, byTwo, affectsUser = 0; s32 i, byTwo, affectsUser = 0;
bool32 statusChanged = FALSE; bool32 statusChanged = FALSE;
bool32 mirrorArmorReflected = (GetBattlerAbility(gBattlerTarget) == ABILITY_MIRROR_ARMOR);
u32 flags = 0;
switch (gBattleScripting.moveEffect) // Set move effects which happen later on switch (gBattleScripting.moveEffect) // Set move effects which happen later on
{ {
@ -3016,10 +3018,15 @@ void SetMoveEffect(bool32 primary, u32 certain)
case MOVE_EFFECT_SP_DEF_MINUS_1: case MOVE_EFFECT_SP_DEF_MINUS_1:
case MOVE_EFFECT_ACC_MINUS_1: case MOVE_EFFECT_ACC_MINUS_1:
case MOVE_EFFECT_EVS_MINUS_1: case MOVE_EFFECT_EVS_MINUS_1:
flags = affectsUser;
if (mirrorArmorReflected && !affectsUser)
flags |= STAT_BUFF_ALLOW_PTR;
if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(1) | STAT_BUFF_NEGATIVE, if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(1) | STAT_BUFF_NEGATIVE,
gBattleScripting.moveEffect - MOVE_EFFECT_ATK_MINUS_1 + 1, gBattleScripting.moveEffect - MOVE_EFFECT_ATK_MINUS_1 + 1,
affectsUser, 0)) flags, gBattlescriptCurrInstr + 1))
{ {
if (!mirrorArmorReflected)
gBattlescriptCurrInstr++; gBattlescriptCurrInstr++;
} }
else else
@ -3058,10 +3065,14 @@ void SetMoveEffect(bool32 primary, u32 certain)
case MOVE_EFFECT_SP_DEF_MINUS_2: case MOVE_EFFECT_SP_DEF_MINUS_2:
case MOVE_EFFECT_ACC_MINUS_2: case MOVE_EFFECT_ACC_MINUS_2:
case MOVE_EFFECT_EVS_MINUS_2: case MOVE_EFFECT_EVS_MINUS_2:
flags = affectsUser;
if (mirrorArmorReflected && !affectsUser)
flags |= STAT_BUFF_ALLOW_PTR;
if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(2) | STAT_BUFF_NEGATIVE, if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(2) | STAT_BUFF_NEGATIVE,
gBattleScripting.moveEffect - MOVE_EFFECT_ATK_MINUS_2 + 1, gBattleScripting.moveEffect - MOVE_EFFECT_ATK_MINUS_2 + 1,
affectsUser, 0)) flags, gBattlescriptCurrInstr + 1))
{ {
if (!mirrorArmorReflected)
gBattlescriptCurrInstr++; gBattlescriptCurrInstr++;
} }
else else
@ -9005,6 +9016,14 @@ static void Cmd_various(void)
gBattlescriptCurrInstr += 7; gBattlescriptCurrInstr += 7;
} }
return; return;
case VARIOUS_SET_ATTACKER_STICKY_WEB_USER:
// For Mirror Armor: "If the Pokémon with this Ability is affected by Sticky Web, the effect is reflected back to the Pokémon which set it up.
// If Pokémon which set up Sticky Web is not on the field, no Pokémon have their Speed lowered."
gBattlerAttacker = gBattlerTarget; // Initialize 'fail' condition
SET_STATCHANGER(STAT_SPEED, 1, TRUE);
if (gBattleStruct->stickyWebUser != 0xFF)
gBattlerAttacker = gBattleStruct->stickyWebUser;
break;
case VARIOUS_TRY_TO_APPLY_MIMICRY: case VARIOUS_TRY_TO_APPLY_MIMICRY:
{ {
bool8 isMimicryDone = FALSE; bool8 isMimicryDone = FALSE;
@ -9553,8 +9572,9 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
bool32 certain = FALSE; bool32 certain = FALSE;
bool32 notProtectAffected = FALSE; bool32 notProtectAffected = FALSE;
u32 index; u32 index;
bool32 affectsUser = (flags & MOVE_EFFECT_AFFECTS_USER);
if (flags & MOVE_EFFECT_AFFECTS_USER) if (affectsUser)
gActiveBattler = gBattlerAttacker; gActiveBattler = gBattlerAttacker;
else else
gActiveBattler = gBattlerTarget; gActiveBattler = gBattlerTarget;
@ -9655,8 +9675,9 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
} }
return STAT_CHANGE_DIDNT_WORK; return STAT_CHANGE_DIDNT_WORK;
} }
else if (GetBattlerAbility(gActiveBattler) == ABILITY_KEEN_EYE else if (!certain
&& !certain && statId == STAT_ACC) && ((GetBattlerAbility(gActiveBattler) == ABILITY_KEEN_EYE && statId == STAT_ACC)
|| (GetBattlerAbility(gActiveBattler) == ABILITY_HYPER_CUTTER && statId == STAT_ATK)))
{ {
if (flags == STAT_BUFF_ALLOW_PTR) if (flags == STAT_BUFF_ALLOW_PTR)
{ {
@ -9669,17 +9690,16 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
} }
return STAT_CHANGE_DIDNT_WORK; return STAT_CHANGE_DIDNT_WORK;
} }
else if (GetBattlerAbility(gActiveBattler) == ABILITY_HYPER_CUTTER else if (GetBattlerAbility(gActiveBattler) == ABILITY_MIRROR_ARMOR && !affectsUser && gBattlerAttacker != gBattlerTarget && gActiveBattler == gBattlerTarget)
&& !certain && statId == STAT_ATK)
{ {
if (flags == STAT_BUFF_ALLOW_PTR) if (flags == STAT_BUFF_ALLOW_PTR)
{ {
SET_STATCHANGER(statId, GET_STAT_BUFF_VALUE(statValue) | STAT_BUFF_NEGATIVE, TRUE);
BattleScriptPush(BS_ptr); BattleScriptPush(BS_ptr);
gBattleScripting.battler = gActiveBattler; gBattleScripting.battler = gActiveBattler;
gBattlerAbility = gActiveBattler; gBattlerAbility = gActiveBattler;
gBattlescriptCurrInstr = BattleScript_AbilityNoSpecificStatLoss; gBattlescriptCurrInstr = BattleScript_MirrorArmorReflect;
gLastUsedAbility = GetBattlerAbility(gActiveBattler); RecordAbilityBattle(gActiveBattler, gBattleMons[gActiveBattler].ability);
RecordAbilityBattle(gActiveBattler, gLastUsedAbility);
} }
return STAT_CHANGE_DIDNT_WORK; return STAT_CHANGE_DIDNT_WORK;
} }
@ -11575,6 +11595,7 @@ static void Cmd_setstickyweb(void)
{ {
gSideStatuses[targetSide] |= SIDE_STATUS_STICKY_WEB; gSideStatuses[targetSide] |= SIDE_STATUS_STICKY_WEB;
gSideTimers[targetSide].stickyWebAmount = 1; gSideTimers[targetSide].stickyWebAmount = 1;
gBattleStruct->stickyWebUser = gBattlerAttacker; // For Mirror Armor
gBattlescriptCurrInstr += 5; gBattlescriptCurrInstr += 5;
} }
} }

View File

@ -4986,15 +4986,16 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
case ABILITY_TANGLING_HAIR: case ABILITY_TANGLING_HAIR:
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& gBattleMons[gBattlerAttacker].hp != 0 && gBattleMons[gBattlerAttacker].hp != 0
&& CompareStat(gBattlerAttacker, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN) && (CompareStat(gBattlerAttacker, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN) || GetBattlerAbility(gBattlerAttacker) == ABILITY_MIRROR_ARMOR)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg && !gProtectStructs[gBattlerAttacker].confusionSelfDmg
&& TARGET_TURN_DAMAGED && TARGET_TURN_DAMAGED
&& IsMoveMakingContact(move, gBattlerAttacker)) && IsMoveMakingContact(move, gBattlerAttacker))
{ {
gBattleScripting.moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_SPD_MINUS_1; SET_STATCHANGER(STAT_SPEED, 1, TRUE);
gBattleScripting.moveEffect = MOVE_EFFECT_SPD_MINUS_1;
PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility); PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility);
BattleScriptPushCursor(); BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_AbilityStatusEffect; gBattlescriptCurrInstr = BattleScript_GooeyActivates;
gHitMarker |= HITMARKER_IGNORE_SAFEGUARD; gHitMarker |= HITMARKER_IGNORE_SAFEGUARD;
effect++; effect++;
} }