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::
printstring STRINGID_PKMNCANTUSEMOVETAUNT
goto BattleScript_SelectingUnusableMoveInPalace
BattleScript_SelectingNotAllowedMoveThroatChop::
printselectionstring STRINGID_PKMNCANTUSEMOVETHROATCHOP
endselectionscript
@ -6757,6 +6757,14 @@ BattleScript_AbilityStatusEffect::
seteffectsecondary
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::
waitstate
call BattleScript_AbilityPopUp

View File

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

View File

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

View File

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

View File

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

View File

@ -1032,7 +1032,6 @@ static void Cmd_attackcanceler(void)
}
gHitMarker |= HITMARKER_OBEYS;
if (NoTargetPresent(gCurrentMove))
{
gBattlescriptCurrInstr = BattleScript_ButItFailedAtkStringPpReduce;
@ -4539,8 +4538,6 @@ static void Cmd_moveend(void)
gBattleScripting.moveendState++;
break;
case MOVEEND_UPDATE_LAST_MOVES:
gDisableStructs[gBattlerAttacker].usedMoves |= gBitTable[gCurrMovePos];
gBattleStruct->lastMoveTarget[gBattlerAttacker] = gBattlerTarget;
if (gMoveResultFlags & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE))
gBattleStruct->lastMoveFailed |= gBitTable[gBattlerAttacker];
else
@ -4553,10 +4550,15 @@ static void Cmd_moveend(void)
gBattlerTarget = gActiveBattler;
gHitMarker &= ~(HITMARKER_SWAP_ATTACKER_TARGET);
}
if (gHitMarker & HITMARKER_ATTACKSTRING_PRINTED)
if (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove)
{
gLastPrintedMoves[gBattlerAttacker] = gChosenMove;
gLastUsedMove = gCurrentMove;
gDisableStructs[gBattlerAttacker].usedMoves |= gBitTable[gCurrMovePos];
gBattleStruct->lastMoveTarget[gBattlerAttacker] = gBattlerTarget;
if (gHitMarker & HITMARKER_ATTACKSTRING_PRINTED)
{
gLastPrintedMoves[gBattlerAttacker] = gChosenMove;
gLastUsedMove = gCurrentMove;
}
}
if (!(gAbsentBattlerFlags & gBitTable[gBattlerAttacker])
&& !(gBattleStruct->field_91 & gBitTable[gBattlerAttacker])
@ -4564,9 +4566,11 @@ static void Cmd_moveend(void)
&& gBattleMoves[originallyUsedMove].effect != EFFECT_HEALING_WISH)
{
if (gHitMarker & HITMARKER_OBEYS)
{
gLastMoves[gBattlerAttacker] = gChosenMove;
gLastResultingMoves[gBattlerAttacker] = gCurrentMove;
{ if (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove)
{
gLastMoves[gBattlerAttacker] = gChosenMove;
gLastResultingMoves[gBattlerAttacker] = gCurrentMove;
}
}
else
{
@ -4665,9 +4669,41 @@ static void Cmd_moveend(void)
}
gBattleScripting.moveendState++;
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.
if (gSpecialStatuses[gBattlerAttacker].instructedChosenTarget)
*(gBattleStruct->moveTarget + gBattlerAttacker) = gSpecialStatuses[gBattlerAttacker].instructedChosenTarget & 0x3;
if (gSpecialStatuses[gBattlerAttacker].dancerOriginalTarget)
*(gBattleStruct->moveTarget + gBattlerAttacker) = gSpecialStatuses[gBattlerAttacker].dancerOriginalTarget & 0x3;
gProtectStructs[gBattlerAttacker].usesBouncedMove = 0;
gBattleStruct->ateBoost[gBattlerAttacker] = 0;
gStatuses3[gBattlerAttacker] &= ~(STATUS3_ME_FIRST);
@ -8384,7 +8420,7 @@ static void Cmd_setbide(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);
gBattlescriptCurrInstr++;
@ -11060,7 +11096,7 @@ static void Cmd_pursuitrelated(void)
gCurrentMove = MOVE_PURSUIT;
gBattlescriptCurrInstr += 5;
gBattleScripting.animTurn = 1;
gBattleScripting.field_20 = gBattlerAttacker;
gBattleScripting.savedBattler = gBattlerAttacker;
gBattlerAttacker = gActiveBattler;
}
else

View File

@ -1351,6 +1351,7 @@ enum
ENDTURN_WRAP,
ENDTURN_UPROAR,
ENDTURN_THRASH,
ENDTURN_FLINCH,
ENDTURN_DISABLE,
ENDTURN_ENCORE,
ENDTURN_MAGNET_RISE,
@ -1660,6 +1661,9 @@ u8 DoBattlerEndTurnEffects(void)
}
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_FLINCH: // reset flinch
gBattleMons[gActiveBattler].status2 &= ~(STATUS2_FLINCHED);
gBattleStruct->turnEffectsTracker++;
case ENDTURN_DISABLE: // disable
if (gDisableStructs[gActiveBattler].disableTimer != 0)
{
@ -2183,7 +2187,6 @@ u8 AtkCanceller_UnableToUseMove(void)
case CANCELLER_FLINCH: // flinch
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_FLINCHED)
{
gBattleMons[gBattlerAttacker].status2 &= ~(STATUS2_FLINCHED);
gProtectStructs[gBattlerAttacker].flinchImmobility = 1;
CancelMultiTurnMoves(gBattlerAttacker);
gBattlescriptCurrInstr = BattleScript_MoveUsedFlinched;
@ -3447,6 +3450,35 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
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
for (battler = 0; battler < gBattlersCount; battler++)
{