From dc8adc2924fc74e1b8a590bc9c6924bbc759f689 Mon Sep 17 00:00:00 2001
From: magatsuchi <88991542+magatsuchi@users.noreply.github.com>
Date: Wed, 20 Apr 2022 10:55:49 -0500
Subject: [PATCH] Modular Tablets: Converting PDAs to the NtOS System (SKYRAT
VERSION) (#12920)
* hot-patch 1
* hot patch 2
* hot patch 3
* slight issue
---
.../IceRuins/icemoon_surface_engioutpost.dmm | 4 +-
.../commswilding_3.dmm | 2 +-
_maps/RandomRuins/SpaceRuins/bigderelict1.dmm | 2 +-
_maps/RandomRuins/SpaceRuins/derelict7.dmm | 2 +-
.../RandomRuins/SpaceRuins/forgottenship.dmm | 2 +-
_maps/RandomZLevels/SnowCabin.dmm | 18 +-
_maps/RandomZLevels/moonoutpost19.dmm | 7 +-
_maps/RandomZLevels/undergroundoutpost45.dmm | 7 +-
.../map_files/Blueshift/BlueShift_middle.dmm | 42 +-
_maps/map_files/Blueshift/BlueShift_upper.dmm | 26 +-
.../map_files/Deltastation/DeltaStation2.dmm | 64 +-
.../Deltastation/DeltaStation2_skyrat.dmm | 68 +-
.../skyrat_old/DeltaStation2_skyrat_old.dmm | 68 +-
.../map_files/IceBoxStation/IceBoxStation.dmm | 52 +-
.../IceBoxStation/IceBoxStation_skyrat.dmm | 52 +-
.../IcemoonUnderground_Above.dmm | 2 +-
.../IcemoonUnderground_Above_skyrat.dmm | 2 +-
.../skyrat_old/IceBoxStation_skyrat_old.dmm | 54 +-
.../IcemoonUnderground_Above_skyrat_old.dmm | 4 +-
_maps/map_files/KiloStation/KiloStation.dmm | 53 +-
.../KiloStation/KiloStation_skyrat.dmm | 53 +-
.../skyrat_old/KiloStation_skyrat_old.dmm | 53 +-
_maps/map_files/MetaStation/MetaStation.dmm | 70 +-
.../MetaStation/MetaStation_skyrat.dmm | 70 +-
.../skryat_old/MetaStation_skyrat_old.dmm | 70 +-
_maps/map_files/NSSJourney/NSSJourney.dmm | 38 +-
_maps/map_files/generic/CentCom.dmm | 12 +-
_maps/map_files/generic/CentCom_skyrat.dmm | 12 +-
_maps/map_files/generic/CentCom_skyrat_z2.dmm | 2 +-
.../skryat_old/tramstation_skyrat_old.dmm | 50 +-
_maps/map_files/tramstation/tramstation.dmm | 50 +-
.../tramstation/tramstation_skyrat.dmm | 52 +-
code/__DEFINES/access.dm | 60 +-
code/__DEFINES/dcs/signals/signals_object.dm | 6 +-
code/__DEFINES/devices.dm | 54 +-
code/__DEFINES/hud.dm | 28 +-
code/__DEFINES/machines.dm | 3 +
code/__HELPERS/cmp.dm | 8 +-
code/_globalvars/phobias.dm | 2 +-
code/_onclick/hud/ai.dm | 47 +-
code/_onclick/hud/pai.dm | 40 +-
code/_onclick/hud/robot.dm | 25 +-
code/controllers/subsystem/id_access.dm | 4 +-
code/controllers/subsystem/wardrobe.dm | 14 +-
code/datums/action.dm | 6 +-
code/datums/components/uplink.dm | 18 +-
.../config_types/greyscale_configs.dm | 20 +-
.../greyscale/json_configs/pda_clown.json | 19 +-
code/datums/mind.dm | 4 +-
code/game/machinery/PDApainter.dm | 28 +-
code/game/machinery/camera/camera.dm | 10 +-
.../game/machinery/computer/communications.dm | 1 -
code/game/machinery/computer/security.dm | 8 +-
code/game/machinery/navbeacon.dm | 2 +-
.../machinery/telecomms/computers/message.dm | 97 +-
.../telecomms/machines/message_server.dm | 51 +-
.../effects/spawners/random/contraband.dm | 2 +-
code/game/objects/items/cards_ids.dm | 4 +-
code/game/objects/items/devices/PDA/PDA.dm | 1311 -----------------
.../objects/items/devices/PDA/PDA_types.dm | 258 ----
code/game/objects/items/devices/PDA/cart.dm | 648 --------
code/game/objects/items/devices/PDA/radio.dm | 38 -
.../objects/items/devices/PDA/virus_cart.dm | 146 --
.../items/devices/scanners/health_analyzer.dm | 8 +-
code/game/objects/items/storage/backpack.dm | 2 +-
code/game/objects/items/storage/boxes.dm | 22 +-
.../game/objects/items/storage/uplink_kits.dm | 8 +-
.../closets/secure/engineering.dm | 2 +-
.../crates_lockers/closets/secure/medical.dm | 2 +-
.../closets/secure/scientist.dm | 2 +-
.../crates_lockers/closets/secure/security.dm | 6 +-
.../crates_lockers/closets/syndicate.dm | 2 +-
code/game/objects/structures/displaycase.dm | 2 +-
code/modules/admin/verbs/debug.dm | 10 +-
.../cargo/markets/market_items/misc.dm | 2 +-
code/modules/client/preferences/pda.dm | 41 -
code/modules/clothing/chameleon.dm | 29 +-
code/modules/clothing/outfits/ert.dm | 9 +-
code/modules/clothing/outfits/standard.dm | 9 +-
code/modules/clothing/suits/wintercoats.dm | 3 +-
code/modules/jobs/job_types/_job.dm | 15 +-
.../jobs/job_types/atmospheric_technician.dm | 5 +-
code/modules/jobs/job_types/bartender.dm | 2 +-
code/modules/jobs/job_types/botanist.dm | 2 +-
code/modules/jobs/job_types/captain.dm | 2 +-
.../jobs/job_types/cargo_technician.dm | 5 +-
code/modules/jobs/job_types/chaplain.dm | 2 +-
code/modules/jobs/job_types/chemist.dm | 2 +-
code/modules/jobs/job_types/chief_engineer.dm | 3 +-
.../jobs/job_types/chief_medical_officer.dm | 3 +-
code/modules/jobs/job_types/clown.dm | 4 +-
code/modules/jobs/job_types/cook.dm | 2 +-
code/modules/jobs/job_types/curator.dm | 3 +-
code/modules/jobs/job_types/detective.dm | 3 +-
code/modules/jobs/job_types/geneticist.dm | 2 +-
.../jobs/job_types/head_of_personnel.dm | 3 +-
.../jobs/job_types/head_of_security.dm | 3 +-
code/modules/jobs/job_types/janitor.dm | 5 +-
code/modules/jobs/job_types/lawyer.dm | 2 +-
code/modules/jobs/job_types/medical_doctor.dm | 2 +-
code/modules/jobs/job_types/mime.dm | 2 +-
code/modules/jobs/job_types/paramedic.dm | 2 +-
code/modules/jobs/job_types/psychologist.dm | 2 +-
code/modules/jobs/job_types/quartermaster.dm | 2 +-
.../jobs/job_types/research_director.dm | 2 +-
code/modules/jobs/job_types/roboticist.dm | 2 +-
code/modules/jobs/job_types/scientist.dm | 2 +-
.../jobs/job_types/security_officer.dm | 10 +-
code/modules/jobs/job_types/shaft_miner.dm | 2 +-
.../jobs/job_types/station_engineer.dm | 2 +-
code/modules/jobs/job_types/virologist.dm | 2 +-
code/modules/jobs/job_types/warden.dm | 2 +-
code/modules/mining/abandoned_crates.dm | 2 +-
code/modules/mob/living/carbon/human/human.dm | 8 +-
.../mob/living/carbon/human/human_helpers.dm | 15 +-
.../mob/living/carbon/human/species.dm | 2 +-
code/modules/mob/living/silicon/ai/ai.dm | 13 +-
code/modules/mob/living/silicon/pai/pai.dm | 15 +-
.../mob/living/silicon/pai/pai_shell.dm | 4 +-
.../mob/living/silicon/pai/software.dm | 12 -
.../modules/mob/living/silicon/robot/robot.dm | 47 +-
.../mob/living/silicon/robot/robot_defines.dm | 3 +-
code/modules/mob/living/silicon/silicon.dm | 55 +-
code/modules/mob/mob.dm | 9 +-
.../mob_spawn/corpses/mining_corpses.dm | 1 -
.../mob_spawn/corpses/nonhuman_corpses.dm | 1 -
.../mob_spawn/ghost_roles/unused_roles.dm | 2 +-
code/modules/mob_spawn/mob_spawn.dm | 4 +-
.../computers/item/computer.dm | 104 +-
.../computers/item/computer_ui.dm | 101 +-
.../computers/item/role_tablet_presets.dm | 227 +++
.../computers/item/tablet.dm | 152 +-
.../computers/item/tablet_presets.dm | 3 -
.../file_system/programs/newscasterapp.dm | 2 +-
.../file_system/programs/notepad.dm | 29 +
.../file_system/programs/ntmessenger.dm | 366 +++++
.../file_system/programs/phys_scanner.dm | 78 +
.../file_system/programs/records.dm | 74 +
.../file_system/programs/robocontrol.dm | 15 +-
.../file_system/programs/signaler.dm | 20 +-
.../file_system/programs/statusdisplay.dm | 55 +
.../modular_computers/hardware/card_slot.dm | 11 +
.../modular_computers/hardware/hard_drive.dm | 20 +-
.../modular_computers/hardware/identifier.dm | 13 +
.../modular_computers/hardware/job_disk.dm | 253 ++++
.../hardware/network_card.dm | 10 +-
.../modular_computers/hardware/virus_disk.dm | 140 ++
code/modules/tgui/states/reverse_contained.dm | 18 +
.../uplink/uplink_items/device_tools.dm | 10 +-
code/modules/uplink/uplink_items/explosive.dm | 8 +-
code/modules/vending/assist.dm | 2 +-
code/modules/vending/cartridge.dm | 15 +-
icons/obj/modular_tablet.dmi | Bin 20551 -> 22910 bytes
icons/obj/module.dmi | Bin 18023 -> 18794 bytes
.../code/_globalvars/maint_loot_uncommon.dm | 38 +-
modular_skyrat/modules/aesthetics/pda/pda.dm | 30 -
.../alternative_job_titles/code/job.dm | 5 +-
.../modules/blueshield/code/blueshield.dm | 2 +-
.../modules/brigoff/code/brigoff.dm | 2 +-
.../code/datums/contractor_support.dm | 2 +-
.../modules/cryosleep/code/cryopod.dm | 4 -
.../modules/clothing/under/accessories.dm | 5 +-
.../modules/cyborgpda/code/robot.dm | 23 -
modular_skyrat/modules/cyborgpda/readme.md | 30 -
.../exp_corps/code/expeditionary_trooper.dm | 4 +-
.../modules/goofsec/code/department_guards.dm | 10 +-
.../goofsec/code/sec_clothing_overrides.dm | 8 +-
.../code/syndicate_loadout.dm | 2 +-
.../code/nanotrasen_consultant.dm | 8 +-
modular_skyrat/modules/salon/code/barber.dm | 2 +-
.../code/peacekeeper/armadyne_clothing.dm | 4 +-
.../code/security_medic/security_medic.dm | 2 +-
tgstation.dme | 18 +-
tgui/packages/tgui/interfaces/NtosMain.js | 112 +-
.../packages/tgui/interfaces/NtosMessenger.js | 220 +++
tgui/packages/tgui/interfaces/NtosNotepad.js | 36 +
.../tgui/interfaces/NtosPhysScanner.js | 48 +
tgui/packages/tgui/interfaces/NtosRecords.js | 86 ++
.../tgui/interfaces/NtosRoboControl.js | 12 +-
tgui/packages/tgui/interfaces/NtosStatus.js | 45 +
tools/UpdatePaths/pdas_to_tabs.txt | 56 +
tools/UpdatePaths/toxins_to_plasma.txt | 2 +-
182 files changed, 2968 insertions(+), 4053 deletions(-)
delete mode 100644 code/game/objects/items/devices/PDA/PDA.dm
delete mode 100644 code/game/objects/items/devices/PDA/PDA_types.dm
delete mode 100644 code/game/objects/items/devices/PDA/cart.dm
delete mode 100644 code/game/objects/items/devices/PDA/radio.dm
delete mode 100644 code/game/objects/items/devices/PDA/virus_cart.dm
delete mode 100644 code/modules/client/preferences/pda.dm
create mode 100644 code/modules/modular_computers/computers/item/role_tablet_presets.dm
create mode 100644 code/modules/modular_computers/file_system/programs/notepad.dm
create mode 100644 code/modules/modular_computers/file_system/programs/ntmessenger.dm
create mode 100644 code/modules/modular_computers/file_system/programs/phys_scanner.dm
create mode 100644 code/modules/modular_computers/file_system/programs/records.dm
create mode 100644 code/modules/modular_computers/file_system/programs/statusdisplay.dm
create mode 100644 code/modules/modular_computers/hardware/identifier.dm
create mode 100644 code/modules/modular_computers/hardware/job_disk.dm
create mode 100644 code/modules/modular_computers/hardware/virus_disk.dm
create mode 100644 code/modules/tgui/states/reverse_contained.dm
delete mode 100644 modular_skyrat/modules/aesthetics/pda/pda.dm
delete mode 100644 modular_skyrat/modules/cyborgpda/code/robot.dm
delete mode 100644 modular_skyrat/modules/cyborgpda/readme.md
create mode 100644 tgui/packages/tgui/interfaces/NtosMessenger.js
create mode 100644 tgui/packages/tgui/interfaces/NtosNotepad.js
create mode 100644 tgui/packages/tgui/interfaces/NtosPhysScanner.js
create mode 100644 tgui/packages/tgui/interfaces/NtosRecords.js
create mode 100644 tgui/packages/tgui/interfaces/NtosStatus.js
create mode 100644 tools/UpdatePaths/pdas_to_tabs.txt
diff --git a/_maps/RandomRuins/IceRuins/icemoon_surface_engioutpost.dmm b/_maps/RandomRuins/IceRuins/icemoon_surface_engioutpost.dmm
index 056bd39bf62..e7a18109475 100644
--- a/_maps/RandomRuins/IceRuins/icemoon_surface_engioutpost.dmm
+++ b/_maps/RandomRuins/IceRuins/icemoon_surface_engioutpost.dmm
@@ -532,13 +532,13 @@
/turf/open/floor/plating,
/area/ruin/planetengi)
"cI" = (
-/obj/item/pda/clear{
+/obj/item/modular_computer/tablet/pda/clear{
note = "Chief's asked me to check on the machinery inside PDA. He's also worried about Build, but i'm sure Harry'll handle the construction. I just need to work on Internals. Fuck i'm hungry"
},
/turf/open/floor/iron,
/area/ruin/planetengi)
"cJ" = (
-/obj/item/pda/engineering{
+/obj/item/modular_computer/tablet/pda/engineering{
note = "To-do: Check on SM status. Get a pint at eat. Nag the research manager for RCDs."
},
/turf/open/floor/iron,
diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1/commswilding_3.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1/commswilding_3.dmm
index 5394b2d4f93..984bfe87aa1 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1/commswilding_3.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1/commswilding_3.dmm
@@ -120,7 +120,7 @@
dir = 8;
pixel_x = -24
},
-/obj/item/pda/chameleon/broken{
+/obj/item/modular_computer/tablet/pda/chameleon/broken{
pixel_x = 5;
pixel_y = 4
},
diff --git a/_maps/RandomRuins/SpaceRuins/bigderelict1.dmm b/_maps/RandomRuins/SpaceRuins/bigderelict1.dmm
index c895f7ba7a0..acfbced15ce 100644
--- a/_maps/RandomRuins/SpaceRuins/bigderelict1.dmm
+++ b/_maps/RandomRuins/SpaceRuins/bigderelict1.dmm
@@ -1136,7 +1136,7 @@
/area/ruin/space/has_grav/derelictoutpost/cargostorage)
"eC" = (
/obj/structure/closet/crate,
-/obj/item/pda/clear,
+/obj/item/modular_computer/tablet/pda/clear,
/obj/effect/turf_decal/delivery,
/turf/open/floor/iron,
/area/ruin/space/has_grav/derelictoutpost/cargostorage)
diff --git a/_maps/RandomRuins/SpaceRuins/derelict7.dmm b/_maps/RandomRuins/SpaceRuins/derelict7.dmm
index 15efea7ef6d..d10b6e4a2bb 100644
--- a/_maps/RandomRuins/SpaceRuins/derelict7.dmm
+++ b/_maps/RandomRuins/SpaceRuins/derelict7.dmm
@@ -323,7 +323,7 @@
/obj/effect/turf_decal/trimline/neutral/warning{
dir = 1
},
-/obj/item/cartridge/signal,
+/obj/item/computer_hardware/hard_drive/role/signal,
/turf/open/floor/iron/dark/side/airless{
dir = 1
},
diff --git a/_maps/RandomRuins/SpaceRuins/forgottenship.dmm b/_maps/RandomRuins/SpaceRuins/forgottenship.dmm
index abe021aa747..4b6e77ad1b9 100644
--- a/_maps/RandomRuins/SpaceRuins/forgottenship.dmm
+++ b/_maps/RandomRuins/SpaceRuins/forgottenship.dmm
@@ -435,7 +435,7 @@
},
/obj/item/toy/nuke,
/obj/item/clothing/under/chameleon,
-/obj/item/pda/chameleon,
+/obj/item/modular_computer/tablet/pda/chameleon,
/obj/item/clothing/mask/chameleon,
/obj/item/card/id/advanced/chameleon,
/turf/open/floor/mineral/plastitanium,
diff --git a/_maps/RandomZLevels/SnowCabin.dmm b/_maps/RandomZLevels/SnowCabin.dmm
index 5132bd764d3..3c060629625 100644
--- a/_maps/RandomZLevels/SnowCabin.dmm
+++ b/_maps/RandomZLevels/SnowCabin.dmm
@@ -959,12 +959,11 @@
/area/awaymission/cabin/snowforest/sovietsurface)
"dm" = (
/obj/structure/table/reinforced,
-/obj/item/pda/syndicate{
- background_color = "#0039A6";
- default_cartridge = /obj/item/cartridge/virus/mime;
+/obj/item/modular_computer/tablet/pda/syndicate{
+ default_disk = /obj/item/computer_hardware/hard_drive/role/virus/mime;
desc = "A portable microcomputer by Thinktronic Systems, LTD. Seems like it may have useful information on it.";
- name = "soviet PDA";
- note = "TRANSLATED TO GALACTIC COMMON: My partner has left to help those Nanotrasen fucks three days ago. They said that a distress signal came from down south and they had to check it out. How fucking long does it take to investigate a mining outpost? Either those Nanotrasen fuckers betrayed us or something really did go wrong. Either way, I'm leaving before this becomes an issue for me and anyone else here. That dumb idiot."
+ name = "soviet tablet";
+ note = "TRANSLATED TO GALACTIC COMMON: My partner has left to help those Nanotrasen fucks three days ago. They said that a distress signal came from down south and they had to check it out. How fucking long does it take to investigate a mining outpost? Either those Nanotrasen fuckers betrayed us or something really did go wrong. Either way, I'm leaving before this becomes an issue for me and anyone else here. That dumb idiot."
},
/turf/open/floor/plating/snowed/snow_cabin,
/area/awaymission/cabin/snowforest/sovietsurface)
@@ -3563,12 +3562,11 @@
/area/awaymission/cabin/caves)
"nb" = (
/obj/effect/turf_decal/weather/snow,
-/obj/item/pda/syndicate{
- background_color = "#0039A6";
- default_cartridge = /obj/item/cartridge/virus/clown;
+/obj/item/modular_computer/tablet/pda/syndicate{
+ default_disk = /obj/item/computer_hardware/hard_drive/role/virus/clown;
desc = "A portable microcomputer by Thinktronic Systems, LTD. Seems like it may have useful information on it.";
- name = "soviet PDA";
- note = "TRANSLATED TO GALACTIC COMMON: DO NOT GO SOUTH."
+ name = "soviet tablet";
+ note = "TRANSLATED TO GALACTIC COMMON: DO NOT GO SOUTH."
},
/obj/effect/decal/remains/human{
color = "#72e4fa"
diff --git a/_maps/RandomZLevels/moonoutpost19.dmm b/_maps/RandomZLevels/moonoutpost19.dmm
index 3d405d7d6ae..973d12d5af1 100644
--- a/_maps/RandomZLevels/moonoutpost19.dmm
+++ b/_maps/RandomZLevels/moonoutpost19.dmm
@@ -2893,11 +2893,8 @@
/area/awaymission/moonoutpost19/research)
"hr" = (
/obj/structure/table,
-/obj/item/cartridge/signal/ordnance,
-/obj/item/cartridge/signal/ordnance{
- pixel_x = -4;
- pixel_y = 2
- },
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/obj/machinery/firealarm/directional/north,
/turf/open/floor/iron/cafeteria{
dir = 5
diff --git a/_maps/RandomZLevels/undergroundoutpost45.dmm b/_maps/RandomZLevels/undergroundoutpost45.dmm
index ebf98cfda57..17e3739055d 100644
--- a/_maps/RandomZLevels/undergroundoutpost45.dmm
+++ b/_maps/RandomZLevels/undergroundoutpost45.dmm
@@ -6061,11 +6061,8 @@
/area/awaymission/undergroundoutpost45/research)
"nk" = (
/obj/structure/table,
-/obj/item/cartridge/signal/ordnance,
-/obj/item/cartridge/signal/ordnance{
- pixel_x = -4;
- pixel_y = 2
- },
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/iron/cafeteria{
dir = 5;
diff --git a/_maps/map_files/Blueshift/BlueShift_middle.dmm b/_maps/map_files/Blueshift/BlueShift_middle.dmm
index 2986d4879eb..d452eae3a6d 100644
--- a/_maps/map_files/Blueshift/BlueShift_middle.dmm
+++ b/_maps/map_files/Blueshift/BlueShift_middle.dmm
@@ -9542,18 +9542,12 @@
/area/maintenance/port/aft)
"cIv" = (
/obj/structure/table/reinforced,
-/obj/item/cartridge/engineering{
- pixel_y = 6
- },
-/obj/item/cartridge/engineering{
- pixel_y = 6
- },
-/obj/item/cartridge/engineering{
- pixel_y = 6
- },
-/obj/item/cartridge/atmos,
-/obj/item/cartridge/atmos,
-/obj/item/cartridge/atmos,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/atmos,
+/obj/item/computer_hardware/hard_drive/role/atmos,
+/obj/item/computer_hardware/hard_drive/role/atmos,
/obj/item/reagent_containers/pill/patch/aiuri,
/obj/effect/turf_decal/tile/neutral{
dir = 4
@@ -47383,17 +47377,9 @@
/obj/item/folder/red{
pixel_x = -7
},
-/obj/item/cartridge/detective{
- pixel_x = 7;
- pixel_y = 8
- },
-/obj/item/cartridge/detective{
- pixel_x = 7;
- pixel_y = 4
- },
-/obj/item/cartridge/detective{
- pixel_x = 7
- },
+/obj/item/computer_hardware/hard_drive/role/detective,
+/obj/item/computer_hardware/hard_drive/role/detective,
+/obj/item/computer_hardware/hard_drive/role/detective,
/obj/structure/noticeboard/hos{
dir = 4;
pixel_x = -28
@@ -50210,9 +50196,9 @@
dir = 10
},
/obj/structure/table/wood,
-/obj/item/cartridge/quartermaster,
-/obj/item/cartridge/quartermaster,
-/obj/item/cartridge/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/obj/item/coin/gold,
/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass{
pixel_x = -4;
@@ -55088,8 +55074,8 @@
"tiE" = (
/obj/structure/table/wood,
/obj/item/modular_computer/laptop/preset/civilian,
-/obj/item/cartridge/lawyer,
-/obj/item/cartridge/lawyer,
+/obj/item/computer_hardware/hard_drive/role/lawyer,
+/obj/item/computer_hardware/hard_drive/role/lawyer,
/turf/open/floor/carpet/blue,
/area/service/lawoffice)
"tiG" = (
diff --git a/_maps/map_files/Blueshift/BlueShift_upper.dmm b/_maps/map_files/Blueshift/BlueShift_upper.dmm
index d76c5706041..59f3104f276 100644
--- a/_maps/map_files/Blueshift/BlueShift_upper.dmm
+++ b/_maps/map_files/Blueshift/BlueShift_upper.dmm
@@ -4700,15 +4700,9 @@
/area/medical/chemistry)
"beB" = (
/obj/structure/table/glass,
-/obj/item/cartridge/medical{
- pixel_x = 3
- },
-/obj/item/cartridge/medical{
- pixel_x = -3
- },
-/obj/item/cartridge/chemistry{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/chemistry,
/obj/machinery/light_switch/directional/north,
/obj/machinery/light/directional/north,
/turf/open/floor/iron/white,
@@ -14498,7 +14492,7 @@
/area/science/research)
"etw" = (
/obj/structure/table,
-/obj/item/pda/clown,
+/obj/item/modular_computer/tablet/pda/clown,
/turf/open/floor/noslip,
/area/maintenance/fore/upper)
"etD" = (
@@ -27874,15 +27868,9 @@
/area/maintenance/fore/upper)
"jqu" = (
/obj/structure/table/glass,
-/obj/item/cartridge/signal/ordnance{
- pixel_x = -6
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_x = 6
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/obj/effect/turf_decal/siding/purple{
dir = 4
},
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index df545cffd66..7f12fe3e4b7 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -35374,15 +35374,9 @@
"hYe" = (
/obj/structure/table/glass,
/obj/item/folder/blue,
-/obj/item/cartridge/medical{
- pixel_x = -3
- },
-/obj/item/cartridge/medical{
- pixel_x = 3
- },
-/obj/item/cartridge/chemistry{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/chemistry,
/obj/effect/turf_decal/tile/blue{
dir = 4
},
@@ -56819,15 +56813,9 @@
/area/service/hydroponics)
"opa" = (
/obj/structure/table/reinforced,
-/obj/item/cartridge/quartermaster{
- pixel_x = -6
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = 6
- },
-/obj/item/cartridge/quartermaster{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/obj/item/gps/mining,
/obj/effect/turf_decal/tile/neutral/fourcorners,
/turf/open/floor/iron,
@@ -67897,31 +67885,15 @@
/turf/open/floor/iron,
/area/medical/medbay/central)
"rFD" = (
-/obj/item/cartridge/atmos{
- pixel_x = -2;
- pixel_y = 8
- },
-/obj/item/cartridge/atmos{
- pixel_x = -2;
- pixel_y = 4
- },
-/obj/item/cartridge/atmos{
- pixel_x = -2
- },
+/obj/item/computer_hardware/hard_drive/role/atmos,
+/obj/item/computer_hardware/hard_drive/role/atmos,
+/obj/item/computer_hardware/hard_drive/role/atmos,
/obj/effect/turf_decal/tile/neutral/fourcorners,
/obj/machinery/airalarm/directional/south,
/obj/effect/turf_decal/bot,
-/obj/item/cartridge/engineering{
- pixel_x = 6;
- pixel_y = 8
- },
-/obj/item/cartridge/engineering{
- pixel_x = 6;
- pixel_y = 4
- },
-/obj/item/cartridge/engineering{
- pixel_x = 6
- },
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
/obj/structure/rack,
/turf/open/floor/iron/dark,
/area/command/heads_quarters/ce)
@@ -71941,15 +71913,9 @@
/area/command/heads_quarters/hop)
"sNs" = (
/obj/structure/table,
-/obj/item/cartridge/signal/ordnance{
- pixel_x = 6
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_x = -6
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/obj/machinery/camera/directional/east{
c_tag = "Science - Research Director's Office";
name = "science camera";
diff --git a/_maps/map_files/Deltastation/DeltaStation2_skyrat.dmm b/_maps/map_files/Deltastation/DeltaStation2_skyrat.dmm
index e2cda8cacc2..a044426f5a1 100644
--- a/_maps/map_files/Deltastation/DeltaStation2_skyrat.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2_skyrat.dmm
@@ -4812,15 +4812,9 @@
/area/hallway/secondary/entry)
"aYa" = (
/obj/structure/table/reinforced,
-/obj/item/cartridge/quartermaster{
- pixel_x = -6
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = 6
- },
-/obj/item/cartridge/quartermaster{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/obj/item/gps/mining,
/obj/effect/turf_decal/tile/neutral/fourcorners,
/turf/open/floor/iron,
@@ -33715,7 +33709,7 @@
/obj/item/grenade/smokebomb,
/obj/item/screwdriver,
/obj/item/toy/crayon/spraycan,
-/obj/item/pda,
+/obj/item/modular_computer/tablet/pda,
/obj/item/radio,
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plating,
@@ -38166,15 +38160,9 @@
"hYe" = (
/obj/structure/table/glass,
/obj/item/folder/blue,
-/obj/item/cartridge/medical{
- pixel_x = -3
- },
-/obj/item/cartridge/medical{
- pixel_x = 3
- },
-/obj/item/cartridge/chemistry{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/chemistry,
/obj/effect/turf_decal/tile/blue{
dir = 4
},
@@ -70792,7 +70780,7 @@
/obj/structure/closet/crate,
/obj/item/reagent_containers/hypospray/medipen/atropine,
/obj/item/grenade/smokebomb,
-/obj/item/pda,
+/obj/item/modular_computer/tablet/pda,
/turf/open/floor/iron/dark,
/area/security/prison)
"rEc" = (
@@ -74924,31 +74912,15 @@
/turf/open/floor/carpet/green,
/area/command/heads_quarters/captain/private/nt_rep)
"sMb" = (
-/obj/item/cartridge/atmos{
- pixel_x = -2;
- pixel_y = 8
- },
-/obj/item/cartridge/atmos{
- pixel_x = -2;
- pixel_y = 4
- },
-/obj/item/cartridge/atmos{
- pixel_x = -2
- },
+/obj/item/computer_hardware/hard_drive/role/atmos,
+/obj/item/computer_hardware/hard_drive/role/atmos,
+/obj/item/computer_hardware/hard_drive/role/atmos,
/obj/effect/turf_decal/tile/neutral/fourcorners,
/obj/machinery/airalarm/directional/south,
/obj/effect/turf_decal/bot,
-/obj/item/cartridge/engineering{
- pixel_x = 6;
- pixel_y = 8
- },
-/obj/item/cartridge/engineering{
- pixel_x = 6;
- pixel_y = 4
- },
-/obj/item/cartridge/engineering{
- pixel_x = 6
- },
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
/obj/structure/rack,
/turf/open/floor/iron/dark,
/area/command/heads_quarters/ce)
@@ -74977,15 +74949,9 @@
/area/ai_monitored/command/storage/eva)
"sNs" = (
/obj/structure/table,
-/obj/item/cartridge/signal/ordnance{
- pixel_x = 6
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_x = -6
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/obj/machinery/camera/directional/east{
c_tag = "Science - Research Director's Office";
name = "science camera";
diff --git a/_maps/map_files/Deltastation/skyrat_old/DeltaStation2_skyrat_old.dmm b/_maps/map_files/Deltastation/skyrat_old/DeltaStation2_skyrat_old.dmm
index 3cc17a50e1b..8d95c714060 100644
--- a/_maps/map_files/Deltastation/skyrat_old/DeltaStation2_skyrat_old.dmm
+++ b/_maps/map_files/Deltastation/skyrat_old/DeltaStation2_skyrat_old.dmm
@@ -5167,7 +5167,7 @@
/obj/structure/closet/crate,
/obj/item/reagent_containers/hypospray/medipen/atropine,
/obj/item/grenade/smokebomb,
-/obj/item/pda,
+/obj/item/modular_computer/tablet/pda,
/turf/open/floor/iron/dark,
/area/security/prison)
"aVB" = (
@@ -5328,15 +5328,9 @@
/area/hallway/secondary/entry)
"aYa" = (
/obj/structure/table/reinforced,
-/obj/item/cartridge/quartermaster{
- pixel_x = -6
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = 6
- },
-/obj/item/cartridge/quartermaster{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/obj/item/gps/mining,
/obj/effect/turf_decal/tile/neutral/fourcorners,
/turf/open/floor/iron,
@@ -41073,15 +41067,9 @@
"hYe" = (
/obj/structure/table/glass,
/obj/item/folder/blue,
-/obj/item/cartridge/medical{
- pixel_x = -3
- },
-/obj/item/cartridge/medical{
- pixel_x = 3
- },
-/obj/item/cartridge/chemistry{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/chemistry,
/obj/effect/turf_decal/tile/blue{
dir = 4
},
@@ -70771,7 +70759,7 @@
/obj/item/grenade/smokebomb,
/obj/item/screwdriver,
/obj/item/toy/crayon/spraycan,
-/obj/item/pda,
+/obj/item/modular_computer/tablet/pda,
/obj/item/radio,
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plating,
@@ -79224,31 +79212,15 @@
/turf/open/floor/carpet/green,
/area/command/heads_quarters/captain/private/nt_rep)
"sMb" = (
-/obj/item/cartridge/atmos{
- pixel_x = -2;
- pixel_y = 8
- },
-/obj/item/cartridge/atmos{
- pixel_x = -2;
- pixel_y = 4
- },
-/obj/item/cartridge/atmos{
- pixel_x = -2
- },
+/obj/item/computer_hardware/hard_drive/role/atmos,
+/obj/item/computer_hardware/hard_drive/role/atmos,
+/obj/item/computer_hardware/hard_drive/role/atmos,
/obj/effect/turf_decal/tile/neutral/fourcorners,
/obj/machinery/airalarm/directional/south,
/obj/effect/turf_decal/bot,
-/obj/item/cartridge/engineering{
- pixel_x = 6;
- pixel_y = 8
- },
-/obj/item/cartridge/engineering{
- pixel_x = 6;
- pixel_y = 4
- },
-/obj/item/cartridge/engineering{
- pixel_x = 6
- },
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
/obj/structure/rack,
/turf/open/floor/iron/dark,
/area/command/heads_quarters/ce)
@@ -79280,15 +79252,9 @@
/area/ai_monitored/command/storage/eva)
"sNs" = (
/obj/structure/table,
-/obj/item/cartridge/signal/ordnance{
- pixel_x = 6
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_x = -6
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/obj/machinery/camera/directional/east{
c_tag = "Science - Research Director's Office";
name = "science camera";
diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm
index 686ce4b4fe4..208acd17b7e 100644
--- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm
+++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm
@@ -27143,15 +27143,9 @@
/area/service/library)
"mwr" = (
/obj/structure/table/glass,
-/obj/item/cartridge/medical{
- pixel_x = -3
- },
-/obj/item/cartridge/medical{
- pixel_x = 3
- },
-/obj/item/cartridge/chemistry{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/chemistry,
/obj/machinery/status_display/evac/directional/north,
/obj/effect/turf_decal/tile/blue/full,
/turf/open/floor/iron/dark,
@@ -32894,15 +32888,9 @@
},
/obj/structure/table,
/obj/item/coin/silver,
-/obj/item/cartridge/quartermaster,
-/obj/item/cartridge/quartermaster{
- pixel_x = 6;
- pixel_y = 5
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = -4;
- pixel_y = 7
- },
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/obj/item/clipboard,
/turf/open/floor/iron,
/area/cargo/qm)
@@ -45250,18 +45238,10 @@
/area/command/meeting_room)
"vkB" = (
/obj/structure/table/reinforced,
-/obj/item/cartridge/engineering{
- pixel_x = 4;
- pixel_y = 5
- },
-/obj/item/cartridge/engineering{
- pixel_x = -3;
- pixel_y = 2
- },
-/obj/item/cartridge/engineering{
- pixel_x = 3
- },
-/obj/item/cartridge/atmos,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/atmos,
/obj/structure/disposalpipe/segment{
dir = 4
},
@@ -47679,15 +47659,9 @@
/area/medical/medbay/aft)
"wvC" = (
/obj/structure/table,
-/obj/item/cartridge/signal/ordnance{
- pixel_x = 4;
- pixel_y = 6
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_x = -4;
- pixel_y = 2
- },
-/obj/item/cartridge/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/turf/open/floor/iron/cafeteria,
/area/command/heads_quarters/rd)
"wvQ" = (
diff --git a/_maps/map_files/IceBoxStation/IceBoxStation_skyrat.dmm b/_maps/map_files/IceBoxStation/IceBoxStation_skyrat.dmm
index bb5b1b41166..b5b81b774ca 100644
--- a/_maps/map_files/IceBoxStation/IceBoxStation_skyrat.dmm
+++ b/_maps/map_files/IceBoxStation/IceBoxStation_skyrat.dmm
@@ -26846,18 +26846,10 @@
/area/maintenance/central/greater)
"kWO" = (
/obj/structure/table/reinforced,
-/obj/item/cartridge/engineering{
- pixel_x = 4;
- pixel_y = 5
- },
-/obj/item/cartridge/engineering{
- pixel_x = -3;
- pixel_y = 2
- },
-/obj/item/cartridge/engineering{
- pixel_x = 3
- },
-/obj/item/cartridge/atmos,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/atmos,
/obj/structure/disposalpipe/segment{
dir = 4
},
@@ -34474,15 +34466,9 @@
},
/obj/structure/table,
/obj/item/coin/silver,
-/obj/item/cartridge/quartermaster,
-/obj/item/cartridge/quartermaster{
- pixel_x = 6;
- pixel_y = 5
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = -4;
- pixel_y = 7
- },
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/obj/item/clipboard,
/turf/open/floor/iron,
/area/cargo/qm)
@@ -42859,15 +42845,9 @@
/area/security/brig/upper)
"tIB" = (
/obj/structure/table/glass,
-/obj/item/cartridge/medical{
- pixel_x = -3
- },
-/obj/item/cartridge/medical{
- pixel_x = 3
- },
-/obj/item/cartridge/chemistry{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/chemistry,
/obj/machinery/status_display/evac/directional/north,
/obj/effect/turf_decal/tile/blue/full,
/turf/open/floor/iron/dark,
@@ -48115,15 +48095,9 @@
/area/medical/treatment_center)
"wvC" = (
/obj/structure/table,
-/obj/item/cartridge/signal/ordnance{
- pixel_x = 4;
- pixel_y = 6
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_x = -4;
- pixel_y = 2
- },
-/obj/item/cartridge/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/turf/open/floor/iron/cafeteria,
/area/command/heads_quarters/rd)
"wvF" = (
diff --git a/_maps/map_files/IceBoxStation/IcemoonUnderground_Above.dmm b/_maps/map_files/IceBoxStation/IcemoonUnderground_Above.dmm
index 0cf5d28658d..a0eeffd7e00 100644
--- a/_maps/map_files/IceBoxStation/IcemoonUnderground_Above.dmm
+++ b/_maps/map_files/IceBoxStation/IcemoonUnderground_Above.dmm
@@ -4869,7 +4869,7 @@
"nZ" = (
/obj/structure/table/wood,
/obj/item/taperecorder,
-/obj/item/cartridge/lawyer,
+/obj/item/computer_hardware/hard_drive/role/lawyer,
/obj/machinery/computer/security/telescreen/prison{
pixel_y = 32
},
diff --git a/_maps/map_files/IceBoxStation/IcemoonUnderground_Above_skyrat.dmm b/_maps/map_files/IceBoxStation/IcemoonUnderground_Above_skyrat.dmm
index 33420fa3cf3..b2989b27809 100644
--- a/_maps/map_files/IceBoxStation/IcemoonUnderground_Above_skyrat.dmm
+++ b/_maps/map_files/IceBoxStation/IcemoonUnderground_Above_skyrat.dmm
@@ -17162,7 +17162,7 @@
"hmF" = (
/obj/structure/table/wood,
/obj/item/taperecorder,
-/obj/item/cartridge/lawyer,
+/obj/item/computer_hardware/hard_drive/role/lawyer,
/obj/machinery/computer/security/telescreen/prison{
pixel_y = 32
},
diff --git a/_maps/map_files/IceBoxStation/skyrat_old/IceBoxStation_skyrat_old.dmm b/_maps/map_files/IceBoxStation/skyrat_old/IceBoxStation_skyrat_old.dmm
index 8a2f4e5e76d..4cdadfe41f8 100644
--- a/_maps/map_files/IceBoxStation/skyrat_old/IceBoxStation_skyrat_old.dmm
+++ b/_maps/map_files/IceBoxStation/skyrat_old/IceBoxStation_skyrat_old.dmm
@@ -28318,18 +28318,10 @@
/area/engineering/supermatter/room)
"kWO" = (
/obj/structure/table/reinforced,
-/obj/item/cartridge/engineering{
- pixel_x = 4;
- pixel_y = 5
- },
-/obj/item/cartridge/engineering{
- pixel_x = -3;
- pixel_y = 2
- },
-/obj/item/cartridge/engineering{
- pixel_x = 3
- },
-/obj/item/cartridge/atmos,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/atmos,
/obj/structure/disposalpipe/segment{
dir = 4
},
@@ -36194,15 +36186,9 @@
},
/obj/structure/table,
/obj/item/coin/silver,
-/obj/item/cartridge/quartermaster,
-/obj/item/cartridge/quartermaster{
- pixel_x = 6;
- pixel_y = 5
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = -4;
- pixel_y = 7
- },
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/obj/item/clipboard,
/turf/open/floor/iron,
/area/cargo/qm)
@@ -40402,7 +40388,7 @@
"ryQ" = (
/obj/structure/table/wood,
/obj/item/taperecorder,
-/obj/item/cartridge/lawyer,
+/obj/item/computer_hardware/hard_drive/role/lawyer,
/obj/item/radio/intercom/directional/north,
/turf/open/floor/wood,
/area/service/lawoffice)
@@ -44836,15 +44822,9 @@
/area/engineering/main)
"tIB" = (
/obj/structure/table/glass,
-/obj/item/cartridge/medical{
- pixel_x = -3
- },
-/obj/item/cartridge/medical{
- pixel_x = 3
- },
-/obj/item/cartridge/chemistry{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/chemistry,
/obj/machinery/status_display/evac/directional/north,
/obj/effect/turf_decal/tile/blue/full,
/turf/open/floor/iron/dark,
@@ -50241,15 +50221,9 @@
/area/medical/treatment_center)
"wvC" = (
/obj/structure/table,
-/obj/item/cartridge/signal/ordnance{
- pixel_x = 4;
- pixel_y = 6
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_x = -4;
- pixel_y = 2
- },
-/obj/item/cartridge/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/turf/open/floor/iron/cafeteria,
/area/command/heads_quarters/rd)
"wvF" = (
diff --git a/_maps/map_files/IceBoxStation/skyrat_old/IcemoonUnderground_Above_skyrat_old.dmm b/_maps/map_files/IceBoxStation/skyrat_old/IcemoonUnderground_Above_skyrat_old.dmm
index 3855402e27a..531781bad1f 100644
--- a/_maps/map_files/IceBoxStation/skyrat_old/IcemoonUnderground_Above_skyrat_old.dmm
+++ b/_maps/map_files/IceBoxStation/skyrat_old/IcemoonUnderground_Above_skyrat_old.dmm
@@ -11152,8 +11152,8 @@
"BP" = (
/obj/effect/spawner/random/contraband/permabrig_gear,
/obj/effect/spawner/random/contraband/prison,
-/obj/item/pda/clear,
-/obj/item/pda/clear,
+/obj/item/modular_computer/tablet/pda/clear,
+/obj/item/modular_computer/tablet/pda/clear,
/turf/open/floor/plating,
/area/security/prison)
"BQ" = (
diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm
index 62a7c4f330d..3c3f006d183 100644
--- a/_maps/map_files/KiloStation/KiloStation.dmm
+++ b/_maps/map_files/KiloStation/KiloStation.dmm
@@ -30265,9 +30265,9 @@
/obj/structure/table,
/obj/item/clipboard,
/obj/item/folder/yellow,
-/obj/item/cartridge/quartermaster,
-/obj/item/cartridge/quartermaster,
-/obj/item/cartridge/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/obj/item/pen/fountain,
/turf/open/floor/carpet/orange,
/area/cargo/qm)
@@ -43126,14 +43126,10 @@
"jSV" = (
/obj/structure/table,
/obj/item/clipboard,
-/obj/item/cartridge/roboticist{
- pixel_x = -3
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_x = 6
- },
-/obj/item/cartridge/signal/ordnance,
-/obj/item/cartridge/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/roboticist,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/obj/item/circuitboard/aicore{
pixel_y = 5
},
@@ -46532,21 +46528,10 @@
/obj/effect/turf_decal/tile/blue{
dir = 1
},
-/obj/item/cartridge/medical{
- pixel_x = 6;
- pixel_y = 2
- },
-/obj/item/cartridge/medical{
- pixel_x = 5;
- pixel_y = 1
- },
-/obj/item/cartridge/medical{
- pixel_x = 4
- },
-/obj/item/cartridge/chemistry{
- pixel_x = -6;
- pixel_y = 8
- },
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/chemistry,
/obj/item/clothing/neck/stethoscope{
pixel_y = 5
},
@@ -60478,7 +60463,7 @@
pixel_x = 5
},
/obj/structure/table,
-/obj/item/cartridge/lawyer,
+/obj/item/computer_hardware/hard_drive/role/lawyer,
/obj/effect/turf_decal/bot,
/obj/structure/mirror/directional/north,
/turf/open/floor/iron/dark,
@@ -71020,17 +71005,9 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
-/obj/item/cartridge/engineering{
- pixel_x = 6;
- pixel_y = 6
- },
-/obj/item/cartridge/engineering{
- pixel_x = 8
- },
-/obj/item/cartridge/atmos{
- pixel_x = -6;
- pixel_y = 4
- },
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/atmos,
/obj/item/folder,
/obj/item/stamp/ce,
/turf/open/floor/iron/dark,
diff --git a/_maps/map_files/KiloStation/KiloStation_skyrat.dmm b/_maps/map_files/KiloStation/KiloStation_skyrat.dmm
index fc0dec45a96..11e766c9fbb 100644
--- a/_maps/map_files/KiloStation/KiloStation_skyrat.dmm
+++ b/_maps/map_files/KiloStation/KiloStation_skyrat.dmm
@@ -38519,7 +38519,7 @@
pixel_x = 5
},
/obj/structure/table,
-/obj/item/cartridge/lawyer,
+/obj/item/computer_hardware/hard_drive/role/lawyer,
/obj/effect/turf_decal/bot,
/obj/structure/mirror/directional/north,
/turf/open/floor/iron/dark,
@@ -44753,9 +44753,9 @@
/obj/structure/table,
/obj/item/clipboard,
/obj/item/folder/yellow,
-/obj/item/cartridge/quartermaster,
-/obj/item/cartridge/quartermaster,
-/obj/item/cartridge/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/obj/item/pen/fountain,
/turf/open/floor/carpet/orange,
/area/cargo/qm)
@@ -55110,21 +55110,10 @@
/obj/effect/turf_decal/tile/blue{
dir = 1
},
-/obj/item/cartridge/medical{
- pixel_x = 6;
- pixel_y = 2
- },
-/obj/item/cartridge/medical{
- pixel_x = 5;
- pixel_y = 1
- },
-/obj/item/cartridge/medical{
- pixel_x = 4
- },
-/obj/item/cartridge/chemistry{
- pixel_x = -6;
- pixel_y = 8
- },
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/chemistry,
/obj/item/clothing/neck/stethoscope{
pixel_y = 5
},
@@ -57877,14 +57866,10 @@
"mjr" = (
/obj/structure/table,
/obj/item/clipboard,
-/obj/item/cartridge/roboticist{
- pixel_x = -3
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_x = 6
- },
-/obj/item/cartridge/signal/ordnance,
-/obj/item/cartridge/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/roboticist,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/obj/item/circuitboard/aicore{
pixel_y = 5
},
@@ -73918,17 +73903,9 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
-/obj/item/cartridge/engineering{
- pixel_x = 6;
- pixel_y = 6
- },
-/obj/item/cartridge/engineering{
- pixel_x = 8
- },
-/obj/item/cartridge/atmos{
- pixel_x = -6;
- pixel_y = 4
- },
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/atmos,
/obj/item/folder,
/obj/item/stamp/ce,
/turf/open/floor/iron/dark,
diff --git a/_maps/map_files/KiloStation/skyrat_old/KiloStation_skyrat_old.dmm b/_maps/map_files/KiloStation/skyrat_old/KiloStation_skyrat_old.dmm
index 6407d9e9a99..114c3f4c0b4 100644
--- a/_maps/map_files/KiloStation/skyrat_old/KiloStation_skyrat_old.dmm
+++ b/_maps/map_files/KiloStation/skyrat_old/KiloStation_skyrat_old.dmm
@@ -38401,7 +38401,7 @@
pixel_x = 5
},
/obj/structure/table,
-/obj/item/cartridge/lawyer,
+/obj/item/computer_hardware/hard_drive/role/lawyer,
/obj/structure/cable,
/obj/machinery/power/apc/auto_name/directional/north,
/turf/open/floor/iron/dark,
@@ -44063,9 +44063,9 @@
},
/obj/item/clipboard,
/obj/item/folder/yellow,
-/obj/item/cartridge/quartermaster,
-/obj/item/cartridge/quartermaster,
-/obj/item/cartridge/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/turf/open/floor/iron,
/area/cargo/qm)
"gQJ" = (
@@ -53701,21 +53701,10 @@
/obj/effect/turf_decal/tile/blue{
dir = 1
},
-/obj/item/cartridge/medical{
- pixel_x = 6;
- pixel_y = 2
- },
-/obj/item/cartridge/medical{
- pixel_x = 5;
- pixel_y = 1
- },
-/obj/item/cartridge/medical{
- pixel_x = 4
- },
-/obj/item/cartridge/chemistry{
- pixel_x = -6;
- pixel_y = 8
- },
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/chemistry,
/obj/item/clothing/neck/stethoscope{
pixel_y = 5
},
@@ -56235,14 +56224,10 @@
},
/obj/structure/table,
/obj/item/clipboard,
-/obj/item/cartridge/roboticist{
- pixel_x = -3
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_x = 6
- },
-/obj/item/cartridge/signal/ordnance,
-/obj/item/cartridge/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/roboticist,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/obj/item/circuitboard/aicore{
pixel_y = 5
},
@@ -70914,17 +70899,9 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
-/obj/item/cartridge/engineering{
- pixel_x = 6;
- pixel_y = 6
- },
-/obj/item/cartridge/engineering{
- pixel_x = 8
- },
-/obj/item/cartridge/atmos{
- pixel_x = -6;
- pixel_y = 4
- },
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/atmos,
/obj/item/folder,
/obj/item/stamp/ce,
/turf/open/floor/iron/dark,
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index 2664dd1699a..436a920359a 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -10342,19 +10342,11 @@
/turf/closed/wall/r_wall,
/area/maintenance/solars/starboard/aft)
"cLe" = (
-/obj/item/cartridge/engineering{
- pixel_x = 4;
- pixel_y = 5
- },
-/obj/item/cartridge/engineering{
- pixel_x = -3;
- pixel_y = 2
- },
-/obj/item/cartridge/engineering{
- pixel_x = 3
- },
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
/obj/structure/table/reinforced,
-/obj/item/cartridge/atmos,
+/obj/item/computer_hardware/hard_drive/role/atmos,
/obj/effect/turf_decal/tile/neutral/half/contrasted{
dir = 4
},
@@ -32491,10 +32483,7 @@
"kMr" = (
/obj/machinery/power/apc/auto_name/directional/east,
/obj/structure/table/wood,
-/obj/item/cartridge/detective{
- pixel_x = 7;
- pixel_y = 8
- },
+/obj/item/computer_hardware/hard_drive/role/detective,
/obj/item/folder/red{
pixel_x = -7;
pixel_y = 6
@@ -32502,13 +32491,8 @@
/obj/item/folder/red{
pixel_x = -7
},
-/obj/item/cartridge/detective{
- pixel_x = 7;
- pixel_y = 4
- },
-/obj/item/cartridge/detective{
- pixel_x = 7
- },
+/obj/item/computer_hardware/hard_drive/role/detective,
+/obj/item/computer_hardware/hard_drive/role/detective,
/obj/structure/cable,
/turf/open/floor/iron/dark,
/area/command/heads_quarters/hos)
@@ -44178,15 +44162,9 @@
/obj/effect/turf_decal/siding{
dir = 4
},
-/obj/item/cartridge/signal/ordnance{
- pixel_x = 6
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_x = -6
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/turf/open/floor/iron/dark,
/area/command/heads_quarters/rd)
"oRu" = (
@@ -49694,17 +49672,9 @@
pixel_x = -10;
pixel_y = 9
},
-/obj/item/cartridge/quartermaster{
- pixel_x = 9
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = 5;
- pixel_y = 11
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = 8;
- pixel_y = 4
- },
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/turf/open/floor/wood,
/area/cargo/qm)
"qWo" = (
@@ -51168,7 +51138,7 @@
},
/obj/item/pen,
/obj/item/taperecorder,
-/obj/item/cartridge/lawyer,
+/obj/item/computer_hardware/hard_drive/role/lawyer,
/obj/machinery/button/door/directional/south{
id = "lawyer_shutters";
name = "law office shutter control";
@@ -53876,15 +53846,9 @@
/area/service/chapel/funeral)
"sEP" = (
/obj/structure/table/glass,
-/obj/item/cartridge/medical{
- pixel_x = -3
- },
-/obj/item/cartridge/medical{
- pixel_x = 3
- },
-/obj/item/cartridge/chemistry{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/chemistry,
/obj/machinery/light_switch/directional/north,
/obj/machinery/vending/wallmed/directional/west,
/obj/effect/turf_decal/tile/blue/anticorner/contrasted{
diff --git a/_maps/map_files/MetaStation/MetaStation_skyrat.dmm b/_maps/map_files/MetaStation/MetaStation_skyrat.dmm
index d3cf0fcdd11..b1dcbf6c067 100644
--- a/_maps/map_files/MetaStation/MetaStation_skyrat.dmm
+++ b/_maps/map_files/MetaStation/MetaStation_skyrat.dmm
@@ -14307,15 +14307,9 @@
/area/commons/fitness/recreation)
"dtB" = (
/obj/structure/table/glass,
-/obj/item/cartridge/medical{
- pixel_x = -3
- },
-/obj/item/cartridge/medical{
- pixel_x = 3
- },
-/obj/item/cartridge/chemistry{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/chemistry,
/obj/machinery/light_switch/directional/north,
/obj/machinery/vending/wallmed/directional/west,
/obj/effect/turf_decal/tile/blue/anticorner/contrasted{
@@ -33463,10 +33457,7 @@
"kMr" = (
/obj/machinery/power/apc/auto_name/directional/east,
/obj/structure/table/wood,
-/obj/item/cartridge/detective{
- pixel_x = 7;
- pixel_y = 8
- },
+/obj/item/computer_hardware/hard_drive/role/detective,
/obj/item/folder/red{
pixel_x = -7;
pixel_y = 6
@@ -33474,13 +33465,8 @@
/obj/item/folder/red{
pixel_x = -7
},
-/obj/item/cartridge/detective{
- pixel_x = 7;
- pixel_y = 4
- },
-/obj/item/cartridge/detective{
- pixel_x = 7
- },
+/obj/item/computer_hardware/hard_drive/role/detective,
+/obj/item/computer_hardware/hard_drive/role/detective,
/obj/structure/cable,
/turf/open/floor/iron/dark,
/area/command/heads_quarters/hos)
@@ -44685,15 +44671,9 @@
/obj/effect/turf_decal/siding{
dir = 4
},
-/obj/item/cartridge/signal/ordnance{
- pixel_x = 6
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_x = -6
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/turf/open/floor/iron/dark,
/area/command/heads_quarters/rd)
"oRu" = (
@@ -48912,19 +48892,11 @@
/turf/open/floor/iron/white,
/area/medical/chemistry)
"qxl" = (
-/obj/item/cartridge/engineering{
- pixel_x = 4;
- pixel_y = 5
- },
-/obj/item/cartridge/engineering{
- pixel_x = -3;
- pixel_y = 2
- },
-/obj/item/cartridge/engineering{
- pixel_x = 3
- },
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
/obj/structure/table/reinforced,
-/obj/item/cartridge/atmos,
+/obj/item/computer_hardware/hard_drive/role/atmos,
/obj/effect/turf_decal/tile/neutral/half/contrasted{
dir = 4
},
@@ -50109,17 +50081,9 @@
pixel_x = -10;
pixel_y = 9
},
-/obj/item/cartridge/quartermaster{
- pixel_x = 9
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = 5;
- pixel_y = 11
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = 8;
- pixel_y = 4
- },
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/turf/open/floor/wood,
/area/cargo/qm)
"qWv" = (
@@ -51627,7 +51591,7 @@
},
/obj/item/pen,
/obj/item/taperecorder,
-/obj/item/cartridge/lawyer,
+/obj/item/computer_hardware/hard_drive/role/lawyer,
/obj/machinery/button/door/directional/south{
id = "lawyer_shutters";
name = "law office shutter control";
diff --git a/_maps/map_files/MetaStation/skryat_old/MetaStation_skyrat_old.dmm b/_maps/map_files/MetaStation/skryat_old/MetaStation_skyrat_old.dmm
index 4e92c2ad265..c9e44d8f8a8 100644
--- a/_maps/map_files/MetaStation/skryat_old/MetaStation_skyrat_old.dmm
+++ b/_maps/map_files/MetaStation/skryat_old/MetaStation_skyrat_old.dmm
@@ -15081,15 +15081,9 @@
/area/commons/fitness/recreation)
"dtB" = (
/obj/structure/table/glass,
-/obj/item/cartridge/medical{
- pixel_x = -3
- },
-/obj/item/cartridge/medical{
- pixel_x = 3
- },
-/obj/item/cartridge/chemistry{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/chemistry,
/obj/effect/turf_decal/tile/blue{
dir = 8
},
@@ -35237,10 +35231,7 @@
"kMr" = (
/obj/machinery/power/apc/auto_name/directional/east,
/obj/structure/table/wood,
-/obj/item/cartridge/detective{
- pixel_x = 7;
- pixel_y = 8
- },
+/obj/item/computer_hardware/hard_drive/role/detective,
/obj/item/folder/red{
pixel_x = -7;
pixel_y = 6
@@ -35248,13 +35239,8 @@
/obj/item/folder/red{
pixel_x = -7
},
-/obj/item/cartridge/detective{
- pixel_x = 7;
- pixel_y = 4
- },
-/obj/item/cartridge/detective{
- pixel_x = 7
- },
+/obj/item/computer_hardware/hard_drive/role/detective,
+/obj/item/computer_hardware/hard_drive/role/detective,
/obj/structure/cable,
/turf/open/floor/iron/dark,
/area/command/heads_quarters/hos)
@@ -47020,15 +47006,9 @@
/obj/effect/turf_decal/siding{
dir = 4
},
-/obj/item/cartridge/signal/ordnance{
- pixel_x = 6
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_x = -6
- },
-/obj/item/cartridge/signal/ordnance{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/turf/open/floor/iron/dark,
/area/command/heads_quarters/rd)
"oRu" = (
@@ -51352,19 +51332,11 @@
/turf/open/floor/iron/white,
/area/medical/chemistry)
"qxl" = (
-/obj/item/cartridge/engineering{
- pixel_x = 4;
- pixel_y = 5
- },
-/obj/item/cartridge/engineering{
- pixel_x = -3;
- pixel_y = 2
- },
-/obj/item/cartridge/engineering{
- pixel_x = 3
- },
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
/obj/structure/table/reinforced,
-/obj/item/cartridge/atmos,
+/obj/item/computer_hardware/hard_drive/role/atmos,
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
@@ -52604,17 +52576,9 @@
pixel_x = -10;
pixel_y = 9
},
-/obj/item/cartridge/quartermaster{
- pixel_x = 9
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = 5;
- pixel_y = 11
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = 8;
- pixel_y = 4
- },
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/turf/open/floor/wood,
/area/cargo/qm)
"qWv" = (
@@ -54166,7 +54130,7 @@
},
/obj/item/pen,
/obj/item/taperecorder,
-/obj/item/cartridge/lawyer,
+/obj/item/computer_hardware/hard_drive/role/lawyer,
/obj/machinery/button/door/directional/south{
id = "lawyer_shutters";
name = "law office shutter control";
diff --git a/_maps/map_files/NSSJourney/NSSJourney.dmm b/_maps/map_files/NSSJourney/NSSJourney.dmm
index 74d31bcdc2f..fb6e5e0dd53 100644
--- a/_maps/map_files/NSSJourney/NSSJourney.dmm
+++ b/_maps/map_files/NSSJourney/NSSJourney.dmm
@@ -289,15 +289,9 @@
},
/obj/structure/table,
/obj/item/coin/silver,
-/obj/item/cartridge/quartermaster,
-/obj/item/cartridge/quartermaster{
- pixel_x = 6;
- pixel_y = 5
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = -4;
- pixel_y = 7
- },
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/obj/item/clipboard,
/obj/effect/turf_decal/tile/yellow{
dir = 8
@@ -9604,9 +9598,9 @@
/obj/structure/table,
/obj/item/folder/white,
/obj/item/pen,
-/obj/item/cartridge/signal/ordnance,
-/obj/item/cartridge/signal/ordnance,
-/obj/item/cartridge/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/obj/item/stamp/rd{
pixel_x = 3;
pixel_y = -2
@@ -29754,18 +29748,10 @@
/area/security/brig)
"cjY" = (
/obj/structure/table/reinforced,
-/obj/item/cartridge/engineering{
- pixel_x = 4;
- pixel_y = 5
- },
-/obj/item/cartridge/engineering{
- pixel_x = -3;
- pixel_y = 2
- },
-/obj/item/cartridge/engineering{
- pixel_x = 3
- },
-/obj/item/cartridge/atmos,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/atmos,
/obj/structure/disposalpipe/segment{
dir = 9
},
@@ -45345,7 +45331,7 @@
},
/obj/structure/table/wood,
/obj/item/taperecorder,
-/obj/item/cartridge/lawyer,
+/obj/item/computer_hardware/hard_drive/role/lawyer,
/turf/open/floor/wood,
/area/service/lawoffice)
"mNa" = (
@@ -54252,7 +54238,7 @@
},
/area/security/prison)
"uWg" = (
-/obj/item/pda/clear,
+/obj/item/modular_computer/tablet/pda/clear,
/turf/open/floor/plating,
/area/security/prison/safe)
"uWp" = (
diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index df2ba83c060..3821946e213 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -5590,15 +5590,9 @@
/area/tdome/observation)
"pP" = (
/obj/structure/table/reinforced,
-/obj/item/cartridge/quartermaster{
- pixel_x = -6
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = 6
- },
-/obj/item/cartridge/quartermaster{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/obj/item/gps/mining,
/obj/effect/turf_decal/stripes/line{
dir = 6
diff --git a/_maps/map_files/generic/CentCom_skyrat.dmm b/_maps/map_files/generic/CentCom_skyrat.dmm
index 1aac9798dce..6167dcd72aa 100644
--- a/_maps/map_files/generic/CentCom_skyrat.dmm
+++ b/_maps/map_files/generic/CentCom_skyrat.dmm
@@ -5426,15 +5426,9 @@
/area/centcom/admin)
"pP" = (
/obj/structure/table/reinforced,
-/obj/item/cartridge/quartermaster{
- pixel_x = -6
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = 6
- },
-/obj/item/cartridge/quartermaster{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/obj/item/gps/mining,
/obj/effect/turf_decal/stripes/line{
dir = 6
diff --git a/_maps/map_files/generic/CentCom_skyrat_z2.dmm b/_maps/map_files/generic/CentCom_skyrat_z2.dmm
index 87083468b7a..3c99fa40c7f 100644
--- a/_maps/map_files/generic/CentCom_skyrat_z2.dmm
+++ b/_maps/map_files/generic/CentCom_skyrat_z2.dmm
@@ -3803,7 +3803,7 @@
/turf/open/floor/iron,
/area/centcom/interlink)
"aJM" = (
-/obj/item/pda/clear,
+/obj/item/modular_computer/tablet/pda/clear,
/obj/effect/turf_decal/stripes/asteroid/line{
dir = 8
},
diff --git a/_maps/map_files/tramstation/skryat_old/tramstation_skyrat_old.dmm b/_maps/map_files/tramstation/skryat_old/tramstation_skyrat_old.dmm
index 9bbe3b0b8a2..8efc4bbea24 100644
--- a/_maps/map_files/tramstation/skryat_old/tramstation_skyrat_old.dmm
+++ b/_maps/map_files/tramstation/skryat_old/tramstation_skyrat_old.dmm
@@ -12844,15 +12844,9 @@
"cWa" = (
/obj/structure/table/reinforced,
/obj/structure/window/reinforced,
-/obj/item/cartridge/signal/ordnance{
- pixel_x = -4;
- pixel_y = 2
- },
-/obj/item/cartridge/signal/ordnance,
-/obj/item/cartridge/signal/ordnance{
- pixel_x = 4;
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/obj/effect/landmark/event_spawn,
/turf/open/floor/iron/cafeteria{
dir = 5
@@ -53081,18 +53075,10 @@
/area/ai_monitored/turret_protected/aisat/hallway)
"rxV" = (
/obj/structure/table/reinforced,
-/obj/item/cartridge/engineering{
- pixel_x = 4;
- pixel_y = 5
- },
-/obj/item/cartridge/engineering{
- pixel_x = 3
- },
-/obj/item/cartridge/engineering{
- pixel_x = -3;
- pixel_y = 2
- },
-/obj/item/cartridge/atmos,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/atmos,
/obj/effect/turf_decal/trimline/yellow/filled/line{
dir = 1
},
@@ -64939,14 +64925,8 @@
/obj/effect/turf_decal/trimline/brown/filled/line{
dir = 8
},
-/obj/item/cartridge/quartermaster{
- pixel_x = 6;
- pixel_y = 5
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = -4;
- pixel_y = 7
- },
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/obj/item/clipboard,
/turf/open/floor/iron,
/area/cargo/qm)
@@ -66224,15 +66204,9 @@
dir = 8
},
/obj/item/screwdriver,
-/obj/item/cartridge/medical{
- pixel_x = 3
- },
-/obj/item/cartridge/medical{
- pixel_x = -3
- },
-/obj/item/cartridge/chemistry{
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/chemistry,
/turf/open/floor/iron/dark,
/area/command/heads_quarters/cmo)
"wiy" = (
diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm
index 0d50d3d64ec..fb5c59e4f5d 100644
--- a/_maps/map_files/tramstation/tramstation.dmm
+++ b/_maps/map_files/tramstation/tramstation.dmm
@@ -11803,15 +11803,9 @@
"cWa" = (
/obj/structure/table/reinforced,
/obj/structure/window/reinforced,
-/obj/item/cartridge/signal/ordnance{
- pixel_x = -4;
- pixel_y = 2
- },
-/obj/item/cartridge/signal/ordnance,
-/obj/item/cartridge/signal/ordnance{
- pixel_x = 4;
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/obj/effect/landmark/event_spawn,
/turf/open/floor/iron/cafeteria{
dir = 5
@@ -52182,18 +52176,10 @@
/area/ai_monitored/turret_protected/aisat/hallway)
"rxV" = (
/obj/structure/table/reinforced,
-/obj/item/cartridge/engineering{
- pixel_x = 4;
- pixel_y = 5
- },
-/obj/item/cartridge/engineering{
- pixel_x = 3
- },
-/obj/item/cartridge/engineering{
- pixel_x = -3;
- pixel_y = 2
- },
-/obj/item/cartridge/atmos,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/atmos,
/obj/effect/turf_decal/trimline/yellow/filled/line{
dir = 1
},
@@ -59868,15 +59854,9 @@
/area/security/brig)
"umv" = (
/obj/structure/table/glass,
-/obj/item/cartridge/chemistry{
- pixel_y = 6
- },
-/obj/item/cartridge/medical{
- pixel_x = 3
- },
-/obj/item/cartridge/medical{
- pixel_x = -3
- },
+/obj/item/computer_hardware/hard_drive/role/chemistry,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
/obj/effect/turf_decal/tile/blue/fourcorners,
/turf/open/floor/iron/dark,
/area/command/heads_quarters/cmo)
@@ -63505,14 +63485,8 @@
/obj/effect/turf_decal/trimline/brown/filled/line{
dir = 8
},
-/obj/item/cartridge/quartermaster{
- pixel_x = 6;
- pixel_y = 5
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = -4;
- pixel_y = 7
- },
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/obj/item/clipboard,
/turf/open/floor/iron,
/area/cargo/qm)
diff --git a/_maps/map_files/tramstation/tramstation_skyrat.dmm b/_maps/map_files/tramstation/tramstation_skyrat.dmm
index d7957fe596b..72904b9010b 100644
--- a/_maps/map_files/tramstation/tramstation_skyrat.dmm
+++ b/_maps/map_files/tramstation/tramstation_skyrat.dmm
@@ -11862,15 +11862,9 @@
"cWa" = (
/obj/structure/table/reinforced,
/obj/structure/window/reinforced,
-/obj/item/cartridge/signal/ordnance{
- pixel_x = -4;
- pixel_y = 2
- },
-/obj/item/cartridge/signal/ordnance,
-/obj/item/cartridge/signal/ordnance{
- pixel_x = 4;
- pixel_y = 6
- },
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance,
/obj/effect/landmark/event_spawn,
/turf/open/floor/iron/cafeteria{
dir = 5
@@ -27574,15 +27568,9 @@
/area/space/nearstation)
"ior" = (
/obj/structure/table/glass,
-/obj/item/cartridge/chemistry{
- pixel_y = 6
- },
-/obj/item/cartridge/medical{
- pixel_x = 3
- },
-/obj/item/cartridge/medical{
- pixel_x = -3
- },
+/obj/item/computer_hardware/hard_drive/role/chemistry,
+/obj/item/computer_hardware/hard_drive/role/medical,
+/obj/item/computer_hardware/hard_drive/role/medical,
/obj/effect/turf_decal/tile/blue/fourcorners,
/turf/open/floor/iron/dark,
/area/command/heads_quarters/cmo)
@@ -27677,7 +27665,7 @@
/obj/item/grenade/smokebomb,
/obj/item/screwdriver,
/obj/item/toy/crayon/spraycan,
-/obj/item/pda,
+/obj/item/modular_computer/tablet/pda,
/obj/item/radio,
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plating,
@@ -53037,18 +53025,10 @@
/area/ai_monitored/turret_protected/aisat/hallway)
"rxV" = (
/obj/structure/table/reinforced,
-/obj/item/cartridge/engineering{
- pixel_x = 4;
- pixel_y = 5
- },
-/obj/item/cartridge/engineering{
- pixel_x = 3
- },
-/obj/item/cartridge/engineering{
- pixel_x = -3;
- pixel_y = 2
- },
-/obj/item/cartridge/atmos,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/engineering,
+/obj/item/computer_hardware/hard_drive/role/atmos,
/obj/effect/turf_decal/trimline/yellow/filled/line{
dir = 1
},
@@ -65066,14 +65046,8 @@
/obj/effect/turf_decal/trimline/brown/filled/line{
dir = 8
},
-/obj/item/cartridge/quartermaster{
- pixel_x = 6;
- pixel_y = 5
- },
-/obj/item/cartridge/quartermaster{
- pixel_x = -4;
- pixel_y = 7
- },
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
+/obj/item/computer_hardware/hard_drive/role/quartermaster,
/obj/item/clipboard,
/turf/open/floor/iron,
/area/cargo/qm)
diff --git a/code/__DEFINES/access.dm b/code/__DEFINES/access.dm
index b45ad6a0bc5..aac3cd015bb 100644
--- a/code/__DEFINES/access.dm
+++ b/code/__DEFINES/access.dm
@@ -480,36 +480,36 @@
* Used to see pda_region in [/datum/controller/subsystem/id_access/proc/setup_tgui_lists]
*/
#define PDA_PAINTING_REGIONS list( \
- /obj/item/pda = list(REGION_GENERAL), \
- /obj/item/pda/clown = list(REGION_GENERAL), \
- /obj/item/pda/mime = list(REGION_GENERAL), \
- /obj/item/pda/medical = list(REGION_MEDBAY), \
- /obj/item/pda/viro = list(REGION_MEDBAY), \
- /obj/item/pda/engineering = list(REGION_ENGINEERING), \
- /obj/item/pda/security = list(REGION_SECURITY), \
- /obj/item/pda/detective = list(REGION_SECURITY), \
- /obj/item/pda/warden = list(REGION_SECURITY), \
- /obj/item/pda/janitor = list(REGION_GENERAL), \
- /obj/item/pda/science = list(REGION_RESEARCH), \
- /obj/item/pda/heads/hop = list(REGION_COMMAND), \
- /obj/item/pda/heads/hos = list(REGION_COMMAND), \
- /obj/item/pda/heads/cmo = list(REGION_COMMAND), \
- /obj/item/pda/heads/ce = list(REGION_COMMAND), \
- /obj/item/pda/heads/rd = list(REGION_COMMAND), \
- /obj/item/pda/captain = list(REGION_COMMAND), \
- /obj/item/pda/cargo = list(REGION_SUPPLY), \
- /obj/item/pda/quartermaster = list(REGION_SUPPLY), \
- /obj/item/pda/shaftminer = list(REGION_SUPPLY), \
- /obj/item/pda/chaplain = list(REGION_GENERAL), \
- /obj/item/pda/lawyer = list(REGION_GENERAL, REGION_SECURITY), \
- /obj/item/pda/botanist = list(REGION_GENERAL), \
- /obj/item/pda/roboticist = list(REGION_RESEARCH), \
- /obj/item/pda/curator = list(REGION_GENERAL), \
- /obj/item/pda/cook = list(REGION_GENERAL), \
- /obj/item/pda/bar = list(REGION_GENERAL), \
- /obj/item/pda/atmos = list(REGION_ENGINEERING), \
- /obj/item/pda/chemist = list(REGION_MEDBAY), \
- /obj/item/pda/geneticist = list(REGION_RESEARCH), \
+ /obj/item/modular_computer/tablet/pda = list(REGION_GENERAL), \
+ /obj/item/modular_computer/tablet/pda/clown = list(REGION_GENERAL), \
+ /obj/item/modular_computer/tablet/pda/mime = list(REGION_GENERAL), \
+ /obj/item/modular_computer/tablet/pda/medical = list(REGION_MEDBAY), \
+ /obj/item/modular_computer/tablet/pda/viro = list(REGION_MEDBAY), \
+ /obj/item/modular_computer/tablet/pda/engineering = list(REGION_ENGINEERING), \
+ /obj/item/modular_computer/tablet/pda/security = list(REGION_SECURITY), \
+ /obj/item/modular_computer/tablet/pda/detective = list(REGION_SECURITY), \
+ /obj/item/modular_computer/tablet/pda/warden = list(REGION_SECURITY), \
+ /obj/item/modular_computer/tablet/pda/janitor = list(REGION_GENERAL), \
+ /obj/item/modular_computer/tablet/pda/science = list(REGION_RESEARCH), \
+ /obj/item/modular_computer/tablet/pda/heads/hop = list(REGION_COMMAND), \
+ /obj/item/modular_computer/tablet/pda/heads/hos = list(REGION_COMMAND), \
+ /obj/item/modular_computer/tablet/pda/heads/cmo = list(REGION_COMMAND), \
+ /obj/item/modular_computer/tablet/pda/heads/ce = list(REGION_COMMAND), \
+ /obj/item/modular_computer/tablet/pda/heads/rd = list(REGION_COMMAND), \
+ /obj/item/modular_computer/tablet/pda/captain = list(REGION_COMMAND), \
+ /obj/item/modular_computer/tablet/pda/cargo = list(REGION_SUPPLY), \
+ /obj/item/modular_computer/tablet/pda/quartermaster = list(REGION_SUPPLY), \
+ /obj/item/modular_computer/tablet/pda/shaftminer = list(REGION_SUPPLY), \
+ /obj/item/modular_computer/tablet/pda/chaplain = list(REGION_GENERAL), \
+ /obj/item/modular_computer/tablet/pda/lawyer = list(REGION_GENERAL, REGION_SECURITY), \
+ /obj/item/modular_computer/tablet/pda/botanist = list(REGION_GENERAL), \
+ /obj/item/modular_computer/tablet/pda/roboticist = list(REGION_RESEARCH), \
+ /obj/item/modular_computer/tablet/pda/curator = list(REGION_GENERAL), \
+ /obj/item/modular_computer/tablet/pda/cook = list(REGION_GENERAL), \
+ /obj/item/modular_computer/tablet/pda/bar = list(REGION_GENERAL), \
+ /obj/item/modular_computer/tablet/pda/atmos = list(REGION_ENGINEERING), \
+ /obj/item/modular_computer/tablet/pda/chemist = list(REGION_MEDBAY), \
+ /obj/item/modular_computer/tablet/pda/geneticist = list(REGION_RESEARCH), \
)
/// All regions that make up the station area. Helper define to quickly designate a region as part of the station or not. Access via SSid_access.station_regions.
diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm
index edec22ac708..300ff4f16b5 100644
--- a/code/__DEFINES/dcs/signals/signals_object.dm
+++ b/code/__DEFINES/dcs/signals/signals_object.dm
@@ -268,10 +268,10 @@
// /obj/item/pda signals
///called on pda when the user changes the ringtone: (mob/living/user, new_ringtone)
-#define COMSIG_PDA_CHANGE_RINGTONE "pda_change_ringtone"
+#define COMSIG_TABLET_CHANGE_ID "comsig_tablet_change_id"
#define COMPONENT_STOP_RINGTONE_CHANGE (1<<0)
-#define COMSIG_PDA_CHECK_DETONATE "pda_check_detonate"
- #define COMPONENT_PDA_NO_DETONATE (1<<0)
+#define COMSIG_TABLET_CHECK_DETONATE "pda_check_detonate"
+ #define COMPONENT_TABLET_NO_DETONATE (1<<0)
// /obj/item/radio signals
diff --git a/code/__DEFINES/devices.dm b/code/__DEFINES/devices.dm
index a6ecf11e56e..d76f56168a9 100644
--- a/code/__DEFINES/devices.dm
+++ b/code/__DEFINES/devices.dm
@@ -1,44 +1,18 @@
-// PDA defines //
-#define CART_SECURITY (1<<0)
-#define CART_ENGINE (1<<1)
-#define CART_ATMOS (1<<2)
-#define CART_MEDICAL (1<<3)
-#define CART_MANIFEST (1<<4)
-#define CART_CLOWN (1<<5)
-#define CART_MIME (1<<6)
-#define CART_REAGENT_SCANNER (1<<7)
-#define CART_STATUS_DISPLAY (1<<10)
-#define CART_QUARTERMASTER (1<<11)
+// Role disk defines
-/// PDA ui menu defines
-#define PDA_UI_HUB 0
-#define PDA_UI_NOTEKEEPER 1
-#define PDA_UI_MESSENGER 2
-#define PDA_UI_READ_MESSAGES 21
-#define PDA_UI_ATMOS_SCAN 3
-#define PDA_UI_SKILL_TRACKER 4
-/// mode is divided by on return
-#define PDA_UI_RETURN_DIVIDER 10
-/// if the new mode from return is between these, go straight to the hub.
-#define PDA_UI_REDIRECT_HUB_MIN 4
-#define PDA_UI_REDIRECT_HUB_MAX 9
-#define PDA_UI_CREW_MANIFEST 41
-#define PDA_UI_STATUS_DISPLAY 42
-#define PDA_UI_POWER_MONITOR 43
-#define PDA_UI_POWER_MONITOR_SELECTED 433
-#define PDA_UI_MED_RECORDS 44
-#define PDA_UI_MED_RECORD_SELECTED 441
-#define PDA_UI_SEC_RECORDS 45
-#define PDA_UI_SEC_RECORD_SELECTED 451
-#define PDA_UI_SUPPLY_RECORDS 46
-#define PDA_UI_SILO_LOGS 47
-#define PDA_UI_BOTS_ACCESS 48
-#define PDA_UI_EMOJI_GUIDE 49
-#define PDA_UI_SIGNALER 50
-
-
-// Used by PDA and cartridge code to reduce repetitiveness of spritesheets
-#define PDAIMG(what) {" "}
+#define DISK_POWER (1<<0)
+#define DISK_ATMOS (1<<1)
+#define DISK_MED (1<<2)
+#define DISK_CHEM (1<<3)
+#define DISK_MANIFEST (1<<4)
+#define DISK_NEWS (1<<5)
+#define DISK_SIGNAL (1<<6)
+#define DISK_STATUS (1<<7)
+#define DISK_CARGO (1<<8)
+#define DISK_ROBOS (1<<9)
+#define DISK_JANI (1<<10)
+#define DISK_SEC (1<<11)
+#define DISK_BUDGET (1<<12)
// Used to stringify message targets before sending the signal datum.
#define STRINGIFY_PDA_TARGET(name, job) "[name] ([job])"
diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm
index 5c18965d913..97793291f6d 100644
--- a/code/__DEFINES/hud.dm
+++ b/code/__DEFINES/hud.dm
@@ -163,13 +163,12 @@
#define ui_ai_announcement "SOUTH:6,WEST+7"
#define ui_ai_shuttle "SOUTH:6,WEST+8"
#define ui_ai_state_laws "SOUTH:6,WEST+9"
-#define ui_ai_pda_send "SOUTH:6,WEST+10"
-#define ui_ai_pda_log "SOUTH:6,WEST+11"
-#define ui_ai_take_picture "SOUTH:6,WEST+12"
-#define ui_ai_view_images "SOUTH:6,WEST+13"
-#define ui_ai_sensor "SOUTH:6,WEST+14"
-#define ui_ai_multicam "SOUTH+1:6,WEST+13"
-#define ui_ai_add_multicam "SOUTH+1:6,WEST+14"
+#define ui_ai_mod_int "SOUTH:6,WEST+10"
+#define ui_ai_take_picture "SOUTH:6,WEST+11"
+#define ui_ai_view_images "SOUTH:6,WEST+12"
+#define ui_ai_sensor "SOUTH:6,WEST+13"
+#define ui_ai_multicam "SOUTH+1:6,WEST+12"
+#define ui_ai_add_multicam "SOUTH+1:6,WEST+13"
#define ui_ai_language_menu "SOUTH+1:8,WEST+11:30"
//pAI
@@ -182,14 +181,13 @@
#define ui_pai_host_monitor "SOUTH:6,WEST+6"
#define ui_pai_crew_manifest "SOUTH:6,WEST+7"
#define ui_pai_state_laws "SOUTH:6,WEST+8"
-#define ui_pai_pda_send "SOUTH:6,WEST+9"
-#define ui_pai_pda_log "SOUTH:6,WEST+10"
-#define ui_pai_internal_gps "SOUTH:6,WEST+11"
-#define ui_pai_take_picture "SOUTH:6,WEST+12"
-#define ui_pai_view_images "SOUTH:6,WEST+13"
-#define ui_pai_radio "SOUTH:6,WEST+14"
-#define ui_pai_language_menu "SOUTH+1:8,WEST+13:31"
-#define ui_pai_navigate_menu "SOUTH+1:8,WEST+13:31"
+#define ui_pai_mod_int "SOUTH:6,WEST+9"
+#define ui_pai_internal_gps "SOUTH:6,WEST+10"
+#define ui_pai_take_picture "SOUTH:6,WEST+11"
+#define ui_pai_view_images "SOUTH:6,WEST+12"
+#define ui_pai_radio "SOUTH:6,WEST+13"
+#define ui_pai_language_menu "SOUTH+1:8,WEST+12:31"
+#define ui_pai_navigate_menu "SOUTH+1:8,WEST+12:31"
//Ghosts
#define ui_ghost_spawners_menu "SOUTH:6,CENTER-3:24"
diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm
index 249c178b52d..4201979ccbd 100644
--- a/code/__DEFINES/machines.dm
+++ b/code/__DEFINES/machines.dm
@@ -59,9 +59,11 @@
//Modular computer part defines
#define MC_CPU "CPU"
#define MC_HDD "HDD"
+#define MC_HDD_JOB "HDD_JOB"
#define MC_SDD "SDD"
#define MC_CARD "CARD"
#define MC_CARD2 "CARD2"
+#define MC_CART "CART"
#define MC_NET "NET"
#define MC_PRINT "PRINT"
#define MC_CELL "CELL"
@@ -69,6 +71,7 @@
#define MC_AI "AI"
#define MC_SENSORS "SENSORS"
#define MC_SIGNALER "SIGNALER"
+#define MC_IDENTIFY "IDENTIFY"
//NTNet stuff, for modular computers
// NTNet module-configuration values. Do not change these. If you need to add another use larger number (5..6..7 etc)
diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm
index 2a0db3544e6..8545b04d6f3 100644
--- a/code/__HELPERS/cmp.dm
+++ b/code/__HELPERS/cmp.dm
@@ -128,11 +128,11 @@ GLOBAL_VAR_INIT(cmp_field, "name")
/proc/cmp_typepaths_asc(A, B)
return sorttext("[B]","[A]")
-/proc/cmp_pdaname_asc(obj/item/pda/A, obj/item/pda/B)
- return sorttext(B.owner, A.owner)
+/proc/cmp_pdaname_asc(obj/item/modular_computer/A, obj/item/modular_computer/B)
+ return sorttext(B?.saved_identification, A?.saved_identification)
-/proc/cmp_pdajob_asc(obj/item/pda/A, obj/item/pda/B)
- return sorttext(B.ownjob, A.ownjob)
+/proc/cmp_pdajob_asc(obj/item/modular_computer/A, obj/item/modular_computer/B)
+ return sorttext(B?.saved_job, A?.saved_job)
/proc/cmp_num_string_asc(A, B)
return text2num(A) - text2num(B)
diff --git a/code/_globalvars/phobias.dm b/code/_globalvars/phobias.dm
index 64afd556a2a..b137ba3779a 100644
--- a/code/_globalvars/phobias.dm
+++ b/code/_globalvars/phobias.dm
@@ -139,7 +139,7 @@ GLOBAL_LIST_INIT(phobia_objs, list(
/obj/item/gun/magic/staff/honk,
/obj/item/instrument/bikehorn,
/obj/item/megaphone/clown,
- /obj/item/pda/clown,
+ /obj/item/modular_computer/tablet/pda/clown,
/obj/item/pneumatic_cannon/pie,
/obj/item/stack/ore/bananium,
/obj/item/stack/tile/mineral/bananium,
diff --git a/code/_onclick/hud/ai.dm b/code/_onclick/hud/ai.dm
index 1713a857058..fabbdae41ab 100644
--- a/code/_onclick/hud/ai.dm
+++ b/code/_onclick/hud/ai.dm
@@ -48,6 +48,17 @@
var/mob/living/silicon/ai/AI = usr
AI.toggle_camera_light()
+/atom/movable/screen/ai/modpc
+ name = "Messenger"
+ icon_state = "pda_send"
+ var/mob/living/silicon/ai/robot
+
+/atom/movable/screen/ai/modpc/Click()
+ . = ..()
+ if(.)
+ return
+ robot.modularInterface?.interact(robot)
+
/atom/movable/screen/ai/crew_monitor
name = "Crew Monitoring Console"
icon_state = "crew_monitor"
@@ -108,26 +119,6 @@
var/mob/living/silicon/ai/AI = usr
AI.checklaws()
-/atom/movable/screen/ai/pda_msg_send
- name = "PDA - Send Message"
- icon_state = "pda_send"
-
-/atom/movable/screen/ai/pda_msg_send/Click()
- if(..())
- return
- var/mob/living/silicon/ai/AI = usr
- AI.cmd_send_pdamesg(usr)
-
-/atom/movable/screen/ai/pda_msg_show
- name = "PDA - Show Message Log"
- icon_state = "pda_receive"
-
-/atom/movable/screen/ai/pda_msg_show/Click()
- if(..())
- return
- var/mob/living/silicon/ai/AI = usr
- AI.cmd_show_message_log(usr)
-
/atom/movable/screen/ai/image_take
name = "Take Image"
icon_state = "take_picture"
@@ -190,6 +181,7 @@
/datum/hud/ai/New(mob/owner)
..()
var/atom/movable/screen/using
+ var/mob/living/silicon/ai/myai = mymob
// Language menu
using = new /atom/movable/screen/language_menu
@@ -257,17 +249,14 @@
using.hud = src
static_inventory += using
-//PDA message
- using = new /atom/movable/screen/ai/pda_msg_send()
- using.screen_loc = ui_ai_pda_send
- using.hud = src
- static_inventory += using
-
-//PDA log
- using = new /atom/movable/screen/ai/pda_msg_show()
- using.screen_loc = ui_ai_pda_log
+// Modular Interface
+ using = new /atom/movable/screen/ai/modpc()
+ using.screen_loc = ui_ai_mod_int
using.hud = src
static_inventory += using
+ myai.interfaceButton = using
+ var/atom/movable/screen/ai/modpc/tabletbutton = using
+ tabletbutton.robot = myai
//Take image
using = new /atom/movable/screen/ai/image_take()
diff --git a/code/_onclick/hud/pai.dm b/code/_onclick/hud/pai.dm
index 069a5e093d7..fdd97191f36 100644
--- a/code/_onclick/hud/pai.dm
+++ b/code/_onclick/hud/pai.dm
@@ -119,27 +119,16 @@
var/mob/living/silicon/pai/pAI = usr
pAI.checklaws()
-/atom/movable/screen/pai/pda_msg_send
- name = "PDA - Send Message"
+/atom/movable/screen/pai/modpc
+ name = "Messenger"
icon_state = "pda_send"
- required_software = "digital messenger"
+ var/mob/living/silicon/pai/pAI
-/atom/movable/screen/pai/pda_msg_send/Click()
- if(!..())
+/atom/movable/screen/pai/modpc/Click()
+ . = ..()
+ if(!.) // this works for some reason.
return
- var/mob/living/silicon/pai/pAI = usr
- pAI.cmd_send_pdamesg(usr)
-
-/atom/movable/screen/pai/pda_msg_show
- name = "PDA - Show Message Log"
- icon_state = "pda_receive"
- required_software = "digital messenger"
-
-/atom/movable/screen/pai/pda_msg_show/Click()
- if(!..())
- return
- var/mob/living/silicon/pai/pAI = usr
- pAI.cmd_show_message_log(usr)
+ pAI.modularInterface?.interact(pAI)
/atom/movable/screen/pai/internal_gps
name = "Internal GPS"
@@ -191,6 +180,7 @@
/datum/hud/pai/New(mob/living/silicon/pai/owner)
..()
var/atom/movable/screen/using
+ var/mob/living/silicon/pai/mypai = mymob
// Software menu
using = new /atom/movable/screen/pai/software
@@ -247,15 +237,13 @@
using.screen_loc = ui_pai_state_laws
static_inventory += using
-// PDA message
- using = new /atom/movable/screen/pai/pda_msg_send()
- using.screen_loc = ui_pai_pda_send
- static_inventory += using
-
-// PDA log
- using = new /atom/movable/screen/pai/pda_msg_show()
- using.screen_loc = ui_pai_pda_log
+// Modular Interface
+ using = new /atom/movable/screen/pai/modpc()
+ using.screen_loc = ui_pai_mod_int
static_inventory += using
+ mypai.interfaceButton = using
+ var/atom/movable/screen/pai/modpc/tabletbutton = using
+ tabletbutton.pAI = mypai
// Internal GPS
using = new /atom/movable/screen/pai/internal_gps()
diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm
index c3c16368f45..89ece9204f4 100644
--- a/code/_onclick/hud/robot.dm
+++ b/code/_onclick/hud/robot.dm
@@ -130,14 +130,14 @@
static_inventory += using
//Borg Integrated Tablet
- using = new /atom/movable/screen/robot/modPC()
+ using = new /atom/movable/screen/robot/modpc()
using.screen_loc = ui_borg_tablet
using.hud = src
static_inventory += using
robit.interfaceButton = using
if(robit.modularInterface)
using.vis_contents += robit.modularInterface
- var/atom/movable/screen/robot/modPC/tabletbutton = using
+ var/atom/movable/screen/robot/modpc/tabletbutton = using
tabletbutton.robot = robit
//Alerts
@@ -182,21 +182,6 @@
zone_select.update_appearance()
static_inventory += zone_select
-// SKYRAT EDIT ADDITION BEGIN: Cyborg PDA
-//PDA message
- using = new /atom/movable/screen/robot/pda_msg_send
- using.screen_loc = ui_borg_pda_send
- using.hud = src
- static_inventory += using
-
-//PDA log
- using = new /atom/movable/screen/robot/pda_msg_show
- using.screen_loc = ui_borg_pda_log
- using.hud = src
- static_inventory += using
-// SKYRAT EDIT ADDITION END
-
-
/datum/hud/proc/toggle_show_robot_modules()
if(!iscyborg(mymob))
return
@@ -311,18 +296,18 @@
robot = null
return ..()
-/atom/movable/screen/robot/modPC
+/atom/movable/screen/robot/modpc
name = "Modular Interface"
icon_state = "template"
var/mob/living/silicon/robot/robot
-/atom/movable/screen/robot/modPC/Click()
+/atom/movable/screen/robot/modpc/Click()
. = ..()
if(.)
return
robot.modularInterface?.interact(robot)
-/atom/movable/screen/robot/modPC/Destroy()
+/atom/movable/screen/robot/modpc/Destroy()
if(robot)
robot.interfaceButton = null
robot = null
diff --git a/code/controllers/subsystem/id_access.dm b/code/controllers/subsystem/id_access.dm
index 4fd15a9ba5c..22787a7e35f 100644
--- a/code/controllers/subsystem/id_access.dm
+++ b/code/controllers/subsystem/id_access.dm
@@ -220,7 +220,7 @@ SUBSYSTEM_DEF(id_access)
var/datum/id_trim/trim = trim_singletons_by_path[trim_path]
centcom_job_templates[trim_path] = trim.assignment
- var/list/all_pda_paths = typesof(/obj/item/pda)
+ var/list/all_pda_paths = typesof(/obj/item/modular_computer/tablet/pda)
var/list/pda_regions = PDA_PAINTING_REGIONS
for(var/pda_path in all_pda_paths)
if(!(pda_path in pda_regions))
@@ -234,7 +234,7 @@ SUBSYSTEM_DEF(id_access)
if(!(whitelisted_region in manager_regions))
continue
var/list/manager_pdas = manager_info["pdas"]
- var/obj/item/pda/fake_pda = pda_path
+ var/obj/item/modular_computer/tablet/pda/fake_pda = pda_path
manager_pdas[pda_path] = initial(fake_pda.name)
station_pda_templates[pda_path] = initial(fake_pda.name)
diff --git a/code/controllers/subsystem/wardrobe.dm b/code/controllers/subsystem/wardrobe.dm
index 55ab24c3d69..e255b66223f 100644
--- a/code/controllers/subsystem/wardrobe.dm
+++ b/code/controllers/subsystem/wardrobe.dm
@@ -43,7 +43,6 @@ SUBSYSTEM_DEF(wardrobe)
setup_callbacks()
load_outfits()
load_species()
- load_pda_nicknacks()
load_storage_contents()
hard_refresh_queue()
stock_hit = 0
@@ -304,9 +303,6 @@ SUBSYSTEM_DEF(wardrobe)
/// Mind this
/datum/controller/subsystem/wardrobe/proc/setup_callbacks()
var/list/play_with = new /list(WARDROBE_CALLBACK_REMOVE) // Turns out there's a global list of pdas. Let's work around that yeah?
- play_with[WARDROBE_CALLBACK_INSERT] = CALLBACK(null, /obj/item/pda/proc/display_pda)
- play_with[WARDROBE_CALLBACK_REMOVE] = CALLBACK(null, /obj/item/pda/proc/cloak_pda)
- initial_callbacks[/obj/item/pda] = play_with
play_with = new /list(WARDROBE_CALLBACK_REMOVE) // Don't want organs rotting on the job
play_with[WARDROBE_CALLBACK_INSERT] = CALLBACK(null, /obj/item/organ/proc/enter_wardrobe)
@@ -336,19 +332,11 @@ SUBSYSTEM_DEF(wardrobe)
canonize_type(species_request)
CHECK_TICK
-/datum/controller/subsystem/wardrobe/proc/load_pda_nicknacks()
- for(var/obj/item/pda/pager as anything in typesof(/obj/item/pda))
- var/obj/item/pda/flip_phone = new pager()
- for(var/datum/outfit_item_type as anything in flip_phone.get_types_to_preload())
- canonize_type(outfit_item_type)
- qdel(flip_phone)
- CHECK_TICK
-
/datum/controller/subsystem/wardrobe/proc/load_storage_contents()
for(var/obj/item/storage/crate as anything in subtypesof(/obj/item/storage))
if(!initial(crate.preload))
continue
- var/obj/item/pda/another_crate = new crate()
+ var/obj/item/storage/another_crate = new crate()
//Unlike other uses, I really don't want people being lazy with this one.
var/list/somehow_more_boxes = another_crate.get_types_to_preload()
if(!length(somehow_more_boxes))
diff --git a/code/datums/action.dm b/code/datums/action.dm
index 4366534e734..d7afe1b3aef 100644
--- a/code/datums/action.dm
+++ b/code/datums/action.dm
@@ -240,9 +240,9 @@
name = "Toggle Light"
/datum/action/item_action/toggle_light/Trigger(trigger_flags)
- if(istype(target, /obj/item/pda))
- var/obj/item/pda/P = target
- P.toggle_light(owner)
+ if(istype(target, /obj/item/modular_computer))
+ var/obj/item/modular_computer/mc = target
+ mc.toggle_flashlight()
return
..()
diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm
index 1e24cb536be..60b50f7cb34 100644
--- a/code/datums/components/uplink.dm
+++ b/code/datums/components/uplink.dm
@@ -58,9 +58,9 @@
RegisterSignal(parent, COMSIG_IMPLANT_IMPLANTING, .proc/implanting)
RegisterSignal(parent, COMSIG_IMPLANT_OTHER, .proc/old_implant)
RegisterSignal(parent, COMSIG_IMPLANT_EXISTING_UPLINK, .proc/new_implant)
- else if(istype(parent, /obj/item/pda))
- RegisterSignal(parent, COMSIG_PDA_CHANGE_RINGTONE, .proc/new_ringtone)
- RegisterSignal(parent, COMSIG_PDA_CHECK_DETONATE, .proc/check_detonate)
+ else if(istype(parent, /obj/item/modular_computer/tablet))
+ RegisterSignal(parent, COMSIG_TABLET_CHANGE_ID, .proc/new_ringtone)
+ RegisterSignal(parent, COMSIG_TABLET_CHECK_DETONATE, .proc/check_detonate)
else if(istype(parent, /obj/item/radio))
RegisterSignal(parent, COMSIG_RADIO_NEW_FREQUENCY, .proc/new_frequency)
else if(istype(parent, /obj/item/pen))
@@ -329,23 +329,21 @@
/datum/component/uplink/proc/new_ringtone(datum/source, mob/living/user, new_ring_text)
SIGNAL_HANDLER
- var/obj/item/pda/master = parent
if(trim(lowertext(new_ring_text)) != trim(lowertext(unlock_code)))
if(trim(lowertext(new_ring_text)) == trim(lowertext(failsafe_code)))
failsafe(user)
return COMPONENT_STOP_RINGTONE_CHANGE
+ to_chat(user, span_notice("Unlock failure."))
return
locked = FALSE
interact(null, user)
- to_chat(user, span_hear("The PDA softly beeps."))
- user << browse(null, "window=pda")
- master.ui_mode = PDA_UI_HUB
+ to_chat(user, span_hear("The computer softly beeps."))
return COMPONENT_STOP_RINGTONE_CHANGE
/datum/component/uplink/proc/check_detonate()
SIGNAL_HANDLER
- return COMPONENT_PDA_NO_DETONATE
+ return COMPONENT_TABLET_NO_DETONATE
// Radio signal responses
@@ -385,7 +383,7 @@
/datum/component/uplink/proc/setup_unlock_code()
unlock_code = generate_code()
var/obj/item/P = parent
- if(istype(parent,/obj/item/pda))
+ if(istype(parent,/obj/item/modular_computer/tablet))
unlock_note = "Uplink Passcode: [unlock_code] ([P.name])."
else if(istype(parent,/obj/item/radio))
unlock_note = "Radio Frequency: [format_frequency(unlock_code)] ([P.name])."
@@ -393,7 +391,7 @@
unlock_note = "Uplink Degrees: [english_list(unlock_code)] ([P.name])."
/datum/component/uplink/proc/generate_code()
- if(istype(parent,/obj/item/pda))
+ if(istype(parent,/obj/item/modular_computer/tablet))
return "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
else if(istype(parent,/obj/item/radio))
return return_unused_frequency()
diff --git a/code/datums/greyscale/config_types/greyscale_configs.dm b/code/datums/greyscale/config_types/greyscale_configs.dm
index b0121b3463a..830626cfc4a 100644
--- a/code/datums/greyscale/config_types/greyscale_configs.dm
+++ b/code/datums/greyscale/config_types/greyscale_configs.dm
@@ -107,40 +107,40 @@
icon_file = 'icons/mob/inhands/clothing_righthand.dmi'
json_config = 'code/datums/greyscale/json_configs/jumpsuit_prison_inhand.json'
-/datum/greyscale_config/pda
+/datum/greyscale_config/tablet
name = "PDA"
- icon_file = 'icons/obj/pda.dmi'
+ icon_file = 'icons/obj/modular_tablet.dmi'
json_config = 'code/datums/greyscale/json_configs/pda.json'
-/datum/greyscale_config/pda/chaplain
+/datum/greyscale_config/tablet/chaplain
name = "Chaplain PDA"
json_config = 'code/datums/greyscale/json_configs/pda_chaplain.json'
-/datum/greyscale_config/pda/captain
+/datum/greyscale_config/tablet/captain
name = "Captain PDA"
json_config = 'code/datums/greyscale/json_configs/pda_captain.json'
-/datum/greyscale_config/pda/clown
+/datum/greyscale_config/tablet/clown
name = "Clown PDA"
json_config = 'code/datums/greyscale/json_configs/pda_clown.json'
-/datum/greyscale_config/pda/head
+/datum/greyscale_config/tablet/head
name = "Head PDA"
json_config = 'code/datums/greyscale/json_configs/pda_head.json'
-/datum/greyscale_config/pda/mime
+/datum/greyscale_config/tablet/mime
name = "Mime PDA"
json_config = 'code/datums/greyscale/json_configs/pda_mime.json'
-/datum/greyscale_config/pda/stripe_split
+/datum/greyscale_config/tablet/stripe_split
name = "Split Stripe PDA"
json_config = 'code/datums/greyscale/json_configs/pda_stripe_split.json'
-/datum/greyscale_config/pda/stripe_thick
+/datum/greyscale_config/tablet/stripe_thick
name = "Thick Stripe PDA"
json_config = 'code/datums/greyscale/json_configs/pda_stripe_thick.json'
-/datum/greyscale_config/pda/stripe_thick/head
+/datum/greyscale_config/tablet/stripe_thick/head
name = "Head Thick Stripe PDA"
json_config = 'code/datums/greyscale/json_configs/pda_stripe_thick_head.json'
diff --git a/code/datums/greyscale/json_configs/pda_clown.json b/code/datums/greyscale/json_configs/pda_clown.json
index 0d31131b2c8..e9be8922369 100644
--- a/code/datums/greyscale/json_configs/pda_clown.json
+++ b/code/datums/greyscale/json_configs/pda_clown.json
@@ -2,24 +2,7 @@
"pda": [
{
"type": "icon_state",
- "icon_state": "pda_base",
- "blend_mode": "overlay",
- "color_ids": [ 1 ]
- },
- {
- "type": "icon_state",
- "icon_state": "pda_stripe_clown",
- "blend_mode": "overlay"
- },
- {
- "type": "icon_state",
- "icon_state": "pda_buttons",
- "blend_mode": "overlay",
- "color_ids": [ 2 ]
- },
- {
- "type": "icon_state",
- "icon_state": "pda_screen_borders",
+ "icon_state": "pda-clown",
"blend_mode": "overlay"
}
]
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 023e03b538f..43d0566e274 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -387,7 +387,7 @@
return
var/list/all_contents = traitor_mob.get_all_contents()
- var/obj/item/pda/PDA = locate() in all_contents
+ var/obj/item/modular_computer/tablet/pda/PDA = locate() in all_contents
var/obj/item/radio/R = locate() in all_contents
var/obj/item/pen/P
@@ -440,7 +440,7 @@
if(uplink_loc == R)
unlock_text = "Your Uplink is cunningly disguised as your [R.name]. Simply dial the frequency [format_frequency(new_uplink.unlock_code)] to unlock its hidden features."
else if(uplink_loc == PDA)
- unlock_text = "Your Uplink is cunningly disguised as your [PDA.name]. Simply enter the code \"[new_uplink.unlock_code]\" into the ringtone select to unlock its hidden features."
+ unlock_text = "Your Uplink is cunningly disguised as your [PDA.name]. Simply enter the code \"[new_uplink.unlock_code]\" into the ring tone selection to unlock its hidden features."
else if(uplink_loc == P)
unlock_text = "Your Uplink is cunningly disguised as your [P.name]. Simply twist the top of the pen [english_list(new_uplink.unlock_code)] from its starting position to unlock its hidden features."
new_uplink.unlock_text = unlock_text
diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm
index dca34cb0768..cca8d6cf79f 100644
--- a/code/game/machinery/PDApainter.dm
+++ b/code/game/machinery/PDApainter.dm
@@ -1,6 +1,6 @@
/// Basic machine used to paint PDAs and re-trim ID cards.
/obj/machinery/pdapainter
- name = "\improper PDA & ID Painter"
+ name = "\improper Tablet & ID Painter"
desc = "A painting machine that can be used to paint PDAs and trim IDs. To use, simply insert the item and choose the desired preset."
icon = 'icons/obj/pda.dmi'
icon_state = "pdapainter"
@@ -10,16 +10,14 @@
/// Current ID card inserted into the machine.
var/obj/item/card/id/stored_id_card = null
/// Current PDA inserted into the machine.
- var/obj/item/pda/stored_pda = null
+ var/obj/item/modular_computer/tablet/pda/stored_pda = null
/// A blacklist of PDA types that we should not be able to paint.
var/static/list/pda_type_blacklist = list(
- /obj/item/pda/ai/pai,
- /obj/item/pda/ai,
- /obj/item/pda/heads,
- /obj/item/pda/clear,
- /obj/item/pda/syndicate,
- /obj/item/pda/chameleon,
- /obj/item/pda/chameleon/broken)
+ /obj/item/modular_computer/tablet/pda/heads,
+ /obj/item/modular_computer/tablet/pda/clear,
+ /obj/item/modular_computer/tablet/pda/syndicate,
+ /obj/item/modular_computer/tablet/pda/chameleon,
+ /obj/item/modular_computer/tablet/pda/chameleon/broken)
/// A list of the PDA types that this machine can currently paint.
var/list/pda_types = list()
/// A list of the card trims that this machine can currently imprint onto a card.
@@ -132,11 +130,7 @@
to_chat(user, span_warning("The machine rejects your [O]. This ID card does not appear to be compatible with the PDA Painter."))
return
- if(istype(O, /obj/item/pda/chameleon))
- to_chat(user, span_warning("The machine rejects your [O]. This PDA does not appear to be compatible with the PDA Painter."))
- return
-
- if(istype(O, /obj/item/pda))
+ if(istype(O, /obj/item/modular_computer/tablet/pda))
insert_pda(O, user)
return
@@ -177,7 +171,7 @@
* * new_pda - The PDA to insert.
* * user - The user to try and eject the PDA into the hands of.
*/
-/obj/machinery/pdapainter/proc/insert_pda(obj/item/pda/new_pda, mob/living/user)
+/obj/machinery/pdapainter/proc/insert_pda(obj/item/modular_computer/tablet/pda/new_pda, mob/living/user)
if(!istype(new_pda))
return FALSE
@@ -296,7 +290,7 @@
return TRUE
var/obj/item/held_item = usr.get_active_held_item()
- if(istype(held_item, /obj/item/pda))
+ if(istype(held_item, /obj/item/modular_computer/tablet/pda))
// If we successfully inserted, we've ejected the old item. Return early.
if(insert_pda(held_item, usr))
return TRUE
@@ -326,7 +320,7 @@
return TRUE
var/selection = params["selection"]
- var/obj/item/pda/pda_path = /obj/item/pda
+ var/obj/item/modular_computer/tablet/pda/pda_path = /obj/item/modular_computer/tablet/pda
for(var/path in pda_types)
if(pda_types[path] == selection)
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index c4f4add6c72..69a21cdf87d 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -326,7 +326,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0)
return
// OTHER
- if((istype(I, /obj/item/paper) || istype(I, /obj/item/pda)) && isliving(user))
+ if((istype(I, /obj/item/paper) || istype(I, /obj/item/modular_computer/tablet)) && isliving(user))
var/mob/living/paper_user = user
var/itemname = ""
@@ -335,10 +335,10 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0)
var/obj/item/paper/pressed_paper = I
itemname = pressed_paper.name
info = pressed_paper.info
- else
- var/obj/item/pda/pressed_pda = I
- itemname = pressed_pda.name
- info = pressed_pda.notehtml
+ if(istype(I, /obj/item/modular_computer/tablet))
+ var/obj/item/modular_computer/tablet/computer = I
+ itemname = computer.name
+ info = computer.note
itemname = sanitize(itemname)
to_chat(paper_user, span_notice("You hold \the [itemname] up to the camera..."))
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 519e2bb22d5..439c6015d54 100755
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -936,7 +936,6 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE)
#undef IMPORTANT_ACTION_COOLDOWN
#undef EMERGENCY_ACCESS_COOLDOWN
-#undef MAX_STATUS_LINE_LENGTH
#undef STATE_BUYING_SHUTTLE
#undef STATE_CHANGING_STATUS
#undef STATE_MAIN
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index dc74843076d..872f7b6ed05 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -897,14 +897,14 @@ What a mess.*/
if (!fine || QDELETED(usr) || QDELETED(src) || !canUseSecurityRecordsConsole(usr, t1, null, a2))
return
var/datum/data/crime/crime = GLOB.data_core.createCrimeEntry(t1, "", authenticated, station_time_timestamp(), fine)
- for (var/obj/item/pda/P in GLOB.PDAs)
- if(P.owner == active1.fields["name"])
+ for (var/obj/item/modular_computer/tablet in GLOB.TabletMessengers)
+ if(tablet.saved_identification == active1.fields["name"])
var/message = "You have been fined [fine] credits for '[t1]'. Fines may be paid at security."
- var/datum/signal/subspace/messaging/pda/signal = new(src, list(
+ var/datum/signal/subspace/messaging/tablet_msg/signal = new(src, list(
"name" = "Security Citation",
"job" = "Citation Server",
"message" = message,
- "targets" = list(STRINGIFY_PDA_TARGET(P.owner, P.ownjob)),
+ "targets" = list(tablet),
"automated" = TRUE
))
signal.send_to_receivers()
diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm
index a50ac2de09f..9162403cf5c 100644
--- a/code/game/machinery/navbeacon.dm
+++ b/code/game/machinery/navbeacon.dm
@@ -96,7 +96,7 @@
if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE)
return // prevent intraction when T-scanner revealed
- else if (istype(I, /obj/item/card/id)||istype(I, /obj/item/pda))
+ else if (istype(I, /obj/item/card/id) || istype(I, /obj/item/modular_computer/tablet))
if(open)
if (src.allowed(user))
src.locked = !src.locked
diff --git a/code/game/machinery/telecomms/computers/message.dm b/code/game/machinery/telecomms/computers/message.dm
index 96ce880a8ae..5f9cd39505a 100644
--- a/code/game/machinery/telecomms/computers/message.dm
+++ b/code/game/machinery/telecomms/computers/message.dm
@@ -33,11 +33,6 @@
var/message = "System bootup complete. Please select an option. " // The message that shows on the main menu.
var/auth = FALSE // Are they authenticated?
var/optioncount = 7
- // Custom Message Properties
- var/customsender = "System Administrator"
- var/obj/item/pda/customrecepient = null
- var/customjob = "Admin"
- var/custommessage = "This is a test, please ignore."
/obj/machinery/computer/message_monitor/screwdriver_act(mob/living/user, obj/item/I)
if(obj_flags & EMAGGED)
@@ -137,7 +132,7 @@
var/index = 0
dat += "
Back - Refresh "
dat += "X Sender Recipient Message "
- for(var/datum/data_pda_msg/pda in linkedServer.pda_msgs)
+ for(var/datum/data_tablet_msg/pda in linkedServer.pda_msgs)
index++
if(index > 3000)
break
@@ -188,24 +183,6 @@
10010000001110100011010000110000101110100001000000111010
001101001011011010110010100101110"}
- //Fake messages
- if(MSG_MON_SCREEN_CUSTOM_MSG)
- dat += "Back - Reset "
-
- dat += {"
- Sender
- Sender's Job
- Recipient
- Message "}
- //Sender - Sender's Job - Recepient - Message
- //Al Green- Your Dad - Your Mom - WHAT UP!?
-
- dat += {"[customsender]
- [customjob]
- [customrecepient ? customrecepient.owner : "NONE"]
- [custommessage] "}
- dat += "
Send "
-
//Request Console Logs
if(MSG_MON_SCREEN_REQUEST_LOGS)
@@ -249,12 +226,6 @@
/obj/machinery/computer/message_monitor/proc/UnmagConsole()
obj_flags &= ~EMAGGED
-/obj/machinery/computer/message_monitor/proc/ResetMessage()
- customsender = "System Administrator"
- customrecepient = null
- custommessage = "This is a test, please ignore."
- customjob = "Admin"
-
/obj/machinery/computer/message_monitor/Topic(href, href_list)
if(..())
return
@@ -350,7 +321,7 @@
if(screen == MSG_MON_SCREEN_LOGS)
if(LINKED_SERVER_NONRESPONSIVE)
message = noserver
- else //if(istype(href_list["delete_logs"], /datum/data_pda_msg))
+ else if(istype(href_list["delete_logs"], /datum/data_tablet_msg))
linkedServer.pda_msgs -= locate(href_list["delete_logs"]) in linkedServer.pda_msgs
message = span_notice("NOTICE: Log Deleted!")
//Delete the request console log.
@@ -359,71 +330,9 @@
if(screen == MSG_MON_SCREEN_REQUEST_LOGS)
if(LINKED_SERVER_NONRESPONSIVE)
message = noserver
- else //if(istype(href_list["delete_logs"], /datum/data_pda_msg))
+ else if(istype(href_list["delete_logs"], /datum/data_tablet_msg))
linkedServer.rc_msgs -= locate(href_list["delete_requests"]) in linkedServer.rc_msgs
message = span_notice("NOTICE: Log Deleted!")
- //Create a custom message
- if (href_list["msg"])
- if(LINKED_SERVER_NONRESPONSIVE)
- message = noserver
- else if(auth)
- screen = MSG_MON_SCREEN_CUSTOM_MSG
- //Fake messaging selection - KEY REQUIRED
- if (href_list["select"])
- if(LINKED_SERVER_NONRESPONSIVE)
- message = noserver
- screen = MSG_MON_SCREEN_MAIN
- else
- switch(href_list["select"])
-
- //Reset
- if("Reset")
- ResetMessage()
-
- //Select Your Name
- if("Sender")
- customsender = tgui_input_text(usr, "Please enter the sender's name.", "Sender") || customsender
-
- //Select Receiver
- if("Recepient")
- //Get out list of viable PDAs
- var/list/obj/item/pda/sendPDAs = get_viewable_pdas()
- if(GLOB.PDAs && length(GLOB.PDAs) > 0)
- customrecepient = tgui_input_list(usr, "Select a PDA from the list", "PDA Selection", sendPDAs)
- else
- customrecepient = null
-
- //Enter custom job
- if("RecJob")
- customjob = tgui_input_text(usr, "Please enter the sender's job.", "Job") || customjob
-
- //Enter message
- if("Message")
- custommessage = tgui_input_text(usr, "Please enter your message.", "Message") || custommessage
-
- //Send message
- if("Send")
- if(isnull(customsender) || customsender == "")
- customsender = "UNKNOWN"
-
- if(isnull(customrecepient))
- message = span_notice("NOTICE: No recepient selected!")
- return attack_hand(usr)
-
- if(isnull(custommessage) || custommessage == "")
- message = span_notice("NOTICE: No message entered!")
- return attack_hand(usr)
-
- var/datum/signal/subspace/messaging/pda/signal = new(src, list(
- "name" = "[customsender]",
- "job" = "[customjob]",
- "message" = custommessage,
- "targets" = list(STRINGIFY_PDA_TARGET(customrecepient.owner, customrecepient.ownjob))
- ))
- // this will log the signal and transmit it to the target
- linkedServer.receive_information(signal, null)
- usr.log_message("(PDA: [name] | [usr.real_name]) sent \"[custommessage]\" to [signal.format_target()]", LOG_PDA)
-
//Request Console Logs - KEY REQUIRED
if(href_list["view_requests"])
diff --git a/code/game/machinery/telecomms/machines/message_server.dm b/code/game/machinery/telecomms/machines/message_server.dm
index e188640677c..fbf385a9044 100644
--- a/code/game/machinery/telecomms/machines/message_server.dm
+++ b/code/game/machinery/telecomms/machines/message_server.dm
@@ -82,7 +82,8 @@
active_power_usage = 100
circuit = /obj/item/circuitboard/machine/telecomms/message_server
- var/list/datum/data_pda_msg/pda_msgs = list()
+ var/list/datum/data_tablet_msg/pda_msgs = list()
+ var/list/datum/data_tablet_msg/modular_msgs = list()
var/list/datum/data_rc_msg/rc_msgs = list()
var/decryptkey = "password"
var/calibrating = 15 MINUTES //Init reads this and adds world.time, then becomes 0 when that time has passed and the machine works
@@ -95,9 +96,9 @@
if (calibrating)
calibrating += world.time
say("Calibrating... Estimated wait time: [rand(3, 9)] minutes.")
- pda_msgs += new /datum/data_pda_msg("System Administrator", "system", "This is an automated message. System calibration started at [station_time_timestamp()]")
+ pda_msgs += new /datum/data_tablet_msg("System Administrator", "system", "This is an automated message. System calibration started at [station_time_timestamp()].")
else
- pda_msgs += new /datum/data_pda_msg("System Administrator", "system", MESSAGE_SERVER_FUNCTIONING_MESSAGE)
+ pda_msgs += new /datum/data_tablet_msg("System Administrator", "system", MESSAGE_SERVER_FUNCTIONING_MESSAGE)
/obj/machinery/telecomms/message_server/Destroy()
for(var/obj/machinery/computer/message_monitor/monitor in GLOB.telecomms_list)
@@ -121,7 +122,7 @@
. = ..()
if(calibrating && calibrating <= world.time)
calibrating = 0
- pda_msgs += new /datum/data_pda_msg("System Administrator", "system", MESSAGE_SERVER_FUNCTIONING_MESSAGE)
+ pda_msgs += new /datum/data_tablet_msg("System Administrator", "system", MESSAGE_SERVER_FUNCTIONING_MESSAGE)
/obj/machinery/telecomms/message_server/receive_information(datum/signal/subspace/messaging/signal, obj/machinery/telecomms/machine_from)
// can't log non-message signals
@@ -129,16 +130,16 @@
return
// log the signal
- if(istype(signal, /datum/signal/subspace/messaging/pda))
- var/datum/signal/subspace/messaging/pda/PDAsignal = signal
- var/datum/data_pda_msg/M = new(PDAsignal.format_target(), "[PDAsignal.data["name"]] ([PDAsignal.data["job"]])", PDAsignal.data["message"], PDAsignal.data["photo"])
- pda_msgs += M
- signal.logged = M
+ if(istype(signal, /datum/signal/subspace/messaging/tablet_msg))
+ var/datum/signal/subspace/messaging/tablet_msg/PDAsignal = signal
+ var/datum/data_tablet_msg/msg = new(PDAsignal.format_target(), "[PDAsignal.data["name"]] ([PDAsignal.data["job"]])", PDAsignal.data["message"], PDAsignal.data["photo"])
+ pda_msgs += msg
+ signal.logged = msg
else if(istype(signal, /datum/signal/subspace/messaging/rc))
- var/datum/data_rc_msg/M = new(signal.data["rec_dpt"], signal.data["send_dpt"], signal.data["message"], signal.data["stamped"], signal.data["verified"], signal.data["priority"])
- signal.logged = M
+ var/datum/data_rc_msg/msg = new(signal.data["rec_dpt"], signal.data["send_dpt"], signal.data["message"], signal.data["stamped"], signal.data["verified"], signal.data["priority"])
+ signal.logged = msg
if(signal.data["send_dpt"]) // don't log messages not from a department but allow them to work
- rc_msgs += M
+ rc_msgs += msg
signal.data["reject"] = FALSE
// pass it along to either the hub or the broadcaster
@@ -172,23 +173,23 @@
copy.levels = levels
return copy
-// PDA signal datum
-/datum/signal/subspace/messaging/pda/proc/format_target()
+// Tablet message signal datum
+/datum/signal/subspace/messaging/tablet_msg/proc/format_target()
if (length(data["targets"]) > 1)
return "Everyone"
- return data["targets"][1]
+ var/obj/item/modular_computer/target = data["targets"][1]
+ return "[target.saved_identification] ([target.saved_job])"
-/datum/signal/subspace/messaging/pda/proc/format_message()
- if (logged && data["photo"])
- return "\"[data["message"]]\" (Photo )"
+/datum/signal/subspace/messaging/tablet_msg/proc/format_message()
return "\"[data["message"]]\""
-/datum/signal/subspace/messaging/pda/broadcast()
+/datum/signal/subspace/messaging/tablet_msg/broadcast()
if (!logged) // Can only go through if a message server logs it
return
- for (var/obj/item/pda/P in GLOB.PDAs)
- if ("[P.owner] ([P.ownjob])" in data["targets"])
- P.receive_message(src)
+ for (var/obj/item/modular_computer/comp in data["targets"])
+ var/obj/item/computer_hardware/hard_drive/drive = comp.all_components[MC_HDD]
+ for(var/datum/computer_file/program/messenger/app in drive.stored_files)
+ app.receive_message(src)
// Request Console signal datum
/datum/signal/subspace/messaging/rc/broadcast()
@@ -200,14 +201,14 @@
Console.createmessage(data["sender"], data["send_dpt"], data["message"], data["verified"], data["stamped"], data["priority"], data["notify_freq"])
// Log datums stored by the message server.
-/datum/data_pda_msg
+/datum/data_tablet_msg
var/sender = "Unspecified"
var/recipient = "Unspecified"
var/message = "Blank" // transferred message
var/datum/picture/picture // attached photo
var/automated = 0 //automated message
-/datum/data_pda_msg/New(param_rec, param_sender, param_message, param_photo)
+/datum/data_tablet_msg/New(param_rec, param_sender, param_message, param_photo)
if(param_rec)
recipient = param_rec
if(param_sender)
@@ -217,7 +218,7 @@
if(param_photo)
picture = param_photo
-/datum/data_pda_msg/Topic(href,href_list)
+/datum/data_tablet_msg/Topic(href,href_list)
..()
if(href_list["photo"])
var/mob/M = usr
diff --git a/code/game/objects/effects/spawners/random/contraband.dm b/code/game/objects/effects/spawners/random/contraband.dm
index acda79a3abc..9b09568be52 100644
--- a/code/game/objects/effects/spawners/random/contraband.dm
+++ b/code/game/objects/effects/spawners/random/contraband.dm
@@ -55,7 +55,7 @@
/obj/item/restraints/handcuffs,
/obj/item/paper/fluff/jobs/prisoner/letter,
/obj/item/storage/wallet/random,
- /obj/item/pda,
+ /obj/item/modular_computer/tablet/pda,
/obj/item/radio/off,
)
diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm
index 611da8c1bca..4d35612caf4 100644
--- a/code/game/objects/items/cards_ids.dm
+++ b/code/game/objects/items/cards_ids.dm
@@ -914,7 +914,7 @@
/obj/item/card/id/advanced/Moved(atom/OldLoc, Dir)
. = ..()
- if(istype(OldLoc, /obj/item/pda) || istype(OldLoc, /obj/item/storage/wallet))
+ if(istype(OldLoc, /obj/item/storage/wallet))
UnregisterSignal(OldLoc, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED))
if(istype(OldLoc, /obj/item/computer_hardware/card_slot))
@@ -926,7 +926,7 @@
var/obj/item/modular_computer/tablet/slot_holder = slot.holder
UnregisterSignal(slot_holder, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED))
- if(istype(loc, /obj/item/pda) || istype(loc, /obj/item/storage/wallet))
+ if(istype(loc, /obj/item/storage/wallet))
RegisterSignal(loc, COMSIG_ITEM_EQUIPPED, .proc/update_intern_status)
RegisterSignal(loc, COMSIG_ITEM_DROPPED, .proc/remove_intern_status)
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
deleted file mode 100644
index ec21b85da23..00000000000
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ /dev/null
@@ -1,1311 +0,0 @@
-
-//The advanced pea-green monochrome lcd of tomorrow.
-
-GLOBAL_LIST_EMPTY(PDAs)
-
-#define PDA_SCANNER_NONE 0
-#define PDA_SCANNER_MEDICAL 1
-#define PDA_SCANNER_FORENSICS 2 //unused
-#define PDA_SCANNER_REAGENT 3
-#define PDA_SCANNER_GAS 5
-#define PDA_SPAM_DELAY 2 MINUTES
-
-/obj/item/pda//SKYRAT EDIT - ICON OVERRIDEN BY AESTHETICS - SEE MODULE
- name = "\improper standard PDA"
- desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by a preprogrammed ROM cartridge."
- icon = 'icons/obj/pda.dmi'
- icon_state = "pda"
- inhand_icon_state = "electronic"
- worn_icon_state = "pda"
- lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
- greyscale_config = /datum/greyscale_config/pda
- greyscale_colors = "#999875#a92323"
- item_flags = NOBLUDGEON
- w_class = WEIGHT_CLASS_TINY
- slot_flags = ITEM_SLOT_ID | ITEM_SLOT_BELT
- actions_types = list(/datum/action/item_action/toggle_light)
- armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, FIRE = 100, ACID = 100)
- resistance_flags = FIRE_PROOF | ACID_PROOF
- light_system = MOVABLE_LIGHT_DIRECTIONAL
- light_range = 2.3
- light_power = 0.6
- light_color = "#FFCC66"
- light_on = FALSE
- custom_materials = list(/datum/material/iron=300, /datum/material/glass=100, /datum/material/plastic=100)
-
- /// String name of owner
- var/owner = null
- /// Typepath of the default cartridge to use
- var/default_cartridge = 0
- /// Current cartridge
- var/obj/item/cartridge/cartridge = null
- /// Controls what menu the PDA will display. 0 is hub; the rest are either built in or based on cartridge.
- var/ui_mode = PDA_UI_HUB
- /// Icon to be overlayed for message alerts. Taken from the pda icon file.
- var/icon_alert = "pda-r"
- /// Icon to be overlayed when an active pAI is slotted in.
- var/icon_pai = "pai_overlay"
- /// Same as above but for an inactive pAI.
- var/icon_inactive_pai = "pai_off_overlay"
- /**
- * This int tells DM which font is currently selected and lets DM know when the last font has been selected
- * so that it can cycle back to the first font when "toggle font" is pressed again.
- */
- var/font_index = 0
- /// The currently selected font.
- var/font_mode = "font-family:monospace;"
- /// The currently selected background color.
- var/background_color = "#808000"
-
- #define FONT_MONO "font-family:monospace;"
- #define FONT_SHARE "font-family:\"Share Tech Mono\", monospace;letter-spacing:0px;"
- #define FONT_ORBITRON "font-family:\"Orbitron\", monospace;letter-spacing:0px; font-size:15px"
- #define FONT_VT "font-family:\"VT323\", monospace;letter-spacing:1px;"
- #define MODE_MONO 0
- #define MODE_SHARE 1
- #define MODE_ORBITRON 2
- #define MODE_VT 3
-
- //Secondary variables
- var/scanmode = PDA_SCANNER_NONE
- var/silent = FALSE //To beep or not to beep, that is the question
- var/toff = FALSE //If TRUE, messenger disabled
- var/tnote = null //Current Texts
- var/last_text //No text spamming
- var/last_everyone //No text for everyone spamming
- var/last_noise //Also no honk spamming that's bad too
- var/ttone = "beep" //The ringtone!
- var/honkamt = 0 //How many honks left when infected with honk.exe
- var/mimeamt = 0 //How many silence left when infected with mime.exe
- var/note = "Congratulations, your station has chosen the Thinktronic 5230 Personal Data Assistant!" //Current note in the notepad function
- var/notehtml = ""
- var/notescanned = FALSE // True if what is in the notekeeper was from a paper.
- var/hidden = FALSE // Is the PDA hidden from the PDA list?
- var/emped = FALSE
- var/equipped = FALSE //used here to determine if this is the first time its been picked up
- var/allow_emojis = FALSE //if the pda can send emojis and actually have them parsed as such
- var/sort_by_job = FALSE // If this is TRUE, will sort PDA list by job.
-
- var/obj/item/card/id/id = null //Making it possible to slot an ID card into the PDA so it can function as both.
- var/ownjob = null //related to above
- ///account id of the ID held
- var/account_id
-
- var/obj/item/paicard/pai = null // A slot for a personal AI device
-
- var/datum/picture/picture //Scanned photo
-
- var/list/contained_item = list(/obj/item/pen, /obj/item/toy/crayon, /obj/item/lipstick, /obj/item/flashlight/pen, /obj/item/clothing/mask/cigarette)
- //This is the typepath to load "into" the pda
- var/obj/item/insert_type = /obj/item/pen
- //This is the currently inserted item
- var/obj/item/inserted_item
- var/underline_flag = TRUE //flag for underline
-
-/obj/item/pda/suicide_act(mob/living/carbon/user)
- var/deathMessage = msg_input(user)
- if (!deathMessage)
- deathMessage = "i ded"
- user.visible_message(span_suicide("[user] is sending a message to the Grim Reaper! It looks like [user.p_theyre()] trying to commit suicide!"))
- tnote += "→ To The Grim Reaper: [deathMessage] "//records a message in their PDA as being sent to the grim reaper
- return BRUTELOSS
-
-/obj/item/pda/examine(mob/user)
- . = ..()
- if(!id && !inserted_item)
- return
-
- if(id)
- . += span_notice("Alt-click to remove the ID.") //won't name ID on examine in case it's stolen
-
- if(inserted_item && (!isturf(loc)))
- . += span_notice("Ctrl-click to remove [inserted_item].") //traitor pens are disguised so we're fine naming them on examine
-
- if((!isnull(cartridge)))
- . += span_notice("Ctrl+Shift-click to remove the cartridge.") //won't name cart on examine in case it's Detomatix
-
-/obj/item/pda/Initialize(mapload)
- . = ..()
-
- GLOB.PDAs += src
- if(default_cartridge)
- cartridge = SSwardrobe.provide_type(default_cartridge, src)
- cartridge.host_pda = src
- if(insert_type)
- inserted_item = SSwardrobe.provide_type(insert_type, src)
- RegisterSignal(src, COMSIG_LIGHT_EATER_ACT, .proc/on_light_eater)
-
- update_appearance()
-
-/obj/item/pda/Destroy()
- GLOB.PDAs -= src
- if(istype(id))
- QDEL_NULL(id)
- if(istype(cartridge))
- QDEL_NULL(cartridge)
- if(istype(pai))
- QDEL_NULL(pai)
- if(istype(inserted_item))
- QDEL_NULL(inserted_item)
- return ..()
-
-/obj/item/pda/equipped(mob/user, slot)
- . = ..()
- if(!equipped)
- if(user.client)
- //SKYRAT EDIT ADDITION BEGIN - Per-character PDA settings
- ttone = sanitize(trim(user.client.prefs.read_preference(/datum/preference/text/pda_ringer), 20))
- //SKYRAT EDIT ADDITION END
- background_color = user.client.prefs.read_preference(/datum/preference/color/pda_color)
- switch(user.client.prefs.read_preference(/datum/preference/choiced/pda_style))
- if(MONO)
- font_index = MODE_MONO
- font_mode = FONT_MONO
- if(SHARE)
- font_index = MODE_SHARE
- font_mode = FONT_SHARE
- if(ORBITRON)
- font_index = MODE_ORBITRON
- font_mode = FONT_ORBITRON
- if(VT)
- font_index = MODE_VT
- font_mode = FONT_VT
- else
- font_index = MODE_MONO
- font_mode = FONT_MONO
- equipped = TRUE
-
-/obj/item/pda/Exited(atom/movable/gone, direction)
- . = ..()
- if(gone == cartridge)
- cartridge.host_pda = null
- cartridge = null
- if(gone == inserted_item)
- inserted_item = null
-
-/obj/item/pda/proc/update_label()
- name = "PDA-[owner] ([ownjob])" //Name generalisation
-
-/obj/item/pda/GetAccess()
- if(id)
- return id.GetAccess()
- else
- return ..()
-
-/obj/item/pda/get_id_examine_strings(mob/user)
- . = ..()
- if(id)
- . += "\The [src] is displaying [id]."
- . += id.get_id_examine_strings(user)
-
-/obj/item/pda/GetID()
- return id
-
-/obj/item/pda/RemoveID()
- return do_remove_id()
-
-/obj/item/pda/InsertID(obj/item/inserting_item)
- var/obj/item/card/inserting_id = inserting_item.RemoveID()
- if(!inserting_id)
- return
- insert_id(inserting_id)
- if(id == inserting_id)
- return TRUE
- return FALSE
-
-/obj/item/pda/update_overlays()
- . = ..()
- var/init_icon = initial(icon)
- if(!init_icon)
- return
- if(id)
- . += mutable_appearance(init_icon, "id_overlay")
- if(inserted_item)
- . += mutable_appearance(init_icon, "insert_overlay")
- if(light_on)
- . += mutable_appearance(init_icon, "light_overlay")
- if(pai)
- if(pai.pai)
- . += mutable_appearance(init_icon, icon_pai)
- else
- . += mutable_appearance(init_icon, icon_inactive_pai)
-
-/obj/item/pda/MouseDrop(mob/over, src_location, over_location)
- var/mob/M = usr
- if((M == over) && usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
- return attack_self(M)
- return ..()
-
-
-/obj/item/pda/attack_self_tk(mob/user)
- to_chat(user, span_warning("The PDA's capacitive touch screen doesn't seem to respond!"))
- return COMPONENT_CANCEL_ATTACK_CHAIN
-
-
-/obj/item/pda/interact(mob/user)
- if(!ISADVANCEDTOOLUSER(user))
- to_chat(user, span_warning("You don't have the dexterity to do this!"))
- return
-
- if(HAS_TRAIT(src, TRAIT_PDA_MESSAGE_MENU_RIGGED) && ui_mode == PDA_UI_MESSENGER)
- explode(user, from_message_menu = TRUE)
- return
-
- ..()
-
- var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/simple/pda)
- assets.send(user)
-
- var/datum/asset/spritesheet/emoji_s = get_asset_datum(/datum/asset/spritesheet/chat)
- emoji_s.send(user) //Already sent by chat but no harm doing this
-
- user.set_machine(src)
-
- var/dat = "Personal Data Assistant "
- dat += assets.css_tag()
- dat += emoji_s.css_tag()
-
- dat += "[PDAIMG(refresh)]Refresh "
-
- if ((!isnull(cartridge)) && ui_mode == PDA_UI_HUB)
- dat += " | [PDAIMG(eject)]Eject [cartridge] "
- if (ui_mode != PDA_UI_HUB)
- dat += " | [PDAIMG(menu)]Return "
-
- else
- dat += ""
-
- dat += " "
-
- if (!owner)
- dat += "Warning: No owner information entered. Please swipe card. "
- dat += "[PDAIMG(refresh)]Retry "
- else
- switch (ui_mode)
- if (PDA_UI_HUB)
- dat += "PERSONAL DATA ASSISTANT v.1.2 "
- dat += "Owner: [owner], [ownjob] "
- dat += text("ID: [id ? "[id.registered_name], [id.assignment]" : "----------"]")
- dat += text(" [id ? "Update PDA Info" : ""] ")
-
- dat += "[station_time_timestamp()] " //:[world.time / 100 % 6][world.time / 100 % 10]"
- dat += "[time2text(world.realtime, "MMM DD")] [GLOB.year_integer+540] "
- dat += "It has been [ROUND_TIME] since the emergency shuttle was last called."
-
-
- dat += " "
-
- dat += "General Functions "
- dat += ""
- if (cartridge.access & CART_ENGINE)
- dat += "Engineering Functions "
- dat += ""
- if (cartridge.access & CART_MEDICAL)
- dat += "Medical Functions "
- dat += ""
- if (cartridge.access & CART_SECURITY)
- dat += "Security Functions "
- dat += ""
- if(cartridge.access & CART_QUARTERMASTER)
- dat += "Quartermaster Functions: "
- dat += ""
- dat += ""
-
- dat += "Utilities "
- dat += ""
-
- if (PDA_UI_NOTEKEEPER)
- dat += "[PDAIMG(notes)] Notekeeper V2.2 "
- dat += "Edit "
- if(notescanned)
- dat += "(This is a scanned image, editing it may cause some text formatting to change.) "
- dat += "[(!notehtml ? note : notehtml)] "
-
- if (PDA_UI_MESSENGER)
- dat += "[PDAIMG(mail)] SpaceMessenger V3.9.6 "
- dat += "[PDAIMG(bell)]Ringer: [silent == 1 ? "Off" : "On"] | "
- dat += "[PDAIMG(mail)]Send / Receive: [toff == 1 ? "Off" : "On"] | "
- dat += "[PDAIMG(bell)]Set Ringtone | "
- dat += "[PDAIMG(mail)]Messages "
- dat += "Sorted by: [sort_by_job ? "Job" : "Name"] "
-
- if(cartridge)
- dat += cartridge.message_header()
-
- dat += "[PDAIMG(menu)] Detected PDAs "
-
- dat += ""
- var/count = 0
-
- if (!toff)
- for (var/obj/item/pda/P in get_viewable_pdas(sort_by_job))
- if (P == src)
- continue
- dat += "[P.owner] ([P.ownjob]) "
- if(cartridge)
- dat += cartridge.message_special(P)
- dat += " "
- count++
- dat += " "
- if (count == 0)
- dat += "None detected. "
- else if(cartridge?.spam_enabled)
- dat += "Send To All "
- if(PDA_UI_SKILL_TRACKER)
- dat += "[PDAIMG(mail)] ExperTrak® Skill Tracker V4.26.2 "
- dat += "Thank you for choosing ExperTrak® brand software! ExperTrak® inc. is proud to be a Nanotrasen employee expertise and effectiveness department subsidary! "
- dat += " This software is designed to track and monitor your skill development as a Nanotrasen employee. Your job performance across different fields has been quantified and categorized below. "
- var/datum/mind/targetmind = user.mind
- if(targetmind)
- for (var/type in GLOB.skill_types)
- var/datum/skill/S = GetSkillRef(type)
- var/lvl_num = targetmind.get_skill_level(type)
- var/lvl_name = uppertext(targetmind.get_skill_level_name(type))
- var/exp = targetmind.get_skill_exp(type)
- var/xp_prog_to_level = targetmind.exp_needed_to_level_up(type)
- var/xp_req_to_level = 0
- if (xp_prog_to_level && lvl_num < length(SKILL_EXP_LIST)) // is it even possible to level up?
- xp_req_to_level = SKILL_EXP_LIST[lvl_num+1] - SKILL_EXP_LIST[lvl_num]
- dat += "[S.name] "
- dat += "[S.desc] "
- dat += "EMPLOYEE SKILL LEVEL: [lvl_name] "
- if (exp && xp_req_to_level)
- var/progress_percent = (xp_req_to_level-xp_prog_to_level)/xp_req_to_level
- var/overall_percent = exp / SKILL_EXP_LIST[length(SKILL_EXP_LIST)]
- dat += " PROGRESS TO NEXT SKILL LEVEL:"
- dat += " " + num2loadingbar(progress_percent) + "([progress_percent*100])%"
- dat += " OVERALL DEVELOPMENT PROGRESS:"
- dat += " " + num2loadingbar(overall_percent) + "([overall_percent*100])%"
- if (lvl_num >= length(SKILL_EXP_LIST) && !(type in targetmind.skills_rewarded))
- dat += "Contact the Professional [S.title] Association "
- dat += " "
- if(PDA_UI_READ_MESSAGES)
- if(icon_alert && !istext(icon_alert))
- cut_overlay(icon_alert)
- icon_alert = initial(icon_alert)
-
- dat += "[PDAIMG(mail)] SpaceMessenger V3.9.6 "
- dat += "[PDAIMG(blank)]Clear Messages "
-
- dat += "[PDAIMG(mail)] Messages "
-
- dat += tnote
- dat += " "
-
- if (PDA_UI_ATMOS_SCAN)
- dat += "[PDAIMG(atmos)] Atmospheric Readings "
-
- var/turf/T = user.loc
- if (isnull(T))
- dat += "Unable to obtain a reading. "
- else
- var/datum/gas_mixture/environment = T.return_air()
- var/list/env_gases = environment.gases
-
- var/pressure = environment.return_pressure()
- var/total_moles = environment.total_moles()
-
- dat += "Air Pressure: [round(pressure,0.1)] kPa "
-
- if (total_moles)
- for(var/id in env_gases)
- var/gas_level = env_gases[id][MOLES]/total_moles
- if(gas_level > 0)
- dat += "[env_gases[id][GAS_META][META_GAS_NAME]]: [round(gas_level*100, 0.01)]% "
-
- dat += "Temperature: [round(environment.temperature-T0C)]°C "
- dat += " "
-
- if(41) //crew manifest - SKYRAT EDIT ADD - PUBLIC MANIFEST
- dat += "[PDAIMG(notes)] Crew Manifest "
- dat += "[GLOB.data_core.get_manifest_html(monochrome=TRUE)] " // SKYRAT EDIT ADD END
- else//Else it links to the cart menu proc. Although, it really uses menu hub 4--menu 4 doesn't really exist as it simply redirects to hub.
- dat += cartridge.generate_menu()
-
- dat += ""
-
- if (underline_flag)
- dat = replacetext(dat, "text-decoration:none", "text-decoration:underline")
- if (!underline_flag)
- dat = replacetext(dat, "text-decoration:underline", "text-decoration:none")
-
- user << browse(dat, "window=pda;size=400x450;border=1;can_resize=1;can_minimize=0")
- onclose(user, "pda", src)
-
-/obj/item/pda/Topic(href, href_list)
- ..()
- var/mob/living/U = usr
- //Looking for master was kind of pointless since PDAs don't appear to have one.
-
- if(!href_list["close"] && usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
- add_fingerprint(U)
- U.set_machine(src)
-
- var/choice = text2num(href_list["choice"]) || href_list["choice"]
- switch(choice)
-
-//BASIC FUNCTIONS===================================
-
- if("Refresh")//Refresh, goes to the end of the proc.
- if(!silent)
- playsound(src, 'sound/machines/terminal_select.ogg', 15, TRUE)
-
- if ("Toggle_Font")
- //CODE REVISION 2
- font_index = (font_index + 1) % 4
-
- switch(font_index)
- if (MODE_MONO)
- font_mode = FONT_MONO
- if (MODE_SHARE)
- font_mode = FONT_SHARE
- if (MODE_ORBITRON)
- font_mode = FONT_ORBITRON
- if (MODE_VT)
- font_mode = FONT_VT
- if(!silent)
- playsound(src, 'sound/machines/terminal_select.ogg', 15, TRUE)
- if ("Change_Color")
- var/new_color = input("Please enter a color name or hex value (Default is \'#808000\').",background_color)as color
- background_color = new_color
-
- if ("Toggle_Underline")
- underline_flag = !underline_flag
- if(!silent)
- playsound(src, 'sound/machines/terminal_select.ogg', 15, TRUE)
-
- if("Return")//Return
- ui_mode = round(ui_mode/PDA_UI_RETURN_DIVIDER)
- if(ISINRANGE(ui_mode, PDA_UI_REDIRECT_HUB_MIN, PDA_UI_REDIRECT_HUB_MAX))//Fix for cartridges. Redirects to hub.
- ui_mode = PDA_UI_HUB
- if(!silent)
- playsound(src, 'sound/machines/terminal_select.ogg', 15, TRUE)
- if ("Authenticate")//Checks for ID
- id_check(U)
- if("UpdateInfo")
- ownjob = id.assignment
- update_label()
- if(!silent)
- playsound(src, 'sound/machines/terminal_processing.ogg', 15, TRUE)
- addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound, src, 'sound/machines/terminal_success.ogg', 15, TRUE), 1.3 SECONDS)
- if("Eject")//Ejects the cart, only done from hub.
- eject_cart(U)
- if(!silent)
- playsound(src, 'sound/machines/terminal_eject.ogg', 50, TRUE)
-
-//MENU FUNCTIONS===================================
-
- if(PDA_UI_HUB)
- ui_mode = PDA_UI_HUB
- if(!silent)
- playsound(src, 'sound/machines/terminal_select.ogg', 15, TRUE)
- if(PDA_UI_NOTEKEEPER)
- ui_mode = PDA_UI_NOTEKEEPER
- if(!silent)
- playsound(src, 'sound/machines/terminal_select.ogg', 15, TRUE)
- if(PDA_UI_MESSENGER)
- if(HAS_TRAIT(src, TRAIT_PDA_MESSAGE_MENU_RIGGED))
- explode(U, from_message_menu = TRUE)
- return
- ui_mode = PDA_UI_MESSENGER
- if(!silent)
- playsound(src, 'sound/machines/terminal_select.ogg', 15, TRUE)
- if(PDA_UI_READ_MESSAGES)
- ui_mode = PDA_UI_READ_MESSAGES
- if(!silent)
- playsound(src, 'sound/machines/terminal_select.ogg', 15, TRUE)
- if(PDA_UI_ATMOS_SCAN)
- ui_mode = PDA_UI_ATMOS_SCAN
- if(!silent)
- playsound(src, 'sound/machines/terminal_select.ogg', 15, TRUE)
-
-
-//MAIN FUNCTIONS===================================
-
- if("Light")
- toggle_light(U)
- if(!silent)
- playsound(src, 'sound/machines/terminal_select.ogg', 15, TRUE)
- if("Medical Scan")
- if(scanmode == PDA_SCANNER_MEDICAL)
- scanmode = PDA_SCANNER_NONE
- else if((!isnull(cartridge)) && (cartridge.access & CART_MEDICAL))
- scanmode = PDA_SCANNER_MEDICAL
- if(!silent)
- playsound(src, 'sound/machines/terminal_select.ogg', 15, TRUE)
- if("Reagent Scan")
- if(scanmode == PDA_SCANNER_REAGENT)
- scanmode = PDA_SCANNER_NONE
- else if((!isnull(cartridge)) && (cartridge.access & CART_REAGENT_SCANNER))
- scanmode = PDA_SCANNER_REAGENT
- if("Honk")
- if ( !(last_noise && world.time < last_noise + 20) )
- playsound(src, 'sound/items/bikehorn.ogg', 50, TRUE)
- last_noise = world.time
- if("Trombone")
- if ( !(last_noise && world.time < last_noise + 20) )
- playsound(src, 'sound/misc/sadtrombone.ogg', 50, TRUE)
- last_noise = world.time
- if("Gas Scan")
- if(scanmode == PDA_SCANNER_GAS)
- scanmode = PDA_SCANNER_NONE
- else if((!isnull(cartridge)) && (cartridge.access & CART_ATMOS))
- scanmode = PDA_SCANNER_GAS
- if(!silent)
- playsound(src, 'sound/machines/terminal_select.ogg', 15, TRUE)
-
-
-//NOTEKEEPER FUNCTIONS===================================
-
- if ("Edit")
- var/n = tgui_input_text(U, "Please enter message", name, note, multiline = TRUE)
- if (in_range(src, U) && loc == U)
- if (ui_mode == PDA_UI_NOTEKEEPER && n)
- note = n
- notehtml = parsemarkdown(n, U)
- notescanned = FALSE
- else
- U << browse(null, "window=pda")
- return
-
-//MESSENGER FUNCTIONS===================================
-
- if("Toggle Messenger")
- toff = !toff
- if("Toggle Ringer")//If viewing texts then erase them, if not then toggle silent status
- silent = !silent
- if("Clear")//Clears messages
- tnote = null
- if("Ringtone")
- var/t = tgui_input_text(U, "Enter a new ringtone", "PDA Ringtone", ttone, 20)
- if(in_range(src, U) && loc == U && t)
- if(SEND_SIGNAL(src, COMSIG_PDA_CHANGE_RINGTONE, U, t) & COMPONENT_STOP_RINGTONE_CHANGE)
- U << browse(null, "window=pda")
- return
- else
- ttone = t
- else
- U << browse(null, "window=pda")
- return
- if("Message")
- create_message(U, locate(href_list["target"]) in GLOB.PDAs)
- if("Mess_us_up")
- if(!HAS_TRAIT(src, TRAIT_PDA_CAN_EXPLODE)) //in case someone ever tries to call this with forged hrefs
- return
- explode(U, locate(href_list["target"]))
-
- if("Sorting Mode")
- sort_by_job = !sort_by_job
-
- if("MessageAll")
- if(cartridge?.spam_enabled)
- send_to_all(U)
-
- if("cart")
- if(cartridge)
- cartridge.special(U, href_list)
- else
- U << browse(null, "window=pda")
- return
-
-//pAI FUNCTIONS===================================
-
- if("pai")
- switch(href_list["option"])
- if("1") // Configure pAI device
- pai.attack_self(U)
- if("2") // Eject pAI device
- usr.put_in_hands(pai)
- pai.slotted = FALSE
- to_chat(usr, span_notice("You remove the pAI from the [name]."))
-
-//SKILL FUNCTIONS===================================
-
- if("SkillReward")
- var/type = text2path(href_list["skill"])
- var/datum/skill/S = GetSkillRef(type)
- var/datum/mind/mind = U.mind
- var/new_level = mind.get_skill_level(type)
- S.try_skill_reward(mind, new_level)
-
-//LINK FUNCTIONS===================================
-
- else
- ui_mode = max(choice, PDA_UI_HUB)
-
- else//If not in range, can't interact or not using the pda.
- U.unset_machine()
- U << browse(null, "window=pda")
- return
-
-//EXTRA FUNCTIONS===================================
-
- if (ui_mode == PDA_UI_MESSENGER || ui_mode == PDA_UI_READ_MESSAGES)//To clear message overlays.
- update_appearance()
-
- if ((honkamt > 0) && (prob(60)))//For clown virus.
- honkamt--
- playsound(src, 'sound/items/bikehorn.ogg', 30, TRUE)
-
- if(U.machine == src && href_list["skiprefresh"]!="1")//Final safety.
- attack_self(U)//It auto-closes the menu prior if the user is not in range and so on.
- else
- U.unset_machine()
- U << browse(null, "window=pda")
- return
-
-/obj/item/pda/proc/remove_id(mob/user)
- if(issilicon(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
- return
- do_remove_id(user)
-
-
-/obj/item/pda/proc/do_remove_id(mob/user)
- if(!id)
- return
- if(user)
- user.put_in_hands(id)
- to_chat(user, span_notice("You remove the ID from the [name]."))
- else
- id.forceMove(get_turf(src))
-
- . = id
- id = null
- updateSelfDialog()
- update_appearance()
- playsound(src, 'sound/machines/terminal_eject.ogg', 50, TRUE)
-
- if(ishuman(loc))
- var/mob/living/carbon/human/H = loc
- if(H.wear_id == src)
- H.sec_hud_set_ID()
-
- update_slot_icon()
-
-
-/obj/item/pda/proc/msg_input(mob/living/U = usr, rigged = FALSE)
- var/t = tgui_input_text(U, "Enter a message", "PDA Messaging")
- if (!t || toff)
- return
- if(!U.canUseTopic(src, BE_CLOSE))
- return
- if(emped)
- t = Gibberish(t, TRUE)
- return t
-
-/**
- * Prompts the user to input and send a message to another PDA.
- * the everyone arg is used for mass messaging from lawyer and captain carts.
- * rigged for PDA bombs. fakename and fakejob for forged messages (also PDA bombs).
- */
-/obj/item/pda/proc/send_message(mob/living/user, list/obj/item/pda/targets, everyone = FALSE, rigged = FALSE, fakename, fakejob)
- var/message = msg_input(user, rigged)
- if(!message || !targets.len)
- return FALSE
- if((last_text && world.time < last_text + 10) || (everyone && last_everyone && world.time < last_everyone + PDA_SPAM_DELAY))
- return FALSE
-
- var/turf/position = get_turf(src)
- for(var/obj/item/jammer/jammer as anything in GLOB.active_jammers)
- var/turf/jammer_turf = get_turf(jammer)
- if(position?.z == jammer_turf.z && (get_dist(position, jammer_turf) <= jammer.range))
- return FALSE
-
- var/list/filter_result = CAN_BYPASS_FILTER(user) ? null : is_ic_filtered_for_pdas(message)
- if (filter_result)
- REPORT_CHAT_FILTER_TO_USER(user, filter_result)
- return FALSE
-
- var/list/soft_filter_result = CAN_BYPASS_FILTER(user) ? null : is_soft_ic_filtered_for_pdas(message)
- if (soft_filter_result)
- if(tgui_alert(usr,"Your message contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to send it?", "Soft Blocked Word", list("Yes", "No")) != "Yes")
- return FALSE
- message_admins("[ADMIN_LOOKUPFLW(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term in PDA messages. Message: \"[html_encode(message)]\"")
- log_admin_private("[key_name(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term in PDA messages. Message: \"[message]\"")
-
- if(prob(1))
- message += "\nSent from my PDA"
- // SKYRAT EDIT BEGIN - PDA messages show a visible message, to comply with CI policy on calling for backup.
- user.visible_message(span_notice("[user] presses some buttons on [user.p_their()] [src]."), span_notice("You press some buttons on your [src]."))
- user.balloon_alert_to_viewers("sent a PDA message")
- // SKYRAT EDIT END
- // Send the signal
- var/list/string_targets = list()
- for (var/obj/item/pda/P in targets)
- if (P.owner && P.ownjob) // != src is checked by the UI
- string_targets += STRINGIFY_PDA_TARGET(P.owner, P.ownjob)
- for (var/obj/machinery/computer/message_monitor/M in targets)
- // In case of "Reply" to a message from a console, this will make the
- // message be logged successfully. If the console is impersonating
- // someone by matching their name and job, the reply will reach the
- // impersonated PDA.
- string_targets += STRINGIFY_PDA_TARGET(M.customsender, M.customjob)
- if (!string_targets.len)
- return FALSE
-
- var/datum/signal/subspace/messaging/pda/signal = new(src, list(
- "name" = "[fakename || owner]",
- "job" = "[fakejob || ownjob]",
- "message" = message,
- "targets" = string_targets,
- "emojis" = allow_emojis,
- "rigged" = rigged,
- ))
- if(rigged) //Will skip the message server and go straight to the hub so it can't be cheesed by disabling the message server machine
- signal.data["rigged_user"] = REF(user) // Used for bomb logging
- signal.server_type = /obj/machinery/telecomms/hub
- signal.data["reject"] = FALSE // Do not refuse the message
- if (picture)
- signal.data["photo"] = picture
- signal.send_to_receivers()
-
- // If it didn't reach, note that fact
- if (!signal.data["done"])
- to_chat(user, span_notice("ERROR: Server isn't responding."))
- if(!silent)
- playsound(src, 'sound/machines/terminal_error.ogg', 15, TRUE)
- return FALSE
-
- var/target_text = signal.format_target()
- if(allow_emojis)
- message = emoji_parse(message)//already sent- this just shows the sent emoji as one to the sender in the to_chat
- signal.data["message"] = emoji_parse(signal.data["message"])
-
- // Log it in our logs
- tnote += "→ To [target_text]: [signal.format_message()] "
- // Show it to ghosts
- var/ghost_message = span_name("[owner] [rigged ? "Rigged" : ""] PDA Message --> [span_name("[target_text]")]: [signal.format_message()]")
- for(var/mob/M in GLOB.player_list)
- if(isobserver(M) && (M.client?.prefs.chat_toggles & CHAT_GHOSTPDA))
- to_chat(M, "[FOLLOW_LINK(M, user)] [ghost_message]")
- // Log in the talk log
- user.log_talk(message, LOG_PDA, tag="[rigged ? "Rigged" : ""] PDA: [initial(name)] to [target_text]")
- if(rigged)
- log_bomber(user, "sent a rigged PDA message (Name: [fakename || owner]. Job: [fakejob || ownjob]) to [english_list(string_targets)] [!is_special_character(user) ? "(SENT BY NON-ANTAG)" : ""]")
- to_chat(user, span_info("PDA message sent to [target_text]: \"[message]\""))
- if(!silent)
- playsound(src, 'sound/machines/terminal_success.ogg', 15, TRUE)
- // Reset the photo
- picture = null
- last_text = world.time
- if (everyone)
- last_everyone = world.time
- return TRUE
-
-/obj/item/pda/proc/receive_message(datum/signal/subspace/messaging/pda/signal)
- var/ref_target = signal.data["rigged"] ? signal.data["rigged_user"] : REF(signal.source)
- tnote += "← From [signal.data["name"]] ([signal.data["job"]]): [signal.format_message()] "
-
- if (!silent)
- if(HAS_TRAIT(SSstation, STATION_TRAIT_PDA_GLITCHED))
- playsound(src, pick('sound/machines/twobeep_voice1.ogg', 'sound/machines/twobeep_voice2.ogg'), 50, TRUE)
- else
- playsound(src, 'sound/machines/twobeep_high.ogg', 50, TRUE)
- audible_message("[icon2html(src, hearers(src))] *[ttone]* ", null, 3)
- //Search for holder of the PDA.
- var/mob/living/L = null
- if(loc && isliving(loc))
- L = loc
- //Maybe they are a pAI!
- else
- L = get(src, /mob/living/silicon)
-
- if(L && (L.stat == CONSCIOUS || L.stat == SOFT_CRIT))
- var/reply = "(Reply )"
- var/hrefstart
- var/hrefend
- if (isAI(L))
- hrefstart = ""
- hrefend = " "
-
- if(signal.data["automated"])
- reply = "\[Automated Message\]"
-
- var/inbound_message = signal.format_message()
- if(signal.data["emojis"] == TRUE)//so will not parse emojis as such from pdas that don't send emojis
- inbound_message = emoji_parse(inbound_message)
-
- to_chat(L, "[icon2html(src)] PDA message from [hrefstart][signal.data["name"]] ([signal.data["job"]])[hrefend], [inbound_message] [reply] ")
-
- update_appearance()
- if(istext(icon_alert))
- icon_alert = mutable_appearance(initial(icon), icon_alert)
- add_overlay(icon_alert)
-
-/obj/item/pda/proc/send_to_all(mob/living/U)
- if (last_everyone && world.time < last_everyone + PDA_SPAM_DELAY)
- to_chat(U,span_warning("Send To All function is still on cooldown."))
- return
- send_message(U,get_viewable_pdas(), TRUE)
-
-/obj/item/pda/proc/create_message(mob/living/U, obj/item/pda/P)
- send_message(U,list(P))
-
-/obj/item/pda/AltClick(mob/user)
- ..()
-
- if(id)
- remove_id(user)
- else
- remove_pen(user)
-
-/obj/item/pda/CtrlClick(mob/user)
- ..()
-
- if(isturf(loc)) //stops the user from dragging the PDA by ctrl-clicking it.
- return
-
- remove_pen(user)
-
-/obj/item/pda/CtrlShiftClick(mob/user)
- ..()
- eject_cart(user)
-
-/obj/item/pda/verb/verb_toggle_light()
- set name = "Toggle light"
- set category = "Object"
- set src in oview(1)
-
- toggle_light(usr)
-
-/obj/item/pda/verb/verb_remove_id()
- set category = "Object"
- set name = "Eject ID"
- set src in usr
-
- if(id)
- remove_id(usr)
- else
- to_chat(usr, span_warning("This PDA does not have an ID in it!"))
-
-/obj/item/pda/verb/verb_remove_pen()
- set category = "Object"
- set name = "Remove Pen"
- set src in usr
-
- remove_pen(usr)
-
-/obj/item/pda/verb/verb_eject_cart()
- set category = "Object"
- set name = "Eject Cartridge"
- set src in usr
-
- eject_cart(usr)
-
-/obj/item/pda/proc/toggle_light(mob/user)
- if(issilicon(user) || !user.canUseTopic(src, BE_CLOSE))
- return
- if(light_on)
- set_light_on(FALSE)
- else if(light_range)
- set_light_on(TRUE)
- update_appearance()
- update_action_buttons(force = TRUE)
-
-/// Special light eater handling
-/obj/item/pda/proc/on_light_eater(obj/item/pda/source, datum/light_eater)
- SIGNAL_HANDLER
- set_light_on(FALSE)
- set_light_range(0) //We won't be turning on again.
- update_appearance()
- visible_message(span_danger("The light in [src] shorts out!"))
- return COMPONENT_BLOCK_LIGHT_EATER
-
-/obj/item/pda/proc/remove_pen(mob/user)
-
- if(issilicon(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) //TK doesn't work even with this removed but here for readability
- return
-
- if(inserted_item)
- to_chat(user, span_notice("You remove [inserted_item] from [src]."))
- user.put_in_hands(inserted_item) //Don't need to manage the pen ref, handled on Exited()
- update_appearance()
- playsound(src, 'sound/machines/pda_button2.ogg', 50, TRUE)
- else
- to_chat(user, span_warning("This PDA does not have a pen in it!"))
-
-/obj/item/pda/proc/eject_cart(mob/user)
- if(issilicon(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) //TK disabled to stop cartridge teleporting into hand
- return
- if (!isnull(cartridge))
- to_chat(user, span_notice("You eject [cartridge] from [src]."))
- user.put_in_hands(cartridge) //We don't manage reference clearing here, dealt with in Exited()
- scanmode = PDA_SCANNER_NONE
- updateSelfDialog()
- update_appearance()
-
-//trying to insert or remove an id
-/obj/item/pda/proc/id_check(mob/user, obj/item/card/id/I)
- if(!I)
- if(id && (src in user.contents))
- remove_id(user)
- return TRUE
- else
- var/obj/item/card/id/C = user.get_active_held_item()
- if(istype(C))
- I = C
-
- if(I?.registered_name)
- if(!user.transferItemToLoc(I, src))
- return FALSE
- insert_id(I, user)
- update_appearance()
- playsound(src, 'sound/machines/pda_button1.ogg', 50, TRUE)
- return TRUE
-
-
-/obj/item/pda/proc/insert_id(obj/item/card/id/inserting_id, mob/user)
- var/obj/old_id = id
- id = inserting_id
- if(ishuman(loc))
- var/mob/living/carbon/human/human_wearer = loc
- if(human_wearer.wear_id == src)
- human_wearer.sec_hud_set_ID()
- if(old_id)
- if(user)
- user.put_in_hands(old_id)
- else
- old_id.forceMove(get_turf(src))
-
- update_slot_icon()
-
-
-/obj/item/pda/pre_attack(obj/target, mob/living/user, params)
- if(!ismachinery(target))
- return ..()
- var/obj/machinery/target_machine = target
- if(!target_machine.panel_open && !istype(target, /obj/machinery/computer))
- return ..()
- if(!istype(cartridge, /obj/item/cartridge/virus/clown))
- return ..()
- var/obj/item/cartridge/virus/installed_cartridge = cartridge
-
- if(installed_cartridge.charges <=0)
- to_chat(user, span_notice("Out of charges."))
- return ..()
- to_chat(user, span_notice("You upload the virus to the airlock controller!"))
- var/sig_list
- if(istype(target,/obj/machinery/door/airlock))
- sig_list += list(COMSIG_AIRLOCK_OPEN, COMSIG_AIRLOCK_CLOSE)
- else
- sig_list += list(COMSIG_ATOM_ATTACK_HAND)
- target.AddComponent(/datum/component/sound_player, uses = rand(15,20), signal_list = sig_list)
- installed_cartridge.charges--
- return TRUE
-
-
-// access to status display signals
-/obj/item/pda/attackby(obj/item/C, mob/user, params)
- if(istype(C, /obj/item/cartridge))
- if(!user.transferItemToLoc(C, src))
- return
- eject_cart(user)
- cartridge = C
- cartridge.host_pda = src
- to_chat(user, span_notice("You insert [cartridge] into [src]."))
- updateSelfDialog()
- update_appearance()
- playsound(src, 'sound/machines/pda_button1.ogg', 50, TRUE)
-
- else if(istype(C, /obj/item/card/id))
- var/obj/item/card/id/idcard = C
- if(!idcard.registered_name)
- to_chat(user, span_warning("\The [src] rejects the ID!"))
- if(!silent)
- playsound(src, 'sound/machines/terminal_error.ogg', 50, TRUE)
- return
- if(!owner)
- owner = idcard.registered_name
- ownjob = idcard.assignment
- update_label()
- to_chat(user, span_notice("Card scanned."))
- if(!silent)
- playsound(src, 'sound/machines/terminal_success.ogg', 50, TRUE)
- else
- if(!id_check(user, idcard))
- return
- to_chat(user, span_notice("You put the ID into \the [src]'s slot."))
- updateSelfDialog()//Update self dialog on success.
-
- return //Return in case of failed check or when successful.
- updateSelfDialog()//For the non-input related code.
- else if(istype(C, /obj/item/paicard) && !pai)
- if(!user.transferItemToLoc(C, src))
- return
- pai = C
- pai.slotted = TRUE
- to_chat(user, span_notice("You slot \the [C] into [src]."))
- update_appearance()
- updateUsrDialog()
- else if(is_type_in_list(C, contained_item)) //Checks if there is a pen
- if(inserted_item)
- to_chat(user, span_warning("There is already \a [inserted_item] in \the [src]!"))
- else
- if(!user.transferItemToLoc(C, src))
- return
- to_chat(user, span_notice("You slide \the [C] into \the [src]."))
- inserted_item = C
- update_appearance()
- playsound(src, 'sound/machines/pda_button1.ogg', 50, TRUE)
- else if(istype(C, /obj/item/photo))
- var/obj/item/photo/P = C
- picture = P.picture
- to_chat(user, span_notice("You scan \the [C]."))
- // Check to see if we have an ID inside, and a valid input for money
- else if(id && iscash(C))
- id.attackby(C, user) // If we do, try and put that attacking object in
- else
- return ..()
-
-/obj/item/pda/attack(mob/living/carbon/C, mob/living/user)
- if(istype(C))
- switch(scanmode)
-
- if(PDA_SCANNER_MEDICAL)
- C.visible_message(span_notice("[user] analyzes [C]'s vitals."))
- healthscan(user, C, 1)
- add_fingerprint(user)
-
-/obj/item/pda/afterattack(atom/A as mob|obj|turf|area, mob/user, proximity)
- . = ..()
- if(!proximity)
- return
- switch(scanmode)
- if(PDA_SCANNER_REAGENT)
- if(!isnull(A.reagents))
- if(A.reagents.reagent_list.len > 0)
- var/reagents_length = A.reagents.reagent_list.len
- to_chat(user, span_notice("[reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found."))
- for (var/re in A.reagents.reagent_list)
- to_chat(user, span_notice("\t [re]"))
- else
- to_chat(user, span_notice("No active chemical agents found in [A]."))
- else
- to_chat(user, span_notice("No significant chemical agents found in [A]."))
-
- if(PDA_SCANNER_GAS)
- A.analyzer_act(user, src)
-
- if (!scanmode && istype(A, /obj/item/paper) && owner)
- var/obj/item/paper/paper = A
- if (!paper.get_info_length())
- to_chat(user, span_warning("Unable to scan! Paper is blank."))
- return
- notehtml = paper.info
- if(paper.add_info)
- for(var/index in 1 to length(paper.add_info))
- var/list/style = paper.add_info_style[index]
- notehtml += PAPER_MARK_TEXT(paper.add_info[index], style[ADD_INFO_COLOR], style[ADD_INFO_FONT])
- note = replacetext(notehtml, " ", "\[br\]")
- note = replacetext(note, "", "\[*\]")
- note = replacetext(note, "", "\[list\]")
- note = replacetext(note, " ", "\[/list\]")
- note = html_encode(note)
- notescanned = TRUE
- to_chat(user, span_notice("Paper scanned. Saved to PDA's notekeeper.") )
-
-/**
- * Called when someone replies to a rigged PDA message. It explodes.
- * from_message_menu : whether it's caused by the target opening the message menu too early.
- */
-/obj/item/pda/proc/explode(mob/target, mob/bomber, from_message_menu = FALSE)
- var/turf/T = get_turf(src)
-
- if(from_message_menu)
- log_bomber(null, null, target, "'s PDA exploded as [target.p_they()] tried to open their PDA message menu because of a recent pda bomb.")
- else
- log_bomber(bomber, "successfully PDA-bombed", target, "as [target.p_they()] tried to reply to a rigged PDA message [bomber && !is_special_character(bomber) ? "(SENT BY NON-ANTAG)" : ""]")
-
- if (ismob(loc))
- var/mob/M = loc
- M.show_message(span_userdanger("Your [src] explodes!"), MSG_VISUAL, span_warning("You hear a loud *pop*!"), MSG_AUDIBLE)
- else
- visible_message(span_danger("[src] explodes!"), span_warning("You hear a loud *pop*!"))
-
- target.client?.give_award(/datum/award/achievement/misc/clickbait, target)
-
- if(T)
- T.hotspot_expose(700,125)
- if(istype(cartridge, /obj/item/cartridge/virus/syndicate))
- explosion(src, devastation_range = -1, heavy_impact_range = 1, light_impact_range = 3, flash_range = 4)
- else
- explosion(src, devastation_range = -1, heavy_impact_range = -1, light_impact_range = 2, flash_range = 3)
- qdel(src)
-
-//AI verb and proc for sending PDA messages.
-
-/obj/item/pda/ai/verb/cmd_toggle_pda_receiver()
- set category = "AI Commands"
- set name = "PDA - Toggle Sender/Receiver"
-
- if(usr.stat == DEAD)
- return //won't work if dead
- var/mob/living/silicon/S = usr
- if(istype(S) && !isnull(S.aiPDA))
- S.aiPDA.toff = !S.aiPDA.toff
- to_chat(usr, span_notice("PDA sender/receiver toggled [(S.aiPDA.toff ? "Off" : "On")]!"))
- else
- to_chat(usr, "You do not have a PDA. You should make an issue report about this.")
-
-/obj/item/pda/ai/verb/cmd_toggle_pda_silent()
- set category = "AI Commands"
- set name = "PDA - Toggle Ringer"
-
- if(usr.stat == DEAD)
- return //won't work if dead
- var/mob/living/silicon/S = usr
- if(istype(S) && !isnull(S.aiPDA))
- //0
- S.aiPDA.silent = !S.aiPDA.silent
- to_chat(usr, span_notice("PDA ringer toggled [(S.aiPDA.silent ? "Off" : "On")]!"))
- else
- to_chat(usr, "You do not have a PDA. You should make an issue report about this.")
-
-/mob/living/silicon/proc/cmd_send_pdamesg(mob/user)
- var/list/plist = list()
- var/list/namecounts = list()
-
- if(aiPDA.toff)
- to_chat(user, span_alert("Turn on your receiver in order to send messages."))
- return
-
- for (var/obj/item/pda/pda as anything in get_viewable_pdas())
- if (pda == src)
- continue
- else if (pda == aiPDA)
- continue
-
- plist[avoid_assoc_duplicate_keys(pda.owner, namecounts)] = pda
-
- var/choice = tgui_input_list(user, "Please select a PDA", "PDA Messenger", sort_list(plist))
- if (isnull(choice))
- return
-
- var/selected = plist[choice]
-
- if(aicamera.stored.len)
- var/add_photo = tgui_alert(user,"Do you want to attach a photo?", "PDA Messenger", list("Yes","No"))
- if(add_photo == "Yes")
- var/datum/picture/Pic = aicamera.selectpicture(user)
- aiPDA.picture = Pic
-
- if(incapacitated())
- return
-
- aiPDA.create_message(src, selected)
-
-/mob/living/silicon/proc/cmd_show_message_log(mob/user)
- if(incapacitated())
- return
- if(!isnull(aiPDA))
- var/HTML = "AI PDA Message Log [aiPDA.tnote]"
- user << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0")
- else
- to_chat(user, span_warning("You do not have a PDA! You should make an issue report about this."))
-
-// Pass along the pulse to atoms in contents, largely added so pAIs are vulnerable to EMP
-/obj/item/pda/emp_act(severity)
- . = ..()
- if (!(. & EMP_PROTECT_CONTENTS))
- for(var/atom/A in src)
- A.emp_act(severity)
- if (!(. & EMP_PROTECT_SELF))
- emped++
- addtimer(CALLBACK(src, .proc/emp_end), 200 * severity)
-
-/obj/item/pda/proc/emp_end()
- emped--
-
-/proc/get_viewable_pdas(sort_by_job = FALSE)
- . = list()
- // Returns a list of PDAs which can be viewed from another PDA/message monitor.,
- var/sortmode
- if(sort_by_job)
- sortmode = /proc/cmp_pdajob_asc
- else
- sortmode = /proc/cmp_pdaname_asc
-
- for(var/obj/item/pda/P in sort_list(GLOB.PDAs, sortmode))
- if(!P.owner || P.toff || P.hidden)
- continue
- . += P
-
-/obj/item/pda/proc/pda_no_detonate()
- SIGNAL_HANDLER
- return COMPONENT_PDA_NO_DETONATE
-
-/// Return a list of types you want to pregenerate and use later
-/// Do not pass in things that care about their init location, or expect extra input
-/// Also as a curtiousy to me, don't pass in any bombs
-/obj/item/pda/proc/get_types_to_preload()
- var/list/preload = list()
- preload += default_cartridge
- preload += insert_type
- return preload
-
-/// Callbacks for preloading pdas
-/obj/item/pda/proc/display_pda()
- GLOB.PDAs += src
-
-/// See above, we don't want jerry from accounting to try and message nullspace his new bike
-/obj/item/pda/proc/cloak_pda()
- GLOB.PDAs -= src
-
-#undef PDA_SCANNER_NONE
-#undef PDA_SCANNER_MEDICAL
-#undef PDA_SCANNER_FORENSICS
-#undef PDA_SCANNER_REAGENT
-#undef PDA_SCANNER_GAS
-#undef PDA_SPAM_DELAY
diff --git a/code/game/objects/items/devices/PDA/PDA_types.dm b/code/game/objects/items/devices/PDA/PDA_types.dm
deleted file mode 100644
index e4db41d2841..00000000000
--- a/code/game/objects/items/devices/PDA/PDA_types.dm
+++ /dev/null
@@ -1,258 +0,0 @@
-//Clown PDA is slippery.
-/obj/item/pda/clown
- name = "clown PDA"
- default_cartridge = /obj/item/cartridge/virus/clown
- insert_type = /obj/item/toy/crayon/rainbow
- icon_state = "pda-clown"
- greyscale_config = null
- greyscale_config = null
- desc = "A portable microcomputer by Thinktronic Systems, LTD. The surface is coated with polytetrafluoroethylene and banana drippings."
- ttone = "honk"
-
-/obj/item/pda/clown/ComponentInitialize()
- . = ..()
- AddComponent(/datum/component/slippery/clowning, 120, NO_SLIP_WHEN_WALKING, CALLBACK(src, .proc/AfterSlip), slot_whitelist = list(ITEM_SLOT_ID, ITEM_SLOT_BELT))
- AddComponent(/datum/component/wearertargeting/sitcomlaughter, CALLBACK(src, .proc/after_sitcom_laugh))
-
-/obj/item/pda/clown/proc/AfterSlip(mob/living/carbon/human/M)
- if (istype(M) && (M.real_name != owner))
- var/obj/item/cartridge/virus/clown/cart = cartridge
- if(istype(cart) && cart.charges < 5)
- cart.charges++
- playsound(src,'sound/machines/ping.ogg',30,TRUE)
-
-/obj/item/pda/clown/proc/after_sitcom_laugh(mob/victim)
- victim.visible_message("[src] lets out a burst of laughter!")
-
-//Mime PDA sends "silent" messages.
-/obj/item/pda/mime
- name = "mime PDA"
- default_cartridge = /obj/item/cartridge/virus/mime
- insert_type = /obj/item/toy/crayon/mime
- greyscale_config = /datum/greyscale_config/pda/mime
- greyscale_colors = "#e2e2e2#cc4242"
- desc = "A portable microcomputer by Thinktronic Systems, LTD. The hardware has been modified for compliance with the vows of silence."
- allow_emojis = TRUE
- silent = TRUE
- ttone = "silence"
-
-/obj/item/pda/mime/msg_input(mob/living/U = usr, rigged = FALSE)
- if(rigged)
- return ..()
- if(emped || toff)
- return
- var/emojis = emoji_sanitize(stripped_input(U, "Please enter emojis", name))
- if(!emojis)
- return
- if(!U.canUseTopic(src, BE_CLOSE))
- return
- return emojis
-
-// Special AI/pAI PDAs that cannot explode.
-/obj/item/pda/ai
- icon = null
- greyscale_config = null
- greyscale_colors = null
- ttone = "data"
-
-
-/obj/item/pda/ai/attack_self(mob/user)
- if ((honkamt > 0) && (prob(60)))//For clown virus.
- honkamt--
- playsound(loc, 'sound/items/bikehorn.ogg', 30, TRUE)
- return
-
-/obj/item/pda/ai/pai
- ttone = "assist"
-
-/obj/item/pda/ai/Initialize(mapload)
- . = ..()
- RegisterSignal(src, COMSIG_PDA_CHECK_DETONATE, .proc/pda_no_detonate)
-
-/obj/item/pda/medical
- name = "medical PDA"
- default_cartridge = /obj/item/cartridge/medical
- greyscale_config = /datum/greyscale_config/pda/stripe_thick
- greyscale_colors = "#e2e2e2#000099#5d99be"
-
-/obj/item/pda/viro
- name = "virology PDA"
- default_cartridge = /obj/item/cartridge/medical
- greyscale_config = /datum/greyscale_config/pda/stripe_split
- greyscale_colors = "#e2e2e2#355FAC#789876"
-
-/obj/item/pda/engineering
- name = "engineering PDA"
- default_cartridge = /obj/item/cartridge/engineering
- greyscale_config = /datum/greyscale_config/pda/stripe_thick
- greyscale_colors = "#C5994C#69DBF3#D9D65B"
-
-/obj/item/pda/security
- name = "security PDA"
- default_cartridge = /obj/item/cartridge/security
- greyscale_colors = "#cc4242#0000cc"
-
-/obj/item/pda/detective
- name = "detective PDA"
- default_cartridge = /obj/item/cartridge/detective
- greyscale_colors = "#90714F#990202"
-
-/obj/item/pda/warden
- name = "warden PDA"
- default_cartridge = /obj/item/cartridge/security
- greyscale_config = /datum/greyscale_config/pda/stripe_split
- greyscale_colors = "#cc4242#0000cc#666666"
-
-/obj/item/pda/janitor
- name = "janitor PDA"
- greyscale_colors = "#933ea8#235AB2"
- ttone = "slip"
-
-/obj/item/pda/science
- name = "scientist PDA"
- default_cartridge = /obj/item/cartridge/signal/ordnance
- greyscale_config = /datum/greyscale_config/pda/stripe_thick
- greyscale_colors = "#e2e2e2#000099#9F5CA5"
- ttone = "boom"
-
-
-/obj/item/pda/heads
- default_cartridge = /obj/item/cartridge/head
- greyscale_config = /datum/greyscale_config/pda/head
- greyscale_colors = "#789876#a92323"
-
-/obj/item/pda/heads/hop
- name = "head of personnel PDA"
- default_cartridge = /obj/item/cartridge/hop
-
-/obj/item/pda/heads/hos
- name = "head of security PDA"
- default_cartridge = /obj/item/cartridge/hos
- greyscale_config = /datum/greyscale_config/pda/head
- greyscale_colors = "#cc4242#0000cc"
-
-/obj/item/pda/heads/ce
- name = "chief engineer PDA"
- default_cartridge = /obj/item/cartridge/ce
- greyscale_config = /datum/greyscale_config/pda/stripe_thick/head
- greyscale_colors = "#C4A56D#69DBF3#e2e2e2"
-
-/obj/item/pda/heads/cmo
- name = "chief medical officer PDA"
- default_cartridge = /obj/item/cartridge/cmo
- greyscale_config = /datum/greyscale_config/pda/stripe_thick/head
- greyscale_colors = "#e2e2e2#000099#5d99be"
-
-/obj/item/pda/heads/rd
- name = "research director PDA"
- default_cartridge = /obj/item/cartridge/rd
- insert_type = /obj/item/pen/fountain
- greyscale_config = /datum/greyscale_config/pda/stripe_thick/head
- greyscale_colors = "#e2e2e2#000099#9F5CA5"
-
-/obj/item/pda/captain
- name = "captain PDA"
- default_cartridge = /obj/item/cartridge/captain
- insert_type = /obj/item/pen/fountain/captain
- greyscale_config = /datum/greyscale_config/pda/captain
- greyscale_colors = "#2C7CB2#FF0000#FFFFFF#F5D67B"
-
-/obj/item/pda/captain/Initialize(mapload)
- . = ..()
- RegisterSignal(src, COMSIG_PDA_CHECK_DETONATE, .proc/pda_no_detonate)
-
-/obj/item/pda/cargo
- name = "cargo technician PDA"
- default_cartridge = /obj/item/cartridge/quartermaster
- greyscale_colors = "#D6B328#6506ca"
-
-/obj/item/pda/quartermaster
- name = "quartermaster PDA"
- default_cartridge = /obj/item/cartridge/quartermaster
- insert_type = /obj/item/pen/survival
- greyscale_config = /datum/greyscale_config/pda/stripe_thick
- greyscale_colors = "#D6B328#6506ca#927444"
-
-/obj/item/pda/shaftminer
- name = "shaft miner PDA"
- greyscale_config = /datum/greyscale_config/pda/stripe_thick
- greyscale_colors = "#927444#D6B328#6C3BA1"
-
-/obj/item/pda/syndicate
- default_cartridge = /obj/item/cartridge/virus/syndicate
- greyscale_colors = "#891417#80FF80"
- name = "military PDA"
- owner = "John Doe"
- hidden = 1
-
-/obj/item/pda/chaplain
- name = "chaplain PDA"
- greyscale_config = /datum/greyscale_config/pda/chaplain
- greyscale_colors = "#333333#d11818"
- ttone = "holy"
-
-/obj/item/pda/lawyer
- name = "lawyer PDA"
- default_cartridge = /obj/item/cartridge/lawyer
- insert_type = /obj/item/pen/fountain
- greyscale_colors = "#5B74A5#f7e062"
- ttone = "objection"
-
-/obj/item/pda/botanist
- name = "botanist PDA"
- greyscale_config = /datum/greyscale_config/pda/stripe_thick
- greyscale_colors = "#50E193#E26F41#71A7CA"
-
-/obj/item/pda/roboticist
- name = "roboticist PDA"
- greyscale_config = /datum/greyscale_config/pda/stripe_split
- greyscale_colors = "#484848#0099cc#d33725"
- default_cartridge = /obj/item/cartridge/roboticist
-
-/obj/item/pda/curator
- name = "curator PDA"
- greyscale_config = null
- greyscale_colors = null
- icon_state = "pda-library"
- icon_alert = "pda-r-library"
- icon_pai = "pai_overlay_library"
- icon_inactive_pai = "pai_off_overlay_library"
- insert_type = /obj/item/pen/fountain
- desc = "A portable microcomputer by Thinktronic Systems, LTD. This model is a WGW-11 series e-reader."
- note = "Congratulations, your station has chosen the Thinktronic 5290 WGW-11 Series E-reader and Personal Data Assistant!"
- silent = TRUE //Quiet in the library!
-
-/obj/item/pda/clear
- name = "clear PDA"
- icon_state = "pda-clear"
- greyscale_config = null
- greyscale_colors = null
- desc = "A portable microcomputer by Thinktronic Systems, LTD. This model is a special edition with a transparent case."
- note = "Congratulations, you have chosen the Thinktronic 5230 Personal Data Assistant Deluxe Special Max Turbo Limited Edition!"
-
-/obj/item/pda/cook
- name = "cook PDA"
- greyscale_colors = "#e2e2e2#a92323"
-
-/obj/item/pda/bar
- name = "bartender PDA"
- greyscale_colors = "#333333#c7c7c7"
- insert_type = /obj/item/pen/fountain
-
-/obj/item/pda/atmos
- name = "atmospherics PDA"
- default_cartridge = /obj/item/cartridge/atmos
- greyscale_config = /datum/greyscale_config/pda/stripe_thick
- greyscale_colors = "#ceca2b#00E5DA#727272"
-
-/obj/item/pda/chemist
- name = "chemist PDA"
- default_cartridge = /obj/item/cartridge/chemistry
- greyscale_config = /datum/greyscale_config/pda/stripe_thick
- greyscale_colors = "#e2e2e2#355FAC#ea6400"
-
-/obj/item/pda/geneticist
- name = "geneticist PDA"
- default_cartridge = /obj/item/cartridge/medical
- greyscale_config = /datum/greyscale_config/pda/stripe_split
- greyscale_colors = "#e2e2e2#000099#0097ca"
diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm
deleted file mode 100644
index 560fd492c96..00000000000
--- a/code/game/objects/items/devices/PDA/cart.dm
+++ /dev/null
@@ -1,648 +0,0 @@
-/obj/item/cartridge
- name = "generic cartridge"
- desc = "A data cartridge for portable microcomputers."
- icon = 'icons/obj/pda.dmi'
- icon_state = "cart"
- inhand_icon_state = "electronic"
- lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
- w_class = WEIGHT_CLASS_TINY
-
- var/obj/item/integrated_signaler/radio = null
-
- var/access = 0 //Bit flags for cartridge access
-
- var/list/bot_access = list()
-// Selection: SEC_BOT | ADVANCED_SEC_BOT | MULE_BOT | FLOOR_BOT | CLEAN_BOT | MED_BOT | FIRE_BOT | VIBE_BOT
-
- var/spam_enabled = 0 //Enables "Send to All" Option
-
- var/obj/item/pda/host_pda = null
- var/menu
- var/datum/data/record/active1 = null //General
- var/datum/data/record/active2 = null //Medical
- var/datum/data/record/active3 = null //Security
- var/obj/machinery/computer/monitor/powmonitor = null // Power Monitor
- var/list/powermonitors = list()
- var/message1 // used for status_displays
- var/message2
- var/list/stored_data = list()
- var/current_channel
-
- /// Weakref to the currently controlled bot
- var/datum/weakref/active_bot_ref
- var/list/botlist = list()
-
-/obj/item/cartridge/engineering
- name = "\improper Power-ON cartridge"
- icon_state = "cart-e"
- access = CART_ENGINE
- bot_access = list(
- FLOOR_BOT,
- )
-
-/obj/item/cartridge/atmos
- name = "\improper BreatheDeep cartridge"
- icon_state = "cart-a"
- access = CART_ATMOS
- bot_access = list(
- FLOOR_BOT,
- FIRE_BOT,
- )
-
-/obj/item/cartridge/medical
- name = "\improper Med-U cartridge"
- icon_state = "cart-m"
- access = CART_MEDICAL
- bot_access = list(
- MED_BOT,
- )
-
-/obj/item/cartridge/chemistry
- name = "\improper ChemWhiz cartridge"
- icon_state = "cart-chem"
- access = CART_REAGENT_SCANNER
- bot_access = list(
- MED_BOT,
- )
-
-/obj/item/cartridge/security
- name = "\improper R.O.B.U.S.T. cartridge"
- icon_state = "cart-s"
- access = CART_SECURITY | CART_MANIFEST
- bot_access = list(
- SEC_BOT,
- ADVANCED_SEC_BOT,
- )
-
-/obj/item/cartridge/detective
- name = "\improper D.E.T.E.C.T. cartridge"
- icon_state = "cart-s"
- access = CART_SECURITY | CART_MEDICAL | CART_MANIFEST
- bot_access = list(
- SEC_BOT,
- ADVANCED_SEC_BOT,
- )
-
-/obj/item/cartridge/lawyer
- name = "\improper P.R.O.V.E. cartridge"
- icon_state = "cart-s"
- access = CART_SECURITY
- spam_enabled = 1
-
-/obj/item/cartridge/roboticist
- name = "\improper B.O.O.P. Remote Control cartridge"
- desc = "Packed with heavy duty quad-bot interlink!"
- bot_access = list(
- FLOOR_BOT,
- CLEAN_BOT,
- MED_BOT,
- FIRE_BOT,
- VIBE_BOT,
- )
-
-/obj/item/cartridge/signal
- name = "generic signaler cartridge"
- desc = "A data cartridge with an integrated radio signaler module."
-
-/obj/item/cartridge/signal/ordnance
- name = "\improper Signal Ace 2 cartridge"
- desc = "Complete with integrated radio signaler!"
- icon_state = "cart-ord"
- access = CART_REAGENT_SCANNER | CART_ATMOS
-
-/obj/item/cartridge/signal/Initialize(mapload)
- . = ..()
- radio = new(src)
-
-/obj/item/cartridge/quartermaster
- name = "space parts & space vendors cartridge"
- desc = "Perfect for the Quartermaster on the go!"
- icon_state = "cart-q"
- access = CART_QUARTERMASTER
- bot_access = list(
- MULE_BOT,
- )
-
-/obj/item/cartridge/head
- name = "\improper Easy-Record DELUXE cartridge"
- icon_state = "cart-h"
- access = CART_MANIFEST | CART_STATUS_DISPLAY
-
-/obj/item/cartridge/hop
- name = "\improper HumanResources9001 cartridge"
- icon_state = "cart-h"
- access = CART_MANIFEST | CART_STATUS_DISPLAY | CART_SECURITY | CART_QUARTERMASTER
- bot_access = list(
- MULE_BOT,
- CLEAN_BOT,
- VIBE_BOT,
- )
-
-/obj/item/cartridge/hos
- name = "\improper R.O.B.U.S.T. DELUXE cartridge"
- icon_state = "cart-hos"
- access = CART_MANIFEST | CART_STATUS_DISPLAY | CART_SECURITY
- bot_access = list(
- SEC_BOT,
- ADVANCED_SEC_BOT,
- )
-
-
-/obj/item/cartridge/ce
- name = "\improper Power-On DELUXE cartridge"
- icon_state = "cart-ce"
- access = CART_MANIFEST | CART_STATUS_DISPLAY | CART_ENGINE | CART_ATMOS
- bot_access = list(
- FLOOR_BOT,
- FIRE_BOT,
- )
-
-/obj/item/cartridge/cmo
- name = "\improper Med-U DELUXE cartridge"
- icon_state = "cart-cmo"
- access = CART_MANIFEST | CART_STATUS_DISPLAY | CART_REAGENT_SCANNER | CART_MEDICAL
- bot_access = list(
- MED_BOT,
- )
-
-/obj/item/cartridge/rd
- name = "\improper Signal Ace DELUXE cartridge"
- icon_state = "cart-rd"
- access = CART_MANIFEST | CART_STATUS_DISPLAY | CART_REAGENT_SCANNER | CART_ATMOS
- bot_access = list(
- FLOOR_BOT,
- CLEAN_BOT,
- MED_BOT,
- FIRE_BOT,
- VIBE_BOT,
- )
-
-/obj/item/cartridge/rd/Initialize(mapload)
- . = ..()
- radio = new(src)
-
-/obj/item/cartridge/captain
- name = "\improper Value-PAK cartridge"
- desc = "Now with 350% more value!" //Give the Captain...EVERYTHING! (Except Clown and Mime ones)
- icon_state = "cart-c"
- access = ~(CART_CLOWN | CART_MIME)
- spam_enabled = 1
- bot_access = list(
- SEC_BOT,
- ADVANCED_SEC_BOT,
- MULE_BOT,
- FLOOR_BOT,
- CLEAN_BOT,
- MED_BOT,
- FIRE_BOT,
- VIBE_BOT,
- )
-
-/obj/item/cartridge/captain/Initialize(mapload)
- . = ..()
- radio = new(src)
-
-/obj/item/cartridge/proc/post_status(command, data1, data2)
-
- var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS)
-
- if(!frequency)
- return
-
- var/datum/signal/status_signal = new(list("command" = command))
- switch(command)
- if("message")
- status_signal.data["msg1"] = data1
- status_signal.data["msg2"] = data2
- if("alert")
- status_signal.data["picture_state"] = data1
-
- frequency.post_signal(src, status_signal)
-
-/obj/item/cartridge/proc/generate_menu(mob/user)
- if(!host_pda)
- return
- switch(host_pda.ui_mode)
- if(PDA_UI_SIGNALER)
- menu = "[PDAIMG(signaler)] Remote Signaling System "
-
- menu += {"
- Send Signal
- Frequency:
- -
- -
- [format_frequency(radio.frequency)]
- +
- +
-
- Code:
- -
- -
- [radio.code]
- +
- +
- "}
- if (PDA_UI_CREW_MANIFEST)
- menu = "[PDAIMG(notes)] Crew Manifest "
- menu += "[GLOB.data_core.get_manifest_html(monochrome=TRUE)] "
-
-
- if (PDA_UI_STATUS_DISPLAY)
- menu = "[PDAIMG(status)] Station Status Display Interlink "
-
- menu += "\[ Clear \] "
- menu += "\[ Shuttle ETA \] "
- menu += "\[ Message \]"
- menu += " "
- menu += "\[ Alert: None |"
- menu += " Red Alert |"
- menu += " Lockdown |"
- menu += " Biohazard \] "
-
- if (PDA_UI_POWER_MONITOR)
- menu = "[PDAIMG(power)] Power Monitors - Please select one "
- powmonitor = null
- powermonitors = list()
- var/powercount = 0
-
-
-
- var/turf/pda_turf = get_turf(src)
- for(var/obj/machinery/computer/monitor/pMon in GLOB.machines)
- if(pMon.machine_stat & (NOPOWER | BROKEN)) //check to make sure the computer is functional
- continue
- if(pda_turf.z != pMon.z) //and that we're on the same zlevel as the computer (lore: limited signal strength)
- continue
- if(pMon.is_secret_monitor) //make sure it isn't a secret one (ie located on a ruin), allowing people to metagame that the location exists
- continue
- powercount++
- powermonitors += pMon
-
-
- if(!powercount)
- menu += span_danger("No connection ")
- else
-
- menu += ""
- var/count = 0
- for(var/obj/machinery/computer/monitor/pMon in powermonitors)
- count++
- menu += "[pMon] - [get_area_name(pMon, TRUE)] "
-
- menu += " "
-
- if (PDA_UI_POWER_MONITOR_SELECTED)
- menu = "[PDAIMG(power)] Power Monitor "
- if(!powmonitor || !powmonitor.get_powernet())
- menu += span_danger("No connection ")
- else
- var/list/L = list()
- var/datum/powernet/connected_powernet = powmonitor.get_powernet()
- for(var/obj/machinery/power/terminal/term in connected_powernet.nodes)
- if(istype(term.master, /obj/machinery/power/apc))
- var/obj/machinery/power/apc/A = term.master
- L += A
-
- menu += "Location: [get_area_name(powmonitor, TRUE)] Total power: [display_power(connected_powernet.viewavail)] Total load: [display_power(connected_powernet.viewload)] "
-
- menu += ""
-
- if(L.len > 0)
- menu += "Area Eqp./Lgt./Env. Load Cell "
-
- var/list/S = list(" Off","AOff"," On", " AOn")
- var/list/chg = list("N","C","F")
- //Neither copytext nor copytext_char is appropriate here; neither 30 UTF-8 code units nor 30 code points equates to 30 columns of output.
- //Some glyphs are very tall or very wide while others are small or even take up no space at all.
- //Emojis can take modifiers which are many characters but render as only one glyph.
- //A proper solution here (as far as Unicode goes, maybe not ideal as far as markup goes, a table would be better)
- //would be to use [A.area.name]
- for(var/obj/machinery/power/apc/A in L)
- menu += copytext_char(add_trailing(A.area.name, 30, " "), 1, 30)
- menu += " [S[A.equipment+1]] [S[A.lighting+1]] [S[A.environ+1]] [add_leading(display_power(A.lastused_total), 6, " ")] [A.cell ? "[add_leading(round(A.cell.percent()), 3, " ")]% [chg[A.charging+1]]" : " N/C"] "
-
- menu += " "
-
- if (PDA_UI_MED_RECORDS)
- menu = "[PDAIMG(medical)] Medical Record List "
- if(GLOB.data_core.general)
- for(var/datum/data/record/R in sort_record(GLOB.data_core.general))
- menu += "[R.fields["id"]]: [R.fields["name"]] "
- menu += " "
- if(PDA_UI_MED_RECORD_SELECTED)
- menu = "[PDAIMG(medical)] Medical Record "
-
- if(active1 in GLOB.data_core.general)
- menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]] "
- menu += "Gender: [active1.fields["gender"]] "
- menu += "Age: [active1.fields["age"]] "
- menu += "Rank: [active1.fields["rank"]] "
- menu += "Fingerprint: [active1.fields["fingerprint"]] "
- menu += "Physical Status: [active1.fields["p_stat"]] "
- menu += "Mental Status: [active1.fields["m_stat"]] "
- else
- menu += "Record Lost! "
-
- menu += " "
-
- menu += "[PDAIMG(medical)] Medical Data "
- if(active2 in GLOB.data_core.medical)
- menu += "Blood Type: [active2.fields["blood_type"]] "
-
- menu += "Minor Disabilities: [active2.fields["mi_dis"]] "
- menu += "Details: [active2.fields["mi_dis_d"]] "
-
- menu += "Major Disabilities: [active2.fields["ma_dis"]] "
- menu += "Details: [active2.fields["ma_dis_d"]] "
-
- menu += "Allergies: [active2.fields["alg"]] "
- menu += "Details: [active2.fields["alg_d"]] "
-
- menu += "Current Diseases: [active2.fields["cdi"]] "
- menu += "Details: [active2.fields["cdi_d"]] "
-
- menu += "Important Notes: [active2.fields["notes"]] "
- else
- menu += "Record Lost! "
-
- menu += " "
- if (PDA_UI_SEC_RECORDS)
- menu = "[PDAIMG(cuffs)] Security Record List "
- if(GLOB.data_core.general)
- for (var/datum/data/record/R in sort_record(GLOB.data_core.general))
- menu += " [R.fields["id"]]: [R.fields["name"]] "
-
- menu += " "
- if(PDA_UI_SEC_RECORD_SELECTED)
- menu = "[PDAIMG(cuffs)] Security Record "
-
- if(active1 in GLOB.data_core.general)
- menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]] "
- menu += "Gender: [active1.fields["gender"]] "
- menu += "Age: [active1.fields["age"]] "
- menu += "Rank: [active1.fields["rank"]] "
- menu += "Fingerprint: [active1.fields["fingerprint"]] "
- menu += "Physical Status: [active1.fields["p_stat"]] "
- menu += "Mental Status: [active1.fields["m_stat"]] "
- else
- menu += "Record Lost! "
-
- menu += " "
-
- menu += "[PDAIMG(cuffs)] Security Data "
- if(active3 in GLOB.data_core.security)
- menu += "Criminal Status: [active3.fields["criminal"]] "
-
- menu += text(" \nCrimes:")
-
- menu +={"
-
- Crime
- Details
- Author
- Time Added
-
- "}
- for(var/datum/data/crime/c in active3.fields["crim"])
- menu += "[c.crimeName] "
- menu += "[c.crimeDetails] "
- menu += "[c.author] "
- menu += "[c.time] "
- menu += " "
- menu += "
"
- menu += " \nImportant Notes: "
- menu += "[active3.fields["notes"]]"
- else
- menu += "Record Lost! "
-
- menu += " "
-
- if (PDA_UI_SUPPLY_RECORDS)
- menu = "[PDAIMG(crate)] Supply Record Interlink "
-
- menu += "Supply shuttle "
- menu += "Location: "
- switch(SSshuttle.supply.mode)
- if(SHUTTLE_CALL)
- menu += "Moving to "
- if(!is_station_level(SSshuttle.supply.z))
- menu += "station"
- else
- menu += "CentCom"
- menu += " ([SSshuttle.supply.timeLeft(600)] Mins)"
- else
- menu += "At "
- if(!is_station_level(SSshuttle.supply.z))
- menu += "CentCom"
- else
- menu += "station"
- menu += " Current approved orders: "
- for(var/S in SSshuttle.shopping_list)
- var/datum/supply_order/SO = S
- menu += "#[SO.id] - [SO.pack.name] approved by [SO.orderer] [SO.reason ? "([SO.reason])":""] "
- menu += " "
-
- menu += "Current requests: "
- for(var/S in SSshuttle.request_list)
- var/datum/supply_order/SO = S
- menu += "#[SO.id] - [SO.pack.name] requested by [SO.orderer] "
- menu += " Upgrade NOW to Space Parts & Space Vendors PLUS for full remote order control and inventory management."
-
- if (PDA_UI_SILO_LOGS)
- menu = list("[PDAIMG(crate)] Ore Silo Logs ")
- if (GLOB.ore_silo_default)
- var/list/logs = GLOB.silo_access_logs[REF(GLOB.ore_silo_default)]
- var/len = LAZYLEN(logs)
- var/i = 0
- for(var/M in logs)
- if (++i > 30)
- menu += "(... older logs not shown ...)"
- break
- var/datum/ore_silo_log/entry = M
- menu += "[len - i]. [entry.formatted] "
- if(i == 0)
- menu += "Nothing!"
- else
- menu += "No ore silo detected! "
- menu = jointext(menu, "")
-
- if (PDA_UI_BOTS_ACCESS)
- menu = "[PDAIMG(medbot)] Bots Interlink "
- bot_control()
- if (PDA_UI_EMOJI_GUIDE)
- menu = "[PDAIMG(emoji)] Emoji Guidebook "
- var/static/list/emoji_icon_states
- var/static/emoji_table
- if(!emoji_table)
- var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/chat)
- var/list/collate = list("")
- for(var/emoji in sort_list(icon_states(icon(EMOJI_SET))))
- var/tag = sheet.icon_tag("emoji-[emoji]")
- collate += "[emoji] [tag] "
- collate += "
"
- emoji_table = collate.Join()
-
- menu += " To use an emoji in a pda message, refer to the guide and add \":\" around the emoji. Your PDA supports the following emoji: "
- menu += emoji_table
-
- return menu
-
-/obj/item/cartridge/Topic(href, href_list)
- ..()
-
- if(!usr.canUseTopic(src, !issilicon(usr)))
- usr.unset_machine()
- usr << browse(null, "window=pda")
- return
-
- switch(href_list["choice"])
- if("Medical Records")
- active1 = find_record("id", href_list["target"], GLOB.data_core.general)
- if(active1)
- active2 = find_record("id", href_list["target"], GLOB.data_core.medical)
- host_pda.ui_mode = PDA_UI_MED_RECORD_SELECTED
- if(!active2)
- active1 = null
-
- if("Security Records")
- active1 = find_record("id", href_list["target"], GLOB.data_core.general)
- if(active1)
- active3 = find_record("id", href_list["target"], GLOB.data_core.security)
- host_pda.ui_mode = PDA_UI_SEC_RECORD_SELECTED
- if(!active3)
- active1 = null
-
- if("Send Signal")
- INVOKE_ASYNC(radio, /obj/item/integrated_signaler.proc/send_activation)
-
- if("Signal Frequency")
- var/new_frequency = sanitize_frequency(radio.frequency + text2num(href_list["sfreq"]))
- radio.set_frequency(new_frequency)
-
- if("Signal Code")
- radio.code += text2num(href_list["scode"])
- radio.code = round(radio.code)
- radio.code = min(100, radio.code)
- radio.code = max(1, radio.code)
-
- if("Status")
- switch(href_list["statdisp"])
- if("message")
- post_status("message", message1, message2)
- if("alert")
- post_status("alert", href_list["alert"])
- if("setmsg1")
- message1 = reject_bad_text(input("Line 1", "Enter Message Text", message1) as text|null, 40)
- updateSelfDialog()
- if("setmsg2")
- message2 = reject_bad_text(input("Line 2", "Enter Message Text", message2) as text|null, 40)
- updateSelfDialog()
- else
- post_status(href_list["statdisp"])
- if("Power Select")
- var/pnum = text2num(href_list["target"])
- powmonitor = powermonitors[pnum]
- host_pda.ui_mode = PDA_UI_POWER_MONITOR_SELECTED
-
- if("Supply Orders")
- host_pda.ui_mode = PDA_UI_SUPPLY_RECORDS
-
- //emoji previews
- if(href_list["emoji"])
- var/parse = emoji_parse(":[href_list["emoji"]]:")
- to_chat(usr, parse)
-
- var/mob/living/simple_animal/bot/active_bot = active_bot_ref?.resolve()
-
- //Bot control section! Viciously ripped from radios for being laggy and terrible.
- if(href_list["op"])
- switch(href_list["op"])
-
- if("control")
- active_bot_ref = WEAKREF(locate(href_list["bot"]) in GLOB.bots_list)
- if("botlist")
- active_bot_ref = null
- if("summon") //Args are in the correct order, they are stated here just as an easy reminder.
- active_bot.bot_control("summon", usr, host_pda.GetAccess())
- else //Forward all other bot commands to the bot itself!
- active_bot.bot_control(href_list["op"], usr)
-
- if(href_list["mule"]) //MULEbots are special snowflakes, and need different args due to how they work.
- var/mob/living/simple_animal/bot/mulebot/mule = active_bot
- if (istype(mule))
- mule.bot_control(href_list["mule"], usr, pda=TRUE)
-
- if(!host_pda)
- return
- host_pda.attack_self(usr)
-
-
-/obj/item/cartridge/proc/bot_control()
- var/mob/living/simple_animal/bot/active_bot = active_bot_ref?.resolve()
- if(!active_bot)
- menu += "[PDAIMG(refresh)]Scan for active bots "
- var/turf/current_turf = get_turf(src)
- var/zlevel = current_turf.z
- var/botcount = 0
- for(var/B in GLOB.bots_list) //Git da botz
- var/mob/living/simple_animal/bot/Bot = B
- if(!(Bot.bot_mode_flags & BOT_MODE_ON) || Bot.z != zlevel || !(Bot.bot_mode_flags & BOT_MODE_REMOTE_ENABLED) || !(Bot.bot_type in bot_access)) //Only non-emagged bots on the same Z-level are detected!
- continue //Also, the PDA must have access to the bot type.
- menu += "[Bot.name] ([Bot.get_mode()]) "
- botcount++
- if(!botcount) //No bots at all? Lame.
- menu += "No bots found. "
- return menu
-
- menu += "[active_bot] Status: ([PDAIMG(refresh)]refresh ) "
- menu += "Model: [active_bot.bot_type] "
- menu += "Location: [get_area(active_bot)] "
- menu += "Mode: [active_bot.get_mode()]"
- if(active_bot.bot_mode_flags & BOT_MODE_PAI_CONTROLLABLE)
- menu += " pAI: "
- if(active_bot.paicard && active_bot.paicard.pai)
- menu += "[active_bot.paicard.pai.name]"
- if(active_bot.check_access(usr))
- menu += " (eject )"
- else
- menu += "none "
-
- //MULEs!
- if(active_bot.bot_type == MULE_BOT)
- var/mob/living/simple_animal/bot/mulebot/MULE = active_bot
- var/atom/Load = MULE.load
- menu += " Current Load: [ !Load ? "none " : "[Load.name] (unload )" ] "
- menu += "Destination: [MULE.destination ? MULE.destination : "None "] (set ) "
- menu += "Set ID: [MULE.suffix] Modify "
- menu += "Power: [MULE.cell ? MULE.cell.percent() : 0]% "
- menu += "Home: [!MULE.home_destination ? "none " : MULE.home_destination ] "
- menu += "Delivery Reporting: [MULE.report_delivery ? "(On )": "(Off )"] "
- menu += "Auto Return Home: [MULE.auto_return ? "(On )": "(Off )"] "
- menu += "Auto Pickup Crate: [MULE.auto_pickup ? "(On )": "(Off )"] " //Hue.
-
- menu += "\[Stop \] "
- menu += "\[Proceed \] "
- menu += "\[Return Home \] "
-
- else
- menu += " \[Stop Patrol \] " //patrolon
- menu += "\[Start Patrol \] " //patroloff
- menu += "\[Summon Bot \] " //summon
- menu += "Keep an ID inserted to upload access codes upon summoning."
-
- menu += "[PDAIMG(back)]Return to bot list "
-
- return menu
-
-//If the cartridge adds a special line to the top of the messaging app
-/obj/item/cartridge/proc/message_header()
- return ""
-
-//If the cartridge adds something to each potetial messaging target
-/obj/item/cartridge/proc/message_special(obj/item/pda/target)
- return ""
-
-//This is called for special abilities of cartridges
-/obj/item/cartridge/proc/special(mob/living/user, list/params)
diff --git a/code/game/objects/items/devices/PDA/radio.dm b/code/game/objects/items/devices/PDA/radio.dm
deleted file mode 100644
index 39d1a7b5223..00000000000
--- a/code/game/objects/items/devices/PDA/radio.dm
+++ /dev/null
@@ -1,38 +0,0 @@
-// Radio Cartridge, essentially a remote signaler with limited spectrum.
-/obj/item/integrated_signaler
- name = "\improper PDA radio module"
- desc = "An electronic radio system of Nanotrasen origin."
- icon = 'icons/obj/module.dmi'
- icon_state = "power_mod"
-
-/obj/item/integrated_signaler
- var/frequency = FREQ_SIGNALER
- var/code = DEFAULT_SIGNALER_CODE
- var/last_transmission
- var/datum/radio_frequency/radio_connection
-
-/obj/item/integrated_signaler/Destroy()
- radio_connection = null
- return ..()
-
-/obj/item/integrated_signaler/Initialize(mapload)
- . = ..()
- if (frequency < MIN_FREE_FREQ || frequency > MAX_FREE_FREQ)
- frequency = sanitize_frequency(frequency)
- set_frequency(frequency)
-
-/obj/item/integrated_signaler/proc/set_frequency(new_frequency)
- frequency = new_frequency
- radio_connection = SSradio.return_frequency(frequency)
-
-/obj/item/integrated_signaler/proc/send_activation()
- if(last_transmission && world.time < (last_transmission + 5))
- return
- last_transmission = world.time
-
- var/time = time2text(world.realtime,"hh:mm:ss")
- var/turf/T = get_turf(src)
- GLOB.lastsignalers.Add("[time] : [usr.key] used [src] @ location [AREACOORD(T)] : [format_frequency(frequency)]/[code]")
-
- var/datum/signal/signal = new(list("code" = code))
- radio_connection.post_signal(src, signal, filter = RADIO_SIGNALER)
diff --git a/code/game/objects/items/devices/PDA/virus_cart.dm b/code/game/objects/items/devices/PDA/virus_cart.dm
deleted file mode 100644
index fbaba93fad1..00000000000
--- a/code/game/objects/items/devices/PDA/virus_cart.dm
+++ /dev/null
@@ -1,146 +0,0 @@
-/obj/item/cartridge/virus
- name = "Generic Virus PDA cart"
- var/charges = 5
-
-/obj/item/cartridge/virus/proc/send_virus(obj/item/pda/target, mob/living/U)
- return
-
-/obj/item/cartridge/virus/message_header()
- return "[charges] viral files left. "
-
-/obj/item/cartridge/virus/message_special(obj/item/pda/target)
- if (!istype(loc, /obj/item/pda))
- return "" //Sanity check, this shouldn't be possible.
- return " (*Send Virus* )"
-
-/obj/item/cartridge/virus/special(mob/living/user, list/params)
- var/obj/item/pda/P = locate(params["target"]) in GLOB.PDAs //Leaving it alone in case it may do something useful, I guess.
- INVOKE_ASYNC(src, .proc/send_virus, P, user)
-
-/obj/item/cartridge/virus/clown
- name = "\improper Honkworks 5.0 cartridge"
- icon_state = "cart-clown"
- desc = "A data cartridge for portable microcomputers. It smells vaguely of bananas."
- access = CART_CLOWN
-
-/obj/item/cartridge/virus/clown/send_virus(obj/item/pda/target, mob/living/U)
- if(charges <= 0)
- to_chat(U, span_notice("Out of charges."))
- return
- if(!isnull(target) && !target.toff)
- charges--
- to_chat(U, span_notice("Virus Sent!"))
- target.honkamt = (rand(15,20))
- else
- to_chat(U, span_alert("PDA not found."))
-
-/obj/item/cartridge/virus/mime
- name = "\improper Gestur-O 1000 cartridge"
- icon_state = "cart-mi"
- access = CART_MIME
-
-/obj/item/cartridge/virus/mime/send_virus(obj/item/pda/target, mob/living/U)
- if(charges <= 0)
- to_chat(U, span_alert("Out of charges."))
- return
- if(!isnull(target) && !target.toff)
- charges--
- to_chat(U, span_notice("Virus Sent!"))
- target.silent = TRUE
- target.ttone = "silence"
- else
- to_chat(U, span_alert("PDA not found."))
-
-/obj/item/cartridge/virus/syndicate
- name = "\improper Detomatix cartridge"
- icon_state = "cart"
- charges = 6
-
-/obj/item/cartridge/virus/syndicate/send_virus(obj/item/pda/target, mob/living/user)
- if(charges <= 0)
- to_chat(user, span_notice("Out of charges."))
- return
- if(!target || target.toff)
- to_chat(user, span_alert("PDA not found."))
- return
-
- var/difficulty = 0
- if(target.cartridge)
- difficulty += bit_count(target.cartridge.access&(CART_MEDICAL | CART_SECURITY | CART_ENGINE | CART_CLOWN | CART_MANIFEST))
- if(target.cartridge.access & CART_MANIFEST)
- difficulty++ //if cartridge has manifest access it has extra snowflake difficulty
- if(SEND_SIGNAL(target, COMSIG_PDA_CHECK_DETONATE) & COMPONENT_PDA_NO_DETONATE || prob(difficulty * 15))
- user.show_message(span_danger("An error flashes on your [src]."), MSG_VISUAL)
- charges--
- return
-
- var/original_host = host_pda
- var/fakename = sanitize_name(tgui_input_text(user, "Enter a name for the rigged message.", "Forge Message", max_length = MAX_NAME_LEN), allow_numbers = TRUE)
- if(!fakename || host_pda != original_host || !user.canUseTopic(host_pda, BE_CLOSE))
- return
- var/fakejob = sanitize_name(tgui_input_text(user, "Enter a job for the rigged message.", "Forge Message", max_length = MAX_NAME_LEN), allow_numbers = TRUE)
- if(!fakejob || host_pda != original_host || !user.canUseTopic(host_pda, BE_CLOSE))
- return
- if(charges > 0 && host_pda.send_message(user, list(target), rigged = REF(user), fakename = fakename, fakejob = fakejob))
- charges--
- user.show_message(span_notice("Success!"), MSG_VISUAL)
- //Rigs the PDA to explode if they try to outsmart us by using the message function menu.
- var/reference = REF(src)
- ADD_TRAIT(target, TRAIT_PDA_CAN_EXPLODE, reference)
- ADD_TRAIT(target, TRAIT_PDA_MESSAGE_MENU_RIGGED, reference)
- addtimer(TRAIT_CALLBACK_REMOVE(target, TRAIT_PDA_MESSAGE_MENU_RIGGED, reference), 10 SECONDS)
-
-/obj/item/cartridge/virus/frame
- name = "\improper F.R.A.M.E. cartridge"
- icon_state = "cart"
- var/telecrystals = 0
- var/current_progression = 0
-
-/obj/item/cartridge/virus/frame/send_virus(obj/item/pda/target, mob/living/U)
- if(charges <= 0)
- to_chat(U, span_alert("Out of charges."))
- return
- if(!isnull(target) && !target.toff)
- charges--
- var/lock_code = "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
- to_chat(U, span_notice("Virus Sent! The unlock code to the target is: [lock_code]"))
- var/datum/component/uplink/hidden_uplink = target.GetComponent(/datum/component/uplink)
- if(!hidden_uplink)
- var/datum/mind/target_mind
- var/list/backup_players = list()
- for(var/datum/mind/player as anything in get_crewmember_minds())
- if(player.assigned_role?.title == target.id?.assignment)
- backup_players += player
- if(player.name == target.owner)
- target_mind = player
- break
- if(!target_mind)
- if(!length(backup_players))
- target_mind = U.mind
- else
- target_mind = pick(backup_players)
- hidden_uplink = target.AddComponent(/datum/component/uplink, target_mind, enabled = TRUE, starting_tc = telecrystals, has_progression = TRUE)
- hidden_uplink.uplink_handler.has_objectives = TRUE
- hidden_uplink.uplink_handler.owner = target_mind
- hidden_uplink.uplink_handler.can_take_objectives = FALSE
- hidden_uplink.uplink_handler.progression_points = min(SStraitor.current_global_progression, current_progression)
- hidden_uplink.uplink_handler.generate_objectives()
- SStraitor.register_uplink_handler(hidden_uplink.uplink_handler)
- else
- hidden_uplink.add_telecrystals(telecrystals)
- telecrystals = 0
- hidden_uplink.locked = FALSE
- hidden_uplink.active = TRUE
- else
- to_chat(U, span_alert("PDA not found."))
-
-/obj/item/cartridge/virus/frame/attackby(obj/item/I, mob/user, params)
- . = ..()
- if(istype(I, /obj/item/stack/telecrystal))
- if(!charges)
- to_chat(user, span_notice("[src] is out of charges, it's refusing to accept [I]."))
- return
- var/obj/item/stack/telecrystal/telecrystalStack = I
- telecrystals += telecrystalStack.amount
- to_chat(user, span_notice("You slot [telecrystalStack] into [src]. The next time it's used, it will also give telecrystals."))
- telecrystalStack.use(telecrystalStack.amount)
diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm
index 264fc639b8c..cbe37318adb 100644
--- a/code/game/objects/items/devices/scanners/health_analyzer.dm
+++ b/code/game/objects/items/devices/scanners/health_analyzer.dm
@@ -113,7 +113,7 @@
return CONTEXTUAL_SCREENTIP_SET
// Used by the PDA medical scanner too
-/proc/healthscan(mob/user, mob/living/target, mode = SCANNER_VERBOSE, advanced = FALSE)
+/proc/healthscan(mob/user, mob/living/target, mode = SCANNER_VERBOSE, advanced = FALSE, tochat = TRUE)
if(user.incapacitated())
return
@@ -386,7 +386,11 @@
render_list += "Detected cybernetic modifications: \n"
render_list += "[cyberimp_detect] \n"
// we handled the last so we don't need handholding
- to_chat(user, examine_block(jointext(render_list, "")), trailing_newline = FALSE, type = MESSAGE_TYPE_INFO) //SKYRAT EDIT CHANGE
+
+ if(tochat)
+ to_chat(user, jointext(render_list, ""), trailing_newline = FALSE, type = MESSAGE_TYPE_INFO)
+ else
+ return(jointext(render_list, ""))
/proc/chemscan(mob/living/user, mob/living/target)
if(user.incapacitated())
diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm
index e3df2a76126..80333102109 100644
--- a/code/game/objects/items/storage/backpack.dm
+++ b/code/game/objects/items/storage/backpack.dm
@@ -677,7 +677,7 @@
STR.silent = TRUE
/obj/item/storage/backpack/duffelbag/clown/syndie/PopulateContents()
- new /obj/item/pda/clown(src)
+ new /obj/item/modular_computer/tablet/pda/clown(src)
new /obj/item/clothing/under/rank/civilian/clown(src)
new /obj/item/clothing/shoes/clown_shoes(src)
new /obj/item/clothing/mask/gas/clown_hat(src)
diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm
index aeb55acd63b..02afc635cc3 100644
--- a/code/game/objects/items/storage/boxes.dm
+++ b/code/game/objects/items/storage/boxes.dm
@@ -561,15 +561,15 @@
/obj/item/storage/box/pdas/PopulateContents()
for(var/i in 1 to 4)
- new /obj/item/pda(src)
- new /obj/item/cartridge/head(src)
+ new /obj/item/modular_computer/tablet/pda(src)
+ new /obj/item/computer_hardware/hard_drive/role/head(src)
- var/newcart = pick( /obj/item/cartridge/engineering,
- /obj/item/cartridge/security,
- /obj/item/cartridge/medical,
- /obj/item/cartridge/signal/ordnance,
- /obj/item/cartridge/quartermaster)
- new newcart(src)
+ var/new_disk = pick( /obj/item/computer_hardware/hard_drive/role/engineering,
+ /obj/item/computer_hardware/hard_drive/role/security,
+ /obj/item/computer_hardware/hard_drive/role/medical,
+ /obj/item/computer_hardware/hard_drive/role/signal/ordnance,
+ /obj/item/computer_hardware/hard_drive/role/quartermaster)
+ new new_disk(src)
/obj/item/storage/box/silver_ids
name = "box of spare silver IDs"
@@ -603,9 +603,9 @@
illustration = "pda"
/obj/item/storage/box/seccarts/PopulateContents()
- new /obj/item/cartridge/detective(src)
+ new /obj/item/computer_hardware/hard_drive/role/detective(src)
for(var/i in 1 to 6)
- new /obj/item/cartridge/security(src)
+ new /obj/item/computer_hardware/hard_drive/role/security(src)
/obj/item/storage/box/firingpins
name = "box of standard firing pins"
@@ -1172,7 +1172,7 @@
/obj/item/storage/box/debugtools/PopulateContents()
var/static/items_inside = list(
/obj/item/flashlight/emp/debug=1,\
- /obj/item/pda=1,\
+ /obj/item/modular_computer/tablet/pda=1,\
/obj/item/modular_computer/tablet/preset/advanced=1,\
/obj/item/geiger_counter=1,\
/obj/item/construction/rcd/combat/admin=1,\
diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm
index 912881dc03a..603a158617e 100644
--- a/code/game/objects/items/storage/uplink_kits.dm
+++ b/code/game/objects/items/storage/uplink_kits.dm
@@ -128,7 +128,7 @@
/obj/item/storage/backpack/duffelbag/syndie/sabotage
new /obj/item/camera_bug(src)
new /obj/item/sbeacondrop/powersink(src)
- new /obj/item/cartridge/virus/syndicate(src)
+ new /obj/item/computer_hardware/hard_drive/role/virus/deto(src)
new /obj/item/storage/toolbox/syndicate(src)
new /obj/item/pizzabox/bomb(src)
new /obj/item/storage/box/syndie_kit/emp(src)
@@ -475,7 +475,7 @@
new /obj/item/storage/belt/chameleon(src)
new /obj/item/radio/headset/chameleon(src)
new /obj/item/stamp/chameleon(src)
- new /obj/item/pda/chameleon(src)
+ new /obj/item/modular_computer/tablet/pda/chameleon(src)
//5*(2*4) = 5*8 = 45, 45 damage if you hit one person with all 5 stars.
//Not counting the damage it will do while embedded (2*4 = 8, at 15% chance)
@@ -515,7 +515,7 @@
new /obj/item/radio/headset/headset_cent/empty(src)
new /obj/item/clothing/glasses/sunglasses(src)
new /obj/item/storage/backpack/satchel(src)
- new /obj/item/pda/heads(src)
+ new /obj/item/modular_computer/tablet/pda/heads(src)
new /obj/item/clipboard(src)
/obj/item/storage/box/syndie_kit/chameleon/broken/PopulateContents()
@@ -531,7 +531,7 @@
new /obj/item/storage/belt/chameleon/broken(src)
new /obj/item/radio/headset/chameleon/broken(src)
new /obj/item/stamp/chameleon/broken(src)
- new /obj/item/pda/chameleon/broken(src)
+ new /obj/item/modular_computer/tablet/pda/chameleon/broken(src)
// No chameleon laser, they can't randomise for //REASONS//
/obj/item/storage/box/syndie_kit/bee_grenades
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
index ea54eb9b7c6..d8468c4d22b 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
@@ -7,7 +7,7 @@
..()
new /obj/item/storage/bag/garment/engineering_chief (src)
- new /obj/item/cartridge/ce(src)
+ new /obj/item/computer_hardware/hard_drive/role/ce(src)
new /obj/item/radio/headset/heads/ce(src)
new /obj/item/megaphone/command(src)
new /obj/item/areaeditor/blueprints(src)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
index b645b25e72f..816d4819128 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
@@ -77,7 +77,7 @@
new /obj/item/clothing/suit/bio_suit/cmo(src)
new /obj/item/clothing/head/bio_hood/cmo(src)
new /obj/item/storage/bag/garment/chief_medical(src)
- new /obj/item/cartridge/cmo(src)
+ new /obj/item/computer_hardware/hard_drive/role/cmo(src)
new /obj/item/radio/headset/heads/cmo(src)
new /obj/item/megaphone/command(src)
new /obj/item/defibrillator/compact/loaded(src)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm
index c0bb728f877..4a21d6785fd 100755
--- a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm
@@ -9,7 +9,7 @@
new /obj/item/clothing/suit/bio_suit/scientist(src)
new /obj/item/clothing/head/bio_hood/scientist(src)
new /obj/item/storage/bag/garment/research_director(src)
- new /obj/item/cartridge/rd(src)
+ new /obj/item/computer_hardware/hard_drive/role/rd(src)
new /obj/item/radio/headset/heads/rd(src)
new /obj/item/megaphone/command(src)
new /obj/item/storage/lockbox/medal/sci(src)
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 759b95294bc..c99b2c507bb 100755
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -12,7 +12,7 @@
new /obj/item/clothing/neck/petcollar(src)
new /obj/item/pet_carrier(src)
new /obj/item/storage/bag/garment/captain(src)
- new /obj/item/cartridge/captain(src)
+ new /obj/item/computer_hardware/hard_drive/role/captain(src)
new /obj/item/storage/box/silver_ids(src)
new /obj/item/radio/headset/heads/captain/alt(src)
new /obj/item/radio/headset/heads/captain(src)
@@ -31,7 +31,7 @@
..()
new /obj/item/storage/bag/garment/hop(src)
new /obj/item/storage/lockbox/medal/service(src)
- new /obj/item/cartridge/hop(src)
+ new /obj/item/computer_hardware/hard_drive/role/hop(src)
new /obj/item/radio/headset/heads/hop(src)
new /obj/item/storage/box/ids(src)
new /obj/item/storage/box/ids(src)
@@ -53,7 +53,7 @@
/obj/structure/closet/secure_closet/hos/PopulateContents()
..()
- new /obj/item/cartridge/hos(src)
+ new /obj/item/computer_hardware/hard_drive/role/hos(src)
new /obj/item/radio/headset/heads/hos(src)
new /obj/item/storage/bag/garment/hos(src)
new /obj/item/storage/lockbox/medal/sec(src)
diff --git a/code/game/objects/structures/crates_lockers/closets/syndicate.dm b/code/game/objects/structures/crates_lockers/closets/syndicate.dm
index 5d5d7da9027..a42797a7aa1 100644
--- a/code/game/objects/structures/crates_lockers/closets/syndicate.dm
+++ b/code/game/objects/structures/crates_lockers/closets/syndicate.dm
@@ -28,7 +28,7 @@
new /obj/item/storage/box/flashbangs(src)
new /obj/item/storage/box/teargas(src)
new /obj/item/storage/backpack/duffelbag/syndie/med(src)
- new /obj/item/pda/syndicate(src)
+ new /obj/item/modular_computer/tablet/pda/syndicate(src)
/obj/structure/closet/syndicate/resources
desc = "An old, dusty locker."
diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm
index f77c4cbd697..3a253cc39cb 100644
--- a/code/game/objects/structures/displaycase.dm
+++ b/code/game/objects/structures/displaycase.dm
@@ -533,7 +533,7 @@
playsound(src, 'sound/machines/click.ogg', 20, TRUE)
toggle_lock()
return
- if(istype(I, /obj/item/pda))
+ if(istype(I, /obj/item/modular_computer))
return TRUE
SStgui.update_uis(src)
. = ..()
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 5aa29a80ad3..9afe0e1d2dd 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -139,10 +139,12 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
id.update_icon()
if(worn)
- if(istype(worn, /obj/item/pda))
- var/obj/item/pda/PDA = worn
- PDA.id = id
- id.forceMove(PDA)
+ if(istype(worn, /obj/item/modular_computer/tablet/pda))
+ var/obj/item/modular_computer/tablet/pda/PDA = worn
+ var/obj/item/computer_hardware/card_slot/card = PDA.all_components[MC_CARD]
+
+ if(card)
+ card.try_insert(id)
else if(istype(worn, /obj/item/storage/wallet))
var/obj/item/storage/wallet/W = worn
W.front_id = id
diff --git a/code/modules/cargo/markets/market_items/misc.dm b/code/modules/cargo/markets/market_items/misc.dm
index b4f68ad7b64..e63377d5ae3 100644
--- a/code/modules/cargo/markets/market_items/misc.dm
+++ b/code/modules/cargo/markets/market_items/misc.dm
@@ -4,7 +4,7 @@
/datum/market_item/misc/Clear_PDA
name = "Clear PDA"
desc = "Show off your style with this limited edition clear PDA!."
- item = /obj/item/pda/clear
+ item = /obj/item/modular_computer/tablet/pda/clear
price_min = CARGO_CRATE_VALUE * 1.25
price_max = CARGO_CRATE_VALUE *3
diff --git a/code/modules/client/preferences/pda.dm b/code/modules/client/preferences/pda.dm
deleted file mode 100644
index f9fb66c0a6e..00000000000
--- a/code/modules/client/preferences/pda.dm
+++ /dev/null
@@ -1,41 +0,0 @@
-/// The color of a PDA
-/datum/preference/color/pda_color
- category = PREFERENCE_CATEGORY_NON_CONTEXTUAL // SKYRAT EDIT - Per-character PDA settings - ORIGINAL: category = PREFERENCE_CATEGORY_GAME_PREFERENCES
- savefile_key = "pda_color"
- savefile_identifier = PREFERENCE_CHARACTER // SKYRAT EDIT - Per-character PDA settings - ORIGINAL: savefile_identifier = PREFERENCE_PLAYER
-
-/datum/preference/color/pda_color/create_default_value()
- return COLOR_OLIVE
-
-// SKYRAT EDIT ADDITION BEGIN -- CUSTOMIZATION
-/datum/preference/color/pda_color/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences)
- return FALSE
-// SKYRAT EDIT END
-
-/// The visual style of a PDA
-/datum/preference/choiced/pda_style
- category = PREFERENCE_CATEGORY_NON_CONTEXTUAL // SKYRAT EDIT - Per-character PDA settings - ORIGINAL: category = PREFERENCE_CATEGORY_GAME_PREFERENCES
- savefile_key = "pda_style"
- savefile_identifier = PREFERENCE_CHARACTER // SKYRAT EDIT - Per-character PDA settings - ORIGINAL: savefile_identifier = PREFERENCE_PLAYER
-
-/datum/preference/choiced/pda_style/init_possible_values()
- return GLOB.pda_styles
-
-// SKYRAT EDIT ADDITION BEGIN -- Per-character PDA settings
-/datum/preference/choiced/pda_style/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences)
- return FALSE
-// SKYRAT EDIT END
-
-// SKYRAT EDIT ADDITION BEGIN -- Per-character PDA settings
-/// The thing your PDA says
-/datum/preference/text/pda_ringer
- category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
- savefile_key = "pda_ringer"
- savefile_identifier = PREFERENCE_CHARACTER
-
-/datum/preference/text/pda_ringer/create_default_value()
- return "beep"
-
-/datum/preference/text/pda_ringer/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences)
- return FALSE
-// SKYRAT EDIT END
diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm
index 54131e3928b..fac24bb601c 100644
--- a/code/modules/clothing/chameleon.dm
+++ b/code/modules/clothing/chameleon.dm
@@ -350,18 +350,17 @@
agent_card.update_label()
agent_card.update_icon()
-/datum/action/item_action/chameleon/change/pda/update_item(obj/item/picked_item)
+/datum/action/item_action/chameleon/change/tablet/update_item(obj/item/picked_item)
..()
- var/obj/item/pda/agent_pda = target
+ var/obj/item/modular_computer/tablet/pda/agent_pda = target
if(istype(agent_pda))
- agent_pda.update_label()
agent_pda.update_appearance()
-/datum/action/item_action/chameleon/change/pda/apply_job_data(datum/job/job_datum)
+/datum/action/item_action/chameleon/change/tablet/apply_job_data(datum/job/job_datum)
..()
- var/obj/item/pda/agent_pda = target
+ var/obj/item/modular_computer/tablet/pda/agent_pda = target
if(istype(agent_pda) && istype(job_datum))
- agent_pda.ownjob = job_datum.title
+ agent_pda.saved_job = job_datum.title
/obj/item/clothing/under/chameleon
@@ -720,25 +719,25 @@
. = ..()
chameleon_action.emp_randomise(INFINITY)
-/obj/item/pda/chameleon
- name = "PDA"
- var/datum/action/item_action/chameleon/change/pda/chameleon_action
+/obj/item/modular_computer/tablet/pda/chameleon
+ name = "tablet"
+ var/datum/action/item_action/chameleon/change/tablet/chameleon_action
-/obj/item/pda/chameleon/Initialize(mapload)
+/obj/item/modular_computer/tablet/pda/chameleon/Initialize(mapload)
. = ..()
chameleon_action = new(src)
- chameleon_action.chameleon_type = /obj/item/pda
- chameleon_action.chameleon_name = "PDA"
- chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/pda/heads, /obj/item/pda/ai, /obj/item/pda/ai/pai), only_root_path = TRUE)
+ chameleon_action.chameleon_type = /obj/item/modular_computer/tablet/pda
+ chameleon_action.chameleon_name = "tablet"
+ chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/modular_computer/tablet/pda/heads), only_root_path = TRUE)
chameleon_action.initialize_disguises()
-/obj/item/pda/chameleon/emp_act(severity)
+/obj/item/modular_computer/tablet/pda/chameleon/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
chameleon_action.emp_randomise()
-/obj/item/pda/chameleon/broken/Initialize(mapload)
+/obj/item/modular_computer/tablet/pda/chameleon/broken/Initialize(mapload)
. = ..()
chameleon_action.emp_randomise(INFINITY)
diff --git a/code/modules/clothing/outfits/ert.dm b/code/modules/clothing/outfits/ert.dm
index e0019b2106b..92e5d40e9fe 100644
--- a/code/modules/clothing/outfits/ert.dm
+++ b/code/modules/clothing/outfits/ert.dm
@@ -197,17 +197,16 @@
gloves = /obj/item/clothing/gloves/color/black
shoes = /obj/item/clothing/shoes/sneakers/black
l_pocket = /obj/item/pen
- r_pocket = /obj/item/pda/heads
+ r_pocket = /obj/item/modular_computer/tablet/pda/heads
l_hand = /obj/item/clipboard
/datum/outfit/centcom/centcom_official/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
if(visualsOnly)
return
- var/obj/item/pda/heads/pda = H.r_store
- pda.owner = H.real_name
- pda.ownjob = "CentCom Official"
- pda.update_label()
+ var/obj/item/modular_computer/tablet/pda/heads/pda = H.r_store
+ pda.saved_identification = H.real_name
+ pda.saved_job = "CentCom Official"
var/obj/item/card/id/W = H.wear_id
W.registered_name = H.real_name
diff --git a/code/modules/clothing/outfits/standard.dm b/code/modules/clothing/outfits/standard.dm
index e9dce405f70..095d25cf0c8 100644
--- a/code/modules/clothing/outfits/standard.dm
+++ b/code/modules/clothing/outfits/standard.dm
@@ -240,7 +240,7 @@
id = /obj/item/card/id/advanced/chameleon/black
id_trim = /datum/id_trim/reaper_assassin
uniform = /obj/item/clothing/under/suit/black
- belt = /obj/item/pda/heads
+ belt = /obj/item/modular_computer/tablet/pda/heads
ears = /obj/item/radio/headset
gloves = /obj/item/clothing/gloves/color/black
glasses = /obj/item/clothing/glasses/sunglasses
@@ -266,10 +266,9 @@
SEND_SIGNAL(sec_briefcase, COMSIG_TRY_STORAGE_INSERT, new /obj/item/ammo_box/a357, null, TRUE, TRUE)
SEND_SIGNAL(sec_briefcase, COMSIG_TRY_STORAGE_INSERT, new /obj/item/grenade/c4/x4, null, TRUE, TRUE)
- var/obj/item/pda/heads/pda = H.belt
- pda.owner = H.real_name
- pda.ownjob = "Reaper"
- pda.update_label()
+ var/obj/item/modular_computer/tablet/pda/heads/pda = H.belt
+ pda.saved_identification = H.real_name
+ pda.saved_job = "Reaper"
var/obj/item/card/id/W = H.wear_id
W.registered_name = H.real_name
diff --git a/code/modules/clothing/suits/wintercoats.dm b/code/modules/clothing/suits/wintercoats.dm
index 180e3f11b85..c6f1304ad83 100644
--- a/code/modules/clothing/suits/wintercoats.dm
+++ b/code/modules/clothing/suits/wintercoats.dm
@@ -17,8 +17,7 @@
allowed += list(
/obj/item/flashlight,
/obj/item/lighter,
- /obj/item/modular_computer/tablet,
- /obj/item/pda,
+ /obj/item/modular_computer/tablet/pda,
/obj/item/radio,
/obj/item/storage/fancy/cigarettes,
/obj/item/tank/internals/emergency_oxygen,
diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm
index 957e39b6140..ee3e09d4669 100644
--- a/code/modules/jobs/job_types/_job.dm
+++ b/code/modules/jobs/job_types/_job.dm
@@ -179,6 +179,12 @@
for(var/i in roundstart_experience)
experiencer.mind.adjust_experience(i, roundstart_experience[i], TRUE)
+ var/obj/item/modular_computer/tablet/pda/PDA = spawned.get_item_by_slot(ITEM_SLOT_BELT)
+ if(istype(PDA))
+ var/obj/item/computer_hardware/identifier/id = PDA.all_components[MC_IDENTIFY]
+
+ if(id)
+ id.UpdateDisplay()
/datum/job/proc/announce_job(mob/living/joining_mob, job_title) // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - Original: /datum/job/proc/announce_job(mob/living/joining_mob)
if(head_announce)
@@ -253,7 +259,7 @@
uniform = /obj/item/clothing/under/color/grey
id = /obj/item/card/id/advanced
ears = /obj/item/radio/headset
- belt = /obj/item/pda
+ belt = /obj/item/modular_computer/tablet/pda
back = /obj/item/storage/backpack
shoes = /obj/item/clothing/shoes/sneakers/black
box = /obj/item/storage/box/survival
@@ -321,11 +327,10 @@
B.bank_cards += C
H.sec_hud_set_ID()
- var/obj/item/pda/PDA = H.get_item_by_slot(pda_slot)
+ var/obj/item/modular_computer/tablet/pda/PDA = H.get_item_by_slot(pda_slot)
if(istype(PDA))
- PDA.owner = H.real_name
- PDA.ownjob = J.title
- PDA.update_label()
+ PDA.saved_identification = C.registered_name
+ PDA.saved_job = C.assignment
/datum/outfit/job/get_chameleon_disguise_info()
diff --git a/code/modules/jobs/job_types/atmospheric_technician.dm b/code/modules/jobs/job_types/atmospheric_technician.dm
index 894cd1c708d..c0a871b6dd1 100644
--- a/code/modules/jobs/job_types/atmospheric_technician.dm
+++ b/code/modules/jobs/job_types/atmospheric_technician.dm
@@ -44,12 +44,9 @@
id_trim = /datum/id_trim/job/atmospheric_technician
uniform = /obj/item/clothing/under/rank/engineering/atmospheric_technician
- backpack_contents = list(
- /obj/item/modular_computer/tablet/preset/advanced/atmos = 1,
- )
belt = /obj/item/storage/belt/utility/atmostech
ears = /obj/item/radio/headset/headset_eng
- l_pocket = /obj/item/pda/atmos
+ l_pocket = /obj/item/modular_computer/tablet/pda/atmos
r_pocket = /obj/item/analyzer
backpack = /obj/item/storage/backpack/industrial
diff --git a/code/modules/jobs/job_types/bartender.dm b/code/modules/jobs/job_types/bartender.dm
index 03eef61755e..d546411c0f4 100644
--- a/code/modules/jobs/job_types/bartender.dm
+++ b/code/modules/jobs/job_types/bartender.dm
@@ -53,7 +53,7 @@
backpack_contents = list(
/obj/item/storage/box/beanbag = 1,
)
- belt = /obj/item/pda/bar
+ belt = /obj/item/modular_computer/tablet/pda/bar
ears = /obj/item/radio/headset/headset_srv
glasses = /obj/item/clothing/glasses/sunglasses/reagent
shoes = /obj/item/clothing/shoes/laceup
diff --git a/code/modules/jobs/job_types/botanist.dm b/code/modules/jobs/job_types/botanist.dm
index 43893211cb6..451db5322a6 100644
--- a/code/modules/jobs/job_types/botanist.dm
+++ b/code/modules/jobs/job_types/botanist.dm
@@ -42,7 +42,7 @@
uniform = /obj/item/clothing/under/rank/civilian/hydroponics
suit = /obj/item/clothing/suit/apron
suit_store = /obj/item/plant_analyzer
- belt = /obj/item/pda/botanist
+ belt = /obj/item/modular_computer/tablet/pda/botanist
ears = /obj/item/radio/headset/headset_srv
gloves = /obj/item/clothing/gloves/botanic_leather
diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm
index d32e0bc75fe..f49499c0b80 100755
--- a/code/modules/jobs/job_types/captain.dm
+++ b/code/modules/jobs/job_types/captain.dm
@@ -62,7 +62,7 @@
/obj/item/melee/baton/telescopic = 1,
/obj/item/station_charter = 1,
)
- belt = /obj/item/pda/captain
+ belt = /obj/item/modular_computer/tablet/pda/captain
ears = /obj/item/radio/headset/heads/captain/alt
glasses = /obj/item/clothing/glasses/sunglasses
gloves = /obj/item/clothing/gloves/color/captain
diff --git a/code/modules/jobs/job_types/cargo_technician.dm b/code/modules/jobs/job_types/cargo_technician.dm
index 2c424c1f2be..9c477c3d028 100644
--- a/code/modules/jobs/job_types/cargo_technician.dm
+++ b/code/modules/jobs/job_types/cargo_technician.dm
@@ -42,10 +42,7 @@
id_trim = /datum/id_trim/job/cargo_technician
uniform = /obj/item/clothing/under/rank/cargo/tech
- backpack_contents = list(
- /obj/item/modular_computer/tablet/preset/cargo = 1,
- )
- belt = /obj/item/pda/cargo
+ belt = /obj/item/modular_computer/tablet/pda/cargo
ears = /obj/item/radio/headset/headset_cargo
l_hand = /obj/item/export_scanner
diff --git a/code/modules/jobs/job_types/chaplain.dm b/code/modules/jobs/job_types/chaplain.dm
index ef0f86c7faa..81ad1ecc481 100644
--- a/code/modules/jobs/job_types/chaplain.dm
+++ b/code/modules/jobs/job_types/chaplain.dm
@@ -120,7 +120,7 @@
/obj/item/camera/spooky = 1,
/obj/item/stamp/chap = 1,
)
- belt = /obj/item/pda/chaplain
+ belt = /obj/item/modular_computer/tablet/pda/chaplain
ears = /obj/item/radio/headset/headset_srv
backpack = /obj/item/storage/backpack/cultpack
diff --git a/code/modules/jobs/job_types/chemist.dm b/code/modules/jobs/job_types/chemist.dm
index 0670eea63c6..859e1394e12 100644
--- a/code/modules/jobs/job_types/chemist.dm
+++ b/code/modules/jobs/job_types/chemist.dm
@@ -45,7 +45,7 @@
id_trim = /datum/id_trim/job/chemist
uniform = /obj/item/clothing/under/rank/medical/chemist
suit = /obj/item/clothing/suit/toggle/labcoat/chemist
- belt = /obj/item/pda/chemist
+ belt = /obj/item/modular_computer/tablet/pda/chemist
ears = /obj/item/radio/headset/headset_med
glasses = /obj/item/clothing/glasses/science
shoes = /obj/item/clothing/shoes/sneakers/white
diff --git a/code/modules/jobs/job_types/chief_engineer.dm b/code/modules/jobs/job_types/chief_engineer.dm
index cdf6117c44d..03df4c57607 100644
--- a/code/modules/jobs/job_types/chief_engineer.dm
+++ b/code/modules/jobs/job_types/chief_engineer.dm
@@ -61,14 +61,13 @@
uniform = /obj/item/clothing/under/rank/engineering/chief_engineer
backpack_contents = list(
/obj/item/melee/baton/telescopic = 1,
- /obj/item/modular_computer/tablet/preset/advanced/command/engineering = 1,
)
belt = /obj/item/storage/belt/utility/chief/full
ears = /obj/item/radio/headset/heads/ce
gloves = /obj/item/clothing/gloves/color/black
head = /obj/item/clothing/head/hardhat/white
shoes = /obj/item/clothing/shoes/sneakers/brown
- l_pocket = /obj/item/pda/heads/ce
+ l_pocket = /obj/item/modular_computer/tablet/pda/heads/ce
backpack = /obj/item/storage/backpack/industrial
satchel = /obj/item/storage/backpack/satchel/eng
diff --git a/code/modules/jobs/job_types/chief_medical_officer.dm b/code/modules/jobs/job_types/chief_medical_officer.dm
index 4da3e2f6abb..b9065156fa3 100644
--- a/code/modules/jobs/job_types/chief_medical_officer.dm
+++ b/code/modules/jobs/job_types/chief_medical_officer.dm
@@ -60,9 +60,8 @@
suit_store = /obj/item/flashlight/pen/paramedic
backpack_contents = list(
/obj/item/melee/baton/telescopic = 1,
- /obj/item/modular_computer/tablet/preset/advanced/command = 1,
)
- belt = /obj/item/pda/heads/cmo
+ belt = /obj/item/modular_computer/tablet/pda/heads/cmo
ears = /obj/item/radio/headset/heads/cmo
shoes = /obj/item/clothing/shoes/sneakers/blue
l_pocket = /obj/item/pinpointer/crew
diff --git a/code/modules/jobs/job_types/clown.dm b/code/modules/jobs/job_types/clown.dm
index d8ca846f6bb..86491e71e02 100644
--- a/code/modules/jobs/job_types/clown.dm
+++ b/code/modules/jobs/job_types/clown.dm
@@ -56,7 +56,7 @@
/obj/item/food/grown/banana = 1,
/obj/item/instrument/bikehorn = 1,
)
- belt = /obj/item/pda/clown
+ belt = /obj/item/modular_computer/tablet/pda/clown
ears = /obj/item/radio/headset/headset_srv
shoes = /obj/item/clothing/shoes/clown_shoes
mask = /obj/item/clothing/mask/gas/clown_hat
@@ -104,7 +104,7 @@
/datum/outfit/job/clown_free
name = "Clown"
- belt = /obj/item/pda/clown
+ belt = /obj/item/modular_computer/tablet/pda/clown
ears = /obj/item/radio/headset/headset_srv
uniform = /obj/item/clothing/under/rank/civilian/clown
shoes = /obj/item/clothing/shoes/clown_shoes
diff --git a/code/modules/jobs/job_types/cook.dm b/code/modules/jobs/job_types/cook.dm
index 8cbeada5cc4..b6d78e54d03 100644
--- a/code/modules/jobs/job_types/cook.dm
+++ b/code/modules/jobs/job_types/cook.dm
@@ -94,7 +94,7 @@
/obj/item/choice_beacon/ingredient = 1,
/obj/item/sharpener = 1,
)
- belt = /obj/item/pda/cook
+ belt = /obj/item/modular_computer/tablet/pda/cook
ears = /obj/item/radio/headset/headset_srv
head = /obj/item/clothing/head/chefhat
mask = /obj/item/clothing/mask/fakemoustache/italian
diff --git a/code/modules/jobs/job_types/curator.dm b/code/modules/jobs/job_types/curator.dm
index 297444e9897..bba6b3489d2 100644
--- a/code/modules/jobs/job_types/curator.dm
+++ b/code/modules/jobs/job_types/curator.dm
@@ -35,12 +35,11 @@
id_trim = /datum/id_trim/job/curator
uniform = /obj/item/clothing/under/rank/civilian/curator
backpack_contents = list(
- /obj/item/modular_computer/tablet/preset/advanced/curator = 1,
/obj/item/barcodescanner = 1,
/obj/item/choice_beacon/hero = 1,
/obj/item/glassblowing/magnifying_glass, //SKYRAT EDIT: Magnifying Glass
)
- belt = /obj/item/pda/curator
+ belt = /obj/item/modular_computer/tablet/pda/curator
ears = /obj/item/radio/headset/headset_srv
shoes = /obj/item/clothing/shoes/laceup
l_pocket = /obj/item/laser_pointer
diff --git a/code/modules/jobs/job_types/detective.dm b/code/modules/jobs/job_types/detective.dm
index 6d9eb1a3808..9db11ec3cd0 100644
--- a/code/modules/jobs/job_types/detective.dm
+++ b/code/modules/jobs/job_types/detective.dm
@@ -54,10 +54,9 @@
backpack_contents = list(
/obj/item/detective_scanner = 1,
/obj/item/melee/baton = 1,
- /obj/item/modular_computer/tablet/preset/advanced/security = 1,
/obj/item/storage/box/evidence = 1,
)
- belt = /obj/item/pda/detective
+ belt = /obj/item/modular_computer/tablet/pda/detective
ears = /obj/item/radio/headset/headset_sec/alt
gloves = /obj/item/clothing/gloves/color/black
head = /obj/item/clothing/head/fedora/det_hat
diff --git a/code/modules/jobs/job_types/geneticist.dm b/code/modules/jobs/job_types/geneticist.dm
index 76e3628bde0..4ceb55e97ec 100644
--- a/code/modules/jobs/job_types/geneticist.dm
+++ b/code/modules/jobs/job_types/geneticist.dm
@@ -40,7 +40,7 @@
uniform = /obj/item/clothing/under/rank/rnd/geneticist
suit = /obj/item/clothing/suit/toggle/labcoat/genetics
suit_store = /obj/item/flashlight/pen
- belt = /obj/item/pda/geneticist
+ belt = /obj/item/modular_computer/tablet/pda/geneticist
ears = /obj/item/radio/headset/headset_sci
shoes = /obj/item/clothing/shoes/sneakers/white
l_pocket = /obj/item/sequence_scanner
diff --git a/code/modules/jobs/job_types/head_of_personnel.dm b/code/modules/jobs/job_types/head_of_personnel.dm
index 51cb9ac39e0..842eefc1e8b 100644
--- a/code/modules/jobs/job_types/head_of_personnel.dm
+++ b/code/modules/jobs/job_types/head_of_personnel.dm
@@ -58,10 +58,9 @@
uniform = /obj/item/clothing/under/rank/civilian/head_of_personnel
backpack_contents = list(
/obj/item/melee/baton/telescopic = 1,
- /obj/item/modular_computer/tablet/preset/advanced/command = 1,
/obj/item/storage/box/ids = 1,
)
- belt = /obj/item/pda/heads/hop
+ belt = /obj/item/modular_computer/tablet/pda/heads/hop
ears = /obj/item/radio/headset/heads/hop
head = /obj/item/clothing/head/hopcap
shoes = /obj/item/clothing/shoes/sneakers/brown
diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm
index 7f046122de5..868d0526016 100644
--- a/code/modules/jobs/job_types/head_of_security.dm
+++ b/code/modules/jobs/job_types/head_of_security.dm
@@ -55,9 +55,8 @@
suit_store = /obj/item/gun/energy/e_gun
backpack_contents = list(
/obj/item/evidencebag = 1,
- /obj/item/modular_computer/tablet/preset/advanced/command = 1,
)
- belt = /obj/item/pda/heads/hos
+ belt = /obj/item/modular_computer/tablet/pda/heads/hos
ears = /obj/item/radio/headset/heads/hos/alt
glasses = /obj/item/clothing/glasses/hud/security/sunglasses
gloves = /obj/item/clothing/gloves/color/black/security //SKYRAT EDIT CHANGE
diff --git a/code/modules/jobs/job_types/janitor.dm b/code/modules/jobs/job_types/janitor.dm
index 3e71b02852a..7ef32aacbd4 100644
--- a/code/modules/jobs/job_types/janitor.dm
+++ b/code/modules/jobs/job_types/janitor.dm
@@ -37,10 +37,7 @@
id_trim = /datum/id_trim/job/janitor
uniform = /obj/item/clothing/under/rank/civilian/janitor
- backpack_contents = list(
- /obj/item/modular_computer/tablet/preset/advanced/custodial = 1,
- )
- belt = /obj/item/pda/janitor
+ belt = /obj/item/modular_computer/tablet/pda/janitor
ears = /obj/item/radio/headset/headset_srv
/datum/outfit/job/janitor/pre_equip(mob/living/carbon/human/H, visualsOnly)
diff --git a/code/modules/jobs/job_types/lawyer.dm b/code/modules/jobs/job_types/lawyer.dm
index bb58f241dce..11d7d8e6be8 100644
--- a/code/modules/jobs/job_types/lawyer.dm
+++ b/code/modules/jobs/job_types/lawyer.dm
@@ -36,7 +36,7 @@
id_trim = /datum/id_trim/job/lawyer
uniform = /obj/item/clothing/under/rank/civilian/lawyer/bluesuit
suit = /obj/item/clothing/suit/toggle/lawyer
- belt = /obj/item/pda/lawyer
+ belt = /obj/item/modular_computer/tablet/pda/lawyer
ears = /obj/item/radio/headset/headset_srvsec
shoes = /obj/item/clothing/shoes/laceup
l_pocket = /obj/item/laser_pointer
diff --git a/code/modules/jobs/job_types/medical_doctor.dm b/code/modules/jobs/job_types/medical_doctor.dm
index 7646d7b84b5..d1cb6fd6890 100644
--- a/code/modules/jobs/job_types/medical_doctor.dm
+++ b/code/modules/jobs/job_types/medical_doctor.dm
@@ -47,7 +47,7 @@
uniform = /obj/item/clothing/under/rank/medical/scrubs/blue
suit = /obj/item/clothing/suit/toggle/labcoat
suit_store = /obj/item/flashlight/pen
- belt = /obj/item/pda/medical
+ belt = /obj/item/modular_computer/tablet/pda/medical
ears = /obj/item/radio/headset/headset_med
shoes = /obj/item/clothing/shoes/sneakers/white
l_hand = /obj/item/storage/medkit/surgery
diff --git a/code/modules/jobs/job_types/mime.dm b/code/modules/jobs/job_types/mime.dm
index 71956c5e300..d821b617649 100644
--- a/code/modules/jobs/job_types/mime.dm
+++ b/code/modules/jobs/job_types/mime.dm
@@ -54,7 +54,7 @@
/obj/item/reagent_containers/food/drinks/bottle/bottleofnothing = 1,
/obj/item/stamp/mime = 1,
)
- belt = /obj/item/pda/mime
+ belt = /obj/item/modular_computer/tablet/pda/mime
ears = /obj/item/radio/headset/headset_srv
gloves = /obj/item/clothing/gloves/color/white
head = /obj/item/clothing/head/frenchberet
diff --git a/code/modules/jobs/job_types/paramedic.dm b/code/modules/jobs/job_types/paramedic.dm
index 17b722a74e5..d04fa51c242 100644
--- a/code/modules/jobs/job_types/paramedic.dm
+++ b/code/modules/jobs/job_types/paramedic.dm
@@ -55,7 +55,7 @@
head = /obj/item/clothing/head/soft/paramedic
gloves = /obj/item/clothing/gloves/color/latex/nitrile
shoes = /obj/item/clothing/shoes/sneakers/blue
- l_pocket = /obj/item/pda/medical
+ l_pocket = /obj/item/modular_computer/tablet/pda/medical
backpack = /obj/item/storage/backpack/medic
satchel = /obj/item/storage/backpack/satchel/med
diff --git a/code/modules/jobs/job_types/psychologist.dm b/code/modules/jobs/job_types/psychologist.dm
index b8c51861940..ef5f80f5828 100644
--- a/code/modules/jobs/job_types/psychologist.dm
+++ b/code/modules/jobs/job_types/psychologist.dm
@@ -48,7 +48,7 @@
/obj/item/storage/pill_bottle/paxpsych,
/obj/item/storage/pill_bottle/psicodine,
)
- belt = /obj/item/pda/medical
+ belt = /obj/item/modular_computer/tablet/pda/medical
ears = /obj/item/radio/headset/headset_srvmed
shoes = /obj/item/clothing/shoes/laceup
l_hand = /obj/item/clipboard
diff --git a/code/modules/jobs/job_types/quartermaster.dm b/code/modules/jobs/job_types/quartermaster.dm
index e5506c1767e..c212032741d 100644
--- a/code/modules/jobs/job_types/quartermaster.dm
+++ b/code/modules/jobs/job_types/quartermaster.dm
@@ -53,7 +53,7 @@
/obj/item/melee/baton/telescopic=1,
/obj/item/modular_computer/tablet/preset/cargo/quartermaster = 1
) //SKYRAT EDIT CHANGE - ORIGINAL: backpack_contents = list(/obj/item/modular_computer/tablet/preset/cargo/quartermaster = 1)
- belt = /obj/item/pda/quartermaster
+ belt = /obj/item/modular_computer/tablet/pda/quartermaster
ears = /obj/item/radio/headset/heads/qm //SKYRAT EDIT CHANGE - OIGINAL: ears = /obj/item/radio/headset/headset_cargo
glasses = /obj/item/clothing/glasses/sunglasses
shoes = /obj/item/clothing/shoes/sneakers/brown
diff --git a/code/modules/jobs/job_types/research_director.dm b/code/modules/jobs/job_types/research_director.dm
index 7625ce1edfe..56d3001df5e 100644
--- a/code/modules/jobs/job_types/research_director.dm
+++ b/code/modules/jobs/job_types/research_director.dm
@@ -62,7 +62,7 @@
/obj/item/melee/baton/telescopic = 1,
/obj/item/modular_computer/tablet/preset/advanced/command = 1,
)
- belt = /obj/item/pda/heads/rd
+ belt = /obj/item/modular_computer/tablet/pda/heads/rd
ears = /obj/item/radio/headset/heads/rd
shoes = /obj/item/clothing/shoes/jackboots //SKYRAT EDIT CHANGE
l_pocket = /obj/item/laser_pointer
diff --git a/code/modules/jobs/job_types/roboticist.dm b/code/modules/jobs/job_types/roboticist.dm
index 9c5d69013cd..fc26e072dfc 100644
--- a/code/modules/jobs/job_types/roboticist.dm
+++ b/code/modules/jobs/job_types/roboticist.dm
@@ -50,7 +50,7 @@
)
belt = /obj/item/storage/belt/utility/full
ears = /obj/item/radio/headset/headset_sci
- l_pocket = /obj/item/pda/roboticist
+ l_pocket = /obj/item/modular_computer/tablet/pda/roboticist
backpack = /obj/item/storage/backpack/science/robo //SKYRAT CHANGE - Roboticist Bags (CHANGE)
satchel = /obj/item/storage/backpack/satchel/tox/robo //SKYRAT CHANGE - Roboticist Bags (CHANGE)
diff --git a/code/modules/jobs/job_types/scientist.dm b/code/modules/jobs/job_types/scientist.dm
index e0c67d36669..23941f90407 100644
--- a/code/modules/jobs/job_types/scientist.dm
+++ b/code/modules/jobs/job_types/scientist.dm
@@ -44,7 +44,7 @@
backpack_contents = list(
/obj/item/modular_computer/tablet/preset/science = 1,
)
- belt = /obj/item/pda/science
+ belt = /obj/item/modular_computer/tablet/pda/science
ears = /obj/item/radio/headset/headset_sci
shoes = /obj/item/clothing/shoes/sneakers/white
diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm
index 6a7916c3ca4..d0b93cabf32 100644
--- a/code/modules/jobs/job_types/security_officer.dm
+++ b/code/modules/jobs/job_types/security_officer.dm
@@ -168,14 +168,14 @@ GLOBAL_LIST_EMPTY(security_officer_distribution)
partners += partner.real_name
if (partners.len)
- for (var/obj/item/pda/pda as anything in GLOB.PDAs)
- if (pda.owner in partners)
- targets += STRINGIFY_PDA_TARGET(pda.owner, pda.ownjob)
+ for (var/obj/item/modular_computer/pda as anything in GLOB.TabletMessengers)
+ if (pda.saved_identification in partners)
+ targets += pda
if (!targets.len)
return
- var/datum/signal/subspace/messaging/pda/signal = new(announcement_system, list(
+ var/datum/signal/subspace/messaging/tablet_msg/signal = new(announcement_system, list(
"name" = "Security Department Update",
"job" = "Automated Announcement System",
"message" = "Officer [officer.real_name] has been assigned to your department, [department].",
@@ -210,7 +210,7 @@ GLOBAL_LIST_EMPTY(security_officer_distribution)
/obj/item/evidencebag = 1,
/obj/item/modular_computer/tablet/preset/advanced/security = 1,
)
- belt = /obj/item/pda/security
+ belt = /obj/item/modular_computer/tablet/pda/security
ears = /obj/item/radio/headset/headset_sec/alt
gloves = /obj/item/clothing/gloves/color/black/security //SKYRAT EDIT CHANGE
head = /obj/item/clothing/head/security_garrison //SKYRAT EDIT CHANGE
diff --git a/code/modules/jobs/job_types/shaft_miner.dm b/code/modules/jobs/job_types/shaft_miner.dm
index 5f5e5d8d986..653740f992d 100644
--- a/code/modules/jobs/job_types/shaft_miner.dm
+++ b/code/modules/jobs/job_types/shaft_miner.dm
@@ -40,7 +40,7 @@
/obj/item/suit_voucher = 1,
/obj/item/stack/marker_beacon/ten = 1
) //SKYRAT EDIT: Suit_Voucher is an addition, one line up
- belt = /obj/item/pda/shaftminer
+ belt = /obj/item/modular_computer/tablet/pda/shaftminer
ears = /obj/item/radio/headset/headset_cargo/mining
gloves = /obj/item/clothing/gloves/color/black
shoes = /obj/item/clothing/shoes/workboots/mining
diff --git a/code/modules/jobs/job_types/station_engineer.dm b/code/modules/jobs/job_types/station_engineer.dm
index 6be9573da74..b806de25a2b 100644
--- a/code/modules/jobs/job_types/station_engineer.dm
+++ b/code/modules/jobs/job_types/station_engineer.dm
@@ -51,7 +51,7 @@
ears = /obj/item/radio/headset/headset_eng
head = /obj/item/clothing/head/hardhat
shoes = /obj/item/clothing/shoes/workboots
- l_pocket = /obj/item/pda/engineering
+ l_pocket = /obj/item/modular_computer/tablet/pda/engineering
r_pocket = /obj/item/t_scanner
backpack = /obj/item/storage/backpack/industrial
diff --git a/code/modules/jobs/job_types/virologist.dm b/code/modules/jobs/job_types/virologist.dm
index 1b874b20ff3..04d2776cca2 100644
--- a/code/modules/jobs/job_types/virologist.dm
+++ b/code/modules/jobs/job_types/virologist.dm
@@ -47,7 +47,7 @@
uniform = /obj/item/clothing/under/rank/medical/virologist
suit = /obj/item/clothing/suit/toggle/labcoat/virologist
suit_store = /obj/item/flashlight/pen
- belt = /obj/item/pda/viro
+ belt = /obj/item/modular_computer/tablet/pda/viro
ears = /obj/item/radio/headset/headset_med
mask = /obj/item/clothing/mask/surgical
shoes = /obj/item/clothing/shoes/sneakers/white
diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm
index 81b3c7614a9..7b6c3af00be 100644
--- a/code/modules/jobs/job_types/warden.dm
+++ b/code/modules/jobs/job_types/warden.dm
@@ -55,7 +55,7 @@
/obj/item/evidencebag = 1,
/obj/item/modular_computer/tablet/preset/advanced/security = 1,
)
- belt = /obj/item/pda/warden
+ belt = /obj/item/modular_computer/tablet/pda/warden
ears = /obj/item/radio/headset/headset_sec/alt
glasses = /obj/item/clothing/glasses/hud/security/sunglasses
gloves = /obj/item/clothing/gloves/color/black/security //SKYRAT EDIT CHANGE
diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm
index 191294a6085..ec06b4a3330 100644
--- a/code/modules/mining/abandoned_crates.dm
+++ b/code/modules/mining/abandoned_crates.dm
@@ -157,7 +157,7 @@
for(var/i in 1 to 5)
new /obj/item/toy/snappop/phoenix(src)
if(41 to 45)
- new /obj/item/pda/clear(src)
+ new /obj/item/modular_computer/tablet/pda/clear(src)
if(46 to 50)
new /obj/item/storage/box/syndie_kit/chameleon/broken
if(51 to 52) // 2% chance
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index bd7c28db5cd..379069012cc 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -319,14 +319,14 @@
return
var/datum/data/crime/crime = GLOB.data_core.createCrimeEntry(t1, "", allowed_access, station_time_timestamp(), fine)
- for (var/obj/item/pda/P in GLOB.PDAs)
- if(P.owner == sec_record.fields["name"]) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
+ for (var/obj/item/modular_computer/tablet in GLOB.TabletMessengers)
+ if(tablet.saved_identification == sec_record.fields["name"]) // SKYRAT EDIT CHANGE
var/message = "You have been fined [fine] credits for '[t1]'. Fines may be paid at security."
- var/datum/signal/subspace/messaging/pda/signal = new(src, list(
+ var/datum/signal/subspace/messaging/tablet_msg/signal = new(src, list(
"name" = "Security Citation",
"job" = "Citation Server",
"message" = message,
- "targets" = list(STRINGIFY_PDA_TARGET(P.owner, P.ownjob)),
+ "targets" = list(tablet),
"automated" = TRUE
))
signal.send_to_receivers()
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index 791f940cdd3..1324dc06d55 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -12,9 +12,9 @@
if(id)
. = id.assignment
else
- var/obj/item/pda/pda = wear_id
+ var/obj/item/modular_computer/pda = wear_id
if(istype(pda))
- . = pda.ownjob
+ . = pda.saved_job
else
return if_no_id
if(!.)
@@ -26,9 +26,9 @@
var/obj/item/card/id/id = get_idcard(FALSE)
if(id)
return id.registered_name
- var/obj/item/pda/pda = wear_id
+ var/obj/item/modular_computer/pda = wear_id
if(istype(pda))
- return pda.owner
+ return pda.saved_identification
return if_no_id
//repurposed proc. Now it combines get_id_name() and get_face_name() to determine a mob's name variable. Made into a separate proc as it'll be useful elsewhere
@@ -60,17 +60,14 @@
//Useful when player is being seen by other mobs
/mob/living/carbon/human/proc/get_id_name(if_no_id = "Unknown")
var/obj/item/storage/wallet/wallet = wear_id
- var/obj/item/pda/pda = wear_id
+ var/obj/item/modular_computer/tablet/pda/pda = wear_id
var/obj/item/card/id/id = wear_id
- var/obj/item/modular_computer/tablet/tablet = wear_id
if(istype(wallet))
id = wallet.front_id
if(istype(id))
. = id.registered_name
else if(istype(pda))
- . = pda.owner
- else if(istype(tablet))
- var/obj/item/computer_hardware/card_slot/card_slot = tablet.all_components[MC_CARD]
+ var/obj/item/computer_hardware/card_slot/card_slot = pda.all_components[MC_CARD]
if(card_slot?.stored_card)
. = card_slot.stored_card.registered_name
if(!.)
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index c7cef296ec5..d7e7c816b7d 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -1022,7 +1022,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
if(!disable_warning)
to_chat(H, span_warning("The [I.name] is too big to attach!")) //should be src?
return FALSE
- if( istype(I, /obj/item/pda) || istype(I, /obj/item/pen) || is_type_in_list(I, H.wear_suit.allowed) )
+ if( istype(I, /obj/item/modular_computer/tablet) || istype(I, /obj/item/pen) || is_type_in_list(I, H.wear_suit.allowed) )
return TRUE
return FALSE
if(ITEM_SLOT_HANDCUFFED)
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index f5c2d23703c..2c195c817d4 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -107,7 +107,7 @@
var/atom/lastloc
interaction_range = null
-
+ var/atom/movable/screen/ai/modpc/interfaceButton
/mob/living/silicon/ai/Initialize(mapload, datum/ai_laws/L, mob/target_ai)
. = ..()
@@ -160,10 +160,7 @@
add_verb(src, /mob/living/silicon/ai/proc/show_laws_verb)
- aiPDA = new/obj/item/pda/ai(src)
- aiPDA.owner = real_name
- aiPDA.ownjob = "AI"
- aiPDA.name = real_name + " (" + aiPDA.ownjob + ")"
+ create_modularInterface()
aiMulti = new(src)
aicamera = new/obj/item/camera/siliconcam/ai_camera(src)
@@ -835,16 +832,12 @@
if(oldname != real_name)
if(eyeobj)
eyeobj.name = "[newname] (AI Eye)"
+ modularInterface.saved_identification = real_name
// Notify Cyborgs
for(var/mob/living/silicon/robot/Slave in connected_robots)
Slave.show_laws()
-/mob/living/silicon/ai/replace_identification_name(oldname,newname)
- if(aiPDA)
- aiPDA.owner = newname
- aiPDA.name = newname + " (" + aiPDA.ownjob + ")"
-
/datum/action/innate/choose_modules
name = "Malfunction Modules"
desc = "Choose from a variety of insidious modules to aid you."
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index 2af326b024f..5510e5c33ad 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -127,6 +127,8 @@
"universal translator" = 35,
)
+ var/atom/movable/screen/ai/modpc/interfaceButton
+
/mob/living/silicon/pai/add_sensors() //pAIs have to buy their HUDs
return
@@ -171,10 +173,10 @@
aicamera = new /obj/item/camera/siliconcam/ai_camera(src)
aicamera.flash_enabled = TRUE
- addtimer(CALLBACK(src, .proc/pdaconfig), 5)
-
. = ..()
+ create_modularInterface()
+
emittersemicd = TRUE
addtimer(CALLBACK(src, .proc/emittercool), 600)
@@ -198,13 +200,6 @@
GLOB.pai_list -= src
return ..()
-/mob/living/silicon/pai/proc/pdaconfig()
- //PDA
- aiPDA = new /obj/item/pda/ai(src)
- aiPDA.owner = real_name
- aiPDA.ownjob = "pAI Messenger"
- aiPDA.name = "[real_name] ([aiPDA.ownjob])"
-
/mob/living/silicon/pai/make_laws()
laws = new /datum/ai_laws/pai()
return TRUE
@@ -255,6 +250,8 @@
/mob/living/silicon/pai/can_interact_with(atom/A)
if(A == signaler) // Bypass for signaler
return TRUE
+ if(A == modularInterface)
+ return TRUE
return ..()
diff --git a/code/modules/mob/living/silicon/pai/pai_shell.dm b/code/modules/mob/living/silicon/pai/pai_shell.dm
index 2a4b5f8fbb8..8431e0e967e 100644
--- a/code/modules/mob/living/silicon/pai/pai_shell.dm
+++ b/code/modules/mob/living/silicon/pai/pai_shell.dm
@@ -21,8 +21,8 @@
REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, PAI_FOLDED)
REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, PAI_FOLDED)
set_density(TRUE)
- if(istype(card.loc, /obj/item/pda))
- var/obj/item/pda/P = card.loc
+ if(istype(card.loc, /obj/item/modular_computer))
+ var/obj/item/modular_computer/P = card.loc
P.pai = null
P.visible_message(span_notice("[src] ejects itself from [P]!"))
if(isliving(card.loc))
diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm
index 0c4a0fcdc08..63a6ee684ac 100644
--- a/code/modules/mob/living/silicon/pai/software.dm
+++ b/code/modules/mob/living/silicon/pai/software.dm
@@ -30,9 +30,6 @@
data["pda"] = list()
data["ram"] = ram
data["refresh_spam"] = refresh_spam
- if(aiPDA)
- data["pda"]["power"] = !aiPDA.toff
- data["pda"]["silent"] = aiPDA.silent
if(master)
data["master"]["name"] = master
data["master"]["dna"] = master_dna
@@ -128,15 +125,6 @@
med.remove_hud_from(src)
if("newscaster")
newscaster.ui_interact(src)
- if("pda")
- if(isnull(aiPDA))
- return FALSE
- if(params["pda"] == "power")
- aiPDA.toff = !aiPDA.toff
- if(params["pda"] == "silent")
- aiPDA.silent = !aiPDA.silent
- if(params["pda"] == "message")
- cmd_send_pdamesg(usr)
if("photography_module")
aicamera.toggle_camera_mode(usr)
if("printer_module")
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 322dd4b751f..bfd8bdb1231 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -79,13 +79,6 @@
toner = tonermax
diag_hud_set_borgcell()
logevent("System brought online.")
- // SKYRAT EDIT ADDITION BEGIN - Cyborg PDA
- if(!shell)
- aiPDA = new/obj/item/pda/ai(src)
- aiPDA.owner = real_name
- aiPDA.ownjob = "Cyborg"
- aiPDA.name = real_name + " (" + aiPDA.ownjob + ")"
- //SKYRAT EDIT ADDITION END
alert_control = new(src, list(ALARM_ATMOS, ALARM_FIRE, ALARM_POWER, ALARM_CAMERA, ALARM_BURGLAR, ALARM_MOTION), list(z))
RegisterSignal(alert_control.listener, COMSIG_ALARM_TRIGGERED, .proc/alarm_triggered)
RegisterSignal(alert_control.listener, COMSIG_ALARM_CLEARED, .proc/alarm_cleared)
@@ -97,17 +90,14 @@
laws = new /datum/ai_laws/syndicate_override()
addtimer(CALLBACK(src, .proc/show_playstyle), 5)
-/mob/living/silicon/robot/proc/create_modularInterface()
- if(!modularInterface)
- modularInterface = new /obj/item/modular_computer/tablet/integrated(src)
- modularInterface.layer = ABOVE_HUD_PLANE
- modularInterface.plane = ABOVE_HUD_PLANE
-
/mob/living/silicon/robot/model/syndicate/create_modularInterface()
if(!modularInterface)
modularInterface = new /obj/item/modular_computer/tablet/integrated/syndicate(src)
+ modularInterface.saved_identification = real_name
+ modularInterface.saved_job = "Cyborg"
return ..()
+
/**
* Sets the tablet theme and icon
*
@@ -711,6 +701,7 @@
notify_ai(AI_NOTIFICATION_CYBORG_RENAMED, oldname, newname)
if(!QDELETED(builtInCamera))
builtInCamera.c_tag = real_name
+ modularInterface.saved_identification = real_name
custom_name = newname
@@ -1004,36 +995,6 @@
lamp_doom = connected_ai.doomsday_device ? TRUE : FALSE
toggle_headlamp(FALSE, TRUE)
-/**
- * Records an IC event log entry in the cyborg's internal tablet.
- *
- * Creates an entry in the borglog list of the cyborg's internal tablet, listing the current
- * in-game time followed by the message given. These logs can be seen by the cyborg in their
- * BorgUI tablet app. By design, logging fails if the cyborg is dead.
- *
- * Arguments:
- * arg1: a string containing the message to log.
- */
-/mob/living/silicon/robot/proc/logevent(string = "")
- if(!string)
- return
- if(stat == DEAD) //Dead borgs log no longer
- return
- if(!modularInterface)
- stack_trace("Cyborg [src] ( [type] ) was somehow missing their integrated tablet. Please make a bug report.")
- create_modularInterface()
- modularInterface.borglog += "[station_time_timestamp()] - [string]"
- var/datum/computer_file/program/robotact/program = modularInterface.get_robotact()
- if(program)
- program.force_full_update()
-
-// SKYRAT EDIT ADDITION BEGIN - Cyborg PDA
-/mob/living/silicon/robot/replace_identification_name(oldname,newname)
- if(aiPDA && !shell)
- aiPDA.owner = newname
- aiPDA.name = newname + " (" + aiPDA.ownjob + ")"
-// SKYRAT EDIT ADDITION END
-
/mob/living/silicon/robot/get_exp_list(minutes)
. = ..()
diff --git a/code/modules/mob/living/silicon/robot/robot_defines.dm b/code/modules/mob/living/silicon/robot/robot_defines.dm
index 911579b6f5f..68501f892af 100644
--- a/code/modules/mob/living/silicon/robot/robot_defines.dm
+++ b/code/modules/mob/living/silicon/robot/robot_defines.dm
@@ -68,8 +68,7 @@
var/atom/movable/screen/robot/lamp/lampButton
///The reference to the built-in tablet that borgs carry.
- var/obj/item/modular_computer/tablet/integrated/modularInterface
- var/atom/movable/screen/robot/modPC/interfaceButton
+ var/atom/movable/screen/robot/modpc/interfaceButton
var/sight_mode = 0
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD, DIAG_TRACK_HUD)
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index d13a4b92f41..0b0e6c4d688 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -47,7 +47,8 @@
var/hack_software = FALSE //Will be able to use hacking actions
interaction_range = 7 //wireless control range
- var/obj/item/pda/ai/aiPDA
+
+ var/obj/item/modular_computer/tablet/integrated/modularInterface
/mob/living/silicon/Initialize(mapload)
. = ..()
@@ -71,12 +72,35 @@
QDEL_NULL(radio)
QDEL_NULL(aicamera)
QDEL_NULL(builtInCamera)
- QDEL_NULL(aiPDA)
laws?.owner = null //Laws will refuse to die otherwise.
QDEL_NULL(laws)
GLOB.silicon_mobs -= src
return ..()
+/mob/living/silicon/proc/create_modularInterface()
+ if(!modularInterface)
+ modularInterface = new /obj/item/modular_computer/tablet/integrated(src)
+ modularInterface.layer = ABOVE_HUD_PLANE
+ modularInterface.plane = ABOVE_HUD_PLANE
+ modularInterface.saved_identification = real_name || name
+ if(istype(src, /mob/living/silicon/robot))
+ modularInterface.saved_job = "Cyborg"
+ modularInterface.install_component(new /obj/item/computer_hardware/hard_drive/small/integrated/borg)
+ if(istype(src, /mob/living/silicon/ai))
+ modularInterface.saved_job = "AI"
+ modularInterface.install_component(new /obj/item/computer_hardware/hard_drive/small/integrated)
+ if(istype(src, /mob/living/silicon/pai))
+ modularInterface.saved_job = "pAI Messenger"
+ modularInterface.install_component(new /obj/item/computer_hardware/hard_drive/small/integrated)
+
+/mob/living/silicon/robot/model/syndicate/create_modularInterface()
+ if(!modularInterface)
+ modularInterface = new /obj/item/modular_computer/tablet/integrated/syndicate(src)
+ modularInterface.saved_identification = real_name
+ modularInterface.saved_job = "Cyborg"
+ return ..()
+
+
/mob/living/silicon/med_hud_set_health()
return //we use a different hud
@@ -403,3 +427,30 @@
/mob/living/silicon/on_standing_up()
return // Silicons are always standing by default.
+
+/**
+ * Records an IC event log entry in the cyborg's internal tablet.
+ *
+ * Creates an entry in the borglog list of the cyborg's internal tablet (if it's a borg), listing the current
+ * in-game time followed by the message given. These logs can be seen by the cyborg in their
+ * BorgUI tablet app. By design, logging fails if the cyborg is dead.
+ *
+ * (This used to be in robot.dm. It's in here now.)
+ *
+ * Arguments:
+ * arg1: a string containing the message to log.
+ */
+/mob/living/silicon/proc/logevent(string = "")
+ if(!string)
+ return
+ if(stat == DEAD) //Dead silicons log no longer
+ return
+ if(!modularInterface)
+ stack_trace("Silicon [src] ( [type] ) was somehow missing their integrated tablet. Please make a bug report.")
+ create_modularInterface()
+ var/mob/living/silicon/robot/robo = modularInterface.borgo
+ if(istype(robo))
+ modularInterface.borglog += "[station_time_timestamp()] - [string]"
+ var/datum/computer_file/program/robotact/program = modularInterface.get_robotact()
+ if(program)
+ program.force_full_update()
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 122d66e27b4..ded71b6e6d7 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1064,11 +1064,10 @@
break
search_id = 0
- else if( search_pda && istype(A, /obj/item/pda) )
- var/obj/item/pda/PDA = A
- if(PDA.owner == oldname)
- PDA.owner = newname
- PDA.update_label()
+ else if( search_pda && istype(A, /obj/item/modular_computer/tablet/pda) )
+ var/obj/item/modular_computer/tablet/pda/PDA = A
+ if(PDA.saved_identification == oldname)
+ PDA.saved_identification = newname
if(!search_id)
break
search_pda = 0
diff --git a/code/modules/mob_spawn/corpses/mining_corpses.dm b/code/modules/mob_spawn/corpses/mining_corpses.dm
index 3d36a9e1916..bcecebfb1cf 100644
--- a/code/modules/mob_spawn/corpses/mining_corpses.dm
+++ b/code/modules/mob_spawn/corpses/mining_corpses.dm
@@ -124,7 +124,6 @@
uniform = /obj/item/clothing/under/rank/civilian/clown
back = /obj/item/storage/backpack/clown
backpack_contents = list()
- belt = /obj/item/pda/clown
ears = /obj/item/radio/headset/headset_srv
shoes = /obj/item/clothing/shoes/clown_shoes
mask = /obj/item/clothing/mask/gas/clown_hat
diff --git a/code/modules/mob_spawn/corpses/nonhuman_corpses.dm b/code/modules/mob_spawn/corpses/nonhuman_corpses.dm
index 258b7b98ea6..b39c381f0f9 100644
--- a/code/modules/mob_spawn/corpses/nonhuman_corpses.dm
+++ b/code/modules/mob_spawn/corpses/nonhuman_corpses.dm
@@ -15,7 +15,6 @@
. = ..()
dead_ai.name = src.name
dead_ai.real_name = src.name
- dead_ai.aiPDA.toff = TRUE //turns the AI's PDA messenger off, stopping it showing up on player PDAs
///dead slimes, with a var for whatever color you want.
/obj/effect/mob_spawn/corpse/slime
diff --git a/code/modules/mob_spawn/ghost_roles/unused_roles.dm b/code/modules/mob_spawn/ghost_roles/unused_roles.dm
index 932813fb3d6..b852ab77c9b 100644
--- a/code/modules/mob_spawn/ghost_roles/unused_roles.dm
+++ b/code/modules/mob_spawn/ghost_roles/unused_roles.dm
@@ -216,7 +216,7 @@
/obj/effect/mob_spawn/ghost_role/human/doctor/alive/equip(mob/living/carbon/human/doctor)
. = ..()
// Remove radio and PDA so they wouldn't annoy station crew.
- var/list/del_types = list(/obj/item/pda, /obj/item/radio/headset)
+ var/list/del_types = list(/obj/item/modular_computer/tablet, /obj/item/radio/headset)
for(var/del_type in del_types)
var/obj/item/unwanted_item = locate(del_type) in doctor
qdel(unwanted_item)
diff --git a/code/modules/mob_spawn/mob_spawn.dm b/code/modules/mob_spawn/mob_spawn.dm
index ec37984775c..f25cca69db9 100644
--- a/code/modules/mob_spawn/mob_spawn.dm
+++ b/code/modules/mob_spawn/mob_spawn.dm
@@ -284,9 +284,9 @@
. = ..()
if(conceal_presence)
// We don't want corpse PDAs to show up in the messenger list.
- var/obj/item/pda/messenger = locate(/obj/item/pda) in spawned_human
+ var/obj/item/modular_computer/tablet/pda/messenger = locate(/obj/item/modular_computer/tablet/pda/) in spawned_human
if(messenger)
- messenger.toff = TRUE
+ messenger.invisible = TRUE
// Or on crew monitors
var/obj/item/clothing/under/sensor_clothes = spawned_human.w_uniform
if(istype(sensor_clothes))
diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm
index 54f7f265284..e7b30d69a04 100644
--- a/code/modules/modular_computers/computers/item/computer.dm
+++ b/code/modules/modular_computers/computers/item/computer.dm
@@ -1,3 +1,5 @@
+GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar to GLOB.PDAs (used primarily with ntmessenger.dm)
+
// This is the base type that does all the hardware stuff.
// Other types expand it - tablets use a direct subtypes, and
// consoles and laptops use "procssor" item that is held inside machinery piece
@@ -11,7 +13,11 @@
max_integrity = 100
armor = list(MELEE = 0, BULLET = 20, LASER = 20, ENERGY = 100, BOMB = 0, BIO = 100, FIRE = 0, ACID = 0)
+ var/bypass_state = FALSE // bypassing the set icon state
+
var/enabled = 0 // Whether the computer is turned on.
+ var/upgradable = TRUE // whether or not the computer can be upgraded
+ var/deconstructable = TRUE // whether or not the computer can be deconstructed
var/screen_on = 1 // Whether the computer is active/opened/it's screen is on.
var/device_theme = "ntos" // Sets the theme for the main menu, hardware config, and file browser apps. Overridden by certain non-NT devices.
var/datum/computer_file/program/active_program = null // A currently active program running on the computer.
@@ -46,14 +52,26 @@
/// Number of total expansion bays this computer has available.
var/max_bays = 0
+ var/saved_identification = null // next two values are the currently imprinted id and job values
+ var/saved_job = null
+
+ var/honkamnt = 0 /// honk honk honk honk honk honkh onk honkhnoohnk
+
var/list/idle_threads // Idle programs on background. They still receive process calls but can't be interacted with.
var/obj/physical = null // Object that represents our computer. It's used for Adjacent() and UI visibility checks.
var/has_light = FALSE //If the computer has a flashlight/LED light/what-have-you installed
var/comp_light_luminosity = 3 //The brightness of that light
var/comp_light_color //The color of that light
+ var/invisible = FALSE // whether or not the tablet is invisible in messenger and other apps
+
+ var/datum/picture/saved_image // the saved image used for messaging purpose like come on dude
+
+ var/obj/item/paicard/pai = null
/obj/item/modular_computer/Initialize(mapload)
. = ..()
+
+ var/obj/item/computer_hardware/identifier/id = all_components[MC_IDENTIFY]
START_PROCESSING(SSobj, src)
if(!physical)
physical = src
@@ -61,20 +79,28 @@
idle_threads = list()
if(looping_sound)
soundloop = new(src, enabled)
+ if(id)
+ id.UpdateDisplay()
update_appearance()
+ Add_Messenger()
/obj/item/modular_computer/Destroy()
wipe_program(forced = TRUE)
for(var/datum/computer_file/program/idle as anything in idle_threads)
idle.kill_program(TRUE)
- idle_threads.Cut()
+ idle_threads?.Cut()
STOP_PROCESSING(SSobj, src)
for(var/port in all_components)
var/obj/item/computer_hardware/component = all_components[port]
qdel(component)
- all_components.Cut() //Die demon die
+ all_components?.Cut()
//Some components will actually try and interact with this, so let's do it later
QDEL_NULL(soundloop)
+ Remove_Messenger()
+
+ if(istype(pai))
+ QDEL_NULL(pai)
+
physical = null
return ..()
@@ -86,6 +112,16 @@
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
return ..()
+// shameless copy of newscaster photo saving
+
+/obj/item/modular_computer/proc/save_photo(icon/photo)
+ var/photo_file = copytext_char(md5("\icon[photo]"), 1, 6)
+ if(!fexists("[GLOB.log_directory]/photos/[photo_file].png"))
+ //Clean up repeated frames
+ var/icon/clean = new /icon()
+ clean.Insert(photo, "", SOUTH, 1, 0)
+ fcopy(clean, "[GLOB.log_directory]/photos/[photo_file].png")
+ return photo_file
/**
* Plays a ping sound.
@@ -103,7 +139,10 @@
if(user.canUseTopic(src, BE_CLOSE))
var/obj/item/computer_hardware/card_slot/card_slot2 = all_components[MC_CARD2]
var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
- return (card_slot2?.try_eject(user) || card_slot?.try_eject(user)) //Try the secondary one first.
+ if(card_slot2?.try_eject(user) || card_slot?.try_eject(user))
+ return TRUE
+ if(!istype(src, /obj/item/modular_computer/tablet))
+ return FALSE
// Gets IDs/access levels from card slot. Would be useful when/if PDAs would become modular PCs.
/obj/item/modular_computer/GetAccess()
@@ -169,6 +208,8 @@
if(human_wearer.wear_id == src)
human_wearer.sec_hud_set_ID()
update_slot_icon()
+ update_appearance()
+
return removed_id
return ..()
@@ -176,10 +217,11 @@
/obj/item/modular_computer/InsertID(obj/item/inserting_item)
var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
var/obj/item/computer_hardware/card_slot/card_slot2 = all_components[MC_CARD2]
+
if(!(card_slot || card_slot2))
return FALSE
- var/obj/item/card/inserting_id = inserting_item.RemoveID()
+ var/obj/item/card/inserting_id = inserting_item.GetID()
if(!inserting_id)
return FALSE
@@ -188,8 +230,8 @@
var/mob/living/carbon/human/human_wearer = loc
if(human_wearer.wear_id == src)
human_wearer.sec_hud_set_ID()
+ update_appearance()
update_slot_icon()
- return TRUE
return FALSE
@@ -241,19 +283,24 @@
. += get_modular_computer_parts_examine(user)
/obj/item/modular_computer/update_icon_state()
- icon_state = enabled ? icon_state_powered : icon_state_unpowered
+ if(!bypass_state)
+ icon_state = enabled ? icon_state_powered : icon_state_unpowered
return ..()
/obj/item/modular_computer/update_overlays()
. = ..()
+ var/init_icon = initial(icon)
+
+ if(!init_icon)
+ return
if(!display_overlays)
return
if(enabled)
- . += active_program?.program_icon_state || icon_state_menu
+ . += active_program ? mutable_appearance(init_icon, active_program.program_icon_state) : mutable_appearance(init_icon, icon_state_menu)
if(atom_integrity <= integrity_failure * max_integrity)
- . += "bsod"
- . += "broken"
+ . += mutable_appearance(init_icon, "bsod")
+ . += mutable_appearance(init_icon, "broken")
// On-click handling. Turns on the computer if it's off and opens the GUI.
@@ -353,6 +400,16 @@
if(istype(holder))
to_chat(holder, "[icon2html(src)] [span_notice("The [src] displays a [caller.filedesc] notification: [alerttext]")]")
+/obj/item/modular_computer/proc/ring(ringtone) // bring bring
+ if(HAS_TRAIT(SSstation, STATION_TRAIT_PDA_GLITCHED))
+ playsound(src, pick('sound/machines/twobeep_voice1.ogg', 'sound/machines/twobeep_voice2.ogg'), 50, TRUE)
+ else
+ playsound(src, 'sound/machines/twobeep_high.ogg', 50, TRUE)
+ visible_message("*[ringtone]*")
+
+/obj/item/modular_computer/proc/send_sound()
+ playsound(src, 'sound/machines/terminal_success.ogg', 15, TRUE)
+
// Function used by NanoUI's to obtain data for header. All relevant entries begin with "PC_"
/obj/item/modular_computer/proc/get_header_data()
var/list/data = list()
@@ -489,6 +546,8 @@
return TRUE
/obj/item/modular_computer/screwdriver_act(mob/user, obj/item/tool)
+ if(!deconstructable)
+ return
if(!length(all_components))
balloon_alert(user, "no components installed!")
return
@@ -520,6 +579,25 @@
if(istype(W, /obj/item/card/id) && InsertID(W))
return
+ // Insert a PAI.
+ if(istype(W, /obj/item/paicard) && !pai)
+ if(!user.transferItemToLoc(W, src))
+ return
+ pai = W
+ pai.slotted = TRUE
+ to_chat(user, span_notice("You slot \the [W] into [src]."))
+ return
+
+ // Scan a photo.
+ if(istype(W, /obj/item/photo))
+ var/obj/item/computer_hardware/hard_drive/hdd = all_components[MC_HDD]
+ var/obj/item/photo/pic = W
+ if(hdd)
+ for(var/datum/computer_file/program/messenger/messenger in hdd.stored_files)
+ saved_image = pic.picture
+ messenger.ProcessPhoto()
+ return
+
// Insert items into the components
for(var/h in all_components)
var/obj/item/computer_hardware/H = all_components[h]
@@ -527,7 +605,7 @@
return
// Insert new hardware
- if(istype(W, /obj/item/computer_hardware))
+ if(istype(W, /obj/item/computer_hardware) && upgradable)
if(install_component(W, user))
return
@@ -574,3 +652,9 @@
if(physical && physical != src)
return physical.Adjacent(neighbor)
return ..()
+
+/obj/item/modular_computer/proc/Add_Messenger()
+ GLOB.TabletMessengers += src
+
+/obj/item/modular_computer/proc/Remove_Messenger()
+ GLOB.TabletMessengers -= src
diff --git a/code/modules/modular_computers/computers/item/computer_ui.dm b/code/modules/modular_computers/computers/item/computer_ui.dm
index 45f8805a4ca..7319751bc8d 100644
--- a/code/modules/modular_computers/computers/item/computer_ui.dm
+++ b/code/modules/modular_computers/computers/item/computer_ui.dm
@@ -4,6 +4,8 @@
// Operates TGUI
/obj/item/modular_computer/ui_interact(mob/user, datum/tgui/ui)
+ if(issilicon(user)) // silicons have some issues regarding real_name
+ saved_identification = user.real_name
if(!enabled)
if(ui)
ui.close()
@@ -37,6 +39,10 @@
to_chat(user, span_danger("\The [src] beeps three times, it's screen displaying a \"DISK ERROR\" warning."))
return // No HDD, No HDD files list or no stored files. Something is very broken.
+ if(honkamnt > 0) // EXTRA annoying, huh!
+ honkamnt--
+ playsound(src, 'sound/items/bikehorn.ogg', 30, TRUE)
+
ui = SStgui.try_update_ui(user, src, ui)
if (!ui)
ui = new(user, src, "NtosMain")
@@ -44,28 +50,55 @@
if(ui.open())
ui.send_asset(get_asset_datum(/datum/asset/simple/headers))
+/obj/item/modular_computer/ui_static_data(mob/user)
+ . = ..()
+ var/list/data = list()
+
+ data["show_imprint"] = istype(src, /obj/item/modular_computer/tablet/)
+
+ return data
+
+
/obj/item/modular_computer/ui_data(mob/user)
var/list/data = get_header_data()
data["device_theme"] = device_theme
-
data["login"] = list()
+
+ data["disk"] = null
+
var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD]
+ var/obj/item/computer_hardware/hard_drive/role/ssd = all_components[MC_HDD_JOB]
data["cardholder"] = FALSE
+
if(cardholder)
data["cardholder"] = TRUE
- var/obj/item/card/id/stored_card = cardholder.GetID()
- if(stored_card)
- var/stored_name = stored_card.registered_name
- var/stored_title = stored_card.assignment
- if(!stored_name)
- stored_name = "Unknown"
- if(!stored_title)
- stored_title = "Unknown"
- data["login"] = list(
- IDName = stored_name,
- IDJob = stored_title,
- )
+
+ var/stored_name = saved_identification
+ var/stored_title = saved_job
+ if(!stored_name)
+ stored_name = "Unknown"
+ if(!stored_title)
+ stored_title = "Unknown"
+ data["login"] = list(
+ IDName = saved_identification,
+ IDJob = saved_job,
+ )
+ data["proposed_login"] = list(
+ IDName = cardholder.current_identification,
+ IDJob = cardholder.current_job,
+ )
+
+ if(ssd)
+ data["disk"] = ssd
+ data["disk_name"] = ssd.name
+
+ for(var/datum/computer_file/program/prog in ssd.stored_files)
+ var/running = FALSE
+ if(prog in idle_threads)
+ running = TRUE
+
+ data["disk_programs"] += list(list("name" = prog.filename, "desc" = prog.filedesc, "running" = running, "icon" = prog.program_icon, "alert" = prog.alert_pending))
data["removable_media"] = list()
if(all_components[MC_SDD])
@@ -89,6 +122,7 @@
data["has_light"] = has_light
data["light_on"] = light_on
data["comp_light_color"] = comp_light_color
+ data["pai"] = pai
return data
@@ -134,10 +168,15 @@
if("PC_runprogram")
var/prog = params["name"]
+ var/is_disk = params["is_disk"]
var/datum/computer_file/program/P = null
+ var/obj/item/computer_hardware/hard_drive/role/ssd = all_components[MC_HDD_JOB]
var/mob/user = usr
- if(hard_drive)
+
+ if(hard_drive && !is_disk)
P = hard_drive.find_file_by_name(prog)
+ if(ssd && is_disk)
+ P = ssd.find_file_by_name(prog)
if(!P || !istype(P)) // Program not found or it's not executable program.
to_chat(user, span_danger("\The [src]'s screen shows \"I/O ERROR - Unable to run program\" warning."))
@@ -198,6 +237,13 @@
if(uninstall_component(portable_drive, usr))
user.put_in_hands(portable_drive)
playsound(src, 'sound/machines/card_slide.ogg', 50)
+ if("job disk")
+ var/obj/item/computer_hardware/hard_drive/role/ssd = all_components[MC_HDD_JOB]
+ if(!ssd)
+ return
+ if(uninstall_component(ssd, usr))
+ user.put_in_hands(ssd)
+ playsound(src, 'sound/machines/card_slide.ogg', 50)
if("intelliCard")
var/obj/item/computer_hardware/ai_slot/intelliholder = all_components[MC_AI]
if(!intelliholder)
@@ -208,14 +254,37 @@
var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD]
if(!cardholder)
return
- cardholder.try_eject(user)
+ if(cardholder.try_eject(user))
+ playsound(src, 'sound/machines/card_slide.ogg', 50)
if("secondary RFID card")
var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD2]
if(!cardholder)
return
- cardholder.try_eject(user)
+ if(cardholder.try_eject(user))
+ playsound(src, 'sound/machines/card_slide.ogg', 50)
+ if("PC_Imprint_ID")
+ var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD]
+ var/obj/item/computer_hardware/identifier/id_hardware = all_components[MC_IDENTIFY]
+ if(!cardholder)
+ return
+ saved_identification = cardholder.current_identification
+ saved_job = cardholder.current_job
+ if(id_hardware)
+ id_hardware.UpdateDisplay()
+
+ playsound(src, 'sound/machines/terminal_processing.ogg', 15, TRUE)
+ if("PC_Pai_Interact")
+ switch(params["option"])
+ if("eject")
+ usr.put_in_hands(pai)
+ pai.slotted = FALSE
+ pai = null
+ to_chat(usr, span_notice("You remove the pAI from the [name]."))
+ if("interact")
+ pai.attack_self(usr)
+ return UI_UPDATE
else
return
diff --git a/code/modules/modular_computers/computers/item/role_tablet_presets.dm b/code/modules/modular_computers/computers/item/role_tablet_presets.dm
new file mode 100644
index 00000000000..9206c53eb08
--- /dev/null
+++ b/code/modules/modular_computers/computers/item/role_tablet_presets.dm
@@ -0,0 +1,227 @@
+/obj/item/modular_computer/tablet/pda/medical
+ name = "medical PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/medical
+ greyscale_config = /datum/greyscale_config/tablet/stripe_thick
+ greyscale_colors = "#e2e2e2#000099#5d99be"
+
+/obj/item/modular_computer/tablet/pda/viro
+ name = "virology PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/medical
+ greyscale_config = /datum/greyscale_config/tablet/stripe_split
+ greyscale_colors = "#e2e2e2#355FAC#789876"
+
+/obj/item/modular_computer/tablet/pda/engineering
+ name = "engineering PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/engineering
+ greyscale_config = /datum/greyscale_config/tablet/stripe_thick
+ greyscale_colors = "#C5994C#69DBF3#D9D65B"
+
+/obj/item/modular_computer/tablet/pda/security
+ name = "security PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/security
+ greyscale_colors = "#cc4242#0000cc"
+
+/obj/item/modular_computer/tablet/pda/detective
+ name = "detective PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/detective
+ greyscale_colors = "#90714F#990202"
+
+/obj/item/modular_computer/tablet/pda/warden
+ name = "warden PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/security
+ greyscale_config = /datum/greyscale_config/tablet/stripe_split
+ greyscale_colors = "#cc4242#0000cc#666666"
+
+/obj/item/modular_computer/tablet/pda/janitor
+ name = "janitor PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/janitor
+ greyscale_colors = "#933ea8#235AB2"
+
+/obj/item/modular_computer/tablet/pda/science
+ name = "scientist PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/signal/ordnance
+ greyscale_config = /datum/greyscale_config/tablet/stripe_thick
+ greyscale_colors = "#e2e2e2#000099#9F5CA5"
+
+/obj/item/modular_computer/tablet/pda/heads
+ default_disk = /obj/item/computer_hardware/hard_drive/role/head
+ greyscale_config = /datum/greyscale_config/tablet/head
+ greyscale_colors = "#789876#a92323"
+
+/obj/item/modular_computer/tablet/pda/heads/hop
+ name = "head of personnel PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/hop
+
+/obj/item/modular_computer/tablet/pda/heads/hos
+ name = "head of security PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/hos
+ greyscale_config = /datum/greyscale_config/tablet/head
+ greyscale_colors = "#cc4242#0000cc"
+
+/obj/item/modular_computer/tablet/pda/heads/ce
+ name = "chief engineer PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/ce
+ greyscale_config = /datum/greyscale_config/tablet/stripe_thick/head
+ greyscale_colors = "#C4A56D#69DBF3#e2e2e2"
+
+/obj/item/modular_computer/tablet/pda/heads/cmo
+ name = "chief medical officer PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/cmo
+ greyscale_config = /datum/greyscale_config/tablet/stripe_thick/head
+ greyscale_colors = "#e2e2e2#000099#5d99be"
+
+/obj/item/modular_computer/tablet/pda/heads/rd
+ name = "research director PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/rd
+ greyscale_config = /datum/greyscale_config/tablet/stripe_thick/head
+ greyscale_colors = "#e2e2e2#000099#9F5CA5"
+ insert_type = /obj/item/pen/fountain
+
+/obj/item/modular_computer/tablet/pda/captain
+ name = "captain PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/captain
+ greyscale_config = /datum/greyscale_config/tablet/captain
+ greyscale_colors = "#2C7CB2#FF0000#FFFFFF#F5D67B"
+ insert_type = /obj/item/pen/fountain
+
+/obj/item/modular_computer/tablet/pda/captain/Initialize(mapload)
+ . = ..()
+ RegisterSignal(src, COMSIG_TABLET_CHECK_DETONATE, .proc/tab_no_detonate)
+
+/obj/item/modular_computer/tablet/pda/cargo
+ name = "cargo technician PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/quartermaster
+ greyscale_colors = "#D6B328#6506ca"
+
+/obj/item/modular_computer/tablet/pda/quartermaster/Initialize(mapload)
+ . = ..()
+ install_component(new /obj/item/computer_hardware/printer/mini)
+
+/obj/item/modular_computer/tablet/pda/quartermaster
+ name = "quartermaster PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/quartermaster
+ greyscale_config = /datum/greyscale_config/tablet/stripe_thick
+ greyscale_colors = "#D6B328#6506ca#927444"
+
+/obj/item/modular_computer/tablet/pda/quartermaster/Initialize(mapload)
+ . = ..()
+ install_component(new /obj/item/computer_hardware/printer/mini)
+
+/obj/item/modular_computer/tablet/pda/shaftminer
+ name = "shaft miner PDA"
+ greyscale_config = /datum/greyscale_config/tablet/stripe_thick
+ greyscale_colors = "#927444#D6B328#6C3BA1"
+
+/obj/item/modular_computer/tablet/pda/chaplain
+ name = "chaplain PDA"
+ greyscale_config = /datum/greyscale_config/tablet/chaplain
+ greyscale_colors = "#333333#d11818"
+
+/obj/item/modular_computer/tablet/pda/lawyer
+ name = "lawyer PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/lawyer
+ greyscale_colors = "#5B74A5#f7e062"
+ insert_type = /obj/item/pen/fountain
+
+/obj/item/modular_computer/tablet/pda/botanist
+ name = "botanist PDA"
+ greyscale_config = /datum/greyscale_config/tablet/stripe_thick
+ greyscale_colors = "#50E193#E26F41#71A7CA"
+
+/obj/item/modular_computer/tablet/pda/roboticist
+ name = "roboticist PDA"
+ greyscale_config = /datum/greyscale_config/tablet/stripe_split
+ greyscale_colors = "#484848#0099cc#d33725"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/roboticist
+
+/obj/item/modular_computer/tablet/pda/cook
+ name = "cook PDA"
+ greyscale_colors = "#e2e2e2#a92323"
+
+/obj/item/modular_computer/tablet/pda/bar
+ name = "bartender PDA"
+ greyscale_colors = "#333333#c7c7c7"
+
+/obj/item/modular_computer/tablet/pda/atmos
+ name = "atmospherics PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/atmos
+ greyscale_config = /datum/greyscale_config/tablet/stripe_thick
+ greyscale_colors = "#ceca2b#00E5DA#727272"
+
+/obj/item/modular_computer/tablet/pda/chemist
+ name = "chemist PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/chemistry
+ greyscale_config = /datum/greyscale_config/tablet/stripe_thick
+ greyscale_colors = "#e2e2e2#355FAC#ea6400"
+
+/obj/item/modular_computer/tablet/pda/geneticist
+ name = "geneticist PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/medical
+ greyscale_config = /datum/greyscale_config/tablet/stripe_split
+ greyscale_colors = "#e2e2e2#000099#0097ca"
+
+/obj/item/modular_computer/tablet/pda/clown
+ name = "clown PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/virus/clown
+ icon_state = "pda-clown"
+ greyscale_config = null
+ greyscale_colors = null
+ insert_type = /obj/item/toy/crayon/rainbow
+
+/obj/item/modular_computer/tablet/pda/clown/ComponentInitialize()
+ . = ..()
+ AddComponent(/datum/component/slippery/clowning, 120, NO_SLIP_WHEN_WALKING, CALLBACK(src, .proc/AfterSlip), slot_whitelist = list(ITEM_SLOT_ID, ITEM_SLOT_BELT))
+ AddComponent(/datum/component/wearertargeting/sitcomlaughter, CALLBACK(src, .proc/after_sitcom_laugh))
+
+/obj/item/modular_computer/tablet/pda/clown/update_overlays()
+ . = ..()
+ . += mutable_appearance(icon, "pda_stripe_clown") // clowns have eyes that go over their screen, so it needs to be compiled last
+
+/obj/item/modular_computer/tablet/pda/clown/proc/AfterSlip(mob/living/carbon/human/M)
+ if (istype(M) && (M.real_name != saved_identification))
+ var/obj/item/computer_hardware/hard_drive/role/virus/clown/cart = all_components[MC_HDD_JOB]
+ if(istype(cart) && cart.charges < 5)
+ cart.charges++
+ playsound(src,'sound/machines/ping.ogg',30,TRUE)
+
+/obj/item/modular_computer/tablet/pda/clown/proc/after_sitcom_laugh(mob/victim)
+ victim.visible_message("[src] lets out a burst of laughter!")
+
+/obj/item/modular_computer/tablet/pda/mime
+ name = "mime PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/virus/mime
+ greyscale_config = /datum/greyscale_config/tablet/mime
+ greyscale_colors = "#e2e2e2#cc4242"
+ insert_type = /obj/item/toy/crayon/mime
+
+/obj/item/modular_computer/tablet/pda/mime/Initialize(mapload)
+ . = ..()
+ var/obj/item/computer_hardware/hard_drive/hdd = all_components[MC_HDD]
+
+ if(hdd)
+ for(var/datum/computer_file/program/messenger/msg in hdd.stored_files)
+ msg.mime_mode = TRUE
+ msg.allow_emojis = TRUE
+
+/obj/item/modular_computer/tablet/pda/curator
+ name = "curator PDA"
+ default_disk = /obj/item/computer_hardware/hard_drive/role/curator
+ greyscale_config = null
+ greyscale_colors = null
+ icon_state = "pda-library"
+ insert_type = /obj/item/pen/fountain
+ display_overlays = FALSE
+
+/obj/item/modular_computer/tablet/pda/syndicate
+ name = "military PDA"
+ greyscale_colors = "#891417#80FF80"
+ saved_identification = "John Doe"
+ saved_job = "Citizen"
+ invisible = TRUE
+
+/obj/item/modular_computer/tablet/pda/clear
+ name = "clear PDA"
+ icon_state = "pda-clear"
+ greyscale_config = null
+ greyscale_colors = null
+
diff --git a/code/modules/modular_computers/computers/item/tablet.dm b/code/modules/modular_computers/computers/item/tablet.dm
index f69f3bbb0ef..0b7994a4fa0 100644
--- a/code/modules/modular_computers/computers/item/tablet.dm
+++ b/code/modules/modular_computers/computers/item/tablet.dm
@@ -16,16 +16,95 @@
has_light = TRUE //LED flashlight!
comp_light_luminosity = 2.3 //Same as the PDA
looping_sound = FALSE
+
var/has_variants = TRUE
var/finish_color = null
+ var/list/contained_item = list(/obj/item/pen, /obj/item/toy/crayon, /obj/item/lipstick, /obj/item/flashlight/pen, /obj/item/clothing/mask/cigarette)
+ var/obj/item/insert_type = /obj/item/pen
+ var/obj/item/inserted_item
+
+ var/note = "Congratulations on your station upgrading to the new NtOS and Thinktronic based collaboration effort, bringing you the best in electronics and software since 2467!" // the note used by the notekeeping app, stored here for convenience
+
/obj/item/modular_computer/tablet/update_icon_state()
- if(has_variants)
+ if(has_variants && !bypass_state)
if(!finish_color)
finish_color = pick("red", "blue", "brown", "green", "black")
icon_state = icon_state_powered = icon_state_unpowered = "[base_icon_state]-[finish_color]"
return ..()
+/obj/item/modular_computer/tablet/interact(mob/user)
+ . = ..()
+ if(HAS_TRAIT(src, TRAIT_PDA_MESSAGE_MENU_RIGGED))
+ explode(usr, from_message_menu = TRUE)
+ return
+
+/obj/item/modular_computer/tablet/attackby(obj/item/W, mob/user)
+ . = ..()
+
+ if(is_type_in_list(W, contained_item))
+ if(inserted_item)
+ to_chat(user, span_warning("There is already \a [inserted_item] in \the [src]!"))
+ else
+ if(!user.transferItemToLoc(W, src))
+ return
+ to_chat(user, span_notice("You insert \the [W] into \the [src]."))
+ inserted_item = W
+ playsound(src, 'sound/machines/pda_button1.ogg', 50, TRUE)
+
+/obj/item/modular_computer/tablet/AltClick(mob/user)
+ . = ..()
+ if(.)
+ return
+
+ remove_pen(user)
+
+/obj/item/modular_computer/tablet/proc/tab_no_detonate()
+ SIGNAL_HANDLER
+ return COMPONENT_TABLET_NO_DETONATE
+
+/obj/item/modular_computer/tablet/proc/remove_pen(mob/user)
+
+ if(issilicon(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) //TK doesn't work even with this removed but here for readability
+ return
+
+ if(inserted_item)
+ to_chat(user, span_notice("You remove [inserted_item] from [src]."))
+ user.put_in_hands(inserted_item)
+ inserted_item = null
+ update_appearance()
+ playsound(src, 'sound/machines/pda_button2.ogg', 50, TRUE)
+ else
+ to_chat(user, span_warning("This tablet does not have a pen in it!"))
+
+// Tablet 'splosion..
+
+/obj/item/modular_computer/tablet/proc/explode(mob/target, mob/bomber, from_message_menu = FALSE)
+ var/turf/T = get_turf(src)
+
+ if(from_message_menu)
+ log_bomber(null, null, target, "'s tablet exploded as [target.p_they()] tried to open their tablet message menu because of a recent tablet bomb.")
+ else
+ log_bomber(bomber, "successfully tablet-bombed", target, "as [target.p_they()] tried to reply to a rigged tablet message [bomber && !is_special_character(bomber) ? "(SENT BY NON-ANTAG)" : ""]")
+
+ if (ismob(loc))
+ var/mob/M = loc
+ M.show_message(span_userdanger("Your [src] explodes!"), MSG_VISUAL, span_warning("You hear a loud *pop*!"), MSG_AUDIBLE)
+ else
+ visible_message(span_danger("[src] explodes!"), span_warning("You hear a loud *pop*!"))
+
+ target.client?.give_award(/datum/award/achievement/misc/clickbait, target)
+
+ if(T)
+ T.hotspot_expose(700,125)
+ if(istype(all_components[MC_HDD_JOB], /obj/item/computer_hardware/hard_drive/role/virus/deto))
+ explosion(src, devastation_range = -1, heavy_impact_range = 1, light_impact_range = 3, flash_range = 4)
+ else
+ explosion(src, devastation_range = -1, heavy_impact_range = -1, light_impact_range = 2, flash_range = 3)
+ qdel(src)
+
+// SUBTYPES
+
/obj/item/modular_computer/tablet/syndicate_contract_uplink
name = "contractor tablet"
icon = 'icons/obj/contractor_tablet.dmi'
@@ -65,8 +144,8 @@
has_light = FALSE //tablet light button actually enables/disables the borg lamp
comp_light_luminosity = 0
has_variants = FALSE
- ///Ref to the borg we're installed in. Set by the borg during our creation.
- var/mob/living/silicon/robot/borgo
+ ///Ref to the silicon we're installed in. Set by the borg during our creation.
+ var/mob/living/silicon/borgo
///Ref to the RoboTact app. Important enough to borgs to deserve a ref.
var/datum/computer_file/program/robotact/robotact
///IC log that borgs can view in their personal management app
@@ -119,22 +198,28 @@
/obj/item/modular_computer/tablet/integrated/ui_data(mob/user)
. = ..()
.["has_light"] = TRUE
- .["light_on"] = borgo?.lamp_enabled
- .["comp_light_color"] = borgo?.lamp_color
+ if(istype(borgo, /mob/living/silicon/robot))
+ var/mob/living/silicon/robot/robo = borgo
+ .["light_on"] = robo.lamp_enabled
+ .["comp_light_color"] = robo.lamp_color
//Makes the flashlight button affect the borg rather than the tablet
/obj/item/modular_computer/tablet/integrated/toggle_flashlight()
if(!borgo || QDELETED(borgo))
return FALSE
- borgo.toggle_headlamp()
+ if(istype(borgo, /mob/living/silicon/robot))
+ var/mob/living/silicon/robot/robo = borgo
+ robo.toggle_headlamp()
return TRUE
//Makes the flashlight color setting affect the borg rather than the tablet
/obj/item/modular_computer/tablet/integrated/set_flashlight_color(color)
if(!borgo || QDELETED(borgo) || !color)
return FALSE
- borgo.lamp_color = color
- borgo.toggle_headlamp(FALSE, TRUE)
+ if(istype(borgo, /mob/living/silicon/robot))
+ var/mob/living/silicon/robot/robo = borgo
+ robo.lamp_color = color
+ robo.toggle_headlamp(FALSE, TRUE)
return TRUE
/obj/item/modular_computer/tablet/integrated/alert_call(datum/computer_file/program/caller, alerttext, sound = 'sound/machines/twobeep_high.ogg')
@@ -143,6 +228,8 @@
borgo.playsound_local(src, sound, 50, TRUE)
to_chat(borgo, span_notice("The [src] displays a [caller.filedesc] notification: [alerttext]"))
+/obj/item/modular_computer/tablet/integrated/ui_state(mob/user)
+ return GLOB.reverse_contained_state
/obj/item/modular_computer/tablet/integrated/syndicate
icon_state = "tablet-silicon-syndicate"
@@ -153,4 +240,51 @@
/obj/item/modular_computer/tablet/integrated/syndicate/Initialize(mapload)
. = ..()
- borgo.lamp_color = COLOR_RED //Syndicate likes it red
+ if(istype(borgo, /mob/living/silicon/robot))
+ var/mob/living/silicon/robot/robo = borgo
+ robo.lamp_color = COLOR_RED //Syndicate likes it red
+
+// Round start tablets
+
+/obj/item/modular_computer/tablet/pda
+ icon_state = "pda"
+
+ greyscale_config = /datum/greyscale_config/tablet
+ greyscale_colors = "#999875#a92323"
+
+ bypass_state = TRUE
+
+ var/default_disk = 0
+
+/obj/item/modular_computer/tablet/pda/update_overlays()
+ . = ..()
+ var/init_icon = initial(icon)
+ var/obj/item/computer_hardware/card_slot/card = all_components[MC_CARD]
+ if(!init_icon)
+ return
+ if(card)
+ if(card.stored_card)
+ . += mutable_appearance(init_icon, "id_overlay")
+ if(light_on)
+ . += mutable_appearance(init_icon, "light_overlay")
+
+/obj/item/modular_computer/tablet/pda/attack_ai(mob/user)
+ to_chat(user, span_notice("It doesn't feel right to snoop around like that..."))
+ return // we don't want ais or cyborgs using a private role tablet
+
+/obj/item/modular_computer/tablet/pda/Initialize(mapload)
+ . = ..()
+ install_component(new /obj/item/computer_hardware/hard_drive/small)
+ install_component(new /obj/item/computer_hardware/processor_unit/small)
+ install_component(new /obj/item/computer_hardware/battery(src, /obj/item/stock_parts/cell/computer))
+ install_component(new /obj/item/computer_hardware/network_card)
+ install_component(new /obj/item/computer_hardware/card_slot)
+ install_component(new /obj/item/computer_hardware/identifier)
+ install_component(new /obj/item/computer_hardware/sensorpackage)
+
+ if(default_disk)
+ var/obj/item/computer_hardware/hard_drive/portable/disk = new default_disk(src)
+ install_component(disk)
+
+ if(insert_type)
+ inserted_item = new insert_type(src)
diff --git a/code/modules/modular_computers/computers/item/tablet_presets.dm b/code/modules/modular_computers/computers/item/tablet_presets.dm
index 3bfb7f91ec8..1bb4124fdf5 100644
--- a/code/modules/modular_computers/computers/item/tablet_presets.dm
+++ b/code/modules/modular_computers/computers/item/tablet_presets.dm
@@ -106,9 +106,6 @@
//Borg Built-in tablet
/obj/item/modular_computer/tablet/integrated/Initialize(mapload)
. = ..()
- var/obj/item/computer_hardware/hard_drive/small/integrated/hard_drive = new // SKYRAT EDIT ADD
install_component(new /obj/item/computer_hardware/processor_unit/small)
- install_component(hard_drive) // SKYRAT EDIT -- ORIGINAL install_component(new /obj/item/computer_hardware/hard_drive/small/integrated/)
install_component(new /obj/item/computer_hardware/recharger/cyborg)
install_component(new /obj/item/computer_hardware/network_card/integrated)
- hard_drive.store_file(new /datum/computer_file/program/crew_manifest) // SKYRAT EDIT ADD
diff --git a/code/modules/modular_computers/file_system/programs/newscasterapp.dm b/code/modules/modular_computers/file_system/programs/newscasterapp.dm
index dd3fcb8d5fe..8b422470fda 100644
--- a/code/modules/modular_computers/file_system/programs/newscasterapp.dm
+++ b/code/modules/modular_computers/file_system/programs/newscasterapp.dm
@@ -3,7 +3,7 @@
filedesc = "Newscaster"
required_access = list(ACCESS_LIBRARY)
category = PROGRAM_CATEGORY_CREW
- program_icon_state = "computer"
+ program_icon_state = "bountyboard"
extended_desc = "This program allows any user to access the Newscaster network from anywhere."
size = 2
requires_ntnet = TRUE
diff --git a/code/modules/modular_computers/file_system/programs/notepad.dm b/code/modules/modular_computers/file_system/programs/notepad.dm
new file mode 100644
index 00000000000..1d505cc42c1
--- /dev/null
+++ b/code/modules/modular_computers/file_system/programs/notepad.dm
@@ -0,0 +1,29 @@
+/datum/computer_file/program/notepad
+ filename = "notepad"
+ filedesc = "Notepad"
+ category = PROGRAM_CATEGORY_MISC
+ program_icon_state = "generic"
+ extended_desc = "Jot down your work-safe thoughts and what not."
+ size = 2
+ tgui_id = "NtosNotepad"
+ program_icon = "book"
+ usage_flags = PROGRAM_TABLET
+
+/datum/computer_file/program/notepad/ui_act(action, list/params, datum/tgui/ui)
+ . = ..()
+ if(.)
+ return
+
+ switch(action)
+ if("UpdateNote")
+ var/obj/item/modular_computer/tablet/comp = computer
+ comp.note = params["newnote"]
+ return UI_UPDATE
+
+/datum/computer_file/program/notepad/ui_data(mob/user)
+ var/list/data = get_header_data()
+ var/obj/item/modular_computer/tablet/comp = computer
+
+ data["note"] = comp.note
+
+ return data
diff --git a/code/modules/modular_computers/file_system/programs/ntmessenger.dm b/code/modules/modular_computers/file_system/programs/ntmessenger.dm
new file mode 100644
index 00000000000..9dfcd8e929e
--- /dev/null
+++ b/code/modules/modular_computers/file_system/programs/ntmessenger.dm
@@ -0,0 +1,366 @@
+/datum/computer_file/program/messenger
+ filename = "nt_messenger"
+ filedesc = "Direct Messenger"
+ category = PROGRAM_CATEGORY_MISC
+ program_icon_state = "command"
+ extended_desc = "This program allows old-school communication with other modular devices."
+ size = 8
+ usage_flags = PROGRAM_TABLET
+ ui_header = "ntnrc_idle.gif"
+ available_on_ntnet = TRUE
+ tgui_id = "NtosMessenger"
+ program_icon = "comment-alt"
+ alert_able = TRUE
+
+ /// The current ringtone (displayed in the chat when a message is received).
+ var/ringtone = "beep"
+ /// Whether or not the ringtone is currently on.
+ var/ringer_status = TRUE
+ /// Whether or not we're sending and receiving messages.
+ var/sending_and_receiving = TRUE
+ /// The messages currently saved in the app.
+ var/messages = list()
+ /// great wisdom from PDA.dm - "no spamming" (prevents people from spamming the same message over and over)
+ var/last_text
+ /// even more wisdom from PDA.dm - "no everyone spamming" (prevents people from spamming the same message over and over)
+ var/last_text_everyone
+ /// Scanned photo for sending purposes.
+ var/datum/picture/picture
+ /// Whether or not we allow emojis to be sent by the user.
+ var/allow_emojis = FALSE
+ /// Whether or not we're currently looking at the message list.
+ var/viewing_messages = FALSE
+ // Whether or not this device is currently hidden from the message monitor.
+ var/monitor_hidden = FALSE
+ // Whether or not we're sorting by job.
+ var/sort_by_job = TRUE
+ // Whether or not we're sending (or trying to send) a virus.
+ var/sending_virus = FALSE
+
+ /// The path for the current loaded image in rsc
+ var/photo_path
+
+ /// Whether or not this app is loaded on a silicon's tablet.
+ var/is_silicon = FALSE
+ /// Whether or not we're in a mime PDA.
+ var/mime_mode = FALSE
+
+/datum/computer_file/program/messenger/proc/ScrubMessengerList()
+ var/list/dictionary = list()
+
+ for(var/obj/item/modular_computer/messenger in GetViewableDevices(sort_by_job))
+ if(messenger.saved_identification && messenger.saved_job && !(messenger == computer))
+ var/list/data = list()
+ data["name"] = messenger.saved_identification
+ data["job"] = messenger.saved_job
+ data["ref"] = REF(messenger)
+
+ //if(data["ref"] != REF(computer)) // you cannot message yourself (despite all my rage)
+ dictionary += list(data)
+
+ return dictionary
+
+/proc/GetViewableDevices(sort_by_job = FALSE)
+ var/list/dictionary = list()
+
+ var/sortmode
+ if(sort_by_job)
+ sortmode = /proc/cmp_pdajob_asc
+ else
+ sortmode = /proc/cmp_pdaname_asc
+
+ for(var/obj/item/modular_computer/P in sort_list(GLOB.TabletMessengers, sortmode))
+ var/obj/item/computer_hardware/hard_drive/drive = P.all_components[MC_HDD]
+ if(!drive)
+ continue
+ for(var/datum/computer_file/program/messenger/app in drive.stored_files)
+ if(!P.saved_identification || !P.saved_job || P.invisible || app.monitor_hidden)
+ continue
+ dictionary += P
+
+ return dictionary
+
+/datum/computer_file/program/messenger/proc/StringifyMessengerTarget(obj/item/modular_computer/messenger)
+ return "[messenger.saved_identification] ([messenger.saved_job])"
+
+/datum/computer_file/program/messenger/proc/ProcessPhoto()
+ if(computer.saved_image)
+ var/icon/img = computer.saved_image.picture_image
+ var/deter_path = "tmp_msg_photo[rand(0, 99999)].png"
+ usr << browse_rsc(img, deter_path) // funny random assignment for now, i'll make an actual key later
+ photo_path = deter_path
+
+/datum/computer_file/program/messenger/ui_state(mob/user)
+ if(istype(user, /mob/living/silicon))
+ return GLOB.reverse_contained_state
+ return GLOB.default_state
+
+/datum/computer_file/program/messenger/ui_act(action, list/params, datum/tgui/ui)
+ . = ..()
+ if(.)
+ return
+
+ switch(action)
+ if("PDA_ringSet")
+ var/t = tgui_input_text(usr, "Enter a new ringtone", "Ringtone", "", 20)
+ var/mob/living/usr_mob = usr
+ if(in_range(computer, usr_mob) && computer.loc == usr_mob && t)
+ if(SEND_SIGNAL(computer, COMSIG_TABLET_CHANGE_ID, usr_mob, t) & COMPONENT_STOP_RINGTONE_CHANGE)
+ return
+ else
+ ringtone = t
+ return(UI_UPDATE)
+ if("PDA_ringer_status")
+ ringer_status = !ringer_status
+ return(UI_UPDATE)
+ if("PDA_sAndR")
+ sending_and_receiving = !sending_and_receiving
+ return(UI_UPDATE)
+ if("PDA_viewMessages")
+ viewing_messages = !viewing_messages
+ return(UI_UPDATE)
+ if("PDA_clearMessages")
+ messages = list()
+ return(UI_UPDATE)
+ if("PDA_changeSortStyle")
+ sort_by_job = !sort_by_job
+ return(UI_UPDATE)
+ if("PDA_sendEveryone")
+ if(!sending_and_receiving)
+ to_chat(usr, span_notice("ERROR: Device has sending disabled."))
+ return
+
+ var/list/targets = list()
+
+ for(var/obj/item/modular_computer/mc in GetViewableDevices())
+ targets += mc
+
+ if(targets.len > 0)
+ send_message(usr, targets, TRUE)
+
+ return(UI_UPDATE)
+ if("PDA_sendMessage")
+ if(!sending_and_receiving)
+ to_chat(usr, span_notice("ERROR: Device has sending disabled."))
+ return
+ var/obj/item/modular_computer/target = locate(params["ref"])
+ if(!target)
+ return // we don't want tommy sending his messages to nullspace
+ if(!(target.saved_identification == params["name"] && target.saved_job == params["job"]))
+ to_chat(usr, span_notice("ERROR: User no longer exists."))
+ return
+
+ var/obj/item/computer_hardware/hard_drive/drive = target.all_components[MC_HDD]
+
+ for(var/datum/computer_file/program/messenger/app in drive.stored_files)
+ if(!app.sending_and_receiving && !sending_virus)
+ to_chat(usr, span_notice("ERROR: Device has receiving disabled."))
+ return
+ if(sending_virus)
+ var/obj/item/computer_hardware/hard_drive/role/virus/disk = computer.all_components[MC_HDD_JOB]
+ if(istype(disk))
+ disk.send_virus(target, usr)
+ return(UI_UPDATE)
+ send_message(usr, list(target))
+ return(UI_UPDATE)
+ if("PDA_clearPhoto")
+ computer.saved_image = null
+ photo_path = null
+ return(UI_UPDATE)
+ if("PDA_toggleVirus")
+ sending_virus = !sending_virus
+ return(UI_UPDATE)
+
+
+/datum/computer_file/program/messenger/ui_data(mob/user)
+ var/list/data = get_header_data()
+
+ var/obj/item/computer_hardware/hard_drive/role/disk = computer.all_components[MC_HDD_JOB]
+
+ data["owner"] = computer.saved_identification
+ data["messages"] = messages
+ data["ringer_status"] = ringer_status
+ data["sending_and_receiving"] = sending_and_receiving
+ data["messengers"] = ScrubMessengerList()
+ data["viewing_messages"] = viewing_messages
+ data["sortByJob"] = sort_by_job
+ data["isSilicon"] = is_silicon
+ data["photo"] = photo_path
+
+ if(disk)
+ data["canSpam"] = disk.CanSpam()
+ data["virus_attach"] = istype(disk, /obj/item/computer_hardware/hard_drive/role/virus)
+ data["sending_virus"] = sending_virus
+
+ return data
+
+////////////////////////
+// MESSAGE HANDLING
+////////////////////////
+
+// How I Learned To Stop Being A PDA Bloat Chump And Learn To Embrace The Lightweight
+
+// Gets the input for a message being sent.
+
+/datum/computer_file/program/messenger/proc/msg_input(mob/living/U = usr, rigged = FALSE)
+ var/t = null
+
+ if(mime_mode)
+ t = emoji_sanitize(tgui_input_text(U, "Enter emojis", "NT Messaging"))
+ else
+ t = tgui_input_text(U, "Enter a message", "NT Messaging")
+
+ if (!t || !sending_and_receiving)
+ return
+ if(!U.canUseTopic(computer, BE_CLOSE))
+ return
+ return sanitize(t)
+
+/datum/computer_file/program/messenger/proc/send_message(mob/living/user, list/obj/item/modular_computer/targets, everyone = FALSE, rigged = FALSE, fake_name = null, fake_job = null)
+ var/message = msg_input(user, rigged)
+ if(!message || !targets.len)
+ return FALSE
+ if((last_text && world.time < last_text + 10) || (everyone && last_text_everyone && world.time < last_text_everyone + 2 MINUTES))
+ return FALSE
+
+ var/turf/position = get_turf(computer)
+ for(var/obj/item/jammer/jammer as anything in GLOB.active_jammers)
+ var/turf/jammer_turf = get_turf(jammer)
+ if(position?.z == jammer_turf.z && (get_dist(position, jammer_turf) <= jammer.range))
+ return FALSE
+
+ var/list/filter_result = CAN_BYPASS_FILTER(user) ? null : is_ic_filtered_for_pdas(message)
+ if (filter_result)
+ REPORT_CHAT_FILTER_TO_USER(user, filter_result)
+ return FALSE
+
+ var/list/soft_filter_result = CAN_BYPASS_FILTER(user) ? null : is_soft_ic_filtered_for_pdas(message)
+ if (soft_filter_result)
+ if(tgui_alert(usr,"Your message contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to send it?", "Soft Blocked Word", list("Yes", "No")) != "Yes")
+ return FALSE
+ message_admins("[ADMIN_LOOKUPFLW(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term in PDA messages. Message: \"[html_encode(message)]\"")
+ log_admin_private("[key_name(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term in PDA messages. Message: \"[message]\"")
+
+ // Send the signal
+ var/list/string_targets = list()
+ for (var/obj/item/modular_computer/comp in targets)
+ if (comp.saved_identification && comp.saved_job) // != src is checked by the UI
+ string_targets += STRINGIFY_PDA_TARGET(comp.saved_identification, comp.saved_job)
+
+ if (!string_targets.len)
+ return FALSE
+
+ var/datum/signal/subspace/messaging/tablet_msg/signal = new(computer, list(
+ "name" = fake_name || computer.saved_identification,
+ "job" = fake_job || computer.saved_job,
+ "message" = html_decode(message),
+ "ref" = REF(computer),
+ "targets" = targets,
+ "emojis" = allow_emojis,
+ "rigged" = rigged,
+ "photo" = photo_path,
+ "automated" = FALSE,
+ ))
+ if(rigged) //Will skip the message server and go straight to the hub so it can't be cheesed by disabling the message server machine
+ signal.data["rigged_user"] = REF(user) // Used for bomb logging
+ signal.server_type = /obj/machinery/telecomms/hub
+ signal.data["reject"] = FALSE // Do not refuse the message
+
+ signal.send_to_receivers()
+
+ // If it didn't reach, note that fact
+ if (!signal.data["done"])
+ to_chat(user, span_notice("ERROR: Server isn't responding."))
+ //if(!silent)
+ //playsound(src, 'sound/machines/terminal_error.ogg', 15, TRUE)
+ return FALSE
+
+ if(allow_emojis)
+ message = emoji_parse(message)//already sent- this just shows the sent emoji as one to the sender in the to_chat
+ signal.data["message"] = emoji_parse(signal.data["message"])
+
+ // Log it in our logs
+ var/list/message_data = list()
+ message_data["name"] = signal.data["name"]
+ message_data["job"] = signal.data["job"]
+ message_data["contents"] = html_decode(signal.data["message"])
+ message_data["outgoing"] = TRUE
+ message_data["ref"] = signal.data["ref"]
+ message_data["photo"] = signal.data["photo"]
+
+ // Show it to ghosts
+ var/ghost_message = span_name("[message_data["name"]] [rigged ? "Rigged" : ""] PDA Message --> [span_name("[signal.format_target()]")]: [signal.data["message"]]")
+ for(var/mob/M in GLOB.player_list)
+ if(isobserver(M) && (M.client?.prefs.chat_toggles & CHAT_GHOSTPDA))
+ to_chat(M, "[FOLLOW_LINK(M, user)] [ghost_message]")
+
+ // Log in the talk log
+ user.log_talk(message, LOG_PDA, tag="[rigged ? "Rigged" : ""] PDA: [initial(message_data["name"])] to [signal.format_target()]")
+ if(rigged)
+ log_bomber(user, "sent a rigged PDA message (Name: [message_data["name"]]. Job: [message_data["job"]]) to [english_list(string_targets)] [!is_special_character(user) ? "(SENT BY NON-ANTAG)" : ""]")
+ to_chat(user, span_info("PDA message sent to [signal.format_target()]: [signal.data["message"]]"))
+
+ if (ringer_status)
+ computer.send_sound()
+
+ last_text = world.time
+ if (everyone)
+ message_data["name"] = "Everyone"
+ message_data["job"] = ""
+ last_text_everyone = world.time
+
+ messages += list(message_data)
+ return TRUE
+
+/datum/computer_file/program/messenger/proc/receive_message(datum/signal/subspace/messaging/tablet_msg/signal)
+ var/list/message_data = list()
+ message_data["name"] = signal.data["name"]
+ message_data["job"] = signal.data["job"]
+ message_data["contents"] = html_decode(signal.data["message"])
+ message_data["outgoing"] = FALSE
+ message_data["ref"] = signal.data["ref"]
+ message_data["automated"] = signal.data["automated"]
+ message_data["photo"] = signal.data["photo"]
+ messages += list(message_data)
+
+ var/mob/living/L = null
+ if(computer.loc && isliving(computer.loc))
+ L = computer.loc
+ //Maybe they are a pAI!
+ else
+ L = get(computer, /mob/living/silicon)
+
+ if(L && (L.stat == CONSCIOUS || L.stat == SOFT_CRIT))
+ var/reply = "(Reply )"
+ var/hrefstart
+ var/hrefend
+ if (isAI(L))
+ hrefstart = ""
+ hrefend = " "
+
+ if(signal.data["automated"])
+ reply = "\[Automated Message\]"
+
+ var/inbound_message = signal.format_message()
+ if(signal.data["emojis"] == TRUE)//so will not parse emojis as such from pdas that don't send emojis
+ inbound_message = emoji_parse(inbound_message)
+
+ if(ringer_status)
+ to_chat(L, "[icon2html(src)] PDA message from [hrefstart][signal.data["name"]] ([signal.data["job"]])[hrefend], [inbound_message] [reply] ")
+
+
+ if (ringer_status)
+ computer.ring(ringtone)
+
+/datum/computer_file/program/messenger/Topic(href, href_list)
+ ..()
+
+ if(!href_list["close"] && usr.canUseTopic(computer, BE_CLOSE, FALSE, NO_TK))
+ switch(href_list["choice"])
+ if("Message")
+ send_message(usr, list(locate(href_list["target"])))
+ if("Mess_us_up")
+ if(!HAS_TRAIT(src, TRAIT_PDA_CAN_EXPLODE))
+ var/obj/item/modular_computer/tablet/comp = computer
+ comp.explode(usr, from_message_menu = TRUE)
+ return
diff --git a/code/modules/modular_computers/file_system/programs/phys_scanner.dm b/code/modules/modular_computers/file_system/programs/phys_scanner.dm
new file mode 100644
index 00000000000..804ada70b8e
--- /dev/null
+++ b/code/modules/modular_computers/file_system/programs/phys_scanner.dm
@@ -0,0 +1,78 @@
+/datum/computer_file/program/phys_scanner
+ filename = "phys_scanner"
+ filedesc = "Physical Scanner"
+ category = PROGRAM_CATEGORY_MISC
+ extended_desc = "This program allows the tablet to scan physical objects and display a data output."
+ size = 8
+ usage_flags = PROGRAM_TABLET
+ available_on_ntnet = FALSE
+ tgui_id = "NtosPhysScanner"
+ program_icon = "barcode"
+
+ var/current_mode = 0
+ var/available_modes = 0
+
+ var/last_record = ""
+
+/datum/computer_file/program/phys_scanner/proc/ReadModes()
+ var/reads = list()
+
+ if(available_modes & DISK_CHEM)
+ reads += "Reagent"
+
+ if(available_modes & DISK_MED)
+ reads += "Health"
+
+ return reads
+
+/datum/computer_file/program/phys_scanner/proc/ReadCurrent()
+ if(current_mode & DISK_CHEM)
+ return "Reagent"
+ if(current_mode & DISK_MED)
+ return "Health"
+
+/datum/computer_file/program/phys_scanner/tap(atom/A, mob/living/user, params)
+ . = ..()
+
+ switch(current_mode)
+ if(DISK_CHEM)
+ if(!isnull(A.reagents))
+ if(A.reagents.reagent_list.len > 0)
+ var/reagents_length = A.reagents.reagent_list.len
+ last_record = "[reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found."
+ for (var/re in A.reagents.reagent_list)
+ last_record += "\t [re]"
+ else
+ last_record = "No active chemical agents found in [A]."
+ else
+ last_record = "No significant chemical agents found in [A]."
+ if(DISK_MED)
+ var/mob/living/carbon/carbon = A
+ if(istype(carbon))
+ carbon.visible_message(span_notice("[user] analyzes [A]'s vitals."))
+ last_record = healthscan(user, carbon, 1, tochat = FALSE)
+
+/datum/computer_file/program/phys_scanner/ui_act(action, list/params, datum/tgui/ui)
+ . = ..()
+ if(.)
+ return
+
+ switch(action)
+ if("selectMode")
+ switch(params["newMode"])
+ if("Reagent")
+ current_mode = DISK_CHEM
+ if("Health")
+ current_mode = DISK_MED
+
+ return UI_UPDATE
+
+
+/datum/computer_file/program/phys_scanner/ui_data(mob/user)
+ var/list/data = get_header_data()
+
+ data["set_mode"] = ReadCurrent()
+ data["last_record"] = last_record
+ data["available_modes"] = ReadModes()
+
+ return data
diff --git a/code/modules/modular_computers/file_system/programs/records.dm b/code/modules/modular_computers/file_system/programs/records.dm
new file mode 100644
index 00000000000..d96f89779fe
--- /dev/null
+++ b/code/modules/modular_computers/file_system/programs/records.dm
@@ -0,0 +1,74 @@
+/datum/computer_file/program/records
+ filename = "ntrecords"
+ filedesc = "Records"
+ extended_desc = "Allows the user to view several basic records from the crew."
+ category = PROGRAM_CATEGORY_MISC
+ program_icon = "clipboard"
+ program_icon_state = "crew"
+ tgui_id = "NtosRecords"
+ size = 4
+ usage_flags = PROGRAM_TABLET | PROGRAM_LAPTOP
+ available_on_ntnet = FALSE
+
+ var/mode
+
+/datum/computer_file/program/records/medical
+ filedesc = "Medical Records"
+ filename = "medrecords"
+ program_icon = "book-medical"
+ extended_desc = "Allows the user to view several basic medical records from the crew."
+ transfer_access = list(ACCESS_MEDICAL, ACCESS_FLAG_COMMAND)
+ available_on_ntnet = TRUE
+ mode = "medical"
+
+/datum/computer_file/program/records/security
+ filedesc = "Security Records"
+ filename = "secrecords"
+ extended_desc = "Allows the user to view several basic security records from the crew."
+ transfer_access = list(ACCESS_SECURITY, ACCESS_FLAG_COMMAND)
+ available_on_ntnet = TRUE
+ mode = "security"
+
+/datum/computer_file/program/records/proc/GetRecordsReadable()
+ var/list/all_records = list()
+
+ switch(mode)
+ if("security")
+ for(var/datum/data/record/person in GLOB.data_core.general)
+ var/datum/data/record/security_person = find_record("id", person.fields["id"], GLOB.data_core.security)
+ var/list/current_record = list()
+
+ if(security_person)
+ current_record["wanted"] = security_person.fields["criminal"]
+
+ current_record["id"] = person.fields["id"]
+ current_record["name"] = person.fields["name"]
+ current_record["rank"] = person.fields["rank"]
+ current_record["gender"] = person.fields["gender"]
+ current_record["age"] = person.fields["age"]
+ current_record["species"] = person.fields["species"]
+ current_record["fingerprint"] = person.fields["fingerprint"]
+
+ all_records += list(current_record)
+ if("medical")
+ for(var/datum/data/record/person in GLOB.data_core.medical)
+ var/list/current_record = list()
+
+ current_record["name"] = person.fields["name"]
+ current_record["bloodtype"] = person.fields["blood_type"]
+ current_record["mi_dis"] = person.fields["mi_dis"]
+ current_record["ma_dis"] = person.fields["ma_dis"]
+ current_record["notes"] = person.fields["notes"]
+ current_record["cnotes"] = person.fields["notes_d"]
+
+ all_records += list(current_record)
+
+ return all_records
+
+
+
+/datum/computer_file/program/records/ui_data(mob/user)
+ var/list/data = get_header_data()
+ data["records"] = GetRecordsReadable()
+ data["mode"] = mode
+ return data
diff --git a/code/modules/modular_computers/file_system/programs/robocontrol.dm b/code/modules/modular_computers/file_system/programs/robocontrol.dm
index e7d7e89ae30..b3cdb793a45 100644
--- a/code/modules/modular_computers/file_system/programs/robocontrol.dm
+++ b/code/modules/modular_computers/file_system/programs/robocontrol.dm
@@ -13,6 +13,8 @@
var/botcount = 0
///Access granted by the used to summon robots.
var/list/current_access = list()
+ ///Whether or not this is the cartridge program version.
+ var/cart_mode = FALSE
var/list/drone_ping_types = list(
"Low",
"Medium",
@@ -27,20 +29,23 @@
var/list/botlist = list()
var/list/mulelist = list()
+ var/obj/item/computer_hardware/hard_drive/role/job_disk = computer ? computer.all_components[MC_HDD_JOB] : null
var/obj/item/computer_hardware/card_slot/card_slot = computer ? computer.all_components[MC_CARD] : null
- var/obj/item/card/id/id_card = card_slot?.stored_card
data["have_id_slot"] = !!card_slot
if(computer)
- data["has_id"] = !!id_card
- data["id_owner"] = id_card ? id_card.registered_name : "No Card Inserted."
- data["access_on_card"] = id_card ? id_card.access : null
+ var/obj/item/card/id/id_card = card_slot ? card_slot.stored_card : ""
+ data["id_owner"] = id_card
+ if(cart_mode && job_disk)
+ data["id_owner"] = "JOB DISK OVERRIDE"
botcount = 0
for(var/mob/living/simple_animal/bot/simple_bot as anything in GLOB.bots_list)
if(simple_bot.z != zlevel || !(simple_bot.bot_mode_flags & BOT_MODE_REMOTE_ENABLED)) //Only non-emagged bots on the same Z-level are detected!
continue
- if(computer && !simple_bot.check_access(user, id_card)) // Only check Bots we can access
+ if(computer && !simple_bot.check_access(user) && !cart_mode) // Only check Bots we can access)
+ continue
+ if(!(simple_bot.bot_type in job_disk.bot_access) && cart_mode)
continue
var/list/newbot = list(
"name" = simple_bot.name,
diff --git a/code/modules/modular_computers/file_system/programs/signaler.dm b/code/modules/modular_computers/file_system/programs/signaler.dm
index 125b43e4d67..78b2897466f 100644
--- a/code/modules/modular_computers/file_system/programs/signaler.dm
+++ b/code/modules/modular_computers/file_system/programs/signaler.dm
@@ -19,14 +19,16 @@
. = ..()
if (!.)
return
- if(!computer?.get_modular_computer_part(MC_SIGNALER)) //Giving a clue to users why the program is spitting out zeros.
+ var/obj/item/computer_hardware/hard_drive/role/signal/disk = computer?.get_modular_computer_part(MC_HDD_JOB)
+ if(!(computer?.get_modular_computer_part(MC_SIGNALER) || istype(disk))) //Giving a clue to users why the program is spitting out zeros.
to_chat(user, span_warning("\The [computer] flashes an error: \"hardware\\signal_hardware\\startup.bin -- file not found\"."))
/datum/computer_file/program/signaler/ui_data(mob/user)
var/list/data = get_header_data()
var/obj/item/computer_hardware/radio_card/sensor = computer?.get_modular_computer_part(MC_SIGNALER)
- if(sensor?.check_functionality())
+ var/obj/item/computer_hardware/hard_drive/role/signal/disk = computer?.get_modular_computer_part(MC_HDD_JOB)
+ if(sensor?.check_functionality() || istype(disk))
data["frequency"] = signal_frequency
data["code"] = signal_code
data["minFrequency"] = MIN_FREE_FREQ
@@ -38,7 +40,8 @@
if(.)
return
var/obj/item/computer_hardware/radio_card/sensor = computer?.get_modular_computer_part(MC_SIGNALER)
- if(!(sensor?.check_functionality()))
+ var/obj/item/computer_hardware/hard_drive/role/signal/disk = computer?.get_modular_computer_part(MC_HDD_JOB)
+ if(!(sensor?.check_functionality() || istype(disk)))
playsound(src, 'sound/machines/scanbuzz.ogg', 100, FALSE)
return
switch(action)
@@ -65,18 +68,19 @@
return
var/time = time2text(world.realtime,"hh:mm:ss")
- var/turf/T = get_turf(src)
+ var/turf/T = get_turf(computer)
var/logging_data
if(usr)
- logging_data = "[time] : [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(signal_frequency)]/[signal_code]"
+ message_admins("usr is true")
+ logging_data = "[time] : [usr.key] used [computer] @ location ([T.x],[T.y],[T.z]) : [format_frequency(signal_frequency)]/[signal_code]"
GLOB.lastsignalers.Add(logging_data)
var/datum/signal/signal = new(list("code" = signal_code), logging_data = logging_data)
- radio_connection.post_signal(src, signal)
+ radio_connection.post_signal(computer, signal)
/datum/computer_file/program/signaler/proc/set_frequency(new_frequency)
- SSradio.remove_object(src, signal_frequency)
+ SSradio.remove_object(computer, signal_frequency)
signal_frequency = new_frequency
- radio_connection = SSradio.add_object(src, signal_frequency, RADIO_SIGNALER)
+ radio_connection = SSradio.add_object(computer, signal_frequency, RADIO_SIGNALER)
return
diff --git a/code/modules/modular_computers/file_system/programs/statusdisplay.dm b/code/modules/modular_computers/file_system/programs/statusdisplay.dm
new file mode 100644
index 00000000000..30f7c297f18
--- /dev/null
+++ b/code/modules/modular_computers/file_system/programs/statusdisplay.dm
@@ -0,0 +1,55 @@
+/datum/computer_file/program/status
+ filename = "statusdisplay"
+ filedesc = "Status Display"
+ program_icon = "signal"
+ program_icon_state = "generic"
+ requires_ntnet = TRUE
+ size = 4
+
+ extended_desc = "An app used to change the message on the station status displays."
+ tgui_id = "NtosStatus"
+
+ usage_flags = PROGRAM_ALL
+ available_on_ntnet = FALSE
+
+ var/upper_text
+ var/lower_text
+
+/datum/computer_file/program/status/proc/SendSignal()
+ var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS)
+
+ if(!frequency)
+ return
+
+ var/datum/signal/status_signal = new(list("command" = "message"))
+
+ status_signal.data["msg1"] = reject_bad_text(upper_text || "", MAX_STATUS_LINE_LENGTH)
+ status_signal.data["msg2"] = reject_bad_text(lower_text || "", MAX_STATUS_LINE_LENGTH)
+
+ frequency.post_signal(computer, status_signal)
+
+/datum/computer_file/program/status/proc/SetText(position, text)
+ switch(position)
+ if("upper")
+ upper_text = text
+ if("lower")
+ lower_text = text
+
+/datum/computer_file/program/status/ui_act(action, list/params, datum/tgui/ui)
+ . = ..()
+ if(.)
+ return
+
+ switch(action)
+ if("stat_send")
+ SendSignal()
+ if("stat_update")
+ SetText(params["position"], params["text"]) // i hate the player i hate the player
+
+/datum/computer_file/program/status/ui_data(mob/user)
+ var/list/data = get_header_data()
+
+ data["upper"] = upper_text
+ data["lower"] = lower_text
+
+ return data
diff --git a/code/modules/modular_computers/hardware/card_slot.dm b/code/modules/modular_computers/hardware/card_slot.dm
index f2cf4285b64..2e527435c8e 100644
--- a/code/modules/modular_computers/hardware/card_slot.dm
+++ b/code/modules/modular_computers/hardware/card_slot.dm
@@ -7,6 +7,8 @@
device_type = MC_CARD
var/obj/item/card/id/stored_card
+ var/current_identification = null
+ var/current_job = null
///What happens when the ID card is removed (or deleted) from the module, through try_eject() or not.
/obj/item/computer_hardware/card_slot/Exited(atom/movable/gone, direction)
@@ -76,6 +78,10 @@
stored_card = I
to_chat(user, span_notice("You insert \the [I] into \the [expansion_hw ? "secondary":"primary"] [src]."))
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
+ holder.update_appearance()
+
+ current_identification = stored_card.registered_name
+ current_job = stored_card.assignment
var/holder_loc = holder.loc
if(ishuman(holder_loc))
@@ -99,6 +105,11 @@
to_chat(user, span_notice("You remove the card from \the [src]."))
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
+ holder.update_appearance()
+
+ stored_card = null
+ current_identification = null
+ current_job = null
return TRUE
diff --git a/code/modules/modular_computers/hardware/hard_drive.dm b/code/modules/modular_computers/hardware/hard_drive.dm
index 4c1b1602cea..a131ecb1bf5 100644
--- a/code/modules/modular_computers/hardware/hard_drive.dm
+++ b/code/modules/modular_computers/hardware/hard_drive.dm
@@ -9,6 +9,7 @@
var/max_capacity = 128
var/used_capacity = 0
var/list/stored_files = list() // List of stored files on this drive. DO NOT MODIFY DIRECTLY!
+ var/default_installs = TRUE // install the default progs
/obj/item/computer_hardware/hard_drive/on_remove(obj/item/modular_computer/remove_from, mob/user)
remove_from.shutdown_computer()
@@ -130,7 +131,9 @@
/obj/item/computer_hardware/hard_drive/Initialize(mapload)
. = ..()
- install_default_programs()
+
+ if(default_installs)
+ install_default_programs()
/obj/item/computer_hardware/hard_drive/advanced
@@ -167,12 +170,25 @@
w_class = WEIGHT_CLASS_TINY
custom_price = PAYCHECK_MEDIUM * 2
+/obj/item/computer_hardware/hard_drive/small/install_default_programs()
+ . = ..()
+
+ store_file(new /datum/computer_file/program/messenger(src))
+ store_file(new /datum/computer_file/program/notepad(src))
+
// For borg integrated tablets. No downloader.
/obj/item/computer_hardware/hard_drive/small/integrated/install_default_programs()
+ var/datum/computer_file/program/messenger/messenger = new(src)
+ messenger.is_silicon = TRUE
+ store_file(messenger)
+
+/obj/item/computer_hardware/hard_drive/small/integrated/borg/install_default_programs()
store_file(new /datum/computer_file/program/computerconfig(src)) // Computer configuration utility, allows hardware control and displays more info than status bar
store_file(new /datum/computer_file/program/filemanager(src)) // File manager, allows text editor functions and basic file manipulation.
store_file(new /datum/computer_file/program/robotact(src))
-
+ var/datum/computer_file/program/messenger/messenger = new(src)
+ messenger.is_silicon = TRUE
+ store_file(messenger)
// Syndicate variant - very slight better
/obj/item/computer_hardware/hard_drive/small/syndicate
diff --git a/code/modules/modular_computers/hardware/identifier.dm b/code/modules/modular_computers/hardware/identifier.dm
new file mode 100644
index 00000000000..c64b62cdf4a
--- /dev/null
+++ b/code/modules/modular_computers/hardware/identifier.dm
@@ -0,0 +1,13 @@
+/obj/item/computer_hardware/identifier
+ name = "identifier"
+ desc = "Used to automatically update the names of modular devices."
+ power_usage = 0
+ w_class = WEIGHT_CLASS_TINY
+ device_type = MC_IDENTIFY
+ expansion_hw = FALSE
+
+/obj/item/computer_hardware/identifier/proc/UpdateDisplay()
+ var/name = holder.saved_identification
+ var/job = holder.saved_job
+
+ holder.name = "[name] ([job])"
diff --git a/code/modules/modular_computers/hardware/job_disk.dm b/code/modules/modular_computers/hardware/job_disk.dm
new file mode 100644
index 00000000000..0593ea29ee0
--- /dev/null
+++ b/code/modules/modular_computers/hardware/job_disk.dm
@@ -0,0 +1,253 @@
+/obj/item/computer_hardware/hard_drive/role
+ name = "job data disk"
+ desc = "A disk meant to give a worker the needed programs to work."
+ power_usage = 0
+ icon_state = "datadisk6"
+ w_class = WEIGHT_CLASS_TINY
+ critical = FALSE
+ max_capacity = 500
+ device_type = MC_HDD_JOB
+ default_installs = FALSE
+
+ var/disk_flags = 0 // bit flag for the programs
+ var/can_spam = FALSE
+ var/list/bot_access = list()
+
+/obj/item/computer_hardware/hard_drive/role/on_remove(obj/item/modular_computer/remove_from, mob/user)
+ return
+
+/obj/item/computer_hardware/hard_drive/role/Initialize(mapload)
+ . = ..()
+ var/list/progs_to_store = list()
+
+ if(disk_flags & DISK_POWER)
+ progs_to_store += new /datum/computer_file/program/power_monitor(src)
+ progs_to_store += new /datum/computer_file/program/supermatter_monitor(src)
+
+ if(disk_flags & DISK_ATMOS)
+ progs_to_store += new /datum/computer_file/program/atmosscan(src)
+
+ if(disk_flags & DISK_MANIFEST)
+ progs_to_store += new /datum/computer_file/program/crew_manifest(src)
+
+ if(disk_flags & DISK_SEC)
+ progs_to_store += new /datum/computer_file/program/records/security(src)
+
+ if(disk_flags & DISK_JANI)
+ progs_to_store += new /datum/computer_file/program/radar/custodial_locator(src)
+
+ if((disk_flags & DISK_CHEM) || (disk_flags & DISK_MED))
+ var/datum/computer_file/program/phys_scanner/scanner = new(src)
+
+ if(disk_flags & DISK_CHEM)
+ scanner.available_modes += DISK_CHEM
+
+ if(disk_flags & DISK_MED)
+ progs_to_store += new /datum/computer_file/program/records/medical(src)
+ scanner.available_modes += DISK_MED
+
+ progs_to_store += scanner
+
+ if(disk_flags & DISK_ROBOS)
+ var/datum/computer_file/program/robocontrol/robo = new(src)
+ robo.cart_mode = TRUE
+ progs_to_store += robo
+
+ if(disk_flags & DISK_CARGO)
+ progs_to_store += new /datum/computer_file/program/shipping(src)
+
+ if(disk_flags & DISK_SIGNAL)
+ progs_to_store += new /datum/computer_file/program/signaler(src)
+
+ if(disk_flags & DISK_NEWS)
+ progs_to_store += new /datum/computer_file/program/newscaster(src)
+
+ if(disk_flags & DISK_BUDGET)
+ progs_to_store += new /datum/computer_file/program/budgetorders(src)
+
+ if(disk_flags & DISK_STATUS)
+ progs_to_store += new /datum/computer_file/program/status(src)
+
+ for (var/datum/computer_file/program/prog in progs_to_store)
+ prog.usage_flags = PROGRAM_ALL
+ prog.required_access = list()
+ prog.transfer_access = list()
+ store_file(prog)
+
+
+
+/obj/item/computer_hardware/hard_drive/role/proc/CanSpam()
+ return can_spam
+
+// Disk Definitions
+
+/obj/item/computer_hardware/hard_drive/role/engineering
+ name = "Power-ON disk"
+ desc = "Engineers ignoring station power-draw since 2400."
+ icon_state = "datadisk2"
+ disk_flags = DISK_POWER
+
+/obj/item/computer_hardware/hard_drive/role/atmos
+ name = "\improper BreatheDeep disk"
+ icon_state = "datadisk2"
+ disk_flags = DISK_ATMOS | DISK_ROBOS
+ bot_access = list(
+ FLOOR_BOT,
+ FIRE_BOT,
+ )
+
+/obj/item/computer_hardware/hard_drive/role/medical
+ name = "\improper Med-U disk"
+ icon_state = "datadisk7"
+ disk_flags = DISK_MED | DISK_ROBOS
+ bot_access = list(
+ MED_BOT,
+ )
+
+/obj/item/computer_hardware/hard_drive/role/chemistry
+ name = "\improper ChemWhiz disk"
+ icon_state = "datadisk7"
+ disk_flags = DISK_CHEM
+
+/obj/item/computer_hardware/hard_drive/role/security
+ name = "\improper R.O.B.U.S.T. disk"
+ icon_state = "datadisk9"
+ disk_flags = DISK_SEC | DISK_MANIFEST | DISK_ROBOS
+ bot_access = list(
+ SEC_BOT,
+ ADVANCED_SEC_BOT,
+ )
+
+/obj/item/computer_hardware/hard_drive/role/detective
+ name = "\improper D.E.T.E.C.T. disk"
+ icon_state = "datadisk9"
+ disk_flags = DISK_MED | DISK_SEC | DISK_MANIFEST | DISK_ROBOS
+ bot_access = list(
+ SEC_BOT,
+ ADVANCED_SEC_BOT,
+ )
+
+/obj/item/computer_hardware/hard_drive/role/janitor
+ name = "\improper CustodiPRO disk"
+ icon_state = "datadisk5"
+ desc = "The ultimate in clean-room design."
+ disk_flags = DISK_JANI | DISK_ROBOS
+ bot_access = list(
+ CLEAN_BOT,
+ )
+
+/obj/item/computer_hardware/hard_drive/role/lawyer
+ name = "\improper P.R.O.V.E. disk"
+ icon_state = "datadisk9"
+ disk_flags = DISK_SEC
+ can_spam = TRUE
+
+/obj/item/computer_hardware/hard_drive/role/curator
+ name = "\improper Lib-Tweet disk"
+ icon_state = "datadisk2"
+ disk_flags = DISK_NEWS
+
+/obj/item/computer_hardware/hard_drive/role/roboticist
+ name = "\improper B.O.O.P. Remote Control disk"
+ icon_state = "datadisk5"
+ desc = "Packed with heavy duty quad-bot interlink!"
+ disk_flags = DISK_ROBOS
+ bot_access = list(
+ FLOOR_BOT,
+ CLEAN_BOT,
+ MED_BOT,
+ FIRE_BOT,
+ VIBE_BOT,
+ )
+
+/obj/item/computer_hardware/hard_drive/role/signal
+ name = "generic signaler disk"
+ icon_state = "datadisk5"
+ desc = "A data disk with an integrated radio signaler module."
+ disk_flags = DISK_SIGNAL
+
+/obj/item/computer_hardware/hard_drive/role/signal/ordnance
+ name = "\improper Signal Ace 2 disk"
+ icon_state = "datadisk5"
+ desc = "Complete with integrated radio signaler!"
+ disk_flags = DISK_ATMOS | DISK_SIGNAL | DISK_CHEM
+
+/obj/item/computer_hardware/hard_drive/role/quartermaster
+ name = "space parts & space vendors disk"
+ icon_state = "datadisk0"
+ desc = "Perfect for the Quartermaster on the go!"
+ disk_flags = DISK_CARGO | DISK_ROBOS | DISK_BUDGET
+ bot_access = list(
+ MULE_BOT,
+ )
+
+/obj/item/computer_hardware/hard_drive/role/head
+ name = "\improper Easy-Record DELUXE disk"
+ icon_state = "datadisk7"
+ disk_flags = DISK_MANIFEST | DISK_STATUS | DISK_BUDGET
+
+/obj/item/computer_hardware/hard_drive/role/hop
+ name = "\improper HumanResources9001 disk"
+ icon_state = "datadisk7"
+ disk_flags = DISK_MANIFEST | DISK_STATUS | DISK_JANI | DISK_SEC | DISK_NEWS | DISK_CARGO | DISK_ROBOS | DISK_BUDGET
+ bot_access = list(
+ MULE_BOT,
+ CLEAN_BOT,
+ VIBE_BOT,
+ )
+
+/obj/item/computer_hardware/hard_drive/role/hos
+ name = "\improper R.O.B.U.S.T. DELUXE disk"
+ icon_state = "datadisk7"
+ disk_flags = DISK_MANIFEST | DISK_STATUS | DISK_SEC | DISK_ROBOS | DISK_BUDGET
+ bot_access = list(
+ SEC_BOT,
+ ADVANCED_SEC_BOT,
+ )
+
+
+/obj/item/computer_hardware/hard_drive/role/ce
+ name = "\improper Power-On DELUXE disk"
+ icon_state = "datadisk7"
+ disk_flags = DISK_POWER | DISK_ATMOS | DISK_MANIFEST | DISK_STATUS | DISK_ROBOS | DISK_BUDGET
+ bot_access = list(
+ FLOOR_BOT,
+ FIRE_BOT,
+ )
+
+/obj/item/computer_hardware/hard_drive/role/cmo
+ name = "\improper Med-U DELUXE disk"
+ icon_state = "datadisk7"
+ disk_flags = DISK_MANIFEST | DISK_STATUS | DISK_CHEM | DISK_ROBOS | DISK_BUDGET
+ bot_access = list(
+ MED_BOT,
+ )
+
+/obj/item/computer_hardware/hard_drive/role/rd
+ name = "\improper Signal Ace DELUXE disk"
+ icon_state = "rndmajordisk"
+ disk_flags = DISK_ATMOS | DISK_MANIFEST | DISK_STATUS | DISK_CHEM | DISK_ROBOS | DISK_BUDGET | DISK_SIGNAL
+ bot_access = list(
+ FLOOR_BOT,
+ CLEAN_BOT,
+ MED_BOT,
+ FIRE_BOT,
+ VIBE_BOT,
+ )
+
+/obj/item/computer_hardware/hard_drive/role/captain
+ name = "\improper Value-PAK disk"
+ icon_state = "datadisk8"
+ desc = "Now with 350% more value!" //Give the Captain...EVERYTHING! (Except Mime, Clown, and Syndie)
+ disk_flags = ~0
+ can_spam = TRUE
+ bot_access = list(
+ SEC_BOT,
+ ADVANCED_SEC_BOT,
+ MULE_BOT,
+ FLOOR_BOT,
+ CLEAN_BOT,
+ MED_BOT,
+ FIRE_BOT,
+ VIBE_BOT,
+ )
diff --git a/code/modules/modular_computers/hardware/network_card.dm b/code/modules/modular_computers/hardware/network_card.dm
index b0662785e95..f9a8e46a882 100644
--- a/code/modules/modular_computers/hardware/network_card.dm
+++ b/code/modules/modular_computers/hardware/network_card.dm
@@ -88,10 +88,12 @@
if(!modularInterface.borgo)
return FALSE //No borg found
- if(modularInterface.borgo.lockcharge)
- return FALSE //lockdown restricts borg networking
+ var/mob/living/silicon/robot/robo = modularInterface.borgo
+ if(istype(robo))
+ if(robo.lockcharge)
+ return FALSE //lockdown restricts borg networking
- if(!modularInterface.borgo.cell || modularInterface.borgo.cell.charge == 0)
- return FALSE //borg cell dying restricts borg networking
+ if(!robo.cell || robo.cell.charge == 0)
+ return FALSE //borg cell dying restricts borg networking
return ..()
diff --git a/code/modules/modular_computers/hardware/virus_disk.dm b/code/modules/modular_computers/hardware/virus_disk.dm
new file mode 100644
index 00000000000..6a5c923b60d
--- /dev/null
+++ b/code/modules/modular_computers/hardware/virus_disk.dm
@@ -0,0 +1,140 @@
+/obj/item/computer_hardware/hard_drive/role/virus
+ name = "\improper generic virus disk"
+ icon_state = "virusdisk"
+ var/charges = 5
+
+/obj/item/computer_hardware/hard_drive/role/virus/proc/send_virus(obj/item/modular_computer/tablet/target, mob/living/user)
+ return
+
+/obj/item/computer_hardware/hard_drive/role/virus/clown
+ name = "\improper H.O.N.K. disk"
+
+/obj/item/computer_hardware/hard_drive/role/virus/clown/send_virus(obj/item/modular_computer/tablet/target, mob/living/user)
+ if(charges <= 0)
+ to_chat(user, span_notice("ERROR: Out of charges."))
+ return
+
+ if(target)
+ user.show_message(span_notice("Success!"))
+ charges--
+ target.honkamnt = rand(15, 25)
+ else
+ to_chat(user, span_notice("ERROR: Could not find device."))
+
+/obj/item/computer_hardware/hard_drive/role/virus/mime
+ name = "\improper sound of silence disk"
+
+/obj/item/computer_hardware/hard_drive/role/virus/mime/send_virus(obj/item/modular_computer/tablet/target, mob/living/user)
+ if(charges <= 0)
+ to_chat(user, span_notice("ERROR: Out of charges."))
+ return
+
+ if(target)
+ user.show_message(span_notice("Success!"))
+ charges--
+
+ var/obj/item/computer_hardware/hard_drive/drive = target.all_components[MC_HDD]
+
+ for(var/datum/computer_file/program/messenger/app in drive.stored_files)
+ app.ringer_status = FALSE
+ app.ringtone = ""
+ else
+ to_chat(user, span_notice("ERROR: Could not find device."))
+
+/obj/item/computer_hardware/hard_drive/role/virus/deto
+ name = "\improper D.E.T.O.M.A.T.I.X. disk"
+ charges = 6
+
+/obj/item/computer_hardware/hard_drive/role/virus/deto/send_virus(obj/item/modular_computer/tablet/target, mob/living/user)
+ if(charges <= 0)
+ to_chat(user, span_notice("ERROR: Out of charges."))
+ return
+
+ var/difficulty = 0
+ var/obj/item/computer_hardware/hard_drive/role/disk = target.all_components[MC_HDD_JOB]
+
+ if(disk)
+ difficulty += bit_count(disk.disk_flags & (DISK_MED | DISK_SEC | DISK_POWER | DISK_MANIFEST))
+ if(disk.disk_flags & DISK_MANIFEST)
+ difficulty++ //if cartridge has manifest access it has extra snowflake difficulty
+ if(SEND_SIGNAL(target, COMSIG_TABLET_CHECK_DETONATE) & COMPONENT_TABLET_NO_DETONATE || prob(difficulty * 15))
+ user.show_message(span_danger("ERROR: Target could not be bombed."), MSG_VISUAL)
+ charges--
+ return
+
+ var/original_host = holder
+ var/fakename = sanitize_name(tgui_input_text(user, "Enter a name for the rigged message.", "Forge Message", max_length = MAX_NAME_LEN), allow_numbers = TRUE)
+ if(!fakename || holder != original_host || !user.canUseTopic(holder, BE_CLOSE))
+ return
+ var/fakejob = sanitize_name(tgui_input_text(user, "Enter a job for the rigged message.", "Forge Message", max_length = MAX_NAME_LEN), allow_numbers = TRUE)
+ if(!fakejob || holder != original_host || !user.canUseTopic(holder, BE_CLOSE))
+ return
+
+ var/obj/item/computer_hardware/hard_drive/drive = holder.all_components[MC_HDD]
+
+ for(var/datum/computer_file/program/messenger/app in drive.stored_files)
+ if(charges > 0 && app.send_message(user, list(target), rigged = REF(user), fake_name = fakename, fake_job = fakejob))
+ charges--
+ user.show_message(span_notice("Success!"))
+ var/reference = REF(src)
+ ADD_TRAIT(target, TRAIT_PDA_CAN_EXPLODE, reference)
+ ADD_TRAIT(target, TRAIT_PDA_MESSAGE_MENU_RIGGED, reference)
+ addtimer(TRAIT_CALLBACK_REMOVE(target, TRAIT_PDA_MESSAGE_MENU_RIGGED, reference), 10 SECONDS)
+
+/obj/item/computer_hardware/hard_drive/role/virus/frame
+ name = "\improper F.R.A.M.E. disk"
+
+ var/telecrystals = 0
+ var/current_progression = 0
+
+/obj/item/computer_hardware/hard_drive/role/virus/frame/send_virus(obj/item/modular_computer/tablet/target, mob/living/user)
+ if(charges <= 0)
+ to_chat(user, span_notice("ERROR: Out of charges."))
+ return
+
+ if(target)
+ charges--
+ var/lock_code = "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
+ to_chat(user, span_notice("Success! The unlock code to the target is: [lock_code]"))
+ var/datum/component/uplink/hidden_uplink = target.GetComponent(/datum/component/uplink)
+ if(!hidden_uplink)
+ var/datum/mind/target_mind
+ var/list/backup_players = list()
+ for(var/datum/mind/player as anything in get_crewmember_minds())
+ if(player.assigned_role?.title == target.saved_job)
+ backup_players += player
+ if(player.name == target.saved_identification)
+ target_mind = player
+ break
+ if(!target_mind)
+ if(!length(backup_players))
+ target_mind = user.mind
+ else
+ target_mind = pick(backup_players)
+ hidden_uplink = target.AddComponent(/datum/component/uplink, target_mind, enabled = TRUE, starting_tc = telecrystals, has_progression = TRUE)
+ hidden_uplink.uplink_handler.has_objectives = TRUE
+ hidden_uplink.uplink_handler.owner = target_mind
+ hidden_uplink.uplink_handler.can_take_objectives = FALSE
+ hidden_uplink.uplink_handler.progression_points = min(SStraitor.current_global_progression, current_progression)
+ hidden_uplink.uplink_handler.generate_objectives()
+ SStraitor.register_uplink_handler(hidden_uplink.uplink_handler)
+ else
+ hidden_uplink.add_telecrystals(telecrystals)
+ telecrystals = 0
+ hidden_uplink.locked = FALSE
+ hidden_uplink.active = TRUE
+ else
+ to_chat(user, span_notice("ERROR: Could not find device."))
+
+/obj/item/computer_hardware/hard_drive/role/virus/frame/attackby(obj/item/I, mob/user, params)
+ . = ..()
+ if(istype(I, /obj/item/stack/telecrystal))
+ if(!charges)
+ to_chat(user, span_notice("[src] is out of charges, it's refusing to accept [I]."))
+ return
+ var/obj/item/stack/telecrystal/telecrystalStack = I
+ telecrystals += telecrystalStack.amount
+ to_chat(user, span_notice("You slot [telecrystalStack] into [src]. The next time it's used, it will also give telecrystals."))
+ telecrystalStack.use(telecrystalStack.amount)
+
+
diff --git a/code/modules/tgui/states/reverse_contained.dm b/code/modules/tgui/states/reverse_contained.dm
new file mode 100644
index 00000000000..a6d1034a789
--- /dev/null
+++ b/code/modules/tgui/states/reverse_contained.dm
@@ -0,0 +1,18 @@
+/*!
+ * Not copyrighted, but magatsuchi made it.
+ *
+ */
+
+/**
+ * tgui state: reverse_contained_state
+ *
+ *
+ * Checks if src_object is inside of user.
+ */
+
+GLOBAL_DATUM_INIT(reverse_contained_state, /datum/ui_state/reverse_contained_state, new)
+
+/datum/ui_state/reverse_contained_state/can_use_topic(atom/src_object, mob/user)
+ if(!user.contains(src_object))
+ return UI_CLOSE
+ return user.shared_ui_interaction(src_object)
diff --git a/code/modules/uplink/uplink_items/device_tools.dm b/code/modules/uplink/uplink_items/device_tools.dm
index 4c2306397a5..36e6470fde5 100644
--- a/code/modules/uplink/uplink_items/device_tools.dm
+++ b/code/modules/uplink/uplink_items/device_tools.dm
@@ -99,18 +99,18 @@
illegal_tech = FALSE
/datum/uplink_item/device_tools/frame
- name = "F.R.A.M.E. PDA Cartridge"
- desc = "When inserted into a personal digital assistant, this cartridge gives you five PDA viruses which \
- when used cause the targeted PDA to become a new uplink with zero TCs, and immediately become unlocked. \
+ name = "F.R.A.M.E. disk"
+ desc = "When inserted into a tablet, this cartridge gives you five messenger viruses which \
+ when used cause the targeted tablet to become a new uplink with zero TCs, and immediately become unlocked. \
You will receive the unlock code upon activating the virus, and the new uplink may be charged with \
telecrystals normally."
- item = /obj/item/cartridge/virus/frame
+ item = /obj/item/computer_hardware/hard_drive/role/virus/frame
cost = 4
restricted = TRUE
/datum/uplink_item/device_tools/frame/spawn_item(spawn_path, mob/user, datum/uplink_handler/uplink_handler, atom/movable/source)
. = ..()
- var/obj/item/cartridge/virus/frame/target = .
+ var/obj/item/computer_hardware/hard_drive/role/virus/frame/target = .
if(!target)
return
target.current_progression = uplink_handler.progression_points
diff --git a/code/modules/uplink/uplink_items/explosive.dm b/code/modules/uplink/uplink_items/explosive.dm
index 1a44ba94d5b..6eed450dce0 100644
--- a/code/modules/uplink/uplink_items/explosive.dm
+++ b/code/modules/uplink/uplink_items/explosive.dm
@@ -45,12 +45,12 @@
cant_discount = TRUE
/datum/uplink_item/explosives/detomatix
- name = "Detomatix PDA Cartridge"
- desc = "When inserted into a personal digital assistant, this cartridge gives you four opportunities to \
- detonate PDAs of crewmembers who have their message feature enabled. \
+ name = "Detomatix disk"
+ desc = "When inserted into a tablet, this cartridge gives you four opportunities to \
+ detonate tablets of crewmembers who have their message feature enabled. \
The concussive effect from the explosion will knock the recipient out for a short period, and deafen them for longer."
progression_minimum = 30 MINUTES
- item = /obj/item/cartridge/virus/syndicate
+ item = /obj/item/computer_hardware/hard_drive/role/virus/deto
cost = 6
restricted = TRUE
diff --git a/code/modules/vending/assist.dm b/code/modules/vending/assist.dm
index 38ea84ee7db..018577e5837 100644
--- a/code/modules/vending/assist.dm
+++ b/code/modules/vending/assist.dm
@@ -9,7 +9,7 @@
/obj/item/assembly/igniter = 3,
/obj/item/assembly/signaler = 4,
/obj/item/wirecutters = 1,
- /obj/item/cartridge/signal = 4,
+ /obj/item/computer_hardware/hard_drive/role/signal = 4,
/obj/item/stock_parts/matter_bin = 3,
/obj/item/stock_parts/manipulator = 3,
/obj/item/stock_parts/micro_laser = 3,
diff --git a/code/modules/vending/cartridge.dm b/code/modules/vending/cartridge.dm
index 0780210f680..701bfd5eaaf 100644
--- a/code/modules/vending/cartridge.dm
+++ b/code/modules/vending/cartridge.dm
@@ -7,13 +7,14 @@
icon_deny = "cart-deny"
panel_type = "panel6"
products = list(
- /obj/item/cartridge/medical = 10,
- /obj/item/cartridge/engineering = 10,
- /obj/item/cartridge/security = 10,
- /obj/item/cartridge/signal/ordnance = 10,
- /obj/item/pda/heads = 10,
- /obj/item/cartridge/captain = 3,
- /obj/item/cartridge/quartermaster = 10
+ /obj/item/computer_hardware/hard_drive/role/medical = 10,
+ /obj/item/computer_hardware/hard_drive/role/engineering = 10,
+ /obj/item/computer_hardware/hard_drive/role/security = 10,
+ /obj/item/computer_hardware/hard_drive/role/janitor = 10,
+ /obj/item/computer_hardware/hard_drive/role/signal/ordnance = 10,
+ /obj/item/modular_computer/tablet/pda/heads = 10,
+ /obj/item/computer_hardware/hard_drive/role/captain = 3,
+ /obj/item/computer_hardware/hard_drive/role/quartermaster = 10
)
refill_canister = /obj/item/vending_refill/cart
default_price = PAYCHECK_COMMAND
diff --git a/icons/obj/modular_tablet.dmi b/icons/obj/modular_tablet.dmi
index 60d47a72402296f832244e42df659e090d8ed640..14a1005c07523a603aad608f4e77592cbf3f8a77 100644
GIT binary patch
literal 22910
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 ^f+Cwy)yb}5<`&}Zs%9f
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 (!pzT-;=zFl1Otr`R^7
zJEHpM2jpASzE9@g5D497&fFDkb>tqU5e{*U^C73HAVyeXpUpjv(cF
zQnwydR7s#iX9?nLN?kdScnTWN;6_KPZ9m#`Hvgvl0j~=8&zew6JHee;KFU0STKF6p
z1@goF*yBM#aXMG;_Kjc0`fk5^;LHMZ9>@>zM?XIRl#cuBY(wzEc4Rczsy{o9j46=S
Ws)x)hk|zTo@ObR=-dl+eN%{}yrFN?T
diff --git a/icons/obj/module.dmi b/icons/obj/module.dmi
index d70a56695ef14bf5b6db602df5dfd385158e23ab..a9096a91b3b2904c4d444b51c055f3952180d789 100644
GIT binary patch
literal 18794
zcmcG$bySqy+crFegtUNwq@W@yEiH^RNJ$Aui*$E0bV!LvcPp)QH_{=UL)XyE5Cg+}
z7x(>pzV$w9y=y(+x7PdqFgXQzgFrcnR5$G{1$onFy=`j%t`YVKPEdd6z!A{
zR;d~HP>OZ#gh5*Rn=f1+)k~wAl%{k%;s>9)s1JIMSw&P(^b#M!N>UC
zvEKyTerQ`wxYzi1rCeG)g9yd9rS=<|UxnA2QrQNvKlyzn`3!^P?<2THyaN+$m3WMf
z*}dkGwLE5mHnM&H?qf4v0+OSN8P0o`g~y>UWdcq;U0Oo9SKMB3oG)qM8@BS?yijzP
zkI9}M0-?iL0{BZ9xl%;&w`>UnKhYP6RIyk+enX5uw8489k`$tsl;P;7@NI~79muAd{DVA_jAqA
zlL}9lVxrRhOH1VQrklCYWiRZMLuvKlS#eBR$EG3kOGUpA@mH2Ra$DQkES@FL&Z_>#
z4XMb>@_-}g`cWt37Mb#)gsBhB?_h-`jwXM{=ROmj}sEow-n82tQ{6ESXAjC}F%
zi_9256C%IM5q|oqhEDYRzNg=??pLJLtj9yV@{lZ_HG^pMvykALw-V;BA`aL#uc_+j
zaS87`y?@Q_Vl~a5AC@4=Ecd{PZ_n#0CO@`_|ERec()jX-f$YOgIY<{L$eTaeP%3v9QuS-Z2)$OrV;6Ng#;m!0AfZcZ
zO}U{#VZ)-$ZfV`W=^@D-cAJm+kS&bCMZ#8z#D=_CO5?BgG
zhuGo{`2SOZdesdJ+qiyAqd{t+rXh20o*y)Ar!JbyiELSQJe9BS?37@qCVW7MGgob?
zt|t(>leLVjTlOl!Io`>OCDwMAj>%P0P|9v?jh2sp@T1%o=H|es$ua)oB}{dS|KXM*
zv#S+m6aP$ArA5+Cq+hJueF^GB#bmC4m*w@Huh(wXs^5=4d)hu}xt{!*O`MY)zAH^Y
zX{$AEGc0&X{9!L{bjubo$zWrm_riuFnH`x6Woap7;)$mqYFEd>1{pGz5ow3|ewF@U
z2%CA?C5~<@F77))Af&h9xPc2uoY078Po5kXkc_PNaECQbHEea?ySYlgxcZB`eX{Mm
z%qk?5QsJ}tl1|Ve8`=mwSSh7UmN&kz028-gTQFhrC;lYEBuVXct$4(IuLisimkH>M
z^~`kYpw4rkDOfF!DvMrqO06>y&_@-#&2)4)A2t6paTM*bLkokxzrXAG9n=2V!<`8Z
z;);)wL|XH+rGa0S#}}l(Bil(XQ7c(^_o%4ad)`l~eUATlfl%=lDjPkT^eO1&_Z=H{
z?+nJz&(C)l$%;MeNcvVE`0__d$-1+wSXZP8as1b>?U8g_sU#dLF$Asm!wlDYYP<4_
zig=AXgZ->$>WmqD7T&$UnEjw8Kk}C_JMpRYLh@_N7a&~Ns*$VuPTIQmFXjaOG}zAy
zdlTml8{6|v`KUn;p2ERZ3k0iDs+4QZUaFt6GV#-=*7_5iY;2ENWof>_pd}dA4PKUX
z;Xq$WmVzY;)2NDJOM6cRS$@P)yW+@cp^__gA?6mJ>@4QU5qzUcVGGb;UAu-5KI`d9
ztEm^$r8>M0j*S)Wj*i@{R9V>Yc!P41n_VyOFOiW#LJC>i8|U_Rc89JU8WQ(bL%s5?Qr?jAnTNy4yz3cW?HIQ
z&=~zfC$0Y7i-+e~%0yj)hFWfn$>02+iW#Y2iVr2^e-t%7#jzDMhcmO*K|GZfonXxNpLqmEI&Ys<`n-TSM@0nnEZXDNB#x
zec_3Z3>2N_ixy1PGydM4dxX6NcgI2C&39&h?xrx`)g}?JbZnou&m9;xr3`kYk
z_70kk%Al98PVeb*3VBb)^0w^K!j4WP#dFWt!n3f07Wu6xEG;cHR89A2*}|)fOd
z0_DO|MbDRS_6m=JingX4Hr-~yv4;hW=S8rBjOv=2yQ!a_pRYgeB)B^MX?3agfXcw*
zv8$`AMsqd3|Haq@WtPY(jX_p!+SyxfC;#`1jr)__#9}PC&DC