Crossfire Server, Trunk  R20513
info.c
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 
49 void print_ext_msg(socket_struct *ns, int color, uint8_t type, uint8_t subtype, const char *message) {
50  SockList sl;
51 
52  SockList_Init(&sl);
53  SockList_AddPrintf(&sl, "drawextinfo %d %hhu %hhu %s", color, type, subtype, message);
54  Send_With_Handling(ns, &sl);
55  SockList_Term(&sl);
56 }
57 
87  int flags, int pri, const object *pl, uint8_t type,
88  uint8_t subtype, const char *message) {
89 
90  if ((flags&NDI_ALL) || (flags&NDI_ALL_DMS)) {
91  player *tmppl;
92 
93  for (tmppl = first_player; tmppl != NULL; tmppl = tmppl->next) {
94  if ((flags&NDI_ALL_DMS) && !QUERY_FLAG(tmppl->ob, FLAG_WIZ))
95  continue;
96  draw_ext_info((flags&~NDI_ALL&~NDI_ALL_DMS), pri, tmppl->ob, type, subtype, message);
97  }
98 
99  LOG(llevInfo, "-- %s\n", message);
100  return;
101  }
102 
103  if (!pl || (pl->type == PLAYER && pl->contr == NULL))
104  return;
105  if (pl->type != PLAYER)
106  return;
107  if (pri >= pl->contr->listening)
108  return;
109 
110  print_ext_msg(&pl->contr->socket, flags&NDI_COLOR_MASK, type, subtype, message);
111 }
112 
137 void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format, ...) {
138  char buf[HUGE_BUF];
139  va_list ap;
140 
141  va_start(ap, format);
142  vsnprintf(buf, HUGE_BUF, format, ap);
143  va_end(ap);
144 
145  draw_ext_info(flags, pri, pl, type, subtype, buf);
146 }
147 
161 void ext_info_map(int color, const mapstruct *map, uint8_t type, uint8_t subtype, const char *str1) {
162  player *pl;
163 
164  for (pl = first_player; pl != NULL; pl = pl->next)
165  if (pl->ob != NULL && pl->ob->map == map) {
166  draw_ext_info(color, 0, pl->ob, type, subtype, str1);
167  }
168 }
169 
185 void ext_info_map_except(int color, const mapstruct *map, const object *op, uint8_t type, uint8_t subtype, const char *str1) {
186  player *pl;
187 
188  for (pl = first_player; pl != NULL; pl = pl->next)
189  if (pl->ob != NULL && pl->ob->map == map && pl->ob != op) {
190  draw_ext_info(color, 0, pl->ob, type, subtype, str1);
191  }
192 }
193 
211 void ext_info_map_except2(int color, const mapstruct *map, const object *op1, const object *op2, int type, int subtype, const char *str1) {
212  player *pl;
213 
214  for (pl = first_player; pl != NULL; pl = pl->next)
215  if (pl->ob != NULL && pl->ob->map == map
216  && pl->ob != op1 && pl->ob != op2) {
217  draw_ext_info(color, 0, pl->ob, type, subtype, str1);
218  }
219 }
220 
230 void rangetostring(const object *pl, char *obuf, size_t len) {
231  char name[MAX_BUF];
232 
233  switch (pl->contr->shoottype) {
234  case range_none:
235  strncpy(obuf, "Range: nothing", len);
236  break;
237 
238  case range_bow: {
239  object *op;
240 
241  for (op = pl->inv; op; op = op->below)
242  if (op->type == BOW && QUERY_FLAG(op, FLAG_APPLIED))
243  break;
244  if (op == NULL)
245  break;
246 
247  query_base_name(op, 0, name, MAX_BUF);
248  snprintf(obuf, len, "Range: %s (%s)", name, op->race ? op->race : "nothing");
249  }
250  break;
251 
252  case range_magic:
253  if (settings.casting_time == TRUE && pl->casting_time > -1) {
254  if (pl->casting_time == 0)
255  snprintf(obuf, len, "Range: Holding spell (%s)", pl->spell->name);
256  else
257  snprintf(obuf, len, "Range: Casting spell (%s)", pl->spell->name);
258  }
259  else
260  snprintf(obuf, len, "Range: spell (%s)", pl->contr->ranges[range_magic]->name);
261  break;
262 
263  case range_misc:
264  if (pl->contr->ranges[range_misc])
265  query_base_name(pl->contr->ranges[range_misc], 0, name, MAX_BUF);
266  else
267  strncpy(name, "none", MAX_BUF);
268  snprintf(obuf, len, "Range: %s", name);
269  break;
270 
271  /* range_scroll is only used for controlling golems. If the
272  * the player does not have a golem, reset some things.
273  */
274  case range_golem:
275  if (pl->contr->ranges[range_golem] != NULL)
276  snprintf(obuf, len, "Range: golem (%s)", pl->contr->ranges[range_golem]->name);
277  else {
278  pl->contr->shoottype = range_none;
279  strncpy(obuf, "Range: nothing", len);
280  }
281  break;
282 
283  case range_skill:
284  snprintf(obuf, len, "Skill: %s", pl->chosen_skill != NULL ? pl->chosen_skill->name : "none");
285  break;
286 
287  case range_builder:
289  snprintf(obuf, len, "Builder: %s", name);
290  break;
291 
292  default:
293  strncpy(obuf, "Range: illegal", len);
294  }
295 }
296 
300 void set_title(const object *pl, char *buf, size_t len) {
301  char *p;
302 
303  snprintf(buf, len, "Player: %s ", pl->name);
304  p = strchr(buf, '\0');
305  player_get_title(pl->contr, p, (buf+len)-p);
306 }
307 
325 static void magic_mapping_mark_recursive(object *pl, char *map_mark, int px, int py) {
326  int x, y, dx, dy, mflags, l;
327  int16_t nx, ny;
328  mapstruct *mp;
329  const New_Face *f;
330  object *ob;
331 
332  for (dx = -1; dx <= 1; dx++) {
333  for (dy = -1; dy <= 1; dy++) {
334  x = px+dx;
335  y = py+dy;
336 
337  if (FABS(x) >= MAGIC_MAP_HALF || FABS(y) >= MAGIC_MAP_HALF)
338  continue;
339 
340  mp = pl->map;
341  nx = pl->x+x;
342  ny = pl->y+y;
343 
344  mflags = get_map_flags(pl->map, &mp, nx, ny, &nx, &ny);
345  if (mflags&P_OUT_OF_MAP)
346  continue;
347 
348  if (map_mark[MAGIC_MAP_HALF+x+MAGIC_MAP_SIZE*(MAGIC_MAP_HALF+y)] == 0) {
349  for (l = 0; l < MAP_LAYERS; l++) {
350  ob = GET_MAP_FACE_OBJ(mp, nx, ny, l);
351  if (ob && !ob->invisible && ob->face != blank_face)
352  break;
353  }
354  if (ob)
355  f = ob->face;
356  else
357  f = blank_face;
358 
359  /* Should probably have P_NO_MAGIC here also, but then shops don't
360  * work.
361  */
362  if (mflags&P_BLOCKSVIEW)
363  map_mark[MAGIC_MAP_HALF+x+MAGIC_MAP_SIZE*(MAGIC_MAP_HALF+y)] = FACE_WALL|(f ? f->magicmap : 0);
364  else {
365  map_mark[MAGIC_MAP_HALF+x+MAGIC_MAP_SIZE*(MAGIC_MAP_HALF+y)] = FACE_FLOOR|(f ? f->magicmap : 0);
366  magic_mapping_mark_recursive(pl, map_mark, x, y);
367  }
368  }
369  }
370  }
371 }
372 
393 void magic_mapping_mark(object *pl, char *map_mark, int strength) {
394  int x, y, mflags, l;
395  int16_t nx, ny;
396  mapstruct *mp;
397  const New_Face *f;
398  object *ob;
399 
400  for (x = -strength; x < strength; x++) {
401  for (y = -strength; y < strength; y++) {
402  mp = pl->map;
403  nx = pl->x+x;
404  ny = pl->y+y;
405  mflags = get_map_flags(pl->map, &mp, nx, ny, &nx, &ny);
406  if (mflags&P_OUT_OF_MAP)
407  continue;
408  else {
409  for (l = 0; l < MAP_LAYERS; l++) {
410  ob = GET_MAP_FACE_OBJ(mp, nx, ny, l);
411  if (ob && !ob->invisible && ob->face != blank_face)
412  break;
413  }
414  if (ob)
415  f = ob->face;
416  else
417  f = blank_face;
418  }
419 
420  if (mflags&P_BLOCKSVIEW)
421  map_mark[MAGIC_MAP_HALF+x+MAGIC_MAP_SIZE*(MAGIC_MAP_HALF+y)] = FACE_WALL|(f ? f->magicmap : 0);
422  else {
423  map_mark[MAGIC_MAP_HALF+x+MAGIC_MAP_SIZE*(MAGIC_MAP_HALF+y)] = FACE_FLOOR|(f ? f->magicmap : 0);
424  magic_mapping_mark_recursive(pl, map_mark, x, y);
425  }
426  }
427  }
428 }
429 
440 void draw_magic_map(object *pl) {
441  int x, y;
442  char map_mark[MAGIC_MAP_SIZE*MAGIC_MAP_SIZE];
443  int xmin, xmax, ymin, ymax;
444  SockList sl;
445 
446  if (pl->type != PLAYER) {
447  LOG(llevError, "Non player object called draw_map.\n");
448  return;
449  }
450 
451  /* First, we figure out what spaces are 'reachable' by the player */
452  memset(map_mark, 0, MAGIC_MAP_SIZE*MAGIC_MAP_SIZE);
453  magic_mapping_mark(pl, map_mark, 3);
454 
455  /* We now go through and figure out what spaces have been
456  * marked, and thus figure out rectangular region we send
457  * to the client (eg, if only a 10x10 area is visible, we only
458  * want to send those 100 spaces.)
459  */
460  xmin = MAGIC_MAP_SIZE;
461  ymin = MAGIC_MAP_SIZE;
462  xmax = 0;
463  ymax = 0;
464  for (x = 0; x < MAGIC_MAP_SIZE; x++) {
465  for (y = 0; y < MAGIC_MAP_SIZE; y++) {
466  if (map_mark[x+MAGIC_MAP_SIZE*y]&~FACE_FLOOR) {
467  xmin = MIN(x, xmin);
468  xmax = MAX(x, xmax);
469  ymin = MIN(y, ymin);
470  ymax = MAX(y, ymax);
471  }
472  }
473  }
474 
475  SockList_Init(&sl);
476  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);
477 
478  for (y = ymin; y <= ymax; y++) {
479  for (x = xmin; x <= xmax; x++) {
480  SockList_AddChar(&sl, map_mark[x+MAGIC_MAP_SIZE*y]&~FACE_FLOOR);
481  } /* x loop */
482  } /* y loop */
483 
484  Send_With_Handling(&pl->contr->socket, &sl);
485  SockList_Term(&sl);
486 }
Error, serious thing.
Definition: logger.h:11
Use skill.
Definition: player.h:22
void SockList_AddPrintf(SockList *sl, const char *format,...)
Adds a printf like formatted string.
Definition: lowlevel.c:194
One player.
Definition: player.h:92
Spell-related defines: spellpath, subtypes, ...
Information.
Definition: logger.h:12
const char * race
Human, goblin, dragon, etc.
Definition: object.h:318
void SockList_Init(SockList *sl)
Initializes the SockList instance.
Definition: lowlevel.c:48
#define NDI_ALL
Inform all players of this message.
Definition: newclient.h:246
#define FABS(x)
Decstations have trouble with fabs()...
Definition: define.h:22
unsigned char uint8_t
Definition: win32.h:161
void player_get_title(const struct pl *pl, char *buf, size_t bufsize)
Returns the player&#39;s title.
Definition: player.c:224
No range selected.
Definition: player.h:17
#define HUGE_BUF
Used for messages - some can be quite long.
Definition: define.h:37
#define FACE_WALL
Or&#39;d into the color value by the server right before sending.
Definition: newclient.h:278
void query_base_name(const object *op, int plural, char *buf, size_t size)
Query a short name for the item.
Definition: item.c:722
Socket structure, represents a client-server connection.
Definition: newserver.h:99
socket_struct socket
Socket information for this player.
Definition: player.h:94
int16_t invisible
How much longer the object will be invis.
Definition: object.h:360
rangetype shoottype
Which range-attack is being used by player.
Definition: player.h:99
object * ranges[range_size]
Object for each range.
Definition: player.h:103
Misc items.
Definition: player.h:20
#define TRUE
Definition: compat.h:10
#define FACE_FLOOR
Definition: newclient.h:277
#define MAX(x, y)
Definition: compat.h:20
Global type definitions and header inclusions.
uint8_t casting_time
It takes awhile to cast a spell.
Definition: global.h:268
void set_title(const object *pl, char *buf, size_t len)
Sets player title.
Definition: info.c:300
#define MIN(x, y)
Definition: compat.h:17
struct obj * chosen_skill
The skill chosen to use.
Definition: object.h:386
int16_t y
Position in the map for this object.
Definition: object.h:326
See Shooting Weapon.
Definition: object.h:118
struct obj * spell
Spell that was being cast.
Definition: object.h:408
signed short int16_t
Definition: win32.h:160
#define NDI_ALL_DMS
Inform all logged in DMs.
Definition: newclient.h:247
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
Definition: info.c:86
struct mapdef * map
Pointer to the map in which this object is present.
Definition: object.h:297
void SockList_Term(SockList *sl)
Frees all resources allocated by a SockList instance.
Definition: lowlevel.c:58
#define snprintf
Definition: win32.h:46
Map builder.
Definition: player.h:23
Control golem.
Definition: player.h:21
#define MAP_LAYERS
Definition: map.h:32
const char * name
The name of the object, obviously...
Definition: object.h:311
struct obj * below
Pointer to the object stacked below this one.
Definition: object.h:287
void rangetostring(const object *pl, char *obuf, size_t len)
Get player&#39;s current range attack in obuf.
Definition: info.c:230
uint8_t listening
Which priority will be used in info_all.
Definition: player.h:120
#define NDI_COLOR_MASK
Gives lots of room for expansion - we are using an int anyways, so we have the space to still do all ...
Definition: newclient.h:238
#define P_OUT_OF_MAP
This space is outside the map.
Definition: map.h:251
struct pl * contr
Pointer to the player which control this object.
Definition: object.h:276
uint8_t magicmap
Color to show this in magic map.
Definition: face.h:18
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
void draw_magic_map(object *pl)
Creates and sends magic map to player.
Definition: info.c:440
#define FLAG_WIZ
Object has special privilegies.
Definition: define.h:231
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
int16_t x
Definition: object.h:326
Skill-related defines, including subtypes.
void SockList_AddChar(SockList *sl, char c)
Adds an 8 bit value.
Definition: lowlevel.c:98
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Sends message to player(s).
Definition: info.c:137
static const flag_definition flags[]
Flag mapping.
#define MAGIC_MAP_HALF
Definition: map.h:25
object * ob
The object representing the player.
Definition: player.h:158
See Player.
Definition: object.h:107
#define GET_MAP_FACE_OBJ(M, X, Y, L)
Gets the layer face of specified square.
Definition: map.h:184
static void magic_mapping_mark_recursive(object *pl, char *map_mark, int px, int py)
Helper for magic map creation.
Definition: info.c:325
#define vsnprintf
Definition: win32.h:61
New_Face * blank_face
Following can just as easily be pointers, but it is easier to keep them like this.
Definition: image.c:39
void ext_info_map_except2(int color, const mapstruct *map, const object *op1, const object *op2, int type, int subtype, const char *str1)
Writes to everyone on the map except op1 and op2.
Definition: info.c:211
#define MAGIC_MAP_SIZE
Definition: map.h:24
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
struct Settings settings
Server settings.
Definition: init.c:40
#define FLAG_APPLIED
Object is ready for use by living.
Definition: define.h:235
void magic_mapping_mark(object *pl, char *map_mark, int strength)
Creates magic map for player.
Definition: info.c:393
int16_t casting_time
Time left before spell goes off.
Definition: object.h:402
Bow.
Definition: player.h:18
EXTERN player * first_player
First player.
Definition: global.h:117
New face structure - this enforces the notion that data is face by face only - you can not change the...
Definition: face.h:14
struct pl * next
Pointer to next player, NULL if this is last.
Definition: player.h:93
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
This rolls up wall, blocks_magic, blocks_view, etc, all into one function that just returns a P_...
Definition: map.c:302
struct obj * inv
Pointer to the first object in the inventory.
Definition: object.h:290
Spells.
Definition: player.h:19
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.c:51
#define P_BLOCKSVIEW
This spot blocks the player&#39;s view.
Definition: map.h:226
void ext_info_map(int color, const mapstruct *map, uint8_t type, uint8_t subtype, const char *str1)
Writes to everyone on the specified map.
Definition: info.c:161
Contains the base information we use to make up a packet we want to send.
Definition: newclient.h:680
This is a game-map.
Definition: map.h:325
const New_Face * face
Face with colors.
Definition: object.h:332
void print_ext_msg(socket_struct *ns, int color, uint8_t type, uint8_t subtype, const char *message)
Draws an extended message on the client.
Definition: info.c:49
void ext_info_map_except(int color, const mapstruct *map, const object *op, uint8_t type, uint8_t subtype, const char *str1)
Writes to everyone on the map except *op.
Definition: info.c:185
void Send_With_Handling(socket_struct *ns, SockList *sl)
Calls Write_To_Socket to send data to the client.
Definition: lowlevel.c:542