Adds Dragon Darts effect (CFRU port) (#4612)
* Adds Dragon Darts effect (CFRU port) * fix test compile * review
This commit is contained in:
parent
be2517415b
commit
7a393a974a
7 changed files with 342 additions and 72 deletions
|
@ -20,26 +20,31 @@
|
||||||
#define MOVE_LIMITATION_PLACEHOLDER (1 << 15)
|
#define MOVE_LIMITATION_PLACEHOLDER (1 << 15)
|
||||||
#define MOVE_LIMITATIONS_ALL 0xFFFF
|
#define MOVE_LIMITATIONS_ALL 0xFFFF
|
||||||
|
|
||||||
#define ABILITYEFFECT_ON_SWITCHIN 0
|
enum {
|
||||||
#define ABILITYEFFECT_ENDTURN 1
|
ABILITYEFFECT_ON_SWITCHIN,
|
||||||
#define ABILITYEFFECT_MOVES_BLOCK 2
|
ABILITYEFFECT_ENDTURN,
|
||||||
#define ABILITYEFFECT_ABSORBING 3
|
ABILITYEFFECT_MOVES_BLOCK,
|
||||||
#define ABILITYEFFECT_MOVE_END_ATTACKER 4
|
ABILITYEFFECT_WOULD_BLOCK, // Checks immunity without triggering a script
|
||||||
#define ABILITYEFFECT_MOVE_END 5
|
ABILITYEFFECT_ABSORBING,
|
||||||
#define ABILITYEFFECT_IMMUNITY 6
|
ABILITYEFFECT_WOULD_ABSORB, // Checks immunity without triggering a script
|
||||||
#define ABILITYEFFECT_SYNCHRONIZE 7
|
ABILITYEFFECT_MOVE_END_ATTACKER,
|
||||||
#define ABILITYEFFECT_ATK_SYNCHRONIZE 8
|
ABILITYEFFECT_MOVE_END,
|
||||||
#define ABILITYEFFECT_TRACE1 9
|
ABILITYEFFECT_IMMUNITY,
|
||||||
#define ABILITYEFFECT_TRACE2 10
|
ABILITYEFFECT_SYNCHRONIZE,
|
||||||
#define ABILITYEFFECT_MOVE_END_OTHER 11
|
ABILITYEFFECT_ATK_SYNCHRONIZE,
|
||||||
#define ABILITYEFFECT_NEUTRALIZINGGAS 12
|
ABILITYEFFECT_TRACE1,
|
||||||
#define ABILITYEFFECT_FIELD_SPORT 13 // Only used if B_SPORT_TURNS >= GEN_6
|
ABILITYEFFECT_TRACE2,
|
||||||
#define ABILITYEFFECT_ON_WEATHER 14
|
ABILITYEFFECT_MOVE_END_OTHER,
|
||||||
#define ABILITYEFFECT_ON_TERRAIN 15
|
ABILITYEFFECT_NEUTRALIZINGGAS,
|
||||||
#define ABILITYEFFECT_SWITCH_IN_TERRAIN 16
|
ABILITYEFFECT_FIELD_SPORT, // Only used if B_SPORT_TURNS >= GEN_6
|
||||||
#define ABILITYEFFECT_SWITCH_IN_WEATHER 17
|
ABILITYEFFECT_ON_WEATHER,
|
||||||
#define ABILITYEFFECT_OPPORTUNIST 18
|
ABILITYEFFECT_ON_TERRAIN,
|
||||||
#define ABILITYEFFECT_SWITCH_IN_STATUSES 19
|
ABILITYEFFECT_SWITCH_IN_TERRAIN,
|
||||||
|
ABILITYEFFECT_SWITCH_IN_WEATHER,
|
||||||
|
ABILITYEFFECT_OPPORTUNIST,
|
||||||
|
ABILITYEFFECT_SWITCH_IN_STATUSES,
|
||||||
|
};
|
||||||
|
|
||||||
// Special cases
|
// Special cases
|
||||||
#define ABILITYEFFECT_MUD_SPORT 252 // Only used if B_SPORT_TURNS >= GEN_6
|
#define ABILITYEFFECT_MUD_SPORT 252 // Only used if B_SPORT_TURNS >= GEN_6
|
||||||
#define ABILITYEFFECT_WATER_SPORT 253 // Only used if B_SPORT_TURNS >= GEN_6
|
#define ABILITYEFFECT_WATER_SPORT 253 // Only used if B_SPORT_TURNS >= GEN_6
|
||||||
|
@ -233,6 +238,8 @@ bool32 MoveHasAdditionalEffectWithChance(u32 move, u32 moveEffect, u32 chance);
|
||||||
bool32 MoveHasAdditionalEffectSelf(u32 move, u32 moveEffect);
|
bool32 MoveHasAdditionalEffectSelf(u32 move, u32 moveEffect);
|
||||||
bool32 MoveHasAdditionalEffectSelfArg(u32 move, u32 moveEffect, u32 argument);
|
bool32 MoveHasAdditionalEffectSelfArg(u32 move, u32 moveEffect, u32 argument);
|
||||||
bool32 MoveHasChargeTurnAdditionalEffect(u32 move);
|
bool32 MoveHasChargeTurnAdditionalEffect(u32 move);
|
||||||
|
bool32 CanTargetPartner(u32 battlerAtk, u32 battlerDef);
|
||||||
|
bool32 TargetFullyImmuneToCurrMove(u32 BattlerAtk, u32 battlerDef);
|
||||||
|
|
||||||
bool32 CanSleep(u32 battler);
|
bool32 CanSleep(u32 battler);
|
||||||
bool32 CanBePoisoned(u32 battlerAttacker, u32 battlerTarget);
|
bool32 CanBePoisoned(u32 battlerAttacker, u32 battlerTarget);
|
||||||
|
|
|
@ -352,6 +352,7 @@ enum {
|
||||||
EFFECT_SPICY_EXTRACT,
|
EFFECT_SPICY_EXTRACT,
|
||||||
EFFECT_TERA_BLAST,
|
EFFECT_TERA_BLAST,
|
||||||
EFFECT_TERA_STARSTORM,
|
EFFECT_TERA_STARSTORM,
|
||||||
|
EFFECT_DRAGON_DARTS,
|
||||||
NUM_BATTLE_MOVE_EFFECTS,
|
NUM_BATTLE_MOVE_EFFECTS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -336,6 +336,7 @@ static bool8 CanAbilityPreventStatLoss(u16 abilityDef);
|
||||||
static bool8 CanBurnHitThaw(u16 move);
|
static bool8 CanBurnHitThaw(u16 move);
|
||||||
static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent);
|
static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent);
|
||||||
static void TryUpdateEvolutionTracker(u32 evolutionMethod, u32 upAmount, u16 usedMove);
|
static void TryUpdateEvolutionTracker(u32 evolutionMethod, u32 upAmount, u16 usedMove);
|
||||||
|
static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u8 *failInstr, u16 move);
|
||||||
|
|
||||||
static void Cmd_attackcanceler(void);
|
static void Cmd_attackcanceler(void);
|
||||||
static void Cmd_accuracycheck(void);
|
static void Cmd_accuracycheck(void);
|
||||||
|
@ -1683,11 +1684,9 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u
|
||||||
return calc;
|
return calc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Cmd_accuracycheck(void)
|
static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u8 *failInstr, u16 move)
|
||||||
{
|
{
|
||||||
CMD_ARGS(const u8 *failInstr, u16 move);
|
u32 type;
|
||||||
|
|
||||||
u32 type, move = cmd->move;
|
|
||||||
u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, move);
|
u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, move);
|
||||||
u32 abilityAtk = GetBattlerAbility(gBattlerAttacker);
|
u32 abilityAtk = GetBattlerAbility(gBattlerAttacker);
|
||||||
u32 abilityDef = GetBattlerAbility(gBattlerTarget);
|
u32 abilityDef = GetBattlerAbility(gBattlerTarget);
|
||||||
|
@ -1699,11 +1698,11 @@ static void Cmd_accuracycheck(void)
|
||||||
if (move == NO_ACC_CALC_CHECK_LOCK_ON)
|
if (move == NO_ACC_CALC_CHECK_LOCK_ON)
|
||||||
{
|
{
|
||||||
if (gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker)
|
if (gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker)
|
||||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
gBattlescriptCurrInstr = nextInstr;
|
||||||
else if (gStatuses3[gBattlerTarget] & (STATUS3_SEMI_INVULNERABLE))
|
else if (gStatuses3[gBattlerTarget] & (STATUS3_SEMI_INVULNERABLE))
|
||||||
gBattlescriptCurrInstr = cmd->failInstr;
|
gBattlescriptCurrInstr = failInstr;
|
||||||
else if (!JumpIfMoveAffectedByProtect(gCurrentMove))
|
else if (!JumpIfMoveAffectedByProtect(gCurrentMove))
|
||||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
gBattlescriptCurrInstr = nextInstr;
|
||||||
}
|
}
|
||||||
else if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_2ND_HIT
|
else if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_2ND_HIT
|
||||||
|| (gSpecialStatuses[gBattlerAttacker].multiHitOn
|
|| (gSpecialStatuses[gBattlerAttacker].multiHitOn
|
||||||
|
@ -1711,7 +1710,7 @@ static void Cmd_accuracycheck(void)
|
||||||
|| !(gMovesInfo[move].effect == EFFECT_TRIPLE_KICK || gMovesInfo[move].effect == EFFECT_POPULATION_BOMB))))
|
|| !(gMovesInfo[move].effect == EFFECT_TRIPLE_KICK || gMovesInfo[move].effect == EFFECT_POPULATION_BOMB))))
|
||||||
{
|
{
|
||||||
// No acc checks for second hit of Parental Bond or multi hit moves, except Triple Kick/Triple Axel/Population Bomb
|
// No acc checks for second hit of Parental Bond or multi hit moves, except Triple Kick/Triple Axel/Population Bomb
|
||||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
gBattlescriptCurrInstr = nextInstr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1739,6 +1738,18 @@ static void Cmd_accuracycheck(void)
|
||||||
if (holdEffectAtk == HOLD_EFFECT_BLUNDER_POLICY)
|
if (holdEffectAtk == HOLD_EFFECT_BLUNDER_POLICY)
|
||||||
gBattleStruct->blunderPolicy = TRUE; // Only activates from missing through acc/evasion checks
|
gBattleStruct->blunderPolicy = TRUE; // Only activates from missing through acc/evasion checks
|
||||||
|
|
||||||
|
if (gMovesInfo[gCurrentMove].effect == EFFECT_DRAGON_DARTS
|
||||||
|
&& !recalcDragonDarts // So we don't jump back and forth between targets
|
||||||
|
&& CanTargetPartner(gBattlerAttacker, gBattlerTarget)
|
||||||
|
&& !TargetFullyImmuneToCurrMove(gBattlerAttacker, BATTLE_PARTNER(gBattlerTarget)))
|
||||||
|
{
|
||||||
|
// Smart target to partner if miss
|
||||||
|
gBattlerTarget = BATTLE_PARTNER(gBattlerTarget);
|
||||||
|
gMoveResultFlags &= ~MOVE_RESULT_MISSED;
|
||||||
|
AccuracyCheck(TRUE, nextInstr, failInstr, move);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE &&
|
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE &&
|
||||||
(moveTarget == MOVE_TARGET_BOTH || moveTarget == MOVE_TARGET_FOES_AND_ALLY))
|
(moveTarget == MOVE_TARGET_BOTH || moveTarget == MOVE_TARGET_FOES_AND_ALLY))
|
||||||
gBattleCommunication[MISS_TYPE] = B_MSG_AVOIDED_ATK;
|
gBattleCommunication[MISS_TYPE] = B_MSG_AVOIDED_ATK;
|
||||||
|
@ -1752,6 +1763,16 @@ static void Cmd_accuracycheck(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void Cmd_accuracycheck(void)
|
||||||
|
{
|
||||||
|
CMD_ARGS(const u8 *failInstr, u16 move);
|
||||||
|
|
||||||
|
// The main body of this function has been moved to AccuracyCheck() to accomodate
|
||||||
|
// Dragon Darts' multiple accuracy checks on a single attack;
|
||||||
|
// each dart can try to re-target once after missing.
|
||||||
|
AccuracyCheck(FALSE, cmd->nextInstr, cmd->failInstr, cmd->move);
|
||||||
|
}
|
||||||
|
|
||||||
static void Cmd_attackstring(void)
|
static void Cmd_attackstring(void)
|
||||||
{
|
{
|
||||||
CMD_ARGS();
|
CMD_ARGS();
|
||||||
|
@ -5960,10 +5981,11 @@ static void Cmd_moveend(void)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (gCurrentMove == MOVE_DRAGON_DARTS)
|
if (gMovesInfo[gCurrentMove].effect == EFFECT_DRAGON_DARTS
|
||||||
{
|
&& gBattleStruct->moveTarget[gBattlerAttacker] == gBattlerTarget // Haven't already changed targets
|
||||||
// TODO
|
&& CanTargetPartner(gBattlerAttacker, gBattlerTarget)
|
||||||
}
|
&& !TargetFullyImmuneToCurrMove(gBattlerAttacker, BATTLE_PARTNER(gBattlerTarget)))
|
||||||
|
gBattlerTarget = BATTLE_PARTNER(gBattlerTarget); // Target the partner in doubles for second hit.
|
||||||
|
|
||||||
if (gBattleMons[gBattlerAttacker].hp
|
if (gBattleMons[gBattlerAttacker].hp
|
||||||
&& gBattleMons[gBattlerTarget].hp
|
&& gBattleMons[gBattlerTarget].hp
|
||||||
|
|
|
@ -3629,6 +3629,11 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
|
||||||
{
|
{
|
||||||
gMultiHitCounter = gMovesInfo[gCurrentMove].strikeCount;
|
gMultiHitCounter = gMovesInfo[gCurrentMove].strikeCount;
|
||||||
PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 3, 0)
|
PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 3, 0)
|
||||||
|
|
||||||
|
if (gMovesInfo[gCurrentMove].effect == EFFECT_DRAGON_DARTS
|
||||||
|
&& CanTargetPartner(gBattlerAttacker, gBattlerTarget)
|
||||||
|
&& TargetFullyImmuneToCurrMove(gBattlerAttacker, gBattlerTarget))
|
||||||
|
gBattlerTarget = BATTLE_PARTNER(gBattlerTarget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (B_BEAT_UP >= GEN_5 && gMovesInfo[gCurrentMove].effect == EFFECT_BEAT_UP)
|
else if (B_BEAT_UP >= GEN_5 && gMovesInfo[gCurrentMove].effect == EFFECT_BEAT_UP)
|
||||||
|
@ -4275,7 +4280,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||||
BattleScriptPushCursorAndCallback(BattleScript_OverworldWeatherStarts);
|
BattleScriptPushCursorAndCallback(BattleScript_OverworldWeatherStarts);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ABILITYEFFECT_ON_SWITCHIN: // 0
|
case ABILITYEFFECT_ON_SWITCHIN:
|
||||||
gBattleScripting.battler = battler;
|
gBattleScripting.battler = battler;
|
||||||
switch (gLastUsedAbility)
|
switch (gLastUsedAbility)
|
||||||
{
|
{
|
||||||
|
@ -4845,7 +4850,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ABILITYEFFECT_ENDTURN: // 1
|
case ABILITYEFFECT_ENDTURN:
|
||||||
if (IsBattlerAlive(battler))
|
if (IsBattlerAlive(battler))
|
||||||
{
|
{
|
||||||
gBattlerAttacker = battler;
|
gBattlerAttacker = battler;
|
||||||
|
@ -5036,18 +5041,20 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ABILITYEFFECT_MOVES_BLOCK: // 2
|
case ABILITYEFFECT_MOVES_BLOCK:
|
||||||
|
case ABILITYEFFECT_WOULD_BLOCK:
|
||||||
{
|
{
|
||||||
u16 moveTarget = GetBattlerMoveTargetType(battler, move);
|
u16 moveTarget = GetBattlerMoveTargetType(battler, move);
|
||||||
u16 battlerAbility = GetBattlerAbility(battler);
|
u16 battlerAbility = GetBattlerAbility(battler);
|
||||||
u16 targetAbility = GetBattlerAbility(gBattlerTarget);
|
u16 targetAbility = GetBattlerAbility(gBattlerTarget);
|
||||||
|
const u8 * battleScriptBlocksMove = NULL;
|
||||||
|
|
||||||
if ((gLastUsedAbility == ABILITY_SOUNDPROOF && gMovesInfo[move].soundMove && !(moveTarget & MOVE_TARGET_USER))
|
if ((gLastUsedAbility == ABILITY_SOUNDPROOF && gMovesInfo[move].soundMove && !(moveTarget & MOVE_TARGET_USER))
|
||||||
|| (gLastUsedAbility == ABILITY_BULLETPROOF && gMovesInfo[move].ballisticMove))
|
|| (gLastUsedAbility == ABILITY_BULLETPROOF && gMovesInfo[move].ballisticMove))
|
||||||
{
|
{
|
||||||
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)
|
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)
|
||||||
gHitMarker |= HITMARKER_NO_PPDEDUCT;
|
gHitMarker |= HITMARKER_NO_PPDEDUCT;
|
||||||
gBattlescriptCurrInstr = BattleScript_SoundproofProtected;
|
battleScriptBlocksMove = BattleScript_SoundproofProtected;
|
||||||
effect = 1;
|
effect = 1;
|
||||||
}
|
}
|
||||||
else if ((gLastUsedAbility == ABILITY_DAZZLING || gLastUsedAbility == ABILITY_QUEENLY_MAJESTY || gLastUsedAbility == ABILITY_ARMOR_TAIL || IsBattlerAlive(battler ^= BIT_FLANK))
|
else if ((gLastUsedAbility == ABILITY_DAZZLING || gLastUsedAbility == ABILITY_QUEENLY_MAJESTY || gLastUsedAbility == ABILITY_ARMOR_TAIL || IsBattlerAlive(battler ^= BIT_FLANK))
|
||||||
|
@ -5057,7 +5064,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||||
{
|
{
|
||||||
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)
|
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)
|
||||||
gHitMarker |= HITMARKER_NO_PPDEDUCT;
|
gHitMarker |= HITMARKER_NO_PPDEDUCT;
|
||||||
gBattlescriptCurrInstr = BattleScript_DazzlingProtected;
|
battleScriptBlocksMove = BattleScript_DazzlingProtected;
|
||||||
effect = 1;
|
effect = 1;
|
||||||
}
|
}
|
||||||
else if (GetChosenMovePriority(gBattlerAttacker) > 0
|
else if (GetChosenMovePriority(gBattlerAttacker) > 0
|
||||||
|
@ -5067,7 +5074,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||||
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(moveTarget & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)))
|
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(moveTarget & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)))
|
||||||
CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected
|
CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected
|
||||||
gBattleScripting.battler = gBattlerAbility = gBattlerTarget;
|
gBattleScripting.battler = gBattlerAbility = gBattlerTarget;
|
||||||
gBattlescriptCurrInstr = BattleScript_DarkTypePreventsPrankster;
|
battleScriptBlocksMove = BattleScript_DarkTypePreventsPrankster;
|
||||||
effect = 1;
|
effect = 1;
|
||||||
}
|
}
|
||||||
else if (GetBattlerAbility(gBattlerTarget) == ABILITY_GOOD_AS_GOLD
|
else if (GetBattlerAbility(gBattlerTarget) == ABILITY_GOOD_AS_GOLD
|
||||||
|
@ -5076,12 +5083,24 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||||
&& !(moveTarget & MOVE_TARGET_OPPONENTS_FIELD)
|
&& !(moveTarget & MOVE_TARGET_OPPONENTS_FIELD)
|
||||||
&& !(moveTarget & MOVE_TARGET_ALL_BATTLERS))
|
&& !(moveTarget & MOVE_TARGET_ALL_BATTLERS))
|
||||||
{
|
{
|
||||||
gBattlescriptCurrInstr = BattleScript_GoodAsGoldActivates;
|
battleScriptBlocksMove = BattleScript_GoodAsGoldActivates;
|
||||||
effect = 1;
|
effect = 1;
|
||||||
}
|
}
|
||||||
|
if (caseID == ABILITYEFFECT_WOULD_BLOCK)
|
||||||
|
{
|
||||||
|
if (effect && gLastUsedAbility != 0xFFFF)
|
||||||
|
RecordAbilityBattle(battler, gLastUsedAbility);
|
||||||
|
|
||||||
|
return effect;
|
||||||
|
}
|
||||||
|
else if (effect)
|
||||||
|
{
|
||||||
|
gBattlescriptCurrInstr = battleScriptBlocksMove;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ABILITYEFFECT_ABSORBING: // 3
|
case ABILITYEFFECT_ABSORBING:
|
||||||
|
case ABILITYEFFECT_WOULD_ABSORB:
|
||||||
if (move != MOVE_NONE)
|
if (move != MOVE_NONE)
|
||||||
{
|
{
|
||||||
u8 statId = 0;
|
u8 statId = 0;
|
||||||
|
@ -5114,31 +5133,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||||
effect = 2, statId = STAT_ATK;
|
effect = 2, statId = STAT_ATK;
|
||||||
break;
|
break;
|
||||||
case ABILITY_FLASH_FIRE:
|
case ABILITY_FLASH_FIRE:
|
||||||
if (moveType == TYPE_FIRE
|
if (moveType == TYPE_FIRE && (B_FLASH_FIRE_FROZEN >= GEN_5 || !(gBattleMons[battler].status1 & STATUS1_FREEZE)))
|
||||||
&& (B_FLASH_FIRE_FROZEN >= GEN_5 || !(gBattleMons[battler].status1 & STATUS1_FREEZE)))
|
effect = 3;
|
||||||
{
|
|
||||||
if (!(gBattleResources->flags->flags[battler] & RESOURCE_FLAG_FLASH_FIRE))
|
|
||||||
{
|
|
||||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_BOOST;
|
|
||||||
if (gProtectStructs[gBattlerAttacker].notFirstStrike)
|
|
||||||
gBattlescriptCurrInstr = BattleScript_FlashFireBoost;
|
|
||||||
else
|
|
||||||
gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss;
|
|
||||||
|
|
||||||
gBattleResources->flags->flags[battler] |= RESOURCE_FLAG_FLASH_FIRE;
|
|
||||||
effect = 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_NO_BOOST;
|
|
||||||
if (gProtectStructs[gBattlerAttacker].notFirstStrike)
|
|
||||||
gBattlescriptCurrInstr = BattleScript_FlashFireBoost;
|
|
||||||
else
|
|
||||||
gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss;
|
|
||||||
|
|
||||||
effect = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ABILITY_WELL_BAKED_BODY:
|
case ABILITY_WELL_BAKED_BODY:
|
||||||
if (moveType == TYPE_FIRE)
|
if (moveType == TYPE_FIRE)
|
||||||
|
@ -5153,8 +5149,14 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||||
effect = 1;
|
effect = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (caseID == ABILITYEFFECT_WOULD_ABSORB)
|
||||||
|
{
|
||||||
|
if (effect && gLastUsedAbility != 0xFFFF)
|
||||||
|
RecordAbilityBattle(battler, gLastUsedAbility);
|
||||||
|
|
||||||
if (effect == 1) // Drain Hp ability.
|
return effect;
|
||||||
|
}
|
||||||
|
else if (effect == 1) // Drain Hp ability.
|
||||||
{
|
{
|
||||||
if (BATTLER_MAX_HP(battler) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battler] & STATUS3_HEAL_BLOCK))
|
if (BATTLER_MAX_HP(battler) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battler] & STATUS3_HEAL_BLOCK))
|
||||||
{
|
{
|
||||||
|
@ -5197,6 +5199,26 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId);
|
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (effect == 3)
|
||||||
|
{
|
||||||
|
if (!(gBattleResources->flags->flags[battler] & RESOURCE_FLAG_FLASH_FIRE))
|
||||||
|
{
|
||||||
|
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_BOOST;
|
||||||
|
if (gProtectStructs[gBattlerAttacker].notFirstStrike)
|
||||||
|
gBattlescriptCurrInstr = BattleScript_FlashFireBoost;
|
||||||
|
else
|
||||||
|
gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss;
|
||||||
|
gBattleResources->flags->flags[battler] |= RESOURCE_FLAG_FLASH_FIRE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_NO_BOOST;
|
||||||
|
if (gProtectStructs[gBattlerAttacker].notFirstStrike)
|
||||||
|
gBattlescriptCurrInstr = BattleScript_FlashFireBoost;
|
||||||
|
else
|
||||||
|
gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (effect)
|
if (effect)
|
||||||
gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed.
|
gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed.
|
||||||
|
@ -5876,7 +5898,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ABILITYEFFECT_IMMUNITY: // 5
|
case ABILITYEFFECT_IMMUNITY:
|
||||||
for (battler = 0; battler < gBattlersCount; battler++)
|
for (battler = 0; battler < gBattlersCount; battler++)
|
||||||
{
|
{
|
||||||
switch (GetBattlerAbility(battler))
|
switch (GetBattlerAbility(battler))
|
||||||
|
@ -5989,7 +6011,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ABILITYEFFECT_ATK_SYNCHRONIZE: // 8
|
case ABILITYEFFECT_ATK_SYNCHRONIZE:
|
||||||
if (gLastUsedAbility == ABILITY_SYNCHRONIZE && (gHitMarker & HITMARKER_SYNCHRONISE_EFFECT))
|
if (gLastUsedAbility == ABILITY_SYNCHRONIZE && (gHitMarker & HITMARKER_SYNCHRONISE_EFFECT))
|
||||||
{
|
{
|
||||||
gHitMarker &= ~HITMARKER_SYNCHRONISE_EFFECT;
|
gHitMarker &= ~HITMARKER_SYNCHRONISE_EFFECT;
|
||||||
|
@ -11006,7 +11028,6 @@ void TryRestoreHeldItems(void)
|
||||||
// Check if the lost item should be restored
|
// Check if the lost item should be restored
|
||||||
if ((lostItem != ITEM_NONE || returnNPCItems) && ItemId_GetPocket(lostItem) != POCKET_BERRIES)
|
if ((lostItem != ITEM_NONE || returnNPCItems) && ItemId_GetPocket(lostItem) != POCKET_BERRIES)
|
||||||
SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &lostItem);
|
SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &lostItem);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11512,3 +11533,27 @@ void RemoveBattlerType(u32 battler, u8 type)
|
||||||
*(u8 *)(&gBattleMons[battler].type1 + i) = TYPE_MYSTERY;
|
*(u8 *)(&gBattleMons[battler].type1 + i) = TYPE_MYSTERY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool32 CanTargetPartner(u32 battlerAtk, u32 battlerDef)
|
||||||
|
{
|
||||||
|
return (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
|
||||||
|
&& IsBattlerAlive(BATTLE_PARTNER(battlerDef))
|
||||||
|
&& battlerDef != BATTLE_PARTNER(battlerAtk));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool32 DoesCurrentTargetHaveAbilityImmunity(void)
|
||||||
|
{
|
||||||
|
return (AbilityBattleEffects(ABILITYEFFECT_WOULD_BLOCK, gBattlerTarget, 0, 0, 0)
|
||||||
|
|| AbilityBattleEffects(ABILITYEFFECT_WOULD_ABSORB, gBattlerTarget, 0, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool32 TargetFullyImmuneToCurrMove(u32 BattlerAtk, u32 battlerDef)
|
||||||
|
{
|
||||||
|
u32 moveType = 0;
|
||||||
|
GET_MOVE_TYPE(gCurrentMove, moveType);
|
||||||
|
|
||||||
|
return ((CalcTypeEffectivenessMultiplier(gCurrentMove, moveType, BattlerAtk, battlerDef, GetBattlerAbility(battlerDef), FALSE) == UQ_4_12(0.0))
|
||||||
|
|| IsBattlerProtected(battlerDef, gCurrentMove)
|
||||||
|
|| IsSemiInvulnerable(battlerDef, gCurrentMove)
|
||||||
|
|| DoesCurrentTargetHaveAbilityImmunity());
|
||||||
|
}
|
||||||
|
|
|
@ -2243,4 +2243,10 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
|
||||||
.battleScript = BattleScript_EffectPhotonGeyser,
|
.battleScript = BattleScript_EffectPhotonGeyser,
|
||||||
.battleTvScore = 0, // TODO: Assign points
|
.battleTvScore = 0, // TODO: Assign points
|
||||||
},
|
},
|
||||||
|
|
||||||
|
[EFFECT_DRAGON_DARTS] =
|
||||||
|
{
|
||||||
|
.battleScript = BattleScript_EffectHit,
|
||||||
|
.battleTvScore = 0, // TODO: Assign points
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -16586,7 +16586,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
|
||||||
.description = COMPOUND_STRING(
|
.description = COMPOUND_STRING(
|
||||||
"The user attacks twice. Two\n"
|
"The user attacks twice. Two\n"
|
||||||
"targets are hit once each."),
|
"targets are hit once each."),
|
||||||
.effect = EFFECT_HIT, // TODO: EFFECT_DRAGON_DARTS
|
.effect = EFFECT_DRAGON_DARTS,
|
||||||
.power = 50,
|
.power = 50,
|
||||||
.type = TYPE_DRAGON,
|
.type = TYPE_DRAGON,
|
||||||
.accuracy = 100,
|
.accuracy = 100,
|
||||||
|
|
189
test/battle/move_effect/dragon_darts.c
Normal file
189
test/battle/move_effect/dragon_darts.c
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
#include "global.h"
|
||||||
|
#include "test/battle.h"
|
||||||
|
|
||||||
|
ASSUMPTIONS
|
||||||
|
{
|
||||||
|
ASSUME(gMovesInfo[MOVE_DRAGON_DARTS].effect == EFFECT_DRAGON_DARTS);
|
||||||
|
ASSUME(gSpeciesInfo[SPECIES_CLEFAIRY].types[0] == TYPE_FAIRY || gSpeciesInfo[SPECIES_CLEFAIRY].types[1] == TYPE_FAIRY);
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Dragon Darts strikes twice")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(player, MOVE_DRAGON_DARTS); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, player);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, player);
|
||||||
|
MESSAGE("Hit 2 time(s)!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Dragon Darts strikes each opponent once in a double battle")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentLeft); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentLeft);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
MESSAGE("Hit 2 time(s)!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Dragon Darts strikes the ally twice if the target protects")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponentLeft, MOVE_PROTECT); MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentLeft); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponentLeft);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
MESSAGE("Hit 2 time(s)!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Dragon Darts strikes the right ally twice if the target is a fairy type")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_CLEFAIRY);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentLeft); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
MESSAGE("Hit 2 time(s)!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Dragon Darts strikes the left ally twice if the target is a fairy type")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_CLEFAIRY);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentRight); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
MESSAGE("Hit 2 time(s)!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Dragon Darts strikes the ally twice if the target is in a semi-invulnerable turn")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gMovesInfo[MOVE_FLY].effect == EFFECT_SEMI_INVULNERABLE);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponentLeft, MOVE_FLY, target: playerLeft); MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentLeft); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLY, opponentLeft);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
MESSAGE("Hit 2 time(s)!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Dragon Darts is not effected by Wide Guard")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponentLeft, MOVE_WIDE_GUARD); MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentLeft); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_WIDE_GUARD, opponentLeft);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentLeft);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
MESSAGE("Hit 2 time(s)!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Dragon Darts strikes hit the ally if the target fainted")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(playerRight, MOVE_SONIC_BOOM, target: opponentLeft); MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentLeft); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_SONIC_BOOM, playerRight);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
MESSAGE("Hit 2 time(s)!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Dragon Darts strikes left ally twice if one strike misses")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_BRIGHT_POWDER); };
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentRight, hit: FALSE); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentLeft);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentLeft);
|
||||||
|
MESSAGE("Hit 2 time(s)!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Dragon Darts strikes right ally twice if one strike misses")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_BRIGHT_POWDER); };
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentLeft, hit: FALSE); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
MESSAGE("Hit 2 time(s)!");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue