… | |
… | |
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_inserted ()) |
|
|
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; |
|
|
639 | |
|
|
640 | if (obj->destroyed () || obj->is_inserted ()) |
|
|
641 | return; |
616 | |
642 | |
617 | if (QUERY_FLAG (tmp, FLAG_STARTEQUIP)) |
643 | if (QUERY_FLAG (obj, FLAG_STARTEQUIP)) |
618 | { |
644 | { |
619 | op->statusmsg (format ("You drop the %s.", query_name (tmp))); |
645 | dropper->statusmsg (format ("You drop the %s.", query_name (obj))); |
620 | op->statusmsg ("The god who lent it to you retrieves it."); |
646 | dropper->statusmsg ("The god who lent it to you retrieves it."); |
621 | |
647 | |
622 | tmp->destroy (); |
648 | obj->destroy (); |
623 | op->update_stats (); |
649 | dropper->update_stats (); |
624 | return; |
650 | return; |
625 | } |
651 | } |
626 | |
652 | |
627 | /* Call this before we update the various windows/players. At least |
653 | for (object *floor = GET_MAP_OB (dropper->map, dropper->x, dropper->y); |
628 | * that we, we know the weight is correct. |
654 | floor; |
|
|
655 | floor = floor->above) |
|
|
656 | if (INVOKE_OBJECT (DROP_ON, floor, ARG_OBJECT (obj), ARG_OBJECT (dropper))) |
|
|
657 | return; |
|
|
658 | |
|
|
659 | if (obj->destroyed () || obj->is_inserted ()) |
|
|
660 | return; |
|
|
661 | |
|
|
662 | if (is_in_shop (dropper) && !QUERY_FLAG (obj, FLAG_UNPAID) && obj->type != MONEY) |
|
|
663 | if (!sell_item (obj, dropper)) |
|
|
664 | return; |
|
|
665 | |
|
|
666 | /* If nothing special happened with this object, the default action is to |
|
|
667 | * insert it below the dropper: |
629 | */ |
668 | */ |
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 | |
669 | |
633 | for (object *floor = GET_MAP_OB (op->map, op->x, op->y); floor; floor = floor->above) |
670 | obj->x = dropper->x; |
634 | if (INVOKE_OBJECT (DROP_ON, floor, ARG_OBJECT (tmp), ARG_OBJECT (op))) |
671 | obj->y = dropper->y; |
635 | return; |
|
|
636 | |
672 | |
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); |
673 | insert_ob_in_map (obj, dropper->map, dropper, INS_BELOW_ORIGINATOR); |
651 | } |
674 | } |
652 | |
675 | |
653 | void |
676 | void |
654 | drop (object *op, object *tmp) |
677 | drop (object *op, object *tmp) |
655 | { |
678 | { |
… | |
… | |
853 | |
876 | |
854 | /* draw_look(op);*/ |
877 | /* draw_look(op);*/ |
855 | return 0; |
878 | return 0; |
856 | } |
879 | } |
857 | |
880 | |
|
|
881 | |
|
|
882 | /* This function tries to drop all objects in the <objs> vector. |
|
|
883 | * <dropper> is the object that wants to drop them. |
|
|
884 | * <cnt> can be a 0 pointer or a pointer to the maximum number of |
|
|
885 | * drop operations to perform. |
|
|
886 | * |
|
|
887 | * Returns true if at least one item was dropped. |
|
|
888 | */ |
|
|
889 | bool |
|
|
890 | drop_vector (object *dropper, vector<object *> &objs, int *cnt) |
|
|
891 | { |
|
|
892 | vector<object *>::iterator i; |
|
|
893 | |
|
|
894 | bool did_one = false; |
|
|
895 | |
|
|
896 | for (i = objs.begin (); i != objs.end (); i++) |
|
|
897 | { |
|
|
898 | drop (dropper, *i); |
|
|
899 | if (cnt && --*cnt <= 0) break; |
|
|
900 | did_one = true; |
|
|
901 | } |
|
|
902 | |
|
|
903 | return did_one; |
|
|
904 | } |
|
|
905 | |
858 | /* Object op wants to drop object(s) params. params can be a |
906 | /* Object op wants to drop object(s) params. params can be a |
859 | * comma seperated list. |
907 | * comma seperated list. |
860 | */ |
908 | */ |
861 | int |
909 | int |
862 | command_drop (object *op, char *params) |
910 | command_drop (object *op, char *params) |
… | |
… | |
869 | new_draw_info (NDI_UNIQUE, 0, op, "Drop what?"); |
917 | new_draw_info (NDI_UNIQUE, 0, op, "Drop what?"); |
870 | return 0; |
918 | return 0; |
871 | } |
919 | } |
872 | else |
920 | else |
873 | { |
921 | { |
874 | int cnt = MAX_ITEM_PER_DROP; |
922 | vector<object *> matched_objs; |
875 | |
923 | |
876 | for (tmp = op->inv; tmp; tmp = next) |
924 | for (tmp = op->inv; tmp; tmp = next) |
877 | { |
925 | { |
878 | next = tmp->below; |
926 | next = tmp->below; |
879 | if (QUERY_FLAG (tmp, FLAG_NO_DROP) || tmp->invisible) |
927 | if (QUERY_FLAG (tmp, FLAG_NO_DROP) || tmp->invisible) |
880 | continue; |
928 | continue; |
881 | |
929 | |
882 | if (item_matched_string (op, tmp, params)) |
930 | if (item_matched_string (op, tmp, params)) |
883 | { |
931 | matched_objs.push_back (tmp); |
884 | drop (op, tmp); |
|
|
885 | if (--cnt <= 0) break; |
|
|
886 | did_one = 1; |
|
|
887 | } |
932 | } |
888 | } |
|
|
889 | |
933 | |
890 | if (!did_one) |
934 | int cnt = MAX_ITEM_PER_DROP; |
|
|
935 | |
|
|
936 | if (!drop_vector (op, matched_objs, &cnt)) |
891 | new_draw_info (NDI_UNIQUE, 0, op, "Nothing to drop."); |
937 | new_draw_info (NDI_UNIQUE, 0, op, "Nothing to drop."); |
892 | |
938 | |
893 | if (cnt <= 0) |
939 | if (cnt <= 0) |
894 | op->failmsg ("Only dropped some items, can't drop that many items at once."); |
940 | op->failmsg ("Only dropped some items, can't drop that many items at once."); |
895 | } |
941 | } |