1 | /* |
1 | /* |
2 | * static char *rcsid_login_c = |
2 | * static char *rcsid_login_c = |
3 | * "$Id: login.C,v 1.5 2006/08/28 14:05:24 root Exp $"; |
3 | * "$Id: login.C,v 1.6 2006/08/29 08:01:37 root Exp $"; |
4 | */ |
4 | */ |
5 | |
5 | |
6 | /* |
6 | /* |
7 | CrossFire, A Multiplayer game for X-windows |
7 | CrossFire, A Multiplayer game for X-windows |
8 | |
8 | |
… | |
… | |
59 | /* If we are not exiting the game (ie, this is sort of a backup save), then |
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 |
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 |
61 | * options to have backup saves be done at the starting village |
62 | */ |
62 | */ |
63 | if (!flag) { |
63 | if (!flag) { |
64 | strcpy(pl->maplevel, first_map_path); |
64 | strcpy(pl->maplevel, first_map_path); |
65 | if(pl->ob->map!=NULL) |
65 | if(pl->ob->map!=NULL) |
66 | pl->ob->map = NULL; |
66 | pl->ob->map = NULL; |
67 | pl->ob->x = -1; |
67 | pl->ob->x = -1; |
68 | pl->ob->y = -1; |
68 | pl->ob->y = -1; |
69 | } |
69 | } |
70 | if(!save_player(pl->ob,flag)) { |
70 | if(!save_player(pl->ob,flag)) { |
71 | LOG(llevError, "(failed) "); |
71 | LOG(llevError, "(failed) "); |
72 | new_draw_info(NDI_UNIQUE, 0,pl->ob,"Emergency save failed, checking score..."); |
72 | new_draw_info(NDI_UNIQUE, 0,pl->ob,"Emergency save failed, checking score..."); |
73 | } |
73 | } |
… | |
… | |
93 | void delete_character(const char *name, int newchar) { |
93 | void delete_character(const char *name, int newchar) { |
94 | char buf[MAX_BUF]; |
94 | char buf[MAX_BUF]; |
95 | |
95 | |
96 | sprintf(buf,"%s/%s/%s.pl",settings.localdir,settings.playerdir,name); |
96 | sprintf(buf,"%s/%s/%s.pl",settings.localdir,settings.playerdir,name); |
97 | if(unlink(buf)== -1) |
97 | if(unlink(buf)== -1) |
98 | LOG(llevDebug, "Cannot delete character file %s: %s\n", buf, strerror_local(errno)); |
98 | LOG(llevDebug, "Cannot delete character file %s: %s\n", buf, strerror_local(errno)); |
99 | if (newchar) { |
99 | if (newchar) { |
100 | sprintf(buf,"%s/%s/%s",settings.localdir,settings.playerdir,name); |
100 | sprintf(buf,"%s/%s/%s",settings.localdir,settings.playerdir,name); |
101 | /* this effectively does an rm -rf on the directory */ |
101 | /* this effectively does an rm -rf on the directory */ |
102 | remove_directory(buf); |
102 | remove_directory(buf); |
103 | } |
103 | } |
104 | } |
104 | } |
105 | |
105 | |
106 | /* This verify that a character of name exits, and that it matches |
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, |
107 | * password. It return 0 if there is match, 1 if no such player, |
… | |
… | |
113 | char buf[MAX_BUF]; |
113 | char buf[MAX_BUF]; |
114 | int comp; |
114 | int comp; |
115 | FILE *fp; |
115 | FILE *fp; |
116 | |
116 | |
117 | if (strpbrk(name, "/.\\") != NULL) { |
117 | if (strpbrk(name, "/.\\") != NULL) { |
118 | LOG(llevError, "Username contains illegal characters: %s\n", name); |
118 | LOG(llevError, "Username contains illegal characters: %s\n", name); |
119 | return 1; |
119 | return 1; |
120 | } |
120 | } |
121 | |
121 | |
122 | snprintf(buf, sizeof(buf), "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, name, name); |
122 | snprintf(buf, sizeof(buf), "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, name, name); |
123 | if (strlen(buf) >= sizeof(buf)-1) { |
123 | if (strlen(buf) >= sizeof(buf)-1) { |
124 | LOG(llevError, "Username too long: %s\n", name); |
124 | LOG(llevError, "Username too long: %s\n", name); |
125 | return 1; |
125 | return 1; |
126 | } |
126 | } |
127 | |
127 | |
128 | if ((fp=open_and_uncompress(buf,0,&comp))==NULL) return 1; |
128 | if ((fp=open_and_uncompress(buf,0,&comp))==NULL) return 1; |
129 | |
129 | |
130 | /* Read in the file until we find the password line. Our logic could |
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 |
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 |
132 | * it is written by the program, I think it is fair to assume that the |
133 | * syntax should be pretty standard. |
133 | * syntax should be pretty standard. |
134 | */ |
134 | */ |
135 | while (fgets(buf, MAX_BUF-1, fp) != NULL) { |
135 | while (fgets(buf, MAX_BUF-1, fp) != NULL) { |
136 | if (!strncmp(buf,"password ",9)) { |
136 | if (!strncmp(buf,"password ",9)) { |
137 | buf[strlen(buf)-1]=0; /* remove newline */ |
137 | buf[strlen(buf)-1]=0; /* remove newline */ |
138 | if (check_password(password, buf+9)) { |
138 | if (check_password(password, buf+9)) { |
139 | close_and_delete(fp, comp); |
139 | close_and_delete(fp, comp); |
140 | return 0; |
140 | return 0; |
141 | } |
141 | } |
142 | else { |
142 | else { |
143 | close_and_delete(fp, comp); |
143 | close_and_delete(fp, comp); |
144 | return 2; |
144 | return 2; |
145 | } |
145 | } |
146 | } |
146 | } |
147 | } |
147 | } |
148 | LOG(llevDebug,"Could not find a password line in player %s\n", name); |
148 | LOG(llevDebug,"Could not find a password line in player %s\n", name); |
149 | close_and_delete(fp, comp); |
149 | close_and_delete(fp, comp); |
150 | return 1; |
150 | return 1; |
151 | } |
151 | } |
… | |
… | |
162 | |
162 | |
163 | int check_name(player *me,const char *name) { |
163 | int check_name(player *me,const char *name) { |
164 | player *pl; |
164 | player *pl; |
165 | |
165 | |
166 | for(pl=first_player;pl!=NULL;pl=pl->next) |
166 | for(pl=first_player;pl!=NULL;pl=pl->next) |
167 | if(pl!=me&&pl->ob->name!=NULL&&!strcmp(pl->ob->name,name)) { |
167 | 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."); |
168 | new_draw_info(NDI_UNIQUE, 0,me->ob,"That name is already in use."); |
169 | return 0; |
169 | return 0; |
170 | } |
170 | } |
171 | |
171 | |
172 | if (*name=='\0') { |
172 | if (*name=='\0') { |
173 | new_draw_info(NDI_UNIQUE, 0,me->ob,"Null names are not allowed."); |
173 | new_draw_info(NDI_UNIQUE, 0,me->ob,"Null names are not allowed."); |
174 | return 0; |
174 | return 0; |
175 | } |
175 | } |
176 | |
176 | |
177 | if(!playername_ok(name)) { |
177 | if(!playername_ok(name)) { |
178 | new_draw_info(NDI_UNIQUE, 0,me->ob,"That name contains illegal characters."); |
178 | new_draw_info(NDI_UNIQUE, 0,me->ob,"That name contains illegal characters."); |
179 | return 0; |
179 | return 0; |
180 | } |
180 | } |
181 | if (strlen(name) >= MAX_NAME) { |
181 | if (strlen(name) >= MAX_NAME) { |
182 | new_draw_info(NDI_UNIQUE, 0,me->ob,"That name is too long."); |
182 | new_draw_info(NDI_UNIQUE, 0,me->ob,"That name is too long."); |
183 | return 0; |
183 | return 0; |
184 | } |
184 | } |
185 | |
185 | |
186 | return 1; |
186 | return 1; |
187 | } |
187 | } |
188 | |
188 | |
… | |
… | |
195 | return 0; |
195 | return 0; |
196 | } else { |
196 | } else { |
197 | stat(savedir, buf); |
197 | stat(savedir, buf); |
198 | if (!S_ISDIR(buf->st_mode)) |
198 | if (!S_ISDIR(buf->st_mode)) |
199 | if (mkdir(savedir, SAVE_DIR_MODE)) |
199 | if (mkdir(savedir, SAVE_DIR_MODE)) |
200 | { |
200 | { |
201 | LOG(llevError, "Unable to create player savedir %s: %s\n", savedir, strerror_local(errno)); |
201 | LOG(llevError, "Unable to create player savedir %s: %s\n", savedir, strerror_local(errno)); |
202 | return 0; |
202 | return 0; |
203 | } |
203 | } |
204 | free(buf); |
204 | free(buf); |
205 | } |
205 | } |
206 | return 1; |
206 | return 1; |
207 | } |
207 | } |
208 | |
208 | |
209 | void destroy_object (object *op) |
209 | void destroy_object (object *op) |
210 | { |
210 | { |
211 | object *tmp; |
211 | object *tmp; |
212 | while ((tmp = op->inv)) |
212 | while ((tmp = op->inv)) |
213 | destroy_object (tmp); |
213 | destroy_object (tmp); |
214 | |
214 | |
215 | if (!QUERY_FLAG(op, FLAG_REMOVED)) |
215 | if (!QUERY_FLAG(op, FLAG_REMOVED)) |
216 | remove_ob(op); |
216 | remove_ob(op); |
217 | free_object(op); |
217 | free_object(op); |
218 | } |
218 | } |
219 | |
219 | |
220 | /* |
220 | /* |
221 | * If flag is set, it's only backup, ie dont remove objects from inventory |
221 | * If flag is set, it's only backup, ie dont remove objects from inventory |
… | |
… | |
251 | |
251 | |
252 | /* Prevent accidental saves if connection is reset after player has |
252 | /* Prevent accidental saves if connection is reset after player has |
253 | * mostly exited. |
253 | * mostly exited. |
254 | */ |
254 | */ |
255 | if (pl->state != ST_PLAYING && pl->state != ST_GET_PARTY_PASSWORD) |
255 | if (pl->state != ST_PLAYING && pl->state != ST_GET_PARTY_PASSWORD) |
256 | return 0; |
256 | return 0; |
257 | |
257 | |
258 | INVOKE_PLAYER (SAVE, op->contr, ARG_STRING (filename)); |
258 | INVOKE_PLAYER (SAVE, op->contr, ARG_STRING (filename)); |
259 | |
259 | |
260 | if (flag == 0) |
260 | if (flag == 0) |
261 | terminate_all_pets(op); |
261 | terminate_all_pets(op); |
… | |
… | |
280 | |
280 | |
281 | fprintf(fp,"password %s\n",pl->password); |
281 | fprintf(fp,"password %s\n",pl->password); |
282 | |
282 | |
283 | if (settings.set_title == TRUE) |
283 | if (settings.set_title == TRUE) |
284 | if(pl->own_title[0]!='\0') |
284 | if(pl->own_title[0]!='\0') |
285 | fprintf(fp,"title %s\n",pl->own_title); |
285 | fprintf(fp,"title %s\n",pl->own_title); |
286 | |
286 | |
287 | fprintf(fp,"explore %d\n",pl->explore); |
287 | fprintf(fp,"explore %d\n",pl->explore); |
288 | fprintf(fp,"gen_hp %d\n",pl->gen_hp); |
288 | fprintf(fp,"gen_hp %d\n",pl->gen_hp); |
289 | fprintf(fp,"gen_sp %d\n",pl->gen_sp); |
289 | fprintf(fp,"gen_sp %d\n",pl->gen_sp); |
290 | fprintf(fp,"gen_grace %d\n",pl->gen_grace); |
290 | fprintf(fp,"gen_grace %d\n",pl->gen_grace); |
… | |
… | |
298 | fprintf(fp,"pickup %d\n", pl->mode); |
298 | fprintf(fp,"pickup %d\n", pl->mode); |
299 | fprintf(fp,"outputs_sync %d\n", pl->outputs_sync); |
299 | fprintf(fp,"outputs_sync %d\n", pl->outputs_sync); |
300 | fprintf(fp,"outputs_count %d\n", pl->outputs_count); |
300 | fprintf(fp,"outputs_count %d\n", pl->outputs_count); |
301 | /* Match the enumerations but in string form */ |
301 | /* Match the enumerations but in string form */ |
302 | fprintf(fp,"usekeys %s\n", pl->usekeys==key_inventory?"key_inventory": |
302 | fprintf(fp,"usekeys %s\n", pl->usekeys==key_inventory?"key_inventory": |
303 | (pl->usekeys==keyrings?"keyrings":"containers")); |
303 | (pl->usekeys==keyrings?"keyrings":"containers")); |
304 | /* Match the enumerations but in string form */ |
304 | /* Match the enumerations but in string form */ |
305 | fprintf(fp,"unapply %s\n", pl->unapply==unapply_nochoice?"unapply_nochoice": |
305 | fprintf(fp,"unapply %s\n", pl->unapply==unapply_nochoice?"unapply_nochoice": |
306 | (pl->unapply==unapply_never?"unapply_never":"unapply_always")); |
306 | (pl->unapply==unapply_never?"unapply_never":"unapply_always")); |
307 | |
307 | |
308 | #ifdef BACKUP_SAVE_AT_HOME |
308 | #ifdef BACKUP_SAVE_AT_HOME |
309 | if (op->map!=NULL && flag==0) |
309 | if (op->map!=NULL && flag==0) |
310 | #else |
310 | #else |
311 | if (op->map!=NULL) |
311 | if (op->map!=NULL) |
… | |
… | |
327 | |
327 | |
328 | fprintf(fp,"lev_array %d\n",op->level>10?10:op->level); |
328 | fprintf(fp,"lev_array %d\n",op->level>10?10:op->level); |
329 | for(i=1;i<=pl->last_level&&i<=10;i++) { |
329 | for(i=1;i<=pl->last_level&&i<=10;i++) { |
330 | fprintf(fp,"%d\n",pl->levhp[i]); |
330 | fprintf(fp,"%d\n",pl->levhp[i]); |
331 | fprintf(fp,"%d\n",pl->levsp[i]); |
331 | fprintf(fp,"%d\n",pl->levsp[i]); |
332 | fprintf(fp,"%d\n",pl->levgrace[i]); |
332 | fprintf(fp,"%d\n",pl->levgrace[i]); |
333 | } |
333 | } |
334 | |
334 | |
335 | fp.put (op->contr); |
335 | fp.put (op->contr); |
336 | |
336 | |
337 | fprintf(fp,"endplst\n"); |
337 | fprintf(fp,"endplst\n"); |
… | |
… | |
359 | |
359 | |
360 | CLEAR_FLAG(op, FLAG_NO_FIX_PLAYER); |
360 | CLEAR_FLAG(op, FLAG_NO_FIX_PLAYER); |
361 | |
361 | |
362 | if(!flag) |
362 | if(!flag) |
363 | while ((tmp = op->inv)) |
363 | while ((tmp = op->inv)) |
364 | destroy_object (tmp); |
364 | destroy_object (tmp); |
365 | |
365 | |
366 | /* Eneq(@csd.uu.se): Reveal the container if we have one. */ |
366 | /* Eneq(@csd.uu.se): Reveal the container if we have one. */ |
367 | if (flag&&container!=NULL) |
367 | if (flag&&container!=NULL) |
368 | op->container = container; |
368 | op->container = container; |
369 | |
369 | |
370 | if (wiz) SET_FLAG(op,FLAG_WIZ); |
370 | if (wiz) SET_FLAG(op,FLAG_WIZ); |
371 | |
371 | |
372 | if(!flag) |
372 | if(!flag) |
373 | esrv_send_inventory(op, op); |
373 | esrv_send_inventory(op, op); |
374 | |
374 | |
375 | return 1; |
375 | return 1; |
376 | } |
376 | } |
377 | |
377 | |
378 | void check_login(object *op) { |
378 | void check_login(object *op) { |
… | |
… | |
393 | /* If no file, must be a new player, so lets get confirmation of |
393 | /* If no file, must be a new player, so lets get confirmation of |
394 | * the password. Return control to the higher level dispatch, |
394 | * the password. Return control to the higher level dispatch, |
395 | * since the rest of this just deals with loading of the file. |
395 | * since the rest of this just deals with loading of the file. |
396 | */ |
396 | */ |
397 | if ((fp=open_and_uncompress(filename,1,&comp)) == NULL) { |
397 | if ((fp=open_and_uncompress(filename,1,&comp)) == NULL) { |
398 | confirm_password(op); |
398 | confirm_password(op); |
399 | return; |
399 | return; |
400 | } |
400 | } |
401 | if (fstat(fileno(fp), &statbuf)) { |
401 | if (fstat(fileno(fp), &statbuf)) { |
402 | LOG(llevError,"Unable to stat %s?\n", filename); |
402 | LOG(llevError,"Unable to stat %s?\n", filename); |
403 | elapsed_save_time=0; |
403 | elapsed_save_time=0; |
404 | } else { |
404 | } else { |
405 | elapsed_save_time = time(NULL) - statbuf.st_mtime; |
405 | elapsed_save_time = time(NULL) - statbuf.st_mtime; |
406 | if (elapsed_save_time<0) { |
406 | if (elapsed_save_time<0) { |
407 | LOG(llevError,"Player file %s was saved in the future? (%d time)\n", filename, elapsed_save_time); |
407 | LOG(llevError,"Player file %s was saved in the future? (%d time)\n", filename, elapsed_save_time); |
408 | elapsed_save_time=0; |
408 | elapsed_save_time=0; |
409 | } |
409 | } |
410 | } |
410 | } |
411 | |
411 | |
412 | object_thawer thawer (fp, filename); |
412 | object_thawer thawer (fp, filename); |
413 | |
413 | |
414 | if(fgets(bufall,MAX_BUF,fp) != NULL) { |
414 | if(fgets(bufall,MAX_BUF,fp) != NULL) { |
415 | if(!strncmp(bufall,"checksum ",9)) { |
415 | if(!strncmp(bufall,"checksum ",9)) { |
416 | checksum = strtol(bufall+9,(char **) NULL, 16); |
416 | checksum = strtol(bufall+9,(char **) NULL, 16); |
417 | (void) fgets(bufall,MAX_BUF,fp); |
417 | (void) fgets(bufall,MAX_BUF,fp); |
418 | } |
418 | } |
419 | if(sscanf(bufall,"password %s\n",buf)) { |
419 | if(sscanf(bufall,"password %s\n",buf)) { |
420 | /* New password scheme: */ |
420 | /* New password scheme: */ |
421 | correct=check_password(pl->write_buf+1,buf); |
421 | correct=check_password(pl->write_buf+1,buf); |
422 | } |
422 | } |
423 | /* Old password mode removed - I have no idea what it |
423 | /* Old password mode removed - I have no idea what it |
424 | * was, and the current password mechanism has been used |
424 | * was, and the current password mechanism has been used |
425 | * for at least several years. |
425 | * for at least several years. |
426 | */ |
426 | */ |
427 | } |
427 | } |
428 | if (!correct) { |
428 | if (!correct) { |
429 | new_draw_info(NDI_UNIQUE, 0,op," "); |
429 | new_draw_info(NDI_UNIQUE, 0,op," "); |
430 | new_draw_info(NDI_UNIQUE, 0,op,"Wrong Password!"); |
430 | new_draw_info(NDI_UNIQUE, 0,op,"Wrong Password!"); |
431 | new_draw_info(NDI_UNIQUE, 0,op," "); |
431 | new_draw_info(NDI_UNIQUE, 0,op," "); |
432 | FREE_AND_COPY(op->name, "noname"); |
432 | FREE_AND_COPY(op->name, "noname"); |
433 | FREE_AND_COPY(op->name_pl, "noname"); |
433 | FREE_AND_COPY(op->name_pl, "noname"); |
434 | op->contr->socket.password_fails++; |
434 | op->contr->socket.password_fails++; |
435 | if (op->contr->socket.password_fails >= MAX_PASSWORD_FAILURES) { |
435 | if (op->contr->socket.password_fails >= MAX_PASSWORD_FAILURES) { |
436 | new_draw_info(NDI_UNIQUE, 0,op, |
436 | new_draw_info(NDI_UNIQUE, 0,op, |
437 | "You gave an incorrect password too many times, you will now be dropped from the server."); |
437 | "You gave an incorrect password too many times, you will now be dropped from the server."); |
438 | LOG(llevInfo, "A player connecting from %s has been dropped for password failure\n", |
438 | LOG(llevInfo, "A player connecting from %s has been dropped for password failure\n", |
439 | op->contr->socket.host); |
439 | op->contr->socket.host); |
440 | op->contr->socket.status = Ns_Dead; /* the socket loop should handle the rest for us */ |
440 | op->contr->socket.status = Ns_Dead; /* the socket loop should handle the rest for us */ |
441 | } |
441 | } |
442 | else get_name(op); |
442 | else get_name(op); |
443 | return; /* Once again, rest of code just loads the char */ |
443 | return; /* Once again, rest of code just loads the char */ |
444 | } |
444 | } |
445 | |
445 | |
446 | #ifdef SAVE_INTERVAL |
446 | #ifdef SAVE_INTERVAL |
447 | pl->last_save_time=time(NULL); |
447 | pl->last_save_time=time(NULL); |
448 | #endif /* SAVE_INTERVAL */ |
448 | #endif /* SAVE_INTERVAL */ |
449 | pl->party = NULL; |
449 | pl->party = NULL; |
450 | if (settings.search_items == TRUE) |
450 | if (settings.search_items == TRUE) |
451 | pl->search_str[0]='\0'; |
451 | pl->search_str[0]='\0'; |
452 | pl->name_changed=1; |
452 | pl->name_changed=1; |
453 | pl->orig_stats.Str=0; |
453 | pl->orig_stats.Str=0; |
454 | pl->orig_stats.Dex=0; |
454 | pl->orig_stats.Dex=0; |
455 | pl->orig_stats.Con=0; |
455 | pl->orig_stats.Con=0; |
456 | pl->orig_stats.Int=0; |
456 | pl->orig_stats.Int=0; |
… | |
… | |
461 | pl->bed_x=0, pl->bed_y=0; |
461 | pl->bed_x=0, pl->bed_y=0; |
462 | pl->spellparam[0] = '\0'; |
462 | pl->spellparam[0] = '\0'; |
463 | |
463 | |
464 | /* Loop through the file, loading the rest of the values */ |
464 | /* Loop through the file, loading the rest of the values */ |
465 | while (fgets(bufall,MAX_BUF,fp)!=NULL) { |
465 | while (fgets(bufall,MAX_BUF,fp)!=NULL) { |
466 | sscanf(bufall,"%s %d\n",buf,&value); |
466 | sscanf(bufall,"%s %d\n",buf,&value); |
467 | if (!strcmp(buf,"endplst")) |
467 | if (!strcmp(buf,"endplst")) |
468 | break; |
468 | break; |
469 | else if (!strcmp(buf,"oid")) |
469 | else if (!strcmp(buf,"oid")) |
470 | thawer.get (pl, value); |
470 | thawer.get (pl, value); |
471 | else if (!strcmp(buf,"title") && settings.set_title == TRUE) |
471 | else if (!strcmp(buf,"title") && settings.set_title == TRUE) |
472 | sscanf(bufall,"title %[^\n]",pl->own_title); |
472 | sscanf(bufall,"title %[^\n]",pl->own_title); |
473 | else if (!strcmp(buf,"explore")) |
473 | else if (!strcmp(buf,"explore")) |
474 | pl->explore = value; |
474 | pl->explore = value; |
475 | else if (!strcmp(buf,"gen_hp")) |
475 | else if (!strcmp(buf,"gen_hp")) |
476 | pl->gen_hp=value; |
476 | pl->gen_hp=value; |
477 | else if (!strcmp(buf,"shoottype")) |
477 | else if (!strcmp(buf,"shoottype")) |
478 | pl->shoottype=(rangetype)value; |
478 | pl->shoottype=(rangetype)value; |
479 | else if (!strcmp(buf,"bowtype")) |
479 | else if (!strcmp(buf,"bowtype")) |
480 | pl->bowtype=(bowtype_t)value; |
480 | pl->bowtype=(bowtype_t)value; |
481 | else if (!strcmp(buf,"petmode")) |
481 | else if (!strcmp(buf,"petmode")) |
482 | pl->petmode=(petmode_t)value; |
482 | pl->petmode=(petmode_t)value; |
483 | else if (!strcmp(buf,"gen_sp")) |
483 | else if (!strcmp(buf,"gen_sp")) |
484 | pl->gen_sp=value; |
484 | pl->gen_sp=value; |
485 | else if (!strcmp(buf,"gen_grace")) |
485 | else if (!strcmp(buf,"gen_grace")) |
486 | pl->gen_grace=value; |
486 | pl->gen_grace=value; |
487 | else if (!strcmp(buf,"listening")) |
487 | else if (!strcmp(buf,"listening")) |
488 | pl->listening=value; |
488 | pl->listening=value; |
489 | else if (!strcmp(buf,"peaceful")) |
489 | else if (!strcmp(buf,"peaceful")) |
490 | pl->peaceful=value; |
490 | pl->peaceful=value; |
491 | else if (!strcmp(buf,"no_shout")) |
491 | else if (!strcmp(buf,"no_shout")) |
492 | pl->no_shout=value; |
492 | pl->no_shout=value; |
493 | else if (!strcmp(buf,"digestion")) |
493 | else if (!strcmp(buf,"digestion")) |
494 | pl->digestion=value; |
494 | pl->digestion=value; |
495 | else if (!strcmp(buf,"pickup")) |
495 | else if (!strcmp(buf,"pickup")) |
496 | pl->mode=value; |
496 | pl->mode=value; |
497 | else if (!strcmp(buf,"outputs_sync")) |
497 | else if (!strcmp(buf,"outputs_sync")) |
498 | pl->outputs_sync = value; |
498 | pl->outputs_sync = value; |
499 | else if (!strcmp(buf,"outputs_count")) |
499 | else if (!strcmp(buf,"outputs_count")) |
500 | pl->outputs_count = value; |
500 | pl->outputs_count = value; |
501 | else if (!strcmp(buf,"map")) |
501 | else if (!strcmp(buf,"map")) |
502 | sscanf(bufall,"map %s", pl->maplevel); |
502 | sscanf(bufall,"map %s", pl->maplevel); |
503 | else if (!strcmp(buf,"savebed_map")) |
503 | else if (!strcmp(buf,"savebed_map")) |
504 | sscanf(bufall,"savebed_map %s", pl->savebed_map); |
504 | sscanf(bufall,"savebed_map %s", pl->savebed_map); |
505 | else if (!strcmp(buf,"bed_x")) |
505 | else if (!strcmp(buf,"bed_x")) |
506 | pl->bed_x=value; |
506 | pl->bed_x=value; |
507 | else if (!strcmp(buf,"bed_y")) |
507 | else if (!strcmp(buf,"bed_y")) |
508 | pl->bed_y=value; |
508 | pl->bed_y=value; |
509 | else if (!strcmp(buf,"weapon_sp")) |
509 | else if (!strcmp(buf,"weapon_sp")) |
510 | sscanf(buf,"weapon_sp %f",&pl->weapon_sp); |
510 | sscanf(buf,"weapon_sp %f",&pl->weapon_sp); |
511 | else if (!strcmp(buf,"Str")) |
511 | else if (!strcmp(buf,"Str")) |
512 | pl->orig_stats.Str=value; |
512 | pl->orig_stats.Str=value; |
513 | else if (!strcmp(buf,"Dex")) |
513 | else if (!strcmp(buf,"Dex")) |
514 | pl->orig_stats.Dex=value; |
514 | pl->orig_stats.Dex=value; |
515 | else if (!strcmp(buf,"Con")) |
515 | else if (!strcmp(buf,"Con")) |
516 | pl->orig_stats.Con=value; |
516 | pl->orig_stats.Con=value; |
517 | else if (!strcmp(buf,"Int")) |
517 | else if (!strcmp(buf,"Int")) |
518 | pl->orig_stats.Int=value; |
518 | pl->orig_stats.Int=value; |
519 | else if (!strcmp(buf,"Pow")) |
519 | else if (!strcmp(buf,"Pow")) |
520 | pl->orig_stats.Pow=value; |
520 | pl->orig_stats.Pow=value; |
521 | else if (!strcmp(buf,"Wis")) |
521 | else if (!strcmp(buf,"Wis")) |
522 | pl->orig_stats.Wis=value; |
522 | pl->orig_stats.Wis=value; |
523 | else if (!strcmp(buf,"Cha")) |
523 | else if (!strcmp(buf,"Cha")) |
524 | pl->orig_stats.Cha=value; |
524 | pl->orig_stats.Cha=value; |
525 | else if (!strcmp(buf,"usekeys")) { |
525 | else if (!strcmp(buf,"usekeys")) { |
526 | if (!strcmp(bufall+8,"key_inventory\n")) |
526 | if (!strcmp(bufall+8,"key_inventory\n")) |
527 | pl->usekeys=key_inventory; |
527 | pl->usekeys=key_inventory; |
528 | else if (!strcmp(bufall+8,"keyrings\n")) |
528 | else if (!strcmp(bufall+8,"keyrings\n")) |
529 | pl->usekeys=keyrings; |
529 | pl->usekeys=keyrings; |
530 | else if (!strcmp(bufall+8,"containers\n")) |
530 | else if (!strcmp(bufall+8,"containers\n")) |
531 | pl->usekeys=containers; |
531 | pl->usekeys=containers; |
532 | else LOG(llevDebug,"load_player: got unknown usekeys type: %s\n", bufall+8); |
532 | else LOG(llevDebug,"load_player: got unknown usekeys type: %s\n", bufall+8); |
533 | } |
533 | } |
534 | else if (!strcmp(buf,"unapply")) { |
534 | else if (!strcmp(buf,"unapply")) { |
535 | if (!strcmp(bufall+8,"unapply_nochoice\n")) |
535 | if (!strcmp(bufall+8,"unapply_nochoice\n")) |
536 | pl->unapply=unapply_nochoice; |
536 | pl->unapply=unapply_nochoice; |
537 | else if (!strcmp(bufall+8,"unapply_never\n")) |
537 | else if (!strcmp(bufall+8,"unapply_never\n")) |
538 | pl->unapply=unapply_never; |
538 | pl->unapply=unapply_never; |
539 | else if (!strcmp(bufall+8,"unapply_always\n")) |
539 | else if (!strcmp(bufall+8,"unapply_always\n")) |
540 | pl->unapply=unapply_always; |
540 | pl->unapply=unapply_always; |
541 | else LOG(llevDebug,"load_player: got unknown unapply type: %s\n", bufall+8); |
541 | else LOG(llevDebug,"load_player: got unknown unapply type: %s\n", bufall+8); |
542 | } |
542 | } |
543 | else if (!strcmp(buf,"lev_array")){ |
543 | else if (!strcmp(buf,"lev_array")){ |
544 | for(i=1;i<=value;i++) { |
544 | for(i=1;i<=value;i++) { |
545 | int j; |
545 | int j; |
546 | fscanf(fp,"%d\n",&j); |
546 | fscanf(fp,"%d\n",&j); |
547 | pl->levhp[i]=j; |
547 | pl->levhp[i]=j; |
548 | fscanf(fp,"%d\n",&j); |
548 | fscanf(fp,"%d\n",&j); |
549 | pl->levsp[i]=j; |
549 | pl->levsp[i]=j; |
550 | fscanf(fp,"%d\n",&j); |
550 | fscanf(fp,"%d\n",&j); |
551 | pl->levgrace[i]=j; |
551 | pl->levgrace[i]=j; |
552 | } |
552 | } |
553 | /* spell_array code removed - don't know when that was last used. |
553 | /* spell_array code removed - don't know when that was last used. |
554 | * Even the load code below will someday be replaced by spells being |
554 | * Even the load code below will someday be replaced by spells being |
555 | * objects. |
555 | * objects. |
556 | */ |
556 | */ |
557 | } else if (!strcmp(buf,"known_spell")) { |
557 | } else if (!strcmp(buf,"known_spell")) { |
558 | #if 0 |
558 | #if 0 |
559 | /* Logic is left here in case someone wants to try |
559 | /* Logic is left here in case someone wants to try |
560 | * and write code to update to spell objects. |
560 | * and write code to update to spell objects. |
561 | */ |
561 | */ |
562 | char *cp=strchr(bufall,'\n'); |
562 | char *cp=strchr(bufall,'\n'); |
563 | *cp='\0'; |
563 | *cp='\0'; |
564 | cp=strchr(bufall,' '); |
564 | cp=strchr(bufall,' '); |
565 | cp++; |
565 | cp++; |
566 | for(i=0;i<NROFREALSPELLS;i++) |
566 | for(i=0;i<NROFREALSPELLS;i++) |
567 | if(!strcmp(spells[i].name,cp)) { |
567 | if(!strcmp(spells[i].name,cp)) { |
568 | pl->known_spells[pl->nrofknownspells++]=i; |
568 | pl->known_spells[pl->nrofknownspells++]=i; |
569 | break; |
569 | break; |
570 | } |
570 | } |
571 | if(i==NROFREALSPELLS) |
571 | if(i==NROFREALSPELLS) |
572 | LOG(llevDebug, "Error: unknown spell (%s)\n",cp); |
572 | LOG(llevDebug, "Error: unknown spell (%s)\n",cp); |
573 | #endif |
573 | #endif |
574 | } |
574 | } |
575 | } /* End of loop loading the character file */ |
575 | } /* End of loop loading the character file */ |
576 | leave_map(op); |
576 | leave_map(op); |
577 | op->speed=0; |
577 | op->speed=0; |
578 | update_ob_speed(op); |
578 | update_ob_speed(op); |
579 | reset_object(op); |
579 | reset_object(op); |
… | |
… | |
595 | * First, we check for partial path, then check to see if the full |
595 | * First, we check for partial path, then check to see if the full |
596 | * path (for unique player maps) |
596 | * path (for unique player maps) |
597 | */ |
597 | */ |
598 | if (check_path(pl->maplevel,1)==-1) { |
598 | if (check_path(pl->maplevel,1)==-1) { |
599 | if (check_path(pl->maplevel,0)==-1) { |
599 | if (check_path(pl->maplevel,0)==-1) { |
600 | strcpy(pl->maplevel, pl->savebed_map); |
600 | strcpy(pl->maplevel, pl->savebed_map); |
601 | op->x = pl->bed_x, op->y = pl->bed_y; |
601 | op->x = pl->bed_x, op->y = pl->bed_y; |
602 | } |
602 | } |
603 | } |
603 | } |
604 | |
604 | |
605 | /* If player saved beyond some time ago, and the feature is |
605 | /* If player saved beyond some time ago, and the feature is |
606 | * enabled, put the player back on his savebed map. |
606 | * enabled, put the player back on his savebed map. |
607 | */ |
607 | */ |
608 | if ((settings.reset_loc_time >0) && (elapsed_save_time > settings.reset_loc_time)) { |
608 | if ((settings.reset_loc_time >0) && (elapsed_save_time > settings.reset_loc_time)) { |
609 | strcpy(pl->maplevel, pl->savebed_map); |
609 | strcpy(pl->maplevel, pl->savebed_map); |
610 | op->x = pl->bed_x, op->y = pl->bed_y; |
610 | op->x = pl->bed_x, op->y = pl->bed_y; |
611 | } |
611 | } |
612 | |
612 | |
613 | /* make sure he's a player--needed because of class change. */ |
613 | /* make sure he's a player--needed because of class change. */ |
614 | op->type = PLAYER; |
614 | op->type = PLAYER; |
615 | |
615 | |
… | |
… | |
636 | |
636 | |
637 | /* if it's a dragon player, set the correct title here */ |
637 | /* if it's a dragon player, set the correct title here */ |
638 | if (is_dragon_pl(op) && op->inv != NULL) { |
638 | if (is_dragon_pl(op) && op->inv != NULL) { |
639 | object *tmp, *abil=NULL, *skin=NULL; |
639 | object *tmp, *abil=NULL, *skin=NULL; |
640 | for (tmp=op->inv; tmp!=NULL; tmp=tmp->below) { |
640 | for (tmp=op->inv; tmp!=NULL; tmp=tmp->below) { |
641 | if (tmp->type == FORCE) { |
641 | if (tmp->type == FORCE) { |
642 | if (strcmp(tmp->arch->name, "dragon_ability_force")==0) |
642 | if (strcmp(tmp->arch->name, "dragon_ability_force")==0) |
643 | abil = tmp; |
643 | abil = tmp; |
644 | else if (strcmp(tmp->arch->name, "dragon_skin_force")==0) |
644 | else if (strcmp(tmp->arch->name, "dragon_skin_force")==0) |
645 | skin = tmp; |
645 | skin = tmp; |
646 | } |
646 | } |
647 | } |
647 | } |
648 | set_dragon_name(op, abil, skin); |
648 | set_dragon_name(op, abil, skin); |
649 | } |
649 | } |
650 | |
650 | |
651 | new_draw_info(NDI_UNIQUE, 0,op,"Welcome Back!"); |
651 | new_draw_info(NDI_UNIQUE, 0,op,"Welcome Back!"); |
652 | new_draw_info_format(NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, NULL, |
652 | new_draw_info_format(NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, NULL, |
653 | "%s has entered the game.",pl->ob->name); |
653 | "%s has entered the game.",pl->ob->name); |
654 | |
654 | |
655 | INVOKE_PLAYER (LOAD, pl, ARG_STRING (filename)); |
655 | INVOKE_PLAYER (LOAD, pl, ARG_STRING (filename)); |
656 | INVOKE_PLAYER (LOGIN, pl); |
656 | INVOKE_PLAYER (LOGIN, pl); |
657 | |
657 | |
658 | op->contr->socket.update_look=1; |
658 | op->contr->socket.update_look=1; |
… | |
… | |
661 | * logic for that to take place. If player is permanently |
661 | * logic for that to take place. If player is permanently |
662 | * dead, and not using permadeath mode, the kill_player will |
662 | * dead, and not using permadeath mode, the kill_player will |
663 | * set the play_again flag, so return. |
663 | * set the play_again flag, so return. |
664 | */ |
664 | */ |
665 | if (op->stats.hp<0) { |
665 | if (op->stats.hp<0) { |
666 | new_draw_info(NDI_UNIQUE, 0,op,"Your character was dead last your played."); |
666 | new_draw_info(NDI_UNIQUE, 0,op,"Your character was dead last your played."); |
667 | kill_player(op); |
667 | kill_player(op); |
668 | if (pl->state != ST_PLAYING) return; |
668 | if (pl->state != ST_PLAYING) return; |
669 | } |
669 | } |
670 | LOG(llevInfo,"LOGIN: Player named %s from ip %s\n", op->name, |
670 | LOG(llevInfo,"LOGIN: Player named %s from ip %s\n", op->name, |
671 | op->contr->socket.host); |
671 | op->contr->socket.host); |
672 | |
672 | |
673 | /* Do this after checking for death - no reason sucking up bandwidth if |
673 | /* Do this after checking for death - no reason sucking up bandwidth if |
674 | * the data isn't needed. |
674 | * the data isn't needed. |
675 | */ |
675 | */ |
676 | esrv_new_player(op->contr,op->weight+op->carrying); |
676 | esrv_new_player(op->contr,op->weight+op->carrying); |