|
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 00035 enum 00036 { 00038 SPELLS_FILTER_SPELL, 00040 SPELLS_FILTER_PRAYER, 00042 SPELLS_FILTER_ALL 00043 }; 00044 00053 static spell_entry_struct **spell_list[SPELL_PATH_NUM]; 00055 static size_t spell_list_num[SPELL_PATH_NUM]; 00057 static size_t spell_list_path = 0; 00059 static uint8 spell_list_filter_known; 00061 static uint8 spell_list_filter_type; 00062 00064 static const char *const filter_names[SPELLS_FILTER_ALL + 1] = 00065 { 00066 "Spells", "Prayers", "All" 00067 }; 00068 00070 static button_struct button_path_left, button_path_right, button_close, button_filter_left, button_filter_right, button_filter_known, button_help; 00071 00075 static void list_handle_enter(list_struct *list) 00076 { 00077 /* Ready the selected spell, if any. */ 00078 if (list->text) 00079 { 00080 char buf[MAX_BUF]; 00081 00082 snprintf(buf, sizeof(buf), "/ready_spell %s", list->text[list->row_selected - 1][0]); 00083 client_command_check(buf); 00084 } 00085 } 00086 00089 static const char *list_text_color_hook(list_struct *list, const char *default_color, uint32 row, uint32 col) 00090 { 00091 size_t spell_id; 00092 spell_entry_struct *spell; 00093 00094 /* If the spell is not known, use gray instead of the default color. */ 00095 if (spell_find_path_selected(list->text[row][col], &spell_id)) 00096 { 00097 spell = spell_get(spell_list_path, spell_id); 00098 00099 if (!spell->known) 00100 { 00101 return COLOR_GRAY; 00102 } 00103 } 00104 00105 return default_color; 00106 } 00107 00111 static void spell_list_reload() 00112 { 00113 list_struct *list; 00114 size_t i; 00115 uint32 offset, rows, selected; 00116 00117 list = list_exists(LIST_SPELLS); 00118 00119 if (!list) 00120 { 00121 return; 00122 } 00123 00124 offset = list->row_offset; 00125 selected = list->row_selected; 00126 rows = list->rows; 00127 list_clear(list); 00128 00129 for (i = 0; i < spell_list_num[spell_list_path]; i++) 00130 { 00131 if (spell_list_filter_known && !spell_list[spell_list_path][i]->known) 00132 { 00133 continue; 00134 } 00135 00136 if (spell_list_filter_type != SPELLS_FILTER_ALL) 00137 { 00138 if (spell_list_filter_type == SPELLS_FILTER_SPELL && spell_list[spell_list_path][i]->type != SPELLS_FILTER_SPELL) 00139 { 00140 continue; 00141 } 00142 00143 if (spell_list_filter_type == SPELLS_FILTER_PRAYER && spell_list[spell_list_path][i]->type != SPELLS_FILTER_PRAYER) 00144 { 00145 continue; 00146 } 00147 } 00148 00149 list_add(list, list->rows, 0, spell_list[spell_list_path][i]->name); 00150 } 00151 00152 list_sort(list, LIST_SORT_ALPHA); 00153 00154 if (list->rows == rows) 00155 { 00156 list->row_offset = offset; 00157 list->row_selected = selected; 00158 } 00159 00160 cur_widget[SPELLS_ID]->redraw = 1; 00161 } 00162 00166 static void button_repeat_func(button_struct *button) 00167 { 00168 int path = spell_list_path; 00169 00170 if (button == &button_path_left) 00171 { 00172 path--; 00173 } 00174 else 00175 { 00176 path++; 00177 } 00178 00179 if (path < 0) 00180 { 00181 path = SPELL_PATH_NUM - 1; 00182 } 00183 else if (path > SPELL_PATH_NUM - 1) 00184 { 00185 path = 0; 00186 } 00187 00188 spell_list_path = path; 00189 spell_list_reload(); 00190 } 00191 00196 static void button_filter_adjust(int adj) 00197 { 00198 int type = spell_list_filter_type + adj; 00199 00200 if (type < 0) 00201 { 00202 type = SPELLS_FILTER_ALL; 00203 } 00204 else if (type > SPELLS_FILTER_ALL) 00205 { 00206 type = 0; 00207 } 00208 00209 spell_list_filter_type = type; 00210 spell_list_reload(); 00211 } 00212 00216 void widget_spells_render(widgetdata *widget) 00217 { 00218 list_struct *list; 00219 SDL_Rect box, box2; 00220 00221 /* Create the surface. */ 00222 if (!widget->widgetSF) 00223 { 00224 widget->widgetSF = SDL_ConvertSurface(Bitmaps[BITMAP_CONTENT]->bitmap, Bitmaps[BITMAP_CONTENT]->bitmap->format, Bitmaps[BITMAP_CONTENT]->bitmap->flags); 00225 } 00226 00227 list = list_exists(LIST_SPELLS); 00228 00229 /* Create the spell list. */ 00230 if (!list) 00231 { 00232 spell_list_filter_known = 0; 00233 spell_list_filter_type = SPELLS_FILTER_ALL; 00234 00235 list = list_create(LIST_SPELLS, 12, 1, 8); 00236 list->handle_enter_func = list_handle_enter; 00237 list->text_color_hook = list_text_color_hook; 00238 list->surface = widget->widgetSF; 00239 list_scrollbar_enable(list); 00240 list_set_column(list, 0, 130, 7, NULL, -1); 00241 list_set_font(list, FONT_ARIAL10); 00242 spell_list_reload(); 00243 00244 /* Create various buttons... */ 00245 button_create(&button_path_left); 00246 button_create(&button_path_right); 00247 button_create(&button_close); 00248 button_create(&button_filter_left); 00249 button_create(&button_filter_right); 00250 button_create(&button_filter_known); 00251 button_create(&button_help); 00252 button_path_left.repeat_func = button_path_right.repeat_func = button_repeat_func; 00253 button_close.bitmap = button_path_left.bitmap = button_path_right.bitmap = button_filter_left.bitmap = button_filter_right.bitmap = button_help.bitmap = BITMAP_BUTTON_ROUND; 00254 button_close.bitmap_pressed = button_path_left.bitmap_pressed = button_path_right.bitmap_pressed = button_filter_left.bitmap_pressed = button_filter_right.bitmap_pressed = button_help.bitmap_pressed = BITMAP_BUTTON_ROUND_DOWN; 00255 } 00256 00257 if (widget->redraw) 00258 { 00259 _BLTFX bltfx; 00260 size_t spell_id; 00261 00262 bltfx.surface = widget->widgetSF; 00263 bltfx.flags = 0; 00264 bltfx.alpha = 0; 00265 sprite_blt(Bitmaps[BITMAP_CONTENT], 0, 0, NULL, &bltfx); 00266 00267 widget->redraw = 0; 00268 00269 box.h = 0; 00270 box.w = widget->wd; 00271 string_blt(widget->widgetSF, FONT_SERIF12, "Spells", 0, 3, COLOR_HGOLD, TEXT_ALIGN_CENTER, &box); 00272 list->focus = 1; 00273 list_set_parent(list, widget->x1, widget->y1); 00274 list_show(list, 10, 2); 00275 00276 box.w = 160; 00277 string_blt(widget->widgetSF, FONT_SERIF12, s_settings->spell_paths[spell_list_path], 0, widget->ht - FONT_HEIGHT(FONT_SERIF12) - 7, COLOR_HGOLD, TEXT_ALIGN_CENTER, &box); 00278 00279 box.w = 80; 00280 string_blt(widget->widgetSF, FONT_ARIAL10, filter_names[spell_list_filter_type], 160, 24, COLOR_WHITE, TEXT_ALIGN_CENTER, &box); 00281 00282 /* Show the spell's description. */ 00283 if (list->text && spell_find_path_selected(list->text[list->row_selected - 1][0], &spell_id)) 00284 { 00285 box.h = 120; 00286 box.w = 150; 00287 string_blt(widget->widgetSF, FONT_ARIAL10, spell_list[spell_list_path][spell_id]->desc, 160, 40, COLOR_WHITE, TEXT_WORD_WRAP, &box); 00288 } 00289 00290 /* Show info such as the spell cost, path status, etc if there is 00291 * a selected spell and it's a known one. */ 00292 if (list->text && spell_list[spell_list_path][spell_id]->known) 00293 { 00294 _Sprite *icon = FaceList[spell_list[spell_list_path][spell_id]->icon].sprite; 00295 const char *status; 00296 00297 string_blt_format(widget->widgetSF, FONT_ARIAL10, 160, widget->ht - 30, COLOR_WHITE, TEXT_MARKUP, NULL, "<b>Cost</b>: %d", spell_list[spell_list_path][spell_id]->cost); 00298 00299 switch (spell_list[spell_list_path][spell_id]->path) 00300 { 00301 case 'a': 00302 status = "Attuned"; 00303 break; 00304 00305 case 'r': 00306 status = "Repelled"; 00307 break; 00308 00309 case 'd': 00310 status = "Denied"; 00311 break; 00312 00313 default: 00314 status = "Normal"; 00315 break; 00316 } 00317 00318 string_blt_format(widget->widgetSF, FONT_ARIAL10, 160, widget->ht - 18, COLOR_WHITE, TEXT_MARKUP, NULL, "<b>Status</b>: %s", status); 00319 draw_frame(widget->widgetSF, widget->wd - 6 - icon->bitmap->w, widget->ht - 6 - icon->bitmap->h, icon->bitmap->w + 1, icon->bitmap->h + 1); 00320 sprite_blt(icon, widget->wd - 5 - icon->bitmap->w, widget->ht - 5 - icon->bitmap->h, NULL, &bltfx); 00321 } 00322 } 00323 00324 box2.x = widget->x1; 00325 box2.y = widget->y1; 00326 SDL_BlitSurface(widget->widgetSF, NULL, ScreenSurface, &box2); 00327 00328 /* Render the various buttons. */ 00329 button_close.x = widget->x1 + widget->wd - Bitmaps[BITMAP_BUTTON_ROUND]->bitmap->w - 4; 00330 button_close.y = widget->y1 + 4; 00331 button_render(&button_close, "X"); 00332 00333 button_help.x = widget->x1 + widget->wd - Bitmaps[BITMAP_BUTTON_ROUND]->bitmap->w * 2 - 4; 00334 button_help.y = widget->y1 + 4; 00335 button_render(&button_help, "?"); 00336 00337 button_path_left.x = widget->x1 + 6; 00338 button_path_left.y = widget->y1 + widget->ht - Bitmaps[BITMAP_BUTTON_ROUND]->bitmap->h - 5; 00339 button_render(&button_path_left, "<"); 00340 00341 button_path_right.x = widget->x1 + 6 + 130; 00342 button_path_right.y = widget->y1 + widget->ht - Bitmaps[BITMAP_BUTTON_ROUND]->bitmap->h - 5; 00343 button_render(&button_path_right, ">"); 00344 00345 button_filter_left.x = widget->x1 + 160; 00346 button_filter_left.y = widget->y1 + 24; 00347 button_render(&button_filter_left, "<"); 00348 00349 button_filter_right.x = widget->x1 + 220; 00350 button_filter_right.y = widget->y1 + 24; 00351 button_render(&button_filter_right, ">"); 00352 00353 if (spell_list_filter_known) 00354 { 00355 button_filter_known.pressed = 1; 00356 } 00357 00358 button_filter_known.x = widget->x1 + 243; 00359 button_filter_known.y = widget->y1 + 22; 00360 button_render(&button_filter_known, "Known"); 00361 } 00362 00367 void widget_spells_mevent(widgetdata *widget, SDL_Event *event) 00368 { 00369 list_struct *list = list_exists(LIST_SPELLS); 00370 00371 /* If the list has handled the mouse event, we need to redraw the 00372 * widget. */ 00373 if (list && list_handle_mouse(list, event->motion.x - widget->x1, event->motion.y - widget->y1, event)) 00374 { 00375 widget->redraw = 1; 00376 } 00377 00378 if (button_event(&button_path_left, event)) 00379 { 00380 button_repeat_func(&button_path_left); 00381 } 00382 else if (button_event(&button_path_right, event)) 00383 { 00384 button_repeat_func(&button_path_right); 00385 } 00386 else if (button_event(&button_close, event)) 00387 { 00388 widget->show = 0; 00389 button_close.pressed = 0; 00390 } 00391 else if (button_event(&button_filter_left, event)) 00392 { 00393 button_filter_adjust(-1); 00394 } 00395 else if (button_event(&button_filter_right, event)) 00396 { 00397 button_filter_adjust(1); 00398 } 00399 else if (button_event(&button_filter_known, event)) 00400 { 00401 spell_list_filter_known = !spell_list_filter_known; 00402 spell_list_reload(); 00403 } 00404 else if (button_event(&button_help, event)) 00405 { 00406 show_help("spell list"); 00407 } 00408 else if (list->text && event->type == SDL_MOUSEBUTTONDOWN && event->button.button == SDL_BUTTON_LEFT && !draggingInvItem(DRAG_GET_STATUS)) 00409 { 00410 size_t spell_id; 00411 _Sprite *icon; 00412 00413 if (!spell_find_path_selected(list->text[list->row_selected - 1][0], &spell_id) || !spell_list[spell_list_path][spell_id]->known) 00414 { 00415 return; 00416 } 00417 00418 icon = FaceList[spell_list[spell_list_path][spell_id]->icon].sprite; 00419 00420 if (event->motion.x >= widget->x1 + widget->wd - 5 - icon->bitmap->w && event->motion.x <= widget->x1 + widget->wd - 5 && event->motion.y >= widget->y1 + widget->ht - 5 - icon->bitmap->h && event->motion.y <= widget->y1 + widget->ht - 5) 00421 { 00422 cpl.dragging.spell = spell_get(spell_list_path, spell_id); 00423 draggingInvItem(DRAG_QUICKSLOT_SPELL); 00424 } 00425 } 00426 } 00427 00436 int spell_find(const char *name, size_t *spell_path, size_t *spell_id) 00437 { 00438 for (*spell_path = 0; *spell_path < SPELL_PATH_NUM - 1; *spell_path += 1) 00439 { 00440 for (*spell_id = 0; *spell_id < spell_list_num[*spell_path]; *spell_id += 1) 00441 { 00442 if (!strncasecmp(spell_list[*spell_path][*spell_id]->name, name, strlen(name))) 00443 { 00444 return 1; 00445 } 00446 } 00447 } 00448 00449 return 0; 00450 } 00451 00460 int spell_find_path_selected(const char *name, size_t *spell_id) 00461 { 00462 for (*spell_id = 0; *spell_id < spell_list_num[spell_list_path]; *spell_id += 1) 00463 { 00464 if (!strncasecmp(spell_list[spell_list_path][*spell_id]->name, name, strlen(name))) 00465 { 00466 return 1; 00467 } 00468 } 00469 00470 return 0; 00471 } 00472 00478 spell_entry_struct *spell_get(size_t spell_path, size_t spell_id) 00479 { 00480 return spell_list[spell_path][spell_id]; 00481 } 00482 00485 void spells_init() 00486 { 00487 FILE *fp; 00488 char line[HUGE_BUF]; 00489 size_t i, j, num_spells; 00490 00491 /* Free previously allocated spells. */ 00492 for (i = 0; i < SPELL_PATH_NUM; i++) 00493 { 00494 if (spell_list[i]) 00495 { 00496 if (i != SPELL_PATH_NUM - 1) 00497 { 00498 for (j = 0; j < spell_list_num[i]; j++) 00499 { 00500 free(spell_list[i][j]); 00501 } 00502 } 00503 00504 free(spell_list[i]); 00505 } 00506 } 00507 00508 memset(&spell_list, 0, sizeof(*spell_list) * SPELL_PATH_NUM); 00509 memset(&spell_list_num, 0, sizeof(*spell_list_num) * SPELL_PATH_NUM); 00510 spell_list_path = 0; 00511 num_spells = 0; 00512 00513 fp = server_file_open(SERVER_FILE_SPELLS); 00514 00515 if (!fp) 00516 { 00517 return; 00518 } 00519 00520 while (fgets(line, sizeof(line) - 1, fp)) 00521 { 00522 char *spell_name, *icon, desc[HUGE_BUF]; 00523 int spell_type, spell_path; 00524 00525 line[strlen(line) - 1] = '\0'; 00526 spell_name = strdup(line); 00527 00528 if (!fgets(line, sizeof(line) - 1, fp)) 00529 { 00530 LOG(llevBug, " Got unexpected EOF reading spells file.\n"); 00531 break; 00532 } 00533 00534 spell_type = atoi(line); 00535 00536 if (!fgets(line, sizeof(line) - 1, fp)) 00537 { 00538 LOG(llevBug, " Got unexpected EOF reading spells file.\n"); 00539 break; 00540 } 00541 00542 spell_path = atoi(line); 00543 00544 if (!fgets(line, sizeof(line) - 1, fp)) 00545 { 00546 LOG(llevBug, " Got unexpected EOF reading spells file.\n"); 00547 break; 00548 } 00549 00550 line[strlen(line) - 1] = '\0'; 00551 icon = strdup(line); 00552 desc[0] = '\0'; 00553 00554 while (fgets(line, sizeof(line) - 1, fp)) 00555 { 00556 if (!strcmp(line, "end\n")) 00557 { 00558 spell_entry_struct *entry; 00559 00560 /* Resize the spell list array for this spell path. */ 00561 spell_list[spell_path] = realloc(spell_list[spell_path], sizeof(*spell_list[spell_path]) * (spell_list_num[spell_path] + 1)); 00562 entry = spell_list[spell_path][spell_list_num[spell_path]] = malloc(sizeof(**spell_list[spell_path])); 00563 spell_list_num[spell_path]++; 00564 00565 /* Store the data. */ 00566 strncpy(entry->name, spell_name, sizeof(entry->name) - 1); 00567 entry->name[sizeof(entry->name) - 1] = '\0'; 00568 strncpy(entry->desc, desc, sizeof(entry->desc) - 1); 00569 entry->desc[sizeof(entry->desc) - 1] = '\0'; 00570 strncpy(entry->icon_name, icon, sizeof(entry->icon_name) - 1); 00571 entry->icon_name[sizeof(entry->icon_name) - 1] = '\0'; 00572 entry->icon = get_bmap_id(entry->icon_name); 00573 entry->known = '\0'; 00574 entry->path = 0; 00575 entry->type = spell_type - 1; 00576 00577 free(icon); 00578 free(spell_name); 00579 num_spells++; 00580 break; 00581 } 00582 00583 strncat(desc, line, sizeof(desc) - strlen(desc) - 1); 00584 } 00585 } 00586 00587 fclose(fp); 00588 00589 if (num_spells) 00590 { 00591 spell_list[SPELL_PATH_NUM - 1] = malloc(sizeof(*spell_list[SPELL_PATH_NUM - 1]) * num_spells); 00592 00593 for (i = 0; i < SPELL_PATH_NUM - 1; i++) 00594 { 00595 for (j = 0; j < spell_list_num[i]; j++) 00596 { 00597 spell_list[SPELL_PATH_NUM - 1][spell_list_num[SPELL_PATH_NUM - 1]] = spell_list[i][j]; 00598 spell_list_num[SPELL_PATH_NUM - 1]++; 00599 } 00600 } 00601 } 00602 } 00603 00606 void spells_reload() 00607 { 00608 size_t spell_path, spell_id; 00609 00610 for (spell_path = 0; spell_path < SPELL_PATH_NUM - 1; spell_path++) 00611 { 00612 for (spell_id = 0; spell_id < spell_list_num[spell_path]; spell_id++) 00613 { 00614 spell_list[spell_path][spell_id]->icon = get_bmap_id(spell_list[spell_path][spell_id]->icon_name); 00615 } 00616 } 00617 } 00618 00622 void SpelllistCmd(char *data) 00623 { 00624 char *tmp_data, *cp; 00625 size_t spell_path, spell_id; 00626 int mode; 00627 00628 tmp_data = strdup(data); 00629 cp = strtok(tmp_data, "/"); 00630 00631 mode = atoi(data); 00632 00633 while (cp) 00634 { 00635 char *tmp[3]; 00636 00637 if (split_string(cp, tmp, sizeof(tmp) / sizeof(*tmp), ':') != 3) 00638 { 00639 cp = strtok(NULL, "/"); 00640 continue; 00641 } 00642 00643 /* If the spell exists, mark it as known, and store the path 00644 * status and casting cost. */ 00645 if (spell_find(tmp[0], &spell_path, &spell_id)) 00646 { 00647 spell_entry_struct *spell = spell_get(spell_path, spell_id); 00648 00649 if (mode == SPLIST_MODE_REMOVE) 00650 { 00651 spell->known = 0; 00652 } 00653 else 00654 { 00655 spell->known = 1; 00656 spell->path = tmp[2][0]; 00657 spell->cost = atoi(tmp[1]); 00658 } 00659 } 00660 00661 cp = strtok(NULL, "/"); 00662 } 00663 00664 free(tmp_data); 00665 spell_list_reload(); 00666 }
1.7.4