Crossfire Server  1.75.0
c_misc.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 
20 #include "global.h"
21 
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 
27 #undef SS_STATISTICS
28 #include "loader.h"
29 #include "shstr.h"
30 #include "sounds.h"
31 #include "sproto.h"
32 #include "version.h"
33 
34 #include "assets.h"
35 #include "AssetsManager.h"
36 
37 /* Static declarations where needed (when ordering would be an issue) */
38 static void display_who_entry(object *op, player *pl, const char *format);
39 static void get_who_escape_code_value(char *return_val, int size, const char letter, player *pl);
40 static int onoff_value(const char *line);
41 
50 static void map_info(object *op, const char *search) {
51  if ( *search != 0 ) {
53  "Maps matching search: '%s'", search);
54  }
55  if (QUERY_FLAG(op, FLAG_WIZ)) {
57  "[fixed]Path Reset In (HH:MM:SS) Pl IM TO");
58  } else {
60  "[fixed]Path Reset In (HH:MM)");
61  }
62 
63  /* Allow a comma-separate list of search strings; more complicated because of the const */
64  char *to_be_freed = NULL;
65  char *search_array[64];
66  int search_array_count = 0;
67  if ( search[0] ) {
68  to_be_freed = strdup(search);
69  if ( !to_be_freed ) {
70  search_array[0] = to_be_freed;
71  search_array_count = 1;
72  } else {
73  search_array_count = split_string(to_be_freed,search_array,64,',');
74  }
75  }
76 
77  for (mapstruct *m = first_map; m != NULL; m = m->next) {
78  bool match = TRUE;
79  if ( search_array_count ) {
80  match = FALSE;
81  for (int i=0; i<search_array_count; ++i) {
82  if ( strstr(m->path,search_array[i]) ) {
83  match=TRUE;
84  break;
85  }
86  }
87  }
88  if ( !match ) continue; /* Skip unwanted maps */
89 
90  /* Print out the last 26 characters of the map name... */
91  char map_path[MAX_BUF];
92  if (strlen(m->path) <= 26) {
93  strcpy(map_path, m->path);
94  } else {
95  safe_strncpy(map_path, m->path + strlen(m->path) - 26, sizeof(map_path));
96  }
97 
98  uint32_t ttr = MAP_WHEN_RESET(m) - seconds() > 0 ? MAP_WHEN_RESET(m) - seconds() : 0;
99  if ( !m->reset_timeout && !m->unique ) set_map_reset_time(m);
100  if (m->players) {
101  ttr = (m->unique ? 0 : m->reset_timeout) + ticks_to_seconds(MAP_MINTIMEOUT);
102  }
103  else if (m->timeout) {
104  ttr = (m->unique ? 0 : m->reset_timeout) + ticks_to_seconds(m->timeout);
105  }
106  const uint32_t hh = ttr/3600, mm = (ttr%3600)/60, ss = ttr%60;
107  if (QUERY_FLAG(op, FLAG_WIZ)) {
110  "[fixed]%-26.26s %2d:%02d:%02d %2d %2d %4d",
111  map_path, hh, mm, ss, m->players, m->in_memory, m->timeout);
112  } else {
115  "[fixed]%-26.26s %2d:%02d%s", map_path, hh, mm,
116  m->players ? " (in use)" : "");
117  }
118  }
119  if ( to_be_freed ) free( to_be_freed );
120 }
121 
130 void command_language(object *op, const char *params) {
131  language_t language = nullptr;
132 
133  if (!op->contr)
134  return;
135 
136  if (*params == '\0' || (!strcmp(params, ""))) {
138  "Your current language is set to: English.");
140  "Available languages:");
142  return;
143  }
144 
145  language = i18n_find_language_by_code(params);
146 
147  /* Error out if unknown language. */
148  if (language == nullptr) {
150  "Unknown language.");
151  return;
152  }
153 
154  op->contr->language = language;
155 
157  "Your current language is set to English.");
158 }
159 
173 void command_body(object *op, const char *params) {
174  int i;
175  (void)params;
176 
177  /* Too hard to try and make a header that lines everything up, so just
178  * give a description.
179  */
181  "The first column is the name of the body location.");
182 
184  "The second column is how many of those locations your body has.");
185 
187  "The third column is how many slots in that location are available.");
188 
189  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
190  /* really debugging - normally body_used should not be set to anything
191  * if body_info isn't also set.
192  */
193  if (op->body_info[i] || op->body_used[i]) {
195  "[fixed]%-30s %5d %5d",
196  i18n(op, body_locations[i].use_name), op->body_info[i], op->body_used[i]);
197  }
198  }
199  if (!QUERY_FLAG(op, FLAG_USE_ARMOUR))
201  "You are not allowed to wear armor.");
202  if (!QUERY_FLAG(op, FLAG_USE_WEAPON))
204  "You are not allowed to use weapons.");
205 }
206 
215 void command_motd(object *op, const char *params) {
216  (void)params;
217  display_motd(op);
218 }
219 
228 void command_rules(object *op, const char *params) {
229  (void)params;
230  send_rules(op);
231 }
232 
241 void command_news(object *op, const char *params) {
242  (void)params;
243  send_news(op);
244 }
245 
252 static void malloc_info(object *op) {
253  int ob_used = object_count_used(), ob_free = object_count_free(), players, nrofmaps;
254  int nrm = 0, mapmem = 0, anr, anims, sum_alloc = 0, sum_used = 0, i, alnr;
255  player *pl;
256  mapstruct *m;
257  artifactlist *al;
258 
259  for (al = first_artifactlist, alnr = 0; al != NULL; al = al->next, alnr++)
260  ;
261 
262  anr = getManager()->archetypes()->count();
263 
264  anims = getManager()->animations()->count();
265 
266  for (pl = first_player, players = 0; pl != NULL; pl = pl->next, players++)
267  ;
268 
269  for (m = first_map, nrofmaps = 0; m != NULL; m = m->next, nrofmaps++)
270  if (m->in_memory == MAP_IN_MEMORY) {
271  mapmem += map_size(m) * (sizeof(object *) + sizeof(MapSpace));
272  nrm++;
273  }
274 
276  "Sizeof: object=%zu player=%zu map=%zu",
277  sizeof(object), sizeof(player), sizeof(mapstruct));
278 
280  "[fixed]Objects:");
281 
283  "[fixed]%6d used", ob_used);
284 
285  if (ob_used != nrofallocobjects - nroffreeobjects) {
287  "[fixed] (used list mismatch: %d)",
289  }
290 
292  "[fixed]%6d free (%.2f%% of %d allocated)",
293  ob_free, (float)ob_free / nrofallocobjects * 100, nrofallocobjects);
294 
295  if (ob_free != nroffreeobjects) {
297  "[fixed] (free list mismatch: %d)",
299  }
300 
302  "[fixed]%6d on active list",
304 
305  i = (ob_used*sizeof(object));
306  sum_used += i;
307  sum_alloc += i;
308 
310  "[fixed] object total: %11d", i);
311 
312  i = (ob_free*sizeof(object));
313  sum_alloc += i;
314 
316  "[fixed]%4d players: %8d",
317  players, i = (players*sizeof(player)));
318 
319  sum_alloc += i;
320  sum_used += i;
321 
323  "[fixed]%4d maps allocated: %8d",
324  nrofmaps, i = (nrofmaps*sizeof(mapstruct)));
325 
326  sum_alloc += i;
327  sum_used += nrm*sizeof(mapstruct);
328 
330  "[fixed]%4d maps in memory: %8d",
331  nrm, mapmem);
332 
333  sum_alloc += mapmem;
334  sum_used += mapmem;
335 
337  "[fixed]%4d archetypes: %8d",
338  anr, i = (anr*sizeof(archetype)));
339 
340  sum_alloc += i;
341  sum_used += i;
342 
344  "[fixed]%4d animations: %8d",
345  anims, i = (anims*sizeof(uint16_t)));
346 
347  sum_alloc += i;
348  sum_used += i;
349 
351  "[fixed]%4zu treasurelists %8d",
353 
354  sum_alloc += i;
355  sum_used += i;
356 
358  "[fixed]%4ld treasures %8d",
360 
361  sum_alloc += i;
362  sum_used += i;
363 
365  "[fixed]%4ld artifacts %8d",
366  nrofartifacts, i = (nrofartifacts*sizeof(artifact)));
367 
368  sum_alloc += i;
369  sum_used += i;
370 
372  "[fixed]%4ld artifacts strngs %8d",
373  nrofallowedstr, i = (nrofallowedstr*sizeof(linked_char)));
374 
375  sum_alloc += i;
376  sum_used += i;
377 
379  "[fixed]%4d artifactlists %8d",
380  alnr, i = (alnr*sizeof(artifactlist)));
381 
382  sum_alloc += i;
383  sum_used += i;
384 
386  "[fixed]Total space allocated:%8d",
387  sum_alloc);
388 
390  "[fixed]Total space used: %8d",
391  sum_used);
392 }
393 
405 static void current_region_info(object *op) {
406  /*
407  * Ok I /suppose/ I should write a separate function for this, but it isn't
408  * going to be /that/ slow, and won't get called much
409  */
411 
412  /* This should only be possible if regions are not operating on this server. */
413  if (!r)
414  return;
415 
417  "You are in %s.\n%s",
419 }
420 
427 static void current_map_info(object *op) {
428  mapstruct *m = op->map;
429 
430  if (!m)
431  return;
432 
434  "%s (%s) in %s",
436 
437  if (QUERY_FLAG(op, FLAG_WIZ)) {
439  "players:%d difficulty:%d size:%dx%d start:%dx%d timeout %d reset_group: %s",
440  m->players, m->difficulty,
441  MAP_WIDTH(m), MAP_HEIGHT(m),
442  MAP_ENTER_X(m), MAP_ENTER_Y(m),
443  MAP_TIMEOUT(m), m->reset_group ? m->reset_group : "(none)");
444  }
445  if (m->msg)
447 }
448 
449 #ifdef DEBUG_MALLOC_LEVEL
450 
458 void command_malloc_verify(object *op, char *parms) {
459  extern int malloc_verify(void);
460 
461  if (!malloc_verify())
463  "Heap is corrupted.");
464  else
466  "Heap checks out OK.");
467 
468  return 1;
469 }
470 #endif
471 
482 void command_whereabouts(object *op, const char *params) {
483  player *pl;
484  (void)params;
485 
486  /*
487  * reset the counter on the region, then use it to store the number of
488  * players there.
489  * I don't know how thread-safe this would be, I suspect not very....
490  */
491  for (auto reg : all_regions) {
492  reg->counter = 0;
493  }
494  for (pl = first_player; pl != NULL; pl = pl->next)
495  if (pl->ob->map != NULL)
496  get_region_by_map(pl->ob->map)->counter++;
497 
498  /* we only want to print out by places with a 'longname' field...*/
499  for (auto reg : all_regions) {
500  if (reg->longname == NULL && reg->counter > 0) {
501  if (reg->parent != NULL) {
502  reg->parent->counter += reg->counter;
503  reg->counter = 0;
504  } else /*uh oh, we shouldn't be here. */
505  LOG(llevError, "command_whereabouts() Region %s with no longname has no parent\n", reg->name);
506  }
507  }
509  "In the world currently there are:");
510 
511  for (auto reg : all_regions)
512  if (reg->counter > 0) {
514  "%u players in %s",
515  reg->counter, get_region_longname(reg));
516  }
517 }
518 
520 struct chars_names {
523 };
524 
534 static int name_cmp(const chars_names *c1, const chars_names *c2) {
535  return strcasecmp(c1->namebuf, c2->namebuf);
536 }
537 
548 void list_players(object *op, region *reg, partylist *party) {
549  player *pl;
550  uint16_t i;
551  char *format;
552  int num_players = 0, num_wiz = 0, num_afk = 0, num_bot = 0;
553  chars_names *chars = NULL;
554 
555  if (op == NULL || QUERY_FLAG(op, FLAG_WIZ))
556  format = settings.who_wiz_format;
557  else
558  format = settings.who_format;
559 
560  for (pl = first_player; pl != NULL; pl = pl->next) {
561  if (pl->ob->map == NULL)
562  continue;
563  if (pl->hidden && !QUERY_FLAG(op, FLAG_WIZ))
564  continue;
565 
566  if (reg && !region_is_child_of_region(get_region_by_map(pl->ob->map), reg))
567  continue;
568  if (party && pl->party != party)
569  continue;
570 
571  if (pl->state == ST_PLAYING || pl->state == ST_GET_PARTY_PASSWORD) {
572  num_players++;
573  chars = (chars_names *)realloc(chars, num_players*sizeof(chars_names));
574  if (chars == NULL) {
576  "who failed - out of memory!");
577  return;
578  }
579  sprintf(chars[num_players-1].namebuf, "%s", pl->ob->name);
580  chars[num_players-1].login_order = num_players;
581 
582  /* Check for WIZ's & AFK's*/
583  if (QUERY_FLAG(pl->ob, FLAG_WIZ))
584  num_wiz++;
585 
586  if (QUERY_FLAG(pl->ob, FLAG_AFK))
587  num_afk++;
588 
589  if (pl->socket->is_bot)
590  num_bot++;
591  }
592  }
593  if (first_player != (player *)NULL) {
594  if (reg == NULL && party == NULL)
596  "Total Players (%d) -- WIZ(%d) AFK(%d) BOT(%d)",
597  num_players, num_wiz, num_afk, num_bot);
598  else if (party == NULL)
600  "Total Players in %s (%d) -- WIZ(%d) AFK(%d) BOT(%d)",
601  reg->longname ? reg->longname : reg->name, num_players, num_wiz, num_afk, num_bot);
602  else
604  "Total Players in party %s (%d) -- WIZ(%d) AFK(%d) BOT(%d)",
605  party->partyname, num_players, num_wiz, num_afk, num_bot);
606  }
607  qsort(chars, num_players, sizeof(chars_names), (int (*)(const void *, const void *))name_cmp);
608  for (i = 0; i < num_players; i++)
609  display_who_entry(op, find_player(chars[i].namebuf), format);
610  free(chars);
611 }
612 
621 void command_who(object *op, const char *params) {
622  region *reg;
623 
624  reg = get_region_from_string(params);
625  list_players(op, reg, NULL);
626 }
627 
638 static void display_who_entry(object *op, player *pl, const char *format) {
639  char tmpbuf[MAX_BUF];
640  char outbuf[MAX_BUF];
641  size_t i;
642 
643  strcpy(outbuf, "[fixed]");
644 
645  if (pl == NULL) {
646  LOG(llevError, "display_who_entry(): I was passed a null player\n");
647  return;
648  }
649  for (i = 0; i <= strlen(format); i++) {
650  if (format[i] == '%') {
651  i++;
652  get_who_escape_code_value(tmpbuf, sizeof(tmpbuf), format[i], pl);
653  strcat(outbuf, tmpbuf);
654  } else if (format[i] == '_') {
655  strcat(outbuf, " "); /* allow '_' to be used in place of spaces */
656  } else {
657  snprintf(tmpbuf, sizeof(tmpbuf), "%c", format[i]);
658  strcat(outbuf, tmpbuf);
659  }
660  }
662 }
663 
694 static void get_who_escape_code_value(char *return_val, int size, const char letter, player *pl) {
695  switch (letter) {
696  case 'N':
697  strlcpy(return_val, pl->ob->name, size);
698  break;
699 
700  case 't':
701  player_get_title(pl, return_val, size);
702  break;
703 
704  case 'c':
705  snprintf(return_val, size, "%u", pl->ob->count);
706  break;
707 
708  case 'n':
709  snprintf(return_val, size, "\n");
710  break;
711 
712  case 'h':
713  strlcpy(return_val, pl->peaceful ? "" : " <Hostile>", size);
714  break;
715 
716  case 'l':
717  snprintf(return_val, size, "%d", pl->ob->level);
718  break;
719 
720  case 'd':
721  strlcpy(return_val, (QUERY_FLAG(pl->ob, FLAG_WIZ) ? " <WIZ>" : ""), size);
722  break;
723 
724  case 'a':
725  strlcpy(return_val, (QUERY_FLAG(pl->ob, FLAG_AFK) ? " <AFK>" : ""), size);
726  break;
727 
728  case 'b':
729  strlcpy(return_val, (pl->socket->is_bot == 1) ? " <BOT>" : "", size);
730  break;
731 
732  case 'm':
733  strlcpy(return_val, pl->ob->map->path, size);
734  break;
735 
736  case 'M':
737  strlcpy(return_val, pl->ob->map->name ? pl->ob->map->name : "Untitled", size);
738  break;
739 
740  case 'r':
741  strlcpy(return_val, get_name_of_region_for_map(pl->ob->map), size);
742  break;
743 
744  case 'R':
745  strlcpy(return_val, get_region_longname(get_region_by_map(pl->ob->map)), size);
746  break;
747 
748  case 'i':
749  strlcpy(return_val, pl->socket->host, size);
750  break;
751 
752  case '%':
753  snprintf(return_val, size, "%%");
754  break;
755 
756  case '_':
757  snprintf(return_val, size, "_");
758  break;
759 
760  default:
761  return_val[0] = '\0';
762  }
763 }
764 
773 void command_afk(object *op, const char *params) {
774  (void)params;
775  if (QUERY_FLAG(op, FLAG_AFK)) {
776  CLEAR_FLAG(op, FLAG_AFK);
778  "You are no longer AFK");
779  } else {
780  SET_FLAG(op, FLAG_AFK);
782  "You are now AFK");
783  }
784 }
785 
794 void command_malloc(object *op, const char *params) {
795  (void)params;
796  malloc_info(op);
797 }
798 
807 void command_mapinfo(object *op, const char *params) {
808  (void)params;
809  current_map_info(op);
810 }
811 
820 void command_whereami(object *op, const char *params) {
821  (void)params;
823 }
824 
833 void command_maps(object *op, const char *params) {
834  map_info(op, params);
835 }
836 
845 void command_strings(object *op, const char *params) {
846  char stats[HUGE_BUF];
847  (void)params;
848 
849  ss_dump_statistics(stats, sizeof(stats));
851  "[fixed]%s\n",
852  stats);
853 
855  ss_dump_table(SS_DUMP_TOTALS, stats, sizeof(stats)));
856 }
857 
866 void command_time(object *op, const char *params) {
867  (void)params;
868  time_info(op);
869 }
870 
879 void command_hiscore(object *op, const char *params) {
880  hiscore_display(op, op == NULL ? 9999 : 50, params);
881 }
882 
891 void command_debug(object *op, const char *params) {
892  int i;
893 
894  if (*params == '\0' || !sscanf(params, "%d", &i)) {
896  "Global debug level is %d.",
897  settings.debug);
898  return;
899  }
900  settings.debug = (enum LogLevel)FABS(i);
902  "Debug level set to %d.",
903  i);
904 }
905 
906 
915 void command_wizpass(object *op, const char *params) {
916  int i;
917 
918  if (!op)
919  return;
920 
921  if (*params == '\0')
922  i = (QUERY_FLAG(op, FLAG_WIZPASS)) ? 0 : 1;
923  else
924  i = onoff_value(params);
925 
926  if (i) {
928  "You will now walk through walls.");
929  SET_FLAG(op, FLAG_WIZPASS);
930  } else {
932  "You will now be stopped by walls.");
934  }
935 }
936 
945 void command_wizcast(object *op, const char *params) {
946  int i;
947 
948  if (!op)
949  return;
950 
951  if (*params == '\0')
952  i = (QUERY_FLAG(op, FLAG_WIZCAST)) ? 0 : 1;
953  else
954  i = onoff_value(params);
955 
956  if (i) {
958  "You can now cast spells anywhere.");
959  SET_FLAG(op, FLAG_WIZCAST);
960  } else {
962  "You now cannot cast spells in no-magic areas.");
964  }
965 }
966 
975 void command_dumpallobjects(object *op, const char *params) {
976  (void)op;
977  (void)params;
978  object_dump_all();
979 }
980 
989 void command_dumpfriendlyobjects(object *op, const char *params) {
990  (void)op;
991  (void)params;
993 }
994 
1003 void command_dumpallarchetypes(object *op, const char *params) {
1004  (void)op;
1005  (void)params;
1007 }
1008 
1017 void command_ssdumptable(object *op, const char *params) {
1018  (void)op;
1019  (void)params;
1020  ss_dump_table(SS_DUMP_TABLE, NULL, 0);
1021 }
1022 
1031 void command_dumpmap(object *op, const char *params) {
1032  (void)params;
1033  if (op)
1034  dump_map(op->map);
1035 }
1036 
1045 void command_dumpallmaps(object *op, const char *params) {
1046  (void)op;
1047  (void)params;
1048  dump_all_maps();
1049 }
1050 
1059 void command_printlos(object *op, const char *params) {
1060  (void)params;
1061  if (op)
1062  print_los(op);
1063 }
1064 
1065 
1074 void command_version(object *op, const char *params) {
1075  (void)params;
1077  MSG_TYPE_ADMIN_VERSION, "Crossfire " FULL_VERSION);
1078 }
1079 
1088 void command_listen(object *op, const char *params) {
1089  int i;
1090 
1091  if (*params == '\0' || !sscanf(params, "%d", &i)) {
1093  "Set listen to what (presently %d)?",
1094  op->contr->listening);
1095  return;
1096  }
1097  if (i < 0) {
1099  "Verbose level should be positive.");
1100  return;
1101  }
1102  op->contr->listening = (char)i;
1104  "Your verbose level is now %d.",
1105  i);
1106 }
1107 
1119 void command_statistics(object *pl, const char *params) {
1120  char buf[MAX_BUF];
1121  uint32_t hours, minutes;
1122  uint64_t seconds; /* 64 bit to prevent overflows an intermediate results */
1123  (void)params;
1124 
1125  if (!pl->contr)
1126  return;
1127  safe_strncpy(buf, i18n(pl, "[fixed] Experience: %"), sizeof(buf));
1128  strcat(buf, FMT64);
1130  buf,
1131  pl->stats.exp);
1132  safe_strncpy(buf, i18n(pl, "[fixed] Next Level: %"), sizeof(buf));
1133  strcat(buf, FMT64);
1135  buf,
1136  level_exp(pl->level+1, pl->expmul));
1137 
1139  "[fixed]\nStat Nat/Real/Max");
1140 
1142  "[fixed]Str %2d/ %3d/%3d",
1143  pl->contr->orig_stats.Str, pl->stats.Str, 20+pl->arch->clone.stats.Str);
1145  "[fixed]Dex %2d/ %3d/%3d",
1146  pl->contr->orig_stats.Dex, pl->stats.Dex, 20+pl->arch->clone.stats.Dex);
1148  "[fixed]Con %2d/ %3d/%3d",
1149  pl->contr->orig_stats.Con, pl->stats.Con, 20+pl->arch->clone.stats.Con);
1151  "[fixed]Int %2d/ %3d/%3d",
1152  pl->contr->orig_stats.Int, pl->stats.Int, 20+pl->arch->clone.stats.Int);
1154  "[fixed]Wis %2d/ %3d/%3d",
1155  pl->contr->orig_stats.Wis, pl->stats.Wis, 20+pl->arch->clone.stats.Wis);
1157  "[fixed]Pow %2d/ %3d/%3d",
1158  pl->contr->orig_stats.Pow, pl->stats.Pow, 20+pl->arch->clone.stats.Pow);
1160  "[fixed]Cha %2d/ %3d/%3d",
1161  pl->contr->orig_stats.Cha, pl->stats.Cha, 20+pl->arch->clone.stats.Cha);
1163  "\nAttack Mode: %s",
1164  i18n(pl, pl->contr->peaceful ? "Peaceful" : "Hostile"));
1168  float weap_speed = pl->weapon_speed; // This is the number of attacks per tick.
1169  if (weap_speed < 0.0f)
1170  weap_speed = 0.0f;
1171  if (weap_speed > 1.0f)
1172  weap_speed = 1.0f;
1173  // We will initially calculate the damage if every attack you perform hits.
1174  // This will serve as a baseline for future calculations
1175  float dps = (1000000.0f / tick_duration) * weap_speed * pl->stats.dam;
1176  // TODO: Account for opposing AC in calculations, make some sort of table/chart.
1177  // Then we round the floating-point.
1179  "\n\nDam/Sec: %4d", (int)(dps + 0.5f));
1180 
1181  /* max_time is in microseconds - thus divide by 1000000.
1182  * Need 64 bit values, as otherwise ticks_played * max_time
1183  * can easily overflow.
1184  * Note the message displayed here isn't really
1185  * perfect, since if max_time has been changed since the player started,
1186  * the time estimates use the current value. But I'm presuming that
1187  * max_time won't change very often. MSW 2009-12-01
1188  */
1189  seconds = (uint64_t)pl->contr->ticks_played * (uint64_t)tick_duration / 1000000;
1190  minutes = (uint32_t)seconds / 60;
1191  hours = minutes / 60;
1192  minutes = minutes % 60;
1193 
1195  "You have played this character for %u ticks, which amounts "
1196  "to %d hours and %d minutes.",
1197  pl->contr->ticks_played, hours, minutes);
1198 
1199 
1200  /* Can't think of anything else to print right now */
1201 }
1202 
1211 void command_fix_me(object *op, const char *params) {
1212  (void)params;
1213  object_sum_weight(op);
1214  fix_object(op);
1215 }
1216 
1225 void command_players(object *op, const char *params) {
1226  char buf[MAX_BUF];
1227  char *t;
1228  DIR *dir;
1229  (void)params;
1230 
1231  snprintf(buf, sizeof(buf), "%s/%s/", settings.localdir, settings.playerdir);
1232  t = buf+strlen(buf);
1233  if ((dir = opendir(buf)) != NULL) {
1234  const struct dirent *entry;
1235 
1236  while ((entry = readdir(dir)) != NULL) {
1237  /* skip '.' , '..' */
1238  if (!((entry->d_name[0] == '.' && entry->d_name[1] == '\0')
1239  || (entry->d_name[0] == '.' && entry->d_name[1] == '.' && entry->d_name[2] == '\0'))) {
1240  struct stat st;
1241 
1242  strcpy(t, entry->d_name);
1243  if (stat(buf, &st) == 0) {
1244  /* This was not posix compatible
1245  * if ((st.st_mode & S_IFMT)==S_IFDIR) {
1246  */
1247  if (S_ISDIR(st.st_mode)) {
1248  struct tm *tm = localtime(&st.st_mtime);
1249 
1251  "[fixed]%s\t%04d %02d %02d %02d %02d %02d",
1252  entry->d_name,
1253  1900+tm->tm_year,
1254  1+tm->tm_mon,
1255  tm->tm_mday,
1256  tm->tm_hour,
1257  tm->tm_min,
1258  tm->tm_sec);
1259  }
1260  }
1261  }
1262  }
1263  closedir(dir);
1264  }
1265 }
1266 
1275 void command_applymode(object *op, const char *params) {
1276  unapplymode unapply = op->contr->unapply;
1277  static const char *const types[] = {
1278  "nochoice",
1279  "never",
1280  "always"
1281  };
1282 
1283  if (*params == '\0') {
1285  "applymode is set to %s",
1286  types[op->contr->unapply]);
1287  return;
1288  }
1289 
1290  if (!strcmp(params, "nochoice"))
1292  else if (!strcmp(params, "never"))
1293  op->contr->unapply = unapply_never;
1294  else if (!strcmp(params, "always"))
1295  op->contr->unapply = unapply_always;
1296  else {
1298  "applymode: Unknown options %s, valid options are nochoice, never, always",
1299  params);
1300  return;
1301  }
1303  "applymode%s set to %s",
1304  (unapply == op->contr->unapply ? "" : " now"),
1305  types[op->contr->unapply]);
1306 }
1307 
1316 void command_bowmode(object *op, const char *params) {
1317  bowtype_t oldtype = op->contr->bowtype;
1318  static const char *const types[] = {
1319  "normal",
1320  "threewide",
1321  "spreadshot",
1322  "firenorth",
1323  "firene",
1324  "fireeast",
1325  "firese",
1326  "firesouth",
1327  "firesw",
1328  "firewest",
1329  "firenw",
1330  "bestarrow"
1331  };
1332  int i, found;
1333 
1334  if (*params == '\0') {
1336  "bowmode is set to %s",
1337  types[op->contr->bowtype]);
1338  return;
1339  }
1340 
1341  for (i = 0, found = 0; i <= bow_bestarrow; i++) {
1342  if (!strcmp(params, types[i])) {
1343  found++;
1344  op->contr->bowtype = static_cast<bowtype_t>(i);
1345  break;
1346  }
1347  }
1348  if (!found) {
1350  stringbuffer_append_printf(buf, "bowmode: Unknown options %s, valid options are:", params);
1351  for (i = 0; i <= bow_bestarrow; i++) {
1352  stringbuffer_append_string(buf, " ");
1353  stringbuffer_append_string(buf, types[i]);
1354  if (i < bow_nw)
1355  stringbuffer_append_string(buf, ",");
1356  else
1357  stringbuffer_append_string(buf, ".");
1358  }
1359  char *result = stringbuffer_finish(buf);
1361  free(result);
1362  return;
1363  }
1365  "bowmode%s set to %s",
1366  (oldtype == op->contr->bowtype ? "" : " now"),
1367  types[op->contr->bowtype]);
1368  return;
1369 }
1370 
1379 void command_unarmed_skill(object *op, const char *params) {
1380  object *skill;
1381  size_t i;
1382 
1383  if (*params == '\0') {
1385  "unarmed skill is set to %s",
1386  op->contr->unarmed_skill ? op->contr->unarmed_skill: "nothing");
1387  return;
1388  }
1389 
1390  /* find_skill_by_name() will ready any skill tools - which
1391  * is OK for us because no unarmed skills require skill tools,
1392  * but this could be an issue if you reuse this code for other skills.
1393  */
1394  skill = find_skill_by_name(op, params);
1395 
1396  if (!skill) {
1398  "You do not know any such skill called %s",
1399  params);
1400  return;
1401  }
1402  for (i = 0; i < sizeof(unarmed_skills); i++)
1403  if (skill->subtype == unarmed_skills[i])
1404  break;
1405  if (i == sizeof(unarmed_skills)) {
1407  "%s is not an unarmed skill!",
1408  skill->name);
1409  return;
1410 
1411  }
1412 
1413  if (op->contr->unarmed_skill)
1415 
1416  /* Taking actual skill name is better than taking params,
1417  * as params could be something more than an exact skill name.
1418  */
1419  op->contr->unarmed_skill = add_string(skill->name);
1420 
1422  "unarmed skill is now set to %s",
1423  op->contr->unarmed_skill);
1424 }
1425 
1426 
1435 void command_petmode(object *op, const char *params) {
1436  petmode_t oldtype = op->contr->petmode;
1437  static const char *const types[] = {
1438  "normal",
1439  "sad",
1440  "defend",
1441  "arena"
1442  };
1443 
1444  if (*params == '\0') {
1446  "petmode is set to %s",
1447  types[op->contr->petmode]);
1448  return;
1449  }
1450 
1451  if (!strcmp(params, "normal"))
1452  op->contr->petmode = pet_normal;
1453  else if (!strcmp(params, "sad"))
1454  op->contr->petmode = pet_sad;
1455  else if (!strcmp(params, "defend"))
1456  op->contr->petmode = pet_defend;
1457  else if (!strcmp(params, "arena"))
1458  op->contr->petmode = pet_arena;
1459  else {
1461  "petmode: Unknown options %s, valid options are normal, sad (seek and destroy), defend, arena",
1462  params);
1463  return;
1464  }
1466  "petmode%s set to %s",
1467  (oldtype == op->contr->petmode ? "" : " now"),
1468  types[op->contr->petmode]);
1469 }
1470 
1479 void command_showpets(object *op, const char *params) {
1480  objectlink *obl, *list;
1481  int counter = 0, target = 0;
1482  int have_shown_pet = 0;
1483  if (*params != '\0')
1484  target = atoi(params);
1485 
1486  list = get_friends_of(op);
1487 
1488  for (obl = list; obl != NULL; obl = obl->next) {
1489  object *ob = obl->ob;
1490 
1491  if (target == 0) {
1492  if (counter == 0)
1494  "Pets:");
1496  "%d %s - level %d",
1497  ++counter, ob->name, ob->level);
1498  } else if (!have_shown_pet && ++counter == target) {
1500  "[fixed]level %d %s",
1501  ob->level, ob->name);
1503  "[fixed]%d/%d HP, %d/%d SP",
1504  ob->stats.hp, ob->stats.maxhp, ob->stats.sp, ob->stats.maxsp);
1505 
1506  /* this is not a nice way to do this, it should be made to be more like the statistics command */
1508  "[fixed]Str %d",
1509  ob->stats.Str);
1511  "[fixed]Dex %d",
1512  ob->stats.Dex);
1514  "[fixed]Con %d",
1515  ob->stats.Con);
1517  "[fixed]Int %d",
1518  ob->stats.Int);
1520  "[fixed]Wis %d",
1521  ob->stats.Wis);
1523  "[fixed]Cha %d",
1524  ob->stats.Cha);
1526  "[fixed]Pow %d",
1527  ob->stats.Pow);
1529  "[fixed]wc %d damage %d ac %d",
1530  ob->stats.wc, ob->stats.dam, ob->stats.ac);
1531  have_shown_pet = 1;
1532  }
1533  }
1534  if (list) {
1535  free_objectlink(list);
1536  }
1537 
1538  if (counter == 0)
1540  "You have no pets.");
1541  else if (target != 0 && have_shown_pet == 0)
1543  "No such pet.");
1544 }
1545 
1554 void command_usekeys(object *op, const char *params) {
1555  usekeytype oldtype = op->contr->usekeys;
1556  static const char *const types[] = {
1557  "inventory",
1558  "keyrings",
1559  "containers"
1560  };
1561 
1562  if (*params == '\0') {
1564  "usekeys is set to %s",
1565  types[op->contr->usekeys]);
1566  return;
1567  }
1568 
1569  if (!strcmp(params, "inventory"))
1570  op->contr->usekeys = key_inventory;
1571  else if (!strcmp(params, "keyrings"))
1572  op->contr->usekeys = keyrings;
1573  else if (!strcmp(params, "containers"))
1574  op->contr->usekeys = containers;
1575  else {
1577  "usekeys: Unknown option %s, valid options are inventory, keyrings, containers",
1578  params);
1579  return;
1580  }
1582  "usekeys%s set to %s",
1583  (oldtype == op->contr->usekeys ? "" : " now"),
1584  types[op->contr->usekeys]);
1585 }
1586 
1595 void command_resistances(object *op, const char *params) {
1596  int i;
1597  (void)params;
1598  if (!op)
1599  return;
1600 
1601  for (i = 0; i < NROFATTACKS; i++) {
1602  if (i == ATNR_INTERNAL)
1603  continue;
1604 
1606  "[fixed]%-20s %+5d",
1607  attacktype_desc[i], op->resist[i]);
1608  }
1609 
1610  /* If dragon player, let's display natural resistances */
1611  if (is_dragon_pl(op)) {
1612  int attack;
1613  object *tmp;
1614 
1615  tmp = object_find_by_type_and_arch_name(op, FORCE, "dragon_skin_force");
1616  if (tmp != NULL) {
1618  "\nNatural skin resistances:");
1619 
1620  for (attack = 0; attack < NROFATTACKS; attack++) {
1621  if (atnr_is_dragon_enabled(attack)) {
1623  "%s: %d",
1624  change_resist_msg[attack], tmp->resist[attack]);
1625  }
1626  }
1627  }
1628  }
1629 }
1630 
1641 static void help_topics(object *op, int what) {
1642  DIR *dirp;
1643  struct dirent *de;
1644  char filename[MAX_BUF], line[HUGE_BUF];
1645  char suffix[MAX_BUF];
1646  int namelen;
1647  const char *language;
1648 
1649  language = i18n_get_language_code(op->contr->language);
1650  snprintf(suffix, sizeof(suffix), ".%s", language);
1651 
1652  switch (what) {
1653  case 1:
1654  snprintf(filename, sizeof(filename), "%s/wizhelp", settings.datadir);
1656  " Wiz commands:");
1657  break;
1658 
1659  case 3:
1660  snprintf(filename, sizeof(filename), "%s/mischelp", settings.datadir);
1662  " Misc help:");
1663  break;
1664 
1665  default:
1666  snprintf(filename, sizeof(filename), "%s/help", settings.datadir);
1668  " Commands:");
1669  break;
1670  }
1671  if (!(dirp = opendir(filename)))
1672  return;
1673 
1674  line[0] = '\0';
1675  for (de = readdir(dirp); de; de = readdir(dirp)) {
1676  namelen = NAMLEN(de);
1677 
1678  if (namelen <= 2
1679  && *de->d_name == '.'
1680  && (namelen == 1 || de->d_name[1] == '.'))
1681  continue;
1682  if (strstr(de->d_name, suffix)) {
1683  strcat(line, strtok(de->d_name, "."));
1684  strcat(line, " ");
1685  }
1686  }
1688  line);
1689  closedir(dirp);
1690 }
1691 
1701 static int find_help_file_in(const char *dir, const char *name, const char *language, char *path, int length) {
1702  struct stat st;
1703 
1704  snprintf(path, length, "%s/%s/%s.%s", settings.datadir, dir, name, language);
1705  if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) {
1706  return 1;
1707  }
1708  return 0;
1709 }
1710 
1724 static int find_help_file(const char *name, const char *language, int wiz, char *path, int length) {
1725  if (wiz) {
1726  if (find_help_file_in("wizhelp", name, language, path, length))
1727  return 1;
1728  if (strcmp(language, "en") && find_help_file_in("wizhelp", name, "en", path, length))
1729  return 1;
1730  }
1731 
1732  if (find_help_file_in("help", name, language, path, length))
1733  return 1;
1734  if (strcmp(language, "en") && find_help_file_in("help", name, "en", path, length))
1735  return 1;
1736 
1737  return 0;
1738 }
1739 
1747 static void display_help_file(object *op, const char *filename) {
1748  BufferReader *br;
1749  const char *line;
1750 
1751  if ((br = bufferreader_init_from_file(NULL, filename, "Cannot open help file %s: %s\n", llevError)) == NULL) {
1752  return;
1753  }
1754 
1755  while ((line = bufferreader_next_line(br))) {
1757  }
1758 
1760 }
1761 
1770 void command_help(object *op, const char *params) {
1771  char filename[MAX_BUF];
1772  const char *language;
1773 
1774  /*
1775  * Main help page?
1776  */
1777  if (*params == '\0') {
1778  snprintf(filename, sizeof(filename), "%s/def_help", settings.datadir);
1779  display_help_file(op, filename);
1780  return;
1781  }
1782 
1783  /*
1784  * Topics list
1785  */
1786  if (!strcmp(params, "topics")) {
1787  help_topics(op, 3);
1788  help_topics(op, 0);
1789  if (QUERY_FLAG(op, FLAG_WIZ))
1790  help_topics(op, 1);
1791  return;
1792  }
1793 
1794  /*
1795  * Commands list
1796  */
1797  if (!strcmp(params, "commands")) {
1798  command_list(op, QUERY_FLAG(op, FLAG_WIZ));
1799  return;
1800  }
1801 
1802  /*
1803  * User wants info about command
1804  */
1805  if (strchr(params, '.') || strchr(params, ' ') || strchr(params, '/')) {
1807  "Illegal characters in '%s'",
1808  params);
1809  return;
1810  }
1811 
1812  language = i18n_get_language_code(op->contr->language);
1813 
1814  if (!find_help_file(params, language, QUERY_FLAG(op, FLAG_WIZ), filename, sizeof(filename))) {
1816  "No help available on '%s'",
1817  params);
1818  return;
1819  }
1820 
1821  /*
1822  * Found that. Just cat it to screen.
1823  */
1824  display_help_file(op, filename);
1825 }
1826 
1837 static int onoff_value(const char *line) {
1838  int i;
1839 
1840  if (sscanf(line, "%d", &i))
1841  return (i != 0);
1842 
1843  switch (line[0]) {
1844  case 'o':
1845  switch (line[1]) {
1846  case 'n':
1847  return 1; /* on */
1848  default:
1849  return 0; /* o[ff] */
1850  }
1851 
1852  case 'y': /* y[es] */
1853  case 'k': /* k[ylla] */
1854  case 's':
1855  case 'd':
1856  return 1;
1857 
1858  case 'n': /* n[o] */
1859  case 'e': /* e[i] */
1860  case 'u':
1861  default:
1862  return 0;
1863  }
1864 }
1865 
1871 void command_quit(object* op, const char* params) {
1872  (void)params;
1873  draw_ext_info(
1875  "To leave the game, sleep in (apply) a bed to reality. To "
1876  "permenantly delete your character, use the 'delete' command.");
1877 }
1878 
1887 void command_delete(object *op, const char *params) {
1888  (void)params;
1889  if (QUERY_FLAG(op, FLAG_WIZ)) {
1890  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_ADMIN_DM, "Can't quit when in DM mode.");
1891  return;
1892  }
1893 
1895  i18n(op, "Quitting will delete your character.\nAre you sure you want to delete your character (y/n):"));
1896 
1898 }
1899 
1908 void command_sound(object *op, const char *params) {
1909  (void)params;
1910  if (!(op->contr->socket->sound&SND_MUTE)) {
1911  op->contr->socket->sound = op->contr->socket->sound|SND_MUTE;
1913  "Sounds are turned off.");
1914  } else {
1915  op->contr->socket->sound = op->contr->socket->sound&~SND_MUTE;
1917  "The sounds are enabled.");
1918  }
1919  return;
1920 }
1921 
1933 void receive_player_name(object *op, const char *name) {
1934  if (!check_name(op->contr, name)) {
1935  get_name(op);
1936  return;
1937  }
1938  FREE_AND_COPY(op->name, name);
1939  FREE_AND_COPY(op->name_pl, name);
1941  op->contr->name_changed = 1;
1942  get_password(op);
1943 }
1944 
1953 void receive_player_password(object *op, const char *password) {
1954  unsigned int pwd_len = strlen(password);
1955 
1956  if (pwd_len == 0 || pwd_len > 16) {
1957  if (op->contr->state == ST_CHANGE_PASSWORD_OLD
1959  || op->contr->state == ST_CHANGE_PASSWORD_CONFIRM) {
1961  "Password changed cancelled.");
1963  } else
1964  get_name(op);
1965  return;
1966  }
1967  /* To hide the password better */
1968  /* With currently clients, not sure if this is really the case - MSW */
1970 
1971  if (checkbanned(op->name, op->contr->socket->host)) {
1972  LOG(llevInfo, "Banned player tried to add: [%s@%s]\n", op->name, op->contr->socket->host);
1974  "You are not allowed to play.");
1975  get_name(op);
1976  return;
1977  }
1978 
1979  if (op->contr->state == ST_CONFIRM_PASSWORD) {
1980  if (!check_password(password, op->contr->password)) {
1982  "The passwords did not match.");
1983  get_name(op);
1984  return;
1985  }
1986  LOG(llevInfo, "LOGIN: New player named %s from ip %s\n", op->name, op->contr->socket->host);
1987  display_motd(op);
1989  "\nWelcome, Brave New Warrior!\n");
1990  roll_again(op);
1992  return;
1993  }
1994 
1995  if (op->contr->state == ST_CHANGE_PASSWORD_OLD) {
1996  if (!check_password(password, op->contr->password)) {
1998  "You entered the wrong current password.");
2000  } else {
2001  send_query(op->contr->socket, CS_QUERY_HIDEINPUT, i18n(op, "Please enter your new password, or blank to cancel:"));
2003  }
2004  return;
2005  }
2006 
2007  if (op->contr->state == ST_CHANGE_PASSWORD_NEW) {
2008  safe_strncpy(op->contr->new_password, newhash(password),
2009  sizeof(op->contr->new_password));
2011  i18n(op, "Please confirm your new password, or blank to cancel:"));
2013  return;
2014  }
2015 
2016  if (op->contr->state == ST_CHANGE_PASSWORD_CONFIRM) {
2017  if (!check_password(password, op->contr->new_password)) {
2019  "The new passwords don't match!");
2020  } else {
2022  "Password changed.");
2023  strncpy(op->contr->password, op->contr->new_password, 13);
2024  }
2026  return;
2027  }
2028 
2029  safe_strncpy(op->contr->password, newhash(password),
2030  sizeof(op->contr->password));
2032  check_login(op, password);
2033 }
2034 
2045 void command_title(object *op, const char *params) {
2046  char buf[HUGE_BUF];
2047 
2048  if (settings.set_title == FALSE) {
2050  "You cannot change your title.");
2051  return;
2052  }
2053 
2054  /* dragon players cannot change titles */
2055  if (is_dragon_pl(op)) {
2057  "Dragons cannot change titles.");
2058  return;
2059  }
2060 
2061  if (*params == '\0') {
2062  char tmp[MAX_BUF];
2063 
2064  player_get_title(op->contr, tmp, sizeof(tmp));
2065  snprintf(buf, sizeof(buf), "Your title is '%s'.", tmp);
2067  return;
2068  }
2069  if (strcmp(params, "clear") == 0 || strcmp(params, "default") == 0) {
2070  if (!player_has_own_title(op->contr))
2072  "Your title is the default title.");
2073  else
2075  "Title set to default.");
2076  player_set_own_title(op->contr, "");
2077  return;
2078  }
2079 
2080  if ((int)strlen(params) >= MAX_NAME) {
2082  "Title too long.");
2083  return;
2084  }
2085  player_set_own_title(op->contr, params);
2086 }
2087 
2096 void command_save(object *op, const char *params) {
2097  (void)params;
2098  if (get_map_flags(op->map, NULL, op->x, op->y, NULL, NULL)&P_NO_CLERIC) {
2100  "You can not save on unholy ground.");
2101  } else if (!op->stats.exp) {
2103  "You don't deserve to save yet.");
2104  } else {
2105  if (save_player(op, 1))
2107  "You have been saved.");
2108  else
2110  "SAVE FAILED!");
2111  }
2112 }
2113 
2122 void command_peaceful(object *op, const char *params) {
2123  (void)params;
2124  if ((op->contr->peaceful = !op->contr->peaceful))
2126  "You will not attack other players.");
2127  else
2129  "You will attack other players.");
2130 }
2131 
2140 void command_wimpy(object *op, const char *params) {
2141  int i;
2142 
2143  if (*params == '\0' || !sscanf(params, "%d", &i)) {
2145  "Your current wimpy level is %d.",
2146  op->run_away);
2147  return;
2148  }
2149 
2150  if (i < 0 || i > 100) {
2152  "Wimpy level must be between 1 and 100.");
2153  return;
2154  }
2155 
2157  "Your new wimpy level is %d.",
2158  i);
2159  op->run_away = i;
2160 }
2161 
2170 void command_brace(object *op, const char *params) {
2171  if (*params == '\0')
2172  op->contr->braced = !op->contr->braced;
2173  else
2174  op->contr->braced = onoff_value(params);
2175 
2176  if (op->contr->braced)
2178  "You are braced.");
2179  else
2181  "Not braced.");
2182 
2183  fix_object(op);
2184 }
2185 
2194 void command_kill_pets(object *op, const char *params) {
2195  if (*params == '\0') {
2196  pets_terminate_all(op);
2198  "Your pets have been killed.");
2199  } else {
2200  objectlink *obl, *list = get_friends_of(op);
2201  int counter = 0, removecount = 0;
2202  int target = atoi(params);
2203 
2204  for (obl = list; obl != NULL; obl = obl->next) {
2205  object *ob = obl->ob;
2206  if (object_get_owner(ob) == op) {
2207  if (++counter == target || (target == 0 && !strcasecmp(ob->name, params))) {
2208  pets_terminate(ob);
2209  removecount++;
2210  }
2211  }
2212  }
2213  if (list) {
2214  free_objectlink(list);
2215  }
2216  if (removecount != 0)
2218  "Killed %d pets.",
2219  removecount);
2220  else
2222  "Couldn't find any suitable pets to kill.");
2223  }
2224 }
2225 
2234 void command_passwd(object *pl, const char *params) {
2235  (void)params;
2236  /* If old client, this is the way you change your password. */
2237  if (pl->contr->socket->login_method < 1){
2238  send_query(pl->contr->socket, CS_QUERY_HIDEINPUT, i18n(pl, "Password change.\nPlease enter your current password, or empty string to cancel."));
2239 
2241  }
2242  /* If new client (login_method = 2) or jxclient (login_method = 1), changing the password does nothing anyway, so error out */
2243  else{
2245  "passwd is maintained for older clients that do not support the account system. Please use the 'Password' button in your character selection screen to change your password.");
2246  }
2247 }
2248 
2258 void do_harvest(object *pl, int dir, object *skill) {
2259  int16_t x, y;
2260  int level, exp, check_exhaust = 0;
2261  const int max_harvest = 10;
2262  object *found[max_harvest]; /* Found items that can be harvested. */
2263  mapstruct *map;
2264  object *item, *inv, *harvested;
2265  sstring trace, ttool, tspeed, race, tool, slevel, sexp;
2266  float speed;
2267 
2268  x = pl->x+freearr_x[dir];
2269  y = pl->y+freearr_y[dir];
2270  map = pl->map;
2271 
2272  if (!IS_PLAYER(pl))
2273  return;
2274 
2275  if (!map)
2276  return;
2277 
2278  if (get_map_flags(map, &map, x, y, &x, &y)&P_OUT_OF_MAP) {
2279  draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, i18n(pl, "You cannot %s here."), skill->slaying);
2280  return;
2281  }
2282 
2283  if (!pl->chosen_skill || pl->chosen_skill->skill != skill->skill)
2284  return;
2285 
2286  trace = object_get_value(pl->chosen_skill, "harvest_race");
2287  ttool = object_get_value(pl->chosen_skill, "harvest_tool");
2288  tspeed = object_get_value(pl->chosen_skill, "harvest_speed");
2289  if (!trace || strcmp(trace, "") == 0 || !ttool || strcmp(ttool, "") == 0 || !tspeed || strcmp(tspeed, "") == 0) {
2290  draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, i18n(pl, "You start to %s, but change your mind."), skill->slaying);
2291  LOG(llevError, "do_harvest: tool %s without harvest_[race|tool|speed]\n", pl->chosen_skill->name);
2292  return;
2293  }
2294 
2295  int count = 0; // number of harvested items
2296  FOR_MAP_PREPARE(map, x, y, item) {
2297  if (!LOOK_OBJ(item))
2298  continue;
2299  // do not skip floors, because you can harvest from mountains/lakes
2314  const char* harvestitems;
2315  if ((harvestitems = object_get_value(item, "harvestitems"))) {
2316  struct treasurelist* t = find_treasurelist(harvestitems);
2317  if (t) {
2318  create_treasure(t, item, 0, map->difficulty, 0);
2319  }
2320  object_set_value(item, "harvestitems", NULL, false);
2321  }
2322 
2323  FOR_INV_PREPARE(item, inv) {
2324  if (object_value_set(inv, "harvestable") == false)
2325  continue;
2326  race = object_get_value(inv, "harvest_race");
2327  tool = object_get_value(inv, "harvest_tool");
2328  slevel = object_get_value(inv, "harvest_level");
2329  sexp = object_get_value(inv, "harvest_exp");
2330  if (race && (!slevel || !sexp)) {
2331  LOG(llevError, "do_harvest: item %s without harvest_[level|exp]\n", inv->name);
2332  continue;
2333  }
2334  if (race == trace && (!tool || tool == ttool))
2335  found[count++] = inv;
2336 
2337  if (count >= max_harvest)
2338  break;
2339  } FOR_INV_FINISH();
2340 
2341  if (count >= max_harvest)
2342  break;
2343  } FOR_MAP_FINISH();
2344  if (count == 0) {
2345  draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, i18n(pl, "You find nothing to %s here."), skill->slaying);
2346  return;
2347  }
2348 
2349  assert(count <= max_harvest); // otherwise we have a stack overflow...
2350 
2351  inv = found[rndm(0, count-1)];
2352  assert(inv);
2353  item = inv->env;
2354  assert(item);
2355 
2356  slevel = object_get_value(inv, "harvest_level");
2357  sexp = object_get_value(inv, "harvest_exp");
2358  level = atoi(slevel);
2359  exp = atoi(sexp);
2360 
2361  speed = atof(tspeed);
2362  if (speed < 0)
2363  speed = -speed*pl->speed;
2364  pl->speed_left -= speed;
2365 
2366 
2367  /* Now we found something to harvest, randomly try to get it. */
2368  if (level > skill->level+10) {
2369  draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, i18n(pl, "You find something, but it is too difficult for you to %s."), skill->slaying);
2370  return;
2371  }
2372 
2373  int proba; /* Probability to get the item, 100 based. */
2374  if (level >= skill->level)
2375  /* Up to 10 more levels, 1 to 11 percent probability. */
2376  proba = 10+skill->level-level;
2377  else if (skill->level <= level+10)
2378  proba = 10+(skill->level-level)*2;
2379  else
2380  proba = 30;
2381 
2382  if (proba <= random_roll(0, 100, pl, 1)) {
2383  draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, i18n(pl, "You find something, but fail to %s it."), skill->slaying);
2384  return;
2385  }
2386 
2387  /* Check the new item can fit into inventory.
2388  * Fixes bug #3060474: fishing puts more fishes into inventory than you can carry. */
2389  if (((uint32_t)(pl->weight + pl->carrying + inv->weight)) > get_weight_limit(pl->stats.Str)) {
2390  draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You are carrying too much to %s a %s.", skill->slaying, inv->name);
2391  return;
2392  }
2393 
2394  /* Ok, got it. */
2395 
2396  /* If we have nrof 0, treat it like a singleton.
2397  * Old behavior was infinite here, and extremely abuseable.
2398  * Neila H. 2024-02-06
2399  */
2400  if (inv->nrof == 0) {
2401  check_exhaust = (count == 1 ? 1 : 0);
2402  object_remove(inv);
2403  harvested = inv;
2404  } else {
2405  if (count == 1 && inv->nrof == 1) {
2406  check_exhaust = 1;
2407  }
2408  if ( inv->nrof == 1 ) {
2409  /* Avoid dumping object inventory like a dead monster if it has an inventory */
2410  object_remove(inv);
2411  harvested = inv;
2412  }
2413  else {
2414  harvested = object_split(inv, 1, NULL, 0);
2415  }
2416  }
2417  object_set_value(harvested, "harvestable", NULL, 0);
2418  if (QUERY_FLAG(harvested, FLAG_MONSTER)) {
2419  int spot = object_find_free_spot(harvested, pl->map, pl->x, pl->y, 0, SIZEOFFREE);
2420  if (spot == -1) {
2421  /* Better luck next time...*/
2422  object_remove(harvested);
2423  draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You fail to %s anything.", skill->slaying);
2424  return;
2425  }
2426  object_insert_in_map_at(harvested, pl->map, NULL, 0, pl->x+freearr_x[spot], pl->y+freearr_y[spot]);
2427  draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You %s a %s!", skill->slaying, harvested->name);
2428  } else {
2429  harvested = object_insert_in_ob(harvested, pl);
2430  draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You %s some %s.", skill->slaying, harvested->name);
2431  }
2432 
2433  /* Get exp */
2434  change_exp(pl, exp, skill->name, SK_EXP_ADD_SKILL);
2435 
2436  if (check_exhaust) {
2437  sstring replacement = object_get_value(item, "harvest_exhaust_replacement");
2438  if (replacement) {
2439  if (replacement[0] != '-') {
2440  archetype *other = try_find_archetype(replacement);
2441  if (other) {
2442  object *final = object_create_arch(other);
2443  object_insert_in_map_at(final, map, item, INS_BELOW_ORIGINATOR, item->x, item->y);
2444  }
2445  }
2446  object_remove(item);
2448  }
2449  }
2450 
2451  return;
2452 }
#define MSG_TYPE_COMMAND_MAPS
Definition: newclient.h:541
const char *const change_resist_msg[NROFATTACKS]
These are the descriptions of the resistances displayed when a player puts on/takes off an item...
Definition: init.cpp:70
Error, serious thing.
Definition: logger.h:11
#define dirent
Definition: global.h:215
uint8_t login_method
Login method this client is using.
Definition: newserver.h:132
Fire north-west whatever the facing direction.
Definition: player.h:52
Will unapply whatever is necessary - this goes beyond no choice - if there are multiple ojbect of the...
Definition: player.h:78
signed long object_sum_weight(object *op)
object_sum_weight() is a recursive function which calculates the weight an object is carrying...
Definition: object.cpp:553
#define NUM_BODY_LOCATIONS
Number of body locations.
Definition: object.h:15
Sound-related defines.
Use keys in inventory and active containers.
Definition: player.h:68
living orig_stats
Permanent real stats of player.
Definition: player.h:169
static int onoff_value(const char *line)
Utility function to convert a reply to a yes/no or on/off value.
Definition: c_misc.cpp:1837
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
#define ST_GET_PARTY_PASSWORD
Player tried to join a password-protected party.
Definition: define.h:570
#define INS_BELOW_ORIGINATOR
Insert new object immediately below originator.
Definition: object.h:586
void bufferreader_destroy(BufferReader *br)
Destroy a BufferReader.
Information.
Definition: logger.h:12
void command_whereami(object *op, const char *params)
&#39;whereami&#39; command.
Definition: c_misc.cpp:820
struct archetype * arch
Pointer to archetype.
Definition: object.h:424
void roll_again(object *op)
Ask the player what to do with the statistics.
Definition: player.cpp:1146
int check_name(player *me, const char *name)
Ensure player&#39;s name is valid.
Definition: login.cpp:181
Standard mode/.
Definition: player.h:58
void command_title(object *op, const char *params)
Player wishes to change her title.
Definition: c_misc.cpp:2045
uint32_t hidden
If True, player (DM) is hidden from view.
Definition: player.h:149
object * object_get_owner(object *op)
Returns the object which this object marks as being the owner.
Definition: object.cpp:789
int16_t players
How many players are on this level right now.
Definition: map.h:339
region * get_region_by_map(mapstruct *m)
Gets a region from a map.
Definition: region.cpp:71
object * object_split(object *orig_ob, uint32_t nr, char *err, size_t size)
object_split(ob,nr) splits up ob into two parts.
Definition: object.cpp:2622
void command_applymode(object *op, const char *params)
Players wants to change the apply mode, ie how to handle applying an item when no body slot available...
Definition: c_misc.cpp:1275
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
bool check_password(const char *typed, const char *crypted)
Hash a password and compare it to the stored version.
Definition: server.cpp:114
#define FABS(x)
Decstations have trouble with fabs()...
Definition: define.h:22
int rndm(int min, int max)
Returns a number between min and max.
Definition: utils.cpp:162
#define MSG_TYPE_COMMAND_CONFIG
bowmode, petmode, applymode
Definition: newclient.h:546
std::vector< archetype * > players
Definition: player.cpp:501
#define NDI_WHITE
Definition: newclient.h:247
void map_path(const char *map, int flags, char *pathname, size_t bufsize)
Definition: map.cpp:1174
#define FLAG_USE_ARMOUR
(Monster) can wear armour/shield/helmet
Definition: define.h:283
int nroffreeobjects
How many OBs allocated and free (free)
Definition: object.cpp:290
void command_listen(object *op, const char *params)
Change the player&#39;s listen level.
Definition: c_misc.cpp:1088
char who_wiz_format[MAX_BUF]
The format that the who command should use when called by a dm.
Definition: global.h:278
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
region * get_region_from_string(const char *name)
Tries to find a region that &#39;name&#39; corresponds to.
Definition: region.cpp:116
void * language_t
Strings that should be manipulated through add_string() and free_string().
Definition: global.h:69
void player_set_own_title(struct player *pl, const char *title)
Sets the custom title.
Definition: player.cpp:273
void command_wizpass(object *op, const char *params)
Wizard toggling wall-crossing.
Definition: c_misc.cpp:915
AllAnimations * animations()
Get animations.
Definition: AssetsManager.h:49
uint32_t peaceful
If set, won&#39;t attack friendly creatures.
Definition: player.h:148
void dump_all_maps(void)
Prints out debug-information about all maps.
Definition: map.cpp:268
static void map_info(object *op, const char *search)
This is the &#39;maps&#39; command.
Definition: c_misc.cpp:50
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
Definition: living.cpp:1132
void command_motd(object *op, const char *params)
Display the message of the day.
Definition: c_misc.cpp:215
const char * i18n(const object *who, const char *code)
Translate a message in the appropriate language.
Definition: languages.cpp:42
Shared-strings defines.
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
Definition: object.cpp:1818
void dump_map(const mapstruct *m)
Prints out debug-information about a map.
Definition: map.cpp:245
player * first_player
First player.
Definition: init.cpp:106
unapplymode
This is used to control what to do when we need to unapply an object before we can apply another one...
Definition: player.h:75
#define LOOK_OBJ(ob)
This returns TRUE if the object is something that should be displayed in the look window...
Definition: object.h:521
int login_order
Definition: c_misc.cpp:522
int save_player(object *op, int flag)
Saves a player to disk.
Definition: login.cpp:239
int level
Definition: readable.cpp:1561
const char * playerdir
Where the player files are.
Definition: global.h:251
#define MAP_ENTER_X(m)
Default X coordinate for map enter.
Definition: map.h:83
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
object_find_free_spot(object, map, x, y, start, stop) will search for a spot at the given map and coo...
Definition: object.cpp:3544
#define HUGE_BUF
Used for messages - some can be quite long.
Definition: define.h:37
partylist * party
Party this player is part of.
Definition: player.h:205
sstring slaying
Which race to do double damage to.
Definition: object.h:327
void command_dumpallmaps(object *op, const char *params)
Various map-related statistics.
Definition: c_misc.cpp:1045
sstring add_string(const char *str)
Share a string.
Definition: shstr.cpp:137
#define SND_MUTE
Don&#39;t sent anything for now.
Definition: sounds.h:14
#define SS_DUMP_TOTALS
Definition: shstr.h:47
#define ST_CHANGE_PASSWORD_CONFIRM
Player is confirming new password.
Definition: define.h:573
void dump_friendly_objects(void)
Dumps all friendly objects.
Definition: friend.cpp:70
#define MAP_HEIGHT(m)
Map height.
Definition: map.h:78
#define ST_CONFIRM_PASSWORD
New character, confirm password.
Definition: define.h:569
std::vector< region * > all_regions
Definition: init.cpp:108
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
Changes experience to a player/monster.
Definition: living.cpp:2179
static void help_topics(object *op, int what)
Player wants to know available help topics.
Definition: c_misc.cpp:1641
DIR * opendir(const char *)
static int name_cmp(const chars_names *c1, const chars_names *c2)
Local function for qsort comparison.
Definition: c_misc.cpp:534
void command_sound(object *op, const char *params)
Player wants to change sound status.
Definition: c_misc.cpp:1908
int16_t y
Position in the map for this object.
Definition: object.h:335
#define FLAG_USE_WEAPON
(Monster) can wield weapons
Definition: define.h:284
int is_dragon_pl(const object *op)
Checks if player is a dragon.
Definition: player.cpp:123
int checkbanned(const char *login, const char *host)
Check if a player and/or host is banned.
Definition: ban.cpp:32
void dump_all_archetypes(void)
Dumps all archetypes to debug-level output.
Definition: arch.cpp:148
uint32_t get_weight_limit(int stat)
Definition: living.cpp:2373
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
void time_info(object *op)
Players wants to know the time.
Definition: time.cpp:298
#define ST_CHANGE_PASSWORD_NEW
Player is entering new password.
Definition: define.h:572
#define FLAG_AFK
Player is AFK.
Definition: define.h:364
#define TRUE
Definition: compat.h:11
player * find_player(const char *plname)
Find a player by her full name.
Definition: player.cpp:59
LogLevel debug
Default debugging level.
Definition: global.h:244
int64_t level_exp(int level, double expmul)
Returns how much experience is needed for a player to become the given level.
Definition: living.cpp:1885
int player_has_own_title(const struct player *pl)
Returns whether the player has a custom title.
Definition: player.cpp:248
void print_los(object *op)
Debug-routine which dumps the array which specifies the visible area of a player. ...
Definition: los.cpp:665
int object_count_used(void)
Object statistics.
Definition: object.cpp:1752
#define FALSE
Definition: compat.h:14
object * chosen_skill
The skill chosen to use.
Definition: object.h:396
void receive_player_password(object *op, const char *password)
A player just entered her password, including for changing it.
Definition: c_misc.cpp:1953
void do_harvest(object *pl, int dir, object *skill)
Player is trying to harvest something.
Definition: c_misc.cpp:2258
char * ss_dump_table(int what, char *buf, size_t size)
Dump the contents of the share string tables.
Definition: shstr.cpp:368
int16_t x
Definition: object.h:335
#define SS_DUMP_TABLE
Definition: shstr.h:46
Attack other players in arena.
Definition: player.h:61
Use keys in inventory and active key rings.
Definition: player.h:67
#define MSG_TYPE_COMMAND_STATISTICS
Definition: newclient.h:545
Global type definitions and header inclusions.
#define safe_strncpy
Definition: compat.h:27
struct player * contr
Pointer to the player which control this object.
Definition: object.h:284
bowtype_t
Bow firing mode.
Definition: player.h:41
int8_t Con
Use
Definition: living.h:36
void pets_terminate_all(object *owner)
Removes all pets someone owns.
Definition: pets.cpp:242
void command_fix_me(object *op, const char *params)
Wrapper to fix a player.
Definition: c_misc.cpp:1211
Will not unapply objects automatically.
Definition: player.h:77
#define ST_ROLL_STAT
New character, rolling stats.
Definition: define.h:564
double expmul
needed experience = (calc_exp*expmul) - means some races/classes can need less/more exp to gain level...
Definition: object.h:407
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: main.cpp:308
char * longname
Official title of the region, this might be defined to be the same as name.
Definition: map.h:286
#define ST_PLAYING
Usual state.
Definition: define.h:562
char * host
Which host it is connected from (ip address).
Definition: newserver.h:104
archetype * try_find_archetype(const char *name)
Definition: assets.cpp:274
#define MAP_WHEN_RESET(m)
This is when the map will reset.
Definition: map.h:65
int32_t weight
Attributes of the object.
Definition: object.h:375
char namebuf[MAX_BUF]
Definition: c_misc.cpp:521
float weapon_speed
The overall speed of this object.
Definition: object.h:339
void ss_dump_statistics(char *buf, size_t size)
A call to this function will cause the statistics to be dumped into specified buffer.
Definition: shstr.cpp:337
void command_passwd(object *pl, const char *params)
Player is asking to change password.
Definition: c_misc.cpp:2234
static void current_map_info(object *op)
&#39;mapinfo&#39; command.
Definition: c_misc.cpp:427
uint32_t counter
A generic counter for holding temporary data.
Definition: map.h:289
void hiscore_display(object *op, int max, const char *match)
Displays the high score file.
Definition: hiscore.cpp:451
void get_name(object *op)
Waiting for the player&#39;s name.
Definition: player.cpp:886
#define NROFATTACKS
Definition: attack.h:15
uint8_t run_away
Monster runs away if it&#39;s hp goes below this percentage.
Definition: object.h:394
void list_players(object *op, region *reg, partylist *party)
Displays the players in a region or party.
Definition: c_misc.cpp:548
void object_dump_all(void)
Dumps all objects to console.
Definition: object.cpp:689
AssetsManager * getManager()
Definition: assets.cpp:309
#define MSG_TYPE_ADMIN_DM
DM related admin actions.
Definition: newclient.h:516
void command_kill_pets(object *op, const char *params)
Player wants to get rid of pets.
Definition: c_misc.cpp:2194
#define NAMLEN(dirent)
Definition: global.h:216
long nrofartifacts
Only used in malloc_info().
Definition: init.cpp:116
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.cpp:294
void command_quit(object *op, const char *params)
Tell players to use the &#39;delete&#39; command.
Definition: c_misc.cpp:1871
#define MAP_IN_MEMORY
Map is fully loaded.
Definition: map.h:129
static int find_help_file_in(const char *dir, const char *name, const char *language, char *path, int length)
Find a (help) file in the specified subdirectory of data.
Definition: c_misc.cpp:1701
int16_t level
Level of creature or object.
Definition: object.h:361
object * object_find_by_type_and_arch_name(const object *who, int type, const char *name)
Find object in inventory by type and archetype name.
Definition: object.cpp:4262
int16_t sp
Spell points.
Definition: living.h:42
#define NDI_RED
Definition: newclient.h:249
Main Crossfire structure, one ingame object.
Definition: object.h:282
void object_free(object *ob, int flags)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.cpp:1577
player * next
Pointer to next player, NULL if this is last.
Definition: player.h:108
#define FREE_OBJ_FREE_INVENTORY
Free inventory objects; if not set, drop inventory.
Definition: object.h:546
size_t split_string(char *str, char *array[], size_t array_size, char sep)
Splits a string delimited by passed in sep value into characters into an array of strings...
Definition: utils.cpp:473
One party.
Definition: party.h:10
#define MSG_TYPE_COMMAND
Responses to commands, eg, who.
Definition: newclient.h:420
sstring reset_group
For reset purpose, all maps in the same group reset at the same time.
Definition: map.h:332
uint32_t sound
Client sound mode.
Definition: newserver.h:115
const char *const attacktype_desc[NROFATTACKS]
Short description of names of the attacktypes.
Definition: init.cpp:40
int16_t resist[NROFATTACKS]
Resistance adjustments for attacks.
Definition: object.h:351
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
This calls the appropriate treasure creation function.
Definition: treasure.cpp:287
usekeytype
How to use keys.
Definition: player.h:65
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
Definition: object.h:483
size_t assets_number_of_treasurelists()
Definition: assets.cpp:262
static void current_region_info(object *op)
&#39;whereami&#39; command.
Definition: c_misc.cpp:405
void send_query(socket_struct *ns, uint8_t flags, const char *text)
Asks the client to query the user.
Definition: request.cpp:745
void command_dumpallobjects(object *op, const char *params)
Various object-related statistics.
Definition: c_misc.cpp:975
char * msg
Message map creator may have left.
Definition: map.h:356
#define MSG_TYPE_COMMAND_ERROR
Bad syntax/can&#39;t use command.
Definition: newclient.h:550
Defines for loader.l / loader.c.
int8_t Dex
Use
Definition: living.h:36
float speed
Frequency of object &#39;moves&#39; relative to server tick rate.
Definition: object.h:337
int32_t carrying
How much weight this object contains.
Definition: object.h:377
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Append a formatted string to a string buffer instance.
const char * get_region_msg(const region *r)
Gets a message for a region.
Definition: region.cpp:230
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:360
static bool IS_PLAYER(object *op)
Definition: object.h:611
object * env
Pointer to the object which is the environment.
Definition: object.h:301
#define SET_FLAG(xyz, p)
Definition: define.h:384
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Append a string to a string buffer instance.
#define QUERY_FLAG(xyz, p)
Definition: define.h:386
#define ST_CONFIRM_QUIT
Player used the &#39;quit&#39; command, make sure that&#39;s ok.
Definition: define.h:566
uint8_t unarmed_skills[UNARMED_SKILLS_COUNT]
Table of unarmed attack skills.
Definition: skills.cpp:31
int8_t Wis
Use
Definition: living.h:36
artifactlist * next
Next list of artifacts.
Definition: artifact.h:27
void get_password(object *op)
Waiting for the player&#39;s password.
Definition: player.cpp:897
void command_wizcast(object *op, const char *params)
Wizard toggling "cast everywhere" ability.
Definition: c_misc.cpp:945
void command_resistances(object *op, const char *params)
Players wants to know her resistances.
Definition: c_misc.cpp:1595
void player_get_title(const player *pl, char *buf, size_t bufsize)
Returns the player&#39;s title.
Definition: player.cpp:233
void command_peaceful(object *op, const char *params)
Player toggles her peaceful status.
Definition: c_misc.cpp:2122
BufferReader * bufferreader_init_from_file(BufferReader *br, const char *filepath, const char *failureMessage, LogLevel failureLevel)
Initialize or create a BufferReader from a file path.
void player_set_state(player *pl, uint8_t state)
Set the player&#39;s state to the specified one.
Definition: player.cpp:4493
char new_password[16]
2 (seed) + 11 (crypted) + 1 (EOS) + 2 (safety) = 16
Definition: player.h:196
#define ATNR_INTERNAL
Definition: attack.h:70
int strcasecmp(const char *s1, const char *s2)
void command_dumpfriendlyobjects(object *op, const char *params)
Various friendly object-related statistics.
Definition: c_misc.cpp:989
#define MAP_TIMEOUT(m)
Definition: map.h:69
short freearr_x[SIZEOFFREE]
X offset when searching around a spot.
Definition: object.cpp:299
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:700
socket_struct * socket
Socket information for this player.
Definition: player.h:109
#define FMT64
Definition: compat.h:16
char * name
Shortend name of the region as maps refer to it.
Definition: map.h:280
char password[16]
2 (seed) + 11 (crypted) + 1 (EOS) + 2 (safety) = 16
Definition: player.h:195
Try to find an arrow matching the target.
Definition: player.h:53
This is a game-map.
Definition: map.h:320
objectlink * get_friends_of(const object *owner)
Get a list of friendly objects for the specified owner.
Definition: friend.cpp:117
void command_help(object *op, const char *params)
Player is asking for some help.
Definition: c_misc.cpp:1770
int region_is_child_of_region(const region *child, const region *r)
Checks if a region is a child of another.
Definition: region.cpp:182
int atnr_is_dragon_enabled(int attacknr)
Determine if the attacktype represented by the specified attack-number is enabled for dragon players...
Definition: player.cpp:104
void command_version(object *op, const char *params)
Server version.
Definition: c_misc.cpp:1074
artifactlist * first_artifactlist
First artifact.
Definition: init.cpp:109
Archetypes * archetypes()
Get archetypes.
Definition: AssetsManager.h:44
void command_statistics(object *pl, const char *params)
Prints out some useful information for the character.
Definition: c_misc.cpp:1119
sstring object_get_value(const object *op, const char *const key)
Get an extra value by key.
Definition: object.cpp:4331
char * partyname
Party name.
Definition: party.h:14
#define CS_QUERY_SINGLECHAR
Single character response expected.
Definition: newclient.h:71
#define MSG_TYPE_COMMAND_WHO
Definition: newclient.h:540
language_t language
The language the player wishes to use.
Definition: player.h:222
void command_printlos(object *op, const char *params)
Various LOS-related statistics.
Definition: c_misc.cpp:1059
uint8_t state
Input state of the player (name, password, etc).
Definition: player.h:133
object * ob
The object representing the player.
Definition: player.h:179
#define MAP_ENTER_Y(m)
Default Y coordinate for map enter.
Definition: map.h:85
size_t count() const
Get the number of assets.
This represents all archetypes for one particular object type.
Definition: artifact.h:24
static int find_help_file(const char *name, const char *language, int wiz, char *path, int length)
Find an appropriate help file.
Definition: c_misc.cpp:1724
#define SIZEOFFREE
Definition: define.h:155
#define P_OUT_OF_MAP
This space is outside the map.
Definition: map.h:254
void command_dumpmap(object *op, const char *params)
Various map-related statistics.
Definition: c_misc.cpp:1031
mapstruct * first_map
First map.
Definition: init.cpp:107
uint32_t braced
Will not move if braced, only attack.
Definition: player.h:141
struct Settings settings
Global settings.
Definition: init.cpp:139
void i18n_list_languages(object *who)
List all languages for who.
Definition: languages.cpp:96
uint32_t map_size(mapstruct *m)
Calculate map size without intermediate sign extension.
Definition: map.cpp:808
void command_ssdumptable(object *op, const char *params)
Various string-related statistics.
Definition: c_misc.cpp:1017
#define MSG_TYPE_SKILL_FAILURE
Failure in using skill.
Definition: newclient.h:626
usekeytype usekeys
Method for finding keys for doors.
Definition: player.h:122
void command_delete(object *op, const char *params)
Player wants to totally delete her character.
Definition: c_misc.cpp:1887
int random_roll(int min, int max, const object *op, int goodbad)
Roll a random number between min and max.
Definition: utils.cpp:42
unapplymode unapply
Method for auto unapply.
Definition: player.h:123
int16_t dam
How much damage this object does when hitting.
Definition: living.h:46
void command_list(object *pl, bool is_dm)
Display the list of commands to a player.
Definition: commands.cpp:390
#define MSG_TYPE_ADMIN_VERSION
version info
Definition: newclient.h:520
uint32_t is_bot
Client shouldn&#39;t be reported to metaserver.
Definition: newserver.h:111
void command_save(object *op, const char *params)
Player wants to get saved.
Definition: c_misc.cpp:2096
void command_usekeys(object *op, const char *params)
Player wants to change how keys are used.
Definition: c_misc.cpp:1554
void receive_player_name(object *op, const char *name)
A player just entered her name.
Definition: c_misc.cpp:1933
uint32_t ticks_played
How many ticks this player has played.
Definition: player.h:224
#define FLAG_WIZ
Object has special privilegies.
Definition: define.h:218
#define MAP_MINTIMEOUT
At least that many ticks before swapout.
Definition: config.h:409
uint8_t listening
Which priority will be used in info_all.
Definition: player.h:135
long seconds(void)
Return wall clock time in seconds.
Definition: time.cpp:348
living stats
Str, Con, Dex, etc.
Definition: object.h:378
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
LogLevel
Log levels for the LOG() function.
Definition: logger.h:10
char who_format[MAX_BUF]
The format that the who command should use.
Definition: global.h:277
#define MSG_TYPE_ADMIN
Definition: newclient.h:418
static void malloc_info(object *op)
Sends various memory-related statistics.
Definition: c_misc.cpp:252
void command_time(object *op, const char *params)
Players asks for the time.
Definition: c_misc.cpp:866
uint32_t tick_duration
Gloabal variables:
Definition: time.cpp:35
size_t strlcpy(char *dst, const char *src, size_t size)
Portable implementation of strlcpy(3).
Definition: porting.cpp:222
float speed_left
How much speed is left to spend this round.
Definition: object.h:338
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
void command_bowmode(object *op, const char *params)
Player wants to change the bowmode, how arrows are fired.
Definition: c_misc.cpp:1316
const char * get_name_of_region_for_map(const mapstruct *m)
Gets the name of a region for a map.
Definition: region.cpp:89
void command_strings(object *op, const char *params)
Various string-related statistics.
Definition: c_misc.cpp:845
void command_debug(object *op, const char *params)
Player wants to see/change the debug level.
Definition: c_misc.cpp:891
uint32_t in_memory
Combination of IN_MEMORY_xxx flags.
Definition: map.h:340
short freearr_y[SIZEOFFREE]
Y offset when searching around a spot.
Definition: object.cpp:305
object * object_create_arch(archetype *at)
Create a full object using the given archetype.
Definition: arch.cpp:296
treasurelist represents one logical group of items to be generated together.
Definition: treasure.h:85
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:753
type_definition ** types
Defined types.
long nrofallowedstr
Only used in malloc_info().
Definition: init.cpp:117
void command_whereabouts(object *op, const char *params)
&#39;whereabouts&#39; command.
Definition: c_misc.cpp:482
const char * datadir
Read only data files.
Definition: global.h:249
void set_map_reset_time(mapstruct *map)
Updates the map&#39;s timeout.
Definition: map.cpp:2262
int8_t body_info[NUM_BODY_LOCATIONS]
Body info as loaded from the file.
Definition: object.h:382
void pets_terminate(object *pet)
Removes a pet, taking care of clearning the owner&#39;s fields if needed.
Definition: pets.cpp:224
sstring name_pl
The plural name of the object.
Definition: object.h:323
int object_count_active(void)
Objects statistics.
Definition: object.cpp:1768
region * get_region_by_name(const char *region_name)
Gets a region by name.
Definition: region.cpp:45
static event_registration m
Definition: citylife.cpp:424
This structure contains all information related to one map square.
Definition: map.h:261
int nrofallocobjects
How many OBs allocated (free + used)
Definition: object.cpp:291
#define FREE_AND_COPY(sv, nv)
Release the shared string if not NULL, and make it a reference to nv.
Definition: global.h:206
#define MSG_TYPE_COMMAND_MALLOC
Definition: newclient.h:543
uint32_t name_changed
If true, the player has set a name.
Definition: player.h:147
void command_petmode(object *op, const char *params)
Player wants to change how her pets behave.
Definition: c_misc.cpp:1435
const char * localdir
Read/write data files.
Definition: global.h:250
#define FLAG_WIZCAST
The wizard can cast spells in no-magic area.
Definition: define.h:277
#define MSG_TYPE_LAST
Definition: newclient.h:437
sstring name
The name of the object, obviously...
Definition: object.h:319
void check_login(object *op, const char *password)
Actually login a player, load from disk and such.
Definition: login.cpp:522
Stay close to the owner.
Definition: player.h:60
#define MAP_WIDTH(m)
Map width.
Definition: map.h:76
uint32_t nrof
Number of objects.
Definition: object.h:342
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.cpp:300
int8_t Cha
Use
Definition: living.h:36
Utility structure for the &#39;who&#39; command.
Definition: c_misc.cpp:520
#define SK_EXP_ADD_SKILL
Give the player the skill.
Definition: skills.h:78
#define MSG_TYPE_COMMAND_INFO
Generic info: resistances, etc.
Definition: newclient.h:547
#define CLEAR_FLAG(xyz, p)
Definition: define.h:385
bowtype_t bowtype
Which firemode?
Definition: player.h:116
int8_t ac
Armor Class, lower AC increases probability of not getting hit.
Definition: living.h:38
static void get_who_escape_code_value(char *return_val, int size, const char letter, player *pl)
Returns the value of the escape code used in the who format specifier.
Definition: c_misc.cpp:694
struct dirent * readdir(DIR *)
int8_t Pow
Use
Definition: living.h:36
#define ST_CHANGE_PASSWORD_OLD
Player is entering old password to change password.
Definition: define.h:571
treasurelist * find_treasurelist(const char *name)
Search for the given treasurelist by name.
Definition: assets.cpp:253
petmode_t
Petmode.
Definition: player.h:57
void command_maps(object *op, const char *params)
&#39;maps&#39; command.
Definition: c_misc.cpp:833
body_locations_struct body_locations[NUM_BODY_LOCATIONS]
The ordering of this is actually doesn&#39;t make a difference However, for ease of use, new entries should go at the end so those people that debug the code that get used to something being in the location 4 don&#39;t get confused.
Definition: item.cpp:56
int object_set_value(object *op, const char *key, const char *value, int add_key)
Updates the key in op to value.
Definition: object.cpp:4484
void send_news(const object *op)
Send the news to a player.
Definition: player.cpp:206
treasure is one element in a linked list, which together consist of a complete treasure-list.
Definition: treasure.h:63
#define MSG_TYPE_COMMAND_BODY
Definition: newclient.h:542
void send_rules(const object *op)
Send the rules to a player.
Definition: player.cpp:170
void command_showpets(object *op, const char *params)
Players wants to know her pets.
Definition: c_misc.cpp:1479
language_t i18n_find_language_by_code(const char *code)
Attempt to find the identifier of a language from its code.
Definition: languages.cpp:60
int64_t exp
Experience.
Definition: living.h:47
sstring skill
Name of the skill this object uses/grants.
Definition: object.h:329
int16_t maxsp
Max spell points.
Definition: living.h:43
#define FLAG_MONSTER
Will attack players.
Definition: define.h:232
Will unapply objects when there no choice to unapply.
Definition: player.h:76
#define MSG_TYPE_SKILL
Messages related to skill use.
Definition: newclient.h:424
int closedir(DIR *)
static void display_help_file(object *op, const char *filename)
Attempt to send the contents of the specified file to the player.
Definition: c_misc.cpp:1747
uint8_t set_title
Players can set thier title.
Definition: global.h:266
void command_unarmed_skill(object *op, const char *params)
Player wants to change prefered unarmed skill.
Definition: c_misc.cpp:1379
#define NDI_UNIQUE
Print immediately, don&#39;t buffer.
Definition: newclient.h:270
#define MSG_SUBTYPE_NONE
Definition: newclient.h:439
C function wrappers to interact with assets.
#define CS_QUERY_HIDEINPUT
Hide input being entered.
Definition: newclient.h:72
void command_news(object *op, const char *params)
Display the server news.
Definition: c_misc.cpp:241
One player.
Definition: player.h:107
#define MAX_NAME
Definition: define.h:41
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:746
StringBuffer * buf
Definition: readable.cpp:1563
void command_body(object *op, const char *params)
This command dumps the body information for object *op.
Definition: c_misc.cpp:173
#define FULL_VERSION
Definition: version.h:6
char * bufferreader_next_line(BufferReader *br)
Return the next line in the buffer, as separated by a newline.
static void display_who_entry(object *op, player *pl, const char *format)
Display a line of &#39;who&#39; to op, about pl, using the formatting specified by format.
Definition: c_misc.cpp:638
const char * get_region_longname(const region *r)
Gets the longname of a region.
Definition: region.cpp:209
void command_malloc(object *op, const char *params)
Display memory information.
Definition: c_misc.cpp:794
A buffer that will be expanded as content is added to it.
const char * unarmed_skill
Prefered skill to use in unarmed combat.
Definition: player.h:223
int16_t maxhp
Max hit points.
Definition: living.h:41
uint8_t subtype
Subtype of object.
Definition: object.h:349
Only use keys in inventory.
Definition: player.h:66
uint16_t difficulty
What level the player should be to play here.
Definition: map.h:338
void command_afk(object *op, const char *params)
Toggles the afk status of a player.
Definition: c_misc.cpp:773
void command_wimpy(object *op, const char *params)
Player wants to change how soon she&#39;ll flee.
Definition: c_misc.cpp:2140
void command_language(object *op, const char *params)
This is the &#39;language&#39; command.
Definition: c_misc.cpp:130
void command_hiscore(object *op, const char *params)
Player is asking for the hiscore.
Definition: c_misc.cpp:879
const char * sstring
Definition: sstring.h:2
int object_count_free(void)
Objects statistics.
Definition: object.cpp:1736
mapstruct * next
Next map, linked list.
Definition: map.h:321
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
Definition: object.cpp:2842
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.cpp:2085
int8_t wc
Weapon Class, lower WC increases probability of hitting.
Definition: living.h:37
int8_t Int
Use
Definition: living.h:36
float ticks_to_seconds(int ticks)
Definition: time.cpp:386
tag_t count
Unique object number for this object.
Definition: object.h:307
petmode_t petmode
Which petmode?
Definition: player.h:117
This is a game region.
Definition: map.h:279
sstring i18n_get_language_code(language_t language)
Return the code of a specified language.
Definition: languages.cpp:86
#define FLAG_WIZPASS
The wizard can go through walls.
Definition: define.h:302
Try to find enemies.
Definition: player.h:59
char const * newhash(char const *password)
Definition: server.cpp:101
This is one artifact, ie one special item.
Definition: artifact.h:14
void command_rules(object *op, const char *params)
Display the server rules.
Definition: c_misc.cpp:228
void command_who(object *op, const char *params)
&#39;who&#39; command.
Definition: c_misc.cpp:621
object * find_skill_by_name(object *who, const char *name)
This returns the skill pointer of the given name (the one that accumulates exp, has the level...
Definition: skill_util.cpp:209
object clone
An object from which to do object_copy()
Definition: object.h:487
bool object_value_set(const object *op, const char *const key)
Determine if an extra value is set.
Definition: object.cpp:4361
#define P_NO_CLERIC
No clerical spells cast here.
Definition: map.h:241
size_t assets_number_of_treasures()
Definition: assets.cpp:259
int8_t Str
Use
Definition: living.h:36
void command_dumpallarchetypes(object *op, const char *params)
Various archetypes-related statistics.
Definition: c_misc.cpp:1003
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:693
int8_t body_used[NUM_BODY_LOCATIONS]
Calculated value based on items equipped.
Definition: object.h:383
void command_brace(object *op, const char *params)
Player toggles her braced status.
Definition: c_misc.cpp:2170
char * name
Name of map as given by its creator.
Definition: map.h:323
int16_t hp
Hit Points.
Definition: living.h:40
Definition: object.h:229
void command_mapinfo(object *op, const char *params)
&#39;mapinfo&#39; command.
Definition: c_misc.cpp:807
void display_motd(const object *op)
Sends the message of the day to the player.
Definition: player.cpp:139
void command_players(object *op, const char *params)
Display all known players.
Definition: c_misc.cpp:1225