00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00039 #include <global.h>
00040 #include <sproto.h>
00041 #include <stdarg.h>
00042 #include <spells.h>
00043 #include <skills.h>
00044
00051 static void esrv_print_msg(socket_struct *ns, int color, const char *str) {
00052 SockList sl;
00053
00054 SockList_Init(&sl);
00055 SockList_AddPrintf(&sl, "drawinfo %d %s", color, str);
00056 Send_With_Handling(ns, &sl);
00057 SockList_Term(&sl);
00058 }
00059
00069 static void esrv_print_ext_msg(socket_struct *ns, int color, uint8 type, uint8 subtype, const char *message) {
00070 SockList sl;
00071
00072 SockList_Init(&sl);
00073 SockList_AddPrintf(&sl, "drawextinfo %d %hhu %hhu %s", color, type, subtype, message);
00074 Send_With_Handling(ns, &sl);
00075 SockList_Term(&sl);
00076 }
00077
00089 static void print_message(int colr, const object *pl, const char *tmp) {
00090 if (tmp == NULL) {
00091 tmp = "[NULL]";
00092 }
00093
00094 if (!pl || (pl->type == PLAYER && pl->contr == NULL)) {
00095 fprintf(logfile, "%s\n", tmp);
00096 return;
00097 }
00098 if (pl->type == PLAYER) {
00099 esrv_print_msg(&pl->contr->socket, colr, tmp);
00100 return;
00101 }
00102 }
00103
00108 void flush_output_element(const object *pl, Output_Buf *outputs) {
00109 char tbuf[MAX_BUF];
00110
00111 if (outputs->buf == NULL)
00112 return;
00113 if (outputs->count > 1) {
00114 snprintf(tbuf, MAX_BUF, "%d times %s", outputs->count, outputs->buf);
00115 print_message(NDI_BLACK, pl, tbuf);
00116 } else {
00117 print_message(NDI_BLACK, pl, outputs->buf);
00118 }
00119 free_string(outputs->buf);
00120 outputs->buf = NULL;
00121 outputs->first_update = 0;
00122 }
00123
00138 static void check_output_buffers(const object *pl, const char *buf) {
00139 int i, oldest = 0;
00140
00141 if (pl->contr->outputs_count < 2) {
00142 print_message(NDI_BLACK, pl, buf);
00143 return;
00144 } else {
00145 for (i = 0; i < NUM_OUTPUT_BUFS; i++) {
00146 if (pl->contr->outputs[i].buf
00147 && !strcmp(buf, pl->contr->outputs[i].buf))
00148 break;
00149 else if (pl->contr->outputs[i].first_update < pl->contr->outputs[oldest].first_update)
00150 oldest = i;
00151 }
00152
00153 if (i < NUM_OUTPUT_BUFS) {
00154 pl->contr->outputs[i].count++;
00155 if (pl->contr->outputs[i].count >= pl->contr->outputs_count) {
00156 flush_output_element(pl, &pl->contr->outputs[i]);
00157 }
00158 }
00159
00160 else {
00161 flush_output_element(pl, &pl->contr->outputs[oldest]);
00162
00163 pl->contr->outputs[oldest].first_update = pticks;
00164 pl->contr->outputs[oldest].count = 1;
00165 if (pl->contr->outputs[oldest].buf != NULL)
00166 free_string(pl->contr->outputs[oldest].buf);
00167 pl->contr->outputs[oldest].buf = add_string(buf);
00168 }
00169 }
00170 }
00171
00198 void draw_ext_info(
00199 int flags, int pri, const object *pl, uint8 type,
00200 uint8 subtype, const char *message, const char *oldmessage) {
00201
00202 if ((flags&NDI_ALL) || (flags&NDI_ALL_DMS)) {
00203 player *tmppl;
00204
00205 for (tmppl = first_player; tmppl != NULL; tmppl = tmppl->next) {
00206 if ((flags&NDI_ALL_DMS) && !QUERY_FLAG(tmppl->ob, FLAG_WIZ))
00207 continue;
00208 draw_ext_info((flags&~NDI_ALL&~NDI_ALL_DMS), pri, tmppl->ob, type, subtype, message, oldmessage);
00209 }
00210
00211 return;
00212 }
00213
00214 if (!pl || (pl->type == PLAYER && pl->contr == NULL)) {
00215
00216 print_message(0, NULL, oldmessage);
00217 return;
00218 }
00219 if (pl->type != PLAYER)
00220 return;
00221 if (pri >= pl->contr->listening)
00222 return;
00223
00224
00225
00226
00227
00228
00229 if (!CLIENT_SUPPORT_READABLES(&pl->contr->socket, type)) {
00230 char *buf;
00231
00232 if (oldmessage) {
00233 buf = (char *)oldmessage;
00234 } else {
00235 buf = strdup_local(message);
00236 if (buf == NULL) {
00237 LOG(llevError, "info::draw_ext_info -> Out of memory!\n");
00238 return;
00239 }
00240 strip_media_tag(buf);
00241 }
00242 if ((flags&NDI_COLOR_MASK) == NDI_BLACK && !(flags&NDI_UNIQUE)) {
00243
00244 check_output_buffers(pl, buf);
00245 } else {
00246 print_message(flags&NDI_COLOR_MASK, pl, buf);
00247 }
00248 if (!oldmessage)
00249 free(buf);
00250 } else {
00251 esrv_print_ext_msg(&pl->contr->socket, flags&NDI_COLOR_MASK, type, subtype, message);
00252 }
00253 }
00254
00286 void draw_ext_info_format(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *new_format, const char *old_format, ...) {
00287 char newbuf[HUGE_BUF], oldbuf[HUGE_BUF];
00288 va_list ap;
00289
00290 if (!old_format)
00291 old_format = new_format;
00292
00293 va_start(ap, old_format);
00294 vsnprintf(oldbuf, HUGE_BUF, old_format, ap);
00295 va_end(ap);
00296 va_start(ap, old_format);
00297 vsnprintf(newbuf, HUGE_BUF, new_format, ap);
00298 va_end(ap);
00299
00300 draw_ext_info(flags, pri, pl, type, subtype, newbuf, oldbuf);
00301 }
00302
00306 void ext_info_map(int color, const mapstruct *map, uint8 type, uint8 subtype, const char *str1, const char *str2) {
00307 player *pl;
00308
00309 for (pl = first_player; pl != NULL; pl = pl->next)
00310 if (pl->ob != NULL && pl->ob->map == map) {
00311 draw_ext_info(color, 0, pl->ob, type, subtype, str1, str2);
00312 }
00313 }
00314
00318 void ext_info_map_except(int color, const mapstruct *map, const object *op, uint8 type, uint8 subtype, const char *str1, const char *str2) {
00319 player *pl;
00320
00321 for (pl = first_player; pl != NULL; pl = pl->next)
00322 if (pl->ob != NULL && pl->ob->map == map && pl->ob != op) {
00323 draw_ext_info(color, 0, pl->ob, type, subtype, str1, str2);
00324 }
00325 }
00326
00330 void ext_info_map_except2(int color, const mapstruct *map, const object *op1, const object *op2, int type, int subtype, const char *str1, const char *str2) {
00331 player *pl;
00332
00333 for (pl = first_player; pl != NULL; pl = pl->next)
00334 if (pl->ob != NULL && pl->ob->map == map
00335 && pl->ob != op1 && pl->ob != op2) {
00336 draw_ext_info(color, 0, pl->ob, type, subtype, str1, str2);
00337 }
00338 }
00339
00343 void rangetostring(const object *pl, char *obuf, size_t len) {
00344 char name[MAX_BUF];
00345
00346 switch (pl->contr->shoottype) {
00347 case range_none:
00348 strncpy(obuf, "Range: nothing", len);
00349 break;
00350
00351 case range_bow: {
00352 object *op;
00353
00354 for (op = pl->inv; op; op = op->below)
00355 if (op->type == BOW && QUERY_FLAG(op, FLAG_APPLIED))
00356 break;
00357 if (op == NULL)
00358 break;
00359
00360 query_base_name(op, 0, name, MAX_BUF);
00361 snprintf(obuf, len, "Range: %s (%s)", name, op->race ? op->race : "nothing");
00362 }
00363 break;
00364
00365 case range_magic:
00366 if (settings.casting_time == TRUE) {
00367 if (pl->casting_time > -1) {
00368 if (pl->casting_time == 0)
00369 snprintf(obuf, len, "Range: Holding spell (%s)", pl->spell->name);
00370 else
00371 snprintf(obuf, len, "Range: Casting spell (%s)", pl->spell->name);
00372 } else
00373 snprintf(obuf, len, "Range: spell (%s)", pl->contr->ranges[range_magic]->name);
00374 } else
00375 snprintf(obuf, len, "Range: spell (%s)", pl->contr->ranges[range_magic]->name);
00376 break;
00377
00378 case range_misc:
00379 if (pl->contr->ranges[range_misc])
00380 query_base_name(pl->contr->ranges[range_misc], 0, name, MAX_BUF);
00381 else
00382 strncpy(name, "none", MAX_BUF);
00383 snprintf(obuf, len, "Range: %s", name);
00384 break;
00385
00386
00387
00388
00389 case range_golem:
00390 if (pl->contr->ranges[range_golem] != NULL)
00391 snprintf(obuf, len, "Range: golem (%s)", pl->contr->ranges[range_golem]->name);
00392 else {
00393 pl->contr->shoottype = range_none;
00394 strncpy(obuf, "Range: nothing", len);
00395 }
00396 break;
00397
00398 case range_skill:
00399 snprintf(obuf, len, "Skill: %s", pl->chosen_skill != NULL ? pl->chosen_skill->name : "none");
00400 break;
00401
00402 case range_builder:
00403 query_base_name(pl->contr->ranges[range_builder], 0, name, MAX_BUF);
00404 snprintf(obuf, len, "Builder: %s", name);
00405 break;
00406
00407 default:
00408 strncpy(obuf, "Range: illegal", len);
00409 }
00410 }
00411
00415 void set_title(const object *pl, char *buf, size_t len) {
00416
00417 if (pl->contr->own_title[0] == '\0')
00418 snprintf(buf, len, "Player: %s the %s", pl->name, pl->contr->title);
00419 else
00420 snprintf(buf, len, "Player: %s %s", pl->name, pl->contr->own_title);
00421 }
00422
00434 static void magic_mapping_mark_recursive(object *pl, char *map_mark, int px, int py) {
00435 int x, y, dx, dy, mflags, l;
00436 sint16 nx, ny;
00437 mapstruct *mp;
00438 New_Face *f;
00439 object *ob;
00440
00441 for (dx = -1; dx <= 1; dx++) {
00442 for (dy = -1; dy <= 1; dy++) {
00443 x = px+dx;
00444 y = py+dy;
00445
00446 if (FABS(x) >= MAGIC_MAP_HALF || FABS(y) >= MAGIC_MAP_HALF)
00447 continue;
00448
00449 mp = pl->map;
00450 nx = pl->x+x;
00451 ny = pl->y+y;
00452
00453 mflags = get_map_flags(pl->map, &mp, nx, ny, &nx, &ny);
00454 if (mflags&P_OUT_OF_MAP)
00455 continue;
00456
00457 if (map_mark[MAGIC_MAP_HALF+x+MAGIC_MAP_SIZE*(MAGIC_MAP_HALF+y)] == 0) {
00458 for (l = 0; l < MAP_LAYERS; l++) {
00459 ob = GET_MAP_FACE_OBJ(mp, nx, ny, l);
00460 if (ob && !ob->invisible && ob->face != blank_face)
00461 break;
00462 }
00463 if (ob)
00464 f = ob->face;
00465 else
00466 f = blank_face;
00467
00468
00469
00470
00471 if (mflags&P_BLOCKSVIEW)
00472 map_mark[MAGIC_MAP_HALF+x+MAGIC_MAP_SIZE*(MAGIC_MAP_HALF+y)] = FACE_WALL|(f ? f->magicmap : 0);
00473 else {
00474 map_mark[MAGIC_MAP_HALF+x+MAGIC_MAP_SIZE*(MAGIC_MAP_HALF+y)] = FACE_FLOOR|(f ? f->magicmap : 0);
00475 magic_mapping_mark_recursive(pl, map_mark, x, y);
00476 }
00477 }
00478 }
00479 }
00480 }
00481
00497 void magic_mapping_mark(object *pl, char *map_mark, int strength) {
00498 int x, y, mflags, l;
00499 sint16 nx, ny;
00500 mapstruct *mp;
00501 New_Face *f;
00502 object *ob;
00503
00504 for (x = -strength; x < strength; x++) {
00505 for (y = -strength; y < strength; y++) {
00506 mp = pl->map;
00507 nx = pl->x+x;
00508 ny = pl->y+y;
00509 mflags = get_map_flags(pl->map, &mp, nx, ny, &nx, &ny);
00510 if (mflags&P_OUT_OF_MAP)
00511 continue;
00512 else {
00513 for (l = 0; l < MAP_LAYERS; l++) {
00514 ob = GET_MAP_FACE_OBJ(mp, nx, ny, l);
00515 if (ob && !ob->invisible && ob->face != blank_face)
00516 break;
00517 }
00518 if (ob)
00519 f = ob->face;
00520 else
00521 f = blank_face;
00522 }
00523
00524 if (mflags&P_BLOCKSVIEW)
00525 map_mark[MAGIC_MAP_HALF+x+MAGIC_MAP_SIZE*(MAGIC_MAP_HALF+y)] = FACE_WALL|(f ? f->magicmap : 0);
00526 else {
00527 map_mark[MAGIC_MAP_HALF+x+MAGIC_MAP_SIZE*(MAGIC_MAP_HALF+y)] = FACE_FLOOR|(f ? f->magicmap : 0);
00528 magic_mapping_mark_recursive(pl, map_mark, x, y);
00529 }
00530 }
00531 }
00532 }
00533
00542 void draw_magic_map(object *pl) {
00543 int x, y;
00544 char map_mark[MAGIC_MAP_SIZE*MAGIC_MAP_SIZE];
00545 int xmin, xmax, ymin, ymax;
00546
00547 int max_width;
00548 SockList sl;
00549
00550 if (pl->type != PLAYER) {
00551 LOG(llevError, "Non player object called draw_map.\n");
00552 return;
00553 }
00554
00555
00556 memset(map_mark, 0, MAGIC_MAP_SIZE*MAGIC_MAP_SIZE);
00557 magic_mapping_mark(pl, map_mark, 3);
00558
00559
00560
00561
00562
00563
00564 xmin = MAGIC_MAP_SIZE;
00565 ymin = MAGIC_MAP_SIZE;
00566 xmax = 0;
00567 ymax = 0;
00568 max_width = (MAP_WIDTH(pl->map) > MAGIC_MAP_SIZE) ? MAGIC_MAP_SIZE : MAP_WIDTH(pl->map);
00569 for (x = 0; x < MAGIC_MAP_SIZE; x++) {
00570 for (y = 0; y < MAGIC_MAP_SIZE; y++) {
00571 if (map_mark[x+max_width*y]&~FACE_FLOOR) {
00572 xmin = MIN(x, xmin);
00573 xmax = MAX(x, xmax);
00574 ymin = MIN(y, ymin);
00575 ymax = MAX(y, ymax);
00576 }
00577 }
00578 }
00579
00580 SockList_Init(&sl);
00581 SockList_AddPrintf(&sl, "magicmap %d %d %d %d ", (xmax-xmin+1), (ymax-ymin+1), MAGIC_MAP_HALF-xmin, MAGIC_MAP_HALF-ymin);
00582
00583 for (y = ymin; y <= ymax; y++) {
00584 for (x = xmin; x <= xmax; x++) {
00585 SockList_AddChar(&sl, map_mark[x+MAGIC_MAP_SIZE*y]&~FACE_FLOOR);
00586 }
00587 }
00588
00589 Send_With_Handling(&pl->contr->socket, &sl);
00590 SockList_Term(&sl);
00591 }