;================================ ; do battle ;================================ do_battle: lda #34 sta HERO_X lda #0 sta HERO_STATE sta MENU_STATE sta MENU_POSITION lda #3 sta HERO_LIMIT jsr rotate_intro lda #20 sta BATTLE_COUNT ;============================= ; Init Enemy ;============================= jsr init_enemy ;========================== ; Draw background ;========================== ; Draw sky ldx #0 ; blue from 0 .. 10 battle_sky_loop: lda gr_offsets,X sta GBASL lda gr_offsets+1,X clc adc #$8 ; store to $C00 sta GBASH lda #$66 ; COLOR_MEDIUMBLUE ldy #0 battle_sky_inner: sta (GBASL),Y iny cpy #40 bne battle_sky_inner inx inx cpx #10 bne battle_sky_loop ; green from 10 .. 40 battle_ground_loop: lda gr_offsets,X sta GBASL lda gr_offsets+1,X clc adc #$8 ; store to $C00 sta GBASH lda #$CC ; COLOR_LIGHTGREEN ; FIXME: should be GROUNDCOLOR ldy #0 battle_ground_inner: sta (GBASL),Y iny cpy #40 bne battle_ground_inner inx inx cpx #40 bne battle_ground_loop ; Draw some background images for variety? ; update bottom of screen jsr draw_battle_bottom main_battle_loop: jsr gr_copy_to_current ;======================================== ; draw our hero ;======================================== lda HERO_HP beq battle_draw_hero_down lda HERO_STATE and #HERO_STATE_RUNNING bne battle_draw_hero_running jmp battle_draw_normal_hero battle_draw_hero_down: ; grsim_put_sprite(tfv_defeat,ax-2,24); lda HERO_X sec sbc #2 sta XPOS lda #24 sta YPOS lda #tfv_defeat_sprite jmp battle_actual_draw_hero battle_draw_hero_running: ; grsim_put_sprite(tfv_stand_right,ax,20); ; grsim_put_sprite(tfv_walk_right,ax,20); lda HERO_X sta XPOS lda #20 sta YPOS lda FRAMEL and #$8 beq battle_draw_running_walk battle_draw_running_stand: lda #tfv_stand_right_sprite jmp battle_actual_draw_hero battle_draw_running_walk: lda #tfv_walk_right_sprite jmp battle_actual_draw_hero battle_draw_normal_hero: ; grsim_put_sprite(tfv_stand_left,ax,20); lda HERO_X sta XPOS lda #20 sta YPOS lda #tfv_stand_left_sprite sta INH jsr put_sprite_crop battle_draw_normal_sword: ; grsim_put_sprite(tfv_led_sword,ax-5,20); lda HERO_X sec sbc #5 sta XPOS lda #20 sta YPOS lda #tfv_led_sword_sprite battle_actual_draw_hero: sta INH jsr put_sprite_crop battle_done_draw_hero: ;=========================== ; draw enemy ;=========================== battle_draw_enemy: ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); lda ENEMY_X sta XPOS lda #20 sta YPOS draw_enemy_smc1: lda #$a5 sta INL draw_enemy_smc2: lda #$a5 battle_actual_draw_enemy: sta INH jsr put_sprite_crop battle_done_draw_enemy: ;======================================= ; draw bottom status jsr draw_battle_bottom ;======================================= ; page_flip jsr page_flip ; pause if dead ; if (hp==0) { ; for(i=0;i<15;i++) usleep(100000); ; break; ; } ; delay for framerate ; usleep(100000); ;======================= ; handle keypresses jsr get_keypress sta LAST_KEY cmp #'Q' beq done_battle ;======================== ; handle enemy attacks lda ENEMY_COUNT bne battle_no_enemy_attack battle_start_enemy_attack: ; attack and decrement HP jsr enemy_attack ; update limit count ; max out at 4 lda HERO_LIMIT cmp #4 beq battle_no_inc_limit inc HERO_LIMIT battle_no_inc_limit: ; reset enemy time. FIXME: variable? lda #50 sta ENEMY_COUNT battle_no_enemy_attack: dec ENEMY_COUNT ;=============================== ; handle battle counter update_battle_counter: lda BATTLE_COUNT cmp #64 bcc inc_battle_count ; blt ; battle timer expired, take action ; If running, escape ; TODO: randomly fail at running? */ lda HERO_STATE and #HERO_STATE_RUNNING beq battle_no_escape ; we bravely ran away jmp done_battle battle_no_escape: ; activate menu lda MENU_STATE cmp #MENU_NONE bne menu_activated ; move to main menu lda #MENU_MAIN sta MENU_STATE menu_activated: jsr battle_menu_keypress jmp done_battle_count inc_battle_count: inc BATTLE_COUNT done_battle_count: ;======================== ; check enemy defeated lda ENEMY_HP bne end_battle_loop jsr victory_dance jmp done_battle end_battle_loop: jmp main_battle_loop done_battle: jsr clear_bottoms ; running=0; ? rts .if 0 ; Do Battle */ ; Metrocat (summon?) */ ; Environment: grass, beach, forest, ice */ ; Enemies: HP ATTACK WEAKNESS RESIST */ ; Killer Crab RND-32 PINCH MALAISE FIRE ; Plain Fish BUBBLE FIRE ICE ; Evil Tree RND-16 LEAVE FIRE ICE ; Wood Elf SING MALAISE BOLT ; Giant Bee RND-64 BUZZSAW ICE NONE ; Procrastinon RND-32 PUTOFF NONE MALAISE ; Ice Fish RND-32 AUGER FIRE ICE ; EvilPenguin WADDLE FIRE ICE ; Battle. ; Forest? Grassland? Artic? Ocean? ; ATTACK REST ; MAGIC LIMIT ; SUMMON RUN ; ; SUMMONS -> METROCAT VORTEXCN ; MAGIC -> HEAL FIRE ; ICE MALAISE ; BOLT ; LIMIT -> SLICE ZAP ; DROP ; ; 1 2 3 ;0123456789012345678901234567890123456789| ;----------------------------------------| ; | HP LIMIT | -> FIGHT/LIMIT 21 ;KILLER CRAB | DEATER 128/255 128 | ZAP 22 ; | | REST 23 ; | | RUN AWAY 24 ; ;Sound effects? ; ;List hits ; ;****** ** **** **** ** ** ****** **** ****** ****** ****** ;** ** **** ** ** ** ** ** ** ** ** ** ** ** ;** ** ** **** **** ****** **** ****** ** ****** ****** ;** ** ** ** ** ** ** ** ** ** ** ** ** ;****** ****** ****** **** ** **** ****** ** ****** ** static int battle_bar=0; static int susie_out=0; ; Background depend on map location? */ ; Room for guinea pig in party? */ ; Attacks -> HIT, ZAP, HEAL, RUNAWAY */ #define MAGIC_NONE 0 #define MAGIC_FIRE 1 #define MAGIC_ICE 2 #define MAGIC_MALAISE 4 #define MAGIC_BOLT 8 #define MAGIC_HEAL 16 struct enemy_type { char *name; int hp_base,hp_mask; char *attack_name; int weakness,resist; unsigned char *sprite; }; .endif ;============================= ; Init Enemy ;============================= init_enemy: ; select type ; random, with weight toward proper terrain ; 50% completely random, 50% terrain based? ; enemy_type=random_8()%0x7; ; enemy_hp=enemies[enemy_type].hp_base+ ; (rand()&enemies[enemy_type].hp_mask); lda #0 ; hardcode crab for now sta ENEMY_TYPE sta ENEMY_X lda #200 sta ENEMY_HP lda #30 sta ENEMY_COUNT lda #killer_crab_sprite sta draw_enemy_smc2+1 rts .if 0 ;static struct enemy_type enemies[9]={ ; [0]= { ; .name="Killer Crab", ; .hp_base=50, ; .hp_mask=0x1f, ; .attack_name="Pinch", ; .weakness=MAGIC_MALAISE, ; .resist=MAGIC_FIRE, ; .sprite=killer_crab, ; }, ; [1]= { ; .name="Plain Fish", ; .hp_base=10, ; .hp_mask=0x1f, ; .attack_name="Bubble", ; .weakness=MAGIC_FIRE, ; .resist=MAGIC_ICE, ; .sprite=plain_fish, ; }, ; [2]= { ; .name="Evil Tree", ; .hp_base=10, ; .hp_mask=0x1f, ; .attack_name="Leaves", ; .weakness=MAGIC_FIRE, ; .resist=MAGIC_ICE, ; .sprite=evil_tree, ; }, ; [3]= { ; .name="Wood Elf", ; .hp_base=10, ; .hp_mask=0x1f, ; .attack_name="Song", ; .weakness=MAGIC_MALAISE, ; .resist=MAGIC_BOLT|MAGIC_HEAL, ; .sprite=wood_elf, ; }, ; [4]= { ; .name="Giant Bee", ; .hp_base=10, ; .hp_mask=0x1f, ; .attack_name="Buzzsaw", ; .weakness=MAGIC_ICE, ; .resist=MAGIC_NONE, ; .sprite=giant_bee, ; }, ; [5]= { ; .name="Procrastinon", ; .hp_base=10, ; .hp_mask=0x1f, ; .attack_name="Putoff", ; .weakness=MAGIC_NONE, ; .resist=MAGIC_MALAISE, ; .sprite=procrastinon, ; }, ; [6]= { ; .name="Ice Fish", ; .hp_base=10, ; .hp_mask=0x1f, ; .attack_name="Auger", ; .weakness=MAGIC_FIRE, ; .resist=MAGIC_ICE, ; .sprite=ice_fish, ; }, ; [7]= { ; .name="Evil Penguin", ; .hp_base=10, ; .hp_mask=0x1f, ; .attack_name="Waddle", ; .weakness=MAGIC_FIRE, ; .resist=MAGIC_ICE, ; .sprite=evil_penguin, ; }, ; [8]= { ; .name="Act.Principl", ; .hp_base=10, ; .hp_mask=0x1f, ; .attack_name="BIRDIE", ; .weakness=MAGIC_NONE, ; .resist=MAGIC_ICE|MAGIC_FIRE, ; .sprite=roboknee1, ; }, ;}; static int gr_put_num(int xx,int yy,int number) { int xt=xx,digit,left,hundreds; digit=number/100; if ((digit) && (digit<10)) { grsim_put_sprite(numbers[digit],xt,yy); xt+=4; } hundreds=digit; left=number%100; digit=left/10; if ((digit) || (hundreds)) { grsim_put_sprite(numbers[digit],xt,yy); xt+=4; } left=number%10; digit=left; grsim_put_sprite(numbers[digit],xt,yy); return 0; } ; ; ATTACK SKIP ; MAGIC LIMIT ; SUMMON ESCAPE ; ; SUMMONS -> METROCAT VORTEXCN ; MAGIC -> HEAL FIRE ; ICE MALAISE ; BOLT ; LIMIT -> SLICE ZAP ; DROP ; ; State Machine ; ; time ; BOTTOM -------> MAIN_MENU ----->ATTACK ; ------->SKIP ; ------->MAGIC_MENU ; ------->LIMIT_MENU ; ------->SUMMON_MENU ; ------->ESCAPE ; ; #define MENU_NONE 0 #define MENU_MAIN 1 #define MENU_MAGIC 2 #define MENU_SUMMON 3 #define MENU_LIMIT 4 static int enemy_attacking=0; static int menu_state=MENU_NONE; static int menu_position=0; static int battle_count=0; .endif battle_enemy_string: .byte 0,21,"KILLER CRAB",0 battle_enemy_attack_string: .byte 1,23,"PINCHING",0 battle_name_string: .byte 14,21,"DEATER",0 battle_menu_none: .byte 24,20,"HP",0 .byte 27,20,"MP",0 .byte 30,20,"TIME",0 .byte 35,20,"LIMIT",0 hp_string: .byte 23,21,"100",0 mp_string: .byte 26,21," 50",0 battle_menu_main: .byte 23,20,"ATTACK",0 .byte 23,21,"MAGIC",0 .byte 23,22,"SUMMON",0 .byte 31,20,"SKIP",0 .byte 31,21,"ESCAPE",0 .byte 31,22,"LIMIT",0 ;======================== ; draw_battle_bottom ;======================== ; static int draw_battle_bottom(int enemy_type) { draw_battle_bottom: jsr clear_bottom jsr normal_text ; print(enemies[enemy_type].name); lda #battle_enemy_string sta OUTH jsr move_and_print ; if (enemy_attacking) { ; print_inverse(enemies[enemy_type].attack_name); ; } ; print name string lda #battle_name_string sta OUTH jsr move_and_print ; if (susie_out) { ; vtab(23); ; htab(15); ; move_cursor(); ; print("SUSIE"); ; } lda MENU_STATE cmp #MENU_NONE beq draw_battle_menu_none cmp #MENU_MAIN beq draw_battle_menu_main draw_battle_menu_none: ;====================== ; TFV Stats lda #battle_menu_none sta OUTH jsr move_and_print jsr move_and_print jsr move_and_print ; make limit label flash if at limit break lda HERO_LIMIT cmp #4 bcc plain_limit jsr flash_text plain_limit: jsr move_and_print jsr normal_text jsr move_and_print ; HP jsr move_and_print ; MP ; Draw Time bargraph ; start at 30,42 go to battle_bar ; Y in X, X in A, max in CH ; hlin_double(ram[DRAW_PAGE],30,30+(battle_bar-1),42); lda BATTLE_COUNT lsr lsr lsr lsr sta CH ldx #42 lda #30 jsr draw_bargraph ; Draw Limit bargraph ; start at 30,42 go to battle_bar ; Y in X, X in A, max in CH ; if (limit) hlin_double(ram[DRAW_PAGE],35,35+limit,42); lda HERO_LIMIT sta CH ldx #42 lda #35 jsr draw_bargraph ; ; Susie Stats ; if (susie_out) { ; vtab(23); ; htab(24); ; move_cursor(); ; print_byte(255); ; ; vtab(23); ; htab(27); ; move_cursor(); ; print_byte(0); ; ; ; Draw Time bargraph ; ram[COLOR]=0xa0; ; hlin_double(ram[DRAW_PAGE],30,34,42); ; ram[COLOR]=0x20; ; if (battle_bar) { ; hlin_double(ram[DRAW_PAGE],30,30+(battle_bar-1),42); ; } ; ; ; Draw Limit break bargraph ; ram[COLOR]=0xa0; ; hlin_double(ram[DRAW_PAGE],35,39,42); ; ; ram[COLOR]=0x20; ; if (limit) hlin_double(ram[DRAW_PAGE],35,35+limit,42); jmp done_draw_battle_menu ;====================== ; draw main battle menu draw_battle_menu_main: ; wrap location lda HERO_LIMIT cmp #3 bcs limit3_wrap ; bge limit4_wrap: lda MENU_POSITION cmp #4 bcc done_menu_wrap lda #4 sta MENU_POSITION bne done_menu_wrap ; bra limit3_wrap: lda MENU_POSITION cmp #5 bcc done_menu_wrap lda #5 sta MENU_POSITION bne done_menu_wrap ; bra done_menu_wrap: lda #battle_menu_main sta OUTH ldx MENU_POSITION bne print_menu_attack ; print ATTACK jsr inverse_text print_menu_attack: jsr move_and_print jsr normal_text cpx #2 bne print_menu_magic ; print MAGIC jsr inverse_text print_menu_magic: jsr move_and_print jsr normal_text cpx #4 bne print_menu_summon ; print SUMMON jsr inverse_text print_menu_summon: jsr move_and_print jsr normal_text cpx #1 bne print_menu_skip ; print SKIP jsr inverse_text print_menu_skip: jsr move_and_print jsr normal_text cpx #3 bne print_menu_escape ; print ESCAPE jsr inverse_text print_menu_escape: jsr move_and_print jsr normal_text lda HERO_LIMIT cmp #4 bcc done_battle_draw_menu_main ; only draw if limit >=4 cpx #5 bne print_menu_limit ; print LIMIT jsr inverse_text print_menu_limit: jsr move_and_print jsr normal_text done_battle_draw_menu_main: jmp done_draw_battle_menu draw_battle_menu_summon: ; if (menu_state==MENU_SUMMON) { ; ; if (menu_position>1) menu_position=1; ; ; vtab(21); ; htab(25); ; move_cursor(); ; print("SUMMONS:"); ; ; vtab(22); ; htab(25); ; move_cursor(); ; if (menu_position==0) print_inverse("METROCAT"); ; else print("METROCAT"); ; ; vtab(23); ; htab(25); ; move_cursor(); ; if (menu_position==1) print_inverse("VORTEXCN"); ; else print("VORTEXCN"); ; } jmp done_draw_battle_menu draw_battle_menu_magic: ; if (menu_state==MENU_MAGIC) { ; ; if (menu_position>4) menu_position=4; ; ; vtab(21); ; htab(24); ; move_cursor(); ; print("MAGIC:"); ; ; vtab(22); ; htab(25); ; move_cursor(); ; if (menu_position==0) print_inverse("HEAL"); ; else print("HEAL"); ; ; vtab(23); ; htab(25); ; move_cursor(); ; if (menu_position==2) print_inverse("ICE"); ; else print("ICE"); ; ; vtab(24); ; htab(25); ; move_cursor(); ; if (menu_position==4) print_inverse("BOLT"); ; else print("BOLT"); ; ; vtab(22); ; htab(32); ; move_cursor(); ; if (menu_position==1) print_inverse("FIRE"); ; else print("FIRE"); ; ; vtab(23); ; htab(32); ; move_cursor(); ; if (menu_position==3) print_inverse("MALAISE"); ; else print("MALAISE"); ; ; } jmp done_draw_battle_menu draw_battle_menu_limit: ; if (menu_state==MENU_LIMIT) { ; ; if (menu_position>2) menu_position=2; ; ; vtab(21); ; htab(24); ; move_cursor(); ; print("LIMIT BREAKS:"); ; ; vtab(22); ; htab(25); ; move_cursor(); ; if (menu_position==0) print_inverse("SLICE"); ; else print("SLICE"); ; ; vtab(23); ; htab(25); ; move_cursor(); ; if (menu_position==2) print_inverse("DROP"); ; else print("DROP"); ; ; vtab(22); ; htab(32); ; move_cursor(); ; if (menu_position==1) print_inverse("ZAP"); ; else print("ZAP"); done_draw_battle_menu: ;======================== ; Draw inverse separator lda DRAW_PAGE bne draw_separator_page1 draw_separator_page0: lda #$20 sta $650+12 sta $6d0+12 sta $750+12 sta $7d0+12 bne done_draw_separator ; bra draw_separator_page1: lda #$20 sta $a50+12 sta $ad0+12 sta $b50+12 sta $bd0+12 done_draw_separator: rts ;=========================== ; draw bargraph ;=========================== ; draw text-mode bargraph ; ; limit is 0..4 ; battle_bar is battle_count/16 = 0..4 ; at 30, 35 both line 42 ; Y in X ; X in A ; max in CH draw_bargraph: clc adc gr_offsets,X sta GBASL lda gr_offsets+1,X clc adc DRAW_PAGE sta GBASH ldy #0 draw_bargraph_loop: cpy CH bcc bar_on lda #' '|$80 ; '_' ? bne done_bar bar_on: lda #' ' done_bar: sta (GBASL),Y iny cpy #5 bne draw_bargraph_loop rts .if 0 static int damage_enemy(int value) { if (enemy_hp>value) enemy_hp-=value; else enemy_hp=0; return 0; } static int heal_self(int value) { hp+=value; if (hp>max_hp) hp=max_hp; return 0; } static int damage_tfv(int value) { if (hp>value) hp-=value; else hp=0; return 0; } static int attack(void) { int ax=34; int damage=10; while(ax>10) { gr_copy_to_current(0xc00); if (ax&1) { grsim_put_sprite(tfv_stand_left,ax,20); } else { grsim_put_sprite(tfv_walk_left,ax,20); } grsim_put_sprite(tfv_led_sword,ax-5,20); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); draw_battle_bottom(enemy_type); page_flip(); ax-=1; usleep(20000); } damage_enemy(damage); gr_put_num(2,10,damage); page_flip(); usleep(250000); return 0; } .endif ;=============================== ; enemy attack ;=============================== enemy_attack: ; int ax=enemy_x; ; int damage=10; ; enemy_attacking=1; ; while(ax<30) { ; put attack name on ; occasionally attack with that enemy's power? ; occasionally heal self? ; gr_copy_to_current(0xc00); ; draw first so behind enemy ; grsim_put_sprite(tfv_stand_left,tfv_x,20); ; grsim_put_sprite(tfv_led_sword,tfv_x-5,20); ; if (ax&1) { ; grsim_put_sprite(enemies[enemy_type].sprite,ax,20); ; } ; else { ; grsim_put_sprite(enemies[enemy_type].sprite,ax,20); ; } ; draw_battle_bottom(enemy_type); ; page_flip(); ; ax+=1; ; usleep(20000); ; } ; enemy_attacking=0; ; damage_tfv(damage); ; gr_put_num(25,10,damage); ; draw_battle_bottom(enemy_type); ; page_flip(); ; usleep(250000); ; return damage; ;} rts ;==================================== ; victory dance ;==================================== victory_dance: .if 0 int ax=34; int i; int saved_drawpage; saved_drawpage=ram[DRAW_PAGE]; ram[DRAW_PAGE]=PAGE2; ; 0xc00 clear_bottom(); vtab(21); htab(10); move_cursor(); print("EXPERIENCE +2"); experience+=2; vtab(22); htab(10); move_cursor(); print("MONEY +1"); money+=1; ram[DRAW_PAGE]=saved_drawpage; for(i=0;i<25;i++) { gr_copy_to_current(0xc00); if (i&1) { grsim_put_sprite(tfv_stand_left,ax,20); grsim_put_sprite(tfv_led_sword,ax-5,20); } else { grsim_put_sprite(tfv_victory,ax,20); grsim_put_sprite(tfv_led_sword,ax-2,14); } page_flip(); usleep(200000); .endif rts .if 0 #define MENU_MAGIC_HEAL 0 #define MENU_MAGIC_ICE 1 #define MENU_MAGIC_FIRE 2 #define MENU_MAGIC_MALAISE 3 #define MENU_MAGIC_BOLT 4 static void magic_attack(int which) { int ax=34,ay=20; int mx,my; int damage=20; int i; unsigned char *sprite; if (which==MENU_MAGIC_HEAL) { sprite=magic_health; mx=33; my=20; } if (which==MENU_MAGIC_FIRE) { sprite=magic_fire; mx=2; my=20; } if (which==MENU_MAGIC_ICE) { sprite=magic_ice; mx=2; my=20; } if (which==MENU_MAGIC_BOLT) { sprite=magic_bolt; mx=2; my=20; } if (which==MENU_MAGIC_MALAISE) { sprite=magic_malaise; mx=2; my=20; } ; FIXME: damage based on weakness of enemy ; FIXME: disallow if not enough MP ; cast the magic */ i=0; while(i<10) { gr_copy_to_current(0xc00); grsim_put_sprite(tfv_victory,34,20); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); draw_battle_bottom(enemy_type); page_flip(); i++; usleep(20000); } ax=34; ay=20; i=0; ; Actually put the magic */ while(i<=20) { gr_copy_to_current(0xc00); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); grsim_put_sprite(tfv_stand_left,ax,ay); grsim_put_sprite(tfv_led_sword,ax-5,ay); grsim_put_sprite(sprite,mx+(i&1),my); draw_battle_bottom(enemy_type); page_flip(); i++; usleep(100000); } mp-=5; gr_copy_to_current(0xc00); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); grsim_put_sprite(tfv_stand_left,ax,ay); grsim_put_sprite(tfv_led_sword,ax-5,ay); draw_battle_bottom(enemy_type); if (which!=MENU_MAGIC_HEAL) { damage_enemy(damage); gr_put_num(2,10,damage); } else { heal_self(damage); } draw_battle_bottom(enemy_type); page_flip(); for(i=0;i<20;i++) { usleep(100000); } } ; Limit Break "Drop" */ ; Jump into sky, drop down and slice enemy in half */ static void limit_break_drop(void) { int ax=34,ay=20; int damage=100; int i; while(ay>0) { gr_copy_to_current(0xc00); grsim_put_sprite(tfv_stand_left,ax,ay); grsim_put_sprite(tfv_led_sword,ax-5,ay); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); draw_battle_bottom(enemy_type); page_flip(); ay-=1; usleep(20000); } ax=10; ay=0; ; Falling */ while(ay<=20) { gr_copy_to_current(0xc00); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); grsim_put_sprite(tfv_stand_left,ax,ay); grsim_put_sprite(tfv_led_sword,ax-5,ay); draw_battle_bottom(enemy_type); color_equals(13); vlin(0,ay,ax-5); page_flip(); ay+=1; usleep(100000); } i=0; while(i<13) { gr_copy_to_current(0xc00); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); grsim_put_sprite(tfv_stand_left,ax,ay); grsim_put_sprite(tfv_led_sword,ax-5,ay); draw_battle_bottom(enemy_type); color_equals(COLOR_LIGHTGREEN); vlin(ay,ay+i,ax-5); page_flip(); i++; usleep(100000); } ax=34; ay=20; gr_copy_to_current(0xc00); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); grsim_put_sprite(tfv_stand_left,ax,ay); grsim_put_sprite(tfv_led_sword,ax-5,ay); draw_battle_bottom(enemy_type); color_equals(COLOR_LIGHTGREEN); vlin(20,33,5); damage_enemy(damage); gr_put_num(2,10,damage); page_flip(); for(i=0;i<20;i++) { usleep(100000); } } ; Limit Break "Slice" */ ; Run up and slap a bunch with sword */ ; TODO: cause damage value to bounce around more? */ static void limit_break_slice(void) { int tx=34,ty=20; int damage=5; int i; while(tx>10) { gr_copy_to_current(0xc00); grsim_put_sprite(tfv_stand_left,tx,ty); grsim_put_sprite(tfv_led_sword,tx-5,ty); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); draw_battle_bottom(enemy_type); page_flip(); tx-=1; usleep(20000); } ; Slicing */ for(i=0;i<20;i++) { gr_copy_to_current(0xc00); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); if (i&1) { grsim_put_sprite(tfv_stand_left,tx,20); grsim_put_sprite(tfv_led_sword,tx-5,20); } else { grsim_put_sprite(tfv_victory,tx,20); grsim_put_sprite(tfv_led_sword,tx-2,14); } damage_enemy(damage); ; gr_put_num(2+(i%2),10+((i%2)*2),damage); draw_battle_bottom(enemy_type); page_flip(); usleep(100000); } tx=34; ty=20; gr_copy_to_current(0xc00); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); grsim_put_sprite(tfv_stand_left,tx,ty); grsim_put_sprite(tfv_led_sword,tx-5,ty); draw_battle_bottom(enemy_type); page_flip(); for(i=0;i<20;i++) { usleep(100000); } } ; Limit Break "Zap" */ ; Zap with a laser out of the LED sword */ static void limit_break_zap(void) { int tx=34,ty=20; int damage=100; int i; gr_copy_to_current(0xc00); ; Draw background */ color_equals(COLOR_AQUA); vlin(12,24,34); hlin_double(ram[DRAW_PAGE],28,38,18); ; Sword in air */ grsim_put_sprite(tfv_victory,tx,20); grsim_put_sprite(tfv_led_sword,tx-2,14); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); draw_battle_bottom(enemy_type); page_flip(); usleep(500000); for(i=0;i<32;i++) { gr_copy_to_current(0xc00); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); color_equals(i%16); hlin_double(ram[DRAW_PAGE],5,30,22); grsim_put_sprite(tfv_stand_left,tx,ty); grsim_put_sprite(tfv_led_sword,tx-5,ty); draw_battle_bottom(enemy_type); page_flip(); usleep(100000); } gr_copy_to_current(0xc00); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); grsim_put_sprite(tfv_stand_left,tx,ty); grsim_put_sprite(tfv_led_sword,tx-5,ty); draw_battle_bottom(enemy_type); damage_enemy(damage); gr_put_num(2,10,damage); page_flip(); for(i=0;i<20;i++) { usleep(100000); } } #define MENU_LIMIT_SLICE 0 #define MENU_LIMIT_ZAP 1 #define MENU_LIMIT_DROP 2 static void limit_break(int which) { if (which==MENU_LIMIT_DROP) limit_break_drop(); else if (which==MENU_LIMIT_SLICE) limit_break_slice(); else if (which==MENU_LIMIT_ZAP) limit_break_zap(); ; reset limit counter */ limit=0; } static void summon_metrocat(void) { int tx=34,ty=20; int damage=100; int i; int ax=28,ay=2; i=0; while(i<30) { gr_copy_to_current(0xc00); grsim_put_sprite(tfv_stand_left,tx,ty); grsim_put_sprite(tfv_led_sword,tx-5,ty); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); grsim_put_sprite(metrocat,ax,ay); draw_battle_bottom(enemy_type); page_flip(); i++; usleep(20000); } while(ax>15) { gr_copy_to_current(0xc00); grsim_put_sprite(tfv_stand_left,tx,ty); grsim_put_sprite(tfv_led_sword,tx-5,ty); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); grsim_put_sprite(metrocat,ax,ay); draw_battle_bottom(enemy_type); page_flip(); ax-=1; usleep(20000); } while(ax>5) { gr_copy_to_current(0xc00); grsim_put_sprite(tfv_stand_left,tx,ty); grsim_put_sprite(tfv_led_sword,tx-5,ty); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); grsim_put_sprite(metrocat,ax,ay); draw_battle_bottom(enemy_type); page_flip(); ay+=1; ax-=1; usleep(20000); } i=0; while(i<30) { gr_copy_to_current(0xc00); grsim_put_sprite(tfv_stand_left,tx,ty); grsim_put_sprite(tfv_led_sword,tx-5,ty); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); grsim_put_sprite(metrocat,ax,ay); draw_battle_bottom(enemy_type); page_flip(); i++; usleep(20000); } gr_copy_to_current(0xc00); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); grsim_put_sprite(tfv_stand_left,tx,ty); grsim_put_sprite(tfv_led_sword,tx-5,ty); draw_battle_bottom(enemy_type); damage_enemy(damage); gr_put_num(2,10,damage); page_flip(); for(i=0;i<20;i++) { usleep(100000); } } static void summon_vortex_cannon(void) { int tx=34,ty=20; int damage=5; int i; int ax=20,ay=20; ; draw the cannon */ i=0; while(i<30) { gr_copy_to_current(0xc00); grsim_put_sprite(tfv_stand_left,tx,ty); grsim_put_sprite(tfv_led_sword,tx-5,ty); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); grsim_put_sprite(vortex_cannon,ax,ay); draw_battle_bottom(enemy_type); page_flip(); i++; usleep(20000); } ; Fire vortices */ ax=20; for(i=0;i<5;i++) { while(ax>5) { gr_copy_to_current(0xc00); grsim_put_sprite(tfv_stand_left,tx,ty); grsim_put_sprite(tfv_led_sword,tx-5,ty); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); grsim_put_sprite(vortex_cannon,20,20); grsim_put_sprite(vortex,ax,24); draw_battle_bottom(enemy_type); if (ax<10) { gr_put_num(2,10,damage); } page_flip(); ax-=1; usleep(50000); } damage_enemy(damage); ax=20; } gr_copy_to_current(0xc00); ; grsim_put_sprite(enemies[enemy_type].sprite,enemy_x,20); grsim_put_sprite(tfv_stand_left,tx,ty); grsim_put_sprite(tfv_led_sword,tx-5,ty); draw_battle_bottom(enemy_type); page_flip(); for(i=0;i<20;i++) { usleep(100000); } } static void summon(int which) { if (which==0) summon_metrocat(); else summon_vortex_cannon(); } .endif done_attack: lda #0 sta BATTLE_COUNT lda #MENU_NONE sta MENU_STATE ;========================= ; battle menu keypress ;========================= battle_menu_keypress: lda LAST_KEY cmp #27 beq keypress_escape cmp #'W' beq keypress_up cmp #'S' beq keypress_down cmp #'A' beq keypress_left cmp #'D' beq keypress_right cmp #' ' beq keypress_action cmp #13 beq keypress_action rts keypress_escape: lda #MENU_MAIN sta MENU_STATE lda #0 sta MENU_POSITION rts keypress_up: lda MENU_POSITION cmp #2 bcc done_keypress_up ; blt dec MENU_POSITION dec MENU_POSITION done_keypress_up: rts keypress_down: inc MENU_POSITION inc MENU_POSITION rts keypress_right: inc MENU_POSITION rts keypress_left: lda MENU_POSITION beq done_keypress_left dec MENU_POSITION done_keypress_left: rts keypress_action: ; if (menu_state==MENU_MAIN) { ; ; switch(menu_position) { ; case MENU_MAIN_ATTACK: ; ; attack and decrement HP ; attack(); ; done_attack(); ; break; ; case MENU_MAIN_SKIP: ; done_attack(); ; break; ; case MENU_MAIN_MAGIC: ; menu_state=MENU_MAGIC; ; menu_position=0; ; break; ; case MENU_MAIN_LIMIT: ; menu_state=MENU_LIMIT; ; menu_position=0; ; break; ; case MENU_MAIN_SUMMON: ; menu_state=MENU_SUMMON; ; menu_position=0; ; break; ; case MENU_MAIN_ESCAPE: ; running=1; ; done_attack(); ; break; ; } ; } ; else if (menu_state==MENU_MAGIC) { ; magic_attack(menu_position); ; done_attack(); ; } ; else if (menu_state==MENU_LIMIT) { ; limit_break(menu_position); ; done_attack(); ; } ; else if (menu_state==MENU_SUMMON) { ; summon(menu_position); ; done_attack(); ; } ; } rts .if 0 int boss_battle(void) { int i,ch; int saved_drawpage; int ax=34; int enemy_count=30; int old; susie_out=1; rotate_intro(); battle_count=20; enemy_type=8; enemy_hp=255; saved_drawpage=ram[DRAW_PAGE]; ram[DRAW_PAGE]=PAGE2; ;******************/ ; Draw background */ ; Draw sky */ color_equals(COLOR_BLACK); for(i=0;i<20;i++) { hlin_double(ram[DRAW_PAGE],0,39,i); } color_equals(COLOR_ORANGE); for(i=20;i<39;i++) { hlin_double(ram[DRAW_PAGE],0,39,i); } ; Draw horizon */ ; color_equals(COLOR_GREY); ; hlin_double(ram[DRAW_PAGE],0,39,10); ram[DRAW_PAGE]=saved_drawpage; draw_battle_bottom(enemy_type); while(1) { gr_copy_to_current(0xc00); if (hp==0) { grsim_put_sprite(tfv_defeat,ax-2,24); } else if (running) { ; if (battle_count%2) { grsim_put_sprite(tfv_stand_right,ax,20); } else { grsim_put_sprite(tfv_walk_right,ax,20); } } else { grsim_put_sprite(tfv_stand_left,ax,20); grsim_put_sprite(tfv_led_sword,ax-5,20); } grsim_put_sprite(susie_left,28,30); if ((enemy_count&0xf)<4) { grsim_put_sprite(roboknee1,enemy_x,16); } else { grsim_put_sprite(roboknee2,enemy_x,16); } draw_battle_bottom(enemy_type); page_flip(); if (hp==0) { for(i=0;i<15;i++) usleep(100000); break; } usleep(100000); ch=grsim_input(); if (ch=='q') return 0; if (enemy_count==0) { ; attack and decrement HP enemy_attack(ax); ; update limit count if (limit<4) limit++; ; reset enemy time. FIXME: variable? enemy_count=50; } else { enemy_count--; } if (battle_count>=64) { ; TODO: randomly fail at running? */ if (running) { break; } if (menu_state==MENU_NONE) menu_state=MENU_MAIN; menu_keypress(ch); } else { battle_count++; } old=battle_bar; battle_bar=(battle_count/16); if (battle_bar!=old) draw_battle_bottom(enemy_type); if (enemy_hp==0) { ; FIXME? victory_dance(); break; } } ram[DRAW_PAGE]=PAGE0; clear_bottom(); ram[DRAW_PAGE]=PAGE1; clear_bottom(); running=0; return 0; } .endif