Implemented Dancer and all relevant code for interacting with abilities, certain moves, etc
This commit is contained in:
Nephrite 2019-11-13 23:03:20 +00:00
parent b4ac979600
commit 0343f63eda
7 changed files with 98 additions and 17 deletions

View file

@ -5621,7 +5621,7 @@ BattleScript_MoveUsedIsTaunted::
BattleScript_SelectingNotAllowedMoveTauntInPalace:: BattleScript_SelectingNotAllowedMoveTauntInPalace::
printstring STRINGID_PKMNCANTUSEMOVETAUNT printstring STRINGID_PKMNCANTUSEMOVETAUNT
goto BattleScript_SelectingUnusableMoveInPalace goto BattleScript_SelectingUnusableMoveInPalace
BattleScript_SelectingNotAllowedMoveThroatChop:: BattleScript_SelectingNotAllowedMoveThroatChop::
printselectionstring STRINGID_PKMNCANTUSEMOVETHROATCHOP printselectionstring STRINGID_PKMNCANTUSEMOVETHROATCHOP
endselectionscript endselectionscript
@ -6757,6 +6757,14 @@ BattleScript_AbilityStatusEffect::
seteffectsecondary seteffectsecondary
return return
BattleScript_DancerActivates::
call BattleScript_AbilityPopUp
waitmessage 0x20
setbyte sB_ANIM_TURN, 0x0
setbyte sB_ANIM_TARGETS_HIT, 0x0
orword gHitMarker, HITMARKER_x800000
jumptocalledmove TRUE
BattleScript_SynchronizeActivates:: BattleScript_SynchronizeActivates::
waitstate waitstate
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp

View file

@ -174,6 +174,8 @@ struct SpecialStatus
u8 gemBoost:1; u8 gemBoost:1;
u8 gemParam; u8 gemParam;
u8 damagedMons:4; // Mons that have been damaged directly by using a move, includes substitute. u8 damagedMons:4; // Mons that have been damaged directly by using a move, includes substitute.
u8 dancerUsedMove:1;
u8 dancerOriginalTarget:3;
s32 dmg; s32 dmg;
s32 physicalDmg; s32 physicalDmg;
s32 specialDmg; s32 specialDmg;
@ -594,7 +596,7 @@ struct BattleScripting
u8 battleStyle; u8 battleStyle;
u8 drawlvlupboxState; u8 drawlvlupboxState;
u8 learnMoveState; u8 learnMoveState;
u8 field_20; u8 savedBattler;
u8 reshowMainState; u8 reshowMainState;
u8 reshowHelperState; u8 reshowHelperState;
u8 field_23; u8 field_23;

View file

@ -326,5 +326,6 @@ extern const u8 BattleScript_FlameOrb[];
extern const u8 BattleScript_MoveEffectIncinerate[]; extern const u8 BattleScript_MoveEffectIncinerate[];
extern const u8 BattleScript_MoveEffectBugBite[]; extern const u8 BattleScript_MoveEffectBugBite[];
extern const u8 BattleScript_IllusionOff[]; extern const u8 BattleScript_IllusionOff[];
extern const u8 BattleScript_DancerActivates[];
#endif // GUARD_BATTLE_SCRIPTS_H #endif // GUARD_BATTLE_SCRIPTS_H

View file

@ -21,6 +21,7 @@
#define ABILITYEFFECT_INTIMIDATE2 0xA #define ABILITYEFFECT_INTIMIDATE2 0xA
#define ABILITYEFFECT_TRACE1 0xB #define ABILITYEFFECT_TRACE1 0xB
#define ABILITYEFFECT_TRACE2 0xC #define ABILITYEFFECT_TRACE2 0xC
#define ABILITYEFFECT_MOVE_END_OTHER 0xD
#define ABILITYEFFECT_SWITCH_IN_WEATHER 0xFF #define ABILITYEFFECT_SWITCH_IN_WEATHER 0xFF
#define ITEMEFFECT_ON_SWITCH_IN 0x0 #define ITEMEFFECT_ON_SWITCH_IN 0x0

View file

@ -22,7 +22,7 @@
#define sBATTLE_STYLE gBattleScripting + 0x1D #define sBATTLE_STYLE gBattleScripting + 0x1D
#define sLVLBOX_STATE gBattleScripting + 0x1E #define sLVLBOX_STATE gBattleScripting + 0x1E
#define sLEARNMOVE_STATE gBattleScripting + 0x1F #define sLEARNMOVE_STATE gBattleScripting + 0x1F
#define sFIELD_20 gBattleScripting + 0x20 #define sSAVED_BATTLER gBattleScripting + 0x20
#define sRESHOW_MAIN_STATE gBattleScripting + 0x21 #define sRESHOW_MAIN_STATE gBattleScripting + 0x21
#define sRESHOW_HELPER_STATE gBattleScripting + 0x22 #define sRESHOW_HELPER_STATE gBattleScripting + 0x22
#define sFIELD_23 gBattleScripting + 0x23 #define sFIELD_23 gBattleScripting + 0x23
@ -188,8 +188,9 @@
#define MOVEEND_MIRROR_MOVE 17 #define MOVEEND_MIRROR_MOVE 17
#define MOVEEND_NEXT_TARGET 18 #define MOVEEND_NEXT_TARGET 18
#define MOVEEND_LIFE_ORB 19 #define MOVEEND_LIFE_ORB 19
#define MOVEEND_CLEAR_BITS 20 #define MOVEEND_DANCER 20
#define MOVEEND_COUNT 21 #define MOVEEND_CLEAR_BITS 21
#define MOVEEND_COUNT 22
// stat flags for Cmd_playstatchangeanimation // stat flags for Cmd_playstatchangeanimation
#define BIT_HP 0x1 #define BIT_HP 0x1

View file

@ -1032,7 +1032,6 @@ static void Cmd_attackcanceler(void)
} }
gHitMarker |= HITMARKER_OBEYS; gHitMarker |= HITMARKER_OBEYS;
if (NoTargetPresent(gCurrentMove)) if (NoTargetPresent(gCurrentMove))
{ {
gBattlescriptCurrInstr = BattleScript_ButItFailedAtkStringPpReduce; gBattlescriptCurrInstr = BattleScript_ButItFailedAtkStringPpReduce;
@ -4539,8 +4538,6 @@ static void Cmd_moveend(void)
gBattleScripting.moveendState++; gBattleScripting.moveendState++;
break; break;
case MOVEEND_UPDATE_LAST_MOVES: case MOVEEND_UPDATE_LAST_MOVES:
gDisableStructs[gBattlerAttacker].usedMoves |= gBitTable[gCurrMovePos];
gBattleStruct->lastMoveTarget[gBattlerAttacker] = gBattlerTarget;
if (gMoveResultFlags & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE)) if (gMoveResultFlags & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE))
gBattleStruct->lastMoveFailed |= gBitTable[gBattlerAttacker]; gBattleStruct->lastMoveFailed |= gBitTable[gBattlerAttacker];
else else
@ -4553,10 +4550,15 @@ static void Cmd_moveend(void)
gBattlerTarget = gActiveBattler; gBattlerTarget = gActiveBattler;
gHitMarker &= ~(HITMARKER_SWAP_ATTACKER_TARGET); gHitMarker &= ~(HITMARKER_SWAP_ATTACKER_TARGET);
} }
if (gHitMarker & HITMARKER_ATTACKSTRING_PRINTED) if (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove)
{ {
gLastPrintedMoves[gBattlerAttacker] = gChosenMove; gDisableStructs[gBattlerAttacker].usedMoves |= gBitTable[gCurrMovePos];
gLastUsedMove = gCurrentMove; gBattleStruct->lastMoveTarget[gBattlerAttacker] = gBattlerTarget;
if (gHitMarker & HITMARKER_ATTACKSTRING_PRINTED)
{
gLastPrintedMoves[gBattlerAttacker] = gChosenMove;
gLastUsedMove = gCurrentMove;
}
} }
if (!(gAbsentBattlerFlags & gBitTable[gBattlerAttacker]) if (!(gAbsentBattlerFlags & gBitTable[gBattlerAttacker])
&& !(gBattleStruct->field_91 & gBitTable[gBattlerAttacker]) && !(gBattleStruct->field_91 & gBitTable[gBattlerAttacker])
@ -4564,9 +4566,11 @@ static void Cmd_moveend(void)
&& gBattleMoves[originallyUsedMove].effect != EFFECT_HEALING_WISH) && gBattleMoves[originallyUsedMove].effect != EFFECT_HEALING_WISH)
{ {
if (gHitMarker & HITMARKER_OBEYS) if (gHitMarker & HITMARKER_OBEYS)
{ { if (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove)
gLastMoves[gBattlerAttacker] = gChosenMove; {
gLastResultingMoves[gBattlerAttacker] = gCurrentMove; gLastMoves[gBattlerAttacker] = gChosenMove;
gLastResultingMoves[gBattlerAttacker] = gCurrentMove;
}
} }
else else
{ {
@ -4665,9 +4669,41 @@ static void Cmd_moveend(void)
} }
gBattleScripting.moveendState++; gBattleScripting.moveendState++;
break; break;
case MOVEEND_DANCER: // Special case because it's so annoying
if (gBattleMoves[gCurrentMove].flags & FLAG_DANCE)
{
u8 battler, nextDancer = 0;
if (!(gBattleStruct->lastMoveFailed & gBitTable[gBattlerAttacker]
|| (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove
&& gProtectStructs[gBattlerAttacker].usesBouncedMove)))
{ // Dance move succeeds
// Set target for other Dancer mons; set bit so that mon cannot activate Dancer off of its own move
if (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove)
{
gBattleScripting.savedBattler = gBattlerTarget | 0x4;
gBattleScripting.savedBattler |= (gBattlerAttacker << 4);
gSpecialStatuses[gBattlerAttacker].dancerUsedMove = 1;
}
for (battler = 0; battler < MAX_BATTLERS_COUNT; battler++)
{
if (GetBattlerAbility(battler) == ABILITY_DANCER && !gSpecialStatuses[battler].dancerUsedMove)
{
if (!nextDancer || (gBattleMons[battler].speed < gBattleMons[nextDancer & 0x3].speed))
nextDancer = battler | 0x4;
}
}
if (nextDancer && AbilityBattleEffects(ABILITYEFFECT_MOVE_END_OTHER, nextDancer & 0x3, 0, 0, 0))
effect = TRUE;
}
}
gBattleScripting.atk49_state++;
break;
case MOVEEND_CLEAR_BITS: // Clear bits active while using a move for all targets and all hits. case MOVEEND_CLEAR_BITS: // Clear bits active while using a move for all targets and all hits.
if (gSpecialStatuses[gBattlerAttacker].instructedChosenTarget) if (gSpecialStatuses[gBattlerAttacker].instructedChosenTarget)
*(gBattleStruct->moveTarget + gBattlerAttacker) = gSpecialStatuses[gBattlerAttacker].instructedChosenTarget & 0x3; *(gBattleStruct->moveTarget + gBattlerAttacker) = gSpecialStatuses[gBattlerAttacker].instructedChosenTarget & 0x3;
if (gSpecialStatuses[gBattlerAttacker].dancerOriginalTarget)
*(gBattleStruct->moveTarget + gBattlerAttacker) = gSpecialStatuses[gBattlerAttacker].dancerOriginalTarget & 0x3;
gProtectStructs[gBattlerAttacker].usesBouncedMove = 0; gProtectStructs[gBattlerAttacker].usesBouncedMove = 0;
gBattleStruct->ateBoost[gBattlerAttacker] = 0; gBattleStruct->ateBoost[gBattlerAttacker] = 0;
gStatuses3[gBattlerAttacker] &= ~(STATUS3_ME_FIRST); gStatuses3[gBattlerAttacker] &= ~(STATUS3_ME_FIRST);
@ -8384,7 +8420,7 @@ static void Cmd_setbide(void)
static void Cmd_confuseifrepeatingattackends(void) static void Cmd_confuseifrepeatingattackends(void)
{ {
if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_LOCK_CONFUSE)) if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_LOCK_CONFUSE) && !gSpecialStatuses[gBattlerAttacker].dancerUsedMove)
gBattleScripting.moveEffect = (MOVE_EFFECT_THRASH | MOVE_EFFECT_AFFECTS_USER); gBattleScripting.moveEffect = (MOVE_EFFECT_THRASH | MOVE_EFFECT_AFFECTS_USER);
gBattlescriptCurrInstr++; gBattlescriptCurrInstr++;
@ -11060,7 +11096,7 @@ static void Cmd_pursuitrelated(void)
gCurrentMove = MOVE_PURSUIT; gCurrentMove = MOVE_PURSUIT;
gBattlescriptCurrInstr += 5; gBattlescriptCurrInstr += 5;
gBattleScripting.animTurn = 1; gBattleScripting.animTurn = 1;
gBattleScripting.field_20 = gBattlerAttacker; gBattleScripting.savedBattler = gBattlerAttacker;
gBattlerAttacker = gActiveBattler; gBattlerAttacker = gActiveBattler;
} }
else else

View file

@ -1351,6 +1351,7 @@ enum
ENDTURN_WRAP, ENDTURN_WRAP,
ENDTURN_UPROAR, ENDTURN_UPROAR,
ENDTURN_THRASH, ENDTURN_THRASH,
ENDTURN_FLINCH,
ENDTURN_DISABLE, ENDTURN_DISABLE,
ENDTURN_ENCORE, ENDTURN_ENCORE,
ENDTURN_MAGNET_RISE, ENDTURN_MAGNET_RISE,
@ -1660,6 +1661,9 @@ u8 DoBattlerEndTurnEffects(void)
} }
gBattleStruct->turnEffectsTracker++; gBattleStruct->turnEffectsTracker++;
break; break;
case ENDTURN_FLINCH: // reset flinch
gBattleMons[gActiveBattler].status2 &= ~(STATUS2_FLINCHED);
gBattleStruct->turnEffectsTracker++;
case ENDTURN_DISABLE: // disable case ENDTURN_DISABLE: // disable
if (gDisableStructs[gActiveBattler].disableTimer != 0) if (gDisableStructs[gActiveBattler].disableTimer != 0)
{ {
@ -2183,7 +2187,6 @@ u8 AtkCanceller_UnableToUseMove(void)
case CANCELLER_FLINCH: // flinch case CANCELLER_FLINCH: // flinch
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_FLINCHED) if (gBattleMons[gBattlerAttacker].status2 & STATUS2_FLINCHED)
{ {
gBattleMons[gBattlerAttacker].status2 &= ~(STATUS2_FLINCHED);
gProtectStructs[gBattlerAttacker].flinchImmobility = 1; gProtectStructs[gBattlerAttacker].flinchImmobility = 1;
CancelMultiTurnMoves(gBattlerAttacker); CancelMultiTurnMoves(gBattlerAttacker);
gBattlescriptCurrInstr = BattleScript_MoveUsedFlinched; gBattlescriptCurrInstr = BattleScript_MoveUsedFlinched;
@ -3447,6 +3450,35 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
break; break;
} }
break; break;
case ABILITYEFFECT_MOVE_END_OTHER: // Abilities that activate on *another* battler's moveend: Dancer, Soul-Heart, Receiver, Symbiosis
switch (GetBattlerAbility(battler))
{
case ABILITY_DANCER:
if (IsBattlerAlive(battler)
&& (gBattleMoves[gCurrentMove].flags & FLAG_DANCE)
&& !gSpecialStatuses[battler].dancerUsedMove
&& gBattlerAttacker != battler)
{
// Set bit and save Dancer mon's original target
gSpecialStatuses[battler].dancerUsedMove = 1;
gSpecialStatuses[battler].dancerOriginalTarget = *(gBattleStruct->moveTarget + battler) | 0x4;
gBattleStruct->atkCancellerTracker = 0;
gBattlerAttacker = gBattlerAbility = battler;
gCalledMove = gCurrentMove;
// Set the target to the original target of the mon that first used a Dance move
gBattlerTarget = gBattleScripting.savedBattler & 0x3;
// Make sure that the target isn't an ally - if it is, target the original user
if (GetBattlerSide(gBattlerTarget) == GetBattlerSide(gBattlerAttacker))
gBattlerTarget = (gBattleScripting.savedBattler & 0xF0) >> 4;
gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED);
BattleScriptExecute(BattleScript_DancerActivates);
effect++;
}
break;
}
break;
case ABILITYEFFECT_IMMUNITY: // 5 case ABILITYEFFECT_IMMUNITY: // 5
for (battler = 0; battler < gBattlersCount; battler++) for (battler = 0; battler < gBattlersCount; battler++)
{ {