mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2026-01-09 08:53:08 +00:00
Merge branch 'dev' of https://github.com/Baystation12/Baystation12 into xenohydro
This commit is contained in:
@@ -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")
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
..()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
34
code/game/objects/structures/under_wardrobe.dm
Normal file
34
code/game/objects/structures/under_wardrobe.dm
Normal 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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]."
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
27
code/modules/mob/living/silicon/ai/nano.dm
Normal file
27
code/modules/mob/living/silicon/ai/nano.dm
Normal 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)
|
||||
@@ -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.
|
||||
..()
|
||||
|
||||
@@ -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'
|
||||
|
||||
88
code/modules/nano/modules/crew_monitor.dm
Normal file
88
code/modules/nano/modules/crew_monitor.dm
Normal 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
|
||||
58
code/modules/nano/modules/power_monitor.dm
Normal file
58
code/modules/nano/modules/power_monitor.dm
Normal 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"]
|
||||
116
code/modules/nano/modules/rcon.dm
Normal file
116
code/modules/nano/modules/rcon.dm
Normal 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)
|
||||
@@ -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
|
||||
|
||||
|
||||
11
code/modules/nano/nanoprocs.dm
Normal file
11
code/modules/nano/nanoprocs.dm
Normal 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))
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
..()
|
||||
..()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user