1 /* -*- Mode: C++; c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil -*-
2 *
3 * Quadra, an action puzzle game
4 * Copyright (C) 1998-2000 Ludus Design
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "menu.h"
22
23 #include <stdlib.h>
24 #include "version.h"
25 #include "canvas.h"
26 #include "chat_text.h"
27 #include "color.h"
28 #include "cfgfile.h"
29 #include "crypt.h"
30 #include "dict.h"
31 #include "fonts.h"
32 #include "game.h"
33 #include "game_menu.h"
34 #include "global.h"
35 #include "highscores.h"
36 #include "http_request.h"
37 #include "image_png.h"
38 #include "input.h"
39 #include "inter.h"
40 #include "main.h"
41 #include "menu_demo_central.h"
42 #include "misc.h"
43 #include "multi_player.h"
44 #include "multi_provider.h"
45 #include "net.h"
46 #include "net_server.h"
47 #include "net_stuff.h"
48 #include "overmind.h"
49 #include "pane.h"
50 #include "qserv.h"
51 #include "quadra.h"
52 #include "random.h"
53 #include "recording.h"
54 #include "res_compress.h"
55 #include "sons.h"
56 #include "sprite.h"
57 #include "zone.h"
58 #include "config.h"
59
60 #ifdef UGS_DIRECTX
61 #include <shellapi.h>
62 #endif
63
64 using std::vector;
65
step()66 void Menu_do_nothing::step() {
67 if(quitting)
68 ret();
69 }
70
Menu_highscore(int hscore,int * playagain,bool show_playb)71 Menu_highscore::Menu_highscore(int hscore, int *playagain, bool show_playb) {
72 play_again = playagain;
73 show_playback = show_playb;
74 int i;
75 for(i=0; i<MAX_SCORE; i++) {
76 playdemo[i] = NULL;
77 playdemog[i] = NULL;
78 }
79
80 {
81 Res_doze res("hscore.png");
82 Png img(res);
83 bit = new Bitmap(img);
84 pal.load(img);
85 }
86 inter->set_font(new Font(*fonts.normal, pal, 255,255,255, 0, 20, 40));
87 font2 = new Font(*fonts.normal, pal, 255,255,0, 0,20,40);
88 courrier = new Font(*fonts.courrier, pal, 255,255,255, 0,20,40);
89 courrier2 = new Font(*fonts.courrier, pal, 255,255,0, 0,20,40);
90 (void)new Zone_bitmap(inter, bit, 0, 0, true);
91
92 const char *pic1, *pic2, *pic1s, *pic2s;
93 pic1 = "hscore1.png";
94 pic2 = "hscore2.png";
95 pic1s = "hscore1s.png";
96 pic2s = "hscore2s.png";
97 b_again = b_quit = NULL;
98 if(show_playback) {
99 {
100 Res_doze res1(pic2);
101 Png png1(res1);
102 Res_doze res2(pic2s);
103 Png png2(res2);
104 b_quit = new Zone_menu(inter, png1, 485, 410, png2);
105 }
106 if(play_again) {
107 Res_doze res1(pic1);
108 Png png1(res1);
109 Res_doze res2(pic1s);
110 Png png2(res2);
111 b_again = new Zone_menu(inter, png1, 38, 410, png2);
112 }
113 } else {
114 time_demo = 6000;
115 }
116
117 int x;
118 if(show_playback)
119 x = 60;
120 else
121 x = 100;
122 int y = 50;
123 (void)new Zone_text(inter, "Hero", x, y);
124 (void)new Zone_text(inter, "Score", x+190, y);
125 (void)new Zone_text(inter, "Lines", x+290, y);
126 (void)new Zone_text(inter, "Level", x+390, y);
127 y += 20;
128 Highscores::load();
129 refresh_global(y); //int&
130
131 if(show_playback && net->active) {
132 sync = new Zone_text_button2(inter, bit, font2, "�2 Update", x+460, 186);
133 status = new Zone_text_field(inter, "", 30, 186, 470);
134 status->set_val("Click on �2 Update to update worldwide highscores.");
135 } else {
136 sync = NULL;
137 status = NULL;
138 }
139 sync_request = NULL;
140
141 y = 256;
142 (void)new Zone_text(inter, "Hero", x, y);
143 (void)new Zone_text(inter, "Score", x+190, y);
144 (void)new Zone_text(inter, "Lines", x+290, y);
145 (void)new Zone_text(inter, "Level", x+390, y);
146 y += 20;
147 for(i=0; i<Highscores::numLocal; i++) {
148 if(hscore == i) {
149 (void)new Zone_text(font2, inter, Highscores::bestlocal[i].name, x, y);
150 (void)new Zone_text_numeric(courrier2, inter, &Highscores::bestlocal[i].score, x+160, y, 80);
151 (void)new Zone_text_numeric(courrier2, inter, &Highscores::bestlocal[i].lines, x+260, y, 80);
152 (void)new Zone_text_numeric(courrier2, inter, &Highscores::bestlocal[i].level, x+360, y, 80);
153 sons.levelup->play(0, 0, 11000);
154 } else {
155 (void)new Zone_text(inter, Highscores::bestlocal[i].name, x, y);
156 (void)new Zone_text_numeric(courrier, inter, &Highscores::bestlocal[i].score, x+160, y, 80);
157 (void)new Zone_text_numeric(courrier, inter, &Highscores::bestlocal[i].lines, x+260, y, 80);
158 (void)new Zone_text_numeric(courrier, inter, &Highscores::bestlocal[i].level, x+360, y, 80);
159 }
160 if(show_playback)
161 playdemo[i] = new Zone_text_button2(inter, bit, font2, "Playback", x+460, y);
162 y += 21;
163 }
164
165 playlast = NULL;
166 if(show_playback) {
167 snprintf(st, sizeof(st) - 1, "%s/last.qrec", quadradir);
168 Res_dos *res = new Res_dos(st, RES_TRY);
169 if(res->exist) {
170 y += 6;
171 (void)new Zone_text(inter, "Replay last single-player game:", x, y);
172 playlast = new Zone_text_button2(inter, bit, font2, "Playback", x+460, y);
173 }
174 delete res;
175 }
176 }
177
~Menu_highscore()178 Menu_highscore::~Menu_highscore() {
179 delete font2;
180 delete courrier;
181 delete courrier2;
182 if(sync_request)
183 delete sync_request;
184 }
185
refresh_global(int & y)186 void Menu_highscore::refresh_global(int& y) {
187 int x;
188 if(show_playback)
189 x = 60;
190 else
191 x = 100;
192 list.deleteall();
193 for(int i=0; i<Highscores::numGlobal; i++) {
194 playdemog[i] = NULL;
195 list.zones.push_back(new Zone_text(inter, Highscores::bestglobal[i].name, x, y));
196 list.zones.push_back(new Zone_text_numeric(courrier, inter, &Highscores::bestglobal[i].score, x+160, y, 80));
197 list.zones.push_back(new Zone_text_numeric(courrier, inter, &Highscores::bestglobal[i].lines, x+260, y, 80));
198 list.zones.push_back(new Zone_text_numeric(courrier, inter, &Highscores::bestglobal[i].level, x+360, y, 80));
199 if(show_playback) {
200 playdemog[i] = new Zone_text_button2(inter, bit, font2, "Playback", x+460, y);
201 list.zones.push_back(playdemog[i]);
202 }
203 y += 21;
204 }
205 video->need_paint = 2;
206 }
207
208 // Very specifically for URL-encoding of base64 buffers, mangles its source in
209 // the process.
fast_plusonly_url_encode(Textbuf & out,Textbuf & in)210 static void fast_plusonly_url_encode(Textbuf& out, Textbuf& in) {
211 char* ptr = in.get();
212 out.reserve(in.len());
213 while (*ptr != '\0') {
214 char* index = strchr(ptr, '+');
215 if (index) {
216 *index = '\0';
217 out.appendraw(ptr);
218 out.appendraw("%2B");
219 ptr = index + 1;
220 } else {
221 out.appendraw(ptr);
222 break;
223 }
224 }
225 }
226
start_sync()227 void Menu_highscore::start_sync() {
228 sync->set_text("�2 Cancel");
229 video->need_paint = 2;
230 Res_dos *demofile;
231 sync_request = new Qserv();
232 if(Highscores::numLocal>=1) {
233 char st[1024];
234 Highscores::getFilename(st, 0, sizeof(st));
235 demofile=new Res_dos(st, RES_TRY);
236 if(!demofile->exist) {
237 delete demofile;
238 demofile=NULL;
239 }
240 }
241 else
242 demofile=NULL;
243 if(demofile) {
244 Playback *demo=Highscores::bestlocal[0].demo;
245 sync_request->add_data("postdemo\n");
246 sync_request->add_data("name %s\n", demo->player);
247 sync_request->add_data("score %i\n", demo->score);
248 sync_request->add_data("lines %i\n", demo->lines);
249 sync_request->add_data("level %i\n", demo->level);
250 //Add the recording
251 sync_request->add_data("rec ");
252 Textbuf buf;
253 msgbox("Menu_highscore::start_sync: original size=%i\n", demofile->size());
254 Http_request::base64encode((const Byte*)demofile->buf(), buf, demofile->size());
255 msgbox("Menu_highscore::start_sync: encoded size=%i\n", strlen(buf.get()));
256 delete demofile;
257 demofile=NULL;
258 Textbuf safebuf;
259 fast_plusonly_url_encode(safebuf, buf);
260 sync_request->add_data_large(safebuf);
261 sync_request->add_data("\n");
262 }
263 else
264 sync_request->add_data("gethighscores\n");
265
266 //Expecting MAX_SCORE global highscores in answer
267 sync_request->add_data("num %i\n", MAX_SCORE);
268 sync_request->send();
269 status->set_val("Connecting. Please wait...");
270 }
271
step_sync()272 void Menu_highscore::step_sync() {
273 bool done = sync_request->done();
274 if(!done) {
275 if(sync_request->isconnected()) {
276 sprintf(st, "Connected. Transfer in progress. %i bytes.", sync_request->getnbrecv());
277 status->set_val(st);
278 }
279 return;
280 }
281
282 const char *server_status = sync_request->get_status();
283 if(!server_status || (strcmp(server_status, "Ok") && strcmp(server_status, "Error"))) {
284 stop_sync();
285 status->set_val("No Quadra game server found.");
286 return;
287 }
288 Dict *reply=sync_request->get_reply();
289 if(_debug) {
290 reply->dump();
291 }
292 if(strcmp(server_status, "Ok")) {
293 // qserv returned an "Error" status, display the supplied message
294 const char *msg = reply->find("message");
295 if(!msg)
296 msg = "???";
297 sprintf(st, "Error: the server returned [%s].", msg);
298 status->set_val(st);
299 stop_sync();
300 return;
301 }
302 int i;
303 for(i=0; i<MAX_SCORE; i++) {
304 char dir[16];
305 sprintf(dir, "high%03i", i);
306 Dict *d=reply->find_sub(dir);
307 if(d) {
308 const char* rec=d->find("rec");
309 if(rec) {
310 char fn[1024];
311 Highscores::getGlobalFilename(fn, i, sizeof(fn));
312 Res_dos res(fn, RES_CREATE);
313 if(res.exist) {
314 Buf out;
315 msgbox("Menu_highscore::step_sync: encoded size=%i\n", strlen(rec));
316 Http_request::base64decode(rec, out, strlen(rec));
317 msgbox("Menu_highscore::step_sync: decoded size=%i\n", out.size());
318 res.write(out.get(), out.size());
319 }
320 }
321 }
322 }
323 status->set_val("Transfer completed successfully.");
324 Highscores::freemem();
325 Highscores::load();
326 int y=70;
327 refresh_global(y);
328 stop_sync();
329 }
330
stop_sync()331 void Menu_highscore::stop_sync() {
332 sync->set_text("�2 Update");
333 video->need_paint = 2;
334 delete sync_request;
335 sync_request=NULL;
336 }
337
step()338 void Menu_highscore::step() {
339 Menu_standard::step();
340 if(show_playback) {
341 if(sync_request)
342 step_sync();
343 if(!result)
344 return;
345
346 if(!sync_request) {
347 if(play_again) {
348 if(result == b_again) {
349 *play_again = 1;
350 quit = true;
351 }
352 }
353 if(result == b_quit) {
354 quit = true;
355 }
356 if(sync && result == sync) {
357 start_sync();
358 }
359 for(int i=0; i<MAX_SCORE; i++) {
360 if(result == playdemo[i]) {
361 Highscores::getFilename(st, i, sizeof(st));
362 play_demo(st);
363 }
364 if(result == playdemog[i]) {
365 Highscores::getGlobalFilename(st, i, sizeof(st));
366 play_demo(st);
367 }
368 }
369 if(result == playlast) {
370 snprintf(st, sizeof(st) - 1, "%s/last.qrec", quadradir);
371 play_demo(st);
372 }
373 } else {
374 if(result == sync) {
375 stop_sync();
376 status->set_val("Transfer interrupted by user.");
377 }
378 }
379 } else { // demo mode of the main menu
380 time_demo--;
381 if(result || input->last_key.sym != SDLK_UNKNOWN || time_demo == 0)
382 quit = true;
383 }
384 }
385
play_demo(const char * st)386 void Menu_highscore::play_demo(const char *st) {
387 Res_compress *res = new Res_compress(st, RES_TRY);
388 if(res->exist) {
389 call(new Fade_in(pal));
390 call(new Call_setfont(pal, new Demo_multi_player(res)));
391 call(new Fade_out(pal));
392 // the 'delete res' is done by ~Demo_multi_player
393 } else {
394 msgbox("Menu_highscore::step: Unable to open demo '%s'\n", st);
395 delete res;
396 }
397 }
398
399 Net_starter* net_starter=NULL;
400
Net_starter()401 Net_starter::Net_starter() {
402 if(net)
403 fatal_msgbox("Net already started!\n");
404 time_control = TIME_FREEZE;
405 net=new Net(new Quadra_param());
406 if(!net->active) {
407 msgbox("Net_starter::Net_starter: Can't initialise network.");
408 const char *temp = net->last_error;
409 if(temp)
410 msgbox("Error [%s]\n", temp);
411 else
412 msgbox("No error reported.\n");
413 net_exec = NULL;
414 } else {
415 net_exec = new Executor(true);
416 net_exec->add(new Net_module());
417 overmind.start(net_exec);
418 if(chat_text)
419 chat_text->addwatch();
420 }
421 }
422
~Net_starter()423 Net_starter::~Net_starter() {
424 if(net_exec) {
425 overmind.stop(net_exec);
426 if(chat_text)
427 chat_text->removewatch();
428 }
429 delete net;
430 net=NULL;
431 }
432
Menu_multi_join(Bitmap * bit,Font * font,Font * font2,const Palette & p,bool plocal)433 Menu_multi_join::Menu_multi_join(Bitmap *bit, Font *font, Font *font2, const Palette& p, bool plocal) {
434 pal = p;
435 bit_ = bit;
436 font2_ = font2;
437 local_net = plocal;
438 inter->set_font(font, false);
439 (void)new Zone_bitmap(inter, bit, 0, 0);
440 (void)new Zone_text(inter, "\"To create or to join, that is the "
441 "question\" - Rem, 1999", 20);
442 b_create = new Zone_text_button2(inter, bit, font2, "�2 Create a new game",
443 50);
444 b_refresh = b_refresh_internet = NULL;
445 if(local_net)
446 b_refresh = new Zone_text_button2(inter, bit, font2,
447 "�2 Refresh local games", 80);
448 else
449 b_refresh_internet = new Zone_text_button2(inter, bit, font2,
450 "�2 Refresh Internet games",
451 80);
452 (void)new Zone_text(fteam[7], inter, "Server list:", 10, 120);
453 selected_game = -1;
454 list_game = new Zone_listbox2(inter, bit, font2, &selected_game, 2, 140, 220, 240);
455 int y = 120;
456 (void)new Zone_text(fteam[7], inter, "Type:", 235, y);
457 z_game_type = new Zone_text_field(inter, "", 480, y, 155); y += 22;
458 (void)new Zone_text(fteam[7], inter, "Level up:", 235, y);
459 z_game_speed = new Zone_text_field(inter, "", 480, y, 155); y += 22;
460 (void)new Zone_text(fteam[7], inter, "Start game at level:", 235, y);
461 z_game_level = new Zone_text_field(inter, "", 480, y, 24); y += 22;
462 (void)new Zone_text(fteam[7], inter, "Smallest offensive line combo:",
463 235, y);
464 z_game_minimum = new Zone_text_field(inter, "", 480, y, 155); y += 22;
465 (void)new Zone_text(fteam[7], inter, "The game ends when:", 235, y);
466 z_game_end = new Zone_text_field(inter, "", 480, y, 155); y += 22;
467 (void)new Zone_text(fteam[7], inter, "Status:", 235, y);
468 z_game_status = new Zone_text_field(inter, "", 480, y, 155); y += 22;
469 list_player = new Zone_listbox2(inter, bit, font2, NULL, 235, y, 390, 136);
470 b_join = new Zone_text_button2(inter, bit, font2, "�2 Join selected game",
471 395);
472
473 (void)new Zone_text(fteam[7], inter, "Or enter the IP address of the server:",
474 30, 420);
475 address[0] = 0;
476 (void)new Zone_input_address(this, pal, inter, address, 254, 340, 420, 240);
477 b_info = new Zone_text_button2(inter, bit, font2, "�2 Check IP info",
478 35, 450);
479 b_book = NULL;
480 if(!local_net)
481 b_book = new Zone_text_button2(inter, bit, font2, "�2 Address book", 345, 450);
482 cancel = new Zone_text_button2(inter, bit, font2, "Back �0", 560, 450);
483 }
484
~Menu_multi_join()485 Menu_multi_join::~Menu_multi_join() {
486 removewatch();
487 }
488
addwatch()489 void Menu_multi_join::addwatch() {
490 net->addwatch(P_GAMEINFO, this);
491 }
492
removewatch()493 void Menu_multi_join::removewatch() {
494 net->removewatch(P_GAMEINFO, this);
495 }
496
init()497 void Menu_multi_join::init() {
498 Menu::init();
499 if(!net->active) {
500 exec(new Menu_net_problem(net->last_error,
501 "You will not be able to play on the Internet.",
502 bit_, inter->font));
503 } else {
504 net->close_all_udp();
505 net->init_all_udp();
506 refresh();
507 }
508 }
509
510 class Listgame: public Listable {
511 public:
512 Packet_gameinfo *p;
Listgame(const char * s,Packet_gameinfo * pp)513 Listgame(const char *s, Packet_gameinfo *pp): Listable(s) {
514 p = pp;
515 }
~Listgame()516 virtual ~Listgame() {
517 delete p;
518 }
is_equal(Listable * source)519 virtual bool is_equal(Listable *source) {
520 Listgame *other=(Listgame *) source;
521 return p->from_addr == other->p->from_addr &&
522 p->port == other->p->port;
523 }
524 };
525
step()526 void Menu_multi_join::step() {
527 Menu::step();
528 if(input->last_key.sym == SDLK_ESCAPE || quitting) {
529 ret();
530 return;
531 }
532
533 if(!result)
534 return;
535
536 if(result==b_create) {
537 removewatch();
538 if(address[0] == 0)
539 refresh();
540 call(new Create_game(bit_, inter->font, font2_, pal, true, local_net));
541 }
542 if(result==b_refresh || result==b_refresh_internet) {
543 address[0] = 0; // ignore the IP address written in the box
544 refresh();
545 }
546 if(result==b_info) {
547 call(new Menu_multi_checkip(bit_, inter->font, font2_, pal));
548 }
549 if(result==b_book) {
550 call(new Menu_multi_book(bit_, inter->font, font2_, pal, NULL));
551 }
552 Listgame *lg = (Listgame *) list_game->get_selected();
553 if(lg && list_game->in_listbox(result))
554 refresh_player();
555 if(lg && (list_game->in_listbox(inter->double_clicked) || result==b_join)) {
556 Packet_gameinfo *p = lg->p;
557 if(p->version==20 || p->version==22 || p->version==23 || p->version==Config::net_version) {
558 if(address[0] == 0)
559 refresh();
560 join_game(p->name, p->from_addr, p->port);
561 }
562 }
563 if(result == cancel) {
564 ret();
565 return;
566 }
567 }
568
join_game(char * nam,Dword adr,int port)569 void Menu_multi_join::join_game(char *nam, Dword adr, int port) {
570 removewatch();
571 call(new Join_game(bit_, inter->font, font2_, pal, nam, adr, port, false));
572 }
573
refresh()574 void Menu_multi_join::refresh() {
575 call(new Menu_multi_refresh(this));
576 }
577
clear_game_info()578 void Menu_multi_join::clear_game_info() {
579 list_player->clear();
580 z_game_type->set_val("");
581 z_game_speed->set_val("");
582 z_game_level->set_val("");
583 z_game_minimum->set_val("");
584 z_game_end->set_val("");
585 z_game_status->set_val("");
586 }
587
refresh_player()588 void Menu_multi_join::refresh_player() {
589 clear_game_info();
590 Listgame *lg = (Listgame *) list_game->get_selected();
591 Packet_gameinfo *p = lg->p;
592
593 vector<Net_player*>::const_iterator it;
594 for (it = p->players.begin(); it != p->players.end(); ++it) {
595 char name[256];
596 strcpy(name, (*it)->name);
597 if((*it)->idle==3)
598 strcat(name, " *");
599 list_player->add_item(new Listable(name, fteam[(*it)->team]));
600 }
601
602 if(p->version >= 20) {
603 const char *gtype = "Free for all";
604 if(p->survivor)
605 gtype = "Survivor";
606 if(p->normal_attack.type == ATTACK_NONE
607 && p->clean_attack.type == ATTACK_NONE)
608 gtype = "Peace";
609 if(p->normal_attack.type == ATTACK_BLIND
610 || p->normal_attack.type == ATTACK_FULLBLIND)
611 gtype = "Blind";
612 if(p->hot_potato)
613 gtype = "Hot potato";
614 z_game_type->set_val(gtype);
615 if(!p->nolevel_up)
616 z_game_speed->set_val("At 15 lines");
617 else
618 z_game_speed->set_val("Disabled");
619 game_level_start = (int) p->level_start;
620 z_game_level->set_val(&game_level_start);
621 if(p->combo_min == 1)
622 z_game_minimum->set_val("Single");
623 else if(p->combo_min == 2)
624 z_game_minimum->set_val("Double");
625 else if(p->combo_min == 3)
626 z_game_minimum->set_val("Triple");
627 else if(p->combo_min == 4)
628 z_game_minimum->set_val("Quad");
629 else {
630 char stbuf[16];
631 snprintf(stbuf, sizeof(stbuf), "%i-lines", p->combo_min);
632 z_game_minimum->set_val(stbuf);
633 }
634 switch(p->game_end) {
635 case 0: z_game_end->set_val("Never"); break;
636 case 1:
637 sprintf(game_end_text, "%i %s", p->game_end_value, "frags.");
638 z_game_end->set_val(game_end_text);
639 break;
640 case 2:
641 sprintf(game_end_text, "%i %s", p->game_end_value / 6000, "minutes.");
642 z_game_end->set_val(game_end_text);
643 break;
644 case 3:
645 sprintf(game_end_text, "%i %s", p->game_end_value, "points.");
646 z_game_end->set_val(game_end_text);
647 break;
648 case 4:
649 sprintf(game_end_text, "%i %s", p->game_end_value, "lines.");
650 z_game_end->set_val(game_end_text);
651 break;
652 }
653 if(p->terminated) {
654 z_game_status->set_val("Terminated");
655 } else {
656 if(p->delay_start)
657 z_game_status->set_val("Not yet started");
658 else
659 z_game_status->set_val("Playing");
660 }
661 }
662
663 if(p->version < 20/*Config::net_version*/) {
664 z_game_type->set_val("* older version *");
665 }
666 if(p->version > Config::net_version) {
667 z_game_type->set_val("* newer version *");
668 }
669 }
670
net_call(Packet * p2)671 void Menu_multi_join::net_call(Packet *p2) {
672 Packet_gameinfo *p=(Packet_gameinfo *)p2;
673 // char ad[256];
674 // Net::stringaddress(ad, p->from_addr);
675
676 if(p->name[0])
677 sprintf(st, "%s", p->name);
678 else
679 sprintf(st, "[No name]");
680 Listgame *lg = new Listgame(st, p); // the packet 'p' will be deleted by ~Listgame
681
682 int deja = list_game->search(lg);
683 if(deja != -1) {
684 list_game->replace_item(deja, lg);
685 if(selected_game != -1)
686 if(list_game->get_selected() == lg)
687 refresh_player();
688 } else {
689 list_game->add_item(lg);
690 }
691 }
692
lost_focus(int cancel)693 void Zone_input_address::lost_focus(int cancel) {
694 Zone_text_input::lost_focus(cancel);
695 if(!cancel && val[0] != 0) {
696 parent->refresh();
697 }
698 }
699
Menu_multi_refresh(Menu_multi_join * p)700 Menu_multi_refresh::Menu_multi_refresh(Menu_multi_join *p): Menu(p->inter) {
701 parent = p;
702 }
703
init()704 void Menu_multi_refresh::init() {
705 Menu::init();
706 parent->list_game->clear();
707 parent->clear_game_info();
708
709 if(parent->address[0] != 0) {
710 resolve();
711 return;
712 }
713 if(parent->local_net)
714 find_local_games();
715 else
716 find_internet_games();
717 }
718
find_local_games()719 void Menu_multi_refresh::find_local_games() {
720 Packet_findgame p;
721 Dword to;
722 parent->addwatch();
723 to = INADDR_BROADCAST;
724 net->sendudp(to, &p);
725 const char *error = net->failed();
726 if(error) {
727 call(new Menu_net_problem(error, "You can enter the TCP/IP address of "
728 "the server instead.", parent->bit_,
729 inter->font));
730 }
731 ret();
732 }
733
resolve()734 void Menu_multi_refresh::resolve() {
735 Dword to = net->getaddress(parent->address);
736 if(to > 0) {
737 ret();
738 parent->join_game(NULL, to, net->port_resolve);
739 } else {
740 cancel = NULL;
741 call(new Wait_time(50)); // waits 1/2 second (in case the hosts resolves itself very quickly)
742 }
743 }
744
find_internet_games()745 void Menu_multi_refresh::find_internet_games() {
746 exec(new Menu_multi_internet(parent));
747 }
748
step()749 void Menu_multi_refresh::step() {
750 Menu::step();
751 if(!cancel) {
752 (void)new Zone_bitmap(inter, parent->bit_, 0, 0);
753 (void)new Zone_text(fteam[7], inter, "Looking for server name on "
754 "Internet. This can take several minutes...", 130);
755 cancel = new Zone_text_button2(inter, parent->bit_, parent->font2_,
756 "�2 Cancel", 190);
757 }
758 if(net->name_resolve != (unsigned int)-1) {
759 Dword name_temp = net->name_resolve;
760 net->name_resolve = (Dword)-1;
761 if(name_temp == 0) {
762 (void)new Zone_text(fteam[7], inter, "Unable to locate host. Please verify and try again.", 220);
763 } else {
764 int port = net->port_resolve;
765 if(!port)
766 port = config.info.port_number; // default value
767 parent->join_game(NULL, name_temp, port);
768 ret();
769 return;
770 }
771 }
772 if(result == cancel || input->last_key.sym == SDLK_ESCAPE) {
773 net->gethostbyname_cancel();
774 input->last_key.sym = SDLK_UNKNOWN;
775 ret();
776 }
777 }
778
Menu_multi_internet(Menu_multi_join * p)779 Menu_multi_internet::Menu_multi_internet(Menu_multi_join *p): Menu(p->inter) {
780 parent = p;
781 new Zone_bitmap(inter, parent->bit_, 0, 0);
782 new Zone_text(fteam[7], inter, "Searching for public Internet games...",
783 130);
784 cancel = new Zone_text_button2(inter, parent->bit_, parent->font2_,
785 "�2 Cancel", 190);
786 request = NULL;
787 }
788
~Menu_multi_internet()789 Menu_multi_internet::~Menu_multi_internet() {
790 if(request)
791 delete request;
792 }
793
init()794 void Menu_multi_internet::init() {
795 Menu::init();
796 const char *msg;
797
798 request = new Qserv();
799 request->add_data("getgames\n");
800 request->send();
801 msg = net->failed();
802 if(msg) {
803 exec(new Menu_net_problem(msg, "Either the server is down, or this "
804 "address isn't a Quadra game server.",
805 parent->bit_, inter->font));
806 delete request;
807 request = NULL;
808 }
809 }
810
step()811 void Menu_multi_internet::step() {
812 Menu::step();
813 if(!request)
814 return;
815 bool done = request->done();
816 if(net->failed()) {
817 exec(new Menu_net_problem("No Quadra server found at specified address.",
818 "Either the server is down, or this address "
819 "isn't a Quadra game server.", parent->bit_,
820 inter->font));
821 return;
822 }
823 if(done)
824 parsegames();
825 if(result == cancel || input->last_key.sym == SDLK_ESCAPE) {
826 input->last_key.sym = SDLK_UNKNOWN;
827 ret();
828 }
829 }
830
parse_attack(const char * s)831 Attack Menu_multi_internet::parse_attack(const char *s) {
832 Attack ret;
833 if(s) {
834 ret.type = (Attack_type) atoi(s);
835 const char *sep=strchr(s, ' ');
836 if(sep)
837 ret.param=atoi(sep+1);
838 }
839 return ret;
840 }
841
parsegames()842 void Menu_multi_internet::parsegames() {
843 ret();
844 if(!request->get_status() || strcmp(request->get_status(), "Current games"))
845 return;
846
847 Dict *games=request->get_reply();
848 if(_debug) {
849 games->dump();
850 }
851 unsigned int i, j;
852 for(i = 0; i < games->size(); i++) {
853 const Dict *d = games->get_sub(i);
854 Packet_gameinfo *p=new Packet_gameinfo();
855
856 p->from = NULL;
857 // Word port=0;
858 char cip[32];
859 strcpy(cip, d->get_key());
860 char *cport=strchr(cip, ':');
861 if(cport) {
862 // port=atoi(cport+1);
863 *cport=0; //Cut string at ':' separator
864 }
865 p->from_addr = Net::dotted2addr(cip);
866 const char *temp;
867 temp = d->find("name");
868 if(temp)
869 strcpy(p->name, temp);
870 temp = d->find("version");
871 if(temp)
872 p->version = atoi(temp);
873 temp = d->find("port");
874 if(temp)
875 p->port = atoi(temp);
876
877 const Dict *players = d->find_sub("players");
878 if(players) {
879 for(j=0; j < players->size(); j++) {
880 const Dict *d2 = players->get_sub(j);
881 const char *name = d2->find("name");
882 temp = d2->find("team");
883 int team=0;
884 if(temp) {
885 team = atoi(temp);
886 if(team<0 || team>7)
887 team=0;
888 }
889 int status = -1;
890 temp = d2->find("status");
891 if(temp) {
892 status = atoi(temp);
893 if(status<0 || status>3)
894 status = -1;
895 }
896 int handicap=0;
897 temp = d2->find("handicap");
898 if(temp) {
899 handicap = atoi(temp);
900 if(handicap<0 || handicap>4)
901 handicap=0;
902 }
903 p->add_player(0, team, name, status, handicap);
904 }
905 }
906
907 const Dict *end = d->find_sub("end");
908 if(end) {
909 temp = end->find("value");
910 if(temp)
911 p->game_end_value = atoi(temp);
912 temp = end->find("type");
913 if(temp)
914 p->game_end = atoi(temp);
915 }
916
917 const Dict *rules = d->find_sub("rules");
918 if(rules) {
919 temp = rules->find("levelup");
920 if(temp)
921 p->nolevel_up = atoi(temp) ? false:true;
922 temp = rules->find("levelstart");
923 if(temp)
924 p->level_start = atoi(temp);
925 temp = rules->find("mincombo");
926 if(temp)
927 p->combo_min = atoi(temp);
928 temp = rules->find("allowhandicap");
929 if(temp)
930 p->allow_handicap = atoi(temp) ? true : false;
931 temp = rules->find("survivor");
932 if(temp)
933 p->survivor = atoi(temp) ? true : false;
934 temp = rules->find("hot_potato");
935 if(temp)
936 p->hot_potato = atoi(temp) ? true : false;
937 const Dict *attacks = rules->find_sub("attacks");
938 if(attacks) {
939 temp = attacks->find("normal");
940 p->normal_attack = parse_attack(temp);
941 temp = attacks->find("clean");
942 p->clean_attack = parse_attack(temp);
943 temp = attacks->find("potato_normal");
944 p->potato_normal_attack = parse_attack(temp);
945 temp = attacks->find("potato_clean");
946 p->potato_clean_attack = parse_attack(temp);
947 }
948 }
949
950 const Dict *status = d->find_sub("status");
951 if(status) {
952 temp = status->find("started");
953 if(temp)
954 p->delay_start = atoi(temp) ? false:true;
955 temp = status->find("terminated");
956 if(temp)
957 p->terminated = atoi(temp) ? true:false;
958 }
959
960 parent->net_call(p);
961 }
962 }
963
Menu_single()964 Menu_single::Menu_single() {
965 {
966 Res_doze res("multi.png");
967 Png img(res);
968 bit = new Bitmap(img);
969 pal.load(img);
970 }
971
972 pal.set_size(256); //Useless but whatever
973 set_fteam_color(pal);
974
975 inter->set_font(new Font(*fonts.normal, pal, 255,255,255));
976 font2 = new Font(*fonts.normal, pal, 255,255,0);
977 (void)new Zone_bitmap(inter, bit, 0, 0, true);
978 (void)new Zone_text(inter, "Select game type:", 20);
979 normal = new Zone_text_button2(inter, bit, font2, "Normal", 180);
980 sprint = new Zone_text_button2(inter, bit, font2, "Sprint (5 minutes)", 220);
981 cancel = new Zone_text_button2(inter, bit, font2, "Back �0", 560, 450);
982 }
983
step()984 void Menu_single::step() {
985 Menu_standard::step();
986 if(result == normal) {
987 call(new Fade_in(pal));
988 call(new Single_player(PRESET_SINGLE));
989 call(new Fade_out(pal));
990 }
991 if(result == sprint) {
992 call(new Fade_in(pal));
993 call(new Single_player(PRESET_SINGLE_SPRINT));
994 call(new Fade_out(pal));
995 }
996 if(result == cancel)
997 quit=true;
998 }
999
~Menu_single()1000 Menu_single::~Menu_single() {
1001 delete font2;
1002 }
1003
Menu_multi()1004 Menu_multi::Menu_multi() {
1005 {
1006 Res_doze res("multi.png");
1007 Png img(res);
1008 bit = new Bitmap(img);
1009 pal.load(img);
1010 }
1011
1012 pal.set_size(256); //Useless but whatever
1013 set_fteam_color(pal);
1014
1015 inter->set_font(new Font(*fonts.normal, pal, 255,255,255));
1016 font2 = new Font(*fonts.normal, pal, 255,255,0);
1017 (void)new Zone_bitmap(inter, bit, 0, 0, true);
1018 (void)new Zone_text(inter, "Please select a connection type:", 20);
1019 local = new Zone_text_button2(inter, bit, font2, "Local game (no network)",
1020 180);
1021 net_lan = new Zone_text_button2(inter, bit, font2, "TCP/IP Local "
1022 "network (LAN)", 220);
1023 net_internet = new Zone_text_button2(inter, bit, font2, "TCP/IP Internet",
1024 260);
1025 cancel = new Zone_text_button2(inter, bit, font2, "Back �0", 560, 450);
1026 }
1027
step()1028 void Menu_multi::step() {
1029 Menu_standard::step();
1030 if(result == local) {
1031 call(new Create_game(bit, inter->font, font2, pal, false, false));
1032 }
1033 if(result == net_lan) {
1034 call(new Menu_multi_join(bit, inter->font, font2, pal, true));
1035 }
1036 if(result == net_internet) {
1037 call(new Menu_multi_join(bit, inter->font, font2, pal, false));
1038 }
1039 if(result == cancel)
1040 quit=true;
1041 }
1042
~Menu_multi()1043 Menu_multi::~Menu_multi() {
1044 delete font2;
1045 }
1046
Menu_setup()1047 Menu_setup::Menu_setup() {
1048 {
1049 Res_doze res("setup.png");
1050 Png img(res);
1051 bit = new Bitmap(img);
1052 pal.load(img);
1053 }
1054 inter->set_font(new Font(*fonts.normal, pal, 255,255,255));
1055 set_fteam_color(pal);
1056 (void)new Zone_bitmap(inter, bit, 0, 0, true);
1057
1058 Zone_state_text2 *z_setup_player = new Zone_state_text2(inter, &config.info.setup_player, 333, 11);
1059 z_setup_player->add_string("1");
1060 z_setup_player->add_string("2");
1061 z_setup_player->add_string("3");
1062
1063 z_nameinput = new Zone_text_input(inter, pal, config.player[config.info.setup_player].name, 40, 333, 106, 110, 100);
1064
1065 z_passwdinput = new Zone_text_input(inter, pal, config.player2[config.info.setup_player].ngPasswd, 64, 333, 132, 200);
1066
1067 z_shadow = new Zone_state_text2(inter, &config.player[config.info.setup_player].shadow, 333, 161);
1068 z_shadow->add_string("No");
1069 z_shadow->add_string("Yes");
1070
1071 z_smooth = new Zone_state_text2(inter, &config.player[config.info.setup_player].smooth, 333, 192);
1072 z_smooth->add_string("No");
1073 z_smooth->add_string("Yes");
1074
1075 z_h_repeat = new Zone_state_text(inter, &config.player2[config.info.setup_player].h_repeat, 333, 220);
1076 z_h_repeat->add_string("Slow");
1077 z_h_repeat->add_string("Normal");
1078 z_h_repeat->add_string("Fast");
1079 z_h_repeat->add_string("Faster");
1080
1081 z_v_repeat = new Zone_state_text(inter, &config.player2[config.info.setup_player].v_repeat, 333, 252);
1082 z_v_repeat->add_string("Slow");
1083 z_v_repeat->add_string("Normal");
1084 z_v_repeat->add_string("Fast");
1085 z_v_repeat->add_string("Faster");
1086
1087 z_continuousdown = new Zone_state_text(inter, &config.player2[config.info.setup_player].continuous, 333, 281);
1088 z_continuousdown->add_string("No");
1089 z_continuousdown->add_string("Yes");
1090
1091 z_key[0] = new Zone_set_key(inter, &config.player[config.info.setup_player].key[0], 148, 347);
1092 z_key[1] = new Zone_set_key(inter, &config.player[config.info.setup_player].key[1], 148, 378);
1093 z_key[3] = new Zone_set_key(inter, &config.player[config.info.setup_player].key[3], 148, 408);
1094 z_key[6] = new Zone_set_key(inter, &config.player2[config.info.setup_player].key[1], 148, 439);
1095 z_key[4] = new Zone_set_key(inter, &config.player[config.info.setup_player].key[4], 513, 350);
1096 z_key[2] = new Zone_set_key(inter, &config.player[config.info.setup_player].key[2], 513, 380);
1097 z_key[5] = new Zone_set_key(inter, &config.player2[config.info.setup_player].key[0], 513, 411);
1098
1099 b_player = new Zone_menu(inter, bit, "setup0.png", 195, 11);
1100 b_player->set_child(z_setup_player);
1101 (new Zone_menu(inter, bit, "setup1.png", 255, 101))->set_child(z_nameinput);
1102 (new Zone_menu(inter, bit, "setup2.png", 222, 132))->set_child(z_passwdinput);
1103 (new Zone_menu(inter, bit, "setup3.png", 237, 161))->set_child(z_shadow);
1104 (new Zone_menu(inter, bit, "setup4.png", 240, 192))->set_child(z_smooth);
1105 (new Zone_menu(inter, bit, "setup5.png", 157, 220))->set_child(z_h_repeat);
1106 (new Zone_menu(inter, bit, "setup6.png", 184, 252))->set_child(z_v_repeat);
1107 (new Zone_menu(inter, bit, "setup7.png", 153, 281))->set_child(z_continuousdown);
1108 b_key[0] = new Zone_menu(inter, bit, "setup8.png", 45, 347);
1109 b_key[1] = new Zone_menu(inter, bit, "setup9.png", 32, 378);
1110 b_key[3] = new Zone_menu(inter, bit, "setup10.png", 26, 408);
1111 b_key[6] = new Zone_menu(inter, bit, "setup11.png", 19, 439);
1112 b_key[4] = new Zone_menu(inter, bit, "setup12.png", 344, 350);
1113 b_key[2] = new Zone_menu(inter, bit, "setup13.png", 275, 380);
1114 b_key[5] = new Zone_menu(inter, bit, "setup14.png", 382, 411);
1115 b_all_key = new Zone_menu(inter, bit, "setup15.png", 390, 439);
1116
1117 for(int i=0; i<7; i++)
1118 b_key[i]->set_child(z_key[i]);
1119
1120 b_quit = new Zone_text_button2(inter, bit, fteam[4], "Back �0", 560, 450);
1121 }
1122
~Menu_setup()1123 Menu_setup::~Menu_setup() {
1124 int i;
1125 for(i=0; i<3; i++)
1126 if(!config.player[i].name[0]) {
1127 char st[16];
1128 sprintf(st,"#%i", i+1);
1129 strcpy(config.player[i].name, st);
1130 }
1131 config.write();
1132 }
1133
step()1134 void Menu_setup::step() {
1135 Menu_standard::step();
1136 if(!result) {
1137 return;
1138 }
1139
1140 if(result == b_quit) {
1141 quit = true;
1142 }
1143 if(result == b_player) {
1144 z_nameinput->set_val(config.player[config.info.setup_player].name);
1145 z_passwdinput->set_val(config.player2[config.info.setup_player].ngPasswd);
1146 z_shadow->set_val(&config.player[config.info.setup_player].shadow);
1147 z_smooth->set_val(&config.player[config.info.setup_player].smooth);
1148 z_h_repeat->set_val(&config.player2[config.info.setup_player].h_repeat);
1149 z_v_repeat->set_val(&config.player2[config.info.setup_player].v_repeat);
1150 z_continuousdown->set_val(&config.player2[config.info.setup_player].continuous);
1151 for(int i=0; i<7; i++)
1152 if(i<5)
1153 z_key[i]->set_val(&config.player[config.info.setup_player].key[i]);
1154 else
1155 z_key[i]->set_val(&config.player2[config.info.setup_player].key[i-5]);
1156 }
1157 if(result == b_all_key) {
1158 call(new Menu_setup_all_key(inter, z_key));
1159 }
1160 for(int i=0; i<7; i++) {
1161 if(result==b_key[i]) {
1162 call(new Menu_setup_key(inter, (Zone_set_key *) z_key[i],
1163 "Press a key..."));
1164 }
1165 }
1166 }
1167
Menu_setup_all_key(Inter * in,Zone_set_key * k[])1168 Menu_setup_all_key::Menu_setup_all_key(Inter *in, Zone_set_key *k[]): Menu(in) {
1169 key = k;
1170 quel=0;
1171 }
1172
step()1173 void Menu_setup_all_key::step() {
1174 const size_t touche[7] = {0, 1, 3, 4, 2, 5, 6};
1175 Menu::step();
1176 if(quel > 6 || input->keys[SDLK_ESCAPE] & PRESSED) {
1177 ret();
1178 return;
1179 }
1180 const char *te = NULL;
1181 switch(touche[quel]) {
1182 case 0: te = "Press a key for left..."; break;
1183 case 1: te = "Right..."; break;
1184 case 2: te = "Rotate counter clock-wise..."; break;
1185 case 3: te = "Down..."; break;
1186 case 4: te = "Rotate clock-wise..."; break;
1187 case 5: te = "Rotate twice..."; break;
1188 case 6: te = "Instant drop..."; break;
1189 }
1190 call(new Menu_setup_key(inter, key[touche[quel]], te));
1191 quel++;
1192 }
1193
Menu_setup_key(Inter * in,Zone_set_key * k,const char * t)1194 Menu_setup_key::Menu_setup_key(Inter *in, Zone_set_key *k, const char *t): Menu(in) {
1195 new Zone_text_field(inter, t, 180, 315, 280);
1196 key = k;
1197 }
1198
Menu_setup_key(Inter * in,Zone_set_key * k)1199 Menu_setup_key::Menu_setup_key(Inter *in, Zone_set_key *k): Menu(in) {
1200 key = k;
1201 }
1202
init()1203 void Menu_setup_key::init() {
1204 input->clear_key();
1205 }
1206
step()1207 void Menu_setup_key::step() {
1208 Menu::step();
1209 int loop = 0;
1210 for(int i = SDLK_FIRST; i < SDLK_LAST; ++i) {
1211 if(input->keys[i] & PRESSED) {
1212 loop = i;
1213 break;
1214 }
1215 }
1216 if(loop == 0) return;
1217
1218 input->last_key.sym = SDLK_UNKNOWN;
1219 // denies Enter (reserved for multiplayer chat)
1220 if(loop == SDLK_RETURN) return;
1221 if(loop != SDLK_ESCAPE)
1222 {
1223 *(key->val) = loop;
1224 key->process();
1225 }
1226 ret();
1227 }
1228
Menu_quitgame()1229 Menu_quitgame::Menu_quitgame() {
1230 int y;
1231 for(y=0; y<8; y++)
1232 pal.setcolor(y, y*255/7, y*255/7, y*255/7);
1233 pal.setcolor(255, 255, 255, 255);
1234 inter->set_font(new Font(*fonts.normal, pal, 255,255,255));
1235 for(y=8; y<16; y++)
1236 pal.setcolor(y, 0, 0, y*255/7);
1237 font2 = new Font(*fonts.normal, pal, 0,0,255);
1238 }
1239
~Menu_quitgame()1240 Menu_quitgame::~Menu_quitgame() {
1241 delete font2;
1242 }
1243
init()1244 void Menu_quitgame::init() {
1245 Menu_standard::init();
1246 (void)new Zone_clear(inter);
1247 (void)new Zone_text(inter, "Quadra", 0);
1248 (void)new Zone_text(inter, "You have been playing an unregistered "
1249 "version of Quadra.", 10, 40);
1250 int t,h,m,s;
1251 t = overmind.framecount / 100;
1252 h = t / 60 / 60;
1253 t = t % 3600;
1254 m = t / 60;
1255 s = t % 60;
1256 if(h > 0) {
1257 sprintf(st, "In fact, you played for %i hours and %i minutes!", h, m);
1258 } else if(m > 0) {
1259 sprintf(st, "In fact, you played for %i minutes %i seconds.", m, s);
1260 } else {
1261 sprintf(st, "You spent about %i seconds checking it.", s);
1262 }
1263 (void)new Zone_text(inter, st, 10, 60);
1264 (void)new Zone_text(inter, "Was it enjoyable? Was it incredibly fun?",
1265 10, 80);
1266 (void)new Zone_text(inter, "Feel free to distribute Quadra to everyone "
1267 "you want!", 10, 300);
1268 #ifdef UGS_DIRECTX
1269 (void)new Zone_text(inter, "We even got a Linux version, networkable "
1270 "with yours!", 10, 360);
1271 #else
1272 (void)new Zone_text(inter, "We even got a Windows version, networkable "
1273 "with yours!", 10, 360);
1274 #endif
1275 (void)new Zone_text(inter, "So watch out for Ludus Design products, "
1276 "and remember:", 10, 380);
1277 (void)new Zone_text(font2, inter, "We do great stuff for you!", 20, 410);
1278 }
1279
step()1280 void Menu_quitgame::step() {
1281 Menu_standard::step();
1282 if(!quit)
1283 call(new Wait_time(24000));
1284 quit=true;
1285 }
1286
Menu_help()1287 Menu_help::Menu_help() {
1288 Bitmap *bit;
1289 {
1290 Res_doze res("multi.png");
1291 Png img(res);
1292 bit = new Bitmap(img);
1293 pal.load(img);
1294 }
1295 pal.set_size(256);
1296 set_fteam_color(pal);
1297
1298 inter->set_font(new Font(*fonts.normal, pal, 255,255,255));
1299 font2 = fteam[4];
1300 (void)new Zone_bitmap(inter, bit, 0, 0, true);
1301 b_quit = new Zone_text_button2(inter, NULL, font2, "Back �0", 560, 450);
1302 int y;
1303 (void)new Zone_text(inter, "Thanks for downloading Quadra!", 20);
1304 y = 220;
1305 b_online=NULL;
1306
1307 Zone_text *temp;
1308 (void)new Zone_text(fteam[3], inter, "The Quadra team:", y); y+=20;
1309 (void)new Zone_text(inter, "R�mi Veilleux: Programming, design, graphics", 10, y); y+=20;
1310 (void)new Zone_text(inter, "St�phane Lajoie: Programming", 10, y); y+=20;
1311 (void)new Zone_text(inter, "Pierre Phaneuf: Linux port", 10, y); y+=20;
1312 (void)new Zone_text(inter, "Sylvain Fortin: Glue", 10, y); y+=20;
1313 (void)new Zone_text(inter, "V�ronique Bruneau: Graphics", 10, y); y+=20;
1314 (void)new Zone_text(inter, "Our web site:", 10, y);
1315 b_www = temp = new Zone_text_select(inter, fteam[4],
1316 "http://quadra.sourceforge.net/",
1317 160, y);
1318 temp->set_font(fteam[6]);
1319 }
1320
init()1321 void Menu_help::init() {
1322 Menu_standard::init();
1323 sons.levelup->play(0, 0, 11000);
1324 }
1325
step()1326 void Menu_help::step() {
1327 Menu_standard::step();
1328 if(!result)
1329 return;
1330 if(result == b_quit)
1331 quit = true;
1332 #ifdef UGS_DIRECTX
1333 if(result == b_www)
1334 call_internet("http://quadra.sourceforge.net/");
1335 if(result == b_online)
1336 call_internet("http://www.ludusdesign.com/quadra/register.html");
1337 #endif
1338 }
1339
call_internet(const char * s)1340 void Menu_help::call_internet(const char *s) {
1341 call(new Fade_in(pal));
1342 call(new Menu_internet(s));
1343 call(new Fade_to(Palette(), pal));
1344 }
1345
Menu_option()1346 Menu_option::Menu_option() {
1347 {
1348 Res_doze res("multi.png");
1349 Png img(res);
1350 bit = new Bitmap(img);
1351 pal.load(img);
1352 }
1353 pal.set_size(256);
1354 set_fteam_color(pal);
1355
1356 Palette ptemp;
1357 {
1358 Res_doze res("fond0.png");
1359 Png png(res);
1360 ptemp.load(png);
1361 }
1362 for(int i=184; i<256; i++) // copies the colors of the blocs from fond0.png
1363 pal.setcolor(i, ptemp.r(i), ptemp.g(i), ptemp.b(i));
1364 inter->set_font(new Font(*fonts.normal, pal, 255,255,255));
1365 set_fteam_color(pal);
1366 font2 = fteam[4];
1367 (void)new Zone_bitmap(inter, bit, 0, 0, true);
1368 (void)new Zone_text(inter, "Game options", 20);
1369 b_quit = new Zone_text_button2(inter, bit, font2, "Back �0", 560, 450);
1370
1371 // FIXME: Configuration for the removed CD music player. Should be taken out.
1372 (void)new Zone_text(fteam[7], inter, "Select CD playing mode:", 40, 130);
1373 {
1374 Zone_state_text2 *temp = new Zone_state_text2(inter,
1375 &config.info.cdmusic,
1376 380, 130);
1377 temp->add_string("No music");
1378 temp->add_string("Auto-change track");
1379 temp->add_string("Loop all tracks");
1380 }
1381
1382 (void)new Zone_text(fteam[7], inter, "Mouse cursor speed (1-255):", 40, 160);
1383 (void)new Zone_input_numeric(inter, &config.info.mouse_speed, 4, 1, 255, pal, 380, 160, 60);
1384 old_port = config.info.port_number;
1385
1386 (void)new Zone_text(inter, "Advanced options:", 40, 220);
1387
1388 (void)new Zone_text(fteam[7], inter, "TCP/IP port number (1024-65535):",
1389 40, 250);
1390 (void)new Zone_input_numeric(inter, &config.info.port_number, 6, 1024, 65535, pal, 380, 250, 60);
1391 (void)new Zone_text(fteam[3], inter, "(Note: you must have the same port "
1392 "number to connect to another computer)", 40, 274);
1393
1394 (void)new Zone_text(fteam[7], inter, "Public game server address:", 40, 310);
1395 (void)new Zone_text_input(inter, pal, config.info.game_server_address, 255, 380, 310, 240);
1396 char stbuf[512];
1397 snprintf(stbuf, sizeof(stbuf), "Default server: %s",
1398 config.info3.default_game_server_address);
1399 (void)new Zone_text(fteam[3], inter, stbuf, 40, 334);
1400 strcpy(old_server, config.info.game_server_address);
1401
1402 (void)new Zone_text(fteam[7], inter, "HTTP proxy server:", 40, 370);
1403 (void)new Zone_text_input(inter, pal, config.info2.proxy_address, 127, 380, 370, 240);
1404 strcpy(old_proxy, config.info2.proxy_address);
1405 }
1406
~Menu_option()1407 Menu_option::~Menu_option() {
1408 config.write();
1409 if(strcmp(old_server, config.info.game_server_address) || strcmp(old_proxy, config.info2.proxy_address)) {
1410 Qserv::http_addr=0;
1411 Qserv::http_port=0;
1412 }
1413 }
1414
step()1415 void Menu_option::step() {
1416 Menu_standard::step();
1417 if(result == b_quit)
1418 quit = true;
1419 }
1420
Menu_intro()1421 Menu_intro::Menu_intro() {
1422 int y;
1423 for(y=0; y<8; y++)
1424 pal.setcolor(y, y*255/7, y*255/7, y*255/7);
1425 for(y=8; y<16; y++)
1426 pal.setcolor(y, 0, y*255/7, y*255/7);
1427 pal.setcolor(255, 255, 255, 255);
1428 inter->set_font(new Font(*fonts.normal, pal, 255,255,255));
1429 font2 = new Font(*fonts.normal, pal, 0,255,255);
1430 (void)new Zone_clear(inter);
1431 (void)new Zone_text(inter, "Quadra(tm) by Ludus Design", 10);
1432 (void)new Zone_text(inter, "Using Universal Game Skelton(tm)", 10, 40);
1433 (void)new Zone_text(font2, inter, "Free version released under the "
1434 "GNU Lesser General Public License", 10, 80);
1435
1436 y=130;
1437 warning=0;
1438 if(!sound) {
1439 (void)new Zone_text(inter, "Warning: Failed to initialise sound system",
1440 10, y);
1441 warning++;
1442 y += 20;
1443 }
1444 if(config.warning == 1) {
1445 (void)new Zone_text(inter, "No configuration file found. Using defaults.", 10, y);
1446 y += 20;
1447 }
1448 if(config.warning == 2) {
1449 (void)new Zone_text(inter, "Warning: Wrong version in configuration "
1450 "file. Using defaults.", 10, y);
1451 warning++;
1452 y += 20;
1453 }
1454 (void)new Zone_text(inter, "Hit something to continue...", 10, y);
1455 #ifdef ENABLE_VERSION_CHECK
1456 if(strcmp(VERSION_STRING, config.info3.latest_version) != 0)
1457 {
1458 (void)new Zone_text(font2, inter, "A new version of Quadra is available!",
1459 10, y + 40);
1460 (void)new Zone_text(font2, inter, "Get it at http://quadra.googlecode.com",
1461 10, y + 60);
1462 }
1463 #endif
1464 (void)new Zone_text(inter, "Quadra, Universal Game Skelton and the "
1465 "Ludus Design logo are trademarks", 10, 430);
1466 (void)new Zone_text(inter, "of Ludus Design, Copyright (C) 1998-2000. "
1467 "All rights reserved.", 10, 450);
1468 once = false;
1469 }
1470
init()1471 void Menu_intro::init() {
1472 Menu::init();
1473 call(new Setpalette(pal));
1474 }
1475
step()1476 void Menu_intro::step() {
1477 Menu::step();
1478 ret();
1479 call(new Menu_main());
1480 call(new Setpalette(noir));
1481 call(new Wait_time(3000));
1482 }
1483
~Menu_intro()1484 Menu_intro::~Menu_intro() {
1485 delete font2;
1486 }
1487
Menu_main()1488 Menu_main::Menu_main():
1489 version_warning(false)
1490 {
1491 {
1492 Res_doze res("debuto.png");
1493 Png png(res);
1494 pal.load(png);
1495 }
1496 inter->set_font(new Font(*fonts.normal, pal, 255,255,255));
1497 redraw();
1498 }
1499
redraw()1500 void Menu_main::redraw() {
1501 inter->flush();
1502 Bitmap *background;
1503 {
1504 Res_doze res("debuto.png");
1505 Png png(res);
1506 background = new Bitmap(png);
1507 }
1508 z_back = new Zone_bitmap(inter, background, 0, 0, true);
1509
1510 b_help = NULL;
1511 b_single = new Zone_menu(inter, background, "debut0.png", 160, 99);
1512 b_multi = new Zone_menu(inter, background, "debut1.png", 166, 139);
1513 b_demo = new Zone_menu(inter, background, "debut2.png", 214, 183);
1514 b_tut = new Zone_menu(inter, background, "debut3.png", 235, 225);
1515 b_setup = new Zone_menu(inter, background, "debut4.png", 221, 267);
1516 b_option = new Zone_menu(inter, background, "debut5.png", 264, 310);
1517 b_help = new Zone_menu(inter, background, "debut6.png", 261, 351);
1518 b_quit = new Zone_menu(inter, background, "debut7.png", 295, 392);
1519
1520 sprintf(st, "Quadra version %s", VERSION_STRING);
1521 new Zone_text(inter, st, 450, 430);
1522
1523 b_logo = new Zone_menu(inter, background, "debut8.png", 0, 390);
1524 }
1525
init()1526 void Menu_main::init() {
1527 Menu::init();
1528 // FIXME: The following line might not be necessary without the music.
1529 call(new Wait_time(6)); // to force the palette being set BEFORE the
1530 // music starts
1531 call(new Setpalette(pal));
1532 reset_delay();
1533 }
1534
reset_delay()1535 void Menu_main::reset_delay() {
1536 delay = 12000;
1537
1538 if(!version_warning)
1539 {
1540 if(strcmp(VERSION_STRING, config.info3.latest_version) != 0)
1541 {
1542 (void)new Zone_text(inter, "New version available", 455, 445);
1543 (void)new Zone_text(inter, "Get it at http://quadra.googlecode.com", 330, 460);
1544 version_warning = true;
1545 }
1546 }
1547 }
1548
step()1549 void Menu_main::step() {
1550 Menu::step();
1551 delay--;
1552 if(delay < 0) {
1553 call(new Fade_in(pal));
1554 if(1/*ugs_random.rnd(1) == 0*/) { // always pop a demo (highscore menu sucks)
1555 int i=ugs_random.rnd(3);
1556 char st[20];
1557 sprintf(st, "demo%02i.rec", i);
1558 call(new Call_setfont(pal, new Demo_multi_player(new Res_compress(st, RES_READ, true), true)));
1559 }
1560 else
1561 call(new Menu_highscore());
1562 call(new Fade_out(pal));
1563 reset_delay();
1564 }
1565 if(result == b_quit || input->last_key.sym == SDLK_ESCAPE || quitting) {
1566 input->last_key.sym = SDLK_UNKNOWN;
1567 exec(new Fade_out(pal));
1568 }
1569 if(result == b_tut) {
1570 call(new Fade_in(pal));
1571 call(new Menu_highscore(-1, NULL, true));
1572 call(new Fade_out(pal));
1573 }
1574 #ifdef UGS_DIRECTX
1575 if(result == b_logo) {
1576 call(new Fade_in(pal));
1577 call(new Menu_internet("http://quadra.sourceforge.net/"));
1578 call(new Fade_to(Palette(), pal));
1579 }
1580 #endif
1581 if(result == b_option) {
1582 call(new Fade_in(pal));
1583 call(new Menu_option());
1584 call(new Fade_out(pal));
1585 }
1586 if(result && result == b_help) {
1587 call(new Fade_in(pal));
1588 call(new Menu_help());
1589 call(new Fade_out(pal));
1590 }
1591 if(result == b_setup) {
1592 call(new Fade_in(pal));
1593 call(new Menu_setup());
1594 call(new Fade_out(pal));
1595 }
1596 if(result == b_multi) {
1597 call(new Fade_in(pal));
1598 call(new Menu_multi());
1599 call(new Fade_out(pal));
1600 }
1601 if(result == b_single) {
1602 //-roncli 4/29/01 This doesn't suck anymore. :-D
1603 call(new Fade_in(pal));
1604 call(new Menu_single());
1605 call(new Fade_out(pal));
1606
1607 }
1608 if(result == b_demo) {
1609 call(new Fade_in(pal));
1610 call(new Menu_demo_central());
1611 call(new Fade_out(pal));
1612 }
1613 // if(result && result==z_back) {
1614 // Bulle::test(*z_back->actual);
1615 // video->need_paint=2;
1616 // }
1617 if(result)
1618 reset_delay();
1619 }
1620
Colonne()1621 Menu_stat::Colonne::Colonne() {
1622 sort_me = false;
1623 }
1624
set_titre(const char * s)1625 void Menu_stat::Colonne::set_titre(const char *s) {
1626 strcpy(titre, s);
1627 }
1628
Menu_stat()1629 Menu_stat::Menu_stat():
1630 c_start(105), c_gap(4) {
1631 int i;
1632 {
1633 Res_doze res("result.png");
1634 Png raw(res);
1635 bit = new Bitmap(raw);
1636 pal.load(raw);
1637 }
1638 pal.set_size(256);
1639 Palette temp;
1640 {
1641 Res_doze res("fond0.png");
1642 Png png(res);
1643 temp.load(png);
1644 }
1645 for(i=184; i<256; i++) // copie les couleurs des blocs de l'image fond0.png
1646 pal.setcolor(i, temp.r(i), temp.g(i), temp.b(i));
1647
1648 set_fteam_color(pal);
1649 inter->set_font(new Font(*fonts.normal, pal, 255,255,255));
1650 fcourrier[0] = new Font(*fonts.courrier, pal, 255,125,0);
1651 fcourrier[1] = new Font(*fonts.courrier, pal, 0,225,255);
1652 fcourrier[2] = new Font(*fonts.courrier, pal, 255,0,0);
1653 fcourrier[3] = new Font(*fonts.courrier, pal, 255,0,255);
1654 fcourrier[4] = new Font(*fonts.courrier, pal, 255,255,0);
1655 fcourrier[5] = new Font(*fonts.courrier, pal, 0,255,0);
1656 fcourrier[6] = new Font(*fonts.courrier, pal, 0,0,255);
1657 fcourrier[7] = new Font(*fonts.courrier, pal, 170,170,170);
1658 font2 = fteam[4];
1659 (void)new Zone_bitmap(inter, bit, 0, 0);
1660 b_quit = new Zone_text_button2(inter, bit, font2, "Quit �0", 340, 455);
1661 Zone_text_button *z;
1662 int x(8), wid(105);
1663 z=new Zone_text_button2(inter, bit, font2, "Rank", x, 80, wid-8);
1664 b_page.push_back(z);
1665 x+=wid;
1666 z=new Zone_text_button2(inter, bit, font2, "Speed", x, 80, wid-8);
1667 b_page.push_back(z);
1668 x+=wid;
1669 z=new Zone_text_button2(inter, bit, font2, "Lines", x, 80, wid-8);
1670 b_page.push_back(z);
1671 x+=wid;
1672 z=new Zone_text_button2(inter, bit, font2, "Combos", x, 80, wid-8);
1673 b_page.push_back(z);
1674 x+=wid;
1675
1676 b_restart = b_stop = NULL;
1677
1678 init_columns(bit);
1679
1680 active_sort = -1;
1681 active_page = -1;
1682 change_page(0);
1683
1684 notify();
1685 (void)new Chat_interface(inter, pal, bit->surface, 427, 47, 212, 410);
1686 if(game)
1687 game->net_list.add_watch(this);
1688 }
1689
~Menu_stat()1690 Menu_stat::~Menu_stat() {
1691 while (!col.empty()) {
1692 delete col.back();
1693 col.pop_back();
1694 }
1695 if(game)
1696 game->net_list.remove_watch(this);
1697 for(int i=0; i<MAXTEAMS; i++)
1698 delete fcourrier[i];
1699 if(bit)
1700 delete bit;
1701 }
1702
init_columns(Bitmap * bit)1703 void Menu_stat::init_columns(Bitmap *bit) {
1704 int i, page=0;
1705 Colonne *n;
1706 n=new Colonne();
1707 n->quel_stat = CS::FRAG;
1708 n->width = 70;
1709 n->set_titre("Frags");
1710 col.push_back(n);
1711
1712 n=new Colonne();
1713 n->quel_stat = CS::DEATH;
1714 n->width = 70;
1715 n->set_titre("Deaths");
1716 col.push_back(n);
1717
1718 n=new Colonne();
1719 n->quel_stat = CS::SCORE;
1720 n->width = 90;
1721 n->set_titre("Score");
1722 col.push_back(n);
1723
1724 n=new Colonne();
1725 n->quel_stat = CS::LINESTOT;
1726 n->width = 90;
1727 n->set_titre("Lines");
1728 col.push_back(n);
1729
1730 int px;
1731 px = c_start;
1732 for(i=0; i<4; i++) {
1733 add_title(*col[i], &px, bit);
1734 col[i]->page = page;
1735 }
1736
1737 page++;
1738 px = c_start;
1739 n=new Colonne();
1740 n->quel_stat = CS::PPM;
1741 n->width = 150;
1742 n->set_titre("Points per min.");
1743 n->page = page;
1744 add_title(*n, &px, bit);
1745 col.push_back(n);
1746
1747 n=new Colonne();
1748 n->quel_stat = CS::BPM;
1749 n->width = 150;
1750 n->set_titre("Blocks per min.");
1751 n->page = page;
1752 add_title(*n, &px, bit);
1753 col.push_back(n);
1754
1755 page++;
1756 px = c_start;
1757 for(i=0; i<8; i++) {
1758 n=new Colonne();
1759 n->quel_stat = CS::clear_trans(i);
1760 n->width = 40;
1761 sprintf(st, "%i", i+1);
1762 n->set_titre(st);
1763 n->page = page;
1764 add_title(*n, &px, bit);
1765 col.push_back(n);
1766 }
1767
1768 page++;
1769 px = c_start;
1770 for(i=8; i<16; i++) {
1771 n=new Colonne();
1772 n->quel_stat = CS::clear_trans(i);
1773 n->width = 40;
1774 sprintf(st, "%i", i+1);
1775 n->set_titre(st);
1776 n->page = page;
1777 add_title(*n, &px, bit);
1778 col.push_back(n);
1779 }
1780
1781 page++;
1782 px = c_start;
1783 for(i=0; i<8; i++) {
1784 n=new Colonne();
1785 n->quel_stat = (CS::Stat_type) (CS::COMBO00+i);
1786 n->width = 40;
1787 sprintf(st, "%i", i+1);
1788 n->set_titre(st);
1789 n->page = page;
1790 add_title(*n, &px, bit);
1791 col.push_back(n);
1792 }
1793
1794 page++;
1795 px = c_start;
1796 for(i=8; i<16; i++) {
1797 n=new Colonne();
1798 n->quel_stat = (CS::Stat_type) (CS::COMBO00+i);
1799 n->width = 40;
1800 sprintf(st, "%i", i+1);
1801 n->set_titre(st);
1802 n->page = page;
1803 add_title(*n, &px, bit);
1804 col.push_back(n);
1805 }
1806 }
1807
add_title(Colonne & col,int * px,Bitmap * bit)1808 void Menu_stat::add_title(Colonne &col, int *px, Bitmap *bit) {
1809 col.z_titre = new Zone_text_button2(inter, bit, font2, col.titre, *px+3, 120, col.width-6);
1810 col.z_titre->disable();
1811 *px += col.width;
1812 }
1813
set_sort(int quel)1814 void Menu_stat::set_sort(int quel) {
1815 if(active_sort == quel)
1816 return;
1817 col[quel]->sort_me = true;
1818 col[quel]->z_titre->set_font(fteam[4]);
1819
1820 if(active_sort != -1) {
1821 col[active_sort]->sort_me = false;
1822 col[active_sort]->z_titre->set_font(inter->font);
1823 }
1824 active_sort = quel;
1825 }
1826
change_page(int p)1827 void Menu_stat::change_page(int p) {
1828 int i, last_page=0;
1829 for (i=0; i< static_cast<int>(col.size()); ++i) {
1830 if(col[i]->page == active_page) {
1831 col[i]->z_titre->disable();
1832 }
1833 if(col[i]->page>last_page)
1834 last_page = col[i]->page;
1835 }
1836 switch(active_page) {
1837 case 0:
1838 case 1:
1839 b_page[active_page]->set_font(inter->font);
1840 break;
1841 case 2:
1842 case 3:
1843 b_page[2]->set_font(inter->font);
1844 break;
1845 case 4:
1846 case 5:
1847 b_page[3]->set_font(inter->font);
1848 break;
1849 }
1850 switch(p) {
1851 case 0:
1852 active_page=0;
1853 b_page[0]->set_font(fteam[4]);
1854 break;
1855 case 1:
1856 active_page=1;
1857 b_page[1]->set_font(fteam[4]);
1858 break;
1859 case 2:
1860 if(active_page==2)
1861 active_page=3;
1862 else
1863 active_page=2;
1864 b_page[2]->set_font(fteam[4]);
1865 break;
1866 case 3:
1867 if(active_page==4)
1868 active_page=5;
1869 else
1870 active_page=4;
1871 b_page[3]->set_font(fteam[4]);
1872 break;
1873 }
1874 if (active_page > last_page)
1875 active_page = 0;
1876 for (i = 0; i < static_cast<int>(col.size()); ++i)
1877 if (col[i]->page == active_page)
1878 col[i]->z_titre->enable();
1879 notify();
1880 }
1881
calculate_total(bool force_blit)1882 void Menu_stat::calculate_total(bool force_blit) {
1883 if(!(overmind.framecount&127) || force_blit) {
1884 bool must_reblit = false;
1885 score.updateFromGame();
1886 if(score.team_order_changed || score.order_changed)
1887 must_reblit = true;
1888 if(active_sort!=-1)
1889 score.sort(col[active_sort]->quel_stat);
1890 if(score.team_order_changed || score.order_changed)
1891 must_reblit = true;
1892 if(must_reblit || force_blit)
1893 display();
1894 }
1895 }
1896
display()1897 void Menu_stat::display() {
1898 list.deleteall();
1899 int y = 145;
1900 for(int loo=0; loo<MAXTEAMS; loo++) {
1901 int team = score.team_order[loo];
1902 for(int loo2=0; loo2<MAXPLAYERS; loo2++) {
1903 int i=score.order[loo2];
1904 if(score.player_team[i]==team) {
1905 Canvas *c = game->net_list.get(i);
1906 if(c && c->color == team) {
1907 list.zones.push_back(new Zone_text(fteam[team], inter, c->long_name(), 2, y));
1908
1909 Font *color = fcourrier[team];
1910
1911 int px = c_start;
1912 for(int j = 0; j < static_cast<int>(col.size()); ++j)
1913 if(col[j]->page == active_page) {
1914 list.zones.push_back(new Zone_text_numeric(color, inter, score.stats[i].stats[col[j]->quel_stat].get_address(), px, y, col[j]->width-c_gap));
1915 px += col[j]->width;
1916 }
1917 y += 22;
1918 }
1919 }
1920 }
1921 if(score.player_count[team] > 1) {
1922 list.zones.push_back(new Zone_text(fteam[team], inter, "Total:", 15, y));
1923 int px = c_start;
1924 Font *color = fcourrier[team];
1925 for (int j = 0; j < static_cast<int>(col.size()); ++j)
1926 if (col[j]->page == active_page) {
1927 list.zones.push_back(new Zone_text_numeric(color, inter, score.team_stats[team].stats[col[j]->quel_stat].get_address(), px, y, col[j]->width-c_gap));
1928 px += col[j]->width;
1929 }
1930 y += 34;
1931 } else if(score.player_count[team] == 1) {
1932 y += 12; // leave space between the players/totals of each team
1933 }
1934 }
1935 video->need_paint = 2;
1936 }
1937
notify()1938 void Menu_stat::notify() {
1939 calculate_total(true);
1940 }
1941
init()1942 void Menu_stat::init() {
1943 set_fteam_color(pal);
1944 set_sort(0);
1945 Menu_standard::init();
1946 }
1947
step()1948 void Menu_stat::step() {
1949 Menu_standard::step();
1950 bool force_blit=false;
1951 //Add appropriate button(s)
1952 if(game->server && game->network && !game->terminated && !b_stop)
1953 b_stop = new Zone_text_button2(inter, bit, font2, "�2 End game", 8, 455);
1954 //Remove end-of-game button if already terminated
1955 if(b_stop && game->terminated) {
1956 delete b_stop;
1957 b_stop = NULL;
1958 // delete the rejoin button when deleting the stop button; it may
1959 // be recreated right after but at least it will be in the correct place
1960 delete b_restart;
1961 b_restart = NULL;
1962 video->need_paint = 2;
1963 }
1964 if(net->active && !game->server && !net->connected()) {
1965 delete b_restart;
1966 b_restart=NULL;
1967 }
1968 if(!playback && !b_restart) {
1969 if(game->server)
1970 if(game->terminated)
1971 b_restart = new Zone_text_button2(inter, bit, font2,
1972 "�2 Restart game", 8, 455);
1973 else
1974 b_restart = new Zone_text_button2(inter, bit, font2,
1975 "�2 Rejoin game",
1976 8+(b_stop? b_stop->w+4:0), 455);
1977 else
1978 if(net->active && net->connected())
1979 b_restart = new Zone_text_button2(inter, bit, font2,
1980 "�2 Rejoin game", 8, 455);
1981 }
1982 if(result) {
1983 if(result == b_quit)
1984 quit = true;
1985 if(result == b_stop) {
1986 if(!game->terminated)
1987 game->net_list.send_end_signal(false);
1988 }
1989 if(result == b_restart) {
1990 if(game->server) {
1991 if(game->terminated) {
1992 game->stop_stuff();
1993 game->restart();
1994 }
1995 else
1996 game->abort = false;
1997 exec(new Call_setfont(pal, new Multi_player_launcher()));
1998 }
1999 else {
2000 //We're not server but we want to restart, drop all players
2001 int i;
2002 for(i=0; i<MAXPLAYERS; i++) {
2003 if(game->net_list.get(i)) {
2004 Packet_dropplayer p;
2005 p.player=i;
2006 p.reason=DROP_AUTO;
2007 game->net_list.drop_player(&p, false);
2008 }
2009 }
2010 //... and delete the game
2011 delete game;
2012 exec(new Join_game(bit, inter->font, font2, pal, NULL, 0, 0, true));
2013 }
2014 }
2015 for (int i = 0; i < static_cast<int>(col.size()); ++i) {
2016 if (result == col[i]->z_titre) {
2017 set_sort(i);
2018 force_blit = true;
2019 break;
2020 }
2021 }
2022 for (unsigned int i = 0; i < b_page.size(); ++i)
2023 if (result == b_page[i])
2024 change_page(i);
2025 }
2026 calculate_total(force_blit);
2027 }
2028
Menu_multi_checkip(Bitmap * bit,Font * font,Font * font2,const Palette & p)2029 Menu_multi_checkip::Menu_multi_checkip(Bitmap *bit, Font *font, Font *font2, const Palette& p) {
2030 pal = p;
2031 bit_ = bit;
2032 inter->set_font(font, false);
2033 new Zone_bitmap(inter, bit, 0, 0);
2034 new Zone_text(inter, "IP configuration of this computer", 20);
2035 cancel = new Zone_text_button2(inter, bit, font2, "Back �0", 560, 450);
2036 new Zone_text(inter, "Host name:", 170, 110);
2037 new Zone_text_field(inter, net->host_name, 310, 110, inter->font->width(net->host_name)+8);
2038 new Zone_text(inter, "IP address:", 170, 140);
2039 Zone_listbox *list;
2040 list = new Zone_listbox2(inter, bit, font2, NULL, 310, 140, 160, 200);
2041 vector<Dword>::const_iterator it;
2042 for (it = net->host_adr.begin(); it != net->host_adr.end(); ++it) {
2043 Net::stringaddress(st, *it);
2044 list->add_item(st);
2045 }
2046 }
2047
step()2048 void Menu_multi_checkip::step() {
2049 Menu::step();
2050 if(input->last_key.sym == SDLK_ESCAPE || result == cancel) {
2051 input->last_key.sym = SDLK_UNKNOWN;
2052 ret();
2053 }
2054 }
2055
Menu_multi_book(Bitmap * bit,Font * font,Font * font2,const Palette & p,const char * adr)2056 Menu_multi_book::Menu_multi_book(Bitmap *bit, Font *font, Font *font2, const Palette& p, const char *adr) {
2057 pal = p;
2058 bit_ = bit;
2059 font2_ = font2;
2060 inter->set_font(font, false);
2061 address = adr;
2062 new Zone_bitmap(inter, bit, 0, 0);
2063 cancel = new Zone_text_button2(inter, bit, font2, "Back �0", 560, 450);
2064 if(address) { // if connecting address already provided
2065 new Zone_text(inter, "Connect", 20);
2066 } else {
2067 new Zone_text(inter, "Address book", 20);
2068 for(int i=0; i<10; i++) {
2069 int y = 60 + i*36;
2070 new Zone_text_input(inter, pal, config.info.book[i], 255, 40, y, 460);
2071 b_connect[i] = new Zone_text_button2(inter, bit, font2, "Connect", 520, y);
2072 }
2073 }
2074 status = new Zone_text_field(inter, "", 6, 450, 540);
2075 looking = false;
2076 connect_failed = false;
2077 }
2078
init()2079 void Menu_multi_book::init() {
2080 Menu::init();
2081 if(address)
2082 call(new Fade_in(pal));
2083 }
2084
step()2085 void Menu_multi_book::step() {
2086 Menu::step();
2087 if(input->last_key.sym == SDLK_ESCAPE || result == cancel) {
2088 input->last_key.sym = SDLK_UNKNOWN;
2089 if(looking)
2090 net->gethostbyname_cancel();
2091 config.write();
2092 ret();
2093 }
2094 const char *connect_adr=NULL;
2095
2096 if(address) {
2097 if(!looking && !connect_failed) {
2098 connect_adr = address;
2099 }
2100 } else {
2101 for(int i=0; i<10; i++) {
2102 if(result == b_connect[i] && config.info.book[i][0] != 0) {
2103 connect_adr = config.info.book[i];
2104 break;
2105 }
2106 }
2107 }
2108 if(connect_adr) {
2109 if(looking)
2110 net->gethostbyname_cancel();
2111 Dword adr = net->getaddress(connect_adr);
2112 if(adr > 0) {
2113 call(new Join_game(bit_, inter->font, font2_, pal, NULL, adr, net->port_resolve, false));
2114 if(address)
2115 ret();
2116 } else {
2117 sprintf(st, "Looking for %s...", connect_adr);
2118 status->set_val(st);
2119 looking = true;
2120 }
2121 }
2122 if(looking) {
2123 if(net->name_resolve != (unsigned int)-1) {
2124 if(net->name_resolve == 0) {
2125 status->set_val("Unable to locate host. Please verify and try again.");
2126 looking = false;
2127 connect_failed = true;
2128 } else {
2129 status->set_val("");
2130 looking = false;
2131 call(new Join_game(bit_, inter->font, font2_, pal, NULL, net->name_resolve, net->port_resolve, false));
2132 if(address)
2133 ret();
2134 }
2135 net->name_resolve = (Dword)-1;
2136 }
2137 }
2138 }
2139
Menu_internet(const char * c)2140 Menu_internet::Menu_internet(const char *c): Menu() {
2141 command = c;
2142 new Zone_clear(inter);
2143 }
2144
init()2145 void Menu_internet::init() {
2146 Menu::init();
2147 }
2148
step()2149 void Menu_internet::step() {
2150 Menu::step();
2151 #ifdef UGS_DIRECTX
2152 ShellExecute(0, "open", command, NULL, NULL, SW_SHOWDEFAULT);
2153 #endif
2154 call(new Wait_time(200));
2155 ret();
2156 }
2157
Menu_startserver()2158 Menu_startserver::Menu_startserver() {
2159 {
2160 Res_doze res("multi.png");
2161 Png img(res);
2162 bit = new Bitmap(img);
2163 pal.load(img);
2164 }
2165 set_fteam_color(pal);
2166
2167 inter->set_font(new Font(*fonts.normal, pal, 255,255,255));
2168 (void)new Zone_clear(inter);
2169 }
2170
step()2171 void Menu_startserver::step() {
2172 exec(new Create_game_start(pal, bit, inter->font));
2173 }
2174
~Menu_startserver()2175 Menu_startserver::~Menu_startserver() {
2176 delete bit;
2177 }
2178
Menu_startconnect(const char * adr,bool rejoin)2179 Menu_startconnect::Menu_startconnect(const char *adr, bool rejoin) {
2180 {
2181 Res_doze res("multi.png");
2182 Png img(res);
2183 bit = new Bitmap(img);
2184 pal.load(img);
2185 }
2186 set_fteam_color(pal);
2187
2188 inter->set_font(new Font(*fonts.normal, pal, 255,255,255));
2189 font2 = new Font(*fonts.normal, pal, 255,255,0);
2190 (void)new Zone_clear(inter);
2191 if(rejoin)
2192 module = new Join_game(bit, inter->font, font2, pal, NULL, 0, 0, true);
2193 else
2194 module = new Menu_multi_book(bit, inter->font, font2, pal, adr);
2195 }
2196
step()2197 void Menu_startconnect::step() {
2198 call(new Fade_out(pal));
2199 exec(module);
2200 }
2201
~Menu_startconnect()2202 Menu_startconnect::~Menu_startconnect() {
2203 if(bit)
2204 delete bit;
2205 delete font2;
2206 }
2207