ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/login.C
Revision: 1.20
Committed: Mon Dec 11 02:41:26 2006 UTC (17 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.19: +1 -0 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 elmex 1.1 /*
2     CrossFire, A Multiplayer game for X-windows
3    
4     Copyright (C) 2002 Mark Wedel & Crossfire Development Team
5     Copyright (C) 1992 Frank Tore Johansen
6    
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11    
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     GNU General Public License for more details.
16    
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    
21 root 1.18 The authors can be reached via e-mail at <crossfire@schmorp.de>
22 elmex 1.1 */
23    
24     #include <global.h>
25     #ifndef __CEXTRACT__
26 root 1.15 # include <sproto.h>
27 elmex 1.1 #endif
28     #include <spells.h>
29     #include <loader.h>
30     #include <define.h>
31    
32     extern void sub_weight (object *, signed long);
33     extern void add_weight (object *, signed long);
34     extern long pticks;
35    
36     /* If flag is non zero, it means that we want to try and save everyone, but
37     * keep the game running. Thus, we don't want to free any information.
38     */
39 root 1.15 void
40     emergency_save (int flag)
41     {
42 elmex 1.1 player *pl;
43 root 1.15
44 elmex 1.1 #ifndef NO_EMERGENCY_SAVE
45     trying_emergency_save = 1;
46 root 1.15 if (editor)
47 elmex 1.1 return;
48 root 1.15 LOG (llevError, "Emergency save: ");
49     for (pl = first_player; pl != NULL; pl = pl->next)
50     {
51     if (!pl->ob)
52     {
53     LOG (llevError, "No name, ignoring this.\n");
54     continue;
55     }
56     LOG (llevError, "%s ", pl->ob->name);
57     new_draw_info (NDI_UNIQUE, 0, pl->ob, "Emergency save...");
58 elmex 1.1
59     /* If we are not exiting the game (ie, this is sort of a backup save), then
60     * don't change the location back to the village. Note that there are other
61     * options to have backup saves be done at the starting village
62     */
63 root 1.15 if (!flag)
64     {
65     strcpy (pl->maplevel, first_map_path);
66     if (pl->ob->map != NULL)
67 root 1.6 pl->ob->map = NULL;
68 root 1.15 pl->ob->x = -1;
69     pl->ob->y = -1;
70     }
71     if (!save_player (pl->ob, flag))
72     {
73     LOG (llevError, "(failed) ");
74     new_draw_info (NDI_UNIQUE, 0, pl->ob, "Emergency save failed, checking score...");
75     }
76     check_score (pl->ob);
77 elmex 1.1 }
78 root 1.15 LOG (llevError, "\n");
79 elmex 1.1 #else
80 root 1.15 LOG (llevInfo, "Emergency saves disabled, no save attempted\n");
81 elmex 1.1 #endif
82     /* If the game is exiting, remove the player locks */
83 root 1.15 if (!flag)
84     {
85     for (pl = first_player; pl != NULL; pl = pl->next)
86     {
87     if (pl->ob)
88     {
89     }
90     }
91 elmex 1.1 }
92     }
93    
94     /* Delete character with name. if new is set, also delete the new
95     * style directory, otherwise, just delete the old style playfile
96     * (needed for transition)
97     */
98 root 1.15 void
99     delete_character (const char *name, int newchar)
100     {
101     char buf[MAX_BUF];
102 elmex 1.1
103 root 1.15 sprintf (buf, "%s/%s/%s.pl", settings.localdir, settings.playerdir, name);
104     if (unlink (buf) == -1)
105     LOG (llevDebug, "Cannot delete character file %s: %s\n", buf, strerror (errno));
106     if (newchar)
107     {
108     sprintf (buf, "%s/%s/%s", settings.localdir, settings.playerdir, name);
109     /* this effectively does an rm -rf on the directory */
110     remove_directory (buf);
111 elmex 1.1 }
112     }
113    
114     /* This verify that a character of name exits, and that it matches
115     * password. It return 0 if there is match, 1 if no such player,
116     * 2 if incorrect password.
117     */
118    
119 root 1.15 int
120     verify_player (const char *name, char *password)
121 elmex 1.1 {
122 root 1.15 char buf[MAX_BUF];
123     int comp;
124     FILE *fp;
125    
126     if (strpbrk (name, "/.\\") != NULL)
127     {
128     LOG (llevError, "Username contains illegal characters: %s\n", name);
129     return 1;
130     }
131    
132     snprintf (buf, sizeof (buf), "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, name, name);
133     if (strlen (buf) >= sizeof (buf) - 1)
134     {
135     LOG (llevError, "Username too long: %s\n", name);
136     return 1;
137     }
138    
139     if ((fp = open_and_uncompress (buf, 0, &comp)) == NULL)
140     return 1;
141    
142     /* Read in the file until we find the password line. Our logic could
143     * be a bit better on cleaning up the password from the file, but since
144     * it is written by the program, I think it is fair to assume that the
145     * syntax should be pretty standard.
146     */
147     while (fgets (buf, MAX_BUF - 1, fp) != NULL)
148     {
149     if (!strncmp (buf, "password ", 9))
150     {
151     buf[strlen (buf) - 1] = 0; /* remove newline */
152     if (check_password (password, buf + 9))
153     {
154     close_and_delete (fp, comp);
155     return 0;
156 root 1.6 }
157 root 1.15 else
158     {
159     close_and_delete (fp, comp);
160     return 2;
161 root 1.6 }
162     }
163 elmex 1.1 }
164 root 1.15 LOG (llevDebug, "Could not find a password line in player %s\n", name);
165     close_and_delete (fp, comp);
166     return 1;
167 elmex 1.1 }
168    
169     /* Checks to see if anyone else by 'name' is currently playing.
170     * If we find that file or another character of some name is already in the
171     * game, we don't let this person join (we should really let the new player
172     * enter the password, and if correct, disconnect that socket and attach it to
173     * the players current session.
174     * If no one by that name is currently playing, we then make sure the name
175     * doesn't include any bogus characters.
176     * We return 0 if the name is in use/bad, 1 if it is OK to use this name.
177     */
178    
179 root 1.15 int
180     check_name (player *me, const char *name)
181     {
182     player *pl;
183 elmex 1.1
184 root 1.15 for (pl = first_player; pl != NULL; pl = pl->next)
185     if (pl != me && pl->ob->name != NULL && !strcmp (pl->ob->name, name))
186     {
187     new_draw_info (NDI_UNIQUE, 0, me->ob, "That name is already in use.");
188     return 0;
189     }
190 elmex 1.1
191 root 1.15 if (*name == '\0')
192     {
193     new_draw_info (NDI_UNIQUE, 0, me->ob, "Null names are not allowed.");
194     return 0;
195 elmex 1.1 }
196    
197 root 1.15 if (!playername_ok (name))
198     {
199     new_draw_info (NDI_UNIQUE, 0, me->ob, "That name contains illegal characters.");
200     return 0;
201 elmex 1.1 }
202 root 1.15 if (strlen (name) >= MAX_NAME)
203     {
204     new_draw_info (NDI_UNIQUE, 0, me->ob, "That name is too long.");
205     return 0;
206 elmex 1.1 }
207    
208 root 1.15 return 1;
209 elmex 1.1 }
210    
211 root 1.15 int
212     create_savedir_if_needed (char *savedir)
213 elmex 1.1 {
214     struct stat *buf;
215    
216 root 1.15 if ((buf = (struct stat *) malloc (sizeof (struct stat))) == NULL)
217     {
218     LOG (llevError, "Unable to save playerfile... out of memory.\n");
219     return 0;
220     }
221     else
222     {
223     stat (savedir, buf);
224     if (!S_ISDIR (buf->st_mode))
225     if (mkdir (savedir, SAVE_DIR_MODE))
226     {
227     LOG (llevError, "Unable to create player savedir %s: %s\n", savedir, strerror (errno));
228     return 0;
229     }
230     free (buf);
231     }
232     return 1;
233 elmex 1.1 }
234    
235 root 1.15 void
236     destroy_object (object *op)
237 elmex 1.1 {
238 root 1.15 object *tmp;
239    
240     while ((tmp = op->inv))
241     destroy_object (tmp);
242 elmex 1.1
243 root 1.15 if (!QUERY_FLAG (op, FLAG_REMOVED))
244     remove_ob (op);
245     free_object (op);
246 elmex 1.1 }
247    
248     /*
249     * If flag is set, it's only backup, ie dont remove objects from inventory
250     * If BACKUP_SAVE_AT_HOME is set, and the flag is set, then the player
251     * will be saved at the emergency save location.
252     * Returns non zero if successful.
253     */
254    
255 root 1.15 int
256     save_player (object *op, int flag)
257     {
258     object *tmp, *container = NULL;
259 elmex 1.1 player *pl = op->contr;
260 root 1.15 int i, wiz = QUERY_FLAG (op, FLAG_WIZ);
261    
262 elmex 1.1 #ifdef BACKUP_SAVE_AT_HOME
263     sint16 backup_x, backup_y;
264     #endif
265    
266 root 1.15 if (!op->stats.exp)
267     return 0; /* no experience, no save */
268 elmex 1.1
269 root 1.15 flag &= 1;
270 elmex 1.1
271 root 1.15 if (!pl->name_changed || (!flag && !op->stats.exp))
272     {
273     if (!flag)
274     {
275     new_draw_info (NDI_UNIQUE, 0, op, "Your game is not valid,");
276     new_draw_info (NDI_UNIQUE, 0, op, "Game not saved.");
277     }
278     return 0;
279 elmex 1.1 }
280 root 1.15
281     /* Sanity check - some stuff changes this when player is exiting */
282     if (op->type != PLAYER)
283 elmex 1.1 return 0;
284    
285 root 1.15 /* Prevent accidental saves if connection is reset after player has
286     * mostly exited.
287     */
288     if (pl->state != ST_PLAYING && pl->state != ST_GET_PARTY_PASSWORD)
289     return 0;
290 elmex 1.1
291 root 1.9 INVOKE_PLAYER (SAVE, op->contr);
292 root 1.5
293 elmex 1.1 if (flag == 0)
294 root 1.15 terminate_all_pets (op);
295 elmex 1.1
296 root 1.9 object_freezer freezer;
297 root 1.3
298 root 1.9 /* Eneq(@csd.uu.se): If we have an open container hide it. */
299     if (op->container)
300 root 1.5 {
301 root 1.9 container = op->container;
302     op->container = NULL;
303 root 1.5 }
304 elmex 1.1
305 root 1.15 fprintf (freezer, "password %s\n", pl->password);
306 root 1.3
307 elmex 1.1 if (settings.set_title == TRUE)
308 root 1.15 if (pl->own_title[0] != '\0')
309     fprintf (freezer, "title %s\n", pl->own_title);
310 elmex 1.1
311 root 1.15 fprintf (freezer, "explore %d\n", pl->explore);
312     fprintf (freezer, "gen_hp %d\n", pl->gen_hp);
313     fprintf (freezer, "gen_sp %d\n", pl->gen_sp);
314     fprintf (freezer, "gen_grace %d\n", pl->gen_grace);
315     fprintf (freezer, "listening %d\n", pl->listening);
316     fprintf (freezer, "shoottype %d\n", pl->shoottype);
317     fprintf (freezer, "bowtype %d\n", pl->bowtype);
318     fprintf (freezer, "petmode %d\n", pl->petmode);
319     fprintf (freezer, "peaceful %d\n", pl->peaceful);
320     fprintf (freezer, "no_shout %d\n", pl->no_shout);
321     fprintf (freezer, "digestion %d\n", pl->digestion);
322     fprintf (freezer, "pickup %d\n", pl->mode);
323     fprintf (freezer, "outputs_sync %d\n", pl->outputs_sync);
324     fprintf (freezer, "outputs_count %d\n", pl->outputs_count);
325 elmex 1.1 /* Match the enumerations but in string form */
326 root 1.15 fprintf (freezer, "usekeys %s\n", pl->usekeys == key_inventory ? "key_inventory" : (pl->usekeys == keyrings ? "keyrings" : "containers"));
327 elmex 1.1 /* Match the enumerations but in string form */
328 root 1.15 fprintf (freezer, "unapply %s\n", pl->unapply == unapply_nochoice ? "unapply_nochoice" :
329     (pl->unapply == unapply_never ? "unapply_never" : "unapply_always"));
330 elmex 1.1
331     #ifdef BACKUP_SAVE_AT_HOME
332 root 1.15 if (op->map != NULL && flag == 0)
333 elmex 1.1 #else
334 root 1.15 if (op->map != NULL)
335 elmex 1.1 #endif
336 root 1.15 fprintf (freezer, "map %s\n", op->map->path);
337 elmex 1.1 else
338 root 1.15 fprintf (freezer, "map %s\n", settings.emergency_mapname);
339    
340     fprintf (freezer, "savebed_map %s\n", pl->savebed_map);
341     fprintf (freezer, "bed_x %d\nbed_y %d\n", pl->bed_x, pl->bed_y);
342     fprintf (freezer, "weapon_sp %f\n", pl->weapon_sp);
343     fprintf (freezer, "Str %d\n", pl->orig_stats.Str);
344     fprintf (freezer, "Dex %d\n", pl->orig_stats.Dex);
345     fprintf (freezer, "Con %d\n", pl->orig_stats.Con);
346     fprintf (freezer, "Int %d\n", pl->orig_stats.Int);
347     fprintf (freezer, "Pow %d\n", pl->orig_stats.Pow);
348     fprintf (freezer, "Wis %d\n", pl->orig_stats.Wis);
349     fprintf (freezer, "Cha %d\n", pl->orig_stats.Cha);
350    
351     fprintf (freezer, "lev_array %d\n", op->level > 10 ? 10 : op->level);
352     for (i = 1; i <= pl->last_level && i <= 10; i++)
353     {
354     fprintf (freezer, "%d\n", pl->levhp[i]);
355     fprintf (freezer, "%d\n", pl->levsp[i]);
356     fprintf (freezer, "%d\n", pl->levgrace[i]);
357     }
358 root 1.4
359 root 1.9 freezer.put (op->contr);
360 root 1.4
361 root 1.15 fprintf (freezer, "endplst\n");
362 elmex 1.1
363 root 1.15 SET_FLAG (op, FLAG_NO_FIX_PLAYER);
364     CLEAR_FLAG (op, FLAG_WIZ);
365 elmex 1.1 #ifdef BACKUP_SAVE_AT_HOME
366 root 1.15 if (flag)
367     {
368     backup_x = op->x;
369     backup_y = op->y;
370     op->x = -1;
371     op->y = -1;
372     }
373 elmex 1.1 /* Save objects, but not unpaid objects. Don't remove objects from
374     * inventory.
375     */
376 root 1.15 save_object (freezer, op, 2);
377     if (flag)
378     {
379     op->x = backup_x;
380     op->y = backup_y;
381     }
382 elmex 1.1 #else
383 root 1.15 save_object (freezer, op, 3); /* don't check and don't remove */
384 elmex 1.1 #endif
385    
386 root 1.9 char filename[MAX_BUF];
387 root 1.15
388     sprintf (filename, "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, &op->name, &op->name);
389     make_path_to_file (filename);
390 root 1.9 freezer.save (filename);
391    
392 root 1.15 CLEAR_FLAG (op, FLAG_NO_FIX_PLAYER);
393 elmex 1.1
394 root 1.15 if (!flag)
395     while ((tmp = op->inv))
396     destroy_object (tmp);
397 elmex 1.1
398     /* Eneq(@csd.uu.se): Reveal the container if we have one. */
399 root 1.15 if (flag && container != NULL)
400 elmex 1.1 op->container = container;
401    
402 root 1.15 if (wiz)
403     SET_FLAG (op, FLAG_WIZ);
404 root 1.5
405 root 1.15 if (!flag)
406     esrv_send_inventory (op, op);
407 elmex 1.1
408     return 1;
409     }
410    
411 root 1.15 void
412     check_login (object *op)
413     {
414     char filename[MAX_BUF];
415     char buf[MAX_BUF], bufall[MAX_BUF];
416     int i, value;
417     player *pl = op->contr;
418     int correct = 0;
419    
420     strcpy (pl->maplevel, first_map_path);
421     sprintf (filename, "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, &op->name, &op->name);
422    
423     object_thawer thawer (filename);
424    
425     /* If no file, must be a new player, so lets get confirmation of
426     * the password. Return control to the higher level dispatch,
427     * since the rest of this just deals with loading of the file.
428     */
429     if (!thawer)
430     {
431     confirm_password (op);
432     return;
433 elmex 1.1 }
434 root 1.3
435 root 1.15 if (fgets (bufall, MAX_BUF, thawer) != NULL)
436     {
437     if (sscanf (bufall, "password %s\n", buf))
438     {
439     /* New password scheme: */
440     correct = check_password (pl->write_buf + 1, buf);
441 root 1.6 }
442 root 1.15 }
443 root 1.16
444 root 1.15 if (!correct)
445     {
446     new_draw_info (NDI_UNIQUE, 0, op, " ");
447     new_draw_info (NDI_UNIQUE, 0, op, "Wrong Password!");
448     new_draw_info (NDI_UNIQUE, 0, op, " ");
449     op->name = op->name_pl = "noname";
450     op->contr->socket.password_fails++;
451     if (op->contr->socket.password_fails >= MAX_PASSWORD_FAILURES)
452     {
453     new_draw_info (NDI_UNIQUE, 0, op, "You gave an incorrect password too many times, you will now be dropped from the server.");
454     LOG (llevInfo, "A player connecting from %s has been dropped for password failure\n", op->contr->socket.host);
455     op->contr->socket.status = Ns_Dead; /* the socket loop should handle the rest for us */
456     }
457     else
458     get_name (op);
459 root 1.19
460 root 1.15 return; /* Once again, rest of code just loads the char */
461 elmex 1.1 }
462    
463     #ifdef SAVE_INTERVAL
464 root 1.15 pl->last_save_time = time (NULL);
465 elmex 1.1 #endif /* SAVE_INTERVAL */
466 root 1.15 pl->party = NULL;
467     if (settings.search_items == TRUE)
468     pl->search_str[0] = '\0';
469     pl->name_changed = 1;
470     pl->orig_stats.Str = 0;
471     pl->orig_stats.Dex = 0;
472     pl->orig_stats.Con = 0;
473     pl->orig_stats.Int = 0;
474     pl->orig_stats.Pow = 0;
475     pl->orig_stats.Wis = 0;
476     pl->orig_stats.Cha = 0;
477     strcpy (pl->savebed_map, first_map_path);
478     pl->bed_x = 0, pl->bed_y = 0;
479     pl->spellparam[0] = '\0';
480    
481     /* Loop through the file, loading the rest of the values */
482     while (fgets (bufall, MAX_BUF, thawer) != NULL)
483     {
484     sscanf (bufall, "%s %d\n", buf, &value);
485     if (!strcmp (buf, "endplst"))
486     break;
487     else if (!strcmp (buf, "oid"))
488     thawer.get (pl, value);
489     else if (!strcmp (buf, "title") && settings.set_title == TRUE)
490     sscanf (bufall, "title %[^\n]", pl->own_title);
491     else if (!strcmp (buf, "explore"))
492     pl->explore = value;
493     else if (!strcmp (buf, "gen_hp"))
494     pl->gen_hp = value;
495     else if (!strcmp (buf, "shoottype"))
496     pl->shoottype = (rangetype) value;
497     else if (!strcmp (buf, "bowtype"))
498     pl->bowtype = (bowtype_t) value;
499     else if (!strcmp (buf, "petmode"))
500     pl->petmode = (petmode_t) value;
501     else if (!strcmp (buf, "gen_sp"))
502     pl->gen_sp = value;
503     else if (!strcmp (buf, "gen_grace"))
504     pl->gen_grace = value;
505     else if (!strcmp (buf, "listening"))
506     pl->listening = value;
507     else if (!strcmp (buf, "peaceful"))
508     pl->peaceful = value;
509     else if (!strcmp (buf, "no_shout"))
510     pl->no_shout = value;
511     else if (!strcmp (buf, "digestion"))
512     pl->digestion = value;
513     else if (!strcmp (buf, "pickup"))
514     pl->mode = value;
515     else if (!strcmp (buf, "outputs_sync"))
516     pl->outputs_sync = value;
517     else if (!strcmp (buf, "outputs_count"))
518     pl->outputs_count = value;
519     else if (!strcmp (buf, "map"))
520     sscanf (bufall, "map %s", pl->maplevel);
521     else if (!strcmp (buf, "savebed_map"))
522     sscanf (bufall, "savebed_map %s", pl->savebed_map);
523     else if (!strcmp (buf, "bed_x"))
524     pl->bed_x = value;
525     else if (!strcmp (buf, "bed_y"))
526     pl->bed_y = value;
527     else if (!strcmp (buf, "weapon_sp"))
528     sscanf (buf, "weapon_sp %f", &pl->weapon_sp);
529     else if (!strcmp (buf, "Str"))
530     pl->orig_stats.Str = value;
531     else if (!strcmp (buf, "Dex"))
532     pl->orig_stats.Dex = value;
533     else if (!strcmp (buf, "Con"))
534     pl->orig_stats.Con = value;
535     else if (!strcmp (buf, "Int"))
536     pl->orig_stats.Int = value;
537     else if (!strcmp (buf, "Pow"))
538     pl->orig_stats.Pow = value;
539     else if (!strcmp (buf, "Wis"))
540     pl->orig_stats.Wis = value;
541     else if (!strcmp (buf, "Cha"))
542     pl->orig_stats.Cha = value;
543     else if (!strcmp (buf, "usekeys"))
544     {
545     if (!strcmp (bufall + 8, "key_inventory\n"))
546     pl->usekeys = key_inventory;
547     else if (!strcmp (bufall + 8, "keyrings\n"))
548     pl->usekeys = keyrings;
549     else if (!strcmp (bufall + 8, "containers\n"))
550     pl->usekeys = containers;
551     else
552     LOG (llevDebug, "load_player: got unknown usekeys type: %s\n", bufall + 8);
553 root 1.6 }
554 root 1.15 else if (!strcmp (buf, "unapply"))
555     {
556     if (!strcmp (bufall + 8, "unapply_nochoice\n"))
557     pl->unapply = unapply_nochoice;
558     else if (!strcmp (bufall + 8, "unapply_never\n"))
559     pl->unapply = unapply_never;
560     else if (!strcmp (bufall + 8, "unapply_always\n"))
561     pl->unapply = unapply_always;
562     else
563     LOG (llevDebug, "load_player: got unknown unapply type: %s\n", bufall + 8);
564     }
565     else if (!strcmp (buf, "lev_array"))
566     {
567     for (i = 1; i <= value; i++)
568     {
569     char line[128];
570    
571     fgets (line, 128, thawer);
572     pl->levhp[i] = atoi (line);
573     fgets (line, 128, thawer);
574     pl->levsp[i] = atoi (line);
575     fgets (line, 128, thawer);
576     pl->levgrace[i] = atoi (line);
577     }
578     /* spell_array code removed - don't know when that was last used.
579     * Even the load code below will someday be replaced by spells being
580     * objects.
581     */
582     }
583     else if (!strcmp (buf, "known_spell"))
584     {
585     #if 0
586     /* Logic is left here in case someone wants to try
587     * and write code to update to spell objects.
588     */
589     char *cp = strchr (bufall, '\n');
590    
591     *cp = '\0';
592     cp = strchr (bufall, ' ');
593     cp++;
594     for (i = 0; i < NROFREALSPELLS; i++)
595     if (!strcmp (spells[i].name, cp))
596 root 1.11 {
597 root 1.15 pl->known_spells[pl->nrofknownspells++] = i;
598     break;
599 root 1.11 }
600 root 1.15 if (i == NROFREALSPELLS)
601     LOG (llevDebug, "Error: unknown spell (%s)\n", cp);
602 elmex 1.1 #endif
603 root 1.6 }
604 root 1.15 } /* End of loop loading the character file */
605 root 1.19
606 root 1.15 leave_map (op);
607     op->speed = 0;
608     update_ob_speed (op);
609    
610     clear_object (op);
611    
612     op->contr = pl;
613     pl->ob = op;
614    
615     /* this loads the standard objects values. */
616     load_object (thawer, op, 0);
617    
618     CLEAR_FLAG (op, FLAG_NO_FIX_PLAYER);
619    
620 root 1.17 assign (pl->title, op->arch->clone.name);
621 root 1.15
622     /* If the map where the person was last saved does not exist,
623     * restart them on their home-savebed. This is good for when
624     * maps change between versions
625     * First, we check for partial path, then check to see if the full
626     * path (for unique player maps)
627     */
628     if (check_path (pl->maplevel, 1) == -1)
629     {
630     if (check_path (pl->maplevel, 0) == -1)
631     {
632     strcpy (pl->maplevel, pl->savebed_map);
633     op->x = pl->bed_x, op->y = pl->bed_y;
634     }
635 elmex 1.1 }
636    
637 root 1.15 /* make sure he's a player--needed because of class change. */
638     op->type = PLAYER;
639 elmex 1.1
640 root 1.15 enter_exit (op, NULL);
641 elmex 1.1
642 root 1.15 pl->name_changed = 1;
643     pl->state = ST_PLAYING;
644 elmex 1.1 #ifdef AUTOSAVE
645 root 1.15 pl->last_save_tick = pticks;
646 elmex 1.1 #endif
647 root 1.15 op->carrying = sum_weight (op);
648     /* Need to call fix_player now - program modified so that it is not
649     * called during the load process (FLAG_NO_FIX_PLAYER set when
650     * saved)
651     * Moved ahead of the esrv functions, so proper weights will be
652     * sent to the client.
653     */
654     link_player_skills (op);
655    
656     if (!legal_range (op, op->contr->shoottype))
657     op->contr->shoottype = range_none;
658    
659     fix_player (op);
660    
661     /* if it's a dragon player, set the correct title here */
662     if (is_dragon_pl (op) && op->inv != NULL)
663     {
664     object *tmp, *abil = NULL, *skin = NULL;
665    
666     for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
667     {
668     if (tmp->type == FORCE)
669     {
670     if (strcmp (tmp->arch->name, "dragon_ability_force") == 0)
671     abil = tmp;
672     else if (strcmp (tmp->arch->name, "dragon_skin_force") == 0)
673     skin = tmp;
674 root 1.6 }
675     }
676 root 1.15 set_dragon_name (op, abil, skin);
677     }
678    
679     new_draw_info (NDI_UNIQUE, 0, op, "Welcome Back!");
680     new_draw_info_format (NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, NULL, "%s has entered the game.", &pl->ob->name);
681    
682     INVOKE_PLAYER (LOAD, pl, ARG_STRING (filename));
683     INVOKE_PLAYER (LOGIN, pl);
684    
685     op->contr->socket.update_look = 1;
686     /* If the player should be dead, call kill_player for them
687     * Only check for hp - if player lacks food, let the normal
688     * logic for that to take place. If player is permanently
689     * dead, and not using permadeath mode, the kill_player will
690     * set the play_again flag, so return.
691     */
692     if (op->stats.hp < 0)
693     {
694     new_draw_info (NDI_UNIQUE, 0, op, "Your character was dead last your played.");
695     kill_player (op);
696     if (pl->state != ST_PLAYING)
697     return;
698 elmex 1.1 }
699 root 1.15 LOG (llevInfo, "LOGIN: Player named %s from ip %s\n", &op->name, op->contr->socket.host);
700    
701     /* Do this after checking for death - no reason sucking up bandwidth if
702     * the data isn't needed.
703     */
704     esrv_new_player (op->contr, op->weight + op->carrying);
705     esrv_send_inventory (op, op);
706     esrv_add_spells (op->contr, NULL);
707    
708     CLEAR_FLAG (op, FLAG_FRIENDLY);
709    
710     /* can_use_shield is a new flag. However, the can_use.. seems to largely come
711     * from the class, and not race. I don't see any way to get the class information
712     * to then update this. I don't think this will actually break anything - anyone
713     * that can use armour should be able to use a shield. What this may 'break'
714     * are features new characters get, eg, if someone starts up with a Q, they
715     * should be able to use a shield. However, old Q's won't get that advantage.
716     */
717     if (QUERY_FLAG (op, FLAG_USE_ARMOUR))
718     SET_FLAG (op, FLAG_USE_SHIELD);
719 root 1.20
720 root 1.15 return;
721 elmex 1.1 }