RPED tier-based parts dumping (#72386)

## About The Pull Request

![image](https://user-images.githubusercontent.com/31829017/210158760-9784fc06-f49c-45a3-b020-23c54507d471.png)
Dumping out an RPED (by using it inhand - clickdrag dumping unaffected)
causes it to calculate and drop the lowest tier of parts. Emptying
further can be done by just using it inhand more.

Directly inspired by
https://github.com/Citadel-Station-13/Citadel-Station-13/pull/13763.

The implementation probably sucks. I know I was told to use an
associated list but then I forgot how to approach that and decided to
slap together the current implementation. Sorry.


https://user-images.githubusercontent.com/31829017/210158742-cae83430-bd9f-407f-a0fa-f11975d15d4c.mp4

## Why It's Good For The Game
Decluttering your part exchanger is as easy as pressing Z or whatever
you do to dump out a storage item inhand.

## Changelog
🆑
qol: Rapid Part Exchange Devices and their bluespace variants now
automatically drop their current lowest tier of parts, instead of all of
their parts.
/🆑

Co-authored-by: Hatterhat <Hatterhat@users.noreply.github.com>
This commit is contained in:
Hatterhat
2023-01-06 17:29:49 -08:00
committed by GitHub
co-authored by Hatterhat
parent ff4f44474a
commit 46b114dc3b
2 changed files with 50 additions and 6 deletions
+47
View File
@@ -34,6 +34,11 @@
/obj/item/stack/sheet/bluespace_crystal,
)
/datum/storage/rped/New(atom/parent, max_slots, max_specific_storage, max_total_storage, numerical_stacking, allow_quick_gather, allow_quick_empty, collection_mode, attack_hand_interact)
. = ..()
var/atom/resolve_parent = src.parent?.resolve()
RegisterSignal(resolve_parent, COMSIG_ITEM_ATTACK_SELF, PROC_REF(rped_mass_empty), TRUE)
/datum/storage/rped/can_insert(obj/item/to_insert, mob/user, messages = TRUE, force = FALSE)
. = ..()
@@ -77,4 +82,46 @@
return .
/// overridden mass_empty, so as to dump only the lowest tier of parts currently in the RPED
/datum/storage/rped/proc/rped_mass_empty(datum/source, atom/location, force)
SIGNAL_HANDLER
if(!allow_quick_empty && !force)
return
remove_lowest_tier(get_turf(location))
/**
* Searches through everything currently in storage, calculates the lowest tier of parts inside of it,
* and then dumps out every part that has the equal tier of parts. Likely a worse implementation of remove_all.
*
* @param atom/target where we're placing the item
*/
/datum/storage/rped/proc/remove_lowest_tier(atom/target) // look whatever happens here i'm not proud of this. at all.
var/obj/item/resolve_parent = parent?.resolve()
var/obj/item/resolve_location = real_location?.resolve()
var/list/obj/item/parts_list = list()
var/current_lowest_tier = INFINITY
if(!resolve_parent || !resolve_location)
return
if(!target)
target = get_turf(resolve_parent)
for(var/obj/item/thing in resolve_location)
if(thing.loc != resolve_location)
continue
parts_list.Add(thing)
if(parts_list.len > 0)
parts_list = reverse_range(sortTim(parts_list, GLOBAL_PROC_REF(cmp_rped_sort)))
current_lowest_tier = parts_list[1].get_part_rating()
resolve_parent.balloon_alert(resolve_parent.loc, "dropping lowest rated parts...")
for(var/obj/item/part in parts_list)
if(part.get_part_rating() != current_lowest_tier)
break
if(!attempt_remove(part, target, silent = TRUE))
continue
part.pixel_x = part.base_pixel_x + rand(-8, 8)
part.pixel_y = part.base_pixel_y + rand(-8, 8)
#undef MAX_STACK_PICKUP
+3 -6
View File
@@ -225,14 +225,11 @@ If you create T5+ please take a pass at mech_fabricator.dm. The parts being good
part_list = sortTim(part_list, GLOBAL_PROC_REF(cmp_rped_sort))
return part_list
/proc/cmp_rped_sort(obj/item/A, obj/item/B)
/proc/cmp_rped_sort(obj/item/first_item, obj/item/second_item)
/**
* stacks components like cable,glass,plasteel are not component parts hence their get_part_rating() method is undefined and would return undefined values causing errors
* so we assign them an default rating of 1 when the RPED sorts these components
* even though stacks aren't stock parts, get_part_rating() is defined on the item level (see /obj/item/proc/get_part_rating()) and defaults to returning 0.
*/
var/a_rating = isstack(A) ? 1 : A.get_part_rating()
var/b_rating = isstack(B) ? 1 : B.get_part_rating()
return b_rating - a_rating
return second_item.get_part_rating() - first_item.get_part_rating()
/obj/item/stock_parts
name = "stock part"