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.16 by root, Sun Sep 10 16:56:22 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.16 2006/09/10 16:56:22 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 187
450 if (!correct) 188 char buf[MAX_BUF], bufall[MAX_BUF];
451 {
452 new_draw_info (NDI_UNIQUE, 0, op, " ");
453 new_draw_info (NDI_UNIQUE, 0, op, "Wrong Password!");
454 new_draw_info (NDI_UNIQUE, 0, op, " ");
455 op->name = op->name_pl = "noname";
456 op->contr->socket.password_fails++;
457 if (op->contr->socket.password_fails >= MAX_PASSWORD_FAILURES)
458 {
459 new_draw_info (NDI_UNIQUE, 0, op, "You gave an incorrect password too many times, you will now be dropped from the server.");
460 LOG (llevInfo, "A player connecting from %s has been dropped for password failure\n", op->contr->socket.host);
461 op->contr->socket.status = Ns_Dead; /* the socket loop should handle the rest for us */
462 }
463 else
464 get_name (op);
465 return; /* Once again, rest of code just loads the char */
466 }
467 189
468#ifdef SAVE_INTERVAL 190 pl->set_object (object::create ());
469 pl->last_save_time = time (NULL); 191 pl->last_save_time = time (0);
470#endif /* SAVE_INTERVAL */ 192
471 pl->party = NULL;
472 if (settings.search_items == TRUE)
473 pl->search_str[0] = '\0';
474 pl->name_changed = 1;
475 pl->orig_stats.Str = 0;
476 pl->orig_stats.Dex = 0;
477 pl->orig_stats.Con = 0;
478 pl->orig_stats.Int = 0;
479 pl->orig_stats.Pow = 0;
480 pl->orig_stats.Wis = 0;
481 pl->orig_stats.Cha = 0;
482 strcpy (pl->savebed_map, first_map_path); 193 assign (pl->savebed_map, first_map_path);
483 pl->bed_x = 0, pl->bed_y = 0;
484 pl->spellparam[0] = '\0';
485 194
486 /* Loop through the file, loading the rest of the values */ 195 /* Loop through the file, loading the rest of the values */
487 while (fgets (bufall, MAX_BUF, thawer) != NULL) 196 while (fgets (bufall, MAX_BUF, thawer))
488 { 197 {
198 int value;
489 sscanf (bufall, "%s %d\n", buf, &value); 199 sscanf (bufall, "%s %d\n", buf, &value);
200
490 if (!strcmp (buf, "endplst")) 201 if (!strcmp (buf, "endplst"))
491 break; 202 break;
492 else if (!strcmp (buf, "oid")) 203 else if (!strcmp (buf, "oid"))
493 thawer.get (pl, value); 204 thawer.get (pl, value);
494 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"))
495 sscanf (bufall, "title %[^\n]", pl->own_title); 208 sscanf (bufall, "title %[^\n]", pl->own_title);
496 else if (!strcmp (buf, "explore")) 209 else if (!strcmp (buf, "explore"))
497 pl->explore = value; 210 pl->explore = value;
498 else if (!strcmp (buf, "gen_hp")) 211 else if (!strcmp (buf, "gen_hp"))
499 pl->gen_hp = value; 212 pl->gen_hp = value;
509 pl->gen_grace = value; 222 pl->gen_grace = value;
510 else if (!strcmp (buf, "listening")) 223 else if (!strcmp (buf, "listening"))
511 pl->listening = value; 224 pl->listening = value;
512 else if (!strcmp (buf, "peaceful")) 225 else if (!strcmp (buf, "peaceful"))
513 pl->peaceful = value; 226 pl->peaceful = value;
514 else if (!strcmp (buf, "no_shout"))
515 pl->no_shout = value;
516 else if (!strcmp (buf, "digestion")) 227 else if (!strcmp (buf, "digestion"))
517 pl->digestion = value; 228 pl->digestion = value;
518 else if (!strcmp (buf, "pickup")) 229 else if (!strcmp (buf, "pickup"))
519 pl->mode = value; 230 pl->mode = value;
520 else if (!strcmp (buf, "outputs_sync")) 231 else if (!strcmp (buf, "outputs_sync"))
567 else 278 else
568 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);
569 } 280 }
570 else if (!strcmp (buf, "lev_array")) 281 else if (!strcmp (buf, "lev_array"))
571 { 282 {
572 for (i = 1; i <= value; i++) 283 for (int i = 1; i <= value; i++)
573 { 284 {
574 char line[128]; 285 char line[128];
575 286
576 fgets (line, 128, thawer); 287 fgets (line, 128, thawer);
577 pl->levhp[i] = atoi (line); 288 pl->levhp[i] = atoi (line);
583 /* 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.
584 * 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
585 * objects. 296 * objects.
586 */ 297 */
587 } 298 }
588 else if (!strcmp (buf, "known_spell")) 299 else
589 { 300 LOG (llevDebug, "unparseable line in player file %s: %s\n", path, bufall);
590#if 0 301 }
591 /* Logic is left here in case someone wants to try
592 * and write code to update to spell objects.
593 */
594 char *cp = strchr (bufall, '\n');
595
596 *cp = '\0';
597 cp = strchr (bufall, ' ');
598 cp++;
599 for (i = 0; i < NROFREALSPELLS; i++)
600 if (!strcmp (spells[i].name, cp))
601 {
602 pl->known_spells[pl->nrofknownspells++] = i;
603 break;
604 }
605 if (i == NROFREALSPELLS)
606 LOG (llevDebug, "Error: unknown spell (%s)\n", cp);
607#endif
608 }
609 } /* End of loop loading the character file */
610 leave_map (op);
611 op->speed = 0;
612 update_ob_speed (op);
613
614 clear_object (op);
615
616 op->contr = pl;
617 pl->ob = op;
618 302
619 /* this loads the standard objects values. */ 303 /* this loads the standard objects values. */
620 load_object (thawer, op, 0); 304 load_object (thawer, pl->ob, 0);
621 305
622 CLEAR_FLAG (op, FLAG_NO_FIX_PLAYER);
623
624 strncpy (pl->title, op->arch->clone.name, sizeof (pl->title) - 1);
625 pl->title[sizeof (pl->title) - 1] = '\0';
626
627 /* If the map where the person was last saved does not exist,
628 * restart them on their home-savebed. This is good for when
629 * maps change between versions
630 * First, we check for partial path, then check to see if the full
631 * path (for unique player maps)
632 */
633 if (check_path (pl->maplevel, 1) == -1)
634 {
635 if (check_path (pl->maplevel, 0) == -1)
636 {
637 strcpy (pl->maplevel, pl->savebed_map);
638 op->x = pl->bed_x, op->y = pl->bed_y;
639 }
640 }
641
642 /* make sure he's a player--needed because of class change. */
643 op->type = PLAYER;
644
645 enter_exit (op, NULL);
646
647 pl->name_changed = 1;
648 pl->state = ST_PLAYING;
649#ifdef AUTOSAVE
650 pl->last_save_tick = pticks; 306 pl->last_save_tick = pticks;
651#endif
652 op->carrying = sum_weight (op);
653 /* Need to call fix_player now - program modified so that it is not
654 * called during the load process (FLAG_NO_FIX_PLAYER set when
655 * saved)
656 * Moved ahead of the esrv functions, so proper weights will be
657 * sent to the client.
658 */
659 link_player_skills (op);
660 307
661 if (!legal_range (op, op->contr->shoottype))
662 op->contr->shoottype = range_none;
663
664 fix_player (op);
665
666 /* if it's a dragon player, set the correct title here */
667 if (is_dragon_pl (op) && op->inv != NULL)
668 {
669 object *tmp, *abil = NULL, *skin = NULL;
670
671 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
672 {
673 if (tmp->type == FORCE)
674 {
675 if (strcmp (tmp->arch->name, "dragon_ability_force") == 0)
676 abil = tmp;
677 else if (strcmp (tmp->arch->name, "dragon_skin_force") == 0)
678 skin = tmp;
679 }
680 }
681 set_dragon_name (op, abil, skin);
682 }
683
684 new_draw_info (NDI_UNIQUE, 0, op, "Welcome Back!");
685 new_draw_info_format (NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, NULL, "%s has entered the game.", &pl->ob->name);
686
687 INVOKE_PLAYER (LOAD, pl, ARG_STRING (filename)); 308 INVOKE_PLAYER (LOAD, pl, ARG_STRING (path));
688 INVOKE_PLAYER (LOGIN, pl);
689 309
690 op->contr->socket.update_look = 1;
691 /* If the player should be dead, call kill_player for them
692 * Only check for hp - if player lacks food, let the normal
693 * logic for that to take place. If player is permanently
694 * dead, and not using permadeath mode, the kill_player will
695 * set the play_again flag, so return.
696 */
697 if (op->stats.hp < 0)
698 {
699 new_draw_info (NDI_UNIQUE, 0, op, "Your character was dead last your played.");
700 kill_player (op);
701 if (pl->state != ST_PLAYING)
702 return;
703 }
704 LOG (llevInfo, "LOGIN: Player named %s from ip %s\n", &op->name, op->contr->socket.host);
705
706 /* Do this after checking for death - no reason sucking up bandwidth if
707 * the data isn't needed.
708 */
709 esrv_new_player (op->contr, op->weight + op->carrying);
710 esrv_send_inventory (op, op);
711 esrv_add_spells (op->contr, NULL);
712
713 CLEAR_FLAG (op, FLAG_FRIENDLY);
714
715 /* can_use_shield is a new flag. However, the can_use.. seems to largely come
716 * from the class, and not race. I don't see any way to get the class information
717 * to then update this. I don't think this will actually break anything - anyone
718 * that can use armour should be able to use a shield. What this may 'break'
719 * are features new characters get, eg, if someone starts up with a Q, they
720 * should be able to use a shield. However, old Q's won't get that advantage.
721 */
722 if (QUERY_FLAG (op, FLAG_USE_ARMOUR))
723 SET_FLAG (op, FLAG_USE_SHIELD);
724 return; 310 return pl;
725} 311}
312

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines