diff options
Diffstat (limited to 'engine/battle/move_effects')
58 files changed, 3464 insertions, 0 deletions
diff --git a/engine/battle/move_effects/attract.asm b/engine/battle/move_effects/attract.asm new file mode 100755 index 000000000..026176694 --- /dev/null +++ b/engine/battle/move_effects/attract.asm @@ -0,0 +1,79 @@ +BattleCommand_Attract: ; 377ce +; attract + ld a, [wAttackMissed] + and a + jr nz, .failed + call CheckOppositeGender + jr c, .failed + call CheckHiddenOpponent + jr nz, .failed + ld a, BATTLE_VARS_SUBSTATUS1_OPP + call GetBattleVarAddr + bit SUBSTATUS_IN_LOVE, [hl] + jr nz, .failed + + set SUBSTATUS_IN_LOVE, [hl] + call AnimateCurrentMove + +; 'fell in love!' + ld hl, FellInLoveText + jp StdBattleTextBox + +.failed + jp FailMove +; 377f5 + + +CheckOppositeGender: ; 377f5 + ld a, MON_SPECIES + call BattlePartyAttr + ld a, [hl] + ld [wCurPartySpecies], a + + ld a, [wCurBattleMon] + ld [wCurPartyMon], a + xor a + ld [wMonType], a + + farcall GetGender + jr c, .genderless_samegender + + ld b, 1 + jr nz, .got_gender + dec b + +.got_gender + push bc + ld a, [wTempEnemyMonSpecies] + ld [wCurPartySpecies], a + ld hl, wEnemyMonDVs + ld a, [wEnemySubStatus5] + bit SUBSTATUS_TRANSFORMED, a + jr z, .not_transformed + ld hl, wEnemyBackupDVs +.not_transformed + ld a, [hli] + ld [wTempMonDVs], a + ld a, [hl] + ld [wTempMonDVs + 1], a + ld a, 3 + ld [wMonType], a + farcall GetGender + pop bc + jr c, .genderless_samegender + + ld a, 1 + jr nz, .got_enemy_gender + dec a + +.got_enemy_gender + xor b + jr z, .genderless_samegender + + and a + ret + +.genderless_samegender + scf + ret +; 3784b diff --git a/engine/battle/move_effects/baton_pass.asm b/engine/battle/move_effects/baton_pass.asm new file mode 100644 index 000000000..369565877 --- /dev/null +++ b/engine/battle/move_effects/baton_pass.asm @@ -0,0 +1,241 @@ +BattleCommand_BatonPass: ; 379c9 +; batonpass + + ld a, [hBattleTurn] + and a + jp nz, .Enemy + + +; Need something to switch to + call CheckAnyOtherAlivePartyMons + jp z, FailedBatonPass + + call UpdateBattleMonInParty + call AnimateCurrentMove + + ld c, 50 + call DelayFrames + +; Transition into switchmon menu + call LoadStandardMenuHeader + farcall SetUpBattlePartyMenu_NoLoop + + farcall ForcePickSwitchMonInBattle + +; Return to battle scene + call ClearPalettes + farcall _LoadBattleFontsHPBar + call CloseWindow + call ClearSprites + hlcoord 1, 0 + lb bc, 4, 10 + call ClearBox + ld b, SCGB_BATTLE_COLORS + call GetSGBLayout + call SetPalettes + call BatonPass_LinkPlayerSwitch + +; Mobile link battles handle entrances differently + farcall CheckMobileBattleError + jp c, EndMoveEffect + + ld hl, PassedBattleMonEntrance + call CallBattleCore + + call ResetBatonPassStatus + ret + + +.Enemy: + +; Wildmons don't have anything to switch to + ld a, [wBattleMode] + dec a ; WILDMON + jp z, FailedBatonPass + + call CheckAnyOtherAliveEnemyMons + jp z, FailedBatonPass + + call UpdateEnemyMonInParty + call AnimateCurrentMove + call BatonPass_LinkEnemySwitch + +; Mobile link battles handle entrances differently + farcall CheckMobileBattleError + jp c, EndMoveEffect + +; Passed enemy PartyMon entrance + xor a + ld [wEnemySwitchMonIndex], a + ld hl, EnemySwitch_SetMode + call CallBattleCore + ld hl, ResetBattleParticipants + call CallBattleCore + ld a, 1 + ld [wTypeMatchup], a + ld hl, ApplyStatLevelMultiplierOnAllStats + call CallBattleCore + + ld hl, SpikesDamage + call CallBattleCore + + jr ResetBatonPassStatus + +; 37a67 + + +BatonPass_LinkPlayerSwitch: ; 37a67 + ld a, [wLinkMode] + and a + ret z + + ld a, 1 + ld [wBattlePlayerAction], a + + call LoadStandardMenuHeader + ld hl, LinkBattleSendReceiveAction + call CallBattleCore + call CloseWindow + + xor a + ld [wBattlePlayerAction], a + ret + +; 37a82 + + +BatonPass_LinkEnemySwitch: ; 37a82 + ld a, [wLinkMode] + and a + ret z + + call LoadStandardMenuHeader + ld hl, LinkBattleSendReceiveAction + call CallBattleCore + + ld a, [wOTPartyCount] + add BATTLEACTION_SWITCH1 + ld b, a + ld a, [wBattleAction] + cp BATTLEACTION_SWITCH1 + jr c, .baton_pass + cp b + jr c, .switch + +.baton_pass + ld a, [wCurOTMon] + add BATTLEACTION_SWITCH1 + ld [wBattleAction], a +.switch + jp CloseWindow + +; 37aab + + +FailedBatonPass: ; 37aab + call AnimateFailedMove + jp PrintButItFailed + +; 37ab1 + + +ResetBatonPassStatus: ; 37ab1 +; Reset status changes that aren't passed by Baton Pass. + + ; Nightmare isn't passed. + ld a, BATTLE_VARS_STATUS + call GetBattleVar + and SLP + jr nz, .ok + + ld a, BATTLE_VARS_SUBSTATUS1 + call GetBattleVarAddr + res SUBSTATUS_NIGHTMARE, [hl] +.ok + + ; Disable isn't passed. + call ResetActorDisable + + ; Attraction isn't passed. + ld hl, wPlayerSubStatus1 + res SUBSTATUS_IN_LOVE, [hl] + ld hl, wEnemySubStatus1 + res SUBSTATUS_IN_LOVE, [hl] + ld hl, wPlayerSubStatus5 + + ld a, BATTLE_VARS_SUBSTATUS5 + call GetBattleVarAddr + res SUBSTATUS_TRANSFORMED, [hl] + res SUBSTATUS_ENCORED, [hl] + + ; New mon hasn't used a move yet. + ld a, BATTLE_VARS_LAST_MOVE + call GetBattleVarAddr + ld [hl], 0 + + xor a + ld [wPlayerWrapCount], a + ld [wEnemyWrapCount], a + ret + +; 37ae9 + + +CheckAnyOtherAlivePartyMons: ; 37ae9 + ld hl, wPartyMon1HP + ld a, [wPartyCount] + ld d, a + ld a, [wCurBattleMon] + ld e, a + jr CheckAnyOtherAliveMons + +; 37af6 + + +CheckAnyOtherAliveEnemyMons: ; 37af6 + ld hl, wOTPartyMon1HP + ld a, [wOTPartyCount] + ld d, a + ld a, [wCurOTMon] + ld e, a + + ; fallthrough +; 37b01 + +CheckAnyOtherAliveMons: ; 37b01 +; Check for nonzero HP starting from partymon +; HP at hl for d partymons, besides current mon e. + +; Return nz if any are alive. + + xor a + ld b, a + ld c, a +.loop + ld a, c + cp d + jr z, .done + cp e + jr z, .next + + ld a, [hli] + or b + ld b, a + ld a, [hld] + or b + ld b, a + +.next + push bc + ld bc, PARTYMON_STRUCT_LENGTH + add hl, bc + pop bc + inc c + jr .loop + +.done + ld a, b + and a + ret + +; 37b1d diff --git a/engine/battle/move_effects/beat_up.asm b/engine/battle/move_effects/beat_up.asm new file mode 100644 index 000000000..18e350504 --- /dev/null +++ b/engine/battle/move_effects/beat_up.asm @@ -0,0 +1,219 @@ +BattleCommand_BeatUp: ; 35461 +; beatup + + call ResetDamage + ld a, [hBattleTurn] + and a + jp nz, .enemy_beats_up + ld a, [wPlayerSubStatus3] + bit SUBSTATUS_IN_LOOP, a + jr nz, .next_mon + ld c, 20 + call DelayFrames + xor a + ld [wPlayerRolloutCount], a + ld [wd002], a + ld [wBeatUpHitAtLeastOnce], a + jr .got_mon + +.next_mon + ld a, [wPlayerRolloutCount] + ld b, a + ld a, [wPartyCount] + sub b + ld [wd002], a + +.got_mon + ld a, [wd002] + ld hl, wPartyMonNicknames + call GetNick + ld a, MON_HP + call GetBeatupMonLocation + ld a, [hli] + or [hl] + jp z, .beatup_fail ; fainted + ld a, [wd002] + ld c, a + ld a, [wCurBattleMon] + ; BUG: this can desynchronize link battles + ; Change "cp [hl]" to "cp c" to fix + cp [hl] + ld hl, wBattleMonStatus + jr z, .active_mon + ld a, MON_STATUS + call GetBeatupMonLocation +.active_mon + ld a, [hl] + and a + jp nz, .beatup_fail + + ld a, $1 + ld [wBeatUpHitAtLeastOnce], a + ld hl, BeatUpAttackText + call StdBattleTextBox + ld a, [wEnemyMonSpecies] + ld [wCurSpecies], a + call GetBaseData + ld a, [wBaseDefense] + ld c, a + push bc + ld a, MON_SPECIES + call GetBeatupMonLocation + ld a, [hl] + ld [wCurSpecies], a + call GetBaseData + ld a, [wBaseAttack] + pop bc + ld b, a + push bc + ld a, MON_LEVEL + call GetBeatupMonLocation + ld a, [hl] + ld e, a + pop bc + ld a, [wPlayerMoveStructPower] + ld d, a + ret + +.enemy_beats_up + ld a, [wEnemySubStatus3] + bit SUBSTATUS_IN_LOOP, a + jr nz, .not_first_enemy_beatup + + xor a + ld [wEnemyRolloutCount], a + ld [wd002], a + ld [wBeatUpHitAtLeastOnce], a + jr .enemy_continue + +.not_first_enemy_beatup + ld a, [wEnemyRolloutCount] + ld b, a + ld a, [wOTPartyCount] + sub b + ld [wd002], a +.enemy_continue + ld a, [wBattleMode] + dec a + jr z, .wild + + ld a, [wLinkMode] + and a + jr nz, .link_or_tower + + ld a, [wInBattleTowerBattle] + and a + jr nz, .link_or_tower + + ld a, [wd002] + ld c, a + ld b, 0 + ld hl, wOTPartySpecies + add hl, bc + ld a, [hl] + ld [wNamedObjectIndexBuffer], a + call GetPokemonName + jr .got_enemy_nick + +.link_or_tower + ld a, [wd002] + ld hl, wOTPartyMonNicknames + ld bc, NAME_LENGTH + call AddNTimes + ld de, wStringBuffer1 + call CopyBytes +.got_enemy_nick + ld a, MON_HP + call GetBeatupMonLocation + ld a, [hli] + or [hl] + jp z, .beatup_fail + ld a, [wd002] + ld b, a + ld a, [wCurOTMon] + cp b + ld hl, wEnemyMonStatus + jr z, .active_enemy + + ld a, MON_STATUS + call GetBeatupMonLocation +.active_enemy + ld a, [hl] + and a + jr nz, .beatup_fail + + ld a, $1 + ld [wBeatUpHitAtLeastOnce], a + jr .finish_beatup + +.wild + ld a, [wEnemyMonSpecies] + ld [wNamedObjectIndexBuffer], a + call GetPokemonName + ld hl, BeatUpAttackText + call StdBattleTextBox + jp EnemyAttackDamage + +.finish_beatup + ld hl, BeatUpAttackText + call StdBattleTextBox + ld a, [wBattleMonSpecies] + ld [wCurSpecies], a + call GetBaseData + ld a, [wBaseDefense] + ld c, a + push bc + ld a, MON_SPECIES + call GetBeatupMonLocation + ld a, [hl] + ld [wCurSpecies], a + call GetBaseData + ld a, [wBaseAttack] + pop bc + ld b, a + push bc + ld a, MON_LEVEL + call GetBeatupMonLocation + ld a, [hl] + ld e, a + pop bc + ld a, [wEnemyMoveStructPower] + ld d, a + ret + +; 355b0 + + +.beatup_fail ; 355b0 + ld b, buildopponentrage_command + jp SkipToBattleCommand + +; 355b5 + + +BattleCommanda8: ; 355b5 + ld a, [wBeatUpHitAtLeastOnce] + and a + ret nz + + jp PrintButItFailed + +; 355bd + + +GetBeatupMonLocation: ; 355bd + push bc + ld c, a + ld b, 0 + ld a, [hBattleTurn] + and a + ld hl, wPartyMon1Species + jr z, .got_species + ld hl, wOTPartyMon1Species + +.got_species + ld a, [wd002] + add hl, bc + call GetPartyLocation + pop bc + ret diff --git a/engine/battle/move_effects/belly_drum.asm b/engine/battle/move_effects/belly_drum.asm new file mode 100644 index 000000000..bd300c9cd --- /dev/null +++ b/engine/battle/move_effects/belly_drum.asm @@ -0,0 +1,36 @@ +BattleCommand_BellyDrum: ; 37c1a +; bellydrum +; This command is buggy because it raises the user's attack +; before checking that it has enough HP to use the move. +; Swap the order of these two blocks to fix. + call BattleCommand_AttackUp2 + ld a, [wAttackMissed] + and a + jr nz, .failed + + callfar GetHalfMaxHP + callfar CheckUserHasEnoughHP + jr nc, .failed + + push bc + call AnimateCurrentMove + pop bc + callfar SubtractHPFromUser + call UpdateUserInParty + ld a, 5 + +.max_attack_loop + push af + call BattleCommand_AttackUp2 + pop af + dec a + jr nz, .max_attack_loop + + ld hl, BellyDrumText + jp StdBattleTextBox + +.failed + call AnimateFailedMove + jp PrintButItFailed + +; 37c55 diff --git a/engine/battle/move_effects/bide.asm b/engine/battle/move_effects/bide.asm new file mode 100644 index 000000000..d9958ca53 --- /dev/null +++ b/engine/battle/move_effects/bide.asm @@ -0,0 +1,105 @@ +BattleCommand_StoreEnergy: ; 36671 +; storeenergy + + ld a, BATTLE_VARS_SUBSTATUS3 + call GetBattleVar + bit SUBSTATUS_BIDE, a + ret z + + ld hl, wPlayerRolloutCount + ld a, [hBattleTurn] + and a + jr z, .check_still_storing_energy + ld hl, wEnemyRolloutCount +.check_still_storing_energy + dec [hl] + jr nz, .still_storing + + ld a, BATTLE_VARS_SUBSTATUS3 + call GetBattleVarAddr + res SUBSTATUS_BIDE, [hl] + + ld hl, UnleashedEnergyText + call StdBattleTextBox + + ld a, BATTLE_VARS_MOVE_POWER + call GetBattleVarAddr + ld a, 1 + ld [hl], a + ld hl, wPlayerDamageTaken + 1 + ld de, wPlayerCharging ; player + ld a, [hBattleTurn] + and a + jr z, .player + ld hl, wEnemyDamageTaken + 1 + ld de, wEnemyCharging ; enemy +.player + ld a, [hld] + add a + ld b, a + ld [wCurDamage + 1], a + ld a, [hl] + rl a + ld [wCurDamage], a + jr nc, .not_maxed + ld a, $ff + ld [wCurDamage], a + ld [wCurDamage + 1], a +.not_maxed + or b + jr nz, .built_up_something + ld a, 1 + ld [wAttackMissed], a +.built_up_something + xor a + ld [hli], a + ld [hl], a + ld [de], a + + ld a, BATTLE_VARS_MOVE_ANIM + call GetBattleVarAddr + ld a, BIDE + ld [hl], a + + ld b, unleashenergy_command + jp SkipToBattleCommand + +.still_storing + ld hl, StoringEnergyText + call StdBattleTextBox + jp EndMoveEffect + +; 366e5 + + +BattleCommand_UnleashEnergy: ; 366e5 +; unleashenergy + + ld de, wPlayerDamageTaken + ld bc, wPlayerRolloutCount + ld a, [hBattleTurn] + and a + jr z, .got_damage + ld de, wEnemyDamageTaken + ld bc, wEnemyRolloutCount +.got_damage + ld a, BATTLE_VARS_SUBSTATUS3 + call GetBattleVarAddr + set SUBSTATUS_BIDE, [hl] + xor a + ld [de], a + inc de + ld [de], a + ld [wPlayerMoveStructEffect], a + ld [wEnemyMoveStructEffect], a + call BattleRandom + and 1 + inc a + inc a + ld [bc], a + ld a, 1 + ld [wKickCounter], a + call AnimateCurrentMove + jp EndMoveEffect + +; 3671a diff --git a/engine/battle/move_effects/conversion.asm b/engine/battle/move_effects/conversion.asm new file mode 100644 index 000000000..d66d23a5e --- /dev/null +++ b/engine/battle/move_effects/conversion.asm @@ -0,0 +1,98 @@ +BattleCommand_Conversion: ; 3707f +; conversion + + ld hl, wBattleMonMoves + ld de, wBattleMonType1 + ld a, [hBattleTurn] + and a + jr z, .got_moves + ld hl, wEnemyMonMoves + ld de, wEnemyMonType1 +.got_moves + push de + ld c, 0 + ld de, wStringBuffer1 +.loop + push hl + ld b, 0 + add hl, bc + ld a, [hl] + pop hl + and a + jr z, .okay + push hl + push bc + dec a + ld hl, Moves + MOVE_TYPE + call GetMoveAttr + ld [de], a + inc de + pop bc + pop hl + inc c + ld a, c + cp NUM_MOVES + jr c, .loop +.okay + ld a, $ff + ld [de], a + inc de + ld [de], a + inc de + ld [de], a + pop de + ld hl, wStringBuffer1 +.loop2 + ld a, [hl] + cp -1 + jr z, .fail + cp CURSE_T + jr z, .next + ld a, [de] + cp [hl] + jr z, .next + inc de + ld a, [de] + dec de + cp [hl] + jr nz, .done +.next + inc hl + jr .loop2 + +.fail + call AnimateFailedMove + jp PrintButItFailed + +.done +.loop3 + call BattleRandom + maskbits NUM_MOVES + ld c, a + ld b, 0 + ld hl, wStringBuffer1 + add hl, bc + ld a, [hl] + cp -1 + jr z, .loop3 + cp CURSE_T + jr z, .loop3 + ld a, [de] + cp [hl] + jr z, .loop3 + inc de + ld a, [de] + dec de + cp [hl] + jr z, .loop3 + ld a, [hl] + ld [de], a + inc de + ld [de], a + ld [wNamedObjectIndexBuffer], a + farcall GetTypeName + call AnimateCurrentMove + ld hl, TransformedTypeText + jp StdBattleTextBox + +; 3710e diff --git a/engine/battle/move_effects/conversion2.asm b/engine/battle/move_effects/conversion2.asm new file mode 100644 index 000000000..074ca93ba --- /dev/null +++ b/engine/battle/move_effects/conversion2.asm @@ -0,0 +1,66 @@ +BattleCommand_Conversion2: ; 359e6 +; conversion2 + + ld a, [wAttackMissed] + and a + jr nz, .failed + ld hl, wBattleMonType1 + ld a, [hBattleTurn] + and a + jr z, .got_type + ld hl, wEnemyMonType1 +.got_type + ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP + call GetBattleVar + and a + jr z, .failed + push hl + dec a + ld hl, Moves + MOVE_TYPE + call GetMoveAttr + ld d, a + pop hl + cp CURSE_T + jr z, .failed + call AnimateCurrentMove + call BattleCommand_SwitchTurn + +.loop + call BattleRandom + maskbits NUM_TYPES + cp UNUSED_TYPES + jr c, .okay + cp UNUSED_TYPES_END + jr c, .loop + cp TYPES_END + jr nc, .loop +.okay + ld [hli], a + ld [hld], a + push hl + ld a, BATTLE_VARS_MOVE_TYPE + call GetBattleVarAddr + push af + push hl + ld a, d + ld [hl], a + call BattleCheckTypeMatchup + pop hl + pop af + ld [hl], a + pop hl + ld a, [wTypeMatchup] + cp 10 + jr nc, .loop + call BattleCommand_SwitchTurn + + ld a, [hl] + ld [wNamedObjectIndexBuffer], a + predef GetTypeName + ld hl, TransformedTypeText + jp StdBattleTextBox + +.failed + jp FailMove + +; 35a53 diff --git a/engine/battle/move_effects/counter.asm b/engine/battle/move_effects/counter.asm new file mode 100644 index 000000000..b811b293c --- /dev/null +++ b/engine/battle/move_effects/counter.asm @@ -0,0 +1,60 @@ +BattleCommand_Counter: ; 35813 +; counter + + ld a, 1 + ld [wAttackMissed], a + ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP + call GetBattleVar + and a + ret z + + ld b, a + callfar GetMoveEffect + ld a, b + cp EFFECT_COUNTER + ret z + + call BattleCommand_ResetTypeMatchup + ld a, [wTypeMatchup] + and a + ret z + + call CheckOpponentWentFirst + ret z + + ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP + call GetBattleVar + dec a + ld de, wStringBuffer1 + call GetMoveData + + ld a, [wStringBuffer1 + MOVE_POWER] + and a + ret z + + ld a, [wStringBuffer1 + MOVE_TYPE] + cp SPECIAL + ret nc + + ld hl, wCurDamage + ld a, [hli] + or [hl] + ret z + + ld a, [hl] + add a + ld [hld], a + ld a, [hl] + adc a + ld [hl], a + jr nc, .capped + ld a, $ff + ld [hli], a + ld [hl], a +.capped + + xor a + ld [wAttackMissed], a + ret + +; 35864 diff --git a/engine/battle/move_effects/curse.asm b/engine/battle/move_effects/curse.asm new file mode 100644 index 000000000..b11b9f3fb --- /dev/null +++ b/engine/battle/move_effects/curse.asm @@ -0,0 +1,97 @@ +BattleCommand_Curse: ; 37588 +; curse + + ld de, wBattleMonType1 + ld bc, wPlayerStatLevels + ld a, [hBattleTurn] + and a + jr z, .go + ld de, wEnemyMonType1 + ld bc, wEnemyStatLevels + +.go + +; Curse is different for Ghost-types. + + ld a, [de] + cp GHOST + jr z, .ghost + inc de + ld a, [de] + cp GHOST + jr z, .ghost + + +; If no stats can be increased, don't. + +; Attack + ld a, [bc] + cp MAX_STAT_LEVEL + jr c, .raise + +; Defense + inc bc + ld a, [bc] + cp MAX_STAT_LEVEL + jr nc, .cantraise + +.raise + +; Raise Attack and Defense, and lower Speed. + + ld a, $1 + ld [wKickCounter], a + call AnimateCurrentMove + ld a, SPEED + call LowerStat + call BattleCommand_SwitchTurn + call BattleCommand_StatDownMessage + call ResetMiss + call BattleCommand_SwitchTurn + call BattleCommand_AttackUp + call BattleCommand_StatUpMessage + call ResetMiss + call BattleCommand_DefenseUp + jp BattleCommand_StatUpMessage + + +.ghost + +; Cut HP in half and put a curse on the opponent. + + call CheckHiddenOpponent + jr nz, .failed + + call CheckSubstituteOpp + jr nz, .failed + + ld a, BATTLE_VARS_SUBSTATUS1_OPP + call GetBattleVarAddr + bit SUBSTATUS_CURSE, [hl] + jr nz, .failed + + set SUBSTATUS_CURSE, [hl] + call AnimateCurrentMove + ld hl, GetHalfMaxHP + call CallBattleCore + ld hl, SubtractHPFromUser + call CallBattleCore + call UpdateUserInParty + ld hl, PutACurseText + jp StdBattleTextBox + +.failed + call AnimateFailedMove + jp PrintButItFailed + + +.cantraise + +; Can't raise either stat. + + ld b, ABILITY + 1 + call GetStatName + call AnimateFailedMove + ld hl, WontRiseAnymoreText + jp StdBattleTextBox +; 37618 diff --git a/engine/battle/move_effects/destiny_bond.asm b/engine/battle/move_effects/destiny_bond.asm new file mode 100644 index 000000000..2dc125ddf --- /dev/null +++ b/engine/battle/move_effects/destiny_bond.asm @@ -0,0 +1,11 @@ +BattleCommand_DestinyBond: ; 35bff +; destinybond + + ld a, BATTLE_VARS_SUBSTATUS5 + call GetBattleVarAddr + set SUBSTATUS_DESTINY_BOND, [hl] + call AnimateCurrentMove + ld hl, DestinyBondEffectText + jp StdBattleTextBox + +; 35c0f diff --git a/engine/battle/move_effects/disable.asm b/engine/battle/move_effects/disable.asm new file mode 100644 index 000000000..5df785d24 --- /dev/null +++ b/engine/battle/move_effects/disable.asm @@ -0,0 +1,74 @@ +BattleCommand_Disable: ; 36fed +; disable + + ld a, [wAttackMissed] + and a + jr nz, .failed + + ld de, wEnemyDisableCount + ld hl, wEnemyMonMoves + ld a, [hBattleTurn] + and a + jr z, .got_moves + ld de, wPlayerDisableCount + ld hl, wBattleMonMoves +.got_moves + + ld a, [de] + and a + jr nz, .failed + + ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP + call GetBattleVar + and a + jr z, .failed + cp STRUGGLE + jr z, .failed + + ld b, a + ld c, $ff +.loop + inc c + ld a, [hli] + cp b + jr nz, .loop + + ld a, [hBattleTurn] + and a + ld hl, wEnemyMonPP + jr z, .got_pp + ld hl, wBattleMonPP +.got_pp + ld b, 0 + add hl, bc + ld a, [hl] + and a + jr z, .failed +.loop2 + call BattleRandom + and 7 + jr z, .loop2 + inc a + inc c + swap c + add c + ld [de], a + call AnimateCurrentMove + ld hl, wDisabledMove + ld a, [hBattleTurn] + and a + jr nz, .got_disabled_move_pointer + inc hl +.got_disabled_move_pointer + ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP + call GetBattleVar + ld [hl], a + ld [wNamedObjectIndexBuffer], a + call GetMoveName + ld hl, WasDisabledText + jp StdBattleTextBox + +.failed + jp FailMove + +; 3705c diff --git a/engine/battle/move_effects/encore.asm b/engine/battle/move_effects/encore.asm new file mode 100644 index 000000000..e6607fb11 --- /dev/null +++ b/engine/battle/move_effects/encore.asm @@ -0,0 +1,122 @@ +BattleCommand_Encore: ; 35864 +; encore + + ld hl, wEnemyMonMoves + ld de, wEnemyEncoreCount + ld a, [hBattleTurn] + and a + jr z, .ok + ld hl, wBattleMonMoves + ld de, wPlayerEncoreCount +.ok + ld a, BATTLE_VARS_LAST_MOVE_OPP + call GetBattleVar + and a + jp z, .failed + cp STRUGGLE + jp z, .failed + cp ENCORE + jp z, .failed + cp MIRROR_MOVE + jp z, .failed + ld b, a + +.got_move + ld a, [hli] + cp b + jr nz, .got_move + + ld bc, wBattleMonPP - wBattleMonMoves - 1 + add hl, bc + ld a, [hl] + and PP_MASK + jp z, .failed + ld a, [wAttackMissed] + and a + jp nz, .failed + ld a, BATTLE_VARS_SUBSTATUS5_OPP + call GetBattleVarAddr + bit SUBSTATUS_ENCORED, [hl] + jp nz, .failed + set SUBSTATUS_ENCORED, [hl] + call BattleRandom + and $3 + inc a + inc a + inc a + ld [de], a + call CheckOpponentWentFirst + jr nz, .finish_move + ld a, [hBattleTurn] + and a + jr z, .force_last_enemy_move + + push hl + ld a, [wLastPlayerMove] + ld b, a + ld c, 0 + ld hl, wBattleMonMoves +.find_player_move + ld a, [hli] + cp b + jr z, .got_player_move + inc c + ld a, c + cp NUM_MOVES + jr c, .find_player_move + pop hl + res SUBSTATUS_ENCORED, [hl] + xor a + ld [de], a + jr .failed + +.got_player_move + pop hl + ld a, c + ld [wCurMoveNum], a + ld a, b + ld [wCurPlayerMove], a + dec a + ld de, wPlayerMoveStruct + call GetMoveData + jr .finish_move + +.force_last_enemy_move + push hl + ld a, [wLastEnemyMove] + ld b, a + ld c, 0 + ld hl, wEnemyMonMoves +.find_enemy_move + ld a, [hli] + cp b + jr z, .got_enemy_move + inc c + ld a, c + cp NUM_MOVES + jr c, .find_enemy_move + pop hl + res SUBSTATUS_ENCORED, [hl] + xor a + ld [de], a + jr .failed + +.got_enemy_move + pop hl + ld a, c + ld [wCurEnemyMoveNum], a + ld a, b + ld [wCurEnemyMove], a + dec a + ld de, wEnemyMoveStruct + call GetMoveData + +.finish_move + call AnimateCurrentMove + ld hl, GotAnEncoreText + jp StdBattleTextBox + +.failed + jp PrintDidntAffect2 + +; 35926 diff --git a/engine/battle/move_effects/endure.asm b/engine/battle/move_effects/endure.asm new file mode 100644 index 000000000..ed4329ff5 --- /dev/null +++ b/engine/battle/move_effects/endure.asm @@ -0,0 +1,17 @@ +BattleCommand_Endure: ; 3766f +; endure + +; Endure shares code with Protect. See protect.asm. + + call ProtectChance + ret c + + ld a, BATTLE_VARS_SUBSTATUS1 + call GetBattleVarAddr + set SUBSTATUS_ENDURE, [hl] + + call AnimateCurrentMove + + ld hl, BracedItselfText + jp StdBattleTextBox +; 37683 diff --git a/engine/battle/move_effects/false_swipe.asm b/engine/battle/move_effects/false_swipe.asm new file mode 100644 index 000000000..e93b627ec --- /dev/null +++ b/engine/battle/move_effects/false_swipe.asm @@ -0,0 +1,44 @@ +BattleCommand_FalseSwipe: ; 35c94 +; falseswipe + + ld hl, wEnemyMonHP + ld a, [hBattleTurn] + and a + jr z, .got_hp + ld hl, wBattleMonHP +.got_hp + ld de, wCurDamage + ld c, 2 + push hl + push de + call StringCmp + pop de + pop hl + jr c, .done + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + dec a + ld [de], a + inc a + jr nz, .okay + dec de + ld a, [de] + dec a + ld [de], a +.okay + ld a, [wCriticalHit] + cp 2 + jr nz, .carry + xor a + ld [wCriticalHit], a +.carry + scf + ret + +.done + and a + ret + +; 35cc9 diff --git a/engine/battle/move_effects/focus_energy.asm b/engine/battle/move_effects/focus_energy.asm new file mode 100644 index 000000000..2a3726c53 --- /dev/null +++ b/engine/battle/move_effects/focus_energy.asm @@ -0,0 +1,17 @@ +BattleCommand_FocusEnergy: ; 36c98 +; focusenergy + + ld a, BATTLE_VARS_SUBSTATUS4 + call GetBattleVarAddr + bit SUBSTATUS_FOCUS_ENERGY, [hl] + jr nz, .already_pumped + set SUBSTATUS_FOCUS_ENERGY, [hl] + call AnimateCurrentMove + ld hl, GettingPumpedText + jp StdBattleTextBox + +.already_pumped + call AnimateFailedMove + jp PrintButItFailed + +; 36cb2 diff --git a/engine/battle/move_effects/foresight.asm b/engine/battle/move_effects/foresight.asm new file mode 100644 index 000000000..8c51bb220 --- /dev/null +++ b/engine/battle/move_effects/foresight.asm @@ -0,0 +1,23 @@ +BattleCommand_Foresight: ; 376a0 +; foresight + + ld a, [wAttackMissed] + and a + jr nz, .failed + + call CheckHiddenOpponent + jr nz, .failed + + ld a, BATTLE_VARS_SUBSTATUS1_OPP + call GetBattleVarAddr + bit SUBSTATUS_IDENTIFIED, [hl] + jr nz, .failed + + set SUBSTATUS_IDENTIFIED, [hl] + call AnimateCurrentMove + ld hl, IdentifiedText + jp StdBattleTextBox + +.failed + jp FailMove +; 376c2 diff --git a/engine/battle/move_effects/frustration.asm b/engine/battle/move_effects/frustration.asm new file mode 100644 index 000000000..3f8456ced --- /dev/null +++ b/engine/battle/move_effects/frustration.asm @@ -0,0 +1,29 @@ +BattleCommand_FrustrationPower: ; 3790e +; frustrationpower + + push bc + ld hl, wBattleMonHappiness + ld a, [hBattleTurn] + and a + jr z, .got_happiness + ld hl, wEnemyMonHappiness +.got_happiness + ld a, $ff + sub [hl] + ld [hMultiplicand + 2], a + xor a + ld [hMultiplicand + 0], a + ld [hMultiplicand + 1], a + ld a, 10 + ld [hMultiplier], a + call Multiply + ld a, 25 + ld [hDivisor], a + ld b, 4 + call Divide + ld a, [hQuotient + 2] + ld d, a + pop bc + ret + +; 37939 diff --git a/engine/battle/move_effects/fury_cutter.asm b/engine/battle/move_effects/fury_cutter.asm new file mode 100644 index 000000000..91679368f --- /dev/null +++ b/engine/battle/move_effects/fury_cutter.asm @@ -0,0 +1,61 @@ +BattleCommand_FuryCutter: ; 37792 +; furycutter + + ld hl, wPlayerFuryCutterCount + ld a, [hBattleTurn] + and a + jr z, .go + ld hl, wEnemyFuryCutterCount + +.go + ld a, [wAttackMissed] + and a + jp nz, ResetFuryCutterCount + + inc [hl] + +; Damage capped at 5 turns' worth (16x). + ld a, [hl] + ld b, a + cp 6 + jr c, .checkdouble + ld b, 5 + +.checkdouble + dec b + ret z + +; Double the damage + ld hl, wCurDamage + 1 + sla [hl] + dec hl + rl [hl] + jr nc, .checkdouble + +; No overflow + ld a, $ff + ld [hli], a + ld [hl], a + ret + +; 377be + + +ResetFuryCutterCount: ; 377be + + push hl + + ld hl, wPlayerFuryCutterCount + ld a, [hBattleTurn] + and a + jr z, .reset + ld hl, wEnemyFuryCutterCount + +.reset + xor a + ld [hl], a + + pop hl + ret + +; 377ce diff --git a/engine/battle/move_effects/future_sight.asm b/engine/battle/move_effects/future_sight.asm new file mode 100644 index 000000000..fa2148ab7 --- /dev/null +++ b/engine/battle/move_effects/future_sight.asm @@ -0,0 +1,85 @@ +BattleCommand_CheckFutureSight: ; 37d0d +; checkfuturesight + + ld hl, wPlayerFutureSightCount + ld de, wPlayerFutureSightDamage + ld a, [hBattleTurn] + and a + jr z, .ok + ld hl, wEnemyFutureSightCount + ld de, wEnemyFutureSightDamage +.ok + + ld a, [hl] + and a + ret z + cp 1 + ret nz + + ld [hl], 0 + ld a, [de] + inc de + ld [wCurDamage], a + ld a, [de] + ld [wCurDamage + 1], a + ld b, futuresight_command + jp SkipToBattleCommand + +; 37d34 + +BattleCommand_FutureSight: ; 37d34 +; futuresight + + call CheckUserIsCharging + jr nz, .AlreadyChargingFutureSight + ld a, BATTLE_VARS_MOVE_ANIM + call GetBattleVar + ld b, a + ld a, BATTLE_VARS_LAST_COUNTER_MOVE + call GetBattleVarAddr + ld [hl], b + ld a, BATTLE_VARS_LAST_MOVE + call GetBattleVarAddr + ld [hl], b +.AlreadyChargingFutureSight: + ld hl, wPlayerFutureSightCount + ld a, [hBattleTurn] + and a + jr z, .GotFutureSightCount + ld hl, wEnemyFutureSightCount +.GotFutureSightCount: + ld a, [hl] + and a + jr nz, .failed + ld a, 4 + ld [hl], a + call BattleCommand_LowerSub + call BattleCommand_MoveDelay + ld hl, ForesawAttackText + call StdBattleTextBox + call BattleCommand_RaiseSub + ld de, wPlayerFutureSightDamage + ld a, [hBattleTurn] + and a + jr z, .StoreDamage + ld de, wEnemyFutureSightDamage +.StoreDamage: + ld hl, wCurDamage + ld a, [hl] + ld [de], a + ld [hl], 0 + inc hl + inc de + ld a, [hl] + ld [de], a + ld [hl], 0 + jp EndMoveEffect + +.failed + pop bc + call ResetDamage + call AnimateFailedMove + call PrintButItFailed + jp EndMoveEffect + +; 37d94 diff --git a/engine/battle/move_effects/heal_bell.asm b/engine/battle/move_effects/heal_bell.asm new file mode 100644 index 000000000..c79362f9c --- /dev/null +++ b/engine/battle/move_effects/heal_bell.asm @@ -0,0 +1,36 @@ +BattleCommand_HealBell: ; 35cc9 +; healbell + + ld a, BATTLE_VARS_SUBSTATUS1 + call GetBattleVarAddr + res SUBSTATUS_NIGHTMARE, [hl] + ld de, wPartyMon1Status + ld a, [hBattleTurn] + and a + jr z, .got_status + ld de, wOTPartyMon1Status +.got_status + ld a, BATTLE_VARS_STATUS + call GetBattleVarAddr + xor a + ld [hl], a + ld h, d + ld l, e + ld bc, PARTYMON_STRUCT_LENGTH + ld d, PARTY_LENGTH +.loop + ld [hl], a + add hl, bc + dec d + jr nz, .loop + call AnimateCurrentMove + + ld hl, BellChimedText + call StdBattleTextBox + + ld a, [hBattleTurn] + and a + jp z, CalcPlayerStats + jp CalcEnemyStats + +; 35d00 diff --git a/engine/battle/move_effects/hidden_power.asm b/engine/battle/move_effects/hidden_power.asm new file mode 100644 index 000000000..f96becf97 --- /dev/null +++ b/engine/battle/move_effects/hidden_power.asm @@ -0,0 +1,10 @@ +BattleCommand_HiddenPower: ; 37be8 +; hiddenpower + + ld a, [wAttackMissed] + and a + ret nz + farcall HiddenPowerDamage + ret + +; 37bf4 diff --git a/engine/battle/move_effects/leech_seed.asm b/engine/battle/move_effects/leech_seed.asm new file mode 100644 index 000000000..328a2c416 --- /dev/null +++ b/engine/battle/move_effects/leech_seed.asm @@ -0,0 +1,42 @@ +BattleCommand_LeechSeed: ; 36f9d +; leechseed + ld a, [wAttackMissed] + and a + jr nz, .evaded + call CheckSubstituteOpp + jr nz, .evaded + + ld de, wEnemyMonType1 + ld a, [hBattleTurn] + and a + jr z, .ok + ld de, wBattleMonType1 +.ok + + ld a, [de] + cp GRASS + jr z, .grass + inc de + ld a, [de] + cp GRASS + jr z, .grass + + ld a, BATTLE_VARS_SUBSTATUS4_OPP + call GetBattleVarAddr + bit SUBSTATUS_LEECH_SEED, [hl] + jr nz, .evaded + set SUBSTATUS_LEECH_SEED, [hl] + call AnimateCurrentMove + ld hl, WasSeededText + jp StdBattleTextBox + +.grass + call AnimateFailedMove + jp PrintDoesntAffect + +.evaded + call AnimateFailedMove + ld hl, EvadedText + jp StdBattleTextBox + +; 36fe1 diff --git a/engine/battle/move_effects/lock_on.asm b/engine/battle/move_effects/lock_on.asm new file mode 100644 index 000000000..36d8db926 --- /dev/null +++ b/engine/battle/move_effects/lock_on.asm @@ -0,0 +1,23 @@ +BattleCommand_LockOn: ; 35a53 +; lockon + + call CheckSubstituteOpp + jr nz, .fail + + ld a, [wAttackMissed] + and a + jr nz, .fail + + ld a, BATTLE_VARS_SUBSTATUS5_OPP + call GetBattleVarAddr + set SUBSTATUS_LOCK_ON, [hl] + call AnimateCurrentMove + + ld hl, TookAimText + jp StdBattleTextBox + +.fail + call AnimateFailedMove + jp PrintDidntAffect + +; 35a74 diff --git a/engine/battle/move_effects/magnitude.asm b/engine/battle/move_effects/magnitude.asm new file mode 100644 index 000000000..f56ec5c1b --- /dev/null +++ b/engine/battle/move_effects/magnitude.asm @@ -0,0 +1,29 @@ +BattleCommand_GetMagnitude: ; 37991 +; getmagnitude + + push bc + call BattleRandom + ld b, a + ld hl, MagnitudePower +.loop + ld a, [hli] + cp b + jr nc, .ok + inc hl + inc hl + jr .loop + +.ok + ld d, [hl] + push de + inc hl + ld a, [hl] + ld [wTypeMatchup], a + call BattleCommand_MoveDelay + ld hl, MagnitudeText + call StdBattleTextBox + pop de + pop bc + ret + +INCLUDE "data/moves/magnitude_power.asm" diff --git a/engine/battle/move_effects/metronome.asm b/engine/battle/move_effects/metronome.asm new file mode 100644 index 000000000..6835ab569 --- /dev/null +++ b/engine/battle/move_effects/metronome.asm @@ -0,0 +1,46 @@ +BattleCommand_Metronome: ; 37418 +; metronome + + call ClearLastMove + call CheckUserIsCharging + jr nz, .asm_3742b + + ld a, [wKickCounter] + push af + call BattleCommand_LowerSub + pop af + ld [wKickCounter], a + +.asm_3742b + call LoadMoveAnim + +.GetMove: + call BattleRandom + +; No invalid moves. + cp NUM_ATTACKS + 1 + jr nc, .GetMove + +; None of the moves in MetronomeExcepts. + push af + ld de, 1 + ld hl, MetronomeExcepts + call IsInArray + pop bc + jr c, .GetMove + +; No moves the user already has. + ld a, b + call CheckUserMove + jr z, .GetMove + + + ld a, BATTLE_VARS_MOVE + call GetBattleVarAddr + ld [hl], b + call UpdateMoveData + jp ResetTurn +; 37454 + + +INCLUDE "data/battle/metronome_exception_moves.asm" diff --git a/engine/battle/move_effects/mimic.asm b/engine/battle/move_effects/mimic.asm new file mode 100644 index 000000000..712b42df1 --- /dev/null +++ b/engine/battle/move_effects/mimic.asm @@ -0,0 +1,52 @@ +BattleCommand_Mimic: ; 36f46 +; mimic + + call ClearLastMove + call BattleCommand_MoveDelay + ld a, [wAttackMissed] + and a + jr nz, .fail + ld hl, wBattleMonMoves + ld a, [hBattleTurn] + and a + jr z, .player_turn + ld hl, wEnemyMonMoves +.player_turn + call CheckHiddenOpponent + jr nz, .fail + ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP + call GetBattleVar + and a + jr z, .fail + cp STRUGGLE + jr z, .fail + ld b, a + ld c, NUM_MOVES +.check_already_knows_move + ld a, [hli] + cp b + jr z, .fail + dec c + jr nz, .check_already_knows_move + dec hl +.find_mimic + ld a, [hld] + cp MIMIC + jr nz, .find_mimic + inc hl + ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP + call GetBattleVar + ld [hl], a + ld [wNamedObjectIndexBuffer], a + ld bc, wBattleMonPP - wBattleMonMoves + add hl, bc + ld [hl], 5 + call GetMoveName + call AnimateCurrentMove + ld hl, LearnedMoveText + jp StdBattleTextBox + +.fail + jp FailMimic + +; 36f9d diff --git a/engine/battle/move_effects/mirror_coat.asm b/engine/battle/move_effects/mirror_coat.asm new file mode 100644 index 000000000..41e296108 --- /dev/null +++ b/engine/battle/move_effects/mirror_coat.asm @@ -0,0 +1,61 @@ +BattleCommand_MirrorCoat: ; 37c95 +; mirrorcoat + + ld a, 1 + ld [wAttackMissed], a + + ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP + call GetBattleVar + and a + ret z + + ld b, a + callfar GetMoveEffect + ld a, b + cp EFFECT_MIRROR_COAT + ret z + + call BattleCommand_ResetTypeMatchup + ld a, [wTypeMatchup] + and a + ret z + + call CheckOpponentWentFirst + ret z + + ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP + call GetBattleVar + dec a + ld de, wStringBuffer1 + call GetMoveData + + ld a, [wStringBuffer1 + 2] + and a + ret z + + ld a, [wStringBuffer1 + 3] + cp SPECIAL + ret c + + ld hl, wCurDamage + ld a, [hli] + or [hl] + ret z + + ld a, [hl] + add a + ld [hld], a + ld a, [hl] + adc a + ld [hl], a + jr nc, .capped + ld a, $ff + ld [hli], a + ld [hl], a +.capped + + xor a + ld [wAttackMissed], a + ret + +; 37ce6 diff --git a/engine/battle/move_effects/mirror_move.asm b/engine/battle/move_effects/mirror_move.asm new file mode 100644 index 000000000..c4f208d77 --- /dev/null +++ b/engine/battle/move_effects/mirror_move.asm @@ -0,0 +1,52 @@ +BattleCommand_MirrorMove: ; 373c9 +; mirrormove + + call ClearLastMove + + ld a, BATTLE_VARS_MOVE + call GetBattleVarAddr + + ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP + call GetBattleVar + and a + jr z, .failed + + call CheckUserMove + jr nz, .use + +.failed + call AnimateFailedMove + + ld hl, MirrorMoveFailedText + call StdBattleTextBox + jp EndMoveEffect + +.use + ld a, b + ld [hl], a + ld [wd265], a + + push af + ld a, BATTLE_VARS_MOVE_ANIM + call GetBattleVarAddr + ld d, h + ld e, l + pop af + + dec a + call GetMoveData + call GetMoveName + call CopyName1 + call CheckUserIsCharging + jr nz, .done + + ld a, [wKickCounter] + push af + call BattleCommand_LowerSub + pop af + ld [wKickCounter], a + +.done + call BattleCommand_MoveDelay + jp ResetTurn +; 37418 diff --git a/engine/battle/move_effects/mist.asm b/engine/battle/move_effects/mist.asm new file mode 100644 index 000000000..9ffd86c8e --- /dev/null +++ b/engine/battle/move_effects/mist.asm @@ -0,0 +1,17 @@ +BattleCommand_Mist: ; 36c7e +; mist + + ld a, BATTLE_VARS_SUBSTATUS4 + call GetBattleVarAddr + bit SUBSTATUS_MIST, [hl] + jr nz, .already_mist + set SUBSTATUS_MIST, [hl] + call AnimateCurrentMove + ld hl, MistText + jp StdBattleTextBox + +.already_mist + call AnimateFailedMove + jp PrintButItFailed + +; 36c98 diff --git a/engine/battle/move_effects/nightmare.asm b/engine/battle/move_effects/nightmare.asm new file mode 100644 index 000000000..788e3de41 --- /dev/null +++ b/engine/battle/move_effects/nightmare.asm @@ -0,0 +1,38 @@ +BattleCommand_Nightmare: ; 37536 +; nightmare + +; Can't hit an absent opponent. + + call CheckHiddenOpponent + jr nz, .failed + +; Can't hit a substitute. + + call CheckSubstituteOpp + jr nz, .failed + +; Only works on a sleeping opponent. + + ld a, BATTLE_VARS_STATUS_OPP + call GetBattleVarAddr + and SLP + jr z, .failed + +; Bail if the opponent is already having a nightmare. + + ld a, BATTLE_VARS_SUBSTATUS1_OPP + call GetBattleVarAddr + bit SUBSTATUS_NIGHTMARE, [hl] + jr nz, .failed + +; Otherwise give the opponent a nightmare. + + set SUBSTATUS_NIGHTMARE, [hl] + call AnimateCurrentMove + ld hl, StartedNightmareText + jp StdBattleTextBox + +.failed + call AnimateFailedMove + jp PrintButItFailed +; 37563 diff --git a/engine/battle/move_effects/pain_split.asm b/engine/battle/move_effects/pain_split.asm new file mode 100644 index 000000000..2db3726c6 --- /dev/null +++ b/engine/battle/move_effects/pain_split.asm @@ -0,0 +1,97 @@ +BattleCommand_PainSplit: ; 35926 +; painsplit + + ld a, [wAttackMissed] + and a + jp nz, .ButItFailed + call CheckSubstituteOpp + jp nz, .ButItFailed + call AnimateCurrentMove + ld hl, wBattleMonMaxHP + 1 + ld de, wEnemyMonMaxHP + 1 + call .PlayerShareHP + ld a, $1 + ld [wWhichHPBar], a + hlcoord 10, 9 + predef AnimateHPBar + ld hl, wEnemyMonHP + ld a, [hli] + ld [wBuffer4], a + ld a, [hli] + ld [wBuffer3], a + ld a, [hli] + ld [wBuffer2], a + ld a, [hl] + ld [wBuffer1], a + call .EnemyShareHP + xor a + ld [wWhichHPBar], a + call ResetDamage + hlcoord 2, 2 + predef AnimateHPBar + farcall _UpdateBattleHUDs + + ld hl, SharedPainText + jp StdBattleTextBox + +.PlayerShareHP: + ld a, [hld] + ld [wBuffer1], a + ld a, [hld] + ld [wBuffer2], a + ld a, [hld] + ld b, a + ld [wBuffer3], a + ld a, [hl] + ld [wBuffer4], a + dec de + dec de + ld a, [de] + dec de + add b + ld [wCurDamage + 1], a + ld b, [hl] + ld a, [de] + adc b + srl a + ld [wCurDamage], a + ld a, [wCurDamage + 1] + rr a + ld [wCurDamage + 1], a + inc hl + inc hl + inc hl + inc de + inc de + inc de + +.EnemyShareHP: ; 359ac + ld c, [hl] + dec hl + ld a, [wCurDamage + 1] + sub c + ld b, [hl] + dec hl + ld a, [wCurDamage] + sbc b + jr nc, .skip + + ld a, [wCurDamage] + ld b, a + ld a, [wCurDamage + 1] + ld c, a +.skip + ld a, c + ld [hld], a + ld [wBuffer5], a + ld a, b + ld [hli], a + ld [wBuffer6], a + ret + +; 359cd + +.ButItFailed: + jp PrintDidntAffect2 + +; 359d0 diff --git a/engine/battle/move_effects/pay_day.asm b/engine/battle/move_effects/pay_day.asm new file mode 100644 index 000000000..a5d2fed0d --- /dev/null +++ b/engine/battle/move_effects/pay_day.asm @@ -0,0 +1,28 @@ +BattleCommand_PayDay: ; 3705c +; payday + + xor a + ld hl, wStringBuffer1 + ld [hli], a + + ld a, [hBattleTurn] + and a + ld a, [wBattleMonLevel] + jr z, .ok + ld a, [wEnemyMonLevel] +.ok + + add a + ld hl, wPayDayMoney + 2 + add [hl] + ld [hld], a + jr nc, .done + inc [hl] + dec hl + jr nz, .done + inc [hl] +.done + ld hl, CoinsScatteredText + jp StdBattleTextBox + +; 3707f diff --git a/engine/battle/move_effects/perish_song.asm b/engine/battle/move_effects/perish_song.asm new file mode 100644 index 000000000..8c88c8739 --- /dev/null +++ b/engine/battle/move_effects/perish_song.asm @@ -0,0 +1,40 @@ +BattleCommand_PerishSong: ; 376c2 +; perishsong + + + ld hl, wPlayerSubStatus1 + ld de, wEnemySubStatus1 + bit SUBSTATUS_PERISH, [hl] + jr z, .ok + + ld a, [de] + bit SUBSTATUS_PERISH, a + jr nz, .failed + +.ok + bit SUBSTATUS_PERISH, [hl] + jr nz, .enemy + + set SUBSTATUS_PERISH, [hl] + ld a, 4 + ld [wPlayerPerishCount], a + +.enemy + ld a, [de] + bit SUBSTATUS_PERISH, a + jr nz, .done + + set SUBSTATUS_PERISH, a + ld [de], a + ld a, 4 + ld [wEnemyPerishCount], a + +.done + call AnimateCurrentMove + ld hl, StartPerishText + jp StdBattleTextBox + +.failed + call AnimateFailedMove + jp PrintButItFailed +; 376f8 diff --git a/engine/battle/move_effects/present.asm b/engine/battle/move_effects/present.asm new file mode 100755 index 000000000..a2ef5bc64 --- /dev/null +++ b/engine/battle/move_effects/present.asm @@ -0,0 +1,88 @@ +BattleCommand_Present: ; 37874 +; present + + ld a, [wLinkMode] + cp LINK_COLOSSEUM + jr z, .colosseum_skippush + push bc + push de +.colosseum_skippush + + call BattleCommand_Stab + + ld a, [wLinkMode] + cp LINK_COLOSSEUM + jr z, .colosseum_skippop + pop de + pop bc +.colosseum_skippop + + ld a, [wTypeMatchup] + and a + jp z, AnimateFailedMove + ld a, [wAttackMissed] + and a + jp nz, AnimateFailedMove + + push bc + call BattleRandom + ld b, a + ld hl, PresentPower + ld c, 0 +.next + ld a, [hli] + cp -1 + jr z, .heal_effect ; 378a4 $11 + cp b + jr nc, .got_power ; 378a7 $4 + inc c + inc hl + jr .next ; 378ab $f4 + +.got_power + ld a, c + ld [wPresentPower], a + call AnimateCurrentMoveEitherSide + ld d, [hl] + pop bc + ret + +.heal_effect + pop bc + ld a, 3 + ld [wPresentPower], a + call AnimateCurrentMove + call BattleCommand_SwitchTurn + ld hl, AICheckPlayerMaxHP + ld a, [hBattleTurn] + and a + jr z, .got_hp_fn_pointer ; 378c9 $3 + ld hl, AICheckEnemyMaxHP +.got_hp_fn_pointer + ld a, BANK(AICheckPlayerMaxHP) + rst FarCall + jr c, .already_fully_healed ; 378d1 $20 + + ld hl, GetQuarterMaxHP + call CallBattleCore + call BattleCommand_SwitchTurn + ld hl, RestoreHP + call CallBattleCore + call BattleCommand_SwitchTurn + ld hl, RegainedHealthText + call StdBattleTextBox + call BattleCommand_SwitchTurn + call UpdateOpponentInParty + jr .do_animation ; 378f1 $11 + +.already_fully_healed + call BattleCommand_SwitchTurn + call _CheckBattleScene + jr nc, .do_animation ; 378f9 $9 + call AnimateFailedMove + ld hl, RefusedGiftText + call StdBattleTextBox +.do_animation + jp EndMoveEffect + +INCLUDE "data/moves/present_power.asm" diff --git a/engine/battle/move_effects/protect.asm b/engine/battle/move_effects/protect.asm new file mode 100644 index 000000000..6c65e0ed1 --- /dev/null +++ b/engine/battle/move_effects/protect.asm @@ -0,0 +1,80 @@ +BattleCommand_Protect: ; 37618 +; protect + call ProtectChance + ret c + + ld a, BATTLE_VARS_SUBSTATUS1 + call GetBattleVarAddr + set SUBSTATUS_PROTECT, [hl] + + call AnimateCurrentMove + + ld hl, ProtectedItselfText + jp StdBattleTextBox +; 3762c + + +ProtectChance: ; 3762c + + ld de, wPlayerProtectCount + ld a, [hBattleTurn] + and a + jr z, .asm_37637 + ld de, wEnemyProtectCount +.asm_37637 + + call CheckOpponentWentFirst + jr nz, .failed + +; Can't have a substitute. + + ld a, BATTLE_VARS_SUBSTATUS4 + call GetBattleVar + bit SUBSTATUS_SUBSTITUTE, a + jr nz, .failed + +; Halve the chance of a successful Protect for each consecutive use. + + ld b, $ff + ld a, [de] + ld c, a +.loop + ld a, c + and a + jr z, .done + dec c + + srl b + ld a, b + and a + jr nz, .loop + jr .failed +.done + +.rand + call BattleRandom + and a + jr z, .rand + + dec a + cp b + jr nc, .failed + +; Another consecutive Protect use. + + ld a, [de] + inc a + ld [de], a + + and a + ret + + +.failed + xor a + ld [de], a + call AnimateFailedMove + call PrintButItFailed + scf + ret +; 3766f diff --git a/engine/battle/move_effects/psych_up.asm b/engine/battle/move_effects/psych_up.asm new file mode 100644 index 000000000..c57fff9cd --- /dev/null +++ b/engine/battle/move_effects/psych_up.asm @@ -0,0 +1,51 @@ +BattleCommand_PsychUp: ; 37c55 +; psychup + + ld hl, wEnemyStatLevels + ld de, wPlayerStatLevels + ld a, [hBattleTurn] + and a + jr z, .pointers_correct +; It's the enemy's turn, so swap the pointers. + push hl + ld h, d + ld l, e + pop de +.pointers_correct + push hl + ld b, NUM_LEVEL_STATS +; If any of the enemy's stats is modified from its base level, +; the move succeeds. Otherwise, it fails. +.loop + ld a, [hli] + cp BASE_STAT_LEVEL + jr nz, .break + dec b + jr nz, .loop + pop hl + call AnimateFailedMove + jp PrintButItFailed + +.break + pop hl + ld b, NUM_LEVEL_STATS +.loop2 + ld a, [hli] + ld [de], a + inc de + dec b + jr nz, .loop2 + ld a, [hBattleTurn] + and a + jr nz, .calc_enemy_stats + call CalcPlayerStats + jr .merge + +.calc_enemy_stats + call CalcEnemyStats +.merge + call AnimateCurrentMove + ld hl, CopiedStatsText + jp StdBattleTextBox + +; 37c95 diff --git a/engine/battle/move_effects/pursuit.asm b/engine/battle/move_effects/pursuit.asm new file mode 100644 index 000000000..969e08f73 --- /dev/null +++ b/engine/battle/move_effects/pursuit.asm @@ -0,0 +1,26 @@ +BattleCommand_Pursuit: ; 37b1d +; pursuit +; Double damage if the opponent is switching. + + ld hl, wEnemyIsSwitching + ld a, [hBattleTurn] + and a + jr z, .ok + ld hl, wPlayerIsSwitching +.ok + ld a, [hl] + and a + ret z + + ld hl, wCurDamage + 1 + sla [hl] + dec hl + rl [hl] + ret nc + + ld a, $ff + ld [hli], a + ld [hl], a + ret + +; 37b39 diff --git a/engine/battle/move_effects/rage.asm b/engine/battle/move_effects/rage.asm new file mode 100644 index 000000000..ac01f8137 --- /dev/null +++ b/engine/battle/move_effects/rage.asm @@ -0,0 +1,8 @@ +BattleCommand_Rage: ; 36f1d +; rage + ld a, BATTLE_VARS_SUBSTATUS4 + call GetBattleVarAddr + set SUBSTATUS_RAGE, [hl] + ret + +; 36f25 diff --git a/engine/battle/move_effects/rain_dance.asm b/engine/battle/move_effects/rain_dance.asm new file mode 100644 index 000000000..6c587d551 --- /dev/null +++ b/engine/battle/move_effects/rain_dance.asm @@ -0,0 +1,11 @@ +BattleCommand_StartRain: ; 37bf4 +; startrain + ld a, WEATHER_RAIN + ld [wBattleWeather], a + ld a, 5 + ld [wWeatherCount], a + call AnimateCurrentMove + ld hl, DownpourText + jp StdBattleTextBox + +; 37c07 diff --git a/engine/battle/move_effects/rapid_spin.asm b/engine/battle/move_effects/rapid_spin.asm new file mode 100644 index 000000000..84bcbad7f --- /dev/null +++ b/engine/battle/move_effects/rapid_spin.asm @@ -0,0 +1,38 @@ +BattleCommand_ClearHazards: ; 37b39 +; clearhazards + + ld a, BATTLE_VARS_SUBSTATUS4 + call GetBattleVarAddr + bit SUBSTATUS_LEECH_SEED, [hl] + jr z, .not_leeched + res SUBSTATUS_LEECH_SEED, [hl] + ld hl, ShedLeechSeedText + call StdBattleTextBox +.not_leeched + + ld hl, wPlayerScreens + ld de, wPlayerWrapCount + ld a, [hBattleTurn] + and a + jr z, .got_screens_wrap + ld hl, wEnemyScreens + ld de, wEnemyWrapCount +.got_screens_wrap + bit SCREENS_SPIKES, [hl] + jr z, .no_spikes + res SCREENS_SPIKES, [hl] + ld hl, BlewSpikesText + push de + call StdBattleTextBox + pop de +.no_spikes + + ld a, [de] + and a + ret z + xor a + ld [de], a + ld hl, ReleasedByText + jp StdBattleTextBox + +; 37b74 diff --git a/engine/battle/move_effects/return.asm b/engine/battle/move_effects/return.asm new file mode 100644 index 000000000..e1d568e7c --- /dev/null +++ b/engine/battle/move_effects/return.asm @@ -0,0 +1,27 @@ +BattleCommand_HappinessPower: ; 3784b +; happinesspower + push bc + ld hl, wBattleMonHappiness + ld a, [hBattleTurn] + and a + jr z, .ok + ld hl, wEnemyMonHappiness +.ok + xor a + ld [hMultiplicand + 0], a + ld [hMultiplicand + 1], a + ld a, [hl] + ld [hMultiplicand + 2], a + ld a, 10 + ld [hMultiplier], a + call Multiply + ld a, 25 + ld [hDivisor], a + ld b, 4 + call Divide + ld a, [hQuotient + 2] + ld d, a + pop bc + ret + +; 37874 diff --git a/engine/battle/move_effects/rollout.asm b/engine/battle/move_effects/rollout.asm new file mode 100644 index 000000000..f6966c48a --- /dev/null +++ b/engine/battle/move_effects/rollout.asm @@ -0,0 +1,99 @@ +MAX_ROLLOUT_COUNT EQU 5 + + +BattleCommand_CheckCurl: ; 37718 +; checkcurl + + ld de, wPlayerRolloutCount + ld a, [hBattleTurn] + and a + jr z, .ok + ld de, wEnemyRolloutCount +.ok + ld a, BATTLE_VARS_SUBSTATUS1 + call GetBattleVar + bit SUBSTATUS_ROLLOUT, a + jr z, .reset + + ld b, $4 ; doturn + jp SkipToBattleCommand + +.reset + xor a + ld [de], a + ret +; 37734 + + +BattleCommand_RolloutPower: ; 37734 +; rolloutpower + + ld a, BATTLE_VARS_STATUS + call GetBattleVar + and SLP + ret nz + + ld hl, wPlayerRolloutCount + ld a, [hBattleTurn] + and a + jr z, .got_rollout_count + ld hl, wEnemyRolloutCount + +.got_rollout_count + ld a, [hl] + and a + jr nz, .skip_set_rampage + ld a, 1 + ld [wSomeoneIsRampaging], a + +.skip_set_rampage + ld a, [wAttackMissed] + and a + jr z, .hit + + ld a, BATTLE_VARS_SUBSTATUS1 + call GetBattleVarAddr + res 6, [hl] + ret + +.hit + inc [hl] + ld a, [hl] + ld b, a + cp MAX_ROLLOUT_COUNT + jr c, .not_done_with_rollout + + ld a, BATTLE_VARS_SUBSTATUS1 + call GetBattleVarAddr + res SUBSTATUS_ROLLOUT, [hl] + jr .done_with_substatus_flag + +.not_done_with_rollout + ld a, BATTLE_VARS_SUBSTATUS1 + call GetBattleVarAddr + set SUBSTATUS_ROLLOUT, [hl] + +.done_with_substatus_flag + ld a, BATTLE_VARS_SUBSTATUS2 + call GetBattleVar + bit SUBSTATUS_CURLED, a + jr z, .not_curled + inc b +.not_curled +.loop + dec b + jr z, .done_damage + + ld hl, wCurDamage + 1 + sla [hl] + dec hl + rl [hl] + jr nc, .loop + + ld a, $ff + ld [hli], a + ld [hl], a + +.done_damage + ret +; 37791 diff --git a/engine/battle/move_effects/safeguard.asm b/engine/battle/move_effects/safeguard.asm new file mode 100644 index 000000000..1dc233eab --- /dev/null +++ b/engine/battle/move_effects/safeguard.asm @@ -0,0 +1,25 @@ +BattleCommand_Safeguard: ; 37939 +; safeguard + + ld hl, wPlayerScreens + ld de, wPlayerSafeguardCount + ld a, [hBattleTurn] + and a + jr z, .ok + ld hl, wEnemyScreens + ld de, wEnemySafeguardCount +.ok + bit SCREENS_SAFEGUARD, [hl] + jr nz, .failed + set SCREENS_SAFEGUARD, [hl] + ld a, 5 + ld [de], a + call AnimateCurrentMove + ld hl, CoveredByVeilText + jp StdBattleTextBox + +.failed + call AnimateFailedMove + jp PrintButItFailed + +; 37962 diff --git a/engine/battle/move_effects/sandstorm.asm b/engine/battle/move_effects/sandstorm.asm new file mode 100644 index 000000000..5aaa61deb --- /dev/null +++ b/engine/battle/move_effects/sandstorm.asm @@ -0,0 +1,19 @@ +BattleCommand_StartSandstorm: ; 376f8 +; startsandstorm + + ld a, [wBattleWeather] + cp WEATHER_SANDSTORM + jr z, .failed + + ld a, WEATHER_SANDSTORM + ld [wBattleWeather], a + ld a, 5 + ld [wWeatherCount], a + call AnimateCurrentMove + ld hl, SandstormBrewedText + jp StdBattleTextBox + +.failed + call AnimateFailedMove + jp PrintButItFailed +; 37718 diff --git a/engine/battle/move_effects/selfdestruct.asm b/engine/battle/move_effects/selfdestruct.asm new file mode 100644 index 000000000..6f6b0966f --- /dev/null +++ b/engine/battle/move_effects/selfdestruct.asm @@ -0,0 +1,31 @@ +BattleCommand_Selfdestruct: ; 37380 + farcall StubbedTrainerRankings_Selfdestruct + ld a, BATTLEANIM_PLAYER_DAMAGE + ld [wNumHits], a + ld c, 3 + call DelayFrames + ld a, BATTLE_VARS_STATUS + call GetBattleVarAddr + xor a + ld [hli], a + inc hl + ld [hli], a + ld [hl], a + ld a, $1 + ld [wKickCounter], a + call BattleCommand_LowerSub + call LoadMoveAnim + ld a, BATTLE_VARS_SUBSTATUS4 + call GetBattleVarAddr + res SUBSTATUS_LEECH_SEED, [hl] + ld a, BATTLE_VARS_SUBSTATUS5_OPP + call GetBattleVarAddr + res SUBSTATUS_DESTINY_BOND, [hl] + call _CheckBattleScene + ret nc + farcall DrawPlayerHUD + farcall DrawEnemyHUD + call WaitBGMap + jp RefreshBattleHuds + +; 373c9 diff --git a/engine/battle/move_effects/sketch.asm b/engine/battle/move_effects/sketch.asm new file mode 100644 index 000000000..93f7ff30c --- /dev/null +++ b/engine/battle/move_effects/sketch.asm @@ -0,0 +1,119 @@ +BattleCommand_Sketch: ; 35a74 +; sketch + + call ClearLastMove +; Don't sketch during a link battle + ld a, [wLinkMode] + and a + jr z, .not_linked + call AnimateFailedMove + jp PrintNothingHappened + +.not_linked +; If the opponent has a substitute up, fail. + call CheckSubstituteOpp + jp nz, .fail +; If the opponent is transformed, fail. + ld a, BATTLE_VARS_SUBSTATUS5_OPP + call GetBattleVarAddr + bit SUBSTATUS_TRANSFORMED, [hl] + jp nz, .fail +; Get the user's moveset in its party struct. +; This move replacement shall be permanent. +; Pointer will be in de. + ld a, MON_MOVES + call UserPartyAttr + ld d, h + ld e, l +; Get the battle move structs. + ld hl, wBattleMonMoves + ld a, [hBattleTurn] + and a + jr z, .get_last_move + ld hl, wEnemyMonMoves +.get_last_move + ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP + call GetBattleVar + ld [wTypeMatchup], a + ld b, a +; Fail if move is invalid or is Struggle. + and a + jr z, .fail + cp STRUGGLE + jr z, .fail +; Fail if user already knows that move + ld c, NUM_MOVES +.does_user_already_know_move + ld a, [hli] + cp b + jr z, .fail + dec c + jr nz, .does_user_already_know_move +; Find Sketch in the user's moveset. +; Pointer in hl, and index in c. + dec hl + ld c, NUM_MOVES +.find_sketch + dec c + ld a, [hld] + cp SKETCH + jr nz, .find_sketch + inc hl +; The Sketched move is loaded to that slot. + ld a, b + ld [hl], a +; Copy the base PP from that move. + push bc + push hl + dec a + ld hl, Moves + MOVE_PP + call GetMoveAttr + pop hl + ld bc, wBattleMonPP - wBattleMonMoves + add hl, bc + ld [hl], a + pop bc + + ld a, [hBattleTurn] + and a + jr z, .user_trainer + ld a, [wBattleMode] + dec a + jr nz, .user_trainer +; wildmon + ld a, [hl] + push bc + ld hl, wWildMonPP + ld b, 0 + add hl, bc + ld [hl], a + ld hl, wWildMonMoves + add hl, bc + pop bc + ld [hl], b + jr .done_copy + +.user_trainer + ld a, [hl] + push af + ld l, c + ld h, 0 + add hl, de + ld a, b + ld [hl], a + pop af + ld de, MON_PP - MON_MOVES + add hl, de + ld [hl], a +.done_copy + call GetMoveName + call AnimateCurrentMove + + ld hl, SketchedText + jp StdBattleTextBox + +.fail + call AnimateFailedMove + jp PrintDidntAffect + +; 35b16 diff --git a/engine/battle/move_effects/sleep_talk.asm b/engine/battle/move_effects/sleep_talk.asm new file mode 100644 index 000000000..3f62d4e36 --- /dev/null +++ b/engine/battle/move_effects/sleep_talk.asm @@ -0,0 +1,145 @@ +BattleCommand_SleepTalk: ; 35b33 +; sleeptalk + + call ClearLastMove + ld a, [wAttackMissed] + and a + jr nz, .fail + ld a, [hBattleTurn] + and a + ld hl, wBattleMonMoves + 1 + ld a, [wDisabledMove] + ld d, a + jr z, .got_moves + ld hl, wEnemyMonMoves + 1 + ld a, [wEnemyDisabledMove] + ld d, a +.got_moves + ld a, BATTLE_VARS_STATUS + call GetBattleVar + and SLP + jr z, .fail + ld a, [hl] + and a + jr z, .fail + call .safely_check_has_usable_move + jr c, .fail + dec hl +.sample_move + push hl + call BattleRandom + maskbits NUM_MOVES + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + pop hl + and a + jr z, .sample_move + ld e, a + ld a, BATTLE_VARS_MOVE_ANIM + call GetBattleVar + cp e + jr z, .sample_move + ld a, e + cp d + jr z, .sample_move + call .check_two_turn_move + jr z, .sample_move + ld a, BATTLE_VARS_MOVE + call GetBattleVarAddr + ld a, e + ld [hl], a + call CheckUserIsCharging + jr nz, .charging + ld a, [wKickCounter] + push af + call BattleCommand_LowerSub + pop af + ld [wKickCounter], a +.charging + call LoadMoveAnim + call UpdateMoveData + jp ResetTurn + +.fail + call AnimateFailedMove + jp TryPrintButItFailed + +.safely_check_has_usable_move + push hl + push de + push bc + call .check_has_usable_move + pop bc + pop de + pop hl + ret + +.check_has_usable_move + ld a, [hBattleTurn] + and a + ld a, [wDisabledMove] + jr z, .got_move_2 + + ld a, [wEnemyDisabledMove] +.got_move_2 + ld b, a + ld a, BATTLE_VARS_MOVE + call GetBattleVar + ld c, a + dec hl + ld d, NUM_MOVES +.loop2 + ld a, [hl] + and a + jr z, .carry + + cp c + jr z, .nope + cp b + jr z, .nope + + call .check_two_turn_move + jr nz, .no_carry + +.nope + inc hl + dec d + jr nz, .loop2 + +.carry + scf + ret + +.no_carry + and a + ret + +.check_two_turn_move + push hl + push de + push bc + + ld b, a + callfar GetMoveEffect + ld a, b + + pop bc + pop de + pop hl + + cp EFFECT_SKULL_BASH + ret z + cp EFFECT_RAZOR_WIND + ret z + cp EFFECT_SKY_ATTACK + ret z + cp EFFECT_SOLARBEAM + ret z + cp EFFECT_FLY + ret z + cp EFFECT_BIDE + ret + +; 35bff diff --git a/engine/battle/move_effects/snore.asm b/engine/battle/move_effects/snore.asm new file mode 100644 index 000000000..49fb1b210 --- /dev/null +++ b/engine/battle/move_effects/snore.asm @@ -0,0 +1,13 @@ +BattleCommand_Snore: ; 359d0 +; snore + ld a, BATTLE_VARS_STATUS + call GetBattleVar + and SLP + ret nz + call ResetDamage + ld a, $1 + ld [wAttackMissed], a + call FailMove + jp EndMoveEffect + +; 359e6 diff --git a/engine/battle/move_effects/spikes.asm b/engine/battle/move_effects/spikes.asm new file mode 100644 index 000000000..6cab0b96f --- /dev/null +++ b/engine/battle/move_effects/spikes.asm @@ -0,0 +1,27 @@ +BattleCommand_Spikes: ; 37683 +; spikes + + ld hl, wEnemyScreens + ld a, [hBattleTurn] + and a + jr z, .asm_3768e + ld hl, wPlayerScreens +.asm_3768e + +; Fails if spikes are already down! + + bit SCREENS_SPIKES, [hl] + jr nz, .failed + +; Nothing else stops it from working. + + set SCREENS_SPIKES, [hl] + + call AnimateCurrentMove + + ld hl, SpikesText + jp StdBattleTextBox + +.failed + jp FailMove +; 376a0 diff --git a/engine/battle/move_effects/spite.asm b/engine/battle/move_effects/spite.asm new file mode 100644 index 000000000..30a908ae7 --- /dev/null +++ b/engine/battle/move_effects/spite.asm @@ -0,0 +1,88 @@ +BattleCommand_Spite: ; 35c0f +; spite + + ld a, [wAttackMissed] + and a + jp nz, .failed + ld bc, PARTYMON_STRUCT_LENGTH ; ???? + ld hl, wEnemyMonMoves + ld a, [hBattleTurn] + and a + jr z, .got_moves + ld hl, wBattleMonMoves +.got_moves + ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP + call GetBattleVar + and a + jr z, .failed + cp STRUGGLE + jr z, .failed + ld b, a + ld c, -1 +.loop + inc c + ld a, [hli] + cp b + jr nz, .loop + ld [wTypeMatchup], a + dec hl + ld b, 0 + push bc + ld c, wBattleMonPP - wBattleMonMoves + add hl, bc + pop bc + ld a, [hl] + and PP_MASK + jr z, .failed + push bc + call GetMoveName + ; lose 2-5 PP + call BattleRandom + and %11 + inc a + inc a + ld b, a + ld a, [hl] + and PP_MASK + cp b + jr nc, .deplete_pp + ld b, a +.deplete_pp + ld a, [hl] + sub b + ld [hl], a + push af + ld a, MON_PP + call OpponentPartyAttr + ld d, b + pop af + pop bc + add hl, bc + ld e, a + ld a, BATTLE_VARS_SUBSTATUS5_OPP + call GetBattleVar + bit SUBSTATUS_TRANSFORMED, a + jr nz, .transformed + ld a, [hBattleTurn] + and a + jr nz, .not_wildmon + ld a, [wBattleMode] + dec a + jr nz, .not_wildmon + ld hl, wWildMonPP + add hl, bc +.not_wildmon + ld [hl], e +.transformed + push de + call AnimateCurrentMove + pop de + ld a, d + ld [wTypeMatchup], a + ld hl, SpiteEffectText + jp StdBattleTextBox + +.failed + jp PrintDidntAffect2 + +; 35c94 diff --git a/engine/battle/move_effects/splash.asm b/engine/battle/move_effects/splash.asm new file mode 100644 index 000000000..5b5e504b8 --- /dev/null +++ b/engine/battle/move_effects/splash.asm @@ -0,0 +1,6 @@ +BattleCommand_Splash: ; 36fe1 + call AnimateCurrentMove + farcall StubbedTrainerRankings_Splash + jp PrintNothingHappened + +; 36fed diff --git a/engine/battle/move_effects/substitute.asm b/engine/battle/move_effects/substitute.asm new file mode 100644 index 000000000..1deaa848d --- /dev/null +++ b/engine/battle/move_effects/substitute.asm @@ -0,0 +1,90 @@ +BattleCommand_Substitute: ; 36e7c +; substitute + + call BattleCommand_MoveDelay + ld hl, wBattleMonMaxHP + ld de, wPlayerSubstituteHP + ld a, [hBattleTurn] + and a + jr z, .got_hp + ld hl, wEnemyMonMaxHP + ld de, wEnemySubstituteHP +.got_hp + + ld a, BATTLE_VARS_SUBSTATUS4 + call GetBattleVar + bit SUBSTATUS_SUBSTITUTE, a + jr nz, .already_has_sub + + ld a, [hli] + ld b, [hl] + srl a + rr b + srl a + rr b + dec hl + dec hl + ld a, b + ld [de], a + ld a, [hld] + sub b + ld e, a + ld a, [hl] + sbc 0 + ld d, a + jr c, .too_weak_to_sub + ld a, d + or e + jr z, .too_weak_to_sub + ld [hl], d + inc hl + ld [hl], e + + ld a, BATTLE_VARS_SUBSTATUS4 + call GetBattleVarAddr + set SUBSTATUS_SUBSTITUTE, [hl] + + ld hl, wPlayerWrapCount + ld de, wPlayerTrappingMove + ld a, [hBattleTurn] + and a + jr z, .player + ld hl, wEnemyWrapCount + ld de, wEnemyTrappingMove +.player + + xor a + ld [hl], a + ld [de], a + call _CheckBattleScene + jr c, .no_anim + + xor a + ld [wNumHits], a + ld [wFXAnimID + 1], a + ld [wKickCounter], a + ld a, SUBSTITUTE + call LoadAnim + jr .finish + +.no_anim + call BattleCommand_RaiseSubNoAnim +.finish + ld hl, MadeSubstituteText + call StdBattleTextBox + jp RefreshBattleHuds + +.already_has_sub + call CheckUserIsCharging + call nz, BattleCommand_RaiseSub + ld hl, HasSubstituteText + jr .jp_stdbattletextbox + +.too_weak_to_sub + call CheckUserIsCharging + call nz, BattleCommand_RaiseSub + ld hl, TooWeakSubText +.jp_stdbattletextbox + jp StdBattleTextBox + +; 36f0b diff --git a/engine/battle/move_effects/sunny_day.asm b/engine/battle/move_effects/sunny_day.asm new file mode 100644 index 000000000..ef8c37c5c --- /dev/null +++ b/engine/battle/move_effects/sunny_day.asm @@ -0,0 +1,11 @@ +BattleCommand_StartSun: ; 37c07 +; startsun + ld a, WEATHER_SUN + ld [wBattleWeather], a + ld a, 5 + ld [wWeatherCount], a + call AnimateCurrentMove + ld hl, SunGotBrightText + jp StdBattleTextBox + +; 37c1a diff --git a/engine/battle/move_effects/teleport.asm b/engine/battle/move_effects/teleport.asm new file mode 100644 index 000000000..1bd1eb725 --- /dev/null +++ b/engine/battle/move_effects/teleport.asm @@ -0,0 +1,91 @@ +BattleCommand_Teleport: ; 36778 +; teleport + + ld a, [wBattleType] + cp BATTLETYPE_SHINY + jr z, .failed + cp BATTLETYPE_TRAP + jr z, .failed + cp BATTLETYPE_CELEBI + jr z, .failed + cp BATTLETYPE_SUICUNE + jr z, .failed + + ld a, BATTLE_VARS_SUBSTATUS5_OPP + call GetBattleVar + bit SUBSTATUS_CANT_RUN, a + jr nz, .failed +; Only need to check these next things if it's your turn + ld a, [hBattleTurn] + and a + jr nz, .enemy_turn +; Can't teleport from a trainer battle + ld a, [wBattleMode] + dec a + jr nz, .failed +; If your level is greater than the opponent's, you run without fail. + ld a, [wCurPartyLevel] + ld b, a + ld a, [wBattleMonLevel] + cp b + jr nc, .run_away +; Generate a number between 0 and (YourLevel + TheirLevel). + add b + ld c, a + inc c +.loop_player + call BattleRandom + cp c + jr nc, .loop_player +; If that number is greater than 4 times your level, run away. + srl b + srl b + cp b + jr nc, .run_away + +.failed + call AnimateFailedMove + jp PrintButItFailed + +.enemy_turn + ld a, [wBattleMode] + dec a + jr nz, .failed + ld a, [wBattleMonLevel] + ld b, a + ld a, [wCurPartyLevel] + cp b + jr nc, .run_away + add b + ld c, a + inc c +.loop_enemy + call BattleRandom + cp c + jr nc, .loop_enemy + srl b + srl b + cp b + ; This does the wrong thing. What was + ; probably intended was jr c, .failed + ; The way this is made makes enemy use + ; of Teleport always succeed if able + jr nc, .run_away +.run_away + call UpdateBattleMonInParty + xor a + ld [wNumHits], a + inc a + ld [wForcedSwitch], a + ld [wKickCounter], a + call SetBattleDraw + call BattleCommand_LowerSub + call LoadMoveAnim + ld c, 20 + call DelayFrames + call SetBattleDraw + + ld hl, FledFromBattleText + jp StdBattleTextBox + +; 36804 diff --git a/engine/battle/move_effects/thief.asm b/engine/battle/move_effects/thief.asm new file mode 100644 index 000000000..5397c2bdf --- /dev/null +++ b/engine/battle/move_effects/thief.asm @@ -0,0 +1,116 @@ +BattleCommand_Thief: ; 37492 +; thief + + ld a, [hBattleTurn] + and a + jr nz, .enemy + +; The player needs to be able to steal an item. + + call .playeritem + ld a, [hl] + and a + ret nz + +; The enemy needs to have an item to steal. + + call .enemyitem + ld a, [hl] + and a + ret z + +; Can't steal mail. + + ld [wd265], a + ld d, a + farcall ItemIsMail + ret c + + ld a, [wEffectFailed] + and a + ret nz + + ld a, [wLinkMode] + and a + jr z, .stealenemyitem + + ld a, [wBattleMode] + dec a + ret z + +.stealenemyitem + call .enemyitem + xor a + ld [hl], a + ld [de], a + + call .playeritem + ld a, [wd265] + ld [hl], a + ld [de], a + jr .stole + + +.enemy + +; The enemy can't already have an item. + + call .enemyitem + ld a, [hl] + and a + ret nz + +; The player must have an item to steal. + + call .playeritem + ld a, [hl] + and a + ret z + +; Can't steal mail! + + ld [wd265], a + ld d, a + farcall ItemIsMail + ret c + + ld a, [wEffectFailed] + and a + ret nz + +; If the enemy steals your item, +; it's gone for good if you don't get it back. + + call .playeritem + xor a + ld [hl], a + ld [de], a + + call .enemyitem + ld a, [wd265] + ld [hl], a + ld [de], a + + +.stole + call GetItemName + ld hl, StoleText + jp StdBattleTextBox + + +.playeritem + ld a, 1 + call BattlePartyAttr + ld d, h + ld e, l + ld hl, wBattleMonItem + ret + +.enemyitem + ld a, 1 + call OTPartyAttr + ld d, h + ld e, l + ld hl, wEnemyMonItem + ret +; 37517 diff --git a/engine/battle/move_effects/thunder.asm b/engine/battle/move_effects/thunder.asm new file mode 100644 index 000000000..3705e1a28 --- /dev/null +++ b/engine/battle/move_effects/thunder.asm @@ -0,0 +1,20 @@ +BattleCommand_ThunderAccuracy: ; 37d94 +; thunderaccuracy + + ld a, BATTLE_VARS_MOVE_TYPE + call GetBattleVarAddr + inc hl + ld a, [wBattleWeather] + cp WEATHER_RAIN + jr z, .rain + cp WEATHER_SUN + ret nz + ld [hl], 50 percent + 1 + ret + +.rain + ; Redundant with CheckHit guranteeing hit + ld [hl], 100 percent + ret + +; 37daa diff --git a/engine/battle/move_effects/transform.asm b/engine/battle/move_effects/transform.asm new file mode 100755 index 000000000..5ae7c1511 --- /dev/null +++ b/engine/battle/move_effects/transform.asm @@ -0,0 +1,141 @@ + +BattleCommand_Transform: ; 371cd +; transform + + call ClearLastMove + ld a, BATTLE_VARS_SUBSTATUS5_OPP + call GetBattleVarAddr + bit SUBSTATUS_TRANSFORMED, [hl] + jp nz, BattleEffect_ButItFailed + call CheckHiddenOpponent + jp nz, BattleEffect_ButItFailed + xor a + ld [wNumHits], a + ld [wFXAnimID + 1], a + ld a, $1 + ld [wKickCounter], a + ld a, BATTLE_VARS_SUBSTATUS4 + call GetBattleVarAddr + bit SUBSTATUS_SUBSTITUTE, [hl] + push af + jr z, .mimic_substitute + call CheckUserIsCharging + jr nz, .mimic_substitute + ld a, SUBSTITUTE + call LoadAnim +.mimic_substitute + ld a, BATTLE_VARS_SUBSTATUS5 + call GetBattleVarAddr + set SUBSTATUS_TRANSFORMED, [hl] + call ResetActorDisable + ld hl, wBattleMonSpecies + ld de, wEnemyMonSpecies + ld a, [hBattleTurn] + and a + jr nz, .got_mon_species + ld hl, wEnemyMonSpecies + ld de, wBattleMonSpecies + xor a + ld [wCurMoveNum], a +.got_mon_species + push hl + ld a, [hli] + ld [de], a + inc hl + inc de + inc de + ld bc, NUM_MOVES + call CopyBytes + ld a, [hBattleTurn] + and a + jr z, .mimic_enemy_backup + ld a, [de] + ld [wEnemyBackupDVs], a + inc de + ld a, [de] + ld [wEnemyBackupDVs + 1], a + dec de +.mimic_enemy_backup +; copy DVs + ld a, [hli] + ld [de], a + inc de + ld a, [hli] + ld [de], a + inc de +; move pointer to stats + ld bc, wBattleMonStats - wBattleMonPP + add hl, bc + push hl + ld h, d + ld l, e + add hl, bc + ld d, h + ld e, l + pop hl + ld bc, wBattleMonStructEnd - wBattleMonStats + call CopyBytes +; init the power points + ld bc, wBattleMonMoves - wBattleMonStructEnd + add hl, bc + push de + ld d, h + ld e, l + pop hl + ld bc, wBattleMonPP - wBattleMonStructEnd + add hl, bc + ld b, NUM_MOVES +.pp_loop + ld a, [de] + inc de + and a + jr z, .done_move + cp SKETCH + ld a, 1 + jr z, .done_move + ld a, 5 +.done_move + ld [hli], a + dec b + jr nz, .pp_loop + pop hl + ld a, [hl] + ld [wNamedObjectIndexBuffer], a + call GetPokemonName + ld hl, wEnemyStats + ld de, wPlayerStats + ld bc, 2 * 5 + call BattleSideCopy + ld hl, wEnemyStatLevels + ld de, wPlayerStatLevels + ld bc, 8 + call BattleSideCopy + call _CheckBattleScene + jr c, .mimic_anims + ld a, [hBattleTurn] + and a + ld a, [wPlayerMinimized] + jr z, .got_byte + ld a, [wEnemyMinimized] +.got_byte + and a + jr nz, .mimic_anims + call LoadMoveAnim + jr .after_anim + +.mimic_anims + call BattleCommand_MoveDelay + call BattleCommand_RaiseSubNoAnim +.after_anim + xor a + ld [wNumHits], a + ld [wFXAnimID + 1], a + ld a, $2 + ld [wKickCounter], a + pop af + ld a, SUBSTITUTE + call nz, LoadAnim + ld hl, TransformedText + jp StdBattleTextBox + +; 372c6 diff --git a/engine/battle/move_effects/triple_kick.asm b/engine/battle/move_effects/triple_kick.asm new file mode 100644 index 000000000..cef56a1ae --- /dev/null +++ b/engine/battle/move_effects/triple_kick.asm @@ -0,0 +1,39 @@ +BattleCommand_TripleKick: ; 346b2 +; triplekick + + ld a, [wKickCounter] + ld b, a + inc b + ld hl, wCurDamage + 1 + ld a, [hld] + ld e, a + ld a, [hli] + ld d, a +.next_kick + dec b + ret z + ld a, [hl] + add e + ld [hld], a + ld a, [hl] + adc d + ld [hli], a + +; No overflow. + jr nc, .next_kick + ld a, $ff + ld [hld], a + ld [hl], a + ret + +; 346cd + + +BattleCommand_KickCounter: ; 346cd +; kickcounter + + ld hl, wKickCounter + inc [hl] + ret + +; 346d2 |