mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2026-08-26 14:46:52 +01:00
Merge pull request #7625 from ShadowLarkens/tgui_med
TGUI Medical Conversion
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
if(!H) return
|
||||
|
||||
log_and_message_admins("is altering the appearance of [H].")
|
||||
H.change_appearance(APPEARANCE_ALL, usr, usr, check_species_whitelist = 0, state = admin_state)
|
||||
H.change_appearance(APPEARANCE_ALL, usr, check_species_whitelist = 0, state = GLOB.tgui_admin_state)
|
||||
feedback_add_details("admin_verb","CHAA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/change_human_appearance_self()
|
||||
@@ -29,10 +29,10 @@
|
||||
switch(alert("Do you wish for [H] to be allowed to select non-whitelisted races?","Alter Mob Appearance","Yes","No","Cancel"))
|
||||
if("Yes")
|
||||
log_and_message_admins("has allowed [H] to change [T.his] appearance, without whitelisting of races.")
|
||||
H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 0)
|
||||
H.change_appearance(APPEARANCE_ALL, H, check_species_whitelist = 0)
|
||||
if("No")
|
||||
log_and_message_admins("has allowed [H] to change [T.his] appearance, with whitelisting of races.")
|
||||
H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 1)
|
||||
H.change_appearance(APPEARANCE_ALL, H, check_species_whitelist = 1)
|
||||
feedback_add_details("admin_verb","CMAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/editappear()
|
||||
|
||||
@@ -436,3 +436,37 @@
|
||||
|
||||
/datum/asset/nanoui/send(client)
|
||||
send_asset_list(client, common)
|
||||
|
||||
|
||||
//Pill sprites for UIs
|
||||
/datum/asset/chem_master
|
||||
var/assets = list()
|
||||
var/verify = FALSE
|
||||
|
||||
/datum/asset/chem_master/register()
|
||||
for(var/i = 1 to 24)
|
||||
assets["pill[i].png"] = icon('icons/obj/chemical.dmi', "pill[i]")
|
||||
|
||||
for(var/i = 1 to 4)
|
||||
assets["bottle-[i].png"] = icon('icons/obj/chemical.dmi', "bottle-[i]")
|
||||
|
||||
for(var/asset_name in assets)
|
||||
register_asset(asset_name, assets[asset_name])
|
||||
|
||||
/datum/asset/chem_master/send(client)
|
||||
send_asset_list(client, assets, verify)
|
||||
|
||||
//Cloning pod sprites for UIs
|
||||
/datum/asset/cloning
|
||||
var/assets = list()
|
||||
var/verify = FALSE
|
||||
|
||||
/datum/asset/cloning/register()
|
||||
assets["pod_idle.gif"] = icon('icons/obj/cloning.dmi', "pod_idle")
|
||||
assets["pod_cloning.gif"] = icon('icons/obj/cloning.dmi', "pod_cloning")
|
||||
assets["pod_mess.gif"] = icon('icons/obj/cloning.dmi', "pod_mess")
|
||||
for(var/asset_name in assets)
|
||||
register_asset(asset_name, assets[asset_name])
|
||||
|
||||
/datum/asset/cloning/send(client)
|
||||
send_asset_list(client, assets, verify)
|
||||
|
||||
@@ -213,17 +213,18 @@
|
||||
is_off = "-off"
|
||||
|
||||
// Fridge contents
|
||||
switch(contents.len)
|
||||
if(0)
|
||||
add_overlay("empty[is_off]")
|
||||
if(1 to 2)
|
||||
add_overlay("[icon_contents]-1[is_off]")
|
||||
if(3 to 5)
|
||||
add_overlay("[icon_contents]-2[is_off]")
|
||||
if(6 to 8)
|
||||
add_overlay("[icon_contents]-3[is_off]")
|
||||
else
|
||||
add_overlay("[icon_contents]-4[is_off]")
|
||||
if(contents)
|
||||
switch(contents.len)
|
||||
if(0)
|
||||
add_overlay("empty[is_off]")
|
||||
if(1 to 2)
|
||||
add_overlay("[icon_contents]-1[is_off]")
|
||||
if(3 to 5)
|
||||
add_overlay("[icon_contents]-2[is_off]")
|
||||
if(6 to 8)
|
||||
add_overlay("[icon_contents]-3[is_off]")
|
||||
else
|
||||
add_overlay("[icon_contents]-4[is_off]")
|
||||
|
||||
// Fridge top
|
||||
var/image/top = image(icon, "[icon_base]-top")
|
||||
@@ -241,7 +242,6 @@
|
||||
user.visible_message("[user] [panel_open ? "opens" : "closes"] the maintenance panel of \the [src].", "You [panel_open ? "open" : "close"] the maintenance panel of \the [src].")
|
||||
playsound(src, O.usesound, 50, 1)
|
||||
update_icon()
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
|
||||
if(wrenchable && default_unfasten_wrench(user, O, 20))
|
||||
@@ -261,7 +261,6 @@
|
||||
stock(O)
|
||||
user.visible_message("<span class='notice'>[user] has added \the [O] to \the [src].</span>", "<span class='notice'>You add \the [O] to \the [src].</span>")
|
||||
|
||||
|
||||
else if(istype(O, /obj/item/weapon/storage/bag))
|
||||
var/obj/item/weapon/storage/bag/P = O
|
||||
var/plants_loaded = 0
|
||||
@@ -307,11 +306,11 @@
|
||||
var/datum/stored_item/item = new/datum/stored_item(src, O.type, O.name)
|
||||
item.add_product(O)
|
||||
item_records.Add(item)
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/smartfridge/proc/vend(datum/stored_item/I)
|
||||
I.get_product(get_turf(src))
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/smartfridge/attack_ai(mob/user as mob)
|
||||
attack_hand(user)
|
||||
@@ -320,66 +319,59 @@
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
wires.Interact(user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/*******************
|
||||
* SmartFridge Menu
|
||||
********************/
|
||||
/obj/machinery/smartfridge/tgui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "SmartVend", name)
|
||||
ui.set_autoupdate(FALSE)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/smartfridge/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
user.set_machine(src)
|
||||
/obj/machinery/smartfridge/tgui_data(mob/user)
|
||||
. = list()
|
||||
|
||||
var/data[0]
|
||||
data["contents"] = null
|
||||
data["electrified"] = seconds_electrified > 0
|
||||
data["shoot_inventory"] = shoot_inventory
|
||||
data["locked"] = locked
|
||||
data["secure"] = is_secure
|
||||
|
||||
var/list/items[0]
|
||||
for (var/i=1 to length(item_records))
|
||||
var/list/items = list()
|
||||
for(var/i=1 to length(item_records))
|
||||
var/datum/stored_item/I = item_records[i]
|
||||
var/count = I.get_amount()
|
||||
if(count > 0)
|
||||
items.Add(list(list("display_name" = html_encode(capitalize(I.item_name)), "vend" = i, "quantity" = count)))
|
||||
items.Add(list(list("name" = html_encode(capitalize(I.item_name)), "index" = i, "amount" = count)))
|
||||
|
||||
if(items.len > 0)
|
||||
data["contents"] = items
|
||||
.["contents"] = items
|
||||
.["name"] = name
|
||||
.["locked"] = locked
|
||||
.["secure"] = is_secure
|
||||
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "smartfridge.tmpl", src.name, 400, 500)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
/obj/machinery/smartfridge/tgui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/smartfridge/Topic(href, href_list)
|
||||
if(..()) return 0
|
||||
add_fingerprint(usr)
|
||||
switch(action)
|
||||
if("Release")
|
||||
var/amount = 0
|
||||
if(params["amount"])
|
||||
amount = params["amount"]
|
||||
else
|
||||
amount = input("How many items?", "How many items would you like to take out?", 1) as num|null
|
||||
|
||||
if(QDELETED(src) || QDELETED(usr) || !usr.Adjacent(src))
|
||||
return FALSE
|
||||
|
||||
var/index = text2num(params["index"])
|
||||
var/datum/stored_item/I = item_records[index]
|
||||
var/count = I.get_amount()
|
||||
|
||||
var/mob/user = usr
|
||||
var/datum/nanoui/ui = SSnanoui.get_open_ui(user, src, "main")
|
||||
// Sanity check, there are probably ways to press the button when it shouldn't be possible.
|
||||
if(count > 0)
|
||||
if((count - amount) < 0)
|
||||
amount = count
|
||||
for(var/i = 1 to amount)
|
||||
vend(I)
|
||||
|
||||
src.add_fingerprint(user)
|
||||
|
||||
if(href_list["close"])
|
||||
user.unset_machine()
|
||||
ui.close()
|
||||
return 0
|
||||
|
||||
if(href_list["vend"])
|
||||
var/index = text2num(href_list["vend"])
|
||||
var/amount = text2num(href_list["amount"])
|
||||
var/datum/stored_item/I = item_records[index]
|
||||
var/count = I.get_amount()
|
||||
|
||||
// Sanity check, there are probably ways to press the button when it shouldn't be possible.
|
||||
if(count > 0)
|
||||
if((count - amount) < 0)
|
||||
amount = count
|
||||
for(var/i = 1 to amount)
|
||||
vend(I)
|
||||
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/smartfridge/proc/throw_item()
|
||||
var/obj/throw_item = null
|
||||
@@ -398,17 +390,18 @@
|
||||
spawn(0)
|
||||
throw_item.throw_at(target,16,3,src)
|
||||
src.visible_message("<span class='warning'>[src] launches [throw_item.name] at [target.name]!</span>")
|
||||
SStgui.update_uis(src)
|
||||
return 1
|
||||
|
||||
/************************
|
||||
* Secure SmartFridges
|
||||
*************************/
|
||||
|
||||
/obj/machinery/smartfridge/secure/Topic(href, href_list)
|
||||
/obj/machinery/smartfridge/secure/tgui_act(action, params)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return 0
|
||||
return TRUE
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf)))
|
||||
if(!allowed(usr) && !emagged && locked != -1 && href_list["vend"])
|
||||
if(!allowed(usr) && !emagged && locked != -1 && action == "Release")
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
return 0
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
/mob/living/carbon/human/proc/change_appearance(var/flags = APPEARANCE_ALL_HAIR, var/location = src, var/mob/user = src, var/check_species_whitelist = 1, var/list/species_whitelist = list(), var/list/species_blacklist = list(), var/datum/topic_state/state = default_state)
|
||||
var/datum/nano_module/appearance_changer/AC = new(location, src, check_species_whitelist, species_whitelist, species_blacklist)
|
||||
/mob/living/carbon/human/proc/change_appearance(var/flags = APPEARANCE_ALL_HAIR,
|
||||
var/mob/user = src,
|
||||
var/check_species_whitelist = 1,
|
||||
var/list/species_whitelist = list(),
|
||||
var/list/species_blacklist = list(),
|
||||
var/datum/tgui_state/state = GLOB.tgui_self_state)
|
||||
var/datum/tgui_module/appearance_changer/AC = new(src, src, check_species_whitelist, species_whitelist, species_blacklist)
|
||||
AC.flags = flags
|
||||
AC.ui_interact(user, state = state)
|
||||
AC.tgui_interact(user, custom_state = state)
|
||||
|
||||
/mob/living/carbon/human/proc/change_species(var/new_species)
|
||||
if(!new_species)
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
|
||||
return get_turf(src)
|
||||
|
||||
/mob/proc/say_test(var/text)
|
||||
/proc/say_test(var/text)
|
||||
var/ending = copytext(text, length(text))
|
||||
if(ending == "?")
|
||||
return "1"
|
||||
|
||||
@@ -1,191 +0,0 @@
|
||||
/datum/nano_module/appearance_changer
|
||||
name = "Appearance Editor"
|
||||
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
|
||||
|
||||
/datum/nano_module/appearance_changer/New(var/location, var/mob/living/carbon/human/H, var/check_species_whitelist = 1, var/list/species_whitelist = list(), var/list/species_blacklist = list())
|
||||
..()
|
||||
owner = H
|
||||
src.check_whitelist = check_species_whitelist
|
||||
src.whitelist = species_whitelist
|
||||
src.blacklist = species_blacklist
|
||||
|
||||
/datum/nano_module/appearance_changer/Topic(ref, href_list, var/datum/topic_state/state = default_state)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["race"])
|
||||
if(can_change(APPEARANCE_RACE) && (href_list["race"] in valid_species))
|
||||
if(owner.change_species(href_list["race"]))
|
||||
cut_and_generate_data()
|
||||
return 1
|
||||
if(href_list["gender"])
|
||||
if(can_change(APPEARANCE_GENDER) && (href_list["gender"] in get_genders()))
|
||||
if(owner.change_gender(href_list["gender"]))
|
||||
cut_and_generate_data()
|
||||
return 1
|
||||
if(href_list["gender_id"])
|
||||
if(can_change(APPEARANCE_GENDER) && (href_list["gender_id"] in all_genders_define_list))
|
||||
owner.identifying_gender = href_list["gender_id"]
|
||||
return 1
|
||||
if(href_list["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", -owner.s_tone + 35) as num|null
|
||||
if(isnum(new_s_tone) && can_still_topic(state))
|
||||
new_s_tone = 35 - max(min( round(new_s_tone), 220),1)
|
||||
return owner.change_skin_tone(new_s_tone)
|
||||
if(href_list["skin_color"])
|
||||
if(can_change_skin_color())
|
||||
var/new_skin = input(usr, "Choose your character's skin colour: ", "Skin Color", rgb(owner.r_skin, owner.g_skin, owner.b_skin)) as color|null
|
||||
if(new_skin && can_still_topic(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(owner.change_skin_color(r_skin, g_skin, b_skin))
|
||||
update_dna()
|
||||
return 1
|
||||
if(href_list["hair"])
|
||||
if(can_change(APPEARANCE_HAIR) && (href_list["hair"] in valid_hairstyles))
|
||||
if(owner.change_hair(href_list["hair"]))
|
||||
update_dna()
|
||||
return 1
|
||||
if(href_list["hair_color"])
|
||||
if(can_change(APPEARANCE_HAIR_COLOR))
|
||||
var/new_hair = input("Please select hair color.", "Hair Color", rgb(owner.r_hair, owner.g_hair, owner.b_hair)) as color|null
|
||||
if(new_hair && can_still_topic(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(owner.change_hair_color(r_hair, g_hair, b_hair))
|
||||
update_dna()
|
||||
return 1
|
||||
if(href_list["facial_hair"])
|
||||
if(can_change(APPEARANCE_FACIAL_HAIR) && (href_list["facial_hair"] in valid_facial_hairstyles))
|
||||
if(owner.change_facial_hair(href_list["facial_hair"]))
|
||||
update_dna()
|
||||
return 1
|
||||
if(href_list["facial_hair_color"])
|
||||
if(can_change(APPEARANCE_FACIAL_HAIR_COLOR))
|
||||
var/new_facial = input("Please select facial hair color.", "Facial Hair Color", rgb(owner.r_facial, owner.g_facial, owner.b_facial)) as color|null
|
||||
if(new_facial && can_still_topic(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(owner.change_facial_hair_color(r_facial, g_facial, b_facial))
|
||||
update_dna()
|
||||
return 1
|
||||
if(href_list["eye_color"])
|
||||
if(can_change(APPEARANCE_EYE_COLOR))
|
||||
var/new_eyes = input("Please select eye color.", "Eye Color", rgb(owner.r_eyes, owner.g_eyes, owner.b_eyes)) as color|null
|
||||
if(new_eyes && can_still_topic(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(owner.change_eye_color(r_eyes, g_eyes, b_eyes))
|
||||
update_dna()
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/datum/nano_module/appearance_changer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
|
||||
|
||||
if(!owner || !owner.species)
|
||||
return
|
||||
|
||||
generate_data(check_whitelist, whitelist, blacklist)
|
||||
var/list/data = host.initial_data()
|
||||
|
||||
data["specimen"] = owner.species.name
|
||||
data["gender"] = owner.gender
|
||||
data["gender_id"] = owner.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_skin_tone"] = can_change_skin_tone()
|
||||
data["change_skin_color"] = can_change_skin_color()
|
||||
data["change_eye_color"] = can_change(APPEARANCE_EYE_COLOR)
|
||||
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"] = owner.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"] = owner.f_style
|
||||
|
||||
data["change_hair_color"] = can_change(APPEARANCE_HAIR_COLOR)
|
||||
data["change_facial_hair_color"] = can_change(APPEARANCE_FACIAL_HAIR_COLOR)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "appearance_changer.tmpl", "[src]", 800, 450, state = state)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/datum/nano_module/appearance_changer/proc/update_dna()
|
||||
if(owner && (flags & APPEARANCE_UPDATE_DNA))
|
||||
owner.update_dna()
|
||||
|
||||
/datum/nano_module/appearance_changer/proc/can_change(var/flag)
|
||||
return owner && (flags & flag)
|
||||
|
||||
/datum/nano_module/appearance_changer/proc/can_change_skin_tone()
|
||||
return owner && (flags & APPEARANCE_SKIN) && owner.species.appearance_flags & HAS_SKIN_TONE
|
||||
|
||||
/datum/nano_module/appearance_changer/proc/can_change_skin_color()
|
||||
return owner && (flags & APPEARANCE_SKIN) && owner.species.appearance_flags & HAS_SKIN_COLOR
|
||||
|
||||
/datum/nano_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/nano_module/appearance_changer/proc/generate_data()
|
||||
if(!owner)
|
||||
return
|
||||
if(!valid_species.len)
|
||||
valid_species = owner.generate_valid_species(check_whitelist, whitelist, blacklist)
|
||||
if(!valid_hairstyles.len || !valid_facial_hairstyles.len)
|
||||
valid_hairstyles = owner.generate_valid_hairstyles(check_gender = 0)
|
||||
valid_facial_hairstyles = owner.generate_valid_facial_hairstyles()
|
||||
|
||||
|
||||
/datum/nano_module/appearance_changer/proc/get_genders()
|
||||
var/datum/species/S = owner.species
|
||||
var/list/possible_genders = S.genders
|
||||
if(!owner.internal_organs_by_name["cell"])
|
||||
return possible_genders
|
||||
possible_genders = possible_genders.Copy()
|
||||
possible_genders |= NEUTER
|
||||
return possible_genders
|
||||
@@ -36,12 +36,8 @@
|
||||
to_chat(user, "<span class='notice'>You put [P] in [src].</span>")
|
||||
user.drop_item()
|
||||
P.loc = src
|
||||
icon_state = "[initial(icon_state)]-open"
|
||||
flick("[initial(icon_state)]-open",src)
|
||||
playsound(src, 'sound/bureaucracy/filingcabinet.ogg', 50, 1)
|
||||
sleep(40)
|
||||
icon_state = initial(icon_state)
|
||||
updateUsrDialog()
|
||||
open_animation()
|
||||
SStgui.update_uis(src)
|
||||
else if(P.is_wrench())
|
||||
playsound(src, P.usesound, 50, 1)
|
||||
anchored = !anchored
|
||||
@@ -65,20 +61,12 @@
|
||||
to_chat(user, "<span class='notice'>\The [src] is empty.</span>")
|
||||
return
|
||||
|
||||
user.set_machine(src)
|
||||
var/dat = "<center><table>"
|
||||
for(var/obj/item/P in src)
|
||||
dat += "<tr><td><a href='?src=\ref[src];retrieve=\ref[P]'>[P.name]</a></td></tr>"
|
||||
dat += "</table></center>"
|
||||
user << browse("<html><head><title>[name]</title></head><body>[dat]</body></html>", "window=filingcabinet;size=350x300")
|
||||
|
||||
return
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/structure/filingcabinet/attack_tk(mob/user)
|
||||
if(anchored)
|
||||
attack_self_tk(user)
|
||||
else
|
||||
..()
|
||||
return attack_self_tk(user)
|
||||
return ..()
|
||||
|
||||
/obj/structure/filingcabinet/attack_self_tk(mob/user)
|
||||
if(contents.len)
|
||||
@@ -91,20 +79,46 @@
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You find nothing in [src].</span>")
|
||||
|
||||
/obj/structure/filingcabinet/Topic(href, href_list)
|
||||
if(href_list["retrieve"])
|
||||
usr << browse("", "window=filingcabinet") // Close the menu
|
||||
/obj/structure/filingcabinet/tgui_state(mob/user)
|
||||
return GLOB.tgui_physical_state
|
||||
|
||||
//var/retrieveindex = text2num(href_list["retrieve"])
|
||||
var/obj/item/P = locate(href_list["retrieve"])//contents[retrieveindex]
|
||||
if(istype(P) && (P.loc == src) && src.Adjacent(usr))
|
||||
usr.put_in_hands(P)
|
||||
updateUsrDialog()
|
||||
flick("[initial(icon_state)]-open",src)
|
||||
playsound(src, 'sound/bureaucracy/filingcabinet.ogg', 50, 1)
|
||||
spawn(0)
|
||||
sleep(20)
|
||||
icon_state = initial(icon_state)
|
||||
/obj/structure/filingcabinet/tgui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "FileCabinet", name)
|
||||
ui.set_autoupdate(FALSE)
|
||||
ui.open()
|
||||
|
||||
/obj/structure/filingcabinet/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
data["contents"] = list()
|
||||
for(var/obj/item/P in src)
|
||||
data["contents"].Add(list(list(
|
||||
"name" = P.name,
|
||||
"ref" = "\ref[P]",
|
||||
)))
|
||||
|
||||
return data
|
||||
|
||||
/obj/structure/filingcabinet/tgui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
switch(action)
|
||||
if("retrieve")
|
||||
var/obj/item/P = locate(params["ref"])
|
||||
if(istype(P) && (P.loc == src) && usr.Adjacent(src))
|
||||
usr.put_in_hands(P)
|
||||
open_animation()
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/structure/filingcabinet/proc/open_animation()
|
||||
flick("[initial(icon_state)]-open",src)
|
||||
playsound(src, 'sound/bureaucracy/filingcabinet.ogg', 50, 1)
|
||||
spawn(0)
|
||||
sleep(20)
|
||||
icon_state = initial(icon_state)
|
||||
|
||||
/*
|
||||
* Security Record Cabinets
|
||||
@@ -112,7 +126,6 @@
|
||||
/obj/structure/filingcabinet/security
|
||||
var/virgin = 1
|
||||
|
||||
|
||||
/obj/structure/filingcabinet/security/proc/populate()
|
||||
if(virgin)
|
||||
for(var/datum/data/record/G in data_core.general)
|
||||
|
||||
@@ -144,6 +144,13 @@
|
||||
crash_with("[my_atom] attempted to add a reagent called '[id]' which doesn't exist. ([usr])")
|
||||
return 0
|
||||
|
||||
/datum/reagents/proc/isolate_reagent(reagent)
|
||||
for(var/A in reagent_list)
|
||||
var/datum/reagent/R = A
|
||||
if(R.id != reagent)
|
||||
del_reagent(R.id)
|
||||
update_total()
|
||||
|
||||
/datum/reagents/proc/remove_reagent(var/id, var/amount, var/safety = 0)
|
||||
if(!isnum(amount))
|
||||
return 0
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
#define LIQUID 2
|
||||
#define GAS 3
|
||||
|
||||
#define MAX_PILL_SPRITE 24 //max icon state of the pill sprites
|
||||
#define MAX_BOTTLE_SPRITE 4 //max icon state of the pill sprites
|
||||
#define MAX_MULTI_AMOUNT 20 // Max number of pills/patches that can be made at once
|
||||
#define MAX_UNITS_PER_PILL 60 // Max amount of units in a pill
|
||||
#define MAX_UNITS_PER_PATCH 60 // Max amount of units in a patch
|
||||
#define MAX_UNITS_PER_BOTTLE 60 // Max amount of units in a bottle (it's volume)
|
||||
#define MAX_CUSTOM_NAME_LEN 64 // Max length of a custom pill/condiment/whatever
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -24,11 +32,11 @@
|
||||
var/condi = 0
|
||||
var/useramount = 15 // Last used amount
|
||||
var/pillamount = 10
|
||||
var/bottlesprite = "1"
|
||||
var/pillsprite = "1"
|
||||
var/list/bottle_styles
|
||||
var/bottlesprite = 1
|
||||
var/pillsprite = 1
|
||||
var/max_pill_count = 20
|
||||
var/tab = "home"
|
||||
var/analyze_data[0]
|
||||
var/printing = FALSE
|
||||
flags = OPENCONTAINER
|
||||
clicksound = "button"
|
||||
|
||||
@@ -48,6 +56,9 @@
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/machinery/chem_master/update_icon()
|
||||
icon_state = "mixer[beaker ? "1" : "0"]"
|
||||
|
||||
/obj/machinery/chem_master/attackby(var/obj/item/weapon/B as obj, var/mob/user as mob)
|
||||
|
||||
if(istype(B, /obj/item/weapon/reagent_containers/glass) || istype(B, /obj/item/weapon/reagent_containers/food))
|
||||
@@ -59,7 +70,7 @@
|
||||
user.drop_item()
|
||||
B.loc = src
|
||||
to_chat(user, "You add \the [B] to the machine.")
|
||||
icon_state = "mixer1"
|
||||
update_icon()
|
||||
|
||||
else if(istype(B, /obj/item/weapon/storage/pill_bottle))
|
||||
|
||||
@@ -85,247 +96,420 @@
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
user.set_machine(src)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/chem_master/ui_assets(mob/user)
|
||||
return list(
|
||||
get_asset_datum(/datum/asset/chem_master),
|
||||
)
|
||||
|
||||
/obj/machinery/chem_master/tgui_interact(mob/user, datum/tgui/ui = null)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "ChemMaster", name)
|
||||
ui.open()
|
||||
|
||||
/**
|
||||
* Display the NanoUI window for the chem master.
|
||||
*
|
||||
* See NanoUI documentation for details.
|
||||
*/
|
||||
/obj/machinery/chem_master/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
user.set_machine(src)
|
||||
|
||||
/obj/machinery/chem_master/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["tab"] = tab
|
||||
|
||||
data["condi"] = condi
|
||||
|
||||
data["loaded_pill_bottle"] = !!loaded_pill_bottle
|
||||
if(loaded_pill_bottle)
|
||||
data["pillBottle"] = list("total" = loaded_pill_bottle.contents.len, "max" = loaded_pill_bottle.max_storage_space)
|
||||
else
|
||||
data["pillBottle"] = null
|
||||
data["loaded_pill_bottle_name"] = loaded_pill_bottle.name
|
||||
data["loaded_pill_bottle_contents_len"] = loaded_pill_bottle.contents.len
|
||||
data["loaded_pill_bottle_storage_slots"] = loaded_pill_bottle.max_storage_space
|
||||
|
||||
data["beaker"] = !!beaker
|
||||
if(beaker)
|
||||
var/datum/reagents/R = beaker.reagents
|
||||
var/ui_reagent_beaker_list[0]
|
||||
for(var/datum/reagent/G in R.reagent_list)
|
||||
ui_reagent_beaker_list[++ui_reagent_beaker_list.len] = list("name" = G.name, "volume" = G.volume, "description" = G.description, "id" = G.id)
|
||||
var/list/beaker_reagents_list = list()
|
||||
data["beaker_reagents"] = beaker_reagents_list
|
||||
for(var/datum/reagent/R in beaker.reagents.reagent_list)
|
||||
beaker_reagents_list[++beaker_reagents_list.len] = list("name" = R.name, "volume" = R.volume, "description" = R.description, "id" = R.id)
|
||||
|
||||
data["beaker"] = list("total_volume" = R.total_volume, "reagent_list" = ui_reagent_beaker_list)
|
||||
else
|
||||
data["beaker"] = null
|
||||
|
||||
if(reagents.total_volume)
|
||||
var/ui_reagent_list[0]
|
||||
for(var/datum/reagent/N in reagents.reagent_list)
|
||||
ui_reagent_list[++ui_reagent_list.len] = list("name" = N.name, "volume" = N.volume, "description" = N.description, "id" = N.id)
|
||||
|
||||
data["reagents"] = list("total_volume" = reagents.total_volume, "reagent_list" = ui_reagent_list)
|
||||
else
|
||||
data["reagents"] = null
|
||||
var/list/buffer_reagents_list = list()
|
||||
data["buffer_reagents"] = buffer_reagents_list
|
||||
for(var/datum/reagent/R in reagents.reagent_list)
|
||||
buffer_reagents_list[++buffer_reagents_list.len] = list("name" = R.name, "volume" = R.volume, "id" = R.id, "description" = R.description)
|
||||
|
||||
data["pillsprite"] = pillsprite
|
||||
data["bottlesprite"] = bottlesprite
|
||||
data["mode"] = mode
|
||||
data["printing"] = printing
|
||||
|
||||
if(analyze_data)
|
||||
data["analyzeData"] = list("name" = analyze_data["name"], "desc" = analyze_data["desc"], "blood_type" = analyze_data["blood_type"], "blood_DNA" = analyze_data["blood_DNA"])
|
||||
else
|
||||
data["analyzeData"] = null
|
||||
// Transfer modal information if there is one
|
||||
data["modal"] = tgui_modal_data(src)
|
||||
|
||||
data["pillSprite"] = pillsprite
|
||||
data["bottleSprite"] = bottlesprite
|
||||
return data
|
||||
|
||||
var/P[24] //how many pill sprites there are. Sprites are taken from chemical.dmi and can be found in nano/images/pill.png
|
||||
for(var/i = 1 to P.len)
|
||||
P[i] = i
|
||||
data["pillSpritesAmount"] = P
|
||||
/**
|
||||
* Called in tgui_act() to process modal actions
|
||||
*
|
||||
* Arguments:
|
||||
* * action - The action passed by tgui
|
||||
* * params - The params passed by tgui
|
||||
*/
|
||||
/obj/machinery/chem_master/proc/tgui_act_modal(action, params, datum/tgui/ui, datum/tgui_state/state)
|
||||
. = TRUE
|
||||
var/id = params["id"] // The modal's ID
|
||||
var/list/arguments = istext(params["arguments"]) ? json_decode(params["arguments"]) : params["arguments"]
|
||||
switch(tgui_modal_act(src, action, params))
|
||||
if(TGUI_MODAL_OPEN)
|
||||
switch(id)
|
||||
if("analyze")
|
||||
var/idx = text2num(arguments["idx"]) || 0
|
||||
var/from_beaker = text2num(arguments["beaker"]) || FALSE
|
||||
var/reagent_list = from_beaker ? beaker.reagents.reagent_list : reagents.reagent_list
|
||||
if(idx < 1 || idx > length(reagent_list))
|
||||
return
|
||||
|
||||
data["bottleSpritesAmount"] = list(1, 2, 3, 4) //how many bottle sprites there are. Sprites are taken from chemical.dmi and can be found in nano/images/pill.png
|
||||
var/datum/reagent/R = reagent_list[idx]
|
||||
var/list/result = list("idx" = idx, "name" = R.name, "desc" = R.description)
|
||||
if(!condi && istype(R, /datum/reagent/blood))
|
||||
var/datum/reagent/blood/B = R
|
||||
result["blood_type"] = B.data["blood_type"]
|
||||
result["blood_dna"] = B.data["blood_DNA"]
|
||||
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "chem_master.tmpl", src.name, 575, 400)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(5)
|
||||
arguments["analysis"] = result
|
||||
tgui_modal_message(src, id, "", null, arguments)
|
||||
// if("change_pill_bottle_style")
|
||||
// if(!loaded_pill_bottle)
|
||||
// return
|
||||
// if(!pill_bottle_wrappers)
|
||||
// pill_bottle_wrappers = list(
|
||||
// "CLEAR" = "Default",
|
||||
// COLOR_RED = "Red",
|
||||
// COLOR_GREEN = "Green",
|
||||
// COLOR_PALE_BTL_GREEN = "Pale green",
|
||||
// COLOR_BLUE = "Blue",
|
||||
// COLOR_CYAN_BLUE = "Light blue",
|
||||
// COLOR_TEAL = "Teal",
|
||||
// COLOR_YELLOW = "Yellow",
|
||||
// COLOR_ORANGE = "Orange",
|
||||
// COLOR_PINK = "Pink",
|
||||
// COLOR_MAROON = "Brown"
|
||||
// )
|
||||
// var/current = pill_bottle_wrappers[loaded_pill_bottle.wrapper_color] || "Default"
|
||||
// tgui_modal_choice(src, id, "Please select a pill bottle wrapper:", null, arguments, current, pill_bottle_wrappers)
|
||||
if("addcustom")
|
||||
if(!beaker || !beaker.reagents.total_volume)
|
||||
return
|
||||
tgui_modal_input(src, id, "Please enter the amount to transfer to buffer:", null, arguments, useramount)
|
||||
if("removecustom")
|
||||
if(!reagents.total_volume)
|
||||
return
|
||||
tgui_modal_input(src, id, "Please enter the amount to transfer to [mode ? "beaker" : "disposal"]:", null, arguments, useramount)
|
||||
if("create_condi_pack")
|
||||
if(!condi || !reagents.total_volume)
|
||||
return
|
||||
tgui_modal_input(src, id, "Please name your new condiment pack:", null, arguments, reagents.get_master_reagent_name(), MAX_CUSTOM_NAME_LEN)
|
||||
if("create_pill")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
var/num = round(text2num(arguments["num"] || 1))
|
||||
if(!num)
|
||||
return
|
||||
arguments["num"] = num
|
||||
var/amount_per_pill = CLAMP(reagents.total_volume / num, 0, MAX_UNITS_PER_PILL)
|
||||
var/default_name = "[reagents.get_master_reagent_name()] ([amount_per_pill]u)"
|
||||
var/pills_text = num == 1 ? "new pill" : "[num] new pills"
|
||||
tgui_modal_input(src, id, "Please name your [pills_text]:", null, arguments, default_name, MAX_CUSTOM_NAME_LEN)
|
||||
if("create_pill_multiple")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
tgui_modal_input(src, id, "Please enter the amount of pills to make (max [MAX_MULTI_AMOUNT] at a time):", null, arguments, pillamount, 5)
|
||||
if("change_pill_style")
|
||||
var/list/choices = list()
|
||||
for(var/i = 1 to MAX_PILL_SPRITE)
|
||||
choices += "pill[i].png"
|
||||
tgui_modal_bento(src, id, "Please select the new style for pills:", null, arguments, pillsprite, choices)
|
||||
if("create_patch")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
var/num = round(text2num(arguments["num"] || 1))
|
||||
if(!num)
|
||||
return
|
||||
arguments["num"] = num
|
||||
var/amount_per_patch = CLAMP(reagents.total_volume / num, 0, MAX_UNITS_PER_PATCH)
|
||||
var/default_name = "[reagents.get_master_reagent_name()] ([amount_per_patch]u)"
|
||||
var/patches_text = num == 1 ? "new patch" : "[num] new patches"
|
||||
tgui_modal_input(src, id, "Please name your [patches_text]:", null, arguments, default_name, MAX_CUSTOM_NAME_LEN)
|
||||
if("create_patch_multiple")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
tgui_modal_input(src, id, "Please enter the amount of patches to make (max [MAX_MULTI_AMOUNT] at a time):", null, arguments, pillamount, 5)
|
||||
if("create_bottle")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
var/num = round(text2num(arguments["num"] || 1))
|
||||
if(!num)
|
||||
return
|
||||
arguments["num"] = num
|
||||
var/amount_per_bottle = CLAMP(reagents.total_volume / num, 0, MAX_UNITS_PER_BOTTLE)
|
||||
var/default_name = "[reagents.get_master_reagent_name()]"
|
||||
var/bottles_text = num == 1 ? "new bottle" : "[num] new bottles"
|
||||
tgui_modal_input(src, id, "Please name your [bottles_text] ([amount_per_bottle]u in bottle):", null, arguments, default_name, MAX_CUSTOM_NAME_LEN)
|
||||
if("create_bottle_multiple")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
tgui_modal_input(src, id, "Please enter the amount of bottles to make (max [MAX_MULTI_AMOUNT] at a time):", null, arguments, pillamount, 5)
|
||||
if("change_bottle_style")
|
||||
var/list/choices = list()
|
||||
for(var/i = 1 to MAX_BOTTLE_SPRITE)
|
||||
choices += "bottle-[i].png"
|
||||
tgui_modal_bento(src, id, "Please select the new style for bottles:", null, arguments, bottlesprite, choices)
|
||||
else
|
||||
return FALSE
|
||||
if(TGUI_MODAL_ANSWER)
|
||||
var/answer = params["answer"]
|
||||
switch(id)
|
||||
// if("change_pill_bottle_style")
|
||||
// if(!pill_bottle_wrappers || !loaded_pill_bottle) // wat?
|
||||
// return
|
||||
// var/color = "CLEAR"
|
||||
// for(var/col in pill_bottle_wrappers)
|
||||
// var/col_name = pill_bottle_wrappers[col]
|
||||
// if(col_name == answer)
|
||||
// color = col
|
||||
// break
|
||||
// if(length(color) && color != "CLEAR")
|
||||
// loaded_pill_bottle.wrapper_color = color
|
||||
// loaded_pill_bottle.apply_wrap()
|
||||
// else
|
||||
// loaded_pill_bottle.wrapper_color = null
|
||||
// loaded_pill_bottle.cut_overlays()
|
||||
if("addcustom")
|
||||
var/amount = isgoodnumber(text2num(answer))
|
||||
if(!amount || !arguments["id"])
|
||||
return
|
||||
tgui_act("add", list("id" = arguments["id"], "amount" = amount), ui, state)
|
||||
if("removecustom")
|
||||
var/amount = isgoodnumber(text2num(answer))
|
||||
if(!amount || !arguments["id"])
|
||||
return
|
||||
tgui_act("remove", list("id" = arguments["id"], "amount" = amount), ui, state)
|
||||
if("create_condi_pack")
|
||||
if(!condi || !reagents.total_volume)
|
||||
return
|
||||
if(!length(answer))
|
||||
answer = reagents.get_master_reagent_name()
|
||||
var/obj/item/weapon/reagent_containers/pill/P = new(loc)
|
||||
P.name = "[answer] pack"
|
||||
P.desc = "A small condiment pack. The label says it contains [answer]."
|
||||
P.icon_state = "bouilloncube"//Reskinned monkey cube
|
||||
reagents.trans_to_obj(P, 10)
|
||||
if("create_pill")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
var/count = CLAMP(round(text2num(arguments["num"]) || 0), 0, MAX_MULTI_AMOUNT)
|
||||
if(!count)
|
||||
return
|
||||
|
||||
/obj/machinery/chem_master/Topic(href, href_list)
|
||||
if(stat & (BROKEN|NOPOWER)) return
|
||||
if(usr.stat || usr.restrained()) return
|
||||
if(!in_range(src, usr)) return
|
||||
if(!length(answer))
|
||||
answer = reagents.get_master_reagent_name()
|
||||
var/amount_per_pill = CLAMP(reagents.total_volume / count, 0, MAX_UNITS_PER_PILL)
|
||||
while(count--)
|
||||
if(reagents.total_volume <= 0)
|
||||
to_chat(usr, "<span class='notice'>Not enough reagents to create these pills!</span>")
|
||||
return
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
var/obj/item/weapon/reagent_containers/pill/P = new(loc)
|
||||
P.name = "[answer] pill"
|
||||
P.pixel_x = rand(-7, 7) // Random position
|
||||
P.pixel_y = rand(-7, 7)
|
||||
P.icon_state = "pill[pillsprite]"
|
||||
if(P.icon_state in list("pill1", "pill2", "pill3", "pill4")) // if using greyscale, take colour from reagent
|
||||
P.color = reagents.get_color()
|
||||
reagents.trans_to_obj(P, amount_per_pill)
|
||||
// Load the pills in the bottle if there's one loaded
|
||||
if(istype(loaded_pill_bottle) && length(loaded_pill_bottle.contents) < loaded_pill_bottle.max_storage_space)
|
||||
P.forceMove(loaded_pill_bottle)
|
||||
if("create_pill_multiple")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
tgui_act("modal_open", list("id" = "create_pill", "arguments" = list("num" = answer)), ui, state)
|
||||
if("change_pill_style")
|
||||
var/new_style = CLAMP(text2num(answer) || 0, 0, MAX_PILL_SPRITE)
|
||||
if(!new_style)
|
||||
return
|
||||
pillsprite = new_style
|
||||
if("create_patch")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
var/count = CLAMP(round(text2num(arguments["num"]) || 0), 0, MAX_MULTI_AMOUNT)
|
||||
if(!count)
|
||||
return
|
||||
|
||||
if(!length(answer))
|
||||
answer = reagents.get_master_reagent_name()
|
||||
var/amount_per_patch = CLAMP(reagents.total_volume / count, 0, MAX_UNITS_PER_PATCH)
|
||||
// var/is_medical_patch = chemical_safety_check(reagents)
|
||||
while(count--)
|
||||
if(reagents.total_volume <= 0)
|
||||
to_chat(usr, "<span class='notice'>Not enough reagents to create these patches!</span>")
|
||||
return
|
||||
|
||||
var/obj/item/weapon/reagent_containers/pill/patch/P = new(loc)
|
||||
P.name = "[answer] patch"
|
||||
P.pixel_x = rand(-7, 7) // random position
|
||||
P.pixel_y = rand(-7, 7)
|
||||
reagents.trans_to_obj(P, amount_per_patch)
|
||||
// if(is_medical_patch)
|
||||
// P.instant_application = TRUE
|
||||
// P.icon_state = "bandaid_med"
|
||||
if("create_patch_multiple")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
tgui_act("modal_open", list("id" = "create_patch", "arguments" = list("num" = answer)), ui, state)
|
||||
if("create_bottle")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
var/count = CLAMP(round(text2num(arguments["num"]) || 0), 0, MAX_MULTI_AMOUNT)
|
||||
if(!count)
|
||||
return
|
||||
|
||||
if(!length(answer))
|
||||
answer = reagents.get_master_reagent_name()
|
||||
var/amount_per_bottle = CLAMP(reagents.total_volume / count, 0, MAX_UNITS_PER_BOTTLE)
|
||||
while(count--)
|
||||
if(reagents.total_volume <= 0)
|
||||
to_chat(usr, "<span class='notice'>Not enough reagents to create these bottles!</span>")
|
||||
return
|
||||
var/obj/item/weapon/reagent_containers/glass/bottle/P = new(loc)
|
||||
P.name = "[answer] bottle"
|
||||
P.pixel_x = rand(-7, 7) // random position
|
||||
P.pixel_y = rand(-7, 7)
|
||||
P.icon_state = "bottle-[bottlesprite]" || "bottle-1"
|
||||
reagents.trans_to_obj(P, amount_per_bottle)
|
||||
P.update_icon()
|
||||
if("create_bottle_multiple")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
tgui_act("modal_open", list("id" = "create_bottle", "arguments" = list("num" = answer)), ui, state)
|
||||
if("change_bottle_style")
|
||||
var/new_style = CLAMP(text2num(answer) || 0, 0, MAX_BOTTLE_SPRITE)
|
||||
if(!new_style)
|
||||
return
|
||||
bottlesprite = new_style
|
||||
else
|
||||
return FALSE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/chem_master/tgui_act(action, params, datum/tgui/ui, datum/tgui_state/state)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
if(tgui_act_modal(action, params, ui, state))
|
||||
return TRUE
|
||||
|
||||
add_fingerprint(usr)
|
||||
usr.set_machine(src)
|
||||
|
||||
if(href_list["tab_select"])
|
||||
tab = href_list["tab_select"]
|
||||
|
||||
if (href_list["ejectp"])
|
||||
if(loaded_pill_bottle)
|
||||
loaded_pill_bottle.forceMove(get_turf(src))
|
||||
|
||||
if(Adjacent(usr))
|
||||
usr.put_in_hands(loaded_pill_bottle)
|
||||
|
||||
loaded_pill_bottle = null
|
||||
|
||||
if(beaker)
|
||||
var/datum/reagents/R = beaker.reagents
|
||||
if (tab == "analyze")
|
||||
analyze_data["name"] = href_list["name"]
|
||||
analyze_data["desc"] = href_list["desc"]
|
||||
if(!condi)
|
||||
if(href_list["name"] == "Blood")
|
||||
var/datum/reagent/blood/G
|
||||
for(var/datum/reagent/F in R.reagent_list)
|
||||
if(F.name == href_list["name"])
|
||||
G = F
|
||||
break
|
||||
analyze_data["name"] = G.name
|
||||
analyze_data["blood_type"] = G.data["blood_type"]
|
||||
analyze_data["blood_DNA"] = G.data["blood_DNA"]
|
||||
|
||||
else if (href_list["add"])
|
||||
|
||||
if(href_list["amount"])
|
||||
var/id = href_list["add"]
|
||||
var/amount = CLAMP((text2num(href_list["amount"])), 0, 200)
|
||||
R.trans_id_to(src, id, amount)
|
||||
|
||||
else if (href_list["addcustom"])
|
||||
|
||||
var/id = href_list["addcustom"]
|
||||
useramount = input("Select the amount to transfer.", 30, useramount) as num
|
||||
useramount = CLAMP(useramount, 0, 200)
|
||||
src.Topic(null, list("amount" = "[useramount]", "add" = "[id]"))
|
||||
|
||||
else if (href_list["remove"])
|
||||
|
||||
if(href_list["amount"])
|
||||
var/id = href_list["remove"]
|
||||
var/amount = CLAMP((text2num(href_list["amount"])), 0, 200)
|
||||
if(mode)
|
||||
reagents.trans_id_to(beaker, id, amount)
|
||||
else
|
||||
reagents.remove_reagent(id, amount)
|
||||
|
||||
|
||||
else if (href_list["removecustom"])
|
||||
|
||||
var/id = href_list["removecustom"]
|
||||
useramount = input("Select the amount to transfer.", 30, useramount) as num
|
||||
useramount = CLAMP(useramount, 0, 200)
|
||||
src.Topic(null, list("amount" = "[useramount]", "remove" = "[id]"))
|
||||
|
||||
else if (href_list["toggle"])
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("toggle")
|
||||
mode = !mode
|
||||
|
||||
else if (href_list["eject"])
|
||||
if(beaker)
|
||||
beaker.forceMove(get_turf(src))
|
||||
|
||||
if(Adjacent(usr)) // So the AI doesn't get a beaker somehow.
|
||||
usr.put_in_hands(beaker)
|
||||
|
||||
beaker = null
|
||||
reagents.clear_reagents()
|
||||
icon_state = "mixer0"
|
||||
else if (href_list["createpill"] || href_list["createpill_multiple"])
|
||||
var/count = 1
|
||||
|
||||
if(reagents.total_volume/count < 1) //Sanity checking.
|
||||
if("ejectp")
|
||||
if(loaded_pill_bottle)
|
||||
loaded_pill_bottle.forceMove(get_turf(src))
|
||||
if(Adjacent(usr) && !issilicon(usr))
|
||||
usr.put_in_hands(loaded_pill_bottle)
|
||||
loaded_pill_bottle = null
|
||||
if("print")
|
||||
if(printing || condi)
|
||||
return
|
||||
|
||||
if (href_list["createpill_multiple"])
|
||||
count = input("Select the number of pills to make.", "Max [max_pill_count]", pillamount) as null|num
|
||||
if(!count) //Covers 0 and cancel
|
||||
return
|
||||
count = CLAMP(round(count), 1, max_pill_count) // Fix decimals input and clamp to reasonable amounts
|
||||
|
||||
if(reagents.total_volume/count < 1) //Sanity checking.
|
||||
var/idx = text2num(params["idx"]) || 0
|
||||
var/from_beaker = text2num(params["beaker"]) || FALSE
|
||||
var/reagent_list = from_beaker ? beaker.reagents.reagent_list : reagents.reagent_list
|
||||
if(idx < 1 || idx > length(reagent_list))
|
||||
return
|
||||
|
||||
var/amount_per_pill = reagents.total_volume/count
|
||||
if (amount_per_pill > 60) amount_per_pill = 60
|
||||
var/datum/reagent/R = reagent_list[idx]
|
||||
|
||||
var/pill_cube = "pill"
|
||||
if(condi)//For the condimaster
|
||||
pill_cube = "cube"
|
||||
printing = TRUE
|
||||
visible_message("<span class='notice'>[src] rattles and prints out a sheet of paper.</span>")
|
||||
// playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1)
|
||||
|
||||
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(loc)
|
||||
P.info = "<center><b>Chemical Analysis</b></center><br>"
|
||||
P.info += "<b>Time of analysis:</b> [worldtime2stationtime(world.time)]<br><br>"
|
||||
P.info += "<b>Chemical name:</b> [R.name]<br>"
|
||||
if(istype(R, /datum/reagent/blood))
|
||||
var/datum/reagent/blood/B = R
|
||||
P.info += "<b>Description:</b> N/A<br><b>Blood Type:</b> [B.data["blood_type"]]<br><b>DNA:</b> [B.data["blood_DNA"]]"
|
||||
else
|
||||
pill_cube = "pill"
|
||||
P.info += "<b>Description:</b> [R.description]"
|
||||
P.info += "<br><br><b>Notes:</b><br>"
|
||||
P.name = "Chemical Analysis - [R.name]"
|
||||
spawn(50)
|
||||
printing = FALSE
|
||||
else
|
||||
. = FALSE
|
||||
|
||||
var/name = sanitizeSafe(input(usr,"Name:","Name your [pill_cube]!","[reagents.get_master_reagent_name()] ([amount_per_pill]u)") as null|text, MAX_NAME_LEN)
|
||||
if(. || !beaker)
|
||||
return
|
||||
|
||||
if(!name) //Blank name (sanitized to nothing, or left empty) or cancel
|
||||
. = TRUE
|
||||
var/datum/reagents/R = beaker.reagents
|
||||
switch(action)
|
||||
if("add")
|
||||
var/id = params["id"]
|
||||
var/amount = text2num(params["amount"])
|
||||
if(!id || !amount)
|
||||
return
|
||||
|
||||
|
||||
if(reagents.total_volume/count < 1) //Sanity checking.
|
||||
R.trans_id_to(src, id, amount)
|
||||
if("remove")
|
||||
var/id = params["id"]
|
||||
var/amount = text2num(params["amount"])
|
||||
if(!id || !amount)
|
||||
return
|
||||
while(count-- > 0) // Will definitely eventually stop.
|
||||
var/obj/item/weapon/reagent_containers/pill/P = new/obj/item/weapon/reagent_containers/pill(src.loc)
|
||||
if(!name) name = reagents.get_master_reagent_name()
|
||||
P.name = "[name] pill"
|
||||
P.pixel_x = rand(-7, 7) //random position
|
||||
P.pixel_y = rand(-7, 7)
|
||||
if(!condi) //If normal
|
||||
P.icon_state = "pill"+pillsprite
|
||||
else //If condi is on
|
||||
P.icon_state = "bouilloncube"//Reskinned monkey cube
|
||||
P.desc = "A dissolvable cube."
|
||||
|
||||
if(P.icon_state in list("pill1", "pill2", "pill3", "pill4")) // if using greyscale, take colour from reagent
|
||||
P.color = reagents.get_color()
|
||||
|
||||
reagents.trans_to_obj(P,amount_per_pill)
|
||||
if(src.loaded_pill_bottle)
|
||||
if(loaded_pill_bottle.contents.len < loaded_pill_bottle.max_storage_space)
|
||||
P.loc = loaded_pill_bottle
|
||||
|
||||
else if (href_list["createbottle"])
|
||||
if(!condi)
|
||||
var/name = sanitizeSafe(input(usr,"Name:","Name your bottle!",reagents.get_master_reagent_name()), MAX_NAME_LEN)
|
||||
var/obj/item/weapon/reagent_containers/glass/bottle/P = new/obj/item/weapon/reagent_containers/glass/bottle(src.loc)
|
||||
if(!name) name = reagents.get_master_reagent_name()
|
||||
P.name = "[name] bottle"
|
||||
P.pixel_x = rand(-7, 7) //random position
|
||||
P.pixel_y = rand(-7, 7)
|
||||
P.icon_state = "bottle-"+bottlesprite
|
||||
reagents.trans_to_obj(P,60)
|
||||
P.update_icon()
|
||||
if(mode)
|
||||
reagents.trans_id_to(beaker, id, amount)
|
||||
else
|
||||
var/obj/item/weapon/reagent_containers/food/condiment/P = new/obj/item/weapon/reagent_containers/food/condiment(src.loc)
|
||||
reagents.trans_to_obj(P,50)
|
||||
|
||||
else if (href_list["createpatch"])
|
||||
if(reagents.total_volume < 1) //Sanity checking.
|
||||
reagents.remove_reagent(id, amount)
|
||||
if("eject")
|
||||
if(!beaker)
|
||||
return
|
||||
|
||||
var/name = sanitizeSafe(input(usr,"Name:","Name your patch!","[reagents.get_master_reagent_name()] ([round(reagents.total_volume)]u)") as null|text, MAX_NAME_LEN)
|
||||
|
||||
if(!name) //Blank name (sanitized to nothing, or left empty) or cancel
|
||||
beaker.forceMove(get_turf(src))
|
||||
if(Adjacent(usr) && !issilicon(usr))
|
||||
usr.put_in_hands(beaker)
|
||||
beaker = null
|
||||
reagents.clear_reagents()
|
||||
update_icon()
|
||||
if("create_condi_bottle")
|
||||
if(!condi || !reagents.total_volume)
|
||||
return
|
||||
var/obj/item/weapon/reagent_containers/food/condiment/P = new(loc)
|
||||
reagents.trans_to_obj(P, 50)
|
||||
else
|
||||
return FALSE
|
||||
|
||||
if(reagents.total_volume < 1) //Sanity checking.
|
||||
return
|
||||
var/obj/item/weapon/reagent_containers/pill/patch/P = new/obj/item/weapon/reagent_containers/pill/patch(src.loc)
|
||||
if(!name) name = reagents.get_master_reagent_name()
|
||||
P.name = "[name] patch"
|
||||
P.pixel_x = rand(-7, 7) //random position
|
||||
P.pixel_y = rand(-7, 7)
|
||||
/obj/machinery/chem_master/attack_ai(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
reagents.trans_to_obj(P, 60)
|
||||
if(src.loaded_pill_bottle)
|
||||
if(loaded_pill_bottle.contents.len < loaded_pill_bottle.max_storage_space)
|
||||
P.loc = loaded_pill_bottle
|
||||
/obj/machinery/chem_master/proc/isgoodnumber(num)
|
||||
if(isnum(num))
|
||||
if(num > 200)
|
||||
num = 200
|
||||
else if(num < 0)
|
||||
num = 1
|
||||
return num
|
||||
else
|
||||
return FALSE
|
||||
|
||||
else if(href_list["pill_sprite"])
|
||||
pillsprite = href_list["pill_sprite"]
|
||||
else if(href_list["bottle_sprite"])
|
||||
bottlesprite = href_list["bottle_sprite"]
|
||||
|
||||
SSnanoui.update_uis(src)
|
||||
|
||||
/obj/machinery/chem_master/attack_ai(mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
// /obj/machinery/chem_master/proc/chemical_safety_check(datum/reagents/R)
|
||||
// var/all_safe = TRUE
|
||||
// for(var/datum/reagent/A in R.reagent_list)
|
||||
// if(!GLOB.safe_chem_list.Find(A.id))
|
||||
// all_safe = FALSE
|
||||
// return all_safe
|
||||
|
||||
/obj/machinery/chem_master/condimaster
|
||||
name = "CondiMaster 3000"
|
||||
@@ -365,11 +549,41 @@
|
||||
/obj/item/stack/material/glass/phoronglass = list("platinum", "silicon", "silicon", "silicon"), //5 platinum, 15 silicon,
|
||||
)
|
||||
|
||||
var/static/radial_examine = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_examine")
|
||||
var/static/radial_eject = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_eject")
|
||||
var/static/radial_grind = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_grind")
|
||||
// var/static/radial_juice = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_juice")
|
||||
// var/static/radial_mix = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_mix")
|
||||
|
||||
/obj/machinery/reagentgrinder/Initialize()
|
||||
. = ..()
|
||||
beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
|
||||
default_apply_parts()
|
||||
|
||||
/obj/machinery/reagentgrinder/examine(mob/user)
|
||||
. = ..()
|
||||
if(!in_range(user, src) && !issilicon(user) && !isobserver(user))
|
||||
. += "<span class='warning'>You're too far away to examine [src]'s contents and display!</span>"
|
||||
return
|
||||
|
||||
if(inuse)
|
||||
. += "<span class='warning'>\The [src] is operating.</span>"
|
||||
return
|
||||
|
||||
if(beaker || length(holdingitems))
|
||||
. += "<span class='notice'>\The [src] contains:</span>"
|
||||
if(beaker)
|
||||
. += "<span class='notice'>- \A [beaker].</span>"
|
||||
for(var/i in holdingitems)
|
||||
var/obj/item/O = i
|
||||
. += "<span class='notice'>- \A [O.name].</span>"
|
||||
|
||||
if(!(stat & (NOPOWER|BROKEN)))
|
||||
. += "<span class='notice'>The status display reads:</span>\n"
|
||||
if(beaker)
|
||||
for(var/datum/reagent/R in beaker.reagents.reagent_list)
|
||||
. += "<span class='notice'>- [R.volume] units of [R.name].</span>"
|
||||
|
||||
/obj/machinery/reagentgrinder/update_icon()
|
||||
icon_state = "juicer"+num2text(!isnull(beaker))
|
||||
return
|
||||
@@ -444,94 +658,65 @@
|
||||
user.remove_from_mob(O)
|
||||
O.loc = src
|
||||
holdingitems += O
|
||||
src.updateUsrDialog()
|
||||
return 0
|
||||
|
||||
/obj/machinery/reagentgrinder/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(user.incapacitated() || !Adjacent(user))
|
||||
return
|
||||
replace_beaker(user)
|
||||
|
||||
/obj/machinery/reagentgrinder/attack_hand(mob/user as mob)
|
||||
user.set_machine(src)
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/reagentgrinder/interact(mob/user as mob) // The microwave Menu
|
||||
var/is_chamber_empty = 0
|
||||
var/is_beaker_ready = 0
|
||||
var/processing_chamber = ""
|
||||
var/beaker_contents = ""
|
||||
var/dat = ""
|
||||
/obj/machinery/reagentgrinder/interact(mob/user as mob) // The microwave Menu //I am reasonably certain that this is not a microwave
|
||||
if(inuse || user.incapacitated())
|
||||
return
|
||||
|
||||
if(!inuse)
|
||||
for (var/obj/item/O in holdingitems)
|
||||
processing_chamber += "\A [O.name]<BR>"
|
||||
var/list/options = list()
|
||||
|
||||
if (!processing_chamber)
|
||||
is_chamber_empty = 1
|
||||
processing_chamber = "Nothing."
|
||||
if (!beaker)
|
||||
beaker_contents = "<B>No beaker attached.</B><br>"
|
||||
else
|
||||
is_beaker_ready = 1
|
||||
beaker_contents = "<B>The beaker contains:</B><br>"
|
||||
var/anything = 0
|
||||
for(var/datum/reagent/R in beaker.reagents.reagent_list)
|
||||
anything = 1
|
||||
beaker_contents += "[R.volume] - [R.name]<br>"
|
||||
if(!anything)
|
||||
beaker_contents += "Nothing<br>"
|
||||
if(beaker || length(holdingitems))
|
||||
options["eject"] = radial_eject
|
||||
|
||||
if(isAI(user))
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
options["examine"] = radial_examine
|
||||
|
||||
dat = {"
|
||||
<b>Processing chamber contains:</b><br>
|
||||
[processing_chamber]<br>
|
||||
[beaker_contents]<hr>
|
||||
"}
|
||||
if (is_beaker_ready && !is_chamber_empty && !(stat & (NOPOWER|BROKEN)))
|
||||
dat += "<A href='?src=\ref[src];action=grind'>Process the reagents</a><BR>"
|
||||
if(holdingitems && holdingitems.len > 0)
|
||||
dat += "<A href='?src=\ref[src];action=eject'>Eject the reagents</a><BR>"
|
||||
if (beaker)
|
||||
dat += "<A href='?src=\ref[src];action=detach'>Detach the beaker</a><BR>"
|
||||
// if there is no power or it's broken, the procs will fail but the buttons will still show
|
||||
if(length(holdingitems))
|
||||
options["grind"] = radial_grind
|
||||
|
||||
var/choice
|
||||
if(length(options) < 1)
|
||||
return
|
||||
if(length(options) == 1)
|
||||
for(var/key in options)
|
||||
choice = key
|
||||
else
|
||||
dat += "Please wait..."
|
||||
user << browse("<HEAD><TITLE>All-In-One Grinder</TITLE></HEAD><TT>[dat]</TT>", "window=reagentgrinder")
|
||||
onclose(user, "reagentgrinder")
|
||||
return
|
||||
choice = show_radial_menu(user, src, options, require_near = !issilicon(user))
|
||||
|
||||
|
||||
/obj/machinery/reagentgrinder/Topic(href, href_list)
|
||||
if(..())
|
||||
// post choice verification
|
||||
if(inuse || (isAI(user) && stat & NOPOWER) || user.incapacitated())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
switch(href_list["action"])
|
||||
if ("grind")
|
||||
grind()
|
||||
|
||||
switch(choice)
|
||||
if("eject")
|
||||
eject()
|
||||
if ("detach")
|
||||
detach()
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
eject(user)
|
||||
if("grind")
|
||||
grind(user)
|
||||
if("examine")
|
||||
examine(user)
|
||||
|
||||
/obj/machinery/reagentgrinder/proc/detach()
|
||||
|
||||
if (usr.stat != 0)
|
||||
/obj/machinery/reagentgrinder/proc/eject(mob/user)
|
||||
if(user.incapacitated())
|
||||
return
|
||||
if (!beaker)
|
||||
return
|
||||
beaker.loc = src.loc
|
||||
beaker = null
|
||||
visible_message("<span class='notice'>\The [usr] remove the container from \the [src].</span>")
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/reagentgrinder/proc/eject()
|
||||
|
||||
if (usr.stat != 0)
|
||||
return
|
||||
if (!holdingitems || holdingitems.len == 0)
|
||||
return
|
||||
|
||||
for(var/obj/item/O in holdingitems)
|
||||
O.loc = src.loc
|
||||
holdingitems -= O
|
||||
holdingitems.Cut()
|
||||
if(beaker)
|
||||
replace_beaker(user)
|
||||
|
||||
/obj/machinery/reagentgrinder/proc/grind()
|
||||
|
||||
@@ -549,7 +734,6 @@
|
||||
// Reset the machine.
|
||||
spawn(60)
|
||||
inuse = 0
|
||||
interact(usr)
|
||||
|
||||
// Process.
|
||||
for (var/obj/item/O in holdingitems)
|
||||
@@ -576,13 +760,26 @@
|
||||
continue
|
||||
|
||||
if(O.reagents)
|
||||
O.reagents.trans_to(beaker, min(O.reagents.total_volume, remaining_volume))
|
||||
O.reagents.trans_to_obj(beaker, min(O.reagents.total_volume, remaining_volume))
|
||||
if(O.reagents.total_volume == 0)
|
||||
holdingitems -= O
|
||||
qdel(O)
|
||||
if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
|
||||
break
|
||||
|
||||
/obj/machinery/reagentgrinder/proc/replace_beaker(mob/living/user, obj/item/weapon/reagent_containers/new_beaker)
|
||||
if(!user)
|
||||
return FALSE
|
||||
if(beaker)
|
||||
if(!user.incapacitated() && Adjacent(user))
|
||||
user.put_in_hands(beaker)
|
||||
else
|
||||
beaker.forceMove(drop_location())
|
||||
beaker = null
|
||||
if(new_beaker)
|
||||
beaker = new_beaker
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
///////////////
|
||||
///////////////
|
||||
@@ -648,4 +845,12 @@
|
||||
to_chat(user, span("notice", "Scanning of \the [I] complete."))
|
||||
analyzing = FALSE
|
||||
update_icon()
|
||||
return
|
||||
return
|
||||
|
||||
#undef MAX_PILL_SPRITE
|
||||
#undef MAX_BOTTLE_SPRITE
|
||||
#undef MAX_MULTI_AMOUNT
|
||||
#undef MAX_UNITS_PER_PILL
|
||||
#undef MAX_UNITS_PER_PATCH
|
||||
#undef MAX_UNITS_PER_BOTTLE
|
||||
#undef MAX_CUSTOM_NAME_LEN
|
||||
|
||||
@@ -68,12 +68,12 @@
|
||||
C.loc = src
|
||||
cartridges[C.label] = C
|
||||
cartridges = sortAssoc(cartridges)
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/chemical_dispenser/proc/remove_cartridge(label)
|
||||
. = cartridges[label]
|
||||
cartridges -= label
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/chemical_dispenser/attackby(obj/item/weapon/W, mob/user)
|
||||
if(W.is_wrench())
|
||||
@@ -119,25 +119,26 @@
|
||||
user.drop_from_inventory(RC)
|
||||
RC.loc = src
|
||||
to_chat(user, "<span class='notice'>You set \the [RC] on \the [src].</span>")
|
||||
SSnanoui.update_uis(src) // update all UIs attached to src
|
||||
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/chemical_dispenser/ui_interact(mob/user, ui_key = "main",var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
if(stat & (BROKEN|NOPOWER)) return
|
||||
if(user.stat || user.restrained()) return
|
||||
/obj/machinery/chemical_dispenser/tgui_interact(mob/user, datum/tgui/ui = null)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "ChemDispenser", ui_title) // 390, 655
|
||||
ui.open()
|
||||
|
||||
// this is the data which will be sent to the ui
|
||||
/obj/machinery/chemical_dispenser/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
data["amount"] = amount
|
||||
data["isBeakerLoaded"] = container ? 1 : 0
|
||||
data["glass"] = accept_drinking
|
||||
var beakerD[0]
|
||||
|
||||
var/beakerContents[0]
|
||||
if(container && container.reagents && container.reagents.reagent_list.len)
|
||||
for(var/datum/reagent/R in container.reagents.reagent_list)
|
||||
beakerD[++beakerD.len] = list("name" = R.name, "volume" = R.volume)
|
||||
data["beakerContents"] = beakerD
|
||||
beakerContents.Add(list(list("name" = R.name, "id" = R.id, "volume" = R.volume))) // list in a list because Byond merges the first list...
|
||||
data["beakerContents"] = beakerContents
|
||||
|
||||
if(container)
|
||||
data["beakerCurrentVolume"] = container.reagents.total_volume
|
||||
@@ -146,50 +147,59 @@
|
||||
data["beakerCurrentVolume"] = null
|
||||
data["beakerMaxVolume"] = null
|
||||
|
||||
var chemicals[0]
|
||||
var/chemicals[0]
|
||||
for(var/label in cartridges)
|
||||
var/obj/item/weapon/reagent_containers/chem_disp_cartridge/C = cartridges[label]
|
||||
chemicals[++chemicals.len] = list("label" = label, "amount" = C.reagents.total_volume)
|
||||
chemicals.Add(list(list("title" = label, "id" = label, "amount" = C.reagents.total_volume))) // list in a list because Byond merges the first list...
|
||||
data["chemicals"] = chemicals
|
||||
return data
|
||||
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "chem_disp.tmpl", ui_title, 390, 680)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
/obj/machinery/chemical_dispenser/tgui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/chemical_dispenser/Topic(href, href_list)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return 0 // don't update UIs attached to this object
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("amount")
|
||||
amount = clamp(round(text2num(params["amount"]), 1), 0, 120) // round to nearest 1 and clamp 0 - 120
|
||||
if("dispense")
|
||||
var/label = params["reagent"]
|
||||
if(cartridges[label] && container && container.is_open_container())
|
||||
var/obj/item/weapon/reagent_containers/chem_disp_cartridge/C = cartridges[label]
|
||||
playsound(src, 'sound/machines/reagent_dispense.ogg', 25, 1)
|
||||
C.reagents.trans_to(container, amount)
|
||||
if("remove")
|
||||
var/amount = text2num(params["amount"])
|
||||
if(!container || !amount)
|
||||
return
|
||||
var/datum/reagents/R = container.reagents
|
||||
var/id = params["reagent"]
|
||||
if(amount > 0)
|
||||
R.remove_reagent(id, amount)
|
||||
else if(amount == -1) // Isolate
|
||||
R.isolate_reagent(id)
|
||||
if("ejectBeaker")
|
||||
if(container)
|
||||
container.forceMove(get_turf(src))
|
||||
|
||||
if(href_list["amount"])
|
||||
amount = round(text2num(href_list["amount"]), 1) // round to nearest 1
|
||||
amount = max(0, min(120, amount)) // Since the user can actually type the commands himself, some sanity checking
|
||||
if(Adjacent(usr)) // So the AI doesn't get a beaker somehow.
|
||||
usr.put_in_hands(container)
|
||||
|
||||
else if(href_list["dispense"])
|
||||
var/label = href_list["dispense"]
|
||||
if(cartridges[label] && container && container.is_open_container())
|
||||
var/obj/item/weapon/reagent_containers/chem_disp_cartridge/C = cartridges[label]
|
||||
playsound(src, 'sound/machines/reagent_dispense.ogg', 25, 1)
|
||||
C.reagents.trans_to(container, amount)
|
||||
|
||||
else if(href_list["ejectBeaker"])
|
||||
if(container)
|
||||
container.forceMove(get_turf(src))
|
||||
|
||||
if(Adjacent(usr)) // So the AI doesn't get a beaker somehow.
|
||||
usr.put_in_hands(container)
|
||||
|
||||
container = null
|
||||
container = null
|
||||
else
|
||||
return FALSE
|
||||
|
||||
add_fingerprint(usr)
|
||||
return 1 // update UIs attached to this object
|
||||
|
||||
/obj/machinery/chemical_dispenser/attack_ai(mob/user as mob)
|
||||
src.attack_hand(user)
|
||||
|
||||
/obj/machinery/chemical_dispenser/attack_hand(mob/user as mob)
|
||||
/obj/machinery/chemical_dispenser/attack_ghost(mob/user)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/chemical_dispenser/attack_ai(mob/user)
|
||||
attack_hand(user)
|
||||
|
||||
/obj/machinery/chemical_dispenser/attack_hand(mob/user)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
tgui_interact(user)
|
||||
|
||||
@@ -119,6 +119,8 @@
|
||||
max_duration = 100
|
||||
|
||||
/datum/surgery_step/cavity/place_item/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
|
||||
if(!istype(tool))
|
||||
return FALSE
|
||||
if(..())
|
||||
var/obj/item/organ/external/affected = target.get_organ(target_zone)
|
||||
if(istype(user,/mob/living/silicon/robot))
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
max_duration = 70
|
||||
|
||||
/datum/surgery_step/limb/attach/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
|
||||
if(!istype(tool))
|
||||
return FALSE
|
||||
var/obj/item/organ/external/E = tool
|
||||
var/obj/item/organ/external/P = target.organs_by_name[E.parent_organ]
|
||||
var/obj/item/organ/external/affected = target.get_organ(target_zone)
|
||||
@@ -117,7 +119,7 @@
|
||||
max_duration = 100
|
||||
|
||||
/datum/surgery_step/limb/mechanize/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
|
||||
if(..())
|
||||
if(..() && istype(tool))
|
||||
var/obj/item/robot_parts/p = tool
|
||||
if (p.part)
|
||||
if (!(target_zone in p.part))
|
||||
|
||||
@@ -164,6 +164,9 @@
|
||||
if (!..())
|
||||
return 0
|
||||
|
||||
if(!istype(tool))
|
||||
return FALSE
|
||||
|
||||
var/obj/item/organ/external/affected = target.get_organ(target_zone)
|
||||
|
||||
if(!(affected && !(affected.robotic >= ORGAN_ROBOT)))
|
||||
@@ -227,6 +230,9 @@
|
||||
if (!..())
|
||||
return 0
|
||||
|
||||
if(!istype(tool))
|
||||
return FALSE
|
||||
|
||||
target.op_stage.current_organ = null
|
||||
|
||||
var/list/removable_organs = list()
|
||||
@@ -281,7 +287,7 @@
|
||||
var/obj/item/organ/internal/O = tool
|
||||
var/obj/item/organ/external/affected = target.get_organ(target_zone)
|
||||
|
||||
if(!affected)
|
||||
if(!affected || !istype(O))
|
||||
return
|
||||
|
||||
var/organ_compatible
|
||||
@@ -361,6 +367,9 @@
|
||||
if (!..())
|
||||
return 0
|
||||
|
||||
if(!istype(tool))
|
||||
return FALSE
|
||||
|
||||
target.op_stage.current_organ = null
|
||||
|
||||
var/list/removable_organs = list()
|
||||
@@ -417,6 +426,9 @@
|
||||
if (!..())
|
||||
return 0
|
||||
|
||||
if(!istype(tool))
|
||||
return FALSE
|
||||
|
||||
target.op_stage.current_organ = null
|
||||
|
||||
var/list/removable_organs = list()
|
||||
|
||||
@@ -12,9 +12,10 @@
|
||||
*
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
* optional ui datum/tgui The UI to be updated, if it exists.
|
||||
* optional parent_ui datum/tgui A parent UI that, when closed, closes this UI as well.
|
||||
*/
|
||||
|
||||
/datum/proc/tgui_interact(mob/user, datum/tgui/ui = null)
|
||||
/datum/proc/tgui_interact(mob/user, datum/tgui/ui = null, datum/tgui/parent_ui = null)
|
||||
return FALSE // Not implemented.
|
||||
|
||||
/**
|
||||
@@ -27,7 +28,7 @@
|
||||
*
|
||||
* return list Data to be sent to the UI.
|
||||
*/
|
||||
/datum/proc/tgui_data(mob/user)
|
||||
/datum/proc/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
|
||||
return list() // Not implemented.
|
||||
|
||||
/**
|
||||
@@ -140,6 +141,26 @@
|
||||
*/
|
||||
/datum/proc/tgui_close(mob/user)
|
||||
|
||||
/**
|
||||
* verb
|
||||
*
|
||||
* Used by a client to fix broken TGUI windows caused by opening a UI window before assets load.
|
||||
* Probably not very performant and forcibly destroys a bunch of windows, so it has some warnings attached.
|
||||
* Conveniently, also allows devs to force a dev server reattach without relogging, since it yeets windows.
|
||||
*/
|
||||
/client/verb/tgui_fix_white()
|
||||
set desc = "Only use this if you have a broken TGUI window occupying your screen!"
|
||||
set name = "Fix TGUI"
|
||||
set category = "OOC"
|
||||
|
||||
if(alert(src, "Only use this verb if you have a white TGUI window stuck on your screen.", "Fix TGUI", "Continue", "Nevermind") != "Continue")
|
||||
return
|
||||
|
||||
SStgui.close_user_uis(mob)
|
||||
if(alert(src, "Did that fix the problem?", "Fix TGUI", "Yes", "No") == "No")
|
||||
SStgui.force_close_all_windows(mob)
|
||||
alert(src, "UIs should be fixed now. If not, please cry to your nearest coder.", "Fix TGUI")
|
||||
|
||||
/**
|
||||
* verb
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -36,13 +36,29 @@ GLOBAL_DATUM_INIT(tgui_default_state, /datum/tgui_state/default, new)
|
||||
return STATUS_DISABLED // Otherwise they can keep the UI open.
|
||||
|
||||
/mob/living/silicon/ai/default_can_use_tgui_topic(src_object)
|
||||
. = shared_tgui_interaction(src_object)
|
||||
if(. < STATUS_INTERACTIVE)
|
||||
. = shared_tgui_interaction()
|
||||
if(. != STATUS_INTERACTIVE)
|
||||
return
|
||||
|
||||
// The AI can interact with anything it can see nearby, or with cameras while wireless control is enabled.
|
||||
if(!control_disabled && can_see(src_object))
|
||||
// Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras)
|
||||
// unless it's on the same level as the object it's interacting with.
|
||||
var/turf/T = get_turf(src_object)
|
||||
if(!T || !(z == T.z || (T.z in using_map.player_levels)))
|
||||
return STATUS_CLOSE
|
||||
|
||||
// If an object is in view then we can interact with it
|
||||
if(src_object in view(client.view, src))
|
||||
return STATUS_INTERACTIVE
|
||||
|
||||
// If we're installed in a chassi, rather than transfered to an inteliCard or other container, then check if we have camera view
|
||||
if(is_in_chassis())
|
||||
//stop AIs from leaving windows open and using then after they lose vision
|
||||
if(cameranet && !cameranet.checkTurfVis(get_turf(src_object)))
|
||||
return STATUS_CLOSE
|
||||
return STATUS_INTERACTIVE
|
||||
else if(get_dist(src_object, src) <= client.view) // View does not return what one would expect while installed in an inteliCard
|
||||
return STATUS_INTERACTIVE
|
||||
|
||||
return STATUS_CLOSE
|
||||
|
||||
/mob/living/simple_animal/default_can_use_tgui_topic(src_object)
|
||||
|
||||
@@ -34,8 +34,12 @@
|
||||
var/status = STATUS_INTERACTIVE
|
||||
/// Topic state used to determine status/interactability.
|
||||
var/datum/tgui_state/state = null
|
||||
// The map z-level to display.
|
||||
/// The map z-level to display.
|
||||
var/map_z_level = 1
|
||||
/// The Parent UI
|
||||
var/datum/tgui/parent_ui
|
||||
/// Children of this UI
|
||||
var/list/children = list()
|
||||
|
||||
/**
|
||||
* public
|
||||
@@ -46,12 +50,13 @@
|
||||
* required src_object datum The object or datum which owns the UI.
|
||||
* required interface string The interface used to render the UI.
|
||||
* optional title string The title of the UI.
|
||||
* optional parent_ui datum/tgui The parent of this UI.
|
||||
* optional ui_x int Deprecated: Window width.
|
||||
* optional ui_y int Deprecated: Window height.
|
||||
*
|
||||
* return datum/tgui The requested UI.
|
||||
*/
|
||||
/datum/tgui/New(mob/user, datum/src_object, interface, title, ui_x, ui_y)
|
||||
/datum/tgui/New(mob/user, datum/src_object, interface, title, datum/tgui/parent_ui, ui_x, ui_y)
|
||||
src.user = user
|
||||
src.src_object = src_object
|
||||
src.window_key = "[REF(src_object)]-main"
|
||||
@@ -59,6 +64,9 @@
|
||||
if(title)
|
||||
src.title = title
|
||||
src.state = src_object.tgui_state()
|
||||
src.parent_ui = parent_ui
|
||||
if(parent_ui)
|
||||
parent_ui.children += src
|
||||
// Deprecated
|
||||
if(ui_x && ui_y)
|
||||
src.window_size = list(ui_x, ui_y)
|
||||
@@ -100,10 +108,13 @@
|
||||
*
|
||||
* Close the UI, and all its children.
|
||||
*/
|
||||
/datum/tgui/proc/close(can_be_suspended = TRUE)
|
||||
/datum/tgui/proc/close(can_be_suspended = TRUE, logout = FALSE)
|
||||
if(closing)
|
||||
return
|
||||
closing = TRUE
|
||||
for(var/datum/tgui/child in children)
|
||||
child.close(can_be_suspended, logout)
|
||||
children.Cut()
|
||||
// If we don't have window_id, open proc did not have the opportunity
|
||||
// to finish, therefore it's safe to skip this whole block.
|
||||
if(window)
|
||||
@@ -111,10 +122,11 @@
|
||||
// and we want to keep them around, to allow user to read
|
||||
// the error message properly.
|
||||
window.release_lock()
|
||||
window.close(can_be_suspended)
|
||||
window.close(can_be_suspended, logout)
|
||||
src_object.tgui_close(user)
|
||||
SStgui.on_close(src)
|
||||
state = null
|
||||
parent_ui = null
|
||||
qdel(src)
|
||||
|
||||
/**
|
||||
@@ -209,7 +221,7 @@
|
||||
"observer" = isobserver(user),
|
||||
),
|
||||
)
|
||||
var/data = custom_data || with_data && src_object.tgui_data(user)
|
||||
var/data = custom_data || with_data && src_object.tgui_data(user, src, state)
|
||||
if(data)
|
||||
json_data["data"] = data
|
||||
var/static_data = with_static_data && src_object.tgui_static_data(user)
|
||||
@@ -244,7 +256,7 @@
|
||||
return
|
||||
// Update through a normal call to ui_interact
|
||||
if(status != STATUS_DISABLED && (autoupdate || force))
|
||||
src_object.tgui_interact(user, src)
|
||||
src_object.tgui_interact(user, src, parent_ui)
|
||||
return
|
||||
// Update status only
|
||||
var/needs_update = process_status()
|
||||
@@ -262,6 +274,8 @@
|
||||
/datum/tgui/proc/process_status()
|
||||
var/prev_status = status
|
||||
status = src_object.tgui_status(user, state)
|
||||
if(parent_ui)
|
||||
status = min(status, parent_ui.status)
|
||||
return prev_status != status
|
||||
|
||||
/datum/tgui/proc/log_message(message)
|
||||
|
||||
@@ -133,13 +133,19 @@
|
||||
*
|
||||
* optional can_be_suspended bool
|
||||
*/
|
||||
/datum/tgui_window/proc/close(can_be_suspended = TRUE)
|
||||
/datum/tgui_window/proc/close(can_be_suspended = TRUE, logout = FALSE)
|
||||
if(!client)
|
||||
return
|
||||
if(can_be_suspended && can_be_suspended())
|
||||
log_tgui(client, "[id]/close: suspending")
|
||||
status = TGUI_WINDOW_READY
|
||||
send_message("suspend")
|
||||
// You would think that BYOND would null out client or make it stop passing istypes or, y'know, ANYTHING during
|
||||
// logout, but nope! It appears to be perfectly valid to call winset by every means we can measure in Logout,
|
||||
// and yet it causes a bad client runtime. To avoid that happening, we just have to know if we're in Logout or
|
||||
// not.
|
||||
if(!logout && client)
|
||||
winset(client, null, "mapwindow.map.focus=true")
|
||||
return
|
||||
log_tgui(client, "[id]/close")
|
||||
release_lock()
|
||||
@@ -149,7 +155,8 @@
|
||||
// to read the error message.
|
||||
if(!fatally_errored)
|
||||
client << browse(null, "window=[id]")
|
||||
|
||||
if(!logout && client)
|
||||
winset(client, null, "mapwindow.map.focus=true")
|
||||
/**
|
||||
* public
|
||||
*
|
||||
@@ -189,9 +196,9 @@
|
||||
/datum/tgui_window/proc/send_asset(datum/asset/asset)
|
||||
if(!client || !asset)
|
||||
return
|
||||
// if(istype(asset, /datum/asset/spritesheet))
|
||||
// var/datum/asset/spritesheet/spritesheet = asset
|
||||
// send_message("asset/stylesheet", spritesheet.css_filename())
|
||||
if(istype(asset, /datum/asset/spritesheet))
|
||||
var/datum/asset/spritesheet/spritesheet = asset
|
||||
send_message("asset/stylesheet", spritesheet.css_filename())
|
||||
send_message("asset/mappings", asset.get_url_mappings())
|
||||
sent_assets += list(asset)
|
||||
asset.send(client)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
O.loc = src
|
||||
|
||||
user.visible_message("[user] adds \a [O] to \the [src]!", "You add \a [O] to \the [src]!")
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
src.attack_hand(user)
|
||||
|
||||
@@ -36,27 +36,32 @@
|
||||
icon_state = "centrifuge_moving"
|
||||
|
||||
/obj/machinery/computer/centrifuge/attack_hand(var/mob/user as mob)
|
||||
if(..()) return
|
||||
ui_interact(user)
|
||||
if(..())
|
||||
return
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/computer/centrifuge/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
user.set_machine(src)
|
||||
/obj/machinery/computer/centrifuge/tgui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "IsolationCentrifuge", name)
|
||||
ui.open()
|
||||
|
||||
var/data[0]
|
||||
/obj/machinery/computer/centrifuge/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["antibodies"] = null
|
||||
data["pathogens"] = null
|
||||
data["pathogens"] = list()
|
||||
data["is_antibody_sample"] = null
|
||||
data["busy"] = null
|
||||
data["sample_inserted"] = !!sample
|
||||
|
||||
if (curing)
|
||||
if(curing)
|
||||
data["busy"] = "Isolating antibodies..."
|
||||
else if (isolating)
|
||||
else if(isolating)
|
||||
data["busy"] = "Isolating pathogens..."
|
||||
else
|
||||
data["sample_inserted"] = !!sample
|
||||
|
||||
if (sample)
|
||||
if(sample)
|
||||
var/datum/reagent/blood/B = locate(/datum/reagent/blood) in sample.reagents.reagent_list
|
||||
if (B)
|
||||
if(B)
|
||||
data["antibodies"] = antigens2string(B.data["antibodies"], none=null)
|
||||
|
||||
var/list/pathogens[0]
|
||||
@@ -65,8 +70,7 @@
|
||||
var/datum/disease2/disease/V = virus[ID]
|
||||
pathogens.Add(list(list("name" = V.name(), "spread_type" = V.spreadtype, "reference" = "\ref[V]")))
|
||||
|
||||
if (pathogens.len > 0)
|
||||
data["pathogens"] = pathogens
|
||||
data["pathogens"] = pathogens
|
||||
|
||||
else
|
||||
var/datum/reagent/antibodies/A = locate(/datum/reagent/antibodies) in sample.reagents.reagent_list
|
||||
@@ -74,103 +78,90 @@
|
||||
data["antibodies"] = antigens2string(A.data["antibodies"], none=null)
|
||||
data["is_antibody_sample"] = 1
|
||||
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "isolation_centrifuge.tmpl", src.name, 400, 500)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/centrifuge/process()
|
||||
..()
|
||||
if (stat & (NOPOWER|BROKEN)) return
|
||||
if(stat & (NOPOWER|BROKEN)) return
|
||||
|
||||
if (curing)
|
||||
if(curing)
|
||||
curing -= 1
|
||||
if (curing == 0)
|
||||
if(curing == 0)
|
||||
cure()
|
||||
|
||||
if (isolating)
|
||||
if(isolating)
|
||||
isolating -= 1
|
||||
if(isolating == 0)
|
||||
isolate()
|
||||
|
||||
/obj/machinery/computer/centrifuge/Topic(href, href_list)
|
||||
if (..()) return 1
|
||||
/obj/machinery/computer/centrifuge/tgui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
var/mob/user = usr
|
||||
var/datum/nanoui/ui = SSnanoui.get_open_ui(user, src, "main")
|
||||
add_fingerprint(user)
|
||||
|
||||
src.add_fingerprint(user)
|
||||
|
||||
if (href_list["close"])
|
||||
user.unset_machine()
|
||||
ui.close()
|
||||
return 0
|
||||
|
||||
if (href_list["print"])
|
||||
print(user)
|
||||
return 1
|
||||
|
||||
if(href_list["isolate"])
|
||||
var/datum/reagent/blood/B = locate(/datum/reagent/blood) in sample.reagents.reagent_list
|
||||
if (B)
|
||||
var/datum/disease2/disease/virus = locate(href_list["isolate"])
|
||||
virus2 = virus.getcopy()
|
||||
isolating = 40
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
switch(href_list["action"])
|
||||
if ("antibody")
|
||||
switch(action)
|
||||
if("print")
|
||||
print(user)
|
||||
. = TRUE
|
||||
if("isolate")
|
||||
var/datum/reagent/blood/B = locate(/datum/reagent/blood) in sample.reagents.reagent_list
|
||||
if(B)
|
||||
var/datum/disease2/disease/virus = locate(params["isolate"])
|
||||
virus2 = virus.getcopy()
|
||||
isolating = 40
|
||||
update_icon()
|
||||
. = TRUE
|
||||
if("antibody")
|
||||
var/delay = 20
|
||||
var/datum/reagent/blood/B = locate(/datum/reagent/blood) in sample.reagents.reagent_list
|
||||
if (!B)
|
||||
if(!B)
|
||||
state("\The [src] buzzes, \"No antibody carrier detected.\"", "blue")
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
var/has_toxins = locate(/datum/reagent/toxin) in sample.reagents.reagent_list
|
||||
var/has_radium = sample.reagents.has_reagent("radium")
|
||||
if (has_toxins || has_radium)
|
||||
if(has_toxins || has_radium)
|
||||
state("\The [src] beeps, \"Pathogen purging speed above nominal.\"", "blue")
|
||||
if (has_toxins)
|
||||
if(has_toxins)
|
||||
delay = delay/2
|
||||
if (has_radium)
|
||||
if(has_radium)
|
||||
delay = delay/2
|
||||
|
||||
curing = round(delay)
|
||||
playsound(src, 'sound/machines/juicer.ogg', 50, 1)
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
. = TRUE
|
||||
if("sample")
|
||||
if(sample)
|
||||
sample.loc = src.loc
|
||||
sample = null
|
||||
return 1
|
||||
. = TRUE
|
||||
|
||||
return 0
|
||||
|
||||
/obj/machinery/computer/centrifuge/proc/cure()
|
||||
if (!sample) return
|
||||
if(!sample) return
|
||||
var/datum/reagent/blood/B = locate(/datum/reagent/blood) in sample.reagents.reagent_list
|
||||
if (!B) return
|
||||
if(!B) return
|
||||
|
||||
var/list/data = list("antibodies" = B.data["antibodies"])
|
||||
var/amt= sample.reagents.get_reagent_amount("blood")
|
||||
sample.reagents.remove_reagent("blood", amt)
|
||||
sample.reagents.add_reagent("antibodies", amt, data)
|
||||
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
update_icon()
|
||||
ping("\The [src] pings, \"Antibody isolated.\"")
|
||||
|
||||
/obj/machinery/computer/centrifuge/proc/isolate()
|
||||
if (!sample) return
|
||||
if(!sample) return
|
||||
var/obj/item/weapon/virusdish/dish = new/obj/item/weapon/virusdish(loc)
|
||||
dish.virus2 = virus2
|
||||
virus2 = null
|
||||
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
update_icon()
|
||||
ping("\The [src] pings, \"Pathogen isolated.\"")
|
||||
|
||||
@@ -182,20 +173,20 @@
|
||||
<large><u>Sample:</u></large> [sample.name]<br>
|
||||
"}
|
||||
|
||||
if (user)
|
||||
if(user)
|
||||
P.info += "<u>Generated By:</u> [user.name]<br>"
|
||||
|
||||
P.info += "<hr>"
|
||||
|
||||
var/datum/reagent/blood/B = locate(/datum/reagent/blood) in sample.reagents.reagent_list
|
||||
if (B)
|
||||
if(B)
|
||||
P.info += "<u>Antibodies:</u> "
|
||||
P.info += antigens2string(B.data["antibodies"])
|
||||
P.info += "<br>"
|
||||
|
||||
var/list/virus = B.data["virus2"]
|
||||
P.info += "<u>Pathogens:</u> <br>"
|
||||
if (virus.len > 0)
|
||||
if(virus.len > 0)
|
||||
for (var/ID in virus)
|
||||
var/datum/disease2/disease/V = virus[ID]
|
||||
P.info += "[V.name()]<br>"
|
||||
@@ -204,7 +195,7 @@
|
||||
|
||||
else
|
||||
var/datum/reagent/antibodies/A = locate(/datum/reagent/antibodies) in sample.reagents.reagent_list
|
||||
if (A)
|
||||
if(A)
|
||||
P.info += "The following antibodies have been isolated from the blood sample: "
|
||||
P.info += antigens2string(A.data["antibodies"])
|
||||
P.info += "<br>"
|
||||
|
||||
@@ -238,6 +238,26 @@ var/global/list/virusDB = list()
|
||||
|
||||
return r
|
||||
|
||||
/datum/disease2/disease/proc/get_tgui_info()
|
||||
. = list(
|
||||
"name" = name(),
|
||||
"spreadtype" = spreadtype,
|
||||
"antigen" = antigens2string(antigen),
|
||||
"rate" = stageprob * 10,
|
||||
"resistance" = resistance,
|
||||
"species" = jointext(affected_species, ", "),
|
||||
"symptoms" = list(),
|
||||
"ref" = "\ref[src]",
|
||||
)
|
||||
|
||||
for(var/datum/disease2/effectholder/E in effects)
|
||||
.["symptoms"].Add(list(list(
|
||||
"stage" = E.stage,
|
||||
"name" = E.effect.name,
|
||||
"strength" = "[E.multiplier >= 3 ? "Severe" : E.multiplier > 1 ? "Above Average" : "Average"]",
|
||||
"aggressiveness" = E.chance * 15,
|
||||
)))
|
||||
|
||||
/datum/disease2/disease/proc/addToDB()
|
||||
if ("[uniqueID]" in virusDB)
|
||||
return 0
|
||||
@@ -245,6 +265,8 @@ var/global/list/virusDB = list()
|
||||
v.fields["id"] = uniqueID
|
||||
v.fields["name"] = name()
|
||||
v.fields["description"] = get_info()
|
||||
v.fields["tgui_description"] = get_tgui_info()
|
||||
v.fields["tgui_description"]["record"] = "\ref[v]"
|
||||
v.fields["antigen"] = antigens2string(antigen)
|
||||
v.fields["spread type"] = spreadtype
|
||||
virusDB["[uniqueID]"] = v
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
if(istype(I,/obj/item/weapon/virusdish))
|
||||
var/mob/living/carbon/c = user
|
||||
if (dish)
|
||||
if(dish)
|
||||
to_chat(user, "\The [src] is already loaded.")
|
||||
return
|
||||
|
||||
@@ -40,36 +40,46 @@
|
||||
return src.attack_hand(user)
|
||||
|
||||
/obj/machinery/computer/diseasesplicer/attack_hand(var/mob/user as mob)
|
||||
if(..()) return
|
||||
ui_interact(user)
|
||||
if(..())
|
||||
return TRUE
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/computer/diseasesplicer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
user.set_machine(src)
|
||||
/obj/machinery/computer/diseasesplicer/tgui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "DiseaseSplicer", name)
|
||||
ui.open()
|
||||
|
||||
var/data[0]
|
||||
/obj/machinery/computer/diseasesplicer/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["dish_inserted"] = !!dish
|
||||
data["growth"] = 0
|
||||
data["affected_species"] = null
|
||||
|
||||
if (memorybank)
|
||||
data["buffer"] = null
|
||||
if(memorybank)
|
||||
data["buffer"] = list("name" = (analysed ? memorybank.effect.name : "Unknown Symptom"), "stage" = memorybank.effect.stage)
|
||||
if (species_buffer)
|
||||
data["species_buffer"] = null
|
||||
if(species_buffer)
|
||||
data["species_buffer"] = analysed ? jointext(species_buffer, ", ") : "Unknown Species"
|
||||
|
||||
if (splicing)
|
||||
data["effects"] = null
|
||||
data["info"] = null
|
||||
data["growth"] = 0
|
||||
data["affected_species"] = null
|
||||
data["busy"] = null
|
||||
if(splicing)
|
||||
data["busy"] = "Splicing..."
|
||||
else if (scanning)
|
||||
else if(scanning)
|
||||
data["busy"] = "Scanning..."
|
||||
else if (burning)
|
||||
else if(burning)
|
||||
data["busy"] = "Copying data to disk..."
|
||||
else if (dish)
|
||||
else if(dish)
|
||||
data["growth"] = min(dish.growth, 100)
|
||||
|
||||
if (dish.virus2)
|
||||
if (dish.virus2.affected_species)
|
||||
data["affected_species"] = dish.analysed ? jointext(dish.virus2.affected_species, ", ") : "Unknown"
|
||||
if(dish.virus2)
|
||||
if(dish.virus2.affected_species)
|
||||
data["affected_species"] = dish.analysed ? dish.virus2.affected_species : list()
|
||||
|
||||
if (dish.growth >= 50)
|
||||
if(dish.growth >= 50)
|
||||
var/list/effects[0]
|
||||
for (var/datum/disease2/effectholder/e in dish.virus2.effects)
|
||||
effects.Add(list(list("name" = (dish.analysed ? e.effect.name : "Unknown"), "stage" = (e.stage), "reference" = "\ref[e]")))
|
||||
@@ -81,11 +91,7 @@
|
||||
else
|
||||
data["info"] = "No dish loaded."
|
||||
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "disease_splicer.tmpl", src.name, 400, 600)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/diseasesplicer/process()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
@@ -95,100 +101,94 @@
|
||||
scanning -= 1
|
||||
if(!scanning)
|
||||
ping("\The [src] pings, \"Analysis complete.\"")
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
if(splicing)
|
||||
splicing -= 1
|
||||
if(!splicing)
|
||||
ping("\The [src] pings, \"Splicing operation complete.\"")
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
if(burning)
|
||||
burning -= 1
|
||||
if(!burning)
|
||||
var/obj/item/weapon/diseasedisk/d = new /obj/item/weapon/diseasedisk(src.loc)
|
||||
d.analysed = analysed
|
||||
if(analysed)
|
||||
if (memorybank)
|
||||
if(memorybank)
|
||||
d.name = "[memorybank.effect.name] GNA disk (Stage: [memorybank.effect.stage])"
|
||||
d.effect = memorybank
|
||||
else if (species_buffer)
|
||||
else if(species_buffer)
|
||||
d.name = "[jointext(species_buffer, ", ")] GNA disk"
|
||||
d.species = species_buffer
|
||||
else
|
||||
if (memorybank)
|
||||
if(memorybank)
|
||||
d.name = "Unknown GNA disk (Stage: [memorybank.effect.stage])"
|
||||
d.effect = memorybank
|
||||
else if (species_buffer)
|
||||
else if(species_buffer)
|
||||
d.name = "Unknown Species GNA disk"
|
||||
d.species = species_buffer
|
||||
|
||||
ping("\The [src] pings, \"Backup disk saved.\"")
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/computer/diseasesplicer/Topic(href, href_list)
|
||||
if(..()) return 1
|
||||
/obj/machinery/computer/diseasesplicer/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
var/mob/user = usr
|
||||
var/datum/nanoui/ui = SSnanoui.get_open_ui(user, src, "main")
|
||||
add_fingerprint(user)
|
||||
|
||||
src.add_fingerprint(user)
|
||||
switch(action)
|
||||
if("grab")
|
||||
if(dish)
|
||||
memorybank = locate(params["grab"])
|
||||
species_buffer = null
|
||||
analysed = dish.analysed
|
||||
dish = null
|
||||
scanning = 10
|
||||
. = TRUE
|
||||
|
||||
if (href_list["close"])
|
||||
user.unset_machine()
|
||||
ui.close()
|
||||
return 0
|
||||
if("affected_species")
|
||||
if(dish)
|
||||
memorybank = null
|
||||
species_buffer = dish.virus2.affected_species
|
||||
analysed = dish.analysed
|
||||
dish = null
|
||||
scanning = 10
|
||||
. = TRUE
|
||||
|
||||
if (href_list["grab"])
|
||||
if (dish)
|
||||
memorybank = locate(href_list["grab"])
|
||||
species_buffer = null
|
||||
analysed = dish.analysed
|
||||
dish = null
|
||||
scanning = 10
|
||||
return 1
|
||||
if("eject")
|
||||
if(dish)
|
||||
dish.loc = src.loc
|
||||
dish = null
|
||||
. = TRUE
|
||||
|
||||
if (href_list["affected_species"])
|
||||
if (dish)
|
||||
memorybank = null
|
||||
species_buffer = dish.virus2.affected_species
|
||||
analysed = dish.analysed
|
||||
dish = null
|
||||
scanning = 10
|
||||
return 1
|
||||
if("splice")
|
||||
if(dish)
|
||||
var/target = text2num(params["splice"]) // target = 1 to 4 for effects, 5 for species
|
||||
if(memorybank && 0 < target && target <= 4)
|
||||
if(target < memorybank.effect.stage) return // too powerful, catching this for href exploit prevention
|
||||
|
||||
if(href_list["eject"])
|
||||
if (dish)
|
||||
dish.loc = src.loc
|
||||
dish = null
|
||||
return 1
|
||||
var/datum/disease2/effectholder/target_holder
|
||||
var/list/illegal_types = list()
|
||||
for(var/datum/disease2/effectholder/e in dish.virus2.effects)
|
||||
if(e.stage == target)
|
||||
target_holder = e
|
||||
else
|
||||
illegal_types += e.effect.type
|
||||
if(memorybank.effect.type in illegal_types) return
|
||||
target_holder.effect = memorybank.effect
|
||||
|
||||
if(href_list["splice"])
|
||||
if(dish)
|
||||
var/target = text2num(href_list["splice"]) // target = 1 to 4 for effects, 5 for species
|
||||
if(memorybank && 0 < target && target <= 4)
|
||||
if(target < memorybank.effect.stage) return // too powerful, catching this for href exploit prevention
|
||||
else if(species_buffer && target == 5)
|
||||
dish.virus2.affected_species = species_buffer
|
||||
|
||||
var/datum/disease2/effectholder/target_holder
|
||||
var/list/illegal_types = list()
|
||||
for(var/datum/disease2/effectholder/e in dish.virus2.effects)
|
||||
if(e.stage == target)
|
||||
target_holder = e
|
||||
else
|
||||
illegal_types += e.effect.type
|
||||
if(memorybank.effect.type in illegal_types) return
|
||||
target_holder.effect = memorybank.effect
|
||||
else
|
||||
return
|
||||
|
||||
else if(species_buffer && target == 5)
|
||||
dish.virus2.affected_species = species_buffer
|
||||
splicing = 10
|
||||
dish.virus2.uniqueID = rand(0,10000)
|
||||
. = TRUE
|
||||
|
||||
else
|
||||
return
|
||||
if("disk")
|
||||
burning = 10
|
||||
. = TRUE
|
||||
|
||||
splicing = 10
|
||||
dish.virus2.uniqueID = rand(0,10000)
|
||||
return 1
|
||||
|
||||
if(href_list["disk"])
|
||||
burning = 10
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
O.loc = src
|
||||
|
||||
user.visible_message("[user] adds \a [O] to \the [src]!", "You add \a [O] to \the [src]!")
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
src.attack_hand(user)
|
||||
return
|
||||
@@ -46,17 +46,23 @@
|
||||
O.loc = src
|
||||
|
||||
user.visible_message("[user] adds \a [O] to \the [src]!", "You add \a [O] to \the [src]!")
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
src.attack_hand(user)
|
||||
|
||||
/obj/machinery/disease2/incubator/attack_hand(mob/user as mob)
|
||||
if(stat & (NOPOWER|BROKEN)) return
|
||||
ui_interact(user)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/disease2/incubator/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
user.set_machine(src)
|
||||
/obj/machinery/disease2/incubator/tgui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "DishIncubator", name)
|
||||
ui.set_autoupdate(FALSE)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/disease2/incubator/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
data["chemicals_inserted"] = !!beaker
|
||||
data["dish_inserted"] = !!dish
|
||||
@@ -74,23 +80,19 @@
|
||||
data["can_breed_virus"] = null
|
||||
data["blood_already_infected"] = null
|
||||
|
||||
if (beaker)
|
||||
if(beaker)
|
||||
var/datum/reagent/blood/B = locate(/datum/reagent/blood) in beaker.reagents.reagent_list
|
||||
data["can_breed_virus"] = dish && dish.virus2 && B
|
||||
|
||||
if (B)
|
||||
if (!B.data["virus2"])
|
||||
if(B)
|
||||
if(!B.data["virus2"])
|
||||
B.data["virus2"] = list()
|
||||
|
||||
var/list/virus = B.data["virus2"]
|
||||
for (var/ID in virus)
|
||||
data["blood_already_infected"] = virus[ID]
|
||||
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "dish_incubator.tmpl", src.name, 400, 600)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
return data
|
||||
|
||||
/obj/machinery/disease2/incubator/process()
|
||||
if(dish && on && dish.virus2)
|
||||
@@ -105,7 +107,7 @@
|
||||
|
||||
foodsupply -= 1
|
||||
dish.growth += 3
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
if(radiation)
|
||||
if(radiation > 50 & prob(5))
|
||||
@@ -118,90 +120,82 @@
|
||||
else if(prob(5))
|
||||
dish.virus2.minormutate()
|
||||
radiation -= 1
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
if(toxins && prob(5))
|
||||
dish.virus2.infectionchance -= 1
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
if(toxins > 50)
|
||||
dish.growth = 0
|
||||
dish.virus2 = null
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
else if(!dish)
|
||||
on = 0
|
||||
icon_state = "incubator"
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
if(beaker)
|
||||
if(foodsupply < 100 && beaker.reagents.remove_reagent("virusfood",5))
|
||||
if(foodsupply + 10 <= 100)
|
||||
foodsupply += 10
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
if (locate(/datum/reagent/toxin) in beaker.reagents.reagent_list && toxins < 100)
|
||||
if(locate(/datum/reagent/toxin) in beaker.reagents.reagent_list && toxins < 100)
|
||||
for(var/datum/reagent/toxin/T in beaker.reagents.reagent_list)
|
||||
toxins += max(T.strength,1)
|
||||
beaker.reagents.remove_reagent(T.id,1)
|
||||
if(toxins > 100)
|
||||
toxins = 100
|
||||
break
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/disease2/incubator/Topic(href, href_list)
|
||||
if (..()) return 1
|
||||
/obj/machinery/disease2/incubator/tgui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
var/mob/user = usr
|
||||
var/datum/nanoui/ui = SSnanoui.get_open_ui(user, src, "main")
|
||||
add_fingerprint(user)
|
||||
switch(action)
|
||||
if("ejectchem")
|
||||
if(beaker)
|
||||
beaker.loc = src.loc
|
||||
beaker = null
|
||||
. = TRUE
|
||||
|
||||
src.add_fingerprint(user)
|
||||
if("power")
|
||||
if(dish)
|
||||
on = !on
|
||||
icon_state = on ? "incubator_on" : "incubator"
|
||||
. = TRUE
|
||||
|
||||
if (href_list["close"])
|
||||
user.unset_machine()
|
||||
ui.close()
|
||||
return 0
|
||||
if("ejectdish")
|
||||
if(dish)
|
||||
dish.loc = src.loc
|
||||
dish = null
|
||||
. = TRUE
|
||||
|
||||
if (href_list["ejectchem"])
|
||||
if(beaker)
|
||||
beaker.loc = src.loc
|
||||
beaker = null
|
||||
return 1
|
||||
if("rad")
|
||||
radiation = min(100, radiation + 10)
|
||||
. = TRUE
|
||||
|
||||
if (href_list["power"])
|
||||
if (dish)
|
||||
on = !on
|
||||
icon_state = on ? "incubator_on" : "incubator"
|
||||
return 1
|
||||
if("flush")
|
||||
radiation = 0
|
||||
toxins = 0
|
||||
foodsupply = 0
|
||||
. = TRUE
|
||||
|
||||
if (href_list["ejectdish"])
|
||||
if(dish)
|
||||
dish.loc = src.loc
|
||||
dish = null
|
||||
return 1
|
||||
if("virus")
|
||||
if(!dish)
|
||||
return TRUE
|
||||
|
||||
if (href_list["rad"])
|
||||
radiation = min(100, radiation + 10)
|
||||
return 1
|
||||
var/datum/reagent/blood/B = locate(/datum/reagent/blood) in beaker.reagents.reagent_list
|
||||
if(!B)
|
||||
return TRUE
|
||||
|
||||
if (href_list["flush"])
|
||||
radiation = 0
|
||||
toxins = 0
|
||||
foodsupply = 0
|
||||
return 1
|
||||
if(!B.data["virus2"])
|
||||
B.data["virus2"] = list()
|
||||
|
||||
if(href_list["virus"])
|
||||
if (!dish)
|
||||
return 1
|
||||
var/list/virus = list("[dish.virus2.uniqueID]" = dish.virus2.getcopy())
|
||||
B.data["virus2"] += virus
|
||||
|
||||
var/datum/reagent/blood/B = locate(/datum/reagent/blood) in beaker.reagents.reagent_list
|
||||
if (!B)
|
||||
return 1
|
||||
|
||||
if (!B.data["virus2"])
|
||||
B.data["virus2"] = list()
|
||||
|
||||
var/list/virus = list("[dish.virus2.uniqueID]" = dish.virus2.getcopy())
|
||||
B.data["virus2"] += virus
|
||||
|
||||
ping("\The [src] pings, \"Injection complete.\"")
|
||||
return 1
|
||||
|
||||
return 0
|
||||
ping("\The [src] pings, \"Injection complete.\"")
|
||||
. = TRUE
|
||||
|
||||
+80
-106
@@ -1,8 +1,3 @@
|
||||
// UI menu navigation
|
||||
#define HOME "home"
|
||||
#define LIST "list"
|
||||
#define ENTRY "entry"
|
||||
|
||||
/obj/machinery/disease2/isolator/
|
||||
name = "pathogenic isolator"
|
||||
desc = "Used to isolate and identify diseases, allowing for comparison with a remote database."
|
||||
@@ -11,9 +6,7 @@
|
||||
icon = 'icons/obj/virology.dmi'
|
||||
icon_state = "isolator"
|
||||
var/isolating = 0
|
||||
var/state = HOME
|
||||
var/datum/disease2/disease/virus2 = null
|
||||
var/datum/data/record/entry = null
|
||||
var/obj/item/weapon/reagent_containers/syringe/sample = null
|
||||
|
||||
/obj/machinery/disease2/isolator/update_icon()
|
||||
@@ -44,71 +37,57 @@
|
||||
S.loc = src
|
||||
|
||||
user.visible_message("[user] adds \a [O] to \the [src]!", "You add \a [O] to \the [src]!")
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
update_icon()
|
||||
|
||||
src.attack_hand(user)
|
||||
|
||||
/obj/machinery/disease2/isolator/attack_hand(mob/user as mob)
|
||||
if(stat & (NOPOWER|BROKEN)) return
|
||||
ui_interact(user)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/disease2/isolator/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
user.set_machine(src)
|
||||
/obj/machinery/disease2/isolator/tgui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "PathogenicIsolator", name)
|
||||
ui.open()
|
||||
|
||||
var/data[0]
|
||||
|
||||
/obj/machinery/disease2/isolator/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["syringe_inserted"] = !!sample
|
||||
data["isolating"] = isolating
|
||||
data["pathogen_pool"] = null
|
||||
data["state"] = state
|
||||
data["entry"] = entry
|
||||
data["can_print"] = (state != HOME || sample) && !isolating
|
||||
data["can_print"] = !isolating
|
||||
|
||||
switch (state)
|
||||
if (HOME)
|
||||
if (sample)
|
||||
var/list/pathogen_pool[0]
|
||||
for(var/datum/reagent/blood/B in sample.reagents.reagent_list)
|
||||
var/list/virus = B.data["virus2"]
|
||||
for (var/ID in virus)
|
||||
var/datum/disease2/disease/V = virus[ID]
|
||||
var/datum/data/record/R = null
|
||||
if (ID in virusDB)
|
||||
R = virusDB[ID]
|
||||
var/list/pathogen_pool = list()
|
||||
if(sample)
|
||||
for(var/datum/reagent/blood/B in sample.reagents.reagent_list)
|
||||
var/list/virus = B.data["virus2"]
|
||||
for (var/ID in virus)
|
||||
var/datum/disease2/disease/V = virus[ID]
|
||||
var/datum/data/record/R = null
|
||||
if (ID in virusDB)
|
||||
R = virusDB[ID]
|
||||
|
||||
var/mob/living/carbon/human/D = B.data["donor"]
|
||||
pathogen_pool.Add(list(list(\
|
||||
"name" = "[D.get_species()] [B.name]", \
|
||||
"dna" = B.data["blood_DNA"], \
|
||||
"unique_id" = V.uniqueID, \
|
||||
"reference" = "\ref[V]", \
|
||||
"is_in_database" = !!R, \
|
||||
"record" = "\ref[R]")))
|
||||
var/mob/living/carbon/human/D = B.data["donor"]
|
||||
pathogen_pool.Add(list(list(\
|
||||
"name" = "[D.get_species()] [B.name]", \
|
||||
"dna" = B.data["blood_DNA"], \
|
||||
"unique_id" = V.uniqueID, \
|
||||
"reference" = "\ref[V]", \
|
||||
"is_in_database" = !!R, \
|
||||
"record" = "\ref[R]")))
|
||||
data["pathogen_pool"] = pathogen_pool
|
||||
|
||||
if (pathogen_pool.len > 0)
|
||||
data["pathogen_pool"] = pathogen_pool
|
||||
|
||||
if (LIST)
|
||||
var/list/db[0]
|
||||
for (var/ID in virusDB)
|
||||
var/datum/data/record/r = virusDB[ID]
|
||||
db.Add(list(list("name" = r.fields["name"], "record" = "\ref[r]")))
|
||||
|
||||
if (db.len > 0)
|
||||
data["database"] = db
|
||||
|
||||
if (ENTRY)
|
||||
if (entry)
|
||||
var/desc = entry.fields["description"]
|
||||
data["entry"] = list(\
|
||||
"name" = entry.fields["name"], \
|
||||
"description" = replacetext(desc, "\n", ""))
|
||||
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "pathogenic_isolator.tmpl", src.name, 400, 500)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
var/list/db = list()
|
||||
for(var/ID in virusDB)
|
||||
var/datum/data/record/r = virusDB[ID]
|
||||
db.Add(list(list("name" = r.fields["name"], "record" = "\ref[r]")))
|
||||
data["database"] = db
|
||||
data["modal"] = tgui_modal_data(src)
|
||||
return data
|
||||
|
||||
/obj/machinery/disease2/isolator/process()
|
||||
if (isolating > 0)
|
||||
@@ -120,62 +99,54 @@
|
||||
virus2 = null
|
||||
ping("\The [src] pings, \"Viral strain isolated.\"")
|
||||
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/disease2/isolator/Topic(href, href_list)
|
||||
if (..()) return 1
|
||||
/obj/machinery/disease2/isolator/tgui_act(action, list/params)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
var/mob/user = usr
|
||||
var/datum/nanoui/ui = SSnanoui.get_open_ui(user, src, "main")
|
||||
add_fingerprint(user)
|
||||
|
||||
. = TRUE
|
||||
switch(tgui_modal_act(src, action, params))
|
||||
if(TGUI_MODAL_ANSWER)
|
||||
return
|
||||
|
||||
src.add_fingerprint(user)
|
||||
switch(action)
|
||||
if("view_entry")
|
||||
var/datum/data/record/v = locate(params["vir"])
|
||||
if(!istype(v))
|
||||
return FALSE
|
||||
tgui_modal_message(src, "virus", "", null, v.fields["tgui_description"])
|
||||
return TRUE
|
||||
|
||||
if (href_list["close"])
|
||||
user.unset_machine()
|
||||
ui.close()
|
||||
return 0
|
||||
if("print")
|
||||
print(user, params)
|
||||
return TRUE
|
||||
|
||||
if (href_list[HOME])
|
||||
state = HOME
|
||||
return 1
|
||||
if("isolate")
|
||||
var/datum/disease2/disease/V = locate(params["isolate"])
|
||||
if (V)
|
||||
virus2 = V
|
||||
isolating = 20
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
if (href_list[LIST])
|
||||
state = LIST
|
||||
return 1
|
||||
|
||||
if (href_list[ENTRY])
|
||||
if (istype(locate(href_list["view"]), /datum/data/record))
|
||||
entry = locate(href_list["view"])
|
||||
|
||||
state = ENTRY
|
||||
return 1
|
||||
|
||||
if (href_list["print"])
|
||||
print(user)
|
||||
return 1
|
||||
|
||||
if(!sample) return 1
|
||||
|
||||
if (href_list["isolate"])
|
||||
var/datum/disease2/disease/V = locate(href_list["isolate"])
|
||||
if (V)
|
||||
virus2 = V
|
||||
isolating = 20
|
||||
if("eject")
|
||||
if(!sample)
|
||||
return FALSE
|
||||
sample.forceMove(loc)
|
||||
sample = null
|
||||
update_icon()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
if (href_list["eject"])
|
||||
sample.loc = src.loc
|
||||
sample = null
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
/obj/machinery/disease2/isolator/proc/print(var/mob/user)
|
||||
/obj/machinery/disease2/isolator/proc/print(mob/user, list/params)
|
||||
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(loc)
|
||||
|
||||
switch (state)
|
||||
if (HOME)
|
||||
switch(params["type"])
|
||||
if("patient_diagnosis")
|
||||
if (!sample) return
|
||||
P.name = "paper - Patient Diagnostic Report"
|
||||
P.info = {"
|
||||
@@ -207,7 +178,7 @@
|
||||
<u>Additional Notes:</u>
|
||||
"}
|
||||
|
||||
if (LIST)
|
||||
if("virus_list")
|
||||
P.name = "paper - Virus List"
|
||||
P.info = {"
|
||||
[virology_letterhead("Virus List")]
|
||||
@@ -225,11 +196,14 @@
|
||||
<u>Additional Notes:</u>
|
||||
"}
|
||||
|
||||
if (ENTRY)
|
||||
if("virus_record")
|
||||
var/datum/data/record/v = locate(params["vir"])
|
||||
if(!istype(v))
|
||||
return FALSE
|
||||
P.name = "paper - Viral Profile"
|
||||
P.info = {"
|
||||
[virology_letterhead("Viral Profile")]
|
||||
[entry.fields["description"]]
|
||||
[v.fields["description"]]
|
||||
<hr>
|
||||
<u>Additional Notes:</u>
|
||||
"}
|
||||
|
||||
Reference in New Issue
Block a user