1 | /* |
1 | /* |
2 | * static char *rcsid_main_c = |
2 | * static char *rcsid_main_c = |
3 | * "$Id: main.C,v 1.4 2006/08/24 13:13:49 root Exp $"; |
3 | * "$Id: main.C,v 1.17 2006/09/03 00:18:42 root Exp $"; |
4 | */ |
4 | */ |
5 | |
5 | |
6 | /* |
6 | /* |
7 | CrossFire, A Multiplayer game for X-windows |
7 | CrossFire, A Multiplayer game for X-windows |
8 | |
8 | |
… | |
… | |
47 | #endif |
47 | #endif |
48 | |
48 | |
49 | #include <../random_maps/random_map.h> |
49 | #include <../random_maps/random_map.h> |
50 | #include <../random_maps/rproto.h> |
50 | #include <../random_maps/rproto.h> |
51 | #include "path.h" |
51 | #include "path.h" |
|
|
52 | |
|
|
53 | shstr undead_name; |
52 | |
54 | |
53 | static char days[7][4] = { |
55 | static char days[7][4] = { |
54 | "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; |
56 | "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; |
55 | |
57 | |
56 | void version(object *op) { |
58 | void version(object *op) { |
… | |
… | |
140 | sprintf(buf,"Welcome to Crossfire, v%s!",VERSION); |
142 | sprintf(buf,"Welcome to Crossfire, v%s!",VERSION); |
141 | new_draw_info(NDI_UNIQUE, 0,op,buf); |
143 | new_draw_info(NDI_UNIQUE, 0,op,buf); |
142 | new_draw_info(NDI_UNIQUE, 0,op,"Press `?' for help"); |
144 | new_draw_info(NDI_UNIQUE, 0,op,"Press `?' for help"); |
143 | new_draw_info(NDI_UNIQUE, 0,op," "); |
145 | new_draw_info(NDI_UNIQUE, 0,op," "); |
144 | new_draw_info_format(NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, op, |
146 | new_draw_info_format(NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, op, |
145 | "%s entered the game.",op->name); |
147 | "%s entered the game.",&op->name); |
146 | if(!op->contr->name_changed) { |
148 | if(!op->contr->name_changed) { |
147 | new_draw_info(NDI_UNIQUE, 0,op,"Note that you must set your name with the name"); |
149 | new_draw_info(NDI_UNIQUE, 0,op,"Note that you must set your name with the name"); |
148 | new_draw_info(NDI_UNIQUE, 0,op,"command to enter the highscore list."); |
150 | new_draw_info(NDI_UNIQUE, 0,op,"command to enter the highscore list."); |
149 | new_draw_info(NDI_UNIQUE, 0,op,"(You can also use the crossfire.name X-resource.)"); |
151 | new_draw_info(NDI_UNIQUE, 0,op,"(You can also use the crossfire.name X-resource.)"); |
150 | } |
152 | } |
… | |
… | |
157 | char *crypt_string(char *str, char *salt) { |
159 | char *crypt_string(char *str, char *salt) { |
158 | #if defined(WIN32) || (defined(__FreeBSD__) && !defined(HAVE_LIBDES)) |
160 | #if defined(WIN32) || (defined(__FreeBSD__) && !defined(HAVE_LIBDES)) |
159 | return(str); |
161 | return(str); |
160 | #else |
162 | #else |
161 | static char *c= |
163 | static char *c= |
162 | "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./"; |
164 | "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./"; |
163 | char s[2]; |
165 | char s[2]; |
164 | |
166 | |
165 | if(salt==NULL) |
167 | if(salt==NULL) |
166 | s[0]= c[RANDOM() % (int)strlen(c)], |
168 | s[0]= c[RANDOM() % (int)strlen(c)], |
167 | s[1]= c[RANDOM() % (int)strlen(c)]; |
169 | s[1]= c[RANDOM() % (int)strlen(c)]; |
168 | else |
170 | else |
169 | s[0]= salt[0], |
171 | s[0]= salt[0], |
170 | s[1]= salt[1]; |
172 | s[1]= salt[1]; |
171 | |
173 | |
172 | # ifdef HAVE_LIBDES |
174 | # ifdef HAVE_LIBDES |
173 | return (char*)des_crypt(str,s); |
175 | return (char*)des_crypt(str,s); |
174 | # endif |
176 | # endif |
175 | /* Default case - just use crypt */ |
177 | /* Default case - just use crypt */ |
… | |
… | |
191 | mapstruct *oldmap = op->map; |
193 | mapstruct *oldmap = op->map; |
192 | object *tmp; |
194 | object *tmp; |
193 | |
195 | |
194 | tmp=get_object(); |
196 | tmp=get_object(); |
195 | |
197 | |
196 | EXIT_PATH(tmp) = add_string(op->contr->savebed_map); |
198 | EXIT_PATH(tmp) = op->contr->savebed_map; |
197 | EXIT_X(tmp) = op->contr->bed_x; |
199 | EXIT_X(tmp) = op->contr->bed_x; |
198 | EXIT_Y(tmp) = op->contr->bed_y; |
200 | EXIT_Y(tmp) = op->contr->bed_y; |
199 | enter_exit(op,tmp); |
201 | enter_exit(op,tmp); |
200 | /* If the player has not changed maps and the name does not match |
202 | /* If the player has not changed maps and the name does not match |
201 | * that of the savebed, his savebed map is gone. Lets go back |
203 | * that of the savebed, his savebed map is gone. Lets go back |
202 | * to the emergency path. Update what the players savebed is |
204 | * to the emergency path. Update what the players savebed is |
203 | * while we're at it. |
205 | * while we're at it. |
204 | */ |
206 | */ |
205 | if (oldmap == op->map && strcmp(op->contr->savebed_map, oldmap->path)) { |
207 | if (oldmap == op->map && strcmp(op->contr->savebed_map, oldmap->path)) { |
206 | LOG(llevDebug,"Player %s savebed location %s is invalid - going to emergency location (%s)\n", |
208 | LOG(llevDebug,"Player %s savebed location %s is invalid - going to emergency location (%s)\n", |
207 | settings.emergency_mapname, op->name, op->contr->savebed_map); |
209 | settings.emergency_mapname, &op->name, op->contr->savebed_map); |
208 | strcpy(op->contr->savebed_map, settings.emergency_mapname); |
210 | strcpy(op->contr->savebed_map, settings.emergency_mapname); |
209 | op->contr->bed_x = settings.emergency_x; |
211 | op->contr->bed_x = settings.emergency_x; |
210 | op->contr->bed_y = settings.emergency_y; |
212 | op->contr->bed_y = settings.emergency_y; |
211 | free_string(op->contr->savebed_map); |
|
|
212 | EXIT_PATH(tmp) = add_string(op->contr->savebed_map); |
213 | EXIT_PATH(tmp) = op->contr->savebed_map; |
213 | EXIT_X(tmp) = op->contr->bed_x; |
214 | EXIT_X(tmp) = op->contr->bed_x; |
214 | EXIT_Y(tmp) = op->contr->bed_y; |
215 | EXIT_Y(tmp) = op->contr->bed_y; |
215 | enter_exit(op,tmp); |
216 | enter_exit(op,tmp); |
216 | } |
217 | } |
217 | free_object(tmp); |
218 | free_object(tmp); |
218 | } |
219 | } |
219 | |
220 | |
220 | /* All this really is is a glorified remove_object that also updates |
221 | /* All this really is is a glorified remove_object that also updates |
… | |
… | |
225 | mapstruct *oldmap = op->map; |
226 | mapstruct *oldmap = op->map; |
226 | |
227 | |
227 | remove_ob(op); |
228 | remove_ob(op); |
228 | |
229 | |
229 | if (oldmap) { |
230 | if (oldmap) { |
230 | if (!op->contr->hidden) |
231 | if (!op->contr->hidden) |
231 | oldmap->players--; |
232 | oldmap->players--; |
232 | if (oldmap->players <= 0) { /* can be less than zero due to errors in tracking this */ |
233 | if (oldmap->players <= 0) { /* can be less than zero due to errors in tracking this */ |
233 | set_map_timeout(oldmap); |
234 | set_map_timeout(oldmap); |
234 | } |
235 | } |
235 | } |
236 | } |
236 | } |
237 | } |
237 | |
238 | |
238 | /* |
239 | /* |
239 | * enter_map(): Moves the player and pets from current map (if any) to |
240 | * enter_map(): Moves the player and pets from current map (if any) to |
… | |
… | |
244 | */ |
245 | */ |
245 | static void enter_map(object *op, mapstruct *newmap, int x, int y) { |
246 | static void enter_map(object *op, mapstruct *newmap, int x, int y) { |
246 | mapstruct *oldmap = op->map; |
247 | mapstruct *oldmap = op->map; |
247 | |
248 | |
248 | if (out_of_map(newmap, x, y)) { |
249 | if (out_of_map(newmap, x, y)) { |
249 | LOG(llevError,"enter_map: supplied coordinates are not within the map! (%s: %d, %d)\n", |
250 | LOG(llevError,"enter_map: supplied coordinates are not within the map! (%s: %d, %d)\n", |
250 | newmap->path, x, y); |
251 | newmap->path, x, y); |
251 | x=MAP_ENTER_X(newmap); |
252 | x=MAP_ENTER_X(newmap); |
252 | y=MAP_ENTER_Y(newmap); |
253 | y=MAP_ENTER_Y(newmap); |
253 | if (out_of_map(newmap, x, y)) { |
254 | if (out_of_map(newmap, x, y)) { |
254 | LOG(llevError,"enter_map: map %s provides invalid default enter location (%d, %d) > (%d, %d)\n", |
255 | LOG(llevError,"enter_map: map %s provides invalid default enter location (%d, %d) > (%d, %d)\n", |
255 | newmap->path, x, y, MAP_WIDTH(newmap), MAP_HEIGHT(newmap)); |
256 | newmap->path, x, y, MAP_WIDTH(newmap), MAP_HEIGHT(newmap)); |
256 | new_draw_info(NDI_UNIQUE, 0, op, "The exit is closed"); |
257 | new_draw_info(NDI_UNIQUE, 0, op, "The exit is closed"); |
257 | return; |
258 | return; |
258 | } |
259 | } |
259 | } |
260 | } |
260 | /* try to find a spot for the player */ |
261 | /* try to find a spot for the player */ |
261 | if (ob_blocked(op, newmap, x, y)) { /* First choice blocked */ |
262 | if (ob_blocked(op, newmap, x, y)) { /* First choice blocked */ |
262 | /* We try to find a spot for the player, starting closest in. |
263 | /* We try to find a spot for the player, starting closest in. |
263 | * We could use find_first_free_spot, but that doesn't randomize it at all, |
264 | * We could use find_first_free_spot, but that doesn't randomize it at all, |
264 | * So for example, if the north space is free, you would always end up there even |
265 | * So for example, if the north space is free, you would always end up there even |
265 | * if other spaces around are available. |
266 | * if other spaces around are available. |
266 | * Note that for the second and third calls, we could start at a position other |
267 | * Note that for the second and third calls, we could start at a position other |
267 | * than one, but then we could end up on the other side of walls and so forth. |
268 | * than one, but then we could end up on the other side of walls and so forth. |
268 | */ |
269 | */ |
269 | int i = find_free_spot(op,newmap, x, y, 1, SIZEOFFREE1+1); |
270 | int i = find_free_spot(op,newmap, x, y, 1, SIZEOFFREE1+1); |
270 | if (i==-1) { |
271 | if (i==-1) { |
271 | i = find_free_spot(op,newmap, x, y, 1, SIZEOFFREE2+1); |
272 | i = find_free_spot(op,newmap, x, y, 1, SIZEOFFREE2+1); |
272 | if (i==-1) |
273 | if (i==-1) |
273 | i = find_free_spot(op,newmap, x, y, 1, SIZEOFFREE); |
274 | i = find_free_spot(op,newmap, x, y, 1, SIZEOFFREE); |
274 | } |
275 | } |
275 | if (i != -1 ) { |
276 | if (i != -1 ) { |
276 | x += freearr_x[i]; |
277 | x += freearr_x[i]; |
277 | y += freearr_y[i]; |
278 | y += freearr_y[i]; |
278 | } else { |
279 | } else { |
279 | /* not much we can do in this case. */ |
280 | /* not much we can do in this case. */ |
280 | LOG(llevInfo,"enter_map: Could not find free spot for player - will dump on top of object (%s: %d, %d)\n", |
281 | LOG(llevInfo,"enter_map: Could not find free spot for player - will dump on top of object (%s: %d, %d)\n", |
281 | newmap->path, x , y); |
282 | newmap->path, x , y); |
282 | } |
283 | } |
283 | } /* end if looking for free spot */ |
284 | } /* end if looking for free spot */ |
284 | |
285 | |
|
|
286 | if (op->map!=NULL) |
|
|
287 | { |
|
|
288 | INVOKE_PLAYER (MAP_CHANGE, op->contr, ARG_MAP (op->map), ARG_MAP (newmap)); |
|
|
289 | INVOKE_MAP (LEAVE, op->map, ARG_PLAYER (op->contr)); |
|
|
290 | } |
285 | |
291 | |
286 | /* If it is a player login, he has yet to be inserted anyplace. |
292 | /* If it is a player login, he has yet to be inserted anyplace. |
287 | * otherwise, we need to deal with removing the playe here. |
293 | * otherwise, we need to deal with removing the player here. |
288 | */ |
294 | */ |
289 | if(!QUERY_FLAG(op, FLAG_REMOVED)) |
295 | if(!QUERY_FLAG(op, FLAG_REMOVED)) |
290 | remove_ob(op); |
296 | remove_ob(op); |
291 | if (op->map!=NULL) |
297 | |
292 | { |
|
|
293 | /* Lauwenmark : Here we handle the MAPLEAVE global event */ |
|
|
294 | execute_global_event(EVENT_MAPLEAVE, op); |
|
|
295 | } |
|
|
296 | /* remove_ob clears these so they must be reset after the remove_ob call */ |
298 | /* remove_ob clears these so they must be reset after the remove_ob call */ |
297 | op->x = x; |
299 | op->x = x; |
298 | op->y = y; |
300 | op->y = y; |
299 | op->map = newmap; |
301 | op->map = newmap; |
300 | insert_ob_in_map(op,op->map,NULL,INS_NO_WALK_ON); |
302 | insert_ob_in_map(op,op->map,NULL,INS_NO_WALK_ON); |
301 | |
303 | |
302 | /* Lauwenmark : Here we handle the MAPENTER global event */ |
304 | INVOKE_MAP (ENTER, op->map, ARG_PLAYER (op->contr)); |
303 | execute_global_event(EVENT_MAPENTER, op); |
|
|
304 | |
305 | |
305 | if (!op->contr->hidden) |
306 | if (!op->contr->hidden) |
306 | newmap->players++; |
307 | newmap->players++; |
307 | |
308 | |
308 | newmap->timeout=0; |
309 | newmap->timeout=0; |
309 | op->enemy = NULL; |
310 | op->enemy = NULL; |
310 | |
311 | |
311 | if (op->contr) { |
312 | if (op->contr) { |
312 | strcpy(op->contr->maplevel, newmap->path); |
313 | strcpy(op->contr->maplevel, newmap->path); |
313 | op->contr->count=0; |
314 | op->contr->count=0; |
314 | } |
315 | } |
315 | |
316 | |
316 | /* Update any golems */ |
317 | /* Update any golems */ |
317 | if(op->type == PLAYER && op->contr->ranges[range_golem] != NULL) { |
318 | if(op->type == PLAYER && op->contr->ranges[range_golem] != NULL) { |
318 | int i = find_free_spot(op->contr->ranges[range_golem],newmap, |
319 | int i = find_free_spot(op->contr->ranges[range_golem],newmap, |
319 | x, y, 1, SIZEOFFREE); |
320 | x, y, 1, SIZEOFFREE); |
320 | remove_ob(op->contr->ranges[range_golem]); |
321 | remove_ob(op->contr->ranges[range_golem]); |
321 | if (i==-1) { |
322 | if (i==-1) { |
322 | remove_friendly_object(op->contr->ranges[range_golem]); |
323 | remove_friendly_object(op->contr->ranges[range_golem]); |
323 | free_object(op->contr->ranges[range_golem]); |
324 | free_object(op->contr->ranges[range_golem]); |
324 | op->contr->ranges[range_golem]=NULL; |
325 | op->contr->ranges[range_golem]=NULL; |
325 | op->contr->golem_count=0; |
326 | op->contr->golem_count=0; |
326 | } |
327 | } |
327 | else { |
328 | else { |
328 | object *tmp; |
329 | object *tmp; |
329 | for (tmp=op->contr->ranges[range_golem]; tmp!=NULL; tmp=tmp->more) { |
330 | for (tmp=op->contr->ranges[range_golem]; tmp!=NULL; tmp=tmp->more) { |
330 | tmp->x = x + freearr_x[i]+ (tmp->arch==NULL?0:tmp->arch->clone.x); |
331 | tmp->x = x + freearr_x[i]+ (tmp->arch==NULL?0:tmp->arch->clone.x); |
331 | tmp->y = y + freearr_y[i]+ (tmp->arch==NULL?0:tmp->arch->clone.y); |
332 | tmp->y = y + freearr_y[i]+ (tmp->arch==NULL?0:tmp->arch->clone.y); |
332 | tmp->map = newmap; |
333 | tmp->map = newmap; |
333 | } |
334 | } |
334 | insert_ob_in_map(op->contr->ranges[range_golem], newmap, NULL,0); |
335 | insert_ob_in_map(op->contr->ranges[range_golem], newmap, NULL,0); |
335 | op->contr->ranges[range_golem]->direction = |
336 | op->contr->ranges[range_golem]->direction = |
336 | find_dir_2(op->x - op->contr->ranges[range_golem]->x, |
337 | find_dir_2(op->x - op->contr->ranges[range_golem]->x, |
337 | op->y - op->contr->ranges[range_golem]->y); |
338 | op->y - op->contr->ranges[range_golem]->y); |
338 | } |
339 | } |
339 | } |
340 | } |
340 | op->direction=0; |
341 | op->direction=0; |
341 | |
342 | |
342 | /* since the players map is already loaded, we don't need to worry |
343 | /* since the players map is already loaded, we don't need to worry |
343 | * about pending objects. |
344 | * about pending objects. |
… | |
… | |
352 | if (oldmap) /* adjust old map */ |
353 | if (oldmap) /* adjust old map */ |
353 | { |
354 | { |
354 | oldmap->players--; |
355 | oldmap->players--; |
355 | |
356 | |
356 | if (oldmap->players <= 0) /* can be less than zero due to errors in tracking this */ |
357 | if (oldmap->players <= 0) /* can be less than zero due to errors in tracking this */ |
357 | set_map_timeout(oldmap); |
358 | set_map_timeout(oldmap); |
358 | } |
359 | } |
359 | } |
360 | } |
360 | swap_below_max (newmap->path); |
361 | swap_below_max (newmap->path); |
361 | } |
362 | } |
362 | |
363 | |
… | |
… | |
367 | /* Do MINTIMEOUT first, so that MAXTIMEOUT is used if that is |
368 | /* Do MINTIMEOUT first, so that MAXTIMEOUT is used if that is |
368 | * lower than the min value. |
369 | * lower than the min value. |
369 | */ |
370 | */ |
370 | #if MAP_MINTIMEOUT |
371 | #if MAP_MINTIMEOUT |
371 | if (oldmap->timeout < MAP_MINTIMEOUT) { |
372 | if (oldmap->timeout < MAP_MINTIMEOUT) { |
372 | oldmap->timeout = MAP_MINTIMEOUT; |
373 | oldmap->timeout = MAP_MINTIMEOUT; |
373 | } |
374 | } |
374 | #endif |
375 | #endif |
375 | if (oldmap->timeout > MAP_MAXTIMEOUT) { |
376 | if (oldmap->timeout > MAP_MAXTIMEOUT) { |
376 | oldmap->timeout = MAP_MAXTIMEOUT; |
377 | oldmap->timeout = MAP_MAXTIMEOUT; |
377 | } |
378 | } |
378 | #else |
379 | #else |
379 | /* save out the map */ |
380 | /* save out the map */ |
380 | swap_map(oldmap); |
381 | swap_map(oldmap); |
381 | #endif /* MAP_MAXTIMEOUT */ |
382 | #endif /* MAP_MAXTIMEOUT */ |
… | |
… | |
390 | static char newpath[MAX_BUF],*cp; |
391 | static char newpath[MAX_BUF],*cp; |
391 | |
392 | |
392 | strncpy(newpath, file, MAX_BUF-1); |
393 | strncpy(newpath, file, MAX_BUF-1); |
393 | newpath[MAX_BUF-1]='\0'; |
394 | newpath[MAX_BUF-1]='\0'; |
394 | for (cp=newpath; *cp!='\0'; cp++) { |
395 | for (cp=newpath; *cp!='\0'; cp++) { |
395 | if (*cp=='/') *cp='_'; |
396 | if (*cp=='/') *cp='_'; |
396 | } |
397 | } |
397 | return newpath; |
398 | return newpath; |
398 | } |
399 | } |
399 | |
400 | |
400 | |
401 | |
… | |
… | |
409 | { |
410 | { |
410 | static char newpath[MAX_BUF],*cp; |
411 | static char newpath[MAX_BUF],*cp; |
411 | |
412 | |
412 | cp=strrchr(src, '/'); |
413 | cp=strrchr(src, '/'); |
413 | if (cp) |
414 | if (cp) |
414 | strncpy(newpath, cp+1, MAX_BUF-1); |
415 | strncpy(newpath, cp+1, MAX_BUF-1); |
415 | else |
416 | else |
416 | strncpy(newpath, src, MAX_BUF-1); |
417 | strncpy(newpath, src, MAX_BUF-1); |
417 | newpath[MAX_BUF-1]='\0'; |
418 | newpath[MAX_BUF-1]='\0'; |
418 | |
419 | |
419 | for (cp=newpath; *cp!='\0'; cp++) { |
420 | for (cp=newpath; *cp!='\0'; cp++) { |
420 | if (*cp=='_') *cp='/'; |
421 | if (*cp=='_') *cp='/'; |
421 | } |
422 | } |
422 | return newpath; |
423 | return newpath; |
423 | } |
424 | } |
424 | |
425 | |
425 | |
426 | |
… | |
… | |
447 | * as where the player is. Otherwise, use the origin map. |
448 | * as where the player is. Otherwise, use the origin map. |
448 | * Take the last component (after the last slash) to give |
449 | * Take the last component (after the last slash) to give |
449 | * shorter names without bogus slashes. |
450 | * shorter names without bogus slashes. |
450 | */ |
451 | */ |
451 | if (rp.final_map[0]) { |
452 | if (rp.final_map[0]) { |
452 | cp = strrchr(rp.final_map, '/'); |
453 | cp = strrchr(rp.final_map, '/'); |
453 | if (!cp) cp = rp.final_map; |
454 | if (!cp) cp = rp.final_map; |
454 | } else { |
455 | } else { |
455 | char buf[HUGE_BUF]; |
456 | char buf[HUGE_BUF]; |
456 | |
457 | |
457 | cp = strrchr(rp.origin_map, '/'); |
458 | cp = strrchr(rp.origin_map, '/'); |
458 | if (!cp) cp = rp.origin_map; |
459 | if (!cp) cp = rp.origin_map; |
459 | /* Need to strip of any trailing digits, if it has them */ |
460 | /* Need to strip of any trailing digits, if it has them */ |
460 | strcpy(buf, cp); |
461 | strcpy(buf, cp); |
461 | while (isdigit(buf[strlen(buf) - 1])) |
462 | while (isdigit(buf[strlen(buf) - 1])) |
462 | buf[strlen(buf) - 1] = 0; |
463 | buf[strlen(buf) - 1] = 0; |
463 | cp = buf; |
464 | cp = buf; |
464 | } |
465 | } |
465 | |
466 | |
466 | sprintf(newmap_name,"/random/%s%04d",cp+1, reference_number++); |
467 | sprintf(newmap_name,"/random/%s%04d",cp+1, reference_number++); |
467 | |
468 | |
468 | /* now to generate the actual map. */ |
469 | /* now to generate the actual map. */ |
… | |
… | |
473 | * exit in a unique map leading to a random map will not work properly. |
474 | * exit in a unique map leading to a random map will not work properly. |
474 | * It also means that if the created random map gets reset before |
475 | * It also means that if the created random map gets reset before |
475 | * the exit leading to it, that the exit will no longer work. |
476 | * the exit leading to it, that the exit will no longer work. |
476 | */ |
477 | */ |
477 | if(new_map) { |
478 | if(new_map) { |
478 | int x, y; |
479 | int x, y; |
479 | x=EXIT_X(exit_ob) = MAP_ENTER_X(new_map); |
480 | x=EXIT_X(exit_ob) = MAP_ENTER_X(new_map); |
480 | y=EXIT_Y(exit_ob) = MAP_ENTER_Y(new_map); |
481 | y=EXIT_Y(exit_ob) = MAP_ENTER_Y(new_map); |
481 | EXIT_PATH(exit_ob) = add_string(newmap_name); |
482 | EXIT_PATH(exit_ob) = newmap_name; |
482 | strcpy(new_map->path, newmap_name); |
483 | strcpy(new_map->path, newmap_name); |
483 | enter_map(pl, new_map, x, y); |
484 | enter_map(pl, new_map, x, y); |
484 | } |
485 | } |
485 | } |
486 | } |
486 | |
487 | |
487 | /* The player is trying to enter a non-randomly generated template map. In this |
488 | /* The player is trying to enter a non-randomly generated template map. In this |
488 | * case, use a map file for a template |
489 | * case, use a map file for a template |
… | |
… | |
499 | * to generate the map from. |
500 | * to generate the map from. |
500 | */ |
501 | */ |
501 | snprintf(exitpath, sizeof(exitpath), "%s", EXIT_PATH(exit_ob)+2); |
502 | snprintf(exitpath, sizeof(exitpath), "%s", EXIT_PATH(exit_ob)+2); |
502 | sourcemap = strchr(exitpath, '!'); |
503 | sourcemap = strchr(exitpath, '!'); |
503 | if (!sourcemap) { |
504 | if (!sourcemap) { |
504 | new_draw_info_format(NDI_UNIQUE, 0, pl, "The %s is closed.", exit_ob->name); |
505 | new_draw_info_format(NDI_UNIQUE, 0, pl, "The %s is closed.", &exit_ob->name); |
505 | /* Should only occur when no source map is set. |
506 | /* Should only occur when no source map is set. |
506 | */ |
507 | */ |
507 | LOG(llevError,"enter_fixed_template_map: Exit %s (%d,%d) on map %s has no source template.\n", |
508 | LOG(llevError,"enter_fixed_template_map: Exit %s (%d,%d) on map %s has no source template.\n", |
508 | exit_ob->name, exit_ob->x, exit_ob->y, exit_ob->map->path); |
509 | &exit_ob->name, exit_ob->x, exit_ob->y, exit_ob->map->path); |
509 | return; |
510 | return; |
510 | } |
511 | } |
511 | *sourcemap++ = '\0'; |
512 | *sourcemap++ = '\0'; |
512 | |
513 | |
513 | /* If we are not coming from a template map, we can use relative directories |
514 | /* If we are not coming from a template map, we can use relative directories |
… | |
… | |
551 | if (new_map) { |
552 | if (new_map) { |
552 | /* set the path of the map to where it should be |
553 | /* set the path of the map to where it should be |
553 | * so we don't just save over the source map. |
554 | * so we don't just save over the source map. |
554 | */ |
555 | */ |
555 | strcpy(new_map->path, new_map_name); |
556 | strcpy(new_map->path, new_map_name); |
556 | new_map->templatemap = 1; |
557 | new_map->templatemap = 1; |
557 | enter_map(pl, new_map, EXIT_X(exit_ob), EXIT_Y(exit_ob)); |
558 | enter_map(pl, new_map, EXIT_X(exit_ob), EXIT_Y(exit_ob)); |
558 | } else { |
559 | } else { |
559 | new_draw_info_format(NDI_UNIQUE, 0, pl, "The %s is closed.", exit_ob->name); |
560 | new_draw_info_format(NDI_UNIQUE, 0, pl, "The %s is closed.", &exit_ob->name); |
560 | /* Should only occur when an invalid source map is set. |
561 | /* Should only occur when an invalid source map is set. |
561 | */ |
562 | */ |
562 | LOG(llevDebug,"enter_fixed_template_map: Exit %s (%d,%d) on map %s leads no where.\n", |
563 | LOG(llevDebug,"enter_fixed_template_map: Exit %s (%d,%d) on map %s leads no where.\n", |
563 | exit_ob->name, exit_ob->x, exit_ob->y, exit_ob->map->path); |
564 | &exit_ob->name, exit_ob->x, exit_ob->y, exit_ob->map->path); |
564 | } |
565 | } |
565 | } |
566 | } |
566 | |
567 | |
567 | |
568 | |
568 | /* The player is trying to enter a randomly generated template map. In this |
569 | /* The player is trying to enter a randomly generated template map. In this |
… | |
… | |
598 | new_map_name = create_template_pathname(resultname); |
599 | new_map_name = create_template_pathname(resultname); |
599 | } |
600 | } |
600 | |
601 | |
601 | new_map = ready_map_name(new_map_name, MAP_PLAYER_UNIQUE); |
602 | new_map = ready_map_name(new_map_name, MAP_PLAYER_UNIQUE); |
602 | if (!new_map) { |
603 | if (!new_map) { |
603 | memset(&rp, 0, sizeof(RMParms)); |
604 | memset(&rp, 0, sizeof(RMParms)); |
604 | rp.Xsize=-1; |
605 | rp.Xsize=-1; |
605 | rp.Ysize=-1; |
606 | rp.Ysize=-1; |
606 | rp.region=get_region_by_map(exit_ob->map); |
607 | rp.region=get_region_by_map(exit_ob->map); |
607 | if (exit_ob->msg) set_random_map_variable(&rp,exit_ob->msg); |
608 | if (exit_ob->msg) set_random_map_variable(&rp,exit_ob->msg); |
608 | rp.origin_x = exit_ob->x; |
609 | rp.origin_x = exit_ob->x; |
609 | rp.origin_y = exit_ob->y; |
610 | rp.origin_y = exit_ob->y; |
610 | strcpy(rp.origin_map, pl->map->path); |
611 | strcpy(rp.origin_map, pl->map->path); |
611 | |
612 | |
612 | /* now to generate the actual map. */ |
613 | /* now to generate the actual map. */ |
613 | new_map=generate_random_map(new_map_name,&rp); |
614 | new_map=generate_random_map(new_map_name,&rp); |
614 | } |
615 | } |
615 | |
616 | |
616 | |
617 | |
617 | /* Update the exit_ob so it now points directly at the newly created |
618 | /* Update the exit_ob so it now points directly at the newly created |
618 | * random maps. Not that it is likely to happen, but it does mean that a |
619 | * random maps. Not that it is likely to happen, but it does mean that a |
619 | * exit in a unique map leading to a random map will not work properly. |
620 | * exit in a unique map leading to a random map will not work properly. |
620 | * It also means that if the created random map gets reset before |
621 | * It also means that if the created random map gets reset before |
621 | * the exit leading to it, that the exit will no longer work. |
622 | * the exit leading to it, that the exit will no longer work. |
622 | */ |
623 | */ |
623 | if(new_map) { |
624 | if(new_map) { |
624 | int x, y; |
625 | int x, y; |
625 | x=EXIT_X(exit_ob) = MAP_ENTER_X(new_map); |
626 | x=EXIT_X(exit_ob) = MAP_ENTER_X(new_map); |
626 | y=EXIT_Y(exit_ob) = MAP_ENTER_Y(new_map); |
627 | y=EXIT_Y(exit_ob) = MAP_ENTER_Y(new_map); |
627 | new_map->templatemap = 1; |
628 | new_map->templatemap = 1; |
628 | enter_map(pl, new_map, x, y); |
629 | enter_map(pl, new_map, x, y); |
629 | } |
630 | } |
630 | } |
631 | } |
631 | |
632 | |
632 | |
633 | |
633 | /* Code to enter/detect a character entering a unique map. |
634 | /* Code to enter/detect a character entering a unique map. |
… | |
… | |
636 | { |
637 | { |
637 | char apartment[HUGE_BUF]; |
638 | char apartment[HUGE_BUF]; |
638 | mapstruct *newmap; |
639 | mapstruct *newmap; |
639 | |
640 | |
640 | if (EXIT_PATH(exit_ob)[0]=='/') { |
641 | if (EXIT_PATH(exit_ob)[0]=='/') { |
641 | sprintf(apartment, "%s/%s/%s/%s", settings.localdir, |
642 | sprintf(apartment, "%s/%s/%s/%s", settings.localdir, |
642 | settings.playerdir, op->name, clean_path(EXIT_PATH(exit_ob))); |
643 | settings.playerdir, &op->name, clean_path(EXIT_PATH(exit_ob))); |
643 | newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE); |
644 | newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE); |
644 | if (!newmap) { |
645 | if (!newmap) { |
645 | newmap = load_original_map(create_pathname(EXIT_PATH(exit_ob)), MAP_PLAYER_UNIQUE); |
646 | newmap = load_original_map(create_pathname(EXIT_PATH(exit_ob)), MAP_PLAYER_UNIQUE); |
646 | if (newmap) fix_auto_apply(newmap); |
647 | if (newmap) fix_auto_apply(newmap); |
647 | } |
648 | } |
648 | } else { /* relative directory */ |
649 | } else { /* relative directory */ |
649 | char reldir[HUGE_BUF], tmpc[HUGE_BUF], *cp; |
650 | char reldir[HUGE_BUF], tmpc[HUGE_BUF], *cp; |
650 | |
651 | |
651 | if (exit_ob->map->unique) { |
652 | if (exit_ob->map->unique) { |
652 | |
653 | |
653 | strcpy(reldir, unclean_path(exit_ob->map->path)); |
654 | strcpy(reldir, unclean_path(exit_ob->map->path)); |
654 | |
655 | |
655 | /* Need to copy this over, as clean_path only has one static return buffer */ |
656 | /* Need to copy this over, as clean_path only has one static return buffer */ |
656 | strcpy(tmpc, clean_path(reldir)); |
657 | strcpy(tmpc, clean_path(reldir)); |
657 | /* Remove final component, if any */ |
658 | /* Remove final component, if any */ |
658 | if ((cp=strrchr(tmpc, '_'))!=NULL) *cp=0; |
659 | if ((cp=strrchr(tmpc, '_'))!=NULL) *cp=0; |
659 | |
660 | |
660 | sprintf(apartment, "%s/%s/%s/%s_%s", settings.localdir, |
661 | sprintf(apartment, "%s/%s/%s/%s_%s", settings.localdir, |
661 | settings.playerdir, op->name, tmpc, |
662 | settings.playerdir, &op->name, tmpc, |
662 | clean_path(EXIT_PATH(exit_ob))); |
663 | clean_path(EXIT_PATH(exit_ob))); |
663 | |
664 | |
664 | newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE); |
665 | newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE); |
665 | if (!newmap) { |
666 | if (!newmap) { |
666 | newmap = load_original_map(create_pathname(path_combine_and_normalize(reldir, EXIT_PATH(exit_ob))), MAP_PLAYER_UNIQUE); |
667 | newmap = load_original_map(create_pathname(path_combine_and_normalize(reldir, EXIT_PATH(exit_ob))), MAP_PLAYER_UNIQUE); |
667 | if (newmap) fix_auto_apply(newmap); |
668 | if (newmap) fix_auto_apply(newmap); |
668 | } |
669 | } |
669 | } |
670 | } |
670 | else { |
671 | else { |
671 | /* The exit is unique, but the map we are coming from is not unique. So |
672 | /* The exit is unique, but the map we are coming from is not unique. So |
672 | * use the basic logic - don't need to demangle the path name |
673 | * use the basic logic - don't need to demangle the path name |
673 | */ |
674 | */ |
674 | sprintf(apartment, "%s/%s/%s/%s", settings.localdir, |
675 | sprintf(apartment, "%s/%s/%s/%s", settings.localdir, |
675 | settings.playerdir, op->name, |
676 | settings.playerdir, &op->name, |
676 | clean_path(path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob)))); |
677 | clean_path(path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob)))); |
677 | newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE); |
678 | newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE); |
678 | if (!newmap) { |
679 | if (!newmap) { |
679 | newmap = ready_map_name(path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob)), 0); |
680 | newmap = ready_map_name(path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob)), 0); |
680 | if (newmap) fix_auto_apply(newmap); |
681 | if (newmap) fix_auto_apply(newmap); |
681 | } |
682 | } |
682 | } |
683 | } |
683 | } |
684 | } |
684 | |
685 | |
685 | if (newmap) { |
686 | if (newmap) { |
686 | strcpy(newmap->path, apartment); |
687 | strcpy(newmap->path, apartment); |
687 | newmap->unique = 1; |
688 | newmap->unique = 1; |
688 | enter_map(op, newmap, EXIT_X(exit_ob), EXIT_Y(exit_ob)); |
689 | enter_map(op, newmap, EXIT_X(exit_ob), EXIT_Y(exit_ob)); |
689 | } else { |
690 | } else { |
690 | new_draw_info_format(NDI_UNIQUE, 0, op, "The %s is closed.", exit_ob->name); |
691 | new_draw_info_format(NDI_UNIQUE, 0, op, "The %s is closed.", &exit_ob->name); |
691 | /* Perhaps not critical, but I would think that the unique maps |
692 | /* Perhaps not critical, but I would think that the unique maps |
692 | * should be new enough this does not happen. This also creates |
693 | * should be new enough this does not happen. This also creates |
693 | * a strange situation where some players could perhaps have visited |
694 | * a strange situation where some players could perhaps have visited |
694 | * such a map before it was removed, so they have the private |
695 | * such a map before it was removed, so they have the private |
695 | * map, but other players can't get it anymore. |
696 | * map, but other players can't get it anymore. |
696 | */ |
697 | */ |
697 | LOG(llevDebug,"enter_unique_map: Exit %s (%d,%d) on map %s is leads no where.\n", |
698 | LOG(llevDebug,"enter_unique_map: Exit %s (%d,%d) on map %s is leads no where.\n", |
698 | exit_ob->name, exit_ob->x, exit_ob->y, exit_ob->map->path); |
699 | &exit_ob->name, exit_ob->x, exit_ob->y, exit_ob->map->path); |
699 | } |
700 | } |
700 | |
701 | |
701 | } |
702 | } |
702 | |
703 | |
703 | |
704 | |
704 | /* Tries to move 'op' to exit_ob. op is the character or monster that is |
705 | /* Tries to move 'op' to exit_ob. op is the character or monster that is |
705 | * using the exit, where exit_ob is the exit object (boat, door, teleporter, |
706 | * using the exit, where exit_ob is the exit object (boat, door, teleporter, |
… | |
… | |
717 | * exits, but right now a lot of the code looks at op->contr, |
718 | * exits, but right now a lot of the code looks at op->contr, |
718 | * so thta is an RFE. |
719 | * so thta is an RFE. |
719 | */ |
720 | */ |
720 | if (op->type != PLAYER) return; |
721 | if (op->type != PLAYER) return; |
721 | |
722 | |
722 | /* Need to remove player from transport */ |
|
|
723 | if (op->contr->transport) apply_transport(op, op->contr->transport, AP_UNAPPLY); |
|
|
724 | |
|
|
725 | /* First, lets figure out what map the player is going to go to */ |
723 | /* First, lets figure out what map the player is going to go to */ |
726 | if (exit_ob){ |
724 | if (exit_ob){ |
727 | |
725 | |
728 | /* check to see if we make a template map */ |
726 | /* check to see if we make a template map */ |
729 | if(EXIT_PATH(exit_ob)&&EXIT_PATH(exit_ob)[1]=='@') { |
727 | if(EXIT_PATH(exit_ob)&&EXIT_PATH(exit_ob)[1]=='@') { |
730 | if (EXIT_PATH(exit_ob)[2]=='!') { |
728 | if (EXIT_PATH(exit_ob)[2]=='!') { |
731 | /* generate a template map randomly */ |
729 | /* generate a template map randomly */ |
732 | enter_random_template_map(op, exit_ob); |
730 | enter_random_template_map(op, exit_ob); |
733 | } else { |
731 | } else { |
734 | /* generate a template map from a fixed template */ |
732 | /* generate a template map from a fixed template */ |
735 | enter_fixed_template_map(op, exit_ob); |
733 | enter_fixed_template_map(op, exit_ob); |
736 | } |
734 | } |
737 | } |
735 | } |
738 | /* check to see if we make a randomly generated map */ |
736 | /* check to see if we make a randomly generated map */ |
739 | else if(EXIT_PATH(exit_ob)&&EXIT_PATH(exit_ob)[1]=='!') { |
737 | else if(EXIT_PATH(exit_ob)&&EXIT_PATH(exit_ob)[1]=='!') { |
740 | enter_random_map(op, exit_ob); |
738 | enter_random_map(op, exit_ob); |
741 | } |
739 | } |
742 | else if (QUERY_FLAG(exit_ob, FLAG_UNIQUE)) { |
740 | else if (QUERY_FLAG(exit_ob, FLAG_UNIQUE)) { |
743 | enter_unique_map(op, exit_ob); |
741 | enter_unique_map(op, exit_ob); |
744 | } else { |
742 | } else { |
745 | int x=EXIT_X(exit_ob), y=EXIT_Y(exit_ob); |
743 | int x=EXIT_X(exit_ob), y=EXIT_Y(exit_ob); |
746 | /* 'Normal' exits that do not do anything special |
744 | /* 'Normal' exits that do not do anything special |
747 | * Simple enough we don't need another routine for it. |
745 | * Simple enough we don't need another routine for it. |
748 | */ |
746 | */ |
749 | mapstruct *newmap; |
747 | mapstruct *newmap; |
750 | if (exit_ob->map) { |
748 | if (exit_ob->map) { |
751 | newmap = ready_map_name(path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob)), 0); |
749 | newmap = ready_map_name(path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob)), 0); |
752 | /* Random map was previously generated, but is no longer about. Lets generate a new |
750 | /* Random map was previously generated, but is no longer about. Lets generate a new |
753 | * map. |
751 | * map. |
754 | */ |
752 | */ |
755 | if (!newmap && !strncmp(EXIT_PATH(exit_ob),"/random/",8)) { |
753 | if (!newmap && !strncmp(EXIT_PATH(exit_ob),"/random/",8)) { |
756 | /* Maps that go down have a message set. However, maps that go |
754 | /* Maps that go down have a message set. However, maps that go |
757 | * up, don't. If the going home has reset, there isn't much |
755 | * up, don't. If the going home has reset, there isn't much |
758 | * point generating a random map, because it won't match the maps. |
756 | * point generating a random map, because it won't match the maps. |
759 | */ |
757 | */ |
760 | if (exit_ob->msg) { |
758 | if (exit_ob->msg) { |
761 | enter_random_map(op, exit_ob); |
759 | enter_random_map(op, exit_ob); |
762 | } else { |
760 | } else { |
763 | new_draw_info_format(NDI_UNIQUE, 0, op, "The %s is closed.", exit_ob->name); |
761 | new_draw_info_format(NDI_UNIQUE, 0, op, "The %s is closed.", &exit_ob->name); |
764 | return; |
762 | return; |
765 | } |
763 | } |
766 | |
764 | |
767 | /* For exits that cause damages (like pits). Don't know if any |
765 | /* For exits that cause damages (like pits). Don't know if any |
768 | * random maps use this or not. |
766 | * random maps use this or not. |
769 | */ |
767 | */ |
770 | if(exit_ob->stats.dam && op->type==PLAYER) |
768 | if(exit_ob->stats.dam && op->type==PLAYER) |
771 | hit_player(op,exit_ob->stats.dam,exit_ob,exit_ob->attacktype,1); |
769 | hit_player(op,exit_ob->stats.dam,exit_ob,exit_ob->attacktype,1); |
772 | return; |
770 | return; |
773 | } |
771 | } |
774 | } else { |
772 | } else { |
775 | /* For word of recall and other force objects |
773 | /* For word of recall and other force objects |
776 | * They contain the full pathname of the map to go back to, |
774 | * They contain the full pathname of the map to go back to, |
777 | * so we don't need to normalize it. |
775 | * so we don't need to normalize it. |
778 | * But we do need to see if it is unique or not |
776 | * But we do need to see if it is unique or not |
779 | */ |
777 | */ |
780 | if (!strncmp(EXIT_PATH(exit_ob), settings.localdir, strlen(settings.localdir))) |
778 | if (!strncmp(EXIT_PATH(exit_ob), settings.localdir, strlen(settings.localdir))) |
781 | newmap = ready_map_name(EXIT_PATH(exit_ob), MAP_PLAYER_UNIQUE); |
779 | newmap = ready_map_name(EXIT_PATH(exit_ob), MAP_PLAYER_UNIQUE); |
782 | else |
780 | else |
783 | newmap = ready_map_name(EXIT_PATH(exit_ob), 0); |
781 | newmap = ready_map_name(EXIT_PATH(exit_ob), 0); |
784 | } |
782 | } |
785 | if (!newmap) |
783 | if (!newmap) |
786 | { |
784 | { |
787 | if (exit_ob->name) |
785 | if (exit_ob->name) |
788 | new_draw_info_format(NDI_UNIQUE, 0, op, "The %s is closed.", exit_ob->name); |
786 | new_draw_info_format(NDI_UNIQUE, 0, op, "The %s is closed.", &exit_ob->name); |
789 | /* don't cry to momma if name is not set - as in tmp objects |
787 | /* don't cry to momma if name is not set - as in tmp objects |
790 | * used by the savebed code and character creation */ |
788 | * used by the savebed code and character creation */ |
791 | return; |
789 | return; |
792 | } |
790 | } |
793 | |
791 | |
794 | /* This supports the old behaviour, but it really should not be used. |
792 | /* This supports the old behaviour, but it really should not be used. |
795 | * I will note for example that with this method, it is impossible to |
793 | * I will note for example that with this method, it is impossible to |
796 | * set 0,0 destination coordinates. Really, if we want to support |
794 | * set 0,0 destination coordinates. Really, if we want to support |
797 | * using the new maps default coordinates, the exit ob should use |
795 | * using the new maps default coordinates, the exit ob should use |
798 | * something like -1, -1 so it is clear to do that. |
796 | * something like -1, -1 so it is clear to do that. |
799 | */ |
797 | */ |
800 | if (x==0 && y==0) { |
798 | if (x==0 && y==0) { |
801 | x=MAP_ENTER_X(newmap); |
799 | x=MAP_ENTER_X(newmap); |
802 | y=MAP_ENTER_Y(newmap); |
800 | y=MAP_ENTER_Y(newmap); |
803 | LOG(llevDebug,"enter_exit: Exit %s (%d,%d) on map %s is 0 destination coordinates\n", |
801 | LOG(llevDebug,"enter_exit: Exit %s (%d,%d) on map %s is 0 destination coordinates\n", |
804 | exit_ob->name?exit_ob->name:"(none)", exit_ob->x, exit_ob->y, |
802 | &exit_ob->name, exit_ob->x, exit_ob->y, |
805 | exit_ob->map?exit_ob->map->path:"(none)"); |
803 | exit_ob->map ? exit_ob->map->path : "<nil>"); |
806 | } |
804 | } |
807 | |
805 | |
808 | /* mids 02/13/2002 if exit is damned, update players death & WoR home-position and delete town portal */ |
806 | /* mids 02/13/2002 if exit is damned, update players death & WoR home-position and delete town portal */ |
809 | if (QUERY_FLAG(exit_ob, FLAG_DAMNED)) { |
807 | if (QUERY_FLAG(exit_ob, FLAG_DAMNED)) { |
810 | /* remove an old force with a slaying field == PORTAL_DESTINATION_NAME */ |
808 | /* remove an old force with a slaying field == PORTAL_DESTINATION_NAME */ |
811 | for(tmp=op->inv; tmp != NULL; tmp = tmp->below) { |
809 | for(tmp=op->inv; tmp != NULL; tmp = tmp->below) { |
… | |
… | |
822 | /* LOG(llevDebug,"enter_exit: Taking damned exit %s to (%d,%d) on map %s\n", |
820 | /* LOG(llevDebug,"enter_exit: Taking damned exit %s to (%d,%d) on map %s\n", |
823 | * exit_ob->name?exit_ob->name:"(none)", exit_ob->x, exit_ob->y, |
821 | * exit_ob->name?exit_ob->name:"(none)", exit_ob->x, exit_ob->y, |
824 | * path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob))); */ |
822 | * path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob))); */ |
825 | } |
823 | } |
826 | |
824 | |
827 | enter_map(op, newmap, x, y); |
825 | enter_map(op, newmap, x, y); |
828 | } |
826 | } |
829 | /* For exits that cause damages (like pits) */ |
827 | /* For exits that cause damages (like pits) */ |
830 | if(exit_ob->stats.dam && op->type==PLAYER) |
828 | if(exit_ob->stats.dam && op->type==PLAYER) |
831 | hit_player(op,exit_ob->stats.dam,exit_ob,exit_ob->attacktype,1); |
829 | hit_player(op,exit_ob->stats.dam,exit_ob,exit_ob->attacktype,1); |
832 | } else { |
830 | } else { |
833 | int flags = 0; |
831 | int flags = 0; |
834 | mapstruct *newmap; |
832 | mapstruct *newmap; |
835 | |
833 | |
836 | |
834 | |
837 | /* Hypothetically, I guess its possible that a standard map matches |
835 | /* Hypothetically, I guess its possible that a standard map matches |
838 | * the localdir, but that seems pretty unlikely - unlikely enough that |
836 | * the localdir, but that seems pretty unlikely - unlikely enough that |
839 | * I'm not going to attempt to try to deal with that possibility. |
837 | * I'm not going to attempt to try to deal with that possibility. |
840 | * We use the fact that when a player saves on a unique map, it prepends |
838 | * We use the fact that when a player saves on a unique map, it prepends |
841 | * the localdir to that name. So its an easy way to see of the map is |
839 | * the localdir to that name. So its an easy way to see of the map is |
842 | * unique or not. |
840 | * unique or not. |
843 | */ |
841 | */ |
844 | if (!strncmp(op->contr->maplevel, settings.localdir, strlen(settings.localdir))) |
842 | if (!strncmp(op->contr->maplevel, settings.localdir, strlen(settings.localdir))) |
845 | flags = MAP_PLAYER_UNIQUE; |
843 | flags = MAP_PLAYER_UNIQUE; |
846 | |
844 | |
847 | /* newmap returns the map (if already loaded), or loads it for |
845 | /* newmap returns the map (if already loaded), or loads it for |
848 | * us. |
846 | * us. |
849 | */ |
847 | */ |
850 | newmap = ready_map_name(op->contr->maplevel, flags); |
848 | newmap = ready_map_name(op->contr->maplevel, flags); |
851 | if (!newmap) |
849 | if (!newmap) |
852 | { |
850 | { |
853 | LOG(llevError, |
851 | LOG(llevError, |
854 | "enter_exit: Pathname to map does not exist! (%s)\n", |
852 | "enter_exit: Pathname to map does not exist! (%s)\n", |
855 | op->contr->maplevel); |
853 | op->contr->maplevel); |
856 | newmap = ready_map_name(settings.emergency_mapname, 0); |
854 | newmap = ready_map_name(settings.emergency_mapname, 0); |
857 | op->x = settings.emergency_x; |
855 | op->x = settings.emergency_x; |
858 | op->y = settings.emergency_y; |
856 | op->y = settings.emergency_y; |
859 | /* If we can't load the emergency map, something is probably really |
857 | /* If we can't load the emergency map, something is probably really |
860 | * screwed up, so bail out now. |
858 | * screwed up, so bail out now. |
861 | */ |
859 | */ |
862 | if (!newmap) { |
860 | if (!newmap) { |
863 | LOG(llevError,"enter_exit: could not load emergency map? Fatal error\n"); |
861 | LOG(llevError,"enter_exit: could not load emergency map? Fatal error\n"); |
864 | abort(); |
862 | abort(); |
865 | } |
863 | } |
866 | } |
864 | } |
867 | enter_map(op, newmap, op->x, op->y); |
865 | enter_map(op, newmap, op->x, op->y); |
868 | } |
866 | } |
869 | } |
867 | } |
870 | |
868 | |
871 | /* |
869 | /* |
872 | * process_active_maps(): Works like process_events(), but it only |
870 | * process_active_maps(): Works like process_events(), but it only |
… | |
… | |
897 | int flag; |
895 | int flag; |
898 | player *pl,*plnext; |
896 | player *pl,*plnext; |
899 | |
897 | |
900 | /* Basically, we keep looping until all the players have done their actions. */ |
898 | /* Basically, we keep looping until all the players have done their actions. */ |
901 | for(flag=1;flag!=0;) { |
899 | for(flag=1;flag!=0;) { |
902 | flag=0; |
900 | flag=0; |
903 | for(pl=first_player;pl!=NULL;pl=plnext) { |
901 | for(pl=first_player;pl!=NULL;pl=plnext) { |
904 | plnext=pl->next; /* In case a player exits the game in handle_player() */ |
902 | plnext=pl->next; /* In case a player exits the game in handle_player() */ |
905 | |
903 | |
906 | if (pl->ob == NULL) continue; |
904 | if (pl->ob == NULL) continue; |
907 | |
905 | |
908 | if (map!=NULL && pl->ob->map!=map) continue; |
906 | if (map!=NULL && pl->ob->map!=map) continue; |
909 | |
907 | |
910 | if(pl->ob->speed_left>0) { |
908 | if(pl->ob->speed_left>0) { |
911 | if (handle_newcs_player(pl->ob)) |
909 | if (handle_newcs_player(pl->ob)) |
912 | flag=1; |
910 | flag=1; |
913 | } /* end if player has speed left */ |
911 | } /* end if player has speed left */ |
914 | |
912 | |
915 | /* If the player is not actively playing, don't make a |
913 | /* If the player is not actively playing, don't make a |
916 | * backup save - nothing to save anyway. Plus, the |
914 | * backup save - nothing to save anyway. Plus, the |
917 | * map may not longer be valid. This can happen when the |
915 | * map may not longer be valid. This can happen when the |
918 | * player quits - they exist for purposes of tracking on the map, |
916 | * player quits - they exist for purposes of tracking on the map, |
919 | * but don't actually reside on any actual map. |
917 | * but don't actually reside on any actual map. |
920 | */ |
918 | */ |
921 | if (QUERY_FLAG(pl->ob, FLAG_REMOVED)) continue; |
919 | if (QUERY_FLAG(pl->ob, FLAG_REMOVED)) continue; |
922 | |
920 | |
923 | #ifdef AUTOSAVE |
921 | #ifdef AUTOSAVE |
924 | /* check for ST_PLAYING state so that we don't try to save off when |
922 | /* check for ST_PLAYING state so that we don't try to save off when |
925 | * the player is logging in. |
923 | * the player is logging in. |
926 | */ |
924 | */ |
927 | if ((pl->last_save_tick+AUTOSAVE)<pticks && pl->state==ST_PLAYING) { |
925 | if ((pl->last_save_tick+AUTOSAVE)<pticks && pl->state==ST_PLAYING) { |
928 | /* Don't save the player on unholy ground. Instead, increase the |
926 | /* Don't save the player on unholy ground. Instead, increase the |
929 | * tick time so it will be about 10 seconds before we try and save |
927 | * tick time so it will be about 10 seconds before we try and save |
930 | * again. |
928 | * again. |
931 | */ |
929 | */ |
932 | // if (get_map_flags(pl->ob->map, NULL, pl->ob->x, pl->ob->y, NULL, NULL) & P_NO_CLERIC) { |
930 | // if (get_map_flags(pl->ob->map, NULL, pl->ob->x, pl->ob->y, NULL, NULL) & P_NO_CLERIC) { |
933 | // pl->last_save_tick += 100; |
931 | // pl->last_save_tick += 100; |
934 | // } else { |
932 | // } else { |
935 | save_player(pl->ob,1); |
933 | save_player(pl->ob,1); |
936 | pl->last_save_tick = pticks; |
934 | pl->last_save_tick = pticks; |
937 | // } |
935 | // } |
938 | } |
936 | } |
939 | #endif |
937 | #endif |
940 | } /* end of for loop for all the players */ |
938 | } /* end of for loop for all the players */ |
941 | } /* for flag */ |
939 | } /* for flag */ |
942 | for(pl=first_player;pl!=NULL;pl=pl->next) { |
940 | for(pl=first_player;pl!=NULL;pl=pl->next) { |
943 | if (map!=NULL && (pl->ob == NULL || pl->ob->map!=map)) |
941 | if (map!=NULL && (pl->ob == NULL || pl->ob->map!=map)) |
944 | continue; |
942 | continue; |
945 | if (settings.casting_time == TRUE) { |
943 | if (settings.casting_time == TRUE) { |
946 | if (pl->ob->casting_time > 0){ |
944 | if (pl->ob->casting_time > 0){ |
947 | pl->ob->casting_time--; |
945 | pl->ob->casting_time--; |
948 | pl->ob->start_holding = 1; |
946 | pl->ob->start_holding = 1; |
949 | } |
947 | } |
950 | /* set spell_state so we can update the range in stats field */ |
948 | /* set spell_state so we can update the range in stats field */ |
951 | if ((pl->ob->casting_time == 0) && (pl->ob->start_holding ==1)){ |
949 | if ((pl->ob->casting_time == 0) && (pl->ob->start_holding ==1)){ |
952 | pl->ob->start_holding = 0; |
950 | pl->ob->start_holding = 0; |
953 | } |
951 | } |
954 | } |
952 | } |
955 | do_some_living(pl->ob); |
953 | do_some_living(pl->ob); |
956 | /* draw(pl->ob);*/ /* updated in socket code */ |
954 | /* draw(pl->ob);*/ /* updated in socket code */ |
957 | } |
955 | } |
958 | } |
956 | } |
959 | |
957 | |
960 | void process_players2(mapstruct *map) |
958 | void process_players2(mapstruct *map) |
961 | { |
959 | { |
962 | player *pl; |
960 | player *pl; |
963 | |
961 | |
964 | /* Then check if any players should use weapon-speed instead of speed */ |
962 | /* Then check if any players should use weapon-speed instead of speed */ |
965 | for(pl=first_player;pl!=NULL;pl=pl->next) { |
963 | for(pl=first_player;pl!=NULL;pl=pl->next) { |
966 | if (map!=NULL) { |
964 | if (map!=NULL) { |
967 | if(pl->ob == NULL || QUERY_FLAG(pl->ob,FLAG_REMOVED)) |
965 | if(pl->ob == NULL || QUERY_FLAG(pl->ob,FLAG_REMOVED)) |
968 | continue; |
966 | continue; |
969 | else if(pl->loading != NULL) /* Player is blocked */ |
967 | else if(pl->loading != NULL) /* Player is blocked */ |
970 | pl->ob->speed_left -= pl->ob->speed; |
968 | pl->ob->speed_left -= pl->ob->speed; |
971 | if (pl->ob->map!=map) continue; |
969 | if (pl->ob->map!=map) continue; |
972 | } |
970 | } |
973 | |
971 | |
974 | /* The code that did weapon_sp handling here was out of place - |
972 | /* The code that did weapon_sp handling here was out of place - |
975 | * this isn't called until after the player has finished there |
973 | * this isn't called until after the player has finished there |
976 | * actions, and is thus out of place. All we do here is bounds |
974 | * actions, and is thus out of place. All we do here is bounds |
977 | * checking. |
975 | * checking. |
978 | */ |
976 | */ |
979 | if (pl->has_hit) { |
977 | if (pl->has_hit) { |
980 | if (pl->ob->speed_left > pl->weapon_sp) pl->ob->speed_left = pl->weapon_sp; |
978 | if (pl->ob->speed_left > pl->weapon_sp) pl->ob->speed_left = pl->weapon_sp; |
981 | |
979 | |
982 | /* This needs to be here - if the player is running, we need to |
980 | /* This needs to be here - if the player is running, we need to |
983 | * clear this each tick, but new commands are not being received |
981 | * clear this each tick, but new commands are not being received |
984 | * so execute_newserver_command() is never called |
982 | * so execute_newserver_command() is never called |
985 | */ |
983 | */ |
986 | pl->has_hit=0; |
984 | pl->has_hit=0; |
987 | |
985 | |
988 | } else if (pl->ob->speed_left>pl->ob->speed) |
986 | } else if (pl->ob->speed_left>pl->ob->speed) |
989 | pl->ob->speed_left = pl->ob->speed; |
987 | pl->ob->speed_left = pl->ob->speed; |
990 | } |
988 | } |
991 | } |
989 | } |
992 | |
990 | |
993 | #define SPEED_DEBUG |
991 | #define SPEED_DEBUG |
994 | |
992 | |
… | |
… | |
1004 | memset(&marker, 0, sizeof(object)); |
1002 | memset(&marker, 0, sizeof(object)); |
1005 | /* Put marker object at beginning of active list */ |
1003 | /* Put marker object at beginning of active list */ |
1006 | marker.active_next = active_objects; |
1004 | marker.active_next = active_objects; |
1007 | |
1005 | |
1008 | if (marker.active_next) |
1006 | if (marker.active_next) |
1009 | marker.active_next->active_prev = ▮ |
1007 | marker.active_next->active_prev = ▮ |
1010 | marker.active_prev = NULL; |
1008 | marker.active_prev = NULL; |
1011 | active_objects = ▮ |
1009 | active_objects = ▮ |
1012 | |
1010 | |
1013 | while (marker.active_next) { |
1011 | while (marker.active_next) { |
1014 | op = marker.active_next; |
1012 | op = marker.active_next; |
1015 | tag = op->count; |
1013 | tag = op->count; |
1016 | |
1014 | |
1017 | /* Move marker forward - swap op and marker */ |
1015 | /* Move marker forward - swap op and marker */ |
1018 | op->active_prev = marker.active_prev; |
1016 | op->active_prev = marker.active_prev; |
1019 | |
1017 | |
1020 | if (op->active_prev) |
1018 | if (op->active_prev) |
1021 | op->active_prev->active_next = op; |
1019 | op->active_prev->active_next = op; |
1022 | else |
1020 | else |
1023 | active_objects = op; |
1021 | active_objects = op; |
1024 | |
1022 | |
1025 | marker.active_next = op->active_next; |
1023 | marker.active_next = op->active_next; |
1026 | |
1024 | |
1027 | if (marker.active_next) |
1025 | if (marker.active_next) |
1028 | marker.active_next->active_prev = ▮ |
1026 | marker.active_next->active_prev = ▮ |
1029 | marker.active_prev = op; |
1027 | marker.active_prev = op; |
1030 | op->active_next = ▮ |
1028 | op->active_next = ▮ |
1031 | |
1029 | |
1032 | /* Now process op */ |
1030 | /* Now process op */ |
1033 | if (QUERY_FLAG (op, FLAG_FREED)) { |
1031 | if (QUERY_FLAG (op, FLAG_FREED)) { |
1034 | LOG (llevError, "BUG: process_events(): Free object on list\n"); |
1032 | LOG (llevError, "BUG: process_events(): Free object on list\n"); |
1035 | op->speed = 0; |
1033 | op->speed = 0; |
1036 | update_ob_speed (op); |
1034 | update_ob_speed (op); |
1037 | continue; |
1035 | continue; |
1038 | } |
1036 | } |
1039 | |
1037 | |
1040 | /* I've seen occasional crashes due to this - the object is removed, |
1038 | /* I've seen occasional crashes due to this - the object is removed, |
1041 | * and thus the map it points to (last map it was on) may be bogus |
1039 | * and thus the map it points to (last map it was on) may be bogus |
1042 | * The real bug is to try to find out the cause of this - someone |
1040 | * The real bug is to try to find out the cause of this - someone |
1043 | * is probably calling remove_ob without either an insert_ob or |
1041 | * is probably calling remove_ob without either an insert_ob or |
1044 | * free_object afterwards, leaving an object dangling. But I'd |
1042 | * free_object afterwards, leaving an object dangling. But I'd |
1045 | * rather log this and continue on instead of crashing. |
1043 | * rather log this and continue on instead of crashing. |
1046 | * Don't remove players - when a player quits, the object is in |
1044 | * Don't remove players - when a player quits, the object is in |
1047 | * sort of a limbo, of removed, but something we want to keep |
1045 | * sort of a limbo, of removed, but something we want to keep |
1048 | * around. |
1046 | * around. |
1049 | */ |
1047 | */ |
1050 | if (QUERY_FLAG (op, FLAG_REMOVED) && op->type != PLAYER && |
1048 | if (QUERY_FLAG (op, FLAG_REMOVED) && op->type != PLAYER && |
1051 | op->map && op->map->in_memory != MAP_IN_MEMORY) { |
1049 | op->map && op->map->in_memory != MAP_IN_MEMORY) { |
1052 | LOG (llevError, "BUG: process_events(): Removed object on list\n"); |
1050 | LOG (llevError, "BUG: process_events(): Removed object on list\n"); |
1053 | dump_object(op); |
1051 | dump_object(op); |
1054 | LOG(llevError, errmsg); |
1052 | LOG(llevError, errmsg); |
1055 | free_object(op); |
1053 | free_object(op); |
1056 | continue; |
1054 | continue; |
1057 | } |
1055 | } |
1058 | |
1056 | |
1059 | if ( ! op->speed) { |
1057 | if ( ! op->speed) { |
1060 | LOG (llevError, "BUG: process_events(): Object %s has no speed, " |
1058 | LOG (llevError, "BUG: process_events(): Object %s has no speed, " |
1061 | "but is on active list\n", op->arch->name); |
1059 | "but is on active list\n", &op->arch->name); |
1062 | update_ob_speed (op); |
1060 | update_ob_speed (op); |
1063 | continue; |
1061 | continue; |
1064 | } |
1062 | } |
1065 | |
1063 | |
1066 | if (op->map == NULL && op->env == NULL && op->name && |
1064 | if (op->map == NULL && op->env == NULL && op->name && |
1067 | op->type != MAP && map == NULL) { |
1065 | op->type != MAP && map == NULL) { |
1068 | LOG (llevError, "BUG: process_events(): Object without map or " |
1066 | LOG (llevError, "BUG: process_events(): Object without map or " |
1069 | "inventory is on active list: %s (%d)\n", |
1067 | "inventory is on active list: %s (%d)\n", |
1070 | op->name, op->count); |
1068 | &op->name, op->count); |
1071 | op->speed = 0; |
1069 | op->speed = 0; |
1072 | update_ob_speed (op); |
1070 | update_ob_speed (op); |
1073 | continue; |
1071 | continue; |
1074 | } |
1072 | } |
1075 | |
1073 | |
1076 | if (map != NULL && op->map != map) |
1074 | if (map != NULL && op->map != map) |
1077 | continue; |
1075 | continue; |
1078 | |
1076 | |
1079 | /* Animate the object. Bug of feature that andim_speed |
1077 | /* Animate the object. Bug of feature that andim_speed |
1080 | * is based on ticks, and not the creatures speed? |
1078 | * is based on ticks, and not the creatures speed? |
1081 | */ |
1079 | */ |
1082 | if (op->anim_speed && op->last_anim >= op->anim_speed) |
1080 | if (op->anim_speed && op->last_anim >= op->anim_speed) |
1083 | { |
1081 | { |
1084 | if ((op->type==PLAYER)||(op->type==MONSTER)) |
1082 | if ((op->type==PLAYER)||(op->type==MONSTER)) |
1085 | animate_object(op, op->facing); |
1083 | animate_object(op, op->facing); |
1086 | else |
1084 | else |
… | |
… | |
1089 | op->last_anim = 1; |
1087 | op->last_anim = 1; |
1090 | } |
1088 | } |
1091 | else |
1089 | else |
1092 | op->last_anim++; |
1090 | op->last_anim++; |
1093 | |
1091 | |
1094 | if (op->speed_left > 0) { |
1092 | if (op->speed_left > 0) { |
1095 | #if 0 |
1093 | #if 0 |
1096 | /* I've seen occasional crashes in move_symptom() with it |
1094 | /* I've seen occasional crashes in move_symptom() with it |
1097 | * crashing because op is removed - add some debugging to |
1095 | * crashing because op is removed - add some debugging to |
1098 | * track if it is removed at this point. |
1096 | * track if it is removed at this point. |
1099 | * This unfortunately is a bit too verbose it seems - not sure |
1097 | * This unfortunately is a bit too verbose it seems - not sure |
1100 | * why - I think what happens is a map is freed or something and |
1098 | * why - I think what happens is a map is freed or something and |
1101 | * some objects get 'lost' - removed never to be reclaimed. |
1099 | * some objects get 'lost' - removed never to be reclaimed. |
1102 | * removed objects generally shouldn't exist. |
1100 | * removed objects generally shouldn't exist. |
1103 | */ |
1101 | */ |
1104 | if (QUERY_FLAG(op, FLAG_REMOVED)) { |
1102 | if (QUERY_FLAG(op, FLAG_REMOVED)) { |
1105 | LOG(llevDebug,"process_events: calling process_object with removed object %s\n", |
1103 | LOG(llevDebug,"process_events: calling process_object with removed object %s\n", |
1106 | op->name?op->name:"null"); |
1104 | op->name?op->name:"null"); |
1107 | } |
1105 | } |
1108 | #endif |
1106 | #endif |
1109 | --op->speed_left; |
1107 | --op->speed_left; |
1110 | process_object (op); |
1108 | process_object (op); |
1111 | if (was_destroyed (op, tag)) |
1109 | if (was_destroyed (op, tag)) |
1112 | continue; |
1110 | continue; |
1113 | } |
1111 | } |
1114 | if (settings.casting_time == TRUE && op->casting_time > 0) |
1112 | if (settings.casting_time == TRUE && op->casting_time > 0) |
1115 | op->casting_time--; |
1113 | op->casting_time--; |
1116 | if (op->speed_left <= 0) |
1114 | if (op->speed_left <= 0) |
1117 | op->speed_left += FABS (op->speed); |
1115 | op->speed_left += FABS (op->speed); |
1118 | } |
1116 | } |
1119 | |
1117 | |
1120 | /* Remove marker object from active list */ |
1118 | /* Remove marker object from active list */ |
1121 | if (marker.active_prev != NULL) |
1119 | if (marker.active_prev != NULL) |
1122 | marker.active_prev->active_next = NULL; |
1120 | marker.active_prev->active_next = NULL; |
1123 | else |
1121 | else |
1124 | active_objects = NULL; |
1122 | active_objects = NULL; |
1125 | |
1123 | |
1126 | process_players2 (map); |
1124 | process_players2 (map); |
1127 | } |
1125 | } |
1128 | |
1126 | |
1129 | void clean_tmp_files(void) { |
1127 | void clean_tmp_files(void) { |
… | |
… | |
1136 | * just make a special function that only saves the unique items. |
1134 | * just make a special function that only saves the unique items. |
1137 | */ |
1135 | */ |
1138 | for(m=first_map;m!=NULL;m=next) { |
1136 | for(m=first_map;m!=NULL;m=next) { |
1139 | next=m->next; |
1137 | next=m->next; |
1140 | if (m->in_memory == MAP_IN_MEMORY) { |
1138 | if (m->in_memory == MAP_IN_MEMORY) { |
1141 | /* If we want to reuse the temp maps, swap it out (note that will also |
1139 | /* If we want to reuse the temp maps, swap it out (note that will also |
1142 | * update the log file. Otherwise, save the map (mostly for unique item |
1140 | * update the log file. Otherwise, save the map (mostly for unique item |
1143 | * stuff). Note that the clean_tmp_map is called after the end of |
1141 | * stuff). Note that the clean_tmp_map is called after the end of |
1144 | * the for loop but is in the #else bracket. IF we are recycling the maps, |
1142 | * the for loop but is in the #else bracket. IF we are recycling the maps, |
1145 | * we certainly don't want the temp maps removed. |
1143 | * we certainly don't want the temp maps removed. |
1146 | */ |
1144 | */ |
1147 | |
1145 | |
1148 | /* XXX The above comment is dead wrong */ |
1146 | /* XXX The above comment is dead wrong */ |
1149 | if (settings.recycle_tmp_maps == TRUE) |
1147 | if (settings.recycle_tmp_maps == TRUE) |
1150 | swap_map(m); |
1148 | swap_map(m); |
1151 | else { |
1149 | else { |
1152 | new_save_map(m, 0); /* note we save here into a overlay map */ |
1150 | new_save_map(m, 0); /* note we save here into a overlay map */ |
1153 | clean_tmp_map(m); |
1151 | clean_tmp_map(m); |
1154 | } |
1152 | } |
1155 | } |
1153 | } |
1156 | } |
1154 | } |
1157 | write_todclock(); /* lets just write the clock here */ |
1155 | write_todclock(); /* lets just write the clock here */ |
1158 | } |
1156 | } |
1159 | |
1157 | |
… | |
… | |
1181 | exit(0); |
1179 | exit(0); |
1182 | } |
1180 | } |
1183 | |
1181 | |
1184 | void leave(player *pl, int draw_exit) { |
1182 | void leave(player *pl, int draw_exit) { |
1185 | if (pl != NULL) { |
1183 | if (pl != NULL) { |
1186 | /* We do this so that the socket handling routine can do the final |
1184 | /* We do this so that the socket handling routine can do the final |
1187 | * cleanup. We also leave that loop to actually handle the freeing |
1185 | * cleanup. We also leave that loop to actually handle the freeing |
1188 | * of the data. |
1186 | * of the data. |
1189 | */ |
1187 | */ |
1190 | if (pl->ob->type != DEAD_OBJECT) |
1188 | if (pl->ob->type != DEAD_OBJECT) |
1191 | { |
1189 | { |
1192 | execute_global_event (EVENT_LOGOUT, pl, pl->socket.host); |
|
|
1193 | LOG (llevInfo,"LOGOUT: Player named %s from ip %s\n", pl->ob->name, pl->socket.host); |
|
|
1194 | |
|
|
1195 | pl->socket.status = Ns_Dead; |
1190 | pl->socket.status = Ns_Dead; |
1196 | |
1191 | |
1197 | /* If a hidden dm dropped connection do not create |
1192 | /* If a hidden dm dropped connection do not create |
1198 | * inconsistencies by showing that they have left the game |
1193 | * inconsistencies by showing that they have left the game |
1199 | */ |
1194 | */ |
1200 | if (!(QUERY_FLAG(pl->ob,FLAG_WIZ) && pl->ob->contr->hidden) |
1195 | if (!(QUERY_FLAG(pl->ob,FLAG_WIZ) && pl->ob->contr->hidden) |
1201 | && draw_exit |
1196 | && draw_exit |
1202 | && (pl->state != ST_GET_NAME && pl->state!=ST_GET_PASSWORD && pl->state != ST_CONFIRM_PASSWORD)) |
1197 | && (pl->state != ST_GET_NAME && pl->state!=ST_GET_PASSWORD && pl->state != ST_CONFIRM_PASSWORD)) |
1203 | { |
1198 | { |
|
|
1199 | if (pl->ob->map) |
|
|
1200 | { |
|
|
1201 | INVOKE_PLAYER (LOGOUT, pl); |
|
|
1202 | LOG (llevInfo,"LOGOUT: Player named %s from ip %s\n", &pl->ob->name, pl->socket.host); |
|
|
1203 | } |
|
|
1204 | |
1204 | char buf[MAX_BUF]; |
1205 | char buf[MAX_BUF]; |
1205 | sprintf (buf, "%s left the game.", pl->ob->name); |
1206 | sprintf (buf, "%s left the game.", &pl->ob->name); |
1206 | new_draw_info(NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, NULL, buf); |
1207 | new_draw_info(NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, NULL, buf); |
1207 | } |
1208 | } |
1208 | |
1209 | |
1209 | if (!QUERY_FLAG (pl->ob, FLAG_REMOVED)) |
1210 | if (!QUERY_FLAG (pl->ob, FLAG_REMOVED)) |
1210 | leave_map (pl->ob); |
1211 | leave_map (pl->ob); |
… | |
… | |
1226 | clock = time (NULL); |
1227 | clock = time (NULL); |
1227 | tm = (struct tm *) localtime (&clock); |
1228 | tm = (struct tm *) localtime (&clock); |
1228 | |
1229 | |
1229 | sprintf (buf, "%s/%s", settings.confdir, PERM_FILE); |
1230 | sprintf (buf, "%s/%s", settings.confdir, PERM_FILE); |
1230 | if ((fp = open_and_uncompress(buf, 0, &comp)) == NULL) |
1231 | if ((fp = open_and_uncompress(buf, 0, &comp)) == NULL) |
1231 | return 0; |
1232 | return 0; |
1232 | |
1233 | |
1233 | while (fgets (buf, MAX_BUF, fp)) { |
1234 | while (fgets (buf, MAX_BUF, fp)) { |
1234 | if (buf[0]=='#') continue; |
1235 | if (buf[0]=='#') continue; |
1235 | if (!strncmp (buf, "msg", 3)) { |
1236 | if (!strncmp (buf, "msg", 3)) { |
1236 | if (forbit) |
1237 | if (forbit) |
1237 | while (fgets (buf, MAX_BUF, fp)) /* print message */ |
1238 | while (fgets (buf, MAX_BUF, fp)) /* print message */ |
1238 | fputs (buf, logfile); |
1239 | fputs (buf, logfile); |
1239 | break; |
1240 | break; |
1240 | |
1241 | |
1241 | } else if (sscanf (buf, "%s %d%*c%d\n", day, &start, &stop) != 3) { |
1242 | } else if (sscanf (buf, "%s %d%*c%d\n", day, &start, &stop) != 3) { |
1242 | LOG(llevDebug, "Warning: Incomplete line in permission file ignored.\n"); |
1243 | LOG(llevDebug, "Warning: Incomplete line in permission file ignored.\n"); |
1243 | continue; |
1244 | continue; |
1244 | } |
1245 | } |
1245 | |
1246 | |
1246 | for (i=0; i< 7; i++) { |
1247 | for (i=0; i< 7; i++) { |
1247 | if (!strncmp (buf, days[i], 3) && (tm->tm_wday == i) && |
1248 | if (!strncmp (buf, days[i], 3) && (tm->tm_wday == i) && |
1248 | (tm->tm_hour >= start) && (tm->tm_hour < stop)) |
1249 | (tm->tm_hour >= start) && (tm->tm_hour < stop)) |
1249 | forbit = 1; |
1250 | forbit = 1; |
1250 | } |
1251 | } |
1251 | } |
1252 | } |
1252 | |
1253 | |
1253 | close_and_delete(fp, comp); |
1254 | close_and_delete(fp, comp); |
1254 | |
1255 | |
1255 | return forbit; |
1256 | return forbit; |
… | |
… | |
1276 | |
1277 | |
1277 | void do_specials(void) { |
1278 | void do_specials(void) { |
1278 | |
1279 | |
1279 | #ifdef WATCHDOG |
1280 | #ifdef WATCHDOG |
1280 | if (!(pticks % 503)) |
1281 | if (!(pticks % 503)) |
1281 | watchdog(); |
1282 | watchdog(); |
1282 | #endif |
1283 | #endif |
1283 | |
1284 | |
1284 | if (!(pticks % PTICKS_PER_CLOCK)) |
1285 | if (!(pticks % PTICKS_PER_CLOCK)) |
1285 | tick_the_clock(); |
1286 | tick_the_clock(); |
1286 | |
1287 | |
1287 | if (!(pticks % 509)) |
1288 | if (!(pticks % 79)) |
1288 | flush_old_maps(); /* Clears the tmp-files of maps which have reset */ |
1289 | flush_old_maps(); /* Clears the tmp-files of maps which have reset */ |
1289 | |
1290 | |
1290 | if (!(pticks % 2503)) |
1291 | if (!(pticks % 2503)) |
1291 | fix_weight(); /* Hack to fix weightproblems caused by bugs */ |
1292 | fix_weight(); /* Hack to fix weightproblems caused by bugs */ |
1292 | |
1293 | |
1293 | if (!(pticks % 2521)) |
1294 | if (!(pticks % 2521)) |
1294 | metaserver_update(); /* 2500 ticks is about 5 minutes */ |
1295 | metaserver_update(); /* 2500 ticks is about 5 minutes */ |
1295 | |
1296 | |
1296 | if (!(pticks % 5003)) |
1297 | if (!(pticks % 5003)) |
1297 | write_book_archive(); |
1298 | write_book_archive(); |
1298 | |
1299 | |
1299 | if (!(pticks % 5009)) |
1300 | if (!(pticks % 5009)) |
1300 | clean_friendly_list(); |
1301 | clean_friendly_list(); |
1301 | |
1302 | |
1302 | if (!(pticks % 5011)) |
1303 | if (!(pticks % 5011)) |
1303 | obsolete_parties(); |
1304 | obsolete_parties(); |
1304 | |
1305 | |
1305 | if (!(pticks % 12503)) |
1306 | if (!(pticks % 12503)) |
1306 | fix_luck(); |
1307 | fix_luck(); |
1307 | } |
1308 | } |
1308 | |
1309 | |
1309 | void server_tick () |
1310 | void server_tick () |
1310 | { |
1311 | { |
1311 | nroferrors = 0; |
1312 | nroferrors = 0; |
1312 | |
1313 | |
1313 | doeric_server(); |
1314 | doeric_server(); |
|
|
1315 | INVOKE_GLOBAL (CLOCK); |
1314 | process_events(NULL); /* "do" something with objects with speed */ |
1316 | process_events(NULL); /* "do" something with objects with speed */ |
1315 | cftimer_process_timers();/* Process the crossfire Timers */ |
|
|
1316 | /* Lauwenmark : Here we handle the CLOCK global event */ |
|
|
1317 | execute_global_event(EVENT_CLOCK); |
|
|
1318 | flush_sockets(); |
1317 | flush_sockets(); |
1319 | check_active_maps(); /* Removes unused maps after a certain timeout */ |
1318 | check_active_maps(); /* Removes unused maps after a certain timeout */ |
1320 | do_specials(); /* Routines called from time to time. */ |
1319 | do_specials(); /* Routines called from time to time. */ |
|
|
1320 | |
|
|
1321 | ++pticks; |
1321 | } |
1322 | } |
1322 | |
1323 | |
1323 | int main(int argc, char **argv) |
1324 | int main(int argc, char **argv) |
1324 | { |
1325 | { |
1325 | #ifdef WIN32 /* ---win32 this sets the win32 from 0d0a to 0a handling */ |
1326 | undead_name = "undead"; // what weird misoptimisation is this again? |
1326 | _fmode = _O_BINARY ; |
|
|
1327 | bRunning = 1; |
|
|
1328 | #endif |
|
|
1329 | |
1327 | |
1330 | #ifdef DEBUG_MALLOC_LEVEL |
|
|
1331 | malloc_debug(DEBUG_MALLOC_LEVEL); |
|
|
1332 | #endif |
|
|
1333 | |
|
|
1334 | settings.argc=argc; |
1328 | settings.argc = argc; |
1335 | settings.argv=argv; |
1329 | settings.argv = argv; |
|
|
1330 | |
|
|
1331 | cfperl_init (); |
|
|
1332 | |
1336 | init(argc, argv); |
1333 | init (argc, argv); |
1337 | initPlugins(); /* GROS - Init the Plugins */ |
|
|
1338 | |
1334 | |
|
|
1335 | cfperl_boot (); |
|
|
1336 | initPlugins (); |
|
|
1337 | |
|
|
1338 | for (;;) |
1339 | cfperl_main (); |
1339 | cfperl_main (); |
1340 | |
1340 | |
|
|
1341 | // unreached |
1341 | emergency_save( 0 ); |
1342 | emergency_save (0); |
1342 | cleanup( ); |
1343 | cleanup (); |
|
|
1344 | |
1343 | return 0; |
1345 | return 0; |
1344 | } |
1346 | } |