/* $Id: playermenu.c,v 1.8 2004/09/26 02:28:06 stpohle Exp $ * */ #include "bomberclone.h" #include "menu.h" #include "menugui.h" #include "player.h" #include "network.h" #include "keyb.h" #include "single.h" #include "ogcache-client.h" /* * prototype definitions */ // static int playermenu_gfxaviable (int gfx); static void playermenu_selgfx_drawplayer (int selgfx, _menu *menu); static void teammenu_ai_choosegfx (); #define PLAYERMENU_GFXSEL_Y 130 /* * check if the gfx is still aviable * static int playermenu_gfxaviable (int gfx) { int i; for (i = 0; i < MAX_PLAYERS && gfx != players[i].gfx_nr; i++); if (i == MAX_PLAYERS) return 1; return 0; }; * * **** DO WE NEED THIS? */ /* * show the basis menu */ static void playermenu_selgfx_drawplayer (int selgfx, _menu *menu) { static int old_gfxsel = -1; static int changed = 0; SDL_Rect rect, srcrect; int i; /* * delete old state, to force an update of all playergfx */ if (menu == NULL) { changed = 1; return; } if (selgfx != old_gfxsel) changed = 1; old_gfxsel = selgfx; /* * 3. draw changes from the last loop */ if (changed) { rect.x = 0; rect.w = menu->oldscreenpos.w - 2 * menuimages[0]->w; rect.y = PLAYERMENU_GFXSEL_Y; rect.h = 4 * GFX_IMGSIZE; menu_draw_background (menu, &rect); for (i = 0; i < gfx.player_gfx_count; i++) { srcrect.h = rect.h = gfx.players[i].menu_image->h; srcrect.w = rect.w = gfx.players[i].menu_image->w; rect.x = (2 * GFX_MENUPLAYERIMGSIZE_X) * (i % 4) + ((menu->oldscreenpos.w - 2 * menuimages[0]->w) - (8 * GFX_MENUPLAYERIMGSIZE_X)) / 2; rect.y = (GFX_MENUPLAYERIMGSIZE_X * 2) * (i / 4) + PLAYERMENU_GFXSEL_Y; srcrect.x = 0; srcrect.y = 0; rect.x += menu->oldscreenpos.x + menuimages[0]->w; rect.y += menu->oldscreenpos.y + menuimages[0]->h; gfx_blit (gfx.players[i].menu_image, &srcrect, gfx.screen, &rect, 10002); /* draw the select border */ if (i == selgfx) { srcrect.x = 0; srcrect.y = 0; srcrect.h = rect.h = GFX_IMGSIZE; srcrect.w = rect.w = GFX_IMGSIZE; rect.x = GFX_IMGSIZE * (i % 4) + ((menu->oldscreenpos.w - 2 * menuimages[0]->w) -(4 * GFX_IMGSIZE)) / 2; rect.y = GFX_IMGSIZE * (i / 4) + PLAYERMENU_GFXSEL_Y; rect.x += (gfx.players[i].menu_image->w - gfx.menuselect.image->w) / 2; // center the playergfx rect.x += menu->oldscreenpos.x + menuimages[0]->w; rect.y += menu->oldscreenpos.y + menuimages[0]->h; gfx_blit (gfx.menuselect.image, &srcrect, gfx.screen, &rect, 10001); } } } } /* * draw a small menu where the player has to select his gfx */ int playermenu_selgfx (int pl_nr) { _menu *menu; int selgfx, eventstate; SDL_Event event; Uint8 *keys; int done = 0; if (pl_nr < 0 || pl_nr >= MAX_PLAYERS) return -1; selgfx = players[pl_nr].gfx_nr; if (selgfx < 0) selgfx = 1; playermenu_selgfx_drawplayer (-1, NULL); player_set_gfx (&players[pl_nr], -1); menu = menu_new ("Player Selection", 400, 270); menu_create_text (menu, "playergfxsel", -1, 50, 40, 5, COLOR_yellow, "%s, please select your Player and press ENTER/RETURN or press ESCAPE for no player (that means you will only watch the next game).", players[pl_nr].name); menu->looprunning = 1; menu_draw (menu); while (!done && bman.state != GS_quit) { /* do the network loop if we have to */ if (bman.sock > 0) { network_loop (); if (bman.notifygamemaster) ogc_loop (); } eventstate = SDL_PollEvent (&event); if (eventstate) { switch (event.type) { case (SDL_QUIT): bman.state = GS_quit; done = 1; menu_delete (menu); return -1; break; case (SDL_KEYDOWN): /* * go to the next gfx or the preview one */ if (event.key.keysym.sym == SDLK_TAB) { keys = SDL_GetKeyState (NULL); if (keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT]) { if ((--selgfx) < 0) selgfx = gfx.player_gfx_count-1; } else { if ((++selgfx) >= gfx.player_gfx_count) selgfx = 0; } break; } /* * cursor keys for gfx selection */ if (event.key.keysym.sym == SDLK_UP && selgfx >= 4) selgfx -= 4; if (event.key.keysym.sym == SDLK_DOWN && selgfx < MAX_PLAYERS-4) selgfx += 4; if (event.key.keysym.sym == SDLK_RIGHT && selgfx < MAX_PLAYERS-1) selgfx++; if (event.key.keysym.sym == SDLK_LEFT && selgfx > 0) selgfx--; /* * do not select any gfx */ else if (event.key.keysym.sym == SDLK_ESCAPE) { selgfx = -1; done = 2; break; } /* * select the current gfx if aviable */ else if (event.key.keysym.sym == SDLK_RETURN || event.key.keysym.sym == SDLK_LCTRL || event.key.keysym.sym == SDLK_RCTRL || event.key.keysym.sym == keyb_gamekeys.keycode[BCPK_drop] || event.key.keysym.sym == keyb_gamekeys.keycode[BCPK_special] || event.key.keysym.sym == keyb_gamekeys.keycode[BCPK_max + BCPK_drop] || event.key.keysym.sym == keyb_gamekeys.keycode[BCPK_max + BCPK_special]) { done = 1; break; } } } playermenu_selgfx_drawplayer (selgfx, menu); gfx_blitdraw (); s_calctimesync (); }; menu_delete (menu); player_set_gfx (&players[pl_nr], selgfx); if (done == 2) return -1; return 0; }; /* +----------------------------------------------------+ | List of Players Details | | |6) | Name: Playername Team | | | | IP: 10.10.10.10 | | | | Port: 11000 | | | | Flags: Firewall, Second Player | | | | | | +-------------+ | | [1) Teammenu ] | | [2) Add AI ] [3)Add 2. Player] | | [4)Kick Player] [5) Close ] | +----------------------------------------------------+ */ void playermenu () { _menu *menu; _menuitem *btn_SecondPlayer; _menuitem *list_PlayerList; _menuitem *detail_Name; _menuitem *detail_Addr; _menuitem *detail_Flags; _charlist playerlist[MAX_PLAYERS + 1]; _charlist *playerlist_sel = &playerlist[0]; int i, done = 0, eventstate, pl_nr, sel_pl_nr; SDL_Event event; /* delete the playerlist */ playerlist[0].text[0] = 0; playerlist[0].next = NULL; /* create the window */ menu = menu_new ("Playermenu", 400, 350); menu_create_label (menu, "Players", 20, 50, 0, COLOR_brown); list_PlayerList = menu_create_list (menu, "playerlist", 15, 70, 170, 160, playerlist, &playerlist_sel, 6); menu_create_label (menu, "Details", 240, 50, 0, COLOR_brown); detail_Name = menu_create_label (menu, "Name", 220, 100, 0, COLOR_yellow); detail_Addr = menu_create_label (menu, "10.10.10.1:6666", 220, 120, 0, COLOR_yellow); detail_Flags = menu_create_label (menu, "firewall", 220, 140, 0, COLOR_yellow); if (GT_SP || GT_MP_PTPM) menu_create_button (menu, "Add AI Player", 20, 280, 150, 2); btn_SecondPlayer = menu_create_button (menu, "2 Player", 250, 280, 150, 3); if (IS_LPLAYER2) sprintf (btn_SecondPlayer->label, "Del 2 Player"); else sprintf (btn_SecondPlayer->label,"Add 2 Player"); if (GT_SP || GT_MP_PTPM) menu_create_button (menu, "Kick Player", 20, 315, 150, 4); menu_create_button (menu, "Close", 250, 315, 150, 5); if (bman.gametype == GT_team && (GT_SP || GT_MP_PTPM)) menu_create_button (menu, "Teammenu", -1, 245, 150, 1); /* prepare everything for the menu_loop */ menu_focus_id (menu, 5); menu->looprunning = 1; menu_draw (menu); /* the menu loop */ do { detail_Name->label[0] = 0; detail_Addr->label[0] = 0; detail_Flags->label[0] = 0; sel_pl_nr = -1; for (i = 0, pl_nr = 0; pl_nr < MAX_PLAYERS; pl_nr++) { if (PS_IS_used(players[pl_nr].state)) { if (i > 0) playerlist[i-1].next = &playerlist[i]; playerlist[i].next = NULL; strncpy (playerlist[i].text, players[pl_nr].name, LEN_PLAYERNAME); /* get detail information */ if (i == (playerlist_sel - &playerlist[0])) { if (players[pl_nr].team_nr >= 0 && players[pl_nr].team_nr < MAX_TEAMS) sprintf (detail_Name->label, "%s(%s)", players[pl_nr].name, teams[players[pl_nr].team_nr].name); else sprintf (detail_Name->label, "%s", players[pl_nr].name); sprintf (detail_Addr->label, "%-32s:%s",players[pl_nr].net.addr.host, players[pl_nr].net.addr.port); sprintf (detail_Flags->label, "FIX ME"); playermenu_getflags (detail_Flags->label, &players[pl_nr]); sel_pl_nr = pl_nr; } i++; } } list_PlayerList->changed = 1; detail_Name->changed = 1; detail_Addr->changed = 1; detail_Flags->changed = 1; eventstate = SDL_PollEvent (&event); if (bman.sock != -1) network_loop (); menu_draw (menu); gfx_blitdraw (); done = menu_event_loop (menu, &event, eventstate); /* * check if one of the buttons was pressed */ if (done == 1 && menu->focus->id == btn_SecondPlayer->id) { /* second local player want to join */ if (IS_LPLAYER2) player_delete (bman.p2_nr); else player2_join (); if (IS_LPLAYER2) sprintf (btn_SecondPlayer->label, "Del 2 Player"); else sprintf (btn_SecondPlayer->label,"Add 2 Player"); btn_SecondPlayer->changed = 1; } if (done == 1 && menu->focus->id == 2) { /* create ai player */ single_create_ai (1); done = 0; } if (done == 1 && menu->focus->id == 1) { /* Teammenu */ teammenu (); done = 0; } if (done == 1 && menu->focus->id == 4) { /* kick player */ if (sel_pl_nr >= 0 && sel_pl_nr < MAX_PLAYERS && sel_pl_nr != bman.p_servnr) player_delete (sel_pl_nr); else menu_displaymessage ("No", "You can't kick yourself from the game.\n"); done = 0; } s_calctimesync (); } while ((done == 0 || menu->focus->id != 5) && done != -1); menu_delete (menu); }; /* * put all flags into the givin text like: * NET_FW, NET_2P, AI... */ void playermenu_getflags (char *text, _player *player) { text[0] = 0; if (player->net.flags & NETF_firewall) sprintf (text, "%sNET_FW ", text); if (player->net.flags & NETF_local2) sprintf (text, "%sNET_2P ", text); if (player->state & PSF_net) sprintf (text, "%sPSF_NET ", text); if (player->state & PSF_ai) sprintf (text, "%sPSF_AI ", text); }; /* * teammenu: Teamplay menuselection * Show and edit all teams and the players. */ struct __teammenu { struct { _charlist names[MAX_PLAYERS]; _charlist *select; _menuitem *item; _menuitem *label; } teamp, freep; _menuitem *teamlist; _charlist teamnames[MAX_TEAMS]; _charlist *teamsel; }; static void teammenu_update (_menu *menu, struct __teammenu *tm); static int inline teammenu_get_selteam (_menu *menu, struct __teammenu *tm); static void teammenu_set_selteam (_menu *menu, struct __teammenu *tm, int teamnr); static void teammenu_player2team (_menu *menu, struct __teammenu *tm); static void teammenu_team2player (_menu *menu, struct __teammenu *tm); void teammenu () { _menu *menu; struct __teammenu tm; int done, eventstate, menu_id = 0, last_id = 0, last_selteam = -1; SDL_Event event; menu = menu_new ("Team Details", 400, 350); menu_create_text (menu, "help1", 10, 70, (250/font[0].size.x), 5, COLOR_gray, "Move the players from one team into the other by selecting them with ENTER."); menu_create_button (menu, "Close", -1, 325, 150, 0); /* reset all teamlist data and create element */ tm.teamsel = NULL; tm.teamnames[0].text[0] = 0; tm.teamnames[0].next = NULL; tm.teamlist = menu_create_list (menu, "Teamlist", 250, 70, 150, 80, tm.teamnames, &tm.teamsel, ++menu_id); /* reset all player data and create element*/ tm.teamp.names[0].text[0] = 0; tm.teamp.names[0].next = NULL; tm.teamp.select = &tm.teamp.names[0];; tm.freep.names[0].text[0] = 0; tm.freep.names[0].next = NULL; tm.freep.select = &tm.freep.names[0];; tm.freep.label = menu_create_label (menu, "Free Players", 40, 160, 0, COLOR_yellow); tm.freep.item = menu_create_list (menu, "freeplayer", 30, 180, 150, 120, tm.freep.names, &tm.freep.select, ++menu_id); tm.teamp.label = menu_create_label (menu, teams[0].name, 250, 160, 0, COLOR_yellow); tm.teamp.item = menu_create_list (menu, "teamplayer", 240, 180, 150, 120, tm.teamp.names, &tm.teamp.select, ++menu_id); /* prepare everything for the menu_loop */ menu_focus_id (menu, 1); menu->looprunning = 1; menu_draw (menu); teammenu_set_selteam (menu, &tm, 0); teammenu_update (menu, &tm); /* the menu loop */ do { gfx_blitdraw (); eventstate = SDL_PollEvent (&event); if (bman.sock != -1) network_loop (); menu_draw (menu); done = menu_event_loop (menu, &event, eventstate); /* * check if one of the buttons was pressed */ if (last_id != menu->focus->id || last_selteam != teammenu_get_selteam(menu, &tm)) { teammenu_update (menu, &tm); } if (done == 1 && menu->focus->id == tm.freep.item->id) { // freeplayer selected teammenu_player2team (menu, &tm); teammenu_update (menu, &tm); done = 0; } if (done == 1 && menu->focus->id == tm.teamp.item->id) { // teamplayer selected teammenu_team2player (menu, &tm); teammenu_update (menu, &tm); done = 0; } if (done == 1 && menu->focus->id == tm.teamlist->id) { menu_focus_id (menu, tm.freep.item->id); teammenu_update (menu, &tm); done = 0; } s_calctimesync (); last_id = menu->focus->id; } while ((done == 0 || menu->focus->id != 0) && done != -1); menu_delete (menu); teammenu_ai_choosegfx (); } /* * add the current selected playxer to the free players */ static void teammenu_team2player (_menu *menu, struct __teammenu *tm) { int sel_team = teammenu_get_selteam (menu,tm); int sel_teampl = tm->teamp.select - tm->teamp.names; if (sel_team < 0 || sel_team >= MAX_TEAMS || sel_teampl < 0 || sel_teampl >= MAX_PLAYERS) return; if (teams[sel_team].players[sel_teampl] == NULL) return; teams[sel_team].players[sel_teampl]->team_nr = -1; team_update (); }; /* * add the current selected player to the current team */ static void teammenu_player2team (_menu *menu, struct __teammenu *tm) { int sel_player = tm->freep.select - tm->freep.names; int sel_team = teammenu_get_selteam (menu,tm); int pl; // d_printf ("teammenu_player2team: sel_player=%d, sel_team=%d\n", sel_player, sel_team); if (sel_team < 0 || sel_team >= MAX_TEAMS || sel_player < 0 || sel_player >= MAX_PLAYERS) return; /* get the player */ pl = 0; while (pl < MAX_PLAYERS && (sel_player > 0 || players[pl].team_nr != -1)) { if (players[pl].team_nr == -1) sel_player--; pl++; } // d_printf ("teammenu_player2team: sel_player=%d, sel_team=%d, pl=\n", sel_player, sel_team, pl); if (pl < MAX_PLAYERS && sel_player == 0 && players[pl].team_nr == -1) players[pl].team_nr = sel_team; team_update (); } /* * update all elements on the screen * clean the player lists for the team and free players */ static void teammenu_update (_menu *menu, struct __teammenu *tm) { int pl, cnt_team, cnt_free; // d_printf ("teammenu_update\n"); /* * teamnames */ tm->teamnames[0].text[0] = 0; tm->teamnames[0].next = NULL; for (pl = 0; pl < MAX_TEAMS; pl++) { if (pl > 0) tm->teamnames[pl-1].next = &tm->teamnames[pl]; tm->teamnames[pl].next = NULL; strncpy (tm->teamnames[pl].text, teams[pl].name, LEN_CHARENTRY); } strncpy (tm->teamp.label->label, tm->teamsel->text, MENU_TITLELEN); /* * playernames */ tm->freep.names[0].next = NULL; tm->freep.names[0].text[0] = 0; tm->teamp.names[0].next = NULL; tm->teamp.names[0].text[0] = 0; for (pl = 0, cnt_team = 0, cnt_free = 0; pl < MAX_PLAYERS; pl++) { if (PS_IS_used (players[pl].state) && (players[pl].team_nr == -1 || players[pl].team_nr == teammenu_get_selteam (menu, tm))) { _charlist *cl; int *cnt; /* select the right list with the right counter */ if (players[pl].team_nr == -1) { cl = tm->freep.names; cnt = &cnt_free; } else { cl = tm->teamp.names; cnt = &cnt_team; } /* set the data */ if (*cnt > 0) cl[(*cnt)-1].next = &cl[*cnt]; strncpy (cl[*cnt].text, players[pl].name, LEN_CHARENTRY); cl[*cnt].next = NULL; (*cnt)++; } } /* send update */ tm->freep.item->changed = 1; tm->freep.label->changed = 1; menu_draw_menuitem (tm->freep.item); menu_draw_menuitem (tm->freep.label); tm->teamp.item->changed = 1; tm->teamp.label->changed = 1; menu_draw_menuitem (tm->teamp.item); menu_draw_menuitem (tm->teamp.label); tm->teamlist->changed = 1; menu_draw_menuitem (tm->teamlist); } /* * get the current teamnumber */ static inline int teammenu_get_selteam (_menu *menu, struct __teammenu *tm) { return (tm->teamsel - tm->teamnames); }; /* * set the current teamnumber */ static void teammenu_set_selteam (_menu *menu, struct __teammenu *tm, int teamnr) { if (teamnr < 0 ) teamnr = 0; else if (teamnr >= MAX_TEAMS) teamnr = MAX_TEAMS-1; tm->teamsel = &tm->teamnames[teamnr]; tm->teamlist->changed = 1; menu_draw_menuitem (tm->teamlist); }; /* * the ai player will choose diffrent gfx for every * team another gfx, but not one which is selected by * human player. */ static void teammenu_ai_choosegfx () { struct _team_tmpdata_ { // int ai_player; // int hu_player; int ai_gfx; } teamdat[MAX_TEAMS]; int tm_nr; int pl_nr; int i, used; _player *pl; /* find a ai player gfx for every team */ for (i = 0, tm_nr = 0; (i < gfx.player_gfx_count && tm_nr < MAX_TEAMS); i++) { used = 0; for (pl_nr = 0; pl_nr < MAX_PLAYERS; pl_nr++) { if ((!PS_IS_aiplayer(players[pl_nr].state)) && (PS_IS_used (players[pl_nr].state)) && i == players[pl_nr].gfx_nr) used = 1; } if (!used && tm_nr < MAX_TEAMS) { teamdat[tm_nr].ai_gfx = i; tm_nr++; } } /* * give all ai players in the teams the right gfx */ for (tm_nr = 0; tm_nr < MAX_TEAMS; tm_nr++) for (pl_nr = 0; pl_nr < MAX_PLAYERS; pl_nr++) { pl = teams[tm_nr].players[pl_nr]; if (pl) { if (PS_IS_used(pl->state) && PS_IS_aiplayer(pl->state)) player_set_gfx (pl, teamdat[tm_nr].ai_gfx); } } };