Crossfire Server  1.75.0
login.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2022 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 
19 #include "global.h"
20 
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/stat.h>
24 
25 #include "define.h"
26 #include "loader.h"
27 #include "output_file.h"
28 #include "spells.h"
29 #include "sproto.h"
30 #include "server.h"
31 
32 static void copy_file(const char *filename, FILE *fpout);
33 
41 void emergency_save(int flag) {
42 #ifndef NO_EMERGENCY_SAVE
43  player *pl;
44 
46  LOG(llevError, "Emergency save: ");
47  for (pl = first_player; pl != NULL; pl = pl->next) {
48  if (!pl->ob) {
49  LOG(llevError, "No name, ignoring this.\n");
50  continue;
51  }
52  LOG(llevError, "%s ", pl->ob->name);
54  "Emergency save...");
55 
56  /* If we are not exiting the game (ie, this is sort of a backup save), then
57  * don't change the location back to the village. Note that there are other
58  * options to have backup saves be done at the starting village
59  */
60  if (!flag) {
61  strcpy(pl->maplevel, first_map_path);
62  if (pl->ob->map != NULL)
63  pl->ob->map = NULL;
64  pl->ob->x = -1;
65  pl->ob->y = -1;
66  }
67  if (!save_player(pl->ob, flag)) {
68  LOG(llevError, "(failed) ");
70  "Emergency save failed, checking score...");
71  }
72  hiscore_check(pl->ob, 1);
73  }
74  LOG(llevError, "\n");
75 #else
76  (void)flag;
77  LOG(llevInfo, "Emergency saves disabled, no save attempted\n");
78 #endif
79 }
80 
88 void delete_character(const char *name) {
89  char buf[MAX_BUF];
90 
91  snprintf(buf, sizeof(buf), "%s/%s/%s", settings.localdir, settings.playerdir, name);
92  /* this effectively does an rm -rf on the directory */
93  remove_directory(buf);
94 }
95 
111 int verify_player(const char *name, char *password) {
112  char buf[MAX_BUF];
113  FILE *fp;
114  player *pltmp;
115 
116  if (strpbrk(name, "/.\\") != NULL) {
117  LOG(llevError, "Username contains illegal characters: %s\n", name);
118  return 1;
119  }
120 
121  /* Make sure we don't have a character that has just been loaded into the game with this name.
122  * It is possible for that character to not have been saved yet, and yet a character exists
123  * with that name.
124  * Creating a second character of the same name makes the game *really* confused, so don't
125  * let that happen.
126  *
127  * Neila Hawkins 2021-07-26
128  */
129  for (pltmp = first_player; pltmp != NULL; pltmp = pltmp->next) {
130  if (pltmp->ob->name != NULL && !strcmp(pltmp->ob->name, name)) {
131  // If we find a player already playing with that name, then disallow it.
132  return 2;
133  }
134  }
135 
136  // There is no unsaved player with that name, check the files
137  snprintf(buf, sizeof(buf), "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, name, name);
138  if (strlen(buf) >= sizeof(buf)-1) {
139  LOG(llevError, "Username too long: %s\n", name);
140  return 1;
141  }
142 
143  fp = fopen(buf, "r");
144  if (fp == NULL)
145  return 1;
146 
147  /* Read in the file until we find the password line. Our logic could
148  * be a bit better on cleaning up the password from the file, but since
149  * it is written by the program, I think it is fair to assume that the
150  * syntax should be pretty standard.
151  */
152  while (fgets(buf, MAX_BUF-1, fp) != NULL) {
153  if (!strncmp(buf, "password ", 9)) {
154  buf[strlen(buf)-1] = 0; /* remove newline */
155  if (check_password(password, buf+9)) {
156  fclose(fp);
157  return 0;
158  }
159 
160  fclose(fp);
161  return 2;
162  }
163  }
164  LOG(llevDebug, "Could not find a password line in player %s\n", name);
165  fclose(fp);
166  return 1;
167 }
168 
181 int check_name(player *me, const char *name) {
182  if (*name == '\0') {
184  "Your username cannot be blank.");
185  return 0;
186  }
187 
188  if (!playername_ok(name)) {
190  "That name contains illegal characters. Use letters, hyphens and underscores only. Hyphens and underscores are not allowed as the first character.");
191  return 0;
192  }
193  if (strlen(name) >= MAX_NAME) {
195  "That name is too long. (Max length: %d characters)", MAX_NAME);
196  return 0;
197  }
198 
199  return 1;
200 }
201 
209 void destroy_object(object *op) {
210  while (op->inv != NULL)
211  destroy_object(op->inv);
212 
213  if (!QUERY_FLAG(op, FLAG_REMOVED))
214  object_remove(op);
216 }
217 
218 void drop_all_unpaid(object *op) {
219  FOR_INV_PREPARE(op, tmp) {
220  if (QUERY_FLAG(tmp, FLAG_UNPAID)) {
221  object_remove(tmp);
222  object_insert_in_map_at(tmp, op->map, op, 0, op->x, op->y);
223  }
224  } FOR_INV_FINISH();
225 }
226 
239 int save_player(object *op, int flag) {
240  FILE *fp;
241  OutputFile of;
242  char filename[MAX_BUF], *tmpfilename;
243  player *pl = op->contr;
244  int i, wiz = QUERY_FLAG(op, FLAG_WIZ);
245  long checksum;
246 #ifdef BACKUP_SAVE_AT_HOME
247  int16_t backup_x, backup_y;
248 #endif
249 
250  PROFILE_BEGIN();
251  if (!op->stats.exp)
252  return 0; /* no experience, no save */
253 
254  flag &= 1;
255 
256  if (!pl->name_changed) {
257  if (!flag) {
259  "Your game is not valid, game not saved.");
260  }
261  return 0;
262  }
263 
264  /* Sanity check - some stuff changes this when player is exiting */
265  if (op->type != PLAYER)
266  return 0;
267 
268  /* Prevent accidental saves if connection is reset after player has
269  * mostly exited.
270  */
271  if (pl->state != ST_PLAYING && pl->state != ST_GET_PARTY_PASSWORD)
272  return 0;
273 
274  if (flag == 0) {
275  pets_terminate_all(op);
276  drop_all_unpaid(op);
277  }
278 
279  /* Update information on this character. Only do it if it is eligible for
280  * for saving.
281  */
282  if (pl->socket->account_name) {
285  /* Add this character to the account. This really only comes up
286  * for new characters, at which time we want to wait until save -
287  * otherwise there is a good chance that character will be
288  * terminated.
289  */
291  account_link(pl->socket->account_name, pl->ob->name);
292  }
293 
294 
295  snprintf(filename, sizeof(filename), "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, op->name, op->name);
296  make_path_to_file(filename);
297  fp = tempnam_secure(settings.tmpdir, NULL, &tmpfilename);
298  if (!fp) {
300  "Can't get secure temporary file for save.");
301  LOG(llevDebug, "Can't get secure temporary file for save.\n");
302  return 0;
303  }
304 
305  fprintf(fp, "password %s\n", pl->password);
306  if (settings.set_title == TRUE)
307  if (player_has_own_title(pl))
308  fprintf(fp, "title %s\n", player_get_own_title(pl));
309 
310  fprintf(fp, "gen_hp %d\n", pl->gen_hp);
311  fprintf(fp, "gen_sp %d\n", pl->gen_sp);
312  fprintf(fp, "gen_grace %d\n", pl->gen_grace);
313  fprintf(fp, "listening %d\n", pl->listening);
314  fprintf(fp, "shoottype %d\n", pl->shoottype);
315  fprintf(fp, "bowtype %d\n", pl->bowtype);
316  fprintf(fp, "petmode %d\n", pl->petmode);
317  fprintf(fp, "peaceful %d\n", pl->peaceful);
318  fprintf(fp, "no_shout %d\n", pl->no_shout);
319  fprintf(fp, "digestion %d\n", pl->digestion);
320  fprintf(fp, "pickup %u\n", pl->mode);
321  fprintf(fp, "partial_commands %u\n", pl->partial_commands);
322  /*
323  * outputs_sync and outputs_count are now unused in favor of the facility
324  * being supported on the client instead of in the server, but for now,
325  * set sane values in case an older server is run on a new player file.
326  * Once the server is officially 2.x, this should likely be removed.
327  */
328  fprintf(fp, "outputs_sync %d\n", 16);
329  fprintf(fp, "outputs_count %d\n", 1);
330  /* Match the enumerations but in string form */
331  fprintf(fp, "usekeys %s\n", pl->usekeys == key_inventory ? "key_inventory" : (pl->usekeys == keyrings ? "keyrings" : "containers"));
332  /* Match the enumerations but in string form */
333  fprintf(fp, "unapply %s\n", pl->unapply == unapply_nochoice ? "unapply_nochoice" : (pl->unapply == unapply_never ? "unapply_never" : "unapply_always"));
334  if (pl->unarmed_skill) fprintf(fp, "unarmed_skill %s\n", pl->unarmed_skill);
335 
336 #ifdef BACKUP_SAVE_AT_HOME
337  if (op->map != NULL && flag == 0)
338 #else
339  if (op->map != NULL)
340 #endif
341  fprintf(fp, "map %s\n", op->map->path);
342  else
343  fprintf(fp, "map %s\n", settings.emergency_mapname);
344 
345  fprintf(fp, "savebed_map %s\n", pl->savebed_map);
346  fprintf(fp, "bed_x %d\nbed_y %d\n", pl->bed_x, pl->bed_y);
347  fprintf(fp, "Str %d\n", pl->orig_stats.Str);
348  fprintf(fp, "Dex %d\n", pl->orig_stats.Dex);
349  fprintf(fp, "Con %d\n", pl->orig_stats.Con);
350  fprintf(fp, "Int %d\n", pl->orig_stats.Int);
351  fprintf(fp, "Pow %d\n", pl->orig_stats.Pow);
352  fprintf(fp, "Wis %d\n", pl->orig_stats.Wis);
353  fprintf(fp, "Cha %d\n", pl->orig_stats.Cha);
354 
355  fprintf(fp, "lev_array %d\n", MIN(op->level, 10));
356  for (i = 1; i <= MIN(op->level, 10) && i <= 10; i++) {
357  fprintf(fp, "%d\n", pl->levhp[i]);
358  fprintf(fp, "%d\n", pl->levsp[i]);
359  fprintf(fp, "%d\n", pl->levgrace[i]);
360  }
361  fprintf(fp, "party_rejoin_mode %d\n", pl->rejoin_party);
362  if (pl->party != NULL) {
363  fprintf(fp, "party_rejoin_name %s\n", pl->party->partyname);
364  fprintf(fp, "party_rejoin_password %s\n", party_get_password(pl->party));
365  }
366  fprintf(fp, "language %s\n", i18n_get_language_code(pl->language));
367  fprintf(fp, "ticks_played %u\n", pl->ticks_played);
368  fprintf(fp, "endplst\n");
369 
371  CLEAR_FLAG(op, FLAG_WIZ);
372 #ifdef BACKUP_SAVE_AT_HOME
373  if (flag) {
374  backup_x = op->x;
375  backup_y = op->y;
376  op->x = -1;
377  op->y = -1;
378  }
379  /* Save objects, but not unpaid objects. Don't remove objects from
380  * inventory.
381  */
382  i = save_object(fp, op, SAVE_FLAG_NO_REMOVE);
383  if (flag) {
384  op->x = backup_x;
385  op->y = backup_y;
386  }
387 #else
388  i = save_object(fp, op, SAVE_FLAG_SAVE_UNPAID|SAVE_FLAG_NO_REMOVE); /* don't check and don't remove */
389 #endif
390 
391  if (wiz)
392  SET_FLAG(op, FLAG_WIZ);
393 
394  if (fclose(fp) != 0 || i != SAVE_ERROR_OK) { /* make sure the write succeeded */
396  "Can't save character!");
397  draw_ext_info_format(NDI_ALL_DMS|NDI_RED, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_LOADSAVE, "Save failure for player %s!", op->name);
398  unlink(tmpfilename);
399  free(tmpfilename);
400  return 0;
401  }
402 
404 
405  if (!flag) {
406  // Clear last_skill_ob before removing inventory. This prevents us
407  // from accessing removed skill objects during cleanup.
408  for (int i = 0; i < MAX_SKILLS; i++) {
409  op->contr->last_skill_ob[i] = NULL;
410  }
411 
412  while (op->inv != NULL)
413  destroy_object(op->inv);
414 
415  /* destroying objects will most likely destroy the pointer
416  * in op->contr->ranges[], so clear the range to a safe value.
417  */
418  op->contr->shoottype = range_none;
419  }
420 
421  checksum = 0;
422  fp = of_open(&of, filename);
423  if (fp == NULL) {
425  "Can't open file for save.");
426  unlink(tmpfilename);
427  free(tmpfilename);
428  return 0;
429  }
430  fprintf(fp, "checksum %lx\n", checksum);
431  copy_file(tmpfilename, fp);
432  unlink(tmpfilename);
433  free(tmpfilename);
434  if (!of_close(&of)) {
436  "Can't close file for save.");
437  return 0;
438  }
439 
440  if (!flag)
441  esrv_send_inventory(op, op);
442 
443  if (chmod(filename, SAVE_MODE) != 0) {
444  LOG(llevError, "Could not set permissions on '%s'\n", filename);
445  }
446 
447  /* if this is the first player save, quest or knowledge states can be unsaved */
448  if (!op->contr->has_directory) {
449  op->contr->has_directory = 1;
452  }
453 
454  PROFILE_END(diff, LOG(llevDebug, "Saved player %s (%ld ms)\n", op->name, diff/1000));
455  return 1;
456 }
457 
466 static void copy_file(const char *filename, FILE *fpout) {
467  FILE *fp;
468  char buf[MAX_BUF];
469 
470  fp = fopen(filename, "r");
471  if (fp == NULL) {
472  LOG(llevError, "copy_file failed to open \"%s\", player file(s) may be corrupt.\n", filename);
473  return;
474  }
475  while (fgets(buf, MAX_BUF, fp) != NULL)
476  fputs(buf, fpout);
477  fclose(fp);
478 }
479 
487 static void wrong_password(object *op) {
489  "\nA character with this name already exists. "
490  "Please choose another name, or make sure you entered your "
491  "password correctly.\n");
492 
493  FREE_AND_COPY(op->name, "noname");
494  FREE_AND_COPY(op->name_pl, "noname");
495 
496  op->contr->socket->password_fails++;
499  "You gave an incorrect password too many times, "
500  "you will now be dropped from the server.");
501 
502  LOG(llevInfo, "A player connecting from %s has been dropped for password failure\n",
503  op->contr->socket->host);
504 
505  op->contr->socket->status = Ns_Dead; /* the socket loop should handle the rest for us */
506  } else
507  get_name(op);
508 }
509 
522 void check_login(object *op, const char *password) {
523  FILE *fp;
524  char filename[MAX_BUF];
525  char buf[MAX_BUF], bufall[MAX_BUF];
526  int i, value;
527  uint32_t uvalue;
528  player *pl = op->contr, *pltmp;
529  int correct = 0;
530  time_t elapsed_save_time = 0;
531  struct stat statbuf;
532  char *party_name = NULL, party_password[9];
533 
534  strcpy(pl->maplevel, first_map_path);
535  party_password[0] = 0;
536 
537  /* Check if this matches a connected player, and if yes disconnect old / connect new. */
538  for (pltmp = first_player; pltmp != NULL; pltmp = pltmp->next) {
539  if (pltmp != pl && pltmp->ob->name != NULL && !strcmp(pltmp->ob->name, op->name)) {
540  if (!password || check_password(password, pltmp->password)) {
541  /* We could try and be more clever and re-assign the existing
542  * object to the new player, etc. However, I'm concerned that
543  * there may be a lot of other state that still needs to be sent
544  * in that case (we can't make any assumptions on what the
545  * client knows, as maybe the client crashed), so treating it
546  * as just a normal login is the safest and easiest thing to do.
547  */
548 
549  pltmp->socket->status = Ns_Dead;
550 
551  save_player(pltmp->ob, 0);
552  leave(pltmp, 1);
553  final_free_player(pltmp);
554  break;
555  }
556  if (password) {
557  wrong_password(op);
558  return;
559  }
560  }
561  }
562 
563  snprintf(filename, sizeof(filename), "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, op->name, op->name);
564 
565  /* If no file, must be a new player, so lets get confirmation of
566  * the password. Return control to the higher level dispatch,
567  * since the rest of this just deals with loading of the file.
568  */
569  fp = fopen(filename, "r");
570  if (fp == NULL) {
571  confirm_password(op);
572  return;
573  }
574  if (fstat(fileno(fp), &statbuf)) {
575  LOG(llevError, "Unable to stat %s?\n", filename);
576  elapsed_save_time = 0;
577  } else {
578  elapsed_save_time = time(NULL)-statbuf.st_mtime;
579  if (elapsed_save_time < 0) {
580  LOG(llevError, "Player file %s was saved in the future? (%ld time)\n", filename, (long)elapsed_save_time);
581  elapsed_save_time = 0;
582  }
583  }
584 
585  if (fgets(bufall, MAX_BUF, fp) != NULL) {
586  if (!strncmp(bufall, "checksum ", 9)) {
587  if ( fgets(bufall, MAX_BUF, fp) == NULL ) {
588  bufall[0]=0; /* should never happen */
589  }
590  }
591  if (sscanf(bufall, "password %s\n", buf)) {
592  /* New password scheme: */
593  correct = password && check_password(password, buf);
594  if (!password) {
595  /* We want to preserve the password. Normally,
596  * pl->password is filled in when user enters
597  * data in the password prompt, but with new login,
598  * there is no password prompt.
599  */
600  strncpy(pl->password, buf, 15);
601  pl->password[15] = 0;
602  }
603  }
604  /* Old password mode removed - I have no idea what it
605  * was, and the current password mechanism has been used
606  * for at least several years.
607  */
608  }
609  if (!correct && password) {
610  wrong_password(op);
611  fclose(fp);
612  return;
613  }
614 
615 #ifdef SAVE_INTERVAL
616  pl->last_save_time = time(NULL);
617 #endif /* SAVE_INTERVAL */
618  pl->party = NULL;
619  if (settings.search_items == TRUE)
620  pl->search_str[0] = '\0';
621  pl->name_changed = 1;
622  pl->orig_stats.Str = 0;
623  pl->orig_stats.Dex = 0;
624  pl->orig_stats.Con = 0;
625  pl->orig_stats.Int = 0;
626  pl->orig_stats.Pow = 0;
627  pl->orig_stats.Wis = 0;
628  pl->orig_stats.Cha = 0;
629  strcpy(pl->savebed_map, first_map_path);
630  pl->bed_x = 0,
631  pl->bed_y = 0;
632  pl->spellparam[0] = '\0';
633 
634  /* Loop through the file, loading the rest of the values */
635  while (fgets(bufall, MAX_BUF, fp) != NULL) {
636  char *val_string, *p;
637 
638  sscanf(bufall, "%s %d\n", buf, &value);
639 
640  val_string = bufall + strlen(buf) +1;
641  p = strchr(val_string, '\n');
642  if (p != NULL)
643  *p = '\0';
644 
645  /* uvalue is an unsigned value. Since at least a
646  * couple different things want an usigned value, cleaner
647  * to just do it once here vs everyplace it may be needed.
648  */
649 
650  uvalue = strtoul(val_string, (char **)NULL, 10);
651 
652  if (!strcmp(buf, "endplst"))
653  break;
654  if (!strcmp(buf, "title") && settings.set_title == TRUE)
655  player_set_own_title(pl, val_string);
656  else if (!strcmp(buf, "unarmed_skill"))
657  pl->unarmed_skill = add_string(val_string);
658  else if (!strcmp(buf, "explore"))
659  ; /* ignore: explore mode has been removed */
660  else if (!strcmp(buf, "gen_hp"))
661  pl->gen_hp = value;
662  else if (!strcmp(buf, "shoottype"))
663  pl->shoottype = (rangetype)value;
664  else if (!strcmp(buf, "bowtype"))
665  pl->bowtype = (bowtype_t)value;
666  else if (!strcmp(buf, "petmode"))
667  pl->petmode = (petmode_t)value;
668  else if (!strcmp(buf, "gen_sp"))
669  pl->gen_sp = value;
670  else if (!strcmp(buf, "gen_grace"))
671  pl->gen_grace = value;
672  else if (!strcmp(buf, "listening"))
673  pl->listening = value;
674  else if (!strcmp(buf, "peaceful"))
675  pl->peaceful = value;
676  else if (!strcmp(buf, "no_shout"))
677  pl->no_shout = value;
678  else if (!strcmp(buf, "digestion"))
679  pl->digestion = value;
680  else if (!strcmp(buf, "pickup")) {
681  pl->mode = uvalue;
682  } else if (!strcmp(buf, "partial_commands")) {
683  pl->partial_commands = uvalue;
684  }
685  else if (!strcmp(buf, "map"))
686  strlcpy(pl->maplevel, val_string, sizeof(pl->maplevel));
687  else if (!strcmp(buf, "savebed_map"))
688  strlcpy(pl->savebed_map, val_string, sizeof(pl->savebed_map));
689  else if (!strcmp(buf, "bed_x"))
690  pl->bed_x = value;
691  else if (!strcmp(buf, "bed_y"))
692  pl->bed_y = value;
693  else if (!strcmp(buf, "Str"))
694  pl->orig_stats.Str = value;
695  else if (!strcmp(buf, "Dex"))
696  pl->orig_stats.Dex = value;
697  else if (!strcmp(buf, "Con"))
698  pl->orig_stats.Con = value;
699  else if (!strcmp(buf, "Int"))
700  pl->orig_stats.Int = value;
701  else if (!strcmp(buf, "Pow"))
702  pl->orig_stats.Pow = value;
703  else if (!strcmp(buf, "Wis"))
704  pl->orig_stats.Wis = value;
705  else if (!strcmp(buf, "Cha"))
706  pl->orig_stats.Cha = value;
707  else if (!strcmp(buf, "usekeys")) {
708  if (!strcmp(val_string, "key_inventory"))
709  pl->usekeys = key_inventory;
710  else if (!strcmp(val_string, "keyrings"))
711  pl->usekeys = keyrings;
712  else if (!strcmp(val_string, "containers"))
713  pl->usekeys = containers;
714  else
715  LOG(llevDebug, "load_player: got unknown usekeys type: %s\n", val_string);
716  } else if (!strcmp(buf, "unapply")) {
717  if (!strcmp(val_string, "unapply_nochoice"))
719  else if (!strcmp(val_string, "unapply_never"))
720  pl->unapply = unapply_never;
721  else if (!strcmp(val_string, "unapply_always"))
722  pl->unapply = unapply_always;
723  else
724  LOG(llevDebug, "load_player: got unknown unapply type: %s\n", val_string);
725  } else if (!strcmp(buf, "lev_array")) {
726  for (i = 1; i <= value; i++) {
727  int j;
728  int count=0;
729 
730  count = fscanf(fp, "%d\n", &j);
731  if ( !count ) j=0; // sanity; should never happen
732  if (j < 3)
733  j = 3;
734  else if (j > 9)
735  j = 9;
736  pl->levhp[i] = j;
737  count = fscanf(fp, "%d\n", &j);
738  if ( !count ) j=0; // sanity; should never happen
739  if (j < 2)
740  j = 2;
741  else if (j > 6)
742  j = 6;
743  pl->levsp[i] = j;
744  count = fscanf(fp, "%d\n", &j);
745  if ( !count ) j=0; // sanity; should never happen
746  if (j < 1)
747  j = 1;
748  else if (j > 3)
749  j = 3;
750  pl->levgrace[i] = j;
751  }
752  } else if (!strcmp(buf, "party_rejoin_mode"))
753  pl->rejoin_party = (enum party_rejoin_mode)value;
754  else if (!strcmp(buf, "party_rejoin_name"))
755  party_name = strdup_local(val_string);
756  else if (!strcmp(buf, "party_rejoin_password")) {
757  strncpy(party_password, val_string, sizeof(party_password));
758  party_password[sizeof(party_password) - 1] = 0;
759  } else if (!strcmp(buf, "language")) {
760  pl->language = i18n_get_language_by_code(val_string);
761  }
762  else if (!strcmp(buf, "ticks_played")) {
763  pl->ticks_played = uvalue;
764  }
765  } /* End of loop loading the character file */
766 
767  /* on first login via account, this player does not exist anyplace -
768  * so don't remove them.
769  */
770  if (!QUERY_FLAG(op, FLAG_REMOVED))
771  object_remove(op);
772  op->speed = 0;
774  /*FIXME dangerous call, object_reset() should be used to init freshly allocated obj struct!*/
775  object_reset(op);
776  op->contr = pl;
777  pl->ob = op;
778  /* this loads the standard objects values. */
779  PROFILE_BEGIN();
780  load_object(fp, op, LO_NEWFILE, 0, false);
781  PROFILE_END(diff, LOG(llevDebug, "Loaded player file for %s (%ld ms)\n", op->name, diff/1000));
782  fclose(fp);
783 
785 
786  pl->is_wraith = object_find_by_name(op, "wraith feed") != NULL;
787  pl->is_old_wraith = object_find_by_name(op, "Wraith_Force") != NULL;
788 
789  LOG(llevInfo, "login: %s from %s\n", op->name, op->contr->socket->host);
790  strncpy(pl->title, op->arch->clone.name, sizeof(pl->title)-1);
791  pl->title[sizeof(pl->title)-1] = '\0';
792 
793  /* If the map where the person was last saved does not exist,
794  * restart them on their home-savebed. This is good for when
795  * maps change between versions
796  * First, we check for partial path, then check to see if the full
797  * path (for unique player maps)
798  */
799  if (has_been_loaded(pl->maplevel) == NULL
800  && check_path(pl->maplevel, 1) == -1
801  && check_path(pl->maplevel, 0) == -1) {
802  strcpy(pl->maplevel, pl->savebed_map);
803  op->x = pl->bed_x,
804  op->y = pl->bed_y;
805  /* if the map was a shop, the player can have unpaid items, remove them. */
806  remove_unpaid_objects(op, NULL, 1);
807  }
808 
809  /* If player saved beyond some time ago, and the feature is
810  * enabled, put the player back on his savebed map.
811  */
812  if ((settings.reset_loc_time > 0) && (elapsed_save_time > settings.reset_loc_time)) {
813  strcpy(pl->maplevel, pl->savebed_map);
814  op->x = pl->bed_x, op->y = pl->bed_y;
815  /* if the map was a shop, the player can have unpaid items, remove them. */
816  remove_unpaid_objects(op, NULL, 1);
817  }
818 
819  /* make sure he's a player--needed because of class change. */
820  op->type = PLAYER;
822 
823  pl->name_changed = 1;
825 #ifdef AUTOSAVE
826  pl->last_save_tick = pticks;
827 #endif
828  op->carrying = object_sum_weight(op);
829 
830  link_player_skills(op);
831 
832  if (!legal_range(op, op->contr->shoottype))
833  op->contr->shoottype = range_none;
834 
835  /* if it's a dragon player, set the correct title here */
836  if (is_dragon_pl(op) && op->inv != NULL) {
837  object *abil, *skin;
838 
839  abil = object_find_by_type_and_arch_name(op, FORCE, "dragon_ability_force");
840  skin = object_find_by_type_and_arch_name(op, FORCE, "dragon_skin_force");
841  set_dragon_name(op, abil, skin);
842  }
843 
845  "Welcome Back!");
848  "%s has entered the game.",
849  pl->ob->name);
851 
853  op->contr->socket->update_look = 1;
854  /* If the player should be dead, call kill_player for them
855  * Only check for hp - if player lacks food, let the normal
856  * logic for that to take place. If player is permanently
857  * dead, and not using permadeath mode, the kill_player will
858  * set the play_again flag, so return.
859  */
860  if (op->stats.hp < 0) {
862  "Your character was dead last time you played.");
863  kill_player(op, NULL);
864  if (pl->state != ST_PLAYING)
865  {
866  // Prevent memory leak from strdup-ed party_name.
867  if (party_name)
868  free(party_name);
869  return;
870  }
871  }
872 
873  /* Do this after checking for death - no reason sucking up bandwidth if
874  * the data isn't needed.
875  */
876  esrv_new_player(op->contr, op->weight+op->carrying);
877  /* Need to do these after esvr_new_player, as once the client
878  * sees that, it wipes any info it has about the player.
879  */
880  esrv_add_spells(op->contr, NULL);
881 
882  /* Need to call fix_object now - program modified so that it is not
883  * called during the load process (FLAG_NO_FIX_PLAYER set when
884  * saved)
885  * Moved ahead of the esrv functions, so proper weights will be
886  * sent to the client. Needs to be after esvr_add_spells, otherwise
887  * we'll try to update spells from fix_object.
888  */
889  fix_object(op);
890 
891  pl->has_directory = 1;
892 
893  esrv_send_inventory(op, op);
894  esrv_send_pickup(pl);
897 
899 
900  /* can_use_shield is a new flag. However, the can_use.. seems to largely come
901  * from the class, and not race. I don't see any way to get the class information
902  * to then update this. I don't think this will actually break anything - anyone
903  * that can use armour should be able to use a shield. What this may 'break'
904  * are features new characters get, eg, if someone starts up with a Q, they
905  * should be able to use a shield. However, old Q's won't get that advantage.
906  */
907  if (QUERY_FLAG(op, FLAG_USE_ARMOUR))
909 
910  /* Rejoin party if needed. */
911  if (pl->rejoin_party != party_rejoin_no && party_name != NULL) {
912  partylist *party;
913 
914  party = party_find(party_name);
915  if (!party && pl->rejoin_party == party_rejoin_always) {
916  party = party_form(op, party_name);
917  if (party)
918  party_set_password(party, party_password);
919  }
920  if (party && !pl->party && party_confirm_password(party, party_password)) {
921  party_join(op, party);
922  }
923 
924  if (pl->party)
925  snprintf(buf, MAX_BUF, "Rejoined party %s.", party->partyname);
926  else
927  snprintf(buf, MAX_BUF, "Couldn't rejoin party %s: %s.", party_name, party ? "invalid password." : "no such party.");
929  buf);
930  }
931  free(party_name);
932 }
Error, serious thing.
Definition: logger.h:11
int check_path(const char *name, int prepend_dir)
This function checks if a file with the given path exists.
Definition: map.cpp:201
Will unapply whatever is necessary - this goes beyond no choice - if there are multiple ojbect of the...
Definition: player.h:78
signed long object_sum_weight(object *op)
object_sum_weight() is a recursive function which calculates the weight an object is carrying...
Definition: object.cpp:553
int16_t gen_hp
Bonuses to regeneration speed of hp.
Definition: player.h:128
char first_map_path[MAX_BUF]
The start-level.
Definition: init.cpp:120
Use keys in inventory and active containers.
Definition: player.h:68
living orig_stats
Permanent real stats of player.
Definition: player.h:169
#define FLAG_UNPAID
Object hasn&#39;t been paid for yet.
Definition: define.h:223
#define MSG_TYPE_ADMIN_LOGIN
login messages/errors
Definition: newclient.h:519
#define ST_GET_PARTY_PASSWORD
Player tried to join a password-protected party.
Definition: define.h:570
Spell-related defines: spellpath, subtypes, ...
#define PROFILE_BEGIN(expr)
Definition: global.h:364
Information.
Definition: logger.h:12
struct archetype * arch
Pointer to archetype.
Definition: object.h:424
void leave(player *pl, int draw_exit)
Player logs out, or was disconnected.
Definition: server.cpp:1308
#define SAVE_ERROR_OK
No error.
Definition: map.h:142
char * account_name
Name of the account logged in on this socket.
Definition: newserver.h:130
static void copy_file(const char *filename, FILE *fpout)
Copy a file.
Definition: login.cpp:466
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
#define NDI_ALL
Inform all players of this message.
Definition: newclient.h:271
bool check_password(const char *typed, const char *crypted)
Hash a password and compare it to the stored version.
Definition: server.cpp:114
int load_object(FILE *fp, object *op, int bufstate, int map_flags, bool artifact_init)
#define FLAG_USE_ARMOUR
(Monster) can wear armour/shield/helmet
Definition: define.h:283
#define strdup_local
Definition: compat.h:29
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
void player_set_own_title(struct player *pl, const char *title)
Sets the custom title.
Definition: player.cpp:273
#define FLAG_FRIENDLY
Will help players.
Definition: define.h:233
uint32_t peaceful
If set, won&#39;t attack friendly creatures.
Definition: player.h:148
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
Definition: living.cpp:1132
No range selected.
Definition: player.h:30
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
Definition: object.cpp:1818
const char * account_get_account_for_char(const char *charname)
This looks at all the accounts and sees if charname is associated with any of them.
Definition: account.cpp:579
void party_set_password(partylist *party, const char *password)
Sets a party&#39;s password.
Definition: party.cpp:244
player * first_player
First player.
Definition: init.cpp:106
#define FLAG_NO_FIX_PLAYER
fix_object() won&#39;t be called
Definition: define.h:264
const char * playerdir
Where the player files are.
Definition: global.h:251
object * object_find_by_name(const object *who, const char *name)
Finds an object in inventory name.
Definition: object.cpp:3941
void enter_player_maplevel(object *op)
Move a player to its stored map level.
Definition: server.cpp:682
partylist * party
Party this player is part of.
Definition: player.h:205
sstring add_string(const char *str)
Share a string.
Definition: shstr.cpp:137
long trying_emergency_save
True when emergency_save() is reached.
Definition: init.cpp:111
void link_player_skills(object *op)
This function goes through the player inventory and sets up the last_skills[] array in the player obj...
Definition: player.cpp:288
void esrv_send_inventory(object *pl, object *op)
Sends inventory of a container.
Definition: item.cpp:316
void make_path_to_file(const char *filename)
Checks if any directories in the given path doesn&#39;t exist, and creates if necessary.
Definition: porting.cpp:164
const char * party_get_password(const partylist *party)
Returns the party&#39;s password.
Definition: party.cpp:232
#define EVENT_LOGIN
Player login.
Definition: events.h:57
int16_t y
Position in the map for this object.
Definition: object.h:335
int is_dragon_pl(const object *op)
Checks if player is a dragon.
Definition: player.cpp:123
uint32_t mode
Mode of player for pickup.
Definition: player.h:125
#define MSG_TYPE_ADMIN_LOADSAVE
load/save operations
Definition: newclient.h:518
enum Sock_Status status
Definition: newserver.h:94
#define TRUE
Definition: compat.h:11
int player_has_own_title(const struct player *pl)
Returns whether the player has a custom title.
Definition: player.cpp:248
char title[BIG_NAME]
Default title, like fighter, wizard, etc.
Definition: player.h:186
int16_t x
Definition: object.h:335
int legal_range(object *op, int r)
Check for the validity of a player range.
Definition: c_range.cpp:247
Use keys in inventory and active key rings.
Definition: player.h:67
#define PROFILE_END(var, expr)
Definition: global.h:369
Global type definitions and header inclusions.
struct player * contr
Pointer to the player which control this object.
Definition: object.h:284
bowtype_t
Bow firing mode.
Definition: player.h:41
int8_t Con
Use
Definition: living.h:36
void pets_terminate_all(object *owner)
Removes all pets someone owns.
Definition: pets.cpp:242
Will not unapply objects automatically.
Definition: player.h:77
int save_player(object *op, int flag)
Saves a player to disk.
Definition: login.cpp:239
static unsigned checksum(const mtar_raw_header_t *rh)
Definition: microtar.cpp:49
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
Definition: main.cpp:308
int8_t levgrace[11]
What grace bonus the player gained on that level.
Definition: player.h:190
#define ST_PLAYING
Usual state.
Definition: define.h:562
#define NDI_DK_ORANGE
DarkOrange2.
Definition: newclient.h:252
#define MAX_PASSWORD_FAILURES
How many times we are allowed to give the wrong password before being kicked.
Definition: newserver.h:88
char * host
Which host it is connected from (ip address).
Definition: newserver.h:104
void esrv_add_spells(player *pl, object *spell)
This tells the client to add the spell *spell, if spell is NULL, then add all spells in the player&#39;s ...
Definition: request.cpp:1994
#define MIN(x, y)
Definition: compat.h:21
#define FLAG_REMOVED
Object is not in any map or invenory.
Definition: define.h:219
int32_t weight
Attributes of the object.
Definition: object.h:375
void events_execute_global_event(int eventcode,...)
Execute a global event.
Definition: events.cpp:30
Account_Chars * account_chars
Detailed information on characters on this account.
Definition: newserver.h:131
int16_t bed_x
Definition: player.h:113
void get_name(object *op)
Waiting for the player&#39;s name.
Definition: player.cpp:886
rangetype shoottype
Which range-attack is being used by player.
Definition: player.h:114
#define SAVE_FLAG_SAVE_UNPAID
If set, unpaid items will be saved.
Definition: map.h:109
uint32_t update_look
If true, we need to send the look window.
Definition: newserver.h:108
int16_t level
Level of creature or object.
Definition: object.h:361
party_rejoin_mode
Whether to rejoin party at login or not.
Definition: player.h:98
void login_check_shutdown(object *const op)
Warn op if a server shutdown is scheduled.
Definition: server.cpp:1493
void remove_directory(const char *path)
This function removes everything in the directory, and the directory itself.
Definition: porting.cpp:117
void esrv_new_player(player *pl, uint32_t weight)
Tells the client that here is a player it should start using.
Definition: request.cpp:1008
object * object_find_by_type_and_arch_name(const object *who, int type, const char *name)
Find object in inventory by type and archetype name.
Definition: object.cpp:4262
#define NDI_RED
Definition: newclient.h:249
player * next
Pointer to next player, NULL if this is last.
Definition: player.h:108
One party.
Definition: party.h:10
#define MSG_TYPE_COMMAND
Responses to commands, eg, who.
Definition: newclient.h:420
static void wrong_password(object *op)
Simple function to print errors when password is not correct, and reinitialise the name...
Definition: login.cpp:487
char maplevel[MAX_BUF]
On which level is the player?
Definition: player.h:111
void kill_player(object *op, const object *killer)
Handle a player&#39;s death.
Definition: player.cpp:3514
FILE * of_open(OutputFile *of, const char *fname)
Opens an output file.
Definition: output_file.cpp:30
#define MSG_TYPE_COMMAND_SUCCESS
Successful result from command.
Definition: newclient.h:551
If party doesn&#39;t exist, form it.
Definition: player.h:101
Defines for loader.l / loader.c.
int8_t Dex
Use
Definition: living.h:36
uint8_t search_items
Search_items command.
Definition: global.h:268
float speed
Frequency of object &#39;moves&#39; relative to server tick rate.
Definition: object.h:337
int32_t carrying
How much weight this object contains.
Definition: object.h:377
#define LO_NEWFILE
Definition: loader.h:17
#define NDI_ALL_DMS
Inform all logged in DMs.
Definition: newclient.h:272
int16_t digestion
Any bonuses/penalties to digestion.
Definition: player.h:127
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:360
const char * tmpdir
Directory to use for temporary files.
Definition: global.h:256
#define SET_FLAG(xyz, p)
Definition: define.h:384
#define QUERY_FLAG(xyz, p)
Definition: define.h:386
#define FLAG_USE_SHIELD
Can this creature use a shield?
Definition: define.h:224
#define MSG_TYPE_ADMIN_PLAYER
Player coming/going/death.
Definition: newclient.h:515
int8_t Wis
Use
Definition: living.h:36
void player_set_state(player *pl, uint8_t state)
Set the player&#39;s state to the specified one.
Definition: player.cpp:4493
void account_char_save(Account_Chars *chars)
Saves the character information for the given account.
uint32_t has_directory
If 0, the player was not yet saved, its directory doesn&#39;t exist.
Definition: player.h:151
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.cpp:1545
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:700
socket_struct * socket
Socket information for this player.
Definition: player.h:109
char password[16]
2 (seed) + 11 (crypted) + 1 (EOS) + 2 (safety) = 16
Definition: player.h:195
void object_reset(object *op)
Totally resets the specified object, without freeing associated memory.
Definition: object.cpp:919
int verify_player(const char *name, char *password)
This verify that a character of name exits, and that it matches password.
Definition: login.cpp:111
language_t i18n_get_language_by_code(const char *code)
Find the identifier of a language from its code.
Definition: languages.cpp:74
char * partyname
Party name.
Definition: party.h:14
void delete_character(const char *name)
Totally deletes a character.
Definition: login.cpp:88
language_t language
The language the player wishes to use.
Definition: player.h:222
uint8_t state
Input state of the player (name, password, etc).
Definition: player.h:133
object * ob
The object representing the player.
Definition: player.h:179
void confirm_password(object *op)
Ask the player to confirm her password during creation.
Definition: player.cpp:1011
void hiscore_check(object *op, int quiet)
Checks if player should enter the hiscore, and if so writes her into the list.
Definition: hiscore.cpp:348
char spellparam[MAX_BUF]
What param to add to spells.
Definition: player.h:115
const char * player_get_own_title(const struct player *pl)
Returns the player&#39;s own title.
Definition: player.cpp:261
struct Settings settings
Global settings.
Definition: init.cpp:139
usekeytype usekeys
Method for finding keys for doors.
Definition: player.h:122
int16_t bed_y
x,y - coordinates of respawn (savebed).
Definition: player.h:113
partylist * party_find(const char *partyname)
Find a party by name.
Definition: party.cpp:148
Don&#39;t rejoin.
Definition: player.h:99
unapplymode unapply
Method for auto unapply.
Definition: player.h:123
void set_dragon_name(object *pl, const object *abil, const object *skin)
Set the new dragon name after gaining levels or changing ability focus (later this can be extended to...
Definition: living.cpp:1688
uint32_t pticks
Number of ticks since time reset.
Definition: time.cpp:47
char savebed_map[MAX_BUF]
Map where player will respawn after death.
Definition: player.h:112
void destroy_object(object *op)
Recursively object_free_drop_inventory() op and its inventory.
Definition: login.cpp:209
uint32_t ticks_played
How many ticks this player has played.
Definition: player.h:224
#define FLAG_WIZ
Object has special privilegies.
Definition: define.h:218
uint8_t listening
Which priority will be used in info_all.
Definition: player.h:135
living stats
Str, Con, Dex, etc.
Definition: object.h:378
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
#define MSG_TYPE_ADMIN
Definition: newclient.h:418
void quest_send_initial_states(player *pl)
Send the current quest states for the specified player, if the client supports those notifications...
Definition: quest.cpp:929
size_t strlcpy(char *dst, const char *src, size_t size)
Portable implementation of strlcpy(3).
Definition: porting.cpp:222
void knowledge_first_player_save(player *pl)
Ensure the knowledge state is correctly saved for the player.
Definition: knowledge.cpp:1423
int save_object(FILE *fp, object *op, int flag)
Dumps all variables in an object to a file.
Definition: object.cpp:5382
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
int8_t levsp[11]
What sp bonus the player gained on that level.
Definition: player.h:189
#define SAVE_FLAG_NO_REMOVE
If set, objects are not removed while saving.
Definition: map.h:110
void remove_unpaid_objects(object *op, object *env, int free_items)
This goes throws the inventory and removes unpaid objects, and puts them back in the map (location an...
Definition: player.cpp:3229
See Player.
Definition: object.h:112
uint8_t password_fails
How many times the player has failed to give the right password.
Definition: newserver.h:105
void knowledge_send_known(player *pl)
Send initial known knowledge to player, if requested.
Definition: knowledge.cpp:1403
int account_link(const char *account_name, const char *player_name)
Adds a player name to an account.
Definition: account.cpp:444
sstring name_pl
The plural name of the object.
Definition: object.h:323
bool is_old_wraith
Whether this player is a "old" wraith, initialized at load time and updated when eating.
Definition: player.h:230
#define FREE_AND_COPY(sv, nv)
Release the shared string if not NULL, and make it a reference to nv.
Definition: global.h:206
uint32_t name_changed
If true, the player has set a name.
Definition: player.h:147
int16_t gen_grace
Bonuses to regeneration speed of grace.
Definition: player.h:131
const char * localdir
Read/write data files.
Definition: global.h:250
object * last_skill_ob[MAX_SKILLS]
Exp objects sent to client.
Definition: player.h:155
sstring name
The name of the object, obviously...
Definition: object.h:319
FILE * tempnam_secure(const char *dir, const char *pfx, char **filename)
A replacement for the tempnam_local() function since that one is not very secure. ...
Definition: porting.cpp:71
Only for debugging purposes.
Definition: logger.h:13
uint32_t no_shout
if True, player is *not *able to use shout command.
Definition: player.h:150
int8_t Cha
Use
Definition: living.h:36
void quest_first_player_save(player *pl)
Ensure the quest state is correctly saved for a player.
Definition: quest.cpp:987
int of_close(OutputFile *of)
Closes an output file.
Definition: output_file.cpp:61
int check_name(player *me, const char *name)
Ensure player&#39;s name is valid.
Definition: login.cpp:181
#define CLEAR_FLAG(xyz, p)
Definition: define.h:385
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:348
bowtype_t bowtype
Which firemode?
Definition: player.h:116
char search_str[MAX_BUF]
Item we are looking for.
Definition: player.h:213
#define SAVE_MODE
If you have defined SAVE_PLAYER, you might want to change this, too.
Definition: config.h:563
rangetype
What range is currently selected by the player.
Definition: player.h:28
void party_join(object *op, partylist *party)
Makes a player join a party.
Definition: party.cpp:85
int8_t Pow
Use
Definition: living.h:36
void object_update_speed(object *op)
Updates the speed of an object.
Definition: object.cpp:1334
Functions for creating text output files.
petmode_t
Petmode.
Definition: player.h:57
int16_t gen_sp
Bonuses to regeneration speed of sp.
Definition: player.h:129
object * inv
Pointer to the first object in the inventory.
Definition: object.h:298
int8_t levhp[11]
What hp bonus the player gained on that level.
Definition: player.h:188
int party_confirm_password(const partylist *party, const char *password)
Checks whether a given password matches the party&#39;s password.
Definition: party.cpp:259
int playername_ok(const char *cp)
Is the player name valid.
Definition: player.cpp:257
int64_t exp
Experience.
Definition: living.h:47
int reset_loc_time
Number of seconds to put player back at home.
Definition: global.h:265
void check_login(object *op, const char *password)
Actually login a player, load from disk and such.
Definition: login.cpp:522
void esrv_send_pickup(player *pl)
Sends the "pickup" state to pl if client wants it requested.
Definition: request.cpp:1880
Will unapply objects when there no choice to unapply.
Definition: player.h:76
uint8_t set_title
Players can set thier title.
Definition: global.h:266
#define NDI_UNIQUE
Print immediately, don&#39;t buffer.
Definition: newclient.h:270
void final_free_player(player *pl)
Sends the &#39;goodbye&#39; command to the player, and closes connection.
Definition: init.cpp:453
uint32_t partial_commands
If 1, then first letters of a command are enough if no ambiguity in name.
Definition: player.h:152
mapstruct * has_been_loaded(const char *name)
Checks whether map has been loaded.
Definition: map.cpp:79
One player.
Definition: player.h:107
void drop_all_unpaid(object *op)
Definition: login.cpp:218
#define MAX_NAME
Definition: define.h:41
StringBuffer * buf
Definition: readable.cpp:1563
const char * unarmed_skill
Prefered skill to use in unarmed combat.
Definition: player.h:223
Only use keys in inventory.
Definition: player.h:66
void emergency_save(int flag)
Save all players.
Definition: login.cpp:41
#define MAX_SKILLS
This is the maximum number of skills the game may handle.
Definition: skills.h:70
char * emergency_mapname
Map to return players to in emergency.
Definition: global.h:300
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.cpp:2085
partylist * party_form(object *op, const char *partyname)
Forms the party struct for a party called &#39;partyname&#39;.
Definition: party.cpp:40
int8_t Int
Use
Definition: living.h:36
petmode_t petmode
Which petmode?
Definition: player.h:117
sstring i18n_get_language_code(language_t language)
Return the code of a specified language.
Definition: languages.cpp:86
bool is_wraith
Whether this player is a wraith or not, initialized at load time.
Definition: player.h:229
void account_char_add(Account_Chars *chars, player *pl)
This adds a player to the list of accounts.
object clone
An object from which to do object_copy()
Definition: object.h:487
int8_t Str
Use
Definition: living.h:36
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:693
int16_t hp
Hit Points.
Definition: living.h:40
party_rejoin_mode rejoin_party
Whether to rejoin or not party at login.
Definition: player.h:212
Core defines: object types, flags, etc.
Definition: object.h:229