388 lines
7.6 KiB
C
388 lines
7.6 KiB
C
|
|
#include "menu.h"
|
|
#include "announce.h"
|
|
#include "bomber.h"
|
|
#include "draw.h"
|
|
#include "game.h"
|
|
#include "gfx.h"
|
|
#include "network.h"
|
|
#include "sound.h"
|
|
#include "utils.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;
|
|
}
|
|
}
|
|
}
|
|
menudelta = 0;
|
|
return menuexit;
|
|
}
|
|
|
|
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 const char* densities[] = {"PACKED", "HIGH", "MEDIUM", "LOW"};
|
|
static const char* generosities[] = {"LOW", "MEDIUM", "HIGH", "RIDICULOUS"};
|
|
static const char* dis_en_abled[] = {"DISABLED", "ENABLED"};
|
|
|
|
static void config_menu(void) {
|
|
int sel;
|
|
|
|
while (!exitflag) {
|
|
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);
|
|
additem("SOUND: %s", dis_en_abled[sound_enabled]);
|
|
sel = domenu(MENU_CONFIG, NULL);
|
|
switch (sel) {
|
|
case 0:
|
|
return;
|
|
case 1:
|
|
configopts.density += menudelta;
|
|
configopts.density &= 3;
|
|
break;
|
|
case 2:
|
|
configopts.generosity += menudelta;
|
|
configopts.generosity &= 3;
|
|
break;
|
|
case 3:
|
|
configopts.flames += menudelta;
|
|
configopts.flames &= 7;
|
|
break;
|
|
case 4:
|
|
configopts.bombs += menudelta;
|
|
configopts.bombs &= 7;
|
|
break;
|
|
case 5:
|
|
sound_enabled = 1 - sound_enabled;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
snprintf(temp, sizeof(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();
|
|
return;
|
|
case ' ':
|
|
case 13:
|
|
unregistergame();
|
|
if (begin_network_game()) {
|
|
run_network_game();
|
|
return;
|
|
}
|
|
send_invites();
|
|
draw_host_game();
|
|
}
|
|
}
|
|
|
|
if (!handle_joins()) continue;
|
|
|
|
send_invites();
|
|
draw_host_game();
|
|
}
|
|
}
|
|
|
|
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;
|
|
snprintf(temp, sizeof(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; }
|
|
|
|
while (!exitflag) {
|
|
switch (res) {
|
|
case 1:
|
|
failure("Game closed");
|
|
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 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()) { 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);
|
|
if (menudelta < 0) sel = -1;
|
|
}
|
|
stop_search();
|
|
|
|
if (menuexit == sel || !gamelistsize) { return; }
|
|
if (!tryjoin(sel)) { return; }
|
|
run_network_game();
|
|
}
|
|
|
|
void mainloop(void) {
|
|
int sel;
|
|
|
|
exitflag = 0;
|
|
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 (menudelta < 0) sel = -1;
|
|
switch (sel) {
|
|
case 0:
|
|
return;
|
|
case 1:
|
|
run_single_player();
|
|
break;
|
|
case 2:
|
|
config_menu();
|
|
break;
|
|
case 3:
|
|
host_game();
|
|
break;
|
|
case 4:
|
|
join_game();
|
|
break;
|
|
}
|
|
}
|
|
}
|