|
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 00037 #include <global.h> 00038 00043 static _player_doll_pos player_doll[PDOLL_INIT] = 00044 { 00045 {93, 55}, 00046 {93, 8}, 00047 {93, 100}, 00048 {93, 158}, 00049 {135, 95}, 00050 {50, 95}, 00051 {50, 134}, 00052 {135, 134}, 00053 {54, 51}, 00054 {141, 10}, 00055 {5, 148}, 00056 {180, 148}, 00057 {5, 108}, 00058 {180, 108}, 00059 {43, 10}, 00060 {4, 10} 00061 }; 00062 00064 static float weapon_speed_table[19] = 00065 { 00066 20.0f, 18.0f, 10.0f, 8.0f, 5.5f, 00067 4.25f, 3.50f, 3.05f, 2.70f, 2.35f, 00068 2.15f, 1.95f, 1.80f, 1.60f, 1.52f, 00069 1.44f, 1.32f, 1.25f, 1.20f 00070 }; 00071 00074 const char *gender_noun[GENDER_MAX] = 00075 { 00076 "neuter", "male", "female", "hermaphrodite" 00077 }; 00078 00081 void clear_player() 00082 { 00083 memset(&cpl, 0, sizeof(cpl)); 00084 quickslots_init(); 00085 objects_init(); 00086 init_player_data(); 00087 WIDGET_REDRAW_ALL(SKILL_EXP_ID); 00088 } 00089 00096 void new_player(long tag, long weight, short face) 00097 { 00098 cpl.ob->tag = tag; 00099 cpl.ob->weight = (float) weight / 1000; 00100 cpl.ob->face = face; 00101 } 00102 00106 void client_send_apply(int tag) 00107 { 00108 char buf[MAX_BUF]; 00109 00110 snprintf(buf, sizeof(buf), "ap %d", tag); 00111 cs_write_string(buf, strlen(buf)); 00112 } 00113 00117 void client_send_examine(int tag) 00118 { 00119 char buf[MAX_BUF]; 00120 00121 snprintf(buf, sizeof(buf), "ex %d", tag); 00122 cs_write_string(buf, strlen(buf)); 00123 } 00124 00130 void client_send_move(int loc, int tag, int nrof) 00131 { 00132 char buf[MAX_BUF]; 00133 00134 snprintf(buf, sizeof(buf), "mv %d %d %d", loc, tag, nrof); 00135 cs_write_string(buf, strlen(buf)); 00136 } 00137 00143 void send_command(const char *command) 00144 { 00145 char buf[MAX_BUF]; 00146 SockList sl; 00147 00148 sl.buf = (unsigned char *) buf; 00149 strcpy((char *) sl.buf, "cm "); 00150 sl.len = 3; 00151 strncpy((char *) sl.buf + sl.len, command, MAX_BUF - sl.len); 00152 sl.buf[MAX_BUF - 1] = '\0'; 00153 sl.len += (int) strlen(command); 00154 send_socklist(sl); 00155 } 00156 00161 void CompleteCmd(unsigned char *data, int len) 00162 { 00163 (void) data; 00164 (void) len; 00165 } 00166 00170 void set_weight_limit(uint32 wlim) 00171 { 00172 cpl.weight_limit = wlim; 00173 } 00174 00177 void init_player_data() 00178 { 00179 new_player(0, 0, 0); 00180 00181 cpl.dm = 0; 00182 cpl.fire_on = cpl.firekey_on = 0; 00183 cpl.run_on = cpl.runkey_on = 0; 00184 cpl.inventory_win = IWIN_BELOW; 00185 00186 cpl.container_tag = -996; 00187 cpl.container = NULL; 00188 00189 memset(&cpl.stats, 0, sizeof(Stats)); 00190 00191 cpl.stats.maxsp = 1; 00192 cpl.stats.maxhp = 1; 00193 cpl.gen_hp = 0.0f; 00194 cpl.gen_sp = 0.0f; 00195 cpl.gen_grace = 0.0f; 00196 cpl.target_hp = 0; 00197 00198 cpl.stats.maxgrace = 1; 00199 cpl.stats.speed = 1; 00200 00201 cpl.range[0] = '\0'; 00202 00203 cpl.ob->nrof = 1; 00204 cpl.partyname[0] = cpl.partyjoin[0] = '\0'; 00205 00206 cpl.menustatus = MENU_NO; 00207 cpl.menustatus = MENU_NO; 00208 00209 /* Avoid division by 0 errors */ 00210 cpl.stats.maxsp = 1; 00211 cpl.stats.maxhp = 1; 00212 cpl.stats.maxgrace = 1; 00213 00214 /* Displayed weapon speed is weapon speed/speed */ 00215 cpl.stats.speed = 0; 00216 cpl.stats.weapon_sp = 0; 00217 cpl.action_timer = 0.0f; 00218 00219 cpl.container_tag = -997; 00220 cpl.container = NULL; 00221 00222 RangeFireMode = 0; 00223 } 00224 00230 void widget_player_data_event(widgetdata *widget, int x, int y) 00231 { 00232 int mx = x - widget->x1, my = y - widget->y1; 00233 00234 if (mx >= 184 && mx <= 210 && my >= 5 && my <= 35) 00235 { 00236 if (!client_command_check("/pray")) 00237 { 00238 send_command("/pray"); 00239 } 00240 } 00241 } 00242 00246 void widget_show_player_data(widgetdata *widget) 00247 { 00248 SDL_Rect box; 00249 00250 sprite_blt(Bitmaps[BITMAP_PLAYER_INFO], widget->x1, widget->y1, NULL, NULL); 00251 00252 box.w = widget->wd - 12; 00253 box.h = 36; 00254 string_blt(ScreenSurface, FONT_ARIAL10, cpl.ext_title, widget->x1 + 6, widget->y1 + 2, COLOR_HGOLD, TEXT_MARKUP | TEXT_WORD_WRAP, &box); 00255 00256 /* Prayer button */ 00257 sprite_blt(Bitmaps[BITMAP_PRAY], widget->x1 + 184, widget->y1 + 5, NULL, NULL); 00258 } 00259 00263 void widget_player_stats(widgetdata *widget) 00264 { 00265 double temp; 00266 SDL_Rect box; 00267 int tmp; 00268 00269 /* Let's look if we have a backbuffer SF, if not create one from the background */ 00270 if (!widget->widgetSF) 00271 { 00272 widget->widgetSF = SDL_ConvertSurface(Bitmaps[BITMAP_STATS_BG]->bitmap, Bitmaps[BITMAP_STATS_BG]->bitmap->format, Bitmaps[BITMAP_STATS_BG]->bitmap->flags); 00273 } 00274 00275 /* We have a backbuffer SF, test for the redrawing flag and do the redrawing */ 00276 if (widget->redraw) 00277 { 00278 char buf[MAX_BUF]; 00279 _BLTFX bltfx; 00280 00281 widget->redraw = 0; 00282 00283 /* We redraw here only all halfway static stuff * 00284 * We simply don't need to redraw that stuff every frame, how often the stats change? */ 00285 bltfx.surface = widget->widgetSF; 00286 bltfx.flags = 0; 00287 bltfx.dark_level = 0; 00288 bltfx.alpha = 0; 00289 00290 sprite_blt(Bitmaps[BITMAP_STATS_BG], 0, 0, NULL, &bltfx); 00291 00292 string_blt(widget->widgetSF, FONT_MONO9, "Stats", 8, 4, COLOR_HGOLD, TEXT_OUTLINE, NULL); 00293 00294 /* Strength */ 00295 string_blt(widget->widgetSF, FONT_ARIAL10, "Str", 8, 17, COLOR_WHITE, 0, NULL); 00296 string_blt_format(widget->widgetSF, FONT_ARIAL10, 33, 17, COLOR_GREEN, 0, NULL, "%02d", cpl.stats.Str); 00297 00298 /* Dexterity */ 00299 string_blt(widget->widgetSF, FONT_ARIAL10, "Dex", 8, 28, COLOR_WHITE, 0, NULL); 00300 string_blt_format(widget->widgetSF, FONT_ARIAL10, 33, 28, COLOR_GREEN, 0, NULL, "%02d", cpl.stats.Dex); 00301 00302 /* Constitution */ 00303 string_blt(widget->widgetSF, FONT_ARIAL10, "Con", 8, 39, COLOR_WHITE, 0, NULL); 00304 string_blt_format(widget->widgetSF, FONT_ARIAL10, 33, 39, COLOR_GREEN, 0, NULL, "%02d", cpl.stats.Con); 00305 00306 /* Intelligence */ 00307 string_blt(widget->widgetSF, FONT_ARIAL10, "Int", 8, 50, COLOR_WHITE, 0, NULL); 00308 string_blt_format(widget->widgetSF, FONT_ARIAL10, 33, 50, COLOR_GREEN, 0, NULL, "%02d", cpl.stats.Int); 00309 00310 /* Wisdom */ 00311 string_blt(widget->widgetSF, FONT_ARIAL10, "Wis", 8, 61, COLOR_WHITE, 0, NULL); 00312 string_blt_format(widget->widgetSF, FONT_ARIAL10, 33, 61, COLOR_GREEN, 0, NULL, "%02d", cpl.stats.Wis); 00313 00314 /* Power */ 00315 string_blt(widget->widgetSF, FONT_ARIAL10, "Pow", 8, 72, COLOR_WHITE, 0, NULL); 00316 string_blt_format(widget->widgetSF, FONT_ARIAL10, 33, 72, COLOR_GREEN, 0, NULL, "%02d", cpl.stats.Pow); 00317 00318 /* Charisma */ 00319 string_blt(widget->widgetSF, FONT_ARIAL10, "Cha", 8, 83, COLOR_WHITE, 0, NULL); 00320 string_blt_format(widget->widgetSF, FONT_ARIAL10, 33, 83, COLOR_GREEN, 0, NULL, "%02d", cpl.stats.Cha); 00321 00322 /* Health */ 00323 string_blt(widget->widgetSF, FONT_ARIAL10, "HP", 58, 10, COLOR_WHITE, 0, NULL); 00324 snprintf(buf, sizeof(buf), "%d/%d", cpl.stats.hp, cpl.stats.maxhp); 00325 string_truncate_overflow(FONT_ARIAL10, buf, 90); 00326 string_blt(widget->widgetSF, FONT_ARIAL10, buf, 160 - string_get_width(FONT_ARIAL10, buf, 0), 10, COLOR_GREEN, 0, NULL); 00327 00328 /* Mana */ 00329 string_blt(widget->widgetSF, FONT_ARIAL10, "Mana", 58, 34, COLOR_WHITE, 0, NULL); 00330 snprintf(buf, sizeof(buf), "%d/%d", cpl.stats.sp, cpl.stats.maxsp); 00331 string_truncate_overflow(FONT_ARIAL10, buf, 75); 00332 string_blt(widget->widgetSF, FONT_ARIAL10, buf, 160 - string_get_width(FONT_ARIAL10, buf, 0), 34, COLOR_GREEN, 0, NULL); 00333 00334 /* Grace */ 00335 string_blt(widget->widgetSF, FONT_ARIAL10, "Grace", 58, 58, COLOR_WHITE, 0, NULL); 00336 snprintf(buf, sizeof(buf), "%d/%d", cpl.stats.grace, cpl.stats.maxgrace); 00337 string_truncate_overflow(FONT_ARIAL10, buf, 75); 00338 string_blt(widget->widgetSF, FONT_ARIAL10, buf, 160 - string_get_width(FONT_ARIAL10, buf, 0), 58, COLOR_GREEN, 0, NULL); 00339 00340 /* Food */ 00341 string_blt(widget->widgetSF, FONT_ARIAL10, "Food", 58, 83, COLOR_WHITE, 0, NULL); 00342 } 00343 00344 /* Now we blit our backbuffer SF */ 00345 box.x = widget->x1; 00346 box.y = widget->y1; 00347 SDL_BlitSurface(widget->widgetSF, NULL, ScreenSurface, &box); 00348 00349 /* Health bar */ 00350 if (cpl.stats.maxhp) 00351 { 00352 tmp = cpl.stats.hp; 00353 00354 if (tmp < 0) 00355 { 00356 tmp = 0; 00357 } 00358 00359 temp = (double) tmp / (double) cpl.stats.maxhp; 00360 box.x = 0; 00361 box.y = 0; 00362 box.h = Bitmaps[BITMAP_HP]->bitmap->h; 00363 box.w = (int) (Bitmaps[BITMAP_HP]->bitmap->w * temp); 00364 00365 if (tmp && !box.w) 00366 { 00367 box.w = 1; 00368 } 00369 00370 if (box.w > Bitmaps[BITMAP_HP]->bitmap->w) 00371 { 00372 box.w = Bitmaps[BITMAP_HP]->bitmap->w; 00373 } 00374 00375 sprite_blt(Bitmaps[BITMAP_HP_BACK], widget->x1 + 57, widget->y1 + 23, NULL, NULL); 00376 sprite_blt(Bitmaps[BITMAP_HP], widget->x1 + 57, widget->y1 + 23, &box, NULL); 00377 } 00378 00379 /* Mana bar */ 00380 if (cpl.stats.maxsp) 00381 { 00382 tmp = cpl.stats.sp; 00383 00384 if (tmp < 0) 00385 { 00386 tmp = 0; 00387 } 00388 00389 temp = (double) tmp / (double) cpl.stats.maxsp; 00390 box.x = 0; 00391 box.y = 0; 00392 box.h = Bitmaps[BITMAP_SP]->bitmap->h; 00393 box.w = (int) (Bitmaps[BITMAP_SP]->bitmap->w * temp); 00394 00395 if (tmp && !box.w) 00396 { 00397 box.w = 1; 00398 } 00399 00400 if (box.w > Bitmaps[BITMAP_SP]->bitmap->w) 00401 { 00402 box.w = Bitmaps[BITMAP_SP]->bitmap->w; 00403 } 00404 00405 sprite_blt(Bitmaps[BITMAP_SP_BACK], widget->x1 + 57, widget->y1 + 47, NULL, NULL); 00406 sprite_blt(Bitmaps[BITMAP_SP], widget->x1 + 57, widget->y1 + 47, &box, NULL); 00407 } 00408 00409 /* Grace bar */ 00410 if (cpl.stats.maxgrace) 00411 { 00412 tmp = cpl.stats.grace; 00413 00414 if (tmp < 0) 00415 { 00416 tmp = 0; 00417 } 00418 00419 temp = (double) tmp / (double) cpl.stats.maxgrace; 00420 00421 box.x = 0; 00422 box.y = 0; 00423 box.h = Bitmaps[BITMAP_GRACE]->bitmap->h; 00424 box.w = (int) (Bitmaps[BITMAP_GRACE]->bitmap->w * temp); 00425 00426 if (tmp && !box.w) 00427 { 00428 box.w = 1; 00429 } 00430 00431 if (box.w > Bitmaps[BITMAP_GRACE]->bitmap->w) 00432 { 00433 box.w = Bitmaps[BITMAP_GRACE]->bitmap->w; 00434 } 00435 00436 sprite_blt(Bitmaps[BITMAP_GRACE_BACK], widget->x1 + 57, widget->y1 + 71, NULL, NULL); 00437 sprite_blt(Bitmaps[BITMAP_GRACE], widget->x1 + 57, widget->y1 + 71, &box, NULL); 00438 } 00439 00440 /* Food bar */ 00441 tmp = cpl.stats.food; 00442 00443 if (tmp < 0) 00444 { 00445 tmp = 0; 00446 } 00447 00448 temp = (double) tmp / 1000; 00449 box.x = 0; 00450 box.y = 0; 00451 box.h = Bitmaps[BITMAP_FOOD]->bitmap->h; 00452 box.w = (int) (Bitmaps[BITMAP_FOOD]->bitmap->w * temp); 00453 00454 if (tmp && !box.w) 00455 { 00456 box.w = 1; 00457 } 00458 00459 if (box.w > Bitmaps[BITMAP_FOOD]->bitmap->w) 00460 { 00461 box.w = Bitmaps[BITMAP_FOOD]->bitmap->w; 00462 } 00463 00464 sprite_blt(Bitmaps[BITMAP_FOOD_BACK], widget->x1 + 87, widget->y1 + 88, NULL, NULL); 00465 sprite_blt(Bitmaps[BITMAP_FOOD], widget->x1 + 87, widget->y1 + 88, &box, NULL); 00466 } 00467 00471 void widget_skillgroups(widgetdata *widget) 00472 { 00473 SDL_Rect box; 00474 00475 if (!widget->widgetSF) 00476 { 00477 widget->widgetSF = SDL_ConvertSurface(Bitmaps[BITMAP_SKILL_LVL_BG]->bitmap, Bitmaps[BITMAP_SKILL_LVL_BG]->bitmap->format, Bitmaps[BITMAP_SKILL_LVL_BG]->bitmap->flags); 00478 } 00479 00480 if (widget->redraw) 00481 { 00482 char buf[MAX_BUF]; 00483 _BLTFX bltfx; 00484 00485 widget->redraw = 0; 00486 bltfx.surface = widget->widgetSF; 00487 bltfx.flags = 0; 00488 bltfx.alpha = 0; 00489 sprite_blt(Bitmaps[BITMAP_SKILL_LVL_BG], 0, 0, NULL, &bltfx); 00490 00491 string_blt(widget->widgetSF, FONT_MONO10, "Skill", 12, 3, COLOR_HGOLD, TEXT_OUTLINE, NULL); 00492 string_blt(widget->widgetSF, FONT_MONO10, "Groups", 8, 14, COLOR_HGOLD, TEXT_OUTLINE, NULL); 00493 00494 /* Agility */ 00495 string_blt(widget->widgetSF, FONT_ARIAL10, "Ag:", 6, 26, COLOR_HGOLD, 0, NULL); 00496 snprintf(buf, sizeof(buf), "%d", cpl.stats.skill_level[0]); 00497 string_blt(widget->widgetSF, FONT_ARIAL10, buf, 47 - string_get_width(FONT_ARIAL10, buf, 0), 26, COLOR_WHITE, 0, NULL); 00498 00499 /* Mental */ 00500 string_blt(widget->widgetSF, FONT_ARIAL10, "Me:", 6, 38, COLOR_HGOLD, 0, NULL); 00501 snprintf(buf, sizeof(buf), " %d", cpl.stats.skill_level[2]); 00502 string_blt(widget->widgetSF, FONT_ARIAL10, buf, 47 - string_get_width(FONT_ARIAL10, buf, 0), 38, COLOR_WHITE, 0, NULL); 00503 00504 /* Magic */ 00505 string_blt(widget->widgetSF, FONT_ARIAL10, "Ma:", 6, 49, COLOR_HGOLD, 0, NULL); 00506 snprintf(buf, sizeof(buf), " %d", cpl.stats.skill_level[4]); 00507 string_blt(widget->widgetSF, FONT_ARIAL10, buf, 47 - string_get_width(FONT_ARIAL10, buf, 0), 49, COLOR_WHITE, 0, NULL); 00508 00509 /* Personality */ 00510 string_blt(widget->widgetSF, FONT_ARIAL10, "Pe:", 6, 62, COLOR_HGOLD, 0, NULL); 00511 snprintf(buf, sizeof(buf), " %d", cpl.stats.skill_level[1]); 00512 string_blt(widget->widgetSF, FONT_ARIAL10, buf, 47 - string_get_width(FONT_ARIAL10, buf, 0), 62, COLOR_WHITE, 0, NULL); 00513 00514 /* Physique */ 00515 string_blt(widget->widgetSF, FONT_ARIAL10, "Ph:", 6, 74, COLOR_HGOLD, 0, NULL); 00516 snprintf(buf, sizeof(buf), " %d", cpl.stats.skill_level[3]); 00517 string_blt(widget->widgetSF, FONT_ARIAL10, buf, 47 - string_get_width(FONT_ARIAL10, buf, 0), 74, COLOR_WHITE, 0, NULL); 00518 00519 /* Wisdom */ 00520 string_blt(widget->widgetSF, FONT_ARIAL10, "Wi:", 6, 86, COLOR_HGOLD, 0, NULL); 00521 snprintf(buf, sizeof(buf), " %d", cpl.stats.skill_level[5]); 00522 string_blt(widget->widgetSF, FONT_ARIAL10, buf, 47 - string_get_width(FONT_ARIAL10, buf, 0), 86, COLOR_WHITE, 0, NULL); 00523 } 00524 00525 box.x = widget->x1; 00526 box.y = widget->y1; 00527 SDL_BlitSurface(widget->widgetSF, NULL, ScreenSurface, &box); 00528 } 00529 00532 void widget_show_player_doll_event() 00533 { 00534 int old_inv_win = cpl.inventory_win, old_inv_tag = cpl.win_inv_tag; 00535 cpl.inventory_win = IWIN_INV; 00536 00537 if (draggingInvItem(DRAG_GET_STATUS) == DRAG_QUICKSLOT) 00538 { 00539 cpl.win_inv_tag = cpl.dragging.tag; 00540 00541 /* Drop to player doll */ 00542 if (!(object_find(cpl.win_inv_tag)->flags & F_APPLIED)) 00543 { 00544 keybind_process_command("?APPLY"); 00545 } 00546 } 00547 00548 if (draggingInvItem(DRAG_GET_STATUS) == DRAG_IWIN_INV) 00549 { 00550 if (object_find(cpl.win_inv_tag)->flags & F_APPLIED) 00551 { 00552 draw_info(COLOR_WHITE, "This is applied already!"); 00553 } 00554 /* Drop to player doll */ 00555 else 00556 { 00557 keybind_process_command("?APPLY"); 00558 } 00559 } 00560 00561 cpl.inventory_win = old_inv_win; 00562 cpl.win_inv_tag = old_inv_tag; 00563 00564 draggingInvItem(DRAG_NONE); 00565 } 00566 00570 void widget_show_player_doll(widgetdata *widget) 00571 { 00572 object *tmp; 00573 char *tooltip_text = NULL; 00574 int idx, tooltip_index = -1, ring_flag = 0; 00575 int mx, my; 00576 00577 /* This is ugly to calculate because it's a curve which increases heavily 00578 * with lower weapon_speed... So, we use a table */ 00579 int ws_temp = cpl.stats.weapon_sp; 00580 00581 if (ws_temp < 0) 00582 { 00583 ws_temp = 0; 00584 } 00585 else if (ws_temp > 18) 00586 { 00587 ws_temp = 18; 00588 } 00589 00590 sprite_blt(Bitmaps[BITMAP_DOLL], widget->x1, widget->y1, NULL, NULL); 00591 00592 if (!cpl.ob) 00593 { 00594 return; 00595 } 00596 00597 string_blt(ScreenSurface, FONT_SANS12, "<b>Ranged</b>", widget->x1 + 20, widget->y1 + 188, COLOR_HGOLD, TEXT_MARKUP, NULL); 00598 string_blt(ScreenSurface, FONT_ARIAL10, "DMG", widget->x1 + 9, widget->y1 + 205, COLOR_HGOLD, 0, NULL); 00599 string_blt_format(ScreenSurface, FONT_MONO10, widget->x1 + 40, widget->y1 + 205, COLOR_WHITE, 0, NULL, "%02d", cpl.stats.ranged_dam); 00600 string_blt(ScreenSurface, FONT_ARIAL10, "WC", widget->x1 + 10, widget->y1 + 215, COLOR_HGOLD, 0, NULL); 00601 string_blt_format(ScreenSurface, FONT_MONO10, widget->x1 + 40, widget->y1 + 215, COLOR_WHITE, 0, NULL, "%02d", cpl.stats.ranged_wc); 00602 string_blt(ScreenSurface, FONT_ARIAL10, "WS", widget->x1 + 10, widget->y1 + 225, COLOR_HGOLD, 0, NULL); 00603 string_blt_format(ScreenSurface, FONT_MONO10, widget->x1 + 40, widget->y1 + 225, COLOR_WHITE, 0, NULL, "%3.2fs", cpl.stats.ranged_ws / 1000.0); 00604 00605 string_blt(ScreenSurface, FONT_SANS12, "<b>Melee</b>", widget->x1 + 155, widget->y1 + 188, COLOR_HGOLD, TEXT_MARKUP, NULL); 00606 string_blt(ScreenSurface, FONT_ARIAL10, "DMG", widget->x1 + 139, widget->y1 + 205, COLOR_HGOLD, 0, NULL); 00607 string_blt_format(ScreenSurface, FONT_MONO10, widget->x1 + 170, widget->y1 + 205, COLOR_WHITE, 0, NULL, "%02d", cpl.stats.dam); 00608 string_blt(ScreenSurface, FONT_ARIAL10, "WC", widget->x1 + 140, widget->y1 + 215, COLOR_HGOLD, 0, NULL); 00609 string_blt_format(ScreenSurface, FONT_MONO10, widget->x1 + 170, widget->y1 + 215, COLOR_WHITE, 0, NULL, "%02d", cpl.stats.wc); 00610 string_blt(ScreenSurface, FONT_ARIAL10, "WS", widget->x1 + 140, widget->y1 + 225, COLOR_HGOLD, 0, NULL); 00611 string_blt_format(ScreenSurface, FONT_MONO10, widget->x1 + 170, widget->y1 + 225, COLOR_WHITE, 0, NULL, "%3.2fs", weapon_speed_table[ws_temp]); 00612 00613 string_blt(ScreenSurface, FONT_ARIAL10, "Speed", widget->x1 + 92, widget->y1 + 193, COLOR_HGOLD, 0, NULL); 00614 string_blt_format(ScreenSurface, FONT_MONO10, widget->x1 + 93, widget->y1 + 205, COLOR_WHITE, 0, NULL, "%3.2f", (float) cpl.stats.speed / FLOAT_MULTF); 00615 string_blt(ScreenSurface, FONT_ARIAL10, "AC", widget->x1 + 92, widget->y1 + 215, COLOR_HGOLD, 0, NULL); 00616 string_blt_format(ScreenSurface, FONT_MONO10, widget->x1 + 92, widget->y1 + 225, COLOR_WHITE, 0, NULL, "%02d", cpl.stats.ac); 00617 00618 /* Show items applied */ 00619 for (tmp = cpl.ob->inv; tmp; tmp = tmp->next) 00620 { 00621 if (tmp->flags & F_APPLIED) 00622 { 00623 idx = -1; 00624 00625 switch (tmp->itype) 00626 { 00627 case TYPE_ARMOUR: 00628 idx = PDOLL_ARMOUR; 00629 break; 00630 00631 case TYPE_HELMET: 00632 idx = PDOLL_HELM; 00633 break; 00634 00635 case TYPE_GIRDLE: 00636 idx = PDOLL_GIRDLE; 00637 break; 00638 00639 case TYPE_BOOTS: 00640 idx = PDOLL_BOOT; 00641 break; 00642 00643 case TYPE_WEAPON: 00644 idx = PDOLL_RHAND; 00645 break; 00646 00647 case TYPE_SHIELD: 00648 idx = PDOLL_LHAND; 00649 break; 00650 00651 case TYPE_RING: 00652 idx = PDOLL_RRING; 00653 break; 00654 00655 case TYPE_BRACERS: 00656 idx = PDOLL_BRACER; 00657 break; 00658 00659 case TYPE_AMULET: 00660 idx = PDOLL_AMULET; 00661 break; 00662 00663 case TYPE_SKILL_ITEM: 00664 idx = PDOLL_SKILL_ITEM; 00665 break; 00666 00667 case TYPE_BOW: 00668 idx = PDOLL_BOW; 00669 break; 00670 00671 case TYPE_GLOVES: 00672 idx = PDOLL_GAUNTLET; 00673 break; 00674 00675 case TYPE_CLOAK: 00676 idx = PDOLL_ROBE; 00677 break; 00678 00679 case TYPE_LIGHT_APPLY: 00680 idx = PDOLL_LIGHT; 00681 break; 00682 00683 case TYPE_WAND: 00684 case TYPE_ROD: 00685 case TYPE_HORN: 00686 idx = PDOLL_WAND; 00687 break; 00688 } 00689 00690 if (idx == PDOLL_RRING) 00691 { 00692 idx += ++ring_flag & 1; 00693 } 00694 00695 if (idx != -1) 00696 { 00697 int mb; 00698 blt_inv_item_centered(tmp, player_doll[idx].xpos + widget->x1, player_doll[idx].ypos + widget->y1); 00699 mb = SDL_GetMouseState(&mx, &my); 00700 00701 /* Prepare item name tooltip */ 00702 if (mx >= widget->x1 + player_doll[idx].xpos && mx < widget->x1 + player_doll[idx].xpos + 33 && my >= widget->y1 + player_doll[idx].ypos && my < widget->y1 + player_doll[idx].ypos + 33) 00703 { 00704 tooltip_index = idx; 00705 tooltip_text = tmp->s_name; 00706 00707 if ((mb & SDL_BUTTON(SDL_BUTTON_LEFT)) && !draggingInvItem(DRAG_GET_STATUS)) 00708 { 00709 cpl.win_pdoll_tag = tmp->tag; 00710 draggingInvItem(DRAG_PDOLL); 00711 } 00712 } 00713 } 00714 } 00715 } 00716 00717 /* Draw item name tooltip */ 00718 if (tooltip_index != -1) 00719 { 00720 tooltip_create(mx, my, FONT_ARIAL10, tooltip_text); 00721 } 00722 } 00723 00730 void widget_show_main_lvl(widgetdata *widget) 00731 { 00732 SDL_Rect box; 00733 00734 if (!widget->widgetSF) 00735 { 00736 widget->widgetSF = SDL_ConvertSurface(Bitmaps[BITMAP_MAIN_LVL_BG]->bitmap, Bitmaps[BITMAP_MAIN_LVL_BG]->bitmap->format, Bitmaps[BITMAP_MAIN_LVL_BG]->bitmap->flags); 00737 } 00738 00739 if (widget->redraw) 00740 { 00741 char buf[MAX_BUF]; 00742 double multi, line; 00743 int s; 00744 sint64 level_exp; 00745 _BLTFX bltfx; 00746 00747 widget->redraw = 0; 00748 bltfx.surface = widget->widgetSF; 00749 bltfx.flags = 0; 00750 bltfx.alpha = 0; 00751 00752 sprite_blt(Bitmaps[BITMAP_MAIN_LVL_BG], 0, 0, NULL, &bltfx); 00753 00754 string_blt(widget->widgetSF, FONT_ARIAL10, "Level / Exp", 5, 5, COLOR_HGOLD, TEXT_OUTLINE, NULL); 00755 00756 snprintf(buf, sizeof(buf), "<b>%d</b>", cpl.stats.level); 00757 string_blt(widget->widgetSF, FONT_SERIF14, buf, widget->wd - 4 - string_get_width(FONT_SERIF14, buf, TEXT_MARKUP), 4, cpl.stats.level == s_settings->max_level ? COLOR_HGOLD : COLOR_WHITE, TEXT_MARKUP, NULL); 00758 00759 string_blt_format(widget->widgetSF, FONT_ARIAL10, 5, 20, COLOR_WHITE, 0, NULL, "%"FMT64, cpl.stats.exp); 00760 00761 /* Calculate the exp bubbles */ 00762 level_exp = cpl.stats.exp - s_settings->level_exp[cpl.stats.level]; 00763 multi = modf(((double) level_exp / (double) (s_settings->level_exp[cpl.stats.level + 1] - s_settings->level_exp[cpl.stats.level]) * 10.0), &line); 00764 00765 sprite_blt(Bitmaps[BITMAP_EXP_BORDER], 9, 49, NULL, &bltfx); 00766 00767 if (multi) 00768 { 00769 box.x = 0; 00770 box.y = 0; 00771 box.h = Bitmaps[BITMAP_EXP_SLIDER]->bitmap->h; 00772 box.w = (int) (Bitmaps[BITMAP_EXP_SLIDER]->bitmap->w * multi); 00773 00774 if (!box.w) 00775 { 00776 box.w = 1; 00777 } 00778 00779 if (box.w > Bitmaps[BITMAP_EXP_SLIDER]->bitmap->w) 00780 { 00781 box.w = Bitmaps[BITMAP_EXP_SLIDER]->bitmap->w; 00782 } 00783 00784 sprite_blt(Bitmaps[BITMAP_EXP_SLIDER], 9, 49, &box, &bltfx); 00785 } 00786 00787 for (s = 0; s < 10; s++) 00788 { 00789 sprite_blt(Bitmaps[BITMAP_EXP_BUBBLE2], 10 + s * 8, 40, NULL, &bltfx); 00790 } 00791 00792 for (s = 0; s < (int) line; s++) 00793 { 00794 sprite_blt(Bitmaps[BITMAP_EXP_BUBBLE1], 10 + s * 8, 40, NULL, &bltfx); 00795 } 00796 } 00797 00798 box.x = widget->x1; 00799 box.y = widget->y1; 00800 SDL_BlitSurface(widget->widgetSF, NULL, ScreenSurface, &box); 00801 } 00802 00806 void widget_show_skill_exp(widgetdata *widget) 00807 { 00808 SDL_Rect box; 00809 static uint32 action_tick = 0; 00810 00811 /* Pre-emptively tick down the skill delay timer */ 00812 if (cpl.action_timer > 0) 00813 { 00814 if (LastTick - action_tick > 125) 00815 { 00816 cpl.action_timer -= (float) (LastTick - action_tick) / 1000.0f; 00817 00818 if (cpl.action_timer < 0) 00819 { 00820 cpl.action_timer = 0; 00821 } 00822 00823 action_tick = LastTick; 00824 WIDGET_REDRAW(widget); 00825 } 00826 } 00827 else 00828 { 00829 action_tick = LastTick; 00830 } 00831 00832 if (!widget->widgetSF) 00833 { 00834 widget->widgetSF = SDL_ConvertSurface(Bitmaps[BITMAP_SKILL_EXP_BG]->bitmap, Bitmaps[BITMAP_SKILL_EXP_BG]->bitmap->format, Bitmaps[BITMAP_SKILL_EXP_BG]->bitmap->flags); 00835 } 00836 00837 if (widget->redraw) 00838 { 00839 int s; 00840 sint64 level_exp; 00841 _BLTFX bltfx; 00842 char buf[MAX_BUF]; 00843 sint64 liLExp = 0; 00844 sint64 liLExpTNL = 0; 00845 sint64 liTExp = 0; 00846 sint64 liTExpTNL = 0; 00847 double fLExpPercent = 0; 00848 double multi = 0, line = 0; 00849 00850 widget->redraw = 0; 00851 bltfx.surface = widget->widgetSF; 00852 bltfx.flags = 0; 00853 bltfx.alpha = 0; 00854 00855 sprite_blt(Bitmaps[BITMAP_SKILL_EXP_BG], 0, 0, NULL, &bltfx); 00856 00857 string_blt(widget->widgetSF, FONT_ARIAL10, "Used", 4, 0, COLOR_HGOLD, TEXT_OUTLINE, NULL); 00858 string_blt(widget->widgetSF, FONT_ARIAL10, "Skill", 5, 9, COLOR_HGOLD, TEXT_OUTLINE, NULL); 00859 00860 if (cpl.skill_name[0] != '\0') 00861 { 00862 switch (setting_get_int(OPT_CAT_GENERAL, OPT_EXP_DISPLAY)) 00863 { 00864 /* Default */ 00865 default: 00866 case 0: 00867 snprintf(buf, sizeof(buf), "%s", cpl.skill_name); 00868 break; 00869 00870 /* LExp% || LExp/LExp tnl || TExp/TExp tnl || (LExp%) LExp/LExp tnl */ 00871 case 1: 00872 case 2: 00873 case 3: 00874 case 4: 00875 if (cpl.skill && (cpl.skill->exp >= 0 || cpl.skill->exp == -2)) 00876 { 00877 snprintf(buf, sizeof(buf), "%s - level: %d", cpl.skill_name, cpl.skill->level); 00878 } 00879 else 00880 { 00881 snprintf(buf, sizeof(buf), "%s - level: **", cpl.skill_name); 00882 } 00883 00884 break; 00885 } 00886 00887 string_blt(widget->widgetSF, FONT_ARIAL10, buf, 28, 0, COLOR_WHITE, 0, NULL); 00888 00889 if (cpl.skill && cpl.skill->exp >= 0) 00890 { 00891 level_exp = cpl.skill->exp - s_settings->level_exp[cpl.skill->level]; 00892 multi = modf(((double) level_exp / (double) (s_settings->level_exp[cpl.skill->level + 1] - s_settings->level_exp[cpl.skill->level]) * 10.0), &line); 00893 00894 liTExp = cpl.skill->exp; 00895 liTExpTNL = s_settings->level_exp[cpl.skill->level + 1]; 00896 00897 liLExp = liTExp - s_settings->level_exp[cpl.skill->level]; 00898 liLExpTNL = liTExpTNL - s_settings->level_exp[cpl.skill->level]; 00899 00900 fLExpPercent = ((float) liLExp / (float) (liLExpTNL)) * 100.0f; 00901 } 00902 00903 switch (setting_get_int(OPT_CAT_GENERAL, OPT_EXP_DISPLAY)) 00904 { 00905 /* Default */ 00906 default: 00907 case 0: 00908 if (cpl.skill && cpl.skill->exp >= 0) 00909 { 00910 snprintf(buf, sizeof(buf), "%d / %-9"FMT64, cpl.skill->level, cpl.skill->exp); 00911 } 00912 else if (cpl.skill && cpl.skill->exp == -2) 00913 { 00914 snprintf(buf, sizeof(buf), "%d / **", cpl.skill->level); 00915 } 00916 else 00917 { 00918 snprintf(buf, sizeof(buf), "** / **"); 00919 } 00920 00921 break; 00922 00923 /* LExp% */ 00924 case 1: 00925 if (cpl.skill && cpl.skill->exp >= 0) 00926 { 00927 snprintf(buf, sizeof(buf), "%#05.2f%%", fLExpPercent); 00928 } 00929 else 00930 { 00931 snprintf(buf, sizeof(buf), "**.**%%"); 00932 } 00933 00934 break; 00935 00936 /* LExp/LExp tnl */ 00937 case 2: 00938 if (cpl.skill && cpl.skill->exp >= 0) 00939 { 00940 snprintf(buf, sizeof(buf), "%"FMT64" / %"FMT64, liLExp, liLExpTNL); 00941 } 00942 else 00943 { 00944 snprintf(buf, sizeof(buf), "** / **"); 00945 } 00946 00947 break; 00948 00949 /* TExp/TExp tnl */ 00950 case 3: 00951 if (cpl.skill && cpl.skill->exp >= 0) 00952 { 00953 snprintf(buf, sizeof(buf), "%"FMT64" / %"FMT64, liTExp, liTExpTNL); 00954 } 00955 else 00956 { 00957 snprintf(buf, sizeof(buf), "** / **"); 00958 } 00959 00960 break; 00961 00962 /* (LExp%) LExp/LExp tnl */ 00963 case 4: 00964 if (cpl.skill && cpl.skill->exp >= 0) 00965 { 00966 snprintf(buf, sizeof(buf), "%#05.2f%% - %"FMT64, fLExpPercent, liLExpTNL - liLExp); 00967 } 00968 else 00969 { 00970 snprintf(buf, sizeof(buf), "(**.**%%) **"); 00971 } 00972 00973 break; 00974 } 00975 00976 if (cpl.skill && (uint32) cpl.skill->level == s_settings->max_level) 00977 { 00978 strncpy(buf, "Maximum level reached", sizeof(buf) - 1); 00979 } 00980 00981 string_blt(widget->widgetSF, FONT_ARIAL10, buf, 28, 9, COLOR_WHITE, 0, NULL); 00982 00983 snprintf(buf, sizeof(buf), "%1.2f sec", cpl.action_timer); 00984 string_blt(widget->widgetSF, FONT_ARIAL10, buf, widget->wd - 3 - string_get_width(FONT_ARIAL10, buf, 0), 0, COLOR_WHITE, 0, NULL); 00985 } 00986 00987 sprite_blt(Bitmaps[BITMAP_EXP_SKILL_BORDER], 142, 11, NULL, &bltfx); 00988 00989 if (multi) 00990 { 00991 box.x = 0; 00992 box.y = 0; 00993 box.h = Bitmaps[BITMAP_EXP_SKILL_LINE]->bitmap->h; 00994 box.w = (int) (Bitmaps[BITMAP_EXP_SKILL_LINE]->bitmap->w * multi); 00995 00996 if (!box.w) 00997 { 00998 box.w = 1; 00999 } 01000 01001 if (box.w > Bitmaps[BITMAP_EXP_SKILL_LINE]->bitmap->w) 01002 { 01003 box.w = Bitmaps[BITMAP_EXP_SKILL_LINE]->bitmap->w; 01004 } 01005 01006 sprite_blt(Bitmaps[BITMAP_EXP_SKILL_LINE], 145, 18, &box, &bltfx); 01007 } 01008 01009 if (line > 0) 01010 { 01011 for (s = 0; s < (int) line; s++) 01012 { 01013 sprite_blt(Bitmaps[BITMAP_EXP_SKILL_BUBBLE], 145 + s * 5, 13, NULL, &bltfx); 01014 } 01015 } 01016 } 01017 01018 box.x = widget->x1; 01019 box.y = widget->y1; 01020 SDL_BlitSurface(widget->widgetSF, NULL, ScreenSurface, &box); 01021 } 01022 01026 void widget_show_regeneration(widgetdata *widget) 01027 { 01028 SDL_Rect box; 01029 01030 if (!widget->widgetSF) 01031 { 01032 widget->widgetSF = SDL_ConvertSurface(Bitmaps[BITMAP_REGEN_BG]->bitmap, Bitmaps[BITMAP_REGEN_BG]->bitmap->format, Bitmaps[BITMAP_REGEN_BG]->bitmap->flags); 01033 } 01034 01035 if (widget->redraw) 01036 { 01037 char buf[MAX_BUF]; 01038 _BLTFX bltfx; 01039 01040 widget->redraw = 0; 01041 bltfx.surface = widget->widgetSF; 01042 bltfx.flags = 0; 01043 bltfx.alpha = 0; 01044 01045 sprite_blt(Bitmaps[BITMAP_REGEN_BG], 0, 0, NULL, &bltfx); 01046 01047 string_blt(widget->widgetSF, FONT_SANS8, "R", 4, 1, COLOR_HGOLD, TEXT_OUTLINE, NULL); 01048 string_blt(widget->widgetSF, FONT_SANS8, "e", 4, 7, COLOR_HGOLD, TEXT_OUTLINE, NULL); 01049 string_blt(widget->widgetSF, FONT_SANS8, "g", 4, 13, COLOR_HGOLD, TEXT_OUTLINE, NULL); 01050 string_blt(widget->widgetSF, FONT_SANS8, "e", 4, 21, COLOR_HGOLD, TEXT_OUTLINE, NULL); 01051 string_blt(widget->widgetSF, FONT_SANS8, "n", 4, 27, COLOR_HGOLD, TEXT_OUTLINE, NULL); 01052 01053 /* Health */ 01054 string_blt(widget->widgetSF, FONT_ARIAL10, "HP:", 13, 3, COLOR_HGOLD, 0, NULL); 01055 snprintf(buf, sizeof(buf), "%2.1f/s", cpl.gen_hp); 01056 string_truncate_overflow(FONT_ARIAL10, buf, 45); 01057 string_blt(widget->widgetSF, FONT_ARIAL10, buf, widget->wd - 5 - string_get_width(FONT_ARIAL10, buf, 0), 3, COLOR_WHITE, 0, NULL); 01058 01059 /* Mana */ 01060 string_blt(widget->widgetSF, FONT_ARIAL10, "Mana:", 13, 13, COLOR_HGOLD, 0, NULL); 01061 snprintf(buf, sizeof(buf), "%2.1f/s", cpl.gen_sp); 01062 string_truncate_overflow(FONT_ARIAL10, buf, 45); 01063 string_blt(widget->widgetSF, FONT_ARIAL10, buf, widget->wd - 5 - string_get_width(FONT_ARIAL10, buf, 0), 13, COLOR_WHITE, 0, NULL); 01064 01065 /* Grace */ 01066 string_blt(widget->widgetSF, FONT_ARIAL10, "Grace:", 13, 23, COLOR_HGOLD, 0, NULL); 01067 snprintf(buf, sizeof(buf), "%2.1f/s", cpl.gen_grace); 01068 string_truncate_overflow(FONT_ARIAL10, buf, 45); 01069 string_blt(widget->widgetSF, FONT_ARIAL10, buf, widget->wd - 5 - string_get_width(FONT_ARIAL10, buf, 0), 23, COLOR_WHITE, 0, NULL); 01070 } 01071 01072 box.x = widget->x1; 01073 box.y = widget->y1; 01074 SDL_BlitSurface(widget->widgetSF, NULL, ScreenSurface, &box); 01075 } 01076 01080 void widget_show_container(widgetdata *widget) 01081 { 01082 SDL_Rect box, box2; 01083 int x = widget->x1; 01084 int y = widget->y1; 01085 01086 /* special case, menuitem is highlighted when mouse is moved over it */ 01087 if (widget->WidgetSubtypeID == MENU_ID) 01088 { 01089 widget_highlight_menu(widget); 01090 } 01091 01092 box.x = box.y = 0; 01093 box.w = widget->wd; 01094 box.h = widget->ht; 01095 01096 /* if we don't have a backbuffer, create it */ 01097 if (!widget->widgetSF) 01098 { 01099 widget->widgetSF = SDL_ConvertSurface(Bitmaps[BITMAP_TEXTWIN_MASK]->bitmap, Bitmaps[BITMAP_TEXTWIN_MASK]->bitmap->format, Bitmaps[BITMAP_TEXTWIN_MASK]->bitmap->flags); 01100 } 01101 01102 if (widget->redraw) 01103 { 01104 widget->redraw = 0; 01105 01106 SDL_FillRect(widget->widgetSF, NULL, 0); 01107 01108 box.x = 0; 01109 box.y = 0; 01110 box.h = 1; 01111 box.w = widget->wd; 01112 SDL_FillRect(widget->widgetSF, &box, SDL_MapRGBA(widget->widgetSF->format, 0x60, 0x60, 0x60, 255)); 01113 box.y = widget->ht; 01114 box.h = 1; 01115 box.x = 0; 01116 box.w = widget->wd; 01117 SDL_FillRect(widget->widgetSF, &box, SDL_MapRGBA(widget->widgetSF->format, 0x60, 0x60, 0x60, 255)); 01118 box.w = widget->wd; 01119 box.x = box.w - 1; 01120 box.w = 1; 01121 box.y = 0; 01122 box.h = widget->ht; 01123 SDL_FillRect(widget->widgetSF, &box, SDL_MapRGBA(widget->widgetSF->format, 0x60, 0x60, 0x60, 255)); 01124 box.x = 0; 01125 box.y = 0; 01126 box.h = widget->ht; 01127 box.w = 1; 01128 SDL_FillRect(widget->widgetSF, &box, SDL_MapRGBA(widget->widgetSF->format, 0x60, 0x60, 0x60, 255)); 01129 } 01130 01131 box.x = x; 01132 box.y = y; 01133 box2.x = 0; 01134 box2.y = 0; 01135 box2.w = widget->wd; 01136 box2.h = widget->ht + 1; 01137 01138 SDL_BlitSurface(widget->widgetSF, &box2, ScreenSurface, &box); 01139 } 01140 01141 /* Handles highlighting of menuitems when the cursor is hovering over them. */ 01142 void widget_highlight_menu(widgetdata *widget) 01143 { 01144 widgetdata *tmp, *tmp2, *tmp3; 01145 _menu *menu = NULL, *tmp_menu = NULL; 01146 _menuitem *menuitem = NULL; 01147 int visible, create_submenu = 0, x = 0, y = 0; 01148 01149 /* Sanity check. Make sure widget is a menu. */ 01150 if (!widget || widget->WidgetSubtypeID != MENU_ID) 01151 { 01152 return; 01153 } 01154 01155 /* Check to see if the cursor is hovering over a menuitem or a widget inside it. 01156 * We don't need to go recursive here, just scan the immediate children. */ 01157 for (tmp = widget->inv; tmp; tmp = tmp->next) 01158 { 01159 visible = 0; 01160 01161 /* Menuitem is being directly hovered over. Make the background visible for visual feedback. */ 01162 if (tmp == widget_mouse_event.owner) 01163 { 01164 visible = 1; 01165 } 01166 /* The cursor is hovering over something the menuitem contains. This only needs to search the direct children, 01167 * as there should be nothing contained within the children. */ 01168 else if (tmp->inv) 01169 { 01170 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp2->next) 01171 { 01172 if (tmp2 == widget_mouse_event.owner) 01173 { 01174 /* The cursor was hovering over something inside the menuitem. */ 01175 visible = 1; 01176 break; 01177 } 01178 } 01179 } 01180 01181 /* Only do any real working if the state of the menuitem changed. */ 01182 if (tmp->visible == visible) 01183 { 01184 continue; 01185 } 01186 01187 menu = MENU(widget); 01188 menuitem = MENUITEM(tmp); 01189 01190 /* Cursor has just started to hover over the menuitem. */ 01191 if (visible) 01192 { 01193 tmp->visible = 1; 01194 01195 /* If the highlighted menuitem is a submenu, we need to create a submenu next to the menuitem. */ 01196 if (menuitem->menu_type == MENU_SUBMENU) 01197 { 01198 create_submenu = 1; 01199 x = tmp->x1 + widget->wd - 4; 01200 y = tmp->y1 - (CONTAINER(widget))->outer_padding_top; 01201 } 01202 } 01203 /* Cursor no longer hovers over the menuitem. */ 01204 else 01205 { 01206 tmp->visible = 0; 01207 01208 /* Let's check if we need to remove the submenu. 01209 * Don't remove it if the cursor is hovering over the submenu itself, 01210 * or a submenu of the submenu, etc. */ 01211 if (menuitem->menu_type == MENU_SUBMENU && menu->submenu) 01212 { 01213 /* This will for sure get the menu that the cursor is hovering over. */ 01214 tmp2 = get_outermost_container(widget_mouse_event.owner); 01215 01216 /* Just in case the 'for sure' part of the last comment turns out to be incorrect... */ 01217 if (tmp2 && tmp2->WidgetSubtypeID == MENU_ID) 01218 { 01219 /* Loop through the submenus to see if we find a match for the menu the cursor is hovering over. */ 01220 for (tmp_menu = menu; tmp_menu->submenu && tmp_menu->submenu != tmp2; tmp_menu = MENU(tmp_menu->submenu)) 01221 { 01222 } 01223 01224 /* Remove any submenus related to menu if the menu underneath the cursor is not a submenu of menu. */ 01225 if (!tmp_menu->submenu) 01226 { 01227 tmp2 = menu->submenu; 01228 01229 while (tmp2) 01230 { 01231 tmp3 = (MENU(tmp2))->submenu; 01232 remove_widget_object(tmp2); 01233 tmp2 = tmp3; 01234 } 01235 01236 menu->submenu = NULL; 01237 } 01238 else 01239 { 01240 /* Cursor is hovering over the submenu, so leave this menuitem highlighted. */ 01241 tmp->visible = 1; 01242 } 01243 } 01244 /* Cursor is not over a menu, so leave the menuitem containing the submenu highlighted. 01245 * We want to keep the submenu open, which should reduce annoyance if the user is not precise with the mouse. */ 01246 else 01247 { 01248 tmp->visible = 1; 01249 } 01250 } 01251 } 01252 } 01253 01254 /* If a submenu needs to be created, create it now. Make sure there can be only one submenu open here. */ 01255 if (create_submenu && !menu->submenu) 01256 { 01257 tmp_menu = MENU(widget); 01258 01259 tmp_menu->submenu = create_menu(x, y, tmp_menu->owner); 01260 01261 if (tmp_menu->owner->WidgetTypeID == MAIN_INV_ID) 01262 { 01263 add_menuitem(tmp_menu->submenu, "All", &menu_inv_filter_all, MENU_CHECKBOX, inventory_filter == INVENTORY_FILTER_ALL); 01264 add_menuitem(tmp_menu->submenu, "Applied", &menu_inv_filter_applied, MENU_CHECKBOX, inventory_filter & INVENTORY_FILTER_APPLIED); 01265 add_menuitem(tmp_menu->submenu, "Unapplied", &menu_inv_filter_unapplied, MENU_CHECKBOX, inventory_filter & INVENTORY_FILTER_UNAPPLIED); 01266 add_menuitem(tmp_menu->submenu, "Containers", &menu_inv_filter_containers, MENU_CHECKBOX, inventory_filter & INVENTORY_FILTER_CONTAINER); 01267 add_menuitem(tmp_menu->submenu, "Magical", &menu_inv_filter_magical, MENU_CHECKBOX, inventory_filter & INVENTORY_FILTER_MAGICAL); 01268 add_menuitem(tmp_menu->submenu, "Cursed", &menu_inv_filter_cursed, MENU_CHECKBOX, inventory_filter & INVENTORY_FILTER_CURSED); 01269 add_menuitem(tmp_menu->submenu, "Unidentified", &menu_inv_filter_unidentified, MENU_CHECKBOX, inventory_filter & INVENTORY_FILTER_UNIDENTIFIED); 01270 add_menuitem(tmp_menu->submenu, "Locked", &menu_inv_filter_locked, MENU_CHECKBOX, inventory_filter & INVENTORY_FILTER_LOCKED); 01271 } 01272 else 01273 { 01274 /* TODO: Remove this later. It's hardcoded here for testing. */ 01275 submenu_chatwindow_filters(tmp_menu->submenu, 0, 0); 01276 add_menuitem(tmp_menu->submenu, "Test", &menu_detach_widget, MENU_SUBMENU, 0); 01277 add_menuitem(tmp_menu->submenu, "Test2", &menu_detach_widget, MENU_SUBMENU, 0); 01278 } 01279 01280 menu_finalize(tmp_menu->submenu); 01281 } 01282 } 01283 01285 void widget_menu_event(widgetdata *widget, int x, int y) 01286 { 01287 widgetdata *tmp; 01288 _menuitem *menuitem; 01289 01290 /* Bypass this code when unnecessary, such as when a menu doesn't exist. */ 01291 if (!cur_widget[MENU_ID]) 01292 { 01293 return; 01294 } 01295 01296 tmp = widget; 01297 01298 /* If the widget isn't a menuitem, the user probably clicked on a widget it contains. 01299 * In that case, the parent is probably the menuitem, so grab that instead. */ 01300 if (tmp->WidgetSubtypeID != MENUITEM_ID && tmp->env && tmp->env->WidgetSubtypeID == MENUITEM_ID) 01301 { 01302 tmp = tmp->env; 01303 } 01304 01305 /* Make sure the menuitem is in a menu first as a sanity check. If so, we found the menu. */ 01306 if (tmp->env && tmp->env->WidgetSubtypeID == MENU_ID) 01307 { 01308 menuitem = MENUITEM(tmp); 01309 /* Get the owner of the menu to do the operations on, 01310 * (this is what the user would have right clicked on). 01311 * Make it the mouse owner as this is what the user is interacting with. */ 01312 widget_mouse_event.owner = (MENU(tmp->env))->owner; 01313 01314 if (widget_mouse_event.owner) 01315 { 01316 widget_menuitem_event(widget_mouse_event.owner, x, y, menuitem->menu_func_ptr); 01317 } 01318 } 01319 } 01320 01322 void widget_menuitem_event(widgetdata *widget, int x, int y, void (*menu_func_ptr)(widgetdata *, int, int)) 01323 { 01324 /* sanity check */ 01325 if (!menu_func_ptr) 01326 { 01327 return; 01328 } 01329 01330 menu_func_ptr(widget, x, y); 01331 } 01332 01333 void widget_show_label(widgetdata *widget) 01334 { 01335 _widget_label *label = LABEL(widget); 01336 01337 string_blt(ScreenSurface, label->font, label->text, widget->x1, widget->y1, label->color, 0, NULL); 01338 } 01339 01340 void widget_show_bitmap(widgetdata *widget) 01341 { 01342 _widget_bitmap *bitmap = BITMAP(widget); 01343 01344 sprite_blt(Bitmaps[bitmap->bitmap_id], widget->x1, widget->y1, NULL, NULL); 01345 } 01346 01352 int gender_to_id(const char *gender) 01353 { 01354 size_t i; 01355 01356 for (i = 0; i < GENDER_MAX; i++) 01357 { 01358 if (!strcmp(gender_noun[i], gender)) 01359 { 01360 return i; 01361 } 01362 } 01363 01364 return -1; 01365 }
1.7.4