|
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 MAP_NAME_FONT FONT_SERIF14 00034 00035 static struct Map the_map; 00036 static SDL_Surface *zoomed = NULL; 00037 00039 _mapdata MapData; 00040 00041 static _multi_part_obj MultiArchs[16]; 00042 00044 static int old_map_mouse_x = 0, old_map_mouse_y = 0; 00048 static int right_click_ticks = -1; 00049 00050 /* Load the multi arch offsets */ 00051 void load_mapdef_dat() 00052 { 00053 FILE *stream; 00054 int i, ii, x, y, d[32]; 00055 char line[256]; 00056 00057 if (!(stream = fopen_wrapper(ARCHDEF_FILE, "r"))) 00058 { 00059 LOG(llevBug, "Can't find file %s\n", ARCHDEF_FILE); 00060 return; 00061 } 00062 00063 for (i = 0; i < 16; i++) 00064 { 00065 if (!fgets(line, 255, stream)) 00066 { 00067 break; 00068 } 00069 00070 sscanf(line, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", &x, &y, &d[0],&d[1], &d[2], &d[3], &d[4], &d[5], &d[6], &d[7], &d[8], &d[9], &d[10], &d[11], &d[12], &d[13], &d[14], &d[15], &d[16], &d[17], &d[18], &d[19], &d[20], &d[21], &d[22], &d[23], &d[24], &d[25], &d[26], &d[27], &d[28], &d[29], &d[30], &d[31]); 00071 MultiArchs[i].xlen = x; 00072 MultiArchs[i].ylen = y; 00073 00074 for (ii = 0; ii < 16; ii++) 00075 { 00076 MultiArchs[i].part[ii].xoff = d[ii * 2]; 00077 MultiArchs[i].part[ii].yoff = d[ii * 2 + 1]; 00078 } 00079 } 00080 00081 fclose(stream); 00082 } 00083 00088 void widget_show_mapname(widgetdata *widget) 00089 { 00090 SDL_Rect box; 00091 00092 box.w = widget->wd; 00093 box.h = 0; 00094 string_blt(ScreenSurface, MAP_NAME_FONT, MapData.name, widget->x1, widget->y1, COLOR_HGOLD, TEXT_MARKUP, &box); 00095 } 00096 00099 void clear_map() 00100 { 00101 memset(&the_map, 0, sizeof(Map)); 00102 } 00103 00108 void display_mapscroll(int dx, int dy) 00109 { 00110 int x, y; 00111 struct Map newmap; 00112 00113 for (x = 0; x < setting_get_int(OPT_CAT_MAP, OPT_MAP_WIDTH); x++) 00114 { 00115 for (y = 0; y < setting_get_int(OPT_CAT_MAP, OPT_MAP_HEIGHT); y++) 00116 { 00117 if (x + dx < 0 || x + dx >= setting_get_int(OPT_CAT_MAP, OPT_MAP_WIDTH) || y + dy < 0 || y + dy >= setting_get_int(OPT_CAT_MAP, OPT_MAP_HEIGHT)) 00118 { 00119 memset((char *) &(newmap.cells[x][y]), 0, sizeof(struct MapCell)); 00120 } 00121 else 00122 { 00123 memcpy((char *) &(newmap.cells[x][y]), (char *) &(the_map.cells[x + dx][y + dy]), sizeof(struct MapCell)); 00124 } 00125 } 00126 } 00127 00128 memcpy((char *) &the_map, (char *) & newmap, sizeof(struct Map)); 00129 } 00130 00134 void update_map_name(const char *name) 00135 { 00136 widgetdata *widget; 00137 00138 strncpy(MapData.name, name, sizeof(MapData.name) - 1); 00139 MapData.name[sizeof(MapData.name) - 1] = '\0'; 00140 00141 /* We need to update all mapname widgets on the screen now. 00142 * Not that there should be more than one at a time, but just in case. */ 00143 for (widget = cur_widget[MAPNAME_ID]; widget; widget = widget->type_next) 00144 { 00145 resize_widget(widget, RESIZE_RIGHT, string_get_width(MAP_NAME_FONT, name, TEXT_MARKUP)); 00146 resize_widget(widget, RESIZE_BOTTOM, string_get_height(MAP_NAME_FONT, name, TEXT_MARKUP)); 00147 } 00148 } 00149 00153 void update_map_weather(const char *weather) 00154 { 00155 effect_start(weather); 00156 } 00157 00164 void init_map_data(int xl, int yl, int px, int py) 00165 { 00166 if (xl != -1) 00167 { 00168 MapData.xlen = xl; 00169 } 00170 00171 if (yl != -1) 00172 { 00173 MapData.ylen = yl; 00174 } 00175 00176 if (px != -1) 00177 { 00178 MapData.posx = px; 00179 } 00180 00181 if (py != -1) 00182 { 00183 MapData.posy = py; 00184 } 00185 00186 if (xl > 0) 00187 { 00188 clear_map(); 00189 } 00190 } 00191 00199 static int calc_map_cell_height(int x, int y) 00200 { 00201 if (x >= 0 && x < setting_get_int(OPT_CAT_MAP, OPT_MAP_WIDTH) && y >= 0 && y < setting_get_int(OPT_CAT_MAP, OPT_MAP_HEIGHT)) 00202 { 00203 return the_map.cells[x][y].height[1]; 00204 } 00205 00206 return 0; 00207 } 00208 00209 #define MAX_STRETCH 8 00210 #define MAX_STRETCH_DIAG 12 00211 00216 void align_tile_stretch(int x, int y) 00217 { 00218 uint8 top, bottom, right, left, min_ht; 00219 uint32 h; 00220 int nw_height, n_height, ne_height, sw_height, s_height, se_height, w_height, e_height, my_height; 00221 00222 if (x < 0 || y < 0 || x >= setting_get_int(OPT_CAT_MAP, OPT_MAP_WIDTH) || y >= setting_get_int(OPT_CAT_MAP, OPT_MAP_HEIGHT)) 00223 { 00224 return; 00225 } 00226 00227 nw_height = calc_map_cell_height(x - 1, y - 1); 00228 n_height = calc_map_cell_height(x, y - 1); 00229 ne_height = calc_map_cell_height(x + 1, y - 1); 00230 sw_height = calc_map_cell_height(x - 1, y + 1); 00231 s_height = calc_map_cell_height(x, y + 1); 00232 se_height = calc_map_cell_height(x + 1, y + 1); 00233 w_height = calc_map_cell_height(x - 1, y); 00234 e_height = calc_map_cell_height(x + 1, y); 00235 my_height = calc_map_cell_height(x, y); 00236 00237 if (abs(my_height - e_height) > MAX_STRETCH) 00238 { 00239 e_height = my_height; 00240 } 00241 00242 if (abs(my_height - se_height) > MAX_STRETCH_DIAG) 00243 { 00244 se_height = my_height; 00245 } 00246 00247 if (abs(my_height - s_height) > MAX_STRETCH) 00248 { 00249 s_height = my_height; 00250 } 00251 00252 if (abs(my_height - sw_height) > MAX_STRETCH_DIAG) 00253 { 00254 sw_height = my_height; 00255 } 00256 00257 if (abs(my_height - w_height) > MAX_STRETCH) 00258 { 00259 w_height = my_height; 00260 } 00261 00262 if (abs(my_height - nw_height) > MAX_STRETCH_DIAG) 00263 { 00264 nw_height = my_height; 00265 } 00266 00267 if (abs(my_height - n_height) > MAX_STRETCH) 00268 { 00269 n_height = my_height; 00270 } 00271 00272 if (abs(my_height - ne_height) > MAX_STRETCH_DIAG) 00273 { 00274 ne_height = my_height; 00275 } 00276 00277 top = MAX(w_height, nw_height); 00278 top = MAX(top, n_height); 00279 top = MAX(top, my_height); 00280 00281 bottom = MAX(s_height, se_height); 00282 bottom = MAX(bottom, e_height); 00283 bottom = MAX(bottom, my_height); 00284 00285 right = MAX(n_height, ne_height); 00286 right = MAX(right, e_height); 00287 right = MAX(right, my_height); 00288 00289 left = MAX(w_height, sw_height); 00290 left = MAX(left, s_height); 00291 left = MAX(left, my_height); 00292 00293 /* Normalize these... */ 00294 min_ht = MIN(top, bottom); 00295 min_ht = MIN(min_ht, left); 00296 min_ht = MIN(min_ht, right); 00297 min_ht = MIN(min_ht, my_height); 00298 00299 top -= min_ht; 00300 bottom -= min_ht; 00301 left -= min_ht; 00302 right -= min_ht; 00303 00304 h = bottom + (left << 8) + (right << 16) + (top << 24); 00305 the_map.cells[x][y].stretch = h; 00306 } 00307 00315 void adjust_tile_stretch() 00316 { 00317 int x, y; 00318 00319 for (x = 0; x < setting_get_int(OPT_CAT_MAP, OPT_MAP_WIDTH); x++) 00320 { 00321 for (y = 0; y < setting_get_int(OPT_CAT_MAP, OPT_MAP_HEIGHT); y++) 00322 { 00323 align_tile_stretch(x - 1, y - 1); 00324 align_tile_stretch(x , y - 1); 00325 align_tile_stretch(x + 1, y - 1); 00326 align_tile_stretch(x + 1, y); 00327 00328 align_tile_stretch(x + 1, y + 1); 00329 align_tile_stretch(x, y + 1); 00330 align_tile_stretch(x - 1, y + 1); 00331 align_tile_stretch(x - 1, y); 00332 00333 align_tile_stretch(x, y); 00334 } 00335 } 00336 } 00337 00354 void map_set_data(int x, int y, int layer, sint16 face, uint8 quick_pos, uint8 obj_flags, const char *name, const char *name_color, sint16 height, uint8 probe, sint16 zoom, sint16 align, uint8 draw_double, uint8 alpha, sint16 rotate, uint8 infravision) 00355 { 00356 the_map.cells[x][y].faces[layer] = face; 00357 the_map.cells[x][y].flags[layer] = obj_flags; 00358 00359 the_map.cells[x][y].probe[layer] = probe; 00360 the_map.cells[x][y].quick_pos[layer] = quick_pos; 00361 00362 strncpy(the_map.cells[x][y].pcolor[layer], name_color, sizeof(the_map.cells[x][y].pcolor[layer]) - 1); 00363 the_map.cells[x][y].pcolor[layer][sizeof(the_map.cells[x][y].pcolor[layer]) - 1] = '\0'; 00364 00365 strncpy(the_map.cells[x][y].pname[layer], name, sizeof(the_map.cells[x][y].pname[layer]) - 1); 00366 the_map.cells[x][y].pname[layer][sizeof(the_map.cells[x][y].pname[layer]) - 1] = '\0'; 00367 00368 the_map.cells[x][y].height[layer] = height; 00369 the_map.cells[x][y].zoom[layer] = zoom; 00370 the_map.cells[x][y].align[layer] = align; 00371 the_map.cells[x][y].draw_double[layer] = draw_double; 00372 the_map.cells[x][y].alpha[layer] = alpha; 00373 the_map.cells[x][y].rotate[layer] = rotate; 00374 the_map.cells[x][y].infravision[layer] = infravision; 00375 } 00376 00381 void map_clear_cell(int x, int y) 00382 { 00383 int i; 00384 00385 the_map.cells[x][y].darkness = 0; 00386 00387 for (i = 1; i <= MAX_LAYERS; i++) 00388 { 00389 the_map.cells[x][y].faces[i] = 0; 00390 the_map.cells[x][y].flags[i] = 0; 00391 the_map.cells[x][y].probe[i] = 0; 00392 the_map.cells[x][y].quick_pos[i] = 0; 00393 the_map.cells[x][y].pname[i][0] = '\0'; 00394 the_map.cells[x][y].height[i] = 0; 00395 the_map.cells[x][y].zoom[i] = 0; 00396 the_map.cells[x][y].align[i] = 0; 00397 the_map.cells[x][y].rotate[i] = 0; 00398 the_map.cells[x][y].infravision[i] = 0; 00399 } 00400 } 00401 00407 void map_set_darkness(int x, int y, uint8 darkness) 00408 { 00409 the_map.cells[x][y].darkness = darkness; 00410 } 00411 00418 static void draw_map_object(int x, int y, int layer, int player_height_offset) 00419 { 00420 struct MapCell *map = &the_map.cells[x][y]; 00421 _Sprite *face_sprite; 00422 int ypos, xpos; 00423 int xl, yl, temp; 00424 int xml, xmpos, xtemp = 0; 00425 uint16 face; 00426 int mid, mnr; 00427 uint32 stretch = 0; 00428 _BLTFX bltfx; 00429 int bitmap_h, bitmap_w; 00430 00431 bltfx.surface = NULL; 00432 xpos = MAP_START_XOFF + x * MAP_TILE_YOFF - y * MAP_TILE_YOFF; 00433 ypos = MAP_START_YOFF + x * MAP_TILE_XOFF + y * MAP_TILE_XOFF; 00434 face = map->faces[layer]; 00435 00436 if (face <= 0 || face >= MAX_FACE_TILES) 00437 { 00438 return; 00439 } 00440 00441 face_sprite = FaceList[face].sprite; 00442 00443 if (!face_sprite) 00444 { 00445 return; 00446 } 00447 00448 bitmap_h = face_sprite->bitmap->h; 00449 bitmap_w = face_sprite->bitmap->w; 00450 00451 if (map->rotate[layer]) 00452 { 00453 rotozoomSurfaceSize(bitmap_w, bitmap_h, map->rotate[layer], map->zoom[layer] ? map->zoom[layer] / 100.0 : 1.0, &bitmap_w, &bitmap_h); 00454 } 00455 else if (map->zoom[layer] && map->zoom[layer] != 100) 00456 { 00457 zoomSurfaceSize(bitmap_w, bitmap_h, map->zoom[layer] / 100.0, map->zoom[layer] / 100.0, &bitmap_w, &bitmap_h); 00458 } 00459 00460 /* We have a set quick_pos = multi tile */ 00461 if (map->quick_pos[layer]) 00462 { 00463 mnr = map->quick_pos[layer]; 00464 mid = mnr >> 4; 00465 mnr &= 0x0f; 00466 xml = MultiArchs[mid].xlen; 00467 yl = ypos - MultiArchs[mid].part[mnr].yoff + MultiArchs[mid].ylen - bitmap_h; 00468 00469 /* we allow overlapping x borders - we simply center then */ 00470 xl = 0; 00471 00472 if (bitmap_w > MultiArchs[mid].xlen) 00473 { 00474 xl = (MultiArchs[mid].xlen - bitmap_w) >> 1; 00475 } 00476 00477 xmpos = xpos - MultiArchs[mid].part[mnr].xoff; 00478 xl += xmpos; 00479 } 00480 /* Single tile... */ 00481 else 00482 { 00483 /* First, we calc the shift positions */ 00484 xml = MAP_TILE_POS_XOFF; 00485 yl = (ypos + MAP_TILE_POS_YOFF) - bitmap_h; 00486 xmpos = xl = xpos; 00487 00488 if (bitmap_w > MAP_TILE_POS_XOFF) 00489 { 00490 xl -= (bitmap_w - MAP_TILE_POS_XOFF) / 2; 00491 } 00492 } 00493 00494 if (map->align[layer]) 00495 { 00496 xl += map->align[layer]; 00497 } 00498 00499 /* Blit the face in the darkness level the tile pos has */ 00500 temp = map->darkness; 00501 00502 if (temp == 210) 00503 { 00504 bltfx.dark_level = 0; 00505 } 00506 else if (temp == 180) 00507 { 00508 bltfx.dark_level = 1; 00509 } 00510 else if (temp == 150) 00511 { 00512 bltfx.dark_level = 2; 00513 } 00514 else if (temp == 120) 00515 { 00516 bltfx.dark_level = 3; 00517 } 00518 else if (temp == 90) 00519 { 00520 bltfx.dark_level = 4; 00521 } 00522 else if (temp == 60) 00523 { 00524 bltfx.dark_level = 5; 00525 } 00526 else if (temp == 0) 00527 { 00528 bltfx.dark_level = 7; 00529 } 00530 else 00531 { 00532 bltfx.dark_level = 6; 00533 } 00534 00535 bltfx.flags = 0; 00536 bltfx.alpha = 0; 00537 00538 if (map->infravision[layer]) 00539 { 00540 bltfx.flags |= BLTFX_FLAG_RED; 00541 } 00542 else 00543 { 00544 bltfx.flags |= BLTFX_FLAG_DARK; 00545 } 00546 00547 if (map->flags[layer] & FFLAG_INVISIBLE) 00548 { 00549 bltfx.flags &= ~BLTFX_FLAG_DARK; 00550 bltfx.flags |= BLTFX_FLAG_GREY; 00551 } 00552 00553 if (map->alpha[layer]) 00554 { 00555 bltfx.flags &= ~BLTFX_FLAG_DARK; 00556 bltfx.flags |= BLTFX_FLAG_SRCALPHA; 00557 bltfx.alpha = map->alpha[layer]; 00558 } 00559 00560 stretch = 0; 00561 00562 if (layer <= 2 && map->stretch) 00563 { 00564 bltfx.flags |= BLTFX_FLAG_STRETCH; 00565 stretch = map->stretch; 00566 } 00567 00568 yl = (yl - map->height[1]) + player_height_offset; 00569 00570 if (layer > 1) 00571 { 00572 yl -= map->height[layer]; 00573 } 00574 00575 sprite_blt_map(face_sprite, xl, yl, NULL, &bltfx, stretch, map->zoom[layer], map->rotate[layer]); 00576 00577 /* Double faces are shown twice, one above the other, when not lower 00578 * on the screen than the player. This simulates high walls without 00579 * obscuring the user's view. */ 00580 if (map->draw_double[layer]) 00581 { 00582 sprite_blt_map(face_sprite, xl, yl - 22, NULL, &bltfx, stretch, map->zoom[layer], map->rotate[layer]); 00583 } 00584 00585 if (xml == MAP_TILE_POS_XOFF) 00586 { 00587 xtemp = (int) (((double) xml / 100.0) * 25.0); 00588 } 00589 else 00590 { 00591 xtemp = (int) (((double) xml / 100.0) * 20.0); 00592 } 00593 00594 /* Do we have a playername? Then print it! */ 00595 if (setting_get_int(OPT_CAT_MAP, OPT_PLAYER_NAMES) && map->pname[layer][0]) 00596 { 00597 if (setting_get_int(OPT_CAT_MAP, OPT_PLAYER_NAMES) == 1 || (setting_get_int(OPT_CAT_MAP, OPT_PLAYER_NAMES) == 2 && strncasecmp(map->pname[layer], cpl.name, strlen(map->pname[layer]))) || (setting_get_int(OPT_CAT_MAP, OPT_PLAYER_NAMES) == 3 && !strncasecmp(map->pname[layer], cpl.name, strlen(map->pname[layer])))) 00598 { 00599 string_blt(cur_widget[MAP_ID]->widgetSF, FONT_SANS9, map->pname[layer], xmpos + xtemp + (xml - xtemp * 2) / 2 - string_get_width(FONT_SANS9, map->pname[layer], 0) / 2 - 2, yl - 24, map->pcolor[layer], TEXT_OUTLINE, NULL); 00600 } 00601 } 00602 00603 /* Perhaps the object has a marked effect, blit it now */ 00604 if (map->flags[layer]) 00605 { 00606 if (map->flags[layer] & FFLAG_SLEEP) 00607 { 00608 sprite_blt_map(Bitmaps[BITMAP_SLEEP], xl + bitmap_w / 2, yl - 5, NULL, NULL, 0, map->zoom[layer], map->rotate[layer]); 00609 } 00610 00611 if (map->flags[layer] & FFLAG_CONFUSED) 00612 { 00613 sprite_blt_map(Bitmaps[BITMAP_CONFUSE], xl + bitmap_w / 2 - 1, yl - 4, NULL, NULL, 0, map->zoom[layer], map->rotate[layer]); 00614 } 00615 00616 if (map->flags[layer] & FFLAG_SCARED) 00617 { 00618 sprite_blt_map(Bitmaps[BITMAP_SCARED], xl + bitmap_w / 2 + 10, yl - 4, NULL, NULL, 0, map->zoom[layer], map->rotate[layer]); 00619 } 00620 00621 if (map->flags[layer] & FFLAG_BLINDED) 00622 { 00623 sprite_blt_map(Bitmaps[BITMAP_BLIND], xl + bitmap_w / 2 + 3, yl - 6, NULL, NULL, 0, map->zoom[layer], map->rotate[layer]); 00624 } 00625 00626 if (map->flags[layer] & FFLAG_PARALYZED) 00627 { 00628 sprite_blt_map(Bitmaps[BITMAP_PARALYZE], xl + bitmap_w / 2 + 2, yl + 3, NULL, NULL, 0, map->zoom[layer], map->rotate[layer]); 00629 sprite_blt_map(Bitmaps[BITMAP_PARALYZE], xl + bitmap_w / 2 + 9, yl + 3, NULL, NULL, 0, map->zoom[layer], map->rotate[layer]); 00630 } 00631 } 00632 00633 if (map->probe[layer] && cpl.target_code) 00634 { 00635 const char *hp_col; 00636 Uint32 sdl_col; 00637 SDL_Rect rect; 00638 SDL_Color color; 00639 00640 if (cpl.target_hp > 90) 00641 { 00642 hp_col = COLOR_GREEN; 00643 } 00644 else if (cpl.target_hp > 75) 00645 { 00646 hp_col = COLOR_DGOLD; 00647 } 00648 else if (cpl.target_hp > 50) 00649 { 00650 hp_col = COLOR_HGOLD; 00651 } 00652 else if (cpl.target_hp > 25) 00653 { 00654 hp_col = COLOR_ORANGE; 00655 } 00656 else if (cpl.target_hp > 10) 00657 { 00658 hp_col = COLOR_YELLOW; 00659 } 00660 else 00661 { 00662 hp_col = COLOR_RED; 00663 } 00664 00665 temp = (xml - xtemp * 2) - 1; 00666 00667 if (temp <= 0) 00668 { 00669 temp = 1; 00670 } 00671 00672 if (temp >= 300) 00673 { 00674 temp = 300; 00675 } 00676 00677 mid = map->probe[layer]; 00678 00679 if (mid <= 0) 00680 { 00681 mid = 1; 00682 } 00683 00684 if (mid > 100) 00685 { 00686 mid = 100; 00687 } 00688 00689 temp = (int) (((double) temp / 100.0) * (double) mid); 00690 00691 rect.h = 2; 00692 rect.w = temp; 00693 rect.x = 0; 00694 rect.y = 0; 00695 00696 text_color_parse(hp_col, &color); 00697 sdl_col = SDL_MapRGB(cur_widget[MAP_ID]->widgetSF->format, color.r, color.g, color.b); 00698 00699 /* First draw the bar */ 00700 rect.x = xmpos + xtemp - 1; 00701 rect.y = yl - 9; 00702 rect.h = 1; 00703 SDL_FillRect(cur_widget[MAP_ID]->widgetSF, &rect, sdl_col); 00704 /* Horizontal lines of left bracket */ 00705 rect.h = 1; 00706 rect.w = 3; 00707 rect.x = xmpos + xtemp - 3; 00708 rect.y = yl - 11; 00709 SDL_FillRect(cur_widget[MAP_ID]->widgetSF, &rect, sdl_col); 00710 rect.y = yl - 7; 00711 SDL_FillRect(cur_widget[MAP_ID]->widgetSF, &rect, sdl_col); 00712 /* Horizontal lines of right bracket */ 00713 rect.x = xmpos + xtemp + (xml - xtemp * 2) - 3; 00714 SDL_FillRect(cur_widget[MAP_ID]->widgetSF, &rect, sdl_col); 00715 rect.y = yl - 11; 00716 SDL_FillRect(cur_widget[MAP_ID]->widgetSF, &rect, sdl_col); 00717 /* Vertical lines */ 00718 rect.w = 1; 00719 rect.h = 5; 00720 rect.x = xmpos + xtemp - 3; 00721 rect.y = yl - 11; 00722 SDL_FillRect(cur_widget[MAP_ID]->widgetSF, &rect, sdl_col); 00723 rect.x = xmpos + xtemp + (xml - xtemp * 2) - 1; 00724 SDL_FillRect(cur_widget[MAP_ID]->widgetSF, &rect, sdl_col); 00725 00726 /* Draw the name of target if it's not a player */ 00727 if (!(setting_get_int(OPT_CAT_MAP, OPT_PLAYER_NAMES) && map->pname[layer][0])) 00728 { 00729 string_blt(cur_widget[MAP_ID]->widgetSF, FONT_SANS9, cpl.target_name, xmpos + xtemp + (xml - xtemp * 2) / 2 - string_get_width(FONT_SANS9, cpl.target_name, 0) / 2 - 2, yl - 24, cpl.target_color, TEXT_OUTLINE, NULL); 00730 } 00731 00732 /* Draw HP remaining percent */ 00733 if (cpl.target_hp > 0) 00734 { 00735 char hp_text[9]; 00736 00737 snprintf(hp_text, sizeof(hp_text), "HP: %d%%", cpl.target_hp); 00738 string_blt(cur_widget[MAP_ID]->widgetSF, FONT_SANS9, hp_text, xmpos + xtemp + (xml - xtemp * 2) / 2 - string_get_width(FONT_SANS9, hp_text, 0) / 2 - 2, yl - 36, hp_col, TEXT_OUTLINE, NULL); 00739 } 00740 } 00741 } 00742 00745 void map_draw_map() 00746 { 00747 int player_height_offset; 00748 int x, y, layer; 00749 int tx, ty; 00750 00751 player_height_offset = the_map.cells[setting_get_int(OPT_CAT_MAP, OPT_MAP_WIDTH) - (setting_get_int(OPT_CAT_MAP, OPT_MAP_WIDTH) / 2) - 1][setting_get_int(OPT_CAT_MAP, OPT_MAP_HEIGHT) - (setting_get_int(OPT_CAT_MAP, OPT_MAP_HEIGHT) / 2) - 1].height[1]; 00752 00753 /* First draw floor and floor masks. */ 00754 for (x = 0; x < setting_get_int(OPT_CAT_MAP, OPT_MAP_WIDTH); x++) 00755 { 00756 for (y = 0; y < setting_get_int(OPT_CAT_MAP, OPT_MAP_HEIGHT); y++) 00757 { 00758 for (layer = 1; layer <= 2; layer++) 00759 { 00760 draw_map_object(x, y, layer, player_height_offset); 00761 } 00762 } 00763 } 00764 00765 /* Now draw everything else. */ 00766 for (x = 0; x < setting_get_int(OPT_CAT_MAP, OPT_MAP_WIDTH); x++) 00767 { 00768 for (y = 0; y < setting_get_int(OPT_CAT_MAP, OPT_MAP_HEIGHT); y++) 00769 { 00770 for (layer = 3; layer <= MAX_LAYERS; layer++) 00771 { 00772 draw_map_object(x, y, layer, player_height_offset); 00773 } 00774 } 00775 } 00776 00777 if (cpl.menustatus == MENU_NO && widget_mouse_event.owner == cur_widget[MAP_ID] && mouse_to_tile_coords(x_custom_cursor, y_custom_cursor, &tx, &ty)) 00778 { 00779 map_draw_one(tx, ty, Bitmaps[BITMAP_SQUARE_HIGHLIGHT]); 00780 } 00781 } 00782 00788 void map_draw_one(int x, int y, _Sprite *sprite) 00789 { 00790 int xpos = MAP_START_XOFF + x * MAP_TILE_YOFF - y * MAP_TILE_YOFF; 00791 int ypos = (MAP_START_YOFF + x * MAP_TILE_XOFF + y * MAP_TILE_XOFF) + MAP_TILE_POS_YOFF - sprite->bitmap->h; 00792 00793 if (sprite->bitmap->w > MAP_TILE_POS_XOFF) 00794 { 00795 xpos -= (sprite->bitmap->w - MAP_TILE_POS_XOFF) / 2; 00796 } 00797 00798 if (the_map.cells[x][y].faces[1]) 00799 { 00800 ypos = (ypos - (the_map.cells[x][y].height[1])) + (the_map.cells[setting_get_int(OPT_CAT_MAP, OPT_MAP_WIDTH) - (setting_get_int(OPT_CAT_MAP, OPT_MAP_WIDTH) / 2) - 1][setting_get_int(OPT_CAT_MAP, OPT_MAP_HEIGHT) - (setting_get_int(OPT_CAT_MAP, OPT_MAP_HEIGHT) / 2) - 1].height[1]); 00801 } 00802 00803 sprite_blt_map(sprite, xpos, ypos, NULL, NULL, 0, 0, 0); 00804 } 00805 00810 static void send_move_path(int tx, int ty) 00811 { 00812 SockList sl; 00813 uint8 buf[HUGE_BUF]; 00814 00815 sl.buf = buf; 00816 sl.len = 0; 00817 SockList_AddString(&sl, "mp "); 00818 SockList_AddChar(&sl, tx); 00819 SockList_AddChar(&sl, ty); 00820 send_socklist(sl); 00821 } 00822 00827 static void send_target(int tx, int ty) 00828 { 00829 char buf[MAX_BUF]; 00830 00831 snprintf(buf, sizeof(buf), "/target !%d %d", tx, ty); 00832 send_command(buf); 00833 } 00834 00839 void widget_map_mevent(widgetdata *widget, SDL_Event *event) 00840 { 00841 int tx, ty; 00842 00843 (void) widget; 00844 00845 /* Check if the mouse is in play field. */ 00846 if (!mouse_to_tile_coords(event->motion.x, event->motion.y, &tx, &ty)) 00847 { 00848 return; 00849 } 00850 00851 if (event->type == SDL_MOUSEBUTTONUP) 00852 { 00853 /* Send target command if we released the right button in time; 00854 * otherwise the widget menu will be created. */ 00855 if (event->button.button == SDL_BUTTON_RIGHT && SDL_GetTicks() - right_click_ticks < 500) 00856 { 00857 send_target(tx, ty); 00858 } 00859 00860 right_click_ticks = -1; 00861 } 00862 else if (event->type == SDL_MOUSEBUTTONDOWN) 00863 { 00864 if (event->button.button == SDL_BUTTON_RIGHT) 00865 { 00866 right_click_ticks = SDL_GetTicks(); 00867 } 00868 /* Running */ 00869 else if (SDL_GetMouseState(NULL, NULL) == SDL_BUTTON_LEFT) 00870 { 00871 if (cpl.fire_on || cpl.run_on) 00872 { 00873 move_keys(dir_from_tile_coords(tx, ty)); 00874 } 00875 else 00876 { 00877 send_move_path(tx, ty); 00878 } 00879 } 00880 } 00881 else if (event->type == SDL_MOUSEMOTION) 00882 { 00883 if (tx != old_map_mouse_x || ty != old_map_mouse_y) 00884 { 00885 map_redraw_flag = 1; 00886 old_map_mouse_x = tx; 00887 old_map_mouse_y = ty; 00888 } 00889 } 00890 } 00891 00894 static void menu_map_walk_here(widgetdata *widget, int x, int y) 00895 { 00896 int tx, ty; 00897 00898 (void) widget; 00899 (void) x; 00900 (void) y; 00901 00902 if (mouse_to_tile_coords(cur_widget[MENU_ID]->x1, cur_widget[MENU_ID]->y1, &tx, &ty)) 00903 { 00904 send_move_path(tx, ty); 00905 } 00906 } 00907 00910 static void menu_map_talk_to(widgetdata *widget, int x, int y) 00911 { 00912 int tx, ty; 00913 00914 (void) widget; 00915 (void) x; 00916 (void) y; 00917 00918 if (mouse_to_tile_coords(cur_widget[MENU_ID]->x1, cur_widget[MENU_ID]->y1, &tx, &ty)) 00919 { 00920 send_target(tx, ty); 00921 send_command("/t_tell hi"); 00922 } 00923 } 00924 00928 void widget_map_render(widgetdata *widget) 00929 { 00930 static int gfx_toggle = 0; 00931 SDL_Rect box; 00932 int mx, my; 00933 00934 if (!widget->widgetSF) 00935 { 00936 widget->widgetSF = SDL_CreateRGBSurface(get_video_flags(), 850, 600, video_get_bpp(), 0, 0, 0, 0); 00937 } 00938 00939 /* Make sure the map widget is always the last to handle events for. */ 00940 SetPriorityWidget_reverse(widget); 00941 00942 if (setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) != 100) 00943 { 00944 int w, h; 00945 00946 zoomSurfaceSize(widget->widgetSF->w, widget->widgetSF->h, setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0, setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0, &w, &h); 00947 widget->wd = w; 00948 widget->ht = h; 00949 } 00950 00951 /* We recreate the map only when there is a change. */ 00952 if (map_redraw_flag && (!popup_get_visible() || popup_overlay_need_update(popup_get_visible()))) 00953 { 00954 SDL_FillRect(widget->widgetSF, NULL, 0); 00955 map_draw_map(); 00956 map_redraw_flag = 0; 00957 effect_sprites_play(); 00958 00959 if (setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) != 100) 00960 { 00961 if (zoomed) 00962 { 00963 SDL_FreeSurface(zoomed); 00964 } 00965 00966 zoomed = zoomSurface(widget->widgetSF, setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0, setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0, setting_get_int(OPT_CAT_MAP, OPT_ZOOM_SMOOTH)); 00967 } 00968 } 00969 00970 box.x = widget->x1; 00971 box.y = widget->y1; 00972 00973 if (setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) == 100) 00974 { 00975 SDL_BlitSurface(widget->widgetSF, NULL, ScreenSurface, &box); 00976 } 00977 else 00978 { 00979 SDL_BlitSurface(zoomed, NULL, ScreenSurface, &box); 00980 } 00981 00982 /* The damage numbers */ 00983 play_anims(); 00984 00985 /* Draw warning icons above player */ 00986 if ((gfx_toggle++ & 63) < 25) 00987 { 00988 if (setting_get_int(OPT_CAT_MAP, OPT_HEALTH_WARNING) && ((float) cpl.stats.hp / (float) cpl.stats.maxhp) * 100 <= setting_get_int(OPT_CAT_MAP, OPT_HEALTH_WARNING)) 00989 { 00990 sprite_blt(Bitmaps[BITMAP_WARN_HP], widget->x1 + 393 * (setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0), widget->y1 + 298 * (setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0), NULL, NULL); 00991 } 00992 } 00993 else 00994 { 00995 /* Low food */ 00996 if (setting_get_int(OPT_CAT_MAP, OPT_FOOD_WARNING) && ((float) cpl.stats.food / 1000.0f) * 100 <= setting_get_int(OPT_CAT_MAP, OPT_FOOD_WARNING)) 00997 { 00998 sprite_blt(Bitmaps[BITMAP_WARN_FOOD], widget->x1 + 390 * (setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0), widget->y1 + 294 * (setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0), NULL, NULL); 00999 } 01000 } 01001 01002 /* Process message animations */ 01003 if (msg_anim.message[0] != '\0') 01004 { 01005 if ((LastTick - msg_anim.tick) < 3000) 01006 { 01007 int bmoff = (int) ((50.0f / 3.0f) * ((float) (LastTick - msg_anim.tick) / 1000.0f) * ((float) (LastTick - msg_anim.tick) / 1000.0f) + ((int) (150.0f * ((float) (LastTick - msg_anim.tick) / 3000.0f)))), y_offset = 0; 01008 char *msg = strdup(msg_anim.message), *cp; 01009 01010 cp = strtok(msg, "\n"); 01011 01012 while (cp) 01013 { 01014 string_blt(ScreenSurface, FONT_SERIF16, cp, widget->x1 + widget->widgetSF->w / 2 - string_get_width(FONT_SERIF16, cp, TEXT_OUTLINE) / 2, widget->y1 + 300 - bmoff + y_offset, msg_anim.color, TEXT_OUTLINE | TEXT_MARKUP, NULL); 01015 y_offset += FONT_HEIGHT(FONT_SERIF16); 01016 cp = strtok(NULL, "\n"); 01017 } 01018 01019 free(msg); 01020 } 01021 else 01022 { 01023 msg_anim.message[0] = '\0'; 01024 } 01025 } 01026 01027 /* Holding the right mouse button for some time, create a menu. */ 01028 if (SDL_GetMouseState(&mx, &my) == SDL_BUTTON(SDL_BUTTON_RIGHT) && right_click_ticks != -1 && SDL_GetTicks() - right_click_ticks > 500) 01029 { 01030 widgetdata *menu; 01031 01032 menu = create_menu(mx, my, widget); 01033 add_menuitem(menu, "Walk Here", &menu_map_walk_here, MENU_NORMAL, 0); 01034 add_menuitem(menu, "Talk To NPC", &menu_map_talk_to, MENU_NORMAL, 0); 01035 add_menuitem(menu, "Move Widget", &menu_move_widget, MENU_NORMAL, 0); 01036 menu_finalize(menu); 01037 right_click_ticks = -1; 01038 } 01039 } 01040 01042 const char tile_off[MAP_TILE_YOFF][MAP_TILE_POS_XOFF] = 01043 { 01044 "000000000000000000000022221111111111111111111111", 01045 "000000000000000000002222222211111111111111111111", 01046 "000000000000000000222222222222111111111111111111", 01047 "000000000000000022222222222222221111111111111111", 01048 "000000000000002222222222222222222211111111111111", 01049 "000000000000222222222222222222222222111111111111", 01050 "000000000022222222222222222222222222221111111111", 01051 "000000002222222222222222222222222222222211111111", 01052 "000000222222222222222222222222222222222222111111", 01053 "000022222222222222222222222222222222222222221111", 01054 "002222222222222222222222222222222222222222222211", 01055 "222222222222222222222222222222222222222222222222", 01056 "332222222222222222222222222222222222222222222244", 01057 "333322222222222222222222222222222222222222224444", 01058 "333333222222222222222222222222222222222222444444", 01059 "333333332222222222222222222222222222222244444444", 01060 "333333333322222222222222222222222222224444444444", 01061 "333333333333222222222222222222222222444444444444", 01062 "333333333333332222222222222222222244444444444444", 01063 "333333333333333322222222222222224444444444444444", 01064 "333333333333333333222222222222444444444444444444", 01065 "333333333333333333332222222244444444444444444444", 01066 "333333333333333333333322224444444444444444444444" 01067 }; 01068 01081 int mouse_to_tile_coords(int mx, int my, int *tx, int *ty) 01082 { 01083 int x, y, xpos, ypos; 01084 01085 /* Adjust mouse x/y, making it look as if the map was drawn from 01086 * top left corner, in order to simplify comparisons below. */ 01087 mx -= (MAP_START_XOFF * (setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0)) + cur_widget[MAP_ID]->x1; 01088 my -= (MAP_START_YOFF * (setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0)) + cur_widget[MAP_ID]->y1; 01089 01090 /* Go through all the map squares. */ 01091 for (x = setting_get_int(OPT_CAT_MAP, OPT_MAP_WIDTH) - 1; x >= 0; x--) 01092 { 01093 for (y = setting_get_int(OPT_CAT_MAP, OPT_MAP_HEIGHT) - 1; y >= 0; y--) 01094 { 01095 /* X/Y position of the map square. */ 01096 xpos = (x * MAP_TILE_YOFF - y * MAP_TILE_YOFF) * (setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0); 01097 ypos = (x * MAP_TILE_XOFF + y * MAP_TILE_XOFF) * (setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0); 01098 01099 if (the_map.cells[x][y].faces[1]) 01100 { 01101 ypos = (ypos - (the_map.cells[x][y].height[1]) * (setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0)) + (the_map.cells[setting_get_int(OPT_CAT_MAP, OPT_MAP_WIDTH) - (setting_get_int(OPT_CAT_MAP, OPT_MAP_WIDTH) / 2) - 1][setting_get_int(OPT_CAT_MAP, OPT_MAP_HEIGHT) - (setting_get_int(OPT_CAT_MAP, OPT_MAP_HEIGHT) / 2) - 1].height[1]) * (setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0); 01102 } 01103 01104 /* See if this square matches our 48x24 box shape. */ 01105 if (mx >= xpos && mx < xpos + (MAP_TILE_POS_XOFF * (setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0)) && my >= ypos && my < ypos + (MAP_TILE_YOFF * (setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0))) 01106 { 01107 /* See if the square matches isometric 48x24 tile. */ 01108 if (tile_off[(int) ((my - ypos) / (setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0))][(int) ((mx - xpos) / (setting_get_int(OPT_CAT_MAP, OPT_MAP_ZOOM) / 100.0))] == '2') 01109 { 01110 if (tx) 01111 { 01112 *tx = x; 01113 } 01114 01115 if (ty) 01116 { 01117 *ty = y; 01118 } 01119 01120 return 1; 01121 } 01122 } 01123 } 01124 } 01125 01126 return 0; 01127 }
1.7.4