Split battle/ into data/ and engine/ components

This commit is contained in:
Remy Oukaour
2017-12-26 17:47:05 -05:00
parent 2f98c2032f
commit b5417fafec
170 changed files with 1790 additions and 1799 deletions

882
engine/battle/ai/items.asm Normal file

File diff suppressed because it is too large Load Diff

221
engine/battle/ai/move.asm Executable file
View File

@@ -0,0 +1,221 @@
AIChooseMove: ; 440ce
; Score each move in EnemyMonMoves starting from Buffer1. Lower is better.
; Pick the move with the lowest score.
; Wildmons attack at random.
ld a, [wBattleMode]
dec a
ret z
ld a, [wLinkMode]
and a
ret nz
; No use picking a move if there's no choice.
farcall CheckEnemyLockedIn
ret nz
; The default score is 20. Unusable moves are given a score of 80.
ld a, 20
ld hl, Buffer1
ld [hli], a
ld [hli], a
ld [hli], a
ld [hl], a
; Don't pick disabled moves.
ld a, [EnemyDisabledMove]
and a
jr z, .CheckPP
ld hl, EnemyMonMoves
ld c, 0
.CheckDisabledMove:
cp [hl]
jr z, .ScoreDisabledMove
inc c
inc hl
jr .CheckDisabledMove
.ScoreDisabledMove:
ld hl, Buffer1
ld b, 0
add hl, bc
ld [hl], 80
; Don't pick moves with 0 PP.
.CheckPP:
ld hl, Buffer1 - 1
ld de, EnemyMonPP
ld b, 0
.CheckMovePP:
inc b
ld a, b
cp EnemyMonMovesEnd - EnemyMonMoves + 1
jr z, .ApplyLayers
inc hl
ld a, [de]
inc de
and $3f
jr nz, .CheckMovePP
ld [hl], 80
jr .CheckMovePP
; Apply AI scoring layers depending on the trainer class.
.ApplyLayers:
ld hl, TrainerClassAttributes + TRNATTR_AI_MOVE_WEIGHTS
; If we have a battle in BattleTower just load the Attributes of the first TrainerClass (Falkner)
; so we have always the same AI, regardless of the loaded class of trainer
ld a, [InBattleTowerBattle]
bit 0, a
jr nz, .battle_tower_skip
ld a, [TrainerClass]
dec a
ld bc, 7 ; Trainer2AI - Trainer1AI
call AddNTimes
.battle_tower_skip
lb bc, CHECK_FLAG, 0
push bc
push hl
.CheckLayer:
pop hl
pop bc
ld a, c
cp 16 ; up to 16 scoring layers
jr z, .DecrementScores
push bc
ld d, BANK(TrainerClassAttributes)
predef FlagPredef
ld d, c
pop bc
inc c
push bc
push hl
ld a, d
and a
jr z, .CheckLayer
ld hl, AIScoringPointers
dec c
ld b, 0
add hl, bc
add hl, bc
ld a, [hli]
ld h, [hl]
ld l, a
ld a, BANK(AIScoring)
call FarCall_hl
jr .CheckLayer
; Decrement the scores of all moves one by one until one reaches 0.
.DecrementScores:
ld hl, Buffer1
ld de, EnemyMonMoves
ld c, EnemyMonMovesEnd - EnemyMonMoves
.DecrementNextScore:
; If the enemy has no moves, this will infinite.
ld a, [de]
inc de
and a
jr z, .DecrementScores
; We are done whenever a score reaches 0
dec [hl]
jr z, .PickLowestScoreMoves
; If we just decremented the fourth move's score, go back to the first move
inc hl
dec c
jr z, .DecrementScores
jr .DecrementNextScore
; In order to avoid bias towards the moves located first in memory, increment the scores
; that were decremented one more time than the rest (in case there was a tie).
; This means that the minimum score will be 1.
.PickLowestScoreMoves:
ld a, c
.move_loop
inc [hl]
dec hl
inc a
cp NUM_MOVES + 1
jr nz, .move_loop
ld hl, Buffer1
ld de, EnemyMonMoves
ld c, NUM_MOVES
; Give a score of 0 to a blank move
.loop2
ld a, [de]
and a
jr nz, .skip_load
ld [hl], a
; Disregard the move if its score is not 1
.skip_load
ld a, [hl]
dec a
jr z, .keep
xor a
ld [hli], a
jr .after_toss
.keep
ld a, [de]
ld [hli], a
.after_toss
inc de
dec c
jr nz, .loop2
; Randomly choose one of the moves with a score of 1
.ChooseMove:
ld hl, Buffer1
call Random
and 3
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
and a
jr z, .ChooseMove
ld [CurEnemyMove], a
ld a, c
ld [CurEnemyMoveNum], a
ret
; 441af
AIScoringPointers: ; 441af
dw AI_Basic
dw AI_Setup
dw AI_Types
dw AI_Offensive
dw AI_Smart
dw AI_Opportunist
dw AI_Aggressive
dw AI_Cautious
dw AI_Status
dw AI_Risky
dw AI_None
dw AI_None
dw AI_None
dw AI_None
dw AI_None
dw AI_None
; 441cf

198
engine/battle/ai/redundant.asm Executable file
View File

@@ -0,0 +1,198 @@
AI_Redundant: ; 2c41a
; Check if move effect c will fail because it's already been used.
; Return z if the move is a good choice.
; Return nz if the move is a bad choice.
ld a, c
ld de, 3
ld hl, .Moves
call IsInArray
jp nc, .NotRedundant
inc hl
ld a, [hli]
ld h, [hl]
ld l, a
jp hl
.Moves: ; 2c42c
dbw EFFECT_DREAM_EATER, .DreamEater
dbw EFFECT_HEAL, .Heal
dbw EFFECT_LIGHT_SCREEN, .LightScreen
dbw EFFECT_MIST, .Mist
dbw EFFECT_FOCUS_ENERGY, .FocusEnergy
dbw EFFECT_CONFUSE, .Confuse
dbw EFFECT_TRANSFORM, .Transform
dbw EFFECT_REFLECT, .Reflect
dbw EFFECT_SUBSTITUTE, .Substitute
dbw EFFECT_LEECH_SEED, .LeechSeed
dbw EFFECT_DISABLE, .Disable
dbw EFFECT_ENCORE, .Encore
dbw EFFECT_SNORE, .Snore
dbw EFFECT_SLEEP_TALK, .SleepTalk
dbw EFFECT_MEAN_LOOK, .MeanLook
dbw EFFECT_NIGHTMARE, .Nightmare
dbw EFFECT_SPIKES, .Spikes
dbw EFFECT_FORESIGHT, .Foresight
dbw EFFECT_PERISH_SONG, .PerishSong
dbw EFFECT_SANDSTORM, .Sandstorm
dbw EFFECT_ATTRACT, .Attract
dbw EFFECT_SAFEGUARD, .Safeguard
dbw EFFECT_RAIN_DANCE, .RainDance
dbw EFFECT_SUNNY_DAY, .SunnyDay
dbw EFFECT_TELEPORT, .Teleport
dbw EFFECT_MORNING_SUN, .MorningSun
dbw EFFECT_SYNTHESIS, .Synthesis
dbw EFFECT_MOONLIGHT, .Moonlight
dbw EFFECT_SWAGGER, .Swagger
dbw EFFECT_FUTURE_SIGHT, .FutureSight
db -1
.LightScreen: ; 2c487
ld a, [EnemyScreens]
bit SCREENS_LIGHT_SCREEN, a
ret
.Mist: ; 2c48d
ld a, [EnemySubStatus4]
bit SUBSTATUS_MIST, a
ret
.FocusEnergy: ; 2c493
ld a, [EnemySubStatus4]
bit SUBSTATUS_FOCUS_ENERGY, a
ret
.Confuse: ; 2c499
ld a, [PlayerSubStatus3]
bit SUBSTATUS_CONFUSED, a
ret nz
ld a, [PlayerScreens]
bit SCREENS_SAFEGUARD, a
ret
.Transform: ; 2c4a5
ld a, [EnemySubStatus5]
bit SUBSTATUS_TRANSFORMED, a
ret
.Reflect: ; 2c4ab
ld a, [EnemyScreens]
bit SCREENS_REFLECT, a
ret
.Substitute: ; 2c4b1
ld a, [EnemySubStatus4]
bit SUBSTATUS_SUBSTITUTE, a
ret
.LeechSeed: ; 2c4b7
ld a, [PlayerSubStatus4]
bit SUBSTATUS_LEECH_SEED, a
ret
.Disable: ; 2c4bd
ld a, [PlayerDisableCount]
and a
ret
.Encore: ; 2c4c2
ld a, [PlayerSubStatus5]
bit SUBSTATUS_ENCORED, a
ret
.Snore:
.SleepTalk: ; 2c4c8
ld a, [EnemyMonStatus]
and SLP
jr z, .Redundant
jr .NotRedundant
.MeanLook: ; 2c4d1
ld a, [EnemySubStatus5]
bit SUBSTATUS_CANT_RUN, a
ret
.Nightmare: ; 2c4d7
ld a, [BattleMonStatus]
and a
jr z, .Redundant
ld a, [PlayerSubStatus1]
bit SUBSTATUS_NIGHTMARE, a
ret
.Spikes: ; 2c4e3
ld a, [PlayerScreens]
bit SCREENS_SPIKES, a
ret
.Foresight: ; 2c4e9
ld a, [PlayerSubStatus1]
bit SUBSTATUS_IDENTIFIED, a
ret
.PerishSong: ; 2c4ef
ld a, [PlayerSubStatus1]
bit SUBSTATUS_PERISH, a
ret
.Sandstorm: ; 2c4f5
ld a, [Weather]
cp WEATHER_SANDSTORM
jr z, .Redundant
jr .NotRedundant
.Attract: ; 2c4fe
farcall CheckOppositeGender
jr c, .Redundant
ld a, [PlayerSubStatus1]
bit SUBSTATUS_IN_LOVE, a
ret
.Safeguard: ; 2c50c
ld a, [EnemyScreens]
bit SCREENS_SAFEGUARD, a
ret
.RainDance: ; 2c512
ld a, [Weather]
cp WEATHER_RAIN
jr z, .Redundant
jr .NotRedundant
.SunnyDay: ; 2c51b
ld a, [Weather]
cp WEATHER_SUN
jr z, .Redundant
jr .NotRedundant
.DreamEater: ; 2c524
ld a, [BattleMonStatus]
and SLP
jr z, .Redundant
jr .NotRedundant
.Swagger: ; 2c52d
ld a, [PlayerSubStatus3]
bit SUBSTATUS_CONFUSED, a
ret
.FutureSight: ; 2c533
ld a, [EnemyScreens]
bit 5, a
ret
.Heal:
.MorningSun:
.Synthesis:
.Moonlight: ; 2c539
farcall AICheckEnemyMaxHP
jr nc, .NotRedundant
.Teleport:
.Redundant: ; 2c541
ld a, 1
and a
ret
.NotRedundant: ; 2c545
xor a
ret

3598
engine/battle/ai/scoring.asm Normal file

File diff suppressed because it is too large Load Diff

672
engine/battle/ai/switch.asm Executable file

File diff suppressed because it is too large Load Diff

435
engine/battle/anim_hp_bar.asm Executable file
View File

@@ -0,0 +1,435 @@
_AnimateHPBar: ; d627
call .IsMaximumMoreThan48Pixels
jr c, .MoreThan48Pixels
call .ComputePixels
.ShortAnimLoop:
push bc
push hl
call ShortAnim_UpdateVariables
pop hl
pop bc
push af
push bc
push hl
call ShortHPBarAnim_UpdateTiles
call HPBarAnim_BGMapUpdate
pop hl
pop bc
pop af
jr nc, .ShortAnimLoop
ret
.MoreThan48Pixels:
call .ComputePixels
.LongAnimLoop:
push bc
push hl
call LongAnim_UpdateVariables
pop hl
pop bc
ret c
push af
push bc
push hl
call LongHPBarAnim_UpdateTiles
call HPBarAnim_BGMapUpdate
pop hl
pop bc
pop af
jr nc, .LongAnimLoop
ret
; d65f
.IsMaximumMoreThan48Pixels: ; d65f
ld a, [wCurHPAnimMaxHP + 1]
and a
jr nz, .player
ld a, [wCurHPAnimMaxHP]
cp 6 * 8
jr nc, .player
and a
ret
.player
scf
ret
; d670
.ComputePixels: ; d670
push hl
ld hl, wCurHPAnimMaxHP
ld a, [hli]
ld e, a
ld a, [hli]
ld d, a
ld a, [hli]
ld c, a
ld a, [hli]
ld b, a
pop hl
call ComputeHPBarPixels
ld a, e
ld [wCurHPBarPixels], a
ld a, [wCurHPAnimNewHP]
ld c, a
ld a, [wCurHPAnimNewHP + 1]
ld b, a
ld a, [wCurHPAnimMaxHP]
ld e, a
ld a, [wCurHPAnimMaxHP + 1]
ld d, a
call ComputeHPBarPixels
ld a, e
ld [wNewHPBarPixels], a
push hl
ld hl, wCurHPAnimOldHP
ld a, [hli]
ld c, a
ld a, [hli]
ld b, a
ld a, [hli]
ld e, a
ld a, [hli]
ld d, a
pop hl
ld a, e
sub c
ld e, a
ld a, d
sbc b
ld d, a
jr c, .negative
ld a, [wCurHPAnimOldHP]
ld [wCurHPAnimLowHP], a
ld a, [wCurHPAnimNewHP]
ld [wCurHPAnimHighHP], a
ld bc, 1
jr .got_direction
.negative
ld a, [wCurHPAnimOldHP]
ld [wCurHPAnimHighHP], a
ld a, [wCurHPAnimNewHP]
ld [wCurHPAnimLowHP], a
ld a, e
xor $ff
inc a
ld e, a
ld a, d
xor $ff
ld d, a
ld bc, -1
.got_direction
ld a, d
ld [wCurHPAnimDeltaHP], a
ld a, e
ld [wCurHPAnimDeltaHP + 1], a
ret
; d6e2
ShortAnim_UpdateVariables: ; d6e2
ld hl, wCurHPBarPixels
ld a, [wNewHPBarPixels]
cp [hl]
jr nz, .not_finished
scf
ret
.not_finished
ld a, c
add [hl]
ld [hl], a
call ShortHPBar_CalcPixelFrame
and a
ret
; d6f5
LongAnim_UpdateVariables: ; d6f5
.loop
ld hl, wCurHPAnimOldHP
ld a, [hli]
ld e, a
ld a, [hli]
ld d, a
ld a, e
cp [hl]
jr nz, .next
inc hl
ld a, d
cp [hl]
jr nz, .next
scf
ret
.next
ld l, e
ld h, d
add hl, bc
ld a, l
ld [wCurHPAnimOldHP], a
ld a, h
ld [wCurHPAnimOldHP + 1], a
push hl
push de
push bc
ld hl, wCurHPAnimMaxHP
ld a, [hli]
ld e, a
ld a, [hli]
ld d, a
ld a, [hli]
ld c, a
ld a, [hli]
ld b, a
; This routine is buggy. The result from ComputeHPBarPixels is stored
; in e. However, the pop de opcode deletes this result before it is even
; used. The game then proceeds as though it never deleted that output.
; To fix, uncomment the line below.
call ComputeHPBarPixels
; ld a, e
pop bc
pop de
pop hl
ld a, e ; Comment or delete this line to fix the above bug.
ld hl, wCurHPBarPixels
cp [hl]
jr z, .loop
ld [hl], a
and a
ret
; d730
ShortHPBarAnim_UpdateTiles: ; d730
call HPBarAnim_UpdateHPRemaining
ld d, $6
ld a, [wWhichHPBar]
and $1
ld b, a
ld a, [wCurHPBarPixels]
ld e, a
ld c, a
push de
call HPBarAnim_RedrawHPBar
pop de
call HPBarAnim_PaletteUpdate
ret
; d749
LongHPBarAnim_UpdateTiles: ; d749
call HPBarAnim_UpdateHPRemaining
ld a, [wCurHPAnimOldHP]
ld c, a
ld a, [wCurHPAnimOldHP + 1]
ld b, a
ld a, [wCurHPAnimMaxHP]
ld e, a
ld a, [wCurHPAnimMaxHP + 1]
ld d, a
call ComputeHPBarPixels
ld c, e
ld d, $6
ld a, [wWhichHPBar]
and $1
ld b, a
push de
call HPBarAnim_RedrawHPBar
pop de
call HPBarAnim_PaletteUpdate
ret
; d771
HPBarAnim_RedrawHPBar: ; d771
ld a, [wWhichHPBar]
cp $2
jr nz, .skip
ld a, 2 * SCREEN_WIDTH
add l
ld l, a
ld a, 0
adc h
ld h, a
.skip
call DrawBattleHPBar
ret
; d784
HPBarAnim_UpdateHPRemaining: ; d784
ld a, [wWhichHPBar]
and a
ret z
cp $1
jr z, .load_15
ld de, SCREEN_WIDTH + 2
jr .loaded_de
.load_15
ld de, SCREEN_WIDTH + 1
.loaded_de
push hl
add hl, de
ld a, " "
ld [hli], a
ld [hli], a
ld [hld], a
dec hl
ld a, [wCurHPAnimOldHP]
ld [StringBuffer2 + 1], a
ld a, [wCurHPAnimOldHP + 1]
ld [StringBuffer2], a
ld de, StringBuffer2
lb bc, 2, 3
call PrintNum
pop hl
ret
; d7b4
HPBarAnim_PaletteUpdate: ; d7b4
ld a, [hCGB]
and a
ret z
ld hl, wCurHPAnimPal
call SetHPPal
ld a, [wCurHPAnimPal]
ld c, a
farcall ApplyHPBarPals
ret
; d7c9
HPBarAnim_BGMapUpdate: ; d7c9
ld a, [hCGB]
and a
jr nz, .cgb
call DelayFrame
call DelayFrame
ret
.cgb
ld a, [wWhichHPBar]
and a
jr z, .load_0
cp $1
jr z, .load_1
ld a, [CurPartyMon]
cp $3
jr nc, .bottom_half_of_screen
ld c, $0
jr .got_third
.bottom_half_of_screen
ld c, $1
.got_third
push af
cp $2
jr z, .skip_delay
cp $5
jr z, .skip_delay
ld a, $2
ld [hBGMapMode], a
ld a, c
ld [hBGMapThird], a
call DelayFrame
.skip_delay
ld a, $1
ld [hBGMapMode], a
ld a, c
ld [hBGMapThird], a
call DelayFrame
pop af
cp $2
jr z, .two_frames
cp $5
jr z, .two_frames
ret
.two_frames
inc c
ld a, $2
ld [hBGMapMode], a
ld a, c
ld [hBGMapThird], a
call DelayFrame
ld a, $1
ld [hBGMapMode], a
ld a, c
ld [hBGMapThird], a
call DelayFrame
ret
.load_0
ld c, $0
jr .finish
.load_1
ld c, $1
.finish
call DelayFrame
ld a, c
ld [hBGMapThird], a
call DelayFrame
ret
; d839
ShortHPBar_CalcPixelFrame: ; d839
ld a, [wCurHPAnimMaxHP]
ld c, a
ld b, 0
ld hl, 0
ld a, [wCurHPBarPixels]
cp 6 * 8
jr nc, .return_max
and a
jr z, .return_zero
call AddNTimes
ld b, 0
; This routine is buggy. If [wCurHPAnimMaxHP] * [wCurHPBarPixels] is divisible
; by 48, the loop runs one extra time. To fix, uncomment the line below.
.loop
ld a, l
sub 6 * 8
ld l, a
ld a, h
sbc $0
ld h, a
; jr z, .done
jr c, .done
inc b
jr .loop
.done
push bc
ld bc, $80
add hl, bc
pop bc
ld a, l
sub 6 * 8
ld l, a
ld a, h
sbc $0
ld h, a
jr c, .no_carry
inc b
.no_carry
ld a, [wCurHPAnimLowHP]
cp b
jr nc, .finish
ld a, [wCurHPAnimHighHP]
cp b
jr c, .finish
ld a, b
.finish
ld [wCurHPAnimOldHP], a
ret
.return_zero
xor a
ld [wCurHPAnimOldHP], a
ret
.return_max
ld a, [wCurHPAnimMaxHP]
ld [wCurHPAnimOldHP], a
ret
; d88c

File diff suppressed because it is too large Load Diff

9511
engine/battle/core.asm Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,79 @@
BattleCommand_Attract: ; 377ce
; attract
ld a, [AttackMissed]
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 FailAttract
; 377f5
CheckOppositeGender: ; 377f5
ld a, MON_SPECIES
call BattlePartyAttr
ld a, [hl]
ld [CurPartySpecies], a
ld a, [CurBattleMon]
ld [CurPartyMon], a
xor a
ld [MonType], a
farcall GetGender
jr c, .genderless_samegender
ld b, 1
jr nz, .got_gender
dec b
.got_gender
push bc
ld a, [TempEnemyMonSpecies]
ld [CurPartySpecies], a
ld hl, EnemyMonDVs
ld a, [EnemySubStatus5]
bit SUBSTATUS_TRANSFORMED, a
jr z, .not_transformed
ld hl, wEnemyBackupDVs
.not_transformed
ld a, [hli]
ld [TempMonDVs], a
ld a, [hl]
ld [TempMonDVs + 1], a
ld a, 3
ld [MonType], 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

View File

@@ -0,0 +1,97 @@
BattleCommand_Curse: ; 37588
; curse
ld de, BattleMonType1
ld bc, PlayerStatLevels
ld a, [hBattleTurn]
and a
jr z, .go
ld de, EnemyMonType1
ld bc, EnemyStatLevels
.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

View File

@@ -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

View File

@@ -0,0 +1,23 @@
BattleCommand_Foresight: ; 376a0
; foresight
ld a, [AttackMissed]
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 FailForesight
; 376c2

View File

@@ -0,0 +1,61 @@
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
MetronomeExcepts: ; 37454
db NO_MOVE
db METRONOME
db STRUGGLE
db SKETCH
db MIMIC
db COUNTER
db MIRROR_COAT
db PROTECT
db DETECT
db ENDURE
db DESTINY_BOND
db SLEEP_TALK
db THIEF
db -1
; 37462

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,40 @@
BattleCommand_PerishSong: ; 376c2
; perishsong
ld hl, PlayerSubStatus1
ld de, EnemySubStatus1
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 [PlayerPerishCount], a
.enemy
ld a, [de]
bit SUBSTATUS_PERISH, a
jr nz, .done
set SUBSTATUS_PERISH, a
ld [de], a
ld a, 4
ld [EnemyPerishCount], a
.done
call AnimateCurrentMove
ld hl, StartPerishText
jp StdBattleTextBox
.failed
call AnimateFailedMove
jp PrintButItFailed
; 376f8

View File

@@ -0,0 +1,93 @@
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, [AttackMissed]
and a
jp nz, AnimateFailedMove
push bc
call BattleRandom
ld b, a
ld hl, .PresentPower
ld c, 0
.next
ld a, [hli]
cp $ff
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
.PresentPower:
db 40 percent, 40
db 70 percent + 1, 80
db 80 percent, 120
db $ff
; 3790e

View File

@@ -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, PlayerProtectCount
ld a, [hBattleTurn]
and a
jr z, .asm_37637
ld de, EnemyProtectCount
.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

View File

@@ -0,0 +1,99 @@
MAX_ROLLOUT_COUNT EQU 5
BattleCommand_CheckCurl: ; 37718
; checkcurl
ld de, PlayerRolloutCount
ld a, [hBattleTurn]
and a
jr z, .ok
ld de, EnemyRolloutCount
.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, PlayerRolloutCount
ld a, [hBattleTurn]
and a
jr z, .got_rollout_count
ld hl, EnemyRolloutCount
.got_rollout_count
ld a, [hl]
and a
jr nz, .skip_set_rampage
ld a, 1
ld [wSomeoneIsRampaging], a
.skip_set_rampage
ld a, [AttackMissed]
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, CurDamage + 1
sla [hl]
dec hl
rl [hl]
jr nc, .loop
ld a, $ff
ld [hli], a
ld [hl], a
.done_damage
ret
; 37791

Some files were not shown because too many files have changed in this diff Show More