diff --git a/code/modules/buildmode/buildmode.dm b/code/modules/buildmode/buildmode.dm
index 4a56257882a..735c2a4c045 100644
--- a/code/modules/buildmode/buildmode.dm
+++ b/code/modules/buildmode/buildmode.dm
@@ -34,7 +34,7 @@
holder.screen += buttons
holder.click_intercept = src
mode.enter_mode(src)
-
+
/datum/buildmode/proc/quit()
mode.exit_mode(src)
holder.screen -= buttons
@@ -100,7 +100,7 @@
else
close_switchstates()
open_modeswitch()
-
+
/datum/buildmode/proc/open_modeswitch()
switch_state = BM_SWITCHSTATE_MODE
holder.screen += modeswitch_buttons
@@ -115,7 +115,7 @@
else
close_switchstates()
open_dirswitch()
-
+
/datum/buildmode/proc/open_dirswitch()
switch_state = BM_SWITCHSTATE_DIR
holder.screen += dirswitch_buttons
@@ -155,7 +155,7 @@
new /datum/buildmode(M.client)
message_admins("[key_name_admin(usr)] has entered build mode.")
log_admin("[key_name(usr)] has entered build mode.")
-
+
#undef BM_SWITCHSTATE_NONE
#undef BM_SWITCHSTATE_MODE
#undef BM_SWITCHSTATE_DIR
diff --git a/code/modules/buildmode/submodes/delete.dm b/code/modules/buildmode/submodes/delete.dm
new file mode 100644
index 00000000000..ea2145a8dbd
--- /dev/null
+++ b/code/modules/buildmode/submodes/delete.dm
@@ -0,0 +1,62 @@
+/datum/buildmode_mode/delete
+ key = "delete"
+
+/datum/buildmode_mode/delete/show_help(client/c)
+ to_chat(c, "***********************************************************\n\
+ Left Mouse Button on anything to delete it. If you break it, you buy it.\n\
+ Right Mouse Button on anything to delete everything of the type. Probably don\'t do this unless you know what you are doing.\n\
+ ***********************************************************")
+
+/datum/buildmode_mode/delete/handle_click(client/c, params, object)
+ var/list/pa = params2list(params)
+ var/left_click = pa.Find("left")
+ var/right_click = pa.Find("right")
+
+ if(left_click)
+ if(isturf(object))
+ var/turf/T = object
+ T.ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
+ else if(isatom(object))
+ qdel(object)
+
+ if(right_click)
+ if(check_rights(R_DEBUG|R_SERVER)) //Prevents buildmoded non-admins from breaking everything.
+ if(isturf(object))
+ return
+ var/atom/deleting = object
+ var/action_type = alert("Strict type ([deleting.type]) or type and all subtypes?",,"Strict type","Type and subtypes","Cancel")
+ if(action_type == "Cancel" || !action_type)
+ return
+
+ if(alert("Are you really sure you want to delete all instances of type [deleting.type]?",,"Yes","No") != "Yes")
+ return
+
+ if(alert("Second confirmation required. Delete?",,"Yes","No") != "Yes")
+ return
+
+ var/O_type = deleting.type
+ switch(action_type)
+ if("Strict type")
+ var/i = 0
+ for(var/atom/Obj in world)
+ if(Obj.type == O_type)
+ i++
+ qdel(Obj)
+ CHECK_TICK
+ if(!i)
+ to_chat(usr, "No instances of this type exist")
+ return
+ log_admin("[key_name(usr)] deleted all instances of type [O_type] ([i] instances deleted) ")
+ message_admins("[key_name(usr)] deleted all instances of type [O_type] ([i] instances deleted) ")
+ if("Type and subtypes")
+ var/i = 0
+ for(var/Obj in world)
+ if(istype(Obj,O_type))
+ i++
+ qdel(Obj)
+ CHECK_TICK
+ if(!i)
+ to_chat(usr, "No instances of this type exist")
+ return
+ log_admin("[key_name(usr)] deleted all instances of type or subtype of [O_type] ([i] instances deleted) ")
+ message_admins("[key_name(usr)] deleted all instances of type or subtype of [O_type] ([i] instances deleted) ")
diff --git a/code/modules/buildmode/submodes/outfit.dm b/code/modules/buildmode/submodes/outfit.dm
new file mode 100644
index 00000000000..55ca0f4464d
--- /dev/null
+++ b/code/modules/buildmode/submodes/outfit.dm
@@ -0,0 +1,44 @@
+/datum/buildmode_mode/outfit
+ key = "outfit"
+ var/datum/outfit/dressuptime
+
+/datum/buildmode_mode/outfit/Destroy()
+ dressuptime = null
+ return ..()
+
+/datum/buildmode_mode/outfit/show_help(client/c)
+ to_chat(c, "***********************************************************\n\
+ Right Mouse Button on buildmode button = Select outfit to equip.\n\
+ Left Mouse Button on mob/living/carbon/human = Equip the selected outfit.\n\
+ Right Mouse Button on mob/living/carbon/human = Strip and delete current outfit.\n\
+ ***********************************************************")
+
+/datum/buildmode_mode/outfit/Reset()
+ . = ..()
+ dressuptime = null
+
+/datum/buildmode_mode/outfit/change_settings(client/c)
+ dressuptime = c.robust_dress_shop()
+
+/datum/buildmode_mode/outfit/handle_click(client/c, params, object)
+ var/list/pa = params2list(params)
+ var/left_click = pa.Find("left")
+ var/right_click = pa.Find("right")
+
+ if(!ishuman(object))
+ return
+ var/mob/living/carbon/human/dollie = object
+
+ if(left_click)
+ if(isnull(dressuptime))
+ to_chat(c, "Pick an outfit first.")
+ return
+
+ for (var/item in dollie.get_equipped_items(TRUE))
+ qdel(item)
+ if(dressuptime != "Naked")
+ dollie.equipOutfit(dressuptime)
+
+ if(right_click)
+ for (var/item in dollie.get_equipped_items(TRUE))
+ qdel(item)
diff --git a/code/modules/holodeck/area_copy.dm b/code/modules/holodeck/area_copy.dm
index 46a0fd38a6c..19a2615b731 100644
--- a/code/modules/holodeck/area_copy.dm
+++ b/code/modules/holodeck/area_copy.dm
@@ -1,7 +1,10 @@
//Vars that will not be copied when using /DuplicateObject
GLOBAL_LIST_INIT(duplicate_forbidden_vars,list(
"tag", "datum_components", "area", "type", "loc", "locs", "vars", "parent", "parent_type", "verbs", "ckey", "key",
- "power_supply", "contents", "reagents", "stat", "x", "y", "z", "group", "atmos_adjacent_turfs", "comp_lookup"
+ "power_supply", "contents", "reagents", "stat", "x", "y", "z", "group", "atmos_adjacent_turfs", "comp_lookup",
+ "client_mobs_in_contents", "bodyparts", "internal_organs", "hand_bodyparts", "overlays", "overlays_standing", "hud_list",
+ "actions", "AIStatus", "appearance", "managed_overlays", "managed_vis_overlays", "computer_id", "lastKnownIP", "implants",
+ "tgui_shared_states"
))
/proc/DuplicateObject(atom/original, perfectcopy = TRUE, sameloc, atom/newloc = null, nerf, holoitem)
@@ -20,7 +23,7 @@ GLOBAL_LIST_INIT(duplicate_forbidden_vars,list(
if(islist(original.vars[V]))
var/list/L = original.vars[V]
O.vars[V] = L.Copy()
- else if(istype(original.vars[V], /datum))
+ else if(istype(original.vars[V], /datum) || ismob(original.vars[V]))
continue // this would reference the original's object, that will break when it is used or deleted.
else
O.vars[V] = original.vars[V]
@@ -52,6 +55,11 @@ GLOBAL_LIST_INIT(duplicate_forbidden_vars,list(
contained_atom.flags_1 |= HOLOGRAM_1
if(M.circuit)
M.circuit.flags_1 |= HOLOGRAM_1
+
+ if(ismob(O)) //Overlays are carried over despite disallowing them, if a fix is found remove this.
+ var/mob/M = O
+ M.cut_overlays()
+ M.regenerate_icons()
return O
diff --git a/icons/misc/buildmode.dmi b/icons/misc/buildmode.dmi
index f0de428b6c5..fb51ad68116 100644
Binary files a/icons/misc/buildmode.dmi and b/icons/misc/buildmode.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 891ffcaa6f8..87181078c6e 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1643,8 +1643,10 @@
#include "code\modules\buildmode\submodes\basic.dm"
#include "code\modules\buildmode\submodes\boom.dm"
#include "code\modules\buildmode\submodes\copy.dm"
+#include "code\modules\buildmode\submodes\delete.dm"
#include "code\modules\buildmode\submodes\fill.dm"
#include "code\modules\buildmode\submodes\mapgen.dm"
+#include "code\modules\buildmode\submodes\outfit.dm"
#include "code\modules\buildmode\submodes\throwing.dm"
#include "code\modules\buildmode\submodes\variable_edit.dm"
#include "code\modules\cargo\bounty.dm"