diff --git a/code/datums/outfits/outfit.dm b/code/datums/outfits/outfit.dm
index 184f1155da2..0134a62d7fb 100644
--- a/code/datums/outfits/outfit.dm
+++ b/code/datums/outfits/outfit.dm
@@ -27,6 +27,8 @@
var/list/chameleon_extras //extra types for chameleon outfit changes, mostly guns
+ var/can_be_admin_equipped = TRUE // Set to FALSE if your outfit requires runtime parameters
+
/datum/outfit/proc/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
//to be overriden for customization depending on client prefs,species etc
return
@@ -159,3 +161,72 @@
types += chameleon_extras
listclearnulls(types)
return types
+
+/datum/outfit/proc/save_to_file(mob/admin)
+ var/stored_data = get_json_data()
+ var/json = json_encode(stored_data)
+ //Kinda annoying but as far as i can tell you need to make actual file.
+ var/f = file("data/TempOutfitUpload")
+ fdel(f)
+ WRITE_FILE(f,json)
+ admin << ftp(f, "[name].json")
+
+/datum/outfit/proc/load_from(list/outfit_data)
+ //This could probably use more strict validation
+ name = outfit_data["name"]
+ uniform = text2path(outfit_data["uniform"])
+ suit = text2path(outfit_data["suit"])
+ back = text2path(outfit_data["back"])
+ belt = text2path(outfit_data["belt"])
+ gloves = text2path(outfit_data["gloves"])
+ shoes = text2path(outfit_data["shoes"])
+ head = text2path(outfit_data["head"])
+ mask = text2path(outfit_data["mask"])
+ l_ear = text2path(outfit_data["l_ear"])
+ r_ear = text2path(outfit_data["r_ear"])
+ glasses = text2path(outfit_data["glasses"])
+ id = text2path(outfit_data["id"])
+ l_pocket = text2path(outfit_data["l_pocket"])
+ r_pocket = text2path(outfit_data["r_pocket"])
+ suit_store = text2path(outfit_data["suit_store"])
+ r_hand = text2path(outfit_data["r_hand"])
+ l_hand = text2path(outfit_data["l_hand"])
+ internals_slot = outfit_data["internals_slot"]
+ var/list/backpack = outfit_data["backpack_contents"]
+ backpack_contents = list()
+ for(var/item in backpack)
+ var/itype = text2path(item)
+ if(itype)
+ backpack_contents[itype] = backpack[item]
+ var/list/impl = outfit_data["implants"]
+ implants = list()
+ for(var/I in impl)
+ var/imptype = text2path(I)
+ if(imptype)
+ implants += imptype
+ return TRUE
+
+/datum/outfit/proc/get_json_data()
+ . = list()
+ .["outfit_type"] = type
+ .["name"] = name
+ .["uniform"] = uniform
+ .["suit"] = suit
+ .["back"] = back
+ .["belt"] = belt
+ .["gloves"] = gloves
+ .["shoes"] = shoes
+ .["head"] = head
+ .["mask"] = mask
+ .["l_ear"] = l_ear
+ .["r_ear"] = r_ear
+ .["glasses"] = glasses
+ .["id"] = id
+ .["l_pocket"] = l_pocket
+ .["r_pocket"] = r_pocket
+ .["suit_store"] = suit_store
+ .["r_hand"] = r_hand
+ .["l_hand"] = l_hand
+ .["internals_slot"] = internals_slot
+ .["backpack_contents"] = backpack_contents
+ .["implants"] = implants
\ No newline at end of file
diff --git a/code/datums/outfits/vv_outfit.dm b/code/datums/outfits/vv_outfit.dm
new file mode 100644
index 00000000000..5a4791eea89
--- /dev/null
+++ b/code/datums/outfits/vv_outfit.dm
@@ -0,0 +1,172 @@
+// This outfit preserves varedits made on the items
+// Created from admin helpers.
+/datum/outfit/varedit
+ var/list/vv_values
+ var/list/stored_access
+ var/update_id_name = FALSE //If the name of the human is same as the name on the id they're wearing we'll update provided id when equipping
+
+/datum/outfit/varedit/pre_equip(mob/living/carbon/human/H, visualsOnly)
+ H.delete_equipment() //Applying VV to wrong objects is not reccomended.
+ . = ..()
+
+/datum/outfit/varedit/proc/set_equipment_by_slot(slot, item_path)
+ switch(slot)
+ if(slot_w_uniform)
+ uniform = item_path
+ if(slot_back)
+ back = item_path
+ if(slot_wear_suit)
+ suit = item_path
+ if(slot_belt)
+ belt = item_path
+ if(slot_gloves)
+ gloves = item_path
+ if(slot_shoes)
+ shoes = item_path
+ if(slot_head)
+ head = item_path
+ if(slot_wear_mask)
+ mask = item_path
+ if(slot_l_ear)
+ l_ear = item_path
+ if(slot_r_ear)
+ r_ear = item_path
+ if(slot_glasses)
+ glasses = item_path
+ if(slot_wear_id)
+ id = item_path
+ if(slot_s_store)
+ suit_store = item_path
+ if(slot_l_store)
+ l_pocket = item_path
+ if(slot_r_store)
+ r_pocket = item_path
+
+
+/proc/collect_vv(obj/item/I)
+ //Temporary/Internal stuff, do not copy these.
+ var/static/list/ignored_vars = list("vars","x","y","z","plane","layer","override","animate_movement","pixel_step_size","screen_loc","fingerprintslast","tip_timer")
+
+ if(istype(I))
+ var/list/vedits = list()
+ for(var/varname in I.vars)
+ if(!I.can_vv_get(varname))
+ continue
+ if(varname in ignored_vars)
+ continue
+ var/vval = I.vars[varname]
+ //Does it even work ?
+ if(vval == initial(I.vars[varname]))
+ continue
+ //Only text/numbers and icons variables to make it less weirdness prone.
+ if(!istext(vval) && !isnum(vval) && !isicon(vval))
+ continue
+ vedits[varname] = I.vars[varname]
+ return vedits
+
+/mob/living/carbon/human/proc/copy_outfit()
+ var/datum/outfit/varedit/O = new
+
+ //Copy equipment
+ var/list/result = list()
+ var/list/slots_to_check = list(slot_w_uniform, slot_back, slot_wear_suit, slot_belt, slot_gloves, slot_shoes, slot_head, slot_wear_mask, slot_l_ear, slot_r_ear, slot_glasses, slot_wear_id, slot_s_store, slot_l_store, slot_r_store)
+ for(var/s in slots_to_check)
+ var/obj/item/I = get_item_by_slot(s)
+ var/vedits = collect_vv(I)
+ if(vedits)
+ result["[s]"] = vedits
+ if(istype(I))
+ O.set_equipment_by_slot(s, I.type)
+
+ //Copy access
+ O.stored_access = list()
+ var/obj/item/id_slot = get_item_by_slot(slot_wear_id)
+ if(id_slot)
+ O.stored_access |= id_slot.GetAccess()
+ var/obj/item/card/id/ID = id_slot.GetID()
+ if(ID && ID.registered_name == real_name)
+ O.update_id_name = TRUE
+ //Copy hands
+ if(l_hand && r_hand) //Not in the mood to let outfits transfer amputees
+ var/obj/item/left_hand = l_hand
+ var/obj/item/right_hand = r_hand
+ if(istype(left_hand))
+ O.l_hand = left_hand.type
+ var/vedits = collect_vv(left_hand)
+ if(vedits)
+ result["LHAND"] = vedits
+ if(istype(right_hand))
+ O.r_hand = right_hand.type
+ var/vedits = collect_vv(left_hand)
+ if(vedits)
+ result["RHAND"] = vedits
+ O.vv_values = result
+ //Copy backpack contents if exist.
+ var/obj/item/backpack = get_item_by_slot(slot_back)
+ if(istype(backpack) && SEND_SIGNAL(backpack, COMSIG_CONTAINS_STORAGE))
+ var/list/bp_stuff = list()
+ var/list/typecounts = list()
+ SEND_SIGNAL(backpack, COMSIG_TRY_STORAGE_RETURN_INVENTORY, bp_stuff, FALSE)
+ for(var/obj/item/I in bp_stuff)
+ if(typecounts[I.type])
+ typecounts[I.type] += 1
+ else
+ typecounts[I.type] = 1
+ O.backpack_contents = typecounts
+ //TODO : Copy varedits from backpack stuff too.
+ //Copy implants
+ O.implants = list()
+ for(var/obj/item/implant/I in contents)
+ if(istype(I))
+ O.implants |= I.type
+ //Copy to outfit cache
+ var/outfit_name = stripped_input(usr, "Enter the outfit name")
+ O.name = outfit_name
+ GLOB.custom_outfits += O
+ to_chat(usr, "Outfit registered, use select equipment to equip it.")
+
+/datum/outfit/varedit/post_equip(mob/living/carbon/human/H, visualsOnly)
+ . = ..()
+ //Apply VV
+ for(var/slot in vv_values)
+ var/list/edits = vv_values[slot]
+ var/obj/item/I
+ switch(slot)
+ if("LHAND")
+ I = H.l_hand
+ if("RHAND")
+ I = H.r_hand
+ else
+ I = H.get_item_by_slot(text2num(slot))
+ for(var/vname in edits)
+ I.vv_edit_var(vname,edits[vname])
+ //Apply access
+ var/obj/item/id_slot = H.get_item_by_slot(slot_wear_id)
+ if(id_slot)
+ var/obj/item/card/id/card = id_slot.GetID()
+ if(istype(card))
+ card.access |= stored_access
+ if(update_id_name)
+ card.registered_name = H.real_name
+ card.update_label()
+
+/datum/outfit/varedit/get_json_data()
+ . = .. ()
+ .["stored_access"] = stored_access
+ .["update_id_name"] = update_id_name
+ var/list/stripped_vv = list()
+ for(var/slot in vv_values)
+ var/list/vedits = vv_values[slot]
+ var/list/stripped_edits = list()
+ for(var/edit in vedits)
+ if(istext(vedits[edit]) || isnum(vedits[edit]) || isnull(vedits[edit]))
+ stripped_edits[edit] = vedits[edit]
+ if(stripped_edits.len)
+ stripped_vv[slot] = stripped_edits
+ .["vv_values"] = stripped_vv
+
+/datum/outfit/varedit/load_from(list/outfit_data)
+ . = ..()
+ stored_access = outfit_data["stored_access"]
+ vv_values = outfit_data["vv_values"]
+ update_id_name = outfit_data["update_id_name"]
\ No newline at end of file
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 06c2361b90a..26a38e7bad5 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -118,7 +118,8 @@ var/list/admin_verbs_event = list(
/client/proc/cmd_admin_create_centcom_report,
/client/proc/fax_panel,
/client/proc/event_manager_panel,
- /client/proc/modify_goals
+ /client/proc/modify_goals,
+ /client/proc/outfit_manager
)
var/list/admin_verbs_spawn = list(
diff --git a/code/modules/admin/outfits.dm b/code/modules/admin/outfits.dm
new file mode 100644
index 00000000000..8804c66c1c1
--- /dev/null
+++ b/code/modules/admin/outfits.dm
@@ -0,0 +1,249 @@
+GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
+
+/client/proc/outfit_manager()
+ set category = "Debug"
+ set name = "Outfit Manager"
+
+ if(!check_rights(R_DEBUG))
+ return
+ holder.outfit_manager(usr)
+
+/datum/admins/proc/outfit_manager(mob/admin)
+ var/list/dat = list("
")
+ for(var/datum/outfit/O in GLOB.custom_outfits)
+ var/vv = FALSE
+ var/datum/outfit/varedit/VO = O
+ if(istype(VO))
+ vv = length(VO.vv_values)
+ dat += "- [O.name][vv ? "(VV)" : ""]
Save Delete"
+ dat += "
"
+ dat += "Create
"
+ dat += "Load from file"
+ admin << browse(dat.Join(),"window=outfitmanager")
+
+/datum/admins/proc/save_outfit(mob/admin,datum/outfit/O)
+ O.save_to_file(admin)
+ outfit_manager(admin)
+
+/datum/admins/proc/delete_outfit(mob/admin,datum/outfit/O)
+ GLOB.custom_outfits -= O
+ qdel(O)
+ to_chat(admin,"Outfit deleted.")
+ outfit_manager(admin)
+
+/datum/admins/proc/load_outfit(mob/admin)
+ var/outfit_file = input("Pick outfit json file:", "File") as null|file
+ if(!outfit_file)
+ return
+ var/filedata = file2text(outfit_file)
+ var/json = json_decode(filedata)
+ if(!json)
+ to_chat(admin,"JSON decode error.")
+ return
+ var/otype = text2path(json["outfit_type"])
+ if(!ispath(otype,/datum/outfit))
+ to_chat(admin,"Malformed/Outdated file.")
+ return
+ var/datum/outfit/O = new otype
+ if(!O.load_from(json))
+ to_chat(admin,"Malformed/Outdated file.")
+ return
+ GLOB.custom_outfits += O
+ outfit_manager(admin)
+
+/datum/admins/proc/create_outfit(mob/admin)
+ var/list/uniforms = typesof(/obj/item/clothing/under)
+ var/list/suits = typesof(/obj/item/clothing/suit)
+ var/list/gloves = typesof(/obj/item/clothing/gloves)
+ var/list/shoes = typesof(/obj/item/clothing/shoes)
+ var/list/headwear = typesof(/obj/item/clothing/head)
+ var/list/glasses = typesof(/obj/item/clothing/glasses)
+ var/list/masks = typesof(/obj/item/clothing/mask)
+ var/list/ids = typesof(/obj/item/card/id)
+
+ var/uniform_select = ""
+
+ var/suit_select = ""
+
+ var/gloves_select = ""
+
+ var/shoes_select = ""
+
+ var/head_select = ""
+
+ var/glasses_select = ""
+
+ var/mask_select = ""
+
+ var/id_select = ""
+
+ var/dat = {"
+ Create Outfit
+
+ "}
+ admin << browse(dat, "window=dressup;size=550x600")
+
+
+/datum/admins/proc/create_outfit_finalize(mob/admin, list/href_list)
+ var/datum/outfit/O = new
+
+ O.name = href_list["outfit_name"]
+ O.uniform = text2path(href_list["outfit_uniform"])
+ O.shoes = text2path(href_list["outfit_shoes"])
+ O.gloves = text2path(href_list["outfit_gloves"])
+ O.suit = text2path(href_list["outfit_suit"])
+ O.head = text2path(href_list["outfit_head"])
+ O.back = text2path(href_list["outfit_back"])
+ O.mask = text2path(href_list["outfit_mask"])
+ O.glasses = text2path(href_list["outfit_glasses"])
+ O.r_hand = text2path(href_list["outfit_r_hand"])
+ O.l_hand = text2path(href_list["outfit_l_hand"])
+ O.suit_store = text2path(href_list["outfit_s_store"])
+ O.l_pocket = text2path(href_list["outfit_l_pocket"])
+ O.r_pocket = text2path(href_list["outfit_r_pocket"])
+ O.id = text2path(href_list["outfit_id"])
+ O.belt = text2path(href_list["outfit_belt"])
+ O.l_ear = text2path(href_list["outfit_l_ear"])
+ O.r_ear = text2path(href_list["outfit_r_ear"])
+
+ GLOB.custom_outfits.Add(O)
+ message_admins("[key_name(usr)] created \"[O.name]\" outfit!")
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 224f07d4277..7f0660332fb 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -333,9 +333,6 @@
if("Cancel") return
if("Yes") delmob = 1
- log_admin("[key_name(usr)] has used rudimentary transformation on [key_name(M)]. Transforming to [href_list["simplemake"]]; deletemob=[delmob]")
- message_admins("[key_name_admin(usr)] has used rudimentary transformation on [key_name_admin(M)]. Transforming to [href_list["simplemake"]]; deletemob=[delmob]", 1)
-
switch(href_list["simplemake"])
if("observer") M.change_mob_type( /mob/dead/observer , null, null, delmob, 1 )
if("drone") M.change_mob_type( /mob/living/carbon/alien/humanoid/drone , null, null, delmob, 1 )
@@ -343,7 +340,11 @@
if("queen") M.change_mob_type( /mob/living/carbon/alien/humanoid/queen/large , null, null, delmob, 1 )
if("sentinel") M.change_mob_type( /mob/living/carbon/alien/humanoid/sentinel , null, null, delmob, 1 )
if("larva") M.change_mob_type( /mob/living/carbon/alien/larva , null, null, delmob, 1 )
- if("human") M.change_mob_type( /mob/living/carbon/human, null, null, delmob, 1 )
+ if("human")
+ var/posttransformoutfit = usr.client.robust_dress_shop()
+ var/mob/living/carbon/human/newmob = M.change_mob_type(/mob/living/carbon/human, null, null, delmob, 1)
+ if(posttransformoutfit && istype(newmob))
+ newmob.equipOutfit(posttransformoutfit)
if("slime") M.change_mob_type( /mob/living/carbon/slime , null, null, delmob, 1 )
if("monkey") M.change_mob_type( /mob/living/carbon/human/monkey , null, null, delmob, 1 )
if("robot") M.change_mob_type( /mob/living/silicon/robot , null, null, delmob, 1 )
@@ -360,6 +361,9 @@
if("constructwraith") M.change_mob_type( /mob/living/simple_animal/hostile/construct/wraith , null, null, delmob, 1 )
if("shade") M.change_mob_type( /mob/living/simple_animal/shade , null, null, delmob, 1 )
+ log_admin("[key_name(usr)] has used rudimentary transformation on [key_name(M)]. Transforming to [href_list["simplemake"]]; deletemob=[delmob]")
+ message_admins("[key_name_admin(usr)] has used rudimentary transformation on [key_name_admin(M)]. Transforming to [href_list["simplemake"]]; deletemob=[delmob]", 1)
+
/////////////////////////////////////new ban stuff
else if(href_list["unbanf"])
@@ -1502,14 +1506,22 @@
usr.client.cmd_admin_animalize(M)
else if(href_list["incarn_ghost"])
- if(!check_rights(R_SPAWN)) return
+ if(!check_rights(R_SPAWN))
+ return
var/mob/dead/observer/G = locateUID(href_list["incarn_ghost"])
if(!istype(G))
to_chat(usr, "This will only work on /mob/dead/observer")
- log_admin("[key_name(G)] was incarnated by [key_name(src.owner)]")
- message_admins("[key_name_admin(G)] was incarnated by [key_name_admin(src.owner)]")
- G.incarnate_ghost()
+
+ var/posttransformoutfit = usr.client.robust_dress_shop()
+
+ var/mob/living/carbon/human/H = G.incarnate_ghost()
+
+ if(posttransformoutfit && istype(H))
+ H.equipOutfit(posttransformoutfit)
+
+ log_admin("[key_name(G)] was incarnated by [key_name(owner)]")
+ message_admins("[key_name_admin(G)] was incarnated by [key_name_admin(owner)]")
else if(href_list["togmutate"])
if(!check_rights(R_SPAWN)) return
@@ -3360,6 +3372,29 @@
message_admins("[key_name_admin(usr)] forcefully unlinked the discord account belonging to [target_ckey]")
log_admin("[key_name_admin(usr)] forcefully unlinked the discord account belonging to [target_ckey]")
+ else if(href_list["create_outfit_finalize"])
+ if(!check_rights(R_ADMIN))
+ return
+ create_outfit_finalize(usr,href_list)
+ else if(href_list["load_outfit"])
+ if(!check_rights(R_ADMIN))
+ return
+ load_outfit(usr)
+ else if(href_list["create_outfit_menu"])
+ if(!check_rights(R_ADMIN))
+ return
+ create_outfit(usr)
+ else if(href_list["delete_outfit"])
+ if(!check_rights(R_ADMIN))
+ return
+ var/datum/outfit/O = locate(href_list["chosen_outfit"]) in GLOB.custom_outfits
+ delete_outfit(usr,O)
+ else if(href_list["save_outfit"])
+ if(!check_rights(R_ADMIN))
+ return
+ var/datum/outfit/O = locate(href_list["chosen_outfit"]) in GLOB.custom_outfits
+ save_outfit(usr,O)
+
/client/proc/create_eventmob_for(var/mob/living/carbon/human/H, var/killthem = 0)
if(!check_rights(R_EVENT))
return
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 6a419ebb29a..00f106e7870 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -576,109 +576,79 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_EVENT))
return
- if(!ishuman(M))
+ if(!ishuman(M) || !isobserver(M))
alert("Invalid mob")
return
- var/list/choices = list(
- "strip",
- "as job...",
- "emergency response team member",
- "emergency response team leader"
+ var/dresscode = robust_dress_shop()
+
+ if(!dresscode)
+ return
+
+ var/delete_pocket
+ var/mob/living/carbon/human/H
+ if(isobserver(M))
+ H = M.change_mob_type(/mob/living/carbon/human, null, null, TRUE)
+ else
+ H = M
+ if(H.l_store || H.r_store || H.s_store) //saves a lot of time for admins and coders alike
+ if(alert("Should the items in their pockets be dropped? Selecting \"No\" will delete them.", "Robust quick dress shop", "Yes", "No") == "No")
+ delete_pocket = TRUE
+
+ for (var/obj/item/I in H.get_equipped_items(delete_pocket))
+ qdel(I)
+ if(dresscode != "Naked")
+ H.equipOutfit(dresscode)
+
+ H.regenerate_icons()
+
+ feedback_add_details("admin_verb", "SE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ log_admin("[key_name(usr)] changed the equipment of [key_name(M)] to [dresscode].")
+ message_admins("[key_name_admin(usr)] changed the equipment of [key_name_admin(M)] to [dresscode].", 1)
+
+/client/proc/robust_dress_shop()
+ var/list/outfits = list(
+ "Naked",
+ "As Job...",
+ "Custom..."
)
- var/admin_outfits = subtypesof(/datum/outfit/admin)
- for(var/type in admin_outfits)
- var/datum/outfit/O = type
- var/name = initial(O.name)
- if(name != "Naked")
- choices[initial(O.name)] = type
+ var/list/paths = subtypesof(/datum/outfit) - typesof(/datum/outfit/job)
+ for(var/path in paths)
+ var/datum/outfit/O = path //not much to initalize here but whatever
+ if(initial(O.can_be_admin_equipped))
+ outfits[initial(O.name)] = path
- var/dostrip = 0
- switch(alert("Strip [M] before dressing?", "Strip?", "Yes", "No", "Cancel"))
- if("Yes")
- dostrip = 1
- if("Cancel")
- return
-
- var/dresscode = input("Select dress for [M]", "Robust quick dress shop") as null|anything in choices
+ var/dresscode = input("Select outfit", "Robust quick dress shop") as null|anything in outfits
if(isnull(dresscode))
return
- var/datum/outfit/O
- if(!(dresscode in list("strip", "as job...", "emergency response team member", "emergency response team leader")))
- O = choices[dresscode]
+ if(outfits[dresscode])
+ dresscode = outfits[dresscode]
- var/datum/job/jobdatum
- if(dresscode == "as job...")
- var/jobname = input("Select job", "Robust quick dress shop") as null|anything in get_all_jobs()
- jobdatum = SSjobs.GetJob(jobname)
+ if(dresscode == "As Job...")
+ var/list/job_paths = subtypesof(/datum/outfit/job)
+ var/list/job_outfits = list()
+ for(var/path in job_paths)
+ var/datum/outfit/O = path
+ if(initial(O.can_be_admin_equipped))
+ job_outfits[initial(O.name)] = path
- feedback_add_details("admin_verb", "SEQ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
- if(dostrip)
- for(var/obj/item/I in M)
- if(istype(I, /obj/item/implant))
- continue
- if(istype(I, /obj/item/organ))
- continue
- qdel(I)
+ dresscode = input("Select job equipment", "Robust quick dress shop") as null|anything in job_outfits
+ dresscode = job_outfits[dresscode]
+ if(isnull(dresscode))
+ return
+ if(dresscode == "Custom...")
+ var/list/custom_names = list()
+ for(var/datum/outfit/D in GLOB.custom_outfits)
+ custom_names[D.name] = D
+ var/selected_name = input("Select outfit", "Robust quick dress shop") as null|anything in custom_names
+ dresscode = custom_names[selected_name]
+ if(isnull(dresscode))
+ return
- switch(dresscode)
- if("strip")
- //do nothing
-
- // god is dead
- if("as job...")
- if(jobdatum)
- dresscode = "[jobdatum.title]"
- jobdatum.equip(M)
-
- if("emergency response team member", "emergency response team leader")
- var/datum/response_team/equip_team = null
- switch(alert("Level", "Emergency Response Team", "Amber", "Red", "Gamma"))
- if("Amber")
- equip_team = new /datum/response_team/amber
- if("Red")
- equip_team = new /datum/response_team/red
- if("Gamma")
- equip_team = new /datum/response_team/gamma
- if(!equip_team)
- return
- if(dresscode == "emergency response team leader")
- equip_team.equip_officer("Commander", M)
- else
- var/list/ert_outfits = list("Security", "Engineer", "Medic", "Janitor", "Paranormal")
- var/echoice = input("Loadout Type", "Emergency Response Team") as null|anything in ert_outfits
- if(!echoice)
- return
- switch(echoice)
- if("Commander")
- equip_team.equip_officer("Commander", M)
- if("Security")
- equip_team.equip_officer("Security", M)
- if("Engineer")
- equip_team.equip_officer("Engineer", M)
- if("Medic")
- equip_team.equip_officer("Medic", M)
- if("Janitor")
- equip_team.equip_officer("Janitor", M)
- if("Paranormal")
- equip_team.equip_officer("Paranormal", M)
- else
- to_chat(src, "Invalid ERT Loadout selected")
-
-
- else // outfit datum
- if(O)
- M.equipOutfit(O, FALSE)
-
- M.regenerate_icons()
-
- log_admin("[key_name(usr)] changed the equipment of [key_name(M)] to [dresscode].")
- message_admins("[key_name_admin(usr)] changed the equipment of [key_name_admin(M)] to [dresscode].", 1)
- return
-
+ return dresscode
/client/proc/startSinglo()
set category = "Debug"
diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm
index 0a0a2e45abd..d337ddee67d 100644
--- a/code/modules/clothing/chameleon.dm
+++ b/code/modules/clothing/chameleon.dm
@@ -15,7 +15,8 @@
standard_outfit_options = list()
for(var/path in subtypesof(/datum/outfit/job))
var/datum/outfit/O = path
- standard_outfit_options[initial(O.name)] = path
+ if(initial(O.can_be_admin_equipped))
+ standard_outfit_options[initial(O.name)] = path
sortTim(standard_outfit_options, /proc/cmp_text_asc)
outfit_options = standard_outfit_options
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index c8c7d5c32e3..b1ae3acc7ce 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -766,14 +766,17 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/proc/incarnate_ghost()
if(!client)
return
+
var/mob/living/carbon/human/new_char = new(get_turf(src))
client.prefs.copy_to(new_char)
if(mind)
- mind.active = 1
+ mind.active = TRUE
mind.transfer_to(new_char)
else
new_char.key = key
+ return new_char
+
/mob/dead/observer/is_literate()
return TRUE
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index 47dd5622379..64ea9c9eb11 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -575,3 +575,10 @@
return 0
return O.equip(src, visualsOnly)
+
+//delete all equipment without dropping anything
+/mob/living/carbon/human/proc/delete_equipment()
+ for(var/slot in get_all_slots())//order matters, dependant slots go first
+ qdel(slot)
+ for(var/obj/item/I in l_hand, r_hand)
+ qdel(I)
diff --git a/code/modules/response_team/ert.dm b/code/modules/response_team/ert.dm
index cdc81a9e759..222d92583b1 100644
--- a/code/modules/response_team/ert.dm
+++ b/code/modules/response_team/ert.dm
@@ -240,32 +240,21 @@ var/ert_request_answered = FALSE
switch(officer_type)
if("Engineer")
M.equipOutfit(engineering_outfit)
- M.job = "ERT Engineering"
if("Security")
M.equipOutfit(security_outfit)
- M.job = "ERT Security"
if("Medic")
M.equipOutfit(medical_outfit)
- M.job = "ERT Medical"
if("Janitor")
M.equipOutfit(janitor_outfit)
- M.job = "ERT Janitor"
if("Paranormal")
M.equipOutfit(paranormal_outfit)
- M.job = "ERT Paranormal"
- M.mind.isholy = TRUE
if("Commander")
- // Override name and age for the commander
- M.rename_character(null, "[pick("Lieutenant", "Captain", "Major")] [pick(GLOB.last_names)]")
- M.age = rand(35,45)
-
M.equipOutfit(command_outfit)
- M.job = "ERT Commander"
/datum/response_team/proc/cannot_send_team()
event_announcement.Announce("[station_name()], we are unfortunately unable to send you an Emergency Response Team at this time.", "ERT Unavailable")
@@ -317,6 +306,7 @@ var/ert_request_answered = FALSE
name = "Response team"
var/rt_assignment = "Emergency Response Team Member"
var/rt_job = "This is a bug"
+ var/rt_mob_job = "This is a bug" // The job set on the actual mob.
allow_backbag_choice = FALSE
allow_loadout = FALSE
pda = /obj/item/pda/heads/ert
diff --git a/code/modules/response_team/ert_outfits.dm b/code/modules/response_team/ert_outfits.dm
index b287643901d..93b87e7d1ec 100644
--- a/code/modules/response_team/ert_outfits.dm
+++ b/code/modules/response_team/ert_outfits.dm
@@ -23,6 +23,10 @@
PDA.ownrank = rt_assignment
PDA.name = "PDA-[H.real_name] ([PDA.ownjob])"
+/datum/outfit/job/centcom/response_team/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
+ . = ..()
+
+ H.job = rt_mob_job
//////////////////// COMMANDER ///////////////////
@@ -30,6 +34,7 @@
name = "RT Commander"
rt_assignment = "Emergency Response Team Leader"
rt_job = "Emergency Response Team Leader"
+ rt_mob_job = "ERT Commander"
uniform = /obj/item/clothing/under/rank/centcom_officer
back = /obj/item/storage/backpack/ert/commander
@@ -39,6 +44,12 @@
l_pocket = /obj/item/pinpointer
r_pocket = /obj/item/melee/classic_baton/telescopic
+/datum/outfit/job/centcom/response_team/commander/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
+ . = ..()
+
+ H.rename_character(null, "[pick("Lieutenant", "Captain", "Major")] [pick(GLOB.last_names)]")
+ H.age = rand(35,45)
+
/datum/outfit/job/centcom/response_team/commander/amber
name = "RT Commander (Amber)"
shoes = /obj/item/clothing/shoes/combat
@@ -107,6 +118,7 @@
/datum/outfit/job/centcom/response_team/security
name = "RT Security"
rt_job = "Emergency Response Team Officer"
+ rt_mob_job = "ERT Security"
uniform = /obj/item/clothing/under/rank/security
back = /obj/item/storage/backpack/ert/security
belt = /obj/item/storage/belt/security/response_team
@@ -194,6 +206,7 @@
/datum/outfit/job/centcom/response_team/engineer
name = "RT Engineer"
rt_job = "Emergency Response Team Engineer"
+ rt_mob_job = "ERT Engineering"
back = /obj/item/storage/backpack/ert/engineer
uniform = /obj/item/clothing/under/rank/engineer
@@ -276,6 +289,7 @@
/datum/outfit/job/centcom/response_team/medic
name = "RT Medic"
rt_job = "Emergency Response Team Medic"
+ rt_mob_job = "ERT Medical"
uniform = /obj/item/clothing/under/rank/medical
back = /obj/item/storage/backpack/ert/medical
pda = /obj/item/pda/heads/ert/medical
@@ -312,6 +326,7 @@
/datum/outfit/job/centcom/response_team/medic/red
name = "RT Medic (Red)"
+ rt_mob_job = "ERT Medical"
shoes = /obj/item/clothing/shoes/white
gloves = /obj/item/clothing/gloves/color/latex/nitrile
suit = /obj/item/clothing/suit/space/hardsuit/ert/medical
@@ -377,6 +392,7 @@
/datum/outfit/job/centcom/response_team/paranormal
name = "RT Paranormal"
rt_job = "Emergency Response Team Inquisitor"
+ rt_mob_job = "ERT Paranormal"
uniform = /obj/item/clothing/under/rank/chaplain
back = /obj/item/storage/backpack/ert/security
gloves = /obj/item/clothing/gloves/color/black
@@ -392,6 +408,11 @@
/obj/item/flashlight/seclite = 1
)
+/datum/outfit/job/centcom/response_team/paranormal/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
+ . = ..()
+ if(H.mind)
+ H.mind.isholy = TRUE
+
/datum/outfit/job/centcom/response_team/paranormal/amber
name = "RT Paranormal (Amber)"
suit = /obj/item/clothing/suit/armor/vest/ert/security/paranormal
@@ -433,6 +454,7 @@
/datum/outfit/job/centcom/response_team/janitorial
name = "RT Janitor"
rt_job = "Emergency Response Team Janitor"
+ rt_mob_job = "ERT Janitor"
uniform = /obj/item/clothing/under/color/purple
back = /obj/item/storage/backpack/ert/janitor
belt = /obj/item/storage/belt/janitor/full
diff --git a/code/modules/vr/vr_outfits.dm b/code/modules/vr/vr_outfits.dm
index ce8d52b4880..e61ea829b27 100644
--- a/code/modules/vr/vr_outfits.dm
+++ b/code/modules/vr/vr_outfits.dm
@@ -1,12 +1,12 @@
//place all the outfits for your levels in here.
/datum/outfit/vr/vr_basic
- name = "basic vr"
+ name = "Basic Virtual Reality"
uniform = /obj/item/clothing/under/psysuit
shoes = /obj/item/clothing/shoes/black
/datum/outfit/vr/roman
- name = "roman"
+ name = "Roman"
uniform = /obj/item/clothing/under/roman
shoes = /obj/item/clothing/shoes/roman
l_hand = /obj/item/shield/riot/roman
diff --git a/paradise.dme b/paradise.dme
index c49361b8e20..cad5f6ab907 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -346,6 +346,7 @@
#include "code\datums\looping_sounds\weather.dm"
#include "code\datums\outfits\outfit.dm"
#include "code\datums\outfits\outfit_admin.dm"
+#include "code\datums\outfits\vv_outfit.dm"
#include "code\datums\ruins\lavaland.dm"
#include "code\datums\ruins\space.dm"
#include "code\datums\spells\area_teleport.dm"
@@ -1151,6 +1152,7 @@
#include "code\modules\admin\IsBanned.dm"
#include "code\modules\admin\machine_upgrade.dm"
#include "code\modules\admin\NewBan.dm"
+#include "code\modules\admin\outfits.dm"
#include "code\modules\admin\player_panel.dm"
#include "code\modules\admin\secrets.dm"
#include "code\modules\admin\sql_notes.dm"