;=========================== ; Battlescreen Drawing code ;=========================== DrawBoxLine: ;This routine draws a line on the bottom message panel. ;Outputs to (HL): B,A,A,A,A... ld (hl),b inc hl ld (hl),a ld d,h ld e,l inc de ld bc,7 ldir ret DrawBottomFrame: ;First draw the status Bar, a horizontal line on top ld hl, 12*7+graph_mem ld (hl),255 ld de, 12*7+graph_mem+1 ld bc,11 ldir ;Drawing the top border for the Frame ld hl, 12*40+graph_mem ld b,$FF ld a,$FF call DrawBoxLine ;Drawing the Bottom border for the Frame ld hl, 12*62+graph_mem ld b,$FF call DrawBoxLine ;Drawing the shadow for the Frame ld hl, 12*63+graph_mem ld b,%01111111 call DrawBoxLine ClearTextBox: ld b,21 ld hl,12*41+Graph_mem jr ClearLines2 ClearLine1: ld hl,12*41+Graph_mem jr ClearLines ClearLine2: ld hl,12*48+Graph_mem jr ClearLines ClearLine3: ld hl,12*55+Graph_mem ClearLines: ld b,7 ClearLines2: xor a ClearLineloop: push bc ld b,%10000000 call DrawBoxLine ld bc,4 add hl,bc pop bc djnz ClearLineLoop ret ClearEnemies: ld hl,enemyram ld (hl),0 ld de,enemyram+1 ld bc,32*5-1 ldir ret ;=================================== ; GetEnemyIX- Gets IX for enemy # ;=================================== ; Input: A=Number of enemy ; Output: IX=Offset to enemy# ; Destroys: BC=32 A=0 F=Z GetEnemyIX: ;Get Starting point in IX ld ix,enemyram ;Abandon if enemy 1 dec a ret z ;Increment IX by 32 each enemy # ld bc,32 GIX_Loop: add ix,bc ;for A times dec a ;Go back unless done jr nz,GIX_Loop ;Return ret ;==================================== ; CalcMonstStat- Calculates a stat ;==================================== ; Input: HL,IX ; Output: HL+2, IX+2, Fills a stat based on slope intercept ; Destroys: CalcMonstStat: ;==================================== ; The first part does (hl)*e -> hl ;==================================== ;Set B=0,C=(hl) ld b,0 ld c,(hl) ;Increase offset by 1 inc hl ;Save offset for math work push hl ;Make A the multiplier ld a,e ;Clear HL for math work ld hl,0 ;Multiplication Loop adds BC to HL A times MultCalcMonst: add hl,bc dec a jr nz,MultCalcMonst ;Get C from Offset (HL), Inc Offset HL, and take back the Math HL ex (sp),hl ld c,(hl) inc hl ex (sp),hl ;Add the intercept add hl,bc ;Set the result of the nasty toil in (ix) ld (ix+0),l ld (ix+1),h ;Add 2 to IX inc ix inc ix ;Get back Offset HL pop hl ;Done! ret ;========================================================== ; GenerateEnemy- Generates enemy #C of type D on level E ;========================================================== ;Input: c-number of enemy, d-type of enemy, e-level of enemy ;Output: Enemy added to EnemyRam GenerateEnemy: ;Save enemy number twice ld a,c ld l,c ;================================== ; Step1: Get the IX for enemy #A ;================================== call GetEnemyIX ;============================================================ ; Step2: Get the X position for the enemy based on enemy # ;============================================================ ;Load inital position ld a,4 ;Finalize if enemy 1 dec l jr z,GetX_Skip ;Increments A by 18 for each enemy # ld h,18 GetX_Loop: add a,h ;for L times dec l ;Go back unless done jr nz,GetX_Loop GetX_Skip: ;Write X position ld (ix+e_xpos),a ;Y position is a constant: 16 ld (ix+e_ypos),16 ;=================================== ; Step3: Get monster stats offset ;=================================== ld hl,monsterdata ld a,d or a jr z,SkipGetSO ld bc,16 GetSOLoop: add hl,bc dec a jr nz,GetSOLoop SkipGetSO: ;======================================================= ; Step4: Get monster stats from Type of Enemy and Level ;======================================================= ;==================== ;Save monster's level ;==================== ld (ix+e_level),e ;================== ;Get Monster's Name ;================== ;Save IX push ix ;Get monster type ld a,(hl) ;Double It for offset purposes add a,a ;Prepare offset BC ld b,0 ld c,a ;Add Offset to MonsterNames ld ix,MonsterNames add ix,bc ;Get Offset that's stored at the offset ld b,(ix+1) ld c,(ix+0) ;Take back original IX pop ix ;Store the name offset ld (ix+e_text1+1),b ld (ix+e_text1+0),c ;==================== ;Get Monster's Sprite ;==================== ;Save HL push hl ;Get Monster Type ld c,(hl) ;Put that in HL ld h,0 ld l,c ;Multiply HL by 32 add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl ;Multiply that by 3 ld b,h ld c,l add hl,bc add hl,bc ;Add offset of MonsterGfx to that ld bc,monstergfx add hl,bc ;Save that into e_sprite ld (ix+e_sprite),l ld (ix+e_sprite+1),h ;Restore HL pop hl ;=================================== ;Get Monster's HP,MHP,ATK,DEF,EXP,GP ;=================================== ;Change IX offset ld bc,e_hp add ix,bc ;Increment HL inc hl ;Do the CalcStat call CalcMonstStat ;Go back twice because inital HP=MHP dec hl dec hl ;Do it again 5 times call CalcMonstStat call CalcMonstStat call CalcMonstStat call CalcMonstStat call CalcMonstStat ;============================== ;Copy monster's attack patterns ;============================== ;Add 2 to IX inc ix inc ix ;IX->DE push ix pop de ;HL is at the table, DE is at the enemyram ld bc,4 ;Copy 4 bytes ldir ;============ ;Set up Text2 ;============ ;Get type of type ld c,(hl) ld b,0 sla c ;BC=type*2 ;Add BC to MonsterTypes ld hl,monstertypes add hl,bc ;Copy the values from there ldi ldi ;done ret ;========================================================= ; DisplayEnemies- Displays Enemies on the Battle Screen ;========================================================= DisplayEnemies: ld b,5 DisplayEnemiesLoop: ld a,b push bc call GetEnemyIX ld a,(ix+e_hp) or a jr z,skipdisplayenemy call DisplayEnemy skipdisplayenemy: pop bc djnz DisplayEnemiesLoop ret ;================ ; DisplayEnemy ;================ DisplayEnemy: push bc push ix ld a,(ix+e_xpos) ld l,(ix+e_ypos) ld b,(ix+e_sprite+1) ld c,(ix+e_sprite+0) push bc pop ix ld bc,$1002 call LargeSprite pop ix pop bc ret ;================================ ; EraseEnemies- Erases enemies ;================================ EraseEnemies: ld hl,9*12+plotsscreen ld de,9*12+plotsscreen+1 ld bc,31*12-1 ld (hl),0 ldir ret ;=============================; ; ___ _ ___ ___ _ ___ ; ; | _ \ / |_ _|_ _| | | __| ; ; ||_|| //||| | | || | | |_ ; ; | _ < //_||| | | || | | __| ; ; ||_||/ _ || | | || |_| |_ ; ; |___/_/ |_||_| |_||___|___| ; ; ; ; C O D E ! ; ; ; ;============================== BossBattle: call ClearEnemies ld a,(room) rra rra and %00000111 ld c,a ld b,0 ld hl,bosstable add hl,bc ld d,(hl) ;ld d,a ld a,(room) add a,5 ld e,a ld c,3 call GenerateEnemy jr BattleMain Battle: ;Clear old enemy data call ClearEnemies ;Make random(5)+1 enemies ld b,5 call random inc a ;Set Counter ld b,a ;Do some stuff to offset the enemies cp 4 jr nc,noShift inc a cp 3 jr nc,noShift inc a noShift: ;Set Shifter Counter ld c,a startgen: push bc push bc ;Put random(8) into C ld b,8 call random ld c,a ;Add (room mod 8)*8 to C ld a,(room) and %00011100 add a,a add a,c ld c,a ;Add to enemytable ; ld b,0 ld hl,enemytable add hl,bc ;Set type of monster ld d,(hl) ;Get random level for monster into C ld b,5 call random ld c,a ;Add to room number ld a,(room) add a,c ld c,a sub 2 jr nc, gen_skipadd xor a gen_skipadd: inc a ld e,a pop bc call GenerateEnemy pop bc dec c djnz startgen BattleMain: ;Reset your stats call ResetPower ;Reset fight counter to random(20)+16 ld b,28 call random add a,8 ld (fight),a ;Copy old screen call copy2apd ;Clear graph_mem ld de,graph_mem+1 ld hl,graph_mem ld (hl),0 ld bc,767 ldir ;Draw the lines and stuff on the screen call drawbottomframe ;Draw the Commands window sprite ld ix,gcommands ld a,72 ld l,40 ld b,24 ld c,3 call LargeSprite ;Display Enemies call DisplayEnemies ;Enable Text on graphscreen and update the lifebar set textwrite,(iy+sgrflags) call UpdateLifeBar ;BattleTransition call BattleTransition ;Copy the screen to the buffer call copy2apd ;Display the screen call FastCopy ;Start the battle engine! jp BattleLoop ;Wait for a key then quit call waitkey ;============= ;CLOSING CODE: ;============= ;Display Cave leavebattle: res textwrite,(iy+sgrflags) call displaycave ;Back up display call copy2apd ;Re-Render Screen call renderscreen ret ResetPower: ld hl,(sword) ld de,(str) add hl,de ld (atk),hl ld hl,(shield) ld de,(ndf) add hl,de ld (def),hl ret UpdateLifeBar: ;Clear Old Life Bar ld hl,plotsscreen ld de,plotsscreen+1 ld bc, 80 ld (hl),0 ldir ;Display Life Bar ld hl,0 ld (pencol),hl ld hl,tHP bcall(_vputs) ld hl,(hp) call vdisphl ld hl,tSlash bcall(_Vputs) ld hl,(mhp) call vdisphl ld hl,$0040 ld (pencol),hl ld hl,(Herbs) ld h,0 call vdisphl ld hl,tHerbs bcall(_vPuts) ret ;====================== ; BattleCommand ;====================== ;Uses the lower right panel to select a command ;returns result into a ; BattleCommand: ;Save the screen call copy2apd ;Address of selection box ld ix,battlebox ;x position ld a,73 ;y position ld hl,41 ;Height and width ld bc,$0A02 bcloop: ;Save variables push af push bc push hl push ix ;ld h,0 ;Draw Sprite call largesprite ;Update Screen call fastcopy ;Restore Screen call copyapd ;Get a key call waitkey ;Get back some vars pop ix pop hl pop bc ;check pressed key cp gLeft jr z,bcLR cp gRight jr z,bcLR cp gUp jr z,bcUD cp gDown jr z,bcUD cp g2nd jr z,bcEnter cp gEnter jr z,bcEnter cp gClear jr z,bcQuit pop af jr bcloop ;Left & right xor selection by 1 and xor x position by 29 bcLR: ld a,h xor 1 ld h,a pop af xor 29 jr bcloop ;Up & down xor selection by 2 and xor y position by 29 bcUD: ld a,h xor 2 ld h,a ld a,l xor 29 ld l,a pop af jr bcloop ;Enter leaves and copyies h to a bcEnter: pop af ld a,h ret st_Quit: ;You gotta pop something... pop af bcQuit: ;Pop register af pop af ;Pop off the pointer to the battlebox routine pop af ;Pop out of the battle to the main game! pop af ;Return from the game to the shell! ret ;================= ; DispEnemyName ;================= ; Input enemy ix ; preserves all registers DispEnemyName: push hl ld l,(ix+e_text2) ld h,(ix+e_text2+1) bcall(_vputs) ld l,(ix+e_text1) ld h,(ix+e_text1+1) bcall(_vputs) pop hl ret ;================ ; SelectTarget ;================ ; Player selects a living enemy (or ally?) ; results in a number of target (or 255 for cancel) SelectTarget: CheckForTarget: ld b,5 ld ix,Enemyram ld de,32 cft_loop: ld a,(ix+e_hp) or (ix+e_hp+1) jr nz,st_proceed add ix,de djnz cft_loop call st_cancel st_proceed: call clearTextBox ld hl,$2902 ld (pencol),hl ld hl,tTarget bcall(_vputs) call copy2apd call ST_Right ST_Disp: call copyapd ld hl,$3002 ld (pencol),hl ld hl,tLv bcall(_vputs) ld a,(target) call GetEnemyIX ld l,(ix+e_Level) ld h,0 call vDisphl ld hl,pencol inc (hl) call DispEnemyName ld a,(target) cp 6 jr nc,ST_SkipCursor ld l,11 ld a,(ix+e_xpos) add a,4 ld ix,battleCursor ld b,4 call PutSprite ST_SkipCursor: call FastCopy call ST_checkkeys jr ST_Disp ST_CheckKeys: call waitkey cp gClear jp z,ST_Quit cp gLeft jr z,ST_Left cp gRight jr z,ST_Right cp gAlpha jr z,ST_Cancel cp gDel jr z,ST_Cancel cp g2nd jr z,ST_Done cp gEnter jr z,ST_Done ret st_Cancel: ld a,255 ld (Target),a st_Done: call copyapd call cleartextbox call fastcopy ;pop something to ret pop hl ret ST_Right: ld a,(target) inc a cp 6 jr nz,st_skipzero1 ld a,1 st_skipzero1: cp 8 jr nz,st_skipzero3 ld a,6 st_skipzero3: ld (target),a call GetEnemyIX ld a,(ix+e_HP) or (ix+e_HP+1) jr z,ST_Right ret ST_Left: ld a,(target) dec a cp 5 jr nz,st_skipzero2 ld a,7 st_skipzero2 or a jr nz,st_skipzero4 ld a,5 st_skipzero4 ld (target),a call GetEnemyIX ld a,(ix+e_HP) or (ix+e_HP+1) jr z,ST_Left ret ;ShowStatus: ; ld a,(target) ; call GetEnemyIX ; bcall(_cleargbuf) ; ld de,0 ; ld hl,tStats ; call FastVputs ; ld de,$0800 ; ld hl,tHP ; call FastVputs ; ld h,(ix+e_hp+1) ; ld l,(ix+e_hp) ; call vdisphl ; ld hl,tSlash ; bcall(_vputs) ; ; ; ; ret ; ; ; FastVputs: ld (pencol),de bcall(_vputs) ret BattleLoop: Yourturn: call BattleCommand or a jr z,cmdFight dec a jr z,cmdMagic dec a jr z,cmdHerb jr cmdRetreat cmdFight: ld hl,$0600 ld (Target),hl call selecttarget ld a,(target) cp 255 jr z,YourTurn call attack jr AllyTurn cmdHerb: ld a,(herbs) or a jr nz,cmdHerb2 ld de,$2902 ld hl,tNoHerbs call FastVputs jr YourTurn cmdHerb2: ld hl,$0607 ld (Target),hl call selecttarget cp 255 jr z,YourTurn jr AllyTurn cmdMagic: jr YourTurn ; ld hl,$0306 ; ld (target),hl ; call attack ; ; jr AllyTurn cmdRetreat: ;Retreating always works in this beta jp leavebattle AllyTurn: jr EnemyTurn EnemyTurn: ld a,6 ld (target),a ld b,5 xor a ETLoop: push bc inc a ld (source),a call getenemyix or (ix+e_hp) or (ix+e_hp+1) jr z,ETSkip1 call attack ETSkip1: pop bc ld a,(source) djnz ETLoop jr YourTurn ;================ ; AtJumpDown ;================ ;IX Jumps down and gives a mean look AtJumpDown: ;Erase monsters call eraseenemies ;Save the screen call copy2apd ;Load old sprite ld h,(ix+e_sprite+1) ld l,(ix+e_sprite) ;Add sprite size to increment sprite ld bc,32 add hl,bc ;Save new sprite ld (ix+e_sprite+1),h ld (ix+e_sprite),l ;jump down 7 pixels ld b,7 JumpDownLoop: ;Save counter and enemy offset push bc push ix ;Increment y position inc (ix+e_ypos) call copyapd call displayenemies call fastcopy ei halt pop ix pop bc djnz JumpDownLoop ret ;============== ; AtJumpUp ;============== ;IX jumps back up and reverts AtJumpUp: ;Erase monsters call eraseenemies ;Save the screen call copy2apd ;jump up 7 pixels ld b,7 JumpUpLoop: ;Save counter and enemy offset push bc push ix ;Increment y position dec (ix+e_ypos) call copyapd call displayenemies call fastcopy ei halt pop ix pop bc djnz JumpUpLoop ;Load old sprite ld h,(ix+e_sprite+1) ld l,(ix+e_sprite) ;Add sprite size to decrement sprite ld bc,-32 add hl,bc ;Save new sprite ld (ix+e_sprite+1),h ld (ix+e_sprite),l call copyapd call displayenemies call fastcopy ret ;================ ; EnemyHit ;=============== ;Animates like it got hit! EnemyHit: ld a,(target) cp 6 jr nc,shakescreen ; ret shakescreen: ld b,4 shake2: push bc ld hl,graph_mem+766 ld de,graph_mem+767 ld bc,766 lddr call fastcopy ei halt halt halt halt halt ld hl,graph_mem+1 ld de,graph_mem ld bc,766 ldir call fastcopy ei halt halt halt halt halt pop bc djnz shake2 ret ;================= ; SourceAttacks ;================= SourceAttacks: push hl ;Find out who's attacking ld a,(source) push af call getenemyix pop af ;If it's a monster it animates cp 6 call c,AtJumpDown ;Display "(source) Attacks!" ld hl,$2902 ld (pencol),hl call DispEnemyName pop hl bcall(_vputs) ret ;============================================= ; TextPause - Pauses until key or 3 seconds ;============================================= TextPause: call fastcopy ei ;Delay of 82 ld b,82 TP_Loop: HALT dec b jp z,cleartextbox icall(_getcsc) or a jr z, TP_loop jp cleartextbox ret ;=========================================== ; CalcAttackSpread - Adds 0-25% to hl ;=========================================== CalcAttackSpread: ;de=hl ld d,h ld e,l ;hl=hl/4 ld a,4 icall(_divhlbya) ;Prepare random, set contents and compare high byte to 0 ld b,l ld a,h or a jr z,at_spread_skip ;if high byte > 0 then max spread becomes 255 because I'm lazy ld b,255 ld h,0 at_spread_skip: ;make the spread call random ld l,a ;add it on add hl,de ret ;========================================= ; DealDamage - Deals hl damage to ix ;========================================= DealDamage: ;Save damage total push hl ld d,h ld e,l ;subtract damage from enemy hp ld h,(ix+e_hp+1) ld l,(ix+e_hp) sbc hl,de ;If damage is greater than life total, dead! jr nc, dd_notzero ld hl,0 dd_notzero: ;save new hp total ld (ix+e_hp+1),h ld (ix+e_hp),l ;Animate enemy! call EnemyHit ;Display "xxxx damage dealt" ld hl,$2902 ld (pencol),hl pop hl call vdisphl ld hl,tDamageDealt bcall(_vputs) ;Display "to Monster!" ld hl,$3002 ld (pencol),hl ld hl,tTo bcall(_vputs) call dispenemyname ld hl,tExclaim bcall(_vputs) ;Refresh screen, pause, clear the text box call textpause ;Check if dead ld a,(ix+e_hp) or (ix+e_hp+1) ;Done if not dead ret nz ;Display "Enemy dies!" ld hl,$2902 ld (pencol),hl call dispenemyname ld hl,tDies bcall(_vputs) ;Update Enemies call eraseenemies call displayenemies ;Refresh and wait jp textpause ;========================================== ; Attack! - (source) attacks (target) ;========================================== Attack: ;Source jumps down and " Attacks!" ld hl,tAttacks call SourceAttacks call textpause call fastcopy ;=================== ; Now do the math ;=================== ;Attack+(rnd(0,attack)/4)-(def/2) ;hl=e_atk ld h,(ix+e_atk+1) ld l,(ix+e_atk) ;add 0-25% call CalcAttackSpread ;Get new enemy ld a,(target) ;Save hl push hl call getenemyix ;De now contains attack damage so the next part won't mess it up pop de ;Get Defense Strength ld h,(ix+e_def+1) ld l,(ix+e_def) ;Divide it by 2 ld a,2 icall(_divhlbya) ;Subtract calculated defense from calculated damage ex de,hl ccf sbc hl,de ;If final damage is negative, make it 0. jr nc, not1dmg ld hl,0 ccf not1dmg: ;Force >= 1 inc hl call DealDamage ;Jump Back up ld a,(source) push af call getenemyix pop af cp 6 call c,AtJumpUp ;Fin call updatelifebar ret