ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/login.C
(Generate patch)

Comparing deliantra/server/server/login.C (file contents):
Revision 1.15 by root, Sun Sep 10 15:59:27 2006 UTC vs.
Revision 1.36 by root, Sat Dec 30 10:16:11 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines