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