| 811 | } |
| 812 | |
| 813 | static bool detachItem(df::item *item) |
| 814 | { // Remove item from any inventory or map block |
| 815 | if (!item->specific_refs.empty() || item->world_data_id != -1) |
| 816 | return false; |
| 817 | |
| 818 | bool building_clutter = false; |
| 819 | for (auto ref : item->general_refs) { |
| 820 | switch (ref->getType()) |
| 821 | { |
| 822 | case general_ref_type::BUILDING_HOLDER: |
| 823 | if (item->flags.bits.in_building) |
| 824 | return false; // Construction mat |
| 825 | building_clutter = true; |
| 826 | break; |
| 827 | case general_ref_type::BUILDING_CAGED: |
| 828 | case general_ref_type::BUILDING_TRIGGER: |
| 829 | case general_ref_type::BUILDING_TRIGGERTARGET: |
| 830 | case general_ref_type::BUILDING_CIVZONE_ASSIGNED: |
| 831 | return false; |
| 832 | default: |
| 833 | break; |
| 834 | } |
| 835 | } |
| 836 | |
| 837 | if (building_clutter) { |
| 838 | if (auto building = virtual_cast<df::building_actual>(Items::getHolderBuilding(item))) { |
| 839 | for (size_t i = 0; i < building->contained_items.size(); i++) |
| 840 | { |
| 841 | auto ci = building->contained_items[i]; |
| 842 | if (ci->item == item) { |
| 843 | removeRef(item->general_refs, general_ref_type::BUILDING_HOLDER, building->id); |
| 844 | vector_erase_at(building->contained_items, i); |
| 845 | delete ci; |
| 846 | return true; |
| 847 | } |
| 848 | } |
| 849 | } |
| 850 | } |
| 851 | |
| 852 | if (auto ref = virtual_cast<df::general_ref_projectile>(Items::getGeneralRef(item, general_ref_type::PROJECTILE))) { |
| 853 | auto proj_id = ref->projectile_id; |
| 854 | bool isRefRemoved = removeRef(item->general_refs, general_ref_type::PROJECTILE, proj_id); |
| 855 | bool isLinkRemoved = linked_list_remove(&world->projectiles.all, proj_id); |
| 856 | return isRefRemoved && isLinkRemoved; |
| 857 | } |
| 858 | |
| 859 | if (item->flags.bits.on_ground) { |
| 860 | if (!removeItemOnGround(item)) |
| 861 | Core::printerr("Item was marked on_ground, but not in block: {} ({},{},{})\n", |
| 862 | item->id, item->pos.x, item->pos.y, item->pos.z); |
| 863 | item->flags.bits.on_ground = false; |
| 864 | return true; |
| 865 | } |
| 866 | |
| 867 | if (item->flags.bits.in_inventory) { |
| 868 | bool found = false; |
| 869 | for (int i = item->general_refs.size()-1; i >= 0; i--) { |
| 870 | auto ref = item->general_refs[i]; |
no test coverage detected