405 lines
7.2 KiB
C
405 lines
7.2 KiB
C
|
|
#include "bomber.h"
|
|
#include "menu.h"
|
|
#include "draw.h"
|
|
#include "gfx.h"
|
|
#include "utils.h"
|
|
#include "sound.h"
|
|
#include "network.h"
|
|
#include "announce.h"
|
|
#include "game.h"
|
|
|
|
GameOptions configopts = { 2, 1, 0, 2 };
|
|
|
|
/* Generic menu */
|
|
|
|
typedef enum {
|
|
MENU_ANY = -1,
|
|
MENU_MAIN = 0,
|
|
MENU_CONFIG = 2,
|
|
MENU_JOIN = 3
|
|
} menuname;
|
|
|
|
#define MENU_SELECT(x) ((menuname) (-x-1))
|
|
|
|
static int menuhistory[32]={0};
|
|
static char menustring[1024];
|
|
static char *menuput,*menuitems[40],*menutitle;
|
|
static int menunum, menuexit;
|
|
static int menudelta;
|
|
|
|
static void drawmenu(int selected) {
|
|
int i,j;
|
|
int tx,ty;
|
|
|
|
clear();
|
|
j=strlen(menutitle)*bigfontxsize;
|
|
drawbigstring((IXSIZE-j) >> 1,20,menutitle);
|
|
ty=((IYSIZE-(bigfontysize*menunum))>>1)-(IYSIZE>>3);
|
|
for(i=0;i<menunum;++i)
|
|
{
|
|
j=strlen(menuitems[i])*bigfontxsize;
|
|
tx=(IXSIZE-j) >> 1;
|
|
if(i==selected)
|
|
{
|
|
greyrect(0,ty-1,tx-5,bigfontysize);
|
|
greyrect(tx+j+3,ty-1,IXSIZE-(tx+j+3),bigfontysize);
|
|
}
|
|
drawbigstring(tx,ty,menuitems[i]);
|
|
ty+=bigfontyspace;
|
|
}
|
|
}
|
|
|
|
static int domenu(menuname whichmenu, int (*pause)(void)) {
|
|
char redraw;
|
|
int selected;
|
|
int mcount=0;
|
|
|
|
if(whichmenu>=0)
|
|
selected=menuhistory[whichmenu];
|
|
else
|
|
selected=-whichmenu-1;
|
|
|
|
if (!pause) pause=mypause;
|
|
|
|
redraw=1;
|
|
clearspritelist();
|
|
while(!exitflag) {
|
|
if(redraw) {
|
|
drawmenu(selected);
|
|
redraw=0;
|
|
}
|
|
if (!pause()) return -1;
|
|
scaninput();
|
|
++mcount;
|
|
|
|
clearsprites();
|
|
clearspritelist();
|
|
addsprite(IXSIZE/2-50-20,IYSIZE-80,walking[2]+(30+mcount%15));
|
|
addsprite(IXSIZE/2+50-20,IYSIZE-80,walking[3]+(30+(mcount+7)%15));
|
|
plotsprites();
|
|
copyup();
|
|
|
|
if(anydown()) playsound(3);
|
|
while(anydown()) {
|
|
switch(takedown()) {
|
|
case MYLEFT:
|
|
menudelta=-1;
|
|
return selected;
|
|
case MYRIGHT:
|
|
case ' ':
|
|
case 13:
|
|
menudelta=1;
|
|
return selected;
|
|
case 'k':
|
|
case MYUP:
|
|
if (selected) --selected;
|
|
else selected=menunum-1;
|
|
if (whichmenu>=0)
|
|
menuhistory[whichmenu]=selected;
|
|
redraw=1;
|
|
break;
|
|
case 'j':
|
|
case MYDOWN:
|
|
++selected;
|
|
if (selected==menunum) selected=0;
|
|
if (whichmenu>=0)
|
|
menuhistory[whichmenu]=selected;
|
|
redraw=1;
|
|
break;
|
|
case 0x1b:
|
|
if (MENU_MAIN == whichmenu && menuexit != selected) {
|
|
selected = menuexit;
|
|
redraw = 1;
|
|
break;
|
|
}
|
|
menudelta = 1;
|
|
return menuexit;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void menustart() {
|
|
menunum=-1;
|
|
menuput=menustring;
|
|
*menuput=0;
|
|
menuexit = 0;
|
|
}
|
|
|
|
static void additem_s(char *item, int len) {
|
|
if (len < 0 || (menustring+sizeof(menustring)-menuput <= len)) return;
|
|
|
|
if(menunum<0)
|
|
menutitle=menuput;
|
|
else
|
|
menuitems[menunum]=menuput;
|
|
++menunum;
|
|
memcpy(menuput,item,len+1);
|
|
menuput += len+1;
|
|
}
|
|
|
|
static void additem(char *item,...) {
|
|
char output[256];
|
|
va_list ap;
|
|
int len;
|
|
|
|
va_start(ap, item);
|
|
|
|
len = vsnprintf(output,sizeof(output),item,ap);
|
|
if (len >= 256) len = 255; /* truncated string */
|
|
|
|
additem_s(output, len);
|
|
}
|
|
|
|
static void addexit(char *item,...) {
|
|
char output[256];
|
|
va_list ap;
|
|
int len;
|
|
|
|
va_start(ap, item);
|
|
|
|
len = vsnprintf(output,sizeof(output),item,ap);
|
|
if (len >= 256) len = 255; /* truncated string */
|
|
|
|
menuexit = menunum;
|
|
additem_s(output, len);
|
|
}
|
|
|
|
|
|
/* end generic menu */
|
|
|
|
/* game menues */
|
|
|
|
static void drawjoinscreen(void) {
|
|
int i;
|
|
char name[17];
|
|
char temp[64];
|
|
|
|
#define JX (IXSIZE/3)
|
|
#define JY (IYSIZE/4)
|
|
|
|
clear();
|
|
centerbig(20,"JOIN NETWORK GAME");
|
|
drawbigstring(JX,JY,"SLOT NAME");
|
|
for(i=0;i<MAXNETNODES;++i)
|
|
{
|
|
if(!netnodes[i].used) continue;
|
|
memmove(name,netnodes[i].name,16);
|
|
name[16]=0;
|
|
sprintf(temp," %d %s",i+1,name);
|
|
drawbigstring(JX,JY+(i+1)*bigfontyspace,temp);
|
|
}
|
|
}
|
|
|
|
static int tryjoin(int which) {
|
|
int res;
|
|
|
|
if (0 == (res = send_join(&gamelistentries[which].netname, playername)))
|
|
return 0;
|
|
|
|
for ( ;; ) {
|
|
switch (res) {
|
|
case 1: return 0;
|
|
case 2:
|
|
drawjoinscreen();
|
|
copyup();
|
|
break;
|
|
case 3: return 1;
|
|
default: break;
|
|
}
|
|
scaninput();
|
|
while(anydown()) {
|
|
switch(takedown()) {
|
|
case 0x1b:
|
|
send_quit();
|
|
return 0;
|
|
}
|
|
}
|
|
res=scaninvite(200);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void main_menu(void) {
|
|
int sel;
|
|
|
|
while(!exitflag) {
|
|
menustart();
|
|
additem("BOMBER MAIN MENU");
|
|
additem("EXIT GAME");
|
|
additem("START SINGLE PLAYER GAME");
|
|
additem("OPTIONS");
|
|
// additem("REMAP MOVEMENT KEYS");
|
|
additem("START NETWORK GAME");
|
|
additem("JOIN NETWORK GAME");
|
|
sel=domenu(MENU_MAIN, NULL);
|
|
if(!sel) {exitflag=1;break;}
|
|
if(sel==1) {gamemode=1;break;}
|
|
if(sel==2) {gamemode=2;break;}
|
|
if(sel==3) {gamemode=3;break;}
|
|
if(sel==4) {gamemode=4;break;}
|
|
}
|
|
}
|
|
|
|
char *densities[]={"PACKED","HIGH","MEDIUM","LOW"};
|
|
char *generosities[]={"LOW","MEDIUM","HIGH","RIDICULOUS"};
|
|
|
|
static void config_menu(void) {
|
|
int sel;
|
|
|
|
for(;;) {
|
|
menustart();
|
|
additem("GAME OPTIONS");
|
|
additem("RETURN TO MAIN MENU");
|
|
additem("DENSITY: %s",densities[configopts.density]);
|
|
additem("GENEROSITY: %s",generosities[configopts.generosity]);
|
|
additem("INITIAL FLAME LENGTH: %d",configopts.flames+1);
|
|
additem("INITIAL NUMBER OF BOMBS: %d",configopts.bombs+1);
|
|
sel=domenu(MENU_CONFIG, NULL);
|
|
if(!sel) {gamemode=0;break;}
|
|
if(sel==1) {
|
|
configopts.density+=menudelta;
|
|
configopts.density&=3;
|
|
}
|
|
if(sel==2) {
|
|
configopts.generosity+=menudelta;
|
|
configopts.generosity&=3;
|
|
}
|
|
if(sel==3) {
|
|
configopts.flames+=menudelta;
|
|
configopts.flames&=7;
|
|
}
|
|
if(sel==4) {
|
|
configopts.bombs+=menudelta;
|
|
configopts.bombs&=7;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void failure(char *str,...) {
|
|
gamemode=0;
|
|
}
|
|
|
|
static void draw_host_game(void) {
|
|
int i;
|
|
char *name;
|
|
char temp[64];
|
|
|
|
#define M3X (IXSIZE/3)
|
|
#define M3Y (IYSIZE/4)
|
|
|
|
clear();
|
|
centerbig(20,"HOST NETWORK GAME");
|
|
drawbigstring(M3X,M3Y,"SLOT NAME");
|
|
for(i=0;i<MAXNETNODES;++i) {
|
|
if(!netnodes[i].used) continue;
|
|
name=netnodes[i].name;
|
|
sprintf(temp," %d %s",i+1,name);
|
|
drawbigstring(M3X,M3Y+(i+2)*bigfontyspace,temp);
|
|
}
|
|
|
|
copyup();
|
|
}
|
|
|
|
|
|
static void host_game(void) {
|
|
create_seed_unique();
|
|
if (!start_network_game()) {
|
|
failure("COULD NOT REGISTER GAME");
|
|
return;
|
|
}
|
|
|
|
draw_host_game();
|
|
for(;;) {
|
|
scaninput();
|
|
while(anydown()) {
|
|
switch(takedown()) {
|
|
case 0x1b:
|
|
unregistergame();
|
|
cancel_network_game();
|
|
gamemode=0;
|
|
return;
|
|
case ' ':
|
|
case 13:
|
|
unregistergame();
|
|
if (begin_network_game()) {
|
|
gamemode=5;
|
|
return;
|
|
}
|
|
send_invites();
|
|
draw_host_game();
|
|
}
|
|
}
|
|
|
|
if (!handle_joins()) continue;
|
|
|
|
send_invites();
|
|
draw_host_game();
|
|
}
|
|
|
|
gamemode=0;
|
|
}
|
|
|
|
static int join_game_pause(void) {
|
|
if (find_more_games()) return 0;
|
|
mypause();
|
|
return 1;
|
|
}
|
|
|
|
static void join_game(void) {
|
|
int i;
|
|
int sel = -1;
|
|
|
|
if (!searchgames()) {
|
|
gamemode = 0;
|
|
return;
|
|
}
|
|
|
|
menuhistory[MENU_JOIN] = 0;
|
|
|
|
while (-1 == sel) {
|
|
menustart();
|
|
if (gamelistsize == 0) {
|
|
additem("JOIN NETWORK GAME - NO GAMES AVAILABLE");
|
|
addexit("EXIT");
|
|
} else {
|
|
additem("JOIN NETWORK GAME");
|
|
for (i = 0; i < gamelistsize; i++) {
|
|
additem(gamelistentries[i].name);
|
|
}
|
|
addexit("EXIT");
|
|
}
|
|
sel = domenu(MENU_JOIN, join_game_pause);
|
|
}
|
|
stop_search();
|
|
|
|
if(menuexit == sel || !gamelistsize) {
|
|
gamemode=0;
|
|
return;
|
|
}
|
|
if(!tryjoin(sel)) {
|
|
gamemode=0;
|
|
return;
|
|
}
|
|
network = NETWORK_SLAVE;
|
|
gamemode=5;
|
|
}
|
|
|
|
void (*modefunctions[])()= {
|
|
main_menu,
|
|
run_single_player,
|
|
config_menu,
|
|
host_game,
|
|
join_game,
|
|
run_network_game,
|
|
};
|
|
|
|
|
|
void mainloop(void) {
|
|
exitflag=0;
|
|
while(!exitflag)
|
|
modefunctions[gamemode]();
|
|
}
|