diff --git a/aurorastation.dme b/aurorastation.dme
index fe182738c74..03d835bbfc5 100644
--- a/aurorastation.dme
+++ b/aurorastation.dme
@@ -1289,6 +1289,7 @@
#include "code\modules\client\preference_setup\loadout\loadout_gloves.dm"
#include "code\modules\client\preference_setup\loadout\loadout_head.dm"
#include "code\modules\client\preference_setup\loadout\loadout_mask.dm"
+#include "code\modules\client\preference_setup\loadout\loadout_religion.dm"
#include "code\modules\client\preference_setup\loadout\loadout_shoes.dm"
#include "code\modules\client\preference_setup\loadout\loadout_smoking.dm"
#include "code\modules\client\preference_setup\loadout\loadout_suit.dm"
@@ -2025,6 +2026,7 @@
#include "code\modules\modular_computers\file_system\programs\research\ntmonitor.dm"
#include "code\modules\modular_computers\file_system\programs\security\camera.dm"
#include "code\modules\modular_computers\file_system\programs\security\digitalwarrant.dm"
+#include "code\modules\modular_computers\file_system\programs\security\penalmechs.dm"
#include "code\modules\modular_computers\file_system\programs\system\client_manager.dm"
#include "code\modules\modular_computers\file_system\programs\system\configurator.dm"
#include "code\modules\modular_computers\file_system\programs\system\file_browser.dm"
diff --git a/code/__defines/machinery.dm b/code/__defines/machinery.dm
index 7fc1aaad4b0..3ccef65d0ef 100644
--- a/code/__defines/machinery.dm
+++ b/code/__defines/machinery.dm
@@ -45,6 +45,7 @@
#define NETWORK_ENGINEERING_OUTPOST "Engineering Outpost"
#define NETWORK_ERT "ZeEmergencyResponseTeam"
#define NETWORK_STATION "Station"
+#define NETWORK_MECHS "Mechs"
#define NETWORK_MEDICAL "Medical"
#define NETWORK_MERCENARY "MercurialNet"
#define NETWORK_MINE "MINE"
diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm
index 56629989b3d..b92a5f358e3 100644
--- a/code/__defines/misc.dm
+++ b/code/__defines/misc.dm
@@ -53,14 +53,13 @@
#define CHAT_GHOSTRADIO 0x2000
#define SHOW_TYPING 0x4000
#define CHAT_NOICONS 0x8000
-#define CHAT_AOOC 0x10000
#define PARALLAX_SPACE 0x1
#define PARALLAX_DUST 0x2
#define PROGRESS_BARS 0x4
#define PARALLAX_IS_STATIC 0x8
-#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_ATTACKLOGS|CHAT_LOOC|CHAT_AOOC)
+#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_ATTACKLOGS|CHAT_LOOC)
//Sound effects toggles
#define ASFX_AMBIENCE 1
@@ -111,7 +110,7 @@
#define MAX_PAPER_MESSAGE_LEN 3072
#define MAX_BOOK_MESSAGE_LEN 9216
#define MAX_LNAME_LEN 64
-#define MAX_NAME_LEN 26
+#define MAX_NAME_LEN 63
// Event defines.
#define EVENT_LEVEL_MUNDANE 1
diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm
index 36a0f6ccc70..3fedc45b938 100644
--- a/code/__defines/mobs.dm
+++ b/code/__defines/mobs.dm
@@ -47,6 +47,15 @@
#define GETPULSE_TOOL 1 // More accurate. (med scanner, sleeper, etc.)
#define PULSE_MAX_BPM 250 // Highest, readable BPM by machines and humans.
+// Blood pressure levels, simplified
+#define BP_HIGH_SYSTOLIC 140
+#define BP_PRE_HIGH_SYSTOLIC 125
+#define BP_IDEAL_SYSTOLIC 80
+
+#define BP_HIGH_DIASTOLIC 100
+#define BP_PRE_HIGH_DIASTOLIC 85
+#define BP_IDEAL_DIASTOLIC 60
+
//intent flags, why wasn't this done the first time?
#define I_HELP "help"
#define I_DISARM "disarm"
diff --git a/code/controllers/subsystems/virtual_reality.dm b/code/controllers/subsystems/virtual_reality.dm
index fc791df8dc5..02c8ae7ad33 100644
--- a/code/controllers/subsystems/virtual_reality.dm
+++ b/code/controllers/subsystems/virtual_reality.dm
@@ -10,7 +10,7 @@
var/list/mechs = list() // A list of lists, containing the mechs and their networks
// IPC BODIES
- var/list/robotnetworks = list("remoterobots", "bunkerrobots")
+ var/list/robotnetworks = list("remoterobots", "bunkerrobots", "prisonrobots")
var/list/robots = list()
/datum/controller/subsystem/virtualreality/New()
diff --git a/code/datums/repositories/crew.dm b/code/datums/repositories/crew.dm
index b1a6a5d5b67..07d70649f8c 100644
--- a/code/datums/repositories/crew.dm
+++ b/code/datums/repositories/crew.dm
@@ -49,17 +49,25 @@ var/global/datum/repository/crew/crew_repository = new()
if(C.sensor_mode >= SUIT_SENSOR_BINARY)
crewmemberData["pulse"] = "N/A"
crewmemberData["tpulse"] = -1
- if(!H.isSynthetic() && H.should_have_organ(BP_HEART))
- var/obj/item/organ/internal/heart/O = H.internal_organs_by_name[BP_HEART]
- if (!O || !BP_IS_ROBOTIC(O)) // Don't make medical freak out over prosthetic hearts
- crewmemberData["tpulse"] = H.pulse()
- crewmemberData["pulse"] = H.get_pulse(GETPULSE_TOOL)
+ crewmemberData["cellCharge"] = -1
+ if(!H.isSynthetic())
+ if(H.should_have_organ(BP_HEART))
+ var/obj/item/organ/internal/heart/O = H.internal_organs_by_name[BP_HEART]
+ if (!O || !BP_IS_ROBOTIC(O)) // Don't make medical freak out over prosthetic hearts
+ crewmemberData["tpulse"] = H.pulse()
+ crewmemberData["pulse"] = H.get_pulse(GETPULSE_TOOL)
+ else
+ if(isipc(H) && H.internal_organs_by_name[BP_IPCTAG]) // Don't make untagged IPCs obvious
+ var/obj/item/organ/internal/cell/cell = H.internal_organs_by_name[BP_CELL]
+ if(cell)
+ crewmemberData["cellCharge"] = Floor(100*H.nutrition / H.max_nutrition)
if(C.sensor_mode >= SUIT_SENSOR_VITAL)
crewmemberData["pressure"] = "N/A"
crewmemberData["toxyg"] = -1
crewmemberData["oxyg"] = OXYGENATION_STATE_UNDEFINED
if(!H.isSynthetic() && H.should_have_organ(BP_HEART))
+ crewmemberData["tpressure"] = H.get_blood_pressure_alert()
crewmemberData["pressure"] = H.get_blood_pressure()
crewmemberData["toxyg"] = H.get_blood_oxygenation()
switch (crewmemberData["toxyg"])
diff --git a/code/game/gamemodes/changeling/helpers/_store.dm b/code/game/gamemodes/changeling/helpers/_store.dm
index 97e23dea1cf..cafa36bb974 100644
--- a/code/game/gamemodes/changeling/helpers/_store.dm
+++ b/code/game/gamemodes/changeling/helpers/_store.dm
@@ -18,15 +18,9 @@ var/list/datum/power/changeling/powerinstances = list()
/datum/power/changeling/absorb_dna
name = "Absorb DNA"
- desc = "Permits us to syphon some of the DNA from a another sentient creature. They will take some toxin damage as a result of our extraction. Does not work on other changelings."
- genomecost = 0
- verbpath = /mob/proc/changeling_absorb_dna
-
-/datum/power/changeling/extract_dna
- name = "Full DNA Extraction"
desc = "Permits us to forcibly absorb a massive quantity DNA from another sentient creature. They will perish during the process, and we become stronger, especially if they were another changeling. Have caution, this takes some time."
genomecost = 0
- verbpath = /mob/proc/changeling_extract_dna
+ verbpath = /mob/proc/changeling_absorb_dna
//Transformation
diff --git a/code/game/gamemodes/changeling/implements/powers/body.dm b/code/game/gamemodes/changeling/implements/powers/body.dm
index e8aaed52988..c3b299b45d5 100644
--- a/code/game/gamemodes/changeling/implements/powers/body.dm
+++ b/code/game/gamemodes/changeling/implements/powers/body.dm
@@ -471,6 +471,7 @@
flick("summoning", effect)
QDEL_IN(effect, 10)
M.forceMove(ling) //move inside the new dude to hide him.
+ ling.occupant = M
M.status_flags |= GODMODE //dont want him to die or breathe or do ANYTHING
addtimer(CALLBACK(src, .proc/revert_horror_form,ling), 10 MINUTES)
diff --git a/code/game/gamemodes/changeling/implements/powers/suck.dm b/code/game/gamemodes/changeling/implements/powers/suck.dm
index b1c19671af8..f1711d8fffd 100644
--- a/code/game/gamemodes/changeling/implements/powers/suck.dm
+++ b/code/game/gamemodes/changeling/implements/powers/suck.dm
@@ -2,84 +2,6 @@
set category = "Changeling"
set name = "Absorb DNA"
- var/datum/changeling/changeling = changeling_power(0, 0, 100)
- if(!changeling)
- return
- if (changeling.justate + 60 SECONDS > world.time)
- to_chat(src, "We are still processing our last DNA sample!")
- return
- if(changeling.isabsorbing)
- to_chat(src, "We are already engaged in an absorption!")
- return
-
- var/mob/living/carbon/human/T = input(usr, "Who are we extracting from?", "Target selection") in typecache_filter_list(oview(1), typecacheof(/mob/living/carbon/human))|null
- if (!T)
- return
- if(changeling.isabsorbing)
- to_chat(src, "We are already engaged in an absorption!")
- return
- if(!istype(T))
- to_chat(src, "[T] is not compatible with our biology.")
- return
- if(T.species.flags & NO_SCAN)
- to_chat(src, "We do not know how to parse this creature's DNA!")
- return
- if (T.mind?.changeling)
- to_chat(src, "This creature's DNA is already as complex as yours!")
- return
- if(islesserform(T))
- to_chat(src, "This creature DNA is not compatible with our form!")
- return
- if(HUSK in T.mutations)
- to_chat(src, "This creature's DNA is ruined beyond useability!")
- return
- for(var/datum/absorbed_dna/D in changeling.absorbed_dna)
- if(D.dna == T.dna)
- to_chat(src, "We have already collected this creature's DNA!")
- return
-
- changeling.isabsorbing = TRUE
- for(var/stage = 1, stage <= 2, stage++)
- switch(stage)
- if(1)
- to_chat(src, "We will attempt to infest and steal [T]'s DNA. We must remain next to them.")
- if(2)
- to_chat(src, "We subtly touch [T], and begin to infest their genetic structure.")
- feedback_add_details("changeling_powers","A[stage]")
- if(!do_mob(src, T, 75))
- to_chat(src, "Our extraction of [T] has been interrupted!")
- changeling.isabsorbing = FALSE
- return
-
- to_chat(src, "We have finished infesting [T], and withdraw from their flesh, taking some of their genetic data.")
- to_chat(src, "We will need a minute to process this sample, before we can begin absorbing another.")
-
- T.reagents.add_reagent("toxin", rand(10, 15))
-
- changeling.justate = world.time
-
- changeling.chem_charges += 5
- changeling.geneticpoints += 1
- for(var/language in T.languages)
- if(!(language in changeling.absorbed_languages))
- changeling.absorbed_languages += language
-
- changeling_update_languages(changeling.absorbed_languages)
-
- var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.get_cloning_variant(), T.languages)
- absorbDNA(newDNA)
-
- changeling.absorbedcount++
- changeling.isabsorbing = FALSE
-
- admin_attack_log(usr, T, "extracted the DNA of", "had their DNA extracted by", "extracted DNA from")
-
- return TRUE
-
-/mob/proc/changeling_extract_dna()
- set category = "Changeling"
- set name = "Full DNA Extraction"
-
var/datum/changeling/changeling = changeling_power(0, 0, 100)
if(!changeling)
return
diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm
index 13b09e50949..f32742dd4fe 100644
--- a/code/game/machinery/OpTable.dm
+++ b/code/game/machinery/OpTable.dm
@@ -100,6 +100,7 @@
if(victim)
if(suppressing && victim.sleeping < 3)
victim.Sleeping(3 - victim.sleeping)
+ victim.willfully_sleeping = FALSE
return 1
icon_state = "[modify_state]-idle"
return 0
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index 6fbdb235db9..73e6826bbf3 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -5,6 +5,9 @@
icon_state = "sleeper"
density = 1
anchored = 1
+ clicksound = 'sound/machines/buttonbeep.ogg'
+ clickvol = 30
+
var/mob/living/carbon/human/occupant = null
var/list/available_chemicals = list("norepinephrine" = "Norepinephrine", "stoxin" = "Soporific", "paracetamol" = "Paracetamol", "dylovene" = "Dylovene", "dexalin" = "Dexalin")
var/obj/item/reagent_containers/glass/beaker = null
diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm
index fe09126ba12..892bb367f52 100644
--- a/code/game/machinery/adv_med.dm
+++ b/code/game/machinery/adv_med.dm
@@ -58,7 +58,7 @@
/obj/machinery/bodyscanner/relaymove(mob/user as mob)
if (user.stat)
return
- src.go_out()
+ go_out()
return
/obj/machinery/bodyscanner/verb/eject()
@@ -66,9 +66,9 @@
set category = "Object"
set name = "Eject Body Scanner"
- if (usr.stat != 0)
+ if (usr.stat != CONSCIOUS)
return
- src.go_out()
+ go_out()
add_fingerprint(usr)
return
@@ -77,50 +77,50 @@
set category = "Object"
set name = "Enter Body Scanner"
- if (usr.stat != 0)
+ if (usr.stat != CONSCIOUS)
return
- if (src.occupant)
- to_chat(usr, "The scanner is already occupied!")
+ if (occupant)
+ to_chat(usr, span("warning", "The scanner is already occupied!"))
return
if (usr.abiotic())
- to_chat(usr, "The subject cannot have abiotic items on.")
+ to_chat(usr, span("warning", "The subject cannot have abiotic items on."))
return
usr.pulling = null
usr.client.perspective = EYE_PERSPECTIVE
usr.client.eye = src
usr.forceMove(src)
- src.occupant = usr
+ occupant = usr
update_use_power(2)
update_icon()
- src.add_fingerprint(usr)
+ add_fingerprint(usr)
return
/obj/machinery/bodyscanner/proc/go_out()
- if ((!( src.occupant ) || src.locked))
+ if(!occupant || locked)
return
- last_occupant_name = src.occupant.name
- if (src.occupant.client)
- src.occupant.client.eye = src.occupant.client.mob
- src.occupant.client.perspective = MOB_PERSPECTIVE
- src.occupant.forceMove(src.loc)
- src.occupant = null
+ last_occupant_name = occupant.name
+ if (occupant.client)
+ occupant.client.eye = occupant.client.mob
+ occupant.client.perspective = MOB_PERSPECTIVE
+ occupant.forceMove(loc)
+ occupant = null
update_use_power(1)
update_icon()
return
/obj/machinery/bodyscanner/attackby(obj/item/grab/G, mob/user)
- if ((!( istype(G, /obj/item/grab) ) || !( isliving(G.affecting) )))
+ if (!istype(G, /obj/item/grab) || !isliving(G.affecting) )
return
- if (src.occupant)
- to_chat(user, "The scanner is already occupied!")
+ if (occupant)
+ to_chat(user, span("warning", "The scanner is already occupied!"))
return
if (G.affecting.abiotic())
- to_chat(user, "Subject cannot have abiotic items on.")
+ to_chat(user, span("warning", "Subject cannot have abiotic items on."))
return
var/mob/living/M = G.affecting
- user.visible_message("[user] starts putting [M] into [src].", "You start putting [M] into [src].", range = 3)
+ user.visible_message(span("notice", "\The [user] starts putting \the [M] into \the [src]."), span("notice", "You start putting \the [M] into \the [src]."), range = 3)
if (do_mob(user, G.affecting, 30, needhand = 0))
var/bucklestatus = M.bucklecheck(user)
@@ -134,11 +134,11 @@
M.client.eye = src
M.forceMove(src)
- src.occupant = M
+ occupant = M
update_use_power(2)
update_icon()
//Foreach goto(154)
- src.add_fingerprint(user)
+ add_fingerprint(user)
//G = null
qdel(G)
return
@@ -149,11 +149,11 @@
if(!ismob(O))
return
var/mob/living/M = O//Theres no reason this shouldn't be /mob/living
- if (src.occupant)
- to_chat(user, "The scanner is already occupied!")
+ if (occupant)
+ to_chat(user, span("notice", "The scanner is already occupied!"))
return
if (M.abiotic())
- to_chat(user, "Subject cannot have abiotic items on.")
+ to_chat(user, span("notice", "Subject cannot have abiotic items on."))
return
var/mob/living/L = O
@@ -163,9 +163,9 @@
return
if(L == user)
- user.visible_message("[user] starts climbing into [src].", "You start climbing into [src].", range = 3)
+ user.visible_message(span("notice", "\The [user] starts climbing into \the [src]."), span("notice", "You start climbing into \the [src]."), range = 3)
else
- user.visible_message("[user] starts putting [L] into [src].", "You start putting [L] into [src].", range = 3)
+ user.visible_message(span("notice", "\The [user] starts putting \the [L] into \the [src]."), span("notice", "You start putting \the [L] into \the [src]."), range = 3)
if (do_mob(user, L, 30, needhand = 0))
if (bucklestatus == 2)
@@ -175,11 +175,11 @@
M.client.perspective = EYE_PERSPECTIVE
M.client.eye = src
M.forceMove(src)
- src.occupant = M
+ occupant = M
update_use_power(2)
update_icon()
- playsound(src.loc, 'sound/machines/medbayscanner1.ogg', 50)
- src.add_fingerprint(user)
+ playsound(loc, 'sound/machines/medbayscanner1.ogg', 50)
+ add_fingerprint(user)
//G = null
return
@@ -187,7 +187,7 @@
switch(severity)
if(1.0)
for(var/atom/movable/A as mob|obj in src)
- A.forceMove(src.loc)
+ A.forceMove(loc)
ex_act(severity)
//Foreach goto(35)
//SN src = null
@@ -196,7 +196,7 @@
if(2.0)
if (prob(50))
for(var/atom/movable/A as mob|obj in src)
- A.forceMove(src.loc)
+ A.forceMove(loc)
ex_act(severity)
//Foreach goto(108)
//SN src = null
@@ -205,7 +205,7 @@
if(3.0)
if (prob(25))
for(var/atom/movable/A as mob|obj in src)
- A.forceMove(src.loc)
+ A.forceMove(loc)
ex_act(severity)
//Foreach goto(181)
//SN src = null
@@ -216,10 +216,10 @@
/obj/machinery/bodyscanner/proc/check_species()
if (!occupant || !ishuman(occupant))
- return 1
+ return TRUE
var/mob/living/carbon/human/O = occupant
if (!O)
- return 1
+ return TRUE
return !(O.get_species() in allowed_species)
/obj/machinery/body_scanconsole/ex_act(severity)
@@ -269,27 +269,27 @@
else
if (stat & NOPOWER)
spawn(rand(0, 15))
- src.icon_state = "body_scannerconsole-p"
+ icon_state = "body_scannerconsole-p"
else
icon_state = initial(icon_state)
/obj/machinery/body_scanconsole/proc/get_collapsed_lung_desc()
- if (!src.connected || !src.connected.occupant)
+ if (!connected || !connected.occupant)
return
- if (src.connected.occupant.name != src.connected.last_occupant_name || !collapse_desc)
+ if (connected.occupant.name != connected.last_occupant_name || !collapse_desc)
var/ldesc = pick("Shows symptoms of collapse.", "Collapsed.", "Pneumothorax detected.")
collapse_desc = ldesc
- src.connected.last_occupant_name = src.connected.occupant.name
+ connected.last_occupant_name = connected.occupant.name
return collapse_desc
/obj/machinery/body_scanconsole/proc/get_broken_lung_desc()
- if (!src.connected || !src.connected.occupant)
+ if (!connected || !connected.occupant)
return
- if (src.connected.occupant.name != src.connected.last_occupant_name || !broken_desc)
+ if (connected.occupant.name != connected.last_occupant_name || !broken_desc)
var/ldesc = pick("Shows symptoms of rupture.", "Ruptured.", "Extensive damage detected.")
broken_desc = ldesc
- src.connected.last_occupant_name = src.connected.occupant.name
+ connected.last_occupant_name = connected.occupant.name
return broken_desc
@@ -298,13 +298,12 @@
for(var/obj/machinery/bodyscanner/C in orange(1,src))
connected = C
break
- src.connected.connected = src
+ connected.connected = src
-/obj/machinery/body_scanconsole/attack_ai(user as mob)
- return src.attack_hand(user)
-
-/obj/machinery/body_scanconsole/attack_hand(user as mob)
+/obj/machinery/body_scanconsole/attack_ai(var/mob/user)
+ return attack_hand(user)
+/obj/machinery/body_scanconsole/attack_hand(var/mob/user)
if(..())
return
@@ -314,29 +313,37 @@
..()
// shouldn't be reachable if occupant is invalid
- if (href_list["print"])
- var/obj/item/paper/R = new(src.loc)
+ if(href_list["print"])
+ var/obj/item/paper/R = new(loc)
R.color = "#eeffe8"
- R.set_content_unsafe("Scan ([src.connected.occupant])", format_occupant_data(src.connected.get_occupant_data()))
+ R.set_content_unsafe("Scan ([connected.occupant])", format_occupant_data(connected.get_occupant_data()))
print(R, "[src] beeps, printing [R.name] after a moment.")
-/obj/machinery/body_scanconsole/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
- var/list/data = list()
- var/occupied = (src.connected && src.connected.occupant)
- var/mob/living/carbon/human/occupant
- if (src.connected)
- occupant = src.connected.occupant
+/obj/machinery/body_scanconsole/ui_interact(mob/user)
+ var/datum/vueui/ui = SSvueui.get_open_ui(user, src)
+ if (!ui)
+ ui = new(user, src, "medical-bodyscanner", 800, 600, capitalize(name))
+ ui.open()
+
+/obj/machinery/body_scanconsole/vueui_data_change(var/list/data, var/mob/user, var/datum/vueui/ui)
+ if(!data)
+ data = list()
+
+ var/mob/living/carbon/human/occupant
+ if (connected)
+ occupant = connected.occupant
+
+ VUEUI_SET_CHECK(data["noscan"], !!connected.check_species(), ., data)
+ VUEUI_SET_CHECK(data["nocons"], !connected, ., data)
+ VUEUI_SET_CHECK(data["occupied"], connected.occupant, ., data)
+ VUEUI_SET_CHECK(data["invalid"], !!connected.check_species(), ., data)
+ VUEUI_SET_CHECK(data["ipc"], !!(occupant && isipc(occupant)), ., data)
- data["noscan"] = src.connected.check_species()
- data["nocons"] = !src.connected
- data["occupied"] = occupied
- data["invalid"] = src.connected && src.connected.check_species()
- data["ipc"] = src.connected && occupant && isipc(occupant)
if (!data["invalid"])
var/datum/reagents/R = occupant.bloodstr
- var/brain_result = occupant.get_brain_status()
+ var/brain_result = occupant.get_brain_result()
var/pulse_result
if(occupant.should_have_organ(BP_HEART))
@@ -355,46 +362,40 @@
if(pulse_result == ">250")
pulse_result = -3
- data["stat"] = occupant.stat
- data["name"] = occupant.name
- data["species"] = occupant.get_species() // mostly for fluff.
- data["brain_activity"] = brain_result
- data["pulse"] = text2num(pulse_result)
- data["blood_pressure"] = occupant.get_blood_pressure()
- data["blood_volume"] = occupant.get_blood_volume()
- data["blood_o2"] = occupant.get_blood_oxygenation()
- data["rads"] = occupant.total_radiation
+ VUEUI_SET_CHECK(data["stat"], occupant.stat, ., data)
+ VUEUI_SET_CHECK(data["name"], occupant.name, ., data)
+ VUEUI_SET_CHECK(data["species"], occupant.get_species(), ., data)
+ VUEUI_SET_CHECK(data["brain_activity"], brain_result, ., data)
+ VUEUI_SET_CHECK(data["pulse"], text2num(pulse_result), ., data)
+ VUEUI_SET_CHECK(data["blood_pressure"], occupant.get_blood_pressure(), ., data)
+ VUEUI_SET_CHECK(data["blood_pressure_level"], occupant.get_blood_pressure_alert(), ., data)
+ VUEUI_SET_CHECK(data["blood_volume"], occupant.get_blood_volume(), ., data)
+ VUEUI_SET_CHECK(data["blood_o2"], occupant.get_blood_oxygenation(), ., data)
+ VUEUI_SET_CHECK(data["rads"], occupant.total_radiation, ., data)
- data["cloneLoss"] = get_severity(occupant.getCloneLoss(), TRUE)
- data["oxyLoss"] = get_severity(occupant.getOxyLoss(), TRUE)
- data["bruteLoss"] = get_severity(occupant.getBruteLoss(), TRUE)
- data["fireLoss"] = get_severity(occupant.getFireLoss(), TRUE)
- data["toxLoss"] = get_severity(occupant.getToxLoss(), TRUE)
+ VUEUI_SET_CHECK(data["cloneLoss"], get_severity(occupant.getCloneLoss()), ., data)
+ VUEUI_SET_CHECK(data["oxyLoss"], get_severity(occupant.getOxyLoss()), ., data)
+ VUEUI_SET_CHECK(data["bruteLoss"], get_severity(occupant.getBruteLoss()), ., data)
+ VUEUI_SET_CHECK(data["fireLoss"], get_severity(occupant.getFireLoss()), ., data)
+ VUEUI_SET_CHECK(data["toxLoss"], get_severity(occupant.getToxLoss()), ., data)
- data["paralysis"] = occupant.paralysis
- data["bodytemp"] = occupant.bodytemperature
- data["occupant"] = occupant
- data["norepiAmt"] = R.get_reagent_amount("norepinephrine")
- data["soporAmt"] = R.get_reagent_amount("stoxin")
- data["bicardAmt"] = R.get_reagent_amount("bicaridine")
- data["dexAmt"] = R.get_reagent_amount("dexalin")
- data["dermAmt"] = R.get_reagent_amount("dermaline")
- data["otherAmt"] = R.total_volume - (data["soporAmt"] + data["dexAmt"] + data["bicardAmt"] + data["norepiAmt"] + data["dermAmt"])
- data["bodyparts"] = get_external_wound_data(occupant)
- data["organs"] = get_internal_wound_data(occupant)
+ VUEUI_SET_CHECK(data["paralysis"], occupant.paralysis, ., data)
+ VUEUI_SET_CHECK(data["bodytemp"], occupant.bodytemperature, ., data)
+ VUEUI_SET_CHECK(data["occupant"], occupant, ., data)
+ VUEUI_SET_CHECK(data["norepiAmt"], R.get_reagent_amount("norepinephrine"), ., data)
+ VUEUI_SET_CHECK(data["soporAmt"], R.get_reagent_amount("stoxin"), ., data)
+ VUEUI_SET_CHECK(data["bicardAmt"], R.get_reagent_amount("bicaridine"), ., data)
+ VUEUI_SET_CHECK(data["dexAmt"], R.get_reagent_amount("dexalin"), ., data)
+ VUEUI_SET_CHECK(data["dermAmt"], R.get_reagent_amount("dermaline"), ., data)
+ VUEUI_SET_CHECK(data["otherAmt"], R.total_volume - (data["soporAmt"] + data["dexAmt"] + data["bicardAmt"] + data["norepiAmt"] + data["dermAmt"]), ., data)
+ VUEUI_SET_CHECK(data["bodyparts"], get_external_wound_data(occupant), ., data)
+ VUEUI_SET_CHECK(data["organs"], get_internal_wound_data(occupant), ., data)
var/list/missing = get_missing_organs(occupant)
- data["missingparts"] = missing
- data["hasmissing"] = missing.len ? 1 : 0
- data["hasvirus"] = occupant.virus2.len || occupant.viruses.len
- data["hastgvirus"] = occupant.viruses.len
- data["tgvirus"] = occupant.viruses
-
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "med_diagnostics.tmpl", "Medical Diagnostics", 800, 500, state = state)
- ui.set_initial_data(data)
- ui.open()
- ui.set_auto_update(1)
+ VUEUI_SET_CHECK(data["missingparts"], missing, ., data)
+ VUEUI_SET_CHECK(data["hasmissing"], !!missing.len, ., data)
+ VUEUI_SET_CHECK(data["hasvirus"], occupant.virus2.len || occupant.viruses.len, ., data)
+ VUEUI_SET_CHECK(data["hastgvirus"], occupant.viruses.len, ., data)
+ VUEUI_SET_CHECK(data["tgvirus"], occupant.viruses, ., data)
/obj/machinery/body_scanconsole/proc/get_internal_damage(var/obj/item/organ/internal/I)
if(I.is_broken())
@@ -457,7 +458,7 @@
if (unk)
wounds += "Has an abnormal mass present."
- data["hasWounds"] = length(wounds) ? 1 : 0
+ data["hasWounds"] = !!length(wounds)
data["wounds"] = wounds
organs += list(data)
@@ -500,8 +501,9 @@
if(O.get_scarring_level() > 0.01)
wounds += "[O.get_scarring_results()]."
- data["hasWounds"] = length(wounds) ? 1 : 0
+ data["hasWounds"] = !!length(wounds)
data["wounds"] = wounds
+
organs += list(data)
return organs
diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm
index 049cc939636..597f479b1f6 100644
--- a/code/game/machinery/alarm.dm
+++ b/code/game/machinery/alarm.dm
@@ -42,6 +42,9 @@
active_power_usage = 1500 //For heating/cooling rooms. 1000 joules equates to about 1 degree every 2 seconds for a single tile of air.
power_channel = ENVIRON
req_one_access = list(access_atmospherics, access_engine_equip)
+ clicksound = "button"
+ clickvol = 30
+
var/alarm_id = null
var/breach_detection = 1 // Whether to use automatic breach detection or not
var/frequency = 1439
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index 4eec54a18c9..28d98b8bffe 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -7,6 +7,8 @@
use_power = 1
idle_power_usage = 10
active_power_usage = 2000
+ clicksound = "keyboard"
+ clickvol = 30
var/list/machine_recipes
var/list/stored_material = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0)
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index 86627ea5be8..7ed745ccb11 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -7,6 +7,8 @@
use_power = 1
idle_power_usage = 300
active_power_usage = 300
+ clicksound = "keyboard"
+
var/circuit = null //The path to the circuit board type. If circuit==null, the computer can't be disassembled.
var/processing = 0
@@ -15,7 +17,6 @@
var/light_power_on = 1
var/overlay_layer
var/is_holographic = TRUE
- clicksound = "keyboard"
/obj/machinery/computer/Initialize()
. = ..()
diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm
index d8741f1285f..187623c3b02 100644
--- a/code/game/machinery/cryo.dm
+++ b/code/game/machinery/cryo.dm
@@ -13,6 +13,8 @@
use_power = 1
idle_power_usage = 20
active_power_usage = 200
+ clicksound = 'sound/machines/buttonbeep.ogg'
+ clickvol = 30
var/temperature_archived
var/mob/living/carbon/occupant = null
diff --git a/code/game/machinery/jukebox.dm b/code/game/machinery/jukebox.dm
index 99eee1afd1b..5fb23bcd0b1 100644
--- a/code/game/machinery/jukebox.dm
+++ b/code/game/machinery/jukebox.dm
@@ -19,6 +19,7 @@ datum/track/New(var/title_name, var/audio)
use_power = 1
idle_power_usage = 10
active_power_usage = 100
+ clicksound = 'sound/machines/buttonbeep.ogg'
var/playing = 0
diff --git a/code/game/machinery/kitchen/microwave.dm b/code/game/machinery/kitchen/microwave.dm
index 7f86296f691..4d9953b6952 100644
--- a/code/game/machinery/kitchen/microwave.dm
+++ b/code/game/machinery/kitchen/microwave.dm
@@ -10,6 +10,9 @@
idle_power_usage = 5
active_power_usage = 2000
flags = OPENCONTAINER | NOREACT
+ clicksound = "button"
+ clickvol = "30"
+
var/operating = FALSE // Is it on?
var/dirty = 0 // = {0..100} Does it need cleaning?
var/broken = 0 // ={0,1,2} How broken is it???
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index b1de271cc39..13950216b0a 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -231,7 +231,7 @@ Class Procs:
/obj/machinery/CouldUseTopic(var/mob/user)
..()
- if(istype (user, /mob/living/carbon))
+ if(clicksound && iscarbon(user))
playsound(src, clicksound, clickvol)
user.set_machine(src)
diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm
index 94bde9ad211..5a50f34479e 100644
--- a/code/game/machinery/spaceheater.dm
+++ b/code/game/machinery/spaceheater.dm
@@ -11,7 +11,7 @@
var/heating_power = 42000
emagged = FALSE
has_special_power_checks = TRUE
-
+ clicksound = "switch"
/obj/machinery/space_heater/Initialize()
. = ..()
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index d7ee51846ad..d5e7a78db48 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -37,6 +37,7 @@
layer = 2.9
anchored = 1
density = 1
+ clicksound = "button"
var/icon_vend //Icon_state when vending
var/icon_deny //Icon_state when denying access
@@ -123,7 +124,6 @@
src.build_inventory()
power_change()
-
/**
* Build src.produdct_records from the products lists
*
@@ -207,12 +207,10 @@
var/obj/item/spacecash/ewallet/C = W
paid = pay_with_ewallet(C)
handled = 1
- playsound(user.loc, 'sound/machines/id_swipe.ogg', 100, 1)
else if (istype(W, /obj/item/spacecash))
var/obj/item/spacecash/C = W
paid = pay_with_cash(C, user)
handled = 1
- playsound(user.loc, 'sound/machines/id_swipe.ogg', 100, 1)
if(paid)
src.vend(currently_vending, usr)
@@ -347,6 +345,7 @@
*/
/obj/machinery/vending/proc/pay_with_ewallet(var/obj/item/spacecash/ewallet/wallet)
visible_message("\The [usr] swipes \the [wallet] through \the [src].")
+ playsound(src.loc, 'sound/machines/id_swipe.ogg', 50, 1)
if(currently_vending.price > wallet.worth)
src.status_message = "Insufficient funds on chargecard."
src.status_error = 1
@@ -367,6 +366,7 @@
visible_message("\The [usr] swipes \the [I] through \the [src].")
else
visible_message("\The [usr] swipes \the [ID_container] through \the [src].")
+ playsound(src.loc, 'sound/machines/id_swipe.ogg', 50, 1)
var/datum/money_account/vendor_account = SSeconomy.get_department_account("Vendor")
var/datum/money_account/customer_account = SSeconomy.get_account(I.associated_account_number)
if (!customer_account)
@@ -509,7 +509,7 @@
var/datum/money_account/vendor_account = SSeconomy.get_department_account("Vendor")
if(stat & (BROKEN|NOPOWER))
return
- if(usr.stat || usr.restrained())
+ if(..())
return
if(href_list["remove_coin"] && !istype(usr,/mob/living/silicon))
diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm
index 793a7accbc7..9eef6c70ff3 100644
--- a/code/game/machinery/washing_machine.dm
+++ b/code/game/machinery/washing_machine.dm
@@ -4,6 +4,9 @@
icon_state = "wm_10"
density = 1
anchored = 1.0
+ clicksound = "button"
+ clickvol = 40
+
var/state = 1
//1 = empty, open door
//2 = empty, closed door
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 0ee25b2bac2..905eed3d12d 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -756,3 +756,8 @@ var/global/list/default_medbay_channels = list(
/obj/item/device/radio/phone/medbay/Initialize()
. = ..()
internal_channels = default_medbay_channels.Copy()
+
+/obj/item/device/radio/CouldUseTopic(var/mob/user)
+ ..()
+ if(iscarbon(user))
+ playsound(src, "button", 10)
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index bcb69d92f8e..774eaed7eba 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -123,7 +123,7 @@ BREATH ANALYZER
pulse_result = 0
else
pulse_result = H.get_pulse(GETPULSE_TOOL)
- pulse_result = "[pulse_result]bpm"
+ pulse_result = "[pulse_result]bpm"
if(H.pulse() == PULSE_NONE)
pulse_result = "[pulse_result]"
else if(H.pulse() < PULSE_NORM)
@@ -141,7 +141,7 @@ BREATH ANALYZER
if(H.should_have_organ(BP_HEART))
if(H.get_blood_volume() <= 70)
dat += "Severe blood loss detected."
- var/oxygenation_string = "[H.get_blood_oxygenation()]% blood oxygenation"
+ var/oxygenation_string = "[H.get_blood_oxygenation()]% blood oxygenation"
switch(H.get_blood_oxygenation())
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
oxygenation_string = "[oxygenation_string]"
@@ -149,7 +149,18 @@ BREATH ANALYZER
oxygenation_string = "[oxygenation_string]"
if(-(INFINITY) to BLOOD_VOLUME_SURVIVE)
oxygenation_string = "[oxygenation_string]"
- dat += "[b]Blood pressure:[endb] [H.get_blood_pressure()] ([oxygenation_string])"
+
+ var/blood_pressure_string
+ switch(H.get_blood_pressure_alert())
+ if(1)
+ blood_pressure_string = "[H.get_blood_pressure()]"
+ if(2)
+ blood_pressure_string = "[H.get_blood_pressure()]"
+ if(3)
+ blood_pressure_string = "[H.get_blood_pressure()]"
+ if(4)
+ blood_pressure_string = "[H.get_blood_pressure()]"
+ dat += "[b]Blood pressure:[endb] [blood_pressure_string] ([oxygenation_string])"
else
if(H.isFBP())
dat += "[b]Blood pressure:[endb] [rand(118, 125)]/[rand(77, 85)] (100%)"
@@ -157,7 +168,12 @@ BREATH ANALYZER
dat += "[b]Blood pressure:[endb] N/A"
// Body temperature.
- dat += "Body temperature: [H.bodytemperature-T0C]°C ([H.bodytemperature*1.8-459.67]°F)"
+ var/temperature_string
+ if(H.bodytemperature < H.species.cold_level_1 || H.bodytemperature > H.species.heat_level_1)
+ temperature_string = "Body temperature: [H.bodytemperature-T0C]°C ([H.bodytemperature*1.8-459.67]°F)"
+ else
+ temperature_string = "Body temperature: [H.bodytemperature-T0C]°C ([H.bodytemperature*1.8-459.67]°F)"
+ dat += temperature_string
// Traumatic shock.
if(H.is_asystole())
@@ -168,7 +184,7 @@ BREATH ANALYZER
if(H.getOxyLoss() > 50)
dat += "[b]Severe oxygen deprivation detected.[endb]"
if(H.getToxLoss() > 50)
- dat += "[b]Major systemic organ failure detected.[endb]"
+ dat += "[b]Major systemic organ failure detected.[endb]"
if(H.getFireLoss() > 50)
dat += "[b]Severe burn damage detected.[endb]"
if(H.getBruteLoss() > 50)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index cb000075d35..63d3bc6ee48 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -360,9 +360,8 @@
new /obj/item/device/radio/headset/headset_sec(src)
new /obj/item/device/radio/headset/headset_sec/alt(src)
new /obj/item/clothing/suit/storage/vest/detective(src)
- new /obj/item/ammo_magazine/c38(src)
- new /obj/item/ammo_magazine/c38(src)
- new /obj/item/gun/projectile/revolver/detective(src)
+ new /obj/item/ammo_magazine/c45m(src)
+ new /obj/item/gun/projectile/sec/detective(src)
new /obj/item/taperoll/police(src)
//Belts
new /obj/item/clothing/accessory/holster/waist(src)
diff --git a/code/game/sound.dm b/code/game/sound.dm
index 63c937ef1da..ad3165dc2a5 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -167,6 +167,12 @@ var/list/fracture_sound = list(
'sound/effects/bonebreak3.ogg',
'sound/effects/bonebreak4.ogg'
)
+var/list/button_sound = list(
+ 'sound/machines/button1.ogg',
+ 'sound/machines/button2.ogg',
+ 'sound/machines/button3.ogg',
+ 'sound/machines/button4.ogg'
+)
var/list/computerbeep_sound = list(
'sound/machines/compbeep1.ogg',
'sound/machines/compbeep2.ogg',
@@ -320,7 +326,7 @@ var/list/glasscrack_sound = list(
return DIZZY
else if (confused)
return DIZZY
- else if (sleeping)
+ else if (stat == UNCONSCIOUS)
return UNDERWATER
else
return ..()
@@ -412,8 +418,8 @@ var/list/glasscrack_sound = list(
if ("pageturn") soundin = pick(page_sound)
if ("fracture") soundin = pick(fracture_sound)
//if ("gunshot") soundin = pick(gun_sound)
+ if ("button") soundin = pick(button_sound)
if ("glasscrack") soundin = pick(glasscrack_sound)
- if ("computerbeep") soundin = pick(computerbeep_sound)
if ("switch") soundin = pick(switch_sound)
if ("keyboard") soundin = pick(keyboard_sound)
if ("pickaxe") soundin = pick(pickaxe_sound)
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index d14136e5491..53e3828ff26 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -22,8 +22,6 @@ var/list/admin_verbs_admin = list(
/client/proc/colorooc, /*allows us to set a custom colour for everythign we say in ooc*/
/client/proc/admin_ghost, /*allows us to ghost/reenter body at will*/
/client/proc/toggle_view_range, /*changes how far we can see*/
- /datum/admins/proc/view_txt_log, /*shows the server log (diary) for today*/
- /datum/admins/proc/view_atk_log, /*shows the server combat-log, doesn't do anything presently*/
/client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/
/client/proc/cmd_admin_pm_panel, /*admin-pm list*/
/client/proc/cmd_admin_subtle_message, /*send an message to somebody as a 'voice in their head'*/
@@ -98,8 +96,7 @@ var/list/admin_verbs_admin = list(
/client/proc/clear_toxins,
/client/proc/wipe_ai, // allow admins to force-wipe AIs
/client/proc/fix_player_list,
- /client/proc/reset_openturf,
- /client/proc/listen_aooc
+ /client/proc/reset_openturf
)
var/list/admin_verbs_ban = list(
/client/proc/unban_panel,
@@ -260,8 +257,6 @@ var/list/admin_verbs_hideable = list(
/client/proc/colorooc,
/client/proc/admin_ghost,
/client/proc/toggle_view_range,
- /datum/admins/proc/view_txt_log,
- /datum/admins/proc/view_atk_log,
/client/proc/cmd_admin_subtle_message,
/client/proc/cmd_admin_check_contents,
/datum/admins/proc/access_news_network,
@@ -343,8 +338,7 @@ var/list/admin_verbs_mod = list(
/client/proc/check_words, /*displays cult-words*/
/client/proc/check_ai_laws, /*shows AI and borg laws*/
/client/proc/aooc,
- /client/proc/print_logout_report,
- /client/proc/listen_aooc
+ /client/proc/print_logout_report
)
var/list/admin_verbs_dev = list( //will need to be altered - Ryan784
@@ -392,8 +386,7 @@ var/list/admin_verbs_cciaa = list(
/datum/admins/proc/create_admin_fax,
/client/proc/check_fax_history,
/client/proc/aooc,
- /client/proc/check_antagonists,
- /client/proc/listen_aooc
+ /client/proc/check_antagonists
)
/client/proc/add_admin_verbs()
@@ -784,18 +777,6 @@ var/list/admin_verbs_cciaa = list(
to_chat(src, "You now have the keys to control the planet, or atleast a small space station")
verbs -= /client/proc/readmin_self
-/client/proc/listen_aooc()
- set name = "Show/Hide AOOC"
- set category = "Preferences"
-
- if(!check_rights(R_ADMIN|R_MOD|R_CCIAA))
- return
- prefs.toggles ^= CHAT_AOOC
- if (prefs.toggles & CHAT_AOOC)
- to_chat(usr, "You now will see all messages in AOOC.")
- else
- to_chat(usr, "You now won't see messages in aooc")
-
/client/proc/deadmin_self()
set name = "De-admin self"
set category = "Admin"
diff --git a/code/modules/admin/verbs/antag-ooc.dm b/code/modules/admin/verbs/antag-ooc.dm
index 8acad2ec765..9350bbbedc2 100644
--- a/code/modules/admin/verbs/antag-ooc.dm
+++ b/code/modules/admin/verbs/antag-ooc.dm
@@ -14,10 +14,6 @@
if(!msg)
return
- if(!(prefs.toggles & CHAT_AOOC))
- to_chat(src, "You have AOOC muted.")
- return
-
var/display_name = src.key
if (holder)
display_name = "[display_name]([holder.rank])"
diff --git a/code/modules/admin/verbs/getlogs.dm b/code/modules/admin/verbs/getlogs.dm
index 3dd9836134c..524759c0920 100644
--- a/code/modules/admin/verbs/getlogs.dm
+++ b/code/modules/admin/verbs/getlogs.dm
@@ -78,34 +78,3 @@
//Other log stuff put here for the sake of organisation
-
-//Shows today's server log
-/datum/admins/proc/view_txt_log()
- set category = "Admin"
- set name = "Show Server Log"
- set desc = "Shows today's server log."
-
- var/path = "data/logs/[time2text(world.realtime,"YYYY/MM-Month/DD-Day")].log"
- if( fexists(path) )
- src << run( file(path) )
- else
- to_chat(src, "Error: view_txt_log(): File not found/Invalid path([path]).")
- return
- feedback_add_details("admin_verb","VTL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
- return
-
-//Shows today's attack log
-/datum/admins/proc/view_atk_log()
- set category = "Admin"
- set name = "Show Server Attack Log"
- set desc = "Shows today's server attack log."
-
- var/path = "data/logs/[time2text(world.realtime,"YYYY/MM-Month/DD-Day")] Attack.log"
- if( fexists(path) )
- src << run( file(path) )
- else
- to_chat(src, "Error: view_atk_log(): File not found/Invalid path([path]).")
- return
- usr << run( file(path) )
- feedback_add_details("admin_verb","SSAL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
- return
diff --git a/code/modules/background/citizenship/unathi.dm b/code/modules/background/citizenship/unathi.dm
index 1a5faf52da9..f54f8f4f48f 100644
--- a/code/modules/background/citizenship/unathi.dm
+++ b/code/modules/background/citizenship/unathi.dm
@@ -41,4 +41,4 @@
uniform = /obj/item/clothing/under/unathi
suit = /obj/item/clothing/suit/unathi/mantle
backpack_contents = list(/obj/item/device/camera = 1)
- belt = /obj/item/material/sword/dao
\ No newline at end of file
+ belt = /obj/item/gun/energy/pistol/hegemony
diff --git a/code/modules/client/preference_setup/loadout/loadout_accessories.dm b/code/modules/client/preference_setup/loadout/loadout_accessories.dm
index 7b69d3bc284..b26c66ac753 100644
--- a/code/modules/client/preference_setup/loadout/loadout_accessories.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_accessories.dm
@@ -262,8 +262,4 @@
/datum/gear/accessory/sleeve_patch/New()
..()
- gear_tweaks += gear_tweak_free_color_choice
-
-/datum/gear/accessory/rosary
- display_name = "rosary"
- path = /obj/item/clothing/accessory/rosary
\ No newline at end of file
+ gear_tweaks += gear_tweak_free_color_choice
\ No newline at end of file
diff --git a/code/modules/client/preference_setup/loadout/loadout_religion.dm b/code/modules/client/preference_setup/loadout/loadout_religion.dm
new file mode 100644
index 00000000000..f97eabcb461
--- /dev/null
+++ b/code/modules/client/preference_setup/loadout/loadout_religion.dm
@@ -0,0 +1,20 @@
+/datum/gear/religion
+ display_name = "trinary perfection robes"
+ path = /obj/item/clothing/suit/trinary_robes
+ sort_category = "Religion"
+
+/datum/gear/religion/trinary/mask
+ display_name = "trinary perfection mask"
+ path = /obj/item/clothing/mask/trinary_mask
+
+/datum/gear/religion/trinary/cape
+ display_name = "trinary perfection cape"
+ path = /obj/item/clothing/accessory/poncho/trinary
+
+/datum/gear/religion/trinary/badge
+ display_name = "trinary perfection brooch"
+ path = /obj/item/clothing/accessory/badge/trinary
+
+/datum/gear/religion/rosary
+ display_name = "rosary"
+ path = /obj/item/clothing/accessory/rosary
diff --git a/code/modules/client/preference_setup/loadout/loadout_suit.dm b/code/modules/client/preference_setup/loadout/loadout_suit.dm
index 983b58df746..07bc43a22a9 100644
--- a/code/modules/client/preference_setup/loadout/loadout_suit.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_suit.dm
@@ -173,6 +173,10 @@
display_name = "winter coat"
path = /obj/item/clothing/suit/storage/hooded/wintercoat
+/datum/gear/suit/winter/red
+ display_name = "winter coat, red"
+ path = /obj/item/clothing/suit/storage/hooded/wintercoat/red
+
/datum/gear/suit/winter/captain
display_name = "winter coat, captain"
path = /obj/item/clothing/suit/storage/hooded/wintercoat/captain
diff --git a/code/modules/client/preference_setup/loadout/loadout_xeno/machine.dm b/code/modules/client/preference_setup/loadout/loadout_xeno/machine.dm
index 83b3068d7ff..f00447836b7 100644
--- a/code/modules/client/preference_setup/loadout/loadout_xeno/machine.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_xeno/machine.dm
@@ -76,6 +76,7 @@
antenna["antenna, double"] = /obj/item/clothing/head/antenna/double
antenna["antenna, left"] = /obj/item/clothing/head/antenna/double/left
antenna["antenna, right"] = /obj/item/clothing/head/antenna/double/right
+ antenna["antenna, trinary perfection"] = /obj/item/clothing/head/antenna/trinary_halo
gear_tweaks += new/datum/gear_tweak/path(antenna)
gear_tweaks += list(gear_tweak_free_color_choice)
@@ -102,4 +103,4 @@
idris["Brown Idris Unit trench coat"] = /obj/item/clothing/suit/armor/vest/idris/trenchcoat/brown
idris["Black Idris Unit duster coat"] = /obj/item/clothing/suit/armor/vest/idris/duster/black
idris["Brown Idris Unit duster coat"] = /obj/item/clothing/suit/armor/vest/idris/duster/brown
- gear_tweaks += new/datum/gear_tweak/path(idris)
\ No newline at end of file
+ gear_tweaks += new/datum/gear_tweak/path(idris)
diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm
index 85ab6dc0837..0fffff8d743 100644
--- a/code/modules/client/preferences_toggles.dm
+++ b/code/modules/client/preferences_toggles.dm
@@ -110,6 +110,7 @@
to_chat(src, "You will [(prefs.toggles & CHAT_OOC) ? "now" : "no longer"] see messages on the OOC channel.")
feedback_add_details("admin_verb","TOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
/client/verb/listen_looc()
set name = "Show/Hide LOOC"
set category = "Preferences"
@@ -119,7 +120,8 @@
to_chat(src, "You will [(prefs.toggles & CHAT_LOOC) ? "now" : "no longer"] see messages on the LOOC channel.")
feedback_add_details("admin_verb","TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
+
+
/client/verb/toggle_chattags()
set name = "Show/Hide Chat Tags"
set category = "Preferences"
@@ -212,4 +214,4 @@
if (prefs.toggles_secondary & PARALLAX_IS_STATIC)
to_chat(src, "Space will no longer move.")
else
- to_chat(src, "Space will now move.")
+ to_chat(src, "Space will now move.")
\ No newline at end of file
diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm
index 13400a9bd3a..92f430a558f 100644
--- a/code/modules/clothing/head/misc.dm
+++ b/code/modules/clothing/head/misc.dm
@@ -593,6 +593,12 @@
icon_state = "right_robot_antennae"
item_state = "right_robot_antennae"
+/obj/item/clothing/head/antenna/trinary_halo
+ name = "trinary perfection antenna"
+ desc = "A decorative antenna that is commonly worn by IPCs who serve the Trinary Perfection. It resembles a golden gear."
+ icon_state = "trinary_halo"
+ item_state = "trinary_halo"
+
/obj/item/clothing/head/fake_culthood
name = "occultist hood"
icon_state = "culthood"
diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm
index 34935377e31..8c2c748de77 100644
--- a/code/modules/clothing/masks/miscellaneous.dm
+++ b/code/modules/clothing/masks/miscellaneous.dm
@@ -92,6 +92,17 @@
flags_inv = HIDEFACE
body_parts_covered = 0
+/obj/item/clothing/mask/trinary_mask
+ name = "trinary perfection mask"
+ desc = "A simple lace mask worn by IPCs and organics alike while within the churches of the Trinary Perfection."
+ icon_state = "trinary_mask"
+ item_state = "trinary_mask"
+ w_class = ITEMSIZE_SMALL
+ body_parts_covered = FACE
+ item_flags = FLEXIBLEMATERIAL
+ down_body_parts_covered = null
+ adjustable = TRUE
+
//scarves (fit in in mask slot)
//None of these actually have on-mob sprites...
/obj/item/clothing/mask/bluescarf
@@ -210,7 +221,7 @@
return
if(user.get_equipped_item(slot_wear_mask) != src)
return
-
+
eye.possess(user)
to_chat(eye.owner, span("notice", "You feel disoriented for a moment as your mind connects to the camera network."))
diff --git a/code/modules/clothing/suits/hoodies.dm b/code/modules/clothing/suits/hoodies.dm
index 68d131209e6..79ad6951548 100644
--- a/code/modules/clothing/suits/hoodies.dm
+++ b/code/modules/clothing/suits/hoodies.dm
@@ -102,6 +102,11 @@
min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE
canremove = 0
+/obj/item/clothing/suit/storage/hooded/wintercoat/red
+ name = "red winter coat"
+ icon_state = "coatred"
+ item_state = "coatred"
+
/obj/item/clothing/suit/storage/hooded/wintercoat/captain
name = "captain's winter coat"
icon_state = "coatcaptain"
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index 44be098b05d..098d1958651 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -154,6 +154,12 @@
body_parts_covered = UPPER_TORSO|LOWER_TORSO
flags_inv = HIDEJUMPSUIT
+/obj/item/clothing/suit/trinary_robes
+ name = "trinary perfection robe"
+ desc = "Robes worn by those who serve The Trinary Perfection."
+ icon_state = "trinary_robes"
+ item_state = "trinary_robes"
+
/*
* Misc
*/
diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm
index 092ad2ce56b..94d9ae9ca86 100644
--- a/code/modules/clothing/under/accessories/accessory.dm
+++ b/code/modules/clothing/under/accessories/accessory.dm
@@ -613,6 +613,13 @@
item_state = "galaxycape"
overlay_state = "galaxycape"
+/obj/item/clothing/accessory/poncho/trinary
+ name = "trinary perfection cape"
+ desc = "A brilliant red and brown cape, commonly worn by those who serve the Trinary Perfection."
+ icon_state = "trinary_cape"
+ item_state = "trinary_cape"
+ overlay_state = "trinary_cape"
+
//tau ceti legion ribbons
/obj/item/clothing/accessory/legion
name = "seniority ribbons"
diff --git a/code/modules/clothing/under/accessories/badges.dm b/code/modules/clothing/under/accessories/badges.dm
index f2f43cb6a9b..d57191fdd05 100644
--- a/code/modules/clothing/under/accessories/badges.dm
+++ b/code/modules/clothing/under/accessories/badges.dm
@@ -227,4 +227,11 @@
desc = "A descriptive identification badge with the holder's credentials displayed with a harsh digital glow."
icon_state = "intelbadge"
overlay_state = "intelbadge"
- badge_string = null
\ No newline at end of file
+ badge_string = null
+
+/obj/item/clothing/accessory/badge/trinary
+ name = "trinary perfection brooch"
+ desc = "A metal brooch worn by those who serve or follow the beliefs of the Trinary Perfection. It resembles a gear with a triangle inside."
+ icon_state = "trinary_badge"
+ overlay_state = "trinary_badge"
+ badge_string = null
\ No newline at end of file
diff --git a/code/modules/economy/quikpay.dm b/code/modules/economy/quikpay.dm
index 585ac0052a4..ac4b409990d 100644
--- a/code/modules/economy/quikpay.dm
+++ b/code/modules/economy/quikpay.dm
@@ -174,12 +174,12 @@
if(items[name] && selection[name])
sum += items[name] * selection[name]
receipt += "[name] : [items[name]]x[selection[name]]: [items[name] * selection[name]]
"
- ui.activeui = "quikpay-confirmation"
+ ui.activeui = "devices-quikpay-confirmation"
. = TRUE
if(href_list["return"])
sum = 0
receipt = ""
- ui.activeui = "quikpay-main"
+ ui.activeui = "devices-quikpay-main"
. = TRUE
diff --git a/code/modules/heavy_vehicle/components/head.dm b/code/modules/heavy_vehicle/components/head.dm
index c38189aa913..5961b96add6 100644
--- a/code/modules/heavy_vehicle/components/head.dm
+++ b/code/modules/heavy_vehicle/components/head.dm
@@ -28,9 +28,6 @@
if(!software)
to_chat(user, "It is missing a software control module.")
-/obj/item/mech_component/sensors/prebuild()
- radio = new(src)
- camera = new(src)
/obj/item/mech_component/sensors/prebuild()
radio = new(src)
diff --git a/code/modules/heavy_vehicle/mech_interaction.dm b/code/modules/heavy_vehicle/mech_interaction.dm
index 9b647fb2aff..9ca45aaf729 100644
--- a/code/modules/heavy_vehicle/mech_interaction.dm
+++ b/code/modules/heavy_vehicle/mech_interaction.dm
@@ -17,7 +17,7 @@
else . = ..()
/mob/living/heavy_vehicle/MouseDrop_T(src_object, over_object, src_location, over_location, src_control, over_control, params, var/mob/user)
- if(!user || incapacitated() || user.incapacitated())
+ if(!user || incapacitated() || user.incapacitated() || lockdown)
return FALSE
if(!(user in pilots) && user != src)
@@ -30,7 +30,7 @@
/mob/living/heavy_vehicle/ClickOn(var/atom/A, params, var/mob/user)
- if(!user || incapacitated() || user.incapacitated())
+ if(!user || incapacitated() || user.incapacitated() || lockdown)
return
if(!loc) return
@@ -258,7 +258,7 @@
if(world.time < next_move)
return 0
- if(!user || incapacitated() || user.incapacitated())
+ if(!user || incapacitated() || user.incapacitated() || lockdown)
return
if(!legs)
@@ -491,3 +491,10 @@
return TRUE
L.apply_damage(legs.trample_damage, BRUTE)
return TRUE
+
+/mob/living/heavy_vehicle/proc/ToggleLockdown()
+ lockdown = !lockdown
+ if(lockdown)
+ src.visible_message("\The [src] beeps loudly as its servos sieze up, and it enters lockdown mode!")
+ else
+ src.visible_message("\The [src] hums with life as it is released from its lockdown mode!")
\ No newline at end of file
diff --git a/code/modules/heavy_vehicle/mech_life.dm b/code/modules/heavy_vehicle/mech_life.dm
index ed01c6b0d03..fbd4c14c0bb 100644
--- a/code/modules/heavy_vehicle/mech_life.dm
+++ b/code/modules/heavy_vehicle/mech_life.dm
@@ -22,7 +22,10 @@
update_pilot_overlay()
if(radio)
- radio.on = (head && head.radio && head.radio.is_functional())
+ radio.on = (head?.radio && head.radio.is_functional())
+
+ if(camera)
+ camera.status = (head?.camera && head.camera.is_functional())
body.update_air(hatch_closed && use_air)
diff --git a/code/modules/heavy_vehicle/mech_movement.dm b/code/modules/heavy_vehicle/mech_movement.dm
index 91b9dab3252..c8205c8b70a 100644
--- a/code/modules/heavy_vehicle/mech_movement.dm
+++ b/code/modules/heavy_vehicle/mech_movement.dm
@@ -47,6 +47,10 @@
to_chat(mover, "Maintenance protocols are in effect.")
next_move = world.time + 3 // Just to stop them from getting spammed with messages.
return MOVEMENT_STOP
+ if(exosuit.lockdown)
+ to_chat(mover, span("warning", "You cannot move while the exosuit's lockdown mode is active."))
+ next_move = world.time + 3 // Just to stop them from getting spammed with messages.
+ return MOVEMENT_STOP
var/obj/item/cell/C = exosuit.get_cell()
if(!C || !C.check_charge(exosuit.legs.power_use * CELLRATE))
to_chat(mover, "The power indicator flashes briefly.")
diff --git a/code/modules/heavy_vehicle/mecha.dm b/code/modules/heavy_vehicle/mecha.dm
index 61e0e523956..429a356df20 100644
--- a/code/modules/heavy_vehicle/mecha.dm
+++ b/code/modules/heavy_vehicle/mecha.dm
@@ -17,6 +17,7 @@
var/offset_y = 0
var/obj/item/device/radio/exosuit/radio
+ var/obj/machinery/camera/camera
var/wreckage_path = /obj/structure/mech_wreckage
@@ -49,6 +50,7 @@
var/list/hardpoints = list()
var/hardpoints_locked
var/maintenance_protocols
+ var/lockdown
// Material
var/material/material
@@ -181,6 +183,11 @@
if(head && head.radio)
radio = new(src)
+ if(!camera)
+ camera = new /obj/machinery/camera(src)
+ camera.c_tag = name
+ camera.replace_networks(list(NETWORK_MECHS))
+
// Create HUD.
instantiate_hud()
diff --git a/code/modules/merchant/merchant_programs.dm b/code/modules/merchant/merchant_programs.dm
index 1d374a7b4f3..1653e5b06db 100644
--- a/code/modules/merchant/merchant_programs.dm
+++ b/code/modules/merchant/merchant_programs.dm
@@ -8,8 +8,9 @@
available_on_ntnet = 0
size = 12
usage_flags = PROGRAM_CONSOLE
- required_access_run = access_merchant
- required_access_download = access_merchant
+ requires_access_to_run = PROGRAM_ACCESS_LIST_ONE
+ required_access_run = list(access_merchant, access_kataphract_trader)
+ required_access_download = list(access_merchant, access_kataphract_trader)
var/obj/machinery/merchant_pad/pad = null
var/current_merchant = 0
var/show_trades = 0
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index d53727e5783..9f35126b248 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -112,7 +112,7 @@
else if(client && willfully_sleeping)
visible_message(span("notice", "[M] [action] [src] waking [t_him] up!"))
sleeping = 0
- willfully_sleeping = 0
+ willfully_sleeping = FALSE
for(var/datum/disease/D in viruses)
@@ -384,7 +384,7 @@
to_chat(usr, span("warning", "You are already sleeping"))
return
if(alert(src,"You sure you want to sleep for a while?","Sleep","Yes","No") == "Yes")
- willfully_sleeping = 1
+ willfully_sleeping = TRUE
usr.sleeping = 20 //Short nap
/mob/living/carbon/Collide(atom/A)
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index d33521734ba..c73f7204c54 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -23,7 +23,7 @@
if(H.health / H.maxHealth < 0.5)
H.bg.awaken_impl(TRUE)
sleeping = 0
- willfully_sleeping = 0
+ willfully_sleeping = FALSE
else
to_chat(H, span("danger", "You sense great disturbance to your physical body!"))
else
@@ -31,7 +31,7 @@
else if(client && willfully_sleeping)
visible_message(span("danger", "[src] is hit by [AM] waking [t_him] up!"))
sleeping = 0
- willfully_sleeping = 0
+ willfully_sleeping = FALSE
/mob/living/carbon/bullet_act(var/obj/item/projectile/P, var/def_zone)
..(P, def_zone)
@@ -51,7 +51,7 @@
if(H.health / H.maxHealth < 0.5)
H.bg.awaken_impl(TRUE)
sleeping = 0
- willfully_sleeping = 0
+ willfully_sleeping = FALSE
else
to_chat(H, span("danger", "You sense great disturbance to your physical body!"))
else
@@ -59,7 +59,7 @@
else if(client && willfully_sleeping)
visible_message("[P] hit [src] waking [t_him] up!")
sleeping = 0
- willfully_sleeping = 0
+ willfully_sleeping = FALSE
/mob/living/carbon/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone)
var/t_him = "it"
@@ -77,7 +77,7 @@
if(H.health / H.maxHealth < 0.5)
H.bg.awaken_impl(TRUE)
sleeping = 0
- willfully_sleeping = 0
+ willfully_sleeping = FALSE
else
to_chat(H, span("danger", "You sense great disturbance to your physical body!"))
else
@@ -87,7 +87,7 @@
user.visible_message("[user] attacked [src] with [I] waking [t_him] up!", \
"You attack [src] with [I], waking [t_him] up!")
sleeping = 0
- willfully_sleeping = 0
+ willfully_sleeping = FALSE
if(!effective_force || blocked >= 100)
diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm
index 1108c341ac0..03ae0cf6299 100644
--- a/code/modules/mob/living/carbon/carbon_defines.dm
+++ b/code/modules/mob/living/carbon/carbon_defines.dm
@@ -31,7 +31,7 @@
var/coughedtime = null // should only be useful for carbons as the only thing using it has a carbon arg.
- var/willfully_sleeping = 0
+ var/willfully_sleeping = FALSE
var/consume_nutrition_from_air = FALSE // used by Diona
var/help_up_offer = 0 //if they have their hand out to offer someone up from the ground.
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index e5180d64a1d..fcef2143f62 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -329,7 +329,7 @@
else if(H.client && H.willfully_sleeping)
message = "slaps [M] across the face, waking them up. Ouch!"
H.sleeping = 0
- H.willfully_sleeping = 0
+ H.willfully_sleeping = FALSE
else
message = "slaps [M] across the face. Ouch!"
else
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 0941fdbb9ac..bea02e6889a 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1864,11 +1864,50 @@
return 0
//Get fluffy numbers
-/mob/living/carbon/human/proc/get_blood_pressure()
+/mob/living/carbon/human/proc/blood_pressure()
if(status_flags & FAKEDEATH)
- return "[Floor(120+rand(-5,5))*0.25]/[Floor(80+rand(-5,5)*0.25)]"
+ return list(Floor(120+rand(-5,5))*0.25, Floor(80+rand(-5,5)*0.25))
var/blood_result = get_blood_circulation()
- return "[Floor((120+rand(-5,5))*(blood_result/100))]/[Floor((80+rand(-5,5))*(blood_result/100))]"
+ return list(Floor((120+rand(-5,5))*(blood_result/100)), Floor((80+rand(-5,5))*(blood_result/100)))
+
+//Formats blood pressure for text display
+/mob/living/carbon/human/proc/get_blood_pressure()
+ var/list/bp = blood_pressure()
+ return "[bp[1]]/[bp[2]]"
+
+//Works out blood pressure alert level -- not very accurate
+/mob/living/carbon/human/proc/get_blood_pressure_alert()
+ var/list/bp = blood_pressure()
+ var/systolic_alert
+ var/diastolic_alert
+
+ switch(bp[1])
+ if(BP_HIGH_SYSTOLIC to INFINITY)
+ systolic_alert = 4
+ if(BP_PRE_HIGH_SYSTOLIC to BP_HIGH_SYSTOLIC)
+ systolic_alert = 3
+ if(BP_IDEAL_SYSTOLIC to BP_PRE_HIGH_SYSTOLIC)
+ systolic_alert = 2
+ if(-INFINITY to BP_IDEAL_SYSTOLIC)
+ systolic_alert = 1
+
+ switch(bp[2])
+ if(BP_HIGH_DIASTOLIC to INFINITY)
+ diastolic_alert = 4
+ if(BP_PRE_HIGH_DIASTOLIC to BP_HIGH_DIASTOLIC)
+ diastolic_alert = 3
+ if(BP_IDEAL_DIASTOLIC to BP_PRE_HIGH_DIASTOLIC)
+ diastolic_alert = 2
+ if(-INFINITY to BP_IDEAL_DIASTOLIC)
+ diastolic_alert = 1
+ if(systolic_alert == 4 || diastolic_alert == 4)
+ return 4
+ if(systolic_alert == 3 || diastolic_alert == 3)
+ return 3
+ if(systolic_alert == 1 || diastolic_alert == 1)
+ return 1
+ if(systolic_alert <= 2 && diastolic_alert <= 2)
+ return 2
//Point at which you dun breathe no more. Separate from asystole crit, which is heart-related.
/mob/living/carbon/human/nervous_system_failure()
diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm
index c532e762c78..c4e4033349c 100644
--- a/code/modules/mob/living/carbon/human/human_organs.dm
+++ b/code/modules/mob/living/carbon/human/human_organs.dm
@@ -205,7 +205,7 @@
return TRUE
return FALSE
-/mob/living/carbon/human/proc/get_brain_status()
+/mob/living/carbon/human/proc/get_brain_result()
var/brain_result
if(should_have_organ(BP_BRAIN))
var/obj/item/organ/internal/brain/brain = internal_organs_by_name[BP_BRAIN]
@@ -215,7 +215,10 @@
brain_result = round(max(0,(1 - brain.damage/brain.max_damage)*100))
else
brain_result = -1
+ return brain_result
+/mob/living/carbon/human/proc/get_brain_status()
+ var/brain_result = get_brain_result()
switch(brain_result)
if(0)
brain_result = "none, patient is braindead"
@@ -227,5 +230,5 @@
else if(brain_result <= 80)
brain_result = "[brain_result]%"
else
- brain_result = "[brain_result]%"
+ brain_result = "[brain_result]%"
return brain_result
diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm
index 5caabff8fa4..7c521535918 100644
--- a/code/modules/mob/living/carbon/human/human_powers.dm
+++ b/code/modules/mob/living/carbon/human/human_powers.dm
@@ -223,7 +223,10 @@ mob/living/carbon/human/proc/change_monitor()
return FALSE
/mob/living/carbon/human/can_commune()
- return species ? species.can_commune() : FALSE
+ if(psi)
+ return TRUE
+ else
+ return species ? species.can_commune() : FALSE
/mob/living/carbon/human/proc/commune()
set category = "Abilities"
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index d8634b102e3..a4db1e9b120 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -784,7 +784,7 @@
//CONSCIOUS
else
stat = CONSCIOUS
- willfully_sleeping = 0
+ willfully_sleeping = FALSE
// Check everything else.
diff --git a/code/modules/mob/living/carbon/human/species/station/diona/diona.dm b/code/modules/mob/living/carbon/human/species/station/diona/diona.dm
index cb9a0ea93da..fa6b2278d38 100644
--- a/code/modules/mob/living/carbon/human/species/station/diona/diona.dm
+++ b/code/modules/mob/living/carbon/human/species/station/diona/diona.dm
@@ -28,7 +28,8 @@
siemens_coefficient = 0.3
eyes = "blank_eyes"
show_ssd = "completely quiescent"
- num_alternate_languages = 1
+ num_alternate_languages = 2
+ secondary_langs = list(LANGUAGE_SKRELLIAN)
name_language = LANGUAGE_ROOTSONG
ethanol_resistance = -1 //Can't get drunk
taste_sensitivity = TASTE_DULL
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 7656f0ebbc5..50ab088e0f6 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -60,7 +60,7 @@
var/move_delay_mod = 0//Added to move delay, used for calculating movement speeds. Provides a centralised value for modifiers to alter
- var/total_radiation // DON'T MODIFY THIS DIRECTLY. USE apply_radiation()!
+ var/total_radiation = 0 // DON'T MODIFY THIS DIRECTLY. USE apply_radiation()!
var/cloaked = 0//Set to 1 by cloaking devices, optimises update_icons
var/tesla_ignore = 0 // If true, mob is not affected by tesla bolts.
diff --git a/code/modules/mob/living/simple_animal/hostile/changeling.dm b/code/modules/mob/living/simple_animal/hostile/changeling.dm
index a2e514e1755..468223909df 100644
--- a/code/modules/mob/living/simple_animal/hostile/changeling.dm
+++ b/code/modules/mob/living/simple_animal/hostile/changeling.dm
@@ -38,6 +38,7 @@
max_tox = 0
var/is_devouring = FALSE
+ var/mob/living/carbon/human/occupant = null
/mob/living/simple_animal/hostile/true_changeling/Initialize()
. = ..()
@@ -64,6 +65,8 @@
if(!gibbed)
visible_message("[src] lets out a waning scream as it falls, twitching, to the floor!")
playsound(loc, 'sound/effects/creepyshriek.ogg', 30, 1)
+ if(occupant)
+ qdel(occupant)
gibs(src.loc)
qdel(src)
return
diff --git a/code/modules/modular_computers/file_system/programs/app_presets.dm b/code/modules/modular_computers/file_system/programs/app_presets.dm
index 45e883f60ac..edaf0c3c54e 100644
--- a/code/modules/modular_computers/file_system/programs/app_presets.dm
+++ b/code/modules/modular_computers/file_system/programs/app_presets.dm
@@ -177,6 +177,7 @@
new /datum/computer_file/program/comm(TRUE),
new /datum/computer_file/program/camera_monitor(),
new /datum/computer_file/program/digitalwarrant(),
+ new /datum/computer_file/program/penal_mechs(),
new /datum/computer_file/program/civilian/cargocontrol(),
new /datum/computer_file/program/civilian/cargoorder(),
new /datum/computer_file/program/alarm_monitor(),
@@ -200,6 +201,7 @@
new /datum/computer_file/program/camera_monitor(),
new /datum/computer_file/program/comm(),
new /datum/computer_file/program/digitalwarrant(),
+ new /datum/computer_file/program/penal_mechs(),
new /datum/computer_file/program/records/security()
)
return _prg_list
@@ -216,6 +218,7 @@
new /datum/computer_file/program/chatclient(),
new /datum/computer_file/program/camera_monitor(),
new /datum/computer_file/program/digitalwarrant(),
+ new /datum/computer_file/program/penal_mechs(),
new /datum/computer_file/program/records/security(),
new /datum/computer_file/program/records/employment(),
new /datum/computer_file/program/records/medical()
@@ -235,6 +238,7 @@
new /datum/computer_file/program/civilian/cargoorder(),
new /datum/computer_file/program/camera_monitor(),
new /datum/computer_file/program/digitalwarrant(),
+ new /datum/computer_file/program/penal_mechs(),
new /datum/computer_file/program/records/security(),
new /datum/computer_file/program/records/employment()
)
diff --git a/code/modules/modular_computers/file_system/programs/security/penalmechs.dm b/code/modules/modular_computers/file_system/programs/security/penalmechs.dm
new file mode 100644
index 00000000000..e0ca4f4f921
--- /dev/null
+++ b/code/modules/modular_computers/file_system/programs/security/penalmechs.dm
@@ -0,0 +1,172 @@
+/datum/computer_file/program/penal_mechs
+ filename = "penalmechs"
+ filedesc = "Remote Penal Monitoring"
+ program_icon_state = "security"
+ extended_desc = "This program allows monitoring and control of active penal miner mechs."
+ required_access_run = access_armory
+ required_access_download = access_armory
+ requires_ntnet = 1
+ available_on_ntnet = 1
+ network_destination = "penal mining mech monitoring system"
+ size = 11
+ usage_flags = PROGRAM_ALL_REGULAR
+ color = LIGHT_COLOR_ORANGE
+
+ var/obj/machinery/camera/current_camera = null
+
+/datum/computer_file/program/penal_mechs/ui_interact(mob/user)
+ var/datum/vueui/ui = SSvueui.get_open_ui(user, src)
+ if (!ui)
+ ui = new /datum/vueui/modularcomputer(user, src, "mcomputer-security-penalcontroller", 500, 400, "Penal Mech Monitoring")
+ ui.auto_update_content = 1
+ ui.open()
+
+/datum/computer_file/program/penal_mechs/vueui_transfer(oldobj)
+ for(var/o in SSvueui.transfer_uis(oldobj, src, "mcomputer-security-penalcontroller", 500, 400, "Penal Mech Monitoring"))
+ var/datum/vueui/ui = o
+ // Let's ensure our ui's autoupdate after transfer.
+ // TODO: revert this value on transfer out.
+ ui.auto_update_content = 1
+ return TRUE
+
+/datum/computer_file/program/penal_mechs/vueui_data_change(var/list/data, var/mob/user, var/datum/vueui/ui)
+ . = ..()
+ data = . || data || list()
+
+ // Gather data for computer header
+ data["_PC"] = get_header_data(data["_PC"])
+
+ var/datum/signal/signal
+ signal = telecomms_process_active()
+
+ var/list/mechs = list()
+ var/list/robots = list()
+
+ if(signal.data["done"])
+ for(var/mech in SSvirtualreality.mechs["prisonmechs"])
+ var/mob/living/heavy_vehicle/M = mech
+
+ if(!ismech(M))
+ continue
+ if(!AreConnectedZLevels(computer.loc.z, M.loc.z))
+ continue
+ var/list/mechData = list("location" = null, "name" = null, "pilot" = null, "ref" = "\ref[M]", "camera" = null, "lockdown" = null)
+
+ mechData["name"] = M.name
+ mechData["pilot"] = "[M.old_mob]"
+ var/turf/mech_turf = get_turf(M)
+ mechData["location"] = "[mech_turf.x], [mech_turf.y], [mech_turf.z]"
+
+ mechData["camera_status"] = M.camera.status
+ mechData["lockdown"] = M.lockdown
+ mechs[++mechs.len] = mechData
+
+ for(var/robot in SSvirtualreality.robots["prisonrobots"])
+ var/mob/living/R = robot
+
+ if(!ismob(R))
+ continue
+ if(!AreConnectedZLevels(computer.loc.z, R.loc.z))
+ continue
+ var/list/robotData = list("location" = null, "name" = null, "pilot" = null, "ref" = "\ref[R]")
+
+ robotData["name"] = R.name
+ robotData["pilot"] = "[R.old_mob]"
+ var/turf/robot_turf = get_turf(R)
+ robotData["location"] = "[robot_turf.x], [robot_turf.y], [robot_turf.z]"
+
+ robots[++robots.len] = robotData
+
+ data["mechs"] = sortByKey(mechs, "pilot")
+ data["robots"] = sortByKey(robots, "pilot")
+
+ data["current_cam_loc"] = current_camera ? "\ref[current_camera.loc]" : null
+
+ return data // This UI needs to constantly update
+
+
+/datum/computer_file/program/penal_mechs/Topic(href, href_list)
+ . = ..()
+
+ if(href_list["track_mech"])
+ if(current_camera)
+ reset_current()
+ usr.reset_view()
+ else
+ var/mob/living/heavy_vehicle/M = locate(href_list["track_mech"]) in mob_list
+ if(!istype(M))
+ return FALSE
+ var/obj/machinery/camera/C = M.camera
+ if(C)
+ switch_to_camera(usr, C)
+ return TRUE
+
+ if(href_list["lockdown_mech"])
+ var/mob/living/heavy_vehicle/M = locate(href_list["lockdown_mech"]) in mob_list
+ if(ismob(M))
+ M.ToggleLockdown()
+ return TRUE
+
+ if(href_list["terminate"])
+ var/mob/living/M = locate(href_list["terminate"]) in mob_list
+ if(M?.old_mob && M.vr_mob)
+ to_chat(M, span("warning", "Your connection to remote-controlled [M] is forcibly severed!"))
+ M.body_return()
+ return TRUE
+
+ if(href_list["message_pilot"])
+ var/mob/living/M = locate(href_list["message_pilot"]) in mob_list
+ if(ismob(M))
+ var/message = sanitize(input("Message to [M.old_mob]", "Set Message") as text|null)
+
+ to_chat(usr, span("notice", "Sending message to [M.old_mob]: [message]"))
+ to_chat(M, span("warning", "Remote Penal Monitoring: [message]"))
+ return TRUE
+
+
+// ToDo - Move this set of camera procs to a general datum when more VueUI programs need cameras
+/datum/computer_file/program/penal_mechs/proc/switch_to_camera(var/mob/user, var/obj/machinery/camera/C)
+ //don't need to check if the camera works for AI because the AI jumps to the camera location and doesn't actually look through cameras.
+ if(isAI(user))
+ var/mob/living/silicon/ai/A = user
+ // Only allow non-carded AIs to view because the interaction with the eye gets all wonky otherwise.
+ if(!A.is_in_chassis())
+ return FALSE
+
+ A.eyeobj.setLoc(get_turf(C))
+ A.client.eye = A.eyeobj
+ return TRUE
+
+ set_current(C)
+ user.machine = ui_host()
+ user.reset_view(current_camera)
+ check_eye(user)
+ return TRUE
+
+/datum/computer_file/program/penal_mechs/proc/set_current(var/obj/machinery/camera/C)
+ if(current_camera == C)
+ return
+
+ if(current_camera)
+ reset_current()
+
+ current_camera = C
+ if(current_camera)
+ var/mob/living/L = current_camera.loc
+ if(istype(L))
+ L.tracking_initiated()
+
+/datum/computer_file/program/penal_mechs/proc/reset_current()
+ if(current_camera)
+ var/mob/living/L = current_camera.loc
+ if(istype(L))
+ L.tracking_cancelled()
+ current_camera = null
+
+/datum/computer_file/program/penal_mechs/check_eye(var/mob/user)
+ if(!current_camera)
+ return FALSE
+ var/viewflag = current_camera.check_eye(user)
+ if ( viewflag < 0 ) //camera doesn't work
+ reset_current()
+ return viewflag
\ No newline at end of file
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 3791f76ec82..b76ed483fa5 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -78,6 +78,7 @@
use_power = 0
req_access = list(access_engine_equip)
gfi_layer_rotation = GFI_ROTATION_DEFDIR
+ clicksound = "switch"
var/area/area
var/areastring = null
var/obj/item/cell/cell
diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm
index 6d92afdeff8..9592067ba57 100644
--- a/code/modules/power/smes.dm
+++ b/code/modules/power/smes.dm
@@ -25,6 +25,7 @@
density = 1
anchored = 1
use_power = 0
+ clicksound = "switch"
var/capacity = 5e6 // maximum charge
var/charge = 1e6 // actual charge
diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm
index 6e5e1061bfc..e96ac737a7a 100644
--- a/code/modules/projectiles/guns/energy.dm
+++ b/code/modules/projectiles/guns/energy.dm
@@ -8,6 +8,7 @@
fire_sound_text = "laser blast"
update_icon_on_init = TRUE
+ var/has_icon_ratio = TRUE // Does this gun use the ratio system to modify its icon_state?
var/has_item_ratio = TRUE // Does this gun use the ratio system to paint its item_states?
var/obj/item/cell/power_supply //What type of power cell this uses
@@ -110,6 +111,7 @@
..()
if(charge_meter && power_supply && power_supply.maxcharge)
var/ratio = power_supply.charge / power_supply.maxcharge
+ var/icon_state_ratio = ""
var/item_state_ratio = ""
//make sure that rounding down will not give us the empty state even if we have charge for a shot left.
@@ -118,13 +120,15 @@
else
ratio = max(round(ratio, 0.25) * 100, 25)
+ if(has_icon_ratio)
+ icon_state_ratio = ratio
if(has_item_ratio)
item_state_ratio = ratio
if(modifystate)
- icon_state = "[modifystate][ratio]"
+ icon_state = "[modifystate][icon_state_ratio]"
item_state = "[modifystate][item_state_ratio]"
else
- icon_state = "[initial(icon_state)][ratio]"
+ icon_state = "[initial(icon_state)][icon_state_ratio]"
item_state = "[initial(item_state)][item_state_ratio]"
update_held_icon()
\ No newline at end of file
diff --git a/code/modules/projectiles/guns/energy/modular.dm b/code/modules/projectiles/guns/energy/modular.dm
index 1e2127947cb..8c1653c5545 100644
--- a/code/modules/projectiles/guns/energy/modular.dm
+++ b/code/modules/projectiles/guns/energy/modular.dm
@@ -1,8 +1,10 @@
/obj/item/gun/energy/laser/prototype
name = "laser prototype"
desc = "A custom prototype laser weapon."
- icon_state = "energykill"
- item_state = "energykill"
+ icon = 'icons/obj/guns/modular_laser.dmi'
+ contained_sprite = TRUE
+ has_icon_ratio = FALSE
+ has_item_ratio = FALSE
fire_sound = 'sound/weapons/Laser.ogg'
slot_flags = SLOT_BELT|SLOT_BACK
w_class = 3
@@ -50,9 +52,9 @@
..()
if(origin_chassis == CHASSIS_LARGE)
if(wielded)
- item_state = "heavyprotogun_wielded"
+ item_state = "large_3_wielded"
else
- item_state = "heavyprotogun"
+ item_state = "large_3"
update_held_icon()
/obj/item/gun/energy/laser/prototype/proc/reset_vars()
@@ -118,18 +120,18 @@
/obj/item/gun/energy/laser/prototype/proc/update_chassis()
switch(origin_chassis)
if(CHASSIS_SMALL)
- gun_type = CHASSIS_SMALL
+ gun_type = CHASSIS_SMALL
slot_flags = SLOT_BELT | SLOT_HOLSTER
- item_state = "retro"
+ item_state = "small_3"
if(CHASSIS_MEDIUM)
gun_type = CHASSIS_MEDIUM
slot_flags = SLOT_BELT | SLOT_BACK
- item_state = "energystun"
+ item_state = "medium_3"
is_wieldable = TRUE
if(CHASSIS_LARGE)
gun_type = CHASSIS_LARGE
slot_flags = SLOT_BACK
- item_state = "heavyprotogun"
+ item_state = "large_3"
is_wieldable = TRUE
update_wield_verb()
@@ -321,4 +323,4 @@
desc = input
to_chat(M, "You describe the gun as [input]. Say hello to your new friend.")
described = 1
- return 1
+ return 1
\ No newline at end of file
diff --git a/code/modules/projectiles/guns/projectile/pistol.dm b/code/modules/projectiles/guns/projectile/pistol.dm
index 65c9e3c59cb..33629f20689 100644
--- a/code/modules/projectiles/guns/projectile/pistol.dm
+++ b/code/modules/projectiles/guns/projectile/pistol.dm
@@ -71,7 +71,7 @@
/obj/item/gun/projectile/sec/wood
desc = "A NanoTrasen designed sidearm, found among law enforcement and security forces. It has a wooden grip. Uses .45 rounds."
- description_fluff = "The NT Mk58 is a ballistic sidearm developed and produced by Nanotrasen. Bulky and heavy, the Mk58 is nonetheless used by security forces and law enforcement for its ease of use, low maintenance requirement, longevity, reliability - and most of all, extremely inexpensive price tag. A trademark of Nanotrasen security forces. This one has a wooden grip. It uses .45 rounds."
+ description_fluff = "The NT Mk58 is a ballistic sidearm developed and produced by Nanotrasen. Bulky and heavy, the Mk58 is nonetheless used by security forces and law enforcement for its ease of use, low maintenance requirement, longevity, reliability - and most of all, extremely inexpensive price tag. A trademark of Nanotrasen security forces. This one has a faux wooden grip. It uses .45 rounds."
name = "custom .45 Pistol"
icon = 'icons/obj/guns/secgun_wood.dmi'
icon_state = "secgunwood"
@@ -84,6 +84,23 @@
else
icon_state = "secgunwood-e"
+/obj/item/gun/projectile/sec/detective
+ desc = "A compact NanoTrasen designed sidearm, popular with law enforcement personnel for concealed carry purposes. It has a faux wooden grip. Uses .45 rounds."
+ description_fluff = "The NT Mk21 Blackjack is a ballistic sidearm developed and produced by Nanotrasen. Unlike the related Mk58, the Inspector is a rather high quality piece - typically issued to higher ranking law enforcement personnel, the Mk10 is compact and chambered in .45 caliber. With all the bells and whistles of a modern, quality police pistol, the Inspector's main drawback is the notoriously nippy recoil - .45 in such a small package does not play well with the average shooter."
+ name = "compact .45 pistol"
+ icon = 'icons/obj/guns/detgun.dmi'
+ icon_state = "detgun"
+ item_state = "detgun"
+ w_class = ITEMSIZE_SMALL
+ magazine_type = /obj/item/ammo_magazine/c45m
+
+/obj/item/gun/projectile/sec/detective/update_icon()
+ ..()
+ if(ammo_magazine?.stored_ammo.len)
+ icon_state = "detgun"
+ else
+ icon_state = "detgunempty"
+
/obj/item/gun/projectile/automatic/x9
name = "automatic .45 pistol"
desc = "The x9 tactical pistol is a lightweight fast firing handgun. Uses .45 rounds."
@@ -218,7 +235,8 @@
/obj/item/gun/projectile/pistol
name = "9mm pistol"
- desc = "500 years since its creation and the Stechkin automatic pistol is still a common sight throughout the Frontier."
+ desc = "A compact 9mm handgun, extremely popular all throughout human space."
+ description_fluff = "The Necropolis Industries Moonlight 9mm can be found in the hands of just about anyone imaginable - special operatives, common criminals, police officers, the average Joe - on account of the time-tested design, low price point, reliability, and ease of concealment. Having a threaded barrel helps, too, and it isn't uncommon to see the Moonlight as a prop in spy films, suppressed."
icon = 'icons/obj/guns/pistol.dmi'
icon_state = "pistol"
item_state = "pistol"
@@ -374,4 +392,4 @@
if(ammo_magazine)
icon_state = "adhomian_pistol"
else
- icon_state = "adhomian_pistol-e"
\ No newline at end of file
+ icon_state = "adhomian_pistol-e"
diff --git a/code/modules/projectiles/modular/laser_base.dm b/code/modules/projectiles/modular/laser_base.dm
index b045cbb707f..7c49b0966ab 100644
--- a/code/modules/projectiles/modular/laser_base.dm
+++ b/code/modules/projectiles/modular/laser_base.dm
@@ -1,6 +1,7 @@
/obj/item/laser_components
- icon = 'icons/obj/modular_laser.dmi'
+ icon = 'icons/obj/guns/modular_laser.dmi'
icon_state = "bfg"
+ contained_sprite = TRUE
var/reliability = 0
var/damage = 1
var/fire_delay = 0
@@ -139,8 +140,9 @@
name = "laser assembly (small)"
desc = "A case for shoving things into. Hopefully they work."
w_class = 2
- icon = 'icons/obj/modular_laser.dmi'
+ icon = 'icons/obj/guns/modular_laser.dmi'
icon_state = "small"
+ contained_sprite = TRUE
var/stage = 1
var/size = CHASSIS_SMALL
var/modifier_cap = 3
@@ -194,6 +196,8 @@
/obj/item/device/laser_assembly/proc/finish()
var/obj/item/gun/energy/laser/prototype/A = new /obj/item/gun/energy/laser/prototype
+ A.icon_state = icon_state
+ A.modifystate = icon_state
A.origin_chassis = size
A.capacitor = capacitor
capacitor.forceMove(A)
@@ -205,11 +209,12 @@
for(var/obj/item/laser_components/modifier/mod in gun_mods)
A.gun_mods += mod
mod.forceMove(A)
+ if(mod.gun_overlay)
+ A.underlays += mod.gun_overlay
A.forceMove(get_turf(src))
- A.icon = getFlatIcon(src)
A.updatetype()
A.pin = null
gun_mods = null
focusing_lens = null
capacitor = null
- qdel(src)
+ qdel(src)
\ No newline at end of file
diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm
index 99de3a4e7d1..81740fc9ad4 100644
--- a/code/modules/reagents/Chemistry-Machinery.dm
+++ b/code/modules/reagents/Chemistry-Machinery.dm
@@ -14,6 +14,8 @@
use_power = 1
idle_power_usage = 20
layer = 2.9
+ clicksound = "button"
+
var/beaker = null
var/obj/item/storage/pill_bottle/loaded_pill_bottle = null
var/mode = TRUE
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm
index 55c5060afa1..acd555d92fc 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm
@@ -1547,6 +1547,6 @@
description = "A chemical rampantly used by those seeking to remedy the effects of prolonged zero-gravity adaptations."
reagent_state = LIQUID
color = "#AA8866"
- metabolism = 0.5 * REM
+ metabolism = 0.2 * REM
taste_description = "sourness"
fallback_specific_heat = 1
diff --git a/code/modules/reagents/dispenser/dispenser2.dm b/code/modules/reagents/dispenser/dispenser2.dm
index 85a1230fcfe..5f8c1c08366 100644
--- a/code/modules/reagents/dispenser/dispenser2.dm
+++ b/code/modules/reagents/dispenser/dispenser2.dm
@@ -2,6 +2,7 @@
name = "chemical dispenser"
icon = 'icons/obj/chemical.dmi'
icon_state = "dispenser"
+ clicksound = "button"
var/list/spawn_cartridges = null // Set to a list of types to spawn one of each on New()
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index 93ba24563d2..8d31a9ff9e5 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -74,7 +74,7 @@
return
if(standard_splash_obj(user, target))
return
-
+
if(istype(target, /obj/))
var/obj/O = target
if(!(O.flags & NOBLUDGEON) && reagents)
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index 01a999c0194..90ac7838cbe 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -4,7 +4,7 @@
/obj/item/reagent_containers/hypospray
name = "hypospray"
- desc = "The DeForest Medical Corporation hypospray is a sterile, air-needle autoinjector for administration of drugs to patients."
+ desc = "The Zeng-Hu Pharmaceuticals hypospray is a sterile, air-needle autoinjector for administration of drugs to patients."
icon = 'icons/obj/syringe.dmi'
item_state = "hypo"
icon_state = "hypo"
@@ -15,13 +15,24 @@
flags = OPENCONTAINER
slot_flags = SLOT_BELT
center_of_mass = null
+ drop_sound = 'sound/items/drop/bottle.ogg'
var/armorcheck = 1
var/time = 3 SECONDS
+ var/has_level_sprites = TRUE
matter = list("glass" = 400, DEFAULT_WALL_MATERIAL = 200)
+/obj/item/reagent_containers/hypospray/Initialize()
+ . = ..()
+ update_icon()
+
+/obj/item/reagent_containers/hypospray/on_reagent_change()
+ update_icon()
+ return
+
/obj/item/reagent_containers/hypospray/cmo
name = "premium hypospray"
- desc = "The DeForest Medical Corporation premium hypospray is a cutting-edge, sterile, air-needle autoinjector for rapid administration of drugs to patients."
+ desc = "The Zeng-Hu Pharmaceuticalsn premium hypospray is a cutting-edge, sterile, air-needle autoinjector for rapid administration of drugs to patients."
+ item_state = "cmo_hypo"
volume = 30
time = 0
@@ -36,6 +47,22 @@
if(!do_mob(user, M, inj_time))
return 1
+/obj/item/reagent_containers/hypospray/update_icon()
+ if(!has_level_sprites)
+ return
+ var/percent = round((reagents.total_volume / 10) * 100)
+ switch(percent)
+ if(0 to 25)
+ icon_state = "[item_state]"
+ if(26 to 50)
+ icon_state = "[item_state]_25"
+ if(51 to 75)
+ icon_state = "[item_state]_50"
+ if(76 to 99)
+ icon_state = "[item_state]_75"
+ if(100 to INFINITY)
+ icon_state = "[item_state]_100"
+
/obj/item/reagent_containers/hypospray/afterattack(var/mob/M, var/mob/user, proximity)
if (!istype(M))
@@ -74,6 +101,7 @@
amount_per_transfer_from_this = 5
volume = 5
time = 0
+ has_level_sprites = FALSE
/obj/item/reagent_containers/hypospray/autoinjector/Initialize()
. =..()
@@ -168,6 +196,7 @@
volume = 20
armorcheck = 0
time = 0
+ has_level_sprites = FALSE
/obj/item/reagent_containers/hypospray/combat/Initialize()
. = ..()
diff --git a/code/modules/shareddream/brainghost.dm b/code/modules/shareddream/brainghost.dm
index 3904628445e..de9d59b5612 100644
--- a/code/modules/shareddream/brainghost.dm
+++ b/code/modules/shareddream/brainghost.dm
@@ -31,7 +31,7 @@
if(body.willfully_sleeping)
body.sleeping = max(body.sleeping - 5, 0)
- body.willfully_sleeping = 0
+ body.willfully_sleeping = FALSE
if(force_awaken)
to_chat(src, "You suddenly feel like your connection to the dream is breaking up by the outside force.")
else
diff --git a/code/modules/telesci/gps.dm b/code/modules/telesci/gps.dm
index 923bdc072f9..fc6795be987 100644
--- a/code/modules/telesci/gps.dm
+++ b/code/modules/telesci/gps.dm
@@ -1,7 +1,5 @@
var/list/GPS_list = list()
-var/global/list/gps_by_type = list()
-
/obj/item/device/gps
name = "global positioning system"
desc = "Helping lost spacemen find their way through the planets since 2016."
@@ -13,69 +11,153 @@ var/global/list/gps_by_type = list()
var/gps_prefix = "COM"
var/gpstag = "COM0"
var/emped = 0
+ var/held_by = null
var/turf/locked_location
+ var/list/tracking = list()
+ var/list/static/gps_count = list()
/obj/item/device/gps/Initialize()
. = ..()
- GPS_list += src
- LAZYADD(gps_by_type["[type]"], src)
- gpstag = "[gps_prefix][LAZYLEN(gps_by_type["[type]"])]"
+ gpstag = next_initial_tag()
name = "global positioning system ([gpstag])"
+ update_position()
add_overlay("working")
+ moved_event.register(src, src, /obj/item/device/gps/proc/update_position)
+
+ for(var/gps in GPS_list)
+ tracking += GPS_list[gps]["tag"]
/obj/item/device/gps/Destroy()
- GPS_list -= src
- var/list/typelist = gps_by_type["[type]"]
- LAZYREMOVE(typelist, src)
+ GPS_list -= GPS_list[gpstag]
+ moved_event.unregister(src, src)
+ if(held_by)
+ moved_event.unregister(held_by, src)
+ held_by = null
return ..()
+/obj/item/device/gps/pickup(var/mob/user)
+ ..()
+ held_by = user
+ moved_event.register(user, src, /obj/item/device/gps/proc/update_position)
+
+/obj/item/device/gps/dropped(var/mob/user)
+ ..()
+ held_by = null
+ moved_event.unregister(user, src)
+
/obj/item/device/gps/emp_act(severity)
emped = 1
cut_overlay("working")
add_overlay("emp")
addtimer(CALLBACK(src, .proc/post_emp), 300)
+ update_position()
/obj/item/device/gps/proc/post_emp()
emped = 0
cut_overlay("emp")
add_overlay("working")
+ update_position()
+
+/obj/item/device/gps/vueui_data_change(var/list/data, var/mob/user, var/datum/vueui/ui)
+ if(!data)
+ . = data = list()
+
+ VUEUI_SET_CHECK(data["own_tag"], gpstag, . , data)
+
+ var/list/tracking_list = list()
+ for(var/tracking_tag in sortList(tracking))
+ if(!GPS_list[tracking_tag]) // Another GPS device has changed its tag or been destroyed
+ tracking -= tracking_tag
+ continue
+
+ if(AreConnectedZLevels(loc.z, GPS_list[tracking_tag]["pos_z"]))
+ tracking_list[tracking_tag] = (GPS_list[tracking_tag])
+
+ VUEUI_SET_CHECK(data["tracking_list"], tracking_list, ., data)
/obj/item/device/gps/attack_self(mob/user)
+ if(!emped)
+ ui_interact(user)
- var/obj/item/device/gps/t = ""
- var/gps_window_height = 110 + GPS_list.len * 20 // Variable window height, depending on how many GPS units there are to show
- if(emped)
- t += "ERROR"
- else
- t += "
Set Tag "
- t += "
Tag: [gpstag]"
- if(locked_location && locked_location.loc)
- t += "
Bluespace coordinates saved: [locked_location.loc]"
- gps_window_height += 20
-
- for(var/obj/item/device/gps/G in GPS_list)
- var/turf/pos = get_turf(G)
- var/area/gps_area = get_area(G)
- var/tracked_gpstag = G.gpstag
- if(G.emped == 1 || !pos)
- t += "
[tracked_gpstag]: ERROR"
- else
- t += "
[tracked_gpstag]: [format_text(gps_area.name)] ([pos.x], [pos.y], [pos.z])"
-
- var/datum/browser/popup = new(user, "GPS", name, 360, min(gps_window_height, 800))
- popup.set_content(t)
- popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
- popup.open()
+/obj/item/device/gps/ui_interact(mob/user)
+ var/datum/vueui/ui = SSvueui.get_open_ui(user, src)
+ if (!ui)
+ ui = new(user, src, "devices-gps-gps", 460, 600, capitalize(name))
+ ui.auto_update_content = TRUE
+ ui.open()
/obj/item/device/gps/Topic(href, href_list)
..()
- if(href_list["tag"] )
- var/a = input("Please enter desired tag.", name, gpstag) as text
- a = uppertext(copytext(sanitize(a), 1, 5))
- if(src.loc == usr)
- gpstag = a
- name = "global positioning system ([gpstag])"
- attack_self(usr)
+
+ if(href_list["tag"])
+ var/set_tag = uppertext(copytext(sanitize(href_list["tag"]), 1, 8))
+
+ var/was_tracked // If we were tracking this, we want to keep it on the list with its new tag
+ if(gpstag in tracking)
+ was_tracked = TRUE
+ tracking -= gpstag
+
+ if(loc == usr)
+ if(!GPS_list[set_tag])
+ GPS_list[gpstag] = null
+ gpstag = set_tag
+ name = "global positioning system ([gpstag])"
+
+ var/datum/vueui/ui = SSvueui.get_open_ui(usr, src)
+ if(ui)
+ ui.title = capitalize(name)
+
+ update_position()
+
+ if(was_tracked)
+ tracking |= gpstag
+ else
+ to_chat(usr, span("warning", "GPS tag already assigned, choose another."))
+
+ return TRUE
+
+ if(href_list["add_tag"])
+ var/new_tag = uppertext(copytext(sanitize(href_list["add_tag"]), 1, 8))
+
+ if(GPS_list[new_tag])
+ tracking |= new_tag
+ return TRUE
+ else
+ to_chat(usr, "Could not locate GPS tag.")
+ return TRUE
+
+ if(href_list["remove_tag"])
+ tracking -= href_list["remove_tag"]
+
+ return TRUE
+
+ if(href_list["add_all"])
+ tracking.Cut()
+ for(var/gps in GPS_list)
+ tracking += GPS_list[gps]["tag"]
+
+ return TRUE
+
+ if(href_list["clear_all"])
+ tracking.Cut()
+ tracking |= gpstag // always want to track ourselves
+
+ return TRUE
+
+ return FALSE
+
+/obj/item/device/gps/proc/update_position()
+ var/turf/T = get_turf(src)
+ GPS_list[gpstag] = list("tag" = gpstag, "pos_x" = T.x, "pos_y" = T.y, "pos_z" = T.z, "area" = "[get_area(src).name]", "emped" = emped)
+
+/obj/item/device/gps/proc/next_initial_tag()
+ if(!LAZYACCESS(gps_count, gps_prefix))
+ gps_count[gps_prefix] = 0
+
+ . = "[gps_prefix][gps_count[gps_prefix]++]"
+
+ if(GPS_list[.]) // if someone has renamed a GPS manually to take this tag already
+ . = next_initial_tag()
/obj/item/device/gps/science
icon_state = "gps-s"
diff --git a/dynamic_maps/.gitignore b/dynamic_maps/.gitignore
new file mode 100644
index 00000000000..f826bafcfa1
--- /dev/null
+++ b/dynamic_maps/.gitignore
@@ -0,0 +1 @@
+*.dmm
\ No newline at end of file
diff --git a/html/changelog.html b/html/changelog.html
index 8afe99556d0..15e61367d91 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -35,6 +35,97 @@
-->
{{url}}{{ JSON.stringify(this.$root.$data, null, ' ') }}{{url}}{{ JSON.stringify(this.$root.$data, null, ' ') }}1&&void 0!==arguments[1]?arguments[1]:{limit:!1};this._log('---------\nSearch pattern: "'.concat(t,'"'));var n=this._prepareSearchers(t),r=n.tokenSearchers,a=n.fullSearcher,i=this._search(r,a),o=i.weights,s=i.results;return this._computeScore(o,s),this.options.shouldSort&&this._sort(s),e.limit&&"number"==typeof e.limit&&(s=s.slice(0,e.limit)),this._format(s)}},{key:"_prepareSearchers",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",e=[];if(this.options.tokenize)for(var n=t.split(this.options.tokenSeparator),r=0,a=n.length;r0&&void 0!==arguments[0]?arguments[0]:[],e=arguments.length>1?arguments[1]:void 0,n=this.list,r={},a=[];if("string"==typeof n[0]){for(var i=0,o=n.length;i Please configure your pAI personality's options. Remember, what you enter here could determine whether or not the user requesting a personality chooses you! \n What you plan to call yourself. Suggestions: Any character name you would choose for a station character OR an AI.\n \n Do you like to partner with sneaky social ninjas? Like to help security hunt down thugs? Enjoy watching an engineer's back while he saves the station yet again? This doesn't have to be limited to just station jobs. Pretty much any general descriptor for what you'd like to be doing works here.\n , or missing
\n Power Supply
\n File System
\n Computer Components
\n {{name}}
\n
\n \n
\n \n \n Name \n Description \n Available Slots \n Actions \n \n \n {{data.name}} \n {{data.desc}} \n 0\">{{data.max_count - data.count}} / {{data.max_count}} \n ∞ \n \n \n
'))}}),_c('vui-button',{attrs:{\"params\":{ _openurl: item[4] }}},[_vm._v(\"Open\")])],1)}),0)]:_vm._e(),_vm._t(\"default\")],2),(!_vm.hideAdvanced && (_vm.avaivabletypes & 1))?_c('vui-button',{staticClass:\"danger\",attrs:{\"params\":{ deleterecord: 1 },\"icon\":\"trash-alt\"}},[_vm._v(\"Delete record\")]):_vm._e()],1):_vm._e()}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n
\n {{ item[0] }} ({{ item[1] }})
\n ')\"/>\n \n {{state._PC.batterypercent}}\n
\n
\n \n
Tank Control System
\n
\n
\n Selected Products:
\n Total: {{ priceSum }}
\n Destination Account: {{ destinationact }}
\n Please swipe your ID to pay.
\n Debug this UI with inspector by opening URL in your browser:
{{url}}Current data of UI:
{{ JSON.stringify(this.$root.$data, null, \\' \\') }}Fuel Injection System
\n \n
\n
\n \n \n
\n Please insert something to copy.
\n
\n Please insert a new toner cartridge!
\n \n \n\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./img.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./img.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./img.vue?vue&type=template&id=6aea3df6&\"\nimport script from \"./img.vue?vue&type=script&lang=js&\"\nexport * from \"./img.vue?vue&type=script&lang=js&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","var isObject = require('../internals/is-object');\n\nmodule.exports = function (it) {\n if (!isObject(it)) {\n throw TypeError(String(it) + ' is not an object');\n } return it;\n};\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('vui-input-search',{attrs:{\"input\":_vm.records,\"keys\":['id', 'name', 'rank']},model:{value:(_vm.filtered),callback:function ($$v) {_vm.filtered=$$v},expression:\"filtered\"}}),_vm._l((_vm.filtered),function(record){return _c('div',{key:record.id},[_c('vui-button',{attrs:{\"params\":{ setactive_virus: record.id},\"push-state\":\"\"},on:{\"click\":function($event){_vm.activeview = _vm.defaultview}}},[_vm._v(_vm._s(record.id)+\": \"+_vm._s(record.name))])],1)})],2)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n
Sensor Data:
\n No sensors connected.\n
\n PDAs to notify:
\n