… | |
… | |
609 | * off |
609 | * off |
610 | */ |
610 | */ |
611 | if (!can_split (op, tmp, nrof)) |
611 | if (!can_split (op, tmp, nrof)) |
612 | return; |
612 | return; |
613 | |
613 | |
|
|
614 | drop_object (op, tmp); |
|
|
615 | |
|
|
616 | if (!tmp->destroyed () && !tmp->is_in_map_or_inv ()) |
|
|
617 | { |
|
|
618 | // if nothing happened with the object we give it back |
|
|
619 | op->insert (tmp); |
|
|
620 | } |
|
|
621 | } |
|
|
622 | |
|
|
623 | /* In contrast to drop_object (op, tmp, nrof) above this function takes the |
|
|
624 | * already split off object, and feeds it to the event handlers and does |
|
|
625 | * other magic with it. |
|
|
626 | * |
|
|
627 | * <droppper> is the object that dropped this object and <obj> is the |
|
|
628 | * object that was dropped. |
|
|
629 | * |
|
|
630 | * Make sure to check what happened with <obj> after this function returns! |
|
|
631 | * Otherwise you may leak this object. |
|
|
632 | */ |
|
|
633 | |
|
|
634 | void |
|
|
635 | drop_object (object *dropper, object *obj) |
|
|
636 | { |
614 | if (INVOKE_OBJECT (DROP, tmp, ARG_OBJECT (op))) |
637 | if (INVOKE_OBJECT (DROP, obj, ARG_OBJECT (dropper))) |
615 | return; |
638 | return; |
616 | |
639 | |
617 | if (QUERY_FLAG (tmp, FLAG_STARTEQUIP)) |
640 | // safe guard for programming errors: |
|
|
641 | if (obj->destroyed () || obj->is_in_map_or_inv ()) |
618 | { |
642 | { |
619 | op->statusmsg (format ("You drop the %s.", query_name (tmp))); |
643 | LOG (llevError, "BUG: A plugin destroyed or put the object somewhere without overriding the DROP event (%s)!", obj->debug_desc ()); |
620 | op->statusmsg ("The god who lent it to you retrieves it."); |
|
|
621 | |
|
|
622 | tmp->destroy (); |
|
|
623 | op->update_stats (); |
|
|
624 | return; |
644 | return; |
625 | } |
645 | } |
626 | |
646 | |
627 | /* Call this before we update the various windows/players. At least |
647 | if (QUERY_FLAG (obj, FLAG_STARTEQUIP)) |
628 | * that we, we know the weight is correct. |
648 | { |
|
|
649 | dropper->statusmsg (format ("You drop the %s.", query_name (obj))); |
|
|
650 | dropper->statusmsg ("The god who lent it to you retrieves it."); |
|
|
651 | |
|
|
652 | obj->destroy (); |
|
|
653 | dropper->update_stats (); |
|
|
654 | return; |
|
|
655 | } |
|
|
656 | |
|
|
657 | for (object *floor = GET_MAP_OB (dropper->map, dropper->x, dropper->y); |
|
|
658 | floor; |
|
|
659 | floor = floor->above) |
|
|
660 | if (INVOKE_OBJECT (DROP_ON, floor, ARG_OBJECT (obj), ARG_OBJECT (dropper))) |
|
|
661 | return; |
|
|
662 | |
|
|
663 | // safe guard for programming errors: |
|
|
664 | if (obj->destroyed () || obj->is_in_map_or_inv ()) |
|
|
665 | { |
|
|
666 | LOG (llevError, "BUG: A plugin destroyed or put the object somewhere without overriding the DROP_ON event (%s)!", obj->debug_desc ()); |
|
|
667 | return; |
|
|
668 | } |
|
|
669 | |
|
|
670 | if (is_in_shop (dropper) && !QUERY_FLAG (obj, FLAG_UNPAID) && obj->type != MONEY) |
|
|
671 | if (!sell_item (obj, dropper)) |
|
|
672 | return; |
|
|
673 | |
|
|
674 | /* If nothing special happened with this object, the default action is to |
|
|
675 | * insert it below the dropper: |
629 | */ |
676 | */ |
630 | // 2007-11-26: moved op->update_stats away and calling it later after |
|
|
631 | // all items of a drop command have been processed. |
|
|
632 | |
677 | |
633 | for (object *floor = GET_MAP_OB (op->map, op->x, op->y); floor; floor = floor->above) |
678 | obj->x = dropper->x; |
634 | if (INVOKE_OBJECT (DROP_ON, floor, ARG_OBJECT (tmp), ARG_OBJECT (op))) |
679 | obj->y = dropper->y; |
635 | return; |
|
|
636 | |
680 | |
637 | if (is_in_shop (op) && !QUERY_FLAG (tmp, FLAG_UNPAID) && tmp->type != MONEY) |
|
|
638 | { |
|
|
639 | if (!sell_item (tmp, op)) |
|
|
640 | { |
|
|
641 | // if we can't sell it we don't drop it, so give it back to the seller |
|
|
642 | op->insert (tmp); |
|
|
643 | return; |
|
|
644 | } |
|
|
645 | } |
|
|
646 | |
|
|
647 | tmp->x = op->x; |
|
|
648 | tmp->y = op->y; |
|
|
649 | |
|
|
650 | insert_ob_in_map (tmp, op->map, op, INS_BELOW_ORIGINATOR); |
681 | insert_ob_in_map (obj, dropper->map, dropper, INS_BELOW_ORIGINATOR); |
651 | } |
682 | } |
652 | |
683 | |
653 | void |
684 | void |
654 | drop (object *op, object *tmp) |
685 | drop (object *op, object *tmp) |
655 | { |
686 | { |
… | |
… | |
853 | |
884 | |
854 | /* draw_look(op);*/ |
885 | /* draw_look(op);*/ |
855 | return 0; |
886 | return 0; |
856 | } |
887 | } |
857 | |
888 | |
|
|
889 | |
|
|
890 | /* This function tries to drop all objects in the <objs> vector. |
|
|
891 | * <dropper> is the object that wants to drop them. |
|
|
892 | * <cnt> can be a 0 pointer or a pointer to the maximum number of |
|
|
893 | * drop operations to perform. |
|
|
894 | * |
|
|
895 | * Returns true if at least one item was dropped. |
|
|
896 | */ |
|
|
897 | bool |
|
|
898 | drop_vector (object *dropper, vector<object *> &objs, int *cnt) |
|
|
899 | { |
|
|
900 | vector<object *>::iterator i; |
|
|
901 | |
|
|
902 | bool did_one = false; |
|
|
903 | |
|
|
904 | for (i = objs.begin (); i != objs.end (); i++) |
|
|
905 | { |
|
|
906 | drop (dropper, *i); |
|
|
907 | if (cnt && --*cnt <= 0) break; |
|
|
908 | did_one = true; |
|
|
909 | } |
|
|
910 | |
|
|
911 | return did_one; |
|
|
912 | } |
|
|
913 | |
858 | /* Object op wants to drop object(s) params. params can be a |
914 | /* Object op wants to drop object(s) params. params can be a |
859 | * comma seperated list. |
915 | * comma seperated list. |
860 | */ |
916 | */ |
861 | int |
917 | int |
862 | command_drop (object *op, char *params) |
918 | command_drop (object *op, char *params) |
… | |
… | |
869 | new_draw_info (NDI_UNIQUE, 0, op, "Drop what?"); |
925 | new_draw_info (NDI_UNIQUE, 0, op, "Drop what?"); |
870 | return 0; |
926 | return 0; |
871 | } |
927 | } |
872 | else |
928 | else |
873 | { |
929 | { |
874 | int cnt = MAX_ITEM_PER_DROP; |
930 | vector<object *> matched_objs; |
875 | |
931 | |
876 | for (tmp = op->inv; tmp; tmp = next) |
932 | for (tmp = op->inv; tmp; tmp = next) |
877 | { |
933 | { |
878 | next = tmp->below; |
934 | next = tmp->below; |
879 | if (QUERY_FLAG (tmp, FLAG_NO_DROP) || tmp->invisible) |
935 | if (QUERY_FLAG (tmp, FLAG_NO_DROP) || tmp->invisible) |
880 | continue; |
936 | continue; |
881 | |
937 | |
882 | if (item_matched_string (op, tmp, params)) |
938 | if (item_matched_string (op, tmp, params)) |
883 | { |
939 | matched_objs.push_back (tmp); |
884 | drop (op, tmp); |
|
|
885 | if (--cnt <= 0) break; |
|
|
886 | did_one = 1; |
|
|
887 | } |
940 | } |
888 | } |
|
|
889 | |
941 | |
890 | if (!did_one) |
942 | int cnt = MAX_ITEM_PER_DROP; |
|
|
943 | |
|
|
944 | if (!drop_vector (op, matched_objs, &cnt)) |
891 | new_draw_info (NDI_UNIQUE, 0, op, "Nothing to drop."); |
945 | new_draw_info (NDI_UNIQUE, 0, op, "Nothing to drop."); |
892 | |
946 | |
893 | if (cnt <= 0) |
947 | if (cnt <= 0) |
894 | op->failmsg ("Only dropped some items, can't drop that many items at once."); |
948 | op->failmsg ("Only dropped some items, can't drop that many items at once."); |
895 | } |
949 | } |