#include #include #include #include #include #include "gr-sim.h" #include "tfv_utils.h" #include "tfv_zp.h" #include "tfv_defines.h" #include "tfv_definitions.h" #include "tfv_sprites.h" #include "tfv_backgrounds.h" /* 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; }; 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; static int draw_battle_bottom(int enemy_type) { int i; clear_bottom(); vtab(22); htab(1); move_cursor(); print(enemies[enemy_type].name); if (enemy_attacking) { vtab(24); htab(2); move_cursor(); print_inverse(enemies[enemy_type].attack_name); } vtab(22); htab(15); move_cursor(); // should print "NAMEO" // print("DEATER"); print(nameo); if (susie_out) { vtab(23); htab(15); move_cursor(); print("SUSIE"); } if (menu_state==MENU_NONE) { /* TFV Stats */ vtab(21); htab(25); move_cursor(); print("HP"); vtab(21); htab(28); move_cursor(); print("MP"); vtab(21); htab(31); move_cursor(); print("TIME"); vtab(21); htab(36); move_cursor(); if (limit<4) { print("LIMIT"); } else { /* Make if flash? set bit 0x40 */ print_flash("LIMIT"); } vtab(22); htab(24); move_cursor(); print_byte(hp); vtab(22); htab(27); move_cursor(); print_byte(mp); /* Draw Time bargraph */ // printf("Battle_bar=%d Limit=%d\n",battle_bar,limit); 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); /* Susie Stats */ if (susie_out) { vtab(23); htab(24); move_cursor(); print_byte(255); vtab(23); htab(27); move_cursor(); print_byte(0); #if 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); #endif } } if (menu_state==MENU_MAIN) { if (limit>3) { if (menu_position>5) menu_position=5; } else { if (menu_position>4) menu_position=4; } vtab(21); htab(24); move_cursor(); if (menu_position==0) print_inverse("ATTACK"); else print("ATTACK"); vtab(22); htab(24); move_cursor(); if (menu_position==2) print_inverse("MAGIC"); else print("MAGIC"); vtab(23); htab(24); move_cursor(); if (menu_position==4) print_inverse("SUMMON"); else print("SUMMON"); vtab(21); htab(32); move_cursor(); if (menu_position==1) print_inverse("SKIP"); else print("SKIP"); vtab(22); htab(32); move_cursor(); if (menu_position==3) print_inverse("ESCAPE"); else print("ESCAPE"); if (limit>3) { vtab(23); htab(32); move_cursor(); if (menu_position==5) print_inverse("LIMIT"); else print("LIMIT"); } } 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"); } 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"); } 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"); } /* Draw inverse separator */ ram[COLOR]=0x20; for(i=40;i<50;i+=2) { hlin_double(ram[DRAW_PAGE],12,12,i); } // ram[DRAW_PAGE]=saved_page; return 0; } static int enemy_hp=0,enemy_type=0,enemy_x=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; } static int enemy_attack(int tfv_x) { 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; } static int victory_dance(void) { 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); } return 0; } static int rotate_intro(void) { int xx,yy,color,x2,y2; double h,theta,dx,dy,theta2,thetadiff,nx,ny; int i; gr_copy(0x400,0xc00); // gr_copy_to_current(0xc00); // page_flip(); // gr_copy_to_current(0xc00); // page_flip(); thetadiff=0; for(i=0;i<8;i++) { grsim_update(); for(yy=0;yy<40;yy++) { for(xx=0;xx<40;xx++) { dx=(xx-20); dy=(yy-20); h=sqrt((dx*dx)+(dy*dy)); theta=atan2(dy,dx); theta2=theta+thetadiff; nx=h*cos(theta2); ny=h*sin(theta2); x2=nx+20; y2=ny+20; if ((x2<0) || (x2>39)) color=0; else if ((y2<0) || (y2>39)) color=0; else color=scrn_page(x2,y2,PAGE2); color_equals(color); plot(xx,yy); } } thetadiff+=(6.28/16.0); page_flip(); usleep(100000); } return 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(); } static void done_attack(void) { // reset battle time battle_count=0; menu_state=MENU_NONE; } #define MENU_MAIN_ATTACK 0 #define MENU_MAIN_SKIP 1 #define MENU_MAIN_MAGIC 2 #define MENU_MAIN_ESCAPE 3 #define MENU_MAIN_SUMMON 4 #define MENU_MAIN_LIMIT 5 static int running=0; void menu_keypress(int ch) { if ((ch==' ') || (ch==13)) { 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(); } } if (ch==27) { menu_state=MENU_MAIN; menu_position=0; } if (ch==APPLE_UP) { if (menu_position>=2) menu_position-=2; } if (ch==APPLE_DOWN) { menu_position+=2; } if (ch==APPLE_RIGHT) { menu_position++; } if (ch==APPLE_LEFT) { if (menu_position>0) menu_position--; } } int do_battle(int ground_color) { int i,ch; int saved_drawpage; int ax=34; int enemy_count=30; int old; rotate_intro(); battle_count=20; /* Setup Enemy */ // enemy_type=X // 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); saved_drawpage=ram[DRAW_PAGE]; ram[DRAW_PAGE]=PAGE2; /*******************/ /* Draw background */ /* Draw sky */ color_equals(COLOR_MEDIUMBLUE); for(i=0;i<10;i++) { hlin_double(ram[DRAW_PAGE],0,39,i); } /* Draw ground */ color_equals(ground_color); for(i=10;i<40;i++) { hlin_double(ram[DRAW_PAGE],0,39,i); } /* Draw some background images for variety? */ 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(enemies[enemy_type].sprite,enemy_x,20); 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) { victory_dance(); break; } } ram[DRAW_PAGE]=PAGE0; clear_bottom(); ram[DRAW_PAGE]=PAGE1; clear_bottom(); running=0; return 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; }