diff --git a/code/_onclick/drag_drop.dm b/code/_onclick/drag_drop.dm
index 42a0574f4d8..3f1ff20d5c8 100644
--- a/code/_onclick/drag_drop.dm
+++ b/code/_onclick/drag_drop.dm
@@ -6,12 +6,13 @@
almost anything into a trash can.
*/
/atom/MouseDrop(atom/over)
- if(!usr || !over) return
- if(!Adjacent(usr) || !over.Adjacent(usr)) return // should stop you from dragging through windows
+ if(!usr || !over)
+ return
+ if(!(istype(over, /obj/screen) || (loc && loc == over.loc)))
+ if(!Adjacent(usr) || !over.Adjacent(usr)) // should stop you from dragging through windows
+ return
- spawn(0)
- over.MouseDrop_T(src,usr)
- return
+ INVOKE_ASYNC(over, .proc/MouseDrop_T, src, usr)
// recieve a mousedrop
/atom/proc/MouseDrop_T(atom/dropping, mob/user)
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index d75e61e1885..58bb69355ea 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -120,7 +120,8 @@
usr.stop_pulling()
/obj/screen/pull/update_icon(mob/mymob)
- if(!mymob) return
+ if(!mymob)
+ return
if(mymob.pulling)
icon_state = "pull"
else
@@ -151,16 +152,49 @@
/obj/screen/storage/Click(location, control, params)
if(world.time <= usr.next_move)
- return 1
- if(usr.stat || usr.paralysis || usr.stunned || usr.IsWeakened())
- return 1
+ return TRUE
+ if(usr.incapacitated(ignore_restraints = TRUE, ignore_lying = TRUE))
+ return TRUE
if(istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech
- return 1
+ return TRUE
if(master)
var/obj/item/I = usr.get_active_hand()
if(I)
master.attackby(I, usr, params)
- return 1
+ return TRUE
+
+/obj/screen/storage/MouseDrop_T(obj/item/I, mob/user)
+ if(!user || !istype(I) || user.incapacitated(ignore_restraints = TRUE, ignore_lying = TRUE) || istype(user.loc, /obj/mecha) || !master)
+ return
+
+ var/obj/item/storage/S = master
+ if(!S)
+ return
+
+ if(I in S.contents) // If the item is already in the storage, move them to the end of the list
+ if(S.contents[S.contents.len] == I) // No point moving them at the end if they're already there!
+ return
+
+ var/list/new_contents = S.contents.Copy()
+ if(S.display_contents_with_number)
+ // Basically move all occurences of I to the end of the list.
+ var/list/obj/item/to_append = list()
+ for(var/obj/item/stored_item in S.contents)
+ if(S.can_items_stack(stored_item, I))
+ new_contents -= stored_item
+ to_append += stored_item
+
+ new_contents.Add(to_append)
+ else
+ new_contents -= I
+ new_contents += I // oof
+ S.contents = new_contents
+
+ if(user.s_active == S)
+ S.orient2hud(user)
+ S.show_to(user)
+ else // If it's not in the storage, try putting it inside
+ S.attackby(I, user)
/obj/screen/zone_sel
name = "damage zone"
@@ -271,7 +305,7 @@
if(choice != selecting)
selecting = choice
- update_icon(usr)
+ update_icon(user)
return 1
/obj/screen/zone_sel/update_icon(mob/user)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index edcc6620531..0c2f5378926 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -310,7 +310,7 @@ GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effect
if(istype(I, /obj/item/storage))
var/obj/item/storage/S = I
if(S.use_to_pickup)
- if(S.collection_mode) //Mode is set to collect all items on a tile and we clicked on a valid one.
+ if(S.pickup_all_on_tile) //Mode is set to collect all items on a tile and we clicked on a valid one.
if(isturf(loc))
var/list/rejections = list()
var/success = 0
@@ -644,6 +644,14 @@ GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effect
deltimer(tip_timer) //delete any in-progress timer if the mouse is moved off the item before it finishes
closeToolTip(usr)
+/obj/item/MouseDrop_T(obj/item/I, mob/user)
+ if(!user || src == I)
+ return
+
+ if(loc && I.loc == loc && istype(loc, /obj/item/storage)) // Are we trying to swap two items in the storage?
+ var/obj/item/storage/S = loc
+ S.swap_items(src, I, user)
+
// Returns a numeric value for sorting items used as parts in machines, so they can be replaced by the rped
/obj/item/proc/get_part_rating()
return 0
diff --git a/code/game/objects/items/weapons/stock_parts.dm b/code/game/objects/items/weapons/stock_parts.dm
index 0d5591bbc16..7df47345bae 100644
--- a/code/game/objects/items/weapons/stock_parts.dm
+++ b/code/game/objects/items/weapons/stock_parts.dm
@@ -11,7 +11,7 @@
use_to_pickup = 1
allow_quick_gather = 1
allow_quick_empty = 1
- collection_mode = 1
+ pickup_all_on_tile = TRUE
display_contents_with_number = 1
max_w_class = WEIGHT_CLASS_NORMAL
max_combined_w_class = 100
diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm
index a3bafa5b3cf..f709a9496a4 100644
--- a/code/game/objects/items/weapons/storage/storage.dm
+++ b/code/game/objects/items/weapons/storage/storage.dm
@@ -9,7 +9,7 @@
name = "storage"
icon = 'icons/obj/storage.dmi'
w_class = WEIGHT_CLASS_NORMAL
- var/silent = 0 // No message on putting items in
+ var/silent = FALSE // No message on putting items in
var/list/can_hold = new/list() //List of objects which this item can store (if set, it can't store anything else)
var/list/cant_hold = new/list() //List of objects which this item can't store (in effect only if can_hold isn't set)
var/empty = FALSE // Will this spawn as an empty box
@@ -22,7 +22,7 @@
var/display_contents_with_number //Set this to make the storage item group contents of the same type and display them as a number.
var/allow_quick_empty //Set this variable to allow the object to have the 'empty' verb, which dumps all the contents on the floor.
var/allow_quick_gather //Set this variable to allow the object to have the 'toggle mode' verb, which quickly collects all items from a tile.
- var/collection_mode = 1; //0 = pick one at a time, 1 = pick all on tile
+ var/pickup_all_on_tile = TRUE //FALSE = pick one at a time, TRUE = pick all on tile
var/use_sound = "rustle" //sound played when used. null for no sound.
/// What kind of [/obj/item/stack] can this be folded into. (e.g. Boxes and cardboard)
@@ -30,7 +30,7 @@
/// How much of the stack item do you get.
var/foldable_amt = 0
-/obj/item/storage/MouseDrop(obj/over_object as obj)
+/obj/item/storage/MouseDrop(obj/over_object)
if(ishuman(usr)) //so monkeys can take off their backpacks -- Urist
var/mob/M = usr
@@ -63,12 +63,12 @@
update_icon() // For content-sensitive icons
return
- if(!( istype(over_object, /obj/screen) ))
+ if(!(istype(over_object, /obj/screen)))
return ..()
- if(!(src.loc == usr) || (src.loc && src.loc.loc == usr))
+ if(!(loc == usr) || (loc && loc.loc == usr))
return
- playsound(src.loc, "rustle", 50, 1, -5)
- if(!( M.restrained() ) && !( M.stat ))
+ playsound(loc, "rustle", 50, TRUE, -5)
+ if(!(M.restrained()) && !(M.stat))
switch(over_object.name)
if("r_hand")
if(!M.unEquip(src))
@@ -78,29 +78,27 @@
if(!M.unEquip(src))
return
M.put_in_l_hand(src)
- src.add_fingerprint(usr)
+ add_fingerprint(usr)
return
if(over_object == usr && in_range(src, usr) || usr.contents.Find(src))
if(usr.s_active)
usr.s_active.close(usr)
- src.show_to(usr)
+ show_to(usr)
return
- return
/obj/item/storage/AltClick(mob/user)
if(ishuman(user) && Adjacent(user) && !user.incapacitated(FALSE, TRUE, TRUE))
show_to(user)
- playsound(loc, "rustle", 50, 1, -5)
+ playsound(loc, "rustle", 50, TRUE, -5)
add_fingerprint(user)
else if(isobserver(user))
show_to(user)
return ..()
/obj/item/storage/proc/return_inv()
+ var/list/L = list()
- var/list/L = list( )
-
- L += src.contents
+ L += contents
for(var/obj/item/storage/S in src)
L += S.return_inv()
@@ -112,7 +110,7 @@
L += F.contents
return L
-/obj/item/storage/proc/show_to(mob/user as mob)
+/obj/item/storage/proc/show_to(mob/user)
if(!user.client)
return
if(user.s_active != src)
@@ -131,38 +129,36 @@
user.s_active = src
return
-/obj/item/storage/proc/hide_from(mob/user as mob)
-
+/obj/item/storage/proc/hide_from(mob/user)
if(!user.client)
return
- user.client.screen -= src.boxes
- user.client.screen -= src.closer
- user.client.screen -= src.contents
+
+ user.client.screen -= boxes
+ user.client.screen -= closer
+ user.client.screen -= contents
if(user.s_active == src)
user.s_active = null
return
/obj/item/storage/proc/open(mob/user as mob)
- if(src.use_sound)
- playsound(src.loc, src.use_sound, 50, 1, -5)
+ if(use_sound)
+ playsound(loc, use_sound, 50, TRUE, -5)
if(user.s_active)
user.s_active.close(user)
show_to(user)
-/obj/item/storage/proc/close(mob/user as mob)
-
- src.hide_from(user)
+/obj/item/storage/proc/close(mob/user)
+ hide_from(user)
user.s_active = null
- return
//This proc draws out the inventory and places the items on it. tx and ty are the upper left tile and mx, my are the bottm right.
//The numbers are calculated from the bottom-left The bottom-left slot being 1,1.
/obj/item/storage/proc/orient_objs(tx, ty, mx, my)
var/cx = tx
var/cy = ty
- src.boxes.screen_loc = "[tx]:,[ty] to [mx],[my]"
- for(var/obj/O in src.contents)
+ boxes.screen_loc = "[tx],[ty] to [mx],[my]"
+ for(var/obj/O in contents)
O.screen_loc = "[cx],[cy]"
O.layer = ABOVE_HUD_LAYER
O.plane = ABOVE_HUD_PLANE
@@ -170,24 +166,23 @@
if(cx > mx)
cx = tx
cy--
- src.closer.screen_loc = "[mx+1],[my]"
- return
+ closer.screen_loc = "[mx + 1],[my]"
//This proc draws out the inventory and places the items on it. It uses the standard position.
-/obj/item/storage/proc/standard_orient_objs(var/rows, var/cols, var/list/obj/item/display_contents)
+/obj/item/storage/proc/standard_orient_objs(rows, cols, list/datum/numbered_display/display_contents)
var/cx = 4
- var/cy = 2+rows
- src.boxes.screen_loc = "4:16,2:16 to [4+cols]:16,[2+rows]:16"
+ var/cy = 2 + rows
+ boxes.screen_loc = "4:16,2:16 to [4 + cols]:16,[2 + rows]:16"
if(display_contents_with_number)
for(var/datum/numbered_display/ND in display_contents)
ND.sample_object.mouse_opacity = MOUSE_OPACITY_OPAQUE
ND.sample_object.screen_loc = "[cx]:16,[cy]:16"
- ND.sample_object.maptext = "[(ND.number > 1)? "[ND.number]" : ""]"
+ ND.sample_object.maptext = "[(ND.number > 1) ? "[ND.number]" : ""]"
ND.sample_object.layer = ABOVE_HUD_LAYER
ND.sample_object.plane = ABOVE_HUD_PLANE
cx++
- if(cx > (4+cols))
+ if(cx > (4 + cols))
cx = 4
cy--
else
@@ -198,78 +193,81 @@
O.layer = ABOVE_HUD_LAYER
O.plane = ABOVE_HUD_PLANE
cx++
- if(cx > (4+cols))
+ if(cx > (4 + cols))
cx = 4
cy--
- src.closer.screen_loc = "[4+cols+1]:16,2:16"
- return
+ closer.screen_loc = "[4 + cols + 1]:16,2:16"
/datum/numbered_display
var/obj/item/sample_object
var/number
-/datum/numbered_display/New(obj/item/sample as obj)
+/datum/numbered_display/New(obj/item/sample)
if(!istype(sample))
qdel(src)
+ return
sample_object = sample
number = 1
//This proc determins the size of the inventory to be displayed. Please touch it only if you know what you're doing.
-/obj/item/storage/proc/orient2hud(mob/user as mob)
-
+/obj/item/storage/proc/orient2hud(mob/user)
var/adjusted_contents = contents.len
//Numbered contents display
- var/list/datum/numbered_display/numbered_contents
+ var/list/datum/numbered_display/display_contents
if(display_contents_with_number)
- numbered_contents = list()
+ for(var/obj/O in contents)
+ O.layer = initial(O.layer)
+ O.plane = initial(O.plane)
+
+ display_contents = list()
adjusted_contents = 0
for(var/obj/item/I in contents)
- var/found = 0
- for(var/datum/numbered_display/ND in numbered_contents)
+ var/found = FALSE
+ for(var/datum/numbered_display/ND in display_contents)
if(ND.sample_object.type == I.type && ND.sample_object.name == I.name)
ND.number++
- found = 1
+ found = TRUE
break
if(!found)
adjusted_contents++
- numbered_contents.Add( new/datum/numbered_display(I) )
+ display_contents.Add(new/datum/numbered_display(I))
//var/mob/living/carbon/human/H = user
var/row_num = 0
- var/col_count = min(7,storage_slots) -1
+ 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.standard_orient_objs(row_num, col_count, numbered_contents)
- return
+ row_num = round((adjusted_contents - 1) / 7) // 7 is the maximum allowed width.
+ standard_orient_objs(row_num, col_count, display_contents)
-//This proc return 1 if the item can be picked up and 0 if it can't.
+//This proc returns TRUE if the item can be picked up and FALSE if it can't.
//Set the stop_messages to stop it from printing messages
-/obj/item/storage/proc/can_be_inserted(obj/item/W as obj, stop_messages = 0)
- if(!istype(W) || (W.flags & ABSTRACT)) return //Not an item
+/obj/item/storage/proc/can_be_inserted(obj/item/W, stop_messages = FALSE)
+ if(!istype(W) || (W.flags & ABSTRACT)) //Not an item
+ return
- if(src.loc == W)
- return 0 //Means the item is already in the storage item
+ if(loc == W)
+ return FALSE //Means the item is already in the storage item
if(contents.len >= storage_slots)
if(!stop_messages)
to_chat(usr, "[W] won't fit in [src], make some space!")
- return 0 //Storage item is full
+ return FALSE //Storage item is full
if(can_hold.len)
if(!is_type_in_typecache(W, can_hold))
if(!stop_messages)
to_chat(usr, "[src] cannot hold [W].")
- return 0
+ return FALSE
if(is_type_in_typecache(W, cant_hold)) //Check for specific items which this container can't hold.
if(!stop_messages)
to_chat(usr, "[src] cannot hold [W].")
- return 0
+ return FALSE
if(W.w_class > max_w_class)
if(!stop_messages)
to_chat(usr, "[W] is too big for [src].")
- return 0
+ return FALSE
var/sum_w_class = W.w_class
for(var/obj/item/I in contents)
@@ -278,32 +276,32 @@
if(sum_w_class > max_combined_w_class)
if(!stop_messages)
to_chat(usr, "[src] is full, make some space.")
- return 0
+ return FALSE
- if(W.w_class >= src.w_class && (istype(W, /obj/item/storage)))
+ if(W.w_class >= w_class && (istype(W, /obj/item/storage)))
if(!istype(src, /obj/item/storage/backpack/holding)) //bohs should be able to hold backpacks again. The override for putting a boh in a boh is in backpack.dm.
if(!stop_messages)
to_chat(usr, "[src] cannot hold [W] as it's a storage item of the same size.")
- return 0 //To prevent the stacking of same sized storage items.
+ return FALSE //To prevent the stacking of same sized storage items.
if(W.flags & NODROP) //SHOULD be handled in unEquip, but better safe than sorry.
to_chat(usr, "\the [W] is stuck to your hand, you can't put it in \the [src]")
- return 0
+ return FALSE
- return 1
+ return TRUE
//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/storage/proc/handle_item_insertion(obj/item/W as obj, prevent_warning = 0)
+/obj/item/storage/proc/handle_item_insertion(obj/item/W, prevent_warning = FALSE)
if(!istype(W))
- return 0
+ return FALSE
if(usr)
if(!usr.unEquip(W))
- return 0
+ return FALSE
usr.update_icons() //update our overlays
if(silent)
- prevent_warning = 1
+ prevent_warning = TRUE
W.forceMove(src)
W.on_enter_storage(src)
if(usr)
@@ -315,28 +313,30 @@
if(!prevent_warning && !istype(W, /obj/item/gun/energy/kinetic_accelerator/crossbow))
for(var/mob/M in viewers(usr, null))
if(M == usr)
- to_chat(usr, "You put the [W] into [src].")
+ to_chat(usr, "You put [W] into [src].")
else if(M in range(1)) //If someone is standing close enough, they can tell what it is...
M.show_message("[usr] puts [W] into [src].")
else if(W && W.w_class >= WEIGHT_CLASS_NORMAL) //Otherwise they can only see large or normal items from a distance...
M.show_message("[usr] puts [W] into [src].")
+ orient2hud(usr)
if(usr.s_active)
usr.s_active.show_to(usr)
W.mouse_opacity = MOUSE_OPACITY_OPAQUE //So you can click on the area around the item to equip it, instead of having to pixel hunt
W.in_inventory = TRUE
update_icon()
- return 1
+ return TRUE
//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/storage/proc/remove_from_storage(obj/item/W as obj, atom/new_location)
- if(!istype(W)) return 0
+/obj/item/storage/proc/remove_from_storage(obj/item/W, atom/new_location)
+ if(!istype(W))
+ return FALSE
if(istype(src, /obj/item/storage/fancy))
var/obj/item/storage/fancy/F = src
- F.update_icon(1)
+ F.update_icon(TRUE)
- for(var/mob/M in range(1, src.loc))
+ for(var/mob/M in range(1, loc))
if(M.s_active == src)
if(M.client)
M.client.screen -= W
@@ -355,6 +355,7 @@
W.forceMove(get_turf(src))
if(usr)
+ orient2hud(usr)
if(usr.s_active)
usr.s_active.show_to(usr)
if(W.maptext)
@@ -362,7 +363,7 @@
W.on_exit_storage(src)
update_icon()
W.mouse_opacity = initial(W.mouse_opacity)
- return 1
+ return TRUE
/obj/item/storage/Exited(atom/A, loc)
remove_from_storage(A, loc) //worry not, comrade; this only gets called once
@@ -383,7 +384,7 @@
var/obj/item/hand_labeler/labeler = I
if(labeler.mode)
return FALSE
- . = 1 //no afterattack
+ . = TRUE //no afterattack
if(isrobot(user))
return //Robots can't interact with storage items.
@@ -394,8 +395,8 @@
handle_item_insertion(I)
-/obj/item/storage/attack_hand(mob/user as mob)
- playsound(src.loc, "rustle", 50, 1, -5)
+/obj/item/storage/attack_hand(mob/user)
+ playsound(loc, "rustle", 50, TRUE, -5)
if(ishuman(user))
var/mob/living/carbon/human/H = user
@@ -408,17 +409,17 @@
H.r_store = null
return
- if(src.loc == user)
+ orient2hud(user)
+ if(loc == user)
if(user.s_active)
user.s_active.close(user)
- src.show_to(user)
+ show_to(user)
else
..()
for(var/mob/M in range(1))
if(M.s_active == src)
- src.close(M)
- src.add_fingerprint(user)
- return
+ close(M)
+ add_fingerprint(user)
/obj/item/storage/attack_ghost(mob/user)
if(isobserver(user))
@@ -430,19 +431,18 @@
set name = "Switch Gathering Method"
set category = "Object"
- collection_mode = !collection_mode
- switch(collection_mode)
- if(1)
+ pickup_all_on_tile = !pickup_all_on_tile
+ switch(pickup_all_on_tile)
+ if(TRUE)
to_chat(usr, "[src] now picks up all items in a tile at once.")
- if(0)
+ if(FALSE)
to_chat(usr, "[src] now picks up one item at a time.")
-
/obj/item/storage/verb/quick_empty()
set name = "Empty Contents"
set category = "Object"
- if((!ishuman(usr) && (src.loc != usr)) || usr.stat || usr.restrained())
+ if((!ishuman(usr) && (loc != usr)) || usr.stat || usr.restrained())
return
drop_inventory(usr)
@@ -469,14 +469,14 @@
else
verbs -= /obj/item/storage/verb/toggle_gathering_mode
- boxes = new /obj/screen/storage( )
+ boxes = new /obj/screen/storage()
boxes.name = "storage"
boxes.master = src
boxes.icon_state = "block"
boxes.screen_loc = "7,7 to 10,8"
boxes.layer = HUD_LAYER
boxes.plane = HUD_PLANE
- closer = new /obj/screen/close( )
+ closer = new /obj/screen/close()
closer.master = src
closer.icon_state = "backpack_close"
closer.layer = ABOVE_HUD_LAYER
@@ -497,12 +497,12 @@
var/atom/A = i
A.emp_act(severity)
-/obj/item/storage/hear_talk(mob/living/M as mob, list/message_pieces)
+/obj/item/storage/hear_talk(mob/living/M, list/message_pieces)
..()
for(var/obj/O in contents)
O.hear_talk(M, message_pieces)
-/obj/item/storage/hear_message(mob/living/M as mob, msg)
+/obj/item/storage/hear_message(mob/living/M, msg)
..()
for(var/obj/O in contents)
O.hear_message(M, msg)
@@ -614,3 +614,24 @@
A.ex_act(severity)
CHECK_TICK
..()
+
+/obj/item/storage/proc/can_items_stack(obj/item/item_1, obj/item/item_2)
+ if(!item_1 || !item_2)
+ return
+
+ return item_1.type == item_2.type && item_1.name == item_2.name
+
+/obj/item/storage/proc/swap_items(obj/item/item_1, obj/item/item_2, mob/user = null)
+ if(!(item_1.loc == src && item_2.loc == src))
+ return
+
+ var/index_1 = contents.Find(item_1)
+ var/index_2 = contents.Find(item_2)
+
+ var/list/new_contents = contents.Copy()
+ new_contents.Swap(index_1, index_2)
+ contents = new_contents
+
+ if(user && user.s_active == src)
+ orient2hud(user)
+ show_to(user)
diff --git a/code/game/turfs/simulated/floor/asteroid.dm b/code/game/turfs/simulated/floor/asteroid.dm
index 6118885a921..d912e183aec 100644
--- a/code/game/turfs/simulated/floor/asteroid.dm
+++ b/code/game/turfs/simulated/floor/asteroid.dm
@@ -85,7 +85,7 @@
else if(istype(I, /obj/item/storage/bag/ore))
var/obj/item/storage/bag/ore/S = I
- if(S.collection_mode == 1)
+ if(S.pickup_all_on_tile)
for(var/obj/item/stack/ore/O in contents)
O.attackby(I, user)
return