|
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 static skill_entry_struct **skill_list[SKILL_LIST_TYPES]; 00035 static size_t skill_list_num[SKILL_LIST_TYPES]; 00036 00038 static size_t skill_list_type = 0; 00040 static uint8 skill_list_filter_known; 00042 static button_struct button_type_left, button_type_right, button_close, button_filter_known, button_help; 00043 00047 static void list_handle_enter(list_struct *list) 00048 { 00049 /* Ready the selected skill, if any. */ 00050 if (list->text) 00051 { 00052 char buf[MAX_BUF]; 00053 00054 snprintf(buf, sizeof(buf), "/ready_skill %s", list->text[list->row_selected - 1][0]); 00055 client_command_check(buf); 00056 } 00057 } 00058 00061 static const char *list_text_color_hook(list_struct *list, const char *default_color, uint32 row, uint32 col) 00062 { 00063 size_t id; 00064 00065 /* If the skill is not known, use gray instead of the default color. */ 00066 if (skill_find_type_selected(list->text[row][col], &id) && !skill_list[skill_list_type][id]->known) 00067 { 00068 return COLOR_GRAY; 00069 } 00070 00071 return default_color; 00072 } 00073 00076 static void skill_list_reload() 00077 { 00078 list_struct *list; 00079 size_t i; 00080 uint32 offset, rows, selected; 00081 00082 list = list_exists(LIST_SKILLS); 00083 00084 if (!list) 00085 { 00086 return; 00087 } 00088 00089 offset = list->row_offset; 00090 selected = list->row_selected; 00091 rows = list->rows; 00092 list_clear(list); 00093 00094 for (i = 0; i < skill_list_num[skill_list_type]; i++) 00095 { 00096 if (skill_list_filter_known && !skill_list[skill_list_type][i]->known) 00097 { 00098 continue; 00099 } 00100 00101 list_add(list, list->rows, 0, skill_list[skill_list_type][i]->name); 00102 } 00103 00104 list_sort(list, LIST_SORT_ALPHA); 00105 00106 if (list->rows == rows) 00107 { 00108 list->row_offset = offset; 00109 list->row_selected = selected; 00110 } 00111 00112 cur_widget[SKILLS_ID]->redraw = 1; 00113 } 00114 00118 static void button_repeat_func(button_struct *button) 00119 { 00120 int path = skill_list_type; 00121 00122 if (button == &button_type_left) 00123 { 00124 path--; 00125 } 00126 else 00127 { 00128 path++; 00129 } 00130 00131 if (path < 0) 00132 { 00133 path = SKILL_LIST_TYPES - 1; 00134 } 00135 else if (path > SKILL_LIST_TYPES - 1) 00136 { 00137 path = 0; 00138 } 00139 00140 skill_list_type = path; 00141 skill_list_reload(); 00142 } 00143 00147 void widget_skills_render(widgetdata *widget) 00148 { 00149 list_struct *list; 00150 SDL_Rect box, box2; 00151 00152 /* Create the surface. */ 00153 if (!widget->widgetSF) 00154 { 00155 widget->widgetSF = SDL_ConvertSurface(Bitmaps[BITMAP_CONTENT]->bitmap, Bitmaps[BITMAP_CONTENT]->bitmap->format, Bitmaps[BITMAP_CONTENT]->bitmap->flags); 00156 } 00157 00158 list = list_exists(LIST_SKILLS); 00159 00160 /* Create the skill list. */ 00161 if (!list) 00162 { 00163 skill_list_filter_known = 0; 00164 00165 list = list_create(LIST_SKILLS, 12, 1, 8); 00166 list->handle_enter_func = list_handle_enter; 00167 list->text_color_hook = list_text_color_hook; 00168 list->surface = widget->widgetSF; 00169 list_scrollbar_enable(list); 00170 list_set_column(list, 0, 130, 7, NULL, -1); 00171 list_set_font(list, FONT_ARIAL10); 00172 skill_list_reload(); 00173 00174 /* Create various buttons... */ 00175 button_create(&button_type_left); 00176 button_create(&button_type_right); 00177 button_create(&button_close); 00178 button_create(&button_filter_known); 00179 button_create(&button_help); 00180 button_type_left.repeat_func = button_type_right.repeat_func = button_repeat_func; 00181 button_close.bitmap = button_type_left.bitmap = button_type_right.bitmap = button_help.bitmap = BITMAP_BUTTON_ROUND; 00182 button_close.bitmap_pressed = button_type_left.bitmap_pressed = button_type_right.bitmap_pressed = button_help.bitmap_pressed = BITMAP_BUTTON_ROUND_DOWN; 00183 } 00184 00185 if (widget->redraw) 00186 { 00187 _BLTFX bltfx; 00188 size_t skill_id; 00189 00190 bltfx.surface = widget->widgetSF; 00191 bltfx.flags = 0; 00192 bltfx.alpha = 0; 00193 sprite_blt(Bitmaps[BITMAP_CONTENT], 0, 0, NULL, &bltfx); 00194 00195 widget->redraw = 0; 00196 00197 box.h = 0; 00198 box.w = widget->wd; 00199 string_blt(widget->widgetSF, FONT_SERIF12, "Skills", 0, 3, COLOR_HGOLD, TEXT_ALIGN_CENTER, &box); 00200 list->focus = 1; 00201 list_set_parent(list, widget->x1, widget->y1); 00202 list_show(list, 10, 2); 00203 00204 box.w = 160; 00205 string_blt(widget->widgetSF, FONT_SERIF12, s_settings->skill_types[skill_list_type], 0, widget->ht - FONT_HEIGHT(FONT_SERIF12) - 7, COLOR_HGOLD, TEXT_ALIGN_CENTER, &box); 00206 00207 /* Show the skill's description. */ 00208 if (list->text && skill_find_type_selected(list->text[list->row_selected - 1][0], &skill_id)) 00209 { 00210 box.h = 120; 00211 box.w = 150; 00212 string_blt(widget->widgetSF, FONT_ARIAL10, skill_list[skill_list_type][skill_id]->desc, 160, 40, COLOR_WHITE, TEXT_WORD_WRAP | TEXT_MARKUP, &box); 00213 } 00214 00215 /* Show the skill's icon, if it's known. */ 00216 if (list->text && skill_list[skill_list_type][skill_id]->known) 00217 { 00218 _Sprite *icon = FaceList[skill_list[skill_list_type][skill_id]->icon].sprite; 00219 char level_buf[MAX_BUF], exp_buf[MAX_BUF]; 00220 00221 if (skill_list[skill_list_type][skill_id]->exp == -1) 00222 { 00223 strncpy(level_buf, "<b>Level</b>: n/a", sizeof(level_buf) - 1); 00224 level_buf[sizeof(level_buf) - 1] = '\0'; 00225 } 00226 else 00227 { 00228 snprintf(level_buf, sizeof(level_buf), "<b>Level</b>: %d", skill_list[skill_list_type][skill_id]->level); 00229 } 00230 00231 if (skill_list[skill_list_type][skill_id]->exp >= 0) 00232 { 00233 snprintf(exp_buf, sizeof(exp_buf), "<b>Exp</b>: %"FMT64, skill_list[skill_list_type][skill_id]->exp); 00234 } 00235 else 00236 { 00237 strncpy(exp_buf, "<b>Exp</b>: n/a", sizeof(exp_buf) - 1); 00238 exp_buf[sizeof(exp_buf) - 1] = '\0'; 00239 } 00240 00241 string_blt(widget->widgetSF, FONT_ARIAL10, level_buf, 160, widget->ht - 30, COLOR_WHITE, TEXT_MARKUP, NULL); 00242 string_blt(widget->widgetSF, FONT_ARIAL10, exp_buf, 160, widget->ht - 18, COLOR_WHITE, TEXT_MARKUP, NULL); 00243 00244 draw_frame(widget->widgetSF, widget->wd - 6 - icon->bitmap->w, widget->ht - 6 - icon->bitmap->h, icon->bitmap->w + 1, icon->bitmap->h + 1); 00245 sprite_blt(icon, widget->wd - 5 - icon->bitmap->w, widget->ht - 5 - icon->bitmap->h, NULL, &bltfx); 00246 } 00247 } 00248 00249 box2.x = widget->x1; 00250 box2.y = widget->y1; 00251 SDL_BlitSurface(widget->widgetSF, NULL, ScreenSurface, &box2); 00252 00253 /* Render the various buttons. */ 00254 button_close.x = widget->x1 + widget->wd - Bitmaps[BITMAP_BUTTON_ROUND]->bitmap->w - 4; 00255 button_close.y = widget->y1 + 4; 00256 button_render(&button_close, "X"); 00257 00258 button_help.x = widget->x1 + widget->wd - Bitmaps[BITMAP_BUTTON_ROUND]->bitmap->w * 2 - 4; 00259 button_help.y = widget->y1 + 4; 00260 button_render(&button_help, "?"); 00261 00262 button_type_left.x = widget->x1 + 6; 00263 button_type_left.y = widget->y1 + widget->ht - Bitmaps[BITMAP_BUTTON_ROUND]->bitmap->h - 5; 00264 button_render(&button_type_left, "<"); 00265 00266 button_type_right.x = widget->x1 + 6 + 130; 00267 button_type_right.y = widget->y1 + widget->ht - Bitmaps[BITMAP_BUTTON_ROUND]->bitmap->h - 5; 00268 button_render(&button_type_right, ">"); 00269 00270 if (skill_list_filter_known) 00271 { 00272 button_filter_known.pressed = 1; 00273 } 00274 00275 button_filter_known.x = widget->x1 + 158; 00276 button_filter_known.y = widget->y1 + 22; 00277 button_render(&button_filter_known, "Known"); 00278 } 00279 00284 void widget_skills_mevent(widgetdata *widget, SDL_Event *event) 00285 { 00286 list_struct *list = list_exists(LIST_SKILLS); 00287 00288 /* If the list has handled the mouse event, we need to redraw the 00289 * widget. */ 00290 if (list && list_handle_mouse(list, event->motion.x - widget->x1, event->motion.y - widget->y1, event)) 00291 { 00292 widget->redraw = 1; 00293 } 00294 00295 if (button_event(&button_type_left, event)) 00296 { 00297 button_repeat_func(&button_type_left); 00298 } 00299 else if (button_event(&button_type_right, event)) 00300 { 00301 button_repeat_func(&button_type_right); 00302 } 00303 else if (button_event(&button_close, event)) 00304 { 00305 widget->show = 0; 00306 button_close.pressed = 0; 00307 } 00308 else if (button_event(&button_filter_known, event)) 00309 { 00310 skill_list_filter_known = !skill_list_filter_known; 00311 skill_list_reload(); 00312 } 00313 else if (button_event(&button_help, event)) 00314 { 00315 show_help("skill list"); 00316 } 00317 } 00318 00327 int skill_find(const char *name, size_t *type, size_t *id) 00328 { 00329 for (*type = 0; *type < SKILL_LIST_TYPES - 1; *type += 1) 00330 { 00331 for (*id = 0; *id < skill_list_num[*type]; *id += 1) 00332 { 00333 if (!strncasecmp(skill_list[*type][*id]->name, name, strlen(name))) 00334 { 00335 return 1; 00336 } 00337 } 00338 } 00339 00340 return 0; 00341 } 00342 00351 int skill_find_type_selected(const char *name, size_t *id) 00352 { 00353 for (*id = 0; *id < skill_list_num[skill_list_type]; *id += 1) 00354 { 00355 if (!strncasecmp(skill_list[skill_list_type][*id]->name, name, strlen(name))) 00356 { 00357 return 1; 00358 } 00359 } 00360 00361 return 0; 00362 } 00363 00369 skill_entry_struct *skill_get(size_t type, size_t id) 00370 { 00371 return skill_list[type][id]; 00372 } 00373 00376 void skills_init() 00377 { 00378 FILE *fp; 00379 char line[HUGE_BUF]; 00380 size_t i, j, num_skills; 00381 00382 /* Free previously allocated skills. */ 00383 for (i = 0; i < SKILL_LIST_TYPES; i++) 00384 { 00385 if (skill_list[i]) 00386 { 00387 if (i != SKILL_LIST_TYPES - 1) 00388 { 00389 for (j = 0; j < skill_list_num[i]; j++) 00390 { 00391 free(skill_list[i][j]); 00392 } 00393 } 00394 00395 free(skill_list[i]); 00396 } 00397 } 00398 00399 memset(&skill_list, 0, sizeof(*skill_list) * SKILL_LIST_TYPES); 00400 memset(&skill_list_num, 0, sizeof(*skill_list_num) * SKILL_LIST_TYPES); 00401 skill_list_type = 0; 00402 num_skills = 0; 00403 00404 fp = server_file_open(SERVER_FILE_SKILLS); 00405 00406 if (!fp) 00407 { 00408 return; 00409 } 00410 00411 while (fgets(line, sizeof(line) - 1, fp)) 00412 { 00413 char *name, *icon, desc[HUGE_BUF]; 00414 int type; 00415 00416 line[strlen(line) - 1] = '\0'; 00417 name = strdup(line); 00418 00419 if (!fgets(line, sizeof(line) - 1, fp)) 00420 { 00421 LOG(llevBug, " Got unexpected EOF reading skills file.\n"); 00422 break; 00423 } 00424 00425 type = atoi(line); 00426 00427 if (!fgets(line, sizeof(line) - 1, fp)) 00428 { 00429 LOG(llevBug, " Got unexpected EOF reading skills file.\n"); 00430 break; 00431 } 00432 00433 line[strlen(line) - 1] = '\0'; 00434 icon = strdup(line); 00435 desc[0] = '\0'; 00436 00437 while (fgets(line, sizeof(line) - 1, fp)) 00438 { 00439 if (!strcmp(line, "end\n")) 00440 { 00441 skill_entry_struct *entry; 00442 00443 /* Resize the skill list array for this skill type. */ 00444 skill_list[type] = realloc(skill_list[type], sizeof(*skill_list[type]) * (skill_list_num[type] + 1)); 00445 entry = skill_list[type][skill_list_num[type]] = malloc(sizeof(**skill_list[type])); 00446 skill_list_num[type]++; 00447 00448 /* Store the data. */ 00449 strncpy(entry->name, name, sizeof(entry->name) - 1); 00450 entry->name[sizeof(entry->name) - 1] = '\0'; 00451 strncpy(entry->desc, desc, sizeof(entry->desc) - 1); 00452 entry->desc[sizeof(entry->desc) - 1] = '\0'; 00453 strncpy(entry->icon_name, icon, sizeof(entry->icon_name) - 1); 00454 entry->icon_name[sizeof(entry->icon_name) - 1] = '\0'; 00455 entry->icon = get_bmap_id(entry->icon_name); 00456 entry->known = 0; 00457 00458 free(icon); 00459 free(name); 00460 num_skills++; 00461 break; 00462 } 00463 00464 strncat(desc, line, sizeof(desc) - strlen(desc) - 1); 00465 } 00466 } 00467 00468 fclose(fp); 00469 00470 if (num_skills) 00471 { 00472 skill_list[SKILL_LIST_TYPES - 1] = malloc(sizeof(*skill_list[SKILL_LIST_TYPES - 1]) * num_skills); 00473 00474 for (i = 0; i < SKILL_LIST_TYPES - 1; i++) 00475 { 00476 for (j = 0; j < skill_list_num[i]; j++) 00477 { 00478 skill_list[SKILL_LIST_TYPES - 1][skill_list_num[SKILL_LIST_TYPES - 1]] = skill_list[i][j]; 00479 skill_list_num[SKILL_LIST_TYPES - 1]++; 00480 } 00481 } 00482 } 00483 } 00484 00487 void skills_reload() 00488 { 00489 size_t type, id; 00490 00491 for (type = 0; type < SKILL_LIST_TYPES - 1; type++) 00492 { 00493 for (id = 0; id < skill_list_num[type]; id++) 00494 { 00495 skill_list[type][id]->icon = get_bmap_id(skill_list[type][id]->icon_name); 00496 } 00497 } 00498 } 00499 00503 void SkilllistCmd(char *data) 00504 { 00505 char *tmp_data, *cp; 00506 size_t skill_type, skill_id; 00507 int mode; 00508 00509 tmp_data = strdup(data); 00510 cp = strtok(tmp_data, "/"); 00511 00512 mode = atoi(data); 00513 00514 while (cp) 00515 { 00516 char *tmp[3]; 00517 00518 if (split_string(cp, tmp, sizeof(tmp) / sizeof(*tmp), '|') != 3) 00519 { 00520 cp = strtok(NULL, "/"); 00521 continue; 00522 } 00523 00524 /* If the skill exists, mark it as known, and store the level/exp. */ 00525 if (skill_find(tmp[0], &skill_type, &skill_id)) 00526 { 00527 skill_entry_struct *skill = skill_get(skill_type, skill_id); 00528 00529 if (mode == SPLIST_MODE_REMOVE) 00530 { 00531 skill->known = 0; 00532 } 00533 else 00534 { 00535 skill->known = 1; 00536 skill->level = atoi(tmp[1]); 00537 skill->exp = atoll(tmp[2]); 00538 WIDGET_REDRAW_ALL(SKILL_EXP_ID); 00539 } 00540 } 00541 00542 cp = strtok(NULL, "/"); 00543 } 00544 00545 free(tmp_data); 00546 skill_list_reload(); 00547 }
1.7.4