|
Atrinik Client 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00030 #include <global.h> 00031 00033 #define EYES_BLINK_TIME (10 * 1000) 00034 00035 #define EYES_BLINK_DELAY (200) 00036 00038 #define NEWS_MAX_WIDTH 455 00039 00040 #define NEWS_MAX_HEIGHT 260 00041 00042 #define NEWS_FONT FONT_SANS12 00043 00048 static size_t last_server_count = 0; 00049 00051 static curl_data *news_data = NULL; 00052 00054 static uint32 eyes_blink_ticks = 0; 00056 static uint8 eyes_draw = 1; 00057 00059 static int char_step = 0; 00061 static uint32 char_race_selected; 00063 static int char_gender_selected; 00065 static int char_points_left; 00067 static int char_points_assigned[7]; 00069 const int char_step_max = 2; 00070 00072 static progress_dots progress; 00073 00075 static void news_popup_draw_func(popup_struct *popup) 00076 { 00077 /* Got the news yet? */ 00078 if (popup->buf) 00079 { 00080 SDL_Rect box; 00081 list_struct *list = list_exists(LIST_NEWS); 00082 00083 box.w = popup->surface->w; 00084 box.h = 0; 00085 /* Show the news title. */ 00086 string_blt(popup->surface, FONT_SERIF12, list ? list->text[list->row_selected - 1][0] : "???", 0, 10, COLOR_HGOLD, TEXT_ALIGN_CENTER, &box); 00087 00088 box.w = NEWS_MAX_WIDTH; 00089 box.h = NEWS_MAX_HEIGHT; 00090 00091 /* Calculate number of last displayed lines. */ 00092 if (!popup->i[1]) 00093 { 00094 string_blt(NULL, NEWS_FONT, popup->buf, 10, 30, COLOR_WHITE, TEXT_WORD_WRAP | TEXT_MARKUP | TEXT_LINES_CALC, &box); 00095 popup->i[1] = box.y; 00096 popup->i[2] = box.h; 00097 box.h = NEWS_MAX_HEIGHT; 00098 } 00099 00100 /* Skip rows we scrolled past. */ 00101 box.y = popup->i[0]; 00102 /* Show the news. */ 00103 string_blt(popup->surface, NEWS_FONT, popup->buf, 10, 30, COLOR_WHITE, TEXT_WORD_WRAP | TEXT_MARKUP | TEXT_LINES_SKIP, &box); 00104 00105 box.x = Bitmaps[popup->bitmap_id]->bitmap->w - 30; 00106 box.y = Bitmaps[popup->bitmap_id]->bitmap->h / 2 - 50; 00107 /* Show scroll buttons. */ 00108 scroll_buttons_show(popup->surface, ScreenSurface->w / 2 - Bitmaps[popup->bitmap_id]->bitmap->w / 2 + box.x, ScreenSurface->h / 2 - Bitmaps[popup->bitmap_id]->bitmap->h / 2 + box.y, (int *) &popup->i[0], popup->i[2] - popup->i[1], popup->i[1], &box); 00109 return; 00110 } 00111 /* Haven't started downloading yet. */ 00112 else if (!popup->custom_data) 00113 { 00114 list_struct *list = list_exists(LIST_NEWS); 00115 char url[MAX_BUF], *id; 00116 CURL *curl; 00117 00118 /* Shouldn't happen... */ 00119 if (!list) 00120 { 00121 popup_destroy_visible(); 00122 return; 00123 } 00124 00125 /* Initialize cURL, escape the selected row's text and construct 00126 * the url to use for downloading. */ 00127 curl = curl_easy_init(); 00128 id = curl_easy_escape(curl, list->text[list->row_selected - 1][0], 0); 00129 snprintf(url, sizeof(url), "http://www.atrinik.org/client_news.php?news=%s", id); 00130 curl_free(id); 00131 curl_easy_cleanup(curl); 00132 00133 /* Start downloading. */ 00134 popup->custom_data = curl_download_start(url); 00135 } 00136 /* Downloading. */ 00137 else 00138 { 00139 /* Check if we finished yet. */ 00140 int ret = curl_download_finished(popup->custom_data); 00141 00142 /* Yes, we finished, store the string we got. */ 00143 if (ret == 1) 00144 { 00145 popup->buf = strdup(((curl_data *) popup->custom_data)->memory ? ((curl_data *) popup->custom_data)->memory : "???"); 00146 } 00147 00148 /* Free the cURL data if we finished. */ 00149 if (ret != 0) 00150 { 00151 curl_data_free(popup->custom_data); 00152 popup->custom_data = NULL; 00153 } 00154 } 00155 00156 /* Haven't downloaded the text yet, inform the user. */ 00157 string_blt(popup->surface, FONT_SERIF12, "Downloading news, please wait...", 10, 10, COLOR_WHITE, TEXT_ALIGN_CENTER, NULL); 00158 } 00159 00161 static int news_popup_event_func(popup_struct *popup, SDL_Event *event) 00162 { 00163 int old_i = popup->i[0]; 00164 00165 if (event->type == SDL_KEYDOWN) 00166 { 00167 /* Escape was pressed? */ 00168 if (event->key.keysym.sym == SDLK_ESCAPE) 00169 { 00170 /* Free the cURL data, if any. */ 00171 if (popup->custom_data) 00172 { 00173 curl_data_free(popup->custom_data); 00174 popup->custom_data = NULL; 00175 } 00176 } 00177 /* Scroll the text. */ 00178 else if (event->key.keysym.sym == SDLK_DOWN) 00179 { 00180 popup->i[0]++; 00181 } 00182 else if (event->key.keysym.sym == SDLK_UP) 00183 { 00184 popup->i[0]--; 00185 } 00186 else if (event->key.keysym.sym == SDLK_PAGEUP) 00187 { 00188 popup->i[0] -= NEWS_MAX_HEIGHT / FONT_HEIGHT(NEWS_FONT); 00189 } 00190 else if (event->key.keysym.sym == SDLK_PAGEDOWN) 00191 { 00192 popup->i[0] += NEWS_MAX_HEIGHT / FONT_HEIGHT(NEWS_FONT); 00193 } 00194 } 00195 /* Mouse wheel? */ 00196 else if (event->type == SDL_MOUSEBUTTONDOWN) 00197 { 00198 if (event->button.button == SDL_BUTTON_WHEELDOWN) 00199 { 00200 popup->i[0]++; 00201 } 00202 else if (event->button.button == SDL_BUTTON_WHEELUP) 00203 { 00204 popup->i[0]--; 00205 } 00206 } 00207 00208 /* Scroll value was changed, verify it's in range. */ 00209 if (old_i != popup->i[0]) 00210 { 00211 if (!popup->buf) 00212 { 00213 popup->i[0] = old_i; 00214 } 00215 else if (popup->i[0] < 0) 00216 { 00217 popup->i[0] = 0; 00218 } 00219 else if (popup->i[0] > popup->i[2] - popup->i[1]) 00220 { 00221 popup->i[0] = popup->i[2] - popup->i[1]; 00222 } 00223 } 00224 00225 return -1; 00226 } 00227 00232 static void char_creation_reset(list_struct *list) 00233 { 00234 /* Reset race. */ 00235 if (char_step == 0) 00236 { 00237 char_race_selected = 0; 00238 } 00239 00240 /* Reset gender. */ 00241 if (char_step == 0 || char_step == 1) 00242 { 00243 char_gender_selected = 0; 00244 } 00245 00246 /* Reset assigned points. */ 00247 if (char_step == 0 || char_step == 2) 00248 { 00249 memset(&char_points_assigned, 0, sizeof(char_points_assigned)); 00250 } 00251 00252 /* Can we actually go back? */ 00253 if (char_step) 00254 { 00255 char_step--; 00256 } 00257 00258 if (list) 00259 { 00260 list_remove(list); 00261 } 00262 } 00263 00268 static void char_creation_enter(list_struct *list) 00269 { 00270 char buf[MAX_BUF]; 00271 00272 /* Picked race. */ 00273 if (char_step == 0) 00274 { 00275 char_race_selected = list->row_selected - 1; 00276 } 00277 /* Picked gender. */ 00278 else if (char_step == 1) 00279 { 00280 /* This is more complicated than the above, because we have to 00281 * change the gender's first letter back to lowercase, and find 00282 * its ID. */ 00283 strncpy(buf, list->text[list->row_selected - 1][0], sizeof(buf) - 1); 00284 buf[0] = tolower(buf[0]); 00285 buf[sizeof(buf) - 1] = '\0'; 00286 char_gender_selected = gender_to_id(buf); 00287 /* Initialize maximum stat points that can be assigned. */ 00288 char_points_left = s_settings->characters[char_race_selected].points_max; 00289 } 00290 /* Selected stats, create the character. */ 00291 else if (char_step == 2) 00292 { 00293 if (char_points_left) 00294 { 00295 return; 00296 } 00297 00298 snprintf(buf, sizeof(buf), "nc %s %d %d %d %d %d %d %d", s_settings->characters[char_race_selected].gender_archetypes[char_gender_selected], s_settings->characters[char_race_selected].stats_base[0] + char_points_assigned[0], s_settings->characters[char_race_selected].stats_base[1] + char_points_assigned[1], s_settings->characters[char_race_selected].stats_base[2] + char_points_assigned[2], s_settings->characters[char_race_selected].stats_base[3] + char_points_assigned[3], s_settings->characters[char_race_selected].stats_base[4] + char_points_assigned[4], s_settings->characters[char_race_selected].stats_base[5] + char_points_assigned[5], s_settings->characters[char_race_selected].stats_base[6] + char_points_assigned[6]); 00299 cs_write_string(buf, strlen(buf)); 00300 return; 00301 } 00302 00303 char_step++; 00304 00305 if (list) 00306 { 00307 list_remove(list); 00308 } 00309 } 00310 00317 static void char_stat_change(int stat_id, int adjust) 00318 { 00319 int points = s_settings->characters[char_race_selected].stats_base[stat_id] + char_points_assigned[stat_id]; 00320 00321 /* Add to stat, if possible. */ 00322 if (adjust > 0 && char_points_left && points < s_settings->characters[char_race_selected].stats_max[stat_id]) 00323 { 00324 char_points_assigned[stat_id]++; 00325 char_points_left--; 00326 } 00327 /* Subtract from stat, if possible. */ 00328 else if (adjust < 0 && points > s_settings->characters[char_race_selected].stats_min[stat_id]) 00329 { 00330 char_points_assigned[stat_id]--; 00331 char_points_left++; 00332 } 00333 } 00334 00336 static int char_creation_key(list_struct *list, SDLKey key) 00337 { 00338 switch (key) 00339 { 00340 /* Change selected stats using left/right arrow keys. */ 00341 case SDLK_RIGHT: 00342 case SDLK_LEFT: 00343 char_stat_change(list->row_selected - 1, key == SDLK_LEFT ? -1 : 1); 00344 return 1; 00345 00346 default: 00347 return -1; 00348 } 00349 } 00350 00352 static void popup_draw_func_post(popup_struct *popup) 00353 { 00354 list_struct *list = NULL; 00355 size_t i; 00356 int face = 0, x, y; 00357 SDL_Rect box; 00358 00359 x = popup->x; 00360 y = popup->y; 00361 00362 /* Not creating character, only show the message text window. */ 00363 if (GameStatus != GAME_STATUS_NEW_CHAR) 00364 { 00365 textwin_show(x + Bitmaps[popup->bitmap_id]->bitmap->w / 2, y + 30, 220, 132); 00366 return; 00367 } 00368 00369 list = list_exists(LIST_CREATION); 00370 00371 y += 50; 00372 00373 if (char_step == 2) 00374 { 00375 y += 40; 00376 } 00377 00378 if (!list) 00379 { 00380 /* Create a new list. */ 00381 list = list_create(LIST_CREATION, 7, 1, 0); 00382 list_set_focus(list); 00383 list->handle_enter_func = char_creation_enter; 00384 00385 /* Show list of races. */ 00386 if (char_step == 0) 00387 { 00388 list_set_column(list, 0, 250, 7, NULL, -1); 00389 00390 for (i = 0; i < s_settings->num_characters; i++) 00391 { 00392 list_add(list, i, 0, s_settings->characters[i].name); 00393 } 00394 } 00395 /* List of genders. */ 00396 else if (char_step == 1) 00397 { 00398 char buf[30]; 00399 size_t row = 0; 00400 00401 list_set_column(list, 0, 250, 7, NULL, -1); 00402 00403 for (i = 0; i < GENDER_MAX; i++) 00404 { 00405 /* Does the selected race have this gender? */ 00406 if (s_settings->characters[char_race_selected].gender_archetypes[i]) 00407 { 00408 /* Uppercase the first letter of the gender's name 00409 * and add it to the list. */ 00410 strncpy(buf, gender_noun[i], sizeof(buf) - 1); 00411 buf[0] = toupper(buf[0]); 00412 buf[sizeof(buf) - 1] = '\0'; 00413 list_add(list, row, 0, buf); 00414 row++; 00415 } 00416 } 00417 } 00418 /* The stats. */ 00419 else if (char_step == 2) 00420 { 00421 list_set_column(list, 0, 30, 7, NULL, -1); 00422 list->y += 2; 00423 list->row_height_adjust = 6; 00424 list->row_color_func = NULL; 00425 list->row_highlight_func = NULL; 00426 list->row_selected_func = NULL; 00427 list->draw_frame_func = NULL; 00428 list->key_event_func = char_creation_key; 00429 list_add(list, 0, 0, "STR:"); 00430 list_add(list, 1, 0, "DEX:"); 00431 list_add(list, 2, 0, "CON:"); 00432 list_add(list, 3, 0, "INT:"); 00433 list_add(list, 4, 0, "WIS:"); 00434 list_add(list, 5, 0, "POW:"); 00435 list_add(list, 6, 0, "CHA:"); 00436 } 00437 } 00438 00439 list_show(list, x + 20, y); 00440 00441 /* Race picking, pick first possible gender. */ 00442 if (char_step == 0) 00443 { 00444 box.w = 460; 00445 box.h = 96; 00446 string_blt(ScreenSurface, FONT_SERIF12, s_settings->characters[list->row_selected - 1].desc, x + 20, y + 125, COLOR_WHITE, TEXT_WORD_WRAP | TEXT_MARKUP, &box); 00447 00448 for (i = 0; i < GENDER_MAX; i++) 00449 { 00450 /* Does the selected race have this gender? */ 00451 if (s_settings->characters[list->row_selected - 1].gender_archetypes[i]) 00452 { 00453 face = get_bmap_id(s_settings->characters[list->row_selected - 1].gender_faces[i]); 00454 break; 00455 } 00456 } 00457 } 00458 else if (char_step == 1) 00459 { 00460 char buf[MAX_BUF]; 00461 00462 strncpy(buf, list->text[list->row_selected - 1][0], sizeof(buf) - 1); 00463 buf[0] = tolower(buf[0]); 00464 buf[sizeof(buf) - 1] = '\0'; 00465 face = get_bmap_id(s_settings->characters[char_race_selected].gender_faces[gender_to_id(buf)]); 00466 } 00467 00468 if (char_step == 2) 00469 { 00470 box.w = 370; 00471 box.h = 150; 00472 string_blt(ScreenSurface, FONT_ARIAL10, s_settings->text[SERVER_TEXT_STATS], x + 116, y + 10, COLOR_WHITE, TEXT_WORD_WRAP | TEXT_MARKUP, &box); 00473 } 00474 else 00475 { 00476 blit_face(face, x + 300, y + 35); 00477 } 00478 00479 /* Show the stat values and the range buttons. */ 00480 if (char_step == 2) 00481 { 00482 int adjust = 0; 00483 00484 for (i = 0; i < NUM_STATS; i++) 00485 { 00486 /* Calculate the current stat value and show it. */ 00487 string_blt_shadow_format(ScreenSurface, FONT_ARIAL12, x + 60, y + 10 + i * 18 + 4, i == list->row_selected - 1 ? COLOR_GREEN : COLOR_HGOLD, COLOR_BLACK, 0, NULL, "%.2d", s_settings->characters[char_race_selected].stats_base[i] + char_points_assigned[i]); 00488 00489 /* One of the range buttons clicked? */ 00490 if (range_buttons_show(x + 80, y + 10 + i * 18, &adjust, 1)) 00491 { 00492 char_stat_change(i, adjust); 00493 } 00494 } 00495 00496 string_blt_shadow(ScreenSurface, FONT_SANS12, "Left:", x + 20, y + 150, COLOR_WHITE, COLOR_BLACK, 0, NULL); 00497 string_blt_shadow_format(ScreenSurface, FONT_ARIAL12, x + 60, y + 150, COLOR_HGOLD, COLOR_BLACK, 0, NULL, "%d", char_points_left); 00498 } 00499 00500 y += 100; 00501 00502 if (char_step == 2) 00503 { 00504 y += 70; 00505 } 00506 00507 /* Show previous button if we're not in the first step. */ 00508 if (char_step > 0) 00509 { 00510 if (button_show(BITMAP_BUTTON, -1, BITMAP_BUTTON_DOWN, x + 19, y, "Previous", FONT_ARIAL10, COLOR_WHITE, COLOR_BLACK, COLOR_HGOLD, COLOR_BLACK, 0)) 00511 { 00512 char_creation_reset(list); 00513 } 00514 } 00515 00516 /* Show the next button, or the play button if we're in the last step. */ 00517 if (button_show(BITMAP_BUTTON, -1, BITMAP_BUTTON_DOWN, x + (char_step == char_step_max ? 90 : 220), y, char_step == char_step_max ? "Play" : "Next", FONT_ARIAL10, COLOR_WHITE, COLOR_BLACK, COLOR_HGOLD, COLOR_BLACK, 0)) 00518 { 00519 char_creation_enter(list); 00520 } 00521 } 00522 00526 static void popup_draw_func(popup_struct *popup) 00527 { 00528 uint8 downloading; 00529 SDL_Rect box; 00530 char buf[MAX_BUF]; 00531 int x, y; 00532 00533 /* Waiting to log in. */ 00534 if (GameStatus == GAME_STATUS_WAITFORPLAY) 00535 { 00536 box.w = Bitmaps[popup->bitmap_id]->bitmap->w; 00537 box.h = Bitmaps[popup->bitmap_id]->bitmap->h; 00538 string_blt_shadow(popup->surface, FONT_SERIF12, "Logging in, please wait...", 0, 0, COLOR_HGOLD, COLOR_BLACK, TEXT_ALIGN_CENTER | TEXT_VALIGN_CENTER, &box); 00539 return; 00540 } 00541 else if (GameStatus == GAME_STATUS_NEW_CHAR) 00542 { 00543 box.w = Bitmaps[popup->bitmap_id]->bitmap->w; 00544 box.h = 0; 00545 string_blt_shadow_format(popup->surface, FONT_SERIF14, 0, 10, COLOR_HGOLD, COLOR_BLACK, TEXT_ALIGN_CENTER, &box, "Welcome, %s!", cpl.name); 00546 box.w = Bitmaps[popup->bitmap_id]->bitmap->w - 40; 00547 box.h = char_step == 2 ? 70 : 30; 00548 string_blt_shadow(popup->surface, FONT_ARIAL12, s_settings->text[SERVER_TEXT_STEP0 + char_step], 20, 30, COLOR_WHITE, COLOR_BLACK, TEXT_MARKUP | TEXT_WORD_WRAP, &box); 00549 return; 00550 } 00551 /* Playing now, so destroy this popup and remove any lists. */ 00552 else if (GameStatus == GAME_STATUS_PLAY) 00553 { 00554 popup_destroy_visible(); 00555 list_remove_all(); 00556 return; 00557 } 00558 /* Connection terminated while we were trying to login. */ 00559 else if (GameStatus <= GAME_STATUS_WAITLOOP) 00560 { 00561 popup_destroy_visible(); 00562 return; 00563 } 00564 00565 /* Downloading the files, or updates haven't finished yet? */ 00566 downloading = GameStatus < GAME_STATUS_LOGIN || !file_updates_finished(); 00567 00568 progress.done = !downloading; 00569 progress_dots_show(&progress, popup->surface, 75, 30); 00570 00571 /* Show that we are connecting to the server. */ 00572 box.w = Bitmaps[popup->bitmap_id]->bitmap->w; 00573 box.h = 0; 00574 string_blt_shadow(popup->surface, FONT_SERIF12, "Connecting to server, please wait...", 0, 10, COLOR_HGOLD, COLOR_BLACK, TEXT_ALIGN_CENTER, &box); 00575 00576 if (downloading) 00577 { 00578 return; 00579 } 00580 00581 box.w = Bitmaps[popup->bitmap_id]->bitmap->w / 2; 00582 x = Bitmaps[popup->bitmap_id]->bitmap->w / 4 - text_input_center_offset(); 00583 y = 75; 00584 00585 /* Player name. */ 00586 if (GameStatus == GAME_STATUS_NAME) 00587 { 00588 string_blt(popup->surface, FONT_ARIAL10, "Enter your name", 0, 55, COLOR_HGOLD, TEXT_ALIGN_CENTER, &box); 00589 text_input_string[0] = toupper(text_input_string[0]); 00590 text_input_show(popup->surface, x, y, FONT_ARIAL10, text_input_string, COLOR_WHITE, 0, BITMAP_LOGIN_INP, NULL); 00591 } 00592 else if (cpl.name[0]) 00593 { 00594 cpl.name[0] = toupper(cpl.name[0]); 00595 text_input_draw_background(popup->surface, x, y, BITMAP_LOGIN_INP); 00596 text_input_draw_text(popup->surface, x, y, FONT_ARIAL10, cpl.name, COLOR_WHITE, 0, BITMAP_LOGIN_INP, NULL); 00597 } 00598 00599 y += 35; 00600 00601 /* Player password. */ 00602 if (GameStatus == GAME_STATUS_PSWD || cpl.password[0]) 00603 { 00604 char *cp; 00605 00606 strncpy(buf, GameStatus == GAME_STATUS_PSWD ? text_input_string : cpl.password, sizeof(buf) - 1); 00607 00608 for (cp = buf; *cp; cp++) 00609 { 00610 *cp = '*'; 00611 } 00612 00613 if (GameStatus == GAME_STATUS_PSWD) 00614 { 00615 string_blt(popup->surface, FONT_ARIAL10, "Enter your password", 0, 95, COLOR_HGOLD, TEXT_ALIGN_CENTER, &box); 00616 text_input_show(popup->surface, x, y, FONT_ARIAL10, buf, COLOR_WHITE, 0, BITMAP_LOGIN_INP, NULL); 00617 } 00618 else 00619 { 00620 text_input_draw_background(popup->surface, x, y, BITMAP_LOGIN_INP); 00621 text_input_draw_text(popup->surface, x, y, FONT_ARIAL10, buf, COLOR_WHITE, 0, BITMAP_LOGIN_INP, NULL); 00622 } 00623 } 00624 00625 y += 35; 00626 00627 /* Verify password for character creation. */ 00628 if (GameStatus == GAME_STATUS_VERIFYPSWD) 00629 { 00630 char *cp; 00631 00632 strncpy(buf, text_input_string, sizeof(buf) - 1); 00633 00634 for (cp = buf; *cp; cp++) 00635 { 00636 *cp = '*'; 00637 } 00638 00639 string_blt(popup->surface, FONT_ARIAL10, "New Character: Verify Password", 0, 130, COLOR_HGOLD, TEXT_ALIGN_CENTER, &box); 00640 text_input_show(popup->surface, x, y, FONT_ARIAL10, buf, COLOR_WHITE, 0, BITMAP_LOGIN_INP, NULL); 00641 char_step = 0; 00642 char_creation_reset(NULL); 00643 } 00644 00645 y += 20; 00646 00647 box.w = Bitmaps[popup->bitmap_id]->bitmap->w - 45; 00648 box.h = 120; 00649 string_blt_shadow(popup->surface, FONT_ARIAL12, s_settings->text[SERVER_TEXT_LOGIN], x, y, COLOR_WHITE, COLOR_BLACK, TEXT_MARKUP | TEXT_WORD_WRAP, &box); 00650 } 00651 00653 static int popup_destroy_callback_func(popup_struct *popup) 00654 { 00655 list_struct *list = list_exists(LIST_CREATION); 00656 00657 (void) popup; 00658 00659 if (list) 00660 { 00661 list_remove(list); 00662 list_set_focus(list_exists(LIST_SERVERS)); 00663 } 00664 00665 if (GameStatus != GAME_STATUS_PLAY) 00666 { 00667 GameStatus = GAME_STATUS_START; 00668 } 00669 00670 return 1; 00671 } 00672 00674 static int popup_event_func(popup_struct *popup, SDL_Event *event) 00675 { 00676 (void) popup; 00677 00678 /* Handle events in character creation. */ 00679 if (GameStatus == GAME_STATUS_NEW_CHAR) 00680 { 00681 list_struct *list = list_exists(LIST_CREATION); 00682 00683 /* Handle list events. */ 00684 if (list) 00685 { 00686 if (event->type == SDL_KEYDOWN || event->type == SDL_KEYUP) 00687 { 00688 if (lists_handle_keyboard(&event->key)) 00689 { 00690 return 1; 00691 } 00692 } 00693 else 00694 { 00695 if (list_handle_mouse(list, event->motion.x, event->motion.y, event)) 00696 { 00697 return 1; 00698 } 00699 } 00700 } 00701 } 00702 00703 if (event->type == SDL_KEYDOWN) 00704 { 00705 /* Try to handle text input. */ 00706 if (text_input_handle(&event->key)) 00707 { 00708 return 1; 00709 } 00710 00711 /* Ignore. */ 00712 return 0; 00713 } 00714 00715 return -1; 00716 } 00717 00721 static void list_handle_enter(list_struct *list) 00722 { 00723 /* Servers list? */ 00724 if (list->id == LIST_SERVERS) 00725 { 00726 /* Get selected server. */ 00727 selected_server = server_get_id(list->row_selected - 1); 00728 00729 /* Valid server, start connecting. */ 00730 if (selected_server) 00731 { 00732 popup_struct *popup = popup_create(BITMAP_POPUP); 00733 00734 popup->draw_func = popup_draw_func; 00735 popup->draw_func_post = popup_draw_func_post; 00736 popup->event_func = popup_event_func; 00737 popup->destroy_callback_func = popup_destroy_callback_func; 00738 GameStatus = GAME_STATUS_STARTCONNECT; 00739 progress_dots_create(&progress); 00740 } 00741 } 00742 else if (list->id == LIST_NEWS) 00743 { 00744 if (list->text && list->text[list->row_selected - 1]) 00745 { 00746 popup_struct *popup = popup_create(BITMAP_POPUP); 00747 00748 popup->draw_func = news_popup_draw_func; 00749 popup->event_func = news_popup_event_func; 00750 } 00751 } 00752 } 00753 00755 static void list_handle_esc(list_struct *list) 00756 { 00757 (void) list; 00758 00759 system_end(); 00760 exit(0); 00761 } 00762 00766 void show_meta_server() 00767 { 00768 int x, y; 00769 list_struct *list; 00770 size_t server_count; 00771 server_struct *node; 00772 char buf[MAX_BUF]; 00773 SDL_Rect box; 00774 00775 /* Active popup, no need to do anything. */ 00776 if (popup_get_visible() && !popup_overlay_need_update(popup_get_visible())) 00777 { 00778 return; 00779 } 00780 00781 x = 15; 00782 y = ScreenSurface->h - Bitmaps[BITMAP_SERVERS_BG]->bitmap->h - 5; 00783 00784 /* Background */ 00785 sprite_blt(Bitmaps[BITMAP_INTRO], 0, 0, NULL, NULL); 00786 textwin_show(Bitmaps[BITMAP_INTRO]->bitmap->w, 1, ScreenSurface->w - Bitmaps[BITMAP_INTRO]->bitmap->w - 2, ScreenSurface->h - 3); 00787 sprite_blt(Bitmaps[BITMAP_SERVERS_BG], x, y, NULL, NULL); 00788 00789 list = list_exists(LIST_SERVERS); 00790 server_count = server_get_count(); 00791 00792 /* List doesn't exist or the count changed? Create new list. */ 00793 if (!list || last_server_count != server_count) 00794 { 00795 size_t i; 00796 00797 /* Remove it if it exists already. */ 00798 if (list) 00799 { 00800 list_remove(list); 00801 } 00802 00803 /* Create the servers list. */ 00804 list = list_create(LIST_SERVERS, 11, 3, 8); 00805 list->handle_enter_func = list_handle_enter; 00806 list->handle_esc_func = list_handle_esc; 00807 list_scrollbar_enable(list); 00808 list_set_column(list, 0, 295, 7, "Server", -1); 00809 list_set_column(list, 1, 50, 9, "Port", 1); 00810 list_set_column(list, 2, 48, 7, "Players", 1); 00811 00812 /* Add the servers to the list. */ 00813 for (i = 0; i < server_count; i++) 00814 { 00815 node = server_get_id(i); 00816 00817 list_add(list, i, 0, node->name); 00818 snprintf(buf, sizeof(buf), "%d", node->port); 00819 list_add(list, i, 1, buf); 00820 00821 if (node->player >= 0) 00822 { 00823 snprintf(buf, sizeof(buf), "%d", node->player); 00824 } 00825 else 00826 { 00827 strcpy(buf, "-"); 00828 } 00829 00830 list_add(list, i, 2, buf); 00831 } 00832 00833 /* Update the focus if we re-created the list, since it's no 00834 * longer the first one in the list. */ 00835 if (last_server_count != server_count) 00836 { 00837 list_set_focus(list); 00838 } 00839 00840 /* Store the new count. */ 00841 last_server_count = server_count; 00842 } 00843 00844 /* Actually draw the list. */ 00845 list_show(list, x + 12, y + 8); 00846 node = server_get_id(list->row_selected - 1); 00847 00848 /* Do we have any selected server? If so, show its version and 00849 * description. */ 00850 if (node) 00851 { 00852 snprintf(buf, sizeof(buf), "Version: %s", node->version); 00853 string_blt_shadow(ScreenSurface, FONT_ARIAL10, buf, x + 13, y + 185, COLOR_HGOLD, COLOR_BLACK, 0, NULL); 00854 00855 box.w = 410; 00856 box.h = 48; 00857 string_blt(ScreenSurface, FONT_ARIAL10, node->desc, x + 13, y + 197, COLOR_WHITE, TEXT_WORD_WRAP | TEXT_MARKUP, &box); 00858 } 00859 00860 /* Show whether we are connecting to the metaserver or not. */ 00861 if (ms_connecting(-1)) 00862 { 00863 string_blt_shadow(ScreenSurface, FONT_ARIAL10, "Connecting to metaserver, please wait...", x + 105, y + 8, COLOR_HGOLD, COLOR_BLACK, 0, NULL); 00864 } 00865 else 00866 { 00867 string_blt_shadow(ScreenSurface, FONT_ARIAL10, "Select a server.", x + 226, y + 8, COLOR_GREEN, COLOR_BLACK, 0, NULL); 00868 } 00869 00870 sprite_blt(Bitmaps[BITMAP_SERVERS_BG_OVER], x, y, NULL, NULL); 00871 00872 x += Bitmaps[BITMAP_SERVERS_BG_OVER]->bitmap->w + 20; 00873 sprite_blt(Bitmaps[BITMAP_NEWS_BG], x, y, NULL, NULL); 00874 00875 box.w = Bitmaps[BITMAP_NEWS_BG]->bitmap->w; 00876 box.h = 0; 00877 string_blt_shadow(ScreenSurface, FONT_SERIF12, "Game News", x, y + 10, COLOR_HGOLD, COLOR_BLACK, TEXT_ALIGN_CENTER, &box); 00878 00879 list = list_exists(LIST_NEWS); 00880 00881 /* No list yet, make one and start downloading the data. */ 00882 if (!list) 00883 { 00884 /* Start downloading. */ 00885 news_data = curl_download_start("http://www.atrinik.org/client_news.php"); 00886 00887 list = list_create(LIST_NEWS, 18, 1, 8); 00888 list->handle_enter_func = list_handle_enter; 00889 list->handle_esc_func = list_handle_esc; 00890 list_set_column(list, 0, 150, 7, NULL, -1); 00891 list_set_font(list, FONT_ARIAL10); 00892 } 00893 00894 /* Download in progress? */ 00895 if (news_data) 00896 { 00897 /* Get the status. */ 00898 int ret = curl_download_finished(news_data); 00899 00900 /* Finished downloading, parse the data. */ 00901 if (ret == 1) 00902 { 00903 char *mem = strdup(news_data->memory ? news_data->memory : "???"), *cp; 00904 size_t i = 0; 00905 00906 cp = strtok(mem, "\n"); 00907 00908 while (cp) 00909 { 00910 list_add(list, i, 0, cp); 00911 i++; 00912 cp = strtok(NULL, "\n"); 00913 } 00914 00915 free(mem); 00916 } 00917 00918 /* Finished downloading or there was an error: clean up in either 00919 * case. */ 00920 if (ret != 0) 00921 { 00922 curl_data_free(news_data); 00923 news_data = NULL; 00924 } 00925 } 00926 00927 /* Show the news list. */ 00928 list_show(list, x + 13, y + 10); 00929 00930 /* Calculate whether to show the eyes or not. Blinks every 00931 * EYES_BLINK_TIME ticks, then waits EYES_BLINK_DELAY ticks until 00932 * showing the eyes again. */ 00933 if (SDL_GetTicks() - eyes_blink_ticks >= (eyes_draw ? EYES_BLINK_TIME : EYES_BLINK_DELAY)) 00934 { 00935 eyes_blink_ticks = SDL_GetTicks(); 00936 eyes_draw = !eyes_draw; 00937 } 00938 00939 if (eyes_draw) 00940 { 00941 sprite_blt(Bitmaps[BITMAP_EYES], Bitmaps[BITMAP_INTRO]->bitmap->w - 90, 310, NULL, NULL); 00942 } 00943 00944 /* Show the play button. */ 00945 if (button_show(BITMAP_BUTTON, -1, BITMAP_BUTTON_DOWN, 489, y + 10, "Play", FONT_ARIAL10, COLOR_WHITE, COLOR_BLACK, COLOR_HGOLD, COLOR_BLACK, 0)) 00946 { 00947 list_handle_enter(list_exists(LIST_SERVERS)); 00948 } 00949 00950 if (button_show(BITMAP_BUTTON, -1, BITMAP_BUTTON_DOWN, 489, y + 35, "Refresh", FONT_ARIAL10, COLOR_WHITE, COLOR_BLACK, COLOR_HGOLD, COLOR_BLACK, 0)) 00951 { 00952 if (!ms_connecting(-1)) 00953 { 00954 GameStatus = GAME_STATUS_META; 00955 } 00956 } 00957 00958 if (button_show(BITMAP_BUTTON, -1, BITMAP_BUTTON_DOWN, 489, y + 60, "Settings", FONT_ARIAL10, COLOR_WHITE, COLOR_BLACK, COLOR_HGOLD, COLOR_BLACK, 0)) 00959 { 00960 settings_open(); 00961 } 00962 00963 if (button_show(BITMAP_BUTTON, -1, BITMAP_BUTTON_DOWN, 489, y + 85, "Update", FONT_ARIAL10, COLOR_WHITE, COLOR_BLACK, COLOR_HGOLD, COLOR_BLACK, 0)) 00964 { 00965 updater_open(); 00966 } 00967 00968 if (button_show(BITMAP_BUTTON, -1, BITMAP_BUTTON_DOWN, 489, y + 110, "Help", FONT_ARIAL10, COLOR_WHITE, COLOR_BLACK, COLOR_HGOLD, COLOR_BLACK, 0)) 00969 { 00970 show_help("main screen"); 00971 } 00972 00973 if (button_show(BITMAP_BUTTON, -1, BITMAP_BUTTON_DOWN, 489, y + 228, "Quit", FONT_ARIAL10, COLOR_WHITE, COLOR_BLACK, COLOR_HGOLD, COLOR_BLACK, 0)) 00974 { 00975 system_end(); 00976 exit(0); 00977 } 00978 }
1.7.4