From fa56a1014984844c71253b788f64f61cd6c1566b Mon Sep 17 00:00:00 2001
From: Iajret <8430839+Iajret@users.noreply.github.com>
Date: Sat, 20 Jun 2026 00:52:44 +0300
Subject: [PATCH] FaxBond app for bonding with your fax (fax message
subscription app) (#96467)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## About The Pull Request
Adds an up that allows you to subscribe to any fax. Heads start with one
by default and they are subscribed to their office fax upon joining.
Later part involved creation of fax subtype specific to a head. So i
decided to also make those as a required map item for the purposes of
CI.
UI
its pretty simplistic, but i am not a UI designer, sorry
## Why It's Good For The Game
It really sucks when you wait for someones message but they never
respond to it because apparently they never visit their office and never
saw a paper over their fax if even if they responded, by the time you
get an answer you already forgot about it anyway. In general, it makes
paperwork experience relating to faxes more enjoyable (probably)
## Changelog
:cl:
add: added a FaxBond app. Everyone can download it and use it on a fax
of their choice to be notified when it receives a message. Heads of
staff come with it preinstalled and automatically subscribed to a fax
inside their office.
/:cl:
---
.../CatwalkStation/CatwalkStation_2023.dmm | 35 ++----
.../map_files/Deltastation/DeltaStation2.dmm | 35 ++----
.../map_files/IceBoxStation/IceBoxStation.dmm | 35 ++----
_maps/map_files/MetaStation/MetaStation.dmm | 35 ++----
.../map_files/NebulaStation/NebulaStation.dmm | 35 ++----
_maps/map_files/tramstation/tramstation.dmm | 35 ++----
_maps/map_files/wawastation/wawastation.dmm | 35 ++----
code/__DEFINES/dcs/signals/signals_fax.dm | 1 +
.../computers/item/role_tablet_presets.dm | 17 +++
.../file_system/programs/faxnotif.dm | 119 ++++++++++++++++++
code/modules/paperwork/fax.dm | 36 ++++++
code/modules/unit_tests/required_map_items.dm | 1 +
tgstation.dme | 2 +
tgui/packages/tgui/interfaces/NtosFaxBond.tsx | 85 +++++++++++++
14 files changed, 310 insertions(+), 196 deletions(-)
create mode 100644 code/__DEFINES/dcs/signals/signals_fax.dm
create mode 100644 code/modules/modular_computers/file_system/programs/faxnotif.dm
create mode 100644 tgui/packages/tgui/interfaces/NtosFaxBond.tsx
diff --git a/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm b/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm
index 2b43ae43fb3..168d97dfb35 100644
--- a/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm
+++ b/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm
@@ -6147,10 +6147,7 @@
"bCC" = (
/obj/machinery/status_display/evac/directional/north,
/obj/structure/table/wood,
-/obj/machinery/fax{
- fax_name = "Captain's Office";
- name = "Captain's Fax Machine"
- },
+/obj/machinery/fax/heads/captain,
/turf/open/floor/wood/large,
/area/station/command/heads_quarters/captain/private)
"bCH" = (
@@ -18908,11 +18905,8 @@
dir = 8
},
/obj/structure/table,
-/obj/machinery/fax{
- fax_name = "Quartermaster's Office";
- name = "Quartermaster's Fax Machine"
- },
/obj/machinery/firealarm/directional/west,
+/obj/machinery/fax/heads/qm,
/turf/open/floor/wood/parquet,
/area/station/command/heads_quarters/qm)
"eYe" = (
@@ -24244,13 +24238,10 @@
/area/station/service/janitor)
"gqc" = (
/obj/structure/table/reinforced/rglass,
-/obj/machinery/fax{
- fax_name = "Chief Engineer's Office";
- name = "Chief Engineer's Fax Machine"
- },
/obj/effect/turf_decal/siding/yellow/end{
dir = 8
},
+/obj/machinery/fax/heads/ce,
/turf/open/floor/engine,
/area/station/command/heads_quarters/ce)
"gqj" = (
@@ -29012,12 +29003,9 @@
/turf/open/floor/wood,
/area/station/command/corporate_showroom)
"hIg" = (
-/obj/machinery/fax{
- fax_name = "Head of Personnel's Office";
- name = "Head of Personnel's Fax Machine"
- },
/obj/structure/table/wood,
/obj/machinery/newscaster/directional/east,
+/obj/machinery/fax/heads/hop,
/turf/open/floor/wood/tile,
/area/station/command/heads_quarters/hop)
"hIj" = (
@@ -63250,10 +63238,7 @@
/area/station/commons/fitness/recreation)
"qPq" = (
/obj/structure/table,
-/obj/machinery/fax{
- fax_name = "Head of Security's Office";
- name = "Head of Security's Fax Machine"
- },
+/obj/machinery/fax/heads/hos,
/turf/open/floor/wood,
/area/station/command/heads_quarters/hos)
"qPs" = (
@@ -69362,10 +69347,7 @@
/obj/effect/turf_decal/trimline/dark_blue/filled/line{
dir = 1
},
-/obj/machinery/fax{
- fax_name = "Chief Medical Officer's Office";
- name = "Chief Medical Officer's Fax Machine"
- },
+/obj/machinery/fax/heads/cmo,
/turf/open/floor/holofloor/dark,
/area/station/command/heads_quarters/cmo)
"syb" = (
@@ -83445,11 +83427,8 @@
/area/station/engineering/atmos/office)
"wha" = (
/obj/structure/cable,
-/obj/machinery/fax{
- fax_name = "Research Director's Office";
- name = "Research Director's Fax Machine"
- },
/obj/structure/table,
+/obj/machinery/fax/heads/rd,
/turf/open/floor/wood,
/area/station/command/heads_quarters/rd)
"whi" = (
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index 6b9115f4b99..6031abb9832 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -12832,12 +12832,9 @@
"deW" = (
/obj/machinery/computer/security/telescreen/entertainment/directional/north,
/obj/structure/table,
-/obj/machinery/fax{
- fax_name = "Chief Medical Officer's Office";
- name = "Chief Medical Officer's Fax Machine"
- },
/obj/effect/turf_decal/tile/blue/opposingcorners,
/obj/machinery/light/cold/directional/north,
+/obj/machinery/fax/heads/cmo,
/turf/open/floor/iron/white,
/area/station/command/heads_quarters/cmo)
"deX" = (
@@ -14882,13 +14879,10 @@
/obj/structure/cable,
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/structure/table/reinforced,
-/obj/machinery/fax{
- fax_name = "Research Director's Office";
- name = "Research Director's Fax Machine"
- },
/obj/effect/turf_decal/tile/purple{
dir = 8
},
+/obj/machinery/fax/heads/rd,
/turf/open/floor/iron/white,
/area/station/command/heads_quarters/rd)
"dGs" = (
@@ -16747,11 +16741,8 @@
"edS" = (
/obj/machinery/firealarm/directional/south,
/obj/structure/table/reinforced,
-/obj/machinery/fax{
- fax_name = "Chief Engineer's Office";
- name = "Chief Engineer's Fax Machine"
- },
/obj/effect/turf_decal/tile/neutral/fourcorners,
+/obj/machinery/fax/heads/ce,
/turf/open/floor/iron/dark,
/area/station/command/heads_quarters/ce)
"edW" = (
@@ -28965,13 +28956,10 @@
/area/space/nearstation)
"haq" = (
/obj/structure/table,
-/obj/machinery/fax{
- fax_name = "Quartermaster's Office";
- name = "Quartermaster's Fax Machine"
- },
/obj/effect/turf_decal/tile/brown/anticorner/contrasted{
dir = 1
},
+/obj/machinery/fax/heads/qm,
/turf/open/floor/iron,
/area/station/command/heads_quarters/qm)
"haw" = (
@@ -38301,12 +38289,9 @@
/area/station/service/library/lounge)
"jst" = (
/obj/structure/table/wood,
-/obj/machinery/fax{
- fax_name = "Head of Security's Office";
- name = "Head of Security's Fax Machine"
- },
/obj/effect/turf_decal/tile/neutral/fourcorners,
/obj/structure/sign/nanotrasen/directional/north,
+/obj/machinery/fax/heads/hos,
/turf/open/floor/iron/dark,
/area/station/command/heads_quarters/hos)
"jsL" = (
@@ -44901,10 +44886,7 @@
"lbt" = (
/obj/structure/table/wood,
/obj/machinery/newscaster/directional/east,
-/obj/machinery/fax{
- fax_name = "Head of Personnel's Office";
- name = "Head of Personnel's Fax Machine"
- },
+/obj/machinery/fax/heads/hop,
/turf/open/floor/wood,
/area/station/command/heads_quarters/hop)
"lbu" = (
@@ -74913,11 +74895,8 @@
/area/station/security/checkpoint/medical/medsci)
"swj" = (
/obj/structure/table/wood,
-/obj/machinery/fax{
- fax_name = "Captain's Office";
- name = "Captain's Fax Machine"
- },
/obj/structure/sign/nanotrasen/directional/west,
+/obj/machinery/fax/heads/captain,
/turf/open/floor/wood,
/area/station/command/heads_quarters/captain)
"swn" = (
diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm
index a31a47131c1..93372524aa3 100644
--- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm
+++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm
@@ -865,10 +865,7 @@
"anP" = (
/obj/structure/table,
/obj/machinery/light_switch/directional/north,
-/obj/machinery/fax{
- fax_name = "Research Director's Office";
- name = "Research Director's Fax Machine"
- },
+/obj/machinery/fax/heads/rd,
/turf/open/floor/iron/white/side{
dir = 1
},
@@ -1958,12 +1955,9 @@
"aBi" = (
/obj/effect/turf_decal/trimline/blue/filled/line,
/obj/structure/table/glass,
-/obj/machinery/fax{
- fax_name = "Chief Medical Officer's Office";
- name = "Chief Medical Officer's Fax Machine"
- },
/obj/machinery/light/cold/directional/south,
/obj/machinery/firealarm/directional/south,
+/obj/machinery/fax/heads/cmo,
/turf/open/floor/iron/dark,
/area/station/command/heads_quarters/cmo)
"aBE" = (
@@ -5590,10 +5584,7 @@
/area/station/service/chapel)
"bAT" = (
/obj/structure/table/reinforced,
-/obj/machinery/fax{
- fax_name = "Chief Engineer's Office";
- name = "Chief Engineer's Fax Machine"
- },
+/obj/machinery/fax/heads/ce,
/turf/open/floor/iron,
/area/station/command/heads_quarters/ce)
"bAX" = (
@@ -17424,10 +17415,7 @@
/area/station/service/hydroponics)
"eUn" = (
/obj/structure/table/wood,
-/obj/machinery/fax{
- fax_name = "Head of Security's Office";
- name = "Head of Security's Fax Machine"
- },
+/obj/machinery/fax/heads/hos,
/turf/open/floor/wood/large,
/area/station/command/heads_quarters/hos)
"eUx" = (
@@ -60778,13 +60766,10 @@
/area/icemoon/underground/explored)
"rdf" = (
/obj/structure/table/wood,
-/obj/machinery/fax{
- fax_name = "Captain's Office";
- name = "Captain's Fax Machine"
- },
/obj/effect/turf_decal/siding/wood{
dir = 8
},
+/obj/machinery/fax/heads/captain,
/turf/open/floor/iron/dark,
/area/station/command/heads_quarters/captain)
"rdg" = (
@@ -77884,10 +77869,7 @@
dir = 4
},
/obj/structure/table,
-/obj/machinery/fax{
- fax_name = "Head of Personnel's Office";
- name = "Head of Personnel's Fax Machine"
- },
+/obj/machinery/fax/heads/hop,
/turf/open/floor/iron,
/area/station/command/heads_quarters/hop)
"vYq" = (
@@ -81692,13 +81674,10 @@
/obj/machinery/power/apc/auto_name/directional/west,
/obj/structure/cable,
/obj/structure/table,
-/obj/machinery/fax{
- fax_name = "Quartermaster's Office";
- name = "Quartermaster's Fax Machine"
- },
/obj/effect/turf_decal/tile/brown/half/contrasted{
dir = 8
},
+/obj/machinery/fax/heads/qm,
/turf/open/floor/iron,
/area/station/command/heads_quarters/qm)
"xen" = (
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index 316f1b0f0f2..611118b44a2 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -8540,13 +8540,10 @@
/area/station/maintenance/port/aft)
"cYc" = (
/obj/structure/table/reinforced,
-/obj/machinery/fax{
- fax_name = "Chief Engineer's Office";
- name = "Chief Engineer's Fax Machine"
- },
/obj/effect/turf_decal/tile/neutral/half/contrasted{
dir = 4
},
+/obj/machinery/fax/heads/ce,
/turf/open/floor/iron,
/area/station/command/heads_quarters/ce)
"cYx" = (
@@ -22558,10 +22555,6 @@
dir = 1
},
/obj/structure/table/wood,
-/obj/machinery/fax{
- fax_name = "Quartermaster";
- name = "Quartermaster's Fax Machine"
- },
/obj/structure/disposalpipe/segment{
dir = 8
},
@@ -22573,6 +22566,7 @@
/obj/effect/mapping_helpers/requests_console/assistance,
/obj/effect/mapping_helpers/requests_console/information,
/obj/effect/mapping_helpers/requests_console/ore_update,
+/obj/machinery/fax/heads/qm,
/turf/open/floor/wood/large,
/area/station/command/heads_quarters/qm)
"hQu" = (
@@ -23730,10 +23724,7 @@
/obj/structure/cable,
/obj/machinery/power/apc/auto_name/directional/north,
/obj/structure/table/wood,
-/obj/machinery/fax{
- fax_name = "Head of Personnel's Office";
- name = "Head of Personnel's Fax Machine"
- },
+/obj/machinery/fax/heads/hop,
/turf/open/floor/carpet,
/area/station/command/heads_quarters/hop)
"iiL" = (
@@ -27716,11 +27707,8 @@
/area/station/medical/chemistry)
"jxv" = (
/obj/structure/table/wood,
-/obj/machinery/fax{
- fax_name = "Captain's Office";
- name = "Captain's Fax Machine"
- },
/obj/structure/window/reinforced/spawner/directional/south,
+/obj/machinery/fax/heads/captain,
/turf/open/floor/wood,
/area/station/command/heads_quarters/captain/private)
"jxM" = (
@@ -47634,10 +47622,7 @@
/obj/machinery/power/apc/auto_name/directional/east,
/obj/structure/table/wood,
/obj/structure/cable,
-/obj/machinery/fax{
- fax_name = "Head of Security's Office";
- name = "Head of Security's Fax Machine"
- },
+/obj/machinery/fax/heads/hos,
/turf/open/floor/iron/dark,
/area/station/command/heads_quarters/hos)
"qmi" = (
@@ -62039,13 +62024,10 @@
"vgZ" = (
/obj/structure/table/glass,
/obj/structure/cable,
-/obj/machinery/fax{
- fax_name = "Chief Medical Officer's Office";
- name = "Chief Medical Officer's Fax Machine"
- },
/obj/effect/turf_decal/tile/blue/half/contrasted{
dir = 1
},
+/obj/machinery/fax/heads/cmo,
/turf/open/floor/iron/white,
/area/station/command/heads_quarters/cmo)
"vhb" = (
@@ -70099,13 +70081,10 @@
/obj/machinery/power/apc/auto_name/directional/west,
/obj/structure/cable,
/obj/structure/table,
-/obj/machinery/fax{
- fax_name = "Research Director's Office";
- name = "Research Director's Fax Machine"
- },
/obj/effect/turf_decal/tile/neutral/opposingcorners{
dir = 1
},
+/obj/machinery/fax/heads/rd,
/turf/open/floor/iron/dark,
/area/station/command/heads_quarters/rd)
"xPx" = (
diff --git a/_maps/map_files/NebulaStation/NebulaStation.dmm b/_maps/map_files/NebulaStation/NebulaStation.dmm
index 4237d32c715..0760f2c0f9a 100644
--- a/_maps/map_files/NebulaStation/NebulaStation.dmm
+++ b/_maps/map_files/NebulaStation/NebulaStation.dmm
@@ -15557,10 +15557,7 @@
/area/station/service/library/printer)
"cqG" = (
/obj/structure/table/reinforced/rglass,
-/obj/machinery/fax{
- fax_name = "Research Director's Office";
- name = "Research Director's Fax Machine"
- },
+/obj/machinery/fax/heads/rd,
/turf/open/floor/carpet/purple,
/area/station/command/heads_quarters/rd)
"cqH" = (
@@ -19865,12 +19862,9 @@
/turf/open/floor/iron/dark,
/area/station/engineering/atmos)
"cXo" = (
-/obj/machinery/fax{
- fax_name = "Chief Engineer's Office";
- name = "Chief Engineer's Fax Machine"
- },
/obj/item/disk/computer/engineering,
/obj/structure/table/reinforced/rglass,
+/obj/machinery/fax/heads/ce,
/turf/open/floor/carpet/orange,
/area/station/command/heads_quarters/ce)
"cXs" = (
@@ -22743,11 +22737,8 @@
},
/obj/effect/turf_decal/siding/wood,
/obj/structure/table/wood,
-/obj/machinery/fax{
- fax_name = "Detective's Office";
- name = "Detective's Fax Machine"
- },
/obj/structure/detectiveboard/directional/north,
+/obj/machinery/fax/heads/hos,
/turf/open/floor/wood/large,
/area/station/security/detectives_office)
"dsq" = (
@@ -67552,10 +67543,7 @@
/obj/item/folder/blue,
/obj/item/clothing/neck/stethoscope,
/obj/item/clothing/glasses/hud/health,
-/obj/machinery/fax{
- fax_name = "Chief Medical Officer's Office";
- name = "Chief Medical Officer's Fax Machine"
- },
+/obj/machinery/fax/heads/cmo,
/turf/open/floor/carpet/blue,
/area/station/command/heads_quarters/cmo)
"jWn" = (
@@ -68761,10 +68749,7 @@
/area/station/hallway/secondary/service)
"kfr" = (
/obj/structure/table/reinforced/rglass,
-/obj/machinery/fax{
- fax_name = "Captain's Office";
- name = "Captain's Fax Machine"
- },
+/obj/machinery/fax/heads/captain,
/turf/open/floor/carpet/royalblue,
/area/station/command/heads_quarters/captain)
"kfu" = (
@@ -74259,10 +74244,7 @@
/area/station/engineering/break_room)
"kRR" = (
/obj/structure/table/reinforced/rglass,
-/obj/machinery/fax{
- fax_name = "Head of Personnel's Office";
- name = "Head of Personnel's Fax Machine"
- },
+/obj/machinery/fax/heads/hop,
/turf/open/floor/carpet/royalblue,
/area/station/command/heads_quarters/hop)
"kSl" = (
@@ -111360,11 +111342,8 @@
/area/station/command/heads_quarters/hop)
"quR" = (
/obj/structure/table/reinforced/rglass,
-/obj/machinery/fax{
- fax_name = "Quartermaster's Office";
- name = "Quartermaster's Fax Machine"
- },
/obj/item/paperwork/cargo,
+/obj/machinery/fax/heads/qm,
/turf/open/floor/carpet,
/area/station/command/heads_quarters/qm)
"quT" = (
diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm
index 7e9d064585a..acaaaec1f6f 100644
--- a/_maps/map_files/tramstation/tramstation.dmm
+++ b/_maps/map_files/tramstation/tramstation.dmm
@@ -5541,11 +5541,8 @@
/area/station/science/xenobiology)
"aPm" = (
/obj/structure/table/glass,
-/obj/machinery/fax{
- name = "Chief Medical Officer's Fax Machine";
- fax_name = "Chief Medical Officer's Office"
- },
/obj/effect/turf_decal/tile/blue/fourcorners,
+/obj/machinery/fax/heads/cmo,
/turf/open/floor/iron/dark,
/area/station/command/heads_quarters/cmo)
"aPs" = (
@@ -31137,10 +31134,6 @@
/area/station/science/ordnance/storage)
"jXF" = (
/obj/structure/table,
-/obj/machinery/fax{
- name = "Research Director's Fax Machine";
- fax_name = "Research Director's Office"
- },
/obj/machinery/button/door/directional/south{
name = "Science Lockdown Toggle";
pixel_x = -6;
@@ -31167,6 +31160,7 @@
id = "misclab";
req_access = list("xenobiology")
},
+/obj/machinery/fax/heads/rd,
/turf/open/floor/iron/cafeteria,
/area/station/command/heads_quarters/rd)
"jXG" = (
@@ -55621,10 +55615,7 @@
/obj/effect/turf_decal/trimline/yellow/filled/line{
dir = 1
},
-/obj/machinery/fax{
- name = "Chief Engineer's Fax Machine";
- fax_name = "Chief Engineer's Office"
- },
+/obj/machinery/fax/heads/ce,
/turf/open/floor/iron/dark,
/area/station/command/heads_quarters/ce)
"suR" = (
@@ -58017,10 +58008,7 @@
"toY" = (
/obj/structure/table/wood,
/obj/structure/reagent_dispensers/wall/peppertank/directional/east,
-/obj/machinery/fax{
- name = "Head of Security's Fax Machine";
- fax_name = "Head of Security's Office"
- },
+/obj/machinery/fax/heads/hos,
/turf/open/floor/carpet,
/area/station/command/heads_quarters/hos)
"tpm" = (
@@ -67340,10 +67328,7 @@
dir = 8
},
/obj/structure/sign/calendar/directional/west,
-/obj/machinery/fax{
- name = "Quartermaster's Fax Machine";
- fax_name = "Quartermaster's Office"
- },
+/obj/machinery/fax/heads/qm,
/turf/open/floor/iron,
/area/station/command/heads_quarters/qm)
"wuE" = (
@@ -68259,10 +68244,7 @@
/obj/structure/window/reinforced/spawner/directional/south,
/obj/structure/table/wood,
/obj/item/radio/intercom/directional/east,
-/obj/machinery/fax{
- name = "Captain's Fax Machine";
- fax_name = "Captain's Office"
- },
+/obj/machinery/fax/heads/captain,
/turf/open/floor/wood,
/area/station/command/heads_quarters/captain)
"wKm" = (
@@ -70871,11 +70853,8 @@
"xNl" = (
/obj/structure/window/reinforced/spawner/directional/east,
/obj/structure/table/wood,
-/obj/machinery/fax{
- name = "Head of Personnel's Fax Machine";
- fax_name = "Head of Personnel's Office"
- },
/obj/machinery/light/warm/directional/north,
+/obj/machinery/fax/heads/hop,
/turf/open/floor/carpet,
/area/station/command/heads_quarters/hop)
"xNm" = (
diff --git a/_maps/map_files/wawastation/wawastation.dmm b/_maps/map_files/wawastation/wawastation.dmm
index a723bb3f2a8..bcc10a68c16 100644
--- a/_maps/map_files/wawastation/wawastation.dmm
+++ b/_maps/map_files/wawastation/wawastation.dmm
@@ -29571,14 +29571,11 @@
/turf/open/floor/plating,
/area/station/maintenance/department/cargo)
"kki" = (
-/obj/machinery/fax{
- fax_name = "Quartermaster's Office";
- name = "Quartermaster's Fax Machine"
- },
/obj/effect/turf_decal/siding/wood{
dir = 6
},
/obj/structure/table/wood/fancy/orange,
+/obj/machinery/fax/heads/qm,
/turf/open/floor/wood,
/area/station/command/heads_quarters/qm)
"kkA" = (
@@ -30294,11 +30291,8 @@
/area/station/science/genetics)
"kvk" = (
/obj/structure/table,
-/obj/machinery/fax{
- fax_name = "Chief Medical Officer's Office";
- name = "Chief Medical Officer's Fax Machine"
- },
/obj/machinery/light_switch/directional/north,
+/obj/machinery/fax/heads/cmo,
/turf/open/floor/iron/dark/textured,
/area/station/command/heads_quarters/cmo)
"kvo" = (
@@ -44652,16 +44646,13 @@
name = "shutter control";
pixel_x = -8
},
-/obj/machinery/fax{
- fax_name = "Captain's Office";
- name = "Captain's Fax Machine"
- },
/obj/structure/table/reinforced,
/obj/machinery/keycard_auth/wall_mounted/directional/south{
pixel_x = 8;
pixel_y = -24
},
/obj/machinery/status_display/ai/directional/east,
+/obj/machinery/fax/heads/captain,
/turf/open/floor/carpet/royalblue,
/area/station/command/heads_quarters/captain/private)
"pvy" = (
@@ -54205,10 +54196,6 @@
/obj/effect/turf_decal/tile/neutral/opposingcorners{
dir = 1
},
-/obj/machinery/fax{
- fax_name = "Research Director's Office";
- name = "Research Director's Fax Machine"
- },
/obj/structure/table,
/obj/machinery/camera/autoname/directional/south{
network = list("ss13","rd")
@@ -54217,6 +54204,7 @@
/obj/machinery/light_switch/directional/south{
pixel_x = 8
},
+/obj/machinery/fax/heads/rd,
/turf/open/floor/iron/dark,
/area/station/command/heads_quarters/rd)
"sAO" = (
@@ -62013,10 +62001,7 @@
"vlD" = (
/obj/structure/table/wood,
/obj/machinery/light_switch/directional/north,
-/obj/machinery/fax{
- fax_name = "Head of Personnel's Office";
- name = "Head of Personnel's Fax Machine"
- },
+/obj/machinery/fax/heads/hop,
/turf/open/floor/carpet/green,
/area/station/command/heads_quarters/hop)
"vlJ" = (
@@ -62090,16 +62075,13 @@
/turf/open/floor/iron,
/area/station/hallway/secondary/exit/departure_lounge)
"vno" = (
-/obj/machinery/fax{
- fax_name = "Chief Engineer's Office";
- name = "Chief Engineer's Fax Machine"
- },
/obj/structure/table/reinforced,
/obj/machinery/light/directional/east,
/obj/effect/turf_decal/trimline/yellow/filled/line{
dir = 5
},
/obj/structure/cable,
+/obj/machinery/fax/heads/ce,
/turf/open/floor/iron,
/area/station/command/heads_quarters/ce)
"vnr" = (
@@ -65330,16 +65312,13 @@
/turf/open/floor/plating,
/area/station/maintenance/central/greater)
"wum" = (
-/obj/machinery/fax{
- fax_name = "Head of Security's Office";
- name = "Head of Security's Fax Machine"
- },
/obj/structure/table/wood/fancy/red,
/obj/structure/secure_safe/hos{
pixel_x = 36;
pixel_y = 28
},
/obj/machinery/airalarm/directional/north,
+/obj/machinery/fax/heads/hos,
/turf/open/floor/iron/dark,
/area/station/command/heads_quarters/hos)
"wun" = (
diff --git a/code/__DEFINES/dcs/signals/signals_fax.dm b/code/__DEFINES/dcs/signals/signals_fax.dm
new file mode 100644
index 00000000000..3cb78d60775
--- /dev/null
+++ b/code/__DEFINES/dcs/signals/signals_fax.dm
@@ -0,0 +1 @@
+#define COMSIG_FAX_MESSAGE_RECEIVED "fax_message_received"
diff --git a/code/modules/modular_computers/computers/item/role_tablet_presets.dm b/code/modules/modular_computers/computers/item/role_tablet_presets.dm
index 2f655ac1d0c..47e10bf5372 100644
--- a/code/modules/modular_computers/computers/item/role_tablet_presets.dm
+++ b/code/modules/modular_computers/computers/item/role_tablet_presets.dm
@@ -7,11 +7,15 @@
greyscale_config = /datum/greyscale_config/tablet/head
greyscale_colors = "#67A364#a92323"
max_capacity = parent_type::max_capacity * 2
+ /// Fax type for a relevant head's tp connect their PDA to (for use with fax notification app)
+ var/fax_type = null
+
var/static/list/datum/computer_file/head_programs = list(
/datum/computer_file/program/status,
/datum/computer_file/program/science,
/datum/computer_file/program/robocontrol,
/datum/computer_file/program/budgetorders,
+ /datum/computer_file/program/faxbond,
)
/obj/item/modular_computer/pda/heads/Initialize(mapload)
@@ -20,12 +24,19 @@
var/datum/computer_file/program/program_type = new programs
store_file(program_type)
+ if (ispath(fax_type, /obj/machinery/fax))
+ var/datum/computer_file/program/faxbond/fax_notifier = locate() in stored_files
+ var/list/faxes_list = SSmachines.get_machines_by_type(fax_type)
+ var/obj/machinery/fax/heads_fax = length(faxes_list) ? pick(faxes_list) : null //there really shouldnt be more than one
+ fax_notifier.connect_fax(heads_fax)
+
/obj/item/modular_computer/pda/heads/captain
name = "captain PDA"
icon_state = "/obj/item/modular_computer/pda/heads/captain"
greyscale_config = /datum/greyscale_config/tablet/captain
greyscale_colors = "#2C7CB2#FF0000#FFFFFF#FFD55B"
inserted_item = /obj/item/pen/fountain/captain
+ fax_type = /obj/machinery/fax/heads/captain
/obj/item/modular_computer/pda/heads/captain/Initialize(mapload)
. = ..()
@@ -42,6 +53,7 @@
icon_state = "/obj/item/modular_computer/pda/heads/hop"
greyscale_config = /datum/greyscale_config/tablet/stripe_thick/head
greyscale_colors = "#374f7e#a52f29#a52f29"
+ fax_type = /obj/machinery/fax/heads/hop
starting_programs = list(
/datum/computer_file/program/records/security,
/datum/computer_file/program/job_management,
@@ -53,6 +65,7 @@
greyscale_config = /datum/greyscale_config/tablet/head
greyscale_colors = "#EA3232#0000CC"
inserted_item = /obj/item/pen/red/security
+ fax_type = /obj/machinery/fax/heads/hos
starting_programs = list(
/datum/computer_file/program/records/security,
)
@@ -62,6 +75,7 @@
icon_state = "/obj/item/modular_computer/pda/heads/ce"
greyscale_config = /datum/greyscale_config/tablet/stripe_thick/head
greyscale_colors = "#D99A2E#69DBF3#FAFAFA"
+ fax_type = /obj/machinery/fax/heads/ce
starting_programs = list(
/datum/computer_file/program/atmosscan,
/datum/computer_file/program/alarm_monitor,
@@ -73,6 +87,7 @@
icon_state = "/obj/item/modular_computer/pda/heads/cmo"
greyscale_config = /datum/greyscale_config/tablet/stripe_thick/head
greyscale_colors = "#FAFAFA#000099#3F96CC"
+ fax_type = /obj/machinery/fax/heads/cmo
starting_programs = list(
/datum/computer_file/program/maintenance/phys_scanner,
/datum/computer_file/program/records/medical,
@@ -84,6 +99,7 @@
greyscale_config = /datum/greyscale_config/tablet/stripe_thick/head
greyscale_colors = "#FAFAFA#000099#B347BC"
inserted_item = /obj/item/pen/fountain
+ fax_type = /obj/machinery/fax/heads/rd
starting_programs = list(
/datum/computer_file/program/borg_monitor,
/datum/computer_file/program/scipaper_program,
@@ -97,6 +113,7 @@
greyscale_colors = "#c4b787#18191e#8b4c31"
inserted_item = /obj/item/pen/survival
stored_paper = 20
+ fax_type = /obj/machinery/fax/heads/qm
starting_programs = list(
/datum/computer_file/program/shipping,
/datum/computer_file/program/restock_tracker,
diff --git a/code/modules/modular_computers/file_system/programs/faxnotif.dm b/code/modules/modular_computers/file_system/programs/faxnotif.dm
new file mode 100644
index 00000000000..5cadc4b4d1f
--- /dev/null
+++ b/code/modules/modular_computers/file_system/programs/faxnotif.dm
@@ -0,0 +1,119 @@
+/datum/computer_file/program/faxbond
+ filename = "faxbond"
+ filedesc = "FaxBond"
+ can_run_on_flags = PROGRAM_PDA
+ downloader_category = PROGRAM_CATEGORY_DEVICE
+ program_open_overlay = "generic"
+ extended_desc = "A lightweight piece of software designed to decrease fax response time. \
+ Will send a notification as soon as one of connected faxes receives a message. \
+ Recommended by 9 out of 10 CentCom officers."
+ size = 1
+ tgui_id = "NtosFaxBond"
+ program_icon = "fa-fax"
+ /// All relevant info of every connected fax, including weak ref for cleaning after ourself + name, area name and muted bool
+ var/list/connected_faxes = list()
+
+/**
+ * Proc for subscribing to faxes. Registers needed signal and updates fax related vars for program. Includes type checking.
+ * Arguments:
+ * * target - [/datum/computer_file/program/proc/tap] proc target, can be anything
+ */
+/datum/computer_file/program/faxbond/proc/connect_fax(obj/machinery/fax/target)
+ if(!istype(target))
+ return FALSE
+
+ var/our_id = target.fax_id
+
+ if(!connected_faxes[our_id])
+ RegisterSignal(target, COMSIG_FAX_MESSAGE_RECEIVED, PROC_REF(on_fax_message_received))
+
+ var/list/fax_info = list()
+ var/area/our_area = get_area(target)
+ fax_info["ref"] = WEAKREF(target)
+ fax_info["name"] = target.fax_name
+ fax_info["area_name"] = our_area.name
+ fax_info["muted"] = FALSE
+ connected_faxes[our_id] += fax_info
+
+ return TRUE
+
+/**
+ * Disconnects a fax given its ID (if it was connected before), removing it from a list and unregistering relevant signal
+ * Arguments:
+ * * fax_id - fax id to disconnect from our PDA
+ */
+/datum/computer_file/program/faxbond/proc/disconnect_fax(fax_id)
+ if(!connected_faxes[fax_id])
+ return
+
+ var/list/fax_info = connected_faxes[fax_id]
+ var/datum/weakref/fax_ref = fax_info["ref"]
+ var/obj/machinery/fax/our_fax = fax_ref.resolve()
+ if (our_fax)
+ UnregisterSignal(our_fax, COMSIG_FAX_MESSAGE_RECEIVED)
+
+ connected_faxes -= fax_id
+
+
+/**
+ * Signal handler for [COMSIG_FAX_MESSAGE_RECEIVED].
+ * Arguments:
+ * * receiver - [/obj/machinery/fax] that received a message
+ * * message_source - name of a sender
+ */
+/datum/computer_file/program/faxbond/proc/on_fax_message_received(obj/machinery/fax/receiver, message_source)
+ SIGNAL_HANDLER
+
+ var/id = receiver.fax_id
+ var/list/fax_info = connected_faxes[id]
+
+ if (fax_info["muted"])
+ return
+
+ var/datum/computer_file/program/messenger/messenger = locate() in computer.stored_files
+ var/datum/signal/subspace/messaging/tablet_message/signal = new(receiver, list(
+ "fakename" = "Fax Notificator",
+ "fakejob" = "PDA Program",
+ "message" = "Your fax [receiver.fax_name] has received a new message from [message_source]",
+ "targets" = list(messenger),
+ "automated" = TRUE
+ ))
+ INVOKE_ASYNC(signal, TYPE_PROC_REF(/datum/signal/subspace, send_to_receivers))
+
+/datum/computer_file/program/faxbond/Destroy()
+ . = ..()
+ for(var/fax in connected_faxes)
+ disconnect_fax(fax)
+
+/datum/computer_file/program/faxbond/tap(atom/tapped_atom, mob/living/user, list/modifiers)
+ return connect_fax(tapped_atom)
+
+/datum/computer_file/program/faxbond/ui_data(mob/user)
+ var/list/data = list()
+
+ data["faxes_info"] = list()
+ for(var/fax_id in connected_faxes)
+ var/list/fax_info = connected_faxes[fax_id]
+ var/list/fax_data = list(
+ "id" = fax_id,
+ "name" = fax_info["name"],
+ "location" = fax_info["area_name"],
+ "muted" = fax_info["muted"],
+ )
+ data["faxes_info"] += list(fax_data)
+ return data
+
+/datum/computer_file/program/faxbond/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
+ . = ..()
+ if(.)
+ return
+ switch(action)
+ if("unsubscribe")
+ disconnect_fax(params["id"])
+ return TRUE
+ if("mute")
+ var/list/fax_info = connected_faxes[params["id"]]
+ if (!fax_info)
+ return FALSE
+ fax_info["muted"] = !fax_info["muted"]
+ return TRUE
diff --git a/code/modules/paperwork/fax.dm b/code/modules/paperwork/fax.dm
index 1761a7fe69f..5336edcdcc2 100644
--- a/code/modules/paperwork/fax.dm
+++ b/code/modules/paperwork/fax.dm
@@ -70,6 +70,41 @@ GLOBAL_VAR_INIT(fax_autoprinting, FALSE)
fax_name = "[current_area.name]"
return ..()
+/obj/machinery/fax/heads
+ abstract_type = /obj/machinery/fax/heads
+
+/obj/machinery/fax/heads/Initialize(mapload)
+ . = ..()
+ REGISTER_REQUIRED_MAP_ITEM(1, 1)
+
+/obj/machinery/fax/heads/captain
+ name = "Captain's Fax Machine"
+ fax_name = "Captain's Office"
+
+/obj/machinery/fax/heads/hop
+ name = "Head of Personnel's Fax Machine"
+ fax_name = "Head of Personnel's Office"
+
+/obj/machinery/fax/heads/hos
+ name = "Head of Security's Fax Machine"
+ fax_name = "Head of Security's Office"
+
+/obj/machinery/fax/heads/cmo
+ name = "Chief Medical Officer's Fax Machine"
+ fax_name = "Chief Medical Officer's Office"
+
+/obj/machinery/fax/heads/rd
+ name = "Research Director's Fax Machine"
+ fax_name = "Research Director's Office"
+
+/obj/machinery/fax/heads/ce
+ name = "Chief Engineer's Fax Machine"
+ fax_name = "Chief Engineer's Office"
+
+/obj/machinery/fax/heads/qm
+ name = "Quartermaster's Fax Machine"
+ fax_name = "Quartermaster's Office"
+
/obj/machinery/fax/admin/syndicate
name = "Syndicate Fax Machine"
@@ -401,6 +436,7 @@ GLOBAL_VAR_INIT(fax_autoprinting, FALSE)
say("Received correspondence from [sender_name].")
history_add("Receive", sender_name)
addtimer(CALLBACK(src, PROC_REF(vend_item), loaded), 1.9 SECONDS)
+ SEND_SIGNAL(src, COMSIG_FAX_MESSAGE_RECEIVED, sender_name)
/**
* Procedure for animating an object entering or leaving the fax machine.
diff --git a/code/modules/unit_tests/required_map_items.dm b/code/modules/unit_tests/required_map_items.dm
index 4d65d7651e1..33ec9469ed0 100644
--- a/code/modules/unit_tests/required_map_items.dm
+++ b/code/modules/unit_tests/required_map_items.dm
@@ -16,6 +16,7 @@
/datum/unit_test/maptest_required_map_items/proc/setup_expected_types()
expected_types += subtypesof(/obj/item/stamp/head)
expected_types += subtypesof(/obj/machinery/modular_computer/preset/cargochat)
+ expected_types += subtypesof(/obj/machinery/fax/heads)
expected_types += /mob/living/basic/parrot/poly
expected_types += /mob/living/basic/pet/dog/corgi/ian
diff --git a/tgstation.dme b/tgstation.dme
index eeb8daccf82..dbf5c85039a 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -338,6 +338,7 @@
#include "code\__DEFINES\dcs\signals\signals_cytology.dm"
#include "code\__DEFINES\dcs\signals\signals_datum.dm"
#include "code\__DEFINES\dcs\signals\signals_event.dm"
+#include "code\__DEFINES\dcs\signals\signals_fax.dm"
#include "code\__DEFINES\dcs\signals\signals_fish.dm"
#include "code\__DEFINES\dcs\signals\signals_food.dm"
#include "code\__DEFINES\dcs\signals\signals_gib.dm"
@@ -5858,6 +5859,7 @@
#include "code\modules\modular_computers\file_system\programs\crewmanifest.dm"
#include "code\modules\modular_computers\file_system\programs\dept_order.dm"
#include "code\modules\modular_computers\file_system\programs\emojipedia.dm"
+#include "code\modules\modular_computers\file_system\programs\faxnotif.dm"
#include "code\modules\modular_computers\file_system\programs\file_browser.dm"
#include "code\modules\modular_computers\file_system\programs\frontier.dm"
#include "code\modules\modular_computers\file_system\programs\jobmanagement.dm"
diff --git a/tgui/packages/tgui/interfaces/NtosFaxBond.tsx b/tgui/packages/tgui/interfaces/NtosFaxBond.tsx
new file mode 100644
index 00000000000..447400e656d
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/NtosFaxBond.tsx
@@ -0,0 +1,85 @@
+import { Button, NoticeBox, Section, Stack, Table } from 'tgui-core/components';
+import type { BooleanLike } from 'tgui-core/react';
+import { useBackend } from '../backend';
+import { NtosWindow } from '../layouts';
+
+type FaxInfoList = {
+ id: string;
+ name: string;
+ location: string;
+ muted: BooleanLike;
+};
+
+type Data = {
+ faxes_info: FaxInfoList[];
+};
+
+export const NtosFaxBond = (props) => {
+ return (
+
+
+
+
+
+ );
+};
+
+export const NtosFaxBondContent = (props) => {
+ const { act, data } = useBackend();
+ const { faxes_info = [] } = data;
+ return (
+ <>
+
+ Scan any fax to be notified when it receives a message.
+
+ {!!faxes_info.length && (
+
+
+
+ ID
+ Name
+ Location
+
+
+ {faxes_info.map((fax) => (
+
+
+ {fax.id}
+
+
+ {fax.name}
+
+
+ {fax.location}
+
+
+
+
+
+
+ ))}
+
+
+ )}
+ >
+ );
+};