Crossfire Server, Trunk
info.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
24 #include "global.h"
25 
26 #include <stdarg.h>
27 #include <string.h>
28 
29 #include "skills.h"
30 #include "spells.h"
31 #include "sproto.h"
32 
41 static void do_print_ext(SockList *sl, int color, uint8_t type, uint8_t subtype, const char *message) {
42  SockList_Init(sl);
43  SockList_AddPrintf(sl, "drawextinfo %d %hhu %hhu %s", color, type, subtype, message);
44 }
45 
62 void print_ext_msg(socket_struct *ns, int color, uint8_t type, uint8_t subtype, const char *message) {
63  SockList sl;
64  do_print_ext(&sl, color, type, subtype, message);
65  Send_With_Handling(ns, &sl);
66  SockList_Term(&sl);
67 }
68 
98  int flags, int pri, const object *pl, uint8_t type,
99  uint8_t subtype, const char *message) {
100 
101  if ((flags&NDI_ALL) || (flags&NDI_ALL_DMS)) {
102  player *tmppl;
103 
104  for (tmppl = first_player; tmppl != NULL; tmppl = tmppl->next) {
105  if ((flags&NDI_ALL_DMS) && !QUERY_FLAG(tmppl->ob, FLAG_WIZ))
106  continue;
107  draw_ext_info((flags&~NDI_ALL&~NDI_ALL_DMS), pri, tmppl->ob, type, subtype, message);
108  }
109  // If NDI_NO_TRANSLATE is set, we assume the message was already printed to the log.
110  // So we skip it in that case. Otherwise we print it.
111  if ((~flags)&NDI_NO_TRANSLATE)
112  LOG(llevInfo, "-- %s\n", message);
113  return;
114  }
115 
116  if (!pl || (pl->type == PLAYER && pl->contr == NULL))
117  return;
118  if (pl->type != PLAYER)
119  return;
120  if (pri >= pl->contr->listening)
121  return;
122 
123  if (flags & NDI_DELAYED) {
124  SockList *sl = player_get_delayed_buffer(pl->contr);
126  } else {
128  }
129 }
130 
155 void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format, ...) {
156  char buf[HUGE_BUF];
157  va_list ap;
158 
159  // Make sure the buf starts with \0.
160  // We will check for this when we attempt to print the translated string to buffer.
161  *buf = '\0';
162 
163  va_start(ap, format);
164  // If NDI_ALL or NDI_ALL_DM, first do the buffer for the untranslated message to the log file,
165  if ((flags&NDI_ALL) || (flags&NDI_ALL_DMS)) {
166  vsnprintf(buf, HUGE_BUF, format, ap);
167  LOG(llevInfo, "-- %s\n", buf);
168  va_end(ap);
169  va_start(ap, format);
170  }
171  // Then, if we need to translate, attempt to do so.
172  if ((~flags)&NDI_NO_TRANSLATE)
173  vsnprintf(buf, HUGE_BUF, i18n(pl, format), ap);
174  // Otherwise, print only to an empty string, because we already did if it is not empty.
175  else if (*buf == '\0')
176  vsnprintf(buf, HUGE_BUF, format, ap);
177  va_end(ap);
178  // Since we already translated, we do not need to do so again.
179  draw_ext_info(flags|NDI_NO_TRANSLATE, pri, pl, type, subtype, buf);
180 }
181 
195 void ext_info_map(int color, const mapstruct *map, uint8_t type, uint8_t subtype, const char *str1) {
196  player *pl;
197 
198  for (pl = first_player; pl != NULL; pl = pl->next)
199  if (pl->ob != NULL && pl->ob->map == map) {
200  draw_ext_info(color, 0, pl->ob, type, subtype, str1);
201  }
202 }
203 
219 void ext_info_map_except(int color, const mapstruct *map, const object *op, uint8_t type, uint8_t subtype, const char *str1) {
220  player *pl;
221 
222  for (pl = first_player; pl != NULL; pl = pl->next)
223  if (pl->ob != NULL && pl->ob->map == map && pl->ob != op) {
224  draw_ext_info(color, 0, pl->ob, type, subtype, str1);
225  }
226 }
227 
245 void ext_info_map_except2(int color, const mapstruct *map, const object *op1, const object *op2, int type, int subtype, const char *str1) {
246  player *pl;
247 
248  for (pl = first_player; pl != NULL; pl = pl->next)
249  if (pl->ob != NULL && pl->ob->map == map
250  && pl->ob != op1 && pl->ob != op2) {
251  draw_ext_info(color, 0, pl->ob, type, subtype, str1);
252  }
253 }
254 
264 void rangetostring(const object *pl, char *obuf, size_t len) {
265  char name[MAX_BUF];
266 
267  switch (pl->contr->shoottype) {
268  case range_none:
269  strncpy(obuf, "Range: nothing", len);
270  break;
271 
272  case range_bow: {
273  object *op;
274 
275  for (op = pl->inv; op; op = op->below)
276  if (op->type == BOW && QUERY_FLAG(op, FLAG_APPLIED))
277  break;
278  if (op == NULL)
279  break;
280 
282  snprintf(obuf, len, "Range: %s (%s)", name, op->race ? op->race : "nothing");
283  }
284  break;
285 
286  case range_magic:
287  if (settings.casting_time == TRUE && pl->casting_time > -1) {
288  if (pl->casting_time == 0)
289  snprintf(obuf, len, "Range: Holding spell (%s)", pl->spell->name);
290  else
291  snprintf(obuf, len, "Range: Casting spell (%s)", pl->spell->name);
292  }
293  else
294  snprintf(obuf, len, "Range: spell (%s)", pl->contr->ranges[range_magic]->name);
295  break;
296 
297  case range_misc:
298  if (pl->contr->ranges[range_misc])
299  query_base_name(pl->contr->ranges[range_misc], 0, name, MAX_BUF);
300  else
301  strncpy(name, "none", MAX_BUF);
302  snprintf(obuf, len, "Range: %s", name);
303  break;
304 
305  /* range_scroll is only used for controlling golems. If the
306  * the player does not have a golem, reset some things.
307  */
308  case range_golem:
309  if (pl->contr->ranges[range_golem] != NULL)
310  snprintf(obuf, len, "Range: golem (%s)", pl->contr->ranges[range_golem]->name);
311  else {
312  pl->contr->shoottype = range_none;
313  strncpy(obuf, "Range: nothing", len);
314  }
315  break;
316 
317  case range_skill:
318  snprintf(obuf, len, "Skill: %s", pl->chosen_skill != NULL ? pl->chosen_skill->name : "none");
319  break;
320 
321  case range_builder:
322  query_base_name(pl->contr->ranges[range_builder], 0, name, MAX_BUF);
323  snprintf(obuf, len, "Builder: %s", name);
324  break;
325 
326  default:
327  strncpy(obuf, "Range: illegal", len);
328  }
329 }
330 
334 void set_title(const object *pl, char *buf, size_t len) {
335  char *p;
336 
337  snprintf(buf, len, "Player: %s ", pl->name);
338  p = strchr(buf, '\0');
339  player_get_title(pl->contr, p, (buf+len)-p);
340 }
341 
359 static void magic_mapping_mark_recursive(object *pl, char *map_mark, int px, int py) {
360  int x, y, dx, dy, mflags, l;
361  int16_t nx, ny;
362  mapstruct *mp;
363  const Face *f;
364  object *ob;
365 
366  for (dx = -1; dx <= 1; dx++) {
367  for (dy = -1; dy <= 1; dy++) {
368  x = px+dx;
369  y = py+dy;
370 
371  if (FABS(x) >= MAGIC_MAP_HALF || FABS(y) >= MAGIC_MAP_HALF)
372  continue;
373 
374  mp = pl->map;
375  nx = pl->x+x;
376  ny = pl->y+y;
377 
378  mflags = get_map_flags(pl->map, &mp, nx, ny, &nx, &ny);
379  if (mflags&P_OUT_OF_MAP)
380  continue;
381 
382  if (map_mark[MAGIC_MAP_HALF+x+MAGIC_MAP_SIZE*(MAGIC_MAP_HALF+y)] == 0) {
383  for (l = 0; l < MAP_LAYERS; l++) {
384  ob = GET_MAP_FACE_OBJ(mp, nx, ny, l);
385  if (ob && !ob->invisible && ob->face != blank_face)
386  break;
387  }
388  if (ob)
389  f = ob->face;
390  else
391  f = blank_face;
392 
393  /* Should probably have P_NO_MAGIC here also, but then shops don't
394  * work.
395  */
396  if (mflags&P_BLOCKSVIEW)
397  map_mark[MAGIC_MAP_HALF+x+MAGIC_MAP_SIZE*(MAGIC_MAP_HALF+y)] = FACE_WALL|(f ? f->magicmap : 0);
398  else {
400  magic_mapping_mark_recursive(pl, map_mark, x, y);
401  }
402  }
403  }
404  }
405 }
406 
427 void magic_mapping_mark(object *pl, char *map_mark, int strength) {
428  int x, y, mflags, l;
429  int16_t nx, ny;
430  mapstruct *mp;
431  const Face *f;
432  object *ob;
433 
434  for (x = -strength; x < strength; x++) {
435  for (y = -strength; y < strength; y++) {
436  mp = pl->map;
437  nx = pl->x+x;
438  ny = pl->y+y;
439  mflags = get_map_flags(pl->map, &mp, nx, ny, &nx, &ny);
440  if (mflags&P_OUT_OF_MAP)
441  continue;
442  else {
443  for (l = 0; l < MAP_LAYERS; l++) {
444  ob = GET_MAP_FACE_OBJ(mp, nx, ny, l);
445  if (ob && !ob->invisible && ob->face != blank_face)
446  break;
447  }
448  if (ob)
449  f = ob->face;
450  else
451  f = blank_face;
452  }
453 
454  if (mflags&P_BLOCKSVIEW)
455  map_mark[MAGIC_MAP_HALF+x+MAGIC_MAP_SIZE*(MAGIC_MAP_HALF+y)] = FACE_WALL|(f ? f->magicmap : 0);
456  else {
458  magic_mapping_mark_recursive(pl, map_mark, x, y);
459  }
460  }
461  }
462 }
463 
474 void draw_magic_map(object *pl) {
475  int x, y;
476  char map_mark[MAGIC_MAP_SIZE*MAGIC_MAP_SIZE];
477  int xmin, xmax, ymin, ymax;
478  SockList sl;
479 
480  if (pl->type != PLAYER) {
481  LOG(llevError, "Non player object called draw_map.\n");
482  return;
483  }
484 
485  /* First, we figure out what spaces are 'reachable' by the player */
486  memset(map_mark, 0, MAGIC_MAP_SIZE*MAGIC_MAP_SIZE);
487  magic_mapping_mark(pl, map_mark, 3);
488 
489  /* We now go through and figure out what spaces have been
490  * marked, and thus figure out rectangular region we send
491  * to the client (eg, if only a 10x10 area is visible, we only
492  * want to send those 100 spaces.)
493  */
494  xmin = MAGIC_MAP_SIZE;
495  ymin = MAGIC_MAP_SIZE;
496  xmax = 0;
497  ymax = 0;
498  for (x = 0; x < MAGIC_MAP_SIZE; x++) {
499  for (y = 0; y < MAGIC_MAP_SIZE; y++) {
500  if (map_mark[x+MAGIC_MAP_SIZE*y]&~FACE_FLOOR) {
501  xmin = MIN(x, xmin);
502  xmax = MAX(x, xmax);
503  ymin = MIN(y, ymin);
504  ymax = MAX(y, ymax);
505  }
506  }
507  }
508 
509  SockList_Init(&sl);
510  SockList_AddPrintf(&sl, "magicmap %d %d %d %d ", xmin <= xmax ? xmax-xmin+1 : 0, ymin <= ymax ? ymax-ymin+1 : 0, MAGIC_MAP_HALF-xmin, MAGIC_MAP_HALF-ymin);
511 
512  for (y = ymin; y <= ymax; y++) {
513  for (x = xmin; x <= xmax; x++) {
514  SockList_AddChar(&sl, map_mark[x+MAGIC_MAP_SIZE*y]&~FACE_FLOOR);
515  } /* x loop */
516  } /* y loop */
517 
518  Send_With_Handling(pl->contr->socket, &sl);
519  SockList_Term(&sl);
520 }
PLAYER
@ PLAYER
Definition: object.h:112
player::next
player * next
Definition: player.h:106
global.h
first_player
player * first_player
Definition: init.cpp:106
settings
struct Settings settings
Definition: init.cpp:139
banquet.l
l
Definition: banquet.py:164
BOW
@ BOW
Definition: object.h:123
llevError
@ llevError
Definition: logger.h:11
FABS
#define FABS(x)
Definition: define.h:22
range_bow
@ range_bow
Definition: player.h:31
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:51
NDI_NO_TRANSLATE
#define NDI_NO_TRANSLATE
Definition: newclient.h:255
player
Definition: player.h:105
diamondslots.x
x
Definition: diamondslots.py:15
ext_info_map_except
void ext_info_map_except(int color, const mapstruct *map, const object *op, uint8_t type, uint8_t subtype, const char *str1)
Definition: info.cpp:219
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
socket_struct
Definition: newserver.h:89
player::ob
object * ob
Definition: player.h:177
NDI_COLOR_MASK
#define NDI_COLOR_MASK
Definition: newclient.h:247
guildjoin.ob
ob
Definition: guildjoin.py:42
range_none
@ range_none
Definition: player.h:30
MIN
#define MIN(x, y)
Definition: compat.h:21
MAP_LAYERS
#define MAP_LAYERS
Definition: map.h:32
NDI_ALL_DMS
#define NDI_ALL_DMS
Definition: newclient.h:253
flags
static const flag_definition flags[]
Definition: gridarta-types-convert.cpp:101
blank_face
const Face * blank_face
Definition: image.cpp:36
skills.h
range_golem
@ range_golem
Definition: player.h:34
smoking_pipe.color
color
Definition: smoking_pipe.py:5
FLAG_APPLIED
#define FLAG_APPLIED
Definition: define.h:235
buf
StringBuffer * buf
Definition: readable.cpp:1552
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
MAX
#define MAX(x, y)
Definition: compat.h:24
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
magic_mapping_mark_recursive
static void magic_mapping_mark_recursive(object *pl, char *map_mark, int px, int py)
Definition: info.cpp:359
range_builder
@ range_builder
Definition: player.h:36
SockList
Definition: newclient.h:670
MAGIC_MAP_SIZE
#define MAGIC_MAP_SIZE
Definition: map.h:24
disinfect.map
map
Definition: disinfect.py:4
print_ext_msg
void print_ext_msg(socket_struct *ns, int color, uint8_t type, uint8_t subtype, const char *message)
Definition: info.cpp:62
py
Install Bug reporting Credits so make sure you have version or later There are files involved in the automatic convert py
Definition: README.txt:7
magic_mapping_mark
void magic_mapping_mark(object *pl, char *map_mark, int strength)
Definition: info.cpp:427
range_magic
@ range_magic
Definition: player.h:32
NDI_DELAYED
#define NDI_DELAYED
Definition: newclient.h:258
SockList_AddChar
void SockList_AddChar(SockList *sl, unsigned char c)
Definition: lowlevel.cpp:103
MAGIC_MAP_HALF
#define MAGIC_MAP_HALF
Definition: map.h:25
GET_MAP_FACE_OBJ
#define GET_MAP_FACE_OBJ(M, X, Y, L)
Definition: map.h:183
FACE_WALL
#define FACE_WALL
Definition: newclient.h:293
message
TIPS on SURVIVING Crossfire is populated with a wealth of different monsters These monsters can have varying immunities and attack types In some of them can be quite a bit smarter than others It will be important for new players to learn the abilities of different monsters and learn just how much it will take to kill them This section discusses how monsters can interact with players Most monsters in the game are out to mindlessly kill and destroy the players These monsters will help boost a player s after he kills them When fighting a large amount of monsters in a single attempt to find a narrower hallway so that you are not being attacked from all sides Charging into a room full of Beholders for instance would not be open the door and fight them one at a time For there are several maps designed for them Find these areas and clear them out All throughout these a player can find signs and books which they can read by stepping onto them and hitting A to apply the book sign These messages will help the player to learn the system One more always keep an eye on your food If your food drops to your character will soon so BE CAREFUL ! NPCs Non Player Character are special monsters which have intelligence Players may be able to interact with these monsters to help solve puzzles and find items of interest To speak with a monster you suspect to be a simply move to an adjacent square to them and push the double ie Enter your message
Definition: survival-guide.txt:34
do_print_ext
static void do_print_ext(SockList *sl, int color, uint8_t type, uint8_t subtype, const char *message)
Definition: info.cpp:41
FACE_FLOOR
#define FACE_FLOOR
Definition: newclient.h:292
sproto.h
Settings::casting_time
uint8_t casting_time
Definition: global.h:270
SockList_Init
void SockList_Init(SockList *sl)
Definition: lowlevel.cpp:52
P_OUT_OF_MAP
#define P_OUT_OF_MAP
Definition: map.h:248
MAX_BUF
#define MAX_BUF
Definition: define.h:35
ext_info_map_except2
void ext_info_map_except2(int color, const mapstruct *map, const object *op1, const object *op2, int type, int subtype, const char *str1)
Definition: info.cpp:245
Face::magicmap
uint8_t magicmap
Definition: face.h:17
SockList_Term
void SockList_Term(SockList *sl)
Definition: lowlevel.cpp:62
range_misc
@ range_misc
Definition: player.h:33
FLAG_WIZ
#define FLAG_WIZ
Definition: define.h:231
llevInfo
@ llevInfo
Definition: logger.h:12
set_title
void set_title(const object *pl, char *buf, size_t len)
Definition: info.cpp:334
spells.h
draw_ext_info
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: info.cpp:97
get_map_flags
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
Definition: map.cpp:299
rangetostring
void rangetostring(const object *pl, char *obuf, size_t len)
Definition: info.cpp:264
mapstruct
Definition: map.h:314
give.op
op
Definition: give.py:33
NDI_ALL
#define NDI_ALL
Definition: newclient.h:252
format
Python Guilds Quick outline Add a guild(mapmakers) this is still a problem *after dropping the token to gain access to the stove a woodfloor now appears which is Toolshed Token(found in Guild_HQ) *Note also have multiple gates in place to protect players and items from the mana explosion drop x for Jewelers room *Jewelers room works just need to determine what x is drop x for Thaumaturgy room *Thaumaturgy room works just need to determine what x is drop gold dropping the Firestar named fearless allows access to but I suspect that the drop location of the chest is not as intended because the player is in the way once you enter the chest the exit back to the basement is things such as the message et al reside on teleporters which then transport items to the map as they are when the map is already purchased items reappear in that area From my this does not cause any problems at the moment But this should be corrected fixed Major it s now possible to buy guilds Ryo Update Uploaded guild package to CVS Changes the cauldrons and the charging room I spent a while agonizing over They were natural guild enhancements but much too much value for any reasonable expense to buy them Then I thought that they should be pay access but at a greatly reduced rate SO when you buy a forge or whatever for your guild it is available on a perplayer daily rate but it will be accessable for testing and to DMs to play with Like I said lots still to do with the especially comingt up with quest items for buying things like the new workshops and stuff One of the things I would like some input on would be proposals for additional fields for either the guildhouses or guild datafiles to play with Currently the Guildhouse but there is no reason we can t have more than one measure of a guild perhaps have dues relate to Dues and use points for some other suspended or inactive or when a guild is founded inactive active Guilds have the format
Definition: README.txt:140
diamondslots.y
y
Definition: diamondslots.py:16
draw_magic_map
void draw_magic_map(object *pl)
Definition: info.cpp:474
Face
Definition: face.h:14
player_get_delayed_buffer
SockList * player_get_delayed_buffer(player *pl)
Definition: player.cpp:4488
query_base_name
void query_base_name(const object *op, int plural, char *buf, size_t size)
Definition: item.cpp:693
range_skill
@ range_skill
Definition: player.h:35
TRUE
#define TRUE
Definition: compat.h:11
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Definition: info.cpp:155
Send_With_Handling
void Send_With_Handling(socket_struct *ns, SockList *sl)
Definition: lowlevel.cpp:444
is_valid_types_gen.type
list type
Definition: is_valid_types_gen.py:25
SockList_AddPrintf
void SockList_AddPrintf(SockList *sl, const char *format,...)
Definition: lowlevel.cpp:199
i18n
const char * i18n(const object *who, const char *code)
Definition: languages.cpp:42
P_BLOCKSVIEW
#define P_BLOCKSVIEW
Definition: map.h:225
ext_info_map
void ext_info_map(int color, const mapstruct *map, uint8_t type, uint8_t subtype, const char *str1)
Definition: info.cpp:195
player_get_title
void player_get_title(const player *pl, char *buf, size_t bufsize)
Definition: player.cpp:232