From 10211cc461b35140c815e18e95f7070eb0dcc586 Mon Sep 17 00:00:00 2001 From: xCrystal Date: Wed, 1 Apr 2015 17:03:05 +0200 Subject: Rename battle files and split move effects Part 5 15.asm, 16.asm, 1a.asm, 1c.asm --- engine/battle/15.asm | 372 -------------- engine/battle/16.asm | 238 --------- engine/battle/1a.asm | 43 -- engine/battle/1c.asm | 905 ----------------------------------- engine/battle/battle_transitions.asm | 815 +++++++++++++++++++++++++++++++ engine/battle/common_text.asm | 238 +++++++++ engine/battle/decrement_pp.asm | 43 ++ engine/battle/experience.asm | 372 ++++++++++++++ engine/battle/ghost_marowak_anim.asm | 89 ++++ main.asm | 9 +- 10 files changed, 1562 insertions(+), 1562 deletions(-) delete mode 100755 engine/battle/15.asm delete mode 100755 engine/battle/16.asm delete mode 100755 engine/battle/1a.asm delete mode 100755 engine/battle/1c.asm create mode 100644 engine/battle/battle_transitions.asm create mode 100644 engine/battle/common_text.asm create mode 100644 engine/battle/decrement_pp.asm create mode 100644 engine/battle/experience.asm create mode 100644 engine/battle/ghost_marowak_anim.asm diff --git a/engine/battle/15.asm b/engine/battle/15.asm deleted file mode 100755 index 9bd67654..00000000 --- a/engine/battle/15.asm +++ /dev/null @@ -1,372 +0,0 @@ -GainExperience: ; 5524f (15:524f) - ld a, [wLinkState] - cp LINK_STATE_BATTLING - ret z ; return if link battle - call DivideExpDataByNumMonsGainingExp - ld hl, wPartyMon1 - xor a - ld [wWhichPokemon], a -.partyMonLoop ; loop over each mon and add gained exp - inc hl - ld a, [hli] - or [hl] ; is mon's HP 0? - jp z, .nextMon ; if so, go to next mon - push hl - ld hl, wPartyGainExpFlags - ld a, [wWhichPokemon] - ld c, a - ld b, $2 - predef FlagActionPredef - ld a, c - and a ; is mon's gain exp flag set? - pop hl - jp z, .nextMon ; if mon's gain exp flag not set, go to next mon - ld de, (wPartyMon1HPExp + 1) - (wPartyMon1HP + 1) - add hl, de - ld d, h - ld e, l - ld hl, wEnemyMonBaseStats - ld c, $5 -.gainStatExpLoop - ld a, [hli] - ld b, a ; enemy mon base stat - ld a, [de] ; stat exp - add b ; add enemy mon base state to stat exp - ld [de], a - jr nc, .nextBaseStat -; if there was a carry, increment the upper byte - dec de - ld a, [de] - inc a - jr z, .maxStatExp ; jump if the value overflowed - ld [de], a - inc de - jr .nextBaseStat -.maxStatExp ; if the upper byte also overflowed, then we have hit the max stat exp - ld a, $ff - ld [de], a - inc de - ld [de], a -.nextBaseStat - dec c - jr z, .asm_552a1 - inc de - inc de - jr .gainStatExpLoop -.asm_552a1 - xor a - ld [H_MULTIPLICAND], a - ld [H_MULTIPLICAND + 1], a - ld a, [wEnemyMonBaseExp] - ld [H_MULTIPLICAND + 2], a - ld a, [wEnemyMonLevel] - ld [H_MULTIPLIER], a - call Multiply - ld a, 7 - ld [H_DIVISOR], a - ld b, 4 - call Divide - ld hl, -((wPartyMon1HPExp + 1) - wPartyMon1OTID + 4 * 2) - add hl, de - ld b, [hl] ; party mon OTID - inc hl - ld a, [wPlayerID] - cp b - jr nz, .tradedMon - ld b, [hl] - ld a, [wPlayerID + 1] - cp b - ld a, $0 - jr z, .next -.tradedMon - call BoostExp ; traded mon exp boost - ld a, $1 -.next - ld [wGainBoostedExp], a - ld a, [W_ISINBATTLE] - dec a ; is it a trainer battle? - call nz, BoostExp ; if so, boost exp - inc hl - inc hl - inc hl -; add the gained exp to the party mon's exp - ld b, [hl] - ld a, [H_QUOTIENT + 3] - ld [wcf4c], a - add b - ld [hld], a - ld b, [hl] - ld a, [H_QUOTIENT + 2] - ld [wcf4b], a - adc b - ld [hl], a - jr nc, .noCarry - dec hl - inc [hl] - inc hl -.noCarry -; calculate exp for the mon at max level, and cap the exp at that value - inc hl - push hl - ld a, [wWhichPokemon] - ld c, a - ld b, 0 - ld hl, wPartySpecies - add hl, bc - ld a, [hl] ; species - ld [wd0b5], a - call GetMonHeader - ld d, MAX_LEVEL - callab CalcExperience ; get max exp -; compare max exp with current exp - ld a, [$ff96] - ld b, a - ld a, [$ff97] - ld c, a - ld a, [$ff98] - ld d, a - pop hl - ld a, [hld] - sub d - ld a, [hld] - sbc c - ld a, [hl] - sbc b - jr c, .next2 -; the mon's exp is greater than the max exp, so overwrite it with the max exp - ld a, b - ld [hli], a - ld a, c - ld [hli], a - ld a, d - ld [hld], a - dec hl -.next2 - push hl - ld a, [wWhichPokemon] - ld hl, wPartyMonNicks - call GetPartyMonName - ld hl, GainedText - call PrintText - xor a ; party mon data - ld [wcc49], a - call LoadMonData - pop hl - ld bc, wPartyMon1Level - wPartyMon1Exp - add hl, bc - push hl - callba CalcLevelFromExperience - pop hl - ld a, [hl] ; current level - cp d - jp z, .nextMon ; if level didn't change, go to next mon - ld a, [W_CURENEMYLVL] - push af - push hl - ld a, d - ld [W_CURENEMYLVL], a - ld [hl], a - ld bc, wPartyMon1Species - wPartyMon1Level - add hl, bc - ld a, [hl] ; species - ld [wd0b5], a - ld [wd11e], a - call GetMonHeader - ld bc, (wPartyMon1MaxHP + 1) - wPartyMon1Species - add hl, bc - push hl - ld a, [hld] - ld c, a - ld b, [hl] - push bc ; push max HP (from before levelling up) - ld d, h - ld e, l - ld bc, (wPartyMon1HPExp - 1) - wPartyMon1MaxHP - add hl, bc - ld b, $1 ; consider stat exp when calculating stats - call CalcStats - pop bc ; pop max HP (from before levelling up) - pop hl - ld a, [hld] - sub c - ld c, a - ld a, [hl] - sbc b - ld b, a ; bc = difference between old max HP and new max HP after levelling - ld de, (wPartyMon1HP + 1) - wPartyMon1MaxHP - add hl, de -; add to the current HP the amount of max HP gained when levelling - ld a, [hl] ; wPartyMon1HP + 1 - add c - ld [hld], a - ld a, [hl] ; wPartyMon1HP + 1 - adc b - ld [hl], a ; wPartyMon1HP - ld a, [wPlayerMonNumber] - ld b, a - ld a, [wWhichPokemon] - cp b ; is the current mon in battle? - jr nz, .printGrewLevelText -; current mon is in battle - ld de, wBattleMonHP -; copy party mon HP to battle mon HP - ld a, [hli] - ld [de], a - inc de - ld a, [hl] - ld [de], a -; copy other stats from party mon to battle mon - ld bc, wPartyMon1Level - (wPartyMon1HP + 1) - add hl, bc - push hl - ld de, wBattleMonLevel - ld bc, $b ; size of stats - call CopyData - pop hl - ld a, [W_PLAYERBATTSTATUS3] - bit 3, a ; is the mon transformed? - jr nz, .recalcStatChanges -; the mon is not transformed, so update the unmodified stats - ld de, wPlayerMonUnmodifiedLevel - ld bc, $b - call CopyData -.recalcStatChanges - xor a - ld [wd11e], a - callab CalculateModifiedStats - callab ApplyBurnAndParalysisPenaltiesToPlayer - callab ApplyBadgeStatBoosts - callab DrawPlayerHUDAndHPBar - callab PrintEmptyString - call SaveScreenTilesToBuffer1 -.printGrewLevelText - ld hl, GrewLevelText - call PrintText - xor a ; party mon data - ld [wcc49], a - call LoadMonData - ld d, $1 - callab PrintStatsBox - call WaitForTextScrollButtonPress - call LoadScreenTilesFromBuffer1 - xor a - ld [wcc49], a - ld a, [wd0b5] - ld [wd11e], a - predef LearnMoveFromLevelUp - ld hl, wccd3 - ld a, [wWhichPokemon] - ld c, a - ld b, $1 - predef FlagActionPredef - pop hl - pop af - ld [W_CURENEMYLVL], a - -.nextMon - ld a, [wPartyCount] - ld b, a - ld a, [wWhichPokemon] - inc a - cp b - jr z, .done - ld [wWhichPokemon], a - ld bc, wPartyMon2 - wPartyMon1 - ld hl, wPartyMon1 - call AddNTimes - jp .partyMonLoop -.done - ld hl, wPartyGainExpFlags - xor a - ld [hl], a ; clear gain exp flags - ld a, [wPlayerMonNumber] - ld c, a - ld b, $1 - push bc - predef FlagActionPredef ; set the gain exp flag for the mon that is currently out - ld hl, wPartyFoughtCurrentEnemyFlags - xor a - ld [hl], a - pop bc - predef_jump FlagActionPredef ; set the fought current enemy flag for the mon that is currently out - -; divide enemy base stats, catch rate, and base exp by the number of mons gaining exp -DivideExpDataByNumMonsGainingExp: ; 5546c (15:546c) - ld a, [wPartyGainExpFlags] - ld b, a - xor a - ld c, $8 - ld d, $0 -.countSetBitsLoop ; loop to count set bits in wPartyGainExpFlags - xor a - srl b - adc d - ld d, a - dec c - jr nz, .countSetBitsLoop - cp $2 - ret c ; return if only one mon is gaining exp - ld [wd11e], a ; store number of mons gaining exp - ld hl, wEnemyMonBaseStats - ld c, $7 -.divideLoop - xor a - ld [H_DIVIDEND], a - ld a, [hl] - ld [H_DIVIDEND + 1], a - ld a, [wd11e] - ld [H_DIVISOR], a - ld b, $2 - call Divide ; divide value by number of mons gaining exp - ld a, [H_QUOTIENT + 3] - ld [hli], a - dec c - jr nz, .divideLoop - ret - -; multiplies exp by 1.5 -BoostExp: ; 5549f (15:549f) - ld a, [H_QUOTIENT + 2] - ld b, a - ld a, [H_QUOTIENT + 3] - ld c, a - srl b - rr c - add c - ld [H_QUOTIENT + 3], a - ld a, [H_QUOTIENT + 2] - adc b - ld [H_QUOTIENT + 2], a - ret - -GainedText: ; 554b2 (15:54b2) - TX_FAR _GainedText - db $08 ; asm - ld a, [wBoostExpByExpAll] - ld hl, WithExpAllText - and a - ret nz - ld hl, ExpPointsText - ld a, [wGainBoostedExp] - and a - ret z - ld hl, BoostedText - ret - -WithExpAllText: ; 554cb (15:54cb) - TX_FAR _WithExpAllText - db $08 ; asm - ld hl, ExpPointsText - ret - -BoostedText: ; 554d4 (15:54d4) - TX_FAR _BoostedText - -ExpPointsText: ; 554d8 (15:54d8) - TX_FAR _ExpPointsText - db "@" - -GrewLevelText: ; 554dd (15:54dd) - TX_FAR _GrewLevelText - db $0b - db "@" diff --git a/engine/battle/16.asm b/engine/battle/16.asm deleted file mode 100755 index 9a00bd98..00000000 --- a/engine/battle/16.asm +++ /dev/null @@ -1,238 +0,0 @@ -PrintBeginningBattleText: ; 58d99 (16:4d99) - ld a, [W_ISINBATTLE] ; W_ISINBATTLE - dec a - jr nz, .trainerBattle - ld a, [W_CURMAP] ; W_CURMAP - cp POKEMONTOWER_3 - jr c, .notPokemonTower - cp LAVENDER_HOUSE_1 - jr c, .pokemonTower -.notPokemonTower - ld a, [wEnemyMonSpecies2] - call PlayCry - ld hl, WildMonAppearedText - ld a, [W_MOVEMISSED] ; W_MOVEMISSED - and a - jr z, .notFishing - ld hl, HookedMonAttackedText -.notFishing - jr .wildBattle -.trainerBattle - call .playSFX - ld c, $14 - call DelayFrames - ld hl, TrainerWantsToFightText -.wildBattle - push hl - callab DrawAllPokeballs - pop hl - call PrintText - jr .done -.pokemonTower - ld b, SILPH_SCOPE - call IsItemInBag - ld a, [wEnemyMonSpecies2] - ld [wcf91], a - cp MAROWAK - jr z, .isMarowak - ld a, b - and a - jr z, .noSilphScope - callab LoadEnemyMonData - jr .notPokemonTower -.noSilphScope - ld hl, EnemyAppearedText - call PrintText - ld hl, GhostCantBeIDdText - call PrintText - jr .done -.isMarowak - ld a, b - and a - jr z, .noSilphScope - ld hl, EnemyAppearedText - call PrintText - ld hl, UnveiledGhostText - call PrintText - callab LoadEnemyMonData - callab MarowakAnim - ld hl, WildMonAppearedText - call PrintText - -.playSFX - xor a - ld [wc0f1], a - ld a, $80 - ld [wc0f2], a - ld a, (SFX_08_77 - SFX_Headers_08) / 3 - call PlaySound - jp WaitForSoundToFinish -.done - ret - -WildMonAppearedText: ; 58e3b (16:4e3b) - TX_FAR _WildMonAppearedText - db "@" - -HookedMonAttackedText: ; 58e40 (16:4e40) - TX_FAR _HookedMonAttackedText - db "@" - -EnemyAppearedText: ; 58e45 (16:4e45) - TX_FAR _EnemyAppearedText - db "@" - -TrainerWantsToFightText: ; 58e4a (16:4e4a) - TX_FAR _TrainerWantsToFightText - db "@" - -UnveiledGhostText: ; 58e4f (16:4e4f) - TX_FAR _UnveiledGhostText - db "@" - -GhostCantBeIDdText: ; 58e54 (16:4e54) - TX_FAR _GhostCantBeIDdText - db "@" - -PrintSendOutMonMessage: ; 58e59 (16:4e59) - ld hl, wEnemyMonHP - ld a, [hli] - or [hl] - ld hl, GoText - jr z, .printText - xor a - ld [H_MULTIPLICAND], a - ld hl, wEnemyMonHP - ld a, [hli] - ld [wcce3], a - ld [H_MULTIPLICAND + 1], a - ld a, [hl] - ld [wcce4], a - ld [H_MULTIPLICAND + 2], a - ld a, 25 - ld [H_MULTIPLIER], a - call Multiply - ld hl, wEnemyMonMaxHP - ld a, [hli] - ld b, [hl] - srl a - rr b - srl a - rr b - ld a, b - ld b, $4 - ld [H_DIVISOR], a ; enemy mon max HP divided by 4 - call Divide - ld a, [H_QUOTIENT + 3] ; a = (enemy mon current HP * 25) / (enemy max HP / 4); this approximates the current percentage of max HP - ld hl, GoText ; 70% or greater - cp 70 - jr nc, .printText - ld hl, DoItText ; 40% - 69% - cp 40 - jr nc, .printText - ld hl, GetmText ; 10% - 39% - cp 10 - jr nc, .printText - ld hl, EnemysWeakText ; 0% - 9% -.printText - jp PrintText - -GoText: ; 58eae (16:4eae) - TX_FAR _GoText - db $08 ; asm - jr PrintPlayerMon1Text - -DoItText: ; 58eb5 (16:4eb5) - TX_FAR _DoItText - db $08 ; asm - jr PrintPlayerMon1Text - -GetmText: ; 58ebc (16:4ebc) - TX_FAR _GetmText - db $08 ; asm - jr PrintPlayerMon1Text - -EnemysWeakText: ; 58ec3 (16:4ec3) - TX_FAR _EnemysWeakText - db $08 ; asm - -PrintPlayerMon1Text: - ld hl, PlayerMon1Text - ret - -PlayerMon1Text: ; 58ecc (16:4ecc) - TX_FAR _PlayerMon1Text - db "@" - -RetreatMon: ; 58ed1 (16:4ed1) - ld hl, PlayerMon2Text - jp PrintText - -PlayerMon2Text: ; 58ed7 (16:4ed7) - TX_FAR _PlayerMon2Text - db $08 ; asm - push de - push bc - ld hl, wEnemyMonHP + 1 - ld de, wcce4 - ld b, [hl] - dec hl - ld a, [de] - sub b - ld [$ff98], a - dec de - ld b, [hl] - ld a, [de] - sbc b - ld [$ff97], a - ld a, $19 - ld [H_POWEROFTEN], a - call Multiply - ld hl, wEnemyMonMaxHP - ld a, [hli] - ld b, [hl] - srl a - rr b - srl a - rr b - ld a, b - ld b, $4 - ld [H_POWEROFTEN], a - call Divide - pop bc - pop de - ld a, [$ff98] - ld hl, EnoughText - and a - ret z - ld hl, ComeBackText - cp $1e - ret c - ld hl, OKExclamationText - cp $46 - ret c - ld hl, GoodText - ret - -EnoughText: ; 58f25 (16:4f25) - TX_FAR _EnoughText - db $08 ; asm - jr PrintComeBackText - -OKExclamationText: ; 58f2c (16:4f2c) - TX_FAR _OKExclamationText - db $08 ; asm - jr PrintComeBackText - -GoodText: ; 58f33 (16:4f33) - TX_FAR _GoodText - db $08 ; asm - jr PrintComeBackText - -PrintComeBackText: ; 58f3a (16:4f3a) - ld hl, ComeBackText - ret - -ComeBackText: ; 58f3e (16:4f3e) - TX_FAR _ComeBackText - db "@" diff --git a/engine/battle/1a.asm b/engine/battle/1a.asm deleted file mode 100755 index ecf5040b..00000000 --- a/engine/battle/1a.asm +++ /dev/null @@ -1,43 +0,0 @@ -DecrementPP: ; 68000 (1a:4000) -; after using a move, decrement pp in battle and (if not transformed?) in party - ld a, [de] - cp a, STRUGGLE - ret z ; if the pokemon is using "struggle", there's nothing to do - ; we don't decrement PP for "struggle" - ld hl, W_PLAYERBATTSTATUS1 - ld a, [hli] ; load the W_PLAYERBATTSTATUS1 pokemon status flags and increment hl to load the - ; W_PLAYERBATTSTATUS2 status flags later - and a, (1 << StoringEnergy) | (1 << ThrashingAbout) | (1 << AttackingMultipleTimes) - ret nz ; if any of these statuses are true, don't decrement PP - bit UsingRage, [hl] - ret nz ; don't decrement PP either if Pokemon is using Rage - ld hl, wBattleMonPP ; PP of first move (in battle) - -; decrement PP in the battle struct - call .DecrementPP - -; decrement PP in the party struct - ld a, [W_PLAYERBATTSTATUS3] - bit Transformed, a - ret nz ; Return if transformed. Pokemon Red stores the "current pokemon's" PP - ; separately from the "Pokemon in your party's" PP. This is - ; duplication -- in all cases *other* than Pokemon with Transform. - ; Normally, this means we have to go on and make the same - ; modification to the "party's pokemon" PP that we made to the - ; "current pokemon's" PP. But, if we're dealing with a Transformed - ; Pokemon, it has separate PP for the move set that it copied from - ; its opponent, which is *not* the same as its real PP as part of your - ; party. So we return, and don't do that part. - - ld hl, wPartyMon1PP ; PP of first move (in party) - ld a, [wPlayerMonNumber] ; which mon in party is active - ld bc, wPartyMon2 - wPartyMon1 - call AddNTimes ; calculate address of the mon to modify -.DecrementPP - ld a, [wPlayerMoveListIndex] ; which move (0, 1, 2, 3) did we use? - ld c, a - ld b, 0 - add hl ,bc ; calculate the address in memory of the PP we need to decrement - ; based on the move chosen. - dec [hl] ; Decrement PP - ret diff --git a/engine/battle/1c.asm b/engine/battle/1c.asm deleted file mode 100755 index ce0296f7..00000000 --- a/engine/battle/1c.asm +++ /dev/null @@ -1,905 +0,0 @@ -MarowakAnim: ; 708ca (1c:48ca) -; animate the ghost being unveiled as a Marowak - ld a, $e4 - ld [rOBP1], a - call CopyMonPicFromBGToSpriteVRAM ; cover the BG ghost pic with a sprite ghost pic that looks the same -; now that the ghost pic is being displayed using sprites, clear the ghost pic from the BG tilemap - hlCoord 12, 0 - ld bc, $707 - call ClearScreenArea - call Delay3 - xor a - ld [H_AUTOBGTRANSFERENABLED], a ; disable BG transfer so we don't see the Marowak too soon -; replace ghost pic with Marowak in BG - ld a, MAROWAK - ld [wHPBarMaxHP], a - ld a, $1 - ld [H_WHOSETURN], a - callab Func_79793 - ; alternate between black and light grey 8 times. - ; this makes the ghost's body appear to flash - ld d, $80 - call FlashSprite8Times -.fadeOutGhostLoop - ld c, 10 - call DelayFrames - ld a, [rOBP1] - sla a - sla a - ld [rOBP1], a - jr nz, .fadeOutGhostLoop - call ClearSprites - call CopyMonPicFromBGToSpriteVRAM ; copy Marowak pic from BG to sprite VRAM - ld b, $e4 -.fadeInMarowakLoop - ld c, 10 - call DelayFrames - ld a, [rOBP1] - srl b - rra - srl b - rra - ld [rOBP1], a - ld a, b - and a - jr nz, .fadeInMarowakLoop - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a ; enable BG transfer so the BG Marowak pic will be visible after the sprite one is cleared - call Delay3 - jp ClearSprites - -; copies a mon pic's from background VRAM to sprite VRAM and sets up OAM -CopyMonPicFromBGToSpriteVRAM: ; 7092a (1c:492a) - ld de, vFrontPic - ld hl, vSprites - ld bc, 7 * 7 - call CopyVideoData - ld a, $10 - ld [W_BASECOORDY], a - ld a, $70 - ld [W_BASECOORDX], a - ld hl, wOAMBuffer - ld bc, $606 - ld d, $8 -.oamLoop - push bc - ld a, [W_BASECOORDY] - ld e, a -.oamInnerLoop - ld a, e - add $8 - ld e, a - ld [hli], a - ld a, [W_BASECOORDX] - ld [hli], a - ld a, d - ld [hli], a - ld a, $10 ; use OBP1 - ld [hli], a - inc d - dec c - jr nz, .oamInnerLoop - inc d - ld a, [W_BASECOORDX] - add $8 - ld [W_BASECOORDX], a - pop bc - dec b - jr nz, .oamLoop - ret - -BattleTransition: ; 7096d (1c:496d) - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - call Delay3 - xor a - ld [hWY], a - dec a - ld [wUpdateSpritesEnabled], a - call DelayFrame - ld hl, wSpriteStateData1 + 2 - ld a, [H_DOWNARROWBLINKCNT2] - ld c, a - ld b, $0 - ld de, $10 -.loop1 - ld a, [hl] - cp $ff - jr z, .skip1 - inc b -.skip1 - add hl, de - dec c - jr nz, .loop1 - ld hl, wOAMBuffer + $10 - ld c, $9 -.loop2 - ld a, b - swap a - cp l - jr z, .skip2 - push hl - push bc - ld bc, $10 - xor a - call FillMemory - pop bc - pop hl -.skip2 - ld de, $10 - add hl, de - dec c - jr nz, .loop2 - call Delay3 - call LoadBattleTransitionTile - ld bc, $0 - ld a, [wLinkState] - cp LINK_STATE_BATTLING - jr z, .linkBattle - call GetBattleTransitionID_WildOrTrainer - call GetBattleTransitionID_CompareLevels - call GetBattleTransitionID_IsDungeonMap -.linkBattle - ld hl, BattleTransitions - add hl, bc - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a - jp [hl] - -; the three GetBattleTransitionID functions set the first -; three bits of c, which determines what transition animation -; to play at the beginning of a battle -; bit 0: set if trainer battle -; bit 1: set if enemy is at least 3 levels higher than player -; bit 2: set if dungeon map -BattleTransitions: ; 709d2 (1c:49d2) - dw BattleTransition_DoubleCircle ; %000 - dw BattleTransition_Spiral ; %001 - dw BattleTransition_Circle ; %010 - dw BattleTransition_Spiral ; %011 - dw BattleTransition_HorizontalStripes ; %100 - dw BattleTransition_Shrink ; %101 - dw BattleTransition_VerticalStripes ; %110 - dw BattleTransition_Split ; %111 - -GetBattleTransitionID_WildOrTrainer: ; 709e2 (1c:49e2) - ld a, [W_CUROPPONENT] - cp $c8 - jr nc, .trainer - res 0, c - ret -.trainer - set 0, c - ret - -GetBattleTransitionID_CompareLevels: ; 709ef (1c:49ef) - ld hl, wPartyMon1HP -.faintedLoop - ld a, [hli] - or [hl] - jr nz, .notFainted - ld de, wPartyMon2 - (wPartyMon1 + 1) - add hl, de - jr .faintedLoop -.notFainted - ld de, wPartyMon1Level - (wPartyMon1HP + 1) - add hl, de - ld a, [hl] - add $3 - ld e, a - ld a, [W_CURENEMYLVL] - sub e - jr nc, .highLevelEnemy - res 1, c - ld a, $1 - ld [wcd47], a - ret -.highLevelEnemy - set 1, c - xor a - ld [wcd47], a - ret - -; fails to recognize VICTORY_ROAD_2, VICTORY_ROAD_3, all ROCKET_HIDEOUT maps, -; MANSION_1, SEAFOAM_ISLANDS_[2-5], POWER_PLANT, DIGLETTS_CAVE -; and SILPH_CO_[9-11]F as dungeon maps -GetBattleTransitionID_IsDungeonMap: ; 70a19 (1c:4a19) - ld a, [W_CURMAP] - ld e, a - ld hl, DungeonMaps1 -.loop1 - ld a, [hli] - cp $ff - jr z, .noMatch1 - cp e - jr nz, .loop1 -.match - set 2, c - ret -.noMatch1 - ld hl, DungeonMaps2 -.loop2 - ld a, [hli] - cp $ff - jr z, .noMatch2 - ld d, a - ld a, [hli] - cp e - jr c, .loop2 - ld a, e - cp d - jr nc, .match -.noMatch2 - res 2, c - ret - -; GetBattleTransitionID_IsDungeonMap checks if W_CURMAP -; is equal to one of these maps -DungeonMaps1: ; 70a3f (1c:4a3f) - db VIRIDIAN_FOREST - db ROCK_TUNNEL_1 - db SEAFOAM_ISLANDS_1 - db ROCK_TUNNEL_2 - db $FF - -; GetBattleTransitionID_IsDungeonMap checks if W_CURMAP -; is in between or equal to each pair of maps -DungeonMaps2: ; 70a44 (1c:4a44) - ; all MT_MOON maps - db MT_MOON_1 - db MT_MOON_3 - - ; all SS_ANNE maps, VICTORY_ROAD_1, LANCES_ROOM, and HALL_OF_FAME - db SS_ANNE_1 - db HALL_OF_FAME - - ; all POKEMONTOWER maps and Lavender Town buildings - db LAVENDER_POKECENTER - db LAVENDER_HOUSE_2 - - ; SILPH_CO_[2-8]F, MANSION[2-4], SAFARI_ZONE, and UNKNOWN_DUNGEON maps, - ; except for SILPH_CO_1F - db SILPH_CO_2F - db UNKNOWN_DUNGEON_1 - db $FF - -LoadBattleTransitionTile: ; 70a4d (1c:4a4d) - ld hl, vChars1 + $7f0 - ld de, BattleTransitionTile - ld bc, (BANK(BattleTransitionTile) << 8) + $01 - jp CopyVideoData - -BattleTransitionTile: ; 70a59 (1c:4a59) - INCBIN "gfx/battle_transition.2bpp" - -BattleTransition_BlackScreen: ; 70a69 (1c:4a69) - ld a, $ff - ld [rBGP], a - ld [rOBP0], a - ld [rOBP1], a - ret - -; for non-dungeon trainer battles -; called regardless of mon levels, but does an -; outward spiral if enemy is at least 3 levels -; higher than player and does an inward spiral otherwise -BattleTransition_Spiral: ; 70a72 (1c:4a72) - ld a, [wcd47] - and a - jr z, .outwardSpiral - call BattleTransition_InwardSpiral - jr .done -.outwardSpiral - hlCoord 10, 10 - ld a, $3 - ld [wd09f], a - ld a, l - ld [wd09b], a - ld a, h - ld [wd09a], a - ld b, $78 -.loop1 - ld c, $3 -.loop2 - push bc - call BattleTransition_OutwardSpiral_ - pop bc - dec c - jr nz, .loop2 - call DelayFrame - dec b - jr nz, .loop1 -.done - call BattleTransition_BlackScreen - xor a - ld [wd09b], a - ld [wd09a], a - ret - -BattleTransition_InwardSpiral: ; 70aaa (1c:4aaa) - ld a, $7 - ld [wWhichTrade], a - ld hl, wTileMap - ld c, $11 - ld de, $14 - call BattleTransition_InwardSpiral_ - inc c - jr .skip -.loop - ld de, $14 - call BattleTransition_InwardSpiral_ -.skip - inc c - ld de, $1 - call BattleTransition_InwardSpiral_ - dec c - dec c - ld de, $ffec - call BattleTransition_InwardSpiral_ - inc c - ld de, rIE - call BattleTransition_InwardSpiral_ - dec c - dec c - ld a, c - and a - jr nz, .loop - ret - -BattleTransition_InwardSpiral_: ; 70ae0 (1c:4ae0) - push bc -.loop - ld [hl], $ff - add hl, de - push bc - ld a, [wWhichTrade] - dec a - jr nz, .skip - call BattleTransition_TransferDelay3 - ld a, $7 -.skip - ld [wWhichTrade], a - pop bc - dec c - jr nz, .loop - pop bc - ret - -BattleTransition_OutwardSpiral_: ; 70af9 (1c:4af9) - ld bc, $ffec - ld de, $14 - ld a, [wd09b] - ld l, a - ld a, [wd09a] - ld h, a - ld a, [wd09f] - cp $0 - jr z, .zero - cp $1 - jr z, .one - cp $2 - jr z, .two - cp $3 - jr z, .three -.done1 - ld [hl], $ff -.done2_ - ld a, l - ld [wd09b], a - ld a, h - ld [wd09a], a - ret -.zero - dec hl - ld a, [hl] - cp $ff - jr nz, .done2 - inc hl - add hl, bc - jr .done1 -.one - add hl, de - ld a, [hl] - cp $ff - jr nz, .done2 - add hl, bc - dec hl - jr .done1 -.two - inc hl - ld a, [hl] - cp $ff - jr nz, .done2 - dec hl - add hl, de - jr .done1 -.three - add hl, bc - ld a, [hl] - cp $ff - jr nz, .done2 - add hl, de - inc hl - jr .done1 -.done2 - ld [hl], $ff - ld a, [wd09f] - inc a - cp $4 - jr nz, .skip - xor a -.skip - ld [wd09f], a - jr .done2_ - -FlashScreen: -BattleTransition_FlashScreen_: ; 70b5d (1c:4b5d) - ld hl, BattleTransition_FlashScreenPalettes -.loop - ld a, [hli] - cp $1 - jr z, .done - ld [rBGP], a - ld c, $2 - call DelayFrames - jr .loop -.done - dec b - jr nz, BattleTransition_FlashScreen_ - ret - -BattleTransition_FlashScreenPalettes: ; 70b72 (1c:4b72) - db $F9,$FE,$FF,$FE,$F9,$E4,$90,$40,$00,$40,$90,$E4 - db $01 ; terminator - -; used for low level trainer dungeon battles -BattleTransition_Shrink: ; 70b7f (1c:4b7f) - ld c, $9 -.loop - push bc - xor a - ld [H_AUTOBGTRANSFERENABLED], a - hlCoord 0, 7 - deCoord 0, 8 - ld bc, $ffd8 - call BattleTransition_CopyTiles1 - hlCoord 0, 10 - deCoord 0, 9 - ld bc, $28 - call BattleTransition_CopyTiles1 - hlCoord 8, 0 - deCoord 9, 0 - ld bc, $fffe - call BattleTransition_CopyTiles2 - hlCoord 11, 0 - deCoord 10, 0 - ld bc, $2 - call BattleTransition_CopyTiles2 - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - ld c, $6 - call DelayFrames - pop bc - dec c - jr nz, .loop - call BattleTransition_BlackScreen - ld c, $a - jp DelayFrames - -; used for high level trainer dungeon battles -BattleTransition_Split: ; 70bca (1c:4bca) - ld c, $9 - xor a - ld [H_AUTOBGTRANSFERENABLED], a -.loop - push bc - hlCoord 0, 16 - deCoord 0, 17 - ld bc, $ffd8 - call BattleTransition_CopyTiles1 - hlCoord 0, 1 - ld de, wTileMap - ld bc, $28 - call BattleTransition_CopyTiles1 - hlCoord 18, 0 - deCoord 19, 0 - ld bc, $fffe - call BattleTransition_CopyTiles2 - hlCoord 1, 0 - ld de, wTileMap - ld bc, $2 - call BattleTransition_CopyTiles2 - call BattleTransition_TransferDelay3 - call Delay3 - pop bc - dec c - jr nz, .loop - call BattleTransition_BlackScreen - ld c, $a - jp DelayFrames - -BattleTransition_CopyTiles1: ; 70c12 (1c:4c12) - ld a, c - ld [wWhichTrade], a - ld a, b - ld [wTrainerEngageDistance], a - ld c, $8 -.loop1 - push bc - push hl - push de - ld bc, $14 - call CopyData - pop hl - pop de - ld a, [wWhichTrade] - ld c, a - ld a, [wTrainerEngageDistance] - ld b, a - add hl, bc - pop bc - dec c - jr nz, .loop1 - ld l, e - ld h, d - ld a, $ff - ld c, $14 -.loop2 - ld [hli], a - dec c - jr nz, .loop2 - ret - -BattleTransition_CopyTiles2: ; 70c3f (1c:4c3f) - ld a, c - ld [wWhichTrade], a - ld a, b - ld [wTrainerEngageDistance], a - ld c, $9 -.loop1 - push bc - push hl - push de - ld c, $12 -.loop2 - ld a, [hl] - ld [de], a - ld a, e - add $14 - jr nc, .noCarry1 - inc d -.noCarry1 - ld e, a - ld a, l - add $14 - jr nc, .noCarry2 - inc h -.noCarry2 - ld l, a - dec c - jr nz, .loop2 - pop hl - pop de - ld a, [wWhichTrade] - ld c, a - ld a, [wTrainerEngageDistance] - ld b, a - add hl, bc - pop bc - dec c - jr nz, .loop1 - ld l, e - ld h, d - ld de, $14 - ld c, $12 -.loop3 - ld [hl], $ff - add hl, de - dec c - jr nz, .loop3 - ret - -; used for high level wild dungeon battles -BattleTransition_VerticalStripes: ; 70c7e (1c:4c7e) - ld c, $12 - ld hl, wTileMap - deCoord 1, 17 - xor a - ld [H_AUTOBGTRANSFERENABLED], a -.loop - push bc - push hl - push de - push de - call BattleTransition_VerticalStripes_ - pop hl - call BattleTransition_VerticalStripes_ - call BattleTransition_TransferDelay3 - pop hl - ld bc, $ffec - add hl, bc - ld e, l - ld d, h - pop hl - ld bc, $14 - add hl, bc - pop bc - dec c - jr nz, .loop - jp BattleTransition_BlackScreen - -BattleTransition_VerticalStripes_: ; 70caa (1c:4caa) - ld c, $a -.loop - ld [hl], $ff - inc hl - inc hl - dec c - jr nz, .loop - ret - -; used for low level wild dungeon battles -BattleTransition_HorizontalStripes: ; 70cb4 (1c:4cb4) - ld c, $14 - ld hl, wTileMap - deCoord 19, 1 - xor a - ld [H_AUTOBGTRANSFERENABLED], a -.loop - push bc - push hl - push de - push de - call BattleTransition_HorizontalStripes_ - pop hl - call BattleTransition_HorizontalStripes_ - call BattleTransition_TransferDelay3 - pop de - pop hl - pop bc - inc hl - dec de - dec c - jr nz, .loop - jp BattleTransition_BlackScreen - -BattleTransition_HorizontalStripes_: ; 70cd8 (1c:4cd8) - ld c, $9 - ld de, $28 -.loop - ld [hl], $ff - add hl, de - dec c - jr nz, .loop - ret - -; used for high level wild non-dungeon battles -; makes one full circle around the screen -; by animating each half circle one at a time -BattleTransition_Circle: ; 70ce4 (1c:4ce4) - call BattleTransition_FlashScreen - ld bc, $000a - ld hl, BattleTransition_HalfCircle1 - call BattleTransition_Circle_Sub1 - ld c, $a - ld b, $1 - ld hl, BattleTransition_HalfCircle2 - call BattleTransition_Circle_Sub1 - jp BattleTransition_BlackScreen - -BattleTransition_FlashScreen: ; 70cfd (1c:4cfd) - ld b, $3 - call BattleTransition_FlashScreen_ - xor a - ld [H_AUTOBGTRANSFERENABLED], a - ret - -BattleTransition_Circle_Sub1: ; 70d06 (1c:4d06) - push bc - push hl - ld a, b - call BattleTransition_Circle_Sub2 - pop hl - ld bc, $0005 - add hl, bc - call BattleTransition_TransferDelay3 - pop bc - dec c - jr nz, BattleTransition_Circle_Sub1 - ret - -BattleTransition_TransferDelay3: ; 70d19 (1c:4d19) - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - call Delay3 - xor a - ld [H_AUTOBGTRANSFERENABLED], a - ret - -; used for low level wild non-dungeon battles -; makes two half circles around the screen -; by animating both half circles at the same time -BattleTransition_DoubleCircle: ; 70d24 (1c:4d24) - call BattleTransition_FlashScreen - ld c, $a - ld hl, BattleTransition_HalfCircle1 - ld de, BattleTransition_HalfCircle2 -.loop - push bc - push hl - push de - push de - xor a - call BattleTransition_Circle_Sub2 - pop hl - ld a, $1 - call BattleTransition_Circle_Sub2 - pop hl - ld bc, $5 - add hl, bc - ld e, l - ld d, h - pop hl - add hl, bc - call BattleTransition_TransferDelay3 - pop bc - dec c - jr nz, .loop - jp BattleTransition_BlackScreen - -BattleTransition_Circle_Sub2: ; 70d50 (1c:4d50) - ld [wWhichTrade], a - ld a, [hli] - ld [wTrainerEngageDistance], a - ld a, [hli] - ld e, a - ld a, [hli] - ld d, a - ld a, [hli] - ld h, [hl] - ld l, a - jp BattleTransition_Circle_Sub3 - -BattleTransition_HalfCircle1: ; 70d61 (1c:4d61) - db $01 - dw BattleTransition_CircleData1 - dwCoord 18, 6 - - db $01 - dw BattleTransition_CircleData2 - dwCoord 19, 3 - - db $01 - dw BattleTransition_CircleData3 - dwCoord 18, 0 - - db $01 - dw BattleTransition_CircleData4 - dwCoord 14, 0 - - db $01 - dw BattleTransition_CircleData5 - dwCoord 10, 0 - - db $00 - dw BattleTransition_CircleData5 - dwCoord 9, 0 - - db $00 - dw BattleTransition_CircleData4 - dwCoord 5, 0 - - db $00 - dw BattleTransition_CircleData3 - dwCoord 1, 0 - - db $00 - dw BattleTransition_CircleData2 - dwCoord 0, 3 - - db $00 - dw BattleTransition_CircleData1 - dwCoord 1, 6 - -BattleTransition_HalfCircle2: ; 70d93 (1c:4d93) - db $00 - dw BattleTransition_CircleData1 - dwCoord 1, 11 - - db $00 - dw BattleTransition_CircleData2 - dwCoord 0, 14 - - db $00 - dw BattleTransition_CircleData3 - dwCoord 1, 17 - - db $00 - dw BattleTransition_CircleData4 - dwCoord 5, 17 - - db $00 - dw BattleTransition_CircleData5 - dwCoord 9, 17 - - db $01 - dw BattleTransition_CircleData5 - dwCoord 10, 17 - - db $01 - dw BattleTransition_CircleData4 - dwCoord 14, 17 - - db $01 - dw BattleTransition_CircleData3 - dwCoord 18, 17 - - db $01 - dw BattleTransition_CircleData2 - dwCoord 19, 14 - - db $01 - dw BattleTransition_CircleData1 - dwCoord 18, 11 - -BattleTransition_Circle_Sub3: ; 70dc5 (1c:4dc5) - push hl - ld a, [de] - ld c, a - inc de -.loop1 - ld [hl], $ff - ld a, [wTrainerEngageDistance] - and a - jr z, .skip1 - inc hl - jr .skip2 -.skip1 - dec hl -.skip2 - dec c - jr nz, .loop1 - pop hl - ld a, [wWhichTrade] - and a - ld bc, $14 - jr z, .skip3 - ld bc, $ffec -.skip3 - add hl, bc - ld a, [de] - inc de - cp $ff - ret z - and a - jr z, BattleTransition_Circle_Sub3 - ld c, a -.loop2 - ld a, [wTrainerEngageDistance] - and a - jr z, .skip4 - dec hl - jr .skip5 -.skip4 - inc hl -.skip5 - dec c - jr nz, .loop2 - jr BattleTransition_Circle_Sub3 - -BattleTransition_CircleData1: ; 70dfe (1c:4dfe) - db $02,$03,$05,$04,$09,$FF - -BattleTransition_CircleData2: ; 70e04 (1c:4e04) - db $01,$01,$02,$02,$04,$02,$04,$02,$03,$FF - -BattleTransition_CircleData3: ; 70e0e (1c:4e0e) - db $02,$01,$03,$01,$04,$01,$04,$01,$04,$01,$03,$01,$02,$01,$01,$01,$01,$FF - -BattleTransition_CircleData4: ; 70e20 (1c:4e20) - db $04,$01,$04,$00,$03,$01,$03,$00,$02,$01,$02,$00,$01,$FF - -BattleTransition_CircleData5: ; 70e2e (1c:4e2e) - db $04,$00,$03,$00,$03,$00,$02,$00,$02,$00,$01,$00,$01,$00,$01,$FF diff --git a/engine/battle/battle_transitions.asm b/engine/battle/battle_transitions.asm new file mode 100644 index 00000000..f1aa4161 --- /dev/null +++ b/engine/battle/battle_transitions.asm @@ -0,0 +1,815 @@ +BattleTransition: ; 7096d (1c:496d) + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + call Delay3 + xor a + ld [hWY], a + dec a + ld [wUpdateSpritesEnabled], a + call DelayFrame + ld hl, wSpriteStateData1 + 2 + ld a, [H_DOWNARROWBLINKCNT2] + ld c, a + ld b, $0 + ld de, $10 +.loop1 + ld a, [hl] + cp $ff + jr z, .skip1 + inc b +.skip1 + add hl, de + dec c + jr nz, .loop1 + ld hl, wOAMBuffer + $10 + ld c, $9 +.loop2 + ld a, b + swap a + cp l + jr z, .skip2 + push hl + push bc + ld bc, $10 + xor a + call FillMemory + pop bc + pop hl +.skip2 + ld de, $10 + add hl, de + dec c + jr nz, .loop2 + call Delay3 + call LoadBattleTransitionTile + ld bc, $0 + ld a, [wLinkState] + cp LINK_STATE_BATTLING + jr z, .linkBattle + call GetBattleTransitionID_WildOrTrainer + call GetBattleTransitionID_CompareLevels + call GetBattleTransitionID_IsDungeonMap +.linkBattle + ld hl, BattleTransitions + add hl, bc + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + jp [hl] + +; the three GetBattleTransitionID functions set the first +; three bits of c, which determines what transition animation +; to play at the beginning of a battle +; bit 0: set if trainer battle +; bit 1: set if enemy is at least 3 levels higher than player +; bit 2: set if dungeon map +BattleTransitions: ; 709d2 (1c:49d2) + dw BattleTransition_DoubleCircle ; %000 + dw BattleTransition_Spiral ; %001 + dw BattleTransition_Circle ; %010 + dw BattleTransition_Spiral ; %011 + dw BattleTransition_HorizontalStripes ; %100 + dw BattleTransition_Shrink ; %101 + dw BattleTransition_VerticalStripes ; %110 + dw BattleTransition_Split ; %111 + +GetBattleTransitionID_WildOrTrainer: ; 709e2 (1c:49e2) + ld a, [W_CUROPPONENT] + cp $c8 + jr nc, .trainer + res 0, c + ret +.trainer + set 0, c + ret + +GetBattleTransitionID_CompareLevels: ; 709ef (1c:49ef) + ld hl, wPartyMon1HP +.faintedLoop + ld a, [hli] + or [hl] + jr nz, .notFainted + ld de, wPartyMon2 - (wPartyMon1 + 1) + add hl, de + jr .faintedLoop +.notFainted + ld de, wPartyMon1Level - (wPartyMon1HP + 1) + add hl, de + ld a, [hl] + add $3 + ld e, a + ld a, [W_CURENEMYLVL] + sub e + jr nc, .highLevelEnemy + res 1, c + ld a, $1 + ld [wcd47], a + ret +.highLevelEnemy + set 1, c + xor a + ld [wcd47], a + ret + +; fails to recognize VICTORY_ROAD_2, VICTORY_ROAD_3, all ROCKET_HIDEOUT maps, +; MANSION_1, SEAFOAM_ISLANDS_[2-5], POWER_PLANT, DIGLETTS_CAVE +; and SILPH_CO_[9-11]F as dungeon maps +GetBattleTransitionID_IsDungeonMap: ; 70a19 (1c:4a19) + ld a, [W_CURMAP] + ld e, a + ld hl, DungeonMaps1 +.loop1 + ld a, [hli] + cp $ff + jr z, .noMatch1 + cp e + jr nz, .loop1 +.match + set 2, c + ret +.noMatch1 + ld hl, DungeonMaps2 +.loop2 + ld a, [hli] + cp $ff + jr z, .noMatch2 + ld d, a + ld a, [hli] + cp e + jr c, .loop2 + ld a, e + cp d + jr nc, .match +.noMatch2 + res 2, c + ret + +; GetBattleTransitionID_IsDungeonMap checks if W_CURMAP +; is equal to one of these maps +DungeonMaps1: ; 70a3f (1c:4a3f) + db VIRIDIAN_FOREST + db ROCK_TUNNEL_1 + db SEAFOAM_ISLANDS_1 + db ROCK_TUNNEL_2 + db $FF + +; GetBattleTransitionID_IsDungeonMap checks if W_CURMAP +; is in between or equal to each pair of maps +DungeonMaps2: ; 70a44 (1c:4a44) + ; all MT_MOON maps + db MT_MOON_1 + db MT_MOON_3 + + ; all SS_ANNE maps, VICTORY_ROAD_1, LANCES_ROOM, and HALL_OF_FAME + db SS_ANNE_1 + db HALL_OF_FAME + + ; all POKEMONTOWER maps and Lavender Town buildings + db LAVENDER_POKECENTER + db LAVENDER_HOUSE_2 + + ; SILPH_CO_[2-8]F, MANSION[2-4], SAFARI_ZONE, and UNKNOWN_DUNGEON maps, + ; except for SILPH_CO_1F + db SILPH_CO_2F + db UNKNOWN_DUNGEON_1 + db $FF + +LoadBattleTransitionTile: ; 70a4d (1c:4a4d) + ld hl, vChars1 + $7f0 + ld de, BattleTransitionTile + ld bc, (BANK(BattleTransitionTile) << 8) + $01 + jp CopyVideoData + +BattleTransitionTile: ; 70a59 (1c:4a59) + INCBIN "gfx/battle_transition.2bpp" + +BattleTransition_BlackScreen: ; 70a69 (1c:4a69) + ld a, $ff + ld [rBGP], a + ld [rOBP0], a + ld [rOBP1], a + ret + +; for non-dungeon trainer battles +; called regardless of mon levels, but does an +; outward spiral if enemy is at least 3 levels +; higher than player and does an inward spiral otherwise +BattleTransition_Spiral: ; 70a72 (1c:4a72) + ld a, [wcd47] + and a + jr z, .outwardSpiral + call BattleTransition_InwardSpiral + jr .done +.outwardSpiral + hlCoord 10, 10 + ld a, $3 + ld [wd09f], a + ld a, l + ld [wd09b], a + ld a, h + ld [wd09a], a + ld b, $78 +.loop1 + ld c, $3 +.loop2 + push bc + call BattleTransition_OutwardSpiral_ + pop bc + dec c + jr nz, .loop2 + call DelayFrame + dec b + jr nz, .loop1 +.done + call BattleTransition_BlackScreen + xor a + ld [wd09b], a + ld [wd09a], a + ret + +BattleTransition_InwardSpiral: ; 70aaa (1c:4aaa) + ld a, $7 + ld [wWhichTrade], a + ld hl, wTileMap + ld c, $11 + ld de, $14 + call BattleTransition_InwardSpiral_ + inc c + jr .skip +.loop + ld de, $14 + call BattleTransition_InwardSpiral_ +.skip + inc c + ld de, $1 + call BattleTransition_InwardSpiral_ + dec c + dec c + ld de, $ffec + call BattleTransition_InwardSpiral_ + inc c + ld de, rIE + call BattleTransition_InwardSpiral_ + dec c + dec c + ld a, c + and a + jr nz, .loop + ret + +BattleTransition_InwardSpiral_: ; 70ae0 (1c:4ae0) + push bc +.loop + ld [hl], $ff + add hl, de + push bc + ld a, [wWhichTrade] + dec a + jr nz, .skip + call BattleTransition_TransferDelay3 + ld a, $7 +.skip + ld [wWhichTrade], a + pop bc + dec c + jr nz, .loop + pop bc + ret + +BattleTransition_OutwardSpiral_: ; 70af9 (1c:4af9) + ld bc, $ffec + ld de, $14 + ld a, [wd09b] + ld l, a + ld a, [wd09a] + ld h, a + ld a, [wd09f] + cp $0 + jr z, .zero + cp $1 + jr z, .one + cp $2 + jr z, .two + cp $3 + jr z, .three +.done1 + ld [hl], $ff +.done2_ + ld a, l + ld [wd09b], a + ld a, h + ld [wd09a], a + ret +.zero + dec hl + ld a, [hl] + cp $ff + jr nz, .done2 + inc hl + add hl, bc + jr .done1 +.one + add hl, de + ld a, [hl] + cp $ff + jr nz, .done2 + add hl, bc + dec hl + jr .done1 +.two + inc hl + ld a, [hl] + cp $ff + jr nz, .done2 + dec hl + add hl, de + jr .done1 +.three + add hl, bc + ld a, [hl] + cp $ff + jr nz, .done2 + add hl, de + inc hl + jr .done1 +.done2 + ld [hl], $ff + ld a, [wd09f] + inc a + cp $4 + jr nz, .skip + xor a +.skip + ld [wd09f], a + jr .done2_ + +FlashScreen: +BattleTransition_FlashScreen_: ; 70b5d (1c:4b5d) + ld hl, BattleTransition_FlashScreenPalettes +.loop + ld a, [hli] + cp $1 + jr z, .done + ld [rBGP], a + ld c, $2 + call DelayFrames + jr .loop +.done + dec b + jr nz, BattleTransition_FlashScreen_ + ret + +BattleTransition_FlashScreenPalettes: ; 70b72 (1c:4b72) + db $F9,$FE,$FF,$FE,$F9,$E4,$90,$40,$00,$40,$90,$E4 + db $01 ; terminator + +; used for low level trainer dungeon battles +BattleTransition_Shrink: ; 70b7f (1c:4b7f) + ld c, $9 +.loop + push bc + xor a + ld [H_AUTOBGTRANSFERENABLED], a + hlCoord 0, 7 + deCoord 0, 8 + ld bc, $ffd8 + call BattleTransition_CopyTiles1 + hlCoord 0, 10 + deCoord 0, 9 + ld bc, $28 + call BattleTransition_CopyTiles1 + hlCoord 8, 0 + deCoord 9, 0 + ld bc, $fffe + call BattleTransition_CopyTiles2 + hlCoord 11, 0 + deCoord 10, 0 + ld bc, $2 + call BattleTransition_CopyTiles2 + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + ld c, $6 + call DelayFrames + pop bc + dec c + jr nz, .loop + call BattleTransition_BlackScreen + ld c, $a + jp DelayFrames + +; used for high level trainer dungeon battles +BattleTransition_Split: ; 70bca (1c:4bca) + ld c, $9 + xor a + ld [H_AUTOBGTRANSFERENABLED], a +.loop + push bc + hlCoord 0, 16 + deCoord 0, 17 + ld bc, $ffd8 + call BattleTransition_CopyTiles1 + hlCoord 0, 1 + ld de, wTileMap + ld bc, $28 + call BattleTransition_CopyTiles1 + hlCoord 18, 0 + deCoord 19, 0 + ld bc, $fffe + call BattleTransition_CopyTiles2 + hlCoord 1, 0 + ld de, wTileMap + ld bc, $2 + call BattleTransition_CopyTiles2 + call BattleTransition_TransferDelay3 + call Delay3 + pop bc + dec c + jr nz, .loop + call BattleTransition_BlackScreen + ld c, $a + jp DelayFrames + +BattleTransition_CopyTiles1: ; 70c12 (1c:4c12) + ld a, c + ld [wWhichTrade], a + ld a, b + ld [wTrainerEngageDistance], a + ld c, $8 +.loop1 + push bc + push hl + push de + ld bc, $14 + call CopyData + pop hl + pop de + ld a, [wWhichTrade] + ld c, a + ld a, [wTrainerEngageDistance] + ld b, a + add hl, bc + pop bc + dec c + jr nz, .loop1 + ld l, e + ld h, d + ld a, $ff + ld c, $14 +.loop2 + ld [hli], a + dec c + jr nz, .loop2 + ret + +BattleTransition_CopyTiles2: ; 70c3f (1c:4c3f) + ld a, c + ld [wWhichTrade], a + ld a, b + ld [wTrainerEngageDistance], a + ld c, $9 +.loop1 + push bc + push hl + push de + ld c, $12 +.loop2 + ld a, [hl] + ld [de], a + ld a, e + add $14 + jr nc, .noCarry1 + inc d +.noCarry1 + ld e, a + ld a, l + add $14 + jr nc, .noCarry2 + inc h +.noCarry2 + ld l, a + dec c + jr nz, .loop2 + pop hl + pop de + ld a, [wWhichTrade] + ld c, a + ld a, [wTrainerEngageDistance] + ld b, a + add hl, bc + pop bc + dec c + jr nz, .loop1 + ld l, e + ld h, d + ld de, $14 + ld c, $12 +.loop3 + ld [hl], $ff + add hl, de + dec c + jr nz, .loop3 + ret + +; used for high level wild dungeon battles +BattleTransition_VerticalStripes: ; 70c7e (1c:4c7e) + ld c, $12 + ld hl, wTileMap + deCoord 1, 17 + xor a + ld [H_AUTOBGTRANSFERENABLED], a +.loop + push bc + push hl + push de + push de + call BattleTransition_VerticalStripes_ + pop hl + call BattleTransition_VerticalStripes_ + call BattleTransition_TransferDelay3 + pop hl + ld bc, $ffec + add hl, bc + ld e, l + ld d, h + pop hl + ld bc, $14 + add hl, bc + pop bc + dec c + jr nz, .loop + jp BattleTransition_BlackScreen + +BattleTransition_VerticalStripes_: ; 70caa (1c:4caa) + ld c, $a +.loop + ld [hl], $ff + inc hl + inc hl + dec c + jr nz, .loop + ret + +; used for low level wild dungeon battles +BattleTransition_HorizontalStripes: ; 70cb4 (1c:4cb4) + ld c, $14 + ld hl, wTileMap + deCoord 19, 1 + xor a + ld [H_AUTOBGTRANSFERENABLED], a +.loop + push bc + push hl + push de + push de + call BattleTransition_HorizontalStripes_ + pop hl + call BattleTransition_HorizontalStripes_ + call BattleTransition_TransferDelay3 + pop de + pop hl + pop bc + inc hl + dec de + dec c + jr nz, .loop + jp BattleTransition_BlackScreen + +BattleTransition_HorizontalStripes_: ; 70cd8 (1c:4cd8) + ld c, $9 + ld de, $28 +.loop + ld [hl], $ff + add hl, de + dec c + jr nz, .loop + ret + +; used for high level wild non-dungeon battles +; makes one full circle around the screen +; by animating each half circle one at a time +BattleTransition_Circle: ; 70ce4 (1c:4ce4) + call BattleTransition_FlashScreen + ld bc, $000a + ld hl, BattleTransition_HalfCircle1 + call BattleTransition_Circle_Sub1 + ld c, $a + ld b, $1 + ld hl, BattleTransition_HalfCircle2 + call BattleTransition_Circle_Sub1 + jp BattleTransition_BlackScreen + +BattleTransition_FlashScreen: ; 70cfd (1c:4cfd) + ld b, $3 + call BattleTransition_FlashScreen_ + xor a + ld [H_AUTOBGTRANSFERENABLED], a + ret + +BattleTransition_Circle_Sub1: ; 70d06 (1c:4d06) + push bc + push hl + ld a, b + call BattleTransition_Circle_Sub2 + pop hl + ld bc, $0005 + add hl, bc + call BattleTransition_TransferDelay3 + pop bc + dec c + jr nz, BattleTransition_Circle_Sub1 + ret + +BattleTransition_TransferDelay3: ; 70d19 (1c:4d19) + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + call Delay3 + xor a + ld [H_AUTOBGTRANSFERENABLED], a + ret + +; used for low level wild non-dungeon battles +; makes two half circles around the screen +; by animating both half circles at the same time +BattleTransition_DoubleCircle: ; 70d24 (1c:4d24) + call BattleTransition_FlashScreen + ld c, $a + ld hl, BattleTransition_HalfCircle1 + ld de, BattleTransition_HalfCircle2 +.loop + push bc + push hl + push de + push de + xor a + call BattleTransition_Circle_Sub2 + pop hl + ld a, $1 + call BattleTransition_Circle_Sub2 + pop hl + ld bc, $5 + add hl, bc + ld e, l + ld d, h + pop hl + add hl, bc + call BattleTransition_TransferDelay3 + pop bc + dec c + jr nz, .loop + jp BattleTransition_BlackScreen + +BattleTransition_Circle_Sub2: ; 70d50 (1c:4d50) + ld [wWhichTrade], a + ld a, [hli] + ld [wTrainerEngageDistance], a + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + ld a, [hli] + ld h, [hl] + ld l, a + jp BattleTransition_Circle_Sub3 + +BattleTransition_HalfCircle1: ; 70d61 (1c:4d61) + db $01 + dw BattleTransition_CircleData1 + dwCoord 18, 6 + + db $01 + dw BattleTransition_CircleData2 + dwCoord 19, 3 + + db $01 + dw BattleTransition_CircleData3 + dwCoord 18, 0 + + db $01 + dw BattleTransition_CircleData4 + dwCoord 14, 0 + + db $01 + dw BattleTransition_CircleData5 + dwCoord 10, 0 + + db $00 + dw BattleTransition_CircleData5 + dwCoord 9, 0 + + db $00 + dw BattleTransition_CircleData4 + dwCoord 5, 0 + + db $00 + dw BattleTransition_CircleData3 + dwCoord 1, 0 + + db $00 + dw BattleTransition_CircleData2 + dwCoord 0, 3 + + db $00 + dw BattleTransition_CircleData1 + dwCoord 1, 6 + +BattleTransition_HalfCircle2: ; 70d93 (1c:4d93) + db $00 + dw BattleTransition_CircleData1 + dwCoord 1, 11 + + db $00 + dw BattleTransition_CircleData2 + dwCoord 0, 14 + + db $00 + dw BattleTransition_CircleData3 + dwCoord 1, 17 + + db $00 + dw BattleTransition_CircleData4 + dwCoord 5, 17 + + db $00 + dw BattleTransition_CircleData5 + dwCoord 9, 17 + + db $01 + dw BattleTransition_CircleData5 + dwCoord 10, 17 + + db $01 + dw BattleTransition_CircleData4 + dwCoord 14, 17 + + db $01 + dw BattleTransition_CircleData3 + dwCoord 18, 17 + + db $01 + dw BattleTransition_CircleData2 + dwCoord 19, 14 + + db $01 + dw BattleTransition_CircleData1 + dwCoord 18, 11 + +BattleTransition_Circle_Sub3: ; 70dc5 (1c:4dc5) + push hl + ld a, [de] + ld c, a + inc de +.loop1 + ld [hl], $ff + ld a, [wTrainerEngageDistance] + and a + jr z, .skip1 + inc hl + jr .skip2 +.skip1 + dec hl +.skip2 + dec c + jr nz, .loop1 + pop hl + ld a, [wWhichTrade] + and a + ld bc, $14 + jr z, .skip3 + ld bc, $ffec +.skip3 + add hl, bc + ld a, [de] + inc de + cp $ff + ret z + and a + jr z, BattleTransition_Circle_Sub3 + ld c, a +.loop2 + ld a, [wTrainerEngageDistance] + and a + jr z, .skip4 + dec hl + jr .skip5 +.skip4 + inc hl +.skip5 + dec c + jr nz, .loop2 + jr BattleTransition_Circle_Sub3 + +BattleTransition_CircleData1: ; 70dfe (1c:4dfe) + db $02,$03,$05,$04,$09,$FF + +BattleTransition_CircleData2: ; 70e04 (1c:4e04) + db $01,$01,$02,$02,$04,$02,$04,$02,$03,$FF + +BattleTransition_CircleData3: ; 70e0e (1c:4e0e) + db $02,$01,$03,$01,$04,$01,$04,$01,$04,$01,$03,$01,$02,$01,$01,$01,$01,$FF + +BattleTransition_CircleData4: ; 70e20 (1c:4e20) + db $04,$01,$04,$00,$03,$01,$03,$00,$02,$01,$02,$00,$01,$FF + +BattleTransition_CircleData5: ; 70e2e (1c:4e2e) + db $04,$00,$03,$00,$03,$00,$02,$00,$02,$00,$01,$00,$01,$00,$01,$FF diff --git a/engine/battle/common_text.asm b/engine/battle/common_text.asm new file mode 100644 index 00000000..9a00bd98 --- /dev/null +++ b/engine/battle/common_text.asm @@ -0,0 +1,238 @@ +PrintBeginningBattleText: ; 58d99 (16:4d99) + ld a, [W_ISINBATTLE] ; W_ISINBATTLE + dec a + jr nz, .trainerBattle + ld a, [W_CURMAP] ; W_CURMAP + cp POKEMONTOWER_3 + jr c, .notPokemonTower + cp LAVENDER_HOUSE_1 + jr c, .pokemonTower +.notPokemonTower + ld a, [wEnemyMonSpecies2] + call PlayCry + ld hl, WildMonAppearedText + ld a, [W_MOVEMISSED] ; W_MOVEMISSED + and a + jr z, .notFishing + ld hl, HookedMonAttackedText +.notFishing + jr .wildBattle +.trainerBattle + call .playSFX + ld c, $14 + call DelayFrames + ld hl, TrainerWantsToFightText +.wildBattle + push hl + callab DrawAllPokeballs + pop hl + call PrintText + jr .done +.pokemonTower + ld b, SILPH_SCOPE + call IsItemInBag + ld a, [wEnemyMonSpecies2] + ld [wcf91], a + cp MAROWAK + jr z, .isMarowak + ld a, b + and a + jr z, .noSilphScope + callab LoadEnemyMonData + jr .notPokemonTower +.noSilphScope + ld hl, EnemyAppearedText + call PrintText + ld hl, GhostCantBeIDdText + call PrintText + jr .done +.isMarowak + ld a, b + and a + jr z, .noSilphScope + ld hl, EnemyAppearedText + call PrintText + ld hl, UnveiledGhostText + call PrintText + callab LoadEnemyMonData + callab MarowakAnim + ld hl, WildMonAppearedText + call PrintText + +.playSFX + xor a + ld [wc0f1], a + ld a, $80 + ld [wc0f2], a + ld a, (SFX_08_77 - SFX_Headers_08) / 3 + call PlaySound + jp WaitForSoundToFinish +.done + ret + +WildMonAppearedText: ; 58e3b (16:4e3b) + TX_FAR _WildMonAppearedText + db "@" + +HookedMonAttackedText: ; 58e40 (16:4e40) + TX_FAR _HookedMonAttackedText + db "@" + +EnemyAppearedText: ; 58e45 (16:4e45) + TX_FAR _EnemyAppearedText + db "@" + +TrainerWantsToFightText: ; 58e4a (16:4e4a) + TX_FAR _TrainerWantsToFightText + db "@" + +UnveiledGhostText: ; 58e4f (16:4e4f) + TX_FAR _UnveiledGhostText + db "@" + +GhostCantBeIDdText: ; 58e54 (16:4e54) + TX_FAR _GhostCantBeIDdText + db "@" + +PrintSendOutMonMessage: ; 58e59 (16:4e59) + ld hl, wEnemyMonHP + ld a, [hli] + or [hl] + ld hl, GoText + jr z, .printText + xor a + ld [H_MULTIPLICAND], a + ld hl, wEnemyMonHP + ld a, [hli] + ld [wcce3], a + ld [H_MULTIPLICAND + 1], a + ld a, [hl] + ld [wcce4], a + ld [H_MULTIPLICAND + 2], a + ld a, 25 + ld [H_MULTIPLIER], a + call Multiply + ld hl, wEnemyMonMaxHP + ld a, [hli] + ld b, [hl] + srl a + rr b + srl a + rr b + ld a, b + ld b, $4 + ld [H_DIVISOR], a ; enemy mon max HP divided by 4 + call Divide + ld a, [H_QUOTIENT + 3] ; a = (enemy mon current HP * 25) / (enemy max HP / 4); this approximates the current percentage of max HP + ld hl, GoText ; 70% or greater + cp 70 + jr nc, .printText + ld hl, DoItText ; 40% - 69% + cp 40 + jr nc, .printText + ld hl, GetmText ; 10% - 39% + cp 10 + jr nc, .printText + ld hl, EnemysWeakText ; 0% - 9% +.printText + jp PrintText + +GoText: ; 58eae (16:4eae) + TX_FAR _GoText + db $08 ; asm + jr PrintPlayerMon1Text + +DoItText: ; 58eb5 (16:4eb5) + TX_FAR _DoItText + db $08 ; asm + jr PrintPlayerMon1Text + +GetmText: ; 58ebc (16:4ebc) + TX_FAR _GetmText + db $08 ; asm + jr PrintPlayerMon1Text + +EnemysWeakText: ; 58ec3 (16:4ec3) + TX_FAR _EnemysWeakText + db $08 ; asm + +PrintPlayerMon1Text: + ld hl, PlayerMon1Text + ret + +PlayerMon1Text: ; 58ecc (16:4ecc) + TX_FAR _PlayerMon1Text + db "@" + +RetreatMon: ; 58ed1 (16:4ed1) + ld hl, PlayerMon2Text + jp PrintText + +PlayerMon2Text: ; 58ed7 (16:4ed7) + TX_FAR _PlayerMon2Text + db $08 ; asm + push de + push bc + ld hl, wEnemyMonHP + 1 + ld de, wcce4 + ld b, [hl] + dec hl + ld a, [de] + sub b + ld [$ff98], a + dec de + ld b, [hl] + ld a, [de] + sbc b + ld [$ff97], a + ld a, $19 + ld [H_POWEROFTEN], a + call Multiply + ld hl, wEnemyMonMaxHP + ld a, [hli] + ld b, [hl] + srl a + rr b + srl a + rr b + ld a, b + ld b, $4 + ld [H_POWEROFTEN], a + call Divide + pop bc + pop de + ld a, [$ff98] + ld hl, EnoughText + and a + ret z + ld hl, ComeBackText + cp $1e + ret c + ld hl, OKExclamationText + cp $46 + ret c + ld hl, GoodText + ret + +EnoughText: ; 58f25 (16:4f25) + TX_FAR _EnoughText + db $08 ; asm + jr PrintComeBackText + +OKExclamationText: ; 58f2c (16:4f2c) + TX_FAR _OKExclamationText + db $08 ; asm + jr PrintComeBackText + +GoodText: ; 58f33 (16:4f33) + TX_FAR _GoodText + db $08 ; asm + jr PrintComeBackText + +PrintComeBackText: ; 58f3a (16:4f3a) + ld hl, ComeBackText + ret + +ComeBackText: ; 58f3e (16:4f3e) + TX_FAR _ComeBackText + db "@" diff --git a/engine/battle/decrement_pp.asm b/engine/battle/decrement_pp.asm new file mode 100644 index 00000000..ecf5040b --- /dev/null +++ b/engine/battle/decrement_pp.asm @@ -0,0 +1,43 @@ +DecrementPP: ; 68000 (1a:4000) +; after using a move, decrement pp in battle and (if not transformed?) in party + ld a, [de] + cp a, STRUGGLE + ret z ; if the pokemon is using "struggle", there's nothing to do + ; we don't decrement PP for "struggle" + ld hl, W_PLAYERBATTSTATUS1 + ld a, [hli] ; load the W_PLAYERBATTSTATUS1 pokemon status flags and increment hl to load the + ; W_PLAYERBATTSTATUS2 status flags later + and a, (1 << StoringEnergy) | (1 << ThrashingAbout) | (1 << AttackingMultipleTimes) + ret nz ; if any of these statuses are true, don't decrement PP + bit UsingRage, [hl] + ret nz ; don't decrement PP either if Pokemon is using Rage + ld hl, wBattleMonPP ; PP of first move (in battle) + +; decrement PP in the battle struct + call .DecrementPP + +; decrement PP in the party struct + ld a, [W_PLAYERBATTSTATUS3] + bit Transformed, a + ret nz ; Return if transformed. Pokemon Red stores the "current pokemon's" PP + ; separately from the "Pokemon in your party's" PP. This is + ; duplication -- in all cases *other* than Pokemon with Transform. + ; Normally, this means we have to go on and make the same + ; modification to the "party's pokemon" PP that we made to the + ; "current pokemon's" PP. But, if we're dealing with a Transformed + ; Pokemon, it has separate PP for the move set that it copied from + ; its opponent, which is *not* the same as its real PP as part of your + ; party. So we return, and don't do that part. + + ld hl, wPartyMon1PP ; PP of first move (in party) + ld a, [wPlayerMonNumber] ; which mon in party is active + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes ; calculate address of the mon to modify +.DecrementPP + ld a, [wPlayerMoveListIndex] ; which move (0, 1, 2, 3) did we use? + ld c, a + ld b, 0 + add hl ,bc ; calculate the address in memory of the PP we need to decrement + ; based on the move chosen. + dec [hl] ; Decrement PP + ret diff --git a/engine/battle/experience.asm b/engine/battle/experience.asm new file mode 100644 index 00000000..9bd67654 --- /dev/null +++ b/engine/battle/experience.asm @@ -0,0 +1,372 @@ +GainExperience: ; 5524f (15:524f) + ld a, [wLinkState] + cp LINK_STATE_BATTLING + ret z ; return if link battle + call DivideExpDataByNumMonsGainingExp + ld hl, wPartyMon1 + xor a + ld [wWhichPokemon], a +.partyMonLoop ; loop over each mon and add gained exp + inc hl + ld a, [hli] + or [hl] ; is mon's HP 0? + jp z, .nextMon ; if so, go to next mon + push hl + ld hl, wPartyGainExpFlags + ld a, [wWhichPokemon] + ld c, a + ld b, $2 + predef FlagActionPredef + ld a, c + and a ; is mon's gain exp flag set? + pop hl + jp z, .nextMon ; if mon's gain exp flag not set, go to next mon + ld de, (wPartyMon1HPExp + 1) - (wPartyMon1HP + 1) + add hl, de + ld d, h + ld e, l + ld hl, wEnemyMonBaseStats + ld c, $5 +.gainStatExpLoop + ld a, [hli] + ld b, a ; enemy mon base stat + ld a, [de] ; stat exp + add b ; add enemy mon base state to stat exp + ld [de], a + jr nc, .nextBaseStat +; if there was a carry, increment the upper byte + dec de + ld a, [de] + inc a + jr z, .maxStatExp ; jump if the value overflowed + ld [de], a + inc de + jr .nextBaseStat +.maxStatExp ; if the upper byte also overflowed, then we have hit the max stat exp + ld a, $ff + ld [de], a + inc de + ld [de], a +.nextBaseStat + dec c + jr z, .asm_552a1 + inc de + inc de + jr .gainStatExpLoop +.asm_552a1 + xor a + ld [H_MULTIPLICAND], a + ld [H_MULTIPLICAND + 1], a + ld a, [wEnemyMonBaseExp] + ld [H_MULTIPLICAND + 2], a + ld a, [wEnemyMonLevel] + ld [H_MULTIPLIER], a + call Multiply + ld a, 7 + ld [H_DIVISOR], a + ld b, 4 + call Divide + ld hl, -((wPartyMon1HPExp + 1) - wPartyMon1OTID + 4 * 2) + add hl, de + ld b, [hl] ; party mon OTID + inc hl + ld a, [wPlayerID] + cp b + jr nz, .tradedMon + ld b, [hl] + ld a, [wPlayerID + 1] + cp b + ld a, $0 + jr z, .next +.tradedMon + call BoostExp ; traded mon exp boost + ld a, $1 +.next + ld [wGainBoostedExp], a + ld a, [W_ISINBATTLE] + dec a ; is it a trainer battle? + call nz, BoostExp ; if so, boost exp + inc hl + inc hl + inc hl +; add the gained exp to the party mon's exp + ld b, [hl] + ld a, [H_QUOTIENT + 3] + ld [wcf4c], a + add b + ld [hld], a + ld b, [hl] + ld a, [H_QUOTIENT + 2] + ld [wcf4b], a + adc b + ld [hl], a + jr nc, .noCarry + dec hl + inc [hl] + inc hl +.noCarry +; calculate exp for the mon at max level, and cap the exp at that value + inc hl + push hl + ld a, [wWhichPokemon] + ld c, a + ld b, 0 + ld hl, wPartySpecies + add hl, bc + ld a, [hl] ; species + ld [wd0b5], a + call GetMonHeader + ld d, MAX_LEVEL + callab CalcExperience ; get max exp +; compare max exp with current exp + ld a, [$ff96] + ld b, a + ld a, [$ff97] + ld c, a + ld a, [$ff98] + ld d, a + pop hl + ld a, [hld] + sub d + ld a, [hld] + sbc c + ld a, [hl] + sbc b + jr c, .next2 +; the mon's exp is greater than the max exp, so overwrite it with the max exp + ld a, b + ld [hli], a + ld a, c + ld [hli], a + ld a, d + ld [hld], a + dec hl +.next2 + push hl + ld a, [wWhichPokemon] + ld hl, wPartyMonNicks + call GetPartyMonName + ld hl, GainedText + call PrintText + xor a ; party mon data + ld [wcc49], a + call LoadMonData + pop hl + ld bc, wPartyMon1Level - wPartyMon1Exp + add hl, bc + push hl + callba CalcLevelFromExperience + pop hl + ld a, [hl] ; current level + cp d + jp z, .nextMon ; if level didn't change, go to next mon + ld a, [W_CURENEMYLVL] + push af + push hl + ld a, d + ld [W_CURENEMYLVL], a + ld [hl], a + ld bc, wPartyMon1Species - wPartyMon1Level + add hl, bc + ld a, [hl] ; species + ld [wd0b5], a + ld [wd11e], a + call GetMonHeader + ld bc, (wPartyMon1MaxHP + 1) - wPartyMon1Species + add hl, bc + push hl + ld a, [hld] + ld c, a + ld b, [hl] + push bc ; push max HP (from before levelling up) + ld d, h + ld e, l + ld bc, (wPartyMon1HPExp - 1) - wPartyMon1MaxHP + add hl, bc + ld b, $1 ; consider stat exp when calculating stats + call CalcStats + pop bc ; pop max HP (from before levelling up) + pop hl + ld a, [hld] + sub c + ld c, a + ld a, [hl] + sbc b + ld b, a ; bc = difference between old max HP and new max HP after levelling + ld de, (wPartyMon1HP + 1) - wPartyMon1MaxHP + add hl, de +; add to the current HP the amount of max HP gained when levelling + ld a, [hl] ; wPartyMon1HP + 1 + add c + ld [hld], a + ld a, [hl] ; wPartyMon1HP + 1 + adc b + ld [hl], a ; wPartyMon1HP + ld a, [wPlayerMonNumber] + ld b, a + ld a, [wWhichPokemon] + cp b ; is the current mon in battle? + jr nz, .printGrewLevelText +; current mon is in battle + ld de, wBattleMonHP +; copy party mon HP to battle mon HP + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + ld [de], a +; copy other stats from party mon to battle mon + ld bc, wPartyMon1Level - (wPartyMon1HP + 1) + add hl, bc + push hl + ld de, wBattleMonLevel + ld bc, $b ; size of stats + call CopyData + pop hl + ld a, [W_PLAYERBATTSTATUS3] + bit 3, a ; is the mon transformed? + jr nz, .recalcStatChanges +; the mon is not transformed, so update the unmodified stats + ld de, wPlayerMonUnmodifiedLevel + ld bc, $b + call CopyData +.recalcStatChanges + xor a + ld [wd11e], a + callab CalculateModifiedStats + callab ApplyBurnAndParalysisPenaltiesToPlayer + callab ApplyBadgeStatBoosts + callab DrawPlayerHUDAndHPBar + callab PrintEmptyString + call SaveScreenTilesToBuffer1 +.printGrewLevelText + ld hl, GrewLevelText + call PrintText + xor a ; party mon data + ld [wcc49], a + call LoadMonData + ld d, $1 + callab PrintStatsBox + call WaitForTextScrollButtonPress + call LoadScreenTilesFromBuffer1 + xor a + ld [wcc49], a + ld a, [wd0b5] + ld [wd11e], a + predef LearnMoveFromLevelUp + ld hl, wccd3 + ld a, [wWhichPokemon] + ld c, a + ld b, $1 + predef FlagActionPredef + pop hl + pop af + ld [W_CURENEMYLVL], a + +.nextMon + ld a, [wPartyCount] + ld b, a + ld a, [wWhichPokemon] + inc a + cp b + jr z, .done + ld [wWhichPokemon], a + ld bc, wPartyMon2 - wPartyMon1 + ld hl, wPartyMon1 + call AddNTimes + jp .partyMonLoop +.done + ld hl, wPartyGainExpFlags + xor a + ld [hl], a ; clear gain exp flags + ld a, [wPlayerMonNumber] + ld c, a + ld b, $1 + push bc + predef FlagActionPredef ; set the gain exp flag for the mon that is currently out + ld hl, wPartyFoughtCurrentEnemyFlags + xor a + ld [hl], a + pop bc + predef_jump FlagActionPredef ; set the fought current enemy flag for the mon that is currently out + +; divide enemy base stats, catch rate, and base exp by the number of mons gaining exp +DivideExpDataByNumMonsGainingExp: ; 5546c (15:546c) + ld a, [wPartyGainExpFlags] + ld b, a + xor a + ld c, $8 + ld d, $0 +.countSetBitsLoop ; loop to count set bits in wPartyGainExpFlags + xor a + srl b + adc d + ld d, a + dec c + jr nz, .countSetBitsLoop + cp $2 + ret c ; return if only one mon is gaining exp + ld [wd11e], a ; store number of mons gaining exp + ld hl, wEnemyMonBaseStats + ld c, $7 +.divideLoop + xor a + ld [H_DIVIDEND], a + ld a, [hl] + ld [H_DIVIDEND + 1], a + ld a, [wd11e] + ld [H_DIVISOR], a + ld b, $2 + call Divide ; divide value by number of mons gaining exp + ld a, [H_QUOTIENT + 3] + ld [hli], a + dec c + jr nz, .divideLoop + ret + +; multiplies exp by 1.5 +BoostExp: ; 5549f (15:549f) + ld a, [H_QUOTIENT + 2] + ld b, a + ld a, [H_QUOTIENT + 3] + ld c, a + srl b + rr c + add c + ld [H_QUOTIENT + 3], a + ld a, [H_QUOTIENT + 2] + adc b + ld [H_QUOTIENT + 2], a + ret + +GainedText: ; 554b2 (15:54b2) + TX_FAR _GainedText + db $08 ; asm + ld a, [wBoostExpByExpAll] + ld hl, WithExpAllText + and a + ret nz + ld hl, ExpPointsText + ld a, [wGainBoostedExp] + and a + ret z + ld hl, BoostedText + ret + +WithExpAllText: ; 554cb (15:54cb) + TX_FAR _WithExpAllText + db $08 ; asm + ld hl, ExpPointsText + ret + +BoostedText: ; 554d4 (15:54d4) + TX_FAR _BoostedText + +ExpPointsText: ; 554d8 (15:54d8) + TX_FAR _ExpPointsText + db "@" + +GrewLevelText: ; 554dd (15:54dd) + TX_FAR _GrewLevelText + db $0b + db "@" diff --git a/engine/battle/ghost_marowak_anim.asm b/engine/battle/ghost_marowak_anim.asm new file mode 100644 index 00000000..73d3bcc2 --- /dev/null +++ b/engine/battle/ghost_marowak_anim.asm @@ -0,0 +1,89 @@ +MarowakAnim: ; 708ca (1c:48ca) +; animate the ghost being unveiled as a Marowak + ld a, $e4 + ld [rOBP1], a + call CopyMonPicFromBGToSpriteVRAM ; cover the BG ghost pic with a sprite ghost pic that looks the same +; now that the ghost pic is being displayed using sprites, clear the ghost pic from the BG tilemap + hlCoord 12, 0 + ld bc, $707 + call ClearScreenArea + call Delay3 + xor a + ld [H_AUTOBGTRANSFERENABLED], a ; disable BG transfer so we don't see the Marowak too soon +; replace ghost pic with Marowak in BG + ld a, MAROWAK + ld [wHPBarMaxHP], a + ld a, $1 + ld [H_WHOSETURN], a + callab Func_79793 + ; alternate between black and light grey 8 times. + ; this makes the ghost's body appear to flash + ld d, $80 + call FlashSprite8Times +.fadeOutGhostLoop + ld c, 10 + call DelayFrames + ld a, [rOBP1] + sla a + sla a + ld [rOBP1], a + jr nz, .fadeOutGhostLoop + call ClearSprites + call CopyMonPicFromBGToSpriteVRAM ; copy Marowak pic from BG to sprite VRAM + ld b, $e4 +.fadeInMarowakLoop + ld c, 10 + call DelayFrames + ld a, [rOBP1] + srl b + rra + srl b + rra + ld [rOBP1], a + ld a, b + and a + jr nz, .fadeInMarowakLoop + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a ; enable BG transfer so the BG Marowak pic will be visible after the sprite one is cleared + call Delay3 + jp ClearSprites + +; copies a mon pic's from background VRAM to sprite VRAM and sets up OAM +CopyMonPicFromBGToSpriteVRAM: ; 7092a (1c:492a) + ld de, vFrontPic + ld hl, vSprites + ld bc, 7 * 7 + call CopyVideoData + ld a, $10 + ld [W_BASECOORDY], a + ld a, $70 + ld [W_BASECOORDX], a + ld hl, wOAMBuffer + ld bc, $606 + ld d, $8 +.oamLoop + push bc + ld a, [W_BASECOORDY] + ld e, a +.oamInnerLoop + ld a, e + add $8 + ld e, a + ld [hli], a + ld a, [W_BASECOORDX] + ld [hli], a + ld a, d + ld [hli], a + ld a, $10 ; use OBP1 + ld [hli], a + inc d + dec c + jr nz, .oamInnerLoop + inc d + ld a, [W_BASECOORDX] + add $8 + ld [W_BASECOORDX], a + pop bc + dec b + jr nz, .oamLoop + ret diff --git a/main.asm b/main.asm index 9cc8b91f..62d5940b 100755 --- a/main.asm +++ b/main.asm @@ -6014,7 +6014,7 @@ DayCareMBlocks: INCBIN "maps/daycarem.blk" FuchsiaHouse3Blocks: INCBIN "maps/fuchsiahouse3.blk" -INCLUDE "engine/battle/15.asm" +INCLUDE "engine/battle/experience.asm" INCLUDE "scripts/route2.asm" INCLUDE "scripts/route3.asm" @@ -6094,7 +6094,7 @@ Route18Blocks: INCBIN "maps/route18.blk" INCBIN "maps/unusedblocks58d7d.blk" -INCLUDE "engine/battle/16.asm" +INCLUDE "engine/battle/common_text.asm" INCLUDE "engine/experience.asm" @@ -6451,7 +6451,7 @@ Plateau_Block: INCBIN "gfx/blocksets/plateau.bst" SECTION "bank1A",ROMX,BANK[$1A] -INCLUDE "engine/battle/1a.asm" +INCLUDE "engine/battle/decrement_pp.asm" Version_GFX: IF DEF(_RED) @@ -6508,7 +6508,8 @@ INCLUDE "engine/gamefreak.asm" INCLUDE "engine/hall_of_fame.asm" INCLUDE "engine/overworld/healing_machine.asm" INCLUDE "engine/overworld/player_animations.asm" -INCLUDE "engine/battle/1c.asm" +INCLUDE "engine/battle/ghost_marowak_anim.asm" +INCLUDE "engine/battle/battle_transitions.asm" INCLUDE "engine/town_map.asm" INCLUDE "engine/mon_party_sprites.asm" INCLUDE "engine/in_game_trades.asm" -- cgit v1.2.3