- Scrubbers in the area can be controlled by air alarms. Air alarm interface must be unlocked with an ID card (minimum access level - atmospheric technician), usable only by humans and AI. Panic syphon drains the air from affected room (simple syphoning does too, but much slower).

- Sleeper consoles inject soporific and track the amounts of rejuvination chemicals and sleep toxins in occupants bloodstream.
- Flashlights can be used to check if mob is dead, blind or has certain superpower. Aim for the eyes.
- Radiation collectors and collector controls can be moved. Secured\unsecured with a wrench.
- Air sensors report nitrogen and carbon dioxide in air composition(if set to).
- Air Control console in Toxins.
- Additional DNA console in genetics
- Enough equipment to build another singularity engine can be found in engineering secure storage.
- Air scrubber, vent and air alarm added to library
- Air alarm added to brig
- Air scrubbers in Toxins turned on, set to filter toxins
- Empty tanks, portable air pumps and similar can be filled with air in Aft Primary Hallway, just connect them to the port. Target pressure is set by Mixed Air Supply console in Atmospherics (defaults to 4000kPa).

git-svn-id: http://tgstation13.googlecode.com/svn/trunk@262 316c924e-a436-60f5-8080-3fe189b3f50e
This commit is contained in:
panurgomatic
2010-10-10 13:25:47 +00:00
parent 294e5dd5ea
commit aa57719d52
8 changed files with 6464 additions and 6034 deletions

View File

@@ -7,27 +7,105 @@
level = 1
var/id_tag
var/frequency = 1439
var/datum/radio_frequency/radio_connection
var/on = 0
var/scrubbing = 1 //0 = siphoning, 1 = scrubbing
var/scrub_CO2 = 1
var/scrub_Toxins = 0
var/volume_rate = 120
var/panic = 0 //is this scrubber panicked?
update_icon()
if(on&&node)
if(on)//&&node)//seems to be broken
if(scrubbing)
icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]on"
else
icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]in"
else
icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]off"
on = 0
//on = 0
return
proc
set_frequency(new_frequency)
radio_controller.remove_object(src, "[frequency]")
frequency = new_frequency
radio_connection = radio_controller.add_object(src, "[frequency]")
broadcast_status()
if(!radio_connection)
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.data["tag"] = id_tag
signal.data["timestamp"] = air_master.current_cycle
signal.data["on"] = on
signal.data["scrubbing"] = scrubbing
signal.data["panic"] = panic
signal.data["filter_co2"] = scrub_CO2
signal.data["filter_toxins"] = scrub_Toxins
radio_connection.post_signal(src, signal)
return 1
//This is probably not a good place for this, since it messes with all scrubbers and alarms in area. Maybe it's better to move this to area code.
//It has its issues. Just place additional air alarm closer to the scrubbers, or assign scrubbers manually
find_air_alarm()
if(src.id_tag) return //id_tag assigned
var/area/A = get_area(loc)
var/area/M = A.master //we want to search master area, not only L(number) one
var/uniq_id = md5(M.name)//hash works like a charm
var/list/alarms = list()
var/list/scrubbers = list()
var/i = 0 //used in id_tag and scrubber name generation
if(M.related && M.related.len)//if has relatives
for(var/area/Rel in M.related)//check all relatives
if(Rel == M) continue //same parent area.
if(Rel.contents && Rel.contents.len)
for(var/obj/machinery/alarm/Al in Rel.contents)//find air alarms in area, append to list
alarms += Al
for(var/obj/machinery/atmospherics/unary/vent_scrubber/V in Rel.contents)//find scrubbers in area, append to list
if(V.id_tag) continue//already connected to air alarm
scrubbers += V
if(scrubbers.len&&alarms.len) //if scrubbers & alarms found in area
for(var/obj/machinery/atmospherics/unary/vent_scrubber/Sc in scrubbers)//iterate over found scrubbers
var/dist = 127 //max value returned by get_dist
var/obj/machinery/alarm/target_alarm = null
for(var/obj/machinery/alarm/Al in alarms)//iterate over found alarms
var/temp_dist = get_dist(Sc.loc, Al.loc)//if distance between current scrubber and current alarm < previous distance, set this alarm as target to connect to
if(temp_dist<dist)
target_alarm = Al
dist = temp_dist
if(target_alarm) //if target(closest) air alarm found,
Sc.id_tag = "[uniq_id]_[i++]" //set scrubber id_tag
Sc.frequency = target_alarm.frequency //set scrubber frequency (alarm frequency)
var/d_name = "[M.name] Air Scrubber #[i]" //displayed name
target_alarm.sensors[Sc.id_tag] = d_name //append scrubber to alarm 'sensor' list
Sc.name = d_name //set scrubber name
//debug
//world << "[Sc.name] in [M.name] is set to frequency [Sc.frequency] with ID [Sc.id_tag]"
//debug
initialize()
find_air_alarm()
set_frequency(frequency)
update_icon()
process()
..()
broadcast_status()
if(!on)
return 0
@@ -75,7 +153,7 @@
network.update = 1
return 1
/* //unused piece of code
hide(var/i) //to make the little pipe section invisible, the icon changes.
if(on&&node)
if(scrubbing)
@@ -85,4 +163,33 @@
else
icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]off"
on = 0
return
return
*/
receive_signal(datum/signal/signal)
if(signal.data["tag"] && (signal.data["tag"] != id_tag))
return ..()
switch(signal.data["command"])
if("toggle_power")
on = !on
if("toggle_scrubbing")
scrubbing = !scrubbing
if("toggle_co2_scrub")
scrub_CO2 = !scrub_CO2
if("toggle_tox_scrub")
scrub_Toxins = !scrub_Toxins
if("toggle_panic_siphon")
panic = !panic
if(panic)
on = 1
scrubbing = 0
volume_rate = 500
else
scrubbing = 1
volume_rate = 120
if(signal.data["tag"])
spawn(2) broadcast_status()
update_icon()
return ..()

View File

@@ -49,17 +49,19 @@
if(0)
t1 = "Conscious"
if(1)
t1 = "Unconscious"
t1 = "<font color='blue'>Unconscious</font>"
if(2)
t1 = "*dead*"
t1 = "<font color='red'>*dead*</font>"
else
dat += text("[]\tHealth %: [] ([])</FONT><BR>", (occupant.health > 50 ? "<font color='blue'>" : "<font color='red'>"), occupant.health, t1)
dat += text("[]\t-Brute Damage %: []</FONT><BR>", (occupant.bruteloss < 60 ? "<font color='blue'>" : "<font color='red'>"), occupant.bruteloss)
dat += text("[]\t-Respiratory Damage %: []</FONT><BR>", (occupant.oxyloss < 60 ? "<font color='blue'>" : "<font color='red'>"), occupant.oxyloss)
dat += text("[]\t-Toxin Content %: []</FONT><BR>", (occupant.toxloss < 60 ? "<font color='blue'>" : "<font color='red'>"), occupant.toxloss)
dat += text("[]\t-Burn Severity %: []</FONT><BR>", (occupant.fireloss < 60 ? "<font color='blue'>" : "<font color='red'>"), occupant.fireloss)
dat += text("<BR>Paralysis Summary %: [] ([] seconds left!)</FONT><BR>", occupant.paralysis, round(occupant.paralysis / 4))
dat += text("<HR><A href='?src=\ref[];refresh=1'>Refresh</A><BR><A href='?src=\ref[];rejuv=1'>Inject Rejuvenators</A>", src, src)
dat += text("<HR>Paralysis Summary %: [] ([] seconds left!)<BR>", occupant.paralysis, round(occupant.paralysis / 4))
dat += text("Rejuvenation chemicals: [] units<BR>", occupant.reagents.get_reagent_amount("inaprovaline"))
dat += text("Soporific: [] units<BR>", occupant.reagents.get_reagent_amount("stoxin"))
dat += text("<HR><A href='?src=\ref[];refresh=1'>Refresh meter readings each second</A><BR><A href='?src=\ref[];rejuv=1'>Inject Rejuvenators</A><BR><A href='?src=\ref[];stox=1'>Inject Soporific</A>", src, src, src)
else
dat += "The sleeper is empty."
dat += text("<BR><BR><A href='?src=\ref[];mach_close=sleeper'>Close</A>", user)
@@ -72,9 +74,11 @@
return
if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon/ai)))
usr.machine = src
if (href_list["rejuv"])
if (src.connected)
if (src.connected)
if (href_list["rejuv"])
src.connected.inject(usr)
if (href_list["stox"])
src.connected.inject_stox(usr)
if (href_list["refresh"])
src.updateUsrDialog()
src.add_fingerprint(usr)
@@ -224,13 +228,23 @@
/obj/machinery/sleeper/proc/inject(mob/user as mob)
if (src.occupant)
if (src.occupant.reagents.get_reagent_amount("inaprovaline") < 60)
if (src.occupant.reagents.get_reagent_amount("inaprovaline") + 30 < 60)
src.occupant.reagents.add_reagent("inaprovaline", 30)
user << text("Occupant now has [] units of rejuvenation in his/her bloodstream.", src.occupant.reagents.get_reagent_amount("inaprovaline"))
else
user << "No occupant!"
return
/obj/machinery/sleeper/proc/inject_stox(mob/user as mob)
if (src.occupant)
if (src.occupant.reagents.get_reagent_amount("stoxin") + 20 < 40)
src.occupant.reagents.add_reagent("stoxin", 20)
user << text("Occupant now has [] units of soporific in his/her bloodstream.", src.occupant.reagents.get_reagent_amount("stoxin"))
else
user << "No occupant!"
return
/obj/machinery/sleeper/proc/check(mob/user as mob)
if (src.occupant)
user << text("\blue <B>Occupant ([]) Statistics:</B>", src.occupant)

View File

@@ -1,3 +1,158 @@
/obj/machinery/alarm
var/frequency = 1439
var/list/sensors = list()
var/list/sensor_information = list()
var/datum/radio_frequency/radio_connection
var/alarm_area //unused atm. Maybe do something if emmaged or hacked...Like change the area to security, syphon air out, ..., profit.
var/locked = 1
var/panic = 0 //is this alarm panicked?
req_access = list(access_atmospherics)
attack_hand(mob/user)
if(!(istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/living/carbon/human)))
user << "\red You don't have the dexterity to do this"
return
if(stat & (NOPOWER|BROKEN))
return
else if(!(istype(usr, /mob/living/silicon/ai)) && locked)
user << "\red You must unlock the Air Alarm interface first"
return
src.add_fingerprint(user)
user << browse(return_text(),"window=air_alarm")
user.machine = src
onclose(user, "air_alarm")
return
receive_signal(datum/signal/signal)
if(!signal || signal.encryption) return
var/id_tag = signal.data["tag"]
if(!id_tag || !sensors.Find(id_tag)) return
sensor_information[id_tag] = signal.data
proc
set_frequency(new_frequency)
radio_controller.remove_object(src, "[frequency]")
frequency = new_frequency
radio_connection = radio_controller.add_object(src, "[frequency]")
/* //moved to vent_scrubber.dm
find_scrubbers()//finds vent_scrubbers in area, sets corresponding frequency, name and id_tags, fills sensor list with id_tags and names
var/area/A = get_area(loc)
var/area/M = A.master
if(!alarm_area)
alarm_area = M
//world << "\red Processing [M.name]"
var/uniq_id = md5(M.name)//hash works like a charm
if(M.related && M.related.len)//if has relatives
var/i = 0
for(var/area/Rel in M.related)//check all relatives
if(Rel == M) continue //same parent area
if(Rel.contents && Rel.contents.len)
for(var/obj/machinery/atmospherics/unary/vent_scrubber/V in Rel.contents)
if(V.id_tag)//id_tag assigned, probably already connected to alarm somewhere
//world << "[V.id_tag] passed"
continue
V.id_tag = "[uniq_id]_[i++]"//unique ID of the scrubber
V.frequency = frequency
var/name = "[M.name] Air Scrubber #[i]" //displayed name
sensors[V.id_tag] = name
V.name = name
//world << "[V.name] in [M.name] is set to [frequency] with ID [V.id_tag] and named [sensors[V.id_tag]]"
*/
send_signal(var/target, var/command)//sends signal 'command' to 'target'. Returns 0 if no radio connection, 1 otherwise
if(!radio_connection)
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.source = src
signal.data["tag"] = target
signal.data["command"] = command
radio_connection.post_signal(src, signal)
//world << text("Signal [] Broadcasted to []", command, target)
return 1
return_text()
var/sensor_data
if(sensors.len)
for(var/id_tag in sensors)
var/long_name = sensors[id_tag]
var/list/data = sensor_information[id_tag]
var/sensor_part = "<B>[long_name]</B>:<BR>"
if(data)
sensor_part += "<B>Operating:</B> <A href='?src=\ref[src];toggle_power=[id_tag]'>[data["on"]?"on":"off"]</A><BR>"
sensor_part += "<B>Type:</B> <A href='?src=\ref[src];toggle_scrubbing=[id_tag]'>[data["scrubbing"]?"scrubbing":"syphoning"]</A><BR>"
if(data["scrubbing"])
sensor_part += "<B>Filtering:</B> Carbon Dioxide <A href='?src=\ref[src];toggle_co2_scrub=[id_tag]'>([data["filter_co2"]?"on":"off"])</A>; Toxins <A href='?src=\ref[src];toggle_tox_scrub=[id_tag]'>([data["filter_toxins"]?"on":"off"])</A><BR>"
sensor_part += "<A href='?src=\ref[src];toggle_panic_siphon=[id_tag]'><font color='[data["panic"]?"blue'>Dea":"red'>A"]ctivate panic syphon</A></font><BR>"
if(data["panic"])
sensor_part += "<font color='red'><B>PANIC SYPHON ACTIVATED</B></font>"
sensor_part += "<HR>"
else
sensor_part = "<FONT color='red'>[long_name] can not be found!</FONT><BR>"
sensor_data += sensor_part
sensor_data += "<A href='?src=\ref[src];toggle_panic_siphon_global=1'><font color='red'><B>TOGGLE PANIC SYPHON IN AREA</B></font></A>"
else
sensor_data = "No scrubbers connected."
var/output = {"<B>[alarm_zone] Air [name]</B><HR>[sensor_data]"}
return output
initialize()
set_frequency(frequency)
/*if(!(sensors.len))//if there's something in the list, do not search the area
find_scrubbers()*/
Topic(href, href_list)
//if(..())
// return
if(href_list["toggle_power"])
send_signal(href_list["toggle_power"], "toggle_power")
if(href_list["toggle_scrubbing"])
send_signal(href_list["toggle_scrubbing"], "toggle_scrubbing")
if(href_list["toggle_co2_scrub"])
send_signal(href_list["toggle_co2_scrub"], "toggle_co2_scrub")
if(href_list["toggle_tox_scrub"])
send_signal(href_list["toggle_tox_scrub"], "toggle_tox_scrub")
if(href_list["toggle_panic_siphon"])
send_signal(href_list["toggle_panic_siphon"], "toggle_panic_siphon")
if(href_list["toggle_panic_siphon_global"])
for(var/V in sensors)
send_signal(V, "toggle_panic_siphon")
panic = !panic
spawn(5)
attack_hand(usr)
return ..()
/obj/machinery/alarm/New()
..()
@@ -93,6 +248,17 @@
for(var/mob/O in viewers(user, null))
O.show_message(text("\red [] has []activated []!", user, (stat&BROKEN) ? "de" : "re", src), 1)
return
else if (istype(W, /obj/item/weapon/card/id))// trying to unlock the interface with an ID card
if(stat & (NOPOWER|BROKEN))
user << "It does nothing"
else
if(src.allowed(usr))
locked = !locked
user << "You [ locked ? "lock" : "unlock"] the Air Alarm interface."
else
user << "\red Access denied."
return
return ..()
/obj/machinery/alarm/power_change()
@@ -101,10 +267,10 @@
else
stat |= NOPOWER
/obj/machinery/alarm/Click()
/*/obj/machinery/alarm/Click()
if(istype(usr, /mob/living/silicon/ai))
return examine()
return ..()
return ..()*/
/obj/machinery/alarm/examine()
set src in oview(1)
@@ -404,4 +570,4 @@
else
usr << browse(null, "window=partyalarm")
return
return
return

View File

@@ -4,6 +4,7 @@ obj/machinery/air_sensor
name = "Gas Sensor"
anchored = 1
var/state = 0
var/id_tag
var/frequency = 1439
@@ -13,8 +14,11 @@ obj/machinery/air_sensor
//Flags:
// 1 for pressure
// 2 for temperature
// Output >= 4 includes gas composition
// 4 for oxygen concentration
// 8 for toxins concentration
// 16 for nitrogen concentration
// 32 for carbon dioxide concentration
var/datum/radio_frequency/radio_connection
@@ -35,12 +39,16 @@ obj/machinery/air_sensor
if(output&2)
signal.data["temperature"] = round(air_sample.temperature,0.1)
if(output&12)
if(output>4)
var/total_moles = air_sample.total_moles()
if(output&4)
signal.data["oxygen"] = round(100*air_sample.oxygen/total_moles)
if(output&8)
signal.data["toxins"] = round(100*air_sample.toxins/total_moles)
if(output&16)
signal.data["nitrogen"] = round(100*air_sample.nitrogen/total_moles)
if(output&32)
signal.data["carbon_dioxide"] = round(100*air_sample.carbon_dioxide/total_moles)
radio_connection.post_signal(src, signal)
@@ -129,26 +137,24 @@ obj/machinery/computer/general_air_control
for(var/id_tag in sensors)
var/long_name = sensors[id_tag]
var/list/data = sensor_information[id_tag]
var/sensor_part = "<B>[long_name]</B>: "
var/sensor_part = "<B>[long_name]</B>:<BR>"
if(data)
if(data["pressure"])
sensor_part += "[data["pressure"]] kPa"
if(data["temperature"])
sensor_part += ", [data["temperature"]] K"
sensor_part += "<BR>"
else if(data["temperature"])
sensor_part += "[data["temperature"]] K<BR>"
if(data["oxygen"]||data["toxins"])
sensor_part += "<B>[long_name] Composition</B>: "
sensor_part += " <B>Pressure:</B> [data["pressure"]] kPa<BR>"
if(data["temperature"])
sensor_part += " <B>Temperature:</B> [data["temperature"]] K<BR>"
if(data["oxygen"]||data["toxins"]||data["nitrogen"]||data["carbon_dioxide"])
sensor_part += " <B>Gas Composition :</B>"
if(data["oxygen"])
sensor_part += "[data["oxygen"]] %O2"
if(data["toxins"])
sensor_part += ", [data["toxins"]] %TX"
sensor_part += "<BR>"
else if(data["toxins"])
sensor_part += "[data["toxins"]] %TX<BR>"
sensor_part += "[data["oxygen"]]% O2; "
if(data["nitrogen"])
sensor_part += "[data["nitrogen"]]% N; "
if(data["carbon_dioxide"])
sensor_part += "[data["carbon_dioxide"]]% CO2; "
if(data["toxins"])
sensor_part += "[data["toxins"]]% TX; "
sensor_part += "<HR>"
else
sensor_part = "<FONT color='red'>[long_name] can not be found!</FONT><BR>"
@@ -159,8 +165,7 @@ obj/machinery/computer/general_air_control
sensor_data = "No sensors connected."
var/output = {"<B>[name]</B><HR>
<B>Sensor Data: <BR></B>
[sensor_data]<HR>"}
<B>Sensor Data:</B><HR><HR>[sensor_data]"}
return output

View File

@@ -746,34 +746,42 @@ However people seem to like it for some reason.
..()
/obj/machinery/power/collector_array/attack_hand(mob/user as mob)
if(src.active==1)
src.active = 0
icon_state = "ca_deactive"
CU.updatecons()
user << "You turn off the collector array."
return
if(src.anchored == 1)
if(src.active==1)
src.active = 0
icon_state = "ca_deactive"
CU.updatecons()
user << "You turn off the collector array."
return
if(src.active==0)
src.active = 1
icon_state = "ca_active"
CU.updatecons()
user << "You turn on the collector array."
if(src.active==0)
src.active = 1
icon_state = "ca_active"
CU.updatecons()
user << "You turn on the collector array."
return
else
src.add_fingerprint(user)
user << "\red The collector needs to be secured to the floor first."
return
/obj/machinery/power/collector_array/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/weapon/tank/plasma))
if(src.P)
user << "\red There appears to already be a plasma tank loaded!"
if(src.anchored == 1)
if(src.P)
user << "\red There appears to already be a plasma tank loaded!"
return
src.P = W
W.loc = src
if (user.client)
user.client.screen -= W
user.u_equip(W)
CU.updatecons()
updateicon()
return
else
user << "The collector needs to be secured to the floor first."
return
src.P = W
W.loc = src
if (user.client)
user.client.screen -= W
user.u_equip(W)
CU.updatecons()
updateicon()
return
if(istype(W, /obj/item/weapon/crowbar))
if(!P)
@@ -786,6 +794,23 @@ However people seem to like it for some reason.
updateicon()
return
if(istype(W, /obj/item/weapon/wrench))
if(active)
user << "\red Turn off the collector first."
return
else if(src.anchored == 0)
playsound(src.loc, 'Ratchet.ogg', 75, 1)
user << "You secure the collector reinforcing bolts to the floor."
src.anchored = 1
return
else if(src.anchored == 1)
playsound(src.loc, 'Ratchet.ogg', 75, 1)
user << "You undo the external reinforcing bolts."
src.anchored = 0
return
else
src.add_fingerprint(user)
user << "\red You hit the [src.name] with your [W.name]!"
@@ -931,17 +956,22 @@ However people seem to like it for some reason.
/obj/machinery/power/collector_control/attack_hand(mob/user as mob)
if(src.active==1)
src.active = 0
user << "You turn off the collector control."
src.lastpower = 0
updateicon()
return
if(src.anchored==1)
if(src.active==1)
src.active = 0
user << "You turn off the collector control."
src.lastpower = 0
updateicon()
return
if(src.active==0)
src.active = 1
user << "You turn on the collector control."
updatecons()
if(src.active==0)
src.active = 1
user << "You turn on the collector control."
updatecons()
return
else
src.add_fingerprint(user)
user << "\red The collector control needs to be secured to the floor first."
return
@@ -949,6 +979,23 @@ However people seem to like it for some reason.
if(istype(W, /obj/item/device/analyzer))
user << "\blue The analyzer detects that [lastpower]W are being produced."
if(istype(W, /obj/item/weapon/wrench))
if(active)
user << "\red Turn off the collector control first."
return
else if(src.anchored == 0)
playsound(src.loc, 'Ratchet.ogg', 75, 1)
user << "You secure the collector control to the floor."
src.anchored = 1
return
else if(src.anchored == 1)
playsound(src.loc, 'Ratchet.ogg', 75, 1)
user << "You undo the collector control securing bolts."
src.anchored = 0
return
else
src.add_fingerprint(user)
user << "\red You hit the [src.name] with your [W.name]!"

View File

@@ -10,6 +10,44 @@
user.sd_SetLuminosity(user.luminosity - FLASHLIGHT_LUM)
/obj/item/device/flashlight/attack(mob/M as mob, mob/user as mob)
src.add_fingerprint(user)
if(src.on && user.zone_sel.selecting == "eyes")
if ((user.mutations & 16 || user.brainloss >= 60) && prob(50))//too dumb to use flashlight properly
return ..()//just hit them in the head
/*user << "\blue You bounce the light spot up and down and drool."
for(var/mob/O in viewers(M, null))
O.show_message(text("\blue [] bounces the light spot up and down and drools", user), 1)
src.add_fingerprint(user)
return*/
if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")//don't have dexterity
usr.show_message("\red You don't have the dexterity to do this!",1)
return
var/mob/living/carbon/human/H = M//mob has protective eyewear
if(istype(M, /mob/living/carbon/human) && ((H.head && H.head.flags & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES)))
user << text("\blue You're going to need to remove that [] first.", ((H.head && H.head.flags & HEADCOVERSEYES) ? "helmet" : ((H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) ? "mask": "glasses")))
return
for(var/mob/O in viewers(M, null))//echo message
O.show_message(text("\blue [] [] to [] eyes", (O == user ? "You direct" : text("[] directs", user)), src, (M==user ? "your" : text("[]", M))),1)
if(istype(M, /mob/living/carbon/human) || istype(M, /mob/living/carbon/monkey))//robots and aliens are unaffected
if(M.stat > 1 || M.sdisabilities & 1)//mob is dead or fully blind
if(M!=user)
user.show_message(text("\red [] pupils does not react to the light!", M),1)
else if(M.mutations&4)//mob has X-RAY vision
if(M!=user)
user.show_message(text("\red [] pupils give an eerie glow!", M),1)
else //nothing wrong
flick("flash", M.flash)//flash the affected mob
if(M!=user)
user.show_message(text("\blue [] pupils narrow", M),1)
else
return ..()
/obj/item/device/flashlight/pickup(mob/user)
if(on)
src.sd_SetLuminosity(0)