ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/login.C
Revision: 1.13
Committed: Thu Sep 7 10:01:58 2006 UTC (17 years, 9 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.12: +10 -18 lines
Log Message:
Some cleanups.

File Contents

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