diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 0235c428763..8ec95866b37 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -211,9 +211,10 @@
continue
success = TRUE
- S.handle_item_insertion(I, 1) //The 1 stops the "You put the [src] into [S]" insertion message from being displayed.
+ S.handle_item_insertion_deferred(I, user) //The 1 stops the "You put the [src] into [S]" insertion message from being displayed.
CHECK_TICK // Because people insist on picking up huge-ass piles of stuff.
+ S.handle_storage_deferred(user)
if(success && !failure)
user << "You put everything in [S]."
else if(success)
diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm
index bce0d2c663e..a5b35a55693 100644
--- a/code/game/objects/items/weapons/storage/bags.dm
+++ b/code/game/objects/items/weapons/storage/bags.dm
@@ -22,6 +22,7 @@
display_contents_with_number = 0 // UNStABLE AS FuCK, turn on when it stops crashing clients
use_to_pickup = 1
slot_flags = SLOT_BELT
+ var/use_deferred = TRUE
// -----------------------------
// Trash bag
@@ -58,7 +59,13 @@
bagfull = 1
break
count++
- handle_item_insertion(L, 1)//value of 1 suppresses confirmation messages from this one
+ if (use_deferred)
+ handle_item_insertion_deferred(L, user)
+ else
+ handle_item_insertion(L, TRUE)
+
+ if (use_deferred)
+ handle_storage_deferred(user)
if (count)
user << "You empty [count] broken bulbs into the trashbag."
@@ -135,122 +142,119 @@
storage_slots = 7
allow_quick_empty = 1 // this function is superceded
- New()
- ..()
- //verbs -= /obj/item/weapon/storage/verb/quick_empty
- //verbs += /obj/item/weapon/storage/bag/sheetsnatcher/quick_empty
+ use_deferred = FALSE
- can_be_inserted(obj/item/W as obj, stop_messages = 0)
- if(!istype(W,/obj/item/stack/material))
- if(!stop_messages)
- usr << "The snatcher does not accept [W]."
- return 0
- var/current = 0
- for(var/obj/item/stack/material/S in contents)
- current += S.amount
- if(capacity == current)//If it's full, you're done
- if(!stop_messages)
- usr << "The snatcher is full."
- return 0
- return 1
+/obj/item/weapon/storage/bag/sheetsnatcher/can_be_inserted(obj/item/W as obj, stop_messages = 0)
+ if(!istype(W,/obj/item/stack/material))
+ if(!stop_messages)
+ usr << "The snatcher does not accept [W]."
+ return 0
+ var/current = 0
+ for(var/obj/item/stack/material/S in contents)
+ current += S.amount
+ if(capacity == current)//If it's full, you're done
+ if(!stop_messages)
+ usr << "The snatcher is full."
+ return 0
+ return 1
// Modified handle_item_insertion. Would prefer not to, but...
- handle_item_insertion(obj/item/W as obj, prevent_warning = 0)
- var/obj/item/stack/material/S = W
- if(!istype(S)) return 0
+/obj/item/weapon/storage/bag/sheetsnatcher/handle_item_insertion(obj/item/W as obj, prevent_warning = 0)
+ var/obj/item/stack/material/S = W
+ if(!istype(S)) return 0
- var/amount
- var/inserted = 0
- var/current = 0
- for(var/obj/item/stack/material/S2 in contents)
- current += S2.amount
- if(capacity < current + S.amount)//If the stack will fill it up
- amount = capacity - current
+ var/amount
+ var/inserted = 0
+ var/current = 0
+ for(var/obj/item/stack/material/S2 in contents)
+ current += S2.amount
+ if(capacity < current + S.amount)//If the stack will fill it up
+ amount = capacity - current
+ else
+ amount = S.amount
+
+ for(var/obj/item/stack/material/sheet in contents)
+ if(S.type == sheet.type) // we are violating the amount limitation because these are not sane objects
+ sheet.amount += amount // they should only be removed through procs in this file, which split them up.
+ S.amount -= amount
+ inserted = 1
+ break
+
+ if(!inserted || !S.amount)
+ usr.remove_from_mob(S)
+ usr.update_icons() //update our overlays
+ if (usr.client && usr.s_active != src)
+ usr.client.screen -= S
+ S.dropped(usr)
+ if(!S.amount)
+ qdel(S)
else
- amount = S.amount
+ S.loc = src
- for(var/obj/item/stack/material/sheet in contents)
- if(S.type == sheet.type) // we are violating the amount limitation because these are not sane objects
- sheet.amount += amount // they should only be removed through procs in this file, which split them up.
- S.amount -= amount
- inserted = 1
- break
-
- if(!inserted || !S.amount)
- usr.remove_from_mob(S)
- usr.update_icons() //update our overlays
- if (usr.client && usr.s_active != src)
- usr.client.screen -= S
- S.dropped(usr)
- if(!S.amount)
- qdel(S)
- else
- S.loc = src
-
- orient2hud(usr)
- if(usr.s_active)
- usr.s_active.show_to(usr)
- update_icon()
- return 1
+ orient2hud(usr)
+ if(usr.s_active)
+ usr.s_active.show_to(usr)
+ update_icon()
+ return 1
// Sets up numbered display to show the stack size of each stored mineral
// NOTE: numbered display is turned off currently because it's broken
- orient2hud(mob/user as mob)
- var/adjusted_contents = contents.len
+/obj/item/weapon/storage/bag/sheetsnatcher/orient2hud(mob/user as mob)
+ var/adjusted_contents = contents.len
- //Numbered contents display
- var/list/datum/numbered_display/numbered_contents
- if(display_contents_with_number)
- numbered_contents = list()
- adjusted_contents = 0
- for(var/obj/item/stack/material/I in contents)
- adjusted_contents++
- var/datum/numbered_display/D = new/datum/numbered_display(I)
- D.number = I.amount
- numbered_contents.Add( D )
+ //Numbered contents display
+ var/list/datum/numbered_display/numbered_contents
+ if(display_contents_with_number)
+ numbered_contents = list()
+ adjusted_contents = 0
+ for(var/obj/item/stack/material/I in contents)
+ adjusted_contents++
+ var/datum/numbered_display/D = new/datum/numbered_display(I)
+ D.number = I.amount
+ numbered_contents.Add( D )
- var/row_num = 0
- var/col_count = min(7,storage_slots) -1
- if (adjusted_contents > 7)
- row_num = round((adjusted_contents-1) / 7) // 7 is the maximum allowed width.
- src.slot_orient_objs(row_num, col_count, numbered_contents)
- return
+ var/row_num = 0
+ var/col_count = min(7,storage_slots) -1
+ if (adjusted_contents > 7)
+ row_num = round((adjusted_contents-1) / 7) // 7 is the maximum allowed width.
+ src.slot_orient_objs(row_num, col_count, numbered_contents)
+ return
// Modified quick_empty verb drops appropriate sized stacks
- quick_empty()
- var/location = get_turf(src)
- for(var/obj/item/stack/material/S in contents)
- while(S.amount)
- var/obj/item/stack/material/N = new S.type(location)
- var/stacksize = min(S.amount,N.max_amount)
- N.amount = stacksize
- S.amount -= stacksize
- if(!S.amount)
- qdel(S) // todo: there's probably something missing here
- orient2hud(usr)
- if(usr.s_active)
- usr.s_active.show_to(usr)
- update_icon()
+/obj/item/weapon/storage/bag/sheetsnatcher/quick_empty()
+ var/location = get_turf(src)
+ for(var/obj/item/stack/material/S in contents)
+ while(S.amount)
+ var/obj/item/stack/material/N = new S.type(location)
+ var/stacksize = min(S.amount,N.max_amount)
+ N.amount = stacksize
+ S.amount -= stacksize
+ if(!S.amount)
+ qdel(S) // todo: there's probably something missing here
+ orient2hud(usr)
+ if(usr.s_active)
+ usr.s_active.show_to(usr)
+ update_icon()
// Instead of removing
- remove_from_storage(obj/item/W as obj, atom/new_location)
- var/obj/item/stack/material/S = W
- if(!istype(S)) return 0
+/obj/item/weapon/storage/bag/sheetsnatcher/remove_from_storage(obj/item/W as obj, atom/new_location)
+ var/obj/item/stack/material/S = W
+ if(!istype(S)) return 0
- //I would prefer to drop a new stack, but the item/attack_hand code
- // that calls this can't recieve a different object than you clicked on.
- //Therefore, make a new stack internally that has the remainder.
- // -Sayu
+ //I would prefer to drop a new stack, but the item/attack_hand code
+ // that calls this can't recieve a different object than you clicked on.
+ //Therefore, make a new stack internally that has the remainder.
+ // -Sayu
- if(S.amount > S.max_amount)
- var/obj/item/stack/material/temp = new S.type(src)
- temp.amount = S.amount - S.max_amount
- S.amount = S.max_amount
+ if(S.amount > S.max_amount)
+ var/obj/item/stack/material/temp = new S.type(src)
+ temp.amount = S.amount - S.max_amount
+ S.amount = S.max_amount
- return ..(S,new_location)
+ return ..(S,new_location)
// -----------------------------
// Sheet Snatcher (Cyborg)
diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm
index 0e3d4dceb2f..032bff6932c 100644
--- a/code/game/objects/items/weapons/storage/storage.dm
+++ b/code/game/objects/items/weapons/storage/storage.dm
@@ -360,34 +360,52 @@
//This proc handles items being inserted. It does not perform any checks of whether an item can or can't be inserted. That's done by can_be_inserted()
//The stop_warning parameter will stop the insertion message from being displayed. It is intended for cases where you are inserting multiple items at once,
//such as when picking up all the items on a tile with one click.
-/obj/item/weapon/storage/proc/handle_item_insertion(obj/item/W as obj, prevent_warning = 0)
+/obj/item/weapon/storage/proc/handle_item_insertion(obj/item/W as obj, prevent_warning = 0, mob/user = usr)
if(!istype(W)) return 0
- if(usr)
- usr.prepare_for_slotmove(W)
- usr.update_icons() //update our overlays
+ if(user)
+ user.prepare_for_slotmove(W)
W.forceMove(src)
W.on_enter_storage(src)
- if(usr)
- if (usr.client && usr.s_active != src)
- usr.client.screen -= W
- W.dropped(usr)
- add_fingerprint(usr)
+ if(user)
+ W.dropped(user)
+ add_fingerprint(user)
if(!prevent_warning)
- for(var/mob/M in viewers(usr, null))
+ for(var/mob/M in viewers(user, null))
if (M == usr)
usr << "You put \the [W] into [src]."
else if (M in range(1)) //If someone is standing close enough, they can tell what it is...
- M.show_message("\The [usr] puts [W] into [src].")
+ M.show_message("\The [user] puts [W] into [src].")
else if (W && W.w_class >= 3) //Otherwise they can only see large or normal items from a distance...
- M.show_message("\The [usr] puts [W] into [src].")
+ M.show_message("\The [user] puts [W] into [src].")
- src.orient2hud(usr)
- if(usr.s_active)
- usr.s_active.show_to(usr)
- update_icon()
+ orient2hud(user)
+ if(user.s_active)
+ user.s_active.show_to(user)
+ queue_icon_update()
return 1
+// This is for inserting more than one thing at a time, you should call handle_storage_deferred after all the items have been inserted.
+/obj/item/weapon/storage/proc/handle_item_insertion_deferred(obj/item/W, mob/user)
+ if (!istype(W))
+ return FALSE
+
+ if (user)
+ user.prepare_for_slotmove(W)
+
+ W.forceMove(src)
+ W.on_enter_storage(src)
+ if (user)
+ W.dropped(user)
+
+/obj/item/weapon/storage/proc/handle_storage_deferred(mob/user)
+ add_fingerprint(user)
+ user.update_icons()
+ orient2hud(user)
+ if (user.s_active)
+ user.s_active.show_to(user)
+ queue_icon_update()
+
//Call this proc to handle the removal of an item from the storage item. The item will be moved to the atom sent as new_target
/obj/item/weapon/storage/proc/remove_from_storage(obj/item/W as obj, atom/new_location)
if(!istype(W)) return 0
@@ -422,6 +440,45 @@
update_icon()
return 1
+/obj/item/weapon/storage/proc/remove_from_storage_deferred(obj/item/W, atom/new_location, mob/user)
+ if (!istype(W))
+ return FALSE
+
+ // fuck if I know.
+ for(var/mob/M in range(1, src.loc))
+ if (M.s_active == src)
+ if (M.client)
+ M.client.screen -= W
+
+ if (new_location)
+ if (ismob(loc))
+ W.dropped(user)
+ if (ismob(new_location))
+ W.layer = 20
+ else
+ W.layer = initial(W.layer)
+
+ W.forceMove(new_location)
+ else
+ W.forceMove(get_turf(src))
+
+ if (W.maptext)
+ W.maptext = ""
+
+ W.on_exit_storage(src)
+
+ return TRUE
+
+/obj/item/weapon/storage/proc/post_remove_from_storage_deferred(atom/oldloc, mob/user)
+ orient2hud(user)
+ if (user.s_active)
+ user.s_active.show_to(user)
+
+ // who knows what the fuck this does
+ if (istype(src, /obj/item/weapon/storage/fancy))
+ update_icon(1)
+ else
+ update_icon()
//This proc is called when you want to place an item into the storage item.
//Its a safe proc for adding things to the storage that does the necessary checks. Object will not be moved if it fails
@@ -513,10 +570,12 @@
var/turf/T = get_turf(src)
hide_from(usr)
for(var/obj/item/I in contents)
- remove_from_storage(I, T)
+ remove_from_storage_deferred(I, T, usr)
CHECK_TICK
+ post_remove_from_storage_deferred(loc, usr)
+
// Override this to fill the storage object with stuff.
/obj/item/weapon/storage/proc/fill()
return
diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm
index 30d3adf7127..2ccf6266c01 100644
--- a/code/modules/mining/mine_items.dm
+++ b/code/modules/mining/mine_items.dm
@@ -1131,8 +1131,7 @@ var/list/total_extraction_beacons = list()
single_spark(O.loc)
do_teleport(O, user, 0)
- if (TICK_CHECK)
- return
+ CHECK_TICK
/******************************Sculpting*******************************/
/obj/item/weapon/autochisel
diff --git a/code/modules/mining/satchel_ore_boxdm.dm b/code/modules/mining/satchel_ore_boxdm.dm
index 0c0aebe2db9..f0dd6e5d770 100644
--- a/code/modules/mining/satchel_ore_boxdm.dm
+++ b/code/modules/mining/satchel_ore_boxdm.dm
@@ -16,12 +16,14 @@
src.contents += W
if (istype(W, /obj/item/weapon/storage))
var/obj/item/weapon/storage/S = W
- S.hide_from(usr)
+ S.hide_from(user)
for(var/obj/item/weapon/ore/O in S.contents)
- S.remove_from_storage(O, src) //This will move the item to this item's contents
+ S.remove_from_storage_deferred(O, src, user) //This will move the item to this item's contents
CHECK_TICK
+ S.post_remove_from_storage_deferred(loc, user)
+
user << span("notice", "You empty the satchel into the box.")
update_ore_count()
diff --git a/html/changelogs/lohikar-bagperf.yml b/html/changelogs/lohikar-bagperf.yml
new file mode 100644
index 00000000000..ef9ad377510
--- /dev/null
+++ b/html/changelogs/lohikar-bagperf.yml
@@ -0,0 +1,5 @@
+author: Lohikar
+delete-after: True
+changes:
+ - experiment: "Storage code has been tweaked so ore bags should no longer take multiple seconds to fill/empty."
+ - tweak: "The ore summoner should actually transport useful amounts of ore now."