Crossfire Server, Trunk
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 #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 #include "AssetsManager.h"
38 
39 /* Static declarations where needed (when ordering would be an issue) */
40 static void display_who_entry(object *op, player *pl, const char *format);
41 static void get_who_escape_code_value(char *return_val, int size, const char letter, player *pl);
42 static int onoff_value(const char *line);
43 
52 static void map_info(object *op, const char *search) {
53  if ( *search != 0 ) {
55  "Maps matching search: '%s'", search);
56  }
57  if (QUERY_FLAG(op, FLAG_WIZ)) {
59  "[fixed]Path Reset In (HH:MM:SS) Pl IM TO");
60  } else {
62  "[fixed]Path Reset In (HH:MM)");
63  }
64 
65  /* Allow a comma-separate list of search strings; more complicated because of the const */
66  char *to_be_freed = NULL;
67  char *search_array[64];
68  int search_array_count = 0;
69  if ( search[0] ) {
70  to_be_freed = strdup(search);
71  if ( !to_be_freed ) {
72  search_array[0] = to_be_freed;
73  search_array_count = 1;
74  } else {
75  search_array_count = split_string(to_be_freed,search_array,64,',');
76  }
77  }
78 
79  for (mapstruct *m = first_map; m != NULL; m = m->next) {
80  bool match = TRUE;
81  if ( search_array_count ) {
82  match = FALSE;
83  for (int i=0; i<search_array_count; ++i) {
84  if ( strstr(m->path,search_array[i]) ) {
85  match=TRUE;
86  break;
87  }
88  }
89  }
90  if ( !match ) continue; /* Skip unwanted maps */
91 
92  /* Print out the last 26 characters of the map name... */
93  char map_path[MAX_BUF];
94  if (strlen(m->path) <= 26) {
95  strcpy(map_path, m->path);
96  } else {
97  safe_strncpy(map_path, m->path + strlen(m->path) - 26, sizeof(map_path));
98  }
99 
100  uint32_t ttr = MAP_WHEN_RESET(m) - seconds() > 0 ? MAP_WHEN_RESET(m) - seconds() : 0;
101  if ( !m->reset_timeout && !m->unique ) set_map_reset_time(m);
102  if (m->players) {
103  ttr = (m->unique ? 0 : m->reset_timeout) + 300;
104  }
105  else if (m->timeout) {
106  ttr = (m->unique ? 0 : m->reset_timeout) + m->timeout;
107  }
108  const uint32_t hh = ttr/3600, mm = (ttr%3600)/60, ss = ttr%60;
109  if (QUERY_FLAG(op, FLAG_WIZ)) {
112  "[fixed]%-26.26s %2d:%02d:%02d %2d %2d %4d",
113  map_path, hh, mm, ss, m->players, m->in_memory, m->timeout);
114  } else {
117  "[fixed]%-26.26s %2d:%02d%s", map_path, hh, mm,
118  m->players ? " (in use)" : "");
119  }
120  }
121  if ( to_be_freed ) free( to_be_freed );
122 }
123 
132 void command_language(object *op, const char *params) {
133  language_t language = nullptr;
134 
135  if (!op->contr)
136  return;
137 
138  if (*params == '\0' || (!strcmp(params, ""))) {
140  "Your current language is set to: English.");
142  "Available languages:");
144  return;
145  }
146 
148 
149  /* Error out if unknown language. */
150  if (language == nullptr) {
152  "Unknown language.");
153  return;
154  }
155 
156  op->contr->language = language;
157 
159  "Your current language is set to English.");
160 }
161 
175 void command_body(object *op, const char *params) {
176  int i;
177  (void)params;
178 
179  /* Too hard to try and make a header that lines everything up, so just
180  * give a description.
181  */
183  "The first column is the name of the body location.");
184 
186  "The second column is how many of those locations your body has.");
187 
189  "The third column is how many slots in that location are available.");
190 
191  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
192  /* really debugging - normally body_used should not be set to anything
193  * if body_info isn't also set.
194  */
195  if (op->body_info[i] || op->body_used[i]) {
197  "[fixed]%-30s %5d %5d",
198  i18n(op, body_locations[i].use_name), op->body_info[i], op->body_used[i]);
199  }
200  }
203  "You are not allowed to wear armor.");
206  "You are not allowed to use weapons.");
207 }
208 
217 void command_motd(object *op, const char *params) {
218  (void)params;
219  display_motd(op);
220 }
221 
230 void command_rules(object *op, const char *params) {
231  (void)params;
232  send_rules(op);
233 }
234 
243 void command_news(object *op, const char *params) {
244  (void)params;
245  send_news(op);
246 }
247 
254 static void malloc_info(object *op) {
255  int ob_used = object_count_used(), ob_free = object_count_free(), players, nrofmaps;
256  int nrm = 0, mapmem = 0, anr, anims, sum_alloc = 0, sum_used = 0, i, alnr;
257  player *pl;
258  mapstruct *m;
259  artifactlist *al;
260 
261  for (al = first_artifactlist, alnr = 0; al != NULL; al = al->next, alnr++)
262  ;
263 
264  anr = getManager()->archetypes()->count();
265 
266  anims = getManager()->animations()->count();
267 
268  for (pl = first_player, players = 0; pl != NULL; pl = pl->next, players++)
269  ;
270 
271  for (m = first_map, nrofmaps = 0; m != NULL; m = m->next, nrofmaps++)
272  if (m->in_memory == MAP_IN_MEMORY) {
273  mapmem += map_size(m) * (sizeof(object *) + sizeof(MapSpace));
274  nrm++;
275  }
276 
278  "Sizeof: object=%zu player=%zu map=%zu",
279  sizeof(object), sizeof(player), sizeof(mapstruct));
280 
282  "[fixed]Objects:");
283 
285  "[fixed]%6d used", ob_used);
286 
287  if (ob_used != nrofallocobjects - nroffreeobjects) {
289  "[fixed] (used list mismatch: %d)",
291  }
292 
294  "[fixed]%6d free (%.2f%% of %d allocated)",
295  ob_free, (float)ob_free / nrofallocobjects * 100, nrofallocobjects);
296 
297  if (ob_free != nroffreeobjects) {
299  "[fixed] (free list mismatch: %d)",
301  }
302 
304  "[fixed]%6d on active list",
306 
307  i = (ob_used*sizeof(object));
308  sum_used += i;
309  sum_alloc += i;
310 
312  "[fixed] object total: %11d", i);
313 
314  i = (ob_free*sizeof(object));
315  sum_alloc += i;
316 
318  "[fixed]%4d players: %8d",
319  players, i = (players*sizeof(player)));
320 
321  sum_alloc += i;
322  sum_used += i;
323 
325  "[fixed]%4d maps allocated: %8d",
326  nrofmaps, i = (nrofmaps*sizeof(mapstruct)));
327 
328  sum_alloc += i;
329  sum_used += nrm*sizeof(mapstruct);
330 
332  "[fixed]%4d maps in memory: %8d",
333  nrm, mapmem);
334 
335  sum_alloc += mapmem;
336  sum_used += mapmem;
337 
339  "[fixed]%4d archetypes: %8d",
340  anr, i = (anr*sizeof(archetype)));
341 
342  sum_alloc += i;
343  sum_used += i;
344 
346  "[fixed]%4d animations: %8d",
347  anims, i = (anims*sizeof(uint16_t)));
348 
349  sum_alloc += i;
350  sum_used += i;
351 
353  "[fixed]%4zu treasurelists %8d",
355 
356  sum_alloc += i;
357  sum_used += i;
358 
360  "[fixed]%4ld treasures %8d",
362 
363  sum_alloc += i;
364  sum_used += i;
365 
367  "[fixed]%4ld artifacts %8d",
368  nrofartifacts, i = (nrofartifacts*sizeof(artifact)));
369 
370  sum_alloc += i;
371  sum_used += i;
372 
374  "[fixed]%4ld artifacts strngs %8d",
375  nrofallowedstr, i = (nrofallowedstr*sizeof(linked_char)));
376 
377  sum_alloc += i;
378  sum_used += i;
379 
381  "[fixed]%4d artifactlists %8d",
382  alnr, i = (alnr*sizeof(artifactlist)));
383 
384  sum_alloc += i;
385  sum_used += i;
386 
388  "[fixed]Total space allocated:%8d",
389  sum_alloc);
390 
392  "[fixed]Total space used: %8d",
393  sum_used);
394 }
395 
407 static void current_region_info(object *op) {
408  /*
409  * Ok I /suppose/ I should write a separate function for this, but it isn't
410  * going to be /that/ slow, and won't get called much
411  */
413 
414  /* This should only be possible if regions are not operating on this server. */
415  if (!r)
416  return;
417 
419  "You are in %s.\n%s",
421 }
422 
429 static void current_map_info(object *op) {
430  mapstruct *m = op->map;
431 
432  if (!m)
433  return;
434 
436  "%s (%s) in %s",
437  m->name, m->path, get_region_longname(get_region_by_map(m)));
438 
439  if (QUERY_FLAG(op, FLAG_WIZ)) {
441  "players:%d difficulty:%d size:%dx%d start:%dx%d timeout %d reset_group: %s",
442  m->players, m->difficulty,
443  MAP_WIDTH(m), MAP_HEIGHT(m),
445  MAP_TIMEOUT(m), m->reset_group ? m->reset_group : "(none)");
446  }
447  if (m->msg)
449 }
450 
451 #ifdef DEBUG_MALLOC_LEVEL
452 
460 void command_malloc_verify(object *op, char *parms) {
461  extern int malloc_verify(void);
462 
463  if (!malloc_verify())
465  "Heap is corrupted.");
466  else
468  "Heap checks out OK.");
469 
470  return 1;
471 }
472 #endif
473 
484 void command_whereabouts(object *op, const char *params) {
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 (auto reg : all_regions) {
494  reg->counter = 0;
495  }
496  for (pl = first_player; pl != NULL; pl = pl->next)
497  if (pl->ob->map != NULL)
498  get_region_by_map(pl->ob->map)->counter++;
499 
500  /* we only want to print out by places with a 'longname' field...*/
501  for (auto reg : all_regions) {
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 (auto reg : all_regions)
514  if (reg->counter > 0) {
516  "%u players in %s",
517  reg->counter, get_region_longname(reg));
518  }
519 }
520 
522 struct chars_names {
525 };
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))
559  else
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);
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  default:
763  return_val[0] = '\0';
764  }
765 }
766 
775 void command_afk(object *op, const char *params) {
776  (void)params;
777  if (QUERY_FLAG(op, FLAG_AFK)) {
780  "You are no longer AFK");
781  } else {
782  SET_FLAG(op, FLAG_AFK);
784  "You are now AFK");
785  }
786 }
787 
796 void command_malloc(object *op, const char *params) {
797  (void)params;
798  malloc_info(op);
799 }
800 
809 void command_mapinfo(object *op, const char *params) {
810  (void)params;
812 }
813 
822 void command_whereami(object *op, const char *params) {
823  (void)params;
825 }
826 
835 void command_maps(object *op, const char *params) {
836  map_info(op, params);
837 }
838 
847 void command_strings(object *op, const char *params) {
848  char stats[HUGE_BUF];
849  (void)params;
850 
851  ss_dump_statistics(stats, sizeof(stats));
853  "[fixed]%s\n",
854  stats);
855 
858 }
859 
868 void command_time(object *op, const char *params) {
869  (void)params;
870  time_info(op);
871 }
872 
881 void command_hiscore(object *op, const char *params) {
882  hiscore_display(op, op == NULL ? 9999 : 50, params);
883 }
884 
893 void command_debug(object *op, const char *params) {
894  int i;
895 
896  if (*params == '\0' || !sscanf(params, "%d", &i)) {
898  "Global debug level is %d.",
899  settings.debug);
900  return;
901  }
902  settings.debug = (enum LogLevel)FABS(i);
904  "Debug level set to %d.",
905  i);
906 }
907 
908 
917 void command_wizpass(object *op, const char *params) {
918  int i;
919 
920  if (!op)
921  return;
922 
923  if (*params == '\0')
924  i = (QUERY_FLAG(op, FLAG_WIZPASS)) ? 0 : 1;
925  else
926  i = onoff_value(params);
927 
928  if (i) {
930  "You will now walk through walls.");
932  } else {
934  "You will now be stopped by walls.");
936  }
937 }
938 
947 void command_wizcast(object *op, const char *params) {
948  int i;
949 
950  if (!op)
951  return;
952 
953  if (*params == '\0')
954  i = (QUERY_FLAG(op, FLAG_WIZCAST)) ? 0 : 1;
955  else
956  i = onoff_value(params);
957 
958  if (i) {
960  "You can now cast spells anywhere.");
962  } else {
964  "You now cannot cast spells in no-magic areas.");
966  }
967 }
968 
977 void command_dumpallobjects(object *op, const char *params) {
978  (void)op;
979  (void)params;
980  object_dump_all();
981 }
982 
991 void command_dumpfriendlyobjects(object *op, const char *params) {
992  (void)op;
993  (void)params;
995 }
996 
1005 void command_dumpallarchetypes(object *op, const char *params) {
1006  (void)op;
1007  (void)params;
1009 }
1010 
1019 void command_ssdumptable(object *op, const char *params) {
1020  (void)op;
1021  (void)params;
1022  ss_dump_table(SS_DUMP_TABLE, NULL, 0);
1023 }
1024 
1033 void command_dumpmap(object *op, const char *params) {
1034  (void)params;
1035  if (op)
1036  dump_map(op->map);
1037 }
1038 
1047 void command_dumpallmaps(object *op, const char *params) {
1048  (void)op;
1049  (void)params;
1050  dump_all_maps();
1051 }
1052 
1061 void command_printlos(object *op, const char *params) {
1062  (void)params;
1063  if (op)
1064  print_los(op);
1065 }
1066 
1067 
1076 void command_version(object *op, const char *params) {
1077  (void)params;
1079  MSG_TYPE_ADMIN_VERSION, "Crossfire " FULL_VERSION);
1080 }
1081 
1090 void command_listen(object *op, const char *params) {
1091  int i;
1092 
1093  if (*params == '\0' || !sscanf(params, "%d", &i)) {
1095  "Set listen to what (presently %d)?",
1096  op->contr->listening);
1097  return;
1098  }
1099  if (i < 0) {
1101  "Verbose level should be positive.");
1102  return;
1103  }
1104  op->contr->listening = (char)i;
1106  "Your verbose level is now %d.",
1107  i);
1108 }
1109 
1121 void command_statistics(object *pl, const char *params) {
1122  char buf[MAX_BUF];
1123  uint32_t hours, minutes;
1124  uint64_t seconds; /* 64 bit to prevent overflows an intermediate results */
1125  (void)params;
1126 
1127  if (!pl->contr)
1128  return;
1129  safe_strncpy(buf, i18n(pl, "[fixed] Experience: %"), sizeof(buf));
1130  strcat(buf, FMT64);
1132  buf,
1133  pl->stats.exp);
1134  safe_strncpy(buf, i18n(pl, "[fixed] Next Level: %"), sizeof(buf));
1135  strcat(buf, FMT64);
1137  buf,
1138  level_exp(pl->level+1, pl->expmul));
1139 
1141  "[fixed]\nStat Nat/Real/Max");
1142 
1144  "[fixed]Str %2d/ %3d/%3d",
1145  pl->contr->orig_stats.Str, pl->stats.Str, 20+pl->arch->clone.stats.Str);
1147  "[fixed]Dex %2d/ %3d/%3d",
1148  pl->contr->orig_stats.Dex, pl->stats.Dex, 20+pl->arch->clone.stats.Dex);
1150  "[fixed]Con %2d/ %3d/%3d",
1151  pl->contr->orig_stats.Con, pl->stats.Con, 20+pl->arch->clone.stats.Con);
1153  "[fixed]Int %2d/ %3d/%3d",
1154  pl->contr->orig_stats.Int, pl->stats.Int, 20+pl->arch->clone.stats.Int);
1156  "[fixed]Wis %2d/ %3d/%3d",
1157  pl->contr->orig_stats.Wis, pl->stats.Wis, 20+pl->arch->clone.stats.Wis);
1159  "[fixed]Pow %2d/ %3d/%3d",
1160  pl->contr->orig_stats.Pow, pl->stats.Pow, 20+pl->arch->clone.stats.Pow);
1162  "[fixed]Cha %2d/ %3d/%3d",
1163  pl->contr->orig_stats.Cha, pl->stats.Cha, 20+pl->arch->clone.stats.Cha);
1165  "\nAttack Mode: %s",
1166  i18n(pl, pl->contr->peaceful ? "Peaceful" : "Hostile"));
1170  float weap_speed = pl->weapon_speed; // This is the number of attacks per tick.
1171  if (weap_speed < 0.0f)
1172  weap_speed = 0.0f;
1173  if (weap_speed > 1.0f)
1174  weap_speed = 1.0f;
1175  // We will initially calculate the damage if every attack you perform hits.
1176  // This will serve as a baseline for future calculations
1177  float dps = (1000000.0f / tick_duration) * weap_speed * pl->stats.dam;
1178  // TODO: Account for opposing AC in calculations, make some sort of table/chart.
1179  // Then we round the floating-point.
1181  "\n\nDam/Sec: %4d", (int)(dps + 0.5f));
1182 
1183  /* max_time is in microseconds - thus divide by 1000000.
1184  * Need 64 bit values, as otherwise ticks_played * max_time
1185  * can easily overflow.
1186  * Note the message displayed here isn't really
1187  * perfect, since if max_time has been changed since the player started,
1188  * the time estimates use the current value. But I'm presuming that
1189  * max_time won't change very often. MSW 2009-12-01
1190  */
1191  seconds = (uint64_t)pl->contr->ticks_played * (uint64_t)tick_duration / 1000000;
1192  minutes = (uint32_t)seconds / 60;
1193  hours = minutes / 60;
1194  minutes = minutes % 60;
1195 
1197  "You have played this character for %u ticks, which amounts "
1198  "to %d hours and %d minutes.",
1199  pl->contr->ticks_played, hours, minutes);
1200 
1201 
1202  /* Can't think of anything else to print right now */
1203 }
1204 
1213 void command_fix_me(object *op, const char *params) {
1214  (void)params;
1216  fix_object(op);
1217 }
1218 
1227 void command_players(object *op, const char *params) {
1228  char buf[MAX_BUF];
1229  char *t;
1230  DIR *dir;
1231  (void)params;
1232 
1233  snprintf(buf, sizeof(buf), "%s/%s/", settings.localdir, settings.playerdir);
1234  t = buf+strlen(buf);
1235  if ((dir = opendir(buf)) != NULL) {
1236  const struct dirent *entry;
1237 
1238  while ((entry = readdir(dir)) != NULL) {
1239  /* skip '.' , '..' */
1240  if (!((entry->d_name[0] == '.' && entry->d_name[1] == '\0')
1241  || (entry->d_name[0] == '.' && entry->d_name[1] == '.' && entry->d_name[2] == '\0'))) {
1242  struct stat st;
1243 
1244  strcpy(t, entry->d_name);
1245  if (stat(buf, &st) == 0) {
1246  /* This was not posix compatible
1247  * if ((st.st_mode & S_IFMT)==S_IFDIR) {
1248  */
1249  if (S_ISDIR(st.st_mode)) {
1250  struct tm *tm = localtime(&st.st_mtime);
1251 
1253  "[fixed]%s\t%04d %02d %02d %02d %02d %02d",
1254  entry->d_name,
1255  1900+tm->tm_year,
1256  1+tm->tm_mon,
1257  tm->tm_mday,
1258  tm->tm_hour,
1259  tm->tm_min,
1260  tm->tm_sec);
1261  }
1262  }
1263  }
1264  }
1265  closedir(dir);
1266  }
1267 }
1268 
1277 void command_applymode(object *op, const char *params) {
1278  unapplymode unapply = op->contr->unapply;
1279  static const char *const types[] = {
1280  "nochoice",
1281  "never",
1282  "always"
1283  };
1284 
1285  if (*params == '\0') {
1287  "applymode is set to %s",
1288  types[op->contr->unapply]);
1289  return;
1290  }
1291 
1292  if (!strcmp(params, "nochoice"))
1293  op->contr->unapply = unapply_nochoice;
1294  else if (!strcmp(params, "never"))
1295  op->contr->unapply = unapply_never;
1296  else if (!strcmp(params, "always"))
1297  op->contr->unapply = unapply_always;
1298  else {
1300  "applymode: Unknown options %s, valid options are nochoice, never, always",
1301  params);
1302  return;
1303  }
1305  "applymode%s set to %s",
1306  (unapply == op->contr->unapply ? "" : " now"),
1307  types[op->contr->unapply]);
1308 }
1309 
1318 void command_bowmode(object *op, const char *params) {
1319  bowtype_t oldtype = op->contr->bowtype;
1320  static const char *const types[] = {
1321  "normal",
1322  "threewide",
1323  "spreadshot",
1324  "firenorth",
1325  "firene",
1326  "fireeast",
1327  "firese",
1328  "firesouth",
1329  "firesw",
1330  "firewest",
1331  "firenw",
1332  "bestarrow"
1333  };
1334  int i, found;
1335 
1336  if (*params == '\0') {
1338  "bowmode is set to %s",
1339  types[op->contr->bowtype]);
1340  return;
1341  }
1342 
1343  for (i = 0, found = 0; i <= bow_bestarrow; i++) {
1344  if (!strcmp(params, types[i])) {
1345  found++;
1346  op->contr->bowtype = static_cast<bowtype_t>(i);
1347  break;
1348  }
1349  }
1350  if (!found) {
1352  stringbuffer_append_printf(buf, "bowmode: Unknown options %s, valid options are:", params);
1353  for (i = 0; i <= bow_bestarrow; i++) {
1356  if (i < bow_nw)
1358  else
1360  }
1361  char *result = stringbuffer_finish(buf);
1363  free(result);
1364  return;
1365  }
1367  "bowmode%s set to %s",
1368  (oldtype == op->contr->bowtype ? "" : " now"),
1369  types[op->contr->bowtype]);
1370  return;
1371 }
1372 
1381 void command_unarmed_skill(object *op, const char *params) {
1382  object *skill;
1383  size_t i;
1384 
1385  if (*params == '\0') {
1387  "unarmed skill is set to %s",
1388  op->contr->unarmed_skill ? op->contr->unarmed_skill: "nothing");
1389  return;
1390  }
1391 
1392  /* find_skill_by_name() will ready any skill tools - which
1393  * is OK for us because no unarmed skills require skill tools,
1394  * but this could be an issue if you reuse this code for other skills.
1395  */
1397 
1398  if (!skill) {
1400  "You do not know any such skill called %s",
1401  params);
1402  return;
1403  }
1404  for (i = 0; i < sizeof(unarmed_skills); i++)
1405  if (skill->subtype == unarmed_skills[i])
1406  break;
1407  if (i == sizeof(unarmed_skills)) {
1409  "%s is not an unarmed skill!",
1410  skill->name);
1411  return;
1412 
1413  }
1414 
1415  if (op->contr->unarmed_skill)
1416  free_string(op->contr->unarmed_skill);
1417 
1418  /* Taking actual skill name is better than taking params,
1419  * as params could be something more than an exact skill name.
1420  */
1421  op->contr->unarmed_skill = add_string(skill->name);
1422 
1424  "unarmed skill is now set to %s",
1425  op->contr->unarmed_skill);
1426 }
1427 
1428 
1437 void command_petmode(object *op, const char *params) {
1438  petmode_t oldtype = op->contr->petmode;
1439  static const char *const types[] = {
1440  "normal",
1441  "sad",
1442  "defend",
1443  "arena"
1444  };
1445 
1446  if (*params == '\0') {
1448  "petmode is set to %s",
1449  types[op->contr->petmode]);
1450  return;
1451  }
1452 
1453  if (!strcmp(params, "normal"))
1454  op->contr->petmode = pet_normal;
1455  else if (!strcmp(params, "sad"))
1456  op->contr->petmode = pet_sad;
1457  else if (!strcmp(params, "defend"))
1458  op->contr->petmode = pet_defend;
1459  else if (!strcmp(params, "arena"))
1460  op->contr->petmode = pet_arena;
1461  else {
1463  "petmode: Unknown options %s, valid options are normal, sad (seek and destroy), defend, arena",
1464  params);
1465  return;
1466  }
1468  "petmode%s set to %s",
1469  (oldtype == op->contr->petmode ? "" : " now"),
1470  types[op->contr->petmode]);
1471 }
1472 
1481 void command_showpets(object *op, const char *params) {
1482  objectlink *obl, *list;
1483  int counter = 0, target = 0;
1484  int have_shown_pet = 0;
1485  if (*params != '\0')
1486  target = atoi(params);
1487 
1488  list = get_friends_of(op);
1489 
1490  for (obl = list; obl != NULL; obl = obl->next) {
1491  object *ob = obl->ob;
1492 
1493  if (target == 0) {
1494  if (counter == 0)
1496  "Pets:");
1498  "%d %s - level %d",
1499  ++counter, ob->name, ob->level);
1500  } else if (!have_shown_pet && ++counter == target) {
1502  "[fixed]level %d %s",
1503  ob->level, ob->name);
1505  "[fixed]%d/%d HP, %d/%d SP",
1506  ob->stats.hp, ob->stats.maxhp, ob->stats.sp, ob->stats.maxsp);
1507 
1508  /* this is not a nice way to do this, it should be made to be more like the statistics command */
1510  "[fixed]Str %d",
1511  ob->stats.Str);
1513  "[fixed]Dex %d",
1514  ob->stats.Dex);
1516  "[fixed]Con %d",
1517  ob->stats.Con);
1519  "[fixed]Int %d",
1520  ob->stats.Int);
1522  "[fixed]Wis %d",
1523  ob->stats.Wis);
1525  "[fixed]Cha %d",
1526  ob->stats.Cha);
1528  "[fixed]Pow %d",
1529  ob->stats.Pow);
1531  "[fixed]wc %d damage %d ac %d",
1532  ob->stats.wc, ob->stats.dam, ob->stats.ac);
1533  have_shown_pet = 1;
1534  }
1535  }
1536  if (list) {
1538  }
1539 
1540  if (counter == 0)
1542  "You have no pets.");
1543  else if (target != 0 && have_shown_pet == 0)
1545  "No such pet.");
1546 }
1547 
1556 void command_usekeys(object *op, const char *params) {
1557  usekeytype oldtype = op->contr->usekeys;
1558  static const char *const types[] = {
1559  "inventory",
1560  "keyrings",
1561  "containers"
1562  };
1563 
1564  if (*params == '\0') {
1566  "usekeys is set to %s",
1567  types[op->contr->usekeys]);
1568  return;
1569  }
1570 
1571  if (!strcmp(params, "inventory"))
1572  op->contr->usekeys = key_inventory;
1573  else if (!strcmp(params, "keyrings"))
1574  op->contr->usekeys = keyrings;
1575  else if (!strcmp(params, "containers"))
1576  op->contr->usekeys = containers;
1577  else {
1579  "usekeys: Unknown option %s, valid options are inventory, keyrings, containers",
1580  params);
1581  return;
1582  }
1584  "usekeys%s set to %s",
1585  (oldtype == op->contr->usekeys ? "" : " now"),
1586  types[op->contr->usekeys]);
1587 }
1588 
1597 void command_resistances(object *op, const char *params) {
1598  int i;
1599  (void)params;
1600  if (!op)
1601  return;
1602 
1603  for (i = 0; i < NROFATTACKS; i++) {
1604  if (i == ATNR_INTERNAL)
1605  continue;
1606 
1608  "[fixed]%-20s %+5d",
1609  attacktype_desc[i], op->resist[i]);
1610  }
1611 
1612  /* If dragon player, let's display natural resistances */
1613  if (is_dragon_pl(op)) {
1614  int attack;
1615  object *tmp;
1616 
1617  tmp = object_find_by_type_and_arch_name(op, FORCE, "dragon_skin_force");
1618  if (tmp != NULL) {
1620  "\nNatural skin resistances:");
1621 
1622  for (attack = 0; attack < NROFATTACKS; attack++) {
1623  if (atnr_is_dragon_enabled(attack)) {
1625  "%s: %d",
1626  change_resist_msg[attack], tmp->resist[attack]);
1627  }
1628  }
1629  }
1630  }
1631 }
1632 
1643 static void help_topics(object *op, int what) {
1644  DIR *dirp;
1645  struct dirent *de;
1646  char filename[MAX_BUF], line[HUGE_BUF];
1647  char suffix[MAX_BUF];
1648  int namelen;
1649  const char *language;
1650 
1651  language = i18n_get_language_code(op->contr->language);
1652  snprintf(suffix, sizeof(suffix), ".%s", language);
1653 
1654  switch (what) {
1655  case 1:
1656  snprintf(filename, sizeof(filename), "%s/wizhelp", settings.datadir);
1658  " Wiz commands:");
1659  break;
1660 
1661  case 3:
1662  snprintf(filename, sizeof(filename), "%s/mischelp", settings.datadir);
1664  " Misc help:");
1665  break;
1666 
1667  default:
1668  snprintf(filename, sizeof(filename), "%s/help", settings.datadir);
1670  " Commands:");
1671  break;
1672  }
1673  if (!(dirp = opendir(filename)))
1674  return;
1675 
1676  line[0] = '\0';
1677  for (de = readdir(dirp); de; de = readdir(dirp)) {
1678  namelen = NAMLEN(de);
1679 
1680  if (namelen <= 2
1681  && *de->d_name == '.'
1682  && (namelen == 1 || de->d_name[1] == '.'))
1683  continue;
1684  if (strstr(de->d_name, suffix)) {
1685  strcat(line, strtok(de->d_name, "."));
1686  strcat(line, " ");
1687  }
1688  }
1690  line);
1691  closedir(dirp);
1692 }
1693 
1703 static int find_help_file_in(const char *dir, const char *name, const char *language, char *path, int length) {
1704  struct stat st;
1705 
1706  snprintf(path, length, "%s/%s/%s.%s", settings.datadir, dir, name, language);
1707  if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) {
1708  return 1;
1709  }
1710  return 0;
1711 }
1712 
1726 static int find_help_file(const char *name, const char *language, int wiz, char *path, int length) {
1727  if (wiz) {
1728  if (find_help_file_in("wizhelp", name, language, path, length))
1729  return 1;
1730  if (strcmp(language, "en") && find_help_file_in("wizhelp", name, "en", path, length))
1731  return 1;
1732  }
1733 
1734  if (find_help_file_in("help", name, language, path, length))
1735  return 1;
1736  if (strcmp(language, "en") && find_help_file_in("help", name, "en", path, length))
1737  return 1;
1738 
1739  return 0;
1740 }
1741 
1749 static void display_help_file(object *op, const char *filename) {
1750  BufferReader *br;
1751  const char *line;
1752 
1753  if ((br = bufferreader_init_from_file(NULL, filename, "Cannot open help file %s: %s\n", llevError)) == NULL) {
1754  return;
1755  }
1756 
1757  while ((line = bufferreader_next_line(br))) {
1759  }
1760 
1762 }
1763 
1772 void command_help(object *op, const char *params) {
1773  char filename[MAX_BUF];
1774  const char *language;
1775 
1776  /*
1777  * Main help page?
1778  */
1779  if (*params == '\0') {
1780  snprintf(filename, sizeof(filename), "%s/def_help", settings.datadir);
1782  return;
1783  }
1784 
1785  /*
1786  * Topics list
1787  */
1788  if (!strcmp(params, "topics")) {
1789  help_topics(op, 3);
1790  help_topics(op, 0);
1791  if (QUERY_FLAG(op, FLAG_WIZ))
1792  help_topics(op, 1);
1793  return;
1794  }
1795 
1796  /*
1797  * Commands list
1798  */
1799  if (!strcmp(params, "commands")) {
1801  return;
1802  }
1803 
1804  /*
1805  * User wants info about command
1806  */
1807  if (strchr(params, '.') || strchr(params, ' ') || strchr(params, '/')) {
1809  "Illegal characters in '%s'",
1810  params);
1811  return;
1812  }
1813 
1814  language = i18n_get_language_code(op->contr->language);
1815 
1816  if (!find_help_file(params, language, QUERY_FLAG(op, FLAG_WIZ), filename, sizeof(filename))) {
1818  "No help available on '%s'",
1819  params);
1820  return;
1821  }
1822 
1823  /*
1824  * Found that. Just cat it to screen.
1825  */
1827 }
1828 
1839 static int onoff_value(const char *line) {
1840  int i;
1841 
1842  if (sscanf(line, "%d", &i))
1843  return (i != 0);
1844 
1845  switch (line[0]) {
1846  case 'o':
1847  switch (line[1]) {
1848  case 'n':
1849  return 1; /* on */
1850  default:
1851  return 0; /* o[ff] */
1852  }
1853 
1854  case 'y': /* y[es] */
1855  case 'k': /* k[ylla] */
1856  case 's':
1857  case 'd':
1858  return 1;
1859 
1860  case 'n': /* n[o] */
1861  case 'e': /* e[i] */
1862  case 'u':
1863  default:
1864  return 0;
1865  }
1866 }
1867 
1873 void command_quit(object* op, const char* params) {
1874  (void)params;
1875  draw_ext_info(
1877  "To leave the game, sleep in (apply) a bed to reality. To "
1878  "permenantly delete your character, use the 'delete' command.");
1879 }
1880 
1889 void command_delete(object *op, const char *params) {
1890  (void)params;
1891  if (QUERY_FLAG(op, FLAG_WIZ)) {
1892  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_ADMIN_DM, "Can't quit when in DM mode.");
1893  return;
1894  }
1895 
1896  send_query(op->contr->socket, CS_QUERY_SINGLECHAR,
1897  i18n(op, "Quitting will delete your character.\nAre you sure you want to delete your character (y/n):"));
1898 
1900 }
1901 
1910 void command_sound(object *op, const char *params) {
1911  (void)params;
1912  if (!(op->contr->socket->sound&SND_MUTE)) {
1913  op->contr->socket->sound = op->contr->socket->sound|SND_MUTE;
1915  "Sounds are turned off.");
1916  } else {
1917  op->contr->socket->sound = op->contr->socket->sound&~SND_MUTE;
1919  "The sounds are enabled.");
1920  }
1921  return;
1922 }
1923 
1935 void receive_player_name(object *op, const char *name) {
1936  if (!check_name(op->contr, name)) {
1937  get_name(op);
1938  return;
1939  }
1940  FREE_AND_COPY(op->name, name);
1941  FREE_AND_COPY(op->name_pl, name);
1943  op->contr->name_changed = 1;
1944  get_password(op);
1945 }
1946 
1955 void receive_player_password(object *op, const char *password) {
1956  unsigned int pwd_len = strlen(password);
1957 
1958  if (pwd_len == 0 || pwd_len > 16) {
1959  if (op->contr->state == ST_CHANGE_PASSWORD_OLD
1960  || op->contr->state == ST_CHANGE_PASSWORD_NEW
1961  || op->contr->state == ST_CHANGE_PASSWORD_CONFIRM) {
1963  "Password changed cancelled.");
1964  player_set_state(op->contr, ST_PLAYING);
1965  } else
1966  get_name(op);
1967  return;
1968  }
1969  /* To hide the password better */
1970  /* With currently clients, not sure if this is really the case - MSW */
1972 
1973  if (checkbanned(op->name, op->contr->socket->host)) {
1974  LOG(llevInfo, "Banned player tried to add: [%s@%s]\n", op->name, op->contr->socket->host);
1976  "You are not allowed to play.");
1977  get_name(op);
1978  return;
1979  }
1980 
1981  if (op->contr->state == ST_CONFIRM_PASSWORD) {
1982  if (!check_password(password, op->contr->password)) {
1984  "The passwords did not match.");
1985  get_name(op);
1986  return;
1987  }
1988  LOG(llevInfo, "LOGIN: New player named %s from ip %s\n", op->name, op->contr->socket->host);
1989  display_motd(op);
1991  "\nWelcome, Brave New Warrior!\n");
1992  roll_again(op);
1993  player_set_state(op->contr, ST_ROLL_STAT);
1994  return;
1995  }
1996 
1997  if (op->contr->state == ST_CHANGE_PASSWORD_OLD) {
1998  if (!check_password(password, op->contr->password)) {
2000  "You entered the wrong current password.");
2001  player_set_state(op->contr, ST_PLAYING);
2002  } else {
2003  send_query(op->contr->socket, CS_QUERY_HIDEINPUT, i18n(op, "Please enter your new password, or blank to cancel:"));
2005  }
2006  return;
2007  }
2008 
2009  if (op->contr->state == ST_CHANGE_PASSWORD_NEW) {
2010  safe_strncpy(op->contr->new_password, newhash(password),
2011  sizeof(op->contr->new_password));
2012  send_query(op->contr->socket, CS_QUERY_HIDEINPUT,
2013  i18n(op, "Please confirm your new password, or blank to cancel:"));
2015  return;
2016  }
2017 
2018  if (op->contr->state == ST_CHANGE_PASSWORD_CONFIRM) {
2019  if (!check_password(password, op->contr->new_password)) {
2021  "The new passwords don't match!");
2022  } else {
2024  "Password changed.");
2025  strncpy(op->contr->password, op->contr->new_password, 13);
2026  }
2027  player_set_state(op->contr, ST_PLAYING);
2028  return;
2029  }
2030 
2031  safe_strncpy(op->contr->password, newhash(password),
2032  sizeof(op->contr->password));
2033  player_set_state(op->contr, ST_ROLL_STAT);
2034  check_login(op, password);
2035 }
2036 
2047 void command_title(object *op, const char *params) {
2048  char buf[MAX_BUF];
2049 
2050  if (settings.set_title == FALSE) {
2052  "You cannot change your title.");
2053  return;
2054  }
2055 
2056  /* dragon players cannot change titles */
2057  if (is_dragon_pl(op)) {
2059  "Dragons cannot change titles.");
2060  return;
2061  }
2062 
2063  if (*params == '\0') {
2064  char tmp[MAX_BUF];
2065 
2066  player_get_title(op->contr, tmp, sizeof(tmp));
2067  snprintf(buf, sizeof(buf), "Your title is '%s'.", tmp);
2069  return;
2070  }
2071  if (strcmp(params, "clear") == 0 || strcmp(params, "default") == 0) {
2072  if (!player_has_own_title(op->contr))
2074  "Your title is the default title.");
2075  else
2077  "Title set to default.");
2078  player_set_own_title(op->contr, "");
2079  return;
2080  }
2081 
2082  if ((int)strlen(params) >= MAX_NAME) {
2084  "Title too long.");
2085  return;
2086  }
2087  player_set_own_title(op->contr, params);
2088 }
2089 
2098 void command_save(object *op, const char *params) {
2099  (void)params;
2100  if (get_map_flags(op->map, NULL, op->x, op->y, NULL, NULL)&P_NO_CLERIC) {
2102  "You can not save on unholy ground.");
2103  } else if (!op->stats.exp) {
2105  "You don't deserve to save yet.");
2106  } else {
2107  if (save_player(op, 1))
2109  "You have been saved.");
2110  else
2112  "SAVE FAILED!");
2113  }
2114 }
2115 
2124 void command_peaceful(object *op, const char *params) {
2125  (void)params;
2126  if ((op->contr->peaceful = !op->contr->peaceful))
2128  "You will not attack other players.");
2129  else
2131  "You will attack other players.");
2132 }
2133 
2142 void command_wimpy(object *op, const char *params) {
2143  int i;
2144 
2145  if (*params == '\0' || !sscanf(params, "%d", &i)) {
2147  "Your current wimpy level is %d.",
2148  op->run_away);
2149  return;
2150  }
2151 
2152  if (i < 0 || i > 100) {
2154  "Wimpy level must be between 1 and 100.");
2155  return;
2156  }
2157 
2159  "Your new wimpy level is %d.",
2160  i);
2161  op->run_away = i;
2162 }
2163 
2172 void command_brace(object *op, const char *params) {
2173  if (*params == '\0')
2174  op->contr->braced = !op->contr->braced;
2175  else
2176  op->contr->braced = onoff_value(params);
2177 
2178  if (op->contr->braced)
2180  "You are braced.");
2181  else
2183  "Not braced.");
2184 
2185  fix_object(op);
2186 }
2187 
2196 void command_kill_pets(object *op, const char *params) {
2197  if (*params == '\0') {
2200  "Your pets have been killed.");
2201  } else {
2202  objectlink *obl, *list = get_friends_of(op);
2203  int counter = 0, removecount = 0;
2204  int target = atoi(params);
2205 
2206  for (obl = list; obl != NULL; obl = obl->next) {
2207  object *ob = obl->ob;
2208  if (object_get_owner(ob) == op) {
2209  if (++counter == target || (target == 0 && !strcasecmp(ob->name, params))) {
2210  if (!QUERY_FLAG(ob, FLAG_REMOVED))
2211  object_remove(ob);
2214  removecount++;
2215  }
2216  }
2217  }
2218  if (list) {
2220  }
2221  if (removecount != 0)
2223  "Killed %d pets.",
2224  removecount);
2225  else
2227  "Couldn't find any suitable pets to kill.");
2228  }
2229 }
2230 
2239 void command_passwd(object *pl, const char *params) {
2240  (void)params;
2241  /* If old client, this is the way you change your password. */
2242  if (pl->contr->socket->login_method < 1){
2243  send_query(pl->contr->socket, CS_QUERY_HIDEINPUT, i18n(pl, "Password change.\nPlease enter your current password, or empty string to cancel."));
2244 
2246  }
2247  /* If new client (login_method = 2) or jxclient (login_method = 1), changing the password does nothing anyway, so error out */
2248  else{
2250  "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.");
2251  }
2252 }
2253 
2263 void do_harvest(object *pl, int dir, object *skill) {
2264  int16_t x, y;
2265  int count = 0, proba; /* Probability to get the item, 100 based. */
2266  int level, exp, check_exhaust = 0;
2267  object *found[10]; /* Found items that can be harvested. */
2268  mapstruct *map;
2269  object *item, *inv, *harvested;
2270  sstring trace, ttool, tspeed, race, tool, slevel, sexp;
2271  float speed;
2272 
2273  x = pl->x+freearr_x[dir];
2274  y = pl->y+freearr_y[dir];
2275  map = pl->map;
2276 
2277  if (!IS_PLAYER(pl))
2278  return;
2279 
2280  if (!map)
2281  return;
2282 
2283  if (get_map_flags(map, &map, x, y, &x, &y)&P_OUT_OF_MAP) {
2284  draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, i18n(pl, "You cannot %s here."), skill->slaying);
2285  return;
2286  }
2287 
2288  if (!pl->chosen_skill || pl->chosen_skill->skill != skill->skill)
2289  return;
2290 
2291  trace = object_get_value(pl->chosen_skill, "harvest_race");
2292  ttool = object_get_value(pl->chosen_skill, "harvest_tool");
2293  tspeed = object_get_value(pl->chosen_skill, "harvest_speed");
2294  if (!trace || strcmp(trace, "") == 0 || !ttool || strcmp(ttool, "") == 0 || !tspeed || strcmp(tspeed, "") == 0) {
2295  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);
2296  LOG(llevError, "do_harvest: tool %s without harvest_[race|tool|speed]\n", pl->chosen_skill->name);
2297  return;
2298  }
2299 
2300  item = GET_MAP_OB(map, x, y);
2301  while (item && count < 10) {
2303  if (object_value_set(inv, "harvestable") == false)
2304  continue;
2305  race = object_get_value(inv, "harvest_race");
2306  tool = object_get_value(inv, "harvest_tool");
2307  slevel = object_get_value(inv, "harvest_level");
2308  sexp = object_get_value(inv, "harvest_exp");
2309  if (race && (!slevel || !sexp)) {
2310  LOG(llevError, "do_harvest: item %s without harvest_[level|exp]\n", inv->name);
2311  continue;
2312  }
2313  if (race == trace && (!tool || tool == ttool))
2314  found[count++] = inv;
2315  } FOR_INV_FINISH();
2316  item = item->above;
2317  }
2318  if (count == 0) {
2319  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);
2320  return;
2321  }
2322 
2323  inv = found[rndm(0, count-1)];
2324  assert(inv);
2325  item = inv->env;
2326  assert(item);
2327 
2328  slevel = object_get_value(inv, "harvest_level");
2329  sexp = object_get_value(inv, "harvest_exp");
2330  level = atoi(slevel);
2331  exp = atoi(sexp);
2332 
2333  speed = atof(tspeed);
2334  if (speed < 0)
2335  speed = -speed*pl->speed;
2336  pl->speed_left -= speed;
2337 
2338 
2339  /* Now we found something to harvest, randomly try to get it. */
2340  if (level > skill->level+10) {
2341  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);
2342  return;
2343  }
2344 
2345  if (level >= skill->level)
2346  /* Up to 10 more levels, 1 to 11 percent probability. */
2347  proba = 10+skill->level-level;
2348  else if (skill->level <= level+10)
2349  proba = 10+(skill->level-level)*2;
2350  else
2351  proba = 30;
2352 
2353  if (proba <= random_roll(0, 100, pl, 1)) {
2354  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);
2355  return;
2356  }
2357 
2358  /* Check the new item can fit into inventory.
2359  * Fixes bug #3060474: fishing puts more fishes into inventory than you can carry. */
2360  if (((uint32_t)(pl->weight + pl->carrying + inv->weight)) > get_weight_limit(pl->stats.Str)) {
2361  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);
2362  return;
2363  }
2364 
2365  /* Ok, got it. */
2366  if (inv->nrof == 0) {
2367  harvested = object_new();
2368  object_copy_with_inv(inv, harvested, true);
2369  } else {
2370  if (count == 1 && inv->nrof == 1) {
2371  check_exhaust = 1;
2372  }
2373  if ( inv->nrof == 1 ) {
2374  /* Avoid dumping object inventory like a dead monster if it has an inventory */
2375  object_remove(inv);
2376  harvested = inv;
2377  }
2378  else {
2379  harvested = object_split(inv, 1, NULL, 0);
2380  }
2381  }
2382  object_set_value(harvested, "harvestable", NULL, 0);
2383  if (QUERY_FLAG(harvested, FLAG_MONSTER)) {
2384  int spot = object_find_free_spot(harvested, pl->map, pl->x, pl->y, 0, SIZEOFFREE);
2385  if (spot == -1) {
2386  /* Better luck next time...*/
2387  object_remove(harvested);
2388  draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You fail to %s anything.", skill->slaying);
2389  return;
2390  }
2391  object_insert_in_map_at(harvested, pl->map, NULL, 0, pl->x+freearr_x[spot], pl->y+freearr_y[spot]);
2392  draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You %s a %s!", skill->slaying, harvested->name);
2393  } else {
2394  harvested = object_insert_in_ob(harvested, pl);
2395  draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You %s some %s.", skill->slaying, harvested->name);
2396  }
2397 
2398  /* Get exp */
2399  change_exp(pl, exp, skill->name, SK_EXP_ADD_SKILL);
2400 
2401  if (check_exhaust) {
2402  sstring replacement = object_get_value(item, "harvest_exhaust_replacement");
2403  if (replacement) {
2404  if (replacement[0] != '-') {
2405  archetype *other = try_find_archetype(replacement);
2406  if (other) {
2407  object *final = object_create_arch(other);
2409  }
2410  }
2413  }
2414  }
2415 
2416  return;
2417 }
object_value_set
bool object_value_set(const object *op, const char *const key)
Definition: object.cpp:4367
GET_MAP_OB
#define GET_MAP_OB(M, X, Y)
Definition: map.h:171
command_dumpallarchetypes
void command_dumpallarchetypes(object *op, const char *params)
Definition: c_misc.cpp:1005
object_get_owner
object * object_get_owner(object *op)
Definition: object.cpp:804
get_name_of_region_for_map
const char * get_name_of_region_for_map(const mapstruct *m)
Definition: region.cpp:90
global.h
make_face_from_files.anims
list anims
Definition: make_face_from_files.py:59
line
Install Bug reporting Credits so make sure you have version or later There are files involved in the automatic convert convertall and filelist py GuildList has the list of guilds for the server GuildLocations is what is used by the install script for setting up the maps It has columns in the first is the name of the no spaces The second is the region of the the third is the destination folder for the the fourth is the exit the fifth and sixth are the x and y coords within the exit the seventh eighth and ninth are the exit location for the storage hall If field seven is then it uses the same exit map as for the guild hall itself filelist py has a list of which files to process for each guild hall convert py takes all the files in filelist py and customises them to the specific guild then outputs them into a in the same order that they are listed in GuildLocations convertall py reads the lines from GuildLocations and runs line by line
Definition: README.txt:12
nrofartifacts
long nrofartifacts
Definition: init.cpp:116
first_player
player * first_player
Definition: init.cpp:106
ST_CHANGE_PASSWORD_OLD
#define ST_CHANGE_PASSWORD_OLD
Definition: define.h:550
settings
struct Settings settings
Definition: init.cpp:139
AssetsCollection::count
size_t count() const
Definition: AssetsCollection.h:80
chars_names::login_order
int login_order
Definition: c_misc.cpp:524
safe_strncpy
#define safe_strncpy
Definition: compat.h:27
remove_friendly_object
void remove_friendly_object(object *op)
Definition: friend.cpp:52
pets_terminate_all
void pets_terminate_all(object *owner)
Definition: pets.cpp:225
object_count_active
int object_count_active(void)
Definition: object.cpp:1778
NUM_BODY_LOCATIONS
#define NUM_BODY_LOCATIONS
Definition: object.h:15
ATNR_INTERNAL
#define ATNR_INTERNAL
Definition: attack.h:72
command_list
void command_list(object *pl, bool is_dm)
Definition: commands.cpp:389
name_cmp
static int name_cmp(const chars_names *c1, const chars_names *c2)
Definition: c_misc.cpp:536
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.cpp:451
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:51
language_t
void * language_t
Definition: global.h:67
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
send_news
void send_news(const object *op)
Definition: player.cpp:206
get_region_by_name
region * get_region_by_name(const char *region_name)
Definition: region.cpp:46
player
Definition: player.h:105
map_info
static void map_info(object *op, const char *search)
Definition: c_misc.cpp:52
ss_dump_statistics
void ss_dump_statistics(char *buf, size_t size)
Definition: shstr.cpp:323
dump_friendly_objects
void dump_friendly_objects(void)
Definition: friend.cpp:70
time_info
void time_info(object *op)
Definition: time.cpp:294
diamondslots.x
x
Definition: diamondslots.py:15
MSG_TYPE_SKILL
#define MSG_TYPE_SKILL
Definition: newclient.h:396
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
receive_player_name
void receive_player_name(object *op, const char *name)
Definition: c_misc.cpp:1935
newhash
char const * newhash(char const *password)
Definition: server.cpp:101
object
I ve redone this file to hopefully make it a little easier to read through and quickly get some idea what to do There are sections section is current programming style hints for developers to make things easier Section is programming guide for new addition Section is notes for making patches Section currently used conventions hints for new code ob is for object
Definition: style-guide.txt:11
command_dumpallobjects
void command_dumpallobjects(object *op, const char *params)
Definition: c_misc.cpp:977
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.cpp:138
command_dumpallmaps
void command_dumpallmaps(object *op, const char *params)
Definition: c_misc.cpp:1047
FALSE
#define FALSE
Definition: compat.h:14
command_body
void command_body(object *op, const char *params)
Definition: c_misc.cpp:175
MapSpace
Definition: map.h:255
get_friends_of
objectlink * get_friends_of(const object *owner)
Definition: friend.cpp:117
bowtype_t
bowtype_t
Definition: player.h:41
pet_defend
@ pet_defend
Definition: player.h:60
region_is_child_of_region
int region_is_child_of_region(const region *child, const region *r)
Definition: region.cpp:183
entry
Definition: entry.py:1
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.cpp:57
FULL_VERSION
#define FULL_VERSION
Definition: version.h:4
command_showpets
void command_showpets(object *op, const char *params)
Definition: c_misc.cpp:1481
Settings::debug
LogLevel debug
Definition: global.h:243
object_dump_all
void object_dump_all(void)
Definition: object.cpp:704
guildoracle.list
list
Definition: guildoracle.py:87
onoff_value
static int onoff_value(const char *line)
Definition: c_misc.cpp:1839
guildjoin.ob
ob
Definition: guildjoin.py:42
Settings::localdir
const char * localdir
Definition: global.h:249
get_password
void get_password(object *op)
Definition: player.cpp:892
player_set_own_title
void player_set_own_title(struct player *pl, const char *title)
Definition: player.cpp:272
commongive.inv
inv
Definition: commongive.py:29
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,...) PRINTF_ARGS(6
command_statistics
void command_statistics(object *pl, const char *params)
Definition: c_misc.cpp:1121
map_path
void map_path(const char *map, int flags, char *pathname, size_t bufsize)
Definition: map.cpp:1165
CS_QUERY_SINGLECHAR
#define CS_QUERY_SINGLECHAR
Definition: newclient.h:56
bufferreader_destroy
void bufferreader_destroy(BufferReader *br)
Definition: bufferreader.cpp:40
command_hiscore
void command_hiscore(object *op, const char *params)
Definition: c_misc.cpp:881
MSG_TYPE_LAST
#define MSG_TYPE_LAST
Definition: newclient.h:407
Ice.tmp
int tmp
Definition: Ice.py:207
FLAG_WIZCAST
#define FLAG_WIZCAST
Definition: define.h:289
player_has_own_title
int player_has_own_title(const struct player *pl)
Definition: player.cpp:247
command_kill_pets
void command_kill_pets(object *op, const char *params)
Definition: c_misc.cpp:2196
fix_object
void fix_object(object *op)
Definition: living.cpp:1125
artifactlist::next
artifactlist * next
Definition: artifact.h:27
NDI_RED
#define NDI_RED
Definition: newclient.h:234
dump_map
void dump_map(const mapstruct *m)
Definition: map.cpp:244
command_rules
void command_rules(object *op, const char *params)
Definition: c_misc.cpp:230
command_ssdumptable
void command_ssdumptable(object *op, const char *params)
Definition: c_misc.cpp:1019
Settings::who_format
char who_format[MAX_BUF]
Definition: global.h:276
region::name
char * name
Definition: map.h:274
object_copy_with_inv
void object_copy_with_inv(const object *src_ob, object *dest_ob, bool update_speed)
Definition: object.cpp:1208
unapply_always
@ unapply_always
Definition: player.h:78
NROFATTACKS
#define NROFATTACKS
Definition: attack.h:17
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:518
partylist
Definition: party.h:10
object_get_value
const char * object_get_value(const object *op, const char *const key)
Definition: object.cpp:4337
AssetsManager.h
bow_bestarrow
@ bow_bestarrow
Definition: player.h:53
buf
StringBuffer * buf
Definition: readable.cpp:1552
version.h
getManager
AssetsManager * getManager()
Definition: assets.cpp:305
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.cpp:2848
get_region_longname
const char * get_region_longname(const region *r)
Definition: region.cpp:210
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
MSG_TYPE_COMMAND
#define MSG_TYPE_COMMAND
Definition: newclient.h:393
shstr.h
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
linked_char
Definition: global.h:96
draw_ext_info
vs only yadda is in because all tags get reset on the next draw_ext_info In the second since it is all in one draw_ext_info
Definition: media-tags.txt:61
region::longname
char * longname
Definition: map.h:280
help_topics
static void help_topics(object *op, int what)
Definition: c_misc.cpp:1643
MSG_TYPE_ADMIN_DM
#define MSG_TYPE_ADMIN_DM
Definition: newclient.h:486
st
Player Stats effect how well a character can survie and interact inside the crossfire world This section discusses the various what they and how they effect the player s actions Also in this section are the stat modifiers that specific classes professions bring Player and sps the current and maximum the Current and Maximum The Current Sp can go somewhat negative When Sp is negative not all spells can be and a more negative Sp makes spell casting less likey to succeed can affect Damage and how the characters as well as how often the character can attack this affects the prices when buying and selling items if this drops the player will start losing hit points wd Cleric or Dwarf sm Elf wd Fireborn ft Human ra Mage C Monk se Ninja hi Priest C Quetzalcoatl mw Swashbuckler st
Definition: stats.txt:110
command_debug
void command_debug(object *op, const char *params)
Definition: c_misc.cpp:893
command_time
void command_time(object *op, const char *params)
Definition: c_misc.cpp:868
m
static event_registration m
Definition: citylife.cpp:425
MAP_IN_MEMORY
#define MAP_IN_MEMORY
Definition: map.h:127
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.cpp:76
letter
**Media tags please refer to the protocol file in doc Developers protocol Quick for your pleasure an example[/b][i] This is an old letter
Definition: media-tags.txt:15
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.cpp:1555
bufferreader_init_from_file
BufferReader * bufferreader_init_from_file(BufferReader *br, const char *filepath, const char *failureMessage, LogLevel failureLevel)
Definition: bufferreader.cpp:65
command_news
void command_news(object *op, const char *params)
Definition: c_misc.cpp:243
FMT64
#define FMT64
Definition: compat.h:16
opendir
DIR * opendir(const char *)
map_size
uint32_t map_size(mapstruct *m)
Definition: map.cpp:798
disinfect.map
map
Definition: disinfect.py:4
Settings::set_title
uint8_t set_title
Definition: global.h:265
nrofallowedstr
long nrofallowedstr
Definition: init.cpp:117
send_rules
void send_rules(const object *op)
Definition: player.cpp:170
display_who_entry
static void display_who_entry(object *op, player *pl, const char *format)
Definition: c_misc.cpp:640
current_region_info
static void current_region_info(object *op)
Definition: c_misc.cpp:407
freearr_y
short freearr_y[SIZEOFFREE]
Definition: object.cpp:305
rotate-tower.result
bool result
Definition: rotate-tower.py:13
ST_CHANGE_PASSWORD_CONFIRM
#define ST_CHANGE_PASSWORD_CONFIRM
Definition: define.h:552
command_malloc
void command_malloc(object *op, const char *params)
Definition: c_misc.cpp:796
i18n_get_language_code
sstring i18n_get_language_code(language_t language)
Definition: languages.cpp:85
SS_DUMP_TABLE
#define SS_DUMP_TABLE
Definition: shstr.h:46
check_login
void check_login(object *op, const char *password)
Definition: login.cpp:511
list_players
void list_players(object *op, region *reg, partylist *party)
Definition: c_misc.cpp:550
unapplymode
unapplymode
Definition: player.h:75
treasurelist
Definition: treasure.h:85
command_dumpfriendlyobjects
void command_dumpfriendlyobjects(object *op, const char *params)
Definition: c_misc.cpp:991
command_language
void command_language(object *op, const char *params)
Definition: c_misc.cpp:132
command_petmode
void command_petmode(object *op, const char *params)
Definition: c_misc.cpp:1437
MSG_TYPE_COMMAND_INFO
#define MSG_TYPE_COMMAND_INFO
Definition: newclient.h:515
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
speed
Player Stats effect how well a character can survie and interact inside the crossfire world This section discusses the various what they and how they effect the player s actions Also in this section are the stat modifiers that specific classes professions bring Player and sps the current and maximum the Current and Maximum The Current Sp can go somewhat negative When Sp is negative not all spells can be and a more negative Sp makes spell casting less likey to succeed can affect Damage and how the characters speed
Definition: stats.txt:23
object_count_free
int object_count_free(void)
Definition: object.cpp:1746
first_map
mapstruct * first_map
Definition: init.cpp:107
get_region_msg
const char * get_region_msg(const region *r)
Definition: region.cpp:231
display_motd
void display_motd(const object *op)
Definition: player.cpp:139
petmode_t
petmode_t
Definition: player.h:57
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:511
command_passwd
void command_passwd(object *pl, const char *params)
Definition: c_misc.cpp:2239
FLAG_AFK
#define FLAG_AFK
Definition: define.h:368
MSG_TYPE_COMMAND_STATISTICS
#define MSG_TYPE_COMMAND_STATISTICS
Definition: newclient.h:513
change_resist_msg
const char *const change_resist_msg[NROFATTACKS]
Definition: init.cpp:70
FREE_AND_COPY
#define FREE_AND_COPY(sv, nv)
Definition: global.h:204
bow_nw
@ bow_nw
Definition: player.h:52
object_create_arch
object * object_create_arch(archetype *at)
Definition: arch.cpp:298
do_harvest
void do_harvest(object *pl, int dir, object *skill)
Definition: c_misc.cpp:2263
command_quit
void command_quit(object *op, const char *params)
Definition: c_misc.cpp:1873
FLAG_WIZPASS
#define FLAG_WIZPASS
Definition: define.h:314
object_free
void object_free(object *ob, int flags)
Definition: object.cpp:1587
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.cpp:1703
artifactlist
Definition: artifact.h:24
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
MAX_NAME
#define MAX_NAME
Definition: define.h:41
AssetsManager::archetypes
Archetypes * archetypes()
Definition: AssetsManager.h:44
ST_CHANGE_PASSWORD_NEW
#define ST_CHANGE_PASSWORD_NEW
Definition: define.h:551
INS_BELOW_ORIGINATOR
#define INS_BELOW_ORIGINATOR
Definition: object.h:575
command_applymode
void command_applymode(object *op, const char *params)
Definition: c_misc.cpp:1277
change_exp
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
Definition: living.cpp:2168
disinfect.count
int count
Definition: disinfect.py:7
push.match
bool match
Definition: push.py:61
level_exp
int64_t level_exp(int level, double expmul)
Definition: living.cpp:1874
body_locations
body_locations_struct body_locations[NUM_BODY_LOCATIONS]
Definition: item.cpp:54
archetype
Definition: object.h:474
display_help_file
static void display_help_file(object *op, const char *filename)
Definition: c_misc.cpp:1749
Settings::playerdir
const char * playerdir
Definition: global.h:250
FLAG_USE_WEAPON
#define FLAG_USE_WEAPON
Definition: define.h:296
sproto.h
command_strings
void command_strings(object *op, const char *params)
Definition: c_misc.cpp:847
ss_dump_table
char * ss_dump_table(int what, char *buf, size_t size)
Definition: shstr.cpp:354
SND_MUTE
#define SND_MUTE
Definition: sounds.h:14
nrofallocobjects
int nrofallocobjects
Definition: object.cpp:291
stringbuffer_append_string
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Definition: stringbuffer.cpp:95
chars_names::namebuf
char namebuf[MAX_BUF]
Definition: c_misc.cpp:523
command_usekeys
void command_usekeys(object *op, const char *params)
Definition: c_misc.cpp:1556
command_whereabouts
void command_whereabouts(object *op, const char *params)
Definition: c_misc.cpp:484
MSG_SUBTYPE_NONE
#define MSG_SUBTYPE_NONE
Definition: newclient.h:409
partylist::partyname
char * partyname
Definition: party.h:14
command_afk
void command_afk(object *op, const char *params)
Definition: c_misc.cpp:775
command_sound
void command_sound(object *op, const char *params)
Definition: c_misc.cpp:1910
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
command_save
void command_save(object *op, const char *params)
Definition: c_misc.cpp:2098
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.cpp:2095
command_resistances
void command_resistances(object *op, const char *params)
Definition: c_misc.cpp:1597
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
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.cpp:211
seconds
long seconds(void)
Definition: time.cpp:344
MAP_WIDTH
#define MAP_WIDTH(m)
Definition: map.h:74
SIZEOFFREE
#define SIZEOFFREE
Definition: define.h:155
P_OUT_OF_MAP
#define P_OUT_OF_MAP
Definition: map.h:248
MAX_BUF
#define MAX_BUF
Definition: define.h:35
receive_player_password
void receive_player_password(object *op, const char *password)
Definition: c_misc.cpp:1955
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: porting.cpp:222
NAMLEN
#define NAMLEN(dirent)
Definition: global.h:211
checkbanned
int checkbanned(const char *login, const char *host)
Definition: ban.cpp:32
object_new
object * object_new(void)
Definition: object.cpp:1268
command_printlos
void command_printlos(object *op, const char *params)
Definition: c_misc.cpp:1061
set_map_reset_time
void set_map_reset_time(mapstruct *map)
Definition: map.cpp:2221
get_weight_limit
uint32_t get_weight_limit(int stat)
Definition: living.cpp:2362
path
pluglist shows those as well as a short text describing each the list will simply appear empty The keyword for the Python plugin is Python plugout< keyword > Unloads a given identified by its _keyword_ So if you want to unload the Python you need to do plugout Python plugin< libname > Loads a given whose _filename_ is libname So in the case of you d have to do a plugin cfpython so Note that all filenames are relative to the default plugin path(SHARE/plugins). Console messages. ----------------- When Crossfire starts
nroffreeobjects
int nroffreeobjects
Definition: object.cpp:290
free_string
void free_string(sstring str)
Definition: shstr.cpp:280
pet_sad
@ pet_sad
Definition: player.h:59
IS_PLAYER
static bool IS_PLAYER(object *op)
Definition: object.h:600
print_los
void print_los(object *op)
Definition: los.cpp:665
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
command_delete
void command_delete(object *op, const char *params)
Definition: c_misc.cpp:1889
ST_PLAYING
#define ST_PLAYING
Definition: define.h:541
region
Definition: map.h:273
sounds.h
FLAG_REMOVED
#define FLAG_REMOVED
Definition: define.h:232
command_version
void command_version(object *op, const char *params)
Definition: c_misc.cpp:1076
FLAG_WIZ
#define FLAG_WIZ
Definition: define.h:231
llevInfo
@ llevInfo
Definition: logger.h:12
command_players
void command_players(object *op, const char *params)
Definition: c_misc.cpp:1227
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:251
all_regions
std::vector< region * > all_regions
Definition: init.cpp:108
object::name
sstring name
Definition: object.h:319
attacktype_desc
const char *const attacktype_desc[NROFATTACKS]
Definition: init.cpp:40
chars_names
Definition: c_misc.cpp:522
MSG_TYPE_SKILL_FAILURE
#define MSG_TYPE_SKILL_FAILURE
Definition: newclient.h:579
pet_normal
@ pet_normal
Definition: player.h:58
object_count_used
int object_count_used(void)
Definition: object.cpp:1762
command_dumpmap
void command_dumpmap(object *op, const char *params)
Definition: c_misc.cpp:1033
is_dragon_pl
int is_dragon_pl(const object *op)
Definition: player.cpp:122
players
std::vector< archetype * > players
Definition: player.cpp:493
ST_CONFIRM_PASSWORD
#define ST_CONFIRM_PASSWORD
Definition: define.h:548
command_maps
void command_maps(object *op, const char *params)
Definition: c_misc.cpp:835
unapply_nochoice
@ unapply_nochoice
Definition: player.h:76
get_map_flags
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
Definition: map.cpp:299
FLAG_USE_ARMOUR
#define FLAG_USE_ARMOUR
Definition: define.h:295
item
Definition: item.py:1
mapstruct
Definition: map.h:314
BufferReader
Definition: bufferreader.cpp:21
MSG_TYPE_COMMAND_BODY
#define MSG_TYPE_COMMAND_BODY
Definition: newclient.h:510
num_players
non standard information is not specified num_players
Definition: arch-handbook.txt:200
sstring
const typedef char * sstring
Definition: sstring.h:2
roll_again
void roll_again(object *op)
Definition: player.cpp:1141
command_motd
void command_motd(object *op, const char *params)
Definition: c_misc.cpp:217
give.op
op
Definition: give.py:33
assets_number_of_treasurelists
size_t assets_number_of_treasurelists()
Definition: assets.cpp:258
i18n_list_languages
void i18n_list_languages(object *who)
Definition: languages.cpp:95
Floor.t
t
Definition: Floor.py:62
types
Crossfire Protocol most of the time after the actual code was already omit certain important and possibly make life miserable any new developer or curious player should be able to find most of the relevant information here If inconsistencies are found or this documentation proves to be consider the latest server side protocol code in the public source code repository as the authoritative reference Introduction If you were ever curious enough to telnet or netcat to a Crossfire chances are you were sorely disappointed While the protocol may seem to use plain text at it actually uses a mix of ASCII and binary data This handbook attempts to document various aspects of the Crossfire protocol As consult the README file to find out how to get in touch with helpful people via mailing and more History the communications plan was set to be a text based system It was up to the server and client to parse these messages and determine what to do These messages were assumed to be line per message At a reasonably early stage of Eric Anderson wrote a then the data itself you could send many data types
Definition: protocol.txt:36
object_split
object * object_split(object *orig_ob, uint32_t nr, char *err, size_t size)
Definition: object.cpp:2628
command_brace
void command_brace(object *op, const char *params)
Definition: c_misc.cpp:2172
object_find_free_spot
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
Definition: object.cpp:3550
command_title
void command_title(object *op, const char *params)
Definition: c_misc.cpp:2047
format
Python Guilds Quick outline Add a guild(mapmakers) this is still a problem *after dropping the token to gain access to the stove a woodfloor now appears which is Toolshed Token(found in Guild_HQ) *Note also have multiple gates in place to protect players and items from the mana explosion drop x for Jewelers room *Jewelers room works just need to determine what x is drop x for Thaumaturgy room *Thaumaturgy room works just need to determine what x is drop gold dropping the Firestar named fearless allows access to but I suspect that the drop location of the chest is not as intended because the player is in the way once you enter the chest the exit back to the basement is things such as the message et al reside on teleporters which then transport items to the map as they are when the map is already purchased items reappear in that area From my this does not cause any problems at the moment But this should be corrected fixed Major it s now possible to buy guilds Ryo Update Uploaded guild package to CVS Changes the cauldrons and the charging room I spent a while agonizing over They were natural guild enhancements but much too much value for any reasonable expense to buy them Then I thought that they should be pay access but at a greatly reduced rate SO when you buy a forge or whatever for your guild it is available on a perplayer daily rate but it will be accessable for testing and to DMs to play with Like I said lots still to do with the especially comingt up with quest items for buying things like the new workshops and stuff One of the things I would like some input on would be proposals for additional fields for either the guildhouses or guild datafiles to play with Currently the Guildhouse but there is no reason we can t have more than one measure of a guild perhaps have dues relate to Dues and use points for some other suspended or inactive or when a guild is founded inactive active Guilds have the format
Definition: README.txt:140
i18n_find_language_by_code
language_t i18n_find_language_by_code(const char *code)
Definition: languages.cpp:59
roll-o-matic.params
params
Definition: roll-o-matic.py:193
diamondslots.y
y
Definition: diamondslots.py:16
NDI_WHITE
#define NDI_WHITE
Definition: newclient.h:232
assets.h
pet_arena
@ pet_arena
Definition: player.h:61
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
random_roll
int random_roll(int min, int max, const object *op, int goodbad)
Definition: utils.cpp:42
get_region_from_string
region * get_region_from_string(const char *name)
Definition: region.cpp:117
tick_duration
uint32_t tick_duration
Definition: time.cpp:35
MAP_HEIGHT
#define MAP_HEIGHT(m)
Definition: map.h:76
MAP_ENTER_Y
#define MAP_ENTER_Y(m)
Definition: map.h:83
MSG_TYPE_COMMAND_CONFIG
#define MSG_TYPE_COMMAND_CONFIG
Definition: newclient.h:514
atnr_is_dragon_enabled
int atnr_is_dragon_enabled(int attacknr)
Definition: player.cpp:103
command_who
void command_who(object *op, const char *params)
Definition: c_misc.cpp:623
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.cpp:4268
stats
Player Stats effect how well a character can survie and interact inside the crossfire world This section discusses the various stats
Definition: stats.txt:2
level
int level
Definition: readable.cpp:1550
first_artifactlist
artifactlist * first_artifactlist
Definition: init.cpp:109
split_string
size_t split_string(char *str, char *array[], size_t array_size, char sep)
Definition: utils.cpp:473
containers
@ containers
Definition: player.h:68
keyrings
@ keyrings
Definition: player.h:67
MSG_TYPE_COMMAND_MAPS
#define MSG_TYPE_COMMAND_MAPS
Definition: newclient.h:509
strcasecmp
int strcasecmp(const char *s1, const char *s2)
malloc_info
static void malloc_info(object *op)
Definition: c_misc.cpp:254
find_help_file
static int find_help_file(const char *name, const char *language, int wiz, char *path, int length)
Definition: c_misc.cpp:1726
command_whereami
void command_whereami(object *op, const char *params)
Definition: c_misc.cpp:822
get_region_by_map
region * get_region_by_map(mapstruct *m)
Definition: region.cpp:72
command_help
void command_help(object *op, const char *params)
Definition: c_misc.cpp:1772
loader.h
command_bowmode
void command_bowmode(object *op, const char *params)
Definition: c_misc.cpp:1318
save_player
int save_player(object *op, int flag)
Definition: login.cpp:230
Settings::datadir
const char * datadir
Definition: global.h:248
ST_GET_PARTY_PASSWORD
#define ST_GET_PARTY_PASSWORD
Definition: define.h:549
command_wizpass
void command_wizpass(object *op, const char *params)
Definition: c_misc.cpp:917
region::counter
uint32_t counter
Definition: map.h:283
skill
skill
Definition: arch-handbook.txt:585
current_map_info
static void current_map_info(object *op)
Definition: c_misc.cpp:429
MAP_ENTER_X
#define MAP_ENTER_X(m)
Definition: map.h:81
object_remove
void object_remove(object *op)
Definition: object.cpp:1828
player_set_state
void player_set_state(player *pl, uint8_t state)
Definition: player.cpp:4475
try_find_archetype
archetype * try_find_archetype(const char *name)
Definition: assets.cpp:270
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.cpp:696
object_sum_weight
signed long object_sum_weight(object *op)
Definition: object.cpp:568
check_password
bool check_password(const char *typed, const char *crypted)
Definition: server.cpp:114
SS_DUMP_TOTALS
#define SS_DUMP_TOTALS
Definition: shstr.h:47
P_NO_CLERIC
#define P_NO_CLERIC
Definition: map.h:237
ST_CONFIRM_QUIT
#define ST_CONFIRM_QUIT
Definition: define.h:545
FREE_OBJ_FREE_INVENTORY
#define FREE_OBJ_FREE_INVENTORY
Definition: object.h:535
command_wimpy
void command_wimpy(object *op, const char *params)
Definition: c_misc.cpp:2142
SK_EXP_ADD_SKILL
#define SK_EXP_ADD_SKILL
Definition: skills.h:78
rndm
int rndm(int min, int max)
Definition: utils.cpp:162
say.item
dictionary item
Definition: say.py:149
MSG_TYPE_ADMIN_VERSION
#define MSG_TYPE_ADMIN_VERSION
Definition: newclient.h:490
unapply_never
@ unapply_never
Definition: player.h:77
treasure
Definition: treasure.h:63
LogLevel
LogLevel
Definition: logger.h:10
artifact
Definition: artifact.h:14
object_set_value
int object_set_value(object *op, const char *key, const char *value, int add_key)
Definition: object.cpp:4490
command_unarmed_skill
void command_unarmed_skill(object *op, const char *params)
Definition: c_misc.cpp:1381
freearr_x
short freearr_x[SIZEOFFREE]
Definition: object.cpp:299
AssetsManager::animations
AllAnimations * animations()
Definition: AssetsManager.h:49
MAP_TIMEOUT
#define MAP_TIMEOUT(m)
Definition: map.h:66
StringBuffer
Definition: stringbuffer.cpp:25
TRUE
#define TRUE
Definition: compat.h:11
ST_ROLL_STAT
#define ST_ROLL_STAT
Definition: define.h:543
check_name
int check_name(player *me, const char *name)
Definition: login.cpp:181
closedir
int closedir(DIR *)
MSG_TYPE_COMMAND_WHO
#define MSG_TYPE_COMMAND_WHO
Definition: newclient.h:508
Settings::who_wiz_format
char who_wiz_format[MAX_BUF]
Definition: global.h:277
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
command_wizcast
void command_wizcast(object *op, const char *params)
Definition: c_misc.cpp:947
send_query
void send_query(socket_struct *ns, uint8_t flags, const char *text)
Definition: request.cpp:728
command_peaceful
void command_peaceful(object *op, const char *params)
Definition: c_misc.cpp:2124
MSG_TYPE_ADMIN
#define MSG_TYPE_ADMIN
Definition: newclient.h:391
command_mapinfo
void command_mapinfo(object *op, const char *params)
Definition: c_misc.cpp:809
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:670
FORCE
@ FORCE
Definition: object.h:229
usekeytype
usekeytype
Definition: player.h:65
command_listen
void command_listen(object *op, const char *params)
Definition: c_misc.cpp:1090
ring_occidental_mages.r
r
Definition: ring_occidental_mages.py:6
dump_all_maps
void dump_all_maps(void)
Definition: map.cpp:267
command_fix_me
void command_fix_me(object *op, const char *params)
Definition: c_misc.cpp:1213
dump_all_archetypes
void dump_all_archetypes(void)
Definition: arch.cpp:150
assets_number_of_treasures
size_t assets_number_of_treasures()
Definition: assets.cpp:255
i18n
const char * i18n(const object *who, const char *code)
Definition: languages.cpp:42
castle_read.suffix
string suffix
Definition: castle_read.py:30
player_get_title
void player_get_title(const player *pl, char *buf, size_t bufsize)
Definition: player.cpp:232
get_name
void get_name(object *op)
Definition: player.cpp:881
bufferreader_next_line
char * bufferreader_next_line(BufferReader *br)
Definition: bufferreader.cpp:102
CS_QUERY_HIDEINPUT
#define CS_QUERY_HIDEINPUT
Definition: newclient.h:57
find_player
player * find_player(const char *plname)
Definition: player.cpp:59
level
Definition: level.py:1