mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-01 12:31:32 +00:00
Converts most spans into span procs. Mostly used regex for this and sorted out any compile time errors afterwards so there could be some bugs. Was initially going to do defines, but ninja said to make it into a proc, and if there's any overhead, they can easily be changed to defines. Makes it easier to control the formatting and prevents typos when creating spans as it'll runtime if you misspell instead of silently failing. Reduces the code you need to write when writing spans, as you don't need to close the span as that's automatically handled by the proc. (Note from Lemon: This should be converted to defines once we update the minimum version to 514. Didn't do it now because byond pain and such)
227 lines
7.7 KiB
Plaintext
227 lines
7.7 KiB
Plaintext
/client/proc/cmd_select_equipment(mob/target in GLOB.mob_list)
|
|
set category = "Admin.Events"
|
|
set name = "Select equipment"
|
|
|
|
|
|
var/datum/select_equipment/ui = new(usr, target)
|
|
ui.ui_interact(usr)
|
|
|
|
/*
|
|
* This is the datum housing the select equipment UI.
|
|
*
|
|
* You may notice some oddities about the way outfits are passed to the UI and vice versa here.
|
|
* That's because it handles both outfit typepaths (for normal outfits) *and* outfit objects (for custom outfits).
|
|
*
|
|
* Custom outfits need to be objects as they're created in runtime.
|
|
* "Then just handle the normal outfits as objects too and simplify the handling" - you may say.
|
|
* There are about 300 outfit types at the time of writing this. Initializing all of these to objects would be a huge waste.
|
|
*
|
|
*/
|
|
|
|
/datum/select_equipment
|
|
var/client/user
|
|
var/mob/target_mob
|
|
|
|
var/dummy_key
|
|
|
|
//static list to share all the outfit typepaths between all instances of this datum.
|
|
var/static/list/cached_outfits
|
|
|
|
//a typepath if the selected outfit is a normal outfit;
|
|
//an object if the selected outfit is a custom outfit
|
|
var/datum/outfit/selected_outfit = /datum/outfit
|
|
//serializable string for the UI to keep track of which outfit is selected
|
|
var/selected_identifier = "/datum/outfit"
|
|
|
|
/datum/select_equipment/New(_user, mob/target)
|
|
user = CLIENT_FROM_VAR(_user)
|
|
|
|
if(!ishuman(target) && !isobserver(target))
|
|
tgui_alert(usr,"Invalid mob")
|
|
return
|
|
target_mob = target
|
|
|
|
/datum/select_equipment/ui_interact(mob/user, datum/tgui/ui)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "SelectEquipment", "Select Equipment")
|
|
ui.open()
|
|
ui.set_autoupdate(FALSE)
|
|
|
|
/datum/select_equipment/ui_state(mob/user)
|
|
return GLOB.admin_state
|
|
|
|
/datum/select_equipment/ui_status(mob/user, datum/ui_state/state)
|
|
if(QDELETED(target_mob))
|
|
return UI_CLOSE
|
|
return ..()
|
|
|
|
/datum/select_equipment/ui_close(mob/user)
|
|
clear_human_dummy(dummy_key)
|
|
qdel(src)
|
|
|
|
/datum/select_equipment/proc/init_dummy()
|
|
dummy_key = "selectequipmentUI_[target_mob]"
|
|
generate_dummy_lookalike(dummy_key, target_mob)
|
|
unset_busy_human_dummy(dummy_key)
|
|
return
|
|
|
|
/**
|
|
* Packs up data about an outfit as an assoc list to send to the UI as an outfit entry.
|
|
*
|
|
* Args:
|
|
* * category (string) - The tab it will be under
|
|
*
|
|
* * identifier (typepath or ref) - This will sent this back to ui_act to preview or spawn in an outfit.
|
|
* * Must be unique between all entries.
|
|
*
|
|
* * name (string) - Will be the text on the button
|
|
*
|
|
* * priority (bool)(optional) - If True, the UI will sort the entry to the top, right below favorites.
|
|
*
|
|
* * custom_entry (bool)(optional) - Send the identifier with a "ref" keyword instead of "path",
|
|
* * for the UI to tell apart custom outfits from normal ones.
|
|
*
|
|
* Returns (list) An outfit entry
|
|
*/
|
|
|
|
/datum/select_equipment/proc/outfit_entry(category, identifier, name, priority=FALSE, custom_entry=FALSE)
|
|
if(custom_entry)
|
|
return list("category" = category, "ref" = identifier, "name" = name, "priority" = priority)
|
|
return list("category" = category, "path" = identifier, "name" = name, "priority" = priority)
|
|
|
|
/datum/select_equipment/proc/make_outfit_entries(category="General", list/outfit_list)
|
|
var/list/entries = list()
|
|
for(var/path as anything in outfit_list)
|
|
var/datum/outfit/outfit = path
|
|
entries += list(outfit_entry(category, path, initial(outfit.name)))
|
|
return entries
|
|
|
|
//GLOB.custom_outfits lists outfit *objects* so we'll need to do some custom handling for it
|
|
/datum/select_equipment/proc/make_custom_outfit_entries(list/outfit_list)
|
|
var/list/entries = list()
|
|
for(var/datum/outfit/outfit as anything in outfit_list)
|
|
entries += list(outfit_entry("Custom", REF(outfit), outfit.name, custom_entry=TRUE)) //it's either this or special handling on the UI side
|
|
return entries
|
|
|
|
/datum/select_equipment/ui_data(mob/user)
|
|
var/list/data = list()
|
|
if(!dummy_key)
|
|
init_dummy()
|
|
|
|
var/icon/dummysprite = get_flat_human_icon(null,
|
|
dummy_key = dummy_key,
|
|
outfit_override = selected_outfit)
|
|
data["icon64"] = icon2base64(dummysprite)
|
|
data["name"] = target_mob
|
|
|
|
var/datum/preferences/prefs = user?.client?.prefs
|
|
data["favorites"] = list()
|
|
if(prefs)
|
|
data["favorites"] = prefs.favorite_outfits
|
|
|
|
var/list/custom
|
|
custom += make_custom_outfit_entries(GLOB.custom_outfits)
|
|
data["custom_outfits"] = custom
|
|
data["current_outfit"] = selected_identifier
|
|
return data
|
|
|
|
|
|
/datum/select_equipment/ui_static_data(mob/user)
|
|
var/list/data = list()
|
|
if(!cached_outfits)
|
|
cached_outfits = list()
|
|
cached_outfits += list(outfit_entry("General", /datum/outfit, "Naked", priority=TRUE))
|
|
cached_outfits += make_outfit_entries("General", subtypesof(/datum/outfit) - typesof(/datum/outfit/job) - typesof(/datum/outfit/plasmaman))
|
|
cached_outfits += make_outfit_entries("Jobs", typesof(/datum/outfit/job))
|
|
cached_outfits += make_outfit_entries("Plasmamen Outfits", typesof(/datum/outfit/plasmaman))
|
|
|
|
data["outfits"] = cached_outfits
|
|
return data
|
|
|
|
|
|
/datum/select_equipment/proc/resolve_outfit(text)
|
|
|
|
var/path = text2path(text)
|
|
if(ispath(path, /datum/outfit))
|
|
return path
|
|
|
|
else //don't bail yet - could be a custom outfit
|
|
var/datum/outfit/custom_outfit = locate(text)
|
|
if(istype(custom_outfit))
|
|
return custom_outfit
|
|
|
|
|
|
/datum/select_equipment/ui_act(action, params)
|
|
if(..())
|
|
return
|
|
. = TRUE
|
|
switch(action)
|
|
if("preview")
|
|
var/datum/outfit/new_outfit = resolve_outfit(params["path"])
|
|
|
|
if(ispath(new_outfit)) //got a typepath - that means we're dealing with a normal outfit
|
|
selected_identifier = new_outfit //these are keyed by type
|
|
//by the way, no, they can't be keyed by name because many of them have duplicate names
|
|
|
|
else if(istype(new_outfit)) //got an initialized object - means it's a custom outfit
|
|
selected_identifier = REF(new_outfit) //and the outfit will be keyed by its ref (cause its type will always be /datum/outfit)
|
|
|
|
else //we got nothing and should bail
|
|
return
|
|
|
|
selected_outfit = new_outfit
|
|
|
|
if("applyoutfit")
|
|
var/datum/outfit/new_outfit = resolve_outfit(params["path"])
|
|
if(new_outfit && ispath(new_outfit)) //initialize it
|
|
new_outfit = new new_outfit
|
|
if(!istype(new_outfit))
|
|
return
|
|
user.admin_apply_outfit(target_mob, new_outfit)
|
|
|
|
if("customoutfit")
|
|
user.outfit_manager()
|
|
|
|
if("togglefavorite")
|
|
var/datum/outfit/outfit_path = resolve_outfit(params["path"])
|
|
if(!ispath(outfit_path)) //we do *not* want custom outfits (i.e objects) here, they're not even persistent
|
|
return
|
|
|
|
if(user.prefs.favorite_outfits.Find(outfit_path)) //already there, remove it
|
|
user.prefs.favorite_outfits -= outfit_path
|
|
else //not there, add it
|
|
user.prefs.favorite_outfits += outfit_path
|
|
user.prefs.save_preferences()
|
|
|
|
/client/proc/admin_apply_outfit(mob/target, dresscode)
|
|
if(!ishuman(target) && !isobserver(target))
|
|
tgui_alert(usr,"Invalid mob")
|
|
return
|
|
|
|
if(!dresscode)
|
|
return
|
|
|
|
var/delete_pocket
|
|
var/mob/living/carbon/human/human_target
|
|
if(isobserver(target))
|
|
human_target = target.change_mob_type(/mob/living/carbon/human, delete_old_mob = TRUE)
|
|
else
|
|
human_target = target
|
|
if(human_target.l_store || human_target.r_store || human_target.s_store) //saves a lot of time for admins and coders alike
|
|
if(tgui_alert(usr,"Drop Items in Pockets? No will delete them.", "Robust quick dress shop", list("Yes", "No")) == "No")
|
|
delete_pocket = TRUE
|
|
|
|
SSblackbox.record_feedback("tally", "admin_verb", 1, "Select Equipment") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
|
for(var/obj/item/item in human_target.get_equipped_items(delete_pocket))
|
|
qdel(item)
|
|
if(dresscode != "Naked")
|
|
human_target.equipOutfit(dresscode)
|
|
|
|
human_target.regenerate_icons()
|
|
|
|
log_admin("[key_name(usr)] changed the equipment of [key_name(human_target)] to [dresscode].")
|
|
message_admins(span_adminnotice("[key_name_admin(usr)] changed the equipment of [ADMIN_LOOKUPFLW(human_target)] to [dresscode]."))
|
|
|
|
return dresscode
|