This commit is contained in:
Zuhayr
2015-02-18 14:17:39 +10:30
52 changed files with 1001 additions and 936 deletions

View File

@@ -42,10 +42,10 @@ var/global/list/facial_hair_styles_male_list = list()
var/global/list/facial_hair_styles_female_list = list()
var/global/list/skin_styles_female_list = list() //unused
//Underwear
var/global/list/underwear_m = list("White", "Grey", "Green", "Blue", "Black", "Mankini", "None") //Curse whoever made male/female underwear diffrent colours
var/global/list/underwear_f = list("Red", "White", "Yellow", "Blue", "Black", "Thong", "Black Sports","White Sports","None")
var/global/list/underwear_m = list("White" = "m1", "Grey" = "m2", "Green" = "m3", "Blue" = "m4", "Black" = "m5", "Mankini" = "m6", "None") //Curse whoever made male/female underwear diffrent colours
var/global/list/underwear_f = list("Red" = "f1", "White" = "f2", "Yellow" = "f3", "Blue" = "f4", "Black" = "f5", "Thong" = "f6", "Black Sports" = "f7","White Sports" = "f8","None")
//undershirt
var/global/list/undershirt_t = list("Black Tank top", "White Tank top", "Black shirt", "White shirt", "None")
var/global/list/undershirt_t = list("Black Tank top" = "u1", "White Tank top" = "u2", "Black shirt" = "u3", "White shirt" = "u4", "None")
//Backpacks
var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt")

View File

@@ -375,6 +375,12 @@ proc/listclearnulls(list/list)
i++
return null
// Returns the key based on the index
/proc/get_key_by_value(var/list/L, var/value)
for(var/key in L)
if(L[key] == value)
return key
/proc/count_by_type(var/list/L, type)
var/i = 0
for(var/T in L)

View File

@@ -433,9 +433,6 @@
f_style = "Shaved"
if(dna.species == "Human") //no more xenos losing ears/tentacles
h_style = pick("Bedhead", "Bedhead 2", "Bedhead 3")
undershirt = undershirt_t.Find("None")
if(gender == MALE)
underwear = underwear_m.Find("None")
else
underwear = underwear_f.Find("None")
undershirt = null
underwear = null
regenerate_icons()

View File

@@ -12,12 +12,11 @@
circuit = /obj/item/weapon/circuitboard/rcon_console
req_one_access = list(access_engine)
var/current_tag = null
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
var/obj/nano_module/rcon/rcon
/obj/machinery/computer/rcon/New()
..()
rcon = new(src)
// Proc: attack_hand()
// Parameters: 1 (user - Person which clicked this computer)
@@ -29,106 +28,5 @@
// Proc: ui_interact()
// Parameters: 4 (standard NanoUI parameters)
// Description: Uses dark magic (NanoUI) to render this machine's UI
/obj/machinery/computer/rcon/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
FindDevices() // Update our devices list
var/data[0]
// 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),
"output_set" = SMES.output_attempt,
"output_val" = round(SMES.output_level),
"output_load" = round(SMES.output_used),
"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 = nanomanager.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)
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.
/obj/machinery/computer/rcon/Topic(href, href_list)
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])", "SMES Input Power Control") as num
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])", "SMES Input Power Control") as num
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)
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
/obj/machinery/computer/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.
/obj/machinery/computer/rcon/proc/FindDevices()
known_SMESs = new /list()
for(var/obj/machinery/power/smes/buildable/SMES in machines)
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.RCon_tag != "NO_TAG")
known_breakers.Add(breaker)
/obj/machinery/computer/rcon/ui_interact(mob/user, ui_key = "rcon", var/datum/nanoui/ui = null, var/force_open = 1)
rcon.ui_interact(user, ui_key, ui, force_open)

View File

@@ -6,11 +6,10 @@
idle_power_usage = 250
active_power_usage = 500
circuit = "/obj/item/weapon/circuitboard/crew"
var/list/tracked = list( )
var/obj/nano_module/crew_monitor/crew_monitor
/obj/machinery/computer/crew/New()
tracked = list()
crew_monitor = new(src)
..()
@@ -25,6 +24,8 @@
return
ui_interact(user)
/obj/machinery/computer/crew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
crew_monitor.ui_interact(user, ui_key, ui, force_open)
/obj/machinery/computer/crew/update_icon()
@@ -38,93 +39,5 @@
icon_state = initial(icon_state)
stat &= ~NOPOWER
/obj/machinery/computer/crew/Topic(href, href_list)
if(..()) return
if (src.z > 6)
usr << "\red <b>Unable to establish a connection</b>: \black You're too far away from the station!"
return 0
if( href_list["close"] )
var/mob/user = usr
var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main")
usr.unset_machine()
ui.close()
return 0
if(href_list["update"])
src.updateDialog()
return 1
/obj/machinery/computer/crew/interact(mob/user)
ui_interact(user)
/obj/machinery/computer/crew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
if(stat & (BROKEN|NOPOWER))
return
user.set_machine(src)
src.scan()
var/data[0]
var/list/crewmembers = list()
for(var/obj/item/clothing/under/C in src.tracked)
var/turf/pos = get_turf(C)
if((C) && (C.has_sensor) && (pos) && (pos.z == src.z) && (C.sensor_mode != SUIT_SENSOR_OFF))
if(istype(C.loc, /mob/living/carbon/human))
var/mob/living/carbon/human/H = C.loc
if(H.w_uniform != C)
continue
var/list/crewmemberData = list("dead"=0, "oxy"=-1, "tox"=-1, "fire"=-1, "brute"=-1, "area"="", "x"=-1, "y"=-1)
crewmemberData["sensor_type"] = C.sensor_mode
crewmemberData["name"] = H.get_authentification_name(if_no_id="Unknown")
crewmemberData["rank"] = H.get_authentification_rank(if_no_id="Unknown", if_no_job="No Job")
crewmemberData["assignment"] = H.get_assignment(if_no_id="Unknown", if_no_job="No Job")
if(C.sensor_mode >= SUIT_SENSOR_BINARY)
crewmemberData["dead"] = H.stat > 1
if(C.sensor_mode >= SUIT_SENSOR_VITAL)
crewmemberData["oxy"] = round(H.getOxyLoss(), 1)
crewmemberData["tox"] = round(H.getToxLoss(), 1)
crewmemberData["fire"] = round(H.getFireLoss(), 1)
crewmemberData["brute"] = round(H.getBruteLoss(), 1)
if(C.sensor_mode >= SUIT_SENSOR_TRACKING)
var/area/A = get_area(H)
crewmemberData["area"] = sanitize(A.name)
crewmemberData["x"] = pos.x
crewmemberData["y"] = pos.y
crewmembers[++crewmembers.len] = crewmemberData
crewmembers = sortByKey(crewmembers, "name")
data["crewmembers"] = crewmembers
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "crew_monitor.tmpl", "Crew Monitoring Computer", 900, 800)
// adding a template with the key "mapContent" enables the map ui functionality
ui.add_template("mapContent", "crew_monitor_map_content.tmpl")
// adding a template with the key "mapHeader" replaces the map header content
ui.add_template("mapHeader", "crew_monitor_map_header.tmpl")
ui.set_initial_data(data)
ui.open()
// should make the UI auto-update; doesn't seem to?
ui.set_auto_update(1)
/obj/machinery/computer/crew/proc/scan()
for(var/mob/living/carbon/human/H in mob_list)
if(istype(H.w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/C = H.w_uniform
if (C.has_sensor)
tracked |= C
return 1
crew_monitor.ui_interact(user)

View File

@@ -1,109 +0,0 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
/obj/machinery/computer/hologram_comp
name = "hologram computer"
desc = "Rumoured to control holograms."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "holo_console0"
var/obj/machinery/hologram/projector/projector = null
var/temp = null
var/lumens = 0.0
var/h_r = 245.0
var/h_g = 245.0
var/h_b = 245.0
/obj/machinery/computer/hologram_comp/New()
..()
spawn( 10 )
src.projector = locate(/obj/machinery/hologram/projector, get_step(src.loc, NORTH))
return
return
/obj/machinery/computer/hologram_comp/DblClick()
if (!in_range(src, usr))
return 0
src.show_console(usr)
return
/obj/machinery/computer/hologram_comp/proc/render()
var/icon/I = new /icon('icons/mob/human.dmi', "body_m_s")
if (src.lumens >= 0)
I.Blend(rgb(src.lumens, src.lumens, src.lumens), ICON_ADD)
else
I.Blend(rgb(- src.lumens, -src.lumens, -src.lumens), ICON_SUBTRACT)
I.Blend(new /icon('icons/mob/human.dmi', "mouth_m_s"), ICON_OVERLAY)
I.Blend(new /icon('icons/mob/human.dmi', "underwear1_m_s"), ICON_OVERLAY)
var/icon/U = new /icon('icons/mob/human_face.dmi', "hair_a_s")
U.Blend(rgb(src.h_r, src.h_g, src.h_b), ICON_ADD)
I.Blend(U, ICON_OVERLAY)
src.projector.hologram.icon = I
/obj/machinery/computer/hologram_comp/proc/show_console(var/mob/user as mob)
var/dat
user.set_machine(src)
if (src.temp)
dat = text("[]<BR><BR><A href='?src=\ref[];temp=1'>Clear</A>", src.temp, src)
else
dat = text("<B>Hologram Status:</B><HR>\nPower: <A href='?src=\ref[];power=1'>[]</A><HR>\n<B>Hologram Control:</B><BR>\nColor Luminosity: []/220 <A href='?src=\ref[];reset=1'>\[Reset\]</A><BR>\nLighten: <A href='?src=\ref[];light=1'>1</A> <A href='?src=\ref[];light=10'>10</A><BR>\nDarken: <A href='?src=\ref[];light=-1'>1</A> <A href='?src=\ref[];light=-10'>10</A><BR>\n<BR>\nHair Color: ([],[],[]) <A href='?src=\ref[];h_reset=1'>\[Reset\]</A><BR>\nRed (0-255): <A href='?src=\ref[];h_r=-300'>\[0\]</A> <A href='?src=\ref[];h_r=-10'>-10</A> <A href='?src=\ref[];h_r=-1'>-1</A> [] <A href='?src=\ref[];h_r=1'>1</A> <A href='?src=\ref[];h_r=10'>10</A> <A href='?src=\ref[];h_r=300'>\[255\]</A><BR>\nGreen (0-255): <A href='?src=\ref[];h_g=-300'>\[0\]</A> <A href='?src=\ref[];h_g=-10'>-10</A> <A href='?src=\ref[];h_g=-1'>-1</A> [] <A href='?src=\ref[];h_g=1'>1</A> <A href='?src=\ref[];h_g=10'>10</A> <A href='?src=\ref[];h_g=300'>\[255\]</A><BR>\nBlue (0-255): <A href='?src=\ref[];h_b=-300'>\[0\]</A> <A href='?src=\ref[];h_b=-10'>-10</A> <A href='?src=\ref[];h_b=-1'>-1</A> [] <A href='?src=\ref[];h_b=1'>1</A> <A href='?src=\ref[];h_b=10'>10</A> <A href='?src=\ref[];h_b=300'>\[255\]</A><BR>", src, (src.projector.hologram ? "On" : "Off"), -src.lumens + 35, src, src, src, src, src, src.h_r, src.h_g, src.h_b, src, src, src, src, src.h_r, src, src, src, src, src, src, src.h_g, src, src, src, src, src, src, src.h_b, src, src, src)
user << browse(dat, "window=hologram_console")
onclose(user, "hologram_console")
return
/obj/machinery/computer/hologram_comp/Topic(href, href_list)
if(..())
return
if (in_range(src, usr))
flick("holo_console1", src)
if (href_list["power"])
if (src.projector.hologram)
src.projector.icon_state = "hologram0"
//src.projector.hologram = null
del(src.projector.hologram)
else
src.projector.hologram = new(src.projector.loc)
src.projector.hologram.icon = 'icons/mob/human.dmi'
src.projector.hologram.icon_state = "body_m_s"
src.projector.icon_state = "hologram1"
src.render()
else
if (href_list["h_r"])
if (src.projector.hologram)
src.h_r += text2num(href_list["h_r"])
src.h_r = min(max(src.h_r, 0), 255)
render()
else
if (href_list["h_g"])
if (src.projector.hologram)
src.h_g += text2num(href_list["h_g"])
src.h_g = min(max(src.h_g, 0), 255)
render()
else
if (href_list["h_b"])
if (src.projector.hologram)
src.h_b += text2num(href_list["h_b"])
src.h_b = min(max(src.h_b, 0), 255)
render()
else
if (href_list["light"])
if (src.projector.hologram)
src.lumens += text2num(href_list["light"])
src.lumens = min(max(src.lumens, -185.0), 35)
render()
else
if (href_list["reset"])
if (src.projector.hologram)
src.lumens = 0
render()
else
if (href_list["temp"])
src.temp = null
for(var/mob/M in viewers(1, src))
if ((M.client && M.machine == src))
src.show_console(M)
return

View File

@@ -94,6 +94,10 @@
secured_wires = 1
assembly_type = /obj/structure/door_assembly/door_assembly_highsecurity //Until somebody makes better sprites.
/obj/machinery/door/airlock/vault/bolted
icon_state = "door_locked"
locked = 1
/obj/machinery/door/airlock/freezer
name = "Freezer Airlock"
icon = 'icons/obj/doors/Doorfreezer.dmi'
@@ -1002,7 +1006,7 @@ About the new airlock wires panel:
if(operating || welded || locked)
return
if(!forced)
//despite the name, this wire is for general door control.
//despite the name, this wire is for general door control.
//Bolts are already covered by the check for locked, above
if( !arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_OPEN_DOOR) )
return

View File

@@ -24,10 +24,12 @@ Possible to do for anyone motivated enough:
* Holopad
*/
// HOLOPAD MODE
// 0 = RANGE BASED
// 1 = AREA BASED
var/const/HOLOPAD_MODE = 0
#define HOLOPAD_PASSIVE_POWER_USAGE 1
#define HOLOGRAM_POWER_USAGE 2
#define RANGE_BASED 4
#define AREA_BASED 6
var/const/HOLOPAD_MODE = RANGE_BASED
/obj/machinery/hologram/holopad
name = "\improper AI holopad"
@@ -36,7 +38,7 @@ var/const/HOLOPAD_MODE = 0
layer = TURF_LAYER+0.1 //Preventing mice and drones from sneaking under them.
var/mob/living/silicon/ai/master//Which AI, if any, is controlling the object? Only one AI may control a hologram at any time.
var/list/mob/living/silicon/ai/masters = new() //List of AIs that use the holopad
var/last_request = 0 //to prevent request spam. ~Carn
var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating.
@@ -62,52 +64,53 @@ var/const/HOLOPAD_MODE = 0
This may change in the future but for now will suffice.*/
if(user.eyeobj.loc != src.loc)//Set client eye on the object if it's not already.
user.eyeobj.setLoc(get_turf(src))
else if(!hologram)//If there is no hologram, possibly make one.
else if(!masters[user])//If there is no hologram, possibly make one.
activate_holo(user)
else if(master==user)//If there is a hologram, remove it. But only if the user is the master. Otherwise do nothing.
clear_holo()
else//If there is a hologram, remove it.
clear_holo(user)
return
/obj/machinery/hologram/holopad/proc/activate_holo(mob/living/silicon/ai/user)
if(!(stat & NOPOWER) && user.eyeobj.loc == src.loc)//If the projector has power and client eye is on it.
if(!hologram)//If there is not already a hologram.
create_holo(user)//Create one.
src.visible_message("A holographic image of [user] flicks to life right before your eyes!")
else
user << "\red ERROR: \black Image feed in progress."
if(!(stat & NOPOWER) && user.eyeobj.loc == src.loc)//If the projector has power and client eye is on it
if (user.holo)
user << "<span class='danger'>ERROR:</span> Image feed in progress."
return
create_holo(user)//Create one.
src.visible_message("A holographic image of [user] flicks to life right before your eyes!")
else
user << "\red ERROR: \black Unable to project hologram."
user << "<span class='danger'>ERROR:</span> Unable to project hologram."
return
/*This is the proc for special two-way communication between AI and holopad/people talking near holopad.
For the other part of the code, check silicon say.dm. Particularly robot talk.*/
/obj/machinery/hologram/holopad/hear_talk(mob/living/M, text, verb, datum/language/speaking)
if(M&&hologram&&master)//Master is mostly a safety in case lag hits or something.
if(!master.say_understands(M, speaking))//The AI will be able to understand most mobs talking through the holopad.
if(M)
for(var/mob/living/silicon/ai/master in masters)
if(!master.say_understands(M, speaking))//The AI will be able to understand most mobs talking through the holopad.
if(speaking)
text = speaking.scramble(text)
else
text = stars(text)
var/name_used = M.GetVoice()
//This communication is imperfect because the holopad "filters" voices and is only designed to connect to the master only.
var/rendered
if(speaking)
text = speaking.scramble(text)
rendered = "<i><span class='game say'>Holopad received, <span class='name'>[name_used]</span> [speaking.format_message(text, verb)]</span></i>"
else
text = stars(text)
var/name_used = M.GetVoice()
//This communication is imperfect because the holopad "filters" voices and is only designed to connect to the master only.
var/rendered
if(speaking)
rendered = "<i><span class='game say'>Holopad received, <span class='name'>[name_used]</span> [speaking.format_message(text, verb)]</span></i>"
else
rendered = "<i><span class='game say'>Holopad received, <span class='name'>[name_used]</span> [verb], <span class='message'>\"[text]\"</span></span></i>"
master.show_message(rendered, 2)
return
rendered = "<i><span class='game say'>Holopad received, <span class='name'>[name_used]</span> [verb], <span class='message'>\"[text]\"</span></span></i>"
master.show_message(rendered, 2)
/obj/machinery/hologram/holopad/see_emote(mob/living/M, text)
if(M && hologram && master)
//var/name_used = M.GetVoice()
var/rendered = "<i><span class='game say'>Holopad received, <span class='message'>[text]</span></span></i>"
//The lack of name_used is needed, because message already contains a name. This is needed for simple mobs to emote properly.
master.show_message(rendered, 2)
if(M)
for(var/mob/living/silicon/ai/master in masters)
//var/name_used = M.GetVoice()
var/rendered = "<i><span class='game say'>Holopad received, <span class='message'>[text]</span></span></i>"
//The lack of name_used is needed, because message already contains a name. This is needed for simple mobs to emote properly.
master.show_message(rendered, 2)
return
/obj/machinery/hologram/holopad/proc/create_holo(mob/living/silicon/ai/A, turf/T = loc)
hologram = new(T)//Spawn a blank effect at the location.
var/obj/effect/overlay/hologram = new(T)//Spawn a blank effect at the location.
hologram.icon = A.holo_icon
hologram.mouse_opacity = 0//So you can't click on it.
hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
@@ -115,32 +118,33 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
hologram.name = "[A.name] (Hologram)"//If someone decides to right click.
hologram.SetLuminosity(2) //hologram lighting
hologram.color = color //painted holopad gives coloured holograms
masters[A] = hologram
SetLuminosity(2) //pad lighting
icon_state = "holopad1"
A.holo = src
master = A//AI is the master.
use_power = 2//Active power usage.
use_power += HOLOGRAM_POWER_USAGE
return 1
/obj/machinery/hologram/holopad/proc/clear_holo()
// hologram.SetLuminosity(0)//Clear lighting. //handled by the lighting controller when its ower is deleted
del(hologram)//Get rid of hologram.
if(master.holo == src)
master.holo = null
master = null//Null the master, since no-one is using it now.
SetLuminosity(0) //pad lighting (hologram lighting will be handled automatically since its owner was deleted)
icon_state = "holopad0"
use_power = 1//Passive power usage.
/obj/machinery/hologram/holopad/proc/clear_holo(mob/living/silicon/ai/user)
if(user.holo == src)
user.holo = null
del(masters[user])//Get rid of user's hologram //qdel
masters -= user //Discard AI from the list of those who use holopad
use_power = max(HOLOPAD_PASSIVE_POWER_USAGE, use_power - HOLOGRAM_POWER_USAGE)//Reduce power usage
if (!masters.len)//If no users left
SetLuminosity(0) //pad lighting (hologram lighting will be handled automatically since its owner was deleted)
icon_state = "holopad0"
use_power = HOLOPAD_PASSIVE_POWER_USAGE
return 1
/obj/machinery/hologram/holopad/process()
if(hologram)//If there is a hologram.
for (var/mob/living/silicon/ai/master in masters)
if(master && !master.stat && master.client && master.eyeobj)//If there is an AI attached, it's not incapacitated, it has a client, and the client eye is centered on the projector.
if(!(stat & NOPOWER))//If the machine has power.
if((HOLOPAD_MODE == 0 && (get_dist(master.eyeobj, src) <= holo_range)))
if((HOLOPAD_MODE == RANGE_BASED && (get_dist(master.eyeobj, src) <= holo_range)))
return 1
else if (HOLOPAD_MODE == 1)
else if (HOLOPAD_MODE == AREA_BASED)
var/area/holo_area = get_area(src)
var/area/eye_area = get_area(master.eyeobj)
@@ -148,14 +152,15 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
if(eye_area in holo_area.master.related)
return 1
clear_holo()//If not, we want to get rid of the hologram.
clear_holo(master)//If not, we want to get rid of the hologram.
return 1
/obj/machinery/hologram/holopad/proc/move_hologram()
if(hologram)
step_to(hologram, master.eyeobj) // So it turns.
hologram.loc = get_turf(master.eyeobj)
/obj/machinery/hologram/holopad/proc/move_hologram(mob/living/silicon/ai/user)
if(masters[user])
step_to(masters[user], user.eyeobj) // So it turns.
var/obj/effect/overlay/H = masters[user]
H.loc = get_turf(user.eyeobj)
masters[user] = H
return 1
/*
@@ -167,7 +172,6 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
use_power = 1
idle_power_usage = 5
active_power_usage = 100
var/obj/effect/overlay/hologram//The projection itself. If there is one, the instrument is on, off otherwise.
//Destruction procs.
/obj/machinery/hologram/ex_act(severity)
@@ -190,9 +194,9 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
del(src)
return
/obj/machinery/hologram/Del()
if(hologram)
src:clear_holo()
/obj/machinery/hologram/holopad/Del()
for (var/mob/living/silicon/ai/master in masters)
clear_holo(master)
..()
/*
@@ -224,3 +228,9 @@ Holographic project of everything else.
desc = "It makes a hologram appear...with magnets or something..."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "hologram0"
#undef RANGE_BASED
#undef AREA_BASED
#undef HOLOPAD_PASSIVE_POWER_USAGE
#undef HOLOGRAM_POWER_USAGE

View File

@@ -248,7 +248,7 @@
throw_impact(atom/hit_atom)
if(primed)
explosion(hit_atom, 0, 0, 2, 4)
explosion(hit_atom, 0, 1, 2, 4)
del(src)
else
..()

View File

@@ -2,7 +2,7 @@
name = "flash"
desc = "Used for blinding and being an asshole."
icon_state = "flash"
item_state = "flashbang" //looks exactly like a flash (and nothing like a flashbang)
item_state = "flash"
throwforce = 5
w_class = 2.0
throw_speed = 4

View File

@@ -7,6 +7,13 @@
slot_flags = SLOT_BELT
attack_verb = list("whipped", "lashed", "disciplined")
/obj/item/weapon/storage/update_icon()
if (ismob(src.loc))
var/mob/M = src.loc
M.update_inv_belt()
/obj/item/weapon/storage/belt/utility
name = "tool-belt" //Carn: utility belt is nicer, but it bamboozles the text parsing.
desc = "Can hold various tools."
@@ -84,7 +91,7 @@
name = "security belt"
desc = "Can hold security gear like handcuffs and flashes."
icon_state = "securitybelt"
item_state = "security"//Could likely use a better one.
item_state = "security"
storage_slots = 7
max_w_class = 3
max_combined_w_class = 21

View File

@@ -20,7 +20,8 @@
// Calling Topic without a corresponding window open causes runtime errors
if(!nowindow && ..())
return 1
if(usr.can_interact_with_interface(src, checkrange) != STATUS_INTERACTIVE)
if(usr.can_interact_with_interface(nano_host(), checkrange) != STATUS_INTERACTIVE)
return 1
add_fingerprint(usr)
return 0

View File

@@ -0,0 +1,34 @@
/obj/structure/undies_wardrobe
name = "underwear wardrobe"
desc = "Holds item of clothing you shouldn't be showing off in the hallways."
icon = 'icons/obj/closet.dmi'
icon_state = "cabinet_closed"
/obj/structure/undies_wardrobe/attack_hand(mob/user as mob)
src.add_fingerprint(user)
var/mob/living/carbon/human/H = user
if(!ishuman(user) || (H.species && !(H.species.flags & HAS_UNDERWEAR)))
user << "<span class='warning'>Sadly there's nothing in here for you to wear.</span>"
return 0
var/utype = alert("Which section do you want to pick from?",,"Male underwear", "Female underwear", "Undershirts")
var/list/selection
switch(utype)
if("Male underwear")
selection = underwear_m
if("Female underwear")
selection = underwear_f
if("Undershirts")
selection = undershirt_t
var/pick = input("Select the style") as null|anything in selection
if(pick)
if(get_dist(src,user) > 1)
return
if(utype == "Undershirts")
H.undershirt = undershirt_t[pick]
else
H.underwear = selection[pick]
H.update_body(1)
return 1

View File

@@ -54,8 +54,8 @@ datum/preferences
var/age = 30 //age of character
var/spawnpoint = "Arrivals Shuttle" //where this character will spawn (0-2).
var/b_type = "A+" //blood type (not-chooseable)
var/underwear = 1 //underwear type
var/undershirt = 1 //undershirt type
var/underwear //underwear type
var/undershirt //undershirt type
var/backbag = 2 //backpack type
var/h_style = "Bald" //Hair type
var/r_hair = 0 //Hair color
@@ -373,12 +373,11 @@ datum/preferences
else
dat += "<br><br>"
if(gender == MALE)
dat += "Underwear: <a href ='?_src_=prefs;preference=underwear;task=input'><b>[underwear_m[underwear]]</b></a><br>"
else
dat += "Underwear: <a href ='?_src_=prefs;preference=underwear;task=input'><b>[underwear_f[underwear]]</b></a><br>"
var/list/undies = gender == MALE ? underwear_m : underwear_f
dat += "Undershirt: <a href='?_src_=prefs;preference=undershirt;task=input'><b>[undershirt_t[undershirt]]</b></a><br>"
dat += "Underwear: <a href ='?_src_=prefs;preference=underwear;task=input'><b>[get_key_by_value(undies,underwear)]</b></a><br>"
dat += "Undershirt: <a href='?_src_=prefs;preference=undershirt;task=input'><b>[get_key_by_value(undershirt_t,undershirt)]</b></a><br>"
dat += "Backpack Type:<br><a href ='?_src_=prefs;preference=bag;task=input'><b>[backbaglist[backbag]]</b></a><br>"
@@ -1178,10 +1177,12 @@ datum/preferences
if("f_style")
f_style = random_facial_hair_style(gender, species)
if("underwear")
underwear = rand(1,underwear_m.len)
var/r = pick(underwear_m)
underwear = underwear_m[r]
ShowChoices(user)
if("undershirt")
undershirt = rand(1,undershirt_t.len)
var/r = pick(undershirt_t)
undershirt = undershirt_t[r]
ShowChoices(user)
if("eyes")
r_eyes = rand(0,255)
@@ -1351,7 +1352,7 @@ datum/preferences
var/new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in underwear_options
if(new_underwear)
underwear = underwear_options.Find(new_underwear)
underwear = underwear_options[new_underwear]
ShowChoices(user)
if("undershirt")
@@ -1360,7 +1361,7 @@ datum/preferences
var/new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in undershirt_options
if (new_undershirt)
undershirt = undershirt_options.Find(new_undershirt)
undershirt = undershirt_options[new_undershirt]
ShowChoices(user)
if("eyes")
@@ -1705,12 +1706,8 @@ datum/preferences
else if(status == "mechanical")
I.mechanize()
if(underwear > underwear_m.len || underwear < 1)
underwear = 0 //I'm sure this is 100% unnecessary, but I'm paranoid... sue me. //HAH NOW NO MORE MAGIC CLONING UNDIES
character.underwear = underwear
if(undershirt > undershirt_t.len || undershirt < 1)
undershirt = 0
character.undershirt = undershirt
if(backbag > 4 || backbag < 1)

View File

@@ -191,6 +191,11 @@
if(isnull(species) || !(species in playable_species))
species = "Human"
if(isnum(underwear))
var/list/undies = gender == MALE ? underwear_m : underwear_f
underwear = undies[undies[underwear]]
if(isnum(undershirt))
undershirt = undershirt_t[undershirt_t[undershirt]]
if(isnull(language)) language = "None"
if(isnull(spawnpoint)) spawnpoint = "Arrivals Shuttle"

View File

@@ -38,9 +38,9 @@ emp_act
return -1 // complete projectile permutation
//Shrapnel
if (P.damage_type == BRUTE)
if (P.can_embed())
var/armor = getarmor_organ(organ, "bullet")
if((P.embed && prob(20 + max(P.damage - armor, -10))))
if(P.embed && prob(20 + max(P.damage - armor, -10)))
var/obj/item/weapon/shard/shrapnel/SP = new()
SP.name = (P.name != "shrapnel")? "[P.name] shrapnel" : "shrapnel"
SP.desc = "[SP.desc] It looks like it was fired from [P.shot_from]."

View File

@@ -326,7 +326,6 @@
if(istype(O)) O.add_autopsy_data("Radiation Poisoning", damage)
proc/breathe()
if(reagents.has_reagent("lexorin")) return
if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) return
if(species && (species.flags & NO_BREATHE || species.flags & IS_SYNTHETIC)) return
@@ -439,17 +438,15 @@
return
if(!breath || (breath.total_moles == 0) || suiciding)
failed_last_breath = 1
if(suiciding)
adjustOxyLoss(2)//If you are suiciding, you should die a little bit faster
failed_last_breath = 1
oxygen_alert = max(oxygen_alert, 1)
return 0
if(health > config.health_threshold_crit)
adjustOxyLoss(HUMAN_MAX_OXYLOSS)
failed_last_breath = 1
else
adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS)
failed_last_breath = 1
oxygen_alert = max(oxygen_alert, 1)

View File

@@ -376,12 +376,11 @@ proc/get_damage_icon_part(damage_state, body_part)
stand_icon.Blend(new/icon('icons/mob/human_face.dmi', "lips_[lip_style]_s"), ICON_OVERLAY)
//Underwear
if(underwear >0 && underwear < 12 && species.flags & HAS_UNDERWEAR)
if(!fat && !skeleton)
stand_icon.Blend(new /icon('icons/mob/human.dmi', "underwear[underwear]_[g]_s"), ICON_OVERLAY)
if(underwear && species.flags & HAS_UNDERWEAR)
stand_icon.Blend(new /icon('icons/mob/human.dmi', underwear), ICON_OVERLAY)
if(undershirt>0 && undershirt < 5 && species.flags & HAS_UNDERWEAR)
stand_icon.Blend(new /icon('icons/mob/human.dmi', "undershirt[undershirt]_s"), ICON_OVERLAY)
if(undershirt && species.flags & HAS_UNDERWEAR)
stand_icon.Blend(new /icon('icons/mob/human.dmi', undershirt), ICON_OVERLAY)
if(update_icons)
update_icons()
@@ -724,13 +723,22 @@ proc/get_damage_icon_part(damage_state, body_part)
belt.screen_loc = ui_belt //TODO
var/t_state = belt.item_state
if(!t_state) t_state = belt.icon_state
var/image/standing = image("icon_state" = "[t_state]")
if(belt.icon_override)
overlays_standing[BELT_LAYER] = image("icon" = belt.icon_override, "icon_state" = "[t_state]")
standing.icon = belt.icon_override
else if(belt.sprite_sheets && belt.sprite_sheets[species.name])
overlays_standing[BELT_LAYER] = image("icon" = belt.sprite_sheets[species.name], "icon_state" = "[t_state]")
standing.icon = belt.sprite_sheets[species.name]
else
overlays_standing[BELT_LAYER] = image("icon" = 'icons/mob/belt.dmi', "icon_state" = "[t_state]")
standing.icon = 'icons/mob/belt.dmi'
if(belt.contents.len && istype(belt, /obj/item/weapon/storage/belt))
for(var/obj/item/i in belt.contents)
var/i_state = i.item_state
if(!i_state) i_state = i.icon_state
standing.overlays += image("icon" = 'icons/mob/belt.dmi', "icon_state" = "[i_state]")
overlays_standing[BELT_LAYER] = standing
else
overlays_standing[BELT_LAYER] = null
if(update_icons) update_icons()

View File

@@ -23,7 +23,10 @@ var/list/ai_verbs_default = list(
/mob/living/silicon/ai/proc/sensor_mode,
/mob/living/silicon/ai/proc/show_laws_verb,
/mob/living/silicon/ai/proc/toggle_acceleration,
/mob/living/silicon/ai/proc/toggle_camera_light
/mob/living/silicon/ai/proc/toggle_camera_light,
/mob/living/silicon/ai/proc/nano_rcon,
/mob/living/silicon/ai/proc/nano_crew_monitor,
/mob/living/silicon/ai/proc/nano_power_monitor
)
//Not sure why this is necessary...
@@ -163,6 +166,8 @@ var/list/ai_verbs_default = list(
hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
init_subsystems()
ai_list += src
..()
return

View File

@@ -49,7 +49,7 @@
ai.client.eye = src
//Holopad
if(ai.holo)
ai.holo.move_hologram()
ai.holo.move_hologram(ai)
/mob/aiEye/proc/getLoc()

View File

@@ -0,0 +1,27 @@
var/obj/nano_module/crew_monitor/crew_monitor
var/obj/nano_module/rcon/rcon
var/obj/nano_module/power_monitor/power_monitor
/mob/living/silicon/ai/proc/init_subsystems()
crew_monitor = new(src)
rcon = new(src)
power_monitor = new(src)
/mob/living/silicon/ai/proc/nano_crew_monitor()
set category = "AI Subystems"
set name = "Crew Monitor"
crew_monitor.ui_interact(usr)
/mob/living/silicon/ai/proc/nano_power_monitor()
set category = "AI Subystems"
set name = "Power Monitor"
power_monitor.ui_interact(usr)
/mob/living/silicon/ai/proc/nano_rcon()
set category = "AI Subystems"
set name = "RCON"
rcon.ui_interact(usr)

View File

@@ -159,7 +159,7 @@
return
var/obj/machinery/hologram/holopad/T = src.holo
if(T && T.hologram && T.master == src)//If there is a hologram and its master is the user.
if(T && T.masters[src])//If there is a hologram and its master is the user.
//Human-like, sorta, heard by those who understand humans.
var/rendered_a
@@ -198,7 +198,7 @@
return
var/obj/machinery/hologram/holopad/T = src.holo
if(T && T.hologram && T.master == src)
if(T && T.masters[src])
var/rendered = "<span class='game say'><span class='name'>[name]</span> <span class='message'>[message]</span></span>"
src << "<i><span class='game say'>Holopad action relayed, <span class='name'>[real_name]</span> <span class='message'>[message]</span></span></i>"
@@ -211,7 +211,7 @@
/mob/living/silicon/ai/emote(var/act, var/type, var/message)
var/obj/machinery/hologram/holopad/T = src.holo
if(T && T.hologram && T.master == src) //Is the AI using a holopad?
if(T && T.masters[src]) //Is the AI using a holopad?
src.holopad_emote(message)
else //Emote normally, then.
..()

View File

@@ -240,12 +240,12 @@ datum/preferences
eyes_s.Blend(facial_s, ICON_OVERLAY)
var/icon/underwear_s = null
if(underwear > 0 && underwear < 7 && current_species.flags & HAS_UNDERWEAR)
underwear_s = new/icon("icon" = 'icons/mob/human.dmi', "icon_state" = "underwear[underwear]_[g]_s")
if(underwear && current_species.flags & HAS_UNDERWEAR)
underwear_s = new/icon("icon" = 'icons/mob/human.dmi', "icon_state" = underwear)
var/icon/undershirt_s = null
if(undershirt > 0 && undershirt < 5 && current_species.flags & HAS_UNDERWEAR)
undershirt_s = new/icon("icon" = 'icons/mob/human.dmi', "icon_state" = "undershirt[undershirt]_s")
if(undershirt && current_species.flags & HAS_UNDERWEAR)
undershirt_s = new/icon("icon" = 'icons/mob/human.dmi', "icon_state" = undershirt)
var/icon/clothes_s = null
if(job_civilian_low & ASSISTANT)//This gives the preview icon clothes depending on which job(if any) is set to 'high'

View File

@@ -0,0 +1,88 @@
/obj/nano_module/crew_monitor
name = "Crew monitor"
var/list/tracked = new
/obj/nano_module/crew_monitor/Topic(href, href_list)
if(..()) return
var/turf/T = get_turf(src)
if (!T || !(T.z in config.player_levels))
usr << "<span class='warning'>Unable to establish a connection<span>: You're too far away from the station!"
return 0
if(href_list["close"] )
var/mob/user = usr
var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main")
usr.unset_machine()
ui.close()
return 0
if(href_list["update"])
src.updateDialog()
return 1
/obj/nano_module/crew_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
user.set_machine(src)
src.scan()
var/data[0]
var/turf/T = get_turf(src)
var/list/crewmembers = list()
for(var/obj/item/clothing/under/C in src.tracked)
var/turf/pos = get_turf(C)
if((C) && (C.has_sensor) && (pos) && (T && pos.z == T.z) && (C.sensor_mode != SUIT_SENSOR_OFF))
if(istype(C.loc, /mob/living/carbon/human))
var/mob/living/carbon/human/H = C.loc
if(H.w_uniform != C)
continue
var/list/crewmemberData = list("dead"=0, "oxy"=-1, "tox"=-1, "fire"=-1, "brute"=-1, "area"="", "x"=-1, "y"=-1)
crewmemberData["sensor_type"] = C.sensor_mode
crewmemberData["name"] = H.get_authentification_name(if_no_id="Unknown")
crewmemberData["rank"] = H.get_authentification_rank(if_no_id="Unknown", if_no_job="No Job")
crewmemberData["assignment"] = H.get_assignment(if_no_id="Unknown", if_no_job="No Job")
if(C.sensor_mode >= SUIT_SENSOR_BINARY)
crewmemberData["dead"] = H.stat > 1
if(C.sensor_mode >= SUIT_SENSOR_VITAL)
crewmemberData["oxy"] = round(H.getOxyLoss(), 1)
crewmemberData["tox"] = round(H.getToxLoss(), 1)
crewmemberData["fire"] = round(H.getFireLoss(), 1)
crewmemberData["brute"] = round(H.getBruteLoss(), 1)
if(C.sensor_mode >= SUIT_SENSOR_TRACKING)
var/area/A = get_area(H)
crewmemberData["area"] = sanitize(A.name)
crewmemberData["x"] = pos.x
crewmemberData["y"] = pos.y
crewmembers[++crewmembers.len] = crewmemberData
crewmembers = sortByKey(crewmembers, "name")
data["crewmembers"] = crewmembers
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "crew_monitor.tmpl", "Crew Monitoring Computer", 900, 800)
// adding a template with the key "mapContent" enables the map ui functionality
ui.add_template("mapContent", "crew_monitor_map_content.tmpl")
// adding a template with the key "mapHeader" replaces the map header content
ui.add_template("mapHeader", "crew_monitor_map_header.tmpl")
ui.set_initial_data(data)
ui.open()
// should make the UI auto-update; doesn't seem to?
ui.set_auto_update(1)
/obj/nano_module/crew_monitor/proc/scan()
for(var/mob/living/carbon/human/H in mob_list)
if(istype(H.w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/C = H.w_uniform
if (C.has_sensor)
tracked |= C
return 1

View File

@@ -0,0 +1,58 @@
/obj/nano_module/power_monitor
name = "Power monitor"
var/list/grid_sensors
var/active_sensor = null //name_tag of the currently selected sensor
/obj/nano_module/power_monitor/New()
..()
refresh_sensors()
/obj/nano_module/power_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
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
// Build list of data from sensor readings.
for(var/obj/machinery/power/sensor/S in grid_sensors)
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 = nanomanager.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)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
// Proc: refresh_sensors()
// Parameters: None
// Description: Refreshes list of active sensors kept on this computer.
/obj/nano_module/power_monitor/proc/refresh_sensors()
grid_sensors = list()
var/turf/T = get_turf(src)
for(var/obj/machinery/power/sensor/S in machines)
if((T && S.loc.z == T.z) || (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
// 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.
/obj/nano_module/power_monitor/Topic(href, href_list)
if(..())
return
if( href_list["clear"] )
active_sensor = null
else if( href_list["setsensor"] )
active_sensor = href_list["setsensor"]

View File

@@ -0,0 +1,116 @@
/obj/nano_module/rcon
name = "RCON interface"
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
/obj/nano_module/rcon/ui_interact(mob/user, ui_key = "rcon", datum/nanoui/ui=null, force_open=1)
FindDevices() // Update our devices list
var/data[0]
// 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),
"output_set" = SMES.output_attempt,
"output_val" = round(SMES.output_level),
"output_load" = round(SMES.output_used),
"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 = nanomanager.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)
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.
/obj/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])", "SMES Input Power Control") as num
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])", "SMES Input Power Control") as num
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)
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
/obj/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.
/obj/nano_module/rcon/proc/FindDevices()
known_SMESs = new /list()
for(var/obj/machinery/power/smes/buildable/SMES in machines)
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.RCon_tag != "NO_TAG")
known_breakers.Add(breaker)

View File

@@ -1,249 +1,249 @@
// This is the window/UI manager for Nano UI
// There should only ever be one (global) instance of nanomanger
/datum/nanomanager
// a list of current open /nanoui UIs, grouped by src_object and ui_key
var/open_uis[0]
// a list of current open /nanoui UIs, not grouped, for use in processing
var/list/processing_uis = list()
// a list of asset filenames which are to be sent to the client on user logon
var/list/asset_files = list()
/**
* Create a new nanomanager instance.
* This proc generates a list of assets which are to be sent to each client on connect
*
* @return /nanomanager new nanomanager object
*/
/datum/nanomanager/New()
var/list/nano_asset_dirs = list(\
"nano/css/",\
"nano/images/",\
"nano/js/",\
"nano/templates/"\
)
var/list/filenames = null
for (var/path in nano_asset_dirs)
filenames = flist(path)
for(var/filename in filenames)
if(copytext(filename, length(filename)) != "/") // filenames which end in "/" are actually directories, which we want to ignore
if(fexists(path + filename))
asset_files.Add(fcopy_rsc(path + filename)) // add this file to asset_files for sending to clients when they connect
return
/**
* Get an open /nanoui ui for the current user, src_object and ui_key and try to update it with data
*
* @param user /mob The mob who opened/owns the ui
* @param src_object /obj|/mob The obj or mob which the ui belongs to
* @param ui_key string A string key used for the ui
* @param ui /datum/nanoui An existing instance of the ui (can be null)
* @param data list The data to be passed to the ui, if it exists
* @param force_open boolean The ui is being forced to (re)open, so close ui if it exists (instead of updating)
*
* @return /nanoui Returns the found ui, for null if none exists
*/
/datum/nanomanager/proc/try_update_ui(var/mob/user, src_object, ui_key, var/datum/nanoui/ui, data, var/force_open = 0)
if (isnull(ui)) // no ui has been passed, so we'll search for one
{
ui = get_open_ui(user, src_object, ui_key)
}
if (!isnull(ui))
// The UI is already open
if (!force_open)
ui.push_data(data)
return ui
else
//testing("nanomanager/try_update_ui mob [user.name] [src_object:name] [ui_key] [force_open] - forcing opening of ui")
ui.close()
return null
/**
* Get an open /nanoui ui for the current user, src_object and ui_key
*
* @param user /mob The mob who opened/owns the ui
* @param src_object /obj|/mob The obj or mob which the ui belongs to
* @param ui_key string A string key used for the ui
*
* @return /nanoui Returns the found ui, or null if none exists
*/
/datum/nanomanager/proc/get_open_ui(var/mob/user, src_object, ui_key)
var/src_object_key = "\ref[src_object]"
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open")
return null
else if (isnull(open_uis[src_object_key][ui_key]) || !istype(open_uis[src_object_key][ui_key], /list))
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open for this object")
return null
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
if (ui.user == user)
return ui
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - ui not found")
return null
/**
* Update all /nanoui uis attached to src_object
*
* @param src_object /obj|/mob The obj or mob which the uis are attached to
*
* @return int The number of uis updated
*/
/datum/nanomanager/proc/update_uis(src_object)
var/src_object_key = "\ref[src_object]"
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
return 0
var/update_count = 0
for (var/ui_key in open_uis[src_object_key])
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
if(ui && ui.src_object && ui.user)
ui.process(1)
update_count++
return update_count
/**
* Update /nanoui uis belonging to user
*
* @param user /mob The mob who owns the uis
* @param src_object /obj|/mob If src_object is provided, only update uis which are attached to src_object (optional)
* @param ui_key string If ui_key is provided, only update uis with a matching ui_key (optional)
*
* @return int The number of uis updated
*/
/datum/nanomanager/proc/update_user_uis(var/mob/user, src_object = null, ui_key = null)
if (isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
return 0 // has no open uis
var/update_count = 0
for (var/datum/nanoui/ui in user.open_uis)
if ((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
ui.process(1)
update_count++
return update_count
/**
* Close /nanoui uis belonging to user
*
* @param user /mob The mob who owns the uis
* @param src_object /obj|/mob If src_object is provided, only close uis which are attached to src_object (optional)
* @param ui_key string If ui_key is provided, only close uis with a matching ui_key (optional)
*
* @return int The number of uis closed
*/
/datum/nanomanager/proc/close_user_uis(var/mob/user, src_object = null, ui_key = null)
if (isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
//testing("nanomanager/close_user_uis mob [user.name] has no open uis")
return 0 // has no open uis
var/close_count = 0
for (var/datum/nanoui/ui in user.open_uis)
if ((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
ui.close()
close_count++
//testing("nanomanager/close_user_uis mob [user.name] closed [open_uis.len] of [close_count] uis")
return close_count
/**
* Add a /nanoui ui to the list of open uis
* This is called by the /nanoui open() proc
*
* @param ui /nanoui The ui to add
*
* @return nothing
*/
/datum/nanomanager/proc/ui_opened(var/datum/nanoui/ui)
var/src_object_key = "\ref[ui.src_object]"
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
open_uis[src_object_key] = list(ui.ui_key = list())
else if (isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list))
open_uis[src_object_key][ui.ui_key] = list();
ui.user.open_uis.Add(ui)
var/list/uis = open_uis[src_object_key][ui.ui_key]
uis.Add(ui)
processing_uis.Add(ui)
//testing("nanomanager/ui_opened mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
/**
* Remove a /nanoui ui from the list of open uis
* This is called by the /nanoui close() proc
*
* @param ui /nanoui The ui to remove
*
* @return int 0 if no ui was removed, 1 if removed successfully
*/
/datum/nanomanager/proc/ui_closed(var/datum/nanoui/ui)
var/src_object_key = "\ref[ui.src_object]"
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
return 0 // wasn't open
else if (isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list))
return 0 // wasn't open
processing_uis.Remove(ui)
ui.user.open_uis.Remove(ui)
var/list/uis = open_uis[src_object_key][ui.ui_key]
uis.Remove(ui)
//testing("nanomanager/ui_closed mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
return 1
/**
* This is called on user logout
* Closes/clears all uis attached to the user's /mob
*
* @param user /mob The user's mob
*
* @return nothing
*/
//
/datum/nanomanager/proc/user_logout(var/mob/user)
//testing("nanomanager/user_logout user [user.name]")
return close_user_uis(user)
/**
* This is called when a player transfers from one mob to another
* Transfers all open UIs to the new mob
*
* @param oldMob /mob The user's old mob
* @param newMob /mob The user's new mob
*
* @return nothing
*/
/datum/nanomanager/proc/user_transferred(var/mob/oldMob, var/mob/newMob)
//testing("nanomanager/user_transferred from mob [oldMob.name] to mob [newMob.name]")
if (isnull(oldMob.open_uis) || !istype(oldMob.open_uis, /list) || open_uis.len == 0)
//testing("nanomanager/user_transferred mob [oldMob.name] has no open uis")
return 0 // has no open uis
if (isnull(newMob.open_uis) || !istype(newMob.open_uis, /list))
newMob.open_uis = list()
for (var/datum/nanoui/ui in oldMob.open_uis)
ui.user = newMob
newMob.open_uis.Add(ui)
oldMob.open_uis.Cut()
return 1 // success
/**
* Sends all nano assets to the client
* This is called on user login
*
* @param client /client The user's client
*
* @return nothing
*/
/datum/nanomanager/proc/send_resources(client)
for(var/file in asset_files)
client << browse_rsc(file) // send the file to the client
// This is the window/UI manager for Nano UI
// There should only ever be one (global) instance of nanomanger
/datum/nanomanager
// a list of current open /nanoui UIs, grouped by src_object and ui_key
var/open_uis[0]
// a list of current open /nanoui UIs, not grouped, for use in processing
var/list/processing_uis = list()
// a list of asset filenames which are to be sent to the client on user logon
var/list/asset_files = list()
/**
* Create a new nanomanager instance.
* This proc generates a list of assets which are to be sent to each client on connect
*
* @return /nanomanager new nanomanager object
*/
/datum/nanomanager/New()
var/list/nano_asset_dirs = list(\
"nano/css/",\
"nano/images/",\
"nano/js/",\
"nano/templates/"\
)
var/list/filenames = null
for (var/path in nano_asset_dirs)
filenames = flist(path)
for(var/filename in filenames)
if(copytext(filename, length(filename)) != "/") // filenames which end in "/" are actually directories, which we want to ignore
if(fexists(path + filename))
asset_files.Add(fcopy_rsc(path + filename)) // add this file to asset_files for sending to clients when they connect
return
/**
* Get an open /nanoui ui for the current user, src_object and ui_key and try to update it with data
*
* @param user /mob The mob who opened/owns the ui
* @param src_object /obj|/mob The obj or mob which the ui belongs to
* @param ui_key string A string key used for the ui
* @param ui /datum/nanoui An existing instance of the ui (can be null)
* @param data list The data to be passed to the ui, if it exists
* @param force_open boolean The ui is being forced to (re)open, so close ui if it exists (instead of updating)
*
* @return /nanoui Returns the found ui, for null if none exists
*/
/datum/nanomanager/proc/try_update_ui(var/mob/user, src_object, ui_key, var/datum/nanoui/ui, data, var/force_open = 0)
if (isnull(ui)) // no ui has been passed, so we'll search for one
{
ui = get_open_ui(user, src_object, ui_key)
}
if (!isnull(ui))
// The UI is already open
if (!force_open)
ui.push_data(data)
return ui
else
//testing("nanomanager/try_update_ui mob [user.name] [src_object:name] [ui_key] [force_open] - forcing opening of ui")
ui.close()
return null
/**
* Get an open /nanoui ui for the current user, src_object and ui_key
*
* @param user /mob The mob who opened/owns the ui
* @param src_object /obj|/mob The obj or mob which the ui belongs to
* @param ui_key string A string key used for the ui
*
* @return /nanoui Returns the found ui, or null if none exists
*/
/datum/nanomanager/proc/get_open_ui(var/mob/user, src_object, ui_key)
var/src_object_key = "\ref[src_object]"
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open")
return null
else if (isnull(open_uis[src_object_key][ui_key]) || !istype(open_uis[src_object_key][ui_key], /list))
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open for this object")
return null
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
if (ui.user == user)
return ui
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - ui not found")
return null
/**
* Update all /nanoui uis attached to src_object
*
* @param src_object /obj|/mob The obj or mob which the uis are attached to
*
* @return int The number of uis updated
*/
/datum/nanomanager/proc/update_uis(src_object)
var/src_object_key = "\ref[src_object]"
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
return 0
var/update_count = 0
for (var/ui_key in open_uis[src_object_key])
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
if(ui && ui.src_object && ui.user && ui.src_object.nano_host())
ui.process(1)
update_count++
return update_count
/**
* Update /nanoui uis belonging to user
*
* @param user /mob The mob who owns the uis
* @param src_object /obj|/mob If src_object is provided, only update uis which are attached to src_object (optional)
* @param ui_key string If ui_key is provided, only update uis with a matching ui_key (optional)
*
* @return int The number of uis updated
*/
/datum/nanomanager/proc/update_user_uis(var/mob/user, src_object = null, ui_key = null)
if (isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
return 0 // has no open uis
var/update_count = 0
for (var/datum/nanoui/ui in user.open_uis)
if ((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
ui.process(1)
update_count++
return update_count
/**
* Close /nanoui uis belonging to user
*
* @param user /mob The mob who owns the uis
* @param src_object /obj|/mob If src_object is provided, only close uis which are attached to src_object (optional)
* @param ui_key string If ui_key is provided, only close uis with a matching ui_key (optional)
*
* @return int The number of uis closed
*/
/datum/nanomanager/proc/close_user_uis(var/mob/user, src_object = null, ui_key = null)
if (isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
//testing("nanomanager/close_user_uis mob [user.name] has no open uis")
return 0 // has no open uis
var/close_count = 0
for (var/datum/nanoui/ui in user.open_uis)
if ((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
ui.close()
close_count++
//testing("nanomanager/close_user_uis mob [user.name] closed [open_uis.len] of [close_count] uis")
return close_count
/**
* Add a /nanoui ui to the list of open uis
* This is called by the /nanoui open() proc
*
* @param ui /nanoui The ui to add
*
* @return nothing
*/
/datum/nanomanager/proc/ui_opened(var/datum/nanoui/ui)
var/src_object_key = "\ref[ui.src_object]"
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
open_uis[src_object_key] = list(ui.ui_key = list())
else if (isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list))
open_uis[src_object_key][ui.ui_key] = list();
ui.user.open_uis.Add(ui)
var/list/uis = open_uis[src_object_key][ui.ui_key]
uis.Add(ui)
processing_uis.Add(ui)
//testing("nanomanager/ui_opened mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
/**
* Remove a /nanoui ui from the list of open uis
* This is called by the /nanoui close() proc
*
* @param ui /nanoui The ui to remove
*
* @return int 0 if no ui was removed, 1 if removed successfully
*/
/datum/nanomanager/proc/ui_closed(var/datum/nanoui/ui)
var/src_object_key = "\ref[ui.src_object]"
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
return 0 // wasn't open
else if (isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list))
return 0 // wasn't open
processing_uis.Remove(ui)
ui.user.open_uis.Remove(ui)
var/list/uis = open_uis[src_object_key][ui.ui_key]
uis.Remove(ui)
//testing("nanomanager/ui_closed mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
return 1
/**
* This is called on user logout
* Closes/clears all uis attached to the user's /mob
*
* @param user /mob The user's mob
*
* @return nothing
*/
//
/datum/nanomanager/proc/user_logout(var/mob/user)
//testing("nanomanager/user_logout user [user.name]")
return close_user_uis(user)
/**
* This is called when a player transfers from one mob to another
* Transfers all open UIs to the new mob
*
* @param oldMob /mob The user's old mob
* @param newMob /mob The user's new mob
*
* @return nothing
*/
/datum/nanomanager/proc/user_transferred(var/mob/oldMob, var/mob/newMob)
//testing("nanomanager/user_transferred from mob [oldMob.name] to mob [newMob.name]")
if (isnull(oldMob.open_uis) || !istype(oldMob.open_uis, /list) || open_uis.len == 0)
//testing("nanomanager/user_transferred mob [oldMob.name] has no open uis")
return 0 // has no open uis
if (isnull(newMob.open_uis) || !istype(newMob.open_uis, /list))
newMob.open_uis = list()
for (var/datum/nanoui/ui in oldMob.open_uis)
ui.user = newMob
newMob.open_uis.Add(ui)
oldMob.open_uis.Cut()
return 1 // success
/**
* Sends all nano assets to the client
* This is called on user login
*
* @param client /client The user's client
*
* @return nothing
*/
/datum/nanomanager/proc/send_resources(client)
for(var/file in asset_files)
client << browse_rsc(file) // send the file to the client

View File

@@ -0,0 +1,11 @@
/atom/movable/proc/nano_host()
return src
/obj/nano_module/nano_host()
return loc
/atom/movable/proc/nano_can_update()
return 1
/obj/machinery/nano_can_update()
return !(stat & (NOPOWER|BROKEN))

View File

@@ -132,7 +132,12 @@ nanoui is used to open and update nano browser uis
* @return nothing
*/
/datum/nanoui/proc/update_status(var/push_update = 0)
var/status = user.can_interact_with_interface(src_object)
var/atom/movable/host = src_object.nano_host()
if(!host.nano_can_update())
close()
return
var/status = user.can_interact_with_interface(host.nano_host())
if(status == STATUS_CLOSE)
close()
else
@@ -181,7 +186,7 @@ nanoui is used to open and update nano browser uis
return STATUS_UPDATE
/mob/living/silicon/ai/can_interact_with_interface(var/src_object)
if(stat || !client)
if(!client || check_unable(1))
return STATUS_CLOSE
// Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras)
// unless it's on the same level as the object it's interacting with.

View File

@@ -16,12 +16,11 @@
density = 1
anchored = 1.0
circuit = /obj/item/weapon/circuitboard/powermonitor
var/list/grid_sensors
var/alerting = 0
var/active_sensor = null //name_tag of the currently selected sensor
use_power = 1
idle_power_usage = 300
active_power_usage = 300
var/obj/nano_module/power_monitor/power_monitor
// Proc: process()
// Parameters: None
@@ -53,19 +52,7 @@
/obj/machinery/computer/power_monitor/New()
..()
spawn(50)
refresh_sensors()
// Proc: refresh_sensors()
// Parameters: None
// Description: Refreshes list of active sensors kept on this computer.
/obj/machinery/computer/power_monitor/proc/refresh_sensors()
grid_sensors = list()
for(var/obj/machinery/power/sensor/S in machines)
if((S.loc.z == src.loc.z) || (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
power_monitor = new(src)
// Proc: attack_hand()
// Parameters: None
@@ -77,50 +64,18 @@
return
ui_interact(user)
// 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.
/obj/machinery/computer/power_monitor/Topic(href, href_list)
..()
if( href_list["clear"] )
active_sensor = null
else if( href_list["setsensor"] )
active_sensor = href_list["setsensor"]
// Proc: ui_interact()
// Parameters: 4 (standard NanoUI parameters)
// Description: 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)
// Proc: check_warnings()
// Parameters: None
// Description: Verifies if any warnings were registered by connected sensors.
/obj/machinery/computer/power_monitor/proc/check_warnings()
for(var/obj/machinery/power/sensor/S in grid_sensors)
for(var/obj/machinery/power/sensor/S in power_monitor.grid_sensors)
if(S.check_grid_warning())
return 1
return 0
// Proc: ui_interact()
// Parameters: 4 (standard NanoUI parameters)
// Description: 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)
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
// Build list of data from sensor readings.
for(var/obj/machinery/power/sensor/S in grid_sensors)
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 = nanomanager.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)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)

View File

@@ -318,14 +318,14 @@
// Parameters: None
// Description: Switches the input on/off depending on previous setting
/obj/machinery/power/smes/buildable/proc/toggle_input()
input_attempt = !input_attempt
inputting(!input_attempt)
update_icon()
// Proc: toggle_output()
// Parameters: None
// Description: Switches the output on/off depending on previous setting
/obj/machinery/power/smes/buildable/proc/toggle_output()
output_attempt = !output_attempt
outputting(!output_attempt)
update_icon()
// Proc: set_input()

View File

@@ -258,6 +258,10 @@
accuracy = scoped_accuracy + scoped_accuracy_mod
if(recoil)
recoil = round(recoil*zoom_amount+1) //recoil is worse when looking through a scope
else
accuracy = (accuracy)
//make sure accuracy and recoil are reset regardless of how the item is unzoomed.
/obj/item/weapon/gun/zoom()
..()
if(!zoom)
accuracy = initial(accuracy)
recoil = initial(recoil)

View File

@@ -1,7 +1,6 @@
/obj/item/weapon/gun/launcher
name = "launcher"
desc = "A device that launches things."
icon = 'icons/obj/weapons.dmi'
w_class = 5.0
flags = CONDUCT
slot_flags = SLOT_BACK

View File

@@ -48,6 +48,7 @@
/obj/item/weapon/gun/launcher/crossbow
name = "powered crossbow"
desc = "A 2557AD twist on an old classic. Pick up that can."
icon = 'icons/obj/weapons.dmi'
icon_state = "crossbow"
item_state = "crossbow-solid"
fire_sound = 'sound/weapons/punchmiss.ogg' // TODO: Decent THWOK noise.

View File

@@ -1,7 +1,6 @@
/obj/item/weapon/gun/launcher/grenade
name = "grenade launcher"
desc = "A bulky pump-action grenade launcher. Holds up to 5 grenades in a revolving magazine."
icon = 'icons/obj/gun.dmi'
icon_state = "riotgun"
item_state = "riotgun"
w_class = 4

View File

@@ -1,7 +1,6 @@
/obj/item/weapon/gun/launcher/pneumatic
name = "pneumatic cannon"
desc = "A large gas-powered cannon."
icon = 'icons/obj/gun.dmi'
icon_state = "pneumatic"
item_state = "pneumatic"
slot_flags = SLOT_BELT

View File

@@ -61,7 +61,6 @@
/obj/item/weapon/gun/launcher/syringe
name = "syringe gun"
desc = "A spring loaded rifle designed to fit syringes, designed to incapacitate unruly patients from a distance."
icon = 'icons/obj/gun.dmi'
icon_state = "syringegun"
item_state = "syringegun"
w_class = 3

View File

@@ -26,6 +26,10 @@
var/obj/item/ammo_magazine/ammo_magazine = null //stored magazine
var/auto_eject = 0 //if the magazine should automatically eject itself when empty.
var/auto_eject_sound = null
//TODO generalize ammo icon states for guns
//var/magazine_states = 0
//var/list/icon_keys = list() //keys
//var/list/ammo_states = list() //values
/obj/item/weapon/gun/projectile/New()
..()
@@ -37,8 +41,7 @@
update_icon()
/obj/item/weapon/gun/projectile/consume_next_projectile()
//store the next ammo_casing in a var so that handle_post_fire() knows which one to eject
//also we might as well remove chambered here, so that we don't have to figure out where it came from later
//get the next casing
if(loaded.len)
chambered = loaded[1] //load next casing.
if(handle_casings != HOLD_CASINGS)
@@ -47,25 +50,36 @@
chambered = ammo_magazine.stored_ammo[1]
if(handle_casings != HOLD_CASINGS)
ammo_magazine.stored_ammo -= chambered
return chambered.BB
if (chambered)
return chambered.BB
return null
/obj/item/weapon/gun/projectile/handle_post_fire()
..()
if(chambered)
chambered.expend()
//check chambered again in case it deleted itself
if(chambered && handle_casings != HOLD_CASINGS)
switch(handle_casings)
if(EJECT_CASINGS) //eject casing onto ground.
chambered.loc = get_turf(src)
if(CYCLE_CASINGS) //cycle the casing back to the end.
if(ammo_magazine)
ammo_magazine.stored_ammo += chambered
else
loaded += chambered
process_chambered()
/obj/item/weapon/gun/projectile/handle_click_empty()
..()
process_chambered()
/obj/item/weapon/gun/projectile/proc/process_chambered()
if (!chambered) return
switch(handle_casings)
if(EJECT_CASINGS) //eject casing onto ground.
chambered.loc = get_turf(src)
if(CYCLE_CASINGS) //cycle the casing back to the end.
if(ammo_magazine)
ammo_magazine.stored_ammo += chambered
else
loaded += chambered
if(handle_casings != HOLD_CASINGS)
chambered = null
//Attempts to load A into src, depending on the type of thing being loaded and the load_method
//Maybe this should be broken up into separate procs for each load method?
@@ -118,7 +132,6 @@
update_icon()
//attempts to unload src. If allow_dump is set to 0, the speedloader unloading method will be disabled
/obj/item/weapon/gun/projectile/proc/unload_ammo(mob/user, var/allow_dump=1)
if(ammo_magazine)
@@ -170,8 +183,9 @@
)
if(auto_eject_sound)
playsound(user, auto_eject_sound, 40, 1)
ammo_magazine.update_icon()
ammo_magazine = null
update_icon()
update_icon() //make sure to do this after unsetting ammo_magazine
/obj/item/weapon/gun/projectile/examine(mob/user)
..(user)

View File

@@ -42,13 +42,13 @@
/obj/item/weapon/gun/projectile/automatic/c20r/update_icon()
..()
if(ammo_magazine)
icon_state = "c20r-[round(loaded.len,4)]"
icon_state = "c20r-[round(ammo_magazine.stored_ammo.len,4)]"
else
icon_state = "c20r"
return
/obj/item/weapon/gun/projectile/automatic/sts35
name = "\improper STS-35 Automatic Rifle"
name = "\improper STS-35 automatic rifle"
desc = "A durable, rugged looking automatic weapon of make popular on the frontier, despite it's bulk. Uses 7.62mm rounds. It is unmarked."
icon_state = "assltrifle"
item_state = "shotgun"
@@ -88,7 +88,7 @@
update_icon()
/obj/item/weapon/gun/projectile/automatic/l6_saw/update_icon()
icon_state = "l6[cover_open ? "open" : "closed"][ammo_magazine ? round(loaded.len, 25) : "-empty"]"
icon_state = "l6[cover_open ? "open" : "closed"][ammo_magazine ? round(ammo_magazine.stored_ammo.len, 25) : "-empty"]"
/obj/item/weapon/gun/projectile/automatic/l6_saw/special_check(mob/user)
if(cover_open)
@@ -102,7 +102,7 @@
return
..()
/obj/item/weapon/gun/projectile/automatic/l6_saw/unload_ammo(mob/user)
/obj/item/weapon/gun/projectile/automatic/l6_saw/unload_ammo(mob/user, var/allow_dump=1)
if(!cover_open)
return
..()
..()

View File

@@ -1,8 +1,8 @@
/obj/item/weapon/gun/projectile/heavysniper
name = "\improper PTRS-7 rifle"
desc = "A portable anti-armour rifle fitted with a scope. Originally designed to used against lightly armoured exosuits, it is capable of punching through non-reinforced walls with ease. Fires 14.5mm AP shells."
desc = "A portable anti-armour rifle fitted with a scope. Originally designed to used against armoured exosuits, it is capable of punching through non-reinforced walls with ease. Fires 14.5mm AP shells."
icon_state = "heavysniper"
item_state = "sniper0"
item_state = "shotgun"
w_class = 4
force = 10
slot_flags = SLOT_BACK

View File

@@ -65,8 +65,19 @@
/obj/item/projectile/proc/on_impact(var/atom/A)
return
//Checks if the projectile is eligible for embedding. Not that it necessarily will.
//Mainly used to ensure that projectiles won't embed if they are penetrating the mob.
/obj/item/projectile/proc/can_embed()
//embed must be enabled and damage type must be brute
if(!embed || damage_type != BRUTE)
return 0
//can't embed if the projectile is penetrating through the mob
if(penetrating > 0 && damage > 20 && prob(damage))
return 0
return 1
//return 1 if the projectile should be allowed to pass through after all, 0 if not.
/obj/item/projectile/proc/on_penetrate(var/atom/A)
/obj/item/projectile/proc/check_penetrate(var/atom/A)
return 1
/obj/item/projectile/proc/check_fire(atom/target as mob, var/mob/living/user as mob) //Checks if you can hit them or not.
@@ -174,7 +185,7 @@
loc = A.loc
return 0 //cannot shoot yourself
if(bumped)
if(bumped || (A in permutated))
return 0
var/passthrough = 0 //if the projectile should continue flying
@@ -195,20 +206,22 @@
for(var/mob/M in A)
attack_mob(M, distance)
//penetrating projectiles can pass through things that otherwise would not let them
if(penetrating > 0)
if(on_penetrate(A))
//penetrating projectiles can pass through things that otherwise would not let them
if(!passthrough && penetrating > 0)
if(check_penetrate(A))
passthrough = 1
penetrating--
//the bullet passes through a dense object!
if(passthrough)
//move ourselves onto A so we can continue on our way.
if(A)
if(istype(A, /turf))
loc = A
else
loc = A.loc
permutated.Add(A)
bumped = 0 //reset bumped variable!
if(istype(A, /turf))
loc = A
else
loc = A.loc
permutated.Add(A)
return 0
//stop flying
@@ -298,4 +311,4 @@
trace.firer = user
var/output = trace.process() //Test it!
del(trace) //No need for it anymore
return output //Send it back to the gun!
return output //Send it back to the gun!

View File

@@ -13,16 +13,17 @@
var/mob/living/L = target
shake_camera(L, 3, 2)
/obj/item/projectile/bullet/on_penetrate(var/atom/A)
if(!A) return 1 //if whatever it was got destroyed when we hit it, then I guess we can just keep going
/obj/item/projectile/bullet/check_penetrate(var/atom/A)
if(!A || !A.density) return 1 //if whatever it was got destroyed when we hit it, then I guess we can just keep going
if(istype(A, /obj/mecha))
return 1 //mecha have their own penetration handling
if(ismob(A))
if(iscarbon(A))
if (damage <= 20 && !prob(damage)) return 0
damage *= 0.7 //squishy mobs absorb KE
//squishy mobs absorb KE
if(can_embed()) return 0
damage *= 0.7
return 1
var/chance = 0
@@ -35,7 +36,7 @@
else if(istype(A, /obj/structure/girder) || istype(A, /obj/structure/cultgirder))
chance = 100
else if(istype(A, /obj/machinery) || istype(A, /obj/structure))
chance = 15
chance = 25
if(prob(chance))
if(A.opacity)

View File

@@ -1702,8 +1702,8 @@ datum
if(!M) M = holder.my_atom
if(prob(33))
M.take_organ_damage(1*REM, 0)
M.adjustOxyLoss(3)
if(prob(20)) M.emote("gasp")
if(M.losebreath < 15)
M.losebreath++
..()
return