… | |
… | |
676 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You remove the %s", query_name (item)); |
676 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You remove the %s", query_name (item)); |
677 | item->destroy (); |
677 | item->destroy (); |
678 | } |
678 | } |
679 | } |
679 | } |
680 | |
680 | |
|
|
681 | |
|
|
682 | static void |
|
|
683 | replace_open_space_floor (object *os, object *material) |
|
|
684 | { |
|
|
685 | object *new_floor = archetype::get (material->slaying); |
|
|
686 | insert_ob_in_map_at (new_floor, os->map, os, |
|
|
687 | INS_BELOW_ORIGINATOR, os->x, os->y); |
|
|
688 | os->destroy (); |
|
|
689 | material->decrease (); |
|
|
690 | } |
|
|
691 | |
|
|
692 | /** |
|
|
693 | * Quad building. |
|
|
694 | */ |
|
|
695 | void |
|
|
696 | apply_builder_quad (object *pl, object *material, mapxy &pos) |
|
|
697 | { |
|
|
698 | object *open_space = 0; |
|
|
699 | object *floor = 0; |
|
|
700 | |
|
|
701 | object *tmp = pos.ms ().bot; |
|
|
702 | bool floor_exists = false; |
|
|
703 | while (tmp) |
|
|
704 | { |
|
|
705 | if (floor_exists && tmp->flag [FLAG_IS_QUAD]) |
|
|
706 | { |
|
|
707 | pl->failmsg ( |
|
|
708 | "You can't build there, there is a block in the way."); |
|
|
709 | return; |
|
|
710 | } |
|
|
711 | |
|
|
712 | if (IS_FLOOR (tmp)) |
|
|
713 | { |
|
|
714 | floor = tmp; |
|
|
715 | floor_exists = true; |
|
|
716 | |
|
|
717 | if (floor->arch->archname == shstr_quad_open_space) |
|
|
718 | { |
|
|
719 | open_space = floor; |
|
|
720 | } |
|
|
721 | else if (!floor->flag [FLAG_IS_QUAD]) |
|
|
722 | { |
|
|
723 | pl->failmsg ( |
|
|
724 | "You can't build there, the floor is not suited."); |
|
|
725 | return; |
|
|
726 | } |
|
|
727 | } |
|
|
728 | |
|
|
729 | tmp = tmp->above; |
|
|
730 | } |
|
|
731 | |
|
|
732 | if (open_space) |
|
|
733 | { |
|
|
734 | if (!material->slaying) |
|
|
735 | { |
|
|
736 | pl->failmsg ( |
|
|
737 | "The floor is open and you can't fill it with that material." |
|
|
738 | "H<Use another material to fill the ceiling.>"); |
|
|
739 | return; |
|
|
740 | } |
|
|
741 | |
|
|
742 | replace_open_space_floor (open_space, material); |
|
|
743 | pl->contr->fire_on = 0; // TODO: stopgap, do not add more than one per keypress |
|
|
744 | return; |
|
|
745 | } |
|
|
746 | else if (floor) |
|
|
747 | { |
|
|
748 | |
|
|
749 | maptile *upper_floor = pos.m->tile_available (TILE_UP); |
|
|
750 | if (!upper_floor) |
|
|
751 | { |
|
|
752 | pl->failmsg ( |
|
|
753 | "Whoops, you can't see the ceiling.. H<You may try again.>"); |
|
|
754 | return; |
|
|
755 | } |
|
|
756 | |
|
|
757 | mapxy above_pos (upper_floor, pos.x, pos.y); |
|
|
758 | if (!above_pos.normalise ()) |
|
|
759 | { |
|
|
760 | pl->failmsg ( |
|
|
761 | "Whoops, you can't access the ceiling. H<You may try again.>"); |
|
|
762 | return; |
|
|
763 | } |
|
|
764 | |
|
|
765 | mapspace &above_ms = above_pos.ms (); |
|
|
766 | for (object *quad_obj = above_ms.top; quad_obj; quad_obj = quad_obj->below) |
|
|
767 | { |
|
|
768 | if (quad_obj->arch->archname == shstr_quad_open_space) |
|
|
769 | { |
|
|
770 | if (!material->slaying) |
|
|
771 | { |
|
|
772 | pl->failmsg ( |
|
|
773 | "The ceiling is open and you can't fill it with that material." |
|
|
774 | "H<Use another material to fill the ceiling.>"); |
|
|
775 | return; |
|
|
776 | } |
|
|
777 | |
|
|
778 | replace_open_space_floor (quad_obj, material); |
|
|
779 | break; |
|
|
780 | } |
|
|
781 | } |
|
|
782 | |
|
|
783 | if (material->destroyed ()) |
|
|
784 | { |
|
|
785 | pl->failmsg ( |
|
|
786 | "You don't have enough build material to build a wall here."); |
|
|
787 | return; |
|
|
788 | } |
|
|
789 | |
|
|
790 | object *quad_wall = material->other_arch->instance (); |
|
|
791 | material->decrease (); |
|
|
792 | |
|
|
793 | insert_ob_in_map_at (quad_wall, floor->map, 0, |
|
|
794 | INS_ABOVE_FLOOR_ONLY, floor->x, floor->y); |
|
|
795 | } |
|
|
796 | else |
|
|
797 | { |
|
|
798 | pl->failmsg ("You can't build a quad block here."); |
|
|
799 | } |
|
|
800 | } |
|
|
801 | |
681 | /** |
802 | /** |
682 | * Global building function |
803 | * Global building function |
683 | * |
804 | * |
684 | * This is the general map building function. Called when the player 'fires' a builder |
805 | * This is the general map building function. Called when the player 'fires' a builder |
685 | * or remover object. |
806 | * or remover object. |
686 | */ |
807 | */ |
687 | void |
808 | void |
688 | apply_map_builder (object *pl, int dir) |
809 | apply_map_builder (object *pl, int dir) |
689 | { |
810 | { |
690 | int x, y; |
|
|
691 | |
|
|
692 | if (!pl->type == PLAYER) |
811 | if (!pl->type == PLAYER) |
693 | return; |
812 | return; |
694 | |
813 | |
695 | /*if ( !player->map->unique ) |
|
|
696 | { |
|
|
697 | new_draw_info( NDI_UNIQUE, 0, player, "You can't build outside a unique map." ); |
|
|
698 | return; |
|
|
699 | } */ |
|
|
700 | |
|
|
701 | if (dir == 0) |
814 | if (dir == 0) |
702 | { |
815 | { |
703 | new_draw_info (NDI_UNIQUE, 0, pl, "You can't build or destroy under yourself."); |
816 | new_draw_info (NDI_UNIQUE, 0, pl, "You can't build or destroy under yourself."); |
704 | return; |
817 | return; |
705 | } |
818 | } |
706 | |
819 | |
707 | x = pl->x + freearr_x[dir]; |
820 | mapxy pos (pl); pos.move (dir); |
708 | y = pl->y + freearr_y[dir]; |
|
|
709 | |
821 | |
710 | if ((1 > x) || (1 > y) || ((pl->map->width - 2) < x) || ((pl->map->height - 2) < y)) |
822 | if (!pos.normalise ()) |
711 | { |
823 | { |
712 | new_draw_info (NDI_UNIQUE, 0, pl, "Can't build on map edge..."); |
824 | pl->failmsg ("You can't build here. H<There is nothing in this direction.>"); |
713 | return; |
825 | return; |
714 | } |
826 | } |
715 | |
827 | |
716 | /* |
828 | /* |
717 | * Check specified square |
829 | * Check specified square |
718 | * The square must have only buildable items |
830 | * The square must have only buildable items |
719 | * Exception: marking runes are all right, |
831 | * Exception: marking runes are all right, |
720 | * since they are used for special things like connecting doors / buttons |
832 | * since they are used for special things like connecting doors / buttons |
721 | */ |
833 | */ |
722 | |
834 | |
723 | object *tmp = GET_MAP_OB (pl->map, x, y); |
|
|
724 | if (!tmp) |
|
|
725 | { |
|
|
726 | /* Nothing, meaning player is standing next to an undefined square... */ |
|
|
727 | LOG (llevError, "apply_map_builder: undefined square at (%d, %d, %s)\n", x, y, &pl->map->path); |
|
|
728 | new_draw_info (NDI_UNIQUE, 0, pl, "You'd better not build here, it looks weird."); |
|
|
729 | return; |
|
|
730 | } |
|
|
731 | |
|
|
732 | object *builder = pl->contr->ranged_ob; |
835 | object *builder = pl->contr->ranged_ob; |
733 | |
836 | |
734 | object *tmp2 = pl->mark (); |
837 | object *tmp2 = pl->mark (); |
735 | |
838 | |
736 | while (tmp) |
839 | mapspace &ms = pos.ms (); |
|
|
840 | |
|
|
841 | object *tmp = 0; |
|
|
842 | for (tmp = pos.ms ().bot; tmp; tmp = tmp->above) |
737 | { |
843 | { |
|
|
844 | if (!tmp->flag [FLAG_IS_BUILDABLE] |
738 | if (!tmp->flag [FLAG_IS_BUILDABLE] && (tmp->type != SIGN || tmp->arch->archname != shstr_rune_mark)) |
845 | && (tmp->type != SIGN || tmp->arch->archname != shstr_rune_mark)) |
739 | { |
846 | { |
740 | /* The item building function already has it's own special |
847 | /* The item building function already has it's own special |
741 | * checks for this |
848 | * checks for this. And so does the quad building function. |
742 | */ |
849 | */ |
743 | if (!tmp2 || tmp2->subtype != ST_MAT_ITEM) |
850 | if (!tmp2 || (tmp2->subtype != ST_MAT_ITEM && tmp2->subtype != ST_MAT_QUAD)) |
744 | { |
851 | { |
745 | if (!INVOKE_PLAYER (BUILD, pl->contr, ARG_OBJECT (builder), ARG_MAP (pl->map), ARG_INT (x), ARG_INT (y), ARG_INT (0))) |
852 | if (!INVOKE_PLAYER (BUILD, pl->contr, ARG_OBJECT (builder), |
|
|
853 | ARG_MAP (pl->map), |
|
|
854 | ARG_INT (pos.y), ARG_INT (pos.y), |
|
|
855 | ARG_INT (0))) |
746 | new_draw_info (NDI_UNIQUE, 0, pl, "You can't build here."); |
856 | new_draw_info (NDI_UNIQUE, 0, pl, "You can't build here."); |
747 | |
857 | |
748 | return; |
858 | return; |
749 | } |
859 | } |
750 | } |
860 | } |
751 | |
|
|
752 | tmp = tmp->above; |
|
|
753 | } |
861 | } |
754 | |
862 | |
755 | /* Now we know the square is ok */ |
863 | /* Now we know the square is ok */ |
756 | if (INVOKE_PLAYER (BUILD, pl->contr, ARG_OBJECT (builder), ARG_MAP (pl->map), ARG_INT (x), ARG_INT (y), ARG_INT (1))) |
864 | if (INVOKE_PLAYER (BUILD, pl->contr, ARG_OBJECT (builder), |
|
|
865 | ARG_MAP (pl->map), ARG_INT (pos.x), ARG_INT (pos.y), ARG_INT (1))) |
757 | return; |
866 | return; |
758 | |
867 | |
759 | if (builder->subtype == ST_BD_REMOVE) |
868 | if (builder->subtype == ST_BD_REMOVE) |
760 | /* Remover -> call specific function and bail out */ |
869 | /* Remover -> call specific function and bail out */ |
761 | { |
870 | { |
… | |
… | |
783 | } |
892 | } |
784 | |
893 | |
785 | switch (tmp->subtype) |
894 | switch (tmp->subtype) |
786 | { |
895 | { |
787 | case ST_MAT_FLOOR: |
896 | case ST_MAT_FLOOR: |
788 | apply_builder_floor (pl, tmp, x, y); |
897 | apply_builder_floor (pl, tmp, pos.x, pos.y); |
789 | return; |
898 | return; |
790 | |
899 | |
791 | case ST_MAT_WALL: |
900 | case ST_MAT_WALL: |
792 | apply_builder_wall (pl, tmp, x, y); |
901 | apply_builder_wall (pl, tmp, pos.x, pos.y); |
793 | return; |
902 | return; |
794 | |
903 | |
795 | case ST_MAT_ITEM: |
904 | case ST_MAT_ITEM: |
796 | apply_builder_item (pl, tmp, x, y); |
905 | apply_builder_item (pl, tmp, pos.x, pos.y); |
|
|
906 | return; |
|
|
907 | |
|
|
908 | case ST_MAT_QUAD: |
|
|
909 | apply_builder_quad (pl, tmp, pos); |
797 | return; |
910 | return; |
798 | |
911 | |
799 | default: |
912 | default: |
800 | new_draw_info (NDI_UNIQUE, 0, pl, "Don't know how to apply this material, sorry."); |
913 | new_draw_info (NDI_UNIQUE, 0, pl, "Don't know how to apply this material, sorry."); |
801 | LOG (llevError, "apply_map_builder: invalid material subtype %d\n", tmp->subtype); |
914 | LOG (llevError, "apply_map_builder: invalid material subtype %d\n", tmp->subtype); |