1 | /* |
1 | /* |
2 | * static char *rcsid_main_c = |
2 | * static char *rcsid_main_c = |
3 | * "$Id: main.C,v 1.16 2006/08/30 16:47:10 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 | } |
… | |
… | |
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); |
… | |
… | |
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 | |
… | |
… | |
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 |
… | |
… | |
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 |
… | |
… | |
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 | } |
… | |
… | |
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); |
… | |
… | |
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); |
… | |
… | |
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 | |
… | |
… | |
755 | * 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. |
756 | */ |
757 | */ |
757 | if (exit_ob->msg) { |
758 | if (exit_ob->msg) { |
758 | enter_random_map(op, exit_ob); |
759 | enter_random_map(op, exit_ob); |
759 | } else { |
760 | } else { |
760 | 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); |
761 | return; |
762 | return; |
762 | } |
763 | } |
763 | |
764 | |
764 | /* 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 |
765 | * random maps use this or not. |
766 | * random maps use this or not. |
… | |
… | |
780 | newmap = ready_map_name(EXIT_PATH(exit_ob), 0); |
781 | newmap = ready_map_name(EXIT_PATH(exit_ob), 0); |
781 | } |
782 | } |
782 | if (!newmap) |
783 | if (!newmap) |
783 | { |
784 | { |
784 | if (exit_ob->name) |
785 | if (exit_ob->name) |
785 | 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); |
786 | /* 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 |
787 | * used by the savebed code and character creation */ |
788 | * used by the savebed code and character creation */ |
788 | return; |
789 | return; |
789 | } |
790 | } |
790 | |
791 | |
… | |
… | |
796 | */ |
797 | */ |
797 | if (x==0 && y==0) { |
798 | if (x==0 && y==0) { |
798 | x=MAP_ENTER_X(newmap); |
799 | x=MAP_ENTER_X(newmap); |
799 | y=MAP_ENTER_Y(newmap); |
800 | y=MAP_ENTER_Y(newmap); |
800 | 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", |
801 | exit_ob->name?exit_ob->name:"(none)", exit_ob->x, exit_ob->y, |
802 | &exit_ob->name, exit_ob->x, exit_ob->y, |
802 | exit_ob->map?exit_ob->map->path:"(none)"); |
803 | exit_ob->map ? exit_ob->map->path : "<nil>"); |
803 | } |
804 | } |
804 | |
805 | |
805 | /* 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 */ |
806 | if (QUERY_FLAG(exit_ob, FLAG_DAMNED)) { |
807 | if (QUERY_FLAG(exit_ob, FLAG_DAMNED)) { |
807 | /* remove an old force with a slaying field == PORTAL_DESTINATION_NAME */ |
808 | /* remove an old force with a slaying field == PORTAL_DESTINATION_NAME */ |
… | |
… | |
1053 | continue; |
1054 | continue; |
1054 | } |
1055 | } |
1055 | |
1056 | |
1056 | if ( ! op->speed) { |
1057 | if ( ! op->speed) { |
1057 | LOG (llevError, "BUG: process_events(): Object %s has no speed, " |
1058 | LOG (llevError, "BUG: process_events(): Object %s has no speed, " |
1058 | "but is on active list\n", op->arch->name); |
1059 | "but is on active list\n", &op->arch->name); |
1059 | update_ob_speed (op); |
1060 | update_ob_speed (op); |
1060 | continue; |
1061 | continue; |
1061 | } |
1062 | } |
1062 | |
1063 | |
1063 | if (op->map == NULL && op->env == NULL && op->name && |
1064 | if (op->map == NULL && op->env == NULL && op->name && |
1064 | op->type != MAP && map == NULL) { |
1065 | op->type != MAP && map == NULL) { |
1065 | LOG (llevError, "BUG: process_events(): Object without map or " |
1066 | LOG (llevError, "BUG: process_events(): Object without map or " |
1066 | "inventory is on active list: %s (%d)\n", |
1067 | "inventory is on active list: %s (%d)\n", |
1067 | op->name, op->count); |
1068 | &op->name, op->count); |
1068 | op->speed = 0; |
1069 | op->speed = 0; |
1069 | update_ob_speed (op); |
1070 | update_ob_speed (op); |
1070 | continue; |
1071 | continue; |
1071 | } |
1072 | } |
1072 | |
1073 | |
… | |
… | |
1196 | && (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)) |
1197 | { |
1198 | { |
1198 | if (pl->ob->map) |
1199 | if (pl->ob->map) |
1199 | { |
1200 | { |
1200 | INVOKE_PLAYER (LOGOUT, pl); |
1201 | INVOKE_PLAYER (LOGOUT, pl); |
1201 | LOG (llevInfo,"LOGOUT: Player named %s from ip %s\n", pl->ob->name, pl->socket.host); |
1202 | LOG (llevInfo,"LOGOUT: Player named %s from ip %s\n", &pl->ob->name, pl->socket.host); |
1202 | } |
1203 | } |
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); |
… | |
… | |
1320 | ++pticks; |
1321 | ++pticks; |
1321 | } |
1322 | } |
1322 | |
1323 | |
1323 | int main(int argc, char **argv) |
1324 | int main(int argc, char **argv) |
1324 | { |
1325 | { |
|
|
1326 | undead_name = "undead"; // what weird misoptimisation is this again? |
|
|
1327 | |
1325 | settings.argc = argc; |
1328 | settings.argc = argc; |
1326 | settings.argv = argv; |
1329 | settings.argv = argv; |
1327 | |
1330 | |
1328 | cfperl_init (); |
1331 | cfperl_init (); |
1329 | |
1332 | |