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.22 by root, Tue Dec 12 21:39:57 2006 UTC vs.
Revision 1.35 by root, Mon Dec 25 17:11:17 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines