diff options
Diffstat (limited to 'engine/battle')
-rwxr-xr-x | engine/battle/animations.asm | 272 | ||||
-rw-r--r-- | engine/battle/bank3d_battle.asm | 292 | ||||
-rw-r--r-- | engine/battle/battle_transitions.asm | 8 | ||||
-rw-r--r-- | engine/battle/common_text.asm | 16 | ||||
-rwxr-xr-x | engine/battle/core.asm | 579 | ||||
-rw-r--r-- | engine/battle/decrement_pp.asm | 2 | ||||
-rw-r--r-- | engine/battle/draw_hud_pokeball_gfx.asm | 10 | ||||
-rw-r--r-- | engine/battle/effects.asm | 95 | ||||
-rwxr-xr-x | engine/battle/end_of_battle.asm | 4 | ||||
-rw-r--r-- | engine/battle/experience.asm | 22 | ||||
-rw-r--r-- | engine/battle/ghost_marowak_anim.asm | 5 | ||||
-rw-r--r-- | engine/battle/link_battle_versus_text.asm | 3 | ||||
-rwxr-xr-x | engine/battle/misc.asm | 19 | ||||
-rw-r--r-- | engine/battle/move_effects/heal.asm | 6 | ||||
-rw-r--r-- | engine/battle/move_effects/reflect_light_screen.asm | 6 | ||||
-rw-r--r-- | engine/battle/move_effects/transform.asm | 11 | ||||
-rwxr-xr-x | engine/battle/read_trainer_party.asm | 101 | ||||
-rwxr-xr-x | engine/battle/safari_zone.asm | 10 | ||||
-rw-r--r-- | engine/battle/scale_sprites.asm | 7 | ||||
-rw-r--r-- | engine/battle/trainer_ai.asm | 27 | ||||
-rw-r--r-- | engine/battle/wild_encounters.asm | 7 |
21 files changed, 976 insertions, 526 deletions
diff --git a/engine/battle/animations.asm b/engine/battle/animations.asm index e10b5e0d..4508dbaa 100755 --- a/engine/battle/animations.asm +++ b/engine/battle/animations.asm @@ -15,6 +15,8 @@ DrawFrameBlock: ld a, [wFBTileCounter] inc a ld [wFBTileCounter], a + ld a, $2 + ld [wdef5], a ld a, [wSubAnimTransform] dec a jr z, .flipHorizontalAndVertical ; SUBANIMTYPE_HVFLIP @@ -46,13 +48,22 @@ DrawFrameBlock: .finishCopying ; finish copying values to OAM (when subanimation not transformed) add [hl] ; X offset ld [de], a ; store X + cp 88 + jr c, .asm_78056 + ld a, [wdef5] + inc a + ld [wdef5], a +.asm_78056 inc hl inc de ld a, [hli] - add $31 ; base tile ID for battle animations + add a, $31 ; base tile ID for battle animations ld [de], a ; store tile ID inc de ld a, [hli] + ld b, a + ld a, [wdef5] + or b ld [de], a ; store flags inc de jp .nextTile @@ -71,10 +82,16 @@ DrawFrameBlock: ld a, 168 sub b ; flip X coordinate ld [de], a ; store X + cp 88 + jr c, .asm_78087 + ld a, [wdef5] + inc a + ld [wdef5], a +.asm_78087 inc hl inc de ld a, [hli] - add $31 ; base tile ID for battle animations + add a, $31 ; base tile ID for battle animations ld [de], a ; store tile ID inc de ; toggle horizontal and vertical flip @@ -82,15 +99,16 @@ DrawFrameBlock: and a ld b, OAM_VFLIP | OAM_HFLIP jr z, .storeFlags1 - cp OAM_HFLIP + cp a, OAM_HFLIP ld b, OAM_VFLIP jr z, .storeFlags1 - cp OAM_VFLIP + cp a, OAM_VFLIP ld b, OAM_HFLIP jr z, .storeFlags1 ld b, 0 .storeFlags1 - ld a, b + ld a, [wdef5] + or b ld [de], a inc de jp .nextTile @@ -107,6 +125,12 @@ DrawFrameBlock: ld a, 168 sub b ; flip X coordinate ld [de], a ; store X + cp 88 + jr c, .asm_780c8 + ld a, [wdef5] + inc a + ld [wdef5], a +.asm_780c8 inc hl inc de ld a, [hli] @@ -122,6 +146,9 @@ DrawFrameBlock: .disableHorizontalFlip res 5, a .storeFlags2 + ld b, a + ld a, [wdef5] + or b ld [de], a inc de .nextTile @@ -245,11 +272,13 @@ PlayAnimation: push af ld a, [wAnimPalette] ldh [rOBP0], a + call UpdateGBCPal_OBP0 call LoadAnimationTileset call LoadSubanimation call PlaySubanimation pop af ldh [rOBP0], a + call UpdateGBCPal_OBP0 .nextAnimationCommand pop hl jr .animationLoop @@ -366,12 +395,7 @@ AnimationTileset2: INCBIN "gfx/battle/attack_anim_2.2bpp" SlotMachineTiles2: -IF DEF(_RED) - INCBIN "gfx/slots/red_slots_2.2bpp" -ENDC -IF DEF(_BLUE) - INCBIN "gfx/slots/blue_slots_2.2bpp" -ENDC + INCBIN "gfx/slots/slots_2.2bpp" SlotMachineTiles2End: MoveAnimation: @@ -537,6 +561,8 @@ SetAnimationPalette: ldh [rOBP0], a ld a, $6c ldh [rOBP1], a + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 ret .notSGB ld a, $e4 @@ -544,6 +570,28 @@ SetAnimationPalette: ldh [rOBP0], a ld a, $6c ldh [rOBP1], a + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 + ret + +Func_78e98: + call SaveScreenTilesToBuffer2 + xor a + ldh [hAutoBGTransferEnabled], a + call ClearScreen + ld h, vBGMap0 / $100 + call WriteLowerByteOfBGMapAndEnableBGTransfer + call Delay3 + xor a + ldh [hAutoBGTransferEnabled], a + call LoadScreenTilesFromBuffer2 + ld h, vBGMap1 / $100 + +WriteLowerByteOfBGMapAndEnableBGTransfer: + ld l, vBGMap0 & $ff + call BattleAnimCopyTileMapToVRAM + ld a, $1 + ldh [hAutoBGTransferEnabled], a ret PlaySubanimation: @@ -659,6 +707,7 @@ DoBallTossSpecialEffects: ldh a, [rOBP0] xor %00111100 ; complement colors 1 and 2 ldh [rOBP0], a + call UpdateGBCPal_OBP0 .skipFlashingEffect ld a, [wSubAnimCounter] cp 11 ; is it the beginning of the subanimation? @@ -948,6 +997,7 @@ AnimationFlashScreenLong: cp $01 ; is it the end of the palettes? jr z, .endOfPalettes ldh [rBGP], a + call UpdateGBCPal_BGP call FlashScreenLongDelay jr .innerLoop .endOfPalettes @@ -1010,14 +1060,17 @@ AnimationFlashScreen: push af ; save initial palette ld a, %00011011 ; 0, 1, 2, 3 (inverted colors) ldh [rBGP], a + call UpdateGBCPal_BGP ld c, 2 call DelayFrames xor a ; white out background ldh [rBGP], a + call UpdateGBCPal_BGP ld c, 2 call DelayFrames pop af ldh [rBGP], a ; restore initial palette + call UpdateGBCPal_BGP ret AnimationDarkScreenPalette: @@ -1063,6 +1116,7 @@ SetAnimationBGPalette: ld a, c .next ldh [rBGP], a + call UpdateGBCPal_BGP ret ld b, $5 @@ -1107,15 +1161,30 @@ AnimationWaterDropletsEverywhere: _AnimationWaterDroplets: ld hl, wOAMBuffer .loop + ld a, $1 + ld [wdef5], a ld a, [wBaseCoordY] ld [hli], a ; Y + cp 40 + jr c, .asm_792d7 + ld a, [wdef5] + inc a + ld [wdef5], a +.asm_792d7 ld a, [wBaseCoordX] add 27 ld [wBaseCoordX], a ld [hli], a ; X + cp 88 + jr c, .asm_792ee + ld a, [wdef5] + add $2 + and $3 + ld [wdef5], a +.asm_792ee ld a, [wDropletTile] ld [hli], a ; tile - xor a + ld a, [wdef5] ld [hli], a ; attribute ld a, [wBaseCoordX] cp 144 @@ -1258,16 +1327,30 @@ BattleAnimWriteOAMEntry: ; Y coordinate = e (increased by 8 each call, before the write to OAM) ; X coordinate = [wBaseCoordX] ; tile = d -; attributes = 0 +; attributes = variable (dependant on coords) + ld a, $1 + ld [wdef5], a ld a, e add 8 ld e, a ld [hli], a + cp 40 + jr c, .asm_793d8 + ld a, [wdef5] + inc a + ld [wdef5], a +.asm_793d8 ld a, [wBaseCoordX] ld [hli], a + cp 88 + jr c, .asm_793e8 + ld a, [wdef5] + add $2 + ld [wdef5], a +.asm_793e8 ld a, d ld [hli], a - xor a + ld a, [wdef5] ld [hli], a ret @@ -1319,7 +1402,7 @@ AdjustOAMBlockYPos2: ret AnimationBlinkEnemyMon: -; Make the enemy mon's sprite blink on and off for a second or two + ; Make the enemy mon's sprite blink on and off for a second or two ld hl, AnimationBlinkMon jp CallWithTurnFlipped @@ -1472,6 +1555,8 @@ AnimationSpiralBallsInward: ld a, [hl] cp $ff jr z, .done + ld a, $2 + ld [wdef5], a ld a, [wSpiralBallsBaseY] add [hl] ld [de], a ; Y @@ -1480,9 +1565,20 @@ AnimationSpiralBallsInward: ld a, [wSpiralBallsBaseX] add [hl] ld [de], a ; X + cp 88 + jr c, .asm_79524 + ld a, $3 + ld [wdef5], a +.asm_79524 inc hl inc de inc de + ld a, [de] + and $f0 + ld b, a + ld a, [wdef5] + or b + ld [de], a inc de dec c jr nz, .innerLoop @@ -1784,7 +1880,7 @@ _AnimationSlideMonOff: jr nz, .slideLoop ret -; Since mon pic tile numbers go from top to bottom, left to right in order, +; Since mon pic tile numbers go from top to bottom, left to right in order, ; adding the height of the mon pic in tiles to a tile number gives the tile ; number of the tile one column to the right (and thus subtracting the height ; gives the reverse). If the next tile would be past the edge of the pic, the 2 @@ -1794,10 +1890,8 @@ _AnimationSlideMonOff: .PlayerNextTile ld a, [hl] add 7 -; This is a bug. The lower right corner tile of the mon back pic is blanked -; while the mon is sliding off the screen. It should compare with the max tile -; plus one instead. - cp $61 +; bugfix: compares against the max tile + 1 as opposed to the max tile + cp $62 ret c ld a, " " ret @@ -1934,18 +2028,24 @@ AnimationSubstitute: CopyMonsterSpriteData: ld bc, 1 tiles ld a, BANK(MonsterSprite) - jp FarCopyData2 + jp FarCopyData HideSubstituteShowMonAnim: ldh a, [hWhoseTurn] and a ld hl, wPlayerMonMinimized + ld de, wPlayerBattleStatus1 + ld bc, wPlayerMoveNum ld a, [wPlayerBattleStatus2] jr z, .next1 ld hl, wEnemyMonMinimized + ld de, wEnemyBattleStatus1 + ld bc, wEnemyMoveNum ld a, [wEnemyBattleStatus2] .next1 push hl + push de + push bc ; if the substitute broke, slide it down, else slide it offscreen horizontally bit HAS_SUBSTITUTE_UP, a jr nz, .substituteStillUp @@ -1954,12 +2054,65 @@ HideSubstituteShowMonAnim: .substituteStillUp call AnimationSlideMonOff .next2 + pop bc + pop de + ld a, [de] + bit INVULNERABLE, a pop hl + jr nz, .invulnerable + ld a, [bc] + cp FLY + jr z, .flyOrDig + cp DIG + jr z, .flyOrDig +.invulnerable ld a, [hl] and a jp nz, AnimationMinimizeMon call AnimationFlashMonPic jp AnimationShowMonPic +.flyOrDig + ldh a, [hWhoseTurn] + and a + jr nz, .enemy + ld a, [wPlayerMonMinimized] + and a + jr nz, .monIsMinimized + ld a, [wBattleMonSpecies] + ld [wcf91], a + ld [wd0b5], a + call GetMonHeader + predef LoadMonBackPic + ret +.enemy + ld a, [wEnemyMonMinimized] + and a + jr nz, .monIsMinimized + ld a, [wEnemyMonSpecies] + ld [wcf91], a + ld [wd0b5], a + call GetMonHeader + ld de, vFrontPic + jp LoadMonFrontSprite +.monIsMinimized + ld hl, wTempPic + push hl + xor a + ld bc, 7 * 7 * $10 + call FillMemory + pop hl + ld de, $194 + add hl, de + ld de, MinimizedMonSprite + ld c, MinimizedMonSpriteEnd - MinimizedMonSprite +.loop + ld a, [de] + ld [hli], a + ld [hli], a + inc de + dec c + jr nz, .loop + jp CopyTempPicToMonPic ReshowSubstituteAnim: call AnimationSlideMonOff @@ -2027,6 +2180,23 @@ AnimationHideEnemyMonPic: ldh [hAutoBGTransferEnabled], a jp Delay3 +Func_79929: + ld hl, wPlayerMonMinimized + ldh a, [hWhoseTurn] + and a + jr z, .playerTurn + ld hl, wEnemyMonMinimized +.playerTurn + ld a, [hl] + and a + jr z, .notMinimized + call AnimationMinimizeMon + ret +.notMinimized + call AnimationFlashMonPic + call AnimationShowMonPic + ret + InitMultipleObjectsOAM: ; Writes c OAM entries with tile d. ; Sets their Y coordinates to sequential multiples of 8, starting from 0. @@ -2048,6 +2218,8 @@ InitMultipleObjectsOAM: jr nz, .loop ret + ret ; unreferenced + AnimationHideMonPic: ; Hides the mon's sprite. ldh a, [hWhoseTurn] @@ -2074,7 +2246,7 @@ ClearMonPicFromTileMap: ret ; puts the tile map destination address of a mon sprite in hl, given the row count in b -; The usual row count is 7, but it may be smaller when sliding a mon sprite in/out, +; The usual row count is 7, but it may be smaller when sliding a mon sprite in/out, ; in order to show only a portion of the mon sprite. GetMonSpriteTileMapPointerFromRowCount: push de @@ -2270,17 +2442,13 @@ INCLUDE "data/tilemaps.asm" AnimationLeavesFalling: ; Makes leaves float down from the top of the screen. This is used ; in Razor Leaf's animation. - ldh a, [rOBP0] - push af ld a, [wAnimPalette] ldh [rOBP0], a + call UpdateGBCPal_OBP0 ld d, $37 ; leaf tile ld a, 3 ; number of leaves ld [wNumFallingObjects], a - call AnimationFallingObjects - pop af - ldh [rOBP0], a - ret + jp AnimationFallingObjects AnimationPetalsFalling: ; Makes lots of petals fall down from the top of the screen. It's used in @@ -2335,6 +2503,8 @@ FallingObjects_UpdateOAMEntry: ; movement byte. ld hl, wOAMBuffer add hl, de + ld a, $1 + ld [wdef5], a ld a, [hl] inc a inc a @@ -2343,6 +2513,12 @@ FallingObjects_UpdateOAMEntry: ld a, 160 ; if Y >= 112, put it off-screen .next ld [hli], a ; Y + cp 40 + jr c, .asm_79e51 + ld a, [wdef5] + inc a + ld [wdef5], a +.asm_79e51 ld a, [wFallingObjectMovementByte] ld b, a ld de, FallingObjects_DeltaXs @@ -2359,6 +2535,13 @@ FallingObjects_UpdateOAMEntry: ld a, [de] add [hl] ld [hli], a ; X + cp 88 + jr c, .asm_79e75 + ld a, [wdef5] + add $2 + and $3 + ld [wdef5], a +.asm_79e75 inc hl xor a ; no horizontal flip jr .next2 @@ -2368,9 +2551,19 @@ FallingObjects_UpdateOAMEntry: ld a, [hl] sub b ld [hli], a ; X + cp 88 + jr c, .asm_79e5c + ld a, [wdef5] + add $2 + and $3 + ld [wdef5], a +.asm_79e5c inc hl ld a, (1 << OAM_X_FLIP) .next2 + ld b, a + ld a, [wdef5] + or b ld [hl], a ; attribute ret @@ -2410,7 +2603,7 @@ FallingObjects_InitXCoords: ret FallingObjects_InitialXCoords: - db $38,$40,$50,$60,$70,$88,$90,$56,$67,$4A,$77,$84,$98,$32,$22,$5C,$6C,$7D,$8E,$99 + db $38, $40, $50, $60, $70, $88, $90, $56, $67, $4A, $77, $84, $98, $32, $22, $5C, $6C, $7D, $8E, $99 FallingObjects_InitMovementData: ld hl, wFallingObjectsMovementData @@ -2426,7 +2619,7 @@ FallingObjects_InitMovementData: ret FallingObjects_InitialMovementData: - db $00,$84,$06,$81,$02,$88,$01,$83,$05,$89,$09,$80,$07,$87,$03,$82,$04,$85,$08,$86 + db $00, $84, $06, $81, $02, $88, $01, $83, $05, $89, $09, $80, $07, $87, $03, $82, $04, $85, $08, $86 AnimationShakeEnemyHUD: ; Shakes the enemy HUD. @@ -2455,6 +2648,14 @@ AnimationShakeEnemyHUD: ld hl, vBGMap1 - $20 * 7 call BattleAnimCopyTileMapToVRAM +; update BGMap attributes + ldh a, [hGBC] + and a + jr z, .notGBC + ld c, 13 + farcall LoadBGMapAttributes +.notGBC + ; Move the window so that the row below the enemy HUD (in BG map 0) lines up ; with the top row of the window on the screen. This makes it so that the window ; covers everything below the enemy HD with a copy that looks just like what @@ -2488,13 +2689,18 @@ AnimationShakeEnemyHUD: ldh [hWY], a ld hl, vBGMap1 call BattleAnimCopyTileMapToVRAM +; update BGMap attributes + ldh a, [hGBC] + and a + jr z, .notGBC2 + ld c, 11 + farcall LoadBGMapAttributes +.notGBC2 xor a ldh [hWY], a call SaveScreenTilesToBuffer1 ld hl, vBGMap0 call BattleAnimCopyTileMapToVRAM - call ClearScreen - call Delay3 call LoadScreenTilesFromBuffer1 ld hl, vBGMap1 jp BattleAnimCopyTileMapToVRAM @@ -2583,7 +2789,7 @@ TossBallAnimation: .PokeBallAnimations: ; sequence of animations that make up the Poké Ball toss - db POOF_ANIM,HIDEPIC_ANIM,SHAKE_ANIM,POOF_ANIM,SHOWPIC_ANIM + db POOF_ANIM, HIDEPIC_ANIM, SHAKE_ANIM, POOF_ANIM, SHOWPIC_ANIM .BlockBall ld a, TOSS_ANIM diff --git a/engine/battle/bank3d_battle.asm b/engine/battle/bank3d_battle.asm new file mode 100644 index 00000000..48c3cde3 --- /dev/null +++ b/engine/battle/bank3d_battle.asm @@ -0,0 +1,292 @@ +InitBattle:: + ld a, [wCurOpponent] + and a + jr z, DetermineWildOpponent + +InitOpponent: + ld a, [wCurOpponent] + ld [wcf91], a + ld [wEnemyMonSpecies2], a + jr InitBattleCommon + +DetermineWildOpponent: + ld a, [wd732] + bit 1, a + jr z, .asm_3ef2f + ldh a, [hJoyHeld] + bit 1, a ; B button pressed? + ret nz +.asm_3ef2f + ld a, [wNumberOfNoRandomBattleStepsLeft] + and a + ret nz + callfar TryDoWildEncounter + ret nz +InitBattleCommon: + ld a, [wMapPalOffset] + push af + ld hl, wLetterPrintingDelayFlags + ld a, [hl] + push af + res 1, [hl] + call InitBattleVariables + ld a, [wEnemyMonSpecies2] + sub OPP_ID_OFFSET + jp c, InitWildBattle + ld [wTrainerClass], a + call GetTrainerInformation + callfar ReadTrainer + callfar DoBattleTransitionAndInitBattleVariables + call _LoadTrainerPic + xor a + ld [wEnemyMonSpecies2], a + ldh [hStartTileID], a + dec a + ld [wAICount], a + hlcoord 12, 0 + predef CopyUncompressedPicToTilemap + ld a, $ff + ld [wEnemyMonPartyPos], a + ld a, $2 + ld [wIsInBattle], a + +; Is this a major story battle? + ld a, [wLoneAttackNo] + and a + jp z, _InitBattleCommon + callabd_ModifyPikachuHappiness PIKAHAPPY_GYMLEADER ; useless since already in bank3d + jp _InitBattleCommon + +InitWildBattle: + ld a, $1 + ld [wIsInBattle], a + callfar LoadEnemyMonData + callfar DoBattleTransitionAndInitBattleVariables + ld a, [wCurOpponent] + cp RESTLESS_SOUL + jr z, .isGhost + callfar IsGhostBattle + jr nz, .isNoGhost +.isGhost + ld hl, wMonHSpriteDim + ld a, $66 + ld [hli], a ; write sprite dimensions + ld bc, GhostPic + ld a, c + ld [hli], a ; write front sprite pointer + ld [hl], b + ld hl, wEnemyMonNick ; set name to "GHOST" + ld a, "G" + ld [hli], a + ld a, "H" + ld [hli], a + ld a, "O" + ld [hli], a + ld a, "S" + ld [hli], a + ld a, "T" + ld [hli], a + ld [hl], "@" + ld a, [wcf91] + push af + ld a, MON_GHOST + ld [wcf91], a + ld de, vFrontPic + call LoadMonFrontSprite ; load ghost sprite + pop af + ld [wcf91], a + jr .spriteLoaded +.isNoGhost + ld de, vFrontPic + call LoadMonFrontSprite ; load mon sprite +.spriteLoaded + xor a + ld [wTrainerClass], a + ldh [hStartTileID], a + hlcoord 12, 0 + predef CopyUncompressedPicToTilemap + +; common code that executes after init battle code specific to trainer or wild battles +_InitBattleCommon: + ld b, SET_PAL_BATTLE_BLACK + call RunPaletteCommand + callfar SlidePlayerAndEnemySilhouettesOnScreen + xor a + ldh [hAutoBGTransferEnabled], a + ld hl, .emptyString + call PrintText + call SaveScreenTilesToBuffer1 + call ClearScreen + ld a, $98 + ldh [hAutoBGTransferDest + 1], a + ld a, $1 + ldh [hAutoBGTransferEnabled], a + call Delay3 + ld a, $9c + ldh [hAutoBGTransferDest + 1], a + call LoadScreenTilesFromBuffer1 + hlcoord 9, 7 + lb bc, 5, 10 + call ClearScreenArea + hlcoord 1, 0 + lb bc, 4, 10 + call ClearScreenArea + call ClearSprites + ld a, [wIsInBattle] + dec a ; is it a wild battle? + ld hl, DrawEnemyHUDAndHPBar + ld b, BANK(DrawEnemyHUDAndHPBar) + call z, Bankswitch ; draw enemy HUD and HP bar if it's a wild battle + callfar StartBattle + callfar EndOfBattle + pop af + ld [wLetterPrintingDelayFlags], a + pop af + ld [wMapPalOffset], a + ld a, [wSavedTilesetType] + ldh [hTilesetType], a + scf + ret +.emptyString + db "@" + +_LoadTrainerPic: +; wd033-wd034 contain pointer to pic + ld a, [wTrainerPicPointer] + ld e, a + ld a, [wTrainerPicPointer + 1] + ld d, a ; de contains pointer to trainer pic + ld a, [wLinkState] + and a + ld a, BANK(TrainerPics) ; this is where all the trainer pics are (not counting Red's) + jr z, .loadSprite + ld a, BANK(RedPicFront) +.loadSprite + call UncompressSpriteFromDE + ld de, vFrontPic + ld a, $77 + ld c, a + jp LoadUncompressedSpriteData + +LoadMonBackPic: +; Assumes the monster's attributes have +; been loaded with GetMonHeader. + ld a, [wBattleMonSpecies2] + ld [wcf91], a + hlcoord 1, 5 + lb bc, 7, 8 + call ClearScreenArea + ld hl, wMonHBackSprite - wMonHeader + call UncompressMonSprite + predef ScaleSpriteByTwo + ld de, vBackPic + call InterlaceMergeSpriteBuffers ; combine the two buffers to a single 2bpp sprite + ld hl, vSprites + ld de, vBackPic + ld c, (2*SPRITEBUFFERSIZE)/16 ; count of 16-byte chunks to be copied + ldh a, [hLoadedROMBank] + ld b, a + jp CopyVideoData + +AnimateSendingOutMon: + ld a, [wPredefRegisters] + ld h, a + ld a, [wPredefRegisters + 1] + ld l, a + ldh a, [hStartTileID] + ldh [hDownArrowBlinkCount1], a + ld b, $4c + ld a, [wIsInBattle] + and a + jr z, .asm_f61ef + add b + ld [hl], a + call Delay3 + ld bc, -41 + add hl, bc + ld a, $1 + ld [wNumMovesMinusOne], a + ld bc, $303 + predef CopyDownscaledMonTiles + ld c, $4 + call DelayFrames + ld bc, -41 + add hl, bc + xor a + ld [wNumMovesMinusOne], a + ld bc, $505 + predef CopyDownscaledMonTiles + ld c, $5 + call DelayFrames + ld bc, -41 + jr .asm_f61f2 +.asm_f61ef + ld bc, -123 +.asm_f61f2 + add hl, bc + ldh a, [hDownArrowBlinkCount1] + add $31 + jr CopyUncompressedPicToHL + +CopyUncompressedPicToTilemap: + ld a, [wPredefRegisters] + ld h, a + ld a, [wPredefRegisters + 1] + ld l, a + ldh a, [hStartTileID] +CopyUncompressedPicToHL:: + ld bc, $707 + ld de, $14 + push af + ld a, [wSpriteFlipped] + and a + jr nz, .asm_f6220 + pop af +.asm_f6211 + push bc + push hl +.asm_f6213 + ld [hl], a + add hl, de + inc a + dec c + jr nz, .asm_f6213 + pop hl + inc hl + pop bc + dec b + jr nz, .asm_f6211 + ret + +.asm_f6220 + push bc + ld b, $0 + dec c + add hl, bc + pop bc + pop af +.asm_f6227 + push bc + push hl +.asm_f6229 + ld [hl], a + add hl, de + inc a + dec c + jr nz, .asm_f6229 + pop hl + dec hl + pop bc + dec b + jr nz, .asm_f6227 + ret + +INCLUDE "engine/battle/init_battle_variables.asm" +INCLUDE "engine/battle/move_effects/focus_energy.asm" +INCLUDE "engine/battle/move_effects/heal.asm" +INCLUDE "engine/battle/move_effects/transform.asm" +INCLUDE "engine/battle/move_effects/reflect_light_screen.asm" +INCLUDE "engine/battle/move_effects/mist.asm" +INCLUDE "engine/battle/move_effects/one_hit_ko.asm" +INCLUDE "engine/battle/move_effects/pay_day.asm" +INCLUDE "engine/battle/move_effects/paralyze.asm" diff --git a/engine/battle/battle_transitions.asm b/engine/battle/battle_transitions.asm index 90e99f98..82c3318c 100644 --- a/engine/battle/battle_transitions.asm +++ b/engine/battle/battle_transitions.asm @@ -163,6 +163,9 @@ BattleTransition_BlackScreen: ldh [rBGP], a ldh [rOBP0], a ldh [rOBP1], a + call UpdateGBCPal_BGP + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 ret ; for non-dungeon trainer battles @@ -326,6 +329,7 @@ BattleTransition_FlashScreen_: cp 1 jr z, .done ldh [rBGP], a + call UpdateGBCPal_BGP ld c, 2 call DelayFrames jr .loop @@ -351,7 +355,7 @@ BattleTransition_FlashScreenPalettes: ; used for low level trainer dungeon battles BattleTransition_Shrink: - ld c, SCREEN_HEIGHT / 2 + ld c, 9 .loop push bc xor a @@ -385,7 +389,7 @@ BattleTransition_Shrink: ; used for high level trainer dungeon battles BattleTransition_Split: - ld c, SCREEN_HEIGHT / 2 + ld c, 9 xor a ldh [hAutoBGTransferEnabled], a .loop diff --git a/engine/battle/common_text.asm b/engine/battle/common_text.asm index 0e270424..95c06bf5 100644 --- a/engine/battle/common_text.asm +++ b/engine/battle/common_text.asm @@ -8,8 +8,20 @@ PrintBeginningBattleText: cp POKEMON_TOWER_7F + 1 jr c, .pokemonTower .notPokemonTower + ld a, [wBattleType] + cp BATTLE_TYPE_PIKACHU + jr nz, .notPikachuBattle + callfar IsPlayerPikachuAsleepInParty + ld e, $24 + jr c, .asm_f4026 + ld e, $a +.asm_f4026 + callfar PlayPikachuSoundClip + jr .continue +.notPikachuBattle ld a, [wEnemyMonSpecies2] call PlayCry +.continue ld hl, WildMonAppearedText ld a, [wMoveMissed] and a @@ -23,9 +35,13 @@ PrintBeginningBattleText: call DelayFrames ld hl, TrainerWantsToFightText .wildBattle + ld a, [wBattleType] + and a + jr nz, .doNotDrawPokeballs push hl callfar DrawAllPokeballs pop hl +.doNotDrawPokeballs call PrintText jr .done .pokemonTower diff --git a/engine/battle/core.asm b/engine/battle/core.asm index 4628e86a..f66f509f 100755 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -67,6 +67,9 @@ SlidePlayerAndEnemySilhouettesOnScreen: ldh [rBGP], a ldh [rOBP0], a ldh [rOBP1], a + call UpdateGBCPal_BGP + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 .slideSilhouettesLoop ; slide silhouettes of the player's pic and the enemy's pic onto the screen ld h, b ld l, $40 @@ -156,10 +159,16 @@ StartBattle: call DelayFrames call SaveScreenTilesToBuffer1 .checkAnyPartyAlive + ld a, [wBattleType] + cp BATTLE_TYPE_RUN + jp z, .specialBattle + cp BATTLE_TYPE_PIKACHU + jp z, .specialBattle call AnyPartyAlive ld a, d and a jp z, HandlePlayerBlackOut ; jump if no mon is alive +.specialBattle call LoadScreenTilesFromBuffer1 ld a, [wBattleType] and a ; is it a normal battle? @@ -893,6 +902,11 @@ ReplaceFaintedEnemyMon: ld hl, wEnemyHPBarColor ld e, $30 call GetBattleHealthBarColor + setpal SHADE_BLACK, SHADE_DARK, SHADE_LIGHT, SHADE_WHITE + ldh [rOBP0], a + ldh [rOBP1], a + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 callfar DrawEnemyPokeballs ld a, [wLinkState] cp LINK_STATE_BATTLING @@ -958,9 +972,7 @@ TrainerDefeatedText: PlayBattleVictoryMusic: push af - ld a, SFX_STOP_ALL_MUSIC - ld [wNewSoundID], a - call PlaySoundWaitForCurrent + call StopAllMusic ld c, BANK(Music_DefeatedTrainer) pop af call PlayMusic @@ -1014,6 +1026,7 @@ RemoveFaintedPlayerMon: ld a, $ff ld [wLowHealthAlarm], a ;disable low health alarm call WaitForSoundToFinish + xor a .skipWaitForSound ; a is 0, so this zeroes the enemy's accumulated damage. ld hl, wEnemyBideAccumulatedDamage @@ -1038,10 +1051,36 @@ RemoveFaintedPlayerMon: and a ; was this called by HandleEnemyMonFainted? ret z ; if so, return + ld a, [wPlayerMonNumber] + ld [wWhichPokemon], a + callfar IsThisPartymonStarterPikachu_Party + jr nc, .notPlayerPikachu + ld e, $3 + callfar PlayPikachuSoundClip + jr .printText +.notPlayerPikachu ld a, [wBattleMonSpecies] call PlayCry +.printText ld hl, PlayerMonFaintedText - jp PrintText + call PrintText + ld a, [wPlayerMonNumber] + ld [wWhichPokemon], a + ld a, [wBattleMonLevel] + ld b, a + ld a, [wEnemyMonLevel] + sub b ; enemylevel - playerlevel + ; are we stronger than the opposing pokemon? + jr c, .regularFaint ; if so, deduct happiness regularly + + cp 30 ; is the enemy 30 levels greater than us? + jr nc, .carelessTrainer ; if so, punish the player for being careless, as they shouldn't be fighting a very high leveled trainer with such a level difference +.regularFaint + callabd_ModifyPikachuHappiness PIKAHAPPY_FAINTED + ret +.carelessTrainer + callabd_ModifyPikachuHappiness PIKAHAPPY_CARELESSTRAINER + ret PlayerMonFaintedText: text_far _PlayerMonFaintedText @@ -1098,7 +1137,7 @@ ChooseNextMon: ld a, [wLinkState] cp LINK_STATE_BATTLING jr nz, .notLinkBattle - inc a + ld a, 1 ld [wActionResultOrTookBattleTurn], a call LinkBattleExchangeData .notLinkBattle @@ -1498,6 +1537,8 @@ TryRunningFromBattle: ld a, [wBattleType] cp BATTLE_TYPE_SAFARI jp z, .canEscape ; jump if it's a safari battle + cp BATTLE_TYPE_RUN + jp z, .canEscape ; hurry, get away? ld a, [wLinkState] cp LINK_STATE_BATTLING jp z, .canEscape @@ -1753,19 +1794,46 @@ SendOutMon: call RunPaletteCommand ld hl, wEnemyBattleStatus1 res USING_TRAPPING_MOVE, [hl] + callfar IsThisPartymonStarterPikachu + jr c, .starterPikachu ld a, $1 ldh [hWhoseTurn], a ld a, POOF_ANIM call PlayMoveAnimation hlcoord 4, 11 predef AnimateSendingOutMon + jr .playRegularCry +.starterPikachu + xor a + ldh [hWhoseTurn], a + ld a, $1 + ldh [hAutoBGTransferEnabled], a + callfar StarterPikachuBattleEntranceAnimation + callfar IsPlayerPikachuAsleepInParty + ld e, $24 + jr c, .asm_3cd81 + ld e, $a +.asm_3cd81 + callfar PlayPikachuSoundClip + jr .done +.playRegularCry ld a, [wcf91] call PlayCry +.done call PrintEmptyString jp SaveScreenTilesToBuffer1 ; show 2 stages of the player mon getting smaller before disappearing AnimateRetreatingPlayerMon: + ld a, [wWhichPokemon] + push af + ld a, [wPlayerMonNumber] + ld [wWhichPokemon], a + callfar IsThisPartymonStarterPikachu + pop bc + ld a, b + ld [wWhichPokemon], a + jr c, .starterPikachu hlcoord 1, 5 lb bc, 7, 7 call ClearScreenArea @@ -1789,10 +1857,17 @@ AnimateRetreatingPlayerMon: call .clearScreenArea ld a, $4c ldcoord_a 5, 11 + jr .clearScreenArea +.starterPikachu + xor a + ldh [hWhoseTurn], a + callfar AnimationSlideMonOff + ret .clearScreenArea hlcoord 1, 5 lb bc, 7, 7 - jp ClearScreenArea + call ClearScreenArea + ret ; reads player's current mon's HP into wBattleMonHP ReadPlayerMonCurHPAndStatus: @@ -2014,36 +2089,49 @@ DisplayBattleMenu:: ld [wTextBoxID], a call DisplayTextBoxID ld a, [wBattleType] - dec a - jp nz, .handleBattleMenuInput ; handle menu input if it's not the old man tutorial -; the following happens for the old man tutorial + cp BATTLE_TYPE_OLD_MAN + jr z, .doSimulatedMenuInput ; simulate menu input if it's the old man or prof. oak pikachu battle + cp BATTLE_TYPE_PIKACHU + jr z, .doSimulatedMenuInput + jp .handleBattleMenuInput +; the following happens for the old man tutorial and prof. oak pikachu battle +.doSimulatedMenuInput ld hl, wPlayerName ld de, wGrassRate ld bc, NAME_LENGTH call CopyData ; temporarily save the player name in unused space, ; which is supposed to get overwritten when entering a - ; map with wild Pokémon. Due to an oversight, the data + ; map with wild Pokémon. + ; In Red/Blue, due to an oversight, the data ; may not get overwritten (cinnabar) and the infamous - ; Missingno. glitch can show up. + ; Missingno. glitch can show up. However, + ; this has been fixed in yellow ld hl, .oldManName + ld a, [wBattleType] + dec a + jr z, .useOldManName + ld hl, .profOakName +.useOldManName ld de, wPlayerName ld bc, NAME_LENGTH call CopyData ; the following simulates the keystrokes by drawing menus on screen hlcoord 9, 14 ld [hl], "▶" - ld c, 80 + ld c, 20 call DelayFrames ld [hl], " " hlcoord 9, 16 ld [hl], "▶" - ld c, 50 + ld c, 20 call DelayFrames ld [hl], "▷" ld a, $2 ; select the "ITEM" menu jp .upperLeftMenuItemWasNotSelected .oldManName db "OLD MAN@" +.profOakName + db "PROF.OAK@" .handleBattleMenuInput ld a, [wBattleAndStartSavedMenuItem] ld [wCurrentMenuItem], a @@ -2126,6 +2214,9 @@ DisplayBattleMenu:: .AButtonPressed call PlaceUnfilledArrowMenuCursor ld a, [wBattleType] + cp BATTLE_TYPE_RUN + jr z, .handleUnusedBattle + ld a, [wBattleType] cp BATTLE_TYPE_SAFARI ld a, [wCurrentMenuItem] ld [wBattleAndStartSavedMenuItem], a @@ -2157,7 +2248,18 @@ DisplayBattleMenu:: .throwSafariBallWasSelected ld a, SAFARI_BALL ld [wcf91], a - jr UseBagItem + jp UseBagItem +.handleUnusedBattle + ld a, [wCurrentMenuItem] + cp $3 + jp z, BattleMenu_RunWasSelected + ld hl, .RunAwayText + call PrintText + jp DisplayBattleMenu + +.RunAwayText + text_far _RunAwayText + text_end .upperLeftMenuItemWasNotSelected ; a menu item other than the upper left item was selected cp $2 @@ -2194,19 +2296,23 @@ BagWasSelected: call DrawHUDsAndHPBars .next ld a, [wBattleType] - dec a ; is it the old man tutorial? - jr nz, DisplayPlayerBag ; no, it is a normal battle - ld hl, OldManItemList + cp BATTLE_TYPE_OLD_MAN ; is it the old man tutorial? + jr z, .simulatedInputBattle + cp BATTLE_TYPE_PIKACHU ; is it the prof oak battle with pikachu? + jr z, .simulatedInputBattle + jr DisplayPlayerBag +.simulatedInputBattle + ld hl, SimulatedInputBattleItemList ld a, l ld [wListPointer], a ld a, h ld [wListPointer + 1], a jr DisplayBagMenu -OldManItemList: - db 1 ; # items - db POKE_BALL, 50 - db -1 +SimulatedInputBattleItemList: + db 1 ; # of items + db POKE_BALL, 1 + db $ff DisplayPlayerBag: ; get the pointer to player's bag when in a normal battle @@ -2365,6 +2471,8 @@ PartyMenuOrRockOrRun: predef StatusScreen predef StatusScreen2 ; now we need to reload the enemy mon pic + ld a, 1 + ldh [hWhoseTurn], a ld a, [wEnemyBattleStatus2] bit HAS_SUBSTITUTE_UP, a ; does the enemy mon have a substitute? ld hl, AnimationSubstitute @@ -2469,13 +2577,13 @@ MoveSelectionMenu: .writemoves ld de, wMovesString - ldh a, [hFlagsFFF6] + ldh a, [hFlagsFFFA] set 2, a - ldh [hFlagsFFF6], a + ldh [hFlagsFFFA], a call PlaceString - ldh a, [hFlagsFFF6] + ldh a, [hFlagsFFFA] res 2, a - ldh [hFlagsFFF6], a + ldh [hFlagsFFFA], a ret .regularmenu @@ -2484,8 +2592,7 @@ MoveSelectionMenu: ld hl, wBattleMonMoves call .loadmoves hlcoord 4, 12 - ld b, 4 - ld c, 14 + lb bc, 4, 14 di ; out of pure coincidence, it is possible for vblank to occur between the di and ei ; so it is necessary to put the di ei block to not cause tearing call TextBoxBorder @@ -2503,8 +2610,7 @@ MoveSelectionMenu: ld hl, wEnemyMonMoves call .loadmoves hlcoord 0, 7 - ld b, 4 - ld c, 14 + lb bc, 4, 14 call TextBoxBorder hlcoord 2, 8 call .writemoves @@ -2518,8 +2624,7 @@ MoveSelectionMenu: call AddNTimes call .loadmoves hlcoord 4, 7 - ld b, 4 - ld c, 14 + lb bc, 4, 14 call TextBoxBorder hlcoord 6, 8 call .writemoves @@ -2533,8 +2638,6 @@ MoveSelectionMenu: ld a, [wMoveMenuType] cp $1 jr z, .selectedmoveknown - ld a, $1 - jr nc, .selectedmoveknown ld a, [wPlayerMoveListIndex] inc a .selectedmoveknown @@ -2595,10 +2698,10 @@ SelectMenuItem: call AddNTimes ld [hl], "▷" .select - ld hl, hFlagsFFF6 + ld hl, hFlagsFFFA set 1, [hl] call HandleMenuInput - ld hl, hFlagsFFF6 + ld hl, hFlagsFFFA res 1, [hl] bit 6, a jp nz, SelectMenuItem_CursorUp ; up @@ -2700,6 +2803,55 @@ SelectMenuItem_CursorDown: ld [wCurrentMenuItem], a jp SelectMenuItem +Func_3d4f5: + bit 3, a + ld a, $0 + jr nz, .asm_3d4fd + ld a, $1 +.asm_3d4fd + ldh [hWhoseTurn], a + call LoadScreenTilesFromBuffer1 + call Func_3d536 + ld a, [wTestBattlePlayerSelectedMove] + and a + jp z, MoveSelectionMenu + ld [wAnimationID], a + xor a + ld [wAnimationType], a + predef MoveAnimation + callfar Func_78e98 + jp MoveSelectionMenu + +Func_3d523: + ld a, [wTestBattlePlayerSelectedMove] + dec a + jr asm_3d52d +Func_3d529: + ld a, [wTestBattlePlayerSelectedMove] + inc a +asm_3d52d: + ld [wTestBattlePlayerSelectedMove], a + call Func_3d536 + jp MoveSelectionMenu + +Func_3d536: + hlcoord 10, 16 + lb bc, 2, 10 + call ClearScreenArea + hlcoord 10, 17 + ld de, wTestBattlePlayerSelectedMove + lb bc, LEADING_ZEROES | 1, 3 + call PrintNumber + ld a, [wTestBattlePlayerSelectedMove] + and a + ret z + cp STRUGGLE + ret nc + ld [wd11e], a + call GetMoveName + hlcoord 13, 17 + jp PlaceString + AnyMoveToSelect: ; return z and Struggle as the selected move if all moves have 0 PP and/or are disabled ld a, STRUGGLE @@ -2733,7 +2885,10 @@ AnyMoveToSelect: or c jr .handleDisabledMovePPLoop .allMovesChecked - and a ; any PP left? +; bugfix: only check PP value and not PP up bits +; in case all other moves have no PP left and a move has a PP up used on it +; and a non-PP up move is disabled + and $3f ; any PP left? ret nz ; return if a move has PP left .noMovesLeft ld hl, NoMovesLeftText @@ -2748,6 +2903,9 @@ NoMovesLeftText: text_end SwapMovesInMenu: + ld a, [wPlayerBattleStatus3] + bit TRANSFORMED, a + jp nz, MoveSelectionMenu ld a, [wMenuItemToSwap] and a jr z, .noMenuItemSelected @@ -2827,8 +2985,7 @@ PrintMenuItem: xor a ldh [hAutoBGTransferEnabled], a hlcoord 0, 8 - ld b, 3 - ld c, 9 + lb bc, 3, 9 call TextBoxBorder ld a, [wPlayerDisabledMove] and a @@ -2895,7 +3052,7 @@ PrintMenuItem: jp Delay3 DisabledText: - db "disabled!@" + db "Disabled!@" TypeText: db "TYPE@" @@ -4574,7 +4731,7 @@ JumpToOHKOMoveEffect: INCLUDE "data/battle/unused_critical_hit_moves.asm" ; determines if attack is a critical hit -; azure heights claims "the fastest pokémon (who are,not coincidentally, +; azure heights claims "the fastest pokémon (who are, not coincidentally, ; among the most popular) tend to CH about 20 to 25% of the time." CriticalHitTest: xor a @@ -4988,7 +5145,7 @@ AttackSubstitute: ldh a, [hWhoseTurn] xor $01 ldh [hWhoseTurn], a - callfar HideSubstituteShowMonAnim ; animate the substitute breaking + callfar Func_79929 ; animate the substitute breaking ; flip the turn back to the way it was ldh a, [hWhoseTurn] xor $01 @@ -5285,32 +5442,26 @@ AdjustDamageForMoveType: .done ret -; function to tell how effective the type of an enemy attack is on the player's current pokemon -; this doesn't take into account the effects that dual types can have -; (e.g. 4x weakness / resistance, weaknesses and resistances canceling) -; the result is stored in [wTypeEffectiveness] -; ($05 is not very effective, $10 is neutral, $14 is super effective) -; as far is can tell, this is only used once in some AI code to help decide which move to use AIGetTypeEffectiveness: ld a, [wEnemyMoveType] - ld d, a ; d = type of enemy move + ld d, a ; d = type of enemy move ld hl, wBattleMonType - ld b, [hl] ; b = type 1 of player's pokemon + ld b, [hl] ; b = type 1 of player's pokemon inc hl - ld c, [hl] ; c = type 2 of player's pokemon + ld c, [hl] ; c = type 2 of player's pokemon ld a, $10 - ld [wTypeEffectiveness], a ; initialize to neutral effectiveness + ld [wd11e], a ; initialize [wd11e] to neutral effectiveness ld hl, TypeEffects .loop ld a, [hli] cp $ff ret z - cp d ; match the type of the move + cp d ; match the type of the move jr nz, .nextTypePair1 ld a, [hli] - cp b ; match with type 1 of pokemon + cp b ; match with type 1 of pokemon jr z, .done - cp c ; or match with type 2 of pokemon + cp c ; or match with type 2 of pokemon jr z, .done jr .nextTypePair2 .nextTypePair1 @@ -5318,9 +5469,21 @@ AIGetTypeEffectiveness: .nextTypePair2 inc hl jr .loop + .done + ld a, [wTrainerClass] + cp LORELEI + jr nz, .ok + ld a, [wEnemyMonSpecies] + cp DEWGONG + jr nz, .ok + call BattleRandom + cp $66 ; 40 percent + ret c +.ok + ld a, [hl] - ld [wTypeEffectiveness], a ; store damage multiplier + ld [wd11e], a ; store damage multiplier ret INCLUDE "data/types/type_matchups.asm" @@ -6299,10 +6462,13 @@ SwapPlayerAndEnemyLevels: ; (for use when scrolling the player sprite and enemy's silhouettes on screen) LoadPlayerBackPic: ld a, [wBattleType] - dec a ; is it the old man tutorial? - ld de, RedPicBack - jr nz, .next ld de, OldManPic + cp BATTLE_TYPE_OLD_MAN ; is it the old man tutorial? + jr z, .next + ld de, ProfOakPicBack + cp BATTLE_TYPE_PIKACHU ; is it the pikachu battle at the beginning of the game? + jr z, .next + ld de, RedPicBack .next ld a, BANK(RedPicBack) call UncompressSpriteFromDE @@ -6327,6 +6493,8 @@ LoadPlayerBackPic: ld [hli], a ; OAM tile number inc a ; increment tile number ldh [hOAMTile], a + ld a, $2 + ld [hl], a inc hl dec c jr nz, .innerLoop @@ -6340,18 +6508,15 @@ LoadPlayerBackPic: jr nz, .loop ld de, vBackPic call InterlaceMergeSpriteBuffers - ld a, $a - ld [MBC1SRamEnable], a - xor a - ld [MBC1SRamBank], a + ld a, $0 + call SwitchSRAMBankAndLatchClockData ld hl, vSprites ld de, sSpriteBuffer1 ldh a, [hLoadedROMBank] ld b, a ld c, 7 * 7 call CopyVideoData - xor a - ld [MBC1SRamEnable], a + call PrepareRTCDataAndDisableSRAM ld a, $31 ldh [hStartTileID], a hlcoord 1, 5 @@ -6723,288 +6888,6 @@ HandleExplodingAnimation: PlayMoveAnimation: ld [wAnimationID], a call Delay3 - predef_jump MoveAnimation - -InitBattle:: - ld a, [wCurOpponent] - and a - jr z, DetermineWildOpponent - -InitOpponent: - ld a, [wCurOpponent] - ld [wcf91], a - ld [wEnemyMonSpecies2], a - jr InitBattleCommon - -DetermineWildOpponent: - ld a, [wd732] - bit 1, a - jr z, .asm_3ef2f - ldh a, [hJoyHeld] - bit 1, a ; B button pressed? - ret nz -.asm_3ef2f - ld a, [wNumberOfNoRandomBattleStepsLeft] - and a - ret nz - callfar TryDoWildEncounter - ret nz -InitBattleCommon: - ld a, [wMapPalOffset] - push af - ld hl, wLetterPrintingDelayFlags - ld a, [hl] - push af - res 1, [hl] - callfar InitBattleVariables - ld a, [wEnemyMonSpecies2] - sub OPP_ID_OFFSET - jp c, InitWildBattle - ld [wTrainerClass], a - call GetTrainerInformation - callfar ReadTrainer - call DoBattleTransitionAndInitBattleVariables - call _LoadTrainerPic - xor a - ld [wEnemyMonSpecies2], a - ldh [hStartTileID], a - dec a - ld [wAICount], a - hlcoord 12, 0 - predef CopyUncompressedPicToTilemap - ld a, $ff - ld [wEnemyMonPartyPos], a - ld a, $2 - ld [wIsInBattle], a - jp _InitBattleCommon - -InitWildBattle: - ld a, $1 - ld [wIsInBattle], a - call LoadEnemyMonData - call DoBattleTransitionAndInitBattleVariables - ld a, [wCurOpponent] - cp RESTLESS_SOUL - jr z, .isGhost - call IsGhostBattle - jr nz, .isNoGhost -.isGhost - ld hl, wMonHSpriteDim - ld a, $66 - ld [hli], a ; write sprite dimensions - ld bc, GhostPic - ld a, c - ld [hli], a ; write front sprite pointer - ld [hl], b - ld hl, wEnemyMonNick ; set name to "GHOST" - ld a, "G" - ld [hli], a - ld a, "H" - ld [hli], a - ld a, "O" - ld [hli], a - ld a, "S" - ld [hli], a - ld a, "T" - ld [hli], a - ld [hl], "@" - ld a, [wcf91] - push af - ld a, MON_GHOST - ld [wcf91], a - ld de, vFrontPic - call LoadMonFrontSprite ; load ghost sprite - pop af - ld [wcf91], a - jr .spriteLoaded -.isNoGhost - ld de, vFrontPic - call LoadMonFrontSprite ; load mon sprite -.spriteLoaded - xor a - ld [wTrainerClass], a - ldh [hStartTileID], a - hlcoord 12, 0 - predef CopyUncompressedPicToTilemap - -; common code that executes after init battle code specific to trainer or wild battles -_InitBattleCommon: - ld b, SET_PAL_BATTLE_BLACK - call RunPaletteCommand - call SlidePlayerAndEnemySilhouettesOnScreen - xor a - ldh [hAutoBGTransferEnabled], a - ld hl, .emptyString - call PrintText - call SaveScreenTilesToBuffer1 - call ClearScreen - ld a, $98 - ldh [hAutoBGTransferDest + 1], a - ld a, $1 - ldh [hAutoBGTransferEnabled], a - call Delay3 - ld a, $9c - ldh [hAutoBGTransferDest + 1], a - call LoadScreenTilesFromBuffer1 - hlcoord 9, 7 - lb bc, 5, 10 - call ClearScreenArea - hlcoord 1, 0 - lb bc, 4, 10 - call ClearScreenArea - call ClearSprites - ld a, [wIsInBattle] - dec a ; is it a wild battle? - call z, DrawEnemyHUDAndHPBar ; draw enemy HUD and HP bar if it's a wild battle - call StartBattle - callfar EndOfBattle - pop af - ld [wLetterPrintingDelayFlags], a - pop af - ld [wMapPalOffset], a - ld a, [wSavedTilesetType] - ldh [hTilesetType], a - scf + predef MoveAnimation + callfar Func_78e98 ret -.emptyString - db "@" - -_LoadTrainerPic: -; wd033-wd034 contain pointer to pic - ld a, [wTrainerPicPointer] - ld e, a - ld a, [wTrainerPicPointer + 1] - ld d, a ; de contains pointer to trainer pic - ld a, [wLinkState] - and a - ld a, BANK(TrainerPics) ; this is where all the trainer pics are (not counting Red's) - jr z, .loadSprite - ld a, BANK(RedPicFront) -.loadSprite - call UncompressSpriteFromDE - ld de, vFrontPic - ld a, $77 - ld c, a - jp LoadUncompressedSpriteData - -; unreferenced -ResetCryModifiers: - xor a - ld [wFrequencyModifier], a - ld [wTempoModifier], a - jp PlaySound - -; animates the mon "growing" out of the pokeball -AnimateSendingOutMon: - ld a, [wPredefRegisters] - ld h, a - ld a, [wPredefRegisters + 1] - ld l, a - ldh a, [hStartTileID] - ldh [hBaseTileID], a - ld b, $4c - ld a, [wIsInBattle] - and a - jr z, .notInBattle - add b - ld [hl], a - call Delay3 - ld bc, -(SCREEN_WIDTH * 2 + 1) - add hl, bc - ld a, 1 - ld [wDownscaledMonSize], a - lb bc, 3, 3 - predef CopyDownscaledMonTiles - ld c, 4 - call DelayFrames - ld bc, -(SCREEN_WIDTH * 2 + 1) - add hl, bc - xor a - ld [wDownscaledMonSize], a - lb bc, 5, 5 - predef CopyDownscaledMonTiles - ld c, 5 - call DelayFrames - ld bc, -(SCREEN_WIDTH * 2 + 1) - jr .next -.notInBattle - ld bc, -(SCREEN_WIDTH * 6 + 3) -.next - add hl, bc - ldh a, [hBaseTileID] - add $31 - jr CopyUncompressedPicToHL - -CopyUncompressedPicToTilemap: - ld a, [wPredefRegisters] - ld h, a - ld a, [wPredefRegisters + 1] - ld l, a - ldh a, [hStartTileID] -CopyUncompressedPicToHL:: - lb bc, 7, 7 - ld de, SCREEN_WIDTH - push af - ld a, [wSpriteFlipped] - and a - jr nz, .flipped - pop af -.loop - push bc - push hl -.innerLoop - ld [hl], a - add hl, de - inc a - dec c - jr nz, .innerLoop - pop hl - inc hl - pop bc - dec b - jr nz, .loop - ret - -.flipped - push bc - ld b, 0 - dec c - add hl, bc - pop bc - pop af -.flippedLoop - push bc - push hl -.flippedInnerLoop - ld [hl], a - add hl, de - inc a - dec c - jr nz, .flippedInnerLoop - pop hl - dec hl - pop bc - dec b - jr nz, .flippedLoop - ret - -LoadMonBackPic: -; Assumes the monster's attributes have -; been loaded with GetMonHeader. - ld a, [wBattleMonSpecies2] - ld [wcf91], a - hlcoord 1, 5 - ld b, 7 - ld c, 8 - call ClearScreenArea - ld hl, wMonHBackSprite - wMonHeader - call UncompressMonSprite - predef ScaleSpriteByTwo - ld de, vBackPic - call InterlaceMergeSpriteBuffers ; combine the two buffers to a single 2bpp sprite - ld hl, vSprites - ld de, vBackPic - ld c, (2*SPRITEBUFFERSIZE)/16 ; count of 16-byte chunks to be copied - ldh a, [hLoadedROMBank] - ld b, a - jp CopyVideoData diff --git a/engine/battle/decrement_pp.asm b/engine/battle/decrement_pp.asm index b7c428f7..441bbb81 100644 --- a/engine/battle/decrement_pp.asm +++ b/engine/battle/decrement_pp.asm @@ -37,7 +37,7 @@ 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 + 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/draw_hud_pokeball_gfx.asm b/engine/battle/draw_hud_pokeball_gfx.asm index 097a0fcc..6aed1d0a 100644 --- a/engine/battle/draw_hud_pokeball_gfx.asm +++ b/engine/battle/draw_hud_pokeball_gfx.asm @@ -27,6 +27,8 @@ SetupOwnPartyPokeballs: ld [hl], a ld a, 8 ld [wHUDPokeballGfxOffsetX], a + xor a + ld [wdef5], a ld hl, wOAMBuffer jp WritePokeballOAMData @@ -41,6 +43,8 @@ SetupEnemyPartyPokeballs: ld [hl], $20 ld a, -8 ld [wHUDPokeballGfxOffsetX], a + ld a, $1 + ld [wdef5], a ld hl, wOAMBuffer + PARTY_LENGTH * 4 jp WritePokeballOAMData @@ -104,7 +108,7 @@ WritePokeballOAMData: ld [hli], a ld a, [de] ld [hli], a - xor a + ld a, [wdef5] ld [hli], a ld a, [wBaseCoordX] ld b, a @@ -174,6 +178,8 @@ SetupPlayerAndEnemyPokeballs: ld [hl], $40 ld a, 8 ld [wHUDPokeballGfxOffsetX], a + xor a + ld [wdef5], a ld hl, wOAMBuffer call WritePokeballOAMData ld hl, wEnemyMons @@ -183,6 +189,8 @@ SetupPlayerAndEnemyPokeballs: ld a, $50 ld [hli], a ld [hl], $68 + ld a, $1 + ld [wdef5], a ld hl, wOAMBuffer + $18 jp WritePokeballOAMData diff --git a/engine/battle/effects.asm b/engine/battle/effects.asm index 441d6c1c..c4e81816 100644 --- a/engine/battle/effects.asm +++ b/engine/battle/effects.asm @@ -60,6 +60,16 @@ SleepEffect: call BattleRandom and $7 jr z, .setSleepCounter + ld b, a + ld a, [wUnknownSerialFlag_d499] + and a + jr z, .asm_3f1ba ; XXX stadium stuff? + ld a, b + and $3 + jr z, .setSleepCounter + ld b, a +.asm_3f1ba + ld a, b ld [de], a call PlayCurrentMoveAnimation2 ld hl, FellAsleepText @@ -198,7 +208,7 @@ FreezeBurnParalyzeEffect: ret nz ; return if they have a substitute, can't effect them ldh a, [hWhoseTurn] and a - jp nz, opponentAttacker + jp nz, .opponentAttacker ld a, [wEnemyMonStatus] and a jp nz, CheckDefrost ; can't inflict status if opponent is already statused @@ -211,7 +221,17 @@ FreezeBurnParalyzeEffect: cp b ; do target type 2 and move type match? ret z ; return if they match ld a, [wPlayerMoveEffect] - cp PARALYZE_SIDE_EFFECT1 + 1 ; 10% status effects are 04, 05, 06 so 07 will set carry for those + cp UNUSED_EFFECT_23 ; more stadium stuff + jr nz, .asm_3f2c7 + ld a, [wUnknownSerialFlag_d499] + and a + ld a, FREEZE_SIDE_EFFECT + ld b, $4d ; else use 0x4D/0x100 or 77/256 = 30.1%~ chance + jr z, .next1 + ld b, $1a ; 0x1A/0x100 or 26/256 = 10.2%~ chance + jr .next1 +.asm_3f2c7 + cp a, PARALYZE_SIDE_EFFECT1 + 1 ; 10% status effects are 04, 05, 06 so 07 will set carry for those ld b, $1a ; 0x1A/0x100 or 26/256 = 10.2%~ chance jr c, .next1 ; branch ahead if this is a 10% chance effect.. ld b, $4d ; else use 0x4D/0x100 or 77/256 = 30.1%~ chance @@ -224,9 +244,9 @@ FreezeBurnParalyzeEffect: ret nc ; do nothing if random value is >= 1A or 4D [no status applied] ld a, b ; what type of effect is this? cp BURN_SIDE_EFFECT1 - jr z, .burn + jr z, .burn1 cp FREEZE_SIDE_EFFECT - jr z, .freeze + jr z, .freeze1 ; .paralyze ld a, 1 << PAR ld [wEnemyMonStatus], a @@ -234,7 +254,7 @@ FreezeBurnParalyzeEffect: ld a, ANIM_A9 call PlayBattleAnimation jp PrintMayNotAttackText ; print paralysis text -.burn +.burn1 ld a, 1 << BRN ld [wEnemyMonStatus], a call HalveAttackDueToBurn ; halve attack of affected mon @@ -242,7 +262,7 @@ FreezeBurnParalyzeEffect: call PlayBattleAnimation ld hl, BurnedText jp PrintText -.freeze +.freeze1 call ClearHyperBeam ; resets hyper beam (recharge) condition from target ld a, 1 << FRZ ld [wEnemyMonStatus], a @@ -250,7 +270,7 @@ FreezeBurnParalyzeEffect: call PlayBattleAnimation ld hl, FrozenText jp PrintText -opponentAttacker: +.opponentAttacker ld a, [wBattleMonStatus] ; mostly same as above with addresses swapped for opponent and a jp nz, CheckDefrost @@ -263,12 +283,22 @@ opponentAttacker: cp b ret z ld a, [wEnemyMoveEffect] - cp PARALYZE_SIDE_EFFECT1 + 1 + cp UNUSED_EFFECT_23 ; more stadium stuff + jr nz, .asm_3f341 + ld a, [wUnknownSerialFlag_d499] + and a + ld a, FREEZE_SIDE_EFFECT + ld b, $4d ; else use 0x4D/0x100 or 77/256 = 30.1%~ chance + jr z, .next2 + ld b, $1a ; 0x1A/0x100 or 26/256 = 10.2%~ chance + jr .next2 +.asm_3f341 + cp a, PARALYZE_SIDE_EFFECT1 + 1 ld b, $1a - jr c, .next1 + jr c, .next2 ld b, $4d sub $1e -.next1 +.next2 push af call BattleRandom cp b @@ -276,23 +306,29 @@ opponentAttacker: ret nc ld a, b cp BURN_SIDE_EFFECT1 - jr z, .burn + jr z, .burn2 cp FREEZE_SIDE_EFFECT - jr z, .freeze + jr z, .freeze2 ld a, 1 << PAR ld [wBattleMonStatus], a call QuarterSpeedDueToParalysis + ld a, ANIM_C7 + call PlayBattleAnimation2 jp PrintMayNotAttackText -.burn +.burn2 ld a, 1 << BRN ld [wBattleMonStatus], a call HalveAttackDueToBurn + ld a, ANIM_C7 + call PlayBattleAnimation2 ld hl, BurnedText jp PrintText -.freeze +.freeze2 ; hyper beam bits aren't reseted for opponent's side ld a, 1 << FRZ ld [wBattleMonStatus], a + ld a, ANIM_C7 + call PlayBattleAnimation2 ld hl, FrozenText jp PrintText @@ -458,25 +494,25 @@ UpdateStatDone: ld bc, wPlayerMonMinimized ldh a, [hWhoseTurn] and a - jr z, .asm_3f4e6 + jr z, .playerTurn ld hl, wEnemyBattleStatus2 ld de, wEnemyMoveNum ld bc, wEnemyMonMinimized -.asm_3f4e6 +.playerTurn ld a, [de] cp MINIMIZE - jr nz, .asm_3f4f9 + jr nz, .notMinimize ; if a substitute is up, slide off the substitute and show the mon pic before ; playing the minimize animation bit HAS_SUBSTITUTE_UP, [hl] push af push bc + push de ld hl, HideSubstituteShowMonAnim ld b, BANK(HideSubstituteShowMonAnim) - push de call nz, Bankswitch pop de -.asm_3f4f9 +.notMinimize call PlayCurrentMoveAnimation ld a, [de] cp MINIMIZE @@ -974,6 +1010,9 @@ FlinchSideEffect: ld hl, wPlayerBattleStatus1 ld de, wEnemyMoveEffect .flinchSideEffect + ld a, [wLinkState] + cp LINK_STATE_BATTLING + call z, ClearHyperBeam ld a, [de] cp FLINCH_SIDE_EFFECT1 ld b, $1a ; ~10% chance of flinch @@ -1015,10 +1054,27 @@ ChargeEffect: set INVULNERABLE, [hl] ; mon is now invulnerable to typical attacks (fly/dig) ld b, ANIM_C0 .notDigOrFly + push de + push bc + inc hl ; battle status 2 + push hl + ld a, [hl] + bit HAS_SUBSTITUTE_UP, a + ld hl, HideSubstituteShowMonAnim + ld b, BANK(HideSubstituteShowMonAnim) + call nz, Bankswitch + pop hl + pop bc xor a ld [wAnimationType], a ld a, b call PlayBattleAnimation + ld a, [hl] + bit HAS_SUBSTITUTE_UP, a + ld hl, ReshowSubstituteAnim + ld b, BANK(ReshowSubstituteAnim) + call nz, Bankswitch + pop de ld a, [de] ld [wChargeMoveNum], a ld hl, ChargeMoveEffectText @@ -1488,6 +1544,7 @@ PlayBattleAnimationGotID: push de push bc predef MoveAnimation + callfar Func_78e98 pop bc pop de pop hl diff --git a/engine/battle/end_of_battle.asm b/engine/battle/end_of_battle.asm index bd4a1901..e64f54e7 100755 --- a/engine/battle/end_of_battle.asm +++ b/engine/battle/end_of_battle.asm @@ -10,6 +10,8 @@ EndOfBattle: ld a, [wEnemyMonStatus] ld [hl], a call ClearScreen + ld b, SET_PAL_OVERWORLD + call RunPaletteCommand callfar DisplayLinkBattleVersusTextBox ld a, [wBattleResult] cp $1 @@ -43,6 +45,8 @@ EndOfBattle: xor a ld [wForceEvolution], a predef EvolutionAfterBattle + ld d, $82 + callfar UpdatePikachuMoodAfterBattle .resetVariables xor a ld [wLowHealthAlarm], a ;disable low health alarm diff --git a/engine/battle/experience.asm b/engine/battle/experience.asm index 0eab6e08..bab804bb 100644 --- a/engine/battle/experience.asm +++ b/engine/battle/experience.asm @@ -43,7 +43,7 @@ GainExperience: inc de jr .nextBaseStat .maxStatExp ; if the upper byte also overflowed, then we have hit the max stat exp - ld a, $ff + dec a ; a is 0 from previous check ld [de], a inc de ld [de], a @@ -233,13 +233,19 @@ GainExperience: .recalcStatChanges xor a ; battle mon ld [wCalculateWhoseStats], a - callfar CalculateModifiedStats - callfar ApplyBurnAndParalysisPenaltiesToPlayer - callfar ApplyBadgeStatBoosts - callfar DrawPlayerHUDAndHPBar - callfar PrintEmptyString + ld hl, CalculateModifiedStats + call Bankswitch15ToF + ld hl, ApplyBurnAndParalysisPenaltiesToPlayer + call Bankswitch15ToF + ld hl, ApplyBadgeStatBoosts + call Bankswitch15ToF + ld hl, DrawPlayerHUDAndHPBar + call Bankswitch15ToF + ld hl, PrintEmptyString + call Bankswitch15ToF call SaveScreenTilesToBuffer1 .printGrewLevelText + callabd_ModifyPikachuHappiness PIKAHAPPY_LEVELUP ld hl, GrewLevelText call PrintText xor a ; PLAYER_PARTY_DATA @@ -339,6 +345,10 @@ BoostExp: ldh [hQuotient + 2], a ret +Bankswitch15ToF: + ld b, BANK(BattleCore) + jp Bankswitch + GainedText: text_far _GainedText text_asm diff --git a/engine/battle/ghost_marowak_anim.asm b/engine/battle/ghost_marowak_anim.asm index 6760c3d5..03059022 100644 --- a/engine/battle/ghost_marowak_anim.asm +++ b/engine/battle/ghost_marowak_anim.asm @@ -2,6 +2,7 @@ MarowakAnim: ; animate the ghost being unveiled as a Marowak ld a, $e4 ldh [rOBP1], a + call UpdateGBCPal_OBP1 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 @@ -27,6 +28,7 @@ MarowakAnim: sla a sla a ldh [rOBP1], a + call UpdateGBCPal_OBP1 jr nz, .fadeOutGhostLoop call ClearSprites call CopyMonPicFromBGToSpriteVRAM ; copy Marowak pic from BG to sprite VRAM @@ -40,6 +42,7 @@ MarowakAnim: srl b rra ldh [rOBP1], a + call UpdateGBCPal_OBP1 ld a, b and a jr nz, .fadeInMarowakLoop @@ -74,7 +77,7 @@ CopyMonPicFromBGToSpriteVRAM: ld [hli], a ld a, d ld [hli], a - ld a, $10 ; use OBP1 + ld a, $14 ; use OBP1 ld [hli], a inc d dec c diff --git a/engine/battle/link_battle_versus_text.asm b/engine/battle/link_battle_versus_text.asm index 29c11356..e55a0672 100644 --- a/engine/battle/link_battle_versus_text.asm +++ b/engine/battle/link_battle_versus_text.asm @@ -2,8 +2,7 @@ DisplayLinkBattleVersusTextBox: call LoadTextBoxTilePatterns hlcoord 3, 4 - ld b, 7 - ld c, 12 + lb bc, 7, 12 call TextBoxBorder hlcoord 4, 5 ld de, wPlayerName diff --git a/engine/battle/misc.asm b/engine/battle/misc.asm index 33af6f6f..df9145f2 100755 --- a/engine/battle/misc.asm +++ b/engine/battle/misc.asm @@ -101,22 +101,3 @@ InitList: ld a, b ld [wItemPrices + 1], a ret - -; get species of mon e in list [wMonDataLocation] for LoadMonData -GetMonSpecies: - ld hl, wPartySpecies - ld a, [wMonDataLocation] - and a - jr z, .getSpecies - dec a - jr z, .enemyParty - ld hl, wBoxSpecies - jr .getSpecies -.enemyParty - ld hl, wEnemyPartyMons -.getSpecies - ld d, 0 - add hl, de - ld a, [hl] - ld [wcf91], a - ret diff --git a/engine/battle/move_effects/heal.asm b/engine/battle/move_effects/heal.asm index e9fb62a7..80923a29 100644 --- a/engine/battle/move_effects/heal.asm +++ b/engine/battle/move_effects/heal.asm @@ -86,7 +86,7 @@ HealEffect_: ld [wHPBarNewHP], a .playAnim ld hl, PlayCurrentMoveAnimation - call BankswitchEtoF + call Bankswitch3DtoF ldh a, [hWhoseTurn] and a hlcoord 10, 9 @@ -98,14 +98,14 @@ HealEffect_: ld [wHPBarType], a predef UpdateHPBar2 ld hl, DrawHUDsAndHPBars - call BankswitchEtoF + call Bankswitch3DtoF ld hl, RegainedHealthText jp PrintText .failed ld c, 50 call DelayFrames ld hl, PrintButItFailedText_ - jp BankswitchEtoF + jp Bankswitch3DtoF StartedSleepingEffect: text_far _StartedSleepingEffect diff --git a/engine/battle/move_effects/reflect_light_screen.asm b/engine/battle/move_effects/reflect_light_screen.asm index 7bdc7be7..c05055fa 100644 --- a/engine/battle/move_effects/reflect_light_screen.asm +++ b/engine/battle/move_effects/reflect_light_screen.asm @@ -23,14 +23,14 @@ ReflectLightScreenEffect_: .playAnim push hl ld hl, PlayCurrentMoveAnimation - call BankswitchEtoF + call Bankswitch3DtoF pop hl jp PrintText .moveFailed ld c, 50 call DelayFrames ld hl, PrintButItFailedText_ - jp BankswitchEtoF + jp Bankswitch3DtoF LightScreenProtectedText: text_far _LightScreenProtectedText @@ -40,6 +40,6 @@ ReflectGainedArmorText: text_far _ReflectGainedArmorText text_end -BankswitchEtoF: +Bankswitch3DtoF: ld b, BANK(BattleCore) jp Bankswitch diff --git a/engine/battle/move_effects/transform.asm b/engine/battle/move_effects/transform.asm index 46cea51c..d37bd94d 100644 --- a/engine/battle/move_effects/transform.asm +++ b/engine/battle/move_effects/transform.asm @@ -100,18 +100,11 @@ TransformEffect_: and a jr z, .lessThanFourMoves ld a, $5 - ld [de], a - inc de - dec b - jr nz, .copyPPLoop - jr .copyStats .lessThanFourMoves -; 0 PP for blank moves - xor a ld [de], a inc de dec b - jr nz, .lessThanFourMoves + jr nz, .copyPPLoop .copyStats ; original (unmodified) stats and stat mods pop hl @@ -141,7 +134,7 @@ TransformEffect_: .failed ld hl, PrintButItFailedText_ - jp BankswitchEtoF + jp Bankswitch3DtoF TransformedText: text_far _TransformedText diff --git a/engine/battle/read_trainer_party.asm b/engine/battle/read_trainer_party.asm index 7e5c1249..02fbfeda 100755 --- a/engine/battle/read_trainer_party.asm +++ b/engine/battle/read_trainer_party.asm @@ -15,8 +15,8 @@ ReadTrainer: ld [hl], a ; get the pointer to trainer data for this class - ld a, [wCurOpponent] - sub $C9 ; convert value from pokemon to trainer + ld a, [wTrainerClass] ; get trainer class + dec a add a ld hl, TrainerDataPointers ld c, a @@ -53,7 +53,7 @@ ReadTrainer: .LoopTrainerData ld a, [hli] and a ; have we reached the end of the trainer data? - jr z, .FinishUp + jp z, .AddAdditionalMoveData ld [wcf91], a ; write species somewhere (XXX why?) ld a, ENEMY_PARTY_DATA ld [wMonDataLocation], a @@ -68,7 +68,7 @@ ReadTrainer: ; - if [wLoneAttackNo] != 0, one pokemon on the team has a special move ld a, [hli] and a ; have we reached the end of the trainer data? - jr z, .AddLoneMove + jr z, .AddAdditionalMoveData ld [wCurEnemyLVL], a ld a, [hli] ld [wcf91], a @@ -78,69 +78,48 @@ ReadTrainer: call AddPartyMon pop hl jr .SpecialTrainer -.AddLoneMove -; does the trainer have a single monster with a different move - ld a, [wLoneAttackNo] ; Brock is 01, Misty is 02, Erika is 04, etc +.AddAdditionalMoveData +; does the trainer have additional move data? + ld a, [wTrainerClass] + ld b, a + ld a, [wTrainerNo] + ld c, a + ld hl, SpecialTrainerMoves +.loopAdditionalMoveData + ld a, [hli] + cp $ff + jr z, .FinishUp + cp b + jr nz, .asm_39c46 + ld a, [hli] + cp c + jr nz, .asm_39c46 + ld d, h + ld e, l +.writeAdditionalMoveDataLoop + ld a, [de] + inc de and a - jr z, .AddTeamMove + jp z, .FinishUp + dec a + ld hl, wEnemyMon1Moves + ld bc, wEnemyMon2 - wEnemyMon1 + call AddNTimes + ld a, [de] + inc de dec a - add a ld c, a ld b, 0 - ld hl, LoneMoves add hl, bc + ld a, [de] + inc de + ld [hl], a + jr .writeAdditionalMoveDataLoop +.asm_39c46 ld a, [hli] - ld d, [hl] - ld hl, wEnemyMon1Moves + 2 - ld bc, wEnemyMon2 - wEnemyMon1 - call AddNTimes - ld [hl], d - jr .FinishUp -.AddTeamMove -; check if our trainer's team has special moves - -; get trainer class number - ld a, [wCurOpponent] - sub OPP_ID_OFFSET - ld b, a - ld hl, TeamMoves - -; iterate through entries in TeamMoves, checking each for our trainer class -.IterateTeamMoves - ld a, [hli] - cp b - jr z, .GiveTeamMoves ; is there a match? - inc hl ; if not, go to the next entry - inc a - jr nz, .IterateTeamMoves - -; no matches found. is this trainer champion rival? - ld a, b - cp RIVAL3 - jr z, .ChampionRival - jr .FinishUp ; nope -.GiveTeamMoves - ld a, [hl] - ld [wEnemyMon5Moves + 2], a - jr .FinishUp -.ChampionRival ; give moves to his team - -; pidgeot - ld a, SKY_ATTACK - ld [wEnemyMon1Moves + 2], a - -; starter - ld a, [wRivalStarter] - cp STARTER3 - ld b, MEGA_DRAIN - jr z, .GiveStarterMove - cp STARTER1 - ld b, FIRE_BLAST - jr z, .GiveStarterMove - ld b, BLIZZARD ; must be squirtle -.GiveStarterMove - ld a, b - ld [wEnemyMon6Moves + 2], a + and a + jr nz, .asm_39c46 + jr .loopAdditionalMoveData .FinishUp ; clear wAmountMoneyWon addresses xor a diff --git a/engine/battle/safari_zone.asm b/engine/battle/safari_zone.asm index 4f01c2f4..9362cc3a 100755 --- a/engine/battle/safari_zone.asm +++ b/engine/battle/safari_zone.asm @@ -2,18 +2,18 @@ PrintSafariZoneBattleText: ld hl, wSafariBaitFactor ld a, [hl] and a - jr z, .asm_4284 + jr z, .asm_411e dec [hl] ld hl, SafariZoneEatingText - jr .asm_429f -.asm_4284 + jr .asm_4138 +.asm_411e dec hl ld a, [hl] and a ret z dec [hl] ld hl, SafariZoneAngryText - jr nz, .asm_429f + jr nz, .asm_4138 push hl ld a, [wEnemyMonSpecies] ld [wd0b5], a @@ -21,7 +21,7 @@ PrintSafariZoneBattleText: ld a, [wMonHCatchRate] ld [wEnemyMonActualCatchRate], a pop hl -.asm_429f +.asm_4138 push hl call LoadScreenTilesFromBuffer1 pop hl diff --git a/engine/battle/scale_sprites.asm b/engine/battle/scale_sprites.asm index 87b4398d..794a65ab 100644 --- a/engine/battle/scale_sprites.asm +++ b/engine/battle/scale_sprites.asm @@ -2,6 +2,13 @@ ; assumes that input sprite chunks are 4x4 tiles, and the rightmost and bottommost 4 pixels will be ignored ; resulting in a 7*7 tile output sprite chunk ScaleSpriteByTwo: + ld a, $0 + call SwitchSRAMBankAndLatchClockData + call ScaleSpriteByTwo_ + call PrepareRTCDataAndDisableSRAM + ret + +ScaleSpriteByTwo_: ld de, sSpriteBuffer1 + (4*4*8) - 5 ; last byte of input data, last 4 rows already skipped ld hl, sSpriteBuffer0 + SPRITEBUFFERSIZE - 1 ; end of destination buffer call ScaleLastSpriteColumnByTwo ; last tile column is special case diff --git a/engine/battle/trainer_ai.asm b/engine/battle/trainer_ai.asm index 2225dca1..17e68e75 100644 --- a/engine/battle/trainer_ai.asm +++ b/engine/battle/trainer_ai.asm @@ -288,13 +288,19 @@ INCLUDE "data/trainers/special_moves.asm" INCLUDE "data/trainers/parties.asm" TrainerAI: - and a ld a, [wIsInBattle] dec a - ret z ; if not a trainer, we're done here + jr z, .done ; if not a trainer, we're done here ld a, [wLinkState] cp LINK_STATE_BATTLING - ret z + jr z, .done ; if in a link battle, we're done as well + ld a, [wEnemyBattleStatus1] + and 1 << CHARGING_UP | 1 << THRASHING_ABOUT | 1 << STORING_ENERGY ; %10011 + jr nz, .done ; don't follow trainer ai if opponent is in a locked state + ld a, [wEnemyBattleStatus2] + and 1 << USING_RAGE ; %1000000 + jr nz, .done ; don't follow trainer ai if opponent is locked in rage + ; note that this doesn't check for hyper beam recharge which can cause problems ld a, [wTrainerClass] ; what trainer class is this? dec a ld c, a @@ -305,7 +311,7 @@ TrainerAI: add hl, bc ld a, [wAICount] and a - ret z ; if no AI uses left, we're done here + jr z, .done; if no AI uses left, we're done here inc hl inc a jr nz, .getpointer @@ -318,6 +324,9 @@ TrainerAI: ld l, a call Random jp hl +.done + and a + ret INCLUDE "data/trainers/ai_pointers.asm" @@ -377,22 +386,22 @@ ErikaAI: jp AIUseSuperPotion KogaAI: - cp 25 percent + 1 + cp 13 percent - 1 ret nc jp AIUseXAttack BlaineAI: cp 25 percent + 1 ret nc + ld a, 10 + call AICheckIfHPBelowFraction + ret nc jp AIUseSuperPotion SabrinaAI: cp 25 percent + 1 ret nc - ld a, 10 - call AICheckIfHPBelowFraction - ret nc - jp AIUseHyperPotion + jp AIUseXDefend Sony2AI: cp 13 percent - 1 diff --git a/engine/battle/wild_encounters.asm b/engine/battle/wild_encounters.asm index 8c9c1529..d16c6515 100644 --- a/engine/battle/wild_encounters.asm +++ b/engine/battle/wild_encounters.asm @@ -24,8 +24,9 @@ TryDoWildEncounter: ld [wRepelRemainingSteps], a .next ; determine if wild pokemon can appear in the half-block we're standing in -; is the bottom right tile (9,9) of the half-block we're standing in a grass/water tile? - hlcoord 9, 9 +; is the bottom left tile (8,9) of the half-block we're standing in a grass/water tile? +; note that by using the bottom left tile, this prevents the "left-shore" tiles from generating grass encounters + hlcoord 8, 9 ld c, [hl] ld a, [wGrassTile] cp c @@ -68,8 +69,6 @@ TryDoWildEncounter: cp $14 ; is the bottom left tile (8,9) of the half-block we're standing in a water tile? jr nz, .gotWildEncounterType ; else, it's treated as a grass tile by default ld hl, wWaterMons -; since the bottom right tile of a "left shore" half-block is $14 but the bottom left tile is not, -; "left shore" half-blocks (such as the one in the east coast of Cinnabar) load grass encounters. .gotWildEncounterType ld b, 0 add hl, bc |