Merge remote-tracking branch 'VORE_MASTER/master' into clara-dev-pink-moo-drink

This commit is contained in:
Riley
2020-08-13 04:08:40 -04:00
312 changed files with 17233 additions and 11559 deletions
@@ -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()
+40 -45
View File
@@ -31,58 +31,53 @@
if(holder)
holder.update_icon()
/obj/item/device/assembly/signaler/interact(var/mob/user)
var/t1 = "-------"
var/dat = {"
<TT>
/obj/item/device/assembly/signaler/interact(mob/user)
if(..())
return TRUE
tgui_interact(user)
<A href='byond://?src=\ref[src];send=1'>Send Signal</A><BR>
<B>Frequency/Code</B> for signaler:<BR>
Frequency:
<A href='byond://?src=\ref[src];freq=-10'>-</A>
<A href='byond://?src=\ref[src];freq=-2'>-</A>
[format_frequency(src.frequency)]
<A href='byond://?src=\ref[src];freq=2'>+</A>
<A href='byond://?src=\ref[src];freq=10'>+</A><BR>
/obj/item/device/assembly/signaler/tgui_state(mob/user)
return GLOB.tgui_deep_inventory_state
Code:
<A href='byond://?src=\ref[src];code=-5'>-</A>
<A href='byond://?src=\ref[src];code=-1'>-</A>
[src.code]
<A href='byond://?src=\ref[src];code=1'>+</A>
<A href='byond://?src=\ref[src];code=5'>+</A><BR>
[t1]
</TT>"}
user << browse(dat, "window=radio")
onclose(user, "radio")
/obj/item/device/assembly/signaler/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Signaler", name)
ui.open()
/obj/item/device/assembly/signaler/Topic(href, href_list, state = deep_inventory_state)
/obj/item/device/assembly/signaler/tgui_data(mob/user)
var/list/data = list()
data["frequency"] = frequency
data["code"] = code
data["minFrequency"] = RADIO_LOW_FREQ
data["maxFrequency"] = RADIO_HIGH_FREQ
return data
/obj/item/device/assembly/signaler/tgui_act(action, params)
if(..())
return TRUE
if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
usr << browse(null, "window=radio")
onclose(usr, "radio")
return
switch(action)
if("signal")
INVOKE_ASYNC(src, .proc/signal)
. = TRUE
if("freq")
frequency = unformat_frequency(params["freq"])
frequency = sanitize_frequency(frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ)
set_frequency(frequency)
. = TRUE
if("code")
code = text2num(params["code"])
code = clamp(round(code), 1, 100)
. = TRUE
if("reset")
if(params["reset"] == "freq")
set_frequency(initial(frequency))
else
code = initial(code)
. = TRUE
if (href_list["freq"])
var/new_frequency = (frequency + text2num(href_list["freq"]))
if(new_frequency < RADIO_LOW_FREQ || new_frequency > RADIO_HIGH_FREQ)
new_frequency = sanitize_frequency(new_frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ)
set_frequency(new_frequency)
if(href_list["code"])
src.code += text2num(href_list["code"])
src.code = round(src.code)
src.code = min(100, src.code)
src.code = max(1, src.code)
if(href_list["send"])
spawn( 0 )
signal()
if(usr)
attack_self(usr)
update_icon()
/obj/item/device/assembly/signaler/attackby(var/obj/item/weapon/W, mob/user, params)
if(issignaler(W))
@@ -115,6 +115,15 @@
scarfs[initial(scarf_type.name)] = scarf_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(scarfs))
/datum/gear/accessory/scarfcolor
display_name = "scarf (recolorable)"
path = /obj/item/clothing/accessory/scarf/white
cost = 1
/datum/gear/accessory/scarfcolor/New()
..()
gear_tweaks = list(gear_tweak_free_color_choice)
/datum/gear/accessory/jacket
display_name = "suit jacket selection"
path = /obj/item/clothing/accessory/jacket
@@ -77,7 +77,7 @@
/datum/gear/suit/mil
display_name = "military jacket selection"
path = /obj/item/clothing/suit/storage/miljacket
/datum/gear/suit/mil/New()
..()
var/list/mil_jackets = list()
@@ -411,5 +411,15 @@
sort_category = "Xenowear"
/datum/gear/suit/teshcoatwhite/New()
..()
gear_tweaks = list(gear_tweak_free_color_choice)
/datum/gear/accessory/teshneckscarf
display_name = "neckscarf, recolorable (Teshari)"
path = /obj/item/clothing/accessory/scarf/teshari/neckscarf
whitelisted = SPECIES_TESHARI
sort_category = "Xenowear"
/datum/gear/accessory/teshneckscarf/New()
..()
gear_tweaks = list(gear_tweak_free_color_choice)
+2
View File
@@ -339,6 +339,8 @@ datum/preferences
else if(href_list["resetslot"])
if("No" == alert("This will reset the current slot. Continue?", "Reset current slot?", "No", "Yes"))
return 0
if("No" == alert("Are you completely sure that you want to reset this character slot?", "Reset current slot?", "No", "Yes"))
return 0
load_character(SAVE_RESET)
sanitize_preferences()
else if(href_list["copy"])
+6 -6
View File
@@ -100,12 +100,12 @@
mode = "sec"
flash_protection = FLASH_PROTECTION_MAJOR
action_button_name = "AR Console (Security Alerts)"
arscreen_path = /datum/nano_module/alarm_monitor/security
tgarscreen_path = /datum/tgui_module/alarm_monitor/security/glasses
enables_planes = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_CH_WANTED,VIS_AUGMENTED)
ar_interact(var/mob/living/carbon/human/user)
if(arscreen)
arscreen.ui_interact(user,"main",null,1,glasses_state)
if(tgarscreen)
tgarscreen.tgui_interact(user)
return 1
/obj/item/clothing/glasses/omnihud/eng
@@ -115,11 +115,11 @@
mode = "eng"
flash_protection = FLASH_PROTECTION_MAJOR
action_button_name = "AR Console (Station Alerts)"
arscreen_path = /datum/nano_module/alarm_monitor/engineering
tgarscreen_path = /datum/tgui_module/alarm_monitor/engineering/glasses
ar_interact(var/mob/living/carbon/human/user)
if(arscreen)
arscreen.ui_interact(user,"main",null,1,glasses_state)
if(tgarscreen)
tgarscreen.tgui_interact(user)
return 1
/obj/item/clothing/glasses/omnihud/rnd
@@ -15,7 +15,7 @@
to_chat(usr, "Your module is not installed in a hardsuit.")
return
module.holder.ui_interact(usr, nano_state = contained_state)
module.holder.tgui_interact(usr, custom_state = GLOB.tgui_contained_state)
/obj/item/rig_module/ai_container
@@ -134,7 +134,7 @@
if(!target)
if(ai_card)
if(istype(ai_card,/obj/item/device/aicard))
ai_card.ui_interact(H, state = deep_inventory_state)
ai_card.tgui_interact(H, custom_state = deep_inventory_state)
else
eject_ai(H)
update_verb_holder()
+11 -116
View File
@@ -28,8 +28,8 @@
var/suit_state //The string used for the suit's icon_state.
var/interface_path = "hardsuit.tmpl"
var/ai_interface_path = "hardsuit.tmpl"
var/interface_path = "RIGSuit"
var/ai_interface_path = "RIGSuit"
var/interface_title = "Hardsuit Controller"
var/wearer_move_delay //Used for AI moving.
var/ai_controlled_move_delay = 10
@@ -284,6 +284,7 @@
if(!seal_target && !suit_is_deployed())
M.visible_message("<span class='danger'>[M]'s suit flashes an error light.</span>","<span class='danger'>Your suit flashes an error light. It can't function properly without being fully deployed.</span>")
playsound(src, 'sound/machines/rig/rigerror.ogg', 20, FALSE)
failed_to_seal = 1
if(!failed_to_seal)
@@ -293,6 +294,7 @@
if(seal_delay && !do_after(M,seal_delay))
if(M)
to_chat(M, "<span class='warning'>You must remain still while the suit is adjusting the components.</span>")
playsound(src, 'sound/machines/rig/rigerror.ogg', 20, FALSE)
failed_to_seal = 1
if(!M)
failed_to_seal = 1
@@ -340,6 +342,7 @@
piece.armor["bio"] = 100
else
piece.armor["bio"] = src.armor["bio"]
playsound(src, "[!seal_target ? 'sound/machines/boltsdown.ogg' : 'sound/machines/boltsup.ogg']", 10, FALSE)
else
failed_to_seal = 1
@@ -371,6 +374,7 @@
else
minihud = new (M.hud_used, src)
to_chat(M, "<span class='notice'><b>Your entire suit [canremove ? "loosens as the components relax" : "tightens around you as the components lock into place"].</b></span>")
playsound(src, 'sound/machines/rig/rigstarted.ogg', 10, FALSE)
M.client.screen -= booting_L
qdel(booting_L)
booting_R.icon_state = "boot_done"
@@ -493,7 +497,7 @@
wearer.wearing_rig = null
wearer = null
return PROCESS_KILL
// Run through cooling
coolingProcess()
@@ -508,6 +512,7 @@
to_chat(wearer, "<span class='danger'>Your suit beeps stridently, and suddenly goes dead.</span>")
else
to_chat(wearer, "<span class='danger'>Your suit beeps stridently, and suddenly you're wearing a leaden mass of metal and plastic composites instead of a powered suit.</span>")
playsound(src, 'sound/machines/rig/rigdown.ogg', 60, FALSE)
if(offline_vision_restriction == 1)
to_chat(wearer, "<span class='danger'>The suit optics flicker and die, leaving you with restricted vision.</span>")
else if(offline_vision_restriction == 2)
@@ -565,6 +570,7 @@
if(fail_msg)
to_chat(user, fail_msg)
playsound(src, 'sound/machines/rig/rigerror.ogg', 20, FALSE)
return 0
// This is largely for cancelling stealth and whatever.
@@ -576,81 +582,6 @@
cell.use(cost*10)
return 1
/obj/item/weapon/rig/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/nano_state = inventory_state)
if(!user)
return
var/list/data = list()
if(selected_module)
data["primarysystem"] = "[selected_module.interface_name]"
if(src.loc != user)
data["ai"] = 1
data["seals"] = "[src.canremove]"
data["sealing"] = "[src.sealing]"
data["helmet"] = (helmet ? "[helmet.name]" : "None.")
data["gauntlets"] = (gloves ? "[gloves.name]" : "None.")
data["boots"] = (boots ? "[boots.name]" : "None.")
data["chest"] = (chest ? "[chest.name]" : "None.")
data["charge"] = cell ? round(cell.charge,1) : 0
data["maxcharge"] = cell ? cell.maxcharge : 0
data["chargestatus"] = cell ? FLOOR((cell.charge/cell.maxcharge)*50, 1) : 0
data["emagged"] = subverted
data["coverlock"] = locked
data["interfacelock"] = interface_locked
data["aicontrol"] = control_overridden
data["aioverride"] = ai_override_enabled
data["securitycheck"] = security_check_enabled
data["malf"] = malfunction_delay
var/list/module_list = list()
var/i = 1
for(var/obj/item/rig_module/module in installed_modules)
var/list/module_data = list(
"index" = i,
"name" = "[module.interface_name]",
"desc" = "[module.interface_desc]",
"can_use" = "[module.usable]",
"can_select" = "[module.selectable]",
"can_toggle" = "[module.toggleable]",
"is_active" = "[module.active]",
"engagecost" = module.use_power_cost*10,
"activecost" = module.active_power_cost*10,
"passivecost" = module.passive_power_cost*10,
"engagestring" = module.engage_string,
"activatestring" = module.activate_string,
"deactivatestring" = module.deactivate_string,
"damage" = module.damage
)
if(module.charges && module.charges.len)
module_data["charges"] = list()
var/datum/rig_charge/selected = module.charges[module.charge_selected]
module_data["chargetype"] = selected ? "[selected.display_name]" : "none"
for(var/chargetype in module.charges)
var/datum/rig_charge/charge = module.charges[chargetype]
module_data["charges"] += list(list("caption" = "[chargetype] ([charge.charges])", "index" = "[chargetype]"))
module_list += list(module_data)
i++
if(module_list.len)
data["modules"] = module_list
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, ((src.loc != user) ? ai_interface_path : interface_path), interface_title, 480, 550, state = nano_state)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/item/weapon/rig/update_icon(var/update_mob_icon)
//TODO: Maybe consider a cache for this (use mob_icon as blank canvas, use suit icon overlay).
@@ -698,44 +629,6 @@
return 1
//TODO: Fix Topic vulnerabilities for malfunction and AI override.
/obj/item/weapon/rig/Topic(href,href_list)
if(!check_suit_access(usr))
return 0
if(href_list["toggle_piece"])
if(ishuman(usr) && (usr.stat || usr.stunned || usr.lying))
return 0
toggle_piece(href_list["toggle_piece"], usr)
else if(href_list["toggle_seals"])
toggle_seals(usr)
else if(href_list["interact_module"])
var/module_index = text2num(href_list["interact_module"])
if(module_index > 0 && module_index <= installed_modules.len)
var/obj/item/rig_module/module = installed_modules[module_index]
switch(href_list["module_mode"])
if("activate")
module.activate()
if("deactivate")
module.deactivate()
if("engage")
module.engage()
if("select")
selected_module = module
if("select_charge_type")
module.charge_selected = href_list["charge_type"]
else if(href_list["toggle_ai_control"])
ai_override_enabled = !ai_override_enabled
notify_ai("Synthetic suit control has been [ai_override_enabled ? "enabled" : "disabled"].")
else if(href_list["toggle_suit_lock"])
locked = !locked
usr.set_machine(src)
src.add_fingerprint(usr)
return 0
/obj/item/weapon/rig/proc/notify_ai(var/message)
for(var/obj/item/rig_module/ai_container/module in installed_modules)
if(module.integrated_ai && module.integrated_ai.client && !module.integrated_ai.stat)
@@ -814,6 +707,7 @@
if(istype(holder))
if(use_obj && check_slot == use_obj)
to_chat(H, "<span class='notice'><b>Your [use_obj.name] [use_obj.gender == PLURAL ? "retract" : "retracts"] swiftly.</b></span>")
playsound(src, 'sound/machines/boltsup.ogg', 10, FALSE)
use_obj.canremove = 1
holder.drop_from_inventory(use_obj)
use_obj.forceMove(get_turf(src))
@@ -832,6 +726,7 @@
return
else
to_chat(H, "<span class='notice'>Your [use_obj.name] [use_obj.gender == PLURAL ? "deploy" : "deploys"] swiftly.</span>")
playsound(src, 'sound/machines/boltsdown.ogg', 10, FALSE)
if(piece == "helmet" && helmet)
helmet.update_light(H)
@@ -0,0 +1,164 @@
/*
* This defines the global UI for RIGSuits.
* It has all of the relevant TGUI procs, but it's entry point is in rig_verbs.dm
* as part of rig/proc/hardsuit_interface().
*/
/*
* tgui_interact() is the proc that opens the UI. It doesn't really do anything else, unlike NanoV1.
* We add an extra argument, custom_state, for the things that want a custom state for their UI.
*/
/obj/item/weapon/rig/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui, datum/tgui_state/custom_state)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, (loc != usr ? ai_interface_path : interface_path), interface_title)
ui.open()
if(custom_state)
ui.set_state(custom_state)
/*
* tgui_state() gives the UI the state to use by default.
*/
/obj/item/weapon/rig/tgui_state()
return GLOB.tgui_inventory_state
/*
* tgui_status() is middlewere for objects to add little exceptions or special cases to the state they use.
* In this case, we're using it in order to make the UI refuse to let the user press any buttons if they're
* not authorized to do so.
* This saves us two lines of code in tgui_act().
*/
/obj/item/weapon/rig/tgui_status(mob/user, datum/tgui_state/state)
. = ..()
if(!check_suit_access(user))
// Forces the UI to never go interactive,
// but doesn't interfere with state saying to close.
. = min(., STATUS_UPDATE)
/*
* tgui_data() is the heavy lifter, it gives the UI it's relevant datastructure every SStgui tick.
*/
/obj/item/weapon/rig/tgui_data(mob/user)
var/list/data = list()
if(selected_module)
data["primarysystem"] = "[selected_module.interface_name]"
else
data["primarysystem"] = null
if(loc != user)
data["ai"] = TRUE
else
data["ai"] = FALSE
data["sealed"] = !canremove
data["sealing"] = sealing
data["helmet"] = (helmet ? "[helmet.name]" : "None.")
data["gauntlets"] = (gloves ? "[gloves.name]" : "None.")
data["boots"] = (boots ? "[boots.name]" : "None.")
data["chest"] = (chest ? "[chest.name]" : "None.")
data["helmetDeployed"] = (helmet && helmet.loc == loc)
data["gauntletsDeployed"] = (gloves && gloves.loc == loc)
data["bootsDeployed"] = (boots && boots.loc == loc)
data["chestDeployed"] = (chest && chest.loc == loc)
data["charge"] = cell ? round(cell.charge,1) : 0
data["maxcharge"] = cell ? cell.maxcharge : 0
data["chargestatus"] = cell ? FLOOR((cell.charge/cell.maxcharge)*50, 1) : 0
data["emagged"] = subverted
data["coverlock"] = locked
data["interfacelock"] = interface_locked
data["aicontrol"] = control_overridden
data["aioverride"] = ai_override_enabled
data["securitycheck"] = security_check_enabled
data["malf"] = malfunction_delay
var/list/module_list = list()
if(!canremove && !sealing)
var/i = 1
for(var/obj/item/rig_module/module in installed_modules)
var/list/module_data = list(
"index" = i,
"name" = "[module.interface_name]",
"desc" = "[module.interface_desc]",
"can_use" = module.usable,
"can_select" = module.selectable,
"can_toggle" = module.toggleable,
"is_active" = module.active,
"engagecost" = module.use_power_cost*10,
"activecost" = module.active_power_cost*10,
"passivecost" = module.passive_power_cost*10,
"engagestring" = module.engage_string,
"activatestring" = module.activate_string,
"deactivatestring" = module.deactivate_string,
"damage" = module.damage
)
if(module.charges && module.charges.len)
module_data["charges"] = list()
var/datum/rig_charge/selected = module.charges[module.charge_selected]
module_data["chargetype"] = selected ? "[selected.display_name]" : "none"
for(var/chargetype in module.charges)
var/datum/rig_charge/charge = module.charges[chargetype]
module_data["charges"] += list(list("caption" = "[chargetype] ([charge.charges])", "index" = "[chargetype]"))
module_list += list(module_data)
i++
if(module_list.len)
data["modules"] = module_list
else
data["modules"] = list()
return data
/*
* tgui_act() is the TGUI equivelent of Topic(). It's responsible for all of the "actions" you can take in the UI.
*/
/obj/item/weapon/rig/tgui_act(action, params)
// This parent call is very important, as it's responsible for invoking tgui_status and checking our state's rules.
if(..())
return TRUE
add_fingerprint(usr)
switch(action)
if("toggle_seals")
toggle_seals(usr)
. = TRUE
if("toggle_ai_control")
ai_override_enabled = !ai_override_enabled
notify_ai("Synthetic suit control has been [ai_override_enabled ? "enabled" : "disabled"].")
. = TRUE
if("toggle_suit_lock")
locked = !locked
. = TRUE
if("toggle_piece")
if(ishuman(usr) && (usr.stat || usr.stunned || usr.lying))
return FALSE
toggle_piece(params["piece"], usr)
. = TRUE
if("interact_module")
var/module_index = text2num(params["module"])
if(module_index > 0 && module_index <= installed_modules.len)
var/obj/item/rig_module/module = installed_modules[module_index]
switch(params["module_mode"])
if("select")
selected_module = module
. = TRUE
if("engage")
module.engage()
. = TRUE
if("toggle")
if(module.active)
module.deactivate()
else
module.activate()
. = TRUE
if("select_charge_type")
module.charge_selected = params["charge_type"]
. = TRUE
@@ -7,7 +7,7 @@
set src = usr.contents
if(wearer && (wearer.back == src || wearer.belt == src))
ui_interact(usr)
tgui_interact(usr)
/obj/item/weapon/rig/verb/toggle_vision()
@@ -4,16 +4,17 @@
icon = 'icons/obj/clothing/ties.dmi'
icon_state = "bluetie"
item_state_slots = list(slot_r_hand_str = "", slot_l_hand_str = "")
appearance_flags = RESET_COLOR // Stops has_suit's color from being multiplied onto the accessory
slot_flags = SLOT_TIE
w_class = ITEMSIZE_SMALL
var/slot = ACCESSORY_SLOT_DECOR
var/obj/item/clothing/has_suit = null //the suit the tie may be attached to
var/image/inv_overlay = null //overlay used when attached to clothing.
var/obj/item/clothing/has_suit = null // The suit the tie may be attached to
var/image/inv_overlay = null // Overlay used when attached to clothing.
var/image/mob_overlay = null
var/overlay_state = null
var/concealed_holster = 0
var/mob/living/carbon/human/wearer = null //To check if the wearer changes, so species spritesheets change properly.
var/list/on_rolled = list() //used when jumpsuit sleevels are rolled ("rolled" entry) or it's rolled down ("down"). Set to "none" to hide in those states.
var/mob/living/carbon/human/wearer = null // To check if the wearer changes, so species spritesheets change properly.
var/list/on_rolled = list() // Used when jumpsuit sleevels are rolled ("rolled" entry) or it's rolled down ("down"). Set to "none" to hide in those states.
sprite_sheets = list(SPECIES_TESHARI = 'icons/mob/species/seromi/ties.dmi') //Teshari can into webbing, too!
/obj/item/clothing/accessory/Destroy()
@@ -29,6 +30,9 @@
inv_overlay = image(icon = icon_override, icon_state = tmp_icon_state, dir = SOUTH)
else
inv_overlay = image(icon = INV_ACCESSORIES_DEF_ICON, icon_state = tmp_icon_state, dir = SOUTH)
inv_overlay.color = src.color
inv_overlay.appearance_flags = appearance_flags // Stops has_suit's color from being multiplied onto the accessory
return inv_overlay
/obj/item/clothing/accessory/proc/get_mob_overlay()
@@ -65,6 +69,7 @@
else
mob_overlay.color = src.color
mob_overlay.appearance_flags = appearance_flags // Stops has_suit's color from being multiplied onto the accessory
return mob_overlay
//when user attached an accessory to S
@@ -72,8 +77,8 @@
if(!istype(S))
return
has_suit = S
loc = has_suit
has_suit.overlays += get_inv_overlay()
src.forceMove(S)
has_suit.add_overlay(get_inv_overlay())
if(user)
to_chat(user, "<span class='notice'>You attach \the [src] to \the [has_suit].</span>")
@@ -82,7 +87,7 @@
/obj/item/clothing/accessory/proc/on_removed(var/mob/user)
if(!has_suit)
return
has_suit.overlays -= get_inv_overlay()
has_suit.cut_overlay(get_inv_overlay())
has_suit = null
if(user)
usr.put_in_hands(src)
@@ -325,6 +330,12 @@
name = "striped blue scarf"
icon_state = "stripedbluescarf"
/obj/item/clothing/accessory/scarf/teshari/neckscarf
name = "small neckscarf"
desc = "a neckscarf that is too small for a human's neck"
icon_state = "tesh_neckscarf"
species_restricted = list(SPECIES_TESHARI)
//bracelets
/obj/item/clothing/accessory/bracelet
+77 -1
View File
@@ -45,6 +45,22 @@
name = "small formal uniform"
icon_state = "seromi_captain_formal"
/obj/item/clothing/under/seromi/smock/blackutilitysmock
name = "black utility smock"
icon_state = "teshari_blackutility_com"
/obj/item/clothing/under/seromi/smock/greydress
name = "small grey dress"
icon_state = "teshari_greydress"
/obj/item/clothing/under/seromi/smock/blackutility
name = "Teshari utility uniform"
icon_state = "teshari_blackutility"
/obj/item/clothing/under/seromi/smock/bluegreydress
name = "small blue and grey dress"
icon_state = "teshari_bluegreydress"
/obj/item/clothing/under/seromi/undercoat
name = "Undercoat"
desc = "A Teshari traditional garb, with a modern twist! Made of micro and nanofibres to make it light and billowy, perfect for going fast and stylishly!"
@@ -179,6 +195,66 @@
icon_state = "tesh_uniform_brg"
item_state = "tesh_uniform_brg"
/obj/item/clothing/under/seromi/undercoat/standard/blackredworksuit
name = "small black and red worksuit"
icon_state = "teshari_black_red_worksuit"
item_state = "teshari_black_red_worksuit"
desc = "A small worksuit designed for a Teshari"
/obj/item/clothing/under/seromi/undercoat/standard/blackpurpleworksuit
name = "small black and purple worksuit"
icon_state = "teshari_black_purple_worksuit"
item_state = "teshari_black_purple_worksuit"
desc = "A small worksuit designed for a Teshari"
/obj/item/clothing/under/seromi/undercoat/standard/blackpurpleworksuit
name = "small black and orange worksuit"
icon_state = "teshari_black_orange_worksuit"
item_state = "teshari_black_orange_worksuit"
desc = "A small worksuit designed for a Teshari"
/obj/item/clothing/under/seromi/undercoat/standard/blackblueworksuit
name = "small black and blue worksuit"
icon_state = "teshari_black_blue_worksuit"
item_state = "teshari_black_blue_worksuit"
desc = "A small worksuit designed for a Teshari"
/obj/item/clothing/under/seromi/undercoat/standard/blackgreenworksuit
name = "small black and greeen worksuit"
icon_state = "teshari_black_green_worksuit"
item_state = "teshari_black_green_worksuit"
desc = "A small worksuit designed for a Teshari"
/obj/item/clothing/under/seromi/undercoat/standard/whiteredworksuit
name = "small white and red worksuit"
icon_state = "teshari_white_red_worksuit"
item_state = "teshari_white_red_worksuit"
desc = "A small worksuit designed for a Teshari"
/obj/item/clothing/under/seromi/undercoat/standard/whitepurpleworksuit
name = "small white and purple worksuit"
icon_state = "teshari_white_purple_worksuit"
item_state = "teshari_white_purple_worksuit"
desc = "A small worksuit designed for a Teshari"
/obj/item/clothing/under/seromi/undercoat/standard/whiteorangeworksuit
name = "small white and orange worksuit"
icon_state = "teshari_white_orange_worksuit"
item_state = "teshari_white_orange_worksuit"
desc = "A small worksuit designed for a Teshari"
/obj/item/clothing/under/seromi/undercoat/standard/whiteblueworksuit
name = "small white and blue worksuit"
icon_state = "teshari_white_blue_worksuit"
item_state = "teshari_white_blue_worksuit"
desc = "A small worksuit designed for a Teshari"
/obj/item/clothing/under/seromi/undercoat/standard/whitegreenworksuit
name = "small white and green worksuit"
icon_state = "teshari_white_green_worksuit"
item_state = "teshari_white_green_worksuit"
desc = "A small worksuit designed for a Teshari"
/obj/item/clothing/under/seromi/undercoat/jobs
icon = 'icons/mob/species/seromi/deptjacket.dmi'
icon_override = 'icons/mob/species/seromi/deptjacket.dmi'
@@ -295,4 +371,4 @@
name = "internal affairs undercoat"
desc = "A traditional Teshari garb made for the Internal Affairs Agent"
icon_state = "tesh_uniform_iaa"
item_state = "tesh_uniform_iaa"
item_state = "tesh_uniform_iaa"
+3 -3
View File
@@ -100,7 +100,7 @@
src.icon_state = "mw"
src.broken = 0 // Fix it!
src.dirty = 0 // just to be sure
src.flags = OPENCONTAINER
src.flags = OPENCONTAINER | NOREACT
else
to_chat(user, "<span class='warning'>It's broken!</span>")
return 1
@@ -119,7 +119,7 @@
src.dirty = 0 // It's clean!
src.broken = 0 // just to be sure
src.icon_state = "mw"
src.flags = OPENCONTAINER
src.flags = OPENCONTAINER | NOREACT
else //Otherwise bad luck!!
to_chat(user, "<span class='warning'>It's dirty!</span>")
return 1
@@ -546,4 +546,4 @@
if(istype(container, /obj/machinery/microwave))
var/obj/machinery/microwave/M = container
M.muck_finish()
. = ..()
. = ..()
+49 -57
View File
@@ -243,7 +243,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))
@@ -263,7 +262,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
@@ -309,11 +307,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)
@@ -322,66 +320,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
@@ -400,17 +391,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)
@@ -172,7 +172,7 @@
message = "does a flip!"
m_type = 1
if("vhelp") //Help for Virgo-specific emotes.
to_chat(src, "vwag, vflap, mlem, blep, awoo, awoo2, growl, nya, peep, chirp, hoot, weh, merp, myarp, bark, bork, mrow, mrowl, hypno, hiss, rattle, squeak, geck, baa, baa2, mar, wurble, snort, meow, moo, croak, nsay, nme, flip")
to_chat(src, "vwag, vflap, mlem, blep, awoo, awoo2, growl, nya, peep, chirp, hoot, weh, merp, myarp, bark, bork, mrow, mrowl, hypno, hiss, rattle, squeak, geck, baa, baa2, mar, wurble, snort, meow, moo, croak, gao, cackle, nsay, nme, flip")
return TRUE
if(message)
@@ -14,111 +14,107 @@
/obj/machinery/computer/drone_control/attack_ai(var/mob/user as mob)
return src.attack_hand(user)
/obj/machinery/computer/drone_control/tgui_status(mob/user)
if(!allowed(user))
return STATUS_CLOSE
return ..()
/obj/machinery/computer/drone_control/attack_hand(var/mob/user as mob)
if(..())
return
if(!allowed(user))
to_chat(user, "<span class='danger'>Access denied.</span>")
return
tgui_interact(user)
user.set_machine(src)
var/dat
dat += "<B>Maintenance Units</B><BR>"
/obj/machinery/computer/drone_control/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "DroneConsole", name)
ui.open()
/obj/machinery/computer/drone_control/tgui_data(mob/user)
var/list/data = list()
data["drones"] = list()
for(var/mob/living/silicon/robot/drone/D in mob_list)
if(D.z != src.z)
if(D.z != z)
continue
if(D.foreign_droid)
continue
data["drones"].Add(list(list(
"name" = D.real_name,
"active" = D.stat != 2,
"charge" = D.cell.charge,
"maxCharge" = D.cell.maxcharge,
"loc" = "[get_area(D)]",
"ref" = "\ref[D]",
)))
dat += "<BR>[D.real_name] ([D.stat == 2 ? "<font color='red'>INACTIVE</FONT>" : "<font color='green'>ACTIVE</FONT>"])"
dat += "<font dize = 9><BR>Cell charge: [D.cell.charge]/[D.cell.maxcharge]."
dat += "<BR>Currently located in: [get_area(D)]."
dat += "<BR><A href='?src=\ref[src];resync=\ref[D]'>Resync</A> | <A href='?src=\ref[src];shutdown=\ref[D]'>Shutdown</A></font>"
data["fabricator"] = dronefab
data["fabPower"] = dronefab?.produce_drones
dat += "<BR><BR><B>Request drone presence in area:</B> <A href='?src=\ref[src];setarea=1'>[drone_call_area]</A> (<A href='?src=\ref[src];ping=1'>Send ping</A>)"
data["areas"] = tagger_locations
data["selected_area"] = "[drone_call_area]"
dat += "<BR><BR><B>Drone fabricator</B>: "
dat += "[dronefab ? "<A href='?src=\ref[src];toggle_fab=1'>[(dronefab.produce_drones && !(dronefab.stat & NOPOWER)) ? "ACTIVE" : "INACTIVE"]</A>" : "<font color='red'><b>FABRICATOR NOT DETECTED.</b></font> (<A href='?src=\ref[src];search_fab=1'>search</a>)"]"
user << browse(dat, "window=computer;size=400x500")
onclose(user, "computer")
return
return data
/obj/machinery/computer/drone_control/Topic(href, href_list)
/obj/machinery/computer/drone_control/tgui_act(action, params)
if(..())
return
return TRUE
if(!allowed(usr))
to_chat(usr, "<span class='danger'>Access denied.</span>")
return
switch(action)
if("set_dcall_area")
var/t_area = params["area"]
if(!t_area || !(t_area in tagger_locations))
return
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
usr.set_machine(src)
drone_call_area = t_area
to_chat(usr, "<span class='notice'>You set the area selector to [drone_call_area].</span>")
if (href_list["setarea"])
if("ping")
to_chat(usr, "<span class='notice'>You issue a maintenance request for all active drones, highlighting [drone_call_area].</span>")
for(var/mob/living/silicon/robot/drone/D in player_list)
if(D.stat == 0)
to_chat(D, "-- Maintenance drone presence requested in: [drone_call_area].")
//Probably should consider using another list, but this one will do.
var/t_area = input("Select the area to ping.", "Set Target Area", null) as null|anything in tagger_locations
if("resync")
var/mob/living/silicon/robot/drone/D = locate(params["ref"])
if(!t_area)
return
if(D.stat != 2)
to_chat(usr, "<span class='danger'>You issue a law synchronization directive for the drone.</span>")
D.law_resync()
drone_call_area = t_area
to_chat(usr, "<span class='notice'>You set the area selector to [drone_call_area].</span>")
if("shutdown")
var/mob/living/silicon/robot/drone/D = locate(params["ref"])
else if (href_list["ping"])
if(D.stat != 2)
to_chat(usr, "<span class='danger'>You issue a kill command for the unfortunate drone.</span>")
message_admins("[key_name_admin(usr)] issued kill order for drone [key_name_admin(D)] from control console.")
log_game("[key_name(usr)] issued kill order for [key_name(src)] from control console.")
D.shut_down()
to_chat(usr, "<span class='notice'>You issue a maintenance request for all active drones, highlighting [drone_call_area].</span>")
for(var/mob/living/silicon/robot/drone/D in player_list)
if(D.stat == 0)
to_chat(D, "-- Maintenance drone presence requested in: [drone_call_area].")
if("search_fab")
if(dronefab)
return
else if (href_list["resync"])
for(var/obj/machinery/drone_fabricator/fab in oview(3,src))
if(fab.stat & NOPOWER)
continue
var/mob/living/silicon/robot/drone/D = locate(href_list["resync"])
dronefab = fab
to_chat(usr, "<span class='notice'>Drone fabricator located.</span>")
return
if(D.stat != 2)
to_chat(usr, "<span class='danger'>You issue a law synchronization directive for the drone.</span>")
D.law_resync()
else if (href_list["shutdown"])
var/mob/living/silicon/robot/drone/D = locate(href_list["shutdown"])
if(D.stat != 2)
to_chat(usr, "<span class='danger'>You issue a kill command for the unfortunate drone.</span>")
message_admins("[key_name_admin(usr)] issued kill order for drone [key_name_admin(D)] from control console.")
log_game("[key_name(usr)] issued kill order for [key_name(src)] from control console.")
D.shut_down()
else if (href_list["search_fab"])
if(dronefab)
return
for(var/obj/machinery/drone_fabricator/fab in oview(3,src))
if(fab.stat & NOPOWER)
continue
dronefab = fab
to_chat(usr, "<span class='notice'>Drone fabricator located.</span>")
return
to_chat(usr, "<span class='danger'>Unable to locate drone fabricator.</span>")
else if (href_list["toggle_fab"])
if(!dronefab)
return
if(get_dist(src,dronefab) > 3)
dronefab = null
to_chat(usr, "<span class='danger'>Unable to locate drone fabricator.</span>")
return
dronefab.produce_drones = !dronefab.produce_drones
to_chat(usr, "<span class='notice'>You [dronefab.produce_drones ? "enable" : "disable"] drone production in the nearby fabricator.</span>")
if("toggle_fab")
if(!dronefab)
return
src.updateUsrDialog()
if(get_dist(src,dronefab) > 3)
dronefab = null
to_chat(usr, "<span class='danger'>Unable to locate drone fabricator.</span>")
return
dronefab.produce_drones = !dronefab.produce_drones
to_chat(usr, "<span class='notice'>You [dronefab.produce_drones ? "enable" : "disable"] drone production in the nearby fabricator.</span>")
@@ -38,6 +38,10 @@
drop_item()
return
/obj/item/weapon/gripper/AltClick(mob/user)
drop_item()
return
/obj/item/weapon/gripper/omni
name = "omni gripper"
desc = "A strange grasping tool that can hold anything a human can, but still maintains the limitations of application its more limited cousins have."
@@ -252,12 +256,15 @@
return resolved
return ..()
/obj/item/weapon/gripper/verb/drop_item()
/obj/item/weapon/gripper/verb/drop_gripper_item()
set name = "Drop Item"
set desc = "Release an item from your magnetic gripper."
set category = "Robot Commands"
drop_item()
obj/item/weapon/gripper/proc/drop_item()
if(!wrapped)
//There's some weirdness with items being lost inside the arm. Trying to fix all cases. ~Z
for(var/obj/item/thing in src.contents)
@@ -268,7 +275,7 @@
wrapped = null
return
to_chat(src.loc, "<span class='danger'>You drop \the [wrapped].</span>")
to_chat(src.loc, "<span class='notice'>You drop \the [wrapped].</span>")
wrapped.loc = get_turf(src)
wrapped = null
//update_icon()
+8 -8
View File
@@ -1,11 +1,11 @@
/mob/living/silicon
var/register_alarms = 1
var/datum/nano_module/alarm_monitor/all/alarm_monitor
var/datum/nano_module/atmos_control/atmos_control
var/datum/tgui_module/alarm_monitor/all/robot/alarm_monitor
var/datum/tgui_module/atmos_control/robot/atmos_control
var/datum/tgui_module/crew_monitor/robot/crew_monitor
var/datum/nano_module/law_manager/law_manager
var/datum/nano_module/power_monitor/power_monitor
var/datum/nano_module/rcon/rcon
var/datum/tgui_module/power_monitor/robot/power_monitor
var/datum/tgui_module/rcon/robot/rcon
/mob/living/silicon
var/list/silicon_subsystems = list(
@@ -49,7 +49,7 @@
set name = "Alarm Monitor"
set category = "Subystems"
alarm_monitor.ui_interact(usr, state = self_state)
alarm_monitor.tgui_interact(usr)
/********************
* Atmos Control *
@@ -58,7 +58,7 @@
set category = "Subystems"
set name = "Atmospherics Control"
atmos_control.ui_interact(usr, state = self_state)
atmos_control.tgui_interact(usr)
/********************
* Crew Monitor *
@@ -85,7 +85,7 @@
set category = "Subystems"
set name = "Power Monitor"
power_monitor.ui_interact(usr, state = self_state)
power_monitor.tgui_interact(usr)
/************
* RCON *
@@ -94,4 +94,4 @@
set category = "Subystems"
set name = "RCON"
rcon.ui_interact(usr, state = self_state)
rcon.tgui_interact(usr)
+21 -6
View File
@@ -343,7 +343,7 @@
/mob/proc/set_respawn_timer(var/time)
// Try to figure out what time to use
// Special cases, can never respawn
if(ticker?.mode?.deny_respawn)
time = -1
@@ -351,22 +351,22 @@
time = -1
else if(!config.respawn)
time = -1
// Special case for observing before game start
else if(ticker?.current_state <= GAME_STATE_SETTING_UP)
time = 1 MINUTE
// Wasn't given a time, use the config time
else if(!time)
time = config.respawn_time
var/keytouse = ckey
// Try harder to find a key to use
if(!keytouse && key)
keytouse = ckey(key)
else if(!keytouse && mind?.key)
keytouse = ckey(mind.key)
GLOB.respawn_timers[keytouse] = world.time + time
/mob/observer/dead/set_respawn_timer()
@@ -388,7 +388,7 @@
var/choice = alert(usr, "Returning to the menu will prevent your character from being revived in-round. Are you sure?", "Confirmation", "No, wait", "Yes, leave")
if(choice == "No, wait")
return
// Beyond this point, you're going to respawn
to_chat(usr, config.respawn_message)
@@ -505,6 +505,11 @@
set category = "IC"
if(pulling)
if(ishuman(pulling))
var/mob/living/carbon/human/H = pulling
visible_message(SPAN_WARNING("\The [src] lets go of \the [H]."), SPAN_NOTICE("You let go of \the [H]."), exclude_mobs = list(H))
if(!H.stat)
to_chat(H, SPAN_WARNING("\The [src] lets go of you."))
pulling.pulledby = null
pulling = null
if(pullin)
@@ -576,6 +581,16 @@
if(ishuman(AM))
var/mob/living/carbon/human/H = AM
if(H.lying) // If they're on the ground we're probably dragging their arms to move them
visible_message(SPAN_WARNING("\The [src] leans down and grips \the [H]'s arms."), SPAN_NOTICE("You lean down and grip \the [H]'s arms."), exclude_mobs = list(H))
if(!H.stat)
to_chat(H, SPAN_WARNING("\The [src] leans down and grips your arms."))
else //Otherwise we're probably just holding their arm to lead them somewhere
visible_message(SPAN_WARNING("\The [src] grips \the [H]'s arm."), SPAN_NOTICE("You grip \the [H]'s arm."), exclude_mobs = list(H))
if(!H.stat)
to_chat(H, SPAN_WARNING("\The [src] grips your arm."))
playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 25) //Quieter than hugging/grabbing but we still want some audio feedback
if(H.pull_damage())
to_chat(src, "<font color='red'><B>Pulling \the [H] in their current condition would probably be a bad idea.</B></font>")
@@ -582,7 +582,6 @@
// Do the initial caching of the player's body icons.
new_character.force_update_limbs()
new_character.update_icons_body()
new_character.update_eyes()
new_character.key = key //Manually transfer the key to log them in
@@ -1304,6 +1304,35 @@
icon_state = "teshari_mushroom"
species_allowed = list(SPECIES_TESHARI)
//Tesh things ported from Ark Station
teshari_twies
name = "Teshari Twies"
icon_state = "teshari_twies"
species_allowed = list(SPECIES_TESHARI)
teshari_backstrafe
name = "Teshari Backstrafe"
icon_state = "teshari_backstrafe"
species_allowed = list(SPECIES_TESHARI)
teshari_longway
name = "Teshari Long way"
icon_state = "teshari_longway"
species_allowed = list(SPECIES_TESHARI)
teshari_tree
name = "Teshari Tree"
icon_state = "teshari_tree"
species_allowed = list(SPECIES_TESHARI)
teshari_fluffymohawk
name = "Teshari Fluffy Mohawk"
icon_state = "teshari_fluffymohawk"
species_allowed = list(SPECIES_TESHARI)
//bald tesh hair for FBP use
teshari_bald
name = "Bald (use with FBP)"
icon_state = "bald"
@@ -57,41 +57,43 @@
ntnet_global.add_log("Quantum relay switched from overload recovery mode to normal operation mode.")
..()
/obj/machinery/ntnet_relay/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
/obj/machinery/ntnet_relay/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "NTNetRelay", src)
ui.open()
/obj/machinery/ntnet_relay/tgui_data(mob/user)
var/list/data = list()
data["enabled"] = enabled
data["dos_capacity"] = dos_capacity
data["dos_overload"] = dos_overload
data["dos_crashed"] = dos_failure
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "ntnet_relay.tmpl", "NTNet Quantum Relay", 500, 300, state = state)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
return data
/obj/machinery/ntnet_relay/attack_hand(var/mob/living/user)
ui_interact(user)
tgui_interact(user)
/obj/machinery/ntnet_relay/Topic(href, href_list)
/obj/machinery/ntnet_relay/tgui_act(action, params)
if(..())
return 1
if(href_list["restart"])
dos_overload = 0
dos_failure = 0
update_icon()
ntnet_global.add_log("Quantum relay manually restarted from overload recovery mode to normal operation mode.")
return 1
else if(href_list["toggle"])
enabled = !enabled
ntnet_global.add_log("Quantum relay manually [enabled ? "enabled" : "disabled"].")
update_icon()
return 1
else if(href_list["purge"])
ntnet_global.banned_nids.Cut()
ntnet_global.add_log("Manual override: Network blacklist cleared.")
return 1
return TRUE
switch(action)
if("restart")
dos_overload = 0
dos_failure = 0
update_icon()
ntnet_global.add_log("Quantum relay manually restarted from overload recovery mode to normal operation mode.")
. = TRUE
if("toggle")
enabled = !enabled
ntnet_global.add_log("Quantum relay manually [enabled ? "enabled" : "disabled"].")
update_icon()
. = TRUE
if("purge")
ntnet_global.banned_nids.Cut()
ntnet_global.add_log("Manual override: Network blacklist cleared.")
. = TRUE
/obj/machinery/ntnet_relay/New()
..()
@@ -1,7 +1,7 @@
/datum/computer_file/program/alarm_monitor
filename = "alarmmonitoreng"
filedesc = "Alarm Monitoring (Engineering)"
nanomodule_path = /datum/nano_module/alarm_monitor/engineering
tguimodule_path = /datum/tgui_module/alarm_monitor/engineering/ntos
ui_header = "alarm_green.gif"
program_icon_state = "alert-green"
program_key_state = "atmos_key"
@@ -15,8 +15,8 @@
/datum/computer_file/program/alarm_monitor/process_tick()
..()
var/datum/nano_module/alarm_monitor/NMA = NM
if(istype(NMA) && NMA.has_major_alarms())
var/datum/tgui_module/alarm_monitor/TMA = TM
if(istype(TMA) && TMA.has_major_alarms())
if(!has_alert)
program_icon_state = "alert-red"
ui_header = "alarm_red.gif"
@@ -29,112 +29,3 @@
update_computer_icon()
has_alert = 0
return 1
/datum/nano_module/alarm_monitor
name = "Alarm monitor"
var/list_cameras = 0 // Whether or not to list camera references. A future goal would be to merge this with the enginering/security camera console. Currently really only for AI-use.
var/list/datum/alarm_handler/alarm_handlers // The particular list of alarm handlers this alarm monitor should present to the user.
//available_to_ai = FALSE
/datum/nano_module/alarm_monitor/New()
..()
alarm_handlers = list()
/datum/nano_module/alarm_monitor/all/New()
..()
alarm_handlers = SSalarm.all_handlers
/datum/nano_module/alarm_monitor/engineering/New()
..()
alarm_handlers = list(atmosphere_alarm, fire_alarm, power_alarm)
/datum/nano_module/alarm_monitor/security/New()
..()
alarm_handlers = list(camera_alarm, motion_alarm)
/datum/nano_module/alarm_monitor/proc/register_alarm(var/object, var/procName)
for(var/datum/alarm_handler/AH in alarm_handlers)
AH.register_alarm(object, procName)
/datum/nano_module/alarm_monitor/proc/unregister_alarm(var/object)
for(var/datum/alarm_handler/AH in alarm_handlers)
AH.unregister_alarm(object)
/datum/nano_module/alarm_monitor/proc/all_alarms()
var/z = get_z(nano_host())
var/list/all_alarms = new()
for(var/datum/alarm_handler/AH in alarm_handlers)
all_alarms += AH.visible_alarms(z)
return all_alarms
/datum/nano_module/alarm_monitor/proc/major_alarms()
var/z = get_z(nano_host())
var/list/all_alarms = new()
for(var/datum/alarm_handler/AH in alarm_handlers)
all_alarms += AH.major_alarms(z)
return all_alarms
// Modified version of above proc that uses slightly less resources, returns 1 if there is a major alarm, 0 otherwise.
/datum/nano_module/alarm_monitor/proc/has_major_alarms()
var/z = get_z(nano_host())
for(var/datum/alarm_handler/AH in alarm_handlers)
if(AH.has_major_alarms(z))
return 1
return 0
/datum/nano_module/alarm_monitor/proc/minor_alarms()
var/z = get_z(nano_host())
var/list/all_alarms = new()
for(var/datum/alarm_handler/AH in alarm_handlers)
all_alarms += AH.minor_alarms(z)
return all_alarms
/datum/nano_module/alarm_monitor/Topic(ref, href_list)
if(..())
return 1
if(href_list["switchTo"])
var/obj/machinery/camera/C = locate(href_list["switchTo"]) in cameranet.cameras
if(!C)
return
usr.switch_to_camera(C)
return 1
/datum/nano_module/alarm_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
var/list/data = host.initial_data()
var/categories[0]
var/z = get_z(nano_host())
for(var/datum/alarm_handler/AH in alarm_handlers)
categories[++categories.len] = list("category" = AH.category, "alarms" = list())
for(var/datum/alarm/A in AH.visible_alarms(z))
var/cameras[0]
var/lost_sources[0]
if(isAI(user))
for(var/obj/machinery/camera/C in A.cameras())
cameras[++cameras.len] = C.nano_structure()
for(var/datum/alarm_source/AS in A.sources)
if(!AS.source)
lost_sources[++lost_sources.len] = AS.source_name
categories[categories.len]["alarms"] += list(list(
"name" = sanitize("[A.alarm_name()]" + "[A.max_severity() > 1 ? "(MAJOR)" : ""]"),
"origin_lost" = A.origin == null,
"has_cameras" = cameras.len,
"cameras" = cameras,
"lost_sources" = lost_sources.len ? sanitize(english_list(lost_sources, nothing_text = "", and_text = ", ")) : ""))
data["categories"] = categories
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "alarm_monitor.tmpl", "Alarm Monitoring Console", 800, 800, state = state)
if(host.update_layout()) // This is necessary to ensure the status bar remains updated along with rest of the UI.
ui.auto_update_layout = 1
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
@@ -1,7 +1,7 @@
/datum/computer_file/program/atmos_control
filename = "atmoscontrol"
filedesc = "Atmosphere Control"
nanomodule_path = /datum/nano_module/atmos_control
tguimodule_path = /datum/tgui_module/atmos_control/ntos
program_icon_state = "atmos_control"
program_key_state = "atmos_key"
program_menu_icon = "shuffle"
@@ -12,96 +12,3 @@
requires_ntnet_feature = NTNET_SYSTEMCONTROL
usage_flags = PROGRAM_LAPTOP | PROGRAM_CONSOLE
size = 17
/datum/nano_module/atmos_control
name = "Atmospherics Control"
var/obj/access = new()
var/emagged = 0
var/ui_ref
var/list/monitored_alarms = list()
/datum/nano_module/atmos_control/New(atmos_computer, req_access, req_one_access, monitored_alarm_ids)
..()
access.req_access = req_access
access.req_one_access = req_one_access
if(monitored_alarm_ids)
for(var/obj/machinery/alarm/alarm in machines)
if(alarm.alarm_id && alarm.alarm_id in monitored_alarm_ids)
monitored_alarms += alarm
// machines may not yet be ordered at this point
monitored_alarms = dd_sortedObjectList(monitored_alarms)
/datum/nano_module/atmos_control/Topic(href, href_list)
if(..())
return 1
if(href_list["alarm"])
if(ui_ref)
var/obj/machinery/alarm/alarm = locate(href_list["alarm"]) in (monitored_alarms.len ? monitored_alarms : machines)
if(alarm)
var/datum/topic_state/TS = generate_state(alarm)
alarm.ui_interact(usr, master_ui = ui_ref, state = TS)
return 1
/datum/nano_module/atmos_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state)
var/list/data = host.initial_data()
var/alarms[0]
var/z = get_z(nano_host())
var/list/map_levels = using_map.get_map_levels(z)
data["map_levels"] = map_levels
// TODO: Move these to a cache, similar to cameras
for(var/obj/machinery/alarm/alarm in (monitored_alarms.len ? monitored_alarms : machines))
if(!monitored_alarms.len && alarm.alarms_hidden)
continue
if(!(alarm.z in map_levels))
continue
alarms[++alarms.len] = list(
"name" = sanitize(alarm.name),
"ref"= "\ref[alarm]",
"danger" = max(alarm.danger_level, alarm.alarm_area.atmosalm),
"x" = alarm.x,
"y" = alarm.y,
"z" = alarm.z)
data["alarms"] = alarms
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "atmos_control.tmpl", src.name, 625, 625, state = state)
if(host.update_layout()) // This is necessary to ensure the status bar remains updated along with rest of the UI.
ui.auto_update_layout = 1
// adding a template with the key "mapContent" enables the map ui functionality
ui.add_template("mapContent", "atmos_control_map_content.tmpl")
// adding a template with the key "mapHeader" replaces the map header content
ui.add_template("mapHeader", "atmos_control_map_header.tmpl")
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(0)
ui_ref = ui
/datum/nano_module/atmos_control/proc/generate_state(air_alarm)
var/datum/topic_state/air_alarm/state = new()
state.atmos_control = src
state.air_alarm = air_alarm
return state
/datum/topic_state/air_alarm
var/datum/nano_module/atmos_control/atmos_control = null
var/obj/machinery/alarm/air_alarm = null
/datum/topic_state/air_alarm/can_use_topic(var/src_object, var/mob/user)
if(has_access(user))
return STATUS_INTERACTIVE
return STATUS_UPDATE
/datum/topic_state/air_alarm/href_list(var/mob/user)
var/list/extra_href = list()
extra_href["remote_connection"] = 1
extra_href["remote_access"] = has_access(user)
return extra_href
/datum/topic_state/air_alarm/proc/has_access(var/mob/user)
return user && (isAI(user) || atmos_control.access.allowed(user) || atmos_control.emagged || air_alarm.rcon_setting == RCON_YES || (air_alarm.alarm_area.atmosalm && air_alarm.rcon_setting == RCON_AUTO) || (access_ce in user.GetAccess()))
@@ -1,7 +1,7 @@
/datum/computer_file/program/power_monitor
filename = "powermonitor"
filedesc = "Power Monitoring"
nanomodule_path = /datum/nano_module/power_monitor/
tguimodule_path = /datum/tgui_module/power_monitor/ntos
program_icon_state = "power_monitor"
program_key_state = "power_key"
program_menu_icon = "battery-3"
@@ -15,8 +15,8 @@
/datum/computer_file/program/power_monitor/process_tick()
..()
var/datum/nano_module/power_monitor/NMA = NM
if(istype(NMA) && NMA.has_alarm())
var/datum/tgui_module/power_monitor/TMA = TM
if(istype(TMA) && TMA.has_alarm())
if(!has_alert)
program_icon_state = "power_monitor_warn"
ui_header = "power_warn.gif"
@@ -28,90 +28,3 @@
ui_header = "power_norm.gif"
update_computer_icon()
has_alert = 0
/datum/nano_module/power_monitor
name = "Power monitor"
var/list/grid_sensors
var/active_sensor = null //name_tag of the currently selected sensor
/datum/nano_module/power_monitor/New()
..()
refresh_sensors()
// Checks whether there is an active alarm, if yes, returns 1, otherwise returns 0.
/datum/nano_module/power_monitor/proc/has_alarm()
for(var/obj/machinery/power/sensor/S in grid_sensors)
if(S.check_grid_warning())
return 1
return 0
// If PC is not null header template is loaded. Use PC.get_header_data() to get relevant nanoui data from it. All data entries begin with "PC_...."
// In future it may be expanded to other modular computer devices.
/datum/nano_module/power_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
var/list/data = host.initial_data()
var/list/sensors = list()
// Focus: If it remains null if no sensor is selected and UI will display sensor list, otherwise it will display sensor reading.
var/obj/machinery/power/sensor/focus = null
var/z = get_z(nano_host())
var/list/map_levels = using_map.get_map_levels(z)
data["map_levels"] = map_levels
// Build list of data from sensor readings.
for(var/obj/machinery/power/sensor/S in grid_sensors)
if(!(S.z in map_levels))
continue
sensors.Add(list(list(
"name" = S.name_tag,
"alarm" = S.check_grid_warning()
)))
if(S.name_tag == active_sensor)
focus = S
data["all_sensors"] = sensors
if(focus)
data["focus"] = focus.return_reading_data()
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "power_monitor.tmpl", "Power Monitoring Console", 800, 500, state = state)
if(host.update_layout()) // This is necessary to ensure the status bar remains updated along with rest of the UI.
ui.auto_update_layout = 1
// adding a template with the key "mapContent" enables the map ui functionality
ui.add_template("mapContent", "power_monitor_map_content.tmpl")
// adding a template with the key "mapHeader" replaces the map header content
ui.add_template("mapHeader", "power_monitor_map_header.tmpl")
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
// Refreshes list of active sensors kept on this computer.
/datum/nano_module/power_monitor/proc/refresh_sensors()
grid_sensors = list()
var/turf/T = get_turf(nano_host())
var/list/levels = list()
if(!T) // Safety check
return
if(T)
levels += using_map.get_map_levels(T.z, FALSE)
for(var/obj/machinery/power/sensor/S in machines)
if(T && (S.loc.z == T.z) || (S.loc.z in levels) || (S.long_range)) // Consoles have range on their Z-Level. Sensors with long_range var will work between Z levels.
if(S.name_tag == "#UNKN#") // Default name. Shouldn't happen!
warning("Powernet sensor with unset ID Tag! [S.x]X [S.y]Y [S.z]Z")
else
grid_sensors += S
// Allows us to process UI clicks, which are relayed in form of hrefs.
/datum/nano_module/power_monitor/Topic(href, href_list)
if(..())
return 1
if( href_list["clear"] )
active_sensor = null
. = 1
if( href_list["refresh"] )
refresh_sensors()
. = 1
else if( href_list["setsensor"] )
active_sensor = href_list["setsensor"]
. = 1
@@ -1,7 +1,7 @@
/datum/computer_file/program/rcon_console
filename = "rconconsole"
filedesc = "RCON Remote Control"
nanomodule_path = /datum/nano_module/rcon
tguimodule_path = /datum/tgui_module/rcon/ntos
program_icon_state = "generic"
program_key_state = "rd_key"
program_menu_icon = "power"
@@ -12,129 +12,3 @@
requires_ntnet_feature = NTNET_SYSTEMCONTROL
usage_flags = PROGRAM_LAPTOP | PROGRAM_CONSOLE
size = 19
/datum/nano_module/rcon
name = "Power RCON"
var/list/known_SMESs = null
var/list/known_breakers = null
// Allows you to hide specific parts of the UI
var/hide_SMES = 0
var/hide_SMES_details = 0
var/hide_breakers = 0
/datum/nano_module/rcon/ui_interact(mob/user, ui_key = "rcon", datum/nanoui/ui=null, force_open=1, var/datum/topic_state/state = default_state)
FindDevices() // Update our devices list
var/list/data = host.initial_data()
// SMES DATA (simplified view)
var/list/smeslist[0]
for(var/obj/machinery/power/smes/buildable/SMES in known_SMESs)
smeslist.Add(list(list(
"charge" = round(SMES.Percentage()),
"input_set" = SMES.input_attempt,
"input_val" = round(SMES.input_level/1000, 0.1),
"output_set" = SMES.output_attempt,
"output_val" = round(SMES.output_level/1000, 0.1),
"output_load" = round(SMES.output_used/1000, 0.1),
"RCON_tag" = SMES.RCon_tag
)))
data["smes_info"] = sortByKey(smeslist, "RCON_tag")
// BREAKER DATA (simplified view)
var/list/breakerlist[0]
for(var/obj/machinery/power/breakerbox/BR in known_breakers)
breakerlist.Add(list(list(
"RCON_tag" = BR.RCon_tag,
"enabled" = BR.on
)))
data["breaker_info"] = breakerlist
data["hide_smes"] = hide_SMES
data["hide_smes_details"] = hide_SMES_details
data["hide_breakers"] = hide_breakers
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "rcon.tmpl", "RCON Console", 600, 400, state = state)
if(host.update_layout()) // This is necessary to ensure the status bar remains updated along with rest of the UI.
ui.auto_update_layout = 1
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
// Proc: Topic()
// Parameters: 2 (href, href_list - allows us to process UI clicks)
// Description: Allows us to process UI clicks, which are relayed in form of hrefs.
/datum/nano_module/rcon/Topic(href, href_list)
if(..())
return
if(href_list["smes_in_toggle"])
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(href_list["smes_in_toggle"])
if(SMES)
SMES.toggle_input()
if(href_list["smes_out_toggle"])
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(href_list["smes_out_toggle"])
if(SMES)
SMES.toggle_output()
if(href_list["smes_in_set"])
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(href_list["smes_in_set"])
if(SMES)
var/inputset = (input(usr, "Enter new input level (0-[SMES.input_level_max/1000] kW)", "SMES Input Power Control", SMES.input_level/1000) as num) * 1000
SMES.set_input(inputset)
if(href_list["smes_out_set"])
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(href_list["smes_out_set"])
if(SMES)
var/outputset = (input(usr, "Enter new output level (0-[SMES.output_level_max/1000] kW)", "SMES Output Power Control", SMES.output_level/1000) as num) * 1000
SMES.set_output(outputset)
if(href_list["toggle_breaker"])
var/obj/machinery/power/breakerbox/toggle = null
for(var/obj/machinery/power/breakerbox/breaker in known_breakers)
if(breaker.RCon_tag == href_list["toggle_breaker"])
toggle = breaker
if(toggle)
if(toggle.update_locked)
to_chat(usr, "The breaker box was recently toggled. Please wait before toggling it again.")
else
toggle.auto_toggle()
if(href_list["hide_smes"])
hide_SMES = !hide_SMES
if(href_list["hide_smes_details"])
hide_SMES_details = !hide_SMES_details
if(href_list["hide_breakers"])
hide_breakers = !hide_breakers
// Proc: GetSMESByTag()
// Parameters: 1 (tag - RCON tag of SMES we want to look up)
// Description: Looks up and returns SMES which has matching RCON tag
/datum/nano_module/rcon/proc/GetSMESByTag(var/tag)
if(!tag)
return
for(var/obj/machinery/power/smes/buildable/S in known_SMESs)
if(S.RCon_tag == tag)
return S
// Proc: FindDevices()
// Parameters: None
// Description: Refreshes local list of known devices.
/datum/nano_module/rcon/proc/FindDevices()
known_SMESs = new /list()
var/z = get_z(nano_host())
var/list/map_levels = using_map.get_map_levels(z)
for(var/obj/machinery/power/smes/buildable/SMES in GLOB.smeses)
if(!(SMES.z in map_levels))
continue
if(SMES.RCon_tag && (SMES.RCon_tag != "NO_TAG") && SMES.RCon)
known_SMESs.Add(SMES)
known_breakers = new /list()
for(var/obj/machinery/power/breakerbox/breaker in machines)
if(!(breaker.z in map_levels))
continue
if(breaker.RCon_tag != "NO_TAG")
known_breakers.Add(breaker)
@@ -1,7 +1,7 @@
/datum/computer_file/program/shutoff_monitor
filename = "shutoffmonitor"
filedesc = "Shutoff Valve Monitoring"
nanomodule_path = /datum/nano_module/shutoff_monitor
tguimodule_path = /datum/tgui_module/shutoff_monitor/ntos
program_icon_state = "atmos_control"
program_key_state = "atmos_key"
program_menu_icon = "wrench"
@@ -11,53 +11,3 @@
network_destination = "shutoff valve control computer"
size = 5
var/has_alert = 0
/datum/nano_module/shutoff_monitor
name = "Shutoff Valve Monitoring"
/datum/nano_module/shutoff_monitor/Topic(ref, href_list)
if(..())
return 1
if(href_list["toggle_enable"])
var/obj/machinery/atmospherics/valve/shutoff/S = locate(href_list["toggle_enable"])
if(!istype(S))
return 0
S.close_on_leaks = !S.close_on_leaks
return 1
if(href_list["toggle_open"])
var/obj/machinery/atmospherics/valve/shutoff/S = locate(href_list["toggle_open"])
if(!istype(S))
return 0
if(S.open)
S.close()
else
S.open()
return 1
/datum/nano_module/shutoff_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
var/list/data = host.initial_data()
var/list/valves = list()
for(var/obj/machinery/atmospherics/valve/shutoff/S in GLOB.shutoff_valves)
valves.Add(list(list(
"name" = S.name,
"enabled" = S.close_on_leaks,
"open" = S.open,
"x" = S.x,
"y" = S.y,
"z" = S.z,
"ref" = "\ref[S]"
)))
data["valves"] = valves
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "shutoff_monitor.tmpl", "Shutoff Valve Monitoring", 627, 700, state = state)
if(host.update_layout()) // This is necessary to ensure the status bar remains updated along with rest of the UI.
ui.auto_update_layout = 1
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
@@ -1,7 +1,7 @@
/datum/computer_file/program/supermatter_monitor
filename = "supmon"
filedesc = "Supermatter Monitoring"
nanomodule_path = /datum/nano_module/supermatter_monitor/
tguimodule_path = /datum/tgui_module/supermatter_monitor/ntos
program_icon_state = "smmon_0"
program_key_state = "tech_key"
program_menu_icon = "notice"
@@ -15,119 +15,11 @@
/datum/computer_file/program/supermatter_monitor/process_tick()
..()
var/datum/nano_module/supermatter_monitor/NMS = NM
var/new_status = istype(NMS) ? NMS.get_status() : 0
var/datum/tgui_module/supermatter_monitor/TMS = TM
var/new_status = istype(TMS) ? TMS.get_status() : 0
if(last_status != new_status)
last_status = new_status
ui_header = "smmon_[last_status].gif"
program_icon_state = "smmon_[last_status]"
if(istype(computer))
computer.update_icon()
/datum/nano_module/supermatter_monitor
name = "Supermatter monitor"
var/list/supermatters
var/obj/machinery/power/supermatter/active = null // Currently selected supermatter crystal.
/datum/nano_module/supermatter_monitor/Destroy()
. = ..()
active = null
supermatters = null
/datum/nano_module/supermatter_monitor/New()
..()
refresh()
// Refreshes list of active supermatter crystals
/datum/nano_module/supermatter_monitor/proc/refresh()
supermatters = list()
var/z = get_z(nano_host())
if(!z)
return
var/valid_z_levels = using_map.get_map_levels(z)
for(var/obj/machinery/power/supermatter/S in machines)
// Delaminating, not within coverage, not on a tile.
if(S.grav_pulling || S.exploded || !(S.z in valid_z_levels) || !istype(S.loc, /turf/))
continue
supermatters.Add(S)
if(!(active in supermatters))
active = null
/datum/nano_module/supermatter_monitor/proc/get_status()
. = SUPERMATTER_INACTIVE
for(var/obj/machinery/power/supermatter/S in supermatters)
. = max(., S.get_status())
/datum/nano_module/supermatter_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
var/list/data = host.initial_data()
if(istype(active))
var/turf/T = get_turf(active)
if(!T)
active = null
return
var/datum/gas_mixture/air = T.return_air()
if(!istype(air))
active = null
return
data["active"] = 1
data["SM_integrity"] = active.get_integrity()
data["SM_power"] = active.power
data["SM_ambienttemp"] = air.temperature
data["SM_ambientpressure"] = air.return_pressure()
data["SM_EPR"] = active.get_epr()
//data["SM_EPR"] = active.get_epr()
if(air.total_moles)
data["SM_gas_O2"] = round(100*air.gas["oxygen"]/air.total_moles,0.01)
data["SM_gas_CO2"] = round(100*air.gas["carbon_dioxide"]/air.total_moles,0.01)
data["SM_gas_N2"] = round(100*air.gas["nitrogen"]/air.total_moles,0.01)
data["SM_gas_PH"] = round(100*air.gas["phoron"]/air.total_moles,0.01)
data["SM_gas_N2O"] = round(100*air.gas["sleeping_agent"]/air.total_moles,0.01)
else
data["SM_gas_O2"] = 0
data["SM_gas_CO2"] = 0
data["SM_gas_N2"] = 0
data["SM_gas_PH"] = 0
data["SM_gas_N2O"] = 0
else
var/list/SMS = list()
for(var/obj/machinery/power/supermatter/S in supermatters)
var/area/A = get_area(S)
if(!A)
continue
SMS.Add(list(list(
"area_name" = A.name,
"integrity" = S.get_integrity(),
"uid" = S.uid
)))
data["active"] = 0
data["supermatters"] = SMS
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "supermatter_monitor.tmpl", "Supermatter Monitoring", 600, 400, state = state)
if(host.update_layout())
ui.auto_update_layout = 1
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/datum/nano_module/supermatter_monitor/Topic(href, href_list)
if(..())
return 1
if( href_list["clear"] )
active = null
return 1
if( href_list["refresh"] )
refresh()
return 1
if( href_list["set"] )
var/newuid = text2num(href_list["set"])
for(var/obj/machinery/power/supermatter/S in supermatters)
if(S.uid == newuid)
active = S
return 1
@@ -2,5 +2,5 @@
filename = "alarmmonitorsec"
filedesc = "Alarm Monitoring (Security)"
extended_desc = "This program provides visual interface for the security alarm system."
nanomodule_path = /datum/nano_module/alarm_monitor/security
tguimodule_path = /datum/tgui_module/alarm_monitor/security/ntos
required_access = access_security
@@ -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
+4 -4
View File
@@ -34,19 +34,19 @@
access = access_engine
cost = 625
p_drain = 0.025
var/datum/nano_module/alarm_monitor/engineering/arscreen
var/datum/tgui_module/alarm_monitor/engineering/nif/tgarscreen
New()
..()
arscreen = new(nif)
tgarscreen = new(nif)
Destroy()
QDEL_NULL(arscreen)
QDEL_NULL(tgarscreen)
return ..()
activate()
if((. = ..()))
arscreen.ui_interact(nif.human,"main",null,1,nif_state)
tgarscreen.tgui_interact(nif.human)
return TRUE
deactivate()
+44 -31
View File
@@ -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)
+3 -3
View File
@@ -39,10 +39,10 @@
to_chat(user, "It reads \"[message]\".")
/obj/effect/decal/writing/attackby(var/obj/item/thing, var/mob/user)
if(is_hot(thing))
if(istype(thing, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/welder = thing
if(welder.isOn() && welder.remove_fuel(0,user) && do_after(user, 5, src) && !QDELETED(src))
playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
playsound(src.loc, welder.usesound, 50, 1)
user.visible_message("<span class='notice'>\The [user] clears away some graffiti.</span>")
qdel(src)
else if(thing.sharp)
@@ -61,4 +61,4 @@
if(lowertext(message) == "elbereth")
to_chat(user, "<span class='notice'>You feel much safer.</span>")
else
. = ..()
. = ..()
+214 -234
View File
@@ -27,9 +27,19 @@ GLOBAL_LIST_EMPTY(apcs)
#define APC_UPOVERLAY_LOCKED 4096
#define APC_UPOVERLAY_OPERATING 8192
#define APC_UPDATE_ICON_COOLDOWN 100 // 10 seconds
// main_status var
#define APC_EXTERNAL_POWER_NOTCONNECTED 0
#define APC_EXTERNAL_POWER_NOENERGY 1
#define APC_EXTERNAL_POWER_GOOD 2
// has_electronics var
#define APC_HAS_ELECTRONICS_NONE 0
#define APC_HAS_ELECTRONICS_WIRED 1
#define APC_HAS_ELECTRONICS_SECURED 2
// the Area Power Controller (APC), formerly Power Distribution Unit (PDU)
// one per area, needs wire conection to power network through a terminal
@@ -101,13 +111,13 @@ GLOBAL_LIST_EMPTY(apcs)
var/lastused_environ = 0
var/lastused_charging = 0
var/lastused_total = 0
var/main_status = 0
var/main_status = APC_EXTERNAL_POWER_NOTCONNECTED
var/mob/living/silicon/ai/hacker = null // Malfunction var. If set AI hacked the APC and has full control.
var/wiresexposed = 0
powernet = 0 // set so that APCs aren't found as powernet nodes //Hackish, Horrible, was like this before I changed it :(
var/debug= 0
var/autoflag= 0 // 0 = off, 1= eqp and lights off, 2 = eqp off, 3 = all on.
var/has_electronics = 0 // 0 - none, 1 - plugged in, 2 - secured by screwdriver
var/has_electronics = APC_HAS_ELECTRONICS_NONE // 0 - none, 1 - plugged in, 2 - secured by screwdriver
var/beenhit = 0 // used for counting how many times it has been hit, used for Aliens at the moment
var/longtermpower = 10
var/datum/wires/apc/wires = null
@@ -131,7 +141,7 @@ GLOBAL_LIST_EMPTY(apcs)
var/last_nightshift_switch = 0
/obj/machinery/power/apc/updateDialog()
if (stat & (BROKEN|MAINT))
if(stat & (BROKEN|MAINT))
return
..()
@@ -175,12 +185,12 @@ GLOBAL_LIST_EMPTY(apcs)
// offset 24 pixels in direction of dir
// this allows the APC to be embedded in a wall, yet still inside an area
if (building)
if(building)
set_dir(ndir)
pixel_x = (src.dir & 3)? 0 : (src.dir == 4 ? 26 : -26) //VOREStation Edit -> 24 to 26
pixel_y = (src.dir & 3)? (src.dir ==1 ? 26 : -26) : 0 //VOREStation Edit -> 24 to 26
if (building==0)
pixel_x = (dir & 3)? 0 : (dir == 4 ? 26 : -26) //VOREStation Edit -> 24 to 26
pixel_y = (dir & 3)? (dir ==1 ? 26 : -26) : 0 //VOREStation Edit -> 24 to 26
if(building==0)
init()
else
area = get_area(src)
@@ -189,11 +199,11 @@ GLOBAL_LIST_EMPTY(apcs)
operating = 0
name = "[area.name] APC"
stat |= MAINT
src.update_icon()
update_icon()
/obj/machinery/power/apc/Destroy()
GLOB.apcs -= src
src.update()
update()
area.apc = null
area.power_light = 0
area.power_equip = 0
@@ -216,11 +226,11 @@ GLOBAL_LIST_EMPTY(apcs)
// APCs are pixel-shifted, so they need to be updated.
/obj/machinery/power/apc/set_dir(new_dir)
..()
pixel_x = (src.dir & 3)? 0 : (src.dir == 4 ? 24 : -24)
pixel_y = (src.dir & 3)? (src.dir ==1 ? 24 : -24) : 0
pixel_x = (dir & 3)? 0 : (dir == 4 ? 24 : -24)
pixel_y = (dir & 3)? (dir ==1 ? 24 : -24) : 0
if(terminal)
terminal.disconnect_from_network()
terminal.set_dir(src.dir) // Terminal has same dir as master
terminal.set_dir(dir) // Terminal has same dir as master
terminal.connect_to_network() // Refresh the network the terminal is connected to.
return
@@ -230,25 +240,25 @@ GLOBAL_LIST_EMPTY(apcs)
/obj/machinery/power/apc/proc/make_terminal()
// create a terminal object at the same position as original turf loc
// wires will attach to this
terminal = new/obj/machinery/power/terminal(src.loc)
terminal = new/obj/machinery/power/terminal(loc)
terminal.set_dir(dir)
terminal.master = src
/obj/machinery/power/apc/proc/init()
has_electronics = 2 //installed and secured
has_electronics = APC_HAS_ELECTRONICS_SECURED //installed and secured
// is starting with a power cell installed, create it and set its charge level
if(cell_type)
src.cell = new cell_type(src)
cell = new cell_type(src)
cell.charge = start_charge * cell.maxcharge / 100.0 // (convert percentage to actual value)
var/area/A = src.loc.loc
var/area/A = loc.loc
//if area isn't specified use current
if(isarea(A) && src.areastring == null)
src.area = A
if(isarea(A) && !areastring)
area = A
name = "\improper [area.name] APC"
else
src.area = get_area_name(areastring)
area = get_area_name(areastring)
name = "\improper [area.name] APC"
area.apc = src
@@ -260,7 +270,7 @@ GLOBAL_LIST_EMPTY(apcs)
make_terminal()
spawn(5)
src.update()
update()
/obj/machinery/power/apc/examine(mob/user)
. = ..()
@@ -271,17 +281,17 @@ GLOBAL_LIST_EMPTY(apcs)
else if(opened)
if(has_electronics && terminal)
. += "The cover is [opened == 2 ? "removed" : "open"] and [ cell ? "a power cell is installed" : "the power cell is missing"]."
else if (!has_electronics && terminal)
else if(!has_electronics && terminal)
. += "The frame is wired, but the electronics are missing."
else if (has_electronics && !terminal)
else if(has_electronics && !terminal)
. += "The electronics are installed, but not wired."
else /* if (!has_electronics && !terminal) */
else /* if(!has_electronics && !terminal) */
. += "It's just an empty metal frame."
else
if (wiresexposed)
if(wiresexposed)
. += "The cover is closed and the wires are exposed."
else if ((locked && emagged) || hacker) //Some things can cause locked && emagged. Malf AI causes hacker.
else if((locked && emagged) || hacker) //Some things can cause locked && emagged. Malf AI causes hacker.
. += "The cover is closed, but the panel is unresponsive."
else if(!locked && emagged) //Normal emag does this.
. += "The cover is closed, but the panel is flashing an error."
@@ -292,7 +302,7 @@ GLOBAL_LIST_EMPTY(apcs)
// update the APC icon to show the three base states
// also add overlays for indicator lights
/obj/machinery/power/apc/update_icon()
if (!status_overlays)
if(!status_overlays)
status_overlays = 1
status_overlays_lock = new
status_overlays_charging = new
@@ -424,7 +434,7 @@ GLOBAL_LIST_EMPTY(apcs)
else if(charging == 2)
update_overlay |= APC_UPOVERLAY_CHARGEING2
if (!equipment)
if(!equipment)
update_overlay |= APC_UPOVERLAY_EQUIPMENT0
else if(equipment == 1)
update_overlay |= APC_UPOVERLAY_EQUIPMENT1
@@ -468,35 +478,34 @@ GLOBAL_LIST_EMPTY(apcs)
//attack with an item - open/close cover, insert cell, or (un)lock interface
/obj/machinery/power/apc/attackby(obj/item/W, mob/user)
if (istype(user, /mob/living/silicon) && get_dist(src,user)>1)
return src.attack_hand(user)
src.add_fingerprint(user)
if (W.is_crowbar() && opened)
if (has_electronics==1)
if (terminal)
if(issilicon(user) && get_dist(src,user) > 1)
return attack_hand(user)
add_fingerprint(user)
if(W.is_crowbar() && opened)
if(has_electronics == APC_HAS_ELECTRONICS_WIRED)
if(terminal)
to_chat(user, "<span class='warning'>Disconnect the wires first.</span>")
return
playsound(src, W.usesound, 50, 1)
to_chat(user, "You begin to remove the power control board...") //lpeters - fixed grammar issues //Ner - grrrrrr
if(do_after(user, 50 * W.toolspeed))
if (has_electronics==1)
has_electronics = 0
if ((stat & BROKEN))
if(has_electronics == APC_HAS_ELECTRONICS_WIRED)
has_electronics = APC_HAS_ELECTRONICS_NONE
if((stat & BROKEN))
user.visible_message(\
"<span class='warning'>[user.name] has broken the charred power control board inside [src.name]!</span>",\
"<span class='warning'>[user.name] has broken the charred power control board inside [name]!</span>",\
"<span class='notice'>You broke the charred power control board and remove the remains.</span>",
"You hear a crack!")
//ticker.mode:apcs-- //XSI said no and I agreed. -rastaf0
else
user.visible_message(\
"<span class='warning'>[user.name] has removed the power control board from [src.name]!</span>",\
"<span class='warning'>[user.name] has removed the power control board from [name]!</span>",\
"<span class='notice'>You remove the power control board.</span>")
new /obj/item/weapon/module/power_control(loc)
else if (opened!=2) //cover isn't removed
else if(opened != 2) //cover isn't removed
opened = 0
update_icon()
else if (W.is_crowbar() && !(stat & BROKEN) )
else if(W.is_crowbar() && !(stat & BROKEN) )
if(coverlocked && !(stat & MAINT))
to_chat(user, "<span class='warning'>The cover is locked and cannot be opened.</span>")
return
@@ -505,9 +514,9 @@ GLOBAL_LIST_EMPTY(apcs)
update_icon()
else if (istype(W, /obj/item/weapon/cell) && opened) // trying to put a cell inside
if(cell)
to_chat(user, "The [src.name] already has a power cell installed.")
to_chat(user, "The [name] already has a power cell installed.")
return
if (stat & MAINT)
if(stat & MAINT)
to_chat(user, "<span class='warning'>You need to install the wiring and electronics first.</span>")
return
if(W.w_class != ITEMSIZE_NORMAL)
@@ -518,27 +527,27 @@ GLOBAL_LIST_EMPTY(apcs)
W.forceMove(src)
cell = W
user.visible_message(\
"<span class='warning'>[user.name] has inserted a power cell into [src.name]!</span>",\
"<span class='warning'>[user.name] has inserted a power cell into [name]!</span>",\
"<span class='notice'>You insert the power cell.</span>")
chargecount = 0
update_icon()
else if (W.is_screwdriver()) // haxing
if(opened)
if (cell)
if(cell)
to_chat(user, "<span class='warning'>Remove the power cell first.</span>")
return
else
if (has_electronics==1 && terminal)
has_electronics = 2
if(has_electronics == APC_HAS_ELECTRONICS_WIRED && terminal)
has_electronics = APC_HAS_ELECTRONICS_SECURED
stat &= ~MAINT
playsound(src, W.usesound, 50, 1)
to_chat(user, "You screw the circuit electronics into place.")
else if (has_electronics==2)
has_electronics = 1
else if(has_electronics == APC_HAS_ELECTRONICS_SECURED)
has_electronics = APC_HAS_ELECTRONICS_WIRED
stat |= MAINT
playsound(src, W.usesound, 50, 1)
to_chat(user, "You unfasten the electronics.")
else /* has_electronics==0 */
else /* has_electronics == APC_HAS_ELECTRONICS_NONE */
to_chat(user, "<span class='warning'>There is nothing to secure.</span>")
return
update_icon()
@@ -548,10 +557,10 @@ GLOBAL_LIST_EMPTY(apcs)
playsound(src, W.usesound, 50, 1)
update_icon()
else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card
togglelock()
else if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card
togglelock(user)
else if (istype(W, /obj/item/stack/cable_coil) && !terminal && opened && has_electronics!=2)
else if(istype(W, /obj/item/stack/cable_coil) && !terminal && opened && has_electronics != APC_HAS_ELECTRONICS_SECURED)
var/turf/T = loc
if(istype(T) && !T.is_plating())
to_chat(user, "<span class='warning'>You must remove the floor plating in front of the APC first.</span>")
@@ -564,9 +573,9 @@ GLOBAL_LIST_EMPTY(apcs)
"You start adding cables to the APC frame...")
playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, 20))
if (C.amount >= 10 && !terminal && opened && has_electronics != 2)
if(C.amount >= 10 && !terminal && opened && has_electronics != APC_HAS_ELECTRONICS_SECURED)
var/obj/structure/cable/N = T.get_cable_node()
if (prob(50) && electrocute_mob(usr, N, N))
if(prob(50) && electrocute_mob(usr, N, N))
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
@@ -578,7 +587,7 @@ GLOBAL_LIST_EMPTY(apcs)
"You add cables to the APC frame.")
make_terminal()
terminal.connect_to_network()
else if (W.is_wirecutter() && terminal && opened && has_electronics!=2)
else if(W.is_wirecutter() && terminal && opened && has_electronics != APC_HAS_ELECTRONICS_SECURED)
var/turf/T = loc
if(istype(T) && !T.is_plating())
to_chat(user, "<span class='warning'>You must remove the floor plating in front of the APC first.</span>")
@@ -587,8 +596,8 @@ GLOBAL_LIST_EMPTY(apcs)
"You begin to cut the cables...")
playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, 50 * W.toolspeed))
if(terminal && opened && has_electronics!=2)
if (prob(50) && electrocute_mob(usr, terminal.powernet, terminal))
if(terminal && opened && has_electronics != APC_HAS_ELECTRONICS_SECURED)
if(prob(50) && electrocute_mob(usr, terminal.powernet, terminal))
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
@@ -597,22 +606,22 @@ GLOBAL_LIST_EMPTY(apcs)
new /obj/item/stack/cable_coil(loc,10)
to_chat(user, "<span class='notice'>You cut the cables and dismantle the power terminal.</span>")
qdel(terminal)
else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && !((stat & BROKEN)))
else if(istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics == APC_HAS_ELECTRONICS_NONE && !((stat & BROKEN)))
user.visible_message("<span class='warning'>[user.name] inserts the power control board into [src].</span>", \
"You start to insert the power control board into the frame...")
playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, 10))
if(has_electronics==0)
has_electronics = 1
if(has_electronics == APC_HAS_ELECTRONICS_NONE)
has_electronics = APC_HAS_ELECTRONICS_WIRED
reboot()
to_chat(user, "<span class='notice'>You place the power control board inside the frame.</span>")
qdel(W)
else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && ((stat & BROKEN)))
else if(istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics == APC_HAS_ELECTRONICS_NONE && ((stat & BROKEN)))
to_chat(user, "<span class='warning'>The [src] is too broken for that. Repair it first.</span>")
return
else if (istype(W, /obj/item/weapon/weldingtool) && opened && has_electronics==0 && !terminal)
else if(istype(W, /obj/item/weapon/weldingtool) && opened && has_electronics == APC_HAS_ELECTRONICS_NONE && !terminal)
var/obj/item/weapon/weldingtool/WT = W
if (WT.get_fuel() < 3)
if(WT.get_fuel() < 3)
to_chat(user, "<span class='warning'>You need more welding fuel to complete this task.</span>")
return
user.visible_message("<span class='warning'>[user.name] begins cutting apart [src] with the [WT.name].</span>", \
@@ -621,7 +630,7 @@ GLOBAL_LIST_EMPTY(apcs)
playsound(src, WT.usesound, 25, 1)
if(do_after(user, 50 * WT.toolspeed))
if(!src || !WT.remove_fuel(3, user)) return
if (emagged || (stat & BROKEN) || opened==2)
if(emagged || (stat & BROKEN) || opened==2)
new /obj/item/stack/material/steel(loc)
user.visible_message(\
"<span class='warning'>[src] has been cut apart by [user.name] with the [WT.name].</span>",\
@@ -635,8 +644,8 @@ GLOBAL_LIST_EMPTY(apcs)
"You hear welding.")
qdel(src)
return
else if (opened && ((stat & BROKEN) || hacker || emagged))
if (istype(W, /obj/item/frame/apc) && (stat & BROKEN))
else if(opened && ((stat & BROKEN) || hacker || emagged))
if(istype(W, /obj/item/frame/apc) && (stat & BROKEN))
if(cell)
to_chat(user, "<span class='warning'>You need to remove the power cell first.</span>")
return
@@ -648,10 +657,10 @@ GLOBAL_LIST_EMPTY(apcs)
qdel(W)
stat &= ~BROKEN
reboot()
if (opened==2)
if(opened==2)
opened = 1
update_icon()
else if (istype(W, /obj/item/device/multitool) && (hacker || emagged))
else if(istype(W, /obj/item/device/multitool) && (hacker || emagged))
if(cell)
to_chat(user, "<span class='warning'>You need to remove the power cell first.</span>")
return
@@ -663,12 +672,12 @@ GLOBAL_LIST_EMPTY(apcs)
playsound(src, 'sound/machines/chime.ogg', 25, 1)
reboot()
else
if ((stat & BROKEN) \
if((stat & BROKEN) \
&& !opened \
&& W.force >= 5 \
&& W.w_class >= ITEMSIZE_SMALL )
user.visible_message("<span class='danger'>The [src.name] has been hit with the [W.name] by [user.name]!</span>", \
"<span class='danger'>You hit the [src.name] with your [W.name]!</span>", \
user.visible_message("<span class='danger'>The [name] has been hit with the [W.name] by [user.name]!</span>", \
"<span class='danger'>You hit the [name] with your [W.name]!</span>", \
"You hear a bang!")
if(prob(20))
opened = 2
@@ -677,12 +686,12 @@ GLOBAL_LIST_EMPTY(apcs)
"You hear a bang!")
update_icon()
else
if (istype(user, /mob/living/silicon))
return src.attack_hand(user)
if (!opened && wiresexposed && (istype(W, /obj/item/device/multitool) || W.is_wirecutter() || istype(W, /obj/item/device/assembly/signaler)))
return src.attack_hand(user)
if(istype(user, /mob/living/silicon))
return attack_hand(user)
if(!opened && wiresexposed && (istype(W, /obj/item/device/multitool) || W.is_wirecutter() || istype(W, /obj/item/device/assembly/signaler)))
return attack_hand(user)
//Placeholder until someone can do take_damage() for APCs or something.
to_chat(user, "<span class='notice'>The [src.name] looks too sturdy to bash open with \the [W.name].</span>")
to_chat(user, "<span class='notice'>The [name] looks too sturdy to bash open with \the [W.name].</span>")
// attack with hand - remove cell (if cover open) or interact with the APC
@@ -698,7 +707,7 @@ GLOBAL_LIST_EMPTY(apcs)
else if(hacker)
to_chat(user, "<span class='warning'>Access denied.</span>")
else
if(src.allowed(usr) && !wires.is_cut(WIRE_IDSCAN))
if(allowed(user) && !wires.is_cut(WIRE_IDSCAN))
locked = !locked
to_chat(user, "You [ locked ? "lock" : "unlock"] the APC interface.")
update_icon()
@@ -707,10 +716,10 @@ GLOBAL_LIST_EMPTY(apcs)
/obj/machinery/power/apc/AltClick(mob/user)
..()
togglelock()
togglelock(user)
/obj/machinery/power/apc/emag_act(var/remaining_charges, var/mob/user)
if (!(emagged || hacker)) // trying to unlock with an emag card
if(!(emagged || hacker)) // trying to unlock with an emag card
if(opened)
to_chat(user, "You must close the cover to do that.")
else if(wiresexposed)
@@ -719,7 +728,7 @@ GLOBAL_LIST_EMPTY(apcs)
to_chat(user, "The [src] isn't working.")
else
flick("apc-spark", src)
if (do_after(user,6))
if(do_after(user,6))
emagged = 1
locked = 0
to_chat(user, "<span class='notice'>You emag the APC interface.</span>")
@@ -733,11 +742,9 @@ GLOBAL_LIST_EMPTY(apcs)
update_icon()
/obj/machinery/power/apc/attack_hand(mob/user)
// if (!can_use(user)) This already gets called in interact() and in topic()
// return
if(!user)
return
src.add_fingerprint(user)
add_fingerprint(user)
//Human mob special interaction goes here.
if(istype(user,/mob/living/carbon/human))
@@ -745,20 +752,20 @@ GLOBAL_LIST_EMPTY(apcs)
if(H.species.can_shred(H))
user.setClickCooldown(user.get_attack_speed())
user.visible_message("<span call='warning'>[user.name] slashes at the [src.name]!</span>", "<span class='notice'>You slash at the [src.name]!</span>")
user.visible_message("<span call='warning'>[user.name] slashes at the [name]!</span>", "<span class='notice'>You slash at the [name]!</span>")
playsound(src, 'sound/weapons/slash.ogg', 100, 1)
var/allcut = wires.is_all_cut()
if(beenhit >= pick(3, 4) && wiresexposed != 1)
wiresexposed = 1
src.update_icon()
src.visible_message("<span call='warning'>The [src.name]'s cover flies open, exposing the wires!</span>")
update_icon()
visible_message("<span call='warning'>The [name]'s cover flies open, exposing the wires!</span>")
else if(wiresexposed == 1 && allcut == 0)
wires.cut_all()
src.update_icon()
src.visible_message("<span call='warning'>The [src.name]'s wires are shredded!</span>")
update_icon()
visible_message("<span call='warning'>The [name]'s wires are shredded!</span>")
else
beenhit += 1
return
@@ -769,16 +776,21 @@ GLOBAL_LIST_EMPTY(apcs)
cell.add_fingerprint(user)
cell.update_icon()
src.cell = null
user.visible_message("<span class='warning'>[user.name] removes the power cell from [src.name]!</span>",\
cell = null
user.visible_message("<span class='warning'>[user.name] removes the power cell from [name]!</span>",\
"<span class='notice'>You remove the power cell.</span>")
charging = 0
src.update_icon()
update_icon()
return
if(stat & (BROKEN|MAINT))
return
// do APC interaction
src.interact(user)
interact(user)
/obj/machinery/power/apc/attack_ghost(mob/user)
if(panel_open)
return wires.Interact(user)
return tgui_interact(user)
/obj/machinery/power/apc/interact(mob/user)
if(!user)
@@ -788,15 +800,18 @@ GLOBAL_LIST_EMPTY(apcs)
wires.Interact(user)
return //The panel is visibly dark when the wires are exposed, so we shouldn't be able to interact with it.
return ui_interact(user)
return tgui_interact(user)
/obj/machinery/power/apc/tgui_interact(mob/user, datum/tgui/ui = null)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "APC", name) // 510, 460
ui.open()
/obj/machinery/power/apc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
if(!user)
return
/obj/machinery/power/apc/tgui_data(mob/user)
var/list/data = list(
"locked" = locked,
"normallyLocked" = locked,
"emagged" = emagged,
"isOperating" = operating,
"externalPower" = main_status,
@@ -808,7 +823,7 @@ GLOBAL_LIST_EMPTY(apcs)
"failTime" = failure_timer * 2,
"gridCheck" = grid_check,
"coverLocked" = coverlocked,
"siliconUser" = issilicon(user) || isobserver(user), //I add observer here so admins can have more control, even if it makes 'siliconUser' seem inaccurate.
"siliconUser" = issilicon(user) || (isobserver(user) && is_admin(user)), //I add observer here so admins can have more control, even if it makes 'siliconUser' seem inaccurate.
"emergencyLights" = !emergency_lights,
"nightshiftLights" = nightshift_lights,
"nightshiftSetting" = nightshift_setting,
@@ -847,18 +862,7 @@ GLOBAL_LIST_EMPTY(apcs)
)
)
// 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)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
ui = new(user, src, ui_key, "apc.tmpl", "[area.name] - APC", 520, data["siliconUser"] ? 490 : 465)
// when the ui is first opened this is the data it will use
ui.set_initial_data(data)
// open the new ui window
ui.open()
// auto update every Master Controller tick
ui.set_auto_update(1)
return data
/obj/machinery/power/apc/proc/report()
return "[area.name] : [equipment]/[lighting]/[environ] ([lastused_equip+lastused_light+lastused_environ]) : [cell? cell.percent() : "N/C"] ([charging])"
@@ -868,23 +872,23 @@ GLOBAL_LIST_EMPTY(apcs)
area.power_light = (lighting >= POWERCHAN_ON)
area.power_equip = (equipment >= POWERCHAN_ON)
area.power_environ = (environ >= POWERCHAN_ON)
// if (area.name == "AI Chamber")
// if(area.name == "AI Chamber")
// spawn(10)
// to_world(" [area.name] [area.power_equip]")
else
area.power_light = 0
area.power_equip = 0
area.power_environ = 0
// if (area.name == "AI Chamber")
// if(area.name == "AI Chamber")
// to_world("[area.power_equip]")
area.power_change()
/obj/machinery/power/apc/proc/can_use(mob/user as mob, var/loud = 0) //used by attack_hand() and Topic()
if(!user.client)
return 0
if(isobserver(user) && is_admin(user) ) //This is to allow nanoUI interaction by ghost admins.
if(isobserver(user) && is_admin(user)) //This is to allow nanoUI interaction by ghost admins.
return 1
if (user.stat)
if(user.stat)
return 0
if(inoperable())
return 0
@@ -897,7 +901,7 @@ GLOBAL_LIST_EMPTY(apcs)
to_chat(user, "<span class='warning'>You must stand to use [src]!</span>")
return 0
autoflag = 5
if (istype(user, /mob/living/silicon))
if(istype(user, /mob/living/silicon))
var/permit = 0 // Malfunction variable. If AI hacks APC it can control it even without AI control wire.
var/mob/living/silicon/ai/AI = user
var/mob/living/silicon/robot/robot = user
@@ -912,122 +916,90 @@ GLOBAL_LIST_EMPTY(apcs)
to_chat(user, "<span class='danger'>\The AI control for [src] has been disabled!</span>")
return 0
else
if (!in_range(src, user) || !istype(src.loc, /turf))
if(!in_range(src, user) || !istype(loc, /turf))
return 0
var/mob/living/carbon/human/H = user
if (istype(H) && prob(H.getBrainLoss()))
if(istype(H) && prob(H.getBrainLoss()))
to_chat(user, "<span class='danger'>You momentarily forget how to use [src].</span>")
return 0
return 1
/obj/machinery/power/apc/Topic(href, href_list)
if(..())
return 1
/obj/machinery/power/apc/tgui_act(action, params)
if(..() || !can_use(usr, TRUE))
return TRUE
if(!can_use(usr, 1))
return 1
// There's a handful of cases where we want to allow users to bypass the `locked` variable.
// If can_admin_interact() wasn't only defined on observers, this could just be part of a single-line
// conditional.
var/locked_exception = FALSE
if(issilicon(usr) || action == "nightshift")
locked_exception = TRUE
if(isobserver(usr))
var/mob/observer/dead/D = usr
if(D.can_admin_interact())
locked_exception = TRUE
if(href_list["nightshift"])
if(last_nightshift_switch > world.time - 10 SECONDS) // don't spam...
to_chat(usr, "<span class='warning'>[src]'s night lighting circuit breaker is still cycling!</span>")
return 0
last_nightshift_switch = world.time
nightshift_setting = text2num(href_list["nightshift"])
update_nightshift()
return 1
if(locked && !locked_exception)
return
if(locked && !issilicon(usr) )
if(isobserver(usr) )
var/mob/observer/dead/O = usr //Added to allow admin nanoUI interactions.
if(!O.can_admin_interact() ) //NanoUI /should/ make this not needed, but better safe than sorry.
to_chat(usr, "Try as you might, your ghostly fingers can't press the buttons.")
return 1
else
to_chat(usr, "You must unlock the panel to use this!")
return 1
if (href_list["lock"])
coverlocked = !coverlocked
else if (href_list["reboot"])
failure_timer = 0
update_icon()
update()
else if (href_list["emergency_lighting"])
emergency_lights = !emergency_lights
for(var/obj/machinery/light/L in area)
if(!initial(L.no_emergency)) //If there was an override set on creation, keep that override
L.no_emergency = emergency_lights
INVOKE_ASYNC(L, /obj/machinery/light/.proc/update, FALSE)
CHECK_TICK
else if (href_list["breaker"])
toggle_breaker()
else if (href_list["cmode"])
chargemode = !chargemode
if(!chargemode)
charging = 0
. = TRUE
switch(action)
if("lock")
if(locked_exception) // Yay code reuse
if(emagged || (stat & (BROKEN|MAINT)))
to_chat(usr, "The APC does not respond to the command.")
return
locked = !locked
update_icon()
if("cover")
coverlocked = !coverlocked
if("breaker")
toggle_breaker()
if("nightshift")
if(last_nightshift_switch > world.time - 10 SECONDS) // don't spam...
to_chat(usr, "<span class='warning'>[src]'s night lighting circuit breaker is still cycling!</span>")
return 0
last_nightshift_switch = world.time
nightshift_setting = params["nightshift"]
update_nightshift()
if("charge")
chargemode = !chargemode
if(!chargemode)
charging = 0
update_icon()
if("channel")
if(params["eqp"])
equipment = setsubsystem(text2num(params["eqp"]))
update_icon()
update()
else if(params["lgt"])
lighting = setsubsystem(text2num(params["lgt"]))
update_icon()
update()
else if(params["env"])
environ = setsubsystem(text2num(params["env"]))
update_icon()
update()
if("reboot")
failure_timer = 0
update_icon()
else if (href_list["eqp"])
var/val = text2num(href_list["eqp"])
equipment = setsubsystem(val)
update_icon()
update()
else if (href_list["lgt"])
var/val = text2num(href_list["lgt"])
lighting = setsubsystem(val)
update_icon()
update()
else if (href_list["env"])
var/val = text2num(href_list["env"])
environ = setsubsystem(val)
update_icon()
update()
else if (href_list["overload"])
if(istype(usr, /mob/living/silicon))
src.overload_lighting()
else if (href_list["toggleaccess"])
if(istype(usr, /mob/living/silicon))
if(emagged || (stat & (BROKEN|MAINT)))
to_chat(usr, "The APC does not respond to the command.")
return
locked = !locked
update_icon()
return 0
update()
if("emergency_lighting")
emergency_lights = !emergency_lights
for(var/obj/machinery/light/L in area)
if(!initial(L.no_emergency)) //If there was an override set on creation, keep that override
L.no_emergency = emergency_lights
INVOKE_ASYNC(L, /obj/machinery/light/.proc/update, FALSE)
CHECK_TICK
if("overload")
if(locked_exception) // Reusing for simplicity!
overload_lighting()
/obj/machinery/power/apc/proc/toggle_breaker()
operating = !operating
src.update()
update()
update_icon()
//This isn't used for now, so might as well disable it
/*
/obj/machinery/power/apc/proc/ion_act()
if(prob(3))
src.locked = 1
if (src.cell.charge > 0)
src.cell.charge = 0
cell.corrupt()
update_icon()
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
smoke.set_up(3, 0, src.loc)
smoke.attach(src)
smoke.start()
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
visible_message("<span class='danger'>The [src.name] suddenly lets out a blast of smoke and some sparks!</span>", \
"<span class='danger'>You hear sizzling electronics.</span>")
*/
/obj/machinery/power/apc/surplus()
if(terminal)
return terminal.surplus()
@@ -1083,12 +1055,12 @@ GLOBAL_LIST_EMPTY(apcs)
var/excess = surplus()
if(!src.avail())
main_status = 0
if(!avail())
main_status = APC_EXTERNAL_POWER_NOTCONNECTED
else if(excess < 0)
main_status = 1
main_status = APC_EXTERNAL_POWER_NOENERGY
else
main_status = 2
main_status = APC_EXTERNAL_POWER_GOOD
if(debug)
log_debug("Status: [main_status] - Excess: [excess] - Last Equip: [lastused_equip] - Last Light: [lastused_light] - Longterm: [longtermpower]")
@@ -1122,7 +1094,7 @@ GLOBAL_LIST_EMPTY(apcs)
// now trickle-charge the cell
lastused_charging = 0 // Clear the variable for new use.
if(src.attempt_charging())
if(attempt_charging())
if(excess > 0) // check to make sure we have enough to charge
// Max charge is capped to % per second constant
var/ch = min(excess*CELLRATE, cell.maxcharge*chargelevel)
@@ -1170,7 +1142,7 @@ GLOBAL_LIST_EMPTY(apcs)
force_update = 0
queue_icon_update()
update()
else if (last_ch != charging)
else if(last_ch != charging)
queue_icon_update()
/obj/machinery/power/apc/proc/update_channels()
@@ -1212,7 +1184,7 @@ GLOBAL_LIST_EMPTY(apcs)
// val 0=off, 1=off(auto) 2=on 3=on(auto)
// on 0=off, 1=on, 2=autooff
// defines a state machine, returns the new state
obj/machinery/power/apc/proc/autoset(var/cur_state, var/on)
/obj/machinery/power/apc/proc/autoset(var/cur_state, var/on)
switch(cur_state)
//if(POWERCHAN_OFF); //autoset will never turn on a channel set to off
if(POWERCHAN_OFF_AUTO)
@@ -1253,24 +1225,24 @@ obj/machinery/power/apc/proc/autoset(var/cur_state, var/on)
switch(severity)
if(1)
//set_broken() //now qdel() do what we need
if (cell)
if(cell)
cell.ex_act(1) // more lags woohoo
qdel(src)
return
if(2)
if (prob(75))
if(prob(75))
set_broken()
if (cell && prob(50))
if(cell && prob(50))
cell.ex_act(2)
if(3)
if (prob(50))
if(prob(50))
set_broken()
if (cell && prob(50))
if(cell && prob(50))
cell.ex_act(3)
if(4)
if (prob(25))
if(prob(25))
set_broken()
if (cell && prob(50))
if(cell && prob(50))
cell.ex_act(3)
return
@@ -1282,7 +1254,7 @@ obj/machinery/power/apc/proc/autoset(var/cur_state, var/on)
/obj/machinery/power/apc/proc/set_broken()
// Aesthetically much better!
spawn(rand(2,5))
src.visible_message("<span class='warning'>[src]'s screen flickers suddenly, then explodes in a rain of sparks and small debris!</span>")
visible_message("<span class='warning'>[src]'s screen flickers suddenly, then explodes in a rain of sparks and small debris!</span>")
stat |= BROKEN
operating = 0
update_icon()
@@ -1314,7 +1286,7 @@ obj/machinery/power/apc/proc/autoset(var/cur_state, var/on)
/obj/machinery/power/apc/proc/ai_hack(var/mob/living/silicon/ai/A = null)
if(!A || !A.hacked_apcs || hacker || aidisabled || A.stat == DEAD)
return 0
src.hacker = A
hacker = A
A.hacked_apcs += src
locked = 1
update_icon()
@@ -1406,3 +1378,11 @@ obj/machinery/power/apc/proc/autoset(var/cur_state, var/on)
CHECK_TICK
#undef APC_UPDATE_ICON_COOLDOWN
#undef APC_EXTERNAL_POWER_NOTCONNECTED
#undef APC_EXTERNAL_POWER_NOENERGY
#undef APC_EXTERNAL_POWER_GOOD
#undef APC_HAS_ELECTRONICS_NONE
#undef APC_HAS_ELECTRONICS_WIRED
#undef APC_HAS_ELECTRONICS_SECURED
+1 -1
View File
@@ -25,7 +25,7 @@
for(var/obj/structure/cable/C in src.loc)
qdel(C)
. = ..()
for(var/datum/nano_module/rcon/R in world)
for(var/datum/tgui_module/rcon/R in world)
R.FindDevices()
/obj/machinery/power/breakerbox/Initialize()
+29 -39
View File
@@ -192,58 +192,48 @@ GLOBAL_LIST_EMPTY(all_turbines)
if(stat & (BROKEN|NOPOWER) || !anchored) return
if(!circ1 || !circ2) //Just incase the middle part of the TEG was not wrenched last.
reconnect()
ui_interact(user)
tgui_interact(user)
/obj/machinery/power/generator/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/obj/machinery/power/generator/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "TEGenerator", name)
ui.open()
/obj/machinery/power/generator/tgui_data(mob/user)
// this is the data which will be sent to the ui
var/vertical = 0
if (dir == NORTH || dir == SOUTH)
vertical = 1
var/data[0]
data["totalOutput"] = effective_gen/1000
data["maxTotalOutput"] = max_power/1000
data["thermalOutput"] = last_thermal_gen/1000
data["circConnected"] = 0
var/list/data = list()
data["totalOutput"] = effective_gen
data["maxTotalOutput"] = max_power
data["thermalOutput"] = last_thermal_gen
data["primary"] = list()
if(circ1)
//The one on the left (or top)
data["primaryDir"] = vertical ? "top" : "left"
data["primaryOutput"] = last_circ1_gen/1000
data["primaryFlowCapacity"] = circ1.volume_capacity_used*100
data["primaryInletPressure"] = circ1.air1.return_pressure()
data["primaryInletTemperature"] = circ1.air1.temperature
data["primaryOutletPressure"] = circ1.air2.return_pressure()
data["primaryOutletTemperature"] = circ1.air2.temperature
data["primary"]["dir"] = vertical ? "top" : "left"
data["primary"]["output"] = last_circ1_gen
data["primary"]["flowCapacity"] = circ1.volume_capacity_used*100
data["primary"]["inletPressure"] = circ1.air1.return_pressure()
data["primary"]["inletTemperature"] = circ1.air1.temperature
data["primary"]["outletPressure"] = circ1.air2.return_pressure()
data["primary"]["outletTemperature"] = circ1.air2.temperature
data["secondary"] = list()
if(circ2)
//Now for the one on the right (or bottom)
data["secondaryDir"] = vertical ? "bottom" : "right"
data["secondaryOutput"] = last_circ2_gen/1000
data["secondaryFlowCapacity"] = circ2.volume_capacity_used*100
data["secondaryInletPressure"] = circ2.air1.return_pressure()
data["secondaryInletTemperature"] = circ2.air1.temperature
data["secondaryOutletPressure"] = circ2.air2.return_pressure()
data["secondaryOutletTemperature"] = circ2.air2.temperature
data["secondary"]["dir"] = vertical ? "bottom" : "right"
data["secondary"]["output"] = last_circ2_gen
data["secondary"]["flowCapacity"] = circ2.volume_capacity_used*100
data["secondary"]["inletPressure"] = circ2.air1.return_pressure()
data["secondary"]["inletTemperature"] = circ2.air1.temperature
data["secondary"]["outletPressure"] = circ2.air2.return_pressure()
data["secondary"]["outletTemperature"] = circ2.air2.temperature
if(circ1 && circ2)
data["circConnected"] = 1
else
data["circConnected"] = 0
// 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)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
ui = new(user, src, ui_key, "generator.tmpl", "Thermoelectric Generator", 450, 500)
// when the ui is first opened this is the data it will use
ui.set_initial_data(data)
// open the new ui window
ui.open()
// auto update every Master Controller tick
ui.set_auto_update(1)
return data
/obj/machinery/power/generator/power_change()
..()
+19 -18
View File
@@ -240,11 +240,16 @@ GLOBAL_LIST_EMPTY(gravity_generators)
/obj/machinery/gravity_generator/main/attack_hand(mob/user)
if((. = ..()))
return
if(CanUseTopic(user, global.default_state) > STATUS_CLOSE)
ui_interact(user)
return TRUE
tgui_interact(user)
return TRUE
/obj/machinery/gravity_generator/main/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/obj/machinery/gravity_generator/main/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "GravityGenerator", name)
ui.open()
/obj/machinery/gravity_generator/main/tgui_data(mob/user)
var/data[0]
data["breaker"] = breaker
@@ -253,22 +258,18 @@ GLOBAL_LIST_EMPTY(gravity_generators)
data["on"] = on
data["operational"] = (stat & BROKEN) ? FALSE : TRUE
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "gravity_generator.tmpl", src.name, 500, 400)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
return data
/obj/machinery/gravity_generator/main/Topic(href, href_list, datum/topic_state/state = default_state)
if((. = ..()))
return
/obj/machinery/gravity_generator/main/tgui_act(action, params)
if((..()))
return TRUE
if(href_list["gentoggle"])
breaker = !breaker
investigate_log("was toggled [breaker ? "<font color='green'>ON</font>" : "<font color='red'>OFF</font>"] by [key_name(usr)].", "gravity")
set_power()
return TOPIC_REFRESH
switch(action)
if("gentoggle")
breaker = !breaker
investigate_log("was toggled [breaker ? "<font color='green'>ON</font>" : "<font color='red'>OFF</font>"] by [key_name(usr)].", "gravity")
set_power()
return TOPIC_REFRESH
// Power and Icon States
+65 -75
View File
@@ -7,6 +7,7 @@
density = 1
anchored = 0
use_power = USE_POWER_OFF
interact_offline = TRUE
var/active = 0
var/power_gen = 5000
@@ -28,13 +29,22 @@
/obj/machinery/power/port_gen/proc/handleInactive()
return
/obj/machinery/power/port_gen/proc/TogglePower()
if(active)
active = FALSE
icon_state = "[initial(icon_state)]"
// soundloop.stop()
else if(HasFuel())
active = TRUE
icon_state = "[initial(icon_state)]on"
// soundloop.start()
/obj/machinery/power/port_gen/process()
if(active && HasFuel() && !IsBroken() && anchored && powernet)
add_avail(power_gen * power_output)
UseFuel()
src.updateDialog()
else
active = 0
active = FALSE
icon_state = initial(icon_state)
handleInactive()
@@ -121,7 +131,7 @@
return ..()
/obj/machinery/power/port_gen/pacman/dismantle()
while ( sheets > 0 )
while( sheets > 0 )
DropFuel()
return ..()
@@ -212,16 +222,16 @@
/obj/machinery/power/port_gen/pacman/handleInactive()
var/cooling_temperature = 20
var/datum/gas_mixture/environment = loc.return_air()
if (environment)
if(environment)
var/ratio = min(environment.return_pressure()/ONE_ATMOSPHERE, 1)
var/ambient = environment.temperature - T20C
cooling_temperature += ambient*ratio
if (temperature > cooling_temperature)
if(temperature > cooling_temperature)
var/temp_loss = (temperature - cooling_temperature)/TEMPERATURE_DIVISOR
temp_loss = between(2, round(temp_loss, 1), TEMPERATURE_CHANGE_MAX)
temperature = max(temperature - temp_loss, cooling_temperature)
src.updateDialog()
updateDialog()
if(overheating)
overheating--
@@ -287,97 +297,77 @@
..()
if (!anchored)
return
ui_interact(user)
tgui_interact(user)
/obj/machinery/power/port_gen/pacman/attack_ai(mob/user as mob)
ui_interact(user)
tgui_interact(user)
/obj/machinery/power/port_gen/pacman/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/obj/machinery/power/port_gen/tgui_status(mob/user, datum/tgui_state/state)
if(IsBroken())
return
return STATUS_CLOSE
return ..()
/obj/machinery/power/port_gen/pacman/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "PortableGenerator", name)
ui.open()
/obj/machinery/power/port_gen/pacman/tgui_data(mob/user)
var/list/data = list()
var/data[0]
data["active"] = active
if(istype(user, /mob/living/silicon/ai))
data["is_ai"] = 1
data["is_ai"] = TRUE
else if(istype(user, /mob/living/silicon/robot) && !Adjacent(user))
data["is_ai"] = 1
data["is_ai"] = TRUE
else
data["is_ai"] = 0
data["output_set"] = power_output
data["output_max"] = max_power_output
data["output_safe"] = max_safe_output
data["output_watts"] = power_output * power_gen
data["temperature_current"] = src.temperature
data["temperature_max"] = src.max_temperature
data["temperature_overheat"] = overheating
// 1 sheet = 1000cm3?
data["is_ai"] = FALSE
data["sheet_name"] = capitalize(sheet_name)
data["fuel_stored"] = round((sheets * 1000) + (sheet_left * 1000))
data["fuel_capacity"] = round(max_sheets * 1000, 0.1)
data["fuel_usage"] = active ? round((power_output / time_per_sheet) * 1000) : 0
data["fuel_type"] = sheet_name
data["anchored"] = anchored
data["connected"] = (powernet == null ? 0 : 1)
data["ready_to_boot"] = anchored && HasFuel()
data["power_generated"] = DisplayPower(power_gen)
data["power_output"] = DisplayPower(power_gen * power_output)
data["unsafe_output"] = power_output > max_safe_output
data["power_available"] = (powernet == null ? 0 : DisplayPower(avail()))
data["temperature_current"] = temperature
data["temperature_max"] = max_temperature
data["temperature_overheat"] = overheating
// 1 sheet = 1000cm3?
return data
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "pacman.tmpl", src.name, 500, 560)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/*
/obj/machinery/power/port_gen/pacman/interact(mob/user)
if (get_dist(src, user) > 1 )
if (!istype(user, /mob/living/silicon/ai))
user.unset_machine()
user << browse(null, "window=port_gen"
return
user.set_machine(src)
var/dat = text("<b>[name]</b><br>")
if (active)
dat += text("Generator: <A href='?src=\ref[src];action=disable'>On</A><br>")
else
dat += text("Generator: <A href='?src=\ref[src];action=enable'>Off</A><br>")
dat += text("[capitalize(sheet_name)]: [sheets] - <A href='?src=\ref[src];action=eject'>Eject</A><br>")
var/stack_percent = round(sheet_left * 100, 1)
dat += text("Current stack: [stack_percent]% <br>")
dat += text("Power output: <A href='?src=\ref[src];action=lower_power'>-</A> [power_gen * power_output] Watts<A href='?src=\ref[src];action=higher_power'>+</A><br>")
dat += text("Power current: [(powernet == null ? "Unconnected" : "[avail()]")]<br>")
var/tempstr = "Temperature: [temperature]&deg;C<br>"
dat += (overheating)? "<span class='danger'>[tempstr]</span>" : tempstr
dat += "<br><A href='?src=\ref[src];action=close'>Close</A>"
user << browse("[dat]", "window=port_gen")
onclose(user, "port_gen")
*/
/obj/machinery/power/port_gen/pacman/Topic(href, href_list)
/obj/machinery/power/port_gen/pacman/tgui_act(action, params)
if(..())
return
src.add_fingerprint(usr)
if(href_list["action"])
if(href_list["action"] == "enable")
if(!active && HasFuel() && !IsBroken())
active = 1
icon_state = "[initial(icon_state)]on" //VOREStation Edit
if(href_list["action"] == "disable")
if (active)
active = 0
icon_state = initial(icon_state) //VOREStation Edit
if(href_list["action"] == "eject")
add_fingerprint(usr)
switch(action)
if("toggle_power")
TogglePower()
. = TRUE
if("eject")
if(!active)
DropFuel()
if(href_list["action"] == "lower_power")
if (power_output > 1)
. = TRUE
if("lower_power")
if(power_output > 1)
power_output--
if (href_list["action"] == "higher_power")
if (power_output < max_power_output || (emagged && power_output < round(max_power_output*2.5)))
. = TRUE
if("higher_power")
if(power_output < max_power_output || (emagged && power_output < round(max_power_output * 2.5)))
power_output++
. = TRUE
/obj/machinery/power/port_gen/pacman/super
name = "S.U.P.E.R.P.A.C.M.A.N.-type Portable Generator"
+3 -1
View File
@@ -5,6 +5,7 @@
var/load = 0 // the current load on the powernet, increased by each machine at processing
var/newavail = 0 // what available power was gathered last tick, then becomes...
var/avail = 0 //...the current available power in the powernet
var/viewavail = 0 // the availability as it appears on the power console (gradually updated)
var/viewload = 0 // the load as it appears on the power console (gradually updated)
var/number = 0 // Unused //TODEL
@@ -134,7 +135,8 @@
S.restore(perc)
//updates the viewed load (as seen on power computers)
viewload = round(load)
viewavail = round(0.8 * viewavail + 0.2 * avail)
viewload = round(0.8 * viewload + 0.2 * load)
//reset the powernet
load = 0
+71 -2
View File
@@ -19,12 +19,22 @@
var/name_tag = "#UNKN#" // ID tag displayed in list of powernet sensors. Each sensor should have it's own tag!
var/long_range = 0 // If 1, sensor reading will show on all computers, regardless of Zlevel
var/list/history = list()
var/record_size = 60
var/record_interval = 50
var/next_record = 0
var/is_secret_monitor = FALSE
// Proc: New()
// Parameters: None
// Description: Automatically assigns name according to ID tag.
/obj/machinery/power/sensor/New()
..()
auto_set_name()
/obj/machinery/power/sensor/Initialize()
. = ..()
history["supply"] = list()
history["demand"] = list()
// Proc: auto_set_name()
// Parameters: None
@@ -38,6 +48,8 @@
for(var/obj/machinery/computer/power_monitor/PM in machines)
if(PM.power_monitor)
PM.power_monitor.refresh_sensors()
history.Cut()
history = null
// Proc: check_grid_warning()
// Parameters: None
@@ -51,10 +63,67 @@
// Proc: process()
// Parameters: None
// Description: This has to be here because we need sensors to remain in Machines list.
// Description: This tracks historical usage, for TGUI power monitors
/obj/machinery/power/sensor/process()
if(!powernet)
use_power = USE_POWER_IDLE
connect_to_network()
else
use_power = USE_POWER_ACTIVE
record()
return 1
// This tracks historical usage, for TGUI power monitors
/obj/machinery/power/sensor/proc/record()
if(world.time >= next_record)
next_record = world.time + record_interval
var/datum/powernet/connected_powernet = powernet
var/list/supply = history["supply"]
if(connected_powernet)
supply += connected_powernet.viewavail
if(supply.len > record_size)
supply.Cut(1, 2)
var/list/demand = history["demand"]
if(connected_powernet)
demand += connected_powernet.viewload
if(demand.len > record_size)
demand.Cut(1, 2)
/obj/machinery/power/sensor/tgui_data()
var/list/data = list()
data["name"] = name_tag
data["stored"] = record_size
data["interval"] = record_interval / 10
data["attached"] = !!powernet
data["history"] = history
data["areas"] = list()
if(powernet)
for(var/obj/machinery/power/terminal/term in powernet.nodes)
if(istype(term.master, /obj/machinery/power/apc))
var/obj/machinery/power/apc/A = term.master
if(istype(A))
var/cell_charge
if(!A.cell)
cell_charge = 0
else
cell_charge = A.cell.percent()
data["areas"] += list(list(
"name" = A.area.name,
"charge" = cell_charge,
"load" = DisplayPower(A.lastused_total),
"charging" = A.charging,
"eqp" = A.equipment,
"lgt" = A.lighting,
"env" = A.environ,
))
return data
// Proc: reading_to_text()
// Parameters: 1 (amount - Power in Watts to be converted to W, kW or MW)
// Description: Helper proc that converts reading in Watts to kW or MW (returns string version of amount parameter)
@@ -178,7 +247,7 @@
APC_entry["total_load"] = reading_to_text(A.lastused_total)
// Hopefully removes those goddamn \improper s which are screwing up the UI
var/N = A.area.name
if(findtext(N, "ÿ"))
if(findtext(N, ""))
N = copytext(N, 3)
APC_entry["name"] = N
// Add data into main list of APC data.
@@ -18,7 +18,7 @@
use_power = USE_POWER_IDLE
idle_power_usage = 300
active_power_usage = 300
var/datum/nano_module/power_monitor/power_monitor
var/datum/tgui_module/power_monitor/power_monitor
// Checks the sensors for alerts. If change (alerts cleared or detected) occurs, calls for icon update.
/obj/machinery/computer/power_monitor/process()
@@ -47,12 +47,11 @@
if(stat & (BROKEN|NOPOWER))
return
ui_interact(user)
tgui_interact(user)
// Uses dark magic to operate the NanoUI of this computer.
/obj/machinery/computer/power_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
power_monitor.ui_interact(user, ui_key, ui, force_open)
/obj/machinery/computer/power_monitor/tgui_interact(mob/user, var/datum/tgui/ui = null)
power_monitor.tgui_interact(user, ui)
// Verifies if any warnings were registered by connected sensors.
/obj/machinery/computer/power_monitor/proc/check_warnings()
@@ -36,7 +36,7 @@
/obj/machinery/particle_accelerator/control_box/attack_hand(mob/user as mob)
if(construction_state >= 3)
interact(user)
tgui_interact(user)
else if(construction_state == 2) // Wires exposed
wires.Interact(user)
@@ -77,36 +77,6 @@
else
icon_state = "[reference]c"
/obj/machinery/particle_accelerator/control_box/Topic(href, href_list)
..()
//Ignore input if we are broken, !silicon guy cant touch us, or nonai controlling from super far away
if(stat & (BROKEN|NOPOWER) || (get_dist(src, usr) > 1 && !istype(usr, /mob/living/silicon)) || (get_dist(src, usr) > 8 && !istype(usr, /mob/living/silicon/ai)))
usr.unset_machine()
usr << browse(null, "window=pacontrol")
return
if( href_list["close"] )
usr << browse(null, "window=pacontrol")
usr.unset_machine()
return
if(href_list["togglep"])
if(!wires.is_cut(WIRE_PARTICLE_POWER))
toggle_power()
else if(href_list["scan"])
part_scan()
else if(href_list["strengthup"])
if(!wires.is_cut(WIRE_PARTICLE_STRENGTH))
add_strength()
else if(href_list["strengthdown"])
if(!wires.is_cut(WIRE_PARTICLE_STRENGTH))
remove_strength()
updateDialog()
update_icon()
/obj/machinery/particle_accelerator/control_box/proc/strength_change()
for(var/obj/structure/particle_accelerator/part in connected_parts)
part.strength = strength
@@ -230,33 +200,54 @@
part.update_icon()
return 1
/obj/machinery/particle_accelerator/control_box/proc/is_interactive(mob/user)
if(!interface_control)
to_chat(user, "<span class='alert'>ERROR: Request timed out. Check wire contacts.</span>")
return FALSE
if(construction_state != 3)
return FALSE
return TRUE
/obj/machinery/particle_accelerator/control_box/interact(mob/user)
if((get_dist(src, user) > 1) || (stat & (BROKEN|NOPOWER)))
if(!istype(user, /mob/living/silicon))
user.unset_machine()
user << browse(null, "window=pacontrol")
return
user.set_machine(src)
/obj/machinery/particle_accelerator/control_box/tgui_status(mob/user)
if(is_interactive(user))
return ..()
return STATUS_CLOSE
var/dat = ""
dat += "Particle Accelerator Control Panel<BR>"
dat += "<A href='?src=\ref[src];close=1'>Close</A><BR><BR>"
dat += "Status:<BR>"
if(!assembled)
dat += "Unable to detect all parts!<BR>"
dat += "<A href='?src=\ref[src];scan=1'>Run Scan</A><BR><BR>"
else
dat += "All parts in place.<BR><BR>"
dat += "Power:"
if(active)
dat += "On<BR>"
else
dat += "Off <BR>"
dat += "<A href='?src=\ref[src];togglep=1'>Toggle Power</A><BR><BR>"
dat += "Particle Strength: [src.strength] "
dat += "<A href='?src=\ref[src];strengthdown=1'>--</A>|<A href='?src=\ref[src];strengthup=1'>++</A><BR><BR>"
/obj/machinery/particle_accelerator/control_box/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ParticleAccelerator", name)
ui.open()
user << browse(dat, "window=pacontrol;size=420x500")
onclose(user, "pacontrol")
return
/obj/machinery/particle_accelerator/control_box/tgui_data(mob/user)
var/list/data = list()
data["assembled"] = assembled
data["power"] = active
data["strength"] = strength
return data
/obj/machinery/particle_accelerator/control_box/tgui_act(action, params)
if(..())
return
switch(action)
if("power")
if(wires.is_cut(WIRE_POWER))
return
toggle_power()
. = TRUE
if("scan")
part_scan()
. = TRUE
if("add_strength")
if(wires.is_cut(WIRE_PARTICLE_STRENGTH))
return
add_strength()
. = TRUE
if("remove_strength")
if(wires.is_cut(WIRE_PARTICLE_STRENGTH))
return
remove_strength()
. = TRUE
update_icon()
+72 -66
View File
@@ -263,11 +263,11 @@ GLOBAL_LIST_EMPTY(smeses)
/obj/machinery/power/smes/attack_ai(mob/user)
add_hiddenprint(user)
ui_interact(user)
tgui_interact(user)
/obj/machinery/power/smes/attack_hand(mob/user)
add_fingerprint(user)
ui_interact(user)
tgui_interact(user)
/obj/machinery/power/smes/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
@@ -344,78 +344,84 @@ GLOBAL_LIST_EMPTY(smeses)
return FALSE
return TRUE
/obj/machinery/power/smes/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
if(stat & BROKEN)
return
// this is the data which will be sent to the ui
var/data[0]
data["nameTag"] = name_tag
data["storedCapacity"] = round(100.0*charge/capacity, 0.1)
data["storedCapacityAbs"] = round(charge/(1000*60), 0.1)
data["storedCapacityMax"] = round(capacity/(1000*60))
data["charging"] = inputting
data["chargeMode"] = input_attempt
data["chargeLevel"] = round(input_level/1000, 0.1)
data["chargeMax"] = round(input_level_max/1000)
data["chargeLoad"] = round(input_available/1000, 0.1)
data["outputOnline"] = output_attempt
data["outputLevel"] = round(output_level/1000, 0.1)
data["outputMax"] = round(output_level_max/1000)
data["outputLoad"] = round(output_used/1000, 0.1)
data["outputting"] = outputting
// 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)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
ui = new(user, src, ui_key, "smes.tmpl", "SMES Unit", 540, 380)
// when the ui is first opened this is the data it will use
ui.set_initial_data(data)
// open the new ui window
/obj/machinery/power/smes/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Smes", name)
ui.open()
// auto update every Master Controller tick
ui.set_auto_update(1)
/obj/machinery/power/smes/tgui_data()
var/list/data = list(
"capacity" = capacity,
"capacityPercent" = round(100*charge/capacity, 0.1),
"charge" = charge,
"inputAttempt" = input_attempt,
"inputting" = inputting,
"inputLevel" = input_level,
"inputLevel_text" = DisplayPower(input_level),
"inputLevelMax" = input_level_max,
"inputAvailable" = input_available,
"outputAttempt" = output_attempt,
"outputting" = outputting,
"outputLevel" = output_level,
"outputLevel_text" = DisplayPower(output_level),
"outputLevelMax" = output_level_max,
"outputUsed" = output_used,
)
return data
/obj/machinery/power/smes/proc/Percentage()
if(!capacity)
return 0
return round(100.0*charge/capacity, 0.1)
/obj/machinery/power/smes/Topic(href, href_list)
if(..())
return 1
if( href_list["cmode"] )
inputting(!input_attempt)
update_icon()
return 1
else if( href_list["online"] )
outputting(!output_attempt)
update_icon()
return 1
else if( href_list["input"] )
switch( href_list["input"] )
if("min")
input_level = 0
if("max")
input_level = input_level_max
if("set")
input_level = (input(usr, "Enter new input level (0-[input_level_max/1000] kW)", "SMES Input Power Control", input_level/1000) as num) * 1000
input_level = max(0, min(input_level_max, input_level)) // clamp to range
return 1
else if( href_list["output"] )
switch( href_list["output"] )
if("min")
output_level = 0
if("max")
output_level = output_level_max
if("set")
output_level = (input(usr, "Enter new output level (0-[output_level_max/1000] kW)", "SMES Output Power Control", output_level/1000) as num) * 1000
output_level = max(0, min(output_level_max, output_level)) // clamp to range
return 1
/obj/machinery/power/smes/tgui_act(action, params)
if(..())
return TRUE
switch(action)
if("tryinput")
inputting(!input_attempt)
update_icon()
. = TRUE
if("tryoutput")
outputting(!output_attempt)
update_icon()
. = TRUE
if("input")
var/target = params["target"]
var/adjust = text2num(params["adjust"])
if(target == "min")
target = 0
. = TRUE
else if(target == "max")
target = input_level_max
. = TRUE
else if(adjust)
target = input_level + adjust
. = TRUE
else if(text2num(target) != null)
target = text2num(target)
. = TRUE
if(.)
input_level = clamp(target, 0, input_level_max)
if("output")
var/target = params["target"]
var/adjust = text2num(params["adjust"])
if(target == "min")
target = 0
. = TRUE
else if(target == "max")
target = output_level_max
. = TRUE
else if(adjust)
target = output_level + adjust
. = TRUE
else if(text2num(target) != null)
target = text2num(target)
. = TRUE
if(.)
output_level = clamp(target, 0, output_level_max)
/obj/machinery/power/smes/proc/inputting(var/do_input)
input_attempt = do_input
+1 -1
View File
@@ -84,7 +84,7 @@
/obj/machinery/power/smes/buildable/Destroy()
qdel(wires)
wires = null
for(var/datum/nano_module/rcon/R in world)
for(var/datum/tgui_module/rcon/R in world)
R.FindDevices()
return ..()
+60 -71
View File
@@ -399,38 +399,32 @@ GLOBAL_LIST_EMPTY(solars_list)
return
/obj/machinery/power/solar_control/attack_hand(mob/user)
if(!..())
interact(user)
if(..())
return TRUE
tgui_interact(user)
/obj/machinery/power/solar_control/interact(mob/user)
/obj/machinery/power/solar_control/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "SolarControl", name)
ui.open()
var/t = "<B><span class='highlight'>Generated power</span></B> : [round(lastgen)] W<BR>"
t += "<B><span class='highlight'>Star Orientation</span></B>: [SSsun.sun.angle]&deg ([angle2text(SSsun.sun.angle)])<BR>"
t += "<B><span class='highlight'>Array Orientation</span></B>: [rate_control(src,"cdir","[cdir]&deg",1,15)] ([angle2text(cdir)])<BR>"
t += "<B><span class='highlight'>Tracking:</span></B><div class='statusDisplay'>"
switch(track)
if(0)
t += "<span class='linkOn'>Off</span> <A href='?src=\ref[src];track=1'>Timed</A> <A href='?src=\ref[src];track=2'>Auto</A><BR>"
if(1)
t += "<A href='?src=\ref[src];track=0'>Off</A> <span class='linkOn'>Timed</span> <A href='?src=\ref[src];track=2'>Auto</A><BR>"
if(2)
t += "<A href='?src=\ref[src];track=0'>Off</A> <A href='?src=\ref[src];track=1'>Timed</A> <span class='linkOn'>Auto</span><BR>"
/obj/machinery/power/solar_control/tgui_data()
var/data = list()
t += "Tracking Rate: [rate_control(src,"tdir","[trackrate] deg/h ([trackrate<0 ? "CCW" : "CW"])",1,30,180)]</div><BR>"
data["generated"] = round(lastgen)
data["generated_ratio"] = data["generated"] / round(max(connected_panels.len, 1) * GLOB.solar_gen_rate)
t += "<B><span class='highlight'>Connected devices:</span></B><div class='statusDisplay'>"
data["sun_angle"] = SSsun.sun.angle
data["array_angle"] = cdir
data["rotation_rate"] = trackrate
data["max_rotation_rate"] = 7200
data["tracking_state"] = track
t += "<A href='?src=\ref[src];search_connected=1'>Search for devices</A><BR>"
t += "Solar panels : [connected_panels.len] connected<BR>"
t += "Solar tracker : [connected_tracker ? "<span class='good'>Found</span>" : "<span class='bad'>Not found</span>"]</div><BR>"
data["connected_panels"] = connected_panels.len
data["connected_tracker"] = (connected_tracker ? TRUE : FALSE)
t += "<A href='?src=\ref[src];close=1'>Close</A>"
var/datum/browser/popup = new(user, "solar", name)
popup.set_content(t)
popup.open()
return
return data
/obj/machinery/power/solar_control/attackby(obj/item/I, user as mob)
if(I.is_screwdriver())
@@ -481,51 +475,52 @@ GLOBAL_LIST_EMPTY(solars_list)
updateDialog()
/obj/machinery/power/solar_control/Topic(href, href_list)
/obj/machinery/power/solar_control/tgui_act(action, params)
if(..())
usr << browse(null, "window=solcon")
usr.unset_machine()
return 0
if(href_list["close"] )
usr << browse(null, "window=solcon")
usr.unset_machine()
return 0
return TRUE
if(href_list["rate control"])
if(href_list["cdir"])
src.cdir = dd_range(0,359,(360+src.cdir+text2num(href_list["cdir"]))%360)
src.targetdir = src.cdir
if(track == 2) //manual update, so losing auto-tracking
track = 0
spawn(1)
switch(action)
if("azimuth")
var/adjust = text2num(params["adjust"])
var/value = text2num(params["value"])
if(adjust)
value = cdir + adjust
if(value != null)
cdir = value
set_panels(cdir)
if(href_list["tdir"])
src.trackrate = dd_range(-7200,7200,src.trackrate+text2num(href_list["tdir"]))
if(src.trackrate) nexttime = world.time + 36000/abs(trackrate)
return TRUE
return FALSE
if("azimuth_rate")
var/adjust = text2num(params["adjust"])
var/value = text2num(params["value"])
if(adjust)
value = trackrate + adjust
if(value != null)
trackrate = round(clamp(value, -7200, 7200), 0.01)
if(trackrate)
nexttime = world.time + 36000 / abs(trackrate)
return TRUE
return TRUE
if("tracking")
var/mode = text2num(params["mode"])
track = mode
if(track == 2)
if(connected_tracker)
connected_tracker.set_angle(SSsun.sun.angle)
set_panels(cdir)
else if(track == 1) //begin manual tracking
targetdir = cdir
if(trackrate)
nexttime = world.time + 36000/abs(trackrate)
set_panels(targetdir)
return TRUE
if(href_list["track"])
track = text2num(href_list["track"])
if(track == 2)
if(connected_tracker)
connected_tracker.set_angle(SSsun.sun.angle)
set_panels(cdir)
else if (track == 1) //begin manual tracking
src.targetdir = src.cdir
if(src.trackrate) nexttime = world.time + 36000/abs(trackrate)
set_panels(targetdir)
if(href_list["search_connected"])
src.search_for_connected()
if(connected_tracker && track == 2)
connected_tracker.set_angle(SSsun.sun.angle)
src.set_panels(cdir)
interact(usr)
return 1
if("refresh")
search_for_connected()
return TRUE
//rotates the panel to the passed angle
/obj/machinery/power/solar_control/proc/set_panels(var/cdir)
for(var/obj/machinery/power/solar/S in connected_panels)
S.adir = cdir //instantly rotates the panel
S.occlusion()//and
@@ -547,7 +542,7 @@ GLOBAL_LIST_EMPTY(solars_list)
/obj/machinery/power/solar_control/ex_act(severity)
switch(severity)
if(1.0)
//SN src = null
//SN = null
qdel(src)
return
if(2.0)
@@ -565,9 +560,3 @@ GLOBAL_LIST_EMPTY(solars_list)
/obj/item/weapon/paper/solar
name = "paper- 'Going green! Setup your own solar array instructions.'"
info = "<h1>Welcome</h1><p>At greencorps we love the environment, and space. With this package you are able to help mother nature and produce energy without any usage of fossil fuel or phoron! Singularity energy is dangerous while solar energy is safe, which is why it's better. Now here is how you setup your own solar array.</p><p>You can make a solar panel by wrenching the solar assembly onto a cable node. Adding a glass panel, reinforced or regular glass will do, will finish the construction of your solar panel. It is that easy!</p><p>Now after setting up 19 more of these solar panels you will want to create a solar tracker to keep track of our mother nature's gift, the SSsun.sun. These are the same steps as before except you insert the tracker equipment circuit into the assembly before performing the final step of adding the glass. You now have a tracker! Now the last step is to add a computer to calculate the SSsun.sun's movements and to send commands to the solar panels to change direction with the SSsun.sun. Setting up the solar computer is the same as setting up any computer, so you should have no trouble in doing that. You do need to put a wire node under the computer, and the wire needs to be connected to the tracker.</p><p>Congratulations, you should have a working solar array. If you are having trouble, here are some tips. Make sure all solar equipment are on a cable node, even the computer. You can always deconstruct your creations if you make a mistake.</p><p>That's all to it, be safe, be green!</p>"
/proc/rate_control(var/S, var/V, var/C, var/Min=1, var/Max=5, var/Limit=null) //How not to name vars
var/href = "<A href='?src=\ref[S];rate control=1;[V]"
var/rate = "[href]=-[Max]'>-</A>[href]=-[Min]'>-</A> [(C?C : 0)] [href]=[Min]'>+</A>[href]=[Max]'>+</A>"
if(Limit) return "[href]=-[Limit]'>-</A>"+rate+"[href]=[Limit]'>+</A>"
return rate
+11 -10
View File
@@ -390,11 +390,11 @@
if(Adjacent(user))
return attack_hand(user)
else
ui_interact(user)
tgui_interact(user)
return
/obj/machinery/power/supermatter/attack_ai(mob/user as mob)
ui_interact(user)
tgui_interact(user)
/obj/machinery/power/supermatter/attack_hand(mob/user as mob)
var/datum/gender/TU = gender_datums[user.get_visible_gender()]
@@ -404,9 +404,15 @@
Consume(user)
/obj/machinery/power/supermatter/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "AiSupermatter", name)
ui.open()
// This is purely informational UI that may be accessed by AIs or robots
/obj/machinery/power/supermatter/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
/obj/machinery/power/supermatter/tgui_data(mob/user)
var/list/data = list()
data["integrity_percentage"] = round(get_integrity())
var/datum/gas_mixture/env = null
@@ -421,12 +427,7 @@
data["ambient_pressure"] = round(env.return_pressure())
data["detonating"] = grav_pulling
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "supermatter_crystal.tmpl", "Supermatter Crystal", 500, 300)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
return data
/obj/machinery/power/supermatter/attackby(obj/item/weapon/W as obj, mob/living/user as mob)
+36 -9
View File
@@ -7,6 +7,7 @@
#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
@@ -245,7 +246,18 @@
if("create_bottle")
if(condi || !reagents.total_volume)
return
tgui_modal_input(src, id, "Please name your bottle:", null, arguments, reagents.get_master_reagent_name(), MAX_CUSTOM_NAME_LEN)
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()] ([amount_per_bottle]u)"
var/bottles_text = num == 1 ? "new bottle" : "[num] new bottles"
tgui_modal_input(src, id, "Please name your [bottles_text]:", 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)
@@ -357,16 +369,28 @@
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/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, 60)
P.update_icon()
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)
@@ -393,7 +417,9 @@
mode = !mode
if("ejectp")
if(loaded_pill_bottle)
loaded_pill_bottle.forceMove(loc)
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)
@@ -842,4 +868,5 @@
#undef MAX_MULTI_AMOUNT
#undef MAX_UNITS_PER_PILL
#undef MAX_UNITS_PER_PATCH
#undef MAX_UNITS_PER_BOTTLE
#undef MAX_CUSTOM_NAME_LEN
@@ -400,6 +400,49 @@
M.heal_organ_damage(30 * removed, 30 * removed * chem_effective)
M.adjustToxLoss(-30 * removed * chem_effective)
/datum/reagent/mortiferin
name = "Mortiferin"
id = "mortiferin"
description = "A liquid compound based upon those used in cloning. Utilized in cases of toxic shock. May cause liver damage."
taste_description = "meat"
reagent_state = LIQUID
color = "#6b4de3"
metabolism = REM * 0.5
mrate_static = TRUE
scannable = 1
/datum/reagent/mortiferin/on_mob_life(var/mob/living/carbon/M, var/alien, var/datum/reagents/metabolism/location)
if(M.stat == DEAD && M.has_modifier_of_type(/datum/modifier/bloodpump_corpse))
affects_dead = TRUE
else
affects_dead = FALSE
. = ..(M, alien, location)
/datum/reagent/mortiferin/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(M.bodytemperature < (T0C - 10) || (M.stat == DEAD && M.has_modifier_of_type(/datum/modifier/bloodpump_corpse)))
var/chem_effective = 1 * M.species.chem_strength_heal
if(alien == IS_SLIME)
if(prob(10))
to_chat(M, "<span class='danger'>It's so cold. Something causes your cellular mass to solidify sporadically, resulting in uncontrollable twitching.</span>")
chem_effective = 0.5
M.Weaken(10)
M.silent = max(M.silent, 10)
M.make_jittery(4)
if(M.stat != DEAD)
M.adjustCloneLoss(-5 * removed * chem_effective)
M.adjustOxyLoss(-10 * removed * chem_effective)
M.adjustToxLoss(-20 * removed * chem_effective)
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/obj/item/organ/internal/liver/L = H.internal_organs_by_name[O_LIVER]
if(istype(L) && prob(5))
if(L.robotic >= ORGAN_ROBOT)
return
L.take_damage(rand(1,3) * removed)
/datum/reagent/necroxadone
name = "Necroxadone"
id = "necroxadone"
@@ -410,18 +453,11 @@
metabolism = REM * 0.5
mrate_static = TRUE
scannable = 1
/datum/reagent/necroxadone/on_mob_life(var/mob/living/carbon/M, var/alien, var/datum/reagents/metabolism/location)
if(M.stat == DEAD && M.has_modifier_of_type(/datum/modifier/bloodpump_corpse))
affects_dead = TRUE
else
affects_dead = FALSE
. = ..(M, alien, location)
affects_dead = TRUE
/datum/reagent/necroxadone/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
var/chem_effective = 1 * M.species.chem_strength_heal
if(M.bodytemperature < 170 || (M.stat == DEAD && M.has_modifier_of_type(/datum/modifier/bloodpump_corpse)))
var/chem_effective = 1 * M.species.chem_strength_heal
if(alien == IS_SLIME)
if(prob(10))
to_chat(M, "<span class='danger'>It's so cold. Something causes your cellular mass to harden sporadically, resulting in seizure-like twitching.</span>")
@@ -433,6 +469,12 @@
M.adjustCloneLoss(-5 * removed * chem_effective)
M.adjustOxyLoss(-20 * removed * chem_effective)
M.adjustToxLoss(-40 * removed * chem_effective)
M.adjustCloneLoss(-15 * removed * chem_effective)
else
M.adjustToxLoss(-25 * removed * chem_effective)
M.adjustOxyLoss(-10 * removed * chem_effective)
M.adjustCloneLoss(-7 * removed * chem_effective)
/* Painkillers */
@@ -428,6 +428,14 @@
catalysts = list("phoron" = 5)
result_amount = 2
/datum/chemical_reaction/mortiferin
name = "Mortiferin"
id = "mortiferin"
result = "mortiferin"
required_reagents = list("cryptobiolin" = 1, "clonexadone" = 1, "corophizine" = 1)
result_amount = 2
catalysts = list("phoron" = 5)
/datum/chemical_reaction/spaceacillin
name = "Spaceacillin"
id = "spaceacillin"
+3 -3
View File
@@ -569,9 +569,9 @@
materials = list(DEFAULT_WALL_MATERIAL = 7500, "gold" = 750, "silver" = 1500, "glass" = 3750)
build_path = /obj/item/mecha_parts/mecha_equipment/repair_droid
/datum/design/item/mecha/shield_drone
name = "Shield Drone"
desc = "Manual shield drone. Deploys a large, familiar, and rectangular shield in one direction at a time."
/datum/design/item/mecha/combat_shield
name = "linear combat shield"
desc = "Linear shield projector. Deploys a large, familiar, and rectangular shield in one direction at a time."
id = "mech_shield_droid"
req_tech = list(TECH_PHORON = 3, TECH_MAGNET = 6, TECH_ILLEGAL = 4)
materials = list(DEFAULT_WALL_MATERIAL = 8000, "gold" = 2000, "silver" = 3000, "phoron" = 5000, "glass" = 3750)
+150 -96
View File
@@ -1,6 +1,12 @@
// Little define makes it cleaner to read the tripple color values out of mobs.
#define MOB_HEX_COLOR(M, V) "#[num2hex(M.r_##V, 2)][num2hex(M.g_##V, 2)][num2hex(M.b_##V, 2)]"
#define MENU_MAIN "Main"
#define MENU_BODYRECORDS "Body Records"
#define MENU_STOCKRECORDS "Stock Records"
#define MENU_SPECIFICRECORD "Specific Record"
#define MENU_OOCNOTES "OOC Notes"
/obj/machinery/computer/transhuman/designer
name = "body design console"
catalogue_data = list(/datum/category_item/catalogue/information/organization/khi,
@@ -12,16 +18,41 @@
circuit = /obj/item/weapon/circuitboard/body_designer
req_access = list(access_medical) // Used for loading people's designs
var/temp = ""
var/menu = 1 //Which menu screen to display
var/menu = MENU_MAIN //Which menu screen to display
var/datum/transhuman/body_record/active_br = null
var/icon/preview_icon = null
//Mob preview
var/map_name
var/obj/screen/south_preview = null
var/obj/screen/east_preview = null
var/obj/screen/west_preview = null
// Mannequins are somewhat expensive to create, so cache it
var/mob/living/carbon/human/dummy/mannequin/mannequin = null
var/obj/item/weapon/disk/body_record/disk = null
/obj/machinery/computer/transhuman/designer/Initialize()
. = ..()
map_name = "transhuman_designer_[REF(src)]_map"
south_preview = new
south_preview.name = ""
south_preview.assigned_map = map_name
south_preview.del_on_map_removal = FALSE
south_preview.screen_loc = "[map_name]:1,1"
east_preview = new
east_preview.name = ""
east_preview.assigned_map = map_name
east_preview.del_on_map_removal = FALSE
east_preview.screen_loc = "[map_name]:2,1"
west_preview = new
west_preview.name = ""
west_preview.assigned_map = map_name
west_preview.del_on_map_removal = FALSE
west_preview.screen_loc = "[map_name]:0,1"
/obj/machinery/computer/transhuman/designer/Destroy()
active_br = null
preview_icon = null
mannequin = null
disk = null
return ..()
@@ -50,15 +81,24 @@
add_fingerprint(user)
if(inoperable())
return
ui_interact(user)
tgui_interact(user)
/obj/machinery/computer/transhuman/designer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
// log_debug("designer.ui_interact([user], force_open = [force_open])")
user.set_machine(src)
/obj/machinery/computer/transhuman/designer/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
give_client_previews(user.client)
ui = new(user, src, "BodyDesigner", name)
ui.open()
var/data[0]
/obj/machinery/computer/transhuman/designer/tgui_static_data(mob/user)
var/list/data = ..()
data["mapRef"] = map_name
return data
if(menu == "2")
/obj/machinery/computer/transhuman/designer/tgui_data(mob/user)
var/list/data = list()
if(menu == MENU_BODYRECORDS)
var/bodyrecords_list_ui[0]
for(var/N in SStranscore.body_scans)
var/datum/transhuman/body_record/BR = SStranscore.body_scans[N]
@@ -66,7 +106,7 @@
if(bodyrecords_list_ui.len)
data["bodyrecords"] = bodyrecords_list_ui
if(menu == "3")
if(menu == MENU_STOCKRECORDS)
var/stock_bodyrecords_list_ui[0]
for (var/N in GLOB.all_species)
var/datum/species/S = GLOB.all_species[N]
@@ -86,11 +126,6 @@
"booc" = active_br.body_oocnotes,
"styles" = list()
)
if(!preview_icon)
update_preview_icon()
force_open = 1 // Force a refresh to send the new image
data["previewIconUrl"] = "body_preview_icon.png"
user << browse_rsc(preview_icon, "body_preview_icon.png")
var/list/styles = data["activeBodyRecord"]["styles"]
var/list/temp
@@ -98,6 +133,12 @@
temp = list("styleHref" = "ear_style", "style" = "Normal")
if(mannequin.ear_style)
temp["style"] = mannequin.ear_style.name
if(mannequin.ear_style.do_colouration)
temp["color"] = MOB_HEX_COLOR(mannequin, ears)
temp["colorHref"] = "ear_color"
if(mannequin.ear_style.extra_overlay)
temp["color2"] = MOB_HEX_COLOR(mannequin, ears2)
temp["colorHref2"] = "ear_color2"
styles["Ears"] = temp
temp = list("styleHref" = "tail_style", "style" = "Normal")
@@ -106,6 +147,9 @@
if(mannequin.tail_style.do_colouration)
temp["color"] = MOB_HEX_COLOR(mannequin, tail)
temp["colorHref"] = "tail_color"
if(mannequin.tail_style.extra_overlay)
temp["color2"] = MOB_HEX_COLOR(mannequin, tail2)
temp["colorHref2"] = "tail_color2"
styles["Tail"] = temp
temp = list("styleHref" = "wing_style", "style" = "Normal")
@@ -114,6 +158,9 @@
if(mannequin.wing_style.do_colouration)
temp["color"] = MOB_HEX_COLOR(mannequin, wing)
temp["colorHref"] = "wing_color"
if(mannequin.wing_style.extra_overlay)
temp["color2"] = MOB_HEX_COLOR(mannequin, wing2)
temp["colorHref2"] = "wing_color2"
styles["Wing"] = temp
temp = list("styleHref" = "hair_style", "style" = mannequin.h_style)
@@ -143,74 +190,74 @@
data["disk"] = disk ? 1 : 0
data["diskStored"] = disk && disk.stored ? 1 : 0
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "body_designer.tmpl", "Body Design Console", 400, 600)
ui.set_initial_data(data)
ui.open()
return data
/obj/machinery/computer/transhuman/designer/Topic(href, href_list)
/obj/machinery/computer/transhuman/designer/tgui_act(action, params)
if(..())
return 1
return TRUE
else if(href_list["debug_load_my_body"])
active_br = new /datum/transhuman/body_record(usr, FALSE, FALSE)
preview_icon = null
switch(action)
if("debug_load_my_body")
active_br = new /datum/transhuman/body_record(usr, FALSE, FALSE)
update_preview_icon()
menu = MENU_SPECIFICRECORD
else if (href_list["view_brec"])
var/datum/transhuman/body_record/BR = locate(href_list["view_brec"])
if(BR && istype(BR.mydna))
if(allowed(usr) || BR.ckey == usr.ckey)
active_br = new /datum/transhuman/body_record(BR) // Load a COPY!
preview_icon = null
menu = 4
if("view_brec")
var/datum/transhuman/body_record/BR = locate(params["view_brec"])
if(BR && istype(BR.mydna))
if(allowed(usr) || BR.ckey == usr.ckey)
active_br = new /datum/transhuman/body_record(BR) // Load a COPY!
update_preview_icon()
menu = MENU_SPECIFICRECORD
else
active_br = null
temp = "Access denied: Body records are confidential."
else
active_br = null
temp = "Access denied: Body records are confidential."
else
active_br = null
temp = "ERROR: Record missing."
temp = "ERROR: Record missing."
else if(href_list["view_stock_brec"])
var/datum/species/S = GLOB.all_species[href_list["view_stock_brec"]]
if(S && (S.spawn_flags & (SPECIES_IS_WHITELISTED|SPECIES_CAN_JOIN)) == SPECIES_CAN_JOIN)
// Generate body record from species!
mannequin = new(null, S.name)
mannequin.real_name = "Stock [S.name] Body"
mannequin.name = mannequin.real_name
mannequin.dna.real_name = mannequin.real_name
active_br = new(mannequin, FALSE, FALSE)
active_br.speciesname = "Custom Sleeve"
preview_icon = null
menu = 4
else
active_br = null
temp = "ERROR: Stock Record missing."
if("view_stock_brec")
var/datum/species/S = GLOB.all_species[params["view_stock_brec"]]
if(S && (S.spawn_flags & (SPECIES_IS_WHITELISTED|SPECIES_CAN_JOIN)) == SPECIES_CAN_JOIN)
// Generate body record from species!
mannequin = new(null, S.name)
mannequin.real_name = "Stock [S.name] Body"
mannequin.name = mannequin.real_name
mannequin.dna.real_name = mannequin.real_name
active_br = new(mannequin, FALSE, FALSE)
active_br.speciesname = "Custom Sleeve"
update_preview_icon()
menu = MENU_SPECIFICRECORD
else
active_br = null
temp = "ERROR: Stock Record missing."
else if (href_list["boocnotes"])
menu = 6
if("boocnotes")
menu = MENU_OOCNOTES
else if (href_list["loadfromdisk"])
if(disk && disk.stored)
active_br = new /datum/transhuman/body_record(disk.stored) // Loads a COPY!
preview_icon = null
if("loadfromdisk")
if(disk && disk.stored)
active_br = new /datum/transhuman/body_record(disk.stored) // Loads a COPY!
update_preview_icon()
menu = MENU_SPECIFICRECORD
else if (href_list["savetodisk"])
if(disk && active_br)
disk.stored = new /datum/transhuman/body_record(active_br) // Saves a COPY!
disk.name = "[initial(disk.name)] ([active_br.mydna.name])"
if("savetodisk")
if(disk && active_br)
disk.stored = new /datum/transhuman/body_record(active_br) // Saves a COPY!
disk.name = "[initial(disk.name)] ([active_br.mydna.name])"
disk.forceMove(get_turf(src))
disk = null
if("ejectdisk")
disk.forceMove(get_turf(src))
disk = null
else if (href_list["ejectdisk"])
disk.forceMove(get_turf(src))
disk = null
else if (href_list["menu"])
menu = href_list["menu"]
temp = ""
else
OnTopic(href, href_list, usr)
if("menu")
menu = params["menu"]
temp = ""
if("href_conversion")
PrefHrefMiddleware(params, usr)
add_fingerprint(usr)
return 1 // Return 1 to refresh UI
@@ -226,24 +273,27 @@
mannequin.delete_inventory(TRUE)
update_preview_mob(mannequin)
COMPILE_OVERLAYS(mannequin)
var/mutable_appearance/MA = new(mannequin)
south_preview.appearance = MA
south_preview.dir = SOUTH
south_preview.screen_loc = "[map_name]:1,1"
south_preview.name = ""
east_preview.appearance = MA
east_preview.dir = EAST
east_preview.screen_loc = "[map_name]:2,1"
east_preview.name = ""
west_preview.appearance = MA
west_preview.dir = WEST
west_preview.screen_loc = "[map_name]:0,1"
west_preview.name = ""
preview_icon = icon('icons/effects/effects.dmi', "nothing")
preview_icon.Scale(48+32, 16+32)
/obj/machinery/computer/transhuman/designer/proc/give_client_previews(client/C)
C.register_map_obj(south_preview)
C.register_map_obj(east_preview)
C.register_map_obj(west_preview)
mannequin.dir = NORTH
var/icon/stamp = getFlatIcon(mannequin)
preview_icon.Blend(stamp, ICON_OVERLAY, 25, 17)
mannequin.dir = WEST
stamp = getFlatIcon(mannequin)
preview_icon.Blend(stamp, ICON_OVERLAY, 1, 9)
mannequin.dir = SOUTH
stamp = getFlatIcon(mannequin)
preview_icon.Blend(stamp, ICON_OVERLAY, 49, 1)
preview_icon.Scale(preview_icon.Width() * 2, preview_icon.Height() * 2) // Scaling here to prevent blurring in the browser.
return preview_icon
/obj/machinery/computer/transhuman/designer/proc/update_preview_mob(var/mob/living/carbon/human/H)
ASSERT(!QDELETED(H))
@@ -306,15 +356,15 @@
// Problem is, those procs save their data to /datum/preferences, not a body_record.
// Luckily the procs to convert from body_record to /datum/preferences and back already exist.
// Its ugly, but I think its still better than duplicating and maintaining all that code.
/obj/machinery/computer/transhuman/designer/proc/OnTopic(var/href,var/list/href_list, var/mob/user)
if(!mannequin || !preview_icon || !active_br)
/obj/machinery/computer/transhuman/designer/proc/PrefHrefMiddleware(list/params, var/mob/user)
if(!mannequin || !active_br)
return
if(href_list["size_multiplier"])
if(params["target_href"] == "size_multiplier")
var/new_size = input(user, "Choose your character's size, ranging from 25% to 200%", "Character Preference") as num|null
if(new_size && ISINRANGE(new_size,25,200))
active_br.sizemult = (new_size/100)
preview_icon = null
update_preview_icon()
return 1
// The black magic horror show begins
@@ -338,26 +388,30 @@
var/datum/category_item/player_setup_item/vore/ears/E = CG.items_by_name["Appearance"]
ASSERT(istype(E))
if(href_list["bio_gender"])
if(params["target_href"] == "bio_gender")
var/new_gender = input(user, "Choose your character's biological gender:", "Character Preference", active_br.bodygender) as null|anything in G.get_genders()
if(new_gender)
active_br.bodygender = new_gender
active_br.mydna.dna.SetUIState(DNA_UI_GENDER, new_gender!=MALE, 1)
preview_icon = null
update_preview_icon()
return 1
var/href_list = list()
href_list["src"] = "\ref[src]"
href_list["[params["target_href"]]"] = params["target_value"]
var/action = 0
action = B.OnTopic(href, href_list, user)
action = B.OnTopic(list2params(href_list), href_list, user)
if(action & TOPIC_UPDATE_PREVIEW && mannequin && active_br)
B.copy_to_mob(mannequin)
active_br.mydna.dna.ResetUIFrom(mannequin)
preview_icon = null
update_preview_icon()
return 1
action = E.OnTopic(href, href_list, user)
action = E.OnTopic(list2params(href_list), href_list, user)
if(action & TOPIC_UPDATE_PREVIEW && mannequin && active_br)
E.copy_to_mob(mannequin)
active_br.mydna.dna.ResetUIFrom(mannequin)
preview_icon = null
update_preview_icon()
return 1
// Fake subtype of preferences we can use to steal code from player_setup
+1 -1
View File
@@ -417,7 +417,7 @@ var/list/infomorph_emotions = list(
desc = "Modify the settings on your integrated radio."
if(radio)
radio.ui_interact(src,"main",null,1,conscious_state)
radio.tgui_interact(src)
else
to_chat(src, "<span class='warning'>You don't have a radio!</span>")
+36 -42
View File
@@ -18,6 +18,7 @@
use_power = USE_POWER_OFF //doesn't use APC power
var/charge_rate = 100000 //100 kW
var/obj/machinery/shield_gen/owned_gen
interact_offline = TRUE
/obj/machinery/shield_capacitor/advanced
name = "advanced shield capacitor"
@@ -67,36 +68,30 @@
/obj/machinery/shield_capacitor/attack_hand(mob/user)
if(stat & (BROKEN))
return
interact(user)
tgui_interact(user)
/obj/machinery/shield_capacitor/interact(mob/user)
if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN)) )
if (!istype(user, /mob/living/silicon))
user.unset_machine()
user << browse(null, "window=shield_capacitor")
return
var/t = "<B>Shield Capacitor Control Console</B><br><br>"
if(locked)
t += "<i>Swipe your ID card to begin.</i>"
else
t += "This capacitor is: [active ? "<font color=green>Online</font>" : "<font color=red>Offline</font>" ] <a href='?src=\ref[src];toggle=1'>[active ? "\[Deactivate\]" : "\[Activate\]"]</a><br>"
t += "Capacitor Status: [time_since_fail > 2 ? "<font color=green>OK.</font>" : "<font color=red>Discharging!</font>"]<br>"
t += "Stored Energy: [format_SI(stored_charge, "J")] ([100 * round(stored_charge/max_charge, 0.01)]%)<br>"
t += "Charge Rate: \
<a href='?src=\ref[src];charge_rate=-100000'>\[----\]</a> \
<a href='?src=\ref[src];charge_rate=-10000'>\[---\]</a> \
<a href='?src=\ref[src];charge_rate=-1000'>\[--\]</a> \
<a href='?src=\ref[src];charge_rate=-100'>\[-\]</a>[format_SI(charge_rate, "W")]\
<a href='?src=\ref[src];charge_rate=100'>\[+\]</a> \
<a href='?src=\ref[src];charge_rate=1000'>\[++\]</a> \
<a href='?src=\ref[src];charge_rate=10000'>\[+++\]</a> \
<a href='?src=\ref[src];charge_rate=100000'>\[++++\]</a><br>"
t += "<hr>"
t += "<A href='?src=\ref[src]'>Refresh</A> "
t += "<A href='?src=\ref[src];close=1'>Close</A><BR>"
/obj/machinery/shield_capacitor/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ShieldCapacitor", name)
ui.open()
user << browse(t, "window=shield_capacitor;size=500x400")
user.set_machine(src)
/obj/machinery/shield_capacitor/tgui_status(mob/user)
if(stat & BROKEN)
return STATUS_CLOSE
return ..()
/obj/machinery/shield_capacitor/tgui_data(mob/user)
var/list/data = list()
data["active"] = active
data["time_since_fail"] = time_since_fail
data["stored_charge"] = stored_charge
data["max_charge"] = max_charge
data["charge_rate"] = charge_rate
data["max_charge_rate"] = max_charge_rate
return data
/obj/machinery/shield_capacitor/process()
if (!anchored)
@@ -119,21 +114,20 @@
time_since_fail = 0 //losing charge faster than we can draw from PN
last_stored_charge = stored_charge
/obj/machinery/shield_capacitor/Topic(href, href_list[])
..()
if( href_list["close"] )
usr << browse(null, "window=shield_capacitor")
usr.unset_machine()
return
if( href_list["toggle"] )
if(!active && !anchored)
to_chat(usr, "<font color='red'>The [src] needs to be firmly secured to the floor first.</font>")
return
active = !active
if( href_list["charge_rate"] )
charge_rate = between(10000, charge_rate + text2num(href_list["charge_rate"]), max_charge_rate)
/obj/machinery/shield_capacitor/tgui_act(action, params)
if(..())
return TRUE
updateDialog()
switch(action)
if("toggle")
if(!active && !anchored)
to_chat(usr, "<font color='red'>The [src] needs to be firmly secured to the floor first.</font>")
return
active = !active
. = TRUE
if("charge_rate")
charge_rate = clamp(text2num(params["rate"]), 10000, max_charge_rate)
. = TRUE
/obj/machinery/shield_capacitor/power_change()
if(stat & BROKEN)
+67 -73
View File
@@ -23,6 +23,7 @@
var/energy_conversion_rate = 0.0006 //how many renwicks per watt? Higher numbers equals more effiency.
var/z_range = 0 // How far 'up and or down' to extend the shield to, in z-levels. Only works on MultiZ supported z-levels.
use_power = USE_POWER_OFF //doesn't use APC power
interact_offline = TRUE // don't check stat & NOPOWER|BROKEN for our UI. We check BROKEN ourselves.
var/id //for button usage
/obj/machinery/shield_gen/advanced
@@ -95,59 +96,50 @@
/obj/machinery/shield_gen/attack_hand(mob/user)
if(stat & (BROKEN))
return
interact(user)
tgui_interact(user)
/obj/machinery/shield_gen/interact(mob/user)
if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN)) )
if (!istype(user, /mob/living/silicon))
user.unset_machine()
user << browse(null, "window=shield_generator")
return
var/t = "<B>Shield Generator Control Console</B><BR><br>"
if(locked)
t += "<i>Swipe your ID card to begin.</i>"
else
t += "[capacitors.len ? "<font color=green>Charge capacitor(s) connected.</font>" : "<font color=red>Unable to locate charge capacitor!</font>"]<br>"
var/i = 0
for(var/obj/machinery/shield_capacitor/capacitor in capacitors)
i++
t += "Capacitor #[i]: [capacitor.active ? "<font color=green>Online.</font>" : "<font color=red>Offline.</font>"] \
Charge: [round(capacitor.stored_charge/1000, 0.1)] kJ ([100 * round(capacitor.stored_charge/capacitor.max_charge, 0.01)]%) \
Status: [capacitor.time_since_fail > 2 ? "<font color=green>OK.</font>" : "<font color=red>Discharging!</font>"]<br>"
t += "This generator is: [active ? "<font color=green>Online</font>" : "<font color=red>Offline</font>" ] <a href='?src=\ref[src];toggle=1'>[active ? "\[Deactivate\]" : "\[Activate\]"]</a><br>"
t += "Field Status: [time_since_fail > 2 ? "<font color=green>Stable</font>" : "<font color=red>Unstable</font>"]<br>"
t += "Coverage Radius (restart required): \
<a href='?src=\ref[src];change_radius=-50'>---</a> \
<a href='?src=\ref[src];change_radius=-5'>--</a> \
<a href='?src=\ref[src];change_radius=-1'>-</a> \
[field_radius] m \
<a href='?src=\ref[src];change_radius=1'>+</a> \
<a href='?src=\ref[src];change_radius=5'>++</a> \
<a href='?src=\ref[src];change_radius=50'>+++</a><br>"
if(HasAbove(src.z) || HasBelow(src.z)) // Won't show up on maps lacking MultiZ support.
t += "Vertical Shielding (restart required): \
<a href='?src=\ref[src];z_range=-1'>-</a> \
[z_range] Vertical Range \
<a href='?src=\ref[src];z_range=1'>+</a><br>"
t += "Overall Field Strength: [round(average_field_strength, 0.01)] Renwick ([target_field_strength ? round(100 * average_field_strength / target_field_strength, 0.1) : "NA"]%)<br>"
t += "Upkeep Power: [format_SI(round(field.len * max(average_field_strength * dissipation_rate, min_dissipation) / energy_conversion_rate), "W")]<br>"
t += "Charge Rate: <a href='?src=\ref[src];strengthen_rate=-0.1'>--</a> \
[strengthen_rate] Renwick/s \
<a href='?src=\ref[src];strengthen_rate=0.1'>++</a><br>"
t += "Shield Generation Power: [format_SI(round(field.len * min(strengthen_rate, target_field_strength - average_field_strength) / energy_conversion_rate), "W")]<br>"
t += "Maximum Field Strength: \
<a href='?src=\ref[src];target_field_strength=-10'>\[min\]</a> \
<a href='?src=\ref[src];target_field_strength=-5'>--</a> \
<a href='?src=\ref[src];target_field_strength=-1'>-</a> \
[target_field_strength] Renwick \
<a href='?src=\ref[src];target_field_strength=1'>+</a> \
<a href='?src=\ref[src];target_field_strength=5'>++</a> \
<a href='?src=\ref[src];target_field_strength=10'>\[max\]</a><br>"
t += "<hr>"
t += "<A href='?src=\ref[src]'>Refresh</A> "
t += "<A href='?src=\ref[src];close=1'>Close</A><BR>"
user << browse(t, "window=shield_generator;size=500x400")
user.set_machine(src)
/obj/machinery/shield_gen/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ShieldGenerator", name)
ui.open()
/obj/machinery/shield_gen/tgui_status(mob/user)
if(stat & BROKEN)
return STATUS_CLOSE
return ..()
/obj/machinery/shield_gen/tgui_data(mob/user)
var/list/data = list()
data["locked"] = locked
data["lockedData"] = list()
if(!locked)
data["lockedData"]["capacitors"] = list()
for(var/obj/machinery/shield_capacitor/C in capacitors)
data["lockedData"]["capacitors"].Add(list(list(
"active" = C.active,
"stored_charge" = C.stored_charge,
"max_charge" = C.max_charge,
"failing" = (C.time_since_fail <= 2),
)))
data["lockedData"]["active"] = active
data["lockedData"]["failing"] = (time_since_fail <= 2)
data["lockedData"]["radius"] = field_radius
data["lockedData"]["max_radius"] = max_field_radius
data["lockedData"]["z_range"] = z_range
data["lockedData"]["max_z_range"] = 10
data["lockedData"]["average_field_strength"] = average_field_strength
data["lockedData"]["target_field_strength"] = target_field_strength
data["lockedData"]["max_field_strength"] = max_field_strength
data["lockedData"]["shields"] = LAZYLEN(field)
data["lockedData"]["upkeep"] = round(field.len * max(average_field_strength * dissipation_rate, min_dissipation) / energy_conversion_rate)
data["lockedData"]["strengthen_rate"] = strengthen_rate
data["lockedData"]["max_strengthen_rate"] = max_strengthen_rate
data["lockedData"]["gen_power"] = round(field.len * min(strengthen_rate, target_field_strength - average_field_strength) / energy_conversion_rate)
return data
/obj/machinery/shield_gen/process()
if (!anchored && active)
@@ -206,30 +198,32 @@
else
average_field_strength = 0
/obj/machinery/shield_gen/Topic(href, href_list[])
..()
if( href_list["close"] )
usr << browse(null, "window=shield_generator")
usr.unset_machine()
return
else if( href_list["toggle"] )
if (!active && !anchored)
to_chat(usr, "<font color='red'>The [src] needs to be firmly secured to the floor first.</font>")
return
toggle()
else if( href_list["change_radius"] )
field_radius = between(0, field_radius + text2num(href_list["change_radius"]), max_field_radius)
else if( href_list["strengthen_rate"] )
strengthen_rate = between(0, strengthen_rate + text2num(href_list["strengthen_rate"]), max_strengthen_rate)
else if( href_list["target_field_strength"] )
target_field_strength = between(1, target_field_strength + text2num(href_list["target_field_strength"]), max_field_strength)
else if( href_list["z_range"] )
z_range = between(0, z_range + text2num(href_list["z_range"]), 10) // Max is extending ten z-levels up and down. Probably too big of a number but it shouldn't matter.
/obj/machinery/shield_gen/tgui_act(action, params)
if(..())
return TRUE
switch(action)
if("toggle")
if (!active && !anchored)
to_chat(usr, "<font color='red'>The [src] needs to be firmly secured to the floor first.</font>")
return
toggle()
. = TRUE
if("change_radius")
field_radius = clamp(text2num(params["val"]), 0, max_field_radius)
. = TRUE
if("strengthen_rate")
strengthen_rate = clamp(text2num(params["val"]), 0, max_strengthen_rate)
. = TRUE
if("target_field_strength")
target_field_strength = clamp(text2num(params["val"]), 1, max_field_strength)
. = TRUE
if("z_range")
z_range = clamp(text2num(params["val"]), 0, 10)
. = TRUE
updateDialog()
/obj/machinery/shield_gen/ex_act(var/severity)
if(active)
toggle()
return ..()
+25 -40
View File
@@ -46,73 +46,58 @@
name = "escape pod controller"
program = /datum/computer/file/embedded_program/docking/simple
var/datum/shuttle/autodock/ferry/escape_pod/pod
valid_actions = list("toggle_override", "force_door")
/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/tgui_data(mob/user)
var/datum/computer/file/embedded_program/docking/simple/docking_program = program // Cast to proper type
data = list(
. = list(
"docking_status" = docking_program.get_docking_status(),
"override_enabled" = docking_program.override_enabled,
"door_state" = docking_program.memory["door_status"]["state"],
"door_lock" = docking_program.memory["door_status"]["lock"],
"exterior_status" = docking_program.memory["door_status"],
"can_force" = pod.can_force() || (emergency_shuttle.departed && pod.can_launch()), //allow players to manually launch ahead of time if the shuttle leaves
"is_armed" = pod.arming_controller.armed,
"armed" = pod.arming_controller.armed,
"internalTemplateName" = "EscapePodConsole",
)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "escape_pod_console.tmpl", name, 470, 290)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/Topic(href, href_list)
if((. = ..()))
return
if("manual_arm")
pod.arming_controller.arm()
return TOPIC_REFRESH
if("force_launch")
if (pod.can_force())
pod.force_launch(src)
else if (emergency_shuttle.departed && pod.can_launch()) //allow players to manually launch ahead of time if the shuttle leaves
pod.launch(src)
return TOPIC_REFRESH
return 0
/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/tgui_act(action, params)
if(..())
return TRUE
switch(action)
if("manual_arm")
pod.arming_controller.arm()
. = TRUE
if("force_launch")
if(pod.can_force())
pod.force_launch(src)
else if(emergency_shuttle.departed && pod.can_launch()) //allow players to manually launch ahead of time if the shuttle leaves
pod.launch(src)
. = TRUE
//This controller is for the escape pod berth (station side)
/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth
name = "escape pod berth controller"
program = /datum/computer/file/embedded_program/docking/simple/escape_pod_berth
valid_actions = list("toggle_override", "force_door")
/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth/tgui_data(mob/user)
var/datum/computer/file/embedded_program/docking/simple/docking_program = program // Cast to proper type
var/armed = null
if (istype(docking_program, /datum/computer/file/embedded_program/docking/simple/escape_pod_berth))
if(istype(docking_program, /datum/computer/file/embedded_program/docking/simple/escape_pod_berth))
var/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/P = docking_program
armed = P.armed
data = list(
. = list(
"docking_status" = docking_program.get_docking_status(),
"override_enabled" = docking_program.override_enabled,
"exterior_status" = docking_program.memory["door_status"],
"armed" = armed,
"internalTemplateName" = "EscapePodBerthConsole",
)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "escape_pod_berth_console.tmpl", name, 470, 290)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth/emag_act(var/remaining_charges, var/mob/user)
if (!emagged)
to_chat(user, "<span class='notice'>You emag the [src], arming the escape pod!</span>")
+37 -1
View File
@@ -26,6 +26,9 @@ Code is pretty much ripped verbatim from nano modules, but with un-needed stuff
if(host)
host.tgui_close(user)
/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
@@ -76,4 +79,37 @@ Code is pretty much ripped verbatim from nano modules, but with un-needed stuff
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, tgui_id, name)
ui.open()
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!
+138
View File
@@ -0,0 +1,138 @@
/datum/tgui_module/alarm_monitor
name = "Alarm monitor"
tgui_id = "StationAlertConsole"
var/list_cameras = 0 // Whether or not to list camera references. A future goal would be to merge this with the enginering/security camera console. Currently really only for AI-use.
var/list/datum/alarm_handler/alarm_handlers // The particular list of alarm handlers this alarm monitor should present to the user.
/datum/tgui_module/alarm_monitor/New()
..()
alarm_handlers = list()
/datum/tgui_module/alarm_monitor/all
/datum/tgui_module/alarm_monitor/all/New()
..()
alarm_handlers = SSalarm.all_handlers
/datum/tgui_module/alarm_monitor/all/robot
/datum/tgui_module/alarm_monitor/all/robot/tgui_state(mob/user)
return GLOB.tgui_self_state
/datum/tgui_module/alarm_monitor/engineering
/datum/tgui_module/alarm_monitor/engineering/New()
..()
alarm_handlers = list(atmosphere_alarm, fire_alarm, power_alarm)
// Subtype for glasses_state
/datum/tgui_module/alarm_monitor/engineering/glasses
/datum/tgui_module/alarm_monitor/engineering/glasses/tgui_state(mob/user)
return GLOB.tgui_glasses_state
// Subtype for nif_state
/datum/tgui_module/alarm_monitor/engineering/nif
/datum/tgui_module/alarm_monitor/engineering/nif/tgui_state(mob/user)
return GLOB.tgui_nif_state
// Subtype for NTOS
/datum/tgui_module/alarm_monitor/engineering/ntos
ntos = TRUE
/datum/tgui_module/alarm_monitor/security
/datum/tgui_module/alarm_monitor/security/New()
..()
alarm_handlers = list(camera_alarm, motion_alarm)
// Subtype for glasses_state
/datum/tgui_module/alarm_monitor/security/glasses
/datum/tgui_module/alarm_monitor/security/glasses/tgui_state(mob/user)
return GLOB.tgui_glasses_state
// Subtype for NTOS
/datum/tgui_module/alarm_monitor/security/ntos
ntos = TRUE
/datum/tgui_module/alarm_monitor/proc/register_alarm(var/object, var/procName)
for(var/datum/alarm_handler/AH in alarm_handlers)
AH.register_alarm(object, procName)
/datum/tgui_module/alarm_monitor/proc/unregister_alarm(var/object)
for(var/datum/alarm_handler/AH in alarm_handlers)
AH.unregister_alarm(object)
/datum/tgui_module/alarm_monitor/proc/all_alarms()
var/z = get_z(tgui_host())
var/list/all_alarms = new()
for(var/datum/alarm_handler/AH in alarm_handlers)
all_alarms += AH.visible_alarms(z)
return all_alarms
/datum/tgui_module/alarm_monitor/proc/major_alarms()
var/z = get_z(tgui_host())
var/list/all_alarms = new()
for(var/datum/alarm_handler/AH in alarm_handlers)
all_alarms += AH.major_alarms(z)
return all_alarms
// Modified version of above proc that uses slightly less resources, returns 1 if there is a major alarm, 0 otherwise.
/datum/tgui_module/alarm_monitor/proc/has_major_alarms()
var/z = get_z(tgui_host())
for(var/datum/alarm_handler/AH in alarm_handlers)
if(AH.has_major_alarms(z))
return 1
return 0
/datum/tgui_module/alarm_monitor/proc/minor_alarms()
var/z = get_z(tgui_host())
var/list/all_alarms = new()
for(var/datum/alarm_handler/AH in alarm_handlers)
all_alarms += AH.minor_alarms(z)
return all_alarms
/datum/tgui_module/alarm_monitor/tgui_act(action, params)
if(..())
return TRUE
// Camera stuff is AI only.
// If you're not an AI, this is a read-only UI.
if(!isAI(usr))
return
switch(action)
if("switchTo")
var/obj/machinery/camera/C = locate(params["camera"]) in cameranet.cameras
if(!C)
return
usr.switch_to_camera(C)
return 1
/datum/tgui_module/alarm_monitor/tgui_data(mob/user)
var/list/data = list()
var/categories[0]
var/z = get_z(tgui_host())
for(var/datum/alarm_handler/AH in alarm_handlers)
categories[++categories.len] = list("category" = AH.category, "alarms" = list())
for(var/datum/alarm/A in AH.visible_alarms(z))
var/cameras[0]
var/lost_sources[0]
if(isAI(user))
for(var/obj/machinery/camera/C in A.cameras())
cameras[++cameras.len] = C.tgui_structure()
for(var/datum/alarm_source/AS in A.sources)
if(!AS.source)
lost_sources[++lost_sources.len] = AS.source_name
categories[categories.len]["alarms"] += list(list(
"name" = "[A.alarm_name()]" + "[A.max_severity() > 1 ? "(MAJOR)" : ""]",
"origin_lost" = A.origin == null,
"has_cameras" = cameras.len,
"cameras" = cameras,
"lost_sources" = lost_sources.len ? sanitize(english_list(lost_sources, nothing_text = "", and_text = ", ")) : ""))
data["categories"] = categories
return data
@@ -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&trade;"
flags = APPEARANCE_ALL_HAIR
customize_usr = TRUE
/datum/tgui_module/appearance_changer/mirror/coskit
name = "SalonPro Porta-Makeover Deluxe&trade;"
+110
View File
@@ -0,0 +1,110 @@
/datum/tgui_module/atmos_control
name = "Atmospherics Control"
tgui_id = "AtmosControl"
var/obj/access = new()
var/emagged = 0
var/ui_ref
var/list/monitored_alarms = list()
/datum/tgui_module/atmos_control/New(atmos_computer, req_access, req_one_access, monitored_alarm_ids)
..()
access.req_access = req_access
access.req_one_access = req_one_access
if(monitored_alarm_ids)
for(var/obj/machinery/alarm/alarm in machines)
if(alarm.alarm_id && alarm.alarm_id in monitored_alarm_ids)
monitored_alarms += alarm
// machines may not yet be ordered at this point
monitored_alarms = dd_sortedObjectList(monitored_alarms)
/datum/tgui_module/atmos_control/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
switch(action)
if("alarm")
if(ui_ref)
var/obj/machinery/alarm/alarm = locate(params["alarm"]) in (monitored_alarms.len ? monitored_alarms : machines)
if(alarm)
var/datum/tgui_state/TS = generate_state(alarm)
alarm.tgui_interact(usr, parent_ui = ui_ref, state = TS)
return 1
if("setZLevel")
ui.set_map_z_level(params["mapZLevel"])
return TRUE
/datum/tgui_module/atmos_control/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.autoupdate = TRUE
ui.open()
ui_ref = ui
/datum/tgui_module/atmos_control/tgui_static_data(mob/user)
. = ..()
var/z = get_z(user)
var/list/map_levels = using_map.get_map_levels(z)
// TODO: Move these to a cache, similar to cameras
var/alarms[0]
for(var/obj/machinery/alarm/alarm in (monitored_alarms.len ? monitored_alarms : machines))
if(!monitored_alarms.len && alarm.alarms_hidden)
continue
if(!(alarm.z in map_levels))
continue
alarms[++alarms.len] = list(
"name" = sanitize(alarm.name),
"ref"= "\ref[alarm]",
"danger" = max(alarm.danger_level, alarm.alarm_area.atmosalm),
"x" = alarm.x,
"y" = alarm.y,
"z" = alarm.z)
.["alarms"] = alarms
/datum/tgui_module/atmos_control/tgui_data(mob/user)
var/list/data = list()
var/z = get_z(user)
var/list/map_levels = using_map.get_map_levels(z)
data["map_levels"] = map_levels
return data
/datum/tgui_module/atmos_control/tgui_close()
. = ..()
ui_ref = null
/datum/tgui_module/atmos_control/proc/generate_state(air_alarm)
var/datum/tgui_state/air_alarm_remote/state = new()
state.atmos_control = src
state.air_alarm = air_alarm
return state
/datum/tgui_state/air_alarm_remote
var/datum/tgui_module/atmos_control/atmos_control = null
var/obj/machinery/alarm/air_alarm = null
/datum/tgui_state/air_alarm_remote/can_use_topic(src_object, mob/user)
if(!atmos_control.ui_ref)
qdel(src)
return STATUS_CLOSE
if(has_access(user))
return STATUS_INTERACTIVE
return STATUS_UPDATE
/datum/tgui_state/air_alarm_remote/proc/has_access(var/mob/user)
return user && (isAI(user) || atmos_control.access.allowed(user) || atmos_control.emagged || air_alarm.rcon_setting == RCON_YES || (air_alarm.alarm_area.atmosalm && air_alarm.rcon_setting == RCON_AUTO) || (access_ce in user.GetAccess()))
/datum/tgui_state/air_alarm_remote/Destroy()
atmos_control = null
air_alarm = null
/datum/tgui_module/atmos_control/ntos
ntos = TRUE
/datum/tgui_module/atmos_control/robot
/datum/tgui_module/atmos_control/robot/tgui_state(mob/user)
return GLOB.tgui_self_state
+1 -31
View File
@@ -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
@@ -0,0 +1,85 @@
/datum/tgui_module/power_monitor
name = "Power monitor"
tgui_id = "PowerMonitor"
var/list/grid_sensors
var/active_sensor = null //name_tag of the currently selected sensor
/datum/tgui_module/power_monitor/New()
. = ..()
refresh_sensors()
/datum/tgui_module/power_monitor/tgui_data(mob/user)
var/list/data = list()
var/list/sensors = list()
// Focus: If it remains null if no sensor is selected and UI will display sensor list, otherwise it will display sensor reading.
var/obj/machinery/power/sensor/focus = null
var/z = get_z(user)
var/list/map_levels = using_map.get_map_levels(z)
// Build list of data from sensor readings.
for(var/obj/machinery/power/sensor/S in grid_sensors)
if(!(S.z in map_levels))
continue
sensors.Add(list(list(
"name" = S.name_tag,
"alarm" = S.check_grid_warning()
)))
if(S.name_tag == active_sensor)
focus = S
data["all_sensors"] = sensors
if(focus)
data["focus"] = focus.tgui_data(user)
else
data["focus"] = null
return data
/datum/tgui_module/power_monitor/tgui_act(action, params)
if(..())
return TRUE
switch(action)
if("clear")
active_sensor = null
. = TRUE
if("refresh")
refresh_sensors()
. = TRUE
if("setsensor")
active_sensor = params["id"]
. = TRUE
/datum/tgui_module/power_monitor/proc/has_alarm()
for(var/obj/machinery/power/sensor/S in grid_sensors)
if(S.check_grid_warning())
return TRUE
return FALSE
/datum/tgui_module/power_monitor/proc/refresh_sensors()
grid_sensors = list()
// Handle ultranested programs
var/turf/T = get_turf(tgui_host())
var/list/levels = list()
if(!T) // Safety check
return
if(T)
levels += using_map.get_map_levels(T.z, FALSE)
for(var/obj/machinery/power/sensor/S in machines)
if(T && (S.loc.z == T.z) || (S.loc.z in levels) || (S.long_range)) // Consoles have range on their Z-Level. Sensors with long_range var will work between Z levels.
if(S.name_tag == "#UNKN#") // Default name. Shouldn't happen!
warning("Powernet sensor with unset ID Tag! [S.x]X [S.y]Y [S.z]Z")
else
grid_sensors += S
/datum/tgui_module/power_monitor/ntos
ntos = TRUE
// Subtype for self_state
/datum/tgui_module/power_monitor/robot
/datum/tgui_module/power_monitor/robot/tgui_state(mob/user)
return GLOB.tgui_self_state
+118
View File
@@ -0,0 +1,118 @@
/datum/tgui_module/rcon
name = "Power RCON"
tgui_id = "RCON"
var/list/known_SMESs = null
var/list/known_breakers = null
/datum/tgui_module/rcon/tgui_data(mob/user)
FindDevices() // Update our devices list
var/list/data = ..()
// SMES DATA (simplified view)
var/list/smeslist[0]
for(var/obj/machinery/power/smes/buildable/SMES in known_SMESs)
smeslist.Add(list(list(
"capacity" = SMES.capacity,
"capacityPercent" = round(100*SMES.charge/SMES.capacity, 0.1),
"charge" = SMES.charge,
"input_set" = SMES.input_attempt,
"input_val" = round(SMES.input_level/1000, 0.1),
"output_set" = SMES.output_attempt,
"output_val" = round(SMES.output_level/1000, 0.1),
"output_load" = round(SMES.output_used/1000, 0.1),
"RCON_tag" = SMES.RCon_tag
)))
data["smes_info"] = sortByKey(smeslist, "RCON_tag")
// BREAKER DATA (simplified view)
var/list/breakerlist[0]
for(var/obj/machinery/power/breakerbox/BR in known_breakers)
breakerlist.Add(list(list(
"RCON_tag" = BR.RCon_tag,
"enabled" = BR.on
)))
data["breaker_info"] = breakerlist
return data
/datum/tgui_module/rcon/tgui_act(action, params)
if(..())
return TRUE
switch(action)
if("smes_in_toggle")
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(params["smes"])
if(SMES)
SMES.toggle_input()
. = TRUE
if("smes_out_toggle")
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(params["smes"])
if(SMES)
SMES.toggle_output()
. = TRUE
if("smes_in_set")
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(params["smes"])
if(SMES)
var/inputset = (input(usr, "Enter new input level (0-[SMES.input_level_max/1000] kW)", "SMES Input Power Control", SMES.input_level/1000) as num) * 1000
SMES.set_input(inputset)
. = TRUE
if("smes_out_set")
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(params["smes"])
if(SMES)
var/outputset = (input(usr, "Enter new output level (0-[SMES.output_level_max/1000] kW)", "SMES Output Power Control", SMES.output_level/1000) as num) * 1000
SMES.set_output(outputset)
. = TRUE
if("toggle_breaker")
var/obj/machinery/power/breakerbox/toggle = null
for(var/obj/machinery/power/breakerbox/breaker in known_breakers)
if(breaker.RCon_tag == params["breaker"])
toggle = breaker
if(toggle)
if(toggle.update_locked)
to_chat(usr, "The breaker box was recently toggled. Please wait before toggling it again.")
else
toggle.auto_toggle()
. = TRUE
// Proc: GetSMESByTag()
// Parameters: 1 (tag - RCON tag of SMES we want to look up)
// Description: Looks up and returns SMES which has matching RCON tag
/datum/tgui_module/rcon/proc/GetSMESByTag(var/tag)
if(!tag)
return
for(var/obj/machinery/power/smes/buildable/S in known_SMESs)
if(S.RCon_tag == tag)
return S
// Proc: FindDevices()
// Parameters: None
// Description: Refreshes local list of known devices.
/datum/tgui_module/rcon/proc/FindDevices()
known_SMESs = new /list()
var/z = get_z(tgui_host())
var/list/map_levels = using_map.get_map_levels(z)
for(var/obj/machinery/power/smes/buildable/SMES in GLOB.smeses)
if(!(SMES.z in map_levels))
continue
if(SMES.RCon_tag && (SMES.RCon_tag != "NO_TAG") && SMES.RCon)
known_SMESs.Add(SMES)
known_breakers = new /list()
for(var/obj/machinery/power/breakerbox/breaker in machines)
if(!(breaker.z in map_levels))
continue
if(breaker.RCon_tag != "NO_TAG")
known_breakers.Add(breaker)
/datum/tgui_module/rcon/ntos
ntos = TRUE
/datum/tgui_module/rcon/robot
/datum/tgui_module/rcon/robot/tgui_state(mob/user)
return GLOB.tgui_self_state
@@ -0,0 +1,46 @@
/datum/tgui_module/shutoff_monitor
name = "Shutoff Valve Monitoring"
tgui_id = "ShutoffMonitor"
/datum/tgui_module/shutoff_monitor/tgui_act(action, params)
if(..())
return TRUE
switch(action)
if("toggle_enable")
var/obj/machinery/atmospherics/valve/shutoff/S = locate(params["valve"])
if(!istype(S))
return 0
S.close_on_leaks = !S.close_on_leaks
return 1
if("toggle_open")
var/obj/machinery/atmospherics/valve/shutoff/S = locate(params["valve"])
if(!istype(S))
return 0
if(S.open)
S.close()
else
S.open()
return 1
/datum/tgui_module/shutoff_monitor/tgui_data(mob/user)
var/list/data = list()
var/list/valves = list()
for(var/obj/machinery/atmospherics/valve/shutoff/S in GLOB.shutoff_valves)
valves.Add(list(list(
"name" = S.name,
"enabled" = S.close_on_leaks,
"open" = S.open,
"x" = S.x,
"y" = S.y,
"z" = S.z,
"ref" = "\ref[S]"
)))
data["valves"] = valves
return data
/datum/tgui_module/shutoff_monitor/ntos
ntos = TRUE
@@ -0,0 +1,108 @@
/datum/tgui_module/supermatter_monitor
name = "Supermatter monitor"
tgui_id = "SupermatterMonitor"
var/list/supermatters
var/obj/machinery/power/supermatter/active = null // Currently selected supermatter crystal.
/datum/tgui_module/supermatter_monitor/Destroy()
. = ..()
active = null
supermatters = null
/datum/tgui_module/supermatter_monitor/New()
..()
refresh()
// Refreshes list of active supermatter crystals
/datum/tgui_module/supermatter_monitor/proc/refresh()
supermatters = list()
var/z = get_z(tgui_host())
if(!z)
return
var/valid_z_levels = using_map.get_map_levels(z)
for(var/obj/machinery/power/supermatter/S in machines)
// Delaminating, not within coverage, not on a tile.
if(S.grav_pulling || S.exploded || !(S.z in valid_z_levels) || !istype(S.loc, /turf/))
continue
supermatters.Add(S)
if(!(active in supermatters))
active = null
/datum/tgui_module/supermatter_monitor/proc/get_status()
. = SUPERMATTER_INACTIVE
for(var/obj/machinery/power/supermatter/S in supermatters)
. = max(., S.get_status())
/datum/tgui_module/supermatter_monitor/tgui_data(mob/user)
var/list/data = ..()
if(istype(active))
var/turf/T = get_turf(active)
if(!T)
active = null
return
var/datum/gas_mixture/air = T.return_air()
if(!istype(air))
active = null
return
data["active"] = 1
data["SM_area"] = get_area(active)
data["SM_integrity"] = active.get_integrity()
data["SM_power"] = active.power
data["SM_ambienttemp"] = air.temperature
data["SM_ambientpressure"] = air.return_pressure()
data["SM_EPR"] = active.get_epr()
//data["SM_EPR"] = active.get_epr()
if(air.total_moles)
data["SM_gas_O2"] = round(100*air.gas["oxygen"]/air.total_moles,0.01)
data["SM_gas_CO2"] = round(100*air.gas["carbon_dioxide"]/air.total_moles,0.01)
data["SM_gas_N2"] = round(100*air.gas["nitrogen"]/air.total_moles,0.01)
data["SM_gas_PH"] = round(100*air.gas["phoron"]/air.total_moles,0.01)
data["SM_gas_N2O"] = round(100*air.gas["sleeping_agent"]/air.total_moles,0.01)
else
data["SM_gas_O2"] = 0
data["SM_gas_CO2"] = 0
data["SM_gas_N2"] = 0
data["SM_gas_PH"] = 0
data["SM_gas_N2O"] = 0
else
var/list/SMS = list()
for(var/obj/machinery/power/supermatter/S in supermatters)
var/area/A = get_area(S)
if(!A)
continue
SMS.Add(list(list(
"area_name" = A.name,
"integrity" = S.get_integrity(),
"uid" = S.uid
)))
data["active"] = 0
data["supermatters"] = SMS
return data
/datum/tgui_module/supermatter_monitor/tgui_act(action, params)
if(..())
return TRUE
switch(action)
if("clear")
active = null
. = TRUE
if("refresh")
refresh()
. = TRUE
if("set")
var/newuid = text2num(params["set"])
for(var/obj/machinery/power/supermatter/S in supermatters)
if(S.uid == newuid)
active = S
. = TRUE
/datum/tgui_module/supermatter_monitor/ntos
ntos = TRUE
+41 -42
View File
@@ -143,57 +143,56 @@
/obj/structure/lift/panel/interact(var/mob/user)
if(!..())
return
tgui_interact(user)
var/dat = list()
dat += "<html><body><hr><b>Lift panel</b><hr>"
/obj/structure/lift/panel/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Turbolift", name)
ui.open()
//the floors list stores levels in order of increasing Z
//therefore, to display upper levels at the top of the menu and
//lower levels at the bottom, we need to go through the list in reverse
/obj/structure/lift/panel/tgui_data(mob/user)
var/list/data = list()
data["doors_open"] = lift.doors_are_open()
data["fire_mode"] = lift.fire_mode
data["floors"] = list()
for(var/i in lift.floors.len to 1 step -1)
var/datum/turbolift_floor/floor = lift.floors[i]
var/label = floor.label? floor.label : "Level #[i]"
dat += "<font color = '[(floor in lift.queued_floors) ? COLOR_YELLOW : COLOR_WHITE]'>"
dat += "<a href='?src=\ref[src];move_to_floor=["\ref[floor]"]'>[label]</a>: [floor.name]</font><br>"
data["floors"].Add(list(list(
"id" = i,
"ref" = "\ref[floor]",
"queued" = (floor in lift.queued_floors),
"target" = (lift.target_floor == floor),
"current" = (lift.current_floor == floor),
"label" = floor.label,
"name" = floor.name,
)))
return data
dat += "<hr>"
if(lift.doors_are_open())
dat += "<a href='?src=\ref[src];close_doors=1'>Close Doors</a><br>"
else
dat += "<a href='?src=\ref[src];open_doors=1'>Open Doors</a><br>"
dat += "<a href='?src=\ref[src];emergency_stop=1'>Emergency Stop</a>"
dat += "<hr></body></html>"
/obj/structure/lift/panel/tgui_act(action, params)
if(..())
return TRUE
user.set_machine(src)
var/datum/browser/popup = new(user, "turbolift_panel", "Lift Panel", 350, 320) //VOREStation Edit - Wider!
popup.set_content(jointext(dat, null))
popup.open()
return
switch(action)
if("move_to_floor")
. = TRUE
lift.queue_move_to(locate(params["ref"]))
if("toggle_doors")
. = TRUE
if(lift.doors_are_open())
lift.close_doors()
else
lift.open_doors()
if("emergency_stop")
. = TRUE
lift.emergency_stop()
/obj/structure/lift/panel/Topic(href, href_list)
. = ..()
if(.)
return
var/panel_interact
if(href_list["move_to_floor"])
lift.queue_move_to(locate(href_list["move_to_floor"]))
panel_interact = 1
if(href_list["open_doors"])
panel_interact = 1
lift.open_doors()
if(href_list["close_doors"])
panel_interact = 1
lift.close_doors()
if(href_list["emergency_stop"])
panel_interact = 1
lift.emergency_stop()
if(panel_interact)
pressed(usr)
updateDialog()
return 0
/obj/structure/lift/panel/update_icon()
if(lift.fire_mode)
+57 -66
View File
@@ -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>"
+2
View File
@@ -254,6 +254,7 @@ var/global/list/virusDB = list()
"resistance" = resistance,
"species" = jointext(affected_species, ", "),
"symptoms" = list(),
"ref" = "\ref[src]",
)
for(var/datum/disease2/effectholder/E in effects)
@@ -272,6 +273,7 @@ var/global/list/virusDB = list()
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
+86 -86
View File
@@ -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
+64 -70
View File
@@ -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
View File
@@ -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_vr.dmi' //VOREStation Edit
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>&nbsp;
"}
if (LIST)
if("virus_list")
P.name = "paper - Virus List"
P.info = {"
[virology_letterhead("Virus List")]
@@ -225,11 +196,14 @@
<u>Additional Notes:</u>&nbsp;
"}
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>&nbsp;
"}