Crossfire Server, Trunk
c_misc.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 
20 #define WANT_UNARMED_SKILLS
21 
22 #include "global.h"
23 
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/stat.h>
28 
29 #undef SS_STATISTICS
30 #include "loader.h"
31 #include "shstr.h"
32 #include "sounds.h"
33 #include "sproto.h"
34 #include "version.h"
35 
36 #include "assets.h"
37 
38 /* Static declarations where needed (when ordering would be an issue) */
39 static void display_who_entry(object *op, player *pl, const char *format);
40 static void get_who_escape_code_value(char *return_val, int size, const char letter, player *pl);
41 static int onoff_value(const char *line);
42 
51 static void map_info(object *op, const char *search) {
52  if ( *search != 0 ) {
54  "Maps matching search: '%s'", search);
55  }
56  if (QUERY_FLAG(op, FLAG_WIZ)) {
58  "[fixed]Path Reset In (HH:MM:SS) Pl IM TO");
59  } else {
61  "[fixed]Path Reset In (HH:MM)");
62  }
63 
64  /* Allow a comma-separate list of search strings; more complicated because of the const */
65  char *to_be_freed = NULL;
66  char *search_array[64];
67  int search_array_count = 0;
68  if ( search[0] ) {
69  to_be_freed = strdup(search);
70  if ( !to_be_freed ) {
71  search_array[0] = to_be_freed;
72  search_array_count = 1;
73  } else {
74  search_array_count = split_string(to_be_freed,search_array,64,',');
75  }
76  }
77 
78  for (mapstruct *m = first_map; m != NULL; m = m->next) {
79  bool match = TRUE;
80  if ( search_array_count ) {
81  match = FALSE;
82  for (int i=0; i<search_array_count; ++i) {
83  if ( strstr(m->path,search_array[i]) ) {
84  match=TRUE;
85  break;
86  }
87  }
88  }
89  if ( !match ) continue; /* Skip unwanted maps */
90 
91  /* Print out the last 26 characters of the map name... */
92  char map_path[MAX_BUF];
93  if (strlen(m->path) <= 26) {
94  strcpy(map_path, m->path);
95  } else {
96  safe_strncpy(map_path, m->path + strlen(m->path) - 26, sizeof(map_path));
97  }
98 
99  uint32_t ttr = MAP_WHEN_RESET(m) - seconds() > 0 ? MAP_WHEN_RESET(m) - seconds() : 0;
100  if ( !m->reset_timeout && !m->unique ) set_map_reset_time(m);
101  if (m->players) {
102  ttr = (m->unique ? 0 : m->reset_timeout) + 300;
103  }
104  else if (m->timeout) {
105  ttr = (m->unique ? 0 : m->reset_timeout) + m->timeout;
106  }
107  const uint32_t hh = ttr/3600, mm = (ttr%3600)/60, ss = ttr%60;
108  if (QUERY_FLAG(op, FLAG_WIZ)) {
111  "[fixed]%-26.26s %2d:%02d:%02d %2d %2d %4d",
112  map_path, hh, mm, ss, m->players, m->in_memory, m->timeout);
113  } else {
116  "[fixed]%-26.26s %2d:%02d%s", map_path, hh, mm,
117  m->players ? " (in use)" : "");
118  }
119  }
120  if ( to_be_freed ) free( to_be_freed );
121 }
122 
131 void command_language(object *op, const char *params) {
132  int language = -1;
133 
134  if (!op->contr)
135  return;
136 
137  if (*params == '\0' || (!strcmp(params, ""))) {
139  "Your current language is set to: English.");
141  "Available languages:");
143  return;
144  }
145 
147 
148  /* Error out if unknown language. */
149  if (language == -1) {
151  "Unknown language.");
152  return;
153  }
154 
155  op->contr->language = language;
156 
158  "Your current language is set to English.");
159 }
160 
174 void command_body(object *op, const char *params) {
175  int i;
176  (void)params;
177 
178  /* Too hard to try and make a header that lines everything up, so just
179  * give a description.
180  */
182  "The first column is the name of the body location.");
183 
185  "The second column is how many of those locations your body has.");
186 
188  "The third column is how many slots in that location are available.");
189 
190  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
191  /* really debugging - normally body_used should not be set to anything
192  * if body_info isn't also set.
193  */
194  if (op->body_info[i] || op->body_used[i]) {
196  "[fixed]%-30s %5d %5d",
197  i18n(op, body_locations[i].use_name), op->body_info[i], op->body_used[i]);
198  }
199  }
202  "You are not allowed to wear armor.");
205  "You are not allowed to use weapons.");
206 }
207 
216 void command_motd(object *op, const char *params) {
217  (void)params;
218  display_motd(op);
219 }
220 
229 void command_rules(object *op, const char *params) {
230  (void)params;
231  send_rules(op);
232 }
233 
242 void command_news(object *op, const char *params) {
243  (void)params;
244  send_news(op);
245 }
246 
253 static void malloc_info(object *op) {
254  int ob_used = object_count_used(), ob_free = object_count_free(), players, nrofmaps;
255  int nrm = 0, mapmem = 0, anr, anims, sum_alloc = 0, sum_used = 0, i, alnr;
256  player *pl;
257  mapstruct *m;
258  artifactlist *al;
259 
260  for (al = first_artifactlist, alnr = 0; al != NULL; al = al->next, alnr++)
261  ;
262 
264 
266 
267  for (pl = first_player, players = 0; pl != NULL; pl = pl->next, players++)
268  ;
269 
270  for (m = first_map, nrofmaps = 0; m != NULL; m = m->next, nrofmaps++)
271  if (m->in_memory == MAP_IN_MEMORY) {
272  mapmem += map_size(m) * (sizeof(object *) + sizeof(MapSpace));
273  nrm++;
274  }
275 
277  "Sizeof: object=%d player=%d map=%d",
278  sizeof(object), sizeof(player), sizeof(mapstruct));
279 
281  "[fixed]Objects:");
282 
284  "[fixed]%6d used", ob_used);
285 
286  if (ob_used != nrofallocobjects - nroffreeobjects) {
288  "[fixed] (used list mismatch: %d)",
290  }
291 
293  "[fixed]%6d free (%.2f%% of %d allocated)",
294  ob_free, (float)ob_free / nrofallocobjects * 100, nrofallocobjects);
295 
296  if (ob_free != nroffreeobjects) {
298  "[fixed] (free list mismatch: %d)",
300  }
301 
303  "[fixed]%6d on active list",
305 
306  i = (ob_used*sizeof(object));
307  sum_used += i;
308  sum_alloc += i;
309 
311  "[fixed] object total: %11d", i);
312 
313  i = (ob_free*sizeof(object));
314  sum_alloc += i;
315 
317  "[fixed]%4d players: %8d",
318  players, i = (players*sizeof(player)));
319 
320  sum_alloc += i;
321  sum_used += i;
322 
324  "[fixed]%4d maps allocated: %8d",
325  nrofmaps, i = (nrofmaps*sizeof(mapstruct)));
326 
327  sum_alloc += i;
328  sum_used += nrm*sizeof(mapstruct);
329 
331  "[fixed]%4d maps in memory: %8d",
332  nrm, mapmem);
333 
334  sum_alloc += mapmem;
335  sum_used += mapmem;
336 
338  "[fixed]%4d archetypes: %8d",
339  anr, i = (anr*sizeof(archetype)));
340 
341  sum_alloc += i;
342  sum_used += i;
343 
345  "[fixed]%4d animations: %8d",
346  anims, i = (anims*sizeof(uint16_t)));
347 
348  sum_alloc += i;
349  sum_used += i;
350 
352  "[fixed]%4d treasurelists %8d",
354 
355  sum_alloc += i;
356  sum_used += i;
357 
359  "[fixed]%4ld treasures %8d",
361 
362  sum_alloc += i;
363  sum_used += i;
364 
366  "[fixed]%4ld artifacts %8d",
367  nrofartifacts, i = (nrofartifacts*sizeof(artifact)));
368 
369  sum_alloc += i;
370  sum_used += i;
371 
373  "[fixed]%4ld artifacts strngs %8d",
374  nrofallowedstr, i = (nrofallowedstr*sizeof(linked_char)));
375 
376  sum_alloc += i;
377  sum_used += i;
378 
380  "[fixed]%4d artifactlists %8d",
381  alnr, i = (alnr*sizeof(artifactlist)));
382 
383  sum_alloc += i;
384  sum_used += i;
385 
387  "[fixed]Total space allocated:%8d",
388  sum_alloc);
389 
391  "[fixed]Total space used: %8d",
392  sum_used);
393 }
394 
406 static void current_region_info(object *op) {
407  /*
408  * Ok I /suppose/ I should write a seperate function for this, but it isn't
409  * going to be /that/ slow, and won't get called much
410  */
412 
413  /* This should only be possible if regions are not operating on this server. */
414  if (!r)
415  return;
416 
418  "You are in %s.\n%s",
420 }
421 
428 static void current_map_info(object *op) {
429  mapstruct *m = op->map;
430 
431  if (!m)
432  return;
433 
435  "%s (%s) in %s",
436  m->name, m->path, get_region_longname(get_region_by_map(m)));
437 
438  if (QUERY_FLAG(op, FLAG_WIZ)) {
440  "players:%d difficulty:%d size:%dx%d start:%dx%d timeout %d reset_group: %s",
441  m->players, m->difficulty,
442  MAP_WIDTH(m), MAP_HEIGHT(m),
444  MAP_TIMEOUT(m), m->reset_group ? m->reset_group : "(none)");
445  }
446  if (m->msg)
448 }
449 
450 #ifdef DEBUG_MALLOC_LEVEL
451 
459 void command_malloc_verify(object *op, char *parms) {
460  extern int malloc_verify(void);
461 
462  if (!malloc_verify())
464  "Heap is corrupted.");
465  else
467  "Heap checks out OK.");
468 
469  return 1;
470 }
471 #endif
472 
483 void command_whereabouts(object *op, const char *params) {
484  region *reg;
485  player *pl;
486  (void)params;
487 
488  /*
489  * reset the counter on the region, then use it to store the number of
490  * players there.
491  * I don't know how thread-safe this would be, I suspect not very....
492  */
493  for (reg = first_region; reg != NULL; reg = reg->next) {
494  reg->counter = 0;
495  }
496  for (pl = first_player; pl != NULL; pl = pl->next)
497  if (pl->ob->map != NULL)
499 
500  /* we only want to print out by places with a 'longname' field...*/
501  for (reg = first_region; reg != NULL; reg = reg->next) {
502  if (reg->longname == NULL && reg->counter > 0) {
503  if (reg->parent != NULL) {
504  reg->parent->counter += reg->counter;
505  reg->counter = 0;
506  } else /*uh oh, we shouldn't be here. */
507  LOG(llevError, "command_whereabouts() Region %s with no longname has no parent\n", reg->name);
508  }
509  }
511  "In the world currently there are:");
512 
513  for (reg = first_region; reg != NULL; reg = reg->next)
514  if (reg->counter > 0) {
516  "%u players in %s",
517  reg->counter, get_region_longname(reg));
518  }
519 }
520 
522 typedef struct {
523  char namebuf[MAX_BUF];
525 } chars_names;
526 
536 static int name_cmp(const chars_names *c1, const chars_names *c2) {
537  return strcasecmp(c1->namebuf, c2->namebuf);
538 }
539 
550 void list_players(object *op, region *reg, partylist *party) {
551  player *pl;
552  uint16_t i;
553  char *format;
554  int num_players = 0, num_wiz = 0, num_afk = 0, num_bot = 0;
555  chars_names *chars = NULL;
556 
557  if (op == NULL || QUERY_FLAG(op, FLAG_WIZ))
558  format = settings.who_wiz_format;
559  else
560  format = settings.who_format;
561 
562  for (pl = first_player; pl != NULL; pl = pl->next) {
563  if (pl->ob->map == NULL)
564  continue;
565  if (pl->hidden && !QUERY_FLAG(op, FLAG_WIZ))
566  continue;
567 
568  if (reg && !region_is_child_of_region(get_region_by_map(pl->ob->map), reg))
569  continue;
570  if (party && pl->party != party)
571  continue;
572 
573  if (pl->state == ST_PLAYING || pl->state == ST_GET_PARTY_PASSWORD) {
574  num_players++;
575  chars = (chars_names *)realloc(chars, num_players*sizeof(chars_names));
576  if (chars == NULL) {
578  "who failed - out of memory!");
579  return;
580  }
581  sprintf(chars[num_players-1].namebuf, "%s", pl->ob->name);
582  chars[num_players-1].login_order = num_players;
583 
584  /* Check for WIZ's & AFK's*/
585  if (QUERY_FLAG(pl->ob, FLAG_WIZ))
586  num_wiz++;
587 
588  if (QUERY_FLAG(pl->ob, FLAG_AFK))
589  num_afk++;
590 
591  if (pl->socket.is_bot)
592  num_bot++;
593  }
594  }
595  if (first_player != (player *)NULL) {
596  if (reg == NULL && party == NULL)
598  "Total Players (%d) -- WIZ(%d) AFK(%d) BOT(%d)",
599  num_players, num_wiz, num_afk, num_bot);
600  else if (party == NULL)
602  "Total Players in %s (%d) -- WIZ(%d) AFK(%d) BOT(%d)",
603  reg->longname ? reg->longname : reg->name, num_players, num_wiz, num_afk, num_bot);
604  else
606  "Total Players in party %s (%d) -- WIZ(%d) AFK(%d) BOT(%d)",
607  party->partyname, num_players, num_wiz, num_afk, num_bot);
608  }
609  qsort(chars, num_players, sizeof(chars_names), (int (*)(const void *, const void *))name_cmp);
610  for (i = 0; i < num_players; i++)
611  display_who_entry(op, find_player(chars[i].namebuf), format);
612  free(chars);
613 }
614 
623 void command_who(object *op, const char *params) {
624  region *reg;
625 
627  list_players(op, reg, NULL);
628 }
629 
640 static void display_who_entry(object *op, player *pl, const char *format) {
641  char tmpbuf[MAX_BUF];
642  char outbuf[MAX_BUF];
643  size_t i;
644 
645  strcpy(outbuf, "[fixed]");
646 
647  if (pl == NULL) {
648  LOG(llevError, "display_who_entry(): I was passed a null player\n");
649  return;
650  }
651  for (i = 0; i <= strlen(format); i++) {
652  if (format[i] == '%') {
653  i++;
654  get_who_escape_code_value(tmpbuf, sizeof(tmpbuf), format[i], pl);
655  strcat(outbuf, tmpbuf);
656  } else if (format[i] == '_') {
657  strcat(outbuf, " "); /* allow '_' to be used in place of spaces */
658  } else {
659  snprintf(tmpbuf, sizeof(tmpbuf), "%c", format[i]);
660  strcat(outbuf, tmpbuf);
661  }
662  }
664 }
665 
696 static void get_who_escape_code_value(char *return_val, int size, const char letter, player *pl) {
697  switch (letter) {
698  case 'N':
699  strlcpy(return_val, pl->ob->name, size);
700  break;
701 
702  case 't':
703  player_get_title(pl, return_val, size);
704  break;
705 
706  case 'c':
707  snprintf(return_val, size, "%u", pl->ob->count);
708  break;
709 
710  case 'n':
711  snprintf(return_val, size, "\n");
712  break;
713 
714  case 'h':
715  strlcpy(return_val, pl->peaceful ? "" : " <Hostile>", size);
716  break;
717 
718  case 'l':
719  snprintf(return_val, size, "%d", pl->ob->level);
720  break;
721 
722  case 'd':
723  strlcpy(return_val, (QUERY_FLAG(pl->ob, FLAG_WIZ) ? " <WIZ>" : ""), size);
724  break;
725 
726  case 'a':
727  strlcpy(return_val, (QUERY_FLAG(pl->ob, FLAG_AFK) ? " <AFK>" : ""), size);
728  break;
729 
730  case 'b':
731  strlcpy(return_val, (pl->socket.is_bot == 1) ? " <BOT>" : "", size);
732  break;
733 
734  case 'm':
735  strlcpy(return_val, pl->ob->map->path, size);
736  break;
737 
738  case 'M':
739  strlcpy(return_val, pl->ob->map->name ? pl->ob->map->name : "Untitled", size);
740  break;
741 
742  case 'r':
743  strlcpy(return_val, get_name_of_region_for_map(pl->ob->map), size);
744  break;
745 
746  case 'R':
747  strlcpy(return_val, get_region_longname(get_region_by_map(pl->ob->map)), size);
748  break;
749 
750  case 'i':
751  strlcpy(return_val, pl->socket.host, size);
752  break;
753 
754  case '%':
755  snprintf(return_val, size, "%%");
756  break;
757 
758  case '_':
759  snprintf(return_val, size, "_");
760  break;
761  }
762 }
763 
772 void command_afk(object *op, const char *params) {
773  (void)params;
774  if (QUERY_FLAG(op, FLAG_AFK)) {
777  "You are no longer AFK");
778  } else {
779  SET_FLAG(op, FLAG_AFK);
781  "You are now AFK");
782  }
783 }
784 
793 void command_malloc(object *op, const char *params) {
794  (void)params;
795  malloc_info(op);
796 }
797 
806 void command_mapinfo(object *op, const char *params) {
807  (void)params;
809 }
810 
819 void command_whereami(object *op, const char *params) {
820  (void)params;
822 }
823 
832 void command_maps(object *op, const char *params) {
833  map_info(op, params);
834 }
835 
844 void command_strings(object *op, const char *params) {
845  char stats[HUGE_BUF];
846  (void)params;
847 
848  ss_dump_statistics(stats, sizeof(stats));
850  "[fixed]%s\n",
851  stats);
852 
854  ss_dump_table(SS_DUMP_TOTALS, stats, sizeof(stats)));
855 }
856 
865 void command_time(object *op, const char *params) {
866  (void)params;
867  time_info(op);
868 }
869 
878 void command_hiscore(object *op, const char *params) {
879  hiscore_display(op, op == NULL ? 9999 : 50, params);
880 }
881 
890 void command_debug(object *op, const char *params) {
891  int i;
892 
893  if (*params == '\0' || !sscanf(params, "%d", &i)) {
895  "Global debug level is %d.",
896  settings.debug);
897  return;
898  }
899  settings.debug = (enum LogLevel)FABS(i);
901  "Debug level set to %d.",
902  i);
903 }
904 
905 
914 void command_wizpass(object *op, const char *params) {
915  int i;
916 
917  if (!op)
918  return;
919 
920  if (*params == '\0')
921  i = (QUERY_FLAG(op, FLAG_WIZPASS)) ? 0 : 1;
922  else
923  i = onoff_value(params);
924 
925  if (i) {
927  "You will now walk through walls.");
929  } else {
931  "You will now be stopped by walls.");
933  }
934 }
935 
944 void command_wizcast(object *op, const char *params) {
945  int i;
946 
947  if (!op)
948  return;
949 
950  if (*params == '\0')
951  i = (QUERY_FLAG(op, FLAG_WIZCAST)) ? 0 : 1;
952  else
953  i = onoff_value(params);
954 
955  if (i) {
957  "You can now cast spells anywhere.");
959  } else {
961  "You now cannot cast spells in no-magic areas.");
963  }
964 }
965 
974 void command_dumpallobjects(object *op, const char *params) {
975  (void)op;
976  (void)params;
977  object_dump_all();
978 }
979 
988 void command_dumpfriendlyobjects(object *op, const char *params) {
989  (void)op;
990  (void)params;
992 }
993 
1002 void command_dumpallarchetypes(object *op, const char *params) {
1003  (void)op;
1004  (void)params;
1006 }
1007 
1016 void command_ssdumptable(object *op, const char *params) {
1017  (void)op;
1018  (void)params;
1019  ss_dump_table(SS_DUMP_TABLE, NULL, 0);
1020 }
1021 
1030 void command_dumpmap(object *op, const char *params) {
1031  (void)params;
1032  if (op)
1033  dump_map(op->map);
1034 }
1035 
1044 void command_dumpallmaps(object *op, const char *params) {
1045  (void)op;
1046  (void)params;
1047  dump_all_maps();
1048 }
1049 
1058 void command_printlos(object *op, const char *params) {
1059  (void)params;
1060  if (op)
1061  print_los(op);
1062 }
1063 
1064 
1073 void command_version(object *op, const char *params) {
1074  (void)params;
1076  MSG_TYPE_ADMIN_VERSION, "Crossfire "FULL_VERSION);
1077 }
1078 
1087 void command_listen(object *op, const char *params) {
1088  int i;
1089 
1090  if (*params == '\0' || !sscanf(params, "%d", &i)) {
1092  "Set listen to what (presently %d)?",
1093  op->contr->listening);
1094  return;
1095  }
1096  if (i < 0) {
1098  "Verbose level should be positive.");
1099  return;
1100  }
1101  op->contr->listening = (char)i;
1103  "Your verbose level is now %d.",
1104  i);
1105 }
1106 
1118 void command_statistics(object *pl, const char *params) {
1119  char buf[MAX_BUF];
1120  uint32_t hours, minutes;
1121  uint64_t seconds; /* 64 bit to prevent overflows an intermediate results */
1122  (void)params;
1123 
1124  if (!pl->contr)
1125  return;
1126  safe_strncpy(buf, i18n(pl, "[fixed] Experience: %"), sizeof(buf));
1127  strcat(buf, FMT64);
1129  buf,
1130  pl->stats.exp);
1131  safe_strncpy(buf, i18n(pl, "[fixed] Next Level: %"), sizeof(buf));
1132  strcat(buf, FMT64);
1134  buf,
1135  level_exp(pl->level+1, pl->expmul));
1136 
1138  "[fixed]\nStat Nat/Real/Max");
1139 
1141  "[fixed]Str %2d/ %3d/%3d",
1142  pl->contr->orig_stats.Str, pl->stats.Str, 20+pl->arch->clone.stats.Str);
1144  "[fixed]Dex %2d/ %3d/%3d",
1145  pl->contr->orig_stats.Dex, pl->stats.Dex, 20+pl->arch->clone.stats.Dex);
1147  "[fixed]Con %2d/ %3d/%3d",
1148  pl->contr->orig_stats.Con, pl->stats.Con, 20+pl->arch->clone.stats.Con);
1150  "[fixed]Int %2d/ %3d/%3d",
1151  pl->contr->orig_stats.Int, pl->stats.Int, 20+pl->arch->clone.stats.Int);
1153  "[fixed]Wis %2d/ %3d/%3d",
1154  pl->contr->orig_stats.Wis, pl->stats.Wis, 20+pl->arch->clone.stats.Wis);
1156  "[fixed]Pow %2d/ %3d/%3d",
1157  pl->contr->orig_stats.Pow, pl->stats.Pow, 20+pl->arch->clone.stats.Pow);
1159  "[fixed]Cha %2d/ %3d/%3d",
1160  pl->contr->orig_stats.Cha, pl->stats.Cha, 20+pl->arch->clone.stats.Cha);
1162  "\nAttack Mode: %s",
1163  i18n(pl, pl->contr->peaceful ? "Peaceful" : "Hostile"));
1167  float weap_speed = pl->weapon_speed; // This is the number of attacks per tick.
1168  if (weap_speed < 0.0f)
1169  weap_speed = 0.0f;
1170  if (weap_speed > 1.0f)
1171  weap_speed = 1.0f;
1172  // We will initially calculate the damage if every attack you perform hits.
1173  // This will serve as a baseline for future calculations
1174  float dps = (1000000.0f / tick_duration) * weap_speed * pl->stats.dam;
1175  // TODO: Account for opposing AC in calculations, make some sort of table/chart.
1176  // Then we round the floating-point.
1178  "\n\nDam/Sec: %4d", (int)(dps + 0.5f));
1179 
1180  /* max_time is in microseconds - thus divide by 1000000.
1181  * Need 64 bit values, as otherwise ticks_played * max_time
1182  * can easily overflow.
1183  * Note the message displayed here isn't really
1184  * perfect, since if max_time has been changed since the player started,
1185  * the time estimates use the current value. But I'm presuming that
1186  * max_time won't change very often. MSW 2009-12-01
1187  */
1188  seconds = (uint64_t)pl->contr->ticks_played * (uint64_t)tick_duration / 1000000;
1189  minutes = (uint32_t)seconds / 60;
1190  hours = minutes / 60;
1191  minutes = minutes % 60;
1192 
1194  "You have played this character for %u ticks, which amounts "
1195  "to %d hours and %d minutes.",
1196  pl->contr->ticks_played, hours, minutes);
1197 
1198 
1199  /* Can't think of anything else to print right now */
1200 }
1201 
1210 void command_fix_me(object *op, const char *params) {
1211  (void)params;
1213  fix_object(op);
1214 }
1215 
1224 void command_players(object *op, const char *params) {
1225  char buf[MAX_BUF];
1226  char *t;
1227  DIR *dir;
1228  (void)params;
1229 
1230  snprintf(buf, sizeof(buf), "%s/%s/", settings.localdir, settings.playerdir);
1231  t = buf+strlen(buf);
1232  if ((dir = opendir(buf)) != NULL) {
1233  const struct dirent *entry;
1234 
1235  while ((entry = readdir(dir)) != NULL) {
1236  /* skip '.' , '..' */
1237  if (!((entry->d_name[0] == '.' && entry->d_name[1] == '\0')
1238  || (entry->d_name[0] == '.' && entry->d_name[1] == '.' && entry->d_name[2] == '\0'))) {
1239  struct stat st;
1240 
1241  strcpy(t, entry->d_name);
1242  if (stat(buf, &st) == 0) {
1243  /* This was not posix compatible
1244  * if ((st.st_mode & S_IFMT)==S_IFDIR) {
1245  */
1246  if (S_ISDIR(st.st_mode)) {
1247  struct tm *tm = localtime(&st.st_mtime);
1248 
1250  "[fixed]%s\t%04d %02d %02d %02d %02d %02d",
1251  entry->d_name,
1252  1900+tm->tm_year,
1253  1+tm->tm_mon,
1254  tm->tm_mday,
1255  tm->tm_hour,
1256  tm->tm_min,
1257  tm->tm_sec);
1258  }
1259  }
1260  }
1261  }
1262  }
1263  closedir(dir);
1264 }
1265 
1274 void command_applymode(object *op, const char *params) {
1275  unapplymode unapply = op->contr->unapply;
1276  static const char *const types[] = {
1277  "nochoice",
1278  "never",
1279  "always"
1280  };
1281 
1282  if (*params == '\0') {
1284  "applymode is set to %s",
1285  types[op->contr->unapply]);
1286  return;
1287  }
1288 
1289  if (!strcmp(params, "nochoice"))
1290  op->contr->unapply = unapply_nochoice;
1291  else if (!strcmp(params, "never"))
1292  op->contr->unapply = unapply_never;
1293  else if (!strcmp(params, "always"))
1294  op->contr->unapply = unapply_always;
1295  else {
1297  "applymode: Unknown options %s, valid options are nochoice, never, always",
1298  params);
1299  return;
1300  }
1302  "applymode%s set to %s",
1303  (unapply == op->contr->unapply ? "" : " now"),
1304  types[op->contr->unapply]);
1305 }
1306 
1315 void command_bowmode(object *op, const char *params) {
1316  bowtype_t oldtype = op->contr->bowtype;
1317  static const char *const types[] = {
1318  "normal",
1319  "threewide",
1320  "spreadshot",
1321  "firenorth",
1322  "firene",
1323  "fireeast",
1324  "firese",
1325  "firesouth",
1326  "firesw",
1327  "firewest",
1328  "firenw",
1329  "bestarrow"
1330  };
1331  int i, found;
1332 
1333  if (*params == '\0') {
1335  "bowmode is set to %s",
1336  types[op->contr->bowtype]);
1337  return;
1338  }
1339 
1340  for (i = 0, found = 0; i <= bow_bestarrow; i++) {
1341  if (!strcmp(params, types[i])) {
1342  found++;
1343  op->contr->bowtype = i;
1344  break;
1345  }
1346  }
1347  if (!found) {
1349  stringbuffer_append_printf(buf, "bowmode: Unknown options %s, valid options are:", params);
1350  for (i = 0; i <= bow_bestarrow; i++) {
1353  if (i < bow_nw)
1355  else
1357  }
1358  char *result = stringbuffer_finish(buf);
1360  free(result);
1361  return;
1362  }
1364  "bowmode%s set to %s",
1365  (oldtype == op->contr->bowtype ? "" : " now"),
1366  types[op->contr->bowtype]);
1367  return;
1368 }
1369 
1378 void command_unarmed_skill(object *op, const char *params) {
1379  object *skill;
1380  size_t i;
1381 
1382  if (*params == '\0') {
1384  "unarmed skill is set to %s",
1385  op->contr->unarmed_skill ? op->contr->unarmed_skill: "nothing");
1386  return;
1387  }
1388 
1389  /* find_skill_by_name() will ready any skill tools - which
1390  * is OK for us because no unarmed skills require skill tools,
1391  * but this could be an issue if you reuse this code for other skills.
1392  */
1393  skill = find_skill_by_name(op, params);
1394 
1395  if (!skill) {
1397  "You do not know any such skill called %s",
1398  params);
1399  return;
1400  }
1401  for (i = 0; i < sizeof(unarmed_skills); i++)
1402  if (skill->subtype == unarmed_skills[i])
1403  break;
1404  if (i == sizeof(unarmed_skills)) {
1406  "%s is not an unarmed skill!",
1407  skill->name);
1408  return;
1409 
1410  }
1411 
1412  if (op->contr->unarmed_skill)
1413  free_string(op->contr->unarmed_skill);
1414 
1415  /* Taking actual skill name is better than taking params,
1416  * as params could be something more than an exact skill name.
1417  */
1418  op->contr->unarmed_skill = add_string(skill->name);
1419 
1421  "unarmed skill is now set to %s",
1422  op->contr->unarmed_skill);
1423 }
1424 
1425 
1434 void command_petmode(object *op, const char *params) {
1435  petmode_t oldtype = op->contr->petmode;
1436  static const char *const types[] = {
1437  "normal",
1438  "sad",
1439  "defend",
1440  "arena"
1441  };
1442 
1443  if (*params == '\0') {
1445  "petmode is set to %s",
1446  types[op->contr->petmode]);
1447  return;
1448  }
1449 
1450  if (!strcmp(params, "normal"))
1451  op->contr->petmode = pet_normal;
1452  else if (!strcmp(params, "sad"))
1453  op->contr->petmode = pet_sad;
1454  else if (!strcmp(params, "defend"))
1455  op->contr->petmode = pet_defend;
1456  else if (!strcmp(params, "arena"))
1457  op->contr->petmode = pet_arena;
1458  else {
1460  "petmode: Unknown options %s, valid options are normal, sad (seek and destroy), defend, arena",
1461  params);
1462  return;
1463  }
1465  "petmode%s set to %s",
1466  (oldtype == op->contr->petmode ? "" : " now"),
1467  types[op->contr->petmode]);
1468 }
1469 
1478 void command_showpets(object *op, const char *params) {
1479  objectlink *obl, *list;
1480  int counter = 0, target = 0;
1481  int have_shown_pet = 0;
1482  if (*params != '\0')
1483  target = atoi(params);
1484 
1485  list = get_friends_of(op);
1486 
1487  for (obl = list; obl != NULL; obl = obl->next) {
1488  object *ob = obl->ob;
1489 
1490  if (target == 0) {
1491  if (counter == 0)
1493  "Pets:");
1495  "%d %s - level %d",
1496  ++counter, ob->name, ob->level);
1497  } else if (!have_shown_pet && ++counter == target) {
1499  "[fixed]level %d %s",
1500  ob->level, ob->name);
1502  "[fixed]%d/%d HP, %d/%d SP",
1503  ob->stats.hp, ob->stats.maxhp, ob->stats.sp, ob->stats.maxsp);
1504 
1505  /* this is not a nice way to do this, it should be made to be more like the statistics command */
1507  "[fixed]Str %d",
1508  ob->stats.Str);
1510  "[fixed]Dex %d",
1511  ob->stats.Dex);
1513  "[fixed]Con %d",
1514  ob->stats.Con);
1516  "[fixed]Int %d",
1517  ob->stats.Int);
1519  "[fixed]Wis %d",
1520  ob->stats.Wis);
1522  "[fixed]Cha %d",
1523  ob->stats.Cha);
1525  "[fixed]Pow %d",
1526  ob->stats.Pow);
1528  "[fixed]wc %d damage %d ac %d",
1529  ob->stats.wc, ob->stats.dam, ob->stats.ac);
1530  have_shown_pet = 1;
1531  }
1532  }
1533  if (list) {
1535  }
1536 
1537  if (counter == 0)
1539  "You have no pets.");
1540  else if (target != 0 && have_shown_pet == 0)
1542  "No such pet.");
1543 }
1544 
1553 void command_usekeys(object *op, const char *params) {
1554  usekeytype oldtype = op->contr->usekeys;
1555  static const char *const types[] = {
1556  "inventory",
1557  "keyrings",
1558  "containers"
1559  };
1560 
1561  if (*params == '\0') {
1563  "usekeys is set to %s",
1564  types[op->contr->usekeys]);
1565  return;
1566  }
1567 
1568  if (!strcmp(params, "inventory"))
1569  op->contr->usekeys = key_inventory;
1570  else if (!strcmp(params, "keyrings"))
1571  op->contr->usekeys = keyrings;
1572  else if (!strcmp(params, "containers"))
1573  op->contr->usekeys = containers;
1574  else {
1576  "usekeys: Unknown option %s, valid options are inventory, keyrings, containers",
1577  params);
1578  return;
1579  }
1581  "usekeys%s set to %s",
1582  (oldtype == op->contr->usekeys ? "" : " now"),
1583  types[op->contr->usekeys]);
1584 }
1585 
1594 void command_resistances(object *op, const char *params) {
1595  int i;
1596  (void)params;
1597  if (!op)
1598  return;
1599 
1600  for (i = 0; i < NROFATTACKS; i++) {
1601  if (i == ATNR_INTERNAL)
1602  continue;
1603 
1605  "[fixed]%-20s %+5d",
1606  attacktype_desc[i], op->resist[i]);
1607  }
1608 
1609  /* If dragon player, let's display natural resistances */
1610  if (is_dragon_pl(op)) {
1611  int attack;
1612  object *tmp;
1613 
1614  tmp = object_find_by_type_and_arch_name(op, FORCE, "dragon_skin_force");
1615  if (tmp != NULL) {
1617  "\nNatural skin resistances:");
1618 
1619  for (attack = 0; attack < NROFATTACKS; attack++) {
1620  if (atnr_is_dragon_enabled(attack)) {
1622  "%s: %d",
1623  change_resist_msg[attack], tmp->resist[attack]);
1624  }
1625  }
1626  }
1627  }
1628 }
1629 
1640 static void help_topics(object *op, int what) {
1641  DIR *dirp;
1642  struct dirent *de;
1643  char filename[MAX_BUF], line[HUGE_BUF];
1644  char suffix[MAX_BUF];
1645  int namelen;
1646  const char *language;
1647 
1648  language = i18n_get_language_code(op->contr->language);
1649  snprintf(suffix, sizeof(suffix), ".%s", language);
1650 
1651  switch (what) {
1652  case 1:
1653  snprintf(filename, sizeof(filename), "%s/wizhelp", settings.datadir);
1655  " Wiz commands:");
1656  break;
1657 
1658  case 3:
1659  snprintf(filename, sizeof(filename), "%s/mischelp", settings.datadir);
1661  " Misc help:");
1662  break;
1663 
1664  default:
1665  snprintf(filename, sizeof(filename), "%s/help", settings.datadir);
1667  " Commands:");
1668  break;
1669  }
1670  if (!(dirp = opendir(filename)))
1671  return;
1672 
1673  line[0] = '\0';
1674  for (de = readdir(dirp); de; de = readdir(dirp)) {
1675  namelen = NAMLEN(de);
1676 
1677  if (namelen <= 2
1678  && *de->d_name == '.'
1679  && (namelen == 1 || de->d_name[1] == '.'))
1680  continue;
1681  if (strstr(de->d_name, suffix)) {
1682  strcat(line, strtok(de->d_name, "."));
1683  strcat(line, " ");
1684  }
1685  }
1687  line);
1688  closedir(dirp);
1689 }
1690 
1700 static int find_help_file_in(const char *dir, const char *name, const char *language, char *path, int length) {
1701  struct stat st;
1702 
1703  snprintf(path, length, "%s/%s/%s.%s", settings.datadir, dir, name, language);
1704  if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) {
1705  return 1;
1706  }
1707  return 0;
1708 }
1709 
1723 static int find_help_file(const char *name, const char *language, int wiz, char *path, int length) {
1724  if (wiz) {
1725  if (find_help_file_in("wizhelp", name, language, path, length))
1726  return 1;
1727  if (strcmp(language, "en") && find_help_file_in("wizhelp", name, "en", path, length))
1728  return 1;
1729  }
1730 
1731  if (find_help_file_in("help", name, language, path, length))
1732  return 1;
1733  if (strcmp(language, "en") && find_help_file_in("help", name, "en", path, length))
1734  return 1;
1735 
1736  return 0;
1737 }
1738 
1746 static void display_help_file(object *op, const char *filename) {
1747  BufferReader *br;
1748  const char *line;
1749 
1750  if ((br = bufferreader_init_from_file(NULL, filename, "Cannot open help file %s: %s\n", llevError)) == NULL) {
1751  return;
1752  }
1753 
1754  while ((line = bufferreader_next_line(br))) {
1756  }
1757 
1759 }
1760 
1769 void command_help(object *op, const char *params) {
1770  char filename[MAX_BUF];
1771  const char *language;
1772 
1773  /*
1774  * Main help page?
1775  */
1776  if (*params == '\0') {
1777  snprintf(filename, sizeof(filename), "%s/def_help", settings.datadir);
1779  return;
1780  }
1781 
1782  /*
1783  * Topics list
1784  */
1785  if (!strcmp(params, "topics")) {
1786  help_topics(op, 3);
1787  help_topics(op, 0);
1788  if (QUERY_FLAG(op, FLAG_WIZ))
1789  help_topics(op, 1);
1790  return;
1791  }
1792 
1793  /*
1794  * Commands list
1795  */
1796  if (!strcmp(params, "commands")) {
1798  return;
1799  }
1800 
1801  /*
1802  * User wants info about command
1803  */
1804  if (strchr(params, '.') || strchr(params, ' ') || strchr(params, '/')) {
1806  "Illegal characters in '%s'",
1807  params);
1808  return;
1809  }
1810 
1811  language = i18n_get_language_code(op->contr->language);
1812 
1813  if (!find_help_file(params, language, QUERY_FLAG(op, FLAG_WIZ), filename, sizeof(filename))) {
1815  "No help available on '%s'",
1816  params);
1817  return;
1818  }
1819 
1820  /*
1821  * Found that. Just cat it to screen.
1822  */
1824 }
1825 
1836 static int onoff_value(const char *line) {
1837  int i;
1838 
1839  if (sscanf(line, "%d", &i))
1840  return (i != 0);
1841 
1842  switch (line[0]) {
1843  case 'o':
1844  switch (line[1]) {
1845  case 'n':
1846  return 1; /* on */
1847  default:
1848  return 0; /* o[ff] */
1849  }
1850 
1851  case 'y': /* y[es] */
1852  case 'k': /* k[ylla] */
1853  case 's':
1854  case 'd':
1855  return 1;
1856 
1857  case 'n': /* n[o] */
1858  case 'e': /* e[i] */
1859  case 'u':
1860  default:
1861  return 0;
1862  }
1863 }
1864 
1870 void command_quit(object* op, const char* params) {
1871  (void)params;
1872  draw_ext_info(
1874  "To leave the game, sleep in (apply) a bed to reality. To "
1875  "permenantly delete your character, use the 'delete' command.");
1876 }
1877 
1886 void command_delete(object *op, const char *params) {
1887  (void)params;
1888  if (QUERY_FLAG(op, FLAG_WIZ)) {
1889  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_ADMIN_DM, "Can't quit when in DM mode.");
1890  return;
1891  }
1892 
1893  send_query(&op->contr->socket, CS_QUERY_SINGLECHAR,
1894  i18n(op, "Quitting will delete your character.\nAre you sure you want to delete your character (y/n):"));
1895 
1897 }
1898 
1907 void command_sound(object *op, const char *params) {
1908  (void)params;
1909  if (!(op->contr->socket.sound&SND_MUTE)) {
1910  op->contr->socket.sound = op->contr->socket.sound|SND_MUTE;
1912  "Sounds are turned off.");
1913  } else {
1914  op->contr->socket.sound = op->contr->socket.sound&~SND_MUTE;
1916  "The sounds are enabled.");
1917  }
1918  return;
1919 }
1920 
1932 void receive_player_name(object *op, const char *name) {
1933  if (!check_name(op->contr, name)) {
1934  get_name(op);
1935  return;
1936  }
1937  FREE_AND_COPY(op->name, name);
1938  FREE_AND_COPY(op->name_pl, name);
1940  op->contr->name_changed = 1;
1941  get_password(op);
1942 }
1943 
1952 void receive_player_password(object *op, const char *password) {
1953  unsigned int pwd_len = strlen(password);
1954 
1955  if (pwd_len == 0 || pwd_len > 16) {
1956  if (op->contr->state == ST_CHANGE_PASSWORD_OLD
1957  || op->contr->state == ST_CHANGE_PASSWORD_NEW
1958  || op->contr->state == ST_CHANGE_PASSWORD_CONFIRM) {
1960  "Password changed cancelled.");
1961  player_set_state(op->contr, ST_PLAYING);
1962  } else
1963  get_name(op);
1964  return;
1965  }
1966  /* To hide the password better */
1967  /* With currently clients, not sure if this is really the case - MSW */
1969 
1970  if (checkbanned(op->name, op->contr->socket.host)) {
1971  LOG(llevInfo, "Banned player tried to add: [%s@%s]\n", op->name, op->contr->socket.host);
1973  "You are not allowed to play.");
1974  get_name(op);
1975  return;
1976  }
1977 
1978  if (op->contr->state == ST_CONFIRM_PASSWORD) {
1979  if (!check_password(password, op->contr->password)) {
1981  "The passwords did not match.");
1982  get_name(op);
1983  return;
1984  }
1985  LOG(llevInfo, "LOGIN: New player named %s from ip %s\n", op->name, op->contr->socket.host);
1986  display_motd(op);
1988  "\nWelcome, Brave New Warrior!\n");
1989  roll_again(op);
1990  player_set_state(op->contr, ST_ROLL_STAT);
1991  return;
1992  }
1993 
1994  if (op->contr->state == ST_CHANGE_PASSWORD_OLD) {
1995  if (!check_password(password, op->contr->password)) {
1997  "You entered the wrong current password.");
1998  player_set_state(op->contr, ST_PLAYING);
1999  } else {
2000  send_query(&op->contr->socket, CS_QUERY_HIDEINPUT, i18n(op, "Please enter your new password, or blank to cancel:"));
2002  }
2003  return;
2004  }
2005 
2006  if (op->contr->state == ST_CHANGE_PASSWORD_NEW) {
2007  safe_strncpy(op->contr->new_password, newhash(password),
2008  sizeof(op->contr->new_password));
2009  send_query(&op->contr->socket, CS_QUERY_HIDEINPUT,
2010  i18n(op, "Please confirm your new password, or blank to cancel:"));
2012  return;
2013  }
2014 
2015  if (op->contr->state == ST_CHANGE_PASSWORD_CONFIRM) {
2016  if (!check_password(password, op->contr->new_password)) {
2018  "The new passwords don't match!");
2019  } else {
2021  "Password changed.");
2022  strncpy(op->contr->password, op->contr->new_password, 13);
2023  }
2024  player_set_state(op->contr, ST_PLAYING);
2025  return;
2026  }
2027 
2028  safe_strncpy(op->contr->password, newhash(password),
2029  sizeof(op->contr->password));
2030  player_set_state(op->contr, ST_ROLL_STAT);
2031  check_login(op, password);
2032 }
2033 
2044 void command_title(object *op, const char *params) {
2045  char buf[MAX_BUF];
2046 
2047  if (settings.set_title == FALSE) {
2049  "You cannot change your title.");
2050  return;
2051  }
2052 
2053  /* dragon players cannot change titles */
2054  if (is_dragon_pl(op)) {
2056  "Dragons cannot change titles.");
2057  return;
2058  }
2059 
2060  if (*params == '\0') {
2061  char tmp[MAX_BUF];
2062 
2063  player_get_title(op->contr, tmp, sizeof(tmp));
2064  snprintf(buf, sizeof(buf), "Your title is '%s'.", tmp);
2066  return;
2067  }
2068  if (strcmp(params, "clear") == 0 || strcmp(params, "default") == 0) {
2069  if (!player_has_own_title(op->contr))
2071  "Your title is the default title.");
2072  else
2074  "Title set to default.");
2075  player_set_own_title(op->contr, "");
2076  return;
2077  }
2078 
2079  if ((int)strlen(params) >= MAX_NAME) {
2081  "Title too long.");
2082  return;
2083  }
2084  player_set_own_title(op->contr, params);
2085 }
2086 
2095 void command_save(object *op, const char *params) {
2096  (void)params;
2097  if (get_map_flags(op->map, NULL, op->x, op->y, NULL, NULL)&P_NO_CLERIC) {
2099  "You can not save on unholy ground.");
2100  } else if (!op->stats.exp) {
2102  "You don't deserve to save yet.");
2103  } else {
2104  if (save_player(op, 1))
2106  "You have been saved.");
2107  else
2109  "SAVE FAILED!");
2110  }
2111 }
2112 
2121 void command_peaceful(object *op, const char *params) {
2122  (void)params;
2123  if ((op->contr->peaceful = !op->contr->peaceful))
2125  "You will not attack other players.");
2126  else
2128  "You will attack other players.");
2129 }
2130 
2139 void command_wimpy(object *op, const char *params) {
2140  int i;
2141 
2142  if (*params == '\0' || !sscanf(params, "%d", &i)) {
2144  "Your current wimpy level is %d.",
2145  op->run_away);
2146  return;
2147  }
2148 
2149  if (i < 0 || i > 100) {
2151  "Wimpy level should be between 1 and 100.",
2152  i);
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') {
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  if (!QUERY_FLAG(ob, FLAG_REMOVED))
2209  object_remove(ob);
2212  removecount++;
2213  }
2214  }
2215  }
2216  if (list) {
2218  }
2219  if (removecount != 0)
2221  "Killed %d pets.",
2222  removecount);
2223  else
2225  "Couldn't find any suitable pets to kill.");
2226  }
2227 }
2228 
2237 void command_passwd(object *pl, const char *params) {
2238  (void)params;
2239  /* If old client, this is the way you change your password. */
2240  if (pl->contr->socket.login_method < 1){
2241  send_query(&pl->contr->socket, CS_QUERY_HIDEINPUT, i18n(pl, "Password change.\nPlease enter your current password, or empty string to cancel."));
2242 
2244  }
2245  /* If new client (login_method = 2) or jxclient (login_method = 1), changing the password does nothing anyway, so error out */
2246  else{
2248  "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.");
2249  }
2250 }
2251 
2261 void do_harvest(object *pl, int dir, object *skill) {
2262  int16_t x, y;
2263  int count = 0, proba; /* Probability to get the item, 100 based. */
2264  int level, exp, check_exhaust = 0;
2265  object *found[10]; /* Found items that can be harvested. */
2266  mapstruct *map;
2267  object *item, *inv, *harvested;
2268  sstring trace, ttool, tspeed, race, tool, slevel, sexp;
2269  float speed;
2270 
2271  x = pl->x+freearr_x[dir];
2272  y = pl->y+freearr_y[dir];
2273  map = pl->map;
2274 
2275  if (!IS_PLAYER(pl))
2276  return;
2277 
2278  if (!map)
2279  return;
2280 
2281  if (get_map_flags(map, &map, x, y, &x, &y)&P_OUT_OF_MAP) {
2282  draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, i18n(pl, "You cannot %s here."), skill->slaying);
2283  return;
2284  }
2285 
2286  if (!pl->chosen_skill || pl->chosen_skill->skill != skill->skill)
2287  return;
2288 
2289  trace = object_get_value(pl->chosen_skill, "harvest_race");
2290  ttool = object_get_value(pl->chosen_skill, "harvest_tool");
2291  tspeed = object_get_value(pl->chosen_skill, "harvest_speed");
2292  if (!trace || strcmp(trace, "") == 0 || !ttool || strcmp(ttool, "") == 0 || !tspeed || strcmp(tspeed, "") == 0) {
2293  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);
2294  LOG(llevError, "do_harvest: tool %s without harvest_[race|tool|speed]\n", pl->chosen_skill->name);
2295  return;
2296  }
2297 
2298  item = GET_MAP_OB(map, x, y);
2299  while (item && count < 10) {
2301  if (object_value_set(inv, "harvestable") == false)
2302  continue;
2303  race = object_get_value(inv, "harvest_race");
2304  tool = object_get_value(inv, "harvest_tool");
2305  slevel = object_get_value(inv, "harvest_level");
2306  sexp = object_get_value(inv, "harvest_exp");
2307  if (race && (!slevel || !sexp)) {
2308  LOG(llevError, "do_harvest: item %s without harvest_[level|exp]\n", inv->name);
2309  continue;
2310  }
2311  if (race == trace && (!tool || tool == ttool))
2312  found[count++] = inv;
2313  } FOR_INV_FINISH();
2314  item = item->above;
2315  }
2316  if (count == 0) {
2317  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);
2318  return;
2319  }
2320 
2321  inv = found[rndm(0, count-1)];
2322  assert(inv);
2323  item = inv->env;
2324  assert(item);
2325 
2326  slevel = object_get_value(inv, "harvest_level");
2327  sexp = object_get_value(inv, "harvest_exp");
2328  level = atoi(slevel);
2329  exp = atoi(sexp);
2330 
2331  speed = atof(tspeed);
2332  if (speed < 0)
2333  speed = -speed*pl->speed;
2334  pl->speed_left -= speed;
2335 
2336 
2337  /* Now we found something to harvest, randomly try to get it. */
2338  if (level > skill->level+10) {
2339  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);
2340  return;
2341  }
2342 
2343  if (level >= skill->level)
2344  /* Up to 10 more levels, 1 to 11 percent probability. */
2345  proba = 10+skill->level-level;
2346  else if (skill->level <= level+10)
2347  proba = 10+(skill->level-level)*2;
2348  else
2349  proba = 30;
2350 
2351  if (proba <= random_roll(0, 100, pl, 1)) {
2352  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);
2353  return;
2354  }
2355 
2356  /* Check the new item can fit into inventory.
2357  * Fixes bug #3060474: fishing puts more fishes into inventory than you can carry. */
2358  if (((uint32_t)(pl->weight + pl->carrying + inv->weight)) > get_weight_limit(pl->stats.Str)) {
2359  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);
2360  return;
2361  }
2362 
2363  /* Ok, got it. */
2364  if (inv->nrof == 0) {
2365  harvested = object_new();
2366  object_copy_with_inv(inv, harvested);
2367  } else {
2368  if (count == 1 && inv->nrof == 1) {
2369  check_exhaust = 1;
2370  }
2371  if ( inv->nrof == 1 ) {
2372  /* Avoid dumping object inventory like a dead monster if it has an inventory */
2373  object_remove(inv);
2374  harvested = inv;
2375  }
2376  else {
2377  harvested = object_split(inv, 1, NULL, 0);
2378  }
2379  }
2380  object_set_value(harvested, "harvestable", NULL, 0);
2381  if (QUERY_FLAG(harvested, FLAG_MONSTER)) {
2382  int spot = object_find_free_spot(harvested, pl->map, pl->x, pl->y, 0, SIZEOFFREE);
2383  if (spot == -1) {
2384  /* Better luck next time...*/
2385  object_remove(harvested);
2386  draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You fail to %s anything.", skill->slaying);
2387  return;
2388  }
2389  object_insert_in_map_at(harvested, pl->map, NULL, 0, pl->x+freearr_x[spot], pl->y+freearr_y[spot]);
2390  draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You %s a %s!", skill->slaying, harvested->name);
2391  } else {
2392  harvested = object_insert_in_ob(harvested, pl);
2393  draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You %s some %s.", skill->slaying, harvested->name);
2394  }
2395 
2396  /* Get exp */
2397  change_exp(pl, exp, skill->name, SK_EXP_ADD_SKILL);
2398 
2399  if (check_exhaust) {
2400  sstring replacement = object_get_value(item, "harvest_exhaust_replacement");
2401  if (replacement) {
2402  if (replacement[0] != '-') {
2403  archetype *other = try_find_archetype(replacement);
2404  if (other) {
2405  object *final = object_create_arch(other);
2407  }
2408  }
2411  }
2412  }
2413 
2414  return;
2415 }
GET_MAP_OB
#define GET_MAP_OB(M, X, Y)
Definition: map.h:173
get_weight_limit
uint32_t get_weight_limit(int stat)
Definition: living.c:2362
command_version
void command_version(object *op, const char *params)
Definition: c_misc.c:1073
nrofallowedstr
EXTERN long nrofallowedstr
Definition: global.h:138
get_name_of_region_for_map
const char * get_name_of_region_for_map(const mapstruct *m)
Definition: region.cpp:94
global.h
make_face_from_files.anims
list anims
Definition: make_face_from_files.py:53
object
struct obj object
get_who_escape_code_value
static void get_who_escape_code_value(char *return_val, int size, const char letter, player *pl)
Definition: c_misc.c:696
ST_CHANGE_PASSWORD_OLD
#define ST_CHANGE_PASSWORD_OLD
Definition: define.h:550
bow_nw
@ bow_nw
Definition: player.h:52
object_free
void object_free(object *ob, int flags)
Definition: object.c:1578
chars_names::login_order
int login_order
Definition: c_misc.c:524
add_string
sstring add_string(const char *str)
Definition: shstr.c:124
object_remove
void object_remove(object *op)
Definition: object.c:1819
safe_strncpy
#define safe_strncpy
Definition: compat.h:27
remove_friendly_object
void remove_friendly_object(object *op)
Definition: friend.cpp:56
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:57
pets_terminate_all
void pets_terminate_all(object *owner)
Definition: pets.c:225
object_sum_weight
signed long object_sum_weight(object *op)
Definition: object.c:572
assets_number_of_animations
size_t assets_number_of_animations()
Definition: assets.cpp:292
NUM_BODY_LOCATIONS
#define NUM_BODY_LOCATIONS
Definition: object.h:13
ATNR_INTERNAL
#define ATNR_INTERNAL
Definition: attack.h:72
time_info
void time_info(object *op)
Definition: time.c:294
command_list
void command_list(object *pl, bool is_dm)
Definition: commands.cpp:392
llevError
@ llevError
Definition: logger.h:11
FABS
#define FABS(x)
Definition: define.h:22
hiscore_display
void hiscore_display(object *op, int max, const char *match)
Definition: hiscore.c:449
command_motd
void command_motd(object *op, const char *params)
Definition: c_misc.c:216
command_afk
void command_afk(object *op, const char *params)
Definition: c_misc.c:772
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
command_bowmode
void command_bowmode(object *op, const char *params)
Definition: c_misc.c:1315
send_news
void send_news(const object *op)
Definition: player.c:203
get_region_by_name
region * get_region_by_name(const char *region_name)
Definition: region.cpp:48
command_help
void command_help(object *op, const char *params)
Definition: c_misc.c:1769
object_find_by_type_and_arch_name
object * object_find_by_type_and_arch_name(const object *who, int type, const char *name)
Definition: object.c:4248
dump_friendly_objects
void dump_friendly_objects(void)
Definition: friend.cpp:74
diamondslots.x
x
Definition: diamondslots.py:15
obj::count
tag_t count
Definition: object.h:302
obj::map
struct mapdef * map
Definition: object.h:300
MSG_TYPE_SKILL
#define MSG_TYPE_SKILL
Definition: newclient.h:407
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
newhash
char const * newhash(char const *password)
Settings::set_title
uint8_t set_title
Definition: global.h:260
pl::peaceful
uint32_t peaceful
Definition: player.h:146
types
type_definition ** types
Definition: gridarta-types-convert.c:56
bufferreader_init_from_file
BufferReader * bufferreader_init_from_file(BufferReader *br, const char *filepath, const char *failureMessage, LogLevel failureLevel)
Definition: bufferreader.c:65
find_help_file
static int find_help_file(const char *name, const char *language, int wiz, char *path, int length)
Definition: c_misc.c:1723
liv::Str
int8_t Str
Definition: living.h:36
FALSE
#define FALSE
Definition: compat.h:14
get_friends_of
objectlink * get_friends_of(const object *owner)
Definition: friend.cpp:121
object_new
object * object_new(void)
Definition: object.c:1255
i18n_find_language_by_code
int i18n_find_language_by_code(const char *code)
Definition: languages.c:81
region_is_child_of_region
int region_is_child_of_region(const region *child, const region *r)
Definition: region.cpp:189
Settings::datadir
const char * datadir
Definition: global.h:243
entry
Definition: entry.py:1
FULL_VERSION
#define FULL_VERSION
Definition: version.h:4
player_has_own_title
int player_has_own_title(const struct pl *pl)
Definition: player.c:247
pl::socket
socket_struct socket
Definition: player.h:107
name_cmp
static int name_cmp(const chars_names *c1, const chars_names *c2)
Definition: c_misc.c:536
command_whereami
void command_whereami(object *op, const char *params)
Definition: c_misc.c:819
pl
Definition: player.h:105
command_petmode
void command_petmode(object *op, const char *params)
Definition: c_misc.c:1434
guildoracle.list
list
Definition: guildoracle.py:87
receive_player_password
void receive_player_password(object *op, const char *password)
Definition: c_misc.c:1952
command_save
void command_save(object *op, const char *params)
Definition: c_misc.c:2095
command_dumpfriendlyobjects
void command_dumpfriendlyobjects(object *op, const char *params)
Definition: c_misc.c:988
guildjoin.ob
ob
Definition: guildjoin.py:42
command_resistances
void command_resistances(object *op, const char *params)
Definition: c_misc.c:1594
get_password
void get_password(object *op)
Definition: player.c:884
commongive.inv
inv
Definition: commongive.py:28
command_unarmed_skill
void command_unarmed_skill(object *op, const char *params)
Definition: c_misc.c:1378
CS_QUERY_SINGLECHAR
#define CS_QUERY_SINGLECHAR
Definition: newclient.h:67
first_artifactlist
EXTERN artifactlist * first_artifactlist
Definition: global.h:118
pl::ob
object * ob
Definition: player.h:176
socket_struct::is_bot
uint32_t is_bot
Definition: newserver.h:107
MSG_TYPE_LAST
#define MSG_TYPE_LAST
Definition: newclient.h:418
bufferreader_next_line
char * bufferreader_next_line(BufferReader *br)
Definition: bufferreader.c:102
bowtype_t
enum _bowtype bowtype_t
FLAG_WIZCAST
#define FLAG_WIZCAST
Definition: define.h:289
Ice.tmp
int tmp
Definition: Ice.py:207
NDI_RED
#define NDI_RED
Definition: newclient.h:245
command_kill_pets
void command_kill_pets(object *op, const char *params)
Definition: c_misc.c:2194
dump_all_maps
void dump_all_maps(void)
Definition: map.c:269
guildbuy.players
list players
Definition: guildbuy.py:17
unapply_always
@ unapply_always
Definition: player.h:78
assets_number_of_archetypes
size_t assets_number_of_archetypes()
Definition: assets.cpp:276
current_region_info
static void current_region_info(object *op)
Definition: c_misc.c:406
player_set_own_title
void player_set_own_title(struct pl *pl, const char *title)
Definition: player.c:272
NROFATTACKS
#define NROFATTACKS
Definition: attack.h:17
command_dumpallmaps
void command_dumpallmaps(object *op, const char *params)
Definition: c_misc.c:1044
give.parms
parms
Definition: give.py:28
npc_dialog.filename
filename
Definition: npc_dialog.py:99
MSG_TYPE_COMMAND_ERROR
#define MSG_TYPE_COMMAND_ERROR
Definition: newclient.h:529
first_map
EXTERN mapstruct * first_map
Definition: global.h:116
version.h
command_printlos
void command_printlos(object *op, const char *params)
Definition: c_misc.c:1058
get_region_longname
const char * get_region_longname(const region *r)
Definition: region.cpp:216
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
treasurestruct
Definition: treasure.h:63
MSG_TYPE_COMMAND
#define MSG_TYPE_COMMAND
Definition: newclient.h:404
shstr.h
command_dumpallobjects
void command_dumpallobjects(object *op, const char *params)
Definition: c_misc.c:974
freearr_x
short freearr_x[SIZEOFFREE]
Definition: object.c:299
freearr_y
short freearr_y[SIZEOFFREE]
Definition: object.c:305
party_struct::partyname
char * partyname
Definition: party.h:14
linked_char
Definition: global.h:86
archt
Definition: object.h:469
settings
struct Settings settings
Definition: init.c:39
command_brace
void command_brace(object *op, const char *params)
Definition: c_misc.c:2170
object_get_value
const char * object_get_value(const object *op, const char *const key)
Definition: object.c:4317
MSG_TYPE_ADMIN_DM
#define MSG_TYPE_ADMIN_DM
Definition: newclient.h:497
obj::slaying
sstring slaying
Definition: object.h:322
free_string
void free_string(sstring str)
Definition: shstr.c:280
command_applymode
void command_applymode(object *op, const char *params)
Definition: c_misc.c:1274
regiondef::next
struct regiondef * next
Definition: map.h:276
m
static event_registration m
Definition: citylife.cpp:427
MAP_IN_MEMORY
#define MAP_IN_MEMORY
Definition: map.h:131
pl::next
struct pl * next
Definition: player.h:106
FMT64
#define FMT64
Definition: compat.h:16
opendir
DIR * opendir(const char *)
is_valid_types_gen.line
line
Definition: is_valid_types_gen.py:34
object_dump_all
void object_dump_all(void)
Definition: object.c:708
command_debug
void command_debug(object *op, const char *params)
Definition: c_misc.c:890
disinfect.map
map
Definition: disinfect.py:4
object_copy_with_inv
void object_copy_with_inv(const object *src_ob, object *dest_ob)
Definition: object.c:1194
command_dumpmap
void command_dumpmap(object *op, const char *params)
Definition: c_misc.c:1030
oblnk::next
struct oblnk * next
Definition: object.h:448
Settings::debug
LogLevel debug
Definition: global.h:239
send_rules
void send_rules(const object *op)
Definition: player.c:167
obj::name
sstring name
Definition: object.h:314
command_wizcast
void command_wizcast(object *op, const char *params)
Definition: c_misc.c:944
pl::state
uint8_t state
Definition: player.h:131
print_los
void print_los(object *op)
Definition: los.c:606
rotate-tower.result
bool result
Definition: rotate-tower.py:13
bow_bestarrow
@ bow_bestarrow
Definition: player.h:53
ST_CHANGE_PASSWORD_CONFIRM
#define ST_CHANGE_PASSWORD_CONFIRM
Definition: define.h:552
command_fix_me
void command_fix_me(object *op, const char *params)
Definition: c_misc.c:1210
SS_DUMP_TABLE
#define SS_DUMP_TABLE
Definition: shstr.h:46
check_login
void check_login(object *op, const char *password)
Definition: login.c:522
pet_normal
@ pet_normal
Definition: player.h:58
unapplymode
unapplymode
Definition: player.h:75
regiondef::counter
uint32_t counter
Definition: map.h:286
petmode_t
enum _petmode petmode_t
MSG_TYPE_COMMAND_INFO
#define MSG_TYPE_COMMAND_INFO
Definition: newclient.h:526
liv::Cha
int8_t Cha
Definition: living.h:36
get_region_msg
const char * get_region_msg(const region *r)
Definition: region.cpp:237
display_motd
void display_motd(const object *op)
Definition: player.c:136
stringbuffer_append_string
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Definition: stringbuffer.c:95
pet_defend
@ pet_defend
Definition: player.h:60
command_whereabouts
void command_whereabouts(object *op, const char *params)
Definition: c_misc.c:483
MAP_WHEN_RESET
#define MAP_WHEN_RESET(m)
Definition: map.h:62
readdir
struct dirent * readdir(DIR *)
MSG_TYPE_COMMAND_MALLOC
#define MSG_TYPE_COMMAND_MALLOC
Definition: newclient.h:522
python_init.path
path
Definition: python_init.py:8
i18n_get_language_code
sstring i18n_get_language_code(int language)
Definition: languages.c:108
ss_dump_statistics
void ss_dump_statistics(char *buf, size_t size)
Definition: shstr.c:323
socket_struct::host
char * host
Definition: newserver.h:100
FLAG_AFK
#define FLAG_AFK
Definition: define.h:368
MSG_TYPE_COMMAND_STATISTICS
#define MSG_TYPE_COMMAND_STATISTICS
Definition: newclient.h:524
command_players
void command_players(object *op, const char *params)
Definition: c_misc.c:1224
ss_dump_table
char * ss_dump_table(int what, char *buf, size_t size)
Definition: shstr.c:354
FREE_AND_COPY
#define FREE_AND_COPY(sv, nv)
Definition: global.h:201
regiondef::name
char * name
Definition: map.h:277
artifactliststruct::next
struct artifactliststruct * next
Definition: artifact.h:29
first_player
EXTERN player * first_player
Definition: global.h:115
fix_object
void fix_object(object *op)
Definition: living.c:1126
object_create_arch
object * object_create_arch(archetype *at)
Definition: arch.cpp:301
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:76
nrofallocobjects
int nrofallocobjects
Definition: object.c:291
FLAG_WIZPASS
#define FLAG_WIZPASS
Definition: define.h:314
artifactliststruct
Definition: artifact.h:26
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
MAX_NAME
#define MAX_NAME
Definition: define.h:41
ST_CHANGE_PASSWORD_NEW
#define ST_CHANGE_PASSWORD_NEW
Definition: define.h:551
current_map_info
static void current_map_info(object *op)
Definition: c_misc.c:428
INS_BELOW_ORIGINATOR
#define INS_BELOW_ORIGINATOR
Definition: object.h:570
tick_duration
uint32_t tick_duration
Definition: time.c:35
object_set_value
int object_set_value(object *op, const char *key, const char *value, int add_key)
Definition: object.c:4470
sstring
const typedef char * sstring
Definition: global.h:40
rndm
int rndm(int min, int max)
Definition: utils.c:162
disinfect.count
int count
Definition: disinfect.py:7
command_hiscore
void command_hiscore(object *op, const char *params)
Definition: c_misc.c:878
push.match
bool match
Definition: push.py:61
liv::Con
int8_t Con
Definition: living.h:36
command_rules
void command_rules(object *op, const char *params)
Definition: c_misc.c:229
FLAG_USE_WEAPON
#define FLAG_USE_WEAPON
Definition: define.h:296
sproto.h
SND_MUTE
#define SND_MUTE
Definition: sounds.h:14
chars_names::namebuf
char namebuf[MAX_BUF]
Definition: c_misc.c:523
MapSpace
Definition: map.h:257
mapdef
Definition: map.h:317
MSG_SUBTYPE_NONE
#define MSG_SUBTYPE_NONE
Definition: newclient.h:420
is_dragon_pl
int is_dragon_pl(const object *op)
Definition: player.c:122
liv::Int
int8_t Int
Definition: living.h:36
command_mapinfo
void command_mapinfo(object *op, const char *params)
Definition: c_misc.c:806
command_language
void command_language(object *op, const char *params)
Definition: c_misc.c:131
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
command_body
void command_body(object *op, const char *params)
Definition: c_misc.c:174
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
party_struct
Definition: party.h:10
key_inventory
@ key_inventory
Definition: player.h:66
find_skill_by_name
object * find_skill_by_name(object *who, const char *name)
Definition: skill_util.c:202
command_passwd
void command_passwd(object *pl, const char *params)
Definition: c_misc.c:2237
mapdef::name
char * name
Definition: map.h:320
MAP_WIDTH
#define MAP_WIDTH(m)
Definition: map.h:78
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: porting.c:220
SIZEOFFREE
#define SIZEOFFREE
Definition: define.h:155
P_OUT_OF_MAP
#define P_OUT_OF_MAP
Definition: map.h:250
command_wimpy
void command_wimpy(object *op, const char *params)
Definition: c_misc.c:2139
MAX_BUF
#define MAX_BUF
Definition: define.h:35
artifactstruct
Definition: artifact.h:14
split_string
size_t split_string(char *str, char *array[], size_t array_size, char sep)
Definition: utils.c:483
NAMLEN
#define NAMLEN(dirent)
Definition: global.h:208
checkbanned
int checkbanned(const char *login, const char *host)
Definition: ban.c:32
level_exp
int64_t level_exp(int level, double expmul)
Definition: living.c:1874
Settings::playerdir
const char * playerdir
Definition: global.h:245
command_sound
void command_sound(object *op, const char *params)
Definition: c_misc.c:1907
IS_PLAYER
static bool IS_PLAYER(object *op)
Definition: object.h:595
StringBuffer
Definition: stringbuffer.c:25
random_roll
int random_roll(int min, int max, const object *op, int goodbad)
Definition: utils.c:42
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
object_count_used
int object_count_used(void)
Definition: object.c:1753
ST_PLAYING
#define ST_PLAYING
Definition: define.h:541
object_count_active
int object_count_active(void)
Definition: object.c:1769
sounds.h
FLAG_REMOVED
#define FLAG_REMOVED
Definition: define.h:232
help_topics
static void help_topics(object *op, int what)
Definition: c_misc.c:1640
do_harvest
void do_harvest(object *pl, int dir, object *skill)
Definition: c_misc.c:2261
command_ssdumptable
void command_ssdumptable(object *op, const char *params)
Definition: c_misc.c:1016
FLAG_WIZ
#define FLAG_WIZ
Definition: define.h:231
llevInfo
@ llevInfo
Definition: logger.h:12
dirent
#define dirent
Definition: xdir.h:12
change_resist_msg
const EXTERN char *const change_resist_msg[NROFATTACKS]
Definition: attack.h:135
Floor.t
t
Definition: Floor.py:62
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
object_count_free
int object_count_free(void)
Definition: object.c:1737
regiondef::parent
struct regiondef * parent
Definition: map.h:278
chars_names
Definition: c_misc.c:522
MSG_TYPE_SKILL_FAILURE
#define MSG_TYPE_SKILL_FAILURE
Definition: newclient.h:590
Settings::who_wiz_format
char who_wiz_format[MAX_BUF]
Definition: global.h:272
malloc_info
static void malloc_info(object *op)
Definition: c_misc.c:253
i18n_list_languages
void i18n_list_languages(object *who)
Definition: languages.c:118
ST_CONFIRM_PASSWORD
#define ST_CONFIRM_PASSWORD
Definition: define.h:548
liv::Dex
int8_t Dex
Definition: living.h:36
unapply_nochoice
@ unapply_nochoice
Definition: player.h:76
FLAG_USE_ARMOUR
#define FLAG_USE_ARMOUR
Definition: define.h:295
item
Definition: item.py:1
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
liv::Wis
int8_t Wis
Definition: living.h:36
MSG_TYPE_COMMAND_BODY
#define MSG_TYPE_COMMAND_BODY
Definition: newclient.h:521
command_title
void command_title(object *op, const char *params)
Definition: c_misc.c:2044
roll_again
void roll_again(object *op)
Definition: player.c:1128
give.op
op
Definition: give.py:33
object_find_free_spot
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
Definition: object.c:3530
assets_number_of_treasurelists
size_t assets_number_of_treasurelists()
Definition: assets.cpp:272
receive_player_name
void receive_player_name(object *op, const char *name)
Definition: c_misc.c:1932
pet_sad
@ pet_sad
Definition: player.h:59
object_value_set
bool object_value_set(const object *op, const char *const key)
Definition: object.c:4347
pet_arena
@ pet_arena
Definition: player.h:61
command_showpets
void command_showpets(object *op, const char *params)
Definition: c_misc.c:1478
bufferreader_destroy
void bufferreader_destroy(BufferReader *br)
Definition: bufferreader.c:40
command_listen
void command_listen(object *op, const char *params)
Definition: c_misc.c:1087
roll-o-matic.params
params
Definition: roll-o-matic.py:193
attacktype_desc
const EXTERN char *const attacktype_desc[NROFATTACKS]
Definition: attack.h:138
diamondslots.y
y
Definition: diamondslots.py:16
NDI_WHITE
#define NDI_WHITE
Definition: newclient.h:243
command_quit
void command_quit(object *op, const char *params)
Definition: c_misc.c:1870
oblnk::ob
object * ob
Definition: object.h:447
assets.h
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
buf
StringBuffer * buf
Definition: readable.c:1610
pl::hidden
uint32_t hidden
Definition: player.h:147
get_region_from_string
region * get_region_from_string(const char *name)
Definition: region.cpp:123
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.c:138
change_exp
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
Definition: living.c:2168
MAP_HEIGHT
#define MAP_HEIGHT(m)
Definition: map.h:80
MAP_ENTER_Y
#define MAP_ENTER_Y(m)
Definition: map.h:87
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.c:2833
command_news
void command_news(object *op, const char *params)
Definition: c_misc.c:242
dump_map
void dump_map(const mapstruct *m)
Definition: map.c:246
MSG_TYPE_COMMAND_CONFIG
#define MSG_TYPE_COMMAND_CONFIG
Definition: newclient.h:525
obj::subtype
uint8_t subtype
Definition: object.h:344
command_time
void command_time(object *op, const char *params)
Definition: c_misc.c:865
containers
@ containers
Definition: player.h:68
list_players
void list_players(object *op, region *reg, partylist *party)
Definition: c_misc.c:550
map_size
uint32_t map_size(mapstruct *m)
Definition: map.c:825
keyrings
@ keyrings
Definition: player.h:67
MSG_TYPE_COMMAND_MAPS
#define MSG_TYPE_COMMAND_MAPS
Definition: newclient.h:520
strcasecmp
int strcasecmp(const char *s1, const char *s2)
get_region_by_map
region * get_region_by_map(mapstruct *m)
Definition: region.cpp:76
obj::skill
sstring skill
Definition: object.h:324
loader.h
nroffreeobjects
int nroffreeobjects
Definition: object.c:290
save_player
int save_player(object *op, int flag)
Definition: login.c:230
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.c:2080
ST_GET_PARTY_PASSWORD
#define ST_GET_PARTY_PASSWORD
Definition: define.h:549
draw_ext_info
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: main.c:309
command_delete
void command_delete(object *op, const char *params)
Definition: c_misc.c:1886
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.c:1546
command_strings
void command_strings(object *op, const char *params)
Definition: c_misc.c:844
pl::ticks_played
uint32_t ticks_played
Definition: player.h:221
i18n
const char * i18n(const object *who, const char *code)
Definition: languages.c:55
MAP_ENTER_X
#define MAP_ENTER_X(m)
Definition: map.h:85
player_set_state
void player_set_state(player *pl, uint8_t state)
Definition: player.c:4439
try_find_archetype
archetype * try_find_archetype(const char *name)
Definition: assets.cpp:288
command_peaceful
void command_peaceful(object *op, const char *params)
Definition: c_misc.c:2121
command_dumpallarchetypes
void command_dumpallarchetypes(object *op, const char *params)
Definition: c_misc.c:1002
check_password
bool check_password(const char *typed, const char *crypted)
Definition: server.c:114
SS_DUMP_TOTALS
#define SS_DUMP_TOTALS
Definition: shstr.h:47
level
int level
Definition: readable.c:1608
seconds
long seconds(void)
Definition: time.c:344
socket_struct::login_method
uint8_t login_method
Definition: newserver.h:128
P_NO_CLERIC
#define P_NO_CLERIC
Definition: map.h:239
nrofartifacts
EXTERN long nrofartifacts
Definition: global.h:137
ST_CONFIRM_QUIT
#define ST_CONFIRM_QUIT
Definition: define.h:545
FREE_OBJ_FREE_INVENTORY
#define FREE_OBJ_FREE_INVENTORY
Definition: object.h:530
command_usekeys
void command_usekeys(object *op, const char *params)
Definition: c_misc.c:1553
SK_EXP_ADD_SKILL
#define SK_EXP_ADD_SKILL
Definition: skills.h:78
command_malloc
void command_malloc(object *op, const char *params)
Definition: c_misc.c:793
say.item
dictionary item
Definition: say.py:149
MSG_TYPE_ADMIN_VERSION
#define MSG_TYPE_ADMIN_VERSION
Definition: newclient.h:501
unapply_never
@ unapply_never
Definition: player.h:77
atnr_is_dragon_enabled
int atnr_is_dragon_enabled(int attacknr)
Definition: player.c:103
LogLevel
LogLevel
Definition: logger.h:10
display_help_file
static void display_help_file(object *op, const char *filename)
Definition: c_misc.c:1746
map_info
static void map_info(object *op, const char *search)
Definition: c_misc.c:51
command_who
void command_who(object *op, const char *params)
Definition: c_misc.c:623
oblnk
Definition: object.h:446
mapdef::path
char path[HUGE_BUF]
Definition: map.h:358
command_statistics
void command_statistics(object *pl, const char *params)
Definition: c_misc.c:1118
MAP_TIMEOUT
#define MAP_TIMEOUT(m)
Definition: map.h:66
pl::party
partylist * party
Definition: player.h:202
TRUE
#define TRUE
Definition: compat.h:11
ST_ROLL_STAT
#define ST_ROLL_STAT
Definition: define.h:543
get_map_flags
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
Definition: map.c:301
player_get_title
void player_get_title(const struct pl *pl, char *buf, size_t bufsize)
Definition: player.c:232
check_name
int check_name(player *me, const char *name)
Definition: login.c:181
closedir
int closedir(DIR *)
command_wizpass
void command_wizpass(object *op, const char *params)
Definition: c_misc.c:914
MSG_TYPE_COMMAND_WHO
#define MSG_TYPE_COMMAND_WHO
Definition: newclient.h:519
first_region
EXTERN region * first_region
Definition: global.h:117
display_who_entry
static void display_who_entry(object *op, player *pl, const char *format)
Definition: c_misc.c:640
body_locations
body_locations_struct body_locations[NUM_BODY_LOCATIONS]
Definition: item.c:54
regiondef::longname
char * longname
Definition: map.h:283
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
set_map_reset_time
void set_map_reset_time(mapstruct *map)
Definition: map.c:2247
BufferReader
Definition: bufferreader.c:21
command_maps
void command_maps(object *op, const char *params)
Definition: c_misc.c:832
send_query
void send_query(socket_struct *ns, uint8_t flags, const char *text)
Definition: request.c:679
object_split
object * object_split(object *orig_ob, uint32_t nr, char *err, size_t size)
Definition: object.c:2613
MSG_TYPE_ADMIN
#define MSG_TYPE_ADMIN
Definition: newclient.h:402
mapstruct
struct mapdef mapstruct
Settings::who_format
char who_format[MAX_BUF]
Definition: global.h:271
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:670
find_help_file_in
static int find_help_file_in(const char *dir, const char *name, const char *language, char *path, int length)
Definition: c_misc.c:1700
FORCE
@ FORCE
Definition: object.h:224
usekeytype
usekeytype
Definition: player.h:65
liv::Pow
int8_t Pow
Definition: living.h:36
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Definition: main.c:319
ring_occidental_mages.r
r
Definition: ring_occidental_mages.py:6
obj::level
int16_t level
Definition: object.h:356
dump_all_archetypes
void dump_all_archetypes(void)
Definition: arch.cpp:152
assets_number_of_treasures
size_t assets_number_of_treasures()
Definition: assets.cpp:269
pl::orig_stats
living orig_stats
Definition: player.h:166
treasureliststruct
Definition: treasure.h:82
give.name
name
Definition: give.py:27
castle_read.suffix
string suffix
Definition: castle_read.py:30
get_name
void get_name(object *op)
Definition: player.c:873
object_get_owner
object * object_get_owner(object *op)
Definition: object.c:808
CS_QUERY_HIDEINPUT
#define CS_QUERY_HIDEINPUT
Definition: newclient.h:68
onoff_value
static int onoff_value(const char *line)
Definition: c_misc.c:1836
find_player
player * find_player(const char *plname)
Definition: player.c:56
level
Definition: level.py:1
Settings::localdir
const char * localdir
Definition: global.h:244
regiondef
Definition: map.h:275