1 | /* |
1 | /* |
2 | * static char *rcsid_build_map = |
2 | * static char *rcsid_build_map = |
3 | * "$Id: build_map.C,v 1.1 2006/08/13 17:16:03 elmex Exp $"; |
3 | * "$Id: build_map.C,v 1.2 2006/08/29 08:01:37 root Exp $"; |
4 | */ |
4 | */ |
5 | /* |
5 | /* |
6 | CrossFire, A Multiplayer game for X-windows |
6 | CrossFire, A Multiplayer game for X-windows |
7 | |
7 | |
8 | Copyright (C) 2001 Mark Wedel & Crossfire Development Team |
8 | Copyright (C) 2001 Mark Wedel & Crossfire Development Team |
… | |
… | |
40 | object* ob; |
40 | object* ob; |
41 | |
41 | |
42 | ob = GET_MAP_OB( map, x, y ); |
42 | ob = GET_MAP_OB( map, x, y ); |
43 | while ( ob ) |
43 | while ( ob ) |
44 | { |
44 | { |
45 | /* if ob is not a marking rune or floor, then check special cases */ |
45 | /* if ob is not a marking rune or floor, then check special cases */ |
46 | if ( strcmp( ob->arch->name, "rune_mark" ) && ob->type != FLOOR ) |
46 | if ( strcmp( ob->arch->name, "rune_mark" ) && ob->type != FLOOR ) |
47 | { |
47 | { |
48 | switch ( tmp->type ) |
48 | switch ( tmp->type ) |
49 | { |
49 | { |
50 | case SIGN: |
50 | case SIGN: |
51 | case MAGIC_EAR: |
51 | case MAGIC_EAR: |
52 | /* Allow signs and magic ears to be built on books */ |
52 | /* Allow signs and magic ears to be built on books */ |
53 | if ( ob->type != BOOK ) { |
53 | if ( ob->type != BOOK ) { |
54 | return 0; } |
54 | return 0; } |
55 | break; |
55 | break; |
56 | case BUTTON: |
56 | case BUTTON: |
57 | case DETECTOR: |
57 | case DETECTOR: |
58 | case PEDESTAL: |
58 | case PEDESTAL: |
59 | case CF_HANDLE: |
59 | case CF_HANDLE: |
60 | /* Allow buttons and levers to be built under gates */ |
60 | /* Allow buttons and levers to be built under gates */ |
61 | if ( ob->type != GATE && ob->type != DOOR ) { |
61 | if ( ob->type != GATE && ob->type != DOOR ) { |
62 | return 0; } |
62 | return 0; } |
63 | break; |
63 | break; |
64 | default: |
64 | default: |
65 | return 0; |
65 | return 0; |
66 | } |
66 | } |
67 | } |
67 | } |
68 | ob = ob->above; |
68 | ob = ob->above; |
69 | } |
69 | } |
70 | return 1; |
70 | return 1; |
71 | } |
71 | } |
72 | |
72 | |
73 | /** |
73 | /** |
74 | * Erases marking runes at specified location |
74 | * Erases marking runes at specified location |
… | |
… | |
398 | /* Now insert our floor */ |
398 | /* Now insert our floor */ |
399 | new_floor = find_archetype( material->slaying ); |
399 | new_floor = find_archetype( material->slaying ); |
400 | if ( !new_floor ) |
400 | if ( !new_floor ) |
401 | { |
401 | { |
402 | /* Not found, log & bail out */ |
402 | /* Not found, log & bail out */ |
403 | LOG( llevError, "apply_builder_floor: unable to find archetype %s.\n", material->slaying ); |
403 | LOG( llevError, "apply_builder_floor: unable to find archetype %s.\n", material->slaying ); |
404 | return; |
404 | return; |
405 | } |
405 | } |
406 | |
406 | |
407 | tmp = arch_to_object( new_floor ); |
407 | tmp = arch_to_object( new_floor ); |
408 | SET_FLAG( tmp, FLAG_IS_BUILDABLE ); |
408 | SET_FLAG( tmp, FLAG_IS_BUILDABLE ); |
409 | SET_FLAG( tmp, FLAG_UNIQUE ); |
409 | SET_FLAG( tmp, FLAG_UNIQUE ); |
410 | SET_FLAG( tmp, FLAG_IS_FLOOR ); |
410 | SET_FLAG( tmp, FLAG_IS_FLOOR ); |
411 | tmp->type = FLOOR; |
411 | tmp->type = FLOOR; |
412 | insert_ob_in_map_at( tmp, pl->map, above_floor, above_floor ? INS_BELOW_ORIGINATOR : INS_ON_TOP, x, y ); |
412 | insert_ob_in_map_at( tmp, pl->map, above_floor, above_floor ? INS_BELOW_ORIGINATOR : INS_ON_TOP, x, y ); |
413 | |
413 | |
414 | /* |
414 | /* |
415 | * Next step: make sure there are either walls or floors around the new square |
415 | * Next step: make sure there are either walls or floors around the new square |
… | |
… | |
491 | |
491 | |
492 | /* Now we can actually insert the wall */ |
492 | /* Now we can actually insert the wall */ |
493 | new_wall = find_archetype( material->slaying ); |
493 | new_wall = find_archetype( material->slaying ); |
494 | if ( !new_wall ) |
494 | if ( !new_wall ) |
495 | { |
495 | { |
496 | LOG( llevError, "apply_builder_wall: unable to find archetype %s\n", material->slaying ); |
496 | LOG( llevError, "apply_builder_wall: unable to find archetype %s\n", material->slaying ); |
497 | return; |
497 | return; |
498 | } |
498 | } |
499 | |
499 | |
500 | tmp = arch_to_object( new_wall ); |
500 | tmp = arch_to_object( new_wall ); |
501 | tmp->type = WALL; |
501 | tmp->type = WALL; |
… | |
… | |
594 | case BUTTON: |
594 | case BUTTON: |
595 | case DETECTOR: |
595 | case DETECTOR: |
596 | case TIMED_GATE: |
596 | case TIMED_GATE: |
597 | case PEDESTAL: |
597 | case PEDESTAL: |
598 | case CF_HANDLE: |
598 | case CF_HANDLE: |
599 | case MAGIC_EAR: |
599 | case MAGIC_EAR: |
600 | case SIGN: |
600 | case SIGN: |
601 | /* Signs don't need a connection, but but magic mouths do. */ |
601 | /* Signs don't need a connection, but but magic mouths do. */ |
602 | if (tmp->type == SIGN && strcmp( tmp->arch->name, "magic_mouth" )) |
602 | if (tmp->type == SIGN && strcmp( tmp->arch->name, "magic_mouth" )) |
603 | break; |
603 | break; |
604 | con_rune = get_connection_rune( pl, x, y ); |
604 | con_rune = get_connection_rune( pl, x, y ); |
605 | connected = find_or_create_connection_for_map( pl, x, y, con_rune ); |
605 | connected = find_or_create_connection_for_map( pl, x, y, con_rune ); |
606 | if ( connected == -1 ) |
606 | if ( connected == -1 ) |
607 | { |
607 | { |
608 | /* Player already informed of failure by the previous function */ |
608 | /* Player already informed of failure by the previous function */ |
609 | free_object( tmp ); |
609 | free_object( tmp ); |
610 | return; |
610 | return; |
611 | } |
611 | } |
612 | /* Remove marking rune */ |
612 | /* Remove marking rune */ |
613 | remove_ob( con_rune ); |
613 | remove_ob( con_rune ); |
614 | free_object( con_rune ); |
614 | free_object( con_rune ); |
615 | } |
615 | } |
616 | |
616 | |
617 | /* For magic mouths/ears, and signs, take the msg from a book of scroll */ |
617 | /* For magic mouths/ears, and signs, take the msg from a book of scroll */ |
618 | if ((tmp->type == SIGN) || (tmp->type == MAGIC_EAR)) |
618 | if ((tmp->type == SIGN) || (tmp->type == MAGIC_EAR)) |
619 | { |
619 | { |
620 | if (adjust_sign_msg( pl, x, y, tmp ) == -1) |
620 | if (adjust_sign_msg( pl, x, y, tmp ) == -1) |
621 | { |
621 | { |
622 | free_object( tmp ); |
622 | free_object( tmp ); |
623 | return; |
623 | return; |
624 | } |
624 | } |
625 | } |
625 | } |
626 | |
626 | |
627 | insert_ob_in_map_at( tmp, pl->map, floor, insert_flag, x, y ); |
627 | insert_ob_in_map_at( tmp, pl->map, floor, insert_flag, x, y ); |
628 | if ( connected != 0 ) |
628 | if ( connected != 0 ) |
629 | add_button_link( tmp, pl->map, connected ); |
629 | add_button_link( tmp, pl->map, connected ); |
630 | |
630 | |
… | |
… | |
649 | item = GET_MAP_OB( pl->map, x, y ); |
649 | item = GET_MAP_OB( pl->map, x, y ); |
650 | if ( !item ) |
650 | if ( !item ) |
651 | { |
651 | { |
652 | /* Should not happen with previous tests, but we never know */ |
652 | /* Should not happen with previous tests, but we never know */ |
653 | new_draw_info( NDI_UNIQUE, 0, pl, "Invalid square." ); |
653 | new_draw_info( NDI_UNIQUE, 0, pl, "Invalid square." ); |
654 | LOG( llevError, "apply_builder_remove: (null) square at (%d, %d, %s)\n", x, y, pl->map->path ); |
654 | LOG( llevError, "apply_builder_remove: (null) square at (%d, %d, %s)\n", x, y, pl->map->path ); |
655 | return; |
655 | return; |
656 | } |
656 | } |
657 | |
657 | |
658 | if ( item->type == FLOOR || QUERY_FLAG(item,FLAG_IS_FLOOR) ) |
658 | if ( item->type == FLOOR || QUERY_FLAG(item,FLAG_IS_FLOOR) ) |
659 | item = item->above; |
659 | item = item->above; |
… | |
… | |
679 | case PEDESTAL: |
679 | case PEDESTAL: |
680 | case CF_HANDLE: |
680 | case CF_HANDLE: |
681 | case MAGIC_EAR: |
681 | case MAGIC_EAR: |
682 | case SIGN: |
682 | case SIGN: |
683 | /* Special case: must unconnect */ |
683 | /* Special case: must unconnect */ |
684 | if (QUERY_FLAG(item,FLAG_IS_LINKED)) |
684 | if (QUERY_FLAG(item,FLAG_IS_LINKED)) |
685 | remove_button_link( item ); |
685 | remove_button_link( item ); |
686 | |
686 | |
687 | /* Fall through */ |
687 | /* Fall through */ |
688 | |
688 | |
689 | default: |
689 | default: |
… | |
… | |
710 | if ( !pl->type == PLAYER ) |
710 | if ( !pl->type == PLAYER ) |
711 | return; |
711 | return; |
712 | |
712 | |
713 | /*if ( !player->map->unique ) |
713 | /*if ( !player->map->unique ) |
714 | { |
714 | { |
715 | new_draw_info( NDI_UNIQUE, 0, player, "You can't build outside a unique map." ); |
715 | new_draw_info( NDI_UNIQUE, 0, player, "You can't build outside a unique map." ); |
716 | return; |
716 | return; |
717 | }*/ |
717 | }*/ |
718 | |
718 | |
719 | if ( dir == 0 ) |
719 | if ( dir == 0 ) |
720 | { |
720 | { |
721 | new_draw_info( NDI_UNIQUE, 0, pl, "You can't build or destroy under yourself." ); |
721 | new_draw_info( NDI_UNIQUE, 0, pl, "You can't build or destroy under yourself." ); |
722 | return; |
722 | return; |
723 | } |
723 | } |
724 | |
724 | |
725 | x = pl->x + freearr_x[ dir ]; |
725 | x = pl->x + freearr_x[ dir ]; |
726 | y = pl->y + freearr_y[ dir ]; |
726 | y = pl->y + freearr_y[ dir ]; |
727 | |
727 | |
… | |
… | |
740 | |
740 | |
741 | tmp = GET_MAP_OB( pl->map, x, y ); |
741 | tmp = GET_MAP_OB( pl->map, x, y ); |
742 | if ( !tmp ) |
742 | if ( !tmp ) |
743 | { |
743 | { |
744 | /* Nothing, meaning player is standing next to an undefined square... */ |
744 | /* Nothing, meaning player is standing next to an undefined square... */ |
745 | LOG( llevError, "apply_map_builder: undefined square at (%d, %d, %s)\n", x, y, pl->map->path ); |
745 | LOG( llevError, "apply_map_builder: undefined square at (%d, %d, %s)\n", x, y, pl->map->path ); |
746 | new_draw_info( NDI_UNIQUE, 0, pl, "You'd better not build here, it looks weird." ); |
746 | new_draw_info( NDI_UNIQUE, 0, pl, "You'd better not build here, it looks weird." ); |
747 | return; |
747 | return; |
748 | } |
748 | } |
749 | tmp2 = find_marked_object( pl ); |
749 | tmp2 = find_marked_object( pl ); |
750 | while ( tmp ) |
750 | while ( tmp ) |
751 | { |
751 | { |
752 | if ( !QUERY_FLAG( tmp, FLAG_IS_BUILDABLE ) && ( ( tmp->type != SIGN ) |
752 | if ( !QUERY_FLAG( tmp, FLAG_IS_BUILDABLE ) && ( ( tmp->type != SIGN ) |
753 | || ( strcmp( tmp->arch->name, "rune_mark" ) ) ) ) |
753 | || ( strcmp( tmp->arch->name, "rune_mark" ) ) ) ) |
754 | { |
754 | { |
755 | /* The item building function already has it's own special |
755 | /* The item building function already has it's own special |
756 | * checks for this |
756 | * checks for this |
757 | */ |
757 | */ |
758 | if ((!tmp2) || (tmp2->subtype != ST_MAT_ITEM )) |
758 | if ((!tmp2) || (tmp2->subtype != ST_MAT_ITEM )) |
759 | { |
759 | { |
760 | new_draw_info( NDI_UNIQUE, 0, pl, "You can't build here." ); |
760 | new_draw_info( NDI_UNIQUE, 0, pl, "You can't build here." ); |
761 | return; |
761 | return; |
762 | } |
762 | } |
763 | } |
763 | } |
764 | tmp = tmp->above; |
764 | tmp = tmp->above; |
765 | } |
765 | } |
766 | |
766 | |
767 | /* Now we know the square is ok */ |
767 | /* Now we know the square is ok */ |
… | |
… | |
781 | */ |
781 | */ |
782 | { |
782 | { |
783 | tmp = tmp2; |
783 | tmp = tmp2; |
784 | if ( !tmp ) |
784 | if ( !tmp ) |
785 | { |
785 | { |
786 | new_draw_info( NDI_UNIQUE, 0, pl, "You need to mark raw materials to use." ); |
786 | new_draw_info( NDI_UNIQUE, 0, pl, "You need to mark raw materials to use." ); |
787 | return; |
787 | return; |
788 | } |
788 | } |
789 | |
789 | |
790 | if ( tmp->type != MATERIAL ) |
790 | if ( tmp->type != MATERIAL ) |
791 | { |
791 | { |
792 | new_draw_info( NDI_UNIQUE, 0, pl, "You can't use the marked item to build." ); |
792 | new_draw_info( NDI_UNIQUE, 0, pl, "You can't use the marked item to build." ); |
793 | return; |
793 | return; |
|
|
794 | } |
794 | } |
795 | |
795 | |
|
|
796 | switch( tmp->subtype ) |
796 | switch( tmp->subtype ) |
797 | { |
797 | { |
798 | case ST_MAT_FLOOR: |
798 | case ST_MAT_FLOOR: |
799 | apply_builder_floor( pl, tmp, x, y ); |
799 | apply_builder_floor( pl, tmp, x, y ); |
800 | return; |
800 | return; |
… | |
… | |
807 | apply_builder_item( pl, tmp, x, y ); |
807 | apply_builder_item( pl, tmp, x, y ); |
808 | return; |
808 | return; |
809 | |
809 | |
810 | default: |
810 | default: |
811 | new_draw_info( NDI_UNIQUE, 0, pl, "Don't know how to apply this material, sorry." ); |
811 | new_draw_info( NDI_UNIQUE, 0, pl, "Don't know how to apply this material, sorry." ); |
812 | LOG( llevError, "apply_map_builder: invalid material subtype %d\n", tmp->subtype ); |
812 | LOG( llevError, "apply_map_builder: invalid material subtype %d\n", tmp->subtype ); |
813 | return; |
813 | return; |
814 | } |
814 | } |
815 | } |
815 | } |
816 | |
816 | |
817 | /* Here, it means the builder has an invalid type */ |
817 | /* Here, it means the builder has an invalid type */ |
… | |
… | |
831 | char buf2[MAX_BUF]; |
831 | char buf2[MAX_BUF]; |
832 | |
832 | |
833 | book = get_msg_book( pl, x, y ); |
833 | book = get_msg_book( pl, x, y ); |
834 | if ( !book ) |
834 | if ( !book ) |
835 | { |
835 | { |
836 | new_draw_info( NDI_UNIQUE, 0, pl, "You need to put a book or scroll with the message." ); |
836 | new_draw_info( NDI_UNIQUE, 0, pl, "You need to put a book or scroll with the message." ); |
837 | return -1; |
837 | return -1; |
838 | } |
838 | } |
839 | |
839 | |
840 | tmp->msg = book->msg; |
840 | tmp->msg = book->msg; |
841 | add_refcount( tmp->msg ); |
841 | add_refcount( tmp->msg ); |
842 | |
842 | |
843 | if (tmp->invisible) |
843 | if (tmp->invisible) |
844 | { |
844 | { |
845 | if(book->custom_name != NULL) |
845 | if(book->custom_name != NULL) |
846 | { |
846 | { |
847 | snprintf(buf, sizeof(buf), "talking %s", book->custom_name); |
847 | snprintf(buf, sizeof(buf), "talking %s", book->custom_name); |
848 | } else { |
848 | } else { |
849 | snprintf(buf, sizeof(buf), "talking %s", book->name); |
849 | snprintf(buf, sizeof(buf), "talking %s", book->name); |
850 | } |
850 | } |
851 | if ( tmp->name ) |
851 | if ( tmp->name ) |
852 | free_string( tmp->name ); |
852 | free_string( tmp->name ); |
853 | tmp->name = add_string( buf ); |
853 | tmp->name = add_string( buf ); |
854 | |
854 | |
855 | if(book->name_pl != NULL) |
855 | if(book->name_pl != NULL) |
856 | { |
856 | { |
857 | snprintf(buf2, sizeof(buf2), "talking %s", book->name_pl); |
857 | snprintf(buf2, sizeof(buf2), "talking %s", book->name_pl); |
858 | if ( tmp->name_pl ) |
858 | if ( tmp->name_pl ) |
859 | free_string( tmp->name_pl ); |
859 | free_string( tmp->name_pl ); |
860 | tmp->name_pl = add_string( buf2 ); |
860 | tmp->name_pl = add_string( buf2 ); |
861 | } |
861 | } |
862 | |
862 | |
863 | tmp->face = book->face; |
863 | tmp->face = book->face; |
864 | tmp->invisible = 0; |
864 | tmp->invisible = 0; |
865 | } |
865 | } |
866 | remove_ob( book ); |
866 | remove_ob( book ); |
867 | free_object( book ); |
867 | free_object( book ); |
868 | return 0; |
868 | return 0; |
869 | } |
869 | } |