mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2026-08-31 00:59:16 +01:00
TGUI Medical Conversion
This commit is contained in:
@@ -0,0 +1,370 @@
|
||||
/**
|
||||
* tgui modals
|
||||
*
|
||||
* Allows creation of modals within tgui.
|
||||
*/
|
||||
|
||||
GLOBAL_LIST(tgui_modals)
|
||||
|
||||
/**
|
||||
* Call this from a proc that is called in tgui_act() to process modal actions
|
||||
*
|
||||
* Example: /obj/machinery/chem_master/proc/tgui_act_modal
|
||||
* You can then switch based on the return value and show different
|
||||
* modals depending on the answer.
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * action - The called action
|
||||
* * params - The params to the action
|
||||
*/
|
||||
/datum/proc/tgui_modal_act(datum/source = src, action = "", params)
|
||||
ASSERT(istype(source))
|
||||
|
||||
. = null
|
||||
switch(action)
|
||||
if("modal_open") // Params: id, arguments
|
||||
return TGUI_MODAL_OPEN
|
||||
if("modal_answer") // Params: id, answer, arguments
|
||||
params["answer"] = tgui_modal_preprocess_answer(source, params["answer"])
|
||||
if(tgui_modal_answer(source, params["id"], params["answer"])) // If there's a current modal with a delegate that returned TRUE, no need to continue
|
||||
. = TGUI_MODAL_DELEGATE
|
||||
else
|
||||
. = TGUI_MODAL_ANSWER
|
||||
tgui_modal_clear(source)
|
||||
if("modal_close") // Params: id
|
||||
tgui_modal_clear(source)
|
||||
return TGUI_MODAL_CLOSE
|
||||
|
||||
/**
|
||||
* Call this from tgui_data() to return modal information if needed
|
||||
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
*/
|
||||
/datum/proc/tgui_modal_data(datum/source = src)
|
||||
ASSERT(istype(source))
|
||||
|
||||
var/datum/tgui_modal/current = LAZYACCESS(GLOB.tgui_modals, REF(source))
|
||||
if(!current)
|
||||
return null
|
||||
|
||||
return current.to_data()
|
||||
|
||||
/**
|
||||
* Clears the current modal for a given datum
|
||||
*
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
*/
|
||||
/datum/proc/tgui_modal_clear(datum/source = src)
|
||||
ASSERT(istype(source))
|
||||
|
||||
LAZYINITLIST(GLOB.tgui_modals)
|
||||
var/datum/tgui_modal/previous = GLOB.tgui_modals[REF(source)]
|
||||
if(!previous)
|
||||
return FALSE
|
||||
|
||||
for(var/i in 1 to length(GLOB.tgui_modals))
|
||||
var/key = GLOB.tgui_modals[i]
|
||||
if(previous == GLOB.tgui_modals[key])
|
||||
GLOB.tgui_modals.Cut(i, i + 1)
|
||||
break
|
||||
|
||||
SStgui.update_uis(source)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Opens a message TGUI modal
|
||||
*
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * id - The ID of the modal
|
||||
* * text - The text to display above the answers
|
||||
* * delegate - The proc to call when closed
|
||||
* * arguments - List of arguments passed to and from JS (mostly useful for chaining modals)
|
||||
*/
|
||||
/datum/proc/tgui_modal_message(datum/source = src, id, text = "Default modal message", delegate, arguments)
|
||||
ASSERT(length(id))
|
||||
|
||||
var/datum/tgui_modal/modal = new(id, text, delegate, arguments)
|
||||
return tgui_modal_new(source, modal)
|
||||
|
||||
/**
|
||||
* Opens a text input TGUI modal
|
||||
*
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * id - The ID of the modal
|
||||
* * text - The text to display above the answers
|
||||
* * delegate - The proc to call when submitted
|
||||
* * arguments - List of arguments passed to and from JS (mostly useful for chaining modals)
|
||||
* * value - The default value of the input
|
||||
* * max_length - The maximum char length of the input
|
||||
*/
|
||||
/datum/proc/tgui_modal_input(datum/source = src, id, text = "Default modal message", delegate, arguments, value = "", max_length = TGUI_MODAL_INPUT_MAX_LENGTH)
|
||||
ASSERT(length(id))
|
||||
ASSERT(max_length > 0)
|
||||
|
||||
var/datum/tgui_modal/input/modal = new(id, text, delegate, arguments, value, max_length)
|
||||
return tgui_modal_new(source, modal)
|
||||
|
||||
/**
|
||||
* Opens a dropdown input TGUI modal
|
||||
*
|
||||
* Internally checks if the answer is in the list of choices.
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * id - The ID of the modal
|
||||
* * text - The text to display above the answers
|
||||
* * delegate - The proc to call when submitted
|
||||
* * arguments - List of arguments passed to and from JS (mostly useful for chaining modals)
|
||||
* * value - The default value of the dropdown
|
||||
* * choices - The list of available choices in the dropdown
|
||||
*/
|
||||
/datum/proc/tgui_modal_choice(datum/source = src, id, text = "Default modal message", delegate, arguments, value = "", choices)
|
||||
ASSERT(length(id))
|
||||
|
||||
var/datum/tgui_modal/input/choice/modal = new(id, text, delegate, arguments, value, choices)
|
||||
return tgui_modal_new(source, modal)
|
||||
|
||||
/**
|
||||
* Opens a bento input TGUI modal
|
||||
*
|
||||
* Internally checks if the answer is in the list of choices.
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * id - The ID of the modal
|
||||
* * text - The text to display above the answers
|
||||
* * delegate - The proc to call when submitted
|
||||
* * arguments - List of arguments passed to and from JS (mostly useful for chaining modals)
|
||||
* * value - The default value of the bento
|
||||
* * choices - The list of available choices in the bento
|
||||
*/
|
||||
/datum/proc/tgui_modal_bento(datum/source = src, id, text = "Default modal message", delegate, arguments, value, choices)
|
||||
ASSERT(length(id))
|
||||
|
||||
var/datum/tgui_modal/input/bento/modal = new(id, text, delegate, arguments, value, choices)
|
||||
return tgui_modal_new(source, modal)
|
||||
|
||||
/**
|
||||
* Opens a yes/no TGUI modal
|
||||
*
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * id - The ID of the modal
|
||||
* * text - The text to display above the answers
|
||||
* * delegate - The proc to call when "Yes" is pressed
|
||||
* * delegate_no - The proc to call when "No" is pressed
|
||||
* * arguments - List of arguments passed to and from JS (mostly useful for chaining modals)
|
||||
* * yes_text - The text to show in the "Yes" button
|
||||
* * no_text - The text to show in the "No" button
|
||||
*/
|
||||
/datum/proc/tgui_modal_boolean(datum/source = src, id, text = "Default modal message", delegate, delegate_no, arguments, yes_text = "Yes", no_text = "No")
|
||||
ASSERT(length(id))
|
||||
|
||||
var/datum/tgui_modal/boolean/modal = new(id, text, delegate, delegate_no, arguments, yes_text, no_text)
|
||||
return tgui_modal_new(source, modal)
|
||||
|
||||
/**
|
||||
* Registers a given modal to a source. Private.
|
||||
*
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * modal - The datum/tgui_modal to register
|
||||
* * replace_previous - Whether any modal currently assigned to source should be replaced
|
||||
* * instant_update - Whether the changes should reflect immediately
|
||||
*/
|
||||
/datum/proc/tgui_modal_new(datum/source = src, datum/tgui_modal/modal = null, replace_previous = TRUE, instant_update = TRUE)
|
||||
ASSERT(istype(source))
|
||||
ASSERT(istype(modal))
|
||||
|
||||
var/datum/tgui_modal/previous = LAZYACCESS(GLOB.tgui_modals, REF(source))
|
||||
if(previous && !replace_previous)
|
||||
return FALSE
|
||||
|
||||
modal.owning_source = source
|
||||
|
||||
// Previous one should get GC'd
|
||||
LAZYSET(GLOB.tgui_modals, REF(source), modal)
|
||||
if(instant_update)
|
||||
SStgui.update_uis(source)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Calls the source's currently assigned modal's (if there is one) on_answer() proc. Private.
|
||||
*
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * id - The ID of the modal
|
||||
* * answer - The provided answer
|
||||
*/
|
||||
/datum/proc/tgui_modal_answer(datum/source = src, id, answer = "")
|
||||
ASSERT(istype(source))
|
||||
|
||||
var/datum/tgui_modal/current = LAZYACCESS(GLOB.tgui_modals, REF(source))
|
||||
if(!current)
|
||||
return FALSE
|
||||
|
||||
return current.on_answer(answer)
|
||||
|
||||
/**
|
||||
* Passes an answer from JS through the modal's proc.
|
||||
*
|
||||
* Used namely for cutting the text short if it's longer
|
||||
* than an input modal's max_length.
|
||||
* Arguments:
|
||||
* * source - The source datum
|
||||
* * answer - The provided answer
|
||||
*/
|
||||
/datum/proc/tgui_modal_preprocess_answer(datum/source = src, answer = "")
|
||||
ASSERT(istype(source))
|
||||
|
||||
var/datum/tgui_modal/current = LAZYACCESS(GLOB.tgui_modals, REF(source))
|
||||
if(!current)
|
||||
return answer
|
||||
|
||||
return current.preprocess_answer(answer)
|
||||
|
||||
/**
|
||||
* Modal datum (contains base information for a modal)
|
||||
*/
|
||||
/datum/tgui_modal
|
||||
var/datum/owning_source
|
||||
var/id
|
||||
var/text
|
||||
var/delegate
|
||||
var/list/arguments
|
||||
var/modal_type = "message"
|
||||
|
||||
/datum/tgui_modal/New(id, text, delegate, list/arguments)
|
||||
src.id = id
|
||||
src.text = text
|
||||
src.delegate = delegate
|
||||
src.arguments = arguments
|
||||
|
||||
/**
|
||||
* Called when it's time to pre-process the answer before using it
|
||||
*
|
||||
* Arguments:
|
||||
* * answer - The answer, a nullable text
|
||||
*/
|
||||
/datum/tgui_modal/proc/preprocess_answer(answer)
|
||||
return reject_bad_text(answer, TGUI_MODAL_INPUT_MAX_LENGTH) // bleh
|
||||
|
||||
/**
|
||||
* Called when a modal receives an answer
|
||||
*
|
||||
* Arguments:
|
||||
* * answer - The answer, a nullable text
|
||||
*/
|
||||
/datum/tgui_modal/proc/on_answer(answer)
|
||||
if(delegate)
|
||||
return call(owning_source, delegate)(answer, arguments)
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Creates a list that describes a modal visually to be passed to JS
|
||||
*/
|
||||
/datum/tgui_modal/proc/to_data()
|
||||
. = list()
|
||||
.["id"] = id
|
||||
.["text"] = text
|
||||
.["args"] = arguments || list()
|
||||
.["type"] = modal_type
|
||||
|
||||
/**
|
||||
* Input modal - has a text entry that can be used to enter an answer
|
||||
*/
|
||||
/datum/tgui_modal/input
|
||||
modal_type = "input"
|
||||
var/value
|
||||
var/max_length
|
||||
|
||||
/datum/tgui_modal/input/New(id, text, delegate, list/arguments, value, max_length)
|
||||
..(id, text, delegate, arguments)
|
||||
src.value = value
|
||||
src.max_length = max_length
|
||||
|
||||
/datum/tgui_modal/input/preprocess_answer(answer)
|
||||
. = ..(answer)
|
||||
if(length(answer) > max_length)
|
||||
. = copytext(., 1, max_length + 1)
|
||||
|
||||
/datum/tgui_modal/input/to_data()
|
||||
. = ..()
|
||||
.["value"] = value
|
||||
|
||||
/**
|
||||
* Choice modal - has a dropdown menu that can be used to select an answer
|
||||
*/
|
||||
/datum/tgui_modal/input/choice
|
||||
modal_type = "choice"
|
||||
var/choices
|
||||
|
||||
/datum/tgui_modal/input/choice/New(id, text, delegate, list/arguments, value, choices)
|
||||
..(id, text, delegate, arguments, value, TGUI_MODAL_INPUT_MAX_LENGTH) // Max length doesn't really matter in dropdowns, but whatever
|
||||
src.choices = choices
|
||||
|
||||
/datum/tgui_modal/input/choice/on_answer(answer)
|
||||
if(answer in choices) // Make sure the answer is actually in our choices!
|
||||
return ..(answer, arguments)
|
||||
return FALSE
|
||||
|
||||
/datum/tgui_modal/input/choice/to_data()
|
||||
. = ..()
|
||||
.["choices"] = choices
|
||||
|
||||
/**
|
||||
* Bento modal - Similar to choice, it displays the choices in a grid of images
|
||||
*
|
||||
* The returned answer is the index of the choice.
|
||||
*/
|
||||
/datum/tgui_modal/input/bento
|
||||
modal_type = "bento"
|
||||
var/choices
|
||||
|
||||
/datum/tgui_modal/input/bento/New(id, text, delegate, list/arguments, value, choices)
|
||||
..(id, text, delegate, arguments, text2num(value), TGUI_MODAL_INPUT_MAX_LENGTH) // Max length doesn't really matter in here, but whatever
|
||||
src.choices = choices
|
||||
|
||||
/datum/tgui_modal/input/bento/preprocess_answer(answer)
|
||||
return text2num(answer) || 0
|
||||
|
||||
/datum/tgui_modal/input/bento/on_answer(answer)
|
||||
if(answer >= 1 && answer <= length(choices)) // Make sure the answer index is actually in our indexes!
|
||||
return ..(answer, arguments)
|
||||
return FALSE
|
||||
|
||||
/datum/tgui_modal/input/bento/to_data()
|
||||
. = ..()
|
||||
.["choices"] = choices
|
||||
|
||||
/**
|
||||
* Boolean modal - has yes/no buttons that do different actions depending on which is pressed
|
||||
*/
|
||||
/datum/tgui_modal/boolean
|
||||
modal_type = "boolean"
|
||||
var/delegate_no
|
||||
var/yes_text
|
||||
var/no_text
|
||||
|
||||
/datum/tgui_modal/boolean/New(id, text, delegate, delegate_no, list/arguments, yes_text, no_text)
|
||||
..(id, text, delegate, arguments)
|
||||
src.delegate_no = delegate_no
|
||||
src.yes_text = yes_text
|
||||
src.no_text = no_text
|
||||
|
||||
/datum/tgui_modal/boolean/preprocess_answer(answer)
|
||||
return text2num(answer) || FALSE
|
||||
|
||||
/datum/tgui_modal/boolean/on_answer(answer)
|
||||
if(answer)
|
||||
return ..(answer, arguments)
|
||||
else if(delegate_no)
|
||||
return call(owning_source, delegate_no)(arguments)
|
||||
return FALSE
|
||||
|
||||
/datum/tgui_modal/boolean/to_data()
|
||||
. = ..()
|
||||
.["yes_text"] = yes_text
|
||||
.["no_text"] = no_text
|
||||
@@ -12,17 +12,26 @@ Code is pretty much ripped verbatim from nano modules, but with un-needed stuff
|
||||
var/list/using_access
|
||||
|
||||
var/tgui_id
|
||||
var/ntos = FALSE
|
||||
|
||||
/datum/tgui_module/New(var/host)
|
||||
src.host = host
|
||||
if(ntos)
|
||||
tgui_id = "Ntos" + tgui_id
|
||||
|
||||
/datum/tgui_module/tgui_host()
|
||||
return host ? host : src
|
||||
return host ? host.tgui_host() : src
|
||||
|
||||
/datum/tgui_module/tgui_close(mob/user)
|
||||
if(host)
|
||||
host.tgui_close(user)
|
||||
|
||||
/datum/tgui_module/proc/check_eye(mob/user)
|
||||
return -1
|
||||
|
||||
/datum/tgui_module/proc/can_still_topic(mob/user, datum/tgui_state/state)
|
||||
return (tgui_status(user, state) == STATUS_INTERACTIVE)
|
||||
|
||||
/datum/tgui_module/proc/check_access(mob/user, access)
|
||||
if(!access)
|
||||
return 1
|
||||
@@ -43,4 +52,70 @@ Code is pretty much ripped verbatim from nano modules, but with un-needed stuff
|
||||
if(access in I.access)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
return 0
|
||||
|
||||
/datum/tgui_module/tgui_static_data()
|
||||
. = ..()
|
||||
|
||||
var/obj/item/modular_computer/host = tgui_host()
|
||||
if(istype(host))
|
||||
. += host.get_header_data()
|
||||
|
||||
/datum/tgui_module/tgui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
var/obj/item/modular_computer/host = tgui_host()
|
||||
if(istype(host))
|
||||
if(action == "PC_exit")
|
||||
host.kill_program()
|
||||
return TRUE
|
||||
if(action == "PC_shutdown")
|
||||
host.shutdown_computer()
|
||||
return TRUE
|
||||
if(action == "PC_minimize")
|
||||
host.minimize_program(usr)
|
||||
return TRUE
|
||||
|
||||
// Just a nice little default interact in case the subtypes don't need any special behavior here
|
||||
/datum/tgui_module/tgui_interact(mob/user, datum/tgui/ui = null)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, tgui_id, name)
|
||||
ui.open()
|
||||
|
||||
// This is a helper for anything that wants to render the map.
|
||||
/datum/tgui_module/proc/get_plane_masters()
|
||||
. = list()
|
||||
// 'Utility' planes
|
||||
. += new /obj/screen/plane_master/fullbright //Lighting system (lighting_overlay objects)
|
||||
. += new /obj/screen/plane_master/lighting //Lighting system (but different!)
|
||||
. += new /obj/screen/plane_master/ghosts //Ghosts!
|
||||
. += new /obj/screen/plane_master{plane = PLANE_AI_EYE} //AI Eye!
|
||||
|
||||
. += new /obj/screen/plane_master{plane = PLANE_CH_STATUS} //Status is the synth/human icon left side of medhuds
|
||||
. += new /obj/screen/plane_master{plane = PLANE_CH_HEALTH} //Health bar
|
||||
. += new /obj/screen/plane_master{plane = PLANE_CH_LIFE} //Alive-or-not icon
|
||||
. += new /obj/screen/plane_master{plane = PLANE_CH_ID} //Job ID icon
|
||||
. += new /obj/screen/plane_master{plane = PLANE_CH_WANTED} //Wanted status
|
||||
. += new /obj/screen/plane_master{plane = PLANE_CH_IMPLOYAL} //Loyalty implants
|
||||
. += new /obj/screen/plane_master{plane = PLANE_CH_IMPTRACK} //Tracking implants
|
||||
. += new /obj/screen/plane_master{plane = PLANE_CH_IMPCHEM} //Chemical implants
|
||||
. += new /obj/screen/plane_master{plane = PLANE_CH_SPECIAL} //"Special" role stuff
|
||||
. += new /obj/screen/plane_master{plane = PLANE_CH_STATUS_OOC} //OOC status HUD
|
||||
|
||||
. += new /obj/screen/plane_master{plane = PLANE_ADMIN1} //For admin use
|
||||
. += new /obj/screen/plane_master{plane = PLANE_ADMIN2} //For admin use
|
||||
. += new /obj/screen/plane_master{plane = PLANE_ADMIN3} //For admin use
|
||||
|
||||
. += new /obj/screen/plane_master{plane = PLANE_MESONS} //Meson-specific things like open ceilings.
|
||||
. += new /obj/screen/plane_master{plane = PLANE_BUILDMODE} //Things that only show up while in build mode
|
||||
|
||||
// Real tangible stuff planes
|
||||
. += new /obj/screen/plane_master/main{plane = TURF_PLANE}
|
||||
. += new /obj/screen/plane_master/main{plane = OBJ_PLANE}
|
||||
. += new /obj/screen/plane_master/main{plane = MOB_PLANE}
|
||||
. += new /obj/screen/plane_master/cloaked //Cloaked atoms!
|
||||
|
||||
/datum/tgui_module/proc/relaymove(mob/user, direction)
|
||||
return FALSE
|
||||
|
||||
@@ -0,0 +1,358 @@
|
||||
/datum/tgui_module/appearance_changer
|
||||
name = "Appearance Editor"
|
||||
tgui_id = "AppearanceChanger"
|
||||
var/flags = APPEARANCE_ALL_HAIR
|
||||
var/mob/living/carbon/human/owner = null
|
||||
var/list/valid_species = list()
|
||||
var/list/valid_hairstyles = list()
|
||||
var/list/valid_facial_hairstyles = list()
|
||||
|
||||
var/check_whitelist
|
||||
var/list/whitelist
|
||||
var/list/blacklist
|
||||
|
||||
var/customize_usr = FALSE
|
||||
|
||||
// Stuff needed to render the map
|
||||
var/map_name
|
||||
var/obj/screen/map_view/cam_screen
|
||||
var/list/cam_plane_masters
|
||||
var/obj/screen/background/cam_background
|
||||
var/obj/screen/skybox/local_skybox
|
||||
// Needed for moving camera support
|
||||
var/camera_diff_x = -1
|
||||
var/camera_diff_y = -1
|
||||
var/camera_diff_z = -1
|
||||
|
||||
/datum/tgui_module/appearance_changer/New(
|
||||
var/host,
|
||||
mob/living/carbon/human/H,
|
||||
check_species_whitelist = 1,
|
||||
list/species_whitelist = list(),
|
||||
list/species_blacklist = list())
|
||||
. = ..()
|
||||
|
||||
map_name = "appearance_changer_[REF(src)]_map"
|
||||
// Initialize map objects
|
||||
cam_screen = new
|
||||
cam_screen.name = "screen"
|
||||
cam_screen.assigned_map = map_name
|
||||
cam_screen.del_on_map_removal = FALSE
|
||||
cam_screen.screen_loc = "[map_name]:1,1"
|
||||
|
||||
cam_plane_masters = get_plane_masters()
|
||||
|
||||
for(var/plane in cam_plane_masters)
|
||||
var/obj/screen/instance = plane
|
||||
instance.assigned_map = map_name
|
||||
instance.del_on_map_removal = FALSE
|
||||
instance.screen_loc = "[map_name]:CENTER"
|
||||
|
||||
local_skybox = new()
|
||||
local_skybox.assigned_map = map_name
|
||||
local_skybox.del_on_map_removal = FALSE
|
||||
local_skybox.screen_loc = "[map_name]:CENTER,CENTER"
|
||||
cam_plane_masters += local_skybox
|
||||
|
||||
cam_background = new
|
||||
cam_background.assigned_map = map_name
|
||||
cam_background.del_on_map_removal = FALSE
|
||||
reload_cameraview()
|
||||
|
||||
owner = H
|
||||
check_whitelist = check_species_whitelist
|
||||
whitelist = species_whitelist
|
||||
blacklist = species_blacklist
|
||||
|
||||
/datum/tgui_module/appearance_changer/Destroy()
|
||||
qdel(cam_screen)
|
||||
QDEL_LIST(cam_plane_masters)
|
||||
qdel(cam_background)
|
||||
return ..()
|
||||
|
||||
/datum/tgui_module/appearance_changer/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
var/mob/living/carbon/human/target = owner
|
||||
if(customize_usr)
|
||||
if(!ishuman(usr))
|
||||
return TRUE
|
||||
target = usr
|
||||
|
||||
switch(action)
|
||||
if("race")
|
||||
if(can_change(APPEARANCE_RACE) && (params["race"] in valid_species))
|
||||
if(target.change_species(params["race"]))
|
||||
cut_and_generate_data()
|
||||
return 1
|
||||
if("gender")
|
||||
if(can_change(APPEARANCE_GENDER) && (params["gender"] in get_genders()))
|
||||
if(target.change_gender(params["gender"]))
|
||||
cut_and_generate_data()
|
||||
return 1
|
||||
if("gender_id")
|
||||
if(can_change(APPEARANCE_GENDER) && (params["gender_id"] in all_genders_define_list))
|
||||
target.identifying_gender = params["gender_id"]
|
||||
return 1
|
||||
if("skin_tone")
|
||||
if(can_change_skin_tone())
|
||||
var/new_s_tone = input(usr, "Choose your character's skin-tone:\n(Light 1 - 220 Dark)", "Skin Tone", -target.s_tone + 35) as num|null
|
||||
if(isnum(new_s_tone) && can_still_topic(usr, state))
|
||||
new_s_tone = 35 - max(min( round(new_s_tone), 220),1)
|
||||
return target.change_skin_tone(new_s_tone)
|
||||
if("skin_color")
|
||||
if(can_change_skin_color())
|
||||
var/new_skin = input(usr, "Choose your character's skin colour: ", "Skin Color", rgb(target.r_skin, target.g_skin, target.b_skin)) as color|null
|
||||
if(new_skin && can_still_topic(usr, state))
|
||||
var/r_skin = hex2num(copytext(new_skin, 2, 4))
|
||||
var/g_skin = hex2num(copytext(new_skin, 4, 6))
|
||||
var/b_skin = hex2num(copytext(new_skin, 6, 8))
|
||||
if(target.change_skin_color(r_skin, g_skin, b_skin))
|
||||
update_dna()
|
||||
return 1
|
||||
if("hair")
|
||||
if(can_change(APPEARANCE_HAIR) && (params["hair"] in valid_hairstyles))
|
||||
if(target.change_hair(params["hair"]))
|
||||
update_dna()
|
||||
return 1
|
||||
if("hair_color")
|
||||
if(can_change(APPEARANCE_HAIR_COLOR))
|
||||
var/new_hair = input("Please select hair color.", "Hair Color", rgb(target.r_hair, target.g_hair, target.b_hair)) as color|null
|
||||
if(new_hair && can_still_topic(usr, state))
|
||||
var/r_hair = hex2num(copytext(new_hair, 2, 4))
|
||||
var/g_hair = hex2num(copytext(new_hair, 4, 6))
|
||||
var/b_hair = hex2num(copytext(new_hair, 6, 8))
|
||||
if(target.change_hair_color(r_hair, g_hair, b_hair))
|
||||
update_dna()
|
||||
return 1
|
||||
if("facial_hair")
|
||||
if(can_change(APPEARANCE_FACIAL_HAIR) && (params["facial_hair"] in valid_facial_hairstyles))
|
||||
if(target.change_facial_hair(params["facial_hair"]))
|
||||
update_dna()
|
||||
return 1
|
||||
if("facial_hair_color")
|
||||
if(can_change(APPEARANCE_FACIAL_HAIR_COLOR))
|
||||
var/new_facial = input("Please select facial hair color.", "Facial Hair Color", rgb(target.r_facial, target.g_facial, target.b_facial)) as color|null
|
||||
if(new_facial && can_still_topic(usr, state))
|
||||
var/r_facial = hex2num(copytext(new_facial, 2, 4))
|
||||
var/g_facial = hex2num(copytext(new_facial, 4, 6))
|
||||
var/b_facial = hex2num(copytext(new_facial, 6, 8))
|
||||
if(target.change_facial_hair_color(r_facial, g_facial, b_facial))
|
||||
update_dna()
|
||||
return 1
|
||||
if("eye_color")
|
||||
if(can_change(APPEARANCE_EYE_COLOR))
|
||||
var/new_eyes = input("Please select eye color.", "Eye Color", rgb(target.r_eyes, target.g_eyes, target.b_eyes)) as color|null
|
||||
if(new_eyes && can_still_topic(usr, state))
|
||||
var/r_eyes = hex2num(copytext(new_eyes, 2, 4))
|
||||
var/g_eyes = hex2num(copytext(new_eyes, 4, 6))
|
||||
var/b_eyes = hex2num(copytext(new_eyes, 6, 8))
|
||||
if(target.change_eye_color(r_eyes, g_eyes, b_eyes))
|
||||
update_dna()
|
||||
return 1
|
||||
return FALSE
|
||||
|
||||
/datum/tgui_module/appearance_changer/tgui_interact(mob/user, datum/tgui/ui = null, datum/tgui/parent_ui = null, datum/tgui_state/custom_state = GLOB.tgui_default_state)
|
||||
var/mob/living/carbon/human/target = owner
|
||||
if(customize_usr)
|
||||
if(!ishuman(user))
|
||||
return TRUE
|
||||
target = user
|
||||
|
||||
if(!target || !target.species)
|
||||
return
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
reload_cameraview()
|
||||
// Register map objects
|
||||
user.client.register_map_obj(cam_screen)
|
||||
for(var/plane in cam_plane_masters)
|
||||
user.client.register_map_obj(plane)
|
||||
user.client.register_map_obj(cam_background)
|
||||
// Open UI
|
||||
ui = new(user, src, tgui_id, name)
|
||||
ui.open()
|
||||
if(custom_state)
|
||||
ui.set_state(custom_state)
|
||||
|
||||
/datum/tgui_module/appearance_changer/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
|
||||
var/list/data = ..()
|
||||
|
||||
generate_data(check_whitelist, whitelist, blacklist)
|
||||
differential_check()
|
||||
|
||||
var/mob/living/carbon/human/target = owner
|
||||
if(customize_usr)
|
||||
if(!ishuman(usr))
|
||||
return TRUE
|
||||
target = usr
|
||||
|
||||
data["name"] = target.name
|
||||
data["specimen"] = target.species.name
|
||||
data["gender"] = target.gender
|
||||
data["gender_id"] = target.identifying_gender
|
||||
data["change_race"] = can_change(APPEARANCE_RACE)
|
||||
if(data["change_race"])
|
||||
var/species[0]
|
||||
for(var/specimen in valid_species)
|
||||
species[++species.len] = list("specimen" = specimen)
|
||||
data["species"] = species
|
||||
|
||||
data["change_gender"] = can_change(APPEARANCE_GENDER)
|
||||
if(data["change_gender"])
|
||||
var/genders[0]
|
||||
for(var/gender in get_genders())
|
||||
genders[++genders.len] = list("gender_name" = gender2text(gender), "gender_key" = gender)
|
||||
data["genders"] = genders
|
||||
var/id_genders[0]
|
||||
for(var/gender in all_genders_define_list)
|
||||
id_genders[++id_genders.len] = list("gender_name" = gender2text(gender), "gender_key" = gender)
|
||||
data["id_genders"] = id_genders
|
||||
|
||||
data["change_hair"] = can_change(APPEARANCE_HAIR)
|
||||
if(data["change_hair"])
|
||||
var/hair_styles[0]
|
||||
for(var/hair_style in valid_hairstyles)
|
||||
hair_styles[++hair_styles.len] = list("hairstyle" = hair_style)
|
||||
data["hair_styles"] = hair_styles
|
||||
data["hair_style"] = target.h_style
|
||||
|
||||
data["change_facial_hair"] = can_change(APPEARANCE_FACIAL_HAIR)
|
||||
if(data["change_facial_hair"])
|
||||
var/facial_hair_styles[0]
|
||||
for(var/facial_hair_style in valid_facial_hairstyles)
|
||||
facial_hair_styles[++facial_hair_styles.len] = list("facialhairstyle" = facial_hair_style)
|
||||
data["facial_hair_styles"] = facial_hair_styles
|
||||
data["facial_hair_style"] = target.f_style
|
||||
|
||||
data["change_skin_tone"] = can_change_skin_tone()
|
||||
data["change_skin_color"] = can_change_skin_color()
|
||||
if(data["change_skin_color"])
|
||||
data["skin_color"] = rgb(target.r_skin, target.g_skin, target.b_skin)
|
||||
data["change_eye_color"] = can_change(APPEARANCE_EYE_COLOR)
|
||||
if(data["change_eye_color"])
|
||||
data["eye_color"] = rgb(target.r_eyes, target.g_eyes, target.b_eyes)
|
||||
data["change_hair_color"] = can_change(APPEARANCE_HAIR_COLOR)
|
||||
if(data["change_hair_color"])
|
||||
data["hair_color"] = rgb(target.r_hair, target.g_hair, target.b_hair)
|
||||
data["change_facial_hair_color"] = can_change(APPEARANCE_FACIAL_HAIR_COLOR)
|
||||
if(data["change_facial_hair_color"])
|
||||
data["facial_hair_color"] = rgb(target.r_facial, target.g_facial, target.b_facial)
|
||||
return data
|
||||
|
||||
/datum/tgui_module/appearance_changer/tgui_static_data(mob/user)
|
||||
var/list/data = ..()
|
||||
data["mapRef"] = map_name
|
||||
return data
|
||||
|
||||
/datum/tgui_module/appearance_changer/proc/differential_check()
|
||||
var/turf/T = get_turf(customize_usr ? tgui_host() : owner)
|
||||
if(T)
|
||||
var/new_x = T.x
|
||||
var/new_y = T.y
|
||||
var/new_z = T.z
|
||||
if((new_x != camera_diff_x) || (new_y != camera_diff_y) || (new_z != camera_diff_z))
|
||||
reload_cameraview()
|
||||
|
||||
/datum/tgui_module/appearance_changer/proc/reload_cameraview()
|
||||
var/turf/camTurf = get_turf(customize_usr ? tgui_host() : owner)
|
||||
if(!camTurf)
|
||||
return
|
||||
|
||||
camera_diff_x = camTurf.x
|
||||
camera_diff_y = camTurf.y
|
||||
camera_diff_z = camTurf.z
|
||||
|
||||
var/list/visible_turfs = list()
|
||||
for(var/turf/T in range(1, camTurf))
|
||||
visible_turfs += T
|
||||
|
||||
cam_screen.vis_contents = visible_turfs
|
||||
cam_background.icon_state = "clear"
|
||||
cam_background.fill_rect(1, 1, 3, 3)
|
||||
|
||||
local_skybox.cut_overlays()
|
||||
local_skybox.add_overlay(SSskybox.get_skybox(get_z(camTurf)))
|
||||
local_skybox.scale_to_view(3)
|
||||
local_skybox.set_position("CENTER", "CENTER", (world.maxx>>1) - camTurf.x, (world.maxy>>1) - camTurf.y)
|
||||
|
||||
/datum/tgui_module/appearance_changer/proc/update_dna()
|
||||
var/mob/living/carbon/human/target = owner
|
||||
if(customize_usr)
|
||||
if(!ishuman(usr))
|
||||
return TRUE
|
||||
target = usr
|
||||
|
||||
if(target && (flags & APPEARANCE_UPDATE_DNA))
|
||||
target.update_dna()
|
||||
|
||||
/datum/tgui_module/appearance_changer/proc/can_change(var/flag)
|
||||
var/mob/living/carbon/human/target = owner
|
||||
if(customize_usr)
|
||||
if(!ishuman(usr))
|
||||
return TRUE
|
||||
target = usr
|
||||
|
||||
return target && (flags & flag)
|
||||
|
||||
/datum/tgui_module/appearance_changer/proc/can_change_skin_tone()
|
||||
var/mob/living/carbon/human/target = owner
|
||||
if(customize_usr)
|
||||
if(!ishuman(usr))
|
||||
return TRUE
|
||||
target = usr
|
||||
|
||||
return target && (flags & APPEARANCE_SKIN) && target.species.appearance_flags & HAS_SKIN_TONE
|
||||
|
||||
/datum/tgui_module/appearance_changer/proc/can_change_skin_color()
|
||||
var/mob/living/carbon/human/target = owner
|
||||
if(customize_usr)
|
||||
if(!ishuman(usr))
|
||||
return TRUE
|
||||
target = usr
|
||||
|
||||
return target && (flags & APPEARANCE_SKIN) && target.species.appearance_flags & HAS_SKIN_COLOR
|
||||
|
||||
/datum/tgui_module/appearance_changer/proc/cut_and_generate_data()
|
||||
// Making the assumption that the available species remain constant
|
||||
valid_facial_hairstyles.Cut()
|
||||
valid_facial_hairstyles.Cut()
|
||||
generate_data()
|
||||
|
||||
/datum/tgui_module/appearance_changer/proc/generate_data()
|
||||
var/mob/living/carbon/human/target = owner
|
||||
if(customize_usr)
|
||||
if(!ishuman(usr))
|
||||
return TRUE
|
||||
target = usr
|
||||
if(!target)
|
||||
return
|
||||
if(!valid_species.len)
|
||||
valid_species = target.generate_valid_species(check_whitelist, whitelist, blacklist)
|
||||
if(!valid_hairstyles.len || !valid_facial_hairstyles.len)
|
||||
valid_hairstyles = target.generate_valid_hairstyles(check_gender = 0)
|
||||
valid_facial_hairstyles = target.generate_valid_facial_hairstyles()
|
||||
|
||||
/datum/tgui_module/appearance_changer/proc/get_genders()
|
||||
var/mob/living/carbon/human/target = owner
|
||||
if(customize_usr)
|
||||
if(!ishuman(usr))
|
||||
return TRUE
|
||||
target = usr
|
||||
var/datum/species/S = target.species
|
||||
var/list/possible_genders = S.genders
|
||||
if(!target.internal_organs_by_name["cell"])
|
||||
return possible_genders
|
||||
possible_genders = possible_genders.Copy()
|
||||
possible_genders |= NEUTER
|
||||
return possible_genders
|
||||
|
||||
/datum/tgui_module/appearance_changer/mirror
|
||||
name = "SalonPro Nano-Mirror™"
|
||||
flags = APPEARANCE_ALL_HAIR
|
||||
customize_usr = TRUE
|
||||
|
||||
/datum/tgui_module/appearance_changer/mirror/coskit
|
||||
name = "SalonPro Porta-Makeover Deluxe™"
|
||||
@@ -37,37 +37,7 @@
|
||||
cam_screen.del_on_map_removal = FALSE
|
||||
cam_screen.screen_loc = "[map_name]:1,1"
|
||||
|
||||
cam_plane_masters = list()
|
||||
|
||||
// 'Utility' planes
|
||||
cam_plane_masters += new /obj/screen/plane_master/fullbright //Lighting system (lighting_overlay objects)
|
||||
cam_plane_masters += new /obj/screen/plane_master/lighting //Lighting system (but different!)
|
||||
cam_plane_masters += new /obj/screen/plane_master/ghosts //Ghosts!
|
||||
cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_AI_EYE} //AI Eye!
|
||||
|
||||
cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_STATUS} //Status is the synth/human icon left side of medhuds
|
||||
cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_HEALTH} //Health bar
|
||||
cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_LIFE} //Alive-or-not icon
|
||||
cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_ID} //Job ID icon
|
||||
cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_WANTED} //Wanted status
|
||||
cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_IMPLOYAL} //Loyalty implants
|
||||
cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_IMPTRACK} //Tracking implants
|
||||
cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_IMPCHEM} //Chemical implants
|
||||
cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_SPECIAL} //"Special" role stuff
|
||||
cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_CH_STATUS_OOC} //OOC status HUD
|
||||
|
||||
cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_ADMIN1} //For admin use
|
||||
cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_ADMIN2} //For admin use
|
||||
cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_ADMIN3} //For admin use
|
||||
|
||||
cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_MESONS} //Meson-specific things like open ceilings.
|
||||
cam_plane_masters += new /obj/screen/plane_master{plane = PLANE_BUILDMODE} //Things that only show up while in build mode
|
||||
|
||||
// Real tangible stuff planes
|
||||
cam_plane_masters += new /obj/screen/plane_master/main{plane = TURF_PLANE}
|
||||
cam_plane_masters += new /obj/screen/plane_master/main{plane = OBJ_PLANE}
|
||||
cam_plane_masters += new /obj/screen/plane_master/main{plane = MOB_PLANE}
|
||||
cam_plane_masters += new /obj/screen/plane_master/cloaked //Cloaked atoms!
|
||||
cam_plane_masters = get_plane_masters()
|
||||
|
||||
for(var/plane in cam_plane_masters)
|
||||
var/obj/screen/instance = plane
|
||||
@@ -144,7 +114,7 @@
|
||||
return data
|
||||
|
||||
/datum/tgui_module/camera/tgui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
var/list/data = ..()
|
||||
data["mapRef"] = map_name
|
||||
var/list/cameras = get_available_cameras(user)
|
||||
data["cameras"] = list()
|
||||
@@ -160,7 +130,10 @@
|
||||
|
||||
/datum/tgui_module/camera/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
return TRUE
|
||||
|
||||
if(action && !issilicon(usr))
|
||||
playsound(tgui_host(), "terminal_type", 50, 1)
|
||||
|
||||
if(action == "switch_camera")
|
||||
var/c_tag = params["name"]
|
||||
@@ -168,11 +141,33 @@
|
||||
var/obj/machinery/camera/C = cameras["[ckey(c_tag)]"]
|
||||
active_camera = C
|
||||
playsound(tgui_host(), get_sfx("terminal_type"), 25, FALSE)
|
||||
|
||||
reload_cameraview()
|
||||
|
||||
return TRUE
|
||||
|
||||
if(action == "pan")
|
||||
var/dir = params["dir"]
|
||||
var/turf/T = get_turf(active_camera)
|
||||
for(var/i in 1 to 10)
|
||||
T = get_step(T, dir)
|
||||
if(T)
|
||||
var/obj/machinery/camera/target
|
||||
var/best_dist = INFINITY
|
||||
|
||||
var/list/possible_cameras = get_available_cameras(usr)
|
||||
for(var/obj/machinery/camera/C in get_area(T))
|
||||
if(!possible_cameras["[ckey(C.c_tag)]"])
|
||||
continue
|
||||
var/dist = get_dist(C, T)
|
||||
if(dist < best_dist)
|
||||
best_dist = dist
|
||||
target = C
|
||||
|
||||
if(target)
|
||||
active_camera = target
|
||||
playsound(tgui_host(), get_sfx("terminal_type"), 25, FALSE)
|
||||
reload_cameraview()
|
||||
. = TRUE
|
||||
|
||||
/datum/tgui_module/camera/proc/differential_check()
|
||||
var/turf/T = get_turf(active_camera)
|
||||
if(T)
|
||||
@@ -284,33 +279,7 @@
|
||||
// If/when that is done, just move all the PC_ specific data and stuff to the modular computers themselves
|
||||
// instead of copying this approach here.
|
||||
/datum/tgui_module/camera/ntos
|
||||
tgui_id = "NtosCameraConsole"
|
||||
|
||||
/datum/tgui_module/camera/ntos/tgui_state()
|
||||
return GLOB.tgui_ntos_state
|
||||
|
||||
/datum/tgui_module/camera/ntos/tgui_static_data()
|
||||
. = ..()
|
||||
|
||||
var/datum/computer_file/program/host = tgui_host()
|
||||
if(istype(host) && host.computer)
|
||||
. += host.computer.get_header_data()
|
||||
|
||||
/datum/tgui_module/camera/ntos/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/datum/computer_file/program/host = tgui_host()
|
||||
if(istype(host) && host.computer)
|
||||
if(action == "PC_exit")
|
||||
host.computer.kill_program()
|
||||
return TRUE
|
||||
if(action == "PC_shutdown")
|
||||
host.computer.shutdown_computer()
|
||||
return TRUE
|
||||
if(action == "PC_minimize")
|
||||
host.computer.minimize_program(usr)
|
||||
return TRUE
|
||||
ntos = TRUE
|
||||
|
||||
// ERT Version provides some additional networks.
|
||||
/datum/tgui_module/camera/ntos/ert
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
/datum/tgui_module/crew_monitor/tgui_act(action, params, datum/tgui/ui)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
if(action && !issilicon(usr))
|
||||
playsound(tgui_host(), "terminal_type", 50, 1)
|
||||
|
||||
var/turf/T = get_turf(usr)
|
||||
if(!T || !(T.z in using_map.player_levels))
|
||||
@@ -21,7 +24,7 @@
|
||||
return TRUE
|
||||
if("setZLevel")
|
||||
ui.set_map_z_level(params["mapZLevel"])
|
||||
SStgui.update_uis(src)
|
||||
return TRUE
|
||||
|
||||
/datum/tgui_module/crew_monitor/tgui_interact(mob/user, datum/tgui/ui = null)
|
||||
var/z = get_z(user)
|
||||
@@ -40,7 +43,7 @@
|
||||
ui.open()
|
||||
|
||||
|
||||
/datum/tgui_module/crew_monitor/tgui_data(mob/user, ui_key = "main", datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
/datum/tgui_module/crew_monitor/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
|
||||
data["isAI"] = isAI(user)
|
||||
@@ -56,33 +59,7 @@
|
||||
return data
|
||||
|
||||
/datum/tgui_module/crew_monitor/ntos
|
||||
tgui_id = "NtosCrewMonitor"
|
||||
|
||||
/datum/tgui_module/crew_monitor/ntos/tgui_state(mob/user)
|
||||
return GLOB.tgui_ntos_state
|
||||
|
||||
/datum/tgui_module/crew_monitor/ntos/tgui_static_data()
|
||||
. = ..()
|
||||
|
||||
var/datum/computer_file/program/host = tgui_host()
|
||||
if(istype(host) && host.computer)
|
||||
. += host.computer.get_header_data()
|
||||
|
||||
/datum/tgui_module/crew_monitor/ntos/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/datum/computer_file/program/host = tgui_host()
|
||||
if(istype(host) && host.computer)
|
||||
if(action == "PC_exit")
|
||||
host.computer.kill_program()
|
||||
return TRUE
|
||||
if(action == "PC_shutdown")
|
||||
host.computer.shutdown_computer()
|
||||
return TRUE
|
||||
if(action == "PC_minimize")
|
||||
host.computer.minimize_program(usr)
|
||||
return TRUE
|
||||
ntos = TRUE
|
||||
|
||||
// Subtype for self_state
|
||||
/datum/tgui_module/crew_monitor/robot
|
||||
|
||||
Reference in New Issue
Block a user